Skip to content

Commit 472bfe7

Browse files
James CraigJames Craig
authored andcommitted
v525 - state variable overriding, divert_fract [BENCHMARKED]
Support for state variable overriding -new members _nStateVarOverrides/_pStateVarOverrides (Model.h/cpp) -new routine CModel::ApplyStateOverrides() (Model.cpp) -new struct sv_over (Model.h) -new options item sv_override_endtime (RavenInclude.h; ParseInput.cpp) -new commands :StateOverrideEndTime & :OverrideState (ParseInput.cpp;ParseTimeSeriesFile.cpp) -adjust model initialization (ModelInitialize.cpp) -incorporate in main loop (RavenMain.cpp; Raven_BMI.cpp) divert_fract as subbasin property (SubBasin.cpp/.h) bug fix - correct handling of temperature perturbations in AdjustDailyHRUForcings() (HydroUnits.cpp)
1 parent bb7add5 commit 472bfe7

File tree

12 files changed

+203
-13
lines changed

12 files changed

+203
-13
lines changed

src/HydroUnits.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ void CHydroUnit::AdjustDailyHRUForcings(const forcing_type Ftyp, force_struct &F
506506
{
507507
double adjust=0;
508508
for (int n=0;n<nStepsPerDay;n++){
509-
adjust+=1.0*epsilon[n]; //mean multiplicative perturbation over the day -exact for single time step
509+
adjust+=epsilon[n]/nStepsPerDay; //mean multiplicative perturbation over the day -exact for single time step
510510
}
511511
F.temp_daily_min*=adjust; //approximate - uses mean perturbation to adjust extremes
512512
F.temp_daily_max*=adjust; //approximate - uses mean perturbation to adjust extremes
@@ -516,7 +516,7 @@ void CHydroUnit::AdjustDailyHRUForcings(const forcing_type Ftyp, force_struct &F
516516
{
517517
double adjust=0;
518518
for (int n=0;n<nStepsPerDay;n++){
519-
adjust+=epsilon[n];
519+
adjust+=epsilon[n]/nStepsPerDay;
520520
}
521521
F.temp_daily_ave+=adjust; //exact
522522
F.temp_daily_min+=adjust; //approximate - uses mean perturbation to adjust extremes

src/LatFlush.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ void CmvLatFlush::GetLateralExchange( const double * const *state_vars, //ar
223223
double stor,Afrom,Ato;
224224
double to_stor,max_to_stor,max_rate;
225225
double mult=1.0; //default: flush 100%
226+
int p;
226227

227228
for(int q=0; q<_nLatConnections; q++)
228229
{
@@ -235,6 +236,8 @@ void CmvLatFlush::GetLateralExchange( const double * const *state_vars, //ar
235236

236237
if (_divert) {
237238
mult=pHRUs[_kFrom[q]]->GetSurfaceProps()->divert_fract;
239+
p=pHRUs[_kFrom[q]]->GetSubBasinIndex();
240+
mult*=_pModel->GetSubBasin(p)->GetDivertFract();
238241
//cout<<" Lat Flush "<<q<<" kFrom: "<<_kFrom[q]<<" "<<_kTo[q] <<" iFrom: "<<_iFromLat[q]<<" "<< mult << " " << _aFrac[q] << " " << stor << endl;
239242
}
240243

src/Model.cpp

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ CModel::CModel(const int nsoillayers,
3333
_nTransParams=0; _pTransParams=NULL;
3434
_nClassChanges=0; _pClassChanges=NULL;
3535
_nParamOverrides=0; _pParamOverrides=NULL;
36+
_nStateVarOverrides=0;_pStateVarOverrides=NULL;
3637
_nObservedTS=0; _pObservedTS=NULL; _pModeledTS=NULL; _aObsIndex=NULL;
3738
_nObsWeightTS =0; _pObsWeightTS=NULL;
3839
_nDiagnostics=0; _pDiagnostics=NULL;
@@ -192,12 +193,12 @@ CModel::~CModel()
192193
if (_aShouldApplyProcess!=NULL){
193194
for (k=0;k<_nProcesses; k++){delete [] _aShouldApplyProcess[k]; } delete [] _aShouldApplyProcess; _aShouldApplyProcess=NULL;
194195
}
195-
for (kk=0;kk<_nHRUGroups;kk++) {delete _pHRUGroups[kk]; } delete [] _pHRUGroups; _pHRUGroups =NULL;
196-
for (kk=0;kk<_nSBGroups;kk++ ) {delete _pSBGroups[kk]; } delete [] _pSBGroups; _pSBGroups =NULL;
197-
for (j=0;j<_nTransParams;j++) {delete _pTransParams[j]; } delete [] _pTransParams; _pTransParams=NULL;
198-
for (j=0;j<_nClassChanges;j++) {delete _pClassChanges[j]; } delete [] _pClassChanges; _pClassChanges=NULL;
199-
for (j=0;j<_nParamOverrides;j++){delete _pParamOverrides[j];} delete [] _pParamOverrides; _pParamOverrides=NULL;
200-
196+
for (kk=0;kk<_nHRUGroups;kk++) {delete _pHRUGroups[kk]; } delete [] _pHRUGroups; _pHRUGroups =NULL;
197+
for (kk=0;kk<_nSBGroups;kk++ ) {delete _pSBGroups[kk]; } delete [] _pSBGroups; _pSBGroups =NULL;
198+
for (j=0;j<_nTransParams;j++) {delete _pTransParams[j]; } delete [] _pTransParams; _pTransParams=NULL;
199+
for (j=0;j<_nClassChanges;j++) {delete _pClassChanges[j]; } delete [] _pClassChanges; _pClassChanges=NULL;
200+
for (j=0;j<_nParamOverrides;j++) {delete _pParamOverrides[j]; } delete [] _pParamOverrides; _pParamOverrides=NULL;
201+
for (j=0;j<_nStateVarOverrides;j++){delete _pStateVarOverrides[j];} delete [] _pStateVarOverrides; _pStateVarOverrides=NULL;
201202
for (i=0;i<_nPerturbations; i++)
202203
{
203204
delete [] _pPerturbations[i]->eps;
@@ -1308,6 +1309,16 @@ void CModel::AddParameterOverride(param_override *pPO)
13081309
ExitGracefully("CModel::AddParameterOverride: adding NULL override",BAD_DATA);}
13091310
}
13101311
//////////////////////////////////////////////////////////////////
1312+
/// \brief Adds state override to model
1313+
///
1314+
/// \param *pSO [in] (valid) pointer to state override structure to be added to model
1315+
//
1316+
void CModel::AddStateVarOverride(sv_over *pSO)
1317+
{
1318+
if (!DynArrayAppend((void**&)(_pStateVarOverrides),(void*)(pSO),_nStateVarOverrides)){
1319+
ExitGracefully("CModel::AddStateVarOverride: adding NULL override",BAD_DATA);}
1320+
}
1321+
//////////////////////////////////////////////////////////////////
13111322
/// \brief Adds class change to model
13121323
///
13131324
/// \param *pTP [in] (valid) pointer to transient parameter to be added to model
@@ -2699,7 +2710,32 @@ void CModel::ApplyLocalParamOverrrides(const int k, const bool revert)
26992710
}
27002711
}
27012712
}
2702-
2713+
//////////////////////////////////////////////////////////////////
2714+
/// \brief overrides state variables with time series values
2715+
/// \notes called at start of timestep prior to mass energy balance
2716+
///
2717+
/// \param &Options [in] Global model options information
2718+
/// \param &tt [in] Current time structure
2719+
//
2720+
void CModel::ApplyStateOverrrides(const optStruct &Options,const time_struct &tt)
2721+
{
2722+
if (tt.model_time>Options.sv_override_endtime-0.5*Options.timestep){return;}
2723+
int i,k;
2724+
double val;
2725+
int nn=(int)((tt.model_time+TIME_CORRECTION)/Options.timestep);
2726+
for (int j=0;j<_nStateVarOverrides;j++)
2727+
{
2728+
CHRUGroup *pGrp=GetHRUGroup(_pStateVarOverrides[j]->kk);
2729+
for (int k_loc=0;k_loc<pGrp->GetNumHRUs();k_loc++){
2730+
k=pGrp->GetHRU(k_loc)->GetGlobalIndex();
2731+
i= _pStateVarOverrides[j]->sv_ind;
2732+
val=_pStateVarOverrides[j]->pTS->GetSampledValue(nn);
2733+
if (val!=RAV_BLANK_DATA){
2734+
_pHydroUnits[k]->SetStateVarValue(i,val); //DOESNT CHECK FOR MAX OR MIN!
2735+
}
2736+
}
2737+
}
2738+
}
27032739
//////////////////////////////////////////////////////////////////
27042740
/// \brief Recalculates HRU derived parameters
27052741
/// \details Recalculate HRU derived parameters that are based upon time-of-year/day and SVs (storage, temp)

src/Model.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ struct class_change;
4848
class CTransientParam;
4949
class CDemandOptimizer;
5050

51+
struct sv_over { // state variable override structure
52+
CTimeSeries *pTS; ///< time series of overridden state
53+
int kk; ///< HRU Group
54+
int sv_ind; ///< state variable index i
55+
sv_over(CTimeSeries* pT, const int kk_in, const int i) {
56+
pTS=pT; kk=kk_in; sv_ind=i;
57+
}
58+
~sv_over() {delete pTS;}
59+
};
5160
////////////////////////////////////////////////////////////////////
5261
/// \brief Data abstraction for water surface model
5362
/// \details Stores and organizes HRUs and basins, provides access to all
@@ -79,6 +88,9 @@ class CModel: public CModelABC
7988
sv_type *_aStateVarType; ///< type of state variable in unit i [size:_nStateVars]
8089
int *_aStateVarLayer; ///< index of state variable for multilayer variables (e.g., SOIL); [size:_nStateVars] value=DOESNT_EXIST(-1) for unique variables (e.g. SURFACE_WATER)
8190
int _aStateVarIndices[MAX_STATE_VAR_TYPES][MAX_SV_LAYERS]; ///< lookup table for state variable indices; the index of SOIL[1] in a state_var[] array may be returned by aStateVarIndices[(int)(SOIL)][1]
91+
92+
sv_over **_pStateVarOverrides; ///< array of pointers to state variable override time series
93+
int _nStateVarOverrides; ///< number of state variable overrides
8294

8395
int _nSoilVars; ///< number of soil layer storage units
8496

@@ -460,11 +472,12 @@ class CModel: public CModelABC
460472
void AddStateVariables (const sv_type *aSV,
461473
const int *aLev,
462474
const int nSV );
463-
void AddLandUseClass ( CLandUseClass *pLU );
475+
void AddLandUseClass ( CLandUseClass *pLU );
464476
void AddCustomOutput ( CCustomOutput *pCO );
465477
void AddCustomTable ( CCustomTable *pTab );
466478
void AddTransientParameter ( CTransientParam *pTP );
467479
void AddParameterOverride ( param_override *pPO );
480+
void AddStateVarOverride ( sv_over *pSO );
468481
void AddPropertyClassChange (const string HRUgroup,
469482
const class_type tclass,
470483
const string new_class,
@@ -514,6 +527,8 @@ class CModel: public CModelABC
514527

515528
//called during simulation:
516529
//critical simulation routines (called once during each timestep):
530+
void ApplyStateOverrrides (const optStruct &Options,
531+
const time_struct &tt);
517532
void UpdateTransientParams (const optStruct &Options,
518533
const time_struct &tt);
519534
void UpdateHRUForcingFunctions (const optStruct &Options,

src/ModelInitialize.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ void CModel::Initialize(const optStruct &Options)
125125
for (kk=0;kk<_nHRUGroups;kk++){_pHRUGroups [kk]->Initialize(); } //disables HRUs
126126
for (pp=0;pp<_nSBGroups; pp++){_pSBGroups [pp]->Initialize(); } //disables SBs and HRUs
127127

128+
for (j=0;j<_nStateVarOverrides; j++){
129+
_pStateVarOverrides[j]->pTS->Initialize(Options.julian_start_day, Options.julian_start_year, Options.duration, Options.timestep,true,Options.calendar);
130+
}
128131
InitializeParameterOverrides();
129132

130133
// Forcing grids are not "Initialized" here because the derived data have to be populated everytime a new chunk is read

src/ParseInput.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ bool ParseMainInputFile (CModel *&pModel,
330330
Options.assimilate_stage =false;
331331
Options.assim_method =DA_RAVEN_DEFAULT;
332332
Options.assimilation_start =-1.0; //start before simulation
333+
Options.sv_override_endtime =ALMOST_INF;
333334
Options.time_zone =0;
334335
Options.rvl_read_frequency =0.0; //do not read at all
335336
Options.custom_interval =1.0; //daily
@@ -455,9 +456,9 @@ bool ParseMainInputFile (CModel *&pModel,
455456
else if (!strcmp(s[0],":SnapshotHydrograph" )){code=66; }
456457
else if (!strcmp(s[0],":SuppressWarnings" )){code=68; }
457458
else if (!strcmp(s[0],":SuppressOutput" )){code=69; }
458-
else if (!strcmp(s[0],":DontWriteWatershedStorage" )){code=70; }//*//avoid writing WatershedStorage.csv
459+
else if (!strcmp(s[0],":DontWriteWatershedStorage" )){code=70; }//avoid writing WatershedStorage.csv
459460
else if (!strcmp(s[0],":EvaluationMetrics" )){code=71; }
460-
else if (!strcmp(s[0],":EvaluationTime" )){code=72; }//After StartDate or JulianStartDay and JulianStartYear commands
461+
else if (!strcmp(s[0],":EvaluationTime" )){code=72; }//After StartDate commands
461462
else if (!strcmp(s[0],":EvaluationPeriod" )){code=73; }
462463
else if (!strcmp(s[0],":SuppressOutputICs" )){code=75; }
463464
else if (!strcmp(s[0],":WaterYearStartMonth" )){code=76; }
@@ -488,6 +489,7 @@ bool ParseMainInputFile (CModel *&pModel,
488489
else if (!strcmp(s[0],":FEWSParamInfoFile" )){code=111;}
489490
else if (!strcmp(s[0],":FEWSBasinStateInfoFile" )){code=112;}
490491
else if (!strcmp(s[0],":TimeOfConcentrationMethod" )){code=113;}
492+
else if (!strcmp(s[0],":StateOverrideEndTime" )){code=114;}//AFTER :StartDate,:Calendar commands
491493

492494
else if (!strcmp(s[0],":WriteGroundwaterHeads" )){code=510;}//GWMIGRATE -TO REMOVE
493495
else if (!strcmp(s[0],":WriteGroundwaterFlows" )){code=511;}//GWMIGRATE -TO REMOVE
@@ -1959,6 +1961,18 @@ bool ParseMainInputFile (CModel *&pModel,
19591961
else {ExitGracefully("ParseInput :TimeOfConcentrationMethod: Unrecognized method",BAD_DATA_WARN);}
19601962
break;
19611963
}
1964+
case(114): //--------------------------------------------
1965+
{/*:StateOverrideEndTime [yyyy-mm-dd] [00:00:00]*///AFTER StartDate or JulianStartDay and JulianStartYear commands
1966+
if(Options.noisy) { cout << "State Override End Time" << endl; }
1967+
if(Len<3) { ImproperFormatWarning(":StateOverrideEndTime",p,Options.noisy); break; }
1968+
1969+
time_struct tt;
1970+
tt = DateStringToTimeStruct(s[1],s[2],Options.calendar);
1971+
Options.sv_override_endtime=TimeDifference(Options.julian_start_day,Options.julian_start_year,tt.julian_day,tt.year,Options.calendar);
1972+
if(Options.forecast_shift!=0) { Options.sv_override_endtime+=Options.forecast_shift; }
1973+
1974+
break;
1975+
}
19621976
case(160): //--------------------------------------------
19631977
{/*:rvh_Filename [filename.rvh]*/
19641978
if(Options.noisy) { cout <<"rvh filename: "<<s[1]<<endl; }

src/ParseTimeSeriesFile.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ bool ParseTimeSeriesFile(CModel *&pModel, const optStruct &Options)
138138
else if (!strcmp(s[0],":AssimilateStreamflow" )){code=101;}
139139
else if (!strcmp(s[0],":SpecifyGaugeForHRU" )){code=102;}
140140
else if (!strcmp(s[0],":AssimilateReservoirStage" )){code=103;}
141+
else if (!strcmp(s[0],":OverrideState" )){code=104;}
141142
//-----------------TRANSPORT--------------------------------
142143
else if (!strcmp(s[0],":FixedConcentrationTimeSeries")){code=300; const_name=s[1];}
143144
else if (!strcmp(s[0],":FixedTemperatureTimeSeries" )){code=300; const_name="TEMPERATURE";}
@@ -1291,6 +1292,32 @@ bool ParseTimeSeriesFile(CModel *&pModel, const optStruct &Options)
12911292
}
12921293
break;
12931294
}
1295+
case(104)://----------------------------------------------
1296+
{/*:OverrideState [state_var] [HRUGroup]
1297+
{yyyy-mm-dd} {hh:mm:ss.0} {double timestep} {int nMeasurements}
1298+
{double val} x nMeasurements [mm]
1299+
:EndOverrideState
1300+
*/
1301+
if (Options.noisy) { cout <<"Override simulated state"<<endl; }
1302+
1303+
int kk=DOESNT_EXIST;
1304+
string grpname=to_string(s[2]);
1305+
CHRUGroup *pHRUgrp=pModel->GetHRUGroup(grpname);
1306+
if (pHRUgrp==NULL){
1307+
ExitGracefully("ParseTimeSeriesFile: bad HRU group name provided in :OverrideState command",BAD_DATA_WARN);
1308+
break;
1309+
}
1310+
kk=pHRUgrp->GetGlobalIndex();
1311+
pTimeSer=CTimeSeries::Parse(p,false,"OverrideState_"+to_string(s[0])+"_"+grpname, kk, "none", Options);
1312+
int layer_ind;
1313+
sv_type typ=pModel->GetStateVarInfo()->StringToSVType(s[1],layer_ind,false);
1314+
1315+
int i=pModel->GetStateVarIndex(typ,layer_ind);
1316+
sv_over *pSO=new sv_over(pTimeSer,kk,i);
1317+
pModel->AddStateVarOverride(pSO);
1318+
1319+
break;
1320+
}
12941321
case (300)://----------------------------------------------
12951322
{/*:FixedConcentrationTimeSeries
12961323
:FixedConcentrationTimeSeries [string constit_name] [string state_var (storage compartment)] {optional HRU Group name}

src/RavenInclude.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,7 @@ struct optStruct
11931193
int nNetCDFattribs; ///< size of array of NetCDF attributes
11941194
int NetCDF_chunk_mem; ///< [MB] size of memory chunk for each forcing grid
11951195
bool in_bmi_mode; ///< true if in BMI mode (no rvt files, no end time)
1196+
double sv_override_endtime; ///< model time [d] after which state variable overrides are disabled (default: 1e99)
11961197
};
11971198

11981199
///////////////////////////////////////////////////////////////////

src/RavenMain.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ int main(int argc, char* argv[])
136136
for(t=t_start; t<Options.duration-TIME_CORRECTION; t+=Options.timestep) // in [d]
137137
{
138138
pModel->UpdateTransientParams (Options,tt);
139+
pModel->ApplyStateOverrrides (Options,tt);
139140
pModel->RecalculateHRUDerivedParams(Options,tt);
140141
pModel->GetEnsemble()->StartTimeStepOps(pModel,Options,tt,e);
141142
pModel->UpdateHRUForcingFunctions (Options,tt);

src/Raven_BMI.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ void CRavenBMI::Initialize(std::string config_file)
215215
void CRavenBMI::Update()
216216
{
217217
pModel->UpdateTransientParams (Options,tt);
218+
pModel->ApplyStateOverrrides (Options,tt);
218219
pModel->RecalculateHRUDerivedParams(Options,tt);
219220
pModel->UpdateHRUForcingFunctions (Options,tt);
220221
pModel->UpdateDiagnostics (Options,tt);

0 commit comments

Comments
 (0)