Skip to content

Commit 6ceaa70

Browse files
James CraigJames Craig
authored andcommitted
v494 - fixed timelag in :DemandExpression; removed input ordering issue; POTMELT_DD_FREEZE;
added _pUserTimeSeries to remove ordering issue where demands have to be specified before user DVs (DemandOptimization.h/.cpp) - removed DemandsAreInitialized() routine and member - much cleaner (DemandOptimization.cpp/.h/ParseManagementFile.cpp) - support :DeclareWorkflowVar before :DefineWorkflowVar (ParseManagementFile.cpp) - added PrepDemandProblem() to Solvers.cpp support buffer height of zero in Lake Freezing (FrozenLake.cpp) new potential melt routing POTMELT_DD_FREEZE (ModelParamCheck.cpp;PotentialMelt.cpp;ParseInput.cpp;RavenInclude.h) fixed :BedTemperature reading bug in ParseInitialConditionFile.cpp (found by M. Krassovski) (ParseInitialConditionFile.cpp) added potential melt params to RavenAlgParams.dat
1 parent c15b27b commit 6ceaa70

14 files changed

+161
-81
lines changed

src/DemandOptimization.cpp

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ CDemandOptimizer::CDemandOptimizer(CModel *pMod)
3939
_nDecisionVars=0;
4040
_pDecisionVars=NULL;
4141
_nUserDecisionVars=0;
42+
_pUserDecisionVars=NULL;
4243

4344
_nSlackVars=0;
4445
_aSlackValues=NULL;
@@ -68,8 +69,6 @@ CDemandOptimizer::CDemandOptimizer(CModel *pMod)
6869
_nGoals=0;
6970
_pGoals=NULL;
7071

71-
_demands_initialized=false;
72-
7372
_do_debug_level=0;//no debugging
7473

7574
_nSolverResiduals=0;
@@ -86,6 +85,7 @@ CDemandOptimizer::~CDemandOptimizer()
8685
cout<<"DESTROYING DEMAND OPTIMIZER"<<endl;
8786
}
8887
for (int i=0;i<_nDecisionVars; i++){delete _pDecisionVars[i]; }delete [] _pDecisionVars;
88+
for (int i=0;i<_nUserDecisionVars;i++){ }delete [] _pUserDecisionVars;
8989
for (int i=0;i<_nUserTimeSeries; i++){delete _pUserTimeSeries[i]; }delete [] _pUserTimeSeries;
9090
for (int i=0;i<_nUserLookupTables;i++){delete _pUserLookupTables[i];}delete [] _pUserLookupTables;
9191
for (int i=0;i<_nWorkflowVars; i++){delete _pWorkflowVars[i]; }delete [] _pWorkflowVars;
@@ -175,13 +175,6 @@ int CDemandOptimizer::GetNumDemandGroups() const
175175
return _nDemandGroups;
176176
}
177177
//////////////////////////////////////////////////////////////////
178-
/// \brief returns true if demands have been initialized
179-
//
180-
bool CDemandOptimizer::DemandsAreInitialized() const
181-
{
182-
return _demands_initialized;
183-
}
184-
//////////////////////////////////////////////////////////////////
185178
/// \brief returns debug level
186179
//
187180
int CDemandOptimizer::GetDebugLevel() const
@@ -301,18 +294,29 @@ void CDemandOptimizer::AddWaterDemand(CDemand* pDem)
301294
//
302295
void CDemandOptimizer::AddDecisionVar(const decision_var* pDV)
303296
{
304-
if (VariableNameExists(pDV->name)) {
297+
if (VariableNameExists(pDV->name) && (pDV->dvar_type!=DV_USER)) { //otherwise, captures self when user vars added to master list
305298
string warn="CDemandOptimizer::AddDecisionVar: decision variable name "+pDV->name+" is already in use.";
306299
ExitGracefully(warn.c_str(),BAD_DATA_WARN);
307300
}
308301

309302
if (!DynArrayAppend((void**&)(_pDecisionVars),(void*)(pDV),_nDecisionVars)){
310-
ExitGracefully("CDemandOptimizer::AddDecisionVar: adding NULL DV",BAD_DATA);}
303+
ExitGracefully("CDemandOptimizer::AddDecisionVar: adding NULL DV",BAD_DATA);}
311304

312-
if (pDV->dvar_type==DV_USER){
313-
_nUserDecisionVars++;
305+
}
306+
//////////////////////////////////////////////////////////////////
307+
/// \brief adds USER decision variable structure to _pUserDecisionVars member aarray (later added to _pDecisionVars array in RVM initialize)
308+
/// \params pDV [in] - user-specified decision variable to be added
309+
//
310+
void CDemandOptimizer::AddUserDecisionVar(const decision_var* pDV)
311+
{
312+
if (VariableNameExists(pDV->name)) {
313+
string warn="CDemandOptimizer::AddUserDecisionVar: decision variable name "+pDV->name+" is already in use.";
314+
ExitGracefully(warn.c_str(),BAD_DATA_WARN);
314315
}
316+
if (!DynArrayAppend((void**&)(_pUserDecisionVars),(void*)(pDV),_nUserDecisionVars)){
317+
ExitGracefully("CDemandOptimizer::AddUserDecisionVar: adding NULL DV",BAD_DATA);}
315318
}
319+
316320
//////////////////////////////////////////////////////////////////
317321
/// \brief disables stage discharge curve handling for reservoir in subbasin p
318322
//
@@ -323,16 +327,16 @@ void CDemandOptimizer::OverrideSDCurve(const int p)
323327
//////////////////////////////////////////////////////////////////
324328
/// \brief sets bounds for user specified decision variable
325329
//
326-
void CDemandOptimizer::SetDecisionVarBounds(const string name, const double& min, const double& max)
330+
void CDemandOptimizer::SetUserDecisionVarBounds(const string name, const double& min, const double& max)
327331
{
328-
for (int i = 0; i < _nDecisionVars; i++) {
329-
if (_pDecisionVars[i]->name==name){
330-
_pDecisionVars[i]->min=min;
331-
_pDecisionVars[i]->max=max;
332+
for (int i = 0; i < _nUserDecisionVars; i++) {
333+
if (_pUserDecisionVars[i]->name==name){
334+
_pUserDecisionVars[i]->min=min;
335+
_pUserDecisionVars[i]->max=max;
332336
return;
333337
}
334338
}
335-
string warn = "SetDecisionVarBounds: invalid decision variable name (" + name + "): must define before use";
339+
string warn = "SetUserDecisionVarBounds: invalid decision variable name (" + name + "): must declare or define before use";
336340
WriteWarning(warn.c_str(),_pModel->GetOptStruct()->noisy);
337341
}
338342

@@ -414,6 +418,9 @@ bool CDemandOptimizer::VariableNameExists(const string &name) const
414418
for (int i=0; i<_nDecisionVars; i++){
415419
if (_pDecisionVars[i]->name==name){return true;}
416420
}
421+
for (int i=0; i<_nUserDecisionVars; i++){//not yet in _pDecisionVars when called
422+
if (_pUserDecisionVars[i]->name==name){return true;}
423+
}
417424
for (int i = 0; i < _nUserConstants; i++) {
418425
if (_aUserConstNames[i]==name){return true;}
419426
}
@@ -464,6 +471,8 @@ void CDemandOptimizer::Initialize(CModel* pModel, const optStruct& Options)
464471
// Populate ordered decision variable array _pDecisionVars[]
465472
// This order has to be maintained because of how the decision variables are indexed (consistent with GetDVColumnInd())
466473
// subbasin outflows -> reservoir outflows -> reservoir stages -> delivered demand -> user-specified DVs -> slack variables
474+
// demand variables added in InitializeDemands
475+
// user and slack variables added in InitalizePostRVM
467476
//------------------------------------------------------------------
468477
// add subbasin outflow DVs
469478
int SB_count=0;
@@ -596,15 +605,12 @@ void CDemandOptimizer::IdentifyUpstreamDemands()
596605
}
597606
//////////////////////////////////////////////////////////////////
598607
/// \brief Initializes Demand decision variables
599-
/// \notes to be called during .rvm file read, PRIOR to declaring any user-specified DVs, goals, or constraints
600-
/// WHY? because of the expected ordering of decision variables in the GetDVColumnInd() routine
608+
/// Called once at end of RVM read PRIOR to InitializePostRVM()
601609
/// \params pModel [in] - pointer to model
602610
/// \params Options [in] - model options structure
603611
//
604612
void CDemandOptimizer::InitializeDemands(CModel* pModel, const optStruct& Options)
605613
{
606-
if (_demands_initialized){return;}//This routine has already been called
607-
608614
if (Options.noisy){cout<<"CDemandOptimizer: Demand initialization..."<<endl;}
609615

610616
// reserve memory for delivery arrays
@@ -657,8 +663,6 @@ void CDemandOptimizer::InitializeDemands(CModel* pModel, const optStruct& Option
657663
}
658664
}
659665
_nReturns=r;
660-
661-
_demands_initialized=true;
662666
}
663667
string ComparisonToString(comparison C)
664668
{
@@ -708,6 +712,12 @@ void CDemandOptimizer::InitializePostRVMRead(CModel* pModel, const optStruct& Op
708712
}
709713
}
710714

715+
//Add User-defined decision vars to _pDecisionVars array
716+
//------------------------------------------------------------------
717+
for (int i = 0; i < _nUserDecisionVars; i++) {
718+
AddDecisionVar(_pUserDecisionVars[i]);
719+
}
720+
711721
int p;
712722
_nSlackVars = 0;
713723
CSubBasin *pSB;
@@ -730,6 +740,7 @@ void CDemandOptimizer::InitializePostRVMRead(CModel* pModel, const optStruct& Op
730740
}
731741

732742
// Convert reservoir commands to user-specified constraints
743+
// allowed here because it doesnt introduce new DVs
733744
//------------------------------------------------------------------
734745
AddReservoirConstraints();
735746

@@ -1243,14 +1254,31 @@ int CDemandOptimizer::GetDVColumnInd(const dv_type typ, const int counter) const
12431254
return 0;
12441255
}
12451256
//////////////////////////////////////////////////////////////////
1257+
/// \brief prepares demand optimization problem
1258+
/// \notes to be called every time step prior to demand updates and routing mass balance from Solvers.cpp
1259+
/// \params pModel [in] - pointer to model
1260+
/// \params Options [in] - model options structure
1261+
/// \params tt [in] - model time structure
1262+
//
1263+
void CDemandOptimizer::PrepDemandProblem(CModel *pModel, const optStruct &Options, const time_struct &tt)
1264+
{
1265+
// update history arrays from previous timestep
1266+
// ----------------------------------------------------------------
1267+
UpdateHistoryArrays();
1268+
1269+
// evaluates value of all workflow variables for this time step
1270+
// ----------------------------------------------------------------
1271+
UpdateWorkflowVariables(tt,Options);
1272+
}
1273+
//////////////////////////////////////////////////////////////////
12461274
/// \brief Solves demand optimization problem
12471275
/// \notes to be called every time step in lieu of routing mass balance
12481276
/// \params pModel [in] - pointer to model
12491277
/// \params Options [in] - model options structure
12501278
/// \params aSBrunoff [in] - array of current amount of runoff released to each subbasin (m3) [size:nSubBasins]
1251-
/// \params t [in] - local model time
1279+
/// \params tt [in] - model time structure
12521280
//
1253-
void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Options, const double *aSBrunoff,const time_struct &tt )
1281+
void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Options, const double *aSBrunoff,const time_struct &tt)
12541282
{
12551283
#ifdef _LPSOLVE_
12561284

@@ -1274,14 +1302,6 @@ void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Optio
12741302
double *Q_iter =new double [_pModel->GetNumSubBasins()];
12751303
int *lprow =new int [_pModel->GetNumSubBasins()]; //index of goal equation for non-linear reservoir stage discharge curve in subbasin p
12761304

1277-
// update history arrays from previous timestep
1278-
// ----------------------------------------------------------------
1279-
UpdateHistoryArrays();
1280-
1281-
// evaluates value of all workflow variables for this time step
1282-
// ----------------------------------------------------------------
1283-
UpdateWorkflowVariables(tt,Options);
1284-
12851305
// instantiate linear programming solver
12861306
// ----------------------------------------------------------------
12871307
lp_lib::lprec *pLinProg;

src/DemandOptimization.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ class CDemandOptimizer
221221
int _nSlackVars; //< number of slack variables
222222

223223
int _nUserDecisionVars; //< number of user-specified decision variables
224+
decision_var **_pUserDecisionVars; //< array of pointers to user-specified decision vars [size: _nUserDecisionVars] (overlaps content of _pDecisionVars)
224225

225226
int _nUserConstants; //< number of user-specified named constants
226227
string *_aUserConstNames; //< array of names of user-specified constants
@@ -246,8 +247,6 @@ class CDemandOptimizer
246247
ofstream _GOALSAT; //< ofstream for GoalSatisfaction.csv
247248
ofstream _RESID; //< ofstream for OptimizationResidual.csv
248249

249-
bool _demands_initialized;//< true if demands have been initialized
250-
251250
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
252251

253252
//Called during simualtion
@@ -269,6 +268,7 @@ class CDemandOptimizer
269268

270269

271270
//Called during initialization
271+
void AddDecisionVar(const decision_var *pDV);
272272
bool UserTimeSeriesExists(string TSname) const;
273273
void AddReservoirConstraints();
274274
void IdentifyUpstreamDemands();
@@ -295,17 +295,16 @@ class CDemandOptimizer
295295
CDemand *GetWaterDemand (const int d);
296296
int GetNumWaterDemands () const;
297297

298-
bool DemandsAreInitialized() const;
299-
300298
void SetHistoryLength (const int n);
301299
void SetCumulativeDate (const int julian_date, const string demandID);
302300
void SetDebugLevel (const int lev);
303301
void SetDemandAsUnrestricted(const string dname);
304302
void OverrideSDCurve (const int p);
305303

306304
void AddGoalOrConstraint (const managementGoal *pGoal);
307-
void AddDecisionVar (const decision_var *pDV);
308-
void SetDecisionVarBounds (const string name, const double &min, const double &max);
305+
306+
void AddUserDecisionVar (const decision_var *pDV);
307+
void SetUserDecisionVarBounds(const string name, const double &min, const double &max);
309308
void AddUserConstant (const string name, const double &val);
310309
void AddWorkflowVariable (const workflowVar *pCV);
311310
void AddUserTimeSeries (const CTimeSeries *pTS);
@@ -327,6 +326,7 @@ class CDemandOptimizer
327326
void Initialize (CModel *pModel, const optStruct &Options);
328327
void InitializePostRVMRead (CModel *pModel, const optStruct &Options);
329328
void InitializeDemands (CModel *pModel, const optStruct &Options);
329+
void PrepDemandProblem (CModel *pModel, const optStruct &Options, const time_struct &tt);
330330
void SolveDemandProblem (CModel *pModel, const optStruct &Options, const double *aSBrunoff, const time_struct &tt);
331331

332332
void WriteOutputFileHeaders(const optStruct &Options);

src/EnergyTransport.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ class CEnthalpyModel :public CConstituentModel
2626
int _mHyporheic; ///< model soil layer corresponding to hyporheic mixing layer (default=2)
2727
double *_aMinResTime; ///< minimum residence time [d] (<1 dt) in each stream reach [size: nSubBasins]
2828

29-
double *_aBedTemp; ///< array of riverbed temperatures (state variable) [C] [size: nSubBasins]
29+
double *_aBedTemp; ///< array of riverbed temperatures (*state variable*) [C] [size: nSubBasins]
30+
3031
double *_aTave_reach; ///< time-lagged average reach water temperature [C] [size: nSubBasins]
3132
double *_aSS_temperature; ///< array of steady state target temperatures in each basin [C] [size: nSubBasins]
3233

src/FrozenLake.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ void CmvFrozenLake::GetRatesOfChange( const double *state_vars,
120120
double SWE=state_vars[iSWE];
121121

122122
double corr=1.0;
123-
if (SWE>buff_ht ){corr=0.0; }
123+
if (SWE>=buff_ht){corr=0.0; }
124124
else if (SWE<=0.0 ){corr=1.0; }
125125
else {corr=1.0-SWE/buff_ht;}
126126

src/Model.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1737,7 +1737,7 @@ void CModel::OverrideStreamflow (const long long SBID)
17371737
CTimeSeries *pTS =new CTimeSeries(name,*pObs);//copy time series
17381738
pTS->SetLocID(SBID);
17391739

1740-
//need to shift everything by one interval, since hydrographs are stored as period-ending
1740+
//need to shift everything by one interval, since HYDROGRAPHS are stored as period-ending
17411741
pTS->ShiftInTime(-(pTS->GetInterval()),*_pOptStruct);
17421742

17431743
//add as inflow hydrograph to downstream

src/ModelParamCheck.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ void CModel::AddFromPotMeltParamList(string *aP,class_type *aPC,int &nP,const po
107107
aP[nP]="MELT_FACTOR"; aPC[nP]=CLASS_LANDUSE; nP++;
108108
aP[nP]="DD_MELT_TEMP";aPC[nP]=CLASS_LANDUSE; nP++;
109109
}
110+
else if(pot_melt == POTMELT_DD_FREEZE)
111+
{
112+
aP[nP]="MELT_FACTOR"; aPC[nP]=CLASS_LANDUSE; nP++;
113+
aP[nP]="DD_MELT_TEMP";aPC[nP]=CLASS_LANDUSE; nP++;
114+
aP[nP]="REFREEZE_FACTOR";aPC[nP]=CLASS_LANDUSE; nP++;
115+
}
110116
else if(pot_melt==POTMELT_RESTRICTED)
111117
{
112118
aP[nP]="MELT_FACTOR"; aPC[nP]=CLASS_LANDUSE; nP++;

src/ParseInitialConditionFile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ bool ParseInitialConditionsFile(CModel *&pModel, const optStruct &Options)
845845
}
846846
else if (!strcmp(s[0], ":BedTemperature"))
847847
{
848-
if (Len >= 3) {
848+
if (Len >= 2) {
849849
CEnthalpyModel *pEnth=(CEnthalpyModel*)(pConstit);
850850
pEnth->SetBedTemperature (p,s_to_d(s[1]));
851851
}

src/ParseInput.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3733,6 +3733,7 @@ potmelt_method ParsePotMeltMethod(const string s)
37333733
{
37343734
string tmp=StringToUppercase(s);
37353735
if (!strcmp(tmp.c_str(),"POTMELT_DEGREE_DAY")){return POTMELT_DEGREE_DAY;}
3736+
else if (!strcmp(tmp.c_str(),"POTMELT_DD_FREEZE" )){return POTMELT_DD_FREEZE;}
37363737
else if (!strcmp(tmp.c_str(),"POTMELT_EB" )){return POTMELT_EB;}
37373738
else if (!strcmp(tmp.c_str(),"POTMELT_RESTRICTED")){return POTMELT_RESTRICTED;}
37383739
else if (!strcmp(tmp.c_str(),"POTMELT_DD_RAIN" )){return POTMELT_DD_RAIN;}

0 commit comments

Comments
 (0)