Esempio n. 1
0
    def setup_mesh(self, m):
        self.m = m
        self.fault_start_idx = m.get_start('fault')
        fault_tris = self.m.get_tris('fault')

        self.unscaled_tri_normals = unscaled_normals(self.m.pts[fault_tris])
        self.tri_size = np.linalg.norm(self.unscaled_tri_normals, axis = 1)
        self.tri_normals = self.unscaled_tri_normals / self.tri_size[:, np.newaxis]

        self.n_tris = self.m.tris.shape[0]
        self.basis_dim = 3
        self.n_dofs = self.basis_dim * self.n_tris
Esempio n. 2
0
    def setup_mesh(self, m):
        if type(m) is CombinedMesh:
            self.m = m
        else:
            self.m = CombinedMesh.from_named_pieces([('fault', m)])

        self.unscaled_tri_normals = unscaled_normals(self.m.pts[self.m.tris])
        self.tri_size = np.linalg.norm(self.unscaled_tri_normals, axis = 1)
        self.tri_normals = self.unscaled_tri_normals / self.tri_size[:, np.newaxis]

        self.n_tris = self.m.tris.shape[0]
        self.basis_dim = 3
        self.n_dofs = self.basis_dim * self.n_tris
Esempio n. 3
0
    def __init__(self, nq, pts, tris, tensor_dim = 3):
        qx, qw = gauss2d_tri(nq)

        tri_pts = pts[tris]
        basis = geometry.linear_basis_tri_arr(qx)

        unscaled_normals = geometry.unscaled_normals(tri_pts)
        jacobians = geometry.jacobians(unscaled_normals)

        basis_factors = []
        for b1 in range(3):
            for b2 in range(3):
                basis_factors.append(np.sum(qw * (basis[:,b1]*basis[:,b2])))
        basis_factors = np.array(basis_factors)
        rows, cols, vals = _mass_op.build_op(basis_factors, jacobians, tensor_dim)

        n_rows = tris.shape[0] * 3 * tensor_dim
        self.shape = (n_rows, n_rows)
        self.mat = scipy.sparse.csr_matrix((vals, (rows, cols)), shape = self.shape)
def traction_continuity_constraints(pts,
                                    surface_tris,
                                    fault_tris,
                                    tensor_dim=3):
    from tectosaur.constraints import ConstraintEQ, Term
    from tectosaur.constraint_builders import find_touching_pts
    from tectosaur.util.geometry import unscaled_normals
    n_surf_tris = surface_tris.shape[0]
    n_fault_tris = fault_tris.shape[0]

    touching_pt = find_touching_pts(surface_tris)
    if fault_tris.shape[0] > 0:
        fault_touching_pt = find_touching_pts(fault_tris)
    else:
        fault_touching_pt = []
    fault_touching_pt.extend(
        [[] for i in range(len(touching_pt) - len(fault_touching_pt))])
    constraints = []

    normals = unscaled_normals(pts[surface_tris])
    normals /= np.linalg.norm(normals, axis=1)[:, np.newaxis]

    jj = 0
    for i, tpt in enumerate(touching_pt):
        if len(tpt) == 0:
            continue

        for independent_idx in range(len(tpt)):
            independent = tpt[independent_idx]
            independent_tri_idx = independent[0]
            independent_tri = surface_tris[independent_tri_idx]

            for dependent_idx in range(independent_idx + 1, len(tpt)):
                dependent = tpt[dependent_idx]
                dependent_tri_idx = dependent[0]
                dependent_tri = surface_tris[dependent_tri_idx]

                n1 = normals[independent_tri_idx]
                n2 = normals[dependent_tri_idx]
                same_plane = np.all(np.abs(n1 - n2) < 1e-6)
                if not same_plane:
                    jj += 1
                    print('not same plane', jj, n1, n2)
                    continue

                # Check for anything that touches across the fault.
                crosses = (fault_tris.shape[0] > 0 and check_if_crosses_fault(
                    independent_tri, dependent_tri, fault_touching_pt,
                    fault_tris))

                if crosses:
                    continue

                for d in range(tensor_dim):
                    independent_dof = (independent_tri_idx * 3 +
                                       independent[1]) * tensor_dim + d
                    dependent_dof = (dependent_tri_idx * 3 +
                                     dependent[1]) * tensor_dim + d
                    if dependent_dof <= independent_dof:
                        continue
                    diff = 0.0
                    constraints.append(
                        ConstraintEQ([
                            Term(1.0, dependent_dof),
                            Term(-1.0, independent_dof)
                        ], diff))
    return constraints
Esempio n. 5
0
def traction_admissibility_constraints(pts, tris, fault_start_idx):
    # At each vertex, there should be three remaining degrees of freedom.
    # Initially, there are n_tris*3 degrees of freedom.
    # So, we need (n_tris-1)*3 constraints.

    touching_pt = find_touching_pts(tris)
    ns = normalize(unscaled_normals(pts[tris]))
    side = get_side_of_fault(pts, tris, fault_start_idx)

    continuity_cs = []
    admissibility_cs = []
    for tpt in touching_pt:
        if len(tpt) == 0:
            continue

        # Separate the triangles touching at the vertex into a groups
        # by the normal vectors for each triangle.
        normal_groups = []
        for i in range(len(tpt)):
            tri_idx = tpt[i][0]
            n = ns[tri_idx]
            joined = False
            for j in range(len(normal_groups)):
                if np.allclose(normal_groups[j][0], n):
                    tri_idx2 = tpt[normal_groups[j][1][0]][0]
                    side1 = side[tri_idx]
                    side2 = side[tri_idx2]
                    crosses = (side1 != side2) and (side1 != 0) and (side2 !=
                                                                     0)
                    fault_tri_idx = None
                    # if crosses:
                    #     continue
                    normal_groups[j][1].append(i)
                    joined = True
                    break
            if not joined:
                normal_groups.append((n, [i]))

        # Continuity within normal group
        for i in range(len(normal_groups)):
            group = normal_groups[i][1]
            independent_idx = group[0]
            independent = tpt[independent_idx]
            independent_tri_idx = independent[0]
            independent_corner_idx = independent[1]
            independent_dof_start = independent_tri_idx * 9 + independent_corner_idx * 3
            for j in range(1, len(group)):
                dependent_idx = group[j]
                dependent = tpt[dependent_idx]
                dependent_tri_idx = dependent[0]
                dependent_corner_idx = dependent[1]
                dependent_dof_start = dependent_tri_idx * 9 + dependent_corner_idx * 3
                for d in range(3):
                    terms = [
                        Term(1.0, dependent_dof_start + d),
                        Term(-1.0, independent_dof_start + d)
                    ]
                    continuity_cs.append(ConstraintEQ(terms, 0.0))

        if len(normal_groups) == 1:
            # Only continuity needed!
            continue

        # assert(len(normal_groups) == 2)

        # Add constant stress constraints
        for i in range(len(normal_groups)):
            tpt_idx1 = normal_groups[i][1][0]
            tri_idx1 = tpt[tpt_idx1][0]
            corner_idx1 = tpt[tpt_idx1][1]
            tri1 = pts[tris[tri_idx1]]
            tri_data1 = (tri1, tri_idx1, corner_idx1)

            for j in range(i + 1, len(normal_groups)):
                tpt_idx2 = normal_groups[j][1][0]
                tri_idx2 = tpt[tpt_idx2][0]
                # print(tri_idx1, tri_idx2)
                corner_idx2 = tpt[tpt_idx2][1]
                tri2 = pts[tris[tri_idx2]]
                tri_data2 = (tri2, tri_idx2, corner_idx2)

                # for c in new_cs:
                #     print(', '.join(['(' + str(t.val) + ',' + str(t.dof) + ')' for t in c.terms]) + ' rhs: ' + str(c.rhs))
                admissibility_cs.append(
                    constant_stress_constraint(tri_data1, tri_data2))
                admissibility_cs.append(equilibrium_constraint(tri_data1))
                admissibility_cs.append(equilibrium_constraint(tri_data2))
    return continuity_cs, admissibility_cs
Esempio n. 6
0
def tri_normal_info(m):
    unscaled_tri_normals = unscaled_normals(m.pts[m.tris])
    tri_size = np.linalg.norm(unscaled_tri_normals, axis=1)
    tri_normals = unscaled_tri_normals / tri_size[:, np.newaxis]
    return unscaled_tri_normals, tri_size, tri_normals