def test_t_eval(): rtol = 1e-3 atol = 1e-6 y0 = [1/3, 2/9] for t_span in ([5, 9], [5, 1]): t_eval = np.linspace(t_span[0], t_span[1], 10) res = solve_ivp(fun_rational, t_span, y0, rtol=rtol, atol=atol, t_eval=t_eval) assert_equal(res.t, t_eval) assert_(res.t_events is None) assert_(res.success) assert_equal(res.status, 0) y_true = sol_rational(res.t) e = compute_error(res.y, y_true, rtol, atol) assert_(np.all(e < 5)) t_eval = [5, 5.01, 7, 8, 8.01, 9] res = solve_ivp(fun_rational, [5, 9], y0, rtol=rtol, atol=atol, t_eval=t_eval) assert_equal(res.t, t_eval) assert_(res.t_events is None) assert_(res.success) assert_equal(res.status, 0) y_true = sol_rational(res.t) e = compute_error(res.y, y_true, rtol, atol) assert_(np.all(e < 5)) t_eval = [5, 4.99, 3, 1.5, 1.1, 1.01, 1] res = solve_ivp(fun_rational, [5, 1], y0, rtol=rtol, atol=atol, t_eval=t_eval) assert_equal(res.t, t_eval) assert_(res.t_events is None) assert_(res.success) assert_equal(res.status, 0) t_eval = [5.01, 7, 8, 8.01] res = solve_ivp(fun_rational, [5, 9], y0, rtol=rtol, atol=atol, t_eval=t_eval) assert_equal(res.t, t_eval) assert_(res.t_events is None) assert_(res.success) assert_equal(res.status, 0) y_true = sol_rational(res.t) e = compute_error(res.y, y_true, rtol, atol) assert_(np.all(e < 5)) t_eval = [4.99, 3, 1.5, 1.1, 1.01] res = solve_ivp(fun_rational, [5, 1], y0, rtol=rtol, atol=atol, t_eval=t_eval) assert_equal(res.t, t_eval) assert_(res.t_events is None) assert_(res.success) assert_equal(res.status, 0) t_eval = [4, 6] assert_raises(ValueError, solve_ivp, fun_rational, [5, 9], y0, rtol=rtol, atol=atol, t_eval=t_eval)
def test_integration_complex(): rtol = 1e-3 atol = 1e-6 y0 = [0.5 + 1j] t_span = [0, 1] tc = np.linspace(t_span[0], t_span[1]) with warnings.catch_warnings(): warnings.simplefilter('ignore') for method, jac in product(['RK23', 'RK45', 'BDF'], [None, jac_complex, jac_complex_sparse]): res = solve_ivp(fun_complex, t_span, y0, method=method, dense_output=True, rtol=rtol, atol=atol, jac=jac) assert_equal(res.t[0], t_span[0]) assert_(res.t_events is None) assert_(res.success) assert_equal(res.status, 0) assert_(res.nfev < 25) if method == 'BDF': assert_equal(res.njev, 1) assert_(res.nlu < 6) else: assert_equal(res.njev, 0) assert_equal(res.nlu, 0) y_true = sol_complex(res.t) e = compute_error(res.y, y_true, rtol, atol) assert_(np.all(e < 5)) yc_true = sol_complex(tc) yc = res.sol(tc) e = compute_error(yc, yc_true, rtol, atol) assert_(np.all(e < 5))
def test_integration_const_jac(): rtol = 1e-3 atol = 1e-6 y0 = [0, 2] t_span = [0, 2] J = jac_linear() J_sparse = csc_matrix(J) for method, jac in product(['Radau', 'BDF'], [J, J_sparse]): res = solve_ivp(fun_linear, t_span, y0, rtol=rtol, atol=atol, method=method, dense_output=True, jac=jac) assert_equal(res.t[0], t_span[0]) assert_(res.t_events is None) assert_(res.success) assert_equal(res.status, 0) assert_(res.nfev < 100) assert_equal(res.njev, 0) assert_(0 < res.nlu < 15) y_true = sol_linear(res.t) e = compute_error(res.y, y_true, rtol, atol) assert_(np.all(e < 10)) tc = np.linspace(*t_span) yc_true = sol_linear(tc) yc = res.sol(tc) e = compute_error(yc, yc_true, rtol, atol) assert_(np.all(e < 15)) assert_allclose(res.sol(res.t), res.y, rtol=1e-14, atol=1e-14)
def test_equilibrium(): def fun(t, y): kf = 0.2 kr = 0.5 a, b, c = y rf = kf * a * b rr = kr * c return [ -rf + rr, -rf + rr, rf - rr, ] ic = [4, 3, 0] dynamic_reference = None known_reference = [4 - 3 / 2, 3 - 3 / 2, 3 / 2] # Calculated by hand for method in all_methods: sol = solve_ivp(fun, ic, 0, 100, method=method) dynamic_result = sol(1.5) if dynamic_reference is None: dynamic_reference = dynamic_result else: assert_allclose(dynamic_result, dynamic_reference, rtol=1e-2) static_result = sol(100) assert_allclose(static_result, known_reference, rtol=1e-2)
def test_integration(): rtol = 1e-3 atol = 1e-6 y0 = [1/3, 2/9] with warnings.catch_warnings(): warnings.simplefilter('ignore') for vectorized, method, t_span, jac in product( [False, True], ['RK23', 'RK45', 'Radau', 'BDF', 'LSODA'], [[5, 9], [5, 1]], [None, jac_rational, jac_rational_sparse]): if vectorized: fun = fun_rational_vectorized else: fun = fun_rational res = solve_ivp(fun, t_span, y0, rtol=rtol, atol=atol, method=method, dense_output=True, jac=jac, vectorized=vectorized) assert_equal(res.t[0], t_span[0]) assert_(res.t_events is None) assert_(res.success) assert_equal(res.status, 0) assert_(res.nfev < 40) if method in ['RK23', 'RK45', 'LSODA']: assert_equal(res.njev, 0) assert_equal(res.nlu, 0) else: assert_(0 < res.njev < 3) assert_(0 < res.nlu < 10) y_true = sol_rational(res.t) e = compute_error(res.y, y_true, rtol, atol) assert_(np.all(e < 5)) tc = np.linspace(*t_span) yc_true = sol_rational(tc) yc = res.sol(tc) e = compute_error(yc, yc_true, rtol, atol) assert_(np.all(e < 5)) tc = (t_span[0] + t_span[-1]) / 2 yc_true = sol_rational(tc) yc = res.sol(tc) e = compute_error(yc, yc_true, rtol, atol) assert_(np.all(e < 5)) # LSODA for some reasons doesn't pass the polynomial through the # previous points exactly after the order change. It might be some # bug in LSOSA implementation or maybe we missing something. if method != 'LSODA': assert_allclose(res.sol(res.t), res.y, rtol=1e-15, atol=1e-15)
def __call__(self, model, rtol): def collected_ode(t, y): return model.f(t, y, model.k) sol = solve_ivp(collected_ode, [0.0, np.max(model.ts)], model.y0, method=self.name, rtol=rtol, t_eval=model.ts) return sol.y.transpose()
def test_solution(): for method in all_methods: sol = solve_ivp(lambda t, y: -y, [2, 3], 0, 4, method=method) assert_equal(sol(0), [2, 3]) assert_equal(sol(0, 1), 3) assert_equal(sol([0, 2, 4]).shape, (3, 2)) assert_equal(sol([0, 2, 4], 0).shape, (3, )) assert_equal(sol([0, 2, 4], [0, 1]).shape, (3, 2)) assert_equal(sol(2, [0, 1]).shape, (2, )) assert_raises(ValueError, sol, -1) assert_raises(ValueError, sol, [1, 4.00000001])
def test_events_and_infinity(): def event(t, y): return y[1] - 0.1 event.terminate = True for method in all_methods: sol = solve_ivp(lambda t, y: -y, [2, 3], 4, np.inf, method=method, events=event) assert_allclose(sol(sol.t_events[0])[1], 0.1)
def test_integration(): rtol = 1e-3 atol = 1e-6 y0 = [1/3, 2/9] with warnings.catch_warnings(): warnings.simplefilter('ignore') for vectorized, method, t_span, jac in product( [False, True], ['RK23', 'RK45', 'Radau', 'BDF'], [[5, 9], [5, 1]], [None, jac_rational, jac_rational_sparse]): if vectorized: fun = fun_rational_vectorized else: fun = fun_rational res = solve_ivp(fun, t_span, y0, rtol=rtol, atol=atol, method=method, dense_output=True, jac=jac, vectorized=vectorized) assert_equal(res.t[0], t_span[0]) assert_(res.t_events is None) assert_(res.success) assert_equal(res.status, 0) assert_(res.nfev < 40) if method in ['RK23', 'RK45']: assert_equal(res.njev, 0) assert_equal(res.nlu, 0) else: assert_(0 < res.njev < 3) assert_(0 < res.nlu < 10) y_true = sol_rational(res.t) e = compute_error(res.y, y_true, rtol, atol) assert_(np.all(e < 5)) tc = np.linspace(*t_span) yc_true = sol_rational(tc) yc = res.sol(tc) e = compute_error(yc, yc_true, rtol, atol) assert_(np.all(e < 5)) assert_allclose(res.sol(res.t), res.y, rtol=1e-15, atol=1e-15)
def test_integration(): rtol = 1e-3 atol = 1e-6 for method in all_methods: for x_span in ([5, 9], [5, 1]): res = solve_ivp(fun_rational, [1 / 3, 2 / 9], x_span[0], x_span[1], rtol=rtol, atol=atol, method=method) assert_equal(res.t0, x_span[0]) assert_equal(res.tF, x_span[-1]) assert_(res.t_events is None) xc = np.linspace(*x_span) yc_true = sol_rational(xc) yc = res(xc) assert_allclose(yc, yc_true, rtol=1e-2)
def test_max_step(): rtol = 1e-3 atol = 1e-6 y0 = [1/3, 2/9] for method in [RK23, RK45, Radau, BDF, LSODA]: for t_span in ([5, 9], [5, 1]): res = solve_ivp(fun_rational, t_span, y0, rtol=rtol, max_step=0.5, atol=atol, method=method, dense_output=True) assert_equal(res.t[0], t_span[0]) assert_equal(res.t[-1], t_span[-1]) assert_(np.all(np.abs(np.diff(res.t)) <= 0.5)) assert_(res.t_events is None) assert_(res.success) assert_equal(res.status, 0) y_true = sol_rational(res.t) e = compute_error(res.y, y_true, rtol, atol) assert_(np.all(e < 5)) tc = np.linspace(*t_span) yc_true = sol_rational(tc) yc = res.sol(tc) e = compute_error(yc, yc_true, rtol, atol) assert_(np.all(e < 5)) # See comment in test_integration. if method is not LSODA: assert_allclose(res.sol(res.t), res.y, rtol=1e-15, atol=1e-15) assert_raises(ValueError, method, fun_rational, t_span[0], y0, t_span[1], max_step=-1) if method is not LSODA: solver = method(fun_rational, t_span[0], y0, t_span[1], rtol=rtol, atol=atol, max_step=1e-20) message = solver.step() assert_equal(solver.status, 'failed') assert_("step size is less" in message) assert_raises(RuntimeError, solver.step)
def test_integration_sparse_difference(): n = 200 t_span = [0, 20] y0 = np.zeros(2 * n) y0[1::2] = 1 sparsity = medazko_sparsity(n) for method in ['BDF', 'Radau']: res = solve_ivp(fun_medazko, t_span, y0, method=method, jac_sparsity=sparsity) assert_equal(res.t[0], t_span[0]) assert_(res.t_events is None) assert_(res.success) assert_equal(res.status, 0) assert_allclose(res.y[78, -1], 0.233994e-3, rtol=1e-2) assert_allclose(res.y[79, -1], 0, atol=1e-3) assert_allclose(res.y[148, -1], 0.359561e-3, rtol=1e-2) assert_allclose(res.y[149, -1], 0, atol=1e-3) assert_allclose(res.y[198, -1], 0.117374129e-3, rtol=1e-2) assert_allclose(res.y[199, -1], 0.6190807e-5, atol=1e-3) assert_allclose(res.y[238, -1], 0, atol=1e-3) assert_allclose(res.y[239, -1], 0.9999997, rtol=1e-2)
def test_no_integration(): for method in ['RK23', 'RK45', 'Radau', 'BDF']: sol = solve_ivp(lambda t, y: -y, [4, 4], [2, 3], method=method, dense_output=True) assert_equal(sol.sol(4), [2, 3])
def test_events(): event_rational_3.terminal = True for method in ['RK23', 'RK45', 'Radau', 'BDF']: res = solve_ivp(fun_rational, [5, 8], [1/3, 2/9], method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.status, 0) assert_equal(res.t_events[0].size, 1) assert_equal(res.t_events[1].size, 1) assert_(5.3 < res.t_events[0][0] < 5.7) assert_(7.3 < res.t_events[1][0] < 7.7) event_rational_1.direction = 1 event_rational_2.direction = 1 res = solve_ivp(fun_rational, [5, 8], [1 / 3, 2 / 9], method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.status, 0) assert_equal(res.t_events[0].size, 1) assert_equal(res.t_events[1].size, 0) assert_(5.3 < res.t_events[0][0] < 5.7) event_rational_1.direction = -1 event_rational_2.direction = -1 res = solve_ivp(fun_rational, [5, 8], [1 / 3, 2 / 9], method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.status, 0) assert_equal(res.t_events[0].size, 0) assert_equal(res.t_events[1].size, 1) assert_(7.3 < res.t_events[1][0] < 7.7) event_rational_1.direction = 0 event_rational_2.direction = 0 res = solve_ivp(fun_rational, [5, 8], [1 / 3, 2 / 9], method=method, events=(event_rational_1, event_rational_2, event_rational_3), dense_output=True) assert_equal(res.status, 1) assert_equal(res.t_events[0].size, 1) assert_equal(res.t_events[1].size, 0) assert_equal(res.t_events[2].size, 1) assert_(5.3 < res.t_events[0][0] < 5.7) assert_(7.3 < res.t_events[2][0] < 7.5) # Also test that termination by event doesn't break interpolants. tc = np.linspace(res.t[0], res.t[-1]) yc_true = sol_rational(tc) yc = res.sol(tc) e = compute_error(yc, yc_true, 1e-3, 1e-6) assert_(np.all(e < 5)) # Test in backward direction. event_rational_1.direction = 0 event_rational_2.direction = 0 for method in ['RK23', 'RK45', 'Radau', 'BDF']: res = solve_ivp(fun_rational, [8, 5], [4/9, 20/81], method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.status, 0) assert_equal(res.t_events[0].size, 1) assert_equal(res.t_events[1].size, 1) assert_(5.3 < res.t_events[0][0] < 5.7) assert_(7.3 < res.t_events[1][0] < 7.7) event_rational_1.direction = -1 event_rational_2.direction = -1 res = solve_ivp(fun_rational, [8, 5], [4/9, 20/81], method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.status, 0) assert_equal(res.t_events[0].size, 1) assert_equal(res.t_events[1].size, 0) assert_(5.3 < res.t_events[0][0] < 5.7) event_rational_1.direction = 1 event_rational_2.direction = 1 res = solve_ivp(fun_rational, [8, 5], [4/9, 20/81], method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.status, 0) assert_equal(res.t_events[0].size, 0) assert_equal(res.t_events[1].size, 1) assert_(7.3 < res.t_events[1][0] < 7.7) event_rational_1.direction = 0 event_rational_2.direction = 0 res = solve_ivp(fun_rational, [8, 5], [4/9, 20/81], method=method, events=(event_rational_1, event_rational_2, event_rational_3), dense_output=True) assert_equal(res.status, 1) assert_equal(res.t_events[0].size, 0) assert_equal(res.t_events[1].size, 1) assert_equal(res.t_events[2].size, 1) assert_(7.3 < res.t_events[1][0] < 7.7) assert_(7.3 < res.t_events[2][0] < 7.5) # Also test that termination by event doesn't break interpolants. tc = np.linspace(res.t[-1], res.t[0]) yc_true = sol_rational(tc) yc = res.sol(tc) e = compute_error(yc, yc_true, 1e-3, 1e-6) assert_(np.all(e < 5))
def test_events(): event_rational_3.terminate = True for method in all_methods: res = solve_ivp(fun_rational, [1 / 3, 2 / 9], 5, 8, method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.tF, 8) assert_equal(len(res.t_events[0]), 1) assert_equal(len(res.t_events[1]), 1) assert_(5.3 < res.t_events[0][0] < 5.7) assert_(7.3 < res.t_events[1][0] < 7.7) event_rational_1.direction = 1 event_rational_2.direction = 1 res = solve_ivp(fun_rational, [1 / 3, 2 / 9], 5, 8, method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.tF, 8) assert_equal(len(res.t_events[0]), 1) assert_equal(len(res.t_events[1]), 0) assert_(5.3 < res.t_events[0][0] < 5.7) event_rational_1.direction = -1 event_rational_2.direction = -1 res = solve_ivp(fun_rational, [1 / 3, 2 / 9], 5, 8, method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.tF, 8) assert_equal(len(res.t_events[0]), 0) assert_equal(len(res.t_events[1]), 1) assert_(7.3 < res.t_events[1][0] < 7.7) event_rational_1.direction = 0 event_rational_2.direction = 0 res = solve_ivp(fun_rational, [1 / 3, 2 / 9], 5, 8, method=method, events=(event_rational_1, event_rational_2, event_rational_3)) assert_allclose(res.tF, 7.4) assert_equal(len(res.t_events[0]), 1) assert_equal(len(res.t_events[1]), 0) assert_equal(len(res.t_events[2]), 1) assert_(5.3 < res.t_events[0][0] < 5.7) assert_(7.3 < res.t_events[2][0] < 7.5) # Also test that termination by event doesn't break interpolants. xc = np.linspace(res.t0, res.tF) yc_true = sol_rational(xc) yc = res(xc) assert_allclose(yc, yc_true, rtol=1e-2) # Test in backward direction. event_rational_1.direction = 0 event_rational_2.direction = 0 for method in all_methods: res = solve_ivp(fun_rational, [4 / 9, 20 / 81], 8, 5, method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.tF, 5) assert_equal(len(res.t_events[0]), 1) assert_equal(len(res.t_events[1]), 1) assert_(5.3 < res.t_events[0][0] < 5.7) assert_(7.3 < res.t_events[1][0] < 7.7) event_rational_1.direction = -1 event_rational_2.direction = -1 res = solve_ivp(fun_rational, [4 / 9, 20 / 81], 8, 5, method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.tF, 5) assert_equal(len(res.t_events[0]), 1) assert_equal(len(res.t_events[1]), 0) assert_(5.3 < res.t_events[0][0] < 5.7) event_rational_1.direction = 1 event_rational_2.direction = 1 res = solve_ivp(fun_rational, [4 / 9, 20 / 81], 8, 5, method=method, events=(event_rational_1, event_rational_2)) assert_equal(res.tF, 5) assert_equal(len(res.t_events[0]), 0) assert_equal(len(res.t_events[1]), 1) assert_(7.3 < res.t_events[1][0] < 7.7) event_rational_1.direction = 0 event_rational_2.direction = 0 res = solve_ivp(fun_rational, [4 / 9, 20 / 81], 8, 5, method=method, events=(event_rational_1, event_rational_2, event_rational_3)) assert_allclose(res.tF, 7.4) assert_equal(len(res.t_events[0]), 0) assert_equal(len(res.t_events[1]), 1) assert_equal(len(res.t_events[2]), 1) assert_(7.3 < res.t_events[1][0] < 7.7) assert_(7.3 < res.t_events[2][0] < 7.5) # Also test that termination by event doesn't break interpolants. xc = np.linspace(res.t0, res.tF) yc_true = sol_rational(xc) yc = res(xc) assert_allclose(yc, yc_true, rtol=1e-2)
def test_no_integration(): for method in all_methods: sol = solve_ivp(lambda t, y: -y, [2, 3], 4, 4, method=method) assert_equal(sol(4), [2, 3]) assert_equal(sol([4, 4, 4]), [[2, 3], [2, 3], [2, 3]])