Tutorial 06: Include Files#
References#
Adding to PYTHONPATH with Python sys [40]
Environment#
SCons and WAVES can be installed in a Conda environment with the Conda package manager. See the Conda installation and Conda environment management documentation for more details about using Conda.
Note
The SALib and numpy versions may not need to be this strict for most tutorials. However, Tutorial: Sensitivity Study uncovered some undocumented SALib version sensitivity to numpy surrounding the numpy v2 rollout.
Create the tutorials environment if it doesn’t exist
$ conda create --name waves-tutorial-env --channel conda-forge waves 'scons>=4.6' matplotlib pandas pyyaml xarray seaborn 'numpy>=2' 'salib>=1.5.1' pytest
Activate the environment
$ conda activate waves-tutorial-env
Some tutorials require additional third-party software that is not available for the Conda package manager. This
software must be installed separately and either made available to SConstruct by modifying your system’s PATH
or by
modifying the SConstruct search paths provided to the waves.scons_extensions.add_program()
method.
Warning
STOP! Before continuing, check that the documentation version matches your installed package version.
You can find the documentation version in the upper-left corner of the webpage.
You can find the installed WAVES version with
waves --version
.
If they don’t match, you can launch identically matched documentation with the WAVES Command-Line Utility
docs subcommand as waves docs
.
Directory Structure#
Create and change to a new project root directory to house the tutorial files if you have not already done so. For example
$ mkdir -p ~/waves-tutorials
$ cd ~/waves-tutorials
$ pwd
/home/roppenheimer/waves-tutorials
Note
If you skipped any of the previous tutorials, run the following commands to create a copy of the necessary tutorial files.
$ pwd
/home/roppenheimer/waves-tutorials
$ waves fetch --overwrite --tutorial 5 && mv tutorial_05_parameter_substitution_SConstruct SConstruct
WAVES fetch
Destination directory: '/home/roppenheimer/waves-tutorials'
Download and copy the
tutorial_05_parameter_substitution
file to a new file namedtutorial_06_include_files
with the WAVES Command-Line Utility fetch subcommand.
$ pwd
/home/roppenheimer/waves-tutorials
$ waves fetch --overwrite tutorials/tutorial_05_parameter_substitution && cp tutorial_05_parameter_substitution tutorial_06_include_files
WAVES fetch
Destination directory: '/home/roppenheimer/waves-tutorials'
Create a new directory in
modsim_package/python
in thewaves-tutorials
directory.
$ pwd
/home/roppenheimer/waves-tutorials
$ mkdir -p modsim_package/python
Python Parameter File#
In this tutorial, we will update the code from Tutorial 05: Parameter Substitution to use an included parameter
file instead of hardcoding the parameter definitions in the SConscript
file. This technique will allow parameter
reuse between simulations.
Create a new file
modsim_package/python/rectangle_compression_nominal.py
from the content below.
waves-tutorials/modsim_package/python/rectangle_compression_nominal.py
"""Parameter sets and schemas for the rectangle compression simulation"""
def parameter_schema(
width=1.0,
height=1.0,
global_seed=1.0,
displacement=-0.01,
):
"""Return nominal simulation variables dictionary
:param float width: The rectangle width
:param float height: The rectangle height
:param float global_seed: The global mesh seed size
:param float displacement: The rectangle top surface displacement
:returns: nominal simulation variables
:rtype: dict
"""
simulation_variables = {
"width": width,
"height": height,
"global_seed": global_seed,
"displacement": displacement,
}
return simulation_variables
The file you just created is similar to the code snippet in your tutorial_05_parameter_substitution
file that
defines the parameter key-value pairs. Here we have added a function to make documentation of the default values easier,
as shown in the WAVES-TUTORIAL API for rectangle_compression_nominal.py.
Create Python module initialization files to create a project specific local Python package.
waves-tutorials/modsim_package/python/__init__.py
$ pwd
/home/roppenheimer/waves-tutorials
$ waves fetch tutorials/modsim_package/python/__init__.py --destination modsim_package/python
$ find . -name "__init__.py"
./waves-tutorials/modsim_package/abaqus/__init__.py
./waves-tutorials/modsim_package/python/__init__.py
./waves-tutorials/modsim_package/__init__.py
The __init__.py
files tell Python what directories to treat as a package or module. They need to exist, but do not
need any content. You can read more about Python Modules in the Python documentation.
SConscript#
Use the
diff
below to make the following modifications to yourtutorial_06_include_files
file:Import
rectangle_compression_nominal
from themodsim_package.python
moduleRemove the
simulation_variables
dictionary that was created in Tutorial 05: Parameter Substitution’s codeDefine
simulation_variables
using the newly importedrectangle_compression_nominal
module
A diff
against the SConscript
file from Tutorial 05: Parameter Substitution is included below to help
identify the changes made in this tutorial.
waves-tutorials/tutorial_06_include_files
--- /home/runner/work/waves/waves/build/docs/tutorials_tutorial_05_parameter_substitution
+++ /home/runner/work/waves/waves/build/docs/tutorials_tutorial_06_include_files
@@ -11,6 +11,8 @@
import pathlib
+from modsim_package.python import rectangle_compression_nominal
+
# Inherit the parent construction environment
Import("env")
@@ -19,12 +21,7 @@
# Simulation variables
build_directory = pathlib.Path(Dir(".").abspath)
workflow_name = build_directory.name
-simulation_variables = {
- "width": 1.0,
- "height": 1.0,
- "global_seed": 1.0,
- "displacement": -0.01,
-}
+simulation_variables = rectangle_compression_nominal.parameter_schema()
# Comment used in tutorial code snippets: marker-1
The first change to be made is importing the rectangle_compression_nominal
module from the
modsim_package.python
module you created in the Python Parameter File section of
this tutorial. This import statement will import all variables within the rectangle_compression_nominal.py
file
and make them available in the SConscript
file’s name space. See the Python Modules documentation for more
information about importing modules. You can access those variables with the following syntax:
rectangle_compression_nominal.simulation_variables
The second change removes the code that defines simulation_variables
that remained from
Tutorial 05: Parameter Substitution’s code.
The final change made in the tutorial_06_include_files
file is to re-define the simulation_variables
from the rectangle_compression_nominal
module. The end result at this point in the code is the same between
this tutorial and Tutorial 05: Parameter Substitution. However, now we import variables from a separate file,
list that file as a source dependency of the parameterized targets, and allow ourselves the ability to change parameters
without modification to the SConscript
file.
SConstruct#
Use the
diff
below to modify yourwaves-tutorials/SConstruct
file in the following ways:Add the
waves-tutorials
directory to your PYTHONPATH to make themodsim_package
- and thus the modules within it - importableAdd
tutorial_06_include_files
to theworkflow_configurations
list
A diff
against the SConstruct
file from Tutorial 05: Parameter Substitution is included below to help identify the
changes made in this tutorial.
waves-tutorials/SConstruct
--- /home/runner/work/waves/waves/build/docs/tutorials_tutorial_05_parameter_substitution_SConstruct
+++ /home/runner/work/waves/waves/build/docs/tutorials_tutorial_06_include_files_SConstruct
@@ -1,6 +1,7 @@
#! /usr/bin/env python
import os
+import sys
import pathlib
import waves
@@ -84,7 +85,8 @@
for key, value in project_variables.items():
env[key] = value
-# Make the project package importable for Python and Abaqus Python environments
+# Make the project package importable for: (1) SConscript files and (2) Python and Abaqus Python environments
+sys.path.insert(0, str(project_dir))
env.PrependENVPath("PYTHONPATH", project_dir)
# Comments used in tutorial code snippets: marker-5
@@ -101,6 +103,7 @@
"tutorial_03_solverprep",
"tutorial_04_simulation",
"tutorial_05_parameter_substitution",
+ "tutorial_06_include_files",
]
for workflow in workflow_configurations:
build_dir = env["variant_dir_base"] / workflow
The first change you made allows for us to import modules from the modsim_package
package. This step is neccessary to
be able to import the modsim_package.python
module in the tutorial_06_include_files
file.
The last change to be made is adding tutorial_06_include_files
to the workflow_configurations
list. This
process should be quite familiar by now.
Build Targets#
Build the new targets
$ pwd
/home/roppenheimer/waves-tutorials
$ scons tutorial_06_include_files
scons: Reading SConscript files ...
Checking whether /apps/abaqus/Commands/abq2024 program exists.../apps/abaqus/Commands/abq2024
Checking whether abq2024 program exists.../apps/abaqus/Commands/abq2024
scons: done reading SConscript files.
scons: Building targets ...
cd /home/roppenheimer/waves-tutorials/build/tutorial_06_include_files && /apps/abaqus/Commands/abq2024 cae -noGui /home/roppenheimer/waves-tutorials/modsim_package/abaqus/rectangle_geometry.py -- --width 1.0 --height 1.0 > rectangle_geometry.stdout 2>&1
cd /home/roppenheimer/waves-tutorials/build/tutorial_06_include_files && /apps/abaqus/Commands/abq2024 cae -noGui /home/roppenheimer/waves-tutorials/modsim_package/abaqus/rectangle_partition.py -- --width 1.0 --height 1.0 > rectangle_partition.stdout 2>&1
cd /home/roppenheimer/waves-tutorials/build/tutorial_06_include_files && /apps/abaqus/Commands/abq2024 cae -noGui /home/roppenheimer/waves-tutorials/modsim_package/abaqus/rectangle_mesh.py -- --global-seed 1.0 > rectangle_mesh.stdout 2>&1
Copy("build/tutorial_06_include_files/rectangle_compression.inp.in", "modsim_package/abaqus/rectangle_compression.inp.in")
Creating 'build/tutorial_06_include_files/rectangle_compression.inp'
Copy("build/tutorial_06_include_files/assembly.inp", "modsim_package/abaqus/assembly.inp")
Copy("build/tutorial_06_include_files/boundary.inp", "modsim_package/abaqus/boundary.inp")
Copy("build/tutorial_06_include_files/field_output.inp", "modsim_package/abaqus/field_output.inp")
Copy("build/tutorial_06_include_files/materials.inp", "modsim_package/abaqus/materials.inp")
Copy("build/tutorial_06_include_files/parts.inp", "modsim_package/abaqus/parts.inp")
Copy("build/tutorial_06_include_files/history_output.inp", "modsim_package/abaqus/history_output.inp")
cd /home/roppenheimer/waves-tutorials/build/tutorial_06_include_files && /apps/abaqus/Commands/abq2024 -job rectangle_compression -input rectangle_compression -double both -interactive -ask_delete no > rectangle_compression.stdout 2>&1
scons: done building targets.
Output Files#
Explore the contents of the build
directory using the tree
command against the build
directory, as shown
below. Note the usage of the -I
to reduce clutter in the tree
command output.
$ pwd
/home/roppenheimer/waves-tutorials
$ tree build/tutorial_06_include_files/
build/tutorial_06_include_files/
|-- abaqus.rpy
|-- abaqus.rpy.1
|-- abaqus.rpy.2
|-- assembly.inp
|-- boundary.inp
|-- field_output.inp
|-- history_output.inp
|-- materials.inp
|-- parts.inp
|-- rectangle_compression.com
|-- rectangle_compression.dat
|-- rectangle_compression.inp
|-- rectangle_compression.inp.in
|-- rectangle_compression.msg
|-- rectangle_compression.odb
|-- rectangle_compression.prt
|-- rectangle_compression.sta
|-- rectangle_compression.stdout
|-- rectangle_geometry.cae
|-- rectangle_geometry.jnl
|-- rectangle_geometry.stdout
|-- rectangle_mesh.cae
|-- rectangle_mesh.inp
|-- rectangle_mesh.jnl
|-- rectangle_mesh.stdout
|-- rectangle_partition.cae
|-- rectangle_partition.jnl
`-- rectangle_partition.stdout
0 directories, 28 files
The output files for this tutorial are exactly the same as those from Tutorial 05: Parameter Substitution. As
was mentioned when modifying the SConscript file, the use of an included Python file
to define our parameters provides the same result as when we hard-code the parameters into the SConscript
file. It
is also worth noting that the modsim_package/python/rectangle_compression_nominal.py
file did not get copied to
the build directory. Instead, we added the modsim_package
directory to PYTHONPATH. This way we can import the
rectangle_compression_nominal
module from its source location and remove any need to duplicate source code by
copying files from place to place.
Workflow Visualization#
View the workflow directed graph by running the following command and opening the image in your preferred image viewer.
$ pwd
/home/roppenheimer/waves-tutorials
$ waves visualize tutorial_06_include_files --output-file tutorial_06_include_files.png --width=28 --height=6 --exclude-list /usr/bin .stdout .jnl .prt .com
The output should look similar to the figure below.

Note that the directed graph has not grown larger than the one shown in Tutorial 05: Parameter Substitution.
While we have added a new parameter file, the dependence is implicitly captured in the simulation variable values passed
to the subsitution dictionary. If the values in the parameter file change, the substituted
rectangle_compression.inp
file contents will also change. So while the parameter file is not explicitly
included in the directed graph, the contents of the rectangle_compression.inp
file will still correctly prompt
re-builds when the parameter file changes.