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