""" from numpy import mat, zeros, sort, asarray, loadtxt, array, dot, \ concatenate, sign, vstack, argmax, nonzero from numpy.linalg import norm, det from scipy.sparse import bmat from scipy.sparse.linalg import spsolve from matplotlib.pylab import figure, gca, triplot, show from pydec import simplicial_complex, simplex_quivers, signed_volume velocity = array([1.,0]) # Read the mesh vertices = loadtxt('vertices.txt') triangles = loadtxt('triangles.txt', dtype='int') - 1 # Make a simplicial complex from it sc = simplicial_complex((vertices,triangles)) # Nk is number of k-simplices N1 = sc[1].num_simplices N2 = sc[2].num_simplices # Permeability is k > 0 and viscosity is mu > 0 k = 1; mu = 1 # The matrix for the full linear system for Darcy in 2D, not taking into # account the boundary conditions, is : # [-(mu/k)star1 d1^T ] # [ d1 Z ] # where Z is a zero matrix of size N2 by N2. # The block sizes are # N1 X N1 N1 X N2 # N2 X N1 N2 X N2 d1 = sc[1].d; star1 = sc[1].star
return A seed(1) # make results consistent # Read in mesh data from file mesh = read_mesh('mesh_example.xml') vertices = mesh.vertices triangles = mesh.elements # remove some triangle from the mesh triangles = triangles[ list(set(range(len(triangles))) - set([30, 320, 21, 198])), :] sc = simplicial_complex((vertices, triangles)) H = [] # harmonic forms # decompose 4 random 1-cochains for i in range(4): omega = sc.get_cochain(1) omega.v[:] = rand(*omega.v.shape) (beta, gamma, h) = hodge_decomposition(omega) h = h.v for v in H: h -= inner(v, h) * v h /= norm(h)
def plotjson(fn): """ plotjson: make plots from json output of fiedler.py fn: the filename of the json file """ fo=open(fn) data=json.load(fo) fo.close() if "adj" in data: (A,adj,Npts) = fiedler.adj_mat(data["adj"]) #scew symetricise A = (A.T - A)/2 A=A.tocoo() pos=A.data>0 skew = numpy.column_stack((A.row[pos],A.col[pos],A.data[pos])).tolist() # #method from hodge decomposition driver.py # sc = simplicial_complex(([[el] for el in range(0,A.shape[0])],numpy.column_stack((A.row[pos],A.col[pos])).tolist())) # omega = sc.get_cochain(1) # omega.v[:] = A.data[pos] # p = omega.k # alpha = sc.get_cochain(p - 1) # #beta = sc.get_cochain(p + 1) # # Solve for alpha # A2 = delta(d(sc.get_cochain_basis(p - 1))).v # b = delta(omega).v # rank=cg( A2, b, tol=1e-8 )[0] # method from ranking driver.py asc = abstract_simplicial_complex([numpy.column_stack((A.row[pos],A.col[pos])).tolist()]) B1 = asc.chain_complex()[1] # boundary matrix rank = lsqr(B1.T, A.data[pos])[0] # solve least squares problem sc = simplicial_complex(([[el] for el in range(0,A.shape[0])],numpy.column_stack((A.row[pos],A.col[pos])).tolist())) omega = sc.get_cochain(1) omega.v[:] = A.data[pos] p = omega.k alpha = sc.get_cochain(p - 1) alpha.v = rank v = A.data[pos]-d(alpha).v cyclic_adj_list=numpy.column_stack((A.row[pos],A.col[pos],v)).tolist() div_adj_list=numpy.column_stack((A.row[pos],A.col[pos],d(alpha).v)).tolist() data["hodge"]=list(rank) data["hodgerank"]=list(numpy.argsort(numpy.argsort(rank))) fo = open(fn,"w") json.dump(data,fo, indent=2) fo.close() fn=fn+".abstract" #fiedler.doPlots(numpy.array(data["f1"]),numpy.array(data["f2"]),numpy.array(data["d"]),cyclic_adj_list,fn+".decomp.cyclic.",widths=[6],vsdeg=False,nByi=data["nByi"],directed=True) #fiedler.doPlots(numpy.array(data["f1"]),numpy.array(data["f2"]),numpy.array(data["d"]),div_adj_list,fn+".decomp.acyclic.",widths=[6],vsdeg=False,nByi=data["nByi"],directed=True) #fiedler.doPlots(numpy.array(data["f1"]),numpy.array(data["f2"]),numpy.array(data["d"]),data["adj"],fn+".decomp.acyclic.over.all.",widths=[6],vsdeg=False,nByi=data["nByi"],adj_list2=div_adj_list,directed=True) #fiedler.doPlots(numpy.array(data["f1"]),-1*numpy.array(rank),numpy.array(data["d"]),cyclic_adj_list,fn+".decomp.harmonic.v.grad.",widths=[6],heights=[2],vsdeg=False,nByi=data["nByi"],directed=True) #fiedler.doPlots(numpy.array(data["f1"]),-1*numpy.array(rank),numpy.array(data["d"]),skew,fn+".decomp.skew.v.grad.",widths=[6],heights=[2],vsdeg=False,nByi=data["nByi"],directed=True) #fiedler.doPlots(numpy.array(data["f1"]),-1*numpy.array(rank),numpy.array(data["d"]),data["adj"],fn+".decomp.acyclic.over.all.v.grad.",widths=[6],heights=[2],vsdeg=False,nByi=data["nByi"],adj_list2=div_adj_list,directed=True) fiedler.doPlots(numpy.array(data["f1"]),-1*numpy.array(rank),numpy.array(data["d"]),data["adj"],fn+".all.v.grad.",widths=[24],heights=[6],vsdeg=False,nByi=data["nByi"],directed=False)
def get_eigs_PyDEC(meshname, use_FEM, quiet=False, draw=False, load=False): # Loading the mesh and constructing the simplicial complex if not quiet: print("") print("Loading '%s'..." % meshname) vers, tris = load_mesh(meshname) triangulation = tri.Triangulation(vers[:, 0], vers[:, 1], triangles=tris) sc = simplicial_complex((vers, tris)) N0 = sc[0].num_simplices if use_FEM: meshname += "_FEM" interpolate = True if draw: # Draw the mesh figure() gca().triplot(vers[:, 0], vers[:, 1], tris) show() if load: if not quiet: print("Loading matrix...") A = scipy.sparse.load_npz('eigen/%s/A.npz' % meshname) else: mkdirs(meshname) # Constructing the matrix equation Ax = b # A is of the form # [ 0 L ] N0 # [ L 0 ] N0 # N0 N0 # # The Laplacian L is dependent on whether we are # using finite elements (Whitney 1-forms) if not quiet: print("Constructing matrix...") if use_FEM: L = sc[0].d.T * whitney_innerproduct(sc, 1) * sc[0].d else: L = sc[0].d.T * sc[1].star * sc[0].d # This matrix takes a long time to construct for large meshes A = scipy.sparse.bmat([[None, L], [L, None]], format='csr') scipy.sparse.save_npz('eigen/%s/A.npz' % meshname, A) b = np.zeros(N0 + N0) all_Us = np.zeros(N0) all_Vs = np.zeros(N0) # Finding points and indices for the boundary and interior # We don't have to convert the simplices to indices with # sc[0].simplex_to_index[...], because the nth 0-simplex is named n. b_is = np.unique(sc.boundary()) i_is = np.delete(np.arange(N0), b_is, 0) # Number of internal and external points N0b = len(b_is) N0i = N0 - N0b # Making sure that all the indices are accounted for assert (N0i == len(i_is)) if N0i == 0: if not quiet: print("No internal points in mesh! Finishing...") np.savetxt("eigen/" + meshname + "/l_final.txt", np.array([])) np.savetxt("eigen/" + meshname + "/l_final.txt", np.array([])) if not quiet: print("Done.") return np.array([]), np.array([]) # Adjusting the system with U and V equal to 0 on the boundary # Same as the method used by Hirani in the Darcy flow example from # 'PyDEC: Software and Algorithms for Discretization of Exterior Calculus' b = b - A * np.concatenate((all_Us, all_Vs)) keep = np.concatenate((i_is, i_is + N0)) b = b[keep] A = A[keep][:, keep] if not quiet: print("Converting to PETSc...") A_petsc = CSR_to_PETSc(A, quiet) if not quiet: print("Preparing eigensolver...") # Create eigensolver # If the eigenvectors are taking too long to converge, either # increase the tolerance or decrease the max iterations eigensolver = SLEPcEigenSolver(A_petsc) eigensolver.parameters['spectrum'] = 'target magnitude' eigensolver.parameters[ 'spectral_transform'] = 'shift-and-invert' # find the smallest eigenvalues first eigensolver.parameters['spectral_shift'] = 1e-6 eigensolver.parameters['tolerance'] = 1e-15 eigensolver.parameters['maximum_iterations'] = int(1e4) # eigensolver.parameters["problem_type"] = "hermitian" # Compute all eigenvalues of A x = \lambda x if not quiet: print("Computing eigenvalues...", end=' ') eigensolver.solve(1000) # number of eigenvectors to compute num_eigs = eigensolver.get_number_converged() if not quiet: print("(Found %d)" % num_eigs) lambdas = np.zeros(num_eigs) vs = np.zeros((num_eigs, N0i * 2)) if not quiet: print("Computing eigenvectors...") next_update_time = time.time() + time_step for i in range(num_eigs): r, c, rx, cx = eigensolver.get_eigenpair(i) lambdas[i] = r vs[i] = rx.vec().getArray() np.savetxt("eigen/" + meshname + "/vectors/l%04d.txt" % i, np.array([lambdas[i]])) np.savetxt("eigen/" + meshname + "/vectors/v%04d.txt" % i, vs[i]) if not quiet and time.time() > next_update_time: if draw: full_eigenvector = np.zeros(N0) full_eigenvector[i_is] = vs[i][:N0i] figure() if interpolate: gca().tricontourf(triangulation, full_eigenvector, cmap='seismic') else: gca().scatter(vers[:, 0], vers[:, 1], c=full_eigenvector, cmap='seismic', linewidth=0.5) show() next_update_time = time.time() + time_step print("%4d / %4d (%3d%% )" % (i + 1, num_eigs, ((i + 1) * 100) // num_eigs)) if not quiet: print("Done.") # We only want the real part lambdas = np.array(lambdas) vs = np.array(vs) # Retain only the positive eigenvalues, sorted in ascending order keep = lambdas > 0 vs = vs[keep] lambdas = lambdas[keep] order = lambdas.argsort() lambdas = lambdas[order] vs = vs[order] # Reinserting the initial conditions and changing the ordering of axes. # Now final_vs[i, :] gives the ith eigenvector, instead of vs[:N0i,i] giving # the ith eigenvalue on the internal mesh points. final_vs = np.zeros((vs.shape[0], N0)) final_vs[:, i_is] = vs[:, :N0i] np.savetxt("eigen/" + meshname + "/l_final.txt", lambdas) np.savetxt("eigen/" + meshname + "/v_final.txt", final_vs) if draw and not quiet: # Draw some eigenstates for i in range(min(5, len(final_vs))): figure() gca().set_title("Eigenvector for lambda[%d] = %f" % (i, lambdas[i])) if interpolate: gca().tricontourf(triangulation, final_vs[i], cmap='seismic') else: gca().scatter(vers[:, 0], vers[:, 1], c=final_vs[i], cmap='seismic', linewidth=0.5) show() return lambdas, final_vs
import numpy as np from scipy.io import loadmat, savemat from pydec import simplicial_complex, whitney_innerproduct X = loadmat('pyamg.mat') del X['__version__'] del X['__header__'] del X['__globals__'] sc = simplicial_complex(X['vertices'], X['elements'].astype('intc')) d = sc[0].d M = whitney_innerproduct(sc, 1) A = d.T.tocsr() * M * d X['A'] = A X['B'] = np.ones((A.shape[0], 1)) savemat('pyamg.mat', X)