Exemplo n.º 1
0
class LSRK4TimeStepper(TimeStepper):
    """A low storage fourth-order Runge-Kutta method

    See JSH, TW: Nodal Discontinuous Galerkin Methods p.64
    or
    Carpenter, M.H., and Kennedy, C.A., Fourth-order-2N-storage
    Runge-Kutta schemes, NASA Langley Tech Report TM 109112, 1994
    """

    _RK4A = [
        0.0,
        -567301805773 / 1357537059087,
        -2404267990393 / 2016746695238,
        -3550918686646 / 2091501179385,
        -1275806237668 / 842570457699,
    ]

    _RK4B = [
        1432997174477 / 9575080441755,
        5161836677717 / 13612068292357,
        1720146321549 / 2090206949498,
        3134564353537 / 4481467310338,
        2277821191437 / 14882151754819,
    ]

    _RK4C = [
        0.0,
        1432997174477 / 9575080441755,
        2526269341429 / 6820363962896,
        2006345519317 / 3224310063776,
        2802321613138 / 2924317926251,
        #1,
    ]

    dt_fudge_factor = 1

    adaptive = False

    def __init__(self,
                 dtype=numpy.float64,
                 rcon=None,
                 vector_primitive_factory=None):
        if vector_primitive_factory is None:
            from hedge.vector_primitives import VectorPrimitiveFactory
            self.vector_primitive_factory = VectorPrimitiveFactory()
        else:
            self.vector_primitive_factory = vector_primitive_factory

        from pytools.log import IntervalTimer, EventCounter
        timer_factory = IntervalTimer
        if rcon is not None:
            timer_factory = rcon.make_timer

        self.timer = timer_factory("t_rk4", "Time spent doing algebra in RK4")
        self.flop_counter = EventCounter(
            "n_flops_rk4", "Floating point operations performed in RK4")

        from pytools import match_precision
        self.dtype = numpy.dtype(dtype)
        self.scalar_dtype = match_precision(numpy.dtype(numpy.float64),
                                            self.dtype)
        self.coeffs = numpy.array([self._RK4A, self._RK4B, self._RK4C],
                                  dtype=self.scalar_dtype).T

    def get_stability_relevant_init_args(self):
        return ()

    def add_instrumentation(self, logmgr):
        logmgr.add_quantity(self.timer)
        logmgr.add_quantity(self.flop_counter)

    def __call__(self, y, t, dt, rhs):
        try:
            self.residual
        except AttributeError:
            self.residual = 0 * rhs(t, y)
            from hedge.tools import count_dofs
            self.dof_count = count_dofs(self.residual)

            self.linear_combiner = self.vector_primitive_factory\
                    .make_linear_combiner(self.dtype, self.scalar_dtype,
                            y, arg_count=2)

        lc = self.linear_combiner

        for a, b, c in self.coeffs:
            this_rhs = rhs(t + c * dt, y)

            sub_timer = self.timer.start_sub_timer()
            self.residual = lc((a, self.residual), (dt, this_rhs))
            del this_rhs
            y = lc((1, y), (b, self.residual))
            sub_timer.stop().submit()

        # 5 is the number of flops above, *NOT* the number of stages,
        # which is already captured in len(self.coeffs)
        self.flop_counter.add(len(self.coeffs) * self.dof_count * 5)

        return y
Exemplo n.º 2
0
class LSRK4TimeStepper(TimeStepper):
    """A low storage fourth-order Runge-Kutta method

    See JSH, TW: Nodal Discontinuous Galerkin Methods p.64
    or 
    Carpenter, M.H., and Kennedy, C.A., Fourth-order-2N-storage 
    Runge-Kutta schemes, NASA Langley Tech Report TM 109112, 1994
    """

    _RK4A = [0.0,
            -567301805773 /1357537059087,
            -2404267990393/2016746695238,
            -3550918686646/2091501179385,
            -1275806237668/ 842570457699,
            ]

    _RK4B = [1432997174477/ 9575080441755,
            5161836677717 /13612068292357,
            1720146321549 / 2090206949498,
            3134564353537 / 4481467310338,
            2277821191437 /14882151754819,
            ]

    _RK4C = [0.0,
            1432997174477/9575080441755,
            2526269341429/6820363962896,
            2006345519317/3224310063776,
            2802321613138/2924317926251,
            #1,
            ]

    dt_fudge_factor = 1

    adaptive = False

    def __init__(self, dtype=numpy.float64, rcon=None,
            vector_primitive_factory=None):
        if vector_primitive_factory is None:
            from hedge.vector_primitives import VectorPrimitiveFactory
            self.vector_primitive_factory = VectorPrimitiveFactory()
        else:
            self.vector_primitive_factory = vector_primitive_factory

        from pytools.log import IntervalTimer, EventCounter
        timer_factory = IntervalTimer
        if rcon is not None:
            timer_factory = rcon.make_timer

        self.timer = timer_factory(
                "t_rk4", "Time spent doing algebra in RK4")
        self.flop_counter = EventCounter(
                "n_flops_rk4", "Floating point operations performed in RK4")

        from pytools import match_precision
        self.dtype = numpy.dtype(dtype)
        self.scalar_dtype = match_precision(
                numpy.dtype(numpy.float64), self.dtype)
        self.coeffs = numpy.array([self._RK4A, self._RK4B, self._RK4C], 
                dtype=self.scalar_dtype).T

    def get_stability_relevant_init_args(self):
        return ()

    def add_instrumentation(self, logmgr):
        logmgr.add_quantity(self.timer)
        logmgr.add_quantity(self.flop_counter)

    def __call__(self, y, t, dt, rhs):
        try:
            self.residual
        except AttributeError:
            self.residual = 0*rhs(t, y)
            from hedge.tools import count_dofs
            self.dof_count = count_dofs(self.residual)

            self.linear_combiner = self.vector_primitive_factory\
                    .make_linear_combiner(self.dtype, self.scalar_dtype, 
                            y, arg_count=2)

        lc = self.linear_combiner

        for a, b, c in self.coeffs:
            this_rhs = rhs(t + c*dt, y)

            sub_timer = self.timer.start_sub_timer()
            self.residual = lc((a, self.residual), (dt, this_rhs))
            del this_rhs
            y = lc((1, y), (b, self.residual))
            sub_timer.stop().submit()

        # 5 is the number of flops above, *NOT* the number of stages,
        # which is already captured in len(self.coeffs)
        self.flop_counter.add(len(self.coeffs)*self.dof_count*5)

        return y
Exemplo n.º 3
0
class AdamsBashforthTimeStepper(TimeStepper):
    dt_fudge_factor = 0.95

    def __init__(self, order, startup_stepper=None, dtype=numpy.float64, rcon=None):
        self.f_history = []

        from pytools import match_precision
        self.dtype = numpy.dtype(dtype)
        self.scalar_dtype = match_precision(
                numpy.dtype(numpy.float64), self.dtype)
        self.coefficients = numpy.asarray(make_ab_coefficients(order),
                dtype=self.scalar_dtype)

        if startup_stepper is not None:
            self.startup_stepper = startup_stepper
        else:
            from hedge.timestep.runge_kutta import LSRK4TimeStepper
            self.startup_stepper = LSRK4TimeStepper(self.dtype)

        from pytools.log import IntervalTimer, EventCounter
        timer_factory = IntervalTimer
        if rcon is not None:
            timer_factory = rcon.make_timer

        self.timer = timer_factory(
                "t_ab", "Time spent doing algebra in Adams-Bashforth")
        self.flop_counter = EventCounter(
                "n_flops_ab", "Floating point operations performed in AB")

    @property
    def order(self):
        return len(self.coefficients)

    def get_stability_relevant_init_args(self):
        return (self.order,)

    def add_instrumentation(self, logmgr):
        logmgr.add_quantity(self.timer)
        logmgr.add_quantity(self.flop_counter)

    def __getinitargs__(self):
        return (self.order, self.startup_stepper)

    def __call__(self, y, t, dt, rhs):
        if len(self.f_history) == 0:
            # insert IC
            self.f_history.append(rhs(t, y))

            from hedge.tools import count_dofs
            self.dof_count = count_dofs(self.f_history[0])

        if len(self.f_history) < len(self.coefficients):
            ynew = self.startup_stepper(y, t, dt, rhs)
            if len(self.f_history) == len(self.coefficients) - 1:
                # here's some memory we won't need any more
                del self.startup_stepper

        else:
            from operator import add

            sub_timer = self.timer.start_sub_timer()
            assert len(self.coefficients) == len(self.f_history)
            ynew = y + dt * reduce(add,
                    (coeff * f 
                        for coeff, f in 
                        zip(self.coefficients, self.f_history)))

            self.f_history.pop()
            sub_timer.stop().submit()

        self.flop_counter.add((2+2*len(self.coefficients)-1)*self.dof_count)

        self.f_history.insert(0, rhs(t+dt, ynew))
        return ynew
Exemplo n.º 4
0
class AdamsBashforthTimeStepper(TimeStepper):
    dt_fudge_factor = 0.95

    def __init__(self,
                 order,
                 startup_stepper=None,
                 dtype=numpy.float64,
                 rcon=None):
        self.f_history = []

        from pytools import match_precision
        self.dtype = numpy.dtype(dtype)
        self.scalar_dtype = match_precision(numpy.dtype(numpy.float64),
                                            self.dtype)
        self.coefficients = numpy.asarray(make_ab_coefficients(order),
                                          dtype=self.scalar_dtype)

        if startup_stepper is not None:
            self.startup_stepper = startup_stepper
        else:
            from hedge.timestep.runge_kutta import LSRK4TimeStepper
            self.startup_stepper = LSRK4TimeStepper(self.dtype)

        from pytools.log import IntervalTimer, EventCounter
        timer_factory = IntervalTimer
        if rcon is not None:
            timer_factory = rcon.make_timer

        self.timer = timer_factory(
            "t_ab", "Time spent doing algebra in Adams-Bashforth")
        self.flop_counter = EventCounter(
            "n_flops_ab", "Floating point operations performed in AB")

    @property
    def order(self):
        return len(self.coefficients)

    def get_stability_relevant_init_args(self):
        return (self.order, )

    def add_instrumentation(self, logmgr):
        logmgr.add_quantity(self.timer)
        logmgr.add_quantity(self.flop_counter)

    def __getinitargs__(self):
        return (self.order, self.startup_stepper)

    def __call__(self, y, t, dt, rhs):
        if len(self.f_history) == 0:
            # insert IC
            self.f_history.append(rhs(t, y))

            from hedge.tools import count_dofs
            self.dof_count = count_dofs(self.f_history[0])

        if len(self.f_history) < len(self.coefficients):
            ynew = self.startup_stepper(y, t, dt, rhs)
            if len(self.f_history) == len(self.coefficients) - 1:
                # here's some memory we won't need any more
                del self.startup_stepper

        else:
            from operator import add

            sub_timer = self.timer.start_sub_timer()
            assert len(self.coefficients) == len(self.f_history)
            ynew = y + dt * reduce(
                add, (coeff * f
                      for coeff, f in zip(self.coefficients, self.f_history)))

            self.f_history.pop()
            sub_timer.stop().submit()

        self.flop_counter.add(
            (2 + 2 * len(self.coefficients) - 1) * self.dof_count)

        self.f_history.insert(0, rhs(t + dt, ynew))
        return ynew