| |
| """ |
| Tests for numerical integration. |
| """ |
| import numpy as np |
| from numpy import (arange, zeros, array, dot, sqrt, cos, sin, eye, pi, exp, |
| allclose) |
|
|
| from numpy.testing import ( |
| assert_, assert_array_almost_equal, |
| assert_allclose, assert_array_equal, assert_equal, assert_warns) |
| import pytest |
| from pytest import raises as assert_raises |
| from scipy.integrate import odeint, ode, complex_ode |
|
|
| |
| |
| |
|
|
|
|
| class TestOdeint: |
| |
|
|
| def _do_problem(self, problem): |
| t = arange(0.0, problem.stop_t, 0.05) |
|
|
| |
| z, infodict = odeint(problem.f, problem.z0, t, full_output=True) |
| assert_(problem.verify(z, t)) |
|
|
| |
| z, infodict = odeint(lambda t, y: problem.f(y, t), problem.z0, t, |
| full_output=True, tfirst=True) |
| assert_(problem.verify(z, t)) |
|
|
| if hasattr(problem, 'jac'): |
| |
| z, infodict = odeint(problem.f, problem.z0, t, Dfun=problem.jac, |
| full_output=True) |
| assert_(problem.verify(z, t)) |
|
|
| |
| z, infodict = odeint(lambda t, y: problem.f(y, t), problem.z0, t, |
| Dfun=lambda t, y: problem.jac(y, t), |
| full_output=True, tfirst=True) |
| assert_(problem.verify(z, t)) |
|
|
| def test_odeint(self): |
| for problem_cls in PROBLEMS: |
| problem = problem_cls() |
| if problem.cmplx: |
| continue |
| self._do_problem(problem) |
|
|
|
|
| class TestODEClass: |
|
|
| ode_class = None |
|
|
| def _do_problem(self, problem, integrator, method='adams'): |
|
|
| |
| def f(t, z): |
| return problem.f(z, t) |
| jac = None |
| if hasattr(problem, 'jac'): |
| def jac(t, z): |
| return problem.jac(z, t) |
|
|
| integrator_params = {} |
| if problem.lband is not None or problem.uband is not None: |
| integrator_params['uband'] = problem.uband |
| integrator_params['lband'] = problem.lband |
|
|
| ig = self.ode_class(f, jac) |
| ig.set_integrator(integrator, |
| atol=problem.atol/10, |
| rtol=problem.rtol/10, |
| method=method, |
| **integrator_params) |
|
|
| ig.set_initial_value(problem.z0, t=0.0) |
| z = ig.integrate(problem.stop_t) |
|
|
| assert_array_equal(z, ig.y) |
| assert_(ig.successful(), (problem, method)) |
| assert_(ig.get_return_code() > 0, (problem, method)) |
| assert_(problem.verify(array([z]), problem.stop_t), (problem, method)) |
|
|
|
|
| class TestOde(TestODEClass): |
|
|
| ode_class = ode |
|
|
| def test_vode(self): |
| |
| for problem_cls in PROBLEMS: |
| problem = problem_cls() |
| if problem.cmplx: |
| continue |
| if not problem.stiff: |
| self._do_problem(problem, 'vode', 'adams') |
| self._do_problem(problem, 'vode', 'bdf') |
|
|
| def test_zvode(self): |
| |
| for problem_cls in PROBLEMS: |
| problem = problem_cls() |
| if not problem.stiff: |
| self._do_problem(problem, 'zvode', 'adams') |
| self._do_problem(problem, 'zvode', 'bdf') |
|
|
| def test_lsoda(self): |
| |
| for problem_cls in PROBLEMS: |
| problem = problem_cls() |
| if problem.cmplx: |
| continue |
| self._do_problem(problem, 'lsoda') |
|
|
| def test_dopri5(self): |
| |
| for problem_cls in PROBLEMS: |
| problem = problem_cls() |
| if problem.cmplx: |
| continue |
| if problem.stiff: |
| continue |
| if hasattr(problem, 'jac'): |
| continue |
| self._do_problem(problem, 'dopri5') |
|
|
| def test_dop853(self): |
| |
| for problem_cls in PROBLEMS: |
| problem = problem_cls() |
| if problem.cmplx: |
| continue |
| if problem.stiff: |
| continue |
| if hasattr(problem, 'jac'): |
| continue |
| self._do_problem(problem, 'dop853') |
|
|
| @pytest.mark.thread_unsafe |
| def test_concurrent_fail(self): |
| for sol in ('vode', 'zvode', 'lsoda'): |
| def f(t, y): |
| return 1.0 |
|
|
| r = ode(f).set_integrator(sol) |
| r.set_initial_value(0, 0) |
|
|
| r2 = ode(f).set_integrator(sol) |
| r2.set_initial_value(0, 0) |
|
|
| r.integrate(r.t + 0.1) |
| r2.integrate(r2.t + 0.1) |
|
|
| assert_raises(RuntimeError, r.integrate, r.t + 0.1) |
|
|
| def test_concurrent_ok(self, num_parallel_threads): |
| def f(t, y): |
| return 1.0 |
|
|
| for k in range(3): |
| for sol in ('vode', 'zvode', 'lsoda', 'dopri5', 'dop853'): |
| if sol in {'vode', 'zvode', 'lsoda'} and num_parallel_threads > 1: |
| continue |
| r = ode(f).set_integrator(sol) |
| r.set_initial_value(0, 0) |
|
|
| r2 = ode(f).set_integrator(sol) |
| r2.set_initial_value(0, 0) |
|
|
| r.integrate(r.t + 0.1) |
| r2.integrate(r2.t + 0.1) |
| r2.integrate(r2.t + 0.1) |
|
|
| assert_allclose(r.y, 0.1) |
| assert_allclose(r2.y, 0.2) |
|
|
| for sol in ('dopri5', 'dop853'): |
| r = ode(f).set_integrator(sol) |
| r.set_initial_value(0, 0) |
|
|
| r2 = ode(f).set_integrator(sol) |
| r2.set_initial_value(0, 0) |
|
|
| r.integrate(r.t + 0.1) |
| r.integrate(r.t + 0.1) |
| r2.integrate(r2.t + 0.1) |
| r.integrate(r.t + 0.1) |
| r2.integrate(r2.t + 0.1) |
|
|
| assert_allclose(r.y, 0.3) |
| assert_allclose(r2.y, 0.2) |
|
|
|
|
| class TestComplexOde(TestODEClass): |
|
|
| ode_class = complex_ode |
|
|
| def test_vode(self): |
| |
| for problem_cls in PROBLEMS: |
| problem = problem_cls() |
| if not problem.stiff: |
| self._do_problem(problem, 'vode', 'adams') |
| else: |
| self._do_problem(problem, 'vode', 'bdf') |
|
|
| def test_lsoda(self): |
|
|
| |
| for problem_cls in PROBLEMS: |
| problem = problem_cls() |
| self._do_problem(problem, 'lsoda') |
|
|
| def test_dopri5(self): |
| |
| for problem_cls in PROBLEMS: |
| problem = problem_cls() |
| if problem.stiff: |
| continue |
| if hasattr(problem, 'jac'): |
| continue |
| self._do_problem(problem, 'dopri5') |
|
|
| def test_dop853(self): |
| |
| for problem_cls in PROBLEMS: |
| problem = problem_cls() |
| if problem.stiff: |
| continue |
| if hasattr(problem, 'jac'): |
| continue |
| self._do_problem(problem, 'dop853') |
|
|
|
|
| class TestSolout: |
| |
| def _run_solout_test(self, integrator): |
| |
| ts = [] |
| ys = [] |
| t0 = 0.0 |
| tend = 10.0 |
| y0 = [1.0, 2.0] |
|
|
| def solout(t, y): |
| ts.append(t) |
| ys.append(y.copy()) |
|
|
| def rhs(t, y): |
| return [y[0] + y[1], -y[1]**2] |
|
|
| ig = ode(rhs).set_integrator(integrator) |
| ig.set_solout(solout) |
| ig.set_initial_value(y0, t0) |
| ret = ig.integrate(tend) |
| assert_array_equal(ys[0], y0) |
| assert_array_equal(ys[-1], ret) |
| assert_equal(ts[0], t0) |
| assert_equal(ts[-1], tend) |
|
|
| def test_solout(self): |
| for integrator in ('dopri5', 'dop853'): |
| self._run_solout_test(integrator) |
|
|
| def _run_solout_after_initial_test(self, integrator): |
| |
| ts = [] |
| ys = [] |
| t0 = 0.0 |
| tend = 10.0 |
| y0 = [1.0, 2.0] |
|
|
| def solout(t, y): |
| ts.append(t) |
| ys.append(y.copy()) |
|
|
| def rhs(t, y): |
| return [y[0] + y[1], -y[1]**2] |
|
|
| ig = ode(rhs).set_integrator(integrator) |
| ig.set_initial_value(y0, t0) |
| ig.set_solout(solout) |
| ret = ig.integrate(tend) |
| assert_array_equal(ys[0], y0) |
| assert_array_equal(ys[-1], ret) |
| assert_equal(ts[0], t0) |
| assert_equal(ts[-1], tend) |
|
|
| def test_solout_after_initial(self): |
| for integrator in ('dopri5', 'dop853'): |
| self._run_solout_after_initial_test(integrator) |
|
|
| def _run_solout_break_test(self, integrator): |
| |
| ts = [] |
| ys = [] |
| t0 = 0.0 |
| tend = 10.0 |
| y0 = [1.0, 2.0] |
|
|
| def solout(t, y): |
| ts.append(t) |
| ys.append(y.copy()) |
| if t > tend/2.0: |
| return -1 |
|
|
| def rhs(t, y): |
| return [y[0] + y[1], -y[1]**2] |
|
|
| ig = ode(rhs).set_integrator(integrator) |
| ig.set_solout(solout) |
| ig.set_initial_value(y0, t0) |
| ret = ig.integrate(tend) |
| assert_array_equal(ys[0], y0) |
| assert_array_equal(ys[-1], ret) |
| assert_equal(ts[0], t0) |
| assert_(ts[-1] > tend/2.0) |
| assert_(ts[-1] < tend) |
|
|
| def test_solout_break(self): |
| for integrator in ('dopri5', 'dop853'): |
| self._run_solout_break_test(integrator) |
|
|
|
|
| class TestComplexSolout: |
| |
| def _run_solout_test(self, integrator): |
| |
| ts = [] |
| ys = [] |
| t0 = 0.0 |
| tend = 20.0 |
| y0 = [0.0] |
|
|
| def solout(t, y): |
| ts.append(t) |
| ys.append(y.copy()) |
|
|
| def rhs(t, y): |
| return [1.0/(t - 10.0 - 1j)] |
|
|
| ig = complex_ode(rhs).set_integrator(integrator) |
| ig.set_solout(solout) |
| ig.set_initial_value(y0, t0) |
| ret = ig.integrate(tend) |
| assert_array_equal(ys[0], y0) |
| assert_array_equal(ys[-1], ret) |
| assert_equal(ts[0], t0) |
| assert_equal(ts[-1], tend) |
|
|
| def test_solout(self): |
| for integrator in ('dopri5', 'dop853'): |
| self._run_solout_test(integrator) |
|
|
| def _run_solout_break_test(self, integrator): |
| |
| ts = [] |
| ys = [] |
| t0 = 0.0 |
| tend = 20.0 |
| y0 = [0.0] |
|
|
| def solout(t, y): |
| ts.append(t) |
| ys.append(y.copy()) |
| if t > tend/2.0: |
| return -1 |
|
|
| def rhs(t, y): |
| return [1.0/(t - 10.0 - 1j)] |
|
|
| ig = complex_ode(rhs).set_integrator(integrator) |
| ig.set_solout(solout) |
| ig.set_initial_value(y0, t0) |
| ret = ig.integrate(tend) |
| assert_array_equal(ys[0], y0) |
| assert_array_equal(ys[-1], ret) |
| assert_equal(ts[0], t0) |
| assert_(ts[-1] > tend/2.0) |
| assert_(ts[-1] < tend) |
|
|
| def test_solout_break(self): |
| for integrator in ('dopri5', 'dop853'): |
| self._run_solout_break_test(integrator) |
|
|
|
|
| |
| |
| |
|
|
|
|
| class ODE: |
| """ |
| ODE problem |
| """ |
| stiff = False |
| cmplx = False |
| stop_t = 1 |
| z0 = [] |
|
|
| lband = None |
| uband = None |
|
|
| atol = 1e-6 |
| rtol = 1e-5 |
|
|
|
|
| class SimpleOscillator(ODE): |
| r""" |
| Free vibration of a simple oscillator:: |
| m \ddot{u} + k u = 0, u(0) = u_0 \dot{u}(0) \dot{u}_0 |
| Solution:: |
| u(t) = u_0*cos(sqrt(k/m)*t)+\dot{u}_0*sin(sqrt(k/m)*t)/sqrt(k/m) |
| """ |
| stop_t = 1 + 0.09 |
| z0 = array([1.0, 0.1], float) |
|
|
| k = 4.0 |
| m = 1.0 |
|
|
| def f(self, z, t): |
| tmp = zeros((2, 2), float) |
| tmp[0, 1] = 1.0 |
| tmp[1, 0] = -self.k / self.m |
| return dot(tmp, z) |
|
|
| def verify(self, zs, t): |
| omega = sqrt(self.k / self.m) |
| u = self.z0[0]*cos(omega*t) + self.z0[1]*sin(omega*t)/omega |
| return allclose(u, zs[:, 0], atol=self.atol, rtol=self.rtol) |
|
|
|
|
| class ComplexExp(ODE): |
| r"""The equation :lm:`\dot u = i u`""" |
| stop_t = 1.23*pi |
| z0 = exp([1j, 2j, 3j, 4j, 5j]) |
| cmplx = True |
|
|
| def f(self, z, t): |
| return 1j*z |
|
|
| def jac(self, z, t): |
| return 1j*eye(5) |
|
|
| def verify(self, zs, t): |
| u = self.z0 * exp(1j*t) |
| return allclose(u, zs, atol=self.atol, rtol=self.rtol) |
|
|
|
|
| class Pi(ODE): |
| r"""Integrate 1/(t + 1j) from t=-10 to t=10""" |
| stop_t = 20 |
| z0 = [0] |
| cmplx = True |
|
|
| def f(self, z, t): |
| return array([1./(t - 10 + 1j)]) |
|
|
| def verify(self, zs, t): |
| u = -2j * np.arctan(10) |
| return allclose(u, zs[-1, :], atol=self.atol, rtol=self.rtol) |
|
|
|
|
| class CoupledDecay(ODE): |
| r""" |
| 3 coupled decays suited for banded treatment |
| (banded mode makes it necessary when N>>3) |
| """ |
|
|
| stiff = True |
| stop_t = 0.5 |
| z0 = [5.0, 7.0, 13.0] |
| lband = 1 |
| uband = 0 |
|
|
| lmbd = [0.17, 0.23, 0.29] |
|
|
| def f(self, z, t): |
| lmbd = self.lmbd |
| return np.array([-lmbd[0]*z[0], |
| -lmbd[1]*z[1] + lmbd[0]*z[0], |
| -lmbd[2]*z[2] + lmbd[1]*z[1]]) |
|
|
| def jac(self, z, t): |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| lmbd = self.lmbd |
| j = np.zeros((self.lband + self.uband + 1, 3), order='F') |
|
|
| def set_j(ri, ci, val): |
| j[self.uband + ri - ci, ci] = val |
| set_j(0, 0, -lmbd[0]) |
| set_j(1, 0, lmbd[0]) |
| set_j(1, 1, -lmbd[1]) |
| set_j(2, 1, lmbd[1]) |
| set_j(2, 2, -lmbd[2]) |
| return j |
|
|
| def verify(self, zs, t): |
| |
| lmbd = np.array(self.lmbd) |
| d10 = lmbd[1] - lmbd[0] |
| d21 = lmbd[2] - lmbd[1] |
| d20 = lmbd[2] - lmbd[0] |
| e0 = np.exp(-lmbd[0] * t) |
| e1 = np.exp(-lmbd[1] * t) |
| e2 = np.exp(-lmbd[2] * t) |
| u = np.vstack(( |
| self.z0[0] * e0, |
| self.z0[1] * e1 + self.z0[0] * lmbd[0] / d10 * (e0 - e1), |
| self.z0[2] * e2 + self.z0[1] * lmbd[1] / d21 * (e1 - e2) + |
| lmbd[1] * lmbd[0] * self.z0[0] / d10 * |
| (1 / d20 * (e0 - e2) - 1 / d21 * (e1 - e2)))).transpose() |
| return allclose(u, zs, atol=self.atol, rtol=self.rtol) |
|
|
|
|
| PROBLEMS = [SimpleOscillator, ComplexExp, Pi, CoupledDecay] |
|
|
| |
|
|
|
|
| def f(t, x): |
| dxdt = [x[1], -x[0]] |
| return dxdt |
|
|
|
|
| def jac(t, x): |
| j = array([[0.0, 1.0], |
| [-1.0, 0.0]]) |
| return j |
|
|
|
|
| def f1(t, x, omega): |
| dxdt = [omega*x[1], -omega*x[0]] |
| return dxdt |
|
|
|
|
| def jac1(t, x, omega): |
| j = array([[0.0, omega], |
| [-omega, 0.0]]) |
| return j |
|
|
|
|
| def f2(t, x, omega1, omega2): |
| dxdt = [omega1*x[1], -omega2*x[0]] |
| return dxdt |
|
|
|
|
| def jac2(t, x, omega1, omega2): |
| j = array([[0.0, omega1], |
| [-omega2, 0.0]]) |
| return j |
|
|
|
|
| def fv(t, x, omega): |
| dxdt = [omega[0]*x[1], -omega[1]*x[0]] |
| return dxdt |
|
|
|
|
| def jacv(t, x, omega): |
| j = array([[0.0, omega[0]], |
| [-omega[1], 0.0]]) |
| return j |
|
|
|
|
| class ODECheckParameterUse: |
| """Call an ode-class solver with several cases of parameter use.""" |
|
|
| |
|
|
| |
| solver_name = '' |
| solver_uses_jac = False |
|
|
| def _get_solver(self, f, jac): |
| solver = ode(f, jac) |
| if self.solver_uses_jac: |
| solver.set_integrator(self.solver_name, atol=1e-9, rtol=1e-7, |
| with_jacobian=self.solver_uses_jac) |
| else: |
| |
| |
| |
| solver.set_integrator(self.solver_name, atol=1e-9, rtol=1e-7) |
| return solver |
|
|
| def _check_solver(self, solver): |
| ic = [1.0, 0.0] |
| solver.set_initial_value(ic, 0.0) |
| solver.integrate(pi) |
| assert_array_almost_equal(solver.y, [-1.0, 0.0]) |
|
|
| def test_no_params(self): |
| solver = self._get_solver(f, jac) |
| self._check_solver(solver) |
|
|
| def test_one_scalar_param(self): |
| solver = self._get_solver(f1, jac1) |
| omega = 1.0 |
| solver.set_f_params(omega) |
| if self.solver_uses_jac: |
| solver.set_jac_params(omega) |
| self._check_solver(solver) |
|
|
| def test_two_scalar_params(self): |
| solver = self._get_solver(f2, jac2) |
| omega1 = 1.0 |
| omega2 = 1.0 |
| solver.set_f_params(omega1, omega2) |
| if self.solver_uses_jac: |
| solver.set_jac_params(omega1, omega2) |
| self._check_solver(solver) |
|
|
| def test_vector_param(self): |
| solver = self._get_solver(fv, jacv) |
| omega = [1.0, 1.0] |
| solver.set_f_params(omega) |
| if self.solver_uses_jac: |
| solver.set_jac_params(omega) |
| self._check_solver(solver) |
|
|
| @pytest.mark.thread_unsafe |
| def test_warns_on_failure(self): |
| |
| solver = self._get_solver(f, jac) |
| solver.set_integrator(self.solver_name, nsteps=1) |
| ic = [1.0, 0.0] |
| solver.set_initial_value(ic, 0.0) |
| assert_warns(UserWarning, solver.integrate, pi) |
|
|
|
|
| class TestDOPRI5CheckParameterUse(ODECheckParameterUse): |
| solver_name = 'dopri5' |
| solver_uses_jac = False |
|
|
|
|
| class TestDOP853CheckParameterUse(ODECheckParameterUse): |
| solver_name = 'dop853' |
| solver_uses_jac = False |
|
|
|
|
| class TestVODECheckParameterUse(ODECheckParameterUse): |
| solver_name = 'vode' |
| solver_uses_jac = True |
|
|
|
|
| class TestZVODECheckParameterUse(ODECheckParameterUse): |
| solver_name = 'zvode' |
| solver_uses_jac = True |
|
|
|
|
| class TestLSODACheckParameterUse(ODECheckParameterUse): |
| solver_name = 'lsoda' |
| solver_uses_jac = True |
|
|
|
|
| def test_odeint_trivial_time(): |
| |
| |
| y0 = 1 |
| t = [0] |
| y, info = odeint(lambda y, t: -y, y0, t, full_output=True) |
| assert_array_equal(y, np.array([[y0]])) |
|
|
|
|
| def test_odeint_banded_jacobian(): |
| |
|
|
| def func(y, t, c): |
| return c.dot(y) |
|
|
| def jac(y, t, c): |
| return c |
|
|
| def jac_transpose(y, t, c): |
| return c.T.copy(order='C') |
|
|
| def bjac_rows(y, t, c): |
| jac = np.vstack((np.r_[0, np.diag(c, 1)], |
| np.diag(c), |
| np.r_[np.diag(c, -1), 0], |
| np.r_[np.diag(c, -2), 0, 0])) |
| return jac |
|
|
| def bjac_cols(y, t, c): |
| return bjac_rows(y, t, c).T.copy(order='C') |
|
|
| c = array([[-205, 0.01, 0.00, 0.0], |
| [0.1, -2.50, 0.02, 0.0], |
| [1e-3, 0.01, -2.0, 0.01], |
| [0.00, 0.00, 0.1, -1.0]]) |
|
|
| y0 = np.ones(4) |
| t = np.array([0, 5, 10, 100]) |
|
|
| |
| sol1, info1 = odeint(func, y0, t, args=(c,), full_output=True, |
| atol=1e-13, rtol=1e-11, mxstep=10000, |
| Dfun=jac) |
|
|
| |
| sol2, info2 = odeint(func, y0, t, args=(c,), full_output=True, |
| atol=1e-13, rtol=1e-11, mxstep=10000, |
| Dfun=jac_transpose, col_deriv=True) |
|
|
| |
| sol3, info3 = odeint(func, y0, t, args=(c,), full_output=True, |
| atol=1e-13, rtol=1e-11, mxstep=10000, |
| Dfun=bjac_rows, ml=2, mu=1) |
|
|
| |
| sol4, info4 = odeint(func, y0, t, args=(c,), full_output=True, |
| atol=1e-13, rtol=1e-11, mxstep=10000, |
| Dfun=bjac_cols, ml=2, mu=1, col_deriv=True) |
|
|
| assert_allclose(sol1, sol2, err_msg="sol1 != sol2") |
| assert_allclose(sol1, sol3, atol=1e-12, err_msg="sol1 != sol3") |
| assert_allclose(sol3, sol4, err_msg="sol3 != sol4") |
|
|
| |
| |
| |
| |
| |
| assert_array_equal(info1['nje'], info2['nje']) |
| assert_array_equal(info3['nje'], info4['nje']) |
|
|
| |
| sol1ty, info1ty = odeint(lambda t, y, c: func(y, t, c), y0, t, args=(c,), |
| full_output=True, atol=1e-13, rtol=1e-11, |
| mxstep=10000, |
| Dfun=lambda t, y, c: jac(y, t, c), tfirst=True) |
| |
| |
| |
| assert_allclose(sol1, sol1ty, rtol=1e-12, err_msg="sol1 != sol1ty") |
|
|
|
|
| def test_odeint_errors(): |
| def sys1d(x, t): |
| return -100*x |
|
|
| def bad1(x, t): |
| return 1.0/0 |
|
|
| def bad2(x, t): |
| return "foo" |
|
|
| def bad_jac1(x, t): |
| return 1.0/0 |
|
|
| def bad_jac2(x, t): |
| return [["foo"]] |
|
|
| def sys2d(x, t): |
| return [-100*x[0], -0.1*x[1]] |
|
|
| def sys2d_bad_jac(x, t): |
| return [[1.0/0, 0], [0, -0.1]] |
|
|
| assert_raises(ZeroDivisionError, odeint, bad1, 1.0, [0, 1]) |
| assert_raises(ValueError, odeint, bad2, 1.0, [0, 1]) |
|
|
| assert_raises(ZeroDivisionError, odeint, sys1d, 1.0, [0, 1], Dfun=bad_jac1) |
| assert_raises(ValueError, odeint, sys1d, 1.0, [0, 1], Dfun=bad_jac2) |
|
|
| assert_raises(ZeroDivisionError, odeint, sys2d, [1.0, 1.0], [0, 1], |
| Dfun=sys2d_bad_jac) |
|
|
|
|
| def test_odeint_bad_shapes(): |
| |
|
|
| def badrhs(x, t): |
| return [1, -1] |
|
|
| def sys1(x, t): |
| return -100*x |
|
|
| def badjac(x, t): |
| return [[0, 0, 0]] |
|
|
| |
| bad_y0 = [[0, 0], [0, 0]] |
| assert_raises(ValueError, odeint, sys1, bad_y0, [0, 1]) |
|
|
| |
| bad_t = [[0, 1], [2, 3]] |
| assert_raises(ValueError, odeint, sys1, [10.0], bad_t) |
|
|
| |
| assert_raises(RuntimeError, odeint, badrhs, 10, [0, 1]) |
|
|
| |
| assert_raises(RuntimeError, odeint, sys1, [10, 10], [0, 1], Dfun=badjac) |
|
|
|
|
| def test_repeated_t_values(): |
| """Regression test for gh-8217.""" |
|
|
| def func(x, t): |
| return -0.25*x |
|
|
| t = np.zeros(10) |
| sol = odeint(func, [1.], t) |
| assert_array_equal(sol, np.ones((len(t), 1))) |
|
|
| tau = 4*np.log(2) |
| t = [0]*9 + [tau, 2*tau, 2*tau, 3*tau] |
| sol = odeint(func, [1, 2], t, rtol=1e-12, atol=1e-12) |
| expected_sol = np.array([[1.0, 2.0]]*9 + |
| [[0.5, 1.0], |
| [0.25, 0.5], |
| [0.25, 0.5], |
| [0.125, 0.25]]) |
| assert_allclose(sol, expected_sol) |
|
|
| |
| sol = odeint(func, [1.], []) |
| assert_array_equal(sol, np.array([], dtype=np.float64).reshape((0, 1))) |
|
|
| |
| assert_raises(ValueError, odeint, func, [1.], [0, 1, 0.5, 0]) |
| assert_raises(ValueError, odeint, func, [1, 2, 3], [0, -1, -2, 3]) |
|
|