Source code for pulse.viscoelasticity

import logging
from abc import ABC, abstractmethod
from dataclasses import dataclass, field

import ufl

from .units import Variable

logger = logging.getLogger(__name__)


[docs] @dataclass class ViscoElasticity(ABC):
[docs] @abstractmethod def strain_energy(self, C_dot) -> ufl.Form: """Strain energy density function. Parameters ---------- C_dot : ufl.core.expr.Expr The time derivative of the deformation gradient (strain rate) Returns ------- ufl.Form The strain energy density function """ ...
[docs] def S(self, C_dot: ufl.core.expr.Expr) -> ufl.core.expr.Expr: """Cauchy stress tensor for the viscoelasticity model. Parameters ---------- C_dot : ufl.core.expr.Expr The time derivative of the deformation gradient (strain rate) Returns ------- ufl.core.expr.Expr The Cauchy stress tensor """ return 2.0 * ufl.diff(self.strain_energy(C_dot), C_dot)
[docs] def P(self, F_dot: ufl.core.expr.Expr | None = None) -> ufl.core.expr.Expr: """First Piola-Kirchhoff stress for the viscoelasticity model.""" if F_dot is None: raise ValueError("F_dot must be provided for P calculation.") C_dot = F_dot.T * F_dot return ufl.diff(self.strain_energy(C_dot), F_dot)
[docs] class NoneViscoElasticity(ViscoElasticity):
[docs] def strain_energy(self, C_dot: ufl.core.expr.Expr) -> ufl.core.expr.Expr: return 0.0
[docs] @dataclass class Viscous(ViscoElasticity): eta: Variable = field(default_factory=lambda: Variable(1e2, "Pa s")) def __post_init__(self): if not isinstance(self.eta, Variable): unit = "Pa s" logger.warning("Setting eta to %s %s", self.eta, unit) self.eta = Variable(self.eta, unit)
[docs] def strain_energy(self, C_dot) -> ufl.Form: E_dot = 0.5 * C_dot eta = self.eta.to_base_units() return 0.5 * eta * ufl.tr(E_dot * E_dot)
def __str__(self): return "0.5\u03b7 tr (E_dot E_dot)"