void climate_setState(DateTime theDate) // // Input: theDate = simulation date // Output: none // Purpose: sets climate variables for current date. // { if ( Fclimate.mode == USE_FILE ) updateFileValues(theDate); if ( Temp.dataSource != NO_TEMP ) setTemp(theDate); setEvap(theDate); setWind(theDate); Adjust.rainFactor = Adjust.rain[datetime_monthOfYear(theDate)-1]; //(5.1.007) Adjust.hydconFactor = Adjust.hydcon[datetime_monthOfYear(theDate)-1]; //(5.1.008) setNextEvapDate(theDate); //(5.1.008) }
void addDryWeatherInflows(DateTime currentDate) // // Input: currentDate = current date/time // Output: none // Purpose: adds dry weather inflows to nodes at current date. // { int j, p; int month, day, hour; double q, w; TDwfInflow* inflow; // --- get month (zero-based), day-of-week (zero-based), // & hour-of-day for routing date/time month = datetime_monthOfYear(currentDate) - 1; day = datetime_dayOfWeek(currentDate) - 1; hour = datetime_hourOfDay(currentDate); // --- for each node with a defined dry weather inflow for (j = 0; j < Nobjects[NODE]; j++) { inflow = Node[j].dwfInflow; if ( !inflow ) continue; // --- get flow inflow (i.e., the inflow whose param code is -1) q = 0.0; while ( inflow ) { if ( inflow->param < 0 ) { q = inflow_getDwfInflow(inflow, month, day, hour); break; } inflow = inflow->next; } if ( fabs(q) < FLOW_TOL ) q = 0.0; // --- add flow inflow to node's lateral inflow Node[j].newLatFlow += q; massbal_addInflowFlow(DRY_WEATHER_INFLOW, q); // --- get pollutant mass inflows inflow = Node[j].dwfInflow; while ( inflow ) { if ( inflow->param >= 0 ) { p = inflow->param; w = q * inflow_getDwfInflow(inflow, month, day, hour); Node[j].newQual[p] += w; massbal_addInflowQual(DRY_WEATHER_INFLOW, p, w); } inflow = inflow->next; } } }
void getEvapRates(Project* project, double theta, double upperDepth) // // Input: theta = moisture content of upper zone // upperDepth = depth of upper zone (ft) // Output: none // Purpose: computes evapotranspiration out of upper & lower zones. // { int p, month; double f; double lowerFrac, upperFrac; // --- no project->GW evaporation when infiltration is occurring project->UpperEvap = 0.0; project->LowerEvap = 0.0; if ( project->Infil > 0.0 ) return; // --- get monthly-adjusted upper zone evap fraction upperFrac = project->A.upperEvapFrac; f = 1.0; p = project->A.upperEvapPat; if ( p >= 0 ) { month = datetime_monthOfYear(getDateTime(project,project->NewRunoffTime)); f = project->Pattern[p].factor[month-1]; } upperFrac *= f; // --- upper zone evaporation requires that soil moisture // be above the wilting point if ( theta > project->A.wiltingPoint ) { // --- actual evap is upper zone fraction applied to max. potential // rate, limited by the available rate after any surface evap project->UpperEvap = upperFrac * project->MaxEvap; project->UpperEvap = MIN(project->UpperEvap, project->AvailEvap); } // --- check if lower zone evaporation is possible if ( project->A.lowerEvapDepth > 0.0 ) { // --- find the fraction of the lower evaporation depth that // extends into the saturated lower zone lowerFrac = (project->A.lowerEvapDepth - upperDepth) / project->A.lowerEvapDepth; lowerFrac = MAX(0.0, lowerFrac); lowerFrac = MIN(lowerFrac, 1.0); // --- make the lower zone evap rate proportional to this fraction // and the evap not used in the upper zone project->LowerEvap = lowerFrac * (1.0 - upperFrac) * project->MaxEvap; project->LowerEvap = MIN(project->LowerEvap, (project->AvailEvap - project->UpperEvap)); } }
void setEvap(DateTime theDate) // // Input: theDate = simulation date // Output: none // Purpose: sets evaporation rate (ft/sec) for a specified date. // { int k; int mon = datetime_monthOfYear(theDate); //(5.1.007) switch ( Evap.type ) { case CONSTANT_EVAP: Evap.rate = Evap.monthlyEvap[0] / UCF(EVAPRATE); break; case MONTHLY_EVAP: Evap.rate = Evap.monthlyEvap[mon-1] / UCF(EVAPRATE); break; case TIMESERIES_EVAP: if ( theDate >= NextEvapDate ) Evap.rate = NextEvapRate / UCF(EVAPRATE); break; case FILE_EVAP: Evap.rate = FileValue[EVAP] / UCF(EVAPRATE); Evap.rate *= Evap.panCoeff[mon-1]; break; case TEMPERATURE_EVAP: Evap.rate = FileValue[EVAP] / UCF(EVAPRATE); break; default: Evap.rate = 0.0; } // --- apply climate change adjustment //(5.1.007) Evap.rate += Adjust.evap[mon-1]; //(5.1.007) // --- set soil recovery factor Evap.recoveryFactor = 1.0; k = Evap.recoveryPattern; if ( k >= 0 && Pattern[k].type == MONTHLY_PATTERN ) { Evap.recoveryFactor = Pattern[k].factor[mon-1]; //(5.1.007) } }
void setEvap(DateTime theDate) // // Input: theDate = simulation date // Output: none // Purpose: sets evaporation rate (ft/sec) for a specified date. // { int yr, mon, day, k; switch ( Evap.type ) { case CONSTANT_EVAP: Evap.rate = Evap.monthlyEvap[0] / UCF(EVAPRATE); break; case MONTHLY_EVAP: datetime_decodeDate(theDate, &yr, &mon, &day); Evap.rate = Evap.monthlyEvap[mon-1] / UCF(EVAPRATE); break; case TIMESERIES_EVAP: if ( theDate >= NextEvapDate ) Evap.rate = NextEvapRate / UCF(EVAPRATE); break; case FILE_EVAP: Evap.rate = FileValue[EVAP] / UCF(EVAPRATE); datetime_decodeDate(theDate, &yr, &mon, &day); Evap.rate *= Evap.panCoeff[mon-1]; break; case TEMPERATURE_EVAP: Evap.rate = FileValue[EVAP] / UCF(EVAPRATE); break; default: Evap.rate = 0.0; } // --- set soil recovery factor Evap.recoveryFactor = 1.0; k = Evap.recoveryPattern; if ( k >= 0 && Pattern[k].type == MONTHLY_PATTERN ) { mon = datetime_monthOfYear(theDate) - 1; Evap.recoveryFactor = Pattern[k].factor[mon]; } }
int evaluatePremise(struct TPremise* p, DateTime theDate, DateTime theTime, DateTime elapsedTime, double tStep) // // Input: p = a control rule premise condition // theDate = the current simulation date // theTime = the current simulation time of day // elpasedTime = decimal days since the start of the simulation // tStep = current time step (days) //(5.0.013 - LR) // Output: returns TRUE if the condition is true or FALSE otherwise // Purpose: evaluates the truth of a control rule premise condition. // { int i = p->node; int j = p->link; double head; switch ( p->attribute ) { case r_TIME: return checkTimeValue(p, elapsedTime, elapsedTime + tStep); case r_DATE: return checkValue(p, theDate); case r_CLOCKTIME: return checkTimeValue(p, theTime, theTime + tStep); case r_DAY: //(5.0.014 - LR) return checkValue(p, datetime_dayOfWeek(theDate)); //(5.0.014 - LR) case r_MONTH: //(5.0.014 - LR) return checkValue(p, datetime_monthOfYear(theDate)); //(5.0.014 - LR) case r_STATUS: if ( j < 0 || Link[j].type != PUMP ) return FALSE; else return checkValue(p, Link[j].setting); case r_SETTING: if ( j < 0 || (Link[j].type != ORIFICE && Link[j].type != WEIR) ) return FALSE; else return checkValue(p, Link[j].setting); case r_FLOW: if ( j < 0 ) return FALSE; else return checkValue(p, Link[j].direction*Link[j].newFlow*UCF(FLOW));//(5.0.019 - LR) case r_DEPTH: if ( j >= 0 ) return checkValue(p, Link[j].newDepth*UCF(LENGTH)); else if ( i >= 0 ) return checkValue(p, Node[i].newDepth*UCF(LENGTH)); else return FALSE; case r_HEAD: if ( i < 0 ) return FALSE; head = (Node[i].newDepth + Node[i].invertElev) * UCF(LENGTH); return checkValue(p, head); case r_INFLOW: if ( i < 0 ) return FALSE; else return checkValue(p, Node[i].newLatFlow*UCF(FLOW)); default: return FALSE; } }
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 setTemp(DateTime theDate) // // Input: theDate = simulation date // Output: none // Purpose: updates temperatures for new simulation date. // { int j; // snow data object index int k; // time series index int mon; // month of year //(5.1.007) int day; // day of year DateTime theDay; // calendar day double hour; // hour of day double tmp; // temporary temperature // --- see if a new day has started mon = datetime_monthOfYear(theDate); //(5.1.007) theDay = floor(theDate); if ( theDay > LastDay ) { // --- update min. & max. temps & their time of day day = datetime_dayOfYear(theDate); if ( Temp.dataSource == FILE_TEMP ) { Tmin = FileValue[TMIN] + Adjust.temp[mon-1]; //(5.1.007) Tmax = FileValue[TMAX] + Adjust.temp[mon-1]; //(5.1.007) if ( Tmin > Tmax ) { tmp = Tmin; Tmin = Tmax; Tmax = tmp; } updateTempTimes(day); if ( Evap.type == TEMPERATURE_EVAP ) { updateTempMoveAve(Tmin, Tmax); //(5.1.010) FileValue[EVAP] = getTempEvap(day, Tma.tAve, Tma.tRng); //(5.1.010) } } // --- compute snow melt coefficients based on day of year Snow.season = sin(0.0172615*(day-81.0)); for (j=0; j<Nobjects[SNOWMELT]; j++) { snow_setMeltCoeffs(j, Snow.season); } // --- update date of last day analyzed LastDay = theDate; } // --- for min/max daily temps. from climate file, // compute hourly temp. by sinusoidal interp. if ( Temp.dataSource == FILE_TEMP ) { hour = (theDate - theDay) * 24.0; if ( hour < Hrsr ) Temp.ta = Tmin + Trng1/2.0 * sin(PI/Dydif * (Hrsr - hour)); else if ( hour >= Hrsr && hour <= Hrss ) Temp.ta = Tave + Trng * sin(PI/Dhrdy * (Hrday - hour)); else Temp.ta = Tmax - Trng * sin(PI/Dydif * (hour - Hrss)); } // --- for user-supplied temperature time series, // get temperature value from time series if ( Temp.dataSource == TSERIES_TEMP ) { k = Temp.tSeries; if ( k >= 0) { Temp.ta = table_tseriesLookup(&Tseries[k], theDate, TRUE); // --- convert from deg. C to deg. F if need be if ( UnitSystem == SI ) { Temp.ta = (9./5.) * Temp.ta + 32.0; } // --- apply climate change adjustment factor //(5.1.007) Temp.ta += Adjust.temp[mon-1]; //(5.1.007) } } // --- compute saturation vapor pressure Temp.ea = 8.1175e6 * exp(-7701.544 / (Temp.ta + 405.0265) ); }