To calculate flows in a pipe network with given inputs of pipes and nodes, we can use the Hardy-Cross method for iteratively solving the equations of flow and head loss for each pipe in the network.
// Sample Calculation
// Define inputs
const nodes = [
{ id: 1, demand: -2, elevation: 340 },
{ id: 2, demand: 4, elevation: 330 },
{ id: 3, demand: -2, elevation: 320 },
];
const pipes = [
{ id: 1, fromNode: 1, toNode: 2, length: 1000, diameter: 0.6, roughness: 0.03 },
{ id: 2, fromNode: 2, toNode: 3, length: 800, diameter: 0.6, roughness: 0.03 },
{ id: 3, fromNode: 1, toNode: 3, length: 1200, diameter: 0.6, roughness: 0.03 },
];
// Define constants
const rho = 1000; // density of fluid in kg/m^3
const g = 9.81; // gravitational acceleration in m/s^2
const maxIter = 1000; // maximum number of iterations
const tolerance = 0.001; // tolerance for convergence
// Initialize the unknowns
pipes.forEach(pipe => pipe.flow = 0);
// Define the functions to calculate flow and head loss
function flowRate(p, q, k) {
return (p - q) / k;
}
function headLoss(L, D, f, q) {
const v = q / (Math.PI * D * D / 4); // velocity in m/s
const relRough = D * f / 8 / L;
const hf = relRough * v * v / 2 / g; // head loss in m
return hf;
}
// Run the Hardy-Cross method
let iter = 0;
let maxError = tolerance + 1;
while (iter < maxIter && maxError > tolerance) {
console.log('Iteration', iter + 1);
// Calculate head loss at each pipe with guessed flows
pipes.forEach(pipe => {
const fromNode = nodes.find(node => node.id == pipe.fromNode);
const toNode = nodes.find(node => node.id == pipe.toNode);
const p = fromNode.elevation;
const q = toNode.elevation;
const q1 = pipe.flow;
const q2 = flowRate(p, q, pipe.diameter, pipe.roughness, q1);
const hf = headLoss(pipe.length, pipe.diameter, pipe.roughness, q2);
pipe.headLoss = hf;
console.log(`Pipe ${pipe.id}: flow=${q2.toFixed(3)}, hl=${hf.toFixed(3)}`);
});
// Calculate the flow corrections for each pipe
maxError = 0;
pipes.forEach(pipe => {
let correction = 0;
pipes.forEach(pipe2 => {
if (pipe2.id != pipe.id) {
const factor = (pipe.fromNode == pipe2.fromNode || pipe.fromNode == pipe2.toNode) ? 1 : -1;
correction += factor * pipe2.headLoss;
}
});
correction /= pipe.headLoss;
const tempFlow = pipe.flow + correction;
const error = Math.abs(tempFlow - pipe.flow);
pipe.flow = tempFlow;
if (error > maxError) maxError = error;
});
console.log('Max Error', maxError.toFixed(3));
iter++;
}
// Output the results
console.log('Results:');
pipes.forEach(pipe => console.log(`Pipe ${pipe.id}: flow=${pipe.flow.toFixed(3)}`));
This implementation assumes a steady-state flow and uses the Darcy-Weisbach formula for head loss calculation. The inputs include the pipe network topology, pipe properties, and node demands and elevations. The outputs are the calculated flows in each pipe based on the iterative solution. The implementation can be extended to handle various types of pipe fittings, pumps, reservoirs, and other features.