LCOV - code coverage report
Current view: top level - src/45_geomoptim - m_lbfgs.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 66.8 % 223 149
Test Date: 2026-11-11 11:17:02 Functions: 75.0 % 8 6
Branches: 50.0 % 236 118

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_lbfgs
       2                 :             : !! NAME
       3                 :             : !!  m_lbfgs
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  This module provides several routines for the application of a
       7                 :             : !!  Limited-memory Broyden-Fletcher-Goldfarb-Shanno (LBFGS) minimization algorithm.
       8                 :             : !!  The working routines were based on the original implementation of J. Nocera available on netlib.org
       9                 :             : !!  They have been reshaped and translated into modern fortran here.
      10                 :             : !!
      11                 :             : !! COPYRIGHT
      12                 :             : !! Copyright (C) 2012-2026 ABINIT group (FB)
      13                 :             : !! This file is distributed under the terms of the
      14                 :             : !! GNU General Public License, see ~abinit/COPYING
      15                 :             : !! or http://www.gnu.org/copyleft/gpl.txt .
      16                 :             : !!
      17                 :             : !! SOURCE
      18                 :             : 
      19                 :             : #if defined HAVE_CONFIG_H
      20                 :             : #include "config.h"
      21                 :             : #endif
      22                 :             : 
      23                 :             : #include "abi_common.h"
      24                 :             : 
      25                 :             : module m_lbfgs
      26                 :             : 
      27                 :             :  use defs_basis
      28                 :             :  use m_abicore
      29                 :             : 
      30                 :             :  implicit none
      31                 :             : 
      32                 :             : type,public :: lbfgs_internal
      33                 :             :  integer              :: lbfgs_status
      34                 :             :  integer              :: ndim
      35                 :             :  integer              :: history_record
      36                 :             :  integer              :: iter
      37                 :             :  real(dp)             :: gtol
      38                 :             :  real(dp),allocatable :: diag(:)
      39                 :             :  real(dp),allocatable :: work(:)
      40                 :             :  real(dp)             :: line_stp
      41                 :             :  real(dp)             :: line_stpmin
      42                 :             :  real(dp)             :: line_stpmax
      43                 :             :  integer              :: line_info
      44                 :             :  integer              :: line_infoc
      45                 :             :  integer              :: line_nfev
      46                 :             :  real(dp)             :: line_dginit
      47                 :             :  real(dp)             :: line_finit
      48                 :             :  real(dp)             :: line_stx
      49                 :             :  real(dp)             :: line_fx
      50                 :             :  real(dp)             :: line_dgx
      51                 :             :  real(dp)             :: line_sty
      52                 :             :  real(dp)             :: line_fy
      53                 :             :  real(dp)             :: line_dgy
      54                 :             :  real(dp)             :: line_stmin
      55                 :             :  real(dp)             :: line_stmax
      56                 :             :  logical              :: line_bracket
      57                 :             :  logical              :: line_stage1
      58                 :             : end type lbfgs_internal
      59                 :             : 
      60                 :             : type(lbfgs_internal),save,public :: lbfgs_plan
      61                 :             : 
      62                 :             : !!***
      63                 :             : 
      64                 :             : contains
      65                 :             : 
      66                 :             : !----------------------------------------------------------------------
      67                 :             : 
      68                 :             : !!****f* m_lbfgs/lbfgs_init
      69                 :             : !! NAME
      70                 :             : !! lbfgs_init
      71                 :             : !!
      72                 :             : !! FUNCTION
      73                 :             : !!   Initialize the internal object lbfgs_internal for LBFGS minimization
      74                 :             : !!
      75                 :             : !! INPUTS
      76                 :             : !!
      77                 :             : !! OUTPUT
      78                 :             : !!
      79                 :             : !! SIDE EFFECTS
      80                 :             : !!
      81                 :             : !! SOURCE
      82                 :             : 
      83                 :           1 : subroutine lbfgs_init(ndim,history_record,diag_guess)
      84                 :             : 
      85                 :             : integer,intent(in)   :: ndim
      86                 :             : integer,intent(in)   :: history_record
      87                 :             : real(dp),intent(in)  :: diag_guess(ndim)
      88                 :             : 
      89                 :             : integer :: nwork
      90                 :             : 
      91                 :           1 :  lbfgs_plan%lbfgs_status = 0
      92                 :           1 :  lbfgs_plan%iter   = 0
      93                 :           1 :  lbfgs_plan%ndim = ndim
      94                 :           1 :  lbfgs_plan%history_record = history_record
      95   [ -  +  +  -  :           3 :  ABI_MALLOC(lbfgs_plan%diag,(ndim))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
      96                 :             : 
      97                 :           1 :  nwork = ndim * ( 2 * history_record + 1 ) + 2 * history_record
      98   [ -  +  +  -  :           3 :  ABI_MALLOC(lbfgs_plan%work,(nwork))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
      99                 :             : 
     100                 :           1 :  lbfgs_plan%gtol = 0.9
     101                 :           1 :  lbfgs_plan%line_stpmin = 1.0e-20
     102                 :           1 :  lbfgs_plan%line_stpmax = 1.0e+20
     103                 :           1 :  lbfgs_plan%line_stp    = 1.0
     104                 :             : 
     105         [ +  + ]:          28 :  lbfgs_plan%diag(:) = diag_guess(:)
     106                 :             : 
     107                 :           1 : end subroutine lbfgs_init
     108                 :             : !!***
     109                 :             : 
     110                 :             : 
     111                 :             : !----------------------------------------------------------------------
     112                 :             : 
     113                 :             : !!****f* m_lbfgs/lbfgs_destroy
     114                 :             : !! NAME
     115                 :             : !! lbfgs_destroy
     116                 :             : !!
     117                 :             : !! FUNCTION
     118                 :             : !!   Free the memory of the internal object lbfgs_internal for LBFGS minimization
     119                 :             : !!
     120                 :             : !! INPUTS
     121                 :             : !!
     122                 :             : !! OUTPUT
     123                 :             : !!
     124                 :             : !! SOURCE
     125                 :             : 
     126                 :           1 : subroutine lbfgs_destroy()
     127                 :             : 
     128         [ +  - ]:           1 :  ABI_SFREE(lbfgs_plan%work)
     129         [ +  - ]:           1 :  ABI_SFREE(lbfgs_plan%diag)
     130                 :             : 
     131                 :           1 : end subroutine lbfgs_destroy
     132                 :             : !!***
     133                 :             : 
     134                 :             : !----------------------------------------------------------------------
     135                 :             : 
     136                 :             : !!****f* m_lbfgs/lbfgs_execute
     137                 :             : !! NAME
     138                 :             : !! lbfgs_execute
     139                 :             : !!
     140                 :             : !! FUNCTION
     141                 :             : !!   Perform one-step of LBFGS minimization
     142                 :             : !!   all the internal information are stored in the lbfgs_internal object
     143                 :             : !!
     144                 :             : !! INPUTS
     145                 :             : !!   x: input and output position vector (atomic reduced coordinates + cell parameters)
     146                 :             : !!   f: total energy
     147                 :             : !!   gradf: gradient of the total energy (=negative forces)
     148                 :             : !!
     149                 :             : !! OUTPUT
     150                 :             : !!
     151                 :             : !! SOURCE
     152                 :             : 
     153                 :          11 : function lbfgs_execute(x,f,gradf)
     154                 :             : 
     155                 :             : real(dp),intent(inout) :: x(lbfgs_plan%ndim)
     156                 :             : real(dp),intent(in)    :: f
     157                 :             : real(dp),intent(in)    :: gradf(lbfgs_plan%ndim)
     158                 :             : integer                :: lbfgs_execute
     159                 :             : 
     160                 :             :  call lbfgs(lbfgs_plan%ndim, lbfgs_plan%history_record, x, f, gradf, lbfgs_plan%diag, lbfgs_plan%work, lbfgs_plan%lbfgs_status, &
     161                 :             :        lbfgs_plan%gtol, lbfgs_plan%line_stpmin, lbfgs_plan%line_stpmax, lbfgs_plan%line_stp, lbfgs_plan%iter,                   &
     162                 :             :        lbfgs_plan%line_info, lbfgs_plan%line_nfev,                                                   &
     163                 :             :        lbfgs_plan%line_dginit, lbfgs_plan%line_finit,                                                &
     164                 :             :        lbfgs_plan%line_stx,  lbfgs_plan%line_fx,  lbfgs_plan%line_dgx,                               &
     165                 :             :        lbfgs_plan%line_sty,  lbfgs_plan%line_fy,  lbfgs_plan%line_dgy,                               &
     166                 :             :        lbfgs_plan%line_stmin,  lbfgs_plan%line_stmax,                                                &
     167                 :          11 :        lbfgs_plan%line_bracket, lbfgs_plan%line_stage1, lbfgs_plan%line_infoc)
     168                 :             : 
     169                 :             : 
     170                 :             : !lbfgs_execute = lbfgs_plan%lbfgs_status
     171                 :          11 :  lbfgs_execute = lbfgs_plan%line_info
     172                 :             : 
     173                 :          11 : end function lbfgs_execute
     174                 :             : !!***
     175                 :             : 
     176                 :             : 
     177                 :             : !----------------------------------------------------------------------
     178                 :             : 
     179                 :             : !!****f* m_lbfgs/lbfgs
     180                 :             : !! NAME
     181                 :             : !! lbfgs
     182                 :             : !!
     183                 :             : !! FUNCTION
     184                 :             : !!   Perform the LBFGS step
     185                 :             : !!   Fortran90 rewritting of the original subroutine by J. Nocera
     186                 :             : !!
     187                 :             : !! INPUTS
     188                 :             : !!
     189                 :             : !! OUTPUT
     190                 :             : !!
     191                 :             : !! SIDE EFFECTS
     192                 :             : !!
     193                 :             : !! SOURCE
     194                 :             : 
     195                 :          11 : subroutine lbfgs(N,M,X,F,G,DIAG,W,IFLAG,      &
     196                 :             :                  GTOL,STPMIN,STPMAX,STP,ITER, &
     197                 :             :                  INFO, NFEV,                  &
     198                 :             :                  LINE_DGINIT,LINE_FINIT,      &
     199                 :             :                  LINE_STX,LINE_FX,LINE_DGX,   &
     200                 :             :                  LINE_STY,LINE_FY,LINE_DGY,   &
     201                 :             :                  LINE_STMIN,LINE_STMAX,       &
     202                 :             :                  LINE_BRACKT,LINE_STAGE1,LINE_INFOC)
     203                 :             : 
     204                 :             : !Arguments ------------------------------------
     205                 :             : !scalars
     206                 :             :  integer,intent(inout) :: LINE_INFOC
     207                 :             :  integer,intent(inout)  :: ITER,IFLAG,INFO,NFEV
     208                 :             :  integer,intent(in)     :: N,M
     209                 :             :  real(dp),intent(inout) :: GTOL
     210                 :             :  real(dp),intent(in)    :: STPMIN,STPMAX
     211                 :             :  real(dp),intent(inout) :: STP
     212                 :             :  real(dp),intent(in)    :: F
     213                 :             :  real(dp),intent(inout) :: LINE_DGINIT,LINE_FINIT
     214                 :             :  real(dp),intent(inout) :: LINE_STX,LINE_FX,LINE_DGX
     215                 :             :  real(dp),intent(inout) :: LINE_STY,LINE_FY,LINE_DGY
     216                 :             :  real(dp),intent(inout) :: LINE_STMIN,LINE_STMAX
     217                 :             :  logical,intent(inout)  :: LINE_BRACKT,LINE_STAGE1
     218                 :             : !arrays
     219                 :             :  real(dp),intent(inout) :: X(N),DIAG(N),W(N*(2*M+1)+2*M)
     220                 :             :  real(dp),intent(in)    :: G(N)
     221                 :             : 
     222                 :             : !Local variables-------------------------------
     223                 :             : !scalars
     224                 :             :  real(dp) :: FTOL,YS,YY,SQ,YR,BETA
     225                 :             :  integer :: POINT,ISPT,IYPT,MAXFEV, &
     226                 :             :          BOUND,NPT,CP,I,INMC,IYCN,ISCN
     227                 :             : !***************************************************************************
     228                 :             : 
     229                 :             : 
     230                 :             : !
     231                 :             : ! Initialize
     232                 :             : !-----------
     233                 :             : 
     234                 :             : ! Parameters for line search routine
     235                 :          11 :  FTOL = 1.0D-4
     236                 :          11 :  MAXFEV = 20
     237                 :             : 
     238                 :          11 :  ISPT = N + 2 * M
     239                 :          11 :  IYPT = ISPT + N * M
     240                 :          11 :  POINT = MAX( 0 , MOD(ITER-1,M) )
     241                 :          11 :  NPT = POINT * N
     242                 :          11 :  ITER  = ITER + 1
     243                 :          11 :  BOUND = MIN( ITER-1 , M)
     244                 :             : 
     245                 :             : 
     246                 :             :  !
     247                 :             :  ! Entering the subroutine with a new position and gradient
     248                 :             :  ! or entering for the first time ever
     249         [ +  + ]:          11 :  if( IFLAG /= 1 ) then
     250         [ +  + ]:          28 :    W(ISPT+1:ISPT+N) = -G(1:N) * DIAG(1:N)
     251                 :             : 
     252                 :             :  else
     253                 :             : 
     254                 :             :    call MCSRCH(N,X,F,G,W(ISPT+POINT*N+1),STP,FTOL,MAXFEV,INFO,NFEV, &
     255                 :             :                DIAG,GTOL,STPMIN,STPMAX,LINE_DGINIT,LINE_FINIT, &
     256                 :             :                LINE_STX,LINE_FX,LINE_DGX, &
     257                 :             :                LINE_STY,LINE_FY,LINE_DGY, &
     258                 :             :                LINE_STMIN,LINE_STMAX, &
     259                 :          10 :                LINE_BRACKT,LINE_STAGE1,LINE_INFOC)
     260                 :             :    !
     261                 :             :    ! Compute the new step and gradient change
     262                 :             :    !
     263                 :          10 :    NPT = POINT * N
     264         [ +  + ]:         280 :    W(ISPT+NPT+1:ISPT+NPT+N) = STP * W(ISPT+NPT+1:ISPT+NPT+N)
     265   [ +  -  +  +  :         550 :    W(IYPT+NPT+1:IYPT+NPT+N) = G(1:N) - W(1:N)
                   +  + ]
     266                 :             : 
     267         [ +  + ]:         280 :    YS = DOT_PRODUCT( W(IYPT+NPT+1:IYPT+NPT+N) , W(ISPT+NPT+1:ISPT+NPT+N) )
     268         [ +  + ]:         280 :    YY = DOT_PRODUCT( W(IYPT+NPT+1:IYPT+NPT+N) , W(IYPT+NPT+1:IYPT+NPT+N) )
     269         [ +  + ]:         280 :    DIAG(1:N)= YS / YY
     270                 :             : 
     271                 :             : !
     272                 :             : !  COMPUTE -H*G USING THE FORMULA GIVEN IN: Nocedal, J. 1980,
     273                 :             : !  "Updating quasi-Newton matrices with limited storage",
     274                 :             : !  Mathematics of Computation, Vol.24, No.151, pp. 773-782.
     275                 :             : !  ---------------------------------------------------------
     276                 :             : !
     277                 :          10 :    POINT = MODULO(ITER - 1,M)
     278                 :          10 :    CP = POINT
     279         [ +  + ]:          10 :    if (POINT == 0) CP = M
     280                 :             : 
     281                 :          10 :    W(N+CP) = one / YS
     282         [ +  + ]:         280 :    W(1:N)  = -G(1:N)
     283                 :             : 
     284                 :             :    CP = POINT
     285         [ +  + ]:          50 :    do I= 1,BOUND
     286                 :          40 :      CP = CP - 1
     287         [ +  + ]:          40 :      if (CP ==  -1) CP = M - 1
     288         [ +  + ]:        1120 :      SQ = DOT_PRODUCT(W(ISPT+CP*N+1:ISPT+CP*N+N),W(1:N))
     289                 :          40 :      INMC = N + M + CP + 1
     290                 :          40 :      IYCN = IYPT + CP * N
     291                 :          40 :      W(INMC)= W(N+CP+1) * SQ
     292         [ +  + ]:        1130 :      W(1:N) = W(1:N) - W(INMC) * W(IYCN+1:IYCN+N)
     293                 :             :    enddo
     294                 :             : 
     295         [ +  + ]:         280 :    W(1:N) = DIAG(1:N) * W(1:N)
     296                 :             : 
     297         [ +  + ]:          50 :    do I=1,BOUND
     298         [ +  + ]:        1120 :      YR = DOT_PRODUCT(W(IYPT+CP*N+1:IYPT+CP*N+N),W(1:N))
     299                 :          40 :      BETA = W(N+CP+1) * YR
     300                 :          40 :      INMC = N + M + CP + 1
     301                 :          40 :      BETA = W(INMC) - BETA
     302                 :          40 :      ISCN = ISPT + CP * N
     303         [ +  + ]:        1120 :      W(1:N) = W(1:N) + BETA * W(ISCN+1:ISCN+N)
     304                 :          40 :      CP = CP + 1
     305         [ +  + ]:          50 :      if (CP == M) CP = 0
     306                 :             :    enddo
     307                 :             : 
     308                 :             : !
     309                 :             : !  STORE THE NEW SEARCH DIRECTION
     310   [ +  +  +  + ]:         550 :    W(ISPT+POINT*N+1:ISPT+POINT*N+N) = W(1:N)
     311                 :             : 
     312                 :             :  endif
     313                 :             : 
     314                 :             : !
     315                 :             : ! Obtain the one-dimensional minimizer of the function
     316                 :             : ! by using the line search routine mcsrch
     317                 :             : !----------------------------------------------------
     318                 :          11 :  NFEV = 0
     319                 :          11 :  STP = one
     320         [ +  + ]:         308 :  W(1:N) = G(1:N)
     321                 :             : 
     322                 :          11 :  INFO  = 0
     323                 :             : 
     324                 :             :  call MCSRCH(N,X,F,G,W(ISPT+POINT*N+1),STP,FTOL,MAXFEV,INFO,NFEV, &
     325                 :             :              DIAG,GTOL,STPMIN,STPMAX,LINE_DGINIT,LINE_FINIT, &
     326                 :             :              LINE_STX,LINE_FX,LINE_DGX, &
     327                 :             :              LINE_STY,LINE_FY,LINE_DGY, &
     328                 :             :              LINE_STMIN,LINE_STMAX, &
     329                 :          11 :              LINE_BRACKT,LINE_STAGE1,LINE_INFOC)
     330                 :             : 
     331         [ +  - ]:          11 :  if (INFO  ==  -1) then
     332                 :          11 :    IFLAG = 1
     333                 :          11 :    return
     334                 :             :  else
     335                 :           0 :    IFLAG = -1
     336                 :           0 :    return
     337                 :             :  endif
     338                 :             : 
     339                 :             : end subroutine lbfgs
     340                 :             : !!***
     341                 :             : 
     342                 :             : !----------------------------------------------------------------------
     343                 :             : 
     344                 :             : !!****f* m_lbfgs/mcsrch
     345                 :             : !! NAME
     346                 :             : !! mcsrch
     347                 :             : !!
     348                 :             : !! FUNCTION
     349                 :             : !!   Perform the line minimization step
     350                 :             : !!   Fortran90 rewritting of the original subroutine by J. Nocera
     351                 :             : !!
     352                 :             : !! INPUTS
     353                 :             : !!
     354                 :             : !! OUTPUT
     355                 :             : !!
     356                 :             : !! SIDE EFFECTS
     357                 :             : !!
     358                 :             : !! SOURCE
     359                 :             : 
     360                 :          21 : subroutine mcsrch(N,X,F,G,S,STP,FTOL,MAXFEV,INFO,NFEV,WA, &
     361                 :             :                   GTOL,STPMIN,STPMAX,DGINIT,FINIT, &
     362                 :             :                   STX,FX,DGX,STY,FY,DGY,STMIN,STMAX, &
     363                 :             :                   BRACKT,STAGE1,INFOC)
     364                 :             : 
     365                 :             : !Arguments ------------------------------------
     366                 :             : !scalars
     367                 :             :  integer,intent(in)     :: N,MAXFEV
     368                 :             :  integer,intent(inout)  :: INFO,NFEV
     369                 :             :  integer,intent(inout)  :: INFOC
     370                 :             :  real(dp),intent(in)    :: GTOL,STPMIN,STPMAX
     371                 :             :  real(dp),intent(in)    :: F,FTOL
     372                 :             :  real(dp),intent(inout) :: STP,DGINIT,FINIT
     373                 :             :  real(dp),intent(inout) :: STX,FX,DGX
     374                 :             :  real(dp),intent(inout) :: STY,FY,DGY
     375                 :             :  real(dp),intent(inout) :: STMIN,STMAX
     376                 :             :  logical,intent(inout) :: BRACKT,STAGE1
     377                 :             : !arrays
     378                 :             :  real(dp),intent(in)     :: G(N)
     379                 :             :  real(dp),intent(inout)  :: X(N),S(N),WA(N)
     380                 :             : 
     381                 :             : !Local variables-------------------------------
     382                 :             : !scalars
     383                 :             :  real(dp),parameter :: XTOL=1.0e-17_dp
     384                 :             :  real(dp),parameter :: P5     = 0.50_dp
     385                 :             :  real(dp),parameter :: P66    = 0.66_dp
     386                 :             :  real(dp),parameter :: XTRAPF = 4.00_dp
     387                 :             :  real(dp) :: DG,DGM,DGTEST,DGXM,DGYM, &
     388                 :             :         FTEST1,FM,FXM,FYM,WIDTH,WIDTH1
     389                 :             : !***************************************************************************
     390                 :             : 
     391                 :          21 :  DGTEST = FTOL * DGINIT
     392                 :          21 :  WIDTH = STPMAX - STPMIN
     393                 :          21 :  WIDTH1 = WIDTH / P5
     394                 :             : 
     395                 :             :  ! Is it a first entry (info == 0)
     396                 :             :  ! or a second entry (info == -1)?
     397         [ +  + ]:          21 :  if( INFO == -1 ) then
     398                 :             : 
     399                 :             :    ! Reset INFO
     400                 :          10 :    INFO = 0
     401                 :             : 
     402                 :          10 :    NFEV = NFEV + 1
     403         [ +  + ]:         280 :    DG = SUM( G(:) * S(:) )
     404                 :          10 :    FTEST1 = FINIT + STP * DGTEST
     405                 :             : !
     406                 :             : !  TEST FOR CONVERGENCE.
     407                 :             : !
     408                 :             :    if ((BRACKT .AND. (STP <= STMIN .OR. STP >= STMAX)) &
     409   [ -  +  -  -  :          10 :       .OR. INFOC  ==  0) INFO = 6
             -  -  -  + ]
     410                 :             :    if (STP  ==  STPMAX .AND. &
     411   [ -  +  -  -  :          10 :        F <= FTEST1 .AND. DG <= DGTEST) INFO = 5
                   -  - ]
     412   [ -  +  -  -  :          10 :    if (STP  ==  STPMIN .AND.  &
                   -  - ]
     413                 :           0 :        (F > FTEST1 .OR. DG >= DGTEST)) INFO = 4
     414         [ -  + ]:          10 :    if (NFEV >= MAXFEV) INFO = 3
     415   [ -  +  -  - ]:          10 :    if (BRACKT .AND. STMAX-STMIN <= XTOL*STMAX) INFO = 2
     416   [ +  +  +  - ]:          10 :    if (F <= FTEST1 .AND. ABS(DG) <= GTOL*(-DGINIT)) INFO = 1
     417                 :             : !
     418                 :             : !  CHECK FOR TERMINATION.
     419                 :             : !
     420         [ +  + ]:          10 :    if (INFO /= 0) return
     421                 :             : !
     422                 :             : !  IN THE FIRST STAGE WE SEEK A STEP FOR WHICH THE MODIFIED
     423                 :             : !  FUNCTION HAS A NONPOSITIVE VALUE AND NONNEGATIVE DERIVATIVE.
     424                 :             : !
     425   [ +  -  -  +  :           1 :    if (STAGE1 .AND. F <= FTEST1 .AND. &
                   -  - ]
     426                 :           0 :        DG >= MIN(FTOL,GTOL)*DGINIT) STAGE1 = .FALSE.
     427                 :             : !
     428                 :             : !  A MODIFIED FUNCTION IS USED TO PREDICT THE STEP ONLY IF
     429                 :             : !  WE HAVE NOT OBTAINED A STEP FOR WHICH THE MODIFIED
     430                 :             : !  FUNCTION HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE
     431                 :             : !  DERIVATIVE, AND IF A LOWER FUNCTION VALUE HAS BEEN
     432                 :             : !  OBTAINED BUT THE DECREASE IS NOT SUFFICIENT.
     433                 :             : !
     434   [ +  -  -  +  :           1 :    if (STAGE1 .AND. F <= FX .AND. F > FTEST1) then
                   -  - ]
     435                 :             : !
     436                 :             : !     DEFINE THE MODIFIED FUNCTION AND DERIVATIVE VALUES.
     437                 :             : !
     438                 :           0 :       FM = F - STP * DGTEST
     439                 :           0 :       FXM = FX - STX * DGTEST
     440                 :           0 :       FYM = FY - STY * DGTEST
     441                 :           0 :       DGM = DG - DGTEST
     442                 :           0 :       DGXM = DGX - DGTEST
     443                 :           0 :       DGYM = DGY - DGTEST
     444                 :             : !
     445                 :             : !     CALL MCSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY
     446                 :             : !     AND TO COMPUTE THE NEW STEP.
     447                 :             : !
     448                 :           0 :       call mcstep(STX,FXM,DGXM,STY,FYM,DGYM,STP,FM,DGM,BRACKT,STMIN,STMAX,INFOC)
     449                 :             : !
     450                 :             : !     RESET THE FUNCTION AND GRADIENT VALUES FOR F.
     451                 :             : !
     452                 :           0 :       FX = FXM + STX * DGTEST
     453                 :           0 :       FY = FYM + STY * DGTEST
     454                 :           0 :       DGX = DGXM + DGTEST
     455                 :           0 :       DGY = DGYM + DGTEST
     456                 :             :    else
     457                 :             : !
     458                 :             : !     CALL MCSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY
     459                 :             : !     AND TO COMPUTE THE NEW STEP.
     460                 :             : !
     461                 :           1 :       call mcstep(STX,FX,DGX,STY,FY,DGY,STP,F,DG,BRACKT,STMIN,STMAX,INFOC)
     462                 :             :    endif
     463                 :             : !
     464                 :             : !  FORCE A SUFFICIENT DECREASE IN THE SIZE OF THE
     465                 :             : !  INTERVAL OF UNCERTAINTY.
     466                 :             : !
     467         [ +  - ]:           1 :    if (BRACKT) then
     468         [ -  + ]:           1 :       if (ABS(STY-STX) >= P66 * WIDTH1) STP = STX + P5 * (STY - STX)
     469                 :          12 :       WIDTH1 = WIDTH
     470                 :          12 :       WIDTH = ABS(STY-STX)
     471                 :             :    endif
     472                 :             : 
     473                 :             :  else
     474                 :             : 
     475                 :          11 :    INFOC = 1
     476                 :             : !
     477                 :             : !  CHECK THE INPUT PARAMETERS FOR ERRORS.
     478                 :             : !
     479                 :             :    if ( STP <= zero .OR. FTOL < zero .OR.  &
     480                 :             :        GTOL < zero .OR. XTOL < zero .OR. STPMIN < zero &
     481   [ +  -  +  -  :          11 :        .OR. STPMAX < STPMIN ) return
          +  -  +  -  +  
                      - ]
     482                 :             : !
     483                 :             : !  COMPUTE THE INITIAL GRADIENT IN THE SEARCH DIRECTION
     484                 :             : !  AND CHECK THAT S IS A DESCENT DIRECTION.
     485                 :             : !
     486         [ +  + ]:         308 :    DGINIT = DOT_PRODUCT( G , S )
     487                 :             : 
     488         [ +  - ]:          11 :    if (DGINIT > zero) then
     489                 :             :      return
     490                 :             :    endif
     491                 :             : !
     492                 :             : !  INITIALIZE LOCAL VARIABLES.
     493                 :             : !
     494                 :             : 
     495                 :          11 :    BRACKT = .FALSE.
     496                 :          11 :    STAGE1 = .TRUE.
     497                 :          11 :    NFEV = 0
     498                 :          11 :    FINIT = F
     499                 :          11 :    DGTEST = FTOL * DGINIT
     500         [ +  + ]:         308 :    WA(:) = X(:)
     501                 :             : 
     502                 :             : 
     503                 :             : !
     504                 :             : !  THE VARIABLES STX, FX, DGX CONTAIN THE VALUES OF THE STEP,
     505                 :             : !  FUNCTION, AND DIRECTIONAL DERIVATIVE AT THE BEST STEP.
     506                 :             : !  THE VARIABLES STY, FY, DGY CONTAIN THE VALUE OF THE STEP,
     507                 :             : !  FUNCTION, AND DERIVATIVE AT THE OTHER ENDPOINT OF
     508                 :             : !  THE INTERVAL OF UNCERTAINTY.
     509                 :             : !  THE VARIABLES STP, F, DG CONTAIN THE VALUES OF THE STEP,
     510                 :             : !  FUNCTION, AND DERIVATIVE AT THE CURRENT STEP.
     511                 :             : !
     512                 :          11 :    STX = zero
     513                 :          11 :    FX = FINIT
     514                 :          11 :    DGX = DGINIT
     515                 :          11 :    STY = zero
     516                 :          11 :    FY = FINIT
     517                 :          11 :    DGY = DGINIT
     518                 :             :  endif
     519                 :             : 
     520                 :             : !
     521                 :             : !SET THE MINIMUM AND MAXIMUM STEPS TO CORRESPOND
     522                 :             : !TO THE PRESENT INTERVAL OF UNCERTAINTY.
     523                 :             : !
     524         [ +  + ]:          12 :  if (BRACKT) then
     525                 :           1 :     STMIN = MIN(STX,STY)
     526                 :           1 :     STMAX = MAX(STX,STY)
     527                 :             :  else
     528                 :          11 :     STMIN = STX
     529                 :          11 :     STMAX = STP + XTRAPF*(STP - STX)
     530                 :             :  endif
     531                 :             : !
     532                 :             : !FORCE THE STEP TO BE WITHIN THE BOUNDS STPMAX AND STPMIN.
     533                 :             : !
     534                 :          12 :  STP = MAX(STPMIN,STP)
     535                 :          12 :  STP = MIN(STP,STPMAX)
     536                 :             : !
     537                 :             : !IF AN UNUSUAL TERMINATION IS TO OCCUR THEN LET
     538                 :             : !STP BE THE LOWEST POINT OBTAINED SO FAR.
     539                 :             : !
     540                 :             :  if ((BRACKT .AND. (STP <= STMIN .OR. STP >= STMAX)) &
     541                 :             :     .OR. NFEV >= MAXFEV-1 .OR. INFOC  ==  0 &
     542   [ +  +  +  -  :          12 :     .OR. (BRACKT .AND. STMAX-STMIN <= XTOL*STMAX)) STP = STX
          +  -  +  -  +  
             -  +  +  -  
                      + ]
     543                 :             : 
     544                 :             : !
     545                 :             : !Evaluate the function and gradient at STP
     546                 :             : !and compute the directional derivative.
     547                 :             : !We return to main program to obtain F and G.
     548                 :             : !
     549         [ +  + ]:         336 :  X(:) = WA(:) + STP * S(:)
     550                 :             : 
     551                 :          12 :  INFO = -1
     552                 :             : 
     553                 :             : end subroutine mcsrch
     554                 :             : !!***
     555                 :             : 
     556                 :             : !----------------------------------------------------------------------
     557                 :             : 
     558                 :             : !!****f* m_lbfgs/mcstep
     559                 :             : !! NAME
     560                 :             : !! mcstep
     561                 :             : !!
     562                 :             : !! FUNCTION
     563                 :             : !!   Perform the step choice in line minimization
     564                 :             : !!   Fortran90 rewritting of the original subroutine by J. Nocera
     565                 :             : !!
     566                 :             : !! INPUTS
     567                 :             : !!
     568                 :             : !! OUTPUT
     569                 :             : !!
     570                 :             : !! SIDE EFFECTS
     571                 :             : !!
     572                 :             : !! SOURCE
     573                 :             : 
     574                 :           1 : subroutine mcstep(STX,FX,DX,STY,FY,DY,STP,FP,DG,BRACKT,STPMIN,STPMAX,INFO)
     575                 :             : 
     576                 :             : !Arguments ------------------------------------
     577                 :             : !scalars
     578                 :             :  integer,intent(inout)  :: INFO
     579                 :             :  real(dp),intent(in)     :: FP
     580                 :             :  real(dp),intent(inout)  :: STX,FX,DX,STY,FY,DY,STP,DG,STPMIN,STPMAX
     581                 :             :  logical,intent(inout) :: BRACKT
     582                 :             : 
     583                 :             : !Local variables-------------------------------
     584                 :             : !scalars
     585                 :             :  logical BOUND
     586                 :             :  real(dp) GAM,P,Q,R,S,SGND,STPC,STPF,STPQ,THETA
     587                 :             : !***************************************************************************
     588                 :             : 
     589                 :           1 :  INFO = 0
     590                 :             : !
     591                 :             : ! CHECK THE INPUT PARAMETERS FOR ERRORS.
     592                 :             : !
     593                 :             :  IF ((BRACKT .AND. (STP <= MIN(STX,STY) .OR. &
     594                 :             :      STP >= MAX(STX,STY))) .OR.  &
     595   [ -  +  -  -  :           1 :      DX*(STP-STX) >= 0.0 .OR. STPMAX < STPMIN) RETURN
          -  -  +  -  +  
                      - ]
     596                 :             : !
     597                 :             : ! Determine if the derivatives have opposite sign
     598                 :             : !
     599                 :           1 :  SGND = DG * ( DX / ABS(DX) )
     600                 :             : 
     601                 :             : ! FIRST CASE. A HIGHER FUNCTION VALUE.
     602                 :             : ! THE MINIMUM IS BRACKETED. IF THE CUBIC STEP IS CLOSER
     603                 :             : ! TO STX THAN THE QUADRATIC STEP, THE CUBIC STEP IS TAKEN,
     604                 :             : ! ELSE THE AVERAGE OF THE CUBIC AND QUADRATIC STEPS IS TAKEN.
     605                 :             : !
     606         [ +  - ]:           1 :  IF (FP > FX) THEN
     607                 :           1 :     INFO = 1
     608                 :           1 :     BOUND = .TRUE.
     609                 :           1 :     THETA = 3*(FX - FP)/(STP - STX) + DX + DG
     610                 :           1 :     S = MAX(ABS(THETA),ABS(DX),ABS(DG))
     611                 :           1 :     GAM = S * SQRT( (THETA/S)**2 - (DX/S)*(DG/S) )
     612         [ -  + ]:           1 :     IF (STP < STX) GAM = -GAM
     613                 :           1 :     P = (GAM - DX) + THETA
     614                 :           1 :     Q = ((GAM - DX) + GAM) + DG
     615                 :           1 :     R = P / Q
     616                 :           1 :     STPC = STX + R*(STP - STX)
     617                 :           1 :     STPQ = STX + ( ( DX / ( ( FX - FP ) / ( STP - STX ) + DX ) ) / 2 ) * ( STP - STX )
     618         [ -  + ]:           1 :     IF (ABS(STPC-STX) < ABS(STPQ-STX)) THEN
     619                 :             :        STPF = STPC
     620                 :             :     ELSE
     621                 :           0 :       STPF = STPC + (STPQ - STPC) / 2
     622                 :             :     END IF
     623                 :           1 :     BRACKT = .TRUE.
     624                 :             : !
     625                 :             : ! SECOND CASE. A LOWER FUNCTION VALUE AND DERIVATIVES OF
     626                 :             : ! OPPOSITE SIGN. THE MINIMUM IS BRACKETED. IF THE CUBIC
     627                 :             : ! STEP IS CLOSER TO STX THAN THE QUADRATIC (SECANT) STEP,
     628                 :             : ! THE CUBIC STEP IS TAKEN, ELSE THE QUADRATIC STEP IS TAKEN.
     629                 :             : !
     630         [ #  # ]:           0 :  ELSE IF (SGND < 0.0) THEN
     631                 :           0 :     INFO = 2
     632                 :           0 :     BOUND = .FALSE.
     633                 :           0 :     THETA = 3*(FX - FP)/(STP - STX) + DX + DG
     634                 :           0 :     S = MAX(ABS(THETA),ABS(DX),ABS(DG))
     635                 :           0 :     GAM = S * SQRT( (THETA/S)**2 - (DX/S)*(DG/S) )
     636         [ #  # ]:           0 :     IF (STP > STX) GAM = -GAM
     637                 :           0 :     P = (GAM - DG) + THETA
     638                 :           0 :     Q = ((GAM - DG) + GAM) + DX
     639                 :           0 :     R = P/Q
     640                 :           0 :     STPC = STP + R*(STX - STP)
     641                 :           0 :     STPQ = STP + (DG/(DG-DX))*(STX - STP)
     642         [ #  # ]:           0 :     IF (ABS(STPC-STP) > ABS(STPQ-STP)) THEN
     643                 :             :        STPF = STPC
     644                 :             :     ELSE
     645                 :           0 :        STPF = STPQ
     646                 :             :     END IF
     647                 :           0 :     BRACKT = .TRUE.
     648                 :             : !
     649                 :             : ! THIRD CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE
     650                 :             : ! SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DECREASES.
     651                 :             : ! THE CUBIC STEP IS ONLY USED IF THE CUBIC TENDS TO INFINITY
     652                 :             : ! IN THE DIRECTION OF THE STEP OR IF THE MINIMUM OF THE CUBIC
     653                 :             : ! IS BEYOND STP. OTHERWISE THE CUBIC STEP IS DEFINED TO BE
     654                 :             : ! EITHER STPMIN OR STPMAX. THE QUADRATIC (SECANT) STEP IS ALSO
     655                 :             : ! COMPUTED AND IF THE MINIMUM IS BRACKETED THEN THE THE STEP
     656                 :             : ! CLOSEST TO STX IS TAKEN, ELSE THE STEP FARTHEST AWAY IS TAKEN.
     657                 :             : !
     658         [ #  # ]:           0 :  ELSE IF (ABS(DG) < ABS(DX)) THEN
     659                 :           0 :     INFO = 3
     660                 :           0 :     BOUND = .TRUE.
     661                 :           0 :     THETA = 3*(FX - FP)/(STP - STX) + DX + DG
     662                 :           0 :     S = MAX(ABS(THETA),ABS(DX),ABS(DG))
     663                 :             : !
     664                 :             : !   THE CASE GAM = 0 ONLY ARISES IF THE CUBIC DOES NOT TEND
     665                 :             : !   TO INFINITY IN THE DIRECTION OF THE STEP.
     666                 :             : !
     667                 :           0 :     GAM = S * SQRT( MAX(0.0D0,(THETA/S)**2 - (DX/S)*(DG/S)) )
     668         [ #  # ]:           0 :     IF (STP > STX) GAM = -GAM
     669                 :           0 :     P = (GAM - DG) + THETA
     670                 :           0 :     Q = (GAM + (DX - DG)) + GAM
     671                 :           0 :     R = P/Q
     672   [ #  #  #  # ]:           0 :     IF (R < 0.0 .AND. GAM .NE. 0.0) THEN
     673                 :           0 :        STPC = STP + R*(STX - STP)
     674         [ #  # ]:           0 :     ELSE IF (STP > STX) THEN
     675                 :             :        STPC = STPMAX
     676                 :             :     ELSE
     677                 :           0 :        STPC = STPMIN
     678                 :             :     END IF
     679                 :           0 :     STPQ = STP + (DG/(DG-DX))*(STX - STP)
     680         [ #  # ]:           0 :     IF (BRACKT) THEN
     681         [ #  # ]:           0 :        IF (ABS(STP-STPC) < ABS(STP-STPQ)) THEN
     682                 :             :           STPF = STPC
     683                 :             :        ELSE
     684                 :           0 :           STPF = STPQ
     685                 :             :        END IF
     686                 :             :     ELSE
     687         [ #  # ]:           0 :        IF (ABS(STP-STPC) > ABS(STP-STPQ)) THEN
     688                 :             :           STPF = STPC
     689                 :             :        ELSE
     690                 :           0 :           STPF = STPQ
     691                 :             :        END IF
     692                 :             :     END IF
     693                 :             : !
     694                 :             : ! FOURTH CASE. A LOWER FUNCTION VALUE, DERIVATIVES OF THE
     695                 :             : ! SAME SIGN, AND THE MAGNITUDE OF THE DERIVATIVE DOES
     696                 :             : ! NOT DECREASE. IF THE MINIMUM IS NOT BRACKETED, THE STEP
     697                 :             : ! IS EITHER STPMIN OR STPMAX, ELSE THE CUBIC STEP IS TAKEN.
     698                 :             : !
     699                 :             :  ELSE
     700                 :           0 :     INFO = 4
     701                 :           0 :     BOUND = .FALSE.
     702         [ #  # ]:           0 :     IF (BRACKT) THEN
     703                 :           0 :        THETA = 3*(FP - FY)/(STY - STP) + DY + DG
     704                 :           0 :        S = MAX(ABS(THETA),ABS(DY),ABS(DG))
     705                 :           0 :        GAM = S * SQRT( (THETA/S)**2 - (DY/S)*(DG/S) )
     706         [ #  # ]:           0 :        IF (STP > STY) GAM = -GAM
     707                 :           0 :        P = (GAM - DG) + THETA
     708                 :           0 :        Q = ((GAM - DG) + GAM) + DY
     709                 :           0 :        R = P/Q
     710                 :           0 :        STPC = STP + R*(STY - STP)
     711                 :           0 :        STPF = STPC
     712         [ #  # ]:           0 :     ELSE IF (STP > STX) THEN
     713                 :             :        STPF = STPMAX
     714                 :             :     ELSE
     715                 :           0 :        STPF = STPMIN
     716                 :             :     END IF
     717                 :             :  END IF
     718                 :             : 
     719                 :             : !
     720                 :             : ! Update the interval of uncertainty. this update does not
     721                 :             : ! depend on the new step or the case analysis above.
     722                 :             : !
     723         [ +  - ]:           1 :  IF (FP > FX) THEN
     724                 :           1 :     STY = STP
     725                 :           1 :     FY = FP
     726                 :           1 :     DY = DG
     727                 :             :  ELSE
     728         [ #  # ]:           0 :     IF (SGND < 0.0) THEN
     729                 :           0 :        STY = STX
     730                 :           0 :        FY = FX
     731                 :           0 :        DY = DX
     732                 :             :     END IF
     733                 :           0 :     STX = STP
     734                 :           0 :     FX = FP
     735                 :           0 :     DX = DG
     736                 :             :  END IF
     737                 :             : 
     738                 :             : !
     739                 :             : ! Compute the new step and safeguard it.
     740                 :             : !
     741                 :           1 :  STPF = MIN(STPMAX,STPF)
     742                 :           1 :  STPF = MAX(STPMIN,STPF)
     743                 :           1 :  STP = STPF
     744   [ +  -  +  - ]:           1 :  IF (BRACKT .AND. BOUND) THEN
     745         [ +  - ]:           1 :     IF (STY > STX) THEN
     746                 :           1 :        STP = MIN( STX + 0.66 * (STY-STX) , STP)
     747                 :             :     ELSE
     748                 :           0 :        STP = MAX( STX + 0.66 * (STY-STX) , STP)
     749                 :             :     END IF
     750                 :             :  END IF
     751                 :             : 
     752                 :             : 
     753                 :             : end subroutine mcstep
     754                 :             : !!***
     755                 :             : 
     756   [ #  #  #  #  :           0 : end module m_lbfgs
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     757                 :             : !!***
        

Generated by: LCOV version 2.3-1