pyvale 2025.7.2__cp311-cp311-macosx_14_0_arm64.whl → 2025.8.1__cp311-cp311-macosx_14_0_arm64.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.

Files changed (176) hide show
  1. pyvale/__init__.py +12 -92
  2. pyvale/blender/__init__.py +23 -0
  3. pyvale/{pyvaleexceptions.py → blender/blenderexceptions.py} +0 -3
  4. pyvale/{blenderlightdata.py → blender/blenderlightdata.py} +3 -3
  5. pyvale/{blendermaterialdata.py → blender/blendermaterialdata.py} +1 -1
  6. pyvale/{blenderrenderdata.py → blender/blenderrenderdata.py} +5 -3
  7. pyvale/{blenderscene.py → blender/blenderscene.py} +33 -30
  8. pyvale/{blendertools.py → blender/blendertools.py} +14 -10
  9. pyvale/dataset/__init__.py +7 -0
  10. pyvale/dataset/dataset.py +443 -0
  11. pyvale/dic/__init__.py +20 -0
  12. pyvale/{dic2d.py → dic/dic2d.py} +31 -36
  13. pyvale/dic/dic2dconv.py +6 -0
  14. pyvale/{dic2dcpp.cpython-311-darwin.so → dic/dic2dcpp.cpython-311-darwin.so} +0 -0
  15. pyvale/{dicdataimport.py → dic/dicdataimport.py} +8 -8
  16. pyvale/{dicregionofinterest.py → dic/dicregionofinterest.py} +1 -1
  17. pyvale/{dicresults.py → dic/dicresults.py} +1 -1
  18. pyvale/{dicstrain.py → dic/dicstrain.py} +9 -9
  19. pyvale/examples/basics/{ex1_1_basicscalars_therm2d.py → ex1a_basicscalars_therm2d.py} +12 -9
  20. pyvale/examples/basics/{ex1_2_sensormodel_therm2d.py → ex1b_sensormodel_therm2d.py} +17 -14
  21. pyvale/examples/basics/{ex1_3_customsens_therm3d.py → ex1c_customsens_therm3d.py} +27 -24
  22. pyvale/examples/basics/{ex1_4_basicerrors_therm3d.py → ex1d_basicerrors_therm3d.py} +32 -29
  23. pyvale/examples/basics/{ex1_5_fielderrs_therm3d.py → ex1e_fielderrs_therm3d.py} +19 -15
  24. pyvale/examples/basics/{ex1_6_caliberrs_therm2d.py → ex1f_caliberrs_therm2d.py} +20 -16
  25. pyvale/examples/basics/{ex1_7_spatavg_therm2d.py → ex1g_spatavg_therm2d.py} +19 -16
  26. pyvale/examples/basics/{ex2_1_basicvectors_disp2d.py → ex2a_basicvectors_disp2d.py} +13 -10
  27. pyvale/examples/basics/{ex2_2_vectorsens_disp2d.py → ex2b_vectorsens_disp2d.py} +19 -15
  28. pyvale/examples/basics/{ex2_3_sensangle_disp2d.py → ex2c_sensangle_disp2d.py} +21 -18
  29. pyvale/examples/basics/{ex2_4_chainfielderrs_disp2d.py → ex2d_chainfielderrs_disp2d.py} +31 -29
  30. pyvale/examples/basics/{ex2_5_vectorfields3d_disp3d.py → ex2e_vectorfields3d_disp3d.py} +21 -18
  31. pyvale/examples/basics/{ex3_1_basictensors_strain2d.py → ex3a_basictensors_strain2d.py} +16 -14
  32. pyvale/examples/basics/{ex3_2_tensorsens2d_strain2d.py → ex3b_tensorsens2d_strain2d.py} +17 -14
  33. pyvale/examples/basics/{ex3_3_tensorsens3d_strain3d.py → ex3c_tensorsens3d_strain3d.py} +25 -22
  34. pyvale/examples/basics/{ex4_1_expsim2d_thermmech2d.py → ex4a_expsim2d_thermmech2d.py} +17 -14
  35. pyvale/examples/basics/{ex4_2_expsim3d_thermmech3d.py → ex4b_expsim3d_thermmech3d.py} +37 -34
  36. pyvale/examples/basics/ex5_nomesh.py +24 -0
  37. pyvale/examples/dic/ex1_2_blenderdeformed.py +174 -0
  38. pyvale/examples/dic/ex1_region_of_interest.py +6 -3
  39. pyvale/examples/dic/ex2_plate_with_hole.py +21 -18
  40. pyvale/examples/dic/ex3_plate_with_hole_strain.py +8 -6
  41. pyvale/examples/dic/ex4_dic_blender.py +17 -15
  42. pyvale/examples/dic/ex5_dic_challenge.py +19 -14
  43. pyvale/examples/genanalyticdata/ex1_1_scalarvisualisation.py +16 -10
  44. pyvale/examples/genanalyticdata/ex1_2_scalarcasebuild.py +3 -3
  45. pyvale/examples/genanalyticdata/ex2_1_analyticsensors.py +29 -23
  46. pyvale/examples/genanalyticdata/ex2_2_analyticsensors_nomesh.py +67 -0
  47. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +12 -9
  48. pyvale/examples/mooseherder/ex0_create_moose_config.py +65 -0
  49. pyvale/examples/mooseherder/ex1a_modify_moose_input.py +71 -0
  50. pyvale/examples/mooseherder/ex1b_modify_gmsh_input.py +69 -0
  51. pyvale/examples/mooseherder/ex2a_run_moose_once.py +80 -0
  52. pyvale/examples/mooseherder/ex2b_run_gmsh_once.py +64 -0
  53. pyvale/examples/mooseherder/ex2c_run_both_once.py +114 -0
  54. pyvale/examples/mooseherder/ex3_run_moose_seq_para.py +157 -0
  55. pyvale/examples/mooseherder/ex4_run_gmsh-moose_seq_para.py +176 -0
  56. pyvale/examples/mooseherder/ex5_run_moose_paramulti.py +136 -0
  57. pyvale/examples/mooseherder/ex6_read_moose_exodus.py +163 -0
  58. pyvale/examples/mooseherder/ex7a_read_moose_herd_results.py +153 -0
  59. pyvale/examples/mooseherder/ex7b_read_multi_herd_results.py +116 -0
  60. pyvale/examples/mooseherder/ex7c_read_multi_gmshmoose_results.py +127 -0
  61. pyvale/examples/mooseherder/ex7d_readconfig_multi_gmshmoose_results.py +143 -0
  62. pyvale/examples/mooseherder/ex8_read_existing_sweep_output.py +72 -0
  63. pyvale/examples/renderblender/ex1_1_blenderscene.py +24 -20
  64. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +22 -18
  65. pyvale/examples/renderblender/ex2_1_stereoscene.py +36 -29
  66. pyvale/examples/renderblender/ex2_2_stereodeformed.py +26 -20
  67. pyvale/examples/renderblender/ex3_1_blendercalibration.py +24 -17
  68. pyvale/examples/renderrasterisation/ex_rastenp.py +14 -12
  69. pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +14 -15
  70. pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +13 -11
  71. pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +13 -11
  72. pyvale/mooseherder/__init__.py +32 -0
  73. pyvale/mooseherder/directorymanager.py +416 -0
  74. pyvale/mooseherder/exodusreader.py +763 -0
  75. pyvale/mooseherder/gmshrunner.py +163 -0
  76. pyvale/mooseherder/inputmodifier.py +236 -0
  77. pyvale/mooseherder/mooseconfig.py +226 -0
  78. pyvale/mooseherder/mooseherd.py +527 -0
  79. pyvale/mooseherder/mooserunner.py +303 -0
  80. pyvale/mooseherder/outputreader.py +22 -0
  81. pyvale/mooseherder/simdata.py +92 -0
  82. pyvale/mooseherder/simrunner.py +31 -0
  83. pyvale/mooseherder/sweepreader.py +356 -0
  84. pyvale/mooseherder/sweeptools.py +76 -0
  85. pyvale/sensorsim/__init__.py +82 -0
  86. pyvale/{camera.py → sensorsim/camera.py} +7 -7
  87. pyvale/{camerasensor.py → sensorsim/camerasensor.py} +7 -7
  88. pyvale/{camerastereo.py → sensorsim/camerastereo.py} +2 -2
  89. pyvale/{cameratools.py → sensorsim/cameratools.py} +4 -4
  90. pyvale/{cython → sensorsim/cython}/rastercyth.c +596 -596
  91. pyvale/{cython → sensorsim/cython}/rastercyth.cpython-311-darwin.so +0 -0
  92. pyvale/{cython → sensorsim/cython}/rastercyth.py +16 -17
  93. pyvale/{errorcalculator.py → sensorsim/errorcalculator.py} +1 -1
  94. pyvale/{errorintegrator.py → sensorsim/errorintegrator.py} +2 -2
  95. pyvale/{errorrand.py → sensorsim/errorrand.py} +4 -4
  96. pyvale/{errorsyscalib.py → sensorsim/errorsyscalib.py} +2 -2
  97. pyvale/{errorsysdep.py → sensorsim/errorsysdep.py} +2 -2
  98. pyvale/{errorsysfield.py → sensorsim/errorsysfield.py} +8 -8
  99. pyvale/{errorsysindep.py → sensorsim/errorsysindep.py} +3 -3
  100. pyvale/sensorsim/exceptions.py +8 -0
  101. pyvale/{experimentsimulator.py → sensorsim/experimentsimulator.py} +23 -3
  102. pyvale/{field.py → sensorsim/field.py} +1 -1
  103. pyvale/{fieldconverter.py → sensorsim/fieldconverter.py} +72 -19
  104. pyvale/sensorsim/fieldinterp.py +37 -0
  105. pyvale/sensorsim/fieldinterpmesh.py +124 -0
  106. pyvale/sensorsim/fieldinterppoints.py +55 -0
  107. pyvale/{fieldsampler.py → sensorsim/fieldsampler.py} +4 -4
  108. pyvale/{fieldscalar.py → sensorsim/fieldscalar.py} +28 -24
  109. pyvale/{fieldtensor.py → sensorsim/fieldtensor.py} +33 -31
  110. pyvale/{fieldvector.py → sensorsim/fieldvector.py} +33 -31
  111. pyvale/{imagedef2d.py → sensorsim/imagedef2d.py} +9 -5
  112. pyvale/{integratorfactory.py → sensorsim/integratorfactory.py} +6 -6
  113. pyvale/{integratorquadrature.py → sensorsim/integratorquadrature.py} +3 -3
  114. pyvale/{integratorrectangle.py → sensorsim/integratorrectangle.py} +3 -3
  115. pyvale/{integratorspatial.py → sensorsim/integratorspatial.py} +1 -1
  116. pyvale/{rastercy.py → sensorsim/rastercy.py} +5 -5
  117. pyvale/{rasternp.py → sensorsim/rasternp.py} +9 -9
  118. pyvale/{rasteropts.py → sensorsim/rasteropts.py} +1 -1
  119. pyvale/{renderer.py → sensorsim/renderer.py} +1 -1
  120. pyvale/{rendermesh.py → sensorsim/rendermesh.py} +5 -5
  121. pyvale/{renderscene.py → sensorsim/renderscene.py} +2 -2
  122. pyvale/{sensorarray.py → sensorsim/sensorarray.py} +1 -1
  123. pyvale/{sensorarrayfactory.py → sensorsim/sensorarrayfactory.py} +12 -12
  124. pyvale/{sensorarraypoint.py → sensorsim/sensorarraypoint.py} +10 -8
  125. pyvale/{sensordata.py → sensorsim/sensordata.py} +1 -1
  126. pyvale/{sensortools.py → sensorsim/sensortools.py} +2 -20
  127. pyvale/sensorsim/simtools.py +174 -0
  128. pyvale/{visualexpplotter.py → sensorsim/visualexpplotter.py} +3 -3
  129. pyvale/{visualimages.py → sensorsim/visualimages.py} +2 -2
  130. pyvale/{visualsimanimator.py → sensorsim/visualsimanimator.py} +4 -4
  131. pyvale/{visualsimplotter.py → sensorsim/visualsimplotter.py} +5 -5
  132. pyvale/{visualsimsensors.py → sensorsim/visualsimsensors.py} +12 -12
  133. pyvale/{visualtools.py → sensorsim/visualtools.py} +1 -1
  134. pyvale/{visualtraceplotter.py → sensorsim/visualtraceplotter.py} +2 -2
  135. pyvale/simcases/case17.geo +3 -0
  136. pyvale/simcases/case17.i +4 -4
  137. pyvale/simcases/run_1case.py +1 -9
  138. pyvale/simcases/run_all_cases.py +1 -1
  139. pyvale/simcases/run_build_case.py +1 -1
  140. pyvale/simcases/run_example_cases.py +1 -1
  141. pyvale/verif/__init__.py +12 -0
  142. pyvale/{analyticsimdatafactory.py → verif/analyticsimdatafactory.py} +2 -2
  143. pyvale/{analyticsimdatagenerator.py → verif/analyticsimdatagenerator.py} +2 -2
  144. pyvale/verif/psens.py +125 -0
  145. pyvale/verif/psensconst.py +18 -0
  146. pyvale/verif/psensmech.py +227 -0
  147. pyvale/verif/psensmultiphys.py +187 -0
  148. pyvale/verif/psensscalar.py +347 -0
  149. pyvale/verif/psenstensor.py +123 -0
  150. pyvale/verif/psensvector.py +116 -0
  151. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/METADATA +6 -7
  152. pyvale-2025.8.1.dist-info/RECORD +262 -0
  153. pyvale/dataset.py +0 -415
  154. pyvale/simtools.py +0 -67
  155. pyvale-2025.7.2.dist-info/RECORD +0 -214
  156. /pyvale/{blendercalibrationdata.py → blender/blendercalibrationdata.py} +0 -0
  157. /pyvale/{dicchecks.py → dic/dicchecks.py} +0 -0
  158. /pyvale/{dicspecklegenerator.py → dic/dicspecklegenerator.py} +0 -0
  159. /pyvale/{dicspecklequality.py → dic/dicspecklequality.py} +0 -0
  160. /pyvale/{dicstrainresults.py → dic/dicstrainresults.py} +0 -0
  161. /pyvale/{cameradata.py → sensorsim/cameradata.py} +0 -0
  162. /pyvale/{cameradata2d.py → sensorsim/cameradata2d.py} +0 -0
  163. /pyvale/{errordriftcalc.py → sensorsim/errordriftcalc.py} +0 -0
  164. /pyvale/{fieldtransform.py → sensorsim/fieldtransform.py} +0 -0
  165. /pyvale/{generatorsrandom.py → sensorsim/generatorsrandom.py} +0 -0
  166. /pyvale/{imagetools.py → sensorsim/imagetools.py} +0 -0
  167. /pyvale/{integratortype.py → sensorsim/integratortype.py} +0 -0
  168. /pyvale/{output.py → sensorsim/output.py} +0 -0
  169. /pyvale/{raster.py → sensorsim/raster.py} +0 -0
  170. /pyvale/{sensordescriptor.py → sensorsim/sensordescriptor.py} +0 -0
  171. /pyvale/{visualimagedef.py → sensorsim/visualimagedef.py} +0 -0
  172. /pyvale/{visualopts.py → sensorsim/visualopts.py} +0 -0
  173. /pyvale/{analyticmeshgen.py → verif/analyticmeshgen.py} +0 -0
  174. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/WHEEL +0 -0
  175. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/licenses/LICENSE +0 -0
  176. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/top_level.txt +0 -0
@@ -7,16 +7,19 @@
7
7
 
8
8
  from pathlib import Path
9
9
  import numpy as np
10
- import mooseherder as mh
11
- import pyvale as pyv
10
+
11
+ # Pyvale Imports
12
+ import pyvale.sensorsim as sens
13
+ import pyvale.mooseherder as mh
14
+ import pyvale.dataset as dataset
12
15
 
13
16
 
14
17
  def main() -> None:
15
- sim_path = pyv.DataSet.mechanical_2d_path()
18
+ sim_path = dataset.mechanical_2d_path()
16
19
  sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
17
20
 
18
- image_path = pyv.DataSet.dic_pattern_5mpx_path()
19
- image_speckle = pyv.ImageTools.load_image_greyscale(image_path)
21
+ image_path = dataset.dic_pattern_5mpx_path()
22
+ image_speckle = sens.ImageTools.load_image_greyscale(image_path)
20
23
 
21
24
  save_path = Path.cwd()/"pyvale-output"
22
25
  if not save_path.is_dir():
@@ -36,12 +39,12 @@ def main() -> None:
36
39
  print(80*"-")
37
40
 
38
41
 
39
- cam_data = pyv.CameraData2D(pixels_count=np.array((1040,1540)),
42
+ cam_data = sens.CameraData2D(pixels_count=np.array((1040,1540)),
40
43
  leng_per_px=0.1e-3,
41
44
  bits=8,
42
45
  roi_cent_world=np.mean(coords,axis=0),
43
46
  subsample=3)
44
- id_opts = pyv.ImageDefOpts(save_path=save_path,
47
+ id_opts = sens.ImageDefOpts(save_path=save_path,
45
48
  crop_on=True,
46
49
  add_static_ref=True)
47
50
 
@@ -51,7 +54,7 @@ def main() -> None:
51
54
  image_mask,
52
55
  image_input,
53
56
  disp_x,
54
- disp_y) = pyv.ImageDef2D.preprocess(cam_data,
57
+ disp_y) = sens.ImageDef2D.preprocess(cam_data,
55
58
  image_speckle,
56
59
  coords,
57
60
  connectivity,
@@ -65,7 +68,7 @@ def main() -> None:
65
68
  print(f"{disp.shape=}")
66
69
 
67
70
 
68
- pyv.ImageDef2D.deform_images_to_disk(cam_data,
71
+ sens.ImageDef2D.deform_images_to_disk(cam_data,
69
72
  upsampled_image,
70
73
  coords,
71
74
  connectivity,
@@ -0,0 +1,65 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ """
8
+ Creating a configuration file
9
+ ================================================================================
10
+
11
+ In this example we generate a json config file which help mooseherder find the
12
+ paths to moose apps we want to use in the future.
13
+
14
+
15
+ **Installing moose**: To run future examples you will need to have moose
16
+ on your system. As moose supports unix operating systems windows users will need
17
+ to use windows subsystem for linux (WSL). We use the proteus moose build which
18
+ can be found here: https://github.com/aurora-multiphysics/proteus. Build scripts
19
+ for common linux distributions can be found in the 'scripts' directory of the
20
+ repo. You can also create your own moose build using instructions here:
21
+ https://mooseframework.inl.gov/.
22
+
23
+ We start by importing what we need for this example.
24
+ """
25
+
26
+ #%%#
27
+ # We start with imports for paths and for our moose configuration object.
28
+ from pathlib import Path
29
+
30
+ # Pyvale imports
31
+ from pyvale.mooseherder import MooseConfig
32
+
33
+ #%%
34
+ # A moose configuration is a dictionary with these three keys "main_path",
35
+ # "app_path" and "app_name". The first two keys retur resolved paths for moose
36
+ # and the app you are using. The last key returns the string used call your
37
+ # moose app on the command line. Once we have this dictionary we can build our
38
+ # moose config object which will perform some checks for us to see if the
39
+ # configuration is valid.
40
+ config = {'main_path': Path.home()/ 'moose',
41
+ 'app_path': Path.home() / 'proteus',
42
+ 'app_name': 'proteus-opt'}
43
+
44
+ moose_config = MooseConfig(config)
45
+
46
+ #%%
47
+ # We are going to save our moose configuration to the default output path for
48
+ # pyvale so if this default output path does not exist we create it. Then all we
49
+ # need to do is call the save configuration method and give it a path and file
50
+ # name for the json we want to save.
51
+ output_path = Path.cwd() / "pyvale-output"
52
+ if not output_path.is_dir():
53
+ output_path.mkdir(parents=True, exist_ok=True)
54
+
55
+ config_path = Path.cwd() / 'moose-config.json'
56
+ moose_config.save_config(config_path)
57
+
58
+ #%%
59
+ # Now we have our moose configuration we can use it to run moose with
60
+ # mooseherder's mooserunner and mooseherd classes which we will see in later
61
+ # examples. For now we will move on to demonstrate how mooseherder modifies
62
+ # input files for gmsh and moose.
63
+
64
+
65
+
@@ -0,0 +1,71 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ """
8
+ Modifying moose input files
9
+ ================================================================================
10
+
11
+ In this example we will use mooseherder's input modifier to programmatically
12
+ change variables in a moose .i input script.
13
+
14
+ We start by importing the packages we need for this example.
15
+ """
16
+
17
+ from pathlib import Path
18
+
19
+ # Pyvale imports
20
+ import pyvale.dataset as dataset
21
+ from pyvale.mooseherder import InputModifier
22
+
23
+ #%%
24
+ # We use the input file for a simple thermo-mechanical cube with higher order
25
+ # quads. We pass this to our input modifier specifying the moose comment
26
+ # character(s) as '#' and moose input files do not have a line end character so
27
+ # we pass an empty string. In the next example we will modify a gmsh script
28
+ # where we will need to specify a line ending character.
29
+ moose_input = dataset.element_case_input_path(dataset.EElemTest.HEX20)
30
+ moose_mod = InputModifier(moose_input, comment_chars="#", end_chars="")
31
+
32
+ #%%
33
+ # Note that the input modifier class only looks for variables between specified
34
+ # sentinel characters in comment lines which starts with '_*' and ends with '**'
35
+ # . An example of what variable block can be found in the moose input file.
36
+ #
37
+ # We then print the variables found in the moose input file to the console which
38
+ # are returned to us as a dictionary keyed by the variables string name in the
39
+ # file:
40
+ print(moose_mod.get_vars())
41
+ print()
42
+
43
+ #%%
44
+ # We can update variables using the input modifier, we just need to create a
45
+ # dictionary keyed by the variable name we want to change and the value we want
46
+ # the variable to take. If the variable does not exist in the input file then an
47
+ # error will be raised. Here we will change the number of elements in 'x' and
48
+ # the elastic modulus.
49
+ new_vars = {"nElemX": 4, "EMod": 3.3e9}
50
+ moose_mod.update_vars(new_vars)
51
+
52
+
53
+ #%%
54
+ # Let's check that the variables in the dictionary have been updated to match
55
+ # what we have changed:
56
+ print(moose_mod.get_vars())
57
+ print()
58
+
59
+ #%%
60
+ # Now we want to save the modified input file so we first create the standard
61
+ # pyvale-output directory if it does not exist. Then we write the file to that
62
+ # directory with suitable file name. Have a look at the file in the
63
+ # pyvale-output directory to verify the variables have been changed.
64
+
65
+ output_path = Path.cwd() / "pyvale-output"
66
+ if not output_path.is_dir():
67
+ output_path.mkdir(parents=True, exist_ok=True)
68
+
69
+ moose_save = output_path/"moose-mod-vars.i"
70
+ moose_mod.write_file(moose_save)
71
+
@@ -0,0 +1,69 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ """
8
+ Modifying gmsh input files
9
+ ================================================================================
10
+
11
+ In this example we will use mooseherder's input modifier to programmatically
12
+ change variables in a gmsh .geo script.
13
+
14
+ We start by importing the packages we need for this example.
15
+ """
16
+
17
+ from pathlib import Path
18
+
19
+ # Pyvale imports
20
+ import pyvale.dataset as dataset
21
+ from pyvale.mooseherder import InputModifier
22
+
23
+ #%%
24
+ # We are going to use a gmsh geo file that is for a 2D rectangular plate with a
25
+ # hole in the center which we retrieve from pyvale's simulation library. We then
26
+ # use this to create an input modifier which has the correct comment string '//'
27
+ # for gmsh and the required line terminator ";".
28
+ gmsh_input = dataset.sim_case_gmsh_file_path(case_num=17)
29
+ gmsh_mod = InputModifier(gmsh_input, "//", ";")
30
+
31
+ #%%
32
+ # Note that the input modifier class only looks for variables between specified
33
+ # sentinel characters in comment lines which starts with '_*' and ends with '**'
34
+ # . An example variable block can be found in the gmsh input file.
35
+ #
36
+ # We then print the variables found in the gmsh input file to the console which
37
+ # are returned to us as a dictionary keyed by the variables string name in the
38
+ # file:
39
+ print(gmsh_mod.get_vars())
40
+ print()
41
+
42
+ #%%
43
+ # We can update the variables in the input modifier using a dictionary keyed by
44
+ # the variable names we want to change and the values being what we want to
45
+ # change them to. We do not have to use numeric values for these we can use
46
+ # expressions in strings.
47
+ new_vars = {"plate_width": 150e-3, "plate_height": "plate_width + 100e-3"}
48
+ gmsh_mod.update_vars(new_vars)
49
+
50
+ #%%
51
+ # Now we print the variables that are currently in the input modifier to check
52
+ # our modification worked.
53
+ print(gmsh_mod.get_vars())
54
+ print()
55
+
56
+ #%%
57
+ # Finally we want to save the modified input file to disk so we can run it with
58
+ # gmsh. First we create the standard pyvale-output directory so we can save the
59
+ # file there. Then we save the gmsh input file to the directory with a suitable
60
+ # name. Have a look at the file in the directory to ensure our modifications
61
+ # have worked.
62
+
63
+ output_path = Path.cwd() / "pyvale-output"
64
+ if not output_path.is_dir():
65
+ output_path.mkdir(parents=True, exist_ok=True)
66
+
67
+ gmsh_save = output_path/"gmsh-mod-vars.geo"
68
+ gmsh_mod.write_file(gmsh_save)
69
+
@@ -0,0 +1,80 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ """
8
+ Running MOOSE once
9
+ ================================================================================
10
+
11
+ In this example we will run a single moose simulation from a moose input .i file
12
+ using a 'runner' object.
13
+
14
+ **Installing moose**: To run this example you will need to have installed moose
15
+ on your system. As moose supports unix operating systems windows users will need
16
+ to use windows subsystem for linux (WSL). We use the proteus moose build which
17
+ can be found here: https://github.com/aurora-multiphysics/proteus. Build scripts
18
+ for common linux distributions can be found in the 'scripts' directory of the
19
+ repo. You can also create your own moose build using instructions here:
20
+ https://mooseframework.inl.gov/.
21
+
22
+ We start by importing what we need for this example.
23
+ """
24
+
25
+ import time
26
+ from pathlib import Path
27
+
28
+ #pyvale imports
29
+ import pyvale.dataset as dataset
30
+ from pyvale.mooseherder import (MooseConfig,
31
+ MooseRunner)
32
+
33
+
34
+ #%%
35
+ # First we build our moose configuration which gives the location of our main
36
+ # moose build, our moose app and the name of the app to use when called on the
37
+ # command line.
38
+ config = {'main_path': Path.home()/ 'moose',
39
+ 'app_path': Path.home() / 'proteus',
40
+ 'app_name': 'proteus-opt'}
41
+ moose_config = MooseConfig(config)
42
+
43
+ #%%
44
+ # We can now build a runner object using our configuration. We can then set some
45
+ # options for the run including parallelisation and if we should redirect
46
+ # terminal output to file. For smaller simulations we are better off using
47
+ # threads for paralleisation as they reduce overhead compared to MPI tasks.
48
+ moose_runner = MooseRunner(moose_config)
49
+
50
+ moose_runner.set_run_opts(n_tasks = 1,
51
+ n_threads = 8,
52
+ redirect_out = False)
53
+
54
+ #%%
55
+ # Let's grab a simple thermo-mechanical cube test case from pyvale's moose
56
+ # simulation library and we will set this as the input file to run with our
57
+ # 'runner'.
58
+ moose_input = dataset.element_case_input_path(dataset.EElemTest.HEX20)
59
+ moose_runner.set_input_file(moose_input)
60
+
61
+ #%%
62
+ # Our moose runner will pass a list of strings which form the command line to
63
+ # run our moose simulation. We print the list of command line arguments here so
64
+ # we can check we are correctly calling our input file with the run options we
65
+ # want.
66
+ print(moose_runner.get_arg_list())
67
+ print()
68
+
69
+ #%%
70
+ # To run our moose simulation we just need to call 'run', here we will time our
71
+ # moose run and then print the solve time to the terminal
72
+ start_time = time.perf_counter()
73
+ moose_runner.run()
74
+ run_time = time.perf_counter() - start_time
75
+
76
+ print()
77
+ print("-"*80)
78
+ print(f'MOOSE run time = {run_time:.3f} seconds')
79
+ print("-"*80)
80
+ print()
@@ -0,0 +1,64 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ """
8
+ Running Gmsh once
9
+ ================================================================================
10
+
11
+ In this example we will run a gmsh script to generate a mesh file using the
12
+ GmshRunner class.
13
+
14
+ **Installing gmsh**: For this example you will need to have a gmsh executable
15
+ which can be downloaded and installed from here: https://gmsh.info/#Download
16
+
17
+ We start by importing what we need for this example.
18
+ """
19
+
20
+ import time
21
+ from pathlib import Path
22
+
23
+ #pyvale imports
24
+ import pyvale.dataset as dataset
25
+ from pyvale.mooseherder import GmshRunner
26
+
27
+ #%%
28
+ # First we need to create a 'runner' for gmsh which needs to know the path to
29
+ # the gmsh executable. You will need to replace this path with the path to where
30
+ # you have install gmsh on your system.
31
+ gmsh_path = Path.home() / 'gmsh/bin/gmsh'
32
+ gmsh_runner = GmshRunner(gmsh_path)
33
+
34
+ #%%
35
+ # Next we grab a gmsh file from pyvale simulation library and we set this as the
36
+ # input file for our runner.
37
+ gmsh_input = dataset.sim_case_gmsh_file_path(case_num=17)
38
+ gmsh_runner.set_input_file(gmsh_input)
39
+
40
+ #%%
41
+ # Now we can run gmsh to generate our mesh using the run method, the parse only
42
+ # flag means we will run gmsh head less and not open the gmsh GUI but terminal
43
+ # output will still be written to stdout.
44
+ #
45
+ # We also use our performance timer to time how long our mesh generation takes
46
+ # and then we print this to the console. Note that parallelisation options for
47
+ # gmsh can be controlled in the gmsh .geo script file.
48
+ start_time = time.perf_counter()
49
+ gmsh_runner.run(gmsh_input,parse_only=True)
50
+ run_time = time.perf_counter() - start_time
51
+
52
+ print()
53
+ print("-"*80)
54
+ print(f'Gmsh run time = {run_time :.3f} seconds')
55
+ print("-"*80)
56
+ print()
57
+
58
+ #%%
59
+ # The GmshRunner and the MooseRunner implement the SimRunner abstract base
60
+ # class. Later on when we will see that we can use this to run a list of
61
+ # different sim runners in order using MooseHerd workflow manager. This allows
62
+ # us to first build our mesh with gmsh and then run a moose simulation using
63
+ # that mesh. We can also implement our own SimRunner's to add additional pre or
64
+ # post processing steps to our simulation chain.
@@ -0,0 +1,114 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ """
8
+ Run Gmsh then MOOSE once
9
+ ================================================================================
10
+
11
+ In this example we use a gmsh runner followed by a moose runner to generate our
12
+ mesh and then run a moose simulation using this mesh. The moose input file needs
13
+ to know the name of the gmsh .msh file which is specified in the gmsh .geo
14
+ script when the Save command is called. It is possible to use the input
15
+ modifiers we have seen previously to update this file name as a variable in the
16
+ moose input script but for this example we have set things manually inside the
17
+ moose input script.
18
+
19
+ **Installing moose**: To run this example you will need to have installed moose
20
+ on your system. As moose supports unix operating systems windows users will need
21
+ to use windows subsystem for linux (WSL). We use the proteus moose build which
22
+ can be found here: https://github.com/aurora-multiphysics/proteus. Build scripts
23
+ for common linux distributions can be found in the 'scripts' directory of the
24
+ repo. You can also create your own moose build using instructions here:
25
+ https://mooseframework.inl.gov/.
26
+
27
+ **Installing gmsh**: For this example you will need to have a gmsh executable
28
+ which can be downloaded and installed from here: https://gmsh.info/#Download
29
+
30
+ We start by importing what we need for this example.
31
+ """
32
+
33
+ import time
34
+ import shutil
35
+ from pathlib import Path
36
+
37
+ #pyvale imports
38
+ import pyvale.dataset as dataset
39
+ from pyvale.mooseherder import (MooseConfig,
40
+ GmshRunner,
41
+ MooseRunner)
42
+
43
+ #%%
44
+ # We need to make sure the output .msh file from gmsh can be found by our moose
45
+ # input script so we are going to put them in our standard pyvale-output
46
+ # directory in our current working directory. First we grab the paths for the
47
+ # .geo and .i and then we copy them to the pyvale-output directory where we will
48
+ # run our simulation from. We then print the paths to we can see where the files
49
+ # are - try opening them with your text editor of choice so you can see how the
50
+ # name of the mesh is specified in the gmsh .geo as the .msh output and the then
51
+ # how the name is matched in the moose .i to read the .msh to run the sim.
52
+
53
+ output_path = Path.cwd() / "pyvale-output"
54
+ if not output_path.is_dir():
55
+ output_path.mkdir(parents=True, exist_ok=True)
56
+
57
+ gmsh_file = dataset.sim_case_gmsh_file_path(case_num=17)
58
+ gmsh_input = output_path / gmsh_file.name
59
+
60
+ moose_file = dataset.sim_case_input_file_path(case_num=17)
61
+ moose_input = output_path / moose_file.name
62
+
63
+ shutil.copyfile(moose_file,moose_input)
64
+ shutil.copyfile(gmsh_file,gmsh_input)
65
+
66
+ print(f"\n{moose_input.resolve()=}")
67
+ print(f"{gmsh_input.resolve()=}\n")
68
+
69
+ #%%
70
+ # We need to run gmsh first to generate our .msh file so we set it up and run it
71
+ # in exactly the same way as we have done in the previous example. We pass the
72
+ # path to the gmsh executable to our runner. We then set our input file and call
73
+ # run to generate the mesh.
74
+ gmsh_path = Path.home() / 'gmsh/bin/gmsh'
75
+ gmsh_runner = GmshRunner(gmsh_path)
76
+
77
+ gmsh_runner.set_input_file(gmsh_input)
78
+
79
+ gmsh_start = time.perf_counter()
80
+ gmsh_runner.run(parse_only=True)
81
+ gmsh_run_time = time.perf_counter()-gmsh_start
82
+
83
+ #%%
84
+ # Now that we have our mesh we can run our moose simulation. We will setup and
85
+ # run moose in exactly the same was as in a previous example. First, we setup
86
+ # our moose configuration and pass this to our runner. We then set our run /
87
+ # parallelisation options before calling run to extecute the simulation.
88
+ config = {'main_path': Path.home()/ 'moose',
89
+ 'app_path': Path.home() / 'proteus',
90
+ 'app_name': 'proteus-opt'}
91
+ moose_config = MooseConfig(config)
92
+
93
+ moose_runner = MooseRunner(moose_config)
94
+
95
+ moose_runner.set_run_opts(n_tasks = 1,
96
+ n_threads = 4,
97
+ redirect_out = True)
98
+
99
+ moose_runner.set_input_file(moose_input)
100
+
101
+ moose_start = time.perf_counter()
102
+ moose_runner.run()
103
+ moose_run_time = time.perf_counter() - moose_start
104
+
105
+ #%%
106
+ # Finally we print the execution times of both runners and print these to the
107
+ # console.
108
+ print("-"*80)
109
+ print(f'Gmsh run time = {gmsh_run_time:.2f} seconds')
110
+ print(f'MOOOSE run time = {moose_run_time:.2f} seconds')
111
+ print("-"*80)
112
+ print()
113
+
114
+
@@ -0,0 +1,157 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ """
8
+ Running a parameter sweep of a MOOSE simulation
9
+ ================================================================================
10
+
11
+ In this example we will perform a parameter sweep of a moose simulation showing
12
+ the capability of the 'herder' workflow manager which can be passed a list of
13
+ 'input modifiers' and 'runners'. The 'herder' will then use the 'input
14
+ modifiers' to update simulation parameters and then call the respective 'runner'
15
+ using the modified input file. In this example we will also see that the
16
+ 'herder' can be used to execute a parameter sweep sequentially or in parallel.
17
+
18
+ **Installing moose**: To run this example you will need to have installed moose
19
+ on your system. As moose supports unix operating systems windows users will need
20
+ to use windows subsystem for linux (WSL). We use the proteus moose build which
21
+ can be found here: https://github.com/aurora-multiphysics/proteus. Build scripts
22
+ for common linux distributions can be found in the 'scripts' directory of the
23
+ repo. You can also create your own moose build using instructions here:
24
+ https://mooseframework.inl.gov/.
25
+
26
+ We start by importing what we need for this example.
27
+ """
28
+
29
+ from pathlib import Path
30
+ import numpy as np
31
+
32
+ #pyvale imports
33
+ import pyvale.dataset as dataset
34
+ from pyvale.mooseherder import (MooseHerd,
35
+ MooseRunner,
36
+ InputModifier,
37
+ DirectoryManager,
38
+ MooseConfig,
39
+ sweep_param_grid)
40
+
41
+ #%%
42
+ # First we are going to setup an input modifier and a runner for our moose
43
+ # simulation. Here we need to make sure that when we set our moose
44
+ # parallelisation options we leave enough threads for all the simulations that
45
+ # are running at once base on our CPU. It is also helpful to redirect stdout to
46
+ # file so that our terminal does not become a mess when we start running our
47
+ # simulations in parallel.
48
+ moose_input = dataset.element_case_input_path(dataset.EElemTest.HEX20)
49
+ moose_modifier = InputModifier(moose_input,'#','')
50
+
51
+ config = {'main_path': Path.home()/ 'moose',
52
+ 'app_path': Path.home() / 'proteus',
53
+ 'app_name': 'proteus-opt'}
54
+ moose_config = MooseConfig(config)
55
+
56
+ moose_runner = MooseRunner(moose_config)
57
+ moose_runner.set_run_opts(n_tasks = 1,
58
+ n_threads = 2,
59
+ redirect_out = True)
60
+
61
+ #%%
62
+ # Now we are going to create a directory manager which will be used to make sure
63
+ # our simulations are run in separate directories. We then create our herd
64
+ # workflow manager with our list of runners and corresponding input modifiers.
65
+ # In our case we are only running moose so our lists have a single item. The
66
+ # last thing we do is specify the number of simulations we want to run in
67
+ # parallel, for this case we match the number of directories.
68
+ num_para_sims: int = 4
69
+ dir_manager = DirectoryManager(n_dirs=num_para_sims)
70
+ herd = MooseHerd([moose_runner],[moose_modifier],dir_manager)
71
+ herd.set_num_para_sims(n_para=num_para_sims)
72
+
73
+ #%%
74
+ # We need somewhere to run our simulations and store the output so we create our
75
+ # standard pyvale output directory and then we set this as the base directory
76
+ # for our directory manager. We clear any old output directories and then create
77
+ # new ones ready to write our simulation output to.
78
+ output_path = Path.cwd() / "pyvale-output"
79
+ if not output_path.is_dir():
80
+ output_path.mkdir(parents=True, exist_ok=True)
81
+
82
+ dir_manager.set_base_dir(output_path)
83
+ dir_manager.reset_dirs()
84
+
85
+ #%%
86
+ # We now need to generate the parameter combinations we want to run using our
87
+ # 'herd'. This is given as a list of list of dictionaries where the outer list
88
+ # corresponds to the unique simulation chain, the inner list corresponds to each
89
+ # simulation runner in the chain, and the dicitionary contains key value pairs
90
+ # where the keys are the variables names to edit in the input file. For this
91
+ # case we only have moose in our simulation chain so our inner list will only
92
+ # have a length of one but in the next example we will see how we can combine
93
+ # a parameter sweep with gmsh->moose sweeping all possible combinations of
94
+ # variables for both simulation tools.
95
+ #
96
+ # For now we are going to use a helper function from mooseherder which will
97
+ # generate all possible combination for us in the correct data format. We just
98
+ # provide a dictionary of lists of unique parameters we want to analyse. Finally
99
+ # we print the unique combinations of parameters to the terminal as well as the
100
+ # total number of simulations to check everything is working as expected.
101
+
102
+ moose_params = {"nElemX": (2,3,4),
103
+ "lengX": np.array([10e-3,15e-3]),
104
+ "PRatio":(0.3,)}
105
+ params = [moose_params,]
106
+ sweep_params = sweep_param_grid(params)
107
+
108
+ print("\nParameter sweep variables by simulation:")
109
+ for ii,pp in enumerate(sweep_params):
110
+ print(f"Sim: {ii}, Params [moose,]: {pp}")
111
+
112
+ print()
113
+ print(f"Total simulations = {len(sweep_params)}")
114
+ print()
115
+
116
+ #%%
117
+ # The run once function of the herd allows us to run a particular single
118
+ # simulation chain from anywhere in the sweep. This is useful for debugging when
119
+ # you want to rerun a single case to see the output or what went wrong. The herd
120
+ # also stores the solution time for each single iteration so we will store this
121
+ # to estimate how long the whole sweep should take when solving sequentially.
122
+ herd.run_once(0,sweep_params[0])
123
+ time_run_once = herd.get_iter_time()
124
+
125
+
126
+ #%%
127
+ # We can run the whole parameter sweep sequentially (one by one) using the run
128
+ # sequential function of the herd. We also store the total solution time
129
+ # for all simulation chains so that we can compare to a parallel run later. Note
130
+ # that it can be beneficial to run sequentially if you are using the herd within
131
+ # another loop or if one of the steps in your simulation chain is expensive and
132
+ # that step needs the computational resource.
133
+ herd.run_sequential(sweep_params)
134
+ time_run_seq = herd.get_sweep_time()
135
+
136
+ #%%
137
+ # Finally, we can run our parameter sweep in parallel. We need a main guard here
138
+ # as we use the multi-processing package. We also store the sweep time for this
139
+ # case to compare our sequential to parallel run time.
140
+ if __name__ == "__main__":
141
+ herd.run_para(sweep_params)
142
+ time_run_para = herd.get_sweep_time()
143
+
144
+ #%%
145
+ # Now that we have run all cases we can compare run times for a single
146
+ # simulation multiplied by the total number of simulations against runnning the
147
+ # sweep in parallel
148
+ print("-"*80)
149
+ print(f'Run time (one iter) = {time_run_once:.3f} seconds')
150
+ print(f'Est. time (one iter x num sims) = {(time_run_once*len(sweep_params)):.3f} seconds')
151
+ print()
152
+ print(f'Run time (seq) = {time_run_seq:.3f} seconds')
153
+ print(f'Run time (para) = {time_run_para:.3f} seconds')
154
+ print("-"*80)
155
+ print()
156
+
157
+