pyvale 2025.7.1__cp311-cp311-win_amd64.whl → 2025.8.1__cp311-cp311-win_amd64.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 (186) 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/dic/cpp/dicfourier.cpp +36 -4
  13. pyvale/dic/cpp/dicinterpolator.cpp +56 -1
  14. pyvale/dic/cpp/dicmain.cpp +24 -19
  15. pyvale/dic/cpp/dicoptimizer.cpp +6 -1
  16. pyvale/dic/cpp/dicscanmethod.cpp +32 -32
  17. pyvale/dic/cpp/dicsignalhandler.cpp +16 -0
  18. pyvale/dic/cpp/dicstrain.cpp +7 -3
  19. pyvale/dic/cpp/dicutil.cpp +79 -23
  20. pyvale/{dic2d.py → dic/dic2d.py} +51 -29
  21. pyvale/dic/dic2dconv.py +6 -0
  22. pyvale/dic/dic2dcpp.cp311-win_amd64.pyd +0 -0
  23. pyvale/{dicchecks.py → dic/dicchecks.py} +28 -16
  24. pyvale/dic/dicdataimport.py +370 -0
  25. pyvale/{dicregionofinterest.py → dic/dicregionofinterest.py} +169 -12
  26. pyvale/{dicresults.py → dic/dicresults.py} +4 -1
  27. pyvale/{dicstrain.py → dic/dicstrain.py} +9 -9
  28. pyvale/examples/basics/{ex1_1_basicscalars_therm2d.py → ex1a_basicscalars_therm2d.py} +12 -9
  29. pyvale/examples/basics/{ex1_2_sensormodel_therm2d.py → ex1b_sensormodel_therm2d.py} +17 -14
  30. pyvale/examples/basics/{ex1_3_customsens_therm3d.py → ex1c_customsens_therm3d.py} +27 -24
  31. pyvale/examples/basics/{ex1_4_basicerrors_therm3d.py → ex1d_basicerrors_therm3d.py} +32 -29
  32. pyvale/examples/basics/{ex1_5_fielderrs_therm3d.py → ex1e_fielderrs_therm3d.py} +19 -15
  33. pyvale/examples/basics/{ex1_6_caliberrs_therm2d.py → ex1f_caliberrs_therm2d.py} +20 -16
  34. pyvale/examples/basics/{ex1_7_spatavg_therm2d.py → ex1g_spatavg_therm2d.py} +19 -16
  35. pyvale/examples/basics/{ex2_1_basicvectors_disp2d.py → ex2a_basicvectors_disp2d.py} +13 -10
  36. pyvale/examples/basics/{ex2_2_vectorsens_disp2d.py → ex2b_vectorsens_disp2d.py} +19 -15
  37. pyvale/examples/basics/{ex2_3_sensangle_disp2d.py → ex2c_sensangle_disp2d.py} +21 -18
  38. pyvale/examples/basics/{ex2_4_chainfielderrs_disp2d.py → ex2d_chainfielderrs_disp2d.py} +31 -29
  39. pyvale/examples/basics/{ex2_5_vectorfields3d_disp3d.py → ex2e_vectorfields3d_disp3d.py} +21 -18
  40. pyvale/examples/basics/{ex3_1_basictensors_strain2d.py → ex3a_basictensors_strain2d.py} +16 -14
  41. pyvale/examples/basics/{ex3_2_tensorsens2d_strain2d.py → ex3b_tensorsens2d_strain2d.py} +17 -14
  42. pyvale/examples/basics/{ex3_3_tensorsens3d_strain3d.py → ex3c_tensorsens3d_strain3d.py} +25 -22
  43. pyvale/examples/basics/{ex4_1_expsim2d_thermmech2d.py → ex4a_expsim2d_thermmech2d.py} +17 -14
  44. pyvale/examples/basics/{ex4_2_expsim3d_thermmech3d.py → ex4b_expsim3d_thermmech3d.py} +37 -34
  45. pyvale/examples/basics/ex5_nomesh.py +24 -0
  46. pyvale/examples/dic/ex1_2_blenderdeformed.py +174 -0
  47. pyvale/examples/dic/ex1_region_of_interest.py +6 -3
  48. pyvale/examples/dic/ex2_plate_with_hole.py +21 -18
  49. pyvale/examples/dic/ex3_plate_with_hole_strain.py +8 -6
  50. pyvale/examples/dic/ex4_dic_blender.py +17 -15
  51. pyvale/examples/dic/ex5_dic_challenge.py +19 -14
  52. pyvale/examples/genanalyticdata/ex1_1_scalarvisualisation.py +16 -10
  53. pyvale/examples/genanalyticdata/ex1_2_scalarcasebuild.py +3 -3
  54. pyvale/examples/genanalyticdata/ex2_1_analyticsensors.py +29 -23
  55. pyvale/examples/genanalyticdata/ex2_2_analyticsensors_nomesh.py +67 -0
  56. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +12 -9
  57. pyvale/examples/mooseherder/ex0_create_moose_config.py +65 -0
  58. pyvale/examples/mooseherder/ex1a_modify_moose_input.py +71 -0
  59. pyvale/examples/mooseherder/ex1b_modify_gmsh_input.py +69 -0
  60. pyvale/examples/mooseherder/ex2a_run_moose_once.py +80 -0
  61. pyvale/examples/mooseherder/ex2b_run_gmsh_once.py +64 -0
  62. pyvale/examples/mooseherder/ex2c_run_both_once.py +114 -0
  63. pyvale/examples/mooseherder/ex3_run_moose_seq_para.py +157 -0
  64. pyvale/examples/mooseherder/ex4_run_gmsh-moose_seq_para.py +176 -0
  65. pyvale/examples/mooseherder/ex5_run_moose_paramulti.py +136 -0
  66. pyvale/examples/mooseherder/ex6_read_moose_exodus.py +163 -0
  67. pyvale/examples/mooseherder/ex7a_read_moose_herd_results.py +153 -0
  68. pyvale/examples/mooseherder/ex7b_read_multi_herd_results.py +116 -0
  69. pyvale/examples/mooseherder/ex7c_read_multi_gmshmoose_results.py +127 -0
  70. pyvale/examples/mooseherder/ex7d_readconfig_multi_gmshmoose_results.py +143 -0
  71. pyvale/examples/mooseherder/ex8_read_existing_sweep_output.py +72 -0
  72. pyvale/examples/renderblender/ex1_1_blenderscene.py +24 -20
  73. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +22 -18
  74. pyvale/examples/renderblender/ex2_1_stereoscene.py +36 -29
  75. pyvale/examples/renderblender/ex2_2_stereodeformed.py +26 -20
  76. pyvale/examples/renderblender/ex3_1_blendercalibration.py +24 -17
  77. pyvale/examples/renderrasterisation/ex_rastenp.py +14 -12
  78. pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +14 -15
  79. pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +13 -11
  80. pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +13 -11
  81. pyvale/mooseherder/__init__.py +32 -0
  82. pyvale/mooseherder/directorymanager.py +416 -0
  83. pyvale/mooseherder/exodusreader.py +763 -0
  84. pyvale/mooseherder/gmshrunner.py +163 -0
  85. pyvale/mooseherder/inputmodifier.py +236 -0
  86. pyvale/mooseherder/mooseconfig.py +226 -0
  87. pyvale/mooseherder/mooseherd.py +527 -0
  88. pyvale/mooseherder/mooserunner.py +303 -0
  89. pyvale/mooseherder/outputreader.py +22 -0
  90. pyvale/mooseherder/simdata.py +92 -0
  91. pyvale/mooseherder/simrunner.py +31 -0
  92. pyvale/mooseherder/sweepreader.py +356 -0
  93. pyvale/mooseherder/sweeptools.py +76 -0
  94. pyvale/sensorsim/__init__.py +82 -0
  95. pyvale/{camera.py → sensorsim/camera.py} +7 -7
  96. pyvale/{camerasensor.py → sensorsim/camerasensor.py} +7 -7
  97. pyvale/{camerastereo.py → sensorsim/camerastereo.py} +2 -2
  98. pyvale/{cameratools.py → sensorsim/cameratools.py} +4 -4
  99. pyvale/{cython → sensorsim/cython}/rastercyth.c +596 -596
  100. pyvale/{cython → sensorsim/cython}/rastercyth.cp311-win_amd64.pyd +0 -0
  101. pyvale/{cython → sensorsim/cython}/rastercyth.py +16 -17
  102. pyvale/{errorcalculator.py → sensorsim/errorcalculator.py} +1 -1
  103. pyvale/{errorintegrator.py → sensorsim/errorintegrator.py} +2 -2
  104. pyvale/{errorrand.py → sensorsim/errorrand.py} +4 -4
  105. pyvale/{errorsyscalib.py → sensorsim/errorsyscalib.py} +2 -2
  106. pyvale/{errorsysdep.py → sensorsim/errorsysdep.py} +2 -2
  107. pyvale/{errorsysfield.py → sensorsim/errorsysfield.py} +8 -8
  108. pyvale/{errorsysindep.py → sensorsim/errorsysindep.py} +3 -3
  109. pyvale/sensorsim/exceptions.py +8 -0
  110. pyvale/{experimentsimulator.py → sensorsim/experimentsimulator.py} +23 -3
  111. pyvale/{field.py → sensorsim/field.py} +1 -1
  112. pyvale/{fieldconverter.py → sensorsim/fieldconverter.py} +72 -19
  113. pyvale/sensorsim/fieldinterp.py +37 -0
  114. pyvale/sensorsim/fieldinterpmesh.py +124 -0
  115. pyvale/sensorsim/fieldinterppoints.py +55 -0
  116. pyvale/{fieldsampler.py → sensorsim/fieldsampler.py} +4 -4
  117. pyvale/{fieldscalar.py → sensorsim/fieldscalar.py} +28 -24
  118. pyvale/{fieldtensor.py → sensorsim/fieldtensor.py} +33 -31
  119. pyvale/{fieldvector.py → sensorsim/fieldvector.py} +33 -31
  120. pyvale/{imagedef2d.py → sensorsim/imagedef2d.py} +9 -5
  121. pyvale/{integratorfactory.py → sensorsim/integratorfactory.py} +6 -6
  122. pyvale/{integratorquadrature.py → sensorsim/integratorquadrature.py} +3 -3
  123. pyvale/{integratorrectangle.py → sensorsim/integratorrectangle.py} +3 -3
  124. pyvale/{integratorspatial.py → sensorsim/integratorspatial.py} +1 -1
  125. pyvale/{rastercy.py → sensorsim/rastercy.py} +5 -5
  126. pyvale/{rasternp.py → sensorsim/rasternp.py} +9 -9
  127. pyvale/{rasteropts.py → sensorsim/rasteropts.py} +1 -1
  128. pyvale/{renderer.py → sensorsim/renderer.py} +1 -1
  129. pyvale/{rendermesh.py → sensorsim/rendermesh.py} +5 -5
  130. pyvale/{renderscene.py → sensorsim/renderscene.py} +2 -2
  131. pyvale/{sensorarray.py → sensorsim/sensorarray.py} +1 -1
  132. pyvale/{sensorarrayfactory.py → sensorsim/sensorarrayfactory.py} +12 -12
  133. pyvale/{sensorarraypoint.py → sensorsim/sensorarraypoint.py} +10 -8
  134. pyvale/{sensordata.py → sensorsim/sensordata.py} +1 -1
  135. pyvale/{sensortools.py → sensorsim/sensortools.py} +2 -20
  136. pyvale/sensorsim/simtools.py +174 -0
  137. pyvale/{visualexpplotter.py → sensorsim/visualexpplotter.py} +3 -3
  138. pyvale/{visualimages.py → sensorsim/visualimages.py} +2 -2
  139. pyvale/{visualsimanimator.py → sensorsim/visualsimanimator.py} +4 -4
  140. pyvale/{visualsimplotter.py → sensorsim/visualsimplotter.py} +5 -5
  141. pyvale/{visualsimsensors.py → sensorsim/visualsimsensors.py} +12 -12
  142. pyvale/{visualtools.py → sensorsim/visualtools.py} +1 -1
  143. pyvale/{visualtraceplotter.py → sensorsim/visualtraceplotter.py} +2 -2
  144. pyvale/simcases/case17.geo +3 -0
  145. pyvale/simcases/case17.i +4 -4
  146. pyvale/simcases/run_1case.py +1 -9
  147. pyvale/simcases/run_all_cases.py +1 -1
  148. pyvale/simcases/run_build_case.py +1 -1
  149. pyvale/simcases/run_example_cases.py +1 -1
  150. pyvale/verif/__init__.py +12 -0
  151. pyvale/{analyticsimdatafactory.py → verif/analyticsimdatafactory.py} +2 -2
  152. pyvale/{analyticsimdatagenerator.py → verif/analyticsimdatagenerator.py} +2 -2
  153. pyvale/verif/psens.py +125 -0
  154. pyvale/verif/psensconst.py +18 -0
  155. pyvale/verif/psensmech.py +227 -0
  156. pyvale/verif/psensmultiphys.py +187 -0
  157. pyvale/verif/psensscalar.py +347 -0
  158. pyvale/verif/psenstensor.py +123 -0
  159. pyvale/verif/psensvector.py +116 -0
  160. {pyvale-2025.7.1.dist-info → pyvale-2025.8.1.dist-info}/METADATA +6 -7
  161. pyvale-2025.8.1.dist-info/RECORD +260 -0
  162. pyvale/dataset.py +0 -415
  163. pyvale/dic2dcpp.cp311-win_amd64.pyd +0 -0
  164. pyvale/dicdataimport.py +0 -247
  165. pyvale/simtools.py +0 -67
  166. pyvale-2025.7.1.dist-info/RECORD +0 -211
  167. /pyvale/{blendercalibrationdata.py → blender/blendercalibrationdata.py} +0 -0
  168. /pyvale/{dicspecklegenerator.py → dic/dicspecklegenerator.py} +0 -0
  169. /pyvale/{dicspecklequality.py → dic/dicspecklequality.py} +0 -0
  170. /pyvale/{dicstrainresults.py → dic/dicstrainresults.py} +0 -0
  171. /pyvale/{cameradata.py → sensorsim/cameradata.py} +0 -0
  172. /pyvale/{cameradata2d.py → sensorsim/cameradata2d.py} +0 -0
  173. /pyvale/{errordriftcalc.py → sensorsim/errordriftcalc.py} +0 -0
  174. /pyvale/{fieldtransform.py → sensorsim/fieldtransform.py} +0 -0
  175. /pyvale/{generatorsrandom.py → sensorsim/generatorsrandom.py} +0 -0
  176. /pyvale/{imagetools.py → sensorsim/imagetools.py} +0 -0
  177. /pyvale/{integratortype.py → sensorsim/integratortype.py} +0 -0
  178. /pyvale/{output.py → sensorsim/output.py} +0 -0
  179. /pyvale/{raster.py → sensorsim/raster.py} +0 -0
  180. /pyvale/{sensordescriptor.py → sensorsim/sensordescriptor.py} +0 -0
  181. /pyvale/{visualimagedef.py → sensorsim/visualimagedef.py} +0 -0
  182. /pyvale/{visualopts.py → sensorsim/visualopts.py} +0 -0
  183. /pyvale/{analyticmeshgen.py → verif/analyticmeshgen.py} +0 -0
  184. {pyvale-2025.7.1.dist-info → pyvale-2025.8.1.dist-info}/WHEEL +0 -0
  185. {pyvale-2025.7.1.dist-info → pyvale-2025.8.1.dist-info}/licenses/LICENSE +0 -0
  186. {pyvale-2025.7.1.dist-info → pyvale-2025.8.1.dist-info}/top_level.txt +0 -0
pyvale/dataset.py DELETED
@@ -1,415 +0,0 @@
1
- #===============================================================================
2
- # pyvale: the python validation engine
3
- # License: MIT
4
- # Copyright (C) 2025 The Computer Aided Validation Team
5
- #===============================================================================
6
-
7
- """
8
- Accesors for data that comes pre-packaged with pyvale for demonstrating its
9
- functionality. This includes moose simulation outputs as exodus files, input
10
- files for moose and gmsh for additional simulation cases, and images required
11
- for testing the image deformation and digital image correlation modules.
12
- """
13
-
14
- from enum import Enum
15
- from pathlib import Path
16
- from importlib.resources import files
17
-
18
- # TODO: finish doc strings for last functions
19
-
20
- SIM_CASE_COUNT = 26
21
- """Constant describing the number of simulation test case input files for moose
22
- and gmsh that come packaged with pyvale.
23
- """
24
-
25
- class EElemTest(Enum):
26
- """Enumeration used to specify different 3D element types for extracting
27
- specific test simulation datasets.
28
- """
29
-
30
- TET4 = "TET4"
31
- """Tetrahedral element, linear with 4 nodes.
32
- """
33
-
34
- TET10 = "TET10"
35
- """Tetrahedral element, quadratic with 10 nodes.
36
- """
37
-
38
- TET14 = "TET14"
39
- """Tetrahedral element, quadratic with 14 nodes.
40
- """
41
-
42
- HEX8 = "HEX8"
43
- """Hexahedral element, linear with 8 nodes.
44
- """
45
-
46
- HEX20 = "HEX20"
47
- """Hexahedral element, quadratic with 20 nodes.
48
- """
49
-
50
- HEX27 = "HEX27"
51
- """Hexahedral element, quadratic with 27 nodes.
52
- """
53
-
54
- def __str__(self):
55
- return self.value
56
-
57
-
58
- class DataSetError(Exception):
59
- """Custom error class for file io errors associated with retrieving datasets
60
- and files packaged with pyvale.
61
- """
62
-
63
-
64
- class DataSet:
65
- @staticmethod
66
- def sim_case_input_file_path(case_num: int) -> Path:
67
- """Gets the path to MOOSE input file (*.i) for a particular simulation
68
- case.
69
-
70
- Parameters
71
- ----------
72
- case_num : int
73
- Integer defining the case number to be retrieved. Must be greater
74
- than 0 and less than the number of simulation cases.
75
-
76
- Returns
77
- -------
78
- Path
79
- Path object to the MOOSE *.i file for the selected simulation case.
80
-
81
- Raises
82
- ------
83
- DataSetError
84
- Raised if an invalid simulation case number is specified.
85
- """
86
- if case_num <= 0:
87
- raise DataSetError("Simulation case number must be greater than 0")
88
- elif case_num > SIM_CASE_COUNT:
89
- raise DataSetError("Simulation case number must be less than " \
90
- + f"{SIM_CASE_COUNT}")
91
-
92
- case_num_str = str(case_num).zfill(2)
93
- case_file = f"case{case_num_str}.i"
94
- return Path(files("pyvale.simcases").joinpath(case_file))
95
-
96
-
97
- @staticmethod
98
- def sim_case_gmsh_file_path(case_num: int) -> Path | None:
99
- """Gets the path to Gmsh input file (*.geo) for a particular simulation
100
- case. Note that not all simulation cases use Gmsh for geometry and mesh
101
- generation. If the specified simulation case does not have an associated
102
- Gmsh *.geo file. In this case 'None' is returned
103
-
104
- Parameters
105
- ----------
106
- case_num : int
107
- Integer defining the case number to be retrieved. Must be greater
108
- than 0 and less than the number of simulation cases.
109
-
110
- Returns
111
- -------
112
- Path | None
113
- Path object to the Gmsh *.geo file for the selected simulation case.
114
- Returns None if there is no *.geo for this simulation case.
115
-
116
- Raises
117
- ------
118
- DataSetError
119
- Raised if an invalid simulation case number is specified.
120
- """
121
- if case_num <= 0:
122
- raise DataSetError("Simulation case number must be greater than 0")
123
- elif case_num > SIM_CASE_COUNT:
124
- raise DataSetError("Simulation case number must be less than " \
125
- + f"{SIM_CASE_COUNT}")
126
-
127
- case_num_str = str(case_num).zfill(2)
128
- case_file = f"case{case_num_str}.geo"
129
- case_path = Path(files("pyvale.simcases").joinpath(case_file))
130
-
131
- if case_path.is_file():
132
- return case_path
133
-
134
- return None
135
-
136
-
137
- @staticmethod
138
- def dic_pattern_5mpx_path() -> Path:
139
- """Path to a 5 mega-pixel speckle pattern image (2464 x 2056 pixels)
140
- with 8 bit resolution stored as a *.tiff. Speckles are sampled by
141
- 5 pixels. A gaussian blur has been applied to the image to remove sharp
142
- transitions from black to white.
143
-
144
- Path
145
- Path to the *.tiff file containing the speckle pattern.
146
- """
147
- return Path(files("pyvale.data")
148
- .joinpath("optspeckle_2464x2056px_spec5px_8bit_gblur1px.tiff"))
149
-
150
- @staticmethod
151
- def thermal_2d_path() -> Path:
152
- """Path to a MOOSE simulation output in exodus format. This case is a
153
- thermal problem solving for a scalar temperature field. The geometry is
154
- a 2D plate (in x,y) with a heat flux applied on one edge and a heat
155
- transfer coefficient applied on the opposite edge inducing a temperature
156
- gradient along the x axis of the plate.
157
-
158
- The simulation parameters can be found in the corresponding MOOSE input
159
- file: case13.i which can be retrieved using `sim_case_input_file_path`
160
- in this class.
161
-
162
-
163
- Returns
164
- -------
165
- Path
166
- Path to the exodus (*.e) output file for this simulation case.
167
- """
168
- return Path(files("pyvale.data").joinpath("case13_out.e"))
169
-
170
- @staticmethod
171
- def thermal_3d_path() -> Path:
172
- """Path to a MOOSE simulation output in exodus format. This case is a 3D
173
- thermal problem solving for a scalar temperature field. The model is a
174
- divertor armour monoblock composed of a tungsten block bonded to a
175
- copper-chromium-zirconium pipe with a pure copper interlayer. A heat
176
- flux is applied to the top surface of the block and a heat transfer
177
- coefficient for cooling water is applied to the inner surface of the
178
- pipe inducing a temperature gradient from the top of the block to the
179
- pipe.
180
-
181
- The simulation parameters can be found in the corresponding MOOSE input
182
- file: case16.i which can be retrieved using `sim_case_input_file_path`
183
- in this class. Note that this case uses a Gmsh *.geo file for geometry
184
- and mesh creation.
185
-
186
- Returns
187
- -------
188
- Path
189
- Path to the exodus (*.e) output file for this simulation case.
190
- """
191
- return Path(files("pyvale.data").joinpath("case16_out.e"))
192
-
193
- @staticmethod
194
- def mechanical_2d_path() -> Path:
195
- """Path to a MOOSE simulation output in exodus format. This case is a 2D
196
- plate with a hole in the center with the bottom edge fixed and a
197
- displacement applied to the top edge. This is a mechanical problem and
198
- solves for the displacement vector field and the tensorial strain field.
199
-
200
- The simulation parameters can be found in the corresponding MOOSE input
201
- file: case17.i which can be retrieved using `sim_case_input_file_path`
202
- in this class. Note that this case uses a Gmsh *.geo file for geometry
203
- and mesh creation.
204
-
205
- Returns
206
- -------
207
- Path
208
- Path to the exodus (*.e) output file for this simulation case.
209
- """
210
- return Path(files("pyvale.data").joinpath("case17_out.e"))
211
-
212
- @staticmethod
213
- def thermomechanical_2d_path() -> Path:
214
- """Path to a MOOSE simulation output in exodus format. This case is a
215
- thermo-mechanical analysis of a 2D plate with a heat flux applied on one
216
- edge and a heat transfer coefficient applied on the opposing edge. The
217
- mechanical deformation results from thermal expansion due to the imposed
218
- temperature gradient. This model is solved for the scalar temperature
219
- field, vector displacement and tensor strain field.
220
-
221
- Returns
222
- -------
223
- Path
224
- Path to the exodus (*.e) output file for this simulation case.
225
- """
226
- return Path(files("pyvale.data").joinpath("case18_1_out.e"))
227
-
228
- @staticmethod
229
- def thermomechanical_3d_path() -> Path:
230
- """Path to a MOOSE simulation output in exodus format. This case is a
231
- thermo-mechanical analysis of a 3D monoblock divertor armour with a heat
232
- flux applied on the top surface and a heat transfer coefficient applied
233
- on the inner surface of the pipe. The mechanical deformation results
234
- from thermal expansion due to the imposed temperature gradient.
235
- This model is solved for the scalar temperature field, vector
236
- displacement and tensor strain field.
237
-
238
- Returns
239
- -------
240
- Path
241
- Path to the exodus (*.e) output file for this simulation case.
242
- """
243
- return Path(files("pyvale.data").joinpath("case16_out.e"))
244
-
245
- @staticmethod
246
- def thermomechanical_2d_experiment_paths() -> list[Path]:
247
- """Path to a MOOSE simulation output in exodus format. This case is a
248
- thermo-mechanical analysis of a 2D plate with a heat flux applied on one
249
- edge and a heat transfer coefficient applied on the opposing edge. The
250
- mechanical deformation results from thermal expansion due to the imposed
251
- temperature gradient. This model is solved for the scalar temperature
252
- field, vector temperature and tensor strain field.
253
-
254
- Here we analyse 3 separate experiments where the thermal conductivity of
255
- the material is perturbed from the nominal case by +/-10%.
256
-
257
- The simulation parameters can be found in the corresponding MOOSE input
258
- file: case18.i which can be retrieved using `sim_case_input_file_path`
259
- in this class.
260
-
261
- Returns
262
- -------
263
- Path
264
- Path to the exodus (*.e) output file for this simulation case.
265
- """
266
- return [Path(files("pyvale.data").joinpath("case18_1_out.e")),
267
- Path(files("pyvale.data").joinpath("case18_2_out.e")),
268
- Path(files("pyvale.data").joinpath("case18_3_out.e"))]
269
-
270
- @staticmethod
271
- def render_mechanical_3d_path() -> Path:
272
- """Path to a MOOSE simulation output in exodus format. This case is a
273
- purely mechanical test case in 3D meant for testing image rendering
274
- algorithms for digital image correlation simulation. The simulation
275
- consists of a linear elastic thin plate with a hole loaded in tension.
276
- The simulation uses linear tetrahedral elements for rendering tests.
277
-
278
- Returns
279
- -------
280
- Path
281
- Path to the exodus (*.e) output file for this simulation case.
282
- """
283
- return Path(files("pyvale.data").joinpath("case26_out.e"))
284
-
285
- @staticmethod
286
- def render_simple_block_path() -> Path:
287
- """Path to a MOOSE simulation output in exodus format. This case is a
288
- a simple rectangular block in 3D loaded in tension. It uses a minimum
289
- number of elements and is intended purely for testing image rendering
290
- algorithms. This simulation uses linear tetrahedral elements.
291
-
292
- Returns
293
- -------
294
- Path
295
- Path to the exodus (*.e) output file for this simulation case.
296
- """
297
- return Path(files("pyvale.data").joinpath("case25_out.e"))
298
-
299
- @staticmethod
300
- def element_case_path(elem_type: EElemTest) -> Path:
301
- """Path to a MOOSE simulation output in exodus format. This case is a
302
- 10mm cube undergoing thermo-mechanical loading solved for the
303
- temperature displacement and strain fields. This case is solved using a
304
- variety of tetrahedral and hexahedral elements with linear or quadratic
305
- shapes functions. These simulation cases are intended for testing
306
- purposes and contain a minimal number of elements.
307
-
308
- Parameters
309
- ----------
310
- elem_type : EElemTest
311
- Enumeration specifying the element type for this test case.
312
-
313
- Returns
314
- -------
315
- Path
316
- Path to the exodus (*.e) output file for this simulation case.
317
- """
318
- return Path(files("pyvale.data")
319
- .joinpath(f"case00_{elem_type.value}_out.e"))
320
-
321
- @staticmethod
322
- def dic_plate_with_hole_ref() -> Path:
323
- """Path to the reference image for the plate with hole example.
324
- 1040x1540 image in .tiff format.
325
-
326
- Parameters
327
- ----------
328
- elem_type : EElemTest
329
- Enumeration specifying the element type for this test case.
330
-
331
- Returns
332
- -------
333
- Path
334
- Path to the reference image (*.tiff).
335
- """
336
- return Path(files("pyvale.data")
337
- .joinpath("plate_hole_ref0000.tiff"))
338
-
339
- @staticmethod
340
- def dic_plate_with_hole_def() -> Path:
341
- """Path to the deformed images for the plate with hole example.
342
- 1040x1540 image in .tiff format.
343
-
344
- Parameters
345
- ----------
346
- elem_type : EElemTest
347
- Enumeration specifying the element type for this test case.
348
-
349
- Returns
350
- -------
351
- Path
352
- Path to the reference image (*.tiff).
353
- """
354
- return Path(files("pyvale.data")
355
- .joinpath("plate_hole_def*.tiff"))
356
-
357
- @staticmethod
358
- def dic_plate_rigid_ref() -> Path:
359
- """Path to the reference image for the plate with hole example.
360
- 1040x1540 image in .tiff format.
361
-
362
- Parameters
363
- ----------
364
- elem_type : EElemTest
365
- Enumeration specifying the element type for this test case.
366
-
367
- Returns
368
- -------
369
- Path
370
- Path to the reference image (*.tiff).
371
- """
372
- return Path(files("pyvale.data")
373
- .joinpath("plate_rigid_ref0000.tiff"))
374
-
375
- @staticmethod
376
- def dic_plate_rigid_def() -> Path:
377
- """Path to the deformed images for the plate with hole example.
378
- 1040x1540 image in .tiff format.
379
-
380
- Returns
381
- -------
382
- Path
383
- Path to the reference image (*.tiff).
384
- """
385
- return Path(files("pyvale.data")
386
- .joinpath("plate_rigid_def*.tiff"))
387
-
388
-
389
-
390
- @staticmethod
391
- def dic_challenge_ref() -> Path:
392
- """Path to the reference images for the 2D dic challenge.
393
-
394
- Returns
395
- -------
396
- Path
397
- Path to the reference image (*.tiff).
398
- """
399
- return Path(files("pyvale.data")
400
- .joinpath("DIC_Challenge_Star_Noise_Ref.tif"))
401
-
402
- @staticmethod
403
- def dic_challenge_def() -> Path:
404
- """Path to the reference images for the 2D dic challenge.
405
-
406
- Returns
407
- -------
408
- Path
409
- Path to the reference image (*.tiff).
410
- """
411
- return Path(files("pyvale.data")
412
- .joinpath("DIC_Challenge_Star_Noise_Def.tif"))
413
-
414
-
415
-
Binary file
pyvale/dicdataimport.py DELETED
@@ -1,247 +0,0 @@
1
- # ================================================================================
2
- # pyvale: the python validation engine
3
- # License: MIT
4
- # Copyright (C) 2025 The Computer Aided Validation Team
5
- # ================================================================================
6
-
7
-
8
-
9
- import numpy as np
10
- import glob
11
- import os
12
- from pathlib import Path
13
-
14
- # import cython module
15
- from pyvale.dicresults import DICResults
16
-
17
- """
18
- Module responsible for handling importing of DIC results from completed
19
- calculations.
20
- """
21
-
22
-
23
- def dic_data_import(data: str | Path,
24
- binary: bool = False,
25
- layout: str = "matrix",
26
- delimiter: str = " ") -> DICResults:
27
- """
28
- Import DIC result data from human readable text or binary files.
29
-
30
- Parameters
31
- ----------
32
-
33
- data : str or pathlib.Path
34
- Path pattern to the data files (can include wildcards). Default is "./".
35
-
36
- layout : str, optional
37
- Format of the output data layout: "column" (flat array per frame) or "matrix"
38
- (reshaped grid per frame). Default is "column".
39
-
40
- binary : bool, optional
41
- If True, expects files in a specific binary format. If False, expects text data.
42
- Default is False.
43
-
44
- delimiter : str, optional
45
- Delimiter used in text data files. Ignored if binary=True. Default is a single space.
46
-
47
- Returns
48
- -------
49
- DICResults
50
- A named container with the following fields:
51
- - ss_x, ss_y (grid arrays if layout=="matrix"; otherwise, 1D integer arrays)
52
- - u, v, m, converged, cost, ftol, xtol, niter (arrays with shape depending on layout)
53
- - filenames (python list)
54
-
55
- Raises
56
- ------
57
- ValueError:
58
- If `layout` is not "column" or "matrix", or text data has insufficient columns,
59
- or binary rows are malformed.
60
-
61
- FileNotFoundError:
62
- If no matching data files are found.
63
- """
64
-
65
-
66
- print("")
67
- print("Attempting DIC Data import...")
68
- print("")
69
-
70
- # convert to str
71
- if isinstance(data, Path):
72
- data = str(data)
73
-
74
- files = sorted(glob.glob(data))
75
- filenames = files
76
- if not files:
77
- raise FileNotFoundError(f"No results found in: {data}")
78
-
79
- print(f"Found {len(files)} files containing DIC results:")
80
- for file in files:
81
- print(f" - {file}")
82
- print("")
83
-
84
-
85
- # Read first file to define reference coordinates
86
- read_data = read_binary if binary else read_text
87
- ss_x_ref, ss_y_ref, *fields = read_data(files[0], delimiter=delimiter)
88
- frames = [list(fields)]
89
-
90
- for file in files[1:]:
91
- ss_x, ss_y, *f = read_data(file, delimiter)
92
- if not (np.array_equal(ss_x_ref, ss_x) and np.array_equal(ss_y_ref, ss_y)):
93
- raise ValueError("Mismatch in coordinates across frames.")
94
- frames.append(f)
95
-
96
- # Stack fields into arrays
97
- arrays = [np.stack([frame[i] for frame in frames]) for i in range(8)]
98
-
99
- if layout == "matrix":
100
- x_unique = np.unique(ss_x_ref)
101
- y_unique = np.unique(ss_y_ref)
102
- X, Y = np.meshgrid(x_unique, y_unique)
103
- shape = (len(files), len(y_unique), len(x_unique))
104
- arrays = [to_grid(a,shape,ss_x_ref, ss_y_ref, x_unique,y_unique) for a in arrays]
105
- return DICResults(X, Y, *arrays, filenames)
106
- else:
107
- return DICResults(ss_x_ref, ss_y_ref, *arrays, filenames)
108
-
109
-
110
-
111
-
112
-
113
- def read_binary(file: str, delimiter: str):
114
- """
115
- Read a binary DIC result file and extract DIC fields.
116
-
117
- Assumes a fixed binary structure with each row containing:
118
- - 2 × int32 (subset coordinates)
119
- - 6 × float64 (u, v, match quality, cost, ftol, xtol)
120
- - 1 × int32 (number of iterations)
121
-
122
- Parameters
123
- ----------
124
- file : str
125
- Path to the binary result file.
126
-
127
- delimiter : str
128
- Ignored for binary data (included for API consistency).
129
-
130
- Returns
131
- -------
132
- tuple of np.ndarray
133
- Arrays corresponding to:
134
- (ss_x, ss_y, u, v, m, cost, ftol, xtol, niter)
135
-
136
- Raises
137
- ------
138
- ValueError
139
- If the binary file size does not align with expected row size.
140
- """
141
-
142
- row_size = (3 * 4 + 6 * 8)
143
- with open(file, "rb") as f:
144
- raw = f.read()
145
- if len(raw) % row_size != 0:
146
- raise ValueError("Binary file has incomplete rows.")
147
- rows = len(raw) // row_size
148
- arr = np.frombuffer(raw, dtype=np.uint8).reshape(rows, row_size)
149
- def extract(col, dtype, start): return np.frombuffer(arr[:, start:start+col], dtype=dtype)
150
- ss_x = extract(4, np.int32, 0)
151
- ss_y = extract(4, np.int32, 4)
152
- u = extract(8, np.float64, 8)
153
- v = extract(8, np.float64, 16)
154
- m = extract(8, np.float64, 24)
155
- conv = extract(1, np.bool_, 25)
156
- cost = extract(8, np.float64, 33)
157
- ftol = extract(8, np.float64, 41)
158
- xtol = extract(8, np.float64, 49)
159
- niter = extract(4, np.int32, 57)
160
- return ss_x, ss_y, u, v, m, conv, cost, ftol, xtol, niter
161
-
162
-
163
-
164
-
165
- def read_text(file: str, delimiter: str):
166
- """
167
- Read a human-readable text DIC result file and extract DIC fields.
168
-
169
- Expects at least 9 columns:
170
- [ss_x, ss_y, u, v, m, conv, cost, ftol, xtol, niter]
171
-
172
- Parameters
173
- ----------
174
- file : str
175
- Path to the text result file.
176
-
177
- delimiter : str
178
- Delimiter used in the text file (e.g., space, tab, comma).
179
-
180
- Returns
181
- -------
182
- tuple of np.ndarray
183
- Arrays corresponding to:
184
- (ss_x, ss_y, u, v, m, conv, cost, ftol, xtol, niter)
185
-
186
- Raises
187
- ------
188
- ValueError
189
- If the text file has fewer than 9 columns.
190
- """
191
-
192
- data = np.loadtxt(file, delimiter=delimiter, skiprows=1)
193
- if data.shape[1] < 9:
194
- raise ValueError("Text data must have at least 9 columns.")
195
- return (
196
- data[:, 0].astype(np.int32), # ss_x
197
- data[:, 1].astype(np.int32), # ss_y
198
- data[:, 2], data[:, 3], data[:, 4], # u, v, mag
199
- data[:, 5].astype(np.bool_), # convergence
200
- data[:, 6], data[:, 7], data[:,8], # cost, ftol, xtol
201
- data[:, 9].astype(np.int32) #niter
202
- )
203
-
204
-
205
-
206
-
207
-
208
- def to_grid(data, shape, ss_x_ref, ss_y_ref, x_unique, y_unique):
209
- """
210
- Reshape a 2D DIC field from flat (column) format into grid (matrix) format.
211
-
212
- This is used when output layout is specified as "matrix".
213
- Maps values using reference subset coordinates (ss_x_ref, ss_y_ref).
214
-
215
- Parameters
216
- ol
217
- ----------
218
- data : np.ndarray
219
- Array of shape (n_frames, n_points) to be reshaped into (n_frames, height, width).
220
-
221
- shape : tuple
222
- Target shape of output array: (n_frames, height, width).
223
-
224
- ss_x_ref : np.ndarray
225
- X coordinates of subset centers.
226
-
227
- ss_y_ref : np.ndarray
228
- Y coordinates of subset centers.
229
-
230
- x_unique : np.ndarray
231
- Sorted unique X coordinates in the grid.
232
-
233
- y_unique : np.ndarray
234
- Sorted unique Y coordinates in the grid.
235
-
236
- Returns
237
- -------
238
- np.ndarray
239
- Reshaped array with shape `shape`, filled with NaNs where no data exists.
240
- """
241
-
242
- grid = np.full(shape, np.nan)
243
- for i, (x, y) in enumerate(zip(ss_x_ref, ss_y_ref)):
244
- x_idx = np.where(x_unique == x)[0][0]
245
- y_idx = np.where(y_unique == y)[0][0]
246
- grid[:, y_idx, x_idx] = data[:, i]
247
- return grid