Statistiques
| Révision :

root / src / CheckPeriodicBound.f90

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