pyvale 2025.7.1__cp311-cp311-win_amd64.whl → 2025.8.1__cp311-cp311-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyvale might be problematic. Click here for more details.
- 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/dic/cpp/dicfourier.cpp +36 -4
- pyvale/dic/cpp/dicinterpolator.cpp +56 -1
- pyvale/dic/cpp/dicmain.cpp +24 -19
- pyvale/dic/cpp/dicoptimizer.cpp +6 -1
- pyvale/dic/cpp/dicscanmethod.cpp +32 -32
- pyvale/dic/cpp/dicsignalhandler.cpp +16 -0
- pyvale/dic/cpp/dicstrain.cpp +7 -3
- pyvale/dic/cpp/dicutil.cpp +79 -23
- pyvale/{dic2d.py → dic/dic2d.py} +51 -29
- pyvale/dic/dic2dconv.py +6 -0
- pyvale/dic/dic2dcpp.cp311-win_amd64.pyd +0 -0
- pyvale/{dicchecks.py → dic/dicchecks.py} +28 -16
- pyvale/dic/dicdataimport.py +370 -0
- pyvale/{dicregionofinterest.py → dic/dicregionofinterest.py} +169 -12
- pyvale/{dicresults.py → dic/dicresults.py} +4 -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.1.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/dic2dcpp.cp311-win_amd64.pyd +0 -0
- pyvale/dicdataimport.py +0 -247
- pyvale/simtools.py +0 -67
- pyvale-2025.7.1.dist-info/RECORD +0 -211
- /pyvale/{blendercalibrationdata.py → blender/blendercalibrationdata.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.1.dist-info → pyvale-2025.8.1.dist-info}/WHEEL +0 -0
- {pyvale-2025.7.1.dist-info → pyvale-2025.8.1.dist-info}/licenses/LICENSE +0 -0
- {pyvale-2025.7.1.dist-info → pyvale-2025.8.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#===============================================================================
|
|
2
|
+
# pyvale: the python validation engine
|
|
3
|
+
# License: MIT
|
|
4
|
+
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
+
#===============================================================================
|
|
6
|
+
import numpy as np
|
|
7
|
+
import pyvale.mooseherder as mh
|
|
8
|
+
import pyvale.sensorsim as sens
|
|
9
|
+
import pyvale.verif.psens as psens
|
|
10
|
+
import pyvale.verif.psensconst as psensconst
|
|
11
|
+
import pyvale.dataset as dataset
|
|
12
|
+
|
|
13
|
+
"""
|
|
14
|
+
DEVELOPER VERIFICATION MODULE
|
|
15
|
+
--------------------------------------------------------------------------------
|
|
16
|
+
This module contains developer utility functions used for verification testing
|
|
17
|
+
of the point sensor simulation toolbox in pyvale.
|
|
18
|
+
|
|
19
|
+
Specifically, this module contains functions used for testing point sensors
|
|
20
|
+
applied to mechanical fields (displacement/strain) for testing vector and tensor
|
|
21
|
+
field point sensors.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def simdata_mech_2d() -> mh.SimData:
|
|
25
|
+
data_path = dataset.mechanical_2d_path()
|
|
26
|
+
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
27
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
28
|
+
sim_data=sim_data,
|
|
29
|
+
disp_comps=("disp_x","disp_y"))
|
|
30
|
+
return sim_data
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def simdata_mech_3d() -> mh.SimData:
|
|
34
|
+
data_path = dataset.element_case_output_path(dataset.EElemTest.HEX20)
|
|
35
|
+
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
36
|
+
field_comps = ("disp_x","disp_y","disp_z")
|
|
37
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
38
|
+
sim_data=sim_data,
|
|
39
|
+
disp_comps=field_comps)
|
|
40
|
+
return sim_data
|
|
41
|
+
|
|
42
|
+
def sens_pos_2d() -> dict[str,np.ndarray]:
|
|
43
|
+
sim_dims = sens.SimTools.get_sim_dims(simdata_mech_2d())
|
|
44
|
+
sens_pos = {}
|
|
45
|
+
|
|
46
|
+
x_lims = sim_dims["x"]
|
|
47
|
+
y_lims = sim_dims["y"]
|
|
48
|
+
z_lims = (0,0)
|
|
49
|
+
|
|
50
|
+
n_sens = (1,4,1)
|
|
51
|
+
sens_pos["line-4"] = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
52
|
+
|
|
53
|
+
n_sens = (2,3,1)
|
|
54
|
+
sens_pos["grid-23"] = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
55
|
+
|
|
56
|
+
return sens_pos
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def sens_pos_3d() -> dict[str,np.ndarray]:
|
|
60
|
+
sens_pos = {}
|
|
61
|
+
sens_pos["cent-cube"] = np.array(((5.0,0.0,5.0), # xz
|
|
62
|
+
(5.0,10.0,5.0), # xz
|
|
63
|
+
(5.0,5.0,0.0), # xy
|
|
64
|
+
(5.0,5.0,10.0), # xy
|
|
65
|
+
(0.0,5.0,5.0), # yz
|
|
66
|
+
(10.0,5.0,5.0),)) # yz
|
|
67
|
+
return sens_pos
|
|
68
|
+
|
|
69
|
+
def sens_pos_2d_lock(sens_pos: np.ndarray) -> dict[str,np.ndarray]:
|
|
70
|
+
pos_lock = {}
|
|
71
|
+
(xx,yy,zz) = (0,1,2)
|
|
72
|
+
|
|
73
|
+
lock = np.full_like(sens_pos,False,dtype=bool)
|
|
74
|
+
lock[:,zz] = True # lock z
|
|
75
|
+
pos_lock["line-4"] = None
|
|
76
|
+
|
|
77
|
+
lock = np.full_like(sens_pos,False,dtype=bool)
|
|
78
|
+
lock[:,zz] = True # lock z
|
|
79
|
+
pos_lock["grid-23"] = None
|
|
80
|
+
|
|
81
|
+
return pos_lock
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def sens_pos_3d_lock(sens_pos: np.ndarray) -> dict[str,np.ndarray]:
|
|
85
|
+
pos_lock = {}
|
|
86
|
+
(xx,yy,zz) = (0,1,2)
|
|
87
|
+
|
|
88
|
+
lock = np.full_like(sens_pos,False,dtype=bool)
|
|
89
|
+
lock[0,yy] = True
|
|
90
|
+
lock[1,yy] = True
|
|
91
|
+
lock[2,zz] = True
|
|
92
|
+
lock[3,zz] = True
|
|
93
|
+
lock[4,xx] = True
|
|
94
|
+
lock[5,xx] = True
|
|
95
|
+
pos_lock["cent-cube"] = lock
|
|
96
|
+
|
|
97
|
+
return pos_lock
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def sens_data_2d_dict() -> dict[str,sens.SensorData]:
|
|
101
|
+
return psens.sens_data_dict(simdata_mech_2d(),sens_pos_2d())
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def sens_data_3d_dict() -> dict[str,sens.SensorData]:
|
|
105
|
+
return psens.sens_data_dict(simdata_mech_3d(),sens_pos_3d())
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def err_chain_field(field: sens.IField,
|
|
109
|
+
sens_pos: np.ndarray,
|
|
110
|
+
samp_times: np.ndarray | None,
|
|
111
|
+
pos_lock: np.ndarray | None,
|
|
112
|
+
) -> list[sens.IErrCalculator]:
|
|
113
|
+
|
|
114
|
+
if samp_times is None:
|
|
115
|
+
samp_times = field.get_time_steps()
|
|
116
|
+
|
|
117
|
+
pos_offset_xyz = np.array((1.0,1.0,-1.0),dtype=np.float64)
|
|
118
|
+
pos_offset_xyz = np.tile(pos_offset_xyz,(sens_pos.shape[0],1))
|
|
119
|
+
|
|
120
|
+
time_offset = np.full((samp_times.shape[0],),0.1)
|
|
121
|
+
|
|
122
|
+
pos_rand = sens.GenNormal(std=1.0,
|
|
123
|
+
mean=0.0,
|
|
124
|
+
seed=psensconst.GOLD_SEED) # units = mm
|
|
125
|
+
time_rand = sens.GenNormal(std=0.1,
|
|
126
|
+
mean=0.0,
|
|
127
|
+
seed=psensconst.GOLD_SEED) # units = s
|
|
128
|
+
ang_rand = sens.GenUniform(low=-1.0,
|
|
129
|
+
high=1.0,
|
|
130
|
+
seed=psensconst.GOLD_SEED)
|
|
131
|
+
|
|
132
|
+
field_err_data = sens.ErrFieldData(
|
|
133
|
+
pos_offset_xyz=pos_offset_xyz,
|
|
134
|
+
time_offset=time_offset,
|
|
135
|
+
pos_rand_xyz=(pos_rand,pos_rand,pos_rand),
|
|
136
|
+
ang_rand_zyx=(ang_rand,ang_rand,ang_rand),
|
|
137
|
+
time_rand=time_rand,
|
|
138
|
+
pos_lock_xyz=pos_lock,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
err_chain = []
|
|
142
|
+
err_chain.append(sens.ErrSysField(field,
|
|
143
|
+
field_err_data))
|
|
144
|
+
return err_chain
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def err_chain_field_dep(field: sens.IField,
|
|
148
|
+
sens_pos: np.ndarray,
|
|
149
|
+
samp_times: np.ndarray | None,
|
|
150
|
+
pos_lock: np.ndarray | None,
|
|
151
|
+
) -> list[sens.IErrCalculator]:
|
|
152
|
+
|
|
153
|
+
if samp_times is None:
|
|
154
|
+
samp_times = field.get_time_steps()
|
|
155
|
+
|
|
156
|
+
time_offset = 2.0*np.ones_like(samp_times)
|
|
157
|
+
time_error_data = sens.ErrFieldData(time_offset=time_offset)
|
|
158
|
+
|
|
159
|
+
pos_offset = -1.0*np.ones_like(sens_pos)
|
|
160
|
+
pos_error_data = sens.ErrFieldData(pos_offset_xyz=pos_offset,
|
|
161
|
+
pos_lock_xyz=pos_lock)
|
|
162
|
+
|
|
163
|
+
angle_offset = np.ones_like(sens_pos)
|
|
164
|
+
angle_error_data = sens.ErrFieldData(ang_offset_zyx=angle_offset)
|
|
165
|
+
|
|
166
|
+
err_chain = []
|
|
167
|
+
err_chain.append(sens.ErrSysField(field,
|
|
168
|
+
time_error_data,
|
|
169
|
+
sens.EErrDep.DEPENDENT))
|
|
170
|
+
err_chain.append(sens.ErrSysField(field,
|
|
171
|
+
time_error_data,
|
|
172
|
+
sens.EErrDep.DEPENDENT))
|
|
173
|
+
err_chain.append(sens.ErrSysField(field,
|
|
174
|
+
pos_error_data,
|
|
175
|
+
sens.EErrDep.DEPENDENT))
|
|
176
|
+
err_chain.append(sens.ErrSysField(field,
|
|
177
|
+
pos_error_data,
|
|
178
|
+
sens.EErrDep.DEPENDENT))
|
|
179
|
+
err_chain.append(sens.ErrSysField(field,
|
|
180
|
+
angle_error_data,
|
|
181
|
+
sens.EErrDep.DEPENDENT))
|
|
182
|
+
err_chain.append(sens.ErrSysField(field,
|
|
183
|
+
angle_error_data,
|
|
184
|
+
sens.EErrDep.DEPENDENT))
|
|
185
|
+
return err_chain
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def err_chain_2d_dict(field: sens.IField,
|
|
189
|
+
sens_pos: np.ndarray,
|
|
190
|
+
samp_times: np.ndarray | None,
|
|
191
|
+
pos_lock: np.ndarray | None
|
|
192
|
+
) -> dict[str,list[sens.IErrCalculator]]:
|
|
193
|
+
err_cases = {}
|
|
194
|
+
err_cases["none"] = None
|
|
195
|
+
err_cases["basic"] = psens.err_chain_basic()
|
|
196
|
+
err_cases["basic-gen"] = psens.err_chain_gen()
|
|
197
|
+
err_cases["field"] = err_chain_field(field,sens_pos,samp_times,pos_lock)
|
|
198
|
+
err_cases["field-dep"] = err_chain_field_dep(field,sens_pos,samp_times,pos_lock)
|
|
199
|
+
|
|
200
|
+
# This has to be last so when we chain all errors together the saturation
|
|
201
|
+
# error is the last thing that happens
|
|
202
|
+
err_cases["basic-dep"] = psens.err_chain_dep()
|
|
203
|
+
|
|
204
|
+
err_cases["all"] = psens.err_chain_all(err_cases)
|
|
205
|
+
|
|
206
|
+
return err_cases
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def err_chain_3d_dict(field: sens.IField,
|
|
210
|
+
sens_pos: np.ndarray,
|
|
211
|
+
samp_times: np.ndarray | None,
|
|
212
|
+
pos_lock: np.ndarray | None
|
|
213
|
+
) -> dict[str,list[sens.IErrCalculator]]:
|
|
214
|
+
err_cases = {}
|
|
215
|
+
err_cases["none"] = None
|
|
216
|
+
err_cases["basic"] = psens.err_chain_basic()
|
|
217
|
+
err_cases["basic-gen"] = psens.err_chain_gen()
|
|
218
|
+
err_cases["field"] = err_chain_field(field,sens_pos,samp_times,pos_lock)
|
|
219
|
+
err_cases["field-dep"] = err_chain_field_dep(field,sens_pos,samp_times,pos_lock)
|
|
220
|
+
|
|
221
|
+
# This has to be last so when we chain all errors together the saturation
|
|
222
|
+
# error is the last thing that happens
|
|
223
|
+
err_cases["basic-dep"] = psens.err_chain_dep()
|
|
224
|
+
|
|
225
|
+
err_cases["all"] = psens.err_chain_all(err_cases)
|
|
226
|
+
|
|
227
|
+
return err_cases
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#===============================================================================
|
|
2
|
+
# pyvale: the python validation engine
|
|
3
|
+
# License: MIT
|
|
4
|
+
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
+
#===============================================================================
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
import copy
|
|
8
|
+
import numpy as np
|
|
9
|
+
import pyvale.mooseherder as mh
|
|
10
|
+
import pyvale.sensorsim as sens
|
|
11
|
+
import pyvale.verif.psens as psens
|
|
12
|
+
import pyvale.verif.psensscalar as psensscalar
|
|
13
|
+
import pyvale.verif.psensvector as psensvector
|
|
14
|
+
import pyvale.verif.psenstensor as psenstensor
|
|
15
|
+
import pyvale.verif.psensmech as psensmech
|
|
16
|
+
import pyvale.dataset as dataset
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def load_simdata_list(data_paths: list[Path],
|
|
20
|
+
disp_comps: tuple[str,...]) -> list[mh.SimData]:
|
|
21
|
+
sim_list = []
|
|
22
|
+
for pp in data_paths:
|
|
23
|
+
sim_data = mh.ExodusReader(pp).read_all_sim_data()
|
|
24
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
25
|
+
sim_data=sim_data,
|
|
26
|
+
disp_comps=disp_comps)
|
|
27
|
+
sim_list.append(sim_data)
|
|
28
|
+
|
|
29
|
+
return sim_list
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def simdata_list_2d() -> list[mh.SimData]:
|
|
33
|
+
data_paths = dataset.thermomechanical_2d_experiment_paths()
|
|
34
|
+
disp_comps = ("disp_x","disp_y")
|
|
35
|
+
return load_simdata_list(data_paths,disp_comps)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def simdata_list_3d() -> list[mh.SimData]:
|
|
39
|
+
data_paths = [dataset.element_case_output_path(dataset.EElemTest.TET4),
|
|
40
|
+
dataset.element_case_output_path(dataset.EElemTest.TET10),
|
|
41
|
+
dataset.element_case_output_path(dataset.EElemTest.HEX8),
|
|
42
|
+
dataset.element_case_output_path(dataset.EElemTest.HEX20)]
|
|
43
|
+
disp_comps = ("disp_x","disp_y","disp_z")
|
|
44
|
+
return load_simdata_list(data_paths,disp_comps)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def sens_pos_2d() -> dict[str,np.ndarray]:
|
|
48
|
+
# Geometry does not change
|
|
49
|
+
sim_dims = sens.SimTools.get_sim_dims(simdata_list_2d()[0])
|
|
50
|
+
sens_pos = {}
|
|
51
|
+
|
|
52
|
+
x_lims = sim_dims["x"]
|
|
53
|
+
y_lims = sim_dims["y"]
|
|
54
|
+
z_lims = (0,0)
|
|
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
|
+
def sens_pos_2d_lock(sens_pos: np.ndarray) -> dict[str,np.ndarray]:
|
|
62
|
+
pos_lock = {}
|
|
63
|
+
(xx,yy,zz) = (0,1,2)
|
|
64
|
+
|
|
65
|
+
lock = np.full_like(sens_pos,False,dtype=bool)
|
|
66
|
+
lock[:,zz] = True # lock z
|
|
67
|
+
pos_lock["grid-22"] = None
|
|
68
|
+
|
|
69
|
+
return pos_lock
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def sens_pos_3d_lock(sens_pos: np.ndarray) -> dict[str,np.ndarray]:
|
|
73
|
+
pos_lock = {}
|
|
74
|
+
(xx,yy,zz) = (0,1,2)
|
|
75
|
+
|
|
76
|
+
lock = np.full_like(sens_pos,False,dtype=bool)
|
|
77
|
+
lock[0,yy] = True
|
|
78
|
+
lock[1,yy] = True
|
|
79
|
+
lock[2,zz] = True
|
|
80
|
+
lock[3,zz] = True
|
|
81
|
+
lock[4,xx] = True
|
|
82
|
+
lock[5,xx] = True
|
|
83
|
+
pos_lock["cent-cube"] = lock
|
|
84
|
+
|
|
85
|
+
return pos_lock
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def sens_pos_3d() -> dict[str,np.ndarray]:
|
|
89
|
+
sens_pos = {}
|
|
90
|
+
sens_pos["cent-cube"] = np.array(((5.0,0.0,5.0), # xz
|
|
91
|
+
(5.0,10.0,5.0), # xz
|
|
92
|
+
(5.0,5.0,0.0), # xy
|
|
93
|
+
(5.0,5.0,10.0), # xy
|
|
94
|
+
(0.0,5.0,5.0), # yz
|
|
95
|
+
(10.0,5.0,5.0),)) # yz
|
|
96
|
+
return sens_pos
|
|
97
|
+
|
|
98
|
+
def sens_data_2d_dict() -> dict[str,sens.SensorData]:
|
|
99
|
+
# Time steps don't change so can take first sim here
|
|
100
|
+
return psens.sens_data_dict(simdata_list_2d()[0],sens_pos_2d())
|
|
101
|
+
|
|
102
|
+
def sens_data_3d_dict() -> dict[str,sens.SensorData]:
|
|
103
|
+
# Time steps don't change so can take first sim here
|
|
104
|
+
return psens.sens_data_dict(simdata_list_3d()[0],sens_pos_3d())
|
|
105
|
+
|
|
106
|
+
def exp_sim_2d() -> dict[str,sens.ExperimentSimulator]:
|
|
107
|
+
sens_data_dict = sens_data_2d_dict()
|
|
108
|
+
sim_list = simdata_list_2d()
|
|
109
|
+
|
|
110
|
+
fields = ("scal","vect","tens")
|
|
111
|
+
exp_sims = {}
|
|
112
|
+
for ss in sens_data_dict:
|
|
113
|
+
|
|
114
|
+
sens_noerrs = {}
|
|
115
|
+
sens_noerrs["scal"] = psensscalar.sens_noerrs(sim_list[0],
|
|
116
|
+
sens_data_dict[ss],
|
|
117
|
+
elem_dims=2)
|
|
118
|
+
sens_noerrs["vect"] = psensvector.sens_2d_noerrs(sim_list[0],
|
|
119
|
+
sens_data_dict[ss])
|
|
120
|
+
sens_noerrs["tens"] = psenstensor.sens_2d_noerrs(sim_list[0],
|
|
121
|
+
sens_data_dict[ss])
|
|
122
|
+
|
|
123
|
+
pos_lock = sens_pos_2d_lock(sens_data_dict[ss].positions)
|
|
124
|
+
for kk in pos_lock:
|
|
125
|
+
if kk in ss:
|
|
126
|
+
pos_lock_key = kk
|
|
127
|
+
break
|
|
128
|
+
|
|
129
|
+
err_chain_dict={}
|
|
130
|
+
err_chain_dict["scal"] = psensscalar.err_chain_2d_dict(
|
|
131
|
+
sens_noerrs["scal"].get_field(),
|
|
132
|
+
sens_data_dict[ss].positions,
|
|
133
|
+
sens_data_dict[ss].sample_times,
|
|
134
|
+
pos_lock[pos_lock_key]
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
err_chain_dict["vect"] = psensmech.err_chain_2d_dict(
|
|
138
|
+
sens_noerrs["vect"].get_field(),
|
|
139
|
+
sens_data_dict[ss].positions,
|
|
140
|
+
sens_data_dict[ss].sample_times,
|
|
141
|
+
pos_lock[pos_lock_key]
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
err_chain_dict["tens"] = psensmech.err_chain_2d_dict(
|
|
145
|
+
sens_noerrs["tens"].get_field(),
|
|
146
|
+
sens_data_dict[ss].positions,
|
|
147
|
+
sens_data_dict[ss].sample_times,
|
|
148
|
+
pos_lock[pos_lock_key]
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
common_keys = (err_chain_dict["scal"].keys() &
|
|
152
|
+
err_chain_dict["vect"].keys() &
|
|
153
|
+
err_chain_dict["tens"].keys())
|
|
154
|
+
# print(80*"=")
|
|
155
|
+
# print(common_keys)
|
|
156
|
+
# print(80*"=")
|
|
157
|
+
|
|
158
|
+
for ee in common_keys:
|
|
159
|
+
tag = f"exp2d_{ss}_err-{ee}"
|
|
160
|
+
|
|
161
|
+
sensor_arrays = []
|
|
162
|
+
for ff in fields:
|
|
163
|
+
this_sens = copy.deepcopy(sens_noerrs[ff])
|
|
164
|
+
# print(80*"-")
|
|
165
|
+
# print(f"{ff=}")
|
|
166
|
+
# print(f"{ee=}")
|
|
167
|
+
# print(80*"-")
|
|
168
|
+
if err_chain_dict[ff][ee] is not None:
|
|
169
|
+
err_int_opts = sens.ErrIntOpts
|
|
170
|
+
err_int = sens.ErrIntegrator(err_chain_dict[ff][ee],
|
|
171
|
+
sens_data_dict[ss],
|
|
172
|
+
this_sens.get_measurement_shape(),
|
|
173
|
+
err_int_opts=err_int_opts)
|
|
174
|
+
this_sens.set_error_integrator(err_int)
|
|
175
|
+
|
|
176
|
+
sensor_arrays.append(this_sens)
|
|
177
|
+
|
|
178
|
+
sim_list = simdata_list_2d()
|
|
179
|
+
sensor_arrays = [sens_noerrs["scal"],sens_noerrs["vect"],sens_noerrs["tens"]]
|
|
180
|
+
exp_sim = sens.ExperimentSimulator(sim_list,
|
|
181
|
+
sensor_arrays,
|
|
182
|
+
num_exp_per_sim=10)
|
|
183
|
+
exp_sims[tag] = exp_sim
|
|
184
|
+
|
|
185
|
+
return exp_sims
|
|
186
|
+
|
|
187
|
+
|