Skip to main content
`Ctrl`+`K`

# Tutorial 06: Include Files

## References

- Adding to PYTHONPATH with Python sys [45]

- Python Modules [45]

## 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.

1. Create the tutorials environment if it doesn’t exist

   Linux/MacOS

       $ 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

   Windows

       PS > conda create --name waves-tutorial-env --channel conda-forge waves scons matplotlib pandas pyyaml xarray seaborn numpy salib pytest

2. Activate the environment

   Linux/MacOS

       $ conda activate waves-tutorial-env

   Windows

       PS > 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.

1. You can find the documentation version in the upper-left corner of the webpage.

2. 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

3. Create and change to a new project root directory to house the tutorial files if you have not already done so. For example

Linux/MacOS

    $ mkdir -p ~/waves-tutorials
    $ cd ~/waves-tutorials
    $ pwd
    /home/roppenheimer/waves-tutorials

Windows

    PS > New-Item $HOME\waves-tutorials -ItemType "Directory"
    PS > Set-Location $HOME\waves-tutorials
    PS > Get-Location

    Path
    ----
    C:\Users\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.

Linux/MacOS

    $ 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'

Windows

    PS > Get-Location

    Path
    ----
    C:\Users\roppenheimer\waves-tutorials

    PS > waves fetch --overwrite --tutorial 5 && Move-Item tutorial_05_parameter_substitution_SConstruct SConstruct -Force
    WAVES fetch
    Destination directory: 'C:\Users\roppenheimer\waves-tutorials'

4. Download and copy the `tutorial_05_parameter_substitution` file to a new file named `tutorial_06_include_files` with the WAVES Command-Line Utility fetch subcommand.

Linux/MacOS

    $ 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'

Windows

    PS > Get-Location

    Path
    ----
    C:\Users\roppenheimer\waves-tutorials

    PS > waves fetch --overwrite tutorials\tutorial_05_parameter_substitution && Copy-Item tutorial_05_parameter_substitution tutorial_06_include_files
    WAVES fetch
    Destination directory: 'C:\Users\roppenheimer\waves-tutorials'

5. Create a new directory in `modsim_package/python` in the `waves-tutorials` directory.

Linux/MacOS

    $ pwd
    /home/roppenheimer/waves-tutorials
    $ mkdir -p modsim_package/python

Windows

    PS > Get-Location

    Path
    ----
    C:\Users\roppenheimer\waves-tutorials

    PS > New-Item modsim_package\python -Force -ItemType "Directory"

## 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.

6. 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.

7. Create Python module initialization files to create a project specific local Python package.

waves-tutorials/modsim_package/python/__init__.py

Linux/MacOS

    $ 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

Windows

    PS > Get-Location

    Path
    ----
    C:\Users\roppenheimer\waves-tutorials

    PS > waves fetch tutorials\modsim_package\python\__init__.py --destination modsim_package\python
    PS > Get-ChildItem -Path . -Recurse "__init__.py"

        Directory: C:\Users\roppenheimer\waves-tutorials\modsim_package

    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    -a---             6/9/2023 4:32 PM              0 __init__.py

        Directory: C:\Users\roppenheimer\waves-tutorials\modsim_package\abaqus

    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    -a---            6/9/2023  4:32 PM              0 __init__.py

        Directory: C:\Users\roppenheimer\waves-tutorials\modsim_package\python

    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    -a---            6/9/2023  4:32 PM              0 __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

8. Use the `diff` below to make the following modifications to your `tutorial_06_include_files` file:

   - Import `rectangle_compression_nominal` from the `modsim_package.python` module

   - Remove the `simulation_variables` dictionary that was created in Tutorial 05: Parameter Substitution’s code

   - Define `simulation_variables` using the newly imported `rectangle_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

9. Use the `diff` below to modify your `waves-tutorials/SConstruct` file in the following ways:

   - Add the `waves-tutorials` directory to your PYTHONPATH to make the `modsim_package` - and thus the modules within it - importable

   - Add `tutorial_06_include_files` to the `workflow_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

10. Build the new targets

Linux/MacOS

    $ 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 '/usr/projects/ea/abaqus/Commands/abq2024' program exists...no
    Checking whether 'abq2024' program exists.../apps/abaqus/Commands/abq2024
    Checking whether 'abaqus' program exists...no
    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.

Windows

    PS > Get-Location

    Path
    ----
    C:\Users\roppenheimer\waves-tutorials

    PS > scons tutorial_06_include_files
    scons: Reading SConscript files ...
    Checking whether '/apps/abaqus/Commands/abq2024' program exists...no
    Checking whether '/usr/projects/ea/abaqus/Commands/abq2024' program exists...no
    Checking whether 'abq2024' program exists...C:\SIMULIA\Commands\abq2024.BAT
    Checking whether 'abaqus' program exists...C:\SIMULIA\Commands\abaqus.BAT
    scons: done reading SConscript files.
    scons: Building targets ...
    cd C:\Users\roppenheimer\waves-tutorials\build\tutorial_06_include_files && C:\SIMULIA\Commands\abq2024.BAT cae -noGUI C:\Users\roppenheimer\waves-tutorials\modsim_package\abaqus\rectangle_geometry.py -- --width 1.0 --height 1.0 > C:\Users\roppenheimer\waves-tutorials\build\tutorial_06_include_files\rectangle_geometry.cae.stdout 2>&1
    cd C:\Users\roppenheimer\waves-tutorials\build\tutorial_06_include_files && C:\SIMULIA\Commands\abq2024.BAT cae -noGUI C:\Users\roppenheimer\waves-tutorials\modsim_package\abaqus\rectangle_partition.py -- --width 1.0 --height 1.0 > C:\Users\roppenheimer\waves-tutorials\build\tutorial_06_include_files\rectangle_partition.cae.stdout 2>&1
    cd C:\Users\roppenheimer\waves-tutorials\build\tutorial_06_include_files && C:\SIMULIA\Commands\abq2024.BAT cae -noGUI C:\Users\roppenheimer\waves-tutorials\modsim_package\abaqus\rectangle_mesh.py -- --global-seed 1.0 > C:\Users\roppenheimer\waves-tutorials\build\tutorial_06_include_files\rectangle_mesh.inp.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 C:\Users\roppenheimer\waves-tutorials\build\tutorial_06_include_files && C:\SIMULIA\Commands\abq2024.BAT -interactive -ask_delete no -job rectangle_compression -input rectangle_compression -double both > C:\Users\roppenheimer\waves-tutorials\build\tutorial_06_include_files\rectangle_compression.odb.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.

Linux/MacOS

    $ 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

Windows

    PS > Get-Location

       Path
       ----
       C:\Users\roppenheimer\waves-tutorials

    PS > tree build\tutorial_06_include_files /F
    C:\USERS\ROPPENHEIMER\WAVES-TUTORIALS\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.odb.stdout
        rectangle_compression.prt
        rectangle_compression.sta
        rectangle_geometry.cae
        rectangle_geometry.cae.stdout
        rectangle_geometry.jnl
        rectangle_mesh.cae
        rectangle_mesh.inp
        rectangle_mesh.inp.stdout
        rectangle_mesh.jnl
        rectangle_partition.cae
        rectangle_partition.cae.stdout
        rectangle_partition.jnl

    No subfolders exist

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.

Linux/MacOS

    $ 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

Windows

    PS > Get-Location

    Path
    ----
    C:\Users\roppenheimer\waves-tutorials

    PS > waves visualize tutorial_06_include_files --output-file tutorial_06_include_files.png --width=28 --height=6 --exclude-list .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.