Millepede-II  V04-00-00
 All Classes Files Functions Variables Enumerator
linesrch.f90
Go to the documentation of this file.
00001 
00002 ! Code converted using TO_F90 by Alan Miller
00003 ! Date: 2012-03-16  Time: 11:06:29
00004 
00031 
00033 MODULE linesrch
00034     IMPLICIT NONE
00035 
00036     INTEGER, PARAMETER :: msfd=20
00037     INTEGER :: nsfd    !< number of function calls
00038     INTEGER :: idgl    !< index of smallest negative slope
00039     INTEGER :: idgr    !< index of smallest positive slope
00040     INTEGER :: idgm    !< index of minimal slope
00041     INTEGER :: minf=1  !< min. number of function calls
00042     INTEGER :: maxf=5  !< max. number of function calls
00043     INTEGER :: lsinfo  !< (status) information
00044     DOUBLE PRECISION, DIMENSION(4,msfd) :: sfd !< abscissa; function value; slope; predicted zero
00045     DOUBLE PRECISION :: stmx=0.9 !< maximum slope ratio
00046     DOUBLE PRECISION :: gtol     !< slope ratio
00047 
00048 END MODULE linesrch
00049 
00067 
00068 SUBROUTINE ptline(n,x,f,g,s,step, info) ! - 2 arguments
00069     USE linesrch
00070 
00071     IMPLICIT NONE
00072     INTEGER, INTENT(IN)                      :: n
00073     DOUBLE PRECISION, INTENT(IN OUT)         :: x(n)
00074     DOUBLE PRECISION, INTENT(IN OUT)         :: f
00075     DOUBLE PRECISION, INTENT(IN OUT)         :: g(n)
00076     DOUBLE PRECISION, INTENT(IN OUT)         :: s(n)
00077     DOUBLE PRECISION, INTENT(OUT)            :: step
00078     INTEGER, INTENT(OUT)                     :: info
00079 
00080     INTEGER::  i1
00081     INTEGER :: i2
00082     INTEGER :: i               ! internal
00083     INTEGER :: im              ! internal
00084     DOUBLE PRECISION :: alpha  ! internal
00085     DOUBLE PRECISION :: dginit ! internal
00086     DOUBLE PRECISION :: dg     ! internal
00087     DOUBLE PRECISION :: fsaved ! internal
00088     DOUBLE PRECISION :: tot    ! internal
00089     DOUBLE PRECISION :: fp1    ! internal
00090     DOUBLE PRECISION :: fp2    ! internal
00091     SAVE
00092 
00093     !     initialization ---------------------------------------------------
00094 
00095     info=0             ! reset INFO flag
00096     dg=0.0D0
00097     DO i=1,n           !
00098         dg=dg-g(i)*s(i)   ! DG = scalar product: grad x search
00099     END DO!
00100 
00101     IF(nsfd == 0) THEN    ! initial call
00102         dginit=dg          ! DG = initial directional gradient
00103         IF(dginit >= 0.0D0) GO TO 100 ! error: step not decreasing
00104         step=1.0D0         ! initial step factor is one
00105         alpha=step         ! get initial step factor
00106         tot=0.0D0          ! reset total step
00107         idgl=1             ! index of smallest negative slope
00108         idgr=0             ! index of smallest positive slope
00109         fsaved=f           ! initial Function value
00110         nsfd=1             ! starting point of iteration
00111         sfd(1,1)=0.0       ! abscissa
00112         sfd(2,1)=0.0       ! reference function value
00113         sfd(3,1)=dginit    ! slope
00114         sfd(4,1)=0.0       ! predicted zero
00115         im=1               ! optimum
00116     ELSE                  ! subsequent call
00117         nsfd=nsfd+1
00118         sfd(1,nsfd)=tot          ! abscissa
00119         sfd(2,nsfd)=f-fsaved     ! function value difference to reference
00120         sfd(3,nsfd)=dg           ! slope
00121         sfd(4,nsfd)=0.0          ! predicted zero (see below)
00122         IF(dg < sfd(3,im)) THEN
00123             im=nsfd
00124         END IF
00125   
00126         !        define interval indices IDGL and IDGR
00127         IF(dg <= 0.0D0) THEN
00128             IF(dg >= sfd(3,idgl)) idgl=nsfd
00129         END IF
00130         IF(dg >= 0.0D0) THEN     ! limit to the right
00131             IF(idgr == 0) idgr=nsfd
00132             IF(dg <= sfd(3,idgr)) idgr=nsfd
00133         END IF
00134   
00135         IF(idgr == 0) THEN
00136             i1=nsfd-1
00137             i2=nsfd
00138         ELSE
00139             i1=idgl
00140             i2=idgr
00141         END IF
00142         fp1=sfd(3,i1)
00143         fp2=sfd(3,i2)                       ! interpolation
00144         sfd(4,nsfd)=(sfd(1,i1)*fp2-sfd(1,i2)*fp1)/(fp2-fp1)
00145   
00146         !        convergence tests
00147         IF(nsfd >= minf.AND.ABS(dg) <= ABS(dginit)*gtol) THEN
00148             !           normal convergence return with INFO=1 ----------------------
00149             alpha=tot+alpha          ! total ALPHA is returned
00150             step =alpha
00151             idgm=idgl
00152             IF(idgr /= 0) THEN
00153                 IF(sfd(3,idgr)+sfd(3,idgl) < 0.0D0) idgm=idgr
00154             END IF
00155             GO TO 101
00156         END IF
00157         IF(nsfd >= maxf) GO TO 102 ! max number of function calls
00158         alpha=MIN(sfd(4,nsfd),stmx)-tot     ! new step from previous
00159         IF(ABS(alpha) < 1.0D-3.AND.sfd(4,nsfd) > stmx) GO TO 103
00160         IF(ABS(alpha) < 1.0D-3) GO TO 104
00161     END IF
00162 
00163     !     prepare next function call ---------------------------------------
00164 
00165     DO i=1,n
00166         x(i)=x(i)+alpha*s(i)    ! step by ALPHA -> new X
00167     END DO
00168     tot=tot+alpha            !
00169     step=tot
00170     info=-1                  ! recalculate function and gradient
00171     lsinfo=info
00172     RETURN
00173 
00174     !     error exits ------------------------------------------------------
00175 104 info=info+1              ! 4: step small
00176 103 info=info+1              ! 3: maximum reached
00177 102 info=info+1              ! 2: too many function calls
00178 101 info=info+1              ! 1: normal convergence
00179     lsinfo=info
00180     im=1
00181     DO i=1,nsfd
00182         IF(ABS(sfd(3,i)) < ABS(sfd(3,im))) im=i
00183     END DO
00184     alpha=sfd(1,im)-sfd(1,nsfd)
00185     IF(im == nsfd) RETURN    ! already at minimum
00186     DO i=1,n
00187         x(i)=x(i)+alpha*s(i)    ! step by ALPHA to slope minimum
00188     END DO
00189     f=sfd(2,im)+fsaved       ! F at minimum
00190     step=sfd(1,im)           ! total step at convergence
00191     IF(im /= 1) RETURN       ! improvement
00192     info=5                   ! no improvement
00193 100 step=0.0D0               ! 0: initial slope not negative
00194     lsinfo=info
00195     RETURN
00196 END SUBROUTINE ptline
00197 
00210 
00211 SUBROUTINE ptldef(gtole,stmax,minfe,maxfe)
00212     USE linesrch
00213 
00214     IMPLICIT NONE
00215     INTEGER, INTENT(IN) :: minfe
00216     INTEGER, INTENT(IN) :: maxfe
00217     REAL, INTENT(IN)    :: gtole
00218     REAL, INTENT(IN)    :: stmax
00219 
00220     gtol=MAX(1.0E-4,MIN(gtole,0.9E0))  ! slope ratio
00221     IF(gtole == 0.0) gtol=0.9D0   ! default slope ratio
00222     stmx=stmax                    ! maximum total step
00223     IF(stmx == 0.0D0) stmx=10.0D0 ! default limit
00224     minf=MAX(1,MIN(minfe,msfd-2)) ! minimum number of evaluations
00225     maxf=MAX(2,MIN(maxfe,msfd-1)) ! maximum number of evaluations
00226     IF(maxfe == 0) maxf=5         ! default max number of values
00227     nsfd=0                        ! reset
00228 END SUBROUTINE ptldef
00229 
00236 
00237 SUBROUTINE ptlopt(nf,m,slopes,steps)
00238     USE linesrch
00239     IMPLICIT NONE
00240 
00241     INTEGER, INTENT(OUT)                     :: nf
00242     INTEGER, INTENT(OUT)                     :: m
00243     REAL, DIMENSION(3), INTENT(OUT)          :: slopes
00244     REAL, DIMENSION(3), INTENT(OUT)          :: steps
00245     INTEGER :: i
00246 
00247     !     ...
00248     nf=nsfd
00249     IF(nsfd == 0) THEN  ! no values
00250         m=0
00251         DO i=1,3
00252             slopes(i)=0.0
00253             steps(i) =0.0
00254         END DO
00255     ELSE                ! values exist
00256         m=1
00257         DO i=1,nsfd
00258             IF(ABS(sfd(3,i)) < ABS(sfd(3,m))) m=i
00259         END DO
00260         slopes(1)=REAL(sfd(3,1))
00261         slopes(2)=REAL(sfd(3,nsfd))
00262         slopes(3)=REAL(sfd(3,m))
00263         steps(1) =REAL(sfd(1,1))
00264         steps(2) =REAL(sfd(1,nsfd))
00265         steps(3) =REAL(sfd(1,m))
00266     END IF
00267 END SUBROUTINE ptlopt
00268 
00272 
00273 SUBROUTINE ptlprt(lunp)
00274     USE linesrch
00275 
00276     IMPLICIT NONE
00277     INTEGER :: i
00278     INTEGER :: j
00279     INTEGER :: im
00280     INTEGER :: lun
00281     INTEGER, INTENT(IN) :: lunp
00282     REAL :: ratio
00283     CHARACTER (LEN=2) :: tlr
00284     !     ...
00285     lun=lunp
00286     IF(lun == 0) lun=6
00287     IF(nsfd <= 0) RETURN
00288     WRITE(lun,*) ' '
00289     WRITE(lun,*) 'PTLINE: line-search method based on slopes',  &
00290     ' with sufficient slope-decrease'
00291     WRITE(lun,*) 'PTLDEF: slope ratio limit=',gtol
00292     WRITE(lun,*) 'PTLDEF: maximum step =',stmx
00293     WRITE(lun,*) 'PTLDEF:',minf,' <= nr of calls <=',maxf
00294     WRITE(lun,101)
00295     im=1
00296     DO i=1,nsfd
00297         IF(ABS(sfd(3,i)) < ABS(sfd(3,im))) im=i
00298     END DO
00299     DO i=1,nsfd
00300         tlr='  '
00301         IF(i == im)   tlr='**'
00302         IF(i == idgl) tlr(1:1)='L'
00303         IF(i == idgr) tlr(2:2)='R'
00304         IF(i == 1) THEN
00305             WRITE(lun,102) i-1, sfd(1,i),tlr,(sfd(j,i),j=2,4)
00306         ELSE
00307             ratio=REAL(ABS(sfd(3,i)/sfd(3,1)))
00308             WRITE(lun,103) i-1, sfd(1,i),tlr,(sfd(j,i),j=2,4),ratio
00309         END IF
00310 
00311     END DO
00312     IF(lsinfo == 0) WRITE(lun,*)  &
00313     'PTLINE: INFO=0  input error (e.g. gradient not negative)'
00314     IF(lsinfo == 1) WRITE(lun,*) 'PTLINE: INFO=1  convergence reached'
00315     IF(lsinfo == 2) WRITE(lun,*) 'PTLINE: INFO=2  too many function calls'
00316     IF(lsinfo == 3) WRITE(lun,*) 'PTLINE: INFO=3  maximum step reached'
00317     IF(lsinfo == 4) WRITE(lun,*) 'PTLINE: INFO=4  step too small (< 0.001)'
00318     WRITE(lun,*) ' '
00319 
00320 101 FORMAT('  i      x              F(x)         F''(X)',  &
00321     '          minimum     F''(X)')
00322 102 FORMAT(i3,f12.6,1X,a2,g15.6,g14.6,f12.6,'     ratio')
00323 103 FORMAT(i3,f12.6,1X,a2,g15.6,g14.6,f12.6,f10.3)
00324 
00325 END SUBROUTINE ptlprt
00326