void getFluxes(double theta, double lowerDepth) // // Input: upperVolume = vol. depth of upper zone (ft) // upperDepth = depth of upper zone (ft) // Output: none // Purpose: computes water fluxes into/out of upper/lower GW zones. // { double upperDepth; // --- find upper zone depth lowerDepth = MAX(lowerDepth, 0.0); lowerDepth = MIN(lowerDepth, TotalDepth); upperDepth = TotalDepth - lowerDepth; // --- find evaporation from both zones getEvapRates(theta, upperDepth); // --- find percolation rate at upper & lower zone boundaries UpperPerc = getUpperPerc(theta, upperDepth); UpperPerc = MIN(UpperPerc, MaxUpperPerc); // --- find losses to deep GW LowerLoss = A.lowerLossCoeff * lowerDepth / TotalDepth; // --- find GW flow from lower zone to conveyance system node GWFlow = getGWFlow(lowerDepth); if ( GWFlow >= 0.0 ) GWFlow = MIN(GWFlow, MaxGWFlowPos); else GWFlow = MAX(GWFlow, MaxGWFlowNeg); }
void getFluxes(Project* project, double theta, double lowerDepth) // // Input: upperVolume = vol. depth of upper zone (ft) // upperDepth = depth of upper zone (ft) // Output: none // Purpose: computes water fluxes into/out of upper/lower project->GW zones. // { double upperDepth; // --- find upper zone depth lowerDepth = MAX(lowerDepth, 0.0); lowerDepth = MIN(lowerDepth, project->TotalDepth); upperDepth = project->TotalDepth - lowerDepth; // --- save lower depth and theta to global variables project->Hgw = lowerDepth; project->Theta = theta; // --- find evaporation rate from both zones getEvapRates(project,theta, upperDepth); // --- find percolation rate from upper to lower zone project->UpperPerc = getUpperPerc(project,theta, upperDepth); project->UpperPerc = MIN(project->UpperPerc, project->MaxUpperPerc); // --- find loss rate to deep project->GW if ( project->DeepFlowExpr != NULL ) project->LowerLoss = mathexpr_eval(project, project->DeepFlowExpr, getVariableValue) / UCF(project,RAINFALL); else project->LowerLoss = project->A.lowerLossCoeff * lowerDepth / project->TotalDepth; project->LowerLoss = MIN(project->LowerLoss, lowerDepth/project->Tstep); // --- find project->GW flow rate from lower zone to drainage system node project->GWFlow = getGWFlow(project,lowerDepth); if ( project->LatFlowExpr != NULL ) { project->GWFlow += mathexpr_eval(project, project->LatFlowExpr, getVariableValue) / UCF(project, GWFLOW); } if ( project->GWFlow >= 0.0 ) project->GWFlow = MIN(project->GWFlow, project->MaxGWFlowPos); else project->GWFlow = MAX(project->GWFlow, project->MaxGWFlowNeg); }
void getFluxes(double theta, double lowerDepth) // // Input: upperVolume = vol. depth of upper zone (ft) // upperDepth = depth of upper zone (ft) // Output: none // Purpose: computes water fluxes into/out of upper/lower GW zones. // { double upperDepth; // --- find upper zone depth lowerDepth = MAX(lowerDepth, 0.0); lowerDepth = MIN(lowerDepth, TotalDepth); upperDepth = TotalDepth - lowerDepth; // --- save lower depth and theta to global variables Hgw = lowerDepth; Theta = theta; // --- find evaporation rate from both zones getEvapRates(theta, upperDepth); // --- find percolation rate from upper to lower zone UpperPerc = getUpperPerc(theta, upperDepth); UpperPerc = MIN(UpperPerc, MaxUpperPerc); // --- find loss rate to deep GW if ( DeepFlowExpr != NULL ) LowerLoss = mathexpr_eval(DeepFlowExpr, getVariableValue) / UCF(RAINFALL); else LowerLoss = A.lowerLossCoeff * lowerDepth / TotalDepth; LowerLoss = MIN(LowerLoss, lowerDepth/Tstep); // --- find GW flow rate from lower zone to drainage system node GWFlow = getGWFlow(lowerDepth); if ( LatFlowExpr != NULL ) { GWFlow += mathexpr_eval(LatFlowExpr, getVariableValue) / UCF(GWFLOW); } if ( GWFlow >= 0.0 ) GWFlow = MIN(GWFlow, MaxGWFlowPos); else GWFlow = MAX(GWFlow, MaxGWFlowNeg); }
void pavementFluxRates(double x[], double f[]) // // Purpose: computes flux rates from the layers of a porous pavement LID. // Input: x = vector of storage levels // Output: f = vector of flux rates // { double surfaceDepth; // depth of water stored on surface (ft) double paveTheta; // moisture content of pavement voids double storageDepth; // depth of water in storage layer (ft) double pervVolume; // volume/unit area of pervious pavement (ft) double pavePorosity; // pavement porosity double availVolume; double maxRate; double head; //... retrieve state variables from work vector surfaceDepth = x[SURF]; paveTheta = x[SOIL]; storageDepth = x[STOR]; pavePorosity = theLidProc->pavement.voidFrac; //... convert state variables to volumes // (SoilVolume refers to pavement layer) SurfaceVolume = surfaceDepth * theLidProc->surface.voidFrac; pervVolume = theLidProc->pavement.thickness * (1.0 - theLidProc->pavement.impervFrac); SoilVolume = paveTheta * pervVolume; StorageVolume = storageDepth * theLidProc->storage.voidFrac; //... get ET rates (arguments are stored volumes in ft) getEvapRates(SurfaceVolume, SoilVolume, StorageVolume); //... no storage evap if pavement layer saturated if ( paveTheta >= pavePorosity ) StorageEvap = 0.0; //... find nominal rate of surface infiltration into pavement SurfaceInfil = SurfaceInflow + (SurfaceVolume / Tstep); //... find pavement layer permeability (referred to as SoilPerc) SoilPerc = getPavementPermRate(); //... limit pavement permeability to stored water + surface infil. maxRate = SoilVolume/Tstep + SurfaceInfil; SoilPerc = MIN(SoilPerc, maxRate); //... find infiltration rate out of storage layer StorageInfil = getStorageInfilRate(); //... find underdrain flow rate StorageDrain = 0.0; head = storageDepth - theLidProc->drain.offset; if ( theLidProc->drain.coeff > 0.0 && head >= 0.0 ) { if ( storageDepth >= theLidProc->storage.thickness ) { head += (paveTheta) / pavePorosity * theLidProc->pavement.thickness; if ( paveTheta >= pavePorosity ) head += surfaceDepth; } StorageDrain = getStorageDrainRate(head); } //... unit is flooded if ( storageDepth >= theLidProc->storage.thickness && paveTheta >= pavePorosity && SurfaceInfil > MIN_RUNOFF ) { //... pavement outflow can't exceed surface infil SoilPerc = MIN(SurfaceInfil, SoilPerc); //... pavement outflow can't exceed storage outflow maxRate = StorageEvap + StorageDrain + StorageInfil; if ( SoilPerc > maxRate ) { SoilPerc = maxRate; SurfaceInfil = SoilPerc; } //... storage outflow can't exceed pavement perm. else { StorageDrain = MIN(StorageDrain, SoilPerc); StorageInfil = SoilPerc - StorageDrain; } } //... unit not flooded else { //... limit underdrain flow by volume above drain offset if ( StorageDrain > 0.0 ) { maxRate = (storageDepth - theLidProc->drain.offset) * theLidProc->storage.voidFrac / Tstep; StorageDrain = MIN(StorageDrain, maxRate); } //... limit storage infil. by remaining volume maxRate = StorageVolume / Tstep - StorageDrain - StorageEvap; maxRate = MAX(0.0, maxRate); StorageInfil = MIN(StorageInfil, maxRate); //... limit pavement outflow by available storage volume availVolume = (theLidProc->storage.thickness - storageDepth) * theLidProc->storage.voidFrac; maxRate = availVolume/Tstep + StorageEvap + StorageDrain + StorageInfil; maxRate = MAX(maxRate, 0.0); SoilPerc = MIN(SoilPerc, maxRate); //... limit pavement inflow by available pavement volume availVolume = (pavePorosity - paveTheta) * pervVolume; maxRate = availVolume / Tstep + SoilPerc; SurfaceInfil = MIN(SurfaceInfil, maxRate); } //... surface outflow SurfaceOutflow = getSurfaceOutflowRate(surfaceDepth); //... compute overall layer flux rates f[SURF] = SurfaceInflow - SurfaceEvap - SurfaceInfil - SurfaceOutflow; f[SOIL] = (SurfaceInfil - SoilEvap - SoilPerc) / pervVolume; f[STOR] = (SoilPerc - StorageEvap - StorageInfil - StorageDrain) / theLidProc->storage.voidFrac; }
void trenchFluxRates(double x[], double f[]) // // Purpose: computes flux rates from the layers of an infiltration trench LID. // Input: x = vector of storage levels // Output: f = vector of flux rates // { double surfaceDepth; double storageDepth; double head; double availVolume; double maxRate; //... extract zone depth levels from work vector surfaceDepth = x[SURF]; storageDepth = x[STOR]; //... convert depths to volumes SurfaceVolume = surfaceDepth * theLidProc->surface.voidFrac; SoilVolume = 0.0; StorageVolume = storageDepth * theLidProc->storage.voidFrac; availVolume = (theLidProc->storage.thickness - storageDepth) * theLidProc->storage.voidFrac; //... nominal storage inflow StorageInflow = SurfaceInflow + SurfaceVolume / Tstep; //... get ET rate loss for each zone getEvapRates(SurfaceVolume, 0.0, StorageVolume); //... no storage evap if surface ponded if ( surfaceDepth > 0.0 ) StorageEvap = 0.0; //... find infiltration rate out of storage layer StorageInfil = getStorageInfilRate(); //... find underdrain flow rate StorageDrain = 0.0; head = storageDepth - theLidProc->drain.offset; if ( theLidProc->drain.coeff > 0.0 && head >= 0.0 ) { if ( storageDepth >= theLidProc->storage.thickness ) { head += surfaceDepth; } StorageDrain = getStorageDrainRate(head); } //... limit underdrain flow by volume above drain offset if ( StorageDrain > 0.0 ) { maxRate = (storageDepth - theLidProc->drain.offset) * theLidProc->storage.voidFrac / Tstep; //... add on storage inflow if storage is full if ( storageDepth >= theLidProc->storage.thickness ) maxRate += StorageInflow; StorageDrain = MIN(StorageDrain, maxRate); } //... limit storage infil. by remaining volume maxRate = StorageVolume / Tstep - StorageDrain - StorageEvap; maxRate = MAX(0.0, maxRate); StorageInfil = MIN(StorageInfil, maxRate); //... limit storage inflow by available storage volume availVolume = (theLidProc->storage.thickness - storageDepth) * theLidProc->storage.voidFrac; maxRate = availVolume/Tstep + StorageEvap + StorageDrain + StorageInfil; maxRate = MAX(maxRate, 0.0); StorageInflow = MIN(StorageInflow, maxRate); //... equate surface infil to storage inflow SurfaceInfil = StorageInflow; //... find surface outflow rate SurfaceOutflow = getSurfaceOutflowRate(surfaceDepth); // ... find net fluxes for each layer f[SURF] = SurfaceInflow - SurfaceEvap - StorageInflow - SurfaceOutflow / theLidProc->surface.voidFrac;; f[STOR] = (StorageInflow - StorageEvap - StorageInfil - StorageDrain) / theLidProc->storage.voidFrac; f[SOIL] = 0.0; }
void biocellFluxRates(double x[], double f[]) // // Purpose: computes flux rates from the layers of a bio-retention cell LID. // Input: x = vector of storage levels // Output: f = vector of flux rates // { double surfaceDepth; double soilTheta; double storageDepth; double head; double availVolume; double maxRate; //... retrieve state variables from work vector surfaceDepth = x[SURF]; soilTheta = x[SOIL]; storageDepth = x[STOR]; //... convert state variables to volumes SurfaceVolume = surfaceDepth * theLidProc->surface.voidFrac; SoilVolume = soilTheta * theLidProc->soil.thickness; StorageVolume = storageDepth * theLidProc->storage.voidFrac; //... get ET rates availVolume = SoilVolume - theLidProc->soil.wiltPoint * theLidProc->soil.thickness; getEvapRates(SurfaceVolume, availVolume, StorageVolume); //... no storage evap if soil layer saturated if ( soilTheta >= theLidProc->soil.porosity ) StorageEvap = 0.0; //... find soil layer perc rate SoilPerc = getSoilPercRate(soilTheta); //... find infiltration rate out of storage layer StorageInfil = getStorageInfilRate(); //... find underdrain flow rate StorageDrain = 0.0; head = storageDepth - theLidProc->drain.offset; if ( theLidProc->drain.coeff > 0.0 && head >= 0.0 ) { if ( storageDepth >= theLidProc->storage.thickness ) { head += (soilTheta - theLidProc->soil.fieldCap) / (theLidProc->soil.porosity - theLidProc->soil.fieldCap) * theLidProc->soil.thickness; if ( soilTheta >= theLidProc->soil.porosity ) head += surfaceDepth; } StorageDrain = getStorageDrainRate(head); } //... special case of no storage layer present if ( theLidProc->storage.thickness == 0.0 ) { StorageEvap = 0.0; maxRate = MIN(StorageInfil, SoilPerc); SoilPerc = maxRate; StorageInfil = maxRate; } //... both storage & soil layers are saturated else if ( storageDepth >= theLidProc->storage.thickness && soilTheta >= theLidProc->soil.porosity ) { //... soil perc can't exceed storage outflow maxRate = StorageDrain + StorageInfil; if ( SoilPerc > maxRate ) SoilPerc = maxRate; //... storage outflow can't exceed soil perc else { //... use up available drain capacity first StorageDrain = MIN(StorageDrain, SoilPerc); StorageInfil = SoilPerc - StorageDrain; } } //... layers not saturated else { //... limit underdrain flow by volume above drain offset if ( StorageDrain > 0.0 ) { maxRate = (storageDepth - theLidProc->drain.offset) * theLidProc->storage.voidFrac / Tstep; StorageDrain = MIN(StorageDrain, maxRate); } //... limit storage infil. by remaining volume maxRate = StorageVolume / Tstep - StorageDrain - StorageEvap; maxRate = MAX(0.0, maxRate); StorageInfil = MIN(StorageInfil, maxRate); //... limit soil perc by available storage volume availVolume = (theLidProc->storage.thickness - storageDepth) * theLidProc->storage.voidFrac; maxRate = availVolume/Tstep + StorageEvap + StorageDrain + StorageInfil; maxRate = MAX(maxRate, 0.0); SoilPerc = MIN(SoilPerc, maxRate); } //... limit surface infil. by available soil pore volume maxRate = (theLidProc->soil.porosity - soilTheta) * theLidProc->soil.thickness / Tstep + SoilPerc; SurfaceInfil = MIN(SurfaceInfil, maxRate); //... find surface layer outflow rate SurfaceOutflow = getSurfaceOutflowRate(surfaceDepth); //... compute overall layer flux rates f[SURF] = (SurfaceInflow - SurfaceEvap - SurfaceInfil - SurfaceOutflow) / theLidProc->surface.voidFrac; f[SOIL] = (SurfaceInfil - SoilEvap - SoilPerc) / theLidProc->soil.thickness; f[STOR] = (SoilPerc - StorageEvap - StorageInfil - StorageDrain) / theLidProc->storage.voidFrac; }
void greenRoofFluxRates(double x[], double f[]) // // Purpose: computes flux rates from the layers of a green roof. // Input: x = vector of storage levels // Output: f = vector of flux rates // { double surfaceDepth; double soilTheta; double storageDepth; double availVolume; double maxRate; //... retrieve state variables from work vector surfaceDepth = x[SURF]; soilTheta = x[SOIL]; storageDepth = x[STOR]; //... convert state variables to volumes SurfaceVolume = surfaceDepth * theLidProc->surface.voidFrac; SoilVolume = soilTheta * theLidProc->soil.thickness; StorageVolume = storageDepth * theLidProc->storage.voidFrac; //... get ET rates availVolume = SoilVolume - theLidProc->soil.wiltPoint * theLidProc->soil.thickness; getEvapRates(SurfaceVolume, availVolume, StorageVolume); //... no storage evap if soil layer saturated if ( soilTheta >= theLidProc->soil.porosity ) StorageEvap = 0.0; //... find soil layer perc rate SoilPerc = getSoilPercRate(soilTheta); //... find storage (drain mat) outflow rate StorageInfil = 0.0; StorageDrain = getDrainMatOutflow(storageDepth); //... both storage & soil layers are saturated if ( storageDepth >= theLidProc->storage.thickness && soilTheta >= theLidProc->soil.porosity ) { //... soil perc can't exceed storage outflow if ( SoilPerc > StorageDrain ) SoilPerc = StorageDrain; //... storage outflow can't exceed soil perc else StorageDrain = MIN(StorageDrain, SoilPerc); } //... storage and/or soil layers not saturated else { //... limit underdrain flow by volume above drain offset if ( StorageDrain > 0.0 ) { maxRate = (storageDepth - theLidProc->drain.offset) * theLidProc->storage.voidFrac / Tstep; StorageDrain = MIN(StorageDrain, maxRate); } //... limit soil perc by available storage volume availVolume = (theLidProc->storage.thickness - storageDepth) * theLidProc->storage.voidFrac; maxRate = availVolume/Tstep + StorageEvap + StorageDrain; SoilPerc = MIN(SoilPerc, maxRate); } //... limit surface infil. by available soil pore volume maxRate = (theLidProc->soil.porosity - soilTheta) * theLidProc->soil.thickness / Tstep + SoilPerc; SurfaceInfil = MIN(SurfaceInfil, maxRate); // ... find surface outflow rate SurfaceOutflow = getSurfaceOutflowRate(surfaceDepth); // ... find net fluxes for each layer f[SURF] = (SurfaceInflow - SurfaceEvap - SurfaceInfil - SurfaceOutflow) / theLidProc->surface.voidFrac; f[SOIL] = (SurfaceInfil - SoilEvap - SoilPerc) / theLidProc->soil.thickness; f[STOR] = (SoilPerc - StorageEvap - StorageDrain) / theLidProc->storage.voidFrac; }