Example #1
0
    def test_base_solver_init(self):
        solver = pybamm.BaseSolver(rtol=1e-2, atol=1e-4)
        self.assertEqual(solver.rtol, 1e-2)
        self.assertEqual(solver.atol, 1e-4)

        solver.rtol = 1e-5
        self.assertEqual(solver.rtol, 1e-5)
        solver.rtol = 1e-7
        self.assertEqual(solver.rtol, 1e-7)

        # max_steps deprecated
        with self.assertRaisesRegex(ValueError, "max_steps has been deprecated"):
            pybamm.BaseSolver(max_steps=10)
Example #2
0
    def test_root_method_init(self):
        solver = pybamm.BaseSolver(root_method="casadi")
        self.assertIsInstance(solver.root_method, pybamm.CasadiAlgebraicSolver)

        solver = pybamm.BaseSolver(root_method="lm")
        self.assertIsInstance(solver.root_method, pybamm.AlgebraicSolver)
        self.assertEqual(solver.root_method.method, "lm")

        root_solver = pybamm.AlgebraicSolver()
        solver = pybamm.BaseSolver(root_method=root_solver)
        self.assertEqual(solver.root_method, root_solver)

        with self.assertRaisesRegex(pybamm.SolverError,
                                    "Root method must be an algebraic solver"):
            pybamm.BaseSolver(root_method=pybamm.ScipySolver())
Example #3
0
 def test_step_or_solve_empty_model(self):
     model = pybamm.BaseModel()
     solver = pybamm.BaseSolver()
     with self.assertRaisesRegex(pybamm.ModelError, "Cannot step empty model"):
         solver.step(None, model, None)
     with self.assertRaisesRegex(pybamm.ModelError, "Cannot solve empty model"):
         solver.solve(model, None)
Example #4
0
 def test_nonmonotonic_teval(self):
     solver = pybamm.BaseSolver(rtol=1e-2, atol=1e-4)
     model = pybamm.BaseModel()
     a = pybamm.Scalar(0)
     model.rhs = {a: a}
     with self.assertRaisesRegex(pybamm.SolverError,
                                 "t_eval must increase monotonically"):
         solver.solve(model, np.array([1, 2, 3, 2]))
Example #5
0
    def test_base_solver_init(self):
        solver = pybamm.BaseSolver(rtol=1e-2, atol=1e-4)
        self.assertEqual(solver.rtol, 1e-2)
        self.assertEqual(solver.atol, 1e-4)

        solver.rtol = 1e-5
        self.assertEqual(solver.rtol, 1e-5)
        solver.rtol = 1e-7
        self.assertEqual(solver.rtol, 1e-7)
Example #6
0
 def test_time_too_short(self):
     solver = pybamm.BaseSolver()
     model = pybamm.BaseModel()
     v = pybamm.StateVector(slice(0, 1))
     model.rhs = {v: v}
     with self.assertRaisesRegex(
             pybamm.SolverError,
             "It looks like t_eval might be dimensionless"):
         solver.solve(model, np.linspace(0, 0.1))
Example #7
0
 def test_block_symbolic_inputs(self):
     solver = pybamm.BaseSolver(rtol=1e-2, atol=1e-4)
     model = pybamm.BaseModel()
     a = pybamm.Scalar(0)
     p = pybamm.InputParameter("p")
     model.rhs = {a: a * p}
     with self.assertRaisesRegex(
         pybamm.SolverError, "Only CasadiAlgebraicSolver can have symbolic inputs"
     ):
         solver.solve(model, np.array([1, 2, 3]))
Example #8
0
    def test_t_eval_none(self):
        model = pybamm.BaseModel()
        v = pybamm.Variable("v")
        model.rhs = {v: 1}
        model.initial_conditions = {v: 1}
        disc = pybamm.Discretisation()
        disc.process_model(model)

        solver = pybamm.BaseSolver()
        with self.assertRaisesRegex(ValueError, "t_eval cannot be None"):
            solver.solve(model, None)
Example #9
0
 def test_timescale_input_fail(self):
     # Make sure timescale can't depend on inputs
     model = pybamm.BaseModel()
     v = pybamm.Variable("v")
     model.rhs = {v: -1}
     model.initial_conditions = {v: 1}
     a = pybamm.InputParameter("a")
     model.timescale = a
     solver = pybamm.BaseSolver()
     with self.assertRaisesRegex(pybamm.SolverError, "The model timescale"):
         solver.set_up(model, inputs={"a": 10})
Example #10
0
    def test_fail_consistent_initial_conditions(self):
        class Model:
            def __init__(self):
                self.y0 = np.array([2])
                self.rhs = {}
                self.jac_algebraic_eval = None
                self.timescale_eval = 1
                t = casadi.MX.sym("t")
                y = casadi.MX.sym("y")
                p = casadi.MX.sym("p")
                self.casadi_algebraic = casadi.Function(
                    "alg", [t, y, p], [self.algebraic_eval(t, y, p)]
                )
                self.convert_to_format = "casadi"

            def rhs_eval(self, t, y, inputs):
                return np.array([])

            def algebraic_eval(self, t, y, inputs):
                # algebraic equation has no root
                return y ** 2 + 1

        solver = pybamm.BaseSolver(root_method="hybr")

        with self.assertRaisesRegex(
            pybamm.SolverError,
            "Could not find acceptable solution: The iteration is not making",
        ):
            solver.calculate_consistent_state(Model())
        solver = pybamm.BaseSolver(root_method="lm")
        with self.assertRaisesRegex(
            pybamm.SolverError, "Could not find acceptable solution: solver terminated"
        ):
            solver.calculate_consistent_state(Model())
        # with casadi
        solver = pybamm.BaseSolver(root_method="casadi")
        with self.assertRaisesRegex(
            pybamm.SolverError, "Could not find acceptable solution: .../casadi"
        ):
            solver.calculate_consistent_state(Model())
Example #11
0
    def test_fail_consistent_initial_conditions(self):
        class Model:
            def __init__(self):
                self.concatenated_initial_conditions = np.array([2])
                self.jac_algebraic_eval = None
                self.timescale = 1
                t = casadi.MX.sym("t")
                y = casadi.MX.sym("y")
                u = casadi.MX.sym("u")
                self.casadi_algebraic = casadi.Function(
                    "alg", [t, y, u], [self.algebraic_eval(t, y)])

            def rhs_eval(self, t, y):
                return np.array([])

            def algebraic_eval(self, t, y):
                # algebraic equation has no root
                return y**2 + 1

        solver = pybamm.BaseSolver(root_method="hybr")

        with self.assertRaisesRegex(
                pybamm.SolverError,
                "Could not find consistent initial conditions: The iteration is not making",
        ):
            solver.calculate_consistent_state(Model())
        solver = pybamm.BaseSolver(root_method="lm")
        with self.assertRaisesRegex(
                pybamm.SolverError,
                "Could not find consistent initial conditions: solver terminated",
        ):
            solver.calculate_consistent_state(Model())
        # with casadi
        solver = pybamm.BaseSolver(root_method="casadi")
        with self.assertRaisesRegex(
                pybamm.SolverError,
                "Could not find consistent initial conditions: .../casadi",
        ):
            solver.calculate_consistent_state(Model())
Example #12
0
    def test_base_solver_init(self):
        solver = pybamm.BaseSolver(rtol=1e-2, atol=1e-4)
        self.assertEqual(solver.rtol, 1e-2)
        self.assertEqual(solver.atol, 1e-4)

        solver.rtol = 1e-5
        self.assertEqual(solver.rtol, 1e-5)
        solver.rtol = 1e-7
        self.assertEqual(solver.rtol, 1e-7)

        with self.assertRaises(NotImplementedError):
            solver.compute_solution(None, None)
        with self.assertRaises(NotImplementedError):
            solver.set_up(None)
Example #13
0
    def test_convert_to_casadi_format(self):
        # Make sure model is converted to casadi format
        model = pybamm.BaseModel()
        v = pybamm.Variable("v")
        model.rhs = {v: -1}
        model.initial_conditions = {v: 1}
        model.convert_to_format = "python"

        disc = pybamm.Discretisation()
        disc.process_model(model)

        solver = pybamm.BaseSolver(root_method="casadi")
        pybamm.set_logging_level("ERROR")
        solver.set_up(model, {})
        self.assertEqual(model.convert_to_format, "casadi")
        pybamm.set_logging_level("WARNING")
Example #14
0
    def test_discretise_model(self):
        # Make sure 0D model is automatically discretised
        model = pybamm.BaseModel()
        v = pybamm.Variable("v")
        model.rhs = {v: -1}
        model.initial_conditions = {v: 1}

        solver = pybamm.BaseSolver()
        self.assertFalse(model.is_discretised)
        solver.set_up(model, {})
        self.assertTrue(model.is_discretised)

        # 1D model cannot be automatically discretised
        model = pybamm.BaseModel()
        v = pybamm.Variable("v", domain="line")
        model.rhs = {v: -1}
        model.initial_conditions = {v: 1}

        with self.assertRaisesRegex(pybamm.DiscretisationError,
                                    "Cannot automatically discretise model"):
            solver.set_up(model, {})
Example #15
0
    def test_set_defaults(self):
        sim = pybamm.Simulation(pybamm.lithium_ion.SPM())

        model_options = {"thermal": "x-full"}
        submesh_types = {
            "Negative particle":
            pybamm.MeshGenerator(pybamm.Exponential1DSubMesh)
        }
        solver = pybamm.BaseSolver()
        quick_plot_vars = ["Negative particle surface concentration"]
        sim.specs(
            model_options=model_options,
            submesh_types=submesh_types,
            solver=solver,
            quick_plot_vars=quick_plot_vars,
        )

        sim.set_defaults()

        self.assertEqual(sim.model_options["thermal"], "x-full")
        self.assertEqual(sim.submesh_types["negative particle"].submesh_type,
                         pybamm.Uniform1DSubMesh)
        self.assertEqual(sim.quick_plot_vars, None)
        self.assertIsInstance(sim.solver, pybamm.ScipySolver)
Example #16
0
    def test_find_consistent_initial_conditions(self):
        # Simple system: a single algebraic equation
        class ScalarModel:
            def __init__(self):
                self.y0 = np.array([2])
                self.rhs = {}
                self.jac_algebraic_eval = None
                self.timescale_eval = 1
                t = casadi.MX.sym("t")
                y = casadi.MX.sym("y")
                p = casadi.MX.sym("p")
                self.casadi_algebraic = casadi.Function(
                    "alg", [t, y, p], [self.algebraic_eval(t, y, p)]
                )
                self.convert_to_format = "casadi"

            def rhs_eval(self, t, y, inputs):
                return np.array([])

            def algebraic_eval(self, t, y, inputs):
                return y + 2

        solver = pybamm.BaseSolver(root_method="lm")
        model = ScalarModel()
        init_cond = solver.calculate_consistent_state(model)
        np.testing.assert_array_equal(init_cond, -2)
        # with casadi
        solver_with_casadi = pybamm.BaseSolver(root_method="casadi", root_tol=1e-12)
        model = ScalarModel()
        init_cond = solver_with_casadi.calculate_consistent_state(model)
        np.testing.assert_array_equal(init_cond, -2)

        # More complicated system
        vec = np.array([0.0, 1.0, 1.5, 2.0])

        class VectorModel:
            def __init__(self):
                self.y0 = np.zeros_like(vec)
                self.rhs = {"test": "test"}
                self.concatenated_rhs = np.array([1])
                self.jac_algebraic_eval = None
                self.timescale_eval = 1
                t = casadi.MX.sym("t")
                y = casadi.MX.sym("y", vec.size)
                p = casadi.MX.sym("p")
                self.casadi_algebraic = casadi.Function(
                    "alg", [t, y, p], [self.algebraic_eval(t, y, p)]
                )
                self.convert_to_format = "casadi"

            def rhs_eval(self, t, y, inputs):
                return y[0:1]

            def algebraic_eval(self, t, y, inputs):
                return (y[1:] - vec[1:]) ** 2

        model = VectorModel()
        init_cond = solver.calculate_consistent_state(model)
        np.testing.assert_array_almost_equal(init_cond, vec)
        # with casadi
        init_cond = solver_with_casadi.calculate_consistent_state(model)
        np.testing.assert_array_almost_equal(init_cond, vec)

        # With jacobian
        def jac_dense(t, y, inputs):
            return 2 * np.hstack([np.zeros((3, 1)), np.diag(y[1:] - vec[1:])])

        model.jac_algebraic_eval = jac_dense
        init_cond = solver.calculate_consistent_state(model)
        np.testing.assert_array_almost_equal(init_cond, vec)

        # With sparse jacobian
        def jac_sparse(t, y, inputs):
            return 2 * csr_matrix(
                np.hstack([np.zeros((3, 1)), np.diag(y[1:] - vec[1:])])
            )

        model.jac_algebraic_eval = jac_sparse
        init_cond = solver.calculate_consistent_state(model)
        np.testing.assert_array_almost_equal(init_cond, vec)