pyvale 2025.7.1__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 (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/{dic2dcpp.cpython-311-aarch64-linux-musl.so → dic/dic2dcpp.cpython-311-aarch64-linux-musl.so} +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/sensorsim/cython/rastercyth.cpython-311-aarch64-linux-musl.so +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 +263 -0
  162. pyvale/cython/rastercyth.cpython-311-aarch64-linux-musl.so +0 -0
  163. pyvale/dataset.py +0 -415
  164. pyvale/dicdataimport.py +0 -247
  165. pyvale/simtools.py +0 -67
  166. pyvale-2025.7.1.dist-info/RECORD +0 -214
  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
@@ -28,32 +28,35 @@ to your error chain.
28
28
 
29
29
  import numpy as np
30
30
  import matplotlib.pyplot as plt
31
- import mooseherder as mh
32
- import pyvale as pyv
31
+
32
+ # Pyvale imports
33
+ import pyvale.mooseherder as mh
34
+ import pyvale.sensorsim as sens
35
+ import pyvale.dataset as dataset
33
36
 
34
37
 
35
38
  #%%
36
39
  # First we use everything we learned from the first three examples to build
37
40
  # a thermocouple sensor array for the same 3D thermal simulation we have
38
41
  # analysed in the previous example.
39
- data_path = pyv.DataSet.thermal_3d_path()
42
+ data_path = dataset.thermal_3d_path()
40
43
  sim_data = mh.ExodusReader(data_path).read_all_sim_data()
41
- sim_data = pyv.scale_length_units(scale=1000.0,
44
+ sim_data = sens.scale_length_units(scale=1000.0,
42
45
  sim_data=sim_data,
43
46
  disp_comps=None)
44
47
  n_sens = (1,4,1)
45
48
  x_lims = (12.5,12.5)
46
49
  y_lims = (0.0,33.0)
47
50
  z_lims = (0.0,12.0)
48
- sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
51
+ sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
49
52
 
50
53
  sample_times = np.linspace(0.0,np.max(sim_data.time),50) # | None
51
54
 
52
- sensor_data = pyv.SensorData(positions=sens_pos,
55
+ sensor_data = sens.SensorData(positions=sens_pos,
53
56
  sample_times=sample_times)
54
57
 
55
58
  field_key: str = "temperature"
56
- tc_array = pyv.SensorArrayFactory \
59
+ tc_array = sens.SensorArrayFactory \
57
60
  .thermocouples_no_errs(sim_data,
58
61
  sensor_data,
59
62
  elem_dims=3,
@@ -73,61 +76,61 @@ err_chain = []
73
76
  #
74
77
  # These systematic errors provide a constant offset to all measurements in
75
78
  # simulation units or as a percentage.
76
- err_chain.append(pyv.ErrSysOffset(offset=-10.0))
77
- err_chain.append(pyv.ErrSysOffsetPercent(offset_percent=-1.0))
79
+ err_chain.append(sens.ErrSysOffset(offset=-10.0))
80
+ err_chain.append(sens.ErrSysOffsetPercent(offset_percent=-1.0))
78
81
 
79
82
  #%%
80
83
  # These systematic errors are sampled from a uniform or normal probability
81
84
  # distribution either in simulation units or as a percentage.
82
- err_chain.append(pyv.ErrSysUnif(low=-1.0,
85
+ err_chain.append(sens.ErrSysUnif(low=-1.0,
83
86
  high=1.0))
84
- err_chain.append(pyv.ErrSysUnifPercent(low_percent=-1.0,
87
+ err_chain.append(sens.ErrSysUnifPercent(low_percent=-1.0,
85
88
  high_percent=1.0))
86
- err_chain.append(pyv.ErrSysNorm(std=1.0))
87
- err_chain.append(pyv.ErrSysNormPercent(std_percent=1.0))
89
+ err_chain.append(sens.ErrSysNorm(std=1.0))
90
+ err_chain.append(sens.ErrSysNormPercent(std_percent=1.0))
88
91
 
89
92
  #%%
90
93
  # pyvale includes a series of random number generator objects that wrap the
91
94
  # random number generators from numpy. These are named `Gen*` and can be
92
95
  # used with an `ErrSysGen` or an `ErrSysGenPercent` object to create custom
93
96
  # probability distribution sampling errors:
94
- sys_gen = pyv.GenTriangular(left=-1.0,
97
+ sys_gen = sens.GenTriangular(left=-1.0,
95
98
  mode=0.0,
96
99
  right=1.0)
97
- err_chain.append(pyv.ErrSysGen(sys_gen))
100
+ err_chain.append(sens.ErrSysGen(sys_gen))
98
101
 
99
102
  #%%
100
103
  # We can also build the equivalent of `ErrSysUnifPercent` above using a
101
104
  # `Gen` object inserted into an `ErrSysGenPercent` object:
102
- unif_gen = pyv.GenUniform(low=-1.0,
105
+ unif_gen = sens.GenUniform(low=-1.0,
103
106
  high=1.0)
104
- err_chain.append(pyv.ErrSysGenPercent(unif_gen))
107
+ err_chain.append(sens.ErrSysGenPercent(unif_gen))
105
108
 
106
109
  #%%
107
110
  # We can also add a series of random errors in a similar manner to the
108
111
  # systematic errors above noting that these will generate a new error for
109
112
  # each sensor and each time step whereas the systematic error sampling
110
113
  # provides a constant shift over all sampling times for each sensor.
111
- err_chain.append(pyv.ErrRandNorm(std = 2.0))
112
- err_chain.append(pyv.ErrRandNormPercent(std_percent=2.0))
113
- err_chain.append(pyv.ErrRandUnif(low=-2.0,high=2.0))
114
- err_chain.append(pyv.ErrRandUnifPercent(low_percent=-2.0,
114
+ err_chain.append(sens.ErrRandNorm(std = 2.0))
115
+ err_chain.append(sens.ErrRandNormPercent(std_percent=2.0))
116
+ err_chain.append(sens.ErrRandUnif(low=-2.0,high=2.0))
117
+ err_chain.append(sens.ErrRandUnifPercent(low_percent=-2.0,
115
118
  high_percent=2.0))
116
- rand_gen = pyv.GenTriangular(left=-5.0,
119
+ rand_gen = sens.GenTriangular(left=-5.0,
117
120
  mode=0.0,
118
121
  right=5.0)
119
- err_chain.append(pyv.ErrRandGenerator(rand_gen))
122
+ err_chain.append(sens.ErrRandGen(rand_gen))
120
123
 
121
124
  #%%
122
125
  # Finally we add some dependent systematic errors including rounding errors,
123
126
  # digitisation and saturation. Note that the saturation error must be placed
124
127
  # last in the error chain. Try changing some of these values to see how the
125
128
  # sensor traces change - particularly the saturation error.
126
- err_chain.append(pyv.ErrSysRoundOff(pyv.ERoundMethod.ROUND,0.1))
127
- err_chain.append(pyv.ErrSysDigitisation(bits_per_unit=2**16/100))
128
- err_chain.append(pyv.ErrSysSaturation(meas_min=0.0,meas_max=400.0))
129
+ err_chain.append(sens.ErrSysRoundOff(sens.ERoundMethod.ROUND,0.1))
130
+ err_chain.append(sens.ErrSysDigitisation(bits_per_unit=2**16/100))
131
+ err_chain.append(sens.ErrSysSaturation(meas_min=0.0,meas_max=400.0))
129
132
 
130
- err_int = pyv.ErrIntegrator(err_chain,
133
+ err_int = sens.ErrIntegrator(err_chain,
131
134
  sensor_data,
132
135
  tc_array.get_measurement_shape())
133
136
  tc_array.set_error_integrator(err_int)
@@ -148,10 +151,10 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
148
151
  print(f"These are the last {time_last} virtual measurements of sensor "
149
152
  + f"{sens_print}:")
150
153
 
151
- pyv.print_measurements(tc_array,sens_print,comp_print,time_print)
154
+ sens.print_measurements(tc_array,sens_print,comp_print,time_print)
152
155
 
153
156
  print(80*"-")
154
157
 
155
- pyv.plot_time_traces(tc_array,field_key)
158
+ sens.plot_time_traces(tc_array,field_key)
156
159
  plt.show()
157
160
 
@@ -24,8 +24,12 @@ Test case: Scalar field point sensors (thermocouples) on a 3D thermal simulation
24
24
  from pathlib import Path
25
25
  import numpy as np
26
26
  import matplotlib.pyplot as plt
27
- import mooseherder as mh
28
- import pyvale as pyv
27
+
28
+ # Pyvale imports
29
+ import pyvale.mooseherder as mh
30
+ import pyvale.sensorsim as sens
31
+ import pyvale.dataset as dataset
32
+
29
33
 
30
34
  #%%
31
35
  # First we use everything we learned from the first three examples to build
@@ -33,9 +37,9 @@ import pyvale as pyv
33
37
  # analysed in the previous examples. Then we will look at a new type of
34
38
  # systematic error called a field error which requires additional
35
39
  # interpolation of the underlying physical field to be measured.
36
- data_path = pyv.DataSet.thermal_3d_path()
40
+ data_path = dataset.thermal_3d_path()
37
41
  sim_data = mh.ExodusReader(data_path).read_all_sim_data()
38
- sim_data = pyv.scale_length_units(scale=1000.0,
42
+ sim_data = sens.scale_length_units(scale=1000.0,
39
43
  sim_data=sim_data,
40
44
  disp_comps=None)
41
45
 
@@ -43,15 +47,15 @@ n_sens = (1,4,1)
43
47
  x_lims = (12.5,12.5)
44
48
  y_lims = (0.0,33.0)
45
49
  z_lims = (0.0,12.0)
46
- sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
50
+ sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
47
51
 
48
52
  sample_times = np.linspace(0.0,np.max(sim_data.time),50) # | None
49
53
 
50
- sensor_data = pyv.SensorData(positions=sens_pos,
54
+ sensor_data = sens.SensorData(positions=sens_pos,
51
55
  sample_times=sample_times)
52
56
 
53
57
  field_key: str = "temperature"
54
- tc_array = pyv.SensorArrayFactory \
58
+ tc_array = sens.SensorArrayFactory \
55
59
  .thermocouples_no_errs(sim_data,
56
60
  sensor_data,
57
61
  elem_dims=3,
@@ -76,8 +80,8 @@ time_offset = np.full((sample_times.shape[0],),0.1)
76
80
  #%%
77
81
  # Using the `Gen*` random generators in pyvale we can randomly perturb the
78
82
  # position or sampling times of our virtual sensors.
79
- pos_rand = pyv.GenNormal(std=1.0) # units = mm
80
- time_rand = pyv.GenNormal(std=0.1) # units = s
83
+ pos_rand = sens.GenNormal(std=1.0) # units = mm
84
+ time_rand = sens.GenNormal(std=0.1) # units = s
81
85
 
82
86
  #%%
83
87
  # Now we put everything into our field error data class ready to build our
@@ -85,7 +89,7 @@ time_rand = pyv.GenNormal(std=0.1) # units = s
85
89
  # to geta feel for the other types of supported field errors. We will look
86
90
  # at the orientation and area averaging errors when we look at vector and
87
91
  # tensor fields in later examples.
88
- field_err_data = pyv.ErrFieldData(
92
+ field_err_data = sens.ErrFieldData(
89
93
  pos_offset_xyz=pos_offset_xyz,
90
94
  time_offset=time_offset,
91
95
  pos_rand_xyz=(None,pos_rand,pos_rand),
@@ -105,9 +109,9 @@ err_chain = []
105
109
  # A field error needs to know which field it should interpolate for error
106
110
  # calculations so we provide the field from the sensor array as well as the
107
111
  # field error error data class.
108
- err_chain.append(pyv.ErrSysField(tc_array.get_field(),
112
+ err_chain.append(sens.ErrSysField(tc_array.get_field(),
109
113
  field_err_data))
110
- err_int = pyv.ErrIntegrator(err_chain,
114
+ err_int = sens.ErrIntegrator(err_chain,
111
115
  sensor_data,
112
116
  tc_array.get_measurement_shape())
113
117
  tc_array.set_error_integrator(err_int)
@@ -128,7 +132,7 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
128
132
  print(f"These are the last {time_last} virtual measurements of sensor "
129
133
  + f"{sens_print}:")
130
134
 
131
- pyv.print_measurements(tc_array,sens_print,comp_print,time_print)
135
+ sens.print_measurements(tc_array,sens_print,comp_print,time_print)
132
136
 
133
137
  print(80*"-")
134
138
 
@@ -142,7 +146,7 @@ if not output_path.is_dir():
142
146
  #%%
143
147
  # If we analyse the time traces we can see offsets in the sensor value and
144
148
  # the sampling times which we expect from our field error setup.
145
- (fig,ax) = pyv.plot_time_traces(tc_array,field_key)
149
+ (fig,ax) = sens.plot_time_traces(tc_array,field_key)
146
150
 
147
151
  save_traces = output_path/"field_ex1_5_sensortraces.png"
148
152
  fig.savefig(save_traces, dpi=300, bbox_inches="tight")
@@ -153,7 +157,7 @@ plt.show()
153
157
  #%%
154
158
  # It is also possible to view the perturbed sensor locations on the
155
159
  # simulation mesh if we create a plot after running the sensor simulation.
156
- pv_plot = pyv.plot_point_sensors_on_sim(tc_array,field_key)
160
+ pv_plot = sens.plot_point_sensors_on_sim(tc_array,field_key)
157
161
  pv_plot.camera_position = [(59.354, 43.428, 69.946),
158
162
  (-2.858, 13.189, 4.523),
159
163
  (-0.215, 0.948, -0.233)]
@@ -16,8 +16,12 @@ Test case: Scalar field point sensors (thermocouples) on a 2D thermal simulation
16
16
 
17
17
  import numpy as np
18
18
  import matplotlib.pyplot as plt
19
- import mooseherder as mh
20
- import pyvale as pyv
19
+
20
+ # Pyvale imports
21
+ import pyvale.mooseherder as mh
22
+ import pyvale.sensorsim as sens
23
+ import pyvale.dataset as dataset
24
+
21
25
 
22
26
  #%%
23
27
  # First we need to define some calibration functions. These functions must take
@@ -27,11 +31,11 @@ import pyvale as pyv
27
31
  # we can calculate the error between them. The calibration functions shown below
28
32
  # are simplified versions of the typical calibration curves for a K-type
29
33
  # thermocouple.
30
- def assumed_calib(signal: np.ndarray) -> np.ndarray:
34
+ def calib_assumed(signal: np.ndarray) -> np.ndarray:
31
35
  return 24.3*signal + 0.616
32
36
 
33
37
 
34
- def truth_calib(signal: np.ndarray) -> np.ndarray:
38
+ def calib_truth(signal: np.ndarray) -> np.ndarray:
35
39
  return -0.01897 + 25.41881*signal - 0.42456*signal**2 + 0.04365*signal**3
36
40
 
37
41
 
@@ -46,8 +50,8 @@ signal_calib_range = np.array((0.0,6.0),dtype=np.float64)
46
50
  milli_volts = np.linspace(signal_calib_range[0],
47
51
  signal_calib_range[1],
48
52
  n_cal_divs)
49
- temp_truth = truth_calib(milli_volts)
50
- temp_assumed = assumed_calib(milli_volts)
53
+ temp_truth = calib_truth(milli_volts)
54
+ temp_assumed = calib_assumed(milli_volts)
51
55
  calib_error = temp_assumed - temp_truth
52
56
 
53
57
  print()
@@ -66,9 +70,9 @@ print()
66
70
  # Now let's go back and build the 2D thermal plate with simulated
67
71
  # thermocouples that we analysed in the first two examples. We use this
68
72
  # simulation as the temperatures are within our calibrated range.
69
- data_path = pyv.DataSet.thermal_2d_path()
73
+ data_path = dataset.thermal_2d_path()
70
74
  sim_data = mh.ExodusReader(data_path).read_all_sim_data()
71
- sim_data = pyv.scale_length_units(scale=1000.0,
75
+ sim_data = sens.scale_length_units(scale=1000.0,
72
76
  sim_data=sim_data,
73
77
  disp_comps=None)
74
78
 
@@ -76,15 +80,15 @@ n_sens = (4,1,1)
76
80
  x_lims = (0.0,100.0)
77
81
  y_lims = (0.0,50.0)
78
82
  z_lims = (0.0,0.0)
79
- sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
83
+ sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
80
84
 
81
85
  sample_times = np.linspace(0.0,np.max(sim_data.time),50) # | None
82
86
 
83
- sensor_data = pyv.SensorData(positions=sens_pos,
87
+ sensor_data = sens.SensorData(positions=sens_pos,
84
88
  sample_times=sample_times)
85
89
 
86
90
  field_key: str = "temperature"
87
- tc_array = pyv.SensorArrayFactory \
91
+ tc_array = sens.SensorArrayFactory \
88
92
  .thermocouples_no_errs(sim_data,
89
93
  sensor_data,
90
94
  elem_dims=2,
@@ -96,11 +100,11 @@ tc_array = pyv.SensorArrayFactory \
96
100
  # that the truth calibration function must be inverted numerically so to
97
101
  # increase accuracy the number of divisions can be increased. However, 1e4
98
102
  # divisions should be suitable for most applications.
99
- cal_err = pyv.ErrSysCalibration(assumed_calib,
100
- truth_calib,
103
+ cal_err = sens.ErrSysCalibration(calib_assumed,
104
+ calib_truth,
101
105
  signal_calib_range,
102
106
  n_cal_divs=10000)
103
- sys_err_int = pyv.ErrIntegrator([cal_err],
107
+ sys_err_int = sens.ErrIntegrator([cal_err],
104
108
  sensor_data,
105
109
  tc_array.get_measurement_shape())
106
110
  tc_array.set_error_integrator(sys_err_int)
@@ -119,10 +123,10 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
119
123
  print(f"These are the last {time_last} virtual measurements of sensor "
120
124
  + f"{sens_print}:")
121
125
 
122
- pyv.print_measurements(tc_array,sens_print,comp_print,time_print)
126
+ sens.print_measurements(tc_array,sens_print,comp_print,time_print)
123
127
 
124
128
  print(80*"-")
125
129
 
126
- pyv.plot_time_traces(tc_array,field_key)
130
+ sens.plot_time_traces(tc_array,field_key)
127
131
  plt.show()
128
132
 
@@ -16,8 +16,11 @@ Test case: Scalar field point sensors (thermocouples) on a 2D thermal simulation
16
16
 
17
17
  import numpy as np
18
18
  import matplotlib.pyplot as plt
19
- import mooseherder as mh
20
- import pyvale as pyv
19
+
20
+ # Pyvale imports
21
+ import pyvale.mooseherder as mh
22
+ import pyvale.sensorsim as sens
23
+ import pyvale.dataset as dataset
21
24
 
22
25
  #%%
23
26
  # First we are going to build a custom sensor array so we can control how
@@ -29,16 +32,16 @@ import pyvale as pyv
29
32
  # area averaged without and area averaging error. The first part of this is
30
33
  # the same as the 3D thermal example we have used previously then we control
31
34
  # the area averaging using the sensor data object.
32
- data_path = pyv.DataSet.thermal_2d_path()
35
+ data_path = dataset.thermal_2d_path()
33
36
  sim_data = mh.ExodusReader(data_path).read_all_sim_data()
34
- sim_data = pyv.scale_length_units(scale=1000.0,
37
+ sim_data = sens.scale_length_units(scale=1000.0,
35
38
  sim_data=sim_data,
36
39
  disp_comps=None)
37
40
 
38
- descriptor = pyv.SensorDescriptorFactory.temperature_descriptor()
41
+ descriptor = sens.SensorDescriptorFactory.temperature_descriptor()
39
42
 
40
43
  field_key = "temperature"
41
- t_field = pyv.FieldScalar(sim_data,
44
+ t_field = sens.FieldScalar(sim_data,
42
45
  field_key=field_key,
43
46
  elem_dims=2)
44
47
 
@@ -46,7 +49,7 @@ n_sens = (4,1,1)
46
49
  x_lims = (0.0,100.0)
47
50
  y_lims = (0.0,50.0)
48
51
  z_lims = (0.0,0.0)
49
- sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
52
+ sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
50
53
 
51
54
  sample_times = np.linspace(0.0,np.max(sim_data.time),50) # | None
52
55
 
@@ -59,15 +62,15 @@ sample_times = np.linspace(0.0,np.max(sim_data.time),50) # | None
59
62
  # additional integration point requires an additional interpolation of the
60
63
  # physical field.
61
64
  sensor_dims = np.array([20.0,20.0,0]) # units = mm
62
- sensor_data = pyv.SensorData(positions=sens_pos,
65
+ sensor_data = sens.SensorData(positions=sens_pos,
63
66
  sample_times=sample_times,
64
- spatial_averager=pyv.EIntSpatialType.QUAD4PT,
67
+ spatial_averager=sens.EIntSpatialType.QUAD4PT,
65
68
  spatial_dims=sensor_dims)
66
69
 
67
70
  #%%
68
71
  # We have added spatial averaging to our sensor data so we can now create
69
72
  # our sensor array as we have done in previous examples.
70
- tc_array = pyv.SensorArrayPoint(sensor_data,
73
+ tc_array = sens.SensorArrayPoint(sensor_data,
71
74
  t_field,
72
75
  descriptor)
73
76
 
@@ -75,8 +78,8 @@ tc_array = pyv.SensorArrayPoint(sensor_data,
75
78
  # We are also going to create a field error that includes area averaging as
76
79
  # an error. We do this by adding the option to our field error data class
77
80
  # specifying rectangular integration with 1 point.
78
- area_avg_err_data = pyv.ErrFieldData(
79
- spatial_averager=pyv.EIntSpatialType.RECT1PT,
81
+ area_avg_err_data = sens.ErrFieldData(
82
+ spatial_averager=sens.EIntSpatialType.RECT1PT,
80
83
  spatial_dims=np.array((5.0,5.0)),
81
84
  )
82
85
 
@@ -85,9 +88,9 @@ area_avg_err_data = pyv.ErrFieldData(
85
88
  # with any of our other error models but we will isolate it for now so we
86
89
  # can see what it does.
87
90
  err_chain = []
88
- err_chain.append(pyv.ErrSysField(t_field,
91
+ err_chain.append(sens.ErrSysField(t_field,
89
92
  area_avg_err_data))
90
- error_int = pyv.ErrIntegrator(err_chain,
93
+ error_int = sens.ErrIntegrator(err_chain,
91
94
  sensor_data,
92
95
  tc_array.get_measurement_shape())
93
96
  tc_array.set_error_integrator(error_int)
@@ -107,11 +110,11 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
107
110
  print(f"These are the last {time_last} virtual measurements of sensor "
108
111
  + f"{sens_print}:")
109
112
 
110
- pyv.print_measurements(tc_array,sens_print,comp_print,time_print)
113
+ sens.print_measurements(tc_array,sens_print,comp_print,time_print)
111
114
 
112
115
  print(80*"-")
113
116
 
114
- pyv.plot_time_traces(tc_array,field_key)
117
+ sens.plot_time_traces(tc_array,field_key)
115
118
  plt.show()
116
119
 
117
120
  #%%
@@ -20,8 +20,11 @@ Test case: point displacement sensors on a 2D plate with hole loaded in tension
20
20
  """
21
21
 
22
22
  import matplotlib.pyplot as plt
23
- import mooseherder as mh
24
- import pyvale as pyv
23
+
24
+ # Pyvale imports
25
+ import pyvale.mooseherder as mh
26
+ import pyvale.sensorsim as sens
27
+ import pyvale.dataset as dataset
25
28
 
26
29
  #%%
27
30
  # Here we load a pre-packaged dataset from pyvale that is the output of a
@@ -29,7 +32,7 @@ import pyvale as pyv
29
32
  # rectangular plate with a central hole that is loaded in tension (we will
30
33
  # see a visualisation of the mesh and results later). We use `mooseherder` to
31
34
  # load the exodus file into a `SimData` object.
32
- data_path = pyv.DataSet.mechanical_2d_path()
35
+ data_path = dataset.mechanical_2d_path()
33
36
  sim_data = mh.ExodusReader(data_path).read_all_sim_data()
34
37
 
35
38
  #%%
@@ -38,7 +41,7 @@ sim_data = mh.ExodusReader(data_path).read_all_sim_data()
38
41
  # the variable names you have in your SimData object.
39
42
  field_name = "disp"
40
43
  field_comps = ("disp_x","disp_y")
41
- sim_data = pyv.scale_length_units(scale=1000.0,
44
+ sim_data = sens.scale_length_units(scale=1000.0,
42
45
  sim_data=sim_data,
43
46
  disp_comps=field_comps)
44
47
 
@@ -53,11 +56,11 @@ n_sens = (2,3,1)
53
56
  x_lims = (0.0,100.0)
54
57
  y_lims = (0.0,150.0)
55
58
  z_lims = (0.0,0.0)
56
- sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
59
+ sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
57
60
 
58
- sens_data = pyv.SensorData(positions=sens_pos)
61
+ sens_data = sens.SensorData(positions=sens_pos)
59
62
 
60
- disp_sens_array = pyv.SensorArrayFactory \
63
+ disp_sens_array = sens.SensorArrayFactory \
61
64
  .disp_sensors_basic_errs(sim_data,
62
65
  sens_data,
63
66
  elem_dims=2,
@@ -92,7 +95,7 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
92
95
  print(f"These are the last {time_last} virtual measurements of sensor "
93
96
  + f"{sens_print}:")
94
97
 
95
- pyv.print_measurements(disp_sens_array,sens_print,comp_print,time_print)
98
+ sens.print_measurements(disp_sens_array,sens_print,comp_print,time_print)
96
99
 
97
100
  print(80*"-")
98
101
 
@@ -101,13 +104,13 @@ print(80*"-")
101
104
  # simulation mesh and visulise the sensor locations with respect to these
102
105
  # fields.
103
106
  for ff in field_comps:
104
- pv_plot = pyv.plot_point_sensors_on_sim(disp_sens_array,ff)
107
+ pv_plot = sens.plot_point_sensors_on_sim(disp_sens_array,ff)
105
108
  pv_plot.show(cpos="xy")
106
109
 
107
110
  #%%
108
111
  # We can also plot the traces for each component of the displacement field.
109
112
  for ff in field_comps:
110
- pyv.plot_time_traces(disp_sens_array,ff)
113
+ sens.plot_time_traces(disp_sens_array,ff)
111
114
 
112
115
  plt.show()
113
116
 
@@ -19,18 +19,22 @@ Test case: point displacement sensors on a 2D plate with hole loaded in tension
19
19
 
20
20
  import numpy as np
21
21
  import matplotlib.pyplot as plt
22
- import mooseherder as mh
23
- import pyvale as pyv
22
+
23
+ # Pyvale imports
24
+ import pyvale.mooseherder as mh
25
+ import pyvale.sensorsim as sens
26
+ import pyvale.dataset as dataset
27
+
24
28
 
25
29
 
26
30
  #%%
27
31
  # First we load the same 2D solid mechanics simulation we had previously as
28
32
  # a `SimData` object and then we scale everything to millimeters.
29
- data_path = pyv.DataSet.mechanical_2d_path()
33
+ data_path = dataset.mechanical_2d_path()
30
34
  sim_data = mh.ExodusReader(data_path).read_all_sim_data()
31
35
  field_name = "disp"
32
36
  field_comps = ("disp_x","disp_y")
33
- sim_data = pyv.scale_length_units(scale=1000.0,
37
+ sim_data = sens.scale_length_units(scale=1000.0,
34
38
  sim_data=sim_data,
35
39
  disp_comps=field_comps)
36
40
 
@@ -45,25 +49,25 @@ sim_data = pyv.scale_length_units(scale=1000.0,
45
49
  # parameter does not need to match the number of field components. For
46
50
  # example: it is possible to have a surface mesh (elem_dims=2) where we
47
51
  # have all 3 components of the displacement field.
48
- disp_field = pyv.FieldVector(sim_data,field_name,field_comps,elem_dims=2)
52
+ disp_field = sens.FieldVector(sim_data,field_name,field_comps,elem_dims=2)
49
53
 
50
54
  #%%
51
55
  # As we saw previously for scalar fields we define our sensor data object
52
56
  # which determines how many point sensors we have and their sampling times.
53
57
  # For vector field sensors we can also define the sensor orientation here
54
58
  # which we will demonstrate in the next example.
55
- n_sens = (2,3,1)
59
+ n_sens = (1,4,1)
56
60
  x_lims = (0.0,100.0)
57
61
  y_lims = (0.0,150.0)
58
62
  z_lims = (0.0,0.0)
59
- sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
63
+ sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
60
64
 
61
65
  #%%
62
66
  # We set custom sampling times here but we could also set this to None so
63
67
  # that the sensors sample at the simulation time steps.
64
68
  sample_times = np.linspace(0.0,np.max(sim_data.time),50)
65
69
 
66
- sens_data = pyv.SensorData(positions=sens_pos,
70
+ sens_data = sens.SensorData(positions=sens_pos,
67
71
  sample_times=sample_times)
68
72
 
69
73
  #%%
@@ -71,7 +75,7 @@ sens_data = pyv.SensorData(positions=sens_pos,
71
75
  # sensor which will be used for labelling sensor placement visualisation or
72
76
  # for time traces. It is also possible to use the sensor descriptor factory
73
77
  # to get the same sensor descriptor object with these defaults.
74
- descriptor = pyv.SensorDescriptor(name="Disp.",
78
+ descriptor = sens.SensorDescriptor(name="Disp.",
75
79
  symbol=r"u",
76
80
  units=r"mm",
77
81
  tag="DS",
@@ -81,7 +85,7 @@ descriptor = pyv.SensorDescriptor(name="Disp.",
81
85
  # The point sensor array class is generic and will take any field class
82
86
  # that implements the field interface. So here we just pass in the vector
83
87
  # field to create our vector field sensor array.
84
- disp_sens_array = pyv.SensorArrayPoint(sens_data,
88
+ disp_sens_array = sens.SensorArrayPoint(sens_data,
85
89
  disp_field,
86
90
  descriptor)
87
91
 
@@ -91,9 +95,9 @@ disp_sens_array = pyv.SensorArrayPoint(sens_data,
91
95
  # the next example we will look at some field errors to do with sensor
92
96
  # orientation that
93
97
  error_chain = []
94
- error_chain.append(pyv.ErrSysUnif(low=-0.01,high=0.01)) # units = mm
95
- error_chain.append(pyv.ErrRandNorm(std=0.01)) # units = mm
96
- error_int = pyv.ErrIntegrator(error_chain,
98
+ error_chain.append(sens.ErrSysUnif(low=-0.01,high=0.01)) # units = mm
99
+ error_chain.append(sens.ErrRandNorm(std=0.01)) # units = mm
100
+ error_int = sens.ErrIntegrator(error_chain,
97
101
  sens_data,
98
102
  disp_sens_array.get_measurement_shape())
99
103
  disp_sens_array.set_error_integrator(error_int)
@@ -105,13 +109,13 @@ disp_sens_array.calc_measurements()
105
109
  # simulation mesh and visulise the sensor locations with respect to these
106
110
  # fields.
107
111
  for ff in field_comps:
108
- pv_plot = pyv.plot_point_sensors_on_sim(disp_sens_array,ff)
112
+ pv_plot = sens.plot_point_sensors_on_sim(disp_sens_array,ff)
109
113
  pv_plot.show(cpos="xy")
110
114
 
111
115
  #%%
112
116
  # We can also plot the traces for each component of the displacement field.
113
117
  for ff in field_comps:
114
- pyv.plot_time_traces(disp_sens_array,ff)
118
+ sens.plot_time_traces(disp_sens_array,ff)
115
119
 
116
120
  plt.show()
117
121