(git:e7e05ae)
semi_empirical_mpole_methods.F
Go to the documentation of this file.
1 !--------------------------------------------------------------------------------------------------!
2 ! CP2K: A general program to perform molecular dynamics simulations !
3 ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 ! !
5 ! SPDX-License-Identifier: GPL-2.0-or-later !
6 !--------------------------------------------------------------------------------------------------!
7 
8 ! **************************************************************************************************
9 !> \brief Setup and Methods for semi-empirical multipole types
10 !> \author Teodoro Laino [tlaino] - 08.2008 Zurich University
11 ! **************************************************************************************************
13 
15  USE kinds, ONLY: dp
16  USE semi_empirical_int_arrays, ONLY: alm,&
17  indexa,&
18  indexb,&
22  nddo_mpole_type,&
24  semi_empirical_mpole_p_type,&
25  semi_empirical_mpole_type
26  USE semi_empirical_par_utils, ONLY: amn_l
27  USE semi_empirical_types, ONLY: semi_empirical_type
28 #include "./base/base_uses.f90"
29 
30  IMPLICIT NONE
31 
32  PRIVATE
33 
34 ! *** Global parameters ***
35  LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .false.
36  CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'semi_empirical_mpole_methods'
37 
38  PUBLIC :: semi_empirical_mpole_p_setup, &
41 
42 CONTAINS
43 
44 ! **************************************************************************************************
45 !> \brief Setup semi-empirical mpole type
46 !> This function setup for each semi-empirical type a structure containing
47 !> the multipolar expansion for all possible combination on-site of atomic
48 !> orbitals ( \mu \nu |
49 !> \param mpoles ...
50 !> \param se_parameter ...
51 !> \param method ...
52 !> \date 09.2008
53 !> \author Teodoro Laino [tlaino] - University of Zurich
54 ! **************************************************************************************************
55  SUBROUTINE semi_empirical_mpole_p_setup(mpoles, se_parameter, method)
56  TYPE(semi_empirical_mpole_p_type), DIMENSION(:), &
57  POINTER :: mpoles
58  TYPE(semi_empirical_type), POINTER :: se_parameter
59  INTEGER, INTENT(IN) :: method
60 
61  CHARACTER(LEN=3), DIMENSION(9), PARAMETER :: &
62  label_print_orb = (/" s", " px", " py", " pz", "dx2", "dzx", "dz2", "dzy", "dxy"/)
63  INTEGER, DIMENSION(9), PARAMETER :: loc_index = (/1, 2, 2, 2, 3, 3, 3, 3, 3/)
64 
65  INTEGER :: a, b, i, ind1, ind2, j, k, k1, k2, mu, &
66  natorb, ndim, nr
67  REAL(kind=dp) :: dlm, tmp, wp, ws, zb, zp, zs, zt
68  REAL(kind=dp), DIMENSION(3, 3, 45) :: m2
69  REAL(kind=dp), DIMENSION(3, 45) :: m1
70  REAL(kind=dp), DIMENSION(45) :: m0
71  REAL(kind=dp), DIMENSION(6, 0:2) :: amn
72  TYPE(semi_empirical_mpole_type), POINTER :: mpole
73 
74  cpassert(.NOT. ASSOCIATED(mpoles))
75  ! If there are atomic orbitals proceed with the expansion in multipoles
76  natorb = se_parameter%natorb
77  IF (natorb /= 0) THEN
78  ndim = natorb*(natorb + 1)/2
79  CALL semi_empirical_mpole_p_create(mpoles, ndim)
80 
81  ! Select method for multipolar expansion
82 
83  ! Fill in information on multipole expansion due to atomic orbitals charge
84  ! distribution
85  NULLIFY (mpole)
86  CALL amn_l(se_parameter, amn)
87  DO i = 1, natorb
88  DO j = 1, i
89  ind1 = indexa(se_map_alm(i), se_map_alm(j))
90  ind2 = indexb(i, j)
91  ! the order in the mpoles structure is like the standard one for the
92  ! integrals: s px py pz dx2-y2 dzx dz2 dzy dxy (lower triangular)
93  ! which differs from the order of the Hamiltonian in CP2K. But I
94  ! preferred to keep this order for consistency with the integrals
95  mpole => mpoles(ind2)%mpole
96  mpole%indi = i
97  mpole%indj = j
98  a = loc_index(i)
99  b = loc_index(j)
100  mpole%c = huge(0.0_dp)
101  mpole%d = huge(0.0_dp)
102  mpole%qs = huge(0.0_dp)
103  mpole%qc = huge(0.0_dp)
104 
105  ! Charge
106  IF (alm(ind1, 0, 0) /= 0.0_dp) THEN
107  dlm = 1.0_dp/sqrt(real((2*0 + 1), kind=dp))
108  tmp = -dlm*amn(indexb(a, b), 0)
109  mpole%c = tmp*alm(ind1, 0, 0)
110  mpole%task(1) = .true.
111  END IF
112 
113  ! Dipole
114  IF (any(alm(ind1, 1, -1:1) /= 0.0_dp)) THEN
115  dlm = 1.0_dp/sqrt(real((2*1 + 1), kind=dp))
116  tmp = -dlm*amn(indexb(a, b), 1)
117  mpole%d(1) = tmp*alm(ind1, 1, 1)
118  mpole%d(2) = tmp*alm(ind1, 1, -1)
119  mpole%d(3) = tmp*alm(ind1, 1, 0)
120  mpole%task(2) = .true.
121  END IF
122 
123  ! Quadrupole
124  IF (any(alm(ind1, 2, -2:2) /= 0.0_dp)) THEN
125  dlm = 1.0_dp/sqrt(real((2*2 + 1), kind=dp))
126  tmp = -dlm*amn(indexb(a, b), 2)
127 
128  ! Spherical components
129  mpole%qs(1) = tmp*alm(ind1, 2, 0) ! d3z2-r2
130  mpole%qs(2) = tmp*alm(ind1, 2, 1) ! dzx
131  mpole%qs(3) = tmp*alm(ind1, 2, -1) ! dzy
132  mpole%qs(4) = tmp*alm(ind1, 2, 2) ! dx2-y2
133  mpole%qs(5) = tmp*alm(ind1, 2, -2) ! dxy
134 
135  ! Convert into cartesian components
136  CALL quadrupole_sph_to_cart(mpole%qc, mpole%qs)
137  mpole%task(3) = .true.
138  END IF
139 
140  IF (debug_this_module) THEN
141  WRITE (*, '(A,2I6,A)') "Orbitals ", i, j, &
142  " ("//label_print_orb(i)//","//label_print_orb(j)//")"
143  IF (mpole%task(1)) WRITE (*, '(9F12.6)') mpole%c
144  IF (mpole%task(2)) WRITE (*, '(9F12.6)') mpole%d
145  IF (mpole%task(3)) WRITE (*, '(9F12.6)') mpole%qc
146  WRITE (*, *)
147  END IF
148  END DO
149  END DO
150 
151  IF (method == do_method_pnnl) THEN
152  ! No d-function for Schenter type integrals
153  cpassert(natorb <= 4)
154 
155  m0 = 0.0_dp
156  m1 = 0.0_dp
157  m2 = 0.0_dp
158 
159  DO mu = 1, se_parameter%natorb
160  m0(indexb(mu, mu)) = 1.0_dp
161  END DO
162 
163  zs = se_parameter%sto_exponents(0)
164  zp = se_parameter%sto_exponents(1)
165  nr = se_parameter%nr
166 
167  ws = real((2*nr + 2)*(2*nr + 1), dp)/(24.0_dp*zs**2)
168  DO k = 1, 3
169  m2(k, k, indexb(1, 1)) = ws
170  END DO
171 
172  IF (zp > 0._dp) THEN
173  zt = sqrt(zs*zp)
174  zb = 0.5_dp*(zs + zp)
175  DO k = 1, 3
176  m1(k, indexb(1, 1 + k)) = (zt/zb)**(2*nr + 1)*real(2*nr + 1, dp)/(2.0*zb*sqrt(3.0_dp))
177  END DO
178 
179  wp = real((2*nr + 2)*(2*nr + 1), dp)/(40.0_dp*zp**2)
180  DO k1 = 1, 3
181  DO k2 = 1, 3
182  IF (k1 == k2) THEN
183  m2(k2, k2, indexb(1 + k1, 1 + k1)) = 3.0_dp*wp
184  ELSE
185  m2(k2, k2, indexb(1 + k1, 1 + k1)) = wp
186  END IF
187  END DO
188  END DO
189  m2(1, 2, indexb(1 + 1, 1 + 2)) = wp
190  m2(2, 1, indexb(1 + 1, 1 + 2)) = wp
191  m2(2, 3, indexb(1 + 2, 1 + 3)) = wp
192  m2(3, 2, indexb(1 + 2, 1 + 3)) = wp
193  m2(3, 1, indexb(1 + 3, 1 + 1)) = wp
194  m2(1, 3, indexb(1 + 3, 1 + 1)) = wp
195  END IF
196 
197  DO i = 1, natorb
198  DO j = 1, i
199  ind1 = indexa(se_map_alm(i), se_map_alm(j))
200  ind2 = indexb(i, j)
201  mpole => mpoles(ind2)%mpole
202  mpole%indi = i
203  mpole%indj = j
204  ! Charge
205  mpole%cs = -m0(indexb(i, j))
206  ! Dipole
207  mpole%ds = -m1(1:3, indexb(i, j))
208  ! Quadrupole
209  mpole%qq = -3._dp*m2(1:3, 1:3, indexb(i, j))
210  IF (debug_this_module) THEN
211  WRITE (*, '(A,2I6,A)') "Orbitals ", i, j, &
212  " ("//label_print_orb(i)//","//label_print_orb(j)//")"
213  WRITE (*, '(9F12.6)') mpole%cs
214  WRITE (*, '(9F12.6)') mpole%ds
215  WRITE (*, '(9F12.6)') mpole%qq
216  WRITE (*, *)
217  END IF
218  END DO
219  END DO
220  ELSE
221  mpole%cs = mpole%c
222  mpole%ds = mpole%d
223  mpole%qq = mpole%qc
224  END IF
225  END IF
226 
227  END SUBROUTINE semi_empirical_mpole_p_setup
228 
229 ! **************************************************************************************************
230 !> \brief Transforms the quadrupole components from sphericals to cartesians
231 !> \param qcart ...
232 !> \param qsph ...
233 !> \date 09.2008
234 !> \author Teodoro Laino [tlaino] - University of Zurich
235 ! **************************************************************************************************
236  SUBROUTINE quadrupole_sph_to_cart(qcart, qsph)
237  REAL(kind=dp), DIMENSION(3, 3), INTENT(OUT) :: qcart
238  REAL(kind=dp), DIMENSION(5), INTENT(IN) :: qsph
239 
240 ! Notation
241 ! qs(1) - d3z2-r2
242 ! qs(2) - dzx
243 ! qs(3) - dzy
244 ! qs(4) - dx2-y2
245 ! qs(5) - dxy
246 ! Cartesian components
247 
248  qcart(1, 1) = (qsph(4) - qsph(1)/sqrt(3.0_dp))*sqrt(3.0_dp)/2.0_dp
249  qcart(2, 1) = qsph(5)*sqrt(3.0_dp)/2.0_dp
250  qcart(3, 1) = qsph(2)*sqrt(3.0_dp)/2.0_dp
251  qcart(2, 2) = -(qsph(4) + qsph(1)/sqrt(3.0_dp))*sqrt(3.0_dp)/2.0_dp
252  qcart(3, 2) = qsph(3)*sqrt(3.0_dp)/2.0_dp
253  qcart(3, 3) = qsph(1)
254  ! Symmetrize tensor
255  qcart(1, 2) = qcart(2, 1)
256  qcart(1, 3) = qcart(3, 1)
257  qcart(2, 3) = qcart(3, 2)
258 
259  END SUBROUTINE quadrupole_sph_to_cart
260 
261 ! **************************************************************************************************
262 !> \brief Setup NDDO multipole type
263 !> \param nddo_mpole ...
264 !> \param natom ...
265 !> \date 09.2008
266 !> \author Teodoro Laino [tlaino] - University of Zurich
267 ! **************************************************************************************************
268  SUBROUTINE nddo_mpole_setup(nddo_mpole, natom)
269  TYPE(nddo_mpole_type), POINTER :: nddo_mpole
270  INTEGER, INTENT(IN) :: natom
271 
272  CHARACTER(len=*), PARAMETER :: routinen = 'nddo_mpole_setup'
273 
274  INTEGER :: handle
275 
276  CALL timeset(routinen, handle)
277 
278  IF (ASSOCIATED(nddo_mpole)) THEN
279  CALL nddo_mpole_release(nddo_mpole)
280  END IF
281  CALL nddo_mpole_create(nddo_mpole)
282  ! Allocate Global Arrays
283  ALLOCATE (nddo_mpole%charge(natom))
284  ALLOCATE (nddo_mpole%dipole(3, natom))
285  ALLOCATE (nddo_mpole%quadrupole(3, 3, natom))
286 
287  ALLOCATE (nddo_mpole%efield0(natom))
288  ALLOCATE (nddo_mpole%efield1(3, natom))
289  ALLOCATE (nddo_mpole%efield2(9, natom))
290 
291  CALL timestop(handle)
292 
293  END SUBROUTINE nddo_mpole_setup
294 
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public do_method_pnnl
Defines the basic variable types.
Definition: kinds.F:23
integer, parameter, public dp
Definition: kinds.F:34
Arrays of parameters used in the semi-empirical calculations \References Everywhere in this module TC...
integer, dimension(9), public se_map_alm
integer, dimension(9, 9), public indexb
real(kind=dp), dimension(45, 0:2, -2:2), public alm
integer, dimension(9, 9), public indexa
Setup and Methods for semi-empirical multipole types.
subroutine, public semi_empirical_mpole_p_setup(mpoles, se_parameter, method)
Setup semi-empirical mpole type This function setup for each semi-empirical type a structure containi...
subroutine, public quadrupole_sph_to_cart(qcart, qsph)
Transforms the quadrupole components from sphericals to cartesians.
subroutine, public nddo_mpole_setup(nddo_mpole, natom)
Setup NDDO multipole type.
Definition of the semi empirical multipole integral expansions types.
subroutine, public nddo_mpole_release(nddo_mpole)
Deallocate NDDO multipole type.
subroutine, public semi_empirical_mpole_p_create(mpole, ndim)
Allocate semi-empirical mpole type.
subroutine, public nddo_mpole_create(nddo_mpole)
Allocate NDDO multipole type.
Utilities to post-process semi-empirical parameters.
Definition of the semi empirical parameter types.