diff --git a/src/core/data/grid/gridlayout.hpp b/src/core/data/grid/gridlayout.hpp index 6adbb01af..5a875451f 100644 --- a/src/core/data/grid/gridlayout.hpp +++ b/src/core/data/grid/gridlayout.hpp @@ -794,6 +794,7 @@ namespace core * @brief AMRToLocal returns the local index associated with the given AMR one. * This method only deals with **cell** indexes. */ + template auto AMRToLocal(Point AMRPoint) const { diff --git a/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp b/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp index 9c44ec623..ae644c59a 100644 --- a/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp +++ b/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp @@ -56,8 +56,7 @@ class MaxwellianParticleInitializer : public ParticleInitializer::loadParticles( }; - auto deltas = [](auto& pos, auto& gen) -> std::array { - if constexpr (dimension == 1) - return {pos(gen)}; - if constexpr (dimension == 2) - return {pos(gen), pos(gen)}; - if constexpr (dimension == 3) - return {pos(gen), pos(gen), pos(gen)}; - }; - - // in the following two calls, // primal indexes are given here because that's what cellCenteredCoordinates takes @@ -196,9 +185,10 @@ void MaxwellianParticleInitializer::loadParticles( if (basis_ == Basis::Magnetic) particleVelocity = basisTransform(basis, particleVelocity); - particles.emplace_back(Particle{cellWeight, particleCharge_, - AMRCellIndex.template toArray(), - deltas(deltaDistrib, randGen), particleVelocity}); + particles.emplace_back( + Particle{cellWeight, particleCharge_, AMRCellIndex.template toArray(), + core::ConstArrayFrom([&] { return deltaDistrib(randGen); }), + particleVelocity}); } } } diff --git a/src/core/data/particles/particle_packer.hpp b/src/core/data/particles/particle_packer.hpp index 2e5d4cb90..683ef3605 100644 --- a/src/core/data/particles/particle_packer.hpp +++ b/src/core/data/particles/particle_packer.hpp @@ -10,6 +10,14 @@ namespace PHARE::core { +// PGI compiler (nvc++ 21.3-0) doesn't like static initializations of arrays, +// would result in empty strings +inline std::array packer_keys() +{ + // The order of this array must match the tuple order of ParticlePacker::get(particle) + return {"weight", "charge", "iCell", "delta", "v"}; +} + template class ParticlePacker { @@ -31,8 +39,6 @@ class ParticlePacker return get(particle); } - static auto& keys() { return keys_; } - auto get(std::size_t i) const { return get(particles_[i]); } bool hasNext() const { return it_ < particles_.size(); } auto next() { return get(it_++); } @@ -55,10 +61,10 @@ class ParticlePacker } } + private: ParticleArray const& particles_; std::size_t it_ = 0; - static inline std::array keys_{"weight", "charge", "iCell", "delta", "v"}; }; diff --git a/src/core/data/particles/particle_utilities.hpp b/src/core/data/particles/particle_utilities.hpp index d3a5aca48..b92688f71 100644 --- a/src/core/data/particles/particle_utilities.hpp +++ b/src/core/data/particles/particle_utilities.hpp @@ -21,7 +21,7 @@ auto positionAsPoint(Particle const& particle, GridLayout auto origin = layout.origin(); auto startIndexes = layout.physicalStartIndex(QtyCentering::primal); auto meshSize = layout.meshSize(); - auto iCell = layout.AMRToLocal(Point{particle.iCell}); + auto iCell = layout.AMRToLocal(Point{particle.iCell}); for (auto iDim = 0u; iDim < GridLayout::dimension; ++iDim) { diff --git a/src/core/utilities/mpi_utils.hpp b/src/core/utilities/mpi_utils.hpp index aac4b9935..5b90fa1cb 100644 --- a/src/core/utilities/mpi_utils.hpp +++ b/src/core/utilities/mpi_utils.hpp @@ -34,7 +34,7 @@ int rank(); void barrier(); template -auto mpi_type_for() +MPI_Datatype mpi_type_for() { if constexpr (std::is_same_v) return MPI_DOUBLE; diff --git a/src/core/utilities/point/point.hpp b/src/core/utilities/point/point.hpp index d67949585..ff973b133 100644 --- a/src/core/utilities/point/point.hpp +++ b/src/core/utilities/point/point.hpp @@ -37,6 +37,7 @@ namespace core static constexpr std::size_t dimension = dim; using type = Type; + template constexpr Point(Indexes... index) : r{{index...}} @@ -172,12 +173,15 @@ namespace core std::array r{}; }; - template + template), void>::type> Point(Indexes... indexes) ->Point>::type, sizeof...(indexes)>; + } // namespace core } // namespace PHARE diff --git a/src/core/utilities/types.hpp b/src/core/utilities/types.hpp index 2862163cd..09854f954 100644 --- a/src/core/utilities/types.hpp +++ b/src/core/utilities/types.hpp @@ -167,6 +167,15 @@ namespace core return arr; } + template + constexpr auto ConstArrayFrom(FN fn) + { + std::array arr{}; + for (uint8_t i = 0; i < size; i++) + arr[i] = fn(); + return arr; + } + template std::vector displacementFrom(std::vector const& input) { diff --git a/src/diagnostic/detail/h5writer.hpp b/src/diagnostic/detail/h5writer.hpp index 2962df38b..2c694a179 100644 --- a/src/diagnostic/detail/h5writer.hpp +++ b/src/diagnostic/detail/h5writer.hpp @@ -309,11 +309,16 @@ void Writer::createDatasetsPerMPI(HiFile& h5file, std::string path, S auto mpi_size = core::mpi::size(); auto sizes = core::mpi::collect(dataSetSize, mpi_size); auto paths = core::mpi::collect(path, mpi_size); + for (int i = 0; i < mpi_size; i++) { if (is_zero(sizes[i])) continue; + createGroupsToDataSet(h5file, paths[i]); + + assert(paths[i].back() != '/'); + h5file.createDataSet(paths[i], HighFive::DataSpace(sizes[i])); } } @@ -328,34 +333,43 @@ void Writer::createDatasetsPerMPI(HiFile& h5file, std::string path, S * sizes. Recommended to use similar sized paths, if possible. key is always assumed to the be * the same */ +namespace +{ + // openacc compiler has issues with the lambda version + template + void _doAttribute(H5Node&& node, std::string const& key, core::Span const& value) + { + node.template createAttribute(key, HighFive::DataSpace(value.size())) + .write(value.data()); + } + + template + void _doAttribute(H5Node&& node, std::string const& key, T const& value) + { + node.template createAttribute(key, HighFive::DataSpace::From(value)).write(value); + } + + template + auto _values(std::vector const& data, int mpi_size) + { + return core::mpi::collect_raw(data, mpi_size); + } + + template + auto _values(T const& data, int mpi_size) + { + return core::mpi::collect(data, mpi_size); + } +} // namespace + template template void Writer::writeAttributesPerMPI(HiFile& h5file, std::string path, std::string key, Data const& data) { - constexpr bool data_is_vector = core::is_std_vector_v; - - auto doAttribute = [&](auto node, auto const& _key, auto const& value) { - if constexpr (data_is_vector) - { - if (value.size()) - node.template createAttribute( - _key, HighFive::DataSpace(value.size())) - .write(value.data()); - } - else - node.template createAttribute(_key, HighFive::DataSpace::From(value)) - .write(value); - }; - int mpi_size = core::mpi::size(); - auto values = [&]() { - if constexpr (data_is_vector) - return core::mpi::collect_raw(data, mpi_size); - else - return core::mpi::collect(data, mpi_size); - }(); - auto paths = core::mpi::collect(path, mpi_size); + auto values = _values(data, mpi_size); + auto paths = core::mpi::collect(path, mpi_size); for (int i = 0; i < mpi_size; i++) { @@ -366,13 +380,13 @@ void Writer::writeAttributesPerMPI(HiFile& h5file, std::string path, if (h5file.exist(keyPath) && h5file.getObjectType(keyPath) == HighFive::ObjectType::Dataset) { if (!h5file.getDataSet(keyPath).hasAttribute(key)) - doAttribute(h5file.getDataSet(keyPath), key, values[i]); + _doAttribute(h5file.getDataSet(keyPath), key, values[i]); } else // group { createGroupsToDataSet(h5file, keyPath + "/dataset"); if (!h5file.getGroup(keyPath).hasAttribute(key)) - doAttribute(h5file.getGroup(keyPath), key, values[i]); + _doAttribute(h5file.getGroup(keyPath), key, values[i]); } } } @@ -454,4 +468,6 @@ void Writer::writeDatasets_(std::vector const& } /* namespace PHARE::diagnostic::h5 */ + + #endif /* PHARE_DETAIL_DIAGNOSTIC_HIGHFIVE_H */ diff --git a/src/diagnostic/detail/types/particle.hpp b/src/diagnostic/detail/types/particle.hpp index 1ab613cb1..f7a26323d 100644 --- a/src/diagnostic/detail/types/particle.hpp +++ b/src/diagnostic/detail/types/particle.hpp @@ -12,6 +12,8 @@ #include #include + + namespace PHARE::diagnostic::h5 { /* @@ -61,6 +63,10 @@ class ParticlesDiagnosticWriter : public H5TypeWriter DiagnosticProperties&, Attributes&, std::unordered_map>>&, std::size_t maxLevel) override; + +private: + // PGI compiler (nvc++ 21.3-0) doesn't like static initializations of arrays + std::array packer_keys_ = core::packer_keys(); }; @@ -95,8 +101,9 @@ void ParticlesDiagnosticWriter::getDataSetInfo(DiagnosticProperties& d auto particleInfo = [&](auto& attr, auto& particles) { std::size_t part_idx = 0; + auto const& keys = packer_keys_; core::apply(Packer::empty(), [&](auto const& arg) { - attr[Packer::keys()[part_idx]] = getSize(arg, particles.size()); + attr[keys[part_idx]] = getSize(arg, particles.size()); ++part_idx; }); }; @@ -147,8 +154,8 @@ void ParticlesDiagnosticWriter::initDataSets( std::string path{h5Writer_.getPatchPathAddTimestamp(lvl, patchID) + "/"}; std::size_t part_idx = 0; core::apply(Packer::empty(), [&](auto const& arg) { - createDataSet(path + Packer::keys()[part_idx], attr, Packer::keys()[part_idx], arg, - null); + auto const& keys = packer_keys_; + createDataSet(path + keys[part_idx], attr, keys[part_idx], arg, null); ++part_idx; }); this->writeGhostsAttr_(h5file, path, core::ghostWidthForParticles(), null); @@ -187,12 +194,12 @@ void ParticlesDiagnosticWriter::write(DiagnosticProperties& diagnostic core::ContiguousParticles copy{particles.size()}; packer.pack(copy); - - h5file.template write_data_set_flat<2>(path + packer.keys()[0], copy.weight.data()); - h5file.template write_data_set_flat<2>(path + packer.keys()[1], copy.charge.data()); - h5file.template write_data_set_flat<2>(path + packer.keys()[2], copy.iCell.data()); - h5file.template write_data_set_flat<2>(path + packer.keys()[3], copy.delta.data()); - h5file.template write_data_set_flat<2>(path + packer.keys()[4], copy.v.data()); + auto const& keys = packer_keys_; + h5file.template write_data_set_flat<2>(path + keys[0], copy.weight.data()); + h5file.template write_data_set_flat<2>(path + keys[1], copy.charge.data()); + h5file.template write_data_set_flat<2>(path + keys[2], copy.iCell.data()); + h5file.template write_data_set_flat<2>(path + keys[3], copy.delta.data()); + h5file.template write_data_set_flat<2>(path + keys[4], copy.v.data()); }; auto checkWrite = [&](auto& tree, auto pType, auto& ps) { @@ -237,7 +244,7 @@ void ParticlesDiagnosticWriter::writeAttributes( writeAttributes_(diagnostic, h5file, fileAttributes, patchAttributes, maxLevel); } - } // namespace PHARE::diagnostic::h5 + #endif /* PHARE_DIAGNOSTIC_DETAIL_TYPES_PARTICLE_H */