Source code for hyperelastic.lab._simulation

import numpy as np

from ._plotting import LabPlotter


[docs] class Simulation(LabPlotter): """Results of a simulation along with methods to convert and plot the data. Attributes ---------- loadcase : class A class with methods for evaluating the deformation gradient and the stress as normal force per undeformed area, e.g. :class:`Uniaxial <.lab.Uniaxial>`. stretch : ndarray The stretch as the ratio of the deformed vs. the undeformed length. labels : list of str A list of the material parameter labels. material : class A class with a method for evaluating the gradient of the strain energy function w.r.t. the deformation gradient, e.g. :class:`DistortionalSpace <.DistortionalSpace>`. parameters : array_like The material parameters. Examples -------- The material model response behaviour of a hyperelastic material model formulation is evaluated for a :class:`uniaxial tension <.lab.Uniaxial>` load case. A given stretch data is used to create the :class:`Simulation <.lab.Simulation>` object. >>> import numpy as np >>> import hyperelastic >>> from hyperelastic import lab >>> >>> stretch = np.linspace(0.7, 2.5, 181) A function which takes the material parameters and returns the hyperelastic constitutive material formulation has to be provided for the simulation objects. Here, we use an isotropic invariant-based :class:`third-order deformation <.models.invariants.ThirdOrderDeformation>` material formulation. >>> def material(**kwargs): >>> "A third-order deformation material formulation." >>> >>> tod = hyperelastic.models.invariants.ThirdOrderDeformation(**kwargs) >>> framework = hyperelastic.InvariantsFramework(tod) >>> >>> return hyperelastic.DeformationSpace(framework) A list of (string) labels is used to apply the list or array of parameter values to the material formulation. >>> simulation = lab.Simulation( >>> loadcase=lab.Uniaxial(), >>> stretch=stretch, >>> material=material, >>> labels=["C10", "C01", "C11", "C20", "C30"], >>> parameters=[0.4, 0.1, 0.02, -0.04, 0.01], >>> ) The stress-stretch plot returns a figure which visualizes the force per undeformed area vs. the ratio of the undeformed and deformed length. >>> fig, ax = simulation.plot_stress_stretch() >>> >>> ax.legend() >>> ax.set_title("Third-Order Deformation") .. image:: images/fig_simulation-tod.png """ def __init__(self, loadcase, stretch, labels, material, parameters=None): """Initialize the results of a simulation. Parameters ---------- loadcase : class A class with methods for evaluating the deformation gradient and the stress as normal force per undeformed area, e.g. :class:`Uniaxial <.lab.Uniaxial>`. stretch : ndarray The stretch as the ratio of the deformed vs. the undeformed length. labels : list of str A list of the material parameter labels. material : class A class with a method for evaluating the gradient of the strain energy function w.r.t. the deformation gradient, e.g. :class:`DistortionalSpace <.DistortionalSpace>`. parameters : array_like or None, optional The material parameters (default is None). """ super().__init__() self.loadcase = loadcase self.stretch = stretch self.labels = labels self.parameters = parameters self.material = material self.label = loadcase.label if self.parameters is None: self.parameters = np.ones(len(self.labels))
[docs] def stress_curve_fit(self, x, *parameters): """Evaluate the stress as force per undeformed area for given material parameters.""" kwargs = {label: p for label, p in zip(self.labels, parameters)} mat = self.material(**kwargs) F = self.loadcase.defgrad(x) P = mat.gradient([F.reshape(3, 3, 1, -1), None])[0].reshape(3, 3, -1) return self.loadcase.stress(F, P)
[docs] def stress(self): "Evaluate the stress as force per undeformed area." return self.stress_curve_fit(self.stretch, *self.parameters)