Line data Source code
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 : !> \brief functions related to the poisson solver on regular grids
10 : !> \par History
11 : !> greens_fn: JGH (9-Mar-2001) : include influence_fn into
12 : !> greens_fn_type add cell volume
13 : !> as indicator for updates
14 : !> greens_fn: JGH (30-Mar-2001) : Added B-spline routines
15 : !> pws : JGH (13-Mar-2001) : new pw_poisson_solver, delete
16 : !> pw_greens_fn
17 : !> 12.2004 condensed from pws, greens_fn and green_fns, by apsi and JGH,
18 : !> made thread safe, new input [fawzi]
19 : !> 14-Mar-2006 : added short range screening function for SE codes
20 : !> \author fawzi
21 : ! **************************************************************************************************
22 : MODULE pw_poisson_types
23 : USE bessel_lib, ONLY: bessk0,&
24 : bessk1
25 : USE dielectric_types, ONLY: dielectric_parameters
26 : USE dirichlet_bc_types, ONLY: dirichlet_bc_parameters
27 : USE kinds, ONLY: dp
28 : USE mathconstants, ONLY: fourpi,&
29 : twopi,&
30 : z_zero
31 : USE mt_util, ONLY: MT0D,&
32 : MT1D,&
33 : MT2D,&
34 : MTin_create_screen_fn
35 : USE ps_implicit_types, ONLY: MIXED_BC,&
36 : NEUMANN_BC,&
37 : ps_implicit_parameters,&
38 : ps_implicit_release,&
39 : ps_implicit_type
40 : USE ps_wavelet_types, ONLY: WAVELET0D,&
41 : ps_wavelet_release,&
42 : ps_wavelet_type
43 : USE pw_grid_types, ONLY: pw_grid_type
44 : USE pw_grids, ONLY: pw_grid_release
45 : USE pw_pool_types, ONLY: pw_pool_create,&
46 : pw_pool_p_type,&
47 : pw_pool_release,&
48 : pw_pool_type,&
49 : pw_pools_dealloc
50 : USE pw_types, ONLY: pw_c1d_gs_type,&
51 : pw_r1d_gs_type
52 : USE realspace_grid_types, ONLY: realspace_grid_type,&
53 : rs_grid_release
54 : #include "../base/base_uses.f90"
55 :
56 : IMPLICIT NONE
57 : PRIVATE
58 :
59 : LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
60 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pw_poisson_types'
61 :
62 : PUBLIC :: pw_poisson_type
63 : PUBLIC :: greens_fn_type, pw_green_create, &
64 : pw_green_release
65 : PUBLIC :: pw_poisson_parameter_type
66 :
67 : INTEGER, PARAMETER, PUBLIC :: pw_poisson_none = 0, &
68 : pw_poisson_periodic = 1, &
69 : pw_poisson_analytic = 2, &
70 : pw_poisson_mt = 3, &
71 : pw_poisson_hockney = 5, &
72 : pw_poisson_multipole = 4, &
73 : pw_poisson_wavelet = 6, &
74 : pw_poisson_implicit = 7
75 : ! EWALD methods
76 : INTEGER, PARAMETER, PUBLIC :: do_ewald_none = 1, &
77 : do_ewald_ewald = 2, &
78 : do_ewald_pme = 3, &
79 : do_ewald_spme = 4
80 :
81 : INTEGER, PARAMETER, PUBLIC :: PERIODIC3D = 1000, &
82 : ANALYTIC2D = 1001, &
83 : ANALYTIC1D = 1002, &
84 : ANALYTIC0D = 1003, &
85 : HOCKNEY2D = 1201, &
86 : HOCKNEY1D = 1202, &
87 : HOCKNEY0D = 1203, &
88 : MULTIPOLE2D = 1301, &
89 : MULTIPOLE1D = 1302, &
90 : MULTIPOLE0D = 1303, &
91 : PS_IMPLICIT = 1400
92 :
93 : ! **************************************************************************************************
94 : !> \brief parameters for the poisson solver independet of input_section
95 : !> \author Ole Schuett
96 : ! **************************************************************************************************
97 : TYPE pw_poisson_parameter_type
98 : INTEGER :: solver = pw_poisson_none
99 :
100 : INTEGER, DIMENSION(3) :: periodic = 0
101 : INTEGER :: ewald_type = do_ewald_none
102 : INTEGER :: ewald_o_spline = 0
103 : REAL(KIND=dp) :: ewald_alpha = 0.0_dp
104 :
105 : REAL(KIND=dp) :: mt_rel_cutoff = 0.0_dp
106 : REAL(KIND=dp) :: mt_alpha = 0.0_dp
107 :
108 : INTEGER :: wavelet_scf_type = 0
109 : INTEGER :: wavelet_method = WAVELET0D
110 : INTEGER :: wavelet_special_dimension = 0
111 : CHARACTER(LEN=1) :: wavelet_geocode = "S"
112 :
113 : LOGICAL :: has_dielectric = .FALSE.
114 : TYPE(dielectric_parameters) :: dielectric_params = dielectric_parameters()
115 : TYPE(ps_implicit_parameters) :: ps_implicit_params = ps_implicit_parameters()
116 : TYPE(dirichlet_bc_parameters) :: dbc_params = dirichlet_bc_parameters()
117 : END TYPE pw_poisson_parameter_type
118 :
119 : ! **************************************************************************************************
120 : !> \brief environment for the poisson solver
121 : !> \author fawzi
122 : ! **************************************************************************************************
123 : TYPE pw_poisson_type
124 : INTEGER :: pw_level = 0
125 : INTEGER :: method = pw_poisson_none
126 : INTEGER :: used_grid = 0
127 : LOGICAL :: rebuild = .TRUE.
128 : TYPE(greens_fn_type), POINTER :: green_fft => NULL()
129 : TYPE(ps_wavelet_type), POINTER :: wavelet => NULL()
130 : TYPE(pw_poisson_parameter_type) :: parameters = pw_poisson_parameter_type()
131 : REAL(KIND=dp), DIMENSION(3, 3) :: cell_hmat = 0.0_dp
132 : TYPE(pw_pool_p_type), DIMENSION(:), POINTER :: pw_pools => NULL()
133 : TYPE(pw_grid_type), POINTER :: mt_super_ref_pw_grid => NULL()
134 : TYPE(ps_implicit_type), POINTER :: implicit_env => NULL()
135 : TYPE(pw_grid_type), POINTER :: dct_pw_grid => NULL()
136 : TYPE(realspace_grid_type), POINTER :: diel_rs_grid => NULL()
137 : CONTAINS
138 : PROCEDURE, PUBLIC, NON_OVERRIDABLE :: create => pw_poisson_create
139 : PROCEDURE, PUBLIC, NON_OVERRIDABLE :: release => pw_poisson_release
140 : END TYPE pw_poisson_type
141 :
142 : ! **************************************************************************************************
143 : !> \brief contains all the informations needed by the fft based poisson solvers
144 : !> \author JGH,Teo,fawzi
145 : ! **************************************************************************************************
146 : TYPE greens_fn_type
147 : INTEGER :: method = PERIODIC3D
148 : INTEGER :: special_dimension = 0
149 : REAL(KIND=dp) :: radius = 0.0_dp
150 : REAL(KIND=dp) :: MT_alpha = 1.0_dp
151 : REAL(KIND=dp) :: MT_rel_cutoff = 1.0_dp
152 : REAL(KIND=dp) :: slab_size = 0.0_dp
153 : REAL(KIND=dp) :: alpha = 0.0_dp
154 : LOGICAL :: p3m = .FALSE.
155 : INTEGER :: p3m_order = 0
156 : REAL(KIND=dp) :: p3m_alpha = 0.0_dp
157 : REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE :: p3m_coeff
158 : REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE :: p3m_bm2
159 : LOGICAL :: sr_screening = .FALSE.
160 : REAL(KIND=dp) :: sr_alpha = 1.0_dp
161 : REAL(KIND=dp) :: sr_rc = 0.0_dp
162 : TYPE(pw_c1d_gs_type) :: influence_fn = pw_c1d_gs_type()
163 : TYPE(pw_c1d_gs_type), POINTER :: dct_influence_fn => NULL()
164 : TYPE(pw_c1d_gs_type), POINTER :: screen_fn => NULL()
165 : TYPE(pw_r1d_gs_type), POINTER :: p3m_charge => NULL()
166 : END TYPE greens_fn_type
167 :
168 : CONTAINS
169 :
170 : ! **************************************************************************************************
171 : !> \brief Allocates and sets up the green functions for the fft based poisson
172 : !> solvers
173 : !> \param green ...
174 : !> \param poisson_params ...
175 : !> \param cell_hmat ...
176 : !> \param pw_pool ...
177 : !> \param mt_super_ref_pw_grid ...
178 : !> \param dct_pw_grid ...
179 : !> \author Fawzi, based on previous functions by JGH and Teo
180 : ! **************************************************************************************************
181 15794 : SUBROUTINE pw_green_create(green, poisson_params, cell_hmat, pw_pool, &
182 : mt_super_ref_pw_grid, dct_pw_grid)
183 : TYPE(greens_fn_type), INTENT(OUT) :: green
184 : TYPE(pw_poisson_parameter_type), INTENT(IN) :: poisson_params
185 : REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN) :: cell_hmat
186 : TYPE(pw_pool_type), POINTER :: pw_pool
187 : TYPE(pw_grid_type), POINTER :: mt_super_ref_pw_grid, dct_pw_grid
188 :
189 : INTEGER :: dim, i, ig, iz, n, nz
190 : REAL(KIND=dp) :: g2, g3d, gg, gxy, gz, j0g, j1g, k0g, &
191 : k1g, rlength, zlength
192 : REAL(KIND=dp), DIMENSION(3) :: abc
193 : TYPE(pw_c1d_gs_type), POINTER :: dct_gf
194 : TYPE(pw_grid_type), POINTER :: dct_grid
195 : TYPE(pw_pool_type), POINTER :: pw_pool_xpndd
196 :
197 : !CPASSERT(cell%orthorhombic)
198 63176 : DO i = 1, 3
199 63176 : abc(i) = cell_hmat(i, i)
200 : END DO
201 63176 : dim = COUNT(poisson_params%periodic == 1)
202 :
203 30116 : SELECT CASE (poisson_params%solver)
204 : CASE (pw_poisson_periodic)
205 : green%method = PERIODIC3D
206 14322 : IF (dim /= 3) THEN
207 0 : CPABORT("Illegal combination of periodicity and Poisson solver periodic3d")
208 : END IF
209 : CASE (pw_poisson_multipole)
210 20 : green%method = MULTIPOLE0D
211 20 : IF (dim /= 0) THEN
212 0 : CPABORT("Illegal combination of periodicity and Poisson solver mulipole0d")
213 : END IF
214 : CASE (pw_poisson_analytic)
215 1382 : SELECT CASE (dim)
216 : CASE (0)
217 170 : green%method = ANALYTIC0D
218 850 : green%radius = 0.5_dp*MINVAL(abc)
219 : CASE (1)
220 6 : green%method = ANALYTIC1D
221 24 : green%special_dimension = MAXLOC(poisson_params%periodic(1:3), 1)
222 30 : green%radius = MAXVAL(abc(1:3))
223 24 : DO i = 1, 3
224 18 : IF (i == green%special_dimension) CYCLE
225 24 : green%radius = MIN(green%radius, 0.5_dp*abc(i))
226 : END DO
227 : CASE (2)
228 8 : green%method = ANALYTIC2D
229 32 : i = MINLOC(poisson_params%periodic, 1)
230 8 : green%special_dimension = i
231 8 : green%slab_size = abc(i)
232 : CASE (3)
233 0 : green%method = PERIODIC3D
234 : CASE DEFAULT
235 186 : CPABORT("")
236 : END SELECT
237 : CASE (pw_poisson_mt)
238 1212 : green%MT_rel_cutoff = poisson_params%mt_rel_cutoff
239 1212 : green%MT_alpha = poisson_params%mt_alpha
240 6060 : green%MT_alpha = green%MT_alpha/MINVAL(abc)
241 1264 : SELECT CASE (dim)
242 : CASE (0)
243 1210 : green%method = MT0D
244 6050 : green%radius = 0.5_dp*MINVAL(abc)
245 : CASE (1)
246 0 : green%method = MT1D
247 0 : green%special_dimension = MAXLOC(poisson_params%periodic(1:3), 1)
248 0 : green%radius = MAXVAL(abc(1:3))
249 0 : DO i = 1, 3
250 0 : IF (i == green%special_dimension) CYCLE
251 0 : green%radius = MIN(green%radius, 0.5_dp*abc(i))
252 : END DO
253 : CASE (2)
254 2 : green%method = MT2D
255 8 : i = MINLOC(poisson_params%periodic, 1)
256 2 : green%special_dimension = i
257 2 : green%slab_size = abc(i)
258 : CASE (3)
259 0 : CPABORT("Illegal combination of periodicity and Poisson solver (MT)")
260 : CASE DEFAULT
261 1212 : CPABORT("")
262 : END SELECT
263 : CASE (pw_poisson_implicit)
264 54 : green%method = PS_IMPLICIT
265 : CASE DEFAULT
266 15794 : CPABORT("An unknown Poisson solver was specified")
267 : END SELECT
268 :
269 : ! allocate influence function,...
270 31588 : SELECT CASE (green%method)
271 : CASE (PERIODIC3D, ANALYTIC2D, ANALYTIC1D, ANALYTIC0D, MT2D, MT1D, MT0D, MULTIPOLE0D, PS_IMPLICIT)
272 15794 : CALL pw_pool%create_pw(green%influence_fn)
273 :
274 15794 : IF (poisson_params%ewald_type == do_ewald_spme) THEN
275 9870 : green%p3m = .TRUE.
276 9870 : green%p3m_order = poisson_params%ewald_o_spline
277 9870 : green%p3m_alpha = poisson_params%ewald_alpha
278 9870 : n = green%p3m_order
279 39480 : ALLOCATE (green%p3m_coeff(-(n - 1):n - 1, 0:n - 1))
280 9870 : CALL spme_coeff_calculate(n, green%p3m_coeff)
281 : NULLIFY (green%p3m_charge)
282 9870 : ALLOCATE (green%p3m_charge)
283 9870 : CALL pw_pool%create_pw(green%p3m_charge)
284 9870 : CALL influence_factor(green)
285 9870 : CALL calc_p3m_charge(green)
286 : ELSE
287 5924 : green%p3m = .FALSE.
288 : END IF
289 : !
290 17006 : SELECT CASE (green%method)
291 : CASE (MT0D, MT1D, MT2D)
292 : CALL MTin_create_screen_fn(green%screen_fn, pw_pool=pw_pool, method=green%method, &
293 : alpha=green%MT_alpha, &
294 : special_dimension=green%special_dimension, slab_size=green%slab_size, &
295 1212 : super_ref_pw_grid=mt_super_ref_pw_grid)
296 : CASE (PS_IMPLICIT)
297 54 : IF ((poisson_params%ps_implicit_params%boundary_condition == MIXED_BC) .OR. &
298 15794 : (poisson_params%ps_implicit_params%boundary_condition == NEUMANN_BC)) THEN
299 22 : CALL pw_pool_create(pw_pool_xpndd, pw_grid=dct_pw_grid)
300 : NULLIFY (green%dct_influence_fn)
301 22 : ALLOCATE (green%dct_influence_fn)
302 22 : CALL pw_pool_xpndd%create_pw(green%dct_influence_fn)
303 22 : CALL pw_pool_release(pw_pool_xpndd)
304 : END IF
305 : END SELECT
306 :
307 : CASE DEFAULT
308 15794 : CPABORT("")
309 : END SELECT
310 :
311 : ! initialize influence function
312 : ASSOCIATE (gf => green%influence_fn, grid => green%influence_fn%pw_grid)
313 30138 : SELECT CASE (green%method)
314 : CASE (PERIODIC3D, MULTIPOLE0D)
315 :
316 345671671 : DO ig = grid%first_gne0, grid%ngpts_cut_local
317 345657327 : g2 = grid%gsq(ig)
318 345671671 : gf%array(ig) = fourpi/g2
319 : END DO
320 14344 : IF (grid%have_g0) gf%array(1) = 0.0_dp
321 :
322 : CASE (ANALYTIC2D)
323 :
324 8 : iz = green%special_dimension ! iz is the direction with NO PBC
325 8 : zlength = green%slab_size ! zlength is the thickness of the cell
326 634372 : DO ig = grid%first_gne0, grid%ngpts_cut_local
327 634364 : nz = grid%g_hat(iz, ig)
328 634364 : g2 = grid%gsq(ig)
329 634364 : g3d = fourpi/g2
330 634364 : gxy = MAX(0.0_dp, g2 - grid%g(iz, ig)*grid%g(iz, ig))
331 634364 : gg = 0.5_dp*SQRT(gxy)
332 634372 : gf%array(ig) = g3d*(1.0_dp - (-1.0_dp)**nz*EXP(-gg*zlength))
333 : END DO
334 8 : IF (grid%have_g0) gf%array(1) = 0.0_dp
335 :
336 : CASE (ANALYTIC1D)
337 : ! see 'ab initio molecular dynamics' table 3.1
338 : ! iz is the direction of the PBC ( can be 1,2,3 -> x,y,z )
339 6 : iz = green%special_dimension
340 : ! rlength is the radius of the tube
341 6 : rlength = green%radius
342 192003 : DO ig = grid%first_gne0, grid%ngpts_cut_local
343 191997 : g2 = grid%gsq(ig)
344 191997 : g3d = fourpi/g2
345 191997 : gxy = SQRT(MAX(0.0_dp, g2 - grid%g(iz, ig)*grid%g(iz, ig)))
346 191997 : gz = ABS(grid%g(iz, ig))
347 191997 : j0g = BESSEL_J0(rlength*gxy)
348 191997 : j1g = BESSEL_J1(rlength*gxy)
349 191997 : IF (gz > 0) THEN
350 187200 : k0g = bessk0(rlength*gz)
351 187200 : k1g = bessk1(rlength*gz)
352 : ELSE
353 : k0g = 0
354 : k1g = 0
355 : END IF
356 : gf%array(ig) = g3d*(1.0_dp + rlength* &
357 192003 : (gxy*j1g*k0g - gz*j0g*k1g))
358 : END DO
359 6 : IF (grid%have_g0) gf%array(1) = 0.0_dp
360 :
361 : CASE (ANALYTIC0D)
362 :
363 170 : rlength = green%radius ! rlength is the radius of the sphere
364 39004540 : DO ig = grid%first_gne0, grid%ngpts_cut_local
365 39004370 : g2 = grid%gsq(ig)
366 39004370 : gg = SQRT(g2)
367 39004370 : g3d = fourpi/g2
368 39004540 : gf%array(ig) = g3d*(1.0_dp - COS(rlength*gg))
369 : END DO
370 170 : IF (grid%have_g0) &
371 85 : gf%array(1) = 0.5_dp*fourpi*rlength*rlength
372 :
373 : CASE (MT2D, MT1D, MT0D)
374 :
375 81587146 : DO ig = grid%first_gne0, grid%ngpts_cut_local
376 81585934 : g2 = grid%gsq(ig)
377 81585934 : g3d = fourpi/g2
378 81587146 : gf%array(ig) = g3d + green%screen_fn%array(ig)
379 : END DO
380 1212 : IF (grid%have_g0) &
381 612 : gf%array(1) = green%screen_fn%array(1)
382 :
383 : CASE (PS_IMPLICIT)
384 :
385 6554816 : DO ig = grid%first_gne0, grid%ngpts_cut_local
386 6554762 : g2 = grid%gsq(ig)
387 6554816 : gf%array(ig) = fourpi/g2
388 : END DO
389 54 : IF (grid%have_g0) gf%array(1) = 0.0_dp
390 :
391 54 : IF (ASSOCIATED(green%dct_influence_fn)) THEN
392 22 : dct_gf => green%dct_influence_fn
393 22 : dct_grid => green%dct_influence_fn%pw_grid
394 :
395 9851771 : DO ig = dct_grid%first_gne0, dct_grid%ngpts_cut_local
396 9851749 : g2 = dct_grid%gsq(ig)
397 9851771 : dct_gf%array(ig) = fourpi/g2
398 : END DO
399 22 : IF (dct_grid%have_g0) dct_gf%array(1) = 0.0_dp
400 : END IF
401 :
402 : CASE DEFAULT
403 15794 : CPABORT("")
404 : END SELECT
405 : END ASSOCIATE
406 :
407 15794 : END SUBROUTINE pw_green_create
408 :
409 : ! **************************************************************************************************
410 : !> \brief destroys the type (deallocates data)
411 : !> \param gftype ...
412 : !> \param pw_pool ...
413 : !> \par History
414 : !> none
415 : !> \author Joost VandeVondele
416 : !> Teodoro Laino
417 : ! **************************************************************************************************
418 15794 : SUBROUTINE pw_green_release(gftype, pw_pool)
419 : TYPE(greens_fn_type), INTENT(INOUT) :: gftype
420 : TYPE(pw_pool_type), OPTIONAL, POINTER :: pw_pool
421 :
422 : LOGICAL :: can_give_back
423 :
424 15794 : can_give_back = PRESENT(pw_pool)
425 15794 : IF (can_give_back) can_give_back = ASSOCIATED(pw_pool)
426 15794 : IF (can_give_back) THEN
427 8054 : CALL pw_pool%give_back_pw(gftype%influence_fn)
428 8054 : IF (ASSOCIATED(gftype%dct_influence_fn)) THEN
429 0 : CALL pw_pool%give_back_pw(gftype%dct_influence_fn)
430 0 : DEALLOCATE (gftype%dct_influence_fn)
431 : END IF
432 8054 : IF (ASSOCIATED(gftype%screen_fn)) THEN
433 56 : CALL pw_pool%give_back_pw(gftype%screen_fn)
434 56 : DEALLOCATE (gftype%screen_fn)
435 : END IF
436 8054 : IF (ASSOCIATED(gftype%p3m_charge)) THEN
437 7682 : CALL pw_pool%give_back_pw(gftype%p3m_charge)
438 7682 : DEALLOCATE (gftype%p3m_charge)
439 : END IF
440 : ELSE
441 7740 : CALL gftype%influence_fn%release()
442 7740 : IF (ASSOCIATED(gftype%dct_influence_fn)) THEN
443 22 : CALL gftype%dct_influence_fn%release()
444 22 : DEALLOCATE (gftype%dct_influence_fn)
445 : END IF
446 7740 : IF (ASSOCIATED(gftype%screen_fn)) THEN
447 1156 : CALL gftype%screen_fn%release()
448 1156 : DEALLOCATE (gftype%screen_fn)
449 : END IF
450 7740 : IF (ASSOCIATED(gftype%p3m_charge)) THEN
451 2188 : CALL gftype%p3m_charge%release()
452 2188 : DEALLOCATE (gftype%p3m_charge)
453 : END IF
454 : END IF
455 15794 : IF (ALLOCATED(gftype%p3m_bm2)) &
456 9870 : DEALLOCATE (gftype%p3m_bm2)
457 15794 : IF (ALLOCATED(gftype%p3m_coeff)) &
458 9870 : DEALLOCATE (gftype%p3m_coeff)
459 15794 : END SUBROUTINE pw_green_release
460 :
461 : ! **************************************************************************************************
462 : !> \brief Calculates the influence_factor for the
463 : !> SPME Green's function in reciprocal space'''
464 : !> \param gftype ...
465 : !> \par History
466 : !> none
467 : !> \author DH (29-Mar-2001)
468 : ! **************************************************************************************************
469 9870 : SUBROUTINE influence_factor(gftype)
470 : TYPE(greens_fn_type), INTENT(INOUT) :: gftype
471 :
472 : COMPLEX(KIND=dp) :: b_m, exp_m, sum_m
473 : INTEGER :: dim, j, k, l, n, pt
474 : INTEGER, DIMENSION(3) :: npts
475 9870 : INTEGER, DIMENSION(:), POINTER :: lb, ub
476 : REAL(KIND=dp) :: l_arg, prod_arg, val
477 9870 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: m_assign
478 :
479 9870 : n = gftype%p3m_order
480 :
481 : ! calculate the assignment function values
482 :
483 9870 : lb => gftype%influence_fn%pw_grid%bounds(1, :)
484 9870 : ub => gftype%influence_fn%pw_grid%bounds(2, :)
485 9870 : IF (ALLOCATED(gftype%p3m_bm2)) THEN
486 0 : IF (LBOUND(gftype%p3m_bm2, 2) /= MINVAL(lb(:)) .OR. &
487 : UBOUND(gftype%p3m_bm2, 2) /= MAXVAL(ub(:))) THEN
488 0 : DEALLOCATE (gftype%p3m_bm2)
489 : END IF
490 : END IF
491 9870 : IF (.NOT. ALLOCATED(gftype%p3m_bm2)) THEN
492 88830 : ALLOCATE (gftype%p3m_bm2(3, MINVAL(lb(:)):MAXVAL(ub(:))))
493 : END IF
494 :
495 29610 : ALLOCATE (m_assign(0:n - 2))
496 58400 : m_assign = 0.0_dp
497 58400 : DO k = 0, n - 2
498 48530 : j = -(n - 1) + 2*k
499 347200 : DO l = 0, n - 1
500 288800 : l_arg = 0.5_dp**l
501 288800 : prod_arg = gftype%p3m_coeff(j, l)*l_arg
502 337330 : m_assign(k) = m_assign(k) + prod_arg
503 : END DO
504 : END DO
505 :
506 : ! calculate the absolute b values
507 :
508 39480 : npts(:) = ub(:) - lb(:) + 1
509 39480 : DO dim = 1, 3
510 943190 : DO pt = lb(dim), ub(dim)
511 903710 : val = twopi*(REAL(pt, KIND=dp)/REAL(npts(dim), KIND=dp))
512 903710 : exp_m = CMPLX(COS(val), -SIN(val), KIND=dp)
513 903710 : sum_m = z_zero
514 5349240 : DO k = 0, n - 2
515 5349240 : sum_m = sum_m + m_assign(k)*exp_m**k
516 : END DO
517 903710 : b_m = exp_m**(n - 1)/sum_m
518 933320 : gftype%p3m_bm2(dim, pt) = SQRT(REAL(b_m*CONJG(b_m), KIND=dp))
519 : END DO
520 : END DO
521 :
522 9870 : DEALLOCATE (m_assign)
523 9870 : END SUBROUTINE influence_factor
524 :
525 : ! **************************************************************************************************
526 : !> \brief ...
527 : !> \param gf ...
528 : ! **************************************************************************************************
529 9870 : PURE SUBROUTINE calc_p3m_charge(gf)
530 :
531 : TYPE(greens_fn_type), INTENT(INOUT) :: gf
532 :
533 : INTEGER :: ig, l, m, n
534 : REAL(KIND=dp) :: arg, novol
535 :
536 : ! check if charge function is consistent with current box volume
537 :
538 : ASSOCIATE (grid => gf%influence_fn%pw_grid, bm2 => gf%p3m_bm2)
539 9870 : arg = 1.0_dp/(8.0_dp*gf%p3m_alpha**2)
540 9870 : novol = REAL(grid%ngpts, KIND=dp)/grid%vol
541 57442488 : DO ig = 1, grid%ngpts_cut_local
542 57432618 : l = grid%g_hat(1, ig)
543 57432618 : m = grid%g_hat(2, ig)
544 57432618 : n = grid%g_hat(3, ig)
545 : gf%p3m_charge%array(ig) = novol*EXP(-arg*grid%gsq(ig))* &
546 57442488 : bm2(1, l)*bm2(2, m)*bm2(3, n)
547 : END DO
548 : END ASSOCIATE
549 :
550 9870 : END SUBROUTINE calc_p3m_charge
551 :
552 : ! **************************************************************************************************
553 : !> \brief Initialize the poisson solver
554 : !> You should call this just before calling the work routine
555 : !> pw_poisson_solver
556 : !> Call pw_poisson_release when you have finished
557 : !> \param poisson_env ...
558 : !> \par History
559 : !> none
560 : !> \author JGH (12-Mar-2001)
561 : ! **************************************************************************************************
562 10944 : SUBROUTINE pw_poisson_create(poisson_env)
563 :
564 : CLASS(pw_poisson_type), INTENT(INOUT) :: poisson_env
565 :
566 : ! Cleanup a potential previous poisson_env
567 10944 : CALL poisson_env%release()
568 :
569 10944 : END SUBROUTINE pw_poisson_create
570 :
571 : ! **************************************************************************************************
572 : !> \brief releases the poisson solver
573 : !> \param poisson_env ...
574 : !> \par History
575 : !> none
576 : !> \author fawzi (11.2002)
577 : ! **************************************************************************************************
578 21888 : SUBROUTINE pw_poisson_release(poisson_env)
579 :
580 : CLASS(pw_poisson_type), INTENT(INOUT) :: poisson_env
581 :
582 21888 : IF (ASSOCIATED(poisson_env%pw_pools)) THEN
583 10944 : CALL pw_pools_dealloc(poisson_env%pw_pools)
584 : END IF
585 :
586 21888 : IF (ASSOCIATED(poisson_env%green_fft)) THEN
587 7740 : CALL pw_green_release(poisson_env%green_fft)
588 7740 : DEALLOCATE (poisson_env%green_fft)
589 : END IF
590 21888 : CALL pw_grid_release(poisson_env%mt_super_ref_pw_grid)
591 21888 : CALL ps_wavelet_release(poisson_env%wavelet)
592 : CALL ps_implicit_release(poisson_env%implicit_env, &
593 21888 : poisson_env%parameters%ps_implicit_params)
594 21888 : CALL pw_grid_release(poisson_env%dct_pw_grid)
595 21888 : IF (ASSOCIATED(poisson_env%diel_rs_grid)) THEN
596 50 : CALL rs_grid_release(poisson_env%diel_rs_grid)
597 50 : DEALLOCATE (poisson_env%diel_rs_grid)
598 : END IF
599 :
600 21888 : END SUBROUTINE pw_poisson_release
601 :
602 : ! **************************************************************************************************
603 : !> \brief Calculates the coefficients for the charge assignment function
604 : !> \param n ...
605 : !> \param coeff ...
606 : !> \par History
607 : !> none
608 : !> \author DG (29-Mar-2001)
609 : ! **************************************************************************************************
610 9870 : SUBROUTINE spme_coeff_calculate(n, coeff)
611 :
612 : INTEGER, INTENT(IN) :: n
613 : REAL(KIND=dp), DIMENSION(-(n-1):n-1, 0:n-1), &
614 : INTENT(OUT) :: coeff
615 :
616 : INTEGER :: i, j, l, m
617 : REAL(KIND=dp) :: b
618 9870 : REAL(KIND=dp), DIMENSION(n, -n:n, 0:n-1) :: a
619 :
620 5311598 : a = 0.0_dp
621 9870 : a(1, 0, 0) = 1.0_dp
622 :
623 58400 : DO i = 2, n
624 48530 : m = i - 1
625 251330 : DO j = -m, m, 2
626 864018 : DO l = 0, m - 1
627 : b = (a(m, j - 1, l) + &
628 : REAL((-1)**l, KIND=dp)*a(m, j + 1, l))/ &
629 671088 : REAL((l + 1)*2**(l + 1), KIND=dp)
630 864018 : a(i, j, 0) = a(i, j, 0) + b
631 : END DO
632 912548 : DO l = 0, m - 1
633 : a(i, j, l + 1) = (a(m, j + 1, l) - &
634 864018 : a(m, j - 1, l))/REAL(l + 1, KIND=dp)
635 : END DO
636 : END DO
637 : END DO
638 :
639 704270 : coeff = 0.0_dp
640 68270 : DO i = 0, n - 1
641 68270 : DO j = -(n - 1), n - 1, 2
642 347200 : coeff(j, i) = a(n, j, i)
643 : END DO
644 : END DO
645 :
646 9870 : END SUBROUTINE spme_coeff_calculate
647 :
648 0 : END MODULE pw_poisson_types
|