HWRF  trunk@4391
hwrf_expt.py
1 
2 
3 ##@namespace hwrf_expt
4 # Generates the object structure of the HWRF system for use by the scripts.
5 #
6 # @anchor hwrf_expt_overview
7 #
8 # This module is the part of the \ref experiment_layer that creates an
9 # object structure from classes in the hwrf and pom packages. It
10 # defines what the HWRF experiment will run, and how the various parts
11 # of the HWRF system connect to one another. As this module has
12 # gotten more complex, some of its implementation has been moved to
13 # the hwrf.hwrfsystem module, which contains helper functions for
14 # defining parts of the workflow.
15 #
16 # @sa hwrf.launcher The launcher module creates the initial directory
17 # structure, and runs sanity checks on the hwrf_expt
18 #
19 # @sa scripts The scripts load this hwrf_expt module and call the
20 # run() (or similar) function for one or more objects within.
21 #
22 # @sa hwrf The hwrf package contains classes that know how to run each
23 # part of the HWRF system.
24 #
25 # @sa pom The pom package defines the initialization of the MPIPOMTC
26 # ocean model.
27 #
28 # @sa hwrf_alerts The hwrf_alerts module adds product alerts needed to
29 # ensure data is delivered to forecasters and the public in the
30 # NCEP production system.
31 
32 ##@var __all__
33 # Ensures that accidental "from hwrf_expt import *" does nothing.
34 __all__=[]
35 
36 import os,os.path
37 
38 import pdb
40 
46 import hwrf.coupling
48 
49 from produtil.run import exe,alias
50 from produtil.fileop import isnonempty
51 from hwrf.wrf import WRFDomain,WRFSimulation,ExternalWRFTask
52 from hwrf.post import PostManyWRF
53 from hwrf.regrib import RegribMany,igrb1,clatlon,GRIB2
54 
55 def prelaunch(conf,logger,cycle):
56  """!This function makes per-cycle modifications to the
57  configuration file storm1.conf.
58 
59  This is called in scripts.exhwrf_launch and run_hwrf.py by
60  hwrf.launcher.launch() on the configuration object
61  (hwrf.launcher.HWRFLauncher, a subclass of
62  hwrf.config.HWRFConfig), before the per-cycle storm1.conf
63  configuration file is written. Any changes made to the conf
64  object will be stored in storm1.conf file and used in later jobs.
65  This allows modifications to the configuration on a per-cycle
66  basis. Note that cycle=None and conf.cycle is unavailable when
67  run_hwrf.py calls prelaunch.
68  @param conf the hwrf.launcher.HWRFLauncher to modify
69  @param logger a logging.Logger for log messages
70  @param cycle the cycle to run, or None if this is being
71  run from run_hwrf.py or the ush.psychoanalyst"""
72 
73  # Prelaunch that happens even when running run_hwrf.py:
75 
76  if cycle is None: return
77 
78  # Prelaunch that only happens in exhwrf_launch, not run_hwrf.py:
79  hwrf.prelaunch.prelaunch_ungrib(conf,logger,cycle)
80  hwrf.prelaunch.prelaunch_rsmc(conf,logger,cycle)
81  hwrf.prelaunch.prelaunch_basin(conf,logger,cycle)
82 
83 def sanity_check(logger):
84  """!Runs a sanity check on this module's contents. This should be
85  called after init_module.
86 
87  This sanity check routine is called automatically by
88  hwrf.launcher.HWRFLauncher.sanity_check_expt() as part of the
89  standard sanity checks in the scripts.exhwrf_launch job. It
90  checks to see if all expected module-scope variables are present
91  and initialized correctly.
92 
93  @param logger a logging.Logger for log messages"""
94  logger.info('The runwrf object = %s'%(repr(runwrf),))
95  logger.info('The gribber object = %s'%(repr(gribber),))
96  logger.info('The datastore (ds) object = %s'%(repr(ds),))
97  logger.info('The wrf object = %s'%(repr(wrf),))
98 
99  # Make sure the mandatory configuration variables are specified:
100  gsi_flag=conf.getbool('config','run_gsi')
101  ocean_flag=conf.getbool('config','run_ocean')
102  ocean=conf.getstr('config','ocean_model')
103  wave_flag=conf.getbool('config','run_wave')
104  wave=conf.getstr('config','wave_model')
105  reloc_flag=conf.getbool('config','run_relocation')
106  spectral_flag=conf.getbool('config','use_spectral')
107  spectral_bdy=conf.getbool('config','spectral_bdy') and spectral_flag
108  fallbacks_flag=conf.getbool('config','allow_fallbacks')
109  extra_trackers=conf.getbool('config','extra_trackers',False)
110  wrf_output_step=conf.getint('forecast_products','wrf_output_step',10800)
111 
112  # Check if the ocean model is a valid one and its init object exists:
113  if ocean_flag:
114  if ocean=='HYCOM':
115  logger.info('The hycominit object = %s'%(repr(hycominit),))
116  logger.info('The hycompost object = %s'%(repr(hycompost),))
117  elif ocean=='POM':
118  logger.info('The pominit object = %s'%(repr(pominit),))
119  else:
121  '[config] ocean_model=%s but should be POM or HYCOM'%(
122  ocean))
123 
124  if wrf_output_step<1:
126  'The wrf_output_step must be at least 1 second')
127  elif wrf_output_step!=10800 and 0 != (3600%wrf_output_step):
129  'One hour (3600 seconds) must be divisable by the WRF '
130  'output timestep. You specified %d.'%(wrf_output_step,))
131 
132  # Check if the wave model is a valid one and its init object exists:
133  if wave_flag:
134  if wave=='WW3':
135  logger.info('The ww3init object = %s'%(repr(ww3init),))
136  logger.info('The ww3post object = %s'%(repr(ww3post),))
137  else:
139  '[config] wave_model=%s but should be WW3'%(
140  wave))
141 
142  # Make sure the configuration makes sense and is supported:
143  if gsi_flag and not reloc_flag:
144  logger.error("Cannot use GSI without relocation.")
146  "Cannot use GSI without relocation.")
147 
148 def inputiter():
149  """!Iterates over all inputs required by this configuration.
150 
151  Calls the inputiter() function on all tasks in the module scope
152  that are expected to have input data. The result can be passed
153  into the "data" argument of hwrf.input.InputSource.get. Iterates
154  over dicts that contain the following:
155  * dataset --- string name of the dataset (gfs, gdas1, gefs,
156  enkf, etc.)
157  * item --- string name of the object (ie.: gfs_sf, gfs_sfcanl, bufr)
158  * atime --- self.conf.cycle
159  * ftime --- only present when relevant: the forecast time, in a
160  format accepted by to_datetime_rel
161  * enkfmem --- only present when relevant: the ENKF member ID
162  * obstype --- only present when relevant: the bufr data type.
163  * optional --- True if the absence of this data is not considered a failure."""
164  gsi_flag=conf.getbool('config','run_gsi')
165  run_ensemble_da=conf.getbool('config','run_ensemble_da',False)
166  spectral_flag=conf.getbool('config','use_spectral')
167  spectral_bdy=conf.getbool('config','spectral_bdy') and spectral_flag
168  ocean_flag=conf.getbool('config','run_ocean')
169  ocean=conf.getstr('config','ocean_model','POM')
170  wave_flag=conf.getbool('config','run_wave')
171  wave=conf.getstr('config','wave_model','WW3')
172  conditional_gsid03=conf.getbool('config','conditional_gsid03',False)
173  tdrflagfile=conf.strinterp('dir','{com}/{stormlabel}.tdr')
174  realtime=conf.getbool('config','realtime')
175  if not conditional_gsid03 or (conditional_gsid03 and isnonempty(tdrflagfile)):
176  gsid03_flag=True
177  else:
178  gsid03_flag=False
179 
180  if ocean_flag:
181  if ocean=='HYCOM':
182  for d in hycominit.inputiter(): yield d
183  elif ocean=='POM':
184  for d in pominit.inputiter(): yield d
185  if wave_flag:
186  if wave=='WW3':
187  for d in ww3init.inputiter(): yield d
188  for d in gfs_init.inputiter(): yield d
189  if gsi_flag:
190  for d in gsi_d02.inputiter(): yield d
191  if gsid03_flag:
192  for d in gsi_d03.inputiter(): yield d
193  for d in fgat_init.inputiter(): yield d
194  if run_ensemble_da:
195  for d in ensda.inputiter(): yield d
196  if not realtime or not os.path.isdir('/dcom/us007003'):
197  for d in ensda_pre.inputiter(): yield d
198 
199 ##@var ww3init
200 # An hwrf.ww3.WW3Init that initializes wavewatch3, or None if wave
201 # coupling is disabled
202 ww3init=None
203 
204 ##@var hycominit
205 # An hwrf.hycom.HYCOMInit that initializes hycom, or None if hycom
206 # coupling is not in use.
207 hycominit=None
208 
209 ##@var ww3post
210 # An hwrf.ww3.WW3Post that post-processes wavewatch3 output, or None
211 # if wave coupling is disabled.
212 ww3post=None
213 
214 ##@var hycompost
215 # An hwrf.hycom.HYCOMPost that post-processes hycom output, or None if
216 # hycom coupling is not in use
217 hycompost=None
218 
219 ##@var conf
220 # An hwrf.launcher.HWRFLauncher for configuration information.
221 conf=None
222 
223 ##@var ds
224 # A produtil.datstore.Datastore for product and task information storage.
225 ds=None
226 
227 ##@var moad
228 # The hwrf.wrf.WRFDomain for the Mother Of All Domains (MOAD)
229 moad=None
230 
231 ##@var storm1outer
232 # The hwrf.wrf.WRFDomain for the intermediate resolution domain
233 storm1outer=None
234 
235 ##@var storm1inner
236 # The hwrf.wrf.WRFDomain for the innermost resolution domain
237 storm1inner=None
238 
239 ##@var wrf
240 # The hwrf.wrf.WRFSimulation describing the simulation to run
241 wrf=None
242 
243 ##@var runwrf
244 # The hwrf.fcsttask.WRFAtmos or hwrf.mpipomtc.WRFCoupledPOM that
245 # runs the full-length forecast.
246 runwrf=None
247 
248 ##@var nonsatpost
249 # The hwrf.post.PostManyWRF for generating non-satellite, native E grid GRIB1 files
250 # from the runwrf object.
251 nonsatpost=None
252 
253 ##@var satpost
254 # The hwrf.post.PostManyWRF for generating synthetic satellite, native
255 # E grid GRIB1 files from the runwrf object.
256 satpost=None
257 
258 ##@var gfs_init
259 # The hwrf.init.HWRFInit that runs initialization tasks such as WPS
260 # and real_nmm on the parent global model analysis.
261 gfs_init=None
262 
263 ##@var gribber
264 # The hwrf.gribtask.GRIBTask that takes satpost and nonsatpost output,
265 # regrids it and converts to GRIB2 format.
266 gribber=None
267 
268 ##@var tracker
269 # The hwrf.tracker.TrackerTask that runs the tracker on output from the gribber.
270 tracker=None
271 
272 ##@var pominit
273 # The initialization for the MPIPOMTC ocean model that is coupled to
274 # WRF in the runwrf object. This is an hwrf.mpipomtc.POMInit object.
275 pominit=None
276 
277 ##@var nhcp
278 # The hwrf.nhc_products.NHCProducts object that generates custom
279 # products for the National Hurricane Center.
280 nhcp=None
281 
282 ##@var wrfcopier
283 # An object that copies WRF inputs and outputs to the COM directory.
284 # This is an hwrf.copywrf.WRFCopyTask object.
285 wrfcopier=None
286 
287 ##@var WORKhwrf
288 # The scrub directory for this job
289 WORKhwrf=None
290 
291 ##@var HOMEhwrf
292 # The HWRF installation location
293 HOMEhwrf=None
294 
295 ##@var fgat_init
296 # The FGAT initialization, which interpolates parent global model
297 # forecasts to the HWRF grid and runs other initialization jobs to
298 # prepare inputs to the GSI. This is an hwrf.init.FGATInit object.
299 fgat_init=None
300 
301 ##@var non_ocean_basins
302 # A list of one-letter basin IDs that are not supported by the
303 # selected ocean model. This is used by the scripts.exhwrf_check_init
304 # to determine if the ocean initialization incorrectly decided not to
305 # run the ocean.
306 non_ocean_basins=None
307 
308 ##@var bufrprep
309 # An hwrf.bufrprep.Bufrprep object that turns data tanks into bufr
310 # files for input to GSI.
311 bufrprep=None
312 
313 ##@var gsi_d02
314 # The intermediate resolution GSI, an hwrf.gsi.FGATGSI, which knows
315 # how to run the GSI data assimilation system on output from the
316 # fgat_init, bufrprep and other objects.
317 gsi_d02=None
318 
319 ##@var gsi_d03
320 # The innermost domain resolution GSI, an hwrf.gsi.FGATGSI, which
321 # knows how to run the GSI data assimilation system on output from the
322 # fgat_init, bufrprep and other objects.
323 gsi_d03=None
324 
325 ##@var gsid03_flag
326 # A boolean value, True if gsi_d03 should be run and False otherwise
327 gsid03_flag=None
328 
329 ##@var gdas_merge
330 # An hwrf.relocate.Merge object that merges output from GSI and the
331 # fgat_init's hwrf.relocate.Stage3 to create the final input fields
332 # to the runwrf
333 gdas_merge=None
334 
335 ##@var cycle
336 # A synonym of conf.cycle: the cycle being run
337 cycle=None
338 
339 ##@var ensda
340 # An hwrf.ensda.DAEnsemble filled with hwrf.ensda.FromGFSENKF objects
341 # that run six hour forecasts based on the GFS ENKF
342 ensda=None
343 
344 ##@var prior_ensda
345 # An hwrf.ensda.DAEnsemble filled with hwrf.ensda.FromPriorCycle objects
346 # that provide access to the prior cycle's ENSDA six hour forecasts.
347 prior_ensda=None
348 
349 ##@var entest
350 # An hwrf.ensda.FromGFSENKF for testing
351 #@bug the hwrf_expt.entest is no longer needed and should be removed
352 entest=None
353 
354 ##@var da_ensemble_size
355 # Number of members in the ensda
356 da_ensemble_size=None
357 
358 ##@var trackerd01
359 # If enabled, an hwrf.tracker.TrackerTask that only uses the moad data
360 # to generate the track.
361 trackerd01=None
362 
363 ##@var trackerd02
364 # If enabled, an hwrf.tracker.TrackerTask that only uses the moad and
365 # intermediate resolution domains' data to generate the track.
366 trackerd02=None
367 
368 ##@var gsipost
369 # An hwrf.gsipost.GSIPost that post-processes inputs and outputs to the
370 # gsi_d02 and gsi_d03 to create native E grid GRIB files input to
371 # the gsigribber
372 gsipost=None
373 
374 ##@var gsigribber
375 # An hwrf.gribtask.GRIBTask that takes the gsipost output and turns it
376 # into lat-lon GRIB2 files suitable for analysis of the effect of GSI.
377 gsigribber=None
378 
379 ##@var ensda_pre
380 # Output from hwrf.ensda.ensda_pre_object_for(), the object that determines
381 # whether the data assimiltation ensemble should be run.
382 ensda_pre=None
383 
384 def init_module(CONFhwrf=None,make_ensemble_da=True,make_post=True):
385  """!Initializes the HWRF object structure.
386 
387  This function is called from all scripts and the
388  hwrf.launcher.HWRFLauncher to initialize the HWRF object
389  structure. The created objects know how to run various parts of
390  the system, and this function connects those objects to one
391  another.
392  @param CONFhwrf the configuration filename
393  @param make_ensemble_da if True, the ensemble data assimilation objects
394  are created
395  @param make_post if True, the post-processing objects are created"""
396  global conf,ds,moad,storm1outer,storm1inner,wrf, anl4trak
397  global runwrf,nonsatpost,satpost,hwrfsub,stormloc,domloc, gfs_init
398  global gribber, tracker, WRFOUThwrf, coupled, pominit
399  global nhcp, wrfcopier, real12, real126, WORKhwrf, HOMEhwrf
400  global rel_stage1, rel_stage2, rel_stage3, fgat_init, non_ocean_basins
401  global bufrprep, gsi_d02, gsi_d03, gsid03_flag, gdas_merge, cycle, prior_ensda
402  global ensda, entest, da_ensemble_size, trackerd01, trackerd02
403  global gsigribber, gsipost, ensda_pre, ocstatus, finalmerge, multistormin
404  global run_multistorm, run_multistorm_00flag
405  global fcstlen, hycominit, hycompost, ww3init, ww3post, wvstatus
406 
407  # Figure out where to find the config file if it was not supplied
408  # as an argument:
409  if CONFhwrf is None:
410  CONFhwrf=os.environ['CONFhwrf']
411 
412  # Generate the HWRFConfig object, which stores experiment
413  # configuration, processor counts and so on. It also knows how to
414  # automatically generate other critical objects like the Datastore:
415  conf=hwrf.launcher.load(CONFhwrf)
416  logger=conf.log()
417  logger.info('Initializing hwrf_expt module...')
418 
419  sync_frequently=conf.getbool('config','sync_frequently',True)
420  produtil.fileop.sync_frequently=sync_frequently
421  if sync_frequently:
423 
424  # MULTISTORM
425  # run_multistorm_00flag identifies the fakestorm of a multistorm.
426  run_multistorm=conf.getbool('config','run_multistorm',False)
427  run_multistorm_00flag = False
428  if run_multistorm:
429  fakestormid=conf.getstr('config','fakestormid','nofakeid')
430  this_stormid=conf.getstr('config','STID','nosid')
431  if fakestormid != 'nofakeid' and fakestormid == this_stormid:
432  run_multistorm_00flag = True
433  #list of all the real storms.
434  multistorm_sids = conf.getstr(
435  'config','multistorm_sids','nosids').split()
436  if multistorm_sids[0]=='nosids':
438  'No sids provided for multistorm run.')
439  num_realstorms = len(multistorm_sids)
440 
441  # Convenience variables:
442  cycle=conf.cycle
443  WORKhwrf=conf.getdir('WORKhwrf')
444  HOMEhwrf=conf.getdir('HOMEhwrf')
445 
446  # Major configuration variables:
447  gsi_flag=conf.getbool('config','run_gsi')
448  run_ensemble_da=conf.getbool('config','run_ensemble_da',False)
449  make_ensemble_da=make_ensemble_da and run_ensemble_da
450  satpost_flag=conf.getbool('config','run_satpost',True)
451  ocean_flag=conf.getbool('config','run_ocean')
452  ocean=conf.getstr('config','ocean_model','POM')
453  wave_flag=conf.getbool('config','run_wave')
454  wave=conf.getstr('config','wave_model','WW3')
455  reloc_flag=conf.getbool('config','run_relocation')
456  spectral_flag=conf.getbool('config','use_spectral')
457  spectral_bdy=conf.getbool('config','spectral_bdy') and spectral_flag
458  fallbacks_flag=conf.getbool('config','allow_fallbacks')
459  gofile_flag=conf.getbool('config','make_gofile',False)
460  extra_trackers=conf.getbool('config','extra_trackers',False)
461  conditional_gsid03=conf.getbool('config','conditional_gsid03',False)
462  conditional_gsid02=conf.getbool('config','conditional_gsid02',False)
463  fcstlen=conf.getint('config','forecast_length',126)
464  fgatstr=conf.getint('fgat','FGATSTR',-3)
465  fgatend=conf.getint('fgat','FGATEND',3)
466  fgatinv=conf.getint('fgat','FGATINV',3)
467  tdrflagfile=conf.strinterp('dir','{com}/{stormlabel}.tdr')
468  ocstatus = hwrf.coupling.CouplingStatus(conf,'ocstatus')
469  wvstatus = hwrf.coupling.CouplingStatus(conf,'wvstatus')
470 
471  ww3_output_step=conf.getint('forecast_products','ww3_output_step',21600)
472  ww3_restart_step=conf.getint('forecast_products','ww3_restart_step',21600)
473 
474  ens_reloc_flag=conf.getbool('config','run_ens_relocation',False)
475  if not conditional_gsid03 or (conditional_gsid03 and isnonempty(tdrflagfile)):
476  gsid03_flag=True
477  else:
478  gsid03_flag=False
479 
480  # ----------------------------------------------------------------------
481  # Define the HWRF workflow
482 
483  # Create and obtain the Datastore object, which stores the HWRF state
484  # information:
485  ds=conf.datastore
486 
487  # Create the objects in this module in a single transaction since that
488  # speeds things up by a factor of 100:
489  with ds.transaction():
490  # Known types of domains:
491  moad=WRFDomain(conf,'moad')
492  storm1outer=WRFDomain(conf,'storm1outer')
493  storm1inner=WRFDomain(conf,'storm1inner')
494  storm1ghost_parent=WRFDomain(conf,'storm1ghost_parent')
495  storm1ghost=WRFDomain(conf,'storm1ghost')
496  storm1ghost_parent_big=WRFDomain(conf,'storm1ghost_parent_big')
497  storm1ghost_big=WRFDomain(conf,'storm1ghost_big')
498  postdoms=[moad,storm1outer,storm1inner]
499 
500  wrf=WRFSimulation(conf,'wrf',moad,conf.cycle,
501  conf.cycle+hwrf.numerics.to_timedelta(fcstlen*3600))
502  wrf.add(storm1outer,moad)
503  wrf.add(storm1inner,storm1outer)
504 
505  # --------------------------------------------------------------------
506  # MULTISTORM
507  # Only add additional domains to WRF for the fake storm (i.e. 00L) of
508  # a multistorm run.
509  # NOTE: This implementation is using the fake storms' (i.e. 00L) conf
510  # HWRFConfig object for all storms in WRFDomain multistorm run.
511  if run_multistorm_00flag:
512  # Define the WRFDomains, and add the domains for storms 2 and beyond.
513  stormNinner = {}; stormNouter = {}
514  for i in range(2,num_realstorms + 1):
515  stormNinner['storm%sinner'%i]=WRFDomain(conf,'storm%sinner'%i)
516  stormNouter['storm%souter'%i]=WRFDomain(conf,'storm%souter'%i)
517  wrf.add(stormNouter['storm%souter'%i], moad)
518  wrf.add(stormNinner['storm%sinner'%i],stormNouter['storm%souter'%i])
519  stormNinner['storm1inner']=storm1inner
520  stormNouter['storm1outer']=storm1outer
521  # ---------------------------------------------------------------------
522 
523  wrf.analysis_in(None)
524 
525  wrf_output_step=conf.getint('forecast_products','wrf_output_step',10800)
526  pom_output_step=conf.getint('forecast_products','pom_output_step',86400)
527  if wrf_output_step<10800:
528  # Just output the history stream for smaller timesteps.
529  wrf.add_output('history',step=wrf_output_step)
530  else:
531  # For the special case of three-hourly output, we still
532  # need hourly for nine hours.
533  wrf.add_output('history',step=3600*3,end=9*3600)
534  wrf.add_output('auxhist2',step=3600,end=9*3600,
535  outname='wrfout_d<domain>_<date>')
536  wrf.add_output('auxhist3',step=3600*3,
537  outname='wrfout_d<domain>_<date>')
538  wrf.add_output('auxhist1',step=3600,outname='wrfdiag_d<domain>', \
539  frames_per_outfile=999,io_form=202)
540  # add hifre2 file to the storm1inner nest nestlevel=2
541  wrf.add_hifreq(2)
542  #wrftask=ExternalWRFTask(ds,conf,'wrf',wrf,location=WRFOUThwrf)
543 
544  # Set up the wrfdoms. This is the same as postdoms, but with
545  # information filled in about grid IDs, output times, etc.:
546  wrfdoms=[d for d in wrf]
547 
548  # --------------------------------------------------------------------
549  # MULTISTORM Final Merge processing
550  if run_multistorm_00flag:
551  finalmerge=hwrf.finalmergetask.FinalMergeTask(ds,conf,\
552  'finalmerge', taskname='finalmerge')
553 
554  # ------------------------------------------------------------------
555  # ATMOSPHERE PRE-PROCESSING
556 
557  wrfghost=WRFSimulation(conf,'wrf',moad,conf.cycle,
558  conf.cycle+hwrf.numerics.to_timedelta(6*3600))
559  wrfghost.add(storm1ghost_parent,moad)
560  wrfghost.add(storm1ghost,storm1ghost_parent)
561 
562  wrfghost_big=WRFSimulation(conf,'wrf',moad,conf.cycle,
563  conf.cycle+hwrf.numerics.to_timedelta(6*3600))
564  wrfghost_big.add(storm1ghost_parent_big,moad)
565  wrfghost_big.add(storm1ghost_big,storm1ghost_parent_big)
566 
567  if run_multistorm_00flag:
568  # NOTE: DO NOT SET the keyword argument outdir= , for fakestorm of multistorm.
569  gfs_init=hwrf.init.HWRFInit(
570  ds,conf,'gfsinit',wrf,6*3600,fcstlen*3600,ibdystep=6*3600,
571  realfcst=True, relocate=False, prep=spectral_flag, prepfcst=spectral_bdy, track=False)
572  else:
573  gfs_init=hwrf.init.HWRFInit(
574  ds,conf,'gfsinit',wrf,6*3600,fcstlen*3600,ibdystep=6*3600,
575  wrfghost=wrfghost_big,prep=spectral_flag,track=True,
576  realfcst=True,relocate=reloc_flag,prepfcst=spectral_bdy)
577 
578  next_cycle=conf.cycle+hwrf.numerics.to_timedelta(6*3600)
580  ds,conf,'tdrcheck',next_cycle)
581  if gsi_flag:
582  if make_ensemble_da:
583  ##################################################
584  # ENSEMBLE DA
585 
586  # NOTE: If you change this section, you must also
587  # change the run_hwrf.py and hwrf_workflow.xml.in to
588  # match.
589  ensdadom=WRFDomain(conf,'ensdadom')
590  ensdawrf=WRFSimulation(
591  conf,'enswrf',moad,conf.cycle,next_cycle)
592  ensdawrf.add(ensdadom,moad)
593  ensdawrf.add_output('history',step=3600*3,end=9*3600)
594  ensdadoms=[ ensdawrf[moad], ensdawrf[ensdadom] ]
595  for dom in ensdadoms:
596  assert(dom.get_grid_id() is not None)
597 
598  def makememb(clazz,ienkf,topname='ensda',priorcycle=None):
599  assert(isinstance(topname,basestring))
600  assert(isinstance(ienkf,int))
601  return clazz(
602  ds,conf,"hwrf_da_ens",gfs_init,ienkf,ensdawrf,
603  "%s.%03d"%(topname,ienkf),relocate=ens_reloc_flag,
604  priorcycle=priorcycle,track=ens_reloc_flag,
605  workdir=conf.getdir('WORKhwrf')+'/%s/%03d'%(
606  topname,ienkf),
607  outdir=conf.getdir('intercom')+'/%s/%03d'%(
608  topname,ienkf))
609 
610  entest=makememb(hwrf.ensda.FromGFSENKF,30,'entest')
611 
612  prior_ensda=hwrf.ensda.DAEnsemble(
613  ds,conf,'hwrf_da_ens',conf.cycle,'prior_ensda')
614  da_ensemble_size=prior_ensda.confint('ensda_size',40)
615  for i in xrange(da_ensemble_size):
616  prior_ensda.set_member(
617  conf.cycle,i+1,hwrf.ensda.FromPriorCycle(
618  ds,conf,"hwrf_da_ens",ensdadoms,
619  i+1,conf.cycle,taskname='%s.%03d'%(
620  'prior_ensda',i+1)))
621 
622  ensda=hwrf.ensda.DAEnsemble(
623  ds,conf,'hwrf_da_ens',conf.cycle,'ensda')
624  for i in xrange(da_ensemble_size):
625  if ens_reloc_flag:
626  priorcycle=prior_ensda.member(conf.cycle,i+1)
627  else:
628  priorcycle=None
629  ensda.set_member(conf.cycle,i+1,makememb(
630  hwrf.ensda.FromGFSENKF,i+1,'ensda',priorcycle))
631 
632  ##################################################
633 
634 
635  if gsid03_flag:
636  gsid03=True
637  else:
638  gsid03=None
639  fgat_init=hwrf.init.FGATInit(
640  ds,conf,'fgat',wrf,3*3600,fcstlen*3600,wrfghost=wrfghost,
641  prep=spectral_flag,track=True,realfcst=False,ibdystep=3*3600,
642  in_dataset='gdas1',relocate=reloc_flag,gsi_d02=True,
643  gsi_d03=gsid03,prepfcst=spectral_bdy)
644  ceninit=fgat_init.init_at_time(conf.cycle)
645 
646  bufrprep=hwrf.bufrprep.Bufrprep(
647  ds,conf,'bufrprep',taskname='bufrprep')
648 
649  ingsi_d02=fgat_init.get_relocates(storm1ghost_parent)
650  gsi_d02=hwrf.gsi.FGATGSI(
651  ds,conf,'gsi_d02',storm1ghost_parent,
652  ceninit.rstage3.get_ghost(storm1ghost_parent),
653  ingsi_d02,wrfghost)
654 
655  if gsid03_flag:
656  ingsi_d03=fgat_init.get_relocates(storm1ghost)
657  gsi_d03=hwrf.gsi.FGATGSI(
658  ds,conf,'gsi_d03',storm1ghost,
659  ceninit.rstage3.get_ghost(storm1ghost),
660  ingsi_d03,wrfghost)
661  else:
662  gsi_d03=None
663 
664 
665  if make_ensemble_da:
666  if ens_reloc_flag:
667  gsi_d02.set_ensda(ensda,ensdadoms)
668  else:
669  gsi_d02.set_ensda(prior_ensda,ensdadoms)
670  if gsid03_flag:
671  if ens_reloc_flag:
672  gsi_d03.set_ensda(ensda,ensdadoms)
673  else:
674  gsi_d03.set_ensda(prior_ensda,ensdadoms)
675 
676  gdas_merge=hwrf.relocate.Merge(
677  ds,conf,'merge',ceninit.rstage3,
678  wrfinput=gfs_init.realinit,
679  wrfanl=gfs_init.runwrfanl,
680  taskname='gdas_merge',
681  gsi_d02=gsi_d02, gsi_d03=gsi_d03)
682 
683 
684  ges_d02=ceninit.rstage3.get_ghost(storm1ghost_parent)
685  if gsid03_flag:
686  ges_d03=ceninit.rstage3.get_ghost(storm1ghost)
687  else:
688  ges_d03=ceninit.rstage3.get_wrfanl(storm1inner)
689  gdas_merge.set_ges(ges_d02,ges_d03)
690 
691  # Create the GSI post. It will post-process the ghost
692  # files from the init.wrfghost, relocation and GSI for
693  # each of d02 and d03:
695  ds,conf,'gsi_products')
696  (gsipost,gsigribber)=hgpp.make_gsi_post(
697  gsi_d02,gsi_d03,storm1ghost,storm1ghost_parent,ceninit,
698  gsid03_flag)
699 
700  # ------------------------------------------------------------------
701  # OCEAN PRE-PROCESSING
702 
703  # Basins where we cannot run the chosen ocean model:
704  non_ocean_basins=conf.getstr('config','non_ocean_basins','Q')
705 
706  # Ocean init job:
707  if ocean_flag:
708  if ocean=='HYCOM':
709  hycominit=hwrf.hycom.HYCOMInit(ds,conf,'hycominit',fcstlen=fcstlen)
710  elif ocean=='POM':
711  pominit=hwrf.mpipomtc.POMInit(ds,conf,'pom',fcstlen=fcstlen,
712  outstep=pom_output_step)
713 
714  # ------------------------------------------------------------------
715  # WAVE PRE-PROCESSING
716 
717  # Basins where we cannot run the chosen wave model:
718  #non_wave_basins='ECABPSQ'
719  non_wave_basins='Q'
720 
721  # Wave init job:
722  if wave_flag and wave=='WW3':
723  ww3init=hwrf.ww3.WW3Init(ds,conf,'ww3init',fcstlen=fcstlen,
724  outstep=ww3_output_step, rststep=ww3_restart_step)
725  for p in ww3init.products():
726  print 'WW3INIT product = ',str(p)
727 
728  # ------------------------------------------------------------------
729  # FORECAST
730  # NOTE: most of the logic is moved to hwrf.hwrfsystem
731 
732  fcst_sec=conf.getstr('config','forecast_section','runwrf')
733  if not run_multistorm:
735  conf,ds,wrf,pominit,ww3init,hycominit,ocstatus)
736  hfcst.make_forecast()
737  runwrf=hfcst.runwrf
738  hycompost=hfcst.hycompost
739  ww3post=hfcst.ww3post
740 
741  if run_multistorm_00flag:
743  conf,ds,wrf,multistorm_sids,finalmerge,
744  stormNouter,stormNinner)
745  hfcst.make_forecast()
746  runwrf=hfcst.runwrf
747  elif run_multistorm:
748  # In the multi-storm configuration, real storms' runwrf
749  # objects make the forecast initial state, and watch the
750  # fake storm run the forecast. We don't put this in
751  # hwrf.hwrfsystem because the code required would be
752  # longer than making runwrf here:
754  ds,conf,fakestormid,fcst_sec,wrf,'runwrf')
755  multistormin=hwrf.multistorm.RealInit(
756  ds,conf,fcst_sec,wrf,keeprun=False,taskname='multistorm_init')
757  realwrf=multistormin
758  realwrf.add_orig_wrfinput(gfs_init.realinit)
759  else:
760  # Single storm runwrf:
761  realwrf=runwrf
762 
763  if not run_multistorm_00flag:
764  realwrf.add_metgrid(gfs_init.metgrid) \
765  .add_geogrid(gfs_init.geogrid) \
766  .add_fort65(gfs_init.realinit) \
767  .add_wrfbdy(gfs_init.realfcst)
768 
769  # Add the merge output for the initial conditions and realfcst
770  # for the boundary:
771  if gsi_flag and not run_multistorm_00flag:
772  realwrf.add_wrfinput(gdas_merge) \
773  .add_wrfanl(gdas_merge,storm1outer) \
774  .add_wrfanl(gdas_merge,storm1inner)
775 
776  if (not gsi_flag or fallbacks_flag
777  or (conditional_gsid03 and
778  conditional_gsid02 and gsi_flag)
779  ) and not run_multistorm_00flag:
780  if reloc_flag or (conditional_gsid03 and \
781  conditional_gsid02):
782  realwrf.add_wrfinput(gfs_init.rstage3) \
783  .add_wrfanl(gfs_init.rstage3,storm1outer) \
784  .add_wrfanl(gfs_init.rstage3,storm1inner)
785  else:
786  # Do not fall back to "no relocation" even if
787  # fallbacks are enabled. This is because the
788  # forecasting skill is useless without vortex
789  # relocation.
790  realwrf.add_wrfinput(gfs_init.realinit) \
791  .add_wrfanl(gfs_init.runwrfanl,storm1outer) \
792  .add_wrfanl(gfs_init.runwrfanl,storm1inner)
793 
794  ################################################################
795 
796  # RETURN HERE IF WE ARE NOT MAKING THE POST
797 
798  if not make_post:
799  logger.info('make_post=False, will not make post. '
800  'Done in hwrf_expt module.')
801  return
802 
803  ################################################################
804 
805 
806  # ------------------------------------------------------------------
807  # POST-PROCESSING
808 
810  ds,conf,'forecast_products',runwrf,wrf,postdoms,
811  wrfdoms,moad,storm1inner,storm1outer)
812  nonsatpost=hfpp.make_nonsatpost()
813  satpost=hfpp.make_satpost()
814  wrfcopier=hfpp.make_wrfcopier(multistorm=run_multistorm)
815  assert(wrfcopier is not None)
816  (gribber,tracker,track,nhcp)=\
817  hfpp.make_gribber_tracker(extra_trackers,satpost_flag,gofile_flag)
818  if extra_trackers:
819  (trackerd01,trackerd02)=\
820  hfpp.make_extra_trackers()
821 
822  logger.info('Done in hwrf_expt module.')
823 
Runs the POM initialization and POM-WRF coupled forecast.
Definition: mpipomtc.py:1
This module provides a set of utility functions to do filesystem operations.
Definition: fileop.py:1
Create namelists, monitor wrf simulations, generate filenames.
Definition: wrf.py:1
def prelaunch_basin(conf, logger, cycle)
Modifies the configuration for the basin.
Definition: prelaunch.py:78
def load(filename)
Loads the HWRFLauncher created by the launch() function.
Definition: launcher.py:297
def to_timedelta
Converts an object to a datetime.timedelta.
Definition: numerics.py:371
Represents a two-dimensional ensemble-vs-time array of hwrf.hwrftask.HWRFTask objects.
Definition: ensda.py:33
def prelaunch_ensid(conf, logger)
Changes the ungrib item and item2 based on the ensemble ID.
Definition: prelaunch.py:15
Functions called automatically before a cycle is launched.
Definition: prelaunch.py:1
def init_module
Initializes the HWRF object structure.
Definition: hwrf_expt.py:384
Runs the GSI based on the HWRF FGAT scheme.
Definition: gsi.py:1103
def sanity_check(logger)
Runs a sanity check on this module's contents.
Definition: hwrf_expt.py:83
Defines StormInfo and related functions for interacting with vitals ATCF data.
Definition: storminfo.py:1
A shell-like syntax for running serial, MPI and OpenMP programs.
Definition: run.py:1
Combines multiple tasks together to make the HWRF post-processing system.
Definition: hwrfsystem.py:1
Raised when the user requests a configuration that makes sense, but is not supported.
Definition: exceptions.py:91
PrepHybrid runs the prep_hybrid program to transform GFS spectral files to the HWRF grid...
Definition: prep.py:1
def inputiter()
Iterates over all inputs required by this configuration.
Definition: hwrf_expt.py:148
Contains the WRFCopyTask, which delivers WRF output and input.
Definition: copywrf.py:1
Utilities for ensemble-based data assimilation.
Definition: ensda.py:1
Runs the real_nmm or wrf executables.
Definition: fcsttask.py:1
Stores products and tasks in an sqlite3 database file.
Definition: datastore.py:1
Definition: ww3.py:1
Runs the GSI data assimilation on the HWRF system.
Definition: gsi.py:1
Called when one hour is not divisable by the WRF output timestep.
Definition: exceptions.py:181
Time manipulation and other numerical routines.
Definition: numerics.py:1
Declares GRIBTask, which automates regribbing operations.
Definition: gribtask.py:1
This module contains Tasks to run the WRF Preprocessing System (WPS): Geogrid, Ungrib and Metgrid...
Definition: wps.py:1
Forecast ensemble member based on the GFS ENKF.
Definition: ensda.py:286
Raised when a time was requested with higher precision than available.
Definition: exceptions.py:194
parses UNIX conf files and makes the result readily available
Definition: config.py:1
Represents an ensemble member from the previous forecast cycle.
Definition: ensda.py:180
Combines Tasks from multiple modules into a single initialization object.
Definition: init.py:1
A wrapper around the pom package that runs the POM initialization.
Definition: mpipomtc.py:56
Runs the deterministic model initialization.
Definition: init.py:26
Creates the initial HWRF directory structure, loads information into each job.
Definition: launcher.py:1
Generates NHC-specific products and validates wrfdiag files.
Definition: nhc_products.py:1
def enada_pre_object_for(ds, conf, section, next_cycle)
Generates a CycleTDRCheck or AlwaysRunENSDA based on configuration settings.
Definition: ensda.py:896
def prelaunch_ungrib(conf, logger, cycle)
Change the ungrib table based on the year.
Definition: prelaunch.py:33
Creates the post-processing for the HWRF forecast job.
Definition: hwrfsystem.py:258
def prelaunch(conf, logger, cycle)
This function makes per-cycle modifications to the configuration file storm1.conf.
Definition: hwrf_expt.py:55
Runs the Unified Post Processor on outputs from the WRF-NMM, producing E grid GRIB files as EGRIB1Pro...
Definition: post.py:1
This module contains tasks to prepare input for the GFDL Vortex Tracker, run the tracker and deliver ...
Definition: tracker.py:1
The FGATInit represents an array of InitBeforeGSI objects, each run for one forecast hour of some par...
Definition: init.py:779
generate and manipulate wrf namelists, predict output filenames
Definition: wrf.py:663
Describes regribbing operations using an algebraic structure.
Definition: regrib.py:1
This is a HWRF task that merges the WRF analysis files.
Definition: relocate.py:2247
def prelaunch_rsmc(conf, logger, cycle)
Modifies the configuration for the RSMC (JTWC, NHC, etc.)
Definition: prelaunch.py:55
Post-processes GSI input and output for data assimilation diagnostics.
Definition: gsipost.py:1
This module implements Python classes that run the 2014 HWRF Relocation.
Definition: relocate.py:1
def runsync
Runs the "sync" command as an exe().
Definition: run.py:372
Raised when the requested configuration conf or hwrf_expt files fail a sanity check.
Definition: exceptions.py:88
Contains Bufrprep, which converts data tanks to bufr files, and otherwise preprocesses the prepbufr a...
Definition: bufrprep.py:1
Configures the GSI post-processing and regribbing.
Definition: hwrfsystem.py:121
A domain in a WRF simulation.
Definition: wrf.py:117
This is a HWRF task that preprocesses observations in data tanks to create bufr files suitable for in...
Definition: bufrprep.py:21