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 Calculation of Ewald contributions in DFTB
10 : !> \author JGH
11 : ! **************************************************************************************************
12 : MODULE ewald_methods_tb
13 : USE atprop_types, ONLY: atprop_type
14 : USE cell_types, ONLY: cell_type
15 : USE dgs, ONLY: dg_sum_patch,&
16 : dg_sum_patch_force_1d,&
17 : dg_sum_patch_force_3d
18 : USE ewald_environment_types, ONLY: ewald_env_get,&
19 : ewald_environment_type
20 : USE ewald_pw_types, ONLY: ewald_pw_get,&
21 : ewald_pw_type
22 : USE kinds, ONLY: dp
23 : USE mathconstants, ONLY: fourpi,&
24 : oorootpi
25 : USE message_passing, ONLY: mp_comm_type,&
26 : mp_para_env_type
27 : USE particle_types, ONLY: particle_type
28 : USE pme_tools, ONLY: get_center,&
29 : set_list
30 : USE pw_grid_types, ONLY: pw_grid_type
31 : USE pw_grids, ONLY: get_pw_grid_info
32 : USE pw_methods, ONLY: pw_copy,&
33 : pw_derive,&
34 : pw_integral_a2b,&
35 : pw_multiply,&
36 : pw_multiply_with,&
37 : pw_transfer,&
38 : pw_zero
39 : USE pw_poisson_methods, ONLY: pw_poisson_rebuild,&
40 : pw_poisson_solve
41 : USE pw_poisson_types, ONLY: greens_fn_type,&
42 : pw_poisson_type
43 : USE pw_pool_types, ONLY: pw_pool_type
44 : USE pw_types, ONLY: pw_c1d_gs_type,&
45 : pw_r3d_rs_type
46 : USE qs_neighbor_list_types, ONLY: get_iterator_info,&
47 : neighbor_list_iterate,&
48 : neighbor_list_iterator_create,&
49 : neighbor_list_iterator_p_type,&
50 : neighbor_list_iterator_release,&
51 : neighbor_list_set_p_type
52 : USE realspace_grid_types, ONLY: realspace_grid_desc_type,&
53 : realspace_grid_type,&
54 : rs_grid_create,&
55 : rs_grid_release,&
56 : rs_grid_set_box,&
57 : rs_grid_zero,&
58 : transfer_pw2rs,&
59 : transfer_rs2pw
60 : USE spme, ONLY: get_patch
61 : USE virial_methods, ONLY: virial_pair_force
62 : USE virial_types, ONLY: virial_type
63 : #include "./base/base_uses.f90"
64 :
65 : IMPLICIT NONE
66 :
67 : PRIVATE
68 :
69 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ewald_methods_tb'
70 :
71 : PUBLIC :: tb_spme_evaluate, tb_ewald_overlap, tb_spme_zforce
72 :
73 : CONTAINS
74 :
75 : ! **************************************************************************************************
76 : !> \brief ...
77 : !> \param ewald_env ...
78 : !> \param ewald_pw ...
79 : !> \param particle_set ...
80 : !> \param box ...
81 : !> \param gmcharge ...
82 : !> \param mcharge ...
83 : !> \param calculate_forces ...
84 : !> \param virial ...
85 : !> \param use_virial ...
86 : !> \param atprop ...
87 : ! **************************************************************************************************
88 18400 : SUBROUTINE tb_spme_evaluate(ewald_env, ewald_pw, particle_set, box, &
89 18400 : gmcharge, mcharge, calculate_forces, virial, use_virial, atprop)
90 :
91 : TYPE(ewald_environment_type), POINTER :: ewald_env
92 : TYPE(ewald_pw_type), POINTER :: ewald_pw
93 : TYPE(particle_type), DIMENSION(:), INTENT(IN) :: particle_set
94 : TYPE(cell_type), POINTER :: box
95 : REAL(KIND=dp), DIMENSION(:, :), INTENT(inout) :: gmcharge
96 : REAL(KIND=dp), DIMENSION(:), INTENT(in) :: mcharge
97 : LOGICAL, INTENT(in) :: calculate_forces
98 : TYPE(virial_type), POINTER :: virial
99 : LOGICAL, INTENT(in) :: use_virial
100 : TYPE(atprop_type), OPTIONAL, POINTER :: atprop
101 :
102 : CHARACTER(len=*), PARAMETER :: routineN = 'tb_spme_evaluate'
103 :
104 : INTEGER :: handle, i, ig, ipart, j, n, npart, &
105 : o_spline, p1
106 18400 : INTEGER, ALLOCATABLE, DIMENSION(:, :) :: center
107 : INTEGER, DIMENSION(3) :: nd, npts
108 : REAL(KIND=dp) :: alpha, dvols, fat(3), ffa, ffb, fint, vgc
109 18400 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: delta
110 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: rhos
111 : REAL(KIND=dp), DIMENSION(3, 3) :: f_stress, h_stress
112 : TYPE(greens_fn_type), POINTER :: green
113 : TYPE(mp_comm_type) :: group
114 : TYPE(mp_para_env_type), POINTER :: para_env
115 73600 : TYPE(pw_c1d_gs_type), DIMENSION(3) :: dphi_g
116 : TYPE(pw_c1d_gs_type), POINTER :: phi_g, phib_g, rhob_g
117 : TYPE(pw_grid_type), POINTER :: grid_spme
118 : TYPE(pw_poisson_type), POINTER :: poisson_env
119 : TYPE(pw_pool_type), POINTER :: pw_pool
120 : TYPE(pw_r3d_rs_type), POINTER :: rhob_r
121 : TYPE(realspace_grid_desc_type), POINTER :: rs_desc
122 717600 : TYPE(realspace_grid_type) :: rden, rpot
123 : TYPE(realspace_grid_type), ALLOCATABLE, &
124 18400 : DIMENSION(:) :: drpot
125 :
126 18400 : CALL timeset(routineN, handle)
127 : !-------------- INITIALISATION ---------------------
128 : CALL ewald_env_get(ewald_env, alpha=alpha, o_spline=o_spline, group=group, &
129 18400 : para_env=para_env)
130 18400 : NULLIFY (green, poisson_env, pw_pool)
131 : CALL ewald_pw_get(ewald_pw, pw_big_pool=pw_pool, rs_desc=rs_desc, &
132 18400 : poisson_env=poisson_env)
133 18400 : CALL pw_poisson_rebuild(poisson_env)
134 18400 : green => poisson_env%green_fft
135 18400 : grid_spme => pw_pool%pw_grid
136 :
137 18400 : CALL get_pw_grid_info(grid_spme, dvol=dvols, npts=npts)
138 :
139 18400 : npart = SIZE(particle_set)
140 :
141 18400 : n = o_spline
142 92000 : ALLOCATE (rhos(n, n, n))
143 :
144 18400 : CALL rs_grid_create(rden, rs_desc)
145 18400 : CALL rs_grid_set_box(grid_spme, rs=rden)
146 18400 : CALL rs_grid_zero(rden)
147 :
148 92000 : ALLOCATE (center(3, npart), delta(3, npart))
149 18400 : CALL get_center(particle_set, box, center, delta, npts, n)
150 :
151 : !-------------- DENSITY CALCULATION ----------------
152 18400 : ipart = 0
153 128835 : DO
154 147235 : CALL set_list(particle_set, npart, center, p1, rden, ipart)
155 147235 : IF (p1 == 0) EXIT
156 :
157 : ! calculate function on small boxes
158 : CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
159 128835 : is_shell=.FALSE., unit_charge=.TRUE.)
160 32064115 : rhos(:, :, :) = rhos(:, :, :)*mcharge(p1)
161 :
162 : ! add boxes to real space grid (big box)
163 147235 : CALL dg_sum_patch(rden, rhos, center(:, p1))
164 : END DO
165 :
166 18400 : NULLIFY (rhob_r)
167 18400 : ALLOCATE (rhob_r)
168 18400 : CALL pw_pool%create_pw(rhob_r)
169 :
170 18400 : CALL transfer_rs2pw(rden, rhob_r)
171 :
172 : ! transform density to G space and add charge function
173 18400 : NULLIFY (rhob_g)
174 18400 : ALLOCATE (rhob_g)
175 18400 : CALL pw_pool%create_pw(rhob_g)
176 18400 : CALL pw_transfer(rhob_r, rhob_g)
177 : ! update charge function
178 18400 : CALL pw_multiply_with(rhob_g, green%p3m_charge)
179 :
180 : !-------------- ELECTROSTATIC CALCULATION -----------
181 :
182 : ! allocate intermediate arrays
183 73600 : DO i = 1, 3
184 73600 : CALL pw_pool%create_pw(dphi_g(i))
185 : END DO
186 18400 : NULLIFY (phi_g)
187 18400 : ALLOCATE (phi_g)
188 18400 : CALL pw_pool%create_pw(phi_g)
189 18400 : IF (use_virial) THEN
190 154 : CALL pw_poisson_solve(poisson_env, rhob_g, vgc, phi_g, dphi_g, h_stress=h_stress)
191 : ELSE
192 18246 : CALL pw_poisson_solve(poisson_env, rhob_g, vgc, phi_g, dphi_g)
193 : END IF
194 :
195 18400 : CALL rs_grid_create(rpot, rs_desc)
196 18400 : CALL rs_grid_set_box(grid_spme, rs=rpot)
197 :
198 : ! Atomic Stress
199 18400 : IF (PRESENT(atprop)) THEN
200 17482 : IF (ASSOCIATED(atprop)) THEN
201 17482 : IF (atprop%stress .AND. use_virial) THEN
202 :
203 52 : CALL rs_grid_zero(rpot)
204 52 : CALL pw_zero(rhob_g)
205 52 : CALL pw_multiply(rhob_g, phi_g, green%p3m_charge)
206 52 : CALL pw_transfer(rhob_g, rhob_r)
207 52 : CALL transfer_pw2rs(rpot, rhob_r)
208 52 : ipart = 0
209 2136 : DO
210 2188 : CALL set_list(particle_set, npart, center, p1, rden, ipart)
211 2188 : IF (p1 == 0) EXIT
212 : ! calculate function on small boxes
213 : CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
214 2136 : is_shell=.FALSE., unit_charge=.TRUE.)
215 2136 : CALL dg_sum_patch_force_1d(rpot, rhos, center(:, p1), fint)
216 2136 : atprop%atstress(1, 1, p1) = atprop%atstress(1, 1, p1) + 0.5_dp*mcharge(p1)*fint*dvols
217 2136 : atprop%atstress(2, 2, p1) = atprop%atstress(2, 2, p1) + 0.5_dp*mcharge(p1)*fint*dvols
218 2136 : atprop%atstress(3, 3, p1) = atprop%atstress(3, 3, p1) + 0.5_dp*mcharge(p1)*fint*dvols
219 : END DO
220 :
221 52 : NULLIFY (phib_g)
222 52 : ALLOCATE (phib_g)
223 52 : CALL pw_pool%create_pw(phib_g)
224 52 : ffa = (0.5_dp/alpha)**2
225 52 : ffb = 1.0_dp/fourpi
226 208 : DO i = 1, 3
227 3741258 : DO ig = grid_spme%first_gne0, grid_spme%ngpts_cut_local
228 3741102 : phib_g%array(ig) = ffb*dphi_g(i)%array(ig)*(1.0_dp + ffa*grid_spme%gsq(ig))
229 3741258 : phib_g%array(ig) = phib_g%array(ig)*green%influence_fn%array(ig)
230 : END DO
231 156 : IF (grid_spme%have_g0) phib_g%array(1) = 0.0_dp
232 520 : DO j = 1, i
233 312 : nd = 0
234 312 : nd(j) = 1
235 312 : CALL pw_copy(phib_g, rhob_g)
236 312 : CALL pw_derive(rhob_g, nd)
237 312 : CALL pw_multiply_with(rhob_g, green%p3m_charge)
238 312 : CALL pw_transfer(rhob_g, rhob_r)
239 312 : CALL transfer_pw2rs(rpot, rhob_r)
240 :
241 312 : ipart = 0
242 156 : DO
243 13128 : CALL set_list(particle_set, npart, center, p1, rden, ipart)
244 13128 : IF (p1 == 0) EXIT
245 : ! calculate function on small boxes
246 : CALL get_patch(particle_set, delta, green, p1, rhos, &
247 12816 : is_core=.FALSE., is_shell=.FALSE., unit_charge=.TRUE.)
248 : ! integrate box and potential
249 12816 : CALL dg_sum_patch_force_1d(rpot, rhos, center(:, p1), fint)
250 12816 : atprop%atstress(i, j, p1) = atprop%atstress(i, j, p1) + fint*dvols*mcharge(p1)
251 13128 : IF (i /= j) atprop%atstress(j, i, p1) = atprop%atstress(j, i, p1) + fint*dvols*mcharge(p1)
252 : END DO
253 :
254 : END DO
255 : END DO
256 52 : CALL pw_pool%give_back_pw(phib_g)
257 52 : DEALLOCATE (phib_g)
258 :
259 : END IF
260 : END IF
261 : END IF
262 :
263 18400 : CALL pw_pool%give_back_pw(rhob_g)
264 18400 : DEALLOCATE (rhob_g)
265 :
266 18400 : CALL rs_grid_zero(rpot)
267 18400 : CALL pw_multiply_with(phi_g, green%p3m_charge)
268 18400 : CALL pw_transfer(phi_g, rhob_r)
269 18400 : CALL pw_pool%give_back_pw(phi_g)
270 18400 : DEALLOCATE (phi_g)
271 18400 : CALL transfer_pw2rs(rpot, rhob_r)
272 :
273 : !---------- END OF ELECTROSTATIC CALCULATION --------
274 :
275 : !------------- STRESS TENSOR CALCULATION ------------
276 :
277 18400 : IF (use_virial) THEN
278 616 : DO i = 1, 3
279 1540 : DO j = i, 3
280 924 : f_stress(i, j) = pw_integral_a2b(dphi_g(i), dphi_g(j))
281 1386 : f_stress(j, i) = f_stress(i, j)
282 : END DO
283 : END DO
284 154 : ffa = (1.0_dp/fourpi)*(0.5_dp/alpha)**2
285 2002 : virial%pv_virial = virial%pv_virial - (ffa*f_stress - h_stress)/REAL(para_env%num_pe, dp)
286 : END IF
287 :
288 : !--------END OF STRESS TENSOR CALCULATION -----------
289 :
290 18400 : IF (calculate_forces) THEN
291 : ! move derivative of potential to real space grid and
292 : ! multiply by charge function in g-space
293 17434 : ALLOCATE (drpot(3))
294 3032 : DO i = 1, 3
295 2274 : CALL rs_grid_create(drpot(i), rs_desc)
296 2274 : CALL rs_grid_set_box(grid_spme, rs=drpot(i))
297 2274 : CALL pw_multiply_with(dphi_g(i), green%p3m_charge)
298 2274 : CALL pw_transfer(dphi_g(i), rhob_r)
299 2274 : CALL pw_pool%give_back_pw(dphi_g(i))
300 3032 : CALL transfer_pw2rs(drpot(i), rhob_r)
301 : END DO
302 : ELSE
303 70568 : DO i = 1, 3
304 70568 : CALL pw_pool%give_back_pw(dphi_g(i))
305 : END DO
306 : END IF
307 18400 : CALL pw_pool%give_back_pw(rhob_r)
308 18400 : DEALLOCATE (rhob_r)
309 :
310 : !----------------- FORCE CALCULATION ----------------
311 :
312 18400 : ipart = 0
313 : DO
314 :
315 147235 : CALL set_list(particle_set, npart, center, p1, rden, ipart)
316 147235 : IF (p1 == 0) EXIT
317 :
318 : ! calculate function on small boxes
319 : CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
320 128835 : is_shell=.FALSE., unit_charge=.TRUE.)
321 :
322 128835 : CALL dg_sum_patch_force_1d(rpot, rhos, center(:, p1), fint)
323 128835 : gmcharge(p1, 1) = gmcharge(p1, 1) + fint*dvols
324 :
325 147235 : IF (calculate_forces) THEN
326 8330 : CALL dg_sum_patch_force_3d(drpot, rhos, center(:, p1), fat)
327 8330 : gmcharge(p1, 2) = gmcharge(p1, 2) - fat(1)*dvols
328 8330 : gmcharge(p1, 3) = gmcharge(p1, 3) - fat(2)*dvols
329 8330 : gmcharge(p1, 4) = gmcharge(p1, 4) - fat(3)*dvols
330 : END IF
331 :
332 : END DO
333 :
334 : !--------------END OF FORCE CALCULATION -------------
335 :
336 : !------------------CLEANING UP ----------------------
337 :
338 18400 : CALL rs_grid_release(rden)
339 18400 : CALL rs_grid_release(rpot)
340 18400 : IF (calculate_forces) THEN
341 3032 : DO i = 1, 3
342 3032 : CALL rs_grid_release(drpot(i))
343 : END DO
344 3032 : DEALLOCATE (drpot)
345 : END IF
346 18400 : DEALLOCATE (rhos)
347 18400 : DEALLOCATE (center, delta)
348 :
349 18400 : CALL timestop(handle)
350 :
351 55200 : END SUBROUTINE tb_spme_evaluate
352 :
353 : ! **************************************************************************************************
354 : !> \brief ...
355 : !> \param gmcharge ...
356 : !> \param mcharge ...
357 : !> \param alpha ...
358 : !> \param n_list ...
359 : !> \param virial ...
360 : !> \param use_virial ...
361 : !> \param atprop ...
362 : ! **************************************************************************************************
363 15924 : SUBROUTINE tb_ewald_overlap(gmcharge, mcharge, alpha, n_list, virial, use_virial, atprop)
364 :
365 : REAL(KIND=dp), DIMENSION(:, :), INTENT(inout) :: gmcharge
366 : REAL(KIND=dp), DIMENSION(:), INTENT(in) :: mcharge
367 : REAL(KIND=dp), INTENT(in) :: alpha
368 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
369 : POINTER :: n_list
370 : TYPE(virial_type), POINTER :: virial
371 : LOGICAL, INTENT(IN) :: use_virial
372 : TYPE(atprop_type), OPTIONAL, POINTER :: atprop
373 :
374 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tb_ewald_overlap'
375 :
376 : INTEGER :: handle, i, iatom, jatom, nmat
377 : REAL(KIND=dp) :: dfr, dr, fr, pfr, rij(3)
378 : TYPE(neighbor_list_iterator_p_type), &
379 15924 : DIMENSION(:), POINTER :: nl_iterator
380 :
381 15924 : CALL timeset(routineN, handle)
382 :
383 15924 : nmat = SIZE(gmcharge, 2)
384 :
385 15924 : CALL neighbor_list_iterator_create(nl_iterator, n_list)
386 75282126 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
387 75266202 : CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom, r=rij)
388 :
389 301064808 : dr = SQRT(SUM(rij(:)**2))
390 75282126 : IF (dr > 1.e-10) THEN
391 75140900 : fr = erfc(alpha*dr)/dr
392 75140900 : gmcharge(iatom, 1) = gmcharge(iatom, 1) + mcharge(jatom)*fr
393 75140900 : gmcharge(jatom, 1) = gmcharge(jatom, 1) + mcharge(iatom)*fr
394 75140900 : IF (nmat > 1) THEN
395 9359599 : dfr = -2._dp*alpha*EXP(-alpha*alpha*dr*dr)*oorootpi/dr - fr/dr
396 9359599 : dfr = -dfr/dr
397 37438396 : DO i = 2, nmat
398 28078797 : gmcharge(iatom, i) = gmcharge(iatom, i) - rij(i - 1)*mcharge(jatom)*dfr
399 37438396 : gmcharge(jatom, i) = gmcharge(jatom, i) + rij(i - 1)*mcharge(iatom)*dfr
400 : END DO
401 : END IF
402 75140900 : IF (use_virial) THEN
403 6231309 : IF (iatom == jatom) THEN
404 132432 : pfr = -0.5_dp*dfr*mcharge(iatom)*mcharge(jatom)
405 : ELSE
406 6098877 : pfr = -dfr*mcharge(iatom)*mcharge(jatom)
407 : END IF
408 6231309 : CALL virial_pair_force(virial%pv_virial, -pfr, rij, rij)
409 6231309 : IF (PRESENT(atprop)) THEN
410 6231309 : IF (ASSOCIATED(atprop)) THEN
411 6231309 : IF (atprop%stress) THEN
412 2620724 : CALL virial_pair_force(atprop%atstress(:, :, iatom), -0.5_dp*pfr, rij, rij)
413 2620724 : CALL virial_pair_force(atprop%atstress(:, :, jatom), -0.5_dp*pfr, rij, rij)
414 : END IF
415 : END IF
416 : END IF
417 : END IF
418 : END IF
419 :
420 : END DO
421 15924 : CALL neighbor_list_iterator_release(nl_iterator)
422 :
423 15924 : CALL timestop(handle)
424 :
425 15924 : END SUBROUTINE tb_ewald_overlap
426 :
427 : ! **************************************************************************************************
428 : !> \brief ...
429 : !> \param ewald_env ...
430 : !> \param ewald_pw ...
431 : !> \param particle_set ...
432 : !> \param box ...
433 : !> \param gmcharge ...
434 : !> \param mcharge ...
435 : ! **************************************************************************************************
436 12 : SUBROUTINE tb_spme_zforce(ewald_env, ewald_pw, particle_set, box, gmcharge, mcharge)
437 :
438 : TYPE(ewald_environment_type), POINTER :: ewald_env
439 : TYPE(ewald_pw_type), POINTER :: ewald_pw
440 : TYPE(particle_type), DIMENSION(:), INTENT(IN) :: particle_set
441 : TYPE(cell_type), POINTER :: box
442 : REAL(KIND=dp), DIMENSION(:, :), INTENT(inout) :: gmcharge
443 : REAL(KIND=dp), DIMENSION(:), INTENT(in) :: mcharge
444 :
445 : CHARACTER(len=*), PARAMETER :: routineN = 'tb_spme_zforce'
446 :
447 : INTEGER :: handle, i, ipart, n, npart, o_spline, p1
448 12 : INTEGER, ALLOCATABLE, DIMENSION(:, :) :: center
449 : INTEGER, DIMENSION(3) :: npts
450 : REAL(KIND=dp) :: alpha, dvols, fat(3), fint, vgc
451 12 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: delta
452 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: rhos
453 : TYPE(greens_fn_type), POINTER :: green
454 : TYPE(mp_comm_type) :: group
455 : TYPE(mp_para_env_type), POINTER :: para_env
456 48 : TYPE(pw_c1d_gs_type), DIMENSION(3) :: dphi_g
457 : TYPE(pw_c1d_gs_type), POINTER :: phi_g, rhob_g
458 : TYPE(pw_grid_type), POINTER :: grid_spme
459 : TYPE(pw_poisson_type), POINTER :: poisson_env
460 : TYPE(pw_pool_type), POINTER :: pw_pool
461 : TYPE(pw_r3d_rs_type), POINTER :: rhob_r
462 : TYPE(realspace_grid_desc_type), POINTER :: rs_desc
463 468 : TYPE(realspace_grid_type) :: rden, rpot
464 432 : TYPE(realspace_grid_type), DIMENSION(3) :: drpot
465 :
466 12 : CALL timeset(routineN, handle)
467 : !-------------- INITIALISATION ---------------------
468 : CALL ewald_env_get(ewald_env, alpha=alpha, o_spline=o_spline, group=group, &
469 12 : para_env=para_env)
470 12 : NULLIFY (green, poisson_env, pw_pool)
471 : CALL ewald_pw_get(ewald_pw, pw_big_pool=pw_pool, rs_desc=rs_desc, &
472 12 : poisson_env=poisson_env)
473 12 : CALL pw_poisson_rebuild(poisson_env)
474 12 : green => poisson_env%green_fft
475 12 : grid_spme => pw_pool%pw_grid
476 :
477 12 : CALL get_pw_grid_info(grid_spme, dvol=dvols, npts=npts)
478 :
479 12 : npart = SIZE(particle_set)
480 :
481 12 : n = o_spline
482 60 : ALLOCATE (rhos(n, n, n))
483 :
484 12 : CALL rs_grid_create(rden, rs_desc)
485 12 : CALL rs_grid_set_box(grid_spme, rs=rden)
486 12 : CALL rs_grid_zero(rden)
487 :
488 60 : ALLOCATE (center(3, npart), delta(3, npart))
489 12 : CALL get_center(particle_set, box, center, delta, npts, n)
490 :
491 : !-------------- DENSITY CALCULATION ----------------
492 12 : ipart = 0
493 206 : DO
494 218 : CALL set_list(particle_set, npart, center, p1, rden, ipart)
495 218 : IF (p1 == 0) EXIT
496 :
497 : ! calculate function on small boxes
498 : CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
499 206 : is_shell=.FALSE., unit_charge=.TRUE.)
500 53354 : rhos(:, :, :) = rhos(:, :, :)*mcharge(p1)
501 :
502 : ! add boxes to real space grid (big box)
503 218 : CALL dg_sum_patch(rden, rhos, center(:, p1))
504 : END DO
505 :
506 12 : NULLIFY (rhob_r)
507 12 : ALLOCATE (rhob_r)
508 12 : CALL pw_pool%create_pw(rhob_r)
509 :
510 12 : CALL transfer_rs2pw(rden, rhob_r)
511 :
512 : ! transform density to G space and add charge function
513 12 : NULLIFY (rhob_g)
514 12 : ALLOCATE (rhob_g)
515 12 : CALL pw_pool%create_pw(rhob_g)
516 12 : CALL pw_transfer(rhob_r, rhob_g)
517 : ! update charge function
518 12 : CALL pw_multiply_with(rhob_g, green%p3m_charge)
519 :
520 : !-------------- ELECTROSTATIC CALCULATION -----------
521 :
522 : ! allocate intermediate arrays
523 48 : DO i = 1, 3
524 48 : CALL pw_pool%create_pw(dphi_g(i))
525 : END DO
526 12 : NULLIFY (phi_g)
527 12 : ALLOCATE (phi_g)
528 12 : CALL pw_pool%create_pw(phi_g)
529 12 : CALL pw_poisson_solve(poisson_env, rhob_g, vgc, phi_g, dphi_g)
530 :
531 12 : CALL rs_grid_create(rpot, rs_desc)
532 12 : CALL rs_grid_set_box(grid_spme, rs=rpot)
533 :
534 12 : CALL pw_pool%give_back_pw(rhob_g)
535 12 : DEALLOCATE (rhob_g)
536 :
537 12 : CALL rs_grid_zero(rpot)
538 12 : CALL pw_multiply_with(phi_g, green%p3m_charge)
539 12 : CALL pw_transfer(phi_g, rhob_r)
540 12 : CALL pw_pool%give_back_pw(phi_g)
541 12 : DEALLOCATE (phi_g)
542 12 : CALL transfer_pw2rs(rpot, rhob_r)
543 :
544 : !---------- END OF ELECTROSTATIC CALCULATION --------
545 :
546 : ! move derivative of potential to real space grid and
547 : ! multiply by charge function in g-space
548 48 : DO i = 1, 3
549 36 : CALL rs_grid_create(drpot(i), rs_desc)
550 36 : CALL rs_grid_set_box(grid_spme, rs=drpot(i))
551 36 : CALL pw_multiply_with(dphi_g(i), green%p3m_charge)
552 36 : CALL pw_transfer(dphi_g(i), rhob_r)
553 36 : CALL pw_pool%give_back_pw(dphi_g(i))
554 48 : CALL transfer_pw2rs(drpot(i), rhob_r)
555 : END DO
556 12 : CALL pw_pool%give_back_pw(rhob_r)
557 12 : DEALLOCATE (rhob_r)
558 :
559 : !----------------- FORCE CALCULATION ----------------
560 :
561 12 : ipart = 0
562 206 : DO
563 :
564 218 : CALL set_list(particle_set, npart, center, p1, rden, ipart)
565 218 : IF (p1 == 0) EXIT
566 :
567 : ! calculate function on small boxes
568 : CALL get_patch(particle_set, delta, green, p1, rhos, is_core=.FALSE., &
569 206 : is_shell=.FALSE., unit_charge=.TRUE.)
570 :
571 206 : CALL dg_sum_patch_force_1d(rpot, rhos, center(:, p1), fint)
572 206 : gmcharge(p1, 1) = gmcharge(p1, 1) + fint*dvols
573 :
574 206 : CALL dg_sum_patch_force_3d(drpot, rhos, center(:, p1), fat)
575 206 : gmcharge(p1, 2) = gmcharge(p1, 2) - fat(1)*dvols
576 206 : gmcharge(p1, 3) = gmcharge(p1, 3) - fat(2)*dvols
577 206 : gmcharge(p1, 4) = gmcharge(p1, 4) - fat(3)*dvols
578 :
579 : END DO
580 :
581 : !--------------END OF FORCE CALCULATION -------------
582 :
583 : !------------------CLEANING UP ----------------------
584 :
585 12 : CALL rs_grid_release(rden)
586 12 : CALL rs_grid_release(rpot)
587 48 : DO i = 1, 3
588 48 : CALL rs_grid_release(drpot(i))
589 : END DO
590 12 : DEALLOCATE (rhos)
591 12 : DEALLOCATE (center, delta)
592 :
593 12 : CALL timestop(handle)
594 :
595 36 : END SUBROUTINE tb_spme_zforce
596 :
597 : END MODULE ewald_methods_tb
598 :
|