From 82bbf7141352cac21295bac96d6e691692a170de Mon Sep 17 00:00:00 2001 From: myerspat Date: Mon, 15 Aug 2022 15:04:03 -0400 Subject: [PATCH] Reduced contains_complex to one while loop --- include/openmc/cell.h | 4 +- src/cell.cpp | 125 ++++++++++++++++++++++-------------------- src/geometry_aux.cpp | 2 +- src/universe.cpp | 4 +- 4 files changed, 72 insertions(+), 63 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 0004a86c6f..23cd0130a8 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -199,7 +199,9 @@ public: vector sqrtkT_; //! Definition of spatial region as Boolean expression of half-spaces - vector region_; + vector region_; + //! Region in infix that may be modified depending on simplicity + vector region_infix_; bool simple_; //!< Does the region contain only intersections? //! \brief Neighboring cells in the same universe. diff --git a/src/cell.cpp b/src/cell.cpp index 8224ba2665..a663d1144f 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -115,46 +115,62 @@ vector tokenize(const std::string region_spec) std::vector::iterator add_parenthesis( std::vector::iterator start, std::vector& infix) { + int32_t start_token = *start; // Add left parenthesis - start = infix.insert(start, OP_LEFT_PAREN); - start = start + 2; + if (start_token == OP_INTERSECTION) { + start = infix.insert(start - 1, OP_LEFT_PAREN); + } else { + start = infix.insert(start + 1, OP_LEFT_PAREN); + } + start++; // Initialize return iterator - std::vector::iterator return_iterator = infix.end() - 1; + std::vector::iterator return_iterator = infix.begin(); // Add right parenthesis // While the start iterator is within the bounds of infix while (start < infix.end()) { start++; - // If we find a union or right parenthesis not wrapped by - // left and right parenthesis then place a right parenthesis, - // If we find a wrapped region return an iterator pointing to - // that wrapped region and continue looking to place a - // right parenthesis - if (*start == OP_UNION || *start == OP_RIGHT_PAREN) { - start = infix.insert(start, OP_RIGHT_PAREN); - return start - 1; - - } else if (*start == OP_LEFT_PAREN) { - return_iterator = start; - int depth = 1; - do { - start++; - if (*start > OP_COMPLEMENT) { - if (*start == OP_RIGHT_PAREN) { - depth--; - } else { - depth++; + // If the current token is an operator and is different than the start token + if (*start >= OP_UNION && *start != start_token) { + // Skip wraped regions but save iterator position to check precedence and + // add right parenthesis depending on the precedence of the original token + // when a right parenthesis is encountered of the opposite token + if (*start == OP_LEFT_PAREN) { + return_iterator = start; + int depth = 1; + do { + start++; + if (*start > OP_COMPLEMENT) { + if (*start == OP_RIGHT_PAREN) { + depth--; + } else { + depth++; + } } + } while (depth > 0); + } else if (start_token == OP_UNION) { + start = infix.insert(start - 1, OP_RIGHT_PAREN); + if (return_iterator == infix.begin()) { + return_iterator = start - 1; } - } while (depth > 0); + return return_iterator; + } else { + start = infix.insert(start, OP_RIGHT_PAREN); + if (return_iterator == infix.begin()) { + return_iterator = start - 1; + } + return return_iterator; + } } } - // If we get here a right parenthesis hasn't been placed, // return iterator infix.push_back(OP_RIGHT_PAREN); + if (return_iterator == infix.begin()) { + return_iterator = start - 1; + } return return_iterator; } @@ -168,15 +184,15 @@ void add_precedence(std::vector& infix) // If the token is a union another operator has not been found set the // current operator to union // If the current operator is a union and the token is an intersection - // assert precedence + // assert precedence // If the token is a parenthesis reset the current operator - if (token == OP_UNION && current_op == 0) { - current_op = OP_UNION; - - } else if (current_op == OP_UNION && token == OP_INTERSECTION) { - it = add_parenthesis(it - 1, infix); - current_op = 0; - + if (token == OP_UNION || token == OP_INTERSECTION) { + if (current_op == 0) { + current_op = token; + } else if (token != current_op) { + it = add_parenthesis(it, infix); + current_op = 0; + } } else if (token > OP_COMPLEMENT) { current_op = 0; } @@ -577,7 +593,6 @@ CSGCell::CSGCell(pugi::xml_node cell_node) // Morgans law region_ = tokenize(region_spec); remove_complement_ops(region_); - region_.shrink_to_fit(); // Convert user IDs to surface indices. for (auto& r : region_) { @@ -602,16 +617,18 @@ CSGCell::CSGCell(pugi::xml_node cell_node) break; } } + region_.shrink_to_fit(); + region_infix_ = region_; // If this cell is simple, remove all the superfluous operator tokens. if (simple_) { - for (auto it = region_.begin(); it != region_.end(); it++) { + for (auto it = region_infix_.begin(); it != region_infix_.end(); it++) { if (*it == OP_INTERSECTION || *it > OP_COMPLEMENT) { - region_.erase(it); + region_infix_.erase(it); } } + region_infix_.shrink_to_fit(); } - region_.shrink_to_fit(); // Read the translation vector. if (check_for_node(cell_node, "translation")) { @@ -655,7 +672,7 @@ std::pair CSGCell::distance( double min_dist {INFTY}; int32_t i_surf {std::numeric_limits::max()}; - for (int32_t token : region_) { + for (int32_t token : region_infix_) { // Ignore this token if it corresponds to an operator rather than a region. if (token >= OP_UNION) continue; @@ -710,7 +727,7 @@ void CSGCell::to_hdf5_inner(hid_t group_id) const BoundingBox CSGCell::bounding_box_simple() const { BoundingBox bbox; - for (int32_t token : region_) { + for (int32_t token : region_infix_) { bbox &= model::surfaces[abs(token) - 1]->bounding_box(token > 0); } return bbox; @@ -820,14 +837,14 @@ BoundingBox CSGCell::bounding_box_complex(vector rpn) BoundingBox CSGCell::bounding_box() const { - return simple_ ? bounding_box_simple() : bounding_box_complex(region_); + return simple_ ? bounding_box_simple() : bounding_box_complex(region_infix_); } //============================================================================== bool CSGCell::contains_simple(Position r, Direction u, int32_t on_surface) const { - for (int32_t token : region_) { + for (int32_t token : region_infix_) { // Assume that no tokens are operators. Evaluate the sense of particle with // respect to the surface and see if the token matches the sense. If the // particle's surface attribute is set and matches the token, that @@ -854,7 +871,7 @@ bool CSGCell::contains_complex( bool in_cell = true; // For each token - for (auto it = region_.begin(); it != region_.end(); it++) { + for (auto it = region_infix_.begin(); it != region_infix_.end(); it++) { int32_t token = *it; // If the token is a surface evaluate the sense @@ -873,32 +890,22 @@ bool CSGCell::contains_complex( } else if ((token == OP_UNION && in_cell == true) || (token == OP_INTERSECTION && in_cell == false)) { // While the iterator is within the bounds of the vector + int depth = 1; do { // Get next token it++; int32_t next_token = *it; - // If the next token is an operator and is not the same as the one that - // started the short circuiting, check if it is a left parenthesis to - // skip a section or break - if (next_token >= OP_UNION && token != next_token) { - if (next_token == OP_LEFT_PAREN) { - int depth = 1; - do { - it++; - if (*it > OP_COMPLEMENT) { - if (*it == OP_RIGHT_PAREN) { - depth--; - } else { - depth++; - } - } - } while (depth > 0); + // If the token is an a parenthesis + if (next_token > OP_COMPLEMENT) { + // Adjust depth accordingly + if (next_token == OP_RIGHT_PAREN) { + depth--; } else { - break; + depth++; } } - } while (it < region_.end() - 1); + } while (depth > 0 && it < region_infix_.end() - 1); } } return in_cell; diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index c3458d4697..7648d270ae 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -154,7 +154,7 @@ void partition_universes() // Collect the set of surfaces in this universe. std::unordered_set surf_inds; for (auto i_cell : univ->cells_) { - for (auto token : model::cells[i_cell]->region_) { + for (auto token : model::cells[i_cell]->region_infix_) { if (token < OP_UNION) surf_inds.insert(std::abs(token) - 1); } diff --git a/src/universe.cpp b/src/universe.cpp index 873d03bb74..723400ec05 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -98,7 +98,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find all of the z-planes in this universe. A set is used here for the // O(log(n)) insertions that will ensure entries are not repeated. for (auto i_cell : univ.cells_) { - for (auto token : model::cells[i_cell]->region_) { + for (auto token : model::cells[i_cell]->region_infix_) { if (token < OP_UNION) { auto i_surf = std::abs(token) - 1; const auto* surf = model::surfaces[i_surf].get(); @@ -125,7 +125,7 @@ UniversePartitioner::UniversePartitioner(const Universe& univ) // Find the tokens for bounding z-planes. int32_t lower_token = 0, upper_token = 0; double min_z, max_z; - for (auto token : model::cells[i_cell]->region_) { + for (auto token : model::cells[i_cell]->region_infix_) { if (token < OP_UNION) { const auto* surf = model::surfaces[std::abs(token) - 1].get(); if (const auto* zplane = dynamic_cast(surf)) {