From 71dfde8d12942170a9a8d91796ab40a6e9becaaf Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 3 Oct 2015 09:26:50 +0700 Subject: [PATCH] Adopt shorthand notation for half-spaces and regions in Python API Surfaces now have __neg__ and __pos__ operators, and regions have __and__, __or__, and __invert__. This makes the syntax for complex regions much less bulky. --- docs/source/usersguide/input.rst | 4 ++-- openmc/region.py | 29 ++++++++++++++++++---------- openmc/surface.py | 20 ++++++------------- src/string.F90 | 8 ++++---- tests/test_complex_cell/geometry.xml | 2 +- 5 files changed, 32 insertions(+), 31 deletions(-) diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index fbc74de4af..91751596ae 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -896,7 +896,7 @@ Each ```` element can have the following attributes or sub-elements: the cell occupies. Each half-space is identified by the unique ID of the surface prefixed by `-` or `+` to indicate that it is the negative or positive half-space, respectively. The `+` sign for a positive half-space - can be omitted. Valid Boolean operators are parentheses, union `^`, + can be omitted. Valid Boolean operators are parentheses, union `|`, complement `~`, and intersection. Intersection is implicit and indicated by the presence of whitespace. The order of operator precedence is parentheses, complement, intersection, and then union. @@ -908,7 +908,7 @@ Each ```` element can have the following attributes or sub-elements: .. code-block:: xml - + .. note:: The ``region`` attribute/element can be omitted to make a cell fill its entire universe. diff --git a/openmc/region.py b/openmc/region.py index cb745b7f8c..c4e1e2143b 100644 --- a/openmc/region.py +++ b/openmc/region.py @@ -7,6 +7,15 @@ from openmc.checkvalue import check_type class Region(object): __metaclass__ = ABCMeta + def __and__(self, other): + return Intersection(self, other) + + def __or__(self, other): + return Union(self, other) + + def __invert__(self): + return Complement(self) + @abstractmethod def __str__(self): return '' @@ -19,8 +28,8 @@ class Region(object): ---------- expression : str Boolean expression relating surface half-spaces. The possible - operators are union '^', intersection ' ', and complement '~'. For - example, '(1 -2) ^ 3 ~(4 -5)'. + operators are union '|', intersection ' ', and complement '~'. For + example, '(1 -2) | 3 ~(4 -5)'. surfaces : dict Dictionary whose keys are suface IDs that appear in the Boolean expression and whose values are Surface objects. @@ -37,7 +46,7 @@ class Region(object): i_start = -1 tokens = [] while i < len(expression): - if expression[i] in '()^~ ': + if expression[i] in '()|~ ': # If special character appears immediately after a non-operator, # create a token with the apporpriate half-space if i_start >= 0: @@ -47,7 +56,7 @@ class Region(object): else: tokens.append(surfaces[abs(j)].positive) - if expression[i] in '()^~': + if expression[i] in '()|~': # For everything other than intersection, add the operator # to the list of tokens tokens.append(expression[i]) @@ -60,7 +69,7 @@ class Region(object): # is not a left parenthese or union operator, that implies that the # whitespace is to be interpreted as an intersection operator if (i_start >= 0 or tokens[-1] == ')') and \ - expression[i+1] not in ')^': + expression[i+1] not in ')|': tokens.append(' ') i_start = -1 @@ -104,7 +113,7 @@ class Region(object): output.append(r1) else: output.append(Intersection(r1, r2)) - elif operator == '^': + elif operator == '|': r1 = output.pop() if isinstance(r1, Union) and can_be_combined(r2): r1.nodes.append(r2) @@ -124,10 +133,10 @@ class Region(object): # generate an abstract syntax tree for the region expression. output = [] stack = [] - precedence = {'^': 1, ' ': 2, '~': 3} - associativity = {'^': 'left', ' ': 'left', '~': 'right'} + precedence = {'|': 1, ' ': 2, '~': 3} + associativity = {'|': 'left', ' ': 'left', '~': 'right'} for token in tokens: - if token in (' ', '^', '~'): + if token in (' ', '|', '~'): # Normal operators while stack: op = stack[-1] @@ -225,7 +234,7 @@ class Union(Region): self._nodes = nodes def __str__(self): - return '(' + ' ^ '.join(map(str, self.nodes)) + ')' + return '(' + ' | '.join(map(str, self.nodes)) + ')' class Complement(Region): diff --git a/openmc/surface.py b/openmc/surface.py index 98ec903c7c..a5763d9cf2 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -48,12 +48,6 @@ class Surface(object): Unique identifier for the surface name : str Name of the surface - negative : Halfspace - Negative half-space of the surface, i.e., if :math:`f(x,y,z) = 0` is the - equation for the sufrace, the region for which :math:`f(x,y,z) < 0`. - positive : Halfspace - Positive half-space of the surface, i.e., if :math:`f(x,y,z) = 0` is the - equation for the sufrace, the region for which :math:`f(x,y,z) > 0`. type : str Type of the surface, e.g. 'x-plane' @@ -75,6 +69,12 @@ class Surface(object): # proper order self._coeff_keys = [] + def __neg__(self): + return Halfspace(self, '-') + + def __pos__(self): + return Halfspace(self, '+') + @property def id(self): return self._id @@ -95,14 +95,6 @@ class Surface(object): def coeffs(self): return self._coeffs - @property - def negative(self): - return Halfspace(self, '-') - - @property - def positive(self): - return Halfspace(self, '+') - @id.setter def id(self, surface_id): if surface_id is None: diff --git a/src/string.F90 b/src/string.F90 index b505aa869b..91a255a361 100644 --- a/src/string.F90 +++ b/src/string.F90 @@ -67,7 +67,7 @@ contains !=============================================================================== ! TOKENIZE takes a string that includes logical expressions for a list of ! bounding surfaces in a cell and splits it into separate tokens. The characters -! (, ), ^, and ~ count as separate tokens since they represent operators. +! (, ), |, and ~ count as separate tokens since they represent operators. !=============================================================================== subroutine tokenize(string, tokens) @@ -85,7 +85,7 @@ contains i = 1 do while (i <= len_trim(string_)) ! Check for special characters - if (index('()^~ ', string_(i:i)) > 0) then + if (index('()|~ ', string_(i:i)) > 0) then ! If the special character appears immediately after a non-operator, ! create a token with the surface half-space if (i_start > 0) then @@ -98,7 +98,7 @@ contains call tokens%push_back(OP_LEFT_PAREN) case (')') call tokens%push_back(OP_RIGHT_PAREN) - case ('^') + case ('|') call tokens%push_back(OP_UNION) case ('~') call tokens%push_back(OP_COMPLEMENT) @@ -112,7 +112,7 @@ contains ! is not a left parenthese or union operator, that implies that the ! whitespace is to be interpreted as an intersection operator if (i_start > 0 .or. tokens%data(tokens%size()) == OP_RIGHT_PAREN) then - if (index(')^', string_(i+1:i+1)) == 0) then + if (index(')|', string_(i+1:i+1)) == 0) then call tokens%push_back(OP_INTERSECTION) end if end if diff --git a/tests/test_complex_cell/geometry.xml b/tests/test_complex_cell/geometry.xml index 1609dad104..18e304fe0e 100644 --- a/tests/test_complex_cell/geometry.xml +++ b/tests/test_complex_cell/geometry.xml @@ -18,7 +18,7 @@ - +