MPI-AMRVAC 3.1
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_multigrid_coupling.t
Go to the documentation of this file.
1!> Module to couple the octree-mg library to AMRVAC. This file uses the VACPP
2!> preprocessor, but its use is kept to a minimum.
4 {^ifoned
6 }
7 {^iftwod
9 }
10 {^ifthreed
12 }
13
14
15 implicit none
16 public
17
18 !> Data structure containing the multigrid tree.
19 type(mg_t) :: mg
20
21 !> If defined, this routine is called after a new multigrid tree is
22 !> constructed.
23 procedure(after_new_tree), pointer :: mg_after_new_tree => null()
24
25 interface
26 subroutine after_new_tree()
27 end subroutine after_new_tree
28 end interface
29
30contains
31
32 !> Setup multigrid for usage
33 subroutine mg_setup_multigrid()
35 use mod_geometry
36
37 if (ndim /= mg_ndim) &
38 error stop "Multigrid module was compiled for different ndim"
39
40 select case (coordinate)
41 case (cartesian)
42 continue
43 case (cylindrical)
44 if (ndim == 3) error stop "Multigrid does not support cylindrical 3D"
45 mg%geometry_type = mg_cylindrical
46 case default
47 error stop "Multigrid does not support your geometry"
48 end select
49
50 if (any([ block_nx^d ] /= block_nx1)) &
51 error stop "Multigrid requires all block_nx to be equal"
52
53 call mg_comm_init(mg)
54 call mg_set_methods(mg)
56 end subroutine mg_setup_multigrid
57
58 !> Set multigrid boundary conditions for the solution according to variable iw
59 subroutine mg_copy_boundary_conditions(mg, iw)
61 type(mg_t), intent(inout) :: mg
62 integer, intent(in) :: iw
63 character(len=std_len) :: bnd_name(mg_num_neighbors)
64 integer :: n
65
66 do n = 1, mg_num_neighbors
67 select case (typeboundary(iw, n))
68 case (bc_symm)
69 mg%bc(n, mg_iphi)%bc_type = mg_bc_neumann
70 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
71 case (bc_asymm)
72 mg%bc(n, mg_iphi)%bc_type = mg_bc_dirichlet
73 mg%bc(n, mg_iphi)%bc_value = 0.0_dp
74 case (bc_cont)
75 mg%bc(n, mg_iphi)%bc_type = mg_bc_continuous
76 mg%bc(n, mg_iphi)%bc_value = 0.0_dp ! Not needed
77 case (bc_periodic)
78 ! Nothing to do here
79 case default
80 write(*,*) "mg_copy_boundary_conditions: unknown boundary type"
81 end select
82 end do
83 end subroutine mg_copy_boundary_conditions
84
85 !> If the grid has changed, rebuild the full multigrid tree
86 subroutine mg_update_refinement(n_coarsen, n_refine)
88 integer, intent(in) :: n_coarsen
89 integer, intent(in) :: n_refine
90
91 ! Don't build multigrid tree while doing initial refinement
92 if (.not. time_advance) return
93
94 if (.not. mg%is_allocated) then
96 else if (n_coarsen + n_refine > 0) then
99 end if
100 end subroutine mg_update_refinement
101
102 !> Copy a variable to the multigrid tree, including a layer of ghost cells
103 subroutine mg_copy_to_tree(iw_from, iw_to, restrict, restrict_gc, factor, state_from)
105 use mod_forest
106 integer, intent(in) :: iw_from !< Variable to use as right-hand side
107 integer, intent(in) :: iw_to !< Copy to this variable
108 logical, intent(in), optional :: restrict !< Restrict variable on multigrid tree
109 logical, intent(in), optional :: restrict_gc !< Fill ghost cells after restrict
110 real(dp), intent(in), optional :: factor !< out = factor * in
111 !> If present, use this as the input state
112 type(state), intent(in), optional, target :: state_from(max_blocks)
113 integer :: iigrid, igrid, id
114 integer :: nc, lvl, ilo^D, ihi^D
115 type(tree_node), pointer :: pnode
116 real(dp) :: fac
117 logical :: do_restrict, do_gc
118
119 if (.not. mg%is_allocated) &
120 error stop "mg_copy_to_tree: tree not allocated yet"
121
122 fac = 1.0_dp; if (present(factor)) fac = factor
123 do_restrict = .false.; if (present(restrict)) do_restrict = restrict
124 do_gc = .false.; if (present(restrict_gc)) do_gc = restrict_gc
125
126 ilo^d=ixmlo^d-1;
127 ihi^d=ixmhi^d+1;
128
129 do iigrid = 1, igridstail
130 igrid = igrids(iigrid);
131 pnode => igrid_to_node(igrid, mype)%node
132 id = pnode%id
133 lvl = mg%boxes(id)%lvl
134 nc = mg%box_size_lvl(lvl)
135
136 ! Include one layer of ghost cells on grid leaves
137 if (present(state_from)) then
138 mg%boxes(id)%cc({0:nc+1}, iw_to) = &
139 fac * state_from(igrid)%w({ilo^d:ihi^d}, iw_from)
140 else
141 mg%boxes(id)%cc({0:nc+1}, iw_to) = fac * ps(igrid)%w({ilo^d:ihi^d}, iw_from)
142 end if
143 end do
144
145 if (do_restrict) then
146 call mg_restrict(mg, iw_to)
147 if (do_gc) call mg_fill_ghost_cells(mg, iw_to)
148 end if
149
150 end subroutine mg_copy_to_tree
151
152 !> Copy a variable from the multigrid tree
153 subroutine mg_copy_from_tree(iw_from, iw_to, state_to)
155 use mod_forest
156 integer, intent(in) :: iw_from !< Variable to use as right-hand side
157 integer, intent(in) :: iw_to !< Copy to this variable
158 !> If present, use this as the output state
159 type(state), intent(inout), optional, target :: state_to(max_blocks)
160 integer :: iigrid, igrid, id
161 integer :: nc, lvl
162 type(tree_node), pointer :: pnode
163
164 if (.not. mg%is_allocated) &
165 error stop "mg_copy_from_tree: tree not allocated yet"
166
167 do iigrid = 1, igridstail
168 igrid = igrids(iigrid);
169 pnode => igrid_to_node(igrid, mype)%node
170 id = pnode%id
171 lvl = mg%boxes(id)%lvl
172 nc = mg%box_size_lvl(lvl)
173
174 if (present(state_to)) then
175 state_to(igrid)%w(ixm^t, iw_to) = mg%boxes(id)%cc({1:nc}, iw_from)
176 else
177 ps(igrid)%w(ixm^t, iw_to) = mg%boxes(id)%cc({1:nc}, iw_from)
178 end if
179 end do
180 end subroutine mg_copy_from_tree
181
182 !> Copy from multigrid tree with one layer of ghost cells. Corner ghost cells
183 !> are not used/set.
184 subroutine mg_copy_from_tree_gc(iw_from, iw_to, state_to)
186 use mod_forest
187 integer, intent(in) :: iw_from !< Variable to use as right-hand side
188 integer, intent(in) :: iw_to !< Copy to this variable
189 !> If present, use this as the output state
190 type(state), intent(inout), optional, target :: state_to(max_blocks)
191 integer :: iigrid, igrid, id
192 integer :: nc, lvl, ilo^D, ihi^D
193 type(tree_node), pointer :: pnode
194
195 if (.not. mg%is_allocated) &
196 error stop "mg_copy_from_tree_gc: tree not allocated yet"
197
198 ilo^d=ixmlo^d-1;
199 ihi^d=ixmhi^d+1;
200
201 do iigrid = 1, igridstail
202 igrid = igrids(iigrid);
203 pnode => igrid_to_node(igrid, mype)%node
204 id = pnode%id
205 lvl = mg%boxes(id)%lvl
206 nc = mg%box_size_lvl(lvl)
207
208 if (present(state_to)) then
209 state_to(igrid)%w({ilo^d:ihi^d}, iw_to) = mg%boxes(id)%cc({0:nc+1}, iw_from)
210 else
211 ps(igrid)%w({ilo^d:ihi^d}, iw_to) = mg%boxes(id)%cc({0:nc+1}, iw_from)
212 end if
213 end do
214 end subroutine mg_copy_from_tree_gc
215
216 !> Generate a multigrid tree that includes the amrvac tree, but also contains
217 !> coarser grid levels. A number of checks has already been performed in
218 !> mg_setup_multigrid, so we don't repeat these checks here.
219 subroutine mg_tree_from_amrvac(mg)
220 use mod_forest
222 type(mg_t), intent(inout) :: mg
223 integer :: i, n, id, ix(ndim)
224 integer :: n_boxes_total, i_c, c_id, c_ix(ndim)
225 integer :: min_lvl, lvl
226 integer :: nb, nb_ix, nb_dim
227 integer :: n_finer
228 type(tree_node), pointer :: pnode, pnode_ch
229 type(tree_node_ptr), allocatable :: id_to_node(:)
230 real(dp) :: dr_coarse
231
232 ! Estimate number of finer blocks
233 n_finer = nparents+nleafs
234
235 call mg_build_rectangle(mg, [ domain_nx^d ], block_nx1, dx(:,1), &
236 [ xprobmin^d ], periodb, n_finer)
237
238 mg%highest_lvl = levmax
239 n_boxes_total = mg%n_boxes + n_finer
240
241 ! To link the two trees
242 allocate(id_to_node(n_boxes_total))
243
244 ! Link base level
245 do i = 1, size(mg%lvls(1)%ids)
246 id = mg%lvls(1)%ids(i)
247 ix = mg%boxes(id)%ix
248
249 pnode => tree_root({ix(^d)})%node
250 pnode%id = id
251 id_to_node(id)%node => pnode
252 mg%boxes(id)%rank = pnode%ipe
253 end do
254
255 ! Add refinement
256 do lvl = 1, mg%highest_lvl
257 do i = 1, size(mg%lvls(lvl)%ids)
258 id = mg%lvls(lvl)%ids(i)
259 pnode => id_to_node(id)%node
260
261 if (.not. pnode%leaf) then
262 call mg_add_children(mg, id)
263
264 do i_c = 1, mg_num_children
265 c_id = mg%boxes(id)%children(i_c)
266 c_ix = mg_child_dix(:, i_c) + 1
267 pnode_ch => pnode%child({c_ix(^d)})%node
268 id_to_node(c_id)%node => pnode_ch
269 pnode_ch%id = c_id
270 mg%boxes(c_id)%rank = pnode_ch%ipe
271 end do
272 end if
273 end do
274
275 call mg_set_leaves_parents(mg%boxes, mg%lvls(lvl))
276
277 if (lvl < mg%highest_lvl) then
278 call mg_set_next_level_ids(mg, lvl)
279 call mg_set_neighbors_lvl(mg, lvl+1)
280 end if
281 end do
282
283 ! Store boxes with refinement boundaries (from the coarse side)
284 do lvl = 1, mg%highest_lvl
285 call mg_set_refinement_boundaries(mg%boxes, mg%lvls(lvl))
286 end do
287
288 ! Assign boxes to MPI processes
290
291 ! Allocate storage for boxes owned by this process
292 call mg_allocate_storage(mg)
293
294 if (associated(mg_after_new_tree)) then
295 call mg_after_new_tree()
296 end if
297
298 end subroutine mg_tree_from_amrvac
299
300end module mod_multigrid_coupling
301
integer, parameter, public mg_iphi
Index of solution.
integer, parameter, public mg_bc_neumann
Value to indicate a Neumann boundary condition.
integer, parameter, public mg_cylindrical
Cylindrical coordinate system.
integer, parameter, public mg_num_children
subroutine, public mg_set_methods(mg)
subroutine, public mg_fill_ghost_cells(mg, iv)
Fill ghost cells at all grid levels.
subroutine, public mg_build_rectangle(mg, domain_size, box_size, dx, r_min, periodic, n_finer)
subroutine, public mg_comm_init(mg, comm)
Prolong from a parent to a child with index offset dix. This method could sometimes work better than ...
subroutine, public mg_restrict(mg, iv)
Restrict all levels.
subroutine, public mg_add_children(mg, id)
subroutine, public mg_set_refinement_boundaries(boxes, level)
Create a list of refinement boundaries (from the coarse side)
subroutine, public mg_set_next_level_ids(mg, lvl)
subroutine, public mg_set_neighbors_lvl(mg, lvl)
integer, parameter, public mg_bc_dirichlet
Value to indicate a Dirichlet boundary condition.
subroutine, public mg_allocate_storage(mg)
Allocate communication buffers and local boxes for a tree that has already been created.
integer, parameter, public mg_ndim
Problem dimension.
subroutine, public mg_deallocate_storage(mg)
Deallocate all allocatable arrays.
subroutine, public mg_set_leaves_parents(boxes, level)
Create a list of leaves and a list of parents for a level.
subroutine, public mg_load_balance_parents(mg)
Load balance the parents (non-leafs). Assign them to the rank that has most children.
integer, dimension(1, 2), parameter, public mg_child_dix
integer, parameter, public mg_bc_continuous
Value to indicate a continuous boundary condition.
Module with basic grid data structures.
Definition mod_forest.t:2
integer, save nleafs
Number of leaf block.
Definition mod_forest.t:76
type(tree_node_ptr), dimension(:^d &), allocatable, save tree_root
Pointers to the coarse grid.
Definition mod_forest.t:29
integer, save nparents
Number of parent blocks.
Definition mod_forest.t:73
type(tree_node_ptr), dimension(:,:), allocatable, save igrid_to_node
Array to go from an [igrid, ipe] index to a node pointer.
Definition mod_forest.t:32
Module with geometry-related routines (e.g., divergence, curl)
Definition mod_geometry.t:2
integer coordinate
Definition mod_geometry.t:7
integer, parameter cartesian
Definition mod_geometry.t:8
integer, parameter cylindrical
This module contains definitions of global parameters and variables and some generic functions/subrou...
integer domain_nx
number of cells for each dimension in level-one mesh
integer, dimension(:, :), allocatable typeboundary
Array indicating the type of boundary condition per variable and per physical boundary.
integer, parameter ndim
Number of spatial dimensions for grid variables.
integer mype
The rank of the current MPI task.
integer block_nx
number of cells for each dimension in grid block excluding ghostcells
double precision, dimension(:), allocatable, parameter d
integer ixm
the mesh range of a physical block without ghost cells
integer, parameter bc_periodic
logical time_advance
do time evolving
logical, dimension(ndim) periodb
True for dimensions with periodic boundaries.
double precision, dimension(:,:), allocatable dx
Module to couple the octree-mg library to AMRVAC. This file uses the VACPP preprocessor,...
type(mg_t) mg
Data structure containing the multigrid tree.
subroutine mg_copy_boundary_conditions(mg, iw)
Set multigrid boundary conditions for the solution according to variable iw.
subroutine mg_update_refinement(n_coarsen, n_refine)
If the grid has changed, rebuild the full multigrid tree.
subroutine mg_copy_to_tree(iw_from, iw_to, restrict, restrict_gc, factor, state_from)
Copy a variable to the multigrid tree, including a layer of ghost cells.
procedure(after_new_tree), pointer mg_after_new_tree
If defined, this routine is called after a new multigrid tree is constructed.
subroutine mg_copy_from_tree_gc(iw_from, iw_to, state_to)
Copy from multigrid tree with one layer of ghost cells. Corner ghost cells are not used/set.
subroutine mg_tree_from_amrvac(mg)
Generate a multigrid tree that includes the amrvac tree, but also contains coarser grid levels....
subroutine mg_setup_multigrid()
Setup multigrid for usage.
subroutine mg_copy_from_tree(iw_from, iw_to, state_to)
Copy a variable from the multigrid tree.
Pointer to a tree_node.
Definition mod_forest.t:6
The data structure that contains information about a tree node/grid block.
Definition mod_forest.t:11