コード例 #1
0
    def test_simple(self):
        V = array([[0,0],[1,0],[0,1]])
        S = array([[0,1,2]])

        sc = simplicial_complex((V,S))

        rows,cols = massmatrix_rowcols(sc,0)

        assert_equal(rows,array([0,0,0,1,1,1,2,2,2]))
        assert_equal(cols,array([0,1,2,0,1,2,0,1,2]))


        rows,cols = massmatrix_rowcols(sc,1)

        edges = [simplex(x) for x in combinations(range(3),2)]
        edge0 = sc[1].simplex_to_index[edges[0]]
        edge1 = sc[1].simplex_to_index[edges[1]]
        edge2 = sc[1].simplex_to_index[edges[2]]

        assert_equal(rows,array([edge0,edge0,edge0,edge1,edge1,edge1,edge2,edge2,edge2]))
        assert_equal(cols,array([edge0,edge1,edge2,edge0,edge1,edge2,edge0,edge1,edge2]))


        rows,cols = massmatrix_rowcols(sc,2)

        assert_equal(rows,array([0]))
        assert_equal(cols,array([0]))
コード例 #2
0
    def test_simple(self):
        V = array([[0, 0], [1, 0], [0, 1]])
        S = array([[0, 1, 2]])

        sc = simplicial_complex((V, S))

        rows, cols = massmatrix_rowcols(sc, 0)

        assert_equal(rows, array([0, 0, 0, 1, 1, 1, 2, 2, 2]))
        assert_equal(cols, array([0, 1, 2, 0, 1, 2, 0, 1, 2]))

        rows, cols = massmatrix_rowcols(sc, 1)

        edges = [simplex(x) for x in combinations(range(3), 2)]
        edge0 = sc[1].simplex_to_index[edges[0]]
        edge1 = sc[1].simplex_to_index[edges[1]]
        edge2 = sc[1].simplex_to_index[edges[2]]

        assert_equal(
            rows,
            array([
                edge0, edge0, edge0, edge1, edge1, edge1, edge2, edge2, edge2
            ]))
        assert_equal(
            cols,
            array([
                edge0, edge1, edge2, edge0, edge1, edge2, edge0, edge1, edge2
            ]))

        rows, cols = massmatrix_rowcols(sc, 2)

        assert_equal(rows, array([0]))
        assert_equal(cols, array([0]))
コード例 #3
0
def massmatrix_rowcols(complex, k):
    """
    Compute the row and column arrays in the COO
    format of the Whitney form mass matrix
    """
    simplices = complex[-1].simplices
    num_simplices = simplices.shape[0]
    p = complex.complex_dimension()

    if k == p:
        #top dimension
        rows = arange(num_simplices, dtype=simplices.dtype)
        cols = arange(num_simplices, dtype=simplices.dtype)
        return rows, cols

    k_faces = [tuple(x) for x in combinations(range(p + 1), k + 1)]

    faces_per_simplex = len(k_faces)
    num_faces = num_simplices * faces_per_simplex
    faces = empty((num_faces, k + 1), dtype=simplices.dtype)

    for n, face in enumerate(k_faces):
        for m, i in enumerate(face):
            faces[n::faces_per_simplex, m] = simplices[:, i]

    #faces.sort() #we can't assume that the p-simplices are sorted

    indices = simplex_array_searchsorted(complex[k].simplices, faces)

    rows = tile(indices.reshape((-1, 1)), (faces_per_simplex, )).flatten()
    cols = tile(indices.reshape((-1, faces_per_simplex)),
                (faces_per_simplex, )).flatten()

    return rows, cols
コード例 #4
0
ファイル: innerproduct.py プロジェクト: DongliangGao/pydec
def massmatrix_rowcols(complex,k):
    """
    Compute the row and column arrays in the COO
    format of the Whitney form mass matrix
    """
    simplices = complex[-1].simplices
    num_simplices = simplices.shape[0]
    p = complex.complex_dimension()
    
    if k == p:
        #top dimension
        rows = arange(num_simplices,dtype=simplices.dtype)
        cols = arange(num_simplices,dtype=simplices.dtype)
        return rows,cols
    
    k_faces = [tuple(x) for x in combinations(range(p+1),k+1)]

    faces_per_simplex = len(k_faces)
    num_faces = num_simplices*faces_per_simplex
    faces     = empty((num_faces,k+1),dtype=simplices.dtype)
   
    for n,face in enumerate(k_faces):
        for m,i in enumerate(face):
            faces[n::faces_per_simplex,m] = simplices[:,i]

    #faces.sort() #we can't assume that the p-simplices are sorted

    indices = simplex_array_searchsorted(complex[k].simplices,faces)

    rows = tile(indices.reshape((-1,1)),(faces_per_simplex,)).flatten()
    cols = tile(indices.reshape((-1,faces_per_simplex)),(faces_per_simplex,)).flatten()

    return rows,cols
コード例 #5
0
ファイル: test_combinatorial.py プロジェクト: cindolfi/pydec
def test_combinations():
    for N in range(6):
        L = list(range(N))
        for K in range(N + 1):
            C = list(combinations(L, K))
            S = set([frozenset(x) for x in C])
            ##Check order
            assert_equal(C, sorted(C))
            ##Check number of elements
            assert_equal(len(C), comb(N, K, exact=True))
            ##Make sure each element is unique
            assert_equal(len(S), comb(N, K, exact=True))
コード例 #6
0
def test_combinations():
    for N in xrange(6):
        L = range(N)            
        for K in xrange(N+1):                
            C = list(combinations(L,K))
            S = set([ frozenset(x) for x in C])
            ##Check order
            assert_equal(C, sorted(C))
            ##Check number of elements
            assert_equal(len(C), comb(N,K,exact=True))
            ##Make sure each element is unique
            assert_equal(len(S), comb(N,K,exact=True))
コード例 #7
0
ファイル: subdivision.py プロジェクト: msebaa/pydec
def loop_subdivision(vertices, simplices):
    """
    Given a triangle mesh represented by the matrices (vertices,simplices), return
    new vertex and simplex arrays for the Loop subdivided mesh.
    """

    #all edges in the mesh
    edges = set()

    for s in simplices:
        edges.update([frozenset(x) for x in combinations(ravel(s), 2)])

    edge_index_map = {}
    for n, e in enumerate(edges):
        edge_index_map[e] = len(vertices) + n

    edge_vertices = []
    for e in edges:
        e0, e1 = sorted(e)
        edge_vertices.append(0.5 * (vertices[e0] + vertices[e1]))

    new_vertices = concatenate((vertices, array(edge_vertices)))
    new_simplices = []

    for n, s in enumerate(simplices):
        v0, v1, v2 = ravel(s)
        e01 = edge_index_map[frozenset((v0, v1))]
        e12 = edge_index_map[frozenset((v1, v2))]
        e20 = edge_index_map[frozenset((v2, v0))]

        new_simplices.append([v0, e01, e20])
        new_simplices.append([v1, e12, e01])
        new_simplices.append([v2, e20, e12])
        new_simplices.append([e01, e12, e20])

    new_simplices = array(new_simplices)

    return new_vertices, new_simplices
コード例 #8
0
ファイル: subdivision.py プロジェクト: DongliangGao/pydec
def loop_subdivision(vertices,simplices):
    """
    Given a triangle mesh represented by the matrices (vertices,simplices), return
    new vertex and simplex arrays for the Loop subdivided mesh.
    """    
    
    #all edges in the mesh
    edges = set()
    
    for s in simplices:        
        edges.update([frozenset(x) for x in combinations(ravel(s),2)])
    
    edge_index_map = {}    
    for n,e in enumerate(edges):
        edge_index_map[e] = len(vertices) + n
    
    edge_vertices = []
    for e in edges:       
        e0,e1 = sorted(e)
        edge_vertices.append(0.5*(vertices[e0] + vertices[e1]))
    
    new_vertices = concatenate((vertices,array(edge_vertices)))
    new_simplices = [] 
    
    for n,s in enumerate(simplices):
        v0,v1,v2 = ravel(s)
        e01 = edge_index_map[frozenset((v0,v1))]
        e12 = edge_index_map[frozenset((v1,v2))]
        e20 = edge_index_map[frozenset((v2,v0))]
        
        new_simplices.append([v0,e01,e20])
        new_simplices.append([v1,e12,e01])
        new_simplices.append([v2,e20,e12])
        new_simplices.append([e01,e12,e20])
        
    new_simplices = array(new_simplices)
    
    return new_vertices,new_simplices
コード例 #9
0
def whitney_innerproduct(complex, k):
    """
    For a given SimplicialComplex, compute a matrix representing the 
    innerproduct of Whitney k-forms
    """
    assert (k >= 0 and k <= complex.complex_dimension())

    ## MASS MATRIX COO DATA
    rows, cols = massmatrix_rowcols(complex, k)
    data = empty(rows.shape)

    ## PRECOMPUTATION
    p = complex.complex_dimension()

    scale_integration = (factorial(k)**2) / ((p + 2) * (p + 1))

    k_forms = [tuple(x) for x in combinations(range(p + 1), k)]
    k_faces = [tuple(x) for x in combinations(range(p + 1), k + 1)]

    num_k_forms = len(k_forms)
    num_k_faces = len(k_faces)

    k_form_pairs = [tuple(x)
                    for x in combinations(k_forms, 2)] + [(x, x)
                                                          for x in k_forms]
    num_k_form_pairs = len(k_form_pairs)
    k_form_pairs_to_index = dict(zip(k_form_pairs, range(num_k_form_pairs)))
    k_form_pairs_to_index.update(
        zip([x[::-1] for x in k_form_pairs], range(num_k_form_pairs)))
    num_k_face_pairs = num_k_faces**2

    if k > 0:
        k_form_pairs_array = array(k_form_pairs)

    #maps flat vector of determinants to the flattened matrix entries
    dets_to_vals = scipy.sparse.lil_matrix(
        (num_k_face_pairs, num_k_form_pairs))

    k_face_pairs = []
    for face1 in k_faces:
        for face2 in k_faces:
            row_index = len(k_face_pairs)

            k_face_pairs.append((face1, face2))

            for n in range(k + 1):
                for m in range(k + 1):
                    form1 = face1[:n] + face1[n + 1:]
                    form2 = face2[:m] + face2[m + 1:]

                    col_index = k_form_pairs_to_index[(form1, form2)]

                    dets_to_vals[row_index, col_index] += (-1)**(n + m) * (
                        (face1[n] == face2[m]) + 1)

    k_face_pairs_to_index = dict(zip(k_face_pairs, range(num_k_faces**2)))
    dets_to_vals = dets_to_vals.tocsr()
    ## END PRECOMPUTATION

    ## COMPUTATION
    if k == 1:
        Fdet = lambda x: x  #det for 1x1 matrices - extend
    else:
        Fdet, = scipy.linalg.flinalg.get_flinalg_funcs(('det', ),
                                                       (complex.vertices, ))

    dets = ones(num_k_form_pairs)

    for i, s in enumerate(complex[-1].simplices):

        # for k=1, dets is already correct i.e. dets[:] = 1
        if k > 0:
            # lambda_i denotes the scalar barycentric basis function of the i-th vertex of this simplex
            # d(lambda_i) is the 1 form (gradient) of the i-th scalar basis function within this simplex
            pts = complex.vertices[s, :]
            d_lambda = barycentric_gradients(pts)

            mtxs = d_lambda[
                k_form_pairs_array]  # these lines are equivalent to:
            for n, (A, B) in enumerate(
                    mtxs):  #   for n,(form1,form2) in enumerate(k_form_pairs):
                dets[n] = Fdet(
                    inner(A, B)
                )[0]  #       dets[n] = det(dot(d_lambda[form1,:],d_lambda[form2,:].T))

        volume = complex[-1].primal_volume[i]
        vals = dets_to_vals * dets
        vals *= volume * scale_integration  #scale by the volume, barycentric weights, and account for the p! in each whitney form

        #put values into appropriate entries of the COO data array
        data[i * num_k_face_pairs:(i + 1) * num_k_face_pairs] = vals

    #now rows,cols,data form a COOrdinate representation for the mass matrix
    shape = (complex[k].num_simplices, complex[k].num_simplices)
    return coo_matrix((data, (rows, cols)), shape).tocsr()
コード例 #10
0
ファイル: innerproduct.py プロジェクト: DongliangGao/pydec
def whitney_innerproduct(complex,k):
    """
    For a given SimplicialComplex, compute a matrix representing the 
    innerproduct of Whitney k-forms
    """
    assert(k >= 0 and k <= complex.complex_dimension())    
        
    ## MASS MATRIX COO DATA
    rows,cols = massmatrix_rowcols(complex,k)
    data = empty(rows.shape)


    ## PRECOMPUTATION
    p = complex.complex_dimension()
   
    scale_integration = (factorial(k)**2)/((p + 2)*(p + 1))   
    
    k_forms = [tuple(x) for x in combinations(range(p+1),k)]
    k_faces = [tuple(x) for x in combinations(range(p+1),k+1)]

    num_k_forms = len(k_forms)
    num_k_faces = len(k_faces)

    k_form_pairs = [tuple(x) for x in combinations(k_forms,2)] + [(x,x) for x in k_forms]
    num_k_form_pairs = len(k_form_pairs)
    k_form_pairs_to_index = dict(zip(k_form_pairs,range(num_k_form_pairs)))
    k_form_pairs_to_index.update(zip([x[::-1] for x in k_form_pairs],range(num_k_form_pairs)))
    num_k_face_pairs = num_k_faces**2


    if k > 0:
        k_form_pairs_array = array(k_form_pairs)

    #maps flat vector of determinants to the flattened matrix entries
    dets_to_vals = scipy.sparse.lil_matrix((num_k_face_pairs,num_k_form_pairs))

    k_face_pairs = []
    for face1 in k_faces:
        for face2 in k_faces:
            row_index = len(k_face_pairs)

            k_face_pairs.append((face1,face2))

            for n in range(k+1):
               for m in range(k+1):
                   form1 = face1[:n] + face1[n+1:]
                   form2 = face2[:m] + face2[m+1:]

                   col_index = k_form_pairs_to_index[(form1,form2)]

                   dets_to_vals[row_index,col_index] += (-1)**(n+m)*((face1[n] == face2[m]) + 1)                 

    k_face_pairs_to_index = dict(zip(k_face_pairs,range(num_k_faces**2)))
    dets_to_vals = dets_to_vals.tocsr()
    ## END PRECOMPUTATION


    ## COMPUTATION
    if k == 1:
        Fdet = lambda x : x #det for 1x1 matrices - extend
    else:
        Fdet, = scipy.linalg.flinalg.get_flinalg_funcs(('det',),(complex.vertices,))



    dets = ones(num_k_form_pairs)


    for i,s in enumerate(complex[-1].simplices):

        # for k=1, dets is already correct i.e. dets[:] = 1
        if k > 0:  
            # lambda_i denotes the scalar barycentric basis function of the i-th vertex of this simplex
            # d(lambda_i) is the 1 form (gradient) of the i-th scalar basis function within this simplex
            pts      = complex.vertices[s,:]
            d_lambda = barycentric_gradients(pts)
            
            mtxs = d_lambda[k_form_pairs_array]     # these lines are equivalent to:
            for n,(A,B) in enumerate(mtxs):         #   for n,(form1,form2) in enumerate(k_form_pairs):
                dets[n] = Fdet(inner(A,B))[0]       #       dets[n] = det(dot(d_lambda[form1,:],d_lambda[form2,:].T))

        volume = complex[-1].primal_volume[i]
        vals = dets_to_vals * dets
        vals *= volume * scale_integration  #scale by the volume, barycentric weights, and account for the p! in each whitney form

        #put values into appropriate entries of the COO data array
        data[i*num_k_face_pairs:(i+1)*num_k_face_pairs] = vals


    #now rows,cols,data form a COOrdinate representation for the mass matrix
    shape = (complex[k].num_simplices,complex[k].num_simplices)  
    return coo_matrix((data,(rows,cols)), shape).tocsr()