diff --git a/tests/unit/test_batch_study.py b/tests/unit/test_batch_study.py index c04e71b5cb..f8762133a6 100644 --- a/tests/unit/test_batch_study.py +++ b/tests/unit/test_batch_study.py @@ -5,6 +5,7 @@ import os import pybamm import unittest +from tempfile import TemporaryDirectory spm = pybamm.lithium_ion.SPM() spm_uniform = pybamm.lithium_ion.SPM({"particle": "uniform profile"}) @@ -90,21 +91,19 @@ def test_solve(self): self.assertIn(output_experiment, experiments_list) def test_create_gif(self): - bs = pybamm.BatchStudy({"spm": pybamm.lithium_ion.SPM()}) - bs.solve([0, 10]) + with TemporaryDirectory() as dir_name: + bs = pybamm.BatchStudy({"spm": pybamm.lithium_ion.SPM()}) + bs.solve([0, 10]) - # Create a temporary file name - test_stub = "batch_study_test" - test_file = f"{test_stub}.gif" + # Create a temporary file name + test_file = os.path.join(dir_name, "batch_study_test.gif") - # create a GIF before calling the plot method - bs.create_gif(number_of_images=3, duration=1, output_filename=test_file) + # create a GIF before calling the plot method + bs.create_gif(number_of_images=3, duration=1, output_filename=test_file) - # create a GIF after calling the plot method - bs.plot(testing=True) - bs.create_gif(number_of_images=3, duration=1, output_filename=test_file) - - os.remove(test_file) + # create a GIF after calling the plot method + bs.plot(testing=True) + bs.create_gif(number_of_images=3, duration=1, output_filename=test_file) if __name__ == "__main__": diff --git a/tests/unit/test_expression_tree/test_symbol.py b/tests/unit/test_expression_tree/test_symbol.py index 3a74375ce7..3f91633fbe 100644 --- a/tests/unit/test_expression_tree/test_symbol.py +++ b/tests/unit/test_expression_tree/test_symbol.py @@ -4,6 +4,7 @@ from tests import TestCase import os import unittest +from tempfile import TemporaryDirectory import numpy as np from scipy.sparse import csr_matrix, coo_matrix @@ -386,13 +387,16 @@ def test_symbol_repr(self): ) def test_symbol_visualise(self): - c = pybamm.Variable("c", "negative electrode") - d = pybamm.Variable("d", "negative electrode") - sym = pybamm.div(c * pybamm.grad(c)) + (c / d + c - d) ** 5 - sym.visualise("test_visualize.png") - self.assertTrue(os.path.exists("test_visualize.png")) - with self.assertRaises(ValueError): - sym.visualise("test_visualize") + with TemporaryDirectory() as dir_name: + test_stub = os.path.join(dir_name, "test_visualize") + test_name = f"{test_stub}.png" + c = pybamm.Variable("c", "negative electrode") + d = pybamm.Variable("d", "negative electrode") + sym = pybamm.div(c * pybamm.grad(c)) + (c / d + c - d) ** 5 + sym.visualise(test_name) + self.assertTrue(os.path.exists(test_name)) + with self.assertRaises(ValueError): + sym.visualise(test_stub) def test_has_spatial_derivatives(self): var = pybamm.Variable("var", domain="test") diff --git a/tests/unit/test_parameters/test_lead_acid_parameters.py b/tests/unit/test_parameters/test_lead_acid_parameters.py index e0151f0e7b..ddc73f61ee 100644 --- a/tests/unit/test_parameters/test_lead_acid_parameters.py +++ b/tests/unit/test_parameters/test_lead_acid_parameters.py @@ -1,10 +1,11 @@ # # Test for the standard lead acid parameters # +import os from tests import TestCase import pybamm from tests import get_discretisation_for_testing - +from tempfile import TemporaryDirectory import unittest @@ -15,10 +16,11 @@ def test_scipy_constants(self): self.assertAlmostEqual(constants.F.evaluate(), 96485, places=0) def test_print_parameters(self): - parameters = pybamm.LeadAcidParameters() - parameter_values = pybamm.lead_acid.BaseModel().default_parameter_values - output_file = "lead_acid_parameters.txt" - parameter_values.print_parameters(parameters, output_file) + with TemporaryDirectory() as dir_name: + parameters = pybamm.LeadAcidParameters() + parameter_values = pybamm.lead_acid.BaseModel().default_parameter_values + output_file = os.path.join(dir_name, "lead_acid_parameters.txt") + parameter_values.print_parameters(parameters, output_file) def test_parameters_defaults_lead_acid(self): # Load parameters to be tested diff --git a/tests/unit/test_parameters/test_lithium_ion_parameters.py b/tests/unit/test_parameters/test_lithium_ion_parameters.py index 9d9d892300..0c46eec16e 100644 --- a/tests/unit/test_parameters/test_lithium_ion_parameters.py +++ b/tests/unit/test_parameters/test_lithium_ion_parameters.py @@ -1,19 +1,21 @@ # -# Tests lithium ion parameters load and give expected values +# Tests lithium-ion parameters load and give expected values # +import os from tests import TestCase import pybamm - +from tempfile import TemporaryDirectory import unittest import numpy as np class TestLithiumIonParameterValues(TestCase): def test_print_parameters(self): - parameters = pybamm.LithiumIonParameters() - parameter_values = pybamm.lithium_ion.BaseModel().default_parameter_values - output_file = "lithium_ion_parameters.txt" - parameter_values.print_parameters(parameters, output_file) + with TemporaryDirectory() as dir_name: + parameters = pybamm.LithiumIonParameters() + parameter_values = pybamm.lithium_ion.BaseModel().default_parameter_values + output_file = os.path.join(dir_name, "lithium_ion_parameters.txt") + parameter_values.print_parameters(parameters, output_file) def test_lithium_ion(self): """This test checks that all the parameters are being calculated diff --git a/tests/unit/test_plotting/test_quick_plot.py b/tests/unit/test_plotting/test_quick_plot.py index 8304e89583..f569f00152 100644 --- a/tests/unit/test_plotting/test_quick_plot.py +++ b/tests/unit/test_plotting/test_quick_plot.py @@ -3,6 +3,7 @@ import unittest from tests import TestCase import numpy as np +from tempfile import TemporaryDirectory class TestQuickPlot(TestCase): @@ -290,12 +291,13 @@ def test_spm_simulation(self): quick_plot.plot(0) # test creating a GIF - test_stub = "spm_sim_test" - test_file = f"{test_stub}.gif" - quick_plot.create_gif(number_of_images=3, duration=3, output_filename=test_file) - assert not os.path.exists(f"{test_stub}*.png") - assert os.path.exists(test_file) - os.remove(test_file) + with TemporaryDirectory() as dir_name: + test_stub = os.path.join(dir_name, "spm_sim_test") + test_file = f"{test_stub}.gif" + quick_plot.create_gif(number_of_images=3, duration=3, + output_filename=test_file) + assert not os.path.exists(f"{test_stub}*.png") + assert os.path.exists(test_file) pybamm.close_plots() def test_loqs_spme(self): diff --git a/tests/unit/test_simulation.py b/tests/unit/test_simulation.py index f008c7ff2a..c98586ee59 100644 --- a/tests/unit/test_simulation.py +++ b/tests/unit/test_simulation.py @@ -6,6 +6,7 @@ import sys import unittest import uuid +from tempfile import TemporaryDirectory class TestSimulation(TestCase): @@ -248,32 +249,37 @@ def test_step_with_inputs(self): ) def test_save_load(self): - model = pybamm.lead_acid.LOQS() - model.use_jacobian = True - sim = pybamm.Simulation(model) - - sim.save("test.pickle") - sim_load = pybamm.load_sim("test.pickle") - self.assertEqual(sim.model.name, sim_load.model.name) - - # save after solving - sim.solve([0, 600]) - sim.save("test.pickle") - sim_load = pybamm.load_sim("test.pickle") - self.assertEqual(sim.model.name, sim_load.model.name) + with TemporaryDirectory() as dir_name: + test_name = os.path.join(dir_name, "tests.pickle") + + model = pybamm.lead_acid.LOQS() + model.use_jacobian = True + sim = pybamm.Simulation(model) + + sim.save(test_name) + sim_load = pybamm.load_sim(test_name) + self.assertEqual(sim.model.name, sim_load.model.name) + + # save after solving + sim.solve([0, 600]) + sim.save(test_name) + sim_load = pybamm.load_sim(test_name) + self.assertEqual(sim.model.name, sim_load.model.name) + + # with python formats + model.convert_to_format = None + sim = pybamm.Simulation(model) + sim.solve([0, 600]) + sim.save(test_name) + model.convert_to_format = "python" + sim = pybamm.Simulation(model) + sim.solve([0, 600]) + with self.assertRaisesRegex( + NotImplementedError, + "Cannot save simulation if model format is python" + ): + sim.save(test_name) - # with python formats - model.convert_to_format = None - sim = pybamm.Simulation(model) - sim.solve([0, 600]) - sim.save("test.pickle") - model.convert_to_format = "python" - sim = pybamm.Simulation(model) - sim.solve([0, 600]) - with self.assertRaisesRegex( - NotImplementedError, "Cannot save simulation if model format is python" - ): - sim.save("test.pickle") def test_load_param(self): # Test load_sim for parameters imports @@ -299,33 +305,36 @@ def test_load_param(self): os.remove(filename) def test_save_load_dae(self): - model = pybamm.lead_acid.LOQS({"surface form": "algebraic"}) - model.use_jacobian = True - sim = pybamm.Simulation(model) - - # save after solving - sim.solve([0, 600]) - sim.save("test.pickle") - sim_load = pybamm.load_sim("test.pickle") - self.assertEqual(sim.model.name, sim_load.model.name) - - # with python format - model.convert_to_format = None - sim = pybamm.Simulation(model) - sim.solve([0, 600]) - sim.save("test.pickle") - - # with Casadi solver & experiment - model.convert_to_format = "casadi" - sim = pybamm.Simulation( - model, - experiment="Discharge at 1C for 20 minutes", - solver=pybamm.CasadiSolver(), - ) - sim.solve([0, 600]) - sim.save("test.pickle") - sim_load = pybamm.load_sim("test.pickle") - self.assertEqual(sim.model.name, sim_load.model.name) + with TemporaryDirectory() as dir_name: + test_name = os.path.join(dir_name, "test.pickle") + + model = pybamm.lead_acid.LOQS({"surface form": "algebraic"}) + model.use_jacobian = True + sim = pybamm.Simulation(model) + + # save after solving + sim.solve([0, 600]) + sim.save(test_name) + sim_load = pybamm.load_sim(test_name) + self.assertEqual(sim.model.name, sim_load.model.name) + + # with python format + model.convert_to_format = None + sim = pybamm.Simulation(model) + sim.solve([0, 600]) + sim.save(test_name) + + # with Casadi solver & experiment + model.convert_to_format = "casadi" + sim = pybamm.Simulation( + model, + experiment="Discharge at 1C for 20 minutes", + solver=pybamm.CasadiSolver(), + ) + sim.solve([0, 600]) + sim.save(test_name) + sim_load = pybamm.load_sim(test_name) + self.assertEqual(sim.model.name, sim_load.model.name) def test_plot(self): sim = pybamm.Simulation(pybamm.lithium_ion.SPM()) @@ -340,21 +349,19 @@ def test_plot(self): sim.plot(testing=True) def test_create_gif(self): - sim = pybamm.Simulation(pybamm.lithium_ion.SPM()) - sim.solve(t_eval=[0, 10]) + with TemporaryDirectory() as dir_name: + sim = pybamm.Simulation(pybamm.lithium_ion.SPM()) + sim.solve(t_eval=[0, 10]) - # Create a temporary file name - test_stub = "test_sim" - test_file = f"{test_stub}.gif" + # Create a temporary file name + test_file = os.path.join(dir_name, "test_sim.gif") - # create a GIF without calling the plot method - sim.create_gif(number_of_images=3, duration=1, output_filename=test_file) - - # call the plot method before creating the GIF - sim.plot(testing=True) - sim.create_gif(number_of_images=3, duration=1, output_filename=test_file) + # create a GIF without calling the plot method + sim.create_gif(number_of_images=3, duration=1, output_filename=test_file) - os.remove(test_file) + # call the plot method before creating the GIF + sim.plot(testing=True) + sim.create_gif(number_of_images=3, duration=1, output_filename=test_file) def test_drive_cycle_interpolant(self): model = pybamm.lithium_ion.SPM() diff --git a/tests/unit/test_solvers/test_solution.py b/tests/unit/test_solvers/test_solution.py index 2ef01d7434..9fc93dfb26 100644 --- a/tests/unit/test_solvers/test_solution.py +++ b/tests/unit/test_solvers/test_solution.py @@ -1,6 +1,7 @@ # # Tests for the Solution class # +import os from tests import TestCase import json import pybamm @@ -9,6 +10,7 @@ import pandas as pd from scipy.io import loadmat from tests import get_discretisation_for_testing +from tempfile import TemporaryDirectory class TestSolution(TestCase): @@ -233,95 +235,103 @@ def test_plot(self): solution.plot(["c", "2c"], testing=True) def test_save(self): - model = pybamm.BaseModel() - # create both 1D and 2D variables - c = pybamm.Variable("c") - d = pybamm.Variable("d", domain="negative electrode") - model.rhs = {c: -c, d: 1} - model.initial_conditions = {c: 1, d: 2} - model.variables = {"c": c, "d": d, "2c": 2 * c, "c + d": c + d} - - disc = get_discretisation_for_testing() - disc.process_model(model) - solution = pybamm.ScipySolver().solve(model, np.linspace(0, 1)) - - # test save data - with self.assertRaises(ValueError): - solution.save_data("test.pickle") - - # set variables first then save - solution.update(["c", "d"]) - with self.assertRaisesRegex(ValueError, "pickle"): - solution.save_data(to_format="pickle") - solution.save_data("test.pickle") - - data_load = pybamm.load("test.pickle") - np.testing.assert_array_equal(solution.data["c"], data_load["c"]) - np.testing.assert_array_equal(solution.data["d"], data_load["d"]) - - # to matlab - solution.save_data("test.mat", to_format="matlab") - data_load = loadmat("test.mat") - np.testing.assert_array_equal(solution.data["c"], data_load["c"].flatten()) - np.testing.assert_array_equal(solution.data["d"], data_load["d"]) - - with self.assertRaisesRegex(ValueError, "matlab"): - solution.save_data(to_format="matlab") - - # to matlab with bad variables name fails - solution.update(["c + d"]) - with self.assertRaisesRegex(ValueError, "Invalid character"): - solution.save_data("test.mat", to_format="matlab") - # Works if providing alternative name - solution.save_data( - "test.mat", to_format="matlab", short_names={"c + d": "c_plus_d"} - ) - data_load = loadmat("test.mat") - np.testing.assert_array_equal(solution.data["c + d"], data_load["c_plus_d"]) - - # to csv - with self.assertRaisesRegex( - ValueError, "only 0D variables can be saved to csv" - ): - solution.save_data("test.csv", to_format="csv") - # only save "c" and "2c" - solution.save_data("test.csv", ["c", "2c"], to_format="csv") - csv_str = solution.save_data(variables=["c", "2c"], to_format="csv") - - # check string is the same as the file - with open("test.csv") as f: - # need to strip \r chars for windows - self.assertEqual(csv_str.replace("\r", ""), f.read()) - - # read csv - df = pd.read_csv("test.csv") - np.testing.assert_array_almost_equal(df["c"], solution.data["c"]) - np.testing.assert_array_almost_equal(df["2c"], solution.data["2c"]) - - # to json - solution.save_data("test.json", to_format="json") - json_str = solution.save_data(to_format="json") - - # check string is the same as the file - with open("test.json") as f: - # need to strip \r chars for windows - self.assertEqual(json_str.replace("\r", ""), f.read()) - - # check if string has the right values - json_data = json.loads(json_str) - np.testing.assert_array_almost_equal(json_data["c"], solution.data["c"]) - np.testing.assert_array_almost_equal(json_data["d"], solution.data["d"]) - - # raise error if format is unknown - with self.assertRaisesRegex(ValueError, "format 'wrong_format' not recognised"): - solution.save_data("test.csv", to_format="wrong_format") - - # test save whole solution - solution.save("test.pickle") - solution_load = pybamm.load("test.pickle") - self.assertEqual(solution.all_models[0].name, solution_load.all_models[0].name) - np.testing.assert_array_equal(solution["c"].entries, solution_load["c"].entries) - np.testing.assert_array_equal(solution["d"].entries, solution_load["d"].entries) + with TemporaryDirectory() as dir_name: + test_stub = os.path.join(dir_name, "test") + + model = pybamm.BaseModel() + # create both 1D and 2D variables + c = pybamm.Variable("c") + d = pybamm.Variable("d", domain="negative electrode") + model.rhs = {c: -c, d: 1} + model.initial_conditions = {c: 1, d: 2} + model.variables = {"c": c, "d": d, "2c": 2 * c, "c + d": c + d} + + disc = get_discretisation_for_testing() + disc.process_model(model) + solution = pybamm.ScipySolver().solve(model, np.linspace(0, 1)) + + # test save data + with self.assertRaises(ValueError): + solution.save_data(f"{test_stub}.pickle") + + # set variables first then save + solution.update(["c", "d"]) + with self.assertRaisesRegex(ValueError, "pickle"): + solution.save_data(to_format="pickle") + solution.save_data(f"{test_stub}.pickle") + + data_load = pybamm.load(f"{test_stub}.pickle") + np.testing.assert_array_equal(solution.data["c"], data_load["c"]) + np.testing.assert_array_equal(solution.data["d"], data_load["d"]) + + # to matlab + solution.save_data(f"{test_stub}.mat", to_format="matlab") + data_load = loadmat(f"{test_stub}.mat") + np.testing.assert_array_equal(solution.data["c"], data_load["c"].flatten()) + np.testing.assert_array_equal(solution.data["d"], data_load["d"]) + + with self.assertRaisesRegex(ValueError, "matlab"): + solution.save_data(to_format="matlab") + + # to matlab with bad variables name fails + solution.update(["c + d"]) + with self.assertRaisesRegex(ValueError, "Invalid character"): + solution.save_data(f"{test_stub}.mat", to_format="matlab") + # Works if providing alternative name + solution.save_data( + f"{test_stub}.mat", to_format="matlab", + short_names={"c + d": "c_plus_d"} + ) + data_load = loadmat(f"{test_stub}.mat") + np.testing.assert_array_equal(solution.data["c + d"], data_load["c_plus_d"]) + + # to csv + with self.assertRaisesRegex( + ValueError, "only 0D variables can be saved to csv" + ): + solution.save_data(f"{test_stub}.csv", to_format="csv") + # only save "c" and "2c" + solution.save_data(f"{test_stub}.csv", ["c", "2c"], to_format="csv") + csv_str = solution.save_data(variables=["c", "2c"], to_format="csv") + + # check string is the same as the file + with open(f"{test_stub}.csv") as f: + # need to strip \r chars for windows + self.assertEqual(csv_str.replace("\r", ""), f.read()) + + # read csv + df = pd.read_csv(f"{test_stub}.csv") + np.testing.assert_array_almost_equal(df["c"], solution.data["c"]) + np.testing.assert_array_almost_equal(df["2c"], solution.data["2c"]) + + # to json + solution.save_data(f"{test_stub}.json", to_format="json") + json_str = solution.save_data(to_format="json") + + # check string is the same as the file + with open(f"{test_stub}.json") as f: + # need to strip \r chars for windows + self.assertEqual(json_str.replace("\r", ""), f.read()) + + # check if string has the right values + json_data = json.loads(json_str) + np.testing.assert_array_almost_equal(json_data["c"], solution.data["c"]) + np.testing.assert_array_almost_equal(json_data["d"], solution.data["d"]) + + # raise error if format is unknown + with self.assertRaisesRegex(ValueError, + "format 'wrong_format' not recognised"): + solution.save_data(f"{test_stub}.csv", to_format="wrong_format") + + # test save whole solution + solution.save(f"{test_stub}.pickle") + solution_load = pybamm.load(f"{test_stub}.pickle") + self.assertEqual(solution.all_models[0].name, + solution_load.all_models[0].name) + np.testing.assert_array_equal(solution["c"].entries, + solution_load["c"].entries) + np.testing.assert_array_equal(solution["d"].entries, + solution_load["d"].entries) def test_get_data_cycles_steps(self): model = pybamm.BaseModel()