pyvale 2025.7.2__cp311-cp311-musllinux_1_2_aarch64.whl → 2025.8.1__cp311-cp311-musllinux_1_2_aarch64.whl

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.

Potentially problematic release.


This version of pyvale might be problematic. Click here for more details.

Files changed (177) hide show
  1. pyvale/__init__.py +12 -92
  2. pyvale/blender/__init__.py +23 -0
  3. pyvale/{pyvaleexceptions.py → blender/blenderexceptions.py} +0 -3
  4. pyvale/{blenderlightdata.py → blender/blenderlightdata.py} +3 -3
  5. pyvale/{blendermaterialdata.py → blender/blendermaterialdata.py} +1 -1
  6. pyvale/{blenderrenderdata.py → blender/blenderrenderdata.py} +5 -3
  7. pyvale/{blenderscene.py → blender/blenderscene.py} +33 -30
  8. pyvale/{blendertools.py → blender/blendertools.py} +14 -10
  9. pyvale/dataset/__init__.py +7 -0
  10. pyvale/dataset/dataset.py +443 -0
  11. pyvale/dic/__init__.py +20 -0
  12. pyvale/{dic2d.py → dic/dic2d.py} +31 -36
  13. pyvale/dic/dic2dconv.py +6 -0
  14. pyvale/{dic2dcpp.cpython-311-aarch64-linux-musl.so → dic/dic2dcpp.cpython-311-aarch64-linux-musl.so} +0 -0
  15. pyvale/{dicdataimport.py → dic/dicdataimport.py} +8 -8
  16. pyvale/{dicregionofinterest.py → dic/dicregionofinterest.py} +1 -1
  17. pyvale/{dicresults.py → dic/dicresults.py} +1 -1
  18. pyvale/{dicstrain.py → dic/dicstrain.py} +9 -9
  19. pyvale/examples/basics/{ex1_1_basicscalars_therm2d.py → ex1a_basicscalars_therm2d.py} +12 -9
  20. pyvale/examples/basics/{ex1_2_sensormodel_therm2d.py → ex1b_sensormodel_therm2d.py} +17 -14
  21. pyvale/examples/basics/{ex1_3_customsens_therm3d.py → ex1c_customsens_therm3d.py} +27 -24
  22. pyvale/examples/basics/{ex1_4_basicerrors_therm3d.py → ex1d_basicerrors_therm3d.py} +32 -29
  23. pyvale/examples/basics/{ex1_5_fielderrs_therm3d.py → ex1e_fielderrs_therm3d.py} +19 -15
  24. pyvale/examples/basics/{ex1_6_caliberrs_therm2d.py → ex1f_caliberrs_therm2d.py} +20 -16
  25. pyvale/examples/basics/{ex1_7_spatavg_therm2d.py → ex1g_spatavg_therm2d.py} +19 -16
  26. pyvale/examples/basics/{ex2_1_basicvectors_disp2d.py → ex2a_basicvectors_disp2d.py} +13 -10
  27. pyvale/examples/basics/{ex2_2_vectorsens_disp2d.py → ex2b_vectorsens_disp2d.py} +19 -15
  28. pyvale/examples/basics/{ex2_3_sensangle_disp2d.py → ex2c_sensangle_disp2d.py} +21 -18
  29. pyvale/examples/basics/{ex2_4_chainfielderrs_disp2d.py → ex2d_chainfielderrs_disp2d.py} +31 -29
  30. pyvale/examples/basics/{ex2_5_vectorfields3d_disp3d.py → ex2e_vectorfields3d_disp3d.py} +21 -18
  31. pyvale/examples/basics/{ex3_1_basictensors_strain2d.py → ex3a_basictensors_strain2d.py} +16 -14
  32. pyvale/examples/basics/{ex3_2_tensorsens2d_strain2d.py → ex3b_tensorsens2d_strain2d.py} +17 -14
  33. pyvale/examples/basics/{ex3_3_tensorsens3d_strain3d.py → ex3c_tensorsens3d_strain3d.py} +25 -22
  34. pyvale/examples/basics/{ex4_1_expsim2d_thermmech2d.py → ex4a_expsim2d_thermmech2d.py} +17 -14
  35. pyvale/examples/basics/{ex4_2_expsim3d_thermmech3d.py → ex4b_expsim3d_thermmech3d.py} +37 -34
  36. pyvale/examples/basics/ex5_nomesh.py +24 -0
  37. pyvale/examples/dic/ex1_2_blenderdeformed.py +174 -0
  38. pyvale/examples/dic/ex1_region_of_interest.py +6 -3
  39. pyvale/examples/dic/ex2_plate_with_hole.py +21 -18
  40. pyvale/examples/dic/ex3_plate_with_hole_strain.py +8 -6
  41. pyvale/examples/dic/ex4_dic_blender.py +17 -15
  42. pyvale/examples/dic/ex5_dic_challenge.py +19 -14
  43. pyvale/examples/genanalyticdata/ex1_1_scalarvisualisation.py +16 -10
  44. pyvale/examples/genanalyticdata/ex1_2_scalarcasebuild.py +3 -3
  45. pyvale/examples/genanalyticdata/ex2_1_analyticsensors.py +29 -23
  46. pyvale/examples/genanalyticdata/ex2_2_analyticsensors_nomesh.py +67 -0
  47. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +12 -9
  48. pyvale/examples/mooseherder/ex0_create_moose_config.py +65 -0
  49. pyvale/examples/mooseherder/ex1a_modify_moose_input.py +71 -0
  50. pyvale/examples/mooseherder/ex1b_modify_gmsh_input.py +69 -0
  51. pyvale/examples/mooseherder/ex2a_run_moose_once.py +80 -0
  52. pyvale/examples/mooseherder/ex2b_run_gmsh_once.py +64 -0
  53. pyvale/examples/mooseherder/ex2c_run_both_once.py +114 -0
  54. pyvale/examples/mooseherder/ex3_run_moose_seq_para.py +157 -0
  55. pyvale/examples/mooseherder/ex4_run_gmsh-moose_seq_para.py +176 -0
  56. pyvale/examples/mooseherder/ex5_run_moose_paramulti.py +136 -0
  57. pyvale/examples/mooseherder/ex6_read_moose_exodus.py +163 -0
  58. pyvale/examples/mooseherder/ex7a_read_moose_herd_results.py +153 -0
  59. pyvale/examples/mooseherder/ex7b_read_multi_herd_results.py +116 -0
  60. pyvale/examples/mooseherder/ex7c_read_multi_gmshmoose_results.py +127 -0
  61. pyvale/examples/mooseherder/ex7d_readconfig_multi_gmshmoose_results.py +143 -0
  62. pyvale/examples/mooseherder/ex8_read_existing_sweep_output.py +72 -0
  63. pyvale/examples/renderblender/ex1_1_blenderscene.py +24 -20
  64. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +22 -18
  65. pyvale/examples/renderblender/ex2_1_stereoscene.py +36 -29
  66. pyvale/examples/renderblender/ex2_2_stereodeformed.py +26 -20
  67. pyvale/examples/renderblender/ex3_1_blendercalibration.py +24 -17
  68. pyvale/examples/renderrasterisation/ex_rastenp.py +14 -12
  69. pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +14 -15
  70. pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +13 -11
  71. pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +13 -11
  72. pyvale/mooseherder/__init__.py +32 -0
  73. pyvale/mooseherder/directorymanager.py +416 -0
  74. pyvale/mooseherder/exodusreader.py +763 -0
  75. pyvale/mooseherder/gmshrunner.py +163 -0
  76. pyvale/mooseherder/inputmodifier.py +236 -0
  77. pyvale/mooseherder/mooseconfig.py +226 -0
  78. pyvale/mooseherder/mooseherd.py +527 -0
  79. pyvale/mooseherder/mooserunner.py +303 -0
  80. pyvale/mooseherder/outputreader.py +22 -0
  81. pyvale/mooseherder/simdata.py +92 -0
  82. pyvale/mooseherder/simrunner.py +31 -0
  83. pyvale/mooseherder/sweepreader.py +356 -0
  84. pyvale/mooseherder/sweeptools.py +76 -0
  85. pyvale/sensorsim/__init__.py +82 -0
  86. pyvale/{camera.py → sensorsim/camera.py} +7 -7
  87. pyvale/{camerasensor.py → sensorsim/camerasensor.py} +7 -7
  88. pyvale/{camerastereo.py → sensorsim/camerastereo.py} +2 -2
  89. pyvale/{cameratools.py → sensorsim/cameratools.py} +4 -4
  90. pyvale/{cython → sensorsim/cython}/rastercyth.c +596 -596
  91. pyvale/sensorsim/cython/rastercyth.cpython-311-aarch64-linux-musl.so +0 -0
  92. pyvale/{cython → sensorsim/cython}/rastercyth.py +16 -17
  93. pyvale/{errorcalculator.py → sensorsim/errorcalculator.py} +1 -1
  94. pyvale/{errorintegrator.py → sensorsim/errorintegrator.py} +2 -2
  95. pyvale/{errorrand.py → sensorsim/errorrand.py} +4 -4
  96. pyvale/{errorsyscalib.py → sensorsim/errorsyscalib.py} +2 -2
  97. pyvale/{errorsysdep.py → sensorsim/errorsysdep.py} +2 -2
  98. pyvale/{errorsysfield.py → sensorsim/errorsysfield.py} +8 -8
  99. pyvale/{errorsysindep.py → sensorsim/errorsysindep.py} +3 -3
  100. pyvale/sensorsim/exceptions.py +8 -0
  101. pyvale/{experimentsimulator.py → sensorsim/experimentsimulator.py} +23 -3
  102. pyvale/{field.py → sensorsim/field.py} +1 -1
  103. pyvale/{fieldconverter.py → sensorsim/fieldconverter.py} +72 -19
  104. pyvale/sensorsim/fieldinterp.py +37 -0
  105. pyvale/sensorsim/fieldinterpmesh.py +124 -0
  106. pyvale/sensorsim/fieldinterppoints.py +55 -0
  107. pyvale/{fieldsampler.py → sensorsim/fieldsampler.py} +4 -4
  108. pyvale/{fieldscalar.py → sensorsim/fieldscalar.py} +28 -24
  109. pyvale/{fieldtensor.py → sensorsim/fieldtensor.py} +33 -31
  110. pyvale/{fieldvector.py → sensorsim/fieldvector.py} +33 -31
  111. pyvale/{imagedef2d.py → sensorsim/imagedef2d.py} +9 -5
  112. pyvale/{integratorfactory.py → sensorsim/integratorfactory.py} +6 -6
  113. pyvale/{integratorquadrature.py → sensorsim/integratorquadrature.py} +3 -3
  114. pyvale/{integratorrectangle.py → sensorsim/integratorrectangle.py} +3 -3
  115. pyvale/{integratorspatial.py → sensorsim/integratorspatial.py} +1 -1
  116. pyvale/{rastercy.py → sensorsim/rastercy.py} +5 -5
  117. pyvale/{rasternp.py → sensorsim/rasternp.py} +9 -9
  118. pyvale/{rasteropts.py → sensorsim/rasteropts.py} +1 -1
  119. pyvale/{renderer.py → sensorsim/renderer.py} +1 -1
  120. pyvale/{rendermesh.py → sensorsim/rendermesh.py} +5 -5
  121. pyvale/{renderscene.py → sensorsim/renderscene.py} +2 -2
  122. pyvale/{sensorarray.py → sensorsim/sensorarray.py} +1 -1
  123. pyvale/{sensorarrayfactory.py → sensorsim/sensorarrayfactory.py} +12 -12
  124. pyvale/{sensorarraypoint.py → sensorsim/sensorarraypoint.py} +10 -8
  125. pyvale/{sensordata.py → sensorsim/sensordata.py} +1 -1
  126. pyvale/{sensortools.py → sensorsim/sensortools.py} +2 -20
  127. pyvale/sensorsim/simtools.py +174 -0
  128. pyvale/{visualexpplotter.py → sensorsim/visualexpplotter.py} +3 -3
  129. pyvale/{visualimages.py → sensorsim/visualimages.py} +2 -2
  130. pyvale/{visualsimanimator.py → sensorsim/visualsimanimator.py} +4 -4
  131. pyvale/{visualsimplotter.py → sensorsim/visualsimplotter.py} +5 -5
  132. pyvale/{visualsimsensors.py → sensorsim/visualsimsensors.py} +12 -12
  133. pyvale/{visualtools.py → sensorsim/visualtools.py} +1 -1
  134. pyvale/{visualtraceplotter.py → sensorsim/visualtraceplotter.py} +2 -2
  135. pyvale/simcases/case17.geo +3 -0
  136. pyvale/simcases/case17.i +4 -4
  137. pyvale/simcases/run_1case.py +1 -9
  138. pyvale/simcases/run_all_cases.py +1 -1
  139. pyvale/simcases/run_build_case.py +1 -1
  140. pyvale/simcases/run_example_cases.py +1 -1
  141. pyvale/verif/__init__.py +12 -0
  142. pyvale/{analyticsimdatafactory.py → verif/analyticsimdatafactory.py} +2 -2
  143. pyvale/{analyticsimdatagenerator.py → verif/analyticsimdatagenerator.py} +2 -2
  144. pyvale/verif/psens.py +125 -0
  145. pyvale/verif/psensconst.py +18 -0
  146. pyvale/verif/psensmech.py +227 -0
  147. pyvale/verif/psensmultiphys.py +187 -0
  148. pyvale/verif/psensscalar.py +347 -0
  149. pyvale/verif/psenstensor.py +123 -0
  150. pyvale/verif/psensvector.py +116 -0
  151. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/METADATA +6 -7
  152. pyvale-2025.8.1.dist-info/RECORD +263 -0
  153. pyvale/cython/rastercyth.cpython-311-aarch64-linux-musl.so +0 -0
  154. pyvale/dataset.py +0 -415
  155. pyvale/simtools.py +0 -67
  156. pyvale-2025.7.2.dist-info/RECORD +0 -215
  157. /pyvale/{blendercalibrationdata.py → blender/blendercalibrationdata.py} +0 -0
  158. /pyvale/{dicchecks.py → dic/dicchecks.py} +0 -0
  159. /pyvale/{dicspecklegenerator.py → dic/dicspecklegenerator.py} +0 -0
  160. /pyvale/{dicspecklequality.py → dic/dicspecklequality.py} +0 -0
  161. /pyvale/{dicstrainresults.py → dic/dicstrainresults.py} +0 -0
  162. /pyvale/{cameradata.py → sensorsim/cameradata.py} +0 -0
  163. /pyvale/{cameradata2d.py → sensorsim/cameradata2d.py} +0 -0
  164. /pyvale/{errordriftcalc.py → sensorsim/errordriftcalc.py} +0 -0
  165. /pyvale/{fieldtransform.py → sensorsim/fieldtransform.py} +0 -0
  166. /pyvale/{generatorsrandom.py → sensorsim/generatorsrandom.py} +0 -0
  167. /pyvale/{imagetools.py → sensorsim/imagetools.py} +0 -0
  168. /pyvale/{integratortype.py → sensorsim/integratortype.py} +0 -0
  169. /pyvale/{output.py → sensorsim/output.py} +0 -0
  170. /pyvale/{raster.py → sensorsim/raster.py} +0 -0
  171. /pyvale/{sensordescriptor.py → sensorsim/sensordescriptor.py} +0 -0
  172. /pyvale/{visualimagedef.py → sensorsim/visualimagedef.py} +0 -0
  173. /pyvale/{visualopts.py → sensorsim/visualopts.py} +0 -0
  174. /pyvale/{analyticmeshgen.py → verif/analyticmeshgen.py} +0 -0
  175. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/WHEEL +0 -0
  176. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/licenses/LICENSE +0 -0
  177. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,303 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+ import os
7
+ import subprocess
8
+ from pathlib import Path
9
+ from pyvale.mooseherder.simrunner import SimRunner
10
+ from pyvale.mooseherder.mooseconfig import MooseConfig
11
+
12
+
13
+ class MooseRunner(SimRunner):
14
+ """Used to run MOOSE models (*.i) from python."""
15
+ def __init__(self, config: MooseConfig):
16
+ """Constructor for MOOSE runner taking a MooseConfig object
17
+ that contains the paths to the main MOOSE install, the MOOSE app and
18
+ the MOOSE app name. Sets default parallelisation options to 1 MPI task
19
+ and 1 thread. Sets environment variables required for MPI setup.
20
+
21
+
22
+ Parameters
23
+ ----------
24
+ config : MooseConfig
25
+ moose configuration object containing the required paths and app
26
+ name to construct the command string.
27
+ """
28
+ self._config = config.get_config()
29
+
30
+ self._n_threads = 1
31
+ self._n_tasks = 1
32
+ self._redirect_stdout = True
33
+ self._arg_list = list('')
34
+ self._input_path = None
35
+
36
+
37
+ def set_env_vars(self) -> None:
38
+ """Sets environment variables for calling MOOSE with MPI."""
39
+ os.environ['CC'] = 'mpicc'
40
+ os.environ['CXX'] = 'mpicxx'
41
+ os.environ['F90'] = 'mpif90'
42
+ os.environ['F77'] = 'mpif77'
43
+ os.environ['FC'] = 'mpif90'
44
+ os.environ['MOOSE_DIR'] = str(self._config['main_path'])
45
+ if not str(self._config['app_path']) in os.environ["PATH"]:
46
+ os.environ["PATH"] = os.environ["PATH"] + ':' + str(self._config['app_path'])
47
+
48
+ def set_threads(self, n_threads: int) -> None:
49
+ """Sets the number of threads asked of MOOSE on the command line.
50
+
51
+ Parameters
52
+ ----------
53
+ n_threads : int
54
+ Number of threads.
55
+ """
56
+ # Need to make sure number is sensible based on cpu
57
+ if n_threads <= 0:
58
+ n_threads = 1
59
+ elif os.cpu_count() is None:
60
+ n_threads = 1
61
+ elif n_threads > os.cpu_count(): # type: ignore
62
+ n_threads = os.cpu_count() # type: ignore
63
+
64
+ self._n_threads = int(n_threads)
65
+
66
+ def set_tasks(self, n_tasks: int) -> None:
67
+ """Sets the number of MPI tasks asked of MOOSE on the command line.
68
+
69
+ Parameters
70
+ ----------
71
+ n_tasks : int
72
+ Number of mpi tasks.
73
+
74
+ Returns
75
+ -------
76
+
77
+ """
78
+ # Need to make sure is sensible based on cpu
79
+ if n_tasks <= 0:
80
+ n_tasks = 1
81
+ elif os.cpu_count() is None:
82
+ n_tasks = 1
83
+ elif n_tasks > os.cpu_count(): # type: ignore
84
+ n_tasks = os.cpu_count() # type: ignore
85
+
86
+ self._n_tasks = int(n_tasks)
87
+
88
+ def set_stdout(self, redirect_flag: bool = True) -> None:
89
+ """Sets MOOSE to redirect output (True) to file instead of console (False).
90
+
91
+ Parameters
92
+ ----------
93
+ redirect_flag : bool
94
+ True = output to stdout file, False
95
+ = output to console. Defaults to True.
96
+
97
+ Returns
98
+ -------
99
+
100
+ """
101
+ self._redirect_stdout = redirect_flag
102
+
103
+ def set_run_opts(self, n_tasks: int = 1,
104
+ n_threads: int = 1,
105
+ redirect_out: bool = True) -> None:
106
+ """Sets all options for MOOSE run parallelisation and output.
107
+
108
+ Parameters
109
+ ----------
110
+ n_tasks : int
111
+ Number of mpi tasks for MOOSE run.
112
+ Defaults to 1.
113
+ n_threads : int
114
+ Number of threads for MOOSE run.
115
+ Defaults to 1.
116
+ redirect : bool
117
+ Redirect MOOSE output from console to
118
+ file (True). Defaults to False.
119
+
120
+ Returns
121
+ -------
122
+
123
+ """
124
+ self.set_threads(n_threads)
125
+ self.set_tasks(n_tasks)
126
+ self.set_stdout(redirect_out)
127
+
128
+
129
+ def get_input_file(self) -> Path | None:
130
+ """get_input_file
131
+
132
+ Parameters
133
+ ----------
134
+
135
+ Returns
136
+ -------
137
+ Path | None
138
+ full path to the input file or None if not specified.
139
+
140
+ """
141
+ return self._input_path
142
+
143
+
144
+ def set_input_file(self, input_path: Path) -> None:
145
+ """Sets the path to the MOOSE input file and checks it exists.
146
+
147
+ Parameters
148
+ ----------
149
+ input_file : Path
150
+ full path and name of *.i MOOSE input script.
151
+
152
+ Returns
153
+ -------
154
+
155
+ Raises
156
+ ------
157
+ FileNotFoundError
158
+ the MOOSE input script doesn't exist
159
+
160
+ """
161
+ if not input_path.is_file():
162
+ raise FileNotFoundError("Input file does not exist.")
163
+
164
+ self._input_path = input_path
165
+ self.assemble_arg_list()
166
+
167
+ def get_input_dir(self) -> Path | None:
168
+ """Gets the path to the directory for the specified input file.
169
+
170
+ Parameters
171
+ ----------
172
+
173
+ Returns
174
+ -------
175
+ Path
176
+ path to input file directory, if no input file is specified
177
+ returns None.
178
+
179
+ """
180
+ if self._input_path is None:
181
+ return None
182
+
183
+ return self._input_path.parent # type: ignore
184
+
185
+ def get_input_tag(self) -> str:
186
+ """Gets the input file name string without the path or the .i
187
+
188
+ Parameters
189
+ ----------
190
+
191
+ Returns
192
+ -------
193
+ str
194
+ input file string, if no input file is specified returns an
195
+ empty string.
196
+
197
+ """
198
+ if self._input_path is None:
199
+ return ""
200
+
201
+ return self._input_path.stem # type: ignore
202
+
203
+
204
+ def get_output_path(self) -> Path | None:
205
+ """Gets the file and path for the output exodus file based
206
+ on the specified input file. Includes '_out.e'.
207
+
208
+ Parameters
209
+ ----------
210
+
211
+ Returns
212
+ -------
213
+ Path
214
+ output exodus file name with path, returns an empty None
215
+ if no input file is specified.
216
+
217
+ """
218
+ if self._input_path is None:
219
+ return None
220
+
221
+ return self._input_path.parent / (self._input_path.stem +'_out.e')
222
+
223
+
224
+ def get_arg_list(self) -> list[str]:
225
+ """Run string getter.
226
+
227
+ Parameters
228
+ ----------
229
+
230
+ Returns
231
+ -------
232
+ str
233
+ command line string to run MOOSE.
234
+
235
+ """
236
+ return self._arg_list
237
+
238
+ def assemble_arg_list(self, input_file = None) -> list[str]:
239
+ """Assmebles the command line string to run MOOSE based on current
240
+ options.
241
+
242
+ Parameters
243
+ ----------
244
+ input_file : str
245
+ Full path to MOOSE input file, if not
246
+ empty updates the input file. Defaults to "".
247
+
248
+ Returns
249
+ -------
250
+ str
251
+ command line string that will be used by the runner when run
252
+ is called.
253
+
254
+ """
255
+ if input_file is not None:
256
+ self.set_input_file(input_file)
257
+
258
+ if self._input_path is None:
259
+ raise RuntimeError('No input file specified, set one using set_input_file or by passing on into this function.')
260
+
261
+ arg_list = []
262
+ if self._n_tasks > 1:
263
+ arg_list = ['mpirun','-np',str(self._n_tasks)]
264
+
265
+ arg_list = arg_list + [str(self._config['app_name']) \
266
+ ,f'--n-threads={self._n_threads}','-i' \
267
+ ,str(self._input_path.name)]
268
+
269
+ if self._redirect_stdout:
270
+ arg_list = arg_list + ['--redirect-stdout']
271
+
272
+ self._arg_list = arg_list
273
+
274
+ return self._arg_list
275
+
276
+
277
+ def run(self, input_file = None) -> None:
278
+ """Runs MOOSE based on current options by passing run string to
279
+ subprocess shell.
280
+
281
+ Parameters
282
+ ----------
283
+ input_file : Path
284
+ Full path to MOOSE input file, if not
285
+ empty updates the input file. Defaults to None.
286
+
287
+ Returns
288
+ -------
289
+
290
+ """
291
+ if input_file is not None:
292
+ self.set_input_file(input_file)
293
+
294
+ if self._input_path is None:
295
+ raise RuntimeError("Set input path before calling run.")
296
+
297
+ self.set_env_vars()
298
+
299
+ self.assemble_arg_list()
300
+ subprocess.run(self._arg_list,
301
+ shell=False,
302
+ cwd=str(self._input_path.parent),
303
+ check=False)
@@ -0,0 +1,22 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+ from abc import ABC, abstractmethod
7
+ from pathlib import Path
8
+ from pyvale.mooseherder.simdata import SimData, SimReadConfig
9
+
10
+
11
+ class OutputReader(ABC):
12
+ @abstractmethod
13
+ def __init__(self, output_file: Path) -> None:
14
+ pass
15
+
16
+ @abstractmethod
17
+ def read_sim_data(self, read_config: SimReadConfig) -> SimData:
18
+ pass
19
+
20
+ @abstractmethod
21
+ def read_all_sim_data(self) -> SimData:
22
+ pass
@@ -0,0 +1,92 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ from dataclasses import dataclass
8
+ import numpy as np
9
+
10
+
11
+ @dataclass
12
+ class SimData:
13
+ """Data class for simulation output. Allows for structured meshes with
14
+ connectivity tables or for point clouds."""
15
+
16
+ num_spat_dims: int = 3
17
+ """ Number of spatial dimensions in the simulation, required to determine
18
+ element types given that all coords are padded to [x,y,z]. Allows for 2D and
19
+ 1D simulations using any combination of the [x,y,z] axes.
20
+ """
21
+
22
+ time: np.ndarray | None = None
23
+ """ Vector of time steps with dimensions [t]. Defaults to None.
24
+ """
25
+
26
+ coords: np.ndarray | None = None
27
+ """ Array of nodal coordinates in N by 3 where N is the number of nodes
28
+ columns are [x,y,z] coordinates and rows are the nth node. Defaults to
29
+ None.
30
+ """
31
+
32
+ connect: dict[str,np.ndarray] | None = None
33
+ """ Element connectivity table:
34
+ key = "connectX" where X is the subdomain e.g. connect1
35
+ Element table given as E by n_e rows where E is the number of elements
36
+ in the given subdomain. n_e is the number of nodes per element.
37
+ Defaults to None.
38
+ """
39
+
40
+ side_sets: dict[tuple[str,str],np.ndarray] | None = None
41
+ """ Sidesets by name and associated node and element numbers.
42
+ key = (name, "node" or "elem") e.g. ("bottom","node") will return node
43
+ numbers associated with associated with sideset called "bottom" as a
44
+ numpy array with n_s entries where n_s is the number of nodes in the
45
+ sideset.
46
+ Defaults to None.
47
+ """
48
+
49
+ node_vars: dict[str,np.ndarray] | None = None
50
+ """ Nodal variable by name.
51
+ key = "name" e.g. "disp_x" or "temp"
52
+ Gives the nodal variable as a numpy array, N by t where N is the number
53
+ of nodes and t is the number of time steps. Note that element variables
54
+ can be stored as nodal depending on output options or material output
55
+ order selected.
56
+ Defaults to None.
57
+ """
58
+
59
+ elem_vars: dict[tuple[str,int],np.ndarray] | None = None
60
+ """ Element variables by name and block.
61
+ key = (name, block num)
62
+ Gives the element variable as a numpy array, E by t where E is the
63
+ number of elements and t is the number of time steps. Note that element
64
+ variables might exist as nodal variables only depending on output
65
+ options and specified material output order.
66
+ Defaults to None.
67
+ """
68
+
69
+ glob_vars: dict[str,np.ndarray] | None = None
70
+ """ Global variables by name. Global variable include postprocessors and
71
+ extracted reactions at boundaries.
72
+ key = name (as specified in input file post-processor), e.g. "react_y"
73
+ Gives a numpy array with t entries corresponding to the number of time
74
+ steps in the simulation.
75
+ Defaults to None.
76
+ """
77
+
78
+ @dataclass(slots=True)
79
+ class SimReadConfig:
80
+ """Used to specify names of variables to be read into the SimData class.
81
+ This class allows the user to only extract the required variables by
82
+ name.
83
+ """
84
+ time: bool = True
85
+ coords: bool = True
86
+ connect: bool = True
87
+ sidesets: np.ndarray | None = None
88
+ node_vars: np.ndarray | None = None
89
+ elem_vars: list[tuple[str,int]] | None = None
90
+ glob_vars: np.ndarray | None = None
91
+ time_inds: np.ndarray | None = None
92
+
@@ -0,0 +1,31 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ from abc import ABC, abstractmethod
8
+ from pathlib import Path
9
+
10
+ class SimRunner(ABC):
11
+ """SimRunner: ABC for the moosherd simulation chain. A simulation has an
12
+ input file which can be get or set. The simulation can then be run with the
13
+ given input files and then the path to the simulation output file can be
14
+ retrieved.
15
+ """
16
+ @abstractmethod
17
+ def get_input_file(self) -> Path | None:
18
+ pass
19
+
20
+ @abstractmethod
21
+ def set_input_file(self, input_path: Path) -> None:
22
+ pass
23
+
24
+ @abstractmethod
25
+ def run(self, input_file: Path | None = None) -> None:
26
+ pass
27
+
28
+ @abstractmethod
29
+ def get_output_path(self) -> Path | None:
30
+ pass
31
+