Saturday, January 21, 2023

SWMM 5.2.2 Code for LID Function lidproc_getOutflow

 This code is part of a function called "lidproc_getOutflow" that computes the runoff outflow from a single LID (Low Impact Development) unit.

The function takes in multiple inputs: a pointer to a specific LID unit, a pointer to a generic LID process, the runoff rate captured by the LID unit, potential evaporation rate, infiltration rate to native soil, maximum infiltration rate to native soil, and time step. It returns surface runoff rate from the LID unit, and sets the values of lidEvap, lidInfil, and lidDrain.

The function uses several arrays and variables to store values such as layer moisture levels, previously and newly computed flux rates, and layer moisture limits. It also defines a pointer to a function that computes flux rates through the LID. It initializes various values such as layer moisture volumes, flux rates, and moisture limits. Then it finds Green-Ampt infiltration from the surface layer and calls the appropriate flux rate function for the LID type.

Input VariablesTypeDescriptionUnits
lidUnitpointerPointer to specific LID unit being analyzed
lidProcpointerPointer to generic LID process of the LID unit
inflowdoubleRunoff rate captured by LID unitft/s
evapdoublePotential evaporation rateft/s
infildoubleInfiltration rate to native soilft/s
maxInfildoubleMaximum infiltration rate to native soilft/s
tStepdoubleTime stepsec
Output VariablesTypeDescriptionUnits
lidEvapdouble pointerEvaporation rate for LID unitft/s
lidInfildouble pointerInfiltration rate for LID unitft/s
lidDraindouble pointerDrain flow for LID unitft/s
returnsdoubleSurface runoff rate from the LID unitft/s

Note: The table only contains the input/output variables defined in the function signature and the purpose of the function.

double lidproc_getOutflow(TLidUnit* lidUnit, TLidProc* lidProc, double inflow,
                          double evap, double infil, double maxInfil,
                          double tStep, double* lidEvap,
                          double* lidInfil, double* lidDrain)
//
//  Purpose: computes runoff outflow from a single LID unit.
//  Input:   lidUnit  = ptr. to specific LID unit being analyzed
//           lidProc  = ptr. to generic LID process of the LID unit
//           inflow   = runoff rate captured by LID unit (ft/s)
//           evap     = potential evaporation rate (ft/s)
//           infil    = infiltration rate to native soil (ft/s)
//           maxInfil = max. infiltration rate to native soil (ft/s)
//           tStep    = time step (sec)
//  Output:  lidEvap  = evaporation rate for LID unit (ft/s)
//           lidInfil = infiltration rate for LID unit (ft/s)
//           lidDrain = drain flow for LID unit (ft/s)
//           returns surface runoff rate from the LID unit (ft/s)
//
{
    int    i;
    double x[MAX_LAYERS];        // layer moisture levels
    double xOld[MAX_LAYERS];     // work vector
    double xPrev[MAX_LAYERS];    // work vector
    double xMin[MAX_LAYERS];     // lower limit on moisture levels
    double xMax[MAX_LAYERS];     // upper limit on moisture levels
    double fOld[MAX_LAYERS];     // previously computed flux rates
    double f[MAX_LAYERS];        // newly computed flux rates

    // convergence tolerance on moisture levels (ft, moisture fraction , ft)
    double xTol[MAX_LAYERS] = {STOPTOL, STOPTOL, STOPTOL, STOPTOL};

    double omega = 0.0;          // integration time weighting

    //... define a pointer to function that computes flux rates through the LID
    void (*fluxRates) (double *, double *) = NULL;

    //... save references to the LID process and LID unit
    theLidProc = lidProc;
    theLidUnit = lidUnit;

    //... save evap, max. infil. & time step to shared variables
    EvapRate = evap;
    MaxNativeInfil = maxInfil;
    Tstep = tStep;

    //... store current moisture levels in vector x
    x[SURF] = theLidUnit->surfaceDepth;
    x[SOIL] = theLidUnit->soilMoisture;
    x[STOR] = theLidUnit->storageDepth;
    x[PAVE] = theLidUnit->paveDepth;

    //... initialize layer moisture volumes, flux rates and moisture limits
    SurfaceVolume  = 0.0;
    PaveVolume     = 0.0;
    SoilVolume     = 0.0;
    StorageVolume  = 0.0;
    SurfaceInflow  = inflow;
    SurfaceInfil   = 0.0;
    SurfaceEvap    = 0.0;
    SurfaceOutflow = 0.0;
    PaveEvap       = 0.0;
    PavePerc       = 0.0;
    SoilEvap       = 0.0;
    SoilPerc       = 0.0;
    StorageInflow  = 0.0;
    StorageExfil   = 0.0;
    StorageEvap    = 0.0;
    StorageDrain   = 0.0;
    for (i = 0; i < MAX_LAYERS; i++)
    {
        f[i] = 0.0;
        fOld[i] = theLidUnit->oldFluxRates[i];
        xMin[i] = 0.0;
        xMax[i] = BIG;
        Xold[i] = x[i];
    }

    //... find Green-Ampt infiltration from surface layer
    if ( theLidProc->lidType == POROUS_PAVEMENT ) SurfaceInfil = 0.0;
    else if ( theLidUnit->soilInfil.Ks > 0.0 )
    {
        SurfaceInfil =
            grnampt_getInfil(&theLidUnit->soilInfil, Tstep,
                             SurfaceInflow, theLidUnit->surfaceDepth,
                             MOD_GREEN_AMPT);
    }
    else SurfaceInfil = infil;

    //... set moisture limits for soil & storage layers
    if ( theLidProc->soil.thickness > 0.0 )
    {
        xMin[SOIL] = theLidProc->soil.wiltPoint;
        xMax[SOIL] = theLidProc->soil.porosity;
    }
    if ( theLidProc->pavement.thickness > 0.0 )
    {
        xMax[PAVE] = theLidProc->pavement.thickness;
    }
    if ( theLidProc->storage.thickness > 0.0 )
    {
        xMax[STOR] = theLidProc->storage.thickness;
    }
    if ( theLidProc->lidType == GREEN_ROOF )
    {
        xMax[STOR] = theLidProc->drainMat.thickness;
    }

    //... determine which flux rate function to use
    switch (theLidProc->lidType)
    {
    case BIO_CELL:
    case RAIN_GARDEN:     fluxRates = &biocellFluxRates;   break;
    case GREEN_ROOF:      fluxRates = &greenRoofFluxRates; break;
    case INFIL_TRENCH:    fluxRates = &trenchFluxRates;    break;
    case POROUS_PAVEMENT: fluxRates = &pavementFluxRates;  break;
    case RAIN_BARREL:     fluxRates = &barrelFluxRates;    break;
    case ROOF_DISCON:     fluxRates = &roofFluxRates;      break;
    case VEG_SWALE:       fluxRates = &swaleFluxRates;
                          omega = 0.5;
                          break;
    default:              return 0.0;
    }

    //... update moisture levels and flux rates over the time step
    i = modpuls_solve(MAX_LAYERS, x, xOld, xPrev, xMin, xMax, xTol,
                     fOld, f, tStep, omega, fluxRates);

/** For debugging only ********************************************
    if  (i == 0)
    {
        fprintf(Frpt.file,
        "\n  WARNING 09: integration failed to converge at %s %s",
            theDate, theTime);
        fprintf(Frpt.file,
        "\n              for LID %s placed in subcatchment %s.",
            theLidProc->ID, theSubcatch->ID);
    }
*******************************************************************/

    //... add any surface overflow to surface outflow
    if ( theLidProc->surface.canOverflow || theLidUnit->fullWidth == 0.0 )
    {
        SurfaceOutflow += getSurfaceOverflowRate(&x[SURF]);
    }

    //... save updated results
    theLidUnit->surfaceDepth = x[SURF];
    theLidUnit->paveDepth    = x[PAVE];
    theLidUnit->soilMoisture = x[SOIL];
    theLidUnit->storageDepth = x[STOR];
    for (i = 0; i < MAX_LAYERS; i++) theLidUnit->oldFluxRates[i] = f[i];

    //... assign values to LID unit evaporation, infiltration & drain flow
    *lidEvap = SurfaceEvap + PaveEvap + SoilEvap + StorageEvap;
    *lidInfil = StorageExfil;
    *lidDrain = StorageDrain;

    //... return surface outflow (per unit area) from unit
    return SurfaceOutflow;
}

No comments:

AI Rivers of Wisdom about ICM SWMM

Here's the text "Rivers of Wisdom" formatted with one sentence per line: [Verse 1] 🌊 Beneath the ancient oak, where shadows p...