Python package for solving partial differential equations with a focus on ease of use and performance
—
Boundary condition system supporting Dirichlet, Neumann, mixed, and periodic conditions with expression-based inhomogeneous boundaries for precise control of field behavior at domain edges.
Impose specific values at boundaries.
class DirichletBC:
def __init__(self, value, *, rank=0):
"""
Initialize Dirichlet boundary condition.
Parameters:
- value: float, str, array, or callable, boundary value
- rank: int, tensor rank of the field (0=scalar, 1=vector, 2=tensor)
"""
@property
def value(self):
"""Boundary value specification"""
def get_data(self, grid, *, derivatives=False):
"""
Get boundary data for given grid.
Parameters:
- grid: GridBase, spatial grid
- derivatives: bool, whether to return derivative information
Returns:
array-like: Boundary values
"""Impose specific normal derivatives at boundaries.
class NeumannBC:
def __init__(self, value, *, rank=0):
"""
Initialize Neumann boundary condition.
Parameters:
- value: float, str, array, or callable, normal derivative value
- rank: int, tensor rank of the field
"""
def get_virtual_point_data(self, grid):
"""
Get data for virtual points beyond boundary.
Parameters:
- grid: GridBase, spatial grid
Returns:
array-like: Virtual point values
"""Impose linear combinations of field values and derivatives.
class MixedBC:
def __init__(self, value, const, *, rank=0):
"""
Initialize mixed boundary condition: ∂ₙf + value·f = const
Parameters:
- value: float, str, array, or callable, coefficient for field value
- const: float, str, array, or callable, constant term
- rank: int, tensor rank of the field
"""
@property
def value(self):
"""Coefficient for field value"""
@property
def const(self):
"""Constant term in boundary condition"""Impose specific second derivatives (curvature) at boundaries.
class CurvatureBC:
def __init__(self, value, *, rank=0):
"""
Initialize curvature boundary condition.
Parameters:
- value: float, str, array, or callable, second derivative value
- rank: int, tensor rank of the field
"""Boundary conditions affecting only the normal component of vector/tensor fields.
class NormalDirichletBC:
def __init__(self, value):
"""
Dirichlet condition for normal component only.
Parameters:
- value: float, str, array, or callable, normal component value
"""
class NormalNeumannBC:
def __init__(self, value):
"""
Neumann condition for normal component only.
Parameters:
- value: float, str, array, or callable, normal derivative value
"""
class NormalMixedBC:
def __init__(self, value, const):
"""
Mixed condition for normal component only.
Parameters:
- value: float, coefficient for normal component
- const: float, constant term
"""
class NormalCurvatureBC:
def __init__(self, value):
"""
Curvature condition for normal component only.
Parameters:
- value: float, second derivative of normal component
"""Use mathematical expressions for inhomogeneous boundary conditions.
class ExpressionValueBC:
def __init__(self, expression, *, rank=0):
"""
Dirichlet condition with expression-based values.
Parameters:
- expression: str or callable, mathematical expression
- rank: int, tensor rank of the field
"""
def get_value(self, coordinates):
"""
Evaluate expression at coordinates.
Parameters:
- coordinates: array-like, boundary coordinates
Returns:
array-like: Expression values
"""
class ExpressionDerivativeBC:
def __init__(self, expression, *, rank=0):
"""
Neumann condition with expression-based derivatives.
Parameters:
- expression: str or callable, derivative expression
- rank: int, tensor rank of the field
"""
class ExpressionMixedBC:
def __init__(self, value_expr, const_expr, *, rank=0):
"""
Mixed condition with expression-based coefficients.
Parameters:
- value_expr: str or callable, coefficient expression
- const_expr: str or callable, constant expression
- rank: int, tensor rank of the field
"""Classes for organizing boundary conditions across grid axes.
class BoundariesList:
def __init__(self, boundaries):
"""
Initialize boundaries for all grid axes.
Parameters:
- boundaries: list or dict, boundary conditions per axis
"""
def __getitem__(self, axis):
"""Get boundary condition for specific axis"""
def copy(self):
"""
Create copy of boundary list.
Returns:
BoundariesList: Copy of boundaries
"""
def check_value_rank(self, rank):
"""
Check compatibility with field rank.
Parameters:
- rank: int, tensor rank to check
Raises:
ValueError: If incompatible
"""
class BoundaryPair:
def __init__(self, lower, upper):
"""
Pair of boundary conditions for opposite sides of an axis.
Parameters:
- lower: boundary condition for lower side
- upper: boundary condition for upper side
"""
@property
def lower(self):
"""Lower boundary condition"""
@property
def upper(self):
"""Upper boundary condition"""
class BoundaryPeriodic:
def __init__(self):
"""
Periodic boundary conditions for an axis.
"""
def check_value_rank(self, rank):
"""
Check compatibility with field rank.
Parameters:
- rank: int, tensor rank to check
"""
class BoundariesSetter:
def __init__(self, setter_func):
"""
Custom function for setting boundary conditions.
Parameters:
- setter_func: callable, function that sets boundary values
"""
def set_ghost_cells(self, data_full, *, args=None):
"""
Set ghost cell values using custom function.
Parameters:
- data_full: array, field data including ghost cells
- args: additional arguments for setter function
"""
def set_default_bc(bc):
"""
Set default boundary conditions for the package.
Parameters:
- bc: boundary condition specification
"""Functions for discovering available boundary condition types.
def registered_boundary_condition_classes():
"""
Get all registered boundary condition classes.
Returns:
dict: Mapping of names to boundary condition classes
"""
def registered_boundary_condition_names():
"""
Get names of all registered boundary conditions.
Returns:
list of str: Boundary condition names
"""import pde
# Create grid and field
grid = pde.CartesianGrid([[0, 10], [0, 5]], [64, 32])
field = pde.ScalarField.random_uniform(grid)
# Simple Dirichlet boundaries
bc_dirichlet = {"value": 1.0}
# Simple Neumann boundaries
bc_neumann = {"derivative": 0.0}
# Apply Laplacian with different boundary conditions
laplace_dirichlet = field.laplace(bc_dirichlet)
laplace_neumann = field.laplace(bc_neumann)
print("Boundary conditions applied successfully")import pde
grid = pde.CartesianGrid([[-1, 1], [0, 2]], [32, 16])
field = pde.ScalarField.random_uniform(grid)
# Different conditions for each axis
bc = {
"x": "periodic", # Periodic in x-direction
"y-": {"value": 0}, # Dirichlet at bottom
"y+": {"derivative": -1} # Neumann at top
}
result = field.laplace(bc)
print(f"Applied mixed boundary conditions")import pde
grid = pde.CartesianGrid([[0, 2*3.14159], [0, 1]], [64, 32])
field = pde.ScalarField.random_uniform(grid)
# Sinusoidal boundary conditions
bc = {
"x": "periodic",
"y-": {"value": "sin(x)"}, # Sin function at bottom
"y+": {"derivative": "cos(x)"} # Cosine derivative at top
}
result = field.laplace(bc)
print("Applied expression-based boundaries")import pde
grid = pde.UnitGrid([64], periodic=False)
field = pde.ScalarField.random_uniform(grid)
# Robin boundary condition: ∂ₙf + 2f = 5
bc = {
"left": {"type": "mixed", "value": 2, "const": 5},
"right": {"derivative": 0} # Neumann on right
}
result = field.laplace(bc)
print("Applied Robin boundary condition")import pde
def custom_bc_setter(data, args=None):
"""Custom boundary condition setter function"""
# Set left boundary to average of interior
data[0] = data[1:3].mean()
# Set right boundary to reflect interior
data[-1] = 2 * data[-2] - data[-3]
grid = pde.UnitGrid([64], periodic=False)
field = pde.ScalarField.random_uniform(grid)
# Use custom function directly
result = field.laplace(custom_bc_setter)
print("Applied custom boundary function")import pde
grid = pde.CartesianGrid([[-1, 1], [-1, 1]], [32, 32])
vector_field = pde.VectorField.random_uniform(grid)
# Normal component boundary conditions
bc_normal = {
"x": pde.NormalDirichletBC(0), # No-penetration
"y": pde.NormalNeumannBC(0) # Free-slip
}
# Apply to divergence calculation
div_result = vector_field.divergence(bc_normal)
print("Applied vector boundary conditions")import pde
# Mixed periodic/non-periodic grid
grid = pde.CartesianGrid([[0, 10], [0, 5]], [64, 32], periodic=[True, False])
field = pde.ScalarField.random_uniform(grid)
# Automatic boundary condition selection
bc_auto = "auto_periodic_neumann" # Periodic where grid is periodic,
# Neumann elsewhere
result = field.laplace(bc_auto)
print("Applied automatic boundary conditions")Install with Tessl CLI
npx tessl i tessl/pypi-py-pde