Skip to content

Commit

Permalink
Expose electrostatic solver that only accounts for boundary potentials
Browse files Browse the repository at this point in the history
  • Loading branch information
RemiLehe committed Dec 11, 2024
1 parent 2318fd7 commit e3c6875
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 45 deletions.
9 changes: 9 additions & 0 deletions Source/FieldSolver/ElectrostaticSolvers/ElectrostaticSolver.H
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ public:
std::array<amrex::Real, 3> beta
) const;

/** Compute the potential `phi` by solving the Poisson equation with the
simulation specific boundary conditions and boundary values, then add the
E field due to that `phi` to `Efield_fp`.
* \param[in] Efield Efield updated to include potential gradient from boundary condition
*/
void AddBoundaryField (
ablastr::fields::MultiLevelVectorField& Efield
);

/** Maximum levels for the electrostatic solver grid */
int num_levels;

Expand Down
36 changes: 36 additions & 0 deletions Source/FieldSolver/ElectrostaticSolvers/ElectrostaticSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,3 +541,39 @@ void ElectrostaticSolver::computeB (
}
}
}

void ElectrostaticSolver::AddBoundaryField (ablastr::fields::MultiLevelVectorField& Efield_fp)
{
WARPX_PROFILE("RelativisticExplicitES::AddBoundaryField");

auto & warpx = WarpX::GetInstance();

// Allocate fields for charge and potential
Vector<std::unique_ptr<MultiFab>> rho(num_levels);
Vector<std::unique_ptr<MultiFab>> phi(num_levels);
// Use number of guard cells used for local deposition of rho
const amrex::IntVect ng = warpx.get_ng_depos_rho();
for (int lev = 0; lev < num_levels; lev++) {
BoxArray nba = warpx.boxArray(lev);
nba.surroundingNodes();
rho[lev] = std::make_unique<amrex::MultiFab>(nba, warpx.DistributionMap(lev), 1, ng);
rho[lev]->setVal(0.);
phi[lev] = std::make_unique<amrex::MultiFab>(nba, warpx.DistributionMap(lev), 1, 1);
phi[lev]->setVal(0.);
}

// Set the boundary potentials appropriately
setPhiBC( amrex::GetVecOfPtrs(phi), warpx.gett_new(0));

// beta is zero for boundaries
const std::array<Real, 3> beta = {0._rt};

// Compute the potential phi, by solving the Poisson equation
computePhi( amrex::GetVecOfPtrs(rho), amrex::GetVecOfPtrs(phi),
beta, self_fields_required_precision,
self_fields_absolute_tolerance, self_fields_max_iters,
self_fields_verbosity );

// Compute the corresponding electric field, from the potential phi.
computeE( Efield_fp, amrex::GetVecOfPtrs(phi), beta );
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,6 @@ public:
ablastr::fields::MultiLevelVectorField& Bfield_fp
);

/** Compute the potential `phi` by solving the Poisson equation with the
simulation specific boundary conditions and boundary values, then add the
E field due to that `phi` to `Efield_fp`.
* \param[in] Efield Efield updated to include potential gradient from boundary condition
*/
void AddBoundaryField (
ablastr::fields::MultiLevelVectorField& Efield
);
};

#endif // WARPX_RELATIVISTICEXPLICITES_H_
Original file line number Diff line number Diff line change
Expand Up @@ -136,40 +136,4 @@ void RelativisticExplicitES::AddSpaceChargeField (
computeE( Efield_fp, amrex::GetVecOfPtrs(phi), beta );
computeB( Bfield_fp, amrex::GetVecOfPtrs(phi), beta );

}

void RelativisticExplicitES::AddBoundaryField (ablastr::fields::MultiLevelVectorField& Efield_fp)
{
WARPX_PROFILE("RelativisticExplicitES::AddBoundaryField");

auto & warpx = WarpX::GetInstance();

// Allocate fields for charge and potential
Vector<std::unique_ptr<MultiFab>> rho(num_levels);
Vector<std::unique_ptr<MultiFab>> phi(num_levels);
// Use number of guard cells used for local deposition of rho
const amrex::IntVect ng = warpx.get_ng_depos_rho();
for (int lev = 0; lev < num_levels; lev++) {
BoxArray nba = warpx.boxArray(lev);
nba.surroundingNodes();
rho[lev] = std::make_unique<amrex::MultiFab>(nba, warpx.DistributionMap(lev), 1, ng);
rho[lev]->setVal(0.);
phi[lev] = std::make_unique<amrex::MultiFab>(nba, warpx.DistributionMap(lev), 1, 1);
phi[lev]->setVal(0.);
}

// Set the boundary potentials appropriately
setPhiBC( amrex::GetVecOfPtrs(phi), warpx.gett_new(0));

// beta is zero for boundaries
const std::array<Real, 3> beta = {0._rt};

// Compute the potential phi, by solving the Poisson equation
computePhi( amrex::GetVecOfPtrs(rho), amrex::GetVecOfPtrs(phi),
beta, self_fields_required_precision,
self_fields_absolute_tolerance, self_fields_max_iters,
self_fields_verbosity );

// Compute the corresponding electric field, from the potential phi.
computeE( Efield_fp, amrex::GetVecOfPtrs(phi), beta );
}
}
8 changes: 8 additions & 0 deletions Source/Python/WarpX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
# include <FieldSolver/SpectralSolver/SpectralSolver.H>
# endif // RZ ifdef
#endif // use PSATD ifdef
#include <FieldSolver/ElectrostaticSolvers/RelativisticExplicitES.H>
#include <FieldSolver/WarpX_FDTD.H>
#include <Filter/NCIGodfreyFilter.H>
#include <Initialization/ExternalField.H>
Expand Down Expand Up @@ -274,6 +275,13 @@ The physical fields in WarpX have the following naming:
[] (WarpX& wx) { wx.Synchronize(); },
"Synchronize particle velocities and positions."
)
.def("add_boundary_electrostatic_field",
[] (WarpX& wx) {
auto Efield_fp = wx.m_fields.get_mr_levels_alldirs("Efield_fp", wx.maxLevel());
wx.GetElectrostaticSolver().AddBoundaryField( Efield_fp );
},
"Compute the electric field due to the potential specified on the domain boundaries and embedded boundaries."
)
;

py::class_<warpx::Config>(m, "Config")
Expand Down

0 comments on commit e3c6875

Please sign in to comment.