def test_tetra(): X = np.array([ [0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, -1.0], [0.0, 0.0, 1.0], ]) cells = np.array([[0, 1, 2, 3], [0, 1, 2, 4]]) mesh = meshplex.Mesh(X, cells) ref = np.array([ [ [-1 / 24, -1 / 24], [1 / 8, 1 / 8], [1 / 8, 1 / 8], [0.0, 0.0], ], [ [-1 / 24, -1 / 24], [1 / 8, 1 / 8], [0.0, 0.0], [1 / 8, 1 / 8], ], [ [-1 / 24, -1 / 24], [0.0, 0.0], [1 / 8, 1 / 8], [1 / 8, 1 / 8], ], ], ) print(mesh.ce_ratios) assert ref.shape == mesh.ce_ratios.shape assert np.all( np.abs(mesh.ce_ratios - ref) < 1.0e-14 * np.abs(ref) + 1.0e-14)
def assert_mesh_consistency(mesh0, tol=1.0e-14): assert np.all( np.logical_xor(mesh0.is_boundary_facet, mesh0.is_interior_facet)) bpts = np.array([ mesh0.is_boundary_point, mesh0.is_interior_point, ~mesh0.is_point_used, ]) assert np.all(np.sum(bpts, axis=0) == 1) # consistency check for facets_cells assert np.all(mesh0.is_boundary_facet[mesh0.facets_cells["boundary"][0]]) assert not np.any( mesh0.is_boundary_facet[mesh0.facets_cells["interior"][0]]) for edge_id, cell_id, local_edge_id in mesh0.facets_cells["boundary"].T: assert edge_id == mesh0.cells("facets")[cell_id][local_edge_id] for ( edge_id, cell_id0, cell_id1, local_edge_id0, local_edge_id1, ) in mesh0.facets_cells["interior"].T: assert edge_id == mesh0.cells("facets")[cell_id0][local_edge_id0] assert edge_id == mesh0.cells("facets")[cell_id1][local_edge_id1] # check consistency of facets_cells_idx with facets_cells for edge_id, idx in enumerate(mesh0.facets_cells_idx): if mesh0.is_boundary_facet[edge_id]: assert edge_id == mesh0.facets_cells["boundary"][0, idx] else: assert edge_id == mesh0.facets_cells["interior"][0, idx] # Assert facets_cells integrity for cell_gid, edge_gids in enumerate(mesh0.cells("facets")): for edge_gid in edge_gids: idx = mesh0.facets_cells_idx[edge_gid] if mesh0.is_boundary_facet[edge_gid]: assert cell_gid == mesh0.facets_cells["boundary"][1, idx] else: assert cell_gid in mesh0.facets_cells["interior"][1:3, idx] # make sure the edges are opposite of the points for cell_gid, (point_ids, edge_ids) in enumerate( zip(mesh0.cells("points"), mesh0.cells("facets"))): for k in range(len(point_ids)): assert set(point_ids) == { *mesh0.edges["points"][edge_ids][k], point_ids[k] } # make sure the is_boundary_point/edge/cell is consistent ref_cells = np.any(mesh0.is_boundary_facet_local, axis=0) assert np.all(mesh0.is_boundary_cell == ref_cells) ref_points = np.zeros(len(mesh0.points), dtype=bool) ref_points[mesh0.idx[1][:, mesh0.is_boundary_facet_local]] = True assert np.all(mesh0.is_boundary_point == ref_points) assert len(mesh0.control_volumes) == len(mesh0.points) assert len(mesh0.control_volume_centroids) == len(mesh0.points) # TODO add more consistency checks # now check the numerical values # create a new mesh from the points and cells and compare mesh1 = meshplex.Mesh(mesh0.points, mesh0.cells("points")) # Can't add those tests since the facet order will be different. # TODO bring back # if mesh0.facets is None: # mesh0.create_facets() # if mesh1.facets is None: # mesh1.create_facets() # assert np.all(mesh0.boundary_facets == mesh1.boundary_facets) # assert np.all(mesh0.interior_facets == mesh1.interior_facets) # assert np.all(mesh0.is_boundary_facet == mesh1.is_boundary_facet) # assert np.all( # np.abs( # mesh0.signed_circumcenter_distances - mesh1.signed_circumcenter_distances # ) # < tol # ) assert np.all(mesh0.is_point_used == mesh1.is_point_used) assert np.all(mesh0.is_boundary_point == mesh1.is_boundary_point) assert np.all(mesh0.is_interior_point == mesh1.is_interior_point) assert np.all( mesh0.is_boundary_facet_local == mesh1.is_boundary_facet_local) assert np.all(mesh0.is_boundary_cell == mesh1.is_boundary_cell) assert np.all(np.abs(mesh0.ei_dot_ei - mesh1.ei_dot_ei) < tol) assert np.all(np.abs(mesh0.cell_volumes - mesh1.cell_volumes) < tol) assert np.all( np.abs(mesh0.circumcenter_facet_distances - mesh1.circumcenter_facet_distances) < tol) assert np.all( np.abs(mesh0.signed_cell_volumes - mesh1.signed_cell_volumes) < tol) assert np.all(np.abs(mesh0.cell_centroids - mesh1.cell_centroids) < tol) assert np.all( np.abs(mesh0.cell_circumcenters - mesh1.cell_circumcenters) < tol) assert np.all(np.abs(mesh0.control_volumes - mesh1.control_volumes) < tol) assert np.all(np.abs(mesh0.ce_ratios - mesh1.ce_ratios) < tol) ipu = mesh0.is_point_used assert np.all( np.abs(mesh0.control_volume_centroids[ipu] - mesh1.control_volume_centroids[ipu]) < tol)
def get_mesh2(): this_dir = pathlib.Path(__file__).resolve().parent mesh0 = meshplex.read(this_dir / "meshes" / "pacman.vtu") return meshplex.Mesh(mesh0.points[:, :2], mesh0.cells("points"))
def test_continuation(max_steps=5): a = 10.0 n = 20 points, cells = meshzoo.rectangle_tri(np.linspace(-a / 2, a / 2, n), np.linspace(-a / 2, a / 2, n)) # add column with zeros for magnetic potential points = np.column_stack([points, np.zeros(points.shape[0])]) mesh = meshplex.Mesh(points, cells) problem = GinzburgLandauReal(mesh) num_unknowns = 2 * problem.mesh.control_volumes.shape[0] u0 = np.ones(num_unknowns) u0[1::2] = 0.0 mu0 = 0.0 # plt.ion() # fig = plt.figure() # ax = fig.add_subplot(111) # plt.axis("square") # plt.xlabel("$\\mu$") # plt.ylabel("$||\\psi||_2$") # plt.grid() # b_list = [] # values_list = [] # line1, = ax.plot(b_list, values_list, "-", color="#1f77f4") mu_list = [] filename = "sol.xdmf" with meshio.xdmf.TimeSeriesWriter(filename) as writer: print(problem.mesh.cells) writer.write_points_cells(problem.mesh.points, [("triangle", problem.mesh.cells("points"))]) def callback(k, mu, sol): mu_list.append(mu) # Store the solution psi = np.array([sol[0::2], sol[1::2]]).T writer.write_data(k, point_data={"psi": psi}) with open("data.yml", "w") as fh: yaml.dump( { "filename": filename, "mu": [float(m) for m in mu_list] }, fh) # pacopy.natural( # problem, # u0, # b0, # callback, # max_steps=1, # lambda_stepsize0=1.0e-2, # newton_max_steps=5, # newton_tol=1.0e-10, # ) pacopy.euler_newton( problem, u0, mu0, callback, max_steps=max_steps, stepsize0=1.0e-2, stepsize_max=1.0, newton_tol=1.0e-10, )
def plot_data(): filename = "data.yml" with open(filename) as fh: data = yaml.safe_load(fh) reader = meshio.xdmf.TimeSeriesReader(data["filename"]) points, cell_blocks = reader.read_points_cells() x, y, _ = points.T triang = matplotlib.tri.Triangulation(x, y) # compute all energies in advance energies = [] mesh = meshplex.Mesh(points, cell_blocks[0].data) for k in range(len(data["mu"])): _, point_data, _ = reader.read_data(k) psi = point_data["psi"] psi = psi[:, 0] + 1j * psi[:, 1] energies.append(gibbs_energy(mesh, psi)) energies = np.array(energies) for k in range(len(data["mu"])): plt.figure(figsize=(11, 4)) ax1 = plt.subplot(1, 2, 1) ax1.plot(data["mu"], energies) ax1.set_xlim(0.0, 1.0) ax1.set_ylim(-1.0, 0.0) ax1.grid() ax1.plot(data["mu"][k], energies[k], "o", color="#1f77f4") ax1.set_xlabel("$\\mu$") ylabel = ax1.set_ylabel("$\\mathcal{E}(\\psi)$", labelpad=20) ylabel.set_rotation(0) ax2 = plt.subplot(1, 2, 2) _, point_data, _ = reader.read_data(k) psi = point_data["psi"] psi = psi[:, 0] + 1j * psi[:, 1] # The absolute values of the solution psi of the Ginzburg-Landau equations all # sit between 0 and 1, so we don't need a fancy scaling of absolute values for # cplot. This results in the values with |psi|=1 being displayed as white, # however, losing visual information about the complex argument. On the other # hand, plots are rather more bright, resulting in more visually appealing # figures. # Choose the brightness to range linearly between 0.0, and 0.7. cplot.tripcolor(triang, psi, abs_scaling=lambda z: 0.7 * z) # plt.tripcolor(triang, np.abs(psi)) cplot.tricontour_abs(triang, psi, np.linspace(0.0, 1.0, 6)) ax2.axis("square") ax2.set_xlim(-5.0, 5.0) ax2.set_ylim(-5.0, 5.0) ax2.set_title("$\\psi$") # plt.colorbar() # plt.set_cmap("gray") # plt.clim(0.0, 1.0) plt.tight_layout() plt.savefig(f"fig{k:03d}.png") # plt.show() plt.close()
def _main(): points = np.array([[0.0, 0.0], [1.0, 0.0], [0.3, 0.8]]) # points = np.array([[0.0, 0.0], [1.0, 0.0], [0.5, np.sqrt(3) / 2]]) cells = np.array([[0, 1, 2]]) mesh = meshplex.Mesh(points, cells) lw = 5.0 col = "0.6" ax = plt.gca() # circumcircle circle1 = plt.Circle( mesh.cell_circumcenters[0], mesh.cell_circumradius[0], color=col, fill=False, linewidth=lw, ) ax.add_patch(circle1) # perpendicular bisectors for i, j in [[0, 1], [1, 2], [2, 0]]: m1 = (points[i] + points[j]) / 2 v1 = m1 - mesh.cell_circumcenters[0] e1 = (mesh.cell_circumcenters[0] + v1 / np.linalg.norm(v1) * mesh.cell_circumradius[0]) plt.plot( [mesh.cell_circumcenters[0, 0], e1[0]], [mesh.cell_circumcenters[0, 1], e1[1]], col, linewidth=lw, ) # heights for i, j, k in [[0, 1, 2], [1, 2, 0], [2, 0, 1]]: p = points - points[i] v1 = p[j] / np.linalg.norm(p[j]) m1 = points[i] + np.dot(p[k], v1) * v1 plt.plot([points[k, 0], m1[0]], [points[k, 1], m1[1]], linewidth=lw, color=col) # # incircle # circle2 = plt.Circle( # mesh.cell_incenters[0], mesh.inradius[0], color=col, fill=False, linewidth=lw # ) # ax.add_patch(circle2) # # angle bisectors # for i, j, k in [[0, 1, 2], [1, 2, 0], [2, 0, 1]]: # p = points - points[i] # v1 = p[j] / np.linalg.norm(p[j]) # v2 = p[k] / np.linalg.norm(p[k]) # alpha = np.arccos(np.dot(v1, v2)) # c = np.cos(alpha / 2) # s = np.sin(alpha / 2) # beta = np.linalg.norm(mesh.cell_incenters[0] - points[i]) + mesh.inradius[0] # m1 = points[i] + np.dot([[c, -s], [s, c]], v1) * beta # plt.plot( # [points[i, 0], m1[0]], # [points[i, 1], m1[1]], # col, # linewidth=lw, # color=col, # ) # triangle plt.plot( [points[0, 0], points[1, 0], points[2, 0], points[0, 0]], [points[0, 1], points[1, 1], points[2, 1], points[0, 1]], color="#d62728", linewidth=lw, ) ax.set_xlim(-0.1, 1.1) ax.set_ylim(-0.4, 0.9) ax.set_aspect("equal") plt.axis("off") plt.savefig("logo.svg", bbox_inches="tight", transparent=True)
def simple_line(): X = np.array([0.0, 0.1, 0.4, 1.0]) cells = np.array([[0, 1], [1, 2], [2, 3]]) return meshplex.Mesh(X, cells)