def test_process_input_parameter(self): parameter_values = pybamm.ParameterValues({ "a": "[input]", "b": 3, "c times 2": pybamm.InputParameter("c") * 2 }) # process input parameter a = pybamm.Parameter("a") processed_a = parameter_values.process_symbol(a) self.assertIsInstance(processed_a, pybamm.InputParameter) self.assertEqual(processed_a.evaluate(inputs={"a": 5}), 5) # process binary operation b = pybamm.Parameter("b") add = a + b processed_add = parameter_values.process_symbol(add) self.assertIsInstance(processed_add, pybamm.Addition) self.assertIsInstance(processed_add.children[0], pybamm.InputParameter) self.assertIsInstance(processed_add.children[1], pybamm.Scalar) self.assertEqual(processed_add.evaluate(inputs={"a": 4}), 7) # process complex input parameter c = pybamm.Parameter("c times 2") processed_c = parameter_values.process_symbol(c) self.assertEqual(processed_c.evaluate(inputs={"c": 5}), 10)
def test_symbol_replacements(self): a = pybamm.Parameter("a") b = pybamm.Parameter("b") c = pybamm.Parameter("c") d = pybamm.Parameter("d") replacer = pybamm.SymbolReplacer({a: b, c: d}) for symbol_in, symbol_out in [ (a, b), # just the symbol (a + a, b + b), # binary operator (2 * pybamm.sin(a), 2 * pybamm.sin(b)), # function (3 * b, 3 * b), # no replacement (a + c, b + d), # two replacements ]: replaced_symbol = replacer.process_symbol(symbol_in) self.assertEqual(replaced_symbol.id, symbol_out.id) var1 = pybamm.Variable("var 1", domain="dom 1") var2 = pybamm.Variable("var 2", domain="dom 2") var3 = pybamm.Variable("var 3", domain="dom 1") conc = pybamm.concatenation(var1, var2) replacer = pybamm.SymbolReplacer({var1: var3}) replaced_symbol = replacer.process_symbol(conc) self.assertEqual(replaced_symbol.id, pybamm.concatenation(var3, var2).id)
def beta(T): T_inf = pybamm.FunctionParameter("T_inf", {"x": self.x}) h = pybamm.Parameter("h") eps0 = pybamm.Parameter("eps0") return (1e-4 * (1.0 + 5.0 * pybamm.sin(3 * np.pi * T / 200.0) + pybamm.exp(0.02 * T)) / eps0 + h * (T_inf - T) / (T_inf**4 - T**4) / eps0)
def lico2_volume_change_Ai2020(sto): omega = pybamm.Parameter( "Positive electrode partial molar volume [m3.mol-1]") c_p_max = pybamm.Parameter( "Maximum concentration in positive electrode [mol.m-3]") t_change = omega * c_p_max * sto return t_change
def test_unpack_list_of_symbols(self): a = pybamm.Scalar(1) b = pybamm.Parameter("b") c = pybamm.Parameter("c") unpacker = pybamm.SymbolUnpacker(pybamm.Parameter) unpacked = unpacker.unpack_list_of_symbols([a + b, a - c, b + c]) # Can't check dictionary directly so check ids self.assertEqual(unpacked.keys(), {b.id: b, c.id: c}.keys()) self.assertEqual(unpacked[b.id].id, b.id) self.assertEqual(unpacked[c.id].id, c.id)
def test_multi_var_function_with_parameters(self): def D(a, b): return a * np.exp(b) parameter_values = pybamm.ParameterValues({"a": 3, "b": 0}) a = pybamm.Parameter("a") b = pybamm.Parameter("b") func = pybamm.Function(D, a, b) processed_func = parameter_values.process_symbol(func) self.assertIsInstance(processed_func, pybamm.Function) self.assertEqual(processed_func.evaluate(), 3)
def test_symbol_new_copy(self): a = pybamm.Parameter("a") b = pybamm.Parameter("b") v_n = pybamm.Variable("v", "negative electrode") x_n = pybamm.standard_spatial_vars.x_n v_s = pybamm.Variable("v", "separator") vec = pybamm.Vector([1, 2, 3, 4, 5]) mat = pybamm.Matrix([[1, 2], [3, 4]]) mesh = get_mesh_for_testing() for symbol in [ a + b, a - b, a * b, a / b, a**b, -a, abs(a), pybamm.Function(np.sin, a), pybamm.FunctionParameter("function", {"a": a}), pybamm.grad(v_n), pybamm.div(pybamm.grad(v_n)), pybamm.upwind(v_n), pybamm.IndefiniteIntegral(v_n, x_n), pybamm.BackwardIndefiniteIntegral(v_n, x_n), pybamm.BoundaryValue(v_n, "right"), pybamm.BoundaryGradient(v_n, "right"), pybamm.PrimaryBroadcast(a, "domain"), pybamm.SecondaryBroadcast(v_n, "current collector"), pybamm.FullBroadcast(a, "domain", {"secondary": "other domain"}), pybamm.concatenation(v_n, v_s), pybamm.NumpyConcatenation(a, b, v_s), pybamm.DomainConcatenation([v_n, v_s], mesh), pybamm.Parameter("param"), pybamm.InputParameter("param"), pybamm.StateVector(slice(0, 56)), pybamm.Matrix(np.ones((50, 40))), pybamm.SpatialVariable("x", ["negative electrode"]), pybamm.t, pybamm.Index(vec, 1), pybamm.NotConstant(a), pybamm.ExternalVariable( "external variable", 20, domain="test", auxiliary_domains={"secondary": "test2"}, ), pybamm.minimum(a, b), pybamm.maximum(a, b), pybamm.SparseStack(mat, mat), ]: self.assertEqual(symbol.id, symbol.new_copy().id)
def test_multi_var_function_parameter(self): def D(a, b): return a * pybamm.exp(b) parameter_values = pybamm.ParameterValues({"a": 3, "b": 0, "Diffusivity": D}) a = pybamm.Parameter("a") b = pybamm.Parameter("b") func = pybamm.FunctionParameter("Diffusivity", {"a": a, "b": b}) processed_func = parameter_values.process_symbol(func) self.assertEqual(processed_func.evaluate(), 3)
def test_evaluate(self): parameter_values = pybamm.ParameterValues({"a": 1, "b": 2, "c": 3}) a = pybamm.Parameter("a") b = pybamm.Parameter("b") c = pybamm.Parameter("c") self.assertEqual(parameter_values.evaluate(a), 1) self.assertEqual(parameter_values.evaluate(a + (b * c)), 7) y = pybamm.StateVector(slice(0, 1)) with self.assertRaises(ValueError): parameter_values.evaluate(y) array = pybamm.Array(np.array([1, 2, 3])) with self.assertRaises(ValueError): parameter_values.evaluate(array)
def _set_dimensional_parameters(self): """Defines the dimensional parameters""" # Reference temperature self.T_ref = pybamm.Parameter("Reference temperature [K]") # Cooling coefficient self.h_cn_dim = pybamm.Parameter( "Negative current collector surface heat transfer coefficient [W.m-2.K-1]" ) self.h_cp_dim = pybamm.Parameter( "Positive current collector surface heat transfer coefficient [W.m-2.K-1]" ) self.h_tab_n_dim = pybamm.Parameter( "Negative tab heat transfer coefficient [W.m-2.K-1]") self.h_tab_p_dim = pybamm.Parameter( "Positive tab heat transfer coefficient [W.m-2.K-1]") self.h_edge_dim = pybamm.Parameter( "Edge heat transfer coefficient [W.m-2.K-1]") self.h_total_dim = pybamm.Parameter( "Total heat transfer coefficient [W.m-2.K-1]") # Typical temperature rise self.Delta_T = pybamm.Scalar(1) # Initial temperature self.T_init_dim = pybamm.Parameter("Initial temperature [K]") # Planar (y,z) thermal diffusion timescale self.tau_th_yz = (self.rho_eff_dim(self.T_ref) * (self.geo.L_z**2) / self.lambda_eff_dim(self.T_ref))
def test_process_parameter_in_parameter(self): parameter_values = pybamm.ParameterValues( {"a": 2, "2a": pybamm.Parameter("a") * 2, "b": np.array([1, 2, 3])} ) # process 2a parameter a = pybamm.Parameter("2a") processed_a = parameter_values.process_symbol(a) self.assertEqual(processed_a.evaluate(), 4) # case where parameter can't be processed b = pybamm.Parameter("b") with self.assertRaisesRegex(TypeError, "Cannot process parameter"): parameter_values.process_symbol(b)
def test_evaluate(self): parameter_values = pybamm.ParameterValues({"a": 1, "b": 2, "c": 3}) a = pybamm.Parameter("a") b = pybamm.Parameter("b") c = pybamm.Parameter("c") self.assertEqual(parameter_values.evaluate(a), 1) self.assertEqual(parameter_values.evaluate(a + (b * c)), 7) d = pybamm.Parameter("a") + pybamm.Parameter("b") * pybamm.Array([4, 5]) np.testing.assert_array_equal( parameter_values.evaluate(d), np.array([9, 11])[:, np.newaxis] ) y = pybamm.StateVector(slice(0, 1)) with self.assertRaises(ValueError): parameter_values.evaluate(y)
def test_symbol_evaluates_to_number(self): a = pybamm.Scalar(3) self.assertTrue(a.evaluates_to_number()) a = pybamm.Parameter("a") self.assertFalse(a.evaluates_to_number()) a = pybamm.Scalar(3) * pybamm.Time() self.assertTrue(a.evaluates_to_number()) # highlight difference between this function and isinstance(a, Scalar) self.assertNotIsInstance(a, pybamm.Scalar) a = pybamm.Variable("a") self.assertFalse(a.evaluates_to_number()) a = pybamm.Scalar(3) - 2 self.assertTrue(a.evaluates_to_number()) a = pybamm.Vector(np.ones(5)) self.assertFalse(a.evaluates_to_number()) a = pybamm.Matrix(np.ones((4, 6))) self.assertFalse(a.evaluates_to_number()) a = pybamm.StateVector(slice(0, 10)) self.assertFalse(a.evaluates_to_number()) # Time variable returns true a = 3 * pybamm.t + 2 self.assertTrue(a.evaluates_to_number())
def test_interpolant_against_function(self): parameter_values = pybamm.ParameterValues({"a": 0.6}) parameter_values.update( { "function": "[function]lico2_ocp_Dualfoil1998", "interpolation": "[data]lico2_data_example", }, path=os.path.join( pybamm.root_dir(), "input", "parameters", "lithium-ion", "cathodes", "lico2_Marquis2019", ), ) a = pybamm.Parameter("a") func = pybamm.FunctionParameter("function", a) interp = pybamm.FunctionParameter("interpolation", a) processed_func = parameter_values.process_symbol(func) processed_interp = parameter_values.process_symbol(interp) np.testing.assert_array_almost_equal(processed_func.evaluate(), processed_interp.evaluate(), decimal=4) # process differentiated function parameter diff_func = func.diff(a) diff_interp = interp.diff(a) processed_diff_func = parameter_values.process_symbol(diff_func) processed_diff_interp = parameter_values.process_symbol(diff_interp) np.testing.assert_array_almost_equal(processed_diff_func.evaluate(), processed_diff_interp.evaluate(), decimal=2)
def test_process_parameters_and_discretise(self): model = pybamm.lithium_ion.SPM() # Set up geometry and parameters geometry = model.default_geometry parameter_values = model.default_parameter_values parameter_values.process_geometry(geometry) # Set up discretisation mesh = pybamm.Mesh(geometry, model.default_submesh_types, model.default_var_pts) disc = pybamm.Discretisation(mesh, model.default_spatial_methods) # Process expression c = pybamm.Parameter("Negative electrode thickness [m]") * pybamm.Variable( "X-averaged negative particle concentration", domain="negative particle", auxiliary_domains={"secondary": "current collector"}, ) processed_c = model.process_parameters_and_discretise(c, parameter_values, disc) self.assertIsInstance(processed_c, pybamm.Multiplication) self.assertIsInstance(processed_c.left, pybamm.Scalar) self.assertIsInstance(processed_c.right, pybamm.StateVector) # Process flux manually and check result against flux computed in particle # submodel c_n = model.variables["X-averaged negative particle concentration"] T = pybamm.PrimaryBroadcast( model.variables["X-averaged negative electrode temperature"], ["negative particle"], ) D = model.param.D_n(c_n, T) N = -D * pybamm.grad(c_n) flux_1 = model.process_parameters_and_discretise(N, parameter_values, disc) flux_2 = model.variables["X-averaged negative particle flux"] param_flux_2 = parameter_values.process_symbol(flux_2) disc_flux_2 = disc.process_symbol(param_flux_2) self.assertEqual(flux_1.id, disc_flux_2.id)
def test_process_function_parameter(self): parameter_values = pybamm.ParameterValues({ "a": 3, "func": pybamm.load_function("process_symbol_test_function.py"), "const": pybamm.load_function("process_symbol_test_constant_function.py"), }) a = pybamm.Parameter("a") # process function func = pybamm.FunctionParameter("func", a) processed_func = parameter_values.process_symbol(func) self.assertIsInstance(processed_func, pybamm.Function) self.assertEqual(processed_func.evaluate(), 369) # process constant function const = pybamm.FunctionParameter("const", a) processed_const = parameter_values.process_symbol(const) self.assertIsInstance(processed_const, pybamm.Function) self.assertEqual(processed_const.evaluate(), 254) # process differentiated function parameter diff_func = func.diff(a) processed_diff_func = parameter_values.process_symbol(diff_func) self.assertEqual(processed_diff_func.evaluate(), 123)
def test_process_interpolant(self): x = np.linspace(0, 10)[:, np.newaxis] data = np.hstack([x, 2 * x]) parameter_values = pybamm.ParameterValues( {"a": 3.01, "Times two": ("times two", data)} ) a = pybamm.Parameter("a") func = pybamm.FunctionParameter("Times two", {"a": a}) processed_func = parameter_values.process_symbol(func) self.assertIsInstance(processed_func, pybamm.Interpolant) self.assertEqual(processed_func.evaluate(), 6.02) # process differentiated function parameter diff_func = func.diff(a) processed_diff_func = parameter_values.process_symbol(diff_func) self.assertEqual(processed_diff_func.evaluate(), 2) # interpolant defined up front interp2 = pybamm.Interpolant(data[:, 0], data[:, 1], a) processed_interp2 = parameter_values.process_symbol(interp2) self.assertEqual(processed_interp2.evaluate(), 6.02) data3 = np.hstack([x, 3 * x]) interp3 = pybamm.Interpolant(data3[:, 0], data3[:, 1], a) processed_interp3 = parameter_values.process_symbol(interp3) self.assertEqual(processed_interp3.evaluate(), 9.03)
def test_simplify(self): a = pybamm.Parameter("A") # test error with self.assertRaisesRegex( pybamm.ModelError, "simplify is deprecated as it now has no effect"): (a + a).simplify()
def test_symbol_evaluates_to_constant_number(self): a = pybamm.Scalar(3) self.assertTrue(a.evaluates_to_constant_number()) a = pybamm.Parameter("a") self.assertFalse(a.evaluates_to_constant_number()) a = pybamm.Variable("a") self.assertFalse(a.evaluates_to_constant_number()) a = pybamm.Scalar(3) - 2 self.assertTrue(a.evaluates_to_constant_number()) a = pybamm.Vector(np.ones(5)) self.assertFalse(a.evaluates_to_constant_number()) a = pybamm.Matrix(np.ones((4, 6))) self.assertFalse(a.evaluates_to_constant_number()) a = pybamm.StateVector(slice(0, 10)) self.assertFalse(a.evaluates_to_constant_number()) # Time variable returns true a = 3 * pybamm.t + 2 self.assertFalse(a.evaluates_to_constant_number())
def test_shape_and_size_for_testing(self): scal = pybamm.Scalar(1) self.assertEqual(scal.shape_for_testing, scal.shape) self.assertEqual(scal.size_for_testing, scal.size) state = pybamm.StateVector(slice(10, 25), domain="test") state2 = pybamm.StateVector(slice(10, 25), domain="test 2") self.assertEqual(state.shape_for_testing, state.shape) param = pybamm.Parameter("a") self.assertEqual(param.shape_for_testing, ()) func = pybamm.FunctionParameter("func", {"state": state}) self.assertEqual(func.shape_for_testing, state.shape_for_testing) concat = pybamm.concatenation(state, state2) self.assertEqual(concat.shape_for_testing, (30, 1)) self.assertEqual(concat.size_for_testing, 30) var = pybamm.Variable("var", domain="negative electrode") broadcast = pybamm.PrimaryBroadcast(0, "negative electrode") self.assertEqual(var.shape_for_testing, broadcast.shape_for_testing) self.assertEqual((var + broadcast).shape_for_testing, broadcast.shape_for_testing) var = pybamm.Variable("var", domain=["random domain", "other domain"]) broadcast = pybamm.PrimaryBroadcast(0, ["random domain", "other domain"]) self.assertEqual(var.shape_for_testing, broadcast.shape_for_testing) self.assertEqual((var + broadcast).shape_for_testing, broadcast.shape_for_testing) sym = pybamm.Symbol("sym") with self.assertRaises(NotImplementedError): sym.shape_for_testing
def test_evaluate_ignoring_errors(self): self.assertIsNone(pybamm.t.evaluate_ignoring_errors(t=None)) self.assertEqual(pybamm.t.evaluate_ignoring_errors(t=0), 0) self.assertIsNone(pybamm.Parameter("a").evaluate_ignoring_errors()) self.assertIsNone( pybamm.StateVector(slice(0, 1)).evaluate_ignoring_errors()) self.assertEqual( pybamm.InputParameter("a").evaluate_ignoring_errors(), 1)
def _set_dimensional_parameters(self): "Defines the dimensional parameters" self.I_typ = pybamm.Parameter("Typical current [A]") self.Q = pybamm.Parameter("Cell capacity [A.h]") self.C_rate = pybamm.AbsoluteValue(self.I_typ / self.Q) self.n_electrodes_parallel = pybamm.Parameter( "Number of electrodes connected in parallel to make a cell") self.n_cells = pybamm.Parameter( "Number of cells connected in series to make a battery") self.i_typ = pybamm.Function( np.abs, self.I_typ / (self.n_electrodes_parallel * self.geo.A_cc)) self.voltage_low_cut_dimensional = pybamm.Parameter( "Lower voltage cut-off [V]") self.voltage_high_cut_dimensional = pybamm.Parameter( "Upper voltage cut-off [V]") # Current as a function of *dimensional* time. The below is overwritten in # lithium_ion_parameters.py and lead_acid_parameters.py to use the correct # timescale used for non-dimensionalisation. For a base model, the user may # provide the typical timescale as a parameter. self.timescale = pybamm.Parameter("Typical timescale [s]") self.dimensional_current_with_time = pybamm.FunctionParameter( "Current function [A]", {"Time[s]": pybamm.t * self.timescale}) self.dimensional_current_density_with_time = ( self.dimensional_current_with_time / (self.n_electrodes_parallel * self.geo.A_cc))
def test_symbol_is_constant(self): a = pybamm.Variable("a") self.assertFalse(a.is_constant()) a = pybamm.Parameter("a") self.assertTrue(a.is_constant()) a = pybamm.Scalar(1) * pybamm.Variable("a") self.assertFalse(a.is_constant()) a = pybamm.Scalar(1) * pybamm.Parameter("a") self.assertTrue(a.is_constant()) a = pybamm.Scalar(1) * pybamm.StateVector(slice(10)) self.assertFalse(a.is_constant()) a = pybamm.Scalar(1) * pybamm.Vector(np.zeros(10)) self.assertTrue(a.is_constant())
def electrolyte_diffusivity_Ecker2015(c_e, T, T_inf, E_D_e, R_g): """ Diffusivity of LiPF6 in EC:DMC as a function of ion concentration [1, 2, 3]. References ---------- .. [1] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of a lithium-ion battery i. determination of parameters." Journal of the Electrochemical Society 162.9 (2015): A1836-A1848. .. [2] Ecker, Madeleine, et al. "Parameterization of a physico-chemical model of a lithium-ion battery ii. model validation." Journal of The Electrochemical Society 162.9 (2015): A1849-A1857. .. [3] Richardson, Giles, et. al. "Generalised single particle models for high-rate operation of graded lithium-ion electrodes: Systematic derivation and validation." Electrochemica Acta 339 (2020): 135862 Parameters ---------- c_e: :class: `numpy.Array` Dimensional electrolyte concentration T: :class: `numpy.Array` Dimensional temperature T_inf: double Reference temperature E_D_e: double Electrolyte diffusion activation energy R_g: double The ideal gas constant Returns ------- :`numpy.Array` Solid diffusivity """ # The diffusivity epends on the electrolyte conductivity E_k_e = pybamm.Parameter( "Electrolyte conductivity activation energy [J.mol-1]") inputs = { "Electrolyte concentration [mol.m-3]": c_e, "Temperature [K]": T, "Reference temperature [K]": T_inf, "Activation energy [J.mol-1]": E_k_e, "Ideal gas constant [J.mol-1.K-1]": R_g, } sigma_e = pybamm.FunctionParameter("Electrolyte conductivity [S.m-1]", inputs) # constants k_b = constants.physical_constants["Boltzmann constant"][0] F = constants.physical_constants["Faraday constant"][0] q_e = constants.physical_constants["electron volt"][0] D_c_e = (k_b / (F * q_e)) * sigma_e * T / c_e return D_c_e
def test_simple_model(self): model = pybamm.BaseModel() v = pybamm.Variable("v") a = pybamm.Parameter("a") model.rhs = {v: -a * v} model.initial_conditions = {v: 1} param = pybamm.ParameterValues({"a": 1}) sim = pybamm.Simulation(model, parameter_values=param) sol = sim.solve([0, 1]) np.testing.assert_array_almost_equal(sol.y.full()[0], np.exp(-sol.t), decimal=5)
def test_orphans(self): a = pybamm.Scalar(1) b = pybamm.Parameter("b") summ = a + b a_orp, b_orp = summ.orphans self.assertIsNone(a_orp.parent) self.assertIsNone(b_orp.parent) self.assertEqual(a.id, a_orp.id) self.assertEqual(b.id, b_orp.id)
def constant_current_constant_voltage_constant_power(variables): I = variables["Current [A]"] V = variables["Terminal voltage [V]"] s_I = pybamm.InputParameter("Current switch") s_V = pybamm.InputParameter("Voltage switch") s_P = pybamm.InputParameter("Power switch") n_cells = pybamm.Parameter( "Number of cells connected in series to make a battery") return (s_I * (I - pybamm.InputParameter("Current input [A]")) + s_V * (V - pybamm.InputParameter("Voltage input [V]") / n_cells) + s_P * (V * I - pybamm.InputParameter("Power input [W]") / n_cells))
def test_set_and_update_parameters(self): a = pybamm.Scalar(1) b = pybamm.Parameter(name="test parameter") c = pybamm.Scalar(3) eqn = a + b * c parameter_values = pybamm.ParameterValues({"test parameter": 2}) eqn_processed = parameter_values.process_symbol(eqn) self.assertEqual(eqn_processed.evaluate(), 7) parameter_values = pybamm.ParameterValues({"test parameter": 3}) eqn_updated = parameter_values.update_scalars(eqn_processed) self.assertEqual(eqn_updated.evaluate(), 10)
def test_process_complex_expression(self): var1 = pybamm.Variable("var1") var2 = pybamm.Variable("var2") par1 = pybamm.Parameter("par1") par2 = pybamm.Parameter("par2") scal1 = pybamm.Scalar(3) scal2 = pybamm.Scalar(4) expression = (scal1 * (par1 + var2)) / ((var1 - par2) + scal2) param = pybamm.ParameterValues(values={"par1": 1, "par2": 2}) exp_param = param.process_symbol(expression) self.assertIsInstance(exp_param, pybamm.Division) # left side self.assertIsInstance(exp_param.children[0], pybamm.Multiplication) self.assertIsInstance(exp_param.children[0].children[0], pybamm.Scalar) self.assertIsInstance(exp_param.children[0].children[1], pybamm.Addition) self.assertTrue( isinstance(exp_param.children[0].children[1].children[0], pybamm.Scalar)) self.assertEqual(exp_param.children[0].children[1].children[0].value, 1) self.assertTrue( isinstance(exp_param.children[0].children[1].children[1], pybamm.Variable)) # right side self.assertIsInstance(exp_param.children[1], pybamm.Addition) self.assertTrue( isinstance(exp_param.children[1].children[0], pybamm.Subtraction)) self.assertTrue( isinstance(exp_param.children[1].children[0].children[0], pybamm.Variable)) self.assertTrue( isinstance(exp_param.children[1].children[0].children[1], pybamm.Scalar)) self.assertEqual(exp_param.children[1].children[0].children[1].value, 2) self.assertIsInstance(exp_param.children[1].children[1], pybamm.Scalar)
def test_smooth_absolute_value(self): # Test that smooth absolute value is used when the setting is changed a = pybamm.Symbol("a") pybamm.settings.abs_smoothing = 10 self.assertEqual(str(abs(a)), str(pybamm.smooth_absolute_value(a, 10))) # But exact absolute value should still be used for constants a = pybamm.Parameter("a") self.assertEqual(str(abs(a)), str(pybamm.AbsoluteValue(a))) a = -1 self.assertEqual(str(abs(a)), "1") # Change setting back for other tests pybamm.settings.abs_smoothing = "exact"