def test_others(): mesh = load_example_mesh("unit_disc") vals = np.ones((len(mesh.vertices),)) - np.linalg.norm(mesh.vertices, axis=1) G = mesh_calculus.gradient(vals, mesh, rotated=False) Gr = mesh_calculus.gradient(vals, mesh, rotated=True) D = mesh_calculus.divergence(Gr.T, mesh) C = mesh_calculus.curl(Gr.T, mesh)
def compare_contour_direction_to_rotated_gradient(mesh, scalars, polyline): """ Check inner product between the polyline edges the rotated gradient vectors closes to the initial points of those edges. These should point to the same direction. Parameters ---------- mesh : trimesh mesh scalars : ndarray stream function polyline : ndarray (N, 3) coordinates of points representing a polyline """ from bfieldtools.mesh_calculus import gradient edges = polyline[1:] - polyline[:-1] g = gradient(scalars, mesh, rotated=True).T fc = mesh.vertices[mesh.faces].mean(axis=1) norm = np.linalg.norm p = polyline # Find closest face centers to polyline nodes f_inds = np.argmin(norm(p[:, None, :] - fc[None, :, :], axis=-1), axis=1) g_poly = g[f_inds] assert np.all(np.sum(g_poly[:-1] * edges, axis=1) > 0)
fig = mlab.figure(bgcolor=(1, 1, 1)) surf = s.plot(False, figure=fig) surf.actor.mapper.interpolate_scalars_before_mapping = True surf.module_manager.scalar_lut_manager.number_of_colors = 16 vecs = mlab.pipeline.vector_field( *vol_points.T.reshape(3, Nvol, Nvol, Nvol), *Bvol.T.reshape(3, Nvol, Nvol, Nvol) ) vecnorm = mlab.pipeline.extract_vector_norm(vecs) seed_points = mesh.vertices[mesh.faces].mean(axis=1) - 0.01 * mesh.face_normals seed_vals = c.basis @ c.inductance @ s seed_vals_grad = np.linalg.norm(gradient(seed_vals, c.mesh), axis=0) seed_vals = abs(seed_vals[mesh.faces].mean(axis=1)) ** 2 seed_vals[seed_vals_grad > seed_vals_grad.max() / 1.8] = 0 Npoints = 500 seed_inds = np.random.choice( np.arange(len(seed_vals)), Npoints, False, seed_vals / seed_vals.sum() ) seed_points = seed_points[seed_inds] streams = [] for pi in seed_points: streamline = mlab.pipeline.streamline(
s = StreamFunction(s, c) from mayavi import mlab from mayavi.api import Engine engine = Engine() engine.start() f = mlab.figure(None, bgcolor=(1, 1, 1), fgcolor=(0.5, 0.5, 0.5), size=(800, 700)) s.plot(figure=f, ncolors=256) c.plot_mesh(representation="wireframe", figure=f) j = gradient(s.vert, c.mesh, rotated=True) Len = np.log(np.linalg.norm(j, axis=0)) vectors = mlab.quiver3d(*c.mesh.triangles_center.T, *j, mode="arrow", colormap="Greens", scalars=Len) # vectors = engine.scenes[0].children[2].children[0].children[0] vectors.glyph.glyph.scale_mode = "scale_by_scalar" vectors.glyph.glyph.scale_factor = 0.6 f.scene.z_plus_view() #
# lls = np.linspace(0.01,1.0, 100) # mm = [] # for ll in lls: # u, v, mesh2d = flatten_mesh(mesh, _lambda=ll) # d = mesh2d.area_faces / mesh.area_faces # mm.append(np.std(d)/np.mean(d)) # print(np.std(d)/np.mean(d)) # plt.plot(lls, mm) #%% Plot flattened mesh and area distortion on faces plot_data_on_faces(mesh2d, mesh2d.area_faces / mesh.area_faces) #%% Plot gradient of the two coordinate functions and the cosine of the angle between the gradients from bfieldtools.mesh_calculus import gradient gx = gradient(u, mesh) gy = gradient(v, mesh) cos = np.sum(gx * gy, axis=0) / (np.linalg.norm(gx, axis=0) * np.linalg.norm(gy, axis=0)) plot_data_on_faces(mesh, cos, vmin=-1, vmax=1) mlab.quiver3d(*mesh.triangles_center.T, *gx, color=(1, 0, 0), mode="arrow") q = mlab.quiver3d(*mesh.triangles_center.T, *gy, color=(0, 0, 1), mode="arrow") q.scene.isometric_view() #%% Map hexagonal grid from 2d to the 3D mesh d = np.sqrt(3 / 4) m = np.min((u.min(), v.min())) mm = np.min((u.max(), v.max())) xx = np.linspace(m * 1.05, mm * 1.05, 12) yy = np.linspace(m * 1.05, mm * 1.05, 12) * d p = np.array(np.meshgrid(xx, yy, 0, indexing="ij"))
plane = load_example_mesh("10x10_plane_hires") scaling_factor = 0.03 plane.apply_scale(scaling_factor) # Rotate to x-plane t = np.eye(4) theta = np.pi / 2 * 1.2 t[1:3, 1:3] = np.array([[np.cos(theta), np.sin(theta)], [-np.sin(theta), np.cos(theta)]]) plane.apply_transform(t) c.U_coupling.reset() U_suh = c.U_coupling(plane.vertices) @ a # Adapt mesh to the function and calculate new points for i in range(2): g = np.linalg.norm(gradient(U_suh, plane), axis=0) face_ind = np.flatnonzero(g > g.max() * 0.05) plane = plane.subdivide(face_ind) U_suh = c.U_coupling(plane.vertices) @ a U_sph = potential(plane.vertices, alpha, np.zeros(alpha.shape), lmax=lmax, normalization="energy", R=R) #%% # Mask inside/outside using solid angle mask = abs(c.U_coupling.matrix.sum(axis=1)) < 1e-6
# Load simple plane mesh that is centered on the origin file_obj = file_obj = pkg_resources.resource_filename( "bfieldtools", "example_meshes/10x10_plane.obj") planemesh = trimesh.load(file_obj, process=False) # Generate a simple scalar function r = np.linalg.norm(planemesh.vertices, axis=1) vals = np.exp(-0.5 * (r / r.max())) # triangle centers for plotting tri_centers = planemesh.vertices[planemesh.faces].mean(axis=1).T tri_centers[1] += 0.1 #%% # Calculate the gradient (e.g., flow from potential) g = gradient(vals, planemesh, rotated=False) # Plot function and its gradient as arrows scene = mlab.figure(None, bgcolor=(1, 1, 1), fgcolor=(0.5, 0.5, 0.5), size=(800, 800)) plot_data_on_vertices(planemesh, vals, ncolors=15, figure=scene) vecs = mlab.quiver3d(*tri_centers, *g, color=(1, 1, 1), mode="arrow", scale_factor=5) vecs.glyph.glyph_source.glyph_position = "center"
#%% Test against analytic formula # Load simple plane mesh that is centered on the origin file_obj = pkg_resources.resource_filename( "bfieldtools", "example_meshes/unit_disc.stl" ) discmesh = trimesh.load(file_obj, process=True) for ii in range(3): discmesh = discmesh.subdivide() disc = MeshConductor(mesh_obj=discmesh) weights = np.zeros(discmesh.vertices.shape[0]) weights[disc.inner_vertices] = 1 mlab.figure() s = mlab.triangular_mesh( *discmesh.vertices.T, discmesh.faces, scalars=weights, colormap="viridis" ) g = gradient(weights, discmesh, rotated=True) mlab.quiver3d(*discmesh.vertices[discmesh.faces].mean(axis=1).T, *g) test_points = np.zeros((100, 3)) test_points[:, 2] = np.linspace(0.0, 5, 100) mlab.points3d(*test_points.T, scale_factor=0.1) # Bfield for 1 Ampere current B0 = magnetic_field_coupling(discmesh, test_points) @ weights B1 = magnetic_field_coupling_analytic(discmesh, test_points) @ weights # Analytic formula for unit disc plt.plot(1e-7 * 2 * np.pi / (np.sqrt(test_points[:, 2] ** 2 + 1) ** 3)) # Field from the mesh plt.plot(np.linalg.norm(B0, axis=1)) plt.plot(np.linalg.norm(B1, axis=1))
opacity=1.0) s.enable_contours = True s.contour.filled_contours = True s.contour.number_of_contours = 30 #%% #%% Calculate linear collocation BEM matrix P_shield = shield.U_coupling(shieldmesh.vertices - d * shieldmesh.vertex_normals) #%% #%% Solve equivalent stream function for the perfect linear mu-metal layer I_shield = np.linalg.solve(-P_shield, P_prim @ sprim) # I_shield = P_prim @ I_prim s_shield = StreamFunction(I_shield, shield) g = gradient(s_shield, shieldmesh, rotated=True) #%% Plot the result fig = mlab.figure(bgcolor=(1, 1, 1)) s0 = mlab.triangular_mesh(*shieldmesh.vertices.T, shieldmesh.faces, color=(0.5, 0.5, 0.5), opacity=0.3) s0.actor.property.backface_culling = False s1 = s_shield.plot(False, 256) # s1.actor.property.opacity=0.8 s1.actor.property.backface_culling = False # s2 = s_shield.plot(True, 10) mlab.quiver3d(*shieldmesh.triangles_center.T, *g, color=(1, 1, 1),