Importing Abaqus results#

This section explains how to import results from Abaqus simulations into HelloTriangle using the compact HelloTriangle HT5 format. The workflow consists of:

  1. Running a local Python extraction script to convert an Abaqus .odb file into a compact .ht5 file. This script should be executed on a computer where Abaqus is installed.

  2. Loading the .ht5 file directly into HelloTriangle using load()

Overview of the workflow#

Abaqus .odb
     │
     ▼
odb_to_ht5_v1.py
     │
     ▼
.ht5 file (HDF5)
     │
     ▼
load("file.ht5") → SimData → Mesh objects

Converting ODB to HT5#

To extract results from an Abaqus ODB file, use the provided script: odb_to_ht5_v1.py (right-click to download).

Note

The script must be executed using standard Python, not Abaqus Python.

User configuration#

At the top of the script, configure the following parameters:

ODB_PATH = "mysimulation.odb"
OUTPUT_HT5 = "mysimulation.ht5"

STEPS_SELECTION = {
    "Step-1": "all",        # export all frames
    "Step-2": [0, 10, -1],  # export selected frames
}

FIELDS = ["U", "S_VON_MISES", "LE_MAX_PRINC"]

Parameters explained:

  • ODB_PATH Path to the Abaqus .odb file

  • OUTPUT_HT5 Name of the generated .ht5 file

  • STEPS_SELECTION Dictionary specifying which steps and frames to export:

    • "all" → export all frames in the step

    • [0, 5, -1] → export specific frames, -1 refers to the last frame

  • FIELDS List of fields to extract. Supports both native and derived fields:

    • Native: U, S, LE, …

    • Derived: S_VON_MISES, S_MAX_PRINC, LE_MAX_PRINC, U_MAGNITUDE

Running the script#

Run the script using standard Python:

python odb_to_ht5_v1.py

Performance considerations#

Abaqus ODB files can be very large. Exporting everything can lead to:

  • Large .ht5 files

  • Slow loading times in HelloTriangle

Important

Always export only the data you need:

  • Limit the number of steps

  • Select only relevant frames

  • Restrict the number of fields

Field handling#

All extracted field data is stored as nodal fields, regardless of the original output location in Abaqus.

Handling of missing data#

Missing values can occur in two situations:

  • A field is not available for certain elements in a mesh

  • A field is not present in a specific frame

In all cases:

  • Missing values are filled with NaN

  • This ensures consistent array sizes across all frames and parts

Section point detection#

Some Abaqus fields (e.g., stress S or strain LE) may be defined at section points (e.g., shell top/bottom). The extraction script automatically detects available section points and exports them as separate fields.

For example:

  • S_VON_MISES_Top

  • S_VON_MISES_Bottom

Each section point becomes its own field in the .ht5 file.

Section points in mixed meshes#

In hybrid meshes (multiple element types), it is possible that:

  • Some elements (e.g., shells) have section points

  • Other elements (e.g., solids) do not

In this case:

  • Values from elements without section points are included in all corresponding section point fields

  • For example, solid element values will appear in both S_VON_MISES_Top and S_VON_MISES_Bottom

This ensures:

  • Consistent field availability across the entire mesh

  • Simpler visualization and post-processing

Component consistency#

All elements contributing to a field must have the same number of components.

Warning

If a field contains incompatible element types with different component sizes (e.g., mixing truss and shell stress tensors), extraction will fail with a clear error message.

Inspecting available fields#

To list all available fields on a mesh:

print(mesh.field_report())

This provides an overview of all attached fields and their components.

Loading HT5 files in HelloTriangle#

Use load() to read the .ht5 file:

data = load("mysimulation.ht5")

This returns a SimData object containing:

  • Metadata (solver, time steps)

  • Parts

  • Fields

Exploring the dataset#

print(data)

Example output:

<SimData>
  solver: Abaqus
  frames: 20 frames (0 → 19)
  time: [0.0 → 1.0]
  parts: PART-1, PART-2

Accessing parts:

print(data.part_names)

Creating meshes#

To construct a mesh for a given part and frame:

mesh = data.get_mesh("PART-1", frame=-1)
  • frame=-1 selects the last frame

  • Negative indexing is supported

Note

If displacement field U is available, the mesh is automatically deformed.

Visualizing results#

draw(mesh, field="S_VON_MISES")