From 96ec4dc2567b51d3bd457bec553893bf755fb10b Mon Sep 17 00:00:00 2001 From: Chichi Lalescu <chichilalescu@gmail.com> Date: Thu, 4 May 2017 22:46:25 +0200 Subject: [PATCH] add DNS option to executable script --- bfps/DNS.py | 185 +++++++++++++++++++++++++++++++++++----------- bfps/__main__.py | 12 ++- tests/test_DNS.py | 13 ++-- 3 files changed, 159 insertions(+), 51 deletions(-) diff --git a/bfps/DNS.py b/bfps/DNS.py index b90c6d46..0d8571b0 100644 --- a/bfps/DNS.py +++ b/bfps/DNS.py @@ -45,12 +45,22 @@ class DNS(_code): def __init__( self, work_dir = './', - simname = 'test', - dns_type = 'NSVE', - fluid_dtype = 'single'): - _code.__init__(self, work_dir = work_dir, simname = simname) - self.dns_type = dns_type - self.name = self.dns_type + '-v' + bfps.__version__ + simname = 'test'): + _code.__init__( + self, + work_dir = work_dir, + simname = simname) + self.host_info = {'type' : 'cluster', + 'environment' : None, + 'deltanprocs' : 1, + 'queue' : '', + 'mail_address': '', + 'mail_events' : None} + self.generate_default_parameters() + return None + def set_precision( + self, + fluid_dtype): if fluid_dtype in [np.float32, np.float64]: self.fluid_dtype = fluid_dtype elif fluid_dtype in ['single', 'double']: @@ -62,9 +72,13 @@ class DNS(_code): if self.rtype == np.float32: self.ctype = np.dtype(np.complex64) self.C_field_dtype = 'float' + self.fluid_precision = 'single' elif self.rtype == np.float64: self.ctype = np.dtype(np.complex128) self.C_field_dtype = 'double' + self.fluid_precision = 'double' + return None + def write_src(self): self.version_message = ( '/***********************************************************************\n' + '* this code automatically generated by bfps\n' + @@ -94,13 +108,22 @@ class DNS(_code): return main_code< {0} >(argc, argv, fpe); }} """.format(self.dns_type + '<{0}>'.format(self.C_field_dtype)) - self.host_info = {'type' : 'cluster', - 'environment' : None, - 'deltanprocs' : 1, - 'queue' : '', - 'mail_address': '', - 'mail_events' : None} - self.generate_default_parameters() + self.includes = '\n'.join( + ['#include ' + hh + for hh in self.include_list]) + with open(self.name + '.cpp', 'w') as outfile: + outfile.write(self.version_message + '\n\n') + outfile.write(self.includes + '\n\n') + outfile.write(self.cread_pars( + template_class = '{0}<rnumber>::'.format(self.dns_type), + template_prefix = 'template <typename rnumber> ', + simname_variable = 'simname.c_str()') + '\n\n') + for rnumber in ['float', 'double']: + outfile.write(self.cread_pars( + template_class = '{0}<{1}>::'.format(self.dns_type, rnumber), + template_prefix = 'template '.format(rnumber), + just_declaration = True) + '\n\n') + outfile.write(self.main + '\n') return None def generate_default_parameters(self): # these parameters are relevant for all DNS classes @@ -123,30 +146,12 @@ class DNS(_code): self.parameters['max_velocity_estimate'] = float(1) self.parameters['max_vorticity_estimate'] = float(1) # parameters specific to particle version - if self.dns_type == 'NSVEp': - self.parameters['niter_part'] = int(1) - self.parameters['nparticles'] = int(10) - self.parameters['tracers0_integration_steps'] = int(4) - self.parameters['tracers0_neighbours'] = int(1) - self.parameters['tracers0_smoothness'] = int(1) - return None - def write_src(self): - self.includes = '\n'.join( - ['#include ' + hh - for hh in self.include_list]) - with open(self.name + '.cpp', 'w') as outfile: - outfile.write(self.version_message + '\n\n') - outfile.write(self.includes + '\n\n') - outfile.write(self.cread_pars( - template_class = '{0}<rnumber>::'.format(self.dns_type), - template_prefix = 'template <typename rnumber> ', - simname_variable = 'simname.c_str()') + '\n\n') - for rnumber in ['float', 'double']: - outfile.write(self.cread_pars( - template_class = '{0}<{1}>::'.format(self.dns_type, rnumber), - template_prefix = 'template '.format(rnumber), - just_declaration = True) + '\n\n') - outfile.write(self.main + '\n') + self.NSVEp_extra_parameters = {} + self.NSVEp_extra_parameters['niter_part'] = int(1) + self.NSVEp_extra_parameters['nparticles'] = int(10) + self.NSVEp_extra_parameters['tracers0_integration_steps'] = int(4) + self.NSVEp_extra_parameters['tracers0_neighbours'] = int(1) + self.NSVEp_extra_parameters['tracers0_smoothness'] = int(1) return None def get_kspace(self): kspace = {} @@ -376,7 +381,6 @@ class DNS(_code): for k in vec_stat_datasets: time_chunk = 2**20//(8*3*3*nshells) time_chunk = max(time_chunk, 1) - print(ofile) ofile.create_dataset('statistics/spectra/' + k + '_' + k, (1, nshells, 3, 3), chunks = (time_chunk, nshells, 3, 3), @@ -434,10 +438,71 @@ class DNS(_code): (3,)), dtype = np.float) return None - def specific_parser_arguments( + def job_parser_arguments( self, parser): - _code.specific_parser_arguments(self, parser) + parser.add_argument( + '--ncpu', + type = int, + dest = 'ncpu', + default = -1) + parser.add_argument( + '--np', '--nprocesses', + metavar = 'NPROCESSES', + help = 'number of mpi processes to use', + type = int, + dest = 'nb_processes', + default = 4) + parser.add_argument( + '--ntpp', '--nthreads-per-process', + type = int, + dest = 'nb_threads_per_process', + metavar = 'NTHREADS_PER_PROCESS', + help = 'number of threads to use per MPI process', + default = 1) + parser.add_argument( + '--no-submit', + action = 'store_true', + dest = 'no_submit') + parser.add_argument( + '--environment', + type = str, + dest = 'environment', + default = None) + parser.add_argument( + '--minutes', + type = int, + dest = 'minutes', + default = 5, + help = 'If environment supports it, this is the requested wall-clock-limit.') + parser.add_argument( + '--njobs', + type = int, dest = 'njobs', + default = 1) + return None + def simulation_parser_arguments( + self, + parser): + parser.add_argument( + '--simname', + type = str, dest = 'simname', + default = 'test') + parser.add_argument( + '-n', '--cube-size', + type = int, + dest = 'n', + default = 32, + metavar = 'N', + help = 'code is run by default in a grid of NxNxN') + parser.add_argument( + '--wd', + type = str, dest = 'work_dir', + default = './') + parser.add_argument( + '--precision', + choices = ['single', 'double'], + type = str, + default = 'single') parser.add_argument( '--src-wd', type = str, @@ -453,10 +518,6 @@ class DNS(_code): type = int, dest = 'src_iteration', default = 0) - parser.add_argument( - '--njobs', - type = int, dest = 'njobs', - default = 1) parser.add_argument( '--kMeta', type = float, @@ -468,6 +529,10 @@ class DNS(_code): dest = 'dtfactor', default = 0.5, help = 'dt is computed as DTFACTOR / N') + return None + def particle_parser_arguments( + self, + parser): parser.add_argument( '--particle-rand-seed', type = int, @@ -503,6 +568,31 @@ class DNS(_code): dest = 'smoothness', default = 1) return None + def add_parser_arguments( + self, + parser): + subparsers = parser.add_subparsers( + dest = 'DNS_class', + help = 'type of simulation to run') + subparsers.required = True + parser_NSVE = subparsers.add_parser( + 'NSVE', + help = 'plain Navier-Stokes vorticity formulation') + self.simulation_parser_arguments(parser_NSVE) + self.job_parser_arguments(parser_NSVE) + self.parameters_to_parser_arguments(parser_NSVE) + + parser_NSVEp = subparsers.add_parser( + 'NSVEp', + help = 'plain Navier-Stokes vorticity formulation, with basic fluid tracers') + self.simulation_parser_arguments(parser_NSVEp) + self.job_parser_arguments(parser_NSVEp) + self.particle_parser_arguments(parser_NSVEp) + self.parameters_to_parser_arguments(parser_NSVEp) + self.parameters_to_parser_arguments( + parser_NSVEp, + self.NSVEp_extra_parameters) + return None def prepare_launch( self, args = []): @@ -532,6 +622,13 @@ class DNS(_code): """ opt = _code.prepare_launch(self, args = args) + self.set_precision(opt.precision) + self.dns_type = opt.DNS_class + self.name = self.dns_type + '-' + self.fluid_precision + '-v' + bfps.__version__ + # merge parameters if needed + if self.dns_type == 'NSVEp': + for k in self.NSVEp_extra_parameters.keys(): + self.parameters[k] = self.NSVEp_extra_parameters[k] self.parameters['nu'] = (opt.kMeta * 2 / opt.n)**(4./3) self.parameters['dt'] = (opt.dtfactor / opt.n) # custom famplitude for 288 and 576 diff --git a/bfps/__main__.py b/bfps/__main__.py index 9db5e350..f1ee7278 100644 --- a/bfps/__main__.py +++ b/bfps/__main__.py @@ -28,6 +28,7 @@ import sys import argparse import bfps +from .DNS import DNS from .NavierStokes import NavierStokes from .NSVorticityEquation import NSVorticityEquation from .FluidResize import FluidResize @@ -64,13 +65,22 @@ def main(): 'NSManyParticles-double'] parser.add_argument( 'base_class', - choices = NSoptions + NSVEoptions + FRoptions + FCoptions + NSMPopt, + choices = ['DNS'] + + NSoptions + + NSVEoptions + + FRoptions + + FCoptions + + NSMPopt, type = str) # first option is the choice of base class or -h or -v # all other options are passed on to the base_class instance opt = parser.parse_args(sys.argv[1:2]) # error is thrown if first option is not a base class, so launch # cannot be executed by mistake. + if opt.base_class == 'DNS': + c = DNS() + c.launch(args = sys.argv[2:]) + return None if 'double' in opt.base_class: precision = 'double' else: diff --git a/tests/test_DNS.py b/tests/test_DNS.py index 4e8cb2f8..9169cef9 100644 --- a/tests/test_DNS.py +++ b/tests/test_DNS.py @@ -2,12 +2,13 @@ from bfps.DNS import DNS def main(): - niterations = 16 - nparticles = 100 - c = DNS(dns_type = 'NSVEp') + niterations = 32 + nparticles = 10000 + c = DNS() c.launch( - ['-n', '32', - '--simname', 'vorticity_equation', + ['NSVEp', + '-n', '32', + '--simname', 'dns_nsvep', '--np', '4', '--ntpp', '1', '--niter_todo', '{0}'.format(niterations), @@ -16,7 +17,7 @@ def main(): '--checkpoints_per_file', '{0}'.format(3), '--nparticles', '{0}'.format(nparticles), '--particle-rand-seed', '2', - #'--njobs', '2', + '--njobs', '2', '--wd', './']) return None -- GitLab