Skip to content

Commit babadb6

Browse files
James CraigJames Craig
authored andcommitted
v519 - analytical diffusive wave discretization [BENCHMARKED]
updated ROUTE_DIFFUSIVE_WAVE to use analytically derived discrete unit hydrograph terms
1 parent a6141f5 commit babadb6

File tree

4 files changed

+58
-24
lines changed

4 files changed

+58
-24
lines changed

src/CommonFunctions.cpp

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,26 +1729,10 @@ double NashCumDist(const double &t, const double &k, const int &NR)
17291729
/// \return Returns cumulative kinematic wave solution distribution
17301730
//
17311731
//int_0^time L/2/t^(3/2)/sqrt(pi*D)*exp(-(v*t-L)^2/(4*D*t)) dt
1732-
// extreme case (D->0): =1 for v*t<L, 0 otherwise
17331732
double ADRCumDist(const double &t, const double &L, const double &v, const double &D)
17341733
{
17351734
ExitGracefullyIf(D<=0,"ADRCumDist: Invalid diffusivity",RUNTIME_ERR);
17361735

1737-
/* double term =L/2.0*pow(PI*D,-0.5);
1738-
double beta =L/sqrt(D);
1739-
double alpha=v/sqrt(D);
1740-
double dt =t/5000.0; //t in [day] (5000.0 is # of integral divisions)
1741-
double integ=0.0;
1742-
for (double tt=0.5*dt;tt<t;tt+=dt)
1743-
{
1744-
// D: unit = m2 / day
1745-
// [m]/[day]^1.5/[m]/[day]^0.5 * exp([m/day]*[day]-[m])^2/([m]^2)/[day])
1746-
integ+=pow(tt,-1.5)*exp(-((alpha*tt-beta)*(alpha*tt-beta))/4.0/tt);
1747-
// equivalent to (old) version, but more stable since alpha, beta ~1-10 whereas both v^2 and D can be very large
1748-
//integ+=pow(tt,-1.5)*exp(-((v*tt-L)*(v*tt-L))/4.0/D/tt); //old version
1749-
}
1750-
return integ*term*dt;
1751-
*/
17521736
//Analytical- Ogata Banks, 1969
17531737
double F=0;
17541738
if (t<=0){return 0.0;}
@@ -1758,6 +1742,49 @@ double ADRCumDist(const double &t, const double &L, const double &v, const doubl
17581742
F+=0.5*(rvn_erfc((L-v*t)/sqrt(4.0*D*t)));
17591743
return F;
17601744
}
1745+
//////////////////////////////////////////////////////////////////
1746+
/// \brief Calculates integral needed for kinematic wave solution distribution
1747+
///
1748+
/// \param &t time [d]
1749+
/// \param &L reach length [m]
1750+
/// \param &v celerity [m/d]
1751+
/// \param &D diffusivity [m2/d]
1752+
/// \return Returns integral
1753+
//
1754+
//int_0^time L/2/t^(1/2)/sqrt(pi*D)*exp(-(v*t-L)^2/(4*D*t)) dt
1755+
// extreme case (D->0): =1 for v*t<L, 0 otherwise
1756+
double G_integral(const double& t, const double& L, const double& v, const double& D)
1757+
{
1758+
double G=0;
1759+
if (t<=0){return 0.0;}
1760+
if(L < 500*(D/v)) {
1761+
G=-0.5*(exp((v*L)/D)*rvn_erfc((L+v*t)/sqrt(4.0*D*t)));
1762+
}
1763+
G+=0.5*(rvn_erfc((L-v*t)/sqrt(4.0*D*t)));
1764+
return L/v*G;
1765+
}
1766+
//////////////////////////////////////////////////////////////////
1767+
/// \brief Calculates discrete integrated UH corresponding to diffusive wave exact solution
1768+
///
1769+
/// \param n index of unit hydrograph [0..N]
1770+
/// \param &t time [d]
1771+
/// \param &L reach length [m]
1772+
/// \param &v celerity [m/d]
1773+
/// \param &D diffusivity [m2/d]
1774+
/// \return Returns Unit hydrograph - sums to one
1775+
//
1776+
double DiffusiveWaveUH(const int n, const double& L, const double& v, const double& D, const double& dt)
1777+
{
1778+
if (n == 0) {
1779+
return 1.0/dt*(G_integral(0.0,L,v,D)-G_integral(dt,L,v,D))+ADRCumDist(dt,L,v,D)-ADRCumDist(0.0,L,v,D);
1780+
}
1781+
else {
1782+
double UH=1.0/dt*(2*G_integral(n*dt,L,v,D)- G_integral((n-1)*dt,L,v,D)- G_integral((n+1)*dt,L,v,D));
1783+
UH+= -(2*n)*ADRCumDist(n*dt,L,v,D)+(n-1)*ADRCumDist((n-1)*dt,L,v,D)+(n+1)*ADRCumDist((n+1)*dt,L,v,D);
1784+
return UH;
1785+
}
1786+
}
1787+
17611788
//////////////////////////////////////////////////////////////////
17621789
/// \brief Calculates time-varying cumulative kinematic wave solution distribution
17631790
///

src/RavenInclude.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,6 +1682,7 @@ double IncompleteGamma (const double &betat, const double &a);
16821682
double TriCumDist (const double &t, const double &tc, const double &tp);
16831683
double NashCumDist (const double &t, const double &k, const int &NR);
16841684
double ADRCumDist (const double &t, const double &L, const double &v, const double &D);
1685+
double DiffusiveWaveUH (const int n, const double& L, const double& v, const double& D, const double& dt);
16851686
double TimeVaryingADRCumDist(const double &t,const double &L,const double *v,int nv,const double &D,const double &dt);
16861687
void CalcWeightsFromUniformNums(const double* aVals, double* aWeights, const int N);
16871688

src/SubBasin.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,20 +1907,22 @@ void CSubBasin::GenerateRoutingHydrograph(const double &Qin_avg,
19071907
"ROUTE_DIFFUSIVE_WAVE only valid for single-segment rivers",BAD_DATA);
19081908
sum=0.0;
19091909
double cc =_c_ref*SEC_PER_DAY; //[m/day]
1910-
double diffusivity=_diffusivity*SEC_PER_DAY; //[m2/d]
1910+
double diffusivity=_diffusivity*SEC_PER_DAY; //[m2/d]
19111911

19121912
for (n=0;n<_nQinHist;n++)
19131913
{
1914-
_aRouteHydro[n ]=max(ADRCumDist(n*tstep,_reach_length,cc,diffusivity)-sum,0.0);
1915-
sum+=_aRouteHydro[n];
1914+
//_aRouteHydro[n ]=max(ADRCumDist(n*tstep,_reach_length,cc,diffusivity)-sum,0.0);
1915+
//_aRouteHydro[n ]=max(ADRCumDist((n+1)*tstep,_reach_length,cc,diffusivity)-sum,0.0); //upstream weighting approach (as done with in-catchment routing)
1916+
_aRouteHydro[n ]=DiffusiveWaveUH(n,_reach_length,cc,diffusivity,tstep);
1917+
//sum+=_aRouteHydro[n];
19161918
}
1917-
_aRouteHydro[_nQinHist-1]=0.0;//must truncate infinite distrib.
1919+
/*_aRouteHydro[_nQinHist - 1] = 0.0;//must truncate infinite distrib.
19181920
1919-
if (travel_time<tstep){ //very sharp ADR CDF or reach length==0 -override
1921+
if (travel_time<tstep) { //very sharp ADR CDF or reach length==0 -override
19201922
_aRouteHydro[0]=1.0-travel_time/tstep;
19211923
_aRouteHydro[1]=travel_time/tstep;
19221924
for (n=2;n<_nQinHist;n++){_aRouteHydro[n]=0.0;}
1923-
}
1925+
}*/
19241926
}
19251927
//---------------------------------------------------------------
19261928
else if(Options.routing==ROUTE_DIFFUSIVE_VARY)

src/UnitTesting.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,15 +263,19 @@ void ADRCumDistTest()
263263
for(int j=0;j<10;j++) {
264264
v[j]=1.0+5.0*((double)(rand())/RAND_MAX);
265265
}
266-
for(double t=0;t<10;t+=0.125) {
266+
//for(double t=0;t<10;t+=0.125) {
267+
for (int n=0;n<80;n++){
268+
double t=(double)(n)*0.125;
267269
TEST<<t<<",";
268270
for(double D=0.03; D<0.3;D+=0.03) {
269271
//TEST<<ADRCumDist(t,5,1.0,D)<<",";
270-
TEST<<ADRCumDist(t+0.125,5,1.0,D)-ADRCumDist(t,5,1.0,D)<<",";
272+
TEST<<ADRCumDist(t+0.125,0.2,1.0,D)-ADRCumDist(t,0.2,1.0,D)<<",";
273+
TEST<<DiffusiveWaveUH(n,0.2,1.0,D,0.125)<<",";
271274
}
272275
TEST<<endl;
273276
}
274277
TEST<<endl;
278+
ExitGracefully("ADRCumDistTest",SIMULATION_DONE);
275279
for(int j=0;j<10;j++) {
276280
TEST<<v[j]<<",";
277281
}

0 commit comments

Comments
 (0)