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
CompressedAir.cpp
1 #include "calculator/util/CompressedAir.h"
2 #ifndef M_PI
3 #define M_PI 3.14159265358979323846
4 #endif
5 
6 PneumaticAirRequirement::PneumaticAirRequirement(const PistonType pistonType, const double cylinderDiameter,
7  const double cylinderStroke, const double pistonRodDiameter,
8  const double airPressure, const double cyclesPerMin)
9  : pistonType(pistonType), cylinderDiameter(cylinderDiameter), cylinderStroke(cylinderStroke),
10  pistonRodDiameter(pistonRodDiameter), airPressure(airPressure), cyclesPerMin(cyclesPerMin)
11 {
12  if (pistonType != PistonType::DoubleActing) {
13  throw std::runtime_error("You must have a DoubleActing piston type to use piston rod diameter");
14  }
15 }
16 
17 PneumaticAirRequirement::PneumaticAirRequirement(const PistonType pistonType, const double cylinderDiameter,
18  const double cylinderStroke, const double airPressure,
19  const double cyclesPerMin)
20  : pistonType(pistonType), cylinderDiameter(cylinderDiameter), cylinderStroke(cylinderStroke),
21  airPressure(airPressure), cyclesPerMin(cyclesPerMin)
22 {
23  if (pistonType != PistonType::SingleActing) {
24  throw std::runtime_error("You must have a SingleActing piston type if you do not use piston rod diameter");
25  }
26 }
27 
29  auto const volumeAirIntakeSingle = (0.785 * std::pow(cylinderDiameter, 2) * cylinderStroke * cyclesPerMin) / 1728;
30  auto const compressionRatio = (airPressure + 14.7) / 14.7;
31 
32  if (pistonType == PneumaticAirRequirement::PistonType::SingleActing) {
33  return {volumeAirIntakeSingle, compressionRatio, volumeAirIntakeSingle * compressionRatio};
34  }
35  auto const volumeAirIntakeDouble = (2 * 1728 * volumeAirIntakeSingle - (0.785 * std::pow(pistonRodDiameter, 2)
36  * cylinderStroke * cyclesPerMin)) / 1728;
37  return {volumeAirIntakeDouble, compressionRatio, volumeAirIntakeDouble * compressionRatio};
38 }
39 
40 ReceiverTank::ReceiverTank(const Method method, const double airDemand, const double allowablePressureDrop,
41  const double atmosphericPressure)
42  : method(method), airDemand(airDemand), allowablePressureDrop(allowablePressureDrop),
43  atmosphericPressure(atmosphericPressure)
44 {
45  if (method != ReceiverTank::Method::General) {
46  throw std::runtime_error("Calculation method must be set to General to use this constructor");
47  }
48 }
49 
50 ReceiverTank::ReceiverTank(Method method, double lengthOfDemandOrDistanceToCompressorRoom, double airFlowRequirementOrSpeedOfAir, double atmosphericPressure,
51  double initialTankPressureOrAirDemand, double finalTankPressureOrAllowablePressureDrop)
52  : method(method), atmosphericPressure(atmosphericPressure),
53  lengthOfDemandOrDistanceToCompressorRoom(lengthOfDemandOrDistanceToCompressorRoom),
54  airFlowRequirementOrSpeedOfAir(airFlowRequirementOrSpeedOfAir),
55  initialTankPressureOrAirDemand(initialTankPressureOrAirDemand),
56  finalTankPressureOrAllowablePressureDrop(finalTankPressureOrAllowablePressureDrop)
57 {
58  if (method != ReceiverTank::Method::DedicatedStorage && method != ReceiverTank::Method::BridgingCompressorReactionDelay) {
59  throw std::runtime_error("Calculation method must be set to DedicatedStorage or BridgingCompressorReactionDelay to use this constructor");
60  }
61 }
62 
63 ReceiverTank::ReceiverTank(Method method, double lengthOfDemand, double airFlowRequirement, double atmosphericPressure,
64  double initialTankPressure, double finalTankPressure, double meteredFlowControl)
65  : method(method), atmosphericPressure(atmosphericPressure), lengthOfDemandOrDistanceToCompressorRoom(lengthOfDemand),
66  airFlowRequirementOrSpeedOfAir(airFlowRequirement), initialTankPressureOrAirDemand(initialTankPressure),
67  finalTankPressureOrAllowablePressureDrop(finalTankPressure), meteredFlowControl(meteredFlowControl)
68 {
69  if (method != ReceiverTank::Method::MeteredStorage) {
70  throw std::runtime_error("Calculation method must be set to MeteredStorage to use this constructor");
71  }
72 }
73 
75  if (method == ReceiverTank::Method::General) {
76  return airDemand * (atmosphericPressure / allowablePressureDrop) * 7.48;
77  } else if (method == ReceiverTank::Method::DedicatedStorage) {
78  return 7.48 * (lengthOfDemandOrDistanceToCompressorRoom * airFlowRequirementOrSpeedOfAir * atmosphericPressure)
79  / (initialTankPressureOrAirDemand - finalTankPressureOrAllowablePressureDrop);
80  } else if (method == ReceiverTank::Method::MeteredStorage) {
81  return (7.48 * lengthOfDemandOrDistanceToCompressorRoom * (airFlowRequirementOrSpeedOfAir - meteredFlowControl) * atmosphericPressure)
82  / (initialTankPressureOrAirDemand - finalTankPressureOrAllowablePressureDrop);
83  }
84  // method must be BridgingCompressorReactionDelay
85  return (lengthOfDemandOrDistanceToCompressorRoom / airFlowRequirementOrSpeedOfAir) * (initialTankPressureOrAirDemand / 60)
86  * (atmosphericPressure / finalTankPressureOrAllowablePressureDrop) * 7.48;
87 }
88 
89 Compressor::OperatingCost::OperatingCost(double motorBhp, double bhpUnloaded, double annualOperatingHours,
90  double runTimeLoaded, double efficiencyLoaded, double efficiencyUnloaded,
91  double costOfElectricity)
92  : motorBhp(motorBhp), bhpUnloaded(bhpUnloaded), annualOperatingHours(annualOperatingHours),
93  runTimeLoaded(runTimeLoaded), efficiencyLoaded(efficiencyLoaded), efficiencyUnloaded(efficiencyUnloaded),
94  costOfElectricity(costOfElectricity)
95 {}
96 
97 Compressor::OperatingCost::Output Compressor::OperatingCost::calculate() {
98  auto const runTimeUnloaded = 100 - runTimeLoaded;
99  auto const costForLoaded = (motorBhp * 0.746 * annualOperatingHours * costOfElectricity * (runTimeLoaded / 100))
100  / (efficiencyLoaded / 100);
101  auto const costForUnloaded = (motorBhp * 0.746 * annualOperatingHours * costOfElectricity * (bhpUnloaded / 100) * (runTimeUnloaded / 100))
102  / (efficiencyUnloaded / 100);
103  return {runTimeUnloaded, costForLoaded, costForUnloaded, costForLoaded + costForUnloaded};
104 }
105 
107  std::vector<double> receivers)
108  : pipeLengths(pipeLengths), receivers(std::move(receivers))
109 {}
110 
111 Compressor::AirSystemCapacity::Output Compressor::AirSystemCapacity::calculate() {
112 
113  auto totalReceiverVol = 0.0;
114  for (auto & gallons : receivers) {
115  gallons /= 7.48;
116  totalReceiverVol += gallons;
117  }
118 
119  return {pipeLengths.totalPipeVolume, receivers, totalReceiverVol,
120  pipeLengths.totalPipeVolume + totalReceiverVol, pipeLengths};
121 }
122 
123 Compressor::AirVelocity::AirVelocity(const double airFlow, const double pipePressure, const double atmosphericPressure)
124  : airFlow(airFlow), pipePressure(pipePressure), atmosphericPressure(atmosphericPressure)
125 {}
126 
127 Compressor::PipeData Compressor::AirVelocity::calculate() {
128  auto const compressedAirVelocity = [this](const double traverseArea) {
129  return (airFlow * atmosphericPressure / (pipePressure + atmosphericPressure)) * (144 / traverseArea) * (1.0 / 60);
130  };
131 
132  return Compressor::PipeData(compressedAirVelocity);
133 }
134 
135 Compressor::PipeSizing::PipeSizing(double airflow, double airlinePressure, double designVelocity,
136  double atmosphericPressure)
137  : airflow(airflow), airlinePressure(airlinePressure), designVelocity(designVelocity),
138  atmosphericPressure(atmosphericPressure)
139 {}
140 
142  auto const crossSectionalArea = (144 * airflow * atmosphericPressure) / (designVelocity * 60 * (airlinePressure + atmosphericPressure));
143  return {crossSectionalArea, std::sqrt(crossSectionalArea / 0.78)};
144 }
145 
146 Compressor::PneumaticValve::PneumaticValve(const double inletPressure, const double outletPressure)
147  : inletPressure(inletPressure), outletPressure(outletPressure),
148  flowRate(0.6875 * std::sqrt(inletPressure - outletPressure) * std::sqrt(inletPressure + outletPressure)),
149  flowRateKnown(false)
150 {}
151 
152 Compressor::PneumaticValve::PneumaticValve(const double inletPressure, const double outletPressure, const double flowRate)
153  : inletPressure(inletPressure), outletPressure(outletPressure), flowRate(flowRate), flowRateKnown(true)
154 {}
155 
157  if (!flowRateKnown) {
158  return flowRate;
159  }
160  return flowRate / (0.6875 * std::sqrt(inletPressure - outletPressure) * std::sqrt(inletPressure + outletPressure));
161 }
162 
163 BagMethod::BagMethod(const double operatingTime, const double bagFillTime, const double heightOfBag,
164  const double diameterOfBag, const int numberOfUnits)
165  : operatingTime(operatingTime), bagFillTime(bagFillTime),
166  heightOfBag(heightOfBag), diameterOfBag(diameterOfBag), numberOfUnits(numberOfUnits)
167 {}
168 
170  auto const flowRate = (0.0273 * std::pow(diameterOfBag, 2) * heightOfBag) / bagFillTime;
171  return {flowRate, (flowRate * operatingTime * numberOfUnits * 60) / 1000 };
172 }
173 
174 EstimateMethod::EstimateMethod(const double operatingTime, const double leakRateEstimate)
175  : operatingTime(operatingTime), leakRateEstimate(leakRateEstimate)
176 {}
177 
179  //return {flowRate, (flowRate * operatingTime * numberOfUnits * 60) / 1000 };
180  //return {(leakRateEstimate * operatingTime * 60) / 1000};
181  EstimateMethod::Output output((leakRateEstimate * operatingTime * 60) / 1000);
182  return output;
183 }
184 
185 DecibelsMethod::DecibelsMethod(const double operatingTime, const double linePressure, const double decibels, const double decibelRatingA,
186  const double pressureA, const double firstFlowA, const double secondFlowA, const double decibelRatingB, const double pressureB,
187  const double firstFlowB, const double secondFlowB)
188  : operatingTime(operatingTime), linePressure(linePressure), decibels(decibels), decibelRatingA(decibelRatingA),
189  pressureA(pressureA), firstFlowA(firstFlowA), secondFlowA(secondFlowA), decibelRatingB(decibelRatingB),
190  pressureB(pressureB), firstFlowB(firstFlowB), secondFlowB(secondFlowB)
191 {}
192 
194  /*
195  double operatingTime;
196  double linePressure; // X
197  double decibels; // Y
198  double decibelRatingA; // Y1
199  double pressureA; // X1
200  double firstFlowA; // Q11
201  double secondFlowA; // Q21
202  double decibelRatingB; // Y2
203  double pressureB; // X2
204  double firstFlowB; // Q12
205  double secondFlowB; // Q22
206  */
207 
208  const double denominator = (pressureB - pressureA) * (decibelRatingB - decibelRatingA);
209  const double leakRateEstimate = ((pressureB - linePressure) * (decibelRatingB - decibels)) / denominator * firstFlowA
210  + ((linePressure - pressureA) * (decibelRatingB - decibels)) / denominator * secondFlowA
211  + ((pressureB - linePressure) * (decibels - decibelRatingA)) / denominator * firstFlowB
212  + ((linePressure - pressureA) * (decibels - decibelRatingA)) / denominator * secondFlowB;
213  const double annualConsumption = (leakRateEstimate * operatingTime * 60) / 1000;
214  DecibelsMethod::Output output(leakRateEstimate, annualConsumption);
215 
216  return output;
217 }
218 
219 OrificeMethod::OrificeMethod(const double operatingTime, const double airTemp, const double atmPressure, const double dischargeCoef,
220  const double diameter, const double supplyPressure, const int numOrifices)
221  : operatingTime(operatingTime), airTemp(airTemp), atmPressure(atmPressure), dischargeCoef(dischargeCoef), diameter(diameter),
222  supplyPressure(supplyPressure), numOrifices(numOrifices)
223 {}
224 
226  const double standardDensity = (atmPressure + supplyPressure) * (144 / (53.34 * airTemp));
227  const double sonicDensity = std::pow(standardDensity * (2 / (1.4 + 1)), 1/(1.4 - 1));
228  const double leakVelocity = std::pow(((2 * 1.4) / (1.4 + 1)) * 53.34 * airTemp * 32.2, 0.5);
229  const double leakRateLBMmin = sonicDensity * (diameter * diameter) * (M_PI/(4 * 144)) * leakVelocity * 60 * dischargeCoef;
230  const double leakRateScfm = leakRateLBMmin / standardDensity;
231  const double leakRateEstimate = leakRateScfm * numOrifices;
232  const double annualConsumption = (operatingTime * leakRateEstimate * 60) / 1000;
233  OrificeMethod::Output output(standardDensity, sonicDensity, leakVelocity, leakRateLBMmin, leakRateScfm, leakRateEstimate, annualConsumption);
234 
235  return output;
236 }
AirSystemCapacity(PipeData pipeLengths, std::vector< double > gallons)
double calculateSize()
OperatingCost(double motorBhp, double bhpUnloaded, double annualOperatingHours, double runTimeLoaded, double efficiencyLoaded, double efficiencyUnloaded, double costOfElectricity)
PipeSizing(double airflow, double airlinePressure, double designVelocity, double atmosphericPressure)
DecibelsMethod(const double operatingTime, const double linePressure, const double decibels, const double decibelRatingA, const double pressureA, const double firstFlowA, const double secondFlowA, const double decibelRatingB, const double pressureB, const double firstFlowB, const double secondFlowB)
PneumaticValve(double inletPressure, double outletPressure)
PneumaticAirRequirement(PistonType pistonType, double cylinderDiameter, double cylinderStroke, double pistonRodDiameter, double airPressure, double cyclesPerMin)
AirVelocity(double airFlow, double pipePressure, double atmosphericPressure)
OrificeMethod(const double operatingTime, const double airTemp, const double atmPressure, const double dischargeCoef, const double diameter, const double supplyPressure, const int numOrifices)
EstimateMethod(const double operatingTime, const double leakRateEstimate)
Output calculate()
BagMethod(double operatingTime, double bagFillTime, double heightOfBag, double diameterOfBag, int numberOfUnits)
Output calculate()