Octopus
poisson.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2011 M. Marques, A. Castro, A. Rubio,
2!! G. Bertsch, M. Oliveira
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
22module poisson_oct_m
23 use accel_oct_m
24 use batch_oct_m
27 use cube_oct_m
29 use debug_oct_m
31 use fft_oct_m
33 use global_oct_m
34 use index_oct_m
35 use, intrinsic :: iso_fortran_env
38 use math_oct_m
39 use mesh_oct_m
43 use mpi_oct_m
46#ifdef HAVE_OPENMP
47 use omp_lib
48#endif
50 use parser_oct_m
62 use space_oct_m
65 use types_oct_m
68 use xc_cam_oct_m
69
70 implicit none
71
72 private
73 public :: &
74 poisson_t, &
103
104 integer, public, parameter :: &
105 POISSON_DIRECT_SUM = -1, &
106 poisson_fft = 0, &
107 poisson_cg = 5, &
109 poisson_multigrid = 7, &
110 poisson_isf = 8, &
111 poisson_psolver = 10, &
112 poisson_nfft = option__poissonsolver__nfft, &
113 poisson_no = -99, &
114 poisson_null = -999
115
116 type poisson_t
117 private
118 type(derivatives_t), pointer, public :: der
119 integer, public :: method = poisson_null
120 integer, public :: kernel
121 type(cube_t), public :: cube
122 type(mesh_cube_parallel_map_t), public :: mesh_cube_map
123 type(poisson_mg_solver_t) :: mg
124 type(poisson_fft_t), public :: fft_solver
125 real(real64), public :: poisson_soft_coulomb_param
126 logical :: all_nodes_default
127 type(poisson_corr_t) :: corrector
128 type(poisson_isf_t) :: isf_solver
129 type(poisson_psolver_t) :: psolver_solver
130 type(poisson_no_t) :: no_solver
131 type(poisson_nfft_t) :: nfft_solver
132 integer :: nslaves
133 logical, public :: is_dressed = .false.
134 type(photon_mode_t), public :: photons
135#ifdef HAVE_MPI
136 type(MPI_Comm) :: intercomm
137 type(mpi_grp_t) :: local_grp
138 logical :: root
139#endif
140 end type poisson_t
141
142 integer, parameter :: &
143 CMD_FINISH = 1, &
145
146contains
147
148 !-----------------------------------------------------------------
149 subroutine poisson_init(this, namespace, space, der, mc, stencil, qtot, label, solver, verbose, force_serial, &
150 force_cmplx, fft_library, fft_batch_size, single_precision)
151 type(poisson_t), intent(inout) :: this
152 class(space_t), intent(in) :: space
153 type(namespace_t), intent(in) :: namespace
154 type(derivatives_t), target, intent(in) :: der
155 type(multicomm_t), intent(in) :: mc
156 type(stencil_t), intent(in) :: stencil
157 real(real64), optional, intent(in) :: qtot
158 character(len=*), optional, intent(in) :: label
159 integer, optional, intent(in) :: solver
160 logical, optional, intent(in) :: verbose
161 logical, optional, intent(in) :: force_serial
162 logical, optional, intent(in) :: force_cmplx
163 integer, optional, intent(in) :: fft_library
164 integer, optional, intent(in) :: fft_batch_size
165 logical, optional, intent(in) :: single_precision
166
167 logical :: need_cube, isf_data_is_parallel
168 integer :: default_solver, default_kernel, box(space%dim), fft_type, library, fft_bs
169 real(real64) :: fft_alpha
170 character(len=60) :: str
171
172 ! Make sure we do not try to initialize an already initialized solver
173 assert(this%method == poisson_null)
174
175 push_sub(poisson_init)
176
177 if (optional_default(verbose,.true.)) then
178 str = "Hartree"
179 if (present(label)) str = trim(label)
180 call messages_print_with_emphasis(msg=trim(str), namespace=namespace)
181 end if
182
183 this%nslaves = 0
184 this%der => der
185
186 !%Variable DressedOrbitals
187 !%Type logical
188 !%Default false
189 !%Section Hamiltonian::Poisson
190 !%Description
191 !% Allows for the calculation of coupled elecron-photon problems
192 !% by applying the dressed orbital approach. Details can be found in
193 !% https://arxiv.org/abs/1812.05562
194 !% At the moment, N electrons in d (<=3) spatial dimensions, coupled
195 !% to one photon mode can be described. The photon mode is included by
196 !% raising the orbital dimension to d+1 and changing the particle interaction
197 !% kernel and the local potential, where the former is included automatically,
198 !% but the latter needs to by added by hand as a user_defined_potential!
199 !% Coordinate 1-d: electron; coordinate d+1: photon.
200 !%End
201 call parse_variable(namespace, 'DressedOrbitals', .false., this%is_dressed)
202 call messages_print_var_value('DressedOrbitals', this%is_dressed, namespace=namespace)
203 if (this%is_dressed) then
204 assert(present(qtot))
205 call messages_experimental('Dressed Orbitals', namespace=namespace)
206 assert(qtot > m_zero)
207 call photon_mode_init(this%photons, namespace, der%dim-1)
208 call photon_mode_set_n_electrons(this%photons, qtot)
209 if(.not.allocated(this%photons%pol_dipole)) then
210 call photon_mode_compute_dipoles(this%photons, der%mesh)
211 end if
212 if (this%photons%nmodes > 1) then
213 call messages_not_implemented('DressedOrbitals for more than one photon mode', namespace=namespace)
214 end if
215 end if
217 this%all_nodes_default = .false.
218#ifdef HAVE_MPI
219 if (.not. optional_default(force_serial, .false.)) then
220 !%Variable ParallelizationPoissonAllNodes
221 !%Type logical
222 !%Default true
223 !%Section Execution::Parallelization
224 !%Description
225 !% When running in parallel, this variable selects whether the
226 !% Poisson solver should divide the work among all nodes or only
227 !% among the parallelization-in-domains groups.
228 !%End
230 call parse_variable(namespace, 'ParallelizationPoissonAllNodes', .true., this%all_nodes_default)
231 end if
232#endif
233
234 !%Variable PoissonSolver
235 !%Type integer
236 !%Section Hamiltonian::Poisson
237 !%Description
238 !% Defines which method to use to solve the Poisson equation. Some incompatibilities apply depending on
239 !% dimensionality, periodicity, etc.
240 !% For a comparison of the accuracy and performance of the methods in Octopus, see P Garcia-Risue&ntilde;o,
241 !% J Alberdi-Rodriguez <i>et al.</i>, <i>J. Comp. Chem.</i> <b>35</b>, 427-444 (2014)
242 !% or <a href=http://arxiv.org/abs/1211.2092>arXiV</a>.
243 !% Defaults:
244 !% <br> 1D and 2D: <tt>fft</tt>.
245 !% <br> 3D: <tt>cg_corrected</tt> if curvilinear, <tt>isf</tt> if not periodic, <tt>fft</tt> if periodic.
246 !% <br> Dressed orbitals: <tt>direct_sum</tt>.
247 !%Option NoPoisson -99
248 !% Do not use a Poisson solver at all.
249 !%Option direct_sum -1
250 !% Direct evaluation of the Hartree potential (only for finite systems).
251 !%Option fft 0
252 !% The Poisson equation is solved using FFTs. A cutoff technique
253 !% for the Poisson kernel is selected so the proper boundary
254 !% conditions are imposed according to the periodicity of the
255 !% system. This can be overridden by the <tt>PoissonFFTKernel</tt>
256 !% variable. To choose the FFT library use <tt>FFTLibrary</tt>
257 !%Option cg 5
258 !% Conjugate gradients.
259 !%Option cg_corrected 6
260 !% Conjugate gradients, corrected for boundary conditions (only for finite systems).
261 !%Option multigrid 7
262 !% Multigrid method.
263 !%Option isf 8
264 !% Interpolating Scaling Functions Poisson solver (only for finite systems).
265 !%Option psolver 10
266 !% Solver based on Interpolating Scaling Functions as implemented in the PSolver library.
267 !% Parallelization in k-points requires <tt>PoissonSolverPSolverParallelData</tt> = no.
268 !% Requires the PSolver external library.
269 !%Option nfft
270 !% (experimental) The Poisson equation is solved in Fourier space with the mesh points
271 !% as the non-equispaced nodes of a FINUFFT transform, which needs no cube and takes a
272 !% curvilinear mesh as it stands. Only for finite 3D systems. Requires FINUFFT.
273 !%End
274
275 default_solver = poisson_fft
276
277 if (space%dim == 3 .and. .not. space%is_periodic()) default_solver = poisson_isf
278
279#ifdef HAVE_CUDA
280 if(accel_is_enabled()) default_solver = poisson_fft
281#endif
282
283 if (space%dim > 3) default_solver = poisson_no ! Kernel for higher dimensions is not implemented.
284
285 if (der%mesh%use_curvilinear) then
286 select case (space%dim)
287 case (1)
288 default_solver = poisson_direct_sum
289 case (2)
290 default_solver = poisson_direct_sum
291 case (3)
292 default_solver = poisson_multigrid
293 end select
294 end if
295
296 if (this%is_dressed) default_solver = poisson_direct_sum
297
298 if (.not. present(solver)) then
299 call parse_variable(namespace, 'PoissonSolver', default_solver, this%method)
300 else
301 this%method = solver
302 end if
303 if (.not. varinfo_valid_option('PoissonSolver', this%method)) call messages_input_error(namespace, 'PoissonSolver')
304 if (optional_default(verbose, .true.)) then
305 select case (this%method)
306 case (poisson_direct_sum)
307 str = "direct sum"
308 case (poisson_fft)
309 str = "fast Fourier transform"
310 case (poisson_cg)
311 str = "conjugate gradients"
313 str = "conjugate gradients, corrected"
314 case (poisson_multigrid)
315 str = "multigrid"
316 case (poisson_isf)
317 str = "interpolating scaling functions"
318 case (poisson_psolver)
319 str = "interpolating scaling functions (from BigDFT)"
320 case (poisson_nfft)
321 str = "non-equispaced fast Fourier transform"
322 case (poisson_no)
323 str = "no Poisson solver - Hartree set to 0"
324 end select
325 write(message(1),'(a,a,a)') "The chosen Poisson solver is '", trim(str), "'"
326 call messages_info(1, namespace=namespace)
327 end if
328
329 if (space%dim > 3 .and. this%method /= poisson_no) then
330 call messages_input_error(namespace, 'PoissonSolver', 'Currently no Poisson solver is available for Dimensions > 3')
331 end if
332
333 fft_bs = optional_default(fft_batch_size, 1)
334 assert(fft_bs > 0)
335
336 if (this%method /= poisson_fft) then
337 this%kernel = poisson_fft_kernel_none
338 else
339
340 ! Documentation in cube.F90
341 call parse_variable(namespace, 'FFTLibrary', fftlib_fftw, library)
342 if (present(fft_library)) library = fft_library
343
344 !%Variable PoissonFFTKernel
345 !%Type integer
346 !%Section Hamiltonian::Poisson
347 !%Description
348 !% Defines which kernel is used to impose the correct boundary
349 !% conditions when using FFTs to solve the Poisson equation. The
350 !% default is selected depending on the dimensionality and
351 !% periodicity of the system:
352 !% <br>In 1D, <tt>spherical</tt> if finite, <tt>fft_nocut</tt> if periodic.
353 !% <br>In 2D, <tt>spherical</tt> if finite, <tt>cylindrical</tt> if 1D-periodic, <tt>fft_nocut</tt> if 2D-periodic.
354 !% <br>In 3D, <tt>spherical</tt> if finite, <tt>cylindrical</tt> if 1D-periodic, <tt>planar</tt> if 2D-periodic,
355 !% <tt>fft_nocut</tt> if 3D-periodic.
356 !% See C. A. Rozzi et al., <i>Phys. Rev. B</i> <b>73</b>, 205119 (2006) for 3D implementation and
357 !% A. Castro et al., <i>Phys. Rev. B</i> <b>80</b>, 033102 (2009) for 2D implementation.
358 !%Option spherical 0
359 !% FFTs using spherical cutoff (in 2D or 3D).
360 !%Option cylindrical 1
361 !% FFTs using cylindrical cutoff (in 2D or 3D).
362 !%Option planar 2
363 !% FFTs using planar cutoff (in 3D).
364 !%Option fft_nocut 3
365 !% FFTs without using a cutoff (for fully periodic systems).
366 !%Option multipole_correction 4
367 !% The boundary conditions are imposed by using a multipole expansion. Only appropriate for finite systems.
368 !% Further specification occurs with variables <tt>PoissonSolverBoundaries</tt> and <tt>PoissonSolverMaxMultipole</tt>.
369 !%End
370
371 select case (space%dim)
372 case (1)
373 if (.not. space%is_periodic()) then
374 default_kernel = poisson_fft_kernel_sph
375 else
376 default_kernel = poisson_fft_kernel_nocut
377 end if
378 case (2)
379 if (space%periodic_dim == 2) then
380 default_kernel = poisson_fft_kernel_nocut
381 else if (space%is_periodic()) then
382 default_kernel = space%periodic_dim
383 else
384 default_kernel = poisson_fft_kernel_sph
385 end if
386 case (3)
387 default_kernel = space%periodic_dim
388 end select
389
390 call parse_variable(namespace, 'PoissonFFTKernel', default_kernel, this%kernel)
391 if (.not. varinfo_valid_option('PoissonFFTKernel', this%kernel)) call messages_input_error(namespace, 'PoissonFFTKernel')
392
393 if (optional_default(verbose,.true.)) then
394 call messages_print_var_option("PoissonFFTKernel", this%kernel, namespace=namespace)
395 end if
396
397 ! the multipole correction kernel does not work on GPUs
398 if(this%kernel == poisson_fft_kernel_corrected .and. fft_default_lib == fftlib_accel) then
400 message(1) = 'PoissonFFTKernel=multipole_correction is not supported on GPUs'
401 message(2) = 'Using FFTW to compute the FFTs on the CPU'
402 call messages_info(2, namespace=namespace)
403 end if
404
405 end if
406
407 !We assume the developer knows what he is doing by providing the solver option
408 if (.not. present(solver)) then
409 if (space%is_periodic() .and. this%method == poisson_direct_sum) then
410 message(1) = 'A periodic system may not use the direct_sum Poisson solver.'
411 call messages_fatal(1, namespace=namespace)
412 end if
413
414 if (space%is_periodic() .and. this%method == poisson_cg_corrected) then
415 message(1) = 'A periodic system may not use the cg_corrected Poisson solver.'
416 call messages_fatal(1, namespace=namespace)
417 end if
418
419 select case (space%dim)
420 case (1)
421
422 select case (space%periodic_dim)
423 case (0)
424 if ((this%method /= poisson_fft) .and. (this%method /= poisson_direct_sum)) then
425 message(1) = 'A finite 1D system may only use fft or direct_sum Poisson solvers.'
426 call messages_fatal(1, namespace=namespace)
427 end if
428 case (1)
429 if (this%method /= poisson_fft) then
430 message(1) = 'A periodic 1D system may only use the fft Poisson solver.'
431 call messages_fatal(1, namespace=namespace)
432 end if
433 end select
434
435 if (der%mesh%use_curvilinear .and. this%method /= poisson_direct_sum) then
436 message(1) = 'If curvilinear coordinates are used in 1D, then the only working'
437 message(2) = 'Poisson solver is direct_sum.'
438 call messages_fatal(2, namespace=namespace)
439 end if
440
441 case (2)
442
443 if ((this%method /= poisson_fft) .and. (this%method /= poisson_direct_sum)) then
444 message(1) = 'A 2D system may only use fft or direct_sum solvers.'
445 call messages_fatal(1, namespace=namespace)
446 end if
447
448 if (der%mesh%use_curvilinear .and. (this%method /= poisson_direct_sum)) then
449 message(1) = 'If curvilinear coordinates are used in 2D, then the only working'
450 message(2) = 'Poisson solver is direct_sum.'
451 call messages_fatal(2, namespace=namespace)
452 end if
453
454 case (3)
455
456 if (space%is_periodic() .and. this%method == poisson_isf) then
457 call messages_write('The ISF solver can only be used for finite systems.')
458 call messages_fatal()
459 end if
460
461 if (space%is_periodic() .and. this%method == poisson_fft .and. &
462 this%kernel /= space%periodic_dim .and. this%kernel >= 0 .and. this%kernel <= 3) then
463 write(message(1), '(a,i1,a)')'The system is periodic in ', space%periodic_dim ,' dimension(s),'
464 write(message(2), '(a,i1,a)')'but Poisson solver is set for ', this%kernel, ' dimensions.'
465 call messages_warning(2, namespace=namespace)
466 end if
467
468 if (space%is_periodic() .and. this%method == poisson_fft .and. this%kernel == poisson_fft_kernel_corrected) then
469 write(message(1), '(a,i1,a)')'PoissonFFTKernel = multipole_correction cannot be used for periodic systems.'
470 call messages_fatal(1, namespace=namespace)
471 end if
472
473 if (this%method == poisson_nfft) then
474 call messages_experimental('PoissonSolver = nfft', namespace=namespace)
475 if (space%dim /= 3 .or. space%is_periodic()) then
476 message(1) = 'The nfft Poisson solver is only available for finite 3D systems.'
477 call messages_fatal(1, namespace=namespace)
478 end if
479 end if
480
481 if (der%mesh%use_curvilinear .and. &
482 .not. any(this%method == [poisson_cg_corrected, poisson_multigrid, poisson_nfft])) then
483 message(1) = 'If curvilinear coordinates are used, then the only working'
484 message(2) = 'Poisson solvers are cg_corrected, multigrid and nfft.'
485 call messages_fatal(2, namespace=namespace)
486 end if
487 if (der%mesh%use_curvilinear .and. this%method == poisson_multigrid .and. accel_is_enabled()) then
488 call messages_not_implemented('Multigrid Poisson solver with curvilinear coordinates on GPUs')
489 end if
490
491 select type (box => der%mesh%box)
492 type is (box_minimum_t)
493 if (this%method == poisson_cg_corrected) then
494 message(1) = 'When using the "minimum" box shape and the "cg_corrected"'
495 message(2) = 'Poisson solver, we have observed "sometimes" some non-'
496 message(3) = 'negligible error. You may want to check that the "fft" or "cg"'
497 message(4) = 'solver are providing, in your case, the same results.'
498 call messages_warning(4, namespace=namespace)
499 end if
500 end select
501
502 end select
503 end if
504
505 if (this%method == poisson_psolver) then
506#if !(defined HAVE_PSOLVER)
507 message(1) = "The PSolver Poisson solver cannot be used since the code was not compiled with the PSolver library."
508 call messages_fatal(1, namespace=namespace)
509#endif
510 end if
511
512 if (optional_default(verbose,.true.)) then
513 call messages_print_with_emphasis(namespace=namespace)
514 end if
515
516 ! Now that we know the method, we check if we need a cube and its dimensions
517 need_cube = .false.
518 fft_type = fft_real
519 if (optional_default(force_cmplx, .false.)) fft_type = fft_complex
520
521 if (this%method == poisson_isf .or. this%method == poisson_psolver) then
522 fft_type = fft_none
523 box(:) = der%mesh%idx%ll(:)
524 need_cube = .true.
525 end if
526
527 if (this%method == poisson_psolver .and. multicomm_have_slaves(mc)) then
528 call messages_not_implemented('Task parallelization with PSolver Poisson solver', namespace=namespace)
529 end if
530
532 ! Documentation in poisson_psolver.F90
533 call parse_variable(namespace, 'PoissonSolverPSolverParallelData', .true., isf_data_is_parallel)
534 if (this%method == poisson_psolver .and. isf_data_is_parallel) then
535 call messages_not_implemented("k-point parallelization with PSolver library and", namespace=namespace)
536 call messages_not_implemented("PoissonSolverPSolverParallelData = yes", namespace=namespace)
537 end if
538 if (this%method == poisson_fft .and. library == fftlib_pfft) then
539 call messages_not_implemented("k-point parallelization with PFFT library for", namespace=namespace)
540 call messages_not_implemented("PFFT library for Poisson solver", namespace=namespace)
541 end if
542 end if
543
544 if (this%method == poisson_fft) then
545
546 need_cube = .true.
547
548 !%Variable DoubleFFTParameter
549 !%Type float
550 !%Default 2.0
551 !%Section Mesh::FFTs
552 !%Description
553 !% For solving the Poisson equation in Fourier space, and for applying the local potential
554 !% in Fourier space, an auxiliary cubic mesh is built. This mesh will be larger than
555 !% the circumscribed cube of the usual mesh by a factor <tt>DoubleFFTParameter</tt>. See
556 !% the section that refers to Poisson equation, and to the local potential for details
557 !% [the default value of two is typically good].
558 !%End
559 call parse_variable(namespace, 'DoubleFFTParameter', m_two, fft_alpha)
560 if (fft_alpha < m_one .or. fft_alpha > m_three) then
561 write(message(1), '(a,f12.5,a)') "Input: '", fft_alpha, &
562 "' is not a valid DoubleFFTParameter"
563 message(2) = '1.0 <= DoubleFFTParameter <= 3.0'
564 call messages_fatal(2, namespace=namespace)
565 end if
566
567 if (space%dim /= 3 .and. library == fftlib_pfft) then
568 call messages_not_implemented('PFFT support for dimensionality other than 3', namespace=namespace)
569 end if
570
571 select case (space%dim)
572
573 case (1)
574 select case (this%kernel)
576 call mesh_double_box(space, der%mesh, fft_alpha, box)
578 box = der%mesh%idx%ll
579 end select
580
581 case (2)
582 select case (this%kernel)
584 call mesh_double_box(space, der%mesh, fft_alpha, box)
585 box(1:2) = maxval(box)
587 call mesh_double_box(space, der%mesh, fft_alpha, box)
589 box(:) = der%mesh%idx%ll(:)
590 end select
591
592 case (3)
593 select case (this%kernel)
595 call mesh_double_box(space, der%mesh, fft_alpha, box)
596 box(:) = maxval(box)
598 call mesh_double_box(space, der%mesh, fft_alpha, box)
599 box(2) = maxval(box(2:3)) ! max of finite directions
600 box(3) = maxval(box(2:3)) ! max of finite directions
602 box(:) = der%mesh%idx%ll(:)
604 call mesh_double_box(space, der%mesh, fft_alpha, box)
605 end select
606
607 end select
608
609 end if
610
611 ! Solvers that cannot transform a whole batch at once are applied one function at a time
612 ! (see X(poisson_solve_batch)) and do not need a batched cube.
613 if (.not. poisson_is_batch_capable(this)) fft_bs = 1
614
615 ! Create the cube
616 if (need_cube) then
617 call cube_init(this%cube, box, namespace, space, der%mesh%spacing, &
618 der%mesh%coord_system, fft_type = fft_type, fft_library = fft_library, &
619 need_partition=.not.der%mesh%parallel_in_domains, &
620 batch_size=fft_bs, single=single_precision)
621 call cube_init_cube_map(this%cube, der%mesh)
622 if (this%cube%parallel_in_domains .and. this%method == poisson_fft) then
623 call mesh_cube_parallel_map_init(this%mesh_cube_map, der%mesh, this%cube)
624 end if
625 end if
626
627 if (this%is_dressed .and. .not. this%method == poisson_direct_sum) then
628 write(message(1), '(a)')'Dressed Orbital calculation currently only working with direct sum Poisson solver.'
629 call messages_fatal(1, namespace=namespace)
630 end if
631
632 call poisson_kernel_init(this, namespace, space, mc, stencil)
633
634 pop_sub(poisson_init)
635 end subroutine poisson_init
636
637 !-----------------------------------------------------------------
638 subroutine poisson_end(this)
639 type(poisson_t), intent(inout) :: this
640
641 logical :: has_cube
642
643 push_sub(poisson_end)
644
645 has_cube = .false.
646
647 select case (this%method)
648 case (poisson_fft)
649 call poisson_fft_end(this%fft_solver)
650 if (this%kernel == poisson_fft_kernel_corrected) call poisson_corrections_end(this%corrector)
651 has_cube = .true.
652
654 call poisson_cg_end()
655 call poisson_corrections_end(this%corrector)
656
657 case (poisson_multigrid)
658 call poisson_multigrid_end(this%mg)
659
660 case (poisson_isf)
661 call poisson_isf_end(this%isf_solver)
662 has_cube = .true.
663
664 case (poisson_psolver)
665 call poisson_psolver_end(this%psolver_solver)
666 has_cube = .true.
667
668 case (poisson_nfft)
669 call poisson_nfft_end(this%nfft_solver)
670
671 case (poisson_no)
672 call poisson_no_end(this%no_solver)
673
674 end select
675 this%method = poisson_null
676
677 if (has_cube) then
678 if (this%cube%parallel_in_domains) then
679 call mesh_cube_parallel_map_end(this%mesh_cube_map)
680 end if
681 call cube_end(this%cube)
682 end if
683
684 if (this%is_dressed) then
685 call photon_mode_end(this%photons)
686 end if
687 this%is_dressed = .false.
688
689 pop_sub(poisson_end)
690 end subroutine poisson_end
691
692 !-----------------------------------------------------------------
693
694 subroutine zpoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
695 type(poisson_t), intent(in) :: this
696 type(namespace_t), intent(in) :: namespace
697 complex(real64), contiguous, intent(inout) :: pot(:)
698 complex(real64), contiguous, intent(in) :: rho(:)
699 logical, optional, intent(in) :: all_nodes
700 type(fourier_space_op_t), optional, intent(in) :: kernel
701 logical, optional, intent(in) :: reset
702
703 logical :: all_nodes_value
704
705 push_sub(zpoisson_solve)
706
707 all_nodes_value = optional_default(all_nodes, this%all_nodes_default)
708
709 assert(ubound(pot, dim = 1) == this%der%mesh%np_part .or. ubound(pot, dim = 1) == this%der%mesh%np)
710 assert(ubound(rho, dim = 1) == this%der%mesh%np_part .or. ubound(rho, dim = 1) == this%der%mesh%np)
711
712 assert(this%method /= poisson_null)
713
714 if (poisson_solver_is_iterative(this) .and. optional_default(reset, .true.)) then
715 pot(1:this%der%mesh%np) = m_zero
716 end if
717
719 !We add the profiling here, as the other path uses dpoisson_solve
720 call profiling_in('ZPOISSON_SOLVE')
721 select case (this%method)
722 case (poisson_fft)
723 call zpoisson_fft_solve(this%fft_solver, this%der%mesh, this%cube, pot, rho, this%mesh_cube_map, kernel=kernel)
724 case (poisson_nfft)
725 assert(.not. present(kernel))
726 call zpoisson_nfft_solve(this%nfft_solver, this%der%mesh, pot, rho)
727 end select
728 call profiling_out('ZPOISSON_SOLVE')
729 else
730 call zpoisson_solve_real_and_imag_separately(this, namespace, pot, rho, all_nodes_value, kernel = kernel)
731 end if
732
733 pop_sub(zpoisson_solve)
734 end subroutine zpoisson_solve
735
736
737 !-----------------------------------------------------------------
738
739 subroutine poisson_solve_batch(this, namespace, potb, rhob, all_nodes, kernel)
740 type(poisson_t), intent(inout) :: this
741 type(namespace_t), intent(in) :: namespace
742 type(batch_t), intent(inout) :: potb
743 type(batch_t), intent(inout) :: rhob
744 logical, optional, intent(in) :: all_nodes
745 type(fourier_space_op_t), optional, intent(in) :: kernel
746
747 integer :: ii
748
749 push_sub(poisson_solve_batch)
750
751 assert(potb%nst_linear == rhob%nst_linear)
752 assert(potb%type() == rhob%type())
753
754 if (potb%type() == type_float) then
755 do ii = 1, potb%nst_linear
756 call dpoisson_solve(this, namespace, potb%dff_linear(:, ii), rhob%dff_linear(:, ii), all_nodes, kernel=kernel)
757 end do
758 else
759 do ii = 1, potb%nst_linear
760 call zpoisson_solve(this, namespace, potb%zff_linear(:, ii), rhob%zff_linear(:, ii), all_nodes, kernel=kernel)
761 end do
762 end if
763
764 pop_sub(poisson_solve_batch)
765 end subroutine poisson_solve_batch
766
767 !-----------------------------------------------------------------
771 logical function poisson_solves_complex_natively(this)
772 type(poisson_t), intent(in) :: this
773
774 select case (this%method)
775 case (poisson_fft)
777 .and. .not. this%is_dressed .and. this%cube%fft%type == fft_complex
778 case (poisson_nfft)
780 case default
782 end select
784
785 !-----------------------------------------------------------------
789 logical function poisson_uses_nfft(this)
790 type(poisson_t), intent(in) :: this
791
792 select case (this%method)
793 case (poisson_nfft)
795 case (poisson_fft)
796 poisson_uses_nfft = this%cube%fft%library == fftlib_nfft
797 case default
798 poisson_uses_nfft = .false.
799 end select
800 end function poisson_uses_nfft
801
802 !-----------------------------------------------------------------
808 logical function poisson_is_batch_capable(this)
809 type(poisson_t), intent(in) :: this
810
811 poisson_is_batch_capable = this%method == poisson_fft &
812 .and. this%kernel /= poisson_fft_kernel_corrected
813 end function poisson_is_batch_capable
814
815 !-----------------------------------------------------------------
817 logical function poisson_is_device_batch_capable(this)
818 type(poisson_t), intent(in) :: this
820 ! Tested in steps: only a batch-capable solver is guaranteed to have an FFT cube.
822 if (.not. accel_is_enabled()) return
823 if (.not. poisson_is_batch_capable(this)) return
824 poisson_is_device_batch_capable = this%cube%fft%library == fftlib_accel &
825 .and. .not. this%cube%parallel_in_domains
827
828 !-----------------------------------------------------------------
829
835 subroutine dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
836 type(poisson_t), intent(in) :: this
837 type(namespace_t), intent(in) :: namespace
838 real(real64), contiguous, intent(inout) :: pot(:)
839 real(real64), contiguous, intent(in) :: rho(:)
843 logical, optional, intent(in) :: all_nodes
844 type(fourier_space_op_t), optional, intent(in) :: kernel
845 logical, optional, intent(in) :: reset
846
847 type(derivatives_t), pointer :: der
848 real(real64), allocatable :: rho_corrected(:), vh_correction(:)
849 logical :: all_nodes_value
850
851 call profiling_in('POISSON_SOLVE')
852 push_sub(dpoisson_solve)
853
854 der => this%der
855
856 assert(ubound(pot, dim = 1) == der%mesh%np_part .or. ubound(pot, dim = 1) == der%mesh%np)
857 assert(ubound(rho, dim = 1) == der%mesh%np_part .or. ubound(rho, dim = 1) == der%mesh%np)
858
859 ! Check optional argument and set to default if necessary.
860 all_nodes_value = optional_default(all_nodes, this%all_nodes_default)
861
862 if (poisson_solver_is_iterative(this) .and. optional_default(reset, .true.)) then
863 pot(1:der%mesh%np) = m_zero
864 end if
865
866 assert(this%method /= poisson_null)
867
868 if (present(kernel)) then
869 assert(this%method == poisson_fft)
870 end if
871
872 select case (this%method)
873 case (poisson_direct_sum)
874 if ((this%is_dressed .and. this%der%dim - 1 > 3) .or. this%der%dim > 3) then
875 message(1) = "Direct sum Poisson solver only available for 1, 2, or 3 dimensions."
876 call messages_fatal(1, namespace=namespace)
877 end if
878 call poisson_solve_direct(this, namespace, pot, rho)
879
880 case (poisson_cg)
881 call poisson_cg1(namespace, der, this%corrector, pot, rho)
882
884 safe_allocate(rho_corrected(1:der%mesh%np))
885 safe_allocate(vh_correction(1:der%mesh%np_part))
886
887 call correct_rho(this%corrector, der, rho, rho_corrected, vh_correction)
889 call lalg_axpy(der%mesh%np, -m_one, vh_correction, pot)
890 call poisson_cg2(namespace, der, pot, rho_corrected)
891 call lalg_axpy(der%mesh%np, m_one, vh_correction, pot)
892
893 safe_deallocate_a(rho_corrected)
894 safe_deallocate_a(vh_correction)
895
896 case (poisson_multigrid)
897 call poisson_multigrid_solver(this%mg, namespace, der, pot, rho)
898
899 case (poisson_fft)
900 if (this%kernel /= poisson_fft_kernel_corrected) then
901 call dpoisson_fft_solve(this%fft_solver, der%mesh, this%cube, pot, rho, this%mesh_cube_map, kernel=kernel)
902 else
903 safe_allocate(rho_corrected(1:der%mesh%np))
904 safe_allocate(vh_correction(1:der%mesh%np_part))
905
906 call correct_rho(this%corrector, der, rho, rho_corrected, vh_correction)
907 call dpoisson_fft_solve(this%fft_solver, der%mesh, this%cube, pot, rho_corrected, this%mesh_cube_map, &
908 average_to_zero = .true., kernel=kernel)
909
910 call lalg_axpy(der%mesh%np, m_one, vh_correction, pot)
911 safe_deallocate_a(rho_corrected)
912 safe_deallocate_a(vh_correction)
913 end if
914
916 call poisson_isf_solve(this%isf_solver, der%mesh, this%cube, pot, rho, all_nodes_value)
917
918
919 case (poisson_psolver)
920 if (this%psolver_solver%datacode == "G") then
921 ! Global version
922 call poisson_psolver_global_solve(this%psolver_solver, der%mesh, this%cube, pot, rho)
923 else ! "D" Distributed version
924 call poisson_psolver_parallel_solve(this%psolver_solver, der%mesh, this%cube, pot, rho, this%mesh_cube_map)
925 end if
926
927 case (poisson_nfft)
928 call dpoisson_nfft_solve(this%nfft_solver, der%mesh, pot, rho)
929
930 case (poisson_no)
931 call poisson_no_solve(this%no_solver, der%mesh, pot, rho)
932 end select
933
934 ! Add extra terms for dressed interaction
935 if (this%is_dressed .and. this%method /= poisson_no) then
936 call photon_mode_add_poisson_terms(this%photons, der%mesh, rho, pot)
937 end if
938
939 pop_sub(dpoisson_solve)
940 call profiling_out('POISSON_SOLVE')
941 end subroutine dpoisson_solve
942
943 !-----------------------------------------------------------------
944 subroutine poisson_init_sm(this, namespace, space, main, der, sm, grp, method, force_cmplx)
945 type(poisson_t), intent(inout) :: this
946 type(namespace_t), intent(in) :: namespace
947 class(space_t), intent(in) :: space
948 type(poisson_t), intent(in) :: main
949 type(derivatives_t), target, intent(in) :: der
950 type(submesh_t), intent(inout) :: sm
951 type(mpi_grp_t), intent(in) :: grp
952 integer, optional, intent(in) :: method
953 logical, optional, intent(in) :: force_cmplx
954
955 integer :: default_solver, idir, iter, maxl
956 integer :: box(space%dim)
957 real(real64) :: qq(der%dim), threshold
958
959 if (this%method /= poisson_null) return ! already initialized
960
961 push_sub(poisson_init_sm)
962
963 this%is_dressed = .false.
964 !TODO: To be implemented as an option
965 this%all_nodes_default = .false.
966
967 this%nslaves = 0
968 this%der => der
969
970#ifdef HAVE_MPI
971 this%all_nodes_default = main%all_nodes_default
972#endif
973
974 default_solver = poisson_direct_sum
975 this%method = default_solver
976 if (present(method)) this%method = method
977
978 if (der%mesh%use_curvilinear) then
979 call messages_not_implemented("Submesh Poisson solver with curvilinear mesh", namespace=namespace)
980 end if
981
982 this%kernel = poisson_fft_kernel_none
983
984 select case (this%method)
985 case (poisson_direct_sum)
986 !Nothing to be done
987
988 case (poisson_isf)
989 !TODO: Add support for domain parrallelization
990 assert(.not. der%mesh%parallel_in_domains)
991 call submesh_get_cube_dim(sm, space, box)
992 call submesh_init_cube_map(sm, space)
993 call cube_init(this%cube, box, namespace, space, sm%mesh%spacing, sm%mesh%coord_system, &
994 fft_type = fft_none, need_partition=.not.der%mesh%parallel_in_domains)
995 call cube_init_cube_map(this%cube, sm%mesh)
996 call poisson_isf_init(this%isf_solver, namespace, der%mesh, this%cube, grp%comm, init_world = this%all_nodes_default)
997
998 case (poisson_psolver)
999 !TODO: Add support for domain parrallelization
1000 assert(.not. der%mesh%parallel_in_domains)
1001 if (this%all_nodes_default) then
1002 this%cube%mpi_grp = grp
1003 else
1004 this%cube%mpi_grp = this%der%mesh%mpi_grp
1005 end if
1006 call submesh_get_cube_dim(sm, space, box)
1007 call submesh_init_cube_map(sm, space)
1008 call cube_init(this%cube, box, namespace, space, sm%mesh%spacing, sm%mesh%coord_system, &
1009 fft_type = fft_none, need_partition=.not.der%mesh%parallel_in_domains)
1010 call cube_init_cube_map(this%cube, sm%mesh)
1011 qq = m_zero
1012 call poisson_psolver_init(this%psolver_solver, namespace, space, this%cube, m_zero, qq, force_isolated=.true.)
1013 call poisson_psolver_get_dims(this%psolver_solver, this%cube)
1014 case (poisson_fft)
1015 !Here we impose zero boundary conditions
1016 this%kernel = poisson_fft_kernel_sph
1017
1018 call submesh_get_cube_dim(sm, space, box)
1019 call submesh_init_cube_map(sm, space)
1020 !We double the size of the cell
1021 !Maybe the factor of two should be controlled as a variable
1022 do idir = 1, space%dim
1023 box(idir) = (2 * (box(idir) - 1)) + 1
1024 end do
1025 if (optional_default(force_cmplx, .false.)) then
1026 call cube_init(this%cube, box, namespace, space, sm%mesh%spacing, sm%mesh%coord_system, &
1027 fft_type = fft_complex, need_partition=.not.der%mesh%parallel_in_domains)
1028 else
1029 call cube_init(this%cube, box, namespace, space, sm%mesh%spacing, sm%mesh%coord_system, &
1030 fft_type = fft_real, need_partition=.not.der%mesh%parallel_in_domains)
1031 end if
1032 call poisson_fft_init(this%fft_solver, namespace, space, this%cube, this%kernel)
1033 case (poisson_cg)
1034 call parse_variable(namespace, 'PoissonSolverMaxMultipole', 4, maxl)
1035 write(message(1),'(a,i2)')'Info: Boundary conditions fixed up to L =', maxl
1036 call messages_info(1, namespace=namespace)
1037 call parse_variable(namespace, 'PoissonSolverMaxIter', 500, iter)
1038 call parse_variable(namespace, 'PoissonSolverThreshold', 1.0e-6_real64, threshold)
1039 call poisson_corrections_init(this%corrector, namespace, space, maxl, this%der%mesh)
1040 call poisson_cg_init(threshold, iter)
1041 end select
1042
1043 pop_sub(poisson_init_sm)
1044 end subroutine poisson_init_sm
1045
1046 ! -----------------------------------------------------------------
1047
1048 logical pure function poisson_solver_is_iterative(this) result(iterative)
1049 type(poisson_t), intent(in) :: this
1050
1051 iterative = this%method == poisson_cg .or. this%method == poisson_cg_corrected
1052 end function poisson_solver_is_iterative
1053
1054 !-----------------------------------------------------------------
1055 subroutine poisson_async_init(this, mc)
1056 type(poisson_t), intent(inout) :: this
1057 type(multicomm_t), intent(in) :: mc
1058
1059 push_sub(poisson_async_init)
1060
1061#ifdef HAVE_MPI
1062 if (multicomm_have_slaves(mc)) then
1063
1064 call mpi_grp_init(this%local_grp, mc%group_comm(p_strategy_states))
1065
1066 this%root = (this%local_grp%is_root())
1067
1068 this%intercomm = mc%slave_intercomm
1069 call mpi_comm_remote_size(this%intercomm, this%nslaves)
1070
1071 end if
1072#endif
1073
1074 pop_sub(poisson_async_init)
1075
1076 end subroutine poisson_async_init
1077
1078 !-----------------------------------------------------------------
1079
1080 subroutine poisson_async_end(this, mc)
1081 type(poisson_t), intent(inout) :: this
1082 type(multicomm_t), intent(in) :: mc
1083
1084#ifdef HAVE_MPI
1085 integer :: islave
1086#endif
1087
1088 push_sub(poisson_async_end)
1089
1090#ifdef HAVE_MPI
1091 if (multicomm_have_slaves(mc)) then
1092
1093 ! send the finish signal
1094 do islave = this%local_grp%rank, this%nslaves - 1, this%local_grp%size
1095 call mpi_send(m_one, 1, mpi_double_precision, islave, cmd_finish, this%intercomm)
1096 end do
1097
1098 end if
1099#endif
1100
1101 pop_sub(poisson_async_end)
1102
1103 end subroutine poisson_async_end
1104
1105 !-----------------------------------------------------------------
1106
1107 subroutine poisson_slave_work(this, namespace)
1108 type(poisson_t), intent(inout) :: this
1109 type(namespace_t), intent(in) :: namespace
1110
1111#ifdef HAVE_MPI
1112 real(real64), allocatable :: rho(:), pot(:)
1113 logical :: done
1114 type(mpi_status) :: status
1115 integer :: bcast_root
1116
1117 push_sub(poisson_slave_work)
1118 call profiling_in("SLAVE_WORK")
1119
1120 safe_allocate(rho(1:this%der%mesh%np))
1121 safe_allocate(pot(1:this%der%mesh%np))
1122 done = .false.
1123
1124 do while(.not. done)
1125
1126 call profiling_in("SLAVE_WAIT")
1127 call mpi_recv(rho(1), this%der%mesh%np, mpi_double_precision, mpi_any_source, mpi_any_tag, this%intercomm, status)
1128 call profiling_out("SLAVE_WAIT")
1129
1130 ! The tag of the message tells us what we have to do.
1131 select case (status%MPI_TAG)
1132
1133 case (cmd_finish)
1134 done = .true.
1136 case (cmd_poisson_solve)
1137 call dpoisson_solve(this, namespace, pot, rho)
1138
1139 call profiling_in("SLAVE_BROADCAST")
1140 bcast_root = mpi_proc_null
1141 if (this%root) bcast_root = mpi_root
1142 call mpi_bcast(pot(1), this%der%mesh%np, mpi_double_precision, bcast_root, this%intercomm)
1143 call profiling_out("SLAVE_BROADCAST")
1144
1145 end select
1146
1147 end do
1148
1149 safe_deallocate_a(pot)
1150 safe_deallocate_a(rho)
1151
1152 call profiling_out("SLAVE_WORK")
1153 pop_sub(poisson_slave_work)
1154#endif
1155 end subroutine poisson_slave_work
1156
1157 !----------------------------------------------------------------
1158
1159 logical pure function poisson_is_async(this) result(async)
1160 type(poisson_t), intent(in) :: this
1161
1162 async = (this%nslaves > 0)
1164 end function poisson_is_async
1165
1166 !----------------------------------------------------------------
1167
1168 subroutine poisson_build_kernel(this, namespace, space, coulb, qq, cam, singul)
1169 type(poisson_t), intent(in) :: this
1170 type(namespace_t), intent(in) :: namespace
1171 class(space_t), intent(in) :: space
1172 type(fourier_space_op_t), intent(inout) :: coulb
1173 real(real64), intent(in) :: qq(:)
1174 type(xc_cam_t), intent(in) :: cam
1175 real(real64), optional, intent(in) :: singul
1176
1177 logical :: reinit
1178
1179 push_sub(poisson_build_kernel)
1181 if (space%is_periodic()) then
1182 assert(ubound(qq, 1) >= space%periodic_dim)
1183 assert(this%method == poisson_fft)
1184 end if
1185
1186 if (cam%omega > m_epsilon) then
1187 if (this%method /= poisson_fft) then
1188 write(message(1),'(a)') "Poisson solver with range separation is only implemented with FFT."
1189 call messages_fatal(1, namespace=namespace)
1190 end if
1191 end if
1192
1193 !We only reinitialize the poisson solver if needed
1194 reinit = .false.
1195 if (allocated(coulb%qq)) then
1196 reinit = any(abs(coulb%qq(1:space%periodic_dim) - qq(1:space%periodic_dim)) > m_epsilon)
1197 end if
1198 reinit = reinit .or. (abs(coulb%mu - cam%omega) > m_epsilon .and. cam%omega > m_epsilon)
1199 reinit = reinit .or. (abs(coulb%alpha - cam%alpha) > m_epsilon .and. cam%alpha > m_epsilon)
1200 reinit = reinit .or. (abs(coulb%beta - cam%beta) > m_epsilon .and. abs(cam%beta) > m_epsilon)
1201
1202 if (reinit) then
1203 call profiling_in('POISSON_BUILD_KERNEL')
1204 !TODO: this should be a select case supporting other kernels.
1205 ! This means that we need an abstract object for kernels.
1206 select case (this%method)
1207 case (poisson_fft)
1208 ! Check that we are consistent: the Poisson solver supports must return 1 here
1209 assert(is_close(poisson_get_full_range_weight(this, cam), m_one))
1210 call coulb%end()
1211 call coulb%init(space, qq, cam, singul)
1212 call poisson_fft_get_kernel(namespace, space, this%cube, coulb, this%kernel, &
1213 this%poisson_soft_coulomb_param)
1214 case default
1215 call messages_not_implemented("poisson_build_kernel with other methods than FFT", namespace=namespace)
1216 end select
1217 call profiling_out('POISSON_BUILD_KERNEL')
1218 end if
1219
1220 pop_sub(poisson_build_kernel)
1221 end subroutine poisson_build_kernel
1222
1223 !----------------------------------------------------------------
1232 real(real64) function poisson_get_full_range_weight(this, cam) result(weight)
1233 type(poisson_t), intent(in) :: this
1234 type(xc_cam_t), intent(in) :: cam
1235
1236 select case (this%method)
1237 case (poisson_fft)
1238 weight = m_one
1239 case default
1240 if(cam%omega < m_epsilon) then
1241 weight = cam%alpha
1242 else if(cam%alpha > m_epsilon .and. cam%beta < m_epsilon) then
1243 weight = cam%alpha
1244 else if(cam%alpha < m_epsilon .and. cam%beta > m_epsilon) then
1245 weight = cam%beta
1246 else
1247 assert(.false.)
1248 end if
1249 end select
1251
1252#include "poisson_init_inc.F90"
1253#include "poisson_direct_inc.F90"
1254#include "poisson_direct_sm_inc.F90"
1255
1256#include "undef.F90"
1257#include "real.F90"
1258#include "poisson_inc.F90"
1259#include "undef.F90"
1260#include "complex.F90"
1261#include "poisson_inc.F90"
1262#include "poisson_re_im_inc.F90"
1263
1264#include "undef.F90"
1265#include "real32.F90"
1266#include "poisson_inc.F90"
1267#include "undef.F90"
1268#include "complex32.F90"
1269#include "poisson_inc.F90"
1270#include "poisson_re_im_inc.F90"
1271
1272end module poisson_oct_m
1273
1274!! Local Variables:
1275!! mode: f90
1276!! coding: utf-8
1277!! End:
constant times a vector plus a vector
Definition: lalg_basic.F90:194
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
Definition: messages.F90:182
pure logical function, public accel_is_enabled()
Definition: accel.F90:414
This module implements batches of mesh functions.
Definition: batch.F90:135
This module handles the calculation mode.
integer, parameter, public p_strategy_kpoints
parallelization in k-points
subroutine, public cube_end(cube)
Definition: cube.F90:406
subroutine, public cube_init(cube, nn, namespace, space, spacing, coord_system, fft_type, fft_library, dont_optimize, nn_out, mpi_grp, need_partition, tp_enlarge, blocksize, batch_size, nthreads, single)
Definition: cube.F90:208
subroutine, public cube_init_cube_map(cube, mesh)
Definition: cube.F90:889
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
Definition: fft.F90:120
integer, parameter, public fft_none
global constants
Definition: fft.F90:178
integer, public fft_default_lib
Definition: fft.F90:284
integer, parameter, public fftlib_accel
Definition: fft.F90:183
integer, parameter, public fft_real
Definition: fft.F90:178
integer, parameter, public fft_complex
Definition: fft.F90:178
integer, parameter, public fftlib_nfft
Definition: fft.F90:183
integer, parameter, public fftlib_pfft
Definition: fft.F90:183
integer, parameter, public fftlib_fftw
Definition: fft.F90:183
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_one
Definition: global.F90:201
real(real64), parameter, public m_three
Definition: global.F90:203
This module implements the index, used for the mesh points.
Definition: index.F90:124
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
subroutine, public mesh_cube_parallel_map_end(this)
subroutine, public mesh_cube_parallel_map_init(this, mesh, cube)
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
subroutine, public mesh_double_box(space, mesh, alpha, db)
finds the dimension of a box doubled in the non-periodic dimensions
Definition: mesh.F90:290
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:898
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1068
character(len=512), private msg
Definition: messages.F90:167
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
subroutine, public messages_experimental(name, namespace)
Definition: messages.F90:1040
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:147
logical pure function, public multicomm_strategy_is_parallel(mc, level)
Definition: multicomm.F90:728
logical pure function, public multicomm_have_slaves(this)
Definition: multicomm.F90:854
Some general things and nomenclature:
Definition: par_vec.F90:173
subroutine, public photon_mode_compute_dipoles(this, mesh)
Computes the polarization dipole.
subroutine, public photon_mode_add_poisson_terms(this, mesh, rho, pot)
subroutine, public photon_mode_end(this)
subroutine, public photon_mode_set_n_electrons(this, qtot)
subroutine, public photon_mode_init(this, namespace, dim, photon_free)
real(real64), public threshold
Definition: poisson_cg.F90:141
subroutine, public poisson_cg2(namespace, der, pot, rho)
Definition: poisson_cg.F90:231
subroutine, public poisson_cg1(namespace, der, corrector, pot, rho)
Definition: poisson_cg.F90:167
subroutine, public poisson_cg_init(thr, itr)
Definition: poisson_cg.F90:149
subroutine, public poisson_cg_end
Definition: poisson_cg.F90:161
subroutine, public poisson_corrections_end(this)
subroutine, public poisson_corrections_init(this, namespace, space, ml, mesh)
subroutine, public correct_rho(this, der, rho, rho_corrected, vh_correction)
integer, parameter, public poisson_fft_kernel_nocut
integer, parameter, public poisson_fft_kernel_cyl
subroutine, public zpoisson_fft_solve(this, mesh, cube, pot, rho, mesh_cube_map, average_to_zero, kernel, sm)
subroutine, public poisson_fft_end(this)
subroutine, public poisson_fft_init(this, namespace, space, cube, kernel, soft_coulb_param, fullcube)
integer, parameter, public poisson_fft_kernel_pla
integer, parameter, public poisson_fft_kernel_none
integer, parameter, public poisson_fft_kernel_corrected
integer, parameter, public poisson_fft_kernel_sph
subroutine, public dpoisson_fft_solve(this, mesh, cube, pot, rho, mesh_cube_map, average_to_zero, kernel, sm)
subroutine, public poisson_isf_end(this)
subroutine, public poisson_isf_init(this, namespace, mesh, cube, all_nodes_comm, init_world)
subroutine, public poisson_isf_solve(this, mesh, cube, pot, rho, all_nodes, sm)
subroutine, public poisson_multigrid_solver(this, namespace, der, pot, rho)
A multigrid Poisson solver with corrections at the boundaries.
subroutine, public poisson_multigrid_end(this)
Poisson solver on the mesh points themselves, through non-equispaced FFTs.
subroutine, public dpoisson_nfft_solve(this, mesh, pot, rho)
subroutine, public poisson_nfft_end(this)
subroutine, public zpoisson_nfft_solve(this, mesh, pot, rho)
The transform is complex either way, so a complex density costs the same as a real one and needs no s...
subroutine, public poisson_no_solve(this, mesh, pot, rho)
Definition: poisson_no.F90:164
subroutine, public poisson_no_end(this)
Definition: poisson_no.F90:152
subroutine, public zpoisson_solve_sm(this, namespace, sm, pot, rho, all_nodes)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:2339
integer, parameter, public poisson_multigrid
Definition: poisson.F90:199
subroutine poisson_kernel_init(this, namespace, space, mc, stencil)
Definition: poisson.F90:1285
integer, parameter, public poisson_psolver
Definition: poisson.F90:199
subroutine, public dpoisson_solve_start(this, rho)
Definition: poisson.F90:2059
integer, parameter cmd_finish
Definition: poisson.F90:237
subroutine, public zpoisson_solve_finish(this, pot)
Definition: poisson.F90:2327
subroutine poisson_solve_direct(this, namespace, pot, rho)
Definition: poisson.F90:1502
integer, parameter, public poisson_fft
Definition: poisson.F90:199
subroutine, public spoisson_solve_batch(this, namespace, pot, rho, kernel, all_nodes, pot_buffer, rho_buffer, count)
Solves the Poisson equation for batched quantities, using fast Fourier transforms (FFTs).
Definition: poisson.F90:2890
subroutine, public spoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
Single-precision scalar Poisson solve (FFT method only). This is the s/c counterpart of the concrete ...
Definition: poisson.F90:2843
subroutine, public zpoisson_solve_batch(this, namespace, pot, rho, kernel, all_nodes, pot_buffer, rho_buffer, count)
Solves the Poisson equation for batched quantities, using fast Fourier transforms (FFTs).
Definition: poisson.F90:2475
subroutine, public zpoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
Definition: poisson.F90:775
subroutine, public poisson_init_sm(this, namespace, space, main, der, sm, grp, method, force_cmplx)
Definition: poisson.F90:1025
subroutine, public poisson_solve_batch(this, namespace, potb, rhob, all_nodes, kernel)
Definition: poisson.F90:820
subroutine, public poisson_async_init(this, mc)
Definition: poisson.F90:1136
subroutine, public dpoisson_solve_sm(this, namespace, sm, pot, rho, all_nodes)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:2079
subroutine zpoisson_solve_real_and_imag_separately(this, namespace, pot, rho, all_nodes, kernel)
Definition: poisson.F90:2586
subroutine, public cpoisson_solve_batch(this, namespace, pot, rho, kernel, all_nodes, pot_buffer, rho_buffer, count)
Solves the Poisson equation for batched quantities, using fast Fourier transforms (FFTs).
Definition: poisson.F90:3110
integer, parameter, public poisson_nfft
Definition: poisson.F90:199
logical pure function poisson_solver_is_iterative(this)
Definition: poisson.F90:1129
subroutine, public poisson_slave_work(this, namespace)
Definition: poisson.F90:1164
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:916
integer, parameter cmd_poisson_solve
Definition: poisson.F90:237
integer, parameter, public poisson_cg
Definition: poisson.F90:199
subroutine, public poisson_init(this, namespace, space, der, mc, stencil, qtot, label, solver, verbose, force_serial, force_cmplx, fft_library, fft_batch_size, single_precision)
Definition: poisson.F90:246
subroutine, public poisson_build_kernel(this, namespace, space, coulb, qq, cam, singul)
Definition: poisson.F90:1181
subroutine, public dpoisson_solve_finish(this, pot)
Definition: poisson.F90:2067
subroutine, public zpoisson_solve_start(this, rho)
Definition: poisson.F90:2319
subroutine, public poisson_async_end(this, mc)
Definition: poisson.F90:1148
integer, parameter, public poisson_cg_corrected
Definition: poisson.F90:199
logical function, public poisson_is_device_batch_capable(this)
Whether a batch can be solved with the densities and potentials kept on the device.
Definition: poisson.F90:898
logical function, public poisson_uses_nfft(this)
Whether the solve goes through a non-equispaced FFT.
Definition: poisson.F90:870
subroutine, public cpoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
Single-precision scalar Poisson solve (FFT method only). This is the s/c counterpart of the concrete ...
Definition: poisson.F90:3056
logical function, public poisson_is_batch_capable(this)
Whether this solver can transform a whole batch of functions in one call.
Definition: poisson.F90:889
integer, parameter, public poisson_isf
Definition: poisson.F90:199
real(real64) function, public poisson_get_full_range_weight(this, cam)
Most Poisson solvers do not implement Coulomb attenuated potentials, and can only be used for global ...
Definition: poisson.F90:1245
subroutine, public dpoisson_solve_batch(this, namespace, pot, rho, kernel, all_nodes, pot_buffer, rho_buffer, count)
Solves the Poisson equation for batched quantities, using fast Fourier transforms (FFTs).
Definition: poisson.F90:2159
logical function, public poisson_solves_complex_natively(this)
Whether zpoisson_solve takes a complex density in one pass.
Definition: poisson.F90:852
integer, parameter, public poisson_null
Definition: poisson.F90:199
integer, parameter, public poisson_no
Definition: poisson.F90:199
logical pure function, public poisson_is_async(this)
Definition: poisson.F90:1172
subroutine, public poisson_end(this)
Definition: poisson.F90:719
subroutine, public poisson_psolver_global_solve(this, mesh, cube, pot, rho, sm)
subroutine, public poisson_psolver_parallel_solve(this, mesh, cube, pot, rho, mesh_cube_map)
subroutine, public poisson_psolver_end(this)
subroutine, public poisson_psolver_get_dims(this, cube)
subroutine, public poisson_psolver_init(this, namespace, space, cube, mu, qq, force_isolated)
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:668
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:600
This module defines stencils used in Octopus.
Definition: stencil.F90:137
subroutine, public submesh_init_cube_map(sm, space)
Definition: submesh.F90:972
subroutine, public submesh_get_cube_dim(sm, space, db)
finds the dimension of a box containing the submesh
Definition: submesh.F90:937
type(type_t), parameter, public type_float
Definition: types.F90:136
This module defines the unit system, used for input and output.
Class defining batches of mesh functions.
Definition: batch.F90:164
Class implementing a box that is a union of spheres. We do this in a specific class instead of using ...
class representing derivatives
Definition of a Fourier Space Coulomb Kernel.
This is defined even when running serial.
Definition: mpi.F90:144
A submesh is a type of mesh, used for the projectors in the pseudopotentials It contains points on a ...
Definition: submesh.F90:177
int true(void)