Skip to content

Commit

Permalink
Remove NamedComponentParticleContainer (Use from AMReX) (#5481)
Browse files Browse the repository at this point in the history
This capability has been upstreamed to AMReX.

Co-authored-by: Axel Huebl <[email protected]>
  • Loading branch information
atmyers and ax3l authored Feb 8, 2025
1 parent 86806f9 commit c0eacd9
Show file tree
Hide file tree
Showing 42 changed files with 368 additions and 517 deletions.
2 changes: 1 addition & 1 deletion Docs/source/developers/particles.rst
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ Attribute name ``int``/``real`` Description Wher
Wheeler process physics is used.
==================== ================ ================================== ===== ==== ======================

WarpX allows extra runtime attributes to be added to particle containers (through ``NewRealComp("attrname")`` or ``NewIntComp("attrname")``).
WarpX allows extra runtime attributes to be added to particle containers (through ``AddRealComp("attrname")`` or ``AddIntComp("attrname")``).
The attribute name can then be used to access the values of that attribute.
For example, using a particle iterator, ``pti``, to loop over the particles the command ``pti.GetAttribs(particle_comps["attrname"]).dataPtr();`` will return the values of the ``"attrname"`` attribute.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ def add_particles():
##########################

assert elec_wrapper.nps == 270 / (2 - args.unique)
assert elec_wrapper.particle_container.get_comp_index("w") == 2
assert elec_wrapper.particle_container.get_comp_index("newPid") == 6
assert elec_wrapper.particle_container.get_real_comp_index("w") == 2
assert elec_wrapper.particle_container.get_real_comp_index("newPid") == 6

new_pid_vals = elec_wrapper.get_particle_real_arrays("newPid", 0)
for vals in new_pid_vals:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@
elec_count = elec_wrapper.nps

# check that the runtime attributes have the right indices
assert elec_wrapper.particle_container.get_comp_index("prev_x") == 6
assert elec_wrapper.particle_container.get_comp_index("prev_z") == 7
assert elec_wrapper.particle_container.get_real_comp_index("prev_x") == 6
assert elec_wrapper.particle_container.get_real_comp_index("prev_z") == 7

# sanity check that the prev_z values are reasonable and
# that the correct number of values are returned
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@
np.random.seed(30025025)

electron_wrapper = particle_containers.ParticleContainerWrapper("electrons")
electron_wrapper.add_real_comp("newPid")
if not sim.amr_restart:
electron_wrapper.add_real_comp("newPid")


def add_particles():
Expand Down Expand Up @@ -140,8 +141,8 @@ def add_particles():
##########################

assert electron_wrapper.nps == 90
assert electron_wrapper.particle_container.get_comp_index("w") == 2
assert electron_wrapper.particle_container.get_comp_index("newPid") == 6
assert electron_wrapper.particle_container.get_real_comp_index("w") == 2
assert electron_wrapper.particle_container.get_real_comp_index("newPid") == 6

new_pid_vals = electron_wrapper.get_particle_real_arrays("newPid", 0)
for vals in new_pid_vals:
Expand Down
16 changes: 9 additions & 7 deletions Python/pywarpx/particle_containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ def add_particles(
# --- Note that the velocities are handled separately and not included in attr
# --- (even though they are stored as attributes in the C++)
for key, vals in kwargs.items():
attr[:, self.particle_container.get_comp_index(key) - built_in_attrs] = vals
attr[
:, self.particle_container.get_real_comp_index(key) - built_in_attrs
] = vals

nattr_int = 0
attr_int = np.empty([0], dtype=np.int32)
Expand Down Expand Up @@ -264,7 +266,7 @@ def get_particle_real_arrays(self, comp_name, level, copy_to_host=False):
List of arrays
The requested particle array data
"""
comp_idx = self.particle_container.get_comp_index(comp_name)
comp_idx = self.particle_container.get_real_comp_index(comp_name)

data_array = []
for pti in libwarpx.libwarpx_so.WarpXParIter(self.particle_container, level):
Expand Down Expand Up @@ -309,7 +311,7 @@ def get_particle_int_arrays(self, comp_name, level, copy_to_host=False):
List of arrays
The requested particle array data
"""
comp_idx = self.particle_container.get_icomp_index(comp_name)
comp_idx = self.particle_container.get_int_comp_index(comp_name)

data_array = []
for pti in libwarpx.libwarpx_so.WarpXParIter(self.particle_container, level):
Expand Down Expand Up @@ -842,16 +844,16 @@ def get_particle_boundary_buffer(self, species_name, boundary, comp_name, level)
)
data_array = []
# loop over the real attributes
if comp_name in part_container.real_comp_names:
comp_idx = part_container.real_comp_names[comp_name]
if comp_name in part_container.real_soa_names:
comp_idx = part_container.get_real_comp_index(comp_name)
for ii, pti in enumerate(
libwarpx.libwarpx_so.BoundaryBufferParIter(part_container, level)
):
soa = pti.soa()
data_array.append(xp.array(soa.get_real_data(comp_idx), copy=False))
# loop over the integer attributes
elif comp_name in part_container.int_comp_names:
comp_idx = part_container.int_comp_names[comp_name]
elif comp_name in part_container.int_soa_names:
comp_idx = part_container.get_int_comp_index(comp_name)
for ii, pti in enumerate(
libwarpx.libwarpx_so.BoundaryBufferParIter(part_container, level)
):
Expand Down
11 changes: 11 additions & 0 deletions Source/Diagnostics/BTDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1462,6 +1462,17 @@ BTDiagnostics::InitializeParticleBuffer ()
m_totalParticles_in_buffer[i][isp] = 0;
m_particles_buffer[i][isp] = std::make_unique<PinnedMemoryParticleContainer>(WarpX::GetInstance().GetParGDB());
const int idx = mpc.getSpeciesID(m_output_species_names[isp]);

// SoA component names
{
auto &pc = mpc.GetParticleContainer(idx);
auto rn = pc.GetRealSoANames();
rn.resize(WarpXParticleContainer::NArrayReal); // strip runtime comps
auto in = pc.GetRealSoANames();
in.resize(WarpXParticleContainer::NArrayInt); // strip runtime comps
m_particles_buffer[i][isp]->SetSoACompileTimeNames(rn, in);
}

m_output_species[i].push_back(ParticleDiag(m_diag_name,
m_output_species_names[isp],
mpc.GetParticleContainerPtr(idx),
Expand Down
26 changes: 12 additions & 14 deletions Source/Diagnostics/FlushFormats/FlushFormatCheckpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,27 +209,25 @@ FlushFormatCheckpoint::CheckpointParticles (
write_real_comps.push_back(1);
}

int const compile_time_comps = static_cast<int>(real_names.size());

// get the names of the real comps
// note: skips the mandatory AMREX_SPACEDIM positions for pure SoA
// get the names of the extra real comps
real_names.resize(pc->NumRealComps() - AMREX_SPACEDIM);
write_real_comps.resize(pc->NumRealComps() - AMREX_SPACEDIM);
auto runtime_rnames = pc->getParticleRuntimeComps();
for (auto const& x : runtime_rnames) {
int const i = x.second + PIdx::nattribs - AMREX_SPACEDIM;
real_names[i] = x.first;
write_real_comps[i] = pc->h_redistribute_real_comp[i + compile_time_comps];

// note, skip the required compnent names here
auto rnames = pc->GetRealSoANames();
for (std::size_t index = PIdx::nattribs; index < rnames.size(); ++index) {
std::size_t const i = index - AMREX_SPACEDIM;
real_names[i] = rnames[index];
write_real_comps[i] = pc->h_redistribute_real_comp[index];
}

// and the int comps
int_names.resize(pc->NumIntComps());
write_int_comps.resize(pc->NumIntComps());
auto runtime_inames = pc->getParticleRuntimeiComps();
for (auto const& x : runtime_inames) {
int const i = x.second + 0;
int_names[i] = x.first;
write_int_comps[i] = pc->h_redistribute_int_comp[i+AMREX_SPACEDIM];
auto inames = pc->GetIntSoANames();
for (std::size_t index = 0; index < inames.size(); ++index) {
int_names[index] = inames[index];
write_int_comps[index] = pc->h_redistribute_int_comp[index];
}

pc->Checkpoint(dir, part_diag.getSpeciesName(),
Expand Down
11 changes: 2 additions & 9 deletions Source/Diagnostics/FlushFormats/FlushFormatInSitu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ FlushFormatInSitu::WriteParticles(const amrex::Vector<ParticleDiag>& particle_di
WarpXParticleContainer* pc = particle_diag.getParticleContainer();

// get names of real comps
std::map<std::string, int> real_comps_map = pc->getParticleComps();
std::vector<std::string> real_comps_map = pc->GetRealSoANames();

// WarpXParticleContainer compile-time extra AoS attributes (Real): 0
// WarpXParticleContainer compile-time extra AoS attributes (int): 0
Expand All @@ -46,14 +46,7 @@ FlushFormatInSitu::WriteParticles(const amrex::Vector<ParticleDiag>& particle_di
// not an efficient search, but N is small...
for(int j = 0; j < PIdx::nattribs; ++j)
{
auto rvn_it = real_comps_map.begin();
for (; rvn_it != real_comps_map.end(); ++rvn_it)
if (rvn_it->second == j)
break;
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
rvn_it != real_comps_map.end(),
"WarpX In Situ: SoA real attribute not found");
std::string varname = rvn_it->first;
std::string varname = real_comps_map.at(j);
particle_varnames.push_back(prefix + "_" + varname);
}
// WarpXParticleContainer compile-time extra SoA attributes (int): 0
Expand Down
18 changes: 10 additions & 8 deletions Source/Diagnostics/FlushFormats/FlushFormatPlotfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,13 +372,13 @@ FlushFormatPlotfile::WriteParticles(const std::string& dir,
real_names.push_back("theta");
#endif

// get the names of the real comps

// note: skips the mandatory AMREX_SPACEDIM positions for pure SoA
// get the names of the extra real comps
real_names.resize(tmp.NumRealComps() - AMREX_SPACEDIM);
auto runtime_rnames = tmp.getParticleRuntimeComps();
for (auto const& x : runtime_rnames) {
real_names[x.second + PIdx::nattribs - AMREX_SPACEDIM] = x.first;

// note, skip the required compnent names here
auto rnames = tmp.GetRealSoANames();
for (std::size_t index = PIdx::nattribs; index < rnames.size(); ++index) {
real_names[index - AMREX_SPACEDIM] = rnames[index];
}

// plot any "extra" fields by default
Expand All @@ -390,8 +390,10 @@ FlushFormatPlotfile::WriteParticles(const std::string& dir,

// and the names
int_names.resize(tmp.NumIntComps());
auto runtime_inames = tmp.getParticleRuntimeiComps();
for (auto const& x : runtime_inames) { int_names[x.second+0] = x.first; }
auto inames = tmp.GetIntSoANames();
for (std::size_t index = 0; index < inames.size(); ++index) {
int_names[index] = inames[index];
}

// plot by default
int_flags.resize(tmp.NumIntComps(), 1);
Expand Down
17 changes: 7 additions & 10 deletions Source/Diagnostics/ParticleDiag/ParticleDiag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,23 @@ ParticleDiag::ParticleDiag (
std::fill(m_plot_flags.begin(), m_plot_flags.end(), 0);
bool contains_positions = false;
if (variables[0] != "none"){
std::map<std::string, int> existing_variable_names = pc->getParticleComps();
for (auto& var : variables){
#ifdef WARPX_DIM_RZ
// we reconstruct to Cartesian x,y,z for RZ particle output
existing_variable_names["y"] = PIdx::theta;
// we reconstruct to Cartesian x,y,z for RZ particle output
if (var == "y") { var = "theta"; }
#endif
for (const auto& var : variables){
if (var == "phi") {
// User requests phi on particle. This is *not* part of the variables that
// the particle container carries, and is only added to particles during output.
// Therefore, this case needs to be treated specifically.
m_plot_phi = true;
} else {
const auto search = existing_variable_names.find(var);
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
search != existing_variable_names.end(),
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(pc->HasRealComp(var),
"variables argument '" + var
+"' is not an existing attribute for this species");
m_plot_flags[existing_variable_names.at(var)] = 1;
m_plot_flags[pc->GetRealCompIndex(var)] = 1;

if (var == "x" || var == "y" || var == "z") {
if (var == "x" || var == "y" || var == "z" || var == "theta") {
contains_positions = true;
}
}
Expand All @@ -75,7 +72,7 @@ ParticleDiag::ParticleDiag (
// Always write out theta, whether or not it's requested,
// to be consistent with always writing out r and z.
// TODO: openPMD does a reconstruction to Cartesian, so we can now skip force-writing this
m_plot_flags[pc->getParticleComps().at("theta")] = 1;
m_plot_flags[pc->GetRealCompIndex("theta")] = 1;
#endif

// build filter functors
Expand Down
38 changes: 22 additions & 16 deletions Source/Diagnostics/ParticleIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,27 +153,30 @@ MultiParticleContainer::Restart (const std::string& dir)
real_comp_names.push_back(comp_name);
}

for (auto const& comp : pc->getParticleRuntimeComps()) {
auto search = std::find(real_comp_names.begin(), real_comp_names.end(), comp.first);
int n_rc = 0;
for (auto const& comp : pc->GetRealSoANames()) {
// skip compile-time components
if (n_rc < WarpXParticleContainer::NArrayReal) { continue; }
n_rc++;

auto search = std::find(real_comp_names.begin(), real_comp_names.end(), comp);
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
search != real_comp_names.end(),
"Species " + species_names[i]
+ "needs runtime real component " + comp.first
+ " needs runtime real component " + comp
+ ", but it was not found in the checkpoint file."
);
}

for (int j = PIdx::nattribs-AMREX_SPACEDIM; j < nr; ++j) {
const auto& comp_name = real_comp_names[j];
auto current_comp_names = pc->getParticleComps();
auto search = current_comp_names.find(comp_name);
if (search == current_comp_names.end()) {
if (!pc->HasRealComp(comp_name)) {
amrex::Print() << Utils::TextMsg::Info(
"Runtime real component " + comp_name
+ " was found in the checkpoint file, but it has not been added yet. "
+ " Adding it now."
);
pc->NewRealComp(comp_name);
pc->AddRealComp(comp_name);
}
}

Expand All @@ -187,26 +190,29 @@ MultiParticleContainer::Restart (const std::string& dir)
int_comp_names.push_back(comp_name);
}

for (auto const& comp : pc->getParticleRuntimeiComps()) {
auto search = std::find(int_comp_names.begin(), int_comp_names.end(), comp.first);
int n_ic = 0;
for (auto const& comp : pc->GetIntSoANames()) {
// skip compile-time components
if (n_ic < WarpXParticleContainer::NArrayInt) { continue; }
n_ic++;

auto search = std::find(int_comp_names.begin(), int_comp_names.end(), comp);
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
search != int_comp_names.end(),
"Species " + species_names[i] + "needs runtime int component " + comp.first
"Species " + species_names[i] + " needs runtime int component " + comp
+ ", but it was not found in the checkpoint file."
);
}

for (int j = 0; j < ni; ++j) {
const auto& comp_name = int_comp_names[j];
auto current_comp_names = pc->getParticleiComps();
auto search = current_comp_names.find(comp_name);
if (search == current_comp_names.end()) {
if (!pc->HasIntComp(comp_name)) {
amrex::Print()<< Utils::TextMsg::Info(
"Runtime int component " + comp_name
+ " was found in the checkpoint file, but it has not been added yet. "
+ " Adding it now."
);
pc->NewIntComp(comp_name);
pc->AddIntComp(comp_name);
}
}

Expand Down Expand Up @@ -258,8 +264,8 @@ storePhiOnParticles ( PinnedMemoryParticleContainer& tmp,
is_full_diagnostic,
"Output of the electrostatic potential (phi) on the particles was requested, "
"but this is only available with `diag_type = Full`.");
tmp.NewRealComp("phi");
int const phi_index = tmp.getParticleComps().at("phi");
tmp.AddRealComp("phi");
int const phi_index = tmp.GetRealCompIndex("phi");
auto& warpx = WarpX::GetInstance();
for (int lev=0; lev<=warpx.finestLevel(); lev++) {
const amrex::Geometry& geom = warpx.Geom(lev);
Expand Down
Loading

0 comments on commit c0eacd9

Please sign in to comment.