Afivo  0.3
m_af_types.f90
1 #include "cpp_macros.h"
2 
4 module m_af_types
5  use iso_c_binding, only: c_ptr
6 
7  implicit none
8  public
9 
10  ! dp stands for double precision (8 byte reals)
11  integer, parameter :: dp = kind(0.0d0)
12 
14  integer, parameter :: af_max_lvl = 30
15 
17  integer, parameter :: af_min_lvl = 1
18 
20  integer, parameter :: af_max_num_vars = 1024
21 
23  integer, parameter :: af_rm_ref = -1
24 
26  integer, parameter :: af_keep_ref = 0
27 
29  integer, parameter :: af_do_ref = 1
30 
32  integer, parameter :: af_derefine = -2
33 
35  integer, parameter :: af_refine = 2
36 
38  integer, parameter :: af_no_box = 0
39 
41  integer, parameter :: af_phys_boundary = -1
42 
45  integer, parameter :: af_init_tag = -huge(1)
46 
48  integer, parameter :: af_xyz = 1
49 
51  integer, parameter :: af_cyl = 2
52 
54  character(len=*), parameter :: af_coord_names(2) = &
55  ["Cartesian ", "Cylindrical"]
56 
58  integer, parameter :: af_bc_dirichlet = -10
59 
61  integer, parameter :: af_bc_neumann = -11
62 
64  integer, parameter :: af_bc_continuous = -12
65 
69  integer, parameter :: af_bc_dirichlet_copy = -13
70 
72  integer, parameter :: af_nlen = 20
73 
76  type lvl_t
77  integer, allocatable :: ids(:)
78  integer, allocatable :: leaves(:)
79  integer, allocatable :: parents(:)
80  end type lvl_t
81 
83  type ref_lvl_t
84  integer, allocatable :: add(:)
85  end type ref_lvl_t
86 
89  integer :: n_add = 0
90  integer :: n_rm = 0
91  integer, allocatable :: rm(:)
92  type(ref_lvl_t), allocatable :: lvls(:)
93  end type ref_info_t
94 
95 #if NDIM == 1
96 
97  integer, parameter :: af_num_children = 2
98 
100  integer, parameter :: af_child_dix(1, 2) = reshape([0,1], [1,2])
102  integer, parameter :: af_child_adj_nb(1, 2) = reshape([1,2], [1,2])
104  logical, parameter :: af_child_low(1, 2) = reshape([.true., .false.], [1, 2])
106 
108  integer, parameter :: af_num_neighbors = 2
110  integer, parameter :: af_neighb_lowx = 1
112  integer, parameter :: af_neighb_highx = 2
113 
115  integer, parameter :: af_neighb_dix(1, 2) = reshape([-1,1], [1,2])
117  logical, parameter :: af_neighb_low(2) = [.true., .false.]
119  integer, parameter :: af_low_neighbs(1) = [1]
121  integer, parameter :: af_high_neighbs(1) = [2]
123  integer, parameter :: af_neighb_high_pm(2) = [-1, 1]
124 
126  integer, parameter :: af_neighb_rev(2) = [2, 1]
128  integer, parameter :: af_neighb_dim(2) = [1, 1]
129 #elif NDIM == 2
130 
131  integer, parameter :: af_num_children = 4
132 
134  integer, parameter :: af_child_dix(2, 4) = reshape([0,0,1,0,0,1,1,1], [2,4])
136  integer, parameter :: af_child_adj_nb(2, 4) = reshape([1,3,2,4,1,2,3,4], [2,4])
138  logical, parameter :: af_child_low(2, 4) = reshape([.true., .true., &
139  .false., .true., .true., .false., .false., .false.], [2, 4])
140 
142  integer, parameter :: af_num_neighbors = 4
144  integer, parameter :: af_neighb_lowx = 1
146  integer, parameter :: af_neighb_highx = 2
148  integer, parameter :: af_neighb_lowy = 3
150  integer, parameter :: af_neighb_highy = 4
151 
153  integer, parameter :: af_neighb_dix(2, 4) = reshape([-1,0,1,0,0,-1,0,1], [2,4])
155  logical, parameter :: af_neighb_low(4) = [.true., .false., .true., .false.]
157  integer, parameter :: af_low_neighbs(2) = [1, 3]
159  integer, parameter :: af_high_neighbs(2) = [2, 4]
161  integer, parameter :: af_neighb_high_pm(4) = [-1, 1, -1, 1]
162 
164  integer, parameter :: af_neighb_rev(4) = [2, 1, 4, 3]
166  integer, parameter :: af_neighb_dim(4) = [1, 1, 2, 2]
167 #elif NDIM == 3
168 
169  integer, parameter :: af_num_children = 8
170 
172  integer, parameter :: af_child_dix(3, 8) = reshape( &
173  [0,0,0, 1,0,0, 0,1,0, 1,1,0, &
174  0,0,1, 1,0,1, 0,1,1, 1,1,1], [3,8])
176  integer, parameter :: af_child_adj_nb(4, 6) = reshape( &
177  [1,3,5,7, 2,4,6,8, 1,2,5,6, 3,4,7,8, 1,2,3,4, 5,6,7,8], [4,6])
179  logical, parameter :: af_child_low(3, 8) = reshape([ &
180  .true., .true., .true., .false., .true., .true., &
181  .true., .false., .true., .false., .false., .true., &
182  .true., .true., .false., .false., .true., .false., &
183  .true., .false., .false., .false., .false., .false.], [3, 8])
184 
186  integer, parameter :: af_num_neighbors = 6
188  integer, parameter :: af_neighb_lowx = 1
190  integer, parameter :: af_neighb_highx = 2
192  integer, parameter :: af_neighb_lowy = 3
194  integer, parameter :: af_neighb_highy = 4
196  integer, parameter :: af_neighb_lowz = 5
198  integer, parameter :: af_neighb_highz = 6
200  integer, parameter :: af_neighb_dix(3, 6) = reshape( &
201  [-1,0,0, 1,0,0, 0,-1,0, 0,1,0, 0,0,-1, 0,0,1], [3,6])
203  logical, parameter :: af_neighb_low(6) = &
204  [.true., .false., .true., .false., .true., .false.]
206  integer, parameter :: af_low_neighbs(3) = [1, 3, 5]
208  integer, parameter :: af_high_neighbs(3) = [2, 4, 6]
210  integer, parameter :: af_neighb_high_pm(6) = [-1, 1, -1, 1, -1, 1]
212  integer, parameter :: af_neighb_rev(6) = [2, 1, 4, 3, 6, 5]
214  integer, parameter :: af_neighb_dim(6) = [1, 1, 2, 2, 3, 3]
215 
217  integer, parameter :: af_num_edges = 12
219  integer, parameter :: af_edge_dim(12) = &
220  [1,1,1,1, 2,2,2,2, 3,3,3,3]
222  integer, parameter :: af_edge_dir(3, 12) = reshape( &
223  [0,-1,-1, 0,1,-1, 0,-1,1, 0,1,1, &
224  -1,0,-1, 1,0,-1, -1,0,1, 1,0,1, &
225  -1,-1,0, 1,-1,0, -1,1,0, 1,1,0], [3, 12])
227  integer, parameter :: af_nb_adj_edge(2, 12) = reshape( &
228  [3,5, 4,5, 3,6, 4,6, &
229  1,5, 2,5, 1,6, 2,6, &
230  1,3, 2,3, 1,4, 2,4], [2,12])
232  integer, parameter :: af_edge_min_ix(3, 12) = reshape( &
233  [0,0,0, 0,1,0, 0,0,1, 0,1,1, &
234  0,0,0, 1,0,0, 0,0,1, 1,0,1, &
235  0,0,0, 1,0,0, 0,1,0, 1,1,0], [3,12])
236 #endif
237 
241  procedure(af_subr_prolong), pointer, nopass :: prolong => null()
243  procedure(af_subr_restrict), pointer, nopass :: restrict => null()
245  procedure(af_subr_bc), pointer, nopass :: bc => null()
247  procedure(af_subr_rb), pointer, nopass :: rb => null()
249  procedure(af_subr_bc_custom), pointer, nopass :: bc_custom => null()
251  procedure(af_subr_funcval), pointer, nopass :: funcval => null()
253  integer :: prolong_limiter = -1
254  end type af_cc_methods
255 
257  integer, parameter :: af_stencil_none = 0
258 
262  integer :: key = af_stencil_none
264  integer :: shape = af_stencil_none
266  integer :: stype = -1
268  logical :: cylindrical_gradient = .false.
270  real(dp), allocatable :: c(:)
272  real(dp), allocatable :: v(:, dtimes(:))
275  real(dp), allocatable :: f(dtimes(:))
277  real(dp), allocatable :: bc_correction(dtimes(:))
279  integer, allocatable :: sparse_ix(:, :)
281  real(dp), allocatable :: sparse_v(:, :)
282  end type stencil_t
283 
286  type box_t
287  integer :: lvl
288  logical :: in_use=.false.
289  integer :: tag=af_init_tag
290  integer :: ix(ndim)
291  integer :: parent
293  integer :: children(af_num_children)
295  integer :: neighbors(af_num_neighbors)
297  integer :: neighbor_mat(dtimes(-1:1))
298  integer :: n_cell
299  real(dp) :: dr(ndim)
300  real(dp) :: r_min(ndim)
301  integer :: coord_t
302  real(dp), allocatable :: cc(dtimes(:), :)
303  real(dp), allocatable :: fc(dtimes(:), :, :)
304 
306  integer :: n_bc = 0
308  integer, allocatable :: bc_index_to_nb(:)
310  integer :: nb_to_bc_index(af_num_neighbors)
312  integer, allocatable :: bc_type(:, :)
314  real(dp), allocatable :: bc_val(:, :, :)
316  real(dp), allocatable :: bc_coords(:, :, :)
317 
319  integer :: n_stencils = 0
321  type(stencil_t), allocatable :: stencils(:)
322  end type box_t
323 
326  type af_t
327  logical :: ready = .false.
328  integer :: box_limit
329  integer :: highest_lvl = 0
330  integer :: highest_id = 0
331  integer :: n_cell
332  integer :: n_var_cell = 0
333  integer :: n_var_face = 0
334  integer :: coord_t
335  integer :: coarse_grid_size(ndim) = -1
336  logical :: periodic(ndim) = .false.
337  real(dp) :: r_base(ndim)
338  real(dp) :: dr_base(ndim)
339 
341  character(len=af_nlen) :: cc_names(af_max_num_vars)
342 
344  character(len=af_nlen) :: fc_names(af_max_num_vars)
345 
347  integer :: cc_num_copies(af_max_num_vars) = 1
348 
350  logical :: cc_write_output(af_max_num_vars) = .true.
351 
353  logical :: cc_write_binary(af_max_num_vars) = .true.
354 
356  logical :: fc_write_binary(af_max_num_vars) = .true.
357 
359  type(af_cc_methods) :: cc_methods(af_max_num_vars)
360 
362  integer :: n_stencil_keys_stored = 0
363 
365  logical :: has_cc_method(af_max_num_vars) = .false.
366 
368  integer, allocatable :: cc_auto_vars(:)
369 
371  integer, allocatable :: cc_func_vars(:)
372 
374  type(lvl_t) :: lvls(af_min_lvl:af_max_lvl)
375 
377  type(box_t), allocatable :: boxes(:)
378 
380  integer, allocatable :: removed_ids(:)
381 
383  integer :: n_removed_ids = 0
384 
386  integer :: mg_i_eps = -1
387 
389  integer :: mg_i_lsf = -1
390 
392  integer :: mg_current_operator_mask = -1
393  end type af_t
394 
396  type af_loc_t
397  integer :: id = -1
398  integer :: ix(ndim) = -1
399  end type af_loc_t
400 
401  abstract interface
402 
403  subroutine af_subr_ref(box, cell_flags)
404  import
405  type(box_t), intent(in) :: box
407  integer, intent(out) :: cell_flags(DTIMES(box%n_cell))
408  end subroutine af_subr_ref
409 
411  subroutine af_subr(box)
412  import
413  type(box_t), intent(inout) :: box
414  end subroutine af_subr
415 
417  subroutine af_subr_arg(box, rarg)
418  import
419  type(box_t), intent(inout) :: box
420  real(dp), intent(in) :: rarg(:)
421  end subroutine af_subr_arg
422 
424  subroutine af_subr_boxes(boxes, id)
425  import
426  type(box_t), intent(inout) :: boxes(:)
427  integer, intent(in) :: id
428  end subroutine af_subr_boxes
429 
431  subroutine af_subr_boxes_arg(boxes, id, rarg)
432  import
433  type(box_t), intent(inout) :: boxes(:)
434  integer, intent(in) :: id
435  real(dp), intent(in) :: rarg(:)
436  end subroutine af_subr_boxes_arg
437 
439  subroutine af_subr_tree(tree, id)
440  import
441  type(af_t), intent(inout) :: tree
442  integer, intent(in) :: id
443  end subroutine af_subr_tree
444 
446  subroutine af_subr_tree_arg(tree, id, rarg)
447  import
448  type(af_t), intent(inout) :: tree
449  integer, intent(in) :: id
450  real(dp), intent(in) :: rarg(:)
451  end subroutine af_subr_tree_arg
452 
454  subroutine af_subr_rb(boxes, id, nb, iv, op_mask)
455  import
456  type(box_t), intent(inout) :: boxes(:)
457  integer, intent(in) :: id
458  integer, intent(in) :: nb
459  integer, intent(in) :: iv
460  integer, intent(in) :: op_mask
461  end subroutine af_subr_rb
462 
464  subroutine af_subr_bc(box, nb, iv, coords, bc_val, bc_type)
465  import
466  type(box_t), intent(in) :: box
467  integer, intent(in) :: nb
468  integer, intent(in) :: iv
469  real(dp), intent(in) :: coords(NDIM, box%n_cell**(NDIM-1))
470  real(dp), intent(out) :: bc_val(box%n_cell**(NDIM-1))
471  integer, intent(out) :: bc_type
472  end subroutine af_subr_bc
473 
477  subroutine af_subr_bc_custom(box, nb, iv, n_gc, cc)
478  import
479  type(box_t), intent(inout) :: box
480  integer, intent(in) :: nb
481  integer, intent(in) :: iv
482  integer, intent(in) :: n_gc
484  real(dp), intent(inout), optional :: &
485  cc(DTIMES(1-n_gc:box%n_cell+n_gc))
486  end subroutine af_subr_bc_custom
487 
491  subroutine af_subr_funcval(box, iv)
492  import
493  type(box_t), intent(inout) :: box
494  integer, intent(in) :: iv
495  end subroutine af_subr_funcval
496 
498  subroutine af_subr_prolong(box_p, box_c, iv, iv_to, add, limiter)
499  import
500  type(box_t), intent(in) :: box_p
501  type(box_t), intent(inout) :: box_c
502  integer, intent(in) :: iv
503  integer, intent(in), optional :: iv_to
504  logical, intent(in), optional :: add
505  integer, intent(in), optional :: limiter
506  end subroutine af_subr_prolong
507 
509  subroutine af_subr_restrict(box_c, box_p, ivs, use_geometry)
510  import
511  type(box_t), intent(in) :: box_c
512  type(box_t), intent(inout) :: box_p
513  integer, intent(in) :: ivs(:)
515  logical, intent(in), optional :: use_geometry
516  end subroutine af_subr_restrict
517  end interface
518 
519  ! *** Types related to multigrid ***
520 
521  ! The mg module supports different multigrid operators, and uses these tags to
522  ! identify boxes / operators
523  integer, parameter :: mg_normal_operator = 1
524  integer, parameter :: mg_lsf_operator = 2
525  integer, parameter :: mg_eps_operator = 3
526  integer, parameter :: mg_auto_operator = 4
527 
528  integer, parameter :: mg_normal_box = 0
529  integer, parameter :: mg_lsf_box = 1
530  integer, parameter :: mg_veps_box = 2
531  integer, parameter :: mg_ceps_box = 4
532 
533  integer, parameter :: mg_prolong_linear = 17
534  integer, parameter :: mg_prolong_sparse = 18
535  integer, parameter :: mg_prolong_auto = 19
536 
538  integer, parameter :: mg_lsf_distance_key = 31
540  integer, parameter :: mg_lsf_mask_key = 32
541 
542  ! Labels for the different steps of a multigrid cycle
543  integer, parameter :: mg_cycle_down = 1
544  integer, parameter :: mg_cycle_up = 3
545 
548  type(c_ptr) :: matrix
549  type(c_ptr) :: rhs
550  type(c_ptr) :: phi
551  type(c_ptr) :: solver
552  type(c_ptr) :: grid
553 
555  real(dp), allocatable :: bc_to_rhs(:, :, :)
556 
558  real(dp), allocatable :: lsf_fac(dtimes(:), :)
559 
560  integer :: symmetric = 1
561  integer :: solver_type = -1
562  integer :: max_iterations = 50
563  integer :: n_cycle_down = 1
564  integer :: n_cycle_up = 1
565  real(dp) :: tolerance = 1e-6_dp
566 
568  integer :: min_unknowns_for_openmp = 10*1000
569  end type coarse_solve_t
570 
572  type :: mg_t
574  integer :: i_phi = -1
576  integer :: i_rhs = -1
578  integer :: i_tmp = -1
579 
581  integer :: operator_mask = -1
583  integer :: i_eps = -1
585  integer :: i_lsf = -1
586 
588  integer :: n_cycle_down = 2
590  integer :: n_cycle_up = 2
591 
593  logical :: initialized = .false.
595  logical :: use_corners = .false.
597  logical :: subtract_mean = .false.
598 
600  real(dp) :: helmholtz_lambda = 0.0_dp
601 
604  real(dp) :: lsf_boundary_value = 0.0_dp
605 
607  real(dp) :: lsf_gradient_safety_factor = 1.5_dp
608 
610  real(dp) :: lsf_length_scale = 1e100_dp
611 
613  real(dp) :: lsf_tol = 1e-8_dp
614 
616  real(dp) :: lsf_min_rel_distance = 1e-4_dp
617 
619  logical :: lsf_use_custom_prolongation = .false.
620 
622  procedure(mg_func_lsf), pointer, nopass :: lsf => null()
623 
625  procedure(mg_lsf_distf), pointer, nopass :: lsf_dist => null()
626 
628  procedure(mg_func_lsf), pointer, nopass :: lsf_boundary_function => null()
629 
631  procedure(af_subr_bc), pointer, nopass :: sides_bc => null()
632 
634  procedure(af_subr_rb), pointer, nopass :: sides_rb => null()
635 
637  procedure(mg_box_op), pointer, nopass :: box_op => null()
638 
640  integer :: operator_type = mg_auto_operator
641 
643  integer :: operator_key = af_stencil_none
644 
646  integer :: prolongation_type = mg_prolong_auto
647 
649  integer :: prolongation_key = af_stencil_none
650 
652  procedure(mg_box_gsrb), pointer, nopass :: box_gsrb => null()
653 
655  procedure(mg_box_corr), pointer, nopass :: box_corr => null()
656 
658  procedure(mg_box_rstr), pointer, nopass :: box_rstr => null()
659 
661  procedure(mg_box_stencil), pointer, nopass :: box_stencil => null()
662 
664  type(coarse_solve_t) :: csolver
665  end type mg_t
666 
667  abstract interface
668 
669  subroutine mg_box_op(box, i_out, mg)
670  import
671  type(box_t), intent(inout) :: box
672  type(mg_t), intent(in) :: mg
673  integer, intent(in) :: i_out
674  end subroutine mg_box_op
675 
677  subroutine mg_box_gsrb(box, redblack_cntr, mg)
678  import
679  type(box_t), intent(inout) :: box
680  type(mg_t), intent(in) :: mg
681  integer, intent(in) :: redblack_cntr
682  end subroutine mg_box_gsrb
683 
684  subroutine mg_box_corr(box_p, box_c, mg)
685  import
686  type(box_t), intent(inout) :: box_c
687  type(box_t), intent(in) :: box_p
688  type(mg_t), intent(in) :: mg
689  end subroutine mg_box_corr
690 
691  subroutine mg_box_rstr(box_c, box_p, iv, mg)
692  import
693  type(box_t), intent(in) :: box_c
694  type(box_t), intent(inout) :: box_p
695  integer, intent(in) :: iv
696  type(mg_t), intent(in) :: mg
697  end subroutine mg_box_rstr
698 
699  subroutine mg_box_stencil(box, mg, stencil, bc_to_rhs, lsf_fac)
700  import
701  type(box_t), intent(in) :: box
702  type(mg_t), intent(in) :: mg
703  real(dp), intent(inout) :: stencil(2*NDIM+1, DTIMES(box%n_cell))
704  real(dp), intent(inout) :: bc_to_rhs(box%n_cell**(NDIM-1), af_num_neighbors)
705  real(dp), intent(inout) :: lsf_fac(DTIMES(box%n_cell))
706  end subroutine mg_box_stencil
707 
709  real(dp) function mg_func_lsf(rr)
710  import
711  real(dp), intent(in) :: rr(ndim)
712  end function mg_func_lsf
713 
716  real(dp) function mg_lsf_distf(a, b, mg)
717  import
718  real(dp), intent(in) :: a(ndim)
719  real(dp), intent(in) :: b(ndim)
720  type(mg_t), intent(in) :: mg
721  end function mg_lsf_distf
722  end interface
723 
724 contains
725 
727  integer function af_get_max_threads()
728  use omp_lib, only: omp_get_max_threads
729  af_get_max_threads = omp_get_max_threads()
730  end function af_get_max_threads
731 
733  subroutine af_print_info(tree)
734  type(af_t), intent(in) :: tree
735  character(len=15) :: fmt_string
736 
737  if (.not. allocated(tree%boxes)) then
738  print *, "af_init has not been called for this tree"
739  else if (.not. tree%ready) then
740  print *, "af_set_base has not been called for this tree"
741  else
742  write(*, "(A)") ""
743  write(*, "(A)") " *** af_print_info(tree) ***"
744  write(*, "(A,I10)") " Current maximum level: ", tree%highest_lvl
745  write(*, "(A,I10)") " Number of boxes used: ", af_num_boxes_used(tree)
746  write(*, "(A,I10)") " Number of leaves used: ", af_num_leaves_used(tree)
747  write(*, "(A,I10)") " Memory limit(boxes): ", tree%box_limit
748  write(*, "(A,E10.2)") " Memory limit(GByte): ", &
749  tree%box_limit * 0.5_dp**30 * &
750  af_box_bytes(tree%n_cell, tree%n_var_cell, tree%n_var_face)
751  write(*, "(A,I10)") " Highest id in box list: ", tree%highest_id
752  write(*, "(A,I10)") " Size of box list: ", size(tree%boxes)
753  write(*, "(A,I10)") " Box size (cells): ", tree%n_cell
754  write(*, "(A,I10)") " Number of cc variables: ", tree%n_var_cell
755  write(*, "(A,I10)") " Number of fc variables: ", tree%n_var_face
756  write(*, "(A,A15)") " Type of coordinates: ", &
757  af_coord_names(tree%coord_t)
758  write(fmt_string, "(A,I0,A)") "(A,", ndim, "E10.2)"
759  write(*, fmt_string) " min. coords: ", tree%r_base
760  write(*, fmt_string) " dr at level one: ", tree%dr_base
761  write(*, "(A,E10.2)") " minval(dr): ", af_min_dr(tree)
762  write(*, "(A)") ""
763  end if
764  end subroutine af_print_info
765 
766  pure function af_box_bytes(n_cell, n_var_cell, n_var_face) result(box_bytes)
767  integer, intent(in) :: n_cell
768  integer, intent(in) :: n_var_cell
769  integer, intent(in) :: n_var_face
770  integer :: box_bytes
771  type(box_t) :: dummy_box
772 
773  box_bytes = 8 * n_var_cell * (n_cell + 2)**ndim + &
774  8 * n_var_face * (n_cell + 1) * n_cell**(ndim-1) + &
775  int(storage_size(dummy_box) / 8)
776  end function af_box_bytes
777 
778  pure function af_num_boxes_used(tree) result(n_boxes)
779  type(af_t), intent(in) :: tree
780  integer :: n_boxes, lvl
781 
782  n_boxes = 0
783  do lvl = 1, tree%highest_lvl
784  n_boxes = n_boxes + size(tree%lvls(lvl)%ids)
785  end do
786  end function af_num_boxes_used
787 
788  pure function af_num_leaves_used(tree) result(n_boxes)
789  type(af_t), intent(in) :: tree
790  integer :: n_boxes, lvl
791 
792  n_boxes = 0
793  do lvl = 1, tree%highest_lvl
794  n_boxes = n_boxes + size(tree%lvls(lvl)%leaves)
795  end do
796  end function af_num_leaves_used
797 
798  pure function af_num_cells_used(tree) result(n_cells)
799  type(af_t), intent(in) :: tree
800  integer :: n_cells
801 
802  n_cells = af_num_leaves_used(tree) * tree%n_cell**ndim
803  end function af_num_cells_used
804 
805  pure function af_total_volume(tree) result(vol)
806  type(af_t), intent(in) :: tree
807  real(dp) :: vol
808  integer :: i, id
809  real(dp) :: r0, r1, box_len(ndim)
810  real(dp), parameter :: pi = acos(-1.0_dp)
811 
812  box_len = tree%n_cell * tree%dr_base
813 
814  if (ndim == 2 .and. tree%coord_t == af_cyl) then
815  vol = 0.0_dp
816  do i = 1, size(tree%lvls(1)%ids)
817  id = tree%lvls(1)%ids(i)
818  r0 = tree%boxes(id)%r_min(1)
819  r1 = r0 + box_len(1)
820  vol = vol + pi * (r1**2 - r0**2) * box_len(ndim)
821  end do
822  else
823  vol = size(tree%lvls(1)%ids) * product(box_len)
824  end if
825  end function af_total_volume
826 
828  elemental logical function af_has_children(box)
829  type(box_t), intent(in) :: box
830 
831  ! Boxes are either fully refined or not, so we only need to check one of the
832  ! children
833  af_has_children = (box%children(1) /= af_no_box)
834  end function af_has_children
835 
840  pure function af_is_phys_boundary(boxes, id, nbs) result(boundary)
841  type(box_t), intent(in) :: boxes(:)
842  integer, intent(in) :: id
843  integer, intent(in) :: nbs(:)
844  logical :: boundary(size(nbs))
845  integer :: n, nb, p_id, nb_id, dim, dix
846 
847  do n = 1, size(nbs)
848  nb = nbs(n)
849  nb_id = boxes(id)%neighbors(nb)
850 
851  if (nb_id < af_no_box) then
852  boundary(n) = .true. ! Physical boundary
853  else ! There could be a periodic boundary
854  dim = af_neighb_dim(nb)
855 
856  if (nb_id == af_no_box) then
857  ! Refinement boundary, compute index difference on parent (which is
858  ! guaranteed to be there)
859  p_id = boxes(id)%parent
860  nb_id = boxes(p_id)%neighbors(nb)
861  dix = boxes(nb_id)%ix(dim) - boxes(p_id)%ix(dim)
862  else
863  ! Normal neighbor, compute index difference
864  dix = boxes(nb_id)%ix(dim) - boxes(id)%ix(dim)
865  end if
866 
867  if (dix /= af_neighb_high_pm(nb)) then
868  ! The difference in index is not the expected +-1, so a periodic
869  ! boundary
870  boundary(n) = .true.
871  else
872  boundary(n) = .false.
873  end if
874  end if
875  end do
876 
877  end function af_is_phys_boundary
878 
881  pure logical function af_is_ref_boundary(boxes, id, nb)
882  type(box_t), intent(in) :: boxes(:)
883  integer, intent(in) :: id
884  integer, intent(in) :: nb
885  integer :: nb_id
886 
887  af_is_ref_boundary = .false.
888  nb_id = boxes(id)%neighbors(nb)
889 
890  if (nb_id == af_no_box) then
891  af_is_ref_boundary = .true.
892  else if (nb_id > af_no_box) then
893  if (.not. af_has_children(boxes(id)) .and. &
894  af_has_children(boxes(nb_id))) then
895  af_is_ref_boundary = .true.
896  end if
897  end if
898  end function af_is_ref_boundary
899 
903  pure function af_get_child_offset(box, nb) result(ix_offset)
904  type(box_t), intent(in) :: box
905  integer, intent(in), optional :: nb
906  integer :: ix_offset(ndim)
907 
908  ix_offset = iand(box%ix-1, 1) * ishft(box%n_cell, -1) ! * n_cell / 2
909  if (present(nb)) ix_offset = ix_offset - af_neighb_dix(:, nb) * box%n_cell
910  end function af_get_child_offset
911 
913  pure function af_get_ix_on_parent(box, ix) result(p_ix)
914  type(box_t), intent(in) :: box
915  integer, intent(in) :: ix(ndim)
916  integer :: p_ix(ndim)
917  p_ix = af_get_child_offset(box) + ishft(ix+1, -1)
918  end function af_get_ix_on_parent
919 
921  pure function af_get_ix_on_neighb(box, ix, nb) result(nb_ix)
922  type(box_t), intent(in) :: box
923  integer, intent(in) :: ix(ndim)
924  integer, intent(in) :: nb
925  integer :: nb_ix(ndim), nb_dim
926 
927  nb_dim = af_neighb_dim(nb)
928  nb_ix = ix
929  nb_ix(nb_dim) = nb_ix(nb_dim) - af_neighb_high_pm(nb) * box%n_cell
930  end function af_get_ix_on_neighb
931 
933  pure function af_neighb_offset(nbs) result(dix)
934  integer, intent(in) :: nbs(:)
935  integer :: n, dim, dix(ndim)
936 
937  dix = 0
938  do n = 1, size(nbs)
939  dim = af_neighb_dim(nbs(n))
940  dix(dim) = dix(dim) + af_neighb_high_pm(nbs(n))
941  end do
942  end function af_neighb_offset
943 
945  subroutine af_get_index_bc_inside(nb, nc, n_gc, lo, hi)
946  integer, intent(in) :: nb
947  integer, intent(in) :: nc
948  integer, intent(in) :: n_gc
949  integer, intent(out) :: lo(NDIM)
950  integer, intent(out) :: hi(NDIM)
951  integer :: nb_dim
952 
953  ! Determine index range next to boundary
954  nb_dim = af_neighb_dim(nb)
955  lo(:) = 1
956  hi(:) = nc
957  if (af_neighb_low(nb)) then
958  lo(nb_dim) = 1
959  hi(nb_dim) = n_gc
960  else
961  lo(nb_dim) = nc - n_gc + 1
962  hi(nb_dim) = nc
963  end if
964  end subroutine af_get_index_bc_inside
965 
967  subroutine af_get_index_bc_outside(nb, nc, n_gc, lo, hi)
968  integer, intent(in) :: nb
969  integer, intent(in) :: nc
970  integer, intent(in) :: n_gc
971  integer, intent(out) :: lo(NDIM)
972  integer, intent(out) :: hi(NDIM)
973  integer :: nb_dim
974 
975  ! Determine index range next to boundary
976  nb_dim = af_neighb_dim(nb)
977  lo(:) = 1
978  hi(:) = nc
979  if (af_neighb_low(nb)) then
980  lo(nb_dim) = 1 - n_gc
981  hi(nb_dim) = 0
982  else
983  lo(nb_dim) = nc + 1
984  hi(nb_dim) = nc + n_gc
985  end if
986  end subroutine af_get_index_bc_outside
987 
989  subroutine af_get_index_bface_inside(nb, nc, n_gc, lo, hi)
990  integer, intent(in) :: nb
991  integer, intent(in) :: nc
992  integer, intent(in) :: n_gc
993  integer, intent(out) :: lo(NDIM)
994  integer, intent(out) :: hi(NDIM)
995  integer :: nb_dim
996 
997  ! Determine index range next to boundary
998  nb_dim = af_neighb_dim(nb)
999  lo(:) = 1
1000  hi(:) = nc
1001  if (af_neighb_low(nb)) then
1002  lo(nb_dim) = 1
1003  hi(nb_dim) = n_gc
1004  else
1005  lo(nb_dim) = nc - n_gc + 2
1006  hi(nb_dim) = nc + 1
1007  end if
1008  end subroutine af_get_index_bface_inside
1009 
1012  pure integer function af_ix_to_ichild(ix)
1013  integer, intent(in) :: ix(ndim)
1014  ! The index can range from 1 (all ix odd) and 2**NDIM (all ix even)
1015 #if NDIM == 1
1016  af_ix_to_ichild = 2 - iand(ix(1), 1)
1017 #elif NDIM == 2
1018  af_ix_to_ichild = 4 - 2 * iand(ix(2), 1) - iand(ix(1), 1)
1019 #elif NDIM == 3
1020  af_ix_to_ichild = &
1021  8 - 4 * iand(ix(3), 1) - 2 * iand(ix(2), 1) - iand(ix(1), 1)
1022 #endif
1023  end function af_ix_to_ichild
1024 
1027  pure function af_cc_ix(box, r) result(cc_ix)
1028  type(box_t), intent(in) :: box
1029  real(dp), intent(in) :: r(ndim)
1030  integer :: cc_ix(ndim)
1031  cc_ix = ceiling((r - box%r_min) / box%dr)
1032  end function af_cc_ix
1033 
1035  pure function af_r_cc(box, cc_ix) result(r)
1036  type(box_t), intent(in) :: box
1037  integer, intent(in) :: cc_ix(ndim)
1038  real(dp) :: r(ndim)
1039  r = box%r_min + (cc_ix-0.5_dp) * box%dr
1040  end function af_r_cc
1041 
1043  pure function af_r_fc(box, dim, fc_ix) result(r)
1044  type(box_t), intent(in) :: box
1045  integer, intent(in) :: dim
1046  integer, intent(in) :: fc_ix(ndim)
1047  real(dp) :: r(ndim)
1048  r = box%r_min + (fc_ix-0.5_dp) * box%dr
1049  r(dim) = r(dim) - 0.5_dp * box%dr(dim)
1050  end function af_r_fc
1051 
1053  pure function af_rr_cc(box, cc_ix) result(r)
1054  type(box_t), intent(in) :: box
1055  real(dp), intent(in) :: cc_ix(ndim)
1056  real(dp) :: r(ndim)
1057  r = box%r_min + (cc_ix-0.5_dp) * box%dr
1058  end function af_rr_cc
1059 
1061  pure function af_r_center(box) result(r_center)
1062  type(box_t), intent(in) :: box
1063  real(dp) :: r_center(ndim)
1064  r_center = box%r_min + 0.5_dp * box%n_cell * box%dr
1065  end function af_r_center
1066 
1068  pure function af_min_dr(tree) result(dr)
1069  type(af_t), intent(in) :: tree
1070  real(dp) :: dr
1071  dr = minval(af_lvl_dr(tree, tree%highest_lvl))
1072  end function af_min_dr
1073 
1075  pure function af_lvl_dr(tree, lvl) result(dr)
1076  type(af_t), intent(in) :: tree
1077  integer, intent(in) :: lvl
1078  real(dp) :: dr(ndim)
1079  dr = tree%dr_base * 0.5_dp**(lvl-1)
1080  end function af_lvl_dr
1081 
1082  subroutine af_set_box_gc(box, nb, iv, gc_scalar, gc_array)
1083  type(box_t), intent(inout) :: box
1084  integer, intent(in) :: nb
1085  integer, intent(in) :: iv
1086  real(dp), optional, intent(in) :: gc_scalar
1087 #if NDIM == 1
1088  real(dp), optional, intent(in) :: gc_array(1)
1089 #elif NDIM == 2
1090  real(dp), optional, intent(in) :: gc_array(box%n_cell)
1091 #elif NDIM == 3
1092 
1093  real(dp), optional, intent(in) :: gc_array(box%n_cell, box%n_cell)
1094 #endif
1095  integer :: nc
1096 
1097  nc = box%n_cell
1098 
1099  if (present(gc_array)) then
1100  select case (nb)
1101 #if NDIM == 1
1102  case (af_neighb_lowx)
1103  box%cc(0, iv) = gc_array(1)
1104  case (af_neighb_highx)
1105  box%cc(nc+1, iv) = gc_array(1)
1106 #elif NDIM == 2
1107  case (af_neighb_lowx)
1108  box%cc(0, 1:nc, iv) = gc_array
1109  case (af_neighb_highx)
1110  box%cc(nc+1, 1:nc, iv) = gc_array
1111  case (af_neighb_lowy)
1112  box%cc(1:nc, 0, iv) = gc_array
1113  case (af_neighb_highy)
1114  box%cc(1:nc, nc+1, iv) = gc_array
1115 #elif NDIM == 3
1116  case (af_neighb_lowx)
1117  box%cc(0, 1:nc, 1:nc, iv) = gc_array
1118  case (af_neighb_highx)
1119  box%cc(nc+1, 1:nc, 1:nc, iv) = gc_array
1120  case (af_neighb_lowy)
1121  box%cc(1:nc, 0, 1:nc, iv) = gc_array
1122  case (af_neighb_highy)
1123  box%cc(1:nc, nc+1, 1:nc, iv) = gc_array
1124  case (af_neighb_lowz)
1125  box%cc(1:nc, 1:nc, 0, iv) = gc_array
1126  case (af_neighb_highz)
1127  box%cc(1:nc, 1:nc, nc+1, iv) = gc_array
1128 #endif
1129  end select
1130  else if (present(gc_scalar)) then
1131  select case (nb)
1132 #if NDIM == 1
1133  case (af_neighb_lowx)
1134  box%cc(0, iv) = gc_scalar
1135  case (af_neighb_highx)
1136  box%cc(nc+1, iv) = gc_scalar
1137 #elif NDIM == 2
1138  case (af_neighb_lowx)
1139  box%cc(0, 1:nc, iv) = gc_scalar
1140  case (af_neighb_highx)
1141  box%cc(nc+1, 1:nc, iv) = gc_scalar
1142  case (af_neighb_lowy)
1143  box%cc(1:nc, 0, iv) = gc_scalar
1144  case (af_neighb_highy)
1145  box%cc(1:nc, nc+1, iv) = gc_scalar
1146 #elif NDIM == 3
1147  case (af_neighb_lowx)
1148  box%cc(0, 1:nc, 1:nc, iv) = gc_scalar
1149  case (af_neighb_highx)
1150  box%cc(nc+1, 1:nc, 1:nc, iv) = gc_scalar
1151  case (af_neighb_lowy)
1152  box%cc(1:nc, 0, 1:nc, iv) = gc_scalar
1153  case (af_neighb_highy)
1154  box%cc(1:nc, nc+1, 1:nc, iv) = gc_scalar
1155  case (af_neighb_lowz)
1156  box%cc(1:nc, 1:nc, 0, iv) = gc_scalar
1157  case (af_neighb_highz)
1158  box%cc(1:nc, 1:nc, nc+1, iv) = gc_scalar
1159 #endif
1160  end select
1161  else
1162  stop "af_set_box_gc: requires gc_scalar or gc_array"
1163  end if
1164  end subroutine af_set_box_gc
1165 
1166 #if NDIM == 2
1167 
1168  pure function af_cyl_radius_cc(box, i) result(r)
1169  type(box_t), intent(in) :: box
1170  integer, intent(in) :: i
1171  real(dp) :: r
1172  r = box%r_min(1) + (i-0.5_dp) * box%dr(1)
1173  end function af_cyl_radius_cc
1174 
1176  pure function af_cyl_volume_cc(box, i) result(dvol)
1177  type(box_t), intent(in) :: box
1178  integer, intent(in) :: i
1179  real(dp), parameter :: two_pi = 2 * acos(-1.0_dp)
1180  real(dp) :: dvol
1181  dvol = two_pi * (box%r_min(1) + (i-0.5_dp) * box%dr(1)) * product(box%dr)
1182  end function af_cyl_volume_cc
1183 
1187  subroutine af_cyl_child_weights(box, i, inner, outer)
1188  type(box_t), intent(in) :: box
1189  integer, intent(in) :: i
1190  real(dp), intent(out) :: inner, outer
1191  real(dp) :: tmp
1192 
1193  tmp = 0.25_dp * box%dr(1) / af_cyl_radius_cc(box, i)
1194  inner = 1 - tmp
1195  outer = 1 + tmp
1196  end subroutine af_cyl_child_weights
1197 
1199  subroutine af_cyl_flux_factors(box, flux_factors)
1200  type(box_t), intent(in) :: box
1201  real(dp), intent(out) :: flux_factors(2, box%n_cell)
1202  integer :: i
1203  real(dp) :: r, inv_r
1204 
1205  do i = 1, box%n_cell
1206  r = af_cyl_radius_cc(box, i)
1207  inv_r = 1/r
1208  flux_factors(1, i) = (r - 0.5_dp * box%dr(1)) * inv_r
1209  flux_factors(2, i) = (r + 0.5_dp * box%dr(1)) * inv_r
1210  end do
1211  end subroutine af_cyl_flux_factors
1212 #endif
1213 
1215  subroutine af_get_face_coords(box, nb, coords)
1216  type(box_t), intent(in) :: box
1217  integer, intent(in) :: nb
1218  real(dp), intent(out) :: coords(NDIM, box%n_cell**(NDIM-1))
1219  integer :: i, nb_dim, bc_dim(NDIM-1)
1220  integer, parameter :: all_dims(NDIM) = [(i, i = 1, ndim)]
1221  real(dp) :: rmin(NDIM)
1222 #if NDIM == 3
1223  integer :: j, ix
1224 #endif
1225 
1226  nb_dim = af_neighb_dim(nb)
1227  bc_dim = pack(all_dims, all_dims /= nb_dim)
1228  rmin(bc_dim) = box%r_min(bc_dim) + 0.5_dp * box%dr(bc_dim)
1229 
1230  if (af_neighb_low(nb)) then
1231  rmin(nb_dim) = box%r_min(nb_dim)
1232  else
1233  rmin(nb_dim) = box%r_min(nb_dim) + box%n_cell * box%dr(nb_dim)
1234  end if
1235 
1236 #if NDIM == 1
1237  coords(nb_dim, 1) = rmin(nb_dim)
1238 #elif NDIM == 2
1239  do i = 1, box%n_cell
1240  coords(bc_dim, i) = rmin(bc_dim) + (i-1) * box%dr(bc_dim)
1241  coords(nb_dim, i) = rmin(nb_dim)
1242  end do
1243 #elif NDIM == 3
1244  ix = 0
1245  do j = 1, box%n_cell
1246  do i = 1, box%n_cell
1247  ix = ix + 1
1248  coords(bc_dim, ix) = rmin(bc_dim) + [i-1, j-1] * box%dr(bc_dim)
1249  coords(nb_dim, ix) = rmin(nb_dim)
1250  end do
1251  end do
1252 #endif
1253  end subroutine af_get_face_coords
1254 
1255 end module m_af_types
Subroutine that gets a box and an array of reals.
Definition: m_af_types.f90:417
To fill ghost cells near physical boundaries in a custom way. If the number of ghost cells to fill is...
Definition: m_af_types.f90:477
To fill ghost cells near physical boundaries.
Definition: m_af_types.f90:464
Subroutine that gets a list of boxes, an id and an array of reals.
Definition: m_af_types.f90:431
Subroutine that gets a list of boxes and a box id.
Definition: m_af_types.f90:424
To set cell-centered variables based on a user-defined function. This can be useful to avoid recomput...
Definition: m_af_types.f90:491
Subroutine for prolongation.
Definition: m_af_types.f90:498
To fill ghost cells near refinement boundaries.
Definition: m_af_types.f90:454
Subroutine for setting refinement flags.
Definition: m_af_types.f90:403
Subroutine for restriction.
Definition: m_af_types.f90:509
Subroutine that gets a tree, a box id and an array of reals.
Definition: m_af_types.f90:446
Subroutine that gets a tree and a box id.
Definition: m_af_types.f90:439
Subroutine that gets a box.
Definition: m_af_types.f90:411
Subroutine that performs Gauss-Seidel relaxation.
Definition: m_af_types.f90:677
Subroutine that performs A * cc(..., i_in) = cc(..., i_out)
Definition: m_af_types.f90:669
Level set function.
Definition: m_af_types.f90:709
Compute distance to boundary starting at point a going to point b, in the range from [0,...
Definition: m_af_types.f90:716
This module contains the basic types and constants that are used in the NDIM-dimensional version of A...
Definition: m_af_types.f90:4
Collection of methods for a cell-centered variable.
Definition: m_af_types.f90:239
Type specifying the location of a cell.
Definition: m_af_types.f90:396
Type which stores all the boxes and levels, as well as some information about the number of boxes,...
Definition: m_af_types.f90:326
The basic building block of afivo: a box with cell-centered and face centered data,...
Definition: m_af_types.f90:286
Generic type for the coarse grid solver.
Definition: m_af_types.f90:547
Type which contains the indices of all boxes at a refinement level, as well as a list with all the "l...
Definition: m_af_types.f90:76
Type to store multigrid options in.
Definition: m_af_types.f90:572
Type that contains the refinement changes in a tree.
Definition: m_af_types.f90:88
Type that contains the refinement changes in a level.
Definition: m_af_types.f90:83
Type for storing a numerical stencil for a box.
Definition: m_af_types.f90:260