Source code for pyfem.materials.ThoulessModeI

# SPDX-License-Identifier: MIT
# Copyright (c) 2011–2026 Joris J.C. Remmers

from typing import Any, Mapping, Tuple

import numpy as np

from pyfem.materials.BaseMaterial import BaseMaterial


[docs] class ThoulessModeI(BaseMaterial): """Mode-I cohesive zone model following Thouless. Parameters ---------- props : Mapping[str, Any] Material properties expected by ``BaseMaterial`` to populate the attributes used here, notably ``Gc``, ``d1d3``, ``d2d3`` and ``Tult``. """ def __init__(self, props: Mapping[str, Any]) -> None: """Initialize the material model and derived parameters. The base class processes ``props`` and defines attributes like ``Gc``, ``d1d3``, ``d2d3`` and ``Tult`` which are used to compute the internal parameters ``d1``, ``d2`` and ``d3``. """ # Call the BaseMaterial constructor BaseMaterial.__init__(self, props) self.d3: float = 2.0 * self.Gc / ((-self.d1d3 + self.d2d3 + 1.0) * self.Tult) self.d1: float = self.d1d3 * self.d3 self.d2: float = self.d2d3 * self.d3 self.dummy: float = self.Tult / self.d1 # Set the labels for the output data in this material model self.outLabels: list[str] = ["Tn", "Ts"]
[docs] def getStress(self, deformation: Any) -> Tuple[np.ndarray, np.ndarray]: """Compute traction and consistent algorithmic tangent. Expects ``deformation.strain`` to provide the normal opening at index 0. Only the normal traction component is modeled in this material; the shear traction remains zero. Parameters ---------- deformation : Any Object with attribute ``strain`` (NumPy array-like) containing the normal opening at index 0. Returns ------- Tuple[np.ndarray, np.ndarray] A tuple ``(stress, tang)`` where ``stress`` is a length-2 array ``[Tn, Ts]`` and ``tang`` is the 2x2 algorithmic tangent. Only the ``(0, 0)`` component is non-zero in this model. Notes ----- Also updates ``self.outData`` with the computed ``stress``. """ stress = np.zeros(2) tang = np.zeros((2, 2)) eps_n = deformation.strain[0] if eps_n < self.d1: stress[0] = self.dummy * eps_n tang[0, 0] = self.dummy elif self.d1 <= eps_n < self.d2: stress[0] = self.Tult tang[0, 0] = 0.0 elif self.d2 <= eps_n < self.d3: stress[0] = self.Tult * (1.0 - (eps_n - self.d2) / (self.d3 - self.d2)) tang[0, 0] = self.Tult * (-1.0) / (self.d3 - self.d2) else: stress[0] = 0.0 tang[0, 0] = 0.0 self.outData = stress return stress, tang