diff --git a/examples/analytic/analytic.py b/examples/analytic/analytic.py
index f0606961be1e349d31e77d8ed84820479da0d96f..0f2e1eff54e177ff97084160ec083daf21350b28 100755
--- a/examples/analytic/analytic.py
+++ b/examples/analytic/analytic.py
@@ -88,7 +88,7 @@ def compute(args):
     # Create the problem we want to solve and insert our operator
     problem = Problem()
     problem.insert(analytic)
-    problem.build()
+    problem.build(args)
 
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/bubble/periodic_bubble.py b/examples/bubble/periodic_bubble.py
index 6a1e7104c05b6c873c690723e8d52d87a0f3b042..8029f494f7fde2818c9860565e02ca6970e38285 100644
--- a/examples/bubble/periodic_bubble.py
+++ b/examples/bubble/periodic_bubble.py
@@ -262,7 +262,7 @@ def compute(args):
                    # integrate_enstrophy, integrate_rho, integrate_mu,
                    min_max_rho, min_max_mu, min_max_U, min_max_W, 
                    adapt_dt)
-    problem.build()
+    problem.build(args)
 
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/bubble/periodic_bubble_levelset.py b/examples/bubble/periodic_bubble_levelset.py
index a581cda1aeb3471c0735a552baf8e609091d91a4..6fcaf328e800ef37e734ecca042fe803b1e18e45 100644
--- a/examples/bubble/periodic_bubble_levelset.py
+++ b/examples/bubble/periodic_bubble_levelset.py
@@ -265,7 +265,7 @@ def compute(args):
                    integrate_enstrophy, integrate_rho, integrate_mu,
                    min_max_U, min_max_W, 
                    adapt_dt)
-    problem.build()
+    problem.build(args)
 
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/bubble/periodic_bubble_levelset_penalization.py b/examples/bubble/periodic_bubble_levelset_penalization.py
index 8932033bd503fc0fd96aec2e07c19634ff0783a5..5732752c4647012cd81bd9454c2400e17223aa22 100644
--- a/examples/bubble/periodic_bubble_levelset_penalization.py
+++ b/examples/bubble/periodic_bubble_levelset_penalization.py
@@ -305,7 +305,7 @@ def compute(args):
                    integrate_enstrophy, integrate_rho, integrate_mu,
                    min_max_U, min_max_W, 
                    adapt_dt)
-    problem.build()
+    problem.build(args)
 
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/bubble/periodic_jet_levelset.py b/examples/bubble/periodic_jet_levelset.py
index 6db6264a10772cafc7f927eeceffa83e52f7847f..9f4ba310f2348a1844db8c205dfa883c3dcce464 100644
--- a/examples/bubble/periodic_jet_levelset.py
+++ b/examples/bubble/periodic_jet_levelset.py
@@ -255,7 +255,7 @@ def compute(args):
                    integrate_enstrophy, integrate_rho,
                    min_max_U, min_max_W, 
                    adapt_dt)
-    problem.build()
+    problem.build(args)
 
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/cylinder/oscillating_cylinder.py b/examples/cylinder/oscillating_cylinder.py
index e46c605a828b0645d3b83f43a27baa1db59302bb..e4a34206cf2e6c9f8b295433f1d1b534d499d01e 100644
--- a/examples/cylinder/oscillating_cylinder.py
+++ b/examples/cylinder/oscillating_cylinder.py
@@ -231,7 +231,7 @@ def compute(args):
                    dump_fields,
                    min_max_U, min_max_W, 
                    adapt_dt)
-    problem.build()
+    problem.build(args)
 
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/example_utils.py b/examples/example_utils.py
index b684387a4d076ce7d60f0c39f1f4a08cde78fa32..b11eaa2b1883d50650dca28a4d8bc82ae9cc7319 100644
--- a/examples/example_utils.py
+++ b/examples/example_utils.py
@@ -137,6 +137,7 @@ class HysopArgParser(argparse.ArgumentParser):
         self._add_main_args()
         self._add_domain_args()
         self._add_simu_args()
+        self._add_problem_args()
         self._add_method_args()
         self._add_threading_args()
         self._add_opencl_args()
@@ -161,6 +162,7 @@ class HysopArgParser(argparse.ArgumentParser):
         self._check_positional_args(args)
         self._check_main_args(args)
         self._check_domain_args(args)
+        self._check_problem_args(args)
         self._check_simu_args(args)
         self._check_method_args(args)
         self._check_opencl_args(args)
@@ -299,6 +301,9 @@ class HysopArgParser(argparse.ArgumentParser):
         args.add_argument('-cp', '--compute-precision', type=str, default='fp32',
                 dest='compute_precision', 
                 help='Floating-point precision used to discretize the parameters and fields.')
+        args.add_argument('-ei', '--enforce-implementation', type=str, default='true',
+                dest='enforce_implementation',
+                help='If set to false, the library may use another implementation than user specified one for some operators.')
         return args
 
     def _check_main_args(self, args):
@@ -307,6 +312,7 @@ class HysopArgParser(argparse.ArgumentParser):
         args.compute_precision = self._convert_precision('compute_precision', 
                                                             args.compute_precision)
         args.dtype = self._precision_to_dtype('compute_precision', args.compute_precision)
+        args.enforce_implementation = self._convert_bool('enforce_implementation', args.enforce_implementation)
 
     def _add_domain_args(self):
         discretization = self.add_argument_group('Discretization parameters')
@@ -401,32 +407,41 @@ class HysopArgParser(argparse.ArgumentParser):
         simu.add_argument('-lcfl', '--lagrangian-cfl', type=float, default=None, 
                 dest='lcfl',
                 help='Specify LCFL for adaptive time stepping.')
-        simu.add_argument('-stopi', '--stop-at-initialization', default=False, action='store_true',
+        simu.add_argument('-dr', '--dry-run', default=False, action='store_true',
+                dest='dry_run',
+                help='Stop execution before the first simulation iteration.')
+        
+    def _add_problem_args(self):
+        problem = self.add_argument_group('Problem parameters')
+        problem.add_argument('-stopi', '--stop-at-initialization', default=False, action='store_true',
                 dest='stop_at_initialization',
                 help='Stop execution before problem initialization.')
-        simu.add_argument('-stopd', '--stop-at-discretization', default=False, action='store_true',
+        problem.add_argument('-stopd', '--stop-at-discretization', default=False, action='store_true',
                 dest='stop_at_discretization',
                 help='Stop execution before problem discretization.')
-        simu.add_argument('-stopwp', '--stop-at-work-properties', default=False, action='store_true',
+        problem.add_argument('-stopwp', '--stop-at-work-properties', default=False, action='store_true',
                 dest='stop_at_work_properties',
                 help='Stop execution before problem work properties retrieval.')
-        simu.add_argument('-stopwa', '--stop-at-work-allocation', default=False, action='store_true',
+        problem.add_argument('-stopwa', '--stop-at-work-allocation', default=False, action='store_true',
                 dest='stop_at_work_allocation',
-                help='Stop execution before problem work properties allocation (allocation of temporary buffers).')
-        simu.add_argument('-stops', '--stop-at-setup', default=False, action='store_true',
+                help='Stop execution before problem work properties allocation.')
+        problem.add_argument('-stops', '--stop-at-setup', default=False, action='store_true',
                 dest='stop_at_setup',
                 help='Stop execution before problem setup.')
-        simu.add_argument('-dr', '--dry-run', default=False, action='store_true',
-                dest='dry_run',
-                help='Stop execution before the first simulation iteration.')
-        return simu
+        problem.add_argument('-stopb', '--stop-at-build', default=False, action='store_true',
+                dest='stop_at_build',
+                help='Stop execution once the problem has been built.')
+        return problem
+
+    def _check_problem_args(self, args):
+        self._check_default(args, ('stop_at_initialization', 'stop_at_discretization', 'stop_at_setup', 
+                                    'stop_at_work_properties', 'stop_at_work_allocation', 'stop_at_build'), bool, allow_none=False)
 
     def _check_simu_args(self, args):
         self._check_default(args, ('tstart', 'tend'), float)
         self._check_default(args, 'dt', float, allow_none=True)
         self._check_default(args, 'nb_iter', int, allow_none=True)
-        self._check_default(args, ('dry_run', 'stop_at_initialization', 'stop_at_discretization', 'stop_at_setup', 
-                                    'stop_at_work_properties', 'stop_at_work_allocation'), bool, allow_none=False)
+        self._check_default(args, 'dry_run', bool, allow_none=False)
         self._check_positive(args, 'dt', strict=True, allow_none=True)
         self._check_positive(args, 'nb_iter', strict=True, allow_none=True)
         self._check_positive(args, 'max_iter', strict=True, allow_none=True)
@@ -527,7 +542,7 @@ class HysopArgParser(argparse.ArgumentParser):
         threading.add_argument('--fftw-planner-effort', type=str, default='FFTW_ESTIMATE', 
               dest='fftw_planner_effort',
               help='Set default planning effort for FFTW plans. The actual number of threads used by FFTW may depend on the planning step. This parameter will set HYSOP_FFTW_PLANNER_EFFORT.')
-        threading.add_argument('--fftw-planner-timelimit', type=str, default='FFTW_NO_TIMELIMIT', 
+        threading.add_argument('--fftw-planner-timelimit', type=str, default='-1', 
               dest='fftw_planner_timelimit',
               help='Set an approximate upper bound in seconds for FFTW planning. This parameter will set HYSOP_FFTW_PLANNER_TIMELIMIT.')
         return threading
@@ -1094,7 +1109,7 @@ class HysopArgParser(argparse.ArgumentParser):
             'fftw_patient':    'FFTW_PATIENT',
             'fftw_exhaustive': 'FFTW_EXHAUSTIVE',
         }
-        self._check_convert(argname, val, values)
+        return self._check_convert(argname, val, values)
     
     def _convert_numba_threading_layer(self, argname, val):
         values = {
@@ -1257,6 +1272,9 @@ class HysopHelpFormatter(ColorHelpFormatter):
                     '--version', '--hardware-info', '--hardware-statistics')
             p  = not action.option_strings[0].startswith('--opencl')
             p &= not action.option_strings[0].startswith('--autotuner')
+            p &= not action.option_strings[0].startswith('--fftw')
+            p &= 'thread' not in action.option_strings[0]
+            p &= 'stop' not in action.option_strings[0]
             p &= (action.option_strings[0] not in blacklist)
             p &= (len(action.option_strings)<2) or (action.option_strings[1] not in blacklist)
             return p
diff --git a/examples/particles_above_salt/particles_above_salt_bc.py b/examples/particles_above_salt/particles_above_salt_bc.py
index 9b1cb78b7fa2a9ff2b47ce259c780eb5881066cc..73a0491c389c9a52da0c080acb1c41830a486caa 100644
--- a/examples/particles_above_salt/particles_above_salt_bc.py
+++ b/examples/particles_above_salt/particles_above_salt_bc.py
@@ -105,6 +105,7 @@ def compute(args):
 
     # Setup usual implementation specific variables
     impl = args.impl
+    enforce_implementation = args.enforce_implementation
     extra_op_kwds = {'mpi_params': mpi_params}
     if (impl is Implementation.PYTHON):
         method = {}
@@ -183,7 +184,7 @@ def compute(args):
     
     #> Diffusion of vorticity, S and C
     diffuse_S = Diffusion(implementation=impl,
-             enforce_implementation=False,
+             enforce_implementation=enforce_implementation,
              name='diffuse_S',
              pretty_name='diffS',
              nu = nu_S,
@@ -192,7 +193,7 @@ def compute(args):
              dt=dt, 
              **extra_op_kwds)
     diffuse_C = Diffusion(implementation=impl,
-             enforce_implementation=False,
+             enforce_implementation=enforce_implementation,
              name='diffuse_C',
              pretty_name='diffC',
              nu = nu_C,
@@ -225,7 +226,7 @@ def compute(args):
                             variables={velo:npts, vorti: npts},
                             diffusion=nu_W, dt=dt,
                             implementation=impl,
-                            enforce_implementation=False,
+                            enforce_implementation=enforce_implementation,
                             **extra_op_kwds)
     
     #> Operator to compute the infinite norm of the velocity
diff --git a/examples/particles_above_salt/particles_above_salt_bc_3d.py b/examples/particles_above_salt/particles_above_salt_bc_3d.py
index 2592f8f05b6b7f20c757b11c7bb1f577d53d4dd8..f16898e6140c41e070f9776cab058b7a0fe62a52 100644
--- a/examples/particles_above_salt/particles_above_salt_bc_3d.py
+++ b/examples/particles_above_salt/particles_above_salt_bc_3d.py
@@ -105,6 +105,8 @@ def compute(args):
 
     # Setup usual implementation specific variables
     impl = args.impl
+    enforce_implementation = args.enforce_implementation
+
     extra_op_kwds = {'mpi_params': mpi_params}
     if (impl is Implementation.PYTHON):
         method = {}
@@ -183,7 +185,7 @@ def compute(args):
     
     #> Diffusion of vorticity, S and C
     diffuse_S = Diffusion(implementation=impl,
-             enforce_implementation=False,
+             enforce_implementation=enforce_implementation,
              name='diffuse_S',
              pretty_name='diffS',
              nu = nu_S,
@@ -191,7 +193,7 @@ def compute(args):
              variables = {S: npts},
              dt=dt, **extra_op_kwds)
     diffuse_C = Diffusion(implementation=impl,
-             enforce_implementation=False,
+             enforce_implementation=enforce_implementation,
              name='diffuse_C',
              pretty_name='diffC',
              nu = nu_C,
@@ -221,11 +223,12 @@ def compute(args):
     ### Build standard operators
     #> Poisson operator to recover the velocity from the vorticity
     poisson = PoissonCurl(name='poisson',
-                          enforce_implementation=False,
                           velocity=velo, vorticity=vorti, 
                           variables={velo:npts, vorti: npts},
                           diffusion=nu_W, dt=dt,
-                          implementation=impl, **extra_op_kwds)
+                          implementation=impl, 
+                          enforce_implementation=enforce_implementation,
+                          **extra_op_kwds)
     
     #> Operator to compute the infinite norm of the velocity
     min_max_U = MinMaxFieldStatistics(name='min_max_U', field=velo,
@@ -282,7 +285,7 @@ def compute(args):
                    dump_fields,
                    splitting, 
                    min_max_U, min_max_W, adapt_dt)
-    problem.build()
+    problem.build(args)
     
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/particles_above_salt/particles_above_salt_periodic.py b/examples/particles_above_salt/particles_above_salt_periodic.py
index e923dd3a76bc6c35f1b8b80d7e1a670fcae6c0f2..26c9625aefd9b4abd01d41d018e39b1e87c542f4 100644
--- a/examples/particles_above_salt/particles_above_salt_periodic.py
+++ b/examples/particles_above_salt/particles_above_salt_periodic.py
@@ -307,7 +307,7 @@ def compute(args):
                    compute_mean_fields,
                    min_max_U, min_max_W, 
                    adapt_dt)
-    problem.build()
+    problem.build(args)
     
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/particles_above_salt/particles_above_salt_symmetrized.py b/examples/particles_above_salt/particles_above_salt_symmetrized.py
index 87a1fabffc142204f519b1db84b29b16b02ea904..af63fdc06586e94a4b48611efe30d97102bada3d 100644
--- a/examples/particles_above_salt/particles_above_salt_symmetrized.py
+++ b/examples/particles_above_salt/particles_above_salt_symmetrized.py
@@ -292,7 +292,7 @@ def compute(args):
                    compute_mean_fields,
                    min_max_U, min_max_W, 
                    adapt_dt)
-    problem.build()
+    problem.build(args)
     
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/scalar_advection/scalar_advection.py b/examples/scalar_advection/scalar_advection.py
index 26cbbc1cf0912b0e07de5f6950db14cbe293c174..3cf75c6cc0fa6c53d00b83c8a3ed66250e166cc4 100644
--- a/examples/scalar_advection/scalar_advection.py
+++ b/examples/scalar_advection/scalar_advection.py
@@ -110,7 +110,7 @@ def compute(args):
     
     # Add a writer of input field at given frequency.
     problem.dump_inputs(fields=scalar, filename='S0', frequency=args.dump_freq)
-    problem.build()
+    problem.build(args)
 
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/scalar_diffusion/scalar_diffusion.py b/examples/scalar_diffusion/scalar_diffusion.py
index 62ea8c52d178dd57b1e94273f02bc4100019f5e3..88683431b40e5341c1614a95799f9a83c12ccd2f 100755
--- a/examples/scalar_diffusion/scalar_diffusion.py
+++ b/examples/scalar_diffusion/scalar_diffusion.py
@@ -81,7 +81,7 @@ def compute(args):
     problem = Problem(method=method)
     problem.insert(splitting)
     problem.dump_inputs(fields=scalar, filename='S0', frequency=args.dump_freq)
-    problem.build()
+    problem.build(args)
     
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/shear_layer/shear_layer.py b/examples/shear_layer/shear_layer.py
index 789d96876736fa5a12ae7d45ee008c5bafcaefdc..d065729dee81caa65fa98846293b0be220d3bc74 100644
--- a/examples/shear_layer/shear_layer.py
+++ b/examples/shear_layer/shear_layer.py
@@ -140,7 +140,7 @@ def compute(args):
     )
     problem = Problem(method=method)
     problem.insert(poisson, splitting, min_max_U, min_max_W, adapt_dt)
-    problem.build()
+    problem.build(args)
     
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/examples/taylor_green/taylor_green.py b/examples/taylor_green/taylor_green.py
index 92a1275fa44b5f6866d61b2ca8f5ab8c809ad19a..d582b457e4a1c9824ff8e1284b3e9ffae4da17b2 100644
--- a/examples/taylor_green/taylor_green.py
+++ b/examples/taylor_green/taylor_green.py
@@ -258,7 +258,7 @@ def compute(args):
     problem.insert(poisson, advec, splitting,
                    min_max_U, min_max_W, enstrophy_op, 
                    adapt_dt, plot)
-    problem.build()
+    problem.build(args)
 
     # If a visu_rank was provided, and show_graph was set,
     # display the graph on the given process rank.
diff --git a/hysop/__init__.py.in b/hysop/__init__.py.in
index fa99e48793562d7372ba4e9afd05373752840a56..0ac87c567fbbd66ee5de98fd45e044128160f0e7 100644
--- a/hysop/__init__.py.in
+++ b/hysop/__init__.py.in
@@ -60,7 +60,7 @@ __DEFAULT_NUMBA_TARGET__ = ('parallel' if __ENABLE_THREADING__ else 'cpu')
 # FFTW
 __FFTW_NUM_THREADS__       = get_env('FFTW_NUM_THREADS',        __MAX_THREADS__)
 __FFTW_PLANNER_EFFORT__    = get_env('FFTW_PLANNER_EFFORT',    'FFTW_ESTIMATE')
-__FFTW_PLANNER_TIMELIMIT__ = get_env('FFTW_PLANNER_TIMELIMIT', 'FFTW_NO_TIMELIMIT')
+__FFTW_PLANNER_TIMELIMIT__ = int(get_env('FFTW_PLANNER_TIMELIMIT', -1))
 
 # OpenCL
 __DEFAULT_PLATFORM_ID__ = int(get_env('DEFAULT_PLATFORM_ID', @OPENCL_DEFAULT_OPENCL_PLATFORM_ID@))
diff --git a/hysop/numerics/fft/fftw_fft.py b/hysop/numerics/fft/fftw_fft.py
index 855a2e7cbaf56e54c0ed69fa3949226e061e3954..72bcda107656df68d19b470a25cae5e1630466de 100644
--- a/hysop/numerics/fft/fftw_fft.py
+++ b/hysop/numerics/fft/fftw_fft.py
@@ -111,9 +111,9 @@ class FftwFFT(HostFFTI):
                        warn_on_misalignment=True,
                        backend=None, allocator=None,
                        **kwds):
-        threads            = first_not_None(threads,           __FFTW_NUM_THREADS__)
-        planner_effort     = first_not_None(planner_effort,    __FFTW_PLANNER_EFFORT__)
-        planning_timelimit = first_not_None(planner_timelimit, __FFTW_PLANNER_TIMELIMIT__)
+        threads            = first_not_None(threads,            __FFTW_NUM_THREADS__)
+        planner_effort     = first_not_None(planner_effort,     __FFTW_PLANNER_EFFORT__)
+        planning_timelimit = first_not_None(planning_timelimit, __FFTW_PLANNER_TIMELIMIT__)
         super(FftwFFT, self).__init__(backend=backend, allocator=allocator, 
                 warn_on_allocation=warn_on_allocation, **kwds)
         self.supported_ftypes = (np.float32, np.float64, np.longdouble)
diff --git a/hysop/numerics/fft/host_fft.py b/hysop/numerics/fft/host_fft.py
index c675ec325f26958e30242b7338c97770ee878fb2..c1259c92187cca4149c5b52263ae490c7ecc6362 100644
--- a/hysop/numerics/fft/host_fft.py
+++ b/hysop/numerics/fft/host_fft.py
@@ -67,17 +67,14 @@ class HostFFTI(FFTI):
         Get the default host FFT interface which is a multithreaded FFTW interface with 
         ESTIMATE planning effort.
         """
-        threads            = first_not_None(threads,           __FFTW_NUM_THREADS__)
-        planner_effort     = first_not_None(planner_effort,    __FFTW_PLANNER_EFFORT__)
-        planning_timelimit = first_not_None(planner_timelimit, __FFTW_PLANNER_TIMELIMIT__)
-        planner_effort = first_not_None(planner_effort, 'FFTW_ESTIMATE')
+        threads            = first_not_None(threads,            __FFTW_NUM_THREADS__)
+        planner_effort     = first_not_None(planner_effort,     __FFTW_PLANNER_EFFORT__)
+        planning_timelimit = first_not_None(planning_timelimit, __FFTW_PLANNER_TIMELIMIT__)
         from hysop.numerics.fft.fftw_fft import FftwFFT
         return FftwFFT(threads=threads,  
                        planner_effort=planner_effort, 
                        planning_timelimit=planning_timelimit,
                        backend=backend, allocator=allocator,
-                       planner_effort=planner_effort, 
-                       planning_timelimit=planning_timelimit,
                        destroy_input=destroy_input,
                        warn_on_allocation=warn_on_allocation,
                        warn_on_misalignment=warn_on_misalignment,
diff --git a/hysop/problem.py b/hysop/problem.py
index 44269d90ee9cba66e062df76ba7cc29eba098173..3bec8c892a04835136fdb5811755671c4bea5236 100644
--- a/hysop/problem.py
+++ b/hysop/problem.py
@@ -23,13 +23,18 @@ class Problem(ComputationalGraph):
         with Timer() as tm:
             msg = self.build_problem(args=args, allow_subbuffers=allow_subbuffers)
             if msg:
-                msg='Problem {} achieved, exiting !'.format(msg)
-                vprint_banner(msg)
+                msg=' Problem {} achieved, exiting ! '.format(msg)
+                vprint_banner(msg, at_border=2)
                 sys.exit(0)
         msg=' Problem building took {} ({}s) '
         msg=msg.format(datetime.timedelta(seconds=round(tm.interval)), 
                         tm.interval)
         vprint_banner(msg, spacing=True, at_border=2)
+
+        if (args is not None) and args.stop_at_build:
+            msg=' Problem has been built, exiting. '
+            vprint_banner(msg, at_border=2)
+            sys.exit(0)
            
     def build_problem(self, args, allow_subbuffers):
         if (args is not None) and args.stop_at_initialization: