U  g@sdZddlZddlZddlZddlZddlZddlZddlTddlTddl TddddgZ ddZ Gd ddZ Gd dde ZGd dde ZdS) aS!low-level wrf implementation, underlying hwrf.wrf This module contains low-level classes that underlie the implementation of the hwrf.wrf module. It also contains the WRFOutput class, which is used to describe a WRF output file, and the parse_wrf_outname, which turns WRF-style filename formats (wrfout_d_) into filenames.N)*parse_wrf_outname WRFOutput WRFDomainBase WRFDomainscCst|tst|}td|r6tddt|f|}td|rZtdt|d|}|r|ddtdd|dd }|S) af!generates wrf filenames from templates like construct_filename Takes a wrf outname, a grid_id and a date and produces the final string outname. The mandatory boolean argument nocolons is set to the namelist &time_control nocolons value. This mimics the construct_filename family of functions in the WRF source code. @param outname the filename format as passed to WRF @param grid_id the integer grid ID @param date the date (anything accepted by hwrf.numerics.to_datetime) @param nocolons if True, colons in the date are converted to underscores @return the string filenamez (?i)z%02dz (?i)z%Y-%m-%d_%H:%M:%Sr:_N) isinstancestrAssertionErrorresearchsubint to_datetimestrftime)outnamegrid_iddatenocolonsoutr9/lfs/h1/ops/prod/packages/hmon.v3.2.7/ush/hwrf/wrfbase.pyrs   "c@sjeZdZdZdddZddZddZd d Zd d Zd dZ ddZ ddZ ddZ ddZ ddZdS)ra!A class that provides information about WRF output and input files. This class is used throughout the HWRF scripts to identify WRF input and output filenames. The underlying implementation knows how to deal with the odd rounding issues involved in predicting WRF filenames based on timesteps, including fractional timesteps. This class also tracks the analysis time, forecast time, stream and full path to the file.NcCst|tstt|tstt||_|dkr@tdkr@tdnL|dk rbt||_|j|j|_n*|dk rt ||_|j|j|_nt d||_ t||_ |dkst|t st||_dS)az!Creates a WRFOutput object that knows the path to its file (self.path()), the output time as a datetime (self.validtime()), the simulation start time as a datetime (self.anltime()), the output forecast second as a timedelta (self.fcstdelta()), the name of the WRF stream (self.stream()), and the WRF domain object (self.domain()). Do not modify the domain object or many things may break. You must specify exactly one of validtime or fcstdelta. If you specify both, OverspecifiedOutputTime will be raised. If you specify neither, NoOutputTime will be raised.Nz=In WRFOutput.__init__, both validtime and fcstdelta were NonezbIn WRFOutput.__init__, both validtime and fcstdelta were specified. You must specify exactly one.)r r r r_anltimeZdelta NoOutputTime _validtime _fcstdelta to_timedeltaOverspecifiedOutputTime_path_streamr_domain)selfanltimestreamdomainpath validtime fcstdeltarrr__init__8s$      zWRFOutput.__init__cCs2t|jt|jAt|jAt|jAt|jAS)zU!provides an integer hash value so this object can be used as a key in a dict)hashr"r!r rrr#rrr__hash__Ys zWRFOutput.__hash__cCsbt|tstS|j|jksdS|j|jks.dS|j|jks>dS|j|jksNdS|j|jks^dSdS)z!does this WRFOutput equal that one? Returns True if the other WRFOutput object is identical to this one, and False if it is not. For anything other than a WRFOutput, returns NotImplemented. @param other another objectFT)r rNotImplementedr"r!r rrr#otherrrr__eq__^s      zWRFOutput.__eq__cCs&dt|t|t|fS)z,!a string representation of this output filez%s output stream=%s path=%s)reprr&r r%r'r,rrr__str__ms zWRFOutput.__str__cCs:dt|t|t|t|t|fS)z5!a detailed string representation of this output filez#WRFOutput(%s,%s,%s,%s,validtime=%s))r2r$r%r&r'r(r,rrr__repr__qs  zWRFOutput.__repr__cCs|jS)z*!Returns the full path to the output file.)r r,rrrr'vszWRFOutput.pathcCs|jS)z/!Returns the lower-case name of the WRF stream.)r!r,rrrr%yszWRFOutput.streamcCs|jS)z!the hwrf.wrf.WRFDomain object Returns the domain object for this output file's WRF domain. Do not modify the returned object or many things will break.)r"r,rrrr&|szWRFOutput.domaincCs|jS)z!the difference between the analysis and forecast time. Returns the time difference between the valid (output) time and the analysis (simulation start) time.)rr,rrrr)szWRFOutput.fcstdeltacCs|jS)z0!Returns the output time as a datetime.datetime.)rr,rrrr(szWRFOutput.validtimecCs|jS)z2!Returns the analysis time as a datetime.datetime.)rr,rrrr$szWRFOutput.anltime)NN)__name__ __module__ __qualname____doc__r*r-r1r3r4r'r%r&r)r(r$rrrrr/s !c@seZdZdZd#ddZddZddZd d Zd d Zd dZ ddZ ddZ ddZ ddZ ddZddZddZddZdd Zd!d"ZdS)$rz!superclass of WRFDomain This is the superclass of WRFDomain and it should not be instantiated directly. It exists to eliminate a cyclic dependency in the module imports. NcCsd|_d|_d|_d|_d|_d|_i|_|dk r|j|_t |j |_ |j|j|j|j|j|jf\|_|_|_|_|_|_nt |||_t ||_ dS)aL!Creates a new WRFDomainBase. conf - an HWRFConfig with configuration information section - the section to read for information about this domain name - the name of the domain. Default: section name. copy - do not specify this. It is used by self.copy() to copy a WRFDomainBase.NT) nestlevelparentr_start_end_dt_outputnlcopyr name Conf2Namelist)r#confsectionrAr@rrrr*s$   zWRFDomainBase.__init__cCs t|jS)z&!an integer representation for hashing)r+rAr,rrrr-szWRFDomainBase.__hash__cCsdt|jfS)z!!a detailed string representationz)r rAr,rrrr4szWRFDomainBase.__repr__cCst|j|jS)z!integer comparison for sorting, like the cmp function. Sorts by domain's string name. @param other the domain to compare against)cmprAr/rrr__cmp__szWRFDomainBase.__cmp__cCst|S)z!synonym for __repr__())r2r,rrrr3szWRFDomainBase.__str__cCs|jdk r|jjS|jSdS)z!returns the analysis time Returns the parent _start time if there is a parent, otherwise returns this domain's analysis time.N)r:r;r,rrr get_anl_times zWRFDomainBase.get_anl_timecCs tddS)zY!Raises NotImplementedError. The WRFDomain overrides this to return the grid id.z,WRFDomainBase does not implement get_grid_idN)NotImplementedErrorr,rrr get_grid_idszWRFDomainBase.get_grid_idcCs|jj|jd|_dS)z!removes forbidden namelist entries Removes all namelist entries that the conf files are forbidden from specifying. Generally this is anything related to domain start, end, size, I/O or timesteps.) var_subsetN)r?r@ _nl_subsetterr,rrrremove_forbiddenszWRFDomainBase.remove_forbiddencCsdS)a>!returns True This returns True. It is intended to be overridden in subclasses to subset the namelist values provided by the configuration files. It should return True to keep the variable, or False to reject it. @param s the namelist name @param v the variable nameTr)r#svrrrrKs zWRFDomainBase._nl_subsettercCstdd|dS)z!Returns a copy of this object. The copy has its own data structures, so modifying the copy will not modify the original.N)r@)rr,rrrr@szWRFDomainBase.copycCsnt|}t|}t|}|jdk s,|jdk r4td|jdksH|jdkrPtd||krdtd|||||fS)a!checks if a timespan is valid Analyzes a potential WRF simulation start, end and timestep to make sure it matches assumptions made within WRF, and within the hwrf package. 1. There must be no timezone (UTC only) 2. The start time must not contain microseconds. 3. The end time must be at or after the start time @param start the start time of the simulation @param end the end time of the simulation @param timestep the simulation timestep or output frequency @returns a tuple (ts,te,dt) where: - ts = the start time as a datetime.datetime - te = the end time as a datetime.datetime - dt = the timestep as a fractions.FractionNz3WRF start and end times must not contain timezones.rz5WRF start and end times must lie exactly on a second.z4Invalid domain start/end times: end is before start.)r to_fractiontzinfoTimezoneProvided microsecondPrecisionTooHighEndBeforeStartr#startendtimesteptstedtrrr_validate_timespans$z WRFDomainBase._validate_timespancCs*||||\}}}||_||_||_dS)a!sets the start and end times of this domain, and the domain timestep Validates the provided inputs through _validate_timespan(). If accepted, sets the start and end times, and the timestep. @param start the start time of the simulation @param end the end time of the simulation @param timestep the simulation timestep or output frequencyN)r\r;r<r=rUrrr set_timings zWRFDomainBase.set_timingcCsdS)z!initializes grid ID and non-nesting-related variables Initializes this domain's variables that are unrelated to nesting. @param grid_id the grid id in WRF (1=moad, 2=...)Nrr#rrrr init_domain(szWRFDomainBase.init_domaincCs8||||_|_|_|||||dd|_dS)a!initializes this domain as the outermost domain Initializes this domain's variables so it knows to act as the Mother Of All Domains (MOAD) - the outermost domain. The grid ID is set to 1 and the parent to None. @param simstart simulation start time @param simend simulation end time @param simdt simulation outer domain timestep @param eta_levels NMM eta vertical levels as set in the eta_levels namelist value.N) _simstart_simend_simdtr]r_r:)r#simstartsimendsimdt eta_levelsrrr init_as_moad.s  zWRFDomainBase.init_as_moadcCsn||||_|j|j|j|_|_|_t|j||jsRtd|j||j f| |j|j|jddS)a.!initializes this domain as a nest Initializes this domain's variables to make it a nest within the given parent WRFDomain @param parent the parent of this nest @param grid_id the grid ID @param start the nest's start time @param end the nest's end timez9Start time %s for domain %d is not at parent %d timestep.N) r_r:rarbrcis_at_timestepr;r=StartNotAtParentTimesteprr])r#r:rrVrWrrr init_as_nest=s  zWRFDomainBase.init_as_nestcCs |jS)z6!creates the wrf namelist as a string, and returns it.)r? make_namelistr,rrrrmOszWRFDomainBase.make_namelist)NN)r5r6r7r8r*r-r4rFr3rGrIrLrKr@r\r]r_rhrlrmrrrrrs" 5   c@seZdZdZddZdd d Zd dZddZ ddZ e ddZ ddZ ddZddZe eeddZddZddZd d!Zd?d#d$Zd%d&Zd'd(Zd)dZd@d*d+Zd,d-Zd.d/Zd0d1ZdAd2d3Zd4d5Zd6d7Zd8d9Zd:d;ZdS)Bra!abstract base class of WRFSimulation This is the abstract base class of WRFSimulation. You should not instantiate it directly. Its purpose is to combine information about multiple WRFDomainBase objects (or WRFDomain objects) to make a single namelist. It also has the ability to make aggregate changes to those objects, or obtain aggregate information about them. This class exists only to avoid cyclic dependencies.c Cstdddddd|dS)z! duplicates this object Returns a deep copy of this object, providing new data structures so modifying the copy will not modify the original. The underlying WRFDomain objects and their data structures are also duplicated.N)dup)rr,rrrr@^szWRFDomains.copyNcCs|dk r|j|_|j|j|j|jf\|_|_|_|_|j|_|j|_t|_ t|_ t|_ t|_ |j D]4\}} |j |} | |j |<| |j |<||j | <qr|j D]\} } | |j | <qdSt|t||_|jdd} t||_t||_|dkr|jd}t||_|jdd}|dkr.intifyroi_parent_startz@%s: invalid value for start. Only nests can have start=centerede_weparent_grid_ratioriz:%s: invalid value for start. Must be %s, %s or an integerj_parent_starte_sn) rr?r|r r nl_setr:InvalidDomainStartrA)r#ZivalueZjvalueZfillthisZ centerthisrr&gotZdxpZdxdZraticenZdypZdydZjcenrrrfill_auto_startssb       zWRFDomains.fill_auto_startscCst|dd}t|}||ks(td}|D]}||dkrL||||<t||dddd||<|jdd}t|ts|jdd|||jdd}t|ts|jdd|||d7}||kr0qq0|S)a0For domains whose i_parent_start or j_parent_start are set automatically, this fills those domains starts with the provided values, for the fakestorm of a multistorm run. ivalue = a list of i start values for N storms jvalue = a list of j start values for N stormsr`rrNrorr)rmaxdomlenr r?r|r r)r#ZivaluesZjvaluesZnumberof_outernestsZnumberof_istartvaluesZij_indexr&rrrrfill_auto_starts_multistorms$     z&WRFDomains.fill_auto_starts_multistormcCs|jS)z:!Returns the simulation start time as a datetime.datetime.)rar,rrrrd(szWRFDomains.simstartcCs|jS)z8!Returns the simulation end time as a datetime.datetime.)rbr,rrrre+szWRFDomains.simendcCs|jS)z:!Returns the simulation timestep as a datetime.time_delta.)rrr,rrrrX.szWRFDomains.timestepcCsd|jkr|S|jS)am!Should colons be omitted from filenames? Should colons be omitted from filenames? This is determined from the configuration files, if it is specified there, or from the I/O forms selected (some don't support colons). The return value may be cached. To ensure the value is recomputed instead, you can call get_nocolons._nocolons_cache)__dict__r~rr,rrrr2s zWRFDomains.nocolonscCs|jdd}|sZ|jdD]:\}}|ddkrt|d}|dksP|dkrd}qZq|s|jD]:\}}|ddkrht|d}|dks|dkrhd}qqh|jdd|||jd <|S) a1!Force a recheck of whether colons be omitted from filenames. Should colons be omitted from filenames? This is determined from the configuration files, if it is specified there, or from the I/O forms selected (some don't support colons). This method guesses the nocolons setting from the WRF/WPS/Real namelist. The result of this calculation is never cached: all namelist options are re-scanned and the flag is recomputed each time. To get the cached value, use the nocolons property instead.rT time_controlrprdr` r)r?r}nl_eachfindr trait_eachrr)r#rvarvaluerrrrr~?s$    zWRFDomains.get_nocolonscCs|jS)z!Gets the default io_form.rsr,rrr get_io_form\szWRFDomains.get_io_formcCs ||_dS)z!Sets the default io_form.Nr)r#irrr set_io_form_szWRFDomains.set_io_formz!The default I/O form for this WRFcCs(|dkr d}|jd|t|j}|S)z!Returns the io_form for the specified stream. @return the io_form for the given stream. If none is specified, the default io_form is returned. @param stream the stream, a lower-case stringhistoryoutput io_form_%s)r?r}rrs)r#r%rrrr io_form_foriszWRFDomains.io_form_forcCs|j|jdS)z!!returns the MOAD as a WRFDomain.r`)rwryr,rrrget_moadrszWRFDomains.get_moadcCs|j|j|jdS)z+!returns the last domain added to this WRF.r`)rwryrtr,rrrget_lastuszWRFDomains.get_lastrc Csd|_|dkr||}n ||||dkrJ|dkr:d}|jddd|dk r^||||dk rrt||j}|} |D]L} | | _ |dk r|| kr| |s| |q~| j ||||||||jdq~|dkr| |S) a!request output from one or more streams Requests that one or all WRF domains output the specified stream. The stream should be "history" or "auxhistN" for an integer N>0. Optional "domain" specifies the domain that should output this stream, otherwise all domains will output it. @param stream the stream: "history" or "auxhistN" for an integer N>0 @param domain the domain (optional) @param io_form WRF IO form. Simply calls self.set_io_form(stream,io_form) @param start output start time (anything accepted by to_datetime) Default: simulation start time. @param end output end time (anything accepted by to_datetime. Default: simulation end time. @param step output interval, sent into to_out_interval(). Default: trait stream+"_interval" or 6hrs @param frames_per_outfile how many output times per output file @param outname output name or array of output names (one per domain). Can only specify for all domains, not for only one. Default: leave unspecified, and let WRF use its defaults. NOTE: You cannot add any more domains after calling this routine.TNinputoutzwrfinputout_drZ write_input)rdrestart)rurrr?r set_outnameto_datetime_relrar~r has_output no_output add_outputmake_restart_time_scalar) r#r%r&rprVrWstepframes_per_outfilerrZmydomrrrrxs@     zWRFDomains.add_outputcCsR|D]H}dD]>}|jd|r |jd|}|jd||jd||q qdS)a!Ensure that only one restart frequency is set Unlike most output frequencies, the restart frequency has to be the same for all domains, and is specified as a scalar value, not an array. This function removes per-domain restart frequencies, moving the restart frequency up to the domain-independent namelist values. The frequency used is the one for the last domain listed by self.__iter__.) Z restart_beginZrestart_begin_sZrestart_begin_mZrestart_begin_hZrestart_begin_drestart_intervalZrestart_interval_sZrestart_interval_mZrestart_interval_hZrestart_interval_drN)r?nl_haver|nl_delr)r#r&nrNrrrrs z#WRFDomains.make_restart_time_scalarcCs.|dkr d}|jddt|ft|dS)a4!Set the wrf output filename for a stream Sets the WRF output filename format for the specified stream to the given name. The name should contain @ and @ if appropriate. @param stream the stream to change @param outname the new output filename formatrinputrz %s_outnameN)r?rr )r#r%rrrrrs zWRFDomains.set_outnamecCs>|dkr d}|jdd|t||jd|t|dS)z!Sets the io_form for the specified stream. Set the io_form for the specified stream. The "history" and "output" streams are synonyms. @param stream the stream @param io_form the io_formrrrrN)r?rr trait_set)r#r%rprrrrscCsD||d}|dkrd}n$|dks,|dkr2d}ntdtj|S)z!Return the suggested output suffix for filenames Gets the suggested output suffix for the specified stream. Returns "int" for 1 and "nc" for 2 or 11. @param stream the stream. Default: "history" rr`rrrrzUnsupported IO form %d)r NameErrorZself_rp)r#r%rZiosrrr get_io_suffixszWRFDomains.get_io_suffixcCsbt|tr|jt|jSt|tr2|jt|St|trL|j|j|Stdt|fdS)aR!return the specified domain Returns a domain with the given name or grid_id. This method may raise IndexError or KeyError if the domain does not exist. If passed a WRFDomainBase, then this simulation's copy of the domain with the same name is returned. @returns the specified domain. @param what If this is a string or WRFDomain, then the domain with that name is returned. If "what" is an integer, the domain with that ID is returned. If it is a WRFDomainBase, then the name stored in that object is used instead.zfIn WRF.get, the key must be a basestring, WRFDomain or an int (or subclass thereof). You provided %s.N) r rrwr rArryKeyErrorr2r#whatrrrgets   zWRFDomains.getcCs |jdS)zP!returns the highest domain number, which is also the number of domains.r`)rtr,rrrrszWRFDomains.maxdomcCs|j S)z!Can we still add domains to this simulation? Returns true if this WRF can accept new domains. Certain operations, such as requesting output files, end the ability to add domains.)Z _domans_doner,rrrcan_addszWRFDomains.can_addc Cs|jrtd|j}t|j}|dkr.|n||}t|j}|}||jkrdt d|f|| }|j d|| |_|||||j|j||j|<||j|<||j|<||j|<|d|_|j ddt||S)a!Add a WRFDomain to this simulation. Adds the child WRFDomain to this WRF, with the specified parent. If the parent is not specified, the last added domain is used as the parent. If specified, the parent may be anything accepted by self.get. The return value is the new WRFDomain. @param child the domain to add @param parent the WRFDomain of the parent @return a new WRFDomain object with the same name as child zAYou cannot add any domains after setting up I/O for a WRF object.Nz%s: domain already existsidr`romax_dom)ru DomainsDonertr rArrrrw DomainExistsr@r?rr~rrLrlrarbrxryrzrrr) r#Zchildr:ZnewidnewnameZ newparentZ parentnamerminerrradds.         zWRFDomains.addcCs ||S)z!Same as self.get(what) Calls self.get(what) @param what the grid_id, domain name or WRFDomain to search for. @return the WRFDomain)rrrrr __getitem__2szWRFDomains.__getitem__cCs|S)z!Same as self.maxdom().)rr,rrr__len__9szWRFDomains.__len__cCs*z||WdStk r$YnXdS)aC!does this simulation contain this domain? Returns True if self.get(what) succeeds, and False if it raises KeyError. Any other exceptions are passed to the caller. @param what the grid_id or name of the WRFDomain to search for, or another WRFDomain whose name we should search for.TF)rrrrrr __contains__<s  zWRFDomains.__contains__ccs(td|jD]}|j|j|Vq dS)z8!Iterates over all WRFDomain objects in this WRFDomains.r`N)rangertrwryr^rrr__iter__IszWRFDomains.__iter__)NN)Nrr)N)rNNNNNNN)r)N) r5r6r7r8r@r*rrrdrerXpropertyrr~rrrprrrrrrrrrrrrrrrrrrrrUsP+ 8 A &   4   2 )r8 fractionsmathr datetimepdblogging hwrf.numerics hwrf.namelisthwrf.exceptions__all__rrobjectrrrrrrs0 bE