def S(self, u_, p_, ivar=None, tang=False):

        C_ = variable(self.kin.C(u_))

        stress = constantvalue.zero((3, 3))

        # volumetric (kinematic) growth
        if self.mat_growth:

            theta_ = ivar["theta"]

            # material has to be evaluated with C_e only, however total S has
            # to be computed by differentiating w.r.t. C (S = 2*dPsi/dC)
            self.mat = materiallaw(self.C_e(C_, theta_), self.I)

        else:

            self.mat = materiallaw(C_, self.I)

        m = 0
        for matlaw in self.matmodels:

            stress += self.add_stress_mat(matlaw, self.matparams[m], ivar, C_)

            m += 1

        # add remodeled material
        if self.mat_growth and self.mat_remodel:

            self.stress_base = stress

            self.stress_remod = constantvalue.zero((3, 3))

            m = 0
            for matlaw in self.matmodels_remod:

                self.stress_remod += self.add_stress_mat(
                    matlaw, self.matparams_remod[m], ivar, C_)

                m += 1

            # update the stress expression: S = (1-phi(theta)) * S_base + phi(theta) * S_remod
            stress = (
                1. - self.phi_remod(theta_)
            ) * self.stress_base + self.phi_remod(theta_) * self.stress_remod

        # if we have p (hydr. pressure) as variable in a 2-field functional
        if self.incompr_2field:
            if self.mat_growth:
                # TeX: S_{\mathrm{vol}} = -2 \frac{\partial[p(J^{\mathrm{e}}-1)]}{\partial \boldsymbol{C}}
                stress += -2. * diff(
                    p_ * (sqrt(det(self.C_e(C_, theta_))) - 1.), C_)
            else:
                # TeX: S_{\mathrm{vol}} = -2 \frac{\partial[p(J-1)]}{\partial \boldsymbol{C}} = -Jp\boldsymbol{C}^{-1}
                stress += -2. * diff(p_ * (sqrt(det(C_)) - 1.), C_)

        if tang:
            return 2. * diff(stress, C_)
        else:
            return stress
Пример #2
0
 def stress(self, strain, alpha):
     # Differentiate the elastic energy w.r.t. the strain tensor
     eps_ = ufl.variable(strain)
     # Derivative of energy w.r.t. the strain tensor to obtain the stress
     # tensor
     sigma = ufl.diff(self.elastic_energy_density_strain(eps_, alpha), eps_)
     return sigma
Пример #3
0
def hyperelasticity(domain, q, p, nf=0):
    # Based on https://github.com/firedrakeproject/firedrake-bench/blob/experiments/forms/firedrake_forms.py
    V = ufl.FunctionSpace(domain, ufl.VectorElement('P', domain.ufl_cell(), q))
    P = ufl.FunctionSpace(domain, ufl.VectorElement('P', domain.ufl_cell(), p))
    v = ufl.TestFunction(V)
    du = ufl.TrialFunction(V)  # Incremental displacement
    u = ufl.Coefficient(V)     # Displacement from previous iteration
    B = ufl.Coefficient(V)     # Body force per unit mass
    # Kinematics
    I = ufl.Identity(domain.ufl_cell().topological_dimension())
    F = I + ufl.grad(u)        # Deformation gradient
    C = F.T*F                  # Right Cauchy-Green tensor
    E = (C - I)/2              # Euler-Lagrange strain tensor
    E = ufl.variable(E)
    # Material constants
    mu = ufl.Constant(domain)  # Lame's constants
    lmbda = ufl.Constant(domain)
    # Strain energy function (material model)
    psi = lmbda/2*(ufl.tr(E)**2) + mu*ufl.tr(E*E)
    S = ufl.diff(psi, E)       # Second Piola-Kirchhoff stress tensor
    PK = F*S                   # First Piola-Kirchoff stress tensor
    # Variational problem
    it = ufl.inner(PK, ufl.grad(v)) - ufl.inner(B, v)
    f = [ufl.Coefficient(P) for _ in range(nf)]
    return ufl.derivative(reduce(ufl.inner,
                                 list(map(ufl.div, f)) + [it])*ufl.dx, u, du)
def s(e):
    """
    Stress as function of strain from strain energy function
    """
    e = ufl.variable(e)
    W = lamé_μ * e * e + lamé_λ / 2 * e**2  # Saint-Venant Kirchhoff
    s = ufl.diff(W, e)
    return s
Пример #5
0
def S(E):
    """
    Stress as function of strain from strain energy function
    """
    E = ufl.variable(E)
    W = lamé_μ * ufl.inner(E, E) + lamé_λ / 2 * ufl.tr(E)**2  # Saint-Venant Kirchhoff
    S = ufl.diff(W, E)
    return S
Пример #6
0
def eigenstate_legacy(A):
    """Eigenvalues and eigenprojectors of the 3x3 (real-valued) tensor A.
    Provides the spectral decomposition A = sum_{a=0}^{2} λ_a * E_a
    with eigenvalues λ_a and their associated eigenprojectors E_a = n_a^R x n_a^L
    ordered by magnitude.
    The eigenprojectors of eigenvalues with multiplicity n are returned as 1/n-fold projector.

    Note: Tensor A must not have complex eigenvalues!
    """
    if ufl.shape(A) != (3, 3):
        raise RuntimeError(
            f"Tensor A of shape {ufl.shape(A)} != (3, 3) is not supported!")
    #
    eps = 1.0e-10
    #
    A = ufl.variable(A)
    #
    # --- determine eigenvalues λ0, λ1, λ2
    #
    # additively decompose: A = tr(A) / 3 * I + dev(A) = q * I + B
    q = ufl.tr(A) / 3
    B = A - q * ufl.Identity(3)
    # observe: det(λI - A) = 0  with shift  λ = q + ω --> det(ωI - B) = 0 = ω**3 - j * ω - b
    j = ufl.tr(
        B * B
    ) / 2  # == -I2(B) for trace-free B, j < 0 indicates A has complex eigenvalues
    b = ufl.tr(B * B * B) / 3  # == I3(B) for trace-free B
    # solve: 0 = ω**3 - j * ω - b  by substitution  ω = p * cos(phi)
    #        0 = p**3 * cos**3(phi) - j * p * cos(phi) - b  | * 4 / p**3
    #        0 = 4 * cos**3(phi) - 3 * cos(phi) - 4 * b / p**3  | --> p := sqrt(j * 4 / 3)
    #        0 = cos(3 * phi) - 4 * b / p**3
    #        0 = cos(3 * phi) - r                  with  -1 <= r <= +1
    #    phi_k = [acos(r) + (k + 1) * 2 * pi] / 3  for  k = 0, 1, 2
    p = 2 / ufl.sqrt(3) * ufl.sqrt(j + eps**2)  # eps: MMM
    r = 4 * b / p**3
    r = ufl.Max(ufl.Min(r, +1 - eps), -1 + eps)  # eps: LMM, MMH
    phi = ufl.acos(r) / 3
    # sorted eigenvalues: λ0 <= λ1 <= λ2
    λ0 = q + p * ufl.cos(phi + 2 / 3 * ufl.pi)  # low
    λ1 = q + p * ufl.cos(phi + 4 / 3 * ufl.pi)  # middle
    λ2 = q + p * ufl.cos(phi)  # high
    #
    # --- determine eigenprojectors E0, E1, E2
    #
    E0 = ufl.diff(λ0, A).T
    E1 = ufl.diff(λ1, A).T
    E2 = ufl.diff(λ2, A).T
    #
    return [λ0, λ1, λ2], [E0, E1, E2]
Пример #7
0
def eigenstate(A):
    """Eigenvalues and eigenprojectors of the 3x3 (real-valued) tensor A.
    Provides the spectral decomposition A = sum_{a=0}^{2} λ_a * E_a
    with (ordered) eigenvalues λ_a and their associated eigenprojectors E_a = n_a^R x n_a^L.

    Note: Tensor A must not have complex eigenvalues!
    """
    if ufl.shape(A) != (3, 3):
        raise RuntimeError(
            f"Tensor A of shape {ufl.shape(A)} != (3, 3) is not supported!")
    #
    eps = 3.0e-16  # slightly above 2**-(53 - 1), see https://en.wikipedia.org/wiki/IEEE_754
    #
    A = ufl.variable(A)
    #
    # --- determine eigenvalues λ0, λ1, λ2
    #
    I1, I2, I3 = invariants_principal(A)
    dq = 2 * I1**3 - 9 * I1 * I2 + 27 * I3
    #
    Δx = [
        A[0, 1] * A[1, 2] * A[2, 0] - A[0, 2] * A[1, 0] * A[2, 1],
        A[0, 1]**2 * A[1, 2] - A[0, 1] * A[0, 2] * A[1, 1] +
        A[0, 1] * A[0, 2] * A[2, 2] - A[0, 2]**2 * A[2, 1],
        A[0, 0] * A[0, 1] * A[2, 1] - A[0, 1]**2 * A[2, 0] -
        A[0, 1] * A[2, 1] * A[2, 2] + A[0, 2] * A[2, 1]**2,
        A[0, 0] * A[0, 2] * A[1, 2] + A[0, 1] * A[1, 2]**2 -
        A[0, 2]**2 * A[1, 0] - A[0, 2] * A[1, 1] * A[1, 2],
        A[0, 0] * A[0, 1] * A[1, 2] - A[0, 1] * A[0, 2] * A[1, 0] -
        A[0, 1] * A[1, 2] * A[2, 2] +
        A[0, 2] * A[1, 2] * A[2, 1],  # noqa: E501
        A[0, 0] * A[0, 2] * A[2, 1] - A[0, 1] * A[0, 2] * A[2, 0] +
        A[0, 1] * A[1, 2] * A[2, 1] -
        A[0, 2] * A[1, 1] * A[2, 1],  # noqa: E501
        A[0, 1] * A[1, 0] * A[1, 2] - A[0, 2] * A[1, 0] * A[1, 1] +
        A[0, 2] * A[1, 0] * A[2, 2] -
        A[0, 2] * A[1, 2] * A[2, 0],  # noqa: E501
        A[0, 0]**2 * A[1, 2] - A[0, 0] * A[0, 2] * A[1, 0] -
        A[0, 0] * A[1, 1] * A[1, 2] - A[0, 0] * A[1, 2] * A[2, 2] +
        A[0, 1] * A[1, 0] * A[1, 2] + A[0, 2] * A[1, 0] * A[2, 2] +
        A[1, 1] * A[1, 2] * A[2, 2] - A[1, 2]**2 * A[2, 1],  # noqa: E501
        A[0, 0]**2 * A[1, 2] - A[0, 0] * A[0, 2] * A[1, 0] -
        A[0, 0] * A[1, 1] * A[1, 2] - A[0, 0] * A[1, 2] * A[2, 2] +
        A[0, 2] * A[1, 0] * A[1, 1] + A[0, 2] * A[1, 2] * A[2, 0] +
        A[1, 1] * A[1, 2] * A[2, 2] - A[1, 2]**2 * A[2, 1],  # noqa: E501
        A[0, 0] * A[0, 1] * A[1, 1] - A[0, 0] * A[0, 1] * A[2, 2] -
        A[0, 1]**2 * A[1, 0] + A[0, 1] * A[0, 2] * A[2, 0] -
        A[0, 1] * A[1, 1] * A[2, 2] + A[0, 1] * A[2, 2]**2 +
        A[0, 2] * A[1, 1] * A[2, 1] -
        A[0, 2] * A[2, 1] * A[2, 2],  # noqa: E501
        A[0, 0] * A[0, 1] * A[1, 1] - A[0, 0] * A[0, 1] * A[2, 2] +
        A[0, 0] * A[0, 2] * A[2, 1] - A[0, 1]**2 * A[1, 0] -
        A[0, 1] * A[1, 1] * A[2, 2] + A[0, 1] * A[1, 2] * A[2, 1] +
        A[0, 1] * A[2, 2]**2 - A[0, 2] * A[2, 1] * A[2, 2],  # noqa: E501
        A[0, 0] * A[0, 1] * A[1, 2] - A[0, 0] * A[0, 2] * A[1, 1] +
        A[0, 0] * A[0, 2] * A[2, 2] - A[0, 1] * A[1, 1] * A[1, 2] -
        A[0, 2]**2 * A[2, 0] + A[0, 2] * A[1, 1]**2 -
        A[0, 2] * A[1, 1] * A[2, 2] +
        A[0, 2] * A[1, 2] * A[2, 1],  # noqa: E501
        A[0, 0] * A[0, 2] * A[1, 1] - A[0, 0] * A[0, 2] * A[2, 2] -
        A[0, 1] * A[0, 2] * A[1, 0] + A[0, 1] * A[1, 1] * A[1, 2] -
        A[0, 1] * A[1, 2] * A[2, 2] + A[0, 2]**2 * A[2, 0] -
        A[0, 2] * A[1, 1]**2 + A[0, 2] * A[1, 1] * A[2, 2],  # noqa: E501
        A[0, 0]**2 * A[1, 1] - A[0, 0]**2 * A[2, 2] -
        A[0, 0] * A[0, 1] * A[1, 0] + A[0, 0] * A[0, 2] * A[2, 0] -
        A[0, 0] * A[1, 1]**2 + A[0, 0] * A[2, 2]**2 +
        A[0, 1] * A[1, 0] * A[1, 1] - A[0, 2] * A[2, 0] * A[2, 2] +
        A[1, 1]**2 * A[2, 2] - A[1, 1] * A[1, 2] * A[2, 1] -
        A[1, 1] * A[2, 2]**2 + A[1, 2] * A[2, 1] * A[2, 2]
    ]  # noqa: E501
    Δy = [
        A[0, 2] * A[1, 0] * A[2, 1] - A[0, 1] * A[1, 2] * A[2, 0],
        A[1, 0]**2 * A[2, 1] - A[1, 0] * A[1, 1] * A[2, 0] +
        A[1, 0] * A[2, 0] * A[2, 2] - A[1, 2] * A[2, 0]**2,
        A[0, 0] * A[1, 0] * A[1, 2] - A[0, 2] * A[1, 0]**2 -
        A[1, 0] * A[1, 2] * A[2, 2] + A[1, 2]**2 * A[2, 0],
        A[0, 0] * A[2, 0] * A[2, 1] - A[0, 1] * A[2, 0]**2 +
        A[1, 0] * A[2, 1]**2 - A[1, 1] * A[2, 0] * A[2, 1],
        A[0, 0] * A[1, 0] * A[2, 1] - A[0, 1] * A[1, 0] * A[2, 0] -
        A[1, 0] * A[2, 1] * A[2, 2] +
        A[1, 2] * A[2, 0] * A[2, 1],  # noqa: E501
        A[0, 0] * A[1, 2] * A[2, 0] - A[0, 2] * A[1, 0] * A[2, 0] +
        A[1, 0] * A[1, 2] * A[2, 1] -
        A[1, 1] * A[1, 2] * A[2, 0],  # noqa: E501
        A[0, 1] * A[1, 0] * A[2, 1] - A[0, 1] * A[1, 1] * A[2, 0] +
        A[0, 1] * A[2, 0] * A[2, 2] -
        A[0, 2] * A[2, 0] * A[2, 1],  # noqa: E501
        A[0, 0]**2 * A[2, 1] - A[0, 0] * A[0, 1] * A[2, 0] -
        A[0, 0] * A[1, 1] * A[2, 1] - A[0, 0] * A[2, 1] * A[2, 2] +
        A[0, 1] * A[1, 0] * A[2, 1] + A[0, 1] * A[2, 0] * A[2, 2] +
        A[1, 1] * A[2, 1] * A[2, 2] - A[1, 2] * A[2, 1]**2,  # noqa: E501
        A[0, 0]**2 * A[2, 1] - A[0, 0] * A[0, 1] * A[2, 0] -
        A[0, 0] * A[1, 1] * A[2, 1] - A[0, 0] * A[2, 1] * A[2, 2] +
        A[0, 1] * A[1, 1] * A[2, 0] + A[0, 2] * A[2, 0] * A[2, 1] +
        A[1, 1] * A[2, 1] * A[2, 2] - A[1, 2] * A[2, 1]**2,  # noqa: E501
        A[0, 0] * A[1, 0] * A[1, 1] - A[0, 0] * A[1, 0] * A[2, 2] -
        A[0, 1] * A[1, 0]**2 + A[0, 2] * A[1, 0] * A[2, 0] -
        A[1, 0] * A[1, 1] * A[2, 2] + A[1, 0] * A[2, 2]**2 +
        A[1, 1] * A[1, 2] * A[2, 0] -
        A[1, 2] * A[2, 0] * A[2, 2],  # noqa: E501
        A[0, 0] * A[1, 0] * A[1, 1] - A[0, 0] * A[1, 0] * A[2, 2] +
        A[0, 0] * A[1, 2] * A[2, 0] - A[0, 1] * A[1, 0]**2 -
        A[1, 0] * A[1, 1] * A[2, 2] + A[1, 0] * A[1, 2] * A[2, 1] +
        A[1, 0] * A[2, 2]**2 - A[1, 2] * A[2, 0] * A[2, 2],  # noqa: E501
        A[0, 0] * A[1, 0] * A[2, 1] - A[0, 0] * A[1, 1] * A[2, 0] +
        A[0, 0] * A[2, 0] * A[2, 2] - A[0, 2] * A[2, 0]**2 -
        A[1, 0] * A[1, 1] * A[2, 1] + A[1, 1]**2 * A[2, 0] -
        A[1, 1] * A[2, 0] * A[2, 2] +
        A[1, 2] * A[2, 0] * A[2, 1],  # noqa: E501
        A[0, 0] * A[1, 1] * A[2, 0] - A[0, 0] * A[2, 0] * A[2, 2] -
        A[0, 1] * A[1, 0] * A[2, 0] + A[0, 2] * A[2, 0]**2 +
        A[1, 0] * A[1, 1] * A[2, 1] - A[1, 0] * A[2, 1] * A[2, 2] -
        A[1, 1]**2 * A[2, 0] + A[1, 1] * A[2, 0] * A[2, 2],  # noqa: E501
        A[0, 0]**2 * A[1, 1] - A[0, 0]**2 * A[2, 2] -
        A[0, 0] * A[0, 1] * A[1, 0] + A[0, 0] * A[0, 2] * A[2, 0] -
        A[0, 0] * A[1, 1]**2 + A[0, 0] * A[2, 2]**2 +
        A[0, 1] * A[1, 0] * A[1, 1] - A[0, 2] * A[2, 0] * A[2, 2] +
        A[1, 1]**2 * A[2, 2] - A[1, 1] * A[1, 2] * A[2, 1] -
        A[1, 1] * A[2, 2]**2 + A[1, 2] * A[2, 1] * A[2, 2]
    ]  # noqa: E501
    Δd = [9, 6, 6, 6, 8, 8, 8, 2, 2, 2, 2, 2, 2, 1]
    Δ = 0
    for i in range(len(Δd)):
        Δ += Δx[i] * Δd[i] * Δy[i]

    Δxp = [
        A[1, 0], A[2, 0], A[2, 1], -A[0, 0] + A[1, 1], -A[0, 0] + A[2, 2],
        -A[1, 1] + A[2, 2]
    ]
    Δyp = [
        A[0, 1], A[0, 2], A[1, 2], -A[0, 0] + A[1, 1], -A[0, 0] + A[2, 2],
        -A[1, 1] + A[2, 2]
    ]
    Δdp = [6, 6, 6, 1, 1, 1]

    dp = 0
    for i in range(len(Δdp)):
        dp += 1 / 2 * Δxp[i] * Δdp[i] * Δyp[i]

    # Avoid dp = 0 and disc = 0, both are known with absolute error of ~eps**2
    # Required to avoid sqrt(0) derivatives and negative square roots
    dp += eps**2
    Δ += eps**2

    phi3 = ufl.atan_2(ufl.sqrt(27) * ufl.sqrt(Δ), dq)

    # sorted eigenvalues: λ0 <= λ1 <= λ2
    λ = [(I1 + 2 * ufl.sqrt(dp) * ufl.cos((phi3 + 2 * ufl.pi * k) / 3)) / 3
         for k in range(1, 4)]
    #
    # --- determine eigenprojectors E0, E1, E2
    #
    E = [ufl.diff(λk, A).T for λk in λ]

    return λ, E
 def stress(self, eps, alpha):
     eps_ = variable(eps)
     sigma = diff(self.elastic_energy_density(eps_, alpha), eps_)
     return sigma
Пример #9
0
# unless otherwise specified.
#
# Next, we will be needing functions for the boundary source ``B``, the
# traction ``T`` and the displacement solution itself ``u``::

# Functions
u = Coefficient(element)        # Displacement from previous iteration
# B = Coefficient(element)        # Body force per unit volume
# T = Coefficient(element)        # Traction force on the boundary

# Now, we can define the kinematic quantities involved in the model::

# Kinematics
d = len(u)
I = Identity(d)         # Identity tensor
F = variable(I + grad(u))         # Deformation gradient
C = F.T*F               # Right Cauchy-Green tensor

# Invariants of deformation tensors
Ic = tr(C)
J = det(F)

# Before defining the energy density and thus the total potential
# energy, it only remains to specify constants for the elasticity
# parameters::

# Elasticity parameters
E = 10.0
nu = 0.3
mu = E/(2*(1 + nu))
lmbda = E*nu/((1 + nu)*(1 - 2*nu))
Пример #10
0
# -

# The first line creates an object of type `InitialConditions`.  The
# following two lines make `u` and `u0` interpolants of `u_init`
# (since `u` and `u0` are finite element functions, they may not be
# able to represent a given function exactly, but the function can be
# approximated by interpolating it in a finite element space).
#
# ```{index} automatic differentiation
# ```
#
# The chemical potential $df/dc$ is computed using UFL automatic
# differentiation:

# Compute the chemical potential df/dc
c = ufl.variable(c)
f = 100 * c**2 * (1 - c)**2
dfdc = ufl.diff(f, c)

# The first line declares that `c` is a variable that some function can
# be differentiated with respect to. The next line is the function
# $f$ defined in the problem statement, and the third line performs
# the differentiation of `f` with respect to the variable `c`.
#
# It is convenient to introduce an expression for $\mu_{n+\theta}$:

# mu_(n+theta)
mu_mid = (1.0 - theta) * mu0 + theta * mu

# which is then used in the definition of the variational forms:
Пример #11
0
 def dJedC(self, u_, theta_):
     C_ = variable(self.kin.C(u_))
     Je = sqrt(det(self.C_e(C_, theta_)))
     return diff(Je,C_)

# Configuration gradient
I = ufl.Identity(u.geometric_dimension())  # noqa: E741
F = I + ufl.grad(u)  # deformation gradient as function of displacement

# Strain measures
E = 1 / 2 * (F.T * F - I)  # E = E(F), total Green-Lagrange strain
E_el = E - P  # E_el = E(F) - P, elastic strain

# Stress
S = 2 * mu * E_el + la * ufl.tr(
    E_el) * I  # S = S(E_el), PK2, St.Venant-Kirchhoff

# Wrap variable around expression (for diff)
S, B, h = ufl.variable(S), ufl.variable(B), ufl.variable(h)

# Yield function
f = ufl.sqrt(3) * rJ2(ufl.dev(S) - ufl.dev(B)) - (Sy + h)

# Plastic potential
g = f

# Total differential of yield function
df = + ufl.inner(ufl.diff(f, S), S - S0) \
     + ufl.inner(ufl.diff(f, h), h - h0) \
     + ufl.inner(ufl.diff(f, B), B - B0)

# Derivative of plastic potential wrt stress
dgdS = ufl.diff(g, S)
Пример #13
0
def assemble_test(cell_batch_size: int):
    mesh = dolfin.UnitCubeMesh(MPI.comm_world, 40, 40, 40)

    def isochoric(F):
        C = F.T*F

        I_1 = tr(C)
        I4_f = dot(e_f, C*e_f)
        I4_s = dot(e_s, C*e_s)
        I8_fs = dot(e_f, C*e_s)

        def cutoff(x):
            return 1.0/(1.0 + ufl.exp(-(x - 1.0)*30.0))

        def scaled_exp(a0, a1, argument):
            return a0/(2.0*a1)*(ufl.exp(b*argument) - 1)

        E_1 = scaled_exp(a, b, I_1 - 3.)

        E_f = cutoff(I4_f)*scaled_exp(a_f, b_f, (I4_f - 1.)**2)
        E_s = cutoff(I4_s)*scaled_exp(a_s, b_s, (I4_s - 1.)**2)
        E_3 = scaled_exp(a_fs, b_fs, I8_fs**2)

        E = E_1 + E_f + E_s + E_3
        return E

    cell = mesh.ufl_cell()

    lamda = dolfin.Constant(0.48, cell)
    a = dolfin.Constant(1.0, cell)
    b = dolfin.Constant(1.0, cell)
    a_s = dolfin.Constant(1.0, cell)
    b_s = dolfin.Constant(1.0, cell)
    a_f = dolfin.Constant(1.0, cell)
    b_f = dolfin.Constant(1.0, cell)
    a_fs = dolfin.Constant(1.0, cell)
    b_fs = dolfin.Constant(1.0, cell)

    # For more fun, make these general vector fields rather than
    # constants:
    e_s = dolfin.Constant([0.0, 1.0, 0.0], cell)
    e_f = dolfin.Constant([1.0, 0.0, 0.0], cell)

    V = dolfin.FunctionSpace(mesh, ufl.VectorElement("CG", cell, 1))
    u = dolfin.Function(V)
    du = dolfin.function.argument.TrialFunction(V)
    v = dolfin.function.argument.TestFunction(V)

    # Misc elasticity related tensors and other quantities
    F = grad(u) + ufl.Identity(3)
    F = ufl.variable(F)
    J = det(F)
    Fbar = J**(-1.0/3.0)*F

    # Define energy
    E_volumetric = lamda*0.5*ln(J)**2
    psi = isochoric(Fbar) + E_volumetric

    # Find first Piola-Kircchoff tensor
    P = ufl.diff(psi, F)

    # Define the variational formulation
    F = inner(P, grad(v))*dx

    # Take the derivative
    J = ufl.derivative(F, u, du)

    a, L = J, F

    if cell_batch_size > 1:
        cxx_flags = "-O2 -ftree-vectorize -funroll-loops -march=native -mtune=native"
    else:
        cxx_flags = "-O2"

    assembler = dolfin.fem.assembling.Assembler([[a]], [L], [],
                                                form_compiler_parameters={"cell_batch_size": cell_batch_size,
                                                                          "enable_cross_cell_gcc_ext": True,
                                                                          "cpp_optimize_flags": cxx_flags})

    t = -time.time()
    A, b = assembler.assemble(
        mat_type=dolfin.cpp.fem.Assembler.BlockType.monolithic)
    t += time.time()

    return A, b, t
Пример #14
0
def holzapfel_ogden(mesh, q, p, nf=0):
    # Based on https://gist.github.com/meg-simula/3ab3fd63264c8cf1912b
    #
    # Original credit note:
    # "Original implementation by Gabriel Balaban,
    # modified by Marie E. Rognes"

    from ufl import (Constant, VectorConstant, Identity, Coefficient,
                     TestFunction, conditional, det, diff, dot, exp,
                     grad, inner, tr, variable)

    # Define some random parameters
    a = Constant(mesh)
    b = Constant(mesh)
    a_s = Constant(mesh)
    b_s = Constant(mesh)
    a_f = Constant(mesh)
    b_f = Constant(mesh)
    a_fs = Constant(mesh)
    b_fs = Constant(mesh)

    # For more fun, make these general vector fields rather than
    # constants:
    e_s = VectorConstant(mesh)
    e_f = VectorConstant(mesh)

    # Define the isochoric energy contribution
    def isochoric(C):
        I_1 = tr(C)
        I4_f = dot(e_f, C*e_f)
        I4_s = dot(e_s, C*e_s)
        I8_fs = dot(e_s, C*e_f)

        def heaviside(x):
            return conditional(x < 1, 0, 1)

        def scaled_exp(a, b, x):
            return a/(2*b)*(exp(b*x) - 1)

        E_1 = scaled_exp(a, b, I_1 - 3)

        E_f = heaviside(I4_f)*scaled_exp(a_f, b_f, (I4_f - 1)**2)
        E_s = heaviside(I4_s)*scaled_exp(a_s, b_s, (I4_s - 1)**2)
        E_3 = scaled_exp(a_fs, b_fs, I8_fs**2)

        E = E_1 + E_f + E_s + E_3
        return E

    # Define mesh and function space
    V = ufl.FunctionSpace(mesh, ufl.VectorElement("CG", mesh.ufl_cell(), q))
    u = Coefficient(V)
    v = TestFunction(V)

    # Misc elasticity related tensors and other quantities
    I = Identity(mesh.ufl_cell().topological_dimension())
    F = grad(u) + I
    F = variable(F)
    J = det(F)
    Cbar = J**(-2/3)*F.T*F

    # Define energy
    Psi = isochoric(Cbar)

    # Find first Piola-Kirchhoff tensor
    P = diff(Psi, F)

    # Define the variational formulation
    it = inner(P, grad(v))

    P = ufl.FunctionSpace(mesh, ufl.VectorElement('P', mesh.ufl_cell(), p))
    f = [ufl.Coefficient(P) for _ in range(nf)]
    return ufl.derivative(reduce(ufl.inner,
                                 list(map(ufl.div, f)) + [it])*ufl.dx, u)
Пример #15
0
))

svals = np.zeros_like(stretchVals)

plt.plot(timeVals, stretchVals)
plt.savefig("stretchesVisco.png")
plt.close()

# stabilization parameters
h = FacetArea(mesh)
h_avg = avg(h)

# new variable name to take derivatives
FF = Identity(3) + grad(u)
CC = FF.T * FF
Fv = variable(FF)
S = diff(freeEnergy(Fv.T * Fv, CCv), Fv)  # first PK stress
dl_interp(CC, C)
dl_interp(CC, Cn)

my_identity = grad(SpatialCoordinate(mesh))

dl_interp(my_identity, CCv)
dl_interp(my_identity, Cvn)
dl_interp(my_identity, C_quart)
dl_interp(my_identity, C_thr_quart)
dl_interp(my_identity, C_half)

a_uv = (derivative(freeEnergy(CC, CCv), u, v) * dx +
        qvals / h_avg * dot(jump(u), jump(v)) * dS)
jac = derivative(a_uv, u, du)
Пример #16
0
 def dJdC(self, u_):
     C_ = variable(self.C(u_))
     J = sqrt(det(C_))
     return diff(J,C_)
Пример #17
0
# Create intial conditions and interpolate
u.interpolate(u_init)

# The first line creates an object of type ``InitialConditions``.  The
# following two lines make ``u`` and ``u0`` interpolants of ``u_init``
# (since ``u`` and ``u0`` are finite element functions, they may not be
# able to represent a given function exactly, but the function can be
# approximated by interpolating it in a finite element space).
#
# .. index:: automatic differentiation
#
# The chemical potential :math:`df/dc` is computed using automated
# differentiation::

# Compute the chemical potential df/dc
c = variable(c)
f = 100 * c**2 * (1 - c)**2
dfdc = diff(f, c)

# The first line declares that ``c`` is a variable that some function can
# be differentiated with respect to. The next line is the function
# :math:`f` defined in the problem statement, and the third line performs
# the differentiation of ``f`` with respect to the variable ``c``.
#
# It is convenient to introduce an expression for :math:`\mu_{n+\theta}`::

# mu_(n+theta)
mu_mid = (1.0 - theta) * mu0 + theta * mu

# which is then used in the definition of the variational forms::
Пример #18
0
# External forces
T = Coefficient(u_element)
p0 = Coefficient(p_element)

# Material parameters FIXME
rho = Constant(cell)
K = Constant(cell)
c00 = Constant(cell)
c11 = Constant(cell)
c22 = Constant(cell)

# Deformation gradient
I = Identity(d)
F = I + grad(u)
F = variable(F)
Finv = inv(F)
J = det(F)

# Left Cauchy-Green deformation tensor
B = F * F.T
I1_B = tr(B)
I2_B = (I1_B**2 - tr(B * B)) / 2
I3_B = J**2

# Right Cauchy-Green deformation tensor
C = F.T * F
I1_C = tr(C)
I2_C = (I1_C**2 - tr(C * C)) / 2
I3_C = J**2