def map_boundary_to_sphere(mesh, basename): bd_mesh = pymesh.form_mesh(mesh.vertices, mesh.faces) bd_mesh, info = pymesh.remove_isolated_vertices(bd_mesh) bd_vertices = np.copy(bd_mesh.vertices) assembler = pymesh.Assembler(bd_mesh) L = assembler.assemble("graph_laplacian") # First, Laplacian smoothing to improve triangle quality. for i in range(100): c = np.mean(bd_vertices, axis=0) bd_vertices = bd_vertices - c r = np.amax(norm(bd_vertices, axis=1)) bd_vertices /= r bd_vertices += L * bd_vertices if i % 10 == 0: sphere_mesh = pymesh.form_mesh(bd_vertices, bd_mesh.faces) pymesh.save_mesh("{}_flow_{:03}.msh".format(basename, i), sphere_mesh) # Then, run mean curvature flow. sphere_mesh = pymesh.form_mesh(bd_vertices, bd_mesh.faces) sphere_mesh = mean_curvature_flow(sphere_mesh, 100, use_graph_laplacian=True) pymesh.save_mesh("{}_flow_final.msh".format(basename), sphere_mesh) bd_vertices = sphere_mesh.vertices # Lastly, project vertices onto unit sphere. bd_vertex_indices = info["ori_vertex_index"] bd_vertex_positions = np.divide(bd_vertices, norm(bd_vertices, axis=1).reshape((-1, 1))) return bd_vertex_indices, bd_vertex_positions
def build_L_deltaV(mesh_list, path, ref_mesh_name): ref_mesh = pymesh.load_mesh(os.path.join(path, ref_mesh_name + ".obj")) faces = ref_mesh.faces # ref_mesh_vertices, min_mesh, max_mesh = normalize_positions(np.copy(ref_mesh.vertices), return_min=True, return_max=True) ref_mesh_vertices = ref_mesh.vertices n_vertices = len(ref_mesh_vertices) print("n_vertices:", n_vertices) LdVs = [] for mesh_name in mesh_list: # compute dV if mesh_name != ref_mesh_name: mesh = pymesh.load_mesh(os.path.join(path, mesh_name + ".obj")) # mesh_vertices = normalize_positions(np.copy(mesh.vertices), min_pos=min_mesh, max_pos=max_mesh) mesh_vertices = mesh.vertices dv_mesh = compute_deltaV(mesh_vertices, ref_mesh_vertices, faces) # compute Laplacians assembler = pymesh.Assembler(mesh) L = assembler.assemble("laplacian").todense() # compute LdV LdVs.append(np.dot(L, dv_mesh.vertices)) else: print( "[Warning] Ref blendshape found in the sorted mesh list name!") return np.array(LdVs)
def hipp_cut(hipp_filename): hipp_img = nib.load(hipp_filename) hipp_matrix = hipp_img.get_fdata() hipp_matrix_s = scipy.ndimage.filters.gaussian_filter(hipp_matrix, sigma=1) #mesh it verts, faces, normals, values = skimage.measure.marching_cubes_lewiner(hipp_matrix_s, level=0.5) hipp_mesh = pymesh.form_mesh(verts, faces) hipp_mesh, info = pymesh.remove_duplicated_faces(hipp_mesh) assembler = pymesh.Assembler(hipp_mesh) L = assembler.assemble('laplacian').toarray() eigen = sciLA.eigh(L) for i in range(50): #print(eigen[0][i]) #Plot_3D.plot_eigh(hipp_mesh, eigen[1][:, i]) if (eigen[0][i] > 0.0000000001): eigen_cut = segment(eigen[1][:, i]) mean_first = np.mean(verts[np.where(eigen_cut==0), :], axis=1) mean_last = np.mean(verts[np.where(eigen_cut==(NUM_CUT-1)), :], axis=1) diff = -mean_first[0, 1] + mean_last[0, 1] + mean_first[0, 2] - mean_last[0, 2] eigen_cut_output = copy.copy(eigen_cut) if diff < 0: for i in range(NUM_CUT): eigen_cut_output[np.where(eigen_cut==i)] = NUM_CUT-i-1 #Plot_3D.plot_eigh(hipp_mesh, eigen_cut) break return eigen_cut_output, hipp_mesh
def compute_distortion_energies_2D(mesh): assert (mesh.dim == 2) regular_tri = pymesh.generate_equilateral_triangle() assembler = pymesh.Assembler(regular_tri) G = assembler.assemble("gradient") vertices = mesh.vertices tris = mesh.faces Js = [G * vertices[tri] for tri in tris] J_F = np.array([np.trace(np.dot(J.T, J)) for J in Js]) J_det = np.array([numpy.linalg.det(J) for J in Js]) invert_J = lambda args: np.full( (3, 3), np.inf) if args[1] == 0 else numpy.linalg.inv(args[0]) J_inv = map(invert_J, zip(Js, J_det)) J_inv_F = np.array([np.trace(np.dot(Ji.T, Ji)) for Ji in J_inv]) conformal_amips = np.divide(J_F, J_det) finite_conformal_amips = np.isfinite(conformal_amips) symmetric_dirichlet = J_F + J_inv_F finite_symmetric_dirichlet = np.isfinite(symmetric_dirichlet) orientations = np.array([ pymesh.orient_2D(vertices[t[0]], vertices[t[1]], vertices[t[2]]) for t in tris ]) orientations[orientations > 0] = 1 orientations[orientations < 0] = -1 num_degenerate_tets = np.count_nonzero(orientations == 0) num_inverted_tets = np.count_nonzero(orientations < 0) num_nonfinite_amips = np.count_nonzero( np.logical_not(finite_conformal_amips)) num_nonfinite_dirichlet =\ np.count_nonzero(np.logical_not(finite_symmetric_dirichlet)) logger = logging.getLogger("Distorsion") if num_degenerate_tets > 0: logger.warn("degenerate tets: {}".format(num_degenerate_tets)) if num_inverted_tets > 0: logger.warn("inverted tets: {}".format(num_inverted_tets)) if num_nonfinite_amips > 0: logger.warn( "Non-finite conformal AMIPS: {}".format(num_nonfinite_amips)) if num_nonfinite_dirichlet > 0: logger.warn("Non-finite symmetric Dirichlet: {}".format( num_nonfinite_dirichlet)) mesh.add_attribute("conformal_AMIPS") mesh.set_attribute("conformal_AMIPS", conformal_amips) mesh.add_attribute("finite_conformal_AMIPS") mesh.set_attribute("finite_conformal_AMIPS", finite_conformal_amips) mesh.add_attribute("symmetric_Dirichlet") mesh.set_attribute("symmetric_Dirichlet", symmetric_dirichlet) mesh.add_attribute("finite_symmetric_Dirichlet") mesh.set_attribute("finite_symmetric_Dirichlet", finite_symmetric_dirichlet) mesh.add_attribute("orientations") mesh.set_attribute("orientations", orientations)
def repousse(mesh, logger): cell_ids = mesh.get_attribute("cell").ravel().astype(int) mesh.add_attribute("edge_length") tol = np.amax(mesh.get_attribute("edge_length")) * 0.1 bbox_min, bbox_max = mesh.bbox scaling = 2.0 / norm(bbox_max - bbox_min) start_time = time() num_cells = np.amax(cell_ids) + 1 results = [] for i in range(num_cells): to_keep = np.arange(mesh.num_faces, dtype=int)[cell_ids == i] if not np.any(to_keep): continue cut_mesh = pymesh.submesh(mesh, to_keep, 0) pymesh.save_mesh("debug.msh", cut_mesh) cut_mesh, __ = pymesh.remove_degenerated_triangles(cut_mesh, 100) cut_mesh, __ = pymesh.split_long_edges(cut_mesh, tol) dof = cut_mesh.num_vertices assembler = pymesh.Assembler(cut_mesh) L = assembler.assemble("laplacian") M = assembler.assemble("mass") L_rhs = M * np.ones(dof) * -0.5 bd_indices = cut_mesh.boundary_vertices n = len(bd_indices) C = scipy.sparse.coo_matrix( (np.ones(n), (np.arange(n, dtype=int), bd_indices)), shape=(n, dof)) C_rhs = np.zeros(n) A = scipy.sparse.bmat([[-L, C.T], [C, None]]) rhs = np.concatenate((L_rhs.ravel(), C_rhs)) solver = pymesh.SparseSolver.create("SparseLU") solver.compute(A) x = solver.solve(rhs) z = x[:dof].reshape((-1, 1)) vertices = np.hstack((cut_mesh.vertices, z)) out_mesh = pymesh.form_mesh(vertices, cut_mesh.faces) results.append(out_mesh) finish_time = time() t = finish_time - start_time logger.info("Repousse running time: {}".format(t)) mesh = pymesh.merge_meshes(results) vertices = mesh.vertices[:, :2] mesh_2d = pymesh.form_mesh(vertices, mesh.faces) pymesh.save_mesh("out_2d.msh", mesh_2d) return mesh
def compute_distortion_energies_3D(mesh): if mesh.num_voxels > 0 and mesh.vertex_per_voxel != 4: raise RuntimeError( "Only tet mesh is supported for distortion computation") regular_tet = pymesh.generate_regular_tetrahedron() assembler = pymesh.Assembler(regular_tet) G = assembler.assemble("gradient") vertices = mesh.vertices tets = mesh.voxels Js = [G * vertices[tet] for tet in tets] J_F = np.array([np.trace(np.dot(J.T, J)) for J in Js]) J_det = np.array([numpy.linalg.det(J) for J in Js]) invert_J = lambda args: np.full( (3, 3), np.inf) if args[1] == 0 else numpy.linalg.inv(args[0]) J_inv = map(invert_J, zip(Js, J_det)) J_inv_F = np.array([np.trace(np.dot(Ji.T, Ji)) for Ji in J_inv]) conformal_amips = np.divide(J_F, np.cbrt(np.square(J_det))) finite_conformal_amips = np.isfinite(conformal_amips) symmetric_dirichlet = J_F + J_inv_F finite_symmetric_dirichlet = np.isfinite(symmetric_dirichlet) orientations = pymesh.get_tet_orientations(mesh) orientations[orientations > 0] = 1 orientations[orientations < 0] = -1 num_degenerate_tets = np.count_nonzero(orientations == 0) num_inverted_tets = np.count_nonzero(orientations < 0) num_nonfinite_amips = np.count_nonzero( np.logical_not(finite_conformal_amips)) num_nonfinite_dirichlet =\ np.count_nonzero(np.logical_not(finite_symmetric_dirichlet)) logger = logging.getLogger("Distorsion") if num_degenerate_tets > 0: logger.warn("degenerate tets: {}".format(num_degenerate_tets)) if num_inverted_tets > 0: logger.warn("inverted tets: {}".format(num_inverted_tets)) if num_nonfinite_amips > 0: logger.warn( "Non-finite conformal AMIPS: {}".format(num_nonfinite_amips)) if num_nonfinite_dirichlet > 0: logger.warn("Non-finite symmetric Dirichlet: {}".format( num_nonfinite_dirichlet)) mesh.add_attribute("conformal_AMIPS") mesh.set_attribute("conformal_AMIPS", conformal_amips) mesh.add_attribute("finite_conformal_AMIPS") mesh.set_attribute("finite_conformal_AMIPS", finite_conformal_amips) mesh.add_attribute("symmetric_Dirichlet") mesh.set_attribute("symmetric_Dirichlet", symmetric_dirichlet) mesh.add_attribute("finite_symmetric_Dirichlet") mesh.set_attribute("finite_symmetric_Dirichlet", finite_symmetric_dirichlet) mesh.add_attribute("orientations") mesh.set_attribute("orientations", orientations)
def mesh_op(filename): mesh = pymesh.load_mesh(filename) assembler = pymesh.Assembler(mesh) L = assembler.assemble("laplacian") print(L.shape, mesh.num_vertices, mesh.num_faces) eigenvals, eigenvecs = eigs(L, k=1000) print(eigenvecs.shape, eigenvals.shape) np.save("eigenvals.npy", eigenvals) np.save("eigenvecs.npy", eigenvecs)
def integrate(mesh, time_step): assembler = pymesh.Assembler(mesh) L = assembler.assemble("laplacian") M = assembler.assemble("mass") bbox_min, bbox_max = mesh.bbox s = np.amax(bbox_max - bbox_min) S = M + (time_step * s) * L solver = pymesh.SparseSolver.create("LDLT") solver.compute(S) vertices = solver.solve(M * mesh.vertices) return normalize_mesh(vertices, mesh.faces)
def main(): args = parse_args() mesh = pymesh.load_mesh(args.input_mesh) assert (mesh.dim == 3) assert (mesh.vertex_per_face == 3) compute_edge_field(mesh) assert (mesh.has_attribute("edges")) compute_cotan_field(mesh) assert (mesh.has_attribute("cotan")) compute_area_and_normal_field(mesh) assert (mesh.has_attribute("vertex_area")) assert (mesh.has_attribute("face_normal")) assembler = pymesh.Assembler(mesh) L = assembler.assemble("laplacian") * -1 A = assembler.assemble("mass") G = assembler.assemble("gradient") t = np.mean(mesh.get_attribute("face_area").ravel()) rhs = np.zeros(mesh.num_vertices) rhs[args.source] = 1.0 u = scipy.sparse.linalg.spsolve(A - t * L, rhs) mesh.add_attribute("u") mesh.set_attribute("u", u) grad_u = (G * u).reshape((-1, 3), order="C") grad_u_2 = compute_gradient(mesh, u) mesh.add_attribute("grad_u") mesh.set_attribute("grad_u", grad_u.ravel()) X = -grad_u / norm(grad_u, axis=1)[..., np.newaxis] mesh.add_attribute("X") mesh.set_attribute("X", X.ravel()) div_X = compute_divergence(mesh, X) mesh.add_attribute("div_X") mesh.set_attribute("div_X", div_X) phi = scipy.sparse.linalg.spsolve(L, div_X) phi = phi - np.amin(phi) mesh.add_attribute("phi") mesh.set_attribute("phi", phi) pymesh.save_mesh(args.output_mesh, mesh, "u", "grad_u", "X", "div_X", "phi")
def tutte_3D(mesh, bd_vertex_indices, bd_vertex_positions): assembler = pymesh.Assembler(mesh) L = assembler.assemble("laplacian") is_constraint = np.zeros(mesh.num_vertices, dtype=bool) is_constraint[bd_vertex_indices] = True is_variable = np.logical_not(is_constraint) M, rhs = init_harmonic_system(L, bd_vertex_indices, bd_vertex_positions, is_variable) x = solve(M, rhs, "SparseLU", 1e-6) out_vertices = np.zeros((mesh.num_vertices, 3)) out_vertices[is_constraint, :] = bd_vertex_positions out_vertices[is_variable, :] = x return pymesh.form_mesh(out_vertices, np.zeros((0, 3)), mesh.voxels)
def repousse_all(mesh, logger): cell_ids = mesh.get_attribute("cell").ravel().astype(int) mesh.add_attribute("edge_length") tol = np.amax(mesh.get_attribute("edge_length")) * 0.1 out_mesh, info = pymesh.remove_degenerated_triangles(mesh, 100) cell_ids = cell_ids[info["ori_face_indices"]].ravel() mesh, info = pymesh.split_long_edges(out_mesh, tol) cell_ids = cell_ids[info["ori_face_indices"]].ravel() mesh.enable_connectivity() is_border = [ len(np.unique(cell_ids[mesh.get_vertex_adjacent_faces(vi)])) > 1 for vi in range(mesh.num_vertices) ] start_time = time() dof = mesh.num_vertices assembler = pymesh.Assembler(mesh) L = assembler.assemble("laplacian") M = assembler.assemble("mass") L_rhs = M * np.ones(dof) * -1 * 1e-1 bd_indices = np.arange(mesh.num_vertices, dtype=int)[is_border] n = len(bd_indices) C = scipy.sparse.coo_matrix( (np.ones(n), (np.arange(n, dtype=int), bd_indices)), shape=(n, dof)) C_rhs = np.zeros(n) A = scipy.sparse.bmat([[-L, C.T], [C, None]]) rhs = np.concatenate((L_rhs.ravel(), C_rhs)) solver = pymesh.SparseSolver.create("SparseLU") solver.compute(A) x = solver.solve(rhs) z = x[:dof].reshape((-1, 1)) vertices = np.hstack((mesh.vertices, z)) finish_time = time() t = finish_time - start_time logger.info("Repousse running time: {}".format(t)) return pymesh.form_mesh(vertices, mesh.faces)
def __init__(self, input_mesh, cell_size): self.input_mesh = input_mesh # Regularise input mesh regularise_mesh(self.input_mesh, cell_size) # Tetrahedralise input mesh self.tetmesh = tetrahedralise(self.input_mesh, cell_size) self.assembler = pymesh.Assembler(self.tetmesh) # save a list of boundary vertices self.boundary_mesh = compute_boundary_mesh(self.tetmesh) source_faces = self.boundary_mesh.get_attribute("face_sources").astype( int) self.boundary_vertices = np.unique( np.array(self.tetmesh.faces[source_faces]).flatten()) self.n_vertices = self.tetmesh.num_vertices self.attributes_to_save = [] self._faces = self.tetmesh.faces[source_faces]
def build_L_deltaV(mesh_list, path, ref_mesh_name): ref_mesh = pymesh.load_mesh(os.path.join(path, ref_mesh_name + ".obj")) n_vertices = len(ref_mesh.vertices) print("n_vertices:", n_vertices) LdVs = [] for mesh_name in mesh_list: # compute dV if mesh_name != ref_mesh_name: mesh = pymesh.load_mesh(os.path.join(path, mesh_name + ".obj")) dv_mesh = compute_deltaV(mesh, ref_mesh) # compute Laplacians assembler = pymesh.Assembler(mesh) L = assembler.assemble("laplacian").todense() # compute LdV LdVs.append(np.dot(L, dv_mesh.vertices)) else: print( "[Warning] Ref blendshape found in the sorted mesh list name!") return np.array(LdVs)
np.set_printoptions(precision=4, linewidth=250, suppress=True) # mesh = pymesh.load_mesh("../data/simple_cube.obj") mesh = pymesh.load_mesh("../data/simple_strange_cube.obj") # mesh = pymesh.load_mesh("../data/teapot.obj") # carefull teapot seems to have double vertices! my gradient does not work for this num_V = len(mesh.vertices) print("num_vertices", num_V) mesh.enable_connectivity() neighbours = mesh.get_vertex_adjacent_vertices(0) print(neighbours) # print("control teapot:", 2659, 2683, 2773, 2837, 2937, 2984) print("control simple_cube:", 1, 2, 4, 6, 7) assembler = pymesh.Assembler(mesh) L = assembler.assemble("laplacian") print(type(L)) print(np.shape(L)) def build_Laplacian(mesh, num_V, anchor_weight=1, is_pymesh=False): """ Build a Laplacian sparse matrix between the vertices of a triangular mesh This mainly follow work from: "Laplacian Mesh Optimization" (Andrew Nealean et al. 2006) and an implementation from: https://github.com/bmershon/laplacian-meshes/blob/master/LaplacianMesh.py :param mesh: :param num_V: num_vertices
def main(): args = parse_args(); mesh = pymesh.load_mesh(args.input_mesh); num_tets = mesh.num_voxels; assert(mesh.dim == 3); assert(mesh.vertex_per_voxel == 4); assert(num_tets > 0); mesh = fit_into_unit_sphere(mesh); mesh.add_attribute("voxel_centroid"); assembler = pymesh.Assembler(mesh); if args.charge_distribution == "sphere": ball = pymesh.generate_icosphere(1.25 + 1e-3, np.zeros(3), 0); charges = ball.vertices; elif args.charge_distribution == "center": charges = np.zeros(3); else: raise NotImplementedError("Unsupported charge distribution ({})."\ .format(args.charge_distribution)); if args.output_kernels: kernels = pymesh.merge_meshes([ pymesh.generate_icosphere(0.05, v, 2) for v in charges ]); pymesh.save_mesh("kernel.msh", kernels); f = test_function(charges); g = test_function_grad(charges); v_pts = mesh.vertices; q_pts = get_quadrature_pts(mesh); c_pts = mesh.get_voxel_attribute("voxel_centroid"); v_values = f(v_pts); q_values = f(q_pts); c_values = f(c_pts); q_grad = g(q_pts); c_grad = g(c_pts); c_grad_norm = numpy.linalg.norm(c_grad, axis=1); q_grad_norm = numpy.linalg.norm(q_grad, axis=1); #for v,val in zip(v_pts, v_values): # print(v, val); assert(len(v_values) == len(v_pts)); assert(len(q_values) == len(q_pts)); assert(len(c_values) == len(c_pts)); assert(len(q_grad) == len(q_pts)); assert(len(c_grad) == len(c_pts)); bd_indices = np.unique(mesh.faces.ravel()).astype(int); bd_values = v_values[bd_indices]; solver = pymesh.HarmonicSolver.create(mesh); solver.order = 1; solver.boundary_indices = bd_indices; solver.boundary_values = bd_values; solver.pre_process(); solver.solve(); sol_values = solver.solution.ravel(); G = assembler.assemble("gradient"); sol_grad = (G * sol_values).reshape((-1,3), order="C"); sol_q_values, sol_q_grad = \ interpolate_at_quadrature_pts(mesh, sol_values, sol_grad); sol_c_values, sol_c_grad = \ interpolate_at_centroids(mesh, sol_values, sol_grad); v_err = sol_values - v_values; c_err = sol_c_values - c_values; q_err = sol_q_values - q_values; v_rel_err = np.divide(v_err, v_values); c_rel_err = np.divide(c_err, c_values); q_rel_err = np.divide(q_err, q_values); c_grad_err = sol_c_grad - c_grad; q_grad_err = sol_q_grad - q_grad; c_grad_err_norm = numpy.linalg.norm(c_grad_err, axis=1); q_grad_err_norm = numpy.linalg.norm(q_grad_err, axis=1); c_grad_rel_err_norm = np.divide(c_grad_err_norm, c_grad_norm); q_grad_rel_err_norm = np.divide(q_grad_err_norm, q_grad_norm); print("num_tets: {}".format(num_tets)); print("==Ground Truth=="); print("max solution at nodes: {}".format(np.amax(np.absolute(v_values)))); print("max solution at centroids: {}".format(np.amax(np.absolute(c_values)))); print("max solution at quadrature pts: {}".format(np.amax(np.absolute(q_values)))); print("max grad solution at centroids: {}".format(np.amax(c_grad_norm))); print("max grad solution at quadrature pts: {}".format(np.amax(q_grad_norm))); print("L2 solution at nodes: {}".format(numpy.linalg.norm(v_values))); print("L2 solution at centroids: {}".format(numpy.linalg.norm(c_values))); print("L2 solution at quadrature pts: {}".format(numpy.linalg.norm(q_values))); print("L2 grad solution at centroids: {}".format(numpy.linalg.norm(c_grad_norm))); print("L2 grad solution at quadrature pts: {}".format(numpy.linalg.norm(q_grad_norm))); print("sqrt ave at nodes: {}".format(math.sqrt(np.mean(np.square(v_values))))); print("sqrt ave at centroids: {}".format(math.sqrt(np.mean(np.square(c_values))))); print("sqrt ave at quadrature pts: {}".format(math.sqrt(np.mean(np.square(q_values))))); print("sqrt ave grad solution at centroids: {}".format(math.sqrt(np.mean(np.square(c_grad_norm))))); print("sqrt ave grad solution at quadrature pts: {}".format(math.sqrt(np.mean(np.square(q_grad_norm))))); print("==Absolute errors=="); print("max error at nodes: {}".format(np.amax(np.absolute(v_err)))); print("max error at centroids: {}".format(np.amax(np.absolute(c_err)))); print("max error at quadrature pts: {}".format(np.amax(np.absolute(q_err)))); print("max grad error at centroids: {}".format(np.amax(c_grad_err_norm))); print("max grad error at quadrature pts: {}".format(np.amax(q_grad_err_norm))); print("average error at nodes: {}".format(np.mean(np.absolute(v_err)))); print("average error at centroids: {}".format(np.mean(np.absolute(c_err)))); print("average error at quadrature pts: {}".format(np.mean(np.absolute(q_err)))); print("average grad error at centroids: {}".format(np.mean(c_grad_err_norm))); print("average grad error at quadrature pts: {}".format(np.mean(q_grad_err_norm))); print("L2 error at nodes: {}".format(numpy.linalg.norm(v_err))); print("L2 error at centroids: {}".format(numpy.linalg.norm(c_err))); print("L2 error at quadrature pts: {}".format(numpy.linalg.norm(q_err))); print("L2 grad error at centroids: {}".format(numpy.linalg.norm(c_grad_err_norm))); print("L2 grad error at quadrature pts: {}".format(numpy.linalg.norm(q_grad_err_norm))); print("==Relative errors=="); print("max rel error at nodes: {}".format(np.amax(np.absolute(v_rel_err)))); print("max rel error at centroids: {}".format(np.amax(np.absolute(c_rel_err)))); print("max rel error at quadrature pts: {}".format(np.amax(np.absolute(q_rel_err)))); print("max grad rel error at centroids: {}".format(np.amax(c_grad_rel_err_norm))); print("max grad rel error at quadrature pts: {}".format(np.amax(q_grad_rel_err_norm))); mesh.add_attribute("target_solution"); mesh.set_attribute("target_solution", v_values); mesh.add_attribute("solution"); mesh.set_attribute("solution", sol_values); mesh.add_attribute("v_error"); mesh.set_attribute("v_error", v_err); mesh.add_attribute("v_rel_error"); mesh.set_attribute("v_rel_error", v_rel_err); mesh.add_attribute("c_error"); mesh.set_attribute("c_error", c_err); mesh.add_attribute("c_rel_error"); mesh.set_attribute("c_rel_error", c_rel_err); mesh.add_attribute("q_error"); mesh.set_attribute("q_error", np.amax(np.absolute(q_err.reshape((-1,4), order="C")), axis=1)); mesh.add_attribute("q_rel_error"); mesh.set_attribute("q_rel_error", np.amax(np.absolute(q_rel_err.reshape((-1,4), order="C")), axis=1)); mesh.add_attribute("c_grad_error"); mesh.set_attribute("c_grad_error", c_grad_err_norm); mesh.add_attribute("c_grad_rel_error"); mesh.set_attribute("c_grad_rel_error", c_grad_rel_err_norm); mesh.add_attribute("q_grad_error"); mesh.set_attribute("q_grad_error", np.amax(q_grad_err_norm.reshape((-1,4), order="C"), axis=1)); mesh.add_attribute("q_grad_rel_error"); mesh.set_attribute("q_grad_rel_error", np.amax(q_grad_rel_err_norm.reshape((-1,4), order="C"), axis=1)); mesh.add_attribute("solution_grad"); mesh.set_attribute("solution_grad", sol_c_grad); mesh.add_attribute("target_grad"); mesh.set_attribute("target_grad", c_grad); pymesh.save_mesh(args.output_mesh, mesh, *mesh.attribute_names);
def main(): args = parse_args() mesh = pymesh.load_mesh(args.input_mesh) assembler = pymesh.Assembler(mesh) M = assembler.assemble(args.type) scipy.sparse.save_npz(args.output_matrix, M)