Beispiel #1
0
void setNextEvapDate(DateTime theDate)
//
//  Input:   theDate = current simulation date
//  Output:  sets a new value for NextEvapDate
//  Purpose: finds date for next change in evaporation after the current date.
//
{
    int    yr, mon, day, k;
    double d, e;

    // --- do nothing if current date hasn't reached the current next date
    if ( NextEvapDate > theDate ) return;

    switch ( Evap.type )
    {
      // --- for constant evaporation, use a next date far in the future
      case CONSTANT_EVAP:
         NextEvapDate = theDate + 365.;
         break;

      // --- for monthly evaporation, use the start of the next month
      case MONTHLY_EVAP:
        datetime_decodeDate(theDate, &yr, &mon, &day);
        if ( mon == 12 )
        {
            mon = 1;
            yr++;
        }
        else mon++;
        NextEvapDate = datetime_encodeDate(yr, mon, 1);
        break;

      // --- for time series evaporation, find the next entry in the
      //     series on or after the current date
      case TIMESERIES_EVAP:
        k = Evap.tSeries;
        if ( k >= 0 )
        {
            NextEvapDate = theDate + 365.;
            while ( table_getNextEntry(&Tseries[k], &d, &e) &&
                    d <= EndDateTime )
            {
                if ( d >= theDate )
                {
                    NextEvapDate = d;
                    NextEvapRate = e;
                    break;
                }
            }
        }
        break;

      // --- for climate file daily evaporation, use the next day
      case FILE_EVAP:
        NextEvapDate = floor(theDate) + 1.0;
        break;

      default: NextEvapDate = theDate + 365.;
    }
}
Beispiel #2
0
void  exfil_initState(int k)
//
//  Input:   k = storage unit index
//  Output:  none
//  Purpose: initializes the state of a storage unit's exfiltration object.
//
{
    int i;
    double a, alast, d;
    TTable* aCurve;
    TExfil* exfil = Storage[k].exfil;

    // --- initialize exfiltration object
    if ( exfil != NULL )
    {
        // --- initialize the Green-Ampt infil. parameters
        grnampt_initState(exfil->btmExfil);
        grnampt_initState(exfil->bankExfil);

        // --- shape given by a Storage Curve
        i = Storage[k].aCurve;
        if ( i >= 0 )
        {
            // --- get bottom area
            aCurve = &Curve[i];
            Storage[k].exfil->btmArea = table_lookupEx(aCurve, 0.0);

            // --- find min/max bank depths and max. bank area
            table_getFirstEntry(aCurve, &d, &a);
            exfil->bankMinDepth = 0.0;
            exfil->bankMaxDepth = 0.0;
            exfil->bankMaxArea = 0.0;
            alast = a;
            while ( table_getNextEntry(aCurve, &d, &a) )
            {
                if ( a < alast ) break;
                else if ( a > alast )
                {
                    exfil->bankMaxArea = a;
                    exfil->bankMaxDepth = d;
                }
                else if ( exfil->bankMaxArea == 0.0 ) exfil->bankMinDepth = d;
                else break;
                alast = a;
            }
        }

        // --- functional storage shape curve
        else
        {
    		exfil->btmArea = Storage[k].aConst;
            if ( Storage[k].aExpon == 0.0 ) exfil->btmArea +=Storage[k].aCoeff;
            exfil->bankMinDepth = 0.0;
            exfil->bankMaxDepth = BIG;
            exfil->bankMaxArea = BIG;
        }
    }
}
Beispiel #3
0
DateTime climate_getNextEvap(DateTime days)
//
//  Input:   days = current simulation date                                    //(5.0.019 - LR)
//  Output:  returns date (in whole days) when evaporation rate next changes
//  Purpose: finds date for next change in evaporation.
//
{
    int    yr, mon, day, k;
    double d, e;

    days = floor(days);                                                        //(5.0.019 - LR)
    switch ( Evap.type )
    {
      case CONSTANT_EVAP:
        return days + 365.;

      case MONTHLY_EVAP:
        datetime_decodeDate(days, &yr, &mon, &day);
        if ( mon == 12 )
        {
            mon = 1;
            yr++;
        }
        else mon++;
        return datetime_encodeDate(yr, mon, 1);

      case TIMESERIES_EVAP:

////  Following section modified for release 5.0.019  ////                     //(5.0.019 - LR)
        if ( NextEvapDate > days ) return NextEvapDate;
        k = Evap.tSeries;
        if ( k >= 0 )
        {    
            while ( table_getNextEntry(&Tseries[k], &d, &e) &&
                    d <= EndDateTime )
            {
                if ( d > days )
                {
                    NextEvapDate = d;
                    NextEvapRate = e;
                    return d;
                }
            }
        }
//////////////////////////////////////////////////////////
        return days + 365.;

      case FILE_EVAP:
        return days + 1.0;

      default: return days + 365.;
    }
}
Beispiel #4
0
int getNextInterval(TTable *curve, double y, double yLast, double wLast, 
                    double *y1, double *y2, double *w1, double *w2, 
                    double *wMax)
//
//  Input:   curve = pointer to a user-supplied shape curve table
//           y = current height in a geometry table
//           yLast = previous height in a geometry table
//           wLast = previous width in a geometry table
//           y1 = height at start of current curve interval
//           y2 = height at end of current curve interval
//           w1 = width at start of current curve interval
//           w2 = width at end of current curve interval
//           wMax = current maximum width of curve
//  Output:  updated values for yLast, wLast, y1, y2, w1, w2, and wMax;
//           returns TRUE if successful, FALSE if not.
//  Purpose: advances to the next height interval of a shape's curve that
//           contains the current height being evaluated in the shape's
//           geometry table.
//
//  Note:    heights and widths are with repsect to a shape of unit height.
{
    // --- keep advancing while the current geom. table height is
    //     above the end of the curve table interval
    while ( y > *y2 )
    {
        // --- move start of geom. table interval up to the end of
        //     the current curve table interval
        if ( *y2 > yLast )
        {
            Atotal += getArea(*y2, *w2, yLast, wLast); 
            Ptotal += getPerim(*y2, *w2, yLast, wLast);
            yLast = *y2;
            wLast = *w2;
        }

        // --- move to the next curve table interval
        *y1 = *y2;
        *w1 = *w2;
        if ( !table_getNextEntry(curve, y2, w2) )
        {
            *y2 = 1.0;
            return TRUE;
        }

        // --- update curve table's max. width
        if ( *w2 > *wMax ) *wMax = *w2;

        // --- check for valid curve table values
        if ( *y2 < *y1 || *w2 < 0.0 ) return FALSE;
        if ( *y2 > 1.0 ) *y2 = 1.0;
    }
    return TRUE;
}
Beispiel #5
0
double table_tseriesLookup(TTable *table, double x, char extend)
//
//  Input:   table = pointer to a TTable structure
//           x = a date/time value
//           extend = TRUE if time series extended on either end
//  Output:  returns a y-value
//  Purpose: retrieves the y-value corresponding to a time series date,
//           using interploation if necessary.
//
//  NOTE: if extend is FALSE and date x is outside the range of the table
//        then 0 is returned; if TRUE then the first or last value is
//        returned.
//
{
    // --- x lies within current time bracket
    if ( table->x1 <= x
    &&   table->x2 >= x
    &&   table->x1 != table->x2 )
    return table_interpolate(x, table->x1, table->y1, table->x2, table->y2);

    // --- x lies before current time bracket:
    //     move to start of time series
    if ( table->x1 == table->x2 || x < table->x1 )
    {
        table_getFirstEntry(table, &(table->x1), &(table->y1));
        if ( x < table->x1 )
        {
            if ( extend == TRUE ) return table->y1;
            else return 0;
        }
    }

    // --- x lies beyond current time bracket:
    //     update start of next time bracket
    table->x1 = table->x2;
    table->y1 = table->y2;

    // --- get end of next time bracket
    while ( table_getNextEntry(table, &(table->x2), &(table->y2)) )
    {
        // --- x lies within the bracket
        if ( x <= table->x2 )
            return table_interpolate(x, table->x1, table->y1,
                                        table->x2, table->y2);
        // --- otherwise move to next time bracket
        table->x1 = table->x2;
        table->y1 = table->y2;
    }

    // --- return last value or 0 if beyond last data value
    if ( extend == TRUE ) return table->y1;
    else return 0.0;
}
Beispiel #6
0
void   table_tseriesInit(TTable *table)
//
//  Input:   table = pointer to a TTable structure
//  Output:  none
//  Purpose: initializes the time bracket within a time series table.
//
{
    table_getFirstEntry(table, &(table->x1), &(table->y1));
    table->x2 = table->x1;
    table->y2 = table->y1;
    table_getNextEntry(table, &(table->x2), &(table->y2));
}
Beispiel #7
0
int getNextRainfall(int j)
//
//  Input:   j = rain gage index
//  Output:  returns 1 if successful; 0 if not
//  Purpose: positions rainfall record to date with next non-zero rainfall
//           while updating the gage's next rain intensity value.
//
//  Note: zero rainfall values explicitly entered into a rain file or
//        time series are skipped over so that a proper accounting of
//        wet and dry periods can be maintained.
//
{
    int    k;                          // time series index
    float  vNext;                      // next rain volume (ft or m)
    double rNext;                      // next rain intensity (in/hr or mm/hr)

    Gage[j].nextRainfall = 0.0;
    do
    {
        if ( Gage[j].dataSource == RAIN_FILE )
        {
            if ( Frain.file && Gage[j].currentFilePos < Gage[j].endFilePos )
            {
                fseek(Frain.file, Gage[j].currentFilePos, SEEK_SET);
                fread(&Gage[j].nextDate, sizeof(DateTime), 1, Frain.file);
                fread(&vNext, sizeof(float), 1, Frain.file);
                Gage[j].currentFilePos = ftell(Frain.file);
                rNext = convertRainfall(j, (double)vNext);
            }
            else return 0;
        }

        else
        {
            k = Gage[j].tSeries;
            if ( k >= 0 )
            {
                if ( !table_getNextEntry(&Tseries[k],
                        &Gage[j].nextDate, &rNext) ) return 0;
                rNext = convertRainfall(j, rNext);
            }
            else return 0;
        }
    } while (rNext == 0.0);
    Gage[j].nextRainfall = rNext;
    return 1;
}
Beispiel #8
0
int   table_validate(TTable *table)
//
//  Input:   table = pointer to a TTable structure
//  Output:  returns error code
//  Purpose: checks that table's x-values are in ascending order.
//
{
    int    result;
    double x1, x2, y1, y2;
    double dx, dxMin = BIG;

    // --- open external file if used as the table's data source
    if ( table->file.mode == USE_FILE )
    {
        table->file.file = fopen(table->file.name, "rt");
        if ( table->file.file == NULL ) return ERR_TABLE_FILE_OPEN;
    }

    // --- retrieve the first data entry in the table
    result = table_getFirstEntry(table, &x1, &y1);

    // --- return error condition if external file has no valid data
    if ( !result && table->file.mode == USE_FILE ) return ERR_TABLE_FILE_READ;

    // --- retrieve successive table entries and check for non-increasing x-values
    while ( table_getNextEntry(table, &x2, &y2) )
    {
        dx = x2 - x1;
        if ( dx <= 0.0 )
        {
            table->x2 = x2;
            return ERR_CURVE_SEQUENCE;
        }
        dxMin = MIN(dxMin, dx);
        x1 = x2;
    }
    table->dxMin = dxMin;

    // --- return error if external file could not be read completely
    if ( table->file.mode == USE_FILE && !feof(table->file.file) )
        return ERR_TABLE_FILE_READ;
    return 0;
}
Beispiel #9
0
DateTime climate_getNextEvap(DateTime days)
//
//  Input:   days = current simulation date (in whole days)
//  Output:  returns date (in whole days) when evaporation rate next changes
//  Purpose: finds date for next change in evaporation.
//
{
    int    yr, mon, day, k;
    double d, e;

    switch ( Evap.type )
    {
      case CONSTANT_EVAP:
        return days + 365.;

      case MONTHLY_EVAP:
        datetime_decodeDate(days, &yr, &mon, &day);
        if ( mon == 12 )
        {
            mon = 1;
            yr++;
        }
        else mon++;
        return datetime_encodeDate(yr, mon, 1);

      case TIMESERIES_EVAP:
        k = Evap.tSeries;
        while ( table_getNextEntry(&Tseries[k], &d, &e) )
        {
            if ( d > days ) return d;
        }
        return days + 365.;

      case FILE_EVAP:
        return days + 1.0;

      default: return days + 365.;
    }
}
Beispiel #10
0
int getNextRainfall(int j)
//
//  Input:   j = rain gage index
//  Output:  returns TRUE if successful
//  Purpose: positions rainfall record to date with next rainfall.
//
{
    int    k;                          // time series index
    int    result;                     // result of table query (TRUE/FALSE)
    float  vNext;                      // next rain volume (ft or m)
    double rNext;                      // next rain intensity (in/hr or mm/hr)

    Gage[j].nextRainfall = 0.0;
    if ( Gage[j].dataSource == RAIN_FILE )
    {
        if ( Frain.file && Gage[j].currentFilePos < Gage[j].endFilePos )
        {
            fseek(Frain.file, Gage[j].currentFilePos, SEEK_SET);
            fread(&Gage[j].nextDate, sizeof(DateTime), 1, Frain.file);
            fread(&vNext, sizeof(float), 1, Frain.file);
            Gage[j].currentFilePos = ftell(Frain.file);
            Gage[j].nextRainfall = convertRainfall(j, (double)vNext);
            return 1;
        }
        return 0;
    }

    else
    {
        k = Gage[j].tSeries;
        if ( k >= 0 )
        {
            result = table_getNextEntry(&Tseries[k], &Gage[j].nextDate, &rNext);
            if ( result ) Gage[j].nextRainfall = convertRainfall(j, rNext);
            return result;
        }
        return 0;
    }
}
Beispiel #11
0
int  computeShapeTables(TShape *shape, TTable *curve)
//
//  Input:   shape = pointer to a TShape object
//           curve = pointer to shape's table of width v. depth
//  Output:  returns TRUE if successful. FALSE if not
//  Purpose: computes the entries in a shape's geometry tables from
//           the shape's width v. height curve normalized with repsect
//           to full height.
//
//  Note:    the shape curve is a user-supplied table of width v. height
//           for a custom x-section of unit height.
{
    int    i, n;
    double dy, y, y1, y2, w, w1, w2;
	double yLast, wLast, wMax;

    // --- get first entry of user's shape curve
    if ( !table_getFirstEntry(curve, &y1, &w1) ) return FALSE;
    if ( y1 < 0.0 || y1 >= 1.0 || w1 < 0.0 ) return FALSE;
    wMax = w1;
    
    // --- if first entry not at zero ht. then add an initial entry
    if ( y1 != 0.0 )
    {
        y2 = y1;
        w2 = w1;
        y1 = 0.0;
        w1 = 0.0;
    }

    // --- otherwise get next entry in the user's shape curve
    else
    {
        if ( !table_getNextEntry(curve, &y2, &w2) ) return FALSE;
        if ( y2 < y1 || w2 < 0.0 ) return FALSE;
        if ( y2 > 1.0 ) y2 = 1.0;
        if ( w2 > wMax ) wMax = w2;
    }

    // --- determine number of entries & interval size in geom. tables
    shape->nTbl = N_SHAPE_TBL;
    n = shape->nTbl - 1;
    dy = 1.0 / (double)(n);

    // --- initialize geometry tables
    shape->areaTbl[0] = 0.0;
    shape->hradTbl[0] = 0.0;
    shape->widthTbl[0] = w1;
    Ptotal = w1;
    Atotal = 0.0;

    // --- fill in rest of geometry tables
    y = 0.0;
    w = w1;
    for ( i = 1; i <= n; i++ )
    {
        // --- advance to next relative height level
        yLast = y;
        wLast = w;
        y = y + dy;

        // --- do not allow height to exceed 1.0
        if ( fabs(y - 1.0) < TINY ) y = 1.0;

        // --- if height exceeds current shape curve interval,
        //     move to next interval of shape curve
        if ( y > y2 )
        {
            if ( !getNextInterval(curve, y, yLast, wLast, &y1, &y2, &w1,
                                  &w2, &wMax) )
                return FALSE;
            yLast = y1;
            wLast = w1;
        }

        // --- get top width, area, & perimeter of current interval
        w = getWidth(y, y1, y2, w1, w2);
        Atotal += getArea(y, w, yLast, wLast); 
        Ptotal += getPerim(y, w, yLast, wLast);

        // --- add top width to total perimeter if at top of shape
        if ( y == 1.0 ) Ptotal += w2;

        // --- update table values
        shape->widthTbl[i] = w;
        shape->areaTbl[i] = Atotal;
        if ( Ptotal > 0.0) shape->hradTbl[i] = Atotal / Ptotal;
        else               shape->hradTbl[i] = 0.0;
    }

    // --- assign values to shape'a area and hyd. radius when full
    shape->aFull = shape->areaTbl[n];
    shape->rFull = shape->hradTbl[n];

    // --- assign values to shape's max. width and section factor
    shape->wMax  = wMax;
    getSmax(shape);
    return TRUE;
}