double landuse_getExternalBuildup(Project* project, int i, int p, double buildup, double tStep) // // Input: i = landuse index // p = pollutant index // buildup = buildup at start of time step (mass/unit) // tStep = time step (sec) // Output: returns pollutant buildup at end of time interval (mass/unit) // Purpose: finds pollutant buildup contributed by external loading over a // given time step. // { double maxBuildup = project->Landuse[i].buildupFunc[p].coeff[0]; double sf = project->Landuse[i].buildupFunc[p].coeff[1]; // scaling factor int ts = (int)floor(project->Landuse[i].buildupFunc[p].coeff[2]); // time series index double rate = 0.0; // --- no buildup increment at start of simulation if (project->NewRunoffTime == 0.0) return 0.0; // --- get buildup rate (mass/unit/day) over the interval if ( ts >= 0 ) { rate = sf * table_tseriesLookup(&project->Tseries[ts], getDateTime(project, project->NewRunoffTime), FALSE); } // --- compute buildup at end of time interval buildup = buildup + rate * tStep / SECperDAY; buildup = MIN(buildup, maxBuildup); return buildup; }
void updateActionValue(struct TAction* a, DateTime currentTime, double dt) //(5.0.012 - LR) // // Input: a = an action object // currentTime = current simulation date/time (days) //(5.0.013 - LR) // dt = time step (days) //(5.0.013 - LR) // Output: none // Purpose: updates value of actions found from Curves or Time Series. // { if ( a->curve >= 0 ) { a->value = table_lookup(&Curve[a->curve], ControlValue); } else if ( a->tseries >= 0 ) { a->value = table_tseriesLookup(&Tseries[a->tseries], currentTime, TRUE); } else if ( a->attribute == r_PID ) { a->value = getPIDSetting(a, dt); } }
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]; break; case MONTHLY_EVAP: datetime_decodeDate(theDate, &yr, &mon, &day); Evap.rate = Evap.monthlyEvap[mon-1]; break; case TIMESERIES_EVAP: k = Evap.tSeries; Evap.rate = table_tseriesLookup(&Tseries[k], theDate, TRUE); break; case FILE_EVAP: Evap.rate = FileValue[EVAP]; datetime_decodeDate(theDate, &yr, &mon, &day); Evap.rate *= Evap.panCoeff[mon-1]; break; default: Evap.rate = 0.0; } // --- convert rate from in/day (mm/day) to ft/sec Evap.rate /= UCF(EVAPRATE); }
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 day; // day of year DateTime theDay; // calendar day double hour; // hour of day // --- see if a new day has started 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]; Tmax = FileValue[TMAX]; updateTempTimes(day); } // --- 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; } } } // --- compute saturation vapor pressure Temp.ea = 8.1175e6 * exp(-7701.544 / (Temp.ta + 405.0265) ); }
void outfall_setOutletDepth(int j, double yNorm, double yCrit, double z) // // Input: j = node index // yNorm = normal flow depth in outfall conduit (ft) // yCrit = critical flow depth in outfall conduit (ft) // z = height to outfall conduit invert (ft) // Output: none // Purpose: sets water depth at an outfall node. // { double x, y; // x,y values in table double yNew; // new depth above invert elev. (ft) double stage; // water elevation at outfall (ft) int k; // table index int i = Node[j].subIndex; // outfall index DateTime currentDate; // current date/time in days switch ( Outfall[i].type ) { case FREE_OUTFALL: if ( z > 0.0 ) Node[j].newDepth = 0.0; else Node[j].newDepth = MIN(yNorm, yCrit); return; case NORMAL_OUTFALL: if ( z > 0.0 ) Node[j].newDepth = 0.0; else Node[j].newDepth = yNorm; return; case FIXED_OUTFALL: stage = Outfall[i].fixedStage; break; case TIDAL_OUTFALL: k = Outfall[i].tideCurve; table_getFirstEntry(&Curve[k], &x, &y); currentDate = NewRoutingTime / MSECperDAY; x += ( currentDate - floor(currentDate) ) * 24.0; stage = table_lookup(&Curve[k], x) / UCF(LENGTH); break; case TIMESERIES_OUTFALL: k = Outfall[i].stageSeries; currentDate = StartDateTime + NewRoutingTime / MSECperDAY; stage = table_tseriesLookup(&Tseries[k], currentDate, TRUE) / UCF(LENGTH); break; default: stage = Node[j].invertElev; } // --- now determine depth at node given outfall stage elev. // --- let critical flow depth be min. of critical & normal depth yCrit = MIN(yCrit, yNorm); // --- if elev. of critical depth is below outfall stage elev. then // the outfall stage determines node depth if ( yCrit + z + Node[j].invertElev < stage ) { yNew = stage - Node[j].invertElev; } // --- otherwise if the outfall conduit lies above the outfall invert else if ( z > 0.0 ) { // --- if the outfall stage lies below the bottom of the outfall // conduit then the result is distance from node invert to stage if ( stage < Node[j].invertElev + z ) yNew = MAX(0.0, (stage - Node[j].invertElev)); // --- otherwise stage lies between bottom of conduit and critical // depth in conduit so result is elev. of critical depth else yNew = z + yCrit; } // --- and for case where there is no conduit offset and outfall stage // lies below critical depth, then node depth = critical depth else yNew = yCrit; Node[j].newDepth = yNew; }