4 #include "cpp_macros.h"
10 public :: af_add_cc_variable
11 public :: af_add_fc_variable
12 public :: af_find_cc_variable
13 public :: af_find_fc_variable
15 public :: af_set_cc_methods
18 public :: af_adjust_refinement
19 public :: af_refine_up_to_lvl
20 public :: af_consistent_fluxes
26 subroutine af_add_cc_variable(tree, name, write_out, n_copies, &
29 type(
af_t),
intent(inout) :: tree
31 character(len=*),
intent(in) :: name
33 logical,
intent(in),
optional :: write_out
35 logical,
intent(in),
optional :: write_binary
37 integer,
intent(in),
optional :: n_copies
39 integer,
intent(out),
optional :: ix
42 logical :: writeout, writebin
44 ncpy = 1;
if (
present(n_copies)) ncpy = n_copies
45 writeout = .true.;
if (
present(write_out)) writeout = write_out
46 writebin = .true.;
if (
present(write_binary)) writebin = write_binary
48 if (ncpy < 1) error stop
"af_add_cc_variable: n_copies < 1"
50 if (tree%n_var_cell + ncpy > af_max_num_vars)
then
51 print *,
"af_max_num_vars:", af_max_num_vars
52 print *,
"Cannot add ", name
53 error stop
"Too many cc variables"
57 tree%n_var_cell = tree%n_var_cell + 1
59 if (
present(ix)) ix = tree%n_var_cell
60 tree%cc_names(tree%n_var_cell) = name
61 tree%cc_write_output(tree%n_var_cell) = writeout
62 tree%cc_write_binary(tree%n_var_cell) = writebin
63 tree%cc_num_copies(tree%n_var_cell) = ncpy
65 write(tree%cc_names(tree%n_var_cell),
"(A,I0)") &
67 tree%cc_write_output(tree%n_var_cell) = .false.
68 tree%cc_write_binary(tree%n_var_cell) = .false.
69 tree%cc_num_copies(tree%n_var_cell) = 0
73 end subroutine af_add_cc_variable
76 subroutine af_add_fc_variable(tree, name, ix, write_binary)
78 type(
af_t),
intent(inout) :: tree
80 character(len=*),
intent(in) :: name
82 integer,
intent(out),
optional :: ix
84 logical,
intent(in),
optional :: write_binary
87 writebin = .true.;
if (
present(write_binary)) writebin = write_binary
89 if (tree%n_var_face + 1 > af_max_num_vars)
then
90 print *,
"af_max_num_vars:", af_max_num_vars
91 print *,
"Cannot add ", name
92 error stop
"Too many fc variables"
95 tree%n_var_face = tree%n_var_face + 1
96 tree%fc_names(tree%n_var_face) = name
97 tree%fc_write_binary(tree%n_var_face) = writebin
98 if (
present(ix)) ix = tree%n_var_face
99 end subroutine af_add_fc_variable
102 integer function af_find_cc_variable(tree, name)
103 type(
af_t),
intent(in) :: tree
104 character(len=*),
intent(in) :: name
107 do n = 1, tree%n_var_cell
108 if (tree%cc_names(n) == name)
exit
111 if (n == tree%n_var_cell+1)
then
112 print *,
"variable name: ", trim(name)
113 error stop
"af_find_cc_variable: variable not found"
116 af_find_cc_variable = n
117 end function af_find_cc_variable
120 integer function af_find_fc_variable(tree, name)
121 type(
af_t),
intent(in) :: tree
122 character(len=*),
intent(in) :: name
125 do n = 1, tree%n_var_face
126 if (tree%fc_names(n) == name)
exit
129 if (n == tree%n_var_face+1)
then
130 print *,
"variable name: ", trim(name)
131 error stop
"af_find_fc_variable: variable not found"
134 af_find_fc_variable = n
135 end function af_find_fc_variable
138 subroutine af_init(tree, n_cell, r_max, grid_size, periodic, r_min, coord, &
139 mem_limit_gb, box_limit)
140 type(
af_t),
intent(inout) :: tree
141 integer,
intent(in) :: n_cell
142 real(dp),
intent(in) :: r_max(ndim)
143 integer,
intent(in) :: grid_size(ndim)
144 logical,
intent(in),
optional :: periodic(ndim)
145 real(dp),
intent(in),
optional :: r_min(ndim)
146 integer,
intent(in),
optional :: coord
147 real(dp),
intent(in),
optional :: mem_limit_gb
149 integer,
intent(in),
optional :: box_limit
151 real(dp) :: r_min_a(ndim), gb_limit
152 integer :: lvl, coord_a, box_bytes
155 r_min_a = 0.0_dp;
if (
present(r_min)) r_min_a = r_min
156 coord_a = af_xyz;
if (
present(coord)) coord_a = coord
157 gb_limit = 4;
if (
present(mem_limit_gb)) gb_limit = mem_limit_gb
159 if (tree%ready) stop
"af_init: tree was already initialized"
160 if (n_cell < 2) stop
"af_init: n_cell should be >= 2"
161 if (btest(n_cell, 0)) stop
"af_init: n_cell should be even"
162 if (gb_limit <= 0) stop
"af_init: mem_limit_gb should be > 0"
163 if (coord_a == af_cyl .and. ndim /= 2) stop
"af_init: cyl. coords only in 2d"
164 if (tree%n_var_cell <= 0) stop
"af_init: no cell-centered variables present"
166 do lvl = af_min_lvl, af_max_lvl
167 allocate(tree%lvls(lvl)%ids(0))
168 allocate(tree%lvls(lvl)%leaves(0))
169 allocate(tree%lvls(lvl)%parents(0))
173 tree%r_base = r_min_a
174 tree%dr_base = (r_max - r_min_a) / grid_size
177 tree%coord_t = coord_a
179 if (
present(box_limit))
then
180 if (box_limit <= 0) stop
"af_init: box_limit should be > 0"
181 tree%box_limit = box_limit
184 box_bytes = af_box_bytes(n_cell, tree%n_var_cell, tree%n_var_face)
185 tree%box_limit = nint(gb_limit * 2.0_dp**30 / box_bytes)
189 allocate(tree%boxes(tree%box_limit))
192 tree%n_removed_ids = 0
193 allocate(tree%removed_ids(tree%box_limit))
196 if (.not.
allocated(tree%cc_auto_vars)) &
197 allocate(tree%cc_auto_vars(0))
198 if (.not.
allocated(tree%cc_func_vars)) &
199 allocate(tree%cc_func_vars(0))
201 call af_set_coarse_grid(tree, grid_size, periodic)
203 end subroutine af_init
206 subroutine af_set_coarse_grid(tree, coarse_grid_size, periodic_dims)
208 type(
af_t),
intent(inout) :: tree
210 integer,
intent(in) :: coarse_grid_size(NDIM)
212 logical,
intent(in),
optional :: periodic_dims(NDIM)
213 logical :: periodic(NDIM)
214 integer :: nx(NDIM), ix(NDIM), IJK, id, n_boxes, nb
216 integer,
allocatable :: id_array(DTIMES(:))
218 if (tree%highest_id > 0) &
219 error stop
"af_set_coarse_grid: this tree already has boxes"
220 if (.not.
allocated(tree%boxes)) &
221 error stop
"af_set_coarse_grid: tree not initialized"
222 if (any(coarse_grid_size < tree%n_cell)) &
223 error stop
"af_set_coarse_grid: coarse_grid_size < tree%n_cell"
224 if (any(modulo(coarse_grid_size, tree%n_cell) /= 0)) &
225 error stop
"af_set_coarse_grid: coarse_grid_size not divisible by tree%n_cell"
227 periodic(:) = .false.;
if (
present(periodic_dims)) periodic = periodic_dims
229 tree%coarse_grid_size(1:ndim) = coarse_grid_size
230 tree%periodic(1:ndim) = periodic
233 nx = coarse_grid_size / tree%n_cell
234 n_boxes = product(nx)
237 call create_index_array(nx, periodic, id_array)
240 if (n_boxes >
size(tree%boxes(:))) &
241 error stop
"Not enough memory available for coarse grid"
244 deallocate(tree%lvls(1)%ids)
245 allocate(tree%lvls(1)%ids(n_boxes))
248 call get_free_ids(tree, tree%lvls(1)%ids)
249 tree%lvls(1)%leaves = tree%lvls(1)%ids
255 tree%boxes(id)%lvl = 1
256 tree%boxes(id)%ix = [ijk]
257 tree%boxes(id)%dr = tree%dr_base
258 tree%boxes(id)%r_min = tree%r_base + &
259 (tree%boxes(id)%ix - 1) * tree%dr_base * tree%n_cell
260 tree%boxes(id)%n_cell = tree%n_cell
261 tree%boxes(id)%coord_t = tree%coord_t
263 tree%boxes(id)%parent = af_no_box
264 tree%boxes(id)%children(:) = af_no_box
267 do nb = 1, af_num_neighbors
268 ix = [ijk] + af_neighb_dix(:, nb)
269 tree%boxes(id)%neighbors(nb) = id_array(ix(1))
271 tree%boxes(id)%neighbor_mat = id_array(i-1:i+1)
273 call af_init_box(tree, id)
279 tree%boxes(id)%lvl = 1
280 tree%boxes(id)%ix = [ijk]
281 tree%boxes(id)%dr = tree%dr_base
282 tree%boxes(id)%r_min = tree%r_base + &
283 (tree%boxes(id)%ix - 1) * tree%dr_base * tree%n_cell
284 tree%boxes(id)%n_cell = tree%n_cell
285 tree%boxes(id)%coord_t = tree%coord_t
287 tree%boxes(id)%parent = af_no_box
288 tree%boxes(id)%children(:) = af_no_box
291 do nb = 1, af_num_neighbors
292 ix = [ijk] + af_neighb_dix(:, nb)
293 tree%boxes(id)%neighbors(nb) = id_array(ix(1), ix(2))
295 tree%boxes(id)%neighbor_mat = id_array(i-1:i+1, j-1:j+1)
297 call af_init_box(tree, id)
305 tree%boxes(id)%lvl = 1
306 tree%boxes(id)%ix = [ijk]
307 tree%boxes(id)%dr = tree%dr_base
308 tree%boxes(id)%r_min = tree%r_base + &
309 (tree%boxes(id)%ix - 1) * tree%dr_base * tree%n_cell
310 tree%boxes(id)%n_cell = tree%n_cell
311 tree%boxes(id)%coord_t = tree%coord_t
313 tree%boxes(id)%parent = af_no_box
314 tree%boxes(id)%children(:) = af_no_box
317 do nb = 1, af_num_neighbors
318 ix = [ijk] + af_neighb_dix(:, nb)
319 tree%boxes(id)%neighbors(nb) = id_array(ix(1), ix(2), ix(3))
321 tree%boxes(id)%neighbor_mat = id_array(i-1:i+1, j-1:j+1, k-1:k+1)
323 call af_init_box(tree, id)
332 do i = 1,
size(tree%lvls(1)%ids)
333 id = tree%lvls(1)%ids(i)
334 do n = 1,
size(tree%cc_func_vars)
335 iv = tree%cc_func_vars(n)
336 call tree%cc_methods(iv)%funcval(tree%boxes(id), iv)
340 end subroutine af_set_coarse_grid
343 subroutine af_set_cc_methods(tree, iv, bc, rb, prolong, restrict, &
344 bc_custom, funcval, prolong_limiter)
349 type(
af_t),
intent(inout) :: tree
350 integer,
intent(in) :: iv
358 integer,
intent(in),
optional :: prolong_limiter
361 if (tree%has_cc_method(iv))
then
362 print *,
"Cannot call af_set_cc_methods twice for ", &
363 trim(tree%cc_names(iv))
368 do i = iv, iv + tree%cc_num_copies(iv) - 1
369 if (
present(bc))
then
370 tree%cc_methods(i)%bc => bc
371 else if (
present(bc_custom))
then
372 tree%cc_methods(i)%bc_custom => bc_custom
373 else if (.not.
present(funcval))
then
374 error stop
"af_set_cc_methods: bc, bc_custom or funcval required"
377 if (
present(funcval))
then
378 tree%cc_methods(i)%funcval => funcval
381 if (
present(rb))
then
382 tree%cc_methods(i)%rb => rb
384 tree%cc_methods(i)%rb => af_gc_interp
387 if (
present(prolong))
then
388 tree%cc_methods(i)%prolong => prolong
390 tree%cc_methods(i)%prolong => af_prolong_linear
393 if (
present(restrict))
then
394 tree%cc_methods(i)%restrict => restrict
396 tree%cc_methods(i)%restrict => af_restrict_box
399 if (
present(prolong_limiter))
then
400 tree%cc_methods(i)%prolong_limiter = prolong_limiter
401 else if (ndim < 3)
then
402 tree%cc_methods(i)%prolong_limiter = af_limiter_mc_t
407 tree%cc_methods(i)%prolong_limiter = af_limiter_gminmod43_t
410 tree%has_cc_method(i) = .true.
413 if (.not.
allocated(tree%cc_auto_vars)) &
414 allocate(tree%cc_auto_vars(0))
415 if (.not.
allocated(tree%cc_func_vars)) &
416 allocate(tree%cc_func_vars(0))
421 if (
present(funcval))
then
422 tree%cc_func_vars = [tree%cc_func_vars, iv]
424 tree%cc_auto_vars = [tree%cc_auto_vars, iv]
427 end subroutine af_set_cc_methods
431 subroutine af_destroy(tree)
432 type(
af_t),
intent(out) :: tree
433 end subroutine af_destroy
436 subroutine create_index_array(nx, periodic, id_array)
437 integer,
intent(in) :: nx(NDIM)
438 logical,
intent(in) :: periodic(NDIM)
439 integer,
intent(inout),
allocatable :: id_array(DTIMES(:))
443 allocate(id_array(0:nx(1)+1))
445 allocate(id_array(0:nx(1)+1, 0:nx(2)+1))
447 allocate(id_array(0:nx(1)+1, 0:nx(2)+1, 0:nx(3)+1))
450 id_array = af_phys_boundary
457 if (periodic(1))
then
458 id_array(0) = id_array(nx(1))
459 id_array(nx(1)+1) = id_array(1)
464 id_array(i, j) = (j-1) * nx(1) + i
468 if (periodic(1))
then
469 id_array(0, :) = id_array(nx(1), :)
470 id_array(nx(1)+1, :) = id_array(1, :)
473 if (periodic(2))
then
474 id_array(:, 0) = id_array(:, nx(2))
475 id_array(:, nx(2)+1) = id_array(:, 1)
481 id_array(i, j, k) = (k-1) * nx(2) * nx(1) + (j-1) * nx(1) + i
486 if (periodic(1))
then
487 id_array(0, :, :) = id_array(nx(1), :, :)
488 id_array(nx(1)+1, :, :) = id_array(1, :, :)
491 if (periodic(2))
then
492 id_array(:, 0, :) = id_array(:, nx(2), :)
493 id_array(:, nx(2)+1, :) = id_array(:, 1, :)
496 if (periodic(3))
then
497 id_array(:, :, 0) = id_array(:, :, nx(3))
498 id_array(:, :, nx(3)+1) = id_array(:, :, 1)
501 end subroutine create_index_array
504 subroutine set_leaves_parents(boxes, level)
505 type(
box_t),
intent(in) :: boxes(:)
506 type(
lvl_t),
intent(inout) :: level
507 integer :: i, id, i_leaf, i_parent
508 integer :: n_parents, n_leaves
510 n_parents = count(af_has_children(boxes(level%ids)))
511 n_leaves =
size(level%ids) - n_parents
513 if (n_parents /=
size(level%parents))
then
514 deallocate(level%parents)
515 allocate(level%parents(n_parents))
518 if (n_leaves /=
size(level%leaves))
then
519 deallocate(level%leaves)
520 allocate(level%leaves(n_leaves))
525 do i = 1,
size(level%ids)
527 if (af_has_children(boxes(id)))
then
528 i_parent = i_parent + 1
529 level%parents(i_parent) = id
532 level%leaves(i_leaf) = id
535 end subroutine set_leaves_parents
539 subroutine af_init_box(tree, id)
540 type(
af_t),
intent(inout) :: tree
541 integer,
intent(in) :: id
542 integer :: nc, ix, nb
545 associate(box => tree%boxes(id))
548 new_box = .not.
allocated(box%cc)
551 allocate(box%cc(dtimes(0:nc+1), tree%n_var_cell))
552 allocate(box%fc(dtimes(nc+1), ndim, tree%n_var_face))
560 box%n_bc = count(box%neighbors < af_no_box)
561 allocate(box%bc_index_to_nb(box%n_bc))
562 allocate(box%bc_coords(ndim, nc**(ndim-1), box%n_bc))
563 allocate(box%bc_val(nc**(ndim-1), tree%n_var_cell, box%n_bc))
564 allocate(box%bc_type(tree%n_var_cell, box%n_bc))
570 do nb = 1, af_num_neighbors
571 if (box%neighbors(nb) < af_no_box)
then
573 box%bc_index_to_nb(ix) = nb
574 box%nb_to_bc_index(nb) = ix
575 call af_get_face_coords(box, nb, box%bc_coords(:, :, ix))
579 end subroutine af_init_box
583 subroutine af_deactivate_box(box)
584 type(box_t),
intent(inout) :: box
587 box%tag = af_init_tag
589 if (
allocated(box%stencils))
deallocate(box%stencils)
590 deallocate(box%bc_index_to_nb, box%bc_coords, &
591 box%bc_val, box%bc_type)
592 end subroutine af_deactivate_box
595 subroutine set_neighbs(boxes, id)
596 type(box_t),
intent(inout) :: boxes(:)
597 integer,
intent(in) :: id
598 integer :: nb, nb_id, IJK
601 if (boxes(id)%neighbor_mat(ijk) == af_no_box)
then
602 nb_id = find_neighb(boxes, id, [ijk])
603 if (nb_id > af_no_box)
then
604 boxes(id)%neighbor_mat(ijk) = nb_id
606 boxes(nb_id)%neighbor_mat(-i) = id
608 boxes(nb_id)%neighbor_mat(-i, -j) = id
610 boxes(nb_id)%neighbor_mat(-i, -j, -k) = id
616 do nb = 1, af_num_neighbors
617 if (boxes(id)%neighbors(nb) == af_no_box)
then
619 nb_id = boxes(id)%neighbor_mat(af_neighb_dix(1, nb))
621 nb_id = boxes(id)%neighbor_mat(af_neighb_dix(1, nb), &
622 af_neighb_dix(2, nb))
624 nb_id = boxes(id)%neighbor_mat(af_neighb_dix(1, nb), &
625 af_neighb_dix(2, nb), af_neighb_dix(3, nb))
627 if (nb_id > af_no_box)
then
628 boxes(id)%neighbors(nb) = nb_id
629 boxes(nb_id)%neighbors(af_neighb_rev(nb)) = id
633 end subroutine set_neighbs
636 function find_neighb(boxes, id, dix)
result(nb_id)
637 type(box_t),
intent(in) :: boxes(:)
638 integer,
intent(in) :: id
639 integer,
intent(in) :: dix(ndim)
640 integer :: nb_id, p_id, c_ix, dix_c(ndim)
642 p_id = boxes(id)%parent
643 c_ix = af_ix_to_ichild(boxes(id)%ix)
647 where ((dix == -1) .eqv. af_child_low(:, c_ix))
653 p_id = boxes(p_id)%neighbor_mat(dindex(dix_c))
655 if (p_id <= af_no_box)
then
658 c_ix = af_ix_to_ichild(boxes(id)%ix + dix)
659 nb_id = boxes(p_id)%children(c_ix)
661 end function find_neighb
664 subroutine af_refine_up_to_lvl(tree, lvl)
665 type(af_t),
intent(inout) :: tree
666 integer,
intent(in) :: lvl
667 type(ref_info_t) :: ref_info
669 if (lvl < tree%highest_lvl) error stop
"tree already above level"
672 call af_adjust_refinement(tree, ref_routine, ref_info)
673 if (ref_info%n_add == 0)
exit
678 subroutine ref_routine(box, cell_flags)
679 type(box_t),
intent(in) :: box
680 integer,
intent(out) :: cell_flags(dtimes(box%n_cell))
682 if (box%lvl < lvl)
then
683 cell_flags = af_do_ref
685 cell_flags = af_keep_ref
687 end subroutine ref_routine
689 end subroutine af_refine_up_to_lvl
697 subroutine af_adjust_refinement(tree, ref_subr, ref_info, ref_buffer, &
699 type(af_t),
intent(inout) :: tree
700 procedure(af_subr_ref) :: ref_subr
701 type(ref_info_t),
intent(inout) :: ref_info
702 integer,
intent(in),
optional :: ref_buffer
704 integer,
intent(in),
optional :: ref_links(:, :)
705 integer :: lvl, id, i, c_ids(af_num_children), i_ch
706 integer :: i_add, i_rm, n_ch, n_add
707 integer,
allocatable :: ref_flags(:)
708 integer :: ref_buffer_val
710 if (.not. tree%ready) stop
"Tree not ready"
713 if (
present(ref_buffer)) ref_buffer_val = ref_buffer
715 if (ref_buffer_val < 0) &
716 error stop
"af_adjust_refinement: ref_buffer < 0"
717 if (ref_buffer_val > tree%n_cell) &
718 error stop
"af_adjust_refinement: ref_buffer > tree%n_cell"
720 allocate(ref_flags(tree%highest_id))
724 call consistent_ref_flags(tree, ref_flags, ref_subr, &
725 ref_buffer_val, ref_links)
728 n_ch = af_num_children
729 ref_info%n_rm = n_ch * count(ref_flags == af_derefine)
730 if (
allocated(ref_info%rm))
deallocate(ref_info%rm)
731 allocate(ref_info%rm(ref_info%n_rm))
734 ref_info%n_add = n_ch * count(ref_flags == af_refine)
735 if (
allocated(ref_info%lvls))
deallocate(ref_info%lvls)
736 allocate(ref_info%lvls(tree%highest_lvl+1))
739 allocate(ref_info%lvls(1)%add(0))
741 do lvl = 1, tree%highest_lvl
743 n_add = n_ch * count(ref_flags(tree%lvls(lvl)%ids) == af_refine)
744 allocate(ref_info%lvls(lvl+1)%add(n_add))
749 do lvl = 1, af_max_lvl-1
752 do i = 1,
size(tree%lvls(lvl)%ids)
753 id = tree%lvls(lvl)%ids(i)
755 if (id >
size(ref_flags))
then
757 else if (ref_flags(id) == af_refine)
then
759 call get_free_ids(tree, c_ids)
760 call add_children(tree, id, c_ids)
761 ref_info%lvls(lvl+1)%add(i_add+1:i_add+n_ch) = &
762 tree%boxes(id)%children
764 else if (ref_flags(id) == af_derefine)
then
766 call auto_restrict(tree, id)
767 ref_info%rm(i_rm+1:i_rm+n_ch) = tree%boxes(id)%children
769 call remove_children(tree, id)
774 call set_leaves_parents(tree%boxes, tree%lvls(lvl))
777 call set_child_ids(tree%lvls(lvl)%parents, &
778 tree%lvls(lvl+1)%ids, tree%boxes)
781 do i = 1,
size(tree%lvls(lvl)%parents)
782 id = tree%lvls(lvl)%parents(i)
783 if (ref_flags(id) == af_refine)
then
784 do i_ch = 1, af_num_children
785 call set_neighbs(tree%boxes, tree%boxes(id)%children(i_ch))
790 if (
size(tree%lvls(lvl+1)%ids) == 0)
exit
793 tree%highest_lvl = lvl
797 i = tree%n_removed_ids
798 tree%removed_ids(i+1:i+ref_info%n_rm) = ref_info%rm(:)
799 tree%n_removed_ids = tree%n_removed_ids + ref_info%n_rm
802 do id = tree%highest_id, 1, -1
803 if (tree%boxes(id)%in_use)
exit
808 i_rm = tree%n_removed_ids
809 i = count(tree%removed_ids(1:i_rm) <= tree%highest_id)
810 tree%removed_ids(1:i) = pack(tree%removed_ids(1:i_rm), &
811 mask=tree%removed_ids(1:i_rm) <= tree%highest_id)
812 tree%n_removed_ids = i
817 lvl = min(lvl+1, af_max_lvl)
818 call set_leaves_parents(tree%boxes, tree%lvls(lvl))
820 call auto_prolong(tree, ref_info)
822 end subroutine af_adjust_refinement
825 subroutine auto_restrict(tree, id)
826 type(af_t),
intent(inout) :: tree
827 integer,
intent(in) :: id
828 integer :: i, iv, i_ch, ch_id
830 if (.not. any(tree%has_cc_method(:)))
return
832 do i_ch = 1, af_num_children
833 ch_id = tree%boxes(id)%children(i_ch)
834 do i = 1,
size(tree%cc_auto_vars)
835 iv = tree%cc_auto_vars(i)
836 call tree%cc_methods(iv)%restrict(tree%boxes(ch_id), &
837 tree%boxes(id), [iv])
840 end subroutine auto_restrict
843 subroutine auto_prolong(tree, ref_info)
845 type(af_t),
intent(inout) :: tree
846 type(ref_info_t),
intent(in) :: ref_info
847 integer :: lvl, i, n, iv, id, p_id
850 if (.not. any(tree%has_cc_method(:)) .or. ref_info%n_add == 0)
then
855 do lvl = 1, tree%highest_lvl
857 do i = 1,
size(ref_info%lvls(lvl)%add)
858 id = ref_info%lvls(lvl)%add(i)
859 p_id = tree%boxes(id)%parent
861 do n = 1,
size(tree%cc_auto_vars)
862 iv = tree%cc_auto_vars(n)
863 call tree%cc_methods(iv)%prolong(tree%boxes(p_id), &
864 tree%boxes(id), iv, limiter=tree%cc_methods(iv)%prolong_limiter)
866 do n = 1,
size(tree%cc_func_vars)
867 iv = tree%cc_func_vars(n)
868 call tree%cc_methods(iv)%funcval(tree%boxes(id), iv)
874 do i = 1,
size(ref_info%lvls(lvl)%add)
875 id = ref_info%lvls(lvl)%add(i)
876 call af_gc_box(tree, id, [tree%cc_auto_vars])
881 end subroutine auto_prolong
885 subroutine get_free_ids(tree, ids)
886 type(af_t),
intent(inout) :: tree
887 integer,
intent(out) :: ids(:)
888 integer :: i, highest_id_prev, n_ids
896 if (n_ids <= tree%n_removed_ids)
then
899 ids(i) = tree%removed_ids(tree%n_removed_ids-n_ids+i)
901 tree%n_removed_ids = tree%n_removed_ids - n_ids
904 highest_id_prev = tree%highest_id
905 tree%highest_id = tree%highest_id + n_ids
907 if (tree%highest_id >
size(tree%boxes))
then
908 print *,
"get_free_ids: exceeding memory limit"
909 write(*,
'(A,E12.2)')
" memory_limit (GByte): ", &
910 tree%box_limit * 0.5_dp**30 * &
911 af_box_bytes(tree%n_cell, tree%n_var_cell, tree%n_var_face)
912 print *,
"memory_limit (boxes): ", tree%box_limit
913 print *,
"You can increase the memory limit in your call to af_init"
914 print *,
"by setting mem_limit_gb to a higher value (in GBytes)"
918 ids = [(highest_id_prev + i, i=1,n_ids)]
922 end subroutine get_free_ids
929 subroutine consistent_ref_flags(tree, ref_flags, ref_subr, &
930 ref_buffer, ref_links)
931 use omp_lib,
only: omp_get_max_threads, omp_get_thread_num
932 type(af_t),
intent(inout) :: tree
933 integer,
intent(inout) :: ref_flags(:)
934 procedure(af_subr_ref) :: ref_subr
935 integer,
intent(in) :: ref_buffer
937 integer,
intent(in),
optional :: ref_links(:, :)
938 integer :: lvl, i, i_ch, ch_id, id
941 integer,
allocatable :: tmp_flags(:, :)
942 integer :: cell_flags(DTIMES(tree%n_cell))
943 integer,
parameter :: unset_flag = -huge(1)
947 allocate(tmp_flags(
size(ref_flags), omp_get_max_threads()))
949 tmp_flags(:, :) = unset_flag
955 thread_id = omp_get_thread_num() + 1
957 do lvl = 1, tree%highest_lvl
959 do i = 1,
size(tree%lvls(lvl)%leaves)
960 id = tree%lvls(lvl)%leaves(i)
962 call ref_subr(tree%boxes(id), cell_flags)
963 call cell_to_ref_flags(cell_flags, tree%n_cell, &
964 tmp_flags(:, thread_id), tree, id, ref_buffer)
968 if (tree%boxes(id)%lvl > 1)
then
969 p_id = tree%boxes(id)%parent
970 do i_ch = 1, af_ix_to_ichild(tree%boxes(id)%ix)-1
971 ch_id = tree%boxes(p_id)%children(i_ch)
972 if (.not. af_has_children(tree%boxes(ch_id)))
exit
975 if (i_ch == af_ix_to_ichild(tree%boxes(id)%ix))
then
977 call ref_subr(tree%boxes(p_id), cell_flags)
978 call cell_to_ref_flags(cell_flags, tree%n_cell, &
979 tmp_flags(:, thread_id), tree, p_id, ref_buffer)
988 do i = 1,
size(ref_flags)
989 ref_flags(i) = maxval(tmp_flags(i, :))
990 if (ref_flags(i) == unset_flag) ref_flags(i) = af_keep_ref
993 if (maxval(ref_flags) > af_do_ref .or. minval(ref_flags) < af_rm_ref) &
994 stop
"af_adjust_refinement: invalid refinement flag given"
997 do i = 1,
size(tree%lvls(af_max_lvl)%ids)
998 id = tree%lvls(af_max_lvl)%ids(i)
999 if (ref_flags(id) == af_do_ref) ref_flags(id) = af_keep_ref
1002 call ensure_two_one_balance(tree, ref_flags)
1003 call handle_derefinement_flags(tree, ref_flags)
1005 if (
present(ref_links))
then
1006 do i = 1,
size(ref_links, 2)
1007 ref_flags(ref_links(:, i)) = maxval(ref_flags(ref_links(:, i)))
1009 call ensure_two_one_balance(tree, ref_flags)
1010 call handle_derefinement_flags(tree, ref_flags)
1013 end subroutine consistent_ref_flags
1016 subroutine ensure_two_one_balance(tree, ref_flags)
1017 type(af_t),
intent(inout) :: tree
1018 integer,
intent(inout) :: ref_flags(:)
1019 integer :: lvl, i, id, nb, nb_id
1020 integer :: p_id, p_nb_id
1023 do lvl = tree%highest_lvl, 1, -1
1024 do i = 1,
size(tree%lvls(lvl)%leaves)
1025 id = tree%lvls(lvl)%leaves(i)
1027 if (ref_flags(id) == af_do_ref .or. ref_flags(id) == af_refine)
then
1028 ref_flags(id) = af_refine
1031 do nb = 1, af_num_neighbors
1032 nb_id = tree%boxes(id)%neighbors(nb)
1033 if (nb_id == af_no_box)
then
1035 p_id = tree%boxes(id)%parent
1036 p_nb_id = tree%boxes(p_id)%neighbors(nb)
1037 ref_flags(p_nb_id) = af_refine
1041 else if (ref_flags(id) == af_rm_ref)
then
1043 do nb = 1, af_num_neighbors
1044 nb_id = tree%boxes(id)%neighbors(nb)
1045 if (nb_id > af_no_box)
then
1046 if (af_has_children(tree%boxes(nb_id)) .or. &
1047 ref_flags(nb_id) > af_keep_ref)
then
1048 ref_flags(id) = af_keep_ref
1057 end subroutine ensure_two_one_balance
1059 subroutine handle_derefinement_flags(tree, ref_flags)
1060 type(af_t),
intent(inout) :: tree
1061 integer,
intent(inout) :: ref_flags(:)
1062 integer :: lvl, i, id, c_ids(af_num_children)
1065 do lvl = tree%highest_lvl-1, 1, -1
1066 do i = 1,
size(tree%lvls(lvl)%parents)
1067 id = tree%lvls(lvl)%parents(i)
1068 c_ids = tree%boxes(id)%children
1071 if (all(af_has_children(tree%boxes(c_ids)))) cycle
1075 if (all(ref_flags(c_ids) == af_rm_ref) .and. &
1076 ref_flags(id) <= af_keep_ref)
then
1077 ref_flags(id) = af_derefine
1079 ref_flags(id) = af_keep_ref
1083 where (ref_flags(c_ids) /= af_derefine)
1084 ref_flags(c_ids) = max(ref_flags(c_ids), af_keep_ref)
1090 end subroutine handle_derefinement_flags
1095 subroutine cell_to_ref_flags(cell_flags, nc, ref_flags, tree, id, &
1098 integer,
intent(in) :: nc
1099 integer,
intent(in) :: cell_flags(DTIMES(nc))
1100 integer,
intent(inout) :: ref_flags(:)
1101 type(af_t),
intent(in) :: tree
1102 integer,
intent(in) :: id
1103 integer,
intent(in) :: ref_buffer
1104 integer :: ix0(NDIM), ix1(NDIM), IJK, nb_id
1106 if (minval(cell_flags) < af_rm_ref .or. &
1107 maxval(cell_flags) > af_do_ref)
then
1108 error stop
"Error: invalid cell flags given"
1112 if (any(cell_flags == af_do_ref))
then
1113 ref_flags(id) = af_do_ref
1114 else if (any(cell_flags == af_keep_ref))
then
1115 ref_flags(id) = max(ref_flags(id), af_keep_ref)
1117 ref_flags(id) = max(ref_flags(id), af_rm_ref)
1120 if (ref_buffer <= 0)
return
1125 if (all([ijk] == 0)) cycle
1127 nb_id = tree%boxes(id)%neighbor_mat(ijk)
1130 if (nb_id <= af_no_box) cycle
1136 ix0 = nc - ref_buffer + 1
1138 elsewhere ([ijk] == -1)
1143 if (any(cell_flags(dslice(ix0, ix1)) == af_do_ref))
then
1144 ref_flags(nb_id) = af_do_ref
1148 end subroutine cell_to_ref_flags
1151 subroutine remove_children(tree, id)
1152 type(af_t),
intent(inout) :: tree
1153 integer,
intent(in) :: id
1154 integer :: ic, c_id, nb_id, nb_rev, nb, IJK
1156 do ic = 1, af_num_children
1157 c_id = tree%boxes(id)%children(ic)
1160 do nb = 1, af_num_neighbors
1161 nb_id = tree%boxes(c_id)%neighbors(nb)
1162 if (nb_id > af_no_box)
then
1163 nb_rev = af_neighb_rev(nb)
1164 tree%boxes(nb_id)%neighbors(nb_rev) = af_no_box
1169 nb_id = tree%boxes(c_id)%neighbor_mat(ijk)
1170 if (nb_id > af_no_box)
then
1172 tree%boxes(nb_id)%neighbor_mat(-i) = af_no_box
1174 tree%boxes(nb_id)%neighbor_mat(-i, -j) = af_no_box
1176 tree%boxes(nb_id)%neighbor_mat(-i, -j, -k) = af_no_box
1181 call af_deactivate_box(tree%boxes(c_id))
1184 tree%boxes(id)%children = af_no_box
1185 end subroutine remove_children
1188 subroutine add_children(tree, id, c_ids)
1189 type(af_t),
intent(inout) :: tree
1190 integer,
intent(in) :: id
1191 integer,
intent(in) :: c_ids(af_num_children)
1192 integer :: i, nb, child_nb(2**(NDIM-1))
1193 integer :: c_id, c_ix_base(NDIM), dix(NDIM)
1195 associate(boxes => tree%boxes)
1196 boxes(id)%children = c_ids
1197 c_ix_base = 2 * boxes(id)%ix - 1
1199 do i = 1, af_num_children
1201 boxes(c_id)%ix = c_ix_base + af_child_dix(:,i)
1202 boxes(c_id)%lvl = boxes(id)%lvl+1
1203 boxes(c_id)%parent = id
1204 boxes(c_id)%tag = af_init_tag
1205 boxes(c_id)%children = af_no_box
1206 boxes(c_id)%neighbors = af_no_box
1207 boxes(c_id)%neighbor_mat = af_no_box
1208 boxes(c_id)%neighbor_mat(dtimes(0)) = c_id
1209 boxes(c_id)%n_cell = boxes(id)%n_cell
1210 boxes(c_id)%coord_t = boxes(id)%coord_t
1211 boxes(c_id)%dr = 0.5_dp * boxes(id)%dr
1212 boxes(c_id)%r_min = boxes(id)%r_min + 0.5_dp * boxes(id)%dr * &
1213 af_child_dix(:,i) * boxes(id)%n_cell
1217 do nb = 1, af_num_neighbors
1218 if (boxes(id)%neighbors(nb) < af_no_box)
then
1219 child_nb = c_ids(af_child_adj_nb(:, nb))
1220 boxes(child_nb)%neighbors(nb) = boxes(id)%neighbors(nb)
1221 dix = af_neighb_dix(:, nb)
1222 boxes(child_nb)%neighbor_mat(dindex(dix)) = &
1223 boxes(id)%neighbors(nb)
1229 do i = 1, af_num_children
1230 call af_init_box(tree, c_ids(i))
1233 end subroutine add_children
1237 subroutine set_child_ids(p_ids, c_ids, boxes)
1238 integer,
intent(in) :: p_ids(:)
1239 integer,
allocatable,
intent(inout) :: c_ids(:)
1240 type(box_t),
intent(in) :: boxes(:)
1241 integer :: i, i0, i1, n_children
1243 n_children = af_num_children *
size(p_ids)
1244 if (n_children /=
size(c_ids))
then
1246 allocate(c_ids(n_children))
1249 do i = 1,
size(p_ids)
1250 i1 = i * af_num_children
1251 i0 = i1 - af_num_children + 1
1252 c_ids(i0:i1) = boxes(p_ids(i))%children
1254 end subroutine set_child_ids
1257 subroutine af_consistent_fluxes(tree, f_ixs)
1258 type(af_t),
intent(inout) :: tree
1259 integer,
intent(in) :: f_ixs(:)
1260 integer :: lvl, i, id, nb, nb_id
1262 if (.not. tree%ready) stop
"Tree not ready"
1264 do lvl = 1, tree%highest_lvl-1
1266 do i = 1,
size(tree%lvls(lvl)%parents)
1267 id = tree%lvls(lvl)%parents(i)
1268 do nb = 1, af_num_neighbors
1269 nb_id = tree%boxes(id)%neighbors(nb)
1272 if (nb_id > af_no_box)
then
1273 if (.not. af_has_children(tree%boxes(nb_id)))
then
1274 call flux_from_children(tree%boxes, id, nb, f_ixs)
1282 end subroutine af_consistent_fluxes
1286 subroutine flux_from_children(boxes, id, nb, f_ixs)
1287 type(box_t),
intent(inout) :: boxes(:)
1288 integer,
intent(in) :: id
1289 integer,
intent(in) :: nb
1290 integer,
intent(in) :: f_ixs(:)
1291 integer :: nc, nch, c_id, i_ch, i, ic, d
1292 integer :: n_chnb, nb_id, i_nb
1294 integer :: ioff(NDIM)
1302 nc = boxes(id)%n_cell
1304 d = af_neighb_dim(nb)
1305 n_chnb = 2**(ndim-1)
1306 nb_id = boxes(id)%neighbors(nb)
1308 if (af_neighb_low(nb))
then
1321 i_ch = af_child_adj_nb(ic, nb)
1322 c_id = boxes(id)%children(i_ch)
1323 boxes(nb_id)%fc(i_nb, 1, f_ixs) = boxes(c_id)%fc(i, 1, f_ixs)
1329 i_ch = af_child_adj_nb(ic, nb)
1330 c_id = boxes(id)%children(i_ch)
1332 ioff = nch*af_child_dix(:, i_ch)
1333 boxes(nb_id)%fc(i_nb, ioff(2)+1:ioff(2)+nch, 1, f_ixs) = 0.5_dp * ( &
1334 boxes(c_id)%fc(i, 1:nc:2, 1, f_ixs) + &
1335 boxes(c_id)%fc(i, 2:nc:2, 1, f_ixs))
1338 if (boxes(nb_id)%coord_t == af_cyl)
then
1341 i_ch = af_child_adj_nb(ic, nb)
1342 c_id = boxes(id)%children(i_ch)
1343 ioff = nch*af_child_dix(:, i_ch)
1346 call af_cyl_child_weights(boxes(nb_id), ioff(1)+n, w1, w2)
1347 boxes(nb_id)%fc(ioff(1)+n, i_nb, 2, f_ixs) = 0.5_dp * (&
1348 w1 * boxes(c_id)%fc(2*n-1, i, 2, f_ixs) + &
1349 w2 * boxes(c_id)%fc(2*n, i, 2, f_ixs))
1355 i_ch = af_child_adj_nb(ic, nb)
1356 c_id = boxes(id)%children(i_ch)
1357 ioff = nch*af_child_dix(:, i_ch)
1358 boxes(nb_id)%fc(ioff(1)+1:ioff(1)+nch, i_nb, 2, f_ixs) = 0.5_dp * ( &
1359 boxes(c_id)%fc(1:nc:2, i, 2, f_ixs) + &
1360 boxes(c_id)%fc(2:nc:2, i, 2, f_ixs))
1366 i_ch = af_child_adj_nb(ic, nb)
1367 c_id = boxes(id)%children(i_ch)
1368 ioff = nch*af_child_dix(:, i_ch)
1369 boxes(nb_id)%fc(i_nb, ioff(2)+1:ioff(2)+nch, &
1370 ioff(3)+1:ioff(3)+nch, 1, f_ixs) = 0.25_dp * ( &
1371 boxes(c_id)%fc(i, 1:nc:2, 1:nc:2, 1, f_ixs) + &
1372 boxes(c_id)%fc(i, 2:nc:2, 1:nc:2, 1, f_ixs) + &
1373 boxes(c_id)%fc(i, 1:nc:2, 2:nc:2, 1, f_ixs) + &
1374 boxes(c_id)%fc(i, 2:nc:2, 2:nc:2, 1, f_ixs))
1378 i_ch = af_child_adj_nb(ic, nb)
1379 c_id = boxes(id)%children(i_ch)
1380 ioff = nch*af_child_dix(:, i_ch)
1381 boxes(nb_id)%fc(ioff(1)+1:ioff(1)+nch, i_nb, &
1382 ioff(3)+1:ioff(3)+nch, 2, f_ixs) = 0.25_dp * ( &
1383 boxes(c_id)%fc(1:nc:2, i, 1:nc:2, 2, f_ixs) + &
1384 boxes(c_id)%fc(2:nc:2, i, 1:nc:2, 2, f_ixs) + &
1385 boxes(c_id)%fc(1:nc:2, i, 2:nc:2, 2, f_ixs) + &
1386 boxes(c_id)%fc(2:nc:2, i, 2:nc:2, 2, f_ixs))
1390 i_ch = af_child_adj_nb(ic, nb)
1391 c_id = boxes(id)%children(i_ch)
1392 ioff = nch*af_child_dix(:, i_ch)
1393 boxes(nb_id)%fc(ioff(1)+1:ioff(1)+nch, &
1394 ioff(2)+1:ioff(2)+nch, i_nb, 3, f_ixs) = 0.25_dp * ( &
1395 boxes(c_id)%fc(1:nc:2, 1:nc:2, i, 3, f_ixs) + &
1396 boxes(c_id)%fc(2:nc:2, 1:nc:2, i, 3, f_ixs) + &
1397 boxes(c_id)%fc(1:nc:2, 2:nc:2, i, 3, f_ixs) + &
1398 boxes(c_id)%fc(2:nc:2, 2:nc:2, i, 3, f_ixs))
1402 end subroutine flux_from_children
To fill ghost cells near physical boundaries in a custom way. If the number of ghost cells to fill is...
To fill ghost cells near physical boundaries.
To set cell-centered variables based on a user-defined function. This can be useful to avoid recomput...
Subroutine for prolongation.
To fill ghost cells near refinement boundaries.
Subroutine for restriction.
This module contains the core routines of Afivo, namely those that deal with initializing and changin...
This module contains routines related to the filling of ghost cells. Note that corner ghost cells are...
Module containing slope limiters.
This module contains the routines related to prolongation: going from coarse to fine variables.
This module contains routines for restriction: going from fine to coarse variables.
This module contains the basic types and constants that are used in the NDIM-dimensional version of A...
This module contains all kinds of different 'helper' routines for Afivo. If the number of routines fo...
Type which stores all the boxes and levels, as well as some information about the number of boxes,...
The basic building block of afivo: a box with cell-centered and face centered data,...
Type which contains the indices of all boxes at a refinement level, as well as a list with all the "l...