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
ProcessCooling.h
1
20#ifndef TOOLS_SUITE_PROCESSCOOLING_H
21#define TOOLS_SUITE_PROCESSCOOLING_H
22
23#include <cmath>
24#include <fstream>
25#include <iostream>
26#include <sstream>
27#include <string>
28#include <utility>
29#include <vector>
30
31using namespace std;
32
33const int MONTHS = 12;
34const int LOAD_NUM = 11;
35const int HOURS_IN_YEAR = 8760;
36
38 public:
39 enum RefrigerantType { R_11, R_123, R_12, R_134a, R_22, R_717 };
40
41 enum ACSourceLocation { Inside, Outside };
42
43 enum CoolingSystemType { Water, Air };
44
45 enum CellFanType { AxialFan, CentrifugalFan };
46
47 enum TowerSizedBy { Tonnage, Fan_HP };
48
49 enum ChillerCompressorType { Centrifugal, Screw, Reciprocating };
50
51 enum FanMotorSpeedType { One, Two, Variable };
52
63 ChillerOutput(vector<vector<double>> efficiency, vector<vector<double>> hours, vector<vector<double>> power,
64 vector<vector<double>> energy)
65 : efficiency(std::move(efficiency)), hours(std::move(hours)), power(std::move(power)),
66 energy(std::move(energy)) {}
67
68 vector<vector<double>> efficiency;
69 vector<vector<double>> hours;
70 vector<vector<double>> power;
71 vector<vector<double>> energy;
72 };
73
81 explicit ChillerPumpingEnergyOutput(vector<double> pumpingEnergy)
82 : chillerPumpingEnergy(std::move(pumpingEnergy)) {}
83
84 vector<double> chillerPumpingEnergy;
85 };
86
87 struct TowerOutput {
92 TowerOutput() = default;
93
102 TowerOutput(vector<double> hours, vector<double> energy) : hours(std::move(hours)), energy(std::move(energy)) {}
103
104 vector<double> tempBins = {35, 45, 55, 65, 75, 75};
105 vector<double> hours;
106 vector<double> energy;
107 };
108
115
127 WaterCooledSystemInput(double CHWT, bool useFreeCooling, double HEXApproachTemp, bool constantCWT, double CWT,
128 bool CWVariableFlow, double CWFlowRate, double CWTFollow)
129 : CHWT(CHWT), useFreeCooling(useFreeCooling), HEXApproachTemp(HEXApproachTemp), constantCWT(constantCWT),
130 CWT(CWT), CWVariableFlow(CWVariableFlow), CWFlowRate(CWFlowRate), CWTFollow(CWTFollow) {
131 isWaterCooled = true;
132 }
133
134 double CHWT = 44;
135 bool useFreeCooling = false;
136 double HEXApproachTemp = 0;
137 bool constantCWT = true;
138 double CWT = 85;
139 bool CWVariableFlow = true;
140 double CWFlowRate = 3;
141 double CWTFollow = 0;
142 bool isWaterCooled = false;
143 };
144
151
160 AirCooledSystemInput(double CHWT, double OADT, ACSourceLocation ACSource, double indoorTemp, double CWTFollow)
161 : CHWT(CHWT), OADT(OADT), ACSource(ACSource), indoorTemp(indoorTemp), CWTFollow(CWTFollow) {
162 isAirCooled = true;
163 }
164
165 double CHWT = 44;
166 double OADT = 95;
167 ACSourceLocation ACSource = ACSourceLocation::Outside;
168 double indoorTemp = 75;
169 double CWTFollow = 0;
170 bool isAirCooled = false;
171 };
172
173 struct PumpInput {
182 PumpInput(bool variableFlow, double flowRate, double efficiency, double motorSize, double motorEfficiency)
183 : variableFlow(variableFlow), flowRate(flowRate), efficiency(efficiency * 100), motorSize(motorSize),
184 motorEfficiency(motorEfficiency * 100) {}
185
186 bool variableFlow;
187 double flowRate;
188 double efficiency;
189 double motorSize;
190 double motorEfficiency;
191 };
192
193 struct TowerInput {
198 TowerInput() = default;
199
210 TowerInput(int numTower, int numFanPerTower_Cells, FanMotorSpeedType fanSpeedType, TowerSizedBy towerSizing,
211 CellFanType towerCellFanType, double cellFanHP, double tonnage)
212 : numTower(numTower), numFanPerTower_Cells(numFanPerTower_Cells), fanSpeedType(fanSpeedType),
213 fanHP(cellFanHP), tonnage(tonnage) {
214 fanHP = getFanHP(tonnage, towerSizing, numFanPerTower_Cells, towerCellFanType, fanHP);
215 }
216
217 int numTower;
218 int numFanPerTower_Cells;
219 FanMotorSpeedType fanSpeedType;
220 double fanHP;
221 double tonnage;
222 };
223
240 ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff,
241 double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector<vector<double>> monthlyLoads)
242 : chillerType(chillerType), capacity(capacity), isFullLoadEffKnown(isFullLoadEffKnown),
243 fullLoadEff(fullLoadEff), age(age), installVSD(installVSD),
244 useARIMonthlyLoadSchedule(useARIMonthlyLoadSchedule), monthlyLoads(std::move(monthlyLoads)),
245 isCustomChiller(false), loadAtPercent({}), kwPerTonLoads({}), changeRefrig(false),
246 currentRefrig(RefrigerantType::R_11), proposedRefrig(RefrigerantType::R_11) {
247 InitNonVaryingMonthlyLoad();
248 }
249
268 ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff,
269 double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector<vector<double>> monthlyLoads,
270 bool changeRefrig, RefrigerantType currentRefrig, RefrigerantType proposedRefrig)
271 : chillerType(chillerType), capacity(capacity), isFullLoadEffKnown(isFullLoadEffKnown),
272 fullLoadEff(fullLoadEff), age(age), installVSD(installVSD),
273 useARIMonthlyLoadSchedule(useARIMonthlyLoadSchedule), monthlyLoads(std::move(monthlyLoads)),
274 isCustomChiller(false), loadAtPercent({}), kwPerTonLoads({}), changeRefrig(changeRefrig),
275 currentRefrig(currentRefrig), proposedRefrig(proposedRefrig) {
276 InitNonVaryingMonthlyLoad();
277 }
278
297 ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff,
298 double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector<vector<double>> monthlyLoads,
299 RefrigerantType currentRefrig, RefrigerantType proposedRefrig)
300 : chillerType(chillerType), capacity(capacity), isFullLoadEffKnown(isFullLoadEffKnown),
301 fullLoadEff(fullLoadEff), age(age), installVSD(installVSD),
302 useARIMonthlyLoadSchedule(useARIMonthlyLoadSchedule), monthlyLoads(std::move(monthlyLoads)),
303 isCustomChiller(false), loadAtPercent({}), kwPerTonLoads({}), changeRefrig(true),
304 currentRefrig(currentRefrig), proposedRefrig(proposedRefrig) {
305 InitNonVaryingMonthlyLoad();
306 }
307
326 ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff,
327 double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector<vector<double>> monthlyLoads,
328 vector<double> loadAtPercent, vector<double> kwPerTonLoads)
329 : chillerType(chillerType), capacity(capacity), isFullLoadEffKnown(isFullLoadEffKnown),
330 fullLoadEff(fullLoadEff), age(age), installVSD(installVSD),
331 useARIMonthlyLoadSchedule(useARIMonthlyLoadSchedule), monthlyLoads(std::move(monthlyLoads)),
332 isCustomChiller(true), loadAtPercent(std::move(loadAtPercent)), kwPerTonLoads(std::move(kwPerTonLoads)),
333 changeRefrig(false), currentRefrig(RefrigerantType::R_11), proposedRefrig(RefrigerantType::R_11) {
334 InitNonVaryingMonthlyLoad();
335 SetCustomCoefficient();
336 }
337
359 ChillerInput(ChillerCompressorType chillerType, double capacity, bool isFullLoadEffKnown, double fullLoadEff,
360 double age, bool installVSD, bool useARIMonthlyLoadSchedule, vector<vector<double>> monthlyLoads,
361 vector<double> loadAtPercent, vector<double> kwPerTonLoads, RefrigerantType currentRefrig,
362 RefrigerantType proposedRefrig)
363 : chillerType(chillerType), capacity(capacity), isFullLoadEffKnown(isFullLoadEffKnown),
364 fullLoadEff(fullLoadEff), age(age), installVSD(installVSD),
365 useARIMonthlyLoadSchedule(useARIMonthlyLoadSchedule), monthlyLoads(std::move(monthlyLoads)),
366 isCustomChiller(true), loadAtPercent(std::move(loadAtPercent)), kwPerTonLoads(std::move(kwPerTonLoads)),
367 changeRefrig(true), currentRefrig(currentRefrig), proposedRefrig(proposedRefrig) {
368 InitNonVaryingMonthlyLoad();
369 SetCustomCoefficient();
370 }
371
372 ChillerCompressorType chillerType;
373 double capacity;
374 bool isFullLoadEffKnown;
375 double fullLoadEff;
376 double age;
377 bool installVSD;
378 bool useARIMonthlyLoadSchedule;
379 vector<vector<double>> monthlyLoads;
380
381 bool isCustomChiller;
382 vector<double> loadAtPercent;
383 vector<double> kwPerTonLoads;
384
385 bool changeRefrig = false;
386 RefrigerantType currentRefrig;
387 RefrigerantType proposedRefrig;
388
389 vector<double> customCoeffs;
390
391 private:
392 void InitNonVaryingMonthlyLoad() {
393 if (monthlyLoads.size() == 1) {
394 auto monthlyLoad = monthlyLoads[0];
395
396 for (int i = 0; i < 11; i++) {
397 monthlyLoads.push_back(monthlyLoad);
398 }
399 }
400 }
401
402 void SetCustomCoefficient() {
403 auto size = static_cast<int>(loadAtPercent.size());
404 vector<double> x(size, 0);
405 vector<double> y(size, 0);
406 for (int i = 0; i < size; i++) {
407 x[i] = loadAtPercent[i];
408 y[i] = kwPerTonLoads[i] * loadAtPercent[i] / kwPerTonLoads[0];
409 }
410 vector<double> coeff = solveForCoefficients(x, y);
411
412 size = static_cast<int>(coeff.size());
413 customCoeffs.resize(size, 0);
414 for (int i = 0; i < size; i++) {
415 customCoeffs[i] = coeff[i];
416 }
417 }
418
419 static vector<double> solveForCoefficients(vector<double> x, vector<double> y) {
420 if (x.empty() || x.size() != y.size())
421 return {};
422
423 const int n = (int)x.size();
424
425 vector<vector<double>> a(n, vector<double>(n, 0));
426 for (int i = 0; i < n; ++i) {
427 for (int j = 0; j < n; ++j) {
428 a[i][j] = pow(x[i], n - 1 - j);
429 }
430 }
431
432 // Forward Elimination
433 for (int k = 0; k < n - 1; ++k) {
434 for (int i = k + 1; i < n; ++i) {
435 double factor = a[i][k] / a[k][k];
436 for (int j = k + 1; j < n; ++j) {
437 a[i][j] -= factor * a[k][j];
438 }
439 y[i] -= factor * y[k];
440 }
441 }
442
443 // Back Substitution
444 vector<double> coeff(n, 0);
445 coeff[n - 1] = y[n - 1] / a[n - 1][n - 1];
446 for (int i = n - 2; i >= 0; --i) {
447 double sum = y[i];
448 for (int j = i + 1; j < n; ++j) {
449 sum -= a[i][j] * coeff[j];
450 }
451 coeff[i] = sum / a[i][i];
452 }
453
454 return coeff;
455 }
456 };
457
458 ~ProcessCooling() = default;
459
474 ProcessCooling(const vector<int>& systemOperationAnnualHours, const vector<double>& weatherDryBulbHourlyTemp,
475 const vector<double>& weatherWetBulbHourlyTemp, const vector<ChillerInput>& chillerInputList,
476 TowerInput towerInput, WaterCooledSystemInput waterCooledSystemInput)
477 : ProcessCooling(systemOperationAnnualHours, weatherDryBulbHourlyTemp, weatherWetBulbHourlyTemp,
478 chillerInputList, {}, towerInput, waterCooledSystemInput) {}
479
491 ProcessCooling(const vector<int>& systemOperationAnnualHours, const vector<double>& weatherDryBulbHourlyTemp,
492 const vector<double>& weatherWetBulbHourlyTemp, const vector<ChillerInput>& chillerInputList,
493 AirCooledSystemInput airCooledSystemInput)
494 : ProcessCooling(systemOperationAnnualHours, weatherDryBulbHourlyTemp, weatherWetBulbHourlyTemp,
495 chillerInputList, airCooledSystemInput, {}, {}) {}
496
502
508
515
516 private:
517 ProcessCooling(const vector<int>& systemOperationAnnualHours, const vector<double>& weatherDryBulbHourlyTemp,
518 const vector<double>& weatherWetBulbHourlyTemp, const vector<ChillerInput>& chillerInputList,
519 AirCooledSystemInput airCooledSystemInput, TowerInput towerInput,
520 WaterCooledSystemInput waterCooledSystemInput);
521
522 vector<int> systemOperationAnnual;
523 vector<double> dryBulbHourlyTemp;
524 vector<double> wetBulbHourlyTemp;
525
526 TowerInput tower {};
527 WaterCooledSystemInput waterCooledSystem;
528 AirCooledSystemInput airCooledSystem;
529 CoolingSystemType coolingType;
530
531 double FCTemp = 0; // Free Cooling Temperature
532 vector<double> CWTHourly;
533
534 int numChillers;
535 vector<ChillerInput> chillers;
536 vector<vector<double>> chillerHourlyLoad;
537 vector<vector<double>> chillerHourlyLoadOperational;
538 vector<vector<double>> chillerHourlyEfficiencyARI;
539 vector<vector<double>> chillerHourlyEfficiency;
540 vector<vector<double>> chillerHourlyPower;
541
542 void annualChillerLoadProfile();
543
544 void annualChillerEfficiencyProfileARI();
545
546 void annualChillerEfficiencyProfile();
547
548 void annualChillerPowerProfile();
549
550 static double getFanHP(double tonnage, TowerSizedBy towerSizing, int fanNum, CellFanType fanType, double fanHP);
551
552 double getPercentFanPower(double wetBulbTemp, double percentWaterFlow, double range, double desiredApproach,
553 int yearHourIndex);
554
555 double getPercentWaterFlow(int yearHourIndex);
556
557 double getRange(int yearHourIndex);
558
559 double getApproach(double wetBulbTemp, double minToChillersTemp) const;
560
561 double modifyPercentFanPower(double percentFanPower) const;
562
563 double getWeightedAverageChillerLoad(int yearHourIndex);
564
565 double getChillerTonnageTotal();
566
567 static double getCubeRoot(double number);
568
569 static double getPumpHP(double power);
570};
571
572#endif // TOOLS_SUITE_PROCESSCOOLING_H
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)
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)