aboutsummaryrefslogtreecommitdiff
path: root/Source/Diagnostics/WarpXOpenPMD.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Diagnostics/WarpXOpenPMD.cpp')
-rw-r--r--Source/Diagnostics/WarpXOpenPMD.cpp426
1 files changed, 337 insertions, 89 deletions
diff --git a/Source/Diagnostics/WarpXOpenPMD.cpp b/Source/Diagnostics/WarpXOpenPMD.cpp
index 05c2066de..ed2bf8020 100644
--- a/Source/Diagnostics/WarpXOpenPMD.cpp
+++ b/Source/Diagnostics/WarpXOpenPMD.cpp
@@ -1,12 +1,95 @@
#include "WarpXOpenPMD.H"
+#include "WarpXAlgorithmSelection.H"
#include "FieldIO.H" // for getReversedVec
+#include <algorithm>
+#include <cstdint>
+#include <map>
+#include <set>
+#include <string>
+#include <sstream>
+#include <tuple>
+#include <utility>
+
+
+namespace detail
+{
+
+ /** Convert AMReX AoS .id and .cpu to a globally unique particle ID
+ */
+ union GlobalID {
+ struct { int id; int cpu; }; //! MPI-rank local ID (and rank/cpu)
+ uint64_t global_id; //! global ID that is unique in the whole simulation
+ };
+ static_assert(sizeof(int) * 2u <= sizeof(uint64_t), "int size might cause collisions in global IDs");
+
+ /** Unclutter a real_names to openPMD record
+ *
+ * @param fullName name as in real_names variable
+ * @return pair of openPMD record and component name
+ */
+ inline std::pair< std::string, std::string >
+ name2openPMD( std::string const& fullName )
+ {
+ std::string record_name = fullName;
+ std::string component_name = openPMD::RecordComponent::SCALAR;
+ std::size_t startComp = fullName.find_last_of("_");
+
+ if( startComp != std::string::npos ) { // non-scalar
+ record_name = fullName.substr(0, startComp);
+ component_name = fullName.substr(startComp + 1u);
+ }
+ return make_pair(record_name, component_name);
+ }
+
+ /** Get the openPMD physical dimensionality of a record
+ *
+ * @param record_name name of the openPMD record
+ * @return map with base quantities and power scaling
+ */
+ std::map< openPMD::UnitDimension, double >
+ getUnitDimension( std::string const & record_name )
+ {
+
+ if( record_name == "position" ) return {
+ {openPMD::UnitDimension::L, 1.}
+ };
+ else if( record_name == "positionOffset" ) return {
+ {openPMD::UnitDimension::L, 1.}
+ };
+ else if( record_name == "momentum" ) return {
+ {openPMD::UnitDimension::L, 1.},
+ {openPMD::UnitDimension::M, 1.},
+ {openPMD::UnitDimension::T, -1.}
+ };
+ else if( record_name == "charge" ) return {
+ {openPMD::UnitDimension::T, 1.},
+ {openPMD::UnitDimension::I, 1.}
+ };
+ else if( record_name == "mass" ) return {
+ {openPMD::UnitDimension::M, 1.}
+ };
+ else if( record_name == "E" ) return {
+ {openPMD::UnitDimension::L, 1.},
+ {openPMD::UnitDimension::M, 1.},
+ {openPMD::UnitDimension::T, -3.},
+ {openPMD::UnitDimension::I, -1.},
+ };
+ else if( record_name == "B" ) return {
+ {openPMD::UnitDimension::M, 1.},
+ {openPMD::UnitDimension::I, -1.},
+ {openPMD::UnitDimension::T, -2.}
+ };
+ else return {};
+ }
+}
+
WarpXOpenPMDPlot::WarpXOpenPMDPlot(bool oneFilePerTS,
- std::string& openPMDFileType)
+ std::string openPMDFileType, std::vector<bool> fieldPMLdirections)
:m_Series(nullptr),
m_OneFilePerTS(oneFilePerTS),
- m_OpenPMDFileType(std::move(openPMDFileType))
- //m_OpenPMDFileType(openPMDFileType)
+ m_OpenPMDFileType(std::move(openPMDFileType)),
+ m_fieldPMLdirections(std::move(fieldPMLdirections))
{}
WarpXOpenPMDPlot::~WarpXOpenPMDPlot()
@@ -74,8 +157,17 @@ WarpXOpenPMDPlot::Init(openPMD::AccessType accessType)
else
m_Series = std::make_unique<openPMD::Series>(filename, accessType);
- // actually default is "particles" by openPMD.
- m_Series->setParticlesPath("particles");
+ // input file / simulation setup author
+ if( WarpX::authors.size() > 0u )
+ m_Series->setAuthor( WarpX::authors );
+ // more natural naming for PIC
+ m_Series->setMeshesPath( "fields" );
+ // conform to ED-PIC extension of openPMD
+ uint32_t const openPMD_ED_PIC = 1u;
+ m_Series->setOpenPMDextension( openPMD_ED_PIC );
+ // meta info
+ m_Series->setSoftware( "WarpX" );
+ m_Series->setSoftwareVersion( WarpX::Version() ) ;
}
@@ -89,23 +181,27 @@ WarpXOpenPMDPlot::WriteOpenPMDParticles(const std::unique_ptr<MultiParticleConta
auto& pc = mpc->GetUniqueContainer(i);
if (pc->plot_species) {
+ // names of amrex::Real and int particle attributes in SoA data
amrex::Vector<std::string> real_names;
amrex::Vector<std::string> int_names;
amrex::Vector<int> int_flags;
- real_names.push_back("weight");
+ // see openPMD ED-PIC extension for namings
+ // 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");
- real_names.push_back("Ex");
- real_names.push_back("Ey");
- real_names.push_back("Ez");
+ real_names.push_back("E_x");
+ real_names.push_back("E_y");
+ real_names.push_back("E_z");
- real_names.push_back("Bx");
- real_names.push_back("By");
- real_names.push_back("Bz");
+ real_names.push_back("B_x");
+ real_names.push_back("B_y");
+ real_names.push_back("B_z");
#ifdef WARPX_DIM_RZ
real_names.push_back("theta");
@@ -159,21 +255,55 @@ WarpXOpenPMDPlot::SavePlotFile (const std::unique_ptr<WarpXParticleContainer>& p
openPMD::Iteration currIteration = m_Series->iterations[iteration];
openPMD::ParticleSpecies currSpecies = currIteration.particles[name];
+ // meta data for ED-PIC extension
+ currSpecies.setAttribute( "particleShape", double( WarpX::noz ) );
+ // TODO allow this per direction in the openPMD standard, ED-PIC extension?
+ currSpecies.setAttribute( "particleShapes", [](){
+ return std::vector< double >{
+ double(WarpX::nox),
+#if AMREX_SPACEDIM==3
+ double(WarpX::noy),
+#endif
+ double(WarpX::noz)
+ };
+ }() );
+ currSpecies.setAttribute( "particlePush", [](){
+ switch( WarpX::particle_pusher_algo ) {
+ case ParticlePusherAlgo::Boris : return "Boris";
+ case ParticlePusherAlgo::Vay : return "Vay";
+ case ParticlePusherAlgo::HigueraCary : return "HigueraCary";
+ default: return "other";
+ }
+ }() );
+ currSpecies.setAttribute( "particleInterpolation", [](){
+ switch( WarpX::field_gathering_algo ) {
+ case GatheringAlgo::EnergyConserving : return "energyConserving";
+ case GatheringAlgo::MomentumConserving : return "momentumConserving";
+ default: return "other";
+ }
+ }() );
+ currSpecies.setAttribute( "particleSmoothing", "none" );
+ currSpecies.setAttribute( "currentDeposition", [](){
+ switch( WarpX::current_deposition_algo ) {
+ case CurrentDepositionAlgo::Esirkepov : return "Esirkepov";
+ default: return "directMorseNielson";
+ }
+ }() );
+
//
// define positions & offsets
//
- SetupPos(currSpecies, counter.GetTotalNumParticles());
+ SetupPos(pc, currSpecies, counter.GetTotalNumParticles());
SetupRealProperties(currSpecies, write_real_comp, real_comp_names, counter.GetTotalNumParticles());
// forces the files created by all processors! this is the key to resolve RZ storage issue!!
m_Series->flush();
for (auto currentLevel = 0; currentLevel <= pc->finestLevel(); currentLevel++)
{
- //long numParticles = counter.m_ParticleSizeAtRank[currentLevel]
- unsigned long long const numParticles = counter.m_ParticleSizeAtRank[currentLevel];
- unsigned long long offset = counter.m_ParticleOffsetAtRank[currentLevel];
+ uint64_t const numParticles = static_cast<uint64_t>( counter.m_ParticleSizeAtRank[currentLevel] );
+ uint64_t offset = static_cast<uint64_t>( counter.m_ParticleOffsetAtRank[currentLevel] );
- if (0 == numParticles)
+ if (0u == numParticles)
return;
// pc->NumIntComp() & NumRealComp() are protected,
@@ -181,22 +311,33 @@ WarpXOpenPMDPlot::SavePlotFile (const std::unique_ptr<WarpXParticleContainer>& p
// soa num real attributes = PIdx::nattribs, and num int in soa is 0
for (WarpXParIter pti(*pc, currentLevel); pti.isValid(); ++pti) {
- auto numParticleOnTile = pti.numParticles();
+ auto const numParticleOnTile = pti.numParticles();
+ uint64_t const numParticleOnTile64 = static_cast<uint64_t>( numParticleOnTile );
- // get position from aos
+ // get position and particle ID from aos
+ // note: this implementation iterates the AoS 4x but saves memory... iterating once could be beneficial, too
const auto& aos = pti.GetArrayOfStructs(); // size = numParticlesOnTile
- { // :: Save Postions, 1D-3D::
- // this code is tested with laser 3d, not tested with 2D examples...
+ {
+ // Save positions
std::vector<std::string> axisNames={"x", "y", "z"};
-
for (auto currDim = 0; currDim < AMREX_SPACEDIM; currDim++) {
- std::vector<amrex::ParticleReal> curr(numParticleOnTile, 0);
+ std::vector<amrex::ParticleReal> curr(numParticleOnTile, 0.);
for (auto i=0; i<numParticleOnTile; i++) {
curr[i] = aos[i].m_rdata.pos[currDim];
}
- currSpecies["position"][axisNames[currDim]].storeChunk(curr, {offset}, {static_cast<unsigned long long>(numParticleOnTile)});
+ currSpecies["position"][axisNames[currDim]].storeChunk(curr, {offset}, {numParticleOnTile64});
m_Series->flush();
}
+
+ // save particle ID after converting it to a globally unique ID
+ std::vector<uint64_t> ids(numParticleOnTile, 0.);
+ for (auto i=0; i<numParticleOnTile; i++) {
+ detail::GlobalID const nextID = { aos[i].m_idata.id, aos[i].m_idata.cpu };
+ ids[i] = nextID.global_id;
+ }
+ auto const scalar = openPMD::RecordComponent::SCALAR;
+ currSpecies["id"][scalar].storeChunk(ids, {offset}, {numParticleOnTile64});
+ m_Series->flush();
}
// save properties
SaveRealProperty(pti,
@@ -204,7 +345,7 @@ WarpXOpenPMDPlot::SavePlotFile (const std::unique_ptr<WarpXParticleContainer>& p
offset,
write_real_comp, real_comp_names);
- offset += numParticleOnTile;
+ offset += numParticleOnTile64;
}
}
}
@@ -224,8 +365,11 @@ WarpXOpenPMDPlot::SetupRealProperties(openPMD::ParticleSpecies& currSpecies,
auto counter = std::min(write_real_comp.size(), real_comp_names.size());
for (int i = 0; i < counter; ++i)
if (write_real_comp[i]) {
- auto& particleVar = currSpecies[real_comp_names[i]];
- auto& particleVarComp = particleVar[openPMD::RecordComponent::SCALAR];
+ // handle scalar and non-scalar records by name
+ std::string record_name, component_name;
+ std::tie(record_name, component_name) = detail::name2openPMD(real_comp_names[i]);
+
+ auto& particleVarComp = currSpecies[record_name][component_name];
particleVarComp.resetDataset(particlesLineup);
}
}
@@ -233,35 +377,40 @@ WarpXOpenPMDPlot::SetupRealProperties(openPMD::ParticleSpecies& currSpecies,
void
WarpXOpenPMDPlot::SaveRealProperty(WarpXParIter& pti,
openPMD::ParticleSpecies& currSpecies,
- unsigned long long offset,
- const amrex::Vector<int>& write_real_comp,
- const amrex::Vector<std::string>& real_comp_names) const
+ unsigned long long const offset,
+ amrex::Vector<int> const& write_real_comp,
+ amrex::Vector<std::string> const& real_comp_names) const
{
int numOutputReal = 0;
int const totalRealAttrs = m_NumAoSRealAttributes + m_NumSoARealAttributes;
- for (int i = 0; i < totalRealAttrs; ++i)
- if (write_real_comp[i])
+ for( int i = 0; i < totalRealAttrs; ++i )
+ if( write_real_comp[i] )
++numOutputReal;
- auto numParticleOnTile = pti.numParticles();
- const auto& aos = pti.GetArrayOfStructs(); // size = numParticlesOnTile
- const auto& soa = pti.GetStructOfArrays();
+ auto const numParticleOnTile = pti.numParticles();
+ auto const& aos = pti.GetArrayOfStructs(); // size = numParticlesOnTile
+ auto const& soa = pti.GetStructOfArrays();
// properties are saved separately
{
- for (auto idx=0; idx<m_NumAoSRealAttributes; idx++) {
- if (write_real_comp[idx]) {
- auto& currVar = currSpecies[real_comp_names[idx]][openPMD::RecordComponent::SCALAR];
- typename amrex::ParticleReal *d =
- static_cast<typename amrex::ParticleReal*> (malloc(sizeof(typename amrex::ParticleReal) * numParticleOnTile));
-
- for (auto kk=0; kk<numParticleOnTile; kk++)
+ for( auto idx=0; idx<m_NumAoSRealAttributes; idx++ ) {
+ if( write_real_comp[idx] ) {
+ // handle scalar and non-scalar records by name
+ std::string record_name, component_name;
+ std::tie(record_name, component_name) = detail::name2openPMD(real_comp_names[idx]);
+ auto& currRecord = currSpecies[record_name];
+ auto& currRecordComp = currRecord[component_name];
+
+ amrex::ParticleReal *d =
+ static_cast<amrex::ParticleReal*>( malloc(sizeof(amrex::ParticleReal) * numParticleOnTile) );
+
+ for( auto kk=0; kk<numParticleOnTile; kk++ )
d[kk] = aos[kk].m_rdata.arr[AMREX_SPACEDIM+idx];
- std::shared_ptr <typename amrex::ParticleReal> data(d, free);
- currVar.storeChunk(data,
+ std::shared_ptr<amrex::ParticleReal> data(d, free);
+ currRecordComp.storeChunk(data,
{offset}, {static_cast<unsigned long long>(numParticleOnTile)});
m_Series->flush();
}
@@ -269,12 +418,30 @@ WarpXOpenPMDPlot::SaveRealProperty(WarpXParIter& pti,
}
{
+ std::set< std::string > addedRecords; // add meta-data per record only once
for (auto idx=0; idx<m_NumSoARealAttributes; idx++) {
auto ii = m_NumAoSRealAttributes + idx;
if (write_real_comp[ii]) {
- auto& currVar = currSpecies[real_comp_names[ii]][openPMD::RecordComponent::SCALAR];
- currVar.storeChunk(openPMD::shareRaw(soa.GetRealData(idx)),
- {offset}, {static_cast<unsigned long long>(numParticleOnTile)});
+ // handle scalar and non-scalar records by name
+ std::string record_name, component_name;
+ std::tie(record_name, component_name) = detail::name2openPMD(real_comp_names[ii]);
+ auto& currRecord = currSpecies[record_name];
+ auto& currRecordComp = currRecord[component_name];
+
+ // meta data for ED-PIC extension
+ bool newRecord = false;
+ std::tie(std::ignore, newRecord) = addedRecords.insert(record_name);
+ if( newRecord ) {
+ currRecord.setAttribute( "macroWeighted", 0u );
+ if( record_name == "momentum" )
+ currRecord.setAttribute( "weightingPower", 1.0 );
+ else
+ currRecord.setAttribute( "weightingPower", 0.0 );
+ currRecord.setUnitDimension( detail::getUnitDimension(record_name) );
+ }
+
+ currRecordComp.storeChunk(openPMD::shareRaw(soa.GetRealData(idx)),
+ {offset}, {static_cast<unsigned long long>(numParticleOnTile)});
}
}
m_Series->flush();
@@ -284,25 +451,44 @@ WarpXOpenPMDPlot::SaveRealProperty(WarpXParIter& pti,
void
-WarpXOpenPMDPlot::SetupPos(openPMD::ParticleSpecies& currSpecies,
- const unsigned long long& np) const
+WarpXOpenPMDPlot::SetupPos(const std::unique_ptr<WarpXParticleContainer>& pc,
+ openPMD::ParticleSpecies& currSpecies,
+ const unsigned long long& np) const
{
- auto particleLineup = openPMD::Dataset(openPMD::determineDatatype<amrex::ParticleReal>(), {np});
-
- currSpecies["positionOffset"]["x"].resetDataset(particleLineup);
- currSpecies["positionOffset"]["x"].makeConstant(0);
- currSpecies["positionOffset"]["y"].resetDataset(particleLineup);
- currSpecies["positionOffset"]["y"].makeConstant(0);
- currSpecies["positionOffset"]["z"].resetDataset(particleLineup);
- currSpecies["positionOffset"]["z"].makeConstant(0);
-
- //auto positions = openPMD::Dataset(openPMD::determineDatatype<amrex::ParticleReal>(), {np});
- currSpecies["position"]["x"].resetDataset(particleLineup);
- currSpecies["position"]["y"].resetDataset(particleLineup);
- currSpecies["position"]["z"].resetDataset(particleLineup);
-}
+ auto const realType = openPMD::Dataset(openPMD::determineDatatype<amrex::ParticleReal>(), {np});
+ auto const idType = openPMD::Dataset(openPMD::determineDatatype< uint64_t >(), {np});
+ for( auto const& comp : {"x", "y", "z"} ) {
+ currSpecies["positionOffset"][comp].resetDataset( realType );
+ currSpecies["positionOffset"][comp].makeConstant( 0. );
+ currSpecies["position"][comp].resetDataset( realType );
+ }
+ auto const scalar = openPMD::RecordComponent::SCALAR;
+ currSpecies["id"][scalar].resetDataset( idType );
+ currSpecies["charge"][scalar].resetDataset( realType );
+ currSpecies["charge"][scalar].makeConstant( pc->getCharge() );
+ currSpecies["mass"][scalar].resetDataset( realType );
+ currSpecies["mass"][scalar].makeConstant( pc->getMass() );
+
+ // meta data
+ currSpecies["position"].setUnitDimension( detail::getUnitDimension("position") );
+ currSpecies["positionOffset"].setUnitDimension( detail::getUnitDimension("positionOffset") );
+ currSpecies["charge"].setUnitDimension( detail::getUnitDimension("charge") );
+ currSpecies["mass"].setUnitDimension( detail::getUnitDimension("mass") );
+
+ // meta data for ED-PIC extension
+ currSpecies["position"].setAttribute( "macroWeighted", 0u );
+ currSpecies["position"].setAttribute( "weightingPower", 0.0 );
+ currSpecies["positionOffset"].setAttribute( "macroWeighted", 0u );
+ currSpecies["positionOffset"].setAttribute( "weightingPower", 0.0 );
+ currSpecies["id"].setAttribute( "macroWeighted", 0u );
+ currSpecies["id"].setAttribute( "weightingPower", 0.0 );
+ currSpecies["charge"].setAttribute( "macroWeighted", 0u );
+ currSpecies["charge"].setAttribute( "weightingPower", 1.0 );
+ currSpecies["mass"].setAttribute( "macroWeighted", 0u );
+ currSpecies["mass"].setAttribute( "weightingPower", 1.0 );
+}
//
@@ -316,48 +502,109 @@ WarpXOpenPMDPlot::WriteOpenPMDFields( //const std::string& filename,
const int iteration,
const double time ) const
{
- //This is AmrEx's tiny profiler. Possibly will apply it later
+ //This is AMReX's tiny profiler. Possibly will apply it later
BL_PROFILE("WarpXOpenPMDPlot::WriteOpenPMDFields()");
if ( nullptr == m_Series)
return;
- const int ncomp = mf.nComp();
+ int const ncomp = mf.nComp();
// Create a few vectors that store info on the global domain
// Swap the indices for each of them, since AMReX data is Fortran order
// and since the openPMD API assumes contiguous C order
// - Size of the box, in integer number of cells
- const amrex::Box& global_box = geom.Domain();
- auto global_size = getReversedVec(global_box.size());
+ amrex::Box const & global_box = geom.Domain();
+ auto const global_size = getReversedVec(global_box.size());
// - Grid spacing
- std::vector<double> grid_spacing = getReversedVec(geom.CellSize());
+ std::vector<double> const grid_spacing = getReversedVec(geom.CellSize());
// - Global offset
- std::vector<double> global_offset = getReversedVec(geom.ProbLo());
+ std::vector<double> const global_offset = getReversedVec(geom.ProbLo());
// - AxisLabels
#if AMREX_SPACEDIM==3
- std::vector<std::string> axis_labels{"x", "y", "z"};
+ std::vector<std::string> const axis_labels{"x", "y", "z"};
#else
- std::vector<std::string> axis_labels{"x", "z"};
+ std::vector<std::string> const axis_labels{"x", "z"};
#endif
// Prepare the type of dataset that will be written
- openPMD::Datatype datatype = openPMD::determineDatatype<amrex::Real>();
- auto dataset = openPMD::Dataset(datatype, global_size);
+ openPMD::Datatype const datatype = openPMD::determineDatatype<amrex::Real>();
+ auto const dataset = openPMD::Dataset(datatype, global_size);
+ // meta data
auto series_iteration = m_Series->iterations[iteration];
series_iteration.setTime( time );
+ // meta data for ED-PIC extension
+ auto const period = geom.periodicity(); // TODO double-check: is this the proper global bound or of some level?
+ std::vector< std::string > fieldBoundary( 6, "reflecting" );
+ std::vector< std::string > particleBoundary( 6, "absorbing" );
+#if AMREX_SPACEDIM!=3
+ fieldBoundary.resize(4);
+ particleBoundary.resize(4);
+#endif
+
+ for( auto i = 0u; i < fieldBoundary.size() / 2u; ++i )
+ if( m_fieldPMLdirections.at( i ) )
+ fieldBoundary.at( i ) = "open";
+
+ for( auto i = 0u; i < fieldBoundary.size() / 2u; ++i )
+ if( period.isPeriodic( i ) ) {
+ fieldBoundary.at(2u*i ) = "periodic";
+ fieldBoundary.at(2u*i + 1u) = "periodic";
+ particleBoundary.at(2u*i ) = "periodic";
+ particleBoundary.at(2u*i + 1u) = "periodic";
+ }
+
+ auto meshes = series_iteration.meshes;
+ meshes.setAttribute( "fieldSolver", [](){
+#ifdef WARPX_USE_PSATD
+ return "PSATD"; // TODO double-check if WARPX_USE_PSATD_HYBRID is covered
+#else
+ switch( WarpX::particle_pusher_algo ) {
+ case MaxwellSolverAlgo::Yee : return "Yee";
+ case MaxwellSolverAlgo::CKC : return "CK";
+ default: return "other";
+ }
+#endif
+ }() );
+ meshes.setAttribute( "fieldBoundary", fieldBoundary );
+ meshes.setAttribute( "particleBoundary", particleBoundary );
+ meshes.setAttribute( "currentSmoothing", [](){
+ if( WarpX::use_filter ) return "Binomial";
+ else return "none";
+ }() );
+ if( WarpX::use_filter )
+ meshes.setAttribute( "currentSmoothingParameters", [](){
+ std::stringstream ss;
+ ss << "period=1;compensator=false";
+ ss << ";numPasses_x=" << WarpX::filter_npass_each_dir[0];
+#if (AMREX_SPACEDIM == 3)
+ ss << ";numPasses_y=" << WarpX::filter_npass_each_dir[1];
+ ss << ";numPasses_z=" << WarpX::filter_npass_each_dir[2];
+#else
+ ss << ";numPasses_z=" << WarpX::filter_npass_each_dir[1];
+#endif
+ std::string currentSmoothingParameters = ss.str();
+ return std::move(currentSmoothingParameters);
+ }() );
+ meshes.setAttribute("chargeCorrection", [](){
+ if( WarpX::do_dive_cleaning ) return "hyperbolic"; // TODO or "spectral" or something? double-check
+ else return "none";
+ }() );
+ if( WarpX::do_dive_cleaning )
+ meshes.setAttribute("chargeCorrectionParameters", "period=1");
+
// Loop through the different components, i.e. different fields stored in mf
for (int icomp=0; icomp<ncomp; icomp++){
// Check if this field is a vector or a scalar, and extract the field name
- const std::string& varname = varnames[icomp];
+ std::string const & varname = varnames[icomp];
std::string field_name = varname;
std::string comp_name = openPMD::MeshRecordComponent::SCALAR;
- for (const char* vector_field: {"E", "B", "j"}){
- for (const char* comp: {"x", "y", "z"}){
- if (varname[0] == *vector_field && varname[1] == *comp ){
+ for( char const* vector_field: {"E", "B", "j"} ) {
+ for( char const* comp: {"x", "y", "z"} ) {
+ if( varname[0] == *vector_field && varname[1] == *comp ) {
field_name = varname[0] + varname.substr(2); // Strip component
comp_name = varname[1];
}
@@ -365,35 +612,36 @@ WarpXOpenPMDPlot::WriteOpenPMDFields( //const std::string& filename,
}
// Setup the mesh record accordingly
- auto mesh = series_iteration.meshes[field_name];
- mesh.setDataOrder(openPMD::Mesh::DataOrder::F); // MultiFab: Fortran order
+ auto mesh = meshes[field_name];
+ mesh.setDataOrder( openPMD::Mesh::DataOrder::F ); // MultiFab: Fortran order of indices and axes
mesh.setAxisLabels( axis_labels );
mesh.setGridSpacing( grid_spacing );
mesh.setGridGlobalOffset( global_offset );
+ mesh.setAttribute( "fieldSmoothing", "none" );
setOpenPMDUnit( mesh, field_name );
// Create a new mesh record component, and store the associated metadata
auto mesh_comp = mesh[comp_name];
mesh_comp.resetDataset( dataset );
// Cell-centered data: position is at 0.5 of a cell size.
- mesh_comp.setPosition(std::vector<double>{AMREX_D_DECL(0.5, 0.5, 0.5)});
+ mesh_comp.setPosition( std::vector<double>{AMREX_D_DECL(0.5, 0.5, 0.5)} );
// Loop through the multifab, and store each box as a chunk,
// in the openPMD file.
- for (amrex::MFIter mfi(mf); mfi.isValid(); ++mfi) {
+ for( amrex::MFIter mfi(mf); mfi.isValid(); ++mfi ) {
- const amrex::FArrayBox& fab = mf[mfi];
- const amrex::Box& local_box = fab.box();
+ amrex::FArrayBox const& fab = mf[mfi];
+ amrex::Box const& local_box = fab.box();
// Determine the offset and size of this chunk
- amrex::IntVect box_offset = local_box.smallEnd() - global_box.smallEnd();
- auto chunk_offset = getReversedVec(box_offset);
- auto chunk_size = getReversedVec(local_box.size());
+ amrex::IntVect const box_offset = local_box.smallEnd() - global_box.smallEnd();
+ auto const chunk_offset = getReversedVec( box_offset );
+ auto const chunk_size = getReversedVec( local_box.size() );
// Write local data
- const double* local_data = fab.dataPtr(icomp);
- mesh_comp.storeChunk(openPMD::shareRaw(local_data),
- chunk_offset, chunk_size);
+ double const * local_data = fab.dataPtr( icomp );
+ mesh_comp.storeChunk( openPMD::shareRaw(local_data),
+ chunk_offset, chunk_size );
}
}
// Flush data to disk after looping over all components