Afivo  0.3
random_refinement_3d.f90
1 
6 program random_refinement_3d
7  use m_a3_all
8 
9  implicit none
10 
11  type(a3_t) :: tree
12  integer :: id, iter, boxes_used
13  integer, parameter :: n_boxes_base = 2
14  integer :: ix_list(3, n_boxes_base)
15  integer :: nb_list(a3_num_neighbors, n_boxes_base)
16  integer, parameter :: box_size = 8
17  integer, parameter :: i_phi = 1
18  type(ref_info_t) :: ref_info
19  real(dp) :: dr, sum_phi_t0, sum_phi
20  character(len=40) :: fname
21  integer :: count_rate,t_start,t_end
22 
23  write(*,'(A)') 'program random_refinement_3d'
24 
25  print *, "Number of threads", af_get_max_threads()
26 
27  ! The cell spacing at the coarsest grid level
28  dr = 2 * acos(-1.0_dp) / box_size ! 2 * pi / box_size
29 
30  ! Initialize tree
31  call a3_init(tree, & ! Tree to initialize
32  box_size, & ! A box contains box_size**DIM cells
33  1, & ! Number of cell-centered variables
34  0, & ! Number of face-centered variables
35  dr, & ! Distance between cells on base level
36  cc_names = ["phi"]) ! Optional: names of cell-centered variables
37 
38  call a3_set_cc_methods(tree, 1, a3_bc_dirichlet_zero, &
39  prolong=a3_prolong_linear_cons)
40 
41  ! Set up geometry.
42  ! Neighbors for the boxes are stored in nb_list
43  nb_list(:, :) = af_no_box ! Default value
44 
45  ! Spatial indices are used to define the coordinates of a box.
46  do id = 1, n_boxes_base
47  ix_list(:, id) = [id, 1, 1] ! Boxes at (1,1,1), (2,1,1), etc.
48  nb_list(a3_neighb_highz, id) = id ! Periodic in z-direction
49  nb_list(a3_neighb_highy, id) = id ! Periodic in y-direction
50  end do
51 
52  ! Periodic boundaries only have to be specified from one side. The lower-x
53  ! neighbor of box 1 is the last box
54  nb_list(a3_neighb_lowx, 1) = n_boxes_base
55 
56  ! Create the base mesh, using the box indices and their neighbor information
57  call a3_set_base(tree, n_boxes_base, ix_list, nb_list)
58  call a3_print_info(tree)
59 
60  ! Set variables on base by using the helper functions a3_loop_box(tree, sub)
61  ! and a3_loop_boxes(tree, sub). These functions call the subroutine sub for
62  ! each box in the tree, with a slightly different syntax.
63  call a3_loop_box(tree, set_init_cond)
64 
65  ! Fill ghost cells for phi. The third argument is a subroutine that fills
66  ! ghost cells near refinement boundaries, and the fourth argument fill ghost
67  ! cells near physical boundaries.
68  call a3_gc_tree(tree, i_phi, a3_gc_interp, a3_bc_dirichlet_zero)
69 
70  call a3_tree_sum_cc(tree, i_phi, sum_phi_t0)
71 
72  call system_clock(t_start, count_rate)
73  boxes_used = 1
74  do iter = 1, 15
75  ! This writes a VTK output file containing the cell-centered values of the
76  ! leaves of the tree (the boxes not covered by refinement).
77  ! Variables are the names given as the third argument.
78  write(fname, "(A,I0)") "random_refinement_3d_", iter
79  call a3_write_silo(tree, trim(fname), dir="output", n_cycle=iter)
80 
81  ! This updates the refinement of the tree, by at most one level per call.
82  ! The second argument is a subroutine that is called for each box that can
83  ! be refined or derefined, and it should set refinement flags. Information
84  ! about the changes in refinement are returned in the third argument.
85  !
86  ! Within each (de)refinement step the subroutine a3_tidy_up is called. This
87  ! means that every now and then whether too much holes appear in the tree
88  ! box list. Therefore reordering of tree is not necessary at the end of the
89  ! iteration process
90  call a3_adjust_refinement(tree, ref_routine, ref_info, ref_buffer=0)
91 
92  call a3_tree_sum_cc(tree, i_phi, sum_phi)
93  write(*, "(A,E10.2)") " conservation error: ", sum_phi - sum_phi_t0
94  boxes_used = boxes_used + ref_info%n_add - ref_info%n_rm
95  write(*,'(4(3x,A,1x,i6))') "# new boxes", ref_info%n_add, &
96  "# removed boxes", ref_info%n_rm, &
97  "# boxes used ", boxes_used, &
98  " highest level ", tree%highest_lvl
99  end do
100  call system_clock(t_end, count_rate)
101 
102  write(*, '(A,i3,1x,A,f8.2,1x,A,/)') &
103  ' Wall-clock time after ',iter, &
104  ' iterations: ', (t_end-t_start) / real(count_rate, dp), &
105  ' seconds'
106 
107  call a3_print_info(tree)
108 
109  ! This call is not really necessary here, but cleaning up the data in a tree
110  ! is important if your program continues with other tasks.
111  call a3_destroy(tree)
112 
113 contains
114 
115  ! Return the refinement flag for boxes(id)
116  subroutine ref_routine(box, cell_flags)
117  type(box3_t), intent(in) :: box ! A list of all boxes in the tree
118  integer, intent(out) :: cell_flags(box%n_cell, box%n_cell, box%n_cell)
119  real(dp) :: rr
120 
121  ! Draw a [0, 1) random number
122  call random_number(rr)
123 
124  if (rr < 0.5_dp**3 .and. box%lvl < 5) then
125  cell_flags = af_do_ref ! Add refinement
126  else
127  cell_flags = af_rm_ref ! Ask to remove this box, which will not always
128  ! happen (see documentation)
129  end if
130  end subroutine ref_routine
131 
132  ! This routine sets the initial conditions for each box
133  subroutine set_init_cond(box)
134  type(box3_t), intent(inout) :: box
135  integer :: i, j, k, nc
136  real(dp) :: rr(3)
137 
138  nc = box%n_cell
139  do k = 1, nc; do j = 1, nc; do i = 1, nc
140  ! Get the coordinate of the cell center at i,j
141  rr = a3_r_cc(box, [i, j, k])
142 
143  ! Set the values at each cell according to some function
144  box%cc(i, j, k, i_phi) = sin(0.5_dp * rr(1)) * cos(rr(2))
145  end do; end do; end do
146  end subroutine set_init_cond
147 
148 end program random_refinement_3d
Module which contains all Afivo modules, so that a user does not have to include them separately...
Definition: m_a3_all.f90:4