Skip to content

Commit 776f204

Browse files
James CraigJames Craig
authored andcommitted
v489 - [BENCHMARKED] - support for frozen wetlands, -template argument, TOTAL_SWE, convolution with transport
Freezing of wetlands (FrozenLake.cpp; PartitionPrecip.cpp) Support for RVP template generation from command line (ParseInput.cpp; RavenMain.cpp) support for convolution + transport (StateVariable.h/.cpp; RavenInclude.h) Added TOTAL_SWE state variable tracking (idea from G. Jost) (RavenInclude.h; Solvers.cpp) added exit gracefully if SAT_WILT>FIELD_CAPACITY (HydroUnits.cpp) handle no name of :OutflowControlStructure (ParseHRUFile.cpp) proper handling of Lakes and wetlands in SNOBAL_HBV (SnowBalance.cpp)
1 parent 80d8cc8 commit 776f204

22 files changed

+156
-111
lines changed

src/CommonFunctions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ string GetProcessName(process_type p)
5050
case(SNOWSQUEEZE): {name="Liquid snow release"; break;}
5151
case(REFREEZE): {name="Snow Refreeze"; break;}
5252
case(SUBLIMATION): {name="Sublimation"; break;}
53-
case(SNOW_BALANCE): {name="Snow Melt & Refreeze"; break;}
53+
case(SNOW_BALANCE): {name="Snow Balance"; break;}
5454
case(GLACIER_MELT): {name="Glacier Melt"; break;}
5555
case(GLACIER_RELEASE): {name="Glacier Release"; break;}
5656
case(GLACIER_INFIL): {name="Glacier Infiltration"; break;}

src/ControlStructures.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ bool COutflowRegime::AreConditionsMet(const time_struct& tt) const
283283
//////////////////////////////////////////////////////////////////
284284
/// \brief returns outflow from control structure for given stage, with prioritized constraints applied
285285
/// \param h [in] stage, in [m]
286-
/// \param Q_start [in] total outflow at start of timestep [m3/s]
286+
/// \param Q_start [in] control structure outflow at start of timestep [m3/s]
287287
/// \returns outflow, in [m3/s]
288288
//
289289
double COutflowRegime::GetOutflow(const double &h, const double &h_start, const double &Q_start, const long &target_SBID, const double &drefelev) const
@@ -293,7 +293,7 @@ double COutflowRegime::GetOutflow(const double &h, const double &h_star
293293

294294
double Q = _pCurve->GetDischarge(h, h_start, Q_start, rivdepth, drefelev);
295295

296-
double dQdt = (Q-Q_start)/tstep;
296+
double dQdt = (Q-Q_start)/tstep; //m3/s/d
297297

298298
//apply constraints here
299299
for (int j = _nConstraints-1; j >=0; j--) //priority from first to last

src/ControlStructures.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class COutflowRegime
7878
void AddRegimeConstraint(RegimeConstraint *pCond);
7979

8080
bool AreConditionsMet(const time_struct &tt) const;
81-
double GetOutflow(const double &h, const double &Qstart, const double &hstart, const long &target_SBID, const double &drefelev) const;
81+
double GetOutflow(const double &h, const double &hstart, const double &Qstart, const long &target_SBID, const double &drefelev) const;
8282
};
8383

8484

src/FrozenLake.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515

1616
//////////////////////////////////////////////////////////////////
1717
/// \brief Implementation of the standard constructor
18-
/// \param cr_type [in] Model of capillary rise selected
19-
/// \param In_index [in] Soil storage unit index from which water is lost
20-
/// \param Out_index [in] Soil storage unit index to which water rises
18+
/// \param lakefreeze_type [in] Model of lake freeze selected
19+
/// \param pTransMod [in] pointer to transport model
20+
/// \param pModel [in] - ponter to hydrologic model
2121
//
2222
CmvFrozenLake::CmvFrozenLake(lakefreeze_type type,
2323
const CTransportModel *pTransMod,
@@ -63,11 +63,10 @@ void CmvFrozenLake::GetParticipatingParamList(string *aP , class_type *aPC , in
6363
{
6464
nP=1;
6565
aP [0]="LAKESNOW_BUFFER_HT"; aPC [0]=CLASS_LANDUSE;
66-
6766
}
6867
else if (_type == LFREEZE_THERMAL)
6968
{
70-
ExitGracefully("LFREEZE_THERMAL",STUB); //need to allow snow buffering
69+
7170
}
7271
else
7372
{
@@ -106,7 +105,8 @@ void CmvFrozenLake::GetRatesOfChange( const double *state_vars,
106105
const time_struct &tt,
107106
double *rates) const
108107
{
109-
if (pHRU->GetHRUType()!=HRU_LAKE){return;}//Lakes only (includes reservoirs)
108+
if ((pHRU->GetHRUType()!=HRU_LAKE) &&
109+
(pHRU->GetHRUType()!=HRU_WETLAND)){return;}//Lakes and wetlands only (includes reservoirs)
110110

111111
double ice_thick=state_vars[iFrom[0]];
112112

@@ -130,6 +130,7 @@ void CmvFrozenLake::GetRatesOfChange( const double *state_vars,
130130
else if (_type == LFREEZE_THERMAL)
131131
{
132132
//just queries thermal model and updates ice thickness variable
133+
// \todo[funct] need to allow snow buffering
133134

134135
ice_thick=state_vars[iFrom[0]];
135136

@@ -142,7 +143,6 @@ void CmvFrozenLake::GetRatesOfChange( const double *state_vars,
142143

143144
rates[0]=(new_ice_thick-ice_thick)/Options.timestep;
144145
}
145-
146146
}
147147

148148
//////////////////////////////////////////////////////////////////

src/HydroUnits.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,11 @@ double CHydroUnit::GetSoilTensionStorageCapacity(const int m) const
278278
ExitGracefullyIf((m<0) || (m>=_pModel->GetNumSoilLayers()),
279279
"CHydroUnit GetSoilTensionStorageCapacity::improper index",BAD_DATA);
280280
#endif
281-
return aThickness[m]*MM_PER_METER*_pSoil[m]->cap_ratio*(_pSoil[m]->field_capacity-_pSoil[m]->sat_wilt);
281+
double storcap=aThickness[m]*MM_PER_METER*_pSoil[m]->cap_ratio*(_pSoil[m]->field_capacity-_pSoil[m]->sat_wilt);
282+
if (storcap<-REAL_SMALL){
283+
ExitGracefully("Wilting point saturation (SAT_WILT) is greater than field capacity (FIELD_CAPACITY) for one or more soil classes, leading to negative tension storage",BAD_DATA);
284+
}
285+
return storcap;
282286
}
283287

284288
//////////////////////////////////////////////////////////////////

src/LandUseClass.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ void CLandUseClass::SetSurfaceProperty(surface_struct &S,
508508
else if (!name.compare("PET_LIN_COEFF" )){S.pet_lin_coeff=value;}
509509
else if (!name.compare("PET_VAP_COEFF" )){S.pet_vap_coeff=value;}
510510
else if (!name.compare("RELHUM_CORR" )){S.relhum_corr=value;}
511+
else if (!name.compare("WINDVEL_CORR" )){S.wind_vel_corr=value;}
511512
else if (!name.compare("WIND_VEL_CORR" )){S.wind_vel_corr=value;}
512513
else if (!name.compare("GR4J_X4" )){S.GR4J_x4=value;}
513514
else if (!name.compare("UBC_ICEPT_FACTOR" )){S.UBC_icept_factor=value;}
@@ -614,6 +615,7 @@ double CLandUseClass::GetSurfaceProperty(const surface_struct &S, string param_n
614615
else if (!name.compare("PET_LIN_COEFF" )){return S.pet_lin_coeff;}
615616
else if (!name.compare("PET_VAP_COEFF" )){return S.pet_vap_coeff;}
616617
else if (!name.compare("RELHUM_CORR" )){return S.relhum_corr;}
618+
else if (!name.compare("WINDVEL_CORR" )){return S.wind_vel_corr;}
617619
else if (!name.compare("WIND_VEL_CORR" )){return S.wind_vel_corr;}
618620
else if (!name.compare("GR4J_X4" )){return S.GR4J_x4;}
619621
else if (!name.compare("UBC_ICEPT_FACTOR" )){return S.UBC_icept_factor;}

src/ParseHRUFile.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,9 @@ CReservoir *ReservoirParse(CParser *p,string name,const CModel *pModel,long long
16571657
if (pContStruct != NULL) {
16581658
ExitGracefully("ReservoirParse: new control structure started before finishing earlier one with :EndOutflowControlStructure",BAD_DATA_WARN);
16591659
}
1660+
1661+
string name="unnamed";
1662+
if (Len>1){name=s[1];}
16601663
long downID=pModel->GetSubBasinByID(SBID)->GetDownstreamID(); //default target basin
16611664
pContStruct=new CControlStructure(s[1],SBID,downID);//assumes SBID appears first
16621665
}

src/ParseInput.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,10 @@ bool ParseInputFiles (CModel *&pModel,
108108
}
109109
ExitGracefully("Cannot find or read .rvi file",BAD_DATA);return false;
110110
}
111-
if (!ParseNetCDFRunInfoFile(pModel, Options, runname_overridden,runmode_overridden)){
112-
ExitGracefully("Cannot find or read NetCDF runinfo file", BAD_DATA); return false;
111+
if (!Options.create_rvp_template) {//otherwise, jump right to parse rvp, where template is created
112+
if (!ParseNetCDFRunInfoFile(pModel, Options, runname_overridden,runmode_overridden)){
113+
ExitGracefully("Cannot find or read NetCDF runinfo file", BAD_DATA); return false;
114+
}
113115
}
114116

115117
// Class Property file (.rvp)
@@ -3531,15 +3533,20 @@ bool ParseMainInputFile (CModel *&pModel,
35313533
} //end while (!end_of_file)
35323534
INPUT.close();
35333535

3536+
// Add TOTAL_SWE state variable if any snow is simulated
3537+
if (pModel->GetStateVarIndex(SNOW) != -1) {
3538+
tmpS[0] = TOTAL_SWE; tmpLev[0]=0; tmpN=1;
3539+
pModel->AddStateVariables(tmpS,tmpLev,tmpN);
3540+
}
3541+
3542+
35343543
//===============================================================================================
35353544
//Check input quality
35363545
//===============================================================================================
35373546
ExitGracefullyIf(Options.timestep<=0,
35383547
"ParseMainInputFile::Must have a postitive time step",BAD_DATA);
35393548
ExitGracefullyIf(Options.duration<0,
35403549
"ParseMainInputFile::Model duration less than zero. Make sure :EndDate is after :StartDate.",BAD_DATA_WARN);
3541-
ExitGracefullyIf((pModel->GetStateVarIndex(CONVOLUTION,0)!=DOESNT_EXIST) && (pModel->GetTransportModel()->GetNumConstituents()>0),
3542-
"ParseMainInputFile: cannot currently perform transport with convolution processes",BAD_DATA);
35433550

35443551
if((Options.nNetCDFattribs>0) && (Options.output_format!=OUTPUT_NETCDF)){
35453552
WriteAdvisory("ParseMainInputFile: NetCDF attributes were specified but output format is not NetCDF.",Options.noisy);

src/ParsePropertyFile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ bool ParseClassPropertiesFile(CModel *&pModel,
217217
}
218218
}
219219

220-
if (Options.create_rvp_template){
220+
if (Options.create_rvp_template){ //can proceed even if .rvp doesnt exist.
221221
CreateRVPTemplate(aPmaster,aPCmaster,nPmaster,Options);
222222
ExitGracefully("Template RVP File Created.",SIMULATION_DONE);
223223
}

src/PartitionPrecip.cpp

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,15 @@ void CmvPrecipitation::Initialize()
5656
if (iFrom[q]==DOESNT_EXIST){iFrom[q]=iAtmos; } //since this routine reacts to presence or absence of individual state variables
5757
}
5858

59-
//lake snow handling
59+
//frozen lake & wetland snow handling
6060
if (pModel->StateVarExists(ICE_THICKNESS))
6161
{
6262
iFrom[13]=pModel->GetStateVarIndex(SNOW); iTo[13]=pModel->GetLakeStorageIndex();
6363
iFrom[14]=pModel->GetStateVarIndex(SNOW_LIQ); iTo[14]=pModel->GetLakeStorageIndex();
6464
iFrom[15]=pModel->GetStateVarIndex(PONDED_WATER); iTo[15]=pModel->GetLakeStorageIndex();
65+
iFrom[16]=pModel->GetStateVarIndex(SNOW); iTo[16]=pModel->GetStateVarIndex(DEPRESSION);
66+
iFrom[17]=pModel->GetStateVarIndex(SNOW_LIQ); iTo[17]=pModel->GetStateVarIndex(DEPRESSION);
67+
iFrom[18]=pModel->GetStateVarIndex(PONDED_WATER); iTo[18]=pModel->GetStateVarIndex(DEPRESSION);
6568
}
6669
}
6770
//////////////////////////////////////////////////////////////////
@@ -167,9 +170,9 @@ void CmvPrecipitation::GetRatesOfChange(const double *state_vars,
167170
int qSnowToLake=13;
168171
int qSnLiqToLake=14;
169172
int qPondToLake=15;
170-
//int qSnowToDep=16;
171-
//int qSnLiqToDep=17;
172-
//int qPondToDep=18;
173+
int qSnowToDep=16;
174+
int qSnLiqToDep=17;
175+
int qPondToDep=18;
173176

174177
//get precipitation information from gauges
175178
total_precip=pHRU->GetForcingFunctions()->precip;//[mm/day]
@@ -237,12 +240,15 @@ void CmvPrecipitation::GetRatesOfChange(const double *state_vars,
237240
rainthru = rainfall;
238241
}
239242

240-
bool lake_frozen=false;
243+
bool lake_frozen =false;
241244
bool wetland_frozen=false;
242245
if (pModel->StateVarExists(ICE_THICKNESS))
243246
{
244247
int iIceThick=pModel->GetStateVarIndex(ICE_THICKNESS);
245-
if (state_vars[iIceThick]>10){lake_frozen=true;}
248+
if (state_vars[iIceThick]>10){ //10mm of ice can support snow?
249+
lake_frozen =true;
250+
wetland_frozen=true;
251+
}
246252
}
247253

248254
if ((pHRU->IsLake()) && (!lake_frozen))
@@ -254,7 +260,7 @@ void CmvPrecipitation::GetRatesOfChange(const double *state_vars,
254260
rates[qLake]=snowthru+rainthru; // in lake, all water just added
255261
}
256262

257-
if (pModel->StateVarExists(ICE_THICKNESS))//all remaining snow and ponded water dumped to lake
263+
if (pModel->StateVarExists(ICE_THICKNESS))//all remaining snow and ponded water dumped to lake \todo[funct]: handle multilayer snowpack models
258264
{
259265
rates[qSnowToLake ]+=state_vars[iSWE ]/Options.timestep;
260266
rates[qSnLiqToLake]+=state_vars[iSnLiq]/Options.timestep;
@@ -264,11 +270,15 @@ void CmvPrecipitation::GetRatesOfChange(const double *state_vars,
264270
{
265271
rates[qDep] =snowthru + rainthru; //all water goes to depression in wetland
266272

267-
/*if (pModel->StateVarExists(ICE_THICKNESS))// \todo[funct]: all remaining snow and ponded water dumped to wetland/depression
273+
if (pModel->StateVarExists(ICE_THICKNESS))//all remaining snow and ponded water dumped to wetland/depression
268274
{
269275
rates[qSnowToDep ]+=state_vars[iSWE ]/Options.timestep;
270276
rates[qSnLiqToDep]+=state_vars[iSnLiq]/Options.timestep;
271-
}*/
277+
}
278+
}
279+
else if (pHRU->GetHRUType() == HRU_WATER)
280+
{
281+
rates[qSW] =snowthru + rainthru; //all water goes to surface water
272282
}
273283
else //regular land, frozen lakes or frozen wetlands - treat snow
274284
{
@@ -307,7 +317,7 @@ void CmvPrecipitation::GetRatesOfChange(const double *state_vars,
307317
rates[qNewSnow]=snowthru;
308318
}
309319

310-
if ( pHRU->IsLake())
320+
if (pHRU->IsLake())
311321
{
312322
if (pHRU->IsLinkedToReservoir()) {
313323
rates[qSW]=rainthru; //handles case when both reservoirs and lake storage used
@@ -325,13 +335,13 @@ void CmvPrecipitation::GetRatesOfChange(const double *state_vars,
325335
{
326336
rates[qDep] =rainthru; //ponded water goes to depression in wetland
327337

328-
/*if (pModel->StateVarExists(ICE_THICKNESS))
338+
if (pModel->StateVarExists(ICE_THICKNESS))
329339
{
330-
rates[qPondToDep ]+=state_vars[iPond ]/Options.timestep; // \todo[funct]: handles on-wetland snowmelt whether ice is present or not
331-
}*/
340+
rates[qPondToDep ]+=state_vars[iPond ]/Options.timestep; //handles on-wetland snowmelt whether ice is present or not
341+
}
332342
}
333343
else{
334-
//everything remaining goes to ponded water variable, usually handled by infiltration & abstraction algorithms
344+
//everything remaining goes to ponded water variable, usually handled by infiltration and/or abstraction algorithms
335345
rates[qPond]=rainthru;
336346
}
337347
}

0 commit comments

Comments
 (0)