1 """!Post-processes GSI input and output for data assimilation diagnostics."""
5 __all__ = [
"GSIPost",
'F_ORG',
'F_GES',
'F_ANL',
'F_ALL']
7 import os, glob, shutil
11 from produtil.run import run, checkrun, alias, mpi, mpirun, exe, bigexe
14 from hwrf.post import EGRIB1Product, check_post, link_post_fix
30 F_ALL=F_ORG|F_GES|F_ANL
33 """!Post-processes GSI inputs and outputs.
35 Runs the hwrf_post on GSI inputs and outputs from one or more of three stages.
36 * original data (F_ORG) - the original, downscaled, parent model data
37 * first guess (F_GES) - the original data, with the vortex relocated
38 * analysis (F_ANL) - the final data input to the forecast
39 This class is compatible with the hwrf.regrib and hwrf.gribtask,
40 and can be used in place of an hwrf.post.PostManyWRF.
42 def __init__(self,dstore,conf,section,**kwargs):
43 """!Constructor for GSIPost
44 @param dstore the produtil.datastore.Datastore database to use
45 @param conf the hwrf.config.HWRFConfig configuration information
46 @param section the section to use in conf
47 @param kwargs keyword arguments passed to the superclass constructor"""
48 super(GSIPost,self).
__init__(dstore,conf,section,**kwargs)
59 def add_case(self,domain,wrfout,org=None,ges=None,anl=None):
60 """!Adds another case to the list of those to post-process
62 @param domain a WRFDomain to be processed
63 @param wrfout a wrfout file for internal use. It will be copied
64 and its fields will e replaced with the ges and/or analysis
66 @param org Optional: original down-scaled parent domain data
67 @param ges Optional: a first guess wrfinput or restart file, generally after
69 @param anl Optional: an analysis (GSI output) wrfinput or restart file
70 @note At least one of org, ges or anl must be given."""
71 assert(
not (org
is None and ges
is None and anl
is None))
72 assert(wrfout
is not None)
73 assert(domain
is not None)
75 self._domains.append(domain)
83 prodname=domain.name+
'_org_'+org.prodname)
89 prodname=domain.name+
'_ges_'+ges.prodname)
95 prodname=domain.name+
'_anl_'+anl.prodname)
98 """!Executes the GSI post for all cases on all domains."""
102 logger.info(
'%s: process this domain'%(str(domain),))
105 logger.info(
'%s: process org'%(str(domain),))
109 logger.info(
'%s: has no org data'%(str(domain),))
112 logger.info(
'%s: process ges'%(str(domain),))
116 logger.info(
'%s: has no ges data'%(str(domain),))
119 logger.info(
'%s: process anl'%(str(domain),))
123 logger.info(
'%s: has no anl data'%(str(domain),))
124 logger.info(
'Done processing domains.')
126 def _process(self,inprod,domain,why,wrfout,outprod):
127 """!Internal function that implements most of run()
129 Do not call directly. This is the implementation of
130 self.run: it runs the post for one case, on one domain."""
131 assert(inprod
is not None)
132 assert(outprod
is not None)
133 assert(wrfout
is not None)
134 assert(domain
is not None)
137 assert(wrfout.location)
138 wrfthere=wrfout.location
142 '%s: is empty or nonexistent'%(wrfthere,))
143 if not inprod.location:
144 logger.info(
'%s: not available (location unknown)'%(
146 elif not inprod.available:
147 logger.info(
'%s (%s): not available according to database'%(
148 inprod.did, inprod.location))
149 shortname=domain.name+
'_'+why+
'_'+inprod.prodname
150 workdir=os.path.join(self.
workdir,shortname)
151 if os.path.exists(workdir):
152 logger.info(
'%s: exists; will delete'%(workdir,))
153 shutil.rmtree(workdir)
155 diffwrf=alias(bigexe(self.
getexe(
'hwrf_3dvar')))
156 post=alias(mpi(self.
getexe(
'post')))
159 deliver_file(wrfthere,
'postinput',keep=
True)
160 make_symlink(inprod.location,
'ghost',force=
True)
161 cmd=diffwrf[
'storm_relocate',
'ghost',
'flnm3',
'new_ght']
162 checkrun(cmd >=
'storm_relocate.log',logger=logger)
163 cmd=diffwrf[
'3dvar_update',
'postinput',
'new_ght']
164 checkrun(cmd >=
'3dvar_update.log',logger=logger)
167 for filename
in glob.glob(
'fort.*'):
171 datestamp=self.conf.cycle.strftime(
'%Y-%m-%d_%H:%M:%S')
172 with open(
'itag',
'wt')
as itag:
173 itag.write(
"""postinput
178 cmd=mpirun(post,allranks=
True) >=
'vpost.log'
179 needcrtm=self.
confbool(
'needcrtm',
False)
180 logger.info(
'link post fix files')
181 link_post_fix(self.
getdir(
'FIXhwrf'),needcrtm,logger=logger)
183 logger.info(
'%s: use this control file for gsi post'%(fort14,))
186 logger.info(
'Run post, log to vpost.log.')
187 ret=
run(cmd,logger=logger)
191 (ok,cenla,cenlo,filename)=check_post(ret,shortname,logger)
195 toloc=os.path.join(self.
outdir,shortname)
196 outprod.deliver(toloc,{
'CENLA':cenla,
'CENLO':cenlo,
197 'fromloc':filename},logger=logger)
200 def products(self,domains=None,domain=None,which_step=F_ALL,**kwargs):
201 """!Iterates over EGRIB1Product objects produced by this task.
203 @param domains a list of WRFDomain objects. Only these will be iterated.
204 @param domain a single WRFDomain; only its products will be iterated
205 @param which_step which steps are of interest:
206 * F_ORG - original parent model data
207 * F_GES - first guess (vortex-relocated parent model data)
208 * F_ANL - analysis, the final input to the forecast
209 * any integer or of the above
210 * F_ALL - all products, the default
211 @param kwargs ignored"""
212 if domains
is None and domain
is not None:
214 elif domains
is None:
Change directory, handle temporary directories.
This module provides a set of utility functions to do filesystem operations.
def add_case
Adds another case to the list of those to post-process.
def getexe
Alias for hwrf.config.HWRFConfig.get() for the "exe" section.
taskname
Read-only property: the name of this task.
The base class of tasks run by the HWRF system.
Post-processes GSI inputs and outputs.
Raised upon errors that would cause a retry, in the PostOneWRF.run when passed the raiseall=True argu...
def remove_file
Deletes the specified file.
dstore
Read-only property, an alias for getdatastore(), the Datastore in which this Datum resides...
def confbool
Alias for self.conf.getbool for section self.section.
Base class of tasks run by HWRF.
A shell-like syntax for running serial, MPI and OpenMP programs.
def getdir
Alias for hwrf.config.HWRFConfig.get() for the "dir" section.
outdir
The directory in which this task should deliver its final output.
def isnonempty(filename)
Returns True if the filename refers to an existent file that is non-empty, and False otherwise...
def products(self, domains=None, domain=None, which_step=F_ALL, kwargs)
Iterates over EGRIB1Product objects produced by this task.
This subclass of TempDir takes a directory name, instead of generating one automatically.
Runs the GSI data assimilation on the HWRF system.
def __init__(self, dstore, conf, section, kwargs)
Constructor for GSIPost.
workdir
The directory in which this task should be run.
def scrub(self)
Should temporary files be deleted as soon as they are not needed?
def log
Obtain a logging domain.
def run(self)
Executes the GSI post for all cases on all domains.
Represents an E grid WRF-NMM GRIB1 file, and stores two metadata values: CENLA and CENLO which contai...
Raised when the post's input file is not available and raiseall=True in PostOneWRF.run.
Runs the Unified Post Processor on outputs from the WRF-NMM, producing E grid GRIB files as EGRIB1Pro...
Exceptions raised by the hwrf package.
def confstr
Alias for self.conf.getstr for section self.section.
def _process(self, inprod, domain, why, wrfout, outprod)
Internal function that implements most of run()
def make_symlink
Creates a symbolic link "target" that points to "source".