Skip to main content
`Ctrl`+`K`

# Tutorial: Input Verification

The Abaqus journal files from Tutorial 01: Geometry and Tutorial 02: Partition and Mesh already perform some input verification by specifying the expected variable types. This input verification can be extended by user specified type methods. This is useful when a journal file should limit the range of allowable float values, for instance. In the case of these tutorials, one might wish to limit the width, height, and global seed parameters to positive float values. The solution approach is sufficiently general to allow modsim owners to similarly implement ranges of floats or integers, specific value choices, or any other restriction which may be necessary to ensure that a simulation workflow is used within its designed assumptions.

## References

- Argparse type [45]

- Tutorial 02: Partition and Mesh

- Tutorial 05: Parameter Substitution

## 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 2 && mv tutorial_02_partition_mesh_SConstruct SConstruct
    WAVES fetch
    Destination directory: '/home/roppenheimer/waves-tutorials'

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

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

5. Create a new directory `modsim_package/argparse_types`.

    $ pwd
    /path/to/waves-tutorials
    $ mkdir -p modsim_package/argparse_types

6. Copy the Abaqus journal files into the new directory `modsim_package/argparse_types`

    $ pwd
    /path/to/waves-tutorials
    $ cp modsim_package/abaqus/rectangle_{geometry,partition,mesh}.py modsim_package/argparse_types

## Journal Files

7. In the `modsim_package` directory, create a new file called `argparse_types.py` using the contents below

waves-tutorials/modsim_package/argparse_types.py

     1"""Python 2/3 compatible argparse types for input verification"""
     2
     3import argparse
     4
     5
     6def positive_float(argument):
     7    """Type function for argparse - positive floats
     8
     9    Abaqus Python 2 and Python 3 compatible argparse type method:
    10    https://docs.python.org/3.12/library/argparse.html#type.
    11
    12    :param str argument: string argument from argparse
    13
    14    :returns: argument
    15    :rtype: float
    16
    17    :raises ValueError:
    18
    19        * The argument can't be cast to float
    20        * The argument is less than 0.0 in a float comparison
    21    """
    22    MINIMUM_VALUE = 0.0
    23    try:
    24        argument = float(argument)
    25    except ValueError:
    26        raise argparse.ArgumentTypeError("invalid float value: '{}'".format(argument))
    27    if not argument > MINIMUM_VALUE:
    28        raise argparse.ArgumentTypeError("invalid positive float: '{}'".format(argument))
    29    return argument

The user-defined Argparse type function must take exactly one positional argument, which should correspond to the string that will be parsed by the argparse interface. The function may perform any arbitrary verification checks and return the type cast argument if all checks pass.

8. Make the following changes to the journal file imports and argparse option definitions.

waves-tutorials/argparse_types/rectangle_geometry.py

    --- /home/runner/work/waves/waves/build/docs/abaqus_rectangle_geometry.py
    +++ /home/runner/work/waves/waves/build/docs/argparse_types_rectangle_geometry.py
    @@ -5,6 +5,8 @@

     import abaqus
     import abaqusConstants
    +
    +from modsim_package.argparse_types import positive_float

     def main(output_file, model_name, part_name, width, height):
    @@ -93,13 +95,13 @@
         )
         parser.add_argument(
             "--width",
    -        type=float,
    +        type=positive_float,
             default=default_width,
             help="The rectangle width. Positive float.",
         )
         parser.add_argument(
             "--height",
    -        type=float,
    +        type=positive_float,
             default=default_height,
             help="The rectangle height. Positive float.",
         )

waves-tutorials/argparse_types/rectangle_partition.py

    --- /home/runner/work/waves/waves/build/docs/abaqus_rectangle_partition.py
    +++ /home/runner/work/waves/waves/build/docs/argparse_types_rectangle_partition.py
    @@ -5,6 +5,8 @@
     import argparse

     import abaqus
    +
    +from modsim_package.argparse_types import positive_float

     def main(input_file, output_file, model_name, part_name, width, height):
    @@ -152,13 +154,13 @@
         )
         parser.add_argument(
             "--width",
    -        type=float,
    +        type=positive_float,
             default=default_width,
             help="The rectangle width. Positive float.",
         )
         parser.add_argument(
             "--height",
    -        type=float,
    +        type=positive_float,
             default=default_height,
             help="The rectangle height. Positive float.",
         )

waves-tutorials/argparse_types/rectangle_mesh.py

    --- /home/runner/work/waves/waves/build/docs/abaqus_rectangle_mesh.py
    +++ /home/runner/work/waves/waves/build/docs/argparse_types_rectangle_mesh.py
    @@ -8,15 +8,8 @@
     import abaqusConstants
     import mesh

    -# Import the shared abaqus utilities, trying both tutorial directory structures.
    -# Most end-users will implement only one of these structures and should replace
    -# the try/except structure with a single import line, e.g.
    -#
    -# import modsim_package.abaqus.abaqus_utilities as abaqus_utilities
    -try:
    -    import modsim_package.abaqus.abaqus_utilities as abaqus_utilities
    -except ImportError:
    -    import abaqus_utilities
    +import modsim_package.abaqus.abaqus_utilities
    +from modsim_package.argparse_types import positive_float

     def main(input_file, output_file, model_name, part_name, global_seed):
    @@ -66,7 +59,7 @@
         part.Set(faces=faces, name="NODES")

         model_object = abaqus.mdb.models[model_name]
    -    abaqus_utilities.export_mesh(model_object, part_name, output_file)
    +    modsim_package.abaqus.abaqus_utilities.export_mesh(model_object, part_name, output_file)

         abaqus.mdb.save()

    @@ -133,7 +126,7 @@
         )
         parser.add_argument(
             "--global-seed",
    -        type=float,
    +        type=positive_float,
             default=default_global_seed,
             help="The global mesh seed size. Positive float.",
         )

Here we import the modsim package files as introduced in Tutorial 02: Partition and Mesh for the meshing journal file, but for all journal files to use the `positive_float` type check in the `argparse` interface.

## SConscript

No change is required to the `SConscript` configuration file. The new journal file location will be changed in the `SConstruct` file below.

## SConstruct

9. Add `tutorial_argparse_types` to the `workflow_configurations` list in the `waves-tutorials/SConstruct` file.

A `diff` against the `SConstruct` file from Tutorial 02: Partition and Mesh is included below to help identify the changes made in this tutorial.

waves-tutorials/SConstruct

    --- /home/runner/work/waves/waves/build/docs/tutorials_tutorial_02_partition_mesh_SConstruct
    +++ /home/runner/work/waves/waves/build/docs/tutorials_tutorial_argparse_types_SConstruct
    @@ -98,6 +98,7 @@
     workflow_configurations = [
         "tutorial_01_geometry",
         "tutorial_02_partition_mesh",
    +    "tutorial_argparse_types",
     ]
     for workflow in workflow_configurations:
         build_dir = env["variant_dir_base"] / workflow

In addition to the new target workflow `tutorial_argparse_types`, the changes above point to the new `argparse_types` path containing the updated journal files.

## Build Targets

10. Build the new targets

    $ pwd
    /path/to/waves-tutorials
    $ scons tutorial_argparse_types
    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_argparse_types && /apps/abaqus/Commands/abaqus cae -noGui /home/roppenheimer/waves-tutorials/modsim_package/abaqus/rectangle_geometry.py -- > rectangle_geometry.stdout 2>&1
    cd /home/roppenheimer/waves-tutorials/build/tutorial_argparse_types && /apps/abaqus/Commands/abaqus cae -noGui /home/roppenheimer/waves-tutorials/modsim_package/abaqus/rectangle_partition.py -- > rectangle_partition.stdout 2>&1
    cd /home/roppenheimer/waves-tutorials/build/tutorial_argparse_types && /apps/abaqus/Commands/abaqus cae -noGui /home/roppenheimer/waves-tutorials/modsim_package/abaqus/rectangle_mesh.py -- > rectangle_mesh.stdout 2>&1
    scons: done building targets.

The build process, targets, and output files should be identical to that of Tutorial 02: Partition and Mesh. You can explore changes in behavior by modifying the `subcommand_options` of both `tutorial_02_partition_mesh` and `tutorial_argparse_types` to include negative floats and re-running both workflows. For instance, by adding the following to the Geometry task definition.

    subcommand_options="--width '-1.0'"

See Tutorial 05: Parameter Substitution for more details about using the command-line interface and `subcommand_options` task argument.

## Output Files

The contents of the new workflow should be identical to that of Tutorial 02: Partition and Mesh.

    $ pwd
    /home/roppenheimer/waves-tutorials
    $ tree build/tutorial_02_partition_mesh/ build/tutorial_argparse_types/
    build/tutorial_02_partition_mesh/
    |-- abaqus.rpy
    |-- abaqus.rpy.1
    |-- abaqus.rpy.2
    |-- 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
    build/tutorial_argparse_types/
    |-- abaqus.rpy
    |-- abaqus.rpy.1
    |-- abaqus.rpy.2
    |-- 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, 26 files