Statistiques
| Révision :

root / src / Calc_baker_allGeomF.f90 @ 7

Historique | Voir | Annoter | Télécharger (9,76 ko)

1
SUBROUTINE Calc_baker_allGeomF()
2
  !     
3
  ! This subroutine analyses a geometry to construct the baker
4
  ! delocalized internal coordinates
5
  ! v1.0
6
  ! We use only one geometry
7
  !     
8
  Use Path_module, only : Pi,a0,BMat_BakerT,Nat,NCoord,XyzGeomI,NGeomI,UMatF, &
9
                          NPrim,BTransInvF,IntCoordI,Coordinate,CurrentCoord, &
10
              ScanCoord,BprimT,BBT,BBT_inv,XprimitiveF,Symmetry_elimination, &
11
              NgeomF,XyzGeomF
12
  ! BMat_BakerT(3*Nat,NCoord), NCoord=3*Nat or NFree=3*Nat-6-Symmetry_elimination
13
  ! depending upon the coordinate choice. IntCoordI(NGeomI,NCoord) where 
14
  ! UMatF(NGeomI,NPrim,NCoord), NCoord number of vectors in UMat matrix, i.e. NCoord
15
  ! Baker coordinates. NPrim is the number of primitive internal coordinates.
16
  
17
  Use Io_module
18
  IMPLICIT NONE
19

    
20
  REAL(KREAL), ALLOCATABLE :: Geom(:,:) !(3,Nat)
21
  ! NPrim is the number of primitive coordinates and NCoord is the number
22
  ! of internal coordinates. BMat is actually (NPrim,3*Nat).
23
  REAL(KREAL), ALLOCATABLE :: GMat(:,:) !(NPrim,NPrim)
24
  ! EigVec(..) contains ALL eigevectors of BMat times BprimT, NOT only Baker Coordinate vectors.
25
  REAL(KREAL), ALLOCATABLE :: EigVec(:,:), EigVal(:) ! EigVec(NPrim,NPrim)
26
  REAL(KREAL), ALLOCATABLE :: x(:), y(:), z(:)
27
  REAL(KREAL), ALLOCATABLE :: XPrimRef(:) ! NPrim
28
  INTEGER(KINT) :: IGeom
29
  
30
  real(KREAL) ::  vx,vy,vz,dist, Norm
31
  real(KREAL) ::  vx1,vy1,vz1,norm1
32
  real(KREAL) ::  vx2,vy2,vz2,norm2
33
  real(KREAL) ::  vx3,vy3,vz3,norm3
34
  real(KREAL) ::  vx4,vy4,vz4,norm4
35
  real(KREAL) ::  vx5,vy5,vz5,norm5
36
  real(KREAL) ::  val,val_d, Q, T
37

    
38
  INTEGER(KINT) :: I,J, n1,n2,n3,n4,IAt,IL,JL,IFrag,ITmp, K, KMax
39
  INTEGER(KINT) :: I0, IOld, IAtTmp, Izm, JAt, Kat, Lat, L, NOUT
40

    
41
  REAL(KREAL) :: sAngleIatIKat, sAngleIIatLat
42
  REAL(KREAL) :: DiheTmp
43

    
44
  LOGICAL :: debug, bond, AddPrimitiveCoord, FAIL
45
  LOGICAL :: DebugPFL
46

    
47
  INTERFACE
48
     function valid(string) result (isValid)
49
       CHARACTER(*), intent(in) :: string
50
       logical                  :: isValid
51
     END function VALID
52

    
53
     FUNCTION angle(v1x,v1y,v1z,norm1,v2x,v2y,v2z,norm2)
54
       use Path_module, only :  Pi,KINT, KREAL
55
       real(KREAL) ::  v1x,v1y,v1z,norm1
56
       real(KREAL) ::  v2x,v2y,v2z,norm2
57
       real(KREAL) ::  angle
58
     END FUNCTION ANGLE
59

    
60
     FUNCTION angle_d(v1x,v1y,v1z,norm1,v2x,v2y,v2z,norm2,v3x,v3y,v3z,norm3)
61
       use Path_module, only :  Pi,KINT, KREAL
62
       real(KREAL) ::  v1x,v1y,v1z,norm1
63
       real(KREAL) ::  v2x,v2y,v2z,norm2
64
       real(KREAL) ::  v3x,v3y,v3z,norm3
65
       real(KREAL) ::  angle_d,ca,sa
66
     END FUNCTION ANGLE_D
67

    
68

    
69

    
70
     SUBROUTINE Calc_Xprim(nat,x,y,z,Coordinate,NPrim,XPrimitive,XPrimRef)
71
       !     
72
       ! This subroutine uses the description of a list of Coordinates
73
       ! to compute the values of the coordinates for a given geometry.
74
       !
75
!!!!!!!!!!
76
       ! Input:
77
       !   Na: INTEGER, Number of atoms
78
       !  x,y,z(Na): REAL, cartesian coordinates of the considered geometry
79
       ! Coordinate (Pointer(ListCoord)): description of the wanted coordiantes
80
       ! NPrim, INTEGER: Number of coordinates to compute
81
       !
82
       ! Optional: XPrimRef(NPrim) REAL: array that contains coordinates values for
83
       ! a former geometry. Useful for Dihedral angles evolution...
84

    
85
!!!!!!!!!!!
86
       ! Output:
87
       ! XPrimimite(NPrim) REAL: array that will contain the values of the coordinates
88
       !
89
!!!!!!!!!
90

    
91
       Use VarTypes
92
       Use Io_module
93
       Use Path_module, only : pi
94

    
95
       IMPLICIT NONE
96

    
97
       Type (ListCoord), POINTER :: Coordinate
98
       INTEGER(KINT), INTENT(IN) :: Nat,NPrim
99
       REAL(KREAL), INTENT(IN) :: x(Nat), y(Nat), z(Nat)
100
       REAL(KREAL), INTENT(IN), OPTIONAL :: XPrimRef(NPrim) 
101
       REAL(KREAL), INTENT(OUT) :: XPrimitive(NPrim)
102

    
103
     END SUBROUTINE CALC_XPRIM
104
  END INTERFACE
105

    
106

    
107

    
108

    
109
  debug=valid("Calc_baker_allGeomF")
110
  debugPFL=valid("bakerPFL")
111
  if (debug) WRITE(*,*) '============ Entering Calc_baker_allGeomF ============='
112

    
113
  ALLOCATE(Geom(3,Nat),x(Nat),y(Nat),z(Nat))
114
  ALLOCATE(XPrimRef(NPrim))
115
 
116
  ! Now calculating values of all primitive bonds for all final geometries:
117
  DO IGeom=1, NGeomF
118
     x(1:Nat) = XyzGeomF(IGeom,1,1:Nat)
119
     y(1:Nat) = XyzGeomF(IGeom,2,1:Nat)
120
     z(1:Nat) = XyzGeomF(IGeom,3,1:Nat)
121
     XPrimREf=XPrimitiveF(IGeom,:)
122
     Call Calc_XPrim(nat,x,y,z,Coordinate,NPrim,XPrimitiveF(IGeom,:),XPrimRef)
123
!    ScanCoord=>Coordinate
124
!    I=0 ! index for the NPrim (NPrim is the number of primitive coordinates).
125
!    DO WHILE (Associated(ScanCoord%next))
126
!      I=I+1
127
!      SELECT CASE (ScanCoord%Type)
128
!       CASE ('BOND')
129
!       Call vecteur(ScanCoord%At2,ScanCoord%At1,x,y,z,vx2,vy2,vz2,Norm2)
130
!            XprimitiveF(IGeom,I) = Norm2  
131
!       CASE ('ANGLE')
132
!     Call vecteur(ScanCoord%At2,ScanCoord%At3,x,y,z,vx1,vy1,vz1,Norm1)
133
!     Call vecteur(ScanCoord%At2,ScanCoord%At1,x,y,z,vx2,vy2,vz2,Norm2)
134
!          XprimitiveF(IGeom,I) = angle(vx1,vy1,vz1,Norm1,vx2,vy2,vz2,Norm2)*Pi/180.
135
!     CASE ('DIHEDRAL')
136
!     Call vecteur(ScanCoord%At3,ScanCoord%At2,x,y,z,vx2,vy2,vz2,Norm2)
137
!     Call vecteur(ScanCoord%At2,ScanCoord%At1,x,y,z,vx1,vy1,vz1,Norm1)
138
!     Call vecteur(ScanCoord%At3,ScanCoord%At4,x,y,z,vx3,vy3,vz3,Norm3)
139
!     Call produit_vect(vx3,vy3,vz3,norm3,vx2,vy2,vz2,norm2, &
140
!                         vx5,vy5,vz5,norm5)
141
!     Call produit_vect(vx1,vy1,vz1,norm1,vx2,vy2,vz2,norm2, &
142
!                         vx4,vy4,vz4,norm4)
143
!                 DiheTmp= angle_d(vx4,vy4,vz4,norm4,vx5,vy5,vz5,norm5, &
144
!                         vx2,vy2,vz2,norm2)
145
!                 XprimitiveF(IGeom,I) = DiheTmp*Pi/180.
146
!! We treat large dihedral angles differently as +180=-180 mathematically and physically
147
!! but this causes lots of troubles when converting baker to cart.
148
!! So we ensure that large dihedral angles always have the same sign
149
!                    if (abs(ScanCoord%SignDihedral).NE.1) THEN
150
!                        ScanCoord%SignDihedral=Int(Sign(1.d0,DiheTmp))
151
!                    ELSE
152
!                         If ((abs(DiheTmp).GE.170.D0).AND.(Sign(1.,DiheTmp)*ScanCoord%SignDihedral<0)) THEN
153
!                          XprimitiveF(IGeom,I) = DiheTmp*Pi/180.+ ScanCoord%SignDihedral*2.*Pi
154
!                        END IF
155
!                    END IF
156
!      END SELECT
157
!      ScanCoord => ScanCoord%next
158
!    END DO ! matches DO WHILE (Associated(ScanCoord%next))
159
  END DO ! matches DO IGeom=1, NGeomF
160
   
161
  ALLOCATE(BprimT(3*Nat,NPrim))
162
  ALLOCATE(Gmat(NPrim,NPrim))
163
  ALLOCATE(EigVal(NPrim),EigVec(NPrim,NPrim))
164
  ALLOCATE(BBT(NCoord,NCoord))
165
  ALLOCATE(BBT_inv(NCoord,NCoord))
166
  BTransInvF = 0.d0
167

    
168
  DO IGeom=1, NGeomF 
169
     Geom(1,:)=XyzGeomF(IGeom,1,1:Nat) ! XyzGeomI(NGeomI,3,Nat)
170
     Geom(2,:)=XyzGeomF(IGeom,2,1:Nat)
171
     Geom(3,:)=XyzGeomF(IGeom,3,1:Nat)
172

    
173
   BprimT=0.d0
174
     ScanCoord=>Coordinate
175
     I=0
176
     DO WHILE (Associated(ScanCoord%next))
177
        I=I+1
178
        SELECT CASE (ScanCoord%Type)
179
        CASE ('BOND') 
180
          CALL CONSTRAINTS_BONDLENGTH_DER(Nat,ScanCoord%at1,ScanCoord%AT2, &
181
               Geom,BprimT(1,I))
182
        CASE ('ANGLE')
183
          CALL CONSTRAINTS_BONDANGLE_DER(Nat,ScanCoord%At1,ScanCoord%AT2, &
184
               ScanCoord%At3,Geom,BprimT(1,I))
185
        CASE ('DIHEDRAL')
186
          CALL CONSTRAINTS_TORSION_DER2(Nat,ScanCoord%At1,ScanCoord%AT2, &
187
               ScanCoord%At3,ScanCoord%At4,Geom,BprimT(1,I))
188
      END SELECT
189
        ScanCoord => ScanCoord%next
190
     END DO
191

    
192
   ! BprimT(3*Nat,NPrim)
193
   ! We now compute G=B(BT) matrix
194
   GMat=0.d0
195
   DO I=1,NPrim
196
    DO J=1,3*Nat
197
           GMat(:,I)=Gmat(:,I)+BprimT(J,:)*BprimT(J,I) !*1.d0/mass(atome(int(K/3.d0)))
198
    END DO
199
   END DO
200
  
201
   ! Diagonalize G
202
   EigVal=0.d0
203
   EigVec=0.d0
204
   Call Jacobi(GMat,NPrim,EigVal,EigVec,NPrim)
205
   Call Trie(NPrim,EigVal,EigVec,NPrim)
206
   DO I=1,NPrim
207
    !WRITE(*,'(1X,"Vector ",I3,": e=",F8.3)') I,EigVal(i)
208
    !WRITE(*,'(20(1X,F8.4))') EigVec(1:min(20,NPrim),I)
209
   END DO
210

    
211
   ! UMatF is nonredundant vector set, i.e. set of eigenvectors of BB^T
212
   !  corresponding to eigenvalues > zero.
213
   ! BMat_BakerT(3*Nat,NCoord), allocated in Path.f90, 
214
   ! NCoord=3*Nat-6
215
   BMat_BakerT = 0.d0
216
   J=0
217
   DO I=1,NPrim
218
    IF (abs(eigval(I))>=1e-6) THEN
219
       J=J+1
220
       DO K=1,NPrim
221
        ! BprimT is transpose of B^prim.
222
        ! B = UMatF^T B^prim, B^T = (B^prim)^T UMatF
223
        BMat_BakerT(:,J)=BMat_BakerT(:,J)+BprimT(:,K)*Eigvec(K,I)
224
       END DO
225
         IF(J .GT. 3*Nat-6) THEN
226
           WRITE(*,*) 'Number of vectors in Eigvec with eigval .GT. 1e-6(=UMatF) (=' &
227
                      ,J,') exceeded 3*Nat-6=',3*Nat-6, &
228
            'Stopping the calculation.'
229
           STOP
230
         END IF
231
         UMatF(IGeom,:,J) =  Eigvec(:,I)
232
    END IF
233
   END DO
234

    
235
!!!!!!!!!!!!!!!!!!!!
236
!
237
! Debug purposes
238
!
239
         if (debugPFL) THEN
240
        UMatF(IGeom,:,:)=0.
241
        DO J=1,3*Nat-6
242
           UMatF(IGeom,J,J)=1.
243
        END DO
244
        END IF
245

    
246
 
247
   !DO I=1, NPrim ! This loop is not needed because we already have IntCoordF
248
             ! from interpolation. 
249
   ! Transpose of UMatF is needed below, that is why UMatF(IGeom,I,:).
250
   ! IntCoordF(IGeom,:) = IntCoordF(IGeom,:) + UMat(IGeom,I,:)*XprimitiveF(IGeom,I)
251
   !END DO
252

    
253
   ! Calculation of BTransInvF starts here:
254
   ! Calculation of BBT(3*Nat-6,3*Nat-6)=BB^T:
255
   ! BMat_BakerT(3*Nat,NCoord) is Transpose of B = UMatF^TB^prim
256
    
257
   BBT = 0.d0
258
   DO I=1, NCoord
259
      DO J=1, 3*Nat
260
       ! BBT(:,I) forms BB^T
261
       BBT(:,I) = BBT(:,I) + BMat_BakerT(J,:)*BMat_BakerT(J,I)
262
    END DO
263
   END DO
264
    
265
   Call GenInv(NCoord,BBT,BBT_inv,NCoord) ! GenInv is in Mat_util.f90
266

    
267
   ! Calculation of (B^T)^-1 = (BB^T)^-1B:
268
   DO I=1, 3*Nat
269
      DO J=1, NCoord
270
        BTransInvF(IGeom,:,I) = BTransInvF(IGeom,:,I) + BBT_inv(:,J)*BMat_BakerT(I,J)
271
      END DO
272
   END DO
273
   
274
  END DO !matches DO IGeom=1, NGeomF
275
  
276
  DEALLOCATE(BBT,BBT_inv,BprimT,GMat,EigVal,EigVec)
277
  DEALLOCATE(Geom,x,y,z,XprimRef)
278
  
279
  IF (debug) WRITE(*,*) "DBG Calc_baker_allGeomF over."
280
END SUBROUTINE Calc_baker_allGeomF