pyvale 2025.7.2__cp311-cp311-musllinux_1_2_i686.whl → 2025.8.1__cp311-cp311-musllinux_1_2_i686.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 (176) hide show
  1. pyvale/__init__.py +12 -92
  2. pyvale/blender/__init__.py +23 -0
  3. pyvale/{pyvaleexceptions.py → blender/blenderexceptions.py} +0 -3
  4. pyvale/{blenderlightdata.py → blender/blenderlightdata.py} +3 -3
  5. pyvale/{blendermaterialdata.py → blender/blendermaterialdata.py} +1 -1
  6. pyvale/{blenderrenderdata.py → blender/blenderrenderdata.py} +5 -3
  7. pyvale/{blenderscene.py → blender/blenderscene.py} +33 -30
  8. pyvale/{blendertools.py → blender/blendertools.py} +14 -10
  9. pyvale/dataset/__init__.py +7 -0
  10. pyvale/dataset/dataset.py +443 -0
  11. pyvale/dic/__init__.py +20 -0
  12. pyvale/{dic2d.py → dic/dic2d.py} +31 -36
  13. pyvale/dic/dic2dconv.py +6 -0
  14. pyvale/{dic2dcpp.cpython-311-i386-linux-musl.so → dic/dic2dcpp.cpython-311-i386-linux-musl.so} +0 -0
  15. pyvale/{dicdataimport.py → dic/dicdataimport.py} +8 -8
  16. pyvale/{dicregionofinterest.py → dic/dicregionofinterest.py} +1 -1
  17. pyvale/{dicresults.py → dic/dicresults.py} +1 -1
  18. pyvale/{dicstrain.py → dic/dicstrain.py} +9 -9
  19. pyvale/examples/basics/{ex1_1_basicscalars_therm2d.py → ex1a_basicscalars_therm2d.py} +12 -9
  20. pyvale/examples/basics/{ex1_2_sensormodel_therm2d.py → ex1b_sensormodel_therm2d.py} +17 -14
  21. pyvale/examples/basics/{ex1_3_customsens_therm3d.py → ex1c_customsens_therm3d.py} +27 -24
  22. pyvale/examples/basics/{ex1_4_basicerrors_therm3d.py → ex1d_basicerrors_therm3d.py} +32 -29
  23. pyvale/examples/basics/{ex1_5_fielderrs_therm3d.py → ex1e_fielderrs_therm3d.py} +19 -15
  24. pyvale/examples/basics/{ex1_6_caliberrs_therm2d.py → ex1f_caliberrs_therm2d.py} +20 -16
  25. pyvale/examples/basics/{ex1_7_spatavg_therm2d.py → ex1g_spatavg_therm2d.py} +19 -16
  26. pyvale/examples/basics/{ex2_1_basicvectors_disp2d.py → ex2a_basicvectors_disp2d.py} +13 -10
  27. pyvale/examples/basics/{ex2_2_vectorsens_disp2d.py → ex2b_vectorsens_disp2d.py} +19 -15
  28. pyvale/examples/basics/{ex2_3_sensangle_disp2d.py → ex2c_sensangle_disp2d.py} +21 -18
  29. pyvale/examples/basics/{ex2_4_chainfielderrs_disp2d.py → ex2d_chainfielderrs_disp2d.py} +31 -29
  30. pyvale/examples/basics/{ex2_5_vectorfields3d_disp3d.py → ex2e_vectorfields3d_disp3d.py} +21 -18
  31. pyvale/examples/basics/{ex3_1_basictensors_strain2d.py → ex3a_basictensors_strain2d.py} +16 -14
  32. pyvale/examples/basics/{ex3_2_tensorsens2d_strain2d.py → ex3b_tensorsens2d_strain2d.py} +17 -14
  33. pyvale/examples/basics/{ex3_3_tensorsens3d_strain3d.py → ex3c_tensorsens3d_strain3d.py} +25 -22
  34. pyvale/examples/basics/{ex4_1_expsim2d_thermmech2d.py → ex4a_expsim2d_thermmech2d.py} +17 -14
  35. pyvale/examples/basics/{ex4_2_expsim3d_thermmech3d.py → ex4b_expsim3d_thermmech3d.py} +37 -34
  36. pyvale/examples/basics/ex5_nomesh.py +24 -0
  37. pyvale/examples/dic/ex1_2_blenderdeformed.py +174 -0
  38. pyvale/examples/dic/ex1_region_of_interest.py +6 -3
  39. pyvale/examples/dic/ex2_plate_with_hole.py +21 -18
  40. pyvale/examples/dic/ex3_plate_with_hole_strain.py +8 -6
  41. pyvale/examples/dic/ex4_dic_blender.py +17 -15
  42. pyvale/examples/dic/ex5_dic_challenge.py +19 -14
  43. pyvale/examples/genanalyticdata/ex1_1_scalarvisualisation.py +16 -10
  44. pyvale/examples/genanalyticdata/ex1_2_scalarcasebuild.py +3 -3
  45. pyvale/examples/genanalyticdata/ex2_1_analyticsensors.py +29 -23
  46. pyvale/examples/genanalyticdata/ex2_2_analyticsensors_nomesh.py +67 -0
  47. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +12 -9
  48. pyvale/examples/mooseherder/ex0_create_moose_config.py +65 -0
  49. pyvale/examples/mooseherder/ex1a_modify_moose_input.py +71 -0
  50. pyvale/examples/mooseherder/ex1b_modify_gmsh_input.py +69 -0
  51. pyvale/examples/mooseherder/ex2a_run_moose_once.py +80 -0
  52. pyvale/examples/mooseherder/ex2b_run_gmsh_once.py +64 -0
  53. pyvale/examples/mooseherder/ex2c_run_both_once.py +114 -0
  54. pyvale/examples/mooseherder/ex3_run_moose_seq_para.py +157 -0
  55. pyvale/examples/mooseherder/ex4_run_gmsh-moose_seq_para.py +176 -0
  56. pyvale/examples/mooseherder/ex5_run_moose_paramulti.py +136 -0
  57. pyvale/examples/mooseherder/ex6_read_moose_exodus.py +163 -0
  58. pyvale/examples/mooseherder/ex7a_read_moose_herd_results.py +153 -0
  59. pyvale/examples/mooseherder/ex7b_read_multi_herd_results.py +116 -0
  60. pyvale/examples/mooseherder/ex7c_read_multi_gmshmoose_results.py +127 -0
  61. pyvale/examples/mooseherder/ex7d_readconfig_multi_gmshmoose_results.py +143 -0
  62. pyvale/examples/mooseherder/ex8_read_existing_sweep_output.py +72 -0
  63. pyvale/examples/renderblender/ex1_1_blenderscene.py +24 -20
  64. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +22 -18
  65. pyvale/examples/renderblender/ex2_1_stereoscene.py +36 -29
  66. pyvale/examples/renderblender/ex2_2_stereodeformed.py +26 -20
  67. pyvale/examples/renderblender/ex3_1_blendercalibration.py +24 -17
  68. pyvale/examples/renderrasterisation/ex_rastenp.py +14 -12
  69. pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +14 -15
  70. pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +13 -11
  71. pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +13 -11
  72. pyvale/mooseherder/__init__.py +32 -0
  73. pyvale/mooseherder/directorymanager.py +416 -0
  74. pyvale/mooseherder/exodusreader.py +763 -0
  75. pyvale/mooseherder/gmshrunner.py +163 -0
  76. pyvale/mooseherder/inputmodifier.py +236 -0
  77. pyvale/mooseherder/mooseconfig.py +226 -0
  78. pyvale/mooseherder/mooseherd.py +527 -0
  79. pyvale/mooseherder/mooserunner.py +303 -0
  80. pyvale/mooseherder/outputreader.py +22 -0
  81. pyvale/mooseherder/simdata.py +92 -0
  82. pyvale/mooseherder/simrunner.py +31 -0
  83. pyvale/mooseherder/sweepreader.py +356 -0
  84. pyvale/mooseherder/sweeptools.py +76 -0
  85. pyvale/sensorsim/__init__.py +82 -0
  86. pyvale/{camera.py → sensorsim/camera.py} +7 -7
  87. pyvale/{camerasensor.py → sensorsim/camerasensor.py} +7 -7
  88. pyvale/{camerastereo.py → sensorsim/camerastereo.py} +2 -2
  89. pyvale/{cameratools.py → sensorsim/cameratools.py} +4 -4
  90. pyvale/{cython → sensorsim/cython}/rastercyth.c +596 -596
  91. pyvale/{cython → sensorsim/cython}/rastercyth.cpython-311-i386-linux-musl.so +0 -0
  92. pyvale/{cython → sensorsim/cython}/rastercyth.py +16 -17
  93. pyvale/{errorcalculator.py → sensorsim/errorcalculator.py} +1 -1
  94. pyvale/{errorintegrator.py → sensorsim/errorintegrator.py} +2 -2
  95. pyvale/{errorrand.py → sensorsim/errorrand.py} +4 -4
  96. pyvale/{errorsyscalib.py → sensorsim/errorsyscalib.py} +2 -2
  97. pyvale/{errorsysdep.py → sensorsim/errorsysdep.py} +2 -2
  98. pyvale/{errorsysfield.py → sensorsim/errorsysfield.py} +8 -8
  99. pyvale/{errorsysindep.py → sensorsim/errorsysindep.py} +3 -3
  100. pyvale/sensorsim/exceptions.py +8 -0
  101. pyvale/{experimentsimulator.py → sensorsim/experimentsimulator.py} +23 -3
  102. pyvale/{field.py → sensorsim/field.py} +1 -1
  103. pyvale/{fieldconverter.py → sensorsim/fieldconverter.py} +72 -19
  104. pyvale/sensorsim/fieldinterp.py +37 -0
  105. pyvale/sensorsim/fieldinterpmesh.py +124 -0
  106. pyvale/sensorsim/fieldinterppoints.py +55 -0
  107. pyvale/{fieldsampler.py → sensorsim/fieldsampler.py} +4 -4
  108. pyvale/{fieldscalar.py → sensorsim/fieldscalar.py} +28 -24
  109. pyvale/{fieldtensor.py → sensorsim/fieldtensor.py} +33 -31
  110. pyvale/{fieldvector.py → sensorsim/fieldvector.py} +33 -31
  111. pyvale/{imagedef2d.py → sensorsim/imagedef2d.py} +9 -5
  112. pyvale/{integratorfactory.py → sensorsim/integratorfactory.py} +6 -6
  113. pyvale/{integratorquadrature.py → sensorsim/integratorquadrature.py} +3 -3
  114. pyvale/{integratorrectangle.py → sensorsim/integratorrectangle.py} +3 -3
  115. pyvale/{integratorspatial.py → sensorsim/integratorspatial.py} +1 -1
  116. pyvale/{rastercy.py → sensorsim/rastercy.py} +5 -5
  117. pyvale/{rasternp.py → sensorsim/rasternp.py} +9 -9
  118. pyvale/{rasteropts.py → sensorsim/rasteropts.py} +1 -1
  119. pyvale/{renderer.py → sensorsim/renderer.py} +1 -1
  120. pyvale/{rendermesh.py → sensorsim/rendermesh.py} +5 -5
  121. pyvale/{renderscene.py → sensorsim/renderscene.py} +2 -2
  122. pyvale/{sensorarray.py → sensorsim/sensorarray.py} +1 -1
  123. pyvale/{sensorarrayfactory.py → sensorsim/sensorarrayfactory.py} +12 -12
  124. pyvale/{sensorarraypoint.py → sensorsim/sensorarraypoint.py} +10 -8
  125. pyvale/{sensordata.py → sensorsim/sensordata.py} +1 -1
  126. pyvale/{sensortools.py → sensorsim/sensortools.py} +2 -20
  127. pyvale/sensorsim/simtools.py +174 -0
  128. pyvale/{visualexpplotter.py → sensorsim/visualexpplotter.py} +3 -3
  129. pyvale/{visualimages.py → sensorsim/visualimages.py} +2 -2
  130. pyvale/{visualsimanimator.py → sensorsim/visualsimanimator.py} +4 -4
  131. pyvale/{visualsimplotter.py → sensorsim/visualsimplotter.py} +5 -5
  132. pyvale/{visualsimsensors.py → sensorsim/visualsimsensors.py} +12 -12
  133. pyvale/{visualtools.py → sensorsim/visualtools.py} +1 -1
  134. pyvale/{visualtraceplotter.py → sensorsim/visualtraceplotter.py} +2 -2
  135. pyvale/simcases/case17.geo +3 -0
  136. pyvale/simcases/case17.i +4 -4
  137. pyvale/simcases/run_1case.py +1 -9
  138. pyvale/simcases/run_all_cases.py +1 -1
  139. pyvale/simcases/run_build_case.py +1 -1
  140. pyvale/simcases/run_example_cases.py +1 -1
  141. pyvale/verif/__init__.py +12 -0
  142. pyvale/{analyticsimdatafactory.py → verif/analyticsimdatafactory.py} +2 -2
  143. pyvale/{analyticsimdatagenerator.py → verif/analyticsimdatagenerator.py} +2 -2
  144. pyvale/verif/psens.py +125 -0
  145. pyvale/verif/psensconst.py +18 -0
  146. pyvale/verif/psensmech.py +227 -0
  147. pyvale/verif/psensmultiphys.py +187 -0
  148. pyvale/verif/psensscalar.py +347 -0
  149. pyvale/verif/psenstensor.py +123 -0
  150. pyvale/verif/psensvector.py +116 -0
  151. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/METADATA +6 -7
  152. pyvale-2025.8.1.dist-info/RECORD +263 -0
  153. pyvale/dataset.py +0 -415
  154. pyvale/simtools.py +0 -67
  155. pyvale-2025.7.2.dist-info/RECORD +0 -215
  156. /pyvale/{blendercalibrationdata.py → blender/blendercalibrationdata.py} +0 -0
  157. /pyvale/{dicchecks.py → dic/dicchecks.py} +0 -0
  158. /pyvale/{dicspecklegenerator.py → dic/dicspecklegenerator.py} +0 -0
  159. /pyvale/{dicspecklequality.py → dic/dicspecklequality.py} +0 -0
  160. /pyvale/{dicstrainresults.py → dic/dicstrainresults.py} +0 -0
  161. /pyvale/{cameradata.py → sensorsim/cameradata.py} +0 -0
  162. /pyvale/{cameradata2d.py → sensorsim/cameradata2d.py} +0 -0
  163. /pyvale/{errordriftcalc.py → sensorsim/errordriftcalc.py} +0 -0
  164. /pyvale/{fieldtransform.py → sensorsim/fieldtransform.py} +0 -0
  165. /pyvale/{generatorsrandom.py → sensorsim/generatorsrandom.py} +0 -0
  166. /pyvale/{imagetools.py → sensorsim/imagetools.py} +0 -0
  167. /pyvale/{integratortype.py → sensorsim/integratortype.py} +0 -0
  168. /pyvale/{output.py → sensorsim/output.py} +0 -0
  169. /pyvale/{raster.py → sensorsim/raster.py} +0 -0
  170. /pyvale/{sensordescriptor.py → sensorsim/sensordescriptor.py} +0 -0
  171. /pyvale/{visualimagedef.py → sensorsim/visualimagedef.py} +0 -0
  172. /pyvale/{visualopts.py → sensorsim/visualopts.py} +0 -0
  173. /pyvale/{analyticmeshgen.py → verif/analyticmeshgen.py} +0 -0
  174. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/WHEEL +0 -0
  175. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/licenses/LICENSE +0 -0
  176. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/top_level.txt +0 -0
@@ -22,9 +22,11 @@ Test case: point strain sensors on a 2D plate with hole loaded in tension
22
22
  from pathlib import Path
23
23
  import numpy as np
24
24
  import matplotlib.pyplot as plt
25
- import mooseherder as mh
26
- from mooseherder import SimData
27
- import pyvale as pyv
25
+
26
+ # Pyvale imports
27
+ import pyvale.mooseherder as mh
28
+ import pyvale.sensorsim as sens
29
+ import pyvale.dataset as dataset
28
30
 
29
31
  #%%
30
32
  # First we load the same 2D solid mechanics simulation we used previously
@@ -32,21 +34,21 @@ import pyvale as pyv
32
34
  # vector field examples except we will need to specify the string keys for
33
35
  # the normal a deviatoric components of our tensor field (as they appear in
34
36
  # our `SimData` object).
35
- data_path: Path = pyv.DataSet.mechanical_2d_path()
36
- sim_data: SimData = mh.ExodusReader(data_path).read_all_sim_data()
37
- sim_data: SimData = pyv.scale_length_units(scale=1000.0,
38
- sim_data=sim_data,
39
- disp_comps=("disp_x","disp_y"))
37
+ data_path: Path = dataset.mechanical_2d_path()
38
+ sim_data = mh.ExodusReader(data_path).read_all_sim_data()
39
+ sim_data = sens.scale_length_units(scale=1000.0,
40
+ sim_data=sim_data,
41
+ disp_comps=("disp_x","disp_y"))
40
42
 
41
43
  n_sens = (2,3,1)
42
44
  x_lims = (0.0,100.0)
43
45
  y_lims = (0.0,150.0)
44
46
  z_lims = (0.0,0.0)
45
- sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
47
+ sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
46
48
 
47
49
  sample_times = np.linspace(0.0,np.max(sim_data.time),50)
48
50
 
49
- sens_data = pyv.SensorData(positions=sens_pos,
51
+ sens_data = sens.SensorData(positions=sens_pos,
50
52
  sample_times=sample_times)
51
53
 
52
54
  #%%
@@ -57,7 +59,7 @@ sens_data = pyv.SensorData(positions=sens_pos,
57
59
  # have seen previously for scalar and vector fields.
58
60
  norm_comps = ("strain_xx","strain_yy")
59
61
  dev_comps = ("strain_xy",)
60
- straingauge_array = pyv.SensorArrayFactory \
62
+ straingauge_array = sens.SensorArrayFactory \
61
63
  .strain_gauges_basic_errs(sim_data,
62
64
  sens_data,
63
65
  elem_dims=2,
@@ -95,7 +97,7 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
95
97
  print(f"These are the last {time_last} virtual measurements of sensor "
96
98
  + f"{sens_print}:")
97
99
 
98
- pyv.print_measurements(straingauge_array,sens_print,comp_print,time_print)
100
+ sens.print_measurements(straingauge_array,sens_print,comp_print,time_print)
99
101
 
100
102
  print(80*"-")
101
103
 
@@ -103,12 +105,12 @@ print(80*"-")
103
105
  # We can plot a given component of our tensor field and display our sensor
104
106
  # locations with respect to the field.
105
107
  plot_field = "strain_yy"
106
- pv_plot = pyv.plot_point_sensors_on_sim(straingauge_array,plot_field)
108
+ pv_plot = sens.plot_point_sensors_on_sim(straingauge_array,plot_field)
107
109
  pv_plot.show(cpos="xy")
108
110
 
109
111
  #%%
110
112
  # We can also plot time traces for all components of the tensor field.
111
113
  for cc in (norm_comps+dev_comps):
112
- pyv.plot_time_traces(straingauge_array,cc)
114
+ sens.plot_time_traces(straingauge_array,cc)
113
115
 
114
116
  plt.show()
@@ -19,17 +19,20 @@ Test case: point strain 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
24
27
 
25
28
  #%%
26
29
  # First we load the same 2D solid mechanics simulation of a plate with a
27
30
  # hole loaded in tension as a `SimData` object. We scale the units to mm
28
31
  # from SI including the coordinates and displacement. Strain is unitless so
29
32
  # we leave it alone.
30
- data_path = pyv.DataSet.mechanical_2d_path()
33
+ data_path = dataset.mechanical_2d_path()
31
34
  sim_data = mh.ExodusReader(data_path).read_all_sim_data()
32
- sim_data = pyv.scale_length_units(scale=1000.0,
35
+ sim_data = sens.scale_length_units(scale=1000.0,
33
36
  sim_data=sim_data,
34
37
  disp_comps=("disp_x","disp_y"))
35
38
 
@@ -41,7 +44,7 @@ sim_data = pyv.scale_length_units(scale=1000.0,
41
44
  field_name = "strain"
42
45
  norm_comps = ("strain_xx","strain_yy")
43
46
  dev_comps = ("strain_xy",)
44
- strain_field = pyv.FieldTensor(sim_data,
47
+ strain_field = sens.FieldTensor(sim_data,
45
48
  field_name=field_name,
46
49
  norm_comps=norm_comps,
47
50
  dev_comps=dev_comps,
@@ -55,11 +58,11 @@ n_sens = (2,3,1)
55
58
  x_lims = (0.0,100.0)
56
59
  y_lims = (0.0,150.0)
57
60
  z_lims = (0.0,0.0)
58
- sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
61
+ sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
59
62
 
60
63
  sample_times = np.linspace(0.0,np.max(sim_data.time),50)
61
64
 
62
- sens_data = pyv.SensorData(positions=sens_pos,
65
+ sens_data = sens.SensorData(positions=sens_pos,
63
66
  sample_times=sample_times)
64
67
 
65
68
  #%%
@@ -67,7 +70,7 @@ sens_data = pyv.SensorData(positions=sens_pos,
67
70
  # the sensor locations and time traces for our sensors. For the strain
68
71
  # gauges we are modelling here we could also use the descriptor factory to
69
72
  # get these defaults.
70
- descriptor = pyv.SensorDescriptor(name="Strain",
73
+ descriptor = sens.SensorDescriptor(name="Strain",
71
74
  symbol=r"\varepsilon",
72
75
  units=r"-",
73
76
  tag="SG",
@@ -75,7 +78,7 @@ descriptor = pyv.SensorDescriptor(name="Strain",
75
78
 
76
79
  #%%
77
80
  # We build our point sensor array as normal.
78
- straingauge_array = pyv.SensorArrayPoint(sens_data,
81
+ straingauge_array = sens.SensorArrayPoint(sens_data,
79
82
  strain_field,
80
83
  descriptor)
81
84
 
@@ -83,9 +86,9 @@ straingauge_array = pyv.SensorArrayPoint(sens_data,
83
86
  # We can add any errors we like to our error chain. Here we add some basic
84
87
  # percentage errors.
85
88
  error_chain = []
86
- error_chain.append(pyv.ErrSysUnifPercent(low_percent=-2.0,high_percent=2.0))
87
- error_chain.append(pyv.ErrRandNormPercent(std_percent=2.0))
88
- error_int = pyv.ErrIntegrator(error_chain,
89
+ error_chain.append(sens.ErrSysUnifPercent(low_percent=-2.0,high_percent=2.0))
90
+ error_chain.append(sens.ErrRandNormPercent(std_percent=2.0))
91
+ error_int = sens.ErrIntegrator(error_chain,
89
92
  sens_data,
90
93
  straingauge_array.get_measurement_shape())
91
94
  straingauge_array.set_error_integrator(error_int)
@@ -102,12 +105,12 @@ measurements = straingauge_array.calc_measurements()
102
105
  # We can plot a given component of our tensor field and display our sensor
103
106
  # locations with respect to the field.
104
107
  plot_field = "strain_yy"
105
- pv_plot = pyv.plot_point_sensors_on_sim(straingauge_array,plot_field)
108
+ pv_plot = sens.plot_point_sensors_on_sim(straingauge_array,plot_field)
106
109
  pv_plot.show(cpos="xy")
107
110
 
108
111
  #%%
109
112
  # We can also plot time traces for all components of the tensor field.
110
113
  for cc in (norm_comps+dev_comps):
111
- pyv.plot_time_traces(straingauge_array,cc)
114
+ sens.plot_time_traces(straingauge_array,cc)
112
115
 
113
116
  plt.show()
@@ -21,14 +21,17 @@ Test case: point strain sensors on a 2D plate with hole loaded in tension
21
21
  import numpy as np
22
22
  import matplotlib.pyplot as plt
23
23
  from scipy.spatial.transform import Rotation
24
- import mooseherder as mh
25
- import pyvale as pyv
24
+
25
+ # Pyvale imports
26
+ import pyvale.mooseherder as mh
27
+ import pyvale.sensorsim as sens
28
+ import pyvale.dataset as dataset
26
29
 
27
30
  #%%
28
31
  # First we load our simulation asa `SimData` object. In this case we are
29
32
  # loading a 10mm cube loaded in tension in the y direction with the addition
30
33
  # of a thermal gradient in the y direction.
31
- data_path = pyv.DataSet.element_case_path(pyv.EElemTest.HEX20)
34
+ data_path = dataset.element_case_output_path(dataset.EElemTest.HEX20)
32
35
  sim_data = mh.ExodusReader(data_path).read_all_sim_data()
33
36
 
34
37
  #%%
@@ -36,7 +39,7 @@ sim_data = mh.ExodusReader(data_path).read_all_sim_data()
36
39
  # displacement field component here for scaling. Note that you don't need to
37
40
  # scale the displacements here if you only want to analyse strains.
38
41
  disp_comps = ("disp_x","disp_y","disp_z")
39
- sim_data = pyv.scale_length_units(scale=1000.0,
42
+ sim_data = sens.scale_length_units(scale=1000.0,
40
43
  sim_data=sim_data,
41
44
  disp_comps=disp_comps)
42
45
 
@@ -48,7 +51,7 @@ sim_data = pyv.scale_length_units(scale=1000.0,
48
51
  field_name = "strain"
49
52
  norm_comps = ("strain_xx","strain_yy","strain_zz")
50
53
  dev_comps = ("strain_xy","strain_yz","strain_xz")
51
- strain_field = pyv.FieldTensor(sim_data,
54
+ strain_field = sens.FieldTensor(sim_data,
52
55
  field_name=field_name,
53
56
  norm_comps=norm_comps,
54
57
  dev_comps=dev_comps,
@@ -80,7 +83,7 @@ sens_angles = (Rotation.from_euler("zyx", [0, 0, 0], degrees=True),
80
83
  Rotation.from_euler("zyx", [0, 0, 45], degrees=True),)
81
84
 
82
85
 
83
- sens_data = pyv.SensorData(positions=sensor_positions,
86
+ sens_data = sens.SensorData(positions=sensor_positions,
84
87
  sample_times=sample_times,
85
88
  angles=sens_angles)
86
89
 
@@ -89,14 +92,14 @@ sens_data = pyv.SensorData(positions=sensor_positions,
89
92
  # the sensor locations and time traces for our sensors. For the strain
90
93
  # gauges we are modelling here we could also use the descriptor factory to
91
94
  # get these defaults.
92
- descriptor = pyv.SensorDescriptor(name="Strain",
95
+ descriptor = sens.SensorDescriptor(name="Strain",
93
96
  symbol=r"\varepsilon",
94
97
  units=r"-",
95
98
  tag="SG",
96
99
  components=('xx','yy','zz','xy','yz','xz'))
97
100
 
98
101
 
99
- straingauge_array = pyv.SensorArrayPoint(sens_data,
102
+ straingauge_array = sens.SensorArrayPoint(sens_data,
100
103
  strain_field,
101
104
  descriptor)
102
105
 
@@ -104,22 +107,22 @@ straingauge_array = pyv.SensorArrayPoint(sens_data,
104
107
  # We can add any errors we like to our error chain. Here we add some basic
105
108
  # percentage errors.
106
109
  error_chain = []
107
- error_chain.append(pyv.ErrSysUnif(low=-0.1e-3,high=0.1e-3))
108
- error_chain.append(pyv.ErrRandNormPercent(std_percent=1.0))
110
+ error_chain.append(sens.ErrSysUnif(low=-0.1e-3,high=0.1e-3))
111
+ error_chain.append(sens.ErrRandNormPercent(std_percent=1.0))
109
112
 
110
113
  #%%
111
114
  # Now we add a field error to perturb the positions of each sensor on its
112
115
  # relevant face and then add a +/- 2deg angle error.
113
116
 
114
117
  pos_uncert = 0.1 # units = mm
115
- pos_rand_xyz = (pyv.GenNormal(std=pos_uncert),
116
- pyv.GenNormal(std=pos_uncert),
117
- pyv.GenNormal(std=pos_uncert))
118
+ pos_rand_xyz = (sens.GenNormal(std=pos_uncert),
119
+ sens.GenNormal(std=pos_uncert),
120
+ sens.GenNormal(std=pos_uncert))
118
121
 
119
122
  angle_uncert = 2.0
120
- angle_rand_zyx = (pyv.GenUniform(low=-angle_uncert,high=angle_uncert), # units = deg
121
- pyv.GenUniform(low=-angle_uncert,high=angle_uncert),
122
- pyv.GenUniform(low=-angle_uncert,high=angle_uncert))
123
+ angle_rand_zyx = (sens.GenUniform(low=-angle_uncert,high=angle_uncert), # units = deg
124
+ sens.GenUniform(low=-angle_uncert,high=angle_uncert),
125
+ sens.GenUniform(low=-angle_uncert,high=angle_uncert))
123
126
 
124
127
  #%%
125
128
  # We are going to lock position perturbation so that the sensors stay on the
@@ -137,15 +140,15 @@ angle_lock[0:2,1] = False # Allow rotation about y
137
140
  angle_lock[2:4,0] = False # Allow rotation about z
138
141
  angle_lock[4:6,2] = False # Allow rotation about x
139
142
 
140
- field_error_data = pyv.ErrFieldData(pos_rand_xyz=pos_rand_xyz,
143
+ field_error_data = sens.ErrFieldData(pos_rand_xyz=pos_rand_xyz,
141
144
  pos_lock_xyz=pos_lock,
142
145
  ang_rand_zyx=angle_rand_zyx,
143
146
  ang_lock_zyx=angle_lock)
144
- sys_err_field = pyv.ErrSysField(strain_field,field_error_data)
147
+ sys_err_field = sens.ErrSysField(strain_field,field_error_data)
145
148
  error_chain.append(sys_err_field)
146
149
 
147
150
 
148
- error_int = pyv.ErrIntegrator(error_chain,
151
+ error_int = sens.ErrIntegrator(error_chain,
149
152
  sens_data,
150
153
  straingauge_array.get_measurement_shape())
151
154
  straingauge_array.set_error_integrator(error_int)
@@ -175,7 +178,7 @@ print("ROTATED SENSORS WITH ANGLE ERRORS:")
175
178
  print(f"These are the last {time_last} virtual measurements of sensor "
176
179
  + f"{sens_print} for {norm_comps[comp_print]}:")
177
180
 
178
- pyv.print_measurements(straingauge_array,sens_print,comp_print,time_print)
181
+ sens.print_measurements(straingauge_array,sens_print,comp_print,time_print)
179
182
 
180
183
  print(80*"-")
181
184
 
@@ -183,12 +186,12 @@ print(80*"-")
183
186
  # We can plot a given component of our tensor field and display our sensor
184
187
  # locations with respect to the field.
185
188
  plot_field = "strain_yy"
186
- pv_plot = pyv.plot_point_sensors_on_sim(straingauge_array,plot_field)
189
+ pv_plot = sens.plot_point_sensors_on_sim(straingauge_array,plot_field)
187
190
  pv_plot.show(cpos="xy")
188
191
 
189
192
  #%%
190
193
  # We can also plot time traces for all components of the tensor field.
191
194
  for cc in (norm_comps+dev_comps):
192
- pyv.plot_time_traces(straingauge_array,cc)
195
+ sens.plot_time_traces(straingauge_array,cc)
193
196
 
194
197
  plt.show()
@@ -23,8 +23,11 @@ Test case: thermo-mechanical analysis of a 2D plate with a temperature gradient.
23
23
 
24
24
  import numpy as np
25
25
  import matplotlib.pyplot as plt
26
- import mooseherder as mh
27
- import pyvale as pyv
26
+
27
+ # Pyvale imports
28
+ import pyvale.mooseherder as mh
29
+ import pyvale.sensorsim as sens
30
+ import pyvale.dataset as dataset
28
31
 
29
32
  #%%
30
33
  # Here we get a list of paths to a set of 3 simulations in this case the
@@ -32,7 +35,7 @@ import pyvale as pyv
32
35
  # coefficient on the other. The mechanical deformation is a result of
33
36
  # thermal expansion. The 3 simulation cases cover a nominal thermal
34
37
  # and a perturbation of +/-10%.
35
- data_paths = pyv.DataSet.thermomechanical_2d_experiment_paths()
38
+ data_paths = dataset.thermomechanical_2d_experiment_paths()
36
39
  elem_dims: int = 2
37
40
 
38
41
  #%%
@@ -43,7 +46,7 @@ disp_comps = ("disp_x","disp_y")
43
46
  sim_list = []
44
47
  for pp in data_paths:
45
48
  sim_data = mh.ExodusReader(pp).read_all_sim_data()
46
- sim_data = pyv.scale_length_units(scale=1000.0,
49
+ sim_data = sens.scale_length_units(scale=1000.0,
47
50
  sim_data=sim_data,
48
51
  disp_comps=disp_comps)
49
52
  sim_list.append(sim_data)
@@ -60,10 +63,10 @@ n_sens = (4,1,1)
60
63
  x_lims = (0.0,100.0)
61
64
  y_lims = (0.0,50.0)
62
65
  z_lims = (0.0,0.0)
63
- tc_sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
66
+ tc_sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
64
67
 
65
- tc_sens_data = pyv.SensorData(positions=tc_sens_pos,
66
- sample_times=sample_times)
68
+ tc_sens_data = sens.SensorData(positions=tc_sens_pos,
69
+ sample_times=sample_times)
67
70
 
68
71
  #%%
69
72
  # We use the sensor array factory to give us thermocouples with basic 2%
@@ -72,7 +75,7 @@ tc_sens_data = pyv.SensorData(positions=tc_sens_pos,
72
75
  # we run our experiment the field object that relies on this will switch the
73
76
  # sim data for the required simulation in our list.
74
77
  tc_field_name = "temperature"
75
- tc_array = pyv.SensorArrayFactory \
78
+ tc_array = sens.SensorArrayFactory \
76
79
  .thermocouples_basic_errs(sim_list[0],
77
80
  tc_sens_data,
78
81
  elem_dims=elem_dims,
@@ -82,8 +85,8 @@ tc_array = pyv.SensorArrayFactory \
82
85
  #%%
83
86
  # We place 3 strain gauges along the direction of the temperature gradient.
84
87
  n_sens = (3,1,1)
85
- sg_sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
86
- sg_sens_data = pyv.SensorData(positions=sg_sens_pos,
88
+ sg_sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
89
+ sg_sens_data = sens.SensorData(positions=sg_sens_pos,
87
90
  sample_times=sample_times)
88
91
 
89
92
  #%%
@@ -91,7 +94,7 @@ sg_sens_data = pyv.SensorData(positions=sg_sens_pos,
91
94
  sg_field_name = "strain"
92
95
  sg_norm_comps = ("strain_xx","strain_yy")
93
96
  sg_dev_comps = ("strain_xy",)
94
- sg_array = pyv.SensorArrayFactory \
97
+ sg_array = sens.SensorArrayFactory \
95
98
  .strain_gauges_basic_errs(sim_list[0],
96
99
  sg_sens_data,
97
100
  elem_dims=elem_dims,
@@ -106,7 +109,7 @@ sg_array = pyv.SensorArrayFactory \
106
109
  # use this to create an experiment simulator while specifying how many
107
110
  # simulate experiments we want to run per simulation and sensor array.
108
111
  sensor_arrays = [tc_array,sg_array]
109
- exp_sim = pyv.ExperimentSimulator(sim_list,
112
+ exp_sim = sens.ExperimentSimulator(sim_list,
110
113
  sensor_arrays,
111
114
  num_exp_per_sim=1000)
112
115
 
@@ -163,12 +166,12 @@ print(80*"=")
163
166
  # deviation. In the next example we will see how to control these plots.
164
167
  # For now we will plot the temperature traces for the first simulation and
165
168
  # the strain traces for the third simulation in our list of SimData objects.
166
- (fig,ax) = pyv.plot_exp_traces(exp_sim,
169
+ (fig,ax) = sens.plot_exp_traces(exp_sim,
167
170
  component="temperature",
168
171
  sens_array_num=0,
169
172
  sim_num=0)
170
173
 
171
- (fig,ax) = pyv.plot_exp_traces(exp_sim,
174
+ (fig,ax) = sens.plot_exp_traces(exp_sim,
172
175
  component="strain_yy",
173
176
  sens_array_num=1,
174
177
  sim_num=2)
@@ -20,14 +20,17 @@ Test case: thermo-mechanical analysis of a divertor heatsink in 3D
20
20
  from pathlib import Path
21
21
  import numpy as np
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
  # First we get the path to simulation output file and then read the
28
31
  # simulation into a `SimData` object. In this case our simulation is a
29
32
  # thermomechanical model of a divertor heatsink.
30
- sim_path = pyv.DataSet.thermomechanical_3d_path()
33
+ sim_path = dataset.thermomechanical_3d_path()
31
34
  sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
32
35
  elem_dims: int = 3
33
36
 
@@ -35,7 +38,7 @@ elem_dims: int = 3
35
38
  # We scale our length and displacement units to mm to help with
36
39
  # visualisation.
37
40
  disp_comps = ("disp_x","disp_y","disp_z")
38
- sim_data = pyv.scale_length_units(scale=1000.0,
41
+ sim_data = sens.scale_length_units(scale=1000.0,
39
42
  sim_data=sim_data,
40
43
  disp_comps=disp_comps)
41
44
 
@@ -59,15 +62,15 @@ x_lims = (12.5,12.5)
59
62
  y_lims = (0.0,33.0)
60
63
  z_lims = (0.0,12.0)
61
64
  n_sens = (1,4,1)
62
- tc_sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
65
+ tc_sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
63
66
 
64
- tc_sens_data = pyv.SensorData(positions=tc_sens_pos,
67
+ tc_sens_data = sens.SensorData(positions=tc_sens_pos,
65
68
  sample_times=sample_times)
66
69
  #%%
67
70
  # We use the sensor array factory to create our thermocouple array with no
68
71
  # errors.
69
72
  tc_field_name = "temperature"
70
- tc_array = pyv.SensorArrayFactory \
73
+ tc_array = sens.SensorArrayFactory \
71
74
  .thermocouples_no_errs(sim_data,
72
75
  tc_sens_data,
73
76
  elem_dims=elem_dims,
@@ -76,30 +79,30 @@ tc_array = pyv.SensorArrayFactory \
76
79
  # Now we build our error chain starting with some basic errors on the order
77
80
  # of 1 degree.
78
81
  tc_err_chain = []
79
- tc_err_chain.append(pyv.ErrSysUnif(low=1.0,high=1.0))
80
- tc_err_chain.append(pyv.ErrRandNorm(std=1.0))
82
+ tc_err_chain.append(sens.ErrSysUnif(low=1.0,high=1.0))
83
+ tc_err_chain.append(sens.ErrRandNorm(std=1.0))
81
84
 
82
85
  #%%
83
86
  # Now we add positioning error for our thermocouples.
84
87
  tc_pos_uncert = 0.1 # units = mm
85
- tc_pos_rand = (pyv.GenNormal(std=tc_pos_uncert),
86
- pyv.GenNormal(std=tc_pos_uncert),
87
- pyv.GenNormal(std=tc_pos_uncert))
88
+ tc_pos_rand = (sens.GenNormal(std=tc_pos_uncert),
89
+ sens.GenNormal(std=tc_pos_uncert),
90
+ sens.GenNormal(std=tc_pos_uncert))
88
91
 
89
92
  #%%
90
93
  # We block translation in x so the thermocouples stay attached.
91
94
  tc_pos_lock = np.full(tc_sens_pos.shape,False,dtype=bool)
92
95
  tc_pos_lock[:,0] = True
93
96
 
94
- tc_field_err_data = pyv.ErrFieldData(pos_rand_xyz=tc_pos_rand,
97
+ tc_field_err_data = sens.ErrFieldData(pos_rand_xyz=tc_pos_rand,
95
98
  pos_lock_xyz=tc_pos_lock)
96
- tc_err_chain.append(pyv.ErrSysField(tc_array.get_field(),
99
+ tc_err_chain.append(sens.ErrSysField(tc_array.get_field(),
97
100
 
98
101
  tc_field_err_data))
99
102
  #%%
100
103
  # We have finished our error chain so we can build our error integrator and
101
104
  # attach it to our thermocouple array.
102
- tc_error_int = pyv.ErrIntegrator(tc_err_chain,
105
+ tc_error_int = sens.ErrIntegrator(tc_err_chain,
103
106
  tc_sens_data,
104
107
  tc_array.get_measurement_shape())
105
108
  tc_array.set_error_integrator(tc_error_int)
@@ -107,7 +110,7 @@ tc_array.set_error_integrator(tc_error_int)
107
110
  #%%
108
111
  # We visualise our thermcouple locations on our mesh to make sure they are
109
112
  # in the correct positions.
110
- pv_plot = pyv.plot_point_sensors_on_sim(tc_array,"temperature")
113
+ pv_plot = sens.plot_point_sensors_on_sim(tc_array,"temperature")
111
114
  pv_plot.camera_position = [(59.354, 43.428, 69.946),
112
115
  (-2.858, 13.189, 4.523),
113
116
  (-0.215, 0.948, -0.233)]
@@ -127,9 +130,9 @@ x_lims = (9.4,9.4)
127
130
  y_lims = (0.0,33.0)
128
131
  z_lims = (12.0,12.0)
129
132
  n_sens = (1,4,1)
130
- sg_sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
133
+ sg_sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
131
134
 
132
- sg_sens_data = pyv.SensorData(positions=sg_sens_pos,
135
+ sg_sens_data = sens.SensorData(positions=sg_sens_pos,
133
136
  sample_times=sample_times)
134
137
 
135
138
  #%%
@@ -138,7 +141,7 @@ sg_sens_data = pyv.SensorData(positions=sg_sens_pos,
138
141
  sg_field_name = "strain"
139
142
  sg_norm_comps = ("strain_xx","strain_yy","strain_zz")
140
143
  sg_dev_comps = ("strain_xy","strain_yz","strain_xz")
141
- sg_array = pyv.SensorArrayFactory \
144
+ sg_array = sens.SensorArrayFactory \
142
145
  .strain_gauges_no_errs(sim_data,
143
146
  sg_sens_data,
144
147
  elem_dims=elem_dims,
@@ -150,30 +153,30 @@ sg_array = pyv.SensorArrayFactory \
150
153
  # Now we build our error chain starting with some basic errors on the order
151
154
  # of 1 percent.
152
155
  sg_err_chain = []
153
- sg_err_chain.append(pyv.ErrSysUnifPercent(low_percent=1.0,high_percent=1.0))
154
- sg_err_chain.append(pyv.ErrRandNormPercent(std_percent=1.0))
156
+ sg_err_chain.append(sens.ErrSysUnifPercent(low_percent=1.0,high_percent=1.0))
157
+ sg_err_chain.append(sens.ErrRandNormPercent(std_percent=1.0))
155
158
 
156
159
  #%%
157
160
  # We are going to add +/-2 degree rotation uncertainty to our strain gauges.
158
161
  angle_uncert = 2.0
159
- angle_rand_zyx = (pyv.GenUniform(low=-angle_uncert,high=angle_uncert), # units = deg
160
- pyv.GenUniform(low=-angle_uncert,high=angle_uncert),
161
- pyv.GenUniform(low=-angle_uncert,high=angle_uncert))
162
+ angle_rand_zyx = (sens.GenUniform(low=-angle_uncert,high=angle_uncert), # units = deg
163
+ sens.GenUniform(low=-angle_uncert,high=angle_uncert),
164
+ sens.GenUniform(low=-angle_uncert,high=angle_uncert))
162
165
 
163
166
  #%%
164
167
  # We only allow rotation on the face the strain gauges are on
165
168
  angle_lock = np.full(sg_sens_pos.shape,True,dtype=bool)
166
169
  angle_lock[:,0] = False # Allow rotation about z
167
170
 
168
- sg_field_err_data = pyv.ErrFieldData(ang_rand_zyx=angle_rand_zyx,
171
+ sg_field_err_data = sens.ErrFieldData(ang_rand_zyx=angle_rand_zyx,
169
172
  ang_lock_zyx=angle_lock)
170
- sg_err_chain.append(pyv.ErrSysField(sg_array.get_field(),
173
+ sg_err_chain.append(sens.ErrSysField(sg_array.get_field(),
171
174
  sg_field_err_data))
172
175
 
173
176
  #%%
174
177
  # We have finished our error chain so we can build our error integrator and
175
178
  # attach it to our thermocouple array.
176
- sg_error_int = pyv.ErrIntegrator(sg_err_chain,
179
+ sg_error_int = sens.ErrIntegrator(sg_err_chain,
177
180
  sg_sens_data,
178
181
  sg_array.get_measurement_shape())
179
182
  sg_array.set_error_integrator(sg_error_int)
@@ -181,7 +184,7 @@ sg_array.set_error_integrator(sg_error_int)
181
184
  #%%
182
185
  # Now we visualise the strain gauge locations to make sure they are where
183
186
  # we expect them to be.
184
- pv_plot = pyv.plot_point_sensors_on_sim(sg_array,"strain_yy")
187
+ pv_plot = sens.plot_point_sensors_on_sim(sg_array,"strain_yy")
185
188
  pv_plot.camera_position = [(59.354, 43.428, 69.946),
186
189
  (-2.858, 13.189, 4.523),
187
190
  (-0.215, 0.948, -0.233)]
@@ -200,7 +203,7 @@ pv_plot.show()
200
203
  # all points on the graph.
201
204
  sim_list = [sim_data,]
202
205
  sensor_arrays = [tc_array,sg_array]
203
- exp_sim = pyv.ExperimentSimulator(sim_list,
206
+ exp_sim = sens.ExperimentSimulator(sim_list,
204
207
  sensor_arrays,
205
208
  num_exp_per_sim=100)
206
209
 
@@ -246,11 +249,11 @@ print(80*"=")
246
249
  # the median as the centre line and to fill between the min and max values.
247
250
  # Note that the default here is to plot the mean and fill between 3 times
248
251
  # the standard deviation.
249
- trace_opts = pyv.TraceOptsExperiment(plot_all_exp_points=True,
250
- centre=pyv.EExpVisCentre.MEDIAN,
251
- fill_between=pyv.EExpVisBounds.MINMAX)
252
+ trace_opts = sens.TraceOptsExperiment(plot_all_exp_points=True,
253
+ centre=sens.EExpVisCentre.MEDIAN,
254
+ fill_between=sens.EExpVisBounds.MINMAX)
252
255
 
253
- (fig,ax) = pyv.plot_exp_traces(exp_sim,
256
+ (fig,ax) = sens.plot_exp_traces(exp_sim,
254
257
  component="temperature",
255
258
  sens_array_num=0,
256
259
  sim_num=0,
@@ -259,7 +262,7 @@ if save_figs:
259
262
  fig.savefig(fig_save_path/(save_tag+"_tc_traces.png"),
260
263
  dpi=300, format='png', bbox_inches='tight')
261
264
 
262
- (fig,ax) = pyv.plot_exp_traces(exp_sim,
265
+ (fig,ax) = sens.plot_exp_traces(exp_sim,
263
266
  component="strain_yy",
264
267
  sens_array_num=1,
265
268
  sim_num=0,
@@ -0,0 +1,24 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ """Basics: No mesh
8
+ ================================================================================
9
+
10
+ TODO
11
+ """
12
+
13
+ import numpy as np
14
+ import pyvale as pyv
15
+
16
+ # Build an analytic mesh in 2D and create a bi-linear field on the mesh
17
+
18
+ # Run normal pyvale to see output of a sensor array
19
+
20
+
21
+
22
+
23
+
24
+