/// <summary> /// Computes solution matrix coeffs. for PRVs, PSVs & FCVs /// whose status is not fixed to OPEN/CLOSED. /// </summary> public static void ComputeMatrixCoeffs( EpanetNetwork net, LsVariables ls, SparseMatrix smat, List <SimulationValve> valves) { foreach (SimulationValve valve in valves) { if (double.IsNaN(valve.SimSetting)) { continue; } switch (valve.Type) { case LinkType.PRV: valve.PrvCoeff(net, ls, smat); break; case LinkType.PSV: valve.PsvCoeff(net, ls, smat); break; case LinkType.FCV: valve.FcvCoeff(net, ls, smat); break; } } }
/// <summary>Computes solution matrix coeffs. for flow control valve.</summary> private void FcvCoeff(EpanetNetwork net, LsVariables ls, SparseMatrix smat) { int k = Index; double q = setting; int n1 = smat.GetRow(first.Index); int n2 = smat.GetRow(second.Index); // If valve active, break network at valve and treat // flow setting as external demand at upstream node // and external supply at downstream node. if (status == StatType.ACTIVE) { ls.AddNodalInFlow(first.Index, -q); ls.AddRhsCoeff(n1, -q); ls.AddNodalInFlow(second.Index, +q); ls.AddRhsCoeff(n2, +q); invHeadLoss = 1.0 / Constants.CBIG; ls.AddAij(smat.GetNdx(k), -invHeadLoss); ls.AddAii(n1, +invHeadLoss); ls.AddAii(n2, +invHeadLoss); flowCorrection = flow - q; } else { // Otherwise treat valve as an open pipe ValveCoeff(net); ls.AddAij(smat.GetNdx(k), -invHeadLoss); ls.AddAii(n1, +invHeadLoss); ls.AddAii(n2, +invHeadLoss); ls.AddRhsCoeff(n1, +(flowCorrection - flow)); ls.AddRhsCoeff(n2, -(flowCorrection - flow)); } }
/// <summary>Computes solution matrix coeffs. for pressure sustaining valve.</summary> private void PsvCoeff(EpanetNetwork net, LsVariables ls, SparseMatrix smat) { int k = Index; int n1 = smat.GetRow(first.Index); int n2 = smat.GetRow(second.Index); double hset = first.Elevation + setting; if (status == StatType.ACTIVE) { invHeadLoss = 0.0; flowCorrection = flow - ls.GetNodalInFlow(first); ls.AddRhsCoeff(n1, +(hset * Constants.CBIG)); ls.AddAii(n1, +Constants.CBIG); if (ls.GetNodalInFlow(first) > 0.0) { ls.AddRhsCoeff(n2, +ls.GetNodalInFlow(first)); } return; } ValveCoeff(net); ls.AddAij(smat.GetNdx(k), -invHeadLoss); ls.AddAii(n1, +invHeadLoss); ls.AddAii(n2, +invHeadLoss); ls.AddRhsCoeff(n1, +(flowCorrection - flow)); ls.AddRhsCoeff(n2, -(flowCorrection - flow)); }
/// <summary>Computes matrix coeffs. for emitters.</summary> /// <remarks> /// Emitters consist of a fictitious pipe connected to /// a fictitious reservoir whose elevation equals that /// of the junction. The headloss through this pipe is /// Ke*(Flow)^Qexp, where Ke = emitter headloss coeff. /// </remarks> public static void ComputeEmitterCoeffs( EpanetNetwork net, List <SimulationNode> junctions, SparseMatrix smat, LsVariables ls) { foreach (SimulationNode node in junctions) { if (node.Node.Ke == 0.0) { continue; } double ke = Math.Max(Constants.CSMALL, node.Node.Ke); double q = node._emitter; double z = ke * Math.Pow(Math.Abs(q), net.QExp); double p = net.QExp * z / Math.Abs(q); p = p < net.RQtol ? 1.0 / net.RQtol : 1.0 / p; double y = Utilities.GetSignal(q) * z * p; ls.AddAii(smat.GetRow(node.Index), +p); ls.AddRhsCoeff(smat.GetRow(node.Index), +(y + p * node.Node.Elevation)); ls.AddNodalInFlow(node, -q); } }
/// <summary>Computes solution matrix coefficients for links.</summary> public static void ComputeMatrixCoeffs( EpanetNetwork net, PipeHeadModelCalculators.Compute hlModel, IEnumerable <SimulationLink> links, IList <Curve> curves, SparseMatrix smat, LsVariables ls) { foreach (SimulationLink link in links) { link.ComputeMatrixCoeff(net, hlModel, curves, smat, ls); } }
/// <summary>Compute P, Y and matrix coeffs.</summary> private void ComputeMatrixCoeff( EpanetNetwork net, PipeHeadModelCalculators.Compute hlModel, IList <Curve> curves, SparseMatrix smat, LsVariables ls) { switch (Type) { // Pipes case LinkType.CV: case LinkType.PIPE: ComputePipeCoeff(net, hlModel); break; // Pumps case LinkType.PUMP: ((SimulationPump)this).ComputePumpCoeff(net); break; // Valves case LinkType.PBV: case LinkType.TCV: case LinkType.GPV: case LinkType.FCV: case LinkType.PRV: case LinkType.PSV: // If valve status fixed then treat as pipe // otherwise ignore the valve for now. if (!((SimulationValve)this).ComputeValveCoeff(net, curves)) { return; } break; default: return; } int n1 = first.Index; int n2 = second.Index; ls.AddNodalInFlow(n1, -flow); ls.AddNodalInFlow(n2, +flow); ls.AddAij(smat.GetNdx(Index), -invHeadLoss); if (!(first is SimulationTank)) { ls.AddAii(smat.GetRow(n1), +invHeadLoss); ls.AddRhsCoeff(smat.GetRow(n1), +flowCorrection); } else { ls.AddRhsCoeff(smat.GetRow(n2), +(invHeadLoss * first.SimHead)); } if (!(second is SimulationTank)) { ls.AddAii(smat.GetRow(n2), +invHeadLoss); ls.AddRhsCoeff(smat.GetRow(n2), -flowCorrection); } else { ls.AddRhsCoeff(smat.GetRow(n1), +(invHeadLoss * second.SimHead)); } }
/// <summary>Completes calculation of nodal flow imbalance (X) flow correction (F) arrays.</summary> public static void ComputeNodeCoeffs(List <SimulationNode> junctions, SparseMatrix smat, LsVariables ls) { foreach (SimulationNode node in junctions) { ls.AddNodalInFlow(node, -node.demand); ls.AddRhsCoeff(smat.GetRow(node.Index), +ls.GetNodalInFlow(node)); } }