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

The simcoon kernels return the heat of the increment \(r\) (storage included, see Read the results); umat_singleT divides it and its derivatives by dtime to give Abaqus the rates it expects (zero at dtime = 0).

The whole thermomechanics stays in simcoon: rpl carries the complete heat of the model, \(r = \Delta\gamma - T_{n+1} \Delta\eta\), i.e. the dissipation, the thermoelastic and latent couplings and the heat storage, and drpldt the matching heat capacity. The heat follows from the free energy of the law; it is not a Taylor-Quinney fraction of the plastic work, the stored energy \(W_m^{ir}\) does not heat the material. Therefore, with these UMATs:

  • set *SPECIFIC HEAT to a negligible value, otherwise the storage is counted twice;

  • do not use *INELASTIC HEAT FRACTION.

An adiabatic analysis then reads rpl = 0 exactly, as in the simcoon solver.

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 take the condensed tangent as it is, the element owning the thickness change.

Plane stress, shells, beams and trusses

The bridges accept every (NDI, NSHR) state Abaqus passes: plane stress and shells (2, 1), shells with transverse shear (2, 3), trusses (1, 0) and beams such as B31 (1, 2) (11, 12, 13), next to the 3D, plane-strain and axisymmetric ones (NDI = 3). The NTENS components of STRESS, STRAN and DDSDDE map in Abaqus order to the simcoon components (the direct ones, then the shears 12, 13, 23).

With NDI < 3 the other components are stress-free and Abaqus does not give their strain. The material point solves it: the simcoon law always runs 3D, and a Newton iteration on its own tangent finds the strain that makes those stress components vanish, each evaluation integrating the whole increment from the start state (condensed_state.hpp, select_umat_M / select_umat_T). The converged point is the 3D law itself on the condensed state, for every law (plasticity, viscoelasticity, damage, SMA, MODUL), and DDSDDE (with DDSDDT, DRPLDE, DRPLDT in the thermomechanical bridge) is its exact condensed derivative whenever the law’s 3D tangent is exact: the global Newton keeps its quadratic convergence. The solved strain is kept in STATEV right after the energies (6 - NTENS values, simcoon order, rotated with DROT as Abaqus rotates STRAN), so each increment solves only its change: for plane stress, the thickness strain and the transverse shears (\(\varepsilon_{33}, \gamma_{13}, \gamma_{23}\)). The cost is two to four evaluations of the law per increment (more for a law whose 3D tangent is approximate, such as SMADI under tangent_mode = 2); a point that does not converge asks for a smaller increment through PNEWDT. The custom-model bridges (umat_externalM / umat_externalT) wrap external_umat the same way, so a custom law is written 3D only.

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:4+nC]           - Stress-free strain components (NDI < 3 only, nC = 6 - NTENS)
statev[4+nC:nstatev]     - Model-specific state variables (nstatev_smart of them)

Set *DEPVAR in your input file to nstatev_smart + 4 + nC: the four work quantities come first, then the solved stress-free strain when NDI < 3 (nC = 0 for 3D, plane-strain and axisymmetric elements, 3 for plane stress and B31 beams, 5 for trusses), then the model’s own variables (the same layout as the Ansys ustatev when nC = 0, see Ansys Integration). The thermomechanical bridge stores the three thermal energies Wt, Wt_r, Wt_ir after Wm: *DEPVAR is then nstatev_smart + 7 + nC.

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

EPJCK

Von Mises + Johnson-Cook yield stress (rate and temperature dependent)

\(E, \nu, \alpha, A, B, n, C, \dot{\varepsilon}_0, m, T_{\mathrm{ref}}, T_{\mathrm{melt}}\)

9 (T_init, p, EP, edot_p)

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

Ladevèze-Le Dantec ply damage with effective-stress plasticity

See header documentation (18 props)

10

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 + nC (+ 7 + nC thermomechanical)

  • 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