Python package for solving partial differential equations with a focus on ease of use and performance
—
Field classes represent data on discrete grids and provide mathematical operations for solving PDEs. py-pde supports scalar, vector, and tensor fields with automatic differentiation and high-performance numba-compiled operations.
Represents scalar-valued functions on grids, providing differential operators and field manipulations.
class ScalarField:
def __init__(self, grid, data=None, *, label=None):
"""
Initialize scalar field on a grid.
Parameters:
- grid: GridBase, the spatial grid
- data: array-like, field values (if None, initializes to zeros)
- label: str, optional label for the field
"""
@classmethod
def random_uniform(cls, grid, vmin=0, vmax=1, **kwargs):
"""
Create field with random uniform values.
Parameters:
- grid: GridBase, the spatial grid
- vmin: float, minimum value
- vmax: float, maximum value
Returns:
ScalarField with random data
"""
@classmethod
def random_normal(cls, grid, mean=0, std=1, **kwargs):
"""
Create field with random normal values.
Parameters:
- grid: GridBase, the spatial grid
- mean: float, mean value
- std: float, standard deviation
Returns:
ScalarField with random normal data
"""
@classmethod
def from_expression(cls, grid, expression, *, user_funcs=None, consts=None, label=None, dtype=None):
"""
Create field from mathematical expression.
Parameters:
- grid: GridBase, the spatial grid
- expression: str or callable, mathematical expression or function
- user_funcs: dict, optional user-defined functions
- consts: dict, optional constants
- label: str, optional field label
- dtype: data type for field values
Returns:
ScalarField created from expression
"""
@classmethod
def from_image(cls, filename, bounds=None, grid=None, *, periodic=None, label=None, dtype=None):
"""
Create field from image file.
Parameters:
- filename: str, path to image file
- bounds: sequence, spatial bounds for the image
- grid: GridBase, optional target grid
- periodic: bool or sequence, periodicity per axis
- label: str, optional field label
- dtype: data type for field values
Returns:
ScalarField created from image data
"""
def laplace(self, bc, **kwargs):
"""
Apply Laplacian operator.
Parameters:
- bc: boundary conditions
- kwargs: additional arguments for operator
Returns:
ScalarField with Laplacian applied
"""
def gradient(self, bc):
"""
Calculate gradient.
Parameters:
- bc: boundary conditions
Returns:
VectorField representing the gradient
"""
def gradient_squared(self, bc=None, *, args=None, **kwargs):
"""
Calculate squared magnitude of gradient.
Parameters:
- bc: boundary conditions
- args: additional arguments for operator
- kwargs: additional keyword arguments
Returns:
ScalarField with squared gradient magnitudes
"""
def project(self, axes, method='integral'):
"""
Project field onto lower-dimensional space.
Parameters:
- axes: int or sequence, axes to project onto
- method: str, projection method ('integral' or 'mean')
Returns:
ScalarField projected onto specified axes
"""
def slice(self, indices, *, label=None):
"""
Extract slice of the field.
Parameters:
- indices: slice indices for each axis
- label: str, optional label for sliced field
Returns:
ScalarField containing the slice
"""
def to_scalar(self, scalar='auto'):
"""
Convert to scalar field.
Parameters:
- scalar: str, conversion method
Returns:
ScalarField representation
"""
def get_boundary_field(self, axis, upper, bc_type='auto_periodic_neumann'):
"""
Extract boundary field values.
Parameters:
- axis: int, axis along which to extract boundary
- upper: bool, whether to use upper boundary
- bc_type: str, boundary condition type
Returns:
ScalarField containing boundary values
"""
@property
def average(self):
"""float: Average value of the field"""
@property
def std(self):
"""float: Standard deviation of field values"""
def integral(self):
"""
Calculate field integral over the domain.
Returns:
float: Integral value
"""
def interpolate_to_grid(self, grid, *, bc=None, args=None, **kwargs):
"""
Interpolate field to different grid.
Parameters:
- grid: GridBase, target grid
- bc: boundary conditions for interpolation
- args: additional arguments
- kwargs: additional keyword arguments
Returns:
ScalarField interpolated to new grid
"""Represents vector-valued functions on grids with vector calculus operations.
class VectorField:
def __init__(self, grid, data=None, *, label=None):
"""
Initialize vector field on a grid.
Parameters:
- grid: GridBase, the spatial grid
- data: array-like, field values (shape: [grid_shape, dim])
- label: str, optional label for the field
"""
@classmethod
def random_uniform(cls, grid, vmin=0, vmax=1, **kwargs):
"""
Create vector field with random uniform values.
Parameters:
- grid: GridBase, the spatial grid
- vmin: float or array-like, minimum values
- vmax: float or array-like, maximum values
Returns:
VectorField with random data
"""
@classmethod
def from_scalars(cls, fields, *, label=None, dtype=None):
"""
Create vector field from scalar field components.
Parameters:
- fields: list of ScalarField, component fields
- label: str, optional label for vector field
- dtype: data type for field values
Returns:
VectorField created from scalar components
"""
@classmethod
def from_expression(cls, grid, expressions, *, user_funcs=None, consts=None, label=None, dtype=None):
"""
Create vector field from mathematical expressions.
Parameters:
- grid: GridBase, the spatial grid
- expressions: list of str or callable, expressions for each component
- user_funcs: dict, optional user-defined functions
- consts: dict, optional constants
- label: str, optional field label
- dtype: data type for field values
Returns:
VectorField created from expressions
"""
def divergence(self, bc):
"""
Calculate divergence.
Parameters:
- bc: boundary conditions
Returns:
ScalarField representing the divergence
"""
def curl(self, bc):
"""
Calculate curl (2D and 3D only).
Parameters:
- bc: boundary conditions
Returns:
VectorField (3D) or ScalarField (2D) representing the curl
"""
def magnitude(self):
"""
Calculate magnitude at each point.
Returns:
ScalarField with vector magnitudes
"""
def dot(self, other, out=None, *, label=None):
"""
Calculate dot product with another vector field.
Parameters:
- other: VectorField, field to dot with
- out: optional output field
- label: str, optional label for result
Returns:
ScalarField containing dot product
"""
def outer_product(self, other, out=None, *, label=None):
"""
Calculate outer product with another vector field.
Parameters:
- other: VectorField, field for outer product
- out: optional output field
- label: str, optional label for result
Returns:
Tensor2Field containing outer product
"""
def make_outer_prod_operator(self, backend='auto'):
"""
Create operator for efficient outer product calculations.
Parameters:
- backend: str, computational backend to use
Returns:
Callable outer product operator
"""
def gradient(self, bc=None, *, args=None, **kwargs):
"""
Calculate gradient (tensor field).
Parameters:
- bc: boundary conditions
- args: additional arguments for operator
- kwargs: additional keyword arguments
Returns:
Tensor2Field representing the gradient
"""
def laplace(self, bc=None, *, args=None, **kwargs):
"""
Apply vector Laplacian operator.
Parameters:
- bc: boundary conditions
- args: additional arguments for operator
- kwargs: additional keyword arguments
Returns:
VectorField with Laplacian applied
"""
def integral(self):
"""
Calculate field integral over the domain.
Returns:
np.ndarray: Integral values for each component
"""
def to_scalar(self, scalar='auto'):
"""
Convert to scalar field.
Parameters:
- scalar: str, conversion method ('auto', 'norm', etc.)
Returns:
ScalarField representation
"""
def get_vector_data(self, transpose=True):
"""
Get data for vector visualization.
Parameters:
- transpose: bool, whether to transpose data
Returns:
dict with vector visualization data
"""
def interpolate_to_grid(self, grid, *, bc=None, args=None, **kwargs):
"""
Interpolate field to different grid.
Parameters:
- grid: GridBase, target grid
- bc: boundary conditions for interpolation
- args: additional arguments
- kwargs: additional keyword arguments
Returns:
VectorField interpolated to new grid
"""Represents second-rank tensor fields on grids.
class Tensor2Field:
def __init__(self, grid, data=None, *, label=None):
"""
Initialize tensor field on a grid.
Parameters:
- grid: GridBase, the spatial grid
- data: array-like, field values (shape: [grid_shape, dim, dim])
- label: str, optional label for the field
"""
@classmethod
def from_expression(cls, grid, expressions, *, user_funcs=None, consts=None, label=None, dtype=None):
"""
Create tensor field from mathematical expressions.
Parameters:
- grid: GridBase, the spatial grid
- expressions: nested list or callable, expressions for tensor components
- user_funcs: dict, optional user-defined functions
- consts: dict, optional constants
- label: str, optional field label
- dtype: data type for field values
Returns:
Tensor2Field created from expressions
"""
def trace(self):
"""
Calculate trace of the tensor field.
Returns:
ScalarField with tensor traces
"""
def transpose(self, label='transpose'):
"""
Calculate transpose of the tensor field.
Parameters:
- label: str, label for transposed field
Returns:
Tensor2Field with transposed tensors
"""
def dot(self, other, out=None, *, axes=None, label=None):
"""
Calculate dot product with vector or tensor field.
Parameters:
- other: VectorField or Tensor2Field, field to dot with
- out: optional output field
- axes: tuple, axes for contraction
- label: str, optional label for result
Returns:
DataFieldBase containing dot product result
"""
def divergence(self, bc=None, *, args=None, **kwargs):
"""
Calculate divergence of tensor field.
Parameters:
- bc: boundary conditions
- args: additional arguments for operator
- kwargs: additional keyword arguments
Returns:
VectorField representing the divergence
"""
def integral(self):
"""
Calculate field integral over the domain.
Returns:
np.ndarray: Integral values for tensor components
"""
def symmetrize(self, make_traceless=False, *, label=None):
"""
Symmetrize the tensor field.
Parameters:
- make_traceless: bool, whether to make traceless
- label: str, optional label for result
Returns:
Tensor2Field with symmetrized tensors
"""
def to_scalar(self, scalar='auto'):
"""
Convert to scalar field.
Parameters:
- scalar: str, conversion method
Returns:
ScalarField representation
"""
def plot_components(self, **kwargs):
"""
Plot tensor field components.
Parameters:
- kwargs: plotting arguments
Returns:
PlotReference with component plots
"""Manages collections of multiple fields for coupled PDE systems.
class FieldCollection:
def __init__(self, fields, *, label=None, copy_fields=False):
"""
Initialize collection of fields.
Parameters:
- fields: list of FieldBase, the fields to collect
- label: str, optional label for the collection
- copy_fields: bool, whether to copy the fields
"""
@classmethod
def from_state(cls, attributes, data=None):
"""
Create field collection from state information.
Parameters:
- attributes: dict, field attributes and metadata
- data: array-like, optional field data
Returns:
FieldCollection created from state
"""
def __getitem__(self, index):
"""Access individual fields by index or slice"""
def __len__(self):
"""Number of fields in collection"""
@property
def grid(self):
"""GridBase: Grid shared by all fields"""
def copy(self):
"""
Create copy of the field collection.
Returns:
FieldCollection with copied fields
"""
@property
def fields(self):
"""list: Individual fields in the collection"""
@property
def labels(self):
"""list: Labels of fields in the collection"""
def assert_field_compatible(self, other, accept_scalar=False):
"""
Check field compatibility for operations.
Parameters:
- other: FieldBase or FieldCollection, field to check
- accept_scalar: bool, whether to accept scalar fields
"""
def integrals(self):
"""
Calculate integrals of all fields.
Returns:
list: Integral values for each field
"""
def averages(self):
"""
Calculate averages of all fields.
Returns:
list: Average values for each field
"""
def magnitudes(self):
"""
Calculate magnitudes of all fields.
Returns:
np.ndarray: Magnitude values for each field
"""
def get_image_data(self, index=0, **kwargs):
"""
Get image data for visualization.
Parameters:
- index: int, field index to visualize
- kwargs: additional visualization parameters
Returns:
dict: Image data and metadata
"""Abstract base class for all field types providing common functionality.
class FieldBase:
@property
def grid(self):
"""GridBase: Grid on which field is defined"""
@property
def data(self):
"""np.ndarray: Raw field data"""
@property
def label(self):
"""str: Field label"""
def copy(self, *, label=None):
"""
Create copy of the field.
Parameters:
- label: str, optional new label
Returns:
FieldBase copy of same type
"""
def interpolate_to_grid(self, grid, *, bc=None, fill=None):
"""
Interpolate field to different grid.
Parameters:
- grid: GridBase, target grid
- bc: boundary conditions for interpolation
- fill: value for points outside domain
Returns:
FieldBase interpolated to new grid
"""import pde
import numpy as np
# Create a 2D Cartesian grid
grid = pde.CartesianGrid([[0, 10], [0, 10]], [64, 64])
# Initialize scalar field with Gaussian
def gaussian(x, y):
return np.exp(-(x-5)**2/2 - (y-5)**2/2)
field = pde.ScalarField.from_expression(grid, gaussian)
# Apply Laplacian with Neumann boundary conditions
bc = {"derivative": 0}
laplacian = field.laplace(bc)
print(f"Original field integral: {field.integral():.3f}")
print(f"Laplacian integral: {laplacian.integral():.3f}")import pde
# Create 2D grid
grid = pde.CartesianGrid([[-5, 5], [-5, 5]], [32, 32])
# Create a vortex vector field
def vortex_field(x, y):
return [-y, x]
vector_field = pde.VectorField.from_expression(grid, vortex_field)
# Calculate divergence and curl
bc = {"derivative": 0}
div = vector_field.divergence(bc)
curl = vector_field.curl(bc)
print(f"Divergence range: [{div.data.min():.3f}, {div.data.max():.3f}]")
print(f"Curl range: [{curl.data.min():.3f}, {curl.data.max():.3f}]")Install with Tessl CLI
npx tessl i tessl/pypi-py-pde