897 lines
29 KiB
HTML
897 lines
29 KiB
HTML
<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
|
|
<html>
|
|
<head>
|
|
<meta content="text/html; charset=iso-8859-1"
|
|
http-equiv="Content-Type">
|
|
<meta
|
|
content="Mozilla/4.79 [en] (X11; U; Linux 2.4.9-34smp i686) [Netscape]"
|
|
name="GENERATOR">
|
|
<title>Smart Initialization Configuration and User's Guide</title>
|
|
</head>
|
|
<body alink="#ff0000" vlink="#551a8b" link="#0000ee" bgcolor="#ffffff"
|
|
text="#000000">
|
|
<h1>
|
|
Smart Initialization Configuration and User's Guide</h1>
|
|
February 15, 2012<br>
|
|
<p>This document describes how smart initialization works, and how it
|
|
can be extended and modified.
|
|
<br>
|
|
</p>
|
|
<h2>Table of Contents</h2>
|
|
<a href="#HowSmartInitializationWorks">How Smart Initialization Works</a>
|
|
<br>
|
|
<a href="#Wherearethefiles">Where are the files that control smart
|
|
initialization?</a>
|
|
<br>
|
|
<a href="#BasicFileStructure">Basic File Structure</a>
|
|
<br>
|
|
<a href="#Workingwith">Working with SCALAR, VECTOR, WEATHER, and
|
|
DISCRETE
|
|
data</a>
|
|
<br>
|
|
<a href="#ModifyinganExistingAlgorithm">Modifying an Existing Algorithm</a>
|
|
<br>
|
|
<a href="#AddingNewAlgorithms">Adding New Algorithms</a>
|
|
<br>
|
|
<a href="#AddingNewModels">Adding New Models</a>
|
|
<br>
|
|
<a href="#CommandLine">Running Smart Initialization from the Command
|
|
Line</a>
|
|
<br>
|
|
<a href="#Examples">Examples of Complete Smart Initalization Files</a>
|
|
<br>
|
|
<a href="#Exercises">Exercises</a>
|
|
<p></p>
|
|
<hr width="100%">
|
|
<h2><a name="HowSmartInitializationWorks"></a>How Smart Initialization
|
|
Works</h2>
|
|
Smart initialization is closely coupled with EDEX. EDEX
|
|
is aware of D2D model data changes and therefore knows when IFP data
|
|
grids
|
|
can be created. Whenever EDEX first starts, or new D2D
|
|
model
|
|
data is detected (which occurs frequently - less than 5 minute
|
|
intervals), the server will
|
|
examine
|
|
the serverConfig/localConfig configuration file for the INITMODULES
|
|
definition.
|
|
If it finds a match with the updated D2D model, then it will spawn a
|
|
process
|
|
to run smart initialization for that model.
|
|
<p>When a smart initialization process is started, it will run a
|
|
particular
|
|
class file, either one that has been supplied with the release, or one
|
|
you have added. The software will examine all of the functions
|
|
within
|
|
that class looking for function names that begin with calc***.
|
|
These
|
|
functions define the output weather element, e.g., calcT will derive T,
|
|
and also the dependencies. The dependencies are determined from
|
|
the
|
|
argument list for each function.
|
|
</p>
|
|
<p>The smart initialization software then figures out the dependencies
|
|
for all of the calc*** functions and will determine what must run
|
|
first,
|
|
second, third, etc. This is done automatically and the programmer
|
|
need not be concerned about it. The software also examines the
|
|
inventory
|
|
for the dependent grids and the inventory for the output grids to
|
|
determine
|
|
if the output grid is already present and no calculations are needed,
|
|
or
|
|
whether the output grid needs to be created by running the algorithms.
|
|
</p>
|
|
<p>When all the possible dependencies and algorithms have run, the
|
|
process
|
|
exits until the next D2D model update.
|
|
</p>
|
|
<p>Smart Initialization algorithms are written in a simple, intuitive
|
|
language
|
|
called Python and its extension, numpy. The following
|
|
sections
|
|
assume that you have knowledge of Python which is covered in the
|
|
<a href="Python.html">GFESuite
|
|
Python Tutorial and Programming Guidelines</a>.
|
|
<br>
|
|
</p>
|
|
<hr width="100%">
|
|
<h2><a name="Wherearethefiles"></a>Where are the files that control
|
|
smart initialization?</h2>
|
|
The standard smart initialization files that are supplied with the
|
|
release
|
|
are installed into your <i>release</i>/edex/data/utility/edex_static/base/smartinit
|
|
directory. No modifications
|
|
should be made to any of the files in the BASE directory.
|
|
User-customized
|
|
files are installed into the <i>release</i>/edex/data/utility/edex_static/site/SITE/smartinit
|
|
directory. These SITE files are not overwritten during installs and upgrades.
|
|
<br>
|
|
<hr width="100%">
|
|
<h2><a name="BasicFileStructure"></a>Basic File Structure</h2>
|
|
The basic structure of a smart initialization file contains a header
|
|
that is simliar to:
|
|
<p><tt>from Init import *</tt>
|
|
</p>
|
|
<p><tt>class <i>model</i>Forecaster(<i>derivedFrom</i>Forecaster):</tt>
|
|
<br>
|
|
<tt> def __init__(self):</tt>
|
|
<br>
|
|
<tt> <i>derivedFrom</i>Forecaster.__init__(self,
|
|
"<i>sourceDb</i>", "<i>destDb</i>")</tt>
|
|
</p>
|
|
<p>This is basically defining a new class called "<i>model</i>Forecaster",
|
|
which is derived from "<i>derivedFrom</i>Forecaster". The
|
|
__init__
|
|
function is the constructor to the class, which calls the base class
|
|
(class
|
|
it has been defined from) with three arguments, self, "sourceDb",
|
|
and "destDb". The source db is the name of the D2D database, such
|
|
as NAM80, NAM40, NAM12, RUC80, GFS40, gfsLR. The
|
|
destination database is the name of the output
|
|
database, such as NAM12, GFS40, NAM_V. If there is an underscore
|
|
in the destination database, then the format is the
|
|
modelname_optionaltype.
|
|
</p>
|
|
<p>A complete example of the header is shown below:
|
|
</p>
|
|
<p><tt>from Init import *</tt>
|
|
</p>
|
|
<p><tt>class NAM12Forecaster(Forecaster):</tt>
|
|
<br>
|
|
<tt> def __init__(self):</tt>
|
|
<br>
|
|
<tt>
|
|
Forecaster.__init__(self,
|
|
"NAM12", "NAM12")</tt>
|
|
<br>
|
|
|
|
</p>
|
|
<p>There usually is a function called levels() which define a set of
|
|
vertical
|
|
pressure levels which are used when accessing cube data from the
|
|
models.
|
|
The levels() return a list of level values to use. Make sure that
|
|
the levels you specify are actually available in the model. A complete
|
|
example is shown below:
|
|
</p>
|
|
<p> <tt> def levels(self):</tt>
|
|
<br>
|
|
<tt> return ["MB950",
|
|
"MB900","MB850","MB800","MB750",</tt>
|
|
<br>
|
|
<tt>
|
|
"MB700","MB650","MB600","MB550", "MB500",</tt>
|
|
<br>
|
|
<tt>
|
|
"MB450", "MB400", "MB350"]</tt>
|
|
</p>
|
|
<p>Following the levels() function are the set of functions with a
|
|
particular
|
|
name. The calculation functions <b><font color="#000099">MUST
|
|
ALL
|
|
BEGIN WITH calc</font></b> in their name. That is how smart
|
|
initialization
|
|
can determine what to run. It basically runs all calc***
|
|
functions
|
|
that are defined. The remainder of the name of the function after
|
|
"calc" is the parameter name to create. For example, if RH is
|
|
your
|
|
weather element name, the name of the function to calculate RH would be
|
|
calcRH(). The typical format for a calc function is shown below, this
|
|
one
|
|
calculates surface temperature from the eta model:
|
|
</p>
|
|
<p><tt> def calcT(self, t_FHAG2, t_BL3060, p_SFC,
|
|
stopo,
|
|
topo):</tt>
|
|
<br>
|
|
<tt> dpdz = 287.04 * t_FHAG2
|
|
/ (p_SFC / 100 * 9.8) # meters / millibar</tt>
|
|
<br>
|
|
<tt> # 45milibars is halfway
|
|
between 30 and 60</tt>
|
|
<br>
|
|
<tt> dpdz = dpdz * 45 #
|
|
meters
|
|
between p_SFC and t_BL3060</tt>
|
|
<br>
|
|
<tt> lapse = (t_FHAG2 -
|
|
t_BL3060)
|
|
/ dpdz # degrees / meter</tt>
|
|
<br>
|
|
<tt> lapse = clip(lapse,
|
|
lapse, 0.012)</tt>
|
|
<br>
|
|
<tt> t = t_FHAG2 + lapse
|
|
* (stopo - topo)</tt>
|
|
<br>
|
|
<tt> return self.KtoF(t)</tt>
|
|
<br>
|
|
|
|
</p>
|
|
<p>Here is the same function with more details:
|
|
</p>
|
|
<p>The following grids from the D2D model database are passed into this
|
|
routine, 2 meter temperatures, the boundary layer temperatures from the
|
|
30-60 hPa levels, the surface pressure in Pascals, surface topography
|
|
from
|
|
the model, and the high resolution topographical data.
|
|
</p>
|
|
<p><tt> def calcT(self, t_FHAG2, t_BL3060, p_SFC,
|
|
stopo,
|
|
topo):</tt>
|
|
</p>
|
|
<p>We begin to calculate the lapse rate, but first we need to determine
|
|
the number of meters between the surface and 30-60 hPa level.
|
|
<br>
|
|
<tt> dpdz = 287.04 * t_FHAG2
|
|
/ (p_SFC / 100 * 9.8) # meters / millibar</tt>
|
|
<br>
|
|
<tt> # 45milibars is halfway
|
|
between 30 and 60</tt>
|
|
<br>
|
|
<tt> dpdz = dpdz * 45 #
|
|
meters
|
|
between p_SFC and t_BL3060</tt>
|
|
</p>
|
|
<p>The lapse rate can now be calculated:
|
|
<br>
|
|
<tt> lapse = (t_FHAG2 -
|
|
t_BL3060)
|
|
/ dpdz # degrees / meter</tt>
|
|
</p>
|
|
<p>We ensure that the lapse rate can't get too steep
|
|
<br>
|
|
<tt> lapse = clip(lapse,
|
|
lapse, 0.012)</tt>
|
|
</p>
|
|
<p>We calculate the surface temperature, which is the model 2m
|
|
temperature
|
|
modified by the lapse rate and the difference between the model surface
|
|
and the real surface elevation.
|
|
<br>
|
|
<tt> t = t_FHAG2 + lapse
|
|
* (stopo - topo)</tt>
|
|
</p>
|
|
<p>We perform unit conversion and return.
|
|
<br>
|
|
<tt> return self.KtoF(t)</tt>
|
|
</p>
|
|
<p>The name of the function is always calc*** where *** is the
|
|
weather
|
|
element name and level. If you are creating weather elements for
|
|
surface data then the weather element name by itself is
|
|
sufficient.
|
|
If you are creating weather elements for upper air or non-surface data,
|
|
then the name of the calc function is: calc***_***, such as
|
|
calcWind_3K() for the Wind at 3000 feet.
|
|
</p>
|
|
<p>Note the argument list for the calc*** functions. The first
|
|
argument
|
|
is always self. The remainder of the arguments represent gridded
|
|
data. The format of the specification can be one of the following
|
|
formats:
|
|
<br>
|
|
<table nosave="" width="100%" border="1">
|
|
<tbody>
|
|
<tr>
|
|
<td><b>Format</b></td>
|
|
<td><b>Example</b></td>
|
|
<td><b>Purpose</b></td>
|
|
</tr>
|
|
<tr>
|
|
<td>EditAreaName</td>
|
|
<td>Colorado</td>
|
|
<td>The name of an editArea. It is probably best to use polygon
|
|
edit areas
|
|
instead of queries (untested with queries). The value of the paramater,
|
|
in this case Colorado, will be a boolean grid suitable for use as a
|
|
mask
|
|
for numeric functions.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>parmName_level</td>
|
|
<td>t_FHAG2</td>
|
|
<td>Refers to a single grid for the parmName and the level.
|
|
The example
|
|
accesses the temperature grid from the model that is at the FHAG2
|
|
(fixed
|
|
height above ground 2m level)</td>
|
|
</tr>
|
|
<tr>
|
|
<td>parmName_c</td>
|
|
<td>rh_c</td>
|
|
<td>Refers to a cube of data for the parmName. The "_c" indicates
|
|
the cube.
|
|
The number of layers in the cube depend upon the levels() function
|
|
contents.
|
|
For example, if the levels() contain: <br>
|
|
<tt> def levels(self):</tt> <br>
|
|
<tt> return ["MB950",
|
|
"MB900","MB850","MB800","MB750",</tt> <br>
|
|
<tt>
|
|
"MB700","MB650","MB600","MB550", "MB500",</tt> <br>
|
|
<tt>
|
|
"MB450", "MB400", "MB350"]</tt> <br>
|
|
then the cube will contain 13 levels. Access of individual levels
|
|
can be done using indexing within the function.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>topo</td>
|
|
<td>topo</td>
|
|
<td>Refers to the high-resolution surface topography field,
|
|
in units
|
|
of meters above MSL.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>stopo</td>
|
|
<td>stopo</td>
|
|
<td>Refers to the model topography field, in units of meters
|
|
above MSL.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>ctime</td>
|
|
<td>ctime</td>
|
|
<td>Time from the source database grid currently being
|
|
calculated, as a
|
|
time range tuple (startTime, endTime), in seconds since January 1, 1970
|
|
at 0000z.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>mtime</td>
|
|
<td>mtime</td>
|
|
<td>Time in the destination database grid currently being
|
|
calculated, as
|
|
a time range tuple (startTime, endTime), in seconds since January 1,
|
|
1970
|
|
at 0000z.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>stime</td>
|
|
<td>stime</td>
|
|
<td>Number of seconds from the model basetime currently being
|
|
calculated,
|
|
in seconds since the model analysis time.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>parmName</td>
|
|
<td>FzLevel</td>
|
|
<td>Refers to the weather element in the OUTPUT database, not the
|
|
INPUT
|
|
D2D database.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</p>
|
|
<p>You can place additional functions (e.g., utility) functions
|
|
anywhere
|
|
in the file after the constructor (__init__) and before the tail end of
|
|
the file. An example of a utility function could be one to
|
|
calculate Td from T and RH as shown below:
|
|
</p>
|
|
<p><tt> def getTd(self, t, rh):</tt>
|
|
<br>
|
|
<tt> # input/output in
|
|
degrees
|
|
K.</tt>
|
|
<br>
|
|
<tt> desat = clip(t, 0,
|
|
373.15)</tt>
|
|
<br>
|
|
<tt> desat = where(less(t,
|
|
173.15), 3.777647e-05, t)</tt>
|
|
<br>
|
|
<tt> desat = exp(26.660820
|
|
- desat * 0.0091379024 - 6106.3960 / desat)</tt>
|
|
<br>
|
|
<tt> desat = desat * rh /
|
|
100.0</tt>
|
|
<br>
|
|
<tt> desat = 26.66082 -
|
|
log(desat)</tt>
|
|
<br>
|
|
<tt> td = (desat -
|
|
sqrt(desat*desat-223.1986))/0.0182758048</tt>
|
|
<br>
|
|
<tt> td = where(greater(td,
|
|
t), t, td)</tt>
|
|
<br>
|
|
<tt> return td</tt>
|
|
</p>
|
|
<p>The tail end of the file contains a definition of main() and must be
|
|
similar to that below:
|
|
</p>
|
|
<p><tt>def main():</tt>
|
|
<br>
|
|
<tt> <i>model</i>Forecaster().run()</tt>
|
|
</p>
|
|
<p>Here is an example of a real tail to the file. The name of the class
|
|
within the main() function must match the name of the class you have
|
|
defined
|
|
in the header:
|
|
</p>
|
|
<p><tt>def main():</tt>
|
|
<br>
|
|
<tt> NAM12Forecaster().run()</tt>
|
|
</p>
|
|
<h2>
|
|
<hr width="100%"><a name="Workingwith"></a>Working with SCALAR, VECTOR,
|
|
WEATHER, and DISCRETE Data</h2>
|
|
This section describes accessing scalar, vector, and weather data
|
|
through
|
|
numerical python.
|
|
<h3>SCALAR</h3>
|
|
<p><br>
|
|
When passing in a weather element that is scalar, you will either
|
|
get a grid, or a cube. The grid is a numeric 2-d grid
|
|
(x,y),
|
|
the cube is a numeric 3-d grid (z,x,y).
|
|
<br>
|
|
</p>
|
|
<h3>VECTOR</h3>
|
|
For a single vector grid (single level), you get a tuple. The
|
|
first
|
|
element is a grid of magnitude, the second is a grid of
|
|
direction.
|
|
To access the magnitude grid, use this syntax: <tt>wind_SFC[0]</tt>,
|
|
and
|
|
for direction, use this syntax: <tt>wind_SFC[1]</tt>. Once
|
|
you access either the magnitude or direction grid, they are treated
|
|
like
|
|
a scalar grid.
|
|
<p>There are several "utility" functions in Init.py (located in your
|
|
release/edex/data/utility/edex_static/base/smartinit
|
|
directory) that can help you when working with vector data. The <tt>self._getUV(
|
|
mag, dir)</tt> call will convert a magnitude/direction grids into a
|
|
returned
|
|
tuple of u and v. The u component is [0] and the v component is
|
|
[1].
|
|
The <tt>self._getMD(u,v)</tt> function converts a grid in u and v
|
|
components
|
|
into a tuple of magnitude and direction. The magnitude component
|
|
is [0] and the direction component is [1].
|
|
<br>
|
|
</p>
|
|
<h3>WEATHER</h3>
|
|
Weather is much more complicated and can be a big performance problem.
|
|
A tuple is provided. The first element is a grid, which contains
|
|
the indexes into the key. The second element is a sequence of all of
|
|
the
|
|
keys. The keys are the ugly strings associated with a
|
|
WeatherKey.
|
|
To access the grid:
|
|
<p><tt>Wx[0]</tt>
|
|
</p>
|
|
<p>To access the sequence, use:
|
|
</p>
|
|
<p><tt>Wx[1]</tt>
|
|
</p>
|
|
<p>To access a particular entry in the sequence, use:
|
|
</p>
|
|
<p><tt>Wx[1][3]</tt>, would give your the 4th key.
|
|
</p>
|
|
<p>Normally you don't access the weather grid in your calculations, but
|
|
if you need to, you have generally created a weather grid first.
|
|
In smart initialization, we know all of the possible weather keys that
|
|
can be created and set up a table with those keys, then we simply poke
|
|
in the correct index for the key. This is much more efficient
|
|
than
|
|
searching the keys for each grid point.
|
|
<br>
|
|
</p>
|
|
<h3>DICRETE</h3>
|
|
Discrete is much more complicated than the simple scalar and vector
|
|
case,
|
|
and like weather, can be a big performance problem. A tuple is
|
|
provided.
|
|
The first element is a grid, which contains the indexes into the key.
|
|
The
|
|
second element is a sequence of all of the keys. The keys
|
|
are
|
|
the discrete key values associated with the weather element. To
|
|
access
|
|
the grid:
|
|
<p><tt>DK[0]</tt>
|
|
</p>
|
|
<p>To access the sequence, use:
|
|
</p>
|
|
<p><tt>DK[1]</tt>
|
|
</p>
|
|
<p>To access a particular entry in the sequence, use:
|
|
</p>
|
|
<p><tt>DK[1][3]</tt>, would give your the 4th key.
|
|
</p>
|
|
<p>Normally you don't access the discrete grid in your calculations,
|
|
but
|
|
if you need to, you have generally created a discrete grid first.
|
|
In smart initialization, we know all of the possible discrete keys that
|
|
can be created and set up a table with those keys, then we simply poke
|
|
in the correct index for the key. This is much more efficient
|
|
than
|
|
searching the keys for each grid point.
|
|
</p>
|
|
<h2>
|
|
<hr width="100%"></h2>
|
|
<h2>
|
|
<a name="ModifyinganExistingAlgorithm"></a>Modifying an Existing
|
|
Algorithm</h2>
|
|
The basic procedure to modify an existing algorithm is shown below:
|
|
<ul>
|
|
<li>Create a new file in <i>release</i> which should be
|
|
named
|
|
similarily,
|
|
but not identical to, the class in which you are modifying. For
|
|
example,
|
|
if you are modifying the NAM12 model intiialization, which is stored in
|
|
NAM12.py,
|
|
perhaps you should name your new file MyNAM12.py to indicate that this
|
|
is
|
|
your eta.</li>
|
|
<li>The format of the file should be standard as shown in the <a
|
|
href="#BasicFileStructure">Basic
|
|
File Structure section</a> above. In particular, it needs
|
|
to
|
|
include the following items:</li>
|
|
<ul>
|
|
<li>the header, which is set to inherit the file you are inheriting
|
|
from</li>
|
|
<li>the levels() function, but only if you are changing it</li>
|
|
<li>a replacement, named the same, of the function you are
|
|
modifying.
|
|
You may want to copy this function (not ALL functions -- just this one)
|
|
into this file from the original file and then edit it.</li>
|
|
<li>the tail, which includes the main() and the final if __name__
|
|
statements</li>
|
|
</ul>
|
|
<li>Modify (create first if necessary) your server <a
|
|
href="localConfig.html#InitializationModules">localConfig.py
|
|
file to override the INITMODULES</a> section of the serverConfig.py.</li>
|
|
</ul>
|
|
Here is an example of overriding the NAM12 derivation of Snow
|
|
Amount.
|
|
The original NAM12.py file contains the following information (only
|
|
part
|
|
of the file is shown). The snow amount function calculates the
|
|
snow
|
|
ratio which varies depending upon temperature, and then assigns the
|
|
snow
|
|
amount based on the snow ratio and QPF where the snow level (freezing
|
|
level
|
|
- 1000
|
|
<p><tt>from Init import *</tt>
|
|
</p>
|
|
<p><tt>class NAM12Forecaster(Forecaster):</tt>
|
|
<br>
|
|
<tt> def __init__(self):</tt>
|
|
<br>
|
|
<tt>
|
|
Forecaster.__init__(self,
|
|
"NAM12", "NAM12")</tt>
|
|
</p>
|
|
<p><tt> def levels(self):</tt>
|
|
<br>
|
|
<tt> return ["MB950",
|
|
"MB900","MB850","MB800","MB750",</tt>
|
|
<br>
|
|
<tt>
|
|
"MB700","MB650","MB600","MB550", "MB500",</tt>
|
|
<br>
|
|
<tt>
|
|
"MB450", "MB400", "MB350"]</tt>
|
|
</p>
|
|
<p><tt> def calcSnowAmt(self, T, FzLevel, QPF, topo):</tt>
|
|
<br>
|
|
<tt> m1 = less(T, 9)</tt>
|
|
<br>
|
|
<tt> m2 = greater_equal(T,
|
|
30)</tt>
|
|
<br>
|
|
<tt> snowr = T * -0.5 + 22.5</tt>
|
|
<br>
|
|
<tt> snowr = where(m1, 20,
|
|
snowr)</tt>
|
|
<br>
|
|
<tt> snowr = where(m2, 0,
|
|
snowr)</tt>
|
|
<br>
|
|
<tt> snowamt =
|
|
where(less_equal(FzLevel
|
|
- 1000, topo*3.048), snowr * QPF, 0)</tt>
|
|
<br>
|
|
<tt> return snowamt</tt>
|
|
</p>
|
|
<p><tt>def main():</tt>
|
|
<br>
|
|
<tt> NAM12Forecaster().run()</tt>
|
|
</p>
|
|
<p>Here is the derived MyNAM12 file that overrides the calcSnowAmt()
|
|
function:
|
|
</p>
|
|
<p><tt>from NAM12 import *</tt>
|
|
</p>
|
|
<p>c<tt>lass MyNAM12Forecaster(NAM12Forecaster):</tt>
|
|
<br>
|
|
<tt> def __init__(self):</tt>
|
|
<br>
|
|
<tt>
|
|
NAM12Forecaster.__init__(self)</tt>
|
|
</p>
|
|
<p><tt> def calcSnowAmt(self, T, QPF):</tt>
|
|
<br>
|
|
<tt> m2 = less_equal(T, 32)</tt>
|
|
<br>
|
|
<tt> snowamt = where(m2,
|
|
10.0 * QPF, 0)</tt>
|
|
<br>
|
|
<tt> return snowamt</tt>
|
|
</p>
|
|
<p><tt>def main():</tt>
|
|
<br>
|
|
<tt> MyNAM12Forecaster().run()</tt>
|
|
</p>
|
|
<p>The algorithm was changed to have a fixed 10:1 snow ratio anytime
|
|
the
|
|
temperature is below 32. The freezing level is no longer used in
|
|
this revision. Of course you can completely rewrite the
|
|
algorithm,
|
|
use different arguments, etc. Note that the name of the function,
|
|
calcSnowAmt() in this case is identical to to the name in the original
|
|
file. This is important!
|
|
<br>
|
|
</p>
|
|
<hr width="100%">
|
|
<h2><a name="AddingNewAlgorithms"></a>Adding New Algorithms</h2>
|
|
Adding a new algorithm is just about the same as <a
|
|
href="#ModifyinganExistingAlgorithm">Modifying
|
|
An Existing Algorithm</a>. You will do the similar steps:
|
|
<ul>
|
|
<li>Create a new file in <i>release</i>/edex/data/utility/edex_static/site/SITE/smartinit
|
|
which should be named similarily,
|
|
but not identical to, the class in which you want to add a new
|
|
algorithm.
|
|
For example, if you are adding to the NAM model intiialization, which
|
|
is
|
|
stored in NAM.py, perhaps you should name your new file MyNAM.py to
|
|
indicate
|
|
that this is your eta.</li>
|
|
<li>The format of the file should be standard as shown in the <a
|
|
href="#BasicFileStructure">Basic
|
|
File Structure section</a> above. In particular, it needs
|
|
to
|
|
include the following items:</li>
|
|
<ul>
|
|
<li>the header, which is set to inherit the file you are
|
|
interheiting from</li>
|
|
<li>the tail, which includes the main() statement</li>
|
|
</ul>
|
|
<li>Add your new function into the newly created file.</li>
|
|
<li>Modify (create first if necessary) your server <a
|
|
href="localConfig.html#InitializationModules">localConfig.py
|
|
file to override the INITMODULES</a> section of the serverConfig.py.</li>
|
|
<li>Modify (create first if necessary) your server <a
|
|
href="localConfig.html#AddinganewWeatherElement">localConfig.py
|
|
file to add the new weather elements</a> for which you want the
|
|
initialization
|
|
to populate.</li>
|
|
</ul>
|
|
Here is an example of a MyNAM12.py initialization file that creates a
|
|
new
|
|
weather element called RH for the NAM model. It does nothing more
|
|
than taking the model RH FHAG2 field and storing it into the NAM12 RH
|
|
weather
|
|
element, after ensuring that the field ranges between 0 and 100%:
|
|
<p><tt>from NAM12 import *</tt>
|
|
</p>
|
|
<p><tt>class MyNAM12Forecaster(NAM12Forecaster):</tt>
|
|
<br>
|
|
<tt> def __init__(self):</tt>
|
|
<br>
|
|
<tt>
|
|
NAM12Forecaster.__init__(self)</tt>
|
|
</p>
|
|
<p><tt> def calcRH(self, rh_FHAG2):</tt>
|
|
<br>
|
|
<tt> return clip(rh_FHAG2,
|
|
0, 100)</tt>
|
|
</p>
|
|
<p><tt>def main():</tt>
|
|
<br>
|
|
<tt> MyNAM12Forecaster().run()</tt>
|
|
</p>
|
|
<hr width="100%">
|
|
<h2><a name="AddingNewModels"></a>Adding New Models</h2>
|
|
Adding new models, and all of the algorithms to derive the elements
|
|
isn't
|
|
much different from <a href="#AddingNewAlgorithms">Adding New
|
|
Algorithms</a>
|
|
or <a href="#ModifyinganExistingAlgorithm">Modifying an Existing
|
|
Algorithm</a>.
|
|
The basic steps are:
|
|
<ul>
|
|
<li>Create a new file in <i>release</i>/edex/data/utility/edex_static/site/SITE/smartinit
|
|
which should be named appropriately
|
|
(and not the same name as any file in <i>release</i>/edex/data/utility/edex_static/base/
|
|
smartnit) For
|
|
example,
|
|
if you are going to create a GWW model initialization, then the name
|
|
should
|
|
probably be GWW.py.</li>
|
|
<li>The format of the file should be standard as shown in the <a
|
|
href="#BasicFileStructure">Basic
|
|
File Structure section</a> above. In particular, it needs
|
|
to
|
|
include the following items:</li>
|
|
<ul>
|
|
<li>the header, which is set to inherit the file you are
|
|
interheiting from</li>
|
|
<li>the levels() function, which you don't need if you aren't
|
|
accessing any
|
|
D2D-cube data.</li>
|
|
<li>all of the calc*** functions that are required to create each
|
|
of your
|
|
weather
|
|
elements.</li>
|
|
<li>the tail, which includes the main() statement</li>
|
|
</ul>
|
|
<li>Modify (create first if necessary) your server <a
|
|
href="localConfig.html#InitializationModules">localConfig.py
|
|
file to override the INITMODULES</a> section of the serverConfig.py.</li>
|
|
<li>Modify (create first if necessary) you server <a
|
|
href="localConfig.html#AddinganewDatabase">localConfig.py
|
|
file to define a new database</a> and all of the weather elements
|
|
associated
|
|
with the database.</li>
|
|
</ul>
|
|
Here is a complete example of creating WaveHeight and Surface Wind from
|
|
the GWW model. The wave height logic catches values that
|
|
are very high and assumes that they are missing data and resets them to
|
|
zero height. There is also a conversion from meters to
|
|
feet.
|
|
The wind logic also catches values that are very high and assumes that
|
|
they are missing data and resets the winds to calm. There is also
|
|
a conversion from meters/second to knots.:
|
|
<p><tt>from Init import *</tt>
|
|
<br>
|
|
<tt>class GWWForecaster(Forecaster):</tt>
|
|
<br>
|
|
<tt> def __init__(self):</tt>
|
|
<br>
|
|
<tt>
|
|
Forecaster.__init__(self,
|
|
"GWW", "GWW")</tt>
|
|
</p>
|
|
<p><tt> def calcWaveHeight(self, htsgw_SFC):</tt>
|
|
<br>
|
|
<tt> grid =
|
|
where(greater(htsgw_SFC,
|
|
50), 0.0, htsgw_SFC/3.048)</tt>
|
|
<br>
|
|
<tt> return clip(grid, 0,
|
|
100)</tt>
|
|
</p>
|
|
<p><tt> def calcWind(self, wind_SFC):</tt>
|
|
<br>
|
|
<tt> mag =
|
|
where(greater(wind_SFC[0],
|
|
50), 0, wind_SFC[0]*1.94)</tt>
|
|
<br>
|
|
<tt> dir =
|
|
where(greater(wind_SFC[0],
|
|
50), 0, wind_SFC[1])</tt>
|
|
<br>
|
|
<tt> dir = clip(dir, 0, 359.5)</tt>
|
|
<br>
|
|
<tt> return (mag, dir)</tt>
|
|
</p>
|
|
<p><tt>def main():</tt>
|
|
<br>
|
|
<tt> GWWForecaster().run()</tt>
|
|
</p>
|
|
<hr width="100%">
|
|
<h2><a name="CommandLine"></a>Running Smart Initialization from the
|
|
Command
|
|
Line</h2>
|
|
Normally you don't need to run smart initialization from the command
|
|
line.
|
|
Smart initialization is automatically started by EDEX when new
|
|
D2D model data arrives.
|
|
<p>In the event that you do want to run smart initialization from the
|
|
command
|
|
line, which you probably would when you are developing new algorithms,
|
|
here is the proper syntax:
|
|
</p>
|
|
<p><tt>ifpInit [-h host] [-p port] [-t modelTime] [-s site] [-u userid] [-a]
|
|
algorithmFile</tt>
|
|
<br>
|
|
<br>
|
|
<table nosave="" width="100%" border="1">
|
|
<tbody>
|
|
<tr>
|
|
<td><b>Switch</b></td>
|
|
<td><b>Optional?</b></td>
|
|
<td><b>Purpose</b></td>
|
|
</tr>
|
|
<tr>
|
|
<td>-h host</td>
|
|
<td>yes</td>
|
|
<td>Defines the host upon which EDEX is running.
|
|
Normally
|
|
this switch is not needed and the software will determine where EDEX
|
|
is running.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>-p port</td>
|
|
<td>yes</td>
|
|
<td>Defines the RPC port upon which EDEX is
|
|
running. Normally
|
|
this switch is not needed and the software will determine where EDEX
|
|
is running.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>-t modelTime</td>
|
|
<td>yes</td>
|
|
<td>Specifies the model run time in the format of
|
|
yyyymmdd_hhmm.
|
|
If not specified, then run using the latest model data.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>-s site</td>
|
|
<td>no</td>
|
|
<td>Specifies the site id for whom to run the init.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>-u user</td>
|
|
<td>yes</td>
|
|
<td>Specifies the user id who is executing the init.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>-a</td>
|
|
<td>yes</td>
|
|
<td>Specifies to create all of the possible data grids, which
|
|
will overwrite
|
|
existing previously calculated grids. Normally by default, only
|
|
those
|
|
grids that haven't yet been created will be attempted to be calculated.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>algorithmFile</td>
|
|
<td>no</td>
|
|
<td>Mandatory argument specifying the name of the smart
|
|
initialization
|
|
module, such as NAM12, or MyNAM12.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<font color="#3366ff">Note: The -h and -p switches are predefined to
|
|
match your AWIPS installation, such that they will point to EDEX
|
|
specified on installation. Thus the -h and -p switches are not
|
|
necessary for normal running of this program. However, if you wish to
|
|
connect to a different server, then you will need to specify the -h and -p
|
|
switches.</font><br>
|
|
</p>
|
|
<hr width="100%">
|
|
<h2><a name="Examples"></a>Examples of Complete Smart Initalization
|
|
Files</h2>
|
|
<p><br>
|
|
Here is an <a href="EXAMPLESmartInit_NAM.py">example of the NAM12.py
|
|
smart initialization file</a> that is provided (or similar to what is
|
|
provided).
|
|
</p>
|
|
<p>Here is an <a href="EXAMPLESmartInit_MyNAM.py">example of a
|
|
modification
|
|
to the NAM12.py called MyNAM12.py</a> which modifies the snow amount
|
|
calculation,
|
|
and adds the surface relative humidity field.
|
|
</p>
|
|
<p>Here is an <a href="EXAMPLESmartInit_NewModel.py">example of adding
|
|
a new model, the GWW model</a>, to calculate wave height and wind.
|
|
</p>
|
|
<p></p>
|
|
<hr width="100%">
|
|
<h2><a name="Exercises"></a>Exercises</h2>
|
|
Several smart initialization exercises are available <a
|
|
href="SmartInitExercises.html">here</a>.
|
|
<br>
|
|
</body>
|
|
</html>
|