aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Docs/source/usage/parameters.rst18
-rwxr-xr-xExamples/Tests/scraping/analysis_rz.py23
-rw-r--r--Examples/Tests/scraping/inputs_rz6
-rw-r--r--Regression/WarpX-tests.ini4
-rw-r--r--Regression/requirements.txt1
-rw-r--r--Source/Diagnostics/BoundaryScrapingDiagnostics.H63
-rw-r--r--Source/Diagnostics/BoundaryScrapingDiagnostics.cpp167
-rw-r--r--Source/Diagnostics/CMakeLists.txt1
-rw-r--r--Source/Diagnostics/Diagnostics.H8
-rw-r--r--Source/Diagnostics/Make.package1
-rw-r--r--Source/Diagnostics/MultiDiagnostics.H2
-rw-r--r--Source/Diagnostics/MultiDiagnostics.cpp4
-rw-r--r--Source/Diagnostics/WarpXOpenPMD.cpp33
-rw-r--r--Source/Particles/ParticleBoundaryBuffer.H2
-rw-r--r--Source/Particles/ParticleBoundaryBuffer.cpp14
15 files changed, 324 insertions, 23 deletions
diff --git a/Docs/source/usage/parameters.rst b/Docs/source/usage/parameters.rst
index 47670c99b..5f7c3394a 100644
--- a/Docs/source/usage/parameters.rst
+++ b/Docs/source/usage/parameters.rst
@@ -1874,9 +1874,10 @@ Diagnostics and output
In-situ visualization
^^^^^^^^^^^^^^^^^^^^^
-WarpX has three types of diagnostics:
+WarpX has four types of diagnostics:
``FullDiagnostics`` consist in dumps of fields and particles at given iterations,
-``BackTransformedDiagnostics`` are used when running a simulation in a boosted frame, to reconstruct output data to the lab frame, and
+``BackTransformedDiagnostics`` are used when running a simulation in a boosted frame, to reconstruct output data to the lab frame,
+``BoundaryScrapingDiagnostics`` are used to collect the particles that are absorbed at the boundary, throughout the simulation, and
``ReducedDiags`` allow the user to compute some reduced quantity (particle temperature, max of a field) and write a small amount of data to text files.
Similar to what is done for physical species, WarpX has a class Diagnostics that allows users to initialize different diagnostics, each of them with different fields, resolution and period.
This currently applies to standard diagnostics, but should be extended to back-transformed diagnostics and reduced diagnostics (and others) in a near future.
@@ -2159,7 +2160,7 @@ BackTransformed Diagnostics (with support for Plotfile/openPMD output)
Back-Transformed Diagnostics (legacy output)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-``BackTransformedDiagnostics`` are used when running a simulation in a boosted frame, to reconstruct output data to the lab frame, and
+``BackTransformedDiagnostics`` are used when running a simulation in a boosted frame, to reconstruct output data to the lab frame
* ``warpx.do_back_transformed_diagnostics`` (`0` or `1`)
Whether to use the **back-transformed diagnostics** (i.e. diagnostics that
@@ -2231,6 +2232,17 @@ Back-Transformed Diagnostics (legacy output)
slice diagnostic if there are within the user-defined width from
the slice region defined by ``slice.dom_lo`` and ``slice.dom_hi``.
+Boundary Scraping Diagnostics
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``BoundaryScrapingDiagnostics`` are used to collect the particles that are absorbed at the embedded boundary, throughout the simulation.
+(Note that this diagnostics does not save any field ; it only saves particles.)
+Currently, the only supported output format is openPMD, so the user needs to set ``<diag>.format=openpmd``. In addition, the user needs
+to set ``<species>.save_particles_at_eb=1`` for each of the species that are to be saved in this diagnostic.
+
+In addition to their usual attributes, the saved particles have an additional integer attribute ``timestamp``, which
+indicates the PIC iteration at which each particle was absorbed at the boundary.
+
.. _running-cpp-parameters-diagnostics-reduced:
Reduced Diagnostics
diff --git a/Examples/Tests/scraping/analysis_rz.py b/Examples/Tests/scraping/analysis_rz.py
index 6c493fb0f..4af31e48a 100755
--- a/Examples/Tests/scraping/analysis_rz.py
+++ b/Examples/Tests/scraping/analysis_rz.py
@@ -13,6 +13,8 @@
# Upon reaching the surface, particles should be removed.
# At the end of the simulation, i.e., at time step 37,
# there should be 512 particles left.
+# In addition, the test checks the boundary scraping diagnostic
+# by making sure that all removed particles are properly recorded.
# Possible errors: 0
# tolerance: 0
@@ -21,6 +23,8 @@
import os
import sys
+import numpy as np
+from openpmd_viewer import OpenPMDTimeSeries
import yt
sys.path.insert(1, '../../../../warpx/Regression/Checksum/')
@@ -38,5 +42,24 @@ print('error = ', error)
print('tolerance = ', tolerance)
assert(error==tolerance)
+# Check that all the removed particles are properly recorded
+# by making sure that, at each iteration, the sum of the number of
+# remaining particles and scraped particles is equal to the
+# original number of particles
+ts_full = OpenPMDTimeSeries('./diags/diag2/')
+ts_scraping = OpenPMDTimeSeries('./diags/diag3/')
+
+def n_remaining_particles( iteration ):
+ w, = ts_full.get_particle(['w'], iteration=iteration)
+ return len(w)
+def n_scraped_particles( iteration ):
+ timestamp = ts_scraping.get_particle( ['timestamp'] )
+ return (timestamp <= iteration).sum()
+n_remaining = np.array([ n_remaining_particles(iteration) for iteration in ts_full.iterations ])
+n_scraped = np.array([ n_scraped_particles(iteration) for iteration in ts_full.iterations ])
+n_total = n_remaining[0]
+assert np.all( n_scraped+n_remaining == n_total)
+
+# Checksum test
test_name = os.path.split(os.getcwd())[1]
checksumAPI.evaluate_checksum(test_name, fn, do_particles=False)
diff --git a/Examples/Tests/scraping/inputs_rz b/Examples/Tests/scraping/inputs_rz
index edc48f40b..e8994bb18 100644
--- a/Examples/Tests/scraping/inputs_rz
+++ b/Examples/Tests/scraping/inputs_rz
@@ -40,8 +40,9 @@ electron.momentum_function_ux(x,y,z) = "if(x*x+y*y>0.0, -1.0*x/sqrt(x*x+y*y), 0.
electron.momentum_function_uy(x,y,z) = "if(x*x+y*y>0.0, -1.0*y/sqrt(x*x+y*y), 0.0)"
electron.momentum_function_uz(x,y,z) = "0"
electron.do_not_deposit = 1
+electron.save_particles_at_eb = 1
-diagnostics.diags_names = diag1 diag2
+diagnostics.diags_names = diag1 diag2 diag3
diag1.intervals = 1
diag1.diag_type = Full
@@ -51,3 +52,6 @@ diag2.intervals = 1
diag2.diag_type = Full
diag2.fields_to_plot = Er
diag2.format = openpmd
+
+diag3.diag_type = BoundaryScraping
+diag3.format = openpmd
diff --git a/Regression/WarpX-tests.ini b/Regression/WarpX-tests.ini
index 2ee2b3c6f..9c29b702f 100644
--- a/Regression/WarpX-tests.ini
+++ b/Regression/WarpX-tests.ini
@@ -3381,8 +3381,8 @@ buildDir = .
inputFile = Examples/Tests/scraping/inputs_rz
runtime_params = warpx.abort_on_warning_threshold = medium
dim = 2
-addToCompileString = USE_EB=TRUE USE_RZ=TRUE
-cmakeSetupOpts = -DWarpX_DIMS=RZ -DWarpX_EB=ON
+addToCompileString = USE_EB=TRUE USE_RZ=TRUE USE_OPENPMD=TRUE
+cmakeSetupOpts = -DWarpX_DIMS=RZ -DWarpX_EB=ON -DWarpX_OPENPMD=ON
restartTest = 0
useMPI = 1
numprocs = 2
diff --git a/Regression/requirements.txt b/Regression/requirements.txt
index 6ae75e268..3cf9e9fdf 100644
--- a/Regression/requirements.txt
+++ b/Regression/requirements.txt
@@ -2,6 +2,7 @@ matplotlib
mpi4py
numpy
openpmd-api
+openpmd-viewer
pandas
scipy
yt
diff --git a/Source/Diagnostics/BoundaryScrapingDiagnostics.H b/Source/Diagnostics/BoundaryScrapingDiagnostics.H
new file mode 100644
index 000000000..cb321b54b
--- /dev/null
+++ b/Source/Diagnostics/BoundaryScrapingDiagnostics.H
@@ -0,0 +1,63 @@
+/* Copyright 2022 Remi Lehe
+ *
+ * This file is part of WarpX.
+ *
+ * License: BSD-3-Clause-LBNL
+ */
+#ifndef WARPX_BOUNDARYSCRAPINGDIAGNOSTICS_H_
+#define WARPX_BOUNDARYSCRAPINGDIAGNOSTICS_H_
+
+#include "Diagnostics.H"
+
+#include <string>
+
+/** collect the particles that are absorbed at the embedded boundary, throughout the simulation
+ */
+class
+BoundaryScrapingDiagnostics final : public Diagnostics
+{
+public:
+
+ /** Constructor
+ *
+ * @param i index of diagnostics in MultiDiagnostics::alldiags
+ * @param name diagnostics name in the inputs file
+ */
+ BoundaryScrapingDiagnostics (int i, std::string name);
+
+private:
+ /** Read relevant parameters for BoundaryScraping */
+ void ReadParameters ();
+ /** \brief Flush data to file. */
+ void Flush (int i_buffer) override;
+ /** \brief Return whether to dump data to file at this time step.
+ * (i.e. whether to call Flush)
+ *
+ * \param[in] step current time step
+ * \param[in] i_buffer used only for BackTransformedDiagnostics.
+ * For BoundaryScrapingDiagnostics, this is always 0
+ * \param[in] force_flush if true, return true for any step
+ */
+ bool DoDump (int step, int i_buffer, bool force_flush=false) override;
+ /** Return whether to pack field data in output buffers at this time step
+ *
+ * This is not used for BoundaryScrapingDiagnostics: no field to output
+ */
+ bool DoComputeAndPack (int step, bool force_flush=false) override;
+ /** Initialize buffers that contain field data
+ *
+ * This is not used for BoundaryScrapingDiagnostics: no field to output
+ */
+ void InitializeBufferData (int i_buffer, int lev) override;
+ /** Initialize functors that point to the fields requested by the user.
+ *
+ * This is not used for BoundaryScrapingDiagnostics: no field to output
+ */
+ void InitializeFieldFunctors (int lev) override;
+ /** Initialize the diagnostics by pointing to the `ParticleBoundaryBuffer`
+ * that correspond to the species requested by the user.
+ */
+ void InitializeParticleBuffer () override;
+
+};
+#endif // WARPX_BOUNDARYSCRAPINGDIAGNOSTICS_H_
diff --git a/Source/Diagnostics/BoundaryScrapingDiagnostics.cpp b/Source/Diagnostics/BoundaryScrapingDiagnostics.cpp
new file mode 100644
index 000000000..19beec6ab
--- /dev/null
+++ b/Source/Diagnostics/BoundaryScrapingDiagnostics.cpp
@@ -0,0 +1,167 @@
+/* Copyright 2022 Remi Lehe
+ *
+ * This file is part of WarpX.
+ *
+ * License: BSD-3-Clause-LBNL
+ */
+
+#include "BoundaryScrapingDiagnostics.H"
+#include "ComputeDiagFunctors/ComputeDiagFunctor.H"
+#include "Diagnostics/Diagnostics.H"
+#include "Diagnostics/FlushFormats/FlushFormat.H"
+#include "Particles/ParticleBoundaryBuffer.H"
+#include "WarpX.H"
+
+#include <AMReX.H>
+
+#include <set>
+#include <string>
+
+using namespace amrex::literals;
+
+BoundaryScrapingDiagnostics::BoundaryScrapingDiagnostics (int i, std::string name)
+ : Diagnostics(i, name)
+{
+ ReadParameters();
+}
+
+void
+BoundaryScrapingDiagnostics::ReadParameters ()
+{
+ BaseReadParameters();
+
+ // Modify some of the quantities that were initialized by default
+ // in the function `BaseReadParameters`
+ m_varnames_fields = {}; // No fields in boundary scraping diagnostics
+ m_varnames = {}; // No fields in boundary scraping diagnostics
+
+ // Number of buffers = 1 for BoundaryScrapingDiagnostics.
+ // (buffers are used in BTDiagnostics, and correspond to different snapshots)
+ m_num_buffers = 1;
+
+ // Do a few checks
+#ifndef AMREX_USE_EB
+ amrex::Abort("You need to compile WarpX with Embedded Boundary (EB) support, in order to use BoundaryScrapingDiagnostic: -DWarpX_EB=ON");
+#endif
+#ifndef WARPX_USE_OPENPMD
+ amrex::Abort("You need to compile WarpX with openPMD support, in order to use BoundaryScrapingDiagnostic: -DWarpX_OPENPMD=ON");
+#endif
+
+ // Check that saving at EB has been activated for each requested species
+ std::set<std::string> particle_saving_activated;
+ for (auto const& species_name : m_output_species_names){
+ amrex::ParmParse pp(species_name);
+ bool save_particles_at_eb;
+ pp.query("save_particles_at_eb", save_particles_at_eb);
+ if (save_particles_at_eb == false) particle_saving_activated.insert(species_name);
+ }
+ std::string error_string = "You need to set "
+ "you need to set:\n";
+ for (auto const& species_name : particle_saving_activated){
+ error_string
+ .append(" ")
+ .append(species_name)
+ .append("save_particles_at_eb=1\n");
+ }
+ error_string.append("in order to use for the BoundaryScrapingDiagnostic.");
+ WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
+ particle_saving_activated.size() == 0u,
+ error_string);
+
+ // Check that the output format is openPMD
+ error_string = std::string("You need to set `")
+ .append(m_diag_name)
+ .append(".format=openpmd` for the BoundaryScrapingDiagnostic.");
+ WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
+ m_format == "openpmd",
+ error_string);
+}
+
+void
+BoundaryScrapingDiagnostics::InitializeFieldFunctors (int /*lev*/)
+{
+ // This function is usually used for field output
+ // Nothing to do here for boundary scraping output,
+ // since it only outputs particles
+}
+
+void
+BoundaryScrapingDiagnostics::InitializeBufferData (int /*i_buffer*/, int /*lev*/)
+{
+ // This function is usually used for field output
+ // Nothing to do here for boundary scraping output,
+ // since it only outputs particles
+}
+
+void
+BoundaryScrapingDiagnostics::InitializeParticleBuffer ()
+{
+ auto & warpx = WarpX::GetInstance();
+ const MultiParticleContainer& mpc = warpx.GetPartContainer();
+
+ // If the user does not specify any species, dump all species
+ if (m_output_species_names.empty()) {
+ m_output_species_names = mpc.GetSpeciesNames();
+ }
+
+ // Initialize one ParticleDiag per species requested
+ ParticleBoundaryBuffer& particle_buffer = warpx.GetParticleBoundaryBuffer();
+ for (int i_buffer = 0; i_buffer < m_num_buffers; ++i_buffer) {
+ for (auto const& species_name : m_output_species_names){
+ // `particle_buffer` contains buffers for all boundaries
+ // here we select the one for the EB (index: AMREX_SPACEDIM*2)
+ WarpXParticleContainer* pc = &mpc.GetParticleContainerFromName(species_name);
+ PinnedMemoryParticleContainer* eb_buffer = particle_buffer.getParticleBufferPointer(species_name, AMREX_SPACEDIM*2);
+ m_output_species[i_buffer].push_back(ParticleDiag(m_diag_name, species_name, pc, eb_buffer));
+ }
+ }
+ // Initialize total number of particles flushed
+ m_totalParticles_flushed_already.resize(m_num_buffers);
+ for (int i_buffer = 0; i_buffer < m_num_buffers; ++i_buffer) {
+ int const n_species = m_output_species_names.size();
+ m_totalParticles_flushed_already[i_buffer].resize(n_species);
+ for (int i_species=0; i_species<n_species; i_species++) {
+ m_totalParticles_flushed_already[i_buffer][i_species] = 0;
+ }
+ }
+}
+
+bool
+BoundaryScrapingDiagnostics::DoComputeAndPack (int /*step*/, bool /*force_flush*/)
+{
+ return false;
+}
+
+bool
+BoundaryScrapingDiagnostics::DoDump (int /*step*/, int /*i_buffer*/, bool force_flush)
+{
+ if (force_flush) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void
+BoundaryScrapingDiagnostics::Flush (int i_buffer)
+{
+ auto & warpx = WarpX::GetInstance();
+
+ // This is not a backtransform diagnostics, but we still set the flag `isBTD`
+ // This enables:
+ // - writing the data that was accumulated in a PinnedMemoryParticleContainer
+ // - writing repeatedly to the same file
+ bool const isBTD = true;
+ // For now, because this function is currently only called at the very end
+ // of the simulation for BoundaryScrapingDiagnostics, we always set `isLastBTD`.
+ // This tells WarpX to write all the metadata (and not purely the particle data)
+ bool const isLastBTD = true;
+ const amrex::Geometry& geom = warpx.Geom(0); // For compatibility with `WriteToFile` ; not used
+
+ m_flush_format->WriteToFile(
+ m_varnames, m_mf_output[i_buffer], m_geom_output[i_buffer], warpx.getistep(),
+ 0., m_output_species[i_buffer], nlev_output, m_file_prefix,
+ m_file_min_digits, false, false, isBTD, i_buffer, geom,
+ isLastBTD, m_totalParticles_flushed_already[i_buffer]);
+
+}
diff --git a/Source/Diagnostics/CMakeLists.txt b/Source/Diagnostics/CMakeLists.txt
index e3f76df6a..4df0f68f8 100644
--- a/Source/Diagnostics/CMakeLists.txt
+++ b/Source/Diagnostics/CMakeLists.txt
@@ -10,6 +10,7 @@ target_sources(WarpX
WarpXIO.cpp
WarpXOpenPMD.cpp
BTDiagnostics.cpp
+ BoundaryScrapingDiagnostics.cpp
BTD_Plotfile_Header_Impl.cpp
)
diff --git a/Source/Diagnostics/Diagnostics.H b/Source/Diagnostics/Diagnostics.H
index 2b849099f..e57447fea 100644
--- a/Source/Diagnostics/Diagnostics.H
+++ b/Source/Diagnostics/Diagnostics.H
@@ -30,14 +30,22 @@
class Diagnostics
{
public:
+ /** Constructor
+ *
+ * @param i index of diagnostics in MultiDiagnostics::alldiags
+ * @param name diagnostics name in the inputs file
+ */
Diagnostics (int i, std::string name);
+
/** Virtual Destructor to handle clean destruction of derived classes */
virtual ~Diagnostics ();
+
/** Pack (stack) all fields in the cell-centered output MultiFab m_mf_output.
*
* Fields are computed (e.g., cell-centered or back-transformed)
on-the-fly using a functor. */
void ComputeAndPack ();
+
/** \brief Flush particle and field buffers to file using the FlushFormat member variable.
*
* This function should belong to class Diagnostics and not be virtual, as it flushes
diff --git a/Source/Diagnostics/Make.package b/Source/Diagnostics/Make.package
index 7c5bf822c..f8bf69f98 100644
--- a/Source/Diagnostics/Make.package
+++ b/Source/Diagnostics/Make.package
@@ -7,6 +7,7 @@ CEXE_sources += ParticleIO.cpp
CEXE_sources += FieldIO.cpp
CEXE_sources += SliceDiagnostic.cpp
CEXE_sources += BTDiagnostics.cpp
+CEXE_sources += BoundaryScrapingDiagnostics.cpp
CEXE_sources += BTD_Plotfile_Header_Impl.cpp
ifeq ($(USE_OPENPMD), TRUE)
diff --git a/Source/Diagnostics/MultiDiagnostics.H b/Source/Diagnostics/MultiDiagnostics.H
index d5ccf2113..06a2b87b4 100644
--- a/Source/Diagnostics/MultiDiagnostics.H
+++ b/Source/Diagnostics/MultiDiagnostics.H
@@ -12,7 +12,7 @@
#include <vector>
/** All types of diagnostics. */
-enum struct DiagTypes {Full, BackTransformed};
+enum struct DiagTypes {Full, BackTransformed, BoundaryScraping};
/**
* \brief This class contains a vector of all diagnostics in the simulation.
diff --git a/Source/Diagnostics/MultiDiagnostics.cpp b/Source/Diagnostics/MultiDiagnostics.cpp
index da7bf2b00..6644f7b66 100644
--- a/Source/Diagnostics/MultiDiagnostics.cpp
+++ b/Source/Diagnostics/MultiDiagnostics.cpp
@@ -2,6 +2,7 @@
#include "Diagnostics/BTDiagnostics.H"
#include "Diagnostics/FullDiagnostics.H"
+#include "Diagnostics/BoundaryScrapingDiagnostics.H"
#include "Utils/TextMsg.H"
#include <AMReX_ParmParse.H>
@@ -28,6 +29,8 @@ MultiDiagnostics::MultiDiagnostics ()
#else
alldiags[i] = std::make_unique<BTDiagnostics>(i, diags_names[i]);
#endif
+ } else if ( diags_types[i] == DiagTypes::BoundaryScraping ){
+ alldiags[i] = std::make_unique<BoundaryScrapingDiagnostics>(i, diags_names[i]);
} else {
amrex::Abort(Utils::TextMsg::Err("Unknown diagnostic type"));
}
@@ -70,6 +73,7 @@ MultiDiagnostics::ReadParameters ()
pp_diag_name.get("diag_type", diag_type_str);
if (diag_type_str == "Full") diags_types[i] = DiagTypes::Full;
if (diag_type_str == "BackTransformed") diags_types[i] = DiagTypes::BackTransformed;
+ if (diag_type_str == "BoundaryScraping") diags_types[i] = DiagTypes::BoundaryScraping;
}
}
diff --git a/Source/Diagnostics/WarpXOpenPMD.cpp b/Source/Diagnostics/WarpXOpenPMD.cpp
index c43e7a2f3..c5d882083 100644
--- a/Source/Diagnostics/WarpXOpenPMD.cpp
+++ b/Source/Diagnostics/WarpXOpenPMD.cpp
@@ -556,8 +556,15 @@ WarpXOpenPMDPlot::WriteOpenPMDParticles (const amrex::Vector<ParticleDiag>& part
WARPX_PROFILE("WarpXOpenPMDPlot::WriteOpenPMDParticles()");
for (unsigned i = 0, n = particle_diags.size(); i < n; ++i) {
+
WarpXParticleContainer* pc = particle_diags[i].getParticleContainer();
- auto tmp = pc->make_alike<amrex::PinnedArenaAllocator>();
+ PinnedMemoryParticleContainer* pinned_pc = particle_diags[i].getPinnedParticleContainer();
+ PinnedMemoryParticleContainer tmp;
+ if (! isBTD) {
+ tmp = pc->make_alike<amrex::PinnedArenaAllocator>();
+ } else {
+ tmp = pinned_pc->make_alike<amrex::PinnedArenaAllocator>();
+ }
// names of amrex::Real and int particle attributes in SoA data
amrex::Vector<std::string> real_names;
amrex::Vector<std::string> int_names;
@@ -568,40 +575,34 @@ WarpXOpenPMDPlot::WriteOpenPMDParticles (const amrex::Vector<ParticleDiag>& part
// note: an underscore separates the record name from its component
// for non-scalar records
real_names.push_back("weighting");
-
real_names.push_back("momentum_x");
real_names.push_back("momentum_y");
real_names.push_back("momentum_z");
-
#ifdef WARPX_DIM_RZ
real_names.push_back("theta");
#endif
-
// get the names of the real comps
- real_names.resize(pc->NumRealComps());
- auto runtime_rnames = pc->getParticleRuntimeComps();
+ real_names.resize(tmp.NumRealComps());
+ auto runtime_rnames = tmp.getParticleRuntimeComps();
for (auto const& x : runtime_rnames)
{
real_names[x.second+PIdx::nattribs] = detail::snakeToCamel(x.first);
}
-
// plot any "extra" fields by default
real_flags = particle_diags[i].plot_flags;
- real_flags.resize(pc->NumRealComps(), 1);
-
+ real_flags.resize(tmp.NumRealComps(), 1);
// and the names
- int_names.resize(pc->NumIntComps());
- auto runtime_inames = pc->getParticleRuntimeiComps();
+ int_names.resize(tmp.NumIntComps());
+ auto runtime_inames = tmp.getParticleRuntimeiComps();
for (auto const& x : runtime_inames)
{
int_names[x.second+0] = detail::snakeToCamel(x.first);
}
-
// plot by default
- int_flags.resize(pc->NumIntComps(), 1);
+ int_flags.resize(tmp.NumIntComps(), 1);
- pc->ConvertUnits(ConvertDirection::WarpX_to_SI);
+ pc->ConvertUnits(ConvertDirection::WarpX_to_SI);
RandomFilter const random_filter(particle_diags[i].m_do_random_filter,
particle_diags[i].m_random_fraction);
UniformFilter const uniform_filter(particle_diags[i].m_do_uniform_filter,
@@ -624,7 +625,6 @@ WarpXOpenPMDPlot::WriteOpenPMDParticles (const amrex::Vector<ParticleDiag>& part
* parser_filter(p, engine) * geometry_filter(p, engine);
}, true);
} else if (isBTD) {
- PinnedMemoryParticleContainer* pinned_pc = particle_diags[i].getPinnedParticleContainer();
tmp.SetParticleGeometry(0,pinned_pc->Geom(0));
tmp.SetParticleBoxArray(0,pinned_pc->ParticleBoxArray(0));
tmp.SetParticleDistributionMap(0, pinned_pc->ParticleDistributionMap(0));
@@ -1321,6 +1321,9 @@ WarpXOpenPMDPlot::WriteOpenPMDFieldsAll ( //const std::string& filename,
series_iteration.setTime( time );
}
+ // If there are no fields to be written, interrupt the function here
+ if ( varnames.size()==0 ) return;
+
// loop over levels up to output_levels
// note: this is usually the finestLevel, not the maxLevel
for (int lev=0; lev < output_levels; lev++) {
diff --git a/Source/Particles/ParticleBoundaryBuffer.H b/Source/Particles/ParticleBoundaryBuffer.H
index f85b34044..a880512ea 100644
--- a/Source/Particles/ParticleBoundaryBuffer.H
+++ b/Source/Particles/ParticleBoundaryBuffer.H
@@ -46,6 +46,8 @@ public:
PinnedMemoryParticleContainer& getParticleBuffer(const std::string species_name, int boundary);
+ PinnedMemoryParticleContainer* getParticleBufferPointer(const std::string species_name, int boundary);
+
static constexpr int numBoundaries () {
return AMREX_SPACEDIM*2
#ifdef AMREX_USE_EB
diff --git a/Source/Particles/ParticleBoundaryBuffer.cpp b/Source/Particles/ParticleBoundaryBuffer.cpp
index f831b31be..86475aa05 100644
--- a/Source/Particles/ParticleBoundaryBuffer.cpp
+++ b/Source/Particles/ParticleBoundaryBuffer.cpp
@@ -172,7 +172,7 @@ void ParticleBoundaryBuffer::gatherParticles (MultiParticleContainer& mypc,
for (int i = 0; i < numSpecies(); ++i)
{
if (!m_do_boundary_buffer[2*idim+iside][i]) continue;
- const auto& pc = mypc.GetParticleContainer(i);
+ const WarpXParticleContainer& pc = mypc.GetParticleContainer(i);
if (!buffer[i].isDefined())
{
buffer[i] = pc.make_alike<amrex::PinnedArenaAllocator>();
@@ -325,3 +325,15 @@ ParticleBoundaryBuffer::getParticleBuffer(const std::string species_name, int bo
return buffer[index];
}
+
+PinnedMemoryParticleContainer *
+ParticleBoundaryBuffer::getParticleBufferPointer(const std::string species_name, int boundary) {
+
+ auto& buffer = m_particle_containers[boundary];
+ auto index = WarpX::GetInstance().GetPartContainer().getSpeciesID(species_name);
+
+ WARPX_ALWAYS_ASSERT_WITH_MESSAGE(m_do_boundary_buffer[boundary][index],
+ "Attempted to get particle buffer for boundary "
+ + std::to_string(boundary) + ", which is not used!");
+ return &buffer[index];
+}