Skip to content

Commit 1093f61

Browse files
authored
Fix BTD/Scrape Flush Count with Filters (#4657)
* Fix BTD/Scrape Flush Count with Filters Move the counting of already flushed particles for writers that call the I/O backends multiple time per data set, e.g., BTD and boundary scraping, into the I/O backend. Currently, filtering is done as the first step in I/O backends and thus the previous count outside of the I/O backends was over-counting particles that might still get filtered out. Offset should be a `long`: Overflow risk is very high for pure `int`. Also, counter is `unsigned`, so `unsigned long` for now. * Simplify: Remove `m_totalParticles_flushed_already` Less state we can forget in checkpoint-restart and that we have to transfer across API boundaries.
1 parent 7a7c704 commit 1093f61

20 files changed

+94
-101
lines changed

Source/Diagnostics/BTDiagnostics.H

-2
Original file line numberDiff line numberDiff line change
@@ -399,8 +399,6 @@ private:
399399
lab-frame data. */
400400
void InitializeParticleFunctors () override;
401401

402-
/** Update total number of particles flushed for all species for ith snapshot */
403-
void UpdateTotalParticlesFlushed(int i_buffer);
404402
/** Reset total number of particles in the particle buffer to 0 for ith snapshot */
405403
void ResetTotalParticlesInBuffer(int i_buffer);
406404
/** Clear particle data stored in the particle buffer */

Source/Diagnostics/BTDiagnostics.cpp

+9-22
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ void BTDiagnostics::DerivedInitData ()
129129
}
130130
}
131131
m_particles_buffer.resize(m_num_buffers);
132-
m_totalParticles_flushed_already.resize(m_num_buffers);
133132
m_totalParticles_in_buffer.resize(m_num_buffers);
134133

135134
// check that simulation can fill all BTD snapshots
@@ -1065,12 +1064,12 @@ BTDiagnostics::Flush (int i_buffer, bool force_flush)
10651064
}
10661065
}
10671066
m_flush_format->WriteToFile(
1068-
m_varnames, m_mf_output[i_buffer], m_geom_output[i_buffer], warpx.getistep(),
1069-
labtime, m_output_species[i_buffer], nlev_output, file_name, m_file_min_digits,
1067+
m_varnames, m_mf_output.at(i_buffer), m_geom_output.at(i_buffer), warpx.getistep(),
1068+
labtime,
1069+
m_output_species.at(i_buffer), nlev_output, file_name, m_file_min_digits,
10701070
m_plot_raw_fields, m_plot_raw_fields_guards,
1071-
use_pinned_pc, isBTD, i_buffer, m_buffer_flush_counter[i_buffer],
1072-
m_max_buffer_multifabs[i_buffer], m_geom_snapshot[i_buffer][0], isLastBTDFlush,
1073-
m_totalParticles_flushed_already[i_buffer]);
1071+
use_pinned_pc, isBTD, i_buffer, m_buffer_flush_counter.at(i_buffer),
1072+
m_max_buffer_multifabs.at(i_buffer), m_geom_snapshot.at(i_buffer).at(0), isLastBTDFlush);
10741073

10751074
// Rescaling the box for plotfile after WriteToFile. This is because, for plotfiles, when writing particles, amrex checks if the particles are within the bounds defined by the box. However, in BTD, particles can be (at max) 1 cell outside the bounds of the geometry. So we keep a one-cell bigger box for plotfile when writing out the particle data and rescale after.
10761075
if (m_format == "plotfile") {
@@ -1104,7 +1103,6 @@ BTDiagnostics::Flush (int i_buffer, bool force_flush)
11041103
NullifyFirstFlush(i_buffer);
11051104
// if particles are selected for output then update and reset counters
11061105
if (!m_output_species_names.empty()) {
1107-
UpdateTotalParticlesFlushed(i_buffer);
11081106
ResetTotalParticlesInBuffer(i_buffer);
11091107
ClearParticleBuffer(i_buffer);
11101108
}
@@ -1271,10 +1269,10 @@ void BTDiagnostics::MergeBuffersForPlotfile (int i_snapshot)
12711269
InterleaveSpeciesHeader(recent_species_Header,snapshot_species_Header,
12721270
m_output_species_names[i], m_buffer_flush_counter[i_snapshot]);
12731271
if (BufferSpeciesHeader.m_total_particles == 0) { continue; }
1274-
if (m_totalParticles_flushed_already[i_snapshot][i]==0) {
1275-
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
1276-
std::rename(recent_ParticleHdrFilename.c_str(), snapshot_ParticleHdrFilename.c_str()) == 0,
1277-
std::string("Renaming ").append(recent_ParticleHdrFilename).append(" to ").append(snapshot_ParticleHdrFilename).append(" has failed"));
1272+
if (!amrex::FileExists(snapshot_ParticleHdrFilename)) {
1273+
WARPX_ALWAYS_ASSERT_WITH_MESSAGE(
1274+
std::rename(recent_ParticleHdrFilename.c_str(), snapshot_ParticleHdrFilename.c_str()) == 0,
1275+
std::string("Renaming ").append(recent_ParticleHdrFilename).append(" to ").append(snapshot_ParticleHdrFilename).append(" has failed"));
12781276
} else {
12791277
InterleaveParticleDataHeader(recent_ParticleHdrFilename,
12801278
snapshot_ParticleHdrFilename);
@@ -1435,10 +1433,8 @@ BTDiagnostics::InitializeParticleBuffer ()
14351433
const MultiParticleContainer& mpc = warpx.GetPartContainer();
14361434
for (int i = 0; i < m_num_buffers; ++i) {
14371435
m_particles_buffer[i].resize(m_output_species_names.size());
1438-
m_totalParticles_flushed_already[i].resize(m_output_species_names.size());
14391436
m_totalParticles_in_buffer[i].resize(m_output_species_names.size());
14401437
for (int isp = 0; isp < m_particles_buffer[i].size(); ++isp) {
1441-
m_totalParticles_flushed_already[i][isp] = 0;
14421438
m_totalParticles_in_buffer[i][isp] = 0;
14431439
m_particles_buffer[i][isp] = std::make_unique<PinnedMemoryParticleContainer>(WarpX::GetInstance().GetParGDB());
14441440
const int idx = mpc.getSpeciesID(m_output_species_names[isp]);
@@ -1489,15 +1485,6 @@ BTDiagnostics::PrepareParticleDataForOutput()
14891485
}
14901486
}
14911487

1492-
void
1493-
BTDiagnostics::UpdateTotalParticlesFlushed(int i_buffer)
1494-
{
1495-
for (int isp = 0; isp < m_totalParticles_flushed_already[i_buffer].size(); ++isp) {
1496-
m_totalParticles_flushed_already[i_buffer][isp] += static_cast<int>(
1497-
m_particles_buffer[i_buffer][isp]->TotalNumberOfParticles());
1498-
}
1499-
}
1500-
15011488
void
15021489
BTDiagnostics::ResetTotalParticlesInBuffer(int i_buffer)
15031490
{

Source/Diagnostics/BoundaryScrapingDiagnostics.cpp

+5-12
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,6 @@ BoundaryScrapingDiagnostics::InitializeParticleBuffer ()
102102
m_output_species[i_buffer].push_back(ParticleDiag(m_diag_name, species_name, pc, bnd_buffer));
103103
}
104104
}
105-
// Initialize total number of particles flushed
106-
m_totalParticles_flushed_already.resize(m_num_buffers);
107-
for (int i_buffer = 0; i_buffer < m_num_buffers; ++i_buffer) {
108-
int const n_species = static_cast<int>(m_output_species_names.size());
109-
m_totalParticles_flushed_already[i_buffer].resize(n_species);
110-
for (int i_species=0; i_species<n_species; i_species++) {
111-
m_totalParticles_flushed_already[i_buffer][i_species] = 0;
112-
}
113-
}
114105
}
115106

116107
bool
@@ -157,11 +148,13 @@ BoundaryScrapingDiagnostics::Flush (int i_buffer, bool /* force_flush */)
157148
const std::string file_prefix = m_file_prefix + "/particles_at_" + particle_buffer.boundaryName(i_buffer);
158149

159150
m_flush_format->WriteToFile(
160-
m_varnames, m_mf_output[i_buffer], m_geom_output[i_buffer], warpx.getistep(),
161-
warpx.gett_new(0), m_output_species[i_buffer], nlev_output, file_prefix,
151+
m_varnames, m_mf_output.at(i_buffer), m_geom_output.at(i_buffer), warpx.getistep(),
152+
warpx.gett_new(0),
153+
m_output_species.at(i_buffer),
154+
nlev_output, file_prefix,
162155
m_file_min_digits, false, false, use_pinned_pc, isBTD,
163156
warpx.getistep(0), bufferID, numBTDBuffers, geom,
164-
isLastBTD, m_totalParticles_flushed_already[i_buffer]);
157+
isLastBTD);
165158

166159
// Now that the data has been written out, clear out the buffer
167160
particle_buffer.clearParticles(i_buffer);

Source/Diagnostics/Diagnostics.H

-5
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,6 @@ protected:
309309
/** Vector of pointers to functors to compute particle output per species*/
310310
amrex::Vector< std::unique_ptr<ComputeParticleDiagFunctor> > m_all_particle_functors;
311311

312-
/** Vector of total number of particles previously flushed, per species, per snapshot.
313-
* The first vector is for total number of snapshots and second vector loops
314-
* over the total number of species selected for diagnostics.
315-
*/
316-
amrex::Vector< amrex::Vector <int> > m_totalParticles_flushed_already;
317312
/** Vector of total number of particles in the buffer, per species, per snapshot.
318313
* The first vector is for total number of snapshots and second vector loops
319314
* over the total number of species selected for diagnostics.

Source/Diagnostics/FlushFormats/FlushFormat.H

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ public:
2424
bool isBTD = false, int snapshotID = -1,
2525
int bufferID = 1, int numBuffers = 1,
2626
const amrex::Geometry& full_BTD_snapshot = amrex::Geometry(),
27-
bool isLastBTDFlush = false,
28-
const amrex::Vector<int>& totalParticlesFlushedAlready = amrex::Vector<int>() ) const = 0;
27+
bool isLastBTDFlush = false) const = 0;
2928

3029
FlushFormat () = default;
3130
virtual ~FlushFormat() = default;

Source/Diagnostics/FlushFormats/FlushFormatAscent.H

+1-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ public:
4141
bool isBTD = false, int snapshotID = -1,
4242
int bufferID = 1, int numBuffers = 1,
4343
const amrex::Geometry& full_BTD_snapshot = amrex::Geometry(),
44-
bool isLastBTDFlush = false,
45-
const amrex::Vector<int>& totalParticlesFlushedAlready = amrex::Vector<int>() ) const override;
44+
bool isLastBTDFlush = false ) const override;
4645

4746
#ifdef AMREX_USE_ASCENT
4847
/** \brief Do in-situ visualization for particle data.

Source/Diagnostics/FlushFormats/FlushFormatAscent.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ FlushFormatAscent::WriteToFile (
2121
const bool /*use_pinned_pc*/,
2222
bool isBTD, int /*snapshotID*/, int /*bufferID*/, int /*numBuffers*/,
2323
const amrex::Geometry& /*full_BTD_snapshot*/,
24-
bool /*isLastBTDFlush*/, const amrex::Vector<int>& /* totalParticlesFlushedAlready*/) const
24+
bool /*isLastBTDFlush*/) const
2525
{
2626
#ifdef AMREX_USE_ASCENT
2727
WARPX_PROFILE("FlushFormatAscent::WriteToFile()");

Source/Diagnostics/FlushFormats/FlushFormatCheckpoint.H

+1-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ class FlushFormatCheckpoint final : public FlushFormatPlotfile
2828
bool isBTD = false, int snapshotID = -1,
2929
int bufferID = 1, int numBuffers = 1,
3030
const amrex::Geometry& full_BTD_snapshot = amrex::Geometry(),
31-
bool isLastBTDFlush = false,
32-
const amrex::Vector<int>& totalParticlesFlushedAlready = amrex::Vector<int>() ) const final;
31+
bool isLastBTDFlush = false) const final;
3332

3433
void CheckpointParticles (const std::string& dir,
3534
const amrex::Vector<ParticleDiag>& particle_diags) const;

Source/Diagnostics/FlushFormats/FlushFormatCheckpoint.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ FlushFormatCheckpoint::WriteToFile (
3939
bool /*isBTD*/, int /*snapshotID*/,
4040
int /*bufferID*/, int /*numBuffers*/,
4141
const amrex::Geometry& /*full_BTD_snapshot*/,
42-
bool /*isLastBTDFlush*/, const amrex::Vector<int>& /* totalParticlesFlushedAlready*/) const
42+
bool /*isLastBTDFlush*/) const
4343
{
4444
WARPX_PROFILE("FlushFormatCheckpoint::WriteToFile()");
4545

Source/Diagnostics/FlushFormats/FlushFormatOpenPMD.H

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ public:
4040
bool isBTD = false, int snapshotID = -1,
4141
int bufferID = 1, int numBuffers = 1,
4242
const amrex::Geometry& full_BTD_snapshot = amrex::Geometry(),
43-
bool isLastBTDFlush = false,
44-
const amrex::Vector<int>& totalParticlesFlushedAlready = amrex::Vector<int>() ) const override;
43+
bool isLastBTDFlush = false ) const override;
4544

4645
~FlushFormatOpenPMD () override = default;
4746

Source/Diagnostics/FlushFormats/FlushFormatOpenPMD.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ FlushFormatOpenPMD::WriteToFile (
126126
const bool use_pinned_pc,
127127
bool isBTD, int snapshotID, int bufferID, int numBuffers,
128128
const amrex::Geometry& full_BTD_snapshot,
129-
bool isLastBTDFlush, const amrex::Vector<int>& totalParticlesFlushedAlready) const
129+
bool isLastBTDFlush) const
130130
{
131131
WARPX_PROFILE("FlushFormatOpenPMD::WriteToFile()");
132132
const std::string& filename = amrex::Concatenate(prefix, iteration[0], file_min_digits);
@@ -164,7 +164,7 @@ FlushFormatOpenPMD::WriteToFile (
164164

165165
// particles: all (reside only on locally finest level)
166166
m_OpenPMDPlotWriter->WriteOpenPMDParticles(
167-
particle_diags, static_cast<amrex::Real>(time), use_pinned_pc, isBTD, isLastBTDFlush, totalParticlesFlushedAlready);
167+
particle_diags, static_cast<amrex::Real>(time), use_pinned_pc, isBTD, isLastBTDFlush);
168168

169169
// signal that no further updates will be written to this iteration
170170
m_OpenPMDPlotWriter->CloseStep(isBTD, isLastBTDFlush);

Source/Diagnostics/FlushFormats/FlushFormatPlotfile.H

+1-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ public:
3535
bool isBTD = false, int snapshotID = -1,
3636
int bufferID = 1, int numBuffers = 1,
3737
const amrex::Geometry& full_BTD_snapshot = amrex::Geometry(),
38-
bool isLastBTDFlush = false,
39-
const amrex::Vector<int>& totalParticlesFlushedAlready = amrex::Vector<int>() ) const override;
38+
bool isLastBTDFlush = false) const override;
4039

4140
/** Write general info of the run into the plotfile */
4241
void WriteJobInfo(const std::string& dir) const;

Source/Diagnostics/FlushFormats/FlushFormatPlotfile.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ FlushFormatPlotfile::WriteToFile (
6565
const bool /*use_pinned_pc*/,
6666
bool isBTD, int snapshotID, int bufferID, int numBuffers,
6767
const amrex::Geometry& /*full_BTD_snapshot*/,
68-
bool isLastBTDFlush, const amrex::Vector<int>& /* totalParticlesFlushedAlready*/) const
68+
bool isLastBTDFlush) const
6969
{
7070
WARPX_PROFILE("FlushFormatPlotfile::WriteToFile()");
7171
auto & warpx = WarpX::GetInstance();
@@ -340,9 +340,9 @@ FlushFormatPlotfile::WriteWarpXHeader(
340340
void
341341
FlushFormatPlotfile::WriteParticles(const std::string& dir,
342342
const amrex::Vector<ParticleDiag>& particle_diags,
343-
const amrex::Real time, bool isBTD) const
343+
const amrex::Real time,
344+
bool isBTD) const
344345
{
345-
346346
for (const auto& part_diag : particle_diags) {
347347
WarpXParticleContainer* pc = part_diag.getParticleContainer();
348348
PinnedMemoryParticleContainer* pinned_pc = part_diag.getPinnedParticleContainer();

Source/Diagnostics/FlushFormats/FlushFormatSensei.H

+1-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ public:
6161
bool isBTD = false, int snapshotID = -1,
6262
int bufferID = 1, int numBuffers = 1,
6363
const amrex::Geometry& full_BTD_snapshot = amrex::Geometry(),
64-
bool isLastBTDFlush = false,
65-
const amrex::Vector<int>& totalParticlesFlushedAlready = amrex::Vector<int>() ) const override;
64+
bool isLastBTDFlush = false) const override;
6665

6766
/** \brief Do in-situ visualization for particle data.
6867
* \param[in] particle_diags Each element of this vector handles output of 1 species.

Source/Diagnostics/FlushFormats/FlushFormatSensei.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,13 @@ FlushFormatSensei::WriteToFile (
5353
bool plot_raw_fields, bool plot_raw_fields_guards,
5454
const bool use_pinned_pc,
5555
bool isBTD, int /*snapshotID*/, int /*bufferID*/, int /*numBuffers*/,
56-
const amrex::Geometry& /*full_BTD_snapshot*/, bool /*isLastBTDFlush*/,
57-
const amrex::Vector<int>& totalParticlesFlushedAlready) const
56+
const amrex::Geometry& /*full_BTD_snapshot*/, bool /*isLastBTDFlush*/) const
5857
{
5958
amrex::ignore_unused(
6059
geom, nlev, prefix, file_min_digits,
6160
plot_raw_fields, plot_raw_fields_guards,
62-
use_pinned_pc,
63-
totalParticlesFlushedAlready);
61+
use_pinned_pc
62+
);
6463

6564
#ifndef AMREX_USE_SENSEI_INSITU
6665
amrex::ignore_unused(varnames, mf, iteration, time, particle_diags,

Source/Diagnostics/FullDiagnostics.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,9 @@ FullDiagnostics::Flush ( int i_buffer, bool /* force_flush */ )
133133
auto & warpx = WarpX::GetInstance();
134134

135135
m_flush_format->WriteToFile(
136-
m_varnames, m_mf_output[i_buffer], m_geom_output[i_buffer], warpx.getistep(),
137-
warpx.gett_new(0), m_output_species[i_buffer], nlev_output, m_file_prefix,
136+
m_varnames, m_mf_output.at(i_buffer), m_geom_output.at(i_buffer), warpx.getistep(),
137+
warpx.gett_new(0),
138+
m_output_species.at(i_buffer), nlev_output, m_file_prefix,
138139
m_file_min_digits, m_plot_raw_fields, m_plot_raw_fields_guards);
139140

140141
FlushRaw();

Source/Diagnostics/OpenPMDHelpFunction.H

+18
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,25 @@
1414
#include <string>
1515

1616

17+
/** Determine the preferred file ending if unspecified
18+
*
19+
* @return file ending without the "."
20+
*/
1721
std::string
1822
WarpXOpenPMDFileType ();
1923

24+
#ifdef WARPX_USE_OPENPMD
25+
/** Determine how many particles were already written in this species and step
26+
*
27+
* This checks for a particle species the current size of the id attribute, if it exists,
28+
* and if it does it takes its extent as the number of particles already on disk.
29+
*
30+
* Note that this checks declared size, not necessarily written size.
31+
*
32+
* @return exisitng extent of the "id" attribute or zero.
33+
*/
34+
unsigned long
35+
num_already_flushed (openPMD::ParticleSpecies & currSpecies);
36+
#endif
37+
2038
#endif // WARPX_OPENPMDHELPFUNCTION_H_

Source/Diagnostics/OpenPMDHelpFunction.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,23 @@ WarpXOpenPMDFileType ()
2727
#endif // WARPX_USE_OPENPMD
2828
return openPMDFileType;
2929
}
30+
31+
#ifdef WARPX_USE_OPENPMD
32+
unsigned long
33+
num_already_flushed (openPMD::ParticleSpecies & currSpecies)
34+
{
35+
const auto *const scalar = openPMD::RecordComponent::SCALAR;
36+
37+
unsigned long ParticleFlushOffset = 0;
38+
39+
if (currSpecies.contains("id")) {
40+
if (currSpecies["id"].contains(scalar)) {
41+
if (!currSpecies["id"][scalar].empty()) {
42+
ParticleFlushOffset = currSpecies["id"][scalar].getExtent().at(0);
43+
}
44+
}
45+
}
46+
47+
return ParticleFlushOffset;
48+
}
49+
#endif

Source/Diagnostics/WarpXOpenPMD.H

+3-5
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@ public:
125125
amrex::Real time,
126126
bool use_pinned_pc = false,
127127
bool isBTD = false,
128-
bool isLastBTDFlush = false,
129-
const amrex::Vector<int>& totalParticlesFlushedAlready = amrex::Vector<int>());
128+
bool isLastBTDFlush = false);
130129

131130
/** Write out all openPMD fields for all active MR levels
132131
*
@@ -290,9 +289,9 @@ private:
290289
* @param[in] int_comp_names The int attribute names, from WarpX
291290
* @param[in] charge Charge of the particles (note: fix for ions)
292291
* @param[in] mass Mass of the particles
292+
* @param[inout] ParticleFlushOffset previously flushed number of particles in BTD
293293
* @param[in] isBTD is this a backtransformed diagnostics (BTD) write?
294294
* @param[in] isLastBTDFlush is this the last time we will flush this BTD station?
295-
* @param[in] ParticleFlushOffset previously flushed number of particles in BTD
296295
*/
297296
void DumpToFile (ParticleContainer* pc,
298297
const std::string& name,
@@ -304,8 +303,7 @@ private:
304303
amrex::ParticleReal charge,
305304
amrex::ParticleReal mass,
306305
bool isBTD = false,
307-
bool isLastBTDFlush = false,
308-
int ParticleFlushOffset = 0);
306+
bool isLastBTDFlush = false);
309307

310308
/** Get the openPMD-api filename for openPMD::Series
311309
*

0 commit comments

Comments
 (0)