pyvale 2025.7.2__cp311-cp311-win_amd64.whl → 2025.8.1__cp311-cp311-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyvale might be problematic. Click here for more details.
- pyvale/__init__.py +12 -92
- pyvale/blender/__init__.py +23 -0
- pyvale/{pyvaleexceptions.py → blender/blenderexceptions.py} +0 -3
- pyvale/{blenderlightdata.py → blender/blenderlightdata.py} +3 -3
- pyvale/{blendermaterialdata.py → blender/blendermaterialdata.py} +1 -1
- pyvale/{blenderrenderdata.py → blender/blenderrenderdata.py} +5 -3
- pyvale/{blenderscene.py → blender/blenderscene.py} +33 -30
- pyvale/{blendertools.py → blender/blendertools.py} +14 -10
- pyvale/dataset/__init__.py +7 -0
- pyvale/dataset/dataset.py +443 -0
- pyvale/dic/__init__.py +20 -0
- pyvale/{dic2d.py → dic/dic2d.py} +31 -36
- pyvale/dic/dic2dconv.py +6 -0
- pyvale/{dic2dcpp.cp311-win_amd64.pyd → dic/dic2dcpp.cp311-win_amd64.pyd} +0 -0
- pyvale/{dicdataimport.py → dic/dicdataimport.py} +8 -8
- pyvale/{dicregionofinterest.py → dic/dicregionofinterest.py} +1 -1
- pyvale/{dicresults.py → dic/dicresults.py} +1 -1
- pyvale/{dicstrain.py → dic/dicstrain.py} +9 -9
- pyvale/examples/basics/{ex1_1_basicscalars_therm2d.py → ex1a_basicscalars_therm2d.py} +12 -9
- pyvale/examples/basics/{ex1_2_sensormodel_therm2d.py → ex1b_sensormodel_therm2d.py} +17 -14
- pyvale/examples/basics/{ex1_3_customsens_therm3d.py → ex1c_customsens_therm3d.py} +27 -24
- pyvale/examples/basics/{ex1_4_basicerrors_therm3d.py → ex1d_basicerrors_therm3d.py} +32 -29
- pyvale/examples/basics/{ex1_5_fielderrs_therm3d.py → ex1e_fielderrs_therm3d.py} +19 -15
- pyvale/examples/basics/{ex1_6_caliberrs_therm2d.py → ex1f_caliberrs_therm2d.py} +20 -16
- pyvale/examples/basics/{ex1_7_spatavg_therm2d.py → ex1g_spatavg_therm2d.py} +19 -16
- pyvale/examples/basics/{ex2_1_basicvectors_disp2d.py → ex2a_basicvectors_disp2d.py} +13 -10
- pyvale/examples/basics/{ex2_2_vectorsens_disp2d.py → ex2b_vectorsens_disp2d.py} +19 -15
- pyvale/examples/basics/{ex2_3_sensangle_disp2d.py → ex2c_sensangle_disp2d.py} +21 -18
- pyvale/examples/basics/{ex2_4_chainfielderrs_disp2d.py → ex2d_chainfielderrs_disp2d.py} +31 -29
- pyvale/examples/basics/{ex2_5_vectorfields3d_disp3d.py → ex2e_vectorfields3d_disp3d.py} +21 -18
- pyvale/examples/basics/{ex3_1_basictensors_strain2d.py → ex3a_basictensors_strain2d.py} +16 -14
- pyvale/examples/basics/{ex3_2_tensorsens2d_strain2d.py → ex3b_tensorsens2d_strain2d.py} +17 -14
- pyvale/examples/basics/{ex3_3_tensorsens3d_strain3d.py → ex3c_tensorsens3d_strain3d.py} +25 -22
- pyvale/examples/basics/{ex4_1_expsim2d_thermmech2d.py → ex4a_expsim2d_thermmech2d.py} +17 -14
- pyvale/examples/basics/{ex4_2_expsim3d_thermmech3d.py → ex4b_expsim3d_thermmech3d.py} +37 -34
- pyvale/examples/basics/ex5_nomesh.py +24 -0
- pyvale/examples/dic/ex1_2_blenderdeformed.py +174 -0
- pyvale/examples/dic/ex1_region_of_interest.py +6 -3
- pyvale/examples/dic/ex2_plate_with_hole.py +21 -18
- pyvale/examples/dic/ex3_plate_with_hole_strain.py +8 -6
- pyvale/examples/dic/ex4_dic_blender.py +17 -15
- pyvale/examples/dic/ex5_dic_challenge.py +19 -14
- pyvale/examples/genanalyticdata/ex1_1_scalarvisualisation.py +16 -10
- pyvale/examples/genanalyticdata/ex1_2_scalarcasebuild.py +3 -3
- pyvale/examples/genanalyticdata/ex2_1_analyticsensors.py +29 -23
- pyvale/examples/genanalyticdata/ex2_2_analyticsensors_nomesh.py +67 -0
- pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +12 -9
- pyvale/examples/mooseherder/ex0_create_moose_config.py +65 -0
- pyvale/examples/mooseherder/ex1a_modify_moose_input.py +71 -0
- pyvale/examples/mooseherder/ex1b_modify_gmsh_input.py +69 -0
- pyvale/examples/mooseherder/ex2a_run_moose_once.py +80 -0
- pyvale/examples/mooseherder/ex2b_run_gmsh_once.py +64 -0
- pyvale/examples/mooseherder/ex2c_run_both_once.py +114 -0
- pyvale/examples/mooseherder/ex3_run_moose_seq_para.py +157 -0
- pyvale/examples/mooseherder/ex4_run_gmsh-moose_seq_para.py +176 -0
- pyvale/examples/mooseherder/ex5_run_moose_paramulti.py +136 -0
- pyvale/examples/mooseherder/ex6_read_moose_exodus.py +163 -0
- pyvale/examples/mooseherder/ex7a_read_moose_herd_results.py +153 -0
- pyvale/examples/mooseherder/ex7b_read_multi_herd_results.py +116 -0
- pyvale/examples/mooseherder/ex7c_read_multi_gmshmoose_results.py +127 -0
- pyvale/examples/mooseherder/ex7d_readconfig_multi_gmshmoose_results.py +143 -0
- pyvale/examples/mooseherder/ex8_read_existing_sweep_output.py +72 -0
- pyvale/examples/renderblender/ex1_1_blenderscene.py +24 -20
- pyvale/examples/renderblender/ex1_2_blenderdeformed.py +22 -18
- pyvale/examples/renderblender/ex2_1_stereoscene.py +36 -29
- pyvale/examples/renderblender/ex2_2_stereodeformed.py +26 -20
- pyvale/examples/renderblender/ex3_1_blendercalibration.py +24 -17
- pyvale/examples/renderrasterisation/ex_rastenp.py +14 -12
- pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +14 -15
- pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +13 -11
- pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +13 -11
- pyvale/mooseherder/__init__.py +32 -0
- pyvale/mooseherder/directorymanager.py +416 -0
- pyvale/mooseherder/exodusreader.py +763 -0
- pyvale/mooseherder/gmshrunner.py +163 -0
- pyvale/mooseherder/inputmodifier.py +236 -0
- pyvale/mooseherder/mooseconfig.py +226 -0
- pyvale/mooseherder/mooseherd.py +527 -0
- pyvale/mooseherder/mooserunner.py +303 -0
- pyvale/mooseherder/outputreader.py +22 -0
- pyvale/mooseherder/simdata.py +92 -0
- pyvale/mooseherder/simrunner.py +31 -0
- pyvale/mooseherder/sweepreader.py +356 -0
- pyvale/mooseherder/sweeptools.py +76 -0
- pyvale/sensorsim/__init__.py +82 -0
- pyvale/{camera.py → sensorsim/camera.py} +7 -7
- pyvale/{camerasensor.py → sensorsim/camerasensor.py} +7 -7
- pyvale/{camerastereo.py → sensorsim/camerastereo.py} +2 -2
- pyvale/{cameratools.py → sensorsim/cameratools.py} +4 -4
- pyvale/{cython → sensorsim/cython}/rastercyth.c +596 -596
- pyvale/{cython → sensorsim/cython}/rastercyth.cp311-win_amd64.pyd +0 -0
- pyvale/{cython → sensorsim/cython}/rastercyth.py +16 -17
- pyvale/{errorcalculator.py → sensorsim/errorcalculator.py} +1 -1
- pyvale/{errorintegrator.py → sensorsim/errorintegrator.py} +2 -2
- pyvale/{errorrand.py → sensorsim/errorrand.py} +4 -4
- pyvale/{errorsyscalib.py → sensorsim/errorsyscalib.py} +2 -2
- pyvale/{errorsysdep.py → sensorsim/errorsysdep.py} +2 -2
- pyvale/{errorsysfield.py → sensorsim/errorsysfield.py} +8 -8
- pyvale/{errorsysindep.py → sensorsim/errorsysindep.py} +3 -3
- pyvale/sensorsim/exceptions.py +8 -0
- pyvale/{experimentsimulator.py → sensorsim/experimentsimulator.py} +23 -3
- pyvale/{field.py → sensorsim/field.py} +1 -1
- pyvale/{fieldconverter.py → sensorsim/fieldconverter.py} +72 -19
- pyvale/sensorsim/fieldinterp.py +37 -0
- pyvale/sensorsim/fieldinterpmesh.py +124 -0
- pyvale/sensorsim/fieldinterppoints.py +55 -0
- pyvale/{fieldsampler.py → sensorsim/fieldsampler.py} +4 -4
- pyvale/{fieldscalar.py → sensorsim/fieldscalar.py} +28 -24
- pyvale/{fieldtensor.py → sensorsim/fieldtensor.py} +33 -31
- pyvale/{fieldvector.py → sensorsim/fieldvector.py} +33 -31
- pyvale/{imagedef2d.py → sensorsim/imagedef2d.py} +9 -5
- pyvale/{integratorfactory.py → sensorsim/integratorfactory.py} +6 -6
- pyvale/{integratorquadrature.py → sensorsim/integratorquadrature.py} +3 -3
- pyvale/{integratorrectangle.py → sensorsim/integratorrectangle.py} +3 -3
- pyvale/{integratorspatial.py → sensorsim/integratorspatial.py} +1 -1
- pyvale/{rastercy.py → sensorsim/rastercy.py} +5 -5
- pyvale/{rasternp.py → sensorsim/rasternp.py} +9 -9
- pyvale/{rasteropts.py → sensorsim/rasteropts.py} +1 -1
- pyvale/{renderer.py → sensorsim/renderer.py} +1 -1
- pyvale/{rendermesh.py → sensorsim/rendermesh.py} +5 -5
- pyvale/{renderscene.py → sensorsim/renderscene.py} +2 -2
- pyvale/{sensorarray.py → sensorsim/sensorarray.py} +1 -1
- pyvale/{sensorarrayfactory.py → sensorsim/sensorarrayfactory.py} +12 -12
- pyvale/{sensorarraypoint.py → sensorsim/sensorarraypoint.py} +10 -8
- pyvale/{sensordata.py → sensorsim/sensordata.py} +1 -1
- pyvale/{sensortools.py → sensorsim/sensortools.py} +2 -20
- pyvale/sensorsim/simtools.py +174 -0
- pyvale/{visualexpplotter.py → sensorsim/visualexpplotter.py} +3 -3
- pyvale/{visualimages.py → sensorsim/visualimages.py} +2 -2
- pyvale/{visualsimanimator.py → sensorsim/visualsimanimator.py} +4 -4
- pyvale/{visualsimplotter.py → sensorsim/visualsimplotter.py} +5 -5
- pyvale/{visualsimsensors.py → sensorsim/visualsimsensors.py} +12 -12
- pyvale/{visualtools.py → sensorsim/visualtools.py} +1 -1
- pyvale/{visualtraceplotter.py → sensorsim/visualtraceplotter.py} +2 -2
- pyvale/simcases/case17.geo +3 -0
- pyvale/simcases/case17.i +4 -4
- pyvale/simcases/run_1case.py +1 -9
- pyvale/simcases/run_all_cases.py +1 -1
- pyvale/simcases/run_build_case.py +1 -1
- pyvale/simcases/run_example_cases.py +1 -1
- pyvale/verif/__init__.py +12 -0
- pyvale/{analyticsimdatafactory.py → verif/analyticsimdatafactory.py} +2 -2
- pyvale/{analyticsimdatagenerator.py → verif/analyticsimdatagenerator.py} +2 -2
- pyvale/verif/psens.py +125 -0
- pyvale/verif/psensconst.py +18 -0
- pyvale/verif/psensmech.py +227 -0
- pyvale/verif/psensmultiphys.py +187 -0
- pyvale/verif/psensscalar.py +347 -0
- pyvale/verif/psenstensor.py +123 -0
- pyvale/verif/psensvector.py +116 -0
- {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/METADATA +6 -7
- pyvale-2025.8.1.dist-info/RECORD +260 -0
- pyvale/dataset.py +0 -415
- pyvale/simtools.py +0 -67
- pyvale-2025.7.2.dist-info/RECORD +0 -212
- /pyvale/{blendercalibrationdata.py → blender/blendercalibrationdata.py} +0 -0
- /pyvale/{dicchecks.py → dic/dicchecks.py} +0 -0
- /pyvale/{dicspecklegenerator.py → dic/dicspecklegenerator.py} +0 -0
- /pyvale/{dicspecklequality.py → dic/dicspecklequality.py} +0 -0
- /pyvale/{dicstrainresults.py → dic/dicstrainresults.py} +0 -0
- /pyvale/{cameradata.py → sensorsim/cameradata.py} +0 -0
- /pyvale/{cameradata2d.py → sensorsim/cameradata2d.py} +0 -0
- /pyvale/{errordriftcalc.py → sensorsim/errordriftcalc.py} +0 -0
- /pyvale/{fieldtransform.py → sensorsim/fieldtransform.py} +0 -0
- /pyvale/{generatorsrandom.py → sensorsim/generatorsrandom.py} +0 -0
- /pyvale/{imagetools.py → sensorsim/imagetools.py} +0 -0
- /pyvale/{integratortype.py → sensorsim/integratortype.py} +0 -0
- /pyvale/{output.py → sensorsim/output.py} +0 -0
- /pyvale/{raster.py → sensorsim/raster.py} +0 -0
- /pyvale/{sensordescriptor.py → sensorsim/sensordescriptor.py} +0 -0
- /pyvale/{visualimagedef.py → sensorsim/visualimagedef.py} +0 -0
- /pyvale/{visualopts.py → sensorsim/visualopts.py} +0 -0
- /pyvale/{analyticmeshgen.py → verif/analyticmeshgen.py} +0 -0
- {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/WHEEL +0 -0
- {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/licenses/LICENSE +0 -0
- {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
#===============================================================================
|
|
2
|
+
# pyvale: the python validation engine
|
|
3
|
+
# License: MIT
|
|
4
|
+
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
+
#===============================================================================
|
|
6
|
+
import copy
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
import pyvale.mooseherder as mh
|
|
10
|
+
import pyvale.sensorsim as sens
|
|
11
|
+
import pyvale.verif.psens as psens
|
|
12
|
+
import pyvale.verif.psensconst as psensconst
|
|
13
|
+
import pyvale.dataset as dataset
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
DEVELOPER VERIFICATION MODULE
|
|
17
|
+
--------------------------------------------------------------------------------
|
|
18
|
+
This module contains developer utility functions used for verification testing
|
|
19
|
+
of the point sensor simulation toolbox in pyvale.
|
|
20
|
+
|
|
21
|
+
Specifically, this module contains functions used for testing point sensors
|
|
22
|
+
applied to scalar fields.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# TODO: fix position locking for 3D field errors
|
|
26
|
+
|
|
27
|
+
def simdata_2d() -> mh.SimData:
|
|
28
|
+
data_path = dataset.thermal_2d_path()
|
|
29
|
+
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
30
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
31
|
+
sim_data=sim_data,
|
|
32
|
+
disp_comps=None)
|
|
33
|
+
return sim_data
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def simdata_3d() -> mh.SimData:
|
|
37
|
+
data_path = dataset.thermal_3d_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=None)
|
|
42
|
+
return sim_data
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def sens_pos_2d() -> dict[str,np.ndarray]:
|
|
46
|
+
sim_dims = sens.SimTools.get_sim_dims(simdata_2d())
|
|
47
|
+
sens_pos = {}
|
|
48
|
+
|
|
49
|
+
x_lims = sim_dims["x"]
|
|
50
|
+
y_lims = sim_dims["y"]
|
|
51
|
+
z_lims = (0,0)
|
|
52
|
+
|
|
53
|
+
n_sens = (4,1,1)
|
|
54
|
+
sens_pos["line-4"] = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
55
|
+
|
|
56
|
+
n_sens = (2,2,1)
|
|
57
|
+
sens_pos["grid-22"] = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
58
|
+
|
|
59
|
+
return sens_pos
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def sens_pos_3d() -> dict[str,np.ndarray]:
|
|
63
|
+
sim_dims = sens.SimTools.get_sim_dims(simdata_3d())
|
|
64
|
+
|
|
65
|
+
sens_pos = {}
|
|
66
|
+
|
|
67
|
+
n_sens = (1,4,1)
|
|
68
|
+
x_lims = (sim_dims["x"][1],sim_dims["x"][1])
|
|
69
|
+
y_lims = sim_dims["y"]
|
|
70
|
+
z_lims = sim_dims["z"]
|
|
71
|
+
sens_pos["line-y-xy"] = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
72
|
+
|
|
73
|
+
n_sens = (1,4,1)
|
|
74
|
+
x_lims = (9.4,9.4)
|
|
75
|
+
y_lims = sim_dims["y"]
|
|
76
|
+
z_lims = (sim_dims["z"][1],sim_dims["z"][1])
|
|
77
|
+
sens_pos["line-y-yz"] = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
78
|
+
|
|
79
|
+
return sens_pos
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def sens_pos_2d_lock(sens_pos: np.ndarray) -> dict[str,np.ndarray]:
|
|
83
|
+
pos_lock = {}
|
|
84
|
+
|
|
85
|
+
lock = np.full_like(sens_pos,False,dtype=bool)
|
|
86
|
+
lock[:,2] = True # lock z
|
|
87
|
+
pos_lock["line-4"] = None
|
|
88
|
+
|
|
89
|
+
lock = np.full_like(sens_pos,False,dtype=bool)
|
|
90
|
+
lock[:,2] = True # lock z
|
|
91
|
+
pos_lock["grid-22"] = None
|
|
92
|
+
|
|
93
|
+
return pos_lock
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def sens_pos_3d_lock(sens_pos: np.ndarray) -> dict[str,np.ndarray]:
|
|
97
|
+
pos_lock = {}
|
|
98
|
+
|
|
99
|
+
lock = np.full_like(sens_pos,False,dtype=bool)
|
|
100
|
+
lock[:,2] = True # lock z
|
|
101
|
+
pos_lock["line-y-xy"] = lock
|
|
102
|
+
|
|
103
|
+
lock = np.full_like(sens_pos,False,dtype=bool)
|
|
104
|
+
lock[:,0] = True # lock x
|
|
105
|
+
pos_lock["line-y-yz"] = None
|
|
106
|
+
|
|
107
|
+
return pos_lock
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def sens_data_2d_dict() -> dict[str,sens.SensorData]:
|
|
111
|
+
return psens.sens_data_dict(simdata_2d(),sens_pos_2d())
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def sens_data_3d_dict() -> dict[str,sens.SensorData]:
|
|
115
|
+
return psens.sens_data_dict(simdata_3d(),sens_pos_3d())
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def err_chain_sfield(field: sens.IField,
|
|
119
|
+
sens_pos: np.ndarray,
|
|
120
|
+
samp_times: np.ndarray | None,
|
|
121
|
+
pos_lock: np.ndarray | None,
|
|
122
|
+
) -> list[sens.IErrCalculator]:
|
|
123
|
+
|
|
124
|
+
if samp_times is None:
|
|
125
|
+
samp_times = field.get_time_steps()
|
|
126
|
+
|
|
127
|
+
pos_offset_xyz = np.array((1.0,1.0,1.0),dtype=np.float64)
|
|
128
|
+
pos_offset_xyz = np.tile(pos_offset_xyz,(sens_pos.shape[0],1))
|
|
129
|
+
|
|
130
|
+
time_offset = np.full((samp_times.shape[0],),0.1)
|
|
131
|
+
|
|
132
|
+
pos_rand = sens.GenNormal(std=1.0,
|
|
133
|
+
mean=0.0,
|
|
134
|
+
seed=psensconst.GOLD_SEED) # units = mm
|
|
135
|
+
time_rand = sens.GenNormal(std=0.1,
|
|
136
|
+
mean=0.0,
|
|
137
|
+
seed=psensconst.GOLD_SEED) # units = s
|
|
138
|
+
|
|
139
|
+
field_err_data = sens.ErrFieldData(
|
|
140
|
+
pos_offset_xyz=pos_offset_xyz,
|
|
141
|
+
time_offset=time_offset,
|
|
142
|
+
pos_rand_xyz=(pos_rand,pos_rand,pos_rand),
|
|
143
|
+
time_rand=time_rand,
|
|
144
|
+
pos_lock_xyz=pos_lock,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
err_chain = []
|
|
148
|
+
err_chain.append(sens.ErrSysField(field,
|
|
149
|
+
field_err_data))
|
|
150
|
+
return err_chain
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def err_chain_sfield_dep(field: sens.IField,
|
|
154
|
+
sens_pos: np.ndarray,
|
|
155
|
+
samp_times: np.ndarray | None,
|
|
156
|
+
pos_lock: np.ndarray | None,
|
|
157
|
+
) -> list[sens.IErrCalculator]:
|
|
158
|
+
|
|
159
|
+
if samp_times is None:
|
|
160
|
+
samp_times = field.get_time_steps()
|
|
161
|
+
|
|
162
|
+
time_offset = 2.0*np.ones_like(samp_times)
|
|
163
|
+
time_error_data = sens.ErrFieldData(time_offset=time_offset)
|
|
164
|
+
|
|
165
|
+
pos_offset = -1.0*np.ones_like(sens_pos)
|
|
166
|
+
pos_error_data = sens.ErrFieldData(pos_offset_xyz=pos_offset,
|
|
167
|
+
pos_lock_xyz=pos_lock)
|
|
168
|
+
|
|
169
|
+
err_chain = []
|
|
170
|
+
err_chain.append(sens.ErrSysField(field,
|
|
171
|
+
time_error_data,
|
|
172
|
+
sens.EErrDep.DEPENDENT))
|
|
173
|
+
err_chain.append(sens.ErrSysField(field,
|
|
174
|
+
time_error_data,
|
|
175
|
+
sens.EErrDep.DEPENDENT))
|
|
176
|
+
|
|
177
|
+
err_chain.append(sens.ErrSysField(field,
|
|
178
|
+
pos_error_data,
|
|
179
|
+
sens.EErrDep.DEPENDENT))
|
|
180
|
+
err_chain.append(sens.ErrSysField(field,
|
|
181
|
+
pos_error_data,
|
|
182
|
+
sens.EErrDep.DEPENDENT))
|
|
183
|
+
return err_chain
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def calib_assumed(signal: np.ndarray) -> np.ndarray:
|
|
187
|
+
return 24.3*signal + 0.616
|
|
188
|
+
|
|
189
|
+
def calib_truth(signal: np.ndarray) -> np.ndarray:
|
|
190
|
+
return -0.01897 + 25.41881*signal - 0.42456*signal**2 + 0.04365*signal**3
|
|
191
|
+
|
|
192
|
+
def err_chain_calib() -> list[sens.IErrCalculator]:
|
|
193
|
+
signal_calib_range = np.array((0.0,6.0),dtype=np.float64)
|
|
194
|
+
cal_err = sens.ErrSysCalibration(calib_assumed,
|
|
195
|
+
calib_truth,
|
|
196
|
+
signal_calib_range,
|
|
197
|
+
n_cal_divs=10000)
|
|
198
|
+
return [cal_err,]
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def err_chain_2d_dict(field: sens.IField,
|
|
202
|
+
sens_pos: np.ndarray,
|
|
203
|
+
samp_times: np.ndarray | None,
|
|
204
|
+
pos_lock: np.ndarray | None
|
|
205
|
+
) -> dict[str,list[sens.IErrCalculator]]:
|
|
206
|
+
err_cases = {}
|
|
207
|
+
err_cases["none"] = None
|
|
208
|
+
err_cases["basic"] = psens.err_chain_basic()
|
|
209
|
+
err_cases["basic-gen"] = psens.err_chain_gen()
|
|
210
|
+
err_cases["field"] = err_chain_sfield(field,sens_pos,samp_times,pos_lock)
|
|
211
|
+
err_cases["field-dep"] = err_chain_sfield_dep(field,sens_pos,samp_times,pos_lock)
|
|
212
|
+
err_cases["calib"] = err_chain_calib()
|
|
213
|
+
|
|
214
|
+
# This has to be last so when we chain all errors together the saturation
|
|
215
|
+
# error is the last thing that happens
|
|
216
|
+
err_cases["basic-dep"] = psens.err_chain_dep()
|
|
217
|
+
|
|
218
|
+
err_cases["all"] = psens.err_chain_all(err_cases)
|
|
219
|
+
|
|
220
|
+
return err_cases
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def err_chain_3d_dict(field: sens.IField,
|
|
224
|
+
sens_pos: np.ndarray,
|
|
225
|
+
samp_times: np.ndarray | None,
|
|
226
|
+
pos_lock: np.ndarray | None
|
|
227
|
+
) -> dict[str,list[sens.IErrCalculator]]:
|
|
228
|
+
err_cases = {}
|
|
229
|
+
err_cases["none"] = None
|
|
230
|
+
err_cases["basic"] = psens.err_chain_basic()
|
|
231
|
+
err_cases["basic-gen"] = psens.err_chain_gen()
|
|
232
|
+
err_cases["field"] = err_chain_sfield(field,sens_pos,samp_times,pos_lock)
|
|
233
|
+
err_cases["field-dep"] = err_chain_sfield_dep(field,sens_pos,samp_times,pos_lock)
|
|
234
|
+
err_cases["calib"] = err_chain_calib()
|
|
235
|
+
|
|
236
|
+
# This has to be last so when we chain all errors together the saturation
|
|
237
|
+
# error is the last thing that happens
|
|
238
|
+
err_cases["basic-dep"] = psens.err_chain_dep()
|
|
239
|
+
|
|
240
|
+
err_cases["all"] = psens.err_chain_all(err_cases)
|
|
241
|
+
|
|
242
|
+
return err_cases
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def sens_noerrs(sim_data: mh.SimData,
|
|
246
|
+
sens_data: sens.SensorData,
|
|
247
|
+
elem_dims: int) -> sens.SensorArrayPoint:
|
|
248
|
+
descriptor = sens.SensorDescriptorFactory.temperature_descriptor()
|
|
249
|
+
field = sens.FieldScalar(sim_data,
|
|
250
|
+
field_key="temperature",
|
|
251
|
+
elem_dims=elem_dims)
|
|
252
|
+
sens_array = sens.SensorArrayPoint(sens_data,
|
|
253
|
+
field,
|
|
254
|
+
descriptor)
|
|
255
|
+
return sens_array
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def gen_sens_dict_2d(sim_data: mh.SimData,
|
|
259
|
+
sens_data_dict: dict[str, sens.SensorData],
|
|
260
|
+
tag: str
|
|
261
|
+
) -> dict[str, sens.SensorArrayPoint]:
|
|
262
|
+
|
|
263
|
+
sens_dict = {}
|
|
264
|
+
for ss in sens_data_dict:
|
|
265
|
+
sens_array = sens_noerrs(sim_data,
|
|
266
|
+
sens_data_dict[ss],
|
|
267
|
+
elem_dims=2)
|
|
268
|
+
|
|
269
|
+
pos_lock = sens_pos_2d_lock(sens_data_dict[ss].positions)
|
|
270
|
+
for kk in pos_lock:
|
|
271
|
+
if kk in ss:
|
|
272
|
+
pos_lock_key = kk
|
|
273
|
+
break
|
|
274
|
+
|
|
275
|
+
err_chain_dict = err_chain_2d_dict(sens_array.get_field(),
|
|
276
|
+
sens_data_dict[ss].positions,
|
|
277
|
+
sens_data_dict[ss].sample_times,
|
|
278
|
+
pos_lock[pos_lock_key])
|
|
279
|
+
|
|
280
|
+
for ee in err_chain_dict:
|
|
281
|
+
key = f"{tag}_{ss}_err-{ee}"
|
|
282
|
+
sens_dict[key] = copy.deepcopy(sens_array)
|
|
283
|
+
|
|
284
|
+
if err_chain_dict[ee] is not None:
|
|
285
|
+
err_int_opts = sens.ErrIntOpts()
|
|
286
|
+
err_int = sens.ErrIntegrator(err_chain_dict[ee],
|
|
287
|
+
sens_data_dict[ss],
|
|
288
|
+
sens_dict[key].get_measurement_shape(),
|
|
289
|
+
err_int_opts=err_int_opts)
|
|
290
|
+
sens_dict[key].set_error_integrator(err_int)
|
|
291
|
+
|
|
292
|
+
return sens_dict
|
|
293
|
+
|
|
294
|
+
def gen_sens_dict_3d(sim_data: mh.SimData,
|
|
295
|
+
sens_data_dict: dict[str,sens.SensorData],
|
|
296
|
+
tag: str,
|
|
297
|
+
) -> dict[str,sens.SensorArrayPoint]:
|
|
298
|
+
|
|
299
|
+
sens_dict = {}
|
|
300
|
+
for ss in sens_data_dict:
|
|
301
|
+
sens_array = sens_noerrs(sim_data,
|
|
302
|
+
sens_data_dict[ss],
|
|
303
|
+
elem_dims=3)
|
|
304
|
+
|
|
305
|
+
pos_lock = sens_pos_3d_lock(sens_data_dict[ss].positions)
|
|
306
|
+
for kk in pos_lock:
|
|
307
|
+
if kk in ss:
|
|
308
|
+
pos_lock_key = kk
|
|
309
|
+
break
|
|
310
|
+
|
|
311
|
+
err_chain_dict = err_chain_3d_dict(sens_array.get_field(),
|
|
312
|
+
sens_data_dict[ss].positions,
|
|
313
|
+
sens_data_dict[ss].sample_times,
|
|
314
|
+
pos_lock[pos_lock_key])
|
|
315
|
+
|
|
316
|
+
for ee in err_chain_dict:
|
|
317
|
+
key = f"{tag}_{ss}_err-{ee}"
|
|
318
|
+
sens_dict[key] = copy.deepcopy(sens_array)
|
|
319
|
+
|
|
320
|
+
if err_chain_dict[ee] is not None:
|
|
321
|
+
err_int_opts = sens.ErrIntOpts()
|
|
322
|
+
err_int = sens.ErrIntegrator(err_chain_dict[ee],
|
|
323
|
+
sens_data_dict[ss],
|
|
324
|
+
sens_dict[key].get_measurement_shape(),
|
|
325
|
+
err_int_opts=err_int_opts)
|
|
326
|
+
sens_dict[key].set_error_integrator(err_int)
|
|
327
|
+
|
|
328
|
+
return sens_dict
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def sens_2d_dict() -> dict[str,sens.SensorArrayPoint]:
|
|
333
|
+
sens_data_dict = sens_data_2d_dict()
|
|
334
|
+
sim_data = simdata_2d()
|
|
335
|
+
tag = "scal2d"
|
|
336
|
+
return gen_sens_dict_2d(sim_data,sens_data_dict,tag)
|
|
337
|
+
|
|
338
|
+
def sens_3d_dict() -> dict[str,sens.SensorArrayPoint]:
|
|
339
|
+
sens_data_dict = sens_data_3d_dict()
|
|
340
|
+
sim_data = simdata_3d()
|
|
341
|
+
tag = "scal3d"
|
|
342
|
+
return gen_sens_dict_3d(sim_data,sens_data_dict,tag)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#===============================================================================
|
|
2
|
+
# pyvale: the python validation engine
|
|
3
|
+
# License: MIT
|
|
4
|
+
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
+
#===============================================================================
|
|
6
|
+
import copy
|
|
7
|
+
import pyvale.mooseherder as mh
|
|
8
|
+
import pyvale.sensorsim as sens
|
|
9
|
+
import pyvale.verif.psensmech as psensmech
|
|
10
|
+
|
|
11
|
+
"""
|
|
12
|
+
DEVELOPER VERIFICATION MODULE
|
|
13
|
+
--------------------------------------------------------------------------------
|
|
14
|
+
This module contains developer utility functions used for verification testing
|
|
15
|
+
of the point sensor simulation toolbox in pyvale.
|
|
16
|
+
|
|
17
|
+
Specifically, this module contains functions used for testing point sensors
|
|
18
|
+
applied to tensor fields.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
# TODO
|
|
22
|
+
# - Calibration errors for tensor fields
|
|
23
|
+
|
|
24
|
+
def sens_2d_noerrs(sim_data: mh.SimData,
|
|
25
|
+
sens_data: sens.SensorData) -> sens.SensorArrayPoint:
|
|
26
|
+
descriptor = sens.SensorDescriptorFactory.strain_descriptor()
|
|
27
|
+
field_name = "strain"
|
|
28
|
+
norm_comps = ("strain_xx","strain_yy")
|
|
29
|
+
dev_comps = ("strain_xy",)
|
|
30
|
+
field = sens.FieldTensor(sim_data,
|
|
31
|
+
field_name=field_name,
|
|
32
|
+
norm_comps=norm_comps,
|
|
33
|
+
dev_comps=dev_comps,
|
|
34
|
+
elem_dims=2)
|
|
35
|
+
sens_array = sens.SensorArrayPoint(sens_data,
|
|
36
|
+
field,
|
|
37
|
+
descriptor)
|
|
38
|
+
return sens_array
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def sens_3d_noerrs(sim_data: mh.SimData,
|
|
42
|
+
sens_data: sens.SensorData) -> sens.SensorArrayPoint:
|
|
43
|
+
descriptor = sens.SensorDescriptorFactory.strain_descriptor()
|
|
44
|
+
field_name = "strain"
|
|
45
|
+
norm_comps = ("strain_xx","strain_yy","strain_zz")
|
|
46
|
+
dev_comps = ("strain_xy","strain_yz","strain_xz")
|
|
47
|
+
field = sens.FieldTensor(sim_data,
|
|
48
|
+
field_name=field_name,
|
|
49
|
+
norm_comps=norm_comps,
|
|
50
|
+
dev_comps=dev_comps,
|
|
51
|
+
elem_dims=3)
|
|
52
|
+
sens_array = sens.SensorArrayPoint(sens_data,
|
|
53
|
+
field,
|
|
54
|
+
descriptor)
|
|
55
|
+
return sens_array
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def sens_2d_dict() -> dict[str,sens.SensorArrayPoint]:
|
|
59
|
+
sim_data = psensmech.simdata_mech_2d()
|
|
60
|
+
sens_data_dict = psensmech.sens_data_2d_dict()
|
|
61
|
+
|
|
62
|
+
sens_dict = {}
|
|
63
|
+
for ss in sens_data_dict:
|
|
64
|
+
sens_array = sens_2d_noerrs(sim_data,sens_data_dict[ss])
|
|
65
|
+
|
|
66
|
+
pos_lock = psensmech.sens_pos_2d_lock(sens_data_dict[ss].positions)
|
|
67
|
+
for kk in pos_lock:
|
|
68
|
+
if kk in ss:
|
|
69
|
+
pos_lock_key = kk
|
|
70
|
+
break
|
|
71
|
+
|
|
72
|
+
err_chain_dict = psensmech.err_chain_2d_dict(sens_array.get_field(),
|
|
73
|
+
sens_data_dict[ss].positions,
|
|
74
|
+
sens_data_dict[ss].sample_times,
|
|
75
|
+
pos_lock[pos_lock_key])
|
|
76
|
+
|
|
77
|
+
for ee in err_chain_dict:
|
|
78
|
+
tag = f"tens2d_{ss}_err-{ee}"
|
|
79
|
+
sens_dict[tag] = copy.deepcopy(sens_array)
|
|
80
|
+
|
|
81
|
+
if err_chain_dict[ee] is not None:
|
|
82
|
+
err_int_opts = sens.ErrIntOpts()
|
|
83
|
+
err_int = sens.ErrIntegrator(err_chain_dict[ee],
|
|
84
|
+
sens_data_dict[ss],
|
|
85
|
+
sens_dict[tag].get_measurement_shape(),
|
|
86
|
+
err_int_opts=err_int_opts)
|
|
87
|
+
sens_dict[tag].set_error_integrator(err_int)
|
|
88
|
+
|
|
89
|
+
return sens_dict
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def sens_3d_dict() -> dict[str,sens.SensorArrayPoint]:
|
|
93
|
+
sim_data = psensmech.simdata_mech_3d()
|
|
94
|
+
sens_data_dict = psensmech.sens_data_3d_dict()
|
|
95
|
+
|
|
96
|
+
sens_dict = {}
|
|
97
|
+
for ss in sens_data_dict:
|
|
98
|
+
sens_array = sens_3d_noerrs(sim_data,sens_data_dict[ss])
|
|
99
|
+
|
|
100
|
+
pos_lock = psensmech.sens_pos_3d_lock(sens_data_dict[ss].positions)
|
|
101
|
+
for kk in pos_lock:
|
|
102
|
+
if kk in ss:
|
|
103
|
+
pos_lock_key = kk
|
|
104
|
+
break
|
|
105
|
+
|
|
106
|
+
err_chain_dict = psensmech.err_chain_3d_dict(sens_array.get_field(),
|
|
107
|
+
sens_data_dict[ss].positions,
|
|
108
|
+
sens_data_dict[ss].sample_times,
|
|
109
|
+
pos_lock=pos_lock[pos_lock_key])
|
|
110
|
+
|
|
111
|
+
for ee in err_chain_dict:
|
|
112
|
+
tag = f"tens3d_{ss}_err-{ee}"
|
|
113
|
+
sens_dict[tag] = copy.deepcopy(sens_array)
|
|
114
|
+
|
|
115
|
+
if err_chain_dict[ee] is not None:
|
|
116
|
+
err_int_opts = sens.ErrIntOpts()
|
|
117
|
+
err_int = sens.ErrIntegrator(err_chain_dict[ee],
|
|
118
|
+
sens_data_dict[ss],
|
|
119
|
+
sens_dict[tag].get_measurement_shape(),
|
|
120
|
+
err_int_opts=err_int_opts)
|
|
121
|
+
sens_dict[tag].set_error_integrator(err_int)
|
|
122
|
+
|
|
123
|
+
return sens_dict
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#===============================================================================
|
|
2
|
+
# pyvale: the python validation engine
|
|
3
|
+
# License: MIT
|
|
4
|
+
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
+
#===============================================================================
|
|
6
|
+
import copy
|
|
7
|
+
import pyvale.mooseherder as mh
|
|
8
|
+
import pyvale.sensorsim as sens
|
|
9
|
+
import pyvale.verif.psensmech as psensmech
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
DEVELOPER VERIFICATION MODULE
|
|
14
|
+
--------------------------------------------------------------------------------
|
|
15
|
+
This module contains developer utility functions used for verification testing
|
|
16
|
+
of the point sensor simulation toolbox in pyvale.
|
|
17
|
+
|
|
18
|
+
Specifically, this module contains functions used for testing point sensors
|
|
19
|
+
applied to vector fields.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
# TODO
|
|
23
|
+
# - Calibration errors for vector fields
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def sens_2d_noerrs(sim_data: mh.SimData,
|
|
27
|
+
sens_data: sens.SensorData) -> sens.SensorArrayPoint:
|
|
28
|
+
descriptor = sens.SensorDescriptorFactory.displacement_descriptor()
|
|
29
|
+
field = sens.FieldVector(sim_data,
|
|
30
|
+
field_key="disp",
|
|
31
|
+
components=("disp_x","disp_y"),
|
|
32
|
+
elem_dims=2)
|
|
33
|
+
sens_array = sens.SensorArrayPoint(sens_data,
|
|
34
|
+
field,
|
|
35
|
+
descriptor)
|
|
36
|
+
return sens_array
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def sens_3d_noerrs(sim_data: mh.SimData,
|
|
40
|
+
sens_data: sens.SensorData) -> sens.SensorArrayPoint:
|
|
41
|
+
descriptor = sens.SensorDescriptorFactory.displacement_descriptor()
|
|
42
|
+
field = sens.FieldVector(sim_data,
|
|
43
|
+
field_key="disp",
|
|
44
|
+
components=("disp_x","disp_y","disp_z"),
|
|
45
|
+
elem_dims=3)
|
|
46
|
+
sens_array = sens.SensorArrayPoint(sens_data,
|
|
47
|
+
field,
|
|
48
|
+
descriptor)
|
|
49
|
+
return sens_array
|
|
50
|
+
|
|
51
|
+
def sens_2d_dict() -> dict[str,sens.SensorArrayPoint]:
|
|
52
|
+
sim_data = psensmech.simdata_mech_2d()
|
|
53
|
+
sens_data_dict = psensmech.sens_data_2d_dict()
|
|
54
|
+
|
|
55
|
+
sens_dict = {}
|
|
56
|
+
for ss in sens_data_dict:
|
|
57
|
+
sens_array = sens_2d_noerrs(sim_data,sens_data_dict[ss])
|
|
58
|
+
|
|
59
|
+
pos_lock = psensmech.sens_pos_2d_lock(sens_data_dict[ss].positions)
|
|
60
|
+
for kk in pos_lock:
|
|
61
|
+
if kk in ss:
|
|
62
|
+
pos_lock_key = kk
|
|
63
|
+
break
|
|
64
|
+
|
|
65
|
+
err_chain_dict = psensmech.err_chain_2d_dict(sens_array.get_field(),
|
|
66
|
+
sens_data_dict[ss].positions,
|
|
67
|
+
sens_data_dict[ss].sample_times,
|
|
68
|
+
pos_lock[pos_lock_key])
|
|
69
|
+
|
|
70
|
+
for ee in err_chain_dict:
|
|
71
|
+
tag = f"vec2d_{ss}_err-{ee}"
|
|
72
|
+
sens_dict[tag] = copy.deepcopy(sens_array)
|
|
73
|
+
|
|
74
|
+
if err_chain_dict[ee] is not None:
|
|
75
|
+
err_int_opts = sens.ErrIntOpts()
|
|
76
|
+
err_int = sens.ErrIntegrator(err_chain_dict[ee],
|
|
77
|
+
sens_data_dict[ss],
|
|
78
|
+
sens_dict[tag].get_measurement_shape(),
|
|
79
|
+
err_int_opts=err_int_opts)
|
|
80
|
+
sens_dict[tag].set_error_integrator(err_int)
|
|
81
|
+
|
|
82
|
+
return sens_dict
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def sens_3d_dict() -> dict[str,sens.SensorArrayPoint]:
|
|
86
|
+
sim_data = psensmech.simdata_mech_3d()
|
|
87
|
+
sens_data_dict = psensmech.sens_data_3d_dict()
|
|
88
|
+
|
|
89
|
+
sens_dict = {}
|
|
90
|
+
for ss in sens_data_dict:
|
|
91
|
+
sens_array = sens_3d_noerrs(sim_data,sens_data_dict[ss])
|
|
92
|
+
|
|
93
|
+
pos_lock = psensmech.sens_pos_3d_lock(sens_data_dict[ss].positions)
|
|
94
|
+
for kk in pos_lock:
|
|
95
|
+
if kk in ss:
|
|
96
|
+
pos_lock_key = kk
|
|
97
|
+
break
|
|
98
|
+
|
|
99
|
+
err_chain_dict = psensmech.err_chain_3d_dict(sens_array.get_field(),
|
|
100
|
+
sens_data_dict[ss].positions,
|
|
101
|
+
sens_data_dict[ss].sample_times,
|
|
102
|
+
pos_lock=pos_lock[pos_lock_key])
|
|
103
|
+
|
|
104
|
+
for ee in err_chain_dict:
|
|
105
|
+
tag = f"vec3d_{ss}_err-{ee}"
|
|
106
|
+
sens_dict[tag] = copy.deepcopy(sens_array)
|
|
107
|
+
|
|
108
|
+
if err_chain_dict[ee] is not None:
|
|
109
|
+
err_int_opts = sens.ErrIntOpts()
|
|
110
|
+
err_int = sens.ErrIntegrator(err_chain_dict[ee],
|
|
111
|
+
sens_data_dict[ss],
|
|
112
|
+
sens_dict[tag].get_measurement_shape(),
|
|
113
|
+
err_int_opts=err_int_opts)
|
|
114
|
+
sens_dict[tag].set_error_integrator(err_int)
|
|
115
|
+
|
|
116
|
+
return sens_dict
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyvale
|
|
3
|
-
Version: 2025.
|
|
3
|
+
Version: 2025.8.1
|
|
4
4
|
Summary: An all-in-one package for sensor simulation, sensor uncertainty quantification, sensor placement optimisation and simulation calibration or validation.
|
|
5
5
|
Author-email: "scepticalrabbit et al." <thescepticalrabbit@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -29,7 +29,6 @@ Project-URL: Issue Tracker, https://github.com/Digital-Validation-Laboratory/pyv
|
|
|
29
29
|
Requires-Python: ==3.11.*
|
|
30
30
|
Description-Content-Type: text/markdown
|
|
31
31
|
License-File: LICENSE
|
|
32
|
-
Requires-Dist: mooseherder>=0.1.0
|
|
33
32
|
Requires-Dist: numpy<2.0.0
|
|
34
33
|
Requires-Dist: scipy>=1.14.0
|
|
35
34
|
Requires-Dist: netCDF4>=1.6.5
|
|
@@ -54,22 +53,22 @@ Dynamic: license-file
|
|
|
54
53
|
# pyvale
|
|
55
54
|

|
|
56
55
|
|
|
57
|
-
The python validation engine (`pyvale`) is
|
|
56
|
+
The python validation engine (`pyvale`) is your virtual engineering laboratory: An all-in-one package for sensor simulation, sensor uncertainty quantification, sensor placement optimisation and simulation calibration/validation. Used to simulate experimental data from an input multi-physics simulation by explicitly modelling sensors with realistic uncertainties. Useful for experimental design, sensor placement optimisation, testing simulation validation metrics and virtually testing digital shadows/twins.
|
|
58
57
|
|
|
59
|
-
We
|
|
58
|
+
We are actively developing dedicated tools for simulation and uncertainty quantification of imaging sensors including digital image correlation (DIC) and infra-red thermography (IRT). Check out the [documentation](https://computer-aided-validation-laboratory.github.io/pyvale/index.html) to get started with some of our examples.
|
|
60
59
|
|
|
61
60
|
## Quick Demo: Simulating Point Sensors
|
|
62
61
|
Here we demonstrate how `pyvale` can be used to simulate thermocouples and strain gauges applied to a [MOOSE](https://mooseframework.inl.gov/index.html) thermo-mechanical simulation of a fusion divertor armour heatsink. The figures below show visualisations of the virtual thermocouple and strain gauge locations on the simualtion mesh as well as time traces for each sensor over a series of simulated experiments.
|
|
63
62
|
|
|
64
|
-
The code to run the simulated experiments and produce the output shown here comes from [this example](https://computer-aided-validation-laboratory.github.io/pyvale/examples/
|
|
63
|
+
The code to run the simulated experiments and produce the output shown here comes from [this example](https://computer-aided-validation-laboratory.github.io/pyvale/examples/basics/ex4_2_expsim3d_thermmech3d.html). You can find more examples and details of `pyvale` python API in the `pyvale` [documentation](https://computer-aided-validation-laboratory.github.io/pyvale/index.html).
|
|
65
64
|
|
|
66
65
|
|||
|
|
67
66
|
|--|--|
|
|
68
|
-
|*Visualisation of the
|
|
67
|
+
|*Visualisation of the thermocouple locations.*|*Visualisation of the strain gauge locations.*|
|
|
69
68
|
|
|
70
69
|
|||
|
|
71
70
|
|--|--|
|
|
72
|
-
|*
|
|
71
|
+
|*Thermocouple time traces over a series of simulated experiments.*|*Strain gauge time traces over a series of simulated experiments.*|
|
|
73
72
|
|
|
74
73
|
|
|
75
74
|
## Quick Install
|