Esempio n. 1
0
def jump_constraints(jump, negative):
    n_dofs_per_side = jump.shape[0]
    cs = []
    coeff_2 = 1.0 if negative else -1.0
    for i in range(n_dofs_per_side):
        dof_1 = i
        dof_2 = i + n_dofs_per_side
        ts = []
        ts.append(Term(1.0, dof_1))
        ts.append(Term(coeff_2, dof_2))
        cs.append(ConstraintEQ(ts, jump[i]))
    return cs
Esempio n. 2
0
def fault_surf_intersection_traction_constraints(m):
    surf_tris = m.get_tris('surf')
    unscaled_ns = tct.util.geometry.unscaled_normals(m.pts[surf_tris])
    ns = tct.util.geometry.normalize(unscaled_ns)
    pt_ns = np.zeros((m.pts.shape[0], 3))
    for i in range(m.n_tris('surf')):
        for d in range(3):
            pt_ns[m.tris[i,d]] += ns[i]
    n_ns = np.ones((m.pts.shape[0]))
    unique, counts = np.unique(surf_tris, return_counts=True)
    n_ns[unique] = counts
    pt_ns /= n_ns[:,np.newaxis]
    cs = []
    for i in m.get_tri_idxs('fault'):
        for d in range(3):
            n = pt_ns[m.tris[i,d]]
            if np.all(n == 0):
                continue
            assert(np.where(surf_tris == m.tris[i,d])[0].shape[0] > 0)
            ts = []
            for d2 in range(3):
                if n[d2] == 0.0:
                    continue
                fault_dof = i * 9 + d * 3 + d2
                ts.append(Term(n[d2], fault_dof))
            cs.append(ConstraintEQ(ts, 0))
    return cs
Esempio n. 3
0
def constant_stress_constraint(tri_data1, tri_data2):
    tri1, tri_idx1, corner_idx1 = tri_data1
    dof_start1 = tri_idx1 * 9 + corner_idx1 * 3
    n1 = np.cross(tri1[1] - tri1[0], tri1[2] - tri1[0])
    n1 /= np.linalg.norm(n1)

    tri2, tri_idx2, corner_idx2 = tri_data2
    dof_start2 = tri_idx2 * 9 + corner_idx2 * 3
    n2 = np.cross(tri2[1] - tri2[0], tri2[2] - tri2[0])
    n2 /= np.linalg.norm(n2)

    terms = []
    for d in range(3):
        terms.append(Term(n1[d], dof_start2 + d))
        terms.append(Term(-n2[d], dof_start1 + d))
    return ConstraintEQ(terms, 0.0)
Esempio n. 4
0
def equilibrium_constraint(tri_data):
    tri, tri_idx, corner_idx = tri_data

    x_to_xp = rot_mat(tri)  # map from x to rotated frame
    x_to_xhat = inv_jacobian(tri)  # map from triangle reference coords to x
    xp_to_xhat = x_to_xhat.dot(x_to_xp.T)

    vals = np.zeros((3, 3))
    for b in range(3):
        for i in range(3):
            for Ik in range(2):
                for Ip in range(3):
                    vals[b, i] += (basis_gradient[Ik, b] * xp_to_xhat[Ik, Ip] *
                                   x_to_xp[Ip, i])
    terms = []
    for b in range(3):
        for d in range(3):
            terms.append(Term(vals[b, d], tri_idx * 9 + b * 3 + d))

    return ConstraintEQ(terms, 0.0)
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. 6
0
 def make_constraint(lhs, rhs):
     terms = []
     for k in range(3):
         terms.append(Term(lhs[1 + k], dof_start1 + k))
         terms.append(Term(-rhs[1 + k], dof_start2 + k))
     out.append(ConstraintEQ(terms, -lhs[0] + rhs[0]))
Esempio n. 7
0
def continuity_constraints(pts, tris, fault_start_idx, tensor_dim=3):
    surface_tris = tris[:fault_start_idx]
    fault_tris = tris[fault_start_idx:]
    touching_pt = find_touching_pts(surface_tris)
    side = get_side_of_fault(pts, tris, fault_start_idx)
    constraints = []
    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_corner_idx = independent[1]
            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_corner_idx = dependent[1]
                dependent_tri = surface_tris[dependent_tri_idx]

                # Check for anything that touches across the fault.
                side1 = side[independent_tri_idx]
                side2 = side[dependent_tri_idx]
                crosses = (side1 != side2) and (side1 != 0) and (side2 != 0)
                fault_tri_idx = None
                if crosses:
                    fault_tri_idxs, fault_corner_idxs = np.where(
                        fault_tris == dependent_tri[dependent_corner_idx])
                    if fault_tri_idxs.shape[0] != 0:
                        fault_tri_idx = fault_tri_idxs[0]
                        fault_corner_idx = fault_corner_idxs[0]

                        # plt_pts = np.vstack((
                        #     pts[independent_tri],
                        #     pts[dependent_tri],
                        #     pts[fault_tris[fault_tri_idx]]
                        # ))
                        # import matplotlib.pyplot as plt
                        # plt.tripcolor(pts[:,0], pts[:,1], tris[:surface_tris.shape[0]], side[:surface_tris.shape[0]])
                        # plt.triplot(plt_pts[:,0], plt_pts[:,1], np.array([[0,1,2]]), 'b-')
                        # plt.triplot(plt_pts[:,0], plt_pts[:,1], np.array([[3,4,5]]), 'k-')
                        # plt.triplot(pts[:,0], pts[:,1], tris[fault_start_idx:], 'r-')
                        # plt.show()

                for d in range(tensor_dim):
                    independent_dof = (independent_tri_idx * 3 +
                                       independent_corner_idx) * tensor_dim + d
                    dependent_dof = (dependent_tri_idx * 3 +
                                     dependent_corner_idx) * tensor_dim + d
                    if dependent_dof <= independent_dof:
                        continue
                    diff = 0.0
                    terms = [
                        Term(1.0, dependent_dof),
                        Term(-1.0, independent_dof)
                    ]
                    if fault_tri_idx is not None:
                        fault_dof = (fault_start_idx * 9 + fault_tri_idx * 9 +
                                     fault_corner_idx * 3 + d)
                        if side1 < side2:
                            terms.append(Term(-1.0, fault_dof))
                        else:
                            terms.append(Term(1.0, fault_dof))
                    constraints.append(ConstraintEQ(terms, 0.0))
    return constraints
Esempio n. 8
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