diff --git a/ImageIterator.py b/ImageIterator.py
index a52c0585287cbb349cad87b824ac6f544fff5a22..6c90a3a4f63df55c0be84585853a136125435a95 100644
--- a/ImageIterator.py
+++ b/ImageIterator.py
@@ -135,7 +135,7 @@ class ImageIterator():
                 if not (self.register_ref_frame):
                     k_frames = range(self.problem.images_ref_frame-1,                           -1, -1)
                 else:
-                    k_frames = range(self.problem.images_ref_frame  ,                           -1, -1)
+                    k_frames = range(self.problem.images_ref_frame-1,                           -1, -1)
             self.printer.print_var("k_frames",k_frames)
 
             if (forward_or_backward == "backward"):
diff --git a/NonlinearSolver_CMA.py b/NonlinearSolver_CMA.py
index bd9777ce4a830ba5ffad3903f1b5f5b7952887f4..929670fe4923ba1e6951d92ad4877750c3312c83 100644
--- a/NonlinearSolver_CMA.py
+++ b/NonlinearSolver_CMA.py
@@ -61,6 +61,7 @@ class CMANonlinearSolver(NonlinearSolver):
         self.sigma0    = parameters["sigma0"]  if ("sigma0" in parameters)  else 2.
         self.bounds    = parameters["bounds"]  if ("bounds" in parameters)  else [0,10]
         self.ftarget   = parameters["ftarget"] if ("ftarget" in parameters) else 1E-6
+        self.tolfun    = parameters["tolfun"]  if ("tolfun"  in parameters) else 1E-11
 
         self.motion_model = parameters["motion_model"] if ("motion_model" in parameters) else "rbm"
 
@@ -87,8 +88,14 @@ class CMANonlinearSolver(NonlinearSolver):
 
         # initial guess for cma.fmin
         if (self.motion_model == "full") or (self.motion_model == "trans") or (self.motion_model == "rbm") or (self.motion_model == "rbm+eigenmodes"):
-            # FA20200221: "full" use the same initial guess, and range, as the one used for displacements
-            self.range_disp  = self.x_0_real_range["trans"]
+            # FA20200317: By default, in the "full" case the results in a frame are bounded according to the results in the previous frame
+            #             And by default, the range used is previous_result +- 0.07
+            self.restrict_x0_range       = parameters["restrict_x0_range"] if ("restrict_x0_range" in parameters) else True
+            self.restrict_x0_range_bound = parameters["restrict_x0_range_bound"] if ("restrict_x0_range_bound" in parameters) else 0.07
+
+            if (self.motion_model == "full" and self.restrict_x0_range == False) or self.motion_model != "full":
+                # FA20200221: "full" use the same initial guess, and range, as the one used for displacements
+                self.range_disp  = self.x_0_real_range["trans"]
 
         if (self.motion_model == "full"):
             assert (len(self.x_0_real) == 2), "2 values for initial guess required"
@@ -96,9 +103,17 @@ class CMANonlinearSolver(NonlinearSolver):
             self.dofs = numpy.zeros(self.n_dofs)
             self.x_0  = numpy.zeros(self.n_dofs)
 
-            for dof in range(int(self.n_dofs/2)):
-                self.x_0[2*dof]   = self.real2norm(self.x_0_real["trans_x"], self.range_disp[0], self.range_disp[1])
-                self.x_0[2*dof+1] = self.real2norm(self.x_0_real["trans_y"], self.range_disp[0], self.range_disp[1])
+            if self.restrict_x0_range:
+                self.x_real     = numpy.zeros(self.n_dofs)
+                self.range_disp = [self.x_0_real_range["trans"]]*(self.n_dofs)
+                for dof in range(int(self.n_dofs/2)):
+                    self.x_0[2*dof]   = self.real2norm(self.x_0_real["trans_x"], self.range_disp[2*dof][0], self.range_disp[2*dof][1])
+                    self.x_0[2*dof+1] = self.real2norm(self.x_0_real["trans_y"], self.range_disp[2*dof+1][0], self.range_disp[2*dof+1][1])
+
+            else:
+                for dof in range(int(self.n_dofs/2)):
+                    self.x_0[2*dof]   = self.real2norm(self.x_0_real["trans_x"], self.range_disp[0], self.range_disp[1])
+                    self.x_0[2*dof+1] = self.real2norm(self.x_0_real["trans_y"], self.range_disp[0], self.range_disp[1])
 
         elif (self.motion_model == "trans"):
             assert (len(self.x_0_real) == 2), "2 values for initial guess required"
@@ -109,17 +124,20 @@ class CMANonlinearSolver(NonlinearSolver):
         elif (self.motion_model == "rbm"):
             assert (len(self.x_0_real) == 3), "3 values for initial guess required"
             self.x_0 = numpy.zeros(len(self.x_0_real))
-            self.x_0[0] = self.real2norm(self.x_0_real["trans_x"], self.range_disp[0], self.range_disp[1])
-            self.x_0[1] = self.real2norm(self.x_0_real["trans_y"], self.range_disp[0], self.range_disp[1])
-            self.x_0[2] = self.real2norm(self.x_0_real["rot"], 0., 360.)
+            self.range_theta = self.x_0_real_range["rot"] if ("rot" in self.x_0_real_range) else [0., 360.]
+
+            self.x_0[0] = self.real2norm(self.x_0_real["trans_x"], self.range_disp[0],  self.range_disp[1])
+            self.x_0[1] = self.real2norm(self.x_0_real["trans_y"], self.range_disp[0],  self.range_disp[1])
+            self.x_0[2] = self.real2norm(self.x_0_real["rot"], self.range_theta[0], self.range_theta[1])
 
         elif (self.motion_model == "rbm+eigenmodes"):
             self.range_modal = self.x_0_real_range["modal_factors"]
+            self.range_theta = self.x_0_real_range["rot"] if ("rot" in self.x_0_real_range) else [0., 360.]
 
             self.x_0 = numpy.zeros(3+self.n_modes)
             self.x_0[0] = self.real2norm(self.x_0_real["trans_x"], self.range_disp[0], self.range_disp[1])
             self.x_0[1] = self.real2norm(self.x_0_real["trans_y"], self.range_disp[0], self.range_disp[1])
-            self.x_0[2] = self.real2norm(self.x_0_real["rot"], 0., 360.)
+            self.x_0[2] = self.real2norm(self.x_0_real["rot"], self.range_theta[0], self.range_theta[1])
 
             for ind in range(self.n_modes):
                 self.x_0[3+ind] = self.real2norm(self.x_0_real["modal_factors"][ind], self.range_modal[0], self.range_modal[1])
@@ -137,12 +155,20 @@ class CMANonlinearSolver(NonlinearSolver):
         # solve with cma.fmin
         # FA20200218: If objective_function has extra args, in cma.fmin() add them as a tuple: args=(extra_arg1, extra_arg2, ...)
         objective_function = self.compute_corr_energy
-        res = cma.fmin(objective_function, self.x_0, self.sigma0, options={'bounds': self.bounds, 'ftarget': self.ftarget, 'verb_filenameprefix': self.working_folder + "/outcmaes/"})
+        res = cma.fmin(objective_function, self.x_0, self.sigma0, options={'bounds': self.bounds, 'ftarget': self.ftarget, 'tolfun':self.tolfun, 'verb_filenameprefix': self.working_folder + "/outcmaes/"})
 
         coeffs = res[0]
         self.print_state("CMA obtained values:",coeffs)
 
-        self.x_0 = coeffs
+        if (self.motion_model == "full") and (self.restrict_x0_range):
+            for dof in range(self.n_dofs):
+                self.x_real[dof] = self.norm2real(coeffs[dof], self.range_disp[dof][0], self.range_disp[dof][1])
+
+            for dof in range(int(self.n_dofs)):
+                self.range_disp[dof] = [self.x_real[dof]-self.restrict_x0_range_bound, self.x_real[dof]+self.restrict_x0_range_bound]
+
+        else:
+            self.x_0 = coeffs
 
         success = True # FA20200218: CHECK: success always true?
         return success, res[4]
@@ -185,7 +211,11 @@ class CMANonlinearSolver(NonlinearSolver):
 
         if (self.motion_model == "full"):
             for dof in range(self.n_dofs):
-                self.dofs[dof] = self.norm2real(coeffs[dof], self.range_disp[0], self.range_disp[1])
+
+                if (self.restrict_x0_range):
+                    self.dofs[dof] = self.norm2real(coeffs[dof], self.range_disp[dof][0], self.range_disp[dof][1])
+                else:
+                    self.dofs[dof] = self.norm2real(coeffs[dof], self.range_disp[0], self.range_disp[1])
 
             self.U_tot.vector()[:] = self.dofs
 
@@ -197,7 +227,7 @@ class CMANonlinearSolver(NonlinearSolver):
                 disp_rot = 0.
 
             elif (self.motion_model == "rbm") or (self.motion_model == "rbm+eigenmodes"):
-                disp_rot = self.norm2real(coeffs[2], 0., 360.)
+                disp_rot = self.norm2real(coeffs[2], self.range_theta[0], self.range_theta[1])
 
             U_rbm = self.U_rbm(disp=[disp_x, disp_y, disp_rot])
             # print(U_rbm.vector()[:])
@@ -248,8 +278,14 @@ class CMANonlinearSolver(NonlinearSolver):
         if (self.motion_model == "full"):
             self.printer.print_str("Values of displacement in nodes:")
             for dof in range(int(self.n_dofs/2)):
-                dof_x = self.norm2real(coeffs[2*dof],   self.range_disp[0], self.range_disp[1])
-                dof_y = self.norm2real(coeffs[2*dof+1], self.range_disp[0], self.range_disp[1])
+
+                if (self.restrict_x0_range):
+                    dof_x = self.norm2real(coeffs[2*dof],   self.range_disp[2*dof][0], self.range_disp[2*dof][1])
+                    dof_y = self.norm2real(coeffs[2*dof+1], self.range_disp[2*dof+1][0], self.range_disp[2*dof+1][1])
+                else:
+                    dof_x = self.norm2real(coeffs[2*dof],   self.range_disp[0], self.range_disp[1])
+                    dof_y = self.norm2real(coeffs[2*dof+1], self.range_disp[0], self.range_disp[1])
+
                 self.printer.print_str("node "+str(dof)+": "+" "*bool(dof_x>=0)+str(round(dof_x,3))+" "*(5-len(str(round(dof_x%1,3))))+"   "+" "*bool(dof_y>=0)+str(round(dof_y,3)))
 
         else:
@@ -258,7 +294,7 @@ class CMANonlinearSolver(NonlinearSolver):
             self.printer.print_str("u_y   = "+str(round(self.norm2real(coeffs[1], self.range_disp[0], self.range_disp[1]),5)))
 
             if (self.motion_model == "rbm") or (self.motion_model == "rbm+eigenmodes"):
-                self.printer.print_str("theta = "+str(round(self.norm2real(coeffs[2], 0., 360.),5)) + "°")
+                self.printer.print_str("theta = "+str(round(self.norm2real(coeffs[2], self.range_theta[0], self.range_theta[1]),5)) + "°")
 
             if (self.motion_model == "rbm+eigenmodes"):
                 print("Values of modal coefficients:")
diff --git a/compute_displacement_error.py b/compute_displacement_error.py
index a2bcba240eec85ad437f014e45a89042f8368765..891a7c20f26d464ab9d06205051dc82847aeabc2 100644
--- a/compute_displacement_error.py
+++ b/compute_displacement_error.py
@@ -30,7 +30,8 @@ def compute_displacement_error(
         ref_ext="vtu",
         working_disp_array_name="displacement",
         ref_disp_array_name="displacement",
-        verbose=1):
+        verbose=1,
+        sort_mesh=0):
 
     working_filenames = glob.glob(working_folder+"/"+working_basename+"_[0-9]*."+working_ext)
     ref_filenames = glob.glob(ref_folder+"/"+ref_basename+"_[0-9]*."+ref_ext)
@@ -65,7 +66,20 @@ def compute_displacement_error(
         ref_disp = ref.GetPointData().GetArray(ref_disp_array_name)
         working_disp = sol.GetPointData().GetArray(working_disp_array_name)
 
-        err_int[k_frame] = numpy.sqrt(numpy.mean([numpy.sum([(working_disp.GetTuple(k_point)[k_dim]-ref_disp.GetTuple(k_point)[k_dim])**2 for k_dim in range(3)]) for k_point in range(n_points)]))
+        if (sort_mesh):
+            # FA20200311: sort_ref and sort_working are created because enumeration is not the same in the meshes of ref and sol
+            from vtk.util import numpy_support
+            coords_ref     = numpy_support.vtk_to_numpy(ref.GetPoints().GetData())
+            coords_working = numpy_support.vtk_to_numpy(sol.GetPoints().GetData())
+
+            sort_ref     = [i_sort[0] for i_sort in sorted(enumerate(coords_ref.tolist()), key=lambda k: [k[1],k[0]])]
+            sort_working = [i_sort[0] for i_sort in sorted(enumerate(coords_working.tolist()), key=lambda k: [k[1],k[0]])]
+
+            err_int[k_frame] = numpy.sqrt(numpy.mean([numpy.sum([(working_disp.GetTuple(sort_working[k_point])[k_dim]-ref_disp.GetTuple(sort_ref[k_point])[k_dim])**2 for k_dim in range(3)]) for k_point in range(n_points)]))
+
+        else:
+            err_int[k_frame] = numpy.sqrt(numpy.mean([numpy.sum([(working_disp.GetTuple(k_point)[k_dim]-ref_disp.GetTuple(k_point)[k_dim])**2 for k_dim in range(3)]) for k_point in range(n_points)]))
+
         ref_int[k_frame] = numpy.sqrt(numpy.mean([numpy.sum([(ref_disp.GetTuple(k_point)[k_dim])**2 for k_dim in range(3)]) for k_point in range(n_points)]))
         ref_max = max(ref_max, numpy.max([numpy.sum([((ref_disp.GetTuple(k_point)[k_dim])**2)**0.5 for k_dim in range(3)]) for k_point in range(n_points)]))