Exemple #1
0
void setNewNodeState(int j, float dt)
//
//  Input:   j  = node index
//           dt = time step (sec)
//  Output:  none
//  Purpose: updates state of node after current time step
//           for Steady Flow or Kinematic Wave flow routing.
//
{
    int   canPond;                     // TRUE if ponding can occur at node  
    float newNetInflow;                // inflow - outflow at node (cfs)

    // --- update stored volume using mid-point integration
    newNetInflow = Node[j].inflow - Node[j].outflow;
    Node[j].newVolume = Node[j].oldVolume +
                        0.5 * (Node[j].oldNetInflow + newNetInflow) * dt;
    if ( Node[j].newVolume < 0.0 ) Node[j].newVolume = 0.0;

    // --- determine any overflow lost from system
    Node[j].overflow = 0.0;
    canPond = (AllowPonding && Node[j].pondedArea > 0.0);
    if ( Node[j].newVolume > Node[j].fullVolume )
    {
        if ( !canPond )
        {
            Node[j].overflow = (Node[j].newVolume - Node[j].fullVolume) / dt;
            Node[j].newVolume = Node[j].fullVolume;

            // --- ignore any negligible overflow
            if ( Node[j].overflow <= FUDGE ) Node[j].overflow = 0.0;
        }
    }

    // --- compute a depth from volume
    //     (depths at upstream nodes are subsequently adjusted in
    //     setNewLinkState to reflect depths in connected conduit)
    if ( canPond )
    {
        Node[j].newDepth = node_getPondedDepth(j, Node[j].newVolume);
    }
    else
    {
        Node[j].newDepth = node_getDepth(j, Node[j].newVolume);
    }
}
Exemple #2
0
double node_getPondedDepth(int j, double v)
//
//  Input:   j = node index
//           v = water volume (ft3)
//  Output:  returns depth of water at a node (ft)
//  Purpose: computes depth of water at a node based on volume.
//
{
    double y;

    // --- if volume below full volume, use normal getDepth function
    if ( v <= Node[j].fullVolume ) return node_getDepth(j, v);

    // --- find ponded volume
    v = v - Node[j].fullVolume;

    // --- depth equals full depth + ponded volume / ponded area
    y = Node[j].fullDepth;
    if ( Node[j].pondedArea > 0.0 ) y += v / Node[j].pondedArea;
    return y;
}
Exemple #3
0
void setNewNodeState(int j, double dt)
//
//  Input:   j  = node index
//           dt = time step (sec)
//  Output:  none
//  Purpose: updates state of node after current time step
//           for Steady Flow or Kinematic Wave flow routing.
//
{
    int   canPond;                     // TRUE if ponding can occur at node  
    double newNetInflow;               // inflow - outflow at node (cfs)

    // --- storage nodes have already been updated
    if ( Node[j].type == STORAGE ) return; 

    // --- update stored volume using mid-point integration
    newNetInflow = Node[j].inflow - Node[j].outflow;
    Node[j].newVolume = Node[j].oldVolume +
                        0.5 * (Node[j].oldNetInflow + newNetInflow) * dt;
    if ( Node[j].newVolume < FUDGE ) Node[j].newVolume = 0.0;

    // --- determine any overflow lost from system
    Node[j].overflow = 0.0;
    canPond = (AllowPonding && Node[j].pondedArea > 0.0);
    if ( Node[j].newVolume > Node[j].fullVolume )
    {
        Node[j].overflow = (Node[j].newVolume - MAX(Node[j].oldVolume,
                            Node[j].fullVolume)) / dt;
        if ( Node[j].overflow < FUDGE ) Node[j].overflow = 0.0;
        if ( !canPond ) Node[j].newVolume = Node[j].fullVolume;
    }

    // --- compute a depth from volume
    //     (depths at upstream nodes are subsequently adjusted in
    //     setNewLinkState to reflect depths in connected conduit)
    Node[j].newDepth = node_getDepth(j, Node[j].newVolume);
}
Exemple #4
0
void updateStorageState(int i, int j, int links[], double dt)
//
//  Input:   i = index of storage node
//           j = current position in links array
//           links = array of topo-sorted link indexes
//           dt = routing time step (sec)
//  Output:  none
//  Purpose: updates depth and volume of a storage node using successive
//           approximation with under-relaxation for Steady or Kin. Wave
//           routing.
//
{
    int    iter;                       // iteration counter
    int    stopped;                    // TRUE when iterations stop
    double vFixed;                     // fixed terms of flow balance eqn.
    double v2;                         // new volume estimate (ft3)
    double d1;                         // initial value of storage depth (ft)
    double d2;                         // updated value of storage depth (ft)
    double outflow;                    // outflow rate from storage (cfs)

    // --- see if storage node needs updating
    if ( Node[i].type != STORAGE ) return;
    if ( Node[i].updated ) return;

    // --- compute terms of flow balance eqn.
    //       v2 = v1 + (inflow - outflow)*dt
    //     that do not depend on storage depth at end of time step
    vFixed = Node[i].oldVolume + 
             0.5 * (Node[i].oldNetInflow + Node[i].inflow) * dt;
    d1 = Node[i].newDepth;

    // --- iterate finding outflow (which depends on depth) and subsequent
    //     new volume and depth until negligible depth change occurs
    iter = 1;
    stopped = FALSE;
    while ( iter < MAXITER && !stopped )
    {
        // --- find total flow in all outflow links
        outflow = getStorageOutflow(i, j, links, dt);

        // --- find new volume from flow balance eqn.
        v2 = vFixed - 0.5 * outflow * dt - node_getLosses(i, dt);

        // --- limit volume to full volume if no ponding
        //     and compute overflow rate
        v2 = MAX(0.0, v2);
        Node[i].overflow = 0.0;
        if ( v2 > Node[i].fullVolume )
        {
            Node[i].overflow = (v2 - MAX(Node[i].oldVolume,
                                         Node[i].fullVolume)) / dt;
            if ( !AllowPonding || Node[i].pondedArea == 0.0 )
                v2 = Node[i].fullVolume;
        }

        // --- update node's volume & depth 
        Node[i].newVolume = v2;
        if ( v2 > Node[i].fullVolume ) d2 = node_getPondedDepth(i, v2);
        else d2 = node_getDepth(i, v2);
        Node[i].newDepth = d2;

        // --- use under-relaxation to estimate new depth value
        //     and stop if close enough to previous value
        d2 = (1.0 - OMEGA)*d1 + OMEGA*d2;
        if ( fabs(d2 - d1) <= STOPTOL ) stopped = TRUE;

        // --- update old depth with new value and continue to iterate
        Node[i].newDepth = d2;
        d1 = d2;
        iter++;
    }

    // --- mark node as being updated
    Node[i].updated = TRUE;
}