Line data Source code
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 Calculate Hirshfeld charges and related functions
10 : !> \par History
11 : !> 11.2014 created [JGH]
12 : !> \author JGH
13 : ! **************************************************************************************************
14 : MODULE hirshfeld_methods
15 : USE ao_util, ONLY: exp_radius_very_extended
16 : USE atom_kind_orbitals, ONLY: calculate_atomic_density
17 : USE atomic_kind_types, ONLY: atomic_kind_type,&
18 : get_atomic_kind
19 : USE cell_types, ONLY: cell_type,&
20 : pbc
21 : USE cp_control_types, ONLY: dft_control_type
22 : USE cp_result_methods, ONLY: cp_results_erase,&
23 : put_results
24 : USE cp_result_types, ONLY: cp_result_type
25 : USE cp_units, ONLY: cp_unit_to_cp2k
26 : USE grid_api, ONLY: GRID_FUNC_AB,&
27 : collocate_pgf_product,&
28 : integrate_pgf_product
29 : USE hirshfeld_types, ONLY: get_hirshfeld_info,&
30 : hirshfeld_type,&
31 : set_hirshfeld_info
32 : USE input_constants, ONLY: radius_covalent,&
33 : radius_default,&
34 : radius_single,&
35 : radius_user,&
36 : radius_vdw,&
37 : shape_function_density,&
38 : shape_function_gaussian
39 : USE kinds, ONLY: default_string_length,&
40 : dp
41 : USE mathconstants, ONLY: pi
42 : USE message_passing, ONLY: mp_para_env_type
43 : USE particle_types, ONLY: particle_type
44 : USE periodic_table, ONLY: get_ptable_info
45 : USE pw_env_types, ONLY: pw_env_get,&
46 : pw_env_type
47 : USE pw_methods, ONLY: pw_integrate_function
48 : USE pw_pool_types, ONLY: pw_pool_type
49 : USE pw_types, ONLY: pw_r3d_rs_type
50 : USE qs_environment_types, ONLY: get_qs_env,&
51 : qs_environment_type
52 : USE qs_kind_types, ONLY: get_qs_kind,&
53 : qs_kind_type
54 : USE qs_rho_types, ONLY: qs_rho_get,&
55 : qs_rho_type
56 : USE realspace_grid_types, ONLY: realspace_grid_desc_type,&
57 : realspace_grid_type,&
58 : rs_grid_zero,&
59 : transfer_pw2rs,&
60 : transfer_rs2pw
61 : #include "./base/base_uses.f90"
62 :
63 : IMPLICIT NONE
64 : PRIVATE
65 :
66 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'hirshfeld_methods'
67 :
68 : PUBLIC :: create_shape_function, comp_hirshfeld_charges, &
69 : comp_hirshfeld_i_charges, write_hirshfeld_charges, &
70 : save_hirshfeld_charges
71 :
72 : ! **************************************************************************************************
73 :
74 : CONTAINS
75 :
76 : ! **************************************************************************************************
77 : !> \brief ...
78 : !> \param charges ...
79 : !> \param hirshfeld_env ...
80 : !> \param particle_set ...
81 : !> \param qs_kind_set ...
82 : !> \param unit_nr ...
83 : ! **************************************************************************************************
84 2274 : SUBROUTINE write_hirshfeld_charges(charges, hirshfeld_env, particle_set, &
85 : qs_kind_set, unit_nr)
86 : REAL(KIND=dp), DIMENSION(:, :), INTENT(inout) :: charges
87 : TYPE(hirshfeld_type), POINTER :: hirshfeld_env
88 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
89 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
90 : INTEGER, INTENT(IN) :: unit_nr
91 :
92 : CHARACTER(len=2) :: element_symbol
93 : INTEGER :: iatom, ikind, natom, nspin
94 : REAL(KIND=dp) :: refc, tc1, zeff
95 :
96 2274 : natom = SIZE(charges, 1)
97 2274 : nspin = SIZE(charges, 2)
98 2274 : WRITE (unit_nr, '(/,T2,A)') '!-----------------------------------------------------------------------------!'
99 2274 : WRITE (UNIT=unit_nr, FMT="(T28,A)") "Hirshfeld Charges"
100 2274 : IF (nspin == 1) THEN
101 : WRITE (UNIT=unit_nr, FMT="(/,T3,A,A)") &
102 1892 : "#Atom Element Kind ", " Ref Charge Population Net charge"
103 : ELSE
104 : WRITE (UNIT=unit_nr, FMT="(/,T3,A,A)") &
105 382 : "#Atom Element Kind ", " Ref Charge Population Spin moment Net charge"
106 : END IF
107 2274 : tc1 = 0.0_dp
108 11883 : DO iatom = 1, natom
109 : CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
110 9609 : element_symbol=element_symbol, kind_number=ikind)
111 9609 : refc = hirshfeld_env%charges(iatom)
112 9609 : CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
113 9609 : IF (nspin == 1) THEN
114 : WRITE (UNIT=unit_nr, FMT="(i7,T15,A2,T20,i3,T27,F8.3,T42,F8.3,T72,F8.3)") &
115 8154 : iatom, element_symbol, ikind, refc, charges(iatom, 1), zeff - charges(iatom, 1)
116 : ELSE
117 : WRITE (UNIT=unit_nr, FMT="(i7,T15,A2,T20,i3,T27,F8.3,T36,2F8.3,T61,F8.3,T72,F8.3)") &
118 1455 : iatom, element_symbol, ikind, refc, charges(iatom, 1), charges(iatom, 2), &
119 5820 : charges(iatom, 1) - charges(iatom, 2), zeff - SUM(charges(iatom, :))
120 : END IF
121 32556 : tc1 = tc1 + (zeff - SUM(charges(iatom, :)))
122 : END DO
123 2274 : WRITE (UNIT=unit_nr, FMT="(/,T3,A,T72,F8.3)") "Total Charge ", tc1
124 2274 : WRITE (unit_nr, '(T2,A)') '!-----------------------------------------------------------------------------!'
125 :
126 2274 : END SUBROUTINE write_hirshfeld_charges
127 :
128 : ! **************************************************************************************************
129 : !> \brief saves the Hirshfeld charges to the results structure
130 : !> \param charges the calculated Hirshfeld charges
131 : !> \param particle_set the particle set
132 : !> \param qs_kind_set the kind set
133 : !> \param qs_env the environment
134 : ! **************************************************************************************************
135 4520 : SUBROUTINE save_hirshfeld_charges(charges, particle_set, qs_kind_set, qs_env)
136 : REAL(KIND=dp), DIMENSION(:, :), INTENT(inout) :: charges
137 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
138 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
139 : TYPE(qs_environment_type), POINTER :: qs_env
140 :
141 : CHARACTER(LEN=default_string_length) :: description
142 : INTEGER :: iatom, ikind, natom
143 : REAL(KIND=dp) :: zeff
144 : REAL(KIND=dp), DIMENSION(:), POINTER :: charges_save
145 : TYPE(cp_result_type), POINTER :: results
146 :
147 4520 : NULLIFY (results)
148 4520 : CALL get_qs_env(qs_env, results=results)
149 :
150 4520 : natom = SIZE(charges, 1)
151 13560 : ALLOCATE (charges_save(natom))
152 :
153 23682 : DO iatom = 1, natom
154 : CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
155 19162 : kind_number=ikind)
156 19162 : CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
157 45754 : charges_save(iatom) = zeff - SUM(charges(iatom, :))
158 : END DO
159 :
160 : ! Store charges in results
161 4520 : description = "[HIRSHFELD-CHARGES]"
162 4520 : CALL cp_results_erase(results=results, description=description)
163 : CALL put_results(results=results, description=description, &
164 4520 : values=charges_save)
165 :
166 4520 : DEALLOCATE (charges_save)
167 :
168 4520 : END SUBROUTINE save_hirshfeld_charges
169 :
170 : ! **************************************************************************************************
171 : !> \brief creates kind specific shape functions for Hirshfeld charges
172 : !> \param hirshfeld_env the env that holds information about Hirshfeld
173 : !> \param qs_kind_set the qs_kind_set
174 : !> \param atomic_kind_set the atomic_kind_set
175 : !> \param radius optional radius parameter to use for all atomic kinds
176 : !> \param radii_list optional list of radii to use for different atomic kinds
177 : ! **************************************************************************************************
178 4702 : SUBROUTINE create_shape_function(hirshfeld_env, qs_kind_set, atomic_kind_set, radius, radii_list)
179 : TYPE(hirshfeld_type), POINTER :: hirshfeld_env
180 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
181 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
182 : REAL(KIND=dp), OPTIONAL :: radius
183 : REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER :: radii_list
184 :
185 : INTEGER, PARAMETER :: ngto = 8
186 :
187 : CHARACTER(len=2) :: esym
188 : INTEGER :: ikind, nkind
189 : LOGICAL :: found
190 : REAL(KIND=dp) :: al, rco, zeff
191 : REAL(KIND=dp), DIMENSION(ngto, 2) :: ppdens
192 : TYPE(atomic_kind_type), POINTER :: atomic_kind
193 : TYPE(qs_kind_type), POINTER :: qs_kind
194 :
195 4702 : CPASSERT(ASSOCIATED(hirshfeld_env))
196 :
197 4702 : nkind = SIZE(qs_kind_set)
198 22276 : ALLOCATE (hirshfeld_env%kind_shape_fn(nkind))
199 :
200 4702 : SELECT CASE (hirshfeld_env%shape_function_type)
201 : CASE (shape_function_gaussian)
202 12818 : DO ikind = 1, nkind
203 8134 : hirshfeld_env%kind_shape_fn(ikind)%numexp = 1
204 8134 : ALLOCATE (hirshfeld_env%kind_shape_fn(ikind)%zet(1))
205 8134 : ALLOCATE (hirshfeld_env%kind_shape_fn(ikind)%coef(1))
206 8134 : CALL get_qs_kind(qs_kind_set(ikind), element_symbol=esym)
207 8134 : rco = 2.0_dp
208 8134 : SELECT CASE (hirshfeld_env%radius_type)
209 : CASE (radius_default)
210 8 : CALL get_ptable_info(symbol=esym, covalent_radius=rco, found=found)
211 8 : rco = MAX(rco, 1.0_dp)
212 : CASE (radius_user)
213 4 : CPASSERT(PRESENT(radii_list))
214 4 : CPASSERT(ASSOCIATED(radii_list))
215 4 : CPASSERT(SIZE(radii_list) == nkind)
216 : ! Note we assume that radii_list is correctly ordered
217 4 : rco = radii_list(ikind)
218 : CASE (radius_vdw)
219 276 : CALL get_ptable_info(symbol=esym, vdw_radius=rco, found=found)
220 276 : IF (.NOT. found) THEN
221 0 : rco = MAX(rco, 1.0_dp)
222 : ELSE
223 276 : IF (hirshfeld_env%use_bohr) &
224 0 : rco = cp_unit_to_cp2k(rco, "angstrom")
225 : END IF
226 : CASE (radius_covalent)
227 7842 : CALL get_ptable_info(symbol=esym, covalent_radius=rco, found=found)
228 7842 : IF (.NOT. found) THEN
229 0 : rco = MAX(rco, 1.0_dp)
230 : ELSE
231 7842 : IF (hirshfeld_env%use_bohr) &
232 0 : rco = cp_unit_to_cp2k(rco, "angstrom")
233 : END IF
234 : CASE (radius_single)
235 4 : CPASSERT(PRESENT(radius))
236 8130 : rco = radius
237 : END SELECT
238 8134 : al = 0.5_dp/rco**2
239 8134 : hirshfeld_env%kind_shape_fn(ikind)%zet(1) = al
240 12818 : hirshfeld_env%kind_shape_fn(ikind)%coef(1) = (al/pi)**1.5_dp
241 : END DO
242 : CASE (shape_function_density)
243 : ! calculate atomic density
244 54 : DO ikind = 1, nkind
245 36 : atomic_kind => atomic_kind_set(ikind)
246 36 : qs_kind => qs_kind_set(ikind)
247 : CALL calculate_atomic_density(ppdens(:, :), atomic_kind, qs_kind, ngto, &
248 36 : confine=.FALSE.)
249 36 : hirshfeld_env%kind_shape_fn(ikind)%numexp = ngto
250 36 : ALLOCATE (hirshfeld_env%kind_shape_fn(ikind)%zet(ngto))
251 36 : ALLOCATE (hirshfeld_env%kind_shape_fn(ikind)%coef(ngto))
252 324 : hirshfeld_env%kind_shape_fn(ikind)%zet(:) = ppdens(:, 1)
253 36 : CALL get_qs_kind(qs_kind, zeff=zeff)
254 342 : hirshfeld_env%kind_shape_fn(ikind)%coef(:) = ppdens(:, 2)/zeff
255 : END DO
256 :
257 : CASE DEFAULT
258 4702 : CPABORT("Unknown shape function")
259 : END SELECT
260 :
261 4702 : END SUBROUTINE create_shape_function
262 :
263 : ! **************************************************************************************************
264 : !> \brief ...
265 : !> \param qs_env ...
266 : !> \param hirshfeld_env ...
267 : !> \param charges ...
268 : ! **************************************************************************************************
269 4498 : SUBROUTINE comp_hirshfeld_charges(qs_env, hirshfeld_env, charges)
270 : TYPE(qs_environment_type), POINTER :: qs_env
271 : TYPE(hirshfeld_type), POINTER :: hirshfeld_env
272 : REAL(KIND=dp), DIMENSION(:, :), INTENT(inout) :: charges
273 :
274 : INTEGER :: is
275 : LOGICAL :: rho_r_valid
276 : REAL(KIND=dp) :: tnfun
277 : TYPE(pw_env_type), POINTER :: pw_env
278 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
279 : TYPE(pw_r3d_rs_type) :: rhonorm
280 4498 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r
281 : TYPE(qs_rho_type), POINTER :: rho
282 :
283 4498 : NULLIFY (rho_r)
284 : ! normalization function on grid
285 4498 : CALL calculate_hirshfeld_normalization(qs_env, hirshfeld_env)
286 : ! check normalization
287 4498 : tnfun = pw_integrate_function(hirshfeld_env%fnorm)
288 23594 : tnfun = ABS(tnfun - SUM(hirshfeld_env%charges))
289 : !
290 4498 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, rho=rho)
291 4498 : CALL qs_rho_get(rho, rho_r=rho_r, rho_r_valid=rho_r_valid)
292 4498 : CALL pw_env_get(pw_env=pw_env, auxbas_pw_pool=auxbas_pw_pool)
293 4498 : CALL auxbas_pw_pool%create_pw(rhonorm)
294 : ! loop over spins
295 9748 : DO is = 1, SIZE(rho_r)
296 5250 : IF (rho_r_valid) THEN
297 : CALL hfun_scale(rhonorm%array, rho_r(is)%array, &
298 5250 : hirshfeld_env%fnorm%array)
299 : ELSE
300 0 : CPABORT("We need rho in real space")
301 : END IF
302 5250 : CALL hirshfeld_integration(qs_env, hirshfeld_env, rhonorm, charges(:, is))
303 31718 : charges(:, is) = charges(:, is)*hirshfeld_env%charges(:)
304 : END DO
305 4498 : CALL auxbas_pw_pool%give_back_pw(rhonorm)
306 :
307 4498 : END SUBROUTINE comp_hirshfeld_charges
308 : ! **************************************************************************************************
309 : !> \brief Calculate fout = fun1/fun2
310 : !> \param fout ...
311 : !> \param fun1 ...
312 : !> \param fun2 ...
313 : ! **************************************************************************************************
314 5452 : SUBROUTINE hfun_scale(fout, fun1, fun2)
315 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT) :: fout
316 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN) :: fun1, fun2
317 :
318 : REAL(KIND=dp), PARAMETER :: small = 1.0e-12_dp
319 :
320 : INTEGER :: i1, i2, i3, n1, n2, n3
321 :
322 5452 : n1 = SIZE(fout, 1)
323 5452 : n2 = SIZE(fout, 2)
324 5452 : n3 = SIZE(fout, 3)
325 5452 : CPASSERT(n1 == SIZE(fun1, 1))
326 5452 : CPASSERT(n2 == SIZE(fun1, 2))
327 5452 : CPASSERT(n3 == SIZE(fun1, 3))
328 5452 : CPASSERT(n1 == SIZE(fun2, 1))
329 5452 : CPASSERT(n2 == SIZE(fun2, 2))
330 5452 : CPASSERT(n3 == SIZE(fun2, 3))
331 :
332 254082 : DO i3 = 1, n3
333 12059746 : DO i2 = 1, n2
334 335935553 : DO i1 = 1, n1
335 335686923 : IF (fun2(i1, i2, i3) > small) THEN
336 110717579 : fout(i1, i2, i3) = fun1(i1, i2, i3)/fun2(i1, i2, i3)
337 : ELSE
338 213163680 : fout(i1, i2, i3) = 0.0_dp
339 : END IF
340 : END DO
341 : END DO
342 : END DO
343 :
344 5452 : END SUBROUTINE hfun_scale
345 :
346 : ! **************************************************************************************************
347 : !> \brief ...
348 : !> \param qs_env ...
349 : !> \param hirshfeld_env ...
350 : !> \param charges ...
351 : !> \param ounit ...
352 : ! **************************************************************************************************
353 22 : SUBROUTINE comp_hirshfeld_i_charges(qs_env, hirshfeld_env, charges, ounit)
354 : TYPE(qs_environment_type), POINTER :: qs_env
355 : TYPE(hirshfeld_type), POINTER :: hirshfeld_env
356 : REAL(KIND=dp), DIMENSION(:, :), INTENT(inout) :: charges
357 : INTEGER, INTENT(IN) :: ounit
358 :
359 : INTEGER, PARAMETER :: maxloop = 100
360 : REAL(KIND=dp), PARAMETER :: maxres = 1.0e-2_dp
361 :
362 : CHARACTER(len=3) :: yesno
363 : INTEGER :: iat, iloop, is, natom
364 : LOGICAL :: rho_r_valid
365 : REAL(KIND=dp) :: res, tnfun
366 : TYPE(pw_env_type), POINTER :: pw_env
367 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
368 : TYPE(pw_r3d_rs_type) :: rhonorm
369 22 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r
370 : TYPE(qs_rho_type), POINTER :: rho
371 :
372 22 : NULLIFY (rho_r)
373 :
374 22 : natom = SIZE(charges, 1)
375 :
376 11 : IF (ounit > 0) WRITE (ounit, "(/,T2,A)") "Hirshfeld charge iterations: Residuals ..."
377 : !
378 22 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, rho=rho)
379 22 : CALL qs_rho_get(rho, rho_r=rho_r, rho_r_valid=rho_r_valid)
380 22 : CALL pw_env_get(pw_env=pw_env, auxbas_pw_pool=auxbas_pw_pool)
381 22 : CALL auxbas_pw_pool%create_pw(rhonorm)
382 : !
383 130 : DO iloop = 1, maxloop
384 :
385 : ! normalization function on grid
386 130 : CALL calculate_hirshfeld_normalization(qs_env, hirshfeld_env)
387 : ! check normalization
388 130 : tnfun = pw_integrate_function(hirshfeld_env%fnorm)
389 520 : tnfun = ABS(tnfun - SUM(hirshfeld_env%charges))
390 : ! loop over spins
391 332 : DO is = 1, SIZE(rho_r)
392 202 : IF (rho_r_valid) THEN
393 : CALL hfun_scale(rhonorm%array, rho_r(is)%array, &
394 202 : hirshfeld_env%fnorm%array)
395 : ELSE
396 0 : CPABORT("We need rho in real space")
397 : END IF
398 202 : CALL hirshfeld_integration(qs_env, hirshfeld_env, rhonorm, charges(:, is))
399 938 : charges(:, is) = charges(:, is)*hirshfeld_env%charges(:)
400 : END DO
401 : ! residual
402 130 : res = 0.0_dp
403 520 : DO iat = 1, natom
404 1126 : res = res + (SUM(charges(iat, :)) - hirshfeld_env%charges(iat))**2
405 : END DO
406 130 : res = SQRT(res/REAL(natom, KIND=dp))
407 130 : IF (ounit > 0) THEN
408 65 : yesno = "NO "
409 65 : IF (MOD(iloop, 10) == 0) yesno = "YES"
410 65 : WRITE (ounit, FMT="(F8.3)", ADVANCE=yesno) res
411 : END IF
412 : ! update
413 520 : DO iat = 1, natom
414 1126 : hirshfeld_env%charges(iat) = SUM(charges(iat, :))
415 : END DO
416 130 : IF (res < maxres) EXIT
417 :
418 : END DO
419 : !
420 22 : CALL auxbas_pw_pool%give_back_pw(rhonorm)
421 :
422 22 : END SUBROUTINE comp_hirshfeld_i_charges
423 :
424 : ! **************************************************************************************************
425 : !> \brief ...
426 : !> \param qs_env ...
427 : !> \param hirshfeld_env ...
428 : ! **************************************************************************************************
429 4628 : SUBROUTINE calculate_hirshfeld_normalization(qs_env, hirshfeld_env)
430 :
431 : TYPE(qs_environment_type), POINTER :: qs_env
432 : TYPE(hirshfeld_type), POINTER :: hirshfeld_env
433 :
434 : CHARACTER(len=*), PARAMETER :: routineN = 'calculate_hirshfeld_normalization'
435 :
436 : INTEGER :: atom_a, handle, iatom, iex, ikind, &
437 : ithread, j, natom, npme, nthread, &
438 : numexp, subpatch_pattern
439 4628 : INTEGER, DIMENSION(:), POINTER :: atom_list, cores
440 : REAL(KIND=dp) :: alpha, coef, eps_rho_rspace, radius
441 : REAL(KIND=dp), DIMENSION(3) :: ra
442 4628 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: pab
443 4628 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
444 : TYPE(cell_type), POINTER :: cell
445 : TYPE(dft_control_type), POINTER :: dft_control
446 4628 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
447 : TYPE(pw_env_type), POINTER :: pw_env
448 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
449 : TYPE(pw_r3d_rs_type), POINTER :: fnorm
450 : TYPE(realspace_grid_desc_type), POINTER :: auxbas_rs_desc
451 : TYPE(realspace_grid_type), POINTER :: rs_rho
452 :
453 4628 : CALL timeset(routineN, handle)
454 :
455 : CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, cell=cell, &
456 4628 : dft_control=dft_control, particle_set=particle_set, pw_env=pw_env)
457 : CALL pw_env_get(pw_env, auxbas_rs_desc=auxbas_rs_desc, auxbas_rs_grid=rs_rho, &
458 4628 : auxbas_pw_pool=auxbas_pw_pool)
459 : ! be careful in parallel nsmax is chosen with multigrid in mind!
460 4628 : CALL rs_grid_zero(rs_rho)
461 :
462 4628 : eps_rho_rspace = dft_control%qs_control%eps_rho_rspace
463 4628 : ALLOCATE (pab(1, 1))
464 4628 : nthread = 1
465 4628 : ithread = 0
466 :
467 12682 : DO ikind = 1, SIZE(atomic_kind_set)
468 8054 : numexp = hirshfeld_env%kind_shape_fn(ikind)%numexp
469 8054 : IF (numexp <= 0) CYCLE
470 8054 : CALL get_atomic_kind(atomic_kind_set(ikind), natom=natom, atom_list=atom_list)
471 24162 : ALLOCATE (cores(natom))
472 :
473 17284 : DO iex = 1, numexp
474 9230 : alpha = hirshfeld_env%kind_shape_fn(ikind)%zet(iex)
475 9230 : coef = hirshfeld_env%kind_shape_fn(ikind)%coef(iex)
476 9230 : npme = 0
477 30480 : cores = 0
478 30480 : DO iatom = 1, natom
479 21250 : atom_a = atom_list(iatom)
480 21250 : ra(:) = pbc(particle_set(atom_a)%r, cell)
481 30480 : IF (rs_rho%desc%parallel .AND. .NOT. rs_rho%desc%distributed) THEN
482 : ! replicated realspace grid, split the atoms up between procs
483 21092 : IF (MODULO(iatom, rs_rho%desc%group_size) == rs_rho%desc%my_pos) THEN
484 10546 : npme = npme + 1
485 10546 : cores(npme) = iatom
486 : END IF
487 : ELSE
488 158 : npme = npme + 1
489 158 : cores(npme) = iatom
490 : END IF
491 : END DO
492 27988 : DO j = 1, npme
493 10704 : iatom = cores(j)
494 10704 : atom_a = atom_list(iatom)
495 10704 : pab(1, 1) = hirshfeld_env%charges(atom_a)*coef
496 10704 : ra(:) = pbc(particle_set(atom_a)%r, cell)
497 10704 : subpatch_pattern = 0
498 : radius = exp_radius_very_extended(la_min=0, la_max=0, lb_min=0, lb_max=0, &
499 : ra=ra, rb=ra, rp=ra, zetp=alpha, eps=eps_rho_rspace, &
500 : pab=pab, o1=0, o2=0, & ! without map_consistent
501 10704 : prefactor=1.0_dp, cutoff=0.0_dp)
502 :
503 : ! la_max==0 so set lmax_global to 0
504 : CALL collocate_pgf_product(0, alpha, 0, 0, 0.0_dp, 0, ra, &
505 : (/0.0_dp, 0.0_dp, 0.0_dp/), 1.0_dp, pab, 0, 0, rs_rho, &
506 : radius=radius, ga_gb_function=GRID_FUNC_AB, &
507 19934 : use_subpatch=.TRUE., subpatch_pattern=subpatch_pattern)
508 : END DO
509 : END DO
510 :
511 20736 : DEALLOCATE (cores)
512 : END DO
513 4628 : DEALLOCATE (pab)
514 :
515 4628 : NULLIFY (fnorm)
516 4628 : CALL get_hirshfeld_info(hirshfeld_env, fnorm=fnorm)
517 4628 : IF (ASSOCIATED(fnorm)) THEN
518 108 : CALL fnorm%release()
519 108 : DEALLOCATE (fnorm)
520 : END IF
521 4628 : ALLOCATE (fnorm)
522 4628 : CALL auxbas_pw_pool%create_pw(fnorm)
523 4628 : CALL set_hirshfeld_info(hirshfeld_env, fnorm=fnorm)
524 :
525 4628 : CALL transfer_rs2pw(rs_rho, fnorm)
526 :
527 4628 : CALL timestop(handle)
528 :
529 4628 : END SUBROUTINE calculate_hirshfeld_normalization
530 :
531 : ! **************************************************************************************************
532 : !> \brief ...
533 : !> \param qs_env ...
534 : !> \param hirshfeld_env ...
535 : !> \param rfun ...
536 : !> \param fval ...
537 : !> \param fderiv ...
538 : ! **************************************************************************************************
539 5452 : SUBROUTINE hirshfeld_integration(qs_env, hirshfeld_env, rfun, fval, fderiv)
540 :
541 : TYPE(qs_environment_type), POINTER :: qs_env
542 : TYPE(hirshfeld_type), POINTER :: hirshfeld_env
543 : TYPE(pw_r3d_rs_type) :: rfun
544 : REAL(KIND=dp), DIMENSION(:), INTENT(inout) :: fval
545 : REAL(KIND=dp), DIMENSION(:, :), INTENT(inout), &
546 : OPTIONAL :: fderiv
547 :
548 : CHARACTER(len=*), PARAMETER :: routineN = 'hirshfeld_integration'
549 :
550 : INTEGER :: atom_a, handle, iatom, iex, ikind, &
551 : ithread, j, natom, npme, nthread, &
552 : numexp
553 5452 : INTEGER, ALLOCATABLE, DIMENSION(:) :: cores
554 5452 : INTEGER, DIMENSION(:), POINTER :: atom_list
555 : LOGICAL :: do_force
556 : REAL(KIND=dp) :: alpha, coef, dvol, eps_rho_rspace, radius
557 : REAL(KIND=dp), DIMENSION(3) :: force_a, force_b, ra
558 5452 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: hab, pab
559 5452 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
560 : TYPE(cell_type), POINTER :: cell
561 : TYPE(dft_control_type), POINTER :: dft_control
562 : TYPE(mp_para_env_type), POINTER :: para_env
563 5452 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
564 : TYPE(pw_env_type), POINTER :: pw_env
565 : TYPE(realspace_grid_desc_type), POINTER :: auxbas_rs_desc
566 : TYPE(realspace_grid_type), POINTER :: rs_v
567 :
568 5452 : CALL timeset(routineN, handle)
569 :
570 5452 : do_force = PRESENT(fderiv)
571 28028 : fval = 0.0_dp
572 5452 : dvol = rfun%pw_grid%dvol
573 :
574 5452 : NULLIFY (pw_env, auxbas_rs_desc)
575 5452 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
576 : CALL pw_env_get(pw_env=pw_env, auxbas_rs_desc=auxbas_rs_desc, &
577 5452 : auxbas_rs_grid=rs_v)
578 5452 : CALL transfer_pw2rs(rs_v, rfun)
579 :
580 : CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, cell=cell, &
581 5452 : dft_control=dft_control, particle_set=particle_set)
582 5452 : eps_rho_rspace = dft_control%qs_control%eps_rho_rspace
583 :
584 5452 : nthread = 1
585 5452 : ithread = 0
586 5452 : ALLOCATE (hab(1, 1), pab(1, 1))
587 :
588 14816 : DO ikind = 1, SIZE(atomic_kind_set)
589 9364 : numexp = hirshfeld_env%kind_shape_fn(ikind)%numexp
590 9364 : IF (numexp <= 0) CYCLE
591 9364 : CALL get_atomic_kind(atomic_kind_set(ikind), natom=natom, atom_list=atom_list)
592 28092 : ALLOCATE (cores(natom))
593 :
594 20660 : DO iex = 1, numexp
595 11296 : alpha = hirshfeld_env%kind_shape_fn(ikind)%zet(iex)
596 11296 : coef = hirshfeld_env%kind_shape_fn(ikind)%coef(iex)
597 11296 : npme = 0
598 36770 : cores = 0
599 36770 : DO iatom = 1, natom
600 25474 : atom_a = atom_list(iatom)
601 25474 : ra(:) = pbc(particle_set(atom_a)%r, cell)
602 36770 : IF (rs_v%desc%parallel .AND. .NOT. rs_v%desc%distributed) THEN
603 : ! replicated realspace grid, split the atoms up between procs
604 25316 : IF (MODULO(iatom, rs_v%desc%group_size) == rs_v%desc%my_pos) THEN
605 12658 : npme = npme + 1
606 12658 : cores(npme) = iatom
607 : END IF
608 : ELSE
609 158 : npme = npme + 1
610 158 : cores(npme) = iatom
611 : END IF
612 : END DO
613 :
614 33476 : DO j = 1, npme
615 12816 : iatom = cores(j)
616 12816 : atom_a = atom_list(iatom)
617 12816 : ra(:) = pbc(particle_set(atom_a)%r, cell)
618 12816 : pab(1, 1) = coef
619 12816 : hab(1, 1) = 0.0_dp
620 12816 : force_a(:) = 0.0_dp
621 12816 : force_b(:) = 0.0_dp
622 :
623 : radius = exp_radius_very_extended(la_min=0, la_max=0, lb_min=0, lb_max=0, &
624 : ra=ra, rb=ra, rp=ra, &
625 : zetp=alpha, eps=eps_rho_rspace, &
626 : pab=pab, o1=0, o2=0, & ! without map_consistent
627 12816 : prefactor=1.0_dp, cutoff=1.0_dp)
628 :
629 : CALL integrate_pgf_product(0, alpha, 0, &
630 : 0, 0.0_dp, 0, ra, (/0.0_dp, 0.0_dp, 0.0_dp/), &
631 : rs_v, hab, pab=pab, o1=0, o2=0, &
632 : radius=radius, calculate_forces=do_force, &
633 : force_a=force_a, force_b=force_b, use_virial=.FALSE., &
634 12816 : use_subpatch=.TRUE., subpatch_pattern=0)
635 12816 : fval(atom_a) = fval(atom_a) + hab(1, 1)*dvol*coef
636 24112 : IF (do_force) THEN
637 0 : fderiv(:, atom_a) = fderiv(:, atom_a) + force_a(:)*dvol
638 : END IF
639 : END DO
640 :
641 : END DO
642 24180 : DEALLOCATE (cores)
643 :
644 : END DO
645 :
646 5452 : DEALLOCATE (hab, pab)
647 :
648 5452 : CALL get_qs_env(qs_env=qs_env, para_env=para_env)
649 50604 : CALL para_env%sum(fval)
650 :
651 5452 : CALL timestop(handle)
652 :
653 10904 : END SUBROUTINE hirshfeld_integration
654 :
655 : END MODULE hirshfeld_methods
|