From 225e1b6e28c0cdcb7ac36678040d1625c31026f1 Mon Sep 17 00:00:00 2001 From: BitterB0NG0 <93603537+BitterB0NG0@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:30:52 -0500 Subject: [PATCH] Added Cell Parameter Testing --- src/pymcnp/files/inp/cell.py | 29 ++- tests/_strategies.py | 354 ++++++++++++++++++++++++++++++++++- tests/test_inp.py | 77 +++++--- 3 files changed, 415 insertions(+), 45 deletions(-) diff --git a/src/pymcnp/files/inp/cell.py b/src/pymcnp/files/inp/cell.py index 9b6dba7..17ccf9f 100644 --- a/src/pymcnp/files/inp/cell.py +++ b/src/pymcnp/files/inp/cell.py @@ -223,7 +223,7 @@ def cast_cell_keyword( if string.startswith("*"): string = string[:1] - if string.startswith(("wwn", "dxc")): + if string.startswith(("wwn", "dxc", "tmp")): if ( len(string) < 4 and types.cast_fortran_integer(string[:3]) is None @@ -373,7 +373,7 @@ def from_mcnp(cls, string: str): parameter.__class__ = Cell.WeightWindowBounds # Processing Suffix/Keyword - suffix = types.cast_fortran_integer(tokens.popl())[3:] + suffix = types.cast_fortran_integer(tokens.popl()[3:]) parameter.set_suffix(suffix) # Processing Value @@ -388,7 +388,7 @@ def from_mcnp(cls, string: str): parameter.__class__ = Cell.DxtranContribution # Processing Suffix/Keyword - suffix = types.cast_fortran_integer(tokens.popl())[3:] + suffix = types.cast_fortran_integer(tokens.popl()[3:]) parameter.set_suffix(suffix) # Processing Value @@ -412,11 +412,8 @@ def from_mcnp(cls, string: str): case "pd": parameter.__class__ = Cell.DetectorContribution - # Processing Keyword - tokens.popl() - # Processing Suffix/Keyword - suffix = types.cast_fortran_integer(tokens.popl())[2:] + suffix = types.cast_fortran_integer(tokens.popl()[2:]) parameter.set_suffix(suffix) # Processing Value @@ -426,11 +423,8 @@ def from_mcnp(cls, string: str): case "tmp": parameter.__class__ = Cell.GasThermalTemperature - # Processing Keyword - tokens.popl() - # Processing Suffix/Keyword - suffix = types.cast_fortran_integer(tokens.popl())[2:] + suffix = types.cast_fortran_integer(tokens.popl()[3:]) parameter.set_suffix(suffix) # Processing Value @@ -614,10 +608,10 @@ def __init__(self): super().__init__() - self.importance: any = None + self.importance: int = None self.designator: tuple[types.Designator] = None - def set_value(self, value: any) -> None: + def set_value(self, value: int) -> None: """ 'set_value' sets cell card particle importance parameter values. @@ -671,9 +665,9 @@ def __init__(self): super().__init__() - self.volume: any = None + self.volume: float = None - def set_value(self, value: any) -> None: + def set_value(self, value: float) -> None: """ 'set_value' sets cell card volume parameter values. @@ -711,9 +705,9 @@ def __init__(self): super().__init__() - self.weight: any = None + self.weight: float = None - def set_value(self, value: any) -> None: + def set_value(self, value: float) -> None: """ 'set_value' sets cell card proton weight parameter values. @@ -1704,6 +1698,7 @@ def from_mcnp(cls, card: str) -> Self: cell.set_parameters(tuple(parameters)) # Processing Geometry + print(tokens) cell.geometry = cls.CellGeometry().from_mcnp(" ".join(tokens.deque)) return cell diff --git a/tests/_strategies.py b/tests/_strategies.py index dc24094..9db0c00 100644 --- a/tests/_strategies.py +++ b/tests/_strategies.py @@ -24,6 +24,57 @@ def fortran_reals(draw, condition=lambda _: True): return str(draw(st.floats(allow_nan=False, allow_infinity=False).filter(condition))) +@st.composite +def mcnp_designators(draw, condition=lambda _: True): + """ + 'mcnp_designator' + """ + + return draw( + st.sampled_from( + [ + "n", + "p", + "e", + "|", + "q", + "y", + "v", + "f", + "h", + "l", + "+", + "-", + "x", + "y", + "o", + "!", + "<", + ">", + "g", + "/", + "z", + "k", + "%", + "^", + "b", + "_", + "~", + "c", + "w", + "@", + "d", + "t", + "s", + "a", + "*", + "?", + "#", + ] + ) + ) + + @st.composite def mcnp_polyhedron_sides(draw, condition=lambda _: True): """ @@ -67,7 +118,9 @@ def mcnp_geometries(draw, identifiers, depth=None) -> str: @st.composite -def mcnp_cells(draw, valid_number, valid_material, valid_density, valid_geometry): +def mcnp_cells( + draw, valid_number, valid_material, valid_density, valid_geometry, valid_parameter +): """ 'mcnp_cells' """ @@ -102,7 +155,304 @@ def mcnp_cells(draw, valid_number, valid_material, valid_density, valid_geometry else: geometry = draw(mcnp_geometries(fortran_integers(lambda i: i > 99_999_999))) - return (number, material, density, geometry) + if valid_parameter is None: + parameters = None + elif valid_parameter: + parameters = draw(mcnp_parameters(True)) + else: + parameters = draw(mcnp_parameters(False)) + + return (number, material, density, geometry, parameters) + + +@st.composite +def mcnp_parameters(draw, valid_value): + return [ + draw(mcnp_parameter_importance(valid_value, True)), + draw(mcnp_parameter_volume(valid_value)), + draw(mcnp_parameter_protonWeight(valid_value)), + draw(mcnp_parameter_exponentialTransform(valid_value, True)), + draw(mcnp_parameter_forcedCollision(valid_value, True)), + draw(mcnp_parameter_weightWindowBounds(valid_value, True, True)), + draw(mcnp_parameter_dxtranContribution(valid_value, True, True)), + draw(mcnp_parameter_fissionTurnOff(valid_value)), + draw(mcnp_parameter_detectorContribution(valid_value, True)), + draw(mcnp_parameter_gasThermalTemperature(valid_value, True)), + draw(mcnp_parameter_universe(valid_value)), + draw(mcnp_parameter_coordinateTransformation(valid_value)), + draw(mcnp_parameter_lattice(valid_value)), + draw(mcnp_parameter_fill(valid_value)), + draw(mcnp_parameter_energyCutoff(valid_value, True)), + draw(mcnp_parameter_cosy(valid_value)), + draw(mcnp_parameter_bfield(valid_value)), + draw(mcnp_parameter_uncolidedSecondaries(valid_value, True)), + ] + + +@st.composite +def mcnp_parameter_importance(draw, valid_value: bool, valid_designator: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_integers(lambda i: i >= 0))) + else: + value = str(draw(fortran_integers(lambda i: i < 0))) + + designator = draw(mcnp_designators(valid_designator)) + + return ("imp", None, designator, value) + + +@st.composite +def mcnp_parameter_volume(draw, valid_value: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_reals(lambda f: f > 0))) + else: + value = str(draw(fortran_reals(lambda f: f <= 0))) + + return ("vol", None, None, value) + + +@st.composite +def mcnp_parameter_protonWeight(draw, valid_value: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_reals())) + else: + value = "a" + + return ("pwt", None, None, value) + + +@st.composite +def mcnp_parameter_exponentialTransform( + draw, valid_value: bool, valid_designator: bool +): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_integers())) + else: + value = "a" + + designator = draw(mcnp_designators(valid_designator)) + + return ("ext", None, designator, value) + + +@st.composite +def mcnp_parameter_forcedCollision(draw, valid_value: bool, valid_designator: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_integers(lambda i: -1 <= i <= 1))) + else: + value = str(draw(fortran_integers(lambda i: -1 > i or i > 1))) + + designator = draw(mcnp_designators(valid_designator)) + + return ("fcl", None, designator, value) + + +@st.composite +def mcnp_parameter_weightWindowBounds( + draw, valid_value: bool, valid_suffix: bool, valid_designator: bool +): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_integers(lambda i: i == -1 or i >= 0))) + else: + value = str(draw(fortran_integers(lambda i: i != -1 and i < 0))) + + if valid_suffix is None: + suffix = None + elif valid_suffix: + suffix = str(draw(fortran_integers(lambda i: 1 <= i and i <= 99_999_999))) + else: + suffix = str(draw(fortran_integers(lambda i: 1 > i or i > 99_999_999))) + + designator = draw(mcnp_designators(valid_designator)) + + return ("wwn", suffix, designator, value) + + +@st.composite +def mcnp_parameter_dxtranContribution( + draw, valid_value: bool, valid_suffix: bool, valid_designator: bool +): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_integers(lambda i: 0 <= i <= 1))) + else: + value = str(draw(fortran_integers(lambda i: 0 > i or 1 < i))) + + if valid_suffix is None: + suffix = None + elif valid_suffix: + suffix = str(draw(fortran_integers(lambda i: 1 <= i and i <= 99_999_999))) + else: + suffix = str(draw(fortran_integers(lambda i: 1 > i or i > 99_999_999))) + + designator = draw(mcnp_designators(valid_designator)) + + return ("dxc", suffix, designator, value) + + +@st.composite +def mcnp_parameter_fissionTurnOff(draw, valid_value: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(st.sampled_from([0, 1, 2]))) + else: + value = str(draw(fortran_integers(lambda i: i not in {0, 1, 2}))) + + return ("nonu", None, None, value) + + +@st.composite +def mcnp_parameter_detectorContribution(draw, valid_value: bool, valid_suffix: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_integers(lambda i: 0 <= i <= 1))) + else: + value = str(draw(fortran_integers(lambda i: 0 > i or 1 < i))) + + if valid_suffix is None: + suffix = None + elif valid_suffix: + suffix = str(draw(fortran_integers(lambda i: 1 <= i and i <= 99_999_999))) + else: + suffix = str(draw(fortran_integers(lambda i: 1 > i or i > 99_999_999))) + + return ("pd", suffix, None, value) + + +@st.composite +def mcnp_parameter_gasThermalTemperature(draw, valid_value: bool, valid_suffix: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_reals(lambda i: i >= 0))) + else: + value = str(draw(fortran_reals(lambda i: i < 0))) + + if valid_suffix is None: + suffix = None + elif valid_suffix: + suffix = str(draw(fortran_integers(lambda i: 1 <= i and i <= 99_999_999))) + else: + suffix = str(draw(fortran_integers(lambda i: 1 > i or i > 99_999_999))) + + return ("tmp", suffix, None, value) + + +@st.composite +def mcnp_parameter_universe(draw, valid_value: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_integers(lambda i: 1 <= i <= 99_999_999))) + else: + value = str(draw(fortran_integers(lambda i: 1 > i or i > 99_999_999))) + + return ("u", None, None, value) + + +@st.composite +def mcnp_parameter_coordinateTransformation(draw, valid_value: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_integers())) + else: + value = "a" + + return ("trcl", None, None, value) + + +@st.composite +def mcnp_parameter_lattice(draw, valid_value: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(st.sampled_from([1, 2]))) + else: + value = str(draw(fortran_integers(lambda i: i not in {1, 2}))) + + return ("lat", None, None, value) + + +@st.composite +def mcnp_parameter_fill(draw, valid_value: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_integers(lambda i: 0 <= i <= 99_999_999))) + else: + value = str(draw(fortran_integers(lambda i: 0 > i or i > 99_999_999))) + + return ("fill", None, None, value) + + +@st.composite +def mcnp_parameter_energyCutoff(draw, valid_value: bool, valid_designator: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_reals())) + else: + value = "a" + + designator = draw(mcnp_designators(valid_designator)) + + return ("elpt", None, designator, value) + + +@st.composite +def mcnp_parameter_cosy(draw, valid_value: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_integers(lambda i: i >= 0))) + else: + value = str(draw(fortran_integers(lambda i: i < 0))) + + return ("cosy", None, None, value) + + +@st.composite +def mcnp_parameter_bfield(draw, valid_value: bool): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(fortran_integers(lambda i: i >= 0))) + else: + value = str(draw(fortran_integers(lambda i: i < 0))) + + return ("bflcl", None, None, value) + + +@st.composite +def mcnp_parameter_uncolidedSecondaries( + draw, valid_value: bool, valid_designator: bool +): + if valid_value is None: + value = None + elif valid_value: + value = str(draw(st.sampled_from([0, 1]))) + else: + value = str(draw(fortran_integers(lambda i: i not in {0, 1}))) + + designator = draw(mcnp_designators(valid_designator)) + + return ("unc", None, designator, value) @st.composite diff --git a/tests/test_inp.py b/tests/test_inp.py index 6ea0519..14c26ae 100644 --- a/tests/test_inp.py +++ b/tests/test_inp.py @@ -10,14 +10,12 @@ from pymcnp.files.inp.cell import Cell from pymcnp.files.inp.surface import Surface from pymcnp.files._utils import errors +from pymcnp.files._utils import types import _strategies as _st -# HY_TRIALS = 100 # ~0:00:50 -# HY_TRIALS = 1000 # ~0:10:00 -# HY_TRIALS = 10000 # ~1:30:00 -HY_TRIALS = 1000 +HY_TRIALS = 7500 class TestCell: @@ -30,33 +28,62 @@ class TestfromMcnp: 'TestfromMcnp' """ - @hy.settings(max_examples=HY_TRIALS) - @hy.given(cell=_st.mcnp_cells(True, True, True, True)) + @hy.settings(max_examples=math.ceil(HY_TRIALS // 18)) + @hy.given(cell=_st.mcnp_cells(True, True, True, True, True)) def test_valid(self, cell): """ 'test_valid' """ - number, material, density, geometry = cell + number, material, density, geometry, parameters = cell + + for parameter in parameters: + keyword, suffix, designator, value = parameter + + parameter_str = keyword + + if suffix is not None: + parameter_str += suffix + + if designator is not None: + parameter_str += ":" + designator - if material != "0": - inp = Cell().from_mcnp(f"{number} {material} {density} {geometry}") - else: - inp = Cell().from_mcnp(f"{number} {material} {geometry}") + parameter_str += "=" + value - assert inp.number == int(number) - assert inp.id == int(number) - assert inp.material == int(material) - assert inp.density == (float(density) if int(material) != 0 else None) + if material != "0": + inp = Cell().from_mcnp( + f"{number} {material} {density} {geometry} {parameter_str}" + ) + else: + inp = Cell().from_mcnp( + f"{number} {material} {geometry} {parameter_str}" + ) + + assert inp.number == int(number) + assert inp.id == int(number) + assert inp.material == int(material) + assert inp.density == (float(density) if int(material) != 0 else None) + assert inp.parameters[0].keyword == Cell.CellParameter.CellKeyword( + keyword + ) + assert float(inp.parameters[0].value) == float(value) + + if suffix is not None: + assert inp.parameters[0].suffix == int(suffix) + + if designator is not None: + assert inp.parameters[0].designator[0] == types.Designator( + designator + ) @hy.settings(max_examples=HY_TRIALS) - @hy.given(cell=_st.mcnp_cells(False, True, True, True)) + @hy.given(cell=_st.mcnp_cells(False, True, True, True, True)) def test_invalid_number(self, cell): """ 'test_invalid_number' """ - number, material, density, geometry = cell + number, material, density, geometry, parameters = cell with pytest.raises(errors.MCNPSemanticError) as err: if material != "0": @@ -67,13 +94,13 @@ def test_invalid_number(self, cell): assert err.value.code == errors.MCNPSemanticCodes.INVALID_CELL_NUMBER @hy.settings(max_examples=HY_TRIALS) - @hy.given(cell=_st.mcnp_cells(True, False, True, True)) + @hy.given(cell=_st.mcnp_cells(True, False, True, True, True)) def test_invalid_material(self, cell): """ 'test_invalid_material' """ - number, material, density, geometry = cell + number, material, density, geometry, parameters = cell with pytest.raises(errors.MCNPSemanticError) as err: if material != "0": @@ -84,13 +111,13 @@ def test_invalid_material(self, cell): assert err.value.code == errors.MCNPSemanticCodes.INVALID_CELL_MATERIAL @hy.settings(max_examples=HY_TRIALS) - @hy.given(cell=_st.mcnp_cells(True, True, False, True)) + @hy.given(cell=_st.mcnp_cells(True, True, False, True, True)) def test_invalid_density(self, cell): """ 'test_invalid_density' """ - number, material, density, geometry = cell + number, material, density, geometry, parameters = cell # Asserting non-void material material = str(min(int(material) + 1, 99_999_999)) @@ -101,13 +128,13 @@ def test_invalid_density(self, cell): assert err.value.code == errors.MCNPSemanticCodes.INVALID_CELL_DENSITY @hy.settings(max_examples=HY_TRIALS) - @hy.given(cell=_st.mcnp_cells(True, True, True, False)) + @hy.given(cell=_st.mcnp_cells(True, True, True, False, True)) def test_invalid_geometry(self, cell): """ 'test_invalid_geometry' """ - number, material, density, geometry = cell + number, material, density, geometry, parameters = cell with pytest.raises(errors.MCNPSemanticError) as err: if material != "0": @@ -287,8 +314,6 @@ def test_valid(self, surfaces): 'test_valid' """ - file = open("text.txt", "a") - for surface in surfaces: number, transform, mnemonic, entries = surface @@ -341,7 +366,7 @@ def test_invalid_transformPeriodic(self, surfaces): @hy.given(surfaces=_st.mcnp_surfaces(True, True, False)) def test_invalid_mnemonic(self, surfaces): """ - 'test_invalid_number' + 'test_invalid_mnemonic' """ for surface in surfaces: