Lecture 6 (a)

Semi-discretization (Method of Lines)

Unstructured grids

  • Most problems have complex domains.

  • Boundary conditions crucial.

  • Little “structure” to problem.

  • What use is “structure” in the grid?

  • Use unstructured grids.

  • But how, whilst keeping accuracy?

An unstructued grid representing parts of the UK

Semi-discrete Methods

Take a “general” PDE

\[ \partial_t \phi = −\partial_x f(\phi) + \partial_x ( \kappa \partial_x \phi) = \mathcal{F}(\phi). \]

Use eg finite differences to approximate \(\mathcal{F} \to F\):

\[ \partial_t \phi_j = F(\phi_j) \simeq \frac{f_{i+1/2} - f_{i-1/2}}{\Delta x} + \dots \]

These are coupled ODEs. Solve using (eg) Runge-Kutta methods.

Example: FTBS

\[ \begin{aligned} \partial_t \phi_j &= -u \left. \left( \partial_x \phi \right) \right|_{x_j} \\ & \to -u \left( \phi_j - \phi_{j-1} \right) / \Delta x \, . \end{aligned} \]

def dphidt_bs(phi, dx, u=1):
    dphidt = np.zeros_like(phi)
    dphidt[:-1] = -u * (phi[:-1] - phi[1:]) / dx
    dphidt[-1] = dphidt[1] # Periodic, 1 ghost point
    return dphidt
def euler_step(phi_n, dphidt, dx, dt, u=1):
    return phi_n + dt * dphidt(phi_n, dx, u)
...
t=0
while t < t_end:
    t += dt
    phi_n = euler_step(phi_n, dphidt_bs, dx, dt)

Runge-Kutta

RK2:

\[ \begin{aligned} \symbf{\phi}^{[1]} &= \symbf{\phi}^{n} + \Delta t \, F ( \symbf{\phi}^n ) \, , \\ \symbf{\phi}^{n+1} &= \tfrac{1}{2} \left\{ \symbf{\phi}^{n} + \symbf{\phi}^{[1]} + \Delta t \, F ( \symbf{\phi}^{[1]} ) \right\} \, . \end{aligned} \]

from scipy.integrate import ode
def dphidt(t, phi):
    ...
r = ode(dphidt).set_integrator('dopri5', max_step=dt)
r.set_initial_value(...)
while t < t_end:
    r.integrate(r.t + dt)

Summary

  • Semi-discretization simplifies constructing complex schemes.
  • Runge-Kutta methods are a standard approach
  • Libraries are an efficient starting point.