From 4182b9ee2eda7fa8aaa5c71f8590ee8a20cf15e3 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 31 May 2024 10:17:44 +0200 Subject: [PATCH 1/6] added test --- test/simulation/test_initialise.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/simulation/test_initialise.py b/test/simulation/test_initialise.py index f4b5ba1ed..82521c7de 100644 --- a/test/simulation/test_initialise.py +++ b/test/simulation/test_initialise.py @@ -149,6 +149,29 @@ def test_cartesian_and_surface_flux_warning(quantity, sys): my_model.initialise() +@pytest.mark.parametrize("value", [100, 0, 100.0]) +def test_initialise_temp_as_number(value): + """ + Creates a Simulation object and checks that the T attribute + can be given as an int or float + """ + # build + my_model = F.Simulation() + my_model.mesh = F.MeshFromVertices([1, 2, 3]) + my_model.materials = F.Material(id=1, D_0=1, E_D=0) + my_model.T = value + my_model.settings = F.Settings( + absolute_tolerance=1e-10, relative_tolerance=1e-10, transient=False + ) + + # run + my_model.initialise() + + # test + assert isinstance(my_model.T, F.Temperature) + assert my_model.T.value == value + + def test_error_is_raised_when_no_temp(): """ Creates a Simulation object and checks that an AttributeError is raised From 55ab10a03a28f5fa657c73bf3832fe70751ac0b1 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 31 May 2024 10:17:54 +0200 Subject: [PATCH 2/6] added setter and getter for T --- festim/generic_simulation.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/festim/generic_simulation.py b/festim/generic_simulation.py index 1426a5985..6ad4afd3a 100644 --- a/festim/generic_simulation.py +++ b/festim/generic_simulation.py @@ -164,6 +164,19 @@ def exports(self, value): "accepted types for exports are list, festim.Export or festim.Exports" ) + @property + def T(self): + return self._T + + @T.setter + def T(self, value): + if isinstance(value, festim.Temperature): + self._T = value + elif value is None: + self._T = value + elif isinstance(value, (int, float)): + self._T = festim.Temperature(value) + def attribute_source_terms(self): """Assigns the source terms (in self.sources) to the correct field (self.mobile, self.T, or traps) @@ -253,6 +266,7 @@ def initialise(self): raise AttributeError("dt must be None in steady state simulations") if self.settings.transient and self.dt is None: raise AttributeError("dt must be provided in transient simulations") + print(self.T) if not self.T: raise AttributeError("Temperature is not defined") From d9b65f87b2d9a4e52fb54aa81ff249cdcff8d1f0 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Fri, 31 May 2024 10:23:51 +0200 Subject: [PATCH 3/6] adapted documentation --- docs/source/userguide/temperature.rst | 4 ++-- festim/generic_simulation.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/userguide/temperature.rst b/docs/source/userguide/temperature.rst index c2d6c450d..98afc448f 100644 --- a/docs/source/userguide/temperature.rst +++ b/docs/source/userguide/temperature.rst @@ -13,10 +13,10 @@ The temperature can be defined as a constant value in Kelvin (K): .. code-block:: python - my_temperature = Temperature(value=300) + my_temperature = 300 -Temperature can also be defined as an expression of time and/or space. +Temperature can also be defined as an expression of time and/or space using the :class:`festim.Temperature`. For example: .. math:: diff --git a/festim/generic_simulation.py b/festim/generic_simulation.py index 6ad4afd3a..89b5a90b2 100644 --- a/festim/generic_simulation.py +++ b/festim/generic_simulation.py @@ -25,7 +25,7 @@ class Simulation: None. settings (festim.Settings, optional): The model's settings. Defaults to None. - temperature (festim.Temperature, optional): The model's + temperature (int, float, festim.Temperature, optional): The model's temperature. Can be an expression or a heat transfer model. Defaults to None. initial_conditions (list of festim.InitialCondition, optional): From f259df8acfc726a3f7c20a03f74534edea74deaa Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 4 Jun 2024 11:06:43 +0200 Subject: [PATCH 4/6] removed print --- festim/generic_simulation.py | 1 - 1 file changed, 1 deletion(-) diff --git a/festim/generic_simulation.py b/festim/generic_simulation.py index 89b5a90b2..354bf3805 100644 --- a/festim/generic_simulation.py +++ b/festim/generic_simulation.py @@ -266,7 +266,6 @@ def initialise(self): raise AttributeError("dt must be None in steady state simulations") if self.settings.transient and self.dt is None: raise AttributeError("dt must be provided in transient simulations") - print(self.T) if not self.T: raise AttributeError("Temperature is not defined") From ede311ec1cf5abd39a21028a91273e0225ce74b0 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 4 Jun 2024 11:31:01 +0200 Subject: [PATCH 5/6] same for sympy Expression --- docs/source/userguide/temperature.rst | 18 +++++++++++++----- festim/generic_simulation.py | 5 +++-- test/simulation/test_initialise.py | 20 +++++++++++++++++--- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/docs/source/userguide/temperature.rst b/docs/source/userguide/temperature.rst index 98afc448f..45efbdd9d 100644 --- a/docs/source/userguide/temperature.rst +++ b/docs/source/userguide/temperature.rst @@ -3,7 +3,8 @@ Temperature =========== Definition of a temperature field or problem is essential for hydrogen transport -and FESTIM as a whole. +and FESTIM as a whole. +Regardless of how you define the temperature of the problem, it is passed to the :code:`T` attribute of the :class:`festim.Simulation` object. ---------------------- Analytical expressions @@ -16,7 +17,7 @@ The temperature can be defined as a constant value in Kelvin (K): my_temperature = 300 -Temperature can also be defined as an expression of time and/or space using the :class:`festim.Temperature`. +Temperature can also be defined as an expression of time and/or space. For example: .. math:: @@ -29,7 +30,7 @@ would be passed to FESTIM as: from festim import x, t - my_temp = Temperature(300+2*x+3*t) + my_temp = 300 + 2*x + 3*t More complex expressions can be expressed with sympy: @@ -44,9 +45,16 @@ would be passed to FESTIM as: from festim import x, t import sympy as sp - my_temp = Temperature(sp.exp(x)*sp.sin(t)) + my_temp = sp.exp(x) * sp.sin(t) -For more details, see :class:`festim.Temperature`. +Conditional expressions are also possible: + +.. code-block:: python + + from festim import x, t + import sympy as sp + + my_temp = sp.Piecewise((400, F.t < 10), (300, True)) --------------------------- From a heat transfer solver diff --git a/festim/generic_simulation.py b/festim/generic_simulation.py index 354bf3805..6723efae3 100644 --- a/festim/generic_simulation.py +++ b/festim/generic_simulation.py @@ -2,6 +2,7 @@ from festim.h_transport_problem import HTransportProblem from fenics import * import numpy as np +import sympy as sp import warnings @@ -25,7 +26,7 @@ class Simulation: None. settings (festim.Settings, optional): The model's settings. Defaults to None. - temperature (int, float, festim.Temperature, optional): The model's + temperature (int, float, sympy.Expr, festim.Temperature, optional): The model's temperature. Can be an expression or a heat transfer model. Defaults to None. initial_conditions (list of festim.InitialCondition, optional): @@ -174,7 +175,7 @@ def T(self, value): self._T = value elif value is None: self._T = value - elif isinstance(value, (int, float)): + elif isinstance(value, (int, float, sp.Expr)): self._T = festim.Temperature(value) def attribute_source_terms(self): diff --git a/test/simulation/test_initialise.py b/test/simulation/test_initialise.py index 82521c7de..c5a3d43d3 100644 --- a/test/simulation/test_initialise.py +++ b/test/simulation/test_initialise.py @@ -1,6 +1,7 @@ import festim as F from pathlib import Path import pytest +import sympy as sp def test_initialise_changes_nb_of_sources(): @@ -149,11 +150,24 @@ def test_cartesian_and_surface_flux_warning(quantity, sys): my_model.initialise() -@pytest.mark.parametrize("value", [100, 0, 100.0]) -def test_initialise_temp_as_number(value): +@pytest.mark.parametrize( + "value", + [ + 100, + 0, + 100.0, + 0.0, + 100 + 1 * F.x, + 0 + 1 * F.x, + F.x, + F.t, + sp.Piecewise((400, F.t < 10), (300, True)), + ], +) +def test_initialise_temp_as_number_or_sympy(value): """ Creates a Simulation object and checks that the T attribute - can be given as an int or float + can be given as an int, a float or a sympy Expr """ # build my_model = F.Simulation() From 2f3c60d79568797624b38ca9a8028f1c8207fec5 Mon Sep 17 00:00:00 2001 From: RemDelaporteMathurin Date: Tue, 4 Jun 2024 20:53:51 +0200 Subject: [PATCH 6/6] added type check --- festim/generic_simulation.py | 4 ++++ test/simulation/test_initialise.py | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/festim/generic_simulation.py b/festim/generic_simulation.py index 6723efae3..f8e672bc2 100644 --- a/festim/generic_simulation.py +++ b/festim/generic_simulation.py @@ -177,6 +177,10 @@ def T(self, value): self._T = value elif isinstance(value, (int, float, sp.Expr)): self._T = festim.Temperature(value) + else: + raise TypeError( + "accepted types for T attribute are int, float, sympy.Expr or festim.Temperature" + ) def attribute_source_terms(self): """Assigns the source terms (in self.sources) to the correct field diff --git a/test/simulation/test_initialise.py b/test/simulation/test_initialise.py index c5a3d43d3..ee3e4849c 100644 --- a/test/simulation/test_initialise.py +++ b/test/simulation/test_initialise.py @@ -205,3 +205,18 @@ def test_error_is_raised_when_no_temp(): with pytest.raises(AttributeError, match="Temperature is not defined"): my_model.initialise() + + +@pytest.mark.parametrize("value", ["coucou", [0, 0]]) +def test_wrong_type_temperature(value): + """ + Creates a Simulation object and checks that a TypeError is raised + when the T attribute is given a value of the wrong type + """ + my_model = F.Simulation() + + with pytest.raises( + TypeError, + match="accepted types for T attribute are int, float, sympy.Expr or festim.Temperature", + ): + my_model.T = value