95 SUBROUTINE pme_evaluate(ewald_env, ewald_pw, box, particle_set, vg_coulomb, &
96 fg_coulomb, pv_g, shell_particle_set, core_particle_set, &
97 fgshell_coulomb, fgcore_coulomb, use_virial, charges, atprop)
102 REAL(kind=
dp),
INTENT(OUT) :: vg_coulomb
103 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT), &
104 OPTIONAL :: fg_coulomb, pv_g
106 POINTER :: shell_particle_set, core_particle_set
107 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT), &
108 OPTIONAL :: fgshell_coulomb, fgcore_coulomb
109 LOGICAL,
INTENT(IN) :: use_virial
110 REAL(kind=
dp),
DIMENSION(:),
OPTIONAL,
POINTER :: charges
113 CHARACTER(LEN=*),
PARAMETER :: routinen =
'pme_evaluate'
115 INTEGER :: handle, i, ig, ipart, j, nd(3), npart, &
117 LOGICAL :: is1_core, is2_core
118 REAL(kind=
dp) :: alpha, dvols, fat1, ffa, ffb
119 REAL(kind=
dp),
DIMENSION(3) :: fat
120 REAL(kind=
dp),
DIMENSION(3, 3) :: f_stress, h_stress
128 TYPE(
pw_pool_type),
POINTER :: pw_big_pool, pw_small_pool
135 CALL timeset(routinen, handle)
136 NULLIFY (poisson_env, rden)
140 pw_small_pool=pw_small_pool, rs_desc=rs_desc, &
141 poisson_env=poisson_env, dg=dg)
143 grid_b => pw_big_pool%pw_grid
144 grid_s => pw_small_pool%pw_grid
146 CALL dg_get(dg, dg_rho0=dg_rho0)
148 npart =
SIZE(particle_set)
152 IF (
PRESENT(shell_particle_set))
THEN
153 cpassert(
ASSOCIATED(shell_particle_set))
154 cpassert(
ASSOCIATED(core_particle_set))
155 nshell =
SIZE(shell_particle_set)
157 allocate_centre=.true., allocate_shell_e=.true., &
158 allocate_shell_centre=.true., nshell=nshell)
162 allocate_centre=.true.)
165 CALL pw_small_pool%create_pw(rhos1)
166 CALL pw_small_pool%create_pw(rhos2)
173 cpassert(
ASSOCIATED(box))
175 IF (rden%desc%parallel .AND. rden%desc%distributed)
THEN
176 CALL get_center(particle_set, box, exp_igr%centre, exp_igr%delta, grid_b%npts, 1)
178 IF (
PRESENT(shell_particle_set) .AND. rden%desc%parallel .AND. rden%desc%distributed)
THEN
179 CALL get_center(shell_particle_set, box, exp_igr%shell_centre, exp_igr%shell_delta, grid_b%npts, 1)
180 CALL get_center(core_particle_set, box, exp_igr%core_centre, exp_igr%core_delta, grid_b%npts, 1)
188 CALL set_list(particle_set, npart, exp_igr%centre, p1, rden, ipart, exp_igr%core_centre)
189 CALL set_list(particle_set, npart, exp_igr%centre, p2, rden, ipart, exp_igr%core_centre)
190 IF (p1 == 0 .AND. p2 == 0)
EXIT
192 is1_core = (particle_set(p1)%shell_index /= 0)
194 is2_core = (particle_set(p2)%shell_index /= 0)
200 IF (is1_core .OR. is2_core)
THEN
201 CALL get_patch(dg, particle_set, exp_igr, box, p1, p2, grid_b, grid_s, &
202 rhos1, rhos2, is1_core=is1_core, is2_core=is2_core, &
203 core_particle_set=core_particle_set, charges=charges)
207 CALL dg_sum_patch(rden, rhos1, exp_igr%core_centre(:, particle_set(p1)%shell_index))
211 IF (p2 /= 0 .AND. is2_core)
THEN
212 CALL dg_sum_patch(rden, rhos2, exp_igr%core_centre(:, particle_set(p2)%shell_index))
213 ELSE IF (p2 /= 0)
THEN
217 CALL get_patch(dg, particle_set, exp_igr, box, p1, p2, grid_b, grid_s, &
218 rhos1, rhos2, charges=charges)
221 IF (p2 /= 0)
CALL dg_sum_patch(rden, rhos2, exp_igr%centre(:, p2))
225 IF (
PRESENT(shell_particle_set))
THEN
228 CALL set_list(shell_particle_set, nshell, exp_igr%shell_centre, p1, rpot, ipart)
229 CALL set_list(shell_particle_set, nshell, exp_igr%shell_centre, p2, rpot, ipart)
230 IF (p1 == 0 .AND. p2 == 0)
EXIT
232 CALL get_patch(dg, shell_particle_set, exp_igr, box, p1, p2, grid_b, grid_s, &
233 rhos1, rhos2, is1_shell=.true., is2_shell=.true., charges=charges)
235 CALL dg_sum_patch(rpot, rhos1, exp_igr%shell_centre(:, p1))
236 IF (p2 /= 0)
CALL dg_sum_patch(rpot, rhos2, exp_igr%shell_centre(:, p2))
240 CALL pw_big_pool%create_pw(rhob_r)
247 CALL pw_big_pool%create_pw(dphi_g(i))
249 CALL pw_big_pool%create_pw(phi_r)
251 CALL pw_poisson_solve(poisson_env, rhob_r, vg_coulomb, phi_r, dphi_g, h_stress)
254 IF (atprop%energy .OR. atprop%stress)
THEN
255 dvols = rhos1%pw_grid%dvol
261 CALL set_list(particle_set, npart, exp_igr%centre, p1, rden, ipart, exp_igr%core_centre)
262 CALL set_list(particle_set, npart, exp_igr%centre, p2, rden, ipart, exp_igr%core_centre)
263 IF (p1 == 0 .AND. p2 == 0)
EXIT
265 CALL get_patch(dg, particle_set, exp_igr, box, p1, p2, grid_b, grid_s, &
266 rhos1, rhos2, charges=charges)
269 IF (atprop%energy)
THEN
270 atprop%atener(p1) = atprop%atener(p1) + 0.5_dp*fat1*dvols
272 IF (atprop%stress)
THEN
273 atprop%atstress(1, 1, p1) = atprop%atstress(1, 1, p1) + 0.5_dp*fat1*dvols
274 atprop%atstress(2, 2, p1) = atprop%atstress(2, 2, p1) + 0.5_dp*fat1*dvols
275 atprop%atstress(3, 3, p1) = atprop%atstress(3, 3, p1) + 0.5_dp*fat1*dvols
279 IF (atprop%energy)
THEN
280 atprop%atener(p2) = atprop%atener(p2) + 0.5_dp*fat1*dvols
282 IF (atprop%stress)
THEN
283 atprop%atstress(1, 1, p2) = atprop%atstress(1, 1, p2) + 0.5_dp*fat1*dvols
284 atprop%atstress(2, 2, p2) = atprop%atstress(2, 2, p2) + 0.5_dp*fat1*dvols
285 atprop%atstress(3, 3, p2) = atprop%atstress(3, 3, p2) + 0.5_dp*fat1*dvols
289 IF (atprop%stress)
THEN
290 CALL pw_big_pool%create_pw(phi_g)
291 CALL pw_big_pool%create_pw(rhob_g)
292 ffa = (0.5_dp/dg_rho0%zet(1))**2
295 DO ig = grid_b%first_gne0, grid_b%ngpts_cut_local
296 phi_g%array(ig) = ffb*dphi_g(i)%array(ig)*(ffa*grid_b%gsq(ig) + 1.0_dp)
297 phi_g%array(ig) = phi_g%array(ig)*poisson_env%green_fft%influence_fn%array(ig)
299 IF (grid_b%have_g0) phi_g%array(1) = 0.0_dp
310 CALL set_list(particle_set, npart, exp_igr%centre, p1, rden, ipart, exp_igr%core_centre)
311 CALL set_list(particle_set, npart, exp_igr%centre, p2, rden, ipart, exp_igr%core_centre)
312 IF (p1 == 0 .AND. p2 == 0)
EXIT
314 CALL get_patch(dg, particle_set, exp_igr, box, p1, p2, grid_b, grid_s, &
315 rhos1, rhos2, charges=charges)
318 atprop%atstress(i, j, p1) = atprop%atstress(i, j, p1) + fat1*dvols
319 IF (i /= j) atprop%atstress(j, i, p1) = atprop%atstress(j, i, p1) + fat1*dvols
322 atprop%atstress(i, j, p2) = atprop%atstress(i, j, p2) + fat1*dvols
323 IF (i /= j) atprop%atstress(j, i, p2) = atprop%atstress(j, i, p2) + fat1*dvols
328 CALL pw_big_pool%give_back_pw(phi_g)
329 CALL pw_big_pool%give_back_pw(rhob_g)
335 CALL pw_big_pool%give_back_pw(phi_r)
341 IF ((use_virial) .AND. (
PRESENT(pv_g)))
THEN
345 f_stress(j, i) = f_stress(i, j)
348 ffa = (1.0_dp/
fourpi)*(0.5_dp/dg_rho0%zet(1))**2
349 f_stress = -ffa*f_stress
350 pv_g = h_stress + f_stress
359 CALL pw_big_pool%give_back_pw(dphi_g(i))
363 CALL pw_big_pool%give_back_pw(rhob_r)
368 IF (
PRESENT(fg_coulomb))
THEN
370 dvols = rhos1%pw_grid%dvol
375 CALL set_list(particle_set, npart, exp_igr%centre, p1, rden, ipart, exp_igr%core_centre)
376 CALL set_list(particle_set, npart, exp_igr%centre, p2, rden, ipart, exp_igr%core_centre)
377 IF (p1 == 0 .AND. p2 == 0)
EXIT
379 is1_core = (particle_set(p1)%shell_index /= 0)
381 is2_core = (particle_set(p2)%shell_index /= 0)
388 CALL get_patch_again(dg, particle_set, exp_igr, p1, p2, rhos1, rhos2, &
389 is1_core=is1_core, is2_core=is2_core, charges=charges)
394 exp_igr%core_centre(:, particle_set(p1)%shell_index), fat)
395 fgcore_coulomb(1, particle_set(p1)%shell_index) = &
396 fgcore_coulomb(1, particle_set(p1)%shell_index) - fat(1)*dvols
397 fgcore_coulomb(2, particle_set(p1)%shell_index) = &
398 fgcore_coulomb(2, particle_set(p1)%shell_index) - fat(2)*dvols
399 fgcore_coulomb(3, particle_set(p1)%shell_index) = &
400 fgcore_coulomb(3, particle_set(p1)%shell_index) - fat(3)*dvols
403 fg_coulomb(1, p1) = fg_coulomb(1, p1) - fat(1)*dvols
404 fg_coulomb(2, p1) = fg_coulomb(2, p1) - fat(2)*dvols
405 fg_coulomb(3, p1) = fg_coulomb(3, p1) - fat(3)*dvols
407 IF (p2 /= 0 .AND. is2_core)
THEN
409 exp_igr%core_centre(:, particle_set(p2)%shell_index), fat)
410 fgcore_coulomb(1, particle_set(p2)%shell_index) = &
411 fgcore_coulomb(1, particle_set(p2)%shell_index) - fat(1)*dvols
412 fgcore_coulomb(2, particle_set(p2)%shell_index) = &
413 fgcore_coulomb(2, particle_set(p2)%shell_index) - fat(2)*dvols
414 fgcore_coulomb(3, particle_set(p2)%shell_index) = &
415 fgcore_coulomb(3, particle_set(p2)%shell_index) - fat(3)*dvols
416 ELSEIF (p2 /= 0)
THEN
418 fg_coulomb(1, p2) = fg_coulomb(1, p2) - fat(1)*dvols
419 fg_coulomb(2, p2) = fg_coulomb(2, p2) - fat(2)*dvols
420 fg_coulomb(3, p2) = fg_coulomb(3, p2) - fat(3)*dvols
425 IF (
PRESENT(fgshell_coulomb))
THEN
426 fgshell_coulomb = 0.0_dp
427 dvols = rhos1%pw_grid%dvol
431 CALL set_list(shell_particle_set, nshell, exp_igr%shell_centre, p1, rden, ipart)
432 CALL set_list(shell_particle_set, nshell, exp_igr%shell_centre, p2, rden, ipart)
433 IF (p1 == 0 .AND. p2 == 0)
EXIT
436 CALL get_patch_again(dg, shell_particle_set, exp_igr, p1, p2, rhos1, rhos2, &
437 is1_shell=.true., is2_shell=.true., charges=charges)
441 fgshell_coulomb(1, p1) = fgshell_coulomb(1, p1) - fat(1)*dvols
442 fgshell_coulomb(2, p1) = fgshell_coulomb(2, p1) - fat(2)*dvols
443 fgshell_coulomb(3, p1) = fgshell_coulomb(3, p1) - fat(3)*dvols
446 fgshell_coulomb(1, p2) = fgshell_coulomb(1, p2) - fat(1)*dvols
447 fgshell_coulomb(2, p2) = fgshell_coulomb(2, p2) - fat(2)*dvols
448 fgshell_coulomb(3, p2) = fgshell_coulomb(3, p2) - fat(3)*dvols
463 CALL pw_small_pool%give_back_pw(rhos1)
464 CALL pw_small_pool%give_back_pw(rhos2)
467 CALL timestop(handle)