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.
Files changed (100) hide show
  1. {gitronics-0.3.2 → gitronics-0.4.0}/.github/workflows/publish.yml +0 -2
  2. {gitronics-0.3.2 → gitronics-0.4.0}/PKG-INFO +1 -1
  3. gitronics-0.4.0/src/gitronics/file_readers.py +175 -0
  4. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_compose_model.py +0 -1
  5. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_file_readers.py +88 -0
  6. gitronics-0.4.0/tests/test_resources/valid_project/data_cards/ssw_card.tally +3 -0
  7. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/volumetric_source.source +1 -1
  8. gitronics-0.4.0/tests/test_resources/valid_project/models/filler_model_repeat_surface.mcnp +33 -0
  9. gitronics-0.4.0/tests/test_resources/valid_project/models/filler_model_repeat_surface.metadata +2 -0
  10. gitronics-0.3.2/src/gitronics/file_readers.py +0 -133
  11. {gitronics-0.3.2 → gitronics-0.4.0}/.gitignore +0 -0
  12. {gitronics-0.3.2 → gitronics-0.4.0}/.python-version +0 -0
  13. {gitronics-0.3.2 → gitronics-0.4.0}/LICENSE +0 -0
  14. {gitronics-0.3.2 → gitronics-0.4.0}/README.md +0 -0
  15. {gitronics-0.3.2 → gitronics-0.4.0}/docs/source/_static/logo.png +0 -0
  16. {gitronics-0.3.2 → gitronics-0.4.0}/docs/source/conf.py +0 -0
  17. {gitronics-0.3.2 → gitronics-0.4.0}/docs/source/index.rst +0 -0
  18. {gitronics-0.3.2 → gitronics-0.4.0}/docs/source/requirements.txt +0 -0
  19. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/assembled/assembled.mcnp +0 -0
  20. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/assembled/assembled.metadata +0 -0
  21. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/build_model.py +0 -0
  22. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/configurations/small_override.yaml +0 -0
  23. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/configurations/valid_configuration.yaml +0 -0
  24. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/data_cards/fine_mesh.tally +0 -0
  25. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/data_cards/materials.mat +0 -0
  26. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/data_cards/my_transform.transform +0 -0
  27. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/data_cards/volumetric_source.source +0 -0
  28. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/envelope_structure.mcnp +0 -0
  29. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/envelope_structure.metadata +0 -0
  30. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_1.mcnp +0 -0
  31. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_1.metadata +0 -0
  32. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_2.mcnp +0 -0
  33. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_2.metadata +0 -0
  34. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_3.mcnp +0 -0
  35. {gitronics-0.3.2 → gitronics-0.4.0}/example_project/models/filler_model_3.metadata +0 -0
  36. {gitronics-0.3.2 → gitronics-0.4.0}/pyproject.toml +0 -0
  37. {gitronics-0.3.2 → gitronics-0.4.0}/readthedocs.yaml +0 -0
  38. {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/__init__.py +0 -0
  39. {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/compose_model.py +0 -0
  40. {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/file_discovery.py +0 -0
  41. {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/generate_model.py +0 -0
  42. {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/helpers.py +0 -0
  43. {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/project_checker.py +0 -0
  44. {gitronics-0.3.2 → gitronics-0.4.0}/src/gitronics/project_manager.py +0 -0
  45. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_file_discovery.py +0 -0
  46. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_generate_model.py +0 -0
  47. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_project_checker.py +0 -0
  48. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_project_manager.py +0 -0
  49. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/duplicated_filename_project/duplicated_name.mat +0 -0
  50. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/duplicated_filename_project/duplicated_name.mcnp +0 -0
  51. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/duplicated_filename_project/duplicated_name.metadata +0 -0
  52. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/expected_file_valid_configuration.mcnp +0 -0
  53. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/invalid_suffix_project/my_file.wrong +0 -0
  54. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/missing_metadata_project/my_file.mcnp +0 -0
  55. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/configurations/envelope_not_accounted.yaml +0 -0
  56. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/configurations/overrides_configuration.yaml +0 -0
  57. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/configurations/small_config.yaml +0 -0
  58. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/configurations/small_override.yaml +0 -0
  59. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/configurations/valid_configuration.yaml +0 -0
  60. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/fine_mesh.tally +0 -0
  61. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/materials.mat +0 -0
  62. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/my_source.source +0 -0
  63. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/data_cards/my_transform.transform +0 -0
  64. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/envelope_structure.mcnp +0 -0
  65. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/envelope_structure.metadata +0 -0
  66. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_1.mcnp +0 -0
  67. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_1.metadata +0 -0
  68. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_2.mcnp +0 -0
  69. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_2.metadata +0 -0
  70. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_3.mcnp +0 -0
  71. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/filler_model_3.metadata +0 -0
  72. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/my_envelope_structure.mcnp +0 -0
  73. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project/models/my_envelope_structure.metadata +0 -0
  74. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/data_cards/fine_mesh.tally +0 -0
  75. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/data_cards/materials.mat +0 -0
  76. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/data_cards/my_transform.transform +0 -0
  77. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/data_cards/volumetric_source.source +0 -0
  78. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_env_struct.yaml +0 -0
  79. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_filler_path.yaml +0 -0
  80. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_materials_path.yaml +0 -0
  81. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_source_path.yaml +0 -0
  82. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_tallies_path.yaml +0 -0
  83. {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
  84. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/missing_transforms_path.yaml +0 -0
  85. {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
  86. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/invalid_configurations/wrong_envelope_name.yaml +0 -0
  87. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/envelope_structure.mcnp +0 -0
  88. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/envelope_structure.metadata +0 -0
  89. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_1.mcnp +0 -0
  90. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_1.metadata +0 -0
  91. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_2.mcnp +0 -0
  92. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_2.metadata +0 -0
  93. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_3.mcnp +0 -0
  94. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/valid_project _with_invalid_configurations/models/filler_model_3.metadata +0 -0
  95. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/wrong_files/only_cells_block.mcnp +0 -0
  96. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/wrong_files/wrong_cells_block.mcnp +0 -0
  97. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/wrong_files/wrong_data_card.mat +0 -0
  98. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/wrong_files/wrong_suffix.wrong +0 -0
  99. {gitronics-0.3.2 → gitronics-0.4.0}/tests/test_resources/wrong_files/wrong_surfaces_block.mcnp +0 -0
  100. {gitronics-0.3.2 → gitronics-0.4.0}/uv.lock +0 -0
@@ -2,8 +2,6 @@ name: Publish Python Package
2
2
 
3
3
  on:
4
4
  push:
5
- branches:
6
- - main
7
5
  tags:
8
6
  - 'v*.*.*'
9
7
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitronics
3
- Version: 0.3.2
3
+ Version: 0.4.0
4
4
  Summary: Automatically build an MCNP from a set of files.
5
5
  Author-email: Alvaro Cubi <cubiric@hotmail.com>
6
6
  License-File: LICENSE
@@ -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
@@ -1,5 +1,4 @@
1
1
  # ruff: noqa: E501
2
- import logging
3
2
  from pathlib import Path
4
3
 
5
4
  from gitronics.compose_model import compose_model
@@ -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,3 @@
1
+ C This will be considered a tally card even tho it doesnt have a first ID of the
2
+ C form FXX4: n
3
+ SSW 4001 4002 4003 4004
@@ -4,4 +4,4 @@ sdef sur 398 nrm=-1 dir=d1 wgt=132732289.6141
4
4
  sb1 -21 2
5
5
  lost 1000
6
6
  prdmp j 1e7
7
- nps 1e9
7
+ nps 1e9
@@ -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
@@ -0,0 +1,2 @@
1
+ transformations:
2
+ my_envelope_name_1: "*(10)"
@@ -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