double form1Eqn(double yc, void* p) // // Input: yc = critical depth // p = pointer to a TCulvert object // Output: returns residual error // Purpose: evaluates the error in satisfying FHWA culvert Equation Form1: // // h/yFull + 0.5*s = yc/yFull + yh/2/yFull + K[ac/aFull*sqrt(g*yh/yFull)]^M // // for a given value of critical depth yc where: // h = inlet depth above culvert invert // s = culvert slope // yFull = full depth of culvert // yh = hydraulic depth at critical depth // ac = flow area at critical depth // g = accel. of gravity // K and M = coefficients // { double ac, wc, yh; TCulvert* culvert = (TCulvert *)p; ac = xsect_getAofY(culvert->xsect, yc); wc = xsect_getWofY(culvert->xsect, yc); yh = ac/wc; culvert->qc = ac * sqrt(GRAVITY * yh); return culvert->hPlus - yc/culvert->yFull - yh/2.0/culvert->yFull - culvert->kk * pow(culvert->qc/culvert->ad, culvert->mm); }
double storage_getOutflow(int j, int i) // // Input: j = node index // i = link index // Output: returns flow from storage node into conduit link (cfs) // Purpose: finds outflow from a storage node into its connecting conduit link // ( non-conduit links have their own getInflow functions). // { int k; double a, y; // --- link must be a conduit if ( Link[i].type != CONDUIT ) return 0.0; // --- find depth of water in conduit y = Node[j].newDepth - Link[i].offset1; // --- return 0 if conduit empty or full flow if full if ( y <= 0.0 ) return 0.0; if ( y >= Link[i].xsect.yFull ) return Link[i].qFull; // --- if partially full, return normal flow k = Link[i].subIndex; a = xsect_getAofY(&Link[i].xsect, y); return Conduit[k].beta * xsect_getSofA(&Link[i].xsect, a); }
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); } }
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; } } }