MEASUR-Tools-Suite v1.0.11
The MEASUR Tools Suite is a collection of industrial efficiency calculations written in C++ and with bindings for compilation to WebAssembly.
Loading...
Searching...
No Matches
process_cooling.h
1#pragma once
2
22#include <cmath>
23#include <fstream>
24#include <iostream>
25#include <sstream>
26#include <string>
27#include <utility>
28#include <vector>
29
30using namespace std;
31
32const int MONTHS = 12;
33const int LOAD_NUM = 11;
34const int HOURS_IN_YEAR = 8760;
35
49 public:
50 enum RefrigerantType { R_11, R_123, R_12, R_134a, R_22, R_717 };
51
52 enum ACSourceLocation { Inside, Outside };
53
54 enum CoolingSystemType { Water, Air };
55
56 enum CellFanType { AxialFan, CentrifugalFan };
57
58 enum TowerSizedBy { Tonnage, Fan_HP };
59
60 enum ChillerCompressorType { Centrifugal, Screw, Reciprocating };
61
62 enum FanMotorSpeedType { One, Two, Variable };
63
74 ChillerOutput(vector<vector<double>> efficiency, vector<vector<double>> hours, vector<vector<double>> power,
75 vector<vector<double>> energy)
76 : efficiency(std::move(efficiency)), hours(std::move(hours)), power(std::move(power)),
77 energy(std::move(energy)) {}
78
79 vector<vector<double>> efficiency;
80 vector<vector<double>> hours;
81 vector<vector<double>> power;
82 vector<vector<double>> energy;
83 };
84
92 explicit ChillerPumpingEnergyOutput(vector<double> pumpingEnergy)
93 : chillerPumpingEnergy(std::move(pumpingEnergy)) {}
94
95 vector<double> chillerPumpingEnergy;
96 };
97
98 struct TowerOutput {
103 TowerOutput() = default;
104
113 TowerOutput(vector<double> hours, vector<double> energy) : hours(std::move(hours)), energy(std::move(energy)) {}
114
115 vector<double> tempBins = {35, 45, 55, 65, 75, 75};
116 vector<double> hours;
117 vector<double> energy;
118 };
119
126
138 WaterCooledSystemInput(double CHWT, bool useFreeCooling, double HEXApproachTemp, bool constantCWT, double CWT,
139 bool CWVariableFlow, double CWFlowRate, double CWTFollow)
140 : CHWT(CHWT), useFreeCooling(useFreeCooling), HEXApproachTemp(HEXApproachTemp), constantCWT(constantCWT),
141 CWT(CWT), CWVariableFlow(CWVariableFlow), CWFlowRate(CWFlowRate), CWTFollow(CWTFollow) {
142 isWaterCooled = true;
143 }
144
145 double CHWT = 44;
146 bool useFreeCooling = false;
147 double HEXApproachTemp = 0;
148 bool constantCWT = true;
149 double CWT = 85;
150 bool CWVariableFlow = true;
151 double CWFlowRate = 3;
152 double CWTFollow = 0;
153 bool isWaterCooled = false;
154 };
155
162
171 AirCooledSystemInput(double CHWT, double OADT, ACSourceLocation ACSource, double indoorTemp, double CWTFollow)
172 : CHWT(CHWT), OADT(OADT), ACSource(ACSource), indoorTemp(indoorTemp), CWTFollow(CWTFollow) {
173 isAirCooled = true;
174 }
175
176 double CHWT = 44;
177 double OADT = 95;
178 ACSourceLocation ACSource = ACSourceLocation::Outside;
179 double indoorTemp = 75;
180 double CWTFollow = 0;
181 bool isAirCooled = false;
182 };
183
184 struct PumpInput {
193 PumpInput(bool variableFlow, double flowRate, double efficiency, double motorSize, double motorEfficiency)
194 : variableFlow(variableFlow), flowRate(flowRate), efficiency(efficiency * 100), motorSize(motorSize),
195 motorEfficiency(motorEfficiency * 100) {}
196
197 bool variableFlow;
198 double flowRate;
199 double efficiency;
200 double motorSize;
201 double motorEfficiency;
202 };
203
204 struct TowerInput {
209 TowerInput() = default;
210
221 TowerInput(int numTower, int numFanPerTower_Cells, FanMotorSpeedType fanSpeedType, TowerSizedBy towerSizing,
222 CellFanType towerCellFanType, double cellFanHP, double tonnage)
223 : numTower(numTower), numFanPerTower_Cells(numFanPerTower_Cells), fanSpeedType(fanSpeedType),
224 fanHP(cellFanHP), tonnage(tonnage) {
225 fanHP = getFanHP(tonnage, towerSizing, numFanPerTower_Cells, towerCellFanType, fanHP);
226 }
227
228 int numTower;
229 int numFanPerTower_Cells;
230 FanMotorSpeedType fanSpeedType;
231 double fanHP;
232 double tonnage;
233 };
234
251 ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff,
252 double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector<vector<double>> monthlyLoads)
253 : chillerType(chillerType), capacity(capacity), isFullLoadEffKnown(isFullLoadEffKnown),
254 fullLoadEff(fullLoadEff), age(age), installVSD(installVSD),
255 useARIMonthlyLoadSchedule(useARIMonthlyLoadSchedule), monthlyLoads(std::move(monthlyLoads)),
256 isCustomChiller(false), loadAtPercent({}), kwPerTonLoads({}), changeRefrig(false),
257 currentRefrig(RefrigerantType::R_11), proposedRefrig(RefrigerantType::R_11) {
258 InitNonVaryingMonthlyLoad();
259 }
260
279 ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff,
280 double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector<vector<double>> monthlyLoads,
281 bool changeRefrig, RefrigerantType currentRefrig, RefrigerantType proposedRefrig)
282 : chillerType(chillerType), capacity(capacity), isFullLoadEffKnown(isFullLoadEffKnown),
283 fullLoadEff(fullLoadEff), age(age), installVSD(installVSD),
284 useARIMonthlyLoadSchedule(useARIMonthlyLoadSchedule), monthlyLoads(std::move(monthlyLoads)),
285 isCustomChiller(false), loadAtPercent({}), kwPerTonLoads({}), changeRefrig(changeRefrig),
286 currentRefrig(currentRefrig), proposedRefrig(proposedRefrig) {
287 InitNonVaryingMonthlyLoad();
288 }
289
308 ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff,
309 double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector<vector<double>> monthlyLoads,
310 RefrigerantType currentRefrig, RefrigerantType proposedRefrig)
311 : chillerType(chillerType), capacity(capacity), isFullLoadEffKnown(isFullLoadEffKnown),
312 fullLoadEff(fullLoadEff), age(age), installVSD(installVSD),
313 useARIMonthlyLoadSchedule(useARIMonthlyLoadSchedule), monthlyLoads(std::move(monthlyLoads)),
314 isCustomChiller(false), loadAtPercent({}), kwPerTonLoads({}), changeRefrig(true),
315 currentRefrig(currentRefrig), proposedRefrig(proposedRefrig) {
316 InitNonVaryingMonthlyLoad();
317 }
318
337 ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff,
338 double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector<vector<double>> monthlyLoads,
339 vector<double> loadAtPercent, vector<double> kwPerTonLoads)
340 : chillerType(chillerType), capacity(capacity), isFullLoadEffKnown(isFullLoadEffKnown),
341 fullLoadEff(fullLoadEff), age(age), installVSD(installVSD),
342 useARIMonthlyLoadSchedule(useARIMonthlyLoadSchedule), monthlyLoads(std::move(monthlyLoads)),
343 isCustomChiller(true), loadAtPercent(std::move(loadAtPercent)), kwPerTonLoads(std::move(kwPerTonLoads)),
344 changeRefrig(false), currentRefrig(RefrigerantType::R_11), proposedRefrig(RefrigerantType::R_11) {
345 InitNonVaryingMonthlyLoad();
346 SetCustomCoefficient();
347 }
348
370 ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff,
371 double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector<vector<double>> monthlyLoads,
372 vector<double> loadAtPercent, vector<double> kwPerTonLoads, RefrigerantType currentRefrig,
373 RefrigerantType proposedRefrig)
374 : chillerType(chillerType), capacity(capacity), isFullLoadEffKnown(isFullLoadEffKnown),
375 fullLoadEff(fullLoadEff), age(age), installVSD(installVSD),
376 useARIMonthlyLoadSchedule(useARIMonthlyLoadSchedule), monthlyLoads(std::move(monthlyLoads)),
377 isCustomChiller(true), loadAtPercent(std::move(loadAtPercent)), kwPerTonLoads(std::move(kwPerTonLoads)),
378 changeRefrig(true), currentRefrig(currentRefrig), proposedRefrig(proposedRefrig) {
379 InitNonVaryingMonthlyLoad();
380 SetCustomCoefficient();
381 }
382
383 ChillerCompressorType chillerType;
384 double capacity;
385 bool isFullLoadEffKnown;
386 double fullLoadEff;
387 double age;
388 bool installVSD;
389 bool useARIMonthlyLoadSchedule;
390 vector<vector<double>> monthlyLoads;
391
392 bool isCustomChiller;
393 vector<double> loadAtPercent;
394 vector<double> kwPerTonLoads;
395
396 bool changeRefrig = false;
397 RefrigerantType currentRefrig;
398 RefrigerantType proposedRefrig;
399
400 vector<double> customCoeffs;
401
402 private:
403 void InitNonVaryingMonthlyLoad() {
404 if (monthlyLoads.size() == 1) {
405 auto monthlyLoad = monthlyLoads[0];
406
407 for (int i = 0; i < 11; i++) {
408 monthlyLoads.push_back(monthlyLoad);
409 }
410 }
411 }
412
413 void SetCustomCoefficient() {
414 auto size = static_cast<int>(loadAtPercent.size());
415 vector<double> x(size, 0);
416 vector<double> y(size, 0);
417 for (int i = 0; i < size; i++) {
418 x[i] = loadAtPercent[i];
419 y[i] = kwPerTonLoads[i] * loadAtPercent[i] / kwPerTonLoads[0];
420 }
421 vector<double> coeff = solveForCoefficients(x, y);
422
423 size = static_cast<int>(coeff.size());
424 customCoeffs.resize(size, 0);
425 for (int i = 0; i < size; i++) {
426 customCoeffs[i] = coeff[i];
427 }
428 }
429
430 static vector<double> solveForCoefficients(vector<double> x, vector<double> y) {
431 if (x.empty() || x.size() != y.size())
432 return {};
433
434 const int n = (int)x.size();
435
436 vector<vector<double>> a(n, vector<double>(n, 0));
437 for (int i = 0; i < n; ++i) {
438 for (int j = 0; j < n; ++j) {
439 a[i][j] = pow(x[i], n - 1 - j);
440 }
441 }
442
443 // Forward Elimination
444 for (int k = 0; k < n - 1; ++k) {
445 for (int i = k + 1; i < n; ++i) {
446 double factor = a[i][k] / a[k][k];
447 for (int j = k + 1; j < n; ++j) {
448 a[i][j] -= factor * a[k][j];
449 }
450 y[i] -= factor * y[k];
451 }
452 }
453
454 // Back Substitution
455 vector<double> coeff(n, 0);
456 coeff[n - 1] = y[n - 1] / a[n - 1][n - 1];
457 for (int i = n - 2; i >= 0; --i) {
458 double sum = y[i];
459 for (int j = i + 1; j < n; ++j) {
460 sum -= a[i][j] * coeff[j];
461 }
462 coeff[i] = sum / a[i][i];
463 }
464
465 return coeff;
466 }
467 };
468
469 ~ProcessCooling() = default;
470
485 ProcessCooling(const vector<int>& systemOperationAnnualHours, const vector<double>& weatherDryBulbHourlyTemp,
486 const vector<double>& weatherWetBulbHourlyTemp, const vector<ChillerInput>& chillerInputList,
487 TowerInput towerInput, WaterCooledSystemInput waterCooledSystemInput)
488 : ProcessCooling(systemOperationAnnualHours, weatherDryBulbHourlyTemp, weatherWetBulbHourlyTemp,
489 chillerInputList, {}, towerInput, waterCooledSystemInput) {}
490
502 ProcessCooling(const vector<int>& systemOperationAnnualHours, const vector<double>& weatherDryBulbHourlyTemp,
503 const vector<double>& weatherWetBulbHourlyTemp, const vector<ChillerInput>& chillerInputList,
504 AirCooledSystemInput airCooledSystemInput)
505 : ProcessCooling(systemOperationAnnualHours, weatherDryBulbHourlyTemp, weatherWetBulbHourlyTemp,
506 chillerInputList, airCooledSystemInput, {}, {}) {}
507
513
519
526
538 static vector<int> getSysOpAnnualHours(const vector<int>& weeklyOpStartHour, const vector<int>& weeklyOpStopHour, const vector<int>& monthlyOpMaxHour);
539
540 private:
541 ProcessCooling(const vector<int>& systemOperationAnnualHours, const vector<double>& weatherDryBulbHourlyTemp,
542 const vector<double>& weatherWetBulbHourlyTemp, const vector<ChillerInput>& chillerInputList,
543 AirCooledSystemInput airCooledSystemInput, TowerInput towerInput,
544 WaterCooledSystemInput waterCooledSystemInput);
545
546 vector<int> systemOperationAnnual;
547 vector<double> dryBulbHourlyTemp;
548 vector<double> wetBulbHourlyTemp;
549
550 TowerInput tower {};
551 WaterCooledSystemInput waterCooledSystem;
552 AirCooledSystemInput airCooledSystem;
553 CoolingSystemType coolingType;
554
555 double FCTemp = 0; // Free Cooling Temperature
556 vector<double> CWTHourly;
557
558 int numChillers;
559 vector<ChillerInput> chillers;
560 vector<vector<double>> chillerHourlyLoad;
561 vector<vector<double>> chillerHourlyLoadOperational;
562 vector<vector<double>> chillerHourlyEfficiencyARI;
563 vector<vector<double>> chillerHourlyEfficiency;
564 vector<vector<double>> chillerHourlyPower;
565
566 void annualChillerLoadProfile();
567
568 void annualChillerEfficiencyProfileARI();
569
570 void annualChillerEfficiencyProfile();
571
572 void annualChillerPowerProfile();
573
574 static double getFanHP(double tonnage, TowerSizedBy towerSizing, int fanNum, CellFanType fanType, double fanHP);
575
576 double getPercentFanPower(double wetBulbTemp, double percentWaterFlow, double range, double desiredApproach,
577 int yearHourIndex);
578
579 double getPercentWaterFlow(int yearHourIndex);
580
581 double getRange(int yearHourIndex);
582
583 double getApproach(double wetBulbTemp, double minToChillersTemp) const;
584
585 double modifyPercentFanPower(double percentFanPower) const;
586
587 double getWeightedAverageChillerLoad(int yearHourIndex);
588
589 double getChillerTonnageTotal();
590
591 static double getCubeRoot(double number);
592
593 static double getPumpHP(double power);
594};
595
Calculator estimates energy consumption of operating Chillers, Pumps and Towers in a cooling system (...
TowerOutput calculateTowerEnergy()
ChillerOutput calculateChillerEnergy()
ProcessCooling(const vector< int > &systemOperationAnnualHours, const vector< double > &weatherDryBulbHourlyTemp, const vector< double > &weatherWetBulbHourlyTemp, const vector< ChillerInput > &chillerInputList, AirCooledSystemInput airCooledSystemInput)
ChillerPumpingEnergyOutput calculatePumpEnergy(PumpInput pump)
static vector< int > getSysOpAnnualHours(const vector< int > &weeklyOpStartHour, const vector< int > &weeklyOpStopHour, const vector< int > &monthlyOpMaxHour)
ProcessCooling(const vector< int > &systemOperationAnnualHours, const vector< double > &weatherDryBulbHourlyTemp, const vector< double > &weatherWetBulbHourlyTemp, const vector< ChillerInput > &chillerInputList, TowerInput towerInput, WaterCooledSystemInput waterCooledSystemInput)
AirCooledSystemInput(double CHWT, double OADT, ACSourceLocation ACSource, double indoorTemp, double CWTFollow)
ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff, double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector< vector< double > > monthlyLoads, bool changeRefrig, RefrigerantType currentRefrig, RefrigerantType proposedRefrig)
ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff, double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector< vector< double > > monthlyLoads, RefrigerantType currentRefrig, RefrigerantType proposedRefrig)
ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff, double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector< vector< double > > monthlyLoads)
ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff, double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector< vector< double > > monthlyLoads, vector< double > loadAtPercent, vector< double > kwPerTonLoads)
ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff, double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector< vector< double > > monthlyLoads, vector< double > loadAtPercent, vector< double > kwPerTonLoads, RefrigerantType currentRefrig, RefrigerantType proposedRefrig)
ChillerOutput(vector< vector< double > > efficiency, vector< vector< double > > hours, vector< vector< double > > power, vector< vector< double > > energy)
ChillerPumpingEnergyOutput(vector< double > pumpingEnergy)
PumpInput(bool variableFlow, double flowRate, double efficiency, double motorSize, double motorEfficiency)
TowerInput(int numTower, int numFanPerTower_Cells, FanMotorSpeedType fanSpeedType, TowerSizedBy towerSizing, CellFanType towerCellFanType, double cellFanHP, double tonnage)
TowerOutput(vector< double > hours, vector< double > energy)
WaterCooledSystemInput(double CHWT, bool useFreeCooling, double HEXApproachTemp, bool constantCWT, double CWT, bool CWVariableFlow, double CWFlowRate, double CWTFollow)