root / src / CheckPeriodicBound.f90 @ 12
Historique | Voir | Annoter | Télécharger (7,55 ko)
1 | 10 | pfleura2 | SUBROUTINE CheckPeriodicBound |
---|---|---|---|
2 | 10 | pfleura2 | ! This subroutine is only for periodic systems |
3 | 10 | pfleura2 | ! it checks that the atoms do not change their |
4 | 10 | pfleura2 | ! positions from one side to the other during the simulations. |
5 | 10 | pfleura2 | ! This would ruin the interpolation. |
6 | 1 | pfleura2 | |
7 | 1 | pfleura2 | |
8 | 12 | pfleura2 | !---------------------------------------------------------------------- |
9 | 12 | pfleura2 | ! Copyright 2003-2014 Ecole Normale Supérieure de Lyon, |
10 | 12 | pfleura2 | ! Centre National de la Recherche Scientifique, |
11 | 12 | pfleura2 | ! Université Claude Bernard Lyon 1. All rights reserved. |
12 | 12 | pfleura2 | ! |
13 | 12 | pfleura2 | ! This work is registered with the Agency for the Protection of Programs |
14 | 12 | pfleura2 | ! as IDDN.FR.001.100009.000.S.P.2014.000.30625 |
15 | 12 | pfleura2 | ! |
16 | 12 | pfleura2 | ! Authors: P. Fleurat-Lessard, P. Dayal |
17 | 12 | pfleura2 | ! Contact: optnpath@gmail.com |
18 | 12 | pfleura2 | ! |
19 | 12 | pfleura2 | ! This file is part of "Opt'n Path". |
20 | 12 | pfleura2 | ! |
21 | 12 | pfleura2 | ! "Opt'n Path" is free software: you can redistribute it and/or modify |
22 | 12 | pfleura2 | ! it under the terms of the GNU Affero General Public License as |
23 | 12 | pfleura2 | ! published by the Free Software Foundation, either version 3 of the License, |
24 | 12 | pfleura2 | ! or (at your option) any later version. |
25 | 12 | pfleura2 | ! |
26 | 12 | pfleura2 | ! "Opt'n Path" is distributed in the hope that it will be useful, |
27 | 12 | pfleura2 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of |
28 | 12 | pfleura2 | ! |
29 | 12 | pfleura2 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
30 | 12 | pfleura2 | ! GNU Affero General Public License for more details. |
31 | 12 | pfleura2 | ! |
32 | 12 | pfleura2 | ! You should have received a copy of the GNU Affero General Public License |
33 | 12 | pfleura2 | ! along with "Opt'n Path". If not, see <http://www.gnu.org/licenses/>. |
34 | 12 | pfleura2 | ! |
35 | 12 | pfleura2 | ! Contact The Office of Technology Licensing, valorisation@ens-lyon.fr, |
36 | 12 | pfleura2 | ! for commercial licensing opportunities. |
37 | 12 | pfleura2 | !---------------------------------------------------------------------- |
38 | 12 | pfleura2 | |
39 | 1 | pfleura2 | Use Path_module |
40 | 1 | pfleura2 | Use Io_module |
41 | 1 | pfleura2 | |
42 | 1 | pfleura2 | IMPLICIT NONE |
43 | 1 | pfleura2 | |
44 | 1 | pfleura2 | |
45 | 1 | pfleura2 | INTEGER(KINT) :: IGeom, I,J,K |
46 | 1 | pfleura2 | REAL(KREAL), ALLOCATABLE :: GeomRef(:,:), GeomTmp(:,:) ! (3,Nat) |
47 | 1 | pfleura2 | |
48 | 1 | pfleura2 | REAL(KREAL) :: Latrloc(3,3),Bloc(3),Xt,Yt,Zt |
49 | 12 | pfleura2 | REAL(KREAL) :: NormA, NormB,Xrel,Yrel |
50 | 10 | pfleura2 | REAL(KREAL) :: Prod,LatrA(3),LatrB(3) |
51 | 10 | pfleura2 | REAL(KREAL) :: V(3) |
52 | 10 | pfleura2 | |
53 | 1 | pfleura2 | LOGICAL :: Debug |
54 | 1 | pfleura2 | |
55 | 1 | pfleura2 | INTERFACE |
56 | 1 | pfleura2 | function valid(string) result (isValid) |
57 | 1 | pfleura2 | CHARACTER(*), intent(in) :: string |
58 | 1 | pfleura2 | logical :: isValid |
59 | 1 | pfleura2 | END function VALID |
60 | 10 | pfleura2 | |
61 | 10 | pfleura2 | |
62 | 10 | pfleura2 | SUBROUTINE die(routine, msg, file, line, unit) |
63 | 10 | pfleura2 | |
64 | 10 | pfleura2 | Use VarTypes |
65 | 10 | pfleura2 | Use io_module |
66 | 10 | pfleura2 | |
67 | 10 | pfleura2 | implicit none |
68 | 10 | pfleura2 | character(len=*), intent(in) :: routine, msg |
69 | 10 | pfleura2 | character(len=*), intent(in), optional :: file |
70 | 10 | pfleura2 | integer(KINT), intent(in), optional :: line, unit |
71 | 10 | pfleura2 | |
72 | 10 | pfleura2 | END SUBROUTINE die |
73 | 10 | pfleura2 | |
74 | 1 | pfleura2 | END INTERFACE |
75 | 1 | pfleura2 | |
76 | 1 | pfleura2 | debug=valid('checkperiodicbound') |
77 | 10 | pfleura2 | if (debug) call header("Entering CheckPeriodicBound") |
78 | 1 | pfleura2 | |
79 | 1 | pfleura2 | ALLOCATE(GeomRef(3,Nat), GeomTmp(3,Nat)) |
80 | 1 | pfleura2 | |
81 | 10 | pfleura2 | ! The test is easy in DIRECT space, so we will convert the geometries |
82 | 10 | pfleura2 | ! into this space. |
83 | 1 | pfleura2 | |
84 | 10 | pfleura2 | SELECT CASE (Iper) |
85 | 10 | pfleura2 | CASE(1) |
86 | 10 | pfleura2 | NormA=DOT_PRODUCT(Lat_a,Lat_a) |
87 | 10 | pfleura2 | DO IGeom=2,NGeomI |
88 | 10 | pfleura2 | DO I=1,NAt |
89 | 10 | pfleura2 | DO J=1,3 |
90 | 10 | pfleura2 | v(J)=XyzGeomI(IGeom,J,I)-XyzGeomI(1,J,I) |
91 | 10 | pfleura2 | END DO |
92 | 10 | pfleura2 | XRel=DOT_PRODUCT(Lat_a,v)/NormA |
93 | 10 | pfleura2 | if (abs(Xrel).GE.BoxTol) THEN |
94 | 10 | pfleura2 | If (debug) THEN |
95 | 10 | pfleura2 | WRITE(*,'("Atom ",I5," moved because XRel=",F10.6)') I,XRel |
96 | 10 | pfleura2 | WRITE(*,'("Ref: ",3(1X,F10.6))') XyzGeomI(1,1:3,I) |
97 | 10 | pfleura2 | WRITE(*,'("Old: ",3(1X,F10.6))') XyzGeomI(IGeom,1:3,I) |
98 | 10 | pfleura2 | WRITE(*,'("New: ",3(1X,F10.6))') XyzGeomI(IGeom,1:3,I)-Lat_a*Sign(1.0d0,XRel) |
99 | 10 | pfleura2 | END IF |
100 | 10 | pfleura2 | XyzGeomI(IGeom,1:3,I)=XyzGeomI(IGeom,1:3,I)-Lat_a*Sign(1.0d0,XRel) |
101 | 10 | pfleura2 | END IF |
102 | 10 | pfleura2 | END DO |
103 | 10 | pfleura2 | END DO |
104 | 10 | pfleura2 | CASE (2) |
105 | 10 | pfleura2 | NormA=DOT_PRODUCT(Lat_a,Lat_a) |
106 | 10 | pfleura2 | NormB=DOT_PRODUCT(Lat_b,Lat_b) |
107 | 10 | pfleura2 | Prod=DOT_PRODUCT(Lat_a,Lat_b) |
108 | 10 | pfleura2 | LatrA=(NormB*Lat_a-Prod*Lat_b)/(NormA*NormB-Prod**2) |
109 | 10 | pfleura2 | LatrB=(NormA*Lat_b-Prod*Lat_a)/(NormA*NormB-Prod**2) |
110 | 1 | pfleura2 | |
111 | 10 | pfleura2 | DO IGeom=2,NGeomI |
112 | 10 | pfleura2 | DO I=1,NAt |
113 | 10 | pfleura2 | DO J=1,3 |
114 | 10 | pfleura2 | v(J)=XyzGeomI(IGeom,J,I)-XyzGeomI(1,J,I) |
115 | 10 | pfleura2 | END DO |
116 | 10 | pfleura2 | XRel=DOT_PRODUCT(Latra,v) |
117 | 10 | pfleura2 | YRel=DOT_PRODUCT(Latrb,v) |
118 | 10 | pfleura2 | if (abs(Xrel).GE.BoxTol) THEN |
119 | 10 | pfleura2 | If (debug) THEN |
120 | 10 | pfleura2 | WRITE(*,'("Atom ",I5," moved because XRel=",F10.6)') I,XRel |
121 | 10 | pfleura2 | WRITE(*,'("Ref: ",3(1X,F10.6))') XyzGeomI(1,1:3,I) |
122 | 10 | pfleura2 | WRITE(*,'("Old: ",3(1X,F10.6))') XyzGeomI(IGeom,1:3,I) |
123 | 10 | pfleura2 | WRITE(*,'("New: ",3(1X,F10.6))') XyzGeomI(IGeom,1:3,I)-Latra*Sign(1.0d0,XRel) |
124 | 10 | pfleura2 | END IF |
125 | 10 | pfleura2 | XyzGeomI(IGeom,1:3,I)=XyzGeomI(IGeom,1:3,I)-Latra*Sign(1.0d0,XRel) |
126 | 10 | pfleura2 | END IF |
127 | 10 | pfleura2 | if (abs(Yrel).GE.BoxTol) THEN |
128 | 10 | pfleura2 | If (debug) THEN |
129 | 10 | pfleura2 | WRITE(*,'("Atom ",I5," moved because YRel=",F10.6)') I,YRel |
130 | 10 | pfleura2 | WRITE(*,'("Ref: ",3(1X,F10.6))') XyzGeomI(1,1:3,I) |
131 | 10 | pfleura2 | WRITE(*,'("Old: ",3(1X,F10.6))') XyzGeomI(IGeom,1:3,I) |
132 | 10 | pfleura2 | WRITE(*,'("New: ",3(1X,F10.6))') XyzGeomI(IGeom,1:3,I)-Latrb*Sign(1.0d0,YRel) |
133 | 10 | pfleura2 | END IF |
134 | 10 | pfleura2 | XyzGeomI(IGeom,1:3,I)=XyzGeomI(IGeom,1:3,I)-Latrb*Sign(1.0d0,YRel) |
135 | 10 | pfleura2 | END IF |
136 | 10 | pfleura2 | END DO |
137 | 10 | pfleura2 | END DO |
138 | 10 | pfleura2 | |
139 | 10 | pfleura2 | CASE(3) |
140 | 10 | pfleura2 | |
141 | 10 | pfleura2 | |
142 | 10 | pfleura2 | |
143 | 10 | pfleura2 | ! if (debug) THEN |
144 | 10 | pfleura2 | ! WRITE(*,'(1X,A,3(1X,F10.6))') "Lat_a:",Lat_a |
145 | 10 | pfleura2 | ! WRITE(*,'(1X,A,3(1X,F10.6))') "Lat_b:",Lat_b |
146 | 10 | pfleura2 | ! WRITE(*,'(1X,A,3(1X,F10.6))') "Lat_c:",Lat_c |
147 | 10 | pfleura2 | ! WRITE(*,'(1X,A,3(1X,F10.6))') "BocTol:",BoxTol |
148 | 10 | pfleura2 | |
149 | 10 | pfleura2 | ! NormA=DOT_PRODUCT(Lat_a,Lat_a) |
150 | 10 | pfleura2 | ! NormB=DOT_PRODUCT(Lat_b,Lat_b) |
151 | 10 | pfleura2 | ! Prod=DOT_PRODUCT(Lat_a,Lat_b) |
152 | 10 | pfleura2 | ! LatrA=(NormB*Lat_a-Prod*Lat_b)/(NormA*NormB-Prod**2) |
153 | 10 | pfleura2 | ! LatrB=(NormA*Lat_b-Prod*Lat_a)/(NormA*NormB-Prod**2) |
154 | 10 | pfleura2 | ! ! NormA=DOT_PRODUCT(Latra,Latra) |
155 | 10 | pfleura2 | ! ! NormB=DOT_PRODUCT(Latrb,Latrb) |
156 | 10 | pfleura2 | |
157 | 10 | pfleura2 | ! DO IGeom=2,NGeomI |
158 | 10 | pfleura2 | ! DO I=1,NAt |
159 | 10 | pfleura2 | ! DO J=1,3 |
160 | 10 | pfleura2 | ! v(J)=XyzGeomI(IGeom,J,I)-XyzGeomI(1,J,I) |
161 | 10 | pfleura2 | ! END DO |
162 | 10 | pfleura2 | ! XRel=DOT_PRODUCT(Latra,v) |
163 | 10 | pfleura2 | ! YRel=DOT_PRODUCT(Latrb,v) |
164 | 10 | pfleura2 | ! If (abs(XRel).GT.BoxTol) WRITE(*,*) "Xrel too big:",IGeom,I,Xrel |
165 | 10 | pfleura2 | ! If (abs(YRel).GT.BoxTol) WRITE(*,*) "Yrel too big:",IGeom,I,Yrel |
166 | 10 | pfleura2 | ! ! WRITE(*,*) "Xrel :",IGeom,I,Xrel |
167 | 10 | pfleura2 | ! ! WRITE(*,*) "Yrel :",IGeom,I,Yrel |
168 | 10 | pfleura2 | ! ! WRITE(*,*) "Zrel :",IGeom,I,Zrel |
169 | 10 | pfleura2 | |
170 | 10 | pfleura2 | ! END DO |
171 | 10 | pfleura2 | ! END DO |
172 | 10 | pfleura2 | ! END IF |
173 | 10 | pfleura2 | |
174 | 1 | pfleura2 | Latrloc(1:3,1)=Lat_a |
175 | 1 | pfleura2 | Latrloc(1:3,2)=Lat_b |
176 | 1 | pfleura2 | Latrloc(1:3,3)=Lat_c |
177 | 1 | pfleura2 | Bloc=1. |
178 | 10 | pfleura2 | ! TODO: Replace by LAPACK subroutine |
179 | 1 | pfleura2 | CALL Gaussj(Latrloc,3,3,Bloc,1,1) |
180 | 1 | pfleura2 | |
181 | 10 | pfleura2 | ! We put first geometry as the reference |
182 | 1 | pfleura2 | GeomRef=0. |
183 | 1 | pfleura2 | DO I=1,Nat |
184 | 1 | pfleura2 | DO K=1,3 |
185 | 1 | pfleura2 | DO J=1,3 |
186 | 1 | pfleura2 | GeomRef(K,I)=GeomRef(K,I)+XyzGeomI(1,J,I)*LatrLoc(K,J) |
187 | 1 | pfleura2 | END DO |
188 | 1 | pfleura2 | END DO |
189 | 1 | pfleura2 | END DO |
190 | 1 | pfleura2 | |
191 | 10 | pfleura2 | DO IGeom=2,NGeomI |
192 | 10 | pfleura2 | GeomTmp=0. |
193 | 10 | pfleura2 | DO I=1,Nat |
194 | 10 | pfleura2 | DO K=1,3 |
195 | 10 | pfleura2 | DO J=1,3 |
196 | 10 | pfleura2 | GeomTmp(K,I)=GeomTmp(K,I)+XyzGeomI(IGeom,J,I)*LatrLoc(K,J) |
197 | 10 | pfleura2 | END DO |
198 | 10 | pfleura2 | if (abs(GeomTmp(K,I)-GeomRef(K,I)).GE.BoxTol) THEN |
199 | 10 | pfleura2 | If (debug) & |
200 | 10 | pfleura2 | WRITE(*,'("Coord ",I1," has been changed for atom ",I5," by ",F4.0," ref:",F9.6," old:",F9.6," new:",F9.6)') & |
201 | 10 | pfleura2 | K,I,Sign(1.d0,GeomRef(K,I)-GeomTmp(K,I)),& |
202 | 10 | pfleura2 | GeomRef(K,I),GeomTmp(K,I), & |
203 | 10 | pfleura2 | GeomTmp(K,I)+Sign(1.d0,GeomRef(K,I)-GeomTmp(K,I)) |
204 | 10 | pfleura2 | |
205 | 10 | pfleura2 | GeomTmp(K,I)=GeomTmp(K,I)+Sign(1.d0,GeomRef(K,I)-GeomTmp(K,I)) |
206 | 10 | pfleura2 | END IF |
207 | 1 | pfleura2 | END DO |
208 | 10 | pfleura2 | Xt=GeomTmp(1,I) |
209 | 10 | pfleura2 | Yt=GeomTmp(2,I) |
210 | 10 | pfleura2 | Zt=GeomTmp(3,I) |
211 | 10 | pfleura2 | XyzGeomI(IGeom,1,I)=Xt*lat_a(1)+Yt*lat_b(1)+Zt*lat_c(1) |
212 | 10 | pfleura2 | XyzGeomI(IGeom,2,I)=Xt*lat_a(2)+Yt*lat_b(2)+Zt*lat_c(2) |
213 | 10 | pfleura2 | XyzGeomI(IGeom,3,I)=Xt*lat_a(3)+Yt*lat_b(3)+Zt*lat_c(3) |
214 | 1 | pfleura2 | END DO |
215 | 1 | pfleura2 | END DO |
216 | 1 | pfleura2 | |
217 | 10 | pfleura2 | CASE DEFAULT |
218 | 10 | pfleura2 | Call Die("CheckPeriodicBound"," Iper unknown") |
219 | 10 | pfleura2 | END SELECT |
220 | 10 | pfleura2 | |
221 | 10 | pfleura2 | |
222 | 10 | pfleura2 | if (debug) WRITE(*,*) "========================= Exiting CheckPeriodicBound ===========" |
223 | 1 | pfleura2 | END SUBROUTINE CheckPeriodicBound |
224 | 1 | pfleura2 | |
225 | 1 | pfleura2 | |
226 | 1 | pfleura2 | |
227 | 1 | pfleura2 | |
228 | 1 | pfleura2 |