Constitutive laws

GenSec is material-agnostic: any stress-strain relationship that implements the Material interface can be used. Three built-in laws and a generic tabulated law are provided.

Abstract interface

Every material must implement:

  • stress(eps) — evaluate \(\sigma(\varepsilon)\) for a scalar strain.

  • stress_array(eps) — vectorized evaluation over a NumPy array of arbitrary shape (1-D, 2-D, …).

  • tangent(eps) — scalar tangent modulus \(E_t = d\sigma/d\varepsilon\).

  • tangent_array(eps) — vectorized tangent modulus over an array of arbitrary shape.

  • eps_min / eps_max — admissible strain range, consumed by the N-M diagram generator to determine scan bounds.

The tangent modulus methods are used by the analytical Jacobian in the Newton-Raphson solver (see Solver pipeline). The base class provides a finite-difference fallback for both tangent and tangent_array, so existing custom materials continue to work without modification.

Optional Numba acceleration

When numba is installed (pip install gensec[fast]), the built-in Concrete and Steel classes automatically use JIT-compiled kernels for stress_array and tangent_array. If Numba is not available, pure-NumPy fallbacks are used transparently.

Concrete — parabola-rectangle (EC2 3.1.7)

The compression branch follows the parabola-rectangle law per EN 1992-1-1, §3.1.7. An optional linear-elastic tension branch can be activated for serviceability checks or nonlinear analyses.

Compression (\(\varepsilon \le 0\))

\[\begin{split}\sigma_c(\varepsilon) = \begin{cases} -f_{cd}\!\left[1 - \left(1 - \dfrac{\varepsilon} {\varepsilon_{c2}}\right)^{\!n}\right] & \varepsilon_{c2} \le \varepsilon \le 0 \\[4pt] -f_{cd} & \varepsilon_{cu2} \le \varepsilon < \varepsilon_{c2} \\[4pt] 0 & \varepsilon < \varepsilon_{cu2} \end{cases}\end{split}\]

where:

  • \(f_{cd} = \alpha_{cc}\,f_{ck}/\gamma_c\) is the design compressive strength,

  • \(\varepsilon_{c2}\) is the strain at peak stress (default \(-0.002\)),

  • \(\varepsilon_{cu2}\) is the ultimate compressive strain (default \(-0.0035\)),

  • \(n\) is the parabolic exponent (default 2.0).

The stress is negative (compressive) by sign convention.

For high-strength concrete (\(f_{ck} > 50\;\text{MPa}\)), the parameters \(\varepsilon_{c2}\), \(\varepsilon_{cu2}\), and \(n\) deviate from the standard values and must be taken from EC2 Table 3.1. The factory function concrete_from_ec2() computes them automatically.

Tension (\(\varepsilon > 0\)) — optional

By default, concrete carries no tensile stress (\(\sigma = 0\) for \(\varepsilon > 0\)). This is the correct assumption for ULS verifications with the parabola-rectangle law.

When both fct and Ec are set to positive values, a linear tension branch is activated:

\[\begin{split}\sigma_c(\varepsilon) = \begin{cases} E_c \, \varepsilon & 0 < \varepsilon \le \varepsilon_{ct} \\[4pt] 0 & \varepsilon > \varepsilon_{ct} \end{cases}\end{split}\]

where \(\varepsilon_{ct} = f_{ct} / E_c\) is the cracking strain. Beyond \(\varepsilon_{ct}\) the concrete is fully cracked and carries no stress.

This branch is useful for:

  • SLS checks — stress limitation, crack width estimation.

  • Nonlinear analysis — capturing the uncracked stiffness.

  • Prestressed sections — where concrete may remain uncracked under service loads.

The fct value should be chosen to match the verification context: \(f_{ctd,0.05}\) (design), \(f_{ctm}\) (mean), or \(f_{ctk,0.05}\) (characteristic).

When using the concrete_ec2 YAML type, setting enable_tension: true automatically populates fct and Ec from the EC2 property object. The tension_fct field controls which tensile strength is used (see yaml_reference).

With the tension branch active, the admissible strain range becomes \([\varepsilon_{cu2},\, \varepsilon_{ct}]\); when disabled it remains \([\varepsilon_{cu2},\, 0]\).

Tangent modulus (concrete)

The analytical tangent modulus \(E_t = d\sigma_c / d\varepsilon\) is:

\[\begin{split}E_t(\varepsilon) = \begin{cases} E_c & 0 < \varepsilon \le \varepsilon_{ct} \;\text{(tension enabled)} \\[4pt] -\dfrac{f_{cd}\,n}{\varepsilon_{c2}} \left(1 - \dfrac{\varepsilon}{\varepsilon_{c2}}\right)^{n-1} & \varepsilon_{c2} < \varepsilon \le 0 \\[4pt] 0 & \text{otherwise (plateau, beyond ultimate, post-cracking)} \end{cases}\end{split}\]

This is used by the analytical Jacobian in the Newton-Raphson solver to avoid finite-difference perturbations.

Reinforcing steel — elastic-plastic with hardening

\[\begin{split}\sigma_s(\varepsilon) = \begin{cases} E_s\,\varepsilon & |\varepsilon| \le \varepsilon_{yd} \\[4pt] \mathrm{sign}(\varepsilon)\!\left[f_{yd} + (f_{td} - f_{yd})\, \dfrac{|\varepsilon| - \varepsilon_{yd}} {\varepsilon_{su} - \varepsilon_{yd}}\right] & \varepsilon_{yd} < |\varepsilon| \le \varepsilon_{su} \\[4pt] 0 & |\varepsilon| > \varepsilon_{su} \end{cases}\end{split}\]

where:

  • \(f_{yd} = f_{yk}/\gamma_s\) is the design yield strength,

  • \(f_{td} = k \cdot f_{yd}\) with \(k =\) k_hardening (ratio \(f_t/f_y\); 1.0 = perfectly plastic),

  • \(\varepsilon_{yd} = f_{yd}/E_s\) is the yield strain,

  • \(\varepsilon_{su}\) is the ultimate strain.

The law is symmetric in tension and compression by default. Set works_in_compression = False to suppress compressive stress (useful for modelling FRP or tendons that buckle in compression).

Tangent modulus (steel)

\[\begin{split}E_t(\varepsilon) = \begin{cases} E_s & |\varepsilon| \le \varepsilon_{yd} \\[4pt] \dfrac{f_{td} - f_{yd}} {\varepsilon_{su} - \varepsilon_{yd}} & \varepsilon_{yd} < |\varepsilon| \le \varepsilon_{su} \\[4pt] 0 & |\varepsilon| > \varepsilon_{su} \end{cases}\end{split}\]

Structural steel (EN 10025-2)

Uses the same elastic-plastic model as reinforcing steel, but yield and ultimate strengths are computed from plate thickness according to NF EN 10025-2 Table 7. The factory function steel_from_en10025() handles the lookup.

Supported grades: S235, S275, S355.

The hardening ratio \(k = f_u/f_y\) is computed automatically from the tabulated \(f_u\) and thickness-dependent \(f_y\).

Tabulated material

For materials not covered by the built-in laws (CFRP, timber, FRP bars, shotcrete, etc.), TabulatedMaterial accepts an arbitrary set of \((\varepsilon_i,\,\sigma_i)\) data points and interpolates linearly between them.

Strains outside the table range produce \(\sigma = 0\) (material failure / rupture).

from gensec.materials import TabulatedMaterial

cfrp = TabulatedMaterial(
    strains=[0.0, 0.017],
    stresses=[0.0, 2800.0],
    name="CFRP",
)

The tabulated law is fully compatible with all solvers and diagram generators. The strain limits eps_min / eps_max are inferred from the first and last data points.