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
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