48 type(af_t),
intent(inout) :: tree
49 type(cfg_t),
intent(inout) :: cfg
50 logical,
intent(in) :: is_used
51 real(dp),
intent(in) :: eta
53 character(len=12) :: name
54 character(len=12) :: author =
"Bourdon-3"
55 real(dp) :: frac_o2, dummy(0)
58 call cfg_add_get(cfg,
"photoi_helmh%author", author, &
59 "Can be Bourdon-3 (default), Bourdon-2, Luque or custom")
60 call cfg_add(cfg,
"photoi_helmh%lambdas", dummy, &
61 "Lambdas to use in Helmholtz eq; unit 1/(m bar)", .true.)
62 call cfg_add(cfg,
"photoi_helmh%coeffs", dummy, &
63 "Weights corresponding to the lambdas; unit 1/(m bar)^2", .true.)
64 call cfg_add_get(cfg,
"photoi_helmh%max_rel_residual", max_rel_residual, &
65 "Maximum residual for Helmholtz solver, relative to max(|rhs|)")
69 if (.not. is_used)
return
82 if (frac_o2 <= 0.0_dp) error stop
"Photoionization: no oxygen present"
84 lambdas = [4425.38_dp, 750.06_dp]
85 coeffs = [337557.38_dp, 19972.14_dp]
93 if (abs(eta - 1.0_dp) > 0) &
94 error stop
"With Luque photoionization, photoi%eta should be 1.0"
96 if (frac_o2 <= 0.0_dp) error stop
"Photoionization: no oxygen present"
100 lambdas = [7305.62_dp, 44081.25_dp]
101 coeffs = [11814508.38_dp, 998607256.0_dp]
111 if (frac_o2 <= 0.0_dp) error stop
"Photoionization: no oxygen present"
115 lambdas = [4147.85_dp, 10950.93_dp, 66755.67_dp]
116 coeffs = [1117314.935_dp, 28692377.5_dp, 2748842283.0_dp]
126 call cfg_get_size(cfg,
"photoi_helmh%lambdas", n_modes)
127 if (n_modes < 1) error stop
"Custom photoionization lambdas and coeffs missing."
128 allocate(lambdas(n_modes))
129 allocate(coeffs(n_modes))
130 call cfg_get(cfg,
"photoi_helmh%lambdas", lambdas)
131 call cfg_get(cfg,
"photoi_helmh%coeffs", coeffs)
137 print *,
"Unknown photoi_helmh_author: ", trim(author)
142 allocate(i_modes(n_modes))
144 write(name,
"(A,I0)")
"helmh_", n
145 call af_add_cc_variable(tree, trim(name), write_out=.false., ix=i_modes(n))
149 allocate(mg_helm(n_modes))
152 mg_helm(n)%i_phi = i_modes(n)
153 mg_helm(n)%i_rhs =
i_rhs
154 mg_helm(n)%i_tmp =
i_tmp
156 mg_helm(n)%helmholtz_lambda = lambdas(n)**2
157 mg_helm(n)%operator_type = mg_normal_operator
158 mg_helm(n)%prolongation_type = mg_prolong_linear
163 type(af_t),
intent(inout) :: tree
164 integer,
intent(in) :: i_photo
166 integer :: n, lvl, i, id
167 real(dp) :: residu, max_rhs
169 call af_tree_clear_cc(tree, i_photo)
171 call af_tree_maxabs_cc(tree, mg_helm(1)%i_rhs, max_rhs)
172 max_rhs = max(max_rhs, sqrt(epsilon(1.0_dp)))
175 if (.not. mg_helm(n)%initialized)
then
178 mg_helm(n)%prolongation_key = mg_helm(1)%prolongation_key
181 call mg_init(tree, mg_helm(n))
184 do i = 1, max_fmg_cycles
185 call mg_fas_fmg(tree, mg_helm(n), .true., .true.)
186 call af_tree_maxabs_cc(tree, mg_helm(n)%i_tmp, residu)
188 if (residu/max_rhs < max_rel_residual)
exit
192 do lvl = 1, tree%highest_lvl
194 do i = 1,
size(tree%lvls(lvl)%leaves)
195 id = tree%lvls(lvl)%leaves(i)
196 tree%boxes(id)%cc(dtimes(:), i_photo) = &
197 tree%boxes(id)%cc(dtimes(:), i_photo) - &
198 coeffs(n) * tree%boxes(id)%cc(dtimes(:), i_modes(n))
211 type(box_t),
intent(in) :: box
212 integer,
intent(in) :: nb
213 integer,
intent(in) :: iv
214 real(dp),
intent(in) :: coords(ndim, box%n_cell**(ndim-1))
215 real(dp),
intent(out) :: bc_val(box%n_cell**(ndim-1))
216 integer,
intent(out) :: bc_type
221 if (af_neighb_dim(nb) == ndim)
then
222 bc_type = af_bc_dirichlet
225 bc_type = af_bc_neumann