AMO-Tools-Suite  v.0.9.0
Set of tools for calculating energy efficiency in industrial equipment
All Classes Namespaces Files Functions Variables Enumerations Friends Macros Pages
Fan203.h
1 
11 #ifndef AMO_TOOLS_SUITE_FAN_H
12 #define AMO_TOOLS_SUITE_FAN_H
13 
14 #include <string>
15 #include <unordered_map>
16 #include <cmath>
17 #include <vector>
18 #include <stdexcept>
19 #include <functional>
20 #include "Planar.h"
21 #include "FanShaftPower.h"
22 
23 #include <fstream>
24 #include <iostream>
25 
26 class FanRatedInfo;
27 class Planar;
28 class FlangePlane;
29 class TraversePlane;
30 class MstPlane;
36 class BaseGasDensity
37 {
38 public:
43  enum class GasType
44  {
45  AIR,
46  STANDARDAIR,
47  OTHERGAS
48  };
53  enum class InputType
54  {
55  DewPoint,
56  RelativeHumidity,
57  WetBulbTemp
58  };
59 
67  // used for method 1
68  BaseGasDensity(const double dryBulbTemp, const double staticPressure, const double barometricPressure,
69  const double gasDensity, const GasType gasType)
70  : tdo(dryBulbTemp), pso(staticPressure), pbo(barometricPressure), gasDensity(gasDensity), gasType(gasType)
71  {
72  }
92  // TODO ensure correctness
93  BaseGasDensity(double const dryBulbTemp, double const staticPressure, double const barometricPressure,
94  double const relativeHumidityOrDewPoint, GasType const gasType,
95  InputType const inputType, double const specificGravity)
96  : tdo(dryBulbTemp), pso(staticPressure), pbo(barometricPressure), g(specificGravity), gasType(gasType)
97  {
98  saturationPressure = calculateSaturationPressure(tdo);
99  relativeHumidity = 0;
100  if (inputType == InputType::RelativeHumidity)
101  {
102  relativeHumidity = relativeHumidityOrDewPoint / 100;
103  }
104  else if (inputType == InputType::DewPoint)
105  {
106  relativeHumidity = calculateSaturationPressure(relativeHumidityOrDewPoint) / saturationPressure;
107  }
108  else if (inputType == InputType::WetBulbTemp)
109  {
110  throw std::runtime_error("The wrong constructor for BaseGasDensity was called here - check inputType field");
111  }
112 
113  calculateFanAttributes(inputType, relativeHumidityOrDewPoint);
114 
115  /*
116  std::ofstream fout;
117  fout.open("debug.txt", std::ios::app);
118  fout << "gasDensity: " << gasDensity << std::endl;
119  fout << "absolutePressure: " << absolutePressure << std::endl;
120  fout << "saturatedHumidity: " << saturatedHumidity << std::endl;
121  fout << "saturationDegree: " << saturationDegree << std::endl;
122  fout << "humidityRatio: " << humidityRatio << std::endl;
123  fout << "specificVolume: " << specificVolume << std::endl;
124  fout << "enthalpy: " << enthalpy << std::endl;
125  fout << "dewPoint: " << dewPoint << std::endl;
126  fout << "relativeHumidity: " << relativeHumidity << std::endl;
127  fout << "saturationPressure: " << saturationPressure << std::endl;
128  fout << "------------------------------" << std::endl << std::endl;
129  fout.close();
130  */
131  }
132 
133  BaseGasDensity(double const dryBulbTemp, double const staticPressure, double const barometricPressure,
134  double const wetBulbTemp, GasType const gasType,
135  InputType const inputType, double const specificGravity, const double cpGas)
136  : tdo(dryBulbTemp), pso(staticPressure), pbo(barometricPressure), wetBulbTemp(wetBulbTemp), g(specificGravity), gasType(gasType)
137  {
138  if (inputType != InputType::WetBulbTemp)
139  throw std::runtime_error("The wrong constructor for BaseGasDensity was called - check inputType field");
140  saturationPressure = calculateSaturationPressure(tdo);
141  relativeHumidity = calculateRelativeHumidityFromWetBulb(tdo, wetBulbTemp, cpGas);
142 
143  calculateFanAttributes(inputType);
144 
145  /*
146  std::ofstream fout;
147  fout.open("debug.txt", std::ios::app);
148  fout << "Wet Bulb" << std::endl;
149  fout << "gasDensity: " << gasDensity << std::endl;
150  fout << "absolutePressure: " << absolutePressure << std::endl;
151  fout << "saturatedHumidity: " << saturatedHumidity << std::endl;
152  fout << "saturationDegree: " << saturationDegree << std::endl;
153  fout << "humidityRatio: " << humidityRatio << std::endl;
154  fout << "specificVolume: " << specificVolume << std::endl;
155  fout << "enthalpy: " << enthalpy << std::endl;
156  fout << "dewPoint: " << dewPoint << std::endl;
157  fout << "relativeHumidity: " << relativeHumidity << std::endl;
158  fout << "saturationPressure: " << saturationPressure << std::endl;
159  fout << "------------------------------" << std::endl << std::endl;
160  fout.close();
161  */
162  }
163 
164  double getGasDensity() const
165  {
166  return gasDensity; // po
167  }
168  double getAbsolutePressureIn() const
169  {
170  return absolutePressure; // pIn
171  }
172  double getSaturatedHumidityRatio() const
173  {
174  return saturatedHumidity; // satW
175  }
176  double getDegreeOfSaturation() const
177  {
178  return saturationDegree; // satDeg
179  }
180  double getHumidityRatio() const
181  {
182  return humidityRatio; // humW
183  }
184  double getSpecificVolume() const
185  {
186  return specificVolume; // specVol
187  }
188  double getEnthalpy() const
189  {
190  return enthalpy;
191  }
192  double getDewPoint() const
193  {
194  return dewPoint;
195  }
196  double getRelativeHumidity() const
197  {
198  return relativeHumidity; // rh
199  }
200  double getSaturationPressure() const
201  {
202  return saturationPressure; // satPress
203  }
204  double getWetBulbTemp() const
205  {
206  return wetBulbTemp; // Tdb
207  }
208 
209 private:
218  double calculateWetBulbTemperature(double dryBulbTemp, double relativeHumidity, double absolutePressure) const
219  {
220  // Newton-Raphson iteration (solve to within 0.001% accuracy)
221 
222  double humidityRatioNormal = calculateRatioRH(dryBulbTemp, relativeHumidity, absolutePressure, 1);
223  double wetBulbTemp = dryBulbTemp; // set initial guess
224  double humidityRatioNew = calculateHumidityRatioFromWetBulb(dryBulbTemp, wetBulbTemp, 0.24);
225 
226  while (fabs((humidityRatioNew - humidityRatioNormal) / humidityRatioNormal) > 0.00001)
227  {
228  double humidityRatioNew2 = calculateHumidityRatioFromWetBulb(dryBulbTemp, wetBulbTemp - 0.001, 0.24);
229  double dw_dtwb = (humidityRatioNew - humidityRatioNew2) / 0.001;
230  wetBulbTemp = wetBulbTemp - (humidityRatioNew - humidityRatioNormal) / dw_dtwb;
231  humidityRatioNew = calculateHumidityRatioFromWetBulb(dryBulbTemp, wetBulbTemp, 0.24);
232  }
233 
234  return wetBulbTemp;
235  }
242  double calculateSaturationPressure(double dryBulbTemp) const
243  {
244  double const C1 = -5674.5359;
245  double const C2 = 6.3925247;
246  double const C3 = -0.009677843;
247  double const C4 = 0.00000062215701;
248  double const C5 = 2.0747825 * std::pow(10, -9);
249  double const C6 = -9.484024 * std::pow(10, -13);
250  double const C7 = 4.1635019;
251  double const C8 = -5800.2206;
252  double const C9 = 1.3914993;
253  double const C10 = -0.048640239;
254  double const C11 = 0.000041764768;
255  double const C12 = -0.000000014452093;
256  double const C13 = 6.5459673;
257 
258  double const tKelvin = (dryBulbTemp + 459.67) * 0.555556;
259 
260  if (tKelvin < 273.15)
261  {
262  double const p = std::exp(C1 / tKelvin + C2 + tKelvin * C3 + tKelvin * tKelvin * (C4 + tKelvin * (C5 + C6 * tKelvin)) + C7 * std::log(tKelvin));
263  return p * (29.9216 / 101325);
264  }
265  double const p = std::exp(C8 / tKelvin + C9 + tKelvin * (C10 + tKelvin * (C11 + tKelvin * C12)) + C13 * std::log(tKelvin));
266 
267  return p * (29.9216 / 101325);
268  }
278  double calculateRatioRH(const double dryBulbTemp, const double relativeHumidity, const double barometricPressure,
279  const double specificGravity) const
280  {
281  auto const pw = (calculateSaturationPressure(dryBulbTemp) * relativeHumidity);
282  return (18.02 / (specificGravity * 28.98)) * pw / (barometricPressure - pw);
283  }
291  double calculateRelativeHumidityFromWetBulb(const double dryBulbTemp, const double wetBulbTemp,
292  const double cpGas) const
293  {
294  double const nMol = 0.62198;
295  double const local_pIn = pbo + (pso / 13.608703);
296  //double const pAtm = 29.9213 / pbo, nMol = 18.02 / (g * 28.98);
297  double const psatDb = calculateSaturationPressure(dryBulbTemp);
298  // double const wSat = nMol * psatDb / (pAtm - psatDb);
299  double const psatWb = calculateSaturationPressure(wetBulbTemp);
300  double const wStar = nMol * psatWb / (local_pIn - psatWb);
301  double const w = ((1093 - (1 - 0.444) * wetBulbTemp) * wStar - cpGas * (dryBulbTemp - wetBulbTemp)) / (1093 + (0.444 * dryBulbTemp) - wetBulbTemp);
302 
303  double const pV = local_pIn * w / (nMol + w);
304 
305  /*
306  std::ofstream fout;
307  fout.open("debug.txt", std::ios::app);
308  fout << "calculateRelativeHumidityFromWetBulb" << std::endl;
309  fout << "psatDb: " << psatDb << std::endl;
310  fout << "psatWb: " << psatWb << std::endl;
311  fout << "wStar: " << wStar << std::endl;
312  fout << "w: " << w << std::endl;
313  fout << "------------------------------" << std::endl << std::endl;
314  fout.close();
315  */
316 
317  return pV / psatDb;
318  }
327  double calculateHumidityRatioFromWetBulb(const double dryBulbTemp, const double wetBulbTemp, const double cpGas) const
328  {
329  double const nMol = 0.62198;
330  double const local_pIn = pbo + (pso / 13.608703);
331 
332  double const psatWb = calculateSaturationPressure(wetBulbTemp);
333  double const wStar = nMol * psatWb / (local_pIn - psatWb);
334  double const w = ((1093 - (1 - 0.444) * wetBulbTemp) * wStar - cpGas * (dryBulbTemp - wetBulbTemp)) / (1093 + (0.444 * dryBulbTemp) - wetBulbTemp);
335 
336  return w;
337  }
345  void calculateFanAttributes(InputType const inputType, double const relativeHumidityOrDewPoint = -1)
346  {
347  double const nMol = 0.62198;
348 
349  absolutePressure = pbo + (pso / 13.608703);
350  saturatedHumidity = nMol * saturationPressure / (absolutePressure - saturationPressure);
351  saturationDegree = relativeHumidity / ( 1 + ( 1 - relativeHumidity) * saturatedHumidity / nMol);
352  humidityRatio = saturationDegree * saturatedHumidity;
353  specificVolume = (10.731557 * (tdo + 459.67) * (1 + 1.6078 * humidityRatio)) / (28.9645 * absolutePressure * 0.4911541);
354  gasDensity = (1 / specificVolume) * (1 + humidityRatio);
355  enthalpy = (0.247 * tdo) + (humidityRatio * (1061 + 0.444 * tdo));
356 
357  if(inputType != InputType::DewPoint)
358  {
359  double const alpha = std::log(absolutePressure * 0.4911541 * humidityRatio / (nMol + humidityRatio));
360 
361  if(tdo < 32)
362  {
363  dewPoint = 90.12 + 26.412 * alpha + 0.8927 * alpha * alpha;
364  }
365  else
366  {
367  dewPoint = 100.45 + 33.193 * alpha + 2.319 * alpha * alpha + 0.17074 * alpha * alpha * alpha + 1.2063 * (std::pow((absolutePressure * 0.4911541 * humidityRatio / (0.62196 + humidityRatio)), 0.1984));
368  }
369 
370  }
371  else
372  {
373  dewPoint = relativeHumidityOrDewPoint;
374  }
375 
376  if(inputType != InputType::WetBulbTemp) // If not given as an input, calculate wet bulb temperature
377  {
378  wetBulbTemp = calculateWetBulbTemperature(tdo, relativeHumidity, absolutePressure);
379  }
380  }
381 
382  // dry bulb temp, reference static pressure, reference barometric pressure, gas density respectively
383  const double tdo, pso, pbo;
384 
385  // gasDensity, specificGravity
390  double gasDensity, g;
391  const GasType gasType;
392 
405  double absolutePressure, saturatedHumidity, saturationDegree, humidityRatio, specificVolume, enthalpy, dewPoint, relativeHumidity, saturationPressure, wetBulbTemp;
406 
407  friend class PlaneData;
408  friend class Fan203;
409 };
410 
416 class PlaneData
417 {
418 public:
419  // used to access private stuff from the nan bindings
427  struct NodeBinding
428  {
429  struct Data
430  {
431  Data(const double density, const double velocity, const double volumeFlowRate, const double velocityPressure,
432  const double totalPressure)
433  : gasDensity(density), gasVelocity(velocity), gasVolumeFlowRate(volumeFlowRate),
434  gasVelocityPressure(velocityPressure), gasTotalPressure(totalPressure) {}
435 
436  const double gasDensity = 0, gasVelocity = 0, gasVolumeFlowRate = 0, gasVelocityPressure = 0, gasTotalPressure = 0;
437  };
446  struct DataFlange : Data
447  {
448  DataFlange(const double density, const double velocity, const double volumeFlowRate, const double velocityPressure,
449  const double totalPressure, const double staticPressure)
450  : Data(density, velocity, volumeFlowRate, velocityPressure, totalPressure),
451  staticPressure(staticPressure) {}
452 
453  const double staticPressure = 0;
454  };
455  struct Output
456  {
457  explicit Output(PlaneData const &planeData)
458  : fanInletFlange(getDataFlange(planeData.fanInletFlange)),
459  fanOrEvaseOutletFlange(getDataFlange(planeData.fanOrEvaseOutletFlange)),
460  flowTraverse(getData(planeData.flowTraverse)),
461  inletMstPlane(getData(planeData.inletMstPlane)),
462  outletMstPlane(getData(planeData.outletMstPlane)),
463  addlTravPlanes(getDataTrav(planeData.addlTravPlanes))
464  {
465  }
466  DataFlange fanInletFlange, fanOrEvaseOutletFlange;
467  Data flowTraverse, inletMstPlane, outletMstPlane;
468  std::vector<Data> addlTravPlanes;
469  };
470  static Output calculate(PlaneData &planeData, BaseGasDensity const &baseGasDensity)
471  {
472  planeData.calculate(baseGasDensity);
473  return Output(planeData);
474  }
475 
476  private:
477  static Data getData(Planar const &plane)
478  {
479  return {plane.gasDensity, plane.gasVelocity, plane.gasVolumeFlowRate, plane.gasVelocityPressure, plane.gasTotalPressure};
480  }
481  static DataFlange getDataFlange(Planar const &plane)
482  {
483  return {plane.gasDensity, plane.gasVelocity, plane.gasVolumeFlowRate, plane.gasVelocityPressure, plane.gasTotalPressure, plane.staticPressure};
484  }
485  static std::vector<Data> getDataTrav(std::vector<TraversePlane> const &addlPlanes)
486  {
487  std::vector<Data> data;
488  for (auto const &plane : addlPlanes)
489  {
490  data.push_back({plane.gasDensity, plane.gasVelocity, plane.gasVolumeFlowRate, plane.gasVelocityPressure, plane.gasTotalPressure});
491  }
492  return data;
493  }
494  };
495 
496  PlaneData(FlangePlane fanInletFlange, FlangePlane fanOrEvaseOutletFlange,
497  TraversePlane flowTraverse, std::vector<TraversePlane> addlTravPlanes,
498  MstPlane inletMstPlane, MstPlane outletMstPlane,
499  const double totalPressureLossBtwnPlanes1and4, const double totalPressureLossBtwnPlanes2and5,
500  bool const plane5upstreamOfPlane2)
501  : fanInletFlange(std::move(fanInletFlange)), fanOrEvaseOutletFlange(std::move(fanOrEvaseOutletFlange)), flowTraverse(std::move(flowTraverse)),
502  addlTravPlanes(std::move(addlTravPlanes)), inletMstPlane(std::move(inletMstPlane)), outletMstPlane(std::move(outletMstPlane)),
503  plane5upstreamOfPlane2(plane5upstreamOfPlane2),
504  totalPressureLossBtwnPlanes1and4(totalPressureLossBtwnPlanes1and4),
505  totalPressureLossBtwnPlanes2and5(totalPressureLossBtwnPlanes2and5)
506  {
507  }
508 
509 private:
510  void establishFanInletOrOutletDensity(Planar &plane,
511  std::function<double(Planar const &, const double)> const &calcDensity,
512  double const mTotal, double const assumedDensity)
513  {
514  double calculatedDensity = assumedDensity;
515  for (auto i = 0; i < 50; i++)
516  {
517  plane.gasDensity = calculatedDensity;
518  plane.gasVolumeFlowRate = mTotal / plane.gasDensity;
519  plane.gasVelocity = plane.gasVolumeFlowRate / plane.area;
520  plane.gasVelocityPressure = plane.gasDensity * std::pow(plane.gasVelocity / 1096, 2);
521  double fanInletOrOutletStaticPressure = plane.gasTotalPressure - plane.gasVelocityPressure;
522  double fanInletOrOutletGasDensity = calcDensity(plane, fanInletOrOutletStaticPressure);
523 
524  calculatedDensity = fanInletOrOutletGasDensity;
525  if (fabs(fanInletOrOutletGasDensity - plane.gasDensity) < 0.0001)
526  {
527  plane.gasDensity = fanInletOrOutletGasDensity;
528  plane.staticPressure = fanInletOrOutletStaticPressure;
529  return;
530  }
531  }
532  throw std::runtime_error("In PlaneData::establishFanInletOrOutletDensity - density iteration did not converge");
533  }
534 
535  void calculate(BaseGasDensity const &bgd)
536  {
537  /*
538  If using custom density or the fields for dry bulb temperature, static pressure and barometric pressure are blank in "Base Gas Density",
539  then the desktop is sending the values entered for Plane 3a (the first traverse plane).
540  */
541  auto const calcDensity = [&bgd](Planar const &plane, const double psx) {
542  return bgd.gasDensity * (bgd.tdo + 460) * (psx + 13.63 * plane.barometricPressure) / ((plane.dryBulbTemperature + 460) * (bgd.pso + 13.63 * bgd.pbo));
543  };
544 
545  flowTraverse.gasDensity = calcDensity(flowTraverse, flowTraverse.staticPressure);
546  for (auto &p : addlTravPlanes)
547  {
548  p.gasDensity = calcDensity(p, p.staticPressure);
549  }
550  inletMstPlane.gasDensity = calcDensity(inletMstPlane, inletMstPlane.staticPressure);
551  outletMstPlane.gasDensity = calcDensity(outletMstPlane, outletMstPlane.staticPressure);
552 
553  flowTraverse.gasVelocity = 1096 * std::sqrt(flowTraverse.pv3 / flowTraverse.gasDensity);
554  flowTraverse.gasVolumeFlowRate = flowTraverse.gasVelocity * flowTraverse.area;
555  //MARK ADDITION FOR issue 259
556  flowTraverse.gasVelocityPressure = flowTraverse.gasDensity * std::pow((flowTraverse.gasVelocity / 1096), 2);
557  flowTraverse.gasTotalPressure = flowTraverse.staticPressure + flowTraverse.gasVelocityPressure;
558 
559  double mTotal = flowTraverse.gasDensity * flowTraverse.gasVolumeFlowRate;
560  for (auto &plane : addlTravPlanes)
561  {
562  plane.gasVelocity = 1096 * std::sqrt(plane.pv3 / plane.gasDensity);
563  plane.gasVolumeFlowRate = plane.gasVelocity * plane.area;
564  //MARK ADDITION FOR issue 259
565  plane.gasVelocityPressure = plane.gasDensity * std::pow((plane.gasVelocity / 1096), 2);
566  plane.gasTotalPressure = plane.staticPressure + plane.gasVelocityPressure;
567  mTotal += plane.gasDensity * plane.gasVolumeFlowRate;
568  }
569 
570  inletMstPlane.gasVolumeFlowRate = mTotal / inletMstPlane.gasDensity;
571  inletMstPlane.gasVelocity = inletMstPlane.gasVolumeFlowRate / inletMstPlane.area;
572  inletMstPlane.gasVelocityPressure = inletMstPlane.gasDensity * std::pow((inletMstPlane.gasVelocity / 1096), 2);
573  inletMstPlane.gasTotalPressure = inletMstPlane.staticPressure + inletMstPlane.gasVelocityPressure;
574 
575  // step 7
576  fanInletFlange.gasTotalPressure = inletMstPlane.gasTotalPressure - totalPressureLossBtwnPlanes1and4;
577 
578  // steps 8 - 13
579  establishFanInletOrOutletDensity(fanInletFlange, calcDensity, mTotal, inletMstPlane.gasDensity);
580 
581  // calculating plane 2 inlet density and pressure
582  outletMstPlane.gasVolumeFlowRate = mTotal / outletMstPlane.gasDensity;
583  outletMstPlane.gasVelocity = outletMstPlane.gasVolumeFlowRate / outletMstPlane.area;
584  outletMstPlane.gasVelocityPressure = outletMstPlane.gasDensity * std::pow(outletMstPlane.gasVelocity / 1096, 2);
585  outletMstPlane.gasTotalPressure = outletMstPlane.staticPressure + outletMstPlane.gasVelocityPressure;
586 
587  // step 7
588  fanOrEvaseOutletFlange.gasTotalPressure = outletMstPlane.gasTotalPressure;
589  fanOrEvaseOutletFlange.gasTotalPressure +=
590  (plane5upstreamOfPlane2) ? -totalPressureLossBtwnPlanes2and5 : totalPressureLossBtwnPlanes2and5;
591 
592  // step 8 - iteration
593  establishFanInletOrOutletDensity(fanOrEvaseOutletFlange, calcDensity, mTotal, outletMstPlane.gasDensity);
594  }
595 
596  FlangePlane fanInletFlange, fanOrEvaseOutletFlange;
597  TraversePlane flowTraverse;
598  std::vector<TraversePlane> addlTravPlanes;
599  MstPlane inletMstPlane;
600  MstPlane outletMstPlane;
601 
602  bool const plane5upstreamOfPlane2;
603  const double totalPressureLossBtwnPlanes1and4, totalPressureLossBtwnPlanes2and5;
604 
605  friend class Fan203;
606  friend struct NodeBinding;
607 };
608 
614 class Fan203
615 {
616 public:
617  Fan203(FanRatedInfo fanRatedInfo, PlaneData planeData, BaseGasDensity baseGasDensity, FanShaftPower fanShaftPower)
618  : fanRatedInfo(fanRatedInfo), planeData(std::move(planeData)),
619  baseGasDensity(baseGasDensity), fanShaftPower(fanShaftPower)
620  {
621  this->planeData.calculate(this->baseGasDensity);
622  };
623 
624  struct Results
625  {
626  Results(const double kpc, const double power, const double flow,
627  const double pressureTotal, const double pressureStatic,
628  const double staticPressureRise)
629  : kpc(kpc), power(power),
630  flow(flow), pressureTotal(pressureTotal),
631  pressureStatic(pressureStatic), staticPressureRise(staticPressureRise)
632  {
633  }
634  const double kpc, power, flow, pressureTotal;
635  const double pressureStatic, staticPressureRise;
636  };
637 
638  struct Output
639  {
640  Output(const double fanEfficiencyTotalPressure, const double fanEfficiencyStaticPressure,
641  const double fanEfficiencyStaticPressureRise, const Results asTested, const Results converted)
642  : fanEfficiencyTotalPressure(fanEfficiencyTotalPressure), fanEfficiencyStaticPressure(fanEfficiencyStaticPressure),
643  fanEfficiencyStaticPressureRise(fanEfficiencyStaticPressureRise), asTested(asTested), converted(converted)
644  {
645  }
646 
647  const double fanEfficiencyTotalPressure, fanEfficiencyStaticPressure, fanEfficiencyStaticPressureRise;
648  const Results asTested, converted;
649  };
650 
651  Output calculate()
652  {
653  // TODO barometricPressure = barometric pressure, what to do if barometric pressure does vary between planes ? pg
654  double const x = (planeData.fanOrEvaseOutletFlange.gasTotalPressure - planeData.fanInletFlange.gasTotalPressure) / (planeData.fanInletFlange.gasTotalPressure + 13.63 * planeData.fanInletFlange.barometricPressure);
655 
656  double isentropicExponent = 1.4; // TODO what value to use for GasTypes other than Air ?
657  if (baseGasDensity.gasType == BaseGasDensity::GasType::AIR)
658  isentropicExponent = 1.4;
659 
660  // TODO barometricPressure = barometric pressure, what to do if barometric pressure does vary between planes ? pg 61
661  double const z = ((isentropicExponent - 1) / isentropicExponent) * ((6362 * fanShaftPower.getFanPowerInput() / planeData.fanInletFlange.gasVolumeFlowRate) / (planeData.fanInletFlange.gasTotalPressure + 13.63 * planeData.fanInletFlange.barometricPressure));
662 
663  double const kp = (std::log(1 + x) / x) * (z / (std::log(1 + z)));
664 
665  planeData.flowTraverse.gasTotalPressure =
666  planeData.flowTraverse.staticPressure + planeData.flowTraverse.gasVelocityPressure;
667  for (auto &p : planeData.addlTravPlanes)
668  {
669  p.gasTotalPressure = p.staticPressure + p.gasVelocityPressure;
670  }
671 
672  double const fanTotalPressure = planeData.fanOrEvaseOutletFlange.gasTotalPressure - planeData.fanInletFlange.gasTotalPressure + fanShaftPower.getSEF();
673 
674  double const fanStaticPressure = planeData.fanOrEvaseOutletFlange.staticPressure - planeData.fanInletFlange.gasTotalPressure + fanShaftPower.getSEF();
675 
676  double const staticPressureRise =
677  planeData.fanOrEvaseOutletFlange.staticPressure - planeData.fanInletFlange.staticPressure +
678  fanShaftPower.getSEF();
679 
680  double const kpFactorRatio = calculateCompressibilityFactor(x, z, isentropicExponent);
681 
682  // corrected variables
683  double const qc = planeData.fanInletFlange.gasVolumeFlowRate * (fanRatedInfo.fanSpeedCorrected / fanRatedInfo.fanSpeed) * kpFactorRatio;
684 
685  double const ptc = fanTotalPressure * kpFactorRatio * std::pow(fanRatedInfo.fanSpeedCorrected / fanRatedInfo.fanSpeed, 2) * (fanRatedInfo.densityCorrected / planeData.fanInletFlange.gasDensity);
686 
687  double const psc = fanStaticPressure * kpFactorRatio * std::pow(fanRatedInfo.fanSpeedCorrected / fanRatedInfo.fanSpeed, 2) * (fanRatedInfo.densityCorrected / planeData.fanInletFlange.gasDensity);
688 
689  double const sprc =
690  staticPressureRise * kpFactorRatio * std::pow(fanRatedInfo.fanSpeedCorrected / fanRatedInfo.fanSpeed, 2) * (fanRatedInfo.densityCorrected / planeData.fanInletFlange.gasDensity);
691 
692  double const hc = fanShaftPower.getFanPowerInput() * kpFactorRatio * std::pow(fanRatedInfo.fanSpeedCorrected / fanRatedInfo.fanSpeed, 3) * (fanRatedInfo.densityCorrected / planeData.fanInletFlange.gasDensity);
693 
694  double const kpc = kp / kpFactorRatio;
695 
696  double const efficiency = planeData.fanInletFlange.gasVolumeFlowRate * kp / (6362 * fanShaftPower.getFanPowerInput());
697 
698  return {
699  fanTotalPressure * efficiency * 100, fanStaticPressure * efficiency * 100, staticPressureRise * efficiency * 100, {kpFactorRatio, fanShaftPower.getFanPowerInput(), planeData.fanInletFlange.gasVolumeFlowRate, fanTotalPressure, fanStaticPressure, staticPressureRise}, {kpc, hc, qc, ptc, psc, sprc}};
700  }
701 
702 private:
703  double calculateCompressibilityFactor(const double x, const double z, const double isentropic)
704  {
705  double assumedKpOverKpc = 1.0;
706  auto const &p1 = planeData.fanInletFlange;
707  for (auto i = 0; i < 50; i++)
708  {
709  double const pt1c = p1.gasTotalPressure * std::pow(fanRatedInfo.fanSpeedCorrected / fanRatedInfo.fanSpeed, 2) * (fanRatedInfo.densityCorrected / p1.gasDensity) * assumedKpOverKpc;
710 
711  // TODO how to get isentropic exponent for gas at converted conditions? section 9.4.1 step 2
712  double const zOverZc = ((pt1c + 13.63 * fanRatedInfo.pressureBarometricCorrected) / (p1.gasTotalPressure + 13.63 * p1.barometricPressure)) * (p1.gasDensity / fanRatedInfo.densityCorrected) * std::pow(fanRatedInfo.fanSpeed / fanRatedInfo.fanSpeedCorrected, 2) * ((isentropic - 1) / isentropic) * (isentropic / (isentropic - 1));
713 
714  double const zc = z / zOverZc;
715 
716  double const ln1xc = std::log(1 + x) * ((std::log(1 + zc) / std::log(1 + z))) * ((isentropic - 1) / isentropic) * (isentropic / (isentropic - 1));
717 
718  double const xc = std::exp(ln1xc) - 1;
719 
720  double const kpOverKpc = (z / zc) * (xc / x) * (isentropic / (isentropic - 1)) * ((isentropic - 1) / isentropic);
721  if (fabs(kpOverKpc - assumedKpOverKpc) < 0.0000001)
722  {
723  return kpOverKpc;
724  }
725  assumedKpOverKpc = kpOverKpc;
726  }
727  throw std::runtime_error("compressibility factor ratio iteration did not converge");
728  }
729 
730  FanRatedInfo const fanRatedInfo;
731  PlaneData planeData;
732  BaseGasDensity const baseGasDensity;
733  FanShaftPower const fanShaftPower;
734 };
735 
736 #endif //AMO_TOOLS_SUITE_FAN_H
BaseGasDensity(double const dryBulbTemp, double const staticPressure, double const barometricPressure, double const relativeHumidityOrDewPoint, GasType const gasType, InputType const inputType, double const specificGravity)
Definition: Fan203.h:93
Definition: Planar.h:65
double getSEF() const
Definition: FanShaftPower.h:73
Definition: Fan203.h:614
const double dryBulbTemperature
Definition: Planar.h:78
BaseGasDensity(const double dryBulbTemp, const double staticPressure, const double barometricPressure, const double gasDensity, const GasType gasType)
Definition: Fan203.h:68
double getFanPowerInput() const
Definition: FanShaftPower.h:67