# RiverWare_Ruleset 7.1 Development # Created 12:50 January 26, 2017 # RULESET NAME "Iterative MRM Rules Set"; AGENDA_ORDER ASCENDING; DESCRIPTION ""; PRECISION 8; BEGIN POLICY_GROUP "Previous Run Analysis"; DESCRIPTION ""; ACTIVE TRUE; BEGIN RULE "Output EOY Storage"; DESCRIPTION "Output the EOY reservoir storage for all reservoirs for both the current year and subsequent years (if defined). For subsequent years, only the finish year's storages are output. This rule is called after each run in an iterative MRM run."; ACTIVE TRUE; RULE_EXEC_CONSTRAINT TRUE; BEGIN DESCRIPTION "Copy end of (current) year reservoir storages to integer indexed series slots."; FOREACH (OBJECT res IN "ListSubbasin"( "Reservoir" )) DO % "IterativeMRM_Outputs" & ( res CONCAT "_EOYStorage" ) ["GetRunIndex"( ), "CurrentYear"] := res & "Storage" ["EndOfCurrentYear"( )]; ENDFOREACH; DESCRIPTION "Copy end of (subsequent) year reservoir storages to integer indexed series slots."; IF_STATEMENT (@"Start Year" != @"Finish Year") THEN FOREACH (OBJECT res IN "ListSubbasin"( "Reservoir" )) DO % "IterativeMRM_Outputs" & ( res CONCAT "_EOYStorage" ) ["GetRunIndex"( ), "SubsequentYears"] := res & "Storage" [@"Finish Timestep"]; ENDFOREACH; END_IF_STATEMENT; END; RULE "Output EOY Account Storage"; DESCRIPTION "Output the EOY account storage for various accounts for both the current year and subsequent years (if defined). For subsequent years, only the finish year's storages are output. This rule is called after each run in an iterative MRM run."; ACTIVE TRUE; RULE_EXEC_CONSTRAINT TRUE; BEGIN DESCRIPTION "Copy end of (current) year account storages to integer indexed series slots."; FOREACH (LIST objectAccount IN "ListOfOutputObjectsAndAccounts"( )) DO % "IterativeMRM_Outputs" & ( ( ( GET @INDEX 0.00000000 FROM objectAccount ) CONCAT "_" CONCAT GET @INDEX 1.00000000 FROM objectAccount ) CONCAT "_EOYStorage" ) ["GetRunIndex"( ), "CurrentYear"] := ( GET @INDEX 0.00000000 FROM objectAccount ) ~ ( ( GET @INDEX 1.00000000 FROM objectAccount ) CONCAT ".Storage" ) ["EndOfCurrentYear"( )]; ENDFOREACH; DESCRIPTION "Copy end of (subsequent) year account storages to integer indexed series slots."; IF_STATEMENT (@"Start Year" != @"Finish Year") THEN FOREACH (LIST objectAccount IN "ListOfOutputObjectsAndAccounts"( )) DO % "IterativeMRM_Outputs" & ( ( ( GET @INDEX 0.00000000 FROM objectAccount ) CONCAT "_" CONCAT GET @INDEX 1.00000000 FROM objectAccount ) CONCAT "_EOYStorage" ) ["GetRunIndex"( ), "SubsequentYears"] := ( GET @INDEX 0.00000000 FROM objectAccount ) ~ ( ( GET @INDEX 1.00000000 FROM objectAccount ) CONCAT ".Storage" ) [@"Finish Timestep"]; ENDFOREACH; END_IF_STATEMENT; END; RULE "Count Days in Article VII"; DESCRIPTION "This rule sums the values in the the RioGrandeCompact.ArticleVIISwitch slot for the current year and for subsequent years (if defined). This essentially counts the number of days in which ArticleVII of the RioGrande Compact is in effect. This rule is called after each run in an iterative MRM run."; ACTIVE TRUE; RULE_EXEC_CONSTRAINT TRUE; BEGIN DESCRIPTION "Count the number of days in Article VII for the current year."; $ "IterativeMRM_Outputs.DaysInArticleVII" ["GetRunIndex"( ), "CurrentYear"] := "SumSlotSkipNaN"( $ "RioGrandeCompact.ArticleVIISwitch", @"Start Timestep", "EndOfCurrentYear"( ) ); DESCRIPTION "Count the number of days in Article VII for the subsequent years (if configured)."; IF_STATEMENT (@"Start Year" != @"Finish Year") THEN $ "IterativeMRM_Outputs.DaysInArticleVII" ["GetRunIndex"( ), "SubsequentYears"] := "SumSlotSkipNaN"( $ "RioGrandeCompact.ArticleVIISwitch", "EndOfCurrentYear"( ) + 1.00000000 "day", @"Finish Timestep" ); END_IF_STATEMENT; END; END; POLICY_GROUP "Run Setup"; DESCRIPTION ""; ACTIVE TRUE; BEGIN RULE "Increment Trace"; DESCRIPTION "Increment the "Trace" on each forecast data object to the next year in the list of years to run in IterativeMRM_Inputs.RunsToMake integer indexed series slot. This rule is called at the beginning of each run in the TracesAndForecasts iterative MRM run configuration."; ACTIVE TRUE; RULE_EXEC_CONSTRAINT TRUE; STOP_ON_NAN; BEGIN FOREACH (STRING periodInModelRun IN { "PreForecast" , "Forecast" , "PostForecast" }) DO FOREACH (STRING forecastLocation IN "InputForecastLocations"( )) DO % "HistoricalYearsForAOPRuns" & periodInModelRun [1.00000000, forecastLocation] := $ "IterativeMRM_Inputs.RunsToMake" ["GetRunIndex"( ), "Year To Run"]; ENDFOREACH; ENDFOREACH; END; END; POLICY_GROUP "General"; DESCRIPTION ""; ACTIVE TRUE; BEGIN RULE "Use Historical Traces"; DESCRIPTION "This rule sets a flag on a data object indicating that the MRM run is going to use historical traces (instead of finding similar years). It is called at the start of each run within a "TracesAndForecasts" iterative MRM run."; ACTIVE TRUE; RULE_EXEC_CONSTRAINT TRUE; BEGIN $ "IterativeMRM_Outputs.UseHistoricalTraces" ["GetRunIndex"( )] := "GetRunIndex"( ); END; RULE "Set Iterative Run Flag"; DESCRIPTION "This rule sets a flag on a data object indicating that an iterative MRM run is in progress. It is called at the start of each run within an iterative run."; ACTIVE TRUE; RULE_EXEC_CONSTRAINT TRUE; BEGIN $ "IterativeMRM_Outputs.IterativeRunFlag" ["GetRunIndex"( )] := "GetRunIndex"( ); END; END; UTILITY_GROUP "Functions"; DESCRIPTION ""; ACTIVE TRUE; BEGIN FUNCTION "StartOfRunEndOfMonth" ( ) RETURN_TYPE DATETIME; SCALE_UNITS ""; DESCRIPTION "This function returns a datetime that represents the end of month for the start month. It does this by processing lots of strings that represent the hours, month, days in that month and year. This function is necessary as iterative rules cannot use the syntax Current Month and there is no other way to get this end of month datetime."; ACTIVE TRUE; PRE_EXEC_DIAG FALSE; POST_EXEC_DIAG FALSE; BEGIN WITH DATETIME startDate = "RunStartDate"( ) DO "GetDate"( "24:00 " CONCAT "GetMonthAsString"( startDate ) CONCAT " " CONCAT "GetWholeNumberAsString"( "GetDaysInMonth"( startDate ) ) CONCAT ", " CONCAT "GetWholeNumberAsString"( "GetYear"( startDate ) ) ) ENDWITH; END; FUNCTION "GetWholeNumberAsString" ( NUMERIC number ) RETURN_TYPE STRING; SCALE_UNITS ""; DESCRIPTION "Convert a number to a string, split the string into a list containing the whole number and decimal portion, then return the whole number portion."; ACTIVE TRUE; PRE_EXEC_DIAG FALSE; POST_EXEC_DIAG FALSE; BEGIN GET @INDEX 0.00000000 FROM "Split"( STRINGIFY number, "." ); END; FUNCTION "EndOfCurrentYear" ( ) RETURN_TYPE DATETIME; SCALE_UNITS ""; DESCRIPTION "Return the DATETIME representing the end of the start year. This is necessary as iterative MRM does not allow you to use the "Current Year" syntax.
"; ACTIVE TRUE; PRE_EXEC_DIAG FALSE; POST_EXEC_DIAG FALSE; BEGIN "GetDate"( "24:00 December 31, " CONCAT "GetWholeNumberAsString"( "GetYear"( @"Start Timestep" ) ) ); END; FUNCTION "ListOfOutputObjectsAndAccounts" ( ) RETURN_TYPE LIST; SCALE_UNITS ""; DESCRIPTION "This is a list of lists where each inner list contains an Object and Account on that object. These are the accounts for which the EOY storage is written to an integer indexed slot."; ACTIVE TRUE; PRE_EXEC_DIAG FALSE; POST_EXEC_DIAG FALSE; BEGIN { { % "Heron" , "MRGCD" } , { % "Heron" , "Albuquerque" } , { % "Heron" , "FederalSanJuan" } , { % "ElVado" , "MRGCD" } , { % "ElVado" , "RioGrande" } , { % "Abiquiu" , "Albuquerque" } , { % "Abiquiu" , "Reclamation" } , { % "ElephantButte" , "NMCredit" } , { % "ElephantButte" , "RioGrande" } }; END; FUNCTION "InputForecastLocations" ( ) RETURN_TYPE LIST; SCALE_UNITS ""; DESCRIPTION ""; ACTIVE TRUE; PRE_EXEC_DIAG TRUE; POST_EXEC_DIAG FALSE; BEGIN { "Lobatos" , "LobatosAnnual" , "RedRiverBlwFishHatchery" , "RioPuebloDeTaosAtLosCordovas" , "EmbudoCreekAtDixon" , "Otowi" , "NrJemez" , "ElVadoInflow" , "RioBlanco" , "NavajoRiver" , "DelNorte" }; END; END; END