HWRF  trunk@4391
multistorm.py
1 import fractions,math,re,datetime,os
2 import produtil.fileop
3 import hwrf.wrf
4 
5 from produtil.datastore import COMPLETED,RUNNING,UNSTARTED,FAILED,\
6  Product, FileProduct, UpstreamFile
7 from produtil.fileop import isnonempty
8 from produtil.workpool import WorkPool
9 
11 from hwrf.hwrftask import HWRFTask
12 from hwrf.numerics import *
13 from hwrf.namelist import *
14 from hwrf.exceptions import *
15 from hwrf.wrfbase import *
16 
17 __all__=['ForecastWatcher','FakeInit','RealInit']
18 
20  """Links real_nmm wrfinput_d01 file or returns the FileProduct,
21  regardless of the time and domain, in the current directory for
22  a final merge."""
23  def __init__(self,stormid,src,domain,atime):
24  super(Input2FinalMerge,self).__init__(stormid,src)
25  self.domain=domain
26  self.atime=atime
27  def get_inputs(self,logger,just_check=False, stormid=None, **kwargs):
28  if stormid is not None and stormid!=self.stormid:
29  if logger is not None:
30  logger.error(
31  'Wrong stormid requested: %s instead of %s, cannot link.'
32  %(stormid,self.stormid))
33  return False
34  if self.src is not None:
35  tgt=self.tgtname
36  p=self.src.wrfinput_at_time(self.atime,self.domain)
37  if p:
38  if not p.available: p.check()
39  return self.link_product(p,WRFInputMissing,logger,
40  target=tgt,
41  just_check=just_check)
42  return False
43 
44 # Used by the realstorms of a multistorm run to setup the paths to the fakestorm
45 # directories for the forecast products.
46 # So this classes as_product method overrides the ExternalWRFTask:as_product method
47 # and sets up the paths for the realstorm products.
48 #runwrf.mon::wrfdiag_d03|0|/pan2/projects/dtc-hurr/James.T.Frimel/pytmp/aa.hwrf_multistorm.int/2012071000/00L/runwrf/wrfdiag_d05|UpstreamFile
49 
51  def __init__(self,ds,conf,fakeid,section,wrf,taskname,**kwargs):
52  workdir=conf.strinterp('dir','{realstormwork}/{taskname}',
53  realstorm=fakeid,taskname=taskname)
54 
55  self._d02map = None
56  self._d03map = None
57  with ds.transaction() as tx:
58  super(ForecastWatcher,self).__init__(
59  ds,conf,section,wrf,
60  taskname=taskname,workdir=workdir,outdir=workdir)
61  self.location=workdir
62  self.workdir=workdir
63  self.outdir=workdir
64 
65  @property
66  def d02remap(self):
67  """The outer domain value for a multistorm.."""
68  return self._d02map
69 
70  @property
71  def d03remap(self):
72  """The inner domain value for a multitorm ."""
73  return self._d03map
74 
75  def change_location(self):
76  # Multistorm - jtf
77  # Changes the one line **task**::runhwrf.mon |ExternalWRFTask in the dstore.
78  # So when check runs in the post ... The correct location is used
79  # for the WRF Simulation status rsl.out.0000, since it is running under
80  # the fakestorm.
81  if self.ismultistorm and not self.isfakestorm:
82  if 'location' in self:
83  fakestormid=self.conf.getstr('config','fakestormid')
84  this_stid=self.conf.getstr('config','STID')
85  self['location']=self['location'].replace(this_stid,fakestormid)
86  #kwargs['location']= kwargs['location'].replace(this_stid,fakestormid)
87 
88  def check_all_inputs(self):
89  """!Placeholder to allow a ForecastWatcher to look like an
90  hwrf.fcsttask.WRFAtmos to the scripts.exhwrf_check_init job.
91  This allows the fake storms to run the init checking job."""
92  return True
93 
94 
95  def as_product(self,wrfout,relocate=False):
96  """Converts a WRFOutput to a Product."""
97  cached=self._get_cache(wrfout)
98  if cached is not None: return cached
99  rel=wrfout.path()
100  #outdir=os.path.join(self['outdir'],rel)
101  outdir=self['outdir']
102  assert(outdir is not None)
103 
104  # TODO: Re-Assess, ASSUMING multistorm_sids order. <jtf>
105  # Same concern sid processing order assumption also used in nhc_products.py
106  #
107  # Input to Forecast processing order determines the the mapping from
108  # stormid to domain, 04E,05E,06E,00L ... d<01,02,03,04,05,06... names.
109  # Go back and review this interconnect dependency to the storm order for forcast input.
110  # Can I be assured that order is the multistorm_sids order ? FOr the logic here,
111  # I'm assuming it is ....
112 
113  # Multistorm - jtf
114  # Changes the runwrf.mon::wrfout_d... entries in database for each real storm.
115  # Changes path location to 00L for all real storms in a multistorm run.
116  # changes the FileProduct location to the correct domain for each real storm.
117  # ie. for the 2nd storm in a multistorm d01 -> 00L/d01, d02 -> 00L/d04, d03 -> 00L/d05
118  if self.ismultistorm and not self.isfakestorm:
119  priority_stid= self.conf.getstr('config','multistorm_priority_sid')
120  multistorm_sids=self.conf.getstr('config','multistorm_sids').split()
121  this_stid=self.storminfo.stormid3
122  this_stid_idx=multistorm_sids.index(this_stid)
123 
124  # All realstorms wrfout files are under 00L since that is where the forecast runs.
125  fake_outdir=self.confstrinterp('{realstormwork}/runwrf',
126  realstorm=self.conf.getstr('config','fakestormid'))
127  wrfprod=os.path.basename(wrfout.path())
128 
129  # Now map the domain name - BIG ASSUMPTION. I don't like this.
130  # Need to determine which storm we are on to determine dXXmap for the name.
131  # Using multistorm ids order for this.
132  # ie. [04E, 05E] for 05E this_stid_index=1, so d02map='d04'
133  if this_stid != priority_stid and wrfout.domain().get_grid_id() != 1:
134  if wrfout.domain().get_grid_id() == 2:
135  self._d02map='d%02d'%(this_stid_idx*2+2)
136  assert('d02' in wrfprod)
137  wrfprod=wrfprod.replace('d02',self._d02map)
138  if wrfout.domain().get_grid_id() == 3:
139  self._d03map='d%02d'%(this_stid_idx*2+3)
140  assert('d03' in wrfprod)
141  wrfprod=wrfprod.replace('d03',self._d03map)
142  loc=os.path.join(fake_outdir,wrfprod)
143  else:
144  loc=os.path.join(outdir,os.path.basename(wrfout.path()))
145 
146  with self.dstore.transaction() as t:
147  uf=UpstreamFile(self.dstore,category=self.taskname,
148  prodname=rel,location=loc)
149  uf['minage']=75
150  uf['stream']=wrfout.stream()
151  uf['location']=loc
152  if relocate: uf.location=loc
153  return self._set_cache(wrfout,uf)
154 
155 # fcsttask.py These methods override methods in WRFTaskBase.
157  def run_exe(self,*args,**kwargs): pass
158  def link_fix(self,*args,**kwargs): pass
159  def make_namelist(self,*args,**kwargs): pass
160 
161  def link_all_inputs(self,just_check=False):
162  okay=True
163  if 'merge' in self.inputs:
164  okay=okay and self.link_input(
165  'merge',stormid=self.storminfo.stormid3,
166  just_check=just_check)
167  else:
168  msg='Input type "merge" was not specified.'
169  self.log().critical(msg)
170  raise WRFInputMissing(msg)
171  okay=okay and super(RealInit,self).link_all_inputs(just_check)
172  return okay
173 
174  def add_orig_wrfinput(self,r):
175  super(RealInit,self).add_wrfinput(r)
176 
177  def add_wrfinput(self,r):
178  """Adds an input source (via self.add_input) that will provide
179  the wrfinput output file from gdas_merge, or whatever the last
180  step in the real storm initialization may have been. The
181  given object must have a get_merge(stormid) function that
182  returns a Product for a given storm"""
183  return self.add_input('merge',Input2FinalMerge(
184  self.storminfo.stormid3,r,self.sim.get_moad(),self.conf.cycle))
185 
186  # The multistorm_input task calls this to deliver these
187  # products from a storms intercom directory to its com directory,
188  # for use and input to the finalmerge task
189  def deliver_products(self):
190  c='_' if self.sim.nocolons else ':'
191  #jtfst 00.nc not {SS).nc and removed MM in atime
192  atime='{year}-{month}-{day}_{HH}'+c+'00'+c+'00'
193  met_nmm_time='{year}-{month}-{day}_{HH}'+c+'00'+c+'00.nc'
194  prefix='{com}/{vit[stormid3]}.{YMDH}.multistorm.'
195  stormid=self.storminfo.stormid3
196  files=[ 'geo_nmm.d01.nc',
197  'geo_nmm_nest.l01.nc',
198  'geo_nmm_nest.l02.nc',
199  'met_nmm.d01.'+met_nmm_time,
200  'wrfinput_d01',
201  'wrfbdy_d01',
202  'fort.65',
203  'wrfanl_d02_'+atime,
204  'wrfanl_d03_'+atime,
205  'wrfinput_d01_'+stormid+'gdas_merge.nc']
206  with WorkPool(4) as workers:
207  for f in files:
208  comfile=self.icstr(prefix+f)
209  localfile=self.icstr(f)
210  if not produtil.fileop.isnonempty(localfile):
212  '%s: does not exist or is empty, cannot copy to %s'%(
213  localfile,comfile))
214  workers.add_work(self._copy_one,[localfile,comfile])
215  workers.barrier()
216  def _copy_one(self,fromf,tof):
217  produtil.fileop.deliver_file(fromf,tof,moveok=False,
218  logger=self.log())
219 
221  def __init__(self,ds,conf,section,wrf,realstorm,stormNinner,stormNouter,**kwargs):
222  super(FakeInit,self).__init__(ds,conf,section,**kwargs)
223  self.realstorm=realstorm
224  self.colon='_' if wrf.get_nocolons() else ':'
225  (self.stormNinner,self.stormNouter) = (stormNinner,stormNouter)
226  self.__wrf=wrf
227  with ds.transaction() as tx:
229 
230  @property
231  def sim(self):
232  """!Returns the hwrf.wrf.WRFSimulation being run."""
233  return self.__wrf
234 
235  # This defines the filenames in the storms com diredtory where
236  # the final_merge task and the wrf forecast gets its inputs from.
237  def define_locations_from_com(self):
238  c='_' if self.sim.nocolons else ':'
239  atime='{year}-{month}-{day}_{HH}'+c+'00'+c+'00'
240  met_nmm_time='{year}-{month}-{day}_{HH}'+c+'00'+c+'00.nc'
241  self.geofile={1:self.productify('{realstormcom}/{realstorm}.{YMDH}.multistorm.geo_nmm.d01.nc',
242  'geo_nmm.d01.nc'),
243  3:self.productify('{realstormcom}/{realstorm}.{YMDH}.multistorm.geo_nmm_nest.l01.nc',
244  'geo_nmm_nest.l01.nc'),
245  9:self.productify('{realstormcom}/{realstorm}.{YMDH}.multistorm.geo_nmm_nest.l02.nc',
246  'geo_nmm_nest.l02.nc') }
247  #jtfst 00.nc not {SS}
248  self.metfile=self.productify('{realstormcom}/{realstorm}.{YMDH}.multistorm.met_nmm.d01.'+met_nmm_time,
249  'met_nmm.d01.'+met_nmm_time)
250  self.real_init=self.productify('{realstormcom}/{realstorm}.{YMDH}.multistorm.wrfinput_d01')
251  self.fort65=self.productify('{realstormcom}/{realstorm}.{YMDH}.multistorm.fort.65')
252  self.wrfbdy=self.productify('{realstormcom}/{realstorm}.{YMDH}.multistorm.wrfbdy_d01')
253  self.wrfinput_final=self.productify('{realstormcom}/{realstorm}.{YMDH}.multistorm.wrfinput_d01')
254  self.wrfanl_for=dict()
255  self.merge_for=dict()
256  multistorm_sids = self.conf.getstr(
257  'config','multistorm_sids','nosids').split()
258  for i1 in xrange(len(multistorm_sids)):
259  i=i1+1
260  stormid=multistorm_sids[i1]
261  self.wrfanl_for[self.stormNinner['storm%sinner'%i]]=\
262  self.productify('{realstormcom}/{realstorm}.{YMDH}.multistorm.wrfanl_d03_'+atime,
263  'storm%sinner_wrfanl'%i,stormid=stormid)
264  self.wrfanl_for[self.stormNouter['storm%souter'%i]]=\
265  self.productify('{realstormcom}/{realstorm}.{YMDH}.multistorm.wrfanl_d02_'+atime,
266  'storm%souter_wrfanl'%i,stormid=stormid)
267  self.merge_for[stormid]=\
268  self.productify('{realstormcom}/{realstorm}.{YMDH}.multistorm.wrfinput_d01_'+stormid+'gdas_merge.nc',
269  'merge_%s'%(stormid,),stormid=stormid)
270 
271  def productify(self,filename,prodname=None,stormid=None):
272  if stormid is None: stormid=self.realstorm
273  loc=self.confstrinterp(filename,realstorm=stormid)
274  basename=os.path.basename(loc)
275  if prodname is None:
276  prodname=basename
277  else:
278  prodname=self.confstrinterp(prodname)
279  basename=prodname
280  uf=UpstreamFile(self.dstore,prodname,self.taskname,location=loc)
281  uf.location=loc
282  uf['basename']=basename
283  return uf
284 
285  # ie. returns com/../04E.2012071000.multistorm.wrfinput_d01_04Egdas_merge.nc
286  def get_merge(self,stormid):
287  if stormid in self.merge_for:
288  return self.merge_for[stormid]
289  return None
290 
291  # ie. returns com/../04E.2012071000.multistorm.wrfinput_d01
292  # which is the gfsinit/realinit wrfinput_d01 file.
294  """Returns the wrfinput file regardless of the time or
295  domain"""
296  return self.wrfinput_final
297 
298  def wrfanl_at_time(self,atime,domain):
299  if domain in self.wrfanl_for:
300  return self.wrfanl_for[domain]
301  return None
302 
303  def wrfinput_at_time(self,atime,domain):
304  """Makes add_wrfinput work with this class."""
305  return self.real_init
306 
307  def fort65_at_time(self,atime,domain):
308  """Makes add_fort65 work with this class."""
309  return self.fort65
310 
311  def wrfbdy_at_time(self,atime,domain):
312  """Makes add_wrfbdy work with this class."""
313  return self.wrfbdy
314 
315  def met_at_time(self,ftime):
316  """Makes add_metgrid work with this class."""
317  assert(self.metfile is not None)
318  if ftime==self.conf.cycle:
319  return self.metfile
320  return None
321 
322  def geodat(self,domain,logger=None):
323  """!Makes add_geogrid work with this class.
324  @param domain the domain of interest
325  @bug this only works for nesting ratios that are a power of 3"""
326  ratio=domain.moad_ratio()
327 
328  if logger is None: logger=self.log()
329  try:
330  return self.geofile[ratio]
331  except KeyError as ke:
332  logger.error('BLAH BLAH Requesting domain %s at nest level %d which we do not have from geogrid: %s: %s'%
333  (str(domain),ratio,str(self.geofile),str(ke)),exc_info=True)
334  return None
335 
336 
337 # This class was created in order to override make_namelist in the
338 # WRFTaskBase class since multistorm calls swcorner_dynamic_multistorm
339 # And the multistorm fcsttask needs the realinit input.
341 
342  def __init__(self,dstore,conf,section,wrf,keeprun=True,
343  wrfdiag_stream='auxhist1',**kwargs):
344 
345  super(WRFAtmosMultiStorm,self).__init__(dstore,conf,section,wrf,
346  keeprun=keeprun,wrfdiag_stream=wrfdiag_stream,**kwargs)
347 
348  def make_namelist(self,filename='namelist.input',logger=None):
349  """Runs set_ij_start (swcorner_dynamic) to generate the i & j
350  start locations for domain 2, then generates the namelist.
351 
352  For the fakestorm of multistorm run, it generates the
353  i & j start locations for each of the outer storms domain
354  then generates the namelist."""
355  if logger is None: logger=self.log()
356  domlat=self.conf.getfloat('config','domlat')
357  domlon=self.conf.getfloat('config','domlon')
358  if self.isfakestorm:
359  s=self.wrf().swcorner_dynamic_multistorm(
360  self.getexe('swcorner_dynamic'),self.conf.syndat_multistorm,
361  domlat,domlon,logger)
362  else:
363  s=self.wrf().swcorner_dynamic(self.getexe('swcorner_dynamic'),
364  self.storminfo, domlat,domlon,logger)
365 
366  # Note: self.storminfo is self.conf.syndat, The multistorm info
367  with open(filename,'wt') as nlin:
368  nlin.write(s)
369 
371  """This is a Task that copies WRF input and output files from the
372  WRF FAKE Storm run directory to the COM directory,for a Multi Storm Basin Scale."""
373  def __init__(self,dstore,conf,section,wrftask,out_prefix,**kwargs):
374 
375  super(WRFCopyTaskMS,self).__init__(
376  dstore,conf,'copywrf',wrftask,conf.getstr('config','out_prefix'))
377 
378  self.__wrftask=wrftask
379 
380  # This is the ForecastWatcher object of a multistorm.
381  @property
382  def wrf_watcher(self):
383  """!Returns the hwrf.wrf.WRFSimulation being run."""
384  return self.__wrftask
385 
386  def comfile(self,orig,destname=None):
387  """Generates a full path to the delivery location of the
388  specified source file. Returns the full path and the basename
389  in a tuple."""
390 
391  # Multistorm - jtf
392  # This function.
393  # Changes **task**::copywrf task, only the *wrfout* FileProduct entries are changed.
394  # Changes id and location.
395  # For multistorm, make sure WRFCopyTaskMS Always uses the UpstreamFile
396  # database prodname of (orig) instead of (orig.location) This ensures correct
397  # name mapping since multistorm,real storm product locations in runwrf.mon are mapped
398  # back to 00L/d<1,2,3,4,5,6,7 ...> and we want the copywrf productname
399  # and location to always be referencing d01,d02,d03, for any of the storms
400  # in a multistorm ... else they would be d01,d04,d05; d01,d06,d07 ...
401  # Using the prodname is extremely convenient and necessary since we have
402  # no reference to which dXX of the storm it is unless we assume
403  # order of processing the storms.
404  # ie. Here is an example database entry, This allows this d04 file under 00L to be
405  # copied and written as the desired d02 file under 05E.
406  # id | available | location | type
407  # runwrf.mon::wrfout_d02_2012-07-10_00:00:00|1|/pytmp/path/2012071000/00L/runwrf/wrfout_d04_2012-07-10_00:00:00|UpstreamFile
408  # copywrf::05e.wrfout_d02_2012-07-10_00:00:00|1|/pytmp/path/com/2012071000/05E/05e.wrfout_d02_2012-07-10_00:00:00|FileProduct
409 
410  if(isinstance(orig,Product)):
411  thisprodname=orig.getprodname()
412  bn=os.path.basename(str(thisprodname))
413  else:
414  bn=os.path.basename(str(orig))
415 
416  # The bn_colon is the same as bn, but uses : to separate time
417  # components, - to separate date components and an _ between
418  # the date and time. This matches the syntax expected by most
419  # programs external to this workflow.
420  bn_colon=re.sub(
421  '([0-9][0-9][0-9][0-9])[_.-]([0-9][0-9])[_.-]([0-9][0-9])'
422  '[_.-]([0-9][0-9])[_.-]([0-9][0-9])[_.-]([0-9][0-9])[^/]*$',
423  r'\1-\2-\3_\4:\5:\6',bn)
424  bn_colon_s00=re.sub(
425  '([0-9][0-9][0-9][0-9])[_.-]([0-9][0-9])[_.-]([0-9][0-9])'
426  '[_.-]([0-9][0-9])[_.-]([0-9][0-9])[_.-]([0-9][0-9])[^/]*$',
427  r'\1-\2-\3_\4:\5:00',bn)
428 
429  if destname is None:
430  fullbn='%s.%s'%(self.out_prefix,bn_colon)
431  else:
432  fullbn=self.confstrinterp(destname,inname=bn,
433  inname_colon=bn_colon,
434  inname_colon_s00=bn_colon_s00)
435  return ( os.path.join(self.outdir,fullbn), fullbn )
436 
437  def _deliver_to_group(self,group,inprod,check=None,destname=None):
438  """Do not call this function directly. It is the internal
439  implementation of d_initial and d_final. Call those functions
440  instead."""
441  (comfile,combn)=self.comfile(inprod,destname=destname)
442  if(isinstance(inprod,Product)):
443  upstream=inprod
444  if check is None: check=False
445  else:
446  # Multistorm - jtf
447  # Setting the wrffile path for multistorm WRFCopyTask, copywrf-upstream::
448  # Not sure why wrffile is using self._wrftask.location (non multistorm)
449  # since that is empty ''. Look at the WRFCopyTask, copywrf-upstream lines in
450  # the datastore AFTER the launcher task runs. Only the filenames are present.
451  # AFTER WRFCopyTask is run ... the paths are updated. The only reason the task
452  # has been working is because the UpstreamFile exists in the SID/runwrf workdir.
453  # That is not the case for multistorm, since these UptreamFile's only exist in
454  # the fakestorm 00L/runwrf dir. Hence this change.
455  # I think for non multistorm (ie. the outer else:) self._wrftask.workdir
456  # should be used instead. It has been working so I will leave it alone.
457  if self.ismultistorm:
458  if self.isfakestorm:
459  wrffile=os.path.join(self._wrftask.workdir,inprod)
460  else:
461  #fakestormid=self.conf.getstr('config','fakestormid')
462  #this_stid=self.storminfo.stormid3
463 
464  fake_outdir=self.confstrinterp('{realstormwork}/runwrf',
465  realstorm=self.conf.getstr('config','fakestormid'))
466 
467  #Note: self.wrf_watcher.d03remap does not exist, if this isfakestorm=True
468  if inprod == 'track_d03.patcf' and self.wrf_watcher.d03remap:
469  inprod_d03remap= inprod.replace('d03',self.wrf_watcher.d03remap)
470  wrffile=os.path.join(fake_outdir,inprod_d03remap)
471  else:
472  #wrffile=os.path.join(self._wrftask.workdir.replace(this_stid,fakestormid),inprod)
473  wrffile=os.path.join(fake_outdir,inprod)
474 
475  else:
476  wrffile=os.path.join(self._wrftask.location,inprod)
477 
478  #This will return the domain map using wrfdiag_d03
479  #with self.dstatore.transaction() at tx:
480  # self.dstore.transaction().query(
481  # "select location from products where id='runwrf::wrfdiag_d03'")[0][0][-3]
482  #Using ForecastWatcher above .. instead
483 
484 
485  # Make an internal UpstreamFile to check for the file:
486  upstream=UpstreamFile(dstore=self.dstore,prodname=combn,
487  category="%s-upstream"%(self.taskname,),location=wrffile)
488  upstream.location=wrffile
489  # Nobody else can see this Product so we must check it:
490  check=True
491 
492  product=FileProduct(
493  dstore=self.dstore,prodname=combn,category=self.taskname,
494  location=comfile)
495  group.append( (upstream,product,bool(check)) )
496  return self
This module provides a set of utility functions to do filesystem operations.
Definition: fileop.py:1
def deliver_file
This moves or copies the file "infile" to "outfile" in a unit operation; outfile will never be seen i...
Definition: fileop.py:359
Create namelists, monitor wrf simulations, generate filenames.
Definition: wrf.py:1
def confstrinterp(self, string, section=None, kwargs)
Alias for self.icstr for backward compatibility.
Definition: hwrftask.py:319
def _copy_one(self, fromf, tof)
Definition: multistorm.py:216
def link_input(self, typenames, just_check=False, kwargs)
link or check for inputs
Definition: fcsttask.py:417
def getexe
Alias for hwrf.config.HWRFConfig.get() for the "exe" section.
Definition: hwrftask.py:403
taskname
Read-only property: the name of this task.
Definition: datastore.py:1134
The base class of tasks run by the HWRF system.
Definition: hwrftask.py:25
def check_all_inputs(self)
Placeholder to allow a ForecastWatcher to look like an hwrf.fcsttask.WRFAtmos to the scripts...
Definition: multistorm.py:88
dstore
Read-only property, an alias for getdatastore(), the Datastore in which this Datum resides...
Definition: datastore.py:557
storminfo
The hwrf.storminfo.StormInfo describing the vitals information for the storm processed by this HWRFTa...
Definition: hwrftask.py:94
base class of classes that run wrf or real_nmm
Definition: fcsttask.py:488
def get_wrfinput_gfsinit_realinit(self)
Definition: multistorm.py:293
def sim(self)
Returns the hwrf.wrf.WRFSimulation being run.
Definition: multistorm.py:231
def wrf_watcher(self)
Returns the hwrf.wrf.WRFSimulation being run.
Definition: multistorm.py:382
low-level wrf implementation, underlying hwrf.wrf
Definition: wrfbase.py:1
def wrfinput_at_time(self, atime, domain)
Definition: multistorm.py:303
Base class of tasks run by HWRF.
Definition: hwrftask.py:1
def wrf(self)
Returns the WRFSimulation object used by this task.
Definition: fcsttask.py:982
outdir
The directory in which this task should deliver its final output.
Definition: hwrftask.py:176
out_prefix
Prefix to prepend to output filenames after the com path.
Definition: copywrf.py:87
Contains the WorkPool class, which maintains pools of threads that perform small tasks.
Definition: workpool.py:1
def geodat
Makes add_geogrid work with this class.
Definition: multistorm.py:322
def isnonempty(filename)
Returns True if the filename refers to an existent file that is non-empty, and False otherwise...
Definition: fileop.py:333
Stores products and tasks in an sqlite3 database file.
Definition: datastore.py:1
The uncoupled HWRF forecast Task.
Definition: fcsttask.py:1544
Time manipulation and other numerical routines.
Definition: numerics.py:1
def comfile
get the full path to a file
Definition: copywrf.py:192
workdir
The directory in which this task should be run.
Definition: hwrftask.py:156
Raised when wrf or real want to run, but wrfinput files are missing.
Definition: exceptions.py:346
def _set_cache(self, wrfout, uf)
Sets the cached produtil.datastore.UpstreamFile for the given wrfout.
Definition: wrf.py:1370
This module provides two different ways to generate Fortran namelist files from HWRFConfig sections: ...
Definition: namelist.py:1
A pool of threads that perform some list of tasks.
Definition: workpool.py:84
def log
Obtain a logging domain.
Definition: hwrftask.py:425
monitors a running wrf simulation
Definition: wrf.py:1296
inputs
a mapping of typename to a list of input objects
Definition: fcsttask.py:381
def _get_cache(self, wrfout)
Returns the product cached for the specified wrfout or None if not found.
Definition: wrf.py:1363
def ismultistorm(self)
Definition: hwrftask.py:135
wrf file delivery task
Definition: copywrf.py:67
Parent class of exceptions specific to the hwrf.fcsttask module.
Definition: exceptions.py:338
def define_locations_from_com(self)
Definition: multistorm.py:237
def add_input(self, typename, inobj)
add input of a specified type
Definition: fcsttask.py:393
Exceptions raised by the hwrf package.
Definition: exceptions.py:1
def fort65_at_time(self, atime, domain)
Definition: multistorm.py:307
def wrfbdy_at_time(self, atime, domain)
Definition: multistorm.py:311
def add_wrfinput(self, r)
Definition: multistorm.py:177
def isfakestorm(self)
Definition: hwrftask.py:113
def icstr(self, string, section=None, kwargs)
Expands a string in the given conf section.
Definition: hwrftask.py:351
def met_at_time(self, ftime)
Definition: multistorm.py:315