Abaqus Integration

This guide explains how to use simcoon’s built-in constitutive models within Abaqus on Linux systems.

Overview

Simcoon provides ready-to-use UMAT bridge files in the software/ directory that allow you to use all simcoon constitutive models directly in Abaqus:

  • software/umat_singleM.cpp - Single mechanical model (selected by material name)

  • software/umat_singleT.cpp - Single thermo-mechanical model

  • software/umat_externalM.cpp - Template for adding custom external UMAT in C++

  • software/umat_externalT.cpp - Template for custom external thermo-mechanical UMAT

These files export an extern "C" umat_() function that Abaqus calls directly. The bridge:

  1. Converts Abaqus arrays → simcoon Armadillo format (abaqus2smart_M())

  2. Calls simcoon’s select_umat_M() to run the appropriate model based on the 5-character material name

  3. Converts results back → Abaqus arrays (smart2abaqus_M())

Note

This is the opposite of the external plugin system documented in External. Here, simcoon models run inside Abaqus. In the external plugin system, external UMATs run inside simcoon’s solver.

Prerequisites

Linux System Requirements

# Required packages (Ubuntu/Debian)
sudo apt-get install build-essential cmake
sudo apt-get install libarmadillo-dev liblapack-dev libblas-dev

# Required packages (RHEL/CentOS)
sudo yum groupinstall "Development Tools"
sudo yum install cmake armadillo-devel lapack-devel blas-devel

simcoon Installation

Ensure simcoon is built and installed using the provided install script:

cd simcoon
sh Install.sh -n 4

# The script will:
# - Build simcoon with CMake/Ninja
# - Install to $CONDA_PREFIX (your conda environment)
# - Install the Python package
# - Optionally run tests

# To skip tests:
sh Install.sh -t -n 4

Using umat_singleT (Thermo-mechanical)

For coupled thermo-mechanical analysis with heat generation:

g++ -shared -fPIC -std=c++17 -O2 -o libumat_simcoon_T.so umat_singleT.cpp \
    -I$SIMCOON_DIR/include \
    -L$SIMCOON_DIR/lib -lsimcoon \
    -larmadillo -llapack -lblas

The thermo-mechanical version provides:

  • Mechanical tangent ddsdde (the Abaqus material Jacobian, see below)

  • Thermal stress tangent ddsddt (\(\partial \boldsymbol{\sigma} / \partial T\))

  • Heat flux derivative drplde (\(\partial r / \partial \boldsymbol{\varepsilon}\))

  • Heat capacity drpldt (\(\partial r / \partial T\))

  • Heat generation rate rpl

Material Jacobian convention

Abaqus integrates a UMAT in its corotated frame: STRESS and STRAN are rotated by Abaqus before the call (DROT is the rotation increment, used here to rotate the tensorial state variables), DSTRAN is the logarithmic strain increment, and STRESS is the Cauchy stress. Under NLGEOM Abaqus defines DDSDDE through the Jaumann rate of the Kirchhoff stress divided by \(J\):

\[\mathbf{C}^{\text{Abaqus}} = \frac{1}{J}\frac{\partial (J\boldsymbol{\sigma})}{\partial \boldsymbol{\varepsilon}} = \frac{\partial \boldsymbol{\sigma}}{\partial \boldsymbol{\varepsilon}} + \boldsymbol{\sigma} \otimes \mathbf{I}\]

since \(\mathrm{d}J = J\,\mathrm{tr}(\mathrm{d}\boldsymbol{\varepsilon})\). The simcoon kernels return the first term, the corotational tangent \(\partial \boldsymbol{\sigma} / \partial \boldsymbol{\varepsilon}\); smart2abaqus_M (and the thermomechanical smart2abaqus_T) add the symmetric part of \(\boldsymbol{\sigma} \otimes \mathbf{I}\), which is what the default symmetric solver of Abaqus keeps (abaqus_jacobian in fea_transfer.hpp). This term does not change the stress, hence not the converged solution: it restores the quadratic convergence of the global Newton loop when \(\sigma / E\) is not small (elastomers, shape memory alloys). It is added only where Abaqus’s definition has it: for NLGEOM steps (Abaqus hands DFGRD1 as the identity otherwise, which abaqus_nlgeom reads) and for the cases with three direct components (3D, plane strain, axisymmetric). Without NLGEOM the Jacobian is the kernel tangent, so linear-perturbation procedures (*FREQUENCY, *BUCKLE) see the right stiffness; plane stress and 1D condense the kernel tangent as it is, the element owning the thickness change.

Using umat_externalM (Custom Model)

If you want to implement a custom constitutive model in C++:

  1. Copy software/umat_externalM.cpp to your working directory

  2. Implement your model in the external_umat() function

  3. Compile and link:

g++ -shared -fPIC -std=c++17 -O2 -o libumat_custom.so umat_externalM.cpp \
    -I$SIMCOON_DIR/include \
    -L$SIMCOON_DIR/lib -lsimcoon \
    -larmadillo -llapack -lblas

The external_umat() signature receives simcoon-format data:

void external_umat(
    const vec &Etot,      // Total strain
    const vec &DEtot,     // Strain increment
    vec &sigma,           // Stress (output)
    mat &Lt,              // Tangent modulus (output)
    const mat &DR,        // Rotation increment
    const int &nprops,    // Number of properties
    const vec &props,     // Material properties
    const int &nstatev,   // Number of state variables
    vec &statev,          // State variables (input/output)
    const double &T,      // Temperature
    const double &DT,     // Temperature increment
    const double &Time,   // Step time
    const double &DTime,  // Time increment
    double &Wm,           // Mechanical work (output)
    double &Wm_r,         // Recoverable work (output)
    double &Wm_ir,        // Irrecoverable work (output)
    double &Wm_d,         // Dissipated work (output)
    const int &ndi,       // Number of direct components
    const int &nshr,      // Number of shear components
    const bool &start,    // First increment flag
    double &tnew_dt       // Suggested time step ratio (output)
);

How It Works

Architecture

┌───────────────────────────────────────────────────────────────┐
│                        Abaqus                                 │
│                           │                                   │
│                           ▼                                   │
│              calls extern "C" umat_()                         │
└───────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌───────────────────────────────────────────────────────────────┐
│              umat_singleM.cpp (bridge)                        │
│                                                               │
│  ┌─────────────────────────────────────────────────────────┐  │
│  │  abaqus2smart_M()                                       │  │
│  │  - Converts stress, ddsdde, stran, dstran → Armadillo   │  │
│  │  - Extracts temperature, properties, state variables    │  │
│  │  - Handles 2D/3D dimensionality (ndi, nshr)             │  │
│  └─────────────────────────────────────────────────────────┘  │
│                           │                                   │
│                           ▼                                   │
│  ┌─────────────────────────────────────────────────────────┐  │
│  │  select_umat_M(rve, ...)                                │  │
│  │  - Reads material name (first 5 chars of cmname)        │  │
│  │  - Dispatches to appropriate model: ELISO, EPICP, etc.  │  │
│  └─────────────────────────────────────────────────────────┘  │
│                           │                                   │
│                           ▼                                   │
│  ┌─────────────────────────────────────────────────────────┐  │
│  │  smart2abaqus_M()                                       │  │
│  │  - Converts sigma, Lt → stress, ddsdde arrays           │  │
│  │  - Packs state variables + work quantities              │  │
│  └─────────────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌───────────────────────────────────────────────────────────────┐
│                        Abaqus                                 │
│              (continues with updated stress/tangent)          │
└───────────────────────────────────────────────────────────────┘

Why extern “C” works

The extern "C" declaration:

  1. Disables C++ name mangling - The function is exported as umat_ exactly

  2. Uses C calling convention - Compatible with Fortran calling convention

  3. Standard types only - double*, int*, char* work universally

Abaqus looks for the symbol umat_ in the shared library - it doesn’t care if the library was compiled from Fortran or C++.

State Variables Layout

simcoon uses a specific layout for state variables (statev array):

statev[0]                - Wm (total mechanical work)
statev[1]                - Wm_r (recoverable work)
statev[2]                - Wm_ir (irrecoverable work)
statev[3]                - Wm_d (dissipated work)
statev[4:nstatev]        - Model-specific state variables (nstatev_smart of them)

Set *DEPVAR in your input file to nstatev_smart + 4: the four work quantities come first, then the model’s own variables (the same layout as the Ansys ustatev, see Ansys Integration).

Available Models

The following constitutive models are available through select_umat_M():

Mechanical Models (umat_singleM)

Code

Model

Properties (in order)

State Variables

ELISO

Isotropic elasticity

\(E, \nu, \alpha\)

1

ELIST

Transversely isotropic elasticity

axis, \(E_L, E_T, \nu_{TL}, \nu_{TT}, G_{LT}, \alpha_L, \alpha_T\)

1

ELORT

Orthotropic elasticity

\(E_1, E_2, E_3, \nu_{12}, \nu_{13}, \nu_{23}, G_{12}, G_{13}, G_{23}, \alpha_1, \alpha_2, \alpha_3\)

1

EPICP

Von Mises plasticity, power-law isotropic hardening

\(E, \nu, \alpha, \sigma_Y, k, m\)

8 (T_init, p, EP)

EPKCP

Von Mises, power-law isotropic + Prager kinematic

\(E, \nu, \alpha, \sigma_Y, k, m, k_X\)

14 (T_init, p, EP, a)

EPCHA

Von Mises + Voce + 2× Armstrong-Frederick

\(E, \nu, \alpha, \sigma_Y, Q, b, C_1, D_1, C_2, D_2\)

33

EPHIL / EPTRI

Hill yield + power-law isotropic hardening

\(E, \nu, \alpha, \sigma_Y, k, m, F, G, H, L, M, N\)

8 (T_init, p, EP)

EPHAC

Cubic elasticity + Hill + Voce + 2× AF

\(E, \nu, G, \alpha, \sigma_Y, Q, b, C_1, D_1, C_2, D_2, F, G, H, L, M, N\)

33

EPANI

Cubic elasticity + anisotropic yield + Voce + 2× AF

\(E, \nu, G, \alpha, \sigma_Y, Q, b, C_1, D_1, C_2, D_2, P_{11}..P_{66}\) (9)

33

EPDFA

Cubic elasticity + DFA yield + Voce + 2× AF

\(E, \nu, G, \alpha, \sigma_Y, Q, b, C_1, D_1, C_2, D_2, F, G, H, L, M, N, K\)

33

EPCHG

Generic Chaboche (selectable yield, N iso/kin terms)

\(E, \nu, G, \alpha, \sigma_Y, N_{iso}, N_{kin}\), criteria, \((Q,b) \times N\), \((C,D) \times N\), crit. params

33

EPHIN

N Hill yield surfaces

\(E, \nu, \alpha, N\), per surface: \(\sigma_Y, k, m, F, G, H, L, M, N\)

1 + 7N

SMADI

SMA unified model

See SMA documentation

24

SMAAI

SMA anisotropic model

See SMA documentation

24

LLDM0

Lemaitre-Ladeveze-Dufailly damage

See header documentation

9

ZENER

Kelvin viscoelastic (single branch)

\(E_0, \nu_0, \alpha, E_1, \nu_1, \eta_{B1}, \eta_{S1}\)

14

ZENNK

Kelvin viscoelastic (N branches)

\(E_0, \nu_0, \alpha, N\), per branch: \(E_i, \nu_i, \eta_{Bi}, \eta_{Si}\)

7 + 7N

PRONK

Prony series viscoelastic (generalized Maxwell)

\(E_0, \nu_0, \alpha, N\), per branch: \(E_i, \nu_i, \eta_{Bi}, \eta_{Si}\)

7 + 7N

MODUL

Composable modular UMAT

self-describing stream (see simcoon.modular)

model-dependent

Several of these names are served by the modular engine through props-translating adapters — identical usage and results; see Constitutive model (UMAT) catalog for per-name status and state-variable layout notes.

Micromechanics Models

Code

Model

Description

MIHEN

Mori-Tanaka (Eshelby)

Mean-field homogenization with Eshelby tensor

MIMTN

Mori-Tanaka with N phases

Multi-phase Mori-Tanaka

MISCN

Self-consistent (N phases)

Self-consistent homogenization

MIPLN

Periodic layered

Layered composite homogenization

Mean-field micromechanics models (MIHEN, MIMTN, MISCN, MIPLN) are not reachable through the Abaqus wrappers. Since 2.0 their sub-phases are passed in memory rather than read from Nellipsoids/Nlayers files, which the Abaqus entry point cannot supply; drive them from Python instead (see In-memory Python solver).

Troubleshooting

Compilation errors

# Check include paths
ls $SIMCOON_DIR/include/simcoon/

# Check library exists
ls $SIMCOON_DIR/lib/libsimcoon.*

Runtime library errors

# Check library path
echo $LD_LIBRARY_PATH

# Check dependencies of your UMAT
ldd libumat_simcoon.so

# Look for missing libraries
ldd libumat_simcoon.so | grep "not found"

Symbol not found errors

# Verify umat_ symbol is exported
nm -D libumat_simcoon.so | grep umat_
# Should show: T umat_

Convergence issues

  • Check that *DEPVAR matches nstatev_smart + 4

  • Verify material properties are in correct units

  • Start with small load increments

  • Check the tangent modulus is properly computed (symmetric, positive definite for elastic)

Debugging

Add debug output in the bridge code:

#include <fstream>

// In umat_() function, after abaqus2smart_M():
std::ofstream debug("umat_debug.log", std::ios::app);
debug << "=== Increment " << kinc << " ===" << std::endl;
debug << "Material: " << umat_name << std::endl;
debug << "T = " << rve_sv_M->T << ", DT = " << rve_sv_M->DT << std::endl;
debug << "Etot: " << rve_sv_M->Etot.t();
debug << "DEtot: " << rve_sv_M->DEtot.t();
debug.close();

Complete Example

Here’s a complete example for a tensile test on a plasticity model:

*HEADING
Tensile test with simcoon EPICP model
**
*NODE
1, 0.0, 0.0, 0.0
2, 1.0, 0.0, 0.0
3, 1.0, 1.0, 0.0
4, 0.0, 1.0, 0.0
5, 0.0, 0.0, 1.0
6, 1.0, 0.0, 1.0
7, 1.0, 1.0, 1.0
8, 0.0, 1.0, 1.0
**
*ELEMENT, TYPE=C3D8, ELSET=ALL
1, 1, 2, 3, 4, 5, 6, 7, 8
**
*SOLID SECTION, ELSET=ALL, MATERIAL=EPICP
**
*MATERIAL, NAME=EPICP
*DEPVAR
12
*USER MATERIAL, CONSTANTS=5
** E, nu, alpha, sigma_y, H
210000., 0.3, 0., 200., 1000.
**
*BOUNDARY
1, 1, 3
2, 2, 3
3, 3
4, 1
4, 3
5, 1, 2
6, 2
8, 1
**
*STEP, NLGEOM=NO
*STATIC
0.1, 1.0, 1e-5, 0.1
**
*BOUNDARY
5, 3, 3, 0.01
6, 3, 3, 0.01
7, 3, 3, 0.01
8, 3, 3, 0.01
**
*OUTPUT, FIELD
*NODE OUTPUT
U, RF
*ELEMENT OUTPUT
S, E, SDV
**
*END STEP