From 8475ac89baf019c2d54810825361dcdccc7b6383 Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Fri, 10 Feb 2023 11:19:49 -0700 Subject: [PATCH 01/43] Make StateDescriptor polymorphic as needed for user package subclassing. --- src/interface/state_descriptor.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/interface/state_descriptor.hpp b/src/interface/state_descriptor.hpp index cecb6ba14602..81af5d5aeb26 100644 --- a/src/interface/state_descriptor.hpp +++ b/src/interface/state_descriptor.hpp @@ -129,6 +129,9 @@ class StateDescriptor { // Preferred constructor explicit StateDescriptor(std::string const &label) : label_(label) {} + // Virtual destructor for subclassing + virtual ~StateDescriptor() = default; + static std::shared_ptr CreateResolvedStateDescriptor(Packages_t &packages); From a1b4caebb03ffa1ca6184ea7979b3ec03aafae6c Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Wed, 19 Apr 2023 10:17:31 -0600 Subject: [PATCH 02/43] PEP1: New functions for getting packages/lists by type --- src/interface/packages.hpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/interface/packages.hpp b/src/interface/packages.hpp index 443061d8172e..1c2ce247d34d 100644 --- a/src/interface/packages.hpp +++ b/src/interface/packages.hpp @@ -30,10 +30,43 @@ class Packages_t { return packages_.at(name); } + // Templated version for retrieving a package with a particular type + // Allows subclassing 'StateDescriptor' to add user package types to list + template + T* const &Get(const std::string &name) { + return static_cast(packages_.at(name).get()); + } + const Dictionary> &AllPackages() const { return packages_; } + // Returns a sub-Dictionary containing just pointers to packages of type T. + // Dictionary is a *new copy*, and members are bare pointers, not shared_ptr. + template + const std::vector AllPackagesOfType() const { + Dictionary sub_dict; + for (auto package : packages_) { + if (T *cast_package = dynamic_cast(package.second.get())) { + sub_dict[package.first] = cast_package; + } + } + return sub_dict; + } + + // Returns a list of pointers to packages of type T. + // List contains bare pointers, not shared_ptr objects + template + const std::vector ListPackagesOfType() const { + std::vector sub_list; + for (auto package : packages_) { + if (T *cast_package = dynamic_cast(package.second.get())) { + sub_list.append(cast_package); + } + } + return sub_list; + } + private: Dictionary> packages_; }; From 2d2ccd76e7729abb783391d4833a80ad856f4b52 Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Wed, 10 May 2023 14:02:35 -0500 Subject: [PATCH 03/43] PEP1: Fix type issues --- src/interface/packages.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/interface/packages.hpp b/src/interface/packages.hpp index 1c2ce247d34d..32bbc07eab53 100644 --- a/src/interface/packages.hpp +++ b/src/interface/packages.hpp @@ -44,7 +44,7 @@ class Packages_t { // Returns a sub-Dictionary containing just pointers to packages of type T. // Dictionary is a *new copy*, and members are bare pointers, not shared_ptr. template - const std::vector AllPackagesOfType() const { + const Dictionary AllPackagesOfType() const { Dictionary sub_dict; for (auto package : packages_) { if (T *cast_package = dynamic_cast(package.second.get())) { @@ -61,7 +61,7 @@ class Packages_t { std::vector sub_list; for (auto package : packages_) { if (T *cast_package = dynamic_cast(package.second.get())) { - sub_list.append(cast_package); + sub_list.push_back(cast_package); } } return sub_list; From 89c833329e9f94b3c50e2c99383f0a52de7e199f Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Wed, 10 May 2023 18:55:27 -0500 Subject: [PATCH 04/43] PEP1: Return pointer directly from Get<> as one might expect --- src/interface/packages.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/interface/packages.hpp b/src/interface/packages.hpp index 32bbc07eab53..82b15a8adbef 100644 --- a/src/interface/packages.hpp +++ b/src/interface/packages.hpp @@ -26,14 +26,14 @@ class Packages_t { Packages_t() = default; void Add(const std::shared_ptr &package); - std::shared_ptr const &Get(const std::string &name) { + std::shared_ptr const &Get(const std::string &name) const { return packages_.at(name); } // Templated version for retrieving a package with a particular type // Allows subclassing 'StateDescriptor' to add user package types to list template - T* const &Get(const std::string &name) { + T* Get(const std::string &name) const { return static_cast(packages_.at(name).get()); } From 977e60d1bd55f06e25f11a34b616acfd3b039a40 Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Fri, 10 Feb 2023 11:19:49 -0700 Subject: [PATCH 05/43] Make StateDescriptor polymorphic as needed for user package subclassing. --- src/interface/state_descriptor.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/interface/state_descriptor.hpp b/src/interface/state_descriptor.hpp index ac9a93dcb58a..02f75120930c 100644 --- a/src/interface/state_descriptor.hpp +++ b/src/interface/state_descriptor.hpp @@ -102,6 +102,9 @@ class StateDescriptor { // Preferred constructor explicit StateDescriptor(std::string const &label) : label_(label) {} + // Virtual destructor for subclassing + virtual ~StateDescriptor() = default; + static std::shared_ptr CreateResolvedStateDescriptor(Packages_t &packages); From 63bd1fbf94dd77af81cd3cb0c34732b2f8896ce6 Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Wed, 19 Apr 2023 10:17:31 -0600 Subject: [PATCH 06/43] PEP1: New functions for getting packages/lists by type --- src/interface/packages.hpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/interface/packages.hpp b/src/interface/packages.hpp index 285a815bf9ea..70966617266c 100644 --- a/src/interface/packages.hpp +++ b/src/interface/packages.hpp @@ -30,11 +30,44 @@ class Packages_t { return packages_.at(name); } + // Templated version for retrieving a package with a particular type + // Allows subclassing 'StateDescriptor' to add user package types to list + template + T* const &Get(const std::string &name) { + return static_cast(packages_.at(name).get()); + } + const Dictionary> &AllPackages() const { return packages_; } Dictionary> &AllPackages() { return packages_; } + // Returns a sub-Dictionary containing just pointers to packages of type T. + // Dictionary is a *new copy*, and members are bare pointers, not shared_ptr. + template + const std::vector AllPackagesOfType() const { + Dictionary sub_dict; + for (auto package : packages_) { + if (T *cast_package = dynamic_cast(package.second.get())) { + sub_dict[package.first] = cast_package; + } + } + return sub_dict; + } + + // Returns a list of pointers to packages of type T. + // List contains bare pointers, not shared_ptr objects + template + const std::vector ListPackagesOfType() const { + std::vector sub_list; + for (auto package : packages_) { + if (T *cast_package = dynamic_cast(package.second.get())) { + sub_list.append(cast_package); + } + } + return sub_list; + } + private: Dictionary> packages_; }; From 0e7a3ba879caa3fadbd44df864794a10a64f382e Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Wed, 12 Jul 2023 16:36:39 -0600 Subject: [PATCH 07/43] Style --- src/interface/packages.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/interface/packages.hpp b/src/interface/packages.hpp index cfd5a71c95d4..92336f5617cb 100644 --- a/src/interface/packages.hpp +++ b/src/interface/packages.hpp @@ -16,6 +16,7 @@ #include #include +#include #include "basic_types.hpp" From 77b1e2ab756c9b95098f254785ba9e3116c84d68 Mon Sep 17 00:00:00 2001 From: par-hermes Date: Thu, 13 Jul 2023 00:13:00 +0000 Subject: [PATCH 08/43] cpp-py-formatter --- src/interface/packages.hpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/interface/packages.hpp b/src/interface/packages.hpp index 92336f5617cb..bd311c821ccd 100644 --- a/src/interface/packages.hpp +++ b/src/interface/packages.hpp @@ -33,9 +33,9 @@ class Packages_t { // Templated version for retrieving a package with a particular type // Allows subclassing 'StateDescriptor' to add user package types to list - template - T* const &Get(const std::string &name) const { - return static_cast(packages_.at(name).get()); + template + T *const &Get(const std::string &name) const { + return static_cast(packages_.at(name).get()); } const Dictionary> &AllPackages() const { @@ -46,10 +46,10 @@ class Packages_t { // Returns a sub-Dictionary containing just pointers to packages of type T. // Dictionary is a *new copy*, and members are bare pointers, not shared_ptr. template - const std::vector AllPackagesOfType() const { - Dictionary sub_dict; + const std::vector AllPackagesOfType() const { + Dictionary sub_dict; for (auto package : packages_) { - if (T *cast_package = dynamic_cast(package.second.get())) { + if (T *cast_package = dynamic_cast(package.second.get())) { sub_dict[package.first] = cast_package; } } @@ -59,10 +59,10 @@ class Packages_t { // Returns a list of pointers to packages of type T. // List contains bare pointers, not shared_ptr objects template - const std::vector ListPackagesOfType() const { - std::vector sub_list; + const std::vector ListPackagesOfType() const { + std::vector sub_list; for (auto package : packages_) { - if (T *cast_package = dynamic_cast(package.second.get())) { + if (T *cast_package = dynamic_cast(package.second.get())) { sub_list.append(cast_package); } } @@ -72,10 +72,10 @@ class Packages_t { // Returns a sub-Dictionary containing just pointers to packages of type T. // Dictionary is a *new copy*, and members are bare pointers, not shared_ptr. template - const Dictionary AllPackagesOfType() const { - Dictionary sub_dict; + const Dictionary AllPackagesOfType() const { + Dictionary sub_dict; for (auto package : packages_) { - if (T *cast_package = dynamic_cast(package.second.get())) { + if (T *cast_package = dynamic_cast(package.second.get())) { sub_dict[package.first] = cast_package; } } From 661ae4595981c652b73a3d9b12e6e53c50ab9991 Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Wed, 9 Aug 2023 15:33:41 -0600 Subject: [PATCH 09/43] Fix the rest of merge duplication --- src/interface/packages.hpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/interface/packages.hpp b/src/interface/packages.hpp index bd311c821ccd..f1312d433348 100644 --- a/src/interface/packages.hpp +++ b/src/interface/packages.hpp @@ -69,19 +69,6 @@ class Packages_t { return sub_list; } - // Returns a sub-Dictionary containing just pointers to packages of type T. - // Dictionary is a *new copy*, and members are bare pointers, not shared_ptr. - template - const Dictionary AllPackagesOfType() const { - Dictionary sub_dict; - for (auto package : packages_) { - if (T *cast_package = dynamic_cast(package.second.get())) { - sub_dict[package.first] = cast_package; - } - } - return sub_dict; - } - private: Dictionary> packages_; }; From ce9786a6a6c117edba5081f98dd1ec92d2382d2d Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Thu, 10 Aug 2023 15:36:44 -0600 Subject: [PATCH 10/43] Fix two issues for KHARMA that didn't make it to backport branch --- src/interface/packages.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/interface/packages.hpp b/src/interface/packages.hpp index f1312d433348..a5e12be47944 100644 --- a/src/interface/packages.hpp +++ b/src/interface/packages.hpp @@ -34,7 +34,7 @@ class Packages_t { // Templated version for retrieving a package with a particular type // Allows subclassing 'StateDescriptor' to add user package types to list template - T *const &Get(const std::string &name) const { + T *const Get(const std::string &name) const { return static_cast(packages_.at(name).get()); } @@ -46,7 +46,7 @@ class Packages_t { // Returns a sub-Dictionary containing just pointers to packages of type T. // Dictionary is a *new copy*, and members are bare pointers, not shared_ptr. template - const std::vector AllPackagesOfType() const { + const Dictionary AllPackagesOfType() const { Dictionary sub_dict; for (auto package : packages_) { if (T *cast_package = dynamic_cast(package.second.get())) { From eb4cf775e048020ecd7a9b953cd792ea91b9726a Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Thu, 10 Aug 2023 16:47:11 -0600 Subject: [PATCH 11/43] PEP1: changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d841a9231061..6fccd6473415 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Current develop ### Added (new features/APIs/variables/...) +- [[PR 907]](https://github.com/parthenon-hpc-lab/parthenon/pull/907) PEP1: Allow subclassing StateDescriptor - [[PR 900]](https://github.com/parthenon-hpc-lab/parthenon/pull/900) Add Morton numbers and expand functionality of LogicalLocation - [[PR 902]](https://github.com/parthenon-hpc-lab/parthenon/pull/902) Add ability to output NaNs for de-allocated sparse fields - [[PR 887]](https://github.com/parthenon-hpc-lab/parthenon/pull/887) Add ability to dump more types of params and read them from restarts From f5ddad85540585983c93c6edaaf9ee471837bd59 Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Fri, 11 Aug 2023 13:41:40 -0600 Subject: [PATCH 12/43] Remove useless const --- src/interface/packages.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/interface/packages.hpp b/src/interface/packages.hpp index a5e12be47944..65f1d18e5561 100644 --- a/src/interface/packages.hpp +++ b/src/interface/packages.hpp @@ -31,10 +31,9 @@ class Packages_t { return packages_.at(name); } - // Templated version for retrieving a package with a particular type - // Allows subclassing 'StateDescriptor' to add user package types to list + // Retrieve a package pointer, cast to a given type T template - T *const Get(const std::string &name) const { + T* Get(const std::string &name) const { return static_cast(packages_.at(name).get()); } From 608721e91b50872ed29df208681038e3e1447eae Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Mon, 14 Aug 2023 10:04:17 -0600 Subject: [PATCH 13/43] pep1: format --- src/interface/packages.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface/packages.hpp b/src/interface/packages.hpp index 65f1d18e5561..1ef6db59f58f 100644 --- a/src/interface/packages.hpp +++ b/src/interface/packages.hpp @@ -33,7 +33,7 @@ class Packages_t { // Retrieve a package pointer, cast to a given type T template - T* Get(const std::string &name) const { + T *Get(const std::string &name) const { return static_cast(packages_.at(name).get()); } From 1e77d2f8957a54c47ebbb97f59d956a008179f1b Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Tue, 22 Aug 2023 16:54:57 -0600 Subject: [PATCH 14/43] First shot at fixing a subtle bug During re-meshing, track which meshblocks are newly created. After prolongating shared boundaries, but before prolongating internal boundaries, update elements on block faces to respect the ownership model. Still needs tweaks to the new-mesh priority! --- src/bvals/bvals.hpp | 6 +++-- src/bvals/bvals_base.cpp | 14 ++++++------ src/defs.hpp | 4 ++-- src/mesh/amr_loadbalance.cpp | 42 ++++++++++++++++++++++++++--------- src/mesh/logical_location.hpp | 17 ++++++++++---- src/mesh/mesh.cpp | 22 +++++------------- 6 files changed, 63 insertions(+), 42 deletions(-) diff --git a/src/bvals/bvals.hpp b/src/bvals/bvals.hpp index 827abac792ca..c36aebbb25cf 100644 --- a/src/bvals/bvals.hpp +++ b/src/bvals/bvals.hpp @@ -20,6 +20,7 @@ // \brief defines BoundaryBase, BoundaryValues classes used for setting BCs on all data #include +#include #include #include @@ -78,7 +79,8 @@ class BoundaryBase { static int BufferID(int dim, bool multilevel); static int FindBufferID(int ox1, int ox2, int ox3, int fi1, int fi2); - void SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist, int *nslist); + void SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist, int *nslist, + const std::set &newly_refined = {}); protected: // 1D refined or unrefined=2 @@ -90,7 +92,7 @@ class BoundaryBase { RegionSize block_size_; ParArrayND sarea_[2]; - void SetNeighborOwnership(); + void SetNeighborOwnership(const std::set &newly_refined = {}); private: // calculate 3x shared static data members when constructing only the 1st class instance diff --git a/src/bvals/bvals_base.cpp b/src/bvals/bvals_base.cpp index d9ad5317ac93..e92623935fb3 100644 --- a/src/bvals/bvals_base.cpp +++ b/src/bvals/bvals_base.cpp @@ -300,8 +300,8 @@ int BoundaryBase::CreateBvalsMPITag(int lid, int bufid) { // TODO(felker): break-up this long function -void BoundaryBase::SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist, - int *nslist) { +void BoundaryBase::SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist, int *nslist, + const std::set &newly_refined) { Kokkos::Profiling::pushRegion("SearchAndSetNeighbors"); MeshBlockTree *neibt; int myox1, myox2 = 0, myox3 = 0, myfx1, myfx2, myfx3; @@ -368,7 +368,7 @@ void BoundaryBase::SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist, } } if (block_size_.nx(X2DIR) == 1) { - SetNeighborOwnership(); + SetNeighborOwnership(newly_refined); Kokkos::Profiling::popRegion(); // SearchAndSetNeighbors return; } @@ -503,7 +503,7 @@ void BoundaryBase::SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist, } if (block_size_.nx(X3DIR) == 1) { - SetNeighborOwnership(); + SetNeighborOwnership(newly_refined); Kokkos::Profiling::popRegion(); // SearchAndSetNeighbors return; } @@ -626,11 +626,11 @@ void BoundaryBase::SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist, } } - SetNeighborOwnership(); + SetNeighborOwnership(newly_refined); Kokkos::Profiling::popRegion(); // SearchAndSetNeighbors } -void BoundaryBase::SetNeighborOwnership() { +void BoundaryBase::SetNeighborOwnership(const std::set &newly_refined) { // Set neighbor block ownership std::set allowed_neighbors; allowed_neighbors.insert(loc); // Insert the location of this block @@ -642,7 +642,7 @@ void BoundaryBase::SetNeighborOwnership() { RootGridInfo rg_info = pmy_mesh_->GetRootGridInfo(); for (int n = 0; n < nneighbor; ++n) { neighbor[n].ownership = - DetermineOwnership(neighbor[n].loc, allowed_neighbors, rg_info); + DetermineOwnership(neighbor[n].loc, allowed_neighbors, rg_info, newly_refined); neighbor[n].ownership.initialized = true; } } diff --git a/src/defs.hpp b/src/defs.hpp index 15dc0d031f83..5f0d96eb950b 100644 --- a/src/defs.hpp +++ b/src/defs.hpp @@ -73,8 +73,8 @@ struct RegionSize { RegionSize() = default; RegionSize(std::array xmin, std::array xmax, std::array xrat, std::array nx) - : xmin_(xmin), xmax_(xmax), xrat_(xrat), - nx_(nx), symmetry_{nx[0] == 1, nx[1] == 1, nx[2] == 1} {} + : xmin_(xmin), xmax_(xmax), xrat_(xrat), nx_(nx), + symmetry_{nx[0] == 1, nx[1] == 1, nx[2] == 1} {} RegionSize(std::array xmin, std::array xmax, std::array xrat, std::array nx, std::array symmetry) : xmin_(xmin), xmax_(xmax), xrat_(xrat), nx_(nx), symmetry_(symmetry) {} diff --git a/src/mesh/amr_loadbalance.cpp b/src/mesh/amr_loadbalance.cpp index fb33d645f842..0681931cfbee 100644 --- a/src/mesh/amr_loadbalance.cpp +++ b/src/mesh/amr_loadbalance.cpp @@ -789,6 +789,7 @@ void Mesh::RedistributeAndRefineMeshBlocks(ParameterInput *pin, ApplicationInput RegionSize block_size = GetBlockSize(); BlockList_t new_block_list(nbe - nbs + 1); + std::set newly_refined; for (int n = nbs; n <= nbe; n++) { int on = newtoold[n]; if ((ranklist[on] == Globals::my_rank) && @@ -810,6 +811,7 @@ void Mesh::RedistributeAndRefineMeshBlocks(ParameterInput *pin, ApplicationInput new_block_list[n - nbs] = MeshBlock::Make(n, n - nbs, newloc[n], block_size, block_bcs, this, pin, app_in, packages, resolved_packages, gflag); + if (newloc[n].level() > loclist[on].level()) newly_refined.insert(newloc[n]); } } @@ -913,29 +915,47 @@ void Mesh::RedistributeAndRefineMeshBlocks(ParameterInput *pin, ApplicationInput } } prolongation_cache.CopyToDevice(); + refinement::ProlongateShared(resolved_packages.get(), prolongation_cache, block_list[0]->cellbounds, block_list[0]->c_cellbounds); - refinement::ProlongateInternal(resolved_packages.get(), prolongation_cache, - block_list[0]->cellbounds, block_list[0]->c_cellbounds); - -#ifdef MPI_PARALLEL - if (send_reqs.size() != 0) - PARTHENON_MPI_CHECK( - MPI_Waitall(send_reqs.size(), send_reqs.data(), MPI_STATUSES_IGNORE)); -#endif - Kokkos::Profiling::popRegion(); // AMR: Recv data and unpack // update the lists loclist = std::move(newloc); ranklist = std::move(newrank); costlist = std::move(newcost); - // re-initialize the MeshBlocks + // A block newly refined and prolongated may have neighbors which were + // already refined to the new level. + // If so, the prolongated versions of shared elements will not reflect + // the true, finer versions present in the neighbor block. + // We must create any new fine buffers and fill them from these neighbors + // in order to maintain a consistent global state. + // Thus we rebuild and synchronize the mesh now, but using a unique + // neighbor precedence favoring the "old" fine blocks over "new" ones for (auto &pmb : block_list) { - pmb->pbval->SearchAndSetNeighbors(tree, ranklist.data(), nslist.data()); + pmb->pbval->SearchAndSetNeighbors(tree, ranklist.data(), nslist.data(), + newly_refined); } Initialize(false, pin, app_in); + // Internal refinement relies on the fine shared values, which are only consistent after + // being updated with any previously fine versions + refinement::ProlongateInternal(resolved_packages.get(), prolongation_cache, + block_list[0]->cellbounds, block_list[0]->c_cellbounds); + + // Rebuild the ownership model, this time weighting the "new" fine blocks just like + // any other blocks at their level. + for (auto &pmb : block_list) { + pmb->pbval->SearchAndSetNeighbors(tree, ranklist.data(), nslist.data()); + } + +#ifdef MPI_PARALLEL + if (send_reqs.size() != 0) + PARTHENON_MPI_CHECK( + MPI_Waitall(send_reqs.size(), send_reqs.data(), MPI_STATUSES_IGNORE)); +#endif + Kokkos::Profiling::popRegion(); // AMR: Recv data and unpack + ResetLoadBalanceVariables(); Kokkos::Profiling::popRegion(); // RedistributeAndRefineMeshBlocks diff --git a/src/mesh/logical_location.hpp b/src/mesh/logical_location.hpp index 21dd7a52f513..0519a9f822d6 100644 --- a/src/mesh/logical_location.hpp +++ b/src/mesh/logical_location.hpp @@ -251,15 +251,24 @@ struct block_ownership_t { inline block_ownership_t DetermineOwnership(const LogicalLocation &main_block, const std::set &allowed_neighbors, - const RootGridInfo &rg_info = RootGridInfo()) { + const RootGridInfo &rg_info = RootGridInfo(), + const std::set &newly_refined = {}) { block_ownership_t main_owns; - auto ownership_less_than = [](const LogicalLocation &a, const LogicalLocation &b) { + auto ownership_level = [&](const LogicalLocation &a) { + // Newly-refined blocks must be treated as their parent level in the first sync + // during refinement. + if (newly_refined.count(a)) return a.level() - 1; + return a.level(); + }; + + auto ownership_less_than = [ownership_level](const LogicalLocation &a, + const LogicalLocation &b) { // Ownership is first determined by block with the highest level, then by maximum // Morton number this is reversed in precedence from the normal comparators where // Morton number takes precedence - if (a.level() == b.level()) return a.morton() < b.morton(); - return a.level() < b.level(); + if (ownership_level(a) == ownership_level(b)) return a.morton() < b.morton(); + return ownership_level(a) < ownership_level(b); }; for (int ox1 : {-1, 0, 1}) { diff --git a/src/mesh/mesh.cpp b/src/mesh/mesh.cpp index a53c89f647a1..cff06851f811 100644 --- a/src/mesh/mesh.cpp +++ b/src/mesh/mesh.cpp @@ -98,9 +98,9 @@ Mesh::Mesh(ParameterInput *pin, ApplicationInput *app_in, Packages_t &packages, // private members: num_mesh_threads_(pin->GetOrAddInteger("parthenon/mesh", "num_threads", 1)), tree(this), use_uniform_meshgen_fn_{true, true, true, true}, lb_flag_(true), - lb_automatic_(), lb_manual_(), MeshGenerator_{nullptr, UniformMeshGenerator, - UniformMeshGenerator, - UniformMeshGenerator}, + lb_automatic_(), lb_manual_(), + MeshGenerator_{nullptr, UniformMeshGenerator, UniformMeshGenerator, + UniformMeshGenerator}, MeshBndryFnctn{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr} { std::stringstream msg; RegionSize block_size; @@ -475,11 +475,6 @@ Mesh::Mesh(ParameterInput *pin, ApplicationInput *app_in, Packages_t &packages, } ResetLoadBalanceVariables(); - - // Output variables in use in this run - if (Globals::my_rank == 0) { - std::cout << "#Variables in use:\n" << *(resolved_packages) << std::endl; - } } //---------------------------------------------------------------------------------------- @@ -524,9 +519,9 @@ Mesh::Mesh(ParameterInput *pin, ApplicationInput *app_in, RestartReader &rr, // private members: num_mesh_threads_(pin->GetOrAddInteger("parthenon/mesh", "num_threads", 1)), tree(this), use_uniform_meshgen_fn_{true, true, true, true}, lb_flag_(true), - lb_automatic_(), lb_manual_(), MeshGenerator_{nullptr, UniformMeshGenerator, - UniformMeshGenerator, - UniformMeshGenerator}, + lb_automatic_(), lb_manual_(), + MeshGenerator_{nullptr, UniformMeshGenerator, UniformMeshGenerator, + UniformMeshGenerator}, MeshBndryFnctn{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr} { std::stringstream msg; RegionSize block_size; @@ -738,11 +733,6 @@ Mesh::Mesh(ParameterInput *pin, ApplicationInput *app_in, RestartReader &rr, } ResetLoadBalanceVariables(); - - // Output variables in use in this run - if (Globals::my_rank == 0) { - std::cout << "#Variables in use:\n" << *(resolved_packages) << std::endl; - } } //---------------------------------------------------------------------------------------- From d9820e8bc90fe2b1134d1cb2ace6d6fe205c9b94 Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Tue, 22 Aug 2023 17:22:52 -0600 Subject: [PATCH 15/43] Make the new-block ownership hierarchy a little more nuanced --- src/mesh/logical_location.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mesh/logical_location.hpp b/src/mesh/logical_location.hpp index 0519a9f822d6..937608961213 100644 --- a/src/mesh/logical_location.hpp +++ b/src/mesh/logical_location.hpp @@ -256,10 +256,11 @@ DetermineOwnership(const LogicalLocation &main_block, block_ownership_t main_owns; auto ownership_level = [&](const LogicalLocation &a) { - // Newly-refined blocks must be treated as their parent level in the first sync - // during refinement. - if (newly_refined.count(a)) return a.level() - 1; - return a.level(); + // Newly-refined blocks are treated as higher-level than blocks at their + // parent level, but lower-level than previously-refined blocks at their + // current level. + if (newly_refined.count(a)) return 2*a.level() - 1; + return 2*a.level(); }; auto ownership_less_than = [ownership_level](const LogicalLocation &a, From 45b64d6e643712860d55144e1b418cfa1ea897c8 Mon Sep 17 00:00:00 2001 From: par-hermes Date: Tue, 22 Aug 2023 23:44:17 +0000 Subject: [PATCH 16/43] cpp-py-formatter --- src/defs.hpp | 4 ++-- src/mesh/logical_location.hpp | 4 ++-- src/mesh/mesh.cpp | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/defs.hpp b/src/defs.hpp index 5f0d96eb950b..15dc0d031f83 100644 --- a/src/defs.hpp +++ b/src/defs.hpp @@ -73,8 +73,8 @@ struct RegionSize { RegionSize() = default; RegionSize(std::array xmin, std::array xmax, std::array xrat, std::array nx) - : xmin_(xmin), xmax_(xmax), xrat_(xrat), nx_(nx), - symmetry_{nx[0] == 1, nx[1] == 1, nx[2] == 1} {} + : xmin_(xmin), xmax_(xmax), xrat_(xrat), + nx_(nx), symmetry_{nx[0] == 1, nx[1] == 1, nx[2] == 1} {} RegionSize(std::array xmin, std::array xmax, std::array xrat, std::array nx, std::array symmetry) : xmin_(xmin), xmax_(xmax), xrat_(xrat), nx_(nx), symmetry_(symmetry) {} diff --git a/src/mesh/logical_location.hpp b/src/mesh/logical_location.hpp index 937608961213..7362cecf6eab 100644 --- a/src/mesh/logical_location.hpp +++ b/src/mesh/logical_location.hpp @@ -259,8 +259,8 @@ DetermineOwnership(const LogicalLocation &main_block, // Newly-refined blocks are treated as higher-level than blocks at their // parent level, but lower-level than previously-refined blocks at their // current level. - if (newly_refined.count(a)) return 2*a.level() - 1; - return 2*a.level(); + if (newly_refined.count(a)) return 2 * a.level() - 1; + return 2 * a.level(); }; auto ownership_less_than = [ownership_level](const LogicalLocation &a, diff --git a/src/mesh/mesh.cpp b/src/mesh/mesh.cpp index cff06851f811..f5411c70d013 100644 --- a/src/mesh/mesh.cpp +++ b/src/mesh/mesh.cpp @@ -98,9 +98,9 @@ Mesh::Mesh(ParameterInput *pin, ApplicationInput *app_in, Packages_t &packages, // private members: num_mesh_threads_(pin->GetOrAddInteger("parthenon/mesh", "num_threads", 1)), tree(this), use_uniform_meshgen_fn_{true, true, true, true}, lb_flag_(true), - lb_automatic_(), lb_manual_(), - MeshGenerator_{nullptr, UniformMeshGenerator, UniformMeshGenerator, - UniformMeshGenerator}, + lb_automatic_(), lb_manual_(), MeshGenerator_{nullptr, UniformMeshGenerator, + UniformMeshGenerator, + UniformMeshGenerator}, MeshBndryFnctn{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr} { std::stringstream msg; RegionSize block_size; @@ -519,9 +519,9 @@ Mesh::Mesh(ParameterInput *pin, ApplicationInput *app_in, RestartReader &rr, // private members: num_mesh_threads_(pin->GetOrAddInteger("parthenon/mesh", "num_threads", 1)), tree(this), use_uniform_meshgen_fn_{true, true, true, true}, lb_flag_(true), - lb_automatic_(), lb_manual_(), - MeshGenerator_{nullptr, UniformMeshGenerator, UniformMeshGenerator, - UniformMeshGenerator}, + lb_automatic_(), lb_manual_(), MeshGenerator_{nullptr, UniformMeshGenerator, + UniformMeshGenerator, + UniformMeshGenerator}, MeshBndryFnctn{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr} { std::stringstream msg; RegionSize block_size; From 02912891cb00038c46d50f2b7bcd4a945da7b7a4 Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Tue, 5 Sep 2023 13:00:38 -0600 Subject: [PATCH 17/43] Use unordered_map for newly refined blocks, keep full list (all ranks) --- src/bvals/bvals.hpp | 10 ++++++---- src/bvals/bvals_base.cpp | 9 ++++++--- src/mesh/amr_loadbalance.cpp | 22 ++++++++++++++-------- src/mesh/logical_location.hpp | 35 +++++++++++++++++++++++------------ 4 files changed, 49 insertions(+), 27 deletions(-) diff --git a/src/bvals/bvals.hpp b/src/bvals/bvals.hpp index c36aebbb25cf..718499a9f804 100644 --- a/src/bvals/bvals.hpp +++ b/src/bvals/bvals.hpp @@ -20,8 +20,8 @@ // \brief defines BoundaryBase, BoundaryValues classes used for setting BCs on all data #include -#include #include +#include #include #include "basic_types.hpp" @@ -79,8 +79,9 @@ class BoundaryBase { static int BufferID(int dim, bool multilevel); static int FindBufferID(int ox1, int ox2, int ox3, int fi1, int fi2); - void SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist, int *nslist, - const std::set &newly_refined = {}); + void + SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist, int *nslist, + const std::unordered_set &newly_refined = {}); protected: // 1D refined or unrefined=2 @@ -92,7 +93,8 @@ class BoundaryBase { RegionSize block_size_; ParArrayND sarea_[2]; - void SetNeighborOwnership(const std::set &newly_refined = {}); + void + SetNeighborOwnership(const std::unordered_set &newly_refined = {}); private: // calculate 3x shared static data members when constructing only the 1st class instance diff --git a/src/bvals/bvals_base.cpp b/src/bvals/bvals_base.cpp index e92623935fb3..057493f186e8 100644 --- a/src/bvals/bvals_base.cpp +++ b/src/bvals/bvals_base.cpp @@ -29,6 +29,7 @@ #include // c_str() #include "globals.hpp" +#include "mesh/logical_location.hpp" #include "mesh/mesh.hpp" #include "utils/buffer_utils.hpp" #include "utils/error_checking.hpp" @@ -300,8 +301,9 @@ int BoundaryBase::CreateBvalsMPITag(int lid, int bufid) { // TODO(felker): break-up this long function -void BoundaryBase::SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist, int *nslist, - const std::set &newly_refined) { +void BoundaryBase::SearchAndSetNeighbors( + MeshBlockTree &tree, int *ranklist, int *nslist, + const std::unordered_set &newly_refined) { Kokkos::Profiling::pushRegion("SearchAndSetNeighbors"); MeshBlockTree *neibt; int myox1, myox2 = 0, myox3 = 0, myfx1, myfx2, myfx3; @@ -630,7 +632,8 @@ void BoundaryBase::SearchAndSetNeighbors(MeshBlockTree &tree, int *ranklist, int Kokkos::Profiling::popRegion(); // SearchAndSetNeighbors } -void BoundaryBase::SetNeighborOwnership(const std::set &newly_refined) { +void BoundaryBase::SetNeighborOwnership( + const std::unordered_set &newly_refined) { // Set neighbor block ownership std::set allowed_neighbors; allowed_neighbors.insert(loc); // Insert the location of this block diff --git a/src/mesh/amr_loadbalance.cpp b/src/mesh/amr_loadbalance.cpp index 0681931cfbee..1436d877d92a 100644 --- a/src/mesh/amr_loadbalance.cpp +++ b/src/mesh/amr_loadbalance.cpp @@ -698,6 +698,7 @@ void Mesh::RedistributeAndRefineMeshBlocks(ParameterInput *pin, ApplicationInput oldtonew[mb_idx] = ntot - 1; current_level = 0; + std::unordered_set newly_refined; for (int n = 0; n < ntot; n++) { // "on" = "old n" = "old gid" = "old global MeshBlock ID" int on = newtoold[n]; @@ -705,6 +706,10 @@ void Mesh::RedistributeAndRefineMeshBlocks(ParameterInput *pin, ApplicationInput current_level = newloc[n].level(); if (newloc[n].level() >= loclist[on].level()) { // same or refined newcost[n] = costlist[on]; + // Keep a list of all blocks refined for below + if (newloc[n].level() > loclist[on].level()) { + newly_refined.insert(newloc[n]); + } } else { double acost = 0.0; for (int l = 0; l < nleaf; l++) @@ -789,7 +794,6 @@ void Mesh::RedistributeAndRefineMeshBlocks(ParameterInput *pin, ApplicationInput RegionSize block_size = GetBlockSize(); BlockList_t new_block_list(nbe - nbs + 1); - std::set newly_refined; for (int n = nbs; n <= nbe; n++) { int on = newtoold[n]; if ((ranklist[on] == Globals::my_rank) && @@ -811,7 +815,6 @@ void Mesh::RedistributeAndRefineMeshBlocks(ParameterInput *pin, ApplicationInput new_block_list[n - nbs] = MeshBlock::Make(n, n - nbs, newloc[n], block_size, block_bcs, this, pin, app_in, packages, resolved_packages, gflag); - if (newloc[n].level() > loclist[on].level()) newly_refined.insert(newloc[n]); } } @@ -936,6 +939,14 @@ void Mesh::RedistributeAndRefineMeshBlocks(ParameterInput *pin, ApplicationInput pmb->pbval->SearchAndSetNeighbors(tree, ranklist.data(), nslist.data(), newly_refined); } + // Make sure all old sends/receives are done before we reconfigure the mesh +#ifdef MPI_PARALLEL + if (send_reqs.size() != 0) + PARTHENON_MPI_CHECK( + MPI_Waitall(send_reqs.size(), send_reqs.data(), MPI_STATUSES_IGNORE)); +#endif + // Re-initialize the mesh with our temporary ownership/neighbor configurations. + // No buffers are different when we switch to the final precedence order. Initialize(false, pin, app_in); // Internal refinement relies on the fine shared values, which are only consistent after @@ -943,17 +954,12 @@ void Mesh::RedistributeAndRefineMeshBlocks(ParameterInput *pin, ApplicationInput refinement::ProlongateInternal(resolved_packages.get(), prolongation_cache, block_list[0]->cellbounds, block_list[0]->c_cellbounds); - // Rebuild the ownership model, this time weighting the "new" fine blocks just like + // Rebuild just the ownership model, this time weighting the "new" fine blocks just like // any other blocks at their level. for (auto &pmb : block_list) { pmb->pbval->SearchAndSetNeighbors(tree, ranklist.data(), nslist.data()); } -#ifdef MPI_PARALLEL - if (send_reqs.size() != 0) - PARTHENON_MPI_CHECK( - MPI_Waitall(send_reqs.size(), send_reqs.data(), MPI_STATUSES_IGNORE)); -#endif Kokkos::Profiling::popRegion(); // AMR: Recv data and unpack ResetLoadBalanceVariables(); diff --git a/src/mesh/logical_location.hpp b/src/mesh/logical_location.hpp index 937608961213..33abdebb96d8 100644 --- a/src/mesh/logical_location.hpp +++ b/src/mesh/logical_location.hpp @@ -23,12 +23,25 @@ #include #include #include +#include #include #include +#include "logical_location.hpp" #include "utils/error_checking.hpp" #include "utils/morton_number.hpp" +namespace parthenon { +class LogicalLocation; +} + +// This must be declared before an unordered_set of LogicalLocation is used +// below, but must be *implemented* after the class definition +template <> +struct std::hash { + std::size_t operator()(const parthenon::LogicalLocation &key) const noexcept; +}; + namespace parthenon { struct RootGridInfo { @@ -252,15 +265,15 @@ inline block_ownership_t DetermineOwnership(const LogicalLocation &main_block, const std::set &allowed_neighbors, const RootGridInfo &rg_info = RootGridInfo(), - const std::set &newly_refined = {}) { + const std::unordered_set &newly_refined = {}) { block_ownership_t main_owns; auto ownership_level = [&](const LogicalLocation &a) { // Newly-refined blocks are treated as higher-level than blocks at their // parent level, but lower-level than previously-refined blocks at their // current level. - if (newly_refined.count(a)) return 2*a.level() - 1; - return 2*a.level(); + if (newly_refined.count(a)) return 2 * a.level() - 1; + return 2 * a.level(); }; auto ownership_less_than = [ownership_level](const LogicalLocation &a, @@ -356,14 +369,12 @@ inline auto GetIndexRangeMaskFromOwnership(TopologicalElement el, } // namespace parthenon -template <> -struct std::hash { - std::size_t operator()(const parthenon::LogicalLocation &key) const noexcept { - // TODO(LFR): Think more carefully about what the best choice for this key is, - // probably the least significant sizeof(size_t) * 8 bits of the morton number - // with 3 * (level - 21) trailing bits removed. - return key.morton().bits[0]; - } -}; +inline std::size_t std::hash::operator()( + const parthenon::LogicalLocation &key) const noexcept { + // TODO(LFR): Think more carefully about what the best choice for this key is, + // probably the least significant sizeof(size_t) * 8 bits of the morton number + // with 3 * (level - 21) trailing bits removed. + return key.morton().bits[0]; +} #endif // MESH_LOGICAL_LOCATION_HPP_ From a4e08833ae0facf4c00a5012ca5edc6ac75d402d Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Wed, 6 Sep 2023 09:03:53 -0600 Subject: [PATCH 18/43] Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index befb895a8a5a..90f89540140d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - [[PR 885]](https://github.com/parthenon-hpc-lab/parthenon/pull/885) Expose PackDescriptor and use uids in SparsePacks ### Fixed (not changing behavior/API/variables/...) +- [[PR 928]](https://github.com/parthenon-hpc-lab/parthenon/pull/928) Fix boundary comms during refinement next to refined blocks - [[PR 933]](https://github.com/parthenon-hpc-lab/parthenon/pull/933) Remove extraneous debug check - [[PR 917]](https://github.com/parthenon-hpc-lab/parthenon/pull/917) Update Iterative Tasking Infrastructure - [[PR 890]](https://github.com/parthenon-hpc-lab/parthenon/pull/890) Fix bugs in sparse communication and prolongation From ecad3b4a401c0c9723a8ee736efb6ca7505c8e36 Mon Sep 17 00:00:00 2001 From: Luke Roberts Date: Thu, 7 Sep 2023 15:25:35 -0600 Subject: [PATCH 19/43] Switch to three levels of parallelism --- src/bvals/comms/boundary_communication.cpp | 60 +++++++++++++++++----- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/src/bvals/comms/boundary_communication.cpp b/src/bvals/comms/boundary_communication.cpp index 2deabe4ef81c..bb25451cc520 100644 --- a/src/bvals/comms/boundary_communication.cpp +++ b/src/bvals/comms/boundary_communication.cpp @@ -82,6 +82,9 @@ TaskStatus SendBoundBufs(std::shared_ptr> &md) { PARTHENON_DEBUG_REQUIRE(bnd_info.size() == nbound, "Need same size for boundary info"); auto &sending_nonzero_flags = cache.sending_non_zero_flags; auto &sending_nonzero_flags_h = cache.sending_non_zero_flags_h; + for (int ibuf = 0; ibuf < cache.buf_vec.size(); ++ibuf) + sending_nonzero_flags_h(ibuf) = true; + Kokkos::parallel_for( "SendBoundBufs", Kokkos::TeamPolicy<>(parthenon::DevExecSpace(), nbound, Kokkos::AUTO), @@ -98,15 +101,27 @@ TaskStatus SendBoundBufs(std::shared_ptr> &md) { int idx_offset = 0; for (int iel = 0; iel < bnd_info(b).ntopological_elements; ++iel) { auto &idxer = bnd_info(b).idxer[iel]; + const int Ni = idxer.EndIdx<5>() - idxer.StartIdx<5>() + 1; Kokkos::parallel_reduce( - Kokkos::TeamThreadRange<>(team_member, idxer.size()), - [&](const int idx, bool &lnon_zero) { - const auto [t, u, v, k, j, i] = idxer(idx); - const Real &val = bnd_info(b).var(iel, t, u, v, k, j, i); - bnd_info(b).buf(idx + idx_offset) = val; - lnon_zero = lnon_zero || (std::abs(val) >= threshold); - }, - Kokkos::LOr(non_zero[iel])); + Kokkos::TeamThreadRange<>(team_member, idxer.size() / Ni), + [&](const int idx, bool &lnon_zero) { + const auto [t, u, v, k, j, i] = idxer(idx * Ni); + Real *var = &bnd_info(b).var(iel, t, u, v, k, j, i); + Real *buf = &bnd_info(b).buf(idx * Ni + idx_offset); + + Kokkos::parallel_for(Kokkos::ThreadVectorRange<>(team_member, Ni), + [&](int m) { + buf[m] = var[m]; + }); + + bool mnon_zero = false; + Kokkos::parallel_reduce(Kokkos::ThreadVectorRange<>(team_member, Ni), + [&](int m, bool &llnon_zero) { + llnon_zero = llnon_zero || (std::abs(buf[m]) >= threshold); + }, Kokkos::LOr(mnon_zero)); + + lnon_zero = lnon_zero || mnon_zero; + }, Kokkos::LOr(non_zero[iel])); idx_offset += idxer.size(); } Kokkos::single(Kokkos::PerTeam(team_member), [&]() { @@ -229,20 +244,37 @@ TaskStatus SetBounds(std::shared_ptr> &md) { int idx_offset = 0; for (int iel = 0; iel < bnd_info(b).ntopological_elements; ++iel) { auto &idxer = bnd_info(b).idxer[iel]; + const int Ni = idxer.EndIdx<5>() - idxer.StartIdx<5>() + 1; if (bnd_info(b).buf_allocated && bnd_info(b).allocated) { - Kokkos::parallel_for(Kokkos::TeamThreadRange<>(team_member, idxer.size()), + Kokkos::parallel_for(Kokkos::TeamThreadRange<>(team_member, idxer.size() / Ni), [&](const int idx) { const auto [t, u, v, k, j, i] = idxer(idx); - if (idxer.IsActive(k, j, i)) - bnd_info(b).var(iel, t, u, v, k, j, i) = - bnd_info(b).buf(idx + idx_offset); + Real *var = &bnd_info(b).var(iel, t, u, v, k, j, i); + Real *buf = &bnd_info(b).buf(idx * Ni + idx_offset); + // Have to do this because of some weird issue about structure bindings being captured + const int kk = k; + const int jj = j; + const int ii = i; + Kokkos::parallel_for(Kokkos::ThreadVectorRange<>(team_member, Ni), + [&](int m) { + if (idxer.IsActive(kk, jj, ii + m)) + var[m] = buf[m]; + }); }); } else if (bnd_info(b).allocated) { const Real default_val = bnd_info(b).var.sparse_default_val; - Kokkos::parallel_for(Kokkos::TeamThreadRange<>(team_member, idxer.size()), + Kokkos::parallel_for(Kokkos::TeamThreadRange<>(team_member, idxer.size() / Ni), [&](const int idx) { const auto [t, u, v, k, j, i] = idxer(idx); - bnd_info(b).var(iel, t, u, v, k, j, i) = default_val; + Real *var = &bnd_info(b).var(iel, t, u, v, k, j, i); + const int kk = k; + const int jj = j; + const int ii = i; + Kokkos::parallel_for(Kokkos::ThreadVectorRange<>(team_member, Ni), + [&](int m) { + if (idxer.IsActive(kk, jj, ii + m)) + var[m] = default_val; + }); }); } idx_offset += idxer.size(); From 6e7467e4abee43a2c5ff6d1a37eac22010b4ef7a Mon Sep 17 00:00:00 2001 From: Luke Roberts Date: Thu, 7 Sep 2023 15:26:32 -0600 Subject: [PATCH 20/43] Remove unecessary initialization of host nonzero flags --- src/bvals/comms/boundary_communication.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/bvals/comms/boundary_communication.cpp b/src/bvals/comms/boundary_communication.cpp index bb25451cc520..6108e1da3bbf 100644 --- a/src/bvals/comms/boundary_communication.cpp +++ b/src/bvals/comms/boundary_communication.cpp @@ -82,8 +82,6 @@ TaskStatus SendBoundBufs(std::shared_ptr> &md) { PARTHENON_DEBUG_REQUIRE(bnd_info.size() == nbound, "Need same size for boundary info"); auto &sending_nonzero_flags = cache.sending_non_zero_flags; auto &sending_nonzero_flags_h = cache.sending_non_zero_flags_h; - for (int ibuf = 0; ibuf < cache.buf_vec.size(); ++ibuf) - sending_nonzero_flags_h(ibuf) = true; Kokkos::parallel_for( "SendBoundBufs", From 3d410234a6974025fb156542f92f18b711b669bd Mon Sep 17 00:00:00 2001 From: Luke Roberts Date: Thu, 7 Sep 2023 15:40:06 -0600 Subject: [PATCH 21/43] Add template in a couple places, format, lint --- src/bvals/comms/boundary_communication.cpp | 92 +++++++++++----------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/src/bvals/comms/boundary_communication.cpp b/src/bvals/comms/boundary_communication.cpp index 6108e1da3bbf..54275ae40db7 100644 --- a/src/bvals/comms/boundary_communication.cpp +++ b/src/bvals/comms/boundary_communication.cpp @@ -82,7 +82,7 @@ TaskStatus SendBoundBufs(std::shared_ptr> &md) { PARTHENON_DEBUG_REQUIRE(bnd_info.size() == nbound, "Need same size for boundary info"); auto &sending_nonzero_flags = cache.sending_non_zero_flags; auto &sending_nonzero_flags_h = cache.sending_non_zero_flags_h; - + Kokkos::parallel_for( "SendBoundBufs", Kokkos::TeamPolicy<>(parthenon::DevExecSpace(), nbound, Kokkos::AUTO), @@ -99,27 +99,28 @@ TaskStatus SendBoundBufs(std::shared_ptr> &md) { int idx_offset = 0; for (int iel = 0; iel < bnd_info(b).ntopological_elements; ++iel) { auto &idxer = bnd_info(b).idxer[iel]; - const int Ni = idxer.EndIdx<5>() - idxer.StartIdx<5>() + 1; + const int Ni = idxer.template EndIdx<5>() - idxer.template StartIdx<5>() + 1; Kokkos::parallel_reduce( Kokkos::TeamThreadRange<>(team_member, idxer.size() / Ni), - [&](const int idx, bool &lnon_zero) { + [&](const int idx, bool &lnon_zero) { const auto [t, u, v, k, j, i] = idxer(idx * Ni); - Real *var = &bnd_info(b).var(iel, t, u, v, k, j, i); - Real *buf = &bnd_info(b).buf(idx * Ni + idx_offset); + Real *var = &bnd_info(b).var(iel, t, u, v, k, j, i); + Real *buf = &bnd_info(b).buf(idx * Ni + idx_offset); Kokkos::parallel_for(Kokkos::ThreadVectorRange<>(team_member, Ni), - [&](int m) { - buf[m] = var[m]; - }); - + [&](int m) { buf[m] = var[m]; }); + bool mnon_zero = false; - Kokkos::parallel_reduce(Kokkos::ThreadVectorRange<>(team_member, Ni), - [&](int m, bool &llnon_zero) { - llnon_zero = llnon_zero || (std::abs(buf[m]) >= threshold); - }, Kokkos::LOr(mnon_zero)); - + Kokkos::parallel_reduce( + Kokkos::ThreadVectorRange<>(team_member, Ni), + [&](int m, bool &llnon_zero) { + llnon_zero = llnon_zero || (std::abs(buf[m]) >= threshold); + }, + Kokkos::LOr(mnon_zero)); + lnon_zero = lnon_zero || mnon_zero; - }, Kokkos::LOr(non_zero[iel])); + }, + Kokkos::LOr(non_zero[iel])); idx_offset += idxer.size(); } Kokkos::single(Kokkos::PerTeam(team_member), [&]() { @@ -242,38 +243,41 @@ TaskStatus SetBounds(std::shared_ptr> &md) { int idx_offset = 0; for (int iel = 0; iel < bnd_info(b).ntopological_elements; ++iel) { auto &idxer = bnd_info(b).idxer[iel]; - const int Ni = idxer.EndIdx<5>() - idxer.StartIdx<5>() + 1; + const int Ni = idxer.template EndIdx<5>() - idxer.template StartIdx<5>() + 1; if (bnd_info(b).buf_allocated && bnd_info(b).allocated) { - Kokkos::parallel_for(Kokkos::TeamThreadRange<>(team_member, idxer.size() / Ni), - [&](const int idx) { - const auto [t, u, v, k, j, i] = idxer(idx); - Real *var = &bnd_info(b).var(iel, t, u, v, k, j, i); - Real *buf = &bnd_info(b).buf(idx * Ni + idx_offset); - // Have to do this because of some weird issue about structure bindings being captured - const int kk = k; - const int jj = j; - const int ii = i; - Kokkos::parallel_for(Kokkos::ThreadVectorRange<>(team_member, Ni), - [&](int m) { - if (idxer.IsActive(kk, jj, ii + m)) - var[m] = buf[m]; - }); - }); + Kokkos::parallel_for( + Kokkos::TeamThreadRange<>(team_member, idxer.size() / Ni), + [&](const int idx) { + const auto [t, u, v, k, j, i] = idxer(idx); + Real *var = &bnd_info(b).var(iel, t, u, v, k, j, i); + Real *buf = &bnd_info(b).buf(idx * Ni + idx_offset); + // Have to do this because of some weird issue about structure bindings + // being captured + const int kk = k; + const int jj = j; + const int ii = i; + Kokkos::parallel_for(Kokkos::ThreadVectorRange<>(team_member, Ni), + [&](int m) { + if (idxer.IsActive(kk, jj, ii + m)) + var[m] = buf[m]; + }); + }); } else if (bnd_info(b).allocated) { const Real default_val = bnd_info(b).var.sparse_default_val; - Kokkos::parallel_for(Kokkos::TeamThreadRange<>(team_member, idxer.size() / Ni), - [&](const int idx) { - const auto [t, u, v, k, j, i] = idxer(idx); - Real *var = &bnd_info(b).var(iel, t, u, v, k, j, i); - const int kk = k; - const int jj = j; - const int ii = i; - Kokkos::parallel_for(Kokkos::ThreadVectorRange<>(team_member, Ni), - [&](int m) { - if (idxer.IsActive(kk, jj, ii + m)) - var[m] = default_val; - }); - }); + Kokkos::parallel_for( + Kokkos::TeamThreadRange<>(team_member, idxer.size() / Ni), + [&](const int idx) { + const auto [t, u, v, k, j, i] = idxer(idx); + Real *var = &bnd_info(b).var(iel, t, u, v, k, j, i); + const int kk = k; + const int jj = j; + const int ii = i; + Kokkos::parallel_for(Kokkos::ThreadVectorRange<>(team_member, Ni), + [&](int m) { + if (idxer.IsActive(kk, jj, ii + m)) + var[m] = default_val; + }); + }); } idx_offset += idxer.size(); } From 82d60c822de6d453ddcfbd31dc4a21b235d5e994 Mon Sep 17 00:00:00 2001 From: Luke Roberts Date: Thu, 7 Sep 2023 16:53:43 -0600 Subject: [PATCH 22/43] Bug fix --- src/bvals/comms/boundary_communication.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bvals/comms/boundary_communication.cpp b/src/bvals/comms/boundary_communication.cpp index 54275ae40db7..54fd5945028e 100644 --- a/src/bvals/comms/boundary_communication.cpp +++ b/src/bvals/comms/boundary_communication.cpp @@ -248,7 +248,7 @@ TaskStatus SetBounds(std::shared_ptr> &md) { Kokkos::parallel_for( Kokkos::TeamThreadRange<>(team_member, idxer.size() / Ni), [&](const int idx) { - const auto [t, u, v, k, j, i] = idxer(idx); + const auto [t, u, v, k, j, i] = idxer(idx * Ni); Real *var = &bnd_info(b).var(iel, t, u, v, k, j, i); Real *buf = &bnd_info(b).buf(idx * Ni + idx_offset); // Have to do this because of some weird issue about structure bindings @@ -267,7 +267,7 @@ TaskStatus SetBounds(std::shared_ptr> &md) { Kokkos::parallel_for( Kokkos::TeamThreadRange<>(team_member, idxer.size() / Ni), [&](const int idx) { - const auto [t, u, v, k, j, i] = idxer(idx); + const auto [t, u, v, k, j, i] = idxer(idx * Ni); Real *var = &bnd_info(b).var(iel, t, u, v, k, j, i); const int kk = k; const int jj = j; From 7f1d629cf0762fa2c2e7e543083b4aa7028088fc Mon Sep 17 00:00:00 2001 From: Luke Roberts Date: Thu, 7 Sep 2023 17:20:01 -0600 Subject: [PATCH 23/43] Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index befb895a8a5a..d3405ddcb800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ - [[PR 890]](https://github.com/parthenon-hpc-lab/parthenon/pull/890) Fix bugs in sparse communication and prolongation ### Infrastructure (changes irrelevant to downstream codes) +- [[PR 938]](https://github.com/parthenon-hpc-lab/parthenon/pull/938) Restructure buffer packing/unpacking kernel hierarchical parallelism - [[PR 904]](https://github.com/parthenon-hpc-lab/parthenon/pull/904) Move to prolongation/restriction in one for AMR and communicate non-cell centered fields - [[PR 918]](https://github.com/parthenon-hpc-lab/parthenon/pull/918) Refactor RegionSize - [[PR 901]](https://github.com/parthenon-hpc-lab/parthenon/pull/901) Implement shared element ownership model From 9b452e5cd1ac8e557f2ff5f0af93df4e1fad94f3 Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Wed, 20 Sep 2023 09:56:04 -0600 Subject: [PATCH 24/43] Fix parsing files with multiple line continuations (#937) * Refresh some string buffers when written * Changelog * Fix continuations: add comment * Comments & naming to make parser clearer --------- Co-authored-by: Ben Prather --- CHANGELOG.md | 1 + src/parameter_input.cpp | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index befb895a8a5a..7f6a2358b53f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - [[PR 885]](https://github.com/parthenon-hpc-lab/parthenon/pull/885) Expose PackDescriptor and use uids in SparsePacks ### Fixed (not changing behavior/API/variables/...) +- [[PR 937]](https://github.com/parthenon-hpc-lab/parthenon/pull/937) Fix multiple line continuations - [[PR 933]](https://github.com/parthenon-hpc-lab/parthenon/pull/933) Remove extraneous debug check - [[PR 917]](https://github.com/parthenon-hpc-lab/parthenon/pull/917) Update Iterative Tasking Infrastructure - [[PR 890]](https://github.com/parthenon-hpc-lab/parthenon/pull/890) Fix bugs in sparse communication and prolongation diff --git a/src/parameter_input.cpp b/src/parameter_input.cpp index 464940eeba2c..b9fd9546f2b6 100644 --- a/src/parameter_input.cpp +++ b/src/parameter_input.cpp @@ -3,7 +3,7 @@ // Copyright(C) 2014 James M. Stone and other code contributors // Licensed under the 3-clause BSD License, see LICENSE file for details //======================================================================================== -// (C) (or copyright) 2020-2022. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -117,7 +117,9 @@ void ParameterInput::LoadFromStream(std::istream &is) { InputBlock *pib{}; int line_num{-1}, blocks_found{0}; + // Buffer multiple lines if a continuation character is present std::string multiline_name, multiline_value, multiline_comment; + // Status in/out of continuation bool continuing = false; while (is.good()) { @@ -175,19 +177,26 @@ void ParameterInput::LoadFromStream(std::istream &is) { PARTHENON_FAIL(msg); } // parse line and add name/value/comment strings (if found) to current block name - bool continuation = ParseLine(pib, line, param_name, param_value, param_comment); - if (continuing || continuation) { + bool has_cont_char = ParseLine(pib, line, param_name, param_value, param_comment); + if (continuing || has_cont_char) { + // Append line data multiline_name += param_name; multiline_value += param_value; multiline_comment += param_comment; + // Set new state continuing = true; } - if (continuing && !continuation) { - continuing = false; + if (continuing && !has_cont_char) { + // Flush line data param_name = multiline_name; param_value = multiline_value; param_comment = multiline_comment; + multiline_name = ""; + multiline_value = ""; + multiline_comment = ""; + // Set new state + continuing = false; } if (!continuing) { From 86f454daf45a0746a58967634a909efd55387dae Mon Sep 17 00:00:00 2001 From: Jonah Miller Date: Thu, 21 Sep 2023 11:51:47 -0600 Subject: [PATCH 25/43] remove ParthenonInit and add docs (#930) * remove ParthenonInit and add docs * CHANGELOG * copyright --------- Co-authored-by: Jonah Maxwell Miller --- CHANGELOG.md | 2 +- benchmarks/burgers/main.cpp | 5 ++- doc/sphinx/src/parthenon_manager.rst | 67 ++++++++++++++++++++++++++++ example/advection/main.cpp | 6 ++- example/calculate_pi/pi_driver.cpp | 5 ++- example/particle_leapfrog/main.cpp | 5 ++- example/particle_tracers/main.cpp | 5 ++- example/poisson/main.cpp | 5 ++- example/sparse_advection/main.cpp | 5 ++- example/stochastic_subgrid/main.cpp | 5 ++- src/parthenon_manager.cpp | 21 ++++----- src/parthenon_manager.hpp | 5 ++- 12 files changed, 107 insertions(+), 29 deletions(-) create mode 100644 doc/sphinx/src/parthenon_manager.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f6a2358b53f..7f996c16fb20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,7 @@ - [[PR 901]](https://github.com/parthenon-hpc-lab/parthenon/pull/901) Implement shared element ownership model ### Removed (removing behavior/API/varaibles/...) - +- [[PR 930](https://github.com/parthenon-hpc-lab/parthenon/pull/930) Remove ParthenonManager::ParthenonInit as it is error-prone and the split functions are the recommended usage. ## Release 0.8.0 Date: 2023-05-26 diff --git a/benchmarks/burgers/main.cpp b/benchmarks/burgers/main.cpp index 2ecc94490325..070a5c8bad8d 100644 --- a/benchmarks/burgers/main.cpp +++ b/benchmarks/burgers/main.cpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2020. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2022-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) { pman.app_input->ProblemGenerator = burgers_benchmark::ProblemGenerator; // call ParthenonInit to initialize MPI and Kokkos, parse the input deck, and set up - auto manager_status = pman.ParthenonInit(argc, argv); + auto manager_status = pman.ParthenonInitEnv(argc, argv); if (manager_status == ParthenonStatus::complete) { pman.ParthenonFinalize(); return 0; @@ -38,6 +38,7 @@ int main(int argc, char *argv[]) { // make use of MPI and Kokkos // This needs to be scoped so that the driver object is destructed before Finalize + pman.ParthenonInitPackagesAndMesh(); { // Initialize the driver burgers_benchmark::BurgersDriver driver(pman.pinput.get(), pman.app_input.get(), diff --git a/doc/sphinx/src/parthenon_manager.rst b/doc/sphinx/src/parthenon_manager.rst new file mode 100644 index 000000000000..15211e8bccdb --- /dev/null +++ b/doc/sphinx/src/parthenon_manager.rst @@ -0,0 +1,67 @@ +.. _parthenonmanager: + +Parthenon Manager +================= + +The ``ParthenonManager`` class helps set up a parthenon-based +application. An instance of ``ParthenonManager`` owns pointers a +number of sub-objects: + +* The ``ApplicationInput`` struct, which lets users set things like + the ``ProcessPackages`` and ``ProblemGenerator`` function pointers. +* The ``ParameterInput`` class, which populates input parameters from + the input file and command line +* The ``Mesh`` object + +The ``ParthenonManager`` has two important methods that usually must +be called in the ``main`` function of a parthenon-based app. The +function + +.. code:: cpp + + ParthenonStatus ParthenonManager::ParthenonInitEnv(int argc, char *argv); + +reads the input deck and populates the ``ParameterInput`` object +pointer ``pman.pin``, and sets up the ``MPI``, and ``Kokkos`` +runtimes. The function + +.. code:: cpp + + void ParthenonManager::ParthenonInitPackagesAndMesh(); + +Calls the ``Initialize(ParameterInput *pin)`` function of all packages +to be utilized and creates the grid hierarchy, including the ``Mesh`` +and ``MeshBlock`` objects, and calls the ``ProblemGenerator`` +initialization routines. + +The reason these functions are split out is to enable decisions to be +made by the application between reading the input deck and setting up +the grid. For example, a common use-case is: + +.. code:: cpp + + using parthenon::ParthenonManager; + using parthenon::ParthenonStatus; + ParthenonManager pman; + + // call ParthenonInit to initialize MPI and Kokkos, parse the input deck, and set up + auto manager_status = pman.ParthenonInitEnv(argc, argv); + if (manager_status == ParthenonStatus::complete) { + pman.ParthenonFinalize(); + return 0; + } + if (manager_status == ParthenonStatus::error) { + pman.ParthenonFinalize(); + return 1; + } + + // Redefine parthenon defaults + pman.app_input->ProcessPackages = MyProcessPackages; + std::string prob = pman.pin->GetString("app", "problem"); + if (prob == "problem1") { + pman.app_input->ProblemGenerator = Problem1Generator; + } else { + pman.app_input->ProblemGenerator = Problem2Generator; + } + + pman.ParthenonInitPackagesAndMesh(); diff --git a/example/advection/main.cpp b/example/advection/main.cpp index d7a823993341..a4c3cc6cf7e9 100644 --- a/example/advection/main.cpp +++ b/example/advection/main.cpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2020. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -26,7 +26,7 @@ int main(int argc, char *argv[]) { pman.app_input->UserWorkAfterLoop = advection_example::UserWorkAfterLoop; // call ParthenonInit to initialize MPI and Kokkos, parse the input deck, and set up - auto manager_status = pman.ParthenonInit(argc, argv); + auto manager_status = pman.ParthenonInitEnv(argc, argv); if (manager_status == ParthenonStatus::complete) { pman.ParthenonFinalize(); return 0; @@ -35,9 +35,11 @@ int main(int argc, char *argv[]) { pman.ParthenonFinalize(); return 1; } + // Now that ParthenonInit has been called and setup succeeded, the code can now // make use of MPI and Kokkos. // This needs to be scoped so that the driver object is destructed before Finalize + pman.ParthenonInitPackagesAndMesh(); { // Initialize the driver advection_example::AdvectionDriver driver(pman.pinput.get(), pman.app_input.get(), diff --git a/example/calculate_pi/pi_driver.cpp b/example/calculate_pi/pi_driver.cpp index 05017f6fc2e1..c322c17c0d3f 100644 --- a/example/calculate_pi/pi_driver.cpp +++ b/example/calculate_pi/pi_driver.cpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2020-2021. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) { // This is called on each mesh block whenever the mesh changes. pman.app_input->InitMeshBlockUserData = &calculate_pi::SetInOrOutBlock; - auto manager_status = pman.ParthenonInit(argc, argv); + auto manager_status = pman.ParthenonInitEnv(argc, argv); if (manager_status == ParthenonStatus::complete) { pman.ParthenonFinalize(); return 0; @@ -50,6 +50,7 @@ int main(int argc, char *argv[]) { } // This needs to be scoped so that the driver object is destructed before Finalize + pman.ParthenonInitPackagesAndMesh(); { PiDriver driver(pman.pinput.get(), pman.app_input.get(), pman.pmesh.get()); diff --git a/example/particle_leapfrog/main.cpp b/example/particle_leapfrog/main.cpp index 565fd857c166..450d2b1230fc 100644 --- a/example/particle_leapfrog/main.cpp +++ b/example/particle_leapfrog/main.cpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2020. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) { pman.app_input->ProblemGenerator = particles_leapfrog::ProblemGenerator; // call ParthenonInit to initialize MPI and Kokkos, parse the input deck, and set up - auto manager_status = pman.ParthenonInit(argc, argv); + auto manager_status = pman.ParthenonInitEnv(argc, argv); if (manager_status == ParthenonStatus::complete) { pman.ParthenonFinalize(); return 0; @@ -37,6 +37,7 @@ int main(int argc, char *argv[]) { // Now that ParthenonInit has been called and setup succeeded, the code can now // make use of MPI and Kokkos + pman.ParthenonInitPackagesAndMesh(); // This needs to be scoped so that the driver object is destructed before Finalize { // Initialize the driver diff --git a/example/particle_tracers/main.cpp b/example/particle_tracers/main.cpp index d95bf999e758..707a94e1bb40 100644 --- a/example/particle_tracers/main.cpp +++ b/example/particle_tracers/main.cpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2021. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2021-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) { pman.app_input->ProblemGenerator = tracers_example::ProblemGenerator; // call ParthenonInit to initialize MPI and Kokkos, parse the input deck, and set up - auto manager_status = pman.ParthenonInit(argc, argv); + auto manager_status = pman.ParthenonInitEnv(argc, argv); if (manager_status == ParthenonStatus::complete) { pman.ParthenonFinalize(); return 0; @@ -38,6 +38,7 @@ int main(int argc, char *argv[]) { // make use of MPI and Kokkos // This needs to be scoped so that the driver object is destructed before Finalize + pman.ParthenonInitPackagesAndMesh(); { // Initialize the driver tracers_example::ParticleDriver driver(pman.pinput.get(), pman.app_input.get(), diff --git a/example/poisson/main.cpp b/example/poisson/main.cpp index 066214ae6b1c..02e7888b73df 100644 --- a/example/poisson/main.cpp +++ b/example/poisson/main.cpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2021. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2021-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) { pman.app_input->MeshProblemGenerator = poisson_example::ProblemGenerator; // call ParthenonInit to initialize MPI and Kokkos, parse the input deck, and set up - auto manager_status = pman.ParthenonInit(argc, argv); + auto manager_status = pman.ParthenonInitEnv(argc, argv); if (manager_status == ParthenonStatus::complete) { pman.ParthenonFinalize(); return 0; @@ -38,6 +38,7 @@ int main(int argc, char *argv[]) { // make use of MPI and Kokkos // This needs to be scoped so that the driver object is destructed before Finalize + pman.ParthenonInitPackagesAndMesh(); { // Initialize the driver poisson_example::PoissonDriver driver(pman.pinput.get(), pman.app_input.get(), diff --git a/example/sparse_advection/main.cpp b/example/sparse_advection/main.cpp index e09954965072..3f513670596b 100644 --- a/example/sparse_advection/main.cpp +++ b/example/sparse_advection/main.cpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2021. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2021-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -29,7 +29,7 @@ int main(int argc, char *argv[]) { sparse_advection_example::PostStepDiagnosticsInLoop; // call ParthenonInit to initialize MPI and Kokkos, parse the input deck, and set up - auto manager_status = pman.ParthenonInit(argc, argv); + auto manager_status = pman.ParthenonInitEnv(argc, argv); if (manager_status == ParthenonStatus::complete) { pman.ParthenonFinalize(); return 0; @@ -43,6 +43,7 @@ int main(int argc, char *argv[]) { DriverStatus driver_status; // This needs to be scoped so that the driver object is destructed before Finalize + pman.ParthenonInitPackagesAndMesh(); { // Initialize the driver sparse_advection_example::SparseAdvectionDriver driver( diff --git a/example/stochastic_subgrid/main.cpp b/example/stochastic_subgrid/main.cpp index 613c7663a830..2ca46f086f93 100644 --- a/example/stochastic_subgrid/main.cpp +++ b/example/stochastic_subgrid/main.cpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2020-2021. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -26,7 +26,7 @@ int main(int argc, char *argv[]) { pman.app_input->UserWorkAfterLoop = stochastic_subgrid_example::UserWorkAfterLoop; // call ParthenonInit to initialize MPI and Kokkos, parse the input deck, and set up - auto manager_status = pman.ParthenonInit(argc, argv); + auto manager_status = pman.ParthenonInitEnv(argc, argv); if (manager_status == ParthenonStatus::complete) { pman.ParthenonFinalize(); return 0; @@ -39,6 +39,7 @@ int main(int argc, char *argv[]) { // make use of MPI and Kokkos // This needs to be scoped so that the driver object is destructed before Finalize + pman.ParthenonInitPackagesAndMesh(); { // Initialize the driver stochastic_subgrid_example::StochasticSubgridDriver driver( diff --git a/src/parthenon_manager.cpp b/src/parthenon_manager.cpp index 7bb08a587658..2329553bfe76 100644 --- a/src/parthenon_manager.cpp +++ b/src/parthenon_manager.cpp @@ -1,9 +1,9 @@ //======================================================================================== // Parthenon performance portable AMR framework -// Copyright(C) 2020-2022 The Parthenon collaboration +// Copyright(C) 2020-2023 The Parthenon collaboration // Licensed under the 3-clause BSD License, see LICENSE file for details //======================================================================================== -// (C) (or copyright) 2020-2022. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -40,16 +40,12 @@ namespace parthenon { -ParthenonStatus ParthenonManager::ParthenonInit(int argc, char *argv[]) { - auto manager_status = ParthenonInitEnv(argc, argv); - if (manager_status != ParthenonStatus::ok) { - return manager_status; +ParthenonStatus ParthenonManager::ParthenonInitEnv(int argc, char *argv[]) { + if (called_init_env_) { + PARTHENON_THROW("ParthenonInitEnv called twice!"); } - ParthenonInitPackagesAndMesh(); - return ParthenonStatus::ok; -} + called_init_env_ = true; -ParthenonStatus ParthenonManager::ParthenonInitEnv(int argc, char *argv[]) { // initialize MPI #ifdef MPI_PARALLEL if (MPI_SUCCESS != MPI_Init(&argc, &argv)) { @@ -146,6 +142,11 @@ ParthenonStatus ParthenonManager::ParthenonInitEnv(int argc, char *argv[]) { } void ParthenonManager::ParthenonInitPackagesAndMesh() { + if (called_init_packages_and_mesh_) { + PARTHENON_THROW("Called ParthenonInitPackagesAndMesh twice!"); + } + called_init_packages_and_mesh_ = true; + // Allow for user overrides to default Parthenon functions if (app_input->ProcessPackages != nullptr) { ProcessPackages = app_input->ProcessPackages; diff --git a/src/parthenon_manager.hpp b/src/parthenon_manager.hpp index 3ff5184e8f95..4dc31f169b1f 100644 --- a/src/parthenon_manager.hpp +++ b/src/parthenon_manager.hpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2020-2021. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -37,7 +37,6 @@ enum class ParthenonStatus { ok, complete, error }; class ParthenonManager { public: ParthenonManager() { app_input.reset(new ApplicationInput()); } - ParthenonStatus ParthenonInit(int argc, char *argv[]); ParthenonStatus ParthenonInitEnv(int argc, char *argv[]); void ParthenonInitPackagesAndMesh(); ParthenonStatus ParthenonFinalize(); @@ -57,6 +56,8 @@ class ParthenonManager { private: ArgParse arg; + bool called_init_env_ = false; + bool called_init_packages_and_mesh_ = false; template void ReadSwarmVars_(const SP_Swarm &pswarm, const BlockList_t &block_list, From ae478d2026b843ff623f27053a4954f8c2eb8492 Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Fri, 22 Sep 2023 07:31:52 -0600 Subject: [PATCH 26/43] Remove global non-optional print statements from Parthenon (#920) * Don't automatically print resolved packages state as this is user-accessible * Remove print statement from default driver PreExecute * format * Restore default prints in an overridable way --------- Co-authored-by: Ben Prather Co-authored-by: Jonah Miller Co-authored-by: Philipp Grete --- src/driver/driver.cpp | 4 +++- src/mesh/mesh.cpp | 10 ---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/driver/driver.cpp b/src/driver/driver.cpp index 60f6940f5cf4..84371eeaeb36 100644 --- a/src/driver/driver.cpp +++ b/src/driver/driver.cpp @@ -39,7 +39,9 @@ Kokkos::Timer Driver::timer_LBandAMR; void Driver::PreExecute() { if (Globals::my_rank == 0) { - std::cout << std::endl << "Setup complete, executing driver...\n" << std::endl; + std::cout << "# Variables in use:\n" << *(pmesh->resolved_packages) << std::endl; + std::cout << std::endl; + std::cout << "Setup complete, executing driver...\n" << std::endl; } timer_main.reset(); diff --git a/src/mesh/mesh.cpp b/src/mesh/mesh.cpp index bb5df2b95006..32f4d1b3245a 100644 --- a/src/mesh/mesh.cpp +++ b/src/mesh/mesh.cpp @@ -475,11 +475,6 @@ Mesh::Mesh(ParameterInput *pin, ApplicationInput *app_in, Packages_t &packages, } ResetLoadBalanceVariables(); - - // Output variables in use in this run - if (Globals::my_rank == 0) { - std::cout << "#Variables in use:\n" << *(resolved_packages) << std::endl; - } } //---------------------------------------------------------------------------------------- @@ -738,11 +733,6 @@ Mesh::Mesh(ParameterInput *pin, ApplicationInput *app_in, RestartReader &rr, } ResetLoadBalanceVariables(); - - // Output variables in use in this run - if (Globals::my_rank == 0) { - std::cout << "#Variables in use:\n" << *(resolved_packages) << std::endl; - } } //---------------------------------------------------------------------------------------- From 39ad758a2c94ac5552200809aa39076a11bb8810 Mon Sep 17 00:00:00 2001 From: Jonah Miller Date: Fri, 22 Sep 2023 09:36:15 -0600 Subject: [PATCH 27/43] add more detailed test of flat sparse pack (#935) * add more detailed test of flat sparse pack * Update test_sparse_pack.cpp Make linter happy --------- Co-authored-by: Jonah Maxwell Miller Co-authored-by: Philipp Grete --- tst/unit/test_sparse_pack.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tst/unit/test_sparse_pack.cpp b/tst/unit/test_sparse_pack.cpp index 2e9f656222b1..48172d5723f3 100644 --- a/tst/unit/test_sparse_pack.cpp +++ b/tst/unit/test_sparse_pack.cpp @@ -197,12 +197,28 @@ TEST_CASE("Test behavior of sparse packs", "[SparsePack]") { auto desc = parthenon::MakePackDescriptor( pkg.get(), {}, {PDOpt::WithFluxes, PDOpt::Flatten}); auto pack = desc.GetPack(&mesh_data); + int lo = pack.GetLowerBoundHost(2); int hi = pack.GetUpperBoundHost(2); REQUIRE(lo == 4 - 1 + 4 + 1); // lo = index in flat pack where block 2 starts. // v3 and v5 = 4 total var components REQUIRE(hi == lo); // hi = index in flat pack where block 2 ends. Only v3 // present, so only 1 var + AND_THEN("The flattened sparse pack can access vars correctly") { + const int nblocks_and_vars = pack.GetMaxNumberOfVars(); + int nwrong = 0; + par_reduce( + loop_pattern_mdrange_tag, "test flat", DevExecSpace(), 0, + nblocks_and_vars - 1, kb.s, kb.e, jb.s, jb.e, ib.s, ib.e, + KOKKOS_LAMBDA(int v, int k, int j, int i, int <ot) { + int n = i + 1e1 * j + 1e2 * k; + if (n != (static_cast(pack(v, k, j, i)) % 1000)) { + ltot += 1; + } + }, + nwrong); + REQUIRE(nwrong == 0); + } } } From 9b197e843d5ef12c0a37c3a30e65a17c0c33215c Mon Sep 17 00:00:00 2001 From: Philipp Grete Date: Mon, 25 Sep 2023 17:31:04 +0200 Subject: [PATCH 28/43] Fix typo --- src/bvals/comms/boundary_communication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bvals/comms/boundary_communication.cpp b/src/bvals/comms/boundary_communication.cpp index 2deabe4ef81c..bee917ac32b8 100644 --- a/src/bvals/comms/boundary_communication.cpp +++ b/src/bvals/comms/boundary_communication.cpp @@ -143,7 +143,7 @@ template TaskStatus StartReceiveBoundBufs(std::shared_ptr> &md) { Kokkos::Profiling::pushRegion("Task_StartReceiveBoundBufs"); Mesh *pmesh = md->GetMeshPointer(); - auto &cache = md->GetBvarsCache().GetSubCache(BoundaryType::flxcor_send, false); + auto &cache = md->GetBvarsCache().GetSubCache(bound_type, false); if (cache.buf_vec.size() == 0) InitializeBufferCache(md, &(pmesh->boundary_comm_map), &cache, ReceiveKey, false); From fb2790bf205670c9d9b78ccf2d97372306e94372 Mon Sep 17 00:00:00 2001 From: jdolence Date: Thu, 28 Sep 2023 11:23:35 -0600 Subject: [PATCH 29/43] move sparse pack identifier to descriptor --- src/interface/sparse_pack_base.cpp | 55 ++++++++++++------------------ src/interface/sparse_pack_base.hpp | 25 ++++++++++---- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/interface/sparse_pack_base.cpp b/src/interface/sparse_pack_base.cpp index 6ddc77194fba..06f910472741 100644 --- a/src/interface/sparse_pack_base.cpp +++ b/src/interface/sparse_pack_base.cpp @@ -276,21 +276,28 @@ template SparsePackBase SparsePackBase::Build>(MeshData *, template SparsePackBase &SparsePackCache::Get(T *pmd, const PackDescriptor &desc, const std::vector &include_block) { - std::string ident = GetIdentifier(desc, include_block); - if (pack_map.count(ident) > 0) { - auto &pack = pack_map[ident].first; + if (pack_map.count(desc.identifier) > 0) { + auto &cache_tuple = pack_map[desc.identifier]; + auto &pack = std::get<0>(cache_tuple); auto alloc_status_in = SparsePackBase::GetAllocStatus(pmd, desc, include_block); - auto &alloc_status = pack_map[ident].second; + auto &alloc_status = std::get<1>(cache_tuple); if (alloc_status.size() != alloc_status_in.size()) - return BuildAndAdd(pmd, desc, ident, include_block); + return BuildAndAdd(pmd, desc, include_block); for (int i = 0; i < alloc_status_in.size(); ++i) { if (alloc_status[i] != alloc_status_in[i]) - return BuildAndAdd(pmd, desc, ident, include_block); + return BuildAndAdd(pmd, desc, include_block); + } + auto &include_status = std::get<2>(cache_tuple); + if (include_status.size() != include_block.size()) + return BuildAndAdd(pmd, desc, include_block); + for (int i = 0; i < include_block.size(); ++i) { + if (include_status[i] != include_block[i]) + return BuildAndAdd(pmd, desc, include_block); } // Cached version is not stale, so just return a reference to it - return pack_map[ident].first; + return std::get<0>(cache_tuple); } - return BuildAndAdd(pmd, desc, ident, include_block); + return BuildAndAdd(pmd, desc, include_block); } template SparsePackBase &SparsePackCache::Get>(MeshData *, const PackDescriptor &, @@ -301,37 +308,17 @@ SparsePackCache::Get>(MeshBlockData *, const PackDescr template SparsePackBase &SparsePackCache::BuildAndAdd(T *pmd, const PackDescriptor &desc, - const std::string &ident, const std::vector &include_block) { - if (pack_map.count(ident) > 0) pack_map.erase(ident); - pack_map[ident] = {SparsePackBase::Build(pmd, desc, include_block), - SparsePackBase::GetAllocStatus(pmd, desc, include_block)}; - return pack_map[ident].first; + if (pack_map.count(desc.identifier) > 0) pack_map.erase(desc.identifier); + pack_map[desc.identifier] = {SparsePackBase::Build(pmd, desc, include_block), + SparsePackBase::GetAllocStatus(pmd, desc, include_block), + include_block}; + return std::get<0>(pack_map[desc.identifier]); } template SparsePackBase & SparsePackCache::BuildAndAdd>(MeshData *, const PackDescriptor &, - const std::string &, const std::vector &); template SparsePackBase &SparsePackCache::BuildAndAdd>( - MeshBlockData *, const PackDescriptor &, const std::string &, - const std::vector &); - -std::string SparsePackCache::GetIdentifier(const PackDescriptor &desc, - const std::vector &include_block) const { - std::string identifier(""); - for (const auto &vgroup : desc.var_groups) { - for (const auto &[vid, uid] : vgroup) { - identifier += std::to_string(uid) + "_"; - } - identifier += "|"; - } - identifier += std::to_string(desc.with_fluxes); - identifier += std::to_string(desc.coarse); - identifier += std::to_string(desc.flat); - for (const auto b : include_block) { - identifier += std::to_string(b); - } - return identifier; -} + MeshBlockData *, const PackDescriptor &, const std::vector &); } // namespace parthenon diff --git a/src/interface/sparse_pack_base.hpp b/src/interface/sparse_pack_base.hpp index 7970d86f330a..780825b87aed 100644 --- a/src/interface/sparse_pack_base.hpp +++ b/src/interface/sparse_pack_base.hpp @@ -54,6 +54,7 @@ class SparsePackBase { friend class SparsePackCache; using alloc_t = std::vector; + using include_t = std::vector; using pack_t = ParArray3D>; using bounds_t = ParArray3D; using bounds_h_t = typename ParArray3D::HostMirror; @@ -114,12 +115,9 @@ class SparsePackCache { template SparsePackBase &BuildAndAdd(T *pmd, const impl::PackDescriptor &desc, - const std::string &ident, const std::vector &include_block); - std::string GetIdentifier(const impl::PackDescriptor &desc, - const std::vector &include_block) const; - std::unordered_map> + std::unordered_map> pack_map; friend class SparsePackBase; @@ -136,7 +134,7 @@ struct PackDescriptor { // default constructor needed for certain use cases PackDescriptor() : nvar_groups(0), var_group_names({}), var_groups({}), with_fluxes(false), - coarse(false), flat(false) {} + coarse(false), flat(false), identifier("") {} template PackDescriptor(StateDescriptor *psd, const std::vector &var_groups_in, @@ -144,7 +142,8 @@ struct PackDescriptor { : nvar_groups(var_groups_in.size()), var_group_names(MakeGroupNames(var_groups_in)), var_groups(BuildUids(var_groups_in.size(), psd, selector)), with_fluxes(options.count(PDOpt::WithFluxes)), - coarse(options.count(PDOpt::Coarse)), flat(options.count(PDOpt::Flatten)) { + coarse(options.count(PDOpt::Coarse)), flat(options.count(PDOpt::Flatten)), + identifier(GetIdentifier()) { PARTHENON_REQUIRE(!(with_fluxes && coarse), "Probably shouldn't be making a coarse pack with fine fluxes."); } @@ -155,8 +154,22 @@ struct PackDescriptor { const bool with_fluxes; const bool coarse; const bool flat; + const std::string identifier; private: + std::string GetIdentifier() { + std::string ident(""); + for (const auto &vgroup : var_groups) { + for (const auto &[vid, uid] : vgroup) { + ident += std::to_string(uid) + "_"; + } + ident += "|"; + } + ident += std::to_string(with_fluxes); + ident += std::to_string(coarse); + ident += std::to_string(flat); + return ident; + } template std::vector BuildUids(int nvgs, const StateDescriptor *const psd, const FUNC_t &selector) { From 4f428d3bf294e922d9b89cc02ad67d4f185138c8 Mon Sep 17 00:00:00 2001 From: jdolence Date: Thu, 28 Sep 2023 11:51:40 -0600 Subject: [PATCH 30/43] formatting --- src/interface/sparse_pack_base.cpp | 4 ++-- src/interface/sparse_pack_base.hpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/interface/sparse_pack_base.cpp b/src/interface/sparse_pack_base.cpp index 06f910472741..d370c0f5f734 100644 --- a/src/interface/sparse_pack_base.cpp +++ b/src/interface/sparse_pack_base.cpp @@ -311,8 +311,8 @@ SparsePackBase &SparsePackCache::BuildAndAdd(T *pmd, const PackDescriptor &desc, const std::vector &include_block) { if (pack_map.count(desc.identifier) > 0) pack_map.erase(desc.identifier); pack_map[desc.identifier] = {SparsePackBase::Build(pmd, desc, include_block), - SparsePackBase::GetAllocStatus(pmd, desc, include_block), - include_block}; + SparsePackBase::GetAllocStatus(pmd, desc, include_block), + include_block}; return std::get<0>(pack_map[desc.identifier]); } template SparsePackBase & diff --git a/src/interface/sparse_pack_base.hpp b/src/interface/sparse_pack_base.hpp index 780825b87aed..26a5f3fd7b61 100644 --- a/src/interface/sparse_pack_base.hpp +++ b/src/interface/sparse_pack_base.hpp @@ -117,7 +117,8 @@ class SparsePackCache { SparsePackBase &BuildAndAdd(T *pmd, const impl::PackDescriptor &desc, const std::vector &include_block); - std::unordered_map> + std::unordered_map> pack_map; friend class SparsePackBase; From 06868acde5a57b6b14b5cd122bae924e48a3393c Mon Sep 17 00:00:00 2001 From: jdolence Date: Thu, 28 Sep 2023 11:58:28 -0600 Subject: [PATCH 31/43] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f996c16fb20..d9ebb4347039 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ - [[PR 890]](https://github.com/parthenon-hpc-lab/parthenon/pull/890) Fix bugs in sparse communication and prolongation ### Infrastructure (changes irrelevant to downstream codes) +- [[PR 944]](https://github.com/parthenon-hpc-lab/parthenon/pull/944) Move sparse pack identifier creation to descriptor - [[PR 904]](https://github.com/parthenon-hpc-lab/parthenon/pull/904) Move to prolongation/restriction in one for AMR and communicate non-cell centered fields - [[PR 918]](https://github.com/parthenon-hpc-lab/parthenon/pull/918) Refactor RegionSize - [[PR 901]](https://github.com/parthenon-hpc-lab/parthenon/pull/901) Implement shared element ownership model From 5b14ea4f24a49a5f727664be4d599e372b24d64e Mon Sep 17 00:00:00 2001 From: Ben Prather Date: Fri, 29 Sep 2023 09:07:09 -0600 Subject: [PATCH 32/43] PEP1: Make StateDescriptor members protected to allow subclasses access --- src/interface/state_descriptor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface/state_descriptor.hpp b/src/interface/state_descriptor.hpp index 06537a87d88a..5bb37ea83b60 100644 --- a/src/interface/state_descriptor.hpp +++ b/src/interface/state_descriptor.hpp @@ -432,7 +432,7 @@ class StateDescriptor { friend std::ostream &operator<<(std::ostream &os, const StateDescriptor &sd); - private: + protected: void InvertControllerMap(); Params params_; From cd8db2ef277a0ab02fa84f71f21d3b8aaa7a1fd9 Mon Sep 17 00:00:00 2001 From: Patrick Mullen Date: Tue, 3 Oct 2023 11:49:25 -0600 Subject: [PATCH 33/43] Add missing ForceRemeshComm dependencies --- src/interface/variable.cpp | 9 ++++++--- src/mesh/mesh.cpp | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/interface/variable.cpp b/src/interface/variable.cpp index fd8b534c95e5..03baf6ffb570 100644 --- a/src/interface/variable.cpp +++ b/src/interface/variable.cpp @@ -81,7 +81,8 @@ void Variable::CopyFluxesAndBdryVar(const Variable *src) { } } - if (IsSet(Metadata::FillGhost) || IsSet(Metadata::Independent)) { + if (IsSet(Metadata::FillGhost) || IsSet(Metadata::Independent) || + IsSet(Metadata::ForceRemeshComm)) { // no need to check mesh->multilevel, if false, we're just making a shallow copy of // an empty ParArrayND coarse_s = src->coarse_s; @@ -172,7 +173,8 @@ void Variable::AllocateFluxesAndCoarse(std::weak_ptr wpmb) { } // Create the boundary object - if (IsSet(Metadata::FillGhost) || IsSet(Metadata::Independent)) { + if (IsSet(Metadata::FillGhost) || IsSet(Metadata::Independent) || + IsSet(Metadata::ForceRemeshComm)) { if (wpmb.expired()) return; std::shared_ptr pmb = wpmb.lock(); @@ -205,7 +207,8 @@ std::int64_t Variable::Deallocate() { } } - if (IsSet(Metadata::FillGhost) || IsSet(Metadata::Independent)) { + if (IsSet(Metadata::FillGhost) || IsSet(Metadata::Independent) || + IsSet(Metadata::ForceRemeshComm)) { mem_size += coarse_s.size() * sizeof(T); coarse_s.Reset(); } diff --git a/src/mesh/mesh.cpp b/src/mesh/mesh.cpp index 32f4d1b3245a..4197c4158b2f 100644 --- a/src/mesh/mesh.cpp +++ b/src/mesh/mesh.cpp @@ -1272,7 +1272,8 @@ void Mesh::SetupMPIComms() { auto &metadata = pair.second; // Create both boundary and flux communicators for everything with either FillGhost // or WithFluxes just to be safe - if (metadata.IsSet(Metadata::FillGhost) || metadata.IsSet(Metadata::WithFluxes)) { + if (metadata.IsSet(Metadata::FillGhost) || metadata.IsSet(Metadata::WithFluxes) || + IsSet(Metadata::ForceRemeshComm)) { MPI_Comm mpi_comm; PARTHENON_MPI_CHECK(MPI_Comm_dup(MPI_COMM_WORLD, &mpi_comm)); const auto ret = mpi_comm_map_.insert({pair.first.label(), mpi_comm}); From 3fcf407ddc8a85c9610338be6331cd52d9677a47 Mon Sep 17 00:00:00 2001 From: Patrick Mullen Date: Tue, 3 Oct 2023 11:57:37 -0600 Subject: [PATCH 34/43] Update Changelog and copyrights --- CHANGELOG.md | 3 ++- src/interface/variable.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f74ad17ac4c..221df3353602 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - [[PR 885]](https://github.com/parthenon-hpc-lab/parthenon/pull/885) Expose PackDescriptor and use uids in SparsePacks ### Fixed (not changing behavior/API/variables/...) +- [[PR 946]](https://github.com/parthenon-hpc-lab/parthenon/pull/928) Add missing ForceRemeshComm dependencies - [[PR 928]](https://github.com/parthenon-hpc-lab/parthenon/pull/928) Fix boundary comms during refinement next to refined blocks - [[PR 937]](https://github.com/parthenon-hpc-lab/parthenon/pull/937) Fix multiple line continuations - [[PR 933]](https://github.com/parthenon-hpc-lab/parthenon/pull/933) Remove extraneous debug check @@ -34,7 +35,7 @@ ### Infrastructure (changes irrelevant to downstream codes) - [[PR 944]](https://github.com/parthenon-hpc-lab/parthenon/pull/944) Move sparse pack identifier creation to descriptor - [[PR 904]](https://github.com/parthenon-hpc-lab/parthenon/pull/904) Move to prolongation/restriction in one for AMR and communicate non-cell centered fields -- [[PR 918]](https://github.com/parthenon-hpc-lab/parthenon/pull/918) Refactor RegionSize +- [[PR 918]](https://github.com/parthenon-hpc-lab/parthenon/pull/918) Refactor RegionSize - [[PR 901]](https://github.com/parthenon-hpc-lab/parthenon/pull/901) Implement shared element ownership model ### Removed (removing behavior/API/varaibles/...) diff --git a/src/interface/variable.cpp b/src/interface/variable.cpp index 03baf6ffb570..ce62354f0631 100644 --- a/src/interface/variable.cpp +++ b/src/interface/variable.cpp @@ -1,5 +1,5 @@ //======================================================================================== -// (C) (or copyright) 2020-2022. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC From f86e01f05367bb95a851396481db1415c54acc1b Mon Sep 17 00:00:00 2001 From: Patrick Mullen Date: Tue, 3 Oct 2023 11:59:08 -0600 Subject: [PATCH 35/43] Fix changelog edits --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 221df3353602..1a1421f9e3cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ - [[PR 885]](https://github.com/parthenon-hpc-lab/parthenon/pull/885) Expose PackDescriptor and use uids in SparsePacks ### Fixed (not changing behavior/API/variables/...) -- [[PR 946]](https://github.com/parthenon-hpc-lab/parthenon/pull/928) Add missing ForceRemeshComm dependencies +- [[PR 947]](https://github.com/parthenon-hpc-lab/parthenon/pull/947) Add missing ForceRemeshComm dependencies - [[PR 928]](https://github.com/parthenon-hpc-lab/parthenon/pull/928) Fix boundary comms during refinement next to refined blocks - [[PR 937]](https://github.com/parthenon-hpc-lab/parthenon/pull/937) Fix multiple line continuations - [[PR 933]](https://github.com/parthenon-hpc-lab/parthenon/pull/933) Remove extraneous debug check From e031760308c132218fb0d41471a1ace50e051c6b Mon Sep 17 00:00:00 2001 From: Patrick Mullen Date: Tue, 3 Oct 2023 13:08:55 -0600 Subject: [PATCH 36/43] Attempt to fix failing CI pipelines --- src/mesh/mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/mesh.cpp b/src/mesh/mesh.cpp index 4197c4158b2f..ed81e3e4e219 100644 --- a/src/mesh/mesh.cpp +++ b/src/mesh/mesh.cpp @@ -1273,7 +1273,7 @@ void Mesh::SetupMPIComms() { // Create both boundary and flux communicators for everything with either FillGhost // or WithFluxes just to be safe if (metadata.IsSet(Metadata::FillGhost) || metadata.IsSet(Metadata::WithFluxes) || - IsSet(Metadata::ForceRemeshComm)) { + metadata.IsSet(Metadata::ForceRemeshComm)) { MPI_Comm mpi_comm; PARTHENON_MPI_CHECK(MPI_Comm_dup(MPI_COMM_WORLD, &mpi_comm)); const auto ret = mpi_comm_map_.insert({pair.first.label(), mpi_comm}); From afd6c03c819017dc92e366c56d97e59ce5c23fc5 Mon Sep 17 00:00:00 2001 From: Jonah Maxwell Miller Date: Mon, 9 Oct 2023 17:25:08 -0600 Subject: [PATCH 37/43] fix warning --- example/sparse_advection/parthenon_app_inputs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/sparse_advection/parthenon_app_inputs.cpp b/example/sparse_advection/parthenon_app_inputs.cpp index 8203ade9b532..6da77c93ed6b 100644 --- a/example/sparse_advection/parthenon_app_inputs.cpp +++ b/example/sparse_advection/parthenon_app_inputs.cpp @@ -176,7 +176,7 @@ void PostStepDiagnosticsInLoop(Mesh *mesh, ParameterInput *pin, const SimTime &t } std::printf("\n"); Real mem_avg = static_cast(mem_tot) / static_cast(blocks_tot); - std::printf("\tMem used/block in bytes [min, max, avg] = [%ld, %ld, %.14e]\n", + std::printf("\tMem used/block in bytes [min, max, avg] = [%lu, %lu, %.14e]\n", mem_min, mem_max, mem_avg); } } From 7397fed75b0b8d779550c8763179c4315cc174b2 Mon Sep 17 00:00:00 2001 From: Jonah Maxwell Miller Date: Mon, 9 Oct 2023 17:27:40 -0600 Subject: [PATCH 38/43] Changelog and copyright --- CHANGELOG.md | 1 + example/sparse_advection/parthenon_app_inputs.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4427452edd2..c100cf8f9df4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - [[PR 885]](https://github.com/parthenon-hpc-lab/parthenon/pull/885) Expose PackDescriptor and use uids in SparsePacks ### Fixed (not changing behavior/API/variables/...) +- [[PR 952]](https://github.com/parthenon-hpc-lab/parthenon/pull/954) Fix format string in sparse advection example - [[PR 947]](https://github.com/parthenon-hpc-lab/parthenon/pull/947) Add missing ForceRemeshComm dependencies - [[PR 928]](https://github.com/parthenon-hpc-lab/parthenon/pull/928) Fix boundary comms during refinement next to refined blocks - [[PR 937]](https://github.com/parthenon-hpc-lab/parthenon/pull/937) Fix multiple line continuations diff --git a/example/sparse_advection/parthenon_app_inputs.cpp b/example/sparse_advection/parthenon_app_inputs.cpp index 6da77c93ed6b..1cd806accad6 100644 --- a/example/sparse_advection/parthenon_app_inputs.cpp +++ b/example/sparse_advection/parthenon_app_inputs.cpp @@ -1,4 +1,4 @@ -// (C) (or copyright) 2021. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC From 635fe2a2b191332f45ff43de5fef1a91fe9b82ad Mon Sep 17 00:00:00 2001 From: Patrick Mullen Date: Wed, 11 Oct 2023 16:34:19 -0600 Subject: [PATCH 39/43] Only permit rank0 to mkdir when -d flag specified --- src/utils/change_rundir.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/utils/change_rundir.cpp b/src/utils/change_rundir.cpp index 761873d058c6..4c616d61f68c 100644 --- a/src/utils/change_rundir.cpp +++ b/src/utils/change_rundir.cpp @@ -3,7 +3,7 @@ // Copyright(C) 2014 James M. Stone and other code contributors // Licensed under the 3-clause BSD License, see LICENSE file for details //======================================================================================== -// (C) (or copyright) 2020. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 for Los // Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC @@ -27,6 +27,8 @@ #include #include "defs.hpp" +#include "globals.hpp" +#include "parthenon_mpi.hpp" #include "utils/error_checking.hpp" namespace fs = FS_NAMESPACE; @@ -42,19 +44,25 @@ void ChangeRunDir(const char *pdir) { if (pdir == nullptr || *pdir == '\0') return; - if (!fs::exists(pdir)) { - if (!fs::create_directories(pdir)) { - msg << "### FATAL ERROR in function [ChangeToRunDir]" << std::endl - << "Cannot create directory '" << pdir << "'"; - PARTHENON_THROW(msg); - } + if (parthenon::Globals::my_rank == 0) { + if (!fs::exists(pdir)) { + if (!fs::create_directories(pdir)) { + msg << "### FATAL ERROR in function [ChangeToRunDir]" << std::endl + << "Cannot create directory '" << pdir << "'"; + PARTHENON_THROW(msg); + } - // in POSIX, this is 0755 permission, rwxr-xr-x - auto perms = fs::perms::owner_all | fs::perms::group_read | fs::perms::group_exec | - fs::perms::others_read | fs::perms::others_exec; - fs::permissions(pdir, perms); + // in POSIX, this is 0755 permission, rwxr-xr-x + auto perms = fs::perms::owner_all | fs::perms::group_read | fs::perms::group_exec | + fs::perms::others_read | fs::perms::others_exec; + fs::permissions(pdir, perms); + } } +#ifdef MPI_PARALLEL + MPI_Barrier(MPI_COMM_WORLD); +#endif + if (chdir(pdir)) { msg << "### FATAL ERROR in function [ChangeToRunDir]" << std::endl << "Cannot cd to directory '" << pdir << "'"; From 62c634623e0b56b83d1fd261e83d80b7b6a9a0e0 Mon Sep 17 00:00:00 2001 From: Patrick Mullen Date: Wed, 11 Oct 2023 16:41:49 -0600 Subject: [PATCH 40/43] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c100cf8f9df4..d55ce40ac5b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - [[PR 885]](https://github.com/parthenon-hpc-lab/parthenon/pull/885) Expose PackDescriptor and use uids in SparsePacks ### Fixed (not changing behavior/API/variables/...) +- [[PR 955]](https://github.com/parthenon-hpc-lab/parthenon/pull/955) Only permit rank0 to mkdir when -d flag specified - [[PR 952]](https://github.com/parthenon-hpc-lab/parthenon/pull/954) Fix format string in sparse advection example - [[PR 947]](https://github.com/parthenon-hpc-lab/parthenon/pull/947) Add missing ForceRemeshComm dependencies - [[PR 928]](https://github.com/parthenon-hpc-lab/parthenon/pull/928) Fix boundary comms during refinement next to refined blocks From 081b14c6379a4adbb7beacae0cd549f78f36681b Mon Sep 17 00:00:00 2001 From: jdolence Date: Tue, 24 Oct 2023 12:10:21 -0600 Subject: [PATCH 41/43] INLINE to FORCEINLINE on all par_for_inner functions --- src/kokkos_abstraction.hpp | 54 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/kokkos_abstraction.hpp b/src/kokkos_abstraction.hpp index cabae1273b6f..f265fd22cc32 100644 --- a/src/kokkos_abstraction.hpp +++ b/src/kokkos_abstraction.hpp @@ -707,7 +707,7 @@ inline void par_for_outer(OuterLoopPatternTeams, const std::string &name, // Inner parallel loop using TeamThreadRange template -KOKKOS_INLINE_FUNCTION void +KOKKOS_FORCEINLINE_FUNCTION void par_for_inner(InnerLoopPatternTTR, team_mbr_t team_member, const int ll, const int lu, const int ml, const int mu, const int nl, const int nu, const int kl, const int ku, const int jl, const int ju, const int il, const int iu, @@ -741,7 +741,7 @@ par_for_inner(InnerLoopPatternTTR, team_mbr_t team_member, const int ll, const i }); } template -KOKKOS_INLINE_FUNCTION void +KOKKOS_FORCEINLINE_FUNCTION void par_for_inner(InnerLoopPatternTTR, team_mbr_t team_member, const int ml, const int mu, const int nl, const int nu, const int kl, const int ku, const int jl, const int ju, const int il, const int iu, const Function &function) { @@ -770,7 +770,7 @@ par_for_inner(InnerLoopPatternTTR, team_mbr_t team_member, const int ml, const i }); } template -KOKKOS_INLINE_FUNCTION void +KOKKOS_FORCEINLINE_FUNCTION void par_for_inner(InnerLoopPatternTTR, team_mbr_t team_member, const int nl, const int nu, const int kl, const int ku, const int jl, const int ju, const int il, const int iu, const Function &function) { @@ -795,10 +795,10 @@ par_for_inner(InnerLoopPatternTTR, team_mbr_t team_member, const int nl, const i }); } template -KOKKOS_INLINE_FUNCTION void par_for_inner(InnerLoopPatternTTR, team_mbr_t team_member, - const int kl, const int ku, const int jl, - const int ju, const int il, const int iu, - const Function &function) { +KOKKOS_FORCEINLINE_FUNCTION void +par_for_inner(InnerLoopPatternTTR, team_mbr_t team_member, const int kl, const int ku, + const int jl, const int ju, const int il, const int iu, + const Function &function) { const int Nk = ku - kl + 1; const int Nj = ju - jl + 1; const int Ni = iu - il + 1; @@ -815,9 +815,9 @@ KOKKOS_INLINE_FUNCTION void par_for_inner(InnerLoopPatternTTR, team_mbr_t team_m }); } template -KOKKOS_INLINE_FUNCTION void par_for_inner(InnerLoopPatternTTR, team_mbr_t team_member, - const int jl, const int ju, const int il, - const int iu, const Function &function) { +KOKKOS_FORCEINLINE_FUNCTION void +par_for_inner(InnerLoopPatternTTR, team_mbr_t team_member, const int jl, const int ju, + const int il, const int iu, const Function &function) { const int Nj = ju - jl + 1; const int Ni = iu - il + 1; const int NjNi = Nj * Ni; @@ -828,22 +828,22 @@ KOKKOS_INLINE_FUNCTION void par_for_inner(InnerLoopPatternTTR, team_mbr_t team_m }); } template -KOKKOS_INLINE_FUNCTION void par_for_inner(InnerLoopPatternTTR, team_mbr_t team_member, - const int il, const int iu, - const Function &function) { +KOKKOS_FORCEINLINE_FUNCTION void par_for_inner(InnerLoopPatternTTR, + team_mbr_t team_member, const int il, + const int iu, const Function &function) { Kokkos::parallel_for(Kokkos::TeamThreadRange(team_member, il, iu + 1), function); } // Inner parallel loop using TeamVectorRange template -KOKKOS_INLINE_FUNCTION void par_for_inner(InnerLoopPatternTVR, team_mbr_t team_member, - const int il, const int iu, - const Function &function) { +KOKKOS_FORCEINLINE_FUNCTION void par_for_inner(InnerLoopPatternTVR, + team_mbr_t team_member, const int il, + const int iu, const Function &function) { Kokkos::parallel_for(Kokkos::TeamVectorRange(team_member, il, iu + 1), function); } // Inner parallel loop using FOR SIMD template -KOKKOS_INLINE_FUNCTION void +KOKKOS_FORCEINLINE_FUNCTION void par_for_inner(InnerLoopPatternSimdFor, team_mbr_t team_member, const int nl, const int nu, const int kl, const int ku, const int jl, const int ju, const int il, const int iu, const Function &function) { @@ -859,10 +859,10 @@ par_for_inner(InnerLoopPatternSimdFor, team_mbr_t team_member, const int nl, con } } template -KOKKOS_INLINE_FUNCTION void par_for_inner(InnerLoopPatternSimdFor, team_mbr_t team_member, - const int kl, const int ku, const int jl, - const int ju, const int il, const int iu, - const Function &function) { +KOKKOS_FORCEINLINE_FUNCTION void +par_for_inner(InnerLoopPatternSimdFor, team_mbr_t team_member, const int kl, const int ku, + const int jl, const int ju, const int il, const int iu, + const Function &function) { for (int k = kl; k <= ku; ++k) { for (int j = jl; j <= ju; ++j) { #pragma omp simd @@ -873,9 +873,9 @@ KOKKOS_INLINE_FUNCTION void par_for_inner(InnerLoopPatternSimdFor, team_mbr_t te } } template -KOKKOS_INLINE_FUNCTION void par_for_inner(InnerLoopPatternSimdFor, team_mbr_t team_member, - const int jl, const int ju, const int il, - const int iu, const Function &function) { +KOKKOS_FORCEINLINE_FUNCTION void +par_for_inner(InnerLoopPatternSimdFor, team_mbr_t team_member, const int jl, const int ju, + const int il, const int iu, const Function &function) { for (int j = jl; j <= ju; ++j) { #pragma omp simd for (int i = il; i <= iu; i++) { @@ -884,9 +884,9 @@ KOKKOS_INLINE_FUNCTION void par_for_inner(InnerLoopPatternSimdFor, team_mbr_t te } } template -KOKKOS_INLINE_FUNCTION void par_for_inner(InnerLoopPatternSimdFor, team_mbr_t team_member, - const int il, const int iu, - const Function &function) { +KOKKOS_FORCEINLINE_FUNCTION void par_for_inner(InnerLoopPatternSimdFor, + team_mbr_t team_member, const int il, + const int iu, const Function &function) { #pragma omp simd for (int i = il; i <= iu; i++) { function(i); From 5145bd8887fc01f9d49562a24e2fe14d5e08d847 Mon Sep 17 00:00:00 2001 From: jdolence Date: Tue, 24 Oct 2023 12:19:41 -0600 Subject: [PATCH 42/43] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49d929c46ab5..978bccbf19c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ - [[PR 890]](https://github.com/parthenon-hpc-lab/parthenon/pull/890) Fix bugs in sparse communication and prolongation ### Infrastructure (changes irrelevant to downstream codes) +- [[PR 967]](https://github.com/parthenon-hpc-lab/parthenon/pull/967) Change INLINE to FORCEINLINE on par_for_inner overloads - [[PR 938]](https://github.com/parthenon-hpc-lab/parthenon/pull/938) Restructure buffer packing/unpacking kernel hierarchical parallelism - [[PR 944]](https://github.com/parthenon-hpc-lab/parthenon/pull/944) Move sparse pack identifier creation to descriptor - [[PR 904]](https://github.com/parthenon-hpc-lab/parthenon/pull/904) Move to prolongation/restriction in one for AMR and communicate non-cell centered fields From 790cebb6488d4fe7b24bef31c7a4de4bbb1a5a3e Mon Sep 17 00:00:00 2001 From: jdolence Date: Tue, 24 Oct 2023 12:43:20 -0600 Subject: [PATCH 43/43] update copyright --- src/kokkos_abstraction.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kokkos_abstraction.hpp b/src/kokkos_abstraction.hpp index f265fd22cc32..bfaf6a247a66 100644 --- a/src/kokkos_abstraction.hpp +++ b/src/kokkos_abstraction.hpp @@ -1,9 +1,9 @@ //======================================================================================== // Parthenon performance portable AMR framework -// Copyright(C) 2020-2022 The Parthenon collaboration +// Copyright(C) 2020-2023 The Parthenon collaboration // Licensed under the 3-clause BSD License, see LICENSE file for details //======================================================================================== -// (C) (or copyright) 2020-2022. Triad National Security, LLC. All rights reserved. +// (C) (or copyright) 2020-2023. Triad National Security, LLC. All rights reserved. // // This program was produced under U.S. Government contract 89233218CNA000001 // for Los Alamos National Laboratory (LANL), which is operated by Triad