pyvale 2025.4.0__py3-none-any.whl → 2025.5.1__py3-none-any.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 (153) hide show
  1. pyvale/__init__.py +78 -64
  2. pyvale/analyticmeshgen.py +102 -0
  3. pyvale/{core/analyticsimdatafactory.py → analyticsimdatafactory.py} +44 -16
  4. pyvale/analyticsimdatagenerator.py +323 -0
  5. pyvale/blendercalibrationdata.py +15 -0
  6. pyvale/blenderlightdata.py +26 -0
  7. pyvale/blendermaterialdata.py +15 -0
  8. pyvale/blenderrenderdata.py +30 -0
  9. pyvale/blenderscene.py +488 -0
  10. pyvale/blendertools.py +420 -0
  11. pyvale/{core/camera.py → camera.py} +15 -15
  12. pyvale/{core/cameradata.py → cameradata.py} +27 -22
  13. pyvale/{core/cameradata2d.py → cameradata2d.py} +8 -6
  14. pyvale/camerastereo.py +217 -0
  15. pyvale/{core/cameratools.py → cameratools.py} +220 -26
  16. pyvale/{core/cython → cython}/rastercyth.py +11 -7
  17. pyvale/data/__init__.py +5 -7
  18. pyvale/data/cal_target.tiff +0 -0
  19. pyvale/data/case00_HEX20_out.e +0 -0
  20. pyvale/data/case00_HEX27_out.e +0 -0
  21. pyvale/data/case00_HEX8_out.e +0 -0
  22. pyvale/data/case00_TET10_out.e +0 -0
  23. pyvale/data/case00_TET14_out.e +0 -0
  24. pyvale/data/case00_TET4_out.e +0 -0
  25. pyvale/{core/dataset.py → dataset.py} +91 -16
  26. pyvale/{core/errorcalculator.py → errorcalculator.py} +13 -16
  27. pyvale/{core/errordriftcalc.py → errordriftcalc.py} +14 -14
  28. pyvale/{core/errorintegrator.py → errorintegrator.py} +25 -28
  29. pyvale/{core/errorrand.py → errorrand.py} +39 -46
  30. pyvale/errorsyscalib.py +134 -0
  31. pyvale/{core/errorsysdep.py → errorsysdep.py} +25 -29
  32. pyvale/{core/errorsysfield.py → errorsysfield.py} +59 -52
  33. pyvale/{core/errorsysindep.py → errorsysindep.py} +85 -182
  34. pyvale/examples/__init__.py +5 -7
  35. pyvale/examples/basics/ex1_1_basicscalars_therm2d.py +131 -0
  36. pyvale/examples/basics/ex1_2_sensormodel_therm2d.py +158 -0
  37. pyvale/examples/basics/ex1_3_customsens_therm3d.py +216 -0
  38. pyvale/examples/basics/ex1_4_basicerrors_therm3d.py +153 -0
  39. pyvale/examples/basics/ex1_5_fielderrs_therm3d.py +168 -0
  40. pyvale/examples/basics/ex1_6_caliberrs_therm2d.py +133 -0
  41. pyvale/examples/basics/ex1_7_spatavg_therm2d.py +123 -0
  42. pyvale/examples/basics/ex2_1_basicvectors_disp2d.py +112 -0
  43. pyvale/examples/basics/ex2_2_vectorsens_disp2d.py +111 -0
  44. pyvale/examples/basics/ex2_3_sensangle_disp2d.py +139 -0
  45. pyvale/examples/basics/ex2_4_chainfielderrs_disp2d.py +196 -0
  46. pyvale/examples/basics/ex2_5_vectorfields3d_disp3d.py +109 -0
  47. pyvale/examples/basics/ex3_1_basictensors_strain2d.py +114 -0
  48. pyvale/examples/basics/ex3_2_tensorsens2d_strain2d.py +111 -0
  49. pyvale/examples/basics/ex3_3_tensorsens3d_strain3d.py +182 -0
  50. pyvale/examples/basics/ex4_1_expsim2d_thermmech2d.py +171 -0
  51. pyvale/examples/basics/ex4_2_expsim3d_thermmech3d.py +252 -0
  52. pyvale/examples/{analyticdatagen → genanalyticdata}/ex1_1_scalarvisualisation.py +6 -9
  53. pyvale/examples/{analyticdatagen → genanalyticdata}/ex1_2_scalarcasebuild.py +8 -11
  54. pyvale/examples/{analyticdatagen → genanalyticdata}/ex2_1_analyticsensors.py +9 -12
  55. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +8 -15
  56. pyvale/examples/renderblender/ex1_1_blenderscene.py +121 -0
  57. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +119 -0
  58. pyvale/examples/renderblender/ex2_1_stereoscene.py +128 -0
  59. pyvale/examples/renderblender/ex2_2_stereodeformed.py +131 -0
  60. pyvale/examples/renderblender/ex3_1_blendercalibration.py +120 -0
  61. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastenp.py +6 -7
  62. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_oneframe.py +5 -7
  63. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_static_cypara.py +6 -13
  64. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_static_pypara.py +9 -12
  65. pyvale/examples/{ex1_4_thermal2d.py → visualisation/ex1_1_plot_traces.py} +33 -20
  66. pyvale/examples/{features/ex_animation_tools_3dmonoblock.py → visualisation/ex2_1_animate_sim.py} +37 -31
  67. pyvale/experimentsimulator.py +175 -0
  68. pyvale/{core/field.py → field.py} +6 -14
  69. pyvale/fieldconverter.py +351 -0
  70. pyvale/{core/fieldsampler.py → fieldsampler.py} +9 -10
  71. pyvale/{core/fieldscalar.py → fieldscalar.py} +17 -18
  72. pyvale/{core/fieldtensor.py → fieldtensor.py} +23 -26
  73. pyvale/{core/fieldtransform.py → fieldtransform.py} +9 -5
  74. pyvale/{core/fieldvector.py → fieldvector.py} +14 -16
  75. pyvale/{core/generatorsrandom.py → generatorsrandom.py} +29 -52
  76. pyvale/{core/imagedef2d.py → imagedef2d.py} +11 -8
  77. pyvale/{core/integratorfactory.py → integratorfactory.py} +12 -13
  78. pyvale/{core/integratorquadrature.py → integratorquadrature.py} +57 -32
  79. pyvale/integratorrectangle.py +165 -0
  80. pyvale/{core/integratorspatial.py → integratorspatial.py} +9 -10
  81. pyvale/{core/integratortype.py → integratortype.py} +7 -8
  82. pyvale/output.py +17 -0
  83. pyvale/pyvaleexceptions.py +11 -0
  84. pyvale/{core/raster.py → raster.py} +8 -8
  85. pyvale/{core/rastercy.py → rastercy.py} +11 -10
  86. pyvale/{core/rasternp.py → rasternp.py} +12 -13
  87. pyvale/{core/rendermesh.py → rendermesh.py} +10 -19
  88. pyvale/{core/sensorarray.py → sensorarray.py} +7 -8
  89. pyvale/{core/sensorarrayfactory.py → sensorarrayfactory.py} +64 -78
  90. pyvale/{core/sensorarraypoint.py → sensorarraypoint.py} +39 -41
  91. pyvale/{core/sensordata.py → sensordata.py} +7 -8
  92. pyvale/sensordescriptor.py +213 -0
  93. pyvale/{core/sensortools.py → sensortools.py} +8 -9
  94. pyvale/simcases/case00_HEX20.i +5 -5
  95. pyvale/simcases/case00_HEX27.i +5 -5
  96. pyvale/simcases/case00_HEX8.i +242 -0
  97. pyvale/simcases/case00_TET10.i +2 -2
  98. pyvale/simcases/case00_TET14.i +2 -2
  99. pyvale/simcases/case00_TET4.i +242 -0
  100. pyvale/simcases/run_1case.py +1 -1
  101. pyvale/simtools.py +67 -0
  102. pyvale/visualexpplotter.py +191 -0
  103. pyvale/{core/visualimagedef.py → visualimagedef.py} +13 -10
  104. pyvale/{core/visualimages.py → visualimages.py} +10 -9
  105. pyvale/visualopts.py +493 -0
  106. pyvale/{core/visualsimanimator.py → visualsimanimator.py} +47 -19
  107. pyvale/visualsimsensors.py +318 -0
  108. pyvale/visualtools.py +136 -0
  109. pyvale/visualtraceplotter.py +142 -0
  110. {pyvale-2025.4.0.dist-info → pyvale-2025.5.1.dist-info}/METADATA +17 -14
  111. pyvale-2025.5.1.dist-info/RECORD +172 -0
  112. {pyvale-2025.4.0.dist-info → pyvale-2025.5.1.dist-info}/WHEEL +1 -1
  113. pyvale/core/__init__.py +0 -7
  114. pyvale/core/analyticmeshgen.py +0 -59
  115. pyvale/core/analyticsimdatagenerator.py +0 -160
  116. pyvale/core/cython/rastercyth.c +0 -32267
  117. pyvale/core/experimentsimulator.py +0 -99
  118. pyvale/core/fieldconverter.py +0 -154
  119. pyvale/core/integratorrectangle.py +0 -88
  120. pyvale/core/optimcheckfuncs.py +0 -153
  121. pyvale/core/sensordescriptor.py +0 -101
  122. pyvale/core/visualexpplotter.py +0 -151
  123. pyvale/core/visualopts.py +0 -180
  124. pyvale/core/visualsimplotter.py +0 -182
  125. pyvale/core/visualtools.py +0 -81
  126. pyvale/core/visualtraceplotter.py +0 -256
  127. pyvale/examples/analyticdatagen/__init__.py +0 -7
  128. pyvale/examples/ex1_1_thermal2d.py +0 -89
  129. pyvale/examples/ex1_2_thermal2d.py +0 -111
  130. pyvale/examples/ex1_3_thermal2d.py +0 -113
  131. pyvale/examples/ex1_5_thermal2d.py +0 -105
  132. pyvale/examples/ex2_1_thermal3d .py +0 -87
  133. pyvale/examples/ex2_2_thermal3d.py +0 -51
  134. pyvale/examples/ex2_3_thermal3d.py +0 -109
  135. pyvale/examples/ex3_1_displacement2d.py +0 -47
  136. pyvale/examples/ex3_2_displacement2d.py +0 -79
  137. pyvale/examples/ex3_3_displacement2d.py +0 -104
  138. pyvale/examples/ex3_4_displacement2d.py +0 -105
  139. pyvale/examples/ex4_1_strain2d.py +0 -57
  140. pyvale/examples/ex4_2_strain2d.py +0 -79
  141. pyvale/examples/ex4_3_strain2d.py +0 -100
  142. pyvale/examples/ex5_1_multiphysics2d.py +0 -78
  143. pyvale/examples/ex6_1_multiphysics2d_expsim.py +0 -118
  144. pyvale/examples/ex6_2_multiphysics3d_expsim.py +0 -158
  145. pyvale/examples/features/__init__.py +0 -7
  146. pyvale/examples/features/ex_area_avg.py +0 -89
  147. pyvale/examples/features/ex_calibration_error.py +0 -108
  148. pyvale/examples/features/ex_chain_field_errs.py +0 -141
  149. pyvale/examples/features/ex_field_errs.py +0 -78
  150. pyvale/examples/features/ex_sensor_single_angle_batch.py +0 -110
  151. pyvale-2025.4.0.dist-info/RECORD +0 -157
  152. {pyvale-2025.4.0.dist-info → pyvale-2025.5.1.dist-info}/licenses/LICENSE +0 -0
  153. {pyvale-2025.4.0.dist-info → pyvale-2025.5.1.dist-info}/top_level.txt +0 -0
@@ -1,79 +0,0 @@
1
- '''
2
- ================================================================================
3
- Example: strain gauges on a 2d plate
4
-
5
- pyvale: the python validation engine
6
- License: MIT
7
- Copyright (C) 2025 The Computer Aided Validation Team
8
- ================================================================================
9
- '''
10
- import numpy as np
11
- import matplotlib.pyplot as plt
12
- import mooseherder as mh
13
- import pyvale as pyv
14
-
15
- def main() -> None:
16
- """pyvale example: strain sensors on a 2D plate with a hole
17
- ----------------------------------------------------------------------------
18
- """
19
- data_path = pyv.DataSet.mechanical_2d_path()
20
- sim_data = mh.ExodusReader(data_path).read_all_sim_data()
21
- # Scale to mm to make 3D visualisation scaling easier
22
- sim_data.coords = sim_data.coords*1000.0 # type: ignore
23
-
24
- descriptor = pyv.SensorDescriptor()
25
- descriptor.name = 'Strain'
26
- descriptor.symbol = r'\varepsilon'
27
- descriptor.units = r'-'
28
- descriptor.tag = 'SG'
29
- descriptor.components = ('xx','yy','xy')
30
-
31
- spat_dims = 2
32
- field_key = 'strain'
33
- norm_components = ('strain_xx','strain_yy')
34
- dev_components = ('strain_xy',)
35
- strain_field = pyv.FieldTensor(sim_data,
36
- field_key,
37
- norm_components,
38
- dev_components,
39
- spat_dims)
40
-
41
- n_sens = (2,3,1)
42
- x_lims = (0.0,100.0)
43
- y_lims = (0.0,150.0)
44
- z_lims = (0.0,0.0)
45
- sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
46
-
47
- use_sim_time = False
48
- if use_sim_time:
49
- sample_times = None
50
- else:
51
- sample_times = np.linspace(0.0,np.max(sim_data.time),50)
52
-
53
- sens_data = pyv.SensorData(positions=sens_pos,
54
- sample_times=sample_times)
55
-
56
- straingauge_array = pyv.SensorArrayPoint(sens_data,
57
- strain_field,
58
- descriptor)
59
-
60
- error_chain = []
61
- error_chain.append(pyv.ErrSysUniform(low=-0.1e-3,high=0.1e-3))
62
- error_chain.append(pyv.ErrRandNormal(std=0.1e-3))
63
- error_int = pyv.ErrIntegrator(error_chain,
64
- sens_data,
65
- straingauge_array.get_measurement_shape())
66
- straingauge_array.set_error_integrator(error_int)
67
-
68
- plot_field = 'strain_yy'
69
- pv_plot = pyv.plot_point_sensors_on_sim(straingauge_array,plot_field)
70
- pv_plot.show(cpos="xy")
71
-
72
- pyv.plot_time_traces(straingauge_array,'strain_xx')
73
- pyv.plot_time_traces(straingauge_array,'strain_yy')
74
- pyv.plot_time_traces(straingauge_array,'strain_xy')
75
- plt.show()
76
-
77
-
78
- if __name__ == "__main__":
79
- main()
@@ -1,100 +0,0 @@
1
- '''
2
- ================================================================================
3
- Example: strain sensors on a 2d plate
4
-
5
- pyvale: the python validation engine
6
- License: MIT
7
- Copyright (C) 2025 The Computer Aided Validation Team
8
- ================================================================================
9
- '''
10
- import numpy as np
11
- import matplotlib.pyplot as plt
12
- from scipy.spatial.transform import Rotation as R
13
- import mooseherder as mh
14
- import pyvale as pyv
15
-
16
- def main() -> None:
17
- """pyvale example: strain sensors on a 2D plate with a hole
18
- ----------------------------------------------------------------------------
19
- - Demonstrates rotation of tensor fields
20
- """
21
- data_path = pyv.DataSet.mechanical_2d_path()
22
- sim_data = mh.ExodusReader(data_path).read_all_sim_data()
23
- # Scale to mm to make 3D visualisation scaling easier
24
- sim_data.coords = sim_data.coords*1000.0 # type: ignore
25
-
26
- descriptor = pyv.SensorDescriptorFactory.strain_descriptor()
27
-
28
- spat_dims = 2
29
- field_key = 'strain'
30
- norm_components = ('strain_xx','strain_yy')
31
- dev_components = ('strain_xy',)
32
- strain_field = pyv.FieldTensor(sim_data,
33
- field_key,
34
- norm_components,
35
- dev_components,
36
- spat_dims)
37
-
38
- n_sens = (2,3,1)
39
- x_lims = (0.0,100.0)
40
- y_lims = (0.0,150.0)
41
- z_lims = (0.0,0.0)
42
- sensor_positions = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
43
-
44
- use_sim_time = False
45
- if use_sim_time:
46
- sample_times = None
47
- else:
48
- sample_times = np.linspace(0.0,np.max(sim_data.time),50)
49
-
50
- sens_data_norot = pyv.SensorData(positions=sensor_positions,
51
- sample_times=sample_times)
52
-
53
- sg_array_norot = pyv.SensorArrayPoint(sens_data_norot,
54
- strain_field,
55
- descriptor)
56
-
57
- meas_norot = sg_array_norot.get_measurements()
58
-
59
- sens_angles = sensor_positions.shape[0] * \
60
- (R.from_euler("zyx", [45, 0, 0], degrees=True),)
61
-
62
- sens_data_rot = pyv.SensorData(positions=sensor_positions,
63
- sample_times=sample_times,
64
- angles=sens_angles)
65
-
66
- sg_array_rot = pyv.SensorArrayPoint(sens_data_rot,
67
- strain_field,
68
- descriptor)
69
-
70
- angle_offset = np.zeros_like(sensor_positions)
71
- angle_offset[:,0] = 1.0 # only rotate about z in 2D
72
- angle_error_data = pyv.ErrFieldData(ang_offset_zyx=angle_offset)
73
-
74
- sys_err_rot = pyv.ErrSysField(strain_field,angle_error_data)
75
- err_int = pyv.ErrIntegrator([sys_err_rot],
76
- sens_data_rot,
77
- sg_array_rot.get_measurement_shape())
78
- sg_array_rot.set_error_integrator(err_int)
79
-
80
-
81
- meas_rot = sg_array_rot.get_measurements()
82
-
83
-
84
- print(80*'-')
85
- sens_num = 4
86
- print('The last 5 time steps (measurements) of sensor {sens_num}:')
87
- pyv.print_measurements(sg_array_rot,
88
- (sens_num-1,sens_num),
89
- (1,2),
90
- (meas_rot.shape[2]-5,meas_rot.shape[2]))
91
- print(80*'-')
92
-
93
- plot_comp = 'strain_yy'
94
- pyv.plot_time_traces(sg_array_norot,plot_comp)
95
- pyv.plot_time_traces(sg_array_rot,plot_comp)
96
- plt.show()
97
-
98
-
99
- if __name__ == "__main__":
100
- main()
@@ -1,78 +0,0 @@
1
- '''
2
- ================================================================================
3
- Example: thermo-mechanical multiphysics on 2D plate
4
-
5
- pyvale: the python validation engine
6
- License: MIT
7
- Copyright (C) 2025 The Computer Aided Validation Team
8
- ================================================================================
9
- '''
10
- import numpy as np
11
- import matplotlib.pyplot as plt
12
- import mooseherder as mh
13
- import pyvale as pyv
14
-
15
-
16
- def main() -> None:
17
- """pyvale example: thermo-mechanical multi-physics sensors on a 2D plate
18
- ----------------------------------------------------------------------------
19
- """
20
- #===========================================================================
21
- # Load Simulations as mooseherder.SimData objects
22
- data_path = pyv.DataSet.thermomechanical_2d_path()
23
- sim_data = mh.ExodusReader(data_path).read_all_sim_data()
24
- # Scale to mm to make 3D visualisation scaling easier
25
- sim_data.coords = sim_data.coords*1000.0 # type: ignore
26
-
27
- #===========================================================================
28
- # Specify sensor locations and sample times
29
- n_sens = (4,1,1)
30
- x_lims = (0.0,100.0)
31
- y_lims = (0.0,50.0)
32
- z_lims = (0.0,0.0)
33
- sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
34
-
35
- use_sim_time = True
36
- if use_sim_time:
37
- sample_times = None
38
- else:
39
- sample_times = np.linspace(0.0,np.max(sim_data.time),50)
40
-
41
- sens_data = pyv.SensorData(positions=sens_pos,
42
- sample_times=sample_times)
43
-
44
- #===========================================================================
45
- # Create pyvale sensor arrays for thermal and mechanical data
46
- tc_field = 'temperature'
47
- tc_array = pyv.SensorArrayFactory \
48
- .thermocouples_basic_errs(sim_data,
49
- sens_data,
50
- tc_field,
51
- spat_dims=2)
52
-
53
- sg_field = 'strain'
54
- sg_array = pyv.SensorArrayFactory \
55
- .strain_gauges_basic_errs(sim_data,
56
- sens_data,
57
- sg_field,
58
- spat_dims=2)
59
-
60
- #===========================================================================
61
- # Visualise Traces
62
- print(80*'-')
63
- sens_num = 4
64
- print('THERMAL: The last 5 time steps (measurements) of sensor {sens_num}:')
65
- pyv.print_measurements(tc_array,
66
- (sens_num-1,sens_num),
67
- (0,1),
68
- (tc_array.get_measurement_shape()[2]-5,
69
- tc_array.get_measurement_shape()[2]))
70
- print(80*'-')
71
-
72
- pyv.plot_time_traces(tc_array,"temperature")
73
- pyv.plot_time_traces(sg_array,"strain_xx")
74
- plt.show()
75
-
76
-
77
- if __name__ == "__main__":
78
- main()
@@ -1,118 +0,0 @@
1
- '''
2
- ================================================================================
3
- Example: thermo-mechanical multiphysics on a 2D plate
4
-
5
- pyvale: the python validation engine
6
- License: MIT
7
- Copyright (C) 2025 The Computer Aided Validation Team
8
- ================================================================================
9
- '''
10
- import numpy as np
11
- import matplotlib.pyplot as plt
12
- import mooseherder as mh
13
- import pyvale as pyv
14
-
15
- def main() -> None:
16
- """pyvale example: thermo-mechanical multi-physics sensors on a 2D plate
17
- ----------------------------------------------------------------------------
18
- - Demonstrates the experiment module for running many monte-carlo style
19
- experiments and statistically analysing the results.
20
- """
21
- # Load Simulations as mooseherder.SimData objects
22
- #base_path = Path("src/pyvale/data")
23
- data_paths = pyv.DataSet.thermomechanical_2d_experiment_paths()
24
-
25
- sim_list = []
26
- for pp in data_paths:
27
- sim_data = mh.ExodusReader(pp).read_all_sim_data()
28
- # Scale to mm to make 3D visualisation scaling easier
29
- sim_data.coords = sim_data.coords*1000.0 # type: ignore
30
- sim_list.append(sim_data)
31
-
32
- #===========================================================================
33
- # Create pyvale sensor arrays for thermal and mechanical data
34
- sim_data = sim_list[0]
35
-
36
- n_sens = (4,1,1)
37
- x_lims = (0.0,100.0)
38
- y_lims = (0.0,50.0)
39
- z_lims = (0.0,0.0)
40
- sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
41
-
42
- use_sim_time = True
43
- if use_sim_time:
44
- sample_times = None
45
- else:
46
- sample_times = np.linspace(0.0,np.max(sim_data.time),50)
47
-
48
- sens_data = pyv.SensorData(positions=sens_pos,
49
- sample_times=sample_times)
50
-
51
- tc_field = 'temperature'
52
- tc_array = pyv.SensorArrayFactory \
53
- .thermocouples_basic_errs(sim_data,
54
- sens_data,
55
- tc_field,
56
- spat_dims=2,
57
- errs_pc=1.0)
58
-
59
- sg_field = 'strain'
60
- sg_array = pyv.SensorArrayFactory \
61
- .strain_gauges_basic_errs(sim_data,
62
- sens_data,
63
- sg_field,
64
- spat_dims=2,
65
- errs_pc=1.0)
66
-
67
- sensor_arrays = [tc_array,sg_array]
68
-
69
- #===========================================================================
70
- # Create and run the simulated experiment
71
- exp_sim = pyv.ExperimentSimulator(sim_list,
72
- sensor_arrays,
73
- num_exp_per_sim=1000)
74
-
75
- exp_data = exp_sim.run_experiments()
76
- exp_stats = exp_sim.calc_stats()
77
-
78
- #===========================================================================
79
- print(80*"=")
80
- print("exp_data and exp_stats are lists where the index is the sensor array")
81
- print("position in the list as field components are not consistent dims.\n")
82
-
83
- print(80*"-")
84
- print("Thermal sensor array @ exp_data[0]")
85
- print(80*"-")
86
- print("shape=(n_sims,n_exps,n_sensors,n_field_comps,n_time_steps)")
87
- print(f"{exp_data[0].shape=}")
88
- print()
89
- print("Stats are calculated over all experiments (axis=1)")
90
- print("shape=(n_sims,n_sensors,n_field_comps,n_time_steps)")
91
- print(f"{exp_stats[0].max.shape=}")
92
- print()
93
- print(80*"-")
94
- print("Mechanical sensor array @ exp_data[1]")
95
- print(80*"-")
96
- print("shape=(n_sims,n_exps,n_sensors,n_field_comps,n_time_steps)")
97
- print(f"{exp_data[1].shape=}")
98
- print()
99
- print("shape=(n_sims,n_sensors,n_field_comps,n_time_steps)")
100
- print(f"{exp_stats[1].max.shape=}")
101
- print(80*"=")
102
-
103
- #===========================================================================
104
- # VISUALISE RESULTS
105
- (fig,ax) = pyv.plot_exp_traces(exp_sim,
106
- component="temperature",
107
- sens_array_num=0,
108
- sim_num=0)
109
-
110
- (fig,ax) = pyv.plot_exp_traces(exp_sim,
111
- component="strain_yy",
112
- sens_array_num=1,
113
- sim_num=2)
114
- plt.show()
115
-
116
-
117
- if __name__ == "__main__":
118
- main()
@@ -1,158 +0,0 @@
1
- '''
2
- ================================================================================
3
- Example: thermo-mechanical multiphysics on a divertor armour heatsink
4
-
5
- pyvale: the python validation engine
6
- License: MIT
7
- Copyright (C) 2025 The Computer Aided Validation Team
8
- ================================================================================
9
- '''
10
- from pathlib import Path
11
- import numpy as np
12
- import matplotlib.pyplot as plt
13
- import mooseherder as mh
14
- import pyvale as pyv
15
-
16
- def main() -> None:
17
- """pyvale example: 3D thermo-mechanical with thermocouples & strain gauges
18
- ----------------------------------------------------------------------------
19
- """
20
- # Load Simulations as mooseherder.SimData objects
21
- sim_path = pyv.DataSet.thermomechanical_3d_path()
22
- sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
23
-
24
- # Scale to mm to make 3D visualisation scaling easier
25
- sim_data.coords = sim_data.coords*1000.0
26
- pyv.print_dimensions(sim_data)
27
-
28
- sim_list = [sim_data]
29
-
30
- use_sim_time = True
31
- if use_sim_time:
32
- sample_times = None
33
- else:
34
- sample_times = np.linspace(0.0,np.max(sim_data.time),50)
35
-
36
- save_tag = "thermomech3d"
37
- fig_save_path = Path.cwd()/"images"
38
- if not fig_save_path.is_dir():
39
- fig_save_path.mkdir(parents=True, exist_ok=True)
40
-
41
- #---------------------------------------------------------------------------
42
- # Create the thermocouple array
43
- x_lims = (12.5,12.5)
44
- y_lims = (0.0,33.0)
45
- z_lims = (0.0,12.0)
46
- n_sens = (1,4,1)
47
- tc_sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
48
-
49
- tc_sens_data = pyv.SensorData(positions=tc_sens_pos,
50
- sample_times=sample_times)
51
-
52
- tc_field = "temperature"
53
- tc_array = pyv.SensorArrayFactory \
54
- .thermocouples_basic_errs(sim_data,
55
- tc_sens_data,
56
- tc_field,
57
- spat_dims=3,
58
- errs_pc=1.0)
59
-
60
- # Visualise the thermocouple locations:
61
- pv_plot = pyv.plot_point_sensors_on_sim(tc_array,"temperature")
62
- pv_plot.camera_position = [(59.354, 43.428, 69.946),
63
- (-2.858, 13.189, 4.523),
64
- (-0.215, 0.948, -0.233)]
65
- pv_plot.save_graphic(fig_save_path/(save_tag+"_tc_vis.svg"))
66
- pv_plot.show()
67
-
68
- #---------------------------------------------------------------------------
69
- # Create the strain gauge array
70
- x_lims = (9.4,9.4)
71
- y_lims = (0.0,33.0)
72
- z_lims = (12.0,12.0)
73
- n_sens = (1,4,1)
74
- sg_sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
75
-
76
- sg_sens_data = pyv.SensorData(positions=sg_sens_pos,
77
- sample_times=sample_times)
78
-
79
-
80
- sg_field = "strain"
81
- sg_array = pyv.SensorArrayFactory \
82
- .strain_gauges_basic_errs(sim_data,
83
- sg_sens_data,
84
- sg_field,
85
- spat_dims=3,
86
- errs_pc=1.0)
87
-
88
- # Visualise the strain gauge locations:
89
- pv_plot = pyv.plot_point_sensors_on_sim(sg_array,"strain_yy")
90
- pv_plot.camera_position = [(59.354, 43.428, 69.946),
91
- (-2.858, 13.189, 4.523),
92
- (-0.215, 0.948, -0.233)]
93
- pv_plot.save_graphic(fig_save_path/(save_tag+"_sg_vis.svg"))
94
- pv_plot.show()
95
-
96
- #---------------------------------------------------------------------------
97
- # Create and run the simulated experiment
98
- sensor_arrays = [tc_array,sg_array]
99
-
100
- exp_sim = pyv.ExperimentSimulator(sim_list,
101
- sensor_arrays,
102
- num_exp_per_sim=100)
103
-
104
- exp_data = exp_sim.run_experiments()
105
- exp_stats = exp_sim.calc_stats()
106
-
107
- #---------------------------------------------------------------------------
108
- print(80*"=")
109
- print("exp_data and exp_stats are lists where the index is the sensor array")
110
- print("position in the list as field components are not consistent dims:")
111
- print(f"{len(exp_data)=}")
112
- print(f"{len(exp_stats)=}")
113
- print()
114
-
115
- print(80*"-")
116
- print("Thermal sensor array @ exp_data[0]")
117
- print(80*"-")
118
- print("shape=(n_sims,n_exps,n_sensors,n_field_comps,n_time_steps)")
119
- print(f"{exp_data[0].shape=}")
120
- print()
121
- print("Stats are calculated over all experiments (axis=1)")
122
- print("shape=(n_sims,n_sensors,n_field_comps,n_time_steps)")
123
- print(f"{exp_stats[0].max.shape=}")
124
- print()
125
- print(80*"-")
126
- print("Mechanical sensor array @ exp_data[1]")
127
- print(80*"-")
128
- print("shape=(n_sims,n_exps,n_sensors,n_field_comps,n_time_steps)")
129
- print(f"{exp_data[1].shape=}")
130
- print()
131
- print("shape=(n_sims,n_sensors,n_field_comps,n_time_steps)")
132
- print(f"{exp_stats[1].max.shape=}")
133
- print(80*"=")
134
-
135
- #---------------------------------------------------------------------------
136
- # Visualise all sensor traces over all experiments
137
- trace_opts = pyv.TraceOptsExperiment(plot_all_exp_points=True)
138
-
139
- (fig,ax) = pyv.plot_exp_traces(exp_sim,
140
- component="temperature",
141
- sens_array_num=0,
142
- sim_num=0,
143
- trace_opts=trace_opts)
144
- fig.savefig(fig_save_path/(save_tag+"_tc_traces.png"),
145
- dpi=300, format='png', bbox_inches='tight')
146
-
147
- (fig,ax) = pyv.plot_exp_traces(exp_sim,
148
- component="strain_yy",
149
- sens_array_num=1,
150
- sim_num=0,
151
- trace_opts=trace_opts)
152
- fig.savefig(fig_save_path/(save_tag+"_sg_traces.png"),
153
- dpi=300, format='png', bbox_inches='tight')
154
- plt.show()
155
-
156
-
157
- if __name__ == "__main__":
158
- main()
@@ -1,7 +0,0 @@
1
- """
2
- ================================================================================
3
- pyvale: the python validation engine
4
- License: MIT
5
- Copyright (C) 2025 The Computer Aided Validation Team
6
- ================================================================================
7
- """
@@ -1,89 +0,0 @@
1
- """
2
- ================================================================================
3
- example: thermocouples on a 2d plate
4
-
5
- pyvale: the python validation engine
6
- License: MIT
7
- Copyright (C) 2025 The Computer Aided Validation Team
8
- ================================================================================
9
- """
10
- import numpy as np
11
- import matplotlib.pyplot as plt
12
- import mooseherder as mh
13
- import pyvale
14
-
15
-
16
- def main() -> None:
17
- """pyvale example: thermocouples on a 2d plate
18
- ----------------------------------------------------------------------------
19
- - Demonstrates area averaging for truth and for systematic errors
20
- """
21
- data_path = pyvale.DataSet.thermal_2d_path()
22
- sim_data = mh.ExodusReader(data_path).read_all_sim_data()
23
- # Scale to mm to make 3D visualisation scaling easier
24
- sim_data.coords = sim_data.coords*1000.0 # type: ignore
25
-
26
- descriptor = pyvale.SensorDescriptorFactory.temperature_descriptor()
27
-
28
- field_key = "temperature"
29
- t_field = pyvale.FieldScalar(sim_data,
30
- field_key=field_key,
31
- spat_dims=2)
32
-
33
- n_sens = (4,1,1)
34
- x_lims = (0.0,100.0)
35
- y_lims = (0.0,50.0)
36
- z_lims = (0.0,0.0)
37
- sens_pos = pyvale.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
38
-
39
- use_sim_time = True
40
- if use_sim_time:
41
- sample_times = None
42
- else:
43
- sample_times = np.linspace(0.0,np.max(sim_data.time),50)
44
-
45
- sensor_dims = np.array([10.0,10.0,0])
46
- sensor_data = pyvale.SensorData(positions=sens_pos,
47
- sample_times=sample_times,
48
- spatial_averager=pyvale.EIntSpatialType.QUAD4PT,
49
- spatial_dims=sensor_dims)
50
-
51
- tc_array = pyvale.SensorArrayPoint(sensor_data,
52
- t_field,
53
- descriptor)
54
-
55
- area_avg_err_data = pyvale.ErrFieldData(
56
- spatial_averager=pyvale.EIntSpatialType.RECT1PT,
57
- spatial_dims=sensor_dims
58
- )
59
- err_chain = []
60
- err_chain.append(pyvale.ErrSysField(t_field,
61
- area_avg_err_data))
62
- error_int = pyvale.ErrIntegrator(err_chain,
63
- sensor_data,
64
- tc_array.get_measurement_shape())
65
- tc_array.set_error_integrator(error_int)
66
-
67
- measurements = tc_array.get_measurements()
68
-
69
- print("\n"+80*"-")
70
- print("For a sensor: measurement = truth + sysematic error + random error")
71
- print(f"measurements.shape = {measurements.shape} = "+
72
- "(n_sensors,n_field_components,n_timesteps)\n")
73
- print("The truth, systematic error and random error arrays have the same "+
74
- "shape.")
75
-
76
- print(80*"-")
77
- print("Looking at the last 5 time steps (measurements) of sensor 0:")
78
- pyvale.print_measurements(tc_array,
79
- (0,1),
80
- (0,1),
81
- (0,10))
82
- print(80*"-")
83
-
84
- pyvale.plot_time_traces(tc_array,field_key)
85
- plt.show()
86
-
87
-
88
- if __name__ == "__main__":
89
- main()