pyvale 2025.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyvale might be problematic. Click here for more details.

Files changed (162) hide show
  1. pyvale-2025.4.0/LICENSE +21 -0
  2. pyvale-2025.4.0/PKG-INFO +140 -0
  3. pyvale-2025.4.0/README.md +92 -0
  4. pyvale-2025.4.0/pyproject.toml +42 -0
  5. pyvale-2025.4.0/setup.cfg +4 -0
  6. pyvale-2025.4.0/src/pyvale/__init__.py +75 -0
  7. pyvale-2025.4.0/src/pyvale/core/__init__.py +7 -0
  8. pyvale-2025.4.0/src/pyvale/core/analyticmeshgen.py +59 -0
  9. pyvale-2025.4.0/src/pyvale/core/analyticsimdatafactory.py +63 -0
  10. pyvale-2025.4.0/src/pyvale/core/analyticsimdatagenerator.py +160 -0
  11. pyvale-2025.4.0/src/pyvale/core/camera.py +146 -0
  12. pyvale-2025.4.0/src/pyvale/core/cameradata.py +64 -0
  13. pyvale-2025.4.0/src/pyvale/core/cameradata2d.py +82 -0
  14. pyvale-2025.4.0/src/pyvale/core/cameratools.py +328 -0
  15. pyvale-2025.4.0/src/pyvale/core/cython/rastercyth.c +32267 -0
  16. pyvale-2025.4.0/src/pyvale/core/cython/rastercyth.py +636 -0
  17. pyvale-2025.4.0/src/pyvale/core/dataset.py +250 -0
  18. pyvale-2025.4.0/src/pyvale/core/errorcalculator.py +112 -0
  19. pyvale-2025.4.0/src/pyvale/core/errordriftcalc.py +146 -0
  20. pyvale-2025.4.0/src/pyvale/core/errorintegrator.py +339 -0
  21. pyvale-2025.4.0/src/pyvale/core/errorrand.py +614 -0
  22. pyvale-2025.4.0/src/pyvale/core/errorsysdep.py +331 -0
  23. pyvale-2025.4.0/src/pyvale/core/errorsysfield.py +407 -0
  24. pyvale-2025.4.0/src/pyvale/core/errorsysindep.py +905 -0
  25. pyvale-2025.4.0/src/pyvale/core/experimentsimulator.py +99 -0
  26. pyvale-2025.4.0/src/pyvale/core/field.py +136 -0
  27. pyvale-2025.4.0/src/pyvale/core/fieldconverter.py +154 -0
  28. pyvale-2025.4.0/src/pyvale/core/fieldsampler.py +112 -0
  29. pyvale-2025.4.0/src/pyvale/core/fieldscalar.py +167 -0
  30. pyvale-2025.4.0/src/pyvale/core/fieldtensor.py +221 -0
  31. pyvale-2025.4.0/src/pyvale/core/fieldtransform.py +384 -0
  32. pyvale-2025.4.0/src/pyvale/core/fieldvector.py +215 -0
  33. pyvale-2025.4.0/src/pyvale/core/generatorsrandom.py +528 -0
  34. pyvale-2025.4.0/src/pyvale/core/imagedef2d.py +566 -0
  35. pyvale-2025.4.0/src/pyvale/core/integratorfactory.py +241 -0
  36. pyvale-2025.4.0/src/pyvale/core/integratorquadrature.py +192 -0
  37. pyvale-2025.4.0/src/pyvale/core/integratorrectangle.py +88 -0
  38. pyvale-2025.4.0/src/pyvale/core/integratorspatial.py +90 -0
  39. pyvale-2025.4.0/src/pyvale/core/integratortype.py +44 -0
  40. pyvale-2025.4.0/src/pyvale/core/optimcheckfuncs.py +153 -0
  41. pyvale-2025.4.0/src/pyvale/core/raster.py +31 -0
  42. pyvale-2025.4.0/src/pyvale/core/rastercy.py +76 -0
  43. pyvale-2025.4.0/src/pyvale/core/rasternp.py +604 -0
  44. pyvale-2025.4.0/src/pyvale/core/rendermesh.py +156 -0
  45. pyvale-2025.4.0/src/pyvale/core/sensorarray.py +179 -0
  46. pyvale-2025.4.0/src/pyvale/core/sensorarrayfactory.py +210 -0
  47. pyvale-2025.4.0/src/pyvale/core/sensorarraypoint.py +280 -0
  48. pyvale-2025.4.0/src/pyvale/core/sensordata.py +72 -0
  49. pyvale-2025.4.0/src/pyvale/core/sensordescriptor.py +101 -0
  50. pyvale-2025.4.0/src/pyvale/core/sensortools.py +143 -0
  51. pyvale-2025.4.0/src/pyvale/core/visualexpplotter.py +151 -0
  52. pyvale-2025.4.0/src/pyvale/core/visualimagedef.py +71 -0
  53. pyvale-2025.4.0/src/pyvale/core/visualimages.py +75 -0
  54. pyvale-2025.4.0/src/pyvale/core/visualopts.py +180 -0
  55. pyvale-2025.4.0/src/pyvale/core/visualsimanimator.py +83 -0
  56. pyvale-2025.4.0/src/pyvale/core/visualsimplotter.py +182 -0
  57. pyvale-2025.4.0/src/pyvale/core/visualtools.py +81 -0
  58. pyvale-2025.4.0/src/pyvale/core/visualtraceplotter.py +256 -0
  59. pyvale-2025.4.0/src/pyvale/data/__init__.py +7 -0
  60. pyvale-2025.4.0/src/pyvale/data/case13_out.e +0 -0
  61. pyvale-2025.4.0/src/pyvale/data/case16_out.e +0 -0
  62. pyvale-2025.4.0/src/pyvale/data/case17_out.e +0 -0
  63. pyvale-2025.4.0/src/pyvale/data/case18_1_out.e +0 -0
  64. pyvale-2025.4.0/src/pyvale/data/case18_2_out.e +0 -0
  65. pyvale-2025.4.0/src/pyvale/data/case18_3_out.e +0 -0
  66. pyvale-2025.4.0/src/pyvale/data/case25_out.e +0 -0
  67. pyvale-2025.4.0/src/pyvale/data/case26_out.e +0 -0
  68. pyvale-2025.4.0/src/pyvale/data/optspeckle_2464x2056px_spec5px_8bit_gblur1px.tiff +0 -0
  69. pyvale-2025.4.0/src/pyvale/examples/__init__.py +7 -0
  70. pyvale-2025.4.0/src/pyvale/examples/analyticdatagen/__init__.py +7 -0
  71. pyvale-2025.4.0/src/pyvale/examples/analyticdatagen/ex1_1_scalarvisualisation.py +38 -0
  72. pyvale-2025.4.0/src/pyvale/examples/analyticdatagen/ex1_2_scalarcasebuild.py +46 -0
  73. pyvale-2025.4.0/src/pyvale/examples/analyticdatagen/ex2_1_analyticsensors.py +83 -0
  74. pyvale-2025.4.0/src/pyvale/examples/ex1_1_thermal2d.py +89 -0
  75. pyvale-2025.4.0/src/pyvale/examples/ex1_2_thermal2d.py +111 -0
  76. pyvale-2025.4.0/src/pyvale/examples/ex1_3_thermal2d.py +113 -0
  77. pyvale-2025.4.0/src/pyvale/examples/ex1_4_thermal2d.py +89 -0
  78. pyvale-2025.4.0/src/pyvale/examples/ex1_5_thermal2d.py +105 -0
  79. pyvale-2025.4.0/src/pyvale/examples/ex2_1_thermal3d .py +87 -0
  80. pyvale-2025.4.0/src/pyvale/examples/ex2_2_thermal3d.py +51 -0
  81. pyvale-2025.4.0/src/pyvale/examples/ex2_3_thermal3d.py +109 -0
  82. pyvale-2025.4.0/src/pyvale/examples/ex3_1_displacement2d.py +47 -0
  83. pyvale-2025.4.0/src/pyvale/examples/ex3_2_displacement2d.py +79 -0
  84. pyvale-2025.4.0/src/pyvale/examples/ex3_3_displacement2d.py +104 -0
  85. pyvale-2025.4.0/src/pyvale/examples/ex3_4_displacement2d.py +105 -0
  86. pyvale-2025.4.0/src/pyvale/examples/ex4_1_strain2d.py +57 -0
  87. pyvale-2025.4.0/src/pyvale/examples/ex4_2_strain2d.py +79 -0
  88. pyvale-2025.4.0/src/pyvale/examples/ex4_3_strain2d.py +100 -0
  89. pyvale-2025.4.0/src/pyvale/examples/ex5_1_multiphysics2d.py +78 -0
  90. pyvale-2025.4.0/src/pyvale/examples/ex6_1_multiphysics2d_expsim.py +118 -0
  91. pyvale-2025.4.0/src/pyvale/examples/ex6_2_multiphysics3d_expsim.py +158 -0
  92. pyvale-2025.4.0/src/pyvale/examples/features/__init__.py +7 -0
  93. pyvale-2025.4.0/src/pyvale/examples/features/ex_animation_tools_3dmonoblock.py +83 -0
  94. pyvale-2025.4.0/src/pyvale/examples/features/ex_area_avg.py +89 -0
  95. pyvale-2025.4.0/src/pyvale/examples/features/ex_calibration_error.py +108 -0
  96. pyvale-2025.4.0/src/pyvale/examples/features/ex_chain_field_errs.py +141 -0
  97. pyvale-2025.4.0/src/pyvale/examples/features/ex_field_errs.py +78 -0
  98. pyvale-2025.4.0/src/pyvale/examples/features/ex_sensor_single_angle_batch.py +110 -0
  99. pyvale-2025.4.0/src/pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +86 -0
  100. pyvale-2025.4.0/src/pyvale/examples/rasterisation/ex_rastenp.py +154 -0
  101. pyvale-2025.4.0/src/pyvale/examples/rasterisation/ex_rastercyth_oneframe.py +220 -0
  102. pyvale-2025.4.0/src/pyvale/examples/rasterisation/ex_rastercyth_static_cypara.py +194 -0
  103. pyvale-2025.4.0/src/pyvale/examples/rasterisation/ex_rastercyth_static_pypara.py +193 -0
  104. pyvale-2025.4.0/src/pyvale/simcases/case00_HEX20.i +242 -0
  105. pyvale-2025.4.0/src/pyvale/simcases/case00_HEX27.i +242 -0
  106. pyvale-2025.4.0/src/pyvale/simcases/case00_TET10.i +242 -0
  107. pyvale-2025.4.0/src/pyvale/simcases/case00_TET14.i +242 -0
  108. pyvale-2025.4.0/src/pyvale/simcases/case01.i +101 -0
  109. pyvale-2025.4.0/src/pyvale/simcases/case02.i +156 -0
  110. pyvale-2025.4.0/src/pyvale/simcases/case03.i +136 -0
  111. pyvale-2025.4.0/src/pyvale/simcases/case04.i +181 -0
  112. pyvale-2025.4.0/src/pyvale/simcases/case05.i +234 -0
  113. pyvale-2025.4.0/src/pyvale/simcases/case06.i +305 -0
  114. pyvale-2025.4.0/src/pyvale/simcases/case07.geo +135 -0
  115. pyvale-2025.4.0/src/pyvale/simcases/case07.i +87 -0
  116. pyvale-2025.4.0/src/pyvale/simcases/case08.geo +144 -0
  117. pyvale-2025.4.0/src/pyvale/simcases/case08.i +153 -0
  118. pyvale-2025.4.0/src/pyvale/simcases/case09.geo +204 -0
  119. pyvale-2025.4.0/src/pyvale/simcases/case09.i +87 -0
  120. pyvale-2025.4.0/src/pyvale/simcases/case10.geo +204 -0
  121. pyvale-2025.4.0/src/pyvale/simcases/case10.i +257 -0
  122. pyvale-2025.4.0/src/pyvale/simcases/case11.geo +337 -0
  123. pyvale-2025.4.0/src/pyvale/simcases/case11.i +147 -0
  124. pyvale-2025.4.0/src/pyvale/simcases/case12.geo +388 -0
  125. pyvale-2025.4.0/src/pyvale/simcases/case12.i +329 -0
  126. pyvale-2025.4.0/src/pyvale/simcases/case13.i +140 -0
  127. pyvale-2025.4.0/src/pyvale/simcases/case14.i +159 -0
  128. pyvale-2025.4.0/src/pyvale/simcases/case15.geo +337 -0
  129. pyvale-2025.4.0/src/pyvale/simcases/case15.i +150 -0
  130. pyvale-2025.4.0/src/pyvale/simcases/case16.geo +391 -0
  131. pyvale-2025.4.0/src/pyvale/simcases/case16.i +357 -0
  132. pyvale-2025.4.0/src/pyvale/simcases/case17.geo +135 -0
  133. pyvale-2025.4.0/src/pyvale/simcases/case17.i +144 -0
  134. pyvale-2025.4.0/src/pyvale/simcases/case18.i +254 -0
  135. pyvale-2025.4.0/src/pyvale/simcases/case18_1.i +254 -0
  136. pyvale-2025.4.0/src/pyvale/simcases/case18_2.i +254 -0
  137. pyvale-2025.4.0/src/pyvale/simcases/case18_3.i +254 -0
  138. pyvale-2025.4.0/src/pyvale/simcases/case19.geo +252 -0
  139. pyvale-2025.4.0/src/pyvale/simcases/case19.i +99 -0
  140. pyvale-2025.4.0/src/pyvale/simcases/case20.geo +252 -0
  141. pyvale-2025.4.0/src/pyvale/simcases/case20.i +250 -0
  142. pyvale-2025.4.0/src/pyvale/simcases/case21.geo +74 -0
  143. pyvale-2025.4.0/src/pyvale/simcases/case21.i +155 -0
  144. pyvale-2025.4.0/src/pyvale/simcases/case22.geo +82 -0
  145. pyvale-2025.4.0/src/pyvale/simcases/case22.i +140 -0
  146. pyvale-2025.4.0/src/pyvale/simcases/case23.geo +164 -0
  147. pyvale-2025.4.0/src/pyvale/simcases/case23.i +140 -0
  148. pyvale-2025.4.0/src/pyvale/simcases/case24.geo +79 -0
  149. pyvale-2025.4.0/src/pyvale/simcases/case24.i +123 -0
  150. pyvale-2025.4.0/src/pyvale/simcases/case25.geo +82 -0
  151. pyvale-2025.4.0/src/pyvale/simcases/case25.i +140 -0
  152. pyvale-2025.4.0/src/pyvale/simcases/case26.geo +166 -0
  153. pyvale-2025.4.0/src/pyvale/simcases/case26.i +140 -0
  154. pyvale-2025.4.0/src/pyvale/simcases/run_1case.py +61 -0
  155. pyvale-2025.4.0/src/pyvale/simcases/run_all_cases.py +69 -0
  156. pyvale-2025.4.0/src/pyvale/simcases/run_build_case.py +64 -0
  157. pyvale-2025.4.0/src/pyvale/simcases/run_example_cases.py +69 -0
  158. pyvale-2025.4.0/src/pyvale.egg-info/PKG-INFO +140 -0
  159. pyvale-2025.4.0/src/pyvale.egg-info/SOURCES.txt +160 -0
  160. pyvale-2025.4.0/src/pyvale.egg-info/dependency_links.txt +1 -0
  161. pyvale-2025.4.0/src/pyvale.egg-info/requires.txt +15 -0
  162. pyvale-2025.4.0/src/pyvale.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (C) 2025 The Computer Aided Validation Team at UKAEA
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,140 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyvale
3
+ Version: 2025.4.0
4
+ Summary: An all-in-one package for sensor simulation, sensor uncertainty quantification, sensor placement optimisation and simulation calibration or validation.
5
+ Author-email: "scepticalrabbit et al." <thescepticalrabbit@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (C) 2025 The Computer Aided Validation Team at UKAEA
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ Project-URL: Repository, https://github.com/Digital-Validation-Laboratory/pyvale
28
+ Project-URL: Issue Tracker, https://github.com/Digital-Validation-Laboratory/pyvale/issues
29
+ Requires-Python: ==3.11.*
30
+ Description-Content-Type: text/markdown
31
+ License-File: LICENSE
32
+ Requires-Dist: mooseherder>=0.1.0
33
+ Requires-Dist: numpy<2.0.0
34
+ Requires-Dist: scipy>=1.14.0
35
+ Requires-Dist: netCDF4>=1.6.5
36
+ Requires-Dist: pyvista>=0.43.3
37
+ Requires-Dist: matplotlib>=3.8
38
+ Requires-Dist: shapely>=2.0.4
39
+ Requires-Dist: sympy>=1.13.0
40
+ Requires-Dist: PyQT6>=6.7.1
41
+ Requires-Dist: imageio>=2.36.1
42
+ Requires-Dist: imageio-ffmpeg>=0.5.1
43
+ Requires-Dist: numba>=0.59.1
44
+ Requires-Dist: pymoo>=0.6.1.3
45
+ Requires-Dist: Cython>=3.0.0
46
+ Requires-Dist: bpy>=4.2.0
47
+ Dynamic: license-file
48
+
49
+ # pyvale
50
+ The python validation engine (`pyvale`): An all-in-one package for sensor simulation, sensor uncertainty quantification, sensor placement optimisation and simulation calibration/validation.​ Used to simulate experimental data from an input multi-physics simulation by explicitly modelling sensors with realistic uncertainties. Useful for experimental design, sensor placement optimisation, testing simulation validation metrics and virtually testing digital shadows/twins.
51
+
52
+ ## Quick Demo: Simulating Point Sensors
53
+ Here we demonstrate how `pyvale` can be used to simulate thermocouples and strain gauges applied to a [MOOSE](https://mooseframework.inl.gov/index.html) thermo-mechanical simulation of a fusion divertor armour heatsink. The figures below show visualisations of the virtual thermocouple and strain gauge locations on the simualtion mesh as well as time traces for each sensor over a series of simulated experiments. The code to run the simulated experiments and produce the output shown here comes from [this example](https://github.com/Computer-Aided-Validation-Laboratory/pyvale/blob/main/src/pyvale/examples/ex6_2_multiphysics3d_expsim.py).
54
+
55
+ |![fig_thermomech3d_tc_vis](https://raw.githubusercontent.com/Computer-Aided-Validation-Laboratory/pyvale/main/images/thermomech3d_sg_vis.svg)|![fig_thermomech3d_sg_vis](https://raw.githubusercontent.com/Computer-Aided-Validation-Laboratory/pyvale/main/images/thermomech3d_sg_vis.svg)|
56
+ |--|--|
57
+ |*Visualisation of the thermcouple locations.*|*Visualisation of the strain gauge locations.*|
58
+
59
+ |![fig_thermomech3d_tc_traces](https://raw.githubusercontent.com/Computer-Aided-Validation-Laboratory/pyvale/main/images/thermomech3d_tc_traces.png)|![fig_thermomech3d_sg_traces](https://raw.githubusercontent.com/Computer-Aided-Validation-Laboratory/pyvale/main/images/thermomech3d_sg_traces.png)|
60
+ |--|--|
61
+ |*Thermocouples time traces over a series of simulated experiments.*|*Strain gauge time traces over a series of simulated experiments.*|
62
+
63
+
64
+ ## Quick Install
65
+ `pyvale` can be installed from pypi:
66
+ ```shell
67
+ pip install pyvale
68
+ ```
69
+
70
+ ## Detailed Install: Ubuntu
71
+ ### Managing Python Versions
72
+ To be compatible with `bpy` (the Blender python interface), `pyvale` uses python 3.11. To install python 3.11 without corrupting your operating systems python installation first add the deadsnakes repository to apt:
73
+ ```shell
74
+ sudo add-apt-repository ppa:deadsnakes/ppa
75
+ sudo apt update && sudo apt upgrade -y
76
+ ```
77
+
78
+ Install python 3.11:
79
+ ```shell
80
+ sudo apt install python3.11
81
+ ```
82
+
83
+ Add `venv` to your python 3.11 install:
84
+ ```shell
85
+ sudo apt install python3.11-venv
86
+ ```
87
+
88
+ Check your python 3.11 install is working using the following command which should open an interactive python interpreter:
89
+ ```shell
90
+ python3.11
91
+ ```
92
+
93
+ ### Virtual Environment
94
+
95
+ We recommend installing `pyvale` in a virtual environment using `venv` or `pyvale` can be installed into an existing environment of your choice. To create a specific virtual environment for `pyvale` navigate to the directory you want to install the environment and use:
96
+
97
+ ```shell
98
+ python3.11 -m venv .pyvale-env
99
+ source .pyvale-env/bin/activate
100
+ ```
101
+
102
+ ### Standard Installation
103
+ `pyvale` can be installed from pypi. Ensure you virtual environment is activated and run:
104
+ ```shell
105
+ pip install pyvale
106
+ ```
107
+
108
+ ### Developer Installation
109
+
110
+ Clone `pyvale` to your local system along with submodules using
111
+ ```shell
112
+ git clone --recurse-submodules git@github.com:Computer-Aided-Validation-Laboratory/pyvale.git
113
+ ```
114
+
115
+ `cd` to the root directory of `pyvale`. Ensure you virtual environment is activated and run the following commmand from the `pyvale` directory:
116
+ ```shell
117
+ pip install -e .
118
+ pip install -e ./dependencies/mooseherder
119
+ ```
120
+
121
+ ### MOOSE
122
+ `pyvale` come pre-packaged with example `moose` physics simulation outputs (as *.e exodus files) to demonstrate its functionality. If you need to run additional simulation cases we recommend `proteus` (https://github.com/aurora-multiphysics/proteus) which has build scripts for common linux distributions.
123
+
124
+ ## Getting Started
125
+ The examples folder in "pyvale/examples" includes a sequence of examples of increasing complexity that demonstrate the functionality of `pyvale`.
126
+
127
+ ## Contributors
128
+ The Computer Aided Validation Team at UKAEA:
129
+ - Lloyd Fletcher (ScepticalRabbit), UK Atomic Energy Authority
130
+ - John Charlton (coolmule0), UK Atomic Energy Authority
131
+ - Joel Hirst (JoelPhys), UK Atomic Energy Authority
132
+ - Lorna Sibson (lornasibson), UK Atomic Energy Authority
133
+ - Adel Tayeb (3adelTayeb), UK Atomic Energy Authority
134
+ - Alex Marsh (alexmarsh2), UK Atomic Energy Authority
135
+ - Rory Spencer (fusmatrs), UK Atomic Energy Authority
136
+
137
+
138
+
139
+
140
+
@@ -0,0 +1,92 @@
1
+ # pyvale
2
+ The python validation engine (`pyvale`): An all-in-one package for sensor simulation, sensor uncertainty quantification, sensor placement optimisation and simulation calibration/validation.​ Used to simulate experimental data from an input multi-physics simulation by explicitly modelling sensors with realistic uncertainties. Useful for experimental design, sensor placement optimisation, testing simulation validation metrics and virtually testing digital shadows/twins.
3
+
4
+ ## Quick Demo: Simulating Point Sensors
5
+ Here we demonstrate how `pyvale` can be used to simulate thermocouples and strain gauges applied to a [MOOSE](https://mooseframework.inl.gov/index.html) thermo-mechanical simulation of a fusion divertor armour heatsink. The figures below show visualisations of the virtual thermocouple and strain gauge locations on the simualtion mesh as well as time traces for each sensor over a series of simulated experiments. The code to run the simulated experiments and produce the output shown here comes from [this example](https://github.com/Computer-Aided-Validation-Laboratory/pyvale/blob/main/src/pyvale/examples/ex6_2_multiphysics3d_expsim.py).
6
+
7
+ |![fig_thermomech3d_tc_vis](https://raw.githubusercontent.com/Computer-Aided-Validation-Laboratory/pyvale/main/images/thermomech3d_sg_vis.svg)|![fig_thermomech3d_sg_vis](https://raw.githubusercontent.com/Computer-Aided-Validation-Laboratory/pyvale/main/images/thermomech3d_sg_vis.svg)|
8
+ |--|--|
9
+ |*Visualisation of the thermcouple locations.*|*Visualisation of the strain gauge locations.*|
10
+
11
+ |![fig_thermomech3d_tc_traces](https://raw.githubusercontent.com/Computer-Aided-Validation-Laboratory/pyvale/main/images/thermomech3d_tc_traces.png)|![fig_thermomech3d_sg_traces](https://raw.githubusercontent.com/Computer-Aided-Validation-Laboratory/pyvale/main/images/thermomech3d_sg_traces.png)|
12
+ |--|--|
13
+ |*Thermocouples time traces over a series of simulated experiments.*|*Strain gauge time traces over a series of simulated experiments.*|
14
+
15
+
16
+ ## Quick Install
17
+ `pyvale` can be installed from pypi:
18
+ ```shell
19
+ pip install pyvale
20
+ ```
21
+
22
+ ## Detailed Install: Ubuntu
23
+ ### Managing Python Versions
24
+ To be compatible with `bpy` (the Blender python interface), `pyvale` uses python 3.11. To install python 3.11 without corrupting your operating systems python installation first add the deadsnakes repository to apt:
25
+ ```shell
26
+ sudo add-apt-repository ppa:deadsnakes/ppa
27
+ sudo apt update && sudo apt upgrade -y
28
+ ```
29
+
30
+ Install python 3.11:
31
+ ```shell
32
+ sudo apt install python3.11
33
+ ```
34
+
35
+ Add `venv` to your python 3.11 install:
36
+ ```shell
37
+ sudo apt install python3.11-venv
38
+ ```
39
+
40
+ Check your python 3.11 install is working using the following command which should open an interactive python interpreter:
41
+ ```shell
42
+ python3.11
43
+ ```
44
+
45
+ ### Virtual Environment
46
+
47
+ We recommend installing `pyvale` in a virtual environment using `venv` or `pyvale` can be installed into an existing environment of your choice. To create a specific virtual environment for `pyvale` navigate to the directory you want to install the environment and use:
48
+
49
+ ```shell
50
+ python3.11 -m venv .pyvale-env
51
+ source .pyvale-env/bin/activate
52
+ ```
53
+
54
+ ### Standard Installation
55
+ `pyvale` can be installed from pypi. Ensure you virtual environment is activated and run:
56
+ ```shell
57
+ pip install pyvale
58
+ ```
59
+
60
+ ### Developer Installation
61
+
62
+ Clone `pyvale` to your local system along with submodules using
63
+ ```shell
64
+ git clone --recurse-submodules git@github.com:Computer-Aided-Validation-Laboratory/pyvale.git
65
+ ```
66
+
67
+ `cd` to the root directory of `pyvale`. Ensure you virtual environment is activated and run the following commmand from the `pyvale` directory:
68
+ ```shell
69
+ pip install -e .
70
+ pip install -e ./dependencies/mooseherder
71
+ ```
72
+
73
+ ### MOOSE
74
+ `pyvale` come pre-packaged with example `moose` physics simulation outputs (as *.e exodus files) to demonstrate its functionality. If you need to run additional simulation cases we recommend `proteus` (https://github.com/aurora-multiphysics/proteus) which has build scripts for common linux distributions.
75
+
76
+ ## Getting Started
77
+ The examples folder in "pyvale/examples" includes a sequence of examples of increasing complexity that demonstrate the functionality of `pyvale`.
78
+
79
+ ## Contributors
80
+ The Computer Aided Validation Team at UKAEA:
81
+ - Lloyd Fletcher (ScepticalRabbit), UK Atomic Energy Authority
82
+ - John Charlton (coolmule0), UK Atomic Energy Authority
83
+ - Joel Hirst (JoelPhys), UK Atomic Energy Authority
84
+ - Lorna Sibson (lornasibson), UK Atomic Energy Authority
85
+ - Adel Tayeb (3adelTayeb), UK Atomic Energy Authority
86
+ - Alex Marsh (alexmarsh2), UK Atomic Energy Authority
87
+ - Rory Spencer (fusmatrs), UK Atomic Energy Authority
88
+
89
+
90
+
91
+
92
+
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pyvale"
7
+ version = "2025.4.0"
8
+ description = "An all-in-one package for sensor simulation, sensor uncertainty quantification, sensor placement optimisation and simulation calibration or validation."
9
+ authors = [
10
+ { name = "scepticalrabbit et al.", email = "thescepticalrabbit@gmail.com" },
11
+ ]
12
+ license = { file = "LICENSE" }
13
+ readme = "README.md"
14
+ requires-python = "==3.11.*"
15
+ dependencies = [
16
+ "mooseherder>=0.1.0",
17
+ "numpy<2.0.0",
18
+ "scipy>=1.14.0",
19
+ "netCDF4>=1.6.5",
20
+ "pyvista>=0.43.3",
21
+ "matplotlib>=3.8",
22
+ "shapely>=2.0.4",
23
+ "sympy>=1.13.0",
24
+ "PyQT6>=6.7.1",
25
+ "imageio>=2.36.1",
26
+ "imageio-ffmpeg>=0.5.1",
27
+ "numba>=0.59.1",
28
+ "pymoo>=0.6.1.3",
29
+ "Cython>=3.0.0",
30
+ "bpy>=4.2.0",
31
+ ]
32
+
33
+ [project.urls]
34
+ "Repository" = "https://github.com/Digital-Validation-Laboratory/pyvale"
35
+ "Issue Tracker" = "https://github.com/Digital-Validation-Laboratory/pyvale/issues"
36
+
37
+ [tool.setuptools.package-data]
38
+ "pyvale.data" = ["*.e","*.tiff"]
39
+ "pyvale.simcases" = ["*.i","*.geo"]
40
+
41
+ [tool.setuptools.packages.find]
42
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,75 @@
1
+ """
2
+ `pyvale`: the python validation engine. Used to simulate experimental data from
3
+ an input multi-physics simulation by explicitly modelling sensors with realistic
4
+ uncertainties. Useful for experimental design, sensor placement optimisation,
5
+ testing simulation validation metrics and testing digital shadows/twins.
6
+ """
7
+
8
+ """
9
+ ================================================================================
10
+ pyvale: the python validation engine
11
+ License: MIT
12
+ Copyright (C) 2025 The Computer Aided Validation Team
13
+ ================================================================================
14
+ """
15
+ # NOTE: this simplifies and decouples how the user calls pyvale from the
16
+ # underlying project structure: the user should be able to use 'pyvale.'
17
+ # and access everything in one layer without multiple import dots
18
+
19
+ from pyvale.core.dataset import *
20
+
21
+ from pyvale.core.field import *
22
+ from pyvale.core.fieldscalar import *
23
+ from pyvale.core.fieldvector import *
24
+ from pyvale.core.fieldtensor import *
25
+ from pyvale.core.fieldconverter import *
26
+ from pyvale.core.fieldtransform import *
27
+
28
+ from pyvale.core.integratorspatial import *
29
+ from pyvale.core.integratorquadrature import *
30
+ from pyvale.core.integratorrectangle import *
31
+ from pyvale.core.integratorfactory import *
32
+
33
+ from pyvale.core.sensordescriptor import *
34
+ from pyvale.core.sensortools import *
35
+ from pyvale.core.sensorarray import *
36
+ from pyvale.core.sensorarrayfactory import *
37
+ from pyvale.core.sensorarraypoint import *
38
+ from pyvale.core.sensordata import *
39
+
40
+ from pyvale.core.camera import *
41
+ from pyvale.core.cameradata import *
42
+ from pyvale.core.cameradata2d import *
43
+ from pyvale.core.cameratools import *
44
+
45
+ import pyvale.core.cython.rastercyth as rastercyth
46
+ from pyvale.core.rastercy import *
47
+
48
+ from pyvale.core.rendermesh import *
49
+ from pyvale.core.rasternp import *
50
+
51
+ from pyvale.core.imagedef2d import *
52
+
53
+ from pyvale.core.errorintegrator import *
54
+ from pyvale.core.errorrand import *
55
+ from pyvale.core.errorsysindep import *
56
+ from pyvale.core.errorsysdep import *
57
+ from pyvale.core.errorsysfield import *
58
+ from pyvale.core.errordriftcalc import *
59
+
60
+ from pyvale.core.generatorsrandom import *
61
+
62
+ from pyvale.core.visualopts import *
63
+ from pyvale.core.visualtools import *
64
+ from pyvale.core.visualsimplotter import *
65
+ from pyvale.core.visualsimanimator import *
66
+ from pyvale.core.visualexpplotter import *
67
+ from pyvale.core.visualtraceplotter import *
68
+ from pyvale.core.visualimages import *
69
+ from pyvale.core.visualimagedef import *
70
+
71
+ from pyvale.core.analyticmeshgen import *
72
+ from pyvale.core.analyticsimdatagenerator import *
73
+ from pyvale.core.analyticsimdatafactory import *
74
+
75
+ from pyvale.core.experimentsimulator import *
@@ -0,0 +1,7 @@
1
+ """
2
+ ================================================================================
3
+ pyvale: the python validation engine
4
+ License: MIT
5
+ Copyright (C) 2025 The Computer Aided Validation Team
6
+ ================================================================================
7
+ """
@@ -0,0 +1,59 @@
1
+ """
2
+ ================================================================================
3
+ pyvale: the python validation engine
4
+ License: MIT
5
+ Copyright (C) 2025 The Computer Aided Validation Team
6
+ ================================================================================
7
+ """
8
+ import numpy as np
9
+
10
+ # NOTE: This module is a feature under developement.
11
+
12
+ def rectangle_mesh_2d(leng_x: float,
13
+ leng_y: float,
14
+ n_elem_x: int,
15
+ n_elem_y: int) -> tuple[np.ndarray,np.ndarray]:
16
+
17
+ n_elems = n_elem_x*n_elem_y
18
+ n_node_x = n_elem_x+1
19
+ n_node_y = n_elem_y+1
20
+ nodes_per_elem = 4
21
+
22
+ coord_x = np.linspace(0,leng_x,n_node_x)
23
+ coord_y = np.linspace(0,leng_y,n_node_y)
24
+ (coord_grid_x,coord_grid_y) = np.meshgrid(coord_x,coord_y)
25
+
26
+ coord_x = np.atleast_2d(coord_grid_x.flatten()).T
27
+ coord_y = np.atleast_2d(coord_grid_y.flatten()).T
28
+ coord_z = np.zeros_like(coord_x)
29
+ coords = np.hstack((coord_x,coord_y,coord_z))
30
+
31
+ connect = np.zeros((n_elems,nodes_per_elem)).astype(np.int64)
32
+ row = 1
33
+ nn = 0
34
+ for ee in range(n_elems):
35
+ nn += 1
36
+ if nn >= row*n_node_x:
37
+ row += 1
38
+ nn += 1
39
+
40
+ connect[ee,:] = np.array([nn,nn+1,nn+n_node_x+1,nn+n_node_x])
41
+ connect = connect.T
42
+
43
+ return (coords,connect)
44
+
45
+
46
+ def fill_dims(coord_x: np.ndarray,
47
+ coord_y: np.ndarray,
48
+ time: np.ndarray) -> tuple[np.ndarray,np.ndarray,np.ndarray]:
49
+
50
+ full_x = np.repeat(np.atleast_2d(coord_x).T,
51
+ time.shape[0],
52
+ axis=1)
53
+ full_y = np.repeat(np.atleast_2d(coord_y).T,
54
+ time.shape[0],
55
+ axis=1)
56
+ full_time = np.repeat(np.atleast_2d(time),
57
+ coord_x.shape[0],
58
+ axis=0)
59
+ return (full_x,full_y,full_time)
@@ -0,0 +1,63 @@
1
+ """
2
+ ================================================================================
3
+ pyvale: the python validation engine
4
+ License: MIT
5
+ Copyright (C) 2025 The Computer Aided Validation Team
6
+ ================================================================================
7
+ """
8
+ import numpy as np
9
+ import sympy
10
+ import mooseherder as mh
11
+ from pyvale.core.analyticsimdatagenerator import (AnalyticCaseData2D,
12
+ AnalyticSimDataGenerator)
13
+
14
+ # NOTE: This module is a feature under developement.
15
+
16
+ def standard_case_2d() -> AnalyticCaseData2D:
17
+ case_data = AnalyticCaseData2D()
18
+ case_data.length_x = 10.0
19
+ case_data.length_y = 7.5
20
+ n_elem_mult = 10
21
+ case_data.num_elem_x = 4*n_elem_mult
22
+ case_data.num_elem_y = 3*n_elem_mult
23
+ case_data.time_steps = np.linspace(0.0,1.0,11)
24
+ return case_data
25
+
26
+
27
+ class AnalyticCaseFactory:
28
+
29
+ @staticmethod
30
+ def scalar_linear_2d() -> tuple[mh.SimData,AnalyticSimDataGenerator]:
31
+
32
+ case_data = standard_case_2d()
33
+ (sym_y,sym_x,sym_t) = sympy.symbols("y,x,t")
34
+ case_data.funcs_x = (20.0/case_data.length_x * sym_x,)
35
+ case_data.funcs_y = (10.0/case_data.length_y * sym_y,)
36
+ case_data.funcs_t = (sym_t,)
37
+ case_data.offsets_space = (20.0,)
38
+ case_data.offsets_time = (0.0,)
39
+
40
+ data_gen = AnalyticSimDataGenerator(case_data)
41
+
42
+ sim_data = data_gen.generate_sim_data()
43
+
44
+ return (sim_data,data_gen)
45
+
46
+ @staticmethod
47
+ def scalar_quadratic_2d() -> tuple[mh.SimData,AnalyticSimDataGenerator]:
48
+
49
+ case_data = standard_case_2d()
50
+ (sym_y,sym_x,sym_t) = sympy.symbols("y,x,t")
51
+ case_data.funcs_x = (sym_x*(sym_x - case_data.length_x),)
52
+ case_data.funcs_y = (sym_y*(sym_y - case_data.length_y),)
53
+ case_data.funcs_t = (sym_t,)
54
+
55
+ data_gen = AnalyticSimDataGenerator(case_data)
56
+
57
+ sim_data = data_gen.generate_sim_data()
58
+
59
+ return (sim_data,data_gen)
60
+
61
+
62
+
63
+
@@ -0,0 +1,160 @@
1
+ """
2
+ ================================================================================
3
+ pyvale: the python validation engine
4
+ License: MIT
5
+ Copyright (C) 2025 The Computer Aided Validation Team
6
+ ================================================================================
7
+ """
8
+ from dataclasses import dataclass
9
+ import numpy as np
10
+ import sympy
11
+ import mooseherder as mh
12
+ from pyvale.core.analyticmeshgen import rectangle_mesh_2d, fill_dims
13
+
14
+ # NOTE: This module is a feature under developement.
15
+
16
+ @dataclass
17
+ class AnalyticCaseData2D:
18
+ length_x: float = 10.0
19
+ length_y: float = 7.5
20
+ num_elem_x: int = 4
21
+ num_elem_y: int = 3
22
+ time_steps: np.ndarray | None = None
23
+ field_keys: tuple[str,...] = ('scalar',)
24
+ funcs_x: tuple[sympy.Expr,...] | None = None
25
+ funcs_y: tuple[sympy.Expr,...] | None = None
26
+ funcs_t: tuple[sympy.Expr,...] | None = None
27
+ symbols: tuple[sympy.Symbol,...] = (sympy.Symbol("y"),
28
+ sympy.Symbol("x"),
29
+ sympy.Symbol("t"))
30
+ offsets_space: tuple[float,...] = (0.0,)
31
+ offsets_time: tuple[float,...] = (0.0,)
32
+ nodes_per_elem: int = 4
33
+
34
+
35
+ class AnalyticSimDataGenerator:
36
+ def __init__(self, case_data: AnalyticCaseData2D
37
+ ) -> None:
38
+
39
+ self._case_data = case_data
40
+ (self._coords,self._connect) = rectangle_mesh_2d(case_data.length_x,
41
+ case_data.length_y,
42
+ case_data.num_elem_x,
43
+ case_data.num_elem_y)
44
+
45
+ self._field_sym_funcs = dict()
46
+ self._field_lam_funcs = dict()
47
+ for ii,kk in enumerate(case_data.field_keys):
48
+ self._field_sym_funcs[kk] = ((case_data.funcs_x[ii] *
49
+ case_data.funcs_y[ii] +
50
+ case_data.offsets_space[ii]) *
51
+ (case_data.funcs_t[ii] +
52
+ case_data.offsets_time[ii]))
53
+
54
+ self._field_lam_funcs[kk] = sympy.lambdify(case_data.symbols,
55
+ self._field_sym_funcs[kk],
56
+ 'numpy')
57
+ self._field_eval = dict()
58
+
59
+
60
+ def evaluate_field_truth(self,
61
+ field_key: str,
62
+ coords: np.ndarray,
63
+ time_steps: np.ndarray | None = None) -> np.ndarray:
64
+
65
+ if time_steps is None:
66
+ time_steps = self._case_data.time_steps
67
+
68
+ (x_eval,y_eval,t_eval) = fill_dims(coords[:,0],
69
+ coords[:,1],
70
+ time_steps)
71
+
72
+ field_vals = self._field_lam_funcs[field_key](y_eval,
73
+ x_eval,
74
+ t_eval)
75
+ return field_vals
76
+
77
+
78
+ def evaluate_all_fields_truth(self,
79
+ coords: np.ndarray,
80
+ time_steps: np.ndarray | None = None) -> np.ndarray:
81
+
82
+ if time_steps is None:
83
+ time_steps = self._case_data.time_steps
84
+
85
+ (x_eval,y_eval,t_eval) = fill_dims(coords[:,0],
86
+ coords[:,1],
87
+ time_steps)
88
+
89
+ eval_comps = dict()
90
+ for kk in self._case_data.field_keys:
91
+ eval_comps[kk] = self._field_lam_funcs[kk](y_eval,
92
+ x_eval,
93
+ t_eval)
94
+ return eval_comps
95
+
96
+
97
+ def evaluate_field_at_nodes(self, field_key: str) -> np.ndarray:
98
+ (x_eval,y_eval,t_eval) = fill_dims(self._coords[:,0],
99
+ self._coords[:,1],
100
+ self._case_data.time_steps)
101
+
102
+ self._field_eval[field_key] = self._field_lam_funcs[field_key](y_eval,
103
+ x_eval,
104
+ t_eval)
105
+ return self._field_eval[field_key]
106
+
107
+ def evaluate_all_fields_at_nodes(self) -> dict[str,np.ndarray]:
108
+ (x_eval,y_eval,t_eval) = fill_dims(self._coords[:,0],
109
+ self._coords[:,1],
110
+ self._case_data.time_steps)
111
+ eval_comps = dict()
112
+ for kk in self._case_data.field_keys:
113
+ eval_comps[kk] = self._field_lam_funcs[kk](y_eval,
114
+ x_eval,
115
+ t_eval)
116
+ self._field_eval = eval_comps
117
+ return self._field_eval
118
+
119
+
120
+ def generate_sim_data(self) -> mh.SimData:
121
+
122
+ sim_data = mh.SimData()
123
+ sim_data.num_spat_dims = 2
124
+ sim_data.time = self._case_data.time_steps
125
+ sim_data.coords = self._coords
126
+ sim_data.connect = {'connect1': self._connect}
127
+
128
+ if not self._field_eval:
129
+ self.evaluate_all_fields_at_nodes()
130
+ sim_data.node_vars = self._field_eval
131
+
132
+ return sim_data
133
+
134
+
135
+ def get_visualisation_grid(self,
136
+ field_key: str | None = None,
137
+ time_step: int = -1
138
+ ) -> tuple[np.ndarray,np.ndarray,np.ndarray]:
139
+
140
+ if field_key is None:
141
+ field_key = self._case_data.field_keys[0]
142
+
143
+ grid_shape = (self._case_data.num_elem_y+1,
144
+ self._case_data.num_elem_x+1)
145
+
146
+ grid_x = np.atleast_2d(self._coords[:,0]).T.reshape(grid_shape)
147
+ grid_y = np.atleast_2d(self._coords[:,1]).T.reshape(grid_shape)
148
+
149
+ if not self._field_eval:
150
+ self.evaluate_all_fields_at_nodes()
151
+
152
+ scalar_grid = np.reshape(self._field_eval[field_key][:,time_step],grid_shape)
153
+
154
+ return (grid_x,grid_y,scalar_grid)
155
+
156
+
157
+
158
+
159
+
160
+