예제 #1
0
파일: mfem.py 프로젝트: tianjuxue/crack
def inverse_map_function_ufl(x, control_points, impact_radii, map_type):
    if len(control_points) == 0:
        return x
    x = fe.variable(x)
    df, rho = distance_function_segments_ufl(x, control_points, impact_radii)
    grad_x = fe.diff(df, x)
    delta_x = fe.conditional(
        fe.gt(df, rho), fe.Constant((0., 0.)),
        grad_x * (rho * inverse_ratio_function_ufl(df / rho, map_type) - df))
    return delta_x + x
예제 #2
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]
예제 #3
0
    def build_weak_form_staggered(self):
        self.x_hat = fe.variable(fe.SpatialCoordinate(self.mesh))
        self.x = fe.variable(
            map_function_ufl(self.x_hat, self.control_points,
                             self.impact_radii, self.map_type,
                             self.boundary_info))
        self.grad_gamma = fe.diff(self.x, self.x_hat)

        def mfem_grad_wrapper(grad):
            def mfem_grad(u):
                return fe.dot(grad(u), fe.inv(self.grad_gamma))

            return mfem_grad

        self.mfem_grad = mfem_grad_wrapper(fe.grad)

        self.psi_plus = partial(self.psi_plus_linear_elasticity,
                                lamda=self.lamda,
                                mu=self.mu)
        self.psi_minus = partial(self.psi_minus_linear_elasticity,
                                 lamda=self.lamda,
                                 mu=self.mu)
        self.psi = partial(psi_linear_elasticity, lamda=self.lamda, mu=self.mu)

        sigma_plus = cauchy_stress_plus(strain(self.mfem_grad(self.x_new)),
                                        self.psi_plus)
        sigma_minus = cauchy_stress_minus(strain(self.mfem_grad(self.x_new)),
                                          self.psi_minus)

        self.u_exact, self.d_exact = self.compute_analytical_solutions_fully_broken(
            self.x)

        self.G_u = (g_d(self.d_exact) * fe.inner(sigma_plus, strain(self.mfem_grad(self.eta))) \
            + fe.inner(sigma_minus, strain(self.mfem_grad(self.eta)))) * fe.det(self.grad_gamma) * fe.dx

        self.G_d = (self.d_new - self.d_exact) * self.zeta * fe.det(
            self.grad_gamma) * fe.dx

        self.u_initial = self.nonzero_initial_guess(self.x)
        self.x_new.assign(fe.project(self.u_initial, self.U))
예제 #4
0
파일: pde.py 프로젝트: tianjuxue/crack
    def build_weak_form_staggered(self):
        self.x_hat = fe.variable(fe.SpatialCoordinate(self.mesh))
        self.x = map_function_ufl(self.x_hat, self.control_points,
                                  self.impact_radii, self.map_type,
                                  self.boundary_info)
        self.grad_gamma = fe.diff(self.x, self.x_hat)

        def mfem_grad_wrapper(grad):
            def mfem_grad(u):
                return fe.dot(grad(u), fe.inv(self.grad_gamma))

            return mfem_grad

        self.mfem_grad = mfem_grad_wrapper(fe.grad)

        # A special note (Tianju): We hope to use Model C, but Newton solver fails without the initial guess by Model A
        if self.i < 2:
            self.psi_plus = partial(psi_plus_linear_elasticity_model_A,
                                    lamda=self.lamda,
                                    mu=self.mu)
            self.psi_minus = partial(psi_minus_linear_elasticity_model_A,
                                     lamda=self.lamda,
                                     mu=self.mu)
        else:
            self.psi_plus = partial(psi_plus_linear_elasticity_model_C,
                                    lamda=self.lamda,
                                    mu=self.mu)
            self.psi_minus = partial(psi_minus_linear_elasticity_model_C,
                                     lamda=self.lamda,
                                     mu=self.mu)
            print("use model C")

        self.psi = partial(psi_linear_elasticity, lamda=self.lamda, mu=self.mu)

        self.sigma_plus = cauchy_stress_plus(
            strain(self.mfem_grad(self.x_new)), self.psi_plus)
        self.sigma_minus = cauchy_stress_minus(
            strain(self.mfem_grad(self.x_new)), self.psi_minus)

        # self.sigma = cauchy_stress_plus(strain(self.mfem_grad(self.x_new)), self.psi)
        # self.sigma_degraded = g_d(self.d_new) * self.sigma_plus + self.sigma_minus

        self.G_u = (g_d(self.d_new) * fe.inner(self.sigma_plus, strain(self.mfem_grad(self.eta))) \
            + fe.inner(self.sigma_minus, strain(self.mfem_grad(self.eta)))) * fe.det(self.grad_gamma) * fe.dx

        if self.solution_scheme == 'explicit':
            self.G_d = (self.H_old * self.zeta * g_d_prime(self.d_new, g_d) \
                    + self.G_c / self.l0 * (self.zeta * self.d_new + self.l0**2 * fe.inner(self.mfem_grad(self.zeta), self.mfem_grad(self.d_new)))) * fe.det(self.grad_gamma) * fe.dx
        else:
            self.G_d = (history(self.H_old, self.psi_plus(strain(self.mfem_grad(self.x_new))), self.psi_cr) * self.zeta * g_d_prime(self.d_new, g_d) \
                    + self.G_c / self.l0 * (self.zeta * self.d_new + self.l0**2 * fe.inner(self.mfem_grad(self.zeta), self.mfem_grad(self.d_new)))) * fe.det(self.grad_gamma) * fe.dx
    def _solve(self, z, x=None):
        # problem variables
        du = TrialFunction(self.V)                          # incremental displacement
        v = TestFunction(self.V)                            # test function
        u = Function(self.V)                                # displacement from previous iteration

        # kinematics
        ii = Identity(3)                                    # identity tensor dimension 3
        f = ii + grad(u)                                    # deformation gradient
        c = f.T * f                                         # right Cauchy-Green tensor

        # invariants of deformation tensors
        ic = tr(c)
        j = det(f)

        # elasticity parameters
        if type(z) in [list, np.ndarray]:
            param = self.param_remapper(z[0]) if self.param_remapper is not None else z[0]
        else:
            param = self.param_remapper(z) if self.param_remapper is not None else z

        e_var = variable(Constant(param))                   # Young's modulus
        nu = Constant(.3)                                   # Shear modulus (Lamè's second parameter)
        mu, lmbda = e_var / (2 * (1 + nu)), e_var * nu / ((1 + nu) * (1 - 2 * nu))

        # strain energy density, total potential energy
        psi = (mu / 2) * (ic - 3) - mu * ln(j) + (lmbda / 2) * (ln(j)) ** 2
        pi = psi * dx - self.time * dot(self.f, u) * self.ds(3)

        ff = derivative(pi, u, v)                           # compute first variation of pi
        jj = derivative(ff, u, du)                          # compute jacobian of f

        # solving
        if x is not None:
            numeric_evals = np.zeros(shape=(x.shape[1], len(self.times)))
            evals = np.zeros(shape=(x.shape[1], len(self.eval_times)))
        else:
            numeric_evals = None
            evals = None
        for it, t in enumerate(self.times):
            self.time.t = t
            self.solver(ff == 0, u, self.bcs, J=jj, bcs=self.bcs, solver_parameters=self.solver_parameters)
            if x is not None:
                numeric_evals[:, it] = np.log(np.array([-u(x_)[2] for x_ in x.T]).T)

        # time-interpolation
        if x is not None:
            for i in range(evals.shape[0]):
                evals[i, :] = np.interp(self.eval_times, self.times, numeric_evals[i, :])
        return (evals, u) if x is not None else u
예제 #6
0
def solve_steady_state_heiser_weissinger(kappa):

    w = fe.Function(V_up)
    (u, p) = fe.split(w)
    p = fe.variable(p)
    (eta, q) = fe.TestFunctions(V_up)
    dw = fe.TrialFunction(V_up)

    kappa = fe.Constant(kappa)

    bcs_u, bcs_p, bcs_v = load_2d_muscle_bc(V_up.sub(0), V_up.sub(1), None,
                                            boundaries)

    F = deformation_grad(u)
    I_1, I_2, J = invariants(F)
    F_iso = isochronic_deformation_grad(F, J)
    I_1_iso, I_2_iso = invariants(F)[0:2]

    W = material_mooney_rivlin(I_1_iso, I_2_iso, c_10,
                               c_01)  #+ incompr_relaxation(p, kappa)
    g = incompr_constr(J)

    # Lagrange function (without constraint)
    L = -W

    # Modified Lagrange function (with constraints)
    L_mod = L - p * g
    P = first_piola_stress(L, F)
    G = incompr_stress(g, F)  # = J*fe.inv(F.T)

    Lp = const_eq(L_mod, p)

    a_static = weak_div_term(P + p * G,
                             eta) + inner(B, eta) * dx + inner(Lp, q) * dx

    J_static = fe.derivative(a_static, w, dw)
    ffc_options = {"optimize": True}
    problem = fe.NonlinearVariationalProblem(
        a_static,
        w,
        bcs_u + bcs_p,
        J=J_static,
        form_compiler_parameters=ffc_options)
    solver = fe.NonlinearVariationalSolver(problem)

    solver.solve()

    return w
예제 #7
0
    def _energy_density(self, u):
        young_mod = 100
        poisson_ratio = 0.3
        shear_mod = young_mod / (2 * (1 + poisson_ratio))
        bulk_mod = young_mod / (3 * (1 - 2 * poisson_ratio))
        d = u.geometric_dimension()
        F = self.DeformationGradient(u)
        F = fa.variable(F)
        J = fa.det(F)
        I1 = fa.tr(self.RightCauchyGreen(F))

        # Plane strain assumption
        Jinv = J**(-2 / 3)
        energy = ((shear_mod / 2) * (Jinv * (I1 + 1) - 3) +
                  (bulk_mod / 2) * (J - 1)**2)
        return energy
예제 #8
0
파일: mfem.py 프로젝트: tianjuxue/crack
def map_function_ufl(x_hat,
                     control_points,
                     impact_radii,
                     map_type,
                     boundary_info=None):
    if len(control_points) == 0:
        return x_hat
    x_hat = fe.variable(x_hat)
    df, rho = distance_function_segments_ufl(x_hat, control_points,
                                             impact_radii)
    grad_x_hat = fe.diff(df, x_hat)
    delta_x_hat = fe.conditional(
        fe.gt(df, rho), fe.Constant((0., 0.)),
        grad_x_hat * (rho * ratio_function_ufl(df / rho, map_type) - df))
    if boundary_info is None:
        return delta_x_hat + x_hat
    else:
        last_control_point = control_points[-1]
        points, directions, rho_default = boundary_info
        mid_point, mid_point1, mid_point2 = points
        direct_vec, rotated_vec = directions
        aux_control_point1 = last_control_point + rho_default * rotated_vec
        aux_control_point2 = last_control_point - rho_default * rotated_vec

        w1 = np.linalg.norm(mid_point1 - aux_control_point1)
        w2 = np.linalg.norm(mid_point2 - aux_control_point2)
        w0 = np.linalg.norm(mid_point - last_control_point)

        assert np.absolute(2 * w0 - w1 - w2) < 1e-5

        AB = mid_point - last_control_point
        AP = x_hat - last_control_point

        x1 = AB[0]
        y1 = AB[1]
        x2 = AP[0]
        y2 = AP[1]

        mod = fe.sqrt(x1**2 + y1**2)
        df_to_direct = (x1 * y2 - y1 * x2) / mod  # AB x AP
        df_to_rotated = (x1 * x2 + y1 * y2) / mod

        k1 = rho_default * (w1 + w2) / (rho_default *
                                        (w1 + w2) + df_to_direct * (w1 - w2))

        new_df_to_direct = rho_default * ratio_function_ufl(
            df_to_direct / rho_default, map_type)

        k2 = rho_default * (w1 + w2) / (rho_default *
                                        (w1 + w2) + new_df_to_direct *
                                        (w1 - w2))

        new_df_to_rotated = df_to_rotated * k1 / k2

        x = fe.as_vector(last_control_point + direct_vec * new_df_to_rotated +
                         rotated_vec * new_df_to_direct)

        return fe.conditional(
            fe.gt(df_to_rotated, 0),
            fe.conditional(fe.gt(np.absolute(df_to_direct), rho), x_hat, x),
            delta_x_hat + x_hat)
예제 #9
0
def first_PK_stress_minus(F, psi_minus):
    F = fe.variable(F)
    energy_minus = psi_minus(F)
    P_minus = fe.diff(energy_minus, F)
    return P_minus
예제 #10
0
def g_d_prime(d, degrad_func):
    d = fe.variable(d)
    degrad = degrad_func(d)
    degrad_prime = fe.diff(degrad, d)
    return degrad_prime
예제 #11
0
 def stress(self, u):
     u_var = fe.variable(u)
     C = fe.variable(kin.right_cauchy_green(u_var))
     return 2 * fe.diff(self.strain_energy(u_var), C)
예제 #12
0
def deformation_grad(u):
    I = fe.Identity(dim)
    return fe.variable(I + grad(u))
예제 #13
0
def first_PK_stress(F, psi):
    F = fe.variable(F)
    energy = psi(F)
    P = fe.diff(energy, F)
    return P
예제 #14
0
    integrals_V.append(fe.dot(fLoad, u) * dxp(i))


########################## VARIATIONAL FORMULATION ###########################
# Large displacements kinematics
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


E = largeKinematics(u)
E = fe.variable(E)


# Stored strain energy density for a generic model
def strainDensityFunction(E, Ey, nu):
    mu = Ey / (2. * (1 + nu))
    lambda_ = Ey * nu / ((1 + nu) * (1 - 2 * nu))
    return lambda_ / 2. * (fe.tr(E))**2. + mu * fe.tr(E * E)


# Collect the strain density functions
integrals_E = []
for i in materials:
    psi = strainDensityFunction(E, materials[i][0], materials[i][1])
    integrals_E.append(psi * dxp(i))
예제 #15
0
def cauchy_stress(epsilon, psi):
    epsilon = fe.variable(epsilon)
    energy = psi(epsilon)
    sigma = fe.diff(energy, epsilon)
    return sigma
예제 #16
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)

# Continuation parameter
lmbda = 0.01
예제 #17
0
def cauchy_stress_minus(epsilon, psi_minus):
    epsilon = fe.variable(epsilon)
    energy_minus = psi_minus(epsilon)
    sigma_minus = fe.diff(energy_minus, epsilon)
    return sigma_minus