Afivo  0.3
boundary_conditions_3d.f90

Example showing how to use different types of boundary conditions

1 
5 program boundary_conditions_3d
6  use m_a3_all
7 
8  implicit none
9 
10  integer, parameter :: box_size = 8
11  integer, parameter :: n_boxes_base = 1
12  integer, parameter :: n_iterations = 20
13  integer, parameter :: i_phi = 1
14 
15  type(a3_t) :: tree
16  integer :: iter
17  integer :: ix_list(3, n_boxes_base)
18  real(dp) :: dr
19  character(len=100) :: fname
20 
21  print *, "Running boundary_conditions_3d"
22  print *, "Number of threads", af_get_max_threads()
23 
24  ! The cell spacing at the coarsest grid level
25  dr = 1.0_dp / box_size
26 
27  ! Initialize tree
28  call a3_init(tree, & ! Tree to initialize
29  box_size, & ! A box contains box_size**DIM cells
30  1, & ! Number of cell-centered variables
31  0, & ! Number of face-centered variables
32  dr, & ! Distance between cells on base level
33  cc_names=["phi"]) ! Variable names
34 
35  ! Set up geometry. This creates a single box, for which we need boundary
36  ! conditions on all sides
37  ix_list(:, 1) = [1, 1, 1] ! Set index of box 1
38 
39  ! Create the base mesh, using the box indices and their neighbor information
40  call a3_set_base(tree, 1, ix_list)
41  call a3_print_info(tree)
42 
43  do iter = 1, n_iterations
44  if (iter == 1) then
45  ! Set initial conditions on first iteration
46  call a3_loop_box(tree, set_phi_zero)
47  else
48  ! Replace phi by average over neighbors
49  call a3_loop_box(tree, average_phi)
50  end if
51 
52  call a3_gc_tree(tree, i_phi, a3_gc_interp, boundary_method)
53 
54  write(fname, "(A,I0)") "boundary_conditions_3d_", iter
55  call a3_write_vtk(tree, trim(fname), dir="output")
56  end do
57 
58 contains
59 
60  ! This routine sets the initial conditions for each box
61  subroutine set_phi_zero(box)
62  type(box3_t), intent(inout) :: box
63 
64  box%cc(:, :, :, i_phi) = 0.0_dp
65  end subroutine set_phi_zero
66 
67  subroutine average_phi(box)
68  type(box3_t), intent(inout) :: box
69  integer :: i, j, k, nc
70  real(dp) :: tmp(box%n_cell, box%n_cell, box%n_cell)
71 
72  nc = box%n_cell
73 
74  do k = 1, nc; do j = 1, nc; do i = 1, nc
75  tmp(i, j, k) = 1/6.0_dp * ( &
76  box%cc(i+1, j, k, i_phi) + &
77  box%cc(i-1, j, k, i_phi) + &
78  box%cc(i, j+1, k, i_phi) + &
79  box%cc(i, j-1, k, i_phi) + &
80  box%cc(i, j, k+1, i_phi) + &
81  box%cc(i, j, k-1, i_phi))
82  end do; end do; end do
83 
84  box%cc(1:nc, 1:nc, 1:nc, i_phi) = tmp(:, :, :)
85  end subroutine average_phi
86 
88  subroutine boundary_method(box, nb, iv, bc_type)
89  type(box3_t), intent(inout) :: box ! Box to operate on
90  integer, intent(in) :: nb ! Direction for the boundary condition
91  integer, intent(in) :: iv ! Index of variable
92  integer, intent(out) :: bc_type ! Type of boundary condition
93  integer :: nc
94 
95  nc = box%n_cell
96 
97  ! Below the solution is specified in the approriate ghost cells
98  select case (nb)
99  case (a3_neighb_lowx) ! Lower-x direction
100  bc_type = af_bc_dirichlet
101  box%cc(0, 1:nc, 1:nc, iv) = 1.0_dp
102  case (a3_neighb_highx) ! Higher-x direction
103  bc_type = af_bc_neumann
104  box%cc(nc+1, 1:nc, 1:nc, iv) = 0.0_dp
105  case (a3_neighb_lowy) ! Lower-y direction
106  bc_type = af_bc_dirichlet
107  box%cc(1:nc, 0, 1:nc, iv) = 1.0_dp
108  case (a3_neighb_highy) ! Higher-y direction
109  bc_type = af_bc_neumann
110  box%cc(1:nc, nc+1, 1:nc, iv) = 0.0_dp
111  case (a3_neighb_lowz) ! Lower-z direction
112  bc_type = af_bc_neumann
113  box%cc(1:nc, 1:nc, 0, iv) = 0.0_dp
114  case (a3_neighb_highz) ! Higher-z direction
115  bc_type = af_bc_neumann
116  box%cc(1:nc, 1:nc, nc+1, iv) = 0.0_dp
117  end select
118 
119  end subroutine boundary_method
121 
122 end program boundary_conditions_3d