Statistiques
| Révision :

root / src / Step_GEDIIS.f90 @ 2

Historique | Voir | Annoter | Télécharger (15,13 ko)

1
     ! Geom = input parameter vector (Geometry), Grad = input gradient vector.
2
     ! HEAT is Energy(Geom)
3
      SUBROUTINE Step_GEDIIS(Geom_new,Geom,Grad,HEAT,Hess,NCoord,FRST)
4

    
5
	  use Io_module
6
	  use Path_module, only : Nom, Atome, OrderInv, indzmat, Pi, Nat
7
	  
8
      IMPLICIT NONE
9

    
10
      INTEGER(KINT) :: NCoord
11
      REAL(KREAL) :: Geom_new(NCoord), Grad(NCoord), Hess(NCoord*NCoord)
12
	  REAL(KREAL), INTENT(IN) :: Geom(NCoord)
13
	  REAL(KREAL) :: HEAT ! HEAT= Energy
14
      LOGICAL :: FRST
15

    
16
      ! MRESET = maximum number of iterations.
17
      INTEGER(KINT), PARAMETER :: MRESET=15, M2=(MRESET+1)*(MRESET+1) !M2 = 256
18
      REAL(KREAL), ALLOCATABLE, SAVE :: GeomSet(:), GradSet(:) ! MRESET*NCoord
19
      REAL(KREAL), ALLOCATABLE, SAVE :: DX(:), GSAVE(:) !NCoord
20
	  REAL(KREAL), SAVE :: ESET(MRESET)
21
	  REAL(KREAL) :: ESET_tmp(MRESET), B(M2),BS(M2),BST(M2), B_tmp(M2) ! M2=256
22
      LOGICAL DEBUG, PRINT, ci_lt_zero
23
      INTEGER(KINT), SAVE :: MSET ! mth Iteration
24
	  REAL(KREAL) :: ci(MRESET), ci_tmp(MRESET) ! MRESET = maximum number of iterations.
25
      INTEGER(KINT) :: NGEDIIS, MPLUS, INV, ITERA, MM, cis_zero, IXX, JXX, MSET_minus_cis_zero
26
      INTEGER(KINT) :: I,J,K, JJ, KJ, JNV, II, IONE, IJ, INK,ITmp, IX, JX, KX, MSET_C_cis_zero
27
	  INTEGER(KINT) :: current_size_B_mat, MyPointer, Iat
28
      REAL(KREAL) :: XMax, XNorm, S, DET, THRES, tmp, ER_star, ER_star_tmp
29

    
30
      DEBUG=.TRUE.
31
      PRINT=.FALSE.
32
	  
33
      IF (PRINT)  WRITE(*,'(/,''      BEGIN GEDIIS   '')')
34
	  
35
      ! Initialization
36
      IF (FRST) THEN
37
      ! FRST will be set to False in SPACE_GEDIIS, so no need to modify it here
38
         IF (ALLOCATED(GeomSet)) THEN
39
            IF (PRINT)  WRITE(*,'(/,''    In FRST, GEDIIS Dealloc  '')')
40
            DEALLOCATE(GeomSet,GradSet,DX,GSave)
41
            RETURN
42
         ELSE
43
            IF (PRINT)  WRITE(*,'(/,''     In FRST,  GEDIIS Alloc  '')')
44
            ALLOCATE(GeomSet(MRESET*NCoord),GradSet(MRESET*NCoord),DX(NCoord),GSAVE(NCoord))
45
         END IF
46
      END IF ! IF (FRST) THEN
47

    
48
      ! SPACE_GEDIIS SIMPLY LOADS THE CURRENT VALUES OF Geom AND Grad INTO THE ARRAYS GeomSet
49
      ! AND GradSet, MSET is set to zero and then 1 in SPACE_GEDIIS at first iteration.
50
      CALL SPACE_GEDIIS(MRESET,MSET,Geom,Grad,HEAT,NCoord,GeomSet,GradSet,ESET,FRST)
51

    
52
      IF (PRINT)  WRITE(*,'(/,''       GEDIIS after SPACE_GEDIIS  '')')
53

    
54
      ! INITIALIZE SOME VARIABLES AND CONSTANTS:
55
      NGEDIIS = MSET !MSET=mth iteration
56
      MPLUS = MSET + 1
57
      MM = MPLUS * MPLUS
58

    
59
      ! CONSTRUCT THE GEDIIS MATRIX:
60
      ! B_ij calculations from <B_ij=(g_i-g_j)(R_i-R_j)>
61
      JJ=0
62
      INV=-NCoord
63
      DO I=1,MSET
64
         INV=INV+NCoord
65
         JNV=-NCoord
66
         DO J=1,MSET
67
            JNV=JNV+NCoord
68
            JJ = JJ + 1
69
            B(JJ)=0.D0
70
			DO K=1, NCoord
71
			   B(JJ) = B(JJ) + (((GradSet(INV+K)-GradSet(JNV+K))*(GeomSet(INV+K)-GeomSet(JNV+K)))/2.D0)
72
			END DO
73
         END DO
74
      END DO
75

    
76
     ! The following shifting is required to correct indices of B_ij elements in the GEDIIS matrix.
77
	 ! The correction is needed because the last coloumn of the matrix contains all 1 and one zero.
78
      DO I=MSET-1,1,-1
79
         DO J=MSET,1,-1
80
            B(I*MSET+J+I) = B(I*MSET+J) 
81
         END DO
82
	  END DO
83
   
84
      ! for last row and last column of GEDIIS matrix 
85
      DO I=1,MPLUS
86
         B(MPLUS*I) = 1.D0
87
         B(MPLUS*MSET+I) = 1.D0
88
      END DO
89
      B(MM) = 0.D0
90
	  
91
	  DO I=1, MPLUS
92
	     !WRITE(*,'(10(1X,F20.4))') B((I-1)*MPLUS+1:I*(MPLUS))
93
	  END DO
94
	  	  
95
      ! ELIMINATE ERROR VECTORS WITH THE LARGEST NORM:
96
   80 CONTINUE
97
      DO I=1,MM !MM = (MSET+1) * (MSET+1)
98
         BS(I) = B(I) !just a copy of the original B (GEDIIS) matrix
99
      END DO
100
	  
101
      IF (NGEDIIS .NE. MSET) THEN
102
        DO II=1,MSET-NGEDIIS
103
           XMAX = -1.D10
104
           ITERA = 0
105
           DO I=1,MSET
106
              XNORM = 0.D0
107
              INV = (I-1) * MPLUS
108
              DO J=1,MSET
109
                 XNORM = XNORM + ABS(B(INV + J))
110
              END DO
111
              IF (XMAX.LT.XNORM .AND. XNORM.NE.1.0D0) THEN
112
                 XMAX = XNORM
113
                 ITERA = I
114
                 IONE = INV + I
115
              ENDIF
116
           END DO
117
		 
118
           DO I=1,MPLUS
119
              INV = (I-1) * MPLUS
120
              DO J=1,MPLUS
121
                 JNV = (J-1) * MPLUS
122
                 IF (J.EQ.ITERA) B(INV + J) = 0.D0
123
                 B(JNV + I) = B(INV + J)
124
              END DO
125
		   END DO
126
           B(IONE) = 1.0D0
127
        END DO
128
	  END IF ! matches IF (NGEDIIS .NE. MSET) THEN
129
	  
130
      ! SCALE GEDIIS MATRIX BEFORE INVERSION:
131
      DO I=1,MPLUS
132
         II = MPLUS * (I-1) + I ! B(II)=diagonal elements of B matrix
133
         GSAVE(I) = 1.D0 / DSQRT(1.D-20+DABS(B(II)))
134
		 !Print *, 'GSAVE(',I,')=', GSAVE(I) 
135
      END DO
136
      GSAVE(MPLUS) = 1.D0
137
      DO I=1,MPLUS
138
         DO J=1,MPLUS
139
            IJ = MPLUS * (I-1) + J
140
            B(IJ) = B(IJ) * GSAVE(I) * GSAVE(J)
141
         END DO
142
      END DO
143
  
144
     ! INVERT THE GEDIIS MATRIX B:
145
	  DO I=1, MPLUS
146
	     !WRITE(*,'(10(1X,F20.4))') B((I-1)*MPLUS+1:I*(MPLUS))
147
	  END DO
148
	  	  
149
      CALL MINV(B,MPLUS,DET) ! matrix inversion.
150
	  
151
	  DO I=1, MPLUS
152
	     !WRITE(*,'(10(1X,F20.16))') B((I-1)*MPLUS+1:I*(MPLUS))
153
	  END DO
154
	  
155
      DO I=1,MPLUS
156
         DO J=1,MPLUS
157
            IJ = MPLUS * (I-1) + J
158
            B(IJ) = B(IJ) * GSAVE(I) * GSAVE(J)
159
         END DO
160
      END DO
161
	  
162
      ! COMPUTE THE NEW INTERPOLATED PARAMETER VECTOR (Geometry):
163
	  ci=0.d0
164
	  ci_tmp=0.d0
165
	
166
	  ci_lt_zero= .FALSE.
167
	  DO I=1, MSET
168
		 DO J=1, MSET ! B matrix is read column-wise
169
		    ci(I)=ci(I)+B((J-1)*(MPLUS)+I)*ESET(J) !ESET is energy set, yet to be fixed.
170
		 END DO
171
		 ci(I)=ci(I)+B((MPLUS-1)*(MPLUS)+I)
172
		 !Print *, 'NO ci < 0 yet, c(',I,')=', ci(I)
173
		 IF((ci(I) .LT. 0.0D0) .OR. (ci(I) .GT. 1.0D0)) THEN
174
		   ci_lt_zero=.TRUE.
175
		   EXIT
176
		 END IF
177
      END DO !matches DO I=1, MSET
178
	  
179
	  IF (ci_lt_zero) Then
180
	  	 cis_zero = 0
181
         ER_star = 0.D0
182
		 ER_star_tmp = 1e32
183
		 
184
		 ! B_ij calculations from <B_ij=(g_i-g_j)(R_i-R_j)>, Full B matrix created first and then rows and columns are removed.
185
         JJ=0
186
         INV=-NCoord
187
         DO IX=1,MSET
188
            INV=INV+NCoord
189
            JNV=-NCoord
190
            DO JX=1,MSET
191
               JNV=JNV+NCoord
192
               JJ = JJ + 1
193
               BST(JJ)=0.D0
194
		       DO KX=1, NCoord
195
		          BST(JJ) = BST(JJ) + (((GradSet(INV+KX)-GradSet(JNV+KX))*(GeomSet(INV+KX)-GeomSet(JNV+KX)))/2.D0)
196
		       END DO
197
            END DO
198
	     END DO  
199
		
200
		 DO I=1, (2**MSET)-2 ! all (2**MSET)-2 combinations of cis, except the one where all cis are .GT. 0 and .LT. 1
201
		     ci(:)=1.D0
202
		     ! find out which cis are zero in I:
203
			 DO IX=1, MSET
204
			    JJ=IAND(I, 2**(IX-1))
205
				IF(JJ .EQ. 0) Then
206
				  ci(IX)=0.D0
207
			    END IF
208
			 END DO
209
			 
210
			 ci_lt_zero = .FALSE.
211
			 ! B_ij calculations from <B_ij=(g_i-g_j)(R_i-R_j)>, Full B matrix created first and then rows and columns are removed.
212
			 DO IX=1, MSET*MSET
213
                B(IX) = BST(IX) !just a copy of the original B (GEDIIS) matrix
214
             END DO
215
			 
216
             ! Removal of KXth row and KXth column in order to accomodate cI to be zero:
217
			 current_size_B_mat=MSET
218
			 cis_zero = 0
219
			 ! The bits of I (index of the upper loop 'DO I=1, (2**MSET)-2'), gives which cis are zero.
220
			 DO KX=1, MSET ! searching for each bit of I (index of the upper loop 'DO I=1, (2**MSET)-2')
221
			    IF (ci(KX) .EQ. 0.D0) Then !remove KXth row and KXth column
222
				   cis_zero = cis_zero + 1
223
				   
224
			       ! First row removal: (B matrix is read column-wise)
225
			       JJ=0
226
                   DO IX=1,current_size_B_mat ! columns reading
227
                      DO JX=1,current_size_B_mat ! rows reading
228
				         IF (JX .NE. KX) Then
229
				             JJ = JJ + 1
230
				             B_tmp(JJ) = B((IX-1)*current_size_B_mat+JX)
231
				         END IF
232
				      END DO   
233
			       END DO
234
			 
235
			       DO IX=1,current_size_B_mat*(current_size_B_mat-1)
236
			          B(IX) = B_tmp(IX)
237
			       END DO
238
			 
239
			       ! Now column removal:
240
			       JJ=0	 
241
                   DO IX=1,KX-1 ! columns reading
242
                      DO JX=1,current_size_B_mat-1 ! rows reading
243
				         JJ = JJ + 1
244
				         B_tmp(JJ) = B(JJ)
245
				      END DO
246
			       END DO				
247
			  
248
                   DO IX=KX+1,current_size_B_mat
249
                      DO JX=1,current_size_B_mat-1
250
				         JJ = JJ + 1
251
			   	         B_tmp(JJ) = B(JJ+current_size_B_mat-1)
252
				      END DO
253
			       END DO
254
			 			 
255
			       DO IX=1,(current_size_B_mat-1)*(current_size_B_mat-1)
256
			          B(IX) = B_tmp(IX)
257
			       END DO
258
				   current_size_B_mat = current_size_B_mat - 1
259
				END IF ! matches IF (ci(KX) .EQ. 0.D0) Then !remove
260
	         END DO ! matches DO KX=1, MSET
261

    
262
			 ! The following shifting is required to correct indices of B_ij elements in the GEDIIS matrix.
263
			 ! The correction is needed because the last coloumn and row of the matrix contains all 1 and one zero.
264
			 DO IX=MSET-cis_zero-1,1,-1
265
				DO JX=MSET-cis_zero,1,-1
266
				   B(IX*(MSET-cis_zero)+JX+IX) = B(IX*(MSET-cis_zero)+JX) 
267
				END DO
268
			 END DO
269
			 
270
			 ! for last row and last column of GEDIIS matrix 
271
			 DO IX=1,MPLUS-cis_zero
272
				B((MPLUS-cis_zero)*IX) = 1.D0
273
				B((MPLUS-cis_zero)*(MSET-cis_zero)+IX) = 1.D0
274
			 END DO
275
			 B((MPLUS-cis_zero) * (MPLUS-cis_zero)) = 0.D0
276
	       
277
	         DO IX=1, MPLUS
278
	            !WRITE(*,'(10(1X,F20.4))') B((IX-1)*MPLUS+1:IX*(MPLUS))
279
	         END DO
280
		   		   
281
			 ! ELIMINATE ERROR VECTORS WITH THE LARGEST NORM:
282
             IF (NGEDIIS .NE. MSET) THEN
283
			    JX = min(MSET-NGEDIIS,MSET-cis_zero-1)
284
                DO II=1,JX
285
                   XMAX = -1.D10
286
                   ITERA = 0
287
                   DO IX=1,MSET-cis_zero
288
                      XNORM = 0.D0
289
                      INV = (IX-1) * (MPLUS-cis_zero)
290
                      DO J=1,MSET-cis_zero
291
                         XNORM = XNORM + ABS(B(INV + J))
292
                      END DO
293
                      IF (XMAX.LT.XNORM .AND. XNORM.NE.1.0D0) THEN
294
                         XMAX = XNORM
295
                         ITERA = IX
296
                         IONE = INV + IX
297
                      ENDIF
298
				   END DO
299
		 
300
                   DO IX=1,MPLUS-cis_zero
301
                      INV = (IX-1) * (MPLUS-cis_zero)
302
                      DO J=1,MPLUS-cis_zero
303
                         JNV = (J-1) * (MPLUS-cis_zero)
304
                         IF (J.EQ.ITERA) B(INV + J) = 0.D0
305
                         B(JNV + IX) = B(INV + J)
306
					  END DO
307
		           END DO
308
                   B(IONE) = 1.0D0
309
			    END DO
310
	         END IF ! matches IF (NGEDIIS .NE. MSET) THEN
311

    
312
			 ! SCALE GEDIIS MATRIX BEFORE INVERSION:
313
			 DO IX=1,MPLUS-cis_zero
314
				II = (MPLUS-cis_zero) * (IX-1) + IX ! B(II)=diagonal elements of B matrix
315
				GSAVE(IX) = 1.D0 / DSQRT(1.D-20+DABS(B(II)))
316
			 END DO
317
			 GSAVE(MPLUS-cis_zero) = 1.D0
318
			 DO IX=1,MPLUS-cis_zero
319
				DO JX=1,MPLUS-cis_zero
320
				   IJ = (MPLUS-cis_zero) * (IX-1) + JX
321
				   B(IJ) = B(IJ) * GSAVE(IX) * GSAVE(JX)
322
				END DO
323
			 END DO
324

    
325
			 ! INVERT THE GEDIIS MATRIX B:	  
326
			 CALL MINV(B,MPLUS-cis_zero,DET) ! matrix inversion.
327
	  
328
			 DO IX=1,MPLUS-cis_zero
329
				DO JX=1,MPLUS-cis_zero
330
				   IJ = (MPLUS-cis_zero) * (IX-1) + JX
331
				   B(IJ) = B(IJ) * GSAVE(IX) * GSAVE(JX)
332
				END DO
333
			 END DO
334
			 
335
	         DO IX=1, MPLUS
336
	            !WRITE(*,'(10(1X,F20.4))') B((IX-1)*MPLUS+1:IX*(MPLUS))
337
	         END DO
338
			 			 
339
             ! ESET is rearranged to handle zero cis and stored in ESET_tmp:
340
			 JJ=0
341
			 DO IX=1, MSET
342
				IF (ci(IX) .NE. 0) Then
343
				   JJ=JJ+1
344
				   ESET_tmp(JJ) = ESET(IX)
345
				END IF
346
			 END DO
347
			 
348
			 ! DETERMINATION OF nonzero cis:
349
			 MyPointer=1
350
     	     DO IX=1, MSET-cis_zero
351
			    tmp = 0.D0
352
		        DO J=1, MSET-cis_zero ! B matrix is read column-wise
353
				   tmp=tmp+B((J-1)*(MPLUS-cis_zero)+IX)*ESET_tmp(J)
354
				END DO
355
		        tmp=tmp+B((MPLUS-cis_zero-1)*(MPLUS-cis_zero)+IX)
356
		        IF((tmp .LT. 0.0D0) .OR. (tmp .GT. 1.0D0)) THEN
357
		           ci_lt_zero=.TRUE.
358
		           EXIT
359
				ELSE
360
				   DO JX=MyPointer,MSET
361
				      IF (ci(JX) .NE. 0) Then
362
				         ci(JX) = tmp
363
					     MyPointer=JX+1
364
					     EXIT
365
					  END IF
366
				   END DO
367
		        END IF
368
             END DO !matches DO I=1, MSET-cis_zero
369
	         !Print *, 'Local set of cis, first 10:, MSET=', MSET, ', I of (2**MSET)-2=', I
370
			 !WRITE(*,'(10(1X,F20.4))') ci(1:MSET)
371
	         !Print *, 'Local set of cis ends:****************************************'
372

    
373
             ! new set of cis determined based on the lower energy (ER_star):
374
			 IF (.NOT. ci_lt_zero) Then
375
                Call Energy_GEDIIS(MRESET,MSET,ci,GeomSet,GradSet,ESET,NCoord,ER_star)
376
				IF (ER_star .LT. ER_star_tmp) Then			
377
				   ci_tmp=ci	
378
				   ER_star_tmp = ER_star
379
				END IF
380
             END IF ! matches IF (.NOT. ci_lt_zero) Then
381
          END DO !matches DO I=1, (2**K)-2 ! all (2**K)-2 combinations of cis, except the one where all cis are .GT. 0 and .LT. 1 
382
		  ci = ci_tmp
383
	  END IF! matches IF (ci_lt_zero) Then
384
	  
385
	  Print *, 'Final set of cis, first 10:***********************************'
386
	  WRITE(*,'(10(1X,F20.4))') ci(1:MSET)
387
	  Print *, 'Final set of cis ends:****************************************'
388
	  Geom_new(:) = 0.D0
389
	  DO I=1, MSET	  
390
         Geom_new(:) = Geom_new(:) + (ci(I)*GeomSet((I-1)*NCoord+1:I*NCoord)) !MPLUS=MSET+1
391
		 ! R_(N+1)=R*+DeltaR:
392
		 DO J=1, NCoord
393
			tmp=0.D0
394
			DO K=1,NCoord
395
			   !tmp=tmp+Hess((J-1)*NCoord+K)*GradSet((I-1)*NCoord+K) ! If Hinv=.False., then we need to invert Hess
396
			END DO
397
			Geom_new(J) = Geom_new(J) - (ci(I)*tmp)
398
		 END DO
399
	  END DO
400
	  
401
	  DX(:) = Geom(:) - Geom_new(:)
402
	  
403
      XNORM = SQRT(DOT_PRODUCT(DX,DX))
404
      IF (PRINT) THEN
405
         WRITE (6,'(/10X,''DEVIATION IN X '',F10.4,8X,''DETERMINANT '',G9.3)') XNORM, DET
406
         !WRITE(*,'(10X,''GEDIIS COEFFICIENTS'')')
407
         !WRITE(*,'(10X,5F12.5)') (B(MPLUS*MSET+I),I=1,MSET)
408
      ENDIF
409

    
410
      ! THE FOLLOWING TOLERENCES FOR XNORM AND DET ARE SOMEWHAT ARBITRARY!
411
      THRES = MAX(10.D0**(-NCoord), 1.D-25)
412
      IF (XNORM.GT.2.D0 .OR. DABS(DET) .LT. THRES) THEN
413
         IF (PRINT)THEN
414
            WRITE(*,*) "THE GEDIIS MATRIX IS ILL CONDITIONED"     
415
            WRITE(*,*) " - PROBABLY, VECTORS ARE LINEARLY DEPENDENT - "
416
            WRITE(*,*) "THE GEDIIS STEP WILL BE REPEATED WITH A SMALLER SPACE"
417
         END IF
418
         DO K=1,MM
419
			B(K) = BS(K) ! why this is reverted? Because "IF (NGEDIIS .GT. 0) GO TO 80", see below
420
         END DO
421
         NGEDIIS = NGEDIIS - 1
422
         IF (NGEDIIS .GT. 0) GO TO 80
423
         IF (PRINT) WRITE(*,'(10X,''NEWTON-RAPHSON STEP TAKEN'')')
424
         Geom_new(:) = Geom(:) ! Geom_new is set to original Geom, thus DX = Geom(:) - Geom_new(:)=zero
425
      END IF ! matches IF (XNORM.GT.2.D0 .OR. DABS(DET).LT. THRES) THEN
426
	  
427
	 !*******************************************************************************************************************
428
	  Geom_new(:) = 0.D0
429
	  DO I=1, MSET	  
430
         Geom_new(:) = Geom_new(:) + (ci(I)*GeomSet((I-1)*NCoord+1:I*NCoord)) !MPLUS=MSET+1
431
		 ! R_(N+1)=R*+DeltaR:
432
		 DO J=1, NCoord
433
			tmp=0.D0
434
			DO K=1,NCoord
435
			   tmp=tmp+Hess((J-1)*NCoord+K)*GradSet((I-1)*NCoord+K) ! If Hinv=.False., then we need to invert Hess
436
			END DO
437
			Geom_new(J) = Geom_new(J) - (ci(I)*tmp)
438
		 END DO
439
	  END DO
440
	 !*******************************************************************************************************************
441
	  
442
      IF (PRINT)  WRITE(*,'(/,''       END GEDIIS  '',/)')
443

    
444
      END SUBROUTINE Step_GEDIIS
445