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: