Skip to content

Commit 0b3c2d2

Browse files
committed
Initial changes to CEnthalpyModel::RouteMassinReservoir, Reservoir.cpp and Reservoir.h to introduce two lake layers to lake enthalpy model.
1 parent a72e9fd commit 0b3c2d2

File tree

4 files changed

+92
-29
lines changed

4 files changed

+92
-29
lines changed

src/EnergyTransport.cpp

100644100755
Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -270,17 +270,21 @@ double CEnthalpyModel::GetEnergyLossesFromLake(const int p, double &Q_sens, doub
270270
double A_new = pRes->GetSurfaceArea();
271271
double A_old = pRes->GetOldSurfaceArea();
272272
double A_avg = 0.5 * (A_new + A_old);
273+
double V_h_new = pRes->GetHypolimnionStorage ();
274+
double V_h_old = pRes->GetOldHypolimnionStorage ();
273275

274276
CHydroUnit* pHRU=_pModel->GetHydroUnit(pRes->GetHRUIndex());
275277

276278
double Acorr=1.0;
277279

278280
double SW(0), LW(0), LW_in(0), temp_air(0), AET(0);
281+
279282
double hstar(0),ksed(0),Vsed=0.001;
280283
double T_new =ConvertVolumetricEnthalpyToTemperature(_aMres[p] / V_new);
281284
double T_old =ConvertVolumetricEnthalpyToTemperature(_aMres_last[p] / V_old);
282285
double Ts_new=ConvertVolumetricEnthalpyToTemperature(_aMsed[p] / Vsed );
283286
double Ts_old=ConvertVolumetricEnthalpyToTemperature(_aMsed_last[p] / Vsed );
287+
284288

285289
if(pHRU!=NULL) { //otherwise only simulate advective mixing+ rain input
286290

@@ -300,7 +304,7 @@ double CEnthalpyModel::GetEnergyLossesFromLake(const int p, double &Q_sens, doub
300304
}
301305

302306
Q_sens =hstar* A_avg * (temp_air -0.5*(T_new+T_old));
303-
Q_cond =ksed * A_avg * (0.5*(Ts_new+Ts_old)- 0.5*(T_new+T_old));
307+
Q_cond =kdiff * A_avg * (0.5*(Ts_new+Ts_old)- 0.5*(T_new+T_old));
304308
Q_sw_in =(SW )*A_avg;
305309
Q_lw_in =(LW_in )*A_avg;
306310
Q_lw_out=(LW )*A_avg;
@@ -340,15 +344,27 @@ void CEnthalpyModel::RouteMassInReservoir (const int p, //
340344
double tstep=Options.timestep;
341345

342346
if((V_old<=0.0) || (V_new<=0.0)) { Res_mass=ResSedMass=0.0; return;} //handles dried out reservoir/lake
343-
347+
348+
double V_h_new = pRes->GetHypolimnionStorage ();
349+
double V_h_old = pRes->GetOldHypolimnionStorage ();
350+
double V_e_new = V_new-V_h_new;
351+
double V_e_old = V_old-V_h_old;
352+
double Q_dn_new = 0;
353+
double Q_dn_old = 0;
354+
double Q_up_new = 0;
355+
double Q_up_old = 0;
356+
double A_h_new = pRes->GetMixingArea();
357+
double A_h_old = pRes->GetOldMixingArea();
358+
double A_h_avg = 0.5 * (A_h_new + A_h_old);
359+
344360
CHydroUnit* pHRU=_pModel->GetHydroUnit(pRes->GetHRUIndex());
345361

346362
double Acorr=1.0;
347363

348-
double T_old =ConvertVolumetricEnthalpyToTemperature(_aMres_last[p]/V_old);
364+
double T_old =ConvertVolumetricEnthalpyToTemperature(_aMres_last[p]/V_e_old);
349365

350366
double SW(0), LW(0), LW_in(0), temp_air(0), AET(0);
351-
double hstar(0), ksed(0), Vsed=0.001;
367+
double hstar(0);
352368
if(pHRU!=NULL) { //otherwise only simulate advective mixing+ rain input
353369
Acorr =pHRU->GetArea()*M2_PER_KM2/A_avg; //handles the fact that GetAET() returns mm/d normalized by HRU area, not actual area
354370

@@ -359,14 +375,38 @@ void CEnthalpyModel::RouteMassInReservoir (const int p, //
359375
LW =-STEFAN_BOLTZ*EMISS_WATER*pow(T_old+ZERO_CELSIUS,4); //[MJ/m2/d] //TMP DEBUG -time-lagged - should include in the N-R formulation
360376

361377
AET =pRes->GetAET()*Acorr/ MM_PER_METER ; //[m/d]
362-
363-
Vsed =pRes->GetLakebedThickness() * pHRU->GetArea()*M2_PER_KM2;
378+
// Vsed =pRes->GetLakebedThickness() * pHRU->GetArea()*M2_PER_KM2;
364379
hstar =pRes->GetLakeConvectionCoeff(); //[MJ/m2/d/K]
365-
ksed =pRes->GetLakebedConductivity()/0.5/ pRes->GetLakebedThickness();//[MJ/m2/d/K]
380+
// ksed =pRes->GetLakebedConductivity()/0.5/ pRes->GetLakebedThickness();//[MJ/m2/d/K]
366381
}
367382

368-
double T_sed_old=ConvertVolumetricEnthalpyToTemperature(_aMsed_last[p]/Vsed);
369-
383+
double Ts_old=ConvertVolumetricEnthalpyToTemperature(_aMsed_last[p]/V_h_old);
384+
385+
386+
double dens_e,dens_h,vdiff,kdiff;
387+
388+
double a0= 999.842594;
389+
double a1= 6.793952e-2;
390+
double a2=-9.095290e-3;
391+
double a3= 1.001685e-4;
392+
double a4=-1.120083e-6;
393+
double a5= 6.536332e-9;
394+
395+
dens_e = a0+a1*T_old + a2*pow(T_old,2) + a3*pow(T_old,3) +a4*pow(T_old,4)+a5*pow(T_old,5);
396+
dens_h = a0+a1*Ts_old + a2*pow(Ts_old,2) + a3*pow(Ts_old,3) +a4*pow(Ts_old,4)+a5*pow(Ts_old,5);
397+
398+
double N2;
399+
400+
if(dens_e<dens_h){
401+
N2 = -1*GRAVITY/dens_e*(dens_e-dens_h)/1.0;
402+
}
403+
double m = -0.65;
404+
double b = -3.1;
405+
406+
vdiff = pow(10,m*log10(N2)+b)/100/100;
407+
kdiff = vdiff*HCP_WATER*SEC_PER_DAY;
408+
409+
370410
// N-R solution of Crank-nicolson problem as set of two non-linear algebraic equations
371411
// -----------------------------------------------------------------------------------------
372412
//dE /dt=Qh_in-Qh_out+(Rnet*A+P*hrain*A)-ET*rho*LH*A+k*(Tair-T(E))*A+ksed*(Tsed-T(E))*A //[MJ/d]
@@ -393,11 +433,11 @@ void CEnthalpyModel::RouteMassInReservoir (const int p, //
393433

394434
B[0]+=(1.0-0.5*tstep/V_old*Q_old)*_aMres_last[p];
395435
B[0]-=0.5*tstep*hstar*A_old*T_old;
396-
B[0]-=0.5*tstep*ksed *A_avg*T_old;
397-
B[0]+=0.5*tstep*ksed *A_avg*T_sed_old;
436+
B[0]-=0.5*tstep*kdiff *A_avg*T_old;
437+
B[0]+=0.5*tstep*kdiff *A_avg*Ts_old;
398438

399-
B[1] =0.5*tstep*ksed *A_avg*T_old;
400-
B[1]+=_aMsed_last[p]-0.5*tstep*ksed *A_avg*T_sed_old;
439+
B[1] =0.5*tstep*kdiff *A_avg*T_old;
440+
B[1]+=_aMsed_last[p]-0.5*tstep*kdiff *A_avg*Ts_old;
401441

402442
int iter=0;
403443
double change=ALMOST_INF;
@@ -409,28 +449,28 @@ void CEnthalpyModel::RouteMassInReservoir (const int p, //
409449

410450
while (change > tolerance)
411451
{
412-
T_guess = ConvertVolumetricEnthalpyToTemperature(E_guess/V_new);
413-
Ts_guess= ConvertVolumetricEnthalpyToTemperature(Es_guess/Vsed);
452+
T_guess = ConvertVolumetricEnthalpyToTemperature(E_guess/V_e_new);
453+
Ts_guess= ConvertVolumetricEnthalpyToTemperature(Es_guess/V_h_new);
414454

415455
A[0][0] = 1.0 + 0.5 * tstep * Q_new/V_new;
416456
A[1][1] = 1.0;
417457
A[1][0] = 0.0;
418458
A[0][1] = 0.0;
419459
if (E_guess!=0.0){
420460
A[0][0]+= 0.5*tstep*hstar*A_new*T_guess/E_guess;
421-
A[0][0]+= 0.5*tstep*ksed *A_avg*T_guess/E_guess; //[MJ/m2/d/K]*[m2]/[MJ/m3/K] = [m3/d]
422-
A[1][0]-= 0.5*tstep*ksed *A_avg*T_guess/E_guess;
461+
A[0][0]+= 0.5*tstep*kdiff *A_avg*T_guess/E_guess; //[MJ/m2/d/K]*[m2]/[MJ/m3/K] = [m3/d]
462+
A[1][0]-= 0.5*tstep*kdiff *A_avg*T_guess/E_guess;
423463
}
424464
if (Es_guess!=0.0){
425-
A[0][1]-= 0.5*tstep*ksed *A_avg*Ts_guess/Es_guess;
426-
A[1][1]+= 0.5*tstep*ksed *A_avg*Ts_guess/Es_guess;
465+
A[0][1]-= 0.5*tstep*kdiff *A_avg*Ts_guess/Es_guess;
466+
A[1][1]+= 0.5*tstep*kdiff *A_avg*Ts_guess/Es_guess;
427467
}
428468

429469
//J_ij=A_ij+E*dA_ij/dE = Jacobian
430-
J[0][0]=A[0][0]+0.5*tstep*(hstar*A_new+ksed*A_avg) * (TemperatureEnthalpyDerivative(E_guess /V_new)/ V_new);
431-
J[0][1]=A[0][1]-0.5*tstep*( ksed*A_avg) * (TemperatureEnthalpyDerivative(Es_guess/Vsed )/ Vsed );
432-
J[1][0]=A[1][0]-0.5*tstep*( ksed*A_avg) * (TemperatureEnthalpyDerivative(E_guess /V_new)/ V_new);
433-
J[1][1]=A[1][1]+0.5*tstep*( ksed*A_avg) * (TemperatureEnthalpyDerivative(Es_guess/Vsed )/ Vsed );
470+
J[0][0]=A[0][0]+0.5*tstep*(hstar*A_new+kdiff*A_avg) * (TemperatureEnthalpyDerivative(E_guess /V_e_new)/ V_e_new);
471+
J[0][1]=A[0][1]-0.5*tstep*( kdiff*A_avg) * (TemperatureEnthalpyDerivative(Es_guess/V_h_new )/ V_h_new );
472+
J[1][0]=A[1][0]-0.5*tstep*( kdiff*A_avg) * (TemperatureEnthalpyDerivative(E_guess /V_e_new)/ V_e_new);
473+
J[1][1]=A[1][1]+0.5*tstep*( kdiff*A_avg) * (TemperatureEnthalpyDerivative(Es_guess/V_h_new )/ V_h_new );
434474

435475
R[0] =-A[0][0]*E_guess-A[0][1]*Es_guess+B[0];
436476
R[1] =-A[1][0]*E_guess-A[1][1]*Es_guess+B[1];
@@ -440,7 +480,7 @@ void CEnthalpyModel::RouteMassInReservoir (const int p, //
440480
dE = (J[0][1]*R[1]-J[1][1]*R[0])/den;
441481
dEs = (J[1][0]*R[0]-J[0][0]*R[1])/den;
442482

443-
change =sqrt(dE*dE+dEs*dEs)/ V_new / HCP_WATER; //convert to approx temp difference (for >0C water)
483+
change =sqrt(dE*dE+dEs*dEs)/ V_e_new / HCP_WATER; //convert to approx temp difference (for >0C water)
444484

445485
E_guess +=dE;
446486
Es_guess +=dEs;

src/Makefile

100644100755
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ LDFLAGS :=
2525
CXXFLAGS += -std=c++11 -fPIC
2626

2727
# OPTION 1) include netcdf - uncomment following two commands (assumes netCDF path = /usr/local):
28-
#CXXFLAGS += -Dnetcdf
29-
#LDLIBS += -L/usr/local -lnetcdf
28+
CXXFLAGS += -Dnetcdf
29+
LDLIBS += -L/usr/local -lnetcdf
3030

3131
# OPTION 2) include lp_solve for water management optimization- uncomment following two commands (assumes liblpsolve55.a in ../lib/lp_solve_unix/ folder):
32-
CXXFLAGS += -D_LPSOLVE_
33-
LDLIBS += -L../lib/lp_solve_unix -llpsolve55
32+
#CXXFLAGS += -D_LPSOLVE_
33+
#LDLIBS += -L../lib/lp_solve_unix -llpsolve55
3434

3535
# OPTION 3) if you use a OSX/BSD system, uncomment the LDFLAGS line below
3636
# this is to allow for use a 1Gb stack, see http://linuxtoosx.blogspot.ca/2010/10/stack-overflow-increasing-stack-limit.html

src/Reservoir.cpp

100644100755
Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ void CReservoir::BaseConstructor(const string Name,const long SubID)
1818
_SBID=SubID;
1919

2020
_pDownSB=NULL;
21-
21+
// _mixing_depth=1;
2222
_lakebed_thick=1.0;
2323
_lakebed_cond =0.0;
2424
_lake_convcoeff=2.0;
@@ -403,6 +403,14 @@ long CReservoir::GetSubbasinID () const { return _SBID; }
403403
//
404404
double CReservoir::GetStorage () const { return GetVolume(_stage); }
405405

406+
/// \returns reservoir hypoliminion storage [m3]
407+
//
408+
double CReservoir::GetHypolimnionStorage () const { return GetVolume(_stage-_mixing_depth); }
409+
410+
/// \returns reservoir old hypoliminion storage [m3]
411+
//
412+
double CReservoir::GetOldHypolimnionStorage () const { return GetVolume(_stage_last-_mixing_depth); }
413+
406414
//////////////////////////////////////////////////////////////////
407415
/// \returns current stage [m]
408416
//
@@ -449,6 +457,16 @@ double CReservoir::GetSurfaceArea () const { return GetArea(_stage); }
449457
//
450458
double CReservoir::GetOldSurfaceArea () const { return GetArea(_stage_last); }
451459

460+
//////////////////////////////////////////////////////////////////
461+
/// \returns current mixing area [m2]
462+
//
463+
double CReservoir::GetMixingArea () const { return GetArea(_stage-_mixing_depth); }
464+
465+
//////////////////////////////////////////////////////////////////
466+
/// \returns current old mixing area [m2]
467+
//
468+
double CReservoir::GetOldMixingArea () const { return GetArea(_stage_last-_mixing_depth); }
469+
452470
//////////////////////////////////////////////////////////////////
453471
/// \returns lakebed thickness [m]
454472
//

src/Reservoir.h

100644100755
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class CReservoir
5555
string _name; ///< reservoir name
5656
long _SBID; ///< subbasin ID
5757
double _max_capacity; ///< maximum reservoir capacity [m3]
58+
double _mixing_depth;
5859

5960
double _lakebed_thick; ///< lakebed thickness [m]
6061
double _lakebed_cond; ///< lakebed thermal conductivity [MJ/m/K/d]
@@ -178,6 +179,8 @@ class CReservoir
178179

179180
double GetStorage () const; //[m3]
180181
double GetOldStorage () const; //[m3]
182+
double GetHypolimnionStorage () const; //[m3]
183+
double GetOldHypolimnionStorage () const; //[m3]
181184
double GetOutflowRate () const; //[m3/s]
182185
double GetOldOutflowRate () const; //[m3/s]
183186
double GetIntegratedOutflow (const double &tstep) const; //[m3]
@@ -191,6 +194,8 @@ class CReservoir
191194
double GetOldStage () const; //[m]
192195
double GetSurfaceArea () const; //[m2]
193196
double GetOldSurfaceArea () const; //[m2]
197+
double GetMixingArea () const; //[m2]
198+
double GetOldMixingArea () const; //[m2]
194199
double GetLakebedThickness () const; //[m]
195200
double GetLakebedConductivity () const; //[MJ/m/K/d]
196201
double GetLakeConvectionCoeff () const; //[MJ/m2/d/K]

0 commit comments

Comments
 (0)