示例#1
0
    def test_adding_2D_external_variable_fail(self):
        model = pybamm.BaseModel()
        a = pybamm.Variable(
            "a",
            domain=["negative electrode", "separator"],
            auxiliary_domains={"secondary": "current collector"},
        )
        b1 = pybamm.Variable(
            "b",
            domain="negative electrode",
            auxiliary_domains={"secondary": "current collector"},
        )
        b2 = pybamm.Variable(
            "b",
            domain="separator",
            auxiliary_domains={"secondary": "current collector"},
        )
        b = pybamm.Concatenation(b1, b2)

        model.rhs = {a: a * b}
        model.initial_conditions = {a: 0}
        model.external_variables = [b]
        model.variables = {"b": b}

        disc = get_1p1d_discretisation_for_testing()
        with self.assertRaisesRegex(
            NotImplementedError, "Cannot create 2D external variable"
        ):
            disc.process_model(model)
    def test_concatenations(self):
        y = np.linspace(0, 1, 10)[:, np.newaxis]
        a = pybamm.Vector(y)
        b = pybamm.Scalar(16)
        c = pybamm.Scalar(3)
        conc = pybamm.NumpyConcatenation(a, b, c)
        self.assert_casadi_equal(conc.to_casadi(),
                                 casadi.MX(conc.evaluate()),
                                 evalf=True)

        # Domain concatenation
        mesh = get_mesh_for_testing()
        a_dom = ["negative electrode"]
        b_dom = ["separator"]
        a = 2 * pybamm.Vector(np.ones_like(mesh[a_dom[0]].nodes), domain=a_dom)
        b = pybamm.Vector(np.ones_like(mesh[b_dom[0]].nodes), domain=b_dom)
        conc = pybamm.DomainConcatenation([b, a], mesh)
        self.assert_casadi_equal(conc.to_casadi(),
                                 casadi.MX(conc.evaluate()),
                                 evalf=True)

        # 2d
        disc = get_1p1d_discretisation_for_testing()
        a = pybamm.Variable("a", domain=a_dom)
        b = pybamm.Variable("b", domain=b_dom)
        conc = pybamm.Concatenation(a, b)
        disc.set_variable_slices([conc])
        expr = disc.process_symbol(conc)
        y = casadi.SX.sym("y", expr.size)
        x = expr.to_casadi(None, y)
        f = casadi.Function("f", [x], [x])
        y_eval = np.linspace(0, 1, expr.size)
        self.assert_casadi_equal(f(y_eval), casadi.SX(expr.evaluate(y=y_eval)))
示例#3
0
    def test_jac_of_domain_concatenation(self):
        # create mesh
        disc = get_1p1d_discretisation_for_testing()
        mesh = disc.mesh
        y = pybamm.StateVector(slice(0, 1500))

        # Jacobian of a DomainConcatenation of constants is a zero matrix of the
        # appropriate size
        a_dom = ["negative electrode"]
        b_dom = ["separator"]
        c_dom = ["positive electrode"]
        cc_npts = mesh["current collector"][0].npts
        curr_coll_vector = pybamm.Vector(np.ones(cc_npts), domain="current collector")
        a = 2 * pybamm.PrimaryBroadcast(curr_coll_vector, a_dom)
        b = pybamm.PrimaryBroadcast(curr_coll_vector, b_dom)
        c = 3 * pybamm.PrimaryBroadcast(curr_coll_vector, c_dom)

        conc = pybamm.Concatenation(a, b, c)
        disc.set_variable_slices([conc])
        conc_disc = disc.process_symbol(conc)
        jac = conc_disc.jac(y).evaluate().toarray()
        np.testing.assert_array_equal(jac, np.zeros((1500, 1500)))

        # Jacobian of a DomainConcatenation of StateVectors
        a = pybamm.Variable("a", domain=a_dom)
        b = pybamm.Variable("b", domain=b_dom)
        c = pybamm.Variable("c", domain=c_dom)
        conc = pybamm.Concatenation(a, b, c)
        disc.set_variable_slices([conc])
        conc_disc = disc.process_symbol(conc)
        y0 = np.ones(1500)
        jac = conc_disc.jac(y).evaluate(y=y0).toarray()
        np.testing.assert_array_equal(jac, np.eye(1500))
示例#4
0
    def test_concatenation_2D(self):
        disc = get_1p1d_discretisation_for_testing(zpts=3)

        a = pybamm.Variable("a", domain=["negative electrode"])
        b = pybamm.Variable("b", domain=["separator"])
        c = pybamm.Variable("c", domain=["positive electrode"])
        conc = pybamm.Concatenation(a, b, c)
        disc.set_variable_slices([conc])
        self.assertEqual(
            disc.y_slices[a.id],
            [slice(0, 40), slice(100, 140),
             slice(200, 240)])
        self.assertEqual(
            disc.y_slices[b.id],
            [slice(40, 65), slice(140, 165),
             slice(240, 265)])
        self.assertEqual(
            disc.y_slices[c.id],
            [slice(65, 100), slice(165, 200),
             slice(265, 300)])
        expr = disc.process_symbol(conc)
        self.assertIsInstance(expr, pybamm.DomainConcatenation)

        # Evaulate
        y = np.linspace(0, 1, 300)
        self.assertEqual(expr.children[0].evaluate(0, y).shape, (120, 1))
        self.assertEqual(expr.children[1].evaluate(0, y).shape, (75, 1))
        self.assertEqual(expr.children[2].evaluate(0, y).shape, (105, 1))
        np.testing.assert_equal(expr.evaluate(0, y), y[:, np.newaxis])
示例#5
0
    def test_domain_concatenation_2D(self):
        disc = get_1p1d_discretisation_for_testing()

        a_dom = ["negative electrode"]
        b_dom = ["separator"]
        a = pybamm.Variable("a", domain=a_dom)
        b = pybamm.Variable("b", domain=b_dom)
        conc = pybamm.concatenation(2 * a, 3 * b)
        disc.set_variable_slices([a, b])
        expr = disc.process_symbol(conc)
        self.assertIsInstance(expr, pybamm.DomainConcatenation)

        y = np.empty((expr._size, 1))
        for i in range(len(y)):
            y[i] = i

        constant_symbols = OrderedDict()
        variable_symbols = OrderedDict()
        pybamm.find_symbols(expr, constant_symbols, variable_symbols)

        self.assertEqual(len(constant_symbols), 0)

        evaluator = pybamm.EvaluatorPython(expr)
        result = evaluator.evaluate(y=y)
        np.testing.assert_allclose(result, expr.evaluate(y=y))

        # check that concatenating a single domain is consistent
        expr = disc.process_symbol(pybamm.Concatenation(a))
        evaluator = pybamm.EvaluatorPython(expr)
        result = evaluator.evaluate(y=y)
        np.testing.assert_allclose(result, expr.evaluate(y=y))
    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_broadcast_2D(self):
        # broadcast in 2D --> Outer symbol
        var = pybamm.Variable("var", ["current collector"])
        disc = get_1p1d_discretisation_for_testing()
        mesh = disc.mesh
        broad = pybamm.Broadcast(var, "separator", broadcast_type="primary")

        disc.set_variable_slices([var])
        broad_disc = disc.process_symbol(broad)
        self.assertIsInstance(broad_disc, pybamm.Outer)
        self.assertIsInstance(broad_disc.children[0], pybamm.StateVector)
        self.assertIsInstance(broad_disc.children[1], pybamm.Vector)
        self.assertEqual(
            broad_disc.shape,
            (mesh["separator"][0].npts * mesh["current collector"][0].npts, 1),
        )
示例#8
0
    def test_outer(self):
        var = pybamm.Variable("var", ["current collector"])
        x = pybamm.SpatialVariable("x_s", ["separator"])

        # create discretisation
        disc = get_1p1d_discretisation_for_testing()
        mesh = disc.mesh

        # process Outer variable
        disc.set_variable_slices([var])
        outer = pybamm.outer(var, x)
        outer_disc = disc.process_symbol(outer)
        self.assertIsInstance(outer_disc, pybamm.Outer)
        self.assertIsInstance(outer_disc.children[0], pybamm.StateVector)
        self.assertIsInstance(outer_disc.children[1], pybamm.Vector)
        self.assertEqual(
            outer_disc.shape,
            (mesh["separator"][0].npts * mesh["current collector"][0].npts, 1),
        )
    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],
        )
示例#10
0
    def test_broadcast_2D(self):
        # broadcast in 2D --> MatrixMultiplication
        var = pybamm.Variable("var", ["current collector"])
        disc = get_1p1d_discretisation_for_testing()
        mesh = disc.mesh
        broad = pybamm.PrimaryBroadcast(var, "separator")

        disc.set_variable_slices([var])
        broad_disc = disc.process_symbol(broad)
        self.assertIsInstance(broad_disc, pybamm.MatrixMultiplication)
        self.assertIsInstance(broad_disc.children[0], pybamm.Matrix)
        self.assertIsInstance(broad_disc.children[1], pybamm.StateVector)
        self.assertEqual(
            broad_disc.shape,
            (mesh["separator"][0].npts * mesh["current collector"][0].npts, 1),
        )
        y_test = np.linspace(0, 1, mesh["current collector"][0].npts)
        np.testing.assert_array_equal(
            broad_disc.evaluate(y=y_test),
            np.outer(y_test,
                     np.ones(mesh["separator"][0].npts)).reshape(-1, 1),
        )

        # test broadcast to edges
        broad_to_edges = pybamm.PrimaryBroadcastToEdges(var, "separator")
        broad_to_edges_disc = disc.process_symbol(broad_to_edges)
        self.assertIsInstance(broad_to_edges_disc, pybamm.MatrixMultiplication)
        self.assertIsInstance(broad_to_edges_disc.children[0], pybamm.Matrix)
        self.assertIsInstance(broad_to_edges_disc.children[1],
                              pybamm.StateVector)
        self.assertEqual(
            broad_to_edges_disc.shape,
            ((mesh["separator"][0].npts + 1) *
             mesh["current collector"][0].npts, 1),
        )
        y_test = np.linspace(0, 1, mesh["current collector"][0].npts)
        np.testing.assert_array_equal(
            broad_to_edges_disc.evaluate(y=y_test),
            np.outer(y_test,
                     np.ones(mesh["separator"][0].npts + 1)).reshape(-1, 1),
        )
示例#11
0
    def test_1D_different_domains(self):
        # Negative electrode domain
        var = pybamm.Variable("var", domain=["negative electrode"])
        x = pybamm.SpatialVariable("x", domain=["negative electrode"])

        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 = [0]
        y_sol = np.ones_like(x_sol)[:, np.newaxis] * 5
        sol = pybamm.Solution(t_sol, y_sol)
        pybamm.ProcessedSymbolicVariable(var_sol, sol)

        # Particle domain
        var = pybamm.Variable("var", 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)

        t_sol = [0]
        y_sol = np.ones_like(r_sol)[:, np.newaxis] * 5
        sol = pybamm.Solution(t_sol, y_sol)
        pybamm.ProcessedSymbolicVariable(var_sol, sol)

        # Current collector domain
        var = pybamm.Variable("var", domain=["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]
        var_sol = disc.process_symbol(var)

        t_sol = [0]
        y_sol = np.ones_like(z_sol)[:, np.newaxis] * 5
        sol = pybamm.Solution(t_sol, y_sol)
        pybamm.ProcessedSymbolicVariable(var_sol, sol)

        # Other domain
        var = pybamm.Variable("var", domain=["line"])
        x = pybamm.SpatialVariable("x", domain=["line"])

        geometry = pybamm.Geometry(
            {"line": {x: {"min": pybamm.Scalar(0), "max": pybamm.Scalar(1)}}}
        )
        submesh_types = {"line": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh)}
        var_pts = {x: 10}
        mesh = pybamm.Mesh(geometry, submesh_types, var_pts)
        disc = pybamm.Discretisation(mesh, {"line": pybamm.FiniteVolume()})
        disc.set_variable_slices([var])
        x_sol = disc.process_symbol(x).entries[:, 0]
        var_sol = disc.process_symbol(var)

        t_sol = [0]
        y_sol = np.ones_like(x_sol)[:, np.newaxis] * 5
        sol = pybamm.Solution(t_sol, y_sol)
        pybamm.ProcessedSymbolicVariable(var_sol, sol)

        # 2D fails
        var = pybamm.Variable(
            "var",
            domain=["negative particle"],
            auxiliary_domains={"secondary": "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])
        r_sol = disc.process_symbol(r).entries[:, 0]
        var_sol = disc.process_symbol(var)

        t_sol = [0]
        y_sol = np.ones_like(r_sol)[:, np.newaxis] * 5
        sol = pybamm.Solution(t_sol, y_sol)
        with self.assertRaisesRegex(NotImplementedError, "Shape not recognized"):
            pybamm.ProcessedSymbolicVariable(var_sol, sol)