def __init__(self, model, param=None, mesh=None, solver=None, name="unnamed"): # Defaults if param is None: param = pybamm.Parameters() if mesh is None: mesh = pybamm.Mesh(param) if solver is None: solver = pybamm.Solver() # Assign attributes self.model = model self.param = param self.mesh = mesh self.solver = solver self.name = name # Initialise simulation to prepare for solving # Set mesh dependent parameters self.param.set_mesh(self.mesh) # Create operators from solver self.operators = self.solver.operators(self.mesh) # Assign param, operators and mesh as model attributes self.model.set_simulation(self.param, self.operators, self.mesh)
def test_model_shape(self): for spatial_discretisation in pybamm.KNOWN_SPATIAL_DISCRETISATIONS: solver = pybamm.Solver( spatial_discretisation=spatial_discretisation) sim = pybamm.Simulation(self.model, solver=solver) y, dydt = pdes_io(sim.model) self.assertEqual(y.shape, dydt.shape)
def test_model_physics(self): sim = pybamm.Simulation(self.model, self.param, self.mesh) solver = pybamm.Solver( integrator="BDF", spatial_discretisation="Finite Volumes" ) sim.run(solver) interface = pybamm.Interface() interface.set_simulation(self.param, self.mesh) cn = np.ones((len(self.mesh.xcn), len(sim.vars.t))) cp = np.ones((len(self.mesh.xcp), len(sim.vars.t))) sim.vars.jn = interface.butler_volmer("xcn", cn, sim.vars.en) sim.vars.jp = interface.butler_volmer("xcp", cp, sim.vars.ep) sim.average() # integral of en is known jn_avg_expected = self.param.icell(sim.vars.t) / self.param.ln jp_avg_expected = -self.param.icell(sim.vars.t) / self.param.lp self.assertTrue( np.allclose(sim.vars.jn_avg[1:], jn_avg_expected[1:], atol=1e-15) ) self.assertTrue( np.allclose(sim.vars.jp_avg[1:], jp_avg_expected[1:], atol=1e-15) )
def test_model_convergence(self): """ Exact solution: c = exp(-4*pi**2*t) * cos(2*pi*x) Initial conditions: c0 = cos(2*pi*x) Boundary conditions: Zero flux Source terms: 0 Can achieve "convergence" in time by changing the integrator tolerance Can't get h**2 convergence in space """ param = pybamm.Parameters(tests="convergence") param.set_mesh(self.mesh) def c_exact(t): return np.exp(-4 * np.pi**2 * t) * np.cos( 2 * np.pi * self.mesh.x.centres) inits = {"concentration": c_exact(0)} def bcs(t): return {"concentration": (np.array([0]), np.array([0]))} def sources(t): return {"concentration": 0} tests = {"inits": inits, "bcs": bcs, "sources": sources} model = pybamm.ReactionDiffusionModel(tests=tests) ns = [1, 2, 3] errs = [0] * len(ns) for i, n in enumerate(ns): solver = pybamm.Solver( integrator="BDF", spatial_discretisation="Finite Volumes", tol=10**(-n), ) sim = pybamm.Simulation(model, param=param, mesh=self.mesh, solver=solver) sim.run() errs[i] = norm(sim.vars.c.T - c_exact(self.mesh.time[:, np.newaxis])) / norm( c_exact(self.mesh.time[:, np.newaxis])) [ self.assertLess(errs[i + 1] / errs[i], 0.14) for i in range(len(errs) - 1) ]
def test_simulation_name(self): model = pybamm.ReactionDiffusionModel() param = pybamm.Parameters() mesh = pybamm.Mesh(param, target_npts=50) solver = pybamm.Solver() sim = pybamm.Simulation(model, param=param, mesh=mesh, solver=solver, name="test name") self.assertEqual(sim.param.electrolyte.s.shape, sim.mesh.x.centres.shape) np.testing.assert_array_equal(sim.operators.x.div(mesh.x.edges), np.ones_like(mesh.x.centres)) self.assertEqual(param, sim.model.param) self.assertEqual(mesh, sim.model.mesh) self.assertEqual(str(sim), "test name")
def test_solver_basic(self): with self.assertRaises(NotImplementedError): pybamm.Solver(integrator="not an integrator") with self.assertRaises(NotImplementedError): pybamm.Solver( spatial_discretisation="not a spatial discretisation")