Source code for irksome.tableaux.multistep_tableaux

import FIAT
import numpy as np
from ..tools import get_lagrange_permutation


[docs] class MultistepTableau(object): """Top-level class representing a tableau encoding a multistep method. It has members :arg a: a 1d array containing the coefficients of the previous steps :arg b: a 1d array containing the weights of the right hand side of the method """ def __init__(self, a, b): self.a = a self.b = b @property def num_total_steps(self): """Return the number of steps the method has.""" return len(self.b) @property def num_prev_steps(self): """Return the number of previous steps the method requires.""" return len(self.b) - 1 @property def is_explicit(self): return np.abs(self.b[-1]) < 1e-10 @property def is_implicit(self): return not self.is_explicit
[docs] class BDF(MultistepTableau): def __init__(self, order): a, b = get_weights_BDF(order) super().__init__(a, b)
[docs] class AdamsMoulton(MultistepTableau): def __init__(self, order): a, b = get_weights_AM(order) super().__init__(a, b)
[docs] class AdamsBashforth(MultistepTableau): def __init__(self, order): a, b = get_weights_AB(order) super().__init__(a, b)
def get_weights_BDF(order): if order < 1 or order > 6: raise ValueError("BDF only valid for orders 1 through 6") uint = FIAT.ufc_simplex(1) L = FIAT.Lagrange(uint, order, variant="equispaced") _, perm = get_lagrange_permutation(L) vals = L.tabulate(1, (1.,))[1, ][perm] beta = vals[-1] a = vals / beta b = np.zeros(order+1) b[-1] = order / beta return a, b def get_weights_AB(order): assert order > 0 uint = FIAT.ufc_simplex(1) nodes = [-i for i in range(order)] nodes.reverse() nodes = np.reshape(nodes, (-1, 1)) Q = FIAT.make_quadrature(uint, 2*order) qpts = Q.get_points() qwts = Q.get_weights() L = FIAT.barycentric_interpolation.LagrangePolynomialSet(uint, nodes) vals = L.tabulate(qpts, 0)[(0,)] b = np.dot(vals, qwts) b = np.insert(b, order, 0) a = np.zeros(order + 1) a[-1] = 1.0 a[-2] = -1.0 return a, b def get_weights_AM(order): assert order >= 0 if order == 0: return np.array([-1.0, 1.0]), np.array([0.0, 1.0]) uint = FIAT.ufc_simplex(1) nodes = [1-i for i in range(order+1)] nodes.reverse() nodes = np.reshape(nodes, (-1, 1)) Q = FIAT.make_quadrature(uint, 2*order) qpts = Q.get_points() qwts = Q.get_weights() L = FIAT.barycentric_interpolation.LagrangePolynomialSet(uint, nodes) vals = L.tabulate(qpts, 0)[(0,)] b = np.dot(vals, qwts) a = np.zeros(order + 1) a[-1] = 1.0 a[-2] = -1.0 return a, b