Hypothetical Simulations
This section presents an overview of a set of functions that allow the user to run a hypothetical simulation, where:
• A limited number of objects on the workspace are involved.
• The simulation has no side-effects, i.e., after simulation the workspace is exactly as before.
• The objects involved initially have their current values, except for those values that the user provides as “fixed values” to the hypothetical simulation.
• At least one and possibly more values resulting from the hypothetical simulation are available for use within rulebased simulation.
Note:  See Hypothetical Simulation Functions for a list of the functions used for hypothetical simulations.
Hypothetical Simulation Overview
Why would you want to do this? Lets consider the following example. Suppose that you would like to maintain a minimum flow of 100 cfs at some point in River Y. Many miles upstream from this point you can control the outflow from Reservoir X. One question you might ask is: what is the release from X which will lead to the 100 cfs flow at the point of concern? A related but simpler question is: If I release 200 cfs from reservoir X, what will be the flow at the point of concern?
Even the answer to the second question can’t be easily predicted; you might have to take into consideration many hydrologic inflows and flow-dependent physical processes like lags, losses, and diversions through different sections of River Y. you might even require that you know the release over some extended period of time in order to be able to determine the flow in the Y at a single time. At any rate, this is exactly the sort of computation performed by the objects in a RiverWare simulation.
On the other hand, answering the first question requires not only knowing the physical consequences of outflow from X, but a search for the release which has the target consequence. The target consequence cannot just be set and allowed to solve upstream because there are routing algorithms can only solve in the downstream direction.
Hypothetical Simulation Functions
The following functions can be used to do hypothetical simulations.
HypSim
Perform a hypothetical simulation with user specified values and returns user-requested result values. See HypSim for more information on this function.
HypLimitSim
Perform hypothetical simulations iteratively to find a value which, when set on a given slot, will lead to another slot achieving but not exceeding a limiting value. See HypLimitSim for more information on this function.
HypLimitSimWithStatus
Same as HypLimitSim but with information on whether a satisfying value was found or not. See HypLimitSimWithStatus for more information on this function.
HypTargetSim
Perform hypothetical simulations iteratively to find a value which, when set on a given slot, will lead to a desired value on another slot. See HypTargetSim for more information on this function.
HypTargetSimWithStatus
Same as HypTargetSim but with information on whether a satisfying value was found or not. See HypLimitSimWithStatus for more information on this function.
Hypothetical Simulation Process
Each hypothetical simulation function proceeds in the following manner. The first time the function is called, all of the objects and links in the specified subbasin are cloned. This copies each object including all of the slots and values. This cloning is necessary as all subsequent computations are performed on the cloned objects, thereby not affecting the real objects on the workspace. Once the objects are cloned, any values specified in the arguments as “fixed values” are set on the objects. Remember, the function also copied all its data at the time it was cloned, so the fixed values are values that are to be set on the object that are not already there.
Then, the hypothetical simulation performs the computations described for that function. For HypSim, the cloned objects will dispatch to simulate the effects of the fixed values. A list containing the values of the specified slots at the specified datetimes will be returned. The calling rule/function can then use these results in its computation.
HypLimitSim, HypLimitSimWithStatus, HypTargetSim, and HypTargetSimWithStatus perform an iterative solution. For each of these functions, you provide min and max values for a control slot and a target or limit of a downstream slot. The computations then boil down to univariate zero-finding, where each evaluation is a hypothetical simulation with different inputs. The solution is found using the bisection method as shown in the following figure; it simulates using the min control slot value (1), then the max control slot value (2), then bisects between the two(3). It continues bisecting until the tolerance or desired accuracy of the limit/target slot is met and a solution is found (N.) If the result of any try is outside of the range of previous tries, then a warning message is issued saying that the function is non-monotonic. There are either multiple solutions or the function is not well behaved. This typically leads to convergence issues.
Figure 5.2
Following are some notes to consider about hypothetical simulation and particularly the iterative hypothetical simulations:
• These are hypothetical simulations, not rulebased simulations. You can set fixed values in the arguments but they cannot change once the function is executed.
• Hypothetical simulation does not support accounting or optimization functionality.
• Each iteration within hypothetical simulation is setting the control value to a new value and re-simulating the system. Some object methods may have a dependence on previous solutions that will lead to different results. Also, slot convergence can be an issue. If setting a new value on a slot does not propagate down the system because convergence is too loose, then the target/limit slot value may never be achieved.
• Use the WithStatus version of the function if you suspect that the function may not work in all cases but you still need a result. If these functions do not find a result, the closest value is returned along with the status. But, make sure to check the status in the calling rule or function, don’t just use the result blindly. Use the “without status” version if you reasonably expect there to be a solution. Then, if there is a problem with the computation and no solution is found, the run is stopped and a message is posted.
• For the iterative functions, if there are multiple timesteps involved, the control slot is always set to the same value for all timesteps in the hypothetical simulation range.
• These hypothetical simulation functions are expensive in terms of run time. Following are some approaches to limit slow down from these functions:
– Limit their use as much as possible.
– If you need to call a function multiple times per timestep with the same arguments, create a helper function with no arguments; functions with no arguments are executed once per timestep and the results are cached for later use.
– Only include the relevant objects in the subbasin; cloning objects and copying values is time and memory expensive.
– Only include as many fixed values as necessary. If you are only solving for the target slot value at t+2, don’t include fixed values from t through t+7. This will lead to unnecessary dispatching of the cloned objects.

Revised: 01/05/2024