65 integer,
parameter,
public :: &
71 type(transfer_table_t) :: tt
72 type(mesh_t),
pointer :: mesh => null()
73 type(derivatives_t),
pointer :: der => null()
78 integer,
public :: n_levels
79 type(multigrid_level_t),
allocatable,
public :: level(:)
82 integer,
allocatable :: sp(:)
83 integer,
allocatable :: ep(:)
84 integer,
allocatable :: ep_part(:)
91 subroutine multigrid_init(mgrid, namespace, space, mesh, der, stencil, mc, nlevels)
92 type(multigrid_t),
target,
intent(out) :: mgrid
93 type(namespace_t),
intent(in) :: namespace
94 class(space_t),
intent(in) :: space
95 class(mesh_t),
target,
intent(in) :: mesh
96 type(derivatives_t),
target,
intent(in) :: der
97 type(stencil_t),
intent(in) :: stencil
98 type(multicomm_t),
intent(in) :: mc
99 integer,
optional,
intent(in) :: nlevels
101 integer :: i, n_levels, np, order
105 if (.not.
present(nlevels))
then
124 write(
message(1),
'(a,i1,a)')
"Set number of multigrid levels to ", n_levels,
". This ignores the value of MultigridLevels."
137 call parse_variable(namespace,
'MultigridDerivativesOrder', 1, order)
140 order = max(2, order)
145 if (any(mesh%idx%ll < 2**n_levels))
then
146 message(1) =
"Grid too small for the multigrid solver. Reducing the number of levels."
148 do i = n_levels, 1, -1
149 if (all(mesh%idx%ll >= 2**i))
then
156 if (n_levels <= 0)
then
157 n_levels = n_levels - 3
162 n_levels = n_levels + 1
165 n_levels = n_levels - 1
168 mgrid%n_levels = n_levels
170 safe_allocate(mgrid%level(0:n_levels))
172 mgrid%level(0)%mesh => mesh
173 mgrid%level(0)%der => der
175 mgrid%level(0)%tt%n_fine = mesh%np
176 safe_allocate(mgrid%level(0)%tt%fine_i(1:mesh%np))
178 write(
message(1),
'(a,i3)')
"Multigrid levels:", n_levels + 1
181 do i = 1, mgrid%n_levels
182 safe_allocate(mgrid%level(i)%mesh)
183 safe_allocate(mgrid%level(i)%der)
185 call multigrid_mesh_half(space, namespace, mgrid%level(i-1)%mesh, mgrid%level(i)%mesh, stencil)
187 call derivatives_init(mgrid%level(i)%der, namespace, space, mesh%coord_system, order=order)
189 call mesh_init_stage_3(mgrid%level(i)%mesh, namespace, space, stencil, mc, parent = mgrid%level(i - 1)%mesh)
193 call derivatives_build(mgrid%level(i)%der, namespace, space, mgrid%level(i)%mesh)
197 mgrid%level(i)%der%finer => mgrid%level(i - 1)%der
198 mgrid%level(i - 1)%der%coarser => mgrid%level(i)%der
199 mgrid%level(i)%der%to_finer => mgrid%level(i)%tt
200 mgrid%level(i - 1)%der%to_coarser => mgrid%level(i)%tt
203 safe_allocate(mgrid%sp(0:mgrid%n_levels))
204 safe_allocate(mgrid%ep(0:mgrid%n_levels))
205 safe_allocate(mgrid%ep_part(0:mgrid%n_levels))
208 do i = 0, mgrid%n_levels
209 mgrid%sp(i) = 1 + mgrid%tp
210 mgrid%ep(i) = mgrid%tp + mgrid%level(i)%mesh%np
211 mgrid%tp = mgrid%tp + mgrid%level(i)%mesh%np_part
212 mgrid%ep_part(i) = mgrid%tp
222 class(
space_t),
intent(in) :: space
223 type(
mesh_t),
intent(in) :: fine, coarse
225 integer :: i, i1, i2, i4, i8, pt
226 integer :: x(space%dim), mod2(space%dim), idx(space%dim)
231 assert(space%dim == 3)
233 tt%n_coarse = coarse%np
234 safe_allocate(tt%to_coarse(1:tt%n_coarse))
237 do i = 1, tt%n_coarse
245 safe_allocate(tt%fine_i(1:tt%n_fine))
259 tt%n_fine1 = tt%n_fine1 + 1
262 tt%n_fine2 = tt%n_fine2 + 1
265 tt%n_fine4 = tt%n_fine4 + 1
268 tt%n_fine8 = tt%n_fine8 + 1
273 assert(tt%n_fine1 + tt%n_fine2 + tt%n_fine4 + tt%n_fine8 == tt%n_fine)
275 safe_allocate(tt%to_fine1(1, 1:tt%n_fine1))
276 safe_allocate(tt%to_fine2(1:2, 1:tt%n_fine2))
277 safe_allocate(tt%to_fine4(1:4, 1:tt%n_fine4))
278 safe_allocate(tt%to_fine8(1:8, 1:tt%n_fine8))
324 assert(i1 == tt%n_fine1 .and. i2 == tt%n_fine2 .and. i4 == tt%n_fine4 .and. i8 == tt%n_fine8)
335 class(
space_t),
intent(in) :: space
337 type(
mesh_t),
target,
intent(in) :: mesh_in
338 type(
mesh_t),
intent(inout) :: mesh_out
345 mesh_out%box => mesh_in%box
346 mesh_out%idx%dim = mesh_in%idx%dim
347 mesh_out%use_curvilinear = mesh_in%use_curvilinear
348 mesh_out%masked_periodic_boundaries = mesh_in%masked_periodic_boundaries
349 mesh_out%coord_system => mesh_in%coord_system
351 safe_allocate(mesh_out%spacing(1:space%dim))
352 mesh_out%spacing(:) = 2*mesh_in%spacing(:)
355 mesh_out%idx%enlarge(:) = mesh_in%idx%enlarge(:)
356 mesh_out%idx%nr(1,:) = (mesh_in%idx%nr(1,:)+mesh_in%idx%enlarge(:))/2
357 mesh_out%idx%nr(2,:) = (mesh_in%idx%nr(2,:)-mesh_in%idx%enlarge(:))/2
358 mesh_out%idx%ll(:) = mesh_out%idx%nr(2, :) - mesh_out%idx%nr(1, :) + 1
360 mesh_out%idx%stride(1) = 1
361 do idim = 2, mesh_out%idx%dim + 1
362 mesh_out%idx%stride(idim) = mesh_out%idx%stride(idim-1) * &
363 (mesh_out%idx%ll(idim-1) + 2*mesh_out%idx%enlarge(idim-1))
373 class(
space_t),
intent(in) :: space
375 type(
mesh_t),
target,
intent(in) :: mesh_in
376 type(
mesh_t),
intent(inout) :: mesh_out
382 mesh_out%box => mesh_in%box
383 mesh_out%idx%dim = mesh_in%idx%dim
384 mesh_out%use_curvilinear = mesh_in%use_curvilinear
385 mesh_out%masked_periodic_boundaries = mesh_in%masked_periodic_boundaries
386 mesh_out%coord_system => mesh_in%coord_system
388 safe_allocate(mesh_out%spacing(1:space%dim))
389 mesh_out%spacing(:) =
m_half*mesh_in%spacing(:)
392 mesh_out%idx%enlarge(:) = mesh_in%idx%enlarge(:)
393 mesh_out%idx%nr(1,:) = (mesh_in%idx%nr(1,:)+mesh_in%idx%enlarge(:))*2
394 mesh_out%idx%nr(2,:) = (mesh_in%idx%nr(2,:)-mesh_in%idx%enlarge(:))*2
402 do idim = space%periodic_dim + 1, space%dim
403 mesh_out%idx%nr(1, idim) = mesh_out%idx%nr(1, idim) - 1
404 mesh_out%idx%nr(2, idim) = mesh_out%idx%nr(2, idim) + 1
406 mesh_out%idx%ll(:) = mesh_out%idx%nr(2, :) - mesh_out%idx%nr(1, :) + 1
408 mesh_out%idx%stride(1) = 1
409 do idim = 2, space%dim+1
410 mesh_out%idx%stride(idim) = mesh_out%idx%stride(idim-1) * &
411 (mesh_out%idx%ll(idim-1) + 2*mesh_out%idx%enlarge(idim-1))
428 safe_deallocate_a(mgrid%sp)
429 safe_deallocate_a(mgrid%ep)
430 safe_deallocate_a(mgrid%ep_part)
432 safe_deallocate_a(mgrid%level(0)%tt%fine_i)
434 do i = 1, mgrid%n_levels
435 level => mgrid%level(i)
439 safe_deallocate_p(level%mesh)
440 safe_deallocate_p(level%der)
442 safe_deallocate_a(level%tt%to_coarse)
443 safe_deallocate_a(level%tt%to_fine1)
444 safe_deallocate_a(level%tt%to_fine2)
445 safe_deallocate_a(level%tt%to_fine4)
446 safe_deallocate_a(level%tt%to_fine8)
447 safe_deallocate_a(level%tt%fine_i)
450 safe_deallocate_a(mgrid%level)
461 next_der => base_der%coarser
466 next_der => next_der%coarser
467 if (.not.
associated(next_der))
exit
474 integer,
intent(in) :: dim
475 real(real64),
intent(inout) :: weight(:)
476 integer,
intent(inout) :: shift(:,:)
478 integer :: nn, di, dj, dk, dd
482 assert(ubound(weight, dim=1) == 3**dim)
483 assert(ubound(shift, dim=1) == dim)
484 assert(ubound(shift, dim=2) == 3**dim)
509 dd = abs(di)+abs(dj)+abs(dk)
526#include "multigrid_inc.F90"
529#include "complex.F90"
530#include "multigrid_inc.F90"
This module implements batches of mesh functions.
This module implements common operations on batches of mesh functions.
Module implementing boundary conditions in Octopus.
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public derivatives_build(der, namespace, space, mesh, qvector, regenerate, verbose)
build the derivatives object:
subroutine, public derivatives_init(der, namespace, space, coord_system, order)
subroutine, public derivatives_end(der)
integer, parameter, public der_stargeneral
real(real64), parameter, public m_half
This module implements the index, used for the mesh points.
subroutine, public index_init(idx, dim)
This subroutine allocates memory and initializes some components.
This module is intended to contain "only mathematical" functions and procedures.
This module contains subroutines, related to the initialization of the mesh.
subroutine, public mesh_init_stage_3(mesh, namespace, space, stencil, mc, parent, regenerate)
When running parallel in domains, stencil and np_stencil are needed to compute the ghost points....
subroutine, public mesh_init_stage_2(mesh, namespace, space, box, stencil, regenerate)
This subroutine creates the global array of spatial indices and the inverse mapping.
This module defines the meshes, which are used in Octopus.
integer function, public mesh_local_index_from_coords(mesh, ix)
This function returns the local index of the point for a given vector of integer coordinates.
subroutine, public mesh_write_info(this, iunit, namespace)
subroutine, public mesh_local_index_to_coords(mesh, ip, ix)
Given a local point index, this function returns the set of integer coordinates of the point.
recursive subroutine, public mesh_end(this)
subroutine, public messages_warning(no_lines, all_nodes, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
This module handles the communicators for the various parallelization strategies.
subroutine, public multigrid_mesh_double(space, namespace, mesh_in, mesh_out, stencil)
subroutine, public dmultigrid_fine2coarse_batch(tt, fine_der, coarse_mesh, fineb, coarseb, method_p)
subroutine, public dmultigrid_coarse2fine(tt, coarse_der, fine_mesh, f_coarse, f_fine, set_bc)
integer function, public multigrid_number_of_levels(base_der)
subroutine, public multigrid_end(mgrid)
subroutine, public dmultigrid_fine2coarse(tt, fine_der, coarse_mesh, f_fine, f_coarse, method_p)
integer, parameter, public fullweight
subroutine, public zmultigrid_fine2coarse_batch(tt, fine_der, coarse_mesh, fineb, coarseb, method_p)
subroutine, public zmultigrid_coarse2fine(tt, coarse_der, fine_mesh, f_coarse, f_fine, set_bc)
subroutine, public multigrid_mesh_half(space, namespace, mesh_in, mesh_out, stencil)
Creates a mesh that has twice the spacing betwen the points than the in mesh. This is used in the mul...
subroutine, public multigrid_init(mgrid, namespace, space, mesh, der, stencil, mc, nlevels)
subroutine, public zmultigrid_fine2coarse(tt, fine_der, coarse_mesh, f_fine, f_coarse, method_p)
subroutine, public dmultigrid_coarse2fine_batch(tt, coarse_der, fine_mesh, coarseb, fineb)
subroutine multigrid_build_stencil(dim, weight, shift)
subroutine, public multigrid_get_transfer_tables(tt, space, fine, coarse)
creates the lookup tables to go between the coarse and fine meshes
subroutine, public zmultigrid_coarse2fine_batch(tt, coarse_der, fine_mesh, coarseb, fineb)
Some general things and nomenclature:
This module defines stencils used in Octopus.
class representing derivatives
Describes mesh distribution to nodes.
The class representing the stencil, which is used for non-local mesh operations.