13 public :: a2_loop_box_arg
14 public :: a2_loop_boxes
15 public :: a2_loop_boxes_arg
16 public :: a2_tree_clear_cc
17 public :: a2_box_clear_cc
18 public :: a2_tree_clear_ghostcells
19 public :: a2_box_clear_ghostcells
20 public :: a2_box_add_cc
21 public :: a2_box_sub_cc
22 public :: a2_tree_times_cc
23 public :: a2_tree_apply
24 public :: a2_box_times_cc
25 public :: a2_box_lincomb_cc
26 public :: a2_box_copy_cc_to
27 public :: a2_box_copy_cc
28 public :: a2_boxes_copy_cc
29 public :: a2_tree_copy_cc
30 public :: a2_reduction
31 public :: a2_reduction_vec
32 public :: a2_reduction_loc
33 public :: a2_tree_max_cc
34 public :: a2_tree_min_cc
35 public :: a2_tree_max_fc
36 public :: a2_tree_sum_cc
37 public :: a2_box_copy_fc
38 public :: a2_boxes_copy_fc
39 public :: a2_tree_copy_fc
42 public :: a2_get_id_at
51 subroutine a2_loop_box(tree, my_procedure, leaves_only)
52 type(
a2_t),
intent(inout) :: tree
53 procedure(
a2_subr) :: my_procedure
54 logical,
intent(in),
optional :: leaves_only
58 leaves = .false.;
if (
present(leaves_only)) leaves = leaves_only
59 if (.not. tree%ready) stop
"a2_loop_box: set_base has not been called" 62 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
65 do i = 1,
size(tree%lvls(lvl)%leaves)
66 id = tree%lvls(lvl)%leaves(i)
67 call my_procedure(tree%boxes(id))
72 do i = 1,
size(tree%lvls(lvl)%ids)
73 id = tree%lvls(lvl)%ids(i)
74 call my_procedure(tree%boxes(id))
80 end subroutine a2_loop_box
83 subroutine a2_loop_box_arg(tree, my_procedure, rarg, leaves_only)
84 type(
a2_t),
intent(inout) :: tree
86 real(dp),
intent(in) :: rarg(:)
87 logical,
intent(in),
optional :: leaves_only
91 if (.not. tree%ready) stop
"Tree not ready" 92 leaves = .false.;
if (
present(leaves_only)) leaves = leaves_only
95 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
98 do i = 1,
size(tree%lvls(lvl)%leaves)
99 id = tree%lvls(lvl)%leaves(i)
100 call my_procedure(tree%boxes(id), rarg)
105 do i = 1,
size(tree%lvls(lvl)%ids)
106 id = tree%lvls(lvl)%ids(i)
107 call my_procedure(tree%boxes(id), rarg)
113 end subroutine a2_loop_box_arg
116 subroutine a2_loop_boxes(tree, my_procedure, leaves_only)
117 type(
a2_t),
intent(inout) :: tree
119 logical,
intent(in),
optional :: leaves_only
121 integer :: lvl, i, id
123 if (.not. tree%ready) stop
"Tree not ready" 124 leaves = .false.;
if (
present(leaves_only)) leaves = leaves_only
127 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
130 do i = 1,
size(tree%lvls(lvl)%leaves)
131 id = tree%lvls(lvl)%leaves(i)
132 call my_procedure(tree%boxes, id)
137 do i = 1,
size(tree%lvls(lvl)%ids)
138 id = tree%lvls(lvl)%ids(i)
139 call my_procedure(tree%boxes, id)
145 end subroutine a2_loop_boxes
148 subroutine a2_loop_boxes_arg(tree, my_procedure, rarg, leaves_only)
149 type(
a2_t),
intent(inout) :: tree
151 real(dp),
intent(in) :: rarg(:)
152 logical,
intent(in),
optional :: leaves_only
154 integer :: lvl, i, id
156 if (.not. tree%ready) stop
"Tree not ready" 157 leaves = .false.;
if (
present(leaves_only)) leaves = leaves_only
160 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
163 do i = 1,
size(tree%lvls(lvl)%leaves)
164 id = tree%lvls(lvl)%leaves(i)
165 call my_procedure(tree%boxes, id, rarg)
170 do i = 1,
size(tree%lvls(lvl)%ids)
171 id = tree%lvls(lvl)%ids(i)
172 call my_procedure(tree%boxes, id, rarg)
178 end subroutine a2_loop_boxes_arg
181 pure function a2_r_inside(box, r, d)
result(inside)
183 real(dp),
intent(in) :: r(2)
184 real(dp),
intent(in),
optional :: d
188 r_max = box%r_min + box%dr * box%n_cell
190 inside = all(r+d >= box%r_min) .and. all(r-d <= r_max)
192 inside = all(r >= box%r_min) .and. all(r <= r_max)
194 end function a2_r_inside
199 pure function a2_get_id_at(tree, rr, highest_lvl, guess)
result(id)
201 real(dp),
intent(in) :: rr(2)
202 integer,
intent(in),
optional :: highest_lvl
203 integer,
intent(in),
optional :: guess
206 integer :: i, i_ch, lvl_max
208 if (
present(guess))
then 210 if (id > 0 .and. id < tree%highest_id)
then 211 if (tree%boxes(id)%in_use .and. &
212 a2_r_inside(tree%boxes(id), rr))
then 215 do while (a2_has_children(tree%boxes(id)))
216 i_ch = child_that_contains(tree%boxes(id), rr)
217 id = tree%boxes(id)%children(i_ch)
225 lvl_max = tree%lvl_limit
226 if (
present(highest_lvl)) lvl_max = highest_lvl
229 do i = 1,
size(tree%lvls(1)%ids)
230 id = tree%lvls(1)%ids(i)
231 if (a2_r_inside(tree%boxes(id), rr))
exit 234 if (i >
size(tree%lvls(1)%ids))
then 240 if (tree%boxes(id)%lvl >= lvl_max .or. &
241 .not. a2_has_children(tree%boxes(id)))
exit 242 i_ch = child_that_contains(tree%boxes(id), rr)
243 id = tree%boxes(id)%children(i_ch)
247 end function a2_get_id_at
252 pure function a2_get_loc(tree, rr, highest_lvl, guess)
result(loc)
254 real(dp),
intent(in) :: rr(2)
255 integer,
intent(in),
optional :: highest_lvl
257 integer,
intent(in),
optional :: guess
260 loc%id = a2_get_id_at(tree, rr, highest_lvl, guess)
262 if (loc%id == -1)
then 265 loc%ix = a2_cc_ix(tree%boxes(loc%id), rr)
269 where (loc%ix < 1) loc%ix = 1
270 where (loc%ix > tree%n_cell) loc%ix = tree%n_cell
272 end function a2_get_loc
275 pure function child_that_contains(box, rr)
result(i_ch)
276 type(
box2_t),
intent(in) :: box
277 real(dp),
intent(in) :: rr(2)
279 real(dp) :: center(2)
282 center = box%r_min + box%dr * ishft(box%n_cell, -1)
284 if (rr(1) > center(1)) i_ch = i_ch + 1
285 if (rr(2) > center(2)) i_ch = i_ch + 2
286 end function child_that_contains
289 pure function a2_r_loc(tree, loc)
result(r)
293 r = tree%boxes(loc%id)%r_min + &
294 (loc%ix-0.5_dp) * tree%boxes(loc%id)%dr
295 end function a2_r_loc
297 subroutine a2_tree_clear_cc(tree, iv)
298 type(
a2_t),
intent(inout) :: tree
299 integer,
intent(in) :: iv
300 integer :: lvl, i, id
303 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
305 do i = 1,
size(tree%lvls(lvl)%ids)
306 id = tree%lvls(lvl)%ids(i)
307 call a2_box_clear_cc(tree%boxes(id), iv)
312 end subroutine a2_tree_clear_cc
315 subroutine a2_box_clear_cc(box, iv)
317 integer,
intent(in) :: iv
319 end subroutine a2_box_clear_cc
321 subroutine a2_tree_clear_ghostcells(tree, iv)
322 type(
a2_t),
intent(inout) :: tree
323 integer,
intent(in) :: iv
324 integer :: lvl, i, id
327 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
329 do i = 1,
size(tree%lvls(lvl)%ids)
330 id = tree%lvls(lvl)%ids(i)
331 call a2_box_clear_ghostcells(tree%boxes(id), iv)
336 end subroutine a2_tree_clear_ghostcells
339 subroutine a2_box_clear_ghostcells(box, iv)
341 integer,
intent(in) :: iv
347 box%cc(nc+1, :, iv) = 0
349 box%cc(:, nc+1, iv) = 0
350 end subroutine a2_box_clear_ghostcells
353 subroutine a2_box_add_cc(box, iv_from, iv_to)
355 integer,
intent(in) :: iv_from, iv_to
356 box%cc(:,:, iv_to) = box%cc(:,:, iv_to) + box%cc(:,:, iv_from)
357 end subroutine a2_box_add_cc
360 subroutine a2_box_sub_cc(box, iv_from, iv_to)
362 integer,
intent(in) :: iv_from, iv_to
363 box%cc(:,:, iv_to) = box%cc(:,:, iv_to) - box%cc(:,:, iv_from)
364 end subroutine a2_box_sub_cc
368 subroutine a2_tree_apply(tree, iv_a, iv_b, op, eps)
369 type(
a2_t),
intent(inout) :: tree
370 integer,
intent(in) :: iv_a, iv_b
371 character(len=*),
intent(in) :: op
372 real(dp),
intent(in),
optional :: eps
373 integer :: lvl, i, id
376 use_eps = sqrt(tiny(1.0_dp))
377 if (
present(eps)) use_eps = eps
380 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
382 do i = 1,
size(tree%lvls(lvl)%ids)
383 id = tree%lvls(lvl)%ids(i)
386 tree%boxes(id)%cc(:, :, iv_a) = &
387 tree%boxes(id)%cc(:, :, iv_a) + &
388 tree%boxes(id)%cc(:, :, iv_b)
390 tree%boxes(id)%cc(:, :, iv_a) = &
391 tree%boxes(id)%cc(:, :, iv_a) * &
392 tree%boxes(id)%cc(:, :, iv_b)
394 tree%boxes(id)%cc(:, :, iv_a) = &
395 tree%boxes(id)%cc(:, :, iv_a) / &
396 max(tree%boxes(id)%cc(:, :, iv_b), eps)
398 error stop
"a2_tree_apply: unknown operand" 404 end subroutine a2_tree_apply
406 subroutine a2_tree_times_cc(tree, ivs, facs)
407 type(
a2_t),
intent(inout) :: tree
408 integer,
intent(in) :: ivs(:)
409 real(dp),
intent(in) :: facs(:)
410 integer :: lvl, i, id, n
412 if (
size(ivs) /=
size(facs)) &
413 error stop
"a2_times_cc: invalid array size" 416 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
418 do i = 1,
size(tree%lvls(lvl)%ids)
419 id = tree%lvls(lvl)%ids(i)
421 call a2_box_times_cc(tree%boxes(id), facs(n), ivs(n))
427 end subroutine a2_tree_times_cc
430 subroutine a2_box_times_cc(box, a, iv)
432 real(dp),
intent(in) :: a
433 integer,
intent(in) :: iv
434 box%cc(:,:, iv) = a * box%cc(:,:, iv)
435 end subroutine a2_box_times_cc
438 subroutine a2_box_lincomb_cc(box, a, iv_a, b, iv_b)
440 real(dp),
intent(in) :: a, b
441 integer,
intent(in) :: iv_a, iv_b
442 box%cc(:,:, iv_b) = a * box%cc(:,:, iv_a) + b * box%cc(:,:, iv_b)
443 end subroutine a2_box_lincomb_cc
446 subroutine a2_box_copy_cc_to(box_from, iv_from, box_to, iv_to)
448 type(
box2_t),
intent(inout) :: box_to
449 integer,
intent(in) :: iv_from, iv_to
450 box_to%cc(:,:, iv_to) = box_from%cc(:,:, iv_from)
451 end subroutine a2_box_copy_cc_to
454 subroutine a2_box_copy_cc(box, iv_from, iv_to)
456 integer,
intent(in) :: iv_from, iv_to
457 box%cc(:,:, iv_to) = box%cc(:,:, iv_from)
458 end subroutine a2_box_copy_cc
461 subroutine a2_boxes_copy_cc(boxes, ids, iv_from, iv_to)
463 integer,
intent(in) :: ids(:), iv_from, iv_to
468 call a2_box_copy_cc(boxes(ids(i)), iv_from, iv_to)
471 end subroutine a2_boxes_copy_cc
474 subroutine a2_tree_copy_cc(tree, iv_from, iv_to)
475 type(
a2_t),
intent(inout) :: tree
476 integer,
intent(in) :: iv_from, iv_to
479 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
480 call a2_boxes_copy_cc(tree%boxes, tree%lvls(lvl)%ids, iv_from, iv_to)
482 end subroutine a2_tree_copy_cc
485 subroutine a2_reduction(tree, box_func, reduction, init_val, out_val)
487 real(dp),
intent(in) :: init_val
488 real(dp),
intent(out) :: out_val
489 real(dp) :: tmp, my_val
490 integer :: i, id, lvl
494 real(dp) function box_func(box)
496 type(
box2_t),
intent(in) :: box
497 end function box_func
500 real(dp) function reduction(a, b)
502 real(dp),
intent(in) :: a, b
503 end function reduction
506 if (.not. tree%ready) stop
"Tree not ready" 511 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
513 do i = 1,
size(tree%lvls(lvl)%leaves)
514 id = tree%lvls(lvl)%leaves(i)
515 tmp = box_func(tree%boxes(id))
516 my_val = reduction(tmp, my_val)
522 out_val = reduction(my_val, out_val)
525 end subroutine a2_reduction
528 subroutine a2_reduction_vec(tree, box_func, reduction, init_val, &
531 integer,
intent(in) :: n_vals
532 real(dp),
intent(in) :: init_val(n_vals)
533 real(dp),
intent(out) :: out_val(n_vals)
534 real(dp) :: tmp(n_vals), my_val(n_vals)
535 integer :: i, id, lvl
539 function box_func(box, n_vals)
result(vec)
541 type(
box2_t),
intent(in) :: box
542 integer,
intent(in) :: n_vals
543 real(dp) :: vec(n_vals)
544 end function box_func
547 function reduction(vec_1, vec_2, n_vals)
result(vec)
549 integer,
intent(in) :: n_vals
550 real(dp),
intent(in) :: vec_1(n_vals), vec_2(n_vals)
551 real(dp) :: vec(n_vals)
552 end function reduction
555 if (.not. tree%ready) stop
"Tree not ready" 560 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
562 do i = 1,
size(tree%lvls(lvl)%leaves)
563 id = tree%lvls(lvl)%leaves(i)
564 tmp = box_func(tree%boxes(id), n_vals)
565 my_val = reduction(tmp, my_val, n_vals)
571 out_val = reduction(my_val, out_val, n_vals)
574 end subroutine a2_reduction_vec
578 subroutine a2_reduction_loc(tree, iv, box_subr, reduction, &
579 init_val, out_val, out_loc)
581 integer,
intent(in) :: iv
582 real(dp),
intent(in) :: init_val
583 real(dp),
intent(out) :: out_val
584 type(
a2_loc_t),
intent(out) :: out_loc
585 real(dp) :: tmp, new_val, my_val
586 integer :: i, id, lvl, tmp_ix(2)
591 subroutine box_subr(box, iv, val, ix)
593 type(
box2_t),
intent(in) :: box
594 integer,
intent(in) :: iv
595 real(dp),
intent(out) :: val
596 integer,
intent(out) :: ix(2)
597 end subroutine box_subr
600 real(dp) function reduction(a, b)
602 real(dp),
intent(in) :: a, b
603 end function reduction
606 if (.not. tree%ready) stop
"Tree not ready" 614 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
616 do i = 1,
size(tree%lvls(lvl)%leaves)
617 id = tree%lvls(lvl)%leaves(i)
618 call box_subr(tree%boxes(id), iv, tmp, tmp_ix)
619 new_val = reduction(tmp, my_val)
620 if (abs(new_val - my_val) > 0)
then 630 new_val = reduction(my_val, out_val)
631 if (abs(new_val - out_val) > 0)
then 632 out_loc%id = my_loc%id
633 out_loc%ix = my_loc%ix
638 end subroutine a2_reduction_loc
642 subroutine a2_tree_max_cc(tree, iv, cc_max, loc)
644 integer,
intent(in) :: iv
645 real(dp),
intent(out) :: cc_max
647 type(
a2_loc_t),
intent(out),
optional :: loc
650 call a2_reduction_loc(tree, iv, box_max_cc, reduce_max, &
651 -huge(1.0_dp)/10, cc_max, tmp_loc)
652 if (
present(loc)) loc = tmp_loc
653 end subroutine a2_tree_max_cc
657 subroutine a2_tree_min_cc(tree, iv, cc_min, loc)
659 integer,
intent(in) :: iv
660 real(dp),
intent(out) :: cc_min
662 type(
a2_loc_t),
intent(out),
optional :: loc
665 call a2_reduction_loc(tree, iv, box_min_cc, reduce_min, &
666 huge(1.0_dp)/10, cc_min, tmp_loc)
668 if (
present(loc)) loc = tmp_loc
669 end subroutine a2_tree_min_cc
672 subroutine a2_tree_max_fc(tree, dim, iv, fc_max, loc)
674 integer,
intent(in) :: dim
675 integer,
intent(in) :: iv
676 real(dp),
intent(out) :: fc_max
678 type(
a2_loc_t),
intent(out),
optional :: loc
683 dim_iv = (dim-1) * tree%n_var_face + iv - 1
685 call a2_reduction_loc(tree, dim_iv, box_max_fc, reduce_max, &
686 -huge(1.0_dp)/10, fc_max, tmp_loc)
687 if (
present(loc)) loc = tmp_loc
688 end subroutine a2_tree_max_fc
690 subroutine box_max_cc(box, iv, val, ix)
691 type(
box2_t),
intent(in) :: box
692 integer,
intent(in) :: iv
693 real(dp),
intent(out) :: val
694 integer,
intent(out) :: ix(2)
698 ix = maxloc(box%cc(1:nc, 1:nc, iv))
699 val = box%cc(ix(1), ix(2), iv)
700 end subroutine box_max_cc
702 subroutine box_min_cc(box, iv, val, ix)
703 type(
box2_t),
intent(in) :: box
704 integer,
intent(in) :: iv
705 real(dp),
intent(out) :: val
706 integer,
intent(out) :: ix(2)
710 ix = minloc(box%cc(1:nc, 1:nc, iv))
711 val = box%cc(ix(1), ix(2), iv)
712 end subroutine box_min_cc
714 subroutine box_max_fc(box, dim_iv, val, ix)
715 type(
box2_t),
intent(in) :: box
716 integer,
intent(in) :: dim_iv
717 real(dp),
intent(out) :: val
718 integer,
intent(out) :: ix(2)
719 integer :: dim, iv, n_fc, nc, dix(2)
724 n_fc =
size(box%fc, 4)
727 dim = dim_iv / n_fc + 1
728 iv = dim_iv - (dim-1) * n_fc + 1
731 ix = maxloc(box%fc(1:nc+dix(1), 1:nc+dix(2), dim, iv))
732 val = box%fc(ix(1), ix(2), dim, iv)
733 end subroutine box_max_fc
735 real(dp) function reduce_max(a, b)
736 real(dp),
intent(in) :: a, b
737 reduce_max = max(a, b)
738 end function reduce_max
740 real(dp) function reduce_min(a, b)
741 real(dp),
intent(in) :: a, b
742 reduce_min = min(a, b)
743 end function reduce_min
747 subroutine a2_tree_sum_cc(tree, iv, cc_sum)
749 integer,
intent(in) :: iv
750 real(dp),
intent(out) :: cc_sum
751 real(dp) :: tmp, my_sum, fac
752 integer :: i, id, lvl, nc
754 if (.not. tree%ready) stop
"Tree not ready" 758 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
759 fac = a2_lvl_dr(tree, lvl)**2
762 do i = 1,
size(tree%lvls(lvl)%leaves)
763 id = tree%lvls(lvl)%leaves(i)
764 nc = tree%boxes(id)%n_cell
765 if (tree%coord_t == af_cyl)
then 766 tmp = sum_2pr_box(tree%boxes(id), iv)
768 tmp = sum(tree%boxes(id)%cc(1:nc, 1:nc, iv))
770 my_sum = my_sum + fac * tmp
781 pure function sum_2pr_box(box, iv)
result(res)
782 type(
box2_t),
intent(in) :: box
783 integer,
intent(in) :: iv
784 real(dp),
parameter :: twopi = 2 * acos(-1.0_dp)
793 res = res + box%cc(i, j, iv) * a2_cyl_radius_cc(box, i)
797 end function sum_2pr_box
798 end subroutine a2_tree_sum_cc
801 subroutine a2_box_copy_fc(box, iv_from, iv_to)
803 integer,
intent(in) :: iv_from
804 integer,
intent(in) :: iv_to
805 box%fc(:,:,:, iv_to) = box%fc(:,:,:, iv_from)
806 end subroutine a2_box_copy_fc
809 subroutine a2_boxes_copy_fc(boxes, ids, iv_from, iv_to)
811 integer,
intent(in) :: ids(:)
812 integer,
intent(in) :: iv_from
813 integer,
intent(in) :: iv_to
818 call a2_box_copy_fc(boxes(ids(i)), iv_from, iv_to)
821 end subroutine a2_boxes_copy_fc
824 subroutine a2_tree_copy_fc(tree, iv_from, iv_to)
825 type(
a2_t),
intent(inout) :: tree
826 integer,
intent(in) :: iv_from
827 integer,
intent(in) :: iv_to
830 if (.not. tree%ready) stop
"Tree not ready" 831 do lvl = lbound(tree%lvls, 1), tree%highest_lvl
832 call a2_boxes_copy_fc(tree%boxes, tree%lvls(lvl)%ids, iv_from, iv_to)
834 end subroutine a2_tree_copy_fc
839 pure function a2_n_cell(tree, lvl)
result(n_cell)
841 integer,
intent(in) :: lvl
847 n_cell = tree%n_cell / (2**(1-lvl))
849 end function a2_n_cell
Subroutine that gets a box and an array of reals.
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...
This module contains the basic types and constants that are used in the 2-dimensional version of Afiv...
Subroutine that gets a list of boxes, an id and an array of reals.
Type specifying the location of a cell.
The basic building block of afivo: a box with cell-centered and face centered data, and information about its position, neighbors, children etc.
Subroutine that gets a box.
Subroutine that gets a list of boxes and a box id.