diff --git a/coverage-report.pdf b/coverage-report.pdf new file mode 100644 index 0000000..8b803a8 Binary files /dev/null and b/coverage-report.pdf differ diff --git a/diffusion2d.py b/diffusion2d.py index 51a07f2..24f458f 100644 --- a/diffusion2d.py +++ b/diffusion2d.py @@ -38,14 +38,22 @@ def __init__(self): self.dt = None def initialize_domain(self, w=10., h=10., dx=0.1, dy=0.1): + assert isinstance(w,float), 'w must be a float' + assert isinstance(h,float), 'h must be a float' + assert isinstance(dx,float), 'dx must be a float' + assert isinstance(dy,float), 'dy must be a float' self.w = w self.h = h self.dx = dx self.dy = dy self.nx = int(w / dx) + #self.nx = int(h / dx) # Introduction of a bug on purpose to check unit tests self.ny = int(h / dy) - def initialize_physical_parameters(self, d=4., T_cold=300, T_hot=700): + def initialize_physical_parameters(self, d=4., T_cold=300., T_hot=700.): + assert isinstance(d,float), 'd must be a float' + assert isinstance(T_cold,float), 'T_cold must be a float' + assert isinstance(T_hot,float), 'T_hot must be a float' self.D = d self.T_cold = T_cold self.T_hot = T_hot @@ -53,6 +61,7 @@ def initialize_physical_parameters(self, d=4., T_cold=300, T_hot=700): # Computing a stable time step dx2, dy2 = self.dx * self.dx, self.dy * self.dy self.dt = dx2 * dy2 / (2 * self.D * (dx2 + dy2)) + #self.dt = dx2 * dy2 / (self.D * (dx2 + dy2)) # Introduction of a bug on purpose to check integration tests print("dt = {}".format(self.dt)) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..22ad198 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +numpy +matplotlib +pytest +coverage +tox>=4 \ No newline at end of file diff --git a/tests/integration/test_diffusion2d.py b/tests/integration/test_diffusion2d.py index fd026b4..6130fec 100644 --- a/tests/integration/test_diffusion2d.py +++ b/tests/integration/test_diffusion2d.py @@ -3,6 +3,7 @@ """ from diffusion2d import SolveDiffusion2D +import numpy as np def test_initialize_physical_parameters(): @@ -11,9 +12,59 @@ def test_initialize_physical_parameters(): """ solver = SolveDiffusion2D() + w = 12. + h = 8. + dx = 0.5 + dy = 0.5 + solver.initialize_domain(w=w, h=h, dx=dx, dy=dy) + + d = 5. + T_cold = 280. + T_hot = 600. + solver.initialize_physical_parameters(d=d, T_cold=T_cold, T_hot=T_hot) + + # Manual calculation of expected dt from the formula used in diffusion2d.py + # dt = dx^2 * dy^2 / (2 * D * (dx^2 + dy^2)) + dx2 = dx * dx + dy2 = dy * dy + expected_dt = dx2 * dy2 / (2 * d * (dx2 + dy2)) + + assert np.isclose(solver.dt, expected_dt), 'dt not computed correctly' + def test_set_initial_condition(): """ Checks function SolveDiffusion2D.get_initial_function """ solver = SolveDiffusion2D() + + w = 10. + h = 9. + dx = 0.2 + dy = 0.2 + solver.initialize_domain(w=w, h=h, dx=dx, dy=dy) + + d = 4. + T_cold = 150. + T_hot = 500. + solver.initialize_physical_parameters(d=d, T_cold=T_cold, T_hot=T_hot) + + u = solver.set_initial_condition() + + # Manual calculation of expected initial condition u + nx = int (w / dx) + ny = int (h / dy) + expected_u = T_cold * np.ones((nx, ny)) + + r = 2 + cx = 5 + cy = 5 + r2 = r ** 2 + + for i in range(nx): + for j in range(ny): + p2 = (i * dx - cx) ** 2 + (j * dy - cy) ** 2 + if p2 < r2: + expected_u[i, j] = T_hot + + np.testing.assert_array_equal(u, expected_u, 'Initial condition u not set correctly') \ No newline at end of file diff --git a/tests/unit/test_diffusion2d_functions.py b/tests/unit/test_diffusion2d_functions.py index c4277ff..e6292d8 100644 --- a/tests/unit/test_diffusion2d_functions.py +++ b/tests/unit/test_diffusion2d_functions.py @@ -3,24 +3,85 @@ """ from diffusion2d import SolveDiffusion2D +import numpy as np +import unittest - -def test_initialize_domain(): +class TestSolveDiffusion2D(unittest.TestCase): """ - Check function SolveDiffusion2D.initialize_domain + Test class for SolveDiffusion2D """ - solver = SolveDiffusion2D() + def setUp(self): + """ + Setup function + """ + self.solver = SolveDiffusion2D() + def test_initialize_domain(self): + """ + Check function SolveDiffusion2D.initialize_domain + """ -def test_initialize_physical_parameters(): - """ - Checks function SolveDiffusion2D.initialize_domain - """ - solver = SolveDiffusion2D() + w = 12. + h = 8. + dx = 0.5 + dy = 0.4 + expected_nx = int(w / dx) + expected_ny = int(h / dy) -def test_set_initial_condition(): - """ - Checks function SolveDiffusion2D.get_initial_function - """ - solver = SolveDiffusion2D() + self.solver.initialize_domain(w=w, h=h, dx=dx, dy=dy) + + self.assertEqual(self.solver.nx, expected_nx, 'nx not correctly initialized, wrong value') + self.assertEqual(self.solver.ny, expected_ny, 'ny not correctly initialized, wrong value') + + def test_initialize_physical_parameters(self): + """ + Checks function SolveDiffusion2D.initialize_domain + """ + self.solver.dx = 0.14 + self.solver.dy = 0.16 + + d = 6. + T_cold = 290. + T_hot = 450. + + dx2 = self.solver.dx * self.solver.dx + dy2 = self.solver.dy * self.solver.dy + expected_dt = dx2 * dy2 / (2 * d * (dx2 + dy2)) + + self.solver.initialize_physical_parameters(d=d, T_cold=T_cold, T_hot=T_hot) + + self.assertEqual(self.solver.D, d, 'D not correctly initialized, wrong value') + self.assertEqual(self.solver.T_cold, T_cold, 'T_cold not correctly initialized, wrong value') + self.assertEqual(self.solver.T_hot, T_hot, 'T_hot not correctly initialized, wrong value') + self.assertEqual(self.solver.dt, expected_dt, 'dt not correctly initialized, wrong value') + + def test_set_initial_condition(self): + """ + Checks function SolveDiffusion2D.get_initial_function + """ + self.solver.w = 10. + self.solver.h = 10. + self.solver.dx = 0.5 + self.solver.dy = 0.5 + self.solver.D = 7. + self.solver.T_cold = 100. + self.solver.T_hot = 500. + + self.solver.nx = int(self.solver.w / self.solver.dx) + self.solver.ny = int(self.solver.h / self.solver.dy) + + u = self.solver.set_initial_condition() + + # Check shape + self.assertEqual(u.shape, (self.solver.nx, self.solver.ny), 'Initial condition u has wrong shape') + + # Check whether a point far from the center is cold + self.assertEqual(u[0,0], self.solver.T_cold, 'Initial condition u far from center not cold') + + # Check whether the center point is hot + self.assertEqual(u[10,10], self.solver.T_hot, 'Initial condition u at center not hot') + + # Check whether both values appear + self.assertTrue(np.any(u == self.solver.T_cold), 'Initial condition u does not contain T_cold') + self.assertTrue(np.any(u == self.solver.T_hot), 'Initial condition u does not contain T_hot') \ No newline at end of file diff --git a/tox.toml b/tox.toml new file mode 100644 index 0000000..d2b0bb1 --- /dev/null +++ b/tox.toml @@ -0,0 +1,8 @@ +requires = ["tox>=4"] +env_list = ["py"] + +[testenv] +description = "Runs tests automatically" +deps = ["-rrequirements.txt"] +setenv = {PYTHONPATH = "{toxindir}"} +commands = [["pytest", "tests", "-v"]] \ No newline at end of file