Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : #include <EnergyPlus/Autosizing/All_Simple_Sizing.hh>
49 : #include <EnergyPlus/Autosizing/CoolingAirFlowSizing.hh>
50 : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
51 : #include <EnergyPlus/Coils/CoilCoolingDXCurveFitOperatingMode.hh>
52 : #include <EnergyPlus/Coils/CoilCoolingDXCurveFitSpeed.hh>
53 : #include <EnergyPlus/Data/EnergyPlusData.hh>
54 : #include <EnergyPlus/DataEnvironment.hh>
55 : #include <EnergyPlus/DataHVACGlobals.hh>
56 : #include <EnergyPlus/DataIPShortCuts.hh>
57 : #include <EnergyPlus/DataSizing.hh>
58 : #include <EnergyPlus/EMSManager.hh>
59 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
60 : #include <EnergyPlus/Psychrometrics.hh>
61 :
62 : using namespace EnergyPlus;
63 :
64 58 : void CoilCoolingDXCurveFitOperatingMode::instantiateFromInputSpec(EnergyPlus::EnergyPlusData &state,
65 : CoilCoolingDXCurveFitOperatingModeInputSpecification input_data)
66 : {
67 : static constexpr std::string_view routineName("CoilCoolingDXCurveFitOperatingMode::instantiateFromInputSpec: ");
68 58 : bool errorsFound(false);
69 58 : this->original_input_specs = input_data;
70 58 : this->name = input_data.name;
71 58 : this->ratedGrossTotalCap = input_data.gross_rated_total_cooling_capacity;
72 58 : if (this->ratedGrossTotalCap == DataSizing::AutoSize) this->ratedGrossTotalCapIsAutosized = true;
73 58 : this->ratedEvapAirFlowRate = input_data.rated_evaporator_air_flow_rate;
74 58 : if (this->ratedEvapAirFlowRate == DataSizing::AutoSize) this->ratedEvapAirFlowRateIsAutosized = true;
75 58 : this->ratedCondAirFlowRate = input_data.rated_condenser_air_flow_rate;
76 58 : this->timeForCondensateRemoval = input_data.nominal_time_for_condensate_removal_to_begin;
77 58 : this->evapRateRatio = input_data.ratio_of_initial_moisture_evaporation_rate_and_steady_state_latent_capacity;
78 58 : this->maxCyclingRate = input_data.maximum_cycling_rate;
79 58 : this->latentTimeConst = input_data.latent_capacity_time_constant;
80 58 : if (UtilityRoutines::SameString(input_data.apply_latent_degradation_to_speeds_greater_than_1, "Yes")) {
81 15 : this->applyLatentDegradationAllSpeeds = true;
82 : } else {
83 43 : this->applyLatentDegradationAllSpeeds = false;
84 : }
85 : // TODO: UNUSED apply_latent_degradation_to_speeds_greater_than_1
86 58 : this->nominalEvaporativePumpPower = input_data.nominal_evap_condenser_pump_power;
87 :
88 : // Must all be greater than zero to use the latent capacity degradation model
89 61 : if ((this->maxCyclingRate > 0.0 || this->evapRateRatio > 0.0 || this->latentTimeConst > 0.0 || this->timeForCondensateRemoval > 0.0) &&
90 5 : (this->maxCyclingRate <= 0.0 || this->evapRateRatio <= 0.0 || this->latentTimeConst <= 0.0 || this->timeForCondensateRemoval <= 0.0)) {
91 1 : ShowWarningError(state, std::string{routineName} + this->object_name + "=\"" + this->name + "\":");
92 1 : ShowContinueError(state, "...At least one of the four input parameters for the latent capacity degradation model");
93 1 : ShowContinueError(state, "...is set to zero. Therefore, the latent degradation model will not be used for this simulation.");
94 1 : this->latentDegradationActive = false;
95 57 : } else if (this->maxCyclingRate > 0.0 && this->evapRateRatio > 0.0 && this->latentTimeConst > 0.0 && this->timeForCondensateRemoval > 0.0) {
96 2 : this->latentDegradationActive = true;
97 : }
98 :
99 58 : if (UtilityRoutines::SameString(input_data.condenser_type, "AirCooled")) {
100 58 : this->condenserType = CondenserType::AIRCOOLED;
101 0 : } else if (UtilityRoutines::SameString(input_data.condenser_type, "EvaporativelyCooled")) {
102 0 : this->condenserType = CondenserType::EVAPCOOLED;
103 : } else {
104 0 : ShowSevereError(state, std::string{routineName} + this->object_name + "=\"" + this->name + "\", invalid");
105 0 : ShowContinueError(state, "...Condenser Type=\"" + input_data.condenser_type + "\":");
106 0 : ShowContinueError(state, "...must be AirCooled or EvaporativelyCooled.");
107 0 : errorsFound = true;
108 : }
109 177 : for (auto &speed_name : input_data.speed_data_names) {
110 119 : this->speeds.emplace_back(state, speed_name);
111 : }
112 :
113 : // convert speed num in IDF to vector index
114 58 : this->nominalSpeedIndex = input_data.nominal_speed_number - 1;
115 :
116 58 : if (errorsFound) {
117 0 : ShowFatalError(
118 0 : state, std::string{routineName} + "Errors found in getting " + this->object_name + " input. Preceding condition(s) causes termination.");
119 : }
120 58 : }
121 :
122 58 : CoilCoolingDXCurveFitOperatingMode::CoilCoolingDXCurveFitOperatingMode(EnergyPlus::EnergyPlusData &state, const std::string &name_to_find)
123 : {
124 58 : int numModes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CoilCoolingDXCurveFitOperatingMode::object_name);
125 : if (numModes <= 0) {
126 : // error
127 : }
128 58 : bool found_it = false;
129 184 : for (int modeNum = 1; modeNum <= numModes; ++modeNum) {
130 : int NumAlphas; // Number of Alphas for each GetObjectItem call
131 : int NumNumbers; // Number of Numbers for each GetObjectItem call
132 : int IOStatus;
133 552 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
134 : CoilCoolingDXCurveFitOperatingMode::object_name,
135 : modeNum,
136 184 : state.dataIPShortCut->cAlphaArgs,
137 : NumAlphas,
138 184 : state.dataIPShortCut->rNumericArgs,
139 : NumNumbers,
140 : IOStatus);
141 184 : if (!UtilityRoutines::SameString(name_to_find, state.dataIPShortCut->cAlphaArgs(1))) {
142 126 : continue;
143 : }
144 58 : found_it = true;
145 :
146 116 : CoilCoolingDXCurveFitOperatingModeInputSpecification input_specs;
147 :
148 58 : input_specs.name = state.dataIPShortCut->cAlphaArgs(1);
149 58 : input_specs.gross_rated_total_cooling_capacity = state.dataIPShortCut->rNumericArgs(1);
150 58 : input_specs.rated_evaporator_air_flow_rate = state.dataIPShortCut->rNumericArgs(2);
151 58 : input_specs.rated_condenser_air_flow_rate = state.dataIPShortCut->rNumericArgs(3);
152 58 : input_specs.maximum_cycling_rate = state.dataIPShortCut->rNumericArgs(4);
153 58 : input_specs.ratio_of_initial_moisture_evaporation_rate_and_steady_state_latent_capacity = state.dataIPShortCut->rNumericArgs(5);
154 58 : input_specs.latent_capacity_time_constant = state.dataIPShortCut->rNumericArgs(6);
155 58 : input_specs.nominal_time_for_condensate_removal_to_begin = state.dataIPShortCut->rNumericArgs(7);
156 58 : input_specs.apply_latent_degradation_to_speeds_greater_than_1 = state.dataIPShortCut->cAlphaArgs(2);
157 58 : input_specs.condenser_type = state.dataIPShortCut->cAlphaArgs(3);
158 58 : input_specs.nominal_evap_condenser_pump_power = state.dataIPShortCut->rNumericArgs(8);
159 58 : input_specs.nominal_speed_number = state.dataIPShortCut->rNumericArgs(9);
160 177 : for (int fieldNum = 4; fieldNum <= NumAlphas; fieldNum++) {
161 124 : if (state.dataIPShortCut->cAlphaArgs(fieldNum).empty()) {
162 5 : break;
163 : }
164 119 : input_specs.speed_data_names.push_back(state.dataIPShortCut->cAlphaArgs(fieldNum));
165 : }
166 :
167 58 : this->instantiateFromInputSpec(state, input_specs);
168 58 : break;
169 : }
170 :
171 58 : if (!found_it) {
172 0 : ShowFatalError(state, "Could not find Coil:Cooling:DX:CurveFit:OperatingMode object with name: " + name_to_find);
173 : }
174 58 : }
175 :
176 56 : void CoilCoolingDXCurveFitOperatingMode::oneTimeInit(EnergyPlus::EnergyPlusData &state)
177 : {
178 56 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
179 22 : SetupEMSActuator(state,
180 : this->object_name,
181 : this->name,
182 : "Autosized Rated Air Flow Rate",
183 : "[m3/s]",
184 : this->ratedAirVolFlowEMSOverrideON,
185 11 : this->ratedAirVolFlowEMSOverrideValue);
186 22 : SetupEMSActuator(state,
187 : this->object_name,
188 : this->name,
189 : "Autosized Rated Total Cooling Capacity",
190 : "[W]",
191 : this->ratedTotCapFlowEMSOverrideON,
192 11 : this->ratedTotCapFlowEMSOverrideValue);
193 : }
194 56 : }
195 :
196 58 : void CoilCoolingDXCurveFitOperatingMode::size(EnergyPlus::EnergyPlusData &state)
197 : {
198 :
199 : static constexpr std::string_view RoutineName = "sizeOperatingMode";
200 116 : std::string CompType = this->object_name;
201 116 : std::string CompName = this->name;
202 58 : bool PrintFlag = true;
203 58 : bool errorsFound = false;
204 :
205 58 : Real64 TempSize = this->original_input_specs.rated_evaporator_air_flow_rate;
206 116 : CoolingAirFlowSizer sizingCoolingAirFlow;
207 116 : std::string stringOverride = "Rated Evaporator Air Flow Rate [m3/s]";
208 58 : if (state.dataGlobal->isEpJSON) stringOverride = "rated_evaporator_air_flow_rate";
209 58 : sizingCoolingAirFlow.overrideSizingString(stringOverride);
210 58 : sizingCoolingAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
211 58 : this->ratedEvapAirFlowRate = sizingCoolingAirFlow.size(state, TempSize, errorsFound);
212 :
213 58 : Real64 constexpr ratedInletAirTemp(26.6667); // 26.6667C or 80F
214 58 : Real64 constexpr ratedInletAirHumRat(0.0111847); // Humidity ratio corresponding to 80F dry bulb/67F wet bulb
215 58 : this->ratedEvapAirMassFlowRate =
216 116 : this->ratedEvapAirFlowRate *
217 58 : Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, ratedInletAirTemp, ratedInletAirHumRat, RoutineName);
218 :
219 116 : std::string SizingString = "Rated Gross Total Cooling Capacity [W]";
220 58 : state.dataSize->DataFlowUsedForSizing = this->ratedEvapAirFlowRate;
221 58 : state.dataSize->DataTotCapCurveIndex = this->speeds[this->nominalSpeedIndex].indexCapFT;
222 58 : TempSize = this->original_input_specs.gross_rated_total_cooling_capacity;
223 116 : CoolingCapacitySizer sizerCoolingCapacity;
224 58 : sizerCoolingCapacity.overrideSizingString(SizingString);
225 58 : sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
226 58 : this->ratedGrossTotalCap = sizerCoolingCapacity.size(state, TempSize, errorsFound);
227 :
228 : // Auto size condenser air flow to Total Capacity * 0.000114 m3/s/w (850 cfm/ton)
229 58 : state.dataSize->DataConstantUsedForSizing = this->ratedGrossTotalCap;
230 58 : state.dataSize->DataFractionUsedForSizing = 0.000114;
231 58 : TempSize = this->original_input_specs.rated_condenser_air_flow_rate;
232 :
233 116 : AutoCalculateSizer sizerCondAirFlow;
234 58 : stringOverride = "Rated Condenser Air Flow Rate [m3/s]";
235 58 : if (state.dataGlobal->isEpJSON) stringOverride = "rated_condenser_air_flow_rate";
236 58 : sizerCondAirFlow.overrideSizingString(stringOverride);
237 58 : sizerCondAirFlow.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
238 58 : this->ratedCondAirFlowRate = sizerCondAirFlow.size(state, TempSize, errorsFound);
239 :
240 58 : if (this->condenserType != CondenserType::AIRCOOLED) {
241 : // Auto size Nominal Evaporative Condenser Pump Power to Total Capacity * 0.004266 w/w (15 W/ton)
242 0 : AutoCalculateSizer sizerCondEvapPumpPower;
243 0 : state.dataSize->DataConstantUsedForSizing = this->ratedGrossTotalCap;
244 0 : state.dataSize->DataFractionUsedForSizing = 0.004266;
245 0 : stringOverride = "Nominal Evaporative Condenser Pump Power [W]";
246 0 : sizerCondEvapPumpPower.overrideSizingString(stringOverride);
247 0 : TempSize = this->original_input_specs.nominal_evap_condenser_pump_power;
248 0 : sizerCondEvapPumpPower.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
249 0 : this->nominalEvaporativePumpPower = sizerCondEvapPumpPower.size(state, TempSize, errorsFound);
250 : }
251 :
252 58 : int thisSpeedNum = 0;
253 177 : for (auto &curSpeed : this->speeds) {
254 119 : curSpeed.parentName = this->parentName;
255 119 : curSpeed.parentModeRatedGrossTotalCap = this->ratedGrossTotalCap;
256 119 : curSpeed.ratedGrossTotalCapIsAutosized = this->ratedGrossTotalCapIsAutosized;
257 119 : curSpeed.parentModeRatedEvapAirFlowRate = this->ratedEvapAirFlowRate;
258 119 : curSpeed.ratedEvapAirFlowRateIsAutosized = this->ratedEvapAirFlowRateIsAutosized;
259 119 : curSpeed.parentModeRatedCondAirFlowRate = this->ratedCondAirFlowRate;
260 :
261 : // Set latent degradation parameters if applicable
262 119 : curSpeed.doLatentDegradation = false;
263 119 : if (this->latentDegradationActive) {
264 5 : if ((thisSpeedNum == 0) || ((thisSpeedNum > 0) && this->applyLatentDegradationAllSpeeds)) {
265 2 : curSpeed.parentModeTimeForCondensateRemoval = this->timeForCondensateRemoval;
266 2 : curSpeed.parentModeEvapRateRatio = this->evapRateRatio;
267 2 : curSpeed.parentModeMaxCyclingRate = this->maxCyclingRate;
268 2 : curSpeed.parentModeLatentTimeConst = this->latentTimeConst;
269 2 : curSpeed.doLatentDegradation = true;
270 : }
271 : }
272 :
273 119 : curSpeed.size(state);
274 119 : thisSpeedNum++;
275 : }
276 58 : }
277 :
278 4520793 : void CoilCoolingDXCurveFitOperatingMode::CalcOperatingMode(EnergyPlus::EnergyPlusData &state,
279 : const DataLoopNode::NodeData &inletNode,
280 : DataLoopNode::NodeData &outletNode,
281 : Real64 &PLR,
282 : int &speedNum,
283 : Real64 &speedRatio,
284 : int const fanOpMode,
285 : DataLoopNode::NodeData &condInletNode,
286 : [[maybe_unused]] DataLoopNode::NodeData &condOutletNode,
287 : [[maybe_unused]] bool const singleMode)
288 : {
289 :
290 : static constexpr std::string_view RoutineName = "CoilCoolingDXCurveFitOperatingMode::calcOperatingMode";
291 : // Currently speedNum is 1-based, while this->speeds are zero-based
292 4520793 : auto &thisspeed(this->speeds[max(speedNum - 1, 0)]);
293 :
294 4520793 : if (((speedNum == 1) && (PLR == 0.0)) || (inletNode.MassFlowRate == 0.0)) {
295 467050 : outletNode.Temp = inletNode.Temp;
296 467050 : outletNode.HumRat = inletNode.HumRat;
297 467050 : outletNode.Enthalpy = inletNode.Enthalpy;
298 467050 : outletNode.Press = inletNode.Press;
299 467050 : OpModeRTF = 0.0;
300 467050 : OpModePower = 0.0;
301 467050 : OpModeWasteHeat = 0.0;
302 467050 : return;
303 : }
304 :
305 4053743 : if (condInletNode.Press <= 0.0) {
306 0 : condInletNode.Press = state.dataEnvrn->OutBaroPress;
307 : }
308 4053743 : if (this->condenserType == CondenserType::AIRCOOLED) {
309 4053743 : this->condInletTemp = condInletNode.Temp;
310 0 : } else if (this->condenserType == CondenserType::EVAPCOOLED) {
311 0 : this->condInletTemp = Psychrometrics::PsyTwbFnTdbWPb(
312 0 : state, condInletNode.Temp, condInletNode.HumRat, condInletNode.Press, "CoilCoolingDXCurveFitOperatingMode::CalcOperatingMode");
313 : }
314 4053743 : thisspeed.ambPressure = condInletNode.Press;
315 4053743 : thisspeed.AirMassFlow = inletNode.MassFlowRate;
316 4053743 : if (fanOpMode == DataHVACGlobals::CycFanCycCoil && speedNum == 1) {
317 149660 : if (PLR > 0.0) {
318 74830 : thisspeed.AirMassFlow = thisspeed.AirMassFlow / PLR;
319 : } else {
320 0 : thisspeed.AirMassFlow = 0.0;
321 : }
322 3978913 : } else if (speedNum > 1) {
323 1225348 : thisspeed.AirMassFlow = state.dataHVACGlobal->MSHPMassFlowRateHigh;
324 : }
325 : // rated flow rate is adjusted by coil face area fraction so adjustment is before next IF
326 4053743 : thisspeed.AirMassFlow *= thisspeed.active_fraction_of_face_coil_area;
327 4053743 : if (thisspeed.RatedAirMassFlowRate > 0.0) {
328 4053743 : thisspeed.AirFF = thisspeed.AirMassFlow / thisspeed.RatedAirMassFlowRate;
329 : } else {
330 0 : thisspeed.AirFF = 0.0;
331 : }
332 :
333 : // If multispeed, evaluate high speed first using speedRatio as PLR
334 4053743 : Real64 plr1 = PLR;
335 4053743 : if (speedNum > 1) {
336 1225348 : plr1 = speedRatio;
337 : }
338 :
339 4053743 : thisspeed.CalcSpeedOutput(state, inletNode, outletNode, plr1, fanOpMode, this->condInletTemp);
340 :
341 : // the outlet node conditions are based on it running at the truncated flow, we need to merge the bypassed air back in and ramp up flow rate
342 4053743 : if (thisspeed.adjustForFaceArea) {
343 903100 : thisspeed.AirMassFlow /= thisspeed.active_fraction_of_face_coil_area;
344 1806200 : Real64 correctedEnthalpy = (1.0 - thisspeed.active_fraction_of_face_coil_area) * inletNode.Enthalpy +
345 903100 : thisspeed.active_fraction_of_face_coil_area * outletNode.Enthalpy;
346 903100 : Real64 correctedHumRat =
347 903100 : (1.0 - thisspeed.active_fraction_of_face_coil_area) * inletNode.HumRat + thisspeed.active_fraction_of_face_coil_area * outletNode.HumRat;
348 903100 : Real64 correctedTemp = Psychrometrics::PsyTdbFnHW(correctedEnthalpy, correctedHumRat);
349 : // Check for saturation error and modify temperature at constant enthalpy
350 903100 : if (correctedTemp < Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName)) {
351 1272 : correctedTemp = Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName);
352 1272 : correctedHumRat = Psychrometrics::PsyWFnTdbH(state, correctedTemp, correctedEnthalpy, RoutineName);
353 : }
354 903100 : outletNode.Temp = correctedTemp;
355 903100 : outletNode.HumRat = correctedHumRat;
356 903100 : outletNode.Enthalpy = correctedEnthalpy;
357 : }
358 :
359 4053743 : Real64 outSpeed1HumRat = outletNode.HumRat;
360 4053743 : Real64 outSpeed1Enthalpy = outletNode.Enthalpy;
361 :
362 4053743 : if (fanOpMode == DataHVACGlobals::ContFanCycCoil) {
363 3920472 : outletNode.HumRat = outletNode.HumRat * plr1 + (1.0 - plr1) * inletNode.HumRat;
364 3920472 : outletNode.Enthalpy = outletNode.Enthalpy * plr1 + (1.0 - plr1) * inletNode.Enthalpy;
365 3920472 : outletNode.Temp = Psychrometrics::PsyTdbFnHW(outletNode.Enthalpy, outletNode.HumRat);
366 :
367 : // Check for saturation error and modify temperature at constant enthalpy
368 3920472 : Real64 tsat = Psychrometrics::PsyTsatFnHPb(state, outletNode.Enthalpy, inletNode.Press, RoutineName);
369 3920472 : if (outletNode.Temp < tsat) {
370 44211 : outletNode.Temp = tsat;
371 44211 : outletNode.HumRat = Psychrometrics::PsyWFnTdbH(state, tsat, outletNode.Enthalpy);
372 : }
373 : }
374 :
375 4053743 : OpModeRTF = thisspeed.RTF;
376 4053743 : OpModePower = thisspeed.fullLoadPower * thisspeed.RTF;
377 4053743 : OpModeWasteHeat = thisspeed.fullLoadWasteHeat * thisspeed.RTF;
378 :
379 4053743 : if ((speedNum > 1) && (speedRatio < 1.0) && !singleMode) {
380 :
381 : // If multispeed, evaluate next lower speed using PLR, then combine with high speed for final outlet conditions
382 635590 : auto &lowerspeed(this->speeds[max(speedNum - 2, 0)]);
383 635590 : lowerspeed.AirMassFlow = state.dataHVACGlobal->MSHPMassFlowRateLow * lowerspeed.active_fraction_of_face_coil_area;
384 :
385 635590 : lowerspeed.CalcSpeedOutput(state, inletNode, outletNode, PLR, fanOpMode, condInletTemp); // out
386 :
387 635590 : if (lowerspeed.adjustForFaceArea) {
388 241688 : lowerspeed.AirMassFlow /= lowerspeed.active_fraction_of_face_coil_area;
389 483376 : Real64 correctedEnthalpy = (1.0 - lowerspeed.active_fraction_of_face_coil_area) * inletNode.Enthalpy +
390 241688 : lowerspeed.active_fraction_of_face_coil_area * outletNode.Enthalpy;
391 483376 : Real64 correctedHumRat = (1.0 - lowerspeed.active_fraction_of_face_coil_area) * inletNode.HumRat +
392 241688 : lowerspeed.active_fraction_of_face_coil_area * outletNode.HumRat;
393 241688 : Real64 correctedTemp = Psychrometrics::PsyTdbFnHW(correctedEnthalpy, correctedHumRat);
394 : // Check for saturation error and modify temperature at constant enthalpy
395 241688 : if (correctedTemp < Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName)) {
396 64 : correctedTemp = Psychrometrics::PsyTsatFnHPb(state, correctedEnthalpy, inletNode.Press, RoutineName);
397 64 : correctedHumRat = Psychrometrics::PsyWFnTdbH(state, correctedTemp, correctedEnthalpy, RoutineName);
398 : }
399 241688 : outletNode.Temp = correctedTemp;
400 241688 : outletNode.HumRat = correctedHumRat;
401 241688 : outletNode.Enthalpy = correctedEnthalpy;
402 : }
403 :
404 1271180 : outletNode.HumRat = (outSpeed1HumRat * speedRatio * thisspeed.AirMassFlow + (1.0 - speedRatio) * outletNode.HumRat * lowerspeed.AirMassFlow) /
405 635590 : inletNode.MassFlowRate;
406 635590 : outletNode.Enthalpy =
407 1271180 : (outSpeed1Enthalpy * speedRatio * thisspeed.AirMassFlow + (1.0 - speedRatio) * outletNode.Enthalpy * lowerspeed.AirMassFlow) /
408 635590 : inletNode.MassFlowRate;
409 : // outletNode.HumRat = outSpeed1HumRat * speedRatio + (1.0 - speedRatio) * outletNode.HumRat;
410 : // outletNode.Enthalpy = outSpeed1Enthalpy * speedRatio + (1.0 - speedRatio) * outletNode.Enthalpy;
411 635590 : outletNode.Temp = Psychrometrics::PsyTdbFnHW(outletNode.Enthalpy, outletNode.HumRat);
412 :
413 635590 : this->OpModePower += (1.0 - thisspeed.RTF) * lowerspeed.fullLoadPower;
414 635590 : this->OpModeWasteHeat += (1.0 - thisspeed.RTF) * lowerspeed.fullLoadWasteHeat;
415 635590 : this->OpModeRTF = 1.0; // if we are on greater than 1 speed, RTF *must* be 1
416 : }
417 : }
418 :
419 0 : Real64 CoilCoolingDXCurveFitOperatingMode::getCurrentEvapCondPumpPower(int speedNum)
420 : {
421 : // Currently speedNum is 1-based, while this->speeds are zero-based
422 0 : auto const &thisspeed(this->speeds[max(speedNum - 1, 0)]);
423 0 : auto const &powerFraction(thisspeed.evap_condenser_pump_power_fraction);
424 0 : return this->nominalEvaporativePumpPower * powerFraction;
425 2313 : }
|