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
@@ -4,8 +4,8 @@
4
4
  # Copyright (C) 2025 The Computer Aided Validation Team
5
5
  # ==============================================================================
6
6
  import numpy as np
7
- import mooseherder as mh
8
- from pyvale.sensorarray import ISensorArray
7
+ import pyvale.mooseherder as mh
8
+ from pyvale.sensorsim.sensorarray import ISensorArray
9
9
 
10
10
 
11
11
  def create_sensor_pos_array(num_sensors: tuple[int,int,int],
@@ -104,23 +104,5 @@ def print_measurements(sens_array: ISensorArray,
104
104
  print()
105
105
 
106
106
 
107
- def print_dimensions(sim_data: mh.SimData) -> None:
108
- """Diagnostic function for quickly finding the coordinate limits for from a
109
- given simulation.
110
107
 
111
- Parameters
112
- ----------
113
- sim_data : mh.SimData
114
- Simulation data objects containing the nodal coordinates.
115
- """
116
- print(80*"-")
117
- print("SimData Dimensions:")
118
- print(f"x [min,max] = [{np.min(sim_data.coords[:,0])}," + \
119
- f"{np.max(sim_data.coords[:,0])}]")
120
- print(f"y [min,max] = [{np.min(sim_data.coords[:,1])}," + \
121
- f"{np.max(sim_data.coords[:,1])}]")
122
- print(f"z [min,max] = [{np.min(sim_data.coords[:,2])}," + \
123
- f"{np.max(sim_data.coords[:,2])}]")
124
- print(f"t [min,max] = [{np.min(sim_data.time)},{np.max(sim_data.time)}]")
125
- print(80*"-")
126
108
 
@@ -0,0 +1,174 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+ from typing import Any
7
+ import dataclasses
8
+ import numpy as np
9
+ import pyvale.mooseherder as mh
10
+ from pyvale.sensorsim.rendermesh import RenderMesh
11
+
12
+
13
+ class SimTools:
14
+ @staticmethod
15
+ def print_dataclass_fields(in_data: Any) -> None:
16
+ """Diagnostic function
17
+
18
+ Parameters
19
+ ----------
20
+ in_data : Any
21
+ A data class to print the type and fields for as well as the type of
22
+ each of the fields.
23
+ """
24
+
25
+ print(f"Data class fields for: {type(in_data)}")
26
+ for field in dataclasses.fields(in_data):
27
+ if not field.name.startswith('__'):
28
+ print(f" {field.name}: {field.type}")
29
+ print()
30
+
31
+ @staticmethod
32
+ def print_sim_data(sim_data: mh.SimData) -> None:
33
+ """Diagnostic function for inspecting a sim data object to work out shapes
34
+ of time, coordinates, connectivity tables, node vars, elem vars as well as
35
+ the associated keys in the dicttionaries for the connectivity,
36
+ node/elem/glob vars.
37
+
38
+ Parameters
39
+ ----------
40
+ sim_data : mh.SimData
41
+ SimData to print shapes of numpy arrays.
42
+ """
43
+ print()
44
+ if sim_data.time is not None:
45
+ print(f"{sim_data.time.shape=}")
46
+ print()
47
+
48
+ if sim_data.coords is not None:
49
+ print(f"{sim_data.coords.shape=}")
50
+ print()
51
+
52
+ def print_dict(in_dict: dict | None) -> None:
53
+ if in_dict is None:
54
+ print(" None\n")
55
+ return
56
+
57
+ print(f"keys={in_dict.keys()}")
58
+ for kk in in_dict:
59
+ print(f" {kk}.shape={in_dict[kk].shape}")
60
+
61
+ print()
62
+
63
+ print("sim_data.connect")
64
+ print_dict(sim_data.connect)
65
+ print("sim_data.node_vars")
66
+ print_dict(sim_data.node_vars)
67
+ print("sim_data.elem_vars")
68
+ print_dict(sim_data.elem_vars)
69
+ print("sim_data.glob_vars")
70
+ print_dict(sim_data.glob_vars)
71
+
72
+
73
+ @staticmethod
74
+ def print_dimensions(sim_data: mh.SimData) -> None:
75
+ """Diagnostic function for quickly finding the coordinate limits for from a
76
+ given simulation.
77
+
78
+ Parameters
79
+ ----------
80
+ sim_data : mh.SimData
81
+ Simulation data object containing the nodal coordinates.
82
+ """
83
+ print(80*"-")
84
+ print("SimData Dimensions:")
85
+ print(f"x [min,max] = [{np.min(sim_data.coords[:,0])}," + \
86
+ f"{np.max(sim_data.coords[:,0])}]")
87
+ print(f"y [min,max] = [{np.min(sim_data.coords[:,1])}," + \
88
+ f"{np.max(sim_data.coords[:,1])}]")
89
+ print(f"z [min,max] = [{np.min(sim_data.coords[:,2])}," + \
90
+ f"{np.max(sim_data.coords[:,2])}]")
91
+ print(f"t [min,max] = [{np.min(sim_data.time)},{np.max(sim_data.time)}]")
92
+ print(80*"-")
93
+
94
+ @staticmethod
95
+ def get_sim_dims(sim_data: mh.SimData) -> dict[str,tuple[float,float]]:
96
+ """Diagnostic function for extracting the dimensional limits in space and
97
+ time from a SimData object. Useful for finding the spatial dimensions over
98
+ which simulated sensors can be placed as well as the times over which they
99
+ can sampled the underlying field.
100
+
101
+ Parameters
102
+ ----------
103
+ sim_data : mh.SimData
104
+ Simulation data object containing the coordinates and time steps.
105
+
106
+ Returns
107
+ -------
108
+ dict[str,tuple[float,float]]
109
+ Dictionary of space and time coordinate limits keyed as 'x','y','z' for
110
+ the spatial dimensions and 't' for time. The dictionary will return a
111
+ tuple with the (min,max) of the given dimension.
112
+ """
113
+ sim_dims = {}
114
+ sim_dims["x"] = (np.min(sim_data.coords[:,0]),np.max(sim_data.coords[:,0]))
115
+ sim_dims["y"] = (np.min(sim_data.coords[:,1]),np.max(sim_data.coords[:,1]))
116
+ sim_dims["z"] = (np.min(sim_data.coords[:,2]),np.max(sim_data.coords[:,2]))
117
+ sim_dims["t"] = (np.min(sim_data.time),np.max(sim_data.time))
118
+ return sim_dims
119
+
120
+ @staticmethod
121
+ def centre_mesh_nodes(nodes: np.ndarray, spat_dim: int) -> np.ndarray:
122
+ """A method to centre the nodes of a mesh around the origin.
123
+
124
+ Parameters
125
+ ----------
126
+ nodes : np.ndarray
127
+ An array containing the node locations of the mesh.
128
+ spat_dim : int
129
+ The spatial dimension of the mesh.
130
+
131
+ Returns
132
+ -------
133
+ np.ndarray
134
+ An array containing the mesh node locations, but centred around
135
+ the origin.
136
+ """
137
+ max = np.max(nodes, axis=0)
138
+ min = np.min(nodes, axis=0)
139
+ middle = max - ((max - min) / 2)
140
+ if spat_dim == 3:
141
+ middle[2] = 0
142
+ centred = np.subtract(nodes, middle)
143
+ return centred
144
+
145
+ @staticmethod
146
+ def get_deformed_nodes(timestep: int,
147
+ render_mesh: RenderMesh) -> np.ndarray | None:
148
+ """A method to obtain the deformed locations of all the nodes at a given
149
+ timestep.
150
+
151
+ Parameters
152
+ ----------
153
+ timestep : int
154
+ The timestep at which to find the deformed nodes.
155
+ render_mesh: RenderMeshData
156
+ A dataclass containing the skinned mesh and simulation results.
157
+
158
+ Returns
159
+ -------
160
+ np.ndarray | None
161
+ An array containing the deformed values of all the components at
162
+ each node location. Returns None if there are no deformation values.
163
+ """
164
+ if render_mesh.fields_disp is None:
165
+ return None
166
+
167
+ added_disp = render_mesh.fields_disp[:, timestep]
168
+ if added_disp.shape[1] == 2:
169
+ added_disp = np.hstack((added_disp,np.zeros([added_disp.shape[0],1])))
170
+ coords = np.delete(render_mesh.coords, 3, axis=1)
171
+ deformed_nodes = coords + added_disp
172
+ return deformed_nodes
173
+
174
+
@@ -12,12 +12,12 @@ statistics and uncertainty bounds over simulated experiments.
12
12
  from typing import Any
13
13
  import numpy as np
14
14
  import matplotlib.pyplot as plt
15
- from pyvale.pyvaleexceptions import VisError
16
- from pyvale.visualopts import (PlotOptsGeneral,
15
+ from pyvale.sensorsim.exceptions import VisError
16
+ from pyvale.sensorsim.visualopts import (PlotOptsGeneral,
17
17
  TraceOptsExperiment,
18
18
  EExpVisBounds,
19
19
  EExpVisCentre)
20
- from pyvale.experimentsimulator import ExperimentSimulator
20
+ from pyvale.sensorsim.experimentsimulator import ExperimentSimulator
21
21
 
22
22
 
23
23
  def plot_exp_traces(exp_sim: ExperimentSimulator,
@@ -11,8 +11,8 @@ NOTE: this module is a feature under developement.
11
11
  from typing import Any
12
12
  import numpy as np
13
13
  import matplotlib.pyplot as plt
14
- from pyvale.camera import CameraBasic2D
15
- from pyvale.visualopts import PlotOptsGeneral
14
+ from pyvale.sensorsim.camera import CameraBasic2D
15
+ from pyvale.sensorsim.visualopts import PlotOptsGeneral
16
16
 
17
17
  # TODO: this only works for a 2D camera, maybe this should be deprecated
18
18
  def plot_measurement_image(camera: CameraBasic2D,
@@ -14,12 +14,12 @@ import numpy as np
14
14
  # See: https://github.com/pyvista/pyvista/discussions/2928
15
15
  #NOTE: causes output to console to be suppressed unfortunately
16
16
  import pyvista as pv
17
- from pyvale.sensorarraypoint import SensorArrayPoint
18
- from pyvale.visualopts import VisOptsSimSensors, VisOptsAnimation
19
- from pyvale.visualtools import (create_pv_plotter,
17
+ from pyvale.sensorsim.sensorarraypoint import SensorArrayPoint
18
+ from pyvale.sensorsim.visualopts import VisOptsSimSensors, VisOptsAnimation
19
+ from pyvale.sensorsim.visualtools import (create_pv_plotter,
20
20
  get_colour_lims,
21
21
  set_animation_writer)
22
- from pyvale.visualsimsensors import (add_sensor_points_nom,
22
+ from pyvale.sensorsim.visualsimsensors import (add_sensor_points_nom,
23
23
  add_sensor_points_pert,
24
24
  add_sim_field)
25
25
 
@@ -8,12 +8,12 @@
8
8
  #NOTE: causes output to console to be suppressed unfortunately
9
9
  import pyvista as pv
10
10
 
11
- import mooseherder as mh
11
+ import pyvale.mooseherder as mh
12
12
 
13
- from pyvale.sensorarraypoint import SensorArrayPoint
14
- from pyvale.fieldconverter import simdata_to_pyvista
15
- from pyvale.visualopts import (VisOptsSimSensors,VisOptsImageSave)
16
- from pyvale.visualtools import (create_pv_plotter,
13
+ from pyvale.sensorsim.sensorarraypoint import SensorArrayPoint
14
+ from pyvale.sensorsim.fieldconverter import simdata_to_pyvista
15
+ from pyvale.sensorsim.visualopts import (VisOptsSimSensors,VisOptsImageSave)
16
+ from pyvale.sensorsim.visualtools import (create_pv_plotter,
17
17
  get_colour_lims,
18
18
  save_image)
19
19
 
@@ -13,15 +13,16 @@ import vtk #NOTE: has to be here to fix latex bug in pyvista/vtk
13
13
  # See: https://github.com/pyvista/pyvista/discussions/2928
14
14
  #NOTE: causes output to console to be suppressed unfortunately
15
15
  #NOTE: May 2025, the console suppression output is fixed but the vtk import is
16
- #still required tro make latex work.
16
+ #still required to make latex work.
17
17
  import pyvista as pv
18
18
 
19
- import mooseherder as mh
19
+ import pyvale.mooseherder as mh
20
20
 
21
- from pyvale.sensorarraypoint import SensorArrayPoint
22
- from pyvale.fieldconverter import simdata_to_pyvista
23
- from pyvale.visualopts import (VisOptsSimSensors,VisOptsImageSave)
24
- from pyvale.visualtools import (create_pv_plotter,
21
+ from pyvale.sensorsim.sensorarraypoint import SensorArrayPoint
22
+ from pyvale.sensorsim.fieldconverter import (simdata_to_pyvista_vis,
23
+ simdata_to_pyvista_interp)
24
+ from pyvale.sensorsim.visualopts import (VisOptsSimSensors,VisOptsImageSave)
25
+ from pyvale.sensorsim.visualtools import (create_pv_plotter,
25
26
  get_colour_lims,
26
27
  save_pv_image)
27
28
 
@@ -195,9 +196,8 @@ def plot_sim_mesh(sim_data: mh.SimData,
195
196
  if vis_opts is None:
196
197
  vis_opts = VisOptsSimSensors()
197
198
 
198
- (_,sim_vis) = simdata_to_pyvista(sim_data=sim_data,
199
- components=None,
200
- elem_dims=elem_dims)
199
+ (_,sim_vis) = simdata_to_pyvista_vis(sim_data=sim_data,
200
+ elem_dims=elem_dims)
201
201
 
202
202
  pv_plot = create_pv_plotter(vis_opts)
203
203
  pv_plot.add_mesh(sim_vis,
@@ -240,9 +240,9 @@ def plot_sim_data(sim_data: mh.SimData,
240
240
  if vis_opts is None:
241
241
  vis_opts = VisOptsSimSensors()
242
242
 
243
- (_,sim_vis) = simdata_to_pyvista(sim_data,
244
- (component,),
245
- elem_dims)
243
+ (_,sim_vis) = simdata_to_pyvista_interp(sim_data,
244
+ (component,),
245
+ elem_dims)
246
246
 
247
247
  sim_vis[component] = sim_data.node_vars[component][:,time_step]
248
248
 
@@ -15,7 +15,7 @@ import vtk #NOTE: has to be here to fix latex bug in pyvista/vtk
15
15
  # NOTE: causes output to console to be suppressed unfortunately
16
16
  # NOTE: May2025 still needs include but does not suppress console output
17
17
  import pyvista as pv
18
- from pyvale.visualopts import (VisOptsSimSensors,
18
+ from pyvale.sensorsim.visualopts import (VisOptsSimSensors,
19
19
  VisOptsImageSave,
20
20
  EImageType,
21
21
  VisOptsAnimation,
@@ -7,8 +7,8 @@
7
7
  from typing import Any
8
8
  import numpy as np
9
9
  import matplotlib.pyplot as plt
10
- from pyvale.sensorarraypoint import SensorArrayPoint
11
- from pyvale.visualopts import (PlotOptsGeneral,
10
+ from pyvale.sensorsim.sensorarraypoint import SensorArrayPoint
11
+ from pyvale.sensorsim.visualopts import (PlotOptsGeneral,
12
12
  TraceOptsSensor)
13
13
 
14
14
 
@@ -16,6 +16,8 @@ Geometry.VolumeLabels = 0;
16
16
 
17
17
  //------------------------------------------------------------------------------
18
18
  // Variables
19
+
20
+ //_* MOOSEHERDER VARIABLES - START
19
21
  file_name = "case17.msh";
20
22
 
21
23
  // Geometric variables
@@ -35,6 +37,7 @@ plate_diff_nodes = 5; // numbers of nodes along the rectangular extension
35
37
  plate_edge_nodes = Floor((hole_sect_nodes-1)/2)+1;
36
38
  elem_size = hole_circ/(4*(hole_sect_nodes-1));
37
39
  tol = elem_size; // Used for bounding box selection tolerance
40
+ //** MOOSEHERDER VARIABLES - START
38
41
 
39
42
  //------------------------------------------------------------------------------
40
43
  // Geometry Definition
pyvale/simcases/case17.i CHANGED
@@ -13,8 +13,8 @@ timeStep = 1
13
13
  topDispRate = ${fparse 1.5e-3 / 60} # m/s
14
14
 
15
15
  # Material Properties: OFHC Copper 250degC
16
- cuEMod= 108e9 # Pa
17
- cuPRatio = 0.33 # -
16
+ EMod= 108e9 # Pa
17
+ PRatio = 0.33 # -
18
18
 
19
19
  #** MOOSEHERDER VARIABLES - END
20
20
  #-------------------------------------------------------------------------
@@ -71,8 +71,8 @@ cuPRatio = 0.33 # -
71
71
  [Materials]
72
72
  [elasticity]
73
73
  type = ComputeIsotropicElasticityTensor
74
- youngs_modulus = ${cuEMod}
75
- poissons_ratio = ${cuPRatio}
74
+ youngs_modulus = ${EMod}
75
+ poissons_ratio = ${PRatio}
76
76
  []
77
77
  [stress]
78
78
  type = ComputeFiniteStrainElasticStress
@@ -9,21 +9,13 @@ Copyright (C) 2025 The Computer Aided Validation Team
9
9
  import time
10
10
  from pathlib import Path
11
11
  from importlib.resources import files
12
- from mooseherder import (MooseConfig,
12
+ from pyvale.mooseherder import (MooseConfig,
13
13
  MooseRunner,
14
14
  GmshRunner)
15
15
 
16
16
  #===============================================================================
17
17
  # Change this to run a different case
18
- <<<<<<< HEAD
19
- <<<<<<< HEAD
20
- CASE_STR = 'case21'
21
- =======
22
- CASE_STR = 'case16'
23
- >>>>>>> deploy
24
- =======
25
18
  CASE_STR = 'case00_HEX27'
26
- >>>>>>> main
27
19
  #===============================================================================
28
20
 
29
21
  CASE_FILES = (CASE_STR+'.geo',CASE_STR+'.i')
@@ -8,7 +8,7 @@ Copyright (C) 2025 The Computer Aided Validation Team
8
8
  '''
9
9
  import time
10
10
  from pathlib import Path
11
- from mooseherder import (MooseConfig,
11
+ from pyvale.mooseherder import (MooseConfig,
12
12
  MooseRunner,
13
13
  GmshRunner)
14
14
 
@@ -9,7 +9,7 @@ Copyright (C) 2025 The Computer Aided Validation Team
9
9
  import time
10
10
  from pathlib import Path
11
11
  from importlib.resources import files
12
- from mooseherder import (MooseConfig,
12
+ from pyvale.mooseherder import (MooseConfig,
13
13
  MooseRunner,
14
14
  GmshRunner)
15
15
 
@@ -8,7 +8,7 @@ Copyright (C) 2025 The Computer Aided Validation Team
8
8
  '''
9
9
  import time
10
10
  from pathlib import Path
11
- from mooseherder import (MooseConfig,
11
+ from pyvale.mooseherder import (MooseConfig,
12
12
  MooseRunner,
13
13
  GmshRunner)
14
14
 
@@ -0,0 +1,12 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ from .analyticmeshgen import (rectangle_mesh_2d,
8
+ fill_dims_2d)
9
+ from .analyticsimdatafactory import (standard_case_2d,
10
+ AnalyticCaseFactory)
11
+ from .analyticsimdatagenerator import (AnalyticData2D,
12
+ AnalyticSimDataGen)
@@ -11,8 +11,8 @@ analytic functions for the physical fields.
11
11
 
12
12
  import numpy as np
13
13
  import sympy
14
- import mooseherder as mh
15
- from pyvale.analyticsimdatagenerator import (AnalyticData2D,
14
+ import pyvale.mooseherder as mh
15
+ from pyvale.verif.analyticsimdatagenerator import (AnalyticData2D,
16
16
  AnalyticSimDataGen)
17
17
 
18
18
 
@@ -12,8 +12,8 @@ underlying physical fields. Useful for testing pyvale.
12
12
  from dataclasses import dataclass
13
13
  import numpy as np
14
14
  import sympy
15
- import mooseherder as mh
16
- from pyvale.analyticmeshgen import rectangle_mesh_2d, fill_dims_2d
15
+ import pyvale.mooseherder as mh
16
+ from pyvale.verif.analyticmeshgen import rectangle_mesh_2d, fill_dims_2d
17
17
 
18
18
 
19
19
  @dataclass(slots=True)
pyvale/verif/psens.py ADDED
@@ -0,0 +1,125 @@
1
+ #===============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ #===============================================================================
6
+
7
+ """
8
+ DEVELOPER VERIFICATION MODULE
9
+ --------------------------------------------------------------------------------
10
+ This module contains developer utility functions used for verification testing
11
+ of the point sensor simulation toolbox in pyvale.
12
+
13
+ Specifically, this module contains generic functions used across all types of
14
+ point sensors.
15
+ """
16
+
17
+ import numpy as np
18
+ import pyvale.mooseherder as mh
19
+ import pyvale.sensorsim as sens
20
+ import pyvale.verif.psensconst as psensconst
21
+
22
+
23
+ def samp_times(sim_data: mh.SimData) -> dict[str, None | np.ndarray]:
24
+ sim_dims = sens.SimTools.get_sim_dims(sim_data)
25
+ sample_times = {}
26
+
27
+ sample_times["sim"] = None
28
+ sample_times["user"] = np.linspace(0.0,sim_dims["t"][1],50)
29
+
30
+ return sample_times
31
+
32
+
33
+ def sens_data_dict(sim_data: mh.SimData,
34
+ sens_pos: dict[str,np.ndarray]) -> dict[str,sens.SensorData]:
35
+ sample_times = samp_times(sim_data)
36
+
37
+ sens_data = {}
38
+ for pp in sens_pos:
39
+ for tt in sample_times:
40
+ tag = f"pos-{pp}_time-{tt}"
41
+ sens_data[tag] = sens.SensorData(
42
+ positions=sens_pos[pp],
43
+ sample_times=sample_times[tt],
44
+ )
45
+
46
+ return sens_data
47
+
48
+
49
+ def err_chain_basic() -> list[sens.IErrCalculator]:
50
+ chain_basic = []
51
+ chain_basic.append(sens.ErrSysOffset(offset=-1.0))
52
+ chain_basic.append(sens.ErrSysUnif(low=-1.0,
53
+ high=1.0,
54
+ seed=psensconst.GOLD_SEED))
55
+ chain_basic.append(sens.ErrSysUnifPercent(low_percent=-1.0,
56
+ high_percent=1.0,
57
+ seed=psensconst.GOLD_SEED))
58
+ chain_basic.append(sens.ErrRandNorm(std=1.0,
59
+ seed=psensconst.GOLD_SEED))
60
+ chain_basic.append(sens.ErrRandNormPercent(std_percent=1.0,
61
+ seed=psensconst.GOLD_SEED))
62
+ return chain_basic
63
+
64
+
65
+ def err_chain_gen() -> list[sens.IErrCalculator]:
66
+ chain_gen = []
67
+ chain_gen.append(sens.ErrSysOffset(offset=-1.0))
68
+ chain_gen.append(sens.ErrSysGen(
69
+ sens.GenUniform(low=-1.0,high=1.0,seed=psensconst.GOLD_SEED)))
70
+ chain_gen.append(sens.ErrSysGenPercent(
71
+ sens.GenUniform(low=-1.0,high=1.0,seed=psensconst.GOLD_SEED)))
72
+ chain_gen.append(sens.ErrRandGen(
73
+ sens.GenNormal(std=1.0,seed=psensconst.GOLD_SEED)))
74
+ chain_gen.append(sens.ErrRandGenPercent(
75
+ sens.GenNormal(std=1.0,seed=psensconst.GOLD_SEED)))
76
+ return chain_gen
77
+
78
+
79
+ def err_chain_dep() -> list[sens.IErrCalculator]:
80
+ chain_dep = []
81
+ chain_dep.append(sens.ErrSysRoundOff(sens.ERoundMethod.ROUND,0.1))
82
+ chain_dep.append(sens.ErrSysDigitisation(bits_per_unit=2**16/100))
83
+ chain_dep.append(sens.ErrSysSaturation(meas_min=0.0,meas_max=100.0))
84
+ return chain_dep
85
+
86
+
87
+ def err_chain_all(err_dict: dict[str,list[sens.IErrCalculator]]
88
+ ) -> list[sens.IErrCalculator]:
89
+ err_chain = []
90
+ for ee in err_dict:
91
+ if err_dict[ee] is not None:
92
+ for ss in err_dict[ee]:
93
+ err_chain.append(ss)
94
+ return err_chain
95
+
96
+
97
+ def gen_gold_measurements(sens_dict: dict[str,sens.SensorArrayPoint]) -> None:
98
+ for ss in sens_dict:
99
+ print(f"Generating gold output for case: {ss}")
100
+ measurements = sens_dict[ss].calc_measurements()
101
+ save_path = psensconst.GOLD_PATH / f"{ss}.npy"
102
+ np.save(save_path,measurements)
103
+
104
+
105
+ def check_gold_measurements(sens_dict: dict[str,sens.SensorArrayPoint]) -> list[str]:
106
+ fails = []
107
+
108
+ for ss in sens_dict:
109
+ measurements = sens_dict[ss].calc_measurements()
110
+ gold_path = psensconst.GOLD_PATH / f"{ss}.npy"
111
+
112
+ load_path = psensconst.GOLD_PATH / f"{ss.lower()}.npy"
113
+ if load_path.is_file():
114
+ gold = np.load(load_path)
115
+
116
+ if not np.allclose(measurements,gold):
117
+ fails.append(f"Gold check failed for: {ss}")
118
+ else:
119
+ fails.append(f"Gold file does not exist for: {ss}, path: {gold_path}")
120
+
121
+ return fails
122
+
123
+ def gen_gold_experiments(exp_sims: dict[str,sens.ExperimentSimulator]) -> None:
124
+ pass
125
+
@@ -0,0 +1,18 @@
1
+ #===============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ #===============================================================================
6
+ from pathlib import Path
7
+
8
+ """
9
+ DEVELOPER VERIFICATION MODULE
10
+ --------------------------------------------------------------------------------
11
+ This module contains developer utility functions used for verification testing
12
+ of the point sensor simulation toolbox in pyvale.
13
+
14
+ Specifically, this module contains constants used for verification testing.
15
+ """
16
+
17
+ GOLD_PATH: Path = Path.cwd() / "tests" / "sensorsim" / "gold"
18
+ GOLD_SEED: int = 123