void updatePondedQual(int j, double wRunon[], double pondedQual[], double tStep) { int p; double c; double vIn; double wPpt, wInfil, w1; double bmpRemoval; int isDry; // --- total inflow volume vIn = Vrain + Vrunon; // --- for dry conditions if ( Vponded + vIn == 0.0 ) isDry = 1; else isDry = 0; // --- analyze each pollutant for (p = 0; p < Nobjects[POLLUT]; p++) { // --- update mass balance for direct deposition wPpt = Pollut[p].pptConcen * LperFT3 * Vrain; //(5.1.006 - MT) massbal_updateLoadingTotals(DEPOSITION_LOAD, p, wPpt * Pollut[p].mcf); // --- surface is dry and has no inflow -- add any remaining mass // to overall mass balance's FINAL_LOAD category if ( isDry ) { massbal_updateLoadingTotals(FINAL_LOAD, p, pondedQual[p] * Pollut[p].mcf); pondedQual[p] = 0.0; OutflowLoad[p] = 0.0; } else { // --- find concen. of ponded water w1 = pondedQual[p] + wPpt + wRunon[p]*tStep; c = w1 / (Vponded + vIn); // --- mass lost to infiltration wInfil = c * Vinfil; wInfil = MIN(wInfil, w1); massbal_updateLoadingTotals(INFIL_LOAD, p, wInfil * Pollut[p].mcf); w1 -= wInfil; // --- mass lost to outflow OutflowLoad[p] = MIN(w1, (c*Voutflow)); w1 -= OutflowLoad[p]; // --- reduce outflow load by average BMP removal bmpRemoval = landuse_getAvgBmpEffic(j, p) * OutflowLoad[p]; massbal_updateLoadingTotals(BMP_REMOVAL_LOAD, p, bmpRemoval*Pollut[p].mcf); OutflowLoad[p] -= bmpRemoval; // --- update ponded mass pondedQual[p] = c * subcatch_getDepth(j) * Subcatch[j].area; //(5.1.006) } } }
double landuse_getWashoffLoad(Project* project, int i, int p, double area, TLandFactor landFactor[], double runoff, double vOutflow) // // Input: i = land use index // p = pollut. index // area = sucatchment area (ft2) // landFactor[] = array of land use data for subcatchment // runoff = runoff flow generated by subcatchment (ft/sec) // vOutflow = runoff volume leaving the subcatchment (ft3) // Output: returns pollutant runoff load (mass) // Purpose: computes pollutant load generated by a land use over a time step. // { double landuseArea; // area of current land use (ft2) double buildup; // current pollutant buildup (lb or kg) double washoffQual; // pollutant concentration in washoff (mass/ft3) double washoffLoad; // pollutant washoff load over time step (lb or kg) double bmpRemoval; // pollutant load removed by BMP treatment (lb or kg) // --- compute concen. of pollutant in washoff (mass/ft3) buildup = landFactor[i].buildup[p]; landuseArea = landFactor[i].fraction * area; washoffQual = landuse_getWashoffQual(project, i, p, buildup, runoff, landuseArea); // --- compute washoff load exported (lbs or kg) from landuse // (project->Pollut[].mcf converts from mg (or ug) mass units to lbs (or kg) washoffLoad = washoffQual * vOutflow * landuseArea / area * project->Pollut[p].mcf; // --- if buildup modelled, reduce it by amount of washoff if ( project->Landuse[i].buildupFunc[p].funcType != NO_BUILDUP || buildup > washoffLoad ) { washoffLoad = MIN(washoffLoad, buildup); buildup -= washoffLoad; landFactor[i].buildup[p] = buildup; } // --- otherwise add washoff to buildup mass balance totals // so that things will balance else { massbal_updateLoadingTotals(project,BUILDUP_LOAD, p, washoffLoad); landFactor[i].buildup[p] = 0.0; } // --- apply any BMP removal to washoff bmpRemoval = project->Landuse[i].washoffFunc[p].bmpEffic * washoffLoad; if ( bmpRemoval > 0.0 ) { massbal_updateLoadingTotals(project,BMP_REMOVAL_LOAD, p, bmpRemoval); washoffLoad -= bmpRemoval; } // --- return washoff load converted back to mass (mg or ug) return washoffLoad / project->Pollut[p].mcf; }
float landuse_getCoPollutLoad(int p, float washoff[], float tStep) // // Input: p = pollutant index // washoff = pollut. washoff rate (mass/sec) // tStep = time step (sec) // Output: returns washoff mass added by co-pollutant relation (mass/sec) // Purpose: finds washoff mass added by a co-pollutant of a given pollutant. // { int k; float w; float load; // --- check if pollutant p has a co-pollutant k k = Pollut[p].coPollut; if ( k >= 0 ) { // --- compute addition to washoff from co-pollutant w = Pollut[p].coFraction * washoff[k]; // --- add to mass balance totals load = w * tStep * Pollut[p].mcf; massbal_updateLoadingTotals(BUILDUP_LOAD, p, load); return w; } return 0.0; }
double landuse_getCoPollutLoad(Project* project, int p, double washoff[]) // // Input: p = pollutant index // washoff = pollut. washoff rate (mass/sec) // Output: returns washoff mass added by co-pollutant relation (mass) // Purpose: finds washoff mass added by a co-pollutant of a given pollutant. // { int k; double w; // --- check if pollutant p has a co-pollutant k k = project->Pollut[p].coPollut; if ( k >= 0 ) { // --- compute addition to washoff from co-pollutant w = project->Pollut[p].coFraction * washoff[k]; // --- add washoff to buildup mass balance totals // so that things will balance massbal_updateLoadingTotals(project,BUILDUP_LOAD, p, w * project->Pollut[p].mcf); return w; } return 0.0; }
void subcatch_sweepBuildup(int j, DateTime aDate) // // Input: j = subcatchment index // Output: none // Purpose: reduces pollutant buildup over a subcatchment if sweeping occurs. // { int i; // land use index int p; // pollutant index double oldBuildup; // buildup before sweeping (lbs or kg) double newBuildup; // buildup after sweeping (lbs or kg) // --- no sweeping if there is snow on plowable impervious area if ( Subcatch[j].snowpack != NULL && Subcatch[j].snowpack->wsnow[IMPERV0] > MIN_TOTAL_DEPTH ) return; // --- consider each land use for (i = 0; i < Nobjects[LANDUSE]; i++) { // --- skip land use if not in subcatchment if ( Subcatch[j].landFactor[i].fraction == 0.0 ) continue; // --- see if land use is subject to sweeping if ( Landuse[i].sweepInterval == 0.0 ) continue; // --- see if sweep interval has been reached if ( aDate - Subcatch[j].landFactor[i].lastSwept >= Landuse[i].sweepInterval ) { // --- update time when last swept Subcatch[j].landFactor[i].lastSwept = aDate; // --- examine each pollutant for (p = 0; p < Nobjects[POLLUT]; p++) { // --- reduce buildup by the fraction available // times the sweeping effic. oldBuildup = Subcatch[j].landFactor[i].buildup[p]; newBuildup = oldBuildup * (1.0 - Landuse[i].sweepRemoval * Landuse[i].washoffFunc[p].sweepEffic); newBuildup = MIN(oldBuildup, newBuildup); newBuildup = MAX(0.0, newBuildup); Subcatch[j].landFactor[i].buildup[p] = newBuildup; // --- update mass balance totals massbal_updateLoadingTotals(SWEEPING_LOAD, p, oldBuildup - newBuildup); } } } }
void subcatch_getBuildup(int j, double tStep) // // Input: j = subcatchment index // tStep = time step (sec) // Output: none // Purpose: adds to pollutant buildup on subcatchment. // { int i; // land use index int p; // pollutant index double f; // land use fraction double area; // land use area (acres or hectares) double curb; // land use curb length (user units) double oldBuildup; // buildup at start of time step double newBuildup; // buildup at end of time step // --- consider each landuse for (i = 0; i < Nobjects[LANDUSE]; i++) { // --- skip landuse if not in subcatch f = Subcatch[j].landFactor[i].fraction; if ( f == 0.0 ) continue; // --- get land area (in acres or hectares) & curb length area = f * Subcatch[j].area * UCF(LANDAREA); curb = f * Subcatch[j].curbLength; // --- examine each pollutant for (p = 0; p < Nobjects[POLLUT]; p++) { // --- see if snow-only buildup is in effect if (Pollut[p].snowOnly && Subcatch[j].newSnowDepth < 0.001/12.0) continue; // --- use land use's buildup function to update buildup amount oldBuildup = Subcatch[j].landFactor[i].buildup[p]; newBuildup = landuse_getBuildup(i, p, area, curb, oldBuildup, tStep); newBuildup = MAX(newBuildup, oldBuildup); Subcatch[j].landFactor[i].buildup[p] = newBuildup; massbal_updateLoadingTotals(BUILDUP_LOAD, p, (newBuildup - oldBuildup)); } } }
void runoff_getOutfallRunon(double tStep) // // Input: tStep = previous runoff time step (sec) // Output: none // Purpose: adds flow and pollutant loads leaving drainage system outfalls // during the previous runoff time step to designated subcatchments. // { int i, k, p; double w; // --- examine each outfall node for (i = 0; i < Nnodes[OUTFALL]; i++) { // --- ignore node if outflow not re-routed onto a subcatchment k = Outfall[i].routeTo; if ( k < 0 ) continue; if ( Subcatch[k].area == 0.0 ) continue; // --- add outfall's flow to subcatchment as runon and re-set routed // flow volume to 0 subcatch_addRunonFlow(k, Outfall[i].vRouted/tStep); massbal_updateRunoffTotals(RUNOFF_RUNON, Outfall[i].vRouted); Outfall[i].vRouted = 0.0; // --- add outfall's pollutant load on to subcatchment's wet // deposition load and re-set routed load to 0 // (Subcatch.newQual is being used as a temporary load accumulator) for (p = 0; p < Nobjects[POLLUT]; p++) { w = Outfall[i].wRouted[p] * LperFT3; massbal_updateLoadingTotals(DEPOSITION_LOAD, p, w * Pollut[p].mcf); Subcatch[k].newQual[p] += w / tStep; Outfall[i].wRouted[p] = 0.0; } } }
float landuse_getRunoffLoad(int i, int p, float area, TLandFactor landFactor[], float runoff, float tStep) // // Input: i = land use index // p = pollut. index // area = area devoted to land use (ft2) // landFactor[] = array of land use data for subcatchment // runoff = runoff flow on subcatchment (ft/sec) // tStep = time step (sec) // Output: returns runoff load for pollutant (mass/sec) // Purpose: computes pollutant load generated by a specific land use. // { float buildup; float washoff; // --- compute washoff mass/sec for this pollutant buildup = landFactor[i].buildup[p]; washoff = landuse_getWashoffMass(i, p, buildup, runoff, area); //added if(strncmp(strTSS, "", MAXFNAME) != 0 && Pollut[p].sedflag > 0) { // check the sediment class if (Pollut[p].sedflag == 1) { // sand buildup *= Landuse[i].frc_sand; washoff *= Landuse[i].frc_sand; } else if (Pollut[p].sedflag == 2) { // silt buildup *= Landuse[i].frc_silt; washoff *= Landuse[i].frc_silt; } else if (Pollut[p].sedflag == 3) { // clay buildup *= Landuse[i].frc_clay; washoff *= Landuse[i].frc_clay; } } // --- convert washoff to lbs (or kg) over time step so that // buildup and mass balances can be adjusted // (Pollut[].mcf converts from concentration mass units // to either lbs or kg) washoff *= tStep * Pollut[p].mcf; // --- if buildup modelled, reduce it by amount of washoff if ( Landuse[i].buildupFunc[p].funcType != NO_BUILDUP ) { washoff = MIN(washoff, buildup); buildup -= washoff; landFactor[i].buildup[p] = buildup; } // --- otherwise add washoff to buildup mass balance totals // so that things will balance else massbal_updateLoadingTotals(BUILDUP_LOAD, p, washoff); // --- return washoff converted back to mass/sec return washoff / tStep / Pollut[p].mcf; }
void subcatch_getWashoff(int j, double runoff, double tStep) // // Input: j = subcatchment index // runoff = total subcatchment runoff (ft/sec) // tStep = time step (sec) // Output: none // Purpose: computes new runoff quality for subcatchment. // // Considers two separate pollutant generating streams that are combined // together: // 1. complete mix mass balance of pollutants in surface ponding due to // runon, wet deposition, infil., & evap. // 2. washoff of pollutant buildup as described by the project's land // use washoff functions. // { int i, p; double massLoad; // --- return if there is no area or no pollutants if ( Nobjects[POLLUT] == 0 || Subcatch[j].area == 0.0 ) return; // --- intialize outflow loads to zero for (p = 0; p < Nobjects[POLLUT]; p++) { WashoffLoad[p] = 0.0; // load just from washoff function OutflowLoad[p] = 0.0; // Washoff load + ponded water load } // --- add outflow of pollutants in ponded water to outflow loads // (Note: at this point, Subcatch.newQual contains mass inflow // from any upstream subcatchments draining to this one) updatePondedQual(j, Subcatch[j].newQual, Subcatch[j].pondedQual, tStep); // --- add washoff loads from landuses to outflow loads if ( runoff >= MIN_RUNOFF ) { for (i = 0; i < Nobjects[LANDUSE]; i++) { if ( Subcatch[j].landFactor[i].fraction > 0.0 ) { landuse_getWashoff(i, Subcatch[j].area, Subcatch[j].landFactor, runoff, tStep, WashoffLoad); } } // --- compute contribution from any co-pollutant for (p = 0; p < Nobjects[POLLUT]; p++) { WashoffLoad[p] += landuse_getCoPollutLoad(p, WashoffLoad); OutflowLoad[p] += WashoffLoad[p]; } } // --- switch from internal runoff (used in washoff functions) to // runoff that actually leaves the subcatchment runoff = Subcatch[j].newRunoff; // --- for each pollutant for (p = 0; p < Nobjects[POLLUT]; p++) { // --- update subcatchment's total runoff load in lbs (or kg) massLoad = OutflowLoad[p] * Pollut[p].mcf; Subcatch[j].totalLoad[p] += massLoad; // --- update overall runoff mass balance if runoff goes to // conveyance system if ( Subcatch[j].outNode >= 0 || Subcatch[j].outSubcatch == j ) massbal_updateLoadingTotals(RUNOFF_LOAD, p, massLoad); // --- save new outflow runoff concentration (in mass/L) if ( runoff > MIN_RUNOFF ) Subcatch[j].newQual[p] = OutflowLoad[p] / (runoff * tStep * LperFT3); else Subcatch[j].newQual[p] = 0.0; } }