Skip to content

Commit

Permalink
v469 - Water management demand refactoring + irrigation forcing
Browse files Browse the repository at this point in the history
new CDemand class and corresponding refactor; Demand groups up and running (WaterDemands.cpp)
-required significant revisions to DemandOptimization.cpp
-new routines GetDemandGroup(), AddDemandGroup(), AddWaterDemand(), GetNumDemandGroups(), InitializeDemands() (DemandOptimization.cpp)
-added printing of corresponding operating regime to GoalSatisfaction.cpp

Support for new irrigation forcing to represent return flows explicitly
-new forcing function irrigation/F_IRRIGATION (Forcings.cpp;RavenInclude.h)
-adjustment of GetAveragePrecip() to include irrigation (Model.cpp)
-revision to PartitionPrecip.cpp
-adjustment to direct evaporation algorithm (UpdateForcings.cpp)

support for $Bxxx and $Exxx variables in expressions (DEmandExpressionHandling.cpp)

bug fixes:
-proper handling of !Dxxx variable in CheckGoalConditions (DemandExpressionHandling.cpp)
-dont add spaces around - in expression : caused issues with brackets, e.g., !Q123[-3] (ParseLib.cpp)
  • Loading branch information
James Craig authored and James Craig committed Jul 22, 2024
1 parent d53e46c commit ff5b6fe
Show file tree
Hide file tree
Showing 23 changed files with 691 additions and 316 deletions.
63 changes: 45 additions & 18 deletions src/DemandExpressionHandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,11 +151,11 @@ int CDemandOptimizer::GetUserDVIndex(const string s) const
/// \brief retrieves index of native decision variable starting with !
/// \params s [in] - string
/// \returns index of named decision variable, or DOESNT_EXIST if not found
/// supports !Qxxx, !Q.name, !hxxx, !Ixxx, !Dxxx, !Cxxx
/// supports !Qxxx, !Q.name, !hxxx, !Ixxx, !Dxxx, !Cxxx, $Bxxx, $Exxx
//
int CDemandOptimizer::GetIndexFromDVString(string s) const //String in format !Qxxx or !Q.name but not !Qxx[n]
{
if ((s[1] == 'Q') || (s[1] == 'h') || (s[1]=='I')) //Subbasin-indexed
if ((s[1] == 'Q') || (s[1] == 'h') || (s[1]=='I') || (s[1]=='B') || (s[1]=='E')) //Subbasin-indexed
{
if (s[2] == '.') {
string name=s.substr(3);
Expand All @@ -176,7 +176,7 @@ int CDemandOptimizer::GetIndexFromDVString(string s) const //String in format !Q
return _pModel->GetSubBasinIndex(SBID);
}
}
else if ((s[1]=='D') || (s[1]=='C'))
else if ((s[1]=='D') || (s[1]=='C') || (s[1]=='d'))
{
string demandID;
if (s[2] == '.') {demandID=s.substr(3);} //!D.FarmerBobsDemand
Expand Down Expand Up @@ -267,25 +267,25 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t
size_t i3=s.find("(");

if ((i1 != NPOS) && (i2 != NPOS) && (i3==NPOS)) { //array NOT nested within function
string contents=s.substr(i1+1,i2-i1);
//cout<<" BRACKET CONTENTS: ["<<contents<<"]"<<endl;
string contents=s.substr(i1+1,i2-i1-1);
n=s_to_i(contents.c_str());
//cout<<" BRACKET CONTENTS: ["<<contents<<"]"<<" n: "<<n<<endl;
has_brackets=true;
}

//----------------------------------------------------------------------
if ((s[0] == '!') && (has_brackets)) //historical lookup (e.g., !Q102[-2])
if ( ((s[0] == '!') || (s[0] == '$')) && (has_brackets)) //historical lookup (e.g., !Q102[-2])
{
ExitGracefullyIf(n>=0, "ConvertToExpressionTerm:: term in square brackets must be <=0 for historical variables.",BAD_DATA_WARN);
ExitGracefullyIf(n>=0, "ConvertToExpressionTerm:: term in square brackets must be <0 for historical variables.",BAD_DATA_WARN);
ExitGracefullyIf(n<-_nHistoryItems, "ConvertToExpressionTerm:: term in square brackets exceeds the magnitude of the :LookbackDuration", BAD_DATA_WARN);

if ((s[1] == 'Q') || (s[1] == 'D') || (s[1]=='h'))
if ((s[1] == 'Q') || (s[1] == 'D') || (s[1]=='h') || (s[1] == 'B') || (s[1] == 'E'))
{
if (n<0)
{
int p=GetIndexFromDVString(s.substr(0,i1));
if (p == DOESNT_EXIST) {
warn="ConvertToExpressionTerm: invalid subbasin ID in expression"+warnstring;
warn="ConvertToExpressionTerm: invalid subbasin ID ("+s.substr(0,i1)+") in expression"+warnstring;
ExitGracefully(warn.c_str(), BAD_DATA_WARN);
return false;
}
Expand All @@ -300,9 +300,9 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t
return true;

}
}
}
else {
warn="ConvertToExpression:: Unparseable term in expression starting with ! - only !Q, !D, or !h currently supported. "+warnstring;
warn="ConvertToExpression:: Unparseable term in history expression starting with !/$ - only !Q, !D, !h, $B, or $E currently supported. "+warnstring;
ExitGracefully(warn.c_str(), BAD_DATA_WARN);
return false;
}
Expand All @@ -314,7 +314,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t
{
int p=GetIndexFromDVString(s);
if (p == DOESNT_EXIST) {
warn="ConvertToExpressionTerm: invalid subbasin ID in expression"+warnstring;
warn="ConvertToExpressionTerm: invalid subbasin ID ("+s+") in expression"+warnstring;
ExitGracefully(warn.c_str(),BAD_DATA_WARN);
return false;
}
Expand All @@ -324,7 +324,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t
return false;
}
if (_aSBIndices[p] == DOESNT_EXIST) {
warn="ConvertToExpressionTerm: disabled subbasin ID in expression"+warnstring+ ". Expression will be ignored";
warn="ConvertToExpressionTerm: disabled subbasin ID in expression "+warnstring+ ". Expression will be ignored";
WriteWarning(warn.c_str(),true);
return false;
}
Expand Down Expand Up @@ -361,7 +361,7 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t
int d=GetIndexFromDVString(s);

if (d == DOESNT_EXIST) {
warn = "ConvertToExpressionTerm: invalid demand ID or demand from disabled subbasin used in expression " +warnstring +": goal/constraint will be ignored";
warn="ConvertToExpressionTerm: invalid demand ID or demand from disabled subbasin used in expression " +warnstring +": goal/constraint will be ignored";
WriteWarning(warn.c_str(),true);
return false;
}
Expand All @@ -385,6 +385,33 @@ bool CDemandOptimizer::ConvertToExpressionTerm(const string s, expressionTerm* t
return true;
}
//----------------------------------------------------------------------
else if (s[0] == '$')
{
if ((s[1] == 'B') || (s[1] == 'E')) //Subbasin-indexed
{
int p=GetIndexFromDVString(s);
if (p == DOESNT_EXIST) {
warn="ConvertToExpressionTerm: invalid subbasin ID ("+s+") in expression"+warnstring;
ExitGracefully(warn.c_str(),BAD_DATA_WARN);
return false;
}
if (!_pModel->GetSubBasin(p)->IsEnabled()) {
warn="ConvertToExpressionTerm: reference to disabled subbasin "+warnstring+". Constraint/goal will be disabled";
WriteWarning(warn.c_str(),true);
return false;
}
if (_aSBIndices[p] == DOESNT_EXIST) {
warn="ConvertToExpressionTerm: disabled subbasin ID in expression "+warnstring+ ". Expression will be ignored";
WriteWarning(warn.c_str(),true);
return false;
}
term->type=TERM_HISTORY;
term->timeshift=0;
term->p_index=p;
return true;
}
}
//----------------------------------------------------------------------
else if (s.find("@ts(") != NPOS) //time series (e.g., @ts(my_time_series,n)
{
string name;
Expand Down Expand Up @@ -768,9 +795,7 @@ expressionStruct *CDemandOptimizer::ParseExpression(const char **s,
terms[j][k] = new expressionTerm();
terms[j][k]->mult=1.0;
valid=ConvertToExpressionTerm(to_string(s[i]),terms[j][k],lineno,filename);
if (!valid){
return NULL;
}
if (!valid){return NULL; }

//TMP DEBUG
//cout<<" TERM["<<k<<" in "<< j << "]: " << s[i] << " : type = " << TermTypeToString(terms[j][k]->type) << " index : " << terms[j][k]->DV_ind << endl;
Expand Down Expand Up @@ -932,7 +957,7 @@ bool CDemandOptimizer::CheckGoalConditions(const int ii, const int k, const time
dv_value=_aCumDelivery[ind];
}
else if (tmp == 'D') {
dv_value = _pModel->GetSubBasinByID(_aDemandSBIDs[ind])->GetDemandDelivery(_aDemandIndices[ind]);
dv_value=_pModel->GetSubBasinByID(_pDemands[ind]->GetSubBasinID())->GetDemandDelivery(_pDemands[ind]->GetLocalIndex());
}
//todo: support !q, !d, !B, !E, !F, !T
}
Expand Down Expand Up @@ -1213,6 +1238,8 @@ double CDemandOptimizer::EvaluateTerm(expressionTerm **pTerms,const int k, const
if (tmp=='Q'){return _aQhist[_aSBIndices[p]][nshift]; }
else if (tmp=='h'){return _ahhist[_aSBIndices[p]][nshift]; }
else if (tmp=='D'){return _aDhist[_aSBIndices[p]][nshift]; }
else if (tmp=='B'){return _pModel->GetSubBasin(p)->GetSpecifiedInflow(t+pT->timeshift*1.0); } //ASSUMES DAILY TIMESTEP!
else if (tmp=='E'){return _pModel->GetSubBasin(p)->GetEnviroMinFlow (t+pT->timeshift*1.0); } //ASSUMES DAILY TIMESTEP!
else {
ExitGracefully("CDemandOptimizer::EvaluateTerm: Invalid history variable ",BAD_DATA);
}
Expand Down
2 changes: 1 addition & 1 deletion src/DemandGroups.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ void CDemandGroup::Initialize()
if(_disabled)
{
for(int p=0;p<_nDemands;p++){
// _aDemands[p]->Disable(); //this disables constituent demands
//_pDemands[p]->Disable(); //this disables constituent demands
}
}
}
Expand Down
Loading

0 comments on commit ff5b6fe

Please sign in to comment.