Source code for felupe.constitution.strain.models._linear_elastic_viscoelastic

# -*- coding: utf-8 -*-
"""
This file is part of FElupe.

FElupe is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

FElupe is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with FElupe.  If not, see <http://www.gnu.org/licenses/>.
"""

import numpy as np

from ....math import cdya_ik, dev, dya, identity, trace


[docs] def linear_elastic_viscoelastic(, εn, σn, ζn, λ, μ, G, τ, Δt, **kwargs): r"""3D linear-elastic viscoelastic material formulation to be used in :class:`~felupe.MaterialStrain`. Arguments --------- dε : ndarray Strain increment. εn : ndarray Old strain tensor. σn : ndarray Old stress tensor. ζn : list List of old state variables. λ : float First Lamé-constant. μ : float Second Lamé-constant (shear modulus). G : list of float List of deviatoric viscoelastic shear moduli. τ : list of float List of time constants for deviatoric viscoelastic shear moduli. Δt : float Time increment. **kwargs Additional keyword arguments. tangent : bool A flag to evaluate the elasticity tensor. Returns ------- dσdε : ndarray Elasticity tensor. σ : ndarray (New) stress tensor. ζ : list List of new state variables. Notes ----- The stress consists of a long-term elastic and a deviatoric viscoelastic stress part, see Eq. :eq:`total-stress`. .. math:: :label: total-stress \boldsymbol{\sigma} = \boldsymbol{\sigma}_e + \boldsymbol{\sigma}_v The long-term elastic part is given in Eq. :eq:`elastic-stress`. .. math:: :label: elastic-stress \boldsymbol{\sigma}_e = 2 \mu\ \boldsymbol{\varepsilon} + \lambda \operatorname{tr}(\boldsymbol{\varepsilon}) \boldsymbol{1} The i-th viscous part is given in Eq. :eq:`visco-stress`, .. math:: :label: visco-stress \dot{\boldsymbol{\sigma}}_{v,i} + \frac{1}{\tau_i} \boldsymbol{\sigma}_{v,i} &= 2 G_i \operatorname{dev}\left( \dot{\boldsymbol{\varepsilon}} \right) \boldsymbol{\sigma}_{v,i} &= a_i\ \boldsymbol{\sigma}_{v,i}^n + b_i \operatorname{dev} \left( \boldsymbol{\varepsilon} - \boldsymbol{\varepsilon}_n \right) with the coefficients as denoted in Eq. :eq:`visco-coeff`. .. math:: :label: visco-coeff a_i &= \exp \left( -\Delta t / \tau_i \right) b_i &= \frac{2 G_i\ \tau_i (1 - a_i)}{\Delta t} The total fourth-order elasticity tensor is given in Eq. :eq:`fourth-order-visco`. .. math:: :label: fourth-order-visco \mathbb{C} = 2 \bar{\mu} \ \boldsymbol{1} \odot \boldsymbol{1} + \bar{\lambda}\ \boldsymbol{1} \otimes \boldsymbol{1} The effective coefficients are summarized in Eq. :eq:`visco-coeff-tangent`. .. math:: :label: visco-coeff-tangent \bar{\mu} &= \mu + \sum_{i=1}^N \frac{b_i}{2} \bar{\lambda} &= \lambda - \frac{2}{3} \left( \bar{\mu} - \mu \right) Examples -------- .. plot:: >>> import felupe as fem >>> >>> umat = fem.MaterialStrain( ... material=fem.linear_elastic_viscoelastic, ... λ=2.0, ... μ=1.0, ... G=[3.0, 2.0], ... τ=[10.0, 100.0], ... Δt=5.0, ... statevars=((2, 3, 3),), ... ) >>> ux = fem.math.linsteps([1, 2, 1, 2, 1, 2, 1], num=20) >>> ax = umat.plot(ux=ux, bx=None, ps=None) See Also -------- MaterialStrain : A strain-based user-defined material definition with a given function for the stress tensor and the (fourth-order) elasticity tensor. """ # helpers eye = identity(dim=3, shape=(1, 1)) # new elastic stress (old stress σn is not used because of included viscoelasticity) ε = εn + σ = 2 * μ * ε + λ * trace(ε) * eye # update deviatoric viscoelastic stress dev_dε = dev() a = [np.exp(-Δt / τi) for τi in τ] b = [2 * Gi * (1 - ai) * τi / Δt for Gi, ai, τi in zip(G, a, τ)] # Alternative method: backward-Euler # a = [1 / (1 + Δt / τi) for τi in τ] # b = [2 * Gi * ai for Gi, ai in zip(G, a)] # update of new deviatoric viscoelastic stress σvn = ζn[0] σv = σvn.copy() for i, σvni in enumerate(ζn[0]): σv[i] = a[i] * σvni + b[i] * dev_dε # evaluate elasticity tensor if kwargs["tangent"]: μ_eff = μ + np.sum(b, axis=0) / 2 λ_eff = λ - 2 / 3 * (μ_eff - μ) dσdε = 2 * μ_eff * cdya_ik(eye, eye) + λ_eff * dya(eye, eye) else: dσdε = None # new total stress σ += np.sum(σv, axis=0) # new state variables ζ = [σv] return dσdε, σ, ζ