def check_lte(method_residual, lte, exact_symb, base_dt, implicit): exact, residual, dys, J = utils.symb2functions(exact_symb) dddy = dys[3] Fddy = lambda t, y: J(t, y) * dys[2](t, y) newton_tol = 1e-10 # tmax varies with dt so that we can vary dt over orders of # magnitude. tmax = 50*dt # Run ode solver if implicit: ts, ys = ode._odeint( residual, [0.0], [sp.array([exact(0.0)], ndmin=1)], dt, tmax, method_residual, target_error=None, time_adaptor=ode.create_random_time_adaptor(base_dt), initialisation_actions=par(ode.higher_order_start, 3), newton_tol=newton_tol) else: ts, ys = ode.odeint_explicit( dys[1], exact(0.0), base_dt, tmax, method_residual, time_adaptor=ode.create_random_time_adaptor(base_dt)) dts = utils.ts2dts(ts) # Check it's accurate-ish exact_ys = map(exact, ts) errors = map(op.sub, exact_ys, ys) utils.assert_list_almost_zero(errors, 1e-3) # Calculate ltes by two methods. Note that we need to drop a few # values because exact calculation (may) need a few dts. Could be # dodgy: exact dddys might not correspond to dddy in experiment if # done over long time and we've wandered away from the solution. exact_dddys = map(dddy, ts, ys) exact_Fddys = map(Fddy, ts, ys) exact_ltes = map(lte, dts[2:], dts[1:-1], dts[:-2], exact_dddys[3:], exact_Fddys[3:]) error_diff_ltes = map(op.sub, errors[1:], errors[:-1])[2:] # Print for debugging when something goes wrong print exact_ltes print error_diff_ltes # Probably the best test is that they give the same order of # magnitude and the same sign... Can't test much more than that # because we have no idea what the constant in front of the dt**4 # term is. Effective zero (noise level) is either dt**4 or newton # tol, whichever is larger. z = 50 * max(dt**4, newton_tol) map(par(utils.assert_same_sign, fp_zero=z), exact_ltes, error_diff_ltes) map(par(utils.assert_same_order_of_magnitude, fp_zero=z), exact_ltes, error_diff_ltes)
def interpolate_dyn(ts, ys): #??ds probably not accurate enough order = 3 ts = ts[-1 * order - 1:] ys = ys[-1 * order - 1:] ynp1_list = ys[1:] yn_list = ys[:-1] dts = utils.ts2dts(ts) # double check steps match imr_ts = map(lambda tn, tnp1: (tn + tnp1) / 2, ts[1:], ts[:-1]) imr_dys = map(lambda dt, ynp1, yn: (ynp1 - yn) / dt, dts, ynp1_list, yn_list) dyn = (sp.interpolate.barycentric_interpolate(imr_ts, imr_dys, ts[-2])) return dyn
def interpolate_dyn(ts, ys): #??ds probably not accurate enough order = 3 ts = ts[-1*order-1:] ys = ys[-1*order-1:] ynp1_list = ys[1:] yn_list = ys[:-1] dts = utils.ts2dts(ts) # double check steps match imr_ts = map(lambda tn, tnp1: (tn + tnp1)/2, ts[1:], ts[:-1]) imr_dys = map(lambda dt, ynp1, yn: (ynp1 - yn)/dt, dts, ynp1_list, yn_list) dyn = (sp.interpolate.barycentric_interpolate (imr_ts, imr_dys, ts[-2])) return dyn
def p_dt(ts): assert len(ts) >= 6 # Get last 5 dts in order: n, nm1, nm2 etc. dts = utils.ts2dts(ts[-6:])[::-1] return f(*dts) # plug them into the symbolic function
def check_lte(method_residual, lte, exact_symb, base_dt, implicit): exact, residual, dys, J = utils.symb2functions(exact_symb) dddy = dys[3] Fddy = lambda t, y: J(t, y) * dys[2](t, y) newton_tol = 1e-10 # tmax varies with dt so that we can vary dt over orders of # magnitude. tmax = 50 * dt # Run ode solver if implicit: ts, ys = ode._odeint( residual, [0.0], [sp.array([exact(0.0)], ndmin=1)], dt, tmax, method_residual, target_error=None, time_adaptor=ode.create_random_time_adaptor(base_dt), initialisation_actions=par(ode.higher_order_start, 3), newton_tol=newton_tol) else: ts, ys = ode.odeint_explicit( dys[1], exact(0.0), base_dt, tmax, method_residual, time_adaptor=ode.create_random_time_adaptor(base_dt)) dts = utils.ts2dts(ts) # Check it's accurate-ish exact_ys = map(exact, ts) errors = map(op.sub, exact_ys, ys) utils.assert_list_almost_zero(errors, 1e-3) # Calculate ltes by two methods. Note that we need to drop a few # values because exact calculation (may) need a few dts. Could be # dodgy: exact dddys might not correspond to dddy in experiment if # done over long time and we've wandered away from the solution. exact_dddys = map(dddy, ts, ys) exact_Fddys = map(Fddy, ts, ys) exact_ltes = map(lte, dts[2:], dts[1:-1], dts[:-2], exact_dddys[3:], exact_Fddys[3:]) error_diff_ltes = map(op.sub, errors[1:], errors[:-1])[2:] # Print for debugging when something goes wrong print exact_ltes print error_diff_ltes # Probably the best test is that they give the same order of # magnitude and the same sign... Can't test much more than that # because we have no idea what the constant in front of the dt**4 # term is. Effective zero (noise level) is either dt**4 or newton # tol, whichever is larger. z = 50 * max(dt**4, newton_tol) map(par(utils.assert_same_sign, fp_zero=z), exact_ltes, error_diff_ltes) map(par(utils.assert_same_order_of_magnitude, fp_zero=z), exact_ltes, error_diff_ltes)