Arithmetic and NumPy Ufunc Support

Arithmetic and NumPy Ufunc Support#

SphericalMesh (and CartesianMesh) inherit a full arithmetic suite from _BaseFrameMesh. Standard Python operators (+, -, *, /, **, etc.) and NumPy ufuncs such as numpy.log10() and numpy.sqrt() operate element-wise on the active scalar field and return a new mesh of the same type with the result as the active scalar. The coordinate arrays are never modified — only the data changes.

import numpy as np
from pyvisual import Plot3d
from pyvisual.core.mesh3d import SphericalMesh

Build a Base Mesh#

We start with a simple dipole-like \(B_r\) field, scaled to be everywhere positive so that logarithmic operations are well-defined.

r = np.linspace(1, 10, 20)
t = np.linspace(0.1, np.pi - 0.1, 30)   # avoid exact poles
p = np.linspace(0, 2 * np.pi, 60)

R, T, P = np.meshgrid(r, t, p, indexing='ij')
Br = np.abs(np.cos(T)) / R ** 2          # always positive

mesh = SphericalMesh(r, t, p, data=Br, dataid='Br')

Radial Flux Scaling#

Multiplying by \(r^2\) removes the geometric falloff and converts \(B_r\) to the signed radial flux \(B_r r^2\). The coordinate arrays are unchanged; only the active scalar is updated.

R_axis = np.linspace(1, 10, 20)
mesh_r2 = mesh * R_axis[:, None, None] ** 2
print(f"Br     range: [{mesh.data.min():.4f}, {mesh.data.max():.4f}]")
print(f"Br r^2 range: [{mesh_r2.data.min():.4f}, {mesh_r2.data.max():.4f}]")

plotter = Plot3d(off_screen=True, window_size=(500, 500))
plotter.show_axes()
plotter.add_sun()
plotter.add_mesh(mesh_r2, cmap='hot', opacity=0.5, show_scalar_bar=False)
plotter.show()
p02 arithmetic
Br     range: [0.0005, 0.9950]
Br r^2 range: [0.0507, 0.9950]

NumPy Ufunc: np.log10#

The __array_ufunc__() hook lets any single-output NumPy ufunc act directly on the mesh. numpy.log10() applied to \(B_r r^2\) converts the field to a logarithmic scale, which is useful when the data spans several decades.

mesh_log = np.log10(mesh_r2)
print(f"log10(Br r^2) range: [{mesh_log.data.min():.3f}, {mesh_log.data.max():.3f}]")

plotter = Plot3d(off_screen=True, window_size=(500, 500))
plotter.show_axes()
plotter.add_sun()
plotter.add_mesh(mesh_log, cmap='inferno', opacity=0.5, show_scalar_bar=False)
plotter.show()
p02 arithmetic
log10(Br r^2) range: [-1.295, -0.002]

Total running time of the script: (0 minutes 1.046 seconds)

Gallery generated by Sphinx-Gallery