62 enum class GasType { AIR, STANDARDAIR, OTHERGAS };
67 enum class InputType { DewPoint, RelativeHumidity, WetBulbTemp };
77 BaseGasDensity(
const double dryBulbTemp,
const double staticPressure,
const double barometricPressure,
79 : tdo(dryBulbTemp), pso(staticPressure), pbo(barometricPressure),
gasDensity(
gasDensity), gasType(gasType) {}
100 BaseGasDensity(
double const dryBulbTemp,
double const staticPressure,
double const barometricPressure,
101 double const relativeHumidityOrDewPoint,
GasType const gasType,
InputType const inputType,
102 double const specificGravity)
103 : tdo(dryBulbTemp), pso(staticPressure), pbo(barometricPressure), g(specificGravity), gasType(gasType) {
105 relativeHumidity = 0;
106 if (inputType == InputType::RelativeHumidity) {
107 relativeHumidity = relativeHumidityOrDewPoint / 100;
109 else if (inputType == InputType::DewPoint) {
112 else if (inputType == InputType::WetBulbTemp) {
113 throw std::runtime_error(
114 "The wrong constructor for BaseGasDensity was called here - check inputType field");
137 BaseGasDensity(
double const dryBulbTemp,
double const staticPressure,
double const barometricPressure,
139 double const specificGravity,
const double cpGas)
140 : tdo(dryBulbTemp), pso(staticPressure), pbo(barometricPressure), wetBulbTemp(wetBulbTemp), g(specificGravity),
142 if (inputType != InputType::WetBulbTemp)
143 throw std::runtime_error(
"The wrong constructor for BaseGasDensity was called - check inputType field");
168 double getGasDensity()
const {
171 double getAbsolutePressureIn()
const {
174 double getSaturatedHumidityRatio()
const {
175 return saturatedHumidity;
177 double getDegreeOfSaturation()
const {
178 return saturationDegree;
180 double getHumidityRatio()
const {
181 return humidityRatio;
183 double getSpecificVolume()
const {
184 return specificVolume;
186 double getEnthalpy()
const {
return enthalpy; }
187 double getDewPoint()
const {
return dewPoint; }
188 double getRelativeHumidity()
const {
189 return relativeHumidity;
191 double getSaturationPressure()
const {
192 return saturationPressure;
194 double getWetBulbTemp()
const {
211 double wetBulbTemp = dryBulbTemp;
213 if (humidityRatioNormal > 0) {
214 while (fabs((humidityRatioNew - humidityRatioNormal) / humidityRatioNormal) > 0.00001) {
216 double dw_dtwb = (humidityRatioNew - humidityRatioNew2) / 0.001;
217 wetBulbTemp = wetBulbTemp - (humidityRatioNew - humidityRatioNormal) / dw_dtwb;
222 while (fabs(humidityRatioNew) > 0.00001) {
224 double dw_dtwb = (humidityRatioNew - humidityRatioNew2) / 0.001;
225 wetBulbTemp = wetBulbTemp - (humidityRatioNew - humidityRatioNormal) / dw_dtwb;
238 double const C1 = -5674.5359;
239 double const C2 = 6.3925247;
240 double const C3 = -0.009677843;
241 double const C4 = 0.00000062215701;
242 double const C5 = 2.0747825 * std::pow(10, -9);
243 double const C6 = -9.484024 * std::pow(10, -13);
244 double const C7 = 4.1635019;
245 double const C8 = -5800.2206;
246 double const C9 = 1.3914993;
247 double const C10 = -0.048640239;
248 double const C11 = 0.000041764768;
249 double const C12 = -0.000000014452093;
250 double const C13 = 6.5459673;
252 double const tKelvin = (dryBulbTemp + 459.67) * 0.555556;
254 if (tKelvin < 273.15) {
256 std::exp(C1 / tKelvin + C2 + tKelvin * C3 + tKelvin * tKelvin * (C4 + tKelvin * (C5 + C6 * tKelvin)) +
257 C7 * std::log(tKelvin));
258 return p * (29.9216 / 101325);
261 std::exp(C8 / tKelvin + C9 + tKelvin * (C10 + tKelvin * (C11 + tKelvin * C12)) + C13 * std::log(tKelvin));
263 return p * (29.9216 / 101325);
274 double calculateRatioRH(
const double dryBulbTemp,
const double relativeHumidity,
const double barometricPressure,
275 const double specificGravity)
const {
277 return (18.02 / (specificGravity * 28.98)) * pw / (barometricPressure - pw);
287 const double cpGas)
const {
288 double const nMol = 0.62198;
289 double const local_pIn = pbo + (pso / 13.608703);
294 double const wStar = nMol * pumpWb / (local_pIn - pumpWb);
295 double const w = ((1093 - (1 - 0.444) * wetBulbTemp) * wStar - cpGas * (dryBulbTemp - wetBulbTemp)) /
296 (1093 + (0.444 * dryBulbTemp) - wetBulbTemp);
298 double const pV = local_pIn * w / (nMol + w);
311 const double cpGas)
const {
312 double const nMol = 0.62198;
313 double const local_pIn = pbo + (pso / 13.608703);
316 double const wStar = nMol * pumpWb / (local_pIn - pumpWb);
317 double const w = ((1093 - (1 - 0.444) * wetBulbTemp) * wStar - cpGas * (dryBulbTemp - wetBulbTemp)) /
318 (1093 + (0.444 * dryBulbTemp) - wetBulbTemp);
330 double const nMol = 0.62198;
333 saturatedHumidity = nMol * saturationPressure / (
absolutePressure - saturationPressure);
334 saturationDegree = relativeHumidity / (1 + (1 - relativeHumidity) * saturatedHumidity / nMol);
335 humidityRatio = saturationDegree * saturatedHumidity;
337 (10.731557 * (tdo + 459.67) * (1 + 1.6078 * humidityRatio)) / (28.9645 *
absolutePressure * 0.4911541);
338 gasDensity = (1 / specificVolume) * (1 + humidityRatio);
339 enthalpy = (0.247 * tdo) + (humidityRatio * (1061 + 0.444 * tdo));
341 if (inputType != InputType::DewPoint) {
342 double const alpha = std::log(
absolutePressure * 0.4911541 * humidityRatio / (nMol + humidityRatio));
345 dewPoint = 90.12 + 26.412 * alpha + 0.8927 * alpha * alpha;
349 100.45 + 33.193 * alpha + 2.319 * alpha * alpha + 0.17074 * alpha * alpha * alpha +
351 (std::pow((
absolutePressure * 0.4911541 * humidityRatio / (0.62196 + humidityRatio)), 0.1984));
355 dewPoint = relativeHumidityOrDewPoint;
359 InputType::WetBulbTemp)
366 const double tdo, pso, pbo;
367 double wetBulbTemp = 0;
389 double absolutePressure = 0, saturatedHumidity = 0, saturationDegree = 0, humidityRatio = 0, specificVolume = 0,
390 enthalpy = 0, dewPoint = 0, relativeHumidity = 0, saturationPressure = 0;
413 Data(
const double density,
const double velocity,
const double volumeFlowRate,
414 const double velocityPressure,
const double totalPressure)
415 : gasDensity(density), gasVelocity(velocity), gasVolumeFlowRate(volumeFlowRate),
416 gasVelocityPressure(velocityPressure), gasTotalPressure(totalPressure) {}
418 double gasDensity = 0, gasVelocity = 0, gasVolumeFlowRate = 0, gasVelocityPressure = 0,
419 gasTotalPressure = 0;
430 DataFlange(
const double density,
const double velocity,
const double volumeFlowRate,
431 const double velocityPressure,
const double totalPressure,
const double staticPressure)
432 :
Data(density, velocity, volumeFlowRate, velocityPressure, totalPressure),
433 staticPressure(staticPressure) {}
435 double staticPressure = 0;
439 : fanInletFlange(getDataFlange(planeData.fanInletFlange)),
440 fanOrEvaseOutletFlange(getDataFlange(planeData.fanOrEvaseOutletFlange)),
441 flowTraverse(getData(planeData.flowTraverse)), inletMstPlane(getData(planeData.inletMstPlane)),
442 outletMstPlane(getData(planeData.outletMstPlane)),
443 addlTravPlanes(getDataTrav(planeData.addlTravPlanes)) {}
444 DataFlange fanInletFlange, fanOrEvaseOutletFlange;
445 Data flowTraverse, inletMstPlane, outletMstPlane;
446 std::vector<Data> addlTravPlanes;
449 planeData.calculate(baseGasDensity);
454 static Data getData(
Planar const& plane) {
455 return {plane.gasDensity, plane.gasVelocity, plane.gasVolumeFlowRate, plane.gasVelocityPressure,
456 plane.gasTotalPressure};
458 static DataFlange getDataFlange(
Planar const& plane) {
459 return {plane.gasDensity, plane.gasVelocity, plane.gasVolumeFlowRate,
460 plane.gasVelocityPressure, plane.gasTotalPressure, plane.staticPressure};
462 static std::vector<Data> getDataTrav(std::vector<TraversePlane>
const& addlPlanes) {
463 std::vector<Data> data;
464 for (
auto const& plane : addlPlanes) {
465 data.push_back({plane.gasDensity, plane.gasVelocity, plane.gasVolumeFlowRate, plane.gasVelocityPressure,
466 plane.gasTotalPressure});
473 std::vector<TraversePlane> addlTravPlanes,
MstPlane inletMstPlane,
MstPlane outletMstPlane,
474 const double totalPressureLossBtwnPlanes1and4,
const double totalPressureLossBtwnPlanes2and5,
475 bool const plane5upstreamOfPlane2)
476 : fanInletFlange(std::move(fanInletFlange)), fanOrEvaseOutletFlange(std::move(fanOrEvaseOutletFlange)),
477 flowTraverse(std::move(flowTraverse)), addlTravPlanes(std::move(addlTravPlanes)),
478 inletMstPlane(std::move(inletMstPlane)), outletMstPlane(std::move(outletMstPlane)),
479 plane5upstreamOfPlane2(plane5upstreamOfPlane2),
480 totalPressureLossBtwnPlanes1and4(totalPressureLossBtwnPlanes1and4),
481 totalPressureLossBtwnPlanes2and5(totalPressureLossBtwnPlanes2and5) {}
484 void establishFanInletOrOutletDensity(
Planar& plane,
485 std::function<
double(
Planar const&,
const double)>
const& calcDensity,
486 double const mTotal,
double const assumedDensity) {
487 double calculatedDensity = assumedDensity;
488 for (
auto i = 0; i < 50; i++) {
489 plane.gasDensity = calculatedDensity;
490 plane.gasVolumeFlowRate = mTotal / plane.gasDensity;
491 plane.gasVelocity = plane.gasVolumeFlowRate / plane.area;
492 plane.gasVelocityPressure = plane.gasDensity * std::pow(plane.gasVelocity / 1096, 2);
493 double fanInletOrOutletStaticPressure = plane.gasTotalPressure - plane.gasVelocityPressure;
494 double fanInletOrOutletGasDensity = calcDensity(plane, fanInletOrOutletStaticPressure);
496 calculatedDensity = fanInletOrOutletGasDensity;
497 if (fabs(fanInletOrOutletGasDensity - plane.gasDensity) < 0.0001) {
498 plane.gasDensity = fanInletOrOutletGasDensity;
499 plane.staticPressure = fanInletOrOutletStaticPressure;
503 throw std::runtime_error(
"In PlaneData::establishFanInletOrOutletDensity - density iteration did not converge");
512 auto const calcDensity = [&bgd](
Planar const& plane,
const double psx) {
513 return bgd.
gasDensity * (bgd.tdo + 460) * (psx + 13.63 * plane.barometricPressure) /
517 flowTraverse.gasDensity = calcDensity(flowTraverse, flowTraverse.staticPressure);
518 for (
auto& p : addlTravPlanes) {
519 p.gasDensity = calcDensity(p, p.staticPressure);
521 inletMstPlane.gasDensity = calcDensity(inletMstPlane, inletMstPlane.staticPressure);
522 outletMstPlane.gasDensity = calcDensity(outletMstPlane, outletMstPlane.staticPressure);
524 flowTraverse.gasVelocity = 1096 * std::sqrt(flowTraverse.pv3 / flowTraverse.gasDensity);
525 flowTraverse.gasVolumeFlowRate = flowTraverse.gasVelocity * flowTraverse.area;
527 flowTraverse.gasVelocityPressure = flowTraverse.gasDensity * std::pow((flowTraverse.gasVelocity / 1096), 2);
528 flowTraverse.gasTotalPressure = flowTraverse.staticPressure + flowTraverse.gasVelocityPressure;
530 double mTotal = flowTraverse.gasDensity * flowTraverse.gasVolumeFlowRate;
531 for (
auto& plane : addlTravPlanes) {
532 plane.gasVelocity = 1096 * std::sqrt(plane.pv3 / plane.gasDensity);
533 plane.gasVolumeFlowRate = plane.gasVelocity * plane.area;
535 plane.gasVelocityPressure = plane.gasDensity * std::pow((plane.gasVelocity / 1096), 2);
536 plane.gasTotalPressure = plane.staticPressure + plane.gasVelocityPressure;
537 mTotal += plane.gasDensity * plane.gasVolumeFlowRate;
540 inletMstPlane.gasVolumeFlowRate = mTotal / inletMstPlane.gasDensity;
541 inletMstPlane.gasVelocity = inletMstPlane.gasVolumeFlowRate / inletMstPlane.area;
542 inletMstPlane.gasVelocityPressure = inletMstPlane.gasDensity * std::pow((inletMstPlane.gasVelocity / 1096), 2);
543 inletMstPlane.gasTotalPressure = inletMstPlane.staticPressure + inletMstPlane.gasVelocityPressure;
546 fanInletFlange.gasTotalPressure = inletMstPlane.gasTotalPressure - totalPressureLossBtwnPlanes1and4;
549 establishFanInletOrOutletDensity(fanInletFlange, calcDensity, mTotal, inletMstPlane.gasDensity);
552 outletMstPlane.gasVolumeFlowRate = mTotal / outletMstPlane.gasDensity;
553 outletMstPlane.gasVelocity = outletMstPlane.gasVolumeFlowRate / outletMstPlane.area;
554 outletMstPlane.gasVelocityPressure = outletMstPlane.gasDensity * std::pow(outletMstPlane.gasVelocity / 1096, 2);
555 outletMstPlane.gasTotalPressure = outletMstPlane.staticPressure + outletMstPlane.gasVelocityPressure;
558 fanOrEvaseOutletFlange.gasTotalPressure = outletMstPlane.gasTotalPressure;
559 fanOrEvaseOutletFlange.gasTotalPressure +=
560 (plane5upstreamOfPlane2) ? -totalPressureLossBtwnPlanes2and5 : totalPressureLossBtwnPlanes2and5;
563 establishFanInletOrOutletDensity(fanOrEvaseOutletFlange, calcDensity, mTotal, outletMstPlane.gasDensity);
566 FlangePlane fanInletFlange, fanOrEvaseOutletFlange;
568 std::vector<TraversePlane> addlTravPlanes;
572 bool const plane5upstreamOfPlane2;
573 const double totalPressureLossBtwnPlanes1and4, totalPressureLossBtwnPlanes2and5;
576 friend struct NodeBinding;
587 : fanRatedInfo(fanRatedInfo), planeData(std::move(planeData)), baseGasDensity(baseGasDensity),
588 fanShaftPower(fanShaftPower) {
589 this->planeData.calculate(this->baseGasDensity);
593 Results(
const double kpc,
const double power,
const double flow,
const double pressureTotal,
594 const double pressureStatic,
const double staticPressureRise)
595 : kpc(kpc), power(power), flow(flow), pressureTotal(pressureTotal), pressureStatic(pressureStatic),
596 staticPressureRise(staticPressureRise) {}
597 const double kpc, power, flow, pressureTotal;
598 const double pressureStatic, staticPressureRise;
602 Output(
const double fanEfficiencyTotalPressure,
const double fanEfficiencyStaticPressure,
603 const double fanEfficiencyStaticPressureRise,
const Results asTested,
const Results converted)
604 : fanEfficiencyTotalPressure(fanEfficiencyTotalPressure),
605 fanEfficiencyStaticPressure(fanEfficiencyStaticPressure),
606 fanEfficiencyStaticPressureRise(fanEfficiencyStaticPressureRise), asTested(asTested),
607 converted(converted) {}
609 const double fanEfficiencyTotalPressure, fanEfficiencyStaticPressure, fanEfficiencyStaticPressureRise;
610 const Results asTested, converted;
617 (planeData.fanOrEvaseOutletFlange.gasTotalPressure - planeData.fanInletFlange.gasTotalPressure) /
618 (planeData.fanInletFlange.gasTotalPressure + 13.63 * planeData.fanInletFlange.barometricPressure);
620 double isentropicExponent = 1.4;
621 if (baseGasDensity.gasType == BaseGasDensity::GasType::AIR)
622 isentropicExponent = 1.4;
627 ((isentropicExponent - 1) / isentropicExponent) *
628 ((6362 * fanShaftPower.
getFanPowerInput() / planeData.fanInletFlange.gasVolumeFlowRate) /
629 (planeData.fanInletFlange.gasTotalPressure + 13.63 * planeData.fanInletFlange.barometricPressure));
631 double const kp = (std::log(1 + x) / x) * (z / (std::log(1 + z)));
633 planeData.flowTraverse.gasTotalPressure =
634 planeData.flowTraverse.staticPressure + planeData.flowTraverse.gasVelocityPressure;
635 for (
auto& p : planeData.addlTravPlanes) {
636 p.gasTotalPressure = p.staticPressure + p.gasVelocityPressure;
639 double const fanTotalPressure = planeData.fanOrEvaseOutletFlange.gasTotalPressure -
640 planeData.fanInletFlange.gasTotalPressure + fanShaftPower.
getSEF();
642 double const fanStaticPressure = planeData.fanOrEvaseOutletFlange.staticPressure -
643 planeData.fanInletFlange.gasTotalPressure + fanShaftPower.
getSEF();
645 double const staticPressureRise = planeData.fanOrEvaseOutletFlange.staticPressure -
646 planeData.fanInletFlange.staticPressure + fanShaftPower.
getSEF();
648 double const kpFactorRatio = calculateCompressibilityFactor(x, z, isentropicExponent);
670 double const qc = planeData.fanInletFlange.gasVolumeFlowRate *
673 double const ptc = fanTotalPressure * kpFactorRatio *
677 double const psc = fanStaticPressure * kpFactorRatio *
681 double const sprc = staticPressureRise * kpFactorRatio *
689 double const kpc = kp / kpFactorRatio;
691 double const efficiency =
692 planeData.fanInletFlange.gasVolumeFlowRate * kp / (6362 * fanShaftPower.
getFanPowerInput());
694 return {fanTotalPressure * efficiency * 100,
695 fanStaticPressure * efficiency * 100,
696 staticPressureRise * efficiency * 100,
697 {kpFactorRatio, fanShaftPower.
getFanPowerInput(), planeData.fanInletFlange.gasVolumeFlowRate,
698 fanTotalPressure, fanStaticPressure, staticPressureRise},
699 {kpc, hc, qc, ptc, psc, sprc}};
703 double calculateCompressibilityFactor(
const double x,
const double z,
const double isentropic) {
704 double assumedKpOverKpc = 1.0;
705 auto const& p1 = planeData.fanInletFlange;
706 for (
auto i = 0; i < 50; i++) {
707 double const pt1c = p1.gasTotalPressure *
713 (p1.gasTotalPressure + 13.63 * p1.barometricPressure)) *
716 ((isentropic - 1) / isentropic) * (isentropic / (isentropic - 1));
718 double const zc = z / zOverZc;
720 double const ln1xc = std::log(1 + x) * ((std::log(1 + zc) / std::log(1 + z))) *
721 ((isentropic - 1) / isentropic) * (isentropic / (isentropic - 1));
723 double const xc = std::exp(ln1xc) - 1;
725 double const kpOverKpc =
726 (z / zc) * (xc / x) * (isentropic / (isentropic - 1)) * ((isentropic - 1) / isentropic);
727 if (fabs(kpOverKpc - assumedKpOverKpc) < 0.0000001) {
730 assumedKpOverKpc = kpOverKpc;
732 throw std::runtime_error(
"compressibility factor ratio iteration did not converge");