29 import nwpservice.flexwrf.flexwrf
39 '''Class for managing preparation and execution of flexwrf components
45 flexwrf_distro_path=None,
49 outgrid_defn_dict=None,
50 flexwrf_specs_dict=None,
51 wrfout_hours_intvl=None,
52 wrfout_num_nests=None,
53 wrfout_data_dict_list=None,
55 num_openmp_threads=None,
57 bypass_flexp_input=None,
60 '''Check and initialise the class
65 flexwrf_distro_path : str
66 (Optional) Full path to the FlexWRF distribution to be used.
67 This is assumed to have been installed in a way that is compatible
68 with the nwpservice module. If arg is not present, uses a default
71 (Optional) Full path to a directory (assumed to have already
72 been created), to be used as scratch space for setting up and
73 running this flexwrf instance. If arg is not present, uses a
75 start_time_dt : datetime
76 Time of first wrfout file(s), start time of flexwrf sim
77 stop_time_dt : datetime
78 Time of last wrfout file(s), end time of flexwrf sim
79 outgrid_defn_dict : dict
80 Dict of outgrid definitions (of use if generating flexwrf namelist)
81 flexwrf_specs_dict : dict
82 For future use when the user input file will be generated by
83 this routine (for now, it's "bypassed" with a complete and correct
85 wrfout_hours_intvl : int
86 Number of expected hours between wrfout files. For now, it is
87 required, even when using bypass_flexp_input
88 wrfout_num_nests : int
89 Number of nests represented by wrfout files. For now, it is
90 required, even when using bypass_flexp_input
91 wrfout_data_dict_list : list
92 Necessary information on the wrfout files. We expect
93 list of dicts, one for each nest, with entries {'nest' : n,
94 'path' : <path>, 'filelist' : [list of wrfout files]}. At
95 this level, it's OK if the path is the same for different nests
96 (e.g. they might all be in the same wrf rundir)
98 (Optional) Number of MPI tasks to use for running this instance
99 of flexwrf. If arg is not present, non-MPI execution is assumed.
100 num_openmp_threads : int
101 (Optional) Number of OpenMP threads to use for running this
102 instance of flexwrf. If arg is not present, non-OpenMP execution
105 Python logging level (e.g. logging.INFO)
106 bypass_flexp_input : str
107 This is an assumed-correct flexwrf namelist to be used for
108 execution of flexwrf. Its presence bypasses the normal process
109 of creating a namelist, and puts complete trust in the
110 correctness of the provided namelist If this argument
111 is present, then any values for start_time_dt, stop_time_dt,
112 hours_intvl and num_nests are ignored. This is meant primarily
113 for devtest operations, and probably shouldn't be used for
119 #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
120 Change this for assumption of single dir
122 These are examples of the wrfout_data_dict_list
126 wrfout_data_dict_list = [
129 'path' : '/path/to/dir/with/wrfout_d01/files'
130 'filelist' : ['wrfout_d01_2014-01-24_00:00:00', ...]
134 'path' : '/path/to/dir/with/wrfout_d02/files'
135 'filelist' : ['wrfout_d02_2014-01-24_00:00:00', ...]
147 LOGGER.debug(
'started')
158 if bypass_flexp_input:
159 if not os.path.isfile(bypass_flexp_input):
160 raise FileNotFoundError(
'bypass_flexp_input not found: %s' %
163 LOGGER.debug(
'bypass_flexp_input: %s' %
169 if not flexwrf_distro_path:
170 flexwrf_distro_path = DEFAULTS.flexwrf_distro_path()
174 raise FileNotFoundError(
'flexwrf_distro_path not found: %s' %
179 if not working_rootdir:
180 working_rootdir = DEFAULTS.working_scratch_rootdir()
183 raise FileNotFoundError(
'working_rootdir not found: %s' %
188 if not wrfout_num_nests:
189 raise ValueError(
"Missing wrfout_num_nests arg")
190 if wrfout_num_nests <= 0:
191 raise ValueError(
"wrfout_num_nests: %d" % wrfout_num_nests)
197 if len(wrfout_data_dict_list) != wrfout_num_nests:
199 'wrfout_data_dict_list unexpected number of nests: %d' %
200 len(wrfout_data_dict_list))
204 for wrfout_nest_dict
in wrfout_data_dict_list:
206 wrfout_dir = wrfout_nest_dict[
'path']
207 wrfout_files = wrfout_nest_dict[
'filelist']
209 for fname
in wrfout_files:
210 fpath = os.path.join(wrfout_dir, fname)
211 if not os.path.isfile(fpath):
212 raise FileNotFoundError(
'fpath: %s' % fpath)
231 if 1 <= num_mpi_tasks <= DEFAULTS.max_mpi_tasks():
233 mpirunpath = DEFAULTS.mpirun_path()
234 if os.path.isfile(mpirunpath)
and \
235 os.access(mpirunpath, os.X_OK):
239 raise FileNotFoundError(
'mpirun not executable: %s' %
242 raise ValueError(
'Bad num_mpi_tasks value: %d' % num_mpi_tasks)
250 if num_openmp_threads:
252 if 1 <= num_openmp_threads <= DEFAULTS.max_openmp_threads():
255 raise ValueError(
'Bad num_openmp_threads value: %d' %
286 '''Set up and run, via nwpservice module, instance of flexwrf
290 flexwrf_output_stagedir : str
291 (Optional) Full path to dir where flexwrf output files will be staged.
292 If not specified, no staging will be done. If specified, we
293 assume the dir already exists.
298 Dictionary with manifest of the flexwrf output files and the location
299 (if applicable) of staged files
303 LOGGER.debug(
'Starting run_flexwrf()...')
319 flexp_input_path =
None
320 raise NotImplementedError(
321 'flexp_input creation not yet supported')
326 LOGGER.debug(
'domainpath: %s' % domainpath)
339 metfiles_path_list = []
348 filter(
lambda n: n.get(
'nest') == (i+1),
353 raise ValueError(
'Failed to find nest index: %d' % (i+1))
354 LOGGER.debug(
'nest_idx: %d' % nest_idx)
360 LOGGER.debug(
'nest_path: %s' % nest_path)
361 LOGGER.debug(
'nest_files: %s' % nest_files)
366 dirname =
'wrfout_d%02d' % (i+1)
368 os.mkdir(dest_path, 0o755)
369 for wrfout_file
in nest_files:
370 src_fpath = os.path.join(nest_path, wrfout_file)
371 dest_fpath = os.path.join(dest_path, wrfout_file)
372 os.symlink(src_fpath, dest_fpath)
374 metfiles_path_list.append(dest_path)
376 nwpflexwrf_obj = nwpservice.flexwrf.flexwrf.FlexWrf(
378 flexwrf_rundir=domainpath,
380 metfilespath_list=metfiles_path_list,
381 output_dir=flexwrf_output_stagedir,
387 nwpflexwrf_obj.setup()
388 output_manifest = nwpflexwrf_obj.run()
389 LOGGER.debug(
'output_manifest: %s' % output_manifest)
393 stage_success = nwpflexwrf_obj.stage_output(auxfiles=
True)
395 staging_dir = flexwrf_output_stagedir
400 'flexwrf_output_manifest' : output_manifest,
401 'staging_dir' : staging_dir,
404 LOGGER.debug(
'return_dict: %s' % return_dict)