Beispiel #1
0
void setNewLinkState(int j)
//
//  Input:   j = link index
//  Output:  none
//  Purpose: updates state of link after current time step under
//           Steady Flow or Kinematic Wave flow routing
//
{
    int   k;
    double a, y1, y2;

    Link[j].newDepth = 0.0;
    Link[j].newVolume = 0.0;

    if ( Link[j].type == CONDUIT )
    {
        // --- find avg. depth from entry/exit conditions
        k = Link[j].subIndex;
        a = 0.5 * (Conduit[k].a1 + Conduit[k].a2);
        Link[j].newVolume = a * link_getLength(j) * Conduit[k].barrels;
        y1 = xsect_getYofA(&Link[j].xsect, Conduit[k].a1);
        y2 = xsect_getYofA(&Link[j].xsect, Conduit[k].a2);
        Link[j].newDepth = 0.5 * (y1 + y2);

        // --- update depths at end nodes
        updateNodeDepth(Link[j].node1, y1 + Link[j].offset1);
        updateNodeDepth(Link[j].node2, y2 + Link[j].offset2);

        // --- check if capacity limited
        if ( Conduit[k].a1 >= Link[j].xsect.aFull )
             Conduit[k].capacityLimited = TRUE;
        else Conduit[k].capacityLimited = FALSE;
    }
}
Beispiel #2
0
void initLinks()
//
//  Input:   none
//  Output:  none
//  Purpose: sets initial upstream/downstream conditions in links.
//
//  Note: initNodes() must have been called first to properly
//        initialize each node's crown elevation.
//
{
    int    i;                          // link index
    int    j;                          // node index
    int    k;                          // conduit or pump index
    double z;                          // crown elev. (ft)

    // --- examine each link
    for ( i = 0; i < Nobjects[LINK]; i++ )
    {
        // --- examine each conduit
        if ( Link[i].type == CONDUIT )
        {
            // --- assign initial flow to both ends of conduit
            k = Link[i].subIndex;
            Conduit[k].q1 = Link[i].newFlow / Conduit[k].barrels;
            Conduit[k].q2 = Conduit[k].q1;

            Conduit[k].q1Old = Conduit[k].q1;
            Conduit[k].q2Old = Conduit[k].q2;

            // --- find areas based on initial flow depth
            Conduit[k].a1 = xsect_getAofY(&Link[i].xsect, Link[i].newDepth);
            Conduit[k].a2 = Conduit[k].a1;

            // --- compute initial volume from area
            Link[i].newVolume = Conduit[k].a1 * link_getLength(i) *
                                Conduit[k].barrels;
            Link[i].oldVolume = Link[i].newVolume;
        }

        // --- update crown elev. of nodes at either end
        j = Link[i].node1;
        z = Node[j].invertElev + Link[i].offset1 + Link[i].xsect.yFull;
        Node[j].crownElev = MAX(Node[j].crownElev, z);
        j = Link[i].node2;
        z = Node[j].invertElev + Link[i].offset2 + Link[i].xsect.yFull;
        Node[j].crownElev = MAX(Node[j].crownElev, z);
    }
}
Beispiel #3
0
double getLinkStep(double tMin, int *minLink)
//
//  Input:   tMin = critical time step found so far (sec)
//  Output:  minLink = index of link with critical time step;
//           returns critical time step (sec)
//  Purpose: finds critical time step for conduits based on Courant criterion.
//
{
    int    i;                           // link index
    int    k;                           // conduit index
    double q;                           // conduit flow (cfs)
    double t;                           // time step (sec)
    double tLink = tMin;                // critical link time step (sec)

    // --- examine each conduit link
    for ( i = 0; i < Nobjects[LINK]; i++ )
    {
        if ( Link[i].type == CONDUIT )
        {
           // --- skip conduits with negligible flow, area or Fr
            k = Link[i].subIndex;
            q = fabs(Link[i].newFlow) / Conduit[k].barrels;
            if ( q <= 0.05 * Link[i].qFull
            ||   Conduit[k].a1 <= FUDGE
            ||   Link[i].froude <= 0.01 
               ) continue;

            // --- compute time step to satisfy Courant condition
            t = Link[i].newVolume / Conduit[k].barrels / q;
            t = t * Conduit[k].modLength / link_getLength(i);
            t = t * Link[i].froude / (1.0 + Link[i].froude) * CourantFactor;

            // --- update critical link time step
            if ( t < tLink )
            {
                tLink = t;
                *minLink = i;
            }
        }
    }
    return tLink;
}
Beispiel #4
0
void setNewLinkState(Project* project, int j)
//
//  Input:   j = link index
//  Output:  none
//  Purpose: updates state of link after current time step under
//           Steady Flow or Kinematic Wave flow routing
//
{
    int   k;
    double a, y1, y2;

    project->Link[j].newDepth = 0.0;
    project->Link[j].newVolume = 0.0;

    if ( project->Link[j].type == CONDUIT )
    {
        // --- find avg. depth from entry/exit conditions
        k = project->Link[j].subIndex;
        a = 0.5 * (project->Conduit[k].a1 + project->Conduit[k].a2);
		project->Link[j].newVolume = a * link_getLength(project, j) * project->Conduit[k].barrels;
		y1 = xsect_getYofA(project, &project->Link[j].xsect, project->Conduit[k].a1);
		y2 = xsect_getYofA(project, &project->Link[j].xsect, project->Conduit[k].a2);
        project->Link[j].newDepth = 0.5 * (y1 + y2);

        // --- update depths at end nodes
		updateNodeDepth(project, project->Link[j].node1, y1 + project->Link[j].offset1);
		updateNodeDepth(project, project->Link[j].node2, y2 + project->Link[j].offset2);

        // --- check if capacity limited
        if ( project->Conduit[k].a1 >= project->Link[j].xsect.aFull )
        {
             project->Conduit[k].capacityLimited = TRUE;
             project->Conduit[k].fullState = ALL_FULL;                                  //(5.1.008)
        }
        else
        {    
            project->Conduit[k].capacityLimited = FALSE;
            project->Conduit[k].fullState = 0;                                          //(5.1.008)
        }
    }
}
Beispiel #5
0
void initLinks(Project* project, int routingModel)
//
//  Input:   none
//  Output:  none
//  Purpose: sets initial upstream/downstream conditions in links.
//
{
    int    i;                          // link index
    int    k;                          // conduit or pump index

    // --- examine each link
    for ( i = 0; i < project->Nobjects[LINK]; i++ )
    {
        if ( routingModel == SF) project->Link[i].newFlow = 0.0;

        // --- otherwise if link is a conduit
        else if ( project->Link[i].type == CONDUIT )
        {
            // --- assign initial flow to both ends of conduit
            k = project->Link[i].subIndex;
            project->Conduit[k].q1 = project->Link[i].newFlow / project->Conduit[k].barrels;
            project->Conduit[k].q2 = project->Conduit[k].q1;

            // --- find areas based on initial flow depth
			project->Conduit[k].a1 = xsect_getAofY(project, &project->Link[i].xsect, project->Link[i].newDepth);
            project->Conduit[k].a2 = project->Conduit[k].a1;

            // --- compute initial volume from area
            {
				project->Link[i].newVolume = project->Conduit[k].a1 * link_getLength(project, i) *
                                    project->Conduit[k].barrels;
            }
            project->Link[i].oldVolume = project->Link[i].newVolume;
        }
    }
}
int kinwave_execute(int j, double* qinflow, double* qoutflow, double tStep)
//
//  Input:   j = link index
//           qinflow = inflow at current time (cfs)
//           tStep = time step (sec)
//  Output:  qoutflow = outflow at current time (cfs),
//           returns number of iterations used
//  Purpose: finds outflow over time step tStep given flow entering a
//           conduit using Kinematic Wave flow routing.
//
//  t
//  |          qin, ain |-------------------| qout, aout
//  |                   |  Flow --->        |
//  |----> x     q1, a1 |-------------------| q2, a2
//
//
{
    int    k;
    int    result = 1;
    double dxdt, dq;
    double ain, aout;
    double qin, qout;
    double a1, a2, q1, q2;

    // --- no routing for non-conduit link
    (*qoutflow) = (*qinflow); 
    if ( Link[j].type != CONDUIT ) return result;

    // --- no routing for dummy xsection
    if ( Link[j].xsect.type == DUMMY ) return result;

    // --- assign module-level variables
    pXsect = &Link[j].xsect;
    Qfull = Link[j].qFull;
    Afull = Link[j].xsect.aFull;
    k = Link[j].subIndex;
    Beta1 = Conduit[k].beta / Qfull;
 
    // --- normalize flows and areas
    q1 = Conduit[k].q1 / Qfull;
    q2 = Conduit[k].q2 / Qfull;
    a1 = Conduit[k].a1 / Afull;
    a2 = Conduit[k].a2 / Afull;
    qin = (*qinflow) / Conduit[k].barrels / Qfull;

    // --- use full area when inlet flow >= full flow                          //(5.0.012 - LR)
    if ( qin >= 1.0 ) ain = 1.0;                                               //(5.0.012 - LR)

    // --- get normalized inlet area corresponding to inlet flow
    else ain = xsect_getAofS(pXsect, qin/Beta1) / Afull;

    // --- check for no flow
    if ( qin <= TINY && q2 <= TINY )
    {
        qout = 0.0;
        aout = 0.0;
    }

    // --- otherwise solve finite difference form of continuity eqn.
    else
    {
        // --- compute constant factors
        dxdt = link_getLength(j) / tStep * Afull / Qfull;
        dq   = q2 - q1;
        C1   = dxdt * WT / WX;
        C2   = (1.0 - WT) * (ain - a1);
        C2   = C2 - WT * a2;
        C2   = C2 * dxdt / WX;
        C2   = C2 + (1.0 - WX) / WX * dq - qin;
    
        // --- starting guess for aout is value from previous time step
        aout = a2;

        // --- solve continuity equation for aout
        result = solveContinuity(qin, ain, &aout);

        // --- report error if continuity eqn. not solved
        if ( result == -1 )
        {
            report_writeErrorMsg(ERR_KINWAVE, Link[j].ID);
            return 1;
        }
        if ( result <= 0 ) result = 1;

        // --- compute normalized outlet flow from outlet area
        qout = Beta1 * xsect_getSofA(pXsect, aout*Afull);
        if ( qin > 1.0 ) qin = 1.0;
    }

    // --- save new flows and areas
    Conduit[k].q1 = qin * Qfull;
    Conduit[k].a1 = ain * Afull;
    Conduit[k].q2 = qout * Qfull;
    Conduit[k].a2 = aout * Afull;
    (*qinflow)  = Conduit[k].q1 * Conduit[k].barrels;
    (*qoutflow) = Conduit[k].q2 * Conduit[k].barrels;
    return result;
}