diff --git a/res/cmake/dep/highfive.cmake b/res/cmake/dep/highfive.cmake index 23baaff86..1b2cc9745 100644 --- a/res/cmake/dep/highfive.cmake +++ b/res/cmake/dep/highfive.cmake @@ -29,6 +29,8 @@ if(HighFive) ) set(HIGHFIVE_USE_BOOST OFF) set(HIGHFIVE_BUILD_DOCS OFF) # conflicts with phare doc target + set(HIGHFIVE_EXAMPLES OFF) + set(HIGHFIVE_PARALLEL_HDF5 ON) # causes failure if cannot occure add_subdirectory(${HIGHFIVE_SRC}) message("HighFive enabled - checking HDF5") diff --git a/res/cmake/test.cmake b/res/cmake/test.cmake index 05c994f2f..827c8dc72 100644 --- a/res/cmake/test.cmake +++ b/res/cmake/test.cmake @@ -22,6 +22,8 @@ # if level >= PHARE_EXEC_LEVEL_MIN AND level <= PHARE_EXEC_LEVEL_MAX # +# this define breaks pgcc / and appears unnecessary +# sed -i 's/# define GTEST_CAN_STREAM_RESULTS_ 1/# define GTEST_CAN_STREAM_RESULTS_ 0/g' subprojects/googletest/googletest/include/gtest/internal/gtest-port.h if (test AND ${PHARE_EXEC_LEVEL_MIN} GREATER 0) # 0 = no tests @@ -34,7 +36,6 @@ if (test AND ${PHARE_EXEC_LEVEL_MIN} GREATER 0) # 0 = no tests function(set_exe_paths_ binary) set_property(TEST ${binary} PROPERTY ENVIRONMENT "PYTHONPATH=${PHARE_PYTHONPATH}") - set_property(TEST ${binary} APPEND PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}") endfunction(set_exe_paths_) function(add_phare_test_ binary) diff --git a/src/amr/tagging/tagger.h b/src/amr/tagging/tagger.h index 0c47fe66a..e5e0149f8 100644 --- a/src/amr/tagging/tagger.h +++ b/src/amr/tagging/tagger.h @@ -2,8 +2,8 @@ #ifndef PHARE_TAGGER_H #define PHARE_TAGGER_H -#include "physical_models/physical_model.h" #include "amr/types/amr_types.h" +#include "solver/physical_models/physical_model.h" #include diff --git a/src/core/data/grid/gridlayout.h b/src/core/data/grid/gridlayout.h index df7850b51..a29ac475a 100644 --- a/src/core/data/grid/gridlayout.h +++ b/src/core/data/grid/gridlayout.h @@ -757,8 +757,9 @@ 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 + auto AMRToLocal(std::array const& AMRPoint) const { static_assert(std::is_integral_v, "Error, must be MeshIndex (integral Point)"); Point localPoint; @@ -774,6 +775,12 @@ namespace core return localPoint; } + template + auto AMRToLocal(Point AMRPoint) const + { + return AMRToLocal(AMRPoint()); + } + /** * @brief AMRToLocal returns the local Box associated with the given AMR one. diff --git a/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.h b/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.h index 2aa0d204e..df0424ffa 100644 --- a/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.h +++ b/src/core/data/ions/particle_initializers/maxwellian_particle_initializer.h @@ -144,16 +144,6 @@ void MaxwellianParticleInitializer::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 @@ -197,9 +187,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.h b/src/core/data/particles/particle_packer.h index b1fc792e7..e7aedc550 100644 --- a/src/core/data/particles/particle_packer.h +++ b/src/core/data/particles/particle_packer.h @@ -10,6 +10,13 @@ namespace PHARE::core { +// PGI compiler doesn't (didn't at least) like static initializations of arrays, would result in an +// empty string +inline std::array packer_keys() +{ + return {"weight", "charge", "iCell", "delta", "v"}; +} + template class ParticlePacker { @@ -31,8 +38,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 +60,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.h b/src/core/data/particles/particle_utilities.h index de0453b1c..1f07b4e21 100644 --- a/src/core/data/particles/particle_utilities.h +++ b/src/core/data/particles/particle_utilities.h @@ -23,7 +23,7 @@ namespace core 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(particle.iCell); for (auto iDim = 0u; iDim < GridLayout::dimension; ++iDim) { diff --git a/src/core/numerics/interpolator/interpolator.h b/src/core/numerics/interpolator/interpolator.h index 55431959e..cae58400f 100644 --- a/src/core/numerics/interpolator/interpolator.h +++ b/src/core/numerics/interpolator/interpolator.h @@ -534,7 +534,7 @@ namespace core auto indexAndWeightDual = [this, &layout](auto const& part) { for (auto iDim = 0u; iDim < dimension; ++iDim) { - auto iCell = layout.AMRToLocal(Point{part.iCell}); + auto iCell = layout.AMRToLocal(part.iCell); double normalizedPos = iCell[iDim] + part.delta[iDim] + dualOffset(interpOrder); startIndex_[centering2int(QtyCentering::dual)][iDim] @@ -550,7 +550,7 @@ namespace core auto indexAndWeightPrimal = [this, &layout](auto const& part) { for (auto iDim = 0u; iDim < dimension; ++iDim) { - auto iCell = layout.AMRToLocal(Point{part.iCell}); + auto iCell = layout.AMRToLocal(part.iCell); double normalizedPos = iCell[iDim] + part.delta[iDim]; startIndex_[centering2int(QtyCentering::primal)][iDim] @@ -623,7 +623,7 @@ namespace core auto indexAndWeightDual = [this, &layout](auto const& part) { for (auto iDim = 0u; iDim < dimension; ++iDim) { - auto iCell = layout.AMRToLocal(Point{part.iCell}); + auto iCell = layout.AMRToLocal(part.iCell); double normalizedPos = iCell[iDim] + part.delta[iDim] + dualOffset(interpOrder); startIndex_[centering2int(QtyCentering::dual)][iDim] @@ -639,7 +639,7 @@ namespace core auto indexAndWeightPrimal = [this, &layout](auto const& part) { for (auto iDim = 0u; iDim < dimension; ++iDim) { - auto iCell = layout.AMRToLocal(Point{part.iCell}); + auto iCell = layout.AMRToLocal(part.iCell); double normalizedPos = iCell[iDim] + part.delta[iDim]; startIndex_[centering2int(QtyCentering::primal)][iDim] diff --git a/src/core/utilities/mpi_utils.h b/src/core/utilities/mpi_utils.h index fc698000b..27f8d85d9 100644 --- a/src/core/utilities/mpi_utils.h +++ b/src/core/utilities/mpi_utils.h @@ -29,7 +29,7 @@ int size(); int rank(); template -auto mpi_type_for() +MPI_Datatype mpi_type_for() { if constexpr (std::is_same_v) return MPI_DOUBLE; @@ -45,7 +45,7 @@ auto mpi_type_for() return MPI_UINT64_T; else if constexpr (std::is_same_v) return MPI_CHAR; - + // don't return anything = compile failure if tried to use this function } @@ -73,9 +73,9 @@ void _collect_vector(SendBuff const& sendBuff, RcvBuff& rcvBuff, std::vector const& displs, int const mpi_size) { auto mpi_type = mpi_type_for(); - + assert(recvcounts.size() == displs.size() and static_cast(displs.size()) == mpi_size); - + MPI_Allgatherv( // MPI_Allgatherv sendBuff.data(), // void *sendbuf, sendBuff.size(), // int sendcount, @@ -85,7 +85,7 @@ void _collect_vector(SendBuff const& sendBuff, RcvBuff& rcvBuff, std::vector diff --git a/src/core/utilities/point/point.h b/src/core/utilities/point/point.h index cac93ec1b..8811feeb1 100644 --- a/src/core/utilities/point/point.h +++ b/src/core/utilities/point/point.h @@ -129,6 +129,7 @@ namespace core auto begin() { return r.begin(); } auto end() { return r.end(); } + auto const& operator()() const { return r; } private: std::array r{}; diff --git a/src/core/utilities/types.h b/src/core/utilities/types.h index 93fe7d0a8..1d464fd14 100644 --- a/src/core/utilities/types.h +++ b/src/core/utilities/types.h @@ -165,6 +165,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.h b/src/diagnostic/detail/h5writer.h index c7664af80..a7edc32a7 100644 --- a/src/diagnostic/detail/h5writer.h +++ b/src/diagnostic/detail/h5writer.h @@ -17,6 +17,7 @@ #include "core/utilities/types.h" + namespace PHARE::diagnostic::h5 { template @@ -287,11 +288,16 @@ void Writer::createDatasetsPerMPI(HiFile& h5file, std::string path, 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 (sizes[i] == 0) continue; + createGroupsToDataSet(h5file, paths[i]); + + assert(paths[i].back() != '/'); + h5file.createDataSet(paths[i], HighFive::DataSpace(sizes[i])); } } @@ -306,31 +312,43 @@ void Writer::createDatasetsPerMPI(HiFile& h5file, std::string path, * 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); + } +} + 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) - 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++) { @@ -341,13 +359,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]); } } } @@ -428,4 +446,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.h b/src/diagnostic/detail/types/particle.h index f5b06dedb..48c7cc18a 100644 --- a/src/diagnostic/detail/types/particle.h +++ b/src/diagnostic/detail/types/particle.h @@ -12,6 +12,8 @@ #include #include + + namespace PHARE::diagnostic::h5 { /* @@ -92,8 +94,9 @@ void ParticlesDiagnosticWriter::getDataSetInfo(DiagnosticProperties& d auto particleInfo = [&](auto& attr, auto& particles) { std::size_t part_idx = 0; + auto keys = core::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; }); }; @@ -138,9 +141,11 @@ 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], - null ? 0 : attr[Packer::keys()[part_idx]].template to(), - arg); + auto keys = core::packer_keys(); + // PGI compiler doesn't like static array initializations + assert(keys[part_idx].size() > 0); + createDataSet(path + keys[part_idx], + null ? 0 : attr[keys[part_idx]].template to(), arg); ++part_idx; }); this->writeGhostsAttr_(h5file, path, amr::ghostWidthForParticles(), null); @@ -178,11 +183,12 @@ void ParticlesDiagnosticWriter::write(DiagnosticProperties& diagnostic core::ContiguousParticles copy{particles.size()}; packer.pack(copy); - h5Writer.writeDataSet(h5file, path + packer.keys()[0], copy.weight.data()); - h5Writer.writeDataSet(h5file, path + packer.keys()[1], copy.charge.data()); - h5Writer.writeDataSet(h5file, path + packer.keys()[2], copy.iCell.data()); - h5Writer.writeDataSet(h5file, path + packer.keys()[3], copy.delta.data()); - h5Writer.writeDataSet(h5file, path + packer.keys()[4], copy.v.data()); + auto keys = core::packer_keys(); + h5Writer.writeDataSet(h5file, path + keys[0], copy.weight.data()); + h5Writer.writeDataSet(h5file, path + keys[1], copy.charge.data()); + h5Writer.writeDataSet(h5file, path + keys[2], copy.iCell.data()); + h5Writer.writeDataSet(h5file, path + keys[3], copy.delta.data()); + h5Writer.writeDataSet(h5file, path + keys[4], copy.v.data()); }; auto checkWrite = [&](auto& tree, auto pType, auto& ps) { @@ -227,7 +233,7 @@ void ParticlesDiagnosticWriter::writeAttributes( writeAttributes_(diagnostic, h5file, fileAttributes, patchAttributes, maxLevel); } - } // namespace PHARE::diagnostic::h5 + #endif /* PHARE_DIAGNOSTIC_DETAIL_TYPES_PARTICLE_H */ diff --git a/tests/core/data/particles/test_main.cpp b/tests/core/data/particles/test_main.cpp index dc3657e86..3ea38419c 100644 --- a/tests/core/data/particles/test_main.cpp +++ b/tests/core/data/particles/test_main.cpp @@ -92,7 +92,7 @@ TEST_F(AParticle, CanBeReducedToAnAbsolutePositionPoint) GridLayout> layout{meshSize, nbrCells, origin, Box{Point{40, 60, 80}, Point{59, 89, 119}}}; - auto iCell = layout.AMRToLocal(Point{part.iCell}); + auto iCell = layout.AMRToLocal(part.iCell); auto p = positionAsPoint(part, layout); auto startIndexes = layout.physicalStartIndex(QtyCentering::primal); auto expectedPosition = Point{};