Afivo  0.3
m_a3_multigrid.f90
1 
4  use m_a3_types
5 
6  implicit none
7  private
8 
9  ! The mg module supports different multigrid operators, and uses these tags to
10  ! identify boxes / operators
11  integer, parameter, public :: mg_normal_box = 1
12  integer, parameter, public :: mg_lsf_box = 2
13  integer, parameter, public :: mg_ceps_box = 3
14  integer, parameter, public :: mg_veps_box = 4
15 
16  ! Labels for the different steps of a multigrid cycle
17  integer, parameter :: mg_cycle_down = 1
18  integer, parameter :: mg_cycle_base = 2
19  integer, parameter :: mg_cycle_up = 3
20 
22  type, public :: mg3_t
23  integer :: i_phi = -1
24  integer :: i_rhs = -1
25  integer :: i_tmp = -1
26 
27  integer :: i_eps = -1
28  integer :: i_lsf = -1
29  integer :: i_bval = -1
30 
31  integer :: n_cycle_down = -1
32  integer :: n_cycle_up = -1
33  integer :: n_cycle_base = -1
34 
35  logical :: initialized = .false.
36  logical :: use_corners = .false.
37  logical :: subtract_mean = .false.
38 
40  procedure(a3_subr_bc), pointer, nopass :: sides_bc => null()
41 
43  procedure(a3_subr_rb), pointer, nopass :: sides_rb => null()
44 
46  procedure(mg3_box_op), pointer, nopass :: box_op => null()
47 
49  procedure(mg3_box_gsrb), pointer, nopass :: box_gsrb => null()
50 
52  procedure(mg3_box_corr), pointer, nopass :: box_corr => null()
53 
55  procedure(mg3_box_rstr), pointer, nopass :: box_rstr => null()
56  end type mg3_t
57 
58  abstract interface
59 
60  subroutine mg3_box_op(box, i_out, mg)
61  import
62  type(box3_t), intent(inout) :: box
63  type(mg3_t), intent(in) :: mg
64  integer, intent(in) :: i_out
65  end subroutine mg3_box_op
66 
68  subroutine mg3_box_gsrb(box, redblack_cntr, mg)
69  import
70  type(box3_t), intent(inout) :: box
71  type(mg3_t), intent(in) :: mg
72  integer, intent(in) :: redblack_cntr
73  end subroutine mg3_box_gsrb
74 
75  subroutine mg3_box_corr(box_p, box_c, mg)
76  import
77  type(box3_t), intent(inout) :: box_c
78  type(box3_t), intent(in) :: box_p
79  type(mg3_t), intent(in) :: mg
80  end subroutine mg3_box_corr
81 
82  subroutine mg3_box_rstr(box_c, box_p, iv, mg)
83  import
84  type(box3_t), intent(in) :: box_c
85  type(box3_t), intent(inout) :: box_p
86  integer, intent(in) :: iv
87  type(mg3_t), intent(in) :: mg
88  end subroutine mg3_box_rstr
89  end interface
90 
91  public :: mg3_init_mg
92  public :: mg3_fas_fmg
93  public :: mg3_fas_vcycle
94  public :: mg3_box_op
95  public :: mg3_box_gsrb
96  public :: mg3_box_corr
97  public :: mg3_box_rstr
98 
99  ! Automatic selection of operators
100  public :: mg3_set_box_tag
101  public :: mg3_auto_op
102  public :: mg3_auto_gsrb
103  public :: mg3_auto_corr
104  public :: mg3_auto_rstr
105 
106  ! Methods for normal Laplacian
107  public :: mg3_box_lpl
108  public :: mg3_box_gsrb_lpl
109  public :: mg3_box_corr_lpl
110  public :: mg3_box_rstr_lpl
111  public :: mg3_sides_rb
112 
113  ! Methods for Laplacian with jump in coefficient between boxes
114  public :: mg3_box_lpld
115  public :: mg3_box_gsrb_lpld
116  public :: mg3_box_corr_lpld
117 
118  ! Methods for normal Laplacian with internal boundary conditions (LSF)
119  public :: mg3_box_lpllsf
120  public :: mg3_box_gsrb_lpllsf
121  public :: mg3_box_corr_lpllsf
122  public :: mg3_box_rstr_lpllsf
123 
124 contains
125 
127  subroutine mg3_init_mg(mg)
128  type(mg3_t), intent(inout) :: mg
129 
130  if (mg%i_phi < 0) stop "mg3_init_mg: i_phi not set"
131  if (mg%i_tmp < 0) stop "mg3_init_mg: i_tmp not set"
132  if (mg%i_rhs < 0) stop "mg3_init_mg: i_rhs not set"
133  if (mg%i_lsf * mg%i_bval < 0) &
134  stop "mg3_init_mg: you have to set both i_lsf and i_bval"
135 
136  if (.not. associated(mg%sides_bc)) stop "mg3_init_mg: sides_bc not set"
137 
138  ! Check whether these are set, otherwise use default
139  if (mg%n_cycle_down < 0) mg%n_cycle_down = 2
140  if (mg%n_cycle_up < 0) mg%n_cycle_up = 2
141  if (mg%n_cycle_base < 0) mg%n_cycle_base = 4
142 
143  ! Check whether methods are set, otherwise use default (for laplacian)
144  if (.not. associated(mg%sides_rb)) mg%sides_rb => mg3_sides_rb
145  if (.not. associated(mg%box_op)) mg%box_op => mg3_box_lpl
146  if (.not. associated(mg%box_gsrb)) mg%box_gsrb => mg3_box_gsrb_lpl
147  if (.not. associated(mg%box_corr)) mg%box_corr => mg3_box_corr_lpl
148  if (.not. associated(mg%box_rstr)) mg%box_rstr => mg3_box_rstr_lpl
149 
150  mg%initialized = .true.
151  end subroutine mg3_init_mg
152 
153  subroutine check_mg(mg)
154  type(mg3_t), intent(in) :: mg
155  if (.not. mg%initialized) stop "check_mg: you haven't called mg3_init_mg"
156  end subroutine check_mg
157 
161  subroutine mg3_fas_fmg(tree, mg, set_residual, have_guess)
162  use m_a3_ghostcell, only: a3_gc_ids
163  use m_a3_utils, only: a3_boxes_copy_cc
164  type(a3_t), intent(inout) :: tree
165  type(mg3_t), intent(in) :: mg
166  logical, intent(in) :: set_residual
167  logical, intent(in) :: have_guess
168  integer :: lvl, min_lvl
169 
170  call check_mg(mg) ! Check whether mg options are set
171 
172  min_lvl = lbound(tree%lvls, 1)
173 
174  if (have_guess) then
175  do lvl = tree%highest_lvl, min_lvl+1, -1
176  ! Set rhs on coarse grid and restrict phi
177  call set_coarse_phi_rhs(tree, lvl, mg)
178  end do
179  else
180  call init_phi_rhs(tree, mg)
181  end if
182 
183  do lvl = min_lvl, tree%highest_lvl
184  ! Store phi_old in tmp
185  call a3_boxes_copy_cc(tree%boxes, tree%lvls(lvl)%ids, &
186  mg%i_phi, mg%i_tmp)
187 
188  if (lvl > min_lvl) then
189  ! Correct solution at this lvl using lvl-1 data
190  ! phi = phi + prolong(phi_coarse - phi_old_coarse)
191  call correct_children(tree%boxes, tree%lvls(lvl-1)%parents, mg)
192 
193  ! Update ghost cells
194  call a3_gc_ids(tree, tree%lvls(lvl)%ids, mg%i_phi, &
195  mg%sides_rb, mg%sides_bc)
196  end if
197 
198  ! Perform V-cycle, only set residual on last iteration
199  call mg3_fas_vcycle(tree, mg, &
200  set_residual .and. lvl == tree%highest_lvl, lvl)
201  end do
202  end subroutine mg3_fas_fmg
203 
207  subroutine mg3_fas_vcycle(tree, mg, set_residual, highest_lvl)
208  use m_a3_ghostcell, only: a3_gc_ids
209  use m_a3_utils, only: a3_tree_sum_cc
210  type(a3_t), intent(inout) :: tree
211  type(mg3_t), intent(in) :: mg
212  logical, intent(in) :: set_residual
213  integer, intent(in), optional :: highest_lvl
214  integer :: lvl, min_lvl, i, id, max_lvl
215  real(dp) :: sum_phi, mean_phi
216 
217  call check_mg(mg) ! Check whether mg options are set
218  min_lvl = lbound(tree%lvls, 1)
219  max_lvl = tree%highest_lvl
220  if (present(highest_lvl)) max_lvl = highest_lvl
221 
222  do lvl = max_lvl, min_lvl+1, -1
223  ! Downwards relaxation
224  call gsrb_boxes(tree, tree%lvls(lvl)%ids, mg, mg_cycle_down)
225 
226  ! Set rhs on coarse grid, restrict phi, and copy i_phi to i_tmp for the
227  ! correction later
228  call update_coarse(tree, lvl, mg)
229  end do
230 
231  lvl = min_lvl
232  call gsrb_boxes(tree, tree%lvls(lvl)%ids, mg, mg_cycle_base)
233 
234  ! Do the upwards part of the v-cycle in the tree
235  do lvl = min_lvl+1, max_lvl
236  ! Correct solution at this lvl using lvl-1 data
237  ! phi = phi + prolong(phi_coarse - phi_old_coarse)
238  call correct_children(tree%boxes, tree%lvls(lvl-1)%parents, mg)
239 
240  ! Have to fill ghost cells after correction
241  call a3_gc_ids(tree, tree%lvls(lvl)%ids, mg%i_phi, &
242  mg%sides_rb, mg%sides_bc)
243 
244  ! Upwards relaxation
245  call gsrb_boxes(tree, tree%lvls(lvl)%ids, mg, mg_cycle_up)
246  end do
247 
248  if (set_residual) then
249  !$omp parallel private(lvl, i, id)
250  do lvl = min_lvl, max_lvl
251  !$omp do
252  do i = 1, size(tree%lvls(lvl)%ids)
253  id = tree%lvls(lvl)%ids(i)
254  call residual_box(tree%boxes(id), mg)
255  end do
256  !$omp end do nowait
257  end do
258  !$omp end parallel
259  end if
260 
261  ! Subtract the mean of phi, for example when doing a fully periodic
262  ! simulation. Note that the integrated r.h.s. term should also be zero then.
263  if (mg%subtract_mean) then
264  call a3_tree_sum_cc(tree, mg%i_phi, sum_phi)
265  mean_phi = sum_phi / a3_total_volume(tree)
266  !$omp parallel private(lvl, i, id)
267  do lvl = min_lvl, max_lvl
268  !$omp do
269  do i = 1, size(tree%lvls(lvl)%ids)
270  id = tree%lvls(lvl)%ids(i)
271  tree%boxes(id)%cc(:, :, :, mg%i_phi) = &
272  tree%boxes(id)%cc(:, :, :, mg%i_phi) - mean_phi
273  end do
274  !$omp end do nowait
275  end do
276  !$omp end parallel
277  end if
278 
279  end subroutine mg3_fas_vcycle
280 
282  subroutine mg3_sides_rb(boxes, id, nb, iv)
283  use m_a3_ghostcell, only: a3_gc_prolong_copy
284  type(box3_t), intent(inout) :: boxes(:)
285  integer, intent(in) :: id
286  integer, intent(in) :: nb
287  integer, intent(in) :: iv
288  integer :: nc, ix, dix, i, di, j, dj, co(3)
289  integer :: hnc, p_id, p_nb_id
290  real(dp) :: grad(3-1)
291  integer :: k, dk
292  real(dp) :: tmp(0:boxes(id)%n_cell/2+1, 0:boxes(id)%n_cell/2+1)
293  real(dp) :: gc(boxes(id)%n_cell, boxes(id)%n_cell)
294 
295  nc = boxes(id)%n_cell
296  hnc = nc/2
297 
298  p_id = boxes(id)%parent
299  p_nb_id = boxes(p_id)%neighbors(nb)
300  co = a3_get_child_offset(boxes(id))
301 
302  associate(box => boxes(p_nb_id))
303  ! First fill a temporary array with data next to the fine grid
304  select case (nb)
305  case (a3_neighb_lowx)
306  tmp = box%cc(nc, co(2):co(2)+hnc+1, co(3):co(3)+hnc+1, iv)
307  case (a3_neighb_highx)
308  tmp = box%cc(1, co(2):co(2)+hnc+1, co(3):co(3)+hnc+1, iv)
309  case (a3_neighb_lowy)
310  tmp = box%cc(co(1):co(1)+hnc+1, nc, co(3):co(3)+hnc+1, iv)
311  case (a3_neighb_highy)
312  tmp = box%cc(co(1):co(1)+hnc+1, 1, co(3):co(3)+hnc+1, iv)
313  case (a3_neighb_lowz)
314  tmp = box%cc(co(1):co(1)+hnc+1, co(2):co(2)+hnc+1, nc, iv)
315  case (a3_neighb_highz)
316  tmp = box%cc(co(1):co(1)+hnc+1, co(2):co(2)+hnc+1, 1, iv)
317  end select
318  end associate
319 
320  ! Now interpolate the coarse grid data to obtain values 'straight' next to
321  ! the fine grid points
322  do j = 1, hnc
323  do i = 1, hnc
324  grad(1) = 0.125_dp * (tmp(i+1, j) - tmp(i-1, j))
325  grad(2) = 0.125_dp * (tmp(i, j+1) - tmp(i, j-1))
326  gc(2*i-1, 2*j-1) = tmp(i, j) - grad(1) - grad(2)
327  gc(2*i, 2*j-1) = tmp(i, j) + grad(1) - grad(2)
328  gc(2*i-1, 2*j) = tmp(i, j) - grad(1) + grad(2)
329  gc(2*i, 2*j) = tmp(i, j) + grad(1) + grad(2)
330  end do
331  end do
332 
333  if (a3_neighb_low(nb)) then
334  ix = 1
335  dix = 1
336  else
337  ix = nc
338  dix = -1
339  end if
340 
341  select case (a3_neighb_dim(nb))
342  case (1)
343  i = ix
344  di = dix
345  do k = 1, nc
346  dk = -1 + 2 * iand(k, 1)
347  do j = 1, nc
348  dj = -1 + 2 * iand(j, 1)
349  boxes(id)%cc(i-di, j, k, iv) = &
350  0.5_dp * gc(j, k) + &
351  0.75_dp * boxes(id)%cc(i, j, k, iv) - &
352  0.25_dp * boxes(id)%cc(i+di, j, k, iv)
353  end do
354  end do
355  case (2)
356  j = ix
357  dj = dix
358  do k = 1, nc
359  dk = -1 + 2 * iand(k, 1)
360  do i = 1, nc
361  di = -1 + 2 * iand(i, 1)
362  boxes(id)%cc(i, j-dj, k, iv) = &
363  0.5_dp * gc(i, k) + &
364  0.75_dp * boxes(id)%cc(i, j, k, iv) - &
365  0.25_dp * boxes(id)%cc(i, j+dj, k, iv)
366  end do
367  end do
368  case (3)
369  k = ix
370  dk = dix
371  do j = 1, nc
372  dj = -1 + 2 * iand(j, 1)
373  do i = 1, nc
374  di = -1 + 2 * iand(i, 1)
375  boxes(id)%cc(i, j, k-dk, iv) = &
376  0.5_dp * gc(i, j) + &
377  0.75_dp * boxes(id)%cc(i, j, k, iv) - &
378  0.25_dp * boxes(id)%cc(i, j, k+dk, iv)
379  end do
380  end do
381  end select
382 
383  end subroutine mg3_sides_rb
384 
390  subroutine mg3_sides_rb_old(boxes, id, nb, iv)
391  use m_a3_ghostcell, only: a3_gc_prolong_copy
392  type(box3_t), intent(inout) :: boxes(:)
393  integer, intent(in) :: id
394  integer, intent(in) :: nb
395  integer, intent(in) :: iv
396  integer :: nc, ix, dix, i, di, j, dj
397  integer :: k, dk
398 
399  nc = boxes(id)%n_cell
400 
401  if (a3_neighb_low(nb)) then
402  ix = 1
403  dix = 1
404  else
405  ix = nc
406  dix = -1
407  end if
408 
409  call a3_gc_prolong_copy(boxes, id, nb, iv)
410 
411  select case (a3_neighb_dim(nb))
412  case (1)
413  i = ix
414  di = dix
415  do k = 1, nc
416  dk = -1 + 2 * iand(k, 1)
417  do j = 1, nc
418  dj = -1 + 2 * iand(j, 1)
419  ! Trilinear extrapolation (using 8 points)
420  ! boxes(id)%cc(i-di, j, k, iv) = &
421  ! 0.5_dp * boxes(id)%cc(i-di, j, k, iv) + 0.0625_dp * (&
422  ! 27 * boxes(id)%cc(i, j, k, iv) &
423  ! - 9 * boxes(id)%cc(i+di, j, k, iv) &
424  ! - 9 * boxes(id)%cc(i, j+dj, k, iv) &
425  ! - 9 * boxes(id)%cc(i, j, k+dk, iv) &
426  ! + 3 * boxes(id)%cc(i+di, j+dj, k, iv) &
427  ! + 3 * boxes(id)%cc(i+di, j, k+dk, iv) &
428  ! + 3 * boxes(id)%cc(i, j+dj, k+dk, iv) &
429  ! - 1 * boxes(id)%cc(i+di, j+dj, k+dk, iv))
430 
431  ! Extrapolation using 2 points
432  boxes(id)%cc(i-di, j, k, iv) = &
433  0.5_dp * boxes(id)%cc(i-di, j, k, iv) + &
434  0.75_dp * boxes(id)%cc(i, j, k, iv) - &
435  0.25_dp * boxes(id)%cc(i+di, j+dj, k+dk, iv)
436  end do
437  end do
438  case (2)
439  j = ix
440  dj = dix
441  do k = 1, nc
442  dk = -1 + 2 * iand(k, 1)
443  do i = 1, nc
444  di = -1 + 2 * iand(i, 1)
445 
446  ! boxes(id)%cc(i, j-dj, k, iv) = &
447  ! 0.5_dp * boxes(id)%cc(i, j-dj, k, iv) + 0.0625_dp * (&
448  ! 27 * boxes(id)%cc(i, j, k, iv) &
449  ! - 9 * boxes(id)%cc(i+di, j, k, iv) &
450  ! - 9 * boxes(id)%cc(i, j+dj, k, iv) &
451  ! - 9 * boxes(id)%cc(i, j, k+dk, iv) &
452  ! + 3 * boxes(id)%cc(i+di, j+dj, k, iv) &
453  ! + 3 * boxes(id)%cc(i+di, j, k+dk, iv) &
454  ! + 3 * boxes(id)%cc(i, j+dj, k+dk, iv) &
455  ! - 1 * boxes(id)%cc(i+di, j+dj, k+dk, iv))
456 
457  boxes(id)%cc(i, j-dj, k, iv) = &
458  0.5_dp * boxes(id)%cc(i, j-dj, k, iv) + &
459  0.75_dp * boxes(id)%cc(i, j, k, iv) - &
460  0.25_dp * boxes(id)%cc(i+di, j+dj, k+dk, iv)
461  end do
462  end do
463  case (3)
464  k = ix
465  dk = dix
466  do j = 1, nc
467  dj = -1 + 2 * iand(j, 1)
468  do i = 1, nc
469  di = -1 + 2 * iand(i, 1)
470 
471  ! boxes(id)%cc(i, j, k-dk, iv) = &
472  ! 0.5_dp * boxes(id)%cc(i, j, k-dk, iv) + 0.0625_dp * (&
473  ! 27 * boxes(id)%cc(i, j, k, iv) &
474  ! - 9 * boxes(id)%cc(i+di, j, k, iv) &
475  ! - 9 * boxes(id)%cc(i, j+dj, k, iv) &
476  ! - 9 * boxes(id)%cc(i, j, k+dk, iv) &
477  ! + 3 * boxes(id)%cc(i+di, j+dj, k, iv) &
478  ! + 3 * boxes(id)%cc(i+di, j, k+dk, iv) &
479  ! + 3 * boxes(id)%cc(i, j+dj, k+dk, iv) &
480  ! - 1 * boxes(id)%cc(i+di, j+dj, k+dk, iv))
481 
482  boxes(id)%cc(i, j, k-dk, iv) = &
483  0.5_dp * boxes(id)%cc(i, j, k-dk, iv) + &
484  0.75_dp * boxes(id)%cc(i, j, k, iv) - &
485  0.25_dp * boxes(id)%cc(i+di, j+dj, k+dk, iv)
486  end do
487  end do
488  end select
489 
490  end subroutine mg3_sides_rb_old
491 
492  ! Sets phi = phi + prolong(phi_coarse - phi_old_coarse)
493  subroutine correct_children(boxes, ids, mg)
494  type(box3_t), intent(inout) :: boxes(:)
495  integer, intent(in) :: ids(:)
496  type(mg3_t), intent(in) :: mg
497  integer :: i, id, nc, i_c, c_id
498 
499  !$omp parallel do private(id, nc, i_c, c_id)
500  do i = 1, size(ids)
501  id = ids(i)
502  nc = boxes(id)%n_cell
503 
504  ! Store the correction in i_tmp
505  boxes(id)%cc(:, :, :, mg%i_tmp) = boxes(id)%cc(:, :, :, mg%i_phi) - &
506  boxes(id)%cc(:, :, :, mg%i_tmp)
507 
508  do i_c = 1, a3_num_children
509  c_id = boxes(id)%children(i_c)
510  if (c_id == af_no_box) cycle
511  call mg%box_corr(boxes(id), boxes(c_id), mg)
512  end do
513  end do
514  !$omp end parallel do
515  end subroutine correct_children
516 
517  subroutine gsrb_boxes(tree, ids, mg, type_cycle)
518  use m_a3_ghostcell, only: a3_gc_box
519  type(a3_t), intent(inout) :: tree
520  type(mg3_t), intent(in) :: mg
521  integer, intent(in) :: ids(:)
522  integer, intent(in) :: type_cycle
523  integer :: n, i, n_cycle
524  logical :: use_corners
525 
526  select case (type_cycle)
527  case (mg_cycle_down)
528  n_cycle = mg%n_cycle_down
529  case (mg_cycle_up)
530  n_cycle = mg%n_cycle_up
531  case (mg_cycle_base)
532  n_cycle = mg%n_cycle_base
533  case default
534  error stop "gsrb_boxes: invalid cycle type"
535  end select
536 
537  !$omp parallel private(n, i)
538  do n = 1, 2 * n_cycle
539  !$omp do
540  do i = 1, size(ids)
541  call mg%box_gsrb(tree%boxes(ids(i)), n, mg)
542  end do
543  !$omp end do
544 
545  use_corners = mg%use_corners .or. &
546  (type_cycle /= mg_cycle_down .and. n == 2 * n_cycle)
547 
548  !$omp do
549  do i = 1, size(ids)
550  call a3_gc_box(tree, ids(i), mg%i_phi, mg%sides_rb, &
551  mg%sides_bc, use_corners)
552  end do
553  !$omp end do
554  end do
555  !$omp end parallel
556  end subroutine gsrb_boxes
557 
558  ! Set rhs on coarse grid, restrict phi, and copy i_phi to i_tmp for the
559  ! correction later
560  subroutine update_coarse(tree, lvl, mg)
561  use m_a3_utils, only: a3_n_cell, a3_box_add_cc, a3_box_copy_cc
562  use m_a3_ghostcell, only: a3_gc_ids
563  type(a3_t), intent(inout) :: tree
564  integer, intent(in) :: lvl
565  type(mg3_t), intent(in) :: mg
566  integer :: i, id, p_id, nc
567  real(dp), allocatable :: tmp(:,:,:)
568 
569  id = tree%lvls(lvl)%ids(1)
570  nc = a3_n_cell(tree, lvl)
571  allocate(tmp(1:nc, 1:nc, 1:nc))
572 
573  ! Restrict phi and the residual
574  !$omp parallel do private(id, p_id, tmp)
575  do i = 1, size(tree%lvls(lvl)%ids)
576  id = tree%lvls(lvl)%ids(i)
577  p_id = tree%boxes(id)%parent
578 
579  ! Copy the data currently in i_tmp, and restore it later (i_tmp holds the
580  ! previous state of i_phi)
581  tmp = tree%boxes(id)%cc(1:nc, 1:nc, 1:nc, mg%i_tmp)
582  call residual_box(tree%boxes(id), mg)
583  call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_tmp, mg)
584  call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_phi, mg)
585  tree%boxes(id)%cc(1:nc, 1:nc, 1:nc, mg%i_tmp) = tmp
586  end do
587  !$omp end parallel do
588 
589  call a3_gc_ids(tree, tree%lvls(lvl-1)%ids, mg%i_phi, &
590  mg%sides_rb, mg%sides_bc)
591 
592  ! Set rhs_c = laplacian(phi_c) + restrict(res) where it is refined, and
593  ! store current coarse phi in tmp.
594 
595  !$omp parallel do private(id)
596  do i = 1, size(tree%lvls(lvl-1)%parents)
597  id = tree%lvls(lvl-1)%parents(i)
598 
599  ! Set rhs = L phi
600  call mg%box_op(tree%boxes(id), mg%i_rhs, mg)
601 
602  ! Add tmp (the fine grid residual) to rhs
603  call a3_box_add_cc(tree%boxes(id), mg%i_tmp, mg%i_rhs)
604 
605  ! Story a copy of phi in tmp
606  call a3_box_copy_cc(tree%boxes(id), mg%i_phi, mg%i_tmp)
607  end do
608  !$omp end parallel do
609  end subroutine update_coarse
610 
613  subroutine set_coarse_phi_rhs(tree, lvl, mg)
614  use m_a3_ghostcell, only: a3_gc_ids
615  use m_a3_utils, only: a3_box_add_cc
616  type(a3_t), intent(inout) :: tree
617  integer, intent(in) :: lvl
618  type(mg3_t), intent(in) :: mg
619  integer :: i, id, p_id
620 
621  ! Fill ghost cells here to be sure
622  if (lvl == tree%highest_lvl) then
623  call a3_gc_ids(tree, tree%lvls(lvl)%ids, mg%i_phi, &
624  mg%sides_rb, mg%sides_bc)
625  end if
626 
627  !$omp parallel do private(id, p_id)
628  do i = 1, size(tree%lvls(lvl)%ids)
629  id = tree%lvls(lvl)%ids(i)
630  p_id = tree%boxes(id)%parent
631 
632  call residual_box(tree%boxes(id), mg)
633  call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_tmp, mg)
634  call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_phi, mg)
635  end do
636  !$omp end parallel do
637 
638  call a3_gc_ids(tree, tree%lvls(lvl-1)%ids, mg%i_phi, &
639  mg%sides_rb, mg%sides_bc)
640 
641  ! Set rhs_c = laplacian(phi_c) + restrict(res) where it is refined
642 
643  !$omp parallel do private(id)
644  do i = 1, size(tree%lvls(lvl-1)%parents)
645  id = tree%lvls(lvl-1)%parents(i)
646  call mg%box_op(tree%boxes(id), mg%i_rhs, mg)
647  call a3_box_add_cc(tree%boxes(id), mg%i_tmp, mg%i_rhs)
648  end do
649  !$omp end parallel do
650  end subroutine set_coarse_phi_rhs
651 
653  subroutine init_phi_rhs(tree, mg)
654  use m_a3_utils, only: a3_box_clear_cc
655  type(a3_t), intent(inout) :: tree
656  type(mg3_t), intent(in) :: mg
657  integer :: i, id, p_id, lvl, min_lvl
658 
659  ! Start from phi = 0 and restrict rhs
660  min_lvl = lbound(tree%lvls, 1)
661 
662  !$omp parallel private(lvl, i, id, p_id)
663  do lvl = tree%highest_lvl, min_lvl+1, -1
664  !$omp do
665  do i = 1, size(tree%lvls(lvl)%ids)
666  id = tree%lvls(lvl)%ids(i)
667  call a3_box_clear_cc(tree%boxes(id), mg%i_phi)
668  if (lvl > min_lvl) then
669  p_id = tree%boxes(id)%parent
670  call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_rhs, mg)
671  end if
672  end do
673  !$omp end do
674  end do
675  !$omp end parallel
676  end subroutine init_phi_rhs
677 
678  subroutine residual_box(box, mg)
679  type(box3_t), intent(inout) :: box
680  type(mg3_t), intent(in) :: mg
681  integer :: nc
682 
683  call mg%box_op(box, mg%i_tmp, mg)
684  nc = box%n_cell
685  box%cc(1:nc, 1:nc, 1:nc, mg%i_tmp) = box%cc(1:nc, 1:nc, 1:nc, mg%i_rhs) &
686  - box%cc(1:nc, 1:nc, 1:nc, mg%i_tmp)
687  end subroutine residual_box
688 
690  subroutine mg3_auto_gsrb(box, redblack_cntr, mg)
691  type(box3_t), intent(inout) :: box
692  integer, intent(in) :: redblack_cntr
693  type(mg3_t), intent(in) :: mg
694 
695  if (box%tag == af_init_tag) call mg3_set_box_tag(box, mg)
696 
697  select case(box%tag)
698  case (mg_normal_box)
699  call mg3_box_gsrb_lpl(box, redblack_cntr, mg)
700  case (mg_lsf_box)
701  call mg3_box_gsrb_lpllsf(box, redblack_cntr, mg)
702  case (mg_veps_box, mg_ceps_box)
703  call mg3_box_gsrb_lpld(box, redblack_cntr, mg)
704  end select
705  end subroutine mg3_auto_gsrb
706 
708  subroutine mg3_auto_op(box, i_out, mg)
709  type(box3_t), intent(inout) :: box
710  integer, intent(in) :: i_out
711  type(mg3_t), intent(in) :: mg
712 
713  if (box%tag == af_init_tag) call mg3_set_box_tag(box, mg)
714 
715  select case(box%tag)
716  case (mg_normal_box)
717  call mg3_box_lpl(box, i_out, mg)
718  case (mg_lsf_box)
719  call mg3_box_lpllsf(box, i_out, mg)
720  case (mg_veps_box, mg_ceps_box)
721  call mg3_box_lpld(box, i_out, mg)
722  end select
723  end subroutine mg3_auto_op
724 
726  subroutine mg3_auto_rstr(box_c, box_p, iv, mg)
727  type(box3_t), intent(in) :: box_c
728  type(box3_t), intent(inout) :: box_p
729  integer, intent(in) :: iv
730  type(mg3_t), intent(in) :: mg
731 
732  ! We can only restrict after gsrb, so tag should always be set
733  if (box_c%tag == af_init_tag) stop "mg3_auto_rstr: box_c tag not set"
734 
735  select case(box_c%tag)
736  case (mg_normal_box, mg_veps_box, mg_ceps_box)
737  call mg3_box_rstr_lpl(box_c, box_p, iv, mg)
738  case (mg_lsf_box)
739  call mg3_box_rstr_lpllsf(box_c, box_p, iv, mg)
740  end select
741  end subroutine mg3_auto_rstr
742 
744  subroutine mg3_auto_corr(box_p, box_c, mg)
745  type(box3_t), intent(inout) :: box_c
746  type(box3_t), intent(in) :: box_p
747  type(mg3_t), intent(in) :: mg
748 
749  if (box_c%tag == af_init_tag) call mg3_set_box_tag(box_c, mg)
750 
751  select case(box_c%tag)
752  case (mg_normal_box)
753  call mg3_box_corr_lpl(box_p, box_c, mg)
754  case (mg_lsf_box)
755  call mg3_box_corr_lpllsf(box_p, box_c, mg)
756  case (mg_veps_box, mg_ceps_box)
757  call mg3_box_corr_lpld(box_p, box_c, mg)
758  end select
759  end subroutine mg3_auto_corr
760 
761  subroutine mg3_set_box_tag(box, mg)
762  type(box3_t), intent(inout) :: box
763  type(mg3_t), intent(in) :: mg
764  real(dp) :: a, b
765  logical :: is_lsf, is_deps, is_eps
766 
767  is_lsf = .false.
768  is_eps = .false.
769  is_deps = .false.
770 
771  if (mg%i_lsf /= -1) then
772  is_lsf = minval(box%cc(:, :, :, mg%i_lsf)) * &
773  maxval(box%cc(:, :, :, mg%i_lsf)) < 0
774  end if
775 
776  if (mg%i_eps /= -1) then
777  a = minval(box%cc(:, :, :, mg%i_eps))
778  b = maxval(box%cc(:, :, :, mg%i_eps))
779  is_deps = (b > a)
780  if (.not. is_deps) is_eps = (a < 1 .or. a > 1)
781  end if
782 
783  if (count([is_lsf, is_eps, is_deps]) > 1) &
784  stop "mg3_set_box_tag: Cannot set lsf and eps tag for same box"
785 
786  box%tag = mg_normal_box
787  if (is_lsf) box%tag = mg_lsf_box
788  if (is_eps) box%tag = mg_ceps_box
789  if (is_deps) box%tag = mg_veps_box
790  end subroutine mg3_set_box_tag
791 
792  subroutine mg3_box_corr_lpl(box_p, box_c, mg)
794  type(box3_t), intent(inout) :: box_c
795  type(box3_t), intent(in) :: box_p
796  type(mg3_t), intent(in) :: mg
797 
798  call a3_prolong_linear(box_p, box_c, mg%i_tmp, mg%i_phi, add=.true.)
799  end subroutine mg3_box_corr_lpl
800 
802  subroutine mg3_box_gsrb_lpl(box, redblack_cntr, mg)
803  type(box3_t), intent(inout) :: box
804  integer, intent(in) :: redblack_cntr
805  type(mg3_t), intent(in) :: mg
806  integer :: i, i0, j, nc, i_phi, i_rhs
807  real(dp) :: dx2
808  integer :: k
809  real(dp), parameter :: sixth = 1/6.0_dp
810 
811  dx2 = box%dr**2
812  nc = box%n_cell
813  i_phi = mg%i_phi
814  i_rhs = mg%i_rhs
815 
816  ! The parity of redblack_cntr determines which cells we use. If
817  ! redblack_cntr is even, we use the even cells and vice versa.
818  do k = 1, nc
819  do j = 1, nc
820  i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
821  do i = i0, nc, 2
822  box%cc(i, j, k, i_phi) = sixth * ( &
823  box%cc(i+1, j, k, i_phi) + box%cc(i-1, j, k, i_phi) + &
824  box%cc(i, j+1, k, i_phi) + box%cc(i, j-1, k, i_phi) + &
825  box%cc(i, j, k+1, i_phi) + box%cc(i, j, k-1, i_phi) - &
826  dx2 * box%cc(i, j, k, i_rhs))
827  end do
828  end do
829  end do
830  end subroutine mg3_box_gsrb_lpl
831 
833  subroutine mg3_box_lpl(box, i_out, mg)
834  type(box3_t), intent(inout) :: box
835  integer, intent(in) :: i_out
836  type(mg3_t), intent(in) :: mg
837  integer :: i, j, nc, i_phi
838  real(dp) :: inv_dr_sq
839  integer :: k
840 
841  nc = box%n_cell
842  inv_dr_sq = 1 / box%dr**2
843  i_phi = mg%i_phi
844 
845  do k = 1, nc
846  do j = 1, nc
847  do i = 1, nc
848  box%cc(i, j, k, i_out) = inv_dr_sq * (box%cc(i-1, j, k, i_phi) + &
849  box%cc(i+1, j, k, i_phi) + box%cc(i, j-1, k, i_phi) + &
850  box%cc(i, j+1, k, i_phi) + box%cc(i, j, k-1, i_phi) + &
851  box%cc(i, j, k+1, i_phi) - 6 * box%cc(i, j, k, i_phi))
852  end do
853  end do
854  end do
855  end subroutine mg3_box_lpl
856 
858  subroutine mg3_box_rstr_lpl(box_c, box_p, iv, mg)
859  use m_a3_restrict, only: a3_restrict_box
860  type(box3_t), intent(in) :: box_c
861  type(box3_t), intent(inout) :: box_p
862  integer, intent(in) :: iv
863  type(mg3_t), intent(in) :: mg
864 
865  ! Don't use geometry for restriction, since this is inconsistent with the
866  ! filling of ghost cells near refinement boundaries
867  call a3_restrict_box(box_c, box_p, iv, use_geometry=.false.)
868  end subroutine mg3_box_rstr_lpl
869 
872  subroutine mg3_box_gsrb_lpld(box, redblack_cntr, mg)
873  type(box3_t), intent(inout) :: box
874  integer, intent(in) :: redblack_cntr
875  type(mg3_t), intent(in) :: mg
876  integer :: i, i0, j, nc, i_phi, i_eps, i_rhs
877  real(dp) :: dx2, u(2*3), a0, a(2*3), c(2*3)
878  integer :: k
879 
880  dx2 = box%dr**2
881  nc = box%n_cell
882  i_phi = mg%i_phi
883  i_eps = mg%i_eps
884  i_rhs = mg%i_rhs
885 
886  ! The parity of redblack_cntr determines which cells we use. If
887  ! redblack_cntr is even, we use the even cells and vice versa.
888  do k = 1, nc
889  do j = 1, nc
890  i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
891  do i = i0, nc, 2
892  a0 = box%cc(i, j, k, i_eps) ! value of eps at i,j
893  u(1:2) = box%cc(i-1:i+1:2, j, k, i_phi) ! values at neighbors
894  a(1:2) = box%cc(i-1:i+1:2, j, k, i_eps)
895  u(3:4) = box%cc(i, j-1:j+1:2, k, i_phi)
896  a(3:4) = box%cc(i, j-1:j+1:2, k, i_eps)
897  u(5:6) = box%cc(i, j, k-1:k+1:2, i_phi)
898  a(5:6) = box%cc(i, j, k-1:k+1:2, i_eps)
899  c(:) = 2 * a0 * a(:) / (a0 + a(:))
900 
901  box%cc(i, j, k, i_phi) = &
902  (sum(c(:) * u(:)) - dx2 * box%cc(i, j, k, i_rhs)) / sum(c(:))
903  end do
904  end do
905  end do
906  end subroutine mg3_box_gsrb_lpld
907 
909  subroutine mg3_box_lpld(box, i_out, mg)
910  type(box3_t), intent(inout) :: box
911  integer, intent(in) :: i_out
912  type(mg3_t), intent(in) :: mg
913  integer :: i, j, nc, i_phi, i_eps
914  real(dp) :: inv_dr_sq, a0, u0, u(2*3), a(2*3)
915  integer :: k
916 
917  nc = box%n_cell
918  inv_dr_sq = 1 / box%dr**2
919  i_phi = mg%i_phi
920  i_eps = mg%i_eps
921 
922  do k = 1, nc
923  do j = 1, nc
924  do i = 1, nc
925  u0 = box%cc(i, j, k, i_phi)
926  a0 = box%cc(i, j, k, i_eps)
927  u(1:2) = box%cc(i-1:i+1:2, j, k, i_phi)
928  u(3:4) = box%cc(i, j-1:j+1:2, k, i_phi)
929  u(5:6) = box%cc(i, j, k-1:k+1:2, i_phi)
930  a(1:2) = box%cc(i-1:i+1:2, j, k, i_eps)
931  a(3:4) = box%cc(i, j-1:j+1:2, k, i_eps)
932  a(5:6) = box%cc(i, j, k-1:k+1:2, i_eps)
933 
934  box%cc(i, j, k, i_out) = inv_dr_sq * 2 * &
935  sum(a0*a(:)/(a0 + a(:)) * (u(:) - u0))
936  end do
937  end do
938  end do
939 
940  end subroutine mg3_box_lpld
941 
944  subroutine mg3_box_corr_lpld(box_p, box_c, mg)
945  type(box3_t), intent(inout) :: box_c
946  type(box3_t), intent(in) :: box_p
947  type(mg3_t), intent(in) :: mg
948  integer :: ix_offset(3), i_phi, i_corr, i_eps
949  integer :: nc, i, j, i_c1, i_c2, j_c1, j_c2
950  real(dp) :: u0, u(3), a0, a(3)
951  integer :: k, k_c1, k_c2
952  real(dp), parameter :: third = 1/3.0_dp
953 
954  nc = box_c%n_cell
955  ix_offset = a3_get_child_offset(box_c)
956  i_phi = mg%i_phi
957  i_corr = mg%i_tmp
958  i_eps = mg%i_eps
959 
960  ! In these loops, we calculate the closest coarse index (_c1), and the
961  ! one-but-closest (_c2). The fine cell lies in between.
962  do k = 1, nc
963  k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
964  k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
965  do j = 1, nc
966  j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
967  j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
968  do i = 1, nc
969  i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
970  i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
971 
972  u0 = box_p%cc(i_c1, j_c1, k_c1, i_corr)
973  u(1) = box_p%cc(i_c2, j_c1, k_c1, i_corr)
974  u(2) = box_p%cc(i_c1, j_c2, k_c1, i_corr)
975  u(3) = box_p%cc(i_c1, j_c1, k_c2, i_corr)
976  a0 = box_p%cc(i_c1, j_c1, k_c1, i_eps)
977  a(1) = box_p%cc(i_c2, j_c1, k_c1, i_eps)
978  a(2) = box_p%cc(i_c1, j_c2, k_c1, i_eps)
979  a(3) = box_p%cc(i_c1, j_c1, k_c2, i_eps)
980 
981  ! Get value of phi at coarse cell faces, and average
982  box_c%cc(i, j, k, i_phi) = box_c%cc(i, j, k, i_phi) + third * &
983  sum((a0*u0 + a(:) * (1.5_dp * u(:) - 0.5_dp * u0)) / &
984  (a0 + a(:)))
985  end do
986  end do
987  end do
988  end subroutine mg3_box_corr_lpld
989 
990  ! Below: multigrid operators for internal boundary conditions. A level set
991  ! function defines the location of the interface(s).
992 
994  subroutine lsf_dist_val(lsf_val_bval_a, lsf_val_bval_b, dist, val)
995 
996  real(dp), intent(in) :: lsf_val_bval_a(3)
998  real(dp), intent(in) :: lsf_val_bval_b(3)
1000  real(dp), intent(out) :: dist
1002  real(dp), intent(out) :: val
1003  real(dp) :: lsf_a, lsf_b, bval_a, bval_b
1004 
1005  lsf_a = lsf_val_bval_a(1)
1006  lsf_b = lsf_val_bval_b(1)
1007 
1008  if (lsf_a * lsf_b < 0) then
1009  ! There is a boundary between the points
1010  dist = lsf_a / (lsf_a - lsf_b)
1011  bval_a = lsf_val_bval_a(3)
1012  bval_b = lsf_val_bval_b(3)
1013 
1014  ! Interpolate between boundary values
1015  val = bval_a * (1-dist) + bval_b * dist
1016  else
1017  ! Simply use the value at b
1018  dist = 1
1019  val = lsf_val_bval_b(2)
1020  end if
1021  end subroutine lsf_dist_val
1022 
1023  subroutine mg3_box_corr_lpllsf(box_p, box_c, mg)
1024  type(box3_t), intent(inout) :: box_c
1025  type(box3_t), intent(in) :: box_p
1026  type(mg3_t), intent(in) :: mg
1027  integer :: i_phi, i_corr, i_lsf, ix_offset(3)
1028  integer :: nc, i, j, i_c1, i_c2, j_c1, j_c2
1029  real(dp) :: v_a(3), v_b(3), val(3+1), dist(3+1), c(3+1)
1030  integer :: k, k_c1, k_c2
1031 
1032  nc = box_c%n_cell
1033  ix_offset = a3_get_child_offset(box_c)
1034  i_phi = mg%i_phi
1035  i_corr = mg%i_tmp
1036  i_lsf = mg%i_lsf
1037 
1038  ! In these loops, we calculate the closest coarse index (_c1), and the
1039  ! one-but-closest (_c2). The fine cell lies in between.
1040  do k = 1, nc
1041  k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
1042  k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
1043  do j = 1, nc
1044  j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
1045  j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
1046  do i = 1, nc
1047  i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
1048  i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
1049 
1050  v_a(1:2) = box_c%cc(i, j, k, [i_lsf, i_corr])
1051  v_a(3) = 0.0_dp ! Boundary value for correction is 0
1052  v_b(3) = 0.0_dp ! Idem
1053  v_b(1:2) = box_p%cc(i_c1, j_c1, k_c1, [i_lsf, i_corr])
1054  call lsf_dist_val(v_a, v_b, dist(1), val(1))
1055  v_b(1:2) = box_p%cc(i_c2, j_c1, k_c1, [i_lsf, i_corr])
1056  call lsf_dist_val(v_a, v_b, dist(2), val(2))
1057  v_b(1:2) = box_p%cc(i_c1, j_c2, k_c1, [i_lsf, i_corr])
1058  call lsf_dist_val(v_a, v_b, dist(3), val(3))
1059  v_b(1:2) = box_p%cc(i_c1, j_c1, k_c2, [i_lsf, i_corr])
1060  call lsf_dist_val(v_a, v_b, dist(4), val(4))
1061 
1062  ! This expresses general interpolation between 4 points (on the lines
1063  ! between the fine and the 4 coarse values).
1064  c(1) = dist(2) * dist(3) * dist(4)
1065  c(2) = dist(1) * dist(3) * dist(4)
1066  c(3) = dist(1) * dist(2) * dist(4)
1067  c(4) = dist(1) * dist(2) * dist(3)
1068  box_c%cc(i, j, k, i_phi) = box_c%cc(i, j, k, i_phi) + &
1069  sum(c * val)/sum(c)
1070  end do
1071  end do
1072  end do
1073  end subroutine mg3_box_corr_lpllsf
1074 
1076  subroutine mg3_box_gsrb_lpllsf(box, redblack_cntr, mg)
1077  type(box3_t), intent(inout) :: box
1078  integer, intent(in) :: redblack_cntr
1079  type(mg3_t), intent(in) :: mg
1080  integer :: i, i0, j, nc, i_phi, i_rhs, i_lsf, i_bval
1081  real(dp) :: dx2, dd(2*3), val(2*3), v_a(3), v_b(3)
1082  integer :: k
1083 
1084  dx2 = box%dr**2
1085  nc = box%n_cell
1086  i_phi = mg%i_phi
1087  i_rhs = mg%i_rhs
1088  i_lsf = mg%i_lsf
1089  i_bval = mg%i_bval
1090 
1091  ! The parity of redblack_cntr determines which cells we use. If
1092  ! redblack_cntr is even, we use the even cells and vice versa.
1093  do k = 1, nc
1094  do j = 1, nc
1095  i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
1096  do i = i0, nc, 2
1097  v_a = box%cc(i, j, k, [i_lsf, i_phi, i_bval])
1098  v_b = box%cc(i-1, j, k, [i_lsf, i_phi, i_bval])
1099  call lsf_dist_val(v_a, v_b, dd(1), val(1))
1100  v_b = box%cc(i+1, j, k, [i_lsf, i_phi, i_bval])
1101  call lsf_dist_val(v_a, v_b, dd(2), val(2))
1102  v_b = box%cc(i, j-1, k, [i_lsf, i_phi, i_bval])
1103  call lsf_dist_val(v_a, v_b, dd(3), val(3))
1104  v_b = box%cc(i, j+1, k, [i_lsf, i_phi, i_bval])
1105  call lsf_dist_val(v_a, v_b, dd(4), val(4))
1106  v_b = box%cc(i, j, k-1, [i_lsf, i_phi, i_bval])
1107  call lsf_dist_val(v_a, v_b, dd(5), val(5))
1108  v_b = box%cc(i, j, k+1, [i_lsf, i_phi, i_bval])
1109  call lsf_dist_val(v_a, v_b, dd(6), val(6))
1110 
1111  ! Solve for generalized Laplacian (see routine mg3_box_lpllsf)
1112  box%cc(i, j, k, i_phi) = 1 / (1/(dd(1)*dd(2)) + &
1113  1/(dd(3)*dd(4)) + 1/(dd(5)*dd(6))) * ( &
1114  (dd(2) * val(1) + dd(1) * val(2)) / &
1115  ((dd(1) + dd(2)) * dd(1) * dd(2)) + &
1116  (dd(4) * val(3) + dd(3) * val(4)) / &
1117  ((dd(3) + dd(4)) * dd(3) * dd(4)) + &
1118  (dd(6) * val(5) + dd(5) * val(6)) / &
1119  ((dd(5) + dd(6)) * dd(5) * dd(6)) - &
1120  0.5_dp * dx2 * box%cc(i, j, k, i_rhs))
1121 
1122  end do
1123  end do
1124  end do
1125  end subroutine mg3_box_gsrb_lpllsf
1126 
1128  subroutine mg3_box_lpllsf(box, i_out, mg)
1129  type(box3_t), intent(inout) :: box
1130  integer, intent(in) :: i_out
1131  type(mg3_t), intent(in) :: mg
1132  integer :: i, j, nc, i_phi, i_lsf, i_bval
1133  real(dp) :: inv_dr_sq, dd(2*3), val(2*3)
1134  real(dp) :: f0, v_a(3), v_b(3)
1135  integer :: k
1136 
1137  nc = box%n_cell
1138  inv_dr_sq = 1 / box%dr**2
1139  i_phi = mg%i_phi
1140  i_lsf = mg%i_lsf
1141  i_bval = mg%i_bval
1142 
1143  do k = 1, nc
1144  do j = 1, nc
1145  do i = 1, nc
1146  v_a = box%cc(i, j, k, [i_lsf, i_phi, i_bval])
1147  v_b = box%cc(i-1, j, k, [i_lsf, i_phi, i_bval])
1148  call lsf_dist_val(v_a, v_b, dd(1), val(1))
1149  v_b = box%cc(i+1, j, k, [i_lsf, i_phi, i_bval])
1150  call lsf_dist_val(v_a, v_b, dd(2), val(2))
1151  v_b = box%cc(i, j-1, k, [i_lsf, i_phi, i_bval])
1152  call lsf_dist_val(v_a, v_b, dd(3), val(3))
1153  v_b = box%cc(i, j+1, k, [i_lsf, i_phi, i_bval])
1154  call lsf_dist_val(v_a, v_b, dd(4), val(4))
1155  v_b = box%cc(i, j, k-1, [i_lsf, i_phi, i_bval])
1156  call lsf_dist_val(v_a, v_b, dd(5), val(5))
1157  v_b = box%cc(i, j, k+1, [i_lsf, i_phi, i_bval])
1158  call lsf_dist_val(v_a, v_b, dd(6), val(6))
1159 
1160  ! Generalized Laplacian for neighbors at distance dd * dx
1161  f0 = box%cc(i, j, k, i_phi)
1162  box%cc(i, j, k, i_out) = 2 * inv_dr_sq * ( &
1163  (dd(2) * val(1) + dd(1) * val(2) - (dd(1)+dd(2)) * f0) / &
1164  ((dd(1) + dd(2)) * dd(1) * dd(2)) + &
1165  (dd(4) * val(3) + dd(3) * val(4) - (dd(3)+dd(4)) * f0) / &
1166  ((dd(3) + dd(4)) * dd(3) * dd(4)) + &
1167  (dd(6) * val(5) + dd(5) * val(6) - (dd(5)+dd(6)) * f0) / &
1168  ((dd(5) + dd(6)) * dd(5) * dd(6)))
1169  end do
1170  end do
1171  end do
1172  end subroutine mg3_box_lpllsf
1173 
1175  subroutine mg3_box_rstr_lpllsf(box_c, box_p, iv, mg)
1176  type(box3_t), intent(in) :: box_c
1177  type(box3_t), intent(inout) :: box_p
1178  integer, intent(in) :: iv
1179  type(mg3_t), intent(in) :: mg
1180  integer :: i, j, i_f, j_f, i_c, j_c
1181  integer :: hnc, ix_offset(3), n_ch
1182  logical :: child_mask(2, 2, 2)
1183  integer :: k, k_f, k_c
1184 
1185  hnc = ishft(box_c%n_cell, -1) ! n_cell / 2
1186  ix_offset = a3_get_child_offset(box_c)
1187 
1188  do k = 1, hnc
1189  k_c = ix_offset(3) + k
1190  k_f = 2 * k - 1
1191  do j = 1, hnc
1192  j_c = ix_offset(2) + j
1193  j_f = 2 * j - 1
1194  do i = 1, hnc
1195  i_c = ix_offset(1) + i
1196  i_f = 2 * i - 1
1197 
1198  child_mask = (box_p%cc(i_c, j_c, k_c, mg%i_lsf) * &
1199  box_c%cc(i_f:i_f+1, j_f:j_f+1, k_f:k_f+1, mg%i_lsf) > 0)
1200  n_ch = count(child_mask)
1201 
1202  if (n_ch < a3_num_children .and. n_ch > 0) then
1203  box_p%cc(i_c, j_c, k_c, iv) = 1 / n_ch * &
1204  sum(box_c%cc(i_f:i_f+1, j_f:j_f+1, k_f:k_f+1, iv), &
1205  mask=child_mask)
1206  else ! Take average of children
1207  box_p%cc(i_c, j_c, k_c, iv) = 0.125_dp * &
1208  sum(box_c%cc(i_f:i_f+1, j_f:j_f+1, k_f:k_f+1, iv))
1209  end if
1210  end do
1211  end do
1212  end do
1213  end subroutine mg3_box_rstr_lpllsf
1214 
1215 end module m_a3_multigrid
This module contains all kinds of different &#39;helper&#39; routines for Afivo. If the number of routines fo...
Definition: m_a3_utils.f90:5
Subroutine that performs A * cc(..., i_in) = cc(..., i_out)
This module contains the geometric multigrid routines that come with Afivo.
This module contains routines for restriction: going from fine to coarse variables.
To fill ghost cells near physical boundaries.
Definition: m_a3_types.f90:216
The basic building block of afivo: a box with cell-centered and face centered data, and information about its position, neighbors, children etc.
Definition: m_a3_types.f90:109
Type which stores all the boxes and levels, as well as some information about the number of boxes...
Definition: m_a3_types.f90:131
Type to store multigrid options in.
To fill ghost cells near refinement boundaries.
Definition: m_a3_types.f90:207
This module contains the routines related to prolongation: going from coarse to fine variables...
Definition: m_a3_prolong.f90:4
This module contains routines related to the filling of ghost cells. Note that corner ghost cells are...
This module contains the basic types and constants that are used in the 3-dimensional version of Afiv...
Definition: m_a3_types.f90:5