Ejemplo n.º 1
0
void node_initState(int j)
//
//  Input:   j = node index
//  Output:  none
//  Purpose: initializes a node's state variables at start of simulation.
//
{
    int p;

    // --- initialize depth
    Node[j].oldDepth = Node[j].initDepth;
    Node[j].newDepth = Node[j].oldDepth;
    Node[j].crownElev = Node[j].invertElev;

    Node[j].fullVolume = node_getVolume(j, Node[j].fullDepth);
    Node[j].oldVolume = node_getVolume(j, Node[j].oldDepth);
    Node[j].newVolume = Node[j].oldVolume;

    // --- initialize water quality state
    for (p = 0; p < Nobjects[POLLUT]; p++)
    {
        Node[j].oldQual[p]  = 0.0;
        Node[j].newQual[p]  = 0.0;
    }

    // --- initialize any inflow
    Node[j].oldLatFlow = 0.0;
    Node[j].newLatFlow = 0.0;

    // --- initialize HRT in storage nodes
    if ( Node[j].type == STORAGE )
    {
        Storage[Node[j].subIndex].hrt = 0.0;
    }
}
Ejemplo n.º 2
0
void node_initState(int j)
//
//  Input:   j = node index
//  Output:  none
//  Purpose: initializes a node's state variables at start of simulation.
//
{
    int p, k;                                                                  //(5.1.007)

    // --- initialize depth
    Node[j].oldDepth = Node[j].initDepth;
    Node[j].newDepth = Node[j].oldDepth;
    Node[j].crownElev = Node[j].invertElev;

    Node[j].fullVolume = node_getVolume(j, Node[j].fullDepth);
    Node[j].oldVolume = node_getVolume(j, Node[j].oldDepth);
    Node[j].newVolume = Node[j].oldVolume;

    // --- initialize water quality state
    for (p = 0; p < Nobjects[POLLUT]; p++)
    {
        Node[j].oldQual[p]  = 0.0;
        Node[j].newQual[p]  = 0.0;
    }

    // --- initialize any inflow
    Node[j].oldLatFlow = 0.0;
    Node[j].newLatFlow = 0.0;
    Node[j].losses = 0.0;                                                      //(5.1.007)


////  Following code section added to release 5.1.007.  ////                   //(5.1.007)

    // --- initialize storage nodes
    if ( Node[j].type == STORAGE )
    {
        // --- set hydraulic residence time to 0
        k = Node[j].subIndex;
        Storage[k].hrt = 0.0;

        // --- initialize exfiltration properties
        if ( Storage[k].exfil ) exfil_initState(k);
    }
////

////  Following code section added to release 5.1.008.  ////                   //(5.1.008)

    // --- initialize flow stream routed from outfall onto a subcatchment
    if ( Node[j].type == OUTFALL )
    {
        k = Node[j].subIndex;
        if ( Outfall[k].routeTo >= 0 )
        {
            Outfall[k].vRouted = 0.0;
            for (p = 0; p < Nobjects[POLLUT]; p++) Outfall[k].wRouted[p] = 0.0;
        }
    }
////
}
Ejemplo n.º 3
0
void initNodes()
//
//  Input:   none
//  Output:  none
//  Purpose: sets initial inflow/outflow and volume for each node
//
{
    int i;

    for ( i = 0; i < Nobjects[NODE]; i++ )
    {
        // --- set default crown elevations here
        Node[i].crownElev = Node[i].invertElev;

        // --- initialize node inflow and outflow
        Node[i].inflow = Node[i].newLatFlow;
        Node[i].outflow = 0.0;

        // --- initialize node volume
        Node[i].newVolume = 0.0;
        if ( AllowPonding &&
             Node[i].pondedArea > 0.0 &&
             Node[i].newDepth > Node[i].fullDepth )
        {
            Node[i].newVolume = Node[i].fullVolume +
                                (Node[i].newDepth - Node[i].fullDepth) *
                                Node[i].pondedArea;
        }
        else Node[i].newVolume = node_getVolume(i, Node[i].newDepth);
    }

    // --- update nodal inflow/outflow at ends of each link
    //     (needed for Steady Flow & Kin. Wave routing)
    for ( i = 0; i < Nobjects[LINK]; i++ )
    {
        if ( Link[i].newFlow >= 0.0 )
        {
            Node[Link[i].node1].outflow += Link[i].newFlow;
            Node[Link[i].node2].inflow  += Link[i].newFlow;
        }
        else
        {
            Node[Link[i].node1].inflow   -= Link[i].newFlow;
            Node[Link[i].node2].outflow  -= Link[i].newFlow;
        }
    }
}
Ejemplo n.º 4
0
void initNodes(Project* project)
//
//  Input:   none
//  Output:  none
//  Purpose: sets initial inflow/outflow and volume for each node
//
{
    int i;

    for ( i = 0; i < project->Nobjects[NODE]; i++ )
    {
        // --- initialize node inflow and outflow
        project->Node[i].inflow = project->Node[i].newLatFlow;
        project->Node[i].outflow = 0.0;

        // --- initialize node volume
        project->Node[i].newVolume = 0.0;
        if ( project->AllowPonding &&
             project->Node[i].pondedArea > 0.0 &&
             project->Node[i].newDepth > project->Node[i].fullDepth )
        {
            project->Node[i].newVolume = project->Node[i].fullVolume +
                                (project->Node[i].newDepth - project->Node[i].fullDepth) *
                                project->Node[i].pondedArea;
        }
		else project->Node[i].newVolume = node_getVolume(project, i, project->Node[i].newDepth);
    }

    // --- update nodal inflow/outflow at ends of each link
    //     (needed for Steady Flow & Kin. Wave routing)
    for ( i = 0; i < project->Nobjects[LINK]; i++ )
    {
        if ( project->Link[i].newFlow >= 0.0 )
        {
            project->Node[project->Link[i].node1].outflow += project->Link[i].newFlow;
            project->Node[project->Link[i].node2].inflow  += project->Link[i].newFlow;
        }
        else
        {
            project->Node[project->Link[i].node1].inflow   -= project->Link[i].newFlow;
            project->Node[project->Link[i].node2].outflow  -= project->Link[i].newFlow;
        }
    }
}
Ejemplo n.º 5
0
void setNodeDepth(int i, double dt)
//
//  Input:   i  = node index
//           dt = time step (sec)
//  Output:  none
//  Purpose: sets depth at non-outfall node after current time step.
//
{
    int     canPond;                   // TRUE if node can pond overflows
    int     isPonded;                  // TRUE if node is currently ponded 
    double  dQ;                        // inflow minus outflow at node (cfs)
    double  dV;                        // change in node volume (ft3)
    double  dy;                        // change in node depth (ft)
    double  yMax;                      // max. depth at node (ft)
    double  yOld;                      // node depth at previous time step (ft)
    double  yLast;                     // previous node depth (ft)
    double  yNew;                      // new node depth (ft)
    double  yCrown;                    // depth to node crown (ft)
    double  surfArea;                  // node surface area (ft2)
    double  denom;                     // denominator term
    double  corr;                      // correction factor
    double  f;                         // relative surcharge depth

    // --- see if node can pond water above it
    canPond = (AllowPonding && Node[i].pondedArea > 0.0);
    isPonded = (canPond && Node[i].newDepth > Node[i].fullDepth);

    // --- initialize values
    yCrown = Node[i].crownElev - Node[i].invertElev;
    yOld = Node[i].oldDepth;
    yLast = Node[i].newDepth;
    Node[i].overflow = 0.0;
    surfArea = Xnode[i].newSurfArea;

    // --- determine average net flow volume into node over the time step
    dQ = Node[i].inflow - Node[i].outflow;
    dV = 0.5 * (Node[i].oldNetInflow + dQ) * dt;

    // --- if node not surcharged, base depth change on surface area        
    if ( yLast <= yCrown || Node[i].type == STORAGE || isPonded )
    {
        dy = dV / surfArea;
        yNew = yOld + dy;

        // --- save non-ponded surface area for use in surcharge algorithm     //(5.1.002)
        if ( !isPonded ) Xnode[i].oldSurfArea = surfArea;                      //(5.1.002)

        // --- apply under-relaxation to new depth estimate
        if ( Steps > 0 )
        {
            yNew = (1.0 - Omega) * yLast + Omega * yNew;
        }

        // --- don't allow a ponded node to drop much below full depth
        if ( isPonded && yNew < Node[i].fullDepth )
            yNew = Node[i].fullDepth - FUDGE;
    }

    // --- if node surcharged, base depth change on dqdh
    //     NOTE: depth change is w.r.t depth from previous
    //     iteration; also, do not apply under-relaxation.
    else
    {
        // --- apply correction factor for upstream terminal nodes
        corr = 1.0;
        if ( Node[i].degree < 0 ) corr = 0.6;

        // --- allow surface area from last non-surcharged condition
        //     to influence dqdh if depth close to crown depth
        denom = Xnode[i].sumdqdh;
        if ( yLast < 1.25 * yCrown )
        {
            f = (yLast - yCrown) / yCrown;
            denom += (Xnode[i].oldSurfArea/dt -
                      Xnode[i].sumdqdh) * exp(-15.0 * f);
        }

        // --- compute new estimate of node depth
        if ( denom == 0.0 ) dy = 0.0;
        else dy = corr * dQ / denom;
        yNew = yLast + dy;
        if ( yNew < yCrown ) yNew = yCrown - FUDGE;

        // --- don't allow a newly ponded node to rise much above full depth
        if ( canPond && yNew > Node[i].fullDepth )
            yNew = Node[i].fullDepth + FUDGE;
    }

    // --- depth cannot be negative
    if ( yNew < 0 ) yNew = 0.0;

    // --- determine max. non-flooded depth
    yMax = Node[i].fullDepth;
    if ( canPond == FALSE ) yMax += Node[i].surDepth;

    // --- find flooded depth & volume
    if ( yNew > yMax )
    {
        yNew = getFloodedDepth(i, canPond, dV, yNew, yMax, dt);
    }
    else Node[i].newVolume = node_getVolume(i, yNew);

    // --- compute change in depth w.r.t. time
    Xnode[i].dYdT = fabs(yNew - yOld) / dt;

    // --- save new depth for node
    Node[i].newDepth = yNew;
}