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 freeEnergy(C, Cv):
    J = sqrt(det(C))
    I1 = tr(C)
    Ce = C * inv(Cv)
    Ie1 = tr(Ce)
    Je = J / sqrt(det(Cv))

    psiEq = (3**(1 - alph1) / (2.0 * alph1) * mu1 * (I1**alph1 - 3**alph1) +
             3**(1 - alph2) / (2.0 * alph2) * mu2 * (I1**alph2 - 3**alph2) -
             (mu1 + mu2) * ln(J) + mu_pr / 2 * (J - 1)**2)

    psiNeq = (3**(1 - a1) / (2.0 * a1) * m1 * (Ie1**a1 - 3**a1) + 3**(1 - a2) /
              (2.0 * a2) * m2 * (Ie1**a2 - 3**a2) - (m1 + m2) * ln(Je))

    return psiEq + psiNeq
示例#3
0
def invariants_principal(A):
    """Principal invariants of (real-valued) tensor A.
    https://doi.org/10.1007/978-3-7091-0174-2_3
    """
    i1 = ufl.tr(A)
    i2 = (ufl.tr(A)**2 - ufl.tr(A * A)) / 2
    i3 = ufl.det(A)
    return i1, i2, i3
示例#4
0
def problem():
    mesh = dolfin.UnitCubeMesh(MPI.comm_world, 10, 10, 10)
    cell = mesh.ufl_cell()

    vec_element = dolfin.VectorElement("Lagrange", cell, 1)
    # scl_element = dolfin.FiniteElement("Lagrange", cell, 1)

    Q = dolfin.FunctionSpace(mesh, vec_element)
    # Qs = dolfin.FunctionSpace(mesh, scl_element)

    # Coefficients
    v = dolfin.function.argument.TestFunction(Q)  # Test function
    du = dolfin.function.argument.TrialFunction(Q)  # Incremental displacement
    u = dolfin.Function(Q)  # Displacement from previous iteration

    B = dolfin.Constant((0.0, -0.5, 0.0), cell)  # Body force per unit volume
    T = dolfin.Constant((0.1, 0.0, 0.0),
                        cell)  # Traction force on the boundary

    # B, T = dolfin.Function(Q), dolfin.Function(Q)

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

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

    # Elasticity parameters
    E, nu = 10.0, 0.3
    mu = dolfin.Constant(E / (2 * (1 + nu)), cell)
    lmbda = dolfin.Constant(E * nu / ((1 + nu) * (1 - 2 * nu)), cell)

    # mu, lmbda = dolfin.Function(Qs), dolfin.Function(Qs)

    # Stored strain energy density (compressible neo-Hookean model)
    psi = (mu / 2) * (Ic - 3) - mu * ln(J) + (lmbda / 2) * (ln(J))**2

    # Total potential energy
    Pi = psi * dx - dot(B, u) * dx - dot(T, u) * ds

    # Compute first variation of Pi (directional derivative about u in the direction of v)
    F = ufl.derivative(Pi, u, v)

    # Compute Jacobian of F
    J = ufl.derivative(F, u, du)

    return J, F
示例#5
0
    def __init__(self, C, I):
        self.C = C
        self.I = I

        # Cauchy-Green invariants
        self.Ic = tr(C)
        self.IIc = 0.5 * (tr(C)**2. - tr(C * C))
        self.IIIc = det(C)
        # isochoric Cauchy-Green invariants
        self.Ic_bar = self.IIIc**(-1. / 3.) * self.Ic
        self.IIc_bar = self.IIIc**(-2. / 3.) * self.IIc

        # Green-Lagrange strain and invariants (for convenience, used e.g. by St.-Venant-Kirchhoff material)
        self.E = 0.5 * (C - I)
        self.trE = tr(self.E)
        self.trE2 = tr(self.E * self.E)
示例#6
0
def hyperelasticity_action_forms(mesh, vec_el):
    cell = mesh.ufl_cell()

    Q = dolfin.FunctionSpace(mesh, vec_el)

    # Coefficients
    v = dolfin.function.argument.TestFunction(Q)  # Test function
    du = dolfin.function.argument.TrialFunction(Q)  # Incremental displacement
    u = dolfin.Function(Q)  # Displacement from previous iteration
    u.vector().set(0.5)

    B = dolfin.Constant((0.0, -0.5, 0.0), cell)  # Body force per unit volume
    T = dolfin.Constant((0.1, 0.0, 0.0), cell)  # Traction force on the boundary

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

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

    # Elasticity parameters
    E, nu = 10.0, 0.3
    mu = dolfin.Constant(E / (2 * (1 + nu)), cell)
    lmbda = dolfin.Constant(E * nu / ((1 + nu) * (1 - 2 * nu)), cell)

    # Stored strain energy density (compressible neo-Hookean model)
    psi = (mu / 2) * (Ic - 3) - mu * ln(J) + (lmbda / 2) * (ln(J)) ** 2

    # Total potential energy
    Pi = psi * dx - dot(B, u) * dx - dot(T, u) * ds

    # Compute first variation of Pi (directional derivative about u in the direction of v)
    F = ufl.derivative(Pi, u, v)

    # Compute Jacobian of F
    J = ufl.derivative(F, u, du)

    w = dolfin.Function(Q)
    w.vector().set(1.2)

    L = ufl.action(J, w)

    return None, L, None
示例#7
0
def eig(A):
    """Eigenvalues of 3x3 tensor"""
    eps = 1.0e-12

    q = ufl.tr(A) / 3.0
    p1 = 0.5 * (A[0, 1]**2 + A[1, 0]**2 + A[0, 2]**2 + A[2, 0]**2 +
                A[1, 2]**2 + A[2, 1]**2)
    p2 = (A[0, 0] - q)**2 + (A[1, 1] - q)**2 + (A[2, 2] - q)**2 + 2 * p1
    p = ufl.sqrt(p2 / 6)
    B = (A - q * ufl.Identity(3))
    r = ufl.det(B) / (2 * p**3)

    r = ufl.Max(ufl.Min(r, 1.0 - eps), -1.0 + eps)
    phi = ufl.acos(r) / 3.0

    eig0 = ufl.conditional(p2 < eps, q, q + 2 * p * ufl.cos(phi))
    eig2 = ufl.conditional(p2 < eps, q,
                           q + 2 * p * ufl.cos(phi + (2 * numpy.pi / 3)))
    eig1 = ufl.conditional(p2 < eps, q, 3 * q - eig0 -
                           eig2)  # since trace(A) = eig1 + eig2 + eig3

    return eig0, eig1, eig2
示例#8
0
def test_diff_then_integrate():

    # Define 1D geometry
    n = 21
    mesh = UnitIntervalMesh(MPI.comm_world, n)

    # Shift and scale mesh
    x0, x1 = 1.5, 3.14
    mesh.coordinates()[:] *= (x1 - x0)
    mesh.coordinates()[:] += x0

    x = SpatialCoordinate(mesh)[0]
    xs = 0.1 + 0.8 * x / x1  # scaled to be within [0.1,0.9]

    # Define list of expressions to test, and configure
    # accuracies these expressions are known to pass with.
    # The reason some functions are less accurately integrated is
    # likely that the default choice of quadrature rule is not perfect
    F_list = []

    def reg(exprs, acc=10):
        for expr in exprs:
            F_list.append((expr, acc))

    # FIXME: 0*dx and 1*dx fails in the ufl-ffc-jit framework somewhere
    # reg([Constant(0.0, cell=cell)])
    # reg([Constant(1.0, cell=cell)])
    monomial_list = [x**q for q in range(2, 6)]
    reg(monomial_list)
    reg([2.3 * p + 4.5 * q for p in monomial_list for q in monomial_list])
    reg([x**x])
    reg([x**(x**2)], 8)
    reg([x**(x**3)], 6)
    reg([x**(x**4)], 2)
    # Special functions:
    reg([atan(xs)], 8)
    reg([sin(x), cos(x), exp(x)], 5)
    reg([ln(xs), pow(x, 2.7), pow(2.7, x)], 3)
    reg([asin(xs), acos(xs)], 1)
    reg([tan(xs)], 7)

    try:
        import scipy
    except ImportError:
        scipy = None

    if hasattr(math, 'erf') or scipy is not None:
        reg([erf(xs)])
    else:
        print(
            "Warning: skipping test of erf, old python version and no scipy.")

    # if 0:
    #     print("Warning: skipping tests of bessel functions, doesn't build on all platforms.")
    # elif scipy is None:
    #     print("Warning: skipping tests of bessel functions, missing scipy.")
    # else:
    #     for nu in (0, 1, 2):
    #         # Many of these are possibly more accurately integrated,
    #         # but 4 covers all and is sufficient for this test
    #         reg([bessel_J(nu, xs), bessel_Y(nu, xs), bessel_I(nu, xs), bessel_K(nu, xs)], 4)

    # To handle tensor algebra, make an x dependent input tensor
    # xx and square all expressions
    def reg2(exprs, acc=10):
        for expr in exprs:
            F_list.append((inner(expr, expr), acc))

    xx = as_matrix([[2 * x**2, 3 * x**3], [11 * x**5, 7 * x**4]])
    x3v = as_vector([3 * x**2, 5 * x**3, 7 * x**4])
    cc = as_matrix([[2, 3], [4, 5]])
    reg2([xx])
    reg2([x3v])
    reg2([cross(3 * x3v, as_vector([-x3v[1], x3v[0], x3v[2]]))])
    reg2([xx.T])
    reg2([tr(xx)])
    reg2([det(xx)])
    reg2([dot(xx, 0.1 * xx)])
    reg2([outer(xx, xx.T)])
    reg2([dev(xx)])
    reg2([sym(xx)])
    reg2([skew(xx)])
    reg2([elem_mult(7 * xx, cc)])
    reg2([elem_div(7 * xx, xx + cc)])
    reg2([elem_pow(1e-3 * xx, 1e-3 * cc)])
    reg2([elem_pow(1e-3 * cc, 1e-3 * xx)])
    reg2([elem_op(lambda z: sin(z) + 2, 0.03 * xx)], 2)  # pretty inaccurate...

    # FIXME: Add tests for all UFL operators:
    # These cause discontinuities and may be harder to test in the
    # above fashion:
    # 'inv', 'cofac',
    # 'eq', 'ne', 'le', 'ge', 'lt', 'gt', 'And', 'Or', 'Not',
    # 'conditional', 'sign',
    # 'jump', 'avg',
    # 'LiftingFunction', 'LiftingOperator',

    # FIXME: Test other derivatives: (but algorithms for operator
    # derivatives are the same!):
    # 'variable', 'diff',
    # 'Dx', 'grad', 'div', 'curl', 'rot', 'Dn', 'exterior_derivative',

    # Run through all operators defined above and compare integrals
    debug = 0
    for F, acc in F_list:
        # Apply UFL differentiation
        f = diff(F, SpatialCoordinate(mesh))[..., 0]
        if debug:
            print(F)
            print(x)
            print(f)

        # Apply integration with DOLFIN
        # (also passes through form compilation and jit)
        M = f * dx
        f_integral = assemble_scalar(M)  # noqa
        f_integral = MPI.sum(mesh.mpi_comm(), f_integral)

        # Compute integral of f manually from anti-derivative F
        # (passes through PyDOLFIN interface and uses UFL evaluation)
        F_diff = F((x1, )) - F((x0, ))

        # Compare results. Using custom relative delta instead
        # of decimal digits here because some numbers are >> 1.
        delta = min(abs(f_integral), abs(F_diff)) * 10**-acc
        assert f_integral - F_diff <= delta
示例#9
0
def test_div_grad_then_integrate_over_cells_and_boundary():

    # Define 2D geometry
    n = 10
    mesh = RectangleMesh(Point(0.0, 0.0), Point(2.0, 3.0), 2 * n, 3 * n)

    x, y = SpatialCoordinate(mesh)
    xs = 0.1 + 0.8 * x / 2  # scaled to be within [0.1,0.9]
    #    ys = 0.1 + 0.8 * y / 3  # scaled to be within [0.1,0.9]
    n = FacetNormal(mesh)

    # Define list of expressions to test, and configure accuracies
    # these expressions are known to pass with.  The reason some
    # functions are less accurately integrated is likely that the
    # default choice of quadrature rule is not perfect
    F_list = []

    def reg(exprs, acc=10):
        for expr in exprs:
            F_list.append((expr, acc))

    # FIXME: 0*dx and 1*dx fails in the ufl-ffc-jit framework somewhere
    # reg([Constant(0.0, cell=cell)])
    # reg([Constant(1.0, cell=cell)])
    monomial_list = [x**q for q in range(2, 6)]
    reg(monomial_list)
    reg([2.3 * p + 4.5 * q for p in monomial_list for q in monomial_list])
    reg([xs**xs])
    reg(
        [xs**(xs**2)], 8
    )  # Note: Accuracies here are from 1D case, not checked against 2D results.
    reg([xs**(xs**3)], 6)
    reg([xs**(xs**4)], 2)
    # Special functions:
    reg([atan(xs)], 8)
    reg([sin(x), cos(x), exp(x)], 5)
    reg([ln(xs), pow(x, 2.7), pow(2.7, x)], 3)
    reg([asin(xs), acos(xs)], 1)
    reg([tan(xs)], 7)

    # To handle tensor algebra, make an x dependent input tensor
    # xx and square all expressions
    def reg2(exprs, acc=10):
        for expr in exprs:
            F_list.append((inner(expr, expr), acc))

    xx = as_matrix([[2 * x**2, 3 * x**3], [11 * x**5, 7 * x**4]])
    xxs = as_matrix([[2 * xs**2, 3 * xs**3], [11 * xs**5, 7 * xs**4]])
    x3v = as_vector([3 * x**2, 5 * x**3, 7 * x**4])
    cc = as_matrix([[2, 3], [4, 5]])
    reg2(
        [xx]
    )  # TODO: Make unit test for UFL from this, results in listtensor with free indices
    reg2([x3v])
    reg2([cross(3 * x3v, as_vector([-x3v[1], x3v[0], x3v[2]]))])
    reg2([xx.T])
    reg2([tr(xx)])
    reg2([det(xx)])
    reg2([dot(xx, 0.1 * xx)])
    reg2([outer(xx, xx.T)])
    reg2([dev(xx)])
    reg2([sym(xx)])
    reg2([skew(xx)])
    reg2([elem_mult(7 * xx, cc)])
    reg2([elem_div(7 * xx, xx + cc)])
    reg2([elem_pow(1e-3 * xxs, 1e-3 * cc)])
    reg2([elem_pow(1e-3 * cc, 1e-3 * xx)])
    reg2([elem_op(lambda z: sin(z) + 2, 0.03 * xx)], 2)  # pretty inaccurate...

    # FIXME: Add tests for all UFL operators:
    # These cause discontinuities and may be harder to test in the
    # above fashion:
    # 'inv', 'cofac',
    # 'eq', 'ne', 'le', 'ge', 'lt', 'gt', 'And', 'Or', 'Not',
    # 'conditional', 'sign',
    # 'jump', 'avg',
    # 'LiftingFunction', 'LiftingOperator',

    # FIXME: Test other derivatives: (but algorithms for operator
    # derivatives are the same!):
    # 'variable', 'diff',
    # 'Dx', 'grad', 'div', 'curl', 'rot', 'Dn', 'exterior_derivative',

    # Run through all operators defined above and compare integrals
    debug = 0
    if debug:
        F_list = F_list[1:]

    for F, acc in F_list:
        if debug:
            print('\n', "F:", str(F))

        # Integrate over domain and its boundary
        int_dx = assemble(div(grad(F)) * dx(mesh))  # noqa
        int_ds = assemble(dot(grad(F), n) * ds(mesh))  # noqa

        if debug:
            print(int_dx, int_ds)

        # Compare results. Using custom relative delta instead of
        # decimal digits here because some numbers are >> 1.
        delta = min(abs(int_dx), abs(int_ds)) * 10**-acc
        assert int_dx - int_ds <= delta
示例#10
0
def inv(A):
    """Matrix invariants"""
    return ufl.tr(A), 1. / 2 * A[_i, _j] * A[_i, _j], ufl.det(A)
示例#11
0
 def dJdC(self, u_):
     C_ = variable(self.C(u_))
     J = sqrt(det(C_))
     return diff(J,C_)
示例#12
0
 def J(self, u_):
     return det(self.F(u_))
示例#13
0
 def dJedC(self, u_, theta_):
     C_ = variable(self.kin.C(u_))
     Je = sqrt(det(self.C_e(C_, theta_)))
     return diff(Je,C_)
示例#14
0
 def J_e(self, u_, theta_):
     return det(self.kin.F(u_)*inv(self.F_g(theta_)))
示例#15
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
示例#16
0
def test_neohooke():
    mesh = dolfinx.mesh.create_unit_cube(MPI.COMM_WORLD, 7, 7, 7)
    V = dolfinx.fem.VectorFunctionSpace(mesh, ("P", 1))
    P = dolfinx.fem.FunctionSpace(mesh, ("P", 1))

    L = dolfinx.fem.FunctionSpace(mesh, ("DG", 0))

    u = dolfinx.fem.Function(V, name="u")
    v = ufl.TestFunction(V)

    p = dolfinx.fem.Function(P, name="p")
    q = ufl.TestFunction(P)

    lmbda0 = dolfinx.fem.Function(L)

    d = mesh.topology.dim
    Id = ufl.Identity(d)
    F = Id + ufl.grad(u)
    C = F.T * F
    J = ufl.det(F)

    E_, nu_ = 10.0, 0.3
    mu, lmbda = E_ / (2 * (1 + nu_)), E_ * nu_ / ((1 + nu_) * (1 - 2 * nu_))
    psi = (mu / 2) * (ufl.tr(C) -
                      3) - mu * ufl.ln(J) + lmbda / 2 * ufl.ln(J)**2 + (p -
                                                                        1.0)**2
    pi = psi * ufl.dx

    F0 = ufl.derivative(pi, u, v)
    F1 = ufl.derivative(pi, p, q)

    # Number of eigenvalues to find
    nev = 8

    opts = PETSc.Options("neohooke")
    opts["eps_smallest_magnitude"] = True
    opts["eps_nev"] = nev
    opts["eps_ncv"] = 50 * nev
    opts["eps_conv_abs"] = True

    # opts["eps_non_hermitian"] = True
    opts["eps_tol"] = 1.0e-14
    opts["eps_max_it"] = 1000
    opts["eps_error_relative"] = "ascii::ascii_info_detail"
    opts["eps_monitor"] = "ascii"

    slepcp = dolfiny.slepcblockproblem.SLEPcBlockProblem([F0, F1], [u, p],
                                                         lmbda0,
                                                         prefix="neohooke")
    slepcp.solve()

    # mat = dolfiny.la.petsc_to_scipy(slepcp.eps.getOperators()[0])
    # eigvals, eigvecs = linalg.eigsh(mat, which="SM", k=nev)

    with dolfinx.io.XDMFFile(MPI.COMM_WORLD, "eigvec.xdmf", "w") as ofile:
        ofile.write_mesh(mesh)
        for i in range(nev):
            eigval, ur, ui = slepcp.getEigenpair(i)

            # Expect first 6 eignevalues 0, i.e. rigid body modes
            if i < 6:
                assert np.isclose(eigval, 0.0)

            for func in ur:
                name = func.name
                func.name = f"{name}_eigvec_{i}_real"
                ofile.write_function(func)

                func.name = name
# 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))

# Both the first variation of the potential energy, and the Jacobian of
# the variation, can be automatically computed by a call to
# ``derivative``::
示例#18
0
文件: run.py 项目: miklos1/urumi
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)