7 #ifndef ABLASTR_POISSON_SOLVER_H
8 #define ABLASTR_POISSON_SOLVER_H
19 #if defined(ABLASTR_USE_FFT) && defined(WARPX_DIM_3D)
28 #include <AMReX_Config.H>
49 #if defined(AMREX_USE_EB) || defined(WARPX_DIM_RZ)
95 typename T_BoundaryHandler,
96 typename T_PostPhiCalculationFunctor = std::nullopt_t,
97 typename T_FArrayBoxFactory =
void
102 std::array<amrex::Real, 3>
const beta,
103 amrex::Real
const relative_tolerance,
104 amrex::Real absolute_tolerance,
111 T_BoundaryHandler
const boundary_handler,
112 bool is_solver_igf_on_lev0,
113 bool const do_single_precision_comms =
false,
115 [[maybe_unused]] T_PostPhiCalculationFunctor post_phi_calculation = std::nullopt,
116 [[maybe_unused]] std::optional<amrex::Real const> current_time = std::nullopt,
120 using namespace amrex::literals;
124 if (!rel_ref_ratio.has_value()) {
126 "rel_ref_ratio must be set if mesh-refinement is used");
130 auto const finest_level =
static_cast<int>(rho.
size() - 1);
133 amrex::Real max_norm_b = 0.0;
134 for (
int lev=0; lev<=finest_level; lev++) {
135 max_norm_b =
amrex::max(max_norm_b, rho[lev]->norm0());
139 const bool always_use_bnorm = (max_norm_b > 0);
140 if (!always_use_bnorm) {
141 if (absolute_tolerance == 0.0) { absolute_tolerance = amrex::Real(1e-6); }
143 "ElectrostaticSolver",
144 "Max norm of rho is 0",
149 #if !(defined(AMREX_USE_EB) || defined(WARPX_DIM_RZ))
155 for (
int lev=0; lev<=finest_level; lev++) {
158 #if defined(WARPX_DIM_1D_Z)
160 #elif defined(WARPX_DIM_XZ) || defined(WARPX_DIM_RZ)
166 #if !defined(ABLASTR_USE_FFT)
168 "Must compile with FFT support to use the IGF solver!");
171 #if !defined(WARPX_DIM_3D)
173 "The FFT Poisson solver is currently only implemented for 3D!");
176 #if (defined(ABLASTR_USE_FFT) && defined(WARPX_DIM_3D))
178 if(is_solver_igf_on_lev0 && lev==0){
180 {
AMREX_D_DECL(geom[lev].CellSize(0)/std::sqrt(1._rt-beta_solver[0]*beta_solver[0]),
181 geom[lev].CellSize(1)/std::sqrt(1._rt-beta_solver[1]*beta_solver[1]),
182 geom[lev].CellSize(2)/std::sqrt(1._rt-beta_solver[2]*beta_solver[2]))};
183 if ( max_norm_b == 0 ) {
195 rho[lev]->mult(-1._rt/
ep0);
197 #if !(defined(AMREX_USE_EB) || defined(WARPX_DIM_RZ))
200 {
AMREX_D_DECL(geom[lev].CellSize(0)/std::sqrt(1._rt-beta_solver[0]*beta_solver[0]),
201 geom[lev].CellSize(1)/std::sqrt(1._rt-beta_solver[1]*beta_solver[1]),
202 geom[lev].CellSize(2)/std::sqrt(1._rt-beta_solver[2]*beta_solver[2]))};
203 int max_semicoarsening_level = 0;
204 int semicoarsening_direction = -1;
205 const auto min_dir =
static_cast<int>(std::distance(dx_scaled.begin(),
206 std::min_element(dx_scaled.begin(),dx_scaled.end())));
207 const auto max_dir =
static_cast<int>(std::distance(dx_scaled.begin(),
208 std::max_element(dx_scaled.begin(),dx_scaled.end())));
209 if (dx_scaled[max_dir] > dx_scaled[min_dir]) {
210 semicoarsening_direction = max_dir;
211 max_semicoarsening_level =
static_cast<int>
212 (std::log2(dx_scaled[max_dir]/dx_scaled[min_dir]));
214 if (max_semicoarsening_level > 0) {
221 #if defined(AMREX_USE_EB) || defined(WARPX_DIM_RZ)
226 #if defined(AMREX_USE_EB)
227 , {eb_farray_box_factory.value()[lev]}
234 #if defined(WARPX_DIM_RZ)
235 linop.
setSigma({0._rt, 1._rt-beta_solver[1]*beta_solver[1]});
238 1._rt-beta_solver[0]*beta_solver[0],
239 1._rt-beta_solver[1]*beta_solver[1],
240 1._rt-beta_solver[2]*beta_solver[2])});
243 #if defined(AMREX_USE_EB)
246 if (boundary_handler.phi_EB_only_t) {
247 linop.setEBDirichlet(boundary_handler.potential_eb_t(current_time.value()));
250 linop.setEBDirichlet(boundary_handler.getPhiEB(current_time.value()));
261 linop.setDomainBC( boundary_handler.lobc, boundary_handler.hibc );
276 mlmg.
solve( {phi[lev]}, {rho[lev]},
277 relative_tolerance, absolute_tolerance );
284 if (lev < finest_level) {
290 const int ncomp = linop.getNComp();
309 do_single_precision_comms,
315 #pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
330 if constexpr (!std::is_same_v<T_PostPhiCalculationFunctor, std::nullopt_t>) {
331 if (post_phi_calculation.has_value()) {
332 post_phi_calculation.value()(mlmg, lev);
#define AMREX_D_DECL(a, b, c)
#define ABLASTR_PROFILE(fname)
Definition: ProfilerWrapper.H:13
#define ABLASTR_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition: TextMsg.H:75
BoxArray & coarsen(int refinement_ratio)
void setDomainBndry(value_type val, const Geometry &geom)
Array4< typename FabArray< FArrayBox >::value_type const > array(const MFIter &mfi) const noexcept
void setSigma(Array< Real, AMREX_SPACEDIM > const &a_sigma) noexcept
void setVerbose(int v) noexcept
void setAlwaysUseBNorm(int flag) noexcept
void setFinalFillBC(int flag) noexcept
RT solve(const Vector< AMF * > &a_sol, const Vector< AMF const * > &a_rhs, RT a_tol_rel, RT a_tol_abs, const char *checkpoint_file=nullptr)
void setMaxIter(int n) noexcept
void setBeta(Array< Real, AMREX_SPACEDIM > const &a_beta) noexcept
Long size() const noexcept
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void interp(int j, int k, int l, amrex::Array4< amrex::Real > const &fine, amrex::Array4< amrex::Real const > const &crse, const amrex::IntVect r_ratio, IntVect const &type) noexcept
Definition: Interpolate_K.H:9
Definition: constant.H:40
static constexpr auto ep0
vacuum permittivity: dielectric permittivity of vacuum [F/m]
Definition: constant.H:46
Definition: IntegratedGreenFunctionSolver.cpp:33
void computePhiIGF(amrex::MultiFab const &rho, amrex::MultiFab &phi, std::array< amrex::Real, 3 > const &cell_size, amrex::BoxArray const &ba)
Compute the electrostatic potential using the Integrated Green Function method as in http://dx....
Definition: IntegratedGreenFunctionSolver.cpp:36
void computePhi(amrex::Vector< amrex::MultiFab * > const &rho, amrex::Vector< amrex::MultiFab * > &phi, std::array< amrex::Real, 3 > const beta, amrex::Real const relative_tolerance, amrex::Real absolute_tolerance, int const max_iters, int const verbosity, amrex::Vector< amrex::Geometry > const &geom, amrex::Vector< amrex::DistributionMapping > const &dmap, amrex::Vector< amrex::BoxArray > const &grids, utils::enums::GridType grid_type, T_BoundaryHandler const boundary_handler, bool is_solver_igf_on_lev0, bool const do_single_precision_comms=false, std::optional< amrex::Vector< amrex::IntVect > > rel_ref_ratio=std::nullopt, [[maybe_unused]] T_PostPhiCalculationFunctor post_phi_calculation=std::nullopt, [[maybe_unused]] std::optional< amrex::Real const > current_time=std::nullopt, [[maybe_unused]] std::optional< amrex::Vector< T_FArrayBoxFactory const * > > eb_farray_box_factory=std::nullopt)
Definition: PoissonSolver.H:100
void ParallelCopy(amrex::MultiFab &dst, const amrex::MultiFab &src, int src_comp, int dst_comp, int num_comp, const amrex::IntVect &src_nghost, const amrex::IntVect &dst_nghost, bool do_single_precision_comms, const amrex::Periodicity &period, amrex::FabArrayBase::CpOp op)
Definition: Communication.cpp:28
GridType
Definition: Enums.H:17
void WMRecordWarning(const std::string &topic, const std::string &text, const WarnPriority &priority=WarnPriority::medium)
Helper function to abbreviate the call to WarnManager::GetInstance().RecordWarning (recording a warni...
Definition: WarnManager.cpp:318
void ReduceRealMax(Vector< std::reference_wrapper< Real > > const &)
DistributionMapping const & DistributionMap(FabArrayBase const &fa)
AMREX_GPU_HOST_DEVICE constexpr AMREX_FORCE_INLINE const T & max(const T &a, const T &b) noexcept
IntVectND< AMREX_SPACEDIM > IntVect
bool TilingIfNotGPU() noexcept
std::enable_if_t< std::is_integral_v< T > > ParallelFor(TypeList< CTOs... >, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
beta
Definition: stencil.py:434
Definition: Interpolate.H:33
LPInfo & setSemicoarsening(bool x) noexcept
LPInfo & setMaxSemicoarseningLevel(int n) noexcept
LPInfo & setSemicoarseningDirection(int n) noexcept