Pyvista Bodies#

Pyvista is a powerful open-source tool for the creation and visualization of meshes. Pyvista PolyData objects can be directly transformed into Magpylib TriangularMesh magnets via the classmethod from_pyvista.

Note

The Pyvista library used in the following examples is not automatically installed with Magpylib. A Pyvista installation guide is found here.

Dodecahedron Magnet#

In this example a Magpylib magnet is generated directly from a Pyvista body.

import numpy as np
import pyvista as pv
import magpylib as magpy

# Create a simple pyvista PolyData object
dodec_mesh = pv.Dodecahedron(radius=.01)

dodec = magpy.magnet.TriangularMesh.from_pyvista(
    polarization=(0, 0, .1),
    polydata=dodec_mesh,
)

# Add a sensor with path
sens = magpy.Sensor(position=np.linspace((-2,0,1), (2,0,1), 100)/100)

# Show system and field
with magpy.show_context(dodec, sens, backend='plotly') as s:
    s.show(col=1)
    s.show(col=2, output=['Bx', 'Bz'])

Boolean operations with Pyvista#

With Pyvista it is possible to build complex shapes with boolean geometric operations. However, such operations often result in open and disconnected meshes that require some refinement to produce solid magnets. The following example demonstrates the problem, how to analyze and fix it.

import pyvista as pv
import magpylib as magpy

# Create a complex pyvista PolyData object using a boolean operation
sphere = pv.Sphere(radius=0.006)
cube = pv.Cube(x_length=.01, y_length=.01, z_length=.01).triangulate()
obj = cube.boolean_difference(sphere)

# Construct magnet from PolyData object and ignore check results
magnet = magpy.magnet.TriangularMesh.from_pyvista(
    polarization=(0, 0, .1),
    polydata=obj,
    check_disconnected="ignore",
    check_open="ignore",
    reorient_faces="ignore",
    style_label="magnet",
)

print(f'mesh status open: {magnet.status_open}')
print(f'mesh status disconnected: {magnet.status_disconnected}')
print(f"mesh status self-intersecting: {magnet.status_selfintersecting}")
print(f'mesh status reoriented: {magnet.status_reoriented}')

magnet.show(
    backend="plotly",
    style_mesh_open_show=True,
    style_mesh_disconnected_show=True,
)
mesh status open: True
mesh status disconnected: True
mesh status self-intersecting: False
mesh status reoriented: True

The result cannot be used for magnetic field computation. Even if all faces were present, the reorient-faces algorithm would fail when these faces are disconnected. Such problems can be fixed by

  1. giving Pyvista a finer mesh to work with from the start

  2. Pyvista mesh cleaning (merge duplicate points, remove unused points, remove degenerate faces)

The following code produces a clean magnet .

import pyvista as pv
import magpylib as magpy

# Create a complex pyvista PolyData object using a boolean operation. Start with
# finer mesh and clean after operation
sphere = pv.Sphere(radius=0.6)
cube = pv.Cube().triangulate().subdivide(2)
obj = cube.boolean_difference(sphere)
obj = obj.clean()
obj = obj.scale([1e-2]*3)

# Construct magnet from PolyData object
magnet = magpy.magnet.TriangularMesh.from_pyvista(
    polarization=(0, 0, .1),
    polydata=obj,
    style_label="magnet",
)

print(f'mesh status open: {magnet.status_open}')
print(f'mesh status disconnected: {magnet.status_disconnected}')
print(f"mesh status self-intersecting: {magnet.status_selfintersecting}")
print(f'mesh status reoriented: {magnet.status_reoriented}')

magnet.show(backend="plotly")
mesh status open: False
mesh status disconnected: False
mesh status self-intersecting: False
mesh status reoriented: True