def predictor_func(ts, ys):

            pdts = [f(ts) for f in p_dtn_funcs]

            dynp1 = dy_funcs[0](ts, ys)
            yn = y_funcs[1](ts, ys)
            ynm1 = y_funcs[2](ts, ys)
            ynm2 = y_funcs[3](ts, ys)

            return ode.ibdf3_step(dynp1, pdts[0], yn, pdts[1], ynm1,
                                  pdts[2], ynm2)
Exemplo n.º 2
0
        def predictor_func(ts, ys):

            pdts = [f(ts) for f in p_dtn_funcs]

            dynp1 = dy_funcs[0](ts, ys)
            yn = y_funcs[1](ts, ys)
            ynm1 = y_funcs[2](ts, ys)
            ynm2 = y_funcs[3](ts, ys)

            return ode.ibdf3_step(dynp1, pdts[0], yn, pdts[1], ynm1, pdts[2],
                                  ynm2)
def generate_predictor_scheme(pt_infos, predictor_name, symbolic=None):

    # Extract symbolic expressions from what we're given.
    if symbolic is not None:
        try:
            symb_exact, symb_F = symbolic

        except TypeError:  # not iterable
            symb_exact = symbolic

            Sy = sympy.symbols('y', real=True)
            symb_dy = sympy.diff(symb_exact, St, 1).subs(symb_exact, Sy)
            symb_F = sympy.diff(symb_dy, Sy).subs(Sy, symb_exact)

        dydt_func = sympy.lambdify(St, sympy.diff(symb_exact, St, 1))
        f_y = sympy.lambdify(St, symb_exact)

    else:
        dydt_func = None
        f_y = None

    # To cancel errors we need the final step to be at t_np1
    # assert pt_infos[0].time == 0
    n_hist = len(pt_infos) + 5

    # Create symbolic and python functions of (corrector) dts and ts
    # respectively that give the appropriate dts for this predictor.
    p_dtns = []
    p_dtn_funcs = []
    for pt1, pt2 in zip(pt_infos[:-1], pt_infos[1:]):
        p_dtns.append(sum_dts(pt1.time, pt2.time))
        p_dtn_funcs.append(generate_p_dt_func(p_dtns[-1]))

    # For each time point the predictor uses construct symbolic error
    # estimates for the requested estimate at that point and python
    # functions to calculate the value of the estimate.
    y_errors = map(ptinfo2yerr, pt_infos)
    y_funcs = map(par(ptinfo2yfunc, y_of_t_func=f_y), pt_infos)
    dy_errors = map(ptinfo2dyerr, pt_infos)
    dy_funcs = map(par(ptinfo2dyfunc, dydt_func=dydt_func), pt_infos)

    # Construct errors and function for the predictor
    # ============================================================
    if predictor_name == "ebdf2" or predictor_name == "wrong step ebdf2":

        if predictor_name == "wrong step ebdf2":
            temp_p_dtnm1 = p_dtns[1] + Sdts[0]
        else:
            temp_p_dtnm1 = p_dtns[1]

        y_np1_p_expr = y_np1_exact - (
            # Natural ebdf2 lte:
            ebdf2_lte(p_dtns[0], temp_p_dtnm1, Sdddynph)
            # error due to approximation to derivative at tn:
            + ode.ebdf2_step(p_dtns[0], 0, dy_errors[1], p_dtns[1], 0)
            # error due to approximation to yn
            + ode.ebdf2_step(p_dtns[0], y_errors[1], 0, p_dtns[1], 0)
            # error due to approximation to ynm1 (typically zero)
            + ode.ebdf2_step(p_dtns[0], 0, 0, p_dtns[1], y_errors[2]))

        def predictor_func(ts, ys):

            dtn = p_dtn_funcs[0](ts)
            yn = y_funcs[1](ts, ys)
            dyn = dy_funcs[1](ts, ys)

            dtnm1 = p_dtn_funcs[1](ts)
            ynm1 = y_funcs[2](ts, ys)
            return ode.ebdf2_step(dtn, yn, dyn, dtnm1, ynm1)

    elif predictor_name == "ab2":

        y_np1_p_expr = y_np1_exact - (
            # Natural ab2 lte:
            ab2_lte(p_dtns[0], p_dtns[1], Sdddynph)
            # error due to approximation to derivative at tn
            + ode.ab2_step(p_dtns[0], 0, dy_errors[1], p_dtns[1], 0)
            # error due to approximation to derivative at tnm1
            + ode.ab2_step(p_dtns[0], 0, 0, p_dtns[1], dy_errors[2])
            # error due to approximation to yn
            + ode.ab2_step(p_dtns[0], y_errors[1], 0, p_dtns[1], 0))

        def predictor_func(ts, ys):

            dtn = p_dtn_funcs[0](ts)
            yn = y_funcs[1](ts, ys)
            dyn = dy_funcs[1](ts, ys)

            dtnm1 = p_dtn_funcs[1](ts)
            dynm1 = dy_funcs[2](ts, ys)

            return ode.ab2_step(dtn, yn, dyn, dtnm1, dynm1)

    elif predictor_name == "ibdf2":

        y_np1_p_expr = y_np1_exact - (
            # Natural bdf2 lte:
            bdf2_lte(p_dtns[0], p_dtns[1], Sdddynph)
            # error due to approximation to derivative at tnp1
            + ode.ibdf2_step(p_dtns[0], 0, dy_errors[0], p_dtns[1], 0)
            # errors due to approximations to y at tn and tnm1
            + ode.ibdf2_step(p_dtns[0], y_errors[1], 0, p_dtns[1], 0)
            + ode.ibdf2_step(p_dtns[0], 0, 0, p_dtns[1], y_errors[2]))

        def predictor_func(ts, ys):

            pdts = [f(ts) for f in p_dtn_funcs]

            dynp1 = dy_funcs[0](ts, ys)
            yn = y_funcs[1](ts, ys)
            ynm1 = y_funcs[2](ts, ys)

            tsin = [t_at_time_point(ts, pt.time)
                    for pt in reversed(pt_infos[1:])]
            ysin = [ys[-(pt.time+1)] for pt in reversed(pt_infos[1:])]
            dt = pdts[0]

            return ode.ibdf2_step(pdts[0], yn, dynp1, pdts[1], ynm1)

    elif predictor_name == "ibdf3":

        y_np1_p_expr = y_np1_exact - (
            # Natural bdf2 lte:
            bdf3_lte(p_dtns[0], p_dtns[1], Sdddynph)
            # error due to approximation to derivative at tnp1
            + ode.ibdf3_step(
                dy_errors[0],
                p_dtns[0],
                0,
                p_dtns[1],
                0,
                p_dtns[2],
                0)
            # errors due to approximations to y at tn, tnm1, tnm2
            + ode.ibdf3_step(
                0,
                p_dtns[0],
                y_errors[1],
                p_dtns[1],
                0,
                p_dtns[2],
                0)
            + ode.ibdf3_step(
                0,
                p_dtns[0],
                0,
                p_dtns[1],
                y_errors[2],
                p_dtns[2],
                0)
            + ode.ibdf3_step(0, p_dtns[0], 0, p_dtns[1], 0, p_dtns[2], y_errors[3]))

        def predictor_func(ts, ys):

            pdts = [f(ts) for f in p_dtn_funcs]

            dynp1 = dy_funcs[0](ts, ys)
            yn = y_funcs[1](ts, ys)
            ynm1 = y_funcs[2](ts, ys)
            ynm2 = y_funcs[3](ts, ys)

            return ode.ibdf3_step(dynp1, pdts[0], yn, pdts[1], ynm1,
                                  pdts[2], ynm2)

    elif predictor_name == "ebdf3":
        y_np1_p_expr = y_np1_exact - (
            # Natural ebdf3 lte error:
            ebdf3_lte(p_dtns[0], p_dtns[1], p_dtns[2], Sdddynph)
            # error due to approximation to derivative at tn
            + ode.ebdf3_step(
                p_dtns[0],
                0,
                dy_errors[1],
                p_dtns[1],
                0,
                p_dtns[2],
                0)
            # errors due to approximation to y at tn, tnm1, tnm2
            + ode.ebdf3_step(p_dtns[0], y_errors[1], 0,
                             p_dtns[1], 0, p_dtns[2], 0)
            + ode.ebdf3_step(p_dtns[0], 0, 0,
                             p_dtns[1], y_errors[2], p_dtns[2], 0)
            + ode.ebdf3_step(p_dtns[0], 0, 0,
                             p_dtns[1], 0, p_dtns[2], y_errors[3]))

        def predictor_func(ts, ys):

            pdts = [f(ts) for f in p_dtn_funcs]

            dyn = dy_funcs[1](ts, ys)
            yn = y_funcs[1](ts, ys)
            ynm1 = y_funcs[2](ts, ys)
            ynm2 = y_funcs[3](ts, ys)

            return ode.ebdf3_step(pdts[0], yn, dyn,
                                  pdts[1], ynm1,
                                  pdts[2], ynm2)

    elif predictor_name == "use exact dddy":

        symb_dddy = sympy.diff(symb_exact, St, 3)
        f_dddy = sympy.lambdify(St, symb_dddy)

        print symb_exact
        print "dddy =", symb_dddy

        # "Predictor" is just exactly dddy, error forumlated so that matrix
        # turns out right. Calculate at one before last point (same as lte
        # "location").
        def predictor_func(ts, ys):
            tn = t_at_time_point(ts, pt_infos[1].time)
            return f_dddy(tn)

        y_np1_p_expr = Sdddynph

    elif predictor_name == "use exact Fddy":

        symb_ddy = sympy.diff(symb_exact, St, 2)
        f_Fddy = sympy.lambdify(St, symb_F * symb_ddy)

        print "Fddy =", symb_F * symb_ddy

        # "Predictor" is just exactly dddy, error forumlated so that matrix
        # turns out right. Calculate at one before last point (same as lte
        # "location").
        def predictor_func(ts, ys):
            tn = t_at_time_point(ts, pt_infos[1].time)
            return f_Fddy(tn)

        y_np1_p_expr = SFddynph

    else:
        raise ValueError("Unrecognised predictor name " + predictor_name)

    return predictor_func, y_np1_p_expr
Exemplo n.º 4
0
def generate_predictor_scheme(pt_infos, predictor_name, symbolic=None):

    # Extract symbolic expressions from what we're given.
    if symbolic is not None:
        try:
            symb_exact, symb_F = symbolic

        except TypeError:  # not iterable
            symb_exact = symbolic

            Sy = sympy.symbols('y', real=True)
            symb_dy = sympy.diff(symb_exact, St, 1).subs(symb_exact, Sy)
            symb_F = sympy.diff(symb_dy, Sy).subs(Sy, symb_exact)

        dydt_func = sympy.lambdify(St, sympy.diff(symb_exact, St, 1))
        f_y = sympy.lambdify(St, symb_exact)

    else:
        dydt_func = None
        f_y = None

    # To cancel errors we need the final step to be at t_np1
    # assert pt_infos[0].time == 0
    n_hist = len(pt_infos) + 5

    # Create symbolic and python functions of (corrector) dts and ts
    # respectively that give the appropriate dts for this predictor.
    p_dtns = []
    p_dtn_funcs = []
    for pt1, pt2 in zip(pt_infos[:-1], pt_infos[1:]):
        p_dtns.append(sum_dts(pt1.time, pt2.time))
        p_dtn_funcs.append(generate_p_dt_func(p_dtns[-1]))

    # For each time point the predictor uses construct symbolic error
    # estimates for the requested estimate at that point and python
    # functions to calculate the value of the estimate.
    y_errors = map(ptinfo2yerr, pt_infos)
    y_funcs = map(par(ptinfo2yfunc, y_of_t_func=f_y), pt_infos)
    dy_errors = map(ptinfo2dyerr, pt_infos)
    dy_funcs = map(par(ptinfo2dyfunc, dydt_func=dydt_func), pt_infos)

    # Construct errors and function for the predictor
    # ============================================================
    if predictor_name == "ebdf2" or predictor_name == "wrong step ebdf2":

        if predictor_name == "wrong step ebdf2":
            temp_p_dtnm1 = p_dtns[1] + Sdts[0]
        else:
            temp_p_dtnm1 = p_dtns[1]

        y_np1_p_expr = y_np1_exact - (
            # Natural ebdf2 lte:
            ebdf2_lte(p_dtns[0], temp_p_dtnm1, Sdddynph)
            # error due to approximation to derivative at tn:
            + ode.ebdf2_step(p_dtns[0], 0, dy_errors[1], p_dtns[1], 0)
            # error due to approximation to yn
            + ode.ebdf2_step(p_dtns[0], y_errors[1], 0, p_dtns[1], 0)
            # error due to approximation to ynm1 (typically zero)
            + ode.ebdf2_step(p_dtns[0], 0, 0, p_dtns[1], y_errors[2]))

        def predictor_func(ts, ys):

            dtn = p_dtn_funcs[0](ts)
            yn = y_funcs[1](ts, ys)
            dyn = dy_funcs[1](ts, ys)

            dtnm1 = p_dtn_funcs[1](ts)
            ynm1 = y_funcs[2](ts, ys)
            return ode.ebdf2_step(dtn, yn, dyn, dtnm1, ynm1)

    elif predictor_name == "ab2":

        y_np1_p_expr = y_np1_exact - (
            # Natural ab2 lte:
            ab2_lte(p_dtns[0], p_dtns[1], Sdddynph)
            # error due to approximation to derivative at tn
            + ode.ab2_step(p_dtns[0], 0, dy_errors[1], p_dtns[1], 0)
            # error due to approximation to derivative at tnm1
            + ode.ab2_step(p_dtns[0], 0, 0, p_dtns[1], dy_errors[2])
            # error due to approximation to yn
            + ode.ab2_step(p_dtns[0], y_errors[1], 0, p_dtns[1], 0))

        def predictor_func(ts, ys):

            dtn = p_dtn_funcs[0](ts)
            yn = y_funcs[1](ts, ys)
            dyn = dy_funcs[1](ts, ys)

            dtnm1 = p_dtn_funcs[1](ts)
            dynm1 = dy_funcs[2](ts, ys)

            return ode.ab2_step(dtn, yn, dyn, dtnm1, dynm1)

    elif predictor_name == "ibdf2":

        y_np1_p_expr = y_np1_exact - (
            # Natural bdf2 lte:
            bdf2_lte(p_dtns[0], p_dtns[1], Sdddynph)
            # error due to approximation to derivative at tnp1
            + ode.ibdf2_step(p_dtns[0], 0, dy_errors[0], p_dtns[1], 0)
            # errors due to approximations to y at tn and tnm1
            + ode.ibdf2_step(p_dtns[0], y_errors[1], 0, p_dtns[1], 0) +
            ode.ibdf2_step(p_dtns[0], 0, 0, p_dtns[1], y_errors[2]))

        def predictor_func(ts, ys):

            pdts = [f(ts) for f in p_dtn_funcs]

            dynp1 = dy_funcs[0](ts, ys)
            yn = y_funcs[1](ts, ys)
            ynm1 = y_funcs[2](ts, ys)

            tsin = [
                t_at_time_point(ts, pt.time) for pt in reversed(pt_infos[1:])
            ]
            ysin = [ys[-(pt.time + 1)] for pt in reversed(pt_infos[1:])]
            dt = pdts[0]

            return ode.ibdf2_step(pdts[0], yn, dynp1, pdts[1], ynm1)

    elif predictor_name == "ibdf3":

        y_np1_p_expr = y_np1_exact - (
            # Natural bdf2 lte:
            bdf3_lte(p_dtns[0], p_dtns[1], Sdddynph)
            # error due to approximation to derivative at tnp1
            + ode.ibdf3_step(dy_errors[0], p_dtns[0], 0, p_dtns[1], 0,
                             p_dtns[2], 0)
            # errors due to approximations to y at tn, tnm1, tnm2
            + ode.ibdf3_step(0, p_dtns[0], y_errors[1], p_dtns[1], 0,
                             p_dtns[2], 0) +
            ode.ibdf3_step(0, p_dtns[0], 0, p_dtns[1], y_errors[2], p_dtns[2],
                           0) + ode.ibdf3_step(0, p_dtns[0], 0, p_dtns[1], 0,
                                               p_dtns[2], y_errors[3]))

        def predictor_func(ts, ys):

            pdts = [f(ts) for f in p_dtn_funcs]

            dynp1 = dy_funcs[0](ts, ys)
            yn = y_funcs[1](ts, ys)
            ynm1 = y_funcs[2](ts, ys)
            ynm2 = y_funcs[3](ts, ys)

            return ode.ibdf3_step(dynp1, pdts[0], yn, pdts[1], ynm1, pdts[2],
                                  ynm2)

    elif predictor_name == "ebdf3":
        y_np1_p_expr = y_np1_exact - (
            # Natural ebdf3 lte error:
            ebdf3_lte(p_dtns[0], p_dtns[1], p_dtns[2], Sdddynph)
            # error due to approximation to derivative at tn
            + ode.ebdf3_step(p_dtns[0], 0, dy_errors[1], p_dtns[1], 0,
                             p_dtns[2], 0)
            # errors due to approximation to y at tn, tnm1, tnm2
            + ode.ebdf3_step(p_dtns[0], y_errors[1], 0, p_dtns[1], 0,
                             p_dtns[2], 0) +
            ode.ebdf3_step(p_dtns[0], 0, 0, p_dtns[1], y_errors[2], p_dtns[2],
                           0) + ode.ebdf3_step(p_dtns[0], 0, 0, p_dtns[1], 0,
                                               p_dtns[2], y_errors[3]))

        def predictor_func(ts, ys):

            pdts = [f(ts) for f in p_dtn_funcs]

            dyn = dy_funcs[1](ts, ys)
            yn = y_funcs[1](ts, ys)
            ynm1 = y_funcs[2](ts, ys)
            ynm2 = y_funcs[3](ts, ys)

            return ode.ebdf3_step(pdts[0], yn, dyn, pdts[1], ynm1, pdts[2],
                                  ynm2)

    elif predictor_name == "use exact dddy":

        symb_dddy = sympy.diff(symb_exact, St, 3)
        f_dddy = sympy.lambdify(St, symb_dddy)

        print symb_exact
        print "dddy =", symb_dddy

        # "Predictor" is just exactly dddy, error forumlated so that matrix
        # turns out right. Calculate at one before last point (same as lte
        # "location").
        def predictor_func(ts, ys):
            tn = t_at_time_point(ts, pt_infos[1].time)
            return f_dddy(tn)

        y_np1_p_expr = Sdddynph

    elif predictor_name == "use exact Fddy":

        symb_ddy = sympy.diff(symb_exact, St, 2)
        f_Fddy = sympy.lambdify(St, symb_F * symb_ddy)

        print "Fddy =", symb_F * symb_ddy

        # "Predictor" is just exactly dddy, error forumlated so that matrix
        # turns out right. Calculate at one before last point (same as lte
        # "location").
        def predictor_func(ts, ys):
            tn = t_at_time_point(ts, pt_infos[1].time)
            return f_Fddy(tn)

        y_np1_p_expr = SFddynph

    else:
        raise ValueError("Unrecognised predictor name " + predictor_name)

    return predictor_func, y_np1_p_expr