File: linmin.f

package info (click to toggle)
mopac7 1.15-5
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 3,748 kB
  • sloc: fortran: 35,321; sh: 9,039; ansic: 417; makefile: 95
file content (239 lines) | stat: -rw-r--r-- 7,889 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
      SUBROUTINE LINMIN(XPARAM,ALPHA,PVECT,NVAR,FUNCT,OKF,IC, DOTT)
      IMPLICIT DOUBLE PRECISION (A-H,O-Z)
      INCLUDE 'SIZES'
      DIMENSION XPARAM(NVAR),PVECT(NVAR),GRAD(MAXPAR)
      COMMON /GRAVEC/ COSINE
      COMMON /NUMCAL/ NUMCAL
C*********************************************************************
C
C  LINMIN DOES A LINE MINIMISATION.
C
C  ON INPUT:  XPARAM = STARTING COORDINATE OF SEARCH.
C             ALPHA  = STEP SIZE FOR INITIATING SEARCH.
C             PVECT  = DIRECTION OF SEARCH.
C             NVAR   = NUMBER OF VARIABLES IN XPARAM.
C             FUNCT  = INITIAL VALUE OF THE FUNCTION TO BE MINIMIZED.
C             ISOK   = NOT IMPORTANT.
C             COSINE = COSINE OF ANGLE OF CURRENT AND PREVIOUS GRADIENT.
C
C  ON OUTPUT: XPARAM = COORDINATE OF MINIMUM OF FUNCTI0N.
C             ALPHA  = NEW STEP SIZE, USED IN NEXT CALL OF LINMIN.
C             FUNCT  = FINAL, MINIMUM VALUE OF THE FUNCTION.
C             OKF    = TRUE IF LINMIN IMPROVED FUNCT, FALSE OTHERWISE.
C
C**********************************************************************
      COMMON /KEYWRD/ KEYWRD
C
C  THE FOLLOWING COMMON IS USED TO FIND OUT IF A NON-VARIATIONALLY
C  OPTIMIZED WAVE-FUNCTION IS BEING USED.
C
      COMMON /MOLKST/ NUMAT,NAT(NUMATM),NFIRST(NUMATM),NMIDLE(NUMATM),
     1                NLAST(NUMATM), NORBS, NELECS,NALPHA,NBETA,
     2                NCLOSE,NOPEN,NDUMY,FRACT
      CHARACTER KEYWRD*241
      DIMENSION PHI(3), VT(4)
      DIMENSION XSTOR(MAXPAR), XPAREF(MAXPAR)
      INTEGER LEFT,RIGHT,CENTER
      LOGICAL PRINT,OKF, HALFE, DIIS
      SAVE ICALCN, PRINT, HALFE, XMAXM, I
      SAVE MAXLIN,  YMAXST
      DATA ICALCN /0/
      IF (ICALCN.NE.NUMCAL) THEN
         HALFE =(INDEX(KEYWRD,'C.I.') .NE. 0 .OR. NCLOSE.NE.NOPEN)
         IF(INDEX(KEYWRD,'GNORM') .NE. 0)
     1DROP=DROP*MIN(READA(KEYWRD,INDEX(KEYWRD,'GNORM')),1.D0)
         XMAXM  = 0.4D0
         DELTA2 = 0.001D0
         IF(INDEX(KEYWRD,'NOTH') .EQ. 0) THEN
            DELTA1 = 0.5D0
         ELSE
            DELTA1 = 0.1D0
         ENDIF
         ALPHA  = 1.D0
         MAXLIN = 15
         IF(NVAR.EQ.1)THEN
            PVECT(1)=0.01D0
            DROP=0.01D0
            ALPHA=1.D0
            DELTA1 = 0.00005D0
            DELTA2 = 0.00001D0
            IF(INDEX(KEYWRD,'PREC') .NE. 0) DELTA1=0.0000005D0
            MAXLIN=30
         ENDIF
         COSINE=99.99D0
C
         YMAXST  = 0.4D0
         PRINT=(INDEX(KEYWRD,'LINMIN') .NE. 0)
         ICALCN=NUMCAL
      ENDIF
      DO 10 I=1,NVAR
         XPAREF(I)=XPARAM(I)
   10 CONTINUE         
      XMAXM=0.D0
      DO 20 I=1,NVAR
         PABS=ABS(PVECT(I))
   20 XMAXM=MAX(XMAXM,PABS)
      XMAXM=YMAXST/XMAXM
      IF(NVAR.EQ.1)
     1CALL COMPFG(XPARAM, .TRUE., FUNCT,.TRUE.,GRAD,.FALSE.)
      FIN=FUNCT
      SSQLST=FUNCT
      DIIS=IC.EQ.1.AND.NVAR.GT.1
      PHI(1)=FUNCT
      ALPHA=1.D0
      VT(1)=0.0D00
      VT(2)=ALPHA
      IF (VT(2).GT.XMAXM) VT(2)=XMAXM
      FMAX=FUNCT
      FMIN=FUNCT
      ALPHA=VT(2)
      DO 30 I=1,NVAR
   30 XPARAM(I)=XPAREF(I)+ALPHA*PVECT(I)
      CALL COMPFG(XPARAM, .TRUE., PHI(2),.TRUE.,GRAD,.FALSE.)
      IF(PHI(2).GT.FMAX) FMAX=PHI(2)
      IF(PHI(2).LT.FMIN) FMIN=PHI(2)
      CALL EXCHNG (PHI(2),SQSTOR,ENERGY,ESTOR,XPARAM,XSTOR,
     1ALPHA,ALFS,NVAR)
      IF(DIIS)GOTO 190
      IF(NVAR.GT.1)THEN
C
C   CALCULATE A NEW ALPHA BASED ON THIEL'S FORMULA
C
         ALPHA=-ALPHA**2*DOTT/(2.D0*(PHI(2)-SSQLST-ALPHA*DOTT))
         IF(ALPHA.GT.2.D0)ALPHA=2.D0
      ELSE
         IF(PHI(2).LT.PHI(1))THEN
            ALPHA=2*ALPHA
         ELSE
            ALPHA=-ALPHA
         ENDIF
      ENDIF
C#      IF(PRINT)WRITE(6,'(3(A,F12.6))')' ESTIMATED DROP:',DOTT*0.5D0,
C#     1'  ACTUAL: ',PHI(2)-SSQLST, '  PREDICTED ALPHA',ALPHA
      OKF=OKF.OR.PHI(2).LT.SSQLST
      IF(DELTA1.GT.0.3D0)THEN
C
C  THIEL'S TESTS # 18 AND 19
C
         IF(OKF.AND.ALPHA.LT.2.D0)GOTO 190
      ENDIF
      VT(3)=ALPHA
      IF (VT(3).LE.1.D0) THEN
         LEFT=3
         CENTER=1
         RIGHT=2
      ELSE
         LEFT=1
         CENTER=2
         RIGHT=3
      ENDIF
      DO 40 I=1,NVAR
   40 XPARAM(I)=XPAREF(I)+ALPHA*PVECT(I)
      CALL COMPFG (XPARAM, .TRUE., FUNCT,.TRUE.,GRAD,.FALSE.)
      IF(FUNCT.GT.FMAX) FMAX=FUNCT
      IF(FUNCT.LT.FMIN) FMIN=FUNCT
      IF (FUNCT.LT.SQSTOR) CALL EXCHNG (FUNCT,SQSTOR,ENERGY,
     1ESTOR,XPARAM,XSTOR,ALPHA,ALFS,NVAR)
      OKF=(OKF.OR.FUNCT.LT.FIN)
      PHI(3)=FUNCT
      IF (PRINT)WRITE (6,50) VT(1),PHI(1),PHI(1)-FIN,
     1                        VT(2),PHI(2),PHI(2)-FIN,
     2                        VT(3),PHI(3),PHI(3)-FIN
   50 FORMAT ( ' ---QLINMN ',/5X, 'LEFT   ...',F17.8,2F17.11/5X,
     1 'CENTER ...',F17.8,2F17.11,/5X, 'RIGHT  ...',F17.8,2F17.11,/)
      DO 180 ICTR=3,MAXLIN
         ALPHA=VT(2)-VT(3)
         BETA=VT(3)-VT(1)
         GAMMA=VT(1)-VT(2)
         IF(ABS(ALPHA*BETA*GAMMA) .GT. 1.D-4)THEN
            ALPHA=-(PHI(1)*ALPHA+PHI(2)*BETA+PHI(3)*GAMMA)/(ALPHA*BETA*G
     1AMM   A)
         ELSE
C
C   FINISH BECAUSE TWO POINTS CALCULATED ARE VERY CLOSE TOGETHER
C
            GOTO 190
         ENDIF
         BETA=((PHI(1)-PHI(2))/GAMMA)-ALPHA*(VT(1)+VT(2))
         IF (ALPHA) 60,60,90
   60    IF (PHI(RIGHT).GT.PHI(LEFT)) GO TO 70
         ALPHA=3.0D00*VT(RIGHT)-2.0D00*VT(CENTER)
         GO TO 80
   70    ALPHA=3.0D00*VT(LEFT)-2.0D00*VT(CENTER)
   80    S=ALPHA-ALPOLD
         IF (ABS(S).GT.XMAXM) S=SIGN(XMAXM,S)*(1+0.01D0*(XMAXM/S))
         ALPHA=S+ALPOLD
         GO TO 100
   90    ALPHA=-BETA/(2.0D00*ALPHA)
         S=ALPHA-ALPOLD
         XXM=2.0D00*XMAXM
         IF (ABS(S).GT.XXM) S=SIGN(XXM,S)*(1+0.01D0*(XXM/S))
         ALPHA=S+ALPOLD
  100    CONTINUE
C
C   FINISH IF CALCULATED POINT IS NEAR TO POINT ALREADY CALCULATED
C
         DO 110 I=1,3
  110    IF (ABS(ALPHA-VT(I)).LT.DELTA1*(1.D0+VT(I)).AND.OKF) GOTO 190
         DO 120 I=1,NVAR
  120    XPARAM(I)=XPAREF(I)+ALPHA*PVECT(I)
         FUNOLD=FUNCT
         CALL COMPFG (XPARAM, .TRUE., FUNCT,.TRUE.,GRAD,.FALSE.)
         IF(FUNCT.GT.FMAX) FMAX=FUNCT
         IF(FUNCT.LT.FMIN) FMIN=FUNCT
         IF (FUNCT.LT.SQSTOR) CALL EXCHNG (FUNCT,SQSTOR,ENERGY,ESTOR,
     1   XPARAM,XSTOR,ALPHA,ALFS,NVAR)
         OKF=OKF .OR. (FUNCT.LT.FIN)
         IF (PRINT) WRITE(6,130) VT(LEFT),PHI(LEFT), PHI(LEFT)-FIN,
     1                           VT(CENTER),PHI(CENTER),PHI(CENTER)-FIN,
     2                           VT(RIGHT),PHI(RIGHT),PHI(RIGHT)-FIN,
     3                           ALPHA,FUNCT,FUNCT-FIN
  130    FORMAT (5X,'LEFT    ...',F17.8,2F17.11,/5X,'CENTER  ...',
     1F17.8,2F17.11,/5X,'RIGHT   ...',F17.8,2F17.11,/5X,
     2 'NEW     ...',F17.8,2F17.11,/)
C
C TEST TO EXIT FROM LINMIN IF NOT DROPPING IN VALUE OF FUNCTION FAST.
C
         IF(ABS(FUNOLD-FUNCT) .LT. DELTA2 .AND. OKF) GOTO 190
         ALPOLD=ALPHA
         IF ((ALPHA.GT.VT(RIGHT)).OR.(ALPHA.GT.VT(CENTER)
     1        .AND.FUNCT.LT.PHI(CENTER)).OR.(ALPHA.GT.VT(LEFT)
     2        .AND.ALPHA.LT.VT(CENTER).AND.FUNCT.GT.PHI(CENTER)))
     3         GOTO 140
         VT(RIGHT)=ALPHA
         PHI(RIGHT)=FUNCT
         GO TO 150
  140    VT(LEFT)=ALPHA
         PHI(LEFT)=FUNCT
  150    IF (VT(CENTER).LT.VT(RIGHT)) GO TO 160
         I=CENTER
         CENTER=RIGHT
         RIGHT=I
  160    IF (VT(LEFT).LT.VT(CENTER)) GO TO 170
         I=LEFT
         LEFT=CENTER
         CENTER=I
  170    IF (VT(CENTER).LT.VT(RIGHT)) GO TO 180
         I=CENTER
         CENTER=RIGHT
         RIGHT=I
  180 CONTINUE
  190 CONTINUE
C
C  IC=1 IF THE LAST POINT CALCULATED WAS THE BEST POINT, IC=2 OTHERWISE
C
      IC=2
      IF(ABS(ESTOR-ENERGY).LT.1.D-12)IC=1
      CALL EXCHNG (SQSTOR,FUNCT,ESTOR,ENERGY,XSTOR,XPARAM,
     1             ALFS,ALPHA,NVAR)
      OKF = (FUNCT.LT.SSQLST.OR.DIIS)
      IF (FUNCT.GE.SSQLST) RETURN
      IF (ALPHA) 200,220,220
  200 ALPHA=-ALPHA
      DO 210 I=1,NVAR
  210 PVECT(I)=-PVECT(I)
  220 CONTINUE
      RETURN
C
C
      END