void getRainfall(DateTime currentDate) // // Input: currentDate = current calendar date/time // Output: none // Purpose: determines rainfall at current RDII processing date. // // { int j; // rain gage index int i; // past rainfall index int month; // month of current date int gageInterval; // gage recording interval (sec) float rainfall; // rainfall volume (inches or mm) DateTime gageDate; // calendar date for rain gage // --- examine each rain gage for (j = 0; j < Nobjects[GAGE]; j++) { // --- repeat until gage's date reaches or exceeds current date if ( Gage[j].isUsed == FALSE ) continue; while ( GageData[j].gageDate < currentDate ) { // --- get rainfall volume over gage's recording interval // at gage'a current date (in original depth units) gageDate = GageData[j].gageDate; gageInterval = Gage[j].rainInterval; gage_setState(j, gageDate); rainfall = Gage[j].rainfall * (float)gageInterval / 3600.0; // --- if rainfall occurs if ( rainfall > 0.0 ) { // --- if previous dry period long enough then begin // new RDII event with time period index set to 0 ////////////////////////////////////////////////////////////////////////////// // New RDII event occurs when dry period > base of longest UH. (LR - 9/19/06) ////////////////////////////////////////////////////////////////////////////// //if ( GageData[j].drySeconds >= RDII_MIT ) if ( GageData[j].drySeconds >= gageInterval * GageData[j].maxPeriods ) { for (i=0; i<GageData[j].maxPeriods; i++) { GageData[j].pastRain[i] = 0.0; } GageData[j].period = 0; } GageData[j].drySeconds = 0; GageData[j].hasPastRain = TRUE; // --- update count of total rainfall volume (ft3) TotalRainVol += rainfall / UCF(RAINDEPTH) * GageData[j].area; } // --- if no rainfall, update duration of dry period else { GageData[j].drySeconds += gageInterval; if ( GageData[j].drySeconds >= gageInterval * GageData[j].maxPeriods ) { GageData[j].hasPastRain = FALSE; } ////////////////////////// //// Added (LR - 9/19/06) ////////////////////////// else GageData[j].hasPastRain = TRUE; } // --- add rainfall to list of past values, wrapping // array index if necessary if ( GageData[j].period < GageData[j].maxPeriods ) { i = GageData[j].period; } else i = 0; GageData[j].pastRain[i] = rainfall; month = datetime_monthOfYear(currentDate) - 1; GageData[j].pastMonth[i] = (char)month; GageData[j].period = i + 1; // --- advance rain gage's date by gage recording interval GageData[j].gageDate = datetime_addSeconds(gageDate, gageInterval); } } }
void runoff_execute() // // Input: none // Output: none // Purpose: computes runoff from each subcatchment at current runoff time. // { int j; // object index int day; // day of calendar year double runoffStep; // runoff time step (sec) double runoff; // subcatchment runoff (ft/sec) DateTime currentDate; // current date/time char canSweep; // TRUE if street sweeping can occur if ( ErrorCode ) return; // --- convert elapsed runoff time in milliseconds to a calendar date currentDate = getDateTime(NewRunoffTime); // --- update climatological conditions climate_setState(currentDate); // --- if no subcatchments then simply update runoff elapsed time if ( Nobjects[SUBCATCH] == 0 ) { OldRunoffTime = NewRunoffTime; NewRunoffTime += (double)(1000.0 * DryStep); return; } // --- update current rainfall at each raingage // NOTE: must examine gages in sequential order due to possible // presence of co-gages (gages that share same rain time series). IsRaining = FALSE; for (j = 0; j < Nobjects[GAGE]; j++) { gage_setState(j, currentDate); if ( Gage[j].rainfall > 0.0 ) IsRaining = TRUE; } // --- read runoff results from interface file if applicable if ( Frunoff.mode == USE_FILE ) { runoff_readFromFile(); return; } // --- see if street sweeping can occur on current date day = datetime_dayOfYear(currentDate); if ( day >= SweepStart && day <= SweepEnd ) canSweep = TRUE; else canSweep = FALSE; // --- get runoff time step (in seconds) runoffStep = runoff_getTimeStep(currentDate); if ( runoffStep <= 0.0 ) { ErrorCode = ERR_TIMESTEP; return; } // --- update runoff time clock (in milliseconds) OldRunoffTime = NewRunoffTime; NewRunoffTime += (double)(1000.0 * runoffStep); // --- update old state of each subcatchment, for (j = 0; j < Nobjects[SUBCATCH]; j++) subcatch_setOldState(j); // --- determine runon from upstream subcatchments, and implement snow removal for (j = 0; j < Nobjects[SUBCATCH]; j++) { subcatch_getRunon(j); if ( !IgnoreSnowmelt ) snow_plowSnow(j, runoffStep); } // --- determine runoff and pollutant buildup/washoff in each subcatchment HasSnow = FALSE; HasRunoff = FALSE; for (j = 0; j < Nobjects[SUBCATCH]; j++) { // --- find total runoff rate (in ft/sec) over the subcatchment // (the amount that actually leaves the subcatchment (in cfs) // is also computed and is stored in Subcatch[j].newRunoff) runoff = subcatch_getRunoff(j, runoffStep); // --- update state of study area surfaces if ( runoff > 0.0 ) HasRunoff = TRUE; if ( Subcatch[j].newSnowDepth > 0.0 ) HasSnow = TRUE; // --- skip pollutant buildup/washoff if quality ignored if ( IgnoreQuality ) continue; // --- now assign 'runoff' to runoff that leaves the subcatchment if (Subcatch[j].area > 0.0) runoff = Subcatch[j].newRunoff / Subcatch[j].area; // --- add to pollutant buildup if runoff is negligible if ( runoff < MIN_RUNOFF ) subcatch_getBuildup(j, runoffStep); // --- reduce buildup by street sweeping if ( canSweep && Subcatch[j].rainfall <= MIN_RUNOFF) subcatch_sweepBuildup(j, currentDate); // --- compute pollutant washoff subcatch_getWashoff(j, runoff, runoffStep); } // --- update tracking of system-wide max. runoff rate stats_updateMaxRunoff(); // --- save runoff results to interface file if one is used Nsteps++; if ( Frunoff.mode == SAVE_FILE ) { runoff_saveToFile((float)runoffStep); } // --- reset subcatchment runon to 0 for (j = 0; j < Nobjects[SUBCATCH]; j++) Subcatch[j].runon = 0.0; }