From 193c6a9d7cd305b614aef9bd319193ccf717ecc3 Mon Sep 17 00:00:00 2001 From: Sterling Harper Date: Sat, 29 Feb 2020 19:17:20 -0500 Subject: [PATCH] Speed up distribcell initialization --- include/openmc/geometry_aux.h | 6 +++++- include/openmc/lattice.h | 3 ++- src/geometry_aux.cpp | 29 ++++++++++++++++++++++------- src/lattice.cpp | 5 +++-- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/include/openmc/geometry_aux.h b/include/openmc/geometry_aux.h index 800baef265..5ff05e7a7d 100644 --- a/include/openmc/geometry_aux.h +++ b/include/openmc/geometry_aux.h @@ -86,11 +86,15 @@ void count_cell_instances(int32_t univ_indx); //! Recursively search through universes and count universe instances. //! \param search_univ The index of the universe to begin searching from. //! \param target_univ_id The ID of the universe to be counted. +//! \param univ_count_memo Memoized counts that make this function faster for +//! large systems. The first call to this function for each target_univ_id +//! should start with an empty memo. //! \return The number of instances of target_univ_id in the geometry tree under //! search_univ. //============================================================================== -int count_universe_instances(int32_t search_univ, int32_t target_univ_id); +int count_universe_instances(int32_t search_univ, int32_t target_univ_id, + std::unordered_map& univ_count_memo); //============================================================================== //! Build a character array representing the path to a distribcell instance. diff --git a/include/openmc/lattice.h b/include/openmc/lattice.h index cd73b96408..95d30aed5a 100644 --- a/include/openmc/lattice.h +++ b/include/openmc/lattice.h @@ -77,7 +77,8 @@ public: {offsets_.resize(n_maps * universes_.size(), C_NONE);} //! Populate the distribcell offset tables. - int32_t fill_offset_table(int32_t offset, int32_t target_univ_id, int map); + int32_t fill_offset_table(int32_t offset, int32_t target_univ_id, int map, + std::unordered_map& univ_count_memo); //! \brief Check lattice indices. //! \param i_xyz[3] The indices for a lattice tile. diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index ae6d894aa8..c58af934b4 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -385,8 +385,10 @@ prepare_distribcell() } // Fill the cell and lattice offset tables. + #pragma omp parallel for for (int map = 0; map < target_univ_ids.size(); map++) { auto target_univ_id = target_univ_ids[map]; + std::unordered_map univ_count_memo; for (const auto& univ : model::universes) { int32_t offset = 0; for (int32_t cell_indx : univ->cells_) { @@ -395,11 +397,13 @@ prepare_distribcell() if (c.type_ == Fill::UNIVERSE) { c.offset_[map] = offset; int32_t search_univ = c.fill_; - offset += count_universe_instances(search_univ, target_univ_id); + offset += count_universe_instances(search_univ, target_univ_id, + univ_count_memo); } else if (c.type_ == Fill::LATTICE) { Lattice& lat = *model::lattices[c.fill_]; - offset = lat.fill_offset_table(offset, target_univ_id, map); + offset = lat.fill_offset_table(offset, target_univ_id, map, + univ_count_memo); } } } @@ -411,7 +415,6 @@ prepare_distribcell() void count_cell_instances(int32_t univ_indx) { - const auto univ_counts = model::universe_cell_counts.find(univ_indx); if (univ_counts != model::universe_cell_counts.end()) { for (const auto& it : univ_counts->second) { @@ -442,30 +445,42 @@ count_cell_instances(int32_t univ_indx) //============================================================================== int -count_universe_instances(int32_t search_univ, int32_t target_univ_id) +count_universe_instances(int32_t search_univ, int32_t target_univ_id, + std::unordered_map& univ_count_memo) { - // If this is the target, it can't contain itself. + // If this is the target, it can't contain itself. if (model::universes[search_univ]->id_ == target_univ_id) { return 1; } + // If we have already counted the number of instances, reuse that value. + auto search = univ_count_memo.find(search_univ); + if (search != univ_count_memo.end()) { + return search->second; + } + int count {0}; for (int32_t cell_indx : model::universes[search_univ]->cells_) { Cell& c = *model::cells[cell_indx]; if (c.type_ == Fill::UNIVERSE) { int32_t next_univ = c.fill_; - count += count_universe_instances(next_univ, target_univ_id); + count += count_universe_instances(next_univ, target_univ_id, + univ_count_memo); } else if (c.type_ == Fill::LATTICE) { Lattice& lat = *model::lattices[c.fill_]; for (auto it = lat.begin(); it != lat.end(); ++it) { int32_t next_univ = *it; - count += count_universe_instances(next_univ, target_univ_id); + count += count_universe_instances(next_univ, target_univ_id, + univ_count_memo); } } } + // Remember the number of instances in this universe. + univ_count_memo[search_univ] = count; + return count; } diff --git a/src/lattice.cpp b/src/lattice.cpp index 8f88d8c591..eba8807c1e 100644 --- a/src/lattice.cpp +++ b/src/lattice.cpp @@ -93,11 +93,12 @@ Lattice::adjust_indices() //============================================================================== int32_t -Lattice::fill_offset_table(int32_t offset, int32_t target_univ_id, int map) +Lattice::fill_offset_table(int32_t offset, int32_t target_univ_id, int map, + std::unordered_map& univ_count_memo) { for (LatticeIter it = begin(); it != end(); ++it) { offsets_[map * universes_.size() + it.indx_] = offset; - offset += count_universe_instances(*it, target_univ_id); + offset += count_universe_instances(*it, target_univ_id, univ_count_memo); } return offset; }