Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/openmc/cell.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ class Region {
//! Get a vector of the region expression in postfix notation
vector<int32_t> generate_postfix(int32_t cell_id) const;

//! Get a vector of the region expression in infix notation
vector<int32_t> generate_infix(vector<int32_t> rpn) const;

//! Determine if a particle is inside the cell for a simple cell (only
//! intersection operators)
bool contains_simple(Position r, Direction u, int32_t on_surface) const;
Expand Down
59 changes: 59 additions & 0 deletions src/cell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,10 @@ Region::Region(std::string region_spec, int32_t cell_id)
it--;
}
}
} else {
// Simplify expression by going to rpn and back
auto postfix = generate_postfix(cell_id);
expression_ = generate_infix(postfix);
}
expression_.shrink_to_fit();

Expand Down Expand Up @@ -879,6 +883,61 @@ vector<int32_t> Region::generate_postfix(int32_t cell_id) const
return rpn;
}

//==============================================================================
//! Convert Reverse Polish Notation (RPN) to infix using minimal parentheses.
//==============================================================================

vector<int32_t> Region::generate_infix(vector<int32_t> rpn) const
{

vector<vector<int32_t>> stack;
vector<int32_t> pstack;
std::unordered_map<int32_t, int32_t> precedence = {
{OP_UNION, 1}, {OP_INTERSECTION, 2}, {OP_COMPLEMENT, 3}};

int HIGH = 4;

for (auto it = rpn.begin(); it != rpn.end(); ++it) {
auto token = *it;
if (precedence.find(token) != precedence.end()) {
auto p_c = precedence[token];

auto v_r = stack.back();
stack.pop_back();
auto p_r = pstack.back();
pstack.pop_back();

auto v_l = stack.back();
stack.pop_back();
auto p_l = pstack.back();
pstack.pop_back();

if (p_l != p_c && p_l != HIGH) {
v_l.emplace(v_l.begin(), OP_LEFT_PAREN);
v_l.emplace_back(OP_RIGHT_PAREN);
}
v_l.emplace_back(token);

if ((p_r != p_c && p_r != HIGH) ||
((p_r == p_c) && (token == OP_COMPLEMENT))) {
v_r.emplace(v_r.begin(), OP_LEFT_PAREN);
v_r.emplace_back(OP_RIGHT_PAREN);
}

vector<int32_t> merged = v_l;
merged.reserve(v_l.size() + v_r.size());
merged.insert(merged.end(), v_r.begin(), v_r.end());

stack.emplace_back(merged);
pstack.emplace_back(p_c);
} else {
stack.emplace_back(vector<int32_t> {token});
pstack.emplace_back(HIGH);
}
}
return stack.back();
}

//==============================================================================

std::string Region::str() const
Expand Down
1 change: 1 addition & 0 deletions tests/cpp_unit_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set(TEST_NAMES
test_math
test_mcpl_stat_sum
test_mesh
test_region
# Add additional unit test files here
)

Expand Down
27 changes: 27 additions & 0 deletions tests/cpp_unit_tests/test_region.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <catch2/catch_test_macros.hpp>

#include "openmc/cell.h"
#include "openmc/surface.h"

#include <pugixml.hpp>

TEST_CASE("Test region simplification")
{
pugi::xml_document doc;
pugi::xml_node surf_node = doc.append_child("surface");
surf_node.set_name("surface");
surf_node.append_attribute("id") = "0";
surf_node.append_attribute("type") = "x-plane";
surf_node.append_attribute("coeffs") = "1";

for (int i = 1; i < 7; ++i) {
surf_node.attribute("id") = i;
openmc::model::surfaces.push_back(
std::make_unique<openmc::SurfaceXPlane>(surf_node));
openmc::model::surface_map[i] = i - 1;
}
auto region = openmc::Region("(-1 2 (-3 4) | (-5 6))", 0);
auto ref_val = " ( -1 2 -3 4 ) | ( -5 6 )";
auto test_val = region.str();
REQUIRE(test_val == ref_val);
}
Loading