Skip to main content
`Ctrl`+`K`

# Tutorial: Escape Sequences

In addition to source and target file signatures, SCons saves a build signature that includes information about the action required to build the target. The build signature will include the substitution variables used in the task. For example, the contents of the `abaqus_options` string provided to the `waves.scons_extensions.abaqus_journal_builder_factory()` and `waves.scons_extensions.abaqus_solver_builder_factory()` builders is part of the build signature. Changes to these options will trigger a re-build of that task.

Sometimes you may want to exclude elements of the task action from the build signature. For instance, the Solve step introduced in Tutorial 04: Simulation can run Abaqus with a different number of cpus, which shouldn’t affect the simulation results. Adding a variable number of cpus to the `abaqus_options` would change the build signature each time the cpu count changed and unnecessarily re-run the simulation task. To avoid this, you can specify elements of the action to exclude from the build signature with the `$( excluded string $)` escape sequence syntax.

## References

- SCons Variable Substitution [44]

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

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

    $ pwd
    /home/roppenheimer/waves-tutorials
    $ waves fetch --overwrite --tutorial 4 && mv tutorial_04_simulation_SConstruct SConstruct
    Destination directory: '/home/roppenheimer/waves-tutorials'

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

    $ pwd
    /home/roppenheimer/waves-tutorials
    $ waves fetch --overwrite tutorials/tutorial_04_simulation && cp tutorial_04_simulation tutorial_escape_sequences
    WAVES fetch
    Destination directory: '/home/roppenheimer/waves-tutorials'

## SConscript

A `diff` against the `tutorial_04_simulation` file from Tutorial 04: Simulation is included below to help identify the changes made in this tutorial.

waves-tutorials/tutorial_escape_sequences

    --- /home/runner/work/waves/waves/build/docs/tutorials_tutorial_04_simulation
    +++ /home/runner/work/waves/waves/build/docs/tutorials_tutorial_escape_sequences
    @@ -5,6 +5,7 @@

     * ``env`` - The SCons construction environment with the following required keys

    +  * ``solve_cpus`` - Integer number of cpus to use in the Abaqus solve task
       * ``unconditional_build`` - Boolean flag to force building of conditionally ignored targets
       * ``abaqus`` - String path for the Abaqus executable
     """
    @@ -118,7 +119,8 @@
             ],
             source=solve_source_list,
             job="rectangle_compression",
    -        program_options="-double both",
    +        program_options="-double both -cpus $(${solve_cpus}$)",
    +        solve_cpus=env["solve_cpus"],
         )
     )

## SConstruct

A `diff` against the `SConstruct` file from Tutorial 04: Simulation is included below to help identify the changes made in this tutorial.

waves-tutorials/SConstruct

    --- /home/runner/work/waves/waves/build/docs/tutorials_tutorial_04_simulation_SConstruct
    +++ /home/runner/work/waves/waves/build/docs/tutorials_tutorial_escape_sequences_SConstruct
    @@ -24,6 +24,16 @@
         default=False,
         action="store_true",
         help="Boolean flag to force building of conditionally ignored targets. (default: '%default')",
    +)
    +AddOption(
    +    "--solve-cpus",
    +    dest="solve_cpus",
    +    default=1,
    +    nargs=1,
    +    type="int",
    +    action="store",
    +    metavar="N",
    +    help="Run the Abaqus Solve task using N CPUs. (default: '%default')",
     )
     AddOption(
         "--print-build-failures",
    @@ -58,6 +68,7 @@
         unconditional_build=GetOption("unconditional_build"),
         print_build_failures=GetOption("print_build_failures"),
         abaqus_commands=GetOption("abaqus_command"),
    +    solve_cpus=GetOption("solve_cpus"),
     )

     # Conditionally print failed task *.stdout files
    @@ -100,6 +111,7 @@
         "tutorial_02_partition_mesh",
         "tutorial_03_solverprep",
         "tutorial_04_simulation",
    +    "tutorial_escape_sequences",
     ]
     for workflow in workflow_configurations:
         build_dir = env["variant_dir_base"] / workflow

## Build Targets

5. Build the new targets

    $ pwd
    /home/roppenheimer/waves-tutorials
    $ scons tutorial_escape_sequences
    scons: Reading SConscript files ...
    Checking whether abq2024 program exists.../apps/abaqus/Commands/abq2024
    Checking whether abq2021 program exists.../apps/abaqus/Commands/abq2021
    Checking whether abq2020 program exists.../apps/abaqus/Commands/abq2020
    scons: done reading SConscript files.
    scons: Building targets ...
    cd /home/roppenheimer/waves-tutorials/build/tutorial_escape_sequences && /apps/abaqus/Commands/abq2024 cae -noGui /home/roppenheimer/waves-tutorials/modsim_package/abaqus/rectangle_geometry.py -- > rectangle_geometry.stdout 2>&1
    cd /home/roppenheimer/waves-tutorials/build/tutorial_escape_sequences && /apps/abaqus/Commands/abq2024 cae -noGui /home/roppenheimer/waves-tutorials/modsim_package/abaqus/rectangle_partition.py -- > rectangle_partition.stdout 2>&1
    cd /home/roppenheimer/waves-tutorials/build/tutorial_escape_sequences && /apps/abaqus/Commands/abq2024 cae -noGui /home/roppenheimer/waves-tutorials/modsim_package/abaqus/rectangle_mesh.py -- > rectangle_mesh.stdout 2>&1
    Copy("build/tutorial_escape_sequences/rectangle_compression.inp", "modsim_package/abaqus/rectangle_compression.inp")
    Copy("build/tutorial_escape_sequences/assembly.inp", "modsim_package/abaqus/assembly.inp")
    Copy("build/tutorial_escape_sequences/boundary.inp", "modsim_package/abaqus/boundary.inp")
    Copy("build/tutorial_escape_sequences/field_output.inp", "modsim_package/abaqus/field_output.inp")
    Copy("build/tutorial_escape_sequences/materials.inp", "modsim_package/abaqus/materials.inp")
    Copy("build/tutorial_escape_sequences/parts.inp", "modsim_package/abaqus/parts.inp")
    Copy("build/tutorial_escape_sequences/history_output.inp", "modsim_package/abaqus/history_output.inp")
    cd /home/roppenheimer/waves-tutorials/build/tutorial_escape_sequences && /apps/abaqus/Commands/abq2024 -job rectangle_compression -input rectangle_compression -double both -cpus 1 -interactive -ask_delete no > rectangle_compression.stdout 2>&1
    scons: done building targets.

6. Execute the build command again with a different number of solve cpus. Observe that the workflow is reported as up-to-date.

    $ pwd
    /path/to/waves-tutorials
    $ scons tutorial_escape_sequences --solve-cpus=2
    scons: Reading SConscript files ...
    Checking whether abq2021 program exists.../apps/abaqus/Commands/abq2021
    Checking whether abq2020 program exists.../apps/abaqus/Commands/abq2020
    scons: done reading SConscript files.
    scons: Building targets ...
    scons: `tutorial_escape_sequences' is up to date.
    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 that the output files from the previous tutorials also exist in the `build` directory, but the directory is specified by name to reduce clutter in the ouptut shown.

    $ pwd
    /home/roppenheimer/waves-tutorials
    $ tree build/tutorial_escape_sequences/
    build/tutorial_escape_sequences/
    |-- 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.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, 27 files