# RiverWare_Ruleset 7.1 Development
# Created 11:50 April 7, 2017
#
RULESET
NAME "RBS Ruleset (from model file)";
AGENDA_ORDER ASCENDING;
DESCRIPTION "";
PRECISION 8;
BEGIN
POLICY_GROUP "Both Basins - Set Physical Values";
DESCRIPTION "";
ACTIVE TRUE;
BEGIN
RULE "Set Reservoir Outflow and WU Diversion Requests";
DESCRIPTION "";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT TRUE;
BEGIN
DESCRIPTION "This rule sets both reservoir's outflow equal to the sum of the account outflows.
The LocalTimestep function sets the right timestep to deal with the lag.";
FOREACH (OBJECT res IN "ListSubbasin"( "Reservoir" )) DO
res & "Outflow" ["LocalTimestep"( res )] := "SumAcctSlot"( res, "Outflow", "LocalTimestep"( res ) );
ENDFOREACH;
DESCRIPTION "It also sets each Water User's Diversion Requested equal to the accounting Diversion.";
FOREACH (OBJECT wu IN "ListSubbasin"( "WaterUser" )) DO
wu & "Diversion Requested" ["LocalTimestep"( wu )] := "SumAcctSlot"( wu, "Diversion", "LocalTimestep"( wu ) );
ENDFOREACH;
END;
END;
POLICY_GROUP "Big Res Basin - Set Account Values";
DESCRIPTION "";
ACTIVE TRUE;
BEGIN
RULE "CP2 Instream Flow Allocation";
DESCRIPTION "WU J";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT NOT "HasRuleFiredSuccessfully"( "ThisRule" );
BEGIN
DESCRIPTION "Reallocate but this time include the instream flow rights. Use a date that is equal to or later than the latest instream flow's prioirty date.";
FOREACH (LIST triplet IN "SolveWaterRightsWithLags"( "AllocationSubbasin", "AllocatableFlow", "AccountPriorityDate"( % "CP2", "1971" ) )) DO
( GET @INDEX 0.00000000 FROM triplet ) [GET @INDEX 1.00000000 FROM triplet] := GET @INDEX 2.00000000 FROM triplet;
INACTIVE PRINT STRINGIFY ( GET @INDEX 0.00000000 FROM triplet );
INACTIVE PRINT GET @INDEX 1.00000000 FROM triplet;
INACTIVE PRINT GET @INDEX 2.00000000 FROM triplet;
ENDFOREACH;
END;
RULE "CP1 Instream Flow Allocation";
DESCRIPTION "WU J";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT TRUE;
BEGIN
FOREACH (LIST triplet IN "SolveWaterRightsWithLags"( "AllocationSubbasin", "AllocatableFlow", "AccountPriorityDate"( % "CP1", "1900" ) )) DO
( GET @INDEX 0.00000000 FROM triplet ) [GET @INDEX 1.00000000 FROM triplet] := GET @INDEX 2.00000000 FROM triplet;
INACTIVE PRINT STRINGIFY ( GET @INDEX 0.00000000 FROM triplet );
INACTIVE PRINT GET @INDEX 1.00000000 FROM triplet;
INACTIVE PRINT GET @INDEX 2.00000000 FROM triplet;
ENDFOREACH;
END;
RULE "Set BigRes Acct Releases to BigResProject chain";
DESCRIPTION "";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT NOT "HasRuleFiredSuccessfully"( "ThisRule" );
BEGIN
DESCRIPTION "The the In/Out supply to the demand in the waterUserC data object, limited by avail storage. Do this at the t+1 timestep because of the lag.";
$ "BigRes 1936 to CP2 BigResProject.Supply" [@"t + 1"] := "Min"( "GetDataObject"( % "PumpkinFarmers" ) & "DesiredDiversion" [@"t + 1", 0.00000000], "VolumeToFlow"( $ "BigRes^1936.Storage" [@"t"], @"t" ) );
DESCRIPTION "Set the Div supply (Reach5^BigResProject to WaterUserC^BigResProject) to the same value released above.";
$ "Reach5 BigResProject to PumpkinFarmers BigResProject Div.Supply" [@"t + 1"] := "Min"( "GetDataObject"( % "PumpkinFarmers" ) & "DesiredDiversion" [@"t + 1", 0.00000000], "VolumeToFlow"( $ "BigRes^1936.Storage" [@"t"], @"t" ) );
END;
RULE "Set BigRes Project Acct Diversion to 1922 acct";
DESCRIPTION "";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT TRUE;
BEGIN
DESCRIPTION "Set the supply from BigRes to the 1922 account to make up any allocation shortage with project water. Do this at the t+1 timestep because of the lag.";
$ "BigRes 1936 to KiwiFarmers 1922 Div.Supply" [@"t + 1"] := IF ( $ "KiwiFarmers^1902.Shortage" [@"t + 1"] > 0.00000000 "cfs" )
THEN
"Min"( $ "KiwiFarmers^1902.Shortage" [@"t + 1"], "VolumeToFlow"( $ "BigRes^1936.Storage" [@"t"], @"t" ) ) + NaNToZero ( $ "BigRes 1936 to KiwiFarmers 1922 Div.Supply" [@"t + 1"] ) COMMENTED_BY "On subsequent calls of this rule, add to the value in the supply, on the first call, it will be NaN (zero with the NaNToZero operator)."
ENDIF;
END;
RULE "Set DeepRes Project Out";
DESCRIPTION "";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT TRUE;
BEGIN
DESCRIPTION "Set the DeepResProject water releases out of the 1975 account.";
"DeepResProjectOutflowSupply"( ) [] := IF ( $ "PeanutFarmers^1902.Shortage" [@"t + 1"] > 0.00000000 "cfs" )
THEN
( "Min"( $ "PeanutFarmers^1902.Shortage" [@"t + 1"], "VolumeToFlow"( $ "DeepRes^1975.Storage" [@"t - 1"], @"t" ) ) COMMENTED_BY "Min of the shortage or the remaining storage in the acct." + NaNToZero ( "DeepResProjectDiversionSupply"( ) [@"t + 1"] ) COMMENTED_BY "On subsequent calls of this rule, add to the value in the supply, on the first call, it will be NaN (zero with the NaNToZero operator)." ) / ( 1.00000000 - $ "Reach4_Loss.Loss Fraction Above Base" [@"t", 0.00000000] ) COMMENTED_BY "Release enough to account for losses"
ENDIF COMMENTED_BY "Only release additional water if there is a shortage, i.e. the 1902 water right is not met.";
DESCRIPTION "Set the DeepResProject water diversions to the 1902 account. Because of the lag, set it at t+1.";
"DeepResProjectDiversionSupply"( ) [@"t + 1"] := IF ( $ "PeanutFarmers^1902.Shortage" [@"t + 1"] > 0.00000000 "cfs" )
THEN
"Min"( $ "PeanutFarmers^1902.Shortage" [@"t + 1"], "VolumeToFlow"( $ "DeepRes^1975.Storage" [@"t - 1"], @"t" ) ) COMMENTED_BY "The right amount was released above to deal with the loss, now just divert the reduced amount." + NaNToZero ( "DeepResProjectDiversionSupply"( ) [@"t + 1"] ) COMMENTED_BY "On subsequent calls of this rule, add to the value in the supply, on the first call, it will be NaN (zero with the NaNToZero operator)."
ENDIF;
END;
RULE "Initial Allocation - Deep and Big Res Basin";
DESCRIPTION "WU J";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT NOT "HasRuleFiredSuccessfully"( "ThisRule" );
BEGIN
FOREACH (LIST triplet IN "SolveWaterRightsWithLags"( "AllocationSubbasin", "AllocatableFlow", @"24:00:00 January 1, 1800" )) DO
( GET @INDEX 0.00000000 FROM triplet ) [GET @INDEX 1.00000000 FROM triplet] := GET @INDEX 2.00000000 FROM triplet;
INACTIVE PRINT STRINGIFY ( GET @INDEX 0.00000000 FROM triplet );
INACTIVE PRINT GET @INDEX 1.00000000 FROM triplet;
INACTIVE PRINT GET @INDEX 2.00000000 FROM triplet;
ENDFOREACH;
END;
END;
POLICY_GROUP " Big Res Basin - Initialization";
DESCRIPTION "";
ACTIVE TRUE;
BEGIN
RULE "Set Big Res 1936 to Stop Filling";
DESCRIPTION "";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT NOT "HasRuleFiredSuccessfully"( "ThisRule" );
BEGIN
DESCRIPTION "BigRes should fill until it has accrued enough to fill the conservation pool. To do this, we use
the Fill Factors slot. If not set, it defaults to 1.0 and the Water rights Solver will allocate
water to it in priority. Once the accrual limit has been met, we want to set the Fill Factor
slot to zero. Then the water rights solver will not allocate anything to it.
Alternatively, we could have set the Conservation Pool Initial Empty Space to
zero and it would have done the same thing.";
$ "BigRes^1936.Fill Factors" [@"t + 1"] := IF ( $ "BigRes^1936.Accrual" [@"t"] >= "AccrualToReachTopOfConservationPool"( % "BigRes" ) )
THEN
0.00000000
ENDIF;
END;
RULE "Set BigResOut and WU DivReq";
DESCRIPTION "";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT @"t" == @"Start Timestep";
BEGIN
DESCRIPTION "This rule sets Big Res's outflow equal to the sum of the account outflows. ";
% "BigRes" & "Outflow" [] := "SumAcctSlot"( % "BigRes", "Outflow", @"t" );
DESCRIPTION "It also sets each Water User's Diversion Requested equal to the accounting Diversion.";
FOREACH (OBJECT waterUser IN "ListSubbasin"( "WaterUser" ) SET_INTERSECTION "ListSubbasin"( "BelowLag" )) DO
waterUser & "Diversion Requested" [] := "SumAcctSlot"( waterUser, "Diversion", @"t" );
ENDFOREACH;
END;
END;
POLICY_GROUP "Long Res Basin - Set Account Values";
DESCRIPTION "";
ACTIVE TRUE;
BEGIN
RULE "Set LongRes Project Out to Priority 0";
DESCRIPTION "";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT TRUE;
BEGIN
DESCRIPTION "Set the LongResProject water releases out of the 1975 account.";
"LongResProjectOutflowSupply"( ) [] := IF ( $ "Test^0.Shortage" [@"t"] > 0.00000000 "cfs" )
THEN
( "Min"( "Max"( 0.00000000 "cfs", ( $ "WSC_DiversionLimit^allocatable.Max Outflow" [] - ( $ "WSC_DiversionLimit^allocatable.Outflow" [] + NaNToZero ( $ "WSC_DiversionLimit^LongResProject.Outflow" [] ) ) ) COMMENTED_BY "Limit it by the Canal Capacity" ), "Min"( $ "Test^0.Shortage" [@"t"], "VolumeToFlow"( $ "LongRes^4_1975.Storage" [@"t"], @"t" ) ) ) COMMENTED_BY "Min of the shortage or the remaining storage in the acct." + NaNToZero ( "LongResProjectDiversionSupply"( ) [@"t"] ) COMMENTED_BY "On subsequent calls of this rule, add to the value in the supply, on the first call, it will be NaN (zero with the NaNToZero operator)." )
ENDIF COMMENTED_BY "Only release additional water if there is a shortage, i.e. the 0 water right is not met.";
DESCRIPTION "Set theLongResProject water diversions to the 0 account.";
$ "WSC_2 LongResProject to Test 0 Div.Supply" [@"t"] := IF ( $ "Test^0.Shortage" [@"t"] > 0.00000000 "cfs" )
THEN
"Min"( "Max"( 0.00000000 "cfs", ( $ "WSC_DiversionLimit^allocatable.Max Outflow" [] - ( $ "WSC_DiversionLimit^allocatable.Outflow" [] + NaNToZero ( $ "WSC_DiversionLimit^LongResProject.Outflow" [] ) ) ) COMMENTED_BY "Limit it by the Canal Capacity" ), "Min"( $ "Test^0.Shortage" [@"t"], "VolumeToFlow"( $ "LongRes^4_1975.Storage" [@"t"], @"t" ) ) ) COMMENTED_BY "The right amount was released above, now just divert the reduced amount." + NaNToZero ( $ "WSC_2 LongResProject to Test 0 Div.Supply" [@"t"] ) COMMENTED_BY "On subsequent calls of this rule, add to the value in the supply, on the first call, it will be NaN (zero with the NaNToZero operator)."
ENDIF;
END;
RULE "Set LongRes Project Out Peanut";
DESCRIPTION "";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT TRUE;
BEGIN
DESCRIPTION "Set the DeepResProject water releases out of the 1975 account.";
"LongResProjectOutflowSupply"( ) [] := IF ( $ "PeanutFarmers1^1.Shortage" [@"t"] > 0.00000000 "cfs" )
THEN
( "Min"( $ "PeanutFarmers1^1.Shortage" [@"t"], "VolumeToFlow"( $ "LongRes^4_1975.Storage" [@"t - 1"], @"t" ) ) COMMENTED_BY "Min of the shortage or the remaining storage in the acct." + NaNToZero ( "LongResProjectDiversionSupply"( ) [@"t"] ) COMMENTED_BY "On subsequent calls of this rule, add to the value in the supply, on the first call, it will be NaN (zero with the NaNToZero operator)." )
ENDIF COMMENTED_BY "Only release additional water if there is a shortage, i.e. the 1 water right is not met.";
DESCRIPTION "Set the DeepResProject water diversions to the 1902 account. Because of the lag, set it at t+1.";
"LongResProjectDiversionSupply"( ) [@"t"] := IF ( $ "PeanutFarmers1^1.Shortage" [@"t"] > 0.00000000 "cfs" )
THEN
"Min"( $ "PeanutFarmers1^1.Shortage" [@"t"], "VolumeToFlow"( $ "LongRes^4_1975.Storage" [@"t"], @"t" ) ) COMMENTED_BY "The right amount was released above, now just divert the reduced amount." + NaNToZero ( "LongResProjectDiversionSupply"( ) [@"t"] ) COMMENTED_BY "On subsequent calls of this rule, add to the value in the supply, on the first call, it will be NaN (zero with the NaNToZero operator)."
ENDIF;
END;
RULE "Initial Allocation - Long Res Basin";
DESCRIPTION "WU J";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT NOT "HasRuleFiredSuccessfully"( "ThisRule" );
BEGIN
FOREACH (LIST triplet IN "SolveWaterRightsWithLags"( "allocationBasinLongRes", "allocatable", @"24:00:00 January 2, 1800" )) DO
( GET @INDEX 0.00000000 FROM triplet ) [GET @INDEX 1.00000000 FROM triplet] := GET @INDEX 2.00000000 FROM triplet;
INACTIVE PRINT STRINGIFY ( GET @INDEX 0.00000000 FROM triplet );
INACTIVE PRINT GET @INDEX 1.00000000 FROM triplet;
INACTIVE PRINT GET @INDEX 2.00000000 FROM triplet;
ENDFOREACH;
END;
END;
POLICY_GROUP "Both Basins - Set Initial Requests";
DESCRIPTION "";
ACTIVE TRUE;
BEGIN
RULE "SetInitialRequest";
DESCRIPTION "";
ACTIVE TRUE;
RULE_EXEC_CONSTRAINT @"t" == @"Start Timestep";
BEGIN
DESCRIPTION "Set the Initial Request equal to the water right demand for all timesteps.
Only do this for accounts that have a demand (i.e. not storage accounts that
are trying to fill the conservation pool). This is controlled by the water type "HasWaterRightDemand"";
FOREACH (DATETIME date IN @"Start Timestep" TO @"Finish Timestep") DO
FOREACH (OBJECT obj IN "ObjectsFromWaterType"( "HasWaterRightDemand", "All" )) DO
"GetInitialRequestSlot"( obj, "HasWaterRightDemand" ) [date] := "GetDataObject"( obj ) & "WaterRight" [date, 0.00000000];
ENDFOREACH;
ENDFOREACH;
END;
END;
UTILITY_GROUP "Utility Group";
DESCRIPTION "";
ACTIVE TRUE;
BEGIN
FUNCTION "DeepResProjectDiversionSupply" ( )
RETURN_TYPE SLOT;
SCALE_UNITS "";
DESCRIPTION "";
ACTIVE TRUE;
PRE_EXEC_DIAG FALSE;
POST_EXEC_DIAG FALSE;
BEGIN
$ "Reach6 DeepResProject to PeanutFarmers 1902 Div.Supply";
END;
FUNCTION "DeepResProjectOutflowSupply" ( )
RETURN_TYPE SLOT;
SCALE_UNITS "";
DESCRIPTION "";
ACTIVE TRUE;
PRE_EXEC_DIAG FALSE;
POST_EXEC_DIAG FALSE;
BEGIN
( GET @INDEX 0.00000000 FROM "SupplySlotsFrom1to1"( { { % "DeepRes" , "1975" } }, "ALL", "ALL" ) );
END;
FUNCTION "GetDataObject" ( OBJECT obj )
RETURN_TYPE OBJECT;
SCALE_UNITS "";
DESCRIPTION "";
ACTIVE TRUE;
PRE_EXEC_DIAG FALSE;
POST_EXEC_DIAG FALSE;
BEGIN
"GetObject"( obj CONCAT "_Data" );
END;
FUNCTION "GetInitialRequestSlot" ( OBJECT obj, STRING WaterType )
RETURN_TYPE SLOT;
SCALE_UNITS "";
DESCRIPTION "";
ACTIVE TRUE;
PRE_EXEC_DIAG FALSE;
POST_EXEC_DIAG FALSE;
BEGIN
obj ~ ( ( GET @INDEX 0.00000000 FROM "AccountNamesByWaterType"( obj, WaterType ) ) CONCAT ".Initial Request" );
END;
FUNCTION "LocalTimestep" ( OBJECT obj )
RETURN_TYPE DATETIME;
SCALE_UNITS "";
DESCRIPTION "";
ACTIVE TRUE;
PRE_EXEC_DIAG FALSE;
POST_EXEC_DIAG FALSE;
BEGIN
IF ( obj IN "ListSubbasin"( "AboveLag" ) )
THEN
@"t"
ELSE
@"t + 1"
ENDIF;
END;
FUNCTION "SumAcctSlot" ( OBJECT obj, STRING slot, DATETIME date )
RETURN_TYPE NUMERIC;
SCALE_UNITS "cfs";
DESCRIPTION "";
ACTIVE TRUE;
PRE_EXEC_DIAG FALSE;
POST_EXEC_DIAG TRUE;
BEGIN
FOR ( STRING acct IN "AccountNamesByAccountType"( obj, "ALL" ) ) STAT_SUM
NaNToZero ( obj ~ ( acct CONCAT ( "." CONCAT slot ) ) [date] )
ENDFOR;
END;
FUNCTION "AccrualToReachTopOfConservationPool" ( OBJECT res )
RETURN_TYPE NUMERIC;
SCALE_UNITS "";
DESCRIPTION "";
ACTIVE TRUE;
PRE_EXEC_DIAG FALSE;
POST_EXEC_DIAG FALSE;
BEGIN
"ElevationToStorage"( res, res & "Operating Level Table" [@"t", res & "Top of Conservation Pool" []] ) - res & "Storage" [@"Start Timestep - 1"];
END;
FUNCTION "LongResProjectDiversionSupply" ( )
RETURN_TYPE SLOT;
SCALE_UNITS "";
DESCRIPTION "";
ACTIVE TRUE;
PRE_EXEC_DIAG FALSE;
POST_EXEC_DIAG FALSE;
BEGIN
$ "HenryJimDivReach LongResProject to PeanutFarmers1 1 Div.Supply";
END;
FUNCTION "LongResProjectOutflowSupply" ( )
RETURN_TYPE SLOT;
SCALE_UNITS "";
DESCRIPTION "";
ACTIVE TRUE;
PRE_EXEC_DIAG FALSE;
POST_EXEC_DIAG FALSE;
BEGIN
( GET @INDEX 0.00000000 FROM "SupplySlotsFrom1to1"( { { % "LongRes" , "4_1975" } }, "ALL", "ALL" ) );
END;
END;
END