root / src / Egrad.f90 @ 2
Historique | Voir | Annoter | Télécharger (7,38 ko)
1 | 1 | equemene | subroutine Egrad(E,Geom,Grad,NCoord,IGeom,IOpt,GeomCart) |
---|---|---|---|
2 | 1 | equemene | |
3 | 1 | equemene | ! This routines calculates the energy E and the gradient Grad of |
4 | 1 | equemene | ! a molecule with Geometry Geom (may be in internal coordinates), |
5 | 1 | equemene | ! using for now, either gaussian or Ext, more general later. |
6 | 1 | equemene | |
7 | 1 | equemene | use Path_module, only : Nat,AtName,Coord,dzdc,indzmat,Nom,Atome,massat,unit, & |
8 | 1 | equemene | prog,NCart,XyzGeomF,IntCoordF,XyzGeomI, renum, OrderInv |
9 | 1 | equemene | ! IntCoordF(NGeomF,NCoord),GeomOld_all(NGeomF,NCoord) |
10 | 1 | equemene | ! allocated in Path.f90 |
11 | 1 | equemene | use Io_module |
12 | 1 | equemene | IMPLICIT NONE |
13 | 1 | equemene | |
14 | 1 | equemene | ! Energy (calculated if F300K=.F., else estimated) |
15 | 1 | equemene | REAL(KREAL), INTENT (OUT) :: E |
16 | 1 | equemene | ! NCoord: Number of the degrees of freedom |
17 | 1 | equemene | ! IGeom: index of the geometry. |
18 | 1 | equemene | INTEGER(KINT), INTENT (IN) :: NCoord, IGeom, IOpt |
19 | 1 | equemene | ! Geometry at which gradient is calculated (cf Factual also): |
20 | 1 | equemene | REAL(KREAL), INTENT (INOUT) :: Geom(NCoord) |
21 | 1 | equemene | ! Gradient calculated at Geom geometry: |
22 | 1 | equemene | REAL(KREAL), INTENT (OUT) :: Grad(NCoord) |
23 | 1 | equemene | ! Cartesian geometry corresponding to (Internal Geometry) Geom: |
24 | 1 | equemene | REAL(KREAL), INTENT (OUT) :: GeomCart(Nat,3) |
25 | 1 | equemene | |
26 | 1 | equemene | ! ====================================================================== |
27 | 1 | equemene | |
28 | 1 | equemene | CHARACTER(LCHARS) :: LINE |
29 | 1 | equemene | LOGICAL :: debug |
30 | 1 | equemene | LOGICAL, SAVE :: first=.true. |
31 | 1 | equemene | REAL(KREAL), SAVE :: Eold=1.e6 |
32 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: GradTmp(:) |
33 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: GradCart(:) |
34 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: x(:), y(:), z(:) |
35 | 1 | equemene | REAL(KREAL) :: d, a_val, Pi |
36 | 1 | equemene | |
37 | 1 | equemene | INTEGER(KINT) :: iat,jat,kat,i,j,IBeg,Idx |
38 | 1 | equemene | INTEGER(KINT), PARAMETER :: IOLOG=12, IOCOM=11 |
39 | 1 | equemene | |
40 | 1 | equemene | CHARACTER(LCHARS) :: ListName, CH32SVAR1 |
41 | 1 | equemene | CHARACTER(VLCHARS), SAVE :: RstrtCopy, RunCommand |
42 | 1 | equemene | LOGICAL, SAVE :: FCopyRstrt=.False., FOrderChecked=.False. |
43 | 1 | equemene | LOGICAL :: FTmp |
44 | 1 | equemene | INTEGER(kint) :: NbLists,NStep |
45 | 1 | equemene | INTEGER(KINT), PARAMETER :: NbExtName=4 |
46 | 1 | equemene | |
47 | 1 | equemene | |
48 | 1 | equemene | ! ====================================================================== |
49 | 1 | equemene | INTERFACE |
50 | 1 | equemene | function valid(string) result (isValid) |
51 | 1 | equemene | CHARACTER(*), intent(in) :: string |
52 | 1 | equemene | logical :: isValid |
53 | 1 | equemene | END function VALID |
54 | 1 | equemene | END INTERFACE |
55 | 1 | equemene | ! ====================================================================== |
56 | 1 | equemene | |
57 | 1 | equemene | INTEGER(KINT) :: OptGeom |
58 | 1 | equemene | Namelist/path/OptGeom |
59 | 1 | equemene | |
60 | 1 | equemene | Pi=dacos(-1.0d0) |
61 | 1 | equemene | |
62 | 1 | equemene | debug=valid('EGRAD') |
63 | 1 | equemene | if (debug) Call header("Entering Egrad") |
64 | 1 | equemene | |
65 | 1 | equemene | Print *, 'EGrad.f90, L73, IOpt=', IOpt |
66 | 1 | equemene | |
67 | 1 | equemene | Grad=0. |
68 | 1 | equemene | E=0. |
69 | 1 | equemene | |
70 | 1 | equemene | ALLOCATE(GradCart(3*Nat)) |
71 | 1 | equemene | ALLOCATE(x(Nat),y(Nat),z(Nat)) |
72 | 1 | equemene | SELECT CASE (COORD) |
73 | 1 | equemene | CASE ('ZMAT') |
74 | 1 | equemene | ! In order to avoid problem with numbering and linear angles/diehedral, we convert the |
75 | 1 | equemene | ! zmat into cartesian coordinates |
76 | 1 | equemene | ! A remplacer par Int2Cart :-) |
77 | 1 | equemene | Call Int2Cart(nat,indzmat,Geom,GeomCart) |
78 | 1 | equemene | CASE ('BAKER') |
79 | 1 | equemene | WRITE (*,*) "Coord=",TRIM(COORD),": use Egrad_baker.f90, instead of Egrad.f90. Stop" |
80 | 1 | equemene | CASE ('MIXED') |
81 | 1 | equemene | ! write(*,*) "Coucou 4-mixed" |
82 | 1 | equemene | Call Mixed2Cart(Nat,indzmat,geom,GeomCart) |
83 | 1 | equemene | CASE ('CART') |
84 | 1 | equemene | ! write(*,*) "Coucou 4-cart" |
85 | 1 | equemene | if (debug) WRITE(*,*) "Coord=CART... in egrad" |
86 | 1 | equemene | GeomCart=reshape(Geom,(/Nat,3/)) |
87 | 1 | equemene | DO Iat=1,Nat |
88 | 1 | equemene | WRITE(IOTMP,'(1X,A10,3(1X,F15.8),A)') Trim(AtName(Iat)),Geom(3*Iat-2:3*Iat) |
89 | 1 | equemene | END DO |
90 | 1 | equemene | CASE ('HYBRID') |
91 | 1 | equemene | ! write(*,*) "Coucou 4-hybrid" |
92 | 1 | equemene | GeomCart=reshape(Geom,(/Nat,3/)) |
93 | 1 | equemene | CASE DEFAULT |
94 | 1 | equemene | WRITE (*,*) "Coord=",TRIM(COORD)," not recognized. Stop" |
95 | 1 | equemene | STOP |
96 | 1 | equemene | END SELECT |
97 | 1 | equemene | |
98 | 1 | equemene | SELECT CASE (Prog) |
99 | 1 | equemene | CASE ('GAUSSIAN') |
100 | 1 | equemene | ! we call the Gaussian routine. |
101 | 1 | equemene | ! it will return the energy and the gradient in cartesian coordinates. |
102 | 1 | equemene | ! Gradient calculated at GeomCart geometry and stored in GradCart, which has INTENT(OUT) |
103 | 1 | equemene | Call egrad_gaussian(E,GeomCart,GradCart) |
104 | 1 | equemene | CASE ('MOPAC') |
105 | 1 | equemene | ! we call the Mopac routine. |
106 | 1 | equemene | ! it will return the energy and the gradient in cartesian coordinates. |
107 | 1 | equemene | ! Gradient calculated at GeomCart geometry and stored in GradCart, which has INTENT(OUT) |
108 | 1 | equemene | Call egrad_mopac(E,GeomCart,GradCart) |
109 | 1 | equemene | CASE ('VASP') |
110 | 1 | equemene | Call egrad_vasp(E,Geomcart,GradCart) |
111 | 1 | equemene | CASE ('TURBOMOLE') |
112 | 1 | equemene | Call egrad_turbomole(E,Geomcart,GradCart) |
113 | 1 | equemene | CASE ('EXT') |
114 | 1 | equemene | Call egrad_ext(E,Geomcart,GradCart) |
115 | 1 | equemene | CASE ('TEST') |
116 | 1 | equemene | Call egrad_test(Nat,E,Geomcart,GradCart) |
117 | 1 | equemene | CASE ('CHAMFRE') |
118 | 1 | equemene | Call egrad_chamfre(Nat,E,Geomcart,GradCart) |
119 | 1 | equemene | END SELECT |
120 | 1 | equemene | if (debug) THEN |
121 | 1 | equemene | WRITE(*,*) 'DBG EGRAD, GradCart read' |
122 | 1 | equemene | DO I=1,Nat |
123 | 1 | equemene | Iat=I |
124 | 1 | equemene | if (renum) Iat=orderInv(I) |
125 | 1 | equemene | WRITE(*,'(1X,A10,3(1X,F15.8),A)') Trim(AtName(Iat)),GradCart(3*I-2:3*I) |
126 | 1 | equemene | END DO |
127 | 1 | equemene | END IF |
128 | 1 | equemene | |
129 | 1 | equemene | ! If (PROG=="VASP") STOP |
130 | 1 | equemene | |
131 | 1 | equemene | ! We have the gradient in Cartesian coordinates... which is ok for COORD=Cart, Hybrid |
132 | 1 | equemene | ! but we have to convert it into Zmat if COORD=Zmat |
133 | 1 | equemene | SELECT CASE (COORD) |
134 | 1 | equemene | CASE ("ZMAT") |
135 | 1 | equemene | ALLOCATE(GradTmp(3*Nat)) |
136 | 1 | equemene | if (debug) WRITE(*,*) "DBG EGRAD Calling CalcBMat_int" |
137 | 1 | equemene | CALL CalcBMat_int (nat, reshape(GeomCart,(/3,Nat/),ORDER=(/2,1/)), indzmat, dzdc, massat,atome) |
138 | 1 | equemene | |
139 | 1 | equemene | if (debug) WRITE(*,*) "DBG EGRAD Calling ConvGrad_Cart2Int" |
140 | 1 | equemene | CALL ConvGrad_Cart2Int(Nat,dzdc,IndZmat,GradCart,GradTmp) |
141 | 1 | equemene | |
142 | 1 | equemene | if (debug) WRITE(*,*) "DBG EGRAD Storing Grad" |
143 | 1 | equemene | Grad(1)=GradTmp(4) |
144 | 1 | equemene | Grad(2)=GradTmp(7) |
145 | 1 | equemene | ! We might have troubles whith angles that are not in the [0:pi] range because, |
146 | 1 | equemene | ! when converted to catesian coord, they do appear in the [0:Pi] range to gaussian... |
147 | 1 | equemene | ! so that the derivative is not good, and a multiplicative factor should be added... |
148 | 1 | equemene | ! |
149 | 1 | equemene | ! This in fact should be taken care of in B mat calculation... |
150 | 1 | equemene | ! |
151 | 1 | equemene | IF ((Geom(3).LE.0).OR.(Geom(3).GE.Pi)) THEN |
152 | 1 | equemene | Grad(3)=-1.0d0*GradTmp(8) |
153 | 1 | equemene | ELSE |
154 | 1 | equemene | Grad(3)=GradTmp(8) |
155 | 1 | equemene | END IF |
156 | 1 | equemene | Idx=4 |
157 | 1 | equemene | DO I=4,Nat |
158 | 1 | equemene | Grad(Idx)=GradTmp(3*i-2) |
159 | 1 | equemene | Grad(Idx+1)=GradTmp(3*i-1) |
160 | 1 | equemene | Grad(Idx+2)=GradTmp(3*i) |
161 | 1 | equemene | Idx=Idx+3 |
162 | 1 | equemene | END DO |
163 | 1 | equemene | DEALLOCATE(GradTmp) |
164 | 1 | equemene | CASE ('BAKER') |
165 | 1 | equemene | WRITE (*,*) "Coord=",TRIM(COORD),": use Egrad_baker.f90, instead of Egrad.f90. Stop" |
166 | 1 | equemene | CASE ('MIXED') |
167 | 1 | equemene | ALLOCATE(GradTmp(3*Nat)) |
168 | 1 | equemene | if (debug) WRITE(*,*) "DBG EGRAD Calling CalcBMat_mixed" |
169 | 1 | equemene | CALL CalcBMat_mixed (nat, reshape(GeomCart,(/3,Nat/),ORDER=(/2,1/)), indzmat, dzdc, massat,atome) |
170 | 1 | equemene | |
171 | 1 | equemene | if (Debug) THEN |
172 | 1 | equemene | WRITE(*,*) "DzDc" |
173 | 1 | equemene | DO I=1,Nat |
174 | 1 | equemene | DO J=1,3 |
175 | 1 | equemene | WRITE(*,'(50(1X,F12.6))') dzdc(J,I,:,:) |
176 | 1 | equemene | END DO |
177 | 1 | equemene | END DO |
178 | 1 | equemene | END IF |
179 | 1 | equemene | |
180 | 1 | equemene | |
181 | 1 | equemene | CALL ConvGrad_Cart2Int(Nat,dzdc,IndZmat,GradCart,GradTmp) |
182 | 1 | equemene | DO I=1,Nat |
183 | 1 | equemene | WRITE(*,'(1X,3(1X,F10.5))') GradTmp(3*I-2:3*I) |
184 | 1 | equemene | END DO |
185 | 1 | equemene | SELECT CASE (NCART) |
186 | 1 | equemene | CASE (1) |
187 | 1 | equemene | Grad(1:3)=GradTmp(1:3) |
188 | 1 | equemene | Grad(4)=GradTmp(4) |
189 | 1 | equemene | Grad(5)=GradTmp(7) |
190 | 1 | equemene | Grad(6)=GradTmp(8) |
191 | 1 | equemene | Idx=7 |
192 | 1 | equemene | IBeg=4 |
193 | 1 | equemene | CASE(2) |
194 | 1 | equemene | Grad(1:3)=GradTmp(1:3) |
195 | 1 | equemene | Grad(4:6)=GradTmp(4:6) |
196 | 1 | equemene | Grad(7)=GradTmp(7) |
197 | 1 | equemene | Grad(8)=GradTmp(8) |
198 | 1 | equemene | Idx=9 |
199 | 1 | equemene | IBeg=4 |
200 | 1 | equemene | CASE DEFAULT |
201 | 1 | equemene | Idx=1 |
202 | 1 | equemene | IBeg=1 |
203 | 1 | equemene | END SELECT |
204 | 1 | equemene | DO I=IBeg,Nat |
205 | 1 | equemene | Grad(Idx)=GradTmp(3*i-2) |
206 | 1 | equemene | Grad(Idx+1)=GradTmp(3*i-1) |
207 | 1 | equemene | Grad(Idx+2)=GradTmp(3*i) |
208 | 1 | equemene | Idx=Idx+3 |
209 | 1 | equemene | END DO |
210 | 1 | equemene | DEALLOCATE(GradTmp) |
211 | 1 | equemene | CASE ("CART","HYBRID") |
212 | 1 | equemene | Grad=GradCart |
213 | 1 | equemene | CASE DEFAULT |
214 | 1 | equemene | WRITE(*,*) "Coord=",AdjustL(Trim(COORD))," not yet implemented in Egradients. STOP" |
215 | 1 | equemene | STOP |
216 | 1 | equemene | END SELECT |
217 | 1 | equemene | |
218 | 1 | equemene | DEALLOCATE(GradCart) |
219 | 1 | equemene | DEALLOCATE(x,y,z) |
220 | 1 | equemene | |
221 | 1 | equemene | IF (Debug) WRITE(*,*) 'DBG EGRAD grad',grad(1:NCoord) |
222 | 1 | equemene | if (debug) Call Header("Egrad Over") |
223 | 1 | equemene | |
224 | 1 | equemene | !999 CONTINUE |
225 | 1 | equemene | !if (.NOT.Ftmp) WRITE(*,*) 'We should not be here !!!!' |
226 | 1 | equemene | !STOP |
227 | 1 | equemene | ! ====================================================================== |
228 | 1 | equemene | end subroutine Egrad |