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#
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.
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 2 && mv tutorial_02_partition_mesh_SConstruct SConstruct
WAVES fetch
Destination directory: '/home/roppenheimer/waves-tutorials'
Download and copy the
tutorial_02_partition_mesh
file to a new file namedtutorial_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'
Create a new directory
modsim_package/argparse_types
.
$ pwd
/path/to/waves-tutorials
$ mkdir -p modsim_package/argparse_types
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#
In the
modsim_package
directory, create a new file calledargparse_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.
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#
Add
tutorial_argparse_types
to theworkflow_configurations
list in thewaves-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#
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