Skip to main content
`Ctrl`+`K`

# Tutorial: Abaqus CAE

While the core tutorials focus on script based, non-interactive workflows, it is possible to mix interactive and graphical elements into a workflow, too. Interactive tasks remove many of the benefits of a build system, such as large batch execution (parameter studies) and reproducibility. However, they are sometimes unavoidable.

An example of an unavoidable, non-graphical, interactive task is authentication against access controls like when a user is required to enter a password. Interactive tasks may also be necessary when the cost of scripting project files is prohibitively high. For example, a project may require editing binary files where the cost of scripting the edits is not justified, as when the files undergo whole-sale changes frequently, when the edits are difficult to program and require significant analyst judgement, or when large, legacy files are relatively static. In particular, proprietary binary files may be more convenient to edit with the tools provided by the proprietary graphical software, like geometric CAD files.

When adding interactive elements to a workflow, you can preserve some value of automation and reproducibility by limiting interactive tasks to the earliest portions of the workflow and putting interactively modified files under version control. The editing process may be interactive, but preserving the file with version control makes the downstream workflow reproducible for all project members. To regain the benefits of a build system, the downstream workflow must still be executable from a command line interface.

This tutorial will cover one possible solution to incorporate the graphical, interactive tasks of Abaqus model creation in Abaqus CAE with an automated, non-interactive job submission task. Similar solutions are limited by third-party interfaces, but should be possible in most cases where a scripting interface is available.

## 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 the project directory structure and copy the tutorial files into the `~/waves-tutorials/tutorial_abaqus_cae` sub-directory with the WAVES Command-Line Utility fetch subcommand.

    $ waves fetch tutorials/tutorial_abaqus_cae --destination ~/waves-tutorials/tutorial_abaqus_cae
    WAVES fetch
    Destination directory: '/home/roppenheimer/waves-tutorials/tutorial_abaqus_cae'
    $ cd ~/waves-tutorials/tutorial_abaqus_cae
    $ pwd
    /home/roppenheimer/waves-tutorials/tutorial_abaqus_cae

## SConscript File

For this tutorial, we will not discuss the main SCons configuration file named `SConstruct`, which contains project setup boilerplate. Tutorial 00: SConstruct has a more complete discussion about the contents of the `SConstruct` file.

The `SConscript` file contains the workflow task definitions. This tutorial contains two sets of tasks. The first set of tasks prepare the Abaqus CAE cantilever beam model from the tutorials provided by the Abaqus documentation and retrieved with the `fetch` command [42]. These tasks are not strictly part of the tutorial. Instead they produce a job submission ready `beam.cae` file. See the Abaqus manual for a tutorial on using Abaqus CAE.

tutorial_abaqus_cae/SConscript

    14# Create the job-ready beam example CAE file
    15cae_prep.extend(
    16    env.Command(
    17        target=["beamExample.py"],
    18        source=["SConscript"],
    19        action=[
    20            "cd ${TARGET.dir.abspath} && ${abaqus} fetch job=beamExample",
    21            "echo \"mdb.saveAs(pathName='beam.cae')\" >> ${TARGET.abspath}",
    22        ],
    23        abaqus=env["ABAQUS_PROGRAM"],
    24    )
    25)
    26
    27cae_prep.extend(
    28    env.AbaqusJournal(
    29        target=["beam.cae"],
    30        source=["beamExample.py"],
    31    )
    32)

The tutorial task is a single Abaqus journal file execution. It should look similar to the journal file tasks introduced in the core tutorials: Tutorial 01: Geometry and Tutorial 02: Partition and Mesh. You can read more about the behavior of the `AbaqusJournal` builder in the function API `waves.scons_extensions.abaqus_journal_builder_factory()` and the core tutorials.

tutorial_abaqus_cae/SConscript

    36# Run the tutorial CAE job submission solution
    37workflow.extend(
    38    env.AbaqusJournal(
    39        target=["beam.odb"],
    40        source=["submit_cae.py", "beam.cae"],
    41        subcommand_options="--input-file ${SOURCES[1].abspath} --job-name beam --model-name Beam",
    42    )
    43)

## Abaqus Journal File

The Abaqus journal file is a small command line utility designed to open job submission ready CAE model files and submit the simulation. You can read more about journal file design in the core tutorials: Tutorial 01: Geometry and Tutorial 02: Partition and Mesh. This journal file shares many of the same features, such as docstrings for the API, a command line interface, default execution values, input file handling to avoid accidental source modification during workflow execution, and function separation to smaller unit tasks.

tutorial_abaqus_cae/submit_cae.py

      1import os
      2import sys
      3import json
      4import shutil
      5import inspect
      6import tempfile
      7import argparse
      8
      9import abaqus
     10import abaqusConstants
     11import job
     12
     13
     14default_model_name = "Model-1"
     15default_cpus = None
     16
     17
     18def main(input_file, job_name, model_name=default_model_name, cpus=default_cpus, write_inp=False, **kwargs):
     19    """Open an Abaqus CAE model file and submit the job.
     20
     21    If the job already exists, ignore the model name and update the job options. If the job does not exist, create it
     22    using the job attributes passed in from the API/CLI, e.g. ``cpus`` and ``kwargs``.
     23
     24    Because Abaqus modifies CAE files on open, a temporary copy of the file is created to avoid constant job rebuilds in
     25    build tools like SCons or Make.
     26
     27    See ``mdb.Job`` in the "Abaqus Scripting Reference Guide" for job behavior and keyword arguments.
     28
     29    :param str input_file: CAE file to open by absolute or relative path. Must include the extension.
     30    :param str job_name: The name of the Abaqus job
     31    :param str model_name: The name of the Abaqus model
     32    :param int cpus: The number of CPUs for the Abaqus solver
     33    :param bool write_inp: write an Abaqus ``job.inp`` file and exit without submitting the job
     34    :param kwargs: The ``abaqus.mdb.Job`` keyword arguments. If the job exists, these overwrite existing job
     35        attributes. If provided, the ``cpus`` argument overrides both existing job attributes _and_ the kwargs.
     36    """
     37    if cpus is not None:
     38        kwargs.update({"numCpus": cpus})
     39
     40    with AbaqusNamedTemporaryFile(input_file=input_file, suffix=".cae", dir="."):
     41
     42        if job in abaqus.mdb.jobs.keys():
     43            script_job = abaqus.mdb.jobs[job]
     44            script_job.setValues(**kwargs)
     45            model_name = script_job.model
     46
     47        if model_name in abaqus.mdb.models.keys():
     48            script_job = abaqus.mdb.Job(name=job_name, model=model_name, **kwargs)
     49        else:
     50            raise RuntimeError("Could not find model name '{}' in file '{}'\n".format(model_name, input_file))
     51
     52        if write_inp:
     53            script_job.writeInput(consistencyChecking=abaqusConstants.OFF)
     54        else:
     55            script_job.submit()
     56            script_job.waitForCompletion()
     57
     58
     59def get_parser():
     60    """Return parser for CLI options
     61
     62    All options should use the double-hyphen ``--option VALUE`` syntax to avoid clashes with the Abaqus option syntax,
     63    including flag style arguments ``--flag``. Single hyphen ``-f`` flag syntax often clashes with the Abaqus command
     64    line options and should be avoided.
     65
     66    :returns: parser
     67    :rtype: argparse.ArgumentParser
     68    """
     69    filename = inspect.getfile(lambda: None)
     70    basename = os.path.basename(filename)
     71
     72    default_json_file = None
     73
     74    prog = "abaqus cae -noGui {} --".format(basename)
     75    cli_description = (
     76        "Open an Abaqus CAE model file and submit the job."
     77        "If the job already exists, ignore the model name and update the job options. If the job does not exist, "
     78        "create it using the job attributes passed in from the API/CLI, e.g. ``cpus`` and ``kwargs``. "
     79        "Because Abaqus modifies CAE files on open, a temporary copy of the file is created to avoid constant job "
     80        "rebuilds in build tools like SCons or Make."
     81    )
     82    parser = argparse.ArgumentParser(description=cli_description, prog=prog)
     83    parser.add_argument(
     84        "--input-file",
     85        type=str,
     86        required=True,
     87        help="The Abaqus CAE model file with extension, e.g. ``input_file.cae``",
     88    )
     89    parser.add_argument(
     90        "--job-name",
     91        type=str,
     92        required=True,
     93        help="The name of the Abaqus job",
     94    )
     95    parser.add_argument(
     96        "--model-name",
     97        type=str,
     98        default=default_model_name,
     99        help="The name of the Abaqus model (default %(default)s)",
    100    )
    101    parser.add_argument(
    102        "--cpus",
    103        type=int,
    104        default=default_cpus,
    105        help="The number of cpus for the Abaqus simulation (default %(default)s)",
    106    )
    107    parser.add_argument(
    108        "--json-file",
    109        type=str,
    110        default=default_json_file,
    111        help="A JSON file containing a dictionary of keyword arguments for ``abaqus.mdb.Job`` " "(default %(default)s)",
    112    )
    113    parser.add_argument(
    114        "--write-inp",
    115        "--write-input",
    116        action="store_true",
    117        help="Write an Abaqus ``job.inp`` file and exit without submitting the job " "(default %(default)s)",
    118    )
    119    return parser
    120
    121
    122class AbaqusNamedTemporaryFile:
    123    """Open an Abaqus CAE ``input_file`` as a temporary file. Close and delete on exit of context manager.
    124
    125    Provides Windows compatible temporary file handling. Required until Python 3.12 ``delete_on_close=False`` option is
    126    available in Abaqus Python.
    127
    128    :param str input_file: The input file to copy before open
    129    """
    130
    131    def __init__(self, input_file, *args, **kwargs):
    132        self.temporary_file = tempfile.NamedTemporaryFile(*args, delete=False, **kwargs)
    133        shutil.copyfile(input_file, self.temporary_file.name)
    134        abaqus.openMdb(pathName=self.temporary_file.name)
    135
    136    def __enter__(self):
    137        return self.temporary_file
    138
    139    def __exit__(self, exc_type, exc_val, exc_tb):
    140        abaqus.mdb.close()
    141        self.temporary_file.close()
    142        os.remove(self.temporary_file.name)
    143
    144
    145def return_json_dictionary(json_file):
    146    """Open a JSON file and return a dictionary compatible with Abaqus keyword arguments
    147
    148    If the JSON file is ``None``, return an empty dictionary. Convert unicode strings to str. If a value is found in
    149    ``abaqusConstants`` convert the value.
    150
    151    :param str json_file: path to a JSON file
    152
    153    :returns: Abaqus compatible keyword argument dictionary
    154    :rtype: dict
    155    """
    156    kwargs = {}
    157    if json_file is not None:
    158        with open(json_file) as json_open:
    159            dictionary = json.load(json_open)
    160        for key, value in dictionary.items():
    161            if isinstance(key, unicode):
    162                key = str(key)
    163            if isinstance(value, unicode):
    164                value = str(value)
    165            if hasattr(abaqusConstants, value):
    166                value = getattr(abaqusConstants, value)
    167        kwargs[key] = value
    168    return kwargs
    169
    170
    171if __name__ == "__main__":
    172    parser = get_parser()
    173    try:
    174        args, unknown = parser.parse_known_args()
    175    except SystemExit as err:
    176        sys.exit(err.code)
    177    possible_typos = [argument for argument in unknown if argument.startswith("--")]
    178    if len(possible_typos) > 0:
    179        raise RuntimeError("Found possible typos in CLI option(s) {}".format(possible_typos))
    180
    181    kwargs = return_json_dictionary(args.json_file)
    182
    183    sys.exit(
    184        main(
    185            input_file=args.input_file,
    186            job_name=args.job_name,
    187            model_name=args.model_name,
    188            cpus=args.cpus,
    189            write_inp=args.write_inp,
    190            **kwargs  # fmt: skip
    191        )
    192    )

After command line utility design, Python coding practices, and the Python style guide, the most unique aspect of this journal file is the `return_json_dictionary` function. This is necessary to convert string based job arguments to Abaqus scripting objects found in the `abaqusConstants` module. In an active modsim project, this function would be broken into yet smaller units of re-usable work and placed in a shared utilities module as introduced in Tutorial 02: Partition and Mesh.

Here it is kept as a limited use function implemented directly in the calling script for the convenience of documenting this tutorial and maintaining the tutorial suite. See the ModSim Templates for examples of more re-usable utility functions and unit testing.

## Building targets

The tutorial may be executed by a single call of the `submit_beam_cae` alias. However, to demonstrate the interactive use of a CAE file, a second alias is provided, `create_beam_cae`.

First, create the CAE file

    $ pwd
    /home/roppenheimer/waves-tutorials/tutorial_abaqus_cae
    $ scons create_beam_cae

This intermediate workflow will fetch the `beamExample.py` file from the Abaqus tutorial repository with `abaqus fetch`, append a CAE model save command, and execute the journal file. The Abaqus tutorial includes job execution with the name `beam_tutorial`, so you will see job output in the build directory along with the desired `beam.cae` file.

    $ pwd
    /home/roppenheimer/waves-tutorials/tutorial_abaqus_cae
    $ ls build/beam.cae
    build/beam.cae
    $ tree build/
    build/
    |-- SConscript
    |-- abaqus.rpy
    |-- beam.cae
    |-- beam.cae.stdout
    |-- beam.jnl
    |-- beamExample.py
    |-- beam_tutorial.com
    |-- beam_tutorial.dat
    |-- beam_tutorial.inp
    |-- beam_tutorial.log
    |-- beam_tutorial.msg
    |-- beam_tutorial.odb
    |-- beam_tutorial.prt
    `-- beam_tutorial.sta

    0 directories, 14 files

Take some time to open the CAE file and look for familiar CAE model and job data. Since this model is job ready, there is nothing to edit.

Finally, run the post-interactive workflow that is the subject of this tutorial

    $ pwd
    /home/roppenheimer/waves-tutorials/tutorial_abaqus_cae
    $ scons submit_beam_cae

This workflow calls the `submit_cae.py` journal file to submit the job defined in `beam.cae`. The new files should look identical (except for timestamps and job name) to the output produced by the `beamExample.py` job.

    $ pwd
    /home/roppenheimer/waves-tutorials/tutorial_abaqus_cae
    $ tree build -P "beam.*"
    build
    |-- beam.cae
    |-- beam.cae.stdout
    |-- beam.com
    |-- beam.dat
    |-- beam.inp
    |-- beam.jnl
    |-- beam.log
    |-- beam.msg
    |-- beam.odb
    |-- beam.odb.stdout
    |-- beam.prt
    `-- beam.sta

    0 directories, 13 files

To better understand the mixed workflow, open the `build/beam.cae` file and edit it with Abaqus CAE. When you’ve finished editing the file, save it, close Abaqus CAE, and re-run the `scons submit_beam_cae` command. Observe the SCons output during execution and the timestamp changes in the build directory. It should look similar to the example output below.

    $ pwd
    /home/roppenheimer/waves-tutorials/tutorial_abaqus_cae
    $ scons submit_beam_cae --debug=explain
    scons: Reading SConscript files ...
    Checking whether /apps/abaqus/Commands/abq2024 program exists.../apps/abaqus/Commands/abq2024
    Checking whether abq2024 program exists...no
    scons: done reading SConscript files.
    scons: Building targets ...
    scons: rebuilding `build/beam.odb' because `build/beam.cae' changed
    cd /home/roppenheimer/waves-tutorials/tutorial_abaqus_cae/build && /apps/abaqus/Commands/abq2024 cae -noGui /home/roppenheimer/waves-tutorials/tutorial_abaqus_cae/build/submit_cae.py -- --input-file /home/roppenheimer/waves-tutorials/tutorial_abaqus_cae/build/beam.cae --job-name beam --model-name Beam > /home/roppenheimer/waves-tutorials/tutorial_abaqus_cae/build/beam.odb.stdout 2>&1
    scons: done building targets.

## Output Files

The full output directory should look like the following

    $ pwd
    /home/roppenheimer/waves-tutorials/tutorial_abaqus_cae
    $ tree build
    build
    |-- SConscript
    |-- abaqus.rpy
    |-- abaqus.rpy.1
    |-- beam.cae
    |-- beam.cae.stdout
    |-- beam.com
    |-- beam.dat
    |-- beam.inp
    |-- beam.jnl
    |-- beam.log
    |-- beam.msg
    |-- beam.odb
    |-- beam.odb.stdout
    |-- beam.prt
    |-- beam.sta
    |-- beamExample.py
    |-- beam_tutorial.com
    |-- beam_tutorial.dat
    |-- beam_tutorial.inp
    |-- beam_tutorial.log
    |-- beam_tutorial.msg
    |-- beam_tutorial.odb
    |-- beam_tutorial.prt
    |-- beam_tutorial.sta
    `-- submit_cae.py

    0 directories, 26 files