Skip to content

Commit b656a8f

Browse files
Add meaningful particle component names to I/O headers (quokka-astro#1594)
## Summary Updated particle I/O to write meaningful component names (e.g., `mass`, `vx`, `luminosity_0`) instead of generic names (`real_comp0`, `real_comp1`) in plotfile and checkpoint Header files. ## Changes - **`src/particles/particle_types.hpp`**: - Converted particle data index enums to `AMREX_ENUM` for automatic string conversion - Added `luminosity` explicitly to enums for radiating particle types - Created `expandEnumNames<EnumType, nComps, expandLast>()` helper to generate component names - Added unified `getParticleRealCompNames<ParticleType, problem_t>()` and `getParticleIntCompNames<ParticleType, problem_t>()` template functions - Maintained backward compatibility with `constexpr int` aliases for existing code - **`src/particles/PhysicsParticles.hpp`**: - Updated `writePlotFile()` and `writeCheckpoint()` to pass component names to AMReX ## Particle types updated | Particle Type | Real Components | Int Components | |----------------------|----------------------------------------------------------------------------|-----------------| | Rad | birth_time, death_time, luminosity_0, ... | (none) | | CIC | mass, vx, vy, vz | (none) | | CICRad | mass, vx, vy, vz, birth_time, death_time, luminosity_0, ... | (none) | | StochasticStellarPop | mass, vx, vy, vz, birth_time, death_time, mass_at_birth, luminosity_0, ... | evolution_stage | | Sink | mass, vx, vy, vz | (none) | | Test | mass, vx, vy, vz, birth_time, death_time, luminosity_0, ... | evolution_stage | ### Checklist _Before this pull request can be reviewed, all of these tasks should be completed. Denote completed tasks with an `x` inside the square brackets `[ ]` in the Markdown source below:_ - [ ] I have added a description (see above). - [ ] I have added a link to any related issues (if applicable; see above). - [ ] I have read the [Contributing Guide](https://github.com/quokka-astro/quokka/blob/development/CONTRIBUTING.md). - [ ] I have added tests for any new physics that this PR adds to the code. - [ ] *(For quokka-astro org members)* I have manually triggered the GPU tests with the magic comment `/azp run`. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent ae65935 commit b656a8f

2 files changed

Lines changed: 206 additions & 55 deletions

File tree

src/particles/PhysicsParticles.hpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,19 +506,29 @@ template <typename ContainerType, typename problem_t, ParticleType particleType>
506506
}
507507
}
508508

509+
// Get real component names for this particle type using unified template function
510+
[[nodiscard]] static auto getRealCompNames() -> amrex::Vector<std::string> { return getParticleRealCompNames<particleType_, problem_t>(); }
511+
512+
// Get int component names for this particle type using unified template function
513+
[[nodiscard]] static auto getIntCompNames() -> amrex::Vector<std::string> { return getParticleIntCompNames<particleType_, problem_t>(); }
514+
509515
// Implementation of particle data output to plot file
510516
void writePlotFile(const std::string &plotfilename, const std::string &name) override
511517
{
512518
if (container_ != nullptr) {
513-
container_->WritePlotFile(plotfilename, name);
519+
const amrex::Vector<std::string> real_comp_names = getRealCompNames();
520+
const amrex::Vector<std::string> int_comp_names = getIntCompNames();
521+
container_->WritePlotFile(plotfilename, name, real_comp_names, int_comp_names);
514522
}
515523
}
516524

517525
// Implementation of particle data output to checkpoint file
518526
void writeCheckpoint(const std::string &checkpointname, const std::string &name, bool include_header) override
519527
{
520528
if (container_ != nullptr) {
521-
container_->Checkpoint(checkpointname, name, include_header);
529+
const amrex::Vector<std::string> real_comp_names = getRealCompNames();
530+
const amrex::Vector<std::string> int_comp_names = getIntCompNames();
531+
container_->Checkpoint(checkpointname, name, include_header, real_comp_names, int_comp_names);
522532
}
523533
}
524534

src/particles/particle_types.hpp

Lines changed: 194 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define PARTICLE_TYPES_HPP_
33

44
#include "AMReX_AmrParticles.H"
5+
#include "AMReX_Enum.H"
56
#include "AMReX_ParIter.H"
67
#include "physics_info.hpp"
78

@@ -87,12 +88,17 @@ AMREX_ENUM(SNScheme, // NOLINT
8788

8889
//-------------------- Radiation particles --------------------
8990

90-
// Indices for radiation particles (Rad_particles), birth time + death time + radiation groups
91-
enum RadParticleDataIdx {
92-
RadParticleBirthTimeIdx = 0, // Time when particle becomes active
93-
RadParticleDeathTimeIdx, // Time when particle becomes inactive
94-
RadParticleLumIdx // Base index for luminosity components
95-
};
91+
// Indices for radiation particles (Rad_particles) using AMREX_ENUM for automatic string conversion
92+
AMREX_ENUM(RadParticleRealIdx, // NOLINT
93+
birth_time, // Time when particle becomes active
94+
death_time, // Time when particle becomes inactive
95+
luminosity // Base luminosity component (expanded to luminosity_0, luminosity_1, ... in I/O)
96+
);
97+
98+
// Backward compatibility aliases for existing code
99+
constexpr int RadParticleBirthTimeIdx = static_cast<int>(RadParticleRealIdx::birth_time);
100+
constexpr int RadParticleDeathTimeIdx = static_cast<int>(RadParticleRealIdx::death_time);
101+
constexpr int RadParticleLumIdx = static_cast<int>(RadParticleRealIdx::luminosity); // Base index for luminosity components
96102

97103
// Number of real components for Rad_particles, birth time + death time + radiation groups
98104
template <typename problem_t>
@@ -112,13 +118,19 @@ template <typename problem_t> using RadParticleIterator = amrex::ParIter<RadPart
112118

113119
//-------------------- Gravitating particles --------------------
114120

115-
// Indices for gravitating particles (CIC_particles), mass + 3 velocity components
116-
enum CICParticleDataIdx {
117-
CICParticleMassIdx = 0, // Mass of the particle
118-
CICParticleVxIdx, // Velocity in x direction
119-
CICParticleVyIdx, // Velocity in y direction
120-
CICParticleVzIdx // Velocity in z direction
121-
};
121+
// Indices for gravitating particles (CIC_particles) using AMREX_ENUM for automatic string conversion
122+
AMREX_ENUM(CICParticleRealIdx, // NOLINT
123+
mass, // Mass of the particle
124+
vx, // Velocity in x direction
125+
vy, // Velocity in y direction
126+
vz // Velocity in z direction
127+
);
128+
129+
// Backward compatibility aliases for existing code
130+
constexpr int CICParticleMassIdx = static_cast<int>(CICParticleRealIdx::mass);
131+
constexpr int CICParticleVxIdx = static_cast<int>(CICParticleRealIdx::vx);
132+
constexpr int CICParticleVyIdx = static_cast<int>(CICParticleRealIdx::vy);
133+
constexpr int CICParticleVzIdx = static_cast<int>(CICParticleRealIdx::vz);
122134

123135
// Number of real components for CIC_particles, mass + 3 velocity components
124136
constexpr int CICParticleRealComps = 4;
@@ -129,16 +141,25 @@ using CICParticleIterator = amrex::ParIter<CICParticleRealComps>;
129141

130142
//-------------------- Gravitating radiation particles --------------------
131143

132-
// Indices for gravitating radiation particles (CICRad_particles), mass + 3 velocity components + birth time + death time + radiation groups
133-
enum CICRadParticleDataIdx {
134-
CICRadParticleMassIdx = 0, // Mass of the particle
135-
CICRadParticleVxIdx, // Velocity in x direction
136-
CICRadParticleVyIdx, // Velocity in y direction
137-
CICRadParticleVzIdx, // Velocity in z direction
138-
CICRadParticleBirthTimeIdx, // Time when particle becomes active
139-
CICRadParticleDeathTimeIdx, // Time when particle becomes inactive
140-
CICRadParticleLumIdx // Base index for luminosity components
141-
};
144+
// Indices for gravitating radiation particles (CICRad_particles) using AMREX_ENUM for automatic string conversion
145+
AMREX_ENUM(CICRadParticleRealIdx, // NOLINT
146+
mass, // Mass of the particle
147+
vx, // Velocity in x direction
148+
vy, // Velocity in y direction
149+
vz, // Velocity in z direction
150+
birth_time, // Time when particle becomes active
151+
death_time, // Time when particle becomes inactive
152+
luminosity // Base luminosity component (expanded to luminosity_0, luminosity_1, ... in I/O)
153+
);
154+
155+
// Backward compatibility aliases for existing code
156+
constexpr int CICRadParticleMassIdx = static_cast<int>(CICRadParticleRealIdx::mass);
157+
constexpr int CICRadParticleVxIdx = static_cast<int>(CICRadParticleRealIdx::vx);
158+
constexpr int CICRadParticleVyIdx = static_cast<int>(CICRadParticleRealIdx::vy);
159+
constexpr int CICRadParticleVzIdx = static_cast<int>(CICRadParticleRealIdx::vz);
160+
constexpr int CICRadParticleBirthTimeIdx = static_cast<int>(CICRadParticleRealIdx::birth_time);
161+
constexpr int CICRadParticleDeathTimeIdx = static_cast<int>(CICRadParticleRealIdx::death_time);
162+
constexpr int CICRadParticleLumIdx = static_cast<int>(CICRadParticleRealIdx::luminosity); // Base index for luminosity components
142163

143164
// Number of real components for CICRad_particles, mass + 3 velocity components + birth time + death time + radiation groups
144165
template <typename problem_t>
@@ -167,19 +188,33 @@ enum class StellarEvolutionStage { LowMassStar, SNProgenitor, SNRemnant, LowMass
167188

168189
//-------------------- Stellar population particles --------------------
169190

170-
// Indices for StochasticStellarPop_particles
171-
enum StochasticStellarPopParticleDataIdx {
172-
StochasticStellarPopParticleMassIdx = 0, // Mass of the particle
173-
StochasticStellarPopParticleVxIdx, // Velocity in x direction
174-
StochasticStellarPopParticleVyIdx, // Velocity in y direction
175-
StochasticStellarPopParticleVzIdx, // Velocity in z direction
176-
StochasticStellarPopParticleBirthTimeIdx, // Time when particle becomes active
177-
StochasticStellarPopParticleDeathTimeIdx, // Time when particle becomes inactive
178-
StochasticStellarPopParticleMassAtBirthIdx, // Particle mass at birth
179-
StochasticStellarPopParticleLumIdx // Base index for luminosity components
180-
};
191+
// Indices for StochasticStellarPop_particles using AMREX_ENUM for automatic string conversion
192+
AMREX_ENUM(StochasticStellarPopParticleRealIdx, // NOLINT
193+
mass, // Mass of the particle
194+
vx, // Velocity in x direction
195+
vy, // Velocity in y direction
196+
vz, // Velocity in z direction
197+
birth_time, // Time when particle becomes active
198+
death_time, // Time when particle becomes inactive
199+
mass_at_birth, // Particle mass at birth
200+
luminosity // Base luminosity component (expanded to luminosity_0, luminosity_1, ... in I/O)
201+
);
202+
203+
// Integer component indices using AMREX_ENUM
204+
AMREX_ENUM(StochasticStellarPopParticleIntIdx, // NOLINT
205+
evolution_stage // Evolution stage of the particle
206+
);
181207

182-
constexpr int StochasticStellarPopParticleStageIdx = 0; // Evolution stage of the particle, index in the integer components
208+
// Backward compatibility aliases for existing code
209+
constexpr int StochasticStellarPopParticleMassIdx = static_cast<int>(StochasticStellarPopParticleRealIdx::mass);
210+
constexpr int StochasticStellarPopParticleVxIdx = static_cast<int>(StochasticStellarPopParticleRealIdx::vx);
211+
constexpr int StochasticStellarPopParticleVyIdx = static_cast<int>(StochasticStellarPopParticleRealIdx::vy);
212+
constexpr int StochasticStellarPopParticleVzIdx = static_cast<int>(StochasticStellarPopParticleRealIdx::vz);
213+
constexpr int StochasticStellarPopParticleBirthTimeIdx = static_cast<int>(StochasticStellarPopParticleRealIdx::birth_time);
214+
constexpr int StochasticStellarPopParticleDeathTimeIdx = static_cast<int>(StochasticStellarPopParticleRealIdx::death_time);
215+
constexpr int StochasticStellarPopParticleMassAtBirthIdx = static_cast<int>(StochasticStellarPopParticleRealIdx::mass_at_birth);
216+
constexpr int StochasticStellarPopParticleLumIdx = static_cast<int>(StochasticStellarPopParticleRealIdx::luminosity); // Base index for luminosity components
217+
constexpr int StochasticStellarPopParticleStageIdx = static_cast<int>(StochasticStellarPopParticleIntIdx::evolution_stage);
183218

184219
// Number of real components for StochasticStellarPop_particles, mass + 3 velocity components + luminosity
185220
template <typename problem_t>
@@ -203,18 +238,32 @@ using StochasticStellarPopParticleIterator = amrex::ParIter<StochasticStellarPop
203238

204239
//-------------------- Test particles --------------------
205240

206-
// Indices for test particles (Test_particles)
207-
enum TestParticleDataIdx {
208-
TestParticleMassIdx = 0, // Mass of the particle
209-
TestParticleVxIdx, // Velocity in x direction
210-
TestParticleVyIdx, // Velocity in y direction
211-
TestParticleVzIdx, // Velocity in z direction
212-
TestParticleBirthTimeIdx, // Time when particle becomes active
213-
TestParticleDeathTimeIdx, // Time when particle becomes inactive
214-
TestParticleLumIdx // Base index for luminosity components
215-
};
241+
// Indices for test particles (Test_particles) using AMREX_ENUM for automatic string conversion
242+
// The enum values are short names that will appear directly in the Header file
243+
AMREX_ENUM(TestParticleRealIdx, // NOLINT
244+
mass, // Mass of the particle
245+
vx, // Velocity in x direction
246+
vy, // Velocity in y direction
247+
vz, // Velocity in z direction
248+
birth_time, // Time when particle becomes active
249+
death_time, // Time when particle becomes inactive
250+
luminosity // Base luminosity component (expanded to luminosity_0, luminosity_1, ... in I/O)
251+
);
216252

217-
constexpr int TestParticleStageIdx = 0; // Evolution stage of the particle, index in the integer components
253+
// Integer component indices using AMREX_ENUM
254+
AMREX_ENUM(TestParticleIntIdx, // NOLINT
255+
evolution_stage // Evolution stage of the particle
256+
);
257+
258+
// Backward compatibility aliases for existing code
259+
constexpr int TestParticleMassIdx = static_cast<int>(TestParticleRealIdx::mass);
260+
constexpr int TestParticleVxIdx = static_cast<int>(TestParticleRealIdx::vx);
261+
constexpr int TestParticleVyIdx = static_cast<int>(TestParticleRealIdx::vy);
262+
constexpr int TestParticleVzIdx = static_cast<int>(TestParticleRealIdx::vz);
263+
constexpr int TestParticleBirthTimeIdx = static_cast<int>(TestParticleRealIdx::birth_time);
264+
constexpr int TestParticleDeathTimeIdx = static_cast<int>(TestParticleRealIdx::death_time);
265+
constexpr int TestParticleLumIdx = static_cast<int>(TestParticleRealIdx::luminosity); // Base index for luminosity components
266+
constexpr int TestParticleStageIdx = static_cast<int>(TestParticleIntIdx::evolution_stage);
218267

219268
// Number of real components for Test_particles
220269
template <typename problem_t>
@@ -235,13 +284,19 @@ template <typename problem_t> using TestParticleIterator = amrex::ParIter<TestPa
235284

236285
//-------------------- Sink particles --------------------
237286

238-
// Indices for Sink_particles
239-
enum SinkParticleDataIdx {
240-
SinkParticleMassIdx = 0, // Mass of the particle
241-
SinkParticleVxIdx, // Velocity in x direction
242-
SinkParticleVyIdx, // Velocity in y direction
243-
SinkParticleVzIdx, // Velocity in z direction
244-
};
287+
// Indices for Sink_particles using AMREX_ENUM for automatic string conversion
288+
AMREX_ENUM(SinkParticleRealIdx, // NOLINT
289+
mass, // Mass of the particle
290+
vx, // Velocity in x direction
291+
vy, // Velocity in y direction
292+
vz // Velocity in z direction
293+
);
294+
295+
// Backward compatibility aliases for existing code
296+
constexpr int SinkParticleMassIdx = static_cast<int>(SinkParticleRealIdx::mass);
297+
constexpr int SinkParticleVxIdx = static_cast<int>(SinkParticleRealIdx::vx);
298+
constexpr int SinkParticleVyIdx = static_cast<int>(SinkParticleRealIdx::vy);
299+
constexpr int SinkParticleVzIdx = static_cast<int>(SinkParticleRealIdx::vz);
245300

246301
// Number of real components for Sink_particles
247302
constexpr int SinkParticleRealComps = 4; // mass, vx, vy, vz
@@ -252,6 +307,92 @@ using SinkParticleIterator = amrex::ParIter<SinkParticleRealComps>;
252307

253308
#endif // AMREX_SPACEDIM == 3
254309

310+
//-------------------- Component Names for I/O --------------------
311+
312+
// Helper function to generate component names from an enum type
313+
// If expandLast is true, the last enum component is expanded with _0, _1, ... suffixes
314+
// to fill up to nComps total components
315+
template <typename EnumType, int nComps, bool expandLast> auto expandEnumNames() -> amrex::Vector<std::string>
316+
{
317+
const std::vector<std::string> enum_names = amrex::getEnumNameStrings<EnumType>();
318+
const auto enum_size = static_cast<int>(enum_names.size());
319+
amrex::Vector<std::string> names;
320+
321+
if constexpr (nComps <= 0) {
322+
return names;
323+
}
324+
325+
if constexpr (!expandLast) {
326+
// No expansion - use enum names directly
327+
return {enum_names.begin(), enum_names.end()};
328+
}
329+
330+
// Add all components except the last one
331+
for (int i = 0; i < enum_size - 1; ++i) {
332+
names.push_back(enum_names[i]);
333+
}
334+
335+
// Expand the last component into name_0, name_1, ...
336+
const std::string &base_name = enum_names.back();
337+
const int nExtra = nComps - enum_size + 1;
338+
for (int i = 0; i < nExtra; ++i) {
339+
names.push_back(base_name + "_" + std::to_string(i));
340+
}
341+
342+
return names;
343+
}
344+
345+
// Unified template function to get real component names for any particle type
346+
// Uses AMREX_ENUM's getEnumNameStrings() and expands the last component for particle types with luminosity
347+
template <ParticleType particleType, typename problem_t> auto getParticleRealCompNames() -> amrex::Vector<std::string>
348+
{
349+
if constexpr (particleType == ParticleType::Rad) {
350+
return expandEnumNames<RadParticleRealIdx, RadParticleRealComps<problem_t>, true>();
351+
}
352+
#if AMREX_SPACEDIM == 3
353+
else if constexpr (particleType == ParticleType::CIC) {
354+
return expandEnumNames<CICParticleRealIdx, CICParticleRealComps, false>();
355+
} else if constexpr (particleType == ParticleType::CICRad) {
356+
return expandEnumNames<CICRadParticleRealIdx, CICRadParticleRealComps<problem_t>, true>();
357+
} else if constexpr (particleType == ParticleType::StochasticStellarPop) {
358+
return expandEnumNames<StochasticStellarPopParticleRealIdx, StochasticStellarPopParticleRealComps<problem_t>, true>();
359+
} else if constexpr (particleType == ParticleType::Sink) {
360+
return expandEnumNames<SinkParticleRealIdx, SinkParticleRealComps, false>();
361+
} else if constexpr (particleType == ParticleType::Test) {
362+
return expandEnumNames<TestParticleRealIdx, TestParticleRealComps<problem_t>, true>();
363+
}
364+
#endif
365+
else {
366+
return {};
367+
}
368+
}
369+
370+
// Unified template function to get integer component names for any particle type
371+
template <ParticleType particleType, typename problem_t> auto getParticleIntCompNames() -> amrex::Vector<std::string>
372+
{
373+
amrex::Vector<std::string> names;
374+
375+
if constexpr (particleType == ParticleType::Rad) { // NOLINT
376+
// No integer components
377+
}
378+
#if AMREX_SPACEDIM == 3
379+
else if constexpr (particleType == ParticleType::CIC) { // NOLINT
380+
// No integer components
381+
} else if constexpr (particleType == ParticleType::CICRad) { // NOLINT
382+
// No integer components
383+
} else if constexpr (particleType == ParticleType::StochasticStellarPop) {
384+
const std::vector<std::string> enum_names = amrex::getEnumNameStrings<StochasticStellarPopParticleIntIdx>();
385+
names = {enum_names.begin(), enum_names.end()};
386+
} else if constexpr (particleType == ParticleType::Sink) { // NOLINT
387+
// No integer components
388+
} else if constexpr (particleType == ParticleType::Test) {
389+
const std::vector<std::string> enum_names = amrex::getEnumNameStrings<TestParticleIntIdx>();
390+
names = {enum_names.begin(), enum_names.end()};
391+
}
392+
#endif
393+
return names;
394+
}
395+
255396
//-------------------- Units --------------------
256397

257398
// Units data for each particle type as powers of Mass, Length, Time, Temperature

0 commit comments

Comments
 (0)