示例#1
0
文件: pde.py 项目: tianjuxue/crack
 def set_boundaries(self):
     self.boundaries = fe.MeshFunction("size_t", self.mesh,
                                       self.mesh.topology().dim() - 1)
     self.boundaries.set_all(0)
     self.ds = fe.Measure("ds")(subdomain_data=self.boundaries)
     self.I = fe.Identity(self.mesh.topology().dim())
     self.normal = fe.FacetNormal(self.mesh)
示例#2
0
def largeKinematics(u):
    d = u.geometric_dimension()
    I = fe.Identity(d)
    Fgrad = I + fe.grad(u)
    C = Fgrad.T * Fgrad
    E = 0.5 * (C - I)
    return E
示例#3
0
    def __setup_a_priori(self):
        """Sets up the attributes and petsc solver for the a priori quality check.

		Returns
		-------
		None
		"""

        options = [[['ksp_type', 'preonly'], ['pc_type', 'jacobi'],
                    ['pc_jacobi_type', 'diagonal'], ['ksp_rtol', 1e-16],
                    ['ksp_atol', 1e-20], ['ksp_max_it', 1000]]]
        self.ksp_prior = PETSc.KSP().create()
        _setup_petsc_options([self.ksp_prior], options)

        self.transformation_container = fenics.Function(
            self.form_handler.deformation_space)
        dim = self.mesh.geometric_dimension()

        if not self.volume_change > 1:
            raise ConfigError('MeshQuality', 'volume_change',
                              'This parameter has to be larger than 1.')

        self.a_prior = self.trial_dg0 * self.test_dg0 * self.dx
        self.L_prior = fenics.det(
            fenics.Identity(dim) + fenics.grad(self.transformation_container)
        ) * self.test_dg0 * self.dx
示例#4
0
def Kinematics(u):
    # Kinematics
    d = u.geometric_dimension()
    I = fe.Identity(d)                    # Identity tensor
    F = I + fe.grad(u)                    # Deformation gradient
    F = fe.variable(F)                    # To differentiate Psi(F)
    J = fe.det(F)                         # Jacobian of F
    C = F.T*F                             # Right Cauchy-Green deformation tensor
    Ic = fe.tr(C)                         # Trace of C
    
    return [F, J, C, Ic]
示例#5
0
    def compute_shape_derivative(self):
        """Computes the part of the shape derivative that comes from the regularization

		Returns
		-------
		ufl.form.Form
			The weak form of the shape derivative coming from the regularization

		"""

        V = self.form_handler.test_vector_field
        if self.has_regularization:

            n = fenics.FacetNormal(self.form_handler.mesh)
            I = fenics.Identity(self.form_handler.mesh.geometric_dimension())

            self.shape_form = Constant(self.mu_surface) * (
                self.current_surface - Constant(self.target_surface)) * t_div(
                    V, n) * self.ds

            if not self.measure_hole:
                self.shape_form += Constant(self.mu_volume) * (
                    self.current_volume -
                    Constant(self.target_volume)) * div(V) * self.dx
                self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_x - Constant(self.target_barycenter_list[0]))\
                         *(self.current_barycenter_x/self.current_volume*div(V) + 1/self.current_volume*(V[0] + self.spatial_coordinate[0]*div(V)))*self.dx \
                       + Constant(self.mu_barycenter)*(self.current_barycenter_y - Constant(self.target_barycenter_list[1]))\
                         *(self.current_barycenter_y/self.current_volume*div(V) + 1/self.current_volume*(V[1] + self.spatial_coordinate[1]*div(V)))*self.dx

                if self.form_handler.mesh.geometric_dimension() == 3:
                    self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_z - Constant(self.target_barycenter_list[2]))\
                           *(self.current_barycenter_z/self.current_volume*div(V) + 1/self.current_volume*(V[2] + self.spatial_coordinate[2]*div(V)))*self.dx

            else:
                self.shape_form -= Constant(self.mu_volume) * (
                    self.current_volume -
                    Constant(self.target_volume)) * div(V) * self.dx
                self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_x - Constant(self.target_barycenter_list[0]))\
                         *(self.current_barycenter_x/self.current_volume*div(V) - 1/self.current_volume*(V[0] + self.spatial_coordinate[0]*div(V)))*self.dx \
                       + Constant(self.mu_barycenter)*(self.current_barycenter_y - Constant(self.target_barycenter_list[1]))\
                         *(self.current_barycenter_y/self.current_volume*div(V) - 1/self.current_volume*(V[1] + self.spatial_coordinate[1]*div(V)))*self.dx

                if self.form_handler.mesh.geometric_dimension() == 3:
                    self.shape_form += Constant(self.mu_barycenter)*(self.current_barycenter_z - Constant(self.target_barycenter_list[2]))\
                             *(self.current_barycenter_z/self.current_volume*div(V) - 1/self.current_volume*(V[2] + self.spatial_coordinate[2]*div(V)))*self.dx

            return self.shape_form

        else:
            dim = self.form_handler.mesh.geometric_dimension()
            return inner(fenics.Constant([0] * dim), V) * self.dx
def sigma(u):
    return lambda_ * fs.nabla_grad(u) * fs.Identity(d) + 2 * mu * epsilon(u)
v = fs.TestFunction(V)
f = fs.Constant((0, 0, -rho * g))
T = fs.Constant((0, 0, 0))
a = fs.inner(sigma(u), epsilon(v)) * fs.dx
L = fs.dot(f, v) * fs.dx + fs.dot(T, v) * fs.ds

# Compute solution
u = fs.Function(V)
fs.solve(a == L, u, bc)

# Plot solution
plt.figure()
fs.plot(u, title='Displacement', mode='displacement')

# Plot stress
s = sigma(u) - (1. / 3) * fs.tr(sigma(u)) * fs.Identity(d)  # deviatoric stress
von_Mises = fs.sqrt(3. / 2 * fs.inner(s, s))
V = fs.FunctionSpace(mesh, 'P', 1)
von_Mises = fs.project(von_Mises, V)
plt.figure()
fs.plot(von_Mises, title='Stress intensity')

# Compute magnitude of displacement
u_magnitude = fs.sqrt(fs.dot(u, u))
u_magnitude = fs.project(u_magnitude, V)
plt.figure()
fs.plot(u_magnitude, title='Displacement magnitude')
print('min/max u:', u_magnitude.vector().min(), u_magnitude.vector().max())

# Save solution to file in VTK format
fs.File('results/displacement.pvd') << u
def D(E, sigma):  # this is important: it's where the coupling occurs
    return fn.Identity(2) * D0 * (1 + D0*E) + pow(D0, 2) * sigma
# time loop
iteration = 0
while t <= TFinal:
    # log time
    print "t =", t
    
    # solve poroelasticity
    fn.solve(pe_left_hand_side == pe_right_hand_side,
             pe_solution,
             boundary_conditions)
    
    # split
    u, phi, p = pe_solution.split()
    
    # calculate sigma and z
    sigma = fn.project(2 * mu * strain(u_old) - phi * fn.Identity(2) + \
            n_old * c_1 * fn.outer(f_0, f_0), Whf)
    z = fn.project((u - u_old)/dt, Vhf)
    
    rd_rhs_2 = rd_right_hand_side + Istim(t) * F * fn.dx
    
    # solve reaction-diffusion
    fn.solve(rd_left_hand_side == rd_rhs_2,
             rd_solution)
    
    # split
    E, n = rd_solution.split()
    
    # save if divisible by frequency
    if iteration % frequency == 0:
        u.rename("u", "u")
示例#10
0
def def_grad(u):
    I = fe.Identity(u.ufl_shape[0])
    return I + fe.grad(u)
示例#11
0
 def sigma_d(u):
     return eta_b * ufl.nabla_div(u) * fenics.Identity(
         2) + 2 * eta_s * epsilon(u)
示例#12
0
 def get_new_value(self, r: fenics.Function) -> fenics.Expression:
     return 2.0*self.lame_mu*fenics.sym(fenics.grad(r)) \
            + self.lame_lambda*fenics.tr(fenics.sym(fenics.grad(r)))*fenics.Identity(len(r))
示例#13
0
def sigma(r):
    return 2.0 * mu * fnc.sym(fnc.grad(r)) + lmbda * fnc.tr(
        fnc.sym(fnc.grad(r))) * fnc.Identity(len(r))
示例#14
0
def deformation_grad(u):
    I = fe.Identity(dim)
    return fe.variable(I + grad(u))
示例#15
0
 def Identity(self, dim):
     return FEN.Identity(dim)
示例#16
0
 def DeformationGradient(self, u):
     I = fa.Identity(u.geometric_dimension())
     return I + fa.grad(u)
示例#17
0
 def sigma_a(u, rho):
     return -zeta_1 * rho / (
         1 + zeta_2 * rho) * mu_a * fenics.Identity(2) * (K_0)
示例#18
0
def sigma(u, p):
    return 2*mu*epsilon(u) - p*fs.Identity(len(u))
示例#19
0
uViewer << u

# Maximum and minimum displacement
u_magnitude = fe.sqrt(fe.dot(u, u))
u_magnitude = fe.project(u_magnitude, W)
print('Min/Max displacement:',
      u_magnitude.vector().array().min(),
      u_magnitude.vector().array().max())

# Computation of the large deformation strains
#cprint("Computing the deformation tensor and saving to file...", 'green')
epsilon_u = largeKinematics(u)
epsilon_u_project = fe.project(epsilon_u, Z)
epsilonViewer = fe.File('paraview/strain.pvd')
epsilonViewer << epsilon_u_project

# Computation of the stresses
#cprint("Stress derivation and saving to file...", 'green')
S = fe.diff(psi, E)
S_project = fe.project(S, Z)
sigmaViewer = fe.File('paraview/stress.pvd')
sigmaViewer << S_project

# Computation of an equivalent stress
s = S - (1. / 3) * fe.tr(S) * fe.Identity(u.geometric_dimension())
von_Mises = fe.sqrt(3. / 2 * fe.inner(s, s))
von_Mises_project = fe.project(von_Mises, W)
misesViewer = fe.File('paraview/mises.pvd')
misesViewer << von_Mises_project
print("Maximum equivalent stress:", von_Mises_project.vector().array().max())
示例#20
0
    def solve(self):
        """
        Solve the Stokes_sim problem based on the mathematical procedure presented by Ximo in this thesis.
        Returns:

        """

        # --------------------------------------------------------------------
        # DEFINE THE INPUTS #
        # --------------------------------------------------------------------
        self.get_mesh()
        self.get_boundaries()
        self.get_subdomains()
        self.get_restrictions()

        # Create a block of restrictions.
        """ This variable will be used by multiphenics when creating function spaces. It will create function spaces
        on the introduced restrictions. 
        """
        block_restrictions = [
            self.restrictions_dict['liquid_rtc'],
            self.restrictions_dict['liquid_rtc'],
            self.restrictions_dict['interface_rtc']
        ]

        # --------------------------------------------------------------------

        # --------------------------------------------------------------------
        # FUNCTION SPACES #
        # --------------------------------------------------------------------
        V = fn.VectorFunctionSpace(self.mesh, "CG", 2)
        Q = fn.FunctionSpace(self.mesh, "CG", 1)
        L = fn.FunctionSpace(self.mesh, "DGT", 0)  # DGT 0.

        # Create a block function space.
        """ Block Function Spaces are similar to FEniCS function spaces. However, since we are creating function spaces
        based on the block of restrictions, we need to create a 'block of function spaces' for each of the restrictions.
        That block of functions is the list [V, Q, L] from the line of code below this comment. They are assigned in the
        same order in which the block of restrictions has been created, that is:
            - V -> liquid_rtc
            - Q -> liquid_rtc
            - L -> interface_rtc
        """
        W = mp.BlockFunctionSpace([V, Q, L], restrict=block_restrictions)
        # --------------------------------------------------------------------

        # --------------------------------------------------------------------
        # TRIAL/TEST FUNCTIONS #
        # --------------------------------------------------------------------
        """ Trial and test functions are created the multiphenics commands for creating these functions. However, the
        difference wrt the FEniCS functions for this purpose, a trial/test function will be created for each of the
        restrictions (for each function space of the BlockFunctionSpace).
        """
        test = mp.BlockTestFunction(W)
        (v, q, l) = mp.block_split(test)

        trial = mp.BlockTrialFunction(W)
        (u, p, theta) = mp.block_split(trial)

        # Use a value of previous velocity to make the system linear, as explained by Ximo.
        u_prev = fn.Function(V)
        u_prev.assign(fn.Constant((0.1, 0.1)))

        # --------------------------------------------------------------------

        # --------------------------------------------------------------------
        # MEASURES #
        # --------------------------------------------------------------------
        self.get_measures()
        self.dS = self.dS(
            self.boundaries_ids['Interface'])  # Restrict to the interface.

        # Check proper marking of the interface.
        assert fn.assemble(
            1 * self.dS(domain=self.mesh)
        ) > 0., "The length of the interface is zero, wrong marking."

        # --------------------------------------------------------------------
        # DEFINE THE VARIATIONAL PROBLEM #
        # --------------------------------------------------------------------
        r = fn.SpatialCoordinate(self.mesh)[0]
        n = fn.FacetNormal(self.mesh)
        tan_vector = fn.as_vector((n[1], -n[0]))
        e_r = fn.Constant((1., 0.))  # Define unit radial vector
        e_z = fn.Constant((0., 1.))  # Define unit axial vector
        aux_term = (self.eps_r * self.Ca *
                    np.sqrt(self.B)) / (1 + self.Lambda * (self.T_h - 1))

        # Define the term a.
        a = r * aux_term * fn.inner((fn.grad(u) + fn.grad(u).T),
                                    (fn.grad(v) + fn.grad(v).T)) * self.dx(
                                        self.subdomains_ids['Liquid'])
        a += 2 / r * aux_term * fn.dot(u, e_r) * fn.dot(v, e_r) * self.dx(
            self.subdomains_ids['Liquid'])

        # Define the term d.
        del_operation = fn.dot(fn.grad(u), u_prev)
        d = r * self.eps_r**2 * self.We * fn.dot(del_operation, v) * self.dx(
            self.subdomains_ids['Liquid'])

        # Define the term l1.
        def evaporated_charge():
            return (self.sigma * self.T_h) / (self.eps_r * self.Chi) * fn.exp(
                -self.Phi / self.T_h *
                (1 - self.B**0.25 * fn.sqrt(self.E_v_n)))

        l1 = -r * evaporated_charge() * l("+") * self.dS

        # Define the term l2.
        l2 = r * self.sigma * fn.dot(self.E_v, tan_vector("-")) * fn.dot(
            v("+"), tan_vector("-")) * self.dS

        # Define the term b.
        def b(vector, scalar):
            radial_term = r * fn.dot(vector, e_r)
            axial_term = r * fn.dot(vector, e_z)
            return -(radial_term.dx(0) + axial_term.dx(1)) * scalar * self.dx(
                self.subdomains_ids['Liquid'])

        # Define the term c.
        c1 = -r * fn.dot(v("+"), n("-")) * theta("+") * self.dS
        c2 = -r * fn.dot(u("+"), n("-")) * l("+") * self.dS

        # Define the tensors to be solved.
        # The following order is used.
        #       u            p           theta       #
        aa = [
            [a + d, b(v, p), c1],  # Test function v
            [b(u, q), 0, 0],  # Test function q
            [c2, 0, 0]
        ]  # Test function l

        bb = [l2, fn.Constant(0.) * q("+") * self.dS, l1]

        # --------------------------------------------------------------------
        # DEFINE THE BOUNDARY CONDITIONS #
        # --------------------------------------------------------------------
        """ When creating Dirichlet boundary conditions with the multiphenics code, a function space from the Block
        must be selected, depending on which subdomain/boundary should it be applied. To do so, the .sub method is used.
        The input is an integer, which depends on the function space in which you want the BC to be applied. For this
        case, inputs of 0, 1 and 2 are accepted, because we have 3 restrictions. The assignments of these ids to the 
        function space is the one done in the block of restrictions.
        """
        bcs_u = []
        bcs_p = []
        for i in self.boundary_conditions:
            if 'Dirichlet' in self.boundary_conditions[i]:
                bc_val = self.boundary_conditions[i]['Dirichlet'][1]
                if self.boundary_conditions[i]['Dirichlet'][0] == 'v':
                    bc = mp.DirichletBC(W.sub(0), bc_val, self.boundaries,
                                        self.boundaries_ids[i])

                    # Check the created boundary condition.
                    assert len(bc.get_boundary_values()
                               ) > 0., f'Wrongly defined boundary {i}'
                    bcs_u.append(bc)
                elif self.boundary_conditions[i]['Dirichlet'][0] == 'p':
                    bc = mp.DirichletBC(W.sub(1), bc_val, self.boundaries,
                                        self.boundaries_ids[i])
                    # Check the created boundary condition.
                    assert len(bc.get_boundary_values()
                               ) > 0., f'Wrongly defined boundary {i}'
                    bcs_p.append(bc)

        bcs_block = mp.BlockDirichletBC([bcs_u, bcs_p])

        # --------------------------------------------------------------------

        # --------------------------------------------------------------------
        # SOLVE #
        # --------------------------------------------------------------------
        # Assemble the system.
        AA = mp.block_assemble(aa)
        BB = mp.block_assemble(bb)

        # Apply the boundary conditions.
        bcs_block.apply(AA)
        bcs_block.apply(BB)

        # Solve.
        uptheta = mp.BlockFunction(W)
        mp.block_solve(AA, uptheta.block_vector(), BB)
        (u, p, theta) = uptheta.block_split()

        self.u = u
        self.p_star = p
        self.theta = theta

        # Compute normal and tangential velocity components.
        u_n = fn.dot(u, n)
        self.u_n = Stokes.block_project(
            u_n,
            self.mesh,
            self.restrictions_dict['interface_rtc'],
            self.boundaries,
            self.boundaries_ids['Interface'],
            space_type='scalar',
            boundary_type='internal',
            sign='-')

        u_t = fn.dot(u, tan_vector)
        self.u_t = Stokes.block_project(
            u_t,
            self.mesh,
            self.restrictions_dict['interface_rtc'],
            self.boundaries,
            self.boundaries_ids['Interface'],
            space_type='scalar',
            boundary_type='internal',
            sign='+')

        # Compute the convection charge transport.
        special = (fn.Identity(self.mesh.topology().dim()) -
                   fn.outer(n, n)) * fn.grad(self.sigma)
        self.j_conv = self.Kc * self.B**(
            3 / 2) * (fn.dot(self.sigma * n, fn.dot(fn.grad(self.u), n)) -
                      fn.dot(self.u, special))
        self.j_conv = Stokes.block_project(
            self.j_conv,
            self.mesh,
            self.restrictions_dict['interface_rtc'],
            self.boundaries,
            self.boundaries_ids['Interface'],
            space_type='scalar',
            boundary_type='internal',
            sign='-')
示例#21
0
 def sigma_e(u):
     return lambda_ * ufl.nabla_div(u) * fenics.Identity(
         2) + 2 * mu * epsilon(u)
    def compute_static_deformation(self):

        assert self.mesh is not None

        # now we define subdomains on the mesh

        bottom = fe.CompiledSubDomain('near(x[2], 0) && on_boundary')
        top = fe.CompiledSubDomain('near(x[2], 1) && on_boundary')
        # middle = fe.CompiledSubDomain('x[2] > 0.3 && x[2] < 0.7')

        # Initialize mesh function for interior domains
        self.domains = fe.MeshFunction('size_t', self.mesh, 3)
        self.domains.set_all(0)
        # middle.mark(self.domains, 1)

        # Initialize mesh function for boundary domains
        self.boundaries = fe.MeshFunction('size_t', self.mesh, 2)
        self.boundaries.set_all(0)
        bottom.mark(self.boundaries, 1)
        top.mark(self.boundaries, 2)

        # Define new measures associated with the interior domains and
        # exterior boundaries

        self.dx = fe.Measure('dx',
                             domain=self.mesh,
                             subdomain_data=self.domains)
        self.ds = fe.Measure('ds',
                             domain=self.mesh,
                             subdomain_data=self.boundaries)

        # define function spaces
        V = fe.VectorFunctionSpace(self.mesh, "Lagrange", 1)
        # now we define subdomains on the mesh

        bottom = fe.CompiledSubDomain('near(x[2], 0) && on_boundary')
        top = fe.CompiledSubDomain('near(x[2], 1) && on_boundary')
        # middle = fe.CompiledSubDomain('x[2] > 0.3 && x[2] < 0.7')

        d = self.mesh.geometry().dim()

        # Initialize mesh function for interior domains
        self.domains = fe.MeshFunction('size_t', self.mesh, d)
        self.domains.set_all(0)
        # middle.mark(self.domains, 1)

        # Initialize mesh function for boundary domains
        self.boundaries = fe.MeshFunction('size_t', self.mesh, d - 1)
        self.boundaries.set_all(0)
        bottom.mark(self.boundaries, 1)
        top.mark(self.boundaries, 2)

        # Define new measures associated with the interior domains and
        # exterior boundaries

        self.dx = fe.Measure('dx',
                             domain=self.mesh,
                             subdomain_data=self.domains)
        self.ds = fe.Measure('ds',
                             domain=self.mesh,
                             subdomain_data=self.boundaries)

        c_zero = fe.Constant((0, 0, 0))

        # define boundary conditions
        bc_bottom = fe.DirichletBC(V, c_zero, bottom)
        bc_top = fe.DirichletBC(V, c_zero, top)

        bcs = [bc_bottom]  # , bc_top]

        # define functions
        du = TrialFunction(V)
        v = TestFunction(V)
        u = Function(V)
        B = fe.Constant((0., 2.0, 0.))
        T = fe.Constant((0.0, 0.0, 0.0))

        d = u.geometric_dimension()
        I = fe.Identity(d)
        F = I + grad(u)
        C = F.T * F

        I_1 = tr(C)
        J = det(F)

        E, mu = 10., 0.3
        mu, lmbda = fe.Constant(E / (2 * (1 + mu))), fe.Constant(
            E * mu / ((1 + mu) * (1 - 2 * mu)))

        # stored energy (comp. neo-hookean model)
        psi = (mu / 2.) * (I_1 - 3) - mu * fe.ln(J) + (lmbda /
                                                       2.) * (fe.ln(J))**2

        dx = self.dx
        ds = self.ds

        Pi = psi * fe.dx - dot(B, u) * fe.dx - dot(T, u) * fe.ds

        F = fe.derivative(Pi, u, v)
        J = fe.derivative(F, u, du)

        fe.solve(F == 0, u, bcs, J=J)

        # save results
        self.u = u

        # write to disk
        output = fe.File("/tmp/static.pvd")
        output << u
示例#23
0
def sigma(u):
    return (lmbda * fn.tr(eps(u)) * fn.Identity(2) + 2 * mu * eps(u))
示例#24
0
u_right = fe.Expression(("0.0", "0.0", "0.0"), element=element_3)
p_left = fe.Constant(0.)

# Define acting force
b = fe.Constant((0.0, 0.0, 0.0))  # Body force per unit volume
t_bar = fe.Constant((0.0, 0.0, 0.0))  # Traction force on the boundary

# Define test and trial functions
w = fe.Function(V)  # most recently computed solution
(u, p) = fe.split(w)
(v, q) = fe.TestFunctions(V)
dw = fe.TrialFunction(V)

# Kinematics
d = u.geometric_dimension()
I = fe.Identity(d)  # Identity tensor

F = fe.variable(I + grad(u))  # Deformation gradient
C = fe.variable(F.T * F)  # Right Cauchy-Green tensor
J = fe.det(C)

DE = lambda v: 0.5 * (F.T * grad(v) + grad(v).T * F)

a_0 = fe.as_vector([[1.0], [0.], [0.]])

# Invariants
I_1 = tr(C)
I_2 = 0.5 * (tr(C)**2 - tr(C * C))

I_4 = dot(a_0.T, C * a_0)
示例#25
0
def identity(u):
    return fe.Identity(u.ufl_shape[0])