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
    def calculate_darcy_flow(self):
        # equation 5a
        du = self.mech_velocity
        p = self.pressure
        rho = Constant(self.parameters['rho'])
        phi = [Constant(phi) for phi in self.parameters['phi']]
        F = df.variable(kinematics.DeformationGradient(self.displacement))
        J = kinematics.Jacobian(F)
        dx = self.geometry.dx
        N = self.parameters['N']

        # Calculate endo to epi permeability gradient
        w = [TrialFunction(self.vector_space) for i in range(N)]
        v = [TestFunction(self.vector_space) for i in range(N)]
        a = [(1 / phi[i]) * df.inner(F * J * df.inv(F) * w[i], v[i]) * dx
             for i in range(N)]
        # a = [phi[i]*df.inner((w[i]-du), v[i])*dx for i in range(N)]
        # porous dynamics
        if self.parameters['mechanics']:
            A = [-J * self.K[i] * df.inv(F.T) for i in range(N)]
        else:
            A = [self.K[i] for i in range(N)]
        L = [-df.dot(A[i] * df.grad(p[i]), v[i]) * dx for i in range(N)]

        [
            df.solve(a[i] == L[i],
                     self.darcy_flow[i], [],
                     solver_parameters={
                         "linear_solver": "cg",
                         "preconditioner": "sor"
                     }) for i in range(N)
        ]
    def _init_forms(self):

        logger.debug("Initialize forms mechanics problem")
        # Displacement and hydrostatic_pressure
        u, p = dolfin.split(self.state)
        v, q = dolfin.split(self.state_test)

        # Some mechanical quantities
        F = dolfin.variable(kinematics.DeformationGradient(u))
        J = kinematics.Jacobian(F)
        dx = self.geometry.dx

        internal_energy = (self.material.strain_energy(F, ) +
                           self.material.compressibility(p, J))

        self._virtual_work = dolfin.derivative(
            internal_energy * dx,
            self.state,
            self.state_test,
        )

        external_work = self._external_work(u, v)
        if external_work is not None:
            self._virtual_work += external_work

        self._set_dirichlet_bc()
        self._jacobian = dolfin.derivative(
            self._virtual_work,
            self.state,
            dolfin.TrialFunction(self.state_space),
        )
        self._init_solver()
示例#4
0
    def _init_forms(self):

        u = self.state
        v = self.state_test

        F = dolfin.variable(DeformationGradient(u))
        J = Jacobian(F)

        dx = self.geometry.dx

        # Add penalty term
        internal_energy = self.material.strain_energy(F) \
            + self.kappa * (J * dolfin.ln(J) - J + 1)

        self._virtual_work \
            = dolfin.derivative(internal_energy * dx,
                                self.state, self.state_test)

        self._virtual_work += self._external_work(u, v)

        self._jacobian \
            = dolfin.derivative(self._virtual_work, self.state,
                                dolfin.TrialFunction(self.state_space))

        self._set_dirichlet_bc()
示例#5
0
    def _init_forms(self):

        u, p, pinn = dolfin.split(self.state)
        v, q, qinn = dolfin.split(self.state_test)

        F = dolfin.variable(DeformationGradient(u))
        J = Jacobian(F)

        ds = self.geometry.ds
        dsendo = ds(self.geometry.markers['ENDO'])
        dx = self.geometry.dx

        endoarea = dolfin.assemble(dolfin.Constant(1.0) * dsendo)

        internal_energy = self.material.strain_energy(F) * dx \
            + self.material.compressibility(p, J) * dx \
            + (pinn * (self._V0/endoarea - self._Vu)) * dsendo

        self._virtual_work \
            = dolfin.derivative(internal_energy,
                                self.state, self.state_test)

        self._virtual_work += self._external_work(u, v)

        self._jacobian \
            = dolfin.derivative(self._virtual_work, self.state,
                                dolfin.TrialFunction(self.state_space))

        self._set_dirichlet_bc()
    def _external_work(self, u, v):

        F = dolfin.variable(kinematics.DeformationGradient(u))

        N = self.geometry.facet_normal
        ds = self.geometry.ds
        dx = self.geometry.dx

        external_work = []

        for neumann in self.bcs.neumann:

            n = neumann.traction * ufl.cofac(F) * N
            external_work.append(dolfin.inner(v, n) * ds(neumann.marker))

        for robin in self.bcs.robin:

            external_work.append(
                dolfin.inner(robin.value * u, v) * ds(robin.marker))

        for body_force in self.bcs.body_force:

            external_work.append(
                -dolfin.derivative(dolfin.inner(body_force, u) * dx, u, v), )

        if len(external_work) > 0:
            return list_sum(external_work)

        return None
示例#7
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
示例#8
0
    def CauchyStress(self, F, p=None, deviatoric=False):

        F = dolfin.variable(F)

        # First Piola Kirchoff
        if deviatoric:
            p = None

        P = self.FirstPiolaStress(F, p)

        # Cauchy stress
        T = kinematics.InversePiolaTransform(P, F)

        return T
    def __init__(self, u):
        '''Deformation measures.'''

        self.d = d = len(u)
        self.I = I = Identity(d)
        self.F = F = variable(I + grad(u))

        self.C = C = F.T * F
        self.E = 0.5 * (C - I)
        self.J = det(F)

        self.I1 = tr(C)
        self.I2 = 0.5 * (tr(C)**2 - tr(C * C))
        self.I3 = det(C)
示例#10
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
示例#11
0
    def _init_forms(self):

        p, u, r = dolfin.split(self.state)
        q, v, w = dolfin.split(self.state_test)

        F = dolfin.variable(DeformationGradient(u))
        J = Jacobian(F)

        dx = self.geometry.dx

        # Add penalty term
        internal_energy = self.material.strain_energy(
            F,
        ) + self.material.compressibility(p, J)

        self._virtual_work = dolfin.derivative(
            internal_energy * dx,
            self.state,
            self.state_test,
        )

        self._virtual_work += dolfin.derivative(
            rigid_motion_term(
                mesh=self.geometry.mesh,
                u=u,
                r=r,
            ),
            self.state,
            self.state_test,
        )

        self._jacobian = dolfin.derivative(
            self._virtual_work,
            self.state,
            dolfin.TrialFunction(self.state_space),
        )

        self._init_solver()
示例#12
0
def main(traction, outfile='displacement.json'):

    # Create the Beam geometry
    # Length
    L = 10
    # Width
    W = 1

    print('Got traction of {} kN'.format(traction))

    # Create mesh
    mesh = dolfin.BoxMesh(dolfin.Point(0, 0, 0), dolfin.Point(L, W, W), 30, 3,
                          3)

    # Mark boundary subdomians
    left = dolfin.CompiledSubDomain("near(x[0], side) && on_boundary", side=0)
    bottom = dolfin.CompiledSubDomain("near(x[2], side) && on_boundary",
                                      side=0)

    boundary_markers = dolfin.MeshFunction("size_t", mesh,
                                           mesh.topology().dim() - 1)
    boundary_markers.set_all(0)

    left_marker = 1
    bottom_marker = 2

    left.mark(boundary_markers, left_marker)
    bottom.mark(boundary_markers, bottom_marker)

    f = dolfin.File('boundary_markers.pvd')
    f << boundary_markers

    P2 = dolfin.VectorElement("Lagrange", mesh.ufl_cell(), 2)
    P1 = dolfin.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    state_space = dolfin.FunctionSpace(mesh, P2 * P1)
    state = dolfin.Function(state_space)
    state_test = dolfin.TestFunction(state_space)
    u, p = dolfin.split(state)
    v, q = dolfin.split(state_test)

    # Some mechanical quantities
    I = dolfin.Identity(3)
    gradu = dolfin.grad(u)
    F = dolfin.variable(I + gradu)
    J = dolfin.det(F)

    # Material properites
    mu = dolfin.Constant(100.0)
    lmbda = dolfin.Constant(1.0)
    epsilon = 0.5 * (gradu + gradu.T)
    # Strain energy
    W = lmbda / 2 * (dolfin.tr(epsilon)**2) \
        + mu * dolfin.tr(epsilon * epsilon)

    internal_energy = W - p * (J - 1)

    # Neumann BC
    N = dolfin.FacetNormal(mesh)
    p_bottom = dolfin.Constant(traction)
    external_work = dolfin.inner(v, p_bottom * dolfin.cofac(F) * N) \
        * dolfin.ds(bottom_marker, subdomain_data=boundary_markers)

    # Virtual work
    G = dolfin.derivative(internal_energy * dolfin.dx, state,
                          state_test) + external_work

    # Anchor the left side
    bcs = dolfin.DirichletBC(state_space.sub(0),
                             dolfin.Constant((0.0, 0.0, 0.0)), left)

    # Traction at the bottom of the beam
    dolfin.solve(G == 0, state, [bcs])

    # Get displacement and hydrostatic pressure
    u, p = state.split(deepcopy=True)

    point = np.array([10.0, 0.5, 1.0])
    disp = np.zeros(3)
    u.eval(disp, point)

    print(('Get z-position of point ({}): {:.4f} mm'
           '').format(', '.join(['{:.1f}'.format(p) for p in point]),
                      point[2] + disp[2]))

    with open(outfile, 'w') as f:
        json.dump({
            'point': point.tolist(),
            'displacement': disp.tolist()
        },
                  f,
                  indent=4)

    print('Output saved to {}'.format(outfile))

    V = dolfin.VectorFunctionSpace(mesh, "CG", 1)
    u_int = dolfin.interpolate(u, V)
    moved_mesh = dolfin.Mesh(mesh)
    dolfin.ALE.move(mesh, u_int)
    f = dolfin.File('mesh.pvd')
    f << mesh
    f = dolfin.File('bending_beam.pvd')
    f << moved_mesh
    def _init_form(self):
        m = TrialFunction(self.state_space)
        m_n = self.state_previous
        v = self.state_test
        u = self.displacement
        du = self.mech_velocity
        p = self.pressure

        N = self.parameters['N']

        # Get parameters
        rho = Constant(self.parameters['rho'])
        beta = [Constant(beta) for beta in self.parameters['beta']]
        if isinstance(self.parameters['K'], float):
            K = [self.parameters['K']]
        else:
            K = self.parameters['K']
        if self.geometry.f0 is not None:
            self.K = [self.permeability_tensor(k) for k in K]
        else:
            self.K = [Constant(k) for k in K]
        dt = self.parameters['dt'] / self.parameters['steps']
        self.qi = self.inflow_rate(self.parameters['qi'])
        self.qo = self.inflow_rate(self.parameters['qo'])
        k = Constant(1 / dt)
        theta = self.parameters['theta']

        # Crank-Nicolson time scheme
        M = Constant(theta) * m + Constant(1 - theta) * m_n

        # Mechanics
        from ufl import grad as ufl_grad
        dx = self.geometry.dx
        d = self.state.geometric_dimension()
        I = Identity(d)
        F = df.variable(kinematics.DeformationGradient(u))
        J = kinematics.Jacobian(F)

        if N == 1:
            self._form = k * (m - m_n) * v * dx
        else:
            self._form = sum(
                [k * (m[i] - m_n[i]) * v[i] * dx for i in range(N)])

        # porous dynamics
        if self.parameters['mechanics']:
            F = df.variable(kinematics.DeformationGradient(u))
            J = kinematics.Jacobian(F)
            A = [J * df.inv(F) * K * df.inv(F.T) for K in self.K]
        else:
            A = [Constant(1.0) * K for K in self.K]

        if N == 1:
            self._form += -rho * df.div(A[0] * df.grad(p[0])) * v * dx
        else:
            self._form += -rho * sum(
                [df.div(A[i] * df.grad(p[i])) * v[i] * dx for i in range(N)])

        # compartment coupling
        if N > 1:
            # forward
            self._form -= sum([
                -J * beta[i] * (p[i] - p[i + 1]) * v[i] * dx
                for i in range(N - 1)
            ])
            # backward
            self._form -= sum([
                -J * beta[i - 1] * (p[i] - p[i - 1]) * v[i] * dx
                for i in range(1, N)
            ])

        # add mechanics
        if self.parameters['mechanics']:
            if N == 1:
                self._form -= df.dot(df.grad(M), du) * v * dx
            else:
                self._form -= sum(
                    [df.dot(df.grad(M[i]), du) * v[i] * dx for i in range(N)])

        # Add inflow/outflow terms
        if N == 1:
            self._form -= rho * self.qi * v * dx + rho * self.qo * v * dx
        else:
            self._form -= rho * self.qi * v[0] * dx + rho * self.qo * v[-1] * dx
示例#14
0
bcs.append(DirichletBC(Vx, zero, boundary_markers, id_subdomain_fix))
bcs.append(DirichletBC(Vx, uxD_msr, boundary_markers, id_subdomain_msr))

bcs.append(DirichletBC(V, zeros, fixed_vertex_000, "pointwise"))
bcs.append(DirichletBC(Vz, zero, fixed_vertex_010, "pointwise"))

### Define hyperelastic material model

material_parameters = {'E': Constant(1.0), 'nu': Constant(0.0)}

E, nu = material_parameters.values()

d = len(u)  # Displacement dimension

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)
    else:
        raise ValueError('Parameter `force_domain`')

    ### Material model

    E = Constant(1000.0)  # Young's modulus
    nu = Constant(0.3)  # Poisson's ratio

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

    if large_deformations:

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

        I1 = dolfin.tr(C)
        det_F = dolfin.det(F)

        # Strain energy density of a Neo-Hookean material
        psi = (mu / 2.0) * (I1 - len(u) - 2.0 * dolfin.ln(det_F)) + (
            lm / 2.0) * dolfin.ln(det_F)**2

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

    else:

        I = dolfin.Identity(len(u))
 def calculate_pressure(self, displacement, solid_pressure):
     pspace = self.pprob.pressure_space
     F = df.variable(pulse.kinematics.DeformationGradient(displacement))
     return df.project(-self.SecondPiolaStress(F, p=solid_pressure)[0, 0],
                       pspace)
示例#17
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