Time-Dependent PDEs
Method of Lines solver for time-dependent PDEs.
Solves initial-boundary value problems of the form u_t = L(u) + s(t), or u_tt = L(u) + s(t) for problems of second order in time (e.g. the wave equation), where L is a spatial differential operator (Expression) and s an optional source term.
- class findiff.ivp.MOLSolution(t, u, v=None)
Container for time-dependent PDE solutions.
Returned by
TimeDependentPDE.solve()whenstore_everyis set.Attributes
- tndarray, shape (nt_stored,)
Time points at which the solution is stored.
- undarray, shape (nt_stored, *spatial_shape)
Solution snapshots.
u[i]is the solution at timet[i].- vndarray or None
Snapshots of the time derivative \(u_t\) for problems of second order in time, otherwise None.
- property final
Solution at the final time.
- class findiff.ivp.TimeDependentPDE(lhs, u0, bcs, t, source=None, v0=None)
Solve a time-dependent PDE using the Method of Lines.
Solves problems of the form
\[\frac{\partial u}{\partial t} = L(u) + s(t)\]or, if the initial velocity
v0is given, problems of second order in time such as the wave equation,\[\frac{\partial^2 u}{\partial t^2} = L(u) + s(t)\]where L is a spatial differential operator built with findiff and s an optional source term.
Parameters
- lhsExpression
The spatial differential operator L.
- u0ndarray
Initial condition array with the spatial grid shape.
- bcsBoundaryConditions
Spatial boundary conditions applied at each time step. Boundary values may be callables
g(t)for time-dependent conditions.- t1D ndarray
Time points.
t[0]is the initial time.- sourcendarray, callable or None
Optional source term s: an array (constant in time, broadcastable to the grid shape) or a callable
s(t)returning such an array.- v0ndarray or None
Initial velocity \(u_t(t_0)\). If given, the problem is of second order in time.
Examples
1D heat equation \(u_t = D\, u_{xx}\):
>>> import numpy as np >>> from findiff import Diff, BoundaryConditions >>> from findiff.ivp import TimeDependentPDE >>> nx = 51 >>> x = np.linspace(0, 1, nx) >>> dx = x[1] - x[0] >>> L = 0.01 * Diff(0, dx)**2 >>> u0 = np.sin(np.pi * x) >>> bc = BoundaryConditions((nx,)) >>> bc[0] = 0 >>> bc[-1] = 0 >>> t = np.linspace(0, 0.1, 100) >>> u_final = TimeDependentPDE(L, u0, bc, t).solve() >>> u_final.shape (51,)
- solve(method='crank-nicolson', solver=None, store_every=None, callback=None, **solver_options)
Advance the solution in time.
Parameters
- methodstr
Time integration method:
'forward-euler': explicit first-order.'rk4': explicit fourth-order Runge-Kutta.'backward-euler': implicit first-order.'crank-nicolson': implicit second-order (default).'verlet': explicit second-order Stoermer-Verlet, only for problems of second order in time (v0given).
For problems of second order in time,
'forward-euler'is not available (it is unstable for undamped waves); the other methods are applied to the equivalent first-order system.- solverstr, callable, or None
Linear solver for implicit methods. Same interface as
PDE.solve(). Ignored for explicit methods.- store_everyint or None
If
None(default), return only the final solution as an ndarray. If an integer N, store every N-th time step and return aMOLSolution.store_every=1stores all steps.- callbackcallable or None
Called as
callback(step, t_i, u_i)after each time step. ReturnFalseto stop early.- **solver_options
Passed to the linear solver (
rtol,maxiter,preconditioner, etc.).
Returns
- ndarray
Final solution (when
store_everyisNone).- MOLSolution
Solution container (when
store_everyis set). For problems of second order in time it also holds the velocitiesv.