em_app package
Submodules
em_app.plotting module
This module contains functions for plotting magnetic field data.
- em_app.plotting.plot_1d_field(coil_instance, field_component: str, axis: str = 'x', start_point: ndarray | None = None, end_point: ndarray | None = None, num_points: int = 100, plot_type: str = 'line', log_scale: bool = False, ax=None, title: str = '', xlabel: str = '', ylabel: str = '', **kwargs)[source]
Plots a vector field component along a 1D line.
- em_app.plotting.plot_2d_field(coil_instance, field_component: str = 'norm', plane: str = 'xy', center: ndarray | None = None, normal: ndarray | None = None, size_a: float | None = None, size_b: float | None = None, num_points_a: int = 50, num_points_b: int = 50, plot_type: str = 'heatmap', ax=None, title: str = '', offset_from_center: float = 0.0, **kwargs)[source]
Plots a vector field on a 2D plane.
- Parameters:
coil_instance – The coil object to calculate the field from.
field_component (str) – Component to plot (‘x’, ‘y’, ‘z’, or ‘norm’).
plane (str) – Plane to plot on (‘xy’, ‘yz’, or ‘xz’).
center (np.ndarray, optional) – Center point of the plot. Defaults to coil center.
normal (np.ndarray, optional) – Normal vector for custom plane.
size_a (float, optional) – Size along the first axis of the plane.
size_b (float, optional) – Size along the second axis of the plane.
num_points_a (int) – Grid points along first axis.
num_points_b (int) – Grid points along second axis.
plot_type (str) – Type of plot (‘heatmap’, ‘quiver’, ‘streamline’).
ax (matplotlib.axes.Axes, optional) – Matplotlib axis to plot on.
title (str) – Plot title.
offset_from_center (float) – Offset from the center along the normal.
**kwargs – Additional arguments passed to the plotting function.
- em_app.plotting.plot_field_vectors_3d(coil_instance, num_points_a: int = 10, num_points_b: int = 10, num_points_c: int = 10, title: str = '', ax=None, **kwargs)[source]
Generates a 3D quiver plot of the magnetic field vectors on a grid around the coil.
This method automatically creates a grid of field points based on the coil’s dimensions and then calculates and plots the magnetic field vectors at these points.
- Parameters:
coil_instance (Coil) – An instance of a Coil subclass.
num_points_a (int) – Number of grid points along the x-dimension.
num_points_b (int) – Number of grid points along the y-dimension.
num_points_c (int) – Number of grid points along the z-dimension.
title (str, optional) – The title of the plot. Defaults to an auto-generated title.
ax (matplotlib.axes.Axes3D, optional) – The 3D axis to plot on. If None, a new figure is created.
**kwargs – Additional keyword arguments for the ax.quiver function.
em_app.solvers module
- class em_app.solvers.Backend(value)[source]
Bases:
str,Enum- C = 'c'
- CPP = 'cpp'
- CPP_V2 = 'cpp_v2'
- MPI = 'mpi'
- PYTHON = 'python'
- em_app.solvers.calculate_b_field(coil_instance, field_points, backend=Backend.PYTHON)[source]
Calculates the magnetic field generated by a coil at a set of field points using the Biot-Savart law.
- Parameters:
coil_instance (Coil) – An instance of a Coil subclass.
of (field_points (np.ndarray or np.ndarray) – mtf.MultivariateTaylorFunction): The points (x, y, z) where the magnetic field should be calculated. Can be a (M, 3) NumPy array of numbers or MTF objects.
backend (Backend or str, optional) – The backend to use for the calculation. Defaults to Backend.PYTHON.
- Returns:
- A VectorField object containing the field points and the
calculated FieldVector objects.
- Return type:
- em_app.solvers.mpi_biot_savart(element_centers, element_lengths, element_directions, field_points, order=None)[source]
Parallel Biot-Savart calculation using mpi4py with element inputs.
Computes the magnetic field in parallel using MPI (mpi4py library). This function distributes the calculation of the magnetic field at different field points across multiple MPI processes to speed up computation.
Note
Requires mpi4py to be installed. If not installed, it will raise an ImportError.
Must be run in an MPI environment (e.g., using mpiexec or mpirun).
Input arrays element_centers, element_lengths, and element_directions are assumed to be the complete datasets and are broadcasted to all MPI processes.
field_points are distributed among processes. The result is gathered on rank 0.
- Parameters:
element_centers (numpy.ndarray) – (N, 3) array of center coordinates of current elements. (Broadcasted to all MPI processes).
element_lengths (numpy.ndarray) – (N,) array of lengths of current elements (dl). (Broadcasted to all MPI processes).
element_directions (numpy.ndarray) – (N, 3) array of unit vectors for current directions. (Broadcasted to all MPI processes).
field_points (numpy.ndarray) – (M, 3) array of field point coordinates. (Distributed across MPI processes).
- Returns:
On MPI rank 0: (M, 3) array of magnetic field vectors at each field point. On MPI ranks > 0: None.
- Return type:
numpy.ndarray or None
- Raises:
ImportError – if mpi4py is not installed.
- Example (Run in MPI environment, e.g.,
mpiexec -n 4 python your_script.py):
>>> import numpy as np >>> from applications.em.biot_savart import mpi_biot_savart >>> element_centers = np.array([[0, 0, 0], [1, 0, 0]]) >>> element_lengths = np.array([0.1, 0.1]) >>> element_directions = np.array([[1, 0, 0], [0, 1, 0]]) >>> # More field points for MPI to distribute >>> field_points = np.array( ... [[0, 1, 0], [1, 1, 0], [2, 1, 0], [3, 1, 0]] ... ) >>> B_field = mpi_biot_savart( ... element_centers, ... element_lengths, ... element_directions, ... field_points, ... ) >>> if MPI.COMM_WORLD.Get_rank() == 0: # Rank 0 has the full result >>> print(B_field)
- em_app.solvers.numpy_biot_savart(element_centers, element_lengths, element_directions, field_points, order=None)[source]
NumPy vectorized Biot-Savart calculation using element inputs.
Calculates the magnetic field at specified field points due to a set of current elements, using NumPy vectorization for efficiency. This function is designed for serial (single-processor) execution and takes element-based descriptions of the current source.
- Parameters:
element_centers (numpy.ndarray) – (N, 3) array of center coordinates of current elements. Each row represents the (x, y, z) coordinates of the center of a current element.
element_lengths (numpy.ndarray) – (N,) array of lengths of current elements (dl). Each element represents the length of the corresponding current element.
element_directions (numpy.ndarray) – (N, 3) array of unit vectors representing the direction of current flow for each element. Each row is a unit vector.
field_points (numpy.ndarray) – (M, 3) array of field point coordinates. Each row represents the (x, y, z) coordinates where the magnetic field is to be calculated.
- Returns:
- (M, 3) array of magnetic field vectors at each field
point. Each row is a vector representing the (Bx, By, Bz) components of the magnetic field at the corresponding field point.
- Return type:
numpy.ndarray
- Raises:
ValueError – If input arrays do not have the expected dimensions or shapes.
Example
>>> element_centers = np.array([[0, 0, 0], [1, 0, 0]]) >>> element_lengths = np.array([0.1, 0.1]) >>> element_directions = np.array([[1, 0, 0], [0, 1, 0]]) >>> field_points = np.array([[0, 1, 0], [1, 1, 0]]) >>> B_field = numpy_biot_savart( ... element_centers, ... element_lengths, ... element_directions, ... field_points, ... ) >>> print(B_field) [[ 0.00000000e+00 0.00000000e+00 1.00000000e-08] [ 0.00000000e+00 0.00000000e+00 5.00000000e-09]]
- em_app.solvers.serial_biot_savart(element_centers, element_lengths, element_directions, field_points, order=None, backend=Backend.PYTHON)[source]
Serial Biot-Savart calculation with element inputs.
Computes the magnetic field serially (non-parallel), taking current element center points, lengths, and directions as input. This function is suitable for single-processor execution and serves as a serial counterpart to the mpi_biot_savart function.
- Parameters:
element_centers (numpy.ndarray) – (N, 3) array of center coordinates of current elements.
element_lengths (numpy.ndarray) – (N,) array of lengths of current elements (dl).
element_directions (numpy.ndarray) – (N, 3) array of unit vectors for current directions.
field_points (numpy.ndarray) – (M, 3) array of field point coordinates.
order (int, optional) – The maximum order of the Taylor series to compute. If None, the global max order is used. Defaults to None.
- Returns:
- (M, 3) array of magnetic field vectors at each field
point.
- Return type:
numpy.ndarray
Example
>>> element_centers = np.array([[0, 0, 0], [1, 0, 0]]) >>> element_lengths = np.array([0.1, 0.1]) >>> element_directions = np.array([[1, 0, 0], [0, 1, 0]]) >>> field_points = np.array([[0, 1, 0], [1, 1, 0]]) >>> B_field = serial_biot_savart( ... element_centers, ... element_lengths, ... element_directions, ... field_points, ... order=0, ... ) >>> print(B_field) [[ 0.00000000e+00 0.00000000e+00 1.00000000e-08] [ 0.00000000e+00 0.00000000e+00 5.00000000e-09]]
em_app.sources module
- class em_app.sources.Coil(current, use_mtf_for_segments=True, wire_thickness=0.001)[source]
Bases:
objectBase class for a current-carrying coil.
This class provides a common interface for different coil shapes, storing their properties (like current) and the discretized segments used for numerical calculations.
- get_center_point() ndarray[source]
Calculates the approximate center point of the coil.
- Returns:
A (3,) array representing the center of the coil.
- Return type:
np.ndarray
- get_max_size() ndarray[source]
Calculates the maximum extent of the coil in each dimension.
- Returns:
- A (3,) array of the maximum size of the coil
(width, height, depth).
- Return type:
np.ndarray
- get_segments()[source]
Returns the segments of the coil.
- Returns:
- A tuple containing:
segment_centers (np.ndarray): Array of MTF center points.
segment_lengths (np.ndarray): Array of MTF segment lengths.
segment_directions (np.ndarray): Array of MTF direction vectors.
- Return type:
tuple
- plot(ax=None, color='#B87333', num_interpolation_points=2, wire_thickness=None, show_axis=False)[source]
Plots the coil segments in a 3D matplotlib axis.
If a 3D axis is provided, the coil will be plotted on it. Otherwise, a new figure and a new 3D axis will be created.
- Parameters:
ax (matplotlib.axes.Axes3D) – The 3D axis to plot on. Defaults to None.
color (str) – The color for the plotted segments. Defaults to a copper-like hex code.
num_interpolation_points (int) – The number of points to plot for each segment, including start and end points. This is only used when use_mtf_for_segments is True. Defaults to 2.
wire_thickness (float) – The thickness of the wire to plot. Defaults to the thickness specified at initialization.
show_axis (bool) – Whether to plot the central axis of the coil. Defaults to False.
- class em_app.sources.RectangularCoil(current, p1, p2, p4, num_segments_per_side, use_mtf_for_segments=True, wire_thickness=0.001)[source]
Bases:
CoilRepresents a rectangular current-carrying coil.
- static generate_geometry(p1, p2, p4, num_segments_per_side, use_mtf_for_segments=True)[source]
(PRIVATE) Generates segments for a rectangular coil.
- Parameters:
p1 (np.ndarray) – First corner of the rectangle.
p2 (np.ndarray) – Second corner, defining the first side from p1.
p4 (np.ndarray) – Fourth corner, defining the second side from p1.
num_segments_per_side (int) – Segments per side.
use_mtf_for_segments (bool) – Whether to use MTF for segments.
- Returns:
- A tuple containing:
segment_centers (np.ndarray): Array of MTF center points.
segment_lengths (np.ndarray): Array of segment lengths.
segment_directions (np.ndarray): Array of MTF direction vectors.
- Return type:
tuple
- class em_app.sources.RingCoil(current, radius, num_segments, center_point, axis_direction, use_mtf_for_segments=True, wire_thickness=0.001)[source]
Bases:
CoilRepresents a circular current-carrying coil.
- static generate_geometry(ring_radius, num_segments_ring, ring_center_point, ring_axis_direction, use_mtf_for_segments=True)[source]
(PRIVATE) Generates MTF representations for segments of a current ring.
This is a private helper function and should not be used directly.
- Parameters:
ring_radius (float) – Radius of the current ring.
num_segments_ring (int) – Number of segments to discretize the ring into.
ring_center_point (numpy.ndarray) – (3,) array defining the center coordinates (x, y, z) of the ring.
ring_axis_direction (numpy.ndarray) – (3,) array defining the direction vector of the ring’s axis (normal to the plane of the ring).
- Returns:
- A tuple containing:
segment_representations (numpy.ndarray): (N,) array of MTFs or (N, 3) array of segment center points.
element_lengths_ring (numpy.ndarray): (N,) array of lengths of each ring segment (dl).
direction_vectors (numpy.ndarray): (N, 3) array of MTF direction vectors or NumPy direction vectors.
- Return type:
tuple
em_app.vector_fields module
Vector and Vector Field representations.
This module provides classes for representing 3D vectors and vector fields, with support for numerical data and mtflib Multivariate Taylor Functions (MTFs). It includes classes like Vector, FieldVector, VectorField, and VectorFieldGrid.
- class em_app.vector_fields.FieldVector(x, y, z)[source]
Bases:
VectorRepresents a vector at a point in a field, with components that can be Multivariate Taylor Functions (MTFs).
- curl()[source]
Calculates the curl of the B-field vector.
The curl of the B-field is given by the formula: $nabla times mathbf{B} = (frac{partial B_z}{partial y} - frac{partial B_y}{partial z}) mathbf{i} + (frac{partial B_x}{partial z} - frac{partial B_z}{partial x}) mathbf{j} + (frac{partial B_y}{partial x} - frac{partial B_x}{partial y}) mathbf{k}$
This method uses the derivative method from mtflib to compute the partial derivatives.
- Returns:
- A new FieldVector object representing the curl of the
field.
- Return type:
- divergence()[source]
Calculates the divergence of the B-field.
The divergence of a vector field is a scalar value given by the formula: $nabla cdot mathbf{B} = frac{partial B_x}{partial x} + frac{partial B_y}{partial y} + frac{partial B_z}{partial z}$
This method uses the derivative method from mtflib to compute the partial derivatives and then sums the resulting MTF objects.
- Returns:
- A single MTF representing the
scalar divergence of the field.
- Return type:
mtf.MultivariateTaylorFunction
- gradient()[source]
Calculates the Jacobian matrix of the B-field vector.
The gradient of a vector field is a 3x3 matrix where each element is the partial derivative of a component of B with respect to a spatial variable.
- Returns:
A 3x3 array of MTFs representing the Jacobian matrix.
- Return type:
np.ndarray
- class em_app.vector_fields.Vector(*components)[source]
Bases:
objectA generic class to represent a 3D vector. This class handles standard vector operations like addition, subtraction, scalar multiplication/division, dot product, and cross product.
- dot(other)[source]
Calculates the dot product with another Vector object.
- Parameters:
other (Vector) – The Vector object to take the dot product with.
- Returns:
- The scalar result of the
dot product.
- Return type:
mtf.MultivariateTaylorFunction or float
- classmethod from_array_of_vectors(array)[source]
Creates a NumPy array of Vector objects from a 2D NumPy array.
- Parameters:
array (np.ndarray) – A NumPy array of shape (N, 3), where N is the number of vectors.
- Returns:
A NumPy array of Vector objects.
- Return type:
np.ndarray
- is_mtf()[source]
Checks if any of the Vector’s components are MTF objects.
- Returns:
True if any component is an MTF, False otherwise.
- Return type:
bool
- norm()[source]
Calculates the magnitude (L2-norm) of the vector.
- Returns:
The scalar magnitude.
- Return type:
float or mtf.MultivariateTaylorFunction
- to_dataframe(column_names)[source]
Converts the Vector components into a pandas DataFrame.
This method is a helper for creating a clean, tabular representation of the vector, especially when components are MTF objects.
- Parameters:
column_names (list of str) – A list of three strings to be used as the column names for the components.
- Returns:
- A DataFrame representing the vector’s components
and their coefficients if they are MTFs.
- Return type:
pandas.DataFrame
- class em_app.vector_fields.VectorField(vectors, field_points=None)[source]
Bases:
objectA class to store a collection of FieldVector objects, representing a vector field at a set of discrete points in space.
This class can handle both numerical and MTF-based field data.
- get_magnitude()[source]
Calculates and returns the magnitude of each B-vector in the field.
- Returns:
A 1D NumPy array of the magnitudes.
- Return type:
np.ndarray
- quiver(dimension=3, title='Vector Field Quiver Plot', ax=None, **kwargs)[source]
Creates a 3D quiver plot of the vector field.
- Parameters:
title (str, optional) – The title of the plot.
ax (matplotlib.axes.Axes, optional) – An existing 3D Axes object to plot on.
**kwargs – Additional keyword arguments passed to ax.quiver.
- scatter(title='Vector Field Scatter Plot', ax=None, **kwargs)[source]
Creates a 3D scatter plot of the vector field with direction arrows. The color and length of the arrows represent the magnitude of the vectors. This method provides a way to visualize the raw vector field, where arrow lengths are proportional to the vector strength.
- Parameters:
title (str, optional) – The title of the plot.
ax (matplotlib.axes.Axes, optional) – An existing 3D Axes object to plot on.
**kwargs – Additional keyword arguments passed to ax.quiver.
- class em_app.vector_fields.VectorFieldGrid(vectors, field_points, grid_shape, grid_axes)[source]
Bases:
VectorFieldA subclass of VectorField for data on a structured 1D, 2D, or 3D grid.
This class is designed to hold vector field data that is arranged on a structured grid. It stores grid metadata (shape and axes) to allow for easy reshaping of the data for grid-based analysis and plotting.