(git:f56c6e3)
Loading...
Searching...
No Matches
ewalds.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \par History
10!> JGH (15-Mar-2001) : New routine ewald_setup (former pme_setup)
11!> JGH (23-Mar-2001) : Get rid of global variable ewald_grp
12! **************************************************************************************************
13MODULE ewalds
14
17 USE bibliography, ONLY: ewald1921,&
18 cite_reference
19 USE cell_types, ONLY: cell_type
21 USE dg_types, ONLY: dg_get,&
26 USE ewald_pw_types, ONLY: ewald_pw_get,&
28 USE kinds, ONLY: dp
29 USE mathconstants, ONLY: fourpi,&
30 oorootpi,&
31 pi,&
32 z_zero
44#include "./base/base_uses.f90"
45
46 IMPLICIT NONE
47 LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .true.
48 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ewalds'
49
50 PRIVATE
52
53CONTAINS
54
55! **************************************************************************************************
56!> \brief computes the potential and the force from the g-space part of
57!> the 1/r potential
58!> Ref.: J.-P. Hansen, Enrico Fermi School, 1985
59!> Note: Only the positive G-vectors are used in the sum.
60!> \param ewald_env ...
61!> \param ewald_pw ...
62!> \param cell ...
63!> \param atomic_kind_set ...
64!> \param particle_set ...
65!> \param local_particles ...
66!> \param fg_coulomb ...
67!> \param vg_coulomb ...
68!> \param pv_g ...
69!> \param use_virial ...
70!> \param charges ...
71!> \param e_coulomb ...
72!> \par History
73!> JGH (21-Feb-2001) : changed name
74!> \author CJM
75! **************************************************************************************************
76 SUBROUTINE ewald_evaluate(ewald_env, ewald_pw, cell, atomic_kind_set, particle_set, &
77 local_particles, fg_coulomb, vg_coulomb, pv_g, use_virial, charges, e_coulomb)
78 TYPE(ewald_environment_type), POINTER :: ewald_env
79 TYPE(ewald_pw_type), POINTER :: ewald_pw
80 TYPE(cell_type), POINTER :: cell
81 TYPE(atomic_kind_type), POINTER :: atomic_kind_set(:)
82 TYPE(particle_type), POINTER :: particle_set(:)
83 TYPE(distribution_1d_type), POINTER :: local_particles
84 REAL(kind=dp), DIMENSION(:, :), INTENT(OUT) :: fg_coulomb
85 REAL(kind=dp), INTENT(OUT) :: vg_coulomb
86 REAL(kind=dp), DIMENSION(:, :), INTENT(OUT) :: pv_g
87 LOGICAL, INTENT(IN) :: use_virial
88 REAL(kind=dp), DIMENSION(:), OPTIONAL, POINTER :: charges, e_coulomb
89
90 CHARACTER(LEN=*), PARAMETER :: routinen = 'ewald_evaluate'
91
92 COMPLEX(KIND=dp) :: snode
93 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:) :: summe
94 INTEGER :: gpt, handle, iparticle, iparticle_kind, &
95 iparticle_local, lp, mp, nnodes, node, &
96 np, nparticle_kind, nparticle_local
97 INTEGER, DIMENSION(:, :), POINTER :: bds
98 LOGICAL :: atenergy, use_charge_array
99 REAL(kind=dp) :: alpha, denom, e_igdotr, factor, &
100 four_alpha_sq, gauss, pref, q
101 REAL(kind=dp), DIMENSION(3) :: vec
102 REAL(kind=dp), DIMENSION(:), POINTER :: charge
103 REAL(kind=dp), DIMENSION(:, :, :), POINTER :: rho0
104 TYPE(atomic_kind_type), POINTER :: atomic_kind
105 TYPE(dg_rho0_type), POINTER :: dg_rho0
106 TYPE(dg_type), POINTER :: dg
107 TYPE(mp_comm_type) :: group
108 TYPE(pw_grid_type), POINTER :: pw_grid
109 TYPE(pw_pool_type), POINTER :: pw_pool
110 TYPE(structure_factor_type) :: exp_igr
111
112 CALL timeset(routinen, handle)
113 CALL cite_reference(ewald1921)
114 use_charge_array = .false.
115 IF (PRESENT(charges)) use_charge_array = ASSOCIATED(charges)
116 atenergy = PRESENT(e_coulomb)
117 IF (atenergy) atenergy = ASSOCIATED(e_coulomb)
118 IF (atenergy) e_coulomb = 0._dp
119
120 ! pointing
121 CALL ewald_env_get(ewald_env, alpha=alpha, group=group)
122 CALL ewald_pw_get(ewald_pw, pw_big_pool=pw_pool, dg=dg)
123 CALL dg_get(dg, dg_rho0=dg_rho0)
124 rho0 => dg_rho0%density%array
125 pw_grid => pw_pool%pw_grid
126 bds => pw_grid%bounds
127
128 ! allocating
129 nparticle_kind = SIZE(atomic_kind_set)
130 nnodes = 0
131 DO iparticle_kind = 1, nparticle_kind
132 nnodes = nnodes + local_particles%n_el(iparticle_kind)
133 END DO
134
135 CALL structure_factor_allocate(pw_grid%bounds, nnodes, exp_igr)
136
137 ALLOCATE (summe(1:pw_grid%ngpts_cut))
138 ALLOCATE (charge(1:nnodes))
139
140 ! Initializing vg_coulomb and fg_coulomb
141 vg_coulomb = 0.0_dp
142 fg_coulomb = 0.0_dp
143 IF (use_virial) pv_g = 0.0_dp
144 ! defining four_alpha_sq
145 four_alpha_sq = 4.0_dp*alpha**2
146 ! zero node count
147 node = 0
148 DO iparticle_kind = 1, nparticle_kind
149 nparticle_local = local_particles%n_el(iparticle_kind)
150 IF (use_charge_array) THEN
151 DO iparticle_local = 1, nparticle_local
152 node = node + 1
153 iparticle = local_particles%list(iparticle_kind)%array(iparticle_local)
154 charge(node) = charges(iparticle)
155 vec = matmul(cell%h_inv, particle_set(iparticle)%r)
156 CALL structure_factor_evaluate(vec, exp_igr%lb, &
157 exp_igr%ex(:, node), exp_igr%ey(:, node), exp_igr%ez(:, node))
158 END DO
159 ELSE
160 atomic_kind => atomic_kind_set(iparticle_kind)
161 CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q)
162 DO iparticle_local = 1, nparticle_local
163 node = node + 1
164 iparticle = local_particles%list(iparticle_kind)%array(iparticle_local)
165 charge(node) = q
166 vec = matmul(cell%h_inv, particle_set(iparticle)%r)
167 CALL structure_factor_evaluate(vec, exp_igr%lb, &
168 exp_igr%ex(:, node), exp_igr%ey(:, node), exp_igr%ez(:, node))
169 END DO
170 END IF
171 END DO
172
173 summe(:) = z_zero
174 ! looping over the positive g-vectors
175 DO gpt = 1, pw_grid%ngpts_cut_local
176
177 lp = pw_grid%mapl%pos(pw_grid%g_hat(1, gpt))
178 mp = pw_grid%mapm%pos(pw_grid%g_hat(2, gpt))
179 np = pw_grid%mapn%pos(pw_grid%g_hat(3, gpt))
180
181 lp = lp + bds(1, 1)
182 mp = mp + bds(1, 2)
183 np = np + bds(1, 3)
184
185 ! initializing sum to be used in the energy and force
186 DO node = 1, nnodes
187 summe(gpt) = summe(gpt) + charge(node)* &
188 (exp_igr%ex(lp, node) &
189 *exp_igr%ey(mp, node) &
190 *exp_igr%ez(np, node))
191 END DO
192 END DO
193 CALL group%sum(summe)
194
195 pref = fourpi/pw_grid%vol
196
197 ! looping over the positive g-vectors
198 DO gpt = 1, pw_grid%ngpts_cut_local
199 ! computing the potential energy
200 lp = pw_grid%mapl%pos(pw_grid%g_hat(1, gpt))
201 mp = pw_grid%mapm%pos(pw_grid%g_hat(2, gpt))
202 np = pw_grid%mapn%pos(pw_grid%g_hat(3, gpt))
203
204 lp = lp + bds(1, 1)
205 mp = mp + bds(1, 2)
206 np = np + bds(1, 3)
207
208 IF (pw_grid%gsq(gpt) <= 1.0e-10_dp) cycle
209
210 gauss = (rho0(lp, mp, np)*pw_grid%vol)**2/pw_grid%gsq(gpt)
211 factor = gauss*real(summe(gpt)*conjg(summe(gpt)), kind=dp)
212 vg_coulomb = vg_coulomb + factor
213
214 ! atomic energies
215 IF (atenergy) THEN
216 DO node = 1, nnodes
217 snode = conjg(exp_igr%ex(lp, node) &
218 *exp_igr%ey(mp, node) &
219 *exp_igr%ez(np, node))
220 e_coulomb(node) = e_coulomb(node) + gauss*charge(node)*real(summe(gpt)*snode, kind=dp)
221 END DO
222 END IF
223
224 ! computing the force
225 node = 0
226 DO node = 1, nnodes
227 e_igdotr = aimag(summe(gpt)*conjg &
228 (exp_igr%ex(lp, node) &
229 *exp_igr%ey(mp, node) &
230 *exp_igr%ez(np, node)))
231 fg_coulomb(:, node) = fg_coulomb(:, node) &
232 + charge(node)*gauss*e_igdotr*pw_grid%g(:, gpt)
233 END DO
234
235 ! compute the virial P*V
236 denom = 1.0_dp/four_alpha_sq + 1.0_dp/pw_grid%gsq(gpt)
237 IF (use_virial) THEN
238 pv_g(1, 1) = pv_g(1, 1) + factor*(1.0_dp - 2.0_dp*pw_grid%g(1, gpt)*pw_grid%g(1, gpt)*denom)
239 pv_g(1, 2) = pv_g(1, 2) - factor*(2.0_dp*pw_grid%g(1, gpt)*pw_grid%g(2, gpt)*denom)
240 pv_g(1, 3) = pv_g(1, 3) - factor*(2.0_dp*pw_grid%g(1, gpt)*pw_grid%g(3, gpt)*denom)
241 pv_g(2, 1) = pv_g(2, 1) - factor*(2.0_dp*pw_grid%g(2, gpt)*pw_grid%g(1, gpt)*denom)
242 pv_g(2, 2) = pv_g(2, 2) + factor*(1.0_dp - 2.0_dp*pw_grid%g(2, gpt)*pw_grid%g(2, gpt)*denom)
243 pv_g(2, 3) = pv_g(2, 3) - factor*(2.0_dp*pw_grid%g(2, gpt)*pw_grid%g(3, gpt)*denom)
244 pv_g(3, 1) = pv_g(3, 1) - factor*(2.0_dp*pw_grid%g(3, gpt)*pw_grid%g(1, gpt)*denom)
245 pv_g(3, 2) = pv_g(3, 2) - factor*(2.0_dp*pw_grid%g(3, gpt)*pw_grid%g(2, gpt)*denom)
246 pv_g(3, 3) = pv_g(3, 3) + factor*(1.0_dp - 2.0_dp*pw_grid%g(3, gpt)*pw_grid%g(3, gpt)*denom)
247 END IF
248 END DO
249
250 vg_coulomb = vg_coulomb*pref
251 IF (use_virial) pv_g = pv_g*pref
252 IF (atenergy) e_coulomb = e_coulomb*pref
253
254 fg_coulomb = fg_coulomb*(2.0_dp*pref)
255
256 CALL structure_factor_deallocate(exp_igr)
257
258 DEALLOCATE (charge, summe)
259
260 CALL timestop(handle)
261
262 END SUBROUTINE ewald_evaluate
263
264! **************************************************************************************************
265!> \brief Computes the self interaction from g-space
266!> and the neutralizing background
267!> \param ewald_env ...
268!> \param cell ...
269!> \param atomic_kind_set ...
270!> \param local_particles ...
271!> \param e_self ...
272!> \param e_neut ...
273!> \param charges ...
274!> \par History
275!> none
276!> \author CJM
277! **************************************************************************************************
278 SUBROUTINE ewald_self(ewald_env, cell, atomic_kind_set, local_particles, e_self, &
279 e_neut, charges)
280
281 TYPE(ewald_environment_type), POINTER :: ewald_env
282 TYPE(cell_type), POINTER :: cell
283 TYPE(atomic_kind_type), POINTER :: atomic_kind_set(:)
284 TYPE(distribution_1d_type), POINTER :: local_particles
285 REAL(kind=dp), INTENT(OUT) :: e_self, e_neut
286 REAL(kind=dp), DIMENSION(:), POINTER :: charges
287
288 INTEGER :: ewald_type, iparticle_kind, &
289 nparticle_kind, nparticle_local
290 LOGICAL :: is_shell
291 REAL(kind=dp) :: alpha, mm_radius, q, q_neutg, q_self, &
292 q_sum, qcore, qshell
293 TYPE(atomic_kind_type), POINTER :: atomic_kind
294 TYPE(mp_comm_type) :: group
295 TYPE(shell_kind_type), POINTER :: shell
296
297 CALL ewald_env_get(ewald_env, ewald_type=ewald_type, &
298 alpha=alpha, group=group)
299 q_neutg = 0.0_dp
300 q_self = 0.0_dp
301 q_sum = 0.0_dp
302 nparticle_kind = SIZE(atomic_kind_set)
303 IF (ASSOCIATED(charges)) THEN
304 q_self = dot_product(charges, charges)
305 q_sum = sum(charges)
306 ! check and abort..
307 DO iparticle_kind = 1, nparticle_kind
308 atomic_kind => atomic_kind_set(iparticle_kind)
309 CALL get_atomic_kind(atomic_kind=atomic_kind, mm_radius=mm_radius)
310 IF (mm_radius > 0.0_dp) THEN
311 cpabort("Array of charges not implemented for mm_radius > 0.0")
312 END IF
313 END DO
314 ELSE
315 DO iparticle_kind = 1, nparticle_kind
316 atomic_kind => atomic_kind_set(iparticle_kind)
317 CALL get_atomic_kind(atomic_kind=atomic_kind, mm_radius=mm_radius, &
318 qeff=q, shell_active=is_shell, shell=shell)
319 nparticle_local = local_particles%n_el(iparticle_kind)
320 IF (is_shell) THEN
321 CALL get_shell(shell=shell, charge_core=qcore, charge_shell=qshell)
322 ! MI: the core-shell ES interaction, when core and shell belong to the same ion, is excluded
323 ! in the nonbond correction term. Therefore, here the self interaction is computed entirely
324 q_self = q_self + qcore*qcore*nparticle_local + qshell*qshell*nparticle_local
325 q_sum = q_sum + qcore*nparticle_local + qshell*nparticle_local
326 IF (mm_radius > 0) THEN
327 ! the core is always a point charge
328 q_neutg = q_neutg + 2.0_dp*qshell*mm_radius**2
329 END IF
330 ELSE
331 q_self = q_self + q*q*nparticle_local
332 q_sum = q_sum + q*nparticle_local
333 IF (mm_radius > 0) THEN
334 q_neutg = q_neutg + 2.0_dp*q*mm_radius**2
335 END IF
336 END IF
337 END DO
338
339 CALL group%sum(q_self)
340 CALL group%sum(q_sum)
341 END IF
342
343 e_neut = 0.0_dp
344 e_self = 0.0_dp
345 IF (ewald_type /= do_ewald_none) THEN
346 e_self = -q_self*alpha*oorootpi
347 e_neut = -q_sum*pi/(2.0_dp*cell%deth)*(q_sum/alpha**2 - q_neutg)
348 END IF
349
350 END SUBROUTINE ewald_self
351
352! **************************************************************************************************
353!> \brief Computes the self interaction per atom
354!> \param ewald_env ...
355!> \param atomic_kind_set ...
356!> \param local_particles ...
357!> \param e_self ...
358!> \param charges ...
359!> \par History
360!> none
361!> \author JHU from ewald_self
362! **************************************************************************************************
363 SUBROUTINE ewald_self_atom(ewald_env, atomic_kind_set, local_particles, e_self, &
364 charges)
365
366 TYPE(ewald_environment_type), POINTER :: ewald_env
367 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set(:)
368 TYPE(distribution_1d_type), POINTER :: local_particles
369 REAL(kind=dp), DIMENSION(:), INTENT(INOUT) :: e_self(:)
370 REAL(kind=dp), DIMENSION(:), POINTER :: charges
371
372 INTEGER :: ewald_type, ii, iparticle_kind, &
373 iparticle_local, nparticle_kind, &
374 nparticle_local
375 LOGICAL :: is_shell
376 REAL(kind=dp) :: alpha, fself, q, qcore, qshell
377 TYPE(atomic_kind_type), POINTER :: atomic_kind
378 TYPE(shell_kind_type), POINTER :: shell
379
380 CALL ewald_env_get(ewald_env, ewald_type=ewald_type, alpha=alpha)
381
382 fself = alpha*oorootpi
383
384 IF (ewald_type /= do_ewald_none) THEN
385 nparticle_kind = SIZE(atomic_kind_set)
386 IF (ASSOCIATED(charges)) THEN
387 cpabort("Atomic energy not implemented for charges")
388 ELSE
389 DO iparticle_kind = 1, nparticle_kind
390 atomic_kind => atomic_kind_set(iparticle_kind)
391 nparticle_local = local_particles%n_el(iparticle_kind)
392 CALL get_atomic_kind(atomic_kind=atomic_kind, qeff=q, &
393 shell_active=is_shell, shell=shell)
394 IF (is_shell) THEN
395 CALL get_shell(shell=shell, charge_core=qcore, charge_shell=qshell)
396 DO iparticle_local = 1, nparticle_local
397 ii = local_particles%list(iparticle_kind)%array(iparticle_local)
398 e_self(ii) = e_self(ii) - (qcore*qcore + qshell*qshell)*fself
399 END DO
400 ELSE
401 DO iparticle_local = 1, nparticle_local
402 ii = local_particles%list(iparticle_kind)%array(iparticle_local)
403 e_self(ii) = e_self(ii) - q*q*fself
404 END DO
405 END IF
406 END DO
407 END IF
408 END IF
409
410 END SUBROUTINE ewald_self_atom
411
412! **************************************************************************************************
413!> \brief ...
414!> \param iw ...
415!> \param pot_nonbond ...
416!> \param e_gspace ...
417!> \param e_self ...
418!> \param e_neut ...
419!> \param e_bonded ...
420!> \par History
421!> none
422!> \author CJM
423! **************************************************************************************************
424 SUBROUTINE ewald_print(iw, pot_nonbond, e_gspace, e_self, e_neut, e_bonded)
425
426 INTEGER, INTENT(IN) :: iw
427 REAL(kind=dp), INTENT(IN) :: pot_nonbond, e_gspace, e_self, e_neut, &
428 e_bonded
429
430 IF (iw > 0) THEN
431 WRITE (iw, '( A, A )') ' *********************************', &
432 '**********************************************'
433 WRITE (iw, '( A, A, T35, A, T56, E25.15 )') ' INITIAL GSPACE ENERGY', &
434 '[hartree]', '= ', e_gspace
435 WRITE (iw, '( A, A, T35, A, T56, E25.15 )') ' INITIAL NONBONDED ENERGY', &
436 '[hartree]', '= ', pot_nonbond
437 WRITE (iw, '( A, A, T35, A, T56, E25.15 )') ' SELF ENERGY CORRECTION', &
438 '[hartree]', '= ', e_self
439 WRITE (iw, '( A, A, T35, A, T56, E25.15 )') ' NEUT. BACKGROUND', &
440 '[hartree]', '= ', e_neut
441 WRITE (iw, '( A, A, T35, A, T56, E25.15 )') ' BONDED CORRECTION', &
442 '[hartree]', '= ', e_bonded
443 WRITE (iw, '( A, A )') ' *********************************', &
444 '**********************************************'
445 END IF
446 END SUBROUTINE ewald_print
447
448END MODULE ewalds
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public ewald1921
Handles all functions related to the CELL.
Definition cell_types.F:15
subroutine, public dg_get(dg, dg_rho0)
Get the dg_type.
Definition dg_types.F:44
stores a lists of integer that are local to a processor. The idea is that these integers represent ob...
subroutine, public ewald_env_get(ewald_env, ewald_type, alpha, eps_pol, epsilon, gmax, ns_max, o_spline, group, para_env, poisson_section, precs, rcut, do_multipoles, max_multipole, do_ipol, max_ipol_iter, interaction_cutoffs, cell_hmat)
Purpose: Get the EWALD environment.
subroutine, public ewald_pw_get(ewald_pw, pw_big_pool, pw_small_pool, rs_desc, poisson_env, dg)
get the ewald_pw environment to the correct program.
subroutine, public ewald_self_atom(ewald_env, atomic_kind_set, local_particles, e_self, charges)
Computes the self interaction per atom.
Definition ewalds.F:365
subroutine, public ewald_evaluate(ewald_env, ewald_pw, cell, atomic_kind_set, particle_set, local_particles, fg_coulomb, vg_coulomb, pv_g, use_virial, charges, e_coulomb)
computes the potential and the force from the g-space part of the 1/r potential Ref....
Definition ewalds.F:78
subroutine, public ewald_print(iw, pot_nonbond, e_gspace, e_self, e_neut, e_bonded)
...
Definition ewalds.F:425
subroutine, public ewald_self(ewald_env, cell, atomic_kind_set, local_particles, e_self, e_neut, charges)
Computes the self interaction from g-space and the neutralizing background.
Definition ewalds.F:280
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Definition of mathematical constants and functions.
real(kind=dp), parameter, public oorootpi
real(kind=dp), parameter, public pi
real(kind=dp), parameter, public fourpi
complex(kind=dp), parameter, public z_zero
Interface to the message passing library MPI.
Define the data structure for the particle information.
functions related to the poisson solver on regular grids
integer, parameter, public do_ewald_none
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...
elemental subroutine, public get_shell(shell, charge, charge_core, charge_shell, mass_core, mass_shell, k2_spring, k4_spring, max_dist, shell_cutoff)
...
subroutine, public structure_factor_deallocate(exp_igr)
...
subroutine, public structure_factor_allocate(bds, nparts, exp_igr, allocate_centre, allocate_shell_e, allocate_shell_centre, nshell)
...
subroutine, public structure_factor_evaluate(delta, lb, ex, ey, ez)
...
Provides all information about an atomic kind.
Type defining parameters related to the simulation cell.
Definition cell_types.F:55
Type for Gaussian Densities type = type of gaussian (PME) grid = grid number gcc = Gaussian contracti...
structure to store local (to a processor) ordered lists of integers.
Manages a pool of grids (to be used for example as tmp objects), but can also be used to instantiate ...