About RPL Functions
Following is a description of functions and their use in RPL sets.
Predefined Functions
Predefined functions are also useful in constructing rules, methods, and functions. Predefined functions are a set of mathematical, look-up, and mass balance routines that may be accessed from within any other expression. Predefined functions are coded into the RiverWare source code. Because of this, predefined functions cannot be modified. All predefined functions return their results in one of the standard data expression types; they can be substituted for any unspecified expression of that type. Predefined functions are accessed in the RPL Palette,
RPL Palette, under the
Predefined Functions tab at the top of the Palette dialog. Once added to a RPL expression, double-click the function to gets its editor. The documentation for the function is shown to help you specify the arguments and understand the evaluation.
See
RPL Predefined Functions for details on the predefined functions.
Figure 2.24
Writing a User-defined Function
Functions are constructed in much the same way that blocks are constructed, using the RPL Palette. Expressions are simplified by using functions to perform logical and computational operations. To make a function flexible so that it may be used in a variety of situations, arguments are added to the function. Arguments permit the same function to behave differently, depending on from where it is called or by which object. For example, an internal function could be created which forecasts the evaporation from a reservoir based on the reservoir’s surface area. This function could be of use at several reservoirs, but would have to know at which reservoir data to look. The reservoir for which the function should compute the evaporation could be an argument to the function.
Arguments to functions can be of any data expression type. There is no limit to the number of arguments a function may take, but the number of arguments is not dynamic with respect to block execution. The exact number and type of argument(s) is fixed in the function definition. Dynamic argument lists and default argument values are prohibited.
• Add a function to the desired Policy or Utility Group by selecting Set, then Add Function.
• Name the function and press <Enter> after naming.
Note: If you are renaming a function that is called by other RPL expressions, a dialog asks if you want to rename calls to this function in the applicable RPL sets. Answering yes will update existing calls to the function with the new name. For the Expression Slot set, the Initialization Rules set, the Iterative MRM sets, the Object Level Accounting Method set, Optimization Goal sets, and Rulebased Simulation sets only function calls within the set are affected. For Global Function sets, calls in any of the above sets will be affected. Calls to a global function from DMIs, scripts, or other places outside of RPL sets are not renamed. Answering No continues the name edit but does not update any calls to the function. Answering Cancel stops the name change all together.
• In the field Return Type, select the data expression type you wish the function to return. For example, if NUMERIC is selected the function will return a numeric value to the block in which the function is called.
If the function is going to be general to other functions or blocks, adding an argument might be useful depending on the return type of the function. In the above graphic, the Arguments: OBJECT res allows the variable res to be used inside of the function anywhere an <object expr> is allowed. This will allow the function to look at different reservoirs’ data without creating a separate function for each reservoir. If the function is going to be used only in a limited manner, arguments are not necessary.
Arguments to functions can be entered in two ways, using the editor and by typing. The editor is accessed from the
Arguments button
to the right of the Arguments line as shown to the right: Initially, the dialog is blank. You add arguments by selecting the green check button.
The red minus
is used to remove arguments and the arrows
are used to re-order arguments. The default type of an argument is NUMERIC. To change this, use the menu and select a different type. To change the name of the argument, double-click the name and type a new name. Select
OK when finished.
Figure 2.25 results in the argument shown below.
Figure 2.25 Annotated screenshot of the RPL Function Argument Editor
Typing was the original way to enter arguments. You type into the Arguments line using the syntax TYPE argument. Multiple arguments are separated by commas. For example, NUMERIC flow, LIST elevations, OBJECT res. The syntax, spelling, and capitalization must be exact or an error will be issued.
Note: To change the name of a function argument, select the argument in the expression and use the right-click
Rename option. This utility will rename all instances of that argument within the function’s expression and definition. See
Renaming Looping Variables and Function Arguments for details on this utility.
Functions are constructed like blocks and use the RPL Palette to build arguments.
Figure 2.26 shows a sample function constructed using predefined functions and RPL Palette buttons.
Figure 2.26 Screenshot of a completed RPL user defined function
The same short cut copy and paste abilities seen in blocks apply to functions as well. Any time an expression is used multiple times, whether within a function or between functions, time can be saved by copying and pasting that expression into the other locations in which it is used. As with blocks, it is wise to check the validity of an individual function after it is built and fix it rather than wait until the beginning of a run to check the validity of all blocks and functions.
Constraints on Functions
Functions can be constrained to evaluate to either a minimum or maximum value, or configured to stop with an error if a minimum or maximum constraint has been violated.
From the Function Editor, Select View, then Show Post-Execution Checks or select the Post-Exec Checks toggle.
To add one or more constraint using the Function menu item.
• To add a minimum or maximum return value, select Function, then Add Min Constraint or Add Max Constraint, as shown in the figure. The palette is then used to set up the conditions of the selected constraint.
Caution: The Min and Max constraints must evaluate to a legal range or an infeasibility error will be issued.
• To stop the run if the function returns a value outside a range, select Function, then Add Min Error or Add Max Error. The palette is then used to set up the conditions of the selected constraint. If the computed values is larger than the Max Error value or smaller than the Min Error value, the RPL evaluation will be aborted with an error.
Tip: The Post-Execution Checks are executed in order, top to bottom.
Time-invariant Functions and Function Value Caching
The function editor Edit menu provides a toggle control labeled Set Time Varying which is set to on by default. Toggling this property off communicates to RiverWare that the function is guaranteed to evaluate to the same value each time it is evaluated, i.e., it is time invariant. If a function with no arguments is time invariant, then the first time the function is called within a run, the body will be evaluated and the result saved internally. For all subsequent calls of that function within the run, the cached value will be returned without further computation, reducing computation time.
Note: Functions with arguments will almost certainly not be time invariant; if a function has an argument, then presumably there are some argument values for which the function will evaluate to different values.
Note: Incorrect application of caching to a time varying function will lead to incorrect results, so we recommend that the time varying property be toggled off for a function only when it is definitely time invariant, run time is critical, and RPL set analysis has indicated that a significant portion of the run is spent evaluating the function.
Note: During block evaluation (e.g. within a rule or accounting method), the workspace remains unchanged (because RPL expressions evaluate without side effects), so it is safe to cache values for functions without arguments within a single block. RPL does this automatically for all functions without arguments; multiple evaluations of such a function within the same block execution will cause the function to evaluate only once.