The PDE Definition Interface
PDE discretization packages bridge high-level equation descriptions to the solver-ready problems used throughout the SciML ecosystem. The shared interface is based on dispatch: a package extends discretize for each supported pair of PDE representation and discretizer, and may also extend symbolic_discretize to expose the intermediate representation.
SciMLBase does not prescribe one PDE equation language, domain type, boundary condition syntax, or spatial discretization. Those semantics belong to the packages that own the high-level representation and discretizer. This keeps the result of discretization compatible with ordinary ODE, nonlinear, optimization, linear, and other SciML solvers without requiring those solvers to understand PDE-specific syntax.
Core Extension Contract
A discretizer package implements:
SciMLBase.discretize(sys, discretizer, args...; kwargs...)for each supported sys and discretizer pair. The method must return a solver-ready SciML problem, such as an ODEProblem, NonlinearProblem, or OptimizationProblem, or another documented problem type accepted by the intended solver. It should forward relevant problem-construction keyword arguments, validate unsupported equations, domains, and boundary conditions, and preserve enough metadata to reconstruct the PDE solution.
AbstractDiscretization is an optional common marker for discretizer algorithms. Implementing the interface does not require subtyping it: a package may own a more specific public algorithm hierarchy and still participate by extending SciMLBase.discretize.
A package may additionally implement:
SciMLBase.symbolic_discretize(sys, discretizer, args...; kwargs...)The return type is part of the discretizer's public contract. It may be a lowered symbolic system, a tuple containing a system and time span, a collection of generated operators, or a diagnostic representation such as loss functions. It need not be a ModelingToolkit AbstractSystem, but it should describe the same discretization used by discretize and retain the information needed for inspection or downstream transformations.
PDE Representations
SciMLBase defines AbstractPDEProblem and the lightweight PDEProblem wrapper. PDEProblem stores a package-specific PDE representation together with extrapolation and spatial metadata; SciMLBase does not interpret those fields.
High-level packages may instead define their own representation and dispatch directly on it. For example, ModelingToolkit owns PDESystem, including its equations, independent and dependent variables, parameters, domains, and boundary or initial conditions. A downstream discretizer should document which representation types it accepts rather than assuming every PDE enters through PDEProblem.
SciMLBase.PDEProblem — Type
struct PDEProblem{P, E, S} <: SciMLBase.AbstractPDEProblemConcrete wrapper for PDE problems before discretization.
PDEProblem stores a symbolic or package-specific PDE problem object together with extrapolation and spatial-domain metadata used by discretization backends. SciMLBase owns only this lightweight wrapper; concrete PDE semantics and the conversion to ODE, nonlinear, optimization, or linear problems are supplied by downstream discretization packages through discretize and symbolic_discretize.
Fields
prob::Anyextrapolation::Anyspace::Any
Domains and Boundary Conditions
Domain and boundary-condition syntax is owned by the high-level PDE and discretizer packages. SciMLBase does not require a universal interval, mesh, geometry, or boundary-condition type. A discretizer's public interface should document:
- supported domain dimensions, geometries, coordinate systems, and grid or sampling specifications;
- supported initial, Dirichlet, Neumann, Robin, periodic, interface, and other boundary-condition classes;
- how conditions are validated, eliminated, embedded, or transformed; and
- restrictions imposed by the selected discretization, including required regularity, compatible derivative orders, and unsupported combinations.
Invalid or unsupported input should produce an actionable error before the generated numerical problem is passed to a solver.
Discretization Functions
SciMLBase.discretize — Function
discretize(sys, discretizer, args...; kwargs...)Transform a symbolic or high-level problem description into a solver-ready problem.
Discretizer packages implement SciMLBase.discretize for the system/problem types and discretization algorithms they own. A method should return an AbstractSciMLProblem or another documented problem type accepted by the intended solver. Implementations should document the accepted input system type, the meaning of discretizer, the generated problem family, forwarded problem-construction keywords, and any metadata needed to map numerical solutions back to the original variables and domains.
Use symbolic_discretize when the caller needs a diagnostic or symbolic view of the discretized system rather than the solver-ready problem.
SciMLBase.symbolic_discretize — Function
symbolic_discretize(sys, discretizer, args...; kwargs...)Return a symbolic or diagnostic representation of a discretization.
Discretizer packages implement SciMLBase.symbolic_discretize when they can expose lowered equations, operators, grids, boundary-condition handling, or other intermediate artifacts without constructing only the final solver-ready problem. The result should correspond to the same mathematical discretization used by discretize, but may preserve additional information useful for inspection, debugging, code generation, or downstream transformations. Its type is package-defined and need not subtype a symbolic-system abstraction.
Discretization Metadata and Solution Wrapping
Discretizers that return PDE-aware solutions can subtype AbstractDiscretizationMetadata. Use AbstractDiscretizationMetadata{Val(true)} when the generated solution has a saved time axis and AbstractDiscretizationMetadata{Val(false)} when it does not. wrap_sol(sol, metadata) routes these to PDETimeSeriesSolution(sol, metadata) and PDENoTimeSolution(sol, metadata), respectively.
The package that owns the metadata must define the corresponding outer solution constructor. Its metadata should retain the original variables and domains, the layout of generated state variables, and any grids, transformations, or interpolants needed to map the solver output back to the PDE representation. If the wrapper is callable, metadata-specific methods should define the supported evaluation coordinates, interpolation behavior, and extrapolation behavior.
SciMLBase.PDETimeSeriesSolution — Type
struct PDETimeSeriesSolution{T, N, uType, Disc, Sol, DType, tType, domType, ivType, dvType, P, A, IType, S} <: SciMLBase.AbstractPDETimeSeriesSolution{T, N, uType, Disc}Solution to a PDE, solved from an ODEProblem generated by a discretizer.
PDETimeSeriesSolution is the concrete wrapper for time-dependent PDE discretizations whose metadata subtypes AbstractDiscretizationMetadata{Val(true)}. Discretizer packages usually define an outer constructor SciMLBase.PDETimeSeriesSolution(sol, metadata::D) for their metadata type D; the generic wrap_sol dispatch calls that constructor after the underlying ODE or time-dependent solve has finished.
Fields
u: the solution to the PDE, as a dictionary of symbols to Arrays of values. The Arrays are of the same shape as the domain of the PDE. Time is always the first axis.original_sol: The original ODESolution that was used to generate this solution.t: the time points corresponding to the saved values of the ODE solution.ivdomain: The full list of domains for the independent variables. May be a grid for a discrete solution, or a vector/tuple of tuples for a continuous solution.ivs: The list of independent variables for the solution.dvs: The list of dependent variables for the solution.disc_data: Metadata about the discretization process and type.prob: The ODEProblem that was used to generate this solution.alg: The algorithm used to solve the ODEProblem.interp: Interpolations for the solution.retcode: the return code from the solver. Used to determine whether the solver solved successfully, whether it terminated early due to a user-defined callback, or whether it exited due to an error. For more details, see the return code documentation.stats: statistics of the solver, such as the number of function evaluations required.
SciMLBase.PDENoTimeSolution — Type
struct PDENoTimeSolution{T, N, uType, Disc, Sol, domType, ivType, dvType, P, A, IType, S} <: SciMLBase.AbstractPDENoTimeSolution{T, N, uType, Disc}Solution to a PDE, solved from a NonlinearProblem generated by a discretizer.
PDENoTimeSolution is the concrete wrapper for time-independent PDE discretizations whose metadata subtypes AbstractDiscretizationMetadata{Val(false)}. Discretizer packages usually define an outer constructor SciMLBase.PDENoTimeSolution(sol, metadata::D) for their metadata type D; the generic wrap_sol dispatch calls that constructor after the underlying nonlinear, linear, optimization, or stationary solve has finished.
Fields
u: the solution to the PDE, as a dictionary of symbols to Arrays of values. The Arrays are of the same shape as the domain of the PDE. Time is always the first axis.original_sol: The original NonlinearSolution that was used to generate this solution.ivdomain: The full list of domains for the independent variables. May be a grid for a discrete solution, or a vector/tuple of tuples for a continuous solution.ivs: The list of independent variables for the solution.dvs: The list of dependent variables for the solution.disc_data: Metadata about the discretization process and type.prob: The NonlinearProblem that was used to generate this solution.alg: The algorithm used to solve the NonlinearProblem.interp: Interpolations for the solution.retcode: The return code from the solver. Used to determine whether the solver solved successfully (sol.retcode === ReturnCode.Success), whether it terminated due to a user-defined callback (sol.retcode === ReturnCode.Terminated), or whether it exited due to an error. For more details, see the return code section of the ODEProblem.jl documentation.
SciMLBase.wrap_sol — Function
wrap_sol(sol)
wrap_sol(sol, problem_type_or_metadata)Return sol or wrap it in a higher-level SciML solution container.
Solvers call wrap_sol(sol) after constructing a low-level solution. When sol.prob is an AbstractSciMLProblem, the default implementation queries problem_type and dispatches to wrap_sol(sol, problem_type_or_metadata) when the result is not nothing. Problem-family packages extend the two-argument form when a generated solver solution should be returned as a more specific public solution type.
The fallback two-argument method returns sol unchanged. PDE discretizer packages extend the metadata path by defining constructors such as PDETimeSeriesSolution(sol, metadata::D) or PDENoTimeSolution(sol, metadata::D) for their concrete discretization metadata type.
wrap_sol(sol, metadata::AbstractDiscretizationMetadata)Wrap a solver solution produced by a PDE discretizer in the appropriate PDE solution type.
Metadata with parameter Val(true) is routed to PDETimeSeriesSolution(sol, metadata). Metadata with parameter Val(false) is routed to PDENoTimeSolution(sol, metadata). Discretizer packages are responsible for implementing those outer constructors for their concrete metadata types and for filling the wrapper fields from the discretized solve.
Transformations and Analysis
Equation simplification, index reduction, domain decomposition, coordinate transformations, sparsity analysis, and operator construction belong to the packages that own the PDE representation or discretizer. When such a transformation changes variables or state layout, the discretizer must preserve the map needed for solution reconstruction. symbolic_discretize is the common inspection hook for exposing the lowered equations, operators, grids, loss functions, or other package-defined intermediate data.
Downstream Patterns
MethodOfLines.jl extends the interface for MOLFiniteDifference. Its symbolic path returns a semi-discrete system and time span; its solver-ready path constructs an ODEProblem for time-dependent systems or a NonlinearProblem for stationary systems. Its metadata records the discrete space and maps the numerical solution back to the original PDE variables and grids.
NeuralPDE.jl extends the interface for PhysicsInformedNN. Its symbolic path returns a representation containing the generated loss functions and parameters, while discretize constructs an OptimizationProblem. This demonstrates why symbolic_discretize has a package-defined return type and why the shared contract is dispatch-based rather than tied to a single discretizer hierarchy.