107 amrex::Real relative_tolerance,
108 amrex::Real absolute_tolerance,
115 bool is_solver_igf_on_lev0,
116 bool eb_enabled =
false,
117 bool do_single_precision_comms =
false,
119 [[maybe_unused]] T_PostPhiCalculationFunctor post_phi_calculation = std::nullopt,
120 [[maybe_unused]] T_BoundaryHandler
const boundary_handler = std::nullopt,
121 [[maybe_unused]] std::optional<amrex::Real const> current_time = std::nullopt,
124 using namespace amrex::literals;
128 if (!rel_ref_ratio.has_value()) {
130 "rel_ref_ratio must be set if mesh-refinement is used");
134#if !defined(AMREX_USE_EB)
136 "Embedded boundary solve requested but not compiled in");
138 if (eb_enabled && std::is_same_v<void, T_FArrayBoxFactory>) {
139 throw std::runtime_error(
"EB requested by eb_farray_box_factory not provided!");
143 "FFT solver cannot be used with effective potential Poisson solve");
146 constexpr bool is_rz =
true;
148 constexpr bool is_rz =
false;
151 auto const finest_level =
static_cast<int>(rho.
size() - 1);
159 for (
int lev=0; lev<=finest_level; lev++) {
163 rho[lev]->mult(-1._rt/
ep0);
165 std::unique_ptr<amrex::MLNodeLinOp> linop;
169#if defined(AMREX_USE_EB)
170 auto linop_nodelap = std::make_unique<amrex::MLEBNodeFDLaplacian>();
171 linop_nodelap->define(
178 if constexpr (!std::is_same_v<T_BoundaryHandler, std::nullopt_t>) {
181 if (boundary_handler.phi_EB_only_t) {
182 linop_nodelap->setEBDirichlet(boundary_handler.potential_eb_t(current_time.value()));
184 linop_nodelap->setEBDirichlet(boundary_handler.getPhiEB(current_time.value()));
187 linop_nodelap->setSigma(lev, sigma);
188 linop = std::move(linop_nodelap);
193 auto linop_nodelap = std::make_unique<amrex::MLEBNodeFDLaplacian>();
194 linop_nodelap->define(
200 linop_nodelap->setRZ(
true);
201 linop_nodelap->setSigma(lev, sigma);
202 linop = std::move(linop_nodelap);
206 auto linop_nodelap = std::make_unique<amrex::MLNodeLaplacian>();
207 linop_nodelap->define(
213 linop_nodelap->setSigma(lev, sigma);
214 linop = std::move(linop_nodelap);
218 if constexpr (std::is_same_v<T_BoundaryHandler, std::nullopt_t>) {
220 amrex::LinOpBCType::Dirichlet,
221 amrex::LinOpBCType::Dirichlet,
222 amrex::LinOpBCType::Dirichlet
225 linop->setDomainBC(lobc, hibc);
227 linop->setDomainBC(boundary_handler.lobc, boundary_handler.hibc);
234 mlmg.
setConvergenceNormType((max_norm_b > 0) ? amrex::MLMGNormType::bnorm : amrex::MLMGNormType::greater);
244 mlmg.
solve( {phi[lev]}, {rho[lev]},
245 relative_tolerance, absolute_tolerance );
252 if (lev < finest_level) {
254 const int ncomp = linop->getNComp();
258 do_single_precision_comms,
265 if constexpr (!std::is_same_v<T_PostPhiCalculationFunctor, std::nullopt_t>) {
266 if (post_phi_calculation.has_value()) {
267 post_phi_calculation.value()(mlmg, lev);
270 rho[lev]->mult(-
ep0);