MUESLI Manual
Theory, implementation, and use of the Material UnivErSal LIbrary
Table of Contents
- Introduction
- The constitutive point of view
- Theory of material modeling in MUESLI
- Software architecture and implementation
- Obtaining, building, and integrating the library
- How to use MUESLI
- Material family reference
- Extending MUESLI with a new material
- Verification, validation, and debugging
- Practical advice and common failure modes
- Versioning, contribution, and citation
- Appendix: Recommended notation
- Appendix: Template for documenting one material model
- Appendix: Suggested single-point driver
- Appendix: Further reading
- Closing remarks
This document has been automatically generated by a LLM. It is being reviewed and can contain mistakes.
Introduction
Purpose
MUESLI is a continuum-level material library written in C++. Its purpose is to provide a reusable set of constitutive laws for solids, fluids, thermal problems, and coupled multiphysics problems, together with a software structure that makes new models easier to implement, verify, and transfer between simulation codes.
The library sits at the material point level. It does not replace a finite element, finite volume, meshfree, or multiscale solver. Instead, it supplies the local constitutive response required by those solvers: stresses, heat fluxes, thermodynamic conjugates, internal-variable updates, and consistent tangent operators.
Design goals
MUESLI has five practical design goals.
- Clarity. The implementation should resemble the mathematics. Tensor operations, invariants, and constitutive maps should be readable enough that a model can be checked against a paper or textbook without mentally translating everything into Voigt-matrix algebra.
- Extensibility. New materials should be implemented by adding a small number of classes inside an existing family, not by rewriting the whole library.
- Reliability. Constitutive updates should be accompanied by self-checks and regression tests so that stress, tangent, and history evolution remain mutually consistent.
- Plug-ability. The same constitutive code should be usable in research codes and, through thin adapters, in commercial solvers.
- Reusability. Material behavior should be decoupled from the host code so that calibration, benchmarking, and algorithmic development can happen once and be reused in multiple environments.
Scope of the library
At the level publicly described for MUESLI, the library covers the following problem families.
| Family | Representative models and capabilities |
|---|---|
| Small-strain solids | Linear isotropic elasticity, classical plasticity, classical viscoelasticity |
| Finite-strain solids | Saint Venant-Kirchhoff, isotropic hyperelasticity, finite-strain plasticity |
| Hyperelasticity | Neo-Hookean, Arruda-Boyce, Mooney-Rivlin, Yeoh |
| Impact/high-rate response | Johnson-Cook, Zerilli-Armstrong, Arrhenius-type |
| Thermal analysis | Isotropic and anisotropic Fourier heat conduction |
| Small-strain thermomechanics | Thermoelasticity, thermoplasticity, thermoviscoelasticity |
| Fluids | Newtonian fluid |
| Coupled problems | Thermo-mechanics, chemo-mechanics, thermo-chemo-mechanics |
| Reduced-dimensionality models | Plane stress, shells, plates, beams |
| Interfaces | Adapters for Abaqus and LS-DYNA |
| Verification support | Family-specific automatic consistency checks |
This list should be read as the publicly documented envelope of the library. Any local branch may contain more models than those listed here.
What MUESLI is not
MUESLI is not a full simulation framework. In particular, the library should not be expected to provide:
- mesh management,
- global assembly,
- linear algebra solvers,
- nonlinear solution control,
- contact, remeshing, or adaptivity,
- time-step selection for a host solver,
- postprocessing infrastructure.
Those remain responsibilities of the host application.
Intended audiences
This manual addresses three audiences.
- Users who want to link MUESLI into an existing solver and call material routines correctly.
- Developers who want to add a new constitutive law or modify an existing one.
- Researchers who want to understand the thermodynamic and algorithmic choices behind the implementation.
The constitutive point of view
Material points and local state
MUESLI follows the standard computational-mechanics view in which constitutive behavior is evaluated at material points. A material point receives local input from the host code - for example strain, deformation gradient, temperature, temperature gradient, strain rate, or chemical field variables - and returns the quantities needed by the discretization.
Typical outputs include:
- stress in the measure expected by the host code,
- heat flux,
- entropy or internal energy contributions,
- internal-variable updates,
- algorithmic tangent operators,
- diagnostic information about convergence or active mechanisms.
A central conceptual choice in MUESLI is that a material object represents one constitutive law and parameter set, while the point states store the history of the different integration points using that law.
Inputs and outputs by problem class
| Problem class | Typical inputs | Typical outputs |
|---|---|---|
| Small strain solid | strain, strain increment, temperature | Cauchy stress, consistent tangent, state |
| Finite strain solid | deformation gradient, temperature | PK stress or Kirchhoff/Cauchy stress, tangent |
| Heat conduction | temperature gradient | heat flux, conductivity tangent |
| Thermomechanics | strain or F, temperature, grad T | stress, heat flux, coupling blocks, state |
| Fluid | rate of deformation, pressure data | deviatoric stress, viscosity contribution |
| Reduced model | constrained generalized strains | section resultants, reduced tangent |
| High-rate model | plastic strain, strain rate, temperature | flow stress, hardening data, state |
The exact set of arguments depends on the model family and the adapter used by the host code.
History dependence
Many constitutive laws are path-dependent. MUESLI therefore distinguishes between two kinds of data.
- Parameters are fixed for all points using the same material: elastic constants, hardening parameters, conductivity coefficients, reference temperatures, rate constants, and so on.
- State variables evolve point by point: plastic strains, hardening variables, inelastic deformation tensors, viscous strains, accumulated dissipation, temperature-like internal variables, damage measures, and similar quantities.
A safe constitutive implementation separates trial evaluation from state commit. In a nonlinear global solve, the host code may need to evaluate a point many times before accepting the time increment. State variables must therefore be updated in a reversible or staged manner until the host announces convergence.
Tangent operators
For implicit solvers, the local constitutive law is not complete without the algorithmic tangent. In exact Newton methods, the rate of global convergence is governed as much by the consistency of the tangent as by the correctness of the stress update itself.
MUESLI treats the tangent as a first-class result of the constitutive update. For elastic models it is usually the derivative of stress with respect to the chosen strain measure. For inelastic models it is the consistent derivative of the discrete update map, not merely the continuum elastic tensor.
Theory of material modeling in MUESLI
Thermodynamic framework
The natural language of continuum constitutive modeling is thermodynamics. Although each family has its own variables and kinematics, the common organizing principle is a state potential and a dissipation statement.
For many models, the starting point is a Helmholtz free energy \[ \psi = \psi(\text{state variables}), \] with constitutive quantities derived as thermodynamic conjugates. In a small strain thermoelastic example one may write \[ \psi = \psi(\varepsilon^e, T, \alpha), \] where \(\varepsilon^e\) is elastic strain, \(T\) temperature, and \(\alpha\) collects internal variables.
The stress follows from \[ \sigma = \frac{\partial \psi}{\partial \varepsilon^e}, \] while other conjugates are obtained by differentiation with respect to the remaining state variables. The dissipation inequality then constrains the admissible evolution laws.
This thermodynamic organization is especially important for three reasons.
- It keeps the model internally coherent.
- It provides a route to derive the tangent operator.
- It supports the automated consistency checks that compare energies, thermodynamic conjugates, and linearizations.
Small-strain solids
At small strain, the kinematics are based on the symmetric gradient \[ \varepsilon = \frac{1}{2}(\nabla u + \nabla u^{T}). \]
For purely elastic response, stress is an instantaneous function of the current strain (and possibly temperature). In isotropic linear elasticity: \[ \sigma = \lambda \, \text{tr}(\varepsilon) I + 2 \mu \varepsilon, \] or, equivalently, \[ \sigma = C : \varepsilon. \]
For path-dependent small-strain solids, the total strain is split into contributions, for example \[ \varepsilon = \varepsilon^e + \varepsilon^p + \varepsilon^\theta + \varepsilon^v, \] depending on whether the model includes plastic, thermal, or viscous strains.
Classical plasticity
A classical rate-independent plasticity model usually contains:
- a yield function \(f(\sigma, q) \le 0\),
- a flow rule for plastic strain,
- a hardening law for internal variables \(q\),
- Kuhn-Tucker conditions,
- a return-mapping algorithm for the discrete update.
A J2-type model is the canonical example. The constitutive algorithm uses an elastic predictor followed by a plastic corrector. The resulting consistent tangent differs from the elastic tangent whenever the point is plastic.
Classical viscoelasticity
Viscoelastic models represent delayed response through internal strains or internal stresses. They can be organized through rheological analogs such as Maxwell or Kelvin-Voigt branches, but in a constitutive library the important point is the update structure:
- identify the internal variables carrying memory,
- integrate their evolution over the time step,
- compute the observable stress,
- return the derivative of the discrete map.
The small-strain viscoelastic part of MUESLI follows this general architecture.
Finite-strain solids
At finite strain, the basic kinematic object is the deformation gradient \[ F = \frac{\partial \varphi}{\partial X}, \qquad J = \det F. \]
Different stress and strain measures become relevant. In hyperelasticity, the right Cauchy-Green tensor \[ C = F^{T}F \] and an energy density \(W(C)\) are often used. The second Piola stress is then \[ S = 2\frac{\partial W}{\partial C}, \] and the Cauchy stress follows by push-forward: \[ \sigma = \frac{1}{J} F S F^{T}. \]
The design consequence for a library such as MUESLI is that each model must be explicit about:
- the strain measure it accepts,
- the stress measure it returns internally,
- how the adapter converts that result to the measure required by the host code,
- the frame in which the tangent operator is expressed.
Saint Venant-Kirchhoff
Saint Venant-Kirchhoff is the finite-strain extension of linear elasticity written in terms of Green-Lagrange strain. It is useful as a pedagogical large-strain model and as a baseline for testing the finite-strain infrastructure.
Isotropic hyperelasticity
The publicly described hyperelastic models in MUESLI include compressible and incompressible variants of Neo-Hookean, Arruda-Boyce, and Mooney-Rivlin models, plus the Yeoh model.
The common pattern is:
- define a strain-energy density \(W\),
- evaluate its derivatives with respect to the chosen invariants or tensors,
- obtain stress and tangent through differentiation,
- handle volumetric and deviatoric parts carefully, especially near incompressibility.
For developers, the crucial lesson is that hyperelastic models are ideal candidates for the energy -> stress -> tangent verification pipeline.
Finite-strain plasticity
The finite-strain plasticity branch is described publicly as an \(F^e F^p\)-type formulation, meaning a multiplicative decomposition \[ F = F^e F^p. \]
This structure is standard in modern finite plasticity. The elastic response is computed from the elastic part of the deformation, while \(F^p\) evolves according to a flow rule defined in the intermediate configuration. Numerically, the local update usually involves:
- a trial elastic predictor,
- solution of a nonlinear scalar or tensorial consistency problem,
- update of \(F^p\) and hardening variables,
- computation of a consistent tangent in the chosen frame.
Because frame-indifference and measure conversion are easy to get wrong, this family benefits strongly from family-specific tests.
Thermal analysis
For thermal models the constitutive law relates temperature gradients to heat fluxes. The basic Fourier law is \[ q = -k \nabla T \] for isotropic conductivity and \[ q = -K \nabla T \] for anisotropic conductivity, where \(K\) is a symmetric positive-definite conductivity tensor.
In the library, thermal materials should expose:
- conductivity parameters,
- heat-flux evaluation,
- directional or tensorial conductivity when required,
- tangent information when used in nonlinear coupled solves.
Small-strain thermomechanics
Thermomechanical materials couple mechanical and thermal variables. A typical free energy may be decomposed as \[ \psi = \psi_{\text{mech}} + \psi_{\text{therm}} + \psi_{\text{coupling}}. \]
This decomposition gives access to:
- thermal expansion,
- temperature dependence of elastic moduli or hardening,
- entropy and heat capacity effects,
- dissipation-generated heating in inelastic models.
The thermodynamic structure matters because the solver may need not only the mechanical tangent and the thermal tangent, but also the off-diagonal coupling blocks. In a monolithic coupled solve, those blocks are essential to robustness.
Fluids
The fluid branch documented publicly is the Newtonian fluid model. In continuum form, a Newtonian constitutive law takes the form \[ \sigma = -p I + 2 \mu d + \lambda \, \text{tr}(d) I, \] where \(d\) is the symmetric part of the velocity gradient, \(\mu\) is the dynamic viscosity, and \(\lambda\) is the bulk-viscosity-like coefficient.
For library design, the important point is that fluids are expressed in terms of rates rather than total strains, so the interface of this family differs naturally from the solid families.
Impact and high-rate constitutive laws
The impact branch adds phenomenological high-rate, temperature-dependent plasticity models commonly used for metals subjected to severe loading.
Johnson-Cook
A standard Johnson-Cook flow stress has the form \[ \sigma_y = \left(A + B \bar{\varepsilon}_p^n \right) \left(1 + C \ln \frac{\dot{\bar{\varepsilon}}_p}{\dot{\bar{\varepsilon}}_0}\right) \left(1 - \theta^m \right), \] with \[ \theta = \frac{T - T_r}{T_m - T_r}. \]
The model separates hardening, strain-rate sensitivity, and thermal softening. Its appeal lies in ease of calibration and wide industrial use, although it is fundamentally phenomenological.
Zerilli-Armstrong
Zerilli-Armstrong models are also phenomenological, but their functional form is motivated differently and depends on the material class. In practice, the model combines temperature, strain-rate, and work-hardening terms in an exponential structure. The exact variant should be documented in the source code and kept together with the parameter definition.
Arrhenius-type laws
Arrhenius-type viscoplastic laws express the connection between stress, strain rate, and temperature through an activation mechanism, often in the form \[ \dot{\bar{\varepsilon}} = A \, [\sinh(\alpha \sigma)]^n \exp\left(-\frac{Q}{RT}\right). \]
These models are useful when thermally activated flow is central to the response. Compared with Johnson-Cook, they often require more care in inversion and parameter identification.
Coupled chemo-mechanics and thermo-chemo-mechanics
Coupled models introduce additional fields, most commonly concentration-like variables, swelling terms, chemically induced eigenstrains, transport laws, and coupling energies. The decisive implementation principle is the same as in thermomechanics: make the state variables and the thermodynamic coupling explicit, and return a block-structured linearization consistent with the update.
Reduced-dimensional constitutive models
Reduced models such as plane stress, shells, plates, and beams are not merely lower-dimensional copies of 3D materials. They are usually constrained 3D constitutive problems. For example, a plane-stress update may require solving for the out-of-plane strain component that enforces \(\sigma_{33}=0\).
This leads to two important implementation ideas.
- A reduced model may be built by wrapping a 3D constitutive law inside a local constrained solve.
- The tangent of the reduced model must include the effect of that constraint elimination, not just the unrestricted 3D tangent.
For shells, plates, and beams the same logic extends to generalized strains and section resultants, sometimes with through-thickness integration or section-level local solves.
Software architecture and implementation
Why tensor algebra matters
A defining MUESLI choice is to prefer tensor algebra over blanket reliance on Voigt notation. This is not just a matter of elegance.
- Tensor notation preserves the natural structure of constitutive equations.
- The difference between scalar, vector, second-order, and fourth-order objects remains visible in the code.
- Frame transformations, invariants, contractions, and projections become easier to express and audit.
- Model implementations resemble the literature more closely.
Voigt notation still has a role at interfaces, especially where a commercial code expects packed stress or tangent arrays. The key principle is: keep Voigt at the boundary, not at the heart of the model.
Core software concepts
A robust constitutive library usually separates five concerns.
Parameter objects
A parameter object stores material constants and algorithmic tolerances. It should be immutable during a constitutive update and sharable by all points using the same material.
Typical contents:
- elastic constants,
- hardening parameters,
- reference temperatures,
- viscosities or relaxation times,
- conductivity data,
- solver tolerances for local iterations.
Material objects
A material object represents a constitutive law together with one fixed parameter set. Public descriptions of MUESLI state that a material object encapsulates the data of all material points that share the same response. Conceptually, this means the object knows what law is being solved, while point states know where each point currently is on that law.
Responsibilities of the material object include:
- exposing the family interface,
- evaluating point updates,
- providing helper functions common to all points,
- owning or managing the collection of point states when that design is used,
- running family-specific checks.
Point states
A point state stores all history-dependent data for one integration point. The state must be serializable, copyable, and easy to checkpoint.
Examples:
- accumulated plastic strain,
- hardening variables,
- backstress tensors,
- viscous strains,
- inelastic deformation gradient,
- temperature-like internal variables,
- damage or porosity variables.
Input bundles
The host code should pass a compact input bundle to the constitutive law rather than a large number of unrelated scalar arguments. A clean input object typically contains:
- the current kinematic quantity (strain, rate, or deformation gradient),
- the increment and time-step size,
- temperature and field values,
- optional previous-step quantities already available in the host code,
- flags indicating whether the solve is explicit, implicit, trial-only, etc.
Response bundles
Similarly, the constitutive law should return a response bundle that groups:
- stress,
- tangent,
- heat flux,
- updated state,
- local iteration statistics,
- flags or status codes.
This is better than returning stress alone and hiding everything else in side effects.
Family hierarchy
The public documentation emphasizes material families. The purpose of a family is to define a shared contract for all models of the same kinematic and physical type.
A conceptual hierarchy looks like this:
MaterialFamily |- SmallStrainSolid | |- LinearElastic | |- J2Plasticity | `- Viscoelastic |- FiniteStrainSolid | |- SaintVenantKirchhoff | |- NeoHookean | |- ArrudaBoyce | |- MooneyRivlin | |- Yeoh | `- FeFpPlasticity |- ThermalMaterial | |- FourierIsotropic | `- FourierAnisotropic |- ThermoMechanicalMaterial |- FluidMaterial |- ImpactMaterial |- CoupledMaterial `- ReducedMaterial
This tree is conceptual, not a claim about exact class names. The important design rule is that each family should define:
- the admissible input variables,
- the output variables,
- the required constitutive methods,
- the consistency checks applicable to that family.
Constitutive update pattern
Across families, the local algorithm should follow a predictable pattern.
- Read input and current state.
- Build trial quantities.
- Detect the active branch or mechanism.
- Solve the local nonlinear problem if necessary.
- Compute stress, fluxes, and updated internal variables.
- Compute the consistent tangent of the discrete update.
- Store the tentative state without permanently committing it.
- Return status information to the host.
In pseudocode:
Response Material::evaluate(const Input& in, const State& old_state) const
{
State trial = old_state;
Response out{};
// 1. Elastic or reversible predictor
TrialData td = compute_trial(in, old_state);
// 2. Branch selection
if (is_elastic(td)) {
out.stress = elastic_stress(td);
out.tangent = elastic_tangent(td);
out.state = old_state;
return out;
}
// 3. Local solve
LocalSolution sol = solve_local_problem(td, old_state);
// 4. Build final response
out.stress = stress_from_solution(sol);
out.tangent = consistent_tangent(sol);
out.state = state_from_solution(sol);
out.status = sol.status;
return out;
}
What matters is not the exact spelling, but the separation between trial, solution, and committed state.
Consistent linearization
Whenever the host uses Newton-type global iterations, the constitutive update should be linearized after discretization. This is especially important for:
- return-mapping plasticity,
- viscous updates integrated implicitly,
- reduced models with local constraints,
- coupled models with block tangents,
- finite-strain algorithms with push-forward and pull-back operations.
A recurring source of bugs is to return a continuum tangent while the stress has been computed by a discrete algorithm. The solver may still converge, but only linearly or erratically.
Memory ownership and thread safety
Public release notes mention thread-safe compilation. In practice, thread safety at the constitutive level requires:
- no writable global scratch variables,
- no static mutable temporaries shared between points,
- all point-level work arrays to be stack-based or point-owned,
- deterministic treatment of caches and lazy initialization,
- reentrant adapters when called by multithreaded host codes.
A good default is to assume that every constitutive call may occur concurrently on many integration points.
Error handling and diagnostics
Constitutive routines should fail loudly and informatively. Recommended failure modes include:
- invalid parameter ranges,
- loss of positive definiteness in quantities that must stay positive,
- singular local Jacobians,
- non-convergence of return mapping,
- inadmissible deformation gradients such as \(J \le 0\),
- temperatures outside model validity ranges.
A response bundle should therefore be able to carry:
- a convergence flag,
- the number of local iterations,
- an error code,
- optional residual norms.
Interfacing to host codes
One of MUESLI's main goals is transferability. The interface layer should be as thin as possible.
Responsibilities of an adapter include:
- map host-code data structures to MUESLI input bundles,
- convert stress and tangent measures,
- reorder components when the host expects Voigt arrays,
- manage state-variable storage in the host format,
- handle commit and rollback at the correct stage of the global algorithm,
- translate units and reference values consistently.
The constitutive core should not know whether the caller is a research code, Abaqus, LS-DYNA, or a standalone calibration tool.
Verification tools
MUESLI is publicly described as including automatic checks tailored to each family. The conceptual checks are:
- energy-stress consistency: derivative of stored energy reproduces stress,
- stress-tangent consistency: derivative of stress reproduces tangent,
- symmetry and objectivity tests, where applicable,
- reference-case recovery: known limiting cases are reproduced exactly,
- interface regression: adapter output matches the direct core output.
Such checks are not full validation, but they are excellent at finding coding mistakes early.
Obtaining, building, and integrating the library
Getting the sources
Public project information describes two ways of obtaining MUESLI.
- Download a release archive from the project website.
- Clone the Bitbucket repository.
The public release history mentions versions 1.1, 1.3, 1.4, and 1.8. The release notes highlight, among other things, thermoelastic additions, thread-safe compilation, reduced models, the Yeoh material, and later impact and coupled models.
Platform expectations
The public description states that MUESLI has been used and tested on Linux and macOS. When preparing a new installation, verify:
- compiler standard and version,
- optimization flags,
- BLAS/LAPACK or other numerical dependencies if your branch uses them,
- thread-related flags if your host is multithreaded,
- consistent floating-point behavior across debug and release builds.
Build system philosophy
This manual does not assume an exact build system, because that must be taken from the repository itself. In general, the build should produce:
- a static or shared library containing the constitutive core,
- headers exposing the public API,
- test executables or drivers,
- optional interface libraries or user subroutines for commercial codes,
- optional examples and documentation targets.
A healthy build should support both a developer mode and a production mode.
| Mode | Typical flags and behavior |
|---|---|
| Developer | debug symbols, assertions, warnings enabled, sanitizers when possible |
| Production | optimization enabled, assertions reduced, reproducible floating-point |
Recommended source-tree organization
A practical constitutive library benefits from keeping its code separated by role. A good repository layout is:
muesli/ |- doc/ manual, notes, examples |- include/ public headers |- src/ core implementation |- materials/ material families and models |- interfaces/ host-code adapters |- tests/ unit and regression tests |- examples/ standalone drivers `- tools/ calibration or inspection utilities
Again, this is a recommended organization, not a claim about the exact current tree.
Integration checklist for a host code
Before linking MUESLI into a solver, answer the following.
- What stress measure does the solver expect?
- What strain or kinematic measure does it pass to the constitutive routine?
- When, exactly, is local state committed?
- How are state variables stored and restarted?
- What units are used for temperature, time, and mechanical quantities?
- Is the solve explicit, implicit, or staggered coupled?
- Does the solver require a symmetric tangent, and is that mathematically valid?
- Is the constitutive call made concurrently from multiple threads?
If any of these are unclear, the interface will be fragile.
Reproducibility
For scientific use, each material definition should be tied to:
- a named model version,
- a parameter set with units,
- a calibration source,
- a reference problem or regression test,
- a known valid range of temperatures, rates, and deformations.
Without these, code reuse turns into guesswork.
How to use MUESLI
Standard workflow
A typical MUESLI-driven simulation follows this sequence.
- Choose the material family and model.
- Define the parameter set.
- Allocate or initialize one material object.
- Create one state per integration point.
- At each global step, assemble an input bundle for each point.
- Call the constitutive update.
- Use the returned stress, tangent, and fluxes in the host solver.
- Commit the tentative state only after the global step is accepted.
- Output state variables needed for restart and postprocessing.
Schematic example: small-strain elastoplastic point
The following example is schematic. It shows the usage pattern, not exact API names.
#include <vector>
// #include <muesli/...> // Replace with your exact headers.
int main()
{
// 1. Define parameters
J2Parameters par;
par.E = 210e9;
par.nu = 0.30;
par.sigma_y0 = 350e6;
par.H = 2.5e9;
// 2. Create one material object shared by many points
SmallStrainJ2 material(par);
// 3. Create one state per integration point
std::vector<J2State> state(ngp);
for (auto& s : state) {
s = material.initial_state();
}
// 4. Constitutive call inside the host loop
for (int gp = 0; gp < ngp; ++gp) {
SmallStrainInput in;
in.strain_n = eps_n[gp];
in.strain_np1 = eps_np1[gp];
in.temperature = T_np1[gp];
in.dt = dt;
auto out = material.evaluate(in, state[gp]);
sigma[gp] = out.stress;
C_alg[gp] = out.tangent;
// Commit only after the global step is accepted
trial_state[gp] = out.state;
}
if (global_step_converged) {
state = trial_state;
}
}
The essential ideas are:
- one parameterized material object,
- one history object per point,
- evaluate many times,
- commit only after acceptance.
Schematic example: finite-strain hyperelastic point
HyperelasticParameters par; par.mu = 0.8e6; par.kappa = 8.0e6; NeoHookean material(par); HyperState state = material.initial_state(); FiniteStrainInput in; in.F_np1 = F; in.T = temperature; auto out = material.evaluate(in, state); // The host may request PK2, Kirchhoff, or Cauchy stress; // the adapter is responsible for final conversion if needed. Tensor2 S = out.stress; Tensor4 A = out.tangent;
For finite strain, always verify:
- the stress measure returned by the core,
- the tangent frame,
- how incompressibility is treated,
- whether the host expects material or spatial quantities.
Using coupled thermo-mechanical models
In a coupled solve, the input must carry both mechanical and thermal data, for example:
- strain or deformation gradient,
- temperature,
- temperature gradient,
- time increment,
- possibly previous-step dissipation measures.
The returned response may contain a block structure like:
[ d sigma / d eps d sigma / d T ] [ d q / d eps d q / d gradT ]
In a staggered scheme, some of these blocks may be used only partially, but the constitutive update should still be internally consistent.
Explicit versus implicit use
MUESLI can be used in both explicit and implicit host codes, but the constitutive demands differ.
Explicit use
For explicit solvers, the constitutive call often needs only:
- current or incremented kinematics,
- updated stress,
- updated state.
The tangent may be optional or used only for diagnostics. The emphasis is on efficiency and robustness under many short calls.
Implicit use
For implicit solvers, the constitutive law must be fully algorithmic:
- local nonlinear problem solved to tolerance,
- consistent tangent returned,
- state update staged until global acceptance.
If the tangent is approximate, expect slower or less reliable global convergence.
Using MUESLI through commercial-code interfaces
Public project information describes interfaces to Abaqus and LS-DYNA. The recommended philosophy is:
- keep the host-specific code as thin as possible,
- perform all material logic inside the MUESLI core,
- convert data only at the boundary,
- maintain identical regression problems in direct and wrapped modes.
This allows the same constitutive model to be calibrated and debugged outside the commercial solver and then deployed there with minimal changes.
Postprocessing
For reproducibility and debugging, it is good practice to output not only the observable fields but also selected state variables, for example:
- accumulated plastic strain,
- hardening variables,
- temperature or dissipation contributions,
- active-branch flags,
- local iteration counts,
- failure or saturation indicators.
These outputs are often the fastest way to diagnose a wrong update.
Material family reference
Small-strain elasticity
Use this family when deformations are small and reversible response is sufficient.
- State variables: usually none.
- Inputs: strain, optionally temperature.
- Outputs: stress and elastic tangent.
- Typical numerical issues: almost none, which makes this family ideal for verifying the tensor layer, adapters, and stress-measure conventions.
Small-strain plasticity
Use when irreversible deformation occurs at small strain.
- State variables: plastic strain-like variables, hardening variables, backstress if kinematic hardening is present.
- Inputs: total strain or strain increment, temperature if thermally coupled.
- Outputs: stress, consistent elastoplastic tangent, updated state.
- Numerical core: return mapping with a local consistency solve.
- Key verification: elastic limit, yield-surface consistency, tangent tests.
Small-strain viscoelasticity
Use for rate-dependent, reversible delayed response.
- State variables: viscous branch variables.
- Inputs: strain history through increments and time step.
- Outputs: stress and discrete-time tangent.
- Key verification: relaxation, creep, and recovery limits.
Finite-strain hyperelasticity
Use when large reversible deformations dominate.
- State variables: typically none for purely elastic variants.
- Inputs: deformation gradient.
- Outputs: stress measure and tangent.
- Key issues: incompressibility treatment, stress/tangent frame, derivative consistency from the energy density.
Finite-strain plasticity
Use when large deformations and permanent flow are both present.
- State variables: inelastic deformation measure, hardening variables.
- Inputs: deformation gradient, time step, temperature when required.
- Outputs: stress, consistent tangent, updated inelastic state.
- Key issues: objective update, admissibility of \(J\), local nonlinear solve.
Thermal conduction
Use for heat-transfer problems or as the thermal branch of coupled models.
- State variables: usually none for linear Fourier conduction.
- Inputs: temperature gradient.
- Outputs: heat flux and conductivity tensor.
- Key issues: anisotropy and unit consistency.
Small-strain thermomechanics
Use when temperature and deformation are mutually coupled.
- State variables: mechanical and thermal history variables.
- Inputs: strain, temperature, time step, possibly temperature gradient.
- Outputs: stress, thermal quantities, coupling tangent blocks.
- Key issues: reference temperature, thermal strain convention, dissipative heating.
Impact models
Use for high strain-rate metallic response.
- State variables: accumulated plastic strain and rate/temperature-dependent auxiliary quantities.
- Inputs: strain, strain rate, temperature.
- Outputs: flow stress and consistent update data.
- Key issues: parameter calibration, valid temperature/rate range, numerical protection against invalid logarithms or softening extremes.
Fluid materials
Use for viscous fluid response at the constitutive level.
- State variables: often none for Newtonian response.
- Inputs: rate of deformation and pressure-related data from the host.
- Outputs: stress contribution and viscosity tangent.
- Key issues: clear split between constitutive and incompressibility treatment.
Coupled chemo-mechanics and thermo-chemo-mechanics
Use when concentration, diffusion, swelling, or additional internal fields couple with mechanics and temperature.
- State variables: transport and coupling variables.
- Inputs: mechanical, thermal, and chemical fields.
- Outputs: block-structured response and tangent.
- Key issues: consistent coupling linearization and clear thermodynamic bookkeeping.
Reduced-dimensional models
Use when the host code solves plane stress, shells, plates, or beams through reduced kinematics.
- State variables: inherited from the underlying 3D law plus constraint data.
- Inputs: generalized strains or constrained strain components.
- Outputs: reduced stresses/resultants and condensed tangent.
- Key issues: exact satisfaction of the constraint and proper condensation of the tangent.
Extending MUESLI with a new material
Choose the right family first
New models should almost never be added as free-floating classes. First decide which family the model belongs to:
- small strain or finite strain,
- reversible or dissipative,
- purely mechanical or coupled,
- 3D or reduced,
- rate-independent or rate-dependent.
The family determines the interface and the available tests.
Start from thermodynamics, not from code
Before writing C++, write down:
- the state variables,
- the free energy or stored-energy structure,
- the dissipation potential or flow law,
- the admissibility conditions,
- the algorithmic unknowns of the local solve,
- the quantities the host needs back.
If this cannot be written clearly on paper, the code will likely be unstable or hard to verify.
Define parameter and state objects
A good new model begins with two plain data structures.
struct MyModelParameters {
double E;
double nu;
double sigma0;
double H;
double Tref;
};
struct MyModelState {
Tensor2 eps_p;
double p = 0.0;
};
Keep parameters separate from evolving state.
Implement the local update
The local update should be small, explicit, and testable. Prefer a structure in which helper functions are easy to unit test independently:
- trial predictor,
- yield or activation evaluation,
- local residual and Jacobian,
- state reconstruction,
- tangent construction.
Avoid monolithic hundred-line functions whose only output is stress.
Implement the tangent immediately
Do not postpone the tangent. A constitutive model without the correct tangent is half implemented. The best development order is:
- energy or reversible map,
- stress,
- local residual,
- update algorithm,
- consistent tangent,
- checks.
Register tests with the family checks
Every new material should come with:
- a parameterized smoke test,
- at least one path-dependent regression test if applicable,
- numerical differentiation checks,
- limiting-case checks against a simpler model,
- adapter tests if the model will be deployed through external interfaces.
Schematic developer skeleton
class MyThermoPlasticity : public SmallStrainThermoMaterial
{
public:
explicit MyThermoPlasticity(const MyModelParameters& par) : par_(par) {}
MyModelState initial_state() const override
{
return {};
}
Response evaluate(const Input& in, const MyModelState& old_state) const override
{
// 1. Build trial data
// 2. Solve local constitutive equations
// 3. Return stress, tangent, new state, and diagnostics
}
void self_check() const override
{
// Run family-specific consistency checks
}
private:
MyModelParameters par_;
};
The exact inheritance chain is illustrative. The main point is that family contracts should remain visible in the code.
Documentation for each new material
Every new model should be documented with the same template.
- model name,
- governing equations,
- parameters and units,
- admissible input range,
- stress and tangent measures,
- state variables,
- integration algorithm,
- verification tests,
- references.
If this template is enforced, the library becomes much easier to maintain.
Verification, validation, and debugging
Consistency versus validation
It is useful to distinguish two tasks.
- Consistency checking asks whether the code correctly implements the equations.
- Validation asks whether the equations describe reality for the target material.
MUESLI's automated checks are primarily consistency checks. Validation still requires experimental comparison, literature benchmarks, or trusted-code comparison.
Recommended consistency checks
Energy -> stress
For energy-based models, compare analytical stress with numerical derivatives of the energy.
Stress -> tangent
Perturb the kinematic input and compare finite differences of the stress with the returned tangent action.
Elastic limit recovery
For inelastic models, verify that the update reproduces the elastic law in the appropriate limit.
Objectivity and symmetry
For finite-strain models, test frame indifference. For symmetric tangents or conductivity tensors, test the expected symmetry numerically.
Path tests
For history-dependent materials, run loading-unloading cycles, strain-rate jumps, and temperature ramps that exercise different branches.
Benchmark problems
The following benchmarks are especially useful.
| Family | Suggested benchmark |
|---|---|
| Small-strain elasticity | uniaxial tension, simple shear |
| Plasticity | return mapping under monotonic and cyclic loading |
| Viscoelasticity | stress relaxation and creep |
| Hyperelasticity | large simple extension and nearly incompressible loading |
| Finite plasticity | large-strain shear or compression with plastic flow |
| Thermal | one-dimensional heat flux with isotropic and anisotropic cases |
| Thermomechanics | constrained thermal expansion and dissipative heating |
| Reduced models | plane-stress patch test or section-consistency test |
| Impact models | Taylor-type impact or calibrated single-point high-rate loading |
Common debugging patterns
When a constitutive model misbehaves, the following order is efficient.
- Reproduce the problem in a single-point driver.
- Freeze the global solver and inspect only the local update.
- Check the returned tangent by finite differences.
- Check state commit and rollback separately.
- Confirm units and reference values.
- Only then return to the full solver.
Constitutive bugs become much easier to see when the host code is stripped away.
Diagnostics worth logging
For difficult models, log:
- local residual norm,
- local iteration count,
- active branch or mechanism,
- determinant \(J\) for finite strain,
- yield-function value before and after correction,
- line-search or damping information,
- extreme parameter combinations.
These logs are often worth far more than printing raw tensors.
Practical advice and common failure modes
Unit inconsistency
The most common non-coding failure is mixed units. Typical mistakes include:
- MPa parameters with Pa stresses,
- Celsius offsets treated as absolute temperatures,
- milliseconds used with SI rate constants,
- conductivity parameters defined in a different unit system than the solver.
Adopt one library-wide convention and document it.
Wrong stress or strain measure
Finite-strain integrations fail quietly if the host and constitutive law disagree about measures. Always document:
- input measure,
- output stress measure,
- tangent frame,
- conversion performed by the adapter.
Tangent mismatch
If the global Newton method stalls while the stress looks plausible, suspect the tangent first. Numerical differentiation of the discrete update is the fastest check.
State committed too early
If a global iteration evaluates the material several times per step, but the point state is overwritten permanently on the first call, path-dependent models will drift or harden incorrectly. This error is subtle and extremely common.
Reference temperature mistakes
High-rate and thermomechanical models often use reference, room, and melting temperatures. Mixing these or using a host temperature in different units can destroy the response without generating a clear code error.
Reduced-model inconsistency
For plane stress or shell wrappers, a frequent mistake is to satisfy the constraint in stress but return an uncondensed tangent. The response then looks right in postprocessing but destabilizes the solver.
Logarithms and exponentials in high-rate models
Johnson-Cook and Arrhenius-type models can become numerically invalid if:
- strain rate is non-positive inside a logarithm,
- normalized temperature leaves its intended range,
- exponential arguments overflow,
- thermal softening drives stress negative without safeguards.
Guard these operations explicitly.
Versioning, contribution, and citation
Public release milestones
| Version | Publicly noted additions or remarks |
|---|---|
| 1.1 | Early public release |
| 1.3 | Thermoelastic materials, thread-safe compilation, minor bug fixes |
| 1.4 | Reduced models, Yeoh material, minor bug fixes |
| 1.8 | Impact materials, coupled problems, additional bug fixes |
This table reflects the public release notes and should be updated locally if your repository has more recent tags or branches.
Contribution workflow
A robust workflow for new contributions is:
- define the theory and parameters,
- implement the model inside the correct family,
- add tests,
- add a standalone example,
- document the model,
- run the family self-checks,
- run interface regression problems where relevant.
License
MUESLI is publicly described as being distributed under GPL 3.0. If the local repository adds exceptions, dual licensing, or commercial wrappers, document those terms clearly next to the core license.
How to cite the library
The canonical citation should point users to the main MUESLI paper and, if useful, to the project website or release tag used in the computations. A complete scientific citation should also state the specific constitutive model and the parameter set employed.
Appendix: Recommended notation
| Symbol | Meaning |
|---|---|
| \(u\) | displacement |
| \(\varepsilon\) | small-strain tensor |
| \(F\) | deformation gradient |
| \(J\) | determinant of \(F\) |
| \(C\) | right Cauchy-Green tensor |
| \(\sigma\) | Cauchy stress |
| \(S\) | second Piola-Kirchhoff stress |
| \(\psi\) | Helmholtz free energy |
| \(q\) | heat flux |
| \(T\) | absolute temperature |
| \(\alpha\) | generic internal-variable collection |
| \(d\) | symmetric part of velocity gradient |
| \(C_{\text{alg}}\) | algorithmic tangent |
| \(F^e, F^p\) | elastic and plastic parts of multiplicative split |
Appendix: Template for documenting one material model
Copy the following block for every new material added to the library.
#+begin_example
Model name
Purpose
What physical behavior the model is intended to represent.
Governing equations
Free energy, yield function, flow rule, transport law, or other defining equations.
Parameters
List every parameter, its symbol, units, and admissible range.
Inputs
What the host code must pass in.
Outputs
Stress measure, tangent, fluxes, state variables, diagnostics.
State variables
Definition and physical meaning.
Integration algorithm
Predictor/corrector, local Newton solve, closed-form update, etc.
Verification
Energy/stress check, tangent check, benchmark cases.
Notes
Known limitations, reference ranges, calibration remarks. #+end_example
Appendix: Suggested single-point driver
A standalone driver is one of the most valuable files in a constitutive library. It should:
- read a material parameter set,
- generate one or more loading paths,
- call the constitutive law without any host solver,
- write stress, state, and tangent information,
- compare against analytical or regression expectations.
Such a driver is the fastest route to debugging and to onboarding new users.
Appendix: Further reading
- Portillo, del Pozo, Rodríguez-Galán, Segurado, Romero. MUESLI: A Material UnivErSal LIbrary. Advances in Engineering Software, 105, 1-8.
- Project website and release notes for MUESLI.
- Structural and reduced-model papers that build constrained section models on top of 3D constitutive updates.
- Calibration studies using Johnson-Cook, Zerilli-Armstrong, and Arrhenius-type laws implemented in MUESLI.
Closing remarks
The value of a constitutive library is not only the number of models it contains, but the discipline with which those models are organized, verified, and reused. MUESLI is most effective when each constitutive family has a clear contract, each model has a clean thermodynamic statement, and each adapter keeps the constitutive core independent from the solver that calls it.