@@ -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//
187180int CDemandOptimizer::GetDebugLevel () const
@@ -301,18 +294,29 @@ void CDemandOptimizer::AddWaterDemand(CDemand* pDem)
301294//
302295void 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//
604612void 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}
663667string 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;
0 commit comments