SciML / DifferentialEquations.jl

Multi-language suite for high-performance solvers of differential equations and scientific machine learning (SciML) components. Ordinary differential equations (ODEs), stochastic differential equations (SDEs), delay differential equations (DDEs), differential-algebraic equations (DAEs), and more in Julia.
https://docs.sciml.ai/DiffEqDocs/stable/
Other
2.8k stars 222 forks source link

DiffEq's PDE Story 2nd Try: Domains, BCs, Operators, and Problems #260

Closed ChrisRackauckas closed 5 years ago

ChrisRackauckas commented 6 years ago

DiffEq's first PDE attempt (which started the package) was a failure. The issue was that it was tied directly to an FEM subpackage I made internally, but then it couldn't scale to all of the problems it needed to face. The rest of DiffEq was then built up around decentralization. The core idea is that if you separate the data that specifies a problem and leave the solver support to dispatch, many different approaches and packages can step in to offer unique (and fast) ways to solve the problems. That has worked splendidly, so the FEM support was dropped in DiffEq 4.0 since it didn't conform to this.

What I want to return with is a PDE story worthy of the rest of DiffEq. So the goals it needs to meet is:

  1. It should specify problems in a manner that is distinct from implementation. But,
  2. It should hold the information required for algorithms to be fully optimized with their unique features.
  3. All of the components to "do it yourself" as a toolbox should be exposed. And
  4. It should interface with many different approaches and packages. But,
  5. There should be high-level automation to make the standard cases easy and efficient for "most users".

Here is a prototype for a design that could hopefully handle this.

General Flow: Heat Equation FDM

Let's talk about the Heat Equation. First we start with a domain type. Domain types are specified by types <:AbstractDomain. For example,

domain = RegularGrid((0,5),dx)

is a regular grid of [0,5] with spacing dx. But now we have to start talking about boundaries. It's the domain that knows what boundaries it has, and thus what has to be specified. So to the domain we need to add boundary functions.

Boundary conditions are specified by types <:AbstractBoundaryCondition. So we could have:

lbc = Dirichlet(0)
rbc = Neumann(g(t,x))

Now we'd package that together:

space = Space(domain,lbc,rbc)

Those domains are compatible with those boundary conditions, so it works without error. Once we have a space, our Heat Equation is specified via:

u' = D(t,x,u)*A*u + f(t,x,u)

so we specify:

tspan = (0,15)
prob = HeatProblem(D,f,space,tspan)

This is just a bundle of information that describes what we want to solve. But how do we want to solve it? We need to do a call that converts it into something with usable operators. Let's do it method of lines via a conversion call:

ode_prob = ODEProblem(prob,FiniteDifference())

where FiniteDifference dispatches this conversion to DiffEqOperators.jl with default order. FiniteDifference(order=4) can set the spatial discretization order, or we can choose other packages with adaptive space operators etc. This we can take to the ODE solver and solve.

Details

Now let's talk about details.

Domains

Domains are a specification of the domain to solve on. The basic ones will be provided by DiffEqPDEBase.jl. Wrapper libraries such as DiffEqApproxFun.jl or FEniCS.jl could provide extras, like SpectralGrid or FEMMesh. It can be as lean as possible, though in some cases like FEM it will need to hold node/mesh pairings.

Boundary Conditions

These are defined in DiffEqPDEBase.jl and have the minimal information describing a specific kind of boundary condition. Either holding constants, arrays, or functions, they just encapsulate the idea of the BC choice.

Space

Space is how domains and BCs come together. For a given domain, it will make sure the BCs are compatible with the domain. Can this be merged with Domains?

Operators

This part wasn't shown in the simple example. One we have a space, that is enough information to define operators. The high level interface is something like

DerivativeOperator(space,alg,derivative_order,approximation_order)

etc, and then via alg it dispatches to the appropriate package to spit out DiffEqOperators (this stuff is already defined) appropriate for that space. So like DiffEqOperators would just need to be changed to implement that dispatch.

Problems

Problems are just an abstraction over operators which basically knows what operators it should be building given the space, alg, and problem. They don't do anything until the conversion call, in which case they build these operators to then build something to solve.

Conversions

The obvious conversions are to ODE/SDE/DAE/DDEProblems and keep on going. We need two more problem types though. LinearProblem and NonlinearProblem. Then we cover it all. Everything becomes instantiates operators through some conversion.

High-Level Conversions

Then there can also be some standard conversions like DiffusionAdvection(prob,space,tspan) where prob=SDEProblem. This is just high level sugar to make everything boil down to conversions on PDE problems to then give linear, nonlinear, or diffeqs out in the end.

Big Questions

Documentation

I've learned by now to plan documentation levels at the same time as the interface. Where are things documented? I think the general workflow is documented, and then boundary conditions are documented generally, some general domains, the operator calls, and problems are all documented package-wide generic. Then unique domains, space, operator algorithms, and conversions are documented per-package. DiffEqOperators describes no unique domains, it describes what BCs it can support, choices for operator construction, and problem conversions it can perform. DiffEqApproxFun links over to ApproxFun for choices of domains, has a single Spectral() for generating the spectral operators (with choices in there), and then can generate ODEs for the Heat Equation, or a fully implicit discretization to a LinearProblem via a 2D discretization (can it?).

Representation Information?

When you get this ODEProblem... what does it actually represent? We need a way to describe back to the user what u0 means. Coefficients of ...? u0[i,j,k] means what (x,y,z)? Not sure how to handle this.

Time?

Time is kept separate because it usually acts differently when it exists. For algorithms like a fully implicit discretization, LinearProblem(prob,FullyFiniteDifference(dt)) or something.

Passing space

This is just minor bikeshedding, but instead of like making the Heat Equation require the user give f(u,p,t,x,y,z) for 3D, should it be f(u,p,t,x) for x a tuple/number? That keeps it the same regardless of dimension. Minor bikeshedding.

Conclusion

This allows us to specify our problem at a high level, interface with different packages in an extendable way to generate appropriate FDM/FVM/FEM/spectral discretizations, and spit out linear/nonlinear/diffeq problems to take to solvers. The hope is that this give enough places to inject information and package-specific components that it can be efficient, yet gives a good level of automation and transferrability to other setups.

Thanks. Pulling in some people to bikeshed this high level story. @dextorious @dlfivefifty @alanedelman @jlperla

ChrisRackauckas commented 5 years ago

I don't think so, but why would be looking at an explicit solver for a problem with nonlinear constraints? Seems like it would be natural to use a discretization to a DAE.

ranocha commented 5 years ago

For nonlinear conservation laws, useful boundary conditions are often nonlinear. Nevertheless, they can be solved using spatial semidiscretisations such as finite volume or finite difference methods and explicit Runge-Kutta schemes.

jlperla commented 5 years ago

In economics there are lots of nonlinear problems (some of which you saw in https://github.com/JuliaDiffEq/PDERoadmap/issues/22 post) but... I am not sure that this is possible to solve in general, and it is usually the interior themselves that are nonlinear rather than the boundaries.

Many of the approaches to those use an iterative apporach where you define a linear differential equation, solve it, change the parameters, repeat. Of course, you could also define these as generating nonlinear systems of equations instead... but I think we should wait on that sort of generality. When Capstan.jl is mature and reverse-mode works well, the "bigass nonlinear system" approach might work better. So, my feeling is that this library should stay focused on affine and linear operators and boundaries, and that the fully nonlinear stuff should wait until this works.

As an aside note, one of the first nonlinear problems I need to solve are differential quasi-variational inequalities, that is, writing down the stationary problem to solve for u(x) for given functions b(x) and S(x) and a differential operator A:

max( r u(x) - b(x) - A u(x), u(x) - S(x)) = 0

This isn't a linear problem, but it is a linear-complementarity problem when discretized. That is max(C u - b, u - S) = 0 for C = r I - A discretization, and everything else vectors on the spatial discretization.

ChrisRackauckas commented 5 years ago

This issue is on DifferentialEquations.jl, not DiffEqOperators.jl. There was never a plan to limit it to affine boundary conditions.

jlperla commented 5 years ago

My mistake, I was confused. I don't have much to add on a general interface, as problems in economics tend to be of a very particular set of sub-types. What I will say, though, from my limited knowledge is that I think it may be too ambitious to try to come up with design for arbitrary PDEs at this point, since the methods for solving them are so radically different. Having a shared set of types/interfaces/etc. for common things (e.g. domains, grids, spaces, etc.) is a different question. If ApproxFun, DiffEqOperators, etc. share those things, then it is a step forward.

ChrisRackauckas commented 5 years ago

I think it may be too ambitious to try to come up with design for arbitrary PDEs at this point, since the methods for solving them are so radically different.

Solving and specification are two completely different things. We don't have to commit to solve every representable PDE, just have a language to specify what problem to solve. What I already showed in the slides can do that if you allow the AbstractDomain to be something that can be package defined as well, so it's not very ambitious.

ChrisRackauckas commented 5 years ago

Supersceded by being partially done, and the higher level part is https://github.com/JuliaDiffEq/DifferentialEquations.jl/issues/469