Skip to content

Commit 4a20396

Browse files
James CraigJames Craig
authored andcommitted
v487 - MO cleanup; :ReservoirWaterDemand, :DefineControlVariable support
add :ReservoirWaterDemand structure (ParseManagementFile.cpp) added support for !d.xxx (demand) in expressions (DemandExpressionHandling.cpp) support for nested @ts in @lookup() (and other nesting support) (DemandExpressionHandling.cpp) support proper prefix of lp_matrix.csv (DemandOptimization.cpp) properly support :DefineControlVariable parsing by adding spaces to exp (ParseManagementFile.cpp) cleanup: -deprecated @convert : moved units conversions to effectively be handled as named constants (DemandExpressionHandling.cpp) -removed _stage_discharge_as_goal option (DemandOptimization.cpp) bug fixes: -made User time series default to parse type (to use in @cumul() command) (ParseManagementFile.cpp)
1 parent e073434 commit 4a20396

File tree

9 files changed

+313
-355
lines changed

9 files changed

+313
-355
lines changed

src/DemandExpressionHandling.cpp

Lines changed: 84 additions & 89 deletions
Large diffs are not rendered by default.

src/DemandOptimization.cpp

Lines changed: 135 additions & 236 deletions
Large diffs are not rendered by default.

src/DemandOptimization.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,6 @@ class CDemandOptimizer
237237

238238
bool _demands_initialized;//< true if demands have been initialized
239239

240-
bool _stage_discharge_as_goal; //< TMP DEBUG - SET TO TRUE IF SD CURVE IS GOAL INSTEAD OF CONSTRAINT
241-
242240
int _do_debug_level; //< =1 if debug info is to be printed to screen, =2 if LP matrix also printed (full debug), 0 for nothing
243241

244242
//Called during simualtion
@@ -272,9 +270,9 @@ class CDemandOptimizer
272270

273271
int GetDemandIndexFromName(const string dname) const;
274272
double GetNamedConstant (const string s) const;
273+
double GetUnitConversion (const string s) const;
275274
int GetUserDVIndex (const string s) const;
276275
double GetControlVariable (const string s, int &index) const;
277-
//double GetDemandDelivery (const int p) const;
278276
int GetNumUserDVs () const;
279277
int GetDebugLevel () const;
280278
int GetIndexFromDVString (string s) const;

src/EnKF.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ void CEnKFEnsemble::Initialize(const CModel* pModel,const optStruct &Options)
397397
}
398398

399399
for(j=0;j<_nObsDatapoints;j++) {
400-
_output_matrix[e][j]=0; //filled during simulation
400+
_output_matrix[e][j]=0; //filled during simulation in CloseTimeStepOps
401401
}
402402
}
403403

@@ -439,7 +439,7 @@ void CEnKFEnsemble::CloseTimeStepOps(CModel* pModel,optStruct& Options,const tim
439439
AddToStateMatrix(pModel,Options,e);
440440
}
441441

442-
//Build output Matrix
442+
//Build output Matrix
443443
//----------------------------------------------------------
444444
int curr_nn=(int)((tt.model_time+TIME_CORRECTION)/Options.timestep);//current timestep index
445445

@@ -462,6 +462,9 @@ void CEnKFEnsemble::CloseTimeStepOps(CModel* pModel,optStruct& Options,const tim
462462
}
463463
}
464464
}
465+
if (j!=_nObsDatapoints){
466+
ExitGracefully("Indexing issue in EnKF::CloseTimeStepOps: This shouldnt happen.",RUNTIME_ERR);
467+
}
465468
}
466469
//////////////////////////////////////////////////////////////////
467470
/// \brief the EnKF assimilation matrix calculations for updating states

src/Forcings.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ forcing_type GetForcingTypeFromString(const string &forcing_string)
105105
else if (f=="IRRIGATION" ){return F_IRRIGATION; }
106106
else if (f=="TEMP_AVE" ){return F_TEMP_AVE;}
107107
else if (f=="TEMP_MIN" ){return F_TEMP_DAILY_MIN;}
108-
else if (f=="MIN_TEMPERATURE" ){return F_TEMP_DAILY_MIN;}
109-
else if (f=="TEMP_DAILY_MIN" ){return F_TEMP_DAILY_MIN;}
108+
else if (f=="MIN_TEMPERATURE" ){return F_TEMP_DAILY_MIN;}//alias
109+
else if (f=="TEMP_DAILY_MIN" ){return F_TEMP_DAILY_MIN;}//alias
110110
else if (f=="TEMP_MAX" ){return F_TEMP_DAILY_MAX;}
111111
else if (f=="MAX_TEMPERATURE" ){return F_TEMP_DAILY_MAX;}
112-
else if (f=="TEMP_DAILY_MAX" ){return F_TEMP_DAILY_MAX;}
113-
else if (f=="TEMP_DAILY_AVE" ){return F_TEMP_DAILY_AVE;}
112+
else if (f=="TEMP_DAILY_MAX" ){return F_TEMP_DAILY_MAX;}//alias
113+
else if (f=="TEMP_DAILY_AVE" ){return F_TEMP_DAILY_AVE;}//alias
114114
else if (f=="TEMP_MONTH_MAX" ){return F_TEMP_MONTH_MAX;}
115115
else if (f=="TEMP_MONTH_MIN" ){return F_TEMP_MONTH_MIN;}
116116
else if (f=="TEMP_MONTH_AVE" ){return F_TEMP_MONTH_AVE;}
@@ -119,9 +119,9 @@ forcing_type GetForcingTypeFromString(const string &forcing_string)
119119
else if (f=="TEMP_MIN_UNC" ){return F_TEMP_MIN_UNC;}
120120

121121
else if (f=="AIR_DENS" ){return F_AIR_DENS;}
122-
else if (f=="AIR_DENSITY" ){return F_AIR_DENS;}
122+
else if (f=="AIR_DENSITY" ){return F_AIR_DENS;}//alias
123123
else if (f=="AIR_PRES" ){return F_AIR_PRES;}
124-
else if (f=="AIR_PRESSURE" ){return F_AIR_PRES;}
124+
else if (f=="AIR_PRESSURE" ){return F_AIR_PRES;}//alias
125125
else if (f=="REL_HUMIDITY" ){return F_REL_HUMIDITY;}
126126

127127
else if (f=="ET_RADIA" ){return F_ET_RADIA;}
@@ -153,12 +153,6 @@ forcing_type GetForcingTypeFromString(const string &forcing_string)
153153
else if (f=="PRECIP_CONC" ){return F_PRECIP_CONC; }
154154
else if (f=="SUBDAILY_CORR" ){return F_SUBDAILY_CORR;}
155155

156-
else
157-
{
158-
return F_UNRECOGNIZED;
159-
//cout <<"Forcing string:|"<<f<<"|"<<endl;
160-
//ExitGracefully("GetForcingTypeFromString: invalid forcing string",RUNTIME_ERR);
161-
}
162156
return F_UNRECOGNIZED;
163157
}
164158
/////////////////////////////////////////////////////////////////////

src/ParseManagementFile.cpp

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options)
107107

108108
//--Sift through file-----------------------------------------------
109109
firstword=pp->Peek();
110-
if ((firstword == ":DefineDecisionVariable") || (firstword == ":DemandExpression") || (firstword == ":ReturnExpression"))
110+
if ((firstword == ":DefineDecisionVariable") || (firstword == ":DemandExpression") || (firstword == ":ReturnExpression") || (firstword == ":DefineControlVariable"))
111111
{
112112
pp->NextIsMathExp();
113113
}
@@ -175,6 +175,9 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options)
175175
else if(!strcmp(s[0],":DemandLookupTable")) { code=61; }
176176
else if(!strcmp(s[0],":DemandExpression")) { code=62; }
177177
//else if(!strcmp(s[0],":AnnualLicense")) { code=63; }
178+
else if(!strcmp(s[0],":ReservoirWaterDemand")) { code=64; }
179+
else if(!strcmp(s[0],":EndReservoirWaterDemand")) { code=65; }
180+
else if(!strcmp(s[0],":IsUnrestricted")) { code=66; }
178181

179182
else if(!strcmp(s[0],":UserTimeSeries")) { code=70; }
180183

@@ -519,14 +522,15 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options)
519522
//TODO: Would it be better to support @date(), @between, @day_of_year() in general expression??
520523
//:Condition !Q32[0] < 300 + @ts(myTs,0)
521524
//:Condition DATE IS_BETWEEN 1975-01-02 and 2010-01-02
522-
//:Condition DATE > @date(1975-01-02) //[NOT YET SUPPORTED]
523-
//:Condition DATE < @date(2010-01-02) //[NOT YET SUPPORTED]
525+
//:Condition DATE > @date(1975-01-02) //\todo [NOT YET SUPPORTED]
526+
//:Condition DATE < @date(2010-01-02) //\todo [NOT YET SUPPORTED]
524527
//:Condition MONTH = 2
525528
//:Condition DAY_OF_YEAR IS_BETWEEN 173 and 210
526529
//:Condition DAY_OF_YEAR > 174
527530
//:Condition DAY_OF_YEAR < 210
528531
//:Condition DAY_OF_YEAR IS_BETWEEN 300 20 //wraps around
529-
//:Condition @is_between(DAY_OF_YEAR,300,20) = 1 //[NOT YET SUPPORTED]
532+
//:Condition DAY_OF_YEAR IS_BETWEEN Apr-1 Aug-1 //\todo [NOT YET SUPPORTED]
533+
//:Condition @is_between(DAY_OF_YEAR,300,20) = 1 // \todo [NOT YET SUPPORTED]
530534
if (pGoal!=NULL){
531535
bool badcond=false;
532536
exp_condition *pCond = new exp_condition();
@@ -976,7 +980,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options)
976980
break;
977981
}
978982
case (54): //--------------------------------------------
979-
{/*:ReturnDestination [SBID]*/
983+
{/*:ReturnDestination [SBID] */
980984
if(Options.noisy) { cout <<"Return destination ID"<<endl; }
981985
if (pDemand==NULL){
982986
ExitGracefully(":ReturnTimeSeries must be between :WaterDemand and :EndWaterDemand commands.",BAD_DATA_WARN);
@@ -1072,6 +1076,16 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options)
10721076
}
10731077
break;
10741078
}
1079+
case (61): //--------------------------------------------
1080+
{/*:DemandLookupTable
1081+
N
1082+
{Q_i D_i} x N
1083+
:EndDemandLookupTable
1084+
*/
1085+
if(Options.noisy) { cout <<"Demand flow fraction"<<endl; }
1086+
ExitGracefully(":DemandLookupTable.",STUB);
1087+
break;
1088+
}
10751089
case (62): //--------------------------------------------
10761090
{/*:DemandExpression [expression]*/
10771091
if(Options.noisy) { cout <<"Demand expression"<<endl; }
@@ -1098,6 +1112,59 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options)
10981112
}
10991113
break;
11001114
}
1115+
case (63): //--------------------------------------------
1116+
{ /*
1117+
:ReservoirWaterDemand [SBID] [ID] [Name]
1118+
...
1119+
:EndReservoirWaterDemand
1120+
*/
1121+
if(Options.noisy) { cout <<"Reservoir Water demand object"<<endl; }
1122+
if (Len<4){
1123+
ExitGracefully("Incorrect number of terms in :ReservoirWaterDemand command header.",BAD_DATA_WARN);
1124+
}
1125+
else{
1126+
demandSBID =s_to_l(s[1]);
1127+
demand_ID =s_to_i(s[2]);
1128+
demand_name=s[3];
1129+
CSubBasin *pSB=pModel->GetSubBasinByID(demandSBID);
1130+
if (pSB!=NULL) {
1131+
if (pSB->GetReservoir() != NULL) {
1132+
demand_ind=pSB->GetReservoir()->GetNumWaterDemands();
1133+
pDemand=new CDemand(demand_ID,demand_name,demandSBID,true);
1134+
pDemand->SetLocalIndex(demand_ind);
1135+
pSB->GetReservoir()->AddDemand(pDemand);
1136+
pModel->GetDemandOptimizer()->AddWaterDemand(pDemand);
1137+
}
1138+
else
1139+
{
1140+
ExitGracefully("There is no reservoir in the subbasin specified within the :ReservoirWaterDemand command header.",BAD_DATA_WARN);
1141+
break;
1142+
}
1143+
}
1144+
else {
1145+
ExitGracefully("Invalid subbasin ID in :ReservoirWaterDemand command header.",BAD_DATA_WARN);
1146+
break;
1147+
}
1148+
}
1149+
break;
1150+
}
1151+
case (64): //--------------------------------------------
1152+
{/*:EndReservoirWaterDemand*/
1153+
if(Options.noisy) { cout <<"..end reservoir water demand object"<<endl; }
1154+
pDemand=NULL;
1155+
break;
1156+
}
1157+
case (65): //--------------------------------------------
1158+
{/*:IsUnrestricted*/
1159+
if(Options.noisy) { cout <<"Set demand as Unrestricted"<<endl; }
1160+
if (pDemand == NULL) {
1161+
ExitGracefully(":IsUnrestricted command must be between :WaterDemand and :EndWaterDemand commands.",BAD_DATA_WARN);
1162+
}
1163+
else{
1164+
pDO->SetDemandAsUnrestricted(pDemand->GetName());
1165+
}
1166+
break;
1167+
}
11011168
case (70): //---------------------------------------------
11021169
{/*:UserTimeSeries {name} [units]
11031170
{yyyy-mm-dd} {hh:mm:ss.0} {double timestep} {int nMeasurements}
@@ -1106,7 +1173,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options)
11061173
*/
11071174
CTimeSeries *pTimeSer;
11081175
if(Options.noisy) { cout <<"User-specified Time Series"<<endl; }
1109-
pTimeSer=CTimeSeries::Parse(pp,false,s[1], DOESNT_EXIST, "none", Options);
1176+
pTimeSer=CTimeSeries::Parse(pp,true,s[1], DOESNT_EXIST, "none", Options);
11101177
pModel->GetDemandOptimizer()->AddUserTimeSeries(pTimeSer);
11111178
break;
11121179
}
@@ -1146,7 +1213,7 @@ bool ParseManagementFile(CModel *&pModel,const optStruct &Options)
11461213
}//end switch(code)
11471214

11481215
firstword=pp->Peek();
1149-
if ((firstword == ":DefineDecisionVariable") || (firstword == ":DemandExpression") || (firstword == ":ReturnExpression"))
1216+
if ((firstword == ":DefineDecisionVariable") || (firstword == ":DemandExpression") || (firstword == ":ReturnExpression") || (firstword == ":DefineControlVariable"))
11501217
{
11511218
pp->NextIsMathExp();
11521219
}

src/RavenInclude.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ const double MJ_PER_M2_LANGLEY =0.04184;
148148
const double INCH_PER_METER =39.37; ///< [m] to [in]
149149
const double FEET_PER_METER =3.28; ///< [m] to [ft]
150150
const double ACREFTD_PER_CMS =70.0456; ///< [acre-ft/d] to [m3/s]
151+
const double ACREFT_PER_M3 =0.000810714; ///< [acre-ft] to [m3]
151152
const double CFS_PER_CMS =0.0283168; ///< [ft3/s] to [m3/s]
152153
const double CDM_PER_DAY_PER_CMS =86.4; ///< [cdm/day] to [m3/s]
153154
const double MPH_PER_KPH =1.609; ///< [kph] to [mph]

src/TimeSeries.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ void CTimeSeries::Initialize( const double model_start_day, //julian day
278278
}
279279

280280
//////////////////////////////////////////////////////////////////
281-
/// \brief Resamples time series to regular intervals of 1 timestep (tstep) over model duration
281+
/// \brief Resamples time series to regular intervals of 1 timestep (tstep) over model duration, starting with timestep 0 from 0..dt
282282
///
283283
/// \param &tstep [in] Model timestep (in days)
284284
/// \param &model_duration [in] Model simulation duration (in days)
@@ -384,7 +384,7 @@ double CTimeSeries::GetAvgValue(const double &t, const double &tstep) const
384384
//t_loc+tstep is now between n2*_interval and (n2+1)*_interval
385385
double inc;
386386
double blank = 0;
387-
if (t_loc < -TIME_CORRECTION) {return RAV_BLANK_DATA; }
387+
if (t_loc < -TIME_CORRECTION) {return RAV_BLANK_DATA; }
388388
if (t_loc > _nPulses*_interval) {return RAV_BLANK_DATA; }
389389
if (_pulse){
390390
if (n1 == n2){ return _aVal[n1]; }
@@ -404,6 +404,7 @@ double CTimeSeries::GetAvgValue(const double &t, const double &tstep) const
404404
}
405405
}
406406
else{
407+
407408
ExitGracefully("CTimeSeries::GetAvgValue (non-pulse)", STUB);
408409
}
409410
if (blank / tstep > 0.001){return RAV_BLANK_DATA;}
@@ -465,7 +466,7 @@ void CTimeSeries::Multiply (const double &factor)
465466
}
466467
}
467468
///////////////////////////////////////////////////////////////////
468-
/// \brief Returns average value of time series during timestep nn of model simulation
469+
/// \brief Returns average value of time series during timestep nn of model simulation (nn=0..nSteps-1)
469470
/// \notes must be called after resampling
470471
///
471472
/// \param nn [in] time step number (measured from simulation start)

src/WaterDemands.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,10 @@ void CDemand::UpdateDemand(const optStruct &Options,const time_struct& tt)
223223
}
224224
else if (_demType == DEMAND_EXPRESSION)
225225
{
226-
//double val=pModel->GetDO->EvaluateExpression(pExp,tt.model_time);
226+
//double val=_pModel->GetDO->EvaluateExpression(pExp,tt.model_time);
227227
//if (fabs(val-RAV_BLANK_DATA)<REAL_SMALL){_currentDemand=0.0;}
228228
//else {_currentDemand=val;}
229-
ExitGracefully("UpdateDEmand::DEMAND_PCT",STUB);
229+
ExitGracefully("UpdateDEmand::DEMAND_EXPRESSION",STUB);
230230
}
231231
/*
232232
else if (_demType == DEM_SOIL_MOISTURE) {
@@ -253,7 +253,7 @@ void CDemand::UpdateDemand(const optStruct &Options,const time_struct& tt)
253253
}
254254
else if (_retType == RETURN_EXPRESSION)
255255
{
256-
256+
ExitGracefully("UpdateDEmand::RETURN_EXPRESSION",STUB);
257257
}
258258
_currentRetTarget=min(_currentRetTarget,_currentDemand); //this is likely unnecessary
259259
}

0 commit comments

Comments
 (0)