Source code for irksome.dirk_imex_tableaux
from .ButcherTableaux import ButcherTableau
import numpy as np
[docs]
class DIRK_IMEX(ButcherTableau):
"""Top-level class representing a pair of Butcher tableau encoding an implicit-explicit
additive Runge-Kutta method. Since the explicit Butcher matrix is strictly lower triangular,
only the lower-left (ns - 1)x(ns - 1) block is given. However, the full b_hat and c_hat are
given. It has members
:arg A: a 2d array containing the implicit Butcher matrix
:arg b: a 1d array giving weights assigned to each implicit stage when
computing the solution at time n+1.
:arg c: a 1d array containing weights at which time-dependent
implicit terms are evaluated.
:arg A_hat: a 2d array containing the explicit Butcher matrix (lower-left block only)
:arg b_hat: a 1d array giving weights assigned to each explicit stage when
computing the solution at time n+1.
:arg c_hat: a 1d array containing weights at which time-dependent
explicit terms are evaluated.
:arg order: the (integer) formal order of accuracy of the method
"""
def __init__(self, A: np.ndarray, b: np.ndarray, c: np.ndarray, A_hat: np.ndarray,
b_hat: np.ndarray, c_hat: np.ndarray, order: int = None):
# Number of stages
ns = A.shape[0]
assert ns == A.shape[1], "A must be square"
assert A_hat.shape == (ns - 1, ns - 1), "A_hat must have one fewer row and column than A"
assert ns == len(b) == len(b_hat), \
"b and b_hat must have the same length as the number of stages"
assert ns == len(c) == len(c_hat), \
"c and c_hat must have the same length as the number of stages"
super().__init__(A, b, None, c, order, None, None)
self.A_hat = self._pad_matrix(A_hat, "ll")
self.b_hat = b_hat
self.c_hat = c_hat
self.is_dirk_imex = True # Mark this as a DIRK-IMEX scheme
@staticmethod
def _pad_matrix(mat: np.ndarray, loc: str):
"""Zero pads a matrix"""
n = mat.shape[0]
assert n == mat.shape[1], "Matrix must be square"
padded = np.zeros((n+1, n+1), dtype=mat.dtype)
if loc == "ll":
# Lower left corner
padded[1:, :-1] = mat
elif loc == "lr":
# Lower right corner
padded[1:, 1:] = mat
else:
raise ValueError("Location must be ll (lower left) or lr (lower right)")
return padded