Documentation Index
Fetch the complete documentation index at: https://mintlify.com/DedalusProject/dedalus/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The problems module provides classes for defining different types of PDE problems: initial value problems (IVPs), linear boundary value problems (LBVPs), nonlinear boundary value problems (NLBVPs), and eigenvalue problems (EVPs).
Problem Types
InitialValueProblem (IVP)
InitialValueProblem(variables, time='t', namespace=None)
Initial value problems of the form: M·dt(X) + L·X = F(X, t)
Parameters
- variables (list of Fields): Problem variables to solve for
- time (str or Field, optional): Time variable name or field (default: ‘t’)
- namespace (dict, optional): Namespace for parsing equations (recommended: locals())
Constraints
- LHS must be linear in variables
- LHS must be time-independent
- LHS must be first-order in time derivatives
- RHS must not contain time derivatives
Methods
add_equation(equation, condition=“True”) - Add equation to problem
problem.add_equation("dt(u) - ν*lap(u) = -u@grad(u)")
build_solver(timestepper) - Create solver
solver = problem.build_solver(d3.RK222)
build_EVP(eigenvalue, backgrounds, perturbations) - Convert to EVP
Example: Heat Equation
import dedalus.public as d3
import numpy as np
# Setup
coord = d3.Coordinate('x')
dist = d3.Distributor(coord)
xbasis = d3.ChebyshevT(coord, size=64, bounds=(0, 1))
# Fields
u = dist.Field(bases=xbasis, name='u')
τ1 = dist.Field(name='τ1')
τ2 = dist.Field(name='τ2')
# Problem
ν = 0.01
problem = d3.IVP([u, τ1, τ2], namespace=locals())
problem.add_equation("dt(u) - ν*dx(dx(u)) + lift(τ1,-1) + lift(τ2,+1) = 0")
problem.add_equation("u(x='left') = 0")
problem.add_equation("u(x='right') = 0")
# Solve
solver = problem.build_solver(d3.RK222)
solver.stop_sim_time = 10.0
while solver.proceed:
solver.step(dt)
Example: Navier-Stokes
import dedalus.public as d3
import numpy as np
# Setup 2D periodic box
coords = d3.CartesianCoordinates('x', 'y')
dist = d3.Distributor(coords)
xbasis = d3.RealFourier(coords['x'], size=256, bounds=(0, 2*np.pi))
ybasis = d3.RealFourier(coords['y'], size=256, bounds=(0, 2*np.pi))
# Fields
u = dist.VectorField(coords, bases=(xbasis, ybasis), name='u')
p = dist.Field(bases=(xbasis, ybasis), name='p')
# Problem
ν = 1e-4
problem = d3.IVP([u, p], namespace=locals())
problem.add_equation("dt(u) + grad(p) - ν*lap(u) = -u@grad(u)")
problem.add_equation("div(u) = 0")
# Timestepping
solver = problem.build_solver(d3.RK443)
LinearBoundaryValueProblem (LBVP)
LinearBoundaryValueProblem(variables, namespace=None)
Linear boundary value problems: L·X = F
Parameters
- variables (list of Fields): Problem variables
- namespace (dict, optional): Namespace for parsing
Constraints
- LHS must be linear in variables
- RHS must be independent of variables
Methods
add_equation(equation, condition) - Add equation
build_solver() - Create solver
Example: Poisson Equation
import dedalus.public as d3
import numpy as np
# Setup
coord = d3.Coordinate('x')
dist = d3.Distributor(coord)
xbasis = d3.ChebyshevT(coord, size=128, bounds=(0, 1))
# Fields
u = dist.Field(bases=xbasis, name='u')
τ1 = dist.Field(name='τ1')
τ2 = dist.Field(name='τ2')
f = dist.Field(bases=xbasis, name='f')
# Source term
x = dist.local_grid(xbasis)
f['g'] = -np.sin(2*np.pi*x)
# Problem
problem = d3.LBVP([u, τ1, τ2], namespace=locals())
problem.add_equation("dx(dx(u)) + lift(τ1,-1) + lift(τ2,+1) = f")
problem.add_equation("u(x='left') = 0")
problem.add_equation("u(x='right') = 0")
# Solve
solver = problem.build_solver()
solver.solve()
NonlinearBoundaryValueProblem (NLBVP)
NonlinearBoundaryValueProblem(variables, namespace=None)
Nonlinear boundary value problems: G(X) - H(X) = 0
Solved using Newton-Kantorovich iteration.
Methods
add_equation(equation, condition) - Add equation
build_solver() - Create solver
Example
import dedalus.public as d3
# Fields
u = dist.Field(bases=xbasis, name='u')
τ1 = dist.Field(name='τ1')
τ2 = dist.Field(name='τ2')
# Nonlinear problem
ε = 0.1
problem = d3.NLBVP([u, τ1, τ2], namespace=locals())
problem.add_equation("dx(dx(u)) + ε*u**3 + lift(τ1,-1) + lift(τ2,+1) = 0")
problem.add_equation("u(x='left') = 0")
problem.add_equation("u(x='right') = 1")
# Solve with Newton iteration
solver = problem.build_solver()
pert_norm = np.inf
while pert_norm > 1e-10:
solver.newton_iteration()
pert_norm = sum(pert.allreduce_data_norm('c', 2) for pert in solver.perturbations)
EigenvalueProblem (EVP)
EigenvalueProblem(variables, eigenvalue, namespace=None)
Linear eigenvalue problems: λ·M·X + L·X = 0
Parameters
- variables (list of Fields): Eigenvector fields
- eigenvalue (Field): Eigenvalue field
- namespace (dict, optional): Namespace
Constraints
- LHS must be linear in variables
- LHS must be affine in eigenvalue
- RHS must be zero
Methods
add_equation(equation, condition) - Add equation
build_solver() - Create EVP solver
Example: Orr-Sommerfeld
import dedalus.public as d3
import numpy as np
# Setup
coord = d3.Coordinate('z')
dist = d3.Distributor(coord)
zbasis = d3.ChebyshevT(coord, size=128, bounds=(-1, 1))
# Fields
v = dist.Field(bases=zbasis, name='v')
η = dist.Field(bases=zbasis, name='η')
λ = dist.Field(name='λ')
# Base flow
U = dist.Field(bases=zbasis)
z = dist.local_grid(zbasis)
U['g'] = 1 - z**2 # Poiseuille flow
# Parameters
Re = 5000
k = 1.0 # Wavenumber
# Orr-Sommerfeld equation
problem = d3.EVP([v, η], eigenvalue=λ, namespace=locals())
problem.add_equation("λ*(dz(dz(v)) - k**2*v) + 1j*k*U*(dz(dz(v)) - k**2*v) - 1j*k*dz(dz(U))*v - (1/Re)*(dz(dz(dz(dz(v)))) - 2*k**2*dz(dz(v)) + k**4*v) + lift(η,-1) = 0")
problem.add_equation("v(z=-1) = 0")
problem.add_equation("v(z=+1) = 0")
# Solve EVP
solver = problem.build_solver()
subproblem = solver.subproblems_by_group[(0,)]
solver.solve_dense(subproblem)
# Extract eigenvalues
λ_vals = solver.eigenvalues
Aliases
IVP = InitialValueProblem
LBVP = LinearBoundaryValueProblem
NLBVP = NonlinearBoundaryValueProblem
EVP = EigenvalueProblem
Equation Parsing
Equations can be specified as:
-
Strings (parsed using namespace):
problem.add_equation("dt(u) - ν*lap(u) = 0")
-
Expression tuples:
problem.add_equation((d3.dt(u) - ν*d3.lap(u), 0))
See Also