2 program space_plasma_2d
8 integer,
parameter :: i_cs_ion = 1
9 integer,
parameter :: i_cs = 2
10 integer,
parameter :: i_o = 3
11 integer,
parameter :: i_o_min = 4
12 integer,
parameter :: i_cs_ion_old = 5
13 integer,
parameter :: i_cs_old = 6
14 integer,
parameter :: i_o_old = 7
15 integer,
parameter :: i_o_min_old = 8
18 integer,
parameter :: box_size = 8
19 real(dp),
parameter :: domain_len = 3000.0_dp
20 real(dp),
parameter :: dr = domain_len / box_size
21 integer,
parameter :: min_refinement_lvl = 4
22 integer,
parameter :: max_refinement_lvl = 7
25 real(dp) :: dt_adapt = 60.0_dp
26 real(dp) :: dt_output = 60.0_dp
27 real(dp) :: end_time = 3600.0_dp
30 real(dp),
parameter :: dc_cs_ion_parallel = 10.0_dp
31 real(dp),
parameter :: dc_cs_ion_perpendicular = 2.0_dp
32 real(dp),
parameter :: dc_cs = 20.0_dp
33 real(dp),
parameter :: k_attachment = 1.0e-3_dp
34 real(dp),
parameter :: k_recombination = 1.0e-3_dp
35 real(dp),
parameter :: k_photoionization = 5.0e-4_dp
36 real(dp),
parameter :: initial_cs_density = 1.0_dp
37 real(dp),
parameter :: initial_ionization_fraction = 0.5_dp
38 real(dp),
parameter :: initial_o_density = 1e-7
39 real(dp),
parameter :: initial_sigma = 50.0_dp
41 real(dp) :: max_diffusion_coeff
43 type(ref_info_t) :: refine_info
44 integer :: ix_list(2, 1)
45 integer :: time_steps, output_cnt
46 integer :: i, n, n_steps
49 character(len=100) :: fname
51 print *,
"Running space_plasma_2d" 52 print *,
"Number of threads", af_get_max_threads()
60 r_min=[-0.5_dp, -0.5_dp] * domain_len, &
61 cc_names=[
character(len=10) ::
"Cs_ion",
"Cs",
"O",
"O_min", &
62 "Cs_ion_old",
"Cs_old",
"O_old",
"O_min_old"])
65 call a2_set_cc_methods(tree, i_cs_ion, a2_bc_neumann_zero, a2_gc_interp_lim)
66 call a2_set_cc_methods(tree, i_cs, a2_bc_neumann_zero, a2_gc_interp_lim)
67 call a2_set_cc_methods(tree, i_o, a2_bc_neumann_zero, a2_gc_interp_lim)
68 call a2_set_cc_methods(tree, i_o_min, a2_bc_neumann_zero, a2_gc_interp_lim)
71 ix_list(:, 1) = [1, 1]
74 call a2_set_base(tree, 1, ix_list)
80 call a2_loop_box(tree, set_initial_condition)
81 call a2_adjust_refinement(tree, &
85 if (refine_info%n_add == 0)
exit 88 call a2_gc_tree(tree, i_cs_ion, a2_gc_interp_lim, a2_bc_neumann_zero)
89 call a2_gc_tree(tree, i_cs, a2_gc_interp_lim, a2_bc_neumann_zero)
91 call a2_print_info(tree)
95 max_diffusion_coeff = max(dc_cs_ion_parallel, dc_cs_ion_perpendicular, &
100 time_steps = time_steps + 1
101 dr_min = a2_min_dr(tree)
104 dt = 0.25_dp * minval(dr_min)**2 / max_diffusion_coeff
107 dt = min(dt, 0.5_dp/(k_attachment*initial_cs_density), &
108 0.5_dp/(k_recombination*initial_cs_density), &
109 0.5_dp/k_photoionization)
111 n_steps = ceiling(dt_adapt/dt)
112 dt = dt_adapt / n_steps
114 if (output_cnt * dt_output <= time)
then 115 output_cnt = output_cnt + 1
116 write(fname,
"(A,I0)")
"space_plasma_2d_", output_cnt
117 call a2_gc_tree(tree, i_cs_ion, a2_gc_interp_lim, a2_bc_neumann_zero)
118 call a2_gc_tree(tree, i_cs, a2_gc_interp_lim, a2_bc_neumann_zero)
119 call a2_gc_tree(tree, i_o, a2_gc_interp_lim, a2_bc_neumann_zero)
120 call a2_gc_tree(tree, i_o_min, a2_gc_interp_lim, a2_bc_neumann_zero)
122 call a2_write_silo(tree, trim(fname), output_cnt, time, &
123 ixs_cc=[i_cs_ion, i_cs, i_o, i_o_min], dir=
"output")
126 if (time > end_time)
exit 130 call a2_tree_copy_cc(tree, i_cs_ion, i_cs_ion_old)
131 call a2_tree_copy_cc(tree, i_cs, i_cs_old)
132 call a2_tree_copy_cc(tree, i_o, i_o_old)
133 call a2_tree_copy_cc(tree, i_o_min, i_o_min_old)
138 call a2_loop_boxes(tree, get_fluxes)
141 call a2_consistent_fluxes(tree, [i_cs_ion, i_cs])
144 call a2_loop_box_arg(tree, update_solution, [dt])
147 call a2_restrict_tree(tree, i_cs_ion)
148 call a2_restrict_tree(tree, i_cs)
152 call a2_loop_box(tree, average_solution)
157 call a2_gc_tree(tree, i_cs_ion, a2_gc_interp_lim, a2_bc_neumann_zero)
158 call a2_gc_tree(tree, i_cs, a2_gc_interp_lim, a2_bc_neumann_zero)
160 call a2_adjust_refinement(tree, refine_routine, refine_info, 1)
166 subroutine refine_routine(box, cell_flags)
167 type(box2_t),
intent(in) :: box
168 integer,
intent(out) :: cell_flags(box%n_cell, box%n_cell)
174 do j = 1, nc;
do i = 1, nc
175 diff = abs(box%cc(i+1, j, i_cs_ion) + &
176 box%cc(i-1, j, i_cs_ion) + &
177 box%cc(i, j+1, i_cs_ion) + &
178 box%cc(i, j-1, i_cs_ion) - &
179 4 * box%cc(i, j, i_cs_ion)) * box%dr / &
180 (initial_cs_density * initial_ionization_fraction)
182 if (box%lvl < min_refinement_lvl .or. diff > 0.1_dp &
183 .and. box%lvl < max_refinement_lvl)
then 184 cell_flags(i, j) = af_do_ref
185 else if (diff < 0.01_dp)
then 186 cell_flags(i, j) = af_rm_ref
188 cell_flags(i, j) = af_keep_ref
191 end subroutine refine_routine
194 subroutine set_initial_condition(box)
195 type(box2_t),
intent(inout) :: box
197 real(dp) :: distance, density
200 do j = 0, nc+1;
do i = 0, nc+1
201 distance = norm2(a2_r_cc(box, [i, j]))
202 density = exp(-0.5_dp * distance**2/initial_sigma**2)
204 box%cc(i, j, i_cs_ion) = initial_ionization_fraction * density
205 box%cc(i, j, i_cs) = (1 - initial_ionization_fraction) * density
206 box%cc(i, j, i_o) = initial_o_density
208 end subroutine set_initial_condition
210 subroutine get_fluxes(boxes, id)
212 type(box2_t),
intent(inout) :: boxes(:)
213 integer,
intent(in) :: id
216 real(dp),
allocatable :: diff_coeff(:, :, :)
218 nc = boxes(id)%n_cell
219 inv_dx = 1/boxes(id)%dr
221 allocate(diff_coeff(1:nc+1, 1:nc+1, 2))
223 call a2_gc_box(boxes, id, i_cs_ion, a2_gc_interp_lim, a2_bc_neumann_zero)
224 call a2_gc_box(boxes, id, i_cs, a2_gc_interp_lim, a2_bc_neumann_zero)
226 diff_coeff(:, :, 1) = dc_cs_ion_parallel
227 diff_coeff(:, :, 2) = dc_cs_ion_perpendicular
228 call flux_diff_2d(boxes(id)%cc(:, :, i_cs_ion), diff_coeff, inv_dx, nc, 1)
229 boxes(id)%fc(:, :, :, i_cs_ion) = diff_coeff
231 diff_coeff(:, :, :) = dc_cs
232 call flux_diff_2d(boxes(id)%cc(:, :, i_cs), diff_coeff, inv_dx, nc, 1)
233 boxes(id)%fc(:, :, :, i_cs) = diff_coeff
235 end subroutine get_fluxes
238 subroutine update_solution(box, dt)
239 type(box2_t),
intent(inout) :: box
240 real(dp),
intent(in) :: dt(:)
241 real(dp) :: inv_dr, recombination, photoionization
242 real(dp) :: attachment, electron_density
250 electron_density = box%cc(i, j, i_cs_ion) - box%cc(i, j, i_o_min)
251 recombination = dt(1) * k_recombination * box%cc(i, j, i_cs_ion)**2
252 photoionization = dt(1) * k_photoionization * box%cc(i, j, i_cs)
253 box%cc(i, j, i_cs_ion) = box%cc(i, j, i_cs_ion) - recombination + photoionization
254 box%cc(i, j, i_cs) = box%cc(i, j, i_cs) + recombination - photoionization
256 attachment = dt(1) * k_attachment * box%cc(i, j, i_o) * electron_density
257 box%cc(i, j, i_o) = box%cc(i, j, i_o) - attachment
258 box%cc(i, j, i_o_min) = box%cc(i, j, i_o_min) + attachment
261 box%cc(i, j, i_cs_ion) = box%cc(i, j, i_cs_ion) + dt(1) * inv_dr * ( &
262 box%fc(i, j, 1, i_cs_ion) - box%fc(i+1, j, 1, i_cs_ion) + &
263 box%fc(i, j, 2, i_cs_ion) - box%fc(i, j+1, 2, i_cs_ion))
264 box%cc(i, j, i_cs) = box%cc(i, j, i_cs) + dt(1) * inv_dr * ( &
265 box%fc(i, j, 1, i_cs) - box%fc(i+1, j, 1, i_cs) + &
266 box%fc(i, j, 2, i_cs) - box%fc(i, j+1, 2, i_cs))
269 end subroutine update_solution
272 subroutine average_solution(box)
273 type(box2_t),
intent(inout) :: box
275 box%cc(:, :, :) = 0.5_dp * (box%cc(:, :, :) + &
277 end subroutine average_solution
279 end program space_plasma_2d
Module containing a couple simple flux schemes for scalar advection/diffusion problems.
Module which contains all Afivo modules, so that a user does not have to include them separately...