root / src / ConvGrad_Cart2Int.f90 @ 1
Historique | Voir | Annoter | Télécharger (4,35 ko)
1 | 1 | equemene | SUBROUTINE ConvGrad_Cart2Int(n,BMat,indzmat,GradCart,GradInt) |
---|---|---|---|
2 | 1 | equemene | |
3 | 1 | equemene | use Io_module |
4 | 1 | equemene | use Path_module, only : atome |
5 | 1 | equemene | |
6 | 1 | equemene | IMPLICIT NONE |
7 | 1 | equemene | |
8 | 1 | equemene | ! |
9 | 1 | equemene | INTEGER(KINT), INTENT(IN) :: n, indzmat(n,5) |
10 | 1 | equemene | REAL(KREAL), INTENT(IN) :: BMat(3,n,3,n), GradCart(3,n) |
11 | 1 | equemene | REAL(KREAL), INTENT(INOUT) :: GradInt(3,n) |
12 | 1 | equemene | |
13 | 1 | equemene | |
14 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
15 | 1 | equemene | ! |
16 | 1 | equemene | ! This routines converts a gradient in cartesian coordinates into |
17 | 1 | equemene | ! the gradient in internal coordinates (either Zmat, Mixed or Baker) |
18 | 1 | equemene | ! |
19 | 1 | equemene | ! It uses a LAPACK subroutine (dgelsd) which purpose is: |
20 | 1 | equemene | |
21 | 1 | equemene | ! * DGELSD computes the minimum-norm solution to a real linear least |
22 | 1 | equemene | ! * squares problem: |
23 | 1 | equemene | ! * minimize 2-norm(| b - A*x |) |
24 | 1 | equemene | ! * using the singular value decomposition (SVD) of A. A is an M-by-N |
25 | 1 | equemene | ! * matrix which may be rank-deficient. |
26 | 1 | equemene | |
27 | 1 | equemene | ! Variables: |
28 | 1 | equemene | ! input : n, number of atoms |
29 | 1 | equemene | ! BMat: the dZ/dx matrix |
30 | 1 | equemene | ! GradCart: Gradient in cartesian coordinates |
31 | 1 | equemene | ! |
32 | 1 | equemene | ! output : GradInt: Gradient in internal coordintaes |
33 | 1 | equemene | ! |
34 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
35 | 1 | equemene | |
36 | 1 | equemene | logical debug, init |
37 | 1 | equemene | REAL(KREAL), parameter :: zero = 0d0, tol = 1d-8, eps = 1d-12 |
38 | 1 | equemene | |
39 | 1 | equemene | REAL(KREAL) , ALLOCATABLE :: AEigVec(:,:), AEigVal(:),ATA(:) |
40 | 1 | equemene | INTEGER(KINT) :: n3, iat, k |
41 | 1 | equemene | INTEGER(KINT) :: i |
42 | 1 | equemene | ! |
43 | 1 | equemene | save debug, init |
44 | 1 | equemene | data init /.false./ |
45 | 1 | equemene | |
46 | 1 | equemene | ! .. Local Arrays for LAPACK |
47 | 1 | equemene | INTEGER(KINT) :: Info, LWork, Rank |
48 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: S(:), Work(:), GradCTmp(:,:) |
49 | 1 | equemene | |
50 | 1 | equemene | ! IWORK dimension should be at least 3*MIN(M,N)*NLVL + 11*MIN(M,N), |
51 | 1 | equemene | ! where NLVL = MAX( 0, INT( LOG_2( MIN(M,N)/(SMLSIZ+1) ) )+1 ) |
52 | 1 | equemene | ! and SMLSIZ = 25 |
53 | 1 | equemene | INTEGER(KINT) :: LIWork, NLVL, SMLSIZ=12 ! We take smaller value just to be sure |
54 | 1 | equemene | INTEGER(KINT), ALLOCATABLE :: IWork(:) ! IWork |
55 | 1 | equemene | |
56 | 1 | equemene | |
57 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
58 | 1 | equemene | ! |
59 | 1 | equemene | |
60 | 1 | equemene | INTERFACE |
61 | 1 | equemene | function valid(string) result (isValid) |
62 | 1 | equemene | CHARACTER(*), intent(in) :: string |
63 | 1 | equemene | logical :: isValid |
64 | 1 | equemene | END function VALID |
65 | 1 | equemene | |
66 | 1 | equemene | SUBROUTINE DGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, & |
67 | 1 | equemene | WORK, LWORK, IWORK, INFO ) |
68 | 1 | equemene | ! * |
69 | 1 | equemene | ! * -- LAPACK driver routine (version 3.2.2) -- |
70 | 1 | equemene | ! * -- LAPACK is a software package provided by Univ. of Tennessee, -- |
71 | 1 | equemene | ! * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- |
72 | 1 | equemene | ! * June 2010 |
73 | 1 | equemene | ! * |
74 | 1 | equemene | ! * .. Scalar Arguments .. |
75 | 1 | equemene | INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK |
76 | 1 | equemene | DOUBLE PRECISION RCOND |
77 | 1 | equemene | !* .. |
78 | 1 | equemene | !* .. Array Arguments .. |
79 | 1 | equemene | INTEGER IWORK( * ) |
80 | 1 | equemene | DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * ) |
81 | 1 | equemene | |
82 | 1 | equemene | END SUBROUTINE DGELSD |
83 | 1 | equemene | |
84 | 1 | equemene | |
85 | 1 | equemene | |
86 | 1 | equemene | |
87 | 1 | equemene | END INTERFACE |
88 | 1 | equemene | |
89 | 1 | equemene | ! |
90 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
91 | 1 | equemene | |
92 | 1 | equemene | |
93 | 1 | equemene | if (.not.init) then |
94 | 1 | equemene | init = .true. |
95 | 1 | equemene | debug = valid ('GEOSTEP').OR.valid('ConvGrad') |
96 | 1 | equemene | endif |
97 | 1 | equemene | |
98 | 1 | equemene | ! |
99 | 1 | equemene | Allocate(GradCTmp(3,n)) |
100 | 1 | equemene | |
101 | 1 | equemene | if (debug) WRITE(*,*) "================ Entering ConvGrad_Cart2Int =============" |
102 | 1 | equemene | ! |
103 | 1 | equemene | n3 = 3 * n |
104 | 1 | equemene | ! |
105 | 1 | equemene | |
106 | 1 | equemene | NLVL= MAX( 0, INT( LOG( n3*1.d0/(SMLSIZ+1))/LOG(2.d0) ) +1 ) |
107 | 1 | equemene | LIWork=Max(1,3*n3*NLVL + 11*n3+1) |
108 | 1 | equemene | |
109 | 1 | equemene | Allocate(IWork(LIWork),WOrk(1)) |
110 | 1 | equemene | |
111 | 1 | equemene | LWork=-1 |
112 | 1 | equemene | GradInt=0.d0 |
113 | 1 | equemene | |
114 | 1 | equemene | call DGELSD( n3, n3, 1, BMat, n3, GradCart, n3, GradInt, Tol, RANK, & |
115 | 1 | equemene | WORK, LWORK, IWORK, INFO ) |
116 | 1 | equemene | |
117 | 1 | equemene | LWork=Work(1) |
118 | 1 | equemene | if (debug) WRITE(*,*) "DEBUG CONVGRAD_CART2INT LWORK,N3=",LWORK,N3 |
119 | 1 | equemene | |
120 | 1 | equemene | DEALLOCATE(Work) |
121 | 1 | equemene | ALLOCATE(Work(LWork)) |
122 | 1 | equemene | |
123 | 1 | equemene | call DGELSD( n3, n3, 1, BMat, n3, GradCart, n3, GradInt, Tol, RANK, & |
124 | 1 | equemene | WORK, LWORK, IWORK, INFO ) |
125 | 1 | equemene | |
126 | 1 | equemene | GradInt=GradCart |
127 | 1 | equemene | if (debug) then |
128 | 1 | equemene | WRITE(*,*) "DEBUG CONVGRAD_CART2INT -- GradInt after DGELSD" |
129 | 1 | equemene | WRITE(*,*) "INFO=",INFO |
130 | 1 | equemene | DO I=1,N |
131 | 1 | equemene | WRITE(*,'(1X,I5,3(1X,F13.6))') I, GradInt(1:3,I) |
132 | 1 | equemene | END DO |
133 | 1 | equemene | END IF |
134 | 1 | equemene | |
135 | 1 | equemene | |
136 | 1 | equemene | ! In case we used a Zmat, we might have dummy atoms. |
137 | 1 | equemene | ! We are extra cautious and put their gradient components to 0 |
138 | 1 | equemene | |
139 | 1 | equemene | do iat = 1, n |
140 | 1 | equemene | do k = 1, 3 |
141 | 1 | equemene | if (atome(indzmat(iat,1)) == 0) then |
142 | 1 | equemene | GradInt(k,iat) = zero |
143 | 1 | equemene | endif |
144 | 1 | equemene | end do |
145 | 1 | equemene | end do |
146 | 1 | equemene | |
147 | 1 | equemene | where (abs(GradInt)<=eps) GradInt=zero |
148 | 1 | equemene | |
149 | 1 | equemene | if (debug) write (*,*) "DBG ConvGrad_Cart2Int GradInt=",GradInt |
150 | 1 | equemene | |
151 | 1 | equemene | DEALLOCATE(IWork,Work,GradCTmp) |
152 | 1 | equemene | ! |
153 | 1 | equemene | ! |
154 | 1 | equemene | if (debug) WRITE(*,*) "================ ConvGrad_Cart2Int Over =============" |
155 | 1 | equemene | return |
156 | 1 | equemene | ! ====================================================================== |
157 | 1 | equemene | |
158 | 1 | equemene | end SUBROUTINE ConvGrad_Cart2Int |