From c72e0aab83d7346ac63554b5ad2ebed769c4928e Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Sat, 13 Jan 2024 22:08:26 -0600 Subject: [PATCH 01/12] Enforced unique surface types. --- montepy/surfaces/surface_type.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/montepy/surfaces/surface_type.py b/montepy/surfaces/surface_type.py index bd440c53..6fb86f47 100644 --- a/montepy/surfaces/surface_type.py +++ b/montepy/surfaces/surface_type.py @@ -2,7 +2,7 @@ from enum import unique, Enum -# @unique +@unique class SurfaceType(str, Enum): """ An enumeration of the surface types allowed. From a50203302e97922f757308c2c388a88df91db0f1 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Sat, 13 Jan 2024 22:08:51 -0600 Subject: [PATCH 02/12] Added tallies object. --- montepy/mcnp_problem.py | 2 ++ montepy/tallies.py | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 montepy/tallies.py diff --git a/montepy/mcnp_problem.py b/montepy/mcnp_problem.py index 7e4d8f3e..b9cbd56f 100644 --- a/montepy/mcnp_problem.py +++ b/montepy/mcnp_problem.py @@ -9,6 +9,7 @@ from montepy.constants import DEFAULT_VERSION from montepy.materials import Materials from montepy.surfaces import surface_builder +from montepy.tallies import Tallies from montepy.surface_collection import Surfaces from montepy.data_inputs import Material, parse_data from montepy.input_parser import input_syntax_reader, block_type, mcnp_input @@ -36,6 +37,7 @@ def __init__(self, file_name): self._surfaces = Surfaces(problem=self) self._universes = Universes(problem=self) self._transforms = Transforms(problem=self) + self._tallies = Tallies(problem=self) self._data_inputs = [] self._materials = Materials(problem=self) self._mcnp_version = DEFAULT_VERSION diff --git a/montepy/tallies.py b/montepy/tallies.py new file mode 100644 index 00000000..f4778917 --- /dev/null +++ b/montepy/tallies.py @@ -0,0 +1,17 @@ +# Copyright 2024, Battelle Energy Alliance, LLC All Rights Reserved. +import montepy +from montepy.numbered_object_collection import NumberedObjectCollection + +Tally = montepy.data_inputs.tally.Tally + + +class Tallies(NumberedObjectCollection): + """ + A container of multiple :class:`~montepy.data_inputs.tally.Tally` instances. + + :param objects: the list of tallies to start with if needed + :type objects: list + """ + + def __init__(self, objects=None, problem=None): + super().__init__(Tally, objects, problem) From 8fbe84e3113757c8574bfe0ae77ce993952fb36f Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Sat, 13 Jan 2024 22:09:21 -0600 Subject: [PATCH 03/12] Listed tally types allowed. --- montepy/data_inputs/tally_type.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 montepy/data_inputs/tally_type.py diff --git a/montepy/data_inputs/tally_type.py b/montepy/data_inputs/tally_type.py new file mode 100644 index 00000000..170558a5 --- /dev/null +++ b/montepy/data_inputs/tally_type.py @@ -0,0 +1,16 @@ +# Copyright 2024, Battelle Energy Alliance, LLC All Rights Reserved. + +from enum import unique, Enum + + +@unique +class TallyType(Enum): + """ """ + + CURRENT = 1 + SURFACE_FLUX = 2 + CELL_FLUX = 4 + DETECTOR = 5 + ENERGY_DEPOSITION = 6 + FISSION_ENERGY_DEPOSITION = 7 + ENERGY_DETECTOR_PULSE = 8 From 7d26ebdea8db412513000e87c116b6b65f5e6205 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Sat, 13 Jan 2024 22:09:48 -0600 Subject: [PATCH 04/12] Started parsing tally objects. --- montepy/data_inputs/tally.py | 66 +++++++++++++++++++++++++++- montepy/input_parser/tally_parser.py | 2 +- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/montepy/data_inputs/tally.py b/montepy/data_inputs/tally.py index ecfc6429..d9738be8 100644 --- a/montepy/data_inputs/tally.py +++ b/montepy/data_inputs/tally.py @@ -1,14 +1,49 @@ # Copyright 2024, Battelle Energy Alliance, LLC All Rights Reserved. +import copy + import montepy +from montepy.cells import Cells from montepy.data_inputs.data_input import DataInputAbstract +from montepy.data_inputs.tally_type import TallyType from montepy.input_parser.tally_parser import TallyParser +from montepy.numbered_mcnp_object import Numbered_MCNP_Object +from montepy.utilities import * + +_TALLY_TYPE_MODULUS = 10 + + +def _number_validator(self, number): + if number <= 0: + raise ValueError("number must be > 0") + if number % _TALL_TYPE_MODULUS != self._type.value: + raise ValueError(f"Tally Type cannot be changed.") + if self._problem: + self._problem.tallies.check_number(number) -class Tally(DataInputAbstract): +class Tally(DataInputAbstract, Numbered_MCNP_Object): """ """ _parser = TallyParser() + __slots__ = {"_groups", "_type", "_number", "_old_number"} + + def __init__(self, input=None): + self._cells = Cells() + self._old_number = None + self._number = self._generate_default_node(int, -1) + super().__init__(input) + if input: + num = self._input_number + self._old_number = copy.deepcopy(num) + self._number = num + print(self._tree["tally"]) + assert False + try: + tally_type = TallyType(self.number % _TALLY_TYPE_MODULUS) + except ValueError as e: + raise MalformedInputEror(input, f"Tally Type provided not allowed: {e}") + @staticmethod def _class_prefix(): return "f" @@ -19,4 +54,31 @@ def _has_number(): @staticmethod def _has_classifier(): - return 1 + return 2 + + @make_prop_val_node("_old_number") + def old_number(self): + """ + The material number that was used in the read file + + :rtype: int + """ + pass + + @make_prop_val_node("_number", int, validator=_number_validator) + def number(self): + """ + The number to use to identify the material by + + :rtype: int + """ + pass + + +class TallyGroup: + __slots__ = {"_cells"} + + def __init__( + self, + ): + self._cells = montepy.cells.Cells() diff --git a/montepy/input_parser/tally_parser.py b/montepy/input_parser/tally_parser.py index 50a8c917..0f3e8096 100644 --- a/montepy/input_parser/tally_parser.py +++ b/montepy/input_parser/tally_parser.py @@ -13,7 +13,7 @@ def tally(self, p): ret = {} for key, node in p.introduction.nodes.items(): ret[key] = node - ret["tally"] = p.tally_specification + ret["tally"] = p.tally_specification["tally"] return syntax_node.SyntaxNode("data", ret) @_("tally_numbers", "tally_numbers end_phrase") From 2bb0cce5c12fce6557389fa383039ea6bcd7474e Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Sun, 14 Jan 2024 15:06:56 -0600 Subject: [PATCH 05/12] Flattened tally specification data structure for parsing. --- montepy/data_inputs/tally.py | 2 -- montepy/input_parser/tally_parser.py | 38 +++++++++++++--------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/montepy/data_inputs/tally.py b/montepy/data_inputs/tally.py index d9738be8..6a5ca764 100644 --- a/montepy/data_inputs/tally.py +++ b/montepy/data_inputs/tally.py @@ -37,8 +37,6 @@ def __init__(self, input=None): num = self._input_number self._old_number = copy.deepcopy(num) self._number = num - print(self._tree["tally"]) - assert False try: tally_type = TallyType(self.number % _TALLY_TYPE_MODULUS) except ValueError as e: diff --git a/montepy/input_parser/tally_parser.py b/montepy/input_parser/tally_parser.py index 0f3e8096..b1bad16c 100644 --- a/montepy/input_parser/tally_parser.py +++ b/montepy/input_parser/tally_parser.py @@ -27,6 +27,11 @@ def tally_specification(self, p): "tally list", {"tally": p.tally_numbers, "end": text} ) + @_('"("', '"(" padding', '")"', '")" padding') + def paren_phrase(self, p): + """ """ + return self._flush_phrase(p, str) + @_("PARTICLE", "PARTICLE padding") def end_phrase(self, p): """ @@ -41,31 +46,24 @@ def end_phrase(self, p): "tally_numbers tally_numbers", "number_sequence", "tally_group", - "tally_numbers padding", ) def tally_numbers(self, p): - if hasattr(p, "tally_numbers"): - ret = p.tally_numbers - ret.nodes["right"] += p.padding - return ret if hasattr(p, "tally_numbers1"): - return syntax_node.SyntaxNode("tally tree", {"left": p[0], "right": p[1]}) + ret = p.tally_numbers1 + for node in p.tally_numbers2.nodes: + ret.append(node) + return ret else: - left = syntax_node.PaddingNode(None) - right = syntax_node.PaddingNode(None) - return syntax_node.SyntaxNode( - "tally set", {"left": left, "tally": p[0], "right": right} - ) + return p[0] @_( - '"(" number_sequence ")"', - '"(" padding number_sequence ")"', + 'paren_phrase number_sequence paren_phrase', ) def tally_group(self, p): - left = syntax_node.PaddingNode(p[0]) - if hasattr(p, "padding"): - left.append(p.padding) - right = syntax_node.PaddingNode(p[-1]) - return syntax_node.SyntaxNode( - "tally set", {"left": left, "tally": p.number_sequence, "right": right} - ) + ret = syntax_node.ListNode() + ret.append(p[0]) + for node in p.number_sequence.nodes: + ret.append(node) + ret.append(p[2]) + return ret + From 8a38f168bda722d2d334cc945721b69380395661 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Sun, 14 Jan 2024 17:58:33 -0600 Subject: [PATCH 06/12] keep parens as valueNode not PaddingNode. --- montepy/input_parser/cell_parser.py | 4 ++-- montepy/input_parser/tally_parser.py | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/montepy/input_parser/cell_parser.py b/montepy/input_parser/cell_parser.py index 567c9963..825d7ff7 100644 --- a/montepy/input_parser/cell_parser.py +++ b/montepy/input_parser/cell_parser.py @@ -178,7 +178,7 @@ def geometry_factory(self, p): def number_sequence(self, p): if isinstance(p[0], str): sequence = syntax_node.ListNode("parenthetical statement") - sequence.append(p[0]) + sequence.append(syntax_node.ValueNode(p[0], str)) else: sequence = p[0] for node in list(p)[1:]: @@ -186,7 +186,7 @@ def number_sequence(self, p): for val in node.nodes: sequence.append(val) elif isinstance(node, str): - sequence.append(syntax_node.PaddingNode(node)) + sequence.append(syntax_node.ValueNode(node, str)) else: sequence.append(node) return sequence diff --git a/montepy/input_parser/tally_parser.py b/montepy/input_parser/tally_parser.py index b1bad16c..54d79f61 100644 --- a/montepy/input_parser/tally_parser.py +++ b/montepy/input_parser/tally_parser.py @@ -57,7 +57,7 @@ def tally_numbers(self, p): return p[0] @_( - 'paren_phrase number_sequence paren_phrase', + "paren_phrase number_sequence paren_phrase", ) def tally_group(self, p): ret = syntax_node.ListNode() @@ -66,4 +66,3 @@ def tally_group(self, p): ret.append(node) ret.append(p[2]) return ret - From 94d021725e2e276d6cdf3b9157135d8012f67541 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Sun, 14 Jan 2024 17:59:09 -0600 Subject: [PATCH 07/12] Started group parsing mechanism --- montepy/data_inputs/tally.py | 38 ++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/montepy/data_inputs/tally.py b/montepy/data_inputs/tally.py index 6a5ca764..c9091c0b 100644 --- a/montepy/data_inputs/tally.py +++ b/montepy/data_inputs/tally.py @@ -24,9 +24,10 @@ def _number_validator(self, number): class Tally(DataInputAbstract, Numbered_MCNP_Object): """ """ + # todo type enforcement _parser = TallyParser() - __slots__ = {"_groups", "_type", "_number", "_old_number"} + __slots__ = {"_groups", "_type", "_number", "_old_number", "_include_total"} def __init__(self, input=None): self._cells = Cells() @@ -41,6 +42,11 @@ def __init__(self, input=None): tally_type = TallyType(self.number % _TALLY_TYPE_MODULUS) except ValueError as e: raise MalformedInputEror(input, f"Tally Type provided not allowed: {e}") + groups, has_total = TallyGroup.parse_tally_specification( + self._tree["tally"] + ) + self._groups = group + self._include_total = has_total @staticmethod def _class_prefix(): @@ -76,7 +82,31 @@ def number(self): class TallyGroup: __slots__ = {"_cells"} - def __init__( - self, - ): + def __init__(self, cells=None, nodes=None): self._cells = montepy.cells.Cells() + + @staticmethod + def parse_tally_specification(tally_spec): + # TODO type enforcement + ret = [] + in_parens = False + buff = None + has_total = False + for node in tally_spec: + # TODO handle total + if in_parens: + if node.value == ")": + in_parens = False + buff.append(node) + ret.append(buff) + buff = None + else: + buff.apend(node) + else: + if node.value == "(": + in_parens = True + buff = TallyGroup() + buff.append(node) + else: + ret.append(TallyGroup(nodes=[node])) + return (ret, has_total) From d98e63e724d074729869a5ab7eeb31570d05dde3 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Mon, 15 Jan 2024 15:48:36 -0600 Subject: [PATCH 08/12] Implemented append for tally groups. --- montepy/data_inputs/tally.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/montepy/data_inputs/tally.py b/montepy/data_inputs/tally.py index c9091c0b..c99ca097 100644 --- a/montepy/data_inputs/tally.py +++ b/montepy/data_inputs/tally.py @@ -6,6 +6,7 @@ from montepy.data_inputs.data_input import DataInputAbstract from montepy.data_inputs.tally_type import TallyType from montepy.input_parser.tally_parser import TallyParser +from montepy.input_parser import syntax_node from montepy.numbered_mcnp_object import Numbered_MCNP_Object from montepy.utilities import * @@ -45,7 +46,7 @@ def __init__(self, input=None): groups, has_total = TallyGroup.parse_tally_specification( self._tree["tally"] ) - self._groups = group + self._groups = groups self._include_total = has_total @staticmethod @@ -80,10 +81,11 @@ def number(self): class TallyGroup: - __slots__ = {"_cells"} + __slots__ = {"_cells", "_old_numbers"} def __init__(self, cells=None, nodes=None): self._cells = montepy.cells.Cells() + self._old_numbers = [] @staticmethod def parse_tally_specification(tally_spec): @@ -97,16 +99,21 @@ def parse_tally_specification(tally_spec): if in_parens: if node.value == ")": in_parens = False - buff.append(node) + buff._append_node(node) ret.append(buff) buff = None else: - buff.apend(node) + buff._append_node(node) else: if node.value == "(": in_parens = True buff = TallyGroup() - buff.append(node) + buff._append_node(node) else: ret.append(TallyGroup(nodes=[node])) return (ret, has_total) + + def _append_node(self, node): + if not isinstance(node, syntax_node.ValueNode): + raise ValueError(f"Can only append ValueNode. {node} given") + self._old_numbers.append(node) From 8c652ca92664bfcee524feb97fd768e2961ee672 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Mon, 15 Jan 2024 15:57:44 -0600 Subject: [PATCH 09/12] Made tally appendable. --- montepy/data_inputs/tally.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/montepy/data_inputs/tally.py b/montepy/data_inputs/tally.py index c99ca097..12913c07 100644 --- a/montepy/data_inputs/tally.py +++ b/montepy/data_inputs/tally.py @@ -117,3 +117,6 @@ def _append_node(self, node): if not isinstance(node, syntax_node.ValueNode): raise ValueError(f"Can only append ValueNode. {node} given") self._old_numbers.append(node) + + def append(self, cell): + self._cells.append(cell) From 42cca61ed0edf6f9ac288b2e490d7e2ae502d758 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 16 Jan 2024 12:27:04 -0600 Subject: [PATCH 10/12] Added particle type to test to be accurate. --- tests/test_tally.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_tally.py b/tests/test_tally.py index 9e38df73..9d59d50b 100644 --- a/tests/test_tally.py +++ b/tests/test_tally.py @@ -16,8 +16,8 @@ def test_parsing_tally_groups(self): "F4:n 1 2 3", "F4:n (1 3i 5) (7 8 9) T", "f4:n (1 3i 5) (7 8 9)", - "F7 (1 3i 5) (7 8 9)", - "F7 (1 3i 5) (7 8 9) ", + "F7:n (1 3i 5) (7 8 9)", + "F7:n (1 3i 5) (7 8 9) ", ]: print(line) input = Input([line], BlockType.DATA) From 38e97c4b9a1b25df2e747a8c34f33621ed69a99d Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Wed, 17 Jan 2024 09:57:41 -0600 Subject: [PATCH 11/12] Moved to dev version. --- montepy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/montepy/__init__.py b/montepy/__init__.py index ac195ceb..ace5030b 100644 --- a/montepy/__init__.py +++ b/montepy/__init__.py @@ -23,7 +23,7 @@ from montepy.universe import Universe import sys -__version__ = "0.2.5" +__version__ = "0.3.0dev1" # enable deprecated warnings for users if not sys.warnoptions: From c03132a005f6cfdc67943c2f8ea8d57801cc39a8 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 23 Jul 2024 07:28:25 -0500 Subject: [PATCH 12/12] fixed circular import error. --- montepy/data_inputs/__init__.py | 3 ++- montepy/tallies.py | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/montepy/data_inputs/__init__.py b/montepy/data_inputs/__init__.py index a0c7c6b6..e737ac52 100644 --- a/montepy/data_inputs/__init__.py +++ b/montepy/data_inputs/__init__.py @@ -1,6 +1,7 @@ # Copyright 2024, Battelle Energy Alliance, LLC All Rights Reserved. __name__ = "montepy.data_inputs" from .data_input import DataInput +from .data_parser import parse_data from .material import Material +from .tally import Tally from .thermal_scattering import ThermalScatteringLaw -from .data_parser import parse_data diff --git a/montepy/tallies.py b/montepy/tallies.py index f4778917..8427abf8 100644 --- a/montepy/tallies.py +++ b/montepy/tallies.py @@ -2,8 +2,6 @@ import montepy from montepy.numbered_object_collection import NumberedObjectCollection -Tally = montepy.data_inputs.tally.Tally - class Tallies(NumberedObjectCollection): """ @@ -14,4 +12,4 @@ class Tallies(NumberedObjectCollection): """ def __init__(self, objects=None, problem=None): - super().__init__(Tally, objects, problem) + super().__init__(montepy.data_inputs.tally.Tally, objects, problem)