From 2fe95a08a64f3d79a15794b243e506ec081b3eb5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franck=20P=C3=A9rignon?= <franck.perignon@imag.fr>
Date: Wed, 5 Mar 2014 16:00:42 +0000
Subject: [PATCH] Review simu + tests

---
 .../gpu/tests/test_advection_nullVelocity.py  | 28 ++++----
 .../tests/test_advection_randomVelocity.py    | 24 +++----
 HySoP/hysop/operator/reprojection.py          |  5 +-
 HySoP/hysop/operator/tests/test_Stretching.py |  2 +-
 .../hysop/operator/tests/test_advec_scales.py | 44 ++++++------
 HySoP/hysop/operator/tests/test_analytic.py   |  2 +-
 .../operator/tests/test_particle_advection.py |  8 +--
 .../hysop/operator/tests/test_penalization.py | 12 ++--
 HySoP/hysop/operator/tests/test_poisson.py    |  4 +-
 HySoP/hysop/problem/simulation.py             | 68 ++++++++++++-------
 HySoP/hysop/tools/io_utils.py                 | 45 ++++++------
 11 files changed, 132 insertions(+), 110 deletions(-)

diff --git a/HySoP/hysop/gpu/tests/test_advection_nullVelocity.py b/HySoP/hysop/gpu/tests/test_advection_nullVelocity.py
index 7dabdfc4e..99865a8bd 100644
--- a/HySoP/hysop/gpu/tests/test_advection_nullVelocity.py
+++ b/HySoP/hysop/gpu/tests/test_advection_nullVelocity.py
@@ -44,7 +44,7 @@ def assertion_2D(scal, velo, advec):
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec.apply(Simulation(0., 1., 0.01))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
 
     scal_d.toHost()
 
@@ -69,8 +69,8 @@ def assertion_2D_withPython(scal, velo, advec, advec_py):
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec_py.apply(Simulation(0., 1., 0.01))
-    advec.apply(Simulation(0., 1., 0.01))
+    advec_py.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
 
     py_res = scal_d.data[0].copy()
     scal_d.toHost()
@@ -99,7 +99,7 @@ def assertion_3D(scal, velo, advec):
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec.apply(Simulation(0., 1., 0.01))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
 
     scal_d.toHost()
 
@@ -126,8 +126,8 @@ def assertion_3D_withPython(scal, velo, advec, advec_py):
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec_py.apply(Simulation(0., 1., 0.01))
-    advec.apply(Simulation(0., 1., 0.01))
+    advec_py.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
 
     py_res = scal_d.data[0].copy()
     scal_d.toHost()
@@ -954,8 +954,8 @@ def test_rectangular_domain2D():
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec.apply(Simulation(0., 1., 0.01))
-    advec_py.apply(Simulation(0., 1., 0.01))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
     scal_py_res = scal_d.data[0].copy()
 
     scal_d.toHost()
@@ -1008,8 +1008,8 @@ def test_rectangular_domain3D():
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec.apply(Simulation(0., 1., 0.01))
-    advec_py.apply(Simulation(0., 1., 0.01))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
     scal_py_res = scal_d.data[0].copy()
 
     scal_d.toHost()
@@ -1063,8 +1063,8 @@ def test_2D_vector():
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec.apply(Simulation(0., 1., 0.01))
-    advec_py.apply(Simulation(0., 1., 0.01))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
     scal_py_res_X = scal_d.data[0].copy()
     scal_py_res_Y = scal_d.data[1].copy()
 
@@ -1126,8 +1126,8 @@ def test_3D_vector():
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec.apply(Simulation(0., 1., 0.01))
-    advec_py.apply(Simulation(0., 1., 0.01))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
     scal_py_res_X = scal_d.data[0].copy()
     scal_py_res_Y = scal_d.data[1].copy()
     scal_py_res_Z = scal_d.data[2].copy()
diff --git a/HySoP/hysop/gpu/tests/test_advection_randomVelocity.py b/HySoP/hysop/gpu/tests/test_advection_randomVelocity.py
index e2165bfb0..291901935 100644
--- a/HySoP/hysop/gpu/tests/test_advection_randomVelocity.py
+++ b/HySoP/hysop/gpu/tests/test_advection_randomVelocity.py
@@ -48,8 +48,8 @@ def assertion_2D_withPython(scal, velo, advec, advec_py):
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec_py.apply(Simulation(0., 1., 0.001))
-    advec.apply(Simulation(0., 1., 0.001))
+    advec_py.apply(Simulation(tinit=0., tend=0.001, nbIter=1))
+    advec.apply(Simulation(tinit=0., tend=0.001, nbIter=1))
 
     py_res = scal_d.data[0].copy()
     scal_d.toHost()
@@ -81,8 +81,8 @@ def assertion_3D_withPython(scal, velo, advec, advec_py):
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec_py.apply(Simulation(0., 1., 0.1))
-    advec.apply(Simulation(0., 1., 0.1))
+    advec_py.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     py_res = scal_d.data[0].copy()
     scal_d.toHost()
@@ -833,8 +833,8 @@ def test_rectangular_domain2D():
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec_py.apply(Simulation(0., 1., 0.1))
-    advec.apply(Simulation(0., 1., 0.1))
+    advec_py.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     py_res = scal_d.data[0].copy()
     scal_d.toHost()
@@ -888,8 +888,8 @@ def test_rectangular_domain3D():
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec_py.apply(Simulation(0., 1., 0.01))
-    advec.apply(Simulation(0., 1., 0.01))
+    advec_py.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
 
     py_res = scal_d.data[0].copy()
     scal_d.toHost()
@@ -944,8 +944,8 @@ def test_vector_2D():
     velo_d.toDevice()
 
     print np.max(scal_d.data[0] - scal_d.data[1])
-    advec_py.apply(Simulation(0., 1., 0.01))
-    advec.apply(Simulation(0., 1., 0.01))
+    advec_py.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
 
     py_res_X = scal_d.data[0].copy()
     py_res_Y = scal_d.data[1].copy()
@@ -1005,8 +1005,8 @@ def test_vector_3D():
     scal_d.toDevice()
     velo_d.toDevice()
 
-    advec_py.apply(Simulation(0., 1., 0.01))
-    advec.apply(Simulation(0., 1., 0.01))
+    advec_py.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
 
     py_res_X = scal_d.data[0].copy()
     py_res_Y = scal_d.data[1].copy()
diff --git a/HySoP/hysop/operator/reprojection.py b/HySoP/hysop/operator/reprojection.py
index a35bb739c..b1bba130c 100644
--- a/HySoP/hysop/operator/reprojection.py
+++ b/HySoP/hysop/operator/reprojection.py
@@ -74,7 +74,7 @@ class Reprojection_criterion(Monitoring):
         self.diagnostics = npw.zeros(5)
         # Connect writer buffer to diagnostics, if required
         if self._writer is not None:
-            self._writer.buffer = self.diagnostics.reshape(1,5)
+            self._writer.buffer = self.diagnostics.reshape(1, 5)
 
         if self.checkCriterion:
             ## vorticity field
@@ -88,9 +88,8 @@ class Reprojection_criterion(Monitoring):
             self.input = [vorticity]
         else:
             self.input = []
-            
-        self.output = []
 
+        self.output = []
 
     def setUp(self):
         if not self._isUpToDate and self.checkCriterion:
diff --git a/HySoP/hysop/operator/tests/test_Stretching.py b/HySoP/hysop/operator/tests/test_Stretching.py
index 1be61b320..2d5f40e48 100755
--- a/HySoP/hysop/operator/tests/test_Stretching.py
+++ b/HySoP/hysop/operator/tests/test_Stretching.py
@@ -84,5 +84,5 @@ def test_Stretching():
     velo.initialize()
     vorti.initialize()
     stretch.setUp()
-    simulation = Simulation(0, 20, timeStep)
+    simulation = Simulation(tinit=0, tend=20, timeStep=timeStep)
     stretch.apply(simulation)
diff --git a/HySoP/hysop/operator/tests/test_advec_scales.py b/HySoP/hysop/operator/tests/test_advec_scales.py
index 3001b0529..c2df44665 100755
--- a/HySoP/hysop/operator/tests/test_advec_scales.py
+++ b/HySoP/hysop/operator/tests/test_advec_scales.py
@@ -48,8 +48,8 @@ def test_nullVelocity_m4():
         dtype=PARMES_REAL, order=ORDER)
     scal_ref_d.data[0][...] = scal_d.data[0][...]
 
-    advec.apply(Simulation(0., 1., 0.1))
-    advec_py.apply(Simulation(0., 1, 0.1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     assert np.allclose(scal_ref_d.data[0], scal_d.data[0])
 
@@ -97,8 +97,8 @@ def test_nullVelocity_vec_m4():
     scal_ref_d.data[1][...] = scal_d.data[1][...]
     scal_ref_d.data[2][...] = scal_d.data[2][...]
 
-    advec.apply(Simulation(0., 1., 0.1))
-    advec_py.apply(Simulation(0., 1., 0.1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     assert np.allclose(scal_ref_d.data[0], scal_d.data[0])
     assert np.allclose(scal_ref_d.data[1], scal_d.data[1])
@@ -125,7 +125,7 @@ def test_nullVelocity_m6():
                                      dtype=PARMES_REAL, order=ORDER)
     scal_init = npw.copy(scal_d.data[0])
 
-    advec.apply(Simulation(0., 1., 0.1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     assert np.allclose(scal_init, scal_d.data[0])
 
@@ -159,7 +159,7 @@ def test_nullVelocity_vec_m6():
     scal_init1 = npw.copy(scal_d.data[1])
     scal_init2 = npw.copy(scal_d.data[2])
 
-    advec.apply(Simulation(0., 1., 0.1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     assert np.allclose(scal_init0, scal_d.data[0])
     assert np.allclose(scal_init1, scal_d.data[1])
@@ -201,8 +201,8 @@ def test_nullVelocity_m8():
         dtype=PARMES_REAL, order=ORDER)
     scal_ref_d.data[0][...] = scal_d.data[0]
 
-    advec.apply(Simulation(0., 1., 0.1))
-    advec_py.apply(Simulation(0., 1., 0.1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     assert np.allclose(scal_ref_d.data[0], scal_d.data[0])
 
@@ -250,8 +250,8 @@ def test_nullVelocity_vec_m8():
     scal_ref_d.data[1][...] = scal_d.data[1][...]
     scal_ref_d.data[2][...] = scal_d.data[2][...]
 
-    advec.apply(Simulation(0., 1., 0.075))
-    advec_py.apply(Simulation(0., 1., 0.075))
+    advec.apply(Simulation(tinit=0., tend=0.075, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.075, nbIter=1))
 
     assert np.allclose(scal_ref_d.data[0], scal_d.data[0])
     assert np.allclose(scal_ref_d.data[1], scal_d.data[1])
@@ -301,8 +301,8 @@ def _randomVelocity_m4():
         np.random.random(scal_d.data[0].shape),
         dtype=PARMES_REAL, order=ORDER) / (2. * scal_d.resolution[1])
 
-    advec.apply(Simulation(0., 1., 0.1,))
-    advec_py.apply(Simulation(0., 1., 0.1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     assert np.allclose(scal_ref_d.data[0], scal_d.data[0])
 
@@ -358,8 +358,8 @@ def _randomVelocity_vec_m4():
         np.random.random(scal_d.data[2].shape),
         dtype=PARMES_REAL, order=ORDER) / (2. * scal_d.resolution[1])
 
-    advec.apply(Simulation(0., 1., 0.1))
-    advec_py.apply(Simulation(0., 1., 0.1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     assert np.allclose(scal_ref_d.data[0], scal_d.data[0])
     assert np.allclose(scal_ref_d.data[1], scal_d.data[1])
@@ -409,8 +409,8 @@ def test_randomVelocity_m6():
         np.random.random(scal_d.data[0].shape),
         dtype=PARMES_REAL, order=ORDER) / (2. * scal_d.resolution[1])
 
-    advec.apply(Simulation(0., 1., 0.1))
-    advec_py.apply(Simulation(0., 1., 0.1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     assert np.allclose(scal_ref_d.data[0], scal_d.data[0])
 
@@ -466,8 +466,8 @@ def test_randomVelocity_vec_m6():
         np.random.random(scal_d.data[2].shape),
         dtype=PARMES_REAL, order=ORDER) / (2. * scal_d.resolution[1])
 
-    advec.apply(Simulation(0., 1., 0.1))
-    advec_py.apply(Simulation(0., 1., 0.1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     assert np.allclose(scal_ref_d.data[0], scal_d.data[0])
     assert np.allclose(scal_ref_d.data[1], scal_d.data[1])
@@ -517,8 +517,8 @@ def test_randomVelocity_m8():
         np.random.random(scal_d.data[0].shape),
         dtype=PARMES_REAL, order=ORDER) / (2. * scal_d.resolution[1])
 
-    advec.apply(Simulation(0., 1., 0.1))
-    advec_py.apply(Simulation(0., 1., 0.1))
+    advec.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.1, nbIter=1))
 
     assert np.allclose(scal_ref_d.data[0], scal_d.data[0], atol=1e-07)
 
@@ -574,8 +574,8 @@ def test_randomVelocity_vec_m8():
         np.random.random(scal_d.data[2].shape),
         dtype=PARMES_REAL, order=ORDER) / (2. * scal_d.resolution[1])
 
-    advec.apply(Simulation(0., 1., 0.01))
-    advec_py.apply(Simulation(0., 1., 0.01))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
+    advec_py.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
 
     assert np.allclose(scal_ref_d.data[0], scal_d.data[0], atol=1e-07)
     assert np.allclose(scal_ref_d.data[1], scal_d.data[1], atol=1e-07)
diff --git a/HySoP/hysop/operator/tests/test_analytic.py b/HySoP/hysop/operator/tests/test_analytic.py
index 2d6240b71..5c5f159a5 100644
--- a/HySoP/hysop/operator/tests/test_analytic.py
+++ b/HySoP/hysop/operator/tests/test_analytic.py
@@ -70,7 +70,7 @@ res2D = [33, 33]
 L2D = [1., 1.]
 origin2D = [0., 0.]
 nbc = 4
-simu = Simulation(0., 1., 0.1)
+simu = Simulation(tinit=0., tend=0.1, nbIter=1)
 
 ## I - Tests with direct calls of field.initialize
 
diff --git a/HySoP/hysop/operator/tests/test_particle_advection.py b/HySoP/hysop/operator/tests/test_particle_advection.py
index d4b604ca8..3a846186e 100644
--- a/HySoP/hysop/operator/tests/test_particle_advection.py
+++ b/HySoP/hysop/operator/tests/test_particle_advection.py
@@ -70,7 +70,7 @@ def assertion(scal, advec):
                                      dtype=PARMES_REAL, order=ORDER)
     scal_init = npw.copy(scal_d.data[0])
 
-    advec.apply(Simulation(0., 1., 0.01))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
     return np.allclose(scal_init, scal_d.data[0])
 
 
@@ -86,7 +86,7 @@ def assertion_vector2D(scal, advec):
     scal1_init = npw.copy(scal_d.data[0])
     scal2_init = npw.copy(scal_d.data[1])
 
-    advec.apply(Simulation(0., 1., 0.01))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
     return np.allclose(scal1_init, scal_d.data[0]) and \
         np.allclose(scal2_init, scal_d.data[1])
 
@@ -106,7 +106,7 @@ def assertion_vector3D(scal, advec):
     scal2_init = npw.copy(scal_d.data[1])
     scal3_init = npw.copy(scal_d.data[2])
 
-    advec.apply(Simulation(0., 1., 0.01))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
     return np.allclose(scal1_init, scal_d.data[0]) and \
         np.allclose(scal2_init, scal_d.data[1]) and \
         np.allclose(scal3_init, scal_d.data[2])
@@ -125,7 +125,7 @@ def assertion_list(scal, advec):
     scal1_init = npw.copy(scal1_d.data[0])
     scal2_init = npw.copy(scal2_d.data[0])
 
-    advec.apply(Simulation(0., 1., 0.01))
+    advec.apply(Simulation(tinit=0., tend=0.01, nbIter=1))
     print scal1_init, scal1_d.data[0]
     print scal2_init, scal2_d.data[0]
     return np.allclose(scal1_init, scal1_d.data[0]) and \
diff --git a/HySoP/hysop/operator/tests/test_penalization.py b/HySoP/hysop/operator/tests/test_penalization.py
index 239821a08..2b3d68c5c 100644
--- a/HySoP/hysop/operator/tests/test_penalization.py
+++ b/HySoP/hysop/operator/tests/test_penalization.py
@@ -35,7 +35,7 @@ def testPenalScal2D():
     topo = scal.discreteFields.keys()[0]
     scd = scal.discreteFields[topo]
     scd[0] = 128
-    penal.apply(Simulation())
+    penal.apply(Simulation(nbIter=100))
     scalRef = Field(domain=dom, name='ScalarRef')
     scalRef.discretize(topo)
     scalRef.load('ref_scal2D_PenalHspherePlane', fieldname='ScalarRef')
@@ -65,7 +65,7 @@ def testPenalScal3D():
     topo = scal.discreteFields.keys()[0]
     scd = scal.discreteFields[topo]
     scd[0] = 128
-    penal.apply(Simulation())
+    penal.apply(Simulation(nbIter=100))
     scalRef = Field(domain=dom, name='ScalarRef')
     scd = scalRef.discretize(topo)
     scalRef.load('ref_scal3D_PenalHspherePlane', fieldname='ScalarRef')
@@ -91,7 +91,7 @@ def testPenalScal2D_2():
     topo = scal.discreteFields.keys()[0]
     scd = scal.discreteFields[topo]
     scd[0] = 128
-    penal.apply(Simulation())
+    penal.apply(Simulation(nbIter=100))
     scalRef = Field(domain=dom, name='ScalarRef')
     scalRef.discretize(topo)
     scalRef.load('ref_scal2D_PenalSphere', fieldname='ScalarRef')
@@ -119,7 +119,7 @@ def testPenalScal3D_2():
     topo = scal.discreteFields.keys()[0]
     scd = scal.discreteFields[topo]
     scd[0] = 128
-    penal.apply(Simulation())
+    penal.apply(Simulation(nbIter=100))
     scalRef = Field(domain=dom, name='ScalarRef')
     scd = scalRef.discretize(topo)
     scalRef.load('ref_scal3D_PenalSphere', fieldname='ScalarRef')
@@ -144,7 +144,7 @@ def testPenalVec2D():
     velod = velo.discreteFields[topo]
     velod[0] = 128
     velod[1] = 12
-    penal.apply(Simulation())
+    penal.apply(Simulation(nbIter=100))
     veloRef = Field(domain=dom, name='VeloRef', isVector=True)
     veloRef.discretize(topo)
     veloRef.load('ref_velo2D_PenalHspherePlane', fieldname='VeloRef')
@@ -172,7 +172,7 @@ def testPenalVec3D():
     velod[0] = 128
     velod[1] = 12
     velod[2] = 4.3
-    penal.apply(Simulation())
+    penal.apply(Simulation(nbIter=100))
     veloRef = Field(domain=dom, name='VeloRef', isVector=True)
     veloRef.discretize(topo)
     veloRef.load('ref_velo3D_PenalHspherePlane', fieldname='VeloRef')
diff --git a/HySoP/hysop/operator/tests/test_poisson.py b/HySoP/hysop/operator/tests/test_poisson.py
index ebd72ccfe..6880b2a48 100755
--- a/HySoP/hysop/operator/tests/test_poisson.py
+++ b/HySoP/hysop/operator/tests/test_poisson.py
@@ -77,7 +77,7 @@ def test_Poisson3D():
     refOp = Analytic(ref, formula=computeRef,
                      resolutions={ref: resol})
 
-    simu = Simulation()
+    simu = Simulation(nbIter=10)
     refOp.discretize()
     refOp.setUp()
     poisson.discretize()
@@ -115,7 +115,7 @@ def test_Poisson3D():
 ##     refOp = Analytic(ref, formula=computeRef2D,
 ##                      resolutions={ref: resol})
 
-##     simu = Simulation()
+##     simu = Simulation(nbIter=10)
 ##     refOp.setUp()
 ##     poisson.setUp()
 ##     refOp.apply(simu)
diff --git a/HySoP/hysop/problem/simulation.py b/HySoP/hysop/problem/simulation.py
index 50265dac2..20247b3a1 100644
--- a/HySoP/hysop/problem/simulation.py
+++ b/HySoP/hysop/problem/simulation.py
@@ -3,6 +3,8 @@
 
 Description of the simulation parameters (time, iteration ...)
 """
+import sys
+eps = sys.float_info.epsilon
 
 
 class Simulation(object):
@@ -10,23 +12,18 @@ class Simulation(object):
     Setup for simulation parameters.
     """
 
-    def __init__(self, tinit=0.0, tend=1.0, timeStep=0.01, iterMax=100):
+    def __init__(self, tinit=0.0, tend=1.0, nbIter=None, timeStep=None,
+                 iterMax=1000):
         """
         Creates a Timer.
-
-        @param tend : Simulation final time.
-        @param isAdaptative: Boolean value which determines if
-        the time step is adaptative.
-        @param timeStep : Time step. This is a "variable" object.
-        Its data attribute is a list made of a real-type value
-        corresponding to the initial timestep. If the time step is
-        not chosen to be adaptative, then this initial timestep
-        will be considered as the fixed timestep for the whole simulation.
         @param tinit : Simulation starting time.
-        @param iterMax : Simulation maximum iteration number.
-        @param bridgeOp : Redistribute operator
-        @param computeTimeStepOp : Operator which evaluates
-        the adaptative time step according to the flow fields
+        @param tend : Simulation final time.
+        @param nbIter : number of required iterations
+        @param timeStep : default time step
+        @param iterMax : maximum number of iterations (useful
+        only if timeStep is modified. See adaptativeTimeStep operator).
+
+        If both timeStep and nbIter are given, timeStep is not used.
 
         Notation:
         iteration number 'currentIteration'
@@ -41,23 +38,35 @@ class Simulation(object):
         ## Is simulation is terminated
         self.isOver = False
         ## Iteration counter
-        self.currentIteration = 0
-        ## Simulation time step
-        self.timeStep = timeStep
+        self.currentIteration = -1
+        ## Number of iterations
+        if nbIter is not None:
+            self.nbIter = nbIter
+            if nbIter is not None and timeStep is not None:
+                print 'Warning : both nbIter and timeStep are given.\
+                timeStep is ignored'
+            self.timeStep = (self.end - self.start) / self.nbIter
+            print "{0:24.16f}".format(self.timeStep)
+        elif timeStep is not None:
+            ## Simulation time step
+            self.timeStep = timeStep
+        else:
+            raise ValueError('You must set nbIter or timeStep value.')
+        self.iterMax = iterMax
+        assert iterMax >= nbIter
         ## Starting time for the current iteration
         self.tk = tinit
         ## tk + dt
         self.tkp1 = tinit + self.timeStep
-        ## Maximum number of iterations
-        self.iterMax = iterMax
         self._lastStep = False
-        print self.start, self.timeStep, self.end
-        print self.start + self.timeStep
         assert self.end > self.start, \
             'Final time must be greater than initial time'
         assert (self.start + self.timeStep) <= self.end,\
             'start + step is bigger than end.'
 
+        ## Internal tolerance for timer
+        self.tol = eps
+
     def advance(self):
         """
         Proceed to next time.
@@ -80,8 +89,11 @@ class Simulation(object):
                 # Adjust last timestep to reach self.end
                 if self.tkp1 > self.end:
                     self.timeStep = self.end - self.tk
-                    self.tkp1 = self.end
-                    self._lastStep = True
+                    if self.timeStep <= self.tol:
+                        self.isOver = True
+                    else:
+                        self.tkp1 = self.end
+                        self._lastStep = True
             else:
                 # iteration number is reached
                 self.isOver = True
@@ -112,6 +124,16 @@ class Simulation(object):
         return s
 
     def initialize(self):
+        self.tk = self.start
+        self.tkp1 = self.start + self.timeStep
         self.time = self.tkp1
         self.isOver = False
         self.currentIteration = 0
+        self._lastStep = False
+
+    def finalize(self):
+        """
+        Useful for printers if printer.frequency is not 1
+        """
+        self.isOver = True
+        self.currentIteration = -1
diff --git a/HySoP/hysop/tools/io_utils.py b/HySoP/hysop/tools/io_utils.py
index 58fabff58..291e2dddc 100644
--- a/HySoP/hysop/tools/io_utils.py
+++ b/HySoP/hysop/tools/io_utils.py
@@ -78,27 +78,6 @@ class io(object):
 
 class Writer(object):
     """
-    @param params : dictionnary to set parameters
-    for output file (name, path, ...)
-    available keys are :
-    - filename : file name with full or relative path.
-    Default = data.out, in filepath.
-    If filename contains absolute path, filepath is ignored.
-    - filepath : path to the i/o file.
-    Default =  parmepy.tools.io_utils.io.defaultPath.
-    - frequency : how often output file is written. Default = 1
-    (i.e. every iteration). N means writes every N iteration and
-    0 means write only after last iteration.
-    - io_rank : mpi process rank (in comm) that performs writting. Default = 0
-    - writebuffshape : shape (numpy array) of the output buffer,
-     written in filename. Default = 1.
-    - safeOutput : boolean. Default = True.
-    True --> open/close file everytime data are written.
-    False --> open at init and close during finalize. Cost less but if simu
-    crashes, data are lost.
-    @param comm : mpi communicator that handles this
-    writer. Default = parmepy.mpi.main_comm.
-
     Usage :
     \code
     >>> import parmepy.tools.io_utils as io
@@ -116,6 +95,27 @@ class Writer(object):
     """
     def __init__(self, params, comm=None):
         """
+        @param params : dictionnary to set parameters
+        for output file (name, path, ...)
+        available keys are :
+        - filename : file name with full or relative path.
+        Default = data.out, in filepath.
+        If filename contains absolute path, filepath is ignored.
+        - filepath : path to the i/o file.
+        Default =  parmepy.tools.io_utils.io.defaultPath.
+        - frequency : how often output file is written. Default = 1
+        (i.e. every iteration). N means writes every N iteration and
+        0 means write only after last iteration.
+        - io_rank : mpi process rank (in comm)
+         that performs writting. Default = 0
+        - writebuffshape : shape (numpy array) of the output buffer,
+         written in filename. Default = 1.
+        - safeOutput : boolean. Default = True.
+        True --> open/close file everytime data are written.
+        False --> open at init and close during finalize. Cost less but if simu
+        crashes, data are lost.
+        @param comm : mpi communicator that handles this
+        writer. Default = parmepy.mpi.main_comm.
         """
         # Directory for output
         if "filepath" in params:
@@ -191,7 +191,8 @@ class Writer(object):
         @param ite : current iteration number
         """
         rank = self.comm.Get_rank()
-        return rank == self.io_rank and (ite % self.frequency) == 0
+        num = ite + 1  # Number of iterations done
+        return rank == self.io_rank and (num % self.frequency) == 0
 
     def _fullwrite(self):
         if self.comm.Get_rank() == self.io_rank:
-- 
GitLab