Пример #1
0
void climate_initState()
//
//  Input:   none
//  Output:  none
//  Purpose: initializes climate state variables.
//
{
    LastDay = NO_DATE;
    Temp.tmax = MISSING;
    Snow.removed = 0.0;
    NextEvapDate = StartDate;
    NextEvapRate = 0.0;

    // --- initialize variables for time series evaporation
    if ( Evap.type == TIMESERIES_EVAP && Evap.tSeries >= 0  )
    {
        // --- initialize NextEvapDate & NextEvapRate to first entry of
        //     time series whose date <= the simulation start date
        table_getFirstEntry(&Tseries[Evap.tSeries],
                            &NextEvapDate, &NextEvapRate);
        if ( NextEvapDate < StartDate )
        {  
            setNextEvapDate(StartDate);
        }
        Evap.rate = NextEvapRate / UCF(EVAPRATE);

        // --- find the next time evaporation rates change after this
        setNextEvapDate(NextEvapDate); 
    }
}
Пример #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;
        }
    }
}
Пример #3
0
int getFirstRainfall(int j)
//
//  Input:   j = rain gage index
//  Output:  returns TRUE if successful
//  Purpose: positions rainfall record to date with first rainfall.
//
{
    int    k;                          // time series index
    float  vFirst;                     // first rain volume (ft or m)
    double rFirst;                     // first rain intensity (in/hr or mm/hr)

    // --- assign default values to date & rainfall
    Gage[j].startDate = NO_DATE;
    Gage[j].rainfall = 0.0;

    // --- initialize internal cumulative rainfall value
    Gage[j].rainAccum = 0;

    // --- use rain interface file if applicable
    if ( Gage[j].dataSource == RAIN_FILE )
    {
        if ( Frain.file && Gage[j].endFilePos > Gage[j].startFilePos )
        {
            // --- retrieve 1st date & rainfall volume from file
            fseek(Frain.file, Gage[j].startFilePos, SEEK_SET);
            fread(&Gage[j].startDate, sizeof(DateTime), 1, Frain.file);
            fread(&vFirst, sizeof(float), 1, Frain.file);
            Gage[j].currentFilePos = ftell(Frain.file);

            // --- convert rainfall to intensity
            Gage[j].rainfall = convertRainfall(j, (double)vFirst);
            return 1;
        }
        return 0;
    }

    // --- otherwise access user-supplied rainfall time series
    else
    {
        k = Gage[j].tSeries;
        if ( k >= 0 )
        {
            // --- retrieve first rainfall value from time series
            if ( table_getFirstEntry(&Tseries[k], &Gage[j].startDate,
                                     &rFirst) )
            {
                // --- convert rainfall to intensity
                Gage[j].rainfall = convertRainfall(j, rFirst);
                return 1;
            }
        }
        return 0;
    }
}
Пример #4
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;
}
Пример #5
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));
}
Пример #6
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;
}
Пример #7
0
void climate_initState()
//
//  Input:   none
//  Output:  none
//  Purpose: initializes climate state variables.
//
{
    LastDay = NO_DATE;
    Temp.tmax = MISSING;
    Snow.removed = 0.0;
    NextEvapDate = StartDate;
    NextEvapRate = 0.0;

    // --- initialize variables for time series evaporation
    if ( Evap.type == TIMESERIES_EVAP && Evap.tSeries >= 0  )
    {
        // --- initialize NextEvapDate & NextEvapRate to first entry of
        //     time series whose date <= the simulation start date
        table_getFirstEntry(&Tseries[Evap.tSeries],
                            &NextEvapDate, &NextEvapRate);
        if ( NextEvapDate < StartDate )
        {  
            setNextEvapDate(StartDate);
        }
        Evap.rate = NextEvapRate / UCF(EVAPRATE);

        // --- find the next time evaporation rates change after this
        setNextEvapDate(NextEvapDate); 
    }

////  Following section added to release 5.1.010.  ////                        //(5.1.010)
    // --- initialize variables for temperature evaporation
    if ( Evap.type == TEMPERATURE_EVAP )
    {
        Tma.maxCount = sizeof(Tma.ta) / sizeof(double);
        Tma.count = 0;
        Tma.front = 0;
        Tma.tAve = 0.0;
        Tma.tRng = 0.0;
    }
////
}
Пример #8
0
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;
}
Пример #9
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;
}