Saturday, January 21, 2023

SWMM 5.2.2 Code for LID Function greenRoofFluxRates

This code is a function called "greenRoofFluxRates" that calculates flux rates from the layers of a green roof. It takes in two input arrays, "x" and "f", which represent the vector of storage levels and the vector of flux rates, respectively. The function uses several intermediate variables, including "availVolume" and "maxRate". It also makes use of several properties of the green roof, such as "soilThickness", "storageThickness", "soilPorosity", "storageVoidFrac", "soilFieldCap", and "soilWiltPoint".

The code first retrieves the moisture levels from the input vector "x" and converts them to volumes. It then calculates the ET rates, soil layer perc rate, and storage (drain mat) outflow rate. The code also checks for the case where the unit is full and limits the rates accordingly. The Surface infil is adjusted so that the soil porosity is not exceeded. The code also finds the surface outflow rate and computes overall layer flux rates.

A table of the variables used in this function and their descriptions is as follows:

Variable NameDescription
x[SURF], x[SOIL], x[STOR]Input vector of storage levels
f[SURF], f[SOIL], f[STOR]Output vector of flux rates
surfaceDepthMoisture level variable for the surface layer
soilThetaMoisture level variable for the soil layer
storageDepthMoisture level variable for the storage layer
availVolumeIntermediate variable for available volume
maxRateIntermediate variable for maximum rate
soilThicknessProperty of the soil layer representing its thickness
storageThicknessProperty of the storage layer representing its thickness
soilPorosityProperty of the soil layer representing its porosity

Variable NameDescription
storageVoidFracProperty of the storage layer representing its void fraction
soilFieldCapProperty of the soil layer representing its field capacity
soilWiltPointProperty of the soil layer representing its wilting point
SurfaceVolumeVolume of the surface layer
SoilVolumeVolume of the soil layer
StorageVolumeVolume of the storage layer
SurfaceInflowInflow rate to the surface layer
SurfaceEvapEvaporation rate from the surface layer
SoilPercPercolation rate out of the soil layer
SoilEvapEvaporation rate from the soil layer
StorageExfilExfiltration rate out of the storage layer
StorageDrainDrain flow rate out of the storage layer
SurfaceInfilInfiltration rate into the soil layer
SurfaceOutflowOutflow rate from the surface layer

The code uses several helper functions:

  • getEvapRates(SurfaceVolume, 0.0, availVolume, StorageVolume, 1.0) : to calculate evaporation rate
  • getSoilPercRate(soilTheta) : to calculate soil percolation rate
  • getDrainMatOutflow(storageDepth) : to calculate storage (drain mat) outflow rate
  • getSurfaceOutflowRate(surfaceDepth) : to calculate surface outflow rate

The final output of the function is the overall flux rate for each of the three layers: surface, soil, and storage.


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
//
{
    // Moisture level variables
    double surfaceDepth;
    double soilTheta;
    double storageDepth;

    // Intermediate variables
    double availVolume;
    double maxRate;

    // Green roof properties
    double soilThickness    = theLidProc->soil.thickness;
    double storageThickness = theLidProc->storage.thickness;
    double soilPorosity     = theLidProc->soil.porosity;
    double storageVoidFrac  = theLidProc->storage.voidFrac;
    double soilFieldCap     = theLidProc->soil.fieldCap;
    double soilWiltPoint    = theLidProc->soil.wiltPoint;

    //... retrieve moisture levels from input vector
    surfaceDepth = x[SURF];
    soilTheta    = x[SOIL];
    storageDepth = x[STOR];

    //... convert moisture levels to volumes
    SurfaceVolume = surfaceDepth * theLidProc->surface.voidFrac;
    SoilVolume = soilTheta * soilThickness;
    StorageVolume = storageDepth * storageVoidFrac;

    //... get ET rates
    availVolume = SoilVolume - soilWiltPoint * soilThickness;
    getEvapRates(SurfaceVolume, 0.0, availVolume, StorageVolume, 1.0);
    if ( soilTheta >= soilPorosity ) StorageEvap = 0.0;

    //... soil layer perc rate
    SoilPerc = getSoilPercRate(soilTheta);

    //... limit perc rate by available water
    availVolume = (soilTheta - soilFieldCap) * soilThickness;
    maxRate = MAX(availVolume, 0.0) / Tstep - SoilEvap;
    SoilPerc = MIN(SoilPerc, maxRate);
    SoilPerc = MAX(SoilPerc, 0.0);

    //... storage (drain mat) outflow rate
    StorageExfil = 0.0;
    StorageDrain = getDrainMatOutflow(storageDepth);

    //... unit is full
    if ( soilTheta >= soilPorosity && storageDepth >= storageThickness )
    {
        //... outflow from both layers equals limiting rate
        maxRate = MIN(SoilPerc, StorageDrain);
        SoilPerc = maxRate;
        StorageDrain = maxRate;

        //... adjust inflow rate to soil layer
        SurfaceInfil = MIN(SurfaceInfil, maxRate);
    }

    //... unit not full
    else
    {
        //... limit drainmat outflow by available storage volume
        maxRate = storageDepth * storageVoidFrac / Tstep - StorageEvap;
        if ( storageDepth >= storageThickness ) maxRate += SoilPerc;
        maxRate = MAX(maxRate, 0.0);
        StorageDrain = MIN(StorageDrain, maxRate);

        //... limit soil perc inflow by unused storage volume
        maxRate = (storageThickness - storageDepth) * storageVoidFrac / Tstep +
                  StorageDrain + StorageEvap;
        SoilPerc = MIN(SoilPerc, maxRate);
                
        //... adjust surface infil. so soil porosity not exceeded
        maxRate = (soilPorosity - soilTheta) * soilThickness / Tstep +
                  SoilPerc + SoilEvap;
        SurfaceInfil = MIN(SurfaceInfil, maxRate);
    }

    // ... find surface 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 - StorageDrain) /
              theLidProc->storage.voidFrac;
}

SWMM 5.2.2 Code for LID Function biocellFluxRates

 This code is a function called "biocellFluxRates" that calculates flux rates from the layers of a bio-retention cell LID. It takes in two input arrays, "x" and "f", which represent the vector of storage levels and the vector of flux rates, respectively. The function uses several intermediate variables, including "availVolume" and "maxRate". It also makes use of several properties of the LID layers, such as "soilThickness", "soilPorosity", "soilFieldCap", "soilWiltPoint", "storageThickness", and "storageVoidFrac".

The code first retrieves the moisture levels from the input vector "x" and converts them to volumes. It then calculates the ET rates, soil layer perc rate, and exfiltration rate out of the storage layer. The code also checks for underdrain flow and limits the perc rate and exfiltration rate by available water. The surface infil is limited by unused soil volume. The code also checks for special cases where the storage layer is not present, both layers are full, or either layer is not full and limits the rates accordingly.

A table of the variables used in this function and their descriptions is as follows:

Variable NameDescription
x[SURF], x[SOIL], x[STOR]Input vector of storage levels
f[SURF], f[SOIL], f[STOR]Output vector of flux rates
surfaceDepthMoisture level variable for the surface layer
soilThetaMoisture level variable for the soil layer
storageDepthMoisture level variable for the storage layer
availVolumeIntermediate variable for available volume
maxRateIntermediate variable for maximum rate
soilThicknessProperty of the soil layer representing its thickness
soilPorosityProperty of the soil layer representing its porosity
soilFieldCapProperty of the soil layer representing its field capacity
soilWiltPointProperty of the soil layer representing its wilting point
storageThicknessProperty of the storage layer representing its thickness
storageVoidFracProperty of the storage layer representing its void fraction
SurfaceVolumeConverted surface moisture level to volume
SoilVolumeConverted soil moisture level to volume
StorageVolumeConverted storage moisture level to volume
SurfaceInfilRate of inflow to the surface layer
SurfaceEvapRate of evaporation from the surface layer
SoilPercRate of percolation from the soil layer
SoilEvapRate of evaporation from the soil layer
StorageExfilRate of exfiltration from the storage layer
StorageDrainRate of underdrain flow from the storage layer
TstepTime step
theLidProcPointer to LID process data
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
//
{
    // Moisture level variables
    double surfaceDepth;
    double soilTheta;
    double storageDepth;

    // Intermediate variables
    double availVolume;
    double maxRate;

    // LID layer properties
    double soilThickness    = theLidProc->soil.thickness;
    double soilPorosity     = theLidProc->soil.porosity;
    double soilFieldCap     = theLidProc->soil.fieldCap;
    double soilWiltPoint    = theLidProc->soil.wiltPoint;
    double storageThickness = theLidProc->storage.thickness;
    double storageVoidFrac  = theLidProc->storage.voidFrac;

    //... retrieve moisture levels from input vector
    surfaceDepth = x[SURF];
    soilTheta    = x[SOIL];
    storageDepth = x[STOR];

    //... convert moisture levels to volumes
    SurfaceVolume = surfaceDepth * theLidProc->surface.voidFrac;
    SoilVolume    = soilTheta * soilThickness;
    StorageVolume = storageDepth * storageVoidFrac;

    //... get ET rates
    availVolume = SoilVolume - soilWiltPoint * soilThickness;
    getEvapRates(SurfaceVolume, 0.0, availVolume, StorageVolume, 1.0);
    if ( soilTheta >= soilPorosity ) StorageEvap = 0.0;

    //... soil layer perc rate
    SoilPerc = getSoilPercRate(soilTheta);

    //... limit perc rate by available water
    availVolume =  (soilTheta - soilFieldCap) * soilThickness;
    maxRate = MAX(availVolume, 0.0) / Tstep - SoilEvap;
    SoilPerc = MIN(SoilPerc, maxRate);
    SoilPerc = MAX(SoilPerc, 0.0);

    //... exfiltration rate out of storage layer
    StorageExfil = getStorageExfilRate();

    //... underdrain flow rate
    StorageDrain = 0.0;
    if ( theLidProc->drain.coeff > 0.0 )
    {
        StorageDrain = getStorageDrainRate(storageDepth, soilTheta, 0.0,
                                           surfaceDepth);
    }

    //... special case of no storage layer present
    if ( storageThickness == 0.0 )
    {
        StorageEvap = 0.0;
        maxRate = MIN(SoilPerc, StorageExfil);
        SoilPerc = maxRate;
        StorageExfil = maxRate;

        //... limit surface infil. by unused soil volume
        maxRate = (soilPorosity - soilTheta) * soilThickness / Tstep +
                  SoilPerc + SoilEvap;
        SurfaceInfil = MIN(SurfaceInfil, maxRate);
    }

    //... storage & soil layers are full
    else if ( soilTheta >= soilPorosity && storageDepth >= storageThickness )
    {
        //... limiting rate is smaller of soil perc and storage outflow
        maxRate = StorageExfil + StorageDrain;
        if ( SoilPerc < maxRate )
        {
            maxRate = SoilPerc;
            if ( maxRate > StorageExfil ) StorageDrain = maxRate - StorageExfil;
            else
            {
                StorageExfil = maxRate;
                StorageDrain = 0.0;
            }
        }
        else SoilPerc = maxRate;

        //... apply limiting rate to surface infil.
        SurfaceInfil = MIN(SurfaceInfil, maxRate);
    }

    //... either layer not full
    else if ( storageThickness > 0.0 )
    {
        //... limit storage exfiltration by available storage volume
        maxRate = SoilPerc - StorageEvap + storageDepth*storageVoidFrac/Tstep;
        StorageExfil = MIN(StorageExfil, maxRate);
        StorageExfil = MAX(StorageExfil, 0.0);

        //... limit underdrain flow by volume above drain offset
        if ( StorageDrain > 0.0 )
        {
            maxRate = -StorageExfil - StorageEvap;
            if ( storageDepth >= storageThickness) maxRate += SoilPerc;
            if ( theLidProc->drain.offset <= storageDepth )
            {
                maxRate += (storageDepth - theLidProc->drain.offset) *
                           storageVoidFrac/Tstep;
            }
            maxRate = MAX(maxRate, 0.0);
            StorageDrain = MIN(StorageDrain, maxRate);
        }

        //... limit soil perc by unused storage volume
        maxRate = StorageExfil + StorageDrain + StorageEvap +
                  (storageThickness - storageDepth) *
                  storageVoidFrac/Tstep;
        SoilPerc = MIN(SoilPerc, maxRate);

        //... limit surface infil. by unused soil volume
        maxRate = (soilPorosity - soilTheta) * soilThickness / Tstep +
                  SoilPerc + SoilEvap;
        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;
    if ( storageThickness == 0.0 ) f[STOR] = 0.0;
    else f[STOR] = (SoilPerc - StorageEvap - StorageExfil - StorageDrain) /
                   theLidProc->storage.voidFrac;
}

EPANET 2,2 Code runhyd in EPANET.C

 This code is a function called "runhyd" that solves the network hydraulics for a single time period in a project.

It takes in two parameters, a pointer to a "Project" struct (pr) and a pointer to a long int (t) which will hold the current time in seconds. The function returns an error code.

It first finds new demands and control actions by calling the "demands" and "controls" functions. Then it solves the network hydraulic equations by calling the "hydsolve" function and passing it the pointer to the "Project" struct, the iteration count, and the solution accuracy. If there is no error code, it then checks for system unbalance and activates the "Haltflag" if the error is too high. Finally, it reports any warning conditions by calling the "writehydwarn" function.

The function uses the following variables:

VariablePurpose
hydpointer to the "Hydraul" struct in the "Project" struct
timepointer to the "Times" struct in the "Project" struct
rptpointer to the "Report" struct in the "Project" struct
iteriteration count
errcodeerror code
relerrsolution accuracy

int runhyd(Project *pr, long *t) /* **-------------------------------------------------------------- ** Input: none ** Output: t = pointer to current time (in seconds) ** Returns: error code ** Purpose: solves network hydraulics in a single time period **-------------------------------------------------------------- */ { Hydraul *hyd = &pr->hydraul; Times *time = &pr->times; Report *rpt = &pr->report; int iter; // Iteration count int errcode; // Error code double relerr; // Solution accuracy // Find new demands & control actions *t = time->Htime; demands(pr); controls(pr); // Solve network hydraulic equations errcode = hydsolve(pr,&iter,&relerr); if (!errcode) { // Report new status & save results if (rpt->Statflag) writehydstat(pr,iter,relerr); // If system unbalanced and no extra trials // allowed, then activate the Haltflag if (relerr > hyd->Hacc && hyd->ExtraIter == -1) { hyd->Haltflag = 1; } // Report any warning conditions if (!errcode) errcode = writehydwarn(pr,iter,relerr); } return errcode;

InfoSWMM: A 2030 AI-Assisted Study Guide

  InfoSWMM: A 2030 AI-Assisted Study Guide delete   InfoSWMM: A 2030 AI-Assisted Study Guide A comprehensive study guide for someone in 2030...