Source code for irksome.scheme
from FIAT import ufc_simplex, create_quadrature
from FIAT.quadrature import RadauQuadratureLineRule, GaussLobattoLegendreQuadratureLineRule
ufc_line = ufc_simplex(1)
[docs]
class GalerkinScheme:
"""
Base class for describing Galerkin-in-time methods in lieu of
a Butcher tableau.
:arg order: An integer indicating the order of the method
:kwarg basis_type: A string (or tuple of strings) indicating the finite
element family (either `'Lagrange'` or `'Bernstein'`) or the
Lagrange variant (either `'equispaced'`, `'spectral'`, `'chebyshev'`,
or `'integral'`) for the test/trial spaces.
Defaults to equispaced Lagrange elements.
:kwarg quadrature_degree: An integer indicating the degree of the
quadrature to be use in time. Defaults to the sum
of the degrees of the trial and test spaces.
:kwarg quadrature_scheme: A string indicating the quadrature scheme
to be used in time. Defaults to Gauss-Legendre.
"""
def __init__(self, order,
basis_type=None,
quadrature_degree=None,
quadrature_scheme=None):
self.order = order
self.basis_type = basis_type
self.quadrature_degree = quadrature_degree
self.quadrature_scheme = quadrature_scheme
[docs]
class DiscontinuousGalerkinScheme(GalerkinScheme):
"""Class for describing DG-in-time methods"""
def __init__(self, order,
basis_type=None,
quadrature_degree=None,
quadrature_scheme=None):
assert order >= 0, f"{type(self).__name__} must have order >= 0"
super().__init__(order, basis_type=basis_type,
quadrature_degree=quadrature_degree,
quadrature_scheme=quadrature_scheme)
[docs]
class ContinuousPetrovGalerkinScheme(GalerkinScheme):
"""Class for describing cPG-in-time methods"""
def __init__(self, order,
basis_type=None,
quadrature_degree=None,
quadrature_scheme=None):
assert order >= 1, f"{type(self).__name__} must have order >= 1"
super().__init__(order, basis_type=basis_type,
quadrature_degree=quadrature_degree,
quadrature_scheme=quadrature_scheme)
[docs]
class GalerkinCollocationScheme(ContinuousPetrovGalerkinScheme):
"""Class for describing collocation cPG-in-time methods"""
def __init__(self, order,
stage_type="deriv",
quadrature_degree=None,
quadrature_scheme=None):
assert order >= 1, f"{type(self).__name__} must have order >= 1"
if quadrature_scheme is None:
test_type = "spectral"
elif quadrature_scheme in {"radau", "lobatto"}:
test_type = quadrature_scheme
if quadrature_degree is None:
# Default to under-integration!
if quadrature_scheme == "radau":
quadrature_degree = 2*order-2
elif quadrature_scheme == "lobatto":
quadrature_degree = 2*order-3
else:
raise ValueError(f"Unsupported quadrature scheme {quadrature_scheme}.")
if stage_type not in {"deriv", "value"}:
raise ValueError(f"Unsupported stage type {stage_type}.")
trial_type = stage_type
basis_type = (trial_type, test_type)
super().__init__(order, basis_type=basis_type,
quadrature_degree=quadrature_degree,
quadrature_scheme=quadrature_scheme)
[docs]
def create_time_quadrature(degree, scheme=None):
if scheme == "radau":
num_points = (degree + 1) // 2 + 1
return RadauQuadratureLineRule(ufc_line, num_points)
elif scheme == "lobatto":
num_points = degree // 2 + 2
return GaussLobattoLegendreQuadratureLineRule(ufc_line, num_points)
else:
return create_quadrature(ufc_line, degree, scheme=scheme or "default")