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
|
@@ -23,39 +23,42 @@ Test case: point displacement sensors on a 2D plate with hole loaded in tension
|
|
|
23
23
|
import numpy as np
|
|
24
24
|
import matplotlib.pyplot as plt
|
|
25
25
|
from scipy.spatial.transform import Rotation
|
|
26
|
-
|
|
27
|
-
|
|
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
|
# First we are going to setup the same displacement sensor array on the 2D
|
|
31
34
|
# solid mechanics test case we have used previously. This will serve as a
|
|
32
35
|
# baseline with no sensor rotation.
|
|
33
|
-
data_path =
|
|
36
|
+
data_path = dataset.mechanical_2d_path()
|
|
34
37
|
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
35
38
|
|
|
36
39
|
field_name = "disp"
|
|
37
40
|
field_comps = ("disp_x","disp_y")
|
|
38
|
-
sim_data =
|
|
41
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
39
42
|
sim_data=sim_data,
|
|
40
43
|
disp_comps=field_comps)
|
|
41
44
|
|
|
42
|
-
descriptor =
|
|
45
|
+
descriptor = sens.SensorDescriptorFactory.displacement_descriptor()
|
|
43
46
|
|
|
44
|
-
disp_field =
|
|
47
|
+
disp_field = sens.FieldVector(sim_data,field_name,field_comps,elem_dims=2)
|
|
45
48
|
|
|
46
49
|
n_sens = (2,3,1)
|
|
47
50
|
x_lims = (0.0,100.0)
|
|
48
51
|
y_lims = (0.0,150.0)
|
|
49
52
|
z_lims = (0.0,0.0)
|
|
50
|
-
sens_pos =
|
|
53
|
+
sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
51
54
|
|
|
52
55
|
|
|
53
56
|
sample_times = np.linspace(0.0,np.max(sim_data.time),50)
|
|
54
57
|
|
|
55
|
-
sens_data_norot =
|
|
58
|
+
sens_data_norot = sens.SensorData(positions=sens_pos,
|
|
56
59
|
sample_times=sample_times)
|
|
57
60
|
|
|
58
|
-
disp_sens_norot =
|
|
61
|
+
disp_sens_norot = sens.SensorArrayPoint(sens_data_norot,
|
|
59
62
|
disp_field,
|
|
60
63
|
descriptor)
|
|
61
64
|
|
|
@@ -78,11 +81,11 @@ sens_angles = sens_pos.shape[0] * \
|
|
|
78
81
|
sens_angles = (Rotation.from_euler("zyx", [45, 0, 0], degrees=True),)
|
|
79
82
|
|
|
80
83
|
|
|
81
|
-
sens_data_rot =
|
|
84
|
+
sens_data_rot = sens.SensorData(positions=sens_pos,
|
|
82
85
|
sample_times=sample_times,
|
|
83
86
|
angles=sens_angles)
|
|
84
87
|
|
|
85
|
-
disp_sens_rot =
|
|
88
|
+
disp_sens_rot = sens.SensorArrayPoint(sens_data_rot,
|
|
86
89
|
disp_field,
|
|
87
90
|
descriptor)
|
|
88
91
|
|
|
@@ -93,13 +96,13 @@ disp_sens_rot = pyv.SensorArrayPoint(sens_data_rot,
|
|
|
93
96
|
# the random generator should provide the perturbation in degrees.
|
|
94
97
|
angle_offset = np.zeros_like(sens_pos)
|
|
95
98
|
angle_offset[:,0] = 2.0 # only rotate about z in 2D
|
|
96
|
-
angle_rand = (
|
|
97
|
-
angle_error_data =
|
|
99
|
+
angle_rand = (sens.GenNormal(std=2.0),None,None)
|
|
100
|
+
angle_error_data = sens.ErrFieldData(ang_offset_zyx=angle_offset,
|
|
98
101
|
ang_rand_zyx=angle_rand)
|
|
99
102
|
|
|
100
103
|
|
|
101
|
-
sys_err_rot =
|
|
102
|
-
sys_err_int =
|
|
104
|
+
sys_err_rot = sens.ErrSysField(disp_field,angle_error_data)
|
|
105
|
+
sys_err_int = sens.ErrIntegrator([sys_err_rot],
|
|
103
106
|
sens_data_rot,
|
|
104
107
|
disp_sens_rot.get_measurement_shape())
|
|
105
108
|
disp_sens_rot.set_error_integrator(sys_err_int)
|
|
@@ -121,7 +124,7 @@ print("ROTATED SENSORS WITH ANGLE ERRORS:")
|
|
|
121
124
|
print(f"These are the last {time_last} virtual measurements of sensor "
|
|
122
125
|
+ f"{sens_print} for {field_comps[comp_print]}:")
|
|
123
126
|
|
|
124
|
-
|
|
127
|
+
sens.print_measurements(disp_sens_rot,sens_print,comp_print,time_print)
|
|
125
128
|
|
|
126
129
|
print(80*"-")
|
|
127
130
|
|
|
@@ -129,9 +132,9 @@ print(80*"-")
|
|
|
129
132
|
# We can now plot the traces for the non-rotated and rotated sensors to
|
|
130
133
|
# compare them:
|
|
131
134
|
for ff in field_comps:
|
|
132
|
-
(_,ax) =
|
|
135
|
+
(_,ax) = sens.plot_time_traces(disp_sens_norot,ff)
|
|
133
136
|
ax.set_title("No Rotation")
|
|
134
|
-
(_,ax) =
|
|
137
|
+
(_,ax) = sens.plot_time_traces(disp_sens_rot,ff)
|
|
135
138
|
ax.set_title("Rotated with Errors")
|
|
136
139
|
|
|
137
140
|
plt.show()
|
|
@@ -24,36 +24,39 @@ Test case: point displacement sensors on a 2D plate with hole loaded in tension
|
|
|
24
24
|
|
|
25
25
|
import numpy as np
|
|
26
26
|
import matplotlib.pyplot as plt
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
|
|
28
|
+
# Pyvale imports
|
|
29
|
+
import pyvale.mooseherder as mh
|
|
30
|
+
import pyvale.sensorsim as sens
|
|
31
|
+
import pyvale.dataset as dataset
|
|
29
32
|
|
|
30
33
|
#%%
|
|
31
34
|
# We start by building the same displacement sensor array applied to a 2D
|
|
32
35
|
# solid mechanics simulation that we have analysed previously.
|
|
33
|
-
data_path =
|
|
36
|
+
data_path = dataset.mechanical_2d_path()
|
|
34
37
|
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
35
38
|
field_name = "disp"
|
|
36
39
|
field_comps = ("disp_x","disp_y")
|
|
37
|
-
sim_data =
|
|
40
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
38
41
|
sim_data=sim_data,
|
|
39
42
|
disp_comps=field_comps)
|
|
40
43
|
|
|
41
|
-
descriptor =
|
|
44
|
+
descriptor = sens.SensorDescriptorFactory.displacement_descriptor()
|
|
42
45
|
|
|
43
|
-
disp_field =
|
|
46
|
+
disp_field = sens.FieldVector(sim_data,field_name,field_comps,elem_dims=2)
|
|
44
47
|
|
|
45
48
|
n_sens = (2,3,1)
|
|
46
49
|
x_lims = (0.0,100.0)
|
|
47
50
|
y_lims = (0.0,150.0)
|
|
48
51
|
z_lims = (0.0,0.0)
|
|
49
|
-
sensor_positions =
|
|
52
|
+
sensor_positions = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
50
53
|
|
|
51
54
|
sample_times = np.linspace(0.0,np.max(sim_data.time),50)
|
|
52
55
|
|
|
53
|
-
sensor_data =
|
|
56
|
+
sensor_data = sens.SensorData(positions=sensor_positions,
|
|
54
57
|
sample_times=sample_times)
|
|
55
58
|
|
|
56
|
-
disp_sens_array =
|
|
59
|
+
disp_sens_array = sens.SensorArrayPoint(sensor_data,
|
|
57
60
|
disp_field,
|
|
58
61
|
descriptor)
|
|
59
62
|
|
|
@@ -66,16 +69,16 @@ disp_sens_array = pyv.SensorArrayPoint(sensor_data,
|
|
|
66
69
|
# We will apply a position offset of -1.0mm in the x and y axes.
|
|
67
70
|
pos_offset = -1.0*np.ones_like(sensor_positions)
|
|
68
71
|
pos_offset[:,2] = 0.0 # in 2d we only have offset in x and y so zero z
|
|
69
|
-
pos_error_data =
|
|
72
|
+
pos_error_data = sens.ErrFieldData(pos_offset_xyz=pos_offset)
|
|
70
73
|
|
|
71
74
|
#%%
|
|
72
75
|
# We will apply a rotation offset about the z axis of 1 degree
|
|
73
76
|
angle_offset = np.zeros_like(sensor_positions)
|
|
74
77
|
angle_offset[:,0] = 1.0 # only rotate about z in 2D
|
|
75
|
-
angle_error_data =
|
|
78
|
+
angle_error_data = sens.ErrFieldData(ang_offset_zyx=angle_offset)
|
|
76
79
|
|
|
77
80
|
time_offset = 2.0*np.ones_like(disp_sens_array.get_sample_times())
|
|
78
|
-
time_error_data =
|
|
81
|
+
time_error_data = sens.ErrFieldData(time_offset=time_offset)
|
|
79
82
|
|
|
80
83
|
#%%
|
|
81
84
|
# Now we add all our field errors to our error chain. We add each error
|
|
@@ -83,26 +86,25 @@ time_error_data = pyv.ErrFieldData(time_offset=time_offset)
|
|
|
83
86
|
# error dependence to `DEPENDENT` so that the sensor state is accumulated
|
|
84
87
|
# over the error chain as field errors are `INDEPENDENT` by default.
|
|
85
88
|
err_chain = []
|
|
86
|
-
err_chain.append(
|
|
89
|
+
err_chain.append(sens.ErrSysField(disp_field,
|
|
87
90
|
time_error_data,
|
|
88
|
-
|
|
89
|
-
err_chain.append(
|
|
91
|
+
sens.EErrDep.DEPENDENT))
|
|
92
|
+
err_chain.append(sens.ErrSysField(disp_field,
|
|
90
93
|
time_error_data,
|
|
91
|
-
|
|
94
|
+
sens.EErrDep.DEPENDENT))
|
|
92
95
|
|
|
93
|
-
err_chain.append(
|
|
96
|
+
err_chain.append(sens.ErrSysField(disp_field,
|
|
94
97
|
pos_error_data,
|
|
95
|
-
|
|
96
|
-
err_chain.append(
|
|
98
|
+
sens.EErrDep.DEPENDENT))
|
|
99
|
+
err_chain.append(sens.ErrSysField(disp_field,
|
|
97
100
|
pos_error_data,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
err_chain.append(pyv.ErrSysField(disp_field,
|
|
101
|
+
sens.EErrDep.DEPENDENT))
|
|
102
|
+
err_chain.append(sens.ErrSysField(disp_field,
|
|
101
103
|
angle_error_data,
|
|
102
|
-
|
|
103
|
-
err_chain.append(
|
|
104
|
+
sens.EErrDep.DEPENDENT))
|
|
105
|
+
err_chain.append(sens.ErrSysField(disp_field,
|
|
104
106
|
angle_error_data,
|
|
105
|
-
|
|
107
|
+
sens.EErrDep.DEPENDENT))
|
|
106
108
|
|
|
107
109
|
#%%
|
|
108
110
|
# Instead of setting the dependence for each individual error above we could
|
|
@@ -113,13 +115,13 @@ err_chain.append(pyv.ErrSysField(disp_field,
|
|
|
113
115
|
# each error in the chain to the total error rather than just being able to
|
|
114
116
|
# analyse the total systematic and total random error which is the default.
|
|
115
117
|
# Note that this option will use more memory.
|
|
116
|
-
err_int_opts =
|
|
118
|
+
err_int_opts = sens.ErrIntOpts(force_dependence=sens.EErrDep.DEPENDENT,
|
|
117
119
|
store_all_errs=True)
|
|
118
120
|
|
|
119
121
|
#%%
|
|
120
122
|
# Now we build our error integrator, add it to our sensor array and then run
|
|
121
123
|
# our sensor simulation to obtain some virtual measurements.
|
|
122
|
-
error_int =
|
|
124
|
+
error_int = sens.ErrIntegrator(err_chain,
|
|
123
125
|
sensor_data,
|
|
124
126
|
disp_sens_array.get_measurement_shape(),
|
|
125
127
|
err_int_opts)
|
|
@@ -185,13 +187,13 @@ print("ROTATED SENSORS WITH ANGLE ERRORS:")
|
|
|
185
187
|
print(f"These are the last {time_last} virtual measurements of sensor "
|
|
186
188
|
+ f"{sens_print} for {field_comps[comp_print]}:")
|
|
187
189
|
|
|
188
|
-
|
|
190
|
+
sens.print_measurements(disp_sens_array,sens_print,comp_print,time_print)
|
|
189
191
|
|
|
190
192
|
print(80*"-")
|
|
191
193
|
|
|
192
194
|
#%%
|
|
193
195
|
# Finally, we plot the time traces for all field components.
|
|
194
196
|
for ff in field_comps:
|
|
195
|
-
|
|
197
|
+
sens.plot_time_traces(disp_sens_array,ff)
|
|
196
198
|
|
|
197
199
|
plt.show()
|
|
@@ -21,15 +21,18 @@ Test case: Simple 3D cube thermo-mechanical in tension with temp gradient.
|
|
|
21
21
|
|
|
22
22
|
import numpy as np
|
|
23
23
|
import matplotlib.pyplot as plt
|
|
24
|
-
|
|
25
|
-
|
|
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
|
#%%
|
|
29
32
|
# First we load our simulation as a `SimData` object. In this case we are
|
|
30
33
|
# loading a 10mm cube loaded in tension in the y direction with the addition
|
|
31
34
|
# of a thermal gradient in the y direction.
|
|
32
|
-
data_path =
|
|
35
|
+
data_path = dataset.element_case_output_path(dataset.EElemTest.HEX20)
|
|
33
36
|
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
34
37
|
|
|
35
38
|
#%%
|
|
@@ -37,40 +40,40 @@ sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
|
37
40
|
# displacement field component here.
|
|
38
41
|
field_name = "disp"
|
|
39
42
|
field_comps = ("disp_x","disp_y","disp_z")
|
|
40
|
-
sim_data =
|
|
43
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
41
44
|
sim_data=sim_data,
|
|
42
45
|
disp_comps=field_comps)
|
|
43
46
|
|
|
44
47
|
#%%
|
|
45
48
|
# We use a helper function to print the extent of the dimensions in our
|
|
46
|
-
# `
|
|
47
|
-
|
|
49
|
+
# `SimTools` object to help us locate our sensors on the cube.
|
|
50
|
+
sens.SimTools.print_dimensions(sim_data)
|
|
48
51
|
|
|
49
|
-
descriptor =
|
|
52
|
+
descriptor = sens.SensorDescriptorFactory.displacement_descriptor()
|
|
50
53
|
|
|
51
54
|
#%%
|
|
52
55
|
# We pass in the string keys for the three vector field components as they
|
|
53
56
|
# appear in our `SimData` object as well as specifying that our elements are
|
|
54
57
|
# 3 dimensional.
|
|
55
|
-
disp_field =
|
|
58
|
+
disp_field = sens.FieldVector(sim_data,field_name,field_comps,elem_dims=3)
|
|
56
59
|
|
|
57
60
|
#%%
|
|
58
61
|
# Here we manually define our sensor positions to place a sensor on the
|
|
59
62
|
# centre of each face of our 10mm cube. From here everything is the same as
|
|
60
63
|
# for our 2D vector field sensor arrays.
|
|
61
64
|
sensor_positions = np.array(((5.0,0.0,5.0),
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
(5.0,10.0,5.0),
|
|
66
|
+
(5.0,5.0,0.0),
|
|
67
|
+
(5.0,5.0,10.0),
|
|
68
|
+
(0.0,5.0,5.0),
|
|
69
|
+
(10.0,5.0,5.0),))
|
|
67
70
|
|
|
68
71
|
sample_times = np.linspace(0.0,np.max(sim_data.time),50)
|
|
69
72
|
|
|
70
|
-
sensor_data =
|
|
73
|
+
sensor_data = sens.SensorData(positions=sensor_positions,
|
|
71
74
|
sample_times=sample_times)
|
|
72
75
|
|
|
73
|
-
disp_sens_array =
|
|
76
|
+
disp_sens_array = sens.SensorArrayPoint(sensor_data,
|
|
74
77
|
disp_field,
|
|
75
78
|
descriptor)
|
|
76
79
|
|
|
@@ -79,7 +82,7 @@ measurements = disp_sens_array.calc_measurements()
|
|
|
79
82
|
#%%
|
|
80
83
|
# Let's have a look at the y displacement field in relation to the location
|
|
81
84
|
# of our displacement sensors.
|
|
82
|
-
pv_plot =
|
|
85
|
+
pv_plot = sens.plot_point_sensors_on_sim(disp_sens_array,"disp_y")
|
|
83
86
|
pv_plot.show()
|
|
84
87
|
|
|
85
88
|
#%%
|
|
@@ -96,7 +99,7 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
|
|
|
96
99
|
print(f"These are the last {time_last} virtual measurements of sensor "
|
|
97
100
|
+ f"{sens_print} for {field_comps[comp_print]}:")
|
|
98
101
|
|
|
99
|
-
|
|
102
|
+
sens.print_measurements(disp_sens_array,sens_print,comp_print,time_print)
|
|
100
103
|
|
|
101
104
|
print(80*"-")
|
|
102
105
|
|
|
@@ -106,6 +109,6 @@ print(80*"-")
|
|
|
106
109
|
# maximum y displacement, and that all sensors on the sides of the cube
|
|
107
110
|
# should give the same results.
|
|
108
111
|
for ff in field_comps:
|
|
109
|
-
|
|
112
|
+
sens.plot_time_traces(disp_sens_array,ff)
|
|
110
113
|
|
|
111
114
|
plt.show()
|
|
@@ -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
|
-
|
|
26
|
-
|
|
27
|
-
import pyvale as
|
|
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 =
|
|
36
|
-
sim_data
|
|
37
|
-
sim_data
|
|
38
|
-
|
|
39
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
23
|
-
|
|
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 =
|
|
33
|
+
data_path = dataset.mechanical_2d_path()
|
|
31
34
|
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
32
|
-
sim_data =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
87
|
-
error_chain.append(
|
|
88
|
-
error_int =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
25
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
108
|
-
error_chain.append(
|
|
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 = (
|
|
116
|
-
|
|
117
|
-
|
|
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 = (
|
|
121
|
-
|
|
122
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
195
|
+
sens.plot_time_traces(straingauge_array,cc)
|
|
193
196
|
|
|
194
197
|
plt.show()
|