gitronics 0.3.2__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gitronics-0.3.2 → gitronics-0.4.0}/.github/workflows/publish.yml +0 -2
- {gitronics-0.3.2 → gitronics-0.4.0}/PKG-INFO +1 -1
- gitronics-0.4.0/src/gitronics/file_readers.py +175 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_compose_model.py +0 -1
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_file_readers.py +88 -0
- gitronics-0.4.0/tests/test_resources/valid_project/data_cards/ssw_card.tally +3 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/volumetric_source.source +1 -1
- gitronics-0.4.0/tests/test_resources/valid_project/models/filler_model_repeat_surface.mcnp +33 -0
- gitronics-0.4.0/tests/test_resources/valid_project/models/filler_model_repeat_surface.metadata +2 -0
- gitronics-0.3.2/src/gitronics/file_readers.py +0 -133
- {gitronics-0.3.2 → gitronics-0.4.0}/.gitignore +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/.python-version +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/LICENSE +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/README.md +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/docs/source/_static/logo.png +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/docs/source/conf.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/docs/source/index.rst +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/docs/source/requirements.txt +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/assembled/assembled.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/assembled/assembled.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/build_model.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/configurations/small_override.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/configurations/valid_configuration.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/data_cards/fine_mesh.tally +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/data_cards/materials.mat +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/data_cards/my_transform.transform +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/data_cards/volumetric_source.source +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/envelope_structure.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/envelope_structure.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_1.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_1.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_2.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_2.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_3.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_3.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/pyproject.toml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/readthedocs.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/__init__.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/compose_model.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/file_discovery.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/generate_model.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/helpers.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/project_checker.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/project_manager.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_file_discovery.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_generate_model.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_project_checker.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_project_manager.py +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/duplicated_filename_project/duplicated_name.mat +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/duplicated_filename_project/duplicated_name.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/duplicated_filename_project/duplicated_name.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/expected_file_valid_configuration.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/invalid_suffix_project/my_file.wrong +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/missing_metadata_project/my_file.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/configurations/envelope_not_accounted.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/configurations/overrides_configuration.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/configurations/small_config.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/configurations/small_override.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/configurations/valid_configuration.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/fine_mesh.tally +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/materials.mat +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/my_source.source +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/my_transform.transform +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/envelope_structure.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/envelope_structure.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_1.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_1.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_2.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_2.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_3.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_3.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/my_envelope_structure.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/my_envelope_structure.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/data_cards/fine_mesh.tally +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/data_cards/materials.mat +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/data_cards/my_transform.transform +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/data_cards/volumetric_source.source +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_env_struct.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_filler_path.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_materials_path.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_source_path.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_tallies_path.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_tr_for_filler.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_transforms_path.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/wrong_env_struct_path.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/wrong_envelope_name.yaml +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/envelope_structure.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/envelope_structure.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_1.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_1.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_2.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_2.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_3.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_3.metadata +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/wrong_files/only_cells_block.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/wrong_files/wrong_cells_block.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/wrong_files/wrong_data_card.mat +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/wrong_files/wrong_suffix.wrong +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/wrong_files/wrong_surfaces_block.mcnp +0 -0
- {gitronics-0.3.2 → gitronics-0.4.0}/uv.lock +0 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""
|
|
2
|
+
These functions read and parse the individual files that will make up the composed MCNP
|
|
3
|
+
model. The result is an instance of ParsedBlocks which holds all the sections of the
|
|
4
|
+
final file.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import re
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class _FirstIdAndText:
|
|
15
|
+
first_id: int
|
|
16
|
+
text: str
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class ParsedBlocks:
|
|
21
|
+
"""Contains all the sections of the MCNP input model."""
|
|
22
|
+
|
|
23
|
+
cells: dict[int, str]
|
|
24
|
+
surfaces: dict[int, str]
|
|
25
|
+
tallies: dict[int, str]
|
|
26
|
+
materials: dict[int, str]
|
|
27
|
+
transforms: dict[int, str]
|
|
28
|
+
source: str
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def empty_instance(cls) -> "ParsedBlocks":
|
|
32
|
+
"""Returns an empty instance of ParsedBlocks."""
|
|
33
|
+
return ParsedBlocks(
|
|
34
|
+
cells={}, surfaces={}, tallies={}, materials={}, transforms={}, source=""
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def add_cells(self, block: _FirstIdAndText) -> None:
|
|
38
|
+
if block.first_id in self.cells:
|
|
39
|
+
raise ValueError(
|
|
40
|
+
"Overwriting cells block with the same first cell ID:"
|
|
41
|
+
f" {block.first_id}"
|
|
42
|
+
)
|
|
43
|
+
self.cells[block.first_id] = block.text
|
|
44
|
+
|
|
45
|
+
def add_surfaces(self, block: _FirstIdAndText) -> None:
|
|
46
|
+
if block.first_id in self.surfaces:
|
|
47
|
+
raise ValueError(
|
|
48
|
+
"Overwriting surfaces block with the same first surface ID:"
|
|
49
|
+
f" {block.first_id}"
|
|
50
|
+
)
|
|
51
|
+
self.surfaces[block.first_id] = block.text
|
|
52
|
+
|
|
53
|
+
def add_tallies(self, block: _FirstIdAndText) -> None:
|
|
54
|
+
# Tally files are allowed to not have an ID (e.g. a SSW card)
|
|
55
|
+
if block.first_id == 0:
|
|
56
|
+
if 0 in self.tallies:
|
|
57
|
+
self.tallies[0] += block.text
|
|
58
|
+
else:
|
|
59
|
+
self.tallies[0] = block.text
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
if block.first_id in self.tallies:
|
|
63
|
+
raise ValueError(
|
|
64
|
+
"Overwriting tally block with the same first tally ID:"
|
|
65
|
+
f" {block.first_id}"
|
|
66
|
+
)
|
|
67
|
+
self.tallies[block.first_id] = block.text
|
|
68
|
+
|
|
69
|
+
def add_materials(self, block: _FirstIdAndText) -> None:
|
|
70
|
+
if block.first_id in self.materials:
|
|
71
|
+
raise ValueError(
|
|
72
|
+
"Overwriting material block with the same first material ID:"
|
|
73
|
+
f" {block.first_id}"
|
|
74
|
+
)
|
|
75
|
+
self.materials[block.first_id] = block.text
|
|
76
|
+
|
|
77
|
+
def add_transforms(self, block: _FirstIdAndText) -> None:
|
|
78
|
+
if block.first_id in self.transforms:
|
|
79
|
+
raise ValueError(
|
|
80
|
+
"Overwriting transform block with the same first transform ID:"
|
|
81
|
+
f" {block.first_id}"
|
|
82
|
+
)
|
|
83
|
+
self.transforms[block.first_id] = block.text
|
|
84
|
+
|
|
85
|
+
def add_source(self, text: str) -> None:
|
|
86
|
+
if self.source:
|
|
87
|
+
raise ValueError("Overwriting source block which is already set.")
|
|
88
|
+
self.source = text
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
BLANK_LINE = re.compile(r"^\s*\n", flags=re.MULTILINE)
|
|
92
|
+
MCNP_FILE_NEEDED_BLOCKS = 2
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _read_mcnp(file: Path) -> tuple[_FirstIdAndText, _FirstIdAndText]:
|
|
96
|
+
with open(file, encoding="utf-8") as infile:
|
|
97
|
+
blocks = BLANK_LINE.split(infile.read())
|
|
98
|
+
|
|
99
|
+
if len(blocks) < MCNP_FILE_NEEDED_BLOCKS:
|
|
100
|
+
raise ValueError(
|
|
101
|
+
f"File {file} does not contain the two blocks: cells and surfaces."
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
cell_block, surfaces_block = blocks[:2]
|
|
105
|
+
|
|
106
|
+
match_first_cell_id = re.search(r"^\d+", cell_block, flags=re.MULTILINE)
|
|
107
|
+
if not match_first_cell_id:
|
|
108
|
+
raise ValueError(f"Could not parse the first cell ID value in {file}.")
|
|
109
|
+
first_cell_id = int(match_first_cell_id.group())
|
|
110
|
+
|
|
111
|
+
match_first_surface_id = re.search(r"^\*?\d+", surfaces_block, flags=re.MULTILINE)
|
|
112
|
+
if not match_first_surface_id:
|
|
113
|
+
raise ValueError(f"Could not parse the first surface ID value in {file}.")
|
|
114
|
+
first_surface_id = int(match_first_surface_id.group())
|
|
115
|
+
|
|
116
|
+
return _FirstIdAndText(first_cell_id, cell_block), _FirstIdAndText(
|
|
117
|
+
first_surface_id, surfaces_block
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _read_first_block(file: Path) -> _FirstIdAndText:
|
|
122
|
+
with open(file, encoding="utf-8") as infile:
|
|
123
|
+
text = BLANK_LINE.split(infile.read())[0]
|
|
124
|
+
if text[-1] != "\n":
|
|
125
|
+
text += "\n"
|
|
126
|
+
|
|
127
|
+
match_first_id = re.search(r"^\*?[a-zA-Z]*(\d+)", text, flags=re.MULTILINE)
|
|
128
|
+
if not match_first_id:
|
|
129
|
+
raise ValueError(f"Could not parse the first ID value in file {file}.")
|
|
130
|
+
first_id = int(match_first_id.group(1))
|
|
131
|
+
|
|
132
|
+
return _FirstIdAndText(first_id, text)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _read_first_block_without_id(file: Path) -> str:
|
|
136
|
+
with open(file, encoding="utf-8") as infile:
|
|
137
|
+
text = BLANK_LINE.split(infile.read())[0]
|
|
138
|
+
if text[-1] != "\n":
|
|
139
|
+
text += "\n"
|
|
140
|
+
return text
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def read_files(files: list[Path]) -> ParsedBlocks:
|
|
144
|
+
"""Reads the files and returns the parsed blocks."""
|
|
145
|
+
parsed_blocks = ParsedBlocks.empty_instance()
|
|
146
|
+
|
|
147
|
+
for file in files:
|
|
148
|
+
logging.info("Reading file: %s", file)
|
|
149
|
+
suffix = file.suffix[1:] # remove the dot like in ".mcnp"
|
|
150
|
+
|
|
151
|
+
match suffix:
|
|
152
|
+
case "mcnp":
|
|
153
|
+
cells_block, surfaces_block = _read_mcnp(file)
|
|
154
|
+
parsed_blocks.add_cells(cells_block)
|
|
155
|
+
parsed_blocks.add_surfaces(surfaces_block)
|
|
156
|
+
case "tally":
|
|
157
|
+
try:
|
|
158
|
+
block = _read_first_block(file)
|
|
159
|
+
except ValueError:
|
|
160
|
+
block = _FirstIdAndText(0, _read_first_block_without_id(file))
|
|
161
|
+
|
|
162
|
+
parsed_blocks.add_tallies(block)
|
|
163
|
+
case "mat":
|
|
164
|
+
block = _read_first_block(file)
|
|
165
|
+
parsed_blocks.add_materials(block)
|
|
166
|
+
case "transform":
|
|
167
|
+
block = _read_first_block(file)
|
|
168
|
+
parsed_blocks.add_transforms(block)
|
|
169
|
+
case "source":
|
|
170
|
+
text = _read_first_block_without_id(file)
|
|
171
|
+
parsed_blocks.add_source(text)
|
|
172
|
+
case _:
|
|
173
|
+
raise ValueError(f"Unknown file suffix for: {file}")
|
|
174
|
+
|
|
175
|
+
return parsed_blocks
|
|
@@ -70,6 +70,94 @@ def test_read_file_wrong_suffix():
|
|
|
70
70
|
read_files([WRONG_FILES_PATH / "wrong_suffix.wrong"])
|
|
71
71
|
|
|
72
72
|
|
|
73
|
+
def test_read_tallies_without_id():
|
|
74
|
+
parsed_blocks = read_files(
|
|
75
|
+
[
|
|
76
|
+
VALID_PROJECT_PATH / "data_cards" / "ssw_card.tally",
|
|
77
|
+
VALID_PROJECT_PATH / "data_cards" / "ssw_card.tally",
|
|
78
|
+
]
|
|
79
|
+
)
|
|
80
|
+
assert "SSW" in parsed_blocks.tallies[0]
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def test_read_cells_repeated_first_id():
|
|
84
|
+
with pytest.raises(
|
|
85
|
+
ValueError,
|
|
86
|
+
match="Overwriting cells block with the same first cell ID: 1",
|
|
87
|
+
):
|
|
88
|
+
read_files(
|
|
89
|
+
[
|
|
90
|
+
VALID_PROJECT_PATH / "models" / "envelope_structure.mcnp",
|
|
91
|
+
VALID_PROJECT_PATH / "models" / "envelope_structure.mcnp",
|
|
92
|
+
]
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_read_surfaces_repeated_first_id():
|
|
97
|
+
with pytest.raises(
|
|
98
|
+
ValueError,
|
|
99
|
+
match="Overwriting surfaces block with the same first surface ID: 10",
|
|
100
|
+
):
|
|
101
|
+
read_files(
|
|
102
|
+
[
|
|
103
|
+
VALID_PROJECT_PATH / "models" / "filler_model_1.mcnp",
|
|
104
|
+
VALID_PROJECT_PATH / "models" / "filler_model_repeat_surface.mcnp",
|
|
105
|
+
]
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def test_read_tallies_repeated_first_id():
|
|
110
|
+
with pytest.raises(
|
|
111
|
+
ValueError,
|
|
112
|
+
match="Overwriting tally block with the same first tally ID: 24",
|
|
113
|
+
):
|
|
114
|
+
read_files(
|
|
115
|
+
[
|
|
116
|
+
VALID_PROJECT_PATH / "data_cards" / "fine_mesh.tally",
|
|
117
|
+
VALID_PROJECT_PATH / "data_cards" / "fine_mesh.tally",
|
|
118
|
+
]
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def test_read_materials_repeated_first_id():
|
|
123
|
+
with pytest.raises(
|
|
124
|
+
ValueError,
|
|
125
|
+
match="Overwriting material block with the same first material ID: 14",
|
|
126
|
+
):
|
|
127
|
+
read_files(
|
|
128
|
+
[
|
|
129
|
+
VALID_PROJECT_PATH / "data_cards" / "materials.mat",
|
|
130
|
+
VALID_PROJECT_PATH / "data_cards" / "materials.mat",
|
|
131
|
+
]
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def test_read_transforms_repeated_first_id():
|
|
136
|
+
with pytest.raises(
|
|
137
|
+
ValueError,
|
|
138
|
+
match="Overwriting transform block with the same first transform ID: 1",
|
|
139
|
+
):
|
|
140
|
+
read_files(
|
|
141
|
+
[
|
|
142
|
+
VALID_PROJECT_PATH / "data_cards" / "my_transform.transform",
|
|
143
|
+
VALID_PROJECT_PATH / "data_cards" / "my_transform.transform",
|
|
144
|
+
]
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def test_read_source_repeated():
|
|
149
|
+
with pytest.raises(
|
|
150
|
+
ValueError,
|
|
151
|
+
match="Overwriting source block which is already set.",
|
|
152
|
+
):
|
|
153
|
+
read_files(
|
|
154
|
+
[
|
|
155
|
+
VALID_PROJECT_PATH / "data_cards" / "volumetric_source.source",
|
|
156
|
+
VALID_PROJECT_PATH / "data_cards" / "volumetric_source.source",
|
|
157
|
+
]
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
73
161
|
MAIN_INPUT_CELLS = """Title of the MCNP model
|
|
74
162
|
C
|
|
75
163
|
C
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
C Filler model 1
|
|
2
|
+
9910 14 -7.89 10 -20 40 -30
|
|
3
|
+
imp:n=1.0 imp:p=1.0 u=121
|
|
4
|
+
9920 0 10 -20 80 730 -70 -60 -50
|
|
5
|
+
imp:n=1.0 imp:p=1.0 u=121
|
|
6
|
+
|
|
7
|
+
C Surfaces model 1
|
|
8
|
+
10 PZ -1.4030000e+02
|
|
9
|
+
20 PZ 4.6300000e+01
|
|
10
|
+
30 CZ 160.700000
|
|
11
|
+
40 CZ 144.900000
|
|
12
|
+
|
|
13
|
+
C Data cards that will not be read by the global model
|
|
14
|
+
m14 1001.31c 2.379E-02 $ H-1
|
|
15
|
+
5010.31c 2.350E-04 $ B10
|
|
16
|
+
5011.31c 9.469E-04 $ B11
|
|
17
|
+
8016.31c 4.276E-02 $ O
|
|
18
|
+
11023.31c 2.068E-04 $ Na
|
|
19
|
+
c 12000.31c 3.768E-05 $ Mg
|
|
20
|
+
12024.31c 2.976E-05 $ Mg-24 78.99%
|
|
21
|
+
12025.31c 3.768E-06 $ Mg-25 10.0 %
|
|
22
|
+
12026.31c 4.149E-06 $ Mg-26 11.01%
|
|
23
|
+
13027.31c 6.034E-04 $ Al
|
|
24
|
+
c 14000.31c 1.239E-02 $ Si
|
|
25
|
+
14028.31c 1.143E-02 $ Si-28 92.23%
|
|
26
|
+
14029.31c 5.786E-04 $ Si-29 4.67%
|
|
27
|
+
c
|
|
28
|
+
mode n
|
|
29
|
+
sdef sur 398 nrm=-1 dir=d1 wgt=132732289.6141
|
|
30
|
+
sb1 -21 2
|
|
31
|
+
lost 1000
|
|
32
|
+
prdmp j 1e7
|
|
33
|
+
nps 1e9
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
These functions read and parse the individual files that will make up the composed MCNP
|
|
3
|
-
model. The result is an instance of ParsedBlocks which holds all the sections of the
|
|
4
|
-
final file.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import logging
|
|
8
|
-
import re
|
|
9
|
-
from dataclasses import dataclass
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@dataclass
|
|
14
|
-
class ParsedBlocks:
|
|
15
|
-
"""Contains all the sections of the MCNP input model."""
|
|
16
|
-
|
|
17
|
-
cells: dict[int, str]
|
|
18
|
-
surfaces: dict[int, str]
|
|
19
|
-
tallies: dict[int, str]
|
|
20
|
-
materials: dict[int, str]
|
|
21
|
-
transforms: dict[int, str]
|
|
22
|
-
source: str
|
|
23
|
-
|
|
24
|
-
@classmethod
|
|
25
|
-
def empty_instance(cls) -> "ParsedBlocks":
|
|
26
|
-
"""Returns an empty instance of ParsedBlocks."""
|
|
27
|
-
return ParsedBlocks(
|
|
28
|
-
cells={}, surfaces={}, tallies={}, materials={}, transforms={}, source=""
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
def add_file(self, file: Path) -> None:
|
|
32
|
-
"""Adds the file if the suffix is recognized."""
|
|
33
|
-
suffix = file.suffix[1:] # remove the dot like in ".mcnp"
|
|
34
|
-
|
|
35
|
-
match suffix:
|
|
36
|
-
case "mcnp":
|
|
37
|
-
self._add_mcnp_file(file)
|
|
38
|
-
|
|
39
|
-
case "tally":
|
|
40
|
-
self._add_tally_file(file)
|
|
41
|
-
|
|
42
|
-
case "mat":
|
|
43
|
-
self._add_material_file(file)
|
|
44
|
-
|
|
45
|
-
case "transform":
|
|
46
|
-
self._add_transform_file(file)
|
|
47
|
-
|
|
48
|
-
case "source":
|
|
49
|
-
self._add_source_file(file)
|
|
50
|
-
|
|
51
|
-
case _:
|
|
52
|
-
raise ValueError(f"Unknown file suffix for: {file}")
|
|
53
|
-
|
|
54
|
-
def _add_mcnp_file(self, file: Path) -> None:
|
|
55
|
-
cells_block, surfaces_block = _read_mcnp(file)
|
|
56
|
-
self.cells[cells_block.first_id] = cells_block.text
|
|
57
|
-
self.surfaces[surfaces_block.first_id] = surfaces_block.text
|
|
58
|
-
|
|
59
|
-
def _add_tally_file(self, file: Path) -> None:
|
|
60
|
-
block = _read_first_block(file)
|
|
61
|
-
self.tallies[block.first_id] = block.text
|
|
62
|
-
|
|
63
|
-
def _add_material_file(self, file: Path) -> None:
|
|
64
|
-
block = _read_first_block(file)
|
|
65
|
-
self.materials[block.first_id] = block.text
|
|
66
|
-
|
|
67
|
-
def _add_transform_file(self, file: Path) -> None:
|
|
68
|
-
block = _read_first_block(file)
|
|
69
|
-
self.transforms[block.first_id] = block.text
|
|
70
|
-
|
|
71
|
-
def _add_source_file(self, file: Path) -> None:
|
|
72
|
-
self.source = _read_first_block(file).text
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def read_files(files: list[Path]) -> ParsedBlocks:
|
|
76
|
-
"""Reads the files and returns the parsed blocks."""
|
|
77
|
-
parsed_blocks = ParsedBlocks.empty_instance()
|
|
78
|
-
|
|
79
|
-
for file in files:
|
|
80
|
-
logging.info("Reading file: %s", file)
|
|
81
|
-
parsed_blocks.add_file(file)
|
|
82
|
-
|
|
83
|
-
return parsed_blocks
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
@dataclass
|
|
87
|
-
class _FirstIdAndText:
|
|
88
|
-
first_id: int
|
|
89
|
-
text: str
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
BLANK_LINE = re.compile(r"^\s*\n", flags=re.MULTILINE)
|
|
93
|
-
MCNP_FILE_NEEDED_BLOCKS = 2
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
def _read_mcnp(file: Path) -> tuple[_FirstIdAndText, _FirstIdAndText]:
|
|
97
|
-
with open(file, encoding="utf-8") as infile:
|
|
98
|
-
blocks = BLANK_LINE.split(infile.read())
|
|
99
|
-
|
|
100
|
-
if len(blocks) < MCNP_FILE_NEEDED_BLOCKS:
|
|
101
|
-
raise ValueError(
|
|
102
|
-
f"File {file} does not contain the two blocks: cells and surfaces."
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
cells, surfaces = blocks[:2]
|
|
106
|
-
|
|
107
|
-
match_first_cell_id = re.search(r"^\d+", cells, flags=re.MULTILINE)
|
|
108
|
-
if not match_first_cell_id:
|
|
109
|
-
raise ValueError(f"Could not parse the first cell ID value in {file}.")
|
|
110
|
-
first_cell_id = int(match_first_cell_id.group())
|
|
111
|
-
|
|
112
|
-
match_first_surface_id = re.search(r"^\*?\d+", surfaces, flags=re.MULTILINE)
|
|
113
|
-
if not match_first_surface_id:
|
|
114
|
-
raise ValueError(f"Could not parse the first surface ID value in {file}.")
|
|
115
|
-
first_surface_id = int(match_first_surface_id.group())
|
|
116
|
-
|
|
117
|
-
return _FirstIdAndText(first_cell_id, cells), _FirstIdAndText(
|
|
118
|
-
first_surface_id, surfaces
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def _read_first_block(file: Path) -> _FirstIdAndText:
|
|
123
|
-
with open(file, encoding="utf-8") as infile:
|
|
124
|
-
text = BLANK_LINE.split(infile.read())[0]
|
|
125
|
-
if text[-1] != "\n":
|
|
126
|
-
text += "\n"
|
|
127
|
-
|
|
128
|
-
match_first_id = re.search(r"^\*?[a-zA-Z]*(\d+)", text, flags=re.MULTILINE)
|
|
129
|
-
if not match_first_id:
|
|
130
|
-
raise ValueError(f"Could not parse the first ID value in file {file}.")
|
|
131
|
-
first_id = int(match_first_id.group(1))
|
|
132
|
-
|
|
133
|
-
return _FirstIdAndText(first_id, text)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/expected_file_valid_configuration.mcnp
RENAMED
|
File without changes
|
{gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/invalid_suffix_project/my_file.wrong
RENAMED
|
File without changes
|
{gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/missing_metadata_project/my_file.mcnp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/fine_mesh.tally
RENAMED
|
File without changes
|
{gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/materials.mat
RENAMED
|
File without changes
|
{gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/my_source.source
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_1.mcnp
RENAMED
|
File without changes
|
|
File without changes
|
{gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_2.mcnp
RENAMED
|
File without changes
|
|
File without changes
|
{gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_3.mcnp
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/wrong_files/wrong_surfaces_block.mcnp
RENAMED
|
File without changes
|
|
File without changes
|