/** * This file implements a pump optimization algorithm that: * 1. Models different pumps with efficiency characteristics * 2. Determines all possible pump combinations that can meet a demand flow * 3. Finds the optimal combination that minimizes power consumption * 4. Tests the algorithm with different demand levels */ /** * Pump Class * Represents a pump with specific operating characteristics including: * - Maximum flow capacity * - Center of Gravity (CoG) for efficiency * - Efficiency curve mapping flow percentages to power consumption */ class Pump { constructor(name, maxFlow, cog, efficiencyCurve) { this.name = name; this.maxFlow = maxFlow; // Maximum flow at a given pressure this.CoG = cog; // Efficiency center of gravity percentage this.efficiencyCurve = efficiencyCurve; // Flow % -> Power usage mapping } /** * Returns pump flow at a given pressure * Currently assumes constant flow regardless of pressure */ getFlow(pressure) { return this.maxFlow; // Assume constant flow at a given pressure } /** * Calculates power consumption based on flow and pressure * Uses the efficiency curve when available, otherwise uses linear approximation */ getPowerConsumption(flow, pressure) { let flowPercent = flow / this.maxFlow; return this.efficiencyCurve[flowPercent] || (1.2 * flow); // Default linear approximation } } /** * Test pump definitions * Three pump models with different flow capacities and efficiency characteristics */ const pumps = [ new Pump("Pump A", 100, 0.6, {0.6: 50, 0.8: 70, 1.0: 100}), new Pump("Pump B", 120, 0.7, {0.6: 55, 0.8: 75, 1.0: 110}), new Pump("Pump C", 90, 0.5, {0.5: 40, 0.7: 60, 1.0: 90}), ]; const pressure = 1.0; // Assume constant pressure /** * Get all valid pump combinations that meet the required demand flow (Qd) * * @param {Array} pumps - Available pump array * @param {Number} Qd - Required demand flow * @param {Number} pressure - System pressure * @returns {Array} Array of valid pump combinations that can meet or exceed the demand * * This function: * 1. Generates all possible subsets of pumps (power set) * 2. Filters for non-empty subsets that can meet or exceed demand flow */ function getValidPumpCombinations(pumps, Qd, pressure) { let subsets = [[]]; for (let pump of pumps) { let newSubsets = subsets.map(set => [...set, pump]); subsets = subsets.concat(newSubsets); } return subsets.filter(subset => subset.length > 0 && subset.reduce((sum, p) => sum + p.getFlow(pressure), 0) >= Qd); } /** * Find the optimal pump combination that minimizes power consumption * * @param {Array} pumps - Available pump array * @param {Number} Qd - Required demand flow * @param {Number} pressure - System pressure * @returns {Object} Object containing the best pump combination and its power consumption * * This function: * 1. Gets all valid pump combinations that meet demand * 2. For each combination, distributes flow based on CoG proportions * 3. Calculates total power consumption for each distribution * 4. Returns the combination with minimum power consumption */ function optimizePumpSelection(pumps, Qd, pressure) { let validCombinations = getValidPumpCombinations(pumps, Qd, pressure); let bestCombination = null; let minPower = Infinity; validCombinations.forEach(combination => { let totalFlow = combination.reduce((sum, pump) => sum + pump.getFlow(pressure), 0); let totalCoG = combination.reduce((sum, pump) => sum + pump.CoG, 0); // Distribute flow based on CoG proportions let flowDistribution = combination.map(pump => ({ pump, flow: (pump.CoG / totalCoG) * Qd })); let totalPower = flowDistribution.reduce((sum, { pump, flow }) => sum + pump.getPowerConsumption(flow, pressure), 0); if (totalPower < minPower) { minPower = totalPower; bestCombination = flowDistribution; } }); return { bestCombination, minPower }; } /** * Test function that runs optimization for different demand levels * Tests from 0% to 100% of total available flow in 10% increments * Outputs the selected pumps, flow allocation, and power consumption for each scenario */ console.log("Pump Optimization Results:"); const totalAvailableFlow = pumps.reduce((sum, pump) => sum + pump.getFlow(pressure), 0); for (let i = 0; i <= 10; i++) { let Qd = (i / 10) * totalAvailableFlow; // Incremental flow demand let { bestCombination, minPower } = optimizePumpSelection(pumps, Qd, pressure); console.log(`\nTotal Demand Flow: ${Qd.toFixed(2)}`); console.log("Selected Pumps and Allocated Flow:"); bestCombination.forEach(({ pump, flow }) => { console.log(` ${pump.name}: ${flow.toFixed(2)} units`); }); console.log(`Total Power Consumption: ${minPower.toFixed(2)} kW`); }