HWRF  trunk@4391
init.py
1 #!/usr/bin/env python
2 
3 ##@namespace pom.init
4 #POM preprocessing and spinup scripts.
5 #
6 #This module contains classes and methods for ocean prepossessing,
7 #ocean spin up: Phase1 and Phase2 (also known as Phase3 and
8 #Phase4). The prognostic ocean spin up uses wind stress forcing that is
9 #based on NHC vitals. I use a simple "get_vitals" function to extract
10 #vitals from NHC vital file (syndat_tcvitals.${yyyy}).
11 #
12 #@note Please report bugs/questions/comments to bijuthomas(at)mail(dot)uri(dot)edu.
13 #@author Biju Thomas, GSO, University of Rhode Island.
14 #@date June 13, 2014
15 
16 ##@var __all__
17 # List of symbols exported by "from pom.init import *"
18 __all__=[ 'Hwrf', 'Oceanini', 'fbtr', 'g3', 'na', 'phase', 'pget', 'prun', 'psend' ]
19 
20 import os
21 import logging
22 import shutil
23 import os.path
25 
26 from os.path import join as jn2r
27 from produtil.cd import NamedDir
28 from produtil.fileop import deliver_file, makedirs, make_symlink, rmall, isnonempty
29 from produtil.run import mpi, mpirun, checkrun, run, exe , openmp, runsync
30 from util import ysplitter, inpfile, logi2int
31 from exceptions import *
32 from check_lcfiles import Isthis_LCuseful
33 
34 class Hwrf(object):
35  """!Abstract base class that stores data relating to the HWRF
36  workflow in which the POM initialization resides."""
37  def __init__(self,STORMNAME,STORMID,STARTDATE,EXEChwrf,PARMhwrf,
38  FIXhwrf,LCDIR,GFSDIR,CSTREAM,COMIN,
39  sync_frequently=False):
40  """!Hwrf constructor
41  @param STORMNAME Upper-case storm name for filenames (KATRINA)
42  @param STORMID Three character storm number and basin, upper-case (12L)
43  @param STARTDATE Simulation analysis time as a string, YYYYMMDDHH (2005082918)
44  @param EXEChwrf Directory with HWRF executables.
45  @param PARMhwrf Directory with HWRF parameter files.
46  @param FIXhwrf Directory with HWRF fixed files.
47  @param LCDIR Directory with loop current files
48  @param GFSDIR Directory with input files from GFS.
49  @param CSTREAM Directory to place files for the POM forecast to read.
50  @param COMIN HWRF final output directory.
51 
52  @param sync_frequently If True, run "sync" frequently"""
53  self.STORMNAME = STORMNAME
54  self.STORMID = STORMID
55  self.STARTDATE = STARTDATE
56  self.EXEChwrf = EXEChwrf
57  self.PARMhwrf = PARMhwrf
58  self.LCDIR = LCDIR
59  self.GFSDIR = GFSDIR
60  self.FIXhwrf = FIXhwrf
61  assert(self.GFSDIR.find('pom/output')<0)
62  self.CSTREAM = CSTREAM
63  self.COMIN = COMIN
64  self.sync_frequently = bool(sync_frequently)
65 
66  ##@var STORMNAME
67  # Upper-case storm name for filenames (KATRINA)
68 
69  ##@var STORMID
70  # Three character storm number and basin, upper-case (12L)
71 
72  ##@var STARTDATE
73  # Simulation analysis time as a string, YYYYMMDDHH (2005082918)
74 
75  ##@var EXEChwrf
76  # Directory with HWRF executables.
77 
78  ##@var PARMhwrf
79  # Directory with HWRF parameter files.
80 
81  ##@var FIXhwrf
82  # Directory with HWRF fixed files.
83 
84  ##@var LCDIR
85  # Directory with loop current files
86 
87  ##@var GFSDIR
88  # Directory with input files from GFS.
89 
90  ##@var CSTREAM
91  # Directory to place files for the POM forecast to read.
92 
93  ##@var COMIN
94  # HWRF final output directory.
95 
96 class Oceanini(Hwrf):
97  """!Parent class of POM initialization classes."""
98  def __init__(self,ODIR,DOMAIN,ODATA,SSTASIM,STORMNAME,STORMID,STARTDATE,EXEChwrf,PARMhwrf,
99  FIXhwrf,LCDIR,GFSDIR,CSTREAM,COMIN,
100  sync_frequently=False,**kwargs):
101  """!Oceanini constructor
102  @param ODIR Ocean output directory in CSTREAM
103  @param SSTASIM SST ASIM flag, True or False
104  @param DOMAIN Ocean domain.
105  @param ODATA Type of ocean data.
106  @param STORMNAME Upper-case storm name for filenames (KATRINA)
107  @param STORMID Three character storm number and basin, upper-case (12L)
108  @param STARTDATE Simulation analysis time as a string, YYYYMMDDHH (2005082918)
109  @param EXEChwrf Directory with HWRF executables.
110  @param PARMhwrf Directory with HWRF parameter files.
111  @param FIXhwrf Directory with HWRF fixed files.
112  @param LCDIR Directory with loop current files
113  @param GFSDIR Directory with input files from GFS.
114  @param CSTREAM Directory to place files for the POM forecast to read.
115  @param COMIN HWRF final output directory.
116  @param sync_frequently if True, run "sync" frequently
117  @param kwargs Can optionally contain conf, which should point
118  to a ConfigParser-like object to use for configuration
119  information. An hwrf.config.HWRFConfig is acceptable for
120  this."""
121  assert(GFSDIR.find('pom/output')<0)
122  super(Oceanini,self).__init__(STORMNAME,STORMID,STARTDATE,EXEChwrf,PARMhwrf,
123  FIXhwrf,LCDIR,GFSDIR,CSTREAM,COMIN,
124  sync_frequently=sync_frequently)
125  self.ODIR = ODIR
126  self.DOMAIN = DOMAIN
127  self.ODATA = ODATA
128  self.SSTASIM = SSTASIM
129  self.conf = kwargs.pop('conf', None)
130 
131  ##@var ODIR
132  # Ocean output directory in CSTREAM
133 
134  ##@var SSTASIM
135  # SST ASIM flag, True or False
136 
137  ##@var DOMAIN
138  # Ocean domain.
139 
140  ##@var ODATA
141  # Type of ocean data.
142 
143  ##@var conf
144  # A ConfigParser-like object to use for configuration information. This may be
145  # a hwrf.config.HWRFConfig object.
146 
147  def setpath(self,SUBDIR=""):
148  """!Creates the ocean run path, whose subdirectory is SUBDIR.
149  @param SUBDIR the subdirectory to create
150  @returns a tuple (rundir,finaldir) where rundir is CSTREAM+'/'+ODIR
151  and finaldir is the SUBDIR subdirectory of that """
152  RUNDIR = self.CSTREAM +"/"+self.ODIR
153  try:
154  if SUBDIR != "" and os.path.exists(RUNDIR) and \
155  not os.path.exists(RUNDIR+"/"+SUBDIR):
156  makedirs(RUNDIR+"/"+SUBDIR)
157  if not os.path.exists(RUNDIR):
158  makedirs(RUNDIR)
159  return (RUNDIR,RUNDIR+"/"+SUBDIR)
160  except:
161  raise IOError('CSTREAM does NOT exist.')
162 
163 class fbtr(Oceanini):
164  """!Runs the FBTR (feature-based) initialization of the MPIPOMTC."""
165  def __init__(self,*args,**kargs):
166  """!fbtr constructor
167  @param args,kargs passed to Oceanini.__init__()"""
168  super(fbtr,self).__init__(*args,**kargs)
169  def getinp(self, DEST,logger=None):
170  """!Links or copies input files.
171 
172  @param DEST The directory in which to link or copy files.
173  @param logger A logging.Logger for log messages."""
174  if logger is None: logger=logging.getLogger('pom')
175  try:
176  (y4,mm,mm1,dd,hh) = ysplitter(self.STARTDATE)
177  make_symlink(jn2r(self.GFSDIR, "gfs.t"+hh+"z.sfcanl"),jn2r(DEST,"fort.11"),True,logger=logger)
178  make_symlink(jn2r(self.GFSDIR, "gfs.t"+hh+"z.sfcanl"),jn2r(DEST,"for11"),True,logger=logger)
179  make_symlink(jn2r(self.GFSDIR, "gfs.t"+hh+"z.sanl"),jn2r(DEST,"fort.12"),True,logger=logger)
180  make_symlink(jn2r(self.FIXhwrf,"gfdl_ocean_topo_and_mask.united"),
181  jn2r(DEST,"fort.66"),True,logger=logger)
182  make_symlink(jn2r(self.FIXhwrf,"gfdl_gdem."+mm+".ascii"),
183  jn2r(DEST,"fort.8"),True,logger=logger)
184  make_symlink(jn2r(self.FIXhwrf,"gfdl_gdem."+mm1+".ascii"),
185  jn2r(DEST,"fort.90"),True,logger=logger)
186  make_symlink(jn2r(self.FIXhwrf,"gfdl_ocean_readu.dat."+mm),
187  jn2r(DEST,"fort.24"),True,logger=logger)
188  make_symlink(jn2r(self.FIXhwrf,"gfdl_ocean_spinup_gdem3.dat."+mm),
189  jn2r(DEST,"fort.82"),True,logger=logger)
190  make_symlink(jn2r(self.FIXhwrf,"gfdl_ocean_spinup_gspath."+mm),
191  jn2r(DEST,"fort.50"),True,logger=logger)
192  make_symlink(jn2r(self.FIXhwrf,"gfdl_ocean_spinup.BAYuf"),
193  jn2r(DEST,"fort.55"),True,logger=logger)
194  make_symlink(jn2r(self.FIXhwrf,"gfdl_ocean_spinup.FSgsuf"),
195  jn2r(DEST,"fort.65"),True,logger=logger)
196  make_symlink(jn2r(self.FIXhwrf,"gfdl_ocean_spinup.SGYREuf"),
197  jn2r(DEST,"fort.75"),True,logger=logger)
198  lfile = jn2r(self.LCDIR,"hwrf_gfdl_loop_current_rmy5.dat."+y4+mm+dd)
199  rfile = jn2r(self.LCDIR,"hwrf_gfdl_loop_current_wc_ring_rmy5.dat."+y4+mm+dd)
200  if Isthis_LCuseful(self.STARTDATE, lfile, rfile,logger=logger):
201  make_symlink(lfile,jn2r(DEST,"fort.31"),True,logger=logger)
202  make_symlink(rfile,jn2r(DEST,"fort.32"),True,logger=logger)
203  else:
204  make_symlink(jn2r(self.PARMhwrf,"hwrf_gfdl_loop_current_rmy5.dat"),
205  jn2r(DEST,"fort.31"),True,logger=logger)
206  make_symlink(jn2r(self.PARMhwrf,"hwrf_gfdl_loop_current_wc_ring_rmy5.dat"),
207  jn2r(DEST,"fort.32"),True,logger=logger)
208  inpfile(jn2r(DEST,"fort.91"), [mm, dd],logger=logger)
209  inpfile(jn2r(DEST,"input_sharp"),["1"],logger=logger)
210  inpfile(jn2r(DEST,"input"),
211  [self.ODATA, "0", str(logi2int(self.SSTASIM)),self.STORMNAME],logger=logger)
212  except Exception as e:
213  msg='Cannot find input: '+str(e)
214  logger.warning(msg,exc_info=True)
215  raise POMInputError(msg)
216  def setrun(self, DEST,logger=None):
217  """!Runs the FBTR initialization
218  @param DEST the destination directory in which to run and generate output.
219  @param logger a logging.Logger for log messages"""
220  with NamedDir(DEST) as d:
221  if logger is None: logger=logging.getLogger('pom')
222  (y4,mm,mm1,dd,hh) = ysplitter(self.STARTDATE)
223  rmall(jn2r(DEST,"fort.23"),jn2r(DEST,"fort.74"),jn2r(DEST,"fort.77"),logger=logger)
224  rmall(jn2r(DEST,"lonlat.gfs"),jn2r(DEST,"sst.gfs.dat"),jn2r(DEST,"mask.gfs.dat"),logger=logger)
225  if os.path.exists(jn2r(DEST,"fort.11")) and os.path.exists(jn2r(DEST,"fort.12")):
226  with open('listing','wb') as f:
227  listing=str(produtil.listing.Listing())
228  f.write(listing)
230  # Raise stack limit to 6000M
231  produtil.rusage.setrlimit(ignore=True,logger=logger,stack=6e9)
232  xc = self.conf.getexe('hwrf_getsst')
233  log = jn2r(DEST,"getsst.out")
234  with produtil.rusage.rusage(logger=logger):
235  if self.sync_frequently: runsync()
236  retcode = run(openmp(exe(xc),threads=1).env(OMP_STACKSIZE='128M')
237  > log,logger=logger)
238  logger.info("hwrf_getsst: err = %s" %(retcode))
239  if retcode == 0 and os.path.exists(jn2r(DEST,"fort.74")):
240  deliver_file(jn2r(DEST,"fort.74"),jn2r(DEST,"sst.gfs.dat"),False)
241  deliver_file(jn2r(DEST,"fort.77"),jn2r(DEST,"mask.gfs.dat"),False)
242  logger.info("GFS SST extracted: {0}".format(DEST))
243  else:
244  msg="hwrf_getsst Failed: NO GFS SST extracted: {0}".format(DEST)
245  logger.warning(msg)
246  raise POMSSTError(msg)
247  else:
248  msg="GFS Spectral Files NOT Found in %s:" %(DEST)
249  logger.error(msg)
250  raise POMInputError(msg)
251 
252  if isnonempty('fort.31') and isnonempty('fort.32'):
253  rmall(jn2r(DEST,"fort.13"),jn2r(DEST,"gfdl_initdata.united."+mm),logger=logger)
254  xc = self.conf.getexe('hwrf_sharp_mcs_rf_l2m_rmy5')
255  inp = jn2r(DEST,"input_sharp")
256  log = jn2r(DEST,"sharp_mcs_r_l2b.out")
257  if self.sync_frequently: runsync()
258  retcode = run((exe(xc) < inp) >= log,logger=logger)
259  logger.info("sharp_mcs_rf: err = %s" %(retcode))
260  if retcode == 0 and os.path.exists(jn2r(DEST,"fort.13")):
261  deliver_file(jn2r(DEST,"fort.13"),jn2r(DEST,"gfdl_initdata.united."+mm),False,logger=logger)
262  logger.info("Specified LC penetration: {0}".format(retcode))
263  else:
264  deliver_file(jn2r(self.FIXhwrf,"gfdl_initdata.gdem.united."+mm),
265  jn2r(DEST,"gfdl_initdata.united."+mm),logger=logger)
266  logger.warning("sharp_mcs_rf failed: Climate LC penetration %s" %(retcode))
267 
268  else:
269  deliver_file(jn2r(self.FIXhwrf,"gfdl_initdata.gdem.united."+mm),
270  jn2r(DEST,"gfdl_initdata.united."+mm),logger=logger)
271  # Log to highest log level so it is in the jlogfile:
272  logger.critical("LC data NOT available: Climate LC penetration %s" %(retcode))
273  if os.path.exists(jn2r(DEST,"gfdl_initdata.united."+mm)):
274  make_symlink(DEST+"/gfdl_initdata.united."+mm, DEST+"/fort.13",True,logger=logger)
275  xc = self.conf.getexe('hwrf_ocean_transatl06prep')
276  log = jn2r(DEST,"transatl06prep.out")
277  if self.sync_frequently: runsync()
278  retcode = run(exe(xc) >= log, logger=logger)
279  if retcode == 0 and os.path.exists(jn2r(DEST,"fort.113")):
280  deliver_file(jn2r(DEST,"fort.113"),jn2r(DEST,"gfdl_initdata."+self.DOMAIN+"."+mm),False,logger=logger)
281  logger.info("transatl06prep: Success {0}".format(retcode))
282  else:
283  msg="transatl06prep: Failed {0}".format(retcode)
284  logger.warning(msg)
285  raise POMPrepError(msg)
286  else:
287  logger.info("NOT Found in %s:" %("gfdl_initdata.united."+mm))
288  if os.path.exists(jn2r(DEST,"gfdl_initdata."+self.DOMAIN+"."+mm)):
289  deliver_file(jn2r(DEST,"sst.gfs.dat"),jn2r(DEST,"fort.21"),False,logger=logger)
290  deliver_file(jn2r(DEST,"mask.gfs.dat"),jn2r(DEST,"fort.22"),False,logger=logger)
291  rmall(jn2r(DEST,"fort.13"),logger=logger)
292  make_symlink(jn2r(DEST,"gfdl_initdata."+self.DOMAIN+"."+mm),jn2r(DEST,"fort.13"),True,logger=logger)
293  make_symlink(jn2r(self.FIXhwrf,"gfdl_ocean_topo_and_mask."+self.DOMAIN+
294  ".lores"), jn2r(DEST,"fort.66"),True,logger=logger)
295  xc = self.conf.getexe("hwrf_ocean_pomprep_"+self.ODATA[0:2])
296  inp = jn2r(DEST,"input")
297  log = jn2r(DEST,"ocean_pomprep.out")
298  if self.sync_frequently: runsync()
299  retcode = run((exe(xc) < inp ) >= log,logger=logger)
300  if retcode == 0 and os.path.exists(jn2r(DEST,self.STORMNAME+".grid.nc")):
301  logger.info("ocean_pomprep: Success %s:" %(self.ODATA))
302  return True
303  else:
304  msg="ocean_pomprep: Failed %s" %(self.ODATA)
305  logger.warning(msg)
306  raise POMInitFailed(msg)
307  else:
308  msg="NOT Found in %s:" %(''.join(["gfdl_initdata.",self.DOMAIN,".",mm]))
309  logger.warning(msg)
310  raise POMInitFailed(msg)
311 
312 class g3(Oceanini):
313  """!Runs the G3 initialization for POM."""
314  def __init__(self, *args,**kargs):
315  """!g3 constructor
316  @param args,kargs All arguments are passed to Oceanini.__init__()"""
317  super(g3,self).__init__(*args,**kargs)
318  def getinp(self, DEST,logger=None):
319  """!Links all required input files.
320  @param DEST directory in which to link inputs.
321  @param logger a logging.Logger for log messages"""
322  if logger is None: logger=logging.getLogger('pom')
323  (y4,mm,mm1,dd,hh) = ysplitter(self.STARTDATE)
324  try:
325  make_symlink(jn2r(self.GFSDIR,"gfs.t"+hh+"z.sfcanl"),jn2r(DEST,"fort.11"),True,logger=logger)
326  make_symlink(jn2r(self.GFSDIR,"gfs.t"+hh+"z.sfcanl"),jn2r(DEST,"for11"),True,logger=logger)
327  make_symlink(jn2r(self.GFSDIR,"gfs.t"+hh+"z.sanl"),jn2r(DEST,"fort.12"),True,logger=logger)
328  make_symlink(jn2r(self.FIXhwrf,"gfdl_ocean_topo_and_mask."+
329  self.DOMAIN+".lores"),jn2r(DEST,"fort.66"),True,logger=logger)
330  make_symlink(jn2r(self.FIXhwrf,"tgdemv3s"+mm+".nc"),
331  jn2r(DEST,"tin.nc"),True,logger=logger)
332  make_symlink(jn2r(self.FIXhwrf,"sgdemv3s"+mm+".nc"),
333  jn2r(DEST,"sin.nc"),True,logger=logger)
334  inpfile(jn2r(DEST,"input"),
335  [self.ODATA, "0", str(logi2int(self.SSTASIM)),self.STORMNAME],logger=logger)
336  except Exception as e:
337  msg='Input Data does NOT exist: %s'%(str(e),)
338  logger.error(msg,exc_info=True)
339  raise POMInputError(msg)
340  def setrun(self, DEST,logger=None):
341  """!Runs the g3 ocean initialization
342  @param DEST directory in which to run
343  @param logger a logging.Logger for log messages"""
344  with NamedDir(DEST):
345  if logger is None: logger=logging.getLogger('pom')
346  (y4,mm,mm1,dd,hh) = ysplitter(self.STARTDATE)
347  rmall(jn2r(DEST,"fort.23"),jn2r(DEST,"fort.74"),jn2r(DEST,"fort.77"),logger=logger)
348  rmall(jn2r(DEST,"lonlat.gfs"),jn2r(DEST,"sst.gfs.dat"),jn2r(DEST,"mask.gfs.dat"),logger=logger)
349  if os.path.exists(jn2r(DEST,"fort.11")) and os.path.exists(jn2r(DEST,"fort.12")):
351  # Raise stack limit to 6000M
352  produtil.rusage.setrlimit(ignore=True,logger=logger,stack=6e9)
353  xc = self.conf.getexe('hwrf_getsst')
354  log = jn2r(DEST,"getsst.out")
355  if self.sync_frequently: runsync()
356  retcode = run(exe(xc).env(OMP_STACKSIZE='128M')
357  > log,logger=logger)
358  logger.info("hwrf_getsst: err = %s" %(retcode))
359  if retcode == 0 and os.path.exists(jn2r(DEST,"fort.74")):
360  deliver_file(jn2r(DEST,"fort.74"),jn2r(DEST,"sst.gfs.dat"),False,logger=logger)
361  deliver_file(jn2r(DEST,"fort.77"),jn2r(DEST,"mask.gfs.dat"),False,logger=logger)
362  logger.info("GFS SST extracted: {0}".format(retcode))
363  else:
364  msg="hwrf_getsst Failed: NO GFS SST extracted %s" %(retcode)
365  logger.warning(msg)
366  raise POMSSTError(msg)
367  else:
368  msg="GFS Spectral Files NOT Found in %s:" %(DEST)
369  logger.warning(msg)
370  raise POMInputError(msg)
371  deliver_file(jn2r(DEST,"sst.gfs.dat"),jn2r(DEST,"fort.21"),False,logger=logger)
372  deliver_file(jn2r(DEST,"mask.gfs.dat"),jn2r(DEST,"fort.22"),False,logger=logger)
373  xc = self.conf.getexe("hwrf_ocean_pomprep_"+self.ODATA[0:2])
374  inp = jn2r(DEST,"input")
375  log = jn2r(DEST,"ocean_pomprep.out")
376  if self.sync_frequently: runsync()
377  retcode = run((exe(xc) < inp) > log,logger=logger)
378  if retcode == 0 and os.path.exists(jn2r(DEST,self.STORMNAME+".grid.nc")):
379  logging.info("ocean_pomprep: Success %s:" %(self.ODATA))
380  return True
381  else:
382  msg="ocean_pomprep: Failed %s:" %(self.ODATA)
383  logger.warning(msg)
384  raise POMInitFailed(msg)
385 
386 class na(Oceanini):
387  """!Runs the na (NCODA) initialization of POM."""
388  def __init__(self, *args,**kargs):
389  """!na Constructor
390  @param args,kargs All arguments passed to Oceanini.__init__()"""
391  super(na,self).__init__(*args,**kargs)
392  def getinp(self, DEST, logger=None):
393  """!Obtains all input files, linking or copying them.
394  @param DEST Directory in which to link files.
395  @param logger a logging.Logger for log messages"""
396  if logger is None: logger=logging.getLogger('pom')
397  (y4,mm,mm1,dd,hh) = ysplitter(self.STARTDATE)
398  try:
399  # RMY: For now, define local variable "NCDADIR" to point to the NCODA input data #
400  make_symlink(jn2r(self.GFSDIR,"gfs.t"+hh+"z.sfcanl"),jn2r(DEST,"fort.11"),True,logger=logger)
401  make_symlink(jn2r(self.GFSDIR,"gfs.t"+hh+"z.sfcanl"),jn2r(DEST,"for11"),True,logger=logger)
402  make_symlink(jn2r(self.GFSDIR,"gfs.t"+hh+"z.sanl"),jn2r(DEST,"fort.12"),True,logger=logger)
403  make_symlink(jn2r(self.FIXhwrf,"gfdl_ocean_topo_and_mask."+
404  self.DOMAIN+".lores"),jn2r(DEST,"fort.66"),True,logger=logger)
405  NCDADIR="/lfs2/projects/hwrf-vd/hwrf-input/NCODA/"+y4+"/"+y4+mm+dd+"/"
406  make_symlink(jn2r(NCDADIR,"seatmp_pre_000000_005000_1o2161x1051_"+
407  y4+mm+dd+"00_00000000_analfld"),jn2r(DEST,"fort.48"),True,logger=logger)
408  make_symlink(jn2r(NCDADIR,"salint_pre_000000_005000_1o2161x1051_"+
409  y4+mm+dd+"00_00000000_analfld"),jn2r(DEST,"fort.49"),True,logger=logger)
410  make_symlink(jn2r(self.FIXhwrf,"depths_sfc_000000_000000_1o2161x1051_datafld"),
411  jn2r(DEST,"fort.68"),True,logger=logger)
412  make_symlink(jn2r(self.FIXhwrf,"grdlon_sfc_000000_000000_1o2161x1051_datafld"),
413  jn2r(DEST,"fort.78"),True,logger=logger)
414  make_symlink(jn2r(self.FIXhwrf,"grdlat_sfc_000000_000000_1o2161x1051_datafld"),
415  jn2r(DEST,"fort.79"),True,logger=logger)
416  ##################################################################################
417  inpfile(jn2r(DEST,"input"),
418  [self.ODATA, "0", str(logi2int(self.SSTASIM)),self.STORMNAME],logger=logger)
419  except Exception as e:
420  msg='Input data does NOT exist: %s'%(str(e),)
421  logger.error(msg,exc_info=True)
422  raise POMInputError(msg)
423  def setrun(self, DEST,logger=None):
424  """!Runs the na initialization.
425  @param DEST directory in which to run.
426  @param logger a logging.Logger for log messages."""
427  with NamedDir(DEST):
428  if logger is None: logger=logging.getLogger('pom')
429  (y4,mm,mm1,dd,hh) = ysplitter(self.STARTDATE)
430  rmall(jn2r(DEST,"fort.23"),jn2r(DEST,"fort.74"),jn2r(DEST,"fort.77"),logger=logger)
431  rmall(jn2r(DEST,"lonlat.gfs"),jn2r(DEST,"sst.gfs.dat"),jn2r(DEST,"mask.gfs.dat"),logger=logger)
432  if os.path.exists(jn2r(DEST,"fort.11")) and os.path.exists(jn2r(DEST,"fort.12")):
434  # Raise stack limit to 6000M
435  produtil.rusage.setrlimit(ignore=True,logger=logger,stack=6e9)
436  xc = self.conf.getexe('hwrf_getsst')
437  log = jn2r(DEST,"getsst.out")
438  if self.sync_frequently: runsync()
439  retcode = run(exe(xc).env(OMP_STACKSIZE='128M')
440  > log,logger=logger)
441  logging.info("hwrf_getsst: err = %s" %(retcode))
442  if retcode == 0 and os.path.exists(jn2r(DEST,"fort.74")):
443  deliver_file(jn2r(DEST,"fort.74"),jn2r(DEST,"sst.gfs.dat"),False,logger=logger)
444  deliver_file(jn2r(DEST,"fort.77"),jn2r(DEST,"mask.gfs.dat"),False,logger=logger)
445  logger.info("GFS SST extracted: {0}".format(retcode))
446  else:
447  msg="hwrf_getsst Failed: NO GFS SST extracted %s"%(retcode)
448  logger.warning(msg)
449  raise POMSSTError(msg)
450  else:
451  msg="GFS Spectral Files NOT Found in %s:" %(DEST)
452  logger.warning(msg)
453  raise POMInputError(msg)
454  deliver_file(jn2r(DEST,"sst.gfs.dat"),jn2r(DEST,"fort.21"),False,logger=logger)
455  deliver_file(jn2r(DEST,"mask.gfs.dat"),jn2r(DEST,"fort.22"),False,logger=logger)
456  xc = self.conf.getexe("hwrf_ocean_pomprep_"+self.ODATA[0:2])
457  inp = jn2r(DEST,"input")
458  log = jn2r(DEST,"ocean_pomprep.out")
459  if self.sync_frequently: runsync()
460  retcode = run((exe(xc) < inp) >log,logger=logger)
461  if retcode == 0 and os.path.exists(jn2r(DEST,self.STORMNAME+".grid.nc")):
462  logging.info("ocean_pomprep: Success %s:" %(self.ODATA))
463  return True
464  else:
465  msg="ocean_pomprep: Failed %s:" %(self.ODATA)
466  logger.warning(msg)
467  raise POMInitFailed(msg)
468 
470  """!Runs a later phase of the ocean init to add additional
471  features such as cold wakes."""
472  def __init__(self,*args,**kargs):
473  """!phase constructor
474  @param args,kargs All arguments are passed to Oceanini.__init__()"""
475  super(phase,self).__init__(*args,**kargs)
476  def getinp(self, DEST, logger=None):
477  """!Links all input data.
478  @param DEST Directory in which to link files.
479  @param logger a logging.Logger for log messages"""
480  if logger is None: logger=logging.getLogger('pom')
481  try:
482  (y4,mm,mm1,dd,hh) = ysplitter(self.STARTDATE)
483  SRC = jn2r(self.CSTREAM, self.ODIR)
484  make_symlink(jn2r(SRC,self.STORMNAME+".grid.nc"),
485  jn2r(DEST,self.STORMNAME+".grid.nc"),True,logger=logger)
486  make_symlink(jn2r(SRC,self.STORMNAME+".ts_initial.nc"),
487  jn2r(DEST,self.STORMNAME+".ts_initial.nc"),True,logger=logger)
488  make_symlink(jn2r(SRC,self.STORMNAME+".ts_clim.nc"),
489  jn2r(DEST,self.STORMNAME+".ts_clim.nc"),True,logger=logger)
490  make_symlink(jn2r(SRC,self.STORMNAME+".uv_initial.nc"),
491  jn2r(DEST,self.STORMNAME+".uv_initial.nc"),True,logger=logger)
492  make_symlink(jn2r(SRC,self.STORMNAME+".el_initial.nc"),
493  jn2r(DEST,self.STORMNAME+".el_initial.nc"),True,logger=logger)
494  except Exception as e:
495  msg='Input data does not exist: %s'%(str(e),)
496  logger.warning(msg,exc_info=True)
497  raise POMInputError(msg)
498 
499  def setrun(self, DEST,logger=None):
500  """!Runs the phase initialization
501  @param DEST The directory in which to run.
502  @param logger A logging.Logger for log messages."""
503  with NamedDir(DEST):
504  if logger is None: logger=logging.getLogger('pom')
505  (y4,mm,mm1,dd,hh) = ysplitter(self.STARTDATE)
506  if os.path.exists(jn2r(DEST,self.STORMNAME+".grid.nc")) and \
507  os.path.exists(jn2r(DEST,"pom.nml")):
508  exe = self.conf.getexe("hwrf_ocean_init")
509  log = jn2r(DEST,"ocean_init.out")
510  if self.sync_frequently: runsync()
511  retcode=run(mpirun(mpi(exe)*9) >= log ,logger=logger)
512  logger.info("hwrf_ocean_init: err = %s" %( retcode))
513  if retcode == 0 and os.path.exists(jn2r(DEST,"restart.0001.nc")):
514  logger.info("Phase completed HERE: %s" %(DEST))
515  return True
516  else:
517  msg="Phase FAILED HERE: %s" %(DEST)
518  logger.error(msg)
519  return False
520  else:
521  msg="Input Files NOT exists %s:" %(DEST)
522  logger.warning(msg)
523  raise POMInputError(msg)
524  def sendout(self, SRC, infile, DEST, outfile,logger=None):
525  """!Delivers an output file using produtil.fileop.deliver_file()
526  @param SRC Directory with the input file.
527  @param infile Basename of the input file inside of SRC
528  @param DEST Destination directory of the file
529  @param outfile Name of the file in the DEST directory.
530  @param logger A logging.Logger for log messages."""
531  if logger is None: logger=logging.getLogger('pom')
532  if os.path.exists(jn2r(SRC, infile)):
533  deliver_file(jn2r(SRC,infile),jn2r(DEST,outfile),False,logger=logger)
534  return True
535  else:
536  msg="Restart file %s does NOT exist:" %(infile)
537  logger.warning(msg)
538  raise POMInitFailed(msg)
539 
540 class pget:
541  """!Utility class for obtaining input data."""
542  def getinp(self, this, DEST,logger=None):
543  """!Asks "this" to deliver its input by calling this.getinp(...)
544  @param this an Oceanini object
545  @param DEST directory in which to make links
546  @param logger a logging.Logger for messages"""
547  if logger is None: logger=logging.getLogger('pom')
548  logger.info('get input this=%s DEST=%s'%(repr(this),repr(DEST)))
549  this.getinp(DEST,logger=logger)
550 class prun:
551  """!Utility class for executing ocean initialization setrun functions."""
552  def setrun(self, this, DEST,logger=None):
553  """!Runs this.setrun(...) to run the ocean initialization
554  @param this an Oceanini object
555  @param DEST the directory in which to run
556  @param logger a logging.Logger for log messages"""
557  if logger is None: logger=logging.getLogger('pom')
558  return this.setrun(DEST, logger=logger)
559 class psend:
560  """!Utility class for delivering Oceanini output."""
561  def sendout(self, this, SRC, infile, DEST, outfile, logger=None):
562  """!Calls this.sendout(...)
563  @param this An Oceanini object.
564  @param SRC the directory from which to copy
565  @param infile the input file basename of the file in SRC
566  @param DEST the destination directory
567  @param outfile the name of the output file in DEST
568  @param logger a logging.Logger for log messages"""
569  if logger is None: logger=logging.getLogger('pom')
570  return this.sendout(SRC, infile, DEST, outfile, logger=logger)
571 
STORMID
Three character storm number and basin, upper-case (12L)
Definition: init.py:54
Change directory, handle temporary directories.
Definition: cd.py:1
This module provides a set of utility functions to do filesystem operations.
Definition: fileop.py:1
Runs the na (NCODA) initialization of POM.
Definition: init.py:386
def __init__(self, args, kargs)
na Constructor
Definition: init.py:388
Imitates the shell "ls -l" program.
Definition: listing.py:9
STORMNAME
Upper-case storm name for filenames (KATRINA)
Definition: init.py:53
def setpath
Creates the ocean run path, whose subdirectory is SUBDIR.
Definition: init.py:147
def setrun
Runs this.setrun(...) to run the ocean initialization.
Definition: init.py:552
PARMhwrf
Directory with HWRF parameter files.
Definition: init.py:57
EXEChwrf
Directory with HWRF executables.
Definition: init.py:56
def setrun
Runs the g3 ocean initialization.
Definition: init.py:340
GFSDIR
Directory with input files from GFS.
Definition: init.py:59
Runs the G3 initialization for POM.
Definition: init.py:312
sync_frequently
Definition: init.py:64
Utility class for delivering Oceanini output.
Definition: init.py:559
def __init__(self, args, kargs)
phase constructor
Definition: init.py:472
Parent class of POM initialization classes.
Definition: init.py:96
def __init__(self, ODIR, DOMAIN, ODATA, SSTASIM, STORMNAME, STORMID, STARTDATE, EXEChwrf, PARMhwrf, FIXhwrf, LCDIR, GFSDIR, CSTREAM, COMIN, sync_frequently=False, kwargs)
Oceanini constructor.
Definition: init.py:100
def getrlimit
Gets the current resource limits.
Definition: rusage.py:132
def getinp
Asks "this" to deliver its input by calling this.getinp(...)
Definition: init.py:542
def getinp
Obtains all input files, linking or copying them.
Definition: init.py:392
def setrun
Runs the phase initialization.
Definition: init.py:499
def __init__
Hwrf constructor.
Definition: init.py:39
ODIR
Ocean output directory in CSTREAM.
Definition: init.py:125
Raised when the init has trouble extracting SSTs.
Definition: exceptions.py:22
SSTASIM
SST ASIM flag, True or False.
Definition: init.py:128
A shell-like syntax for running serial, MPI and OpenMP programs.
Definition: run.py:1
def setrun
Runs the FBTR initialization.
Definition: init.py:216
def getinp
Links or copies input files.
Definition: init.py:169
This subclass of TempDir takes a directory name, instead of generating one automatically.
Definition: cd.py:228
This module allows querying resource usage and limits, as well as setting resource limits...
Definition: rusage.py:1
def setrun
Runs the na initialization.
Definition: init.py:423
ODATA
Type of ocean data.
Definition: init.py:127
def getinp
Links all input data.
Definition: init.py:476
def __init__(self, args, kargs)
g3 constructor
Definition: init.py:314
FIXhwrf
Directory with HWRF fixed files.
Definition: init.py:60
COMIN
HWRF final output directory.
Definition: init.py:63
Runs a later phase of the ocean init to add additional features such as cold wakes.
Definition: init.py:469
Raised when a required input or input directory did not exist.
Definition: exceptions.py:16
Utility class for obtaining input data.
Definition: init.py:540
conf
A ConfigParser-like object to use for configuration information.
Definition: init.py:129
rusage
Alias for produtil.rusage.RUsage.
Definition: rusage.py:288
def sendout
Calls this.sendout(...)
Definition: init.py:561
STARTDATE
Simulation analysis time as a string, YYYYMMDDHH (2005082918)
Definition: init.py:55
def sendout
Delivers an output file using produtil.fileop.deliver_file()
Definition: init.py:524
Abstract base class that stores data relating to the HWRF workflow in which the POM initialization re...
Definition: init.py:34
LCDIR
Directory with loop current files.
Definition: init.py:58
CSTREAM
Directory to place files for the POM forecast to read.
Definition: init.py:62
def __init__(self, args, kargs)
fbtr constructor
Definition: init.py:165
Utility class for executing ocean initialization setrun functions.
Definition: init.py:550
def setrlimit(logger=None, ignore=False, hard=False, kwargs)
Sets resource limits.
Definition: rusage.py:60
Raised when a POM initialization program unexpectedly fails.
Definition: exceptions.py:19
Runs the FBTR (feature-based) initialization of the MPIPOMTC.
Definition: init.py:163
DOMAIN
Ocean domain.
Definition: init.py:126
def getinp
Links all required input files.
Definition: init.py:318
Raised when the POM prep fails.
Definition: exceptions.py:25