From 3439797e322a78f88bce137ad77835e3c2fb3706 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 24 Jul 2019 03:02:10 -0500 Subject: [PATCH] Update for case where the entire region is a complement. Addition of a cell and redefinition of another to test more robustly. --- include/openmc/cell.h | 1 + src/cell.cpp | 23 +++++++++++++++++----- tests/unit_tests/test_complex_cell_capi.py | 15 +++++++------- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/include/openmc/cell.h b/include/openmc/cell.h index 602da98e7a..db8d60ed48 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -212,6 +212,7 @@ protected: bool contains_complex(Position r, Direction u, int32_t on_surface) const; BoundingBox bounding_box_simple() const; static BoundingBox bounding_box_complex(std::vector rpn); + static void apply_demorgan(std::vector& rpn); }; //============================================================================== diff --git a/src/cell.cpp b/src/cell.cpp index 49d8cb1b41..510002fa97 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -587,8 +587,25 @@ BoundingBox CSGCell::bounding_box_simple() const { return bbox; } +void CSGCell::apply_demorgan(std::vector& rpn) { + for (auto& token : rpn) { + if (token < OP_UNION) { token *= -1; } + else if (token == OP_UNION) { token = OP_INTERSECTION; } + else if (token == OP_INTERSECTION) { token = OP_UNION; } + } +} + BoundingBox CSGCell::bounding_box_complex(std::vector rpn) { + // if the last operator is a complement op, there is no + // sub-region that the complement connects to. This indicates + // that the entire region is a complement and we can apply + // De Morgan's laws immediately + if ((rpn.back() == OP_COMPLEMENT)) { + rpn.pop_back(); + apply_demorgan(rpn); + } + std::reverse(rpn.begin(), rpn.end()); BoundingBox current = model::surfaces[abs(rpn.back()) - 1]->bounding_box(rpn.back() > 0); @@ -626,11 +643,7 @@ BoundingBox CSGCell::bounding_box_complex(std::vector rpn) { // handle complement case using De Morgan's laws if (subrpn.back() == OP_COMPLEMENT) { subrpn.pop_back(); - for (auto& token : subrpn) { - if (token < OP_UNION) { token *= -1; } - else if (token == OP_UNION) { token = OP_INTERSECTION; } - else if (token == OP_INTERSECTION) { token = OP_UNION; } - } + apply_demorgan(subrpn); subrpn.push_back(rpn.back()); rpn.pop_back(); } diff --git a/tests/unit_tests/test_complex_cell_capi.py b/tests/unit_tests/test_complex_cell_capi.py index ebc345f8f8..451233d642 100644 --- a/tests/unit_tests/test_complex_cell_capi.py +++ b/tests/unit_tests/test_complex_cell_capi.py @@ -46,7 +46,7 @@ def complex_cell(run_in_tmpdir): s17 = openmc.YPlane(y0=0.0) c1 = openmc.Cell(fill=u235) - c1.region = +s3 & -s4 & +s13 & -s14 + c1.region = ~(-s3 | +s4 | ~(+s13 & -s14)) c2 = openmc.Cell(fill=u238) c2.region = +s2 & -s5 & +s12 & -s15 & ~(+s3 & -s4 & +s13 & -s14) @@ -59,8 +59,11 @@ def complex_cell(run_in_tmpdir): c4.region = ((+s1 & -s7 & +s11 & -s17) | (+s7 & -s6 & +s17 & -s16)) & \ ~(+s2 & -s5 & +s12 & -s15) + c5 = openmc.Cell(fill=n14) + c5.region = ~(+s1 & -s6 & +s11 & -s16) + model.geometry.root_universe = openmc.Universe() - model.geometry.root_universe.add_cells([c1, c2, c3, c4]) + model.geometry.root_universe.add_cells([c1, c2, c3, c4, c5]) model.settings.batches = 10 model.settings.inactive = 5 @@ -84,13 +87,11 @@ inf = sys.float_info.max expected_results = ( (1, (( -4., -4., -inf), ( 4., 4., inf))), (2, (( -7., -7., -inf), ( 7., 7., inf))), (3, ((-10., -10., -inf), (10., 10., inf))), - (4, ((-10., -10., -inf), (10., 10., inf))) ) + (4, ((-10., -10., -inf), (10., 10., inf))), + (5, ((-inf, -inf, -inf), (inf, inf, inf))) ) @pytest.mark.parametrize("cell_id,expected_box", expected_results) def test_cell_box(cell_id, expected_box): + print("Cell {}".format(cell_id)) cell_box = openmc.capi.cells[cell_id].bounding_box assert tuple(cell_box[0]) == expected_box[0] assert tuple(cell_box[1]) == expected_box[1] - - cell_box = openmc.capi.bounding_box("Cell", cell_id) - assert tuple(cell_box[0]) == expected_box[0] - assert tuple(cell_box[1]) == expected_box[1]