# -*- coding: utf-8 -*-
import math
from pyfr.integrators.dual.phys.base import BaseDualIntegrator
class BaseDualStepper(BaseDualIntegrator):
pass
class BaseDIRKStepper(BaseDualStepper):
stepper_nregs = 1
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.fsal:
self.b = self.a[-1]
self.c = [sum(row) for row in self.a]
@property
def stage_nregs(self):
return self.nstages
def step(self, t, dt):
for s, (sc, tc) in enumerate(zip(self.a, self.c)):
self.pseudointegrator.init_stage(s, sc, dt)
self.pseudointegrator.pseudo_advance(t + dt*tc)
self._finalize_step()
def _finalize_step(self):
if not self.fsal:
bcoeffs = [bt*self._dt for bt in self.b]
self.pseudointegrator.obtain_solution(bcoeffs)
self.pseudointegrator.store_current_soln()
[docs]class DualBackwardEulerStepper(BaseDIRKStepper):
stepper_name = 'backward-euler'
nstages = 1
fsal = True
a = [[1]]
[docs]class SDIRK33Stepper(BaseDIRKStepper):
stepper_name = 'sdirk33'
nstages = 3
fsal = True
_at = math.atan(0.5**1.5) / 3
_al = (3**0.5*math.sin(_at) - math.cos(_at)) / 2**0.5 + 1
a = [
[_al],
[0.5*(1 - _al), _al],
[(4 - 1.5*_al)*_al - 0.25, (1.5*_al - 5)*_al + 1.25, _al]
]
[docs]class SDIRK43Stepper(BaseDIRKStepper):
stepper_name = 'sdirk43'
nstages = 3
fsal = False
_a_lam = (3 + 2*3**0.5*math.cos(math.pi/18))/6
a = [
[_a_lam],
[0.5 - _a_lam, _a_lam],
[2*_a_lam, 1 - 4*_a_lam, _a_lam]
]
_b_rlam = 1/(6*(1 - 2*_a_lam)*(1 - 2*_a_lam))
b = [_b_rlam, 1 - 2*_b_rlam, _b_rlam]