pyvale 2025.7.1__cp311-cp311-win32.whl → 2025.8.1__cp311-cp311-win32.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-win32.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-win32.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-win32.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
|
@@ -28,32 +28,35 @@ to your error chain.
|
|
|
28
28
|
|
|
29
29
|
import numpy as np
|
|
30
30
|
import matplotlib.pyplot as plt
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
|
|
32
|
+
# Pyvale imports
|
|
33
|
+
import pyvale.mooseherder as mh
|
|
34
|
+
import pyvale.sensorsim as sens
|
|
35
|
+
import pyvale.dataset as dataset
|
|
33
36
|
|
|
34
37
|
|
|
35
38
|
#%%
|
|
36
39
|
# First we use everything we learned from the first three examples to build
|
|
37
40
|
# a thermocouple sensor array for the same 3D thermal simulation we have
|
|
38
41
|
# analysed in the previous example.
|
|
39
|
-
data_path =
|
|
42
|
+
data_path = dataset.thermal_3d_path()
|
|
40
43
|
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
41
|
-
sim_data =
|
|
44
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
42
45
|
sim_data=sim_data,
|
|
43
46
|
disp_comps=None)
|
|
44
47
|
n_sens = (1,4,1)
|
|
45
48
|
x_lims = (12.5,12.5)
|
|
46
49
|
y_lims = (0.0,33.0)
|
|
47
50
|
z_lims = (0.0,12.0)
|
|
48
|
-
sens_pos =
|
|
51
|
+
sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
49
52
|
|
|
50
53
|
sample_times = np.linspace(0.0,np.max(sim_data.time),50) # | None
|
|
51
54
|
|
|
52
|
-
sensor_data =
|
|
55
|
+
sensor_data = sens.SensorData(positions=sens_pos,
|
|
53
56
|
sample_times=sample_times)
|
|
54
57
|
|
|
55
58
|
field_key: str = "temperature"
|
|
56
|
-
tc_array =
|
|
59
|
+
tc_array = sens.SensorArrayFactory \
|
|
57
60
|
.thermocouples_no_errs(sim_data,
|
|
58
61
|
sensor_data,
|
|
59
62
|
elem_dims=3,
|
|
@@ -73,61 +76,61 @@ err_chain = []
|
|
|
73
76
|
#
|
|
74
77
|
# These systematic errors provide a constant offset to all measurements in
|
|
75
78
|
# simulation units or as a percentage.
|
|
76
|
-
err_chain.append(
|
|
77
|
-
err_chain.append(
|
|
79
|
+
err_chain.append(sens.ErrSysOffset(offset=-10.0))
|
|
80
|
+
err_chain.append(sens.ErrSysOffsetPercent(offset_percent=-1.0))
|
|
78
81
|
|
|
79
82
|
#%%
|
|
80
83
|
# These systematic errors are sampled from a uniform or normal probability
|
|
81
84
|
# distribution either in simulation units or as a percentage.
|
|
82
|
-
err_chain.append(
|
|
85
|
+
err_chain.append(sens.ErrSysUnif(low=-1.0,
|
|
83
86
|
high=1.0))
|
|
84
|
-
err_chain.append(
|
|
87
|
+
err_chain.append(sens.ErrSysUnifPercent(low_percent=-1.0,
|
|
85
88
|
high_percent=1.0))
|
|
86
|
-
err_chain.append(
|
|
87
|
-
err_chain.append(
|
|
89
|
+
err_chain.append(sens.ErrSysNorm(std=1.0))
|
|
90
|
+
err_chain.append(sens.ErrSysNormPercent(std_percent=1.0))
|
|
88
91
|
|
|
89
92
|
#%%
|
|
90
93
|
# pyvale includes a series of random number generator objects that wrap the
|
|
91
94
|
# random number generators from numpy. These are named `Gen*` and can be
|
|
92
95
|
# used with an `ErrSysGen` or an `ErrSysGenPercent` object to create custom
|
|
93
96
|
# probability distribution sampling errors:
|
|
94
|
-
sys_gen =
|
|
97
|
+
sys_gen = sens.GenTriangular(left=-1.0,
|
|
95
98
|
mode=0.0,
|
|
96
99
|
right=1.0)
|
|
97
|
-
err_chain.append(
|
|
100
|
+
err_chain.append(sens.ErrSysGen(sys_gen))
|
|
98
101
|
|
|
99
102
|
#%%
|
|
100
103
|
# We can also build the equivalent of `ErrSysUnifPercent` above using a
|
|
101
104
|
# `Gen` object inserted into an `ErrSysGenPercent` object:
|
|
102
|
-
unif_gen =
|
|
105
|
+
unif_gen = sens.GenUniform(low=-1.0,
|
|
103
106
|
high=1.0)
|
|
104
|
-
err_chain.append(
|
|
107
|
+
err_chain.append(sens.ErrSysGenPercent(unif_gen))
|
|
105
108
|
|
|
106
109
|
#%%
|
|
107
110
|
# We can also add a series of random errors in a similar manner to the
|
|
108
111
|
# systematic errors above noting that these will generate a new error for
|
|
109
112
|
# each sensor and each time step whereas the systematic error sampling
|
|
110
113
|
# provides a constant shift over all sampling times for each sensor.
|
|
111
|
-
err_chain.append(
|
|
112
|
-
err_chain.append(
|
|
113
|
-
err_chain.append(
|
|
114
|
-
err_chain.append(
|
|
114
|
+
err_chain.append(sens.ErrRandNorm(std = 2.0))
|
|
115
|
+
err_chain.append(sens.ErrRandNormPercent(std_percent=2.0))
|
|
116
|
+
err_chain.append(sens.ErrRandUnif(low=-2.0,high=2.0))
|
|
117
|
+
err_chain.append(sens.ErrRandUnifPercent(low_percent=-2.0,
|
|
115
118
|
high_percent=2.0))
|
|
116
|
-
rand_gen =
|
|
119
|
+
rand_gen = sens.GenTriangular(left=-5.0,
|
|
117
120
|
mode=0.0,
|
|
118
121
|
right=5.0)
|
|
119
|
-
err_chain.append(
|
|
122
|
+
err_chain.append(sens.ErrRandGen(rand_gen))
|
|
120
123
|
|
|
121
124
|
#%%
|
|
122
125
|
# Finally we add some dependent systematic errors including rounding errors,
|
|
123
126
|
# digitisation and saturation. Note that the saturation error must be placed
|
|
124
127
|
# last in the error chain. Try changing some of these values to see how the
|
|
125
128
|
# sensor traces change - particularly the saturation error.
|
|
126
|
-
err_chain.append(
|
|
127
|
-
err_chain.append(
|
|
128
|
-
err_chain.append(
|
|
129
|
+
err_chain.append(sens.ErrSysRoundOff(sens.ERoundMethod.ROUND,0.1))
|
|
130
|
+
err_chain.append(sens.ErrSysDigitisation(bits_per_unit=2**16/100))
|
|
131
|
+
err_chain.append(sens.ErrSysSaturation(meas_min=0.0,meas_max=400.0))
|
|
129
132
|
|
|
130
|
-
err_int =
|
|
133
|
+
err_int = sens.ErrIntegrator(err_chain,
|
|
131
134
|
sensor_data,
|
|
132
135
|
tc_array.get_measurement_shape())
|
|
133
136
|
tc_array.set_error_integrator(err_int)
|
|
@@ -148,10 +151,10 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
|
|
|
148
151
|
print(f"These are the last {time_last} virtual measurements of sensor "
|
|
149
152
|
+ f"{sens_print}:")
|
|
150
153
|
|
|
151
|
-
|
|
154
|
+
sens.print_measurements(tc_array,sens_print,comp_print,time_print)
|
|
152
155
|
|
|
153
156
|
print(80*"-")
|
|
154
157
|
|
|
155
|
-
|
|
158
|
+
sens.plot_time_traces(tc_array,field_key)
|
|
156
159
|
plt.show()
|
|
157
160
|
|
|
@@ -24,8 +24,12 @@ Test case: Scalar field point sensors (thermocouples) on a 3D thermal simulation
|
|
|
24
24
|
from pathlib import Path
|
|
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
|
|
32
|
+
|
|
29
33
|
|
|
30
34
|
#%%
|
|
31
35
|
# First we use everything we learned from the first three examples to build
|
|
@@ -33,9 +37,9 @@ import pyvale as pyv
|
|
|
33
37
|
# analysed in the previous examples. Then we will look at a new type of
|
|
34
38
|
# systematic error called a field error which requires additional
|
|
35
39
|
# interpolation of the underlying physical field to be measured.
|
|
36
|
-
data_path =
|
|
40
|
+
data_path = dataset.thermal_3d_path()
|
|
37
41
|
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
38
|
-
sim_data =
|
|
42
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
39
43
|
sim_data=sim_data,
|
|
40
44
|
disp_comps=None)
|
|
41
45
|
|
|
@@ -43,15 +47,15 @@ n_sens = (1,4,1)
|
|
|
43
47
|
x_lims = (12.5,12.5)
|
|
44
48
|
y_lims = (0.0,33.0)
|
|
45
49
|
z_lims = (0.0,12.0)
|
|
46
|
-
sens_pos =
|
|
50
|
+
sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
47
51
|
|
|
48
52
|
sample_times = np.linspace(0.0,np.max(sim_data.time),50) # | None
|
|
49
53
|
|
|
50
|
-
sensor_data =
|
|
54
|
+
sensor_data = sens.SensorData(positions=sens_pos,
|
|
51
55
|
sample_times=sample_times)
|
|
52
56
|
|
|
53
57
|
field_key: str = "temperature"
|
|
54
|
-
tc_array =
|
|
58
|
+
tc_array = sens.SensorArrayFactory \
|
|
55
59
|
.thermocouples_no_errs(sim_data,
|
|
56
60
|
sensor_data,
|
|
57
61
|
elem_dims=3,
|
|
@@ -76,8 +80,8 @@ time_offset = np.full((sample_times.shape[0],),0.1)
|
|
|
76
80
|
#%%
|
|
77
81
|
# Using the `Gen*` random generators in pyvale we can randomly perturb the
|
|
78
82
|
# position or sampling times of our virtual sensors.
|
|
79
|
-
pos_rand =
|
|
80
|
-
time_rand =
|
|
83
|
+
pos_rand = sens.GenNormal(std=1.0) # units = mm
|
|
84
|
+
time_rand = sens.GenNormal(std=0.1) # units = s
|
|
81
85
|
|
|
82
86
|
#%%
|
|
83
87
|
# Now we put everything into our field error data class ready to build our
|
|
@@ -85,7 +89,7 @@ time_rand = pyv.GenNormal(std=0.1) # units = s
|
|
|
85
89
|
# to geta feel for the other types of supported field errors. We will look
|
|
86
90
|
# at the orientation and area averaging errors when we look at vector and
|
|
87
91
|
# tensor fields in later examples.
|
|
88
|
-
field_err_data =
|
|
92
|
+
field_err_data = sens.ErrFieldData(
|
|
89
93
|
pos_offset_xyz=pos_offset_xyz,
|
|
90
94
|
time_offset=time_offset,
|
|
91
95
|
pos_rand_xyz=(None,pos_rand,pos_rand),
|
|
@@ -105,9 +109,9 @@ err_chain = []
|
|
|
105
109
|
# A field error needs to know which field it should interpolate for error
|
|
106
110
|
# calculations so we provide the field from the sensor array as well as the
|
|
107
111
|
# field error error data class.
|
|
108
|
-
err_chain.append(
|
|
112
|
+
err_chain.append(sens.ErrSysField(tc_array.get_field(),
|
|
109
113
|
field_err_data))
|
|
110
|
-
err_int =
|
|
114
|
+
err_int = sens.ErrIntegrator(err_chain,
|
|
111
115
|
sensor_data,
|
|
112
116
|
tc_array.get_measurement_shape())
|
|
113
117
|
tc_array.set_error_integrator(err_int)
|
|
@@ -128,7 +132,7 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
|
|
|
128
132
|
print(f"These are the last {time_last} virtual measurements of sensor "
|
|
129
133
|
+ f"{sens_print}:")
|
|
130
134
|
|
|
131
|
-
|
|
135
|
+
sens.print_measurements(tc_array,sens_print,comp_print,time_print)
|
|
132
136
|
|
|
133
137
|
print(80*"-")
|
|
134
138
|
|
|
@@ -142,7 +146,7 @@ if not output_path.is_dir():
|
|
|
142
146
|
#%%
|
|
143
147
|
# If we analyse the time traces we can see offsets in the sensor value and
|
|
144
148
|
# the sampling times which we expect from our field error setup.
|
|
145
|
-
(fig,ax) =
|
|
149
|
+
(fig,ax) = sens.plot_time_traces(tc_array,field_key)
|
|
146
150
|
|
|
147
151
|
save_traces = output_path/"field_ex1_5_sensortraces.png"
|
|
148
152
|
fig.savefig(save_traces, dpi=300, bbox_inches="tight")
|
|
@@ -153,7 +157,7 @@ plt.show()
|
|
|
153
157
|
#%%
|
|
154
158
|
# It is also possible to view the perturbed sensor locations on the
|
|
155
159
|
# simulation mesh if we create a plot after running the sensor simulation.
|
|
156
|
-
pv_plot =
|
|
160
|
+
pv_plot = sens.plot_point_sensors_on_sim(tc_array,field_key)
|
|
157
161
|
pv_plot.camera_position = [(59.354, 43.428, 69.946),
|
|
158
162
|
(-2.858, 13.189, 4.523),
|
|
159
163
|
(-0.215, 0.948, -0.233)]
|
|
@@ -16,8 +16,12 @@ Test case: Scalar field point sensors (thermocouples) on a 2D thermal simulation
|
|
|
16
16
|
|
|
17
17
|
import numpy as np
|
|
18
18
|
import matplotlib.pyplot as plt
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
|
|
20
|
+
# Pyvale imports
|
|
21
|
+
import pyvale.mooseherder as mh
|
|
22
|
+
import pyvale.sensorsim as sens
|
|
23
|
+
import pyvale.dataset as dataset
|
|
24
|
+
|
|
21
25
|
|
|
22
26
|
#%%
|
|
23
27
|
# First we need to define some calibration functions. These functions must take
|
|
@@ -27,11 +31,11 @@ import pyvale as pyv
|
|
|
27
31
|
# we can calculate the error between them. The calibration functions shown below
|
|
28
32
|
# are simplified versions of the typical calibration curves for a K-type
|
|
29
33
|
# thermocouple.
|
|
30
|
-
def
|
|
34
|
+
def calib_assumed(signal: np.ndarray) -> np.ndarray:
|
|
31
35
|
return 24.3*signal + 0.616
|
|
32
36
|
|
|
33
37
|
|
|
34
|
-
def
|
|
38
|
+
def calib_truth(signal: np.ndarray) -> np.ndarray:
|
|
35
39
|
return -0.01897 + 25.41881*signal - 0.42456*signal**2 + 0.04365*signal**3
|
|
36
40
|
|
|
37
41
|
|
|
@@ -46,8 +50,8 @@ signal_calib_range = np.array((0.0,6.0),dtype=np.float64)
|
|
|
46
50
|
milli_volts = np.linspace(signal_calib_range[0],
|
|
47
51
|
signal_calib_range[1],
|
|
48
52
|
n_cal_divs)
|
|
49
|
-
temp_truth =
|
|
50
|
-
temp_assumed =
|
|
53
|
+
temp_truth = calib_truth(milli_volts)
|
|
54
|
+
temp_assumed = calib_assumed(milli_volts)
|
|
51
55
|
calib_error = temp_assumed - temp_truth
|
|
52
56
|
|
|
53
57
|
print()
|
|
@@ -66,9 +70,9 @@ print()
|
|
|
66
70
|
# Now let's go back and build the 2D thermal plate with simulated
|
|
67
71
|
# thermocouples that we analysed in the first two examples. We use this
|
|
68
72
|
# simulation as the temperatures are within our calibrated range.
|
|
69
|
-
data_path =
|
|
73
|
+
data_path = dataset.thermal_2d_path()
|
|
70
74
|
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
71
|
-
sim_data =
|
|
75
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
72
76
|
sim_data=sim_data,
|
|
73
77
|
disp_comps=None)
|
|
74
78
|
|
|
@@ -76,15 +80,15 @@ n_sens = (4,1,1)
|
|
|
76
80
|
x_lims = (0.0,100.0)
|
|
77
81
|
y_lims = (0.0,50.0)
|
|
78
82
|
z_lims = (0.0,0.0)
|
|
79
|
-
sens_pos =
|
|
83
|
+
sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
80
84
|
|
|
81
85
|
sample_times = np.linspace(0.0,np.max(sim_data.time),50) # | None
|
|
82
86
|
|
|
83
|
-
sensor_data =
|
|
87
|
+
sensor_data = sens.SensorData(positions=sens_pos,
|
|
84
88
|
sample_times=sample_times)
|
|
85
89
|
|
|
86
90
|
field_key: str = "temperature"
|
|
87
|
-
tc_array =
|
|
91
|
+
tc_array = sens.SensorArrayFactory \
|
|
88
92
|
.thermocouples_no_errs(sim_data,
|
|
89
93
|
sensor_data,
|
|
90
94
|
elem_dims=2,
|
|
@@ -96,11 +100,11 @@ tc_array = pyv.SensorArrayFactory \
|
|
|
96
100
|
# that the truth calibration function must be inverted numerically so to
|
|
97
101
|
# increase accuracy the number of divisions can be increased. However, 1e4
|
|
98
102
|
# divisions should be suitable for most applications.
|
|
99
|
-
cal_err =
|
|
100
|
-
|
|
103
|
+
cal_err = sens.ErrSysCalibration(calib_assumed,
|
|
104
|
+
calib_truth,
|
|
101
105
|
signal_calib_range,
|
|
102
106
|
n_cal_divs=10000)
|
|
103
|
-
sys_err_int =
|
|
107
|
+
sys_err_int = sens.ErrIntegrator([cal_err],
|
|
104
108
|
sensor_data,
|
|
105
109
|
tc_array.get_measurement_shape())
|
|
106
110
|
tc_array.set_error_integrator(sys_err_int)
|
|
@@ -119,10 +123,10 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
|
|
|
119
123
|
print(f"These are the last {time_last} virtual measurements of sensor "
|
|
120
124
|
+ f"{sens_print}:")
|
|
121
125
|
|
|
122
|
-
|
|
126
|
+
sens.print_measurements(tc_array,sens_print,comp_print,time_print)
|
|
123
127
|
|
|
124
128
|
print(80*"-")
|
|
125
129
|
|
|
126
|
-
|
|
130
|
+
sens.plot_time_traces(tc_array,field_key)
|
|
127
131
|
plt.show()
|
|
128
132
|
|
|
@@ -16,8 +16,11 @@ Test case: Scalar field point sensors (thermocouples) on a 2D thermal simulation
|
|
|
16
16
|
|
|
17
17
|
import numpy as np
|
|
18
18
|
import matplotlib.pyplot as plt
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
|
|
20
|
+
# Pyvale imports
|
|
21
|
+
import pyvale.mooseherder as mh
|
|
22
|
+
import pyvale.sensorsim as sens
|
|
23
|
+
import pyvale.dataset as dataset
|
|
21
24
|
|
|
22
25
|
#%%
|
|
23
26
|
# First we are going to build a custom sensor array so we can control how
|
|
@@ -29,16 +32,16 @@ import pyvale as pyv
|
|
|
29
32
|
# area averaged without and area averaging error. The first part of this is
|
|
30
33
|
# the same as the 3D thermal example we have used previously then we control
|
|
31
34
|
# the area averaging using the sensor data object.
|
|
32
|
-
data_path =
|
|
35
|
+
data_path = dataset.thermal_2d_path()
|
|
33
36
|
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
34
|
-
sim_data =
|
|
37
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
35
38
|
sim_data=sim_data,
|
|
36
39
|
disp_comps=None)
|
|
37
40
|
|
|
38
|
-
descriptor =
|
|
41
|
+
descriptor = sens.SensorDescriptorFactory.temperature_descriptor()
|
|
39
42
|
|
|
40
43
|
field_key = "temperature"
|
|
41
|
-
t_field =
|
|
44
|
+
t_field = sens.FieldScalar(sim_data,
|
|
42
45
|
field_key=field_key,
|
|
43
46
|
elem_dims=2)
|
|
44
47
|
|
|
@@ -46,7 +49,7 @@ n_sens = (4,1,1)
|
|
|
46
49
|
x_lims = (0.0,100.0)
|
|
47
50
|
y_lims = (0.0,50.0)
|
|
48
51
|
z_lims = (0.0,0.0)
|
|
49
|
-
sens_pos =
|
|
52
|
+
sens_pos = 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) # | None
|
|
52
55
|
|
|
@@ -59,15 +62,15 @@ sample_times = np.linspace(0.0,np.max(sim_data.time),50) # | None
|
|
|
59
62
|
# additional integration point requires an additional interpolation of the
|
|
60
63
|
# physical field.
|
|
61
64
|
sensor_dims = np.array([20.0,20.0,0]) # units = mm
|
|
62
|
-
sensor_data =
|
|
65
|
+
sensor_data = sens.SensorData(positions=sens_pos,
|
|
63
66
|
sample_times=sample_times,
|
|
64
|
-
spatial_averager=
|
|
67
|
+
spatial_averager=sens.EIntSpatialType.QUAD4PT,
|
|
65
68
|
spatial_dims=sensor_dims)
|
|
66
69
|
|
|
67
70
|
#%%
|
|
68
71
|
# We have added spatial averaging to our sensor data so we can now create
|
|
69
72
|
# our sensor array as we have done in previous examples.
|
|
70
|
-
tc_array =
|
|
73
|
+
tc_array = sens.SensorArrayPoint(sensor_data,
|
|
71
74
|
t_field,
|
|
72
75
|
descriptor)
|
|
73
76
|
|
|
@@ -75,8 +78,8 @@ tc_array = pyv.SensorArrayPoint(sensor_data,
|
|
|
75
78
|
# We are also going to create a field error that includes area averaging as
|
|
76
79
|
# an error. We do this by adding the option to our field error data class
|
|
77
80
|
# specifying rectangular integration with 1 point.
|
|
78
|
-
area_avg_err_data =
|
|
79
|
-
spatial_averager=
|
|
81
|
+
area_avg_err_data = sens.ErrFieldData(
|
|
82
|
+
spatial_averager=sens.EIntSpatialType.RECT1PT,
|
|
80
83
|
spatial_dims=np.array((5.0,5.0)),
|
|
81
84
|
)
|
|
82
85
|
|
|
@@ -85,9 +88,9 @@ area_avg_err_data = pyv.ErrFieldData(
|
|
|
85
88
|
# with any of our other error models but we will isolate it for now so we
|
|
86
89
|
# can see what it does.
|
|
87
90
|
err_chain = []
|
|
88
|
-
err_chain.append(
|
|
91
|
+
err_chain.append(sens.ErrSysField(t_field,
|
|
89
92
|
area_avg_err_data))
|
|
90
|
-
error_int =
|
|
93
|
+
error_int = sens.ErrIntegrator(err_chain,
|
|
91
94
|
sensor_data,
|
|
92
95
|
tc_array.get_measurement_shape())
|
|
93
96
|
tc_array.set_error_integrator(error_int)
|
|
@@ -107,11 +110,11 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
|
|
|
107
110
|
print(f"These are the last {time_last} virtual measurements of sensor "
|
|
108
111
|
+ f"{sens_print}:")
|
|
109
112
|
|
|
110
|
-
|
|
113
|
+
sens.print_measurements(tc_array,sens_print,comp_print,time_print)
|
|
111
114
|
|
|
112
115
|
print(80*"-")
|
|
113
116
|
|
|
114
|
-
|
|
117
|
+
sens.plot_time_traces(tc_array,field_key)
|
|
115
118
|
plt.show()
|
|
116
119
|
|
|
117
120
|
#%%
|
|
@@ -20,8 +20,11 @@ Test case: point displacement sensors on a 2D plate with hole loaded in tension
|
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
22
|
import matplotlib.pyplot as plt
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
# Pyvale imports
|
|
25
|
+
import pyvale.mooseherder as mh
|
|
26
|
+
import pyvale.sensorsim as sens
|
|
27
|
+
import pyvale.dataset as dataset
|
|
25
28
|
|
|
26
29
|
#%%
|
|
27
30
|
# Here we load a pre-packaged dataset from pyvale that is the output of a
|
|
@@ -29,7 +32,7 @@ import pyvale as pyv
|
|
|
29
32
|
# rectangular plate with a central hole that is loaded in tension (we will
|
|
30
33
|
# see a visualisation of the mesh and results later). We use `mooseherder` to
|
|
31
34
|
# load the exodus file into a `SimData` object.
|
|
32
|
-
data_path =
|
|
35
|
+
data_path = dataset.mechanical_2d_path()
|
|
33
36
|
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
34
37
|
|
|
35
38
|
#%%
|
|
@@ -38,7 +41,7 @@ sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
|
38
41
|
# the variable names you have in your SimData object.
|
|
39
42
|
field_name = "disp"
|
|
40
43
|
field_comps = ("disp_x","disp_y")
|
|
41
|
-
sim_data =
|
|
44
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
42
45
|
sim_data=sim_data,
|
|
43
46
|
disp_comps=field_comps)
|
|
44
47
|
|
|
@@ -53,11 +56,11 @@ n_sens = (2,3,1)
|
|
|
53
56
|
x_lims = (0.0,100.0)
|
|
54
57
|
y_lims = (0.0,150.0)
|
|
55
58
|
z_lims = (0.0,0.0)
|
|
56
|
-
sens_pos =
|
|
59
|
+
sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
57
60
|
|
|
58
|
-
sens_data =
|
|
61
|
+
sens_data = sens.SensorData(positions=sens_pos)
|
|
59
62
|
|
|
60
|
-
disp_sens_array =
|
|
63
|
+
disp_sens_array = sens.SensorArrayFactory \
|
|
61
64
|
.disp_sensors_basic_errs(sim_data,
|
|
62
65
|
sens_data,
|
|
63
66
|
elem_dims=2,
|
|
@@ -92,7 +95,7 @@ time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
|
|
|
92
95
|
print(f"These are the last {time_last} virtual measurements of sensor "
|
|
93
96
|
+ f"{sens_print}:")
|
|
94
97
|
|
|
95
|
-
|
|
98
|
+
sens.print_measurements(disp_sens_array,sens_print,comp_print,time_print)
|
|
96
99
|
|
|
97
100
|
print(80*"-")
|
|
98
101
|
|
|
@@ -101,13 +104,13 @@ print(80*"-")
|
|
|
101
104
|
# simulation mesh and visulise the sensor locations with respect to these
|
|
102
105
|
# fields.
|
|
103
106
|
for ff in field_comps:
|
|
104
|
-
pv_plot =
|
|
107
|
+
pv_plot = sens.plot_point_sensors_on_sim(disp_sens_array,ff)
|
|
105
108
|
pv_plot.show(cpos="xy")
|
|
106
109
|
|
|
107
110
|
#%%
|
|
108
111
|
# We can also plot the traces for each component of the displacement field.
|
|
109
112
|
for ff in field_comps:
|
|
110
|
-
|
|
113
|
+
sens.plot_time_traces(disp_sens_array,ff)
|
|
111
114
|
|
|
112
115
|
plt.show()
|
|
113
116
|
|
|
@@ -19,18 +19,22 @@ Test case: point displacement 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
|
|
27
|
+
|
|
24
28
|
|
|
25
29
|
|
|
26
30
|
#%%
|
|
27
31
|
# First we load the same 2D solid mechanics simulation we had previously as
|
|
28
32
|
# a `SimData` object and then we scale everything to millimeters.
|
|
29
|
-
data_path =
|
|
33
|
+
data_path = dataset.mechanical_2d_path()
|
|
30
34
|
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
31
35
|
field_name = "disp"
|
|
32
36
|
field_comps = ("disp_x","disp_y")
|
|
33
|
-
sim_data =
|
|
37
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
34
38
|
sim_data=sim_data,
|
|
35
39
|
disp_comps=field_comps)
|
|
36
40
|
|
|
@@ -45,25 +49,25 @@ sim_data = pyv.scale_length_units(scale=1000.0,
|
|
|
45
49
|
# parameter does not need to match the number of field components. For
|
|
46
50
|
# example: it is possible to have a surface mesh (elem_dims=2) where we
|
|
47
51
|
# have all 3 components of the displacement field.
|
|
48
|
-
disp_field =
|
|
52
|
+
disp_field = sens.FieldVector(sim_data,field_name,field_comps,elem_dims=2)
|
|
49
53
|
|
|
50
54
|
#%%
|
|
51
55
|
# As we saw previously for scalar fields we define our sensor data object
|
|
52
56
|
# which determines how many point sensors we have and their sampling times.
|
|
53
57
|
# For vector field sensors we can also define the sensor orientation here
|
|
54
58
|
# which we will demonstrate in the next example.
|
|
55
|
-
n_sens = (
|
|
59
|
+
n_sens = (1,4,1)
|
|
56
60
|
x_lims = (0.0,100.0)
|
|
57
61
|
y_lims = (0.0,150.0)
|
|
58
62
|
z_lims = (0.0,0.0)
|
|
59
|
-
sens_pos =
|
|
63
|
+
sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
60
64
|
|
|
61
65
|
#%%
|
|
62
66
|
# We set custom sampling times here but we could also set this to None so
|
|
63
67
|
# that the sensors sample at the simulation time steps.
|
|
64
68
|
sample_times = np.linspace(0.0,np.max(sim_data.time),50)
|
|
65
69
|
|
|
66
|
-
sens_data =
|
|
70
|
+
sens_data = sens.SensorData(positions=sens_pos,
|
|
67
71
|
sample_times=sample_times)
|
|
68
72
|
|
|
69
73
|
#%%
|
|
@@ -71,7 +75,7 @@ sens_data = pyv.SensorData(positions=sens_pos,
|
|
|
71
75
|
# sensor which will be used for labelling sensor placement visualisation or
|
|
72
76
|
# for time traces. It is also possible to use the sensor descriptor factory
|
|
73
77
|
# to get the same sensor descriptor object with these defaults.
|
|
74
|
-
descriptor =
|
|
78
|
+
descriptor = sens.SensorDescriptor(name="Disp.",
|
|
75
79
|
symbol=r"u",
|
|
76
80
|
units=r"mm",
|
|
77
81
|
tag="DS",
|
|
@@ -81,7 +85,7 @@ descriptor = pyv.SensorDescriptor(name="Disp.",
|
|
|
81
85
|
# The point sensor array class is generic and will take any field class
|
|
82
86
|
# that implements the field interface. So here we just pass in the vector
|
|
83
87
|
# field to create our vector field sensor array.
|
|
84
|
-
disp_sens_array =
|
|
88
|
+
disp_sens_array = sens.SensorArrayPoint(sens_data,
|
|
85
89
|
disp_field,
|
|
86
90
|
descriptor)
|
|
87
91
|
|
|
@@ -91,9 +95,9 @@ disp_sens_array = pyv.SensorArrayPoint(sens_data,
|
|
|
91
95
|
# the next example we will look at some field errors to do with sensor
|
|
92
96
|
# orientation that
|
|
93
97
|
error_chain = []
|
|
94
|
-
error_chain.append(
|
|
95
|
-
error_chain.append(
|
|
96
|
-
error_int =
|
|
98
|
+
error_chain.append(sens.ErrSysUnif(low=-0.01,high=0.01)) # units = mm
|
|
99
|
+
error_chain.append(sens.ErrRandNorm(std=0.01)) # units = mm
|
|
100
|
+
error_int = sens.ErrIntegrator(error_chain,
|
|
97
101
|
sens_data,
|
|
98
102
|
disp_sens_array.get_measurement_shape())
|
|
99
103
|
disp_sens_array.set_error_integrator(error_int)
|
|
@@ -105,13 +109,13 @@ disp_sens_array.calc_measurements()
|
|
|
105
109
|
# simulation mesh and visulise the sensor locations with respect to these
|
|
106
110
|
# fields.
|
|
107
111
|
for ff in field_comps:
|
|
108
|
-
pv_plot =
|
|
112
|
+
pv_plot = sens.plot_point_sensors_on_sim(disp_sens_array,ff)
|
|
109
113
|
pv_plot.show(cpos="xy")
|
|
110
114
|
|
|
111
115
|
#%%
|
|
112
116
|
# We can also plot the traces for each component of the displacement field.
|
|
113
117
|
for ff in field_comps:
|
|
114
|
-
|
|
118
|
+
sens.plot_time_traces(disp_sens_array,ff)
|
|
115
119
|
|
|
116
120
|
plt.show()
|
|
117
121
|
|