Ejemplo n.º 1
0
    def SecondPiolaStress(self, F, p=None, deviatoric=False):
        import dolfin
        from pulse import kinematics
        material = self.material
        I = kinematics.SecondOrderIdentity(F)

        f0 = material.f0
        f0f0 = dolfin.outer(f0, f0)

        I1 = dolfin.variable(material.active.I1(F))
        I4f = dolfin.variable(material.active.I4(F))

        Fe = material.active.Fe(F)
        Fa = material.active.Fa
        Ce = Fe.T * Fe

        # fe = Fe*f0
        # fefe = dolfin.outer(fe, fe)

        # Elastic volume ratio
        J = dolfin.variable(dolfin.det(Fe))
        # Active volume ration
        Ja = dolfin.det(Fa)

        dim = self.geometry.dim()
        Ce_bar = pow(J, -2.0 / float(dim)) * Ce

        w1 = material.W_1(I1, diff=1, dim=dim)
        w4f = material.W_4(I4f, diff=1)

        # Total Stress
        S_bar = Ja * (2 * w1 * I + 2 * w4f * f0f0) * dolfin.inv(Fa).T

        if material.is_isochoric:

            # Deviatoric
            Dev_S_bar = S_bar - (1.0 / 3.0) * dolfin.inner(
                S_bar, Ce_bar) * dolfin.inv(Ce_bar)

            S_mat = J**(-2.0 / 3.0) * Dev_S_bar
        else:
            S_mat = S_bar

        # Volumetric
        if p is None or deviatoric:
            S_vol = dolfin.zero((dim, dim))
        else:
            psi_vol = material.compressibility(p, J)
            S_vol = J * dolfin.diff(psi_vol, J) * dolfin.inv(Ce)

        # Active stress
        wactive = material.active.Wactive(F, diff=1)
        eta = material.active.eta

        S_active = wactive * (f0f0 + eta * (I - f0f0))

        S = S_mat + S_vol + S_active

        return S
Ejemplo n.º 2
0
    def FirstPiolaStress(self, F, p=None, *args, **kwargs):

        F = dolfin.variable(F)

        # First Piola Kirchoff
        psi_iso = self.strain_energy(F)
        P = dolfin.diff(psi_iso, F)

        if p is not None:
            J = dolfin.variable(kinematics.Jacobian(F))
            psi_vol = self.compressibility(p, J)
            # PiolaTransform
            P_vol = J * dolfin.diff(psi_vol, J) * dolfin.inv(F).T

            P += P_vol

        return P
Ejemplo n.º 3
0
	def Cauchy1(self): #Joy added this
	  
		u = self.parameters["displacement_variable"]
	   
		d = u.geometric_dimension()
		I = Identity(d)
		F = I + grad(u)
	   
		f0 = self.parameters["fiber"]
		s0 = self.parameters["sheet"]
		n0 = self.parameters["sheet-normal"]
		Cff=self.parameters["StrainEnergyDensityFunction_Cff"]
		Css=self.parameters["StrainEnergyDensityFunction_Css"]
		Cnn=self.parameters["StrainEnergyDensityFunction_Cnn"]
		Cns=self.parameters["StrainEnergyDensityFunction_Cns"]
		Cfs=self.parameters["StrainEnergyDensityFunction_Cfs"]
		Cfn=self.parameters["StrainEnergyDensityFunction_Cfn"]
		#Kappa = self.parameters["Kappa"]
		#isincomp = self.parameters["incompressible"]

	  
		p = self.parameters["pressure_variable"]

		Cstrain=self.parameters["StrainEnergyDensityFunction_Coef"]

		F = dolfin.variable(F)
		J = det(F)

		Ea = 0.5*(as_tensor(F[k,i]*F[k,j] - I[i,j], (i,j)))

		Eff = f0[i]*Ea[i,j]*f0[j]
		Ess = s0[i]*Ea[i,j]*s0[j]
		Enn = n0[i]*Ea[i,j]*n0[j]
		Efs = f0[i]*Ea[i,j]*s0[j]
		Efn = f0[i]*Ea[i,j]*n0[j]
		Ens = n0[i]*Ea[i,j]*s0[j]
	
		
		
		#QQ = bff*pow(Eff,2.0) + bfx*(pow(Ess,2.0)+ pow(Enn,2.0)+ 2.0*pow(Ens,2.0)) + bxx*(2.0*pow(Efs,2.0) + 2.0*pow(Efn,2.0))
		QQ = Cff*Eff**2.0 + Css*Ess**2.0 + Cnn*Enn**2.0 + Cns**Ens**2.0 + Cfs**Efs**2.0 + Cfn*Efn**2.0
		Wp = Cstrain*(exp(QQ) -  1.0) - p*(J - 1.0)
		#E = dolfin.variable(Ea)
		sigma =  (1.0/J)*dolfin.diff(Wp,F)*F.T

		
	   
		return sigma
Ejemplo n.º 4
0
    def initialize_with_field(self, u):
        super().initialize_with_field(u)

        d = self.deformation_measures.d
        F = self.deformation_measures.F
        J = self.deformation_measures.J
        I1 = self.deformation_measures.I1
        # I2 = self.deformation_measures.I2
        # I3 = self.deformation_measures.I3

        for m in self.material_parameters:

            E = m.get('E', None)
            nu = m.get('nu', None)

            mu = m.get('mu', None)
            lm = m.get('lm', None)

            if mu is None:
                if E is None or nu is None:
                    raise RuntimeError(
                        'Material model requires parameter "mu"; '
                        'otherwise, require parameters "E" and "nu".')

                mu = E / (2 * (1 + nu))

            if lm is None:
                if E is None or nu is None:
                    raise RuntimeError(
                        'Material model requires parameter "lm"; '
                        'otherwise, require parameters "E" and "nu".')

                lm = E * nu / ((1 + nu) * (1 - 2 * nu))

            psi = (mu / 2) * (I1 - d - 2 * ln(J)) + (lm / 2) * ln(J)**2

            pk1 = diff(psi, F)
            pk2 = dot(inv(F), pk1)

            self.psi.append(psi)
            self.pk1.append(pk1)
            self.pk2.append(pk2)
Ejemplo n.º 5
0
I = dolfin.Identity(d)
F = dolfin.variable(I + dolfin.grad(u))

C = F.T * F
J = dolfin.det(F)
I1 = dolfin.tr(C)

# Lame material parameters
lm = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))
mu = E / (2.0 + 2.0 * nu)

# Energy density of a Neo-Hookean material model
psi = (mu / 2.0) * (I1 - d - 2.0 * dolfin.ln(J)) + (lm / 2.0) * dolfin.ln(J)**2

# First Piola-Kirchhoff
pk1 = dolfin.diff(psi, F)

# Boundary traction
N = dolfin.FacetNormal(mesh)
PN = dolfin.dot(pk1, N)

# Potential energy
Pi = psi * dx  # NOTE: There is no external force potential

# Equilibrium problem
F = dolfin.derivative(Pi, u)

### Model cost and constraints

# Observed displacement
u_obs = u  # NOTE: Generally a vector-valued sub-function
Ejemplo n.º 6
0
def test_potentials(scheme, N, dim, th):
    model, DS, bcs = prepare_model_and_bcs(scheme, N, dim, th)
    prm = model.parameters["sigma"]
    prm.add("12", 2.0)
    if N == 3:
        prm.add("13", 2.0)
        prm.add("23", 2.0)
    #info(model.parameters, True)

    # Prepare arguments for obtaining multi-well potential
    phi = DS.primitive_vars_ctl(indexed=True)["phi"]
    phi0 = DS.primitive_vars_ptl(indexed=True)["phi"]
    phi_te = DS.test_functions()["phi"]
    dw = DoublewellFactory.create(model.parameters["doublewell"])
    S, A, iA = model.build_stension_matrices()

    # Define piece of form containing derivative of the multiwell potential dF
    dF_list = [] # -- there are at least 3 alternative ways how to do that:
    # 1st -- automatic differentiation via diff
    _phi = variable(phi)
    F_auto = multiwell(dw, _phi, S)
    dF_auto = diff(F_auto, _phi)
    dF_list.append(inner(dot(iA, dF_auto), phi_te)*dx)
    # 2nd -- manual specification of dF
    dF_man = multiwell_derivative(dw, phi, phi0, S, semi_implicit=True)
    dF_list.append(inner(dot(iA, dF_man), phi_te)*dx)
    # 3rd -- automatic differentiation via derivative
    F = multiwell(dw, phi, S)*dx # will be used below
    dF_list.append(derivative(F, phi, tuple(dot(iA.T, phi_te))))
    # UFL ISSUE:
    #   The above tuple is needed as long as `ListTensor` type is not
    #   explicitly treated in `ufl/formoperators.py:211`,
    #   cf. `ufl/formoperators.py:168`
    # FIXME: check if this is a bug and report it
    del F_auto, dF_auto, dF_man

    for dF in dF_list:
        # Check that the size of the domain is 1
        mesh = DS.function_spaces()[0].mesh()
        assert near(assemble(Constant(1.0)*dx(domain=mesh)), 1.0)
        # Assemble inner(\vec{1}, phi_)*dx (for later check of the derivative)
        phi_ = DS.test_functions()["phi"]
        # FIXME: 'FullyDecoupled' DS requires "assembly by parts"
        b1 = assemble(inner(as_vector(len(phi_)*[Constant(1.0),]), phi_)*dx)
        if N == 2:
            # Check that F(0.2) == 0.0512 [== F*dx]
            assert near(assemble(F), 0.0512, 1e-10)
            # Check the derivative
            # --- scale b1 by dFd1(0.2) == 0.096
            as_backend_type(b1).vec().scale(0.096)
            # --- assemble "inner(dFd1, phi_)*dx"
            b2 = assemble(dF)
            # --- check that both vectors nearly coincides
            b2.axpy(-1.0, b1)
            assert b2.norm("l2") < 1e-10
        if N == 3:
            # Check that F(0.2, 0.2) == 0.1088 [== F*dx]
            assert near(assemble(F), 0.1088, 1e-10)
            # Check the derivative
            # --- scale b1 by dFdj(0.2, 0.2) == 0.048 [j = 1,2]
            as_backend_type(b1).vec().scale(0.048)
            # --- assemble "inner(dFdj, phi_)*dx"
            b2 = assemble(dF)
            # --- check that both vectors nearly coincides
            b2.axpy(-1.0, b1)
            assert b2.norm("l2") < 1e-10
Ejemplo n.º 7
0
            def u(t, x, y):
                return 0.5 * (t**2 + 1) * sin(2 * x * pi) * sin(2 * y * pi)

            # Declare also a numpy version of the solution (handy for plotting and evaluation)
            def u_numpy(t, x, y):                return 0.5 * (t**2+1) * \
np.sin(2*x*pi) * np.sin(2*y*pi)

            def u_T_numpy(x, y):
                return u_numpy(T[1], x, y)


            # Define right-hand side
            u_x = u(t_, x, y_)
            by_x = by(t_, x, y_)

            f = diff(u_x, t_) + c * u_x + inner(bx, grad(u_x)) + \
                by_x * diff(u_x, y_) + inner(ax, grad(grad(u_x)))

        # We have to use at least quadratic polynomials here
        Vx = FunctionSpace(mx, 'CG', 2)
        Vy = FunctionSpace(my, 'CG', 1)

        phi = TrialFunction(Vx)
        psi = TestFunction(Vx)

        v = Function(Vx)

        gamma = 1.0

        # Jump penalty term
        stab1 = 2.