def test_current_conservation_finite_volumes_convergence(self): electrolyte = pybamm.Electrolyte() # Finite volume only has h**2 convergence if the mesh is uniform? uniform_lengths = {"Ln": 1e-3, "Ls": 1e-3, "Lp": 1e-3} param = pybamm.Parameters(optional_parameters=uniform_lengths, tests="convergence") # Test convergence ns = [100, 200, 400] errn = [0] * len(ns) errp = [0] * len(ns) for i, n in enumerate(ns): # Set up mesh = pybamm.Mesh(param, n) param.set_mesh(mesh) cn = np.cos(2 * np.pi * mesh.xcn) cp = np.cos(2 * np.pi * mesh.xcp) en = mesh.xcn**2 ep = mesh.xcp**2 operators = { "xcn": pybamm.Operators("Finite Volumes", "xcn", mesh), "xcp": pybamm.Operators("Finite Volumes", "xcp", mesh), } in_exact = (-2 * np.pi * np.sin(2 * np.pi * mesh.xn)) + 2 * mesh.xn ip_exact = (-2 * np.pi * np.sin(2 * np.pi * mesh.xp / param.lp)) + 2 * mesh.xp current_bcs_n = (in_exact[0, None], in_exact[-1, None]) current_bcs_p = (ip_exact[0, None], ip_exact[-1, None]) # Exact solutions dendt_exact = 1 / param.gamma_dl_n * (-4 * np.pi**2 * cn + 2) depdt_exact = 1 / param.gamma_dl_p * (-4 * np.pi**2 * cp + 2) # Calculate solution and errors electrolyte.set_simulation(param, operators, mesh) dendt = electrolyte.current_conservation("xcn", cn, en, 0, current_bcs_n) depdt = electrolyte.current_conservation("xcp", cp, ep, 0, current_bcs_p) errn[i] = norm( (dendt - dendt_exact)[1:-1]) / norm(dendt_exact[1:-1]) errp[i] = norm( (depdt - depdt_exact)[1:-1]) / norm(depdt_exact[1:-1]) # Expect h**2 convergence for i in range(len(errn) - 1): self.assertLess(errn[i + 1] / errn[i], 0.26) self.assertLess(errp[i + 1] / errp[i], 0.26)
def test_grad_div_1D_FV_basic(self): param = pybamm.Parameters() mesh = pybamm.Mesh(param, target_npts=50) y = np.ones_like(mesh.x.centres) N = np.ones_like(mesh.x.edges) yn = np.ones_like(mesh.xn.centres) Nn = np.ones_like(mesh.xn.edges) yp = np.ones_like(mesh.xp.centres) Np = np.ones_like(mesh.xp.edges) # Get all operators operators = pybamm.Operators("Finite Volumes", mesh) # Check output shape self.assertEqual(operators.x.grad(y).shape[0], y.shape[0] - 1) self.assertEqual(operators.x.div(N).shape[0], N.shape[0] - 1) self.assertEqual(operators.xn.grad(yn).shape[0], yn.shape[0] - 1) self.assertEqual(operators.xn.div(Nn).shape[0], Nn.shape[0] - 1) self.assertEqual(operators.xp.grad(yp).shape[0], yp.shape[0] - 1) self.assertEqual(operators.xp.div(Np).shape[0], Np.shape[0] - 1) # Check grad and div are both zero self.assertEqual(np.linalg.norm(operators.x.grad(y)), 0) self.assertEqual(np.linalg.norm(operators.x.div(N)), 0) self.assertEqual(np.linalg.norm(operators.xn.grad(yn)), 0) self.assertEqual(np.linalg.norm(operators.xn.div(Nn)), 0) self.assertEqual(np.linalg.norm(operators.xp.grad(yp)), 0) self.assertEqual(np.linalg.norm(operators.xp.div(Np)), 0)
def test_model_shape(self): for spatial_discretisation in pybamm.KNOWN_SPATIAL_DISCRETISATIONS: operators = { domain: pybamm.Operators(spatial_discretisation, domain, self.mesh) for domain in self.model.domains() } self.model.set_simulation(self.param, operators, self.mesh) y, dydt = pdes_io(self.model) self.assertEqual(y.shape, dydt.shape)
def test_macinnes_finite_volumes_convergence(self): electrolyte = pybamm.Electrolyte() # Finite volume only has h**2 convergence if the mesh is uniform? uniform_lengths = {"Ln": 1e-3, "Ls": 1e-3, "Lp": 1e-3} param = pybamm.Parameters(optional_parameters=uniform_lengths, tests="convergence") # Test convergence ns = [100, 200, 400] errn = [0] * len(ns) errp = [0] * len(ns) for i, n in enumerate(ns): # Set up mesh = pybamm.Mesh(param, n) param.set_mesh(mesh) cn = np.cos(2 * np.pi * mesh.xcn) cp = np.sin(2 * np.pi * mesh.xcp) en = mesh.xcn**2 ep = mesh.xcp**2 operators = { "xcn": pybamm.Operators("Finite Volumes", "xcn", mesh), "xcp": pybamm.Operators("Finite Volumes", "xcp", mesh), } in_exact = -2 * np.pi * np.sin(2 * np.pi * mesh.xn) + 2 * mesh.xn ip_exact = 2 * np.pi * np.cos(2 * np.pi * mesh.xp) + 2 * mesh.xp current_bcs_n = (in_exact[0, None], in_exact[-1, None]) current_bcs_p = (ip_exact[0, None], ip_exact[-1, None]) # Calculate solution and errors electrolyte.set_simulation(param, operators, mesh) i_n = electrolyte.macinnes("xcn", cn, en, current_bcs_n) i_p = electrolyte.macinnes("xcp", cp, ep, current_bcs_p) errn[i] = norm(i_n - in_exact) / norm(in_exact) errp[i] = norm(i_p - ip_exact) / norm(ip_exact) # Expect h**2 convergence for i in range(len(errn) - 1): self.assertLess(errn[i + 1] / errn[i], 0.26) self.assertLess(errp[i + 1] / errp[i], 0.26)
def operators(self, mesh): """Define the operators in each domain. Parameters ---------- mesh : :class:`pybamm.mesh.Mesh` instance The mesh on which the operators are defined. Returns ------- :class: `pybamm.operators.Operators` A class of all the operators. """ return pybamm.Operators(self.spatial_discretisation, mesh)
def test_model_shape(self): for spatial_discretisation in pybamm.KNOWN_SPATIAL_DISCRETISATIONS: # Set up param = pybamm.Parameters() mesh = pybamm.Mesh(param) param.set_mesh(mesh) operators = pybamm.Operators(spatial_discretisation, mesh) electrolyte = pybamm.electrolyte.StefanMaxwellDiffusion( param.electrolyte, operators.x, mesh.x, {}) # Test c0 = electrolyte.initial_conditions() vars = VarsForTesting(c=c0, j=c0) dcdt = electrolyte.pdes_rhs(vars) self.assertEqual(c0.shape, dcdt.shape)
def test_finite_volumes_convergence(self): # Finite volume only has h**2 convergence if the mesh is uniform? uniform_lengths = {"Ln": 1e-3, "Ls": 1e-3, "Lp": 1e-3} param = pybamm.Parameters(optional_parameters=uniform_lengths, tests="convergence") # Test convergence ns = [100, 200, 400] errs = [0] * len(ns) for i, n in enumerate(ns): # Set up mesh = pybamm.Mesh(param, target_npts=n) param.set_mesh(mesh) operators = pybamm.Operators("Finite Volumes", mesh) # Exact solution c = np.cos(2 * np.pi * mesh.x.centres) dcdt_exact = -4 * np.pi**2 * c def bcs(t): return {"concentration": (np.array([0]), np.array([0]))} def sources(t): return {"concentration": 0} tests = {"bcs": bcs, "sources": sources} electrolyte = pybamm.electrolyte.StefanMaxwellDiffusion( param.electrolyte, operators.x, mesh.x, tests) # Calculate solution and errors vars = VarsForTesting(c=c) dcdt = electrolyte.pdes_rhs(vars) errs[i] = norm(dcdt - dcdt_exact) / norm(dcdt_exact) # Expect h**2 convergence [ self.assertLess(errs[i + 1] / errs[i], 0.26) for i in range(len(errs) - 1) ]