Repository: RemDelaporteMathurin/FESTIM

Issue:
TXT exports don't work in steady state
Related to #509 

Users should be able to export the txt fields in 1D for a steady state simulation



Discussion:

Patch:
diff --git a/festim/exports/txt_export.py b/festim/exports/txt_export.py
index 1bfdf5a0..52a69995 100644
--- a/festim/exports/txt_export.py
+++ b/festim/exports/txt_export.py
@@ -13,19 +13,25 @@ class TXTExport(festim.Export):
     Args:
         field (str): the exported field ("solute", "1", "retention",
             "T"...)
-        times (list): times of export. The stepsize will be modified to
-            ensure these timesteps are hit.
         label (str): label of the field. Will also be the filename.
         folder (str): the export folder
+        times (list, optional): if provided, the stepsize will be modified to
+            ensure these timesteps are exported. Otherwise exports at all
+            timesteps. Defaults to None.
     """
 
-    def __init__(self, field, times, label, folder) -> None:
+    def __init__(self, field, label, folder, times=None) -> None:
         super().__init__(field=field)
-        self.times = sorted(times)
+        if times:
+            self.times = sorted(times)
+        else:
+            self.times = times
         self.label = label
         self.folder = folder
 
     def is_it_time_to_export(self, current_time):
+        if self.times is None:
+            return True
         for time in self.times:
             if current_time == time:
                 return True
@@ -33,6 +39,8 @@ class TXTExport(festim.Export):
         return False
 
     def when_is_next_time(self, current_time):
+        if self.times is None:
+            return None
         for time in self.times:
             if current_time < time:
                 return time
@@ -45,7 +53,8 @@ class TXTExport(festim.Export):
         solution = f.project(self.function, V_DG1)
         if self.is_it_time_to_export(current_time):
             filename = "{}/{}_{}s.txt".format(self.folder, self.label, current_time)
-            busy = True
+            if dt is None:
+                filename = "{}/{}_steady.txt".format(self.folder, self.label)
             x = f.interpolate(f.Expression("x[0]", degree=1), V_DG1)
             # if the directory doesn't exist
             # create it
@@ -74,4 +83,4 @@ class TXTExports:
         self.folder = folder
         self.exports = []
         for function, label in zip(self.fields, self.labels):
-            self.exports.append(TXTExport(function, times, label, folder))
+            self.exports.append(TXTExport(function, label, folder, times))


Test patch:
diff --git a/test/system/test_misc.py b/test/system/test_misc.py
index 9f7a231f..1c54c7ba 100644
--- a/test/system/test_misc.py
+++ b/test/system/test_misc.py
@@ -1,6 +1,7 @@
 import festim as F
 import numpy as np
 import pytest
+import os
 
 
 def test_convective_flux():
@@ -118,3 +119,46 @@ def test_wrong_value_for_bc_field(field):
     with pytest.raises(ValueError):
         sim.boundary_conditions = [F.BoundaryCondition(surfaces=1, field=field)]
         sim.initialise()
+
+
+def test_txt_export_all_times(tmp_path):
+    """
+    Tests that TXTExport can be exported at all timesteps
+    """
+    my_model = F.Simulation()
+
+    my_model.mesh = F.MeshFromVertices(np.linspace(0, 1))
+    my_model.materials = F.Material(1, 1, 0)
+    my_model.settings = F.Settings(1e-10, 1e-10, final_time=1)
+    my_model.T = F.Temperature(500)
+    my_model.dt = F.Stepsize(0.1)
+
+    my_export = F.TXTExport("solute", label="mobile_conc", folder=tmp_path)
+    my_model.exports = [my_export]
+
+    my_model.initialise()
+    my_model.run()
+
+    assert os.path.exists(
+        "{}/{}_{}s.txt".format(my_export.folder, my_export.label, 0.5)
+    )
+
+
+def test_txt_export_steady_state(tmp_path):
+    """
+    Tests that TXTExport can be exported in steady state
+    """
+    my_model = F.Simulation()
+
+    my_model.mesh = F.MeshFromVertices(np.linspace(0, 1))
+    my_model.materials = F.Material(1, 1, 0)
+    my_model.settings = F.Settings(1e-10, 1e-10, transient=False)
+    my_model.T = F.Temperature(500)
+
+    my_export = F.TXTExport("solute", label="mobile_conc", folder=tmp_path)
+    my_model.exports = [my_export]
+
+    my_model.initialise()
+    my_model.run()
+
+    assert os.path.exists("{}/{}_steady.txt".format(my_export.folder, my_export.label))
diff --git a/test/unit/test_exports/test_txt_export.py b/test/unit/test_exports/test_txt_export.py
index 38568d86..7b063860 100644
--- a/test/unit/test_exports/test_txt_export.py
+++ b/test/unit/test_exports/test_txt_export.py
@@ -25,7 +25,7 @@ class TestWrite:
     @pytest.fixture
     def my_export(self, tmpdir):
         d = tmpdir.mkdir("test_folder")
-        my_export = TXTExport("solute", [1, 2, 3], "solute_label", str(Path(d)))
+        my_export = TXTExport("solute", "solute_label", str(Path(d)), times=[1, 2, 3])
 
         return my_export
 
@@ -85,7 +85,7 @@ class TestIsItTimeToExport:
     @pytest.fixture
     def my_export(self, tmpdir):
         d = tmpdir.mkdir("test_folder")
-        my_export = TXTExport("solute", [1, 2, 3], "solute_label", str(Path(d)))
+        my_export = TXTExport("solute", "solute_label", str(Path(d)), times=[1, 2, 3])
 
         return my_export
 
@@ -105,7 +105,7 @@ class TestWhenIsNextTime:
     @pytest.fixture
     def my_export(self, tmpdir):
         d = tmpdir.mkdir("test_folder")
-        my_export = TXTExport("solute", [1, 2, 3], "solute_label", str(Path(d)))
+        my_export = TXTExport("solute", "solute_label", str(Path(d)), times=[1, 2, 3])
 
         return my_export