예제 #1
0
    def test_processed_var_0D_interpolation(self):
        # without spatial dependence
        t = pybamm.t
        y = pybamm.StateVector(slice(0, 1))
        var = y
        eqn = t * y
        var.mesh = None
        eqn.mesh = None

        t_sol = np.linspace(0, 1, 1000)
        y_sol = np.array([np.linspace(0, 5, 1000)])
        processed_var = pybamm.ProcessedVariable(var,
                                                 pybamm.Solution(t_sol, y_sol))
        # vector
        np.testing.assert_array_equal(processed_var(t_sol), y_sol[0])
        # scalar
        np.testing.assert_array_equal(processed_var(0.5), 2.5)
        np.testing.assert_array_equal(processed_var(0.7), 3.5)

        processed_eqn = pybamm.ProcessedVariable(eqn,
                                                 pybamm.Solution(t_sol, y_sol))
        np.testing.assert_array_equal(processed_eqn(t_sol), t_sol * y_sol[0])
        np.testing.assert_array_almost_equal(processed_eqn(0.5), 0.5 * 2.5)

        # Suppress warning for this test
        pybamm.set_logging_level("ERROR")
        np.testing.assert_array_equal(processed_eqn(2), np.nan)
        pybamm.set_logging_level("WARNING")
    def test_processed_variable_0D(self):
        # without space
        t = pybamm.t
        y = pybamm.StateVector(slice(0, 1))
        var = t * y
        var.mesh = None
        t_sol = np.linspace(0, 1)
        y_sol = np.array([np.linspace(0, 5)])
        var_casadi = to_casadi(var, y_sol)
        processed_var = pybamm.ProcessedVariable(
            [var],
            [var_casadi],
            pybamm.Solution(t_sol, y_sol, pybamm.BaseModel(), {}),
            warn=False,
        )
        np.testing.assert_array_equal(processed_var.entries, t_sol * y_sol[0])

        # scalar value
        var = y
        var.mesh = None
        t_sol = np.array([0])
        y_sol = np.array([1])[:, np.newaxis]
        var_casadi = to_casadi(var, y_sol)
        processed_var = pybamm.ProcessedVariable(
            [var],
            [var_casadi],
            pybamm.Solution(t_sol, y_sol, pybamm.BaseModel(), {}),
            warn=False,
        )
        np.testing.assert_array_equal(processed_var.entries, y_sol[0])
예제 #3
0
    def test_call_failure(self):
        # x domain
        var = pybamm.Variable("var x",
                              domain=["negative electrode", "separator"])
        x = pybamm.SpatialVariable("x",
                                   domain=["negative electrode", "separator"])
        disc = tests.get_discretisation_for_testing()
        disc.set_variable_slices([var])
        x_sol = disc.process_symbol(x).entries[:, 0]
        var_sol = disc.process_symbol(var)
        t_sol = np.linspace(0, 1)
        y_sol = x_sol[:, np.newaxis] * np.linspace(0, 5)

        processed_var = pybamm.ProcessedVariable(var_sol,
                                                 pybamm.Solution(t_sol, y_sol))
        with self.assertRaisesRegex(ValueError, "x cannot be None"):
            processed_var(0)

        # r domain
        var = pybamm.Variable("var r", domain=["negative particle"])
        r = pybamm.SpatialVariable("r", domain=["negative particle"])
        disc = tests.get_discretisation_for_testing()
        disc.set_variable_slices([var])
        r_sol = disc.process_symbol(r).entries[:, 0]
        var_sol = disc.process_symbol(var)
        y_sol = r_sol[:, np.newaxis] * np.linspace(0, 5)

        processed_var = pybamm.ProcessedVariable(var_sol,
                                                 pybamm.Solution(t_sol, y_sol))
        with self.assertRaisesRegex(ValueError, "r cannot be None"):
            processed_var(0)
        with self.assertRaisesRegex(ValueError, "r cannot be None"):
            processed_var(0, 1)
예제 #4
0
    def test_processed_var_1D_interpolation(self):
        t = pybamm.t
        var = pybamm.Variable("var", domain=["negative electrode", "separator"])
        x = pybamm.SpatialVariable("x", domain=["negative electrode", "separator"])
        eqn = t * var + x

        disc = tests.get_discretisation_for_testing()
        disc.set_variable_slices([var])
        x_sol = disc.process_symbol(x).entries[:, 0]
        var_sol = disc.process_symbol(var)
        eqn_sol = disc.process_symbol(eqn)
        t_sol = np.linspace(0, 1)
        y_sol = x_sol[:, np.newaxis] * np.linspace(0, 5)

        processed_var = pybamm.ProcessedVariable(
            var_sol, pybamm.Solution(t_sol, y_sol), warn=False
        )
        # 2 vectors
        np.testing.assert_array_almost_equal(processed_var(t_sol, x_sol), y_sol)
        # 1 vector, 1 scalar
        np.testing.assert_array_almost_equal(
            processed_var(0.5, x_sol)[:, 0], 2.5 * x_sol
        )
        np.testing.assert_array_equal(
            processed_var(t_sol, x_sol[-1]), x_sol[-1] * np.linspace(0, 5)
        )
        # 2 scalars
        np.testing.assert_array_almost_equal(
            processed_var(0.5, x_sol[-1]), 2.5 * x_sol[-1]
        )
        processed_eqn = pybamm.ProcessedVariable(
            eqn_sol, pybamm.Solution(t_sol, y_sol), warn=False
        )
        # 2 vectors
        np.testing.assert_array_almost_equal(
            processed_eqn(t_sol, x_sol), t_sol * y_sol + x_sol[:, np.newaxis]
        )
        # 1 vector, 1 scalar
        self.assertEqual(processed_eqn(0.5, x_sol[10:30]).shape, (20, 1))
        self.assertEqual(processed_eqn(t_sol[4:9], x_sol[-1]).shape, (5,))
        # 2 scalars
        self.assertEqual(processed_eqn(0.5, x_sol[-1]).shape, (1,))

        # test x
        processed_x = pybamm.ProcessedVariable(
            disc.process_symbol(x), pybamm.Solution(t_sol, y_sol), warn=False
        )
        np.testing.assert_array_almost_equal(processed_x(x=x_sol), x_sol[:, np.newaxis])

        # On microscale
        r_n = pybamm.Matrix(
            disc.mesh["negative particle"].nodes, domain="negative particle"
        )
        r_n.mesh = disc.mesh["negative particle"]
        processed_r_n = pybamm.ProcessedVariable(
            r_n, pybamm.Solution(t_sol, y_sol), warn=False
        )
        np.testing.assert_array_equal(r_n.entries[:, 0], processed_r_n.entries[:, 0])
예제 #5
0
    def test_processed_var_2D_secondary_broadcast(self):
        var = pybamm.Variable("var", domain=["negative particle"])
        broad_var = pybamm.SecondaryBroadcast(var, "negative electrode")
        x = pybamm.SpatialVariable("x", domain=["negative electrode"])
        r = pybamm.SpatialVariable("r", domain=["negative particle"])

        disc = tests.get_discretisation_for_testing()
        disc.set_variable_slices([var])
        x_sol = disc.process_symbol(x).entries[:, 0]
        r_sol = disc.process_symbol(r).entries[:, 0]
        var_sol = disc.process_symbol(broad_var)
        t_sol = np.linspace(0, 1)
        y_sol = np.ones(len(x_sol) * len(r_sol))[:, np.newaxis] * np.linspace(0, 5)

        processed_var = pybamm.ProcessedVariable(
            var_sol, pybamm.Solution(t_sol, y_sol), warn=False
        )
        # 3 vectors
        np.testing.assert_array_equal(
            processed_var(t_sol, x_sol, r_sol).shape, (10, 40, 50)
        )
        np.testing.assert_array_equal(
            processed_var(t_sol, x_sol, r_sol),
            np.reshape(y_sol, [len(r_sol), len(x_sol), len(t_sol)]),
        )
        # 2 vectors, 1 scalar
        np.testing.assert_array_equal(processed_var(0.5, x_sol, r_sol).shape, (10, 40))
        np.testing.assert_array_equal(processed_var(t_sol, 0.2, r_sol).shape, (10, 50))
        np.testing.assert_array_equal(processed_var(t_sol, x_sol, 0.5).shape, (40, 50))
        # 1 vectors, 2 scalar
        np.testing.assert_array_equal(processed_var(0.5, 0.2, r_sol).shape, (10,))
        np.testing.assert_array_equal(processed_var(0.5, x_sol, 0.5).shape, (40,))
        np.testing.assert_array_equal(processed_var(t_sol, 0.2, 0.5).shape, (50,))
        # 3 scalars
        np.testing.assert_array_equal(processed_var(0.2, 0.2, 0.2).shape, ())

        # positive particle
        var = pybamm.Variable("var", domain=["positive particle"])
        broad_var = pybamm.SecondaryBroadcast(var, "positive electrode")
        x = pybamm.SpatialVariable("x", domain=["positive electrode"])
        r = pybamm.SpatialVariable("r", domain=["positive particle"])

        disc.set_variable_slices([var])
        x_sol = disc.process_symbol(x).entries[:, 0]
        r_sol = disc.process_symbol(r).entries[:, 0]
        var_sol = disc.process_symbol(broad_var)
        t_sol = np.linspace(0, 1)
        y_sol = np.ones(len(x_sol) * len(r_sol))[:, np.newaxis] * np.linspace(0, 5)

        processed_var = pybamm.ProcessedVariable(
            var_sol, pybamm.Solution(t_sol, y_sol), warn=False
        )
        # 3 vectors
        np.testing.assert_array_equal(
            processed_var(t_sol, x_sol, r_sol).shape, (10, 35, 50)
        )
    def test_processed_variable_2D_x_z(self):
        var = pybamm.Variable(
            "var",
            domain=["negative electrode", "separator"],
            auxiliary_domains={"secondary": "current collector"},
        )
        x = pybamm.SpatialVariable(
            "x",
            domain=["negative electrode", "separator"],
            auxiliary_domains={"secondary": "current collector"},
        )
        z = pybamm.SpatialVariable("z", domain=["current collector"])

        disc = tests.get_1p1d_discretisation_for_testing()
        disc.set_variable_slices([var])
        z_sol = disc.process_symbol(z).entries[:, 0]
        x_sol = disc.process_symbol(x).entries[:, 0]
        # Keep only the first iteration of entries
        x_sol = x_sol[:len(x_sol) // len(z_sol)]
        var_sol = disc.process_symbol(var)
        t_sol = np.linspace(0, 1)
        y_sol = np.ones(len(x_sol) * len(z_sol))[:, np.newaxis] * np.linspace(
            0, 5)

        var_casadi = to_casadi(var_sol, y_sol)
        processed_var = pybamm.ProcessedVariable(
            [var_sol],
            [var_casadi],
            pybamm.Solution(t_sol, y_sol, pybamm.BaseModel(), {}),
            warn=False,
        )
        np.testing.assert_array_equal(
            processed_var.entries,
            np.reshape(
                y_sol,
                [len(x_sol), len(z_sol), len(t_sol)]),
        )

        # On edges
        x_s_edge = pybamm.Matrix(
            np.tile(disc.mesh["separator"].edges, len(z_sol)),
            domain="separator",
            auxiliary_domains={"secondary": "current collector"},
        )
        x_s_edge.mesh = disc.mesh["separator"]
        x_s_edge.secondary_mesh = disc.mesh["current collector"]
        x_s_casadi = to_casadi(x_s_edge, y_sol)
        processed_x_s_edge = pybamm.ProcessedVariable(
            [x_s_edge],
            [x_s_casadi],
            pybamm.Solution(t_sol, y_sol, pybamm.BaseModel(), {}),
            warn=False,
        )
        np.testing.assert_array_equal(
            x_s_edge.entries.flatten(),
            processed_x_s_edge.entries[:, :, 0].T.flatten())
예제 #7
0
    def test_processed_variable_1D(self):
        t = pybamm.t
        var = pybamm.Variable("var", domain=["negative electrode", "separator"])
        x = pybamm.SpatialVariable("x", domain=["negative electrode", "separator"])
        eqn = t * var + x

        # On nodes
        disc = tests.get_discretisation_for_testing()
        disc.set_variable_slices([var])
        x_sol = disc.process_symbol(x).entries[:, 0]
        var_sol = disc.process_symbol(var)
        eqn_sol = disc.process_symbol(eqn)
        t_sol = np.linspace(0, 1)
        y_sol = np.ones_like(x_sol)[:, np.newaxis] * np.linspace(0, 5)

        processed_var = pybamm.ProcessedVariable(
            var_sol, pybamm.Solution(t_sol, y_sol), warn=False
        )
        np.testing.assert_array_equal(processed_var.entries, y_sol)
        np.testing.assert_array_equal(processed_var(t_sol, x_sol), y_sol)
        processed_eqn = pybamm.ProcessedVariable(
            eqn_sol, pybamm.Solution(t_sol, y_sol), warn=False
        )
        np.testing.assert_array_equal(
            processed_eqn(t_sol, x_sol), t_sol * y_sol + x_sol[:, np.newaxis]
        )

        # Test extrapolation
        np.testing.assert_array_equal(processed_var.entries[0], 2 * y_sol[0] - y_sol[1])
        np.testing.assert_array_equal(
            processed_var.entries[1], 2 * y_sol[-1] - y_sol[-2]
        )

        # On edges
        x_s_edge = pybamm.Matrix(disc.mesh["separator"].edges, domain="separator")
        x_s_edge.mesh = disc.mesh["separator"]
        processed_x_s_edge = pybamm.ProcessedVariable(
            x_s_edge, pybamm.Solution(t_sol, y_sol), warn=False
        )
        np.testing.assert_array_equal(
            x_s_edge.entries[:, 0], processed_x_s_edge.entries[:, 0]
        )

        # space only
        eqn = var + x
        eqn_sol = disc.process_symbol(eqn)
        t_sol = np.array([0])
        y_sol = np.ones_like(x_sol)[:, np.newaxis]
        processed_eqn2 = pybamm.ProcessedVariable(
            eqn_sol, pybamm.Solution(t_sol, y_sol), warn=False
        )
        np.testing.assert_array_equal(
            processed_eqn2.entries, y_sol + x_sol[:, np.newaxis]
        )
    def test_call_failure(self):
        # x domain
        var = pybamm.Variable("var x",
                              domain=["negative electrode", "separator"])
        x = pybamm.SpatialVariable("x",
                                   domain=["negative electrode", "separator"])
        disc = tests.get_discretisation_for_testing()
        disc.set_variable_slices([var])
        x_sol = disc.process_symbol(x).entries[:, 0]
        var_sol = disc.process_symbol(var)
        t_sol = np.linspace(0, 1)
        y_sol = x_sol[:, np.newaxis] * np.linspace(0, 5)

        var_casadi = to_casadi(var_sol, y_sol)
        processed_var = pybamm.ProcessedVariable(
            [var_sol],
            [var_casadi],
            pybamm.Solution(t_sol, y_sol, pybamm.BaseModel(), {}),
            warn=False,
        )
        with self.assertRaisesRegex(ValueError, "x cannot be None"):
            processed_var(0)

        # r domain
        var = pybamm.Variable("var r", domain=["negative particle"])
        r = pybamm.SpatialVariable(
            "r",
            domain=["negative particle"],
            auxiliary_domains={"secondary": ["negative electrode"]},
        )
        disc = tests.get_discretisation_for_testing()
        disc.set_variable_slices([var])
        r_sol = disc.process_symbol(r).entries[:, 0]
        var_sol = disc.process_symbol(var)
        y_sol = r_sol[:, np.newaxis] * np.linspace(0, 5)

        var_casadi = to_casadi(var_sol, y_sol)
        processed_var = pybamm.ProcessedVariable(
            [var_sol],
            [var_casadi],
            pybamm.Solution(t_sol, y_sol, pybamm.BaseModel(), {}),
            warn=False,
        )
        with self.assertRaisesRegex(ValueError, "r cannot be None"):
            processed_var(0)
        with self.assertRaisesRegex(ValueError, "r cannot be None"):
            processed_var(0, 1)

        # t is None but len(solution.t) > 1
        with self.assertRaisesRegex(ValueError, "t cannot be None"):
            processed_var()
예제 #9
0
    def test_get_processed_potentials(self):
        # solve cheap SPM to test processed potentials (think of an alternative test?)
        models = [
            pybamm.current_collector.EffectiveResistance2D(),
            pybamm.lithium_ion.SPM(),
        ]
        var = pybamm.standard_spatial_vars
        var_pts = {
            var.x_n: 5,
            var.x_s: 5,
            var.x_p: 5,
            var.r_n: 5,
            var.r_p: 5,
            var.y: 5,
            var.z: 5,
        }
        param = models[1].default_parameter_values
        meshes = [None] * len(models)
        for i, model in enumerate(models):
            param.process_model(model)
            geometry = model.default_geometry
            param.process_geometry(geometry)
            meshes[i] = pybamm.Mesh(geometry, model.default_submesh_types,
                                    var_pts)
            disc = pybamm.Discretisation(meshes[i],
                                         model.default_spatial_methods)
            disc.process_model(model)
        solutions = [None] * len(models)
        t_eval = np.linspace(0, 0.1, 10)
        solutions[0] = models[0].default_solver.solve(models[0])
        solutions[1] = models[1].default_solver.solve(models[1], t_eval)

        # Process SPM V and I
        V = pybamm.ProcessedVariable(
            models[1].variables["Terminal voltage"],
            solutions[1].t,
            solutions[1].y,
            mesh=meshes[1],
        )
        I = pybamm.ProcessedVariable(
            models[1].variables["Total current density"],
            solutions[1].t,
            solutions[1].y,
            mesh=meshes[1],
        )

        # Test potential can be constructed and evaluated without raising error
        potentials = models[0].get_processed_potentials(
            solutions[0], meshes[0], param, V, I)
        for var, processed_var in potentials.items():
            processed_var(0.05, 0.5, 0.5)
예제 #10
0
        def get_max_error(current):
            pybamm.logger.info("current = {}".format(current))
            # Update current (and hence C_e) in the parameters
            param = pybamm.ParameterValues(
                chemistry=pybamm.parameter_sets.Sulzer2019)
            param.update({"Typical current [A]": current})
            param.update_model(leading_order_model, loqs_disc)
            param.update_model(composite_model, comp_disc)
            param.update_model(full_model, full_disc)
            # Solve, make sure times are the same and use tight tolerances
            t_eval = np.linspace(0, 0.6)
            solver_loqs = leading_order_model.default_solver
            solver_loqs.rtol = 1e-8
            solver_loqs.atol = 1e-8
            solution_loqs = solver_loqs.solve(leading_order_model, t_eval)
            solver_comp = composite_model.default_solver
            solver_comp.rtol = 1e-8
            solver_comp.atol = 1e-8
            solution_comp = solver_comp.solve(composite_model, t_eval)
            solver_full = full_model.default_solver
            solver_full.rtol = 1e-8
            solver_full.atol = 1e-8
            solution_full = solver_full.solve(full_model, t_eval)

            # Post-process variables
            t_loqs, y_loqs = solution_loqs.t, solution_loqs.y
            t_comp, y_comp = solution_comp.t, solution_comp.y
            t_full, y_full = solution_full.t, solution_full.y
            voltage_loqs = pybamm.ProcessedVariable(
                leading_order_model.variables["Terminal voltage"],
                t_loqs,
                y_loqs,
                loqs_disc.mesh,
            )
            voltage_comp = pybamm.ProcessedVariable(
                composite_model.variables["Terminal voltage"],
                t_comp,
                y_comp,
                comp_disc.mesh,
            )
            voltage_full = pybamm.ProcessedVariable(
                full_model.variables["Terminal voltage"], t_full, y_full,
                full_disc.mesh)

            # Compare
            t = t_full[:np.min([len(t_loqs), len(t_comp), len(t_full)])]
            loqs_error = np.max(np.abs(voltage_loqs(t) - voltage_full(t)))
            comp_error = np.max(np.abs(voltage_comp(t) - voltage_full(t)))
            return (loqs_error, comp_error)
예제 #11
0
    def test_processed_var_2D_fixed_t_interpolation(self):
        var = pybamm.Variable(
            "var",
            domain=["negative particle"],
            auxiliary_domains={"secondary": ["negative electrode"]},
        )
        x = pybamm.SpatialVariable("x", domain=["negative electrode"])
        r = pybamm.SpatialVariable(
            "r",
            domain=["negative particle"],
            auxiliary_domains={"secondary": ["negative electrode"]},
        )

        disc = tests.get_p2d_discretisation_for_testing()
        disc.set_variable_slices([var])
        x_sol = disc.process_symbol(x).entries[:, 0]
        r_sol = disc.process_symbol(r).entries[:, 0]
        # Keep only the first iteration of entries
        r_sol = r_sol[: len(r_sol) // len(x_sol)]
        var_sol = disc.process_symbol(var)
        t_sol = np.array([0])
        y_sol = np.ones(len(x_sol) * len(r_sol))[:, np.newaxis]

        processed_var = pybamm.ProcessedVariable(
            var_sol, pybamm.Solution(t_sol, y_sol), warn=False
        )
        # 2 vectors
        np.testing.assert_array_equal(processed_var(x=x_sol, r=r_sol).shape, (10, 40))
        # 1 vector, 1 scalar
        np.testing.assert_array_equal(processed_var(x=0.2, r=r_sol).shape, (10,))
        np.testing.assert_array_equal(processed_var(x=x_sol, r=0.5).shape, (40,))
        # 2 scalars
        np.testing.assert_array_equal(processed_var(x=0.2, r=0.2).shape, ())
    def test_processed_variable_1D_unknown_domain(self):
        x = pybamm.SpatialVariable("x",
                                   domain="SEI layer",
                                   coord_sys="cartesian")
        geometry = pybamm.Geometry({
            "SEI layer": {
                x: {
                    "min": pybamm.Scalar(0),
                    "max": pybamm.Scalar(1)
                }
            }
        })

        submesh_types = {"SEI layer": pybamm.Uniform1DSubMesh}
        var_pts = {x: 100}
        mesh = pybamm.Mesh(geometry, submesh_types, var_pts)

        nt = 100

        y_sol = np.zeros((var_pts[x], nt))
        solution = pybamm.Solution(
            np.linspace(0, 1, nt),
            y_sol,
            pybamm.BaseModel(),
            {},
            np.linspace(0, 1, 1),
            np.zeros((var_pts[x])),
            "test",
        )

        c = pybamm.StateVector(slice(0, var_pts[x]), domain=["SEI layer"])
        c.mesh = mesh["SEI layer"]
        c_casadi = to_casadi(c, y_sol)
        pybamm.ProcessedVariable([c], [c_casadi], solution, warn=False)
    def test_processed_var_2D_fixed_t_scikit_interpolation(self):
        var = pybamm.Variable("var", domain=["current collector"])

        disc = tests.get_2p1d_discretisation_for_testing()
        disc.set_variable_slices([var])
        y_sol = disc.mesh["current collector"].edges["y"]
        z_sol = disc.mesh["current collector"].edges["z"]
        var_sol = disc.process_symbol(var)
        var_sol.mesh = disc.mesh["current collector"]
        t_sol = np.array([0])
        u_sol = np.ones(var_sol.shape[0])[:, np.newaxis]

        var_casadi = to_casadi(var_sol, u_sol)
        processed_var = pybamm.ProcessedVariable(
            [var_sol],
            [var_casadi],
            pybamm.Solution(t_sol, u_sol, pybamm.BaseModel(), {}),
            warn=False,
        )
        # 2 vectors
        np.testing.assert_array_equal(
            processed_var(y=y_sol, z=z_sol).shape, (15, 15))
        # 1 vector, 1 scalar
        np.testing.assert_array_equal(
            processed_var(y=0.2, z=z_sol).shape, (15, ))
        np.testing.assert_array_equal(
            processed_var(y=y_sol, z=0.5).shape, (15, ))
        # 2 scalars
        np.testing.assert_array_equal(
            processed_var(t=None, y=0.2, z=0.2).shape, ())
예제 #14
0
    def test_processed_variable_2D_x_r(self):
        var = pybamm.Variable(
            "var",
            domain=["negative particle"],
            auxiliary_domains={"secondary": ["negative electrode"]},
        )
        x = pybamm.SpatialVariable("x", domain=["negative electrode"])
        r = pybamm.SpatialVariable("r", domain=["negative particle"])

        disc = tests.get_p2d_discretisation_for_testing()
        disc.set_variable_slices([var])
        x_sol = disc.process_symbol(x).entries[:, 0]
        r_sol = disc.process_symbol(r).entries[:, 0]
        # Keep only the first iteration of entries
        r_sol = r_sol[:len(r_sol) // len(x_sol)]
        var_sol = disc.process_symbol(var)
        t_sol = np.linspace(0, 1)
        y_sol = np.ones(len(x_sol) * len(r_sol))[:, np.newaxis] * np.linspace(
            0, 5)

        processed_var = pybamm.ProcessedVariable(var_sol,
                                                 pybamm.Solution(t_sol, y_sol))
        np.testing.assert_array_equal(
            processed_var.entries,
            np.reshape(
                y_sol,
                [len(r_sol), len(x_sol), len(t_sol)]),
        )
    def test_processed_var_1D_fixed_t_interpolation(self):
        var = pybamm.Variable("var",
                              domain=["negative electrode", "separator"])
        x = pybamm.SpatialVariable("x",
                                   domain=["negative electrode", "separator"])
        eqn = var + x

        disc = tests.get_discretisation_for_testing()
        disc.set_variable_slices([var])
        x_sol = disc.process_symbol(x).entries[:, 0]
        eqn_sol = disc.process_symbol(eqn)
        t_sol = np.array([1])
        y_sol = x_sol[:, np.newaxis]

        eqn_casadi = to_casadi(eqn_sol, y_sol)
        processed_var = pybamm.ProcessedVariable(
            [eqn_sol],
            [eqn_casadi],
            pybamm.Solution(t_sol, y_sol, pybamm.BaseModel(), {}),
            warn=False,
        )

        # vector
        np.testing.assert_array_almost_equal(processed_var(x=x_sol),
                                             2 * x_sol[:, np.newaxis])
        # scalar
        np.testing.assert_array_almost_equal(processed_var(x=0.5), 1)
예제 #16
0
    def test_processed_variable_1D_unknown_domain(self):
        x = pybamm.SpatialVariable("x",
                                   domain="SEI layer",
                                   coord_sys="cartesian")
        geometry = pybamm.Geometry()
        geometry.add_domain(
            "SEI layer",
            {
                "primary": {
                    x: {
                        "min": pybamm.Scalar(0),
                        "max": pybamm.Scalar(1)
                    }
                }
            },
        )

        submesh_types = {"SEI layer": pybamm.Uniform1DSubMesh}
        var_pts = {x: 100}
        mesh = pybamm.Mesh(geometry, submesh_types, var_pts)

        nt = 100

        solution = pybamm.Solution(
            np.linspace(0, 1, nt),
            np.zeros((var_pts[x], nt)),
            np.linspace(0, 1, 1),
            np.zeros((var_pts[x])),
            "test",
        )

        c = pybamm.StateVector(slice(0, var_pts[x]), domain=["SEI layer"])
        c.mesh = mesh["SEI layer"]
        pybamm.ProcessedVariable(c, solution)
예제 #17
0
    def test_processed_var_2Dspace_scikit_interpolation(self):
        var = pybamm.Variable("var", domain=["current collector"])
        y = pybamm.SpatialVariable("y", domain=["current collector"])
        z = pybamm.SpatialVariable("z", domain=["current collector"])

        disc = tests.get_2p1d_discretisation_for_testing()
        disc.set_variable_slices([var])
        y_sol = disc.process_symbol(y).entries[:, 0]
        z_sol = disc.process_symbol(z).entries[:, 0]
        var_sol = disc.process_symbol(var)
        t_sol = np.array([0])
        u_sol = np.ones(var_sol.shape[0])[:, np.newaxis]

        processed_var = pybamm.ProcessedVariable(var_sol,
                                                 t_sol,
                                                 u_sol,
                                                 mesh=disc.mesh)
        # 2 vectors
        np.testing.assert_array_equal(
            processed_var(t=None, y=y_sol, z=z_sol).shape, (15, 15))
        # 1 vector, 1 scalar
        np.testing.assert_array_equal(
            processed_var(t=None, y=0.2, z=z_sol).shape, (15, 1))
        np.testing.assert_array_equal(
            processed_var(t=None, y=y_sol, z=0.5).shape, (15, ))
        # 2 scalars
        np.testing.assert_array_equal(
            processed_var(t=None, y=0.2, z=0.2).shape, (1, ))
예제 #18
0
    def update(self, variables):
        """Add ProcessedVariables to the dictionary of variables in the solution"""
        # Convert single entry to list
        if isinstance(variables, str):
            variables = [variables]
        # Process
        for key in variables:
            pybamm.logger.debug("Post-processing {}".format(key))
            # If there are symbolic inputs then we need to make a
            # ProcessedSymbolicVariable
            if self.has_symbolic_inputs is True:
                var = pybamm.ProcessedSymbolicVariable(
                    self.model.variables[key], self)

            # Otherwise a standard ProcessedVariable is ok
            else:
                var = pybamm.ProcessedVariable(self.model.variables[key], self,
                                               self._known_evals)

                # Update known_evals in order to process any other variables faster
                for t in var.known_evals:
                    self._known_evals[t].update(var.known_evals[t])

            # Save variable and data
            self._variables[key] = var
            self.data[key] = var.data
예제 #19
0
 def test_failure(self):
     t = np.ones(25)
     y = np.ones((120, 25))
     mat = pybamm.Vector(np.ones(120), domain=["negative particle"])
     disc = tests.get_p2d_discretisation_for_testing()
     with self.assertRaisesRegex(
             ValueError, "3D variable shape does not match domain shape"):
         pybamm.ProcessedVariable(mat, t, y, disc.mesh)
예제 #20
0
    def test_update_geometry(self):
        # test on simple lead-acid model
        model1 = pybamm.lead_acid.LOQS()
        modeltest1 = tests.StandardModelTest(model1)
        t_eval = np.linspace(0, 0.5)
        modeltest1.test_all(t_eval=t_eval, skip_output_tests=True)

        T1, Y1 = modeltest1.solution.t, modeltest1.solution.y

        # trying to update the geometry fails
        parameter_values_update = pybamm.ParameterValues(
            chemistry=pybamm.parameter_sets.Sulzer2019
        )
        parameter_values_update.update(
            {
                "Negative electrode thickness [m]": 0.0002,
                "Separator thickness [m]": 0.0003,
                "Positive electrode thickness [m]": 0.0004,
            }
        )
        with self.assertRaisesRegex(ValueError, "geometry has changed"):
            modeltest1.test_update_parameters(parameter_values_update)

        # instead we need to make a new model and re-discretise
        model2 = pybamm.lead_acid.LOQS()
        # nb: need to be careful make parameters a reasonable size
        modeltest2 = tests.StandardModelTest(model2)
        modeltest2.test_all(
            param=parameter_values_update, t_eval=t_eval, skip_output_tests=True
        )
        T2, Y2 = modeltest2.solution.t, modeltest2.solution.y
        # results should be different
        c1 = pybamm.ProcessedVariable(
            modeltest1.model.variables["Electrolyte concentration"],
            T1,
            Y1,
            mesh=modeltest1.disc.mesh,
        ).entries
        c2 = pybamm.ProcessedVariable(
            modeltest2.model.variables["Electrolyte concentration"],
            T2,
            Y2,
            mesh=modeltest2.disc.mesh,
        ).entries
        self.assertNotEqual(np.linalg.norm(c1 - c2), 0)
        self.assertNotEqual(np.linalg.norm(Y1 - Y2), 0)
예제 #21
0
 def test_processed_variable_1D(self):
     # without space
     t = pybamm.t
     y = pybamm.StateVector(slice(0, 1))
     var = t * y
     t_sol = np.linspace(0, 1)
     y_sol = np.array([np.linspace(0, 5)])
     processed_var = pybamm.ProcessedVariable(var, t_sol, y_sol)
     np.testing.assert_array_equal(processed_var.entries, t_sol * y_sol[0])
예제 #22
0
    def test_processed_var_1D_interpolation(self):
        # without spatial dependence
        t = pybamm.t
        y = pybamm.StateVector(slice(0, 1))
        var = y
        eqn = t * y

        t_sol = np.linspace(0, 1, 1000)
        y_sol = np.array([np.linspace(0, 5, 1000)])
        processed_var = pybamm.ProcessedVariable(var, t_sol, y_sol)
        # vector
        np.testing.assert_array_equal(processed_var(t_sol), y_sol[0])
        # scalar
        np.testing.assert_array_equal(processed_var(0.5), 2.5)
        np.testing.assert_array_equal(processed_var(0.7), 3.5)

        processed_eqn = pybamm.ProcessedVariable(eqn, t_sol, y_sol)
        np.testing.assert_array_equal(processed_eqn(t_sol), t_sol * y_sol[0])
        np.testing.assert_array_almost_equal(processed_eqn(0.5), 0.5 * 2.5)
예제 #23
0
    def update(self, variables):
        """Add ProcessedVariables to the dictionary of variables in the solution"""
        # Convert single entry to list
        if isinstance(variables, str):
            variables = [variables]
        # Process
        for key in variables:
            pybamm.logger.debug("Post-processing {}".format(key))
            # If there are symbolic inputs then we need to make a
            # ProcessedSymbolicVariable
            if self.has_symbolic_inputs is True:
                var = pybamm.ProcessedSymbolicVariable(
                    self.all_models[0].variables[key], self
                )

            # Otherwise a standard ProcessedVariable is ok
            else:
                vars_pybamm = [model.variables[key] for model in self.all_models]

                # Iterate through all models, some may be in the list several times and
                # therefore only get set up once
                vars_casadi = []
                for model, ys, inputs, var_pybamm in zip(
                    self.all_models, self.all_ys, self.all_inputs, vars_pybamm
                ):
                    if key in model._variables_casadi:
                        var_casadi = model._variables_casadi[key]
                    else:
                        t_MX = casadi.MX.sym("t")
                        y_MX = casadi.MX.sym("y", ys.shape[0])
                        symbolic_inputs_dict = {
                            key: casadi.MX.sym("input", value.shape[0])
                            for key, value in inputs.items()
                        }
                        symbolic_inputs = casadi.vertcat(
                            *[p for p in symbolic_inputs_dict.values()]
                        )

                        # Convert variable to casadi
                        # Make all inputs symbolic first for converting to casadi
                        var_sym = var_pybamm.to_casadi(
                            t_MX, y_MX, inputs=symbolic_inputs_dict
                        )

                        var_casadi = casadi.Function(
                            "variable", [t_MX, y_MX, symbolic_inputs], [var_sym]
                        )
                        model._variables_casadi[key] = var_casadi
                    vars_casadi.append(var_casadi)

                var = pybamm.ProcessedVariable(vars_pybamm, vars_casadi, self)

            # Save variable and data
            self._variables[key] = var
            self.data[key] = var.data
예제 #24
0
    def test_processed_variable_3D_x_z(self):
        var = pybamm.Variable(
            "var",
            domain=["negative electrode", "separator"],
            auxiliary_domains={"secondary": "current collector"},
        )
        x = pybamm.SpatialVariable("x",
                                   domain=["negative electrode", "separator"])
        z = pybamm.SpatialVariable("z", domain=["current collector"])

        disc = tests.get_1p1d_discretisation_for_testing()
        disc.set_variable_slices([var])
        x_sol = disc.process_symbol(x).entries[:, 0]
        z_sol = disc.process_symbol(z).entries[:, 0]
        var_sol = disc.process_symbol(var)
        t_sol = np.linspace(0, 1)
        y_sol = np.ones(len(x_sol) * len(z_sol))[:, np.newaxis] * np.linspace(
            0, 5)

        processed_var = pybamm.ProcessedVariable(var_sol,
                                                 t_sol,
                                                 y_sol,
                                                 mesh=disc.mesh)
        np.testing.assert_array_equal(
            processed_var.entries,
            np.reshape(
                y_sol,
                [len(x_sol), len(z_sol), len(t_sol)]),
        )

        # On edges
        x_s_edge = pybamm.Matrix(
            np.repeat(disc.mesh["separator"][0].edges, len(z_sol)),
            domain="separator",
            auxiliary_domains={"secondary": "current collector"},
        )
        processed_x_s_edge = pybamm.ProcessedVariable(x_s_edge, t_sol, y_sol,
                                                      disc.mesh)
        np.testing.assert_array_equal(
            x_s_edge.entries[:, 0],
            processed_x_s_edge.entries[:, :, 0].reshape(-1, 1)[:, 0],
        )
예제 #25
0
 def test_solution_too_short(self):
     t = pybamm.t
     y = pybamm.StateVector(slice(0, 1))
     var = t * y
     var.mesh = None
     t_sol = np.array([1])
     y_sol = np.array([np.linspace(0, 5)])
     with self.assertRaisesRegex(
             pybamm.SolverError,
             "Solution time vector must have length > 1"):
         pybamm.ProcessedVariable(var, pybamm.Solution(t_sol, y_sol))
예제 #26
0
 def test_solution_too_short(self):
     t = pybamm.t
     y = pybamm.StateVector(slice(0, 3))
     var = t * y
     disc = tests.get_2p1d_discretisation_for_testing()
     var.mesh = disc.mesh["current collector"]
     t_sol = np.array([1])
     y_sol = np.linspace(0, 5)[:, np.newaxis]
     with self.assertRaisesRegex(
             pybamm.SolverError,
             "Solution time vector must have length > 1"):
         pybamm.ProcessedVariable(var, pybamm.Solution(t_sol, y_sol))
예제 #27
0
    def test_processed_var_0D_fixed_t_interpolation(self):
        y = pybamm.StateVector(slice(0, 1))
        var = y
        eqn = 2 * y
        var.mesh = None
        eqn.mesh = None

        t_sol = np.array([10])
        y_sol = np.array([[100]])
        processed_var = pybamm.ProcessedVariable(
            eqn, pybamm.Solution(t_sol, y_sol), warn=False
        )

        np.testing.assert_array_equal(processed_var(), 200)
예제 #28
0
    def test_3D_raises_error(self):
        var = pybamm.Variable(
            "var",
            domain=["negative electrode"],
            auxiliary_domains={"secondary": ["current collector"]},
        )

        disc = tests.get_2p1d_discretisation_for_testing()
        disc.set_variable_slices([var])
        var_sol = disc.process_symbol(var)
        t_sol = np.array([0, 1, 2])
        u_sol = np.ones(var_sol.shape[0] * 3)[:, np.newaxis]

        with self.assertRaisesRegex(NotImplementedError, "Shape not recognized"):
            pybamm.ProcessedVariable(var_sol, pybamm.Solution(t_sol, u_sol), warn=False)
예제 #29
0
    def test_processed_variable_2D_fixed_t_scikit(self):
        var = pybamm.Variable("var", domain=["current collector"])

        disc = tests.get_2p1d_discretisation_for_testing()
        disc.set_variable_slices([var])
        y = disc.mesh["current collector"][0].edges["y"]
        z = disc.mesh["current collector"][0].edges["z"]
        var_sol = disc.process_symbol(var)
        t_sol = np.array([0])
        u_sol = np.ones(var_sol.shape[0])[:, np.newaxis]

        processed_var = pybamm.ProcessedVariable(var_sol,
                                                 pybamm.Solution(t_sol, u_sol))
        np.testing.assert_array_equal(processed_var.entries,
                                      np.reshape(u_sol,
                                                 [len(y), len(z)]))
예제 #30
0
파일: solution.py 프로젝트: wpf0221/PyBaMM
    def update(self, variables):
        """Add ProcessedVariables to the dictionary of variables in the solution"""
        # Convert single entry to list
        if isinstance(variables, str):
            variables = [variables]
        # Process
        for key in variables:
            pybamm.logger.debug("Post-processing {}".format(key))
            var = pybamm.ProcessedVariable(self.model.variables[key], self,
                                           self._known_evals)

            # Update known_evals in order to process any other variables faster
            for t in var.known_evals:
                self._known_evals[t].update(var.known_evals[t])

            # Save variable and data
            self._variables[key] = var
            self.data[key] = var.data