Skip to content

Getting started¤

abaqus2py is a thin Python interface for driving ABAQUS finite-element simulations from regular Python function calls. It wraps the full lifecycle of a simulation—preprocessing (generating the input file), job submission, and postprocessing (reading results back)—behind a small API.

The public API consists of just two classes:

Class Use it when
AbaqusSimulator You want a standalone driver to run one or more simulations directly.
F3DASMAbaqusSimulator You want to run simulations over an f3dasm.ExperimentData as part of a data-driven design pipeline.

Both are importable from the top-level package:

from abaqus2py import AbaqusSimulator, F3DASMAbaqusSimulator

Note. ABAQUS itself is not a Python dependency — abaqus2py shells out to the abaqus command-line tool (abaqus cae noGUI=..., abaqus job=...). The library installs and imports without ABAQUS present, but the simulation calls below require a working ABAQUS installation on your PATH. For that reason the simulation cells in this notebook are illustrative and are not executed.

The user-script contract¤

You supply your own ABAQUS modeling scripts; abaqus2py only generates the glue that calls them inside ABAQUS's own (Python-2) interpreter. Two kinds of script are involved, each defining an entry-point function (named main by default):

Preprocess script — defines a function taking a single dict of simulation parameters and producing a .inp file in the current working directory:

# my_model.py  (runs inside ABAQUS' interpreter)
def main(parameters):
    model_name = parameters["name"]
    length = parameters["length"]
    # ... build the model with the abaqus / mdb API ...
    # ... and write a .inp job file to the cwd ...

Postprocess script — defines a function taking an opened odb object and writing a results.pkl file with the extracted results:

# my_model_pp.py  (runs inside ABAQUS' interpreter)
import pickle

def main(odb):
    step = odb.steps[odb.steps.keys()[-1]]
    max_disp = ...  # extract from odb.steps / frames / fieldOutputs
    with open("results.pkl", "wb") as f:
        pickle.dump({"max_displacement": max_disp}, f, protocol=2)

See the scripts/ folder (supercompressible_lin_buckle.py, supercompressible_lin_buckle_pp.py, ...) for full, real examples.

1. The standalone AbaqusSimulator¤

Construct a simulator, then drive it. The constructor configures how jobs are run; the per-simulation parameters are passed at call time.

Each simulation gets its own sub-directory under working_directory, named from the "name" key in its parameter dict (falling back to simulation_<index>).

simulator = AbaqusSimulator(
    num_cpus=1,  # CPUs per job
    working_directory="results",  # sub-directories are created here
    delete_odb=False,  # keep the .odb after post-processing
    delete_temp_files=False,  # keep Abaqus temp files
    max_waiting_time=60,  # seconds to wait for a job to finish
)

The combined run¤

run chains preprocess → submit → (wait) → postprocess in one call. simulation_parameters accepts either a single dict or an iterable of dicts (to run a batch).

simulator.run(
    py_file="scripts/my_model.py",  # pre-processing script
    function_name="main",  # entry point in py_file
    post_py_file="scripts/my_model_pp.py",  # post-processing script
    simulation_parameters=[
        {"name": "sim_a", "length": 100.0},
        {"name": "sim_b", "length": 150.0},
    ],
)
# Results land in results/sim_a/ and results/sim_b/ (each with a results.pkl).

Running the steps individually¤

If you need finer control (e.g. submit on a cluster between preprocessing and postprocessing), call the three steps yourself. submit and postprocess take the .inp / .odb paths produced by the previous step.

params = {"name": "sim_a", "length": 100.0}

# 1. Generate the .inp file(s) under results/sim_a/
simulator.preprocess(
    py_file="scripts/my_model.py",
    simulation_parameters=params,
)

# 2. Submit the job to Abaqus
simulator.submit(inp_files="results/sim_a/sim_a.inp")

# 3. Read the .odb and write results.pkl
simulator.postprocess(
    py_file="scripts/my_model_pp.py",
    odb_files="results/sim_a/sim_a.odb",
)

2. The F3DASMAbaqusSimulator adapter¤

F3DASMAbaqusSimulator is an f3dasm.DataGenerator that wraps an AbaqusSimulator, so you can run a simulation for every row of an ExperimentData. Each input row becomes the parameter dict for the preprocess script, and the results read back from results.pkl are stored as outputs on the sample.

First, build an ExperimentData describing the design space — here a small 2-parameter sweep:

from f3dasm import ExperimentData, create_sampler
from f3dasm.design import Domain

domain = Domain()
domain.add_float("length", low=100.0, high=200.0)
domain.add_float("young_modulus", low=3.0e3, high=4.0e3)

data = ExperimentData(domain=domain)
sampler = create_sampler("random", seed=42)
data = sampler.call(data=data, n_samples=5)

Then construct the data generator with your pre- and post-processing scripts and evaluate it over the data.

Important. Pass pass_id=True to call so that f3dasm forwards each job's index as the id keyword argument. abaqus2py uses this index as the per-sample sub-directory name; without it, all samples would share one directory and overwrite each other.

abaqus_generator = F3DASMAbaqusSimulator(
    py_file="scripts/my_model.py",
    post_py_file="scripts/my_model_pp.py",
    num_cpus=1,
    working_directory="results",
)

# Call the generator on the data. pass_id=True forwards each job index.
data = abaqus_generator.call(data=data, pass_id=True)

# The keys of the dict written by your post-process script (e.g.
# "max_displacement") are now output columns on `data`.
print(data)

How results are stored: scalar outputs (Python/numpy int/float/bool and str) are kept in memory on the ExperimentData; everything else (arrays, lists, ...) is written to disk and referenced from the sample. Pickles produced by ABAQUS's Python-2 interpreter are loaded with encoding="latin1" / fix_imports=True automatically.

A complete worked example¤

The repository ships a full, HPC-oriented study under studies/fragile_becomes_supercompressible/, reproducing Bessa et al. (2019). It wires F3DASMAbaqusSimulator into a Hydra-configured, two-stage (linear-buckle → Riks) f3dasm workflow with SLURM submission. Read studies/fragile_becomes_supercompressible/main.py for the canonical end-to-end usage pattern.