Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, 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 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <AirflowNetwork/Solver.hpp>
57 : #include <EnergyPlus/Autosizing/Base.hh>
58 : #include <EnergyPlus/BranchNodeConnections.hh>
59 : #include <EnergyPlus/DXCoils.hh>
60 : #include <EnergyPlus/Data/EnergyPlusData.hh>
61 : #include <EnergyPlus/DataAirSystems.hh>
62 : #include <EnergyPlus/DataEnvironment.hh>
63 : #include <EnergyPlus/DataHVACGlobals.hh>
64 : #include <EnergyPlus/DataLoopNode.hh>
65 : #include <EnergyPlus/DataSizing.hh>
66 : #include <EnergyPlus/DataZoneControls.hh>
67 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
68 : #include <EnergyPlus/DataZoneEquipment.hh>
69 : #include <EnergyPlus/EMSManager.hh>
70 : #include <EnergyPlus/Fans.hh>
71 : #include <EnergyPlus/FluidProperties.hh>
72 : #include <EnergyPlus/General.hh>
73 : #include <EnergyPlus/GeneralRoutines.hh>
74 : #include <EnergyPlus/HVACMultiSpeedHeatPump.hh>
75 : #include <EnergyPlus/HeatingCoils.hh>
76 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
77 : #include <EnergyPlus/NodeInputManager.hh>
78 : #include <EnergyPlus/OutputProcessor.hh>
79 : #include <EnergyPlus/OutputReportPredefined.hh>
80 : #include <EnergyPlus/Plant/DataPlant.hh>
81 : #include <EnergyPlus/PlantUtilities.hh>
82 : #include <EnergyPlus/Psychrometrics.hh>
83 : #include <EnergyPlus/ScheduleManager.hh>
84 : #include <EnergyPlus/SteamCoils.hh>
85 : #include <EnergyPlus/UtilityRoutines.hh>
86 : #include <EnergyPlus/WaterCoils.hh>
87 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
88 :
89 : namespace EnergyPlus {
90 :
91 : namespace HVACMultiSpeedHeatPump {
92 :
93 : // Module containing the Multi Speed Heat Pump simulation routines
94 :
95 : // MODULE INFORMATION:
96 : // AUTHOR Lixing Gu, Florida Solar Energy Center
97 : // DATE WRITTEN June 2007
98 : // MODIFIED Bereket Nigusse, FSEC, June 2010 - deprecated supply air flow fraction through controlled
99 : // zone from the furnace object input field. Now, the flow fraction is calculated internally
100 : // Brent Griffith, NREL, Dec 2010 -- upgrade to new plant for heat recovery, general fluid props.
101 : // Bereket Nigusse, FSEC, Jan. 2012 -- added hot water and steam heating coil
102 : // PURPOSE OF THIS MODULE:
103 : // To encapsulate the data and algorithms required to simulate Multi Speed Heat Pump in
104 : // EnergyPlus.
105 :
106 : // Module currently models air-cooled or evap-cooled direct expansion systems
107 : // (split or packaged) with multiple speeds. Air-side performance is modeled to determine
108 : // coil discharge air conditions. The module also determines the DX unit's energy
109 : // usage. Neither the air-side performance nor the energy usage includes the effect
110 : // of supply air fan heat/energy usage. The supply air fan is modeled by other modules.
111 :
112 : // Curve Types
113 : enum class CurveType
114 : {
115 : Invalid = -1,
116 : Linear, // Linear curve type
117 : BiLinear, // Bi-linear curve type
118 : Quadratic, // Quadratic curve type
119 : BiQuadratic, // Bi-quadratic curve type
120 : Cubic, // Cubic curve type
121 : Num
122 : };
123 :
124 226090 : void SimMSHeatPump(EnergyPlusData &state,
125 : std::string_view CompName, // Name of the unitary engine driven heat pump system
126 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system time step
127 : int const AirLoopNum, // air loop index
128 : int &CompIndex // Index to changeover-bypass VAV system
129 : )
130 : {
131 :
132 : // SUBROUTINE INFORMATION:
133 : // AUTHOR Lixing Gu, Florida Solar Energy Center
134 : // DATE WRITTEN June. 2007
135 :
136 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
137 : int MSHeatPumpNum; // index of fan coil unit being simulated
138 : Real64 OnOffAirFlowRatio; // Ratio of compressor ON airflow to average airflow over timestep
139 : Real64 QZnLoad; // Zone load required by all zones served by this air loop system
140 : Real64 QSensUnitOut; // MSHP sensible capacity output [W]
141 :
142 : // First time SimMSHeatPump is called, get the input
143 226090 : if (state.dataHVACMultiSpdHP->GetInputFlag) {
144 11 : GetMSHeatPumpInput(state);
145 11 : state.dataHVACMultiSpdHP->GetInputFlag = false; // Set GetInputFlag false so you don't get coil inputs again
146 : }
147 :
148 226090 : if (CompIndex == 0) {
149 11 : MSHeatPumpNum = Util::FindItemInList(CompName, state.dataHVACMultiSpdHP->MSHeatPump);
150 11 : if (MSHeatPumpNum == 0) {
151 0 : ShowFatalError(state, format("MultiSpeed Heat Pump is not found={}", CompName));
152 : }
153 11 : CompIndex = MSHeatPumpNum;
154 : } else {
155 226079 : MSHeatPumpNum = CompIndex;
156 226079 : if (MSHeatPumpNum > state.dataHVACMultiSpdHP->NumMSHeatPumps || MSHeatPumpNum < 1) {
157 0 : ShowFatalError(state,
158 0 : format("SimMSHeatPump: Invalid CompIndex passed={}, Number of MultiSpeed Heat Pumps={}, Heat Pump name={}",
159 : MSHeatPumpNum,
160 0 : state.dataHVACMultiSpdHP->NumMSHeatPumps,
161 : CompName));
162 : }
163 226079 : if (state.dataHVACMultiSpdHP->CheckEquipName(MSHeatPumpNum)) {
164 11 : if (CompName != state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).Name) {
165 0 : ShowFatalError(state,
166 0 : format("SimMSHeatPump: Invalid CompIndex passed={}, Heat Pump name={}{}",
167 : MSHeatPumpNum,
168 : CompName,
169 0 : state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).Name));
170 : }
171 11 : state.dataHVACMultiSpdHP->CheckEquipName(MSHeatPumpNum) = false;
172 : }
173 : }
174 :
175 226090 : OnOffAirFlowRatio = 0.0;
176 :
177 : // Initialize the engine driven heat pump
178 226090 : InitMSHeatPump(state, MSHeatPumpNum, FirstHVACIteration, AirLoopNum, QZnLoad, OnOffAirFlowRatio);
179 :
180 226090 : SimMSHP(state, MSHeatPumpNum, FirstHVACIteration, AirLoopNum, QSensUnitOut, QZnLoad, OnOffAirFlowRatio);
181 :
182 : // Update the unit outlet nodes
183 226090 : UpdateMSHeatPump(state, MSHeatPumpNum);
184 :
185 : // Report the result of the simulation
186 226090 : ReportMSHeatPump(state, MSHeatPumpNum);
187 226090 : }
188 :
189 : //******************************************************************************
190 :
191 226090 : void SimMSHP(EnergyPlusData &state,
192 : int const MSHeatPumpNum, // number of the current engine driven Heat Pump being simulated
193 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
194 : int const AirLoopNum, // air loop index
195 : Real64 &QSensUnitOut, // cooling/heating delivered to zones [W]
196 : Real64 const QZnReq, // required zone load
197 : Real64 &OnOffAirFlowRatio // ratio of compressor ON airflow to AVERAGE airflow over timestep
198 : )
199 : {
200 :
201 : // SUBROUTINE INFORMATION:
202 : // AUTHOR Lixing Gu
203 : // DATE WRITTEN June 2007
204 : // RE-ENGINEERED Revised based on SimPTHP
205 :
206 : // PURPOSE OF THIS SUBROUTINE:
207 : // Simulate a multispeed heat pump; adjust its output to match the
208 : // required system load.
209 :
210 : // METHODOLOGY EMPLOYED:
211 : // Calls ControlMSHPOutput to obtain the desired unit output
212 :
213 : // Locals
214 : Real64 SupHeaterLoad;
215 :
216 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
217 : Real64 PartLoadFrac; // compressor part load fraction
218 : Real64 SpeedRatio; // compressor speed ratio
219 : bool UnitOn; // TRUE if unit is on
220 : int OutletNode; // MSHP air outlet node
221 : int InletNode; // MSHP air inlet node
222 : Real64 AirMassFlow; // air mass flow rate [kg/s]
223 : HVAC::FanOp fanOp; // operating mode (fan cycling or continuous; DX coil always cycles)
224 : int ZoneNum; // Controlled zone number
225 : Real64 QTotUnitOut;
226 : int SpeedNum; // Speed number
227 : HVAC::CompressorOp compressorOp; // compressor operation; 1=on, 0=off
228 : Real64 SaveMassFlowRate; // saved inlet air mass flow rate [kg/s]
229 :
230 : // zero the fan, DX coils, and supplemental electric heater electricity consumption
231 226090 : state.dataHVACGlobal->DXElecHeatingPower = 0.0;
232 226090 : state.dataHVACGlobal->DXElecCoolingPower = 0.0;
233 226090 : state.dataHVACMultiSpdHP->SaveCompressorPLR = 0.0;
234 226090 : state.dataHVACGlobal->ElecHeatingCoilPower = 0.0;
235 226090 : state.dataHVACGlobal->SuppHeatingCoilPower = 0.0;
236 226090 : state.dataHVACGlobal->DefrostElecPower = 0.0;
237 :
238 226090 : auto &multiSpeedHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
239 :
240 : // initialize local variables
241 226090 : UnitOn = true;
242 226090 : OutletNode = multiSpeedHeatPump.AirOutletNodeNum;
243 226090 : InletNode = multiSpeedHeatPump.AirInletNodeNum;
244 226090 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
245 226090 : fanOp = multiSpeedHeatPump.fanOp;
246 226090 : ZoneNum = multiSpeedHeatPump.ControlZoneNum;
247 226090 : compressorOp = HVAC::CompressorOp::On;
248 :
249 : // set the on/off flags
250 226090 : if (multiSpeedHeatPump.fanOp == HVAC::FanOp::Cycling) {
251 : // cycling unit only runs if there is a cooling or heating load.
252 239635 : if (std::abs(QZnReq) < HVAC::SmallLoad || AirMassFlow < HVAC::SmallMassFlow ||
253 71847 : state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
254 95941 : UnitOn = false;
255 : }
256 58302 : } else if (multiSpeedHeatPump.fanOp == HVAC::FanOp::Continuous) {
257 : // continuous unit: fan runs if scheduled on; coil runs only if there is a cooling or heating load
258 58302 : if (AirMassFlow < HVAC::SmallMassFlow) {
259 0 : UnitOn = false;
260 : }
261 : }
262 :
263 226090 : state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
264 :
265 226090 : SaveMassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
266 226090 : if (multiSpeedHeatPump.EMSOverrideCoilSpeedNumOn) {
267 31715 : Real64 SpeedVal = multiSpeedHeatPump.EMSOverrideCoilSpeedNumValue;
268 :
269 41249 : if (!FirstHVACIteration && multiSpeedHeatPump.fanOp == HVAC::FanOp::Cycling && QZnReq < 0.0 &&
270 9534 : state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
271 0 : compressorOp = HVAC::CompressorOp::Off;
272 0 : ControlMSHPOutputEMS(state,
273 : MSHeatPumpNum,
274 : FirstHVACIteration,
275 : compressorOp,
276 : fanOp,
277 : QZnReq,
278 : SpeedVal,
279 : SpeedNum,
280 : SpeedRatio,
281 : PartLoadFrac,
282 : OnOffAirFlowRatio,
283 : SupHeaterLoad);
284 0 : if (ceil(SpeedVal) == multiSpeedHeatPump.NumOfSpeedCooling && SpeedRatio == 1.0) {
285 0 : state.dataLoopNodes->Node(InletNode).MassFlowRate = SaveMassFlowRate;
286 0 : compressorOp = HVAC::CompressorOp::On;
287 0 : ControlMSHPOutputEMS(state,
288 : MSHeatPumpNum,
289 : FirstHVACIteration,
290 : compressorOp,
291 : fanOp,
292 : QZnReq,
293 : SpeedVal,
294 : SpeedNum,
295 : SpeedRatio,
296 : PartLoadFrac,
297 : OnOffAirFlowRatio,
298 : SupHeaterLoad);
299 : }
300 : } else {
301 31715 : ControlMSHPOutputEMS(state,
302 : MSHeatPumpNum,
303 : FirstHVACIteration,
304 : compressorOp,
305 : fanOp,
306 : QZnReq,
307 : SpeedVal,
308 : SpeedNum,
309 : SpeedRatio,
310 : PartLoadFrac,
311 : OnOffAirFlowRatio,
312 : SupHeaterLoad);
313 : }
314 : } else {
315 220914 : if (!FirstHVACIteration && multiSpeedHeatPump.fanOp == HVAC::FanOp::Cycling && QZnReq < 0.0 &&
316 26539 : state.dataAirLoop->AirLoopControlInfo(AirLoopNum).EconoActive) {
317 : // for cycling fan, cooling load, check whether furnace can meet load with compressor off
318 0 : compressorOp = HVAC::CompressorOp::Off;
319 0 : ControlMSHPOutput(state,
320 : MSHeatPumpNum,
321 : FirstHVACIteration,
322 : compressorOp,
323 : fanOp,
324 : QZnReq,
325 : ZoneNum,
326 : SpeedNum,
327 : SpeedRatio,
328 : PartLoadFrac,
329 : OnOffAirFlowRatio,
330 : SupHeaterLoad);
331 0 : if (SpeedNum == multiSpeedHeatPump.NumOfSpeedCooling && SpeedRatio == 1.0) {
332 : // compressor on (reset inlet air mass flow rate to starting value)
333 0 : state.dataLoopNodes->Node(InletNode).MassFlowRate = SaveMassFlowRate;
334 0 : compressorOp = HVAC::CompressorOp::On;
335 0 : ControlMSHPOutput(state,
336 : MSHeatPumpNum,
337 : FirstHVACIteration,
338 : compressorOp,
339 : fanOp,
340 : QZnReq,
341 : ZoneNum,
342 : SpeedNum,
343 : SpeedRatio,
344 : PartLoadFrac,
345 : OnOffAirFlowRatio,
346 : SupHeaterLoad);
347 : }
348 : } else {
349 : // compressor on
350 194375 : ControlMSHPOutput(state,
351 : MSHeatPumpNum,
352 : FirstHVACIteration,
353 : compressorOp,
354 : fanOp,
355 : QZnReq,
356 : ZoneNum,
357 : SpeedNum,
358 : SpeedRatio,
359 : PartLoadFrac,
360 : OnOffAirFlowRatio,
361 : SupHeaterLoad);
362 : }
363 : }
364 :
365 226090 : if (multiSpeedHeatPump.HeatCoilType != MultiSpeedHeatingCoil) {
366 41692 : state.dataHVACMultiSpdHP->SaveCompressorPLR = PartLoadFrac;
367 : } else {
368 184398 : if (SpeedNum > 1) {
369 108049 : state.dataHVACMultiSpdHP->SaveCompressorPLR = 1.0;
370 : }
371 :
372 184398 : if (PartLoadFrac == 1.0 && state.dataHVACMultiSpdHP->SaveCompressorPLR < 1.0 && (!multiSpeedHeatPump.Staged)) {
373 2152 : PartLoadFrac = state.dataHVACMultiSpdHP->SaveCompressorPLR;
374 : }
375 : }
376 :
377 226090 : CalcMSHeatPump(state,
378 : MSHeatPumpNum,
379 : FirstHVACIteration,
380 : compressorOp,
381 : SpeedNum,
382 : SpeedRatio,
383 : PartLoadFrac,
384 : QSensUnitOut,
385 : QZnReq,
386 : OnOffAirFlowRatio,
387 : SupHeaterLoad);
388 :
389 : // calculate delivered capacity
390 226090 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
391 :
392 226090 : QTotUnitOut = AirMassFlow * (state.dataLoopNodes->Node(OutletNode).Enthalpy -
393 226090 : state.dataLoopNodes->Node(multiSpeedHeatPump.NodeNumOfControlledZone).Enthalpy);
394 :
395 : // report variables
396 226090 : multiSpeedHeatPump.CompPartLoadRatio = state.dataHVACMultiSpdHP->SaveCompressorPLR;
397 226090 : if (multiSpeedHeatPump.fanOp == HVAC::FanOp::Cycling) {
398 167788 : if (SupHeaterLoad > 0.0) {
399 69814 : multiSpeedHeatPump.FanPartLoadRatio = 1.0;
400 : } else {
401 97974 : if (SpeedNum < 2) {
402 86269 : multiSpeedHeatPump.FanPartLoadRatio = PartLoadFrac;
403 : } else {
404 11705 : multiSpeedHeatPump.FanPartLoadRatio = 1.0;
405 : }
406 : }
407 : } else {
408 58302 : if (UnitOn) {
409 58302 : multiSpeedHeatPump.FanPartLoadRatio = 1.0;
410 : } else {
411 0 : if (SpeedNum < 2) {
412 0 : multiSpeedHeatPump.FanPartLoadRatio = PartLoadFrac;
413 : } else {
414 0 : multiSpeedHeatPump.FanPartLoadRatio = 1.0;
415 : }
416 : }
417 : }
418 :
419 226090 : if (multiSpeedHeatPump.HeatCoolMode == ModeOfOperation::HeatingMode) {
420 104552 : multiSpeedHeatPump.TotHeatEnergyRate = std::abs(max(0.0, QTotUnitOut));
421 104552 : multiSpeedHeatPump.SensHeatEnergyRate = std::abs(max(0.0, QSensUnitOut));
422 104552 : multiSpeedHeatPump.LatHeatEnergyRate = std::abs(max(0.0, (QTotUnitOut - QSensUnitOut)));
423 104552 : multiSpeedHeatPump.TotCoolEnergyRate = 0.0;
424 104552 : multiSpeedHeatPump.SensCoolEnergyRate = 0.0;
425 104552 : multiSpeedHeatPump.LatCoolEnergyRate = 0.0;
426 : }
427 226090 : if (multiSpeedHeatPump.HeatCoolMode == ModeOfOperation::CoolingMode) {
428 85792 : multiSpeedHeatPump.TotCoolEnergyRate = std::abs(min(0.0, QTotUnitOut));
429 85792 : multiSpeedHeatPump.SensCoolEnergyRate = std::abs(min(0.0, QSensUnitOut));
430 85792 : multiSpeedHeatPump.LatCoolEnergyRate = std::abs(min(0.0, (QTotUnitOut - QSensUnitOut)));
431 85792 : multiSpeedHeatPump.TotHeatEnergyRate = 0.0;
432 85792 : multiSpeedHeatPump.SensHeatEnergyRate = 0.0;
433 85792 : multiSpeedHeatPump.LatHeatEnergyRate = 0.0;
434 : }
435 :
436 226090 : multiSpeedHeatPump.AuxElecPower = multiSpeedHeatPump.AuxOnCyclePower * state.dataHVACMultiSpdHP->SaveCompressorPLR +
437 226090 : multiSpeedHeatPump.AuxOffCyclePower * (1.0 - state.dataHVACMultiSpdHP->SaveCompressorPLR);
438 226090 : Real64 locFanElecPower = 0.0;
439 226090 : locFanElecPower = state.dataFans->fans(multiSpeedHeatPump.FanNum)->totalPower;
440 226090 : multiSpeedHeatPump.ElecPower = locFanElecPower + state.dataHVACGlobal->DXElecCoolingPower + state.dataHVACGlobal->DXElecHeatingPower +
441 226090 : state.dataHVACGlobal->ElecHeatingCoilPower + state.dataHVACGlobal->SuppHeatingCoilPower +
442 226090 : state.dataHVACGlobal->DefrostElecPower + multiSpeedHeatPump.AuxElecPower;
443 226090 : }
444 :
445 : //******************************************************************************
446 :
447 11 : void GetMSHeatPumpInput(EnergyPlusData &state)
448 : {
449 : // SUBROUTINE INFORMATION:
450 : // AUTHOR: Lixing Gu, FSEC
451 : // DATE WRITTEN: July 2007
452 :
453 : // PURPOSE OF THIS SUBROUTINE:
454 : // This routine will get the input required by the multispeed heat pump model
455 :
456 : using namespace OutputReportPredefined;
457 :
458 : // PARAMETERS
459 : static constexpr std::string_view RoutineName("GetMSHeatPumpInput: "); // include trailing blank space
460 : static constexpr std::string_view routineName = "GetMSHeatPumpInput";
461 :
462 : // LOCAL VARIABLES
463 : int NumAlphas; // Number of elements in the alpha array
464 : int NumNumbers; // Number of Numbers for each GetObjectItem call
465 : int IOStatus; // Used in GetObjectItem
466 11 : bool ErrorsFound(false); // True when input errors found
467 : bool IsNotOK; // Flag to verify name
468 : bool AirNodeFound; // True when an air node is found
469 : bool AirLoopFound; // True when an air loop is found
470 : int i; // Index to speeds
471 : int j; // Index to speeds
472 : bool Found; // Flag to find autosize
473 : bool LocalError; // Local error flag
474 11 : Array1D_string Alphas; // Alpha input items for object
475 11 : Array1D_string cAlphaFields; // Alpha field names
476 11 : Array1D_string cNumericFields; // Numeric field names
477 11 : Array1D<Real64> Numbers; // Numeric input items for object
478 11 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
479 11 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
480 11 : int MaxNums(0); // Maximum number of numeric input fields
481 11 : int MaxAlphas(0); // Maximum number of alpha input fields
482 11 : int TotalArgs(0); // Total number of alpha and numeric arguments (max) for a
483 : // certain object in the input file
484 : bool errFlag;
485 : Real64 SteamDensity; // density of steam at 100C
486 :
487 11 : auto &MSHeatPump(state.dataHVACMultiSpdHP->MSHeatPump);
488 :
489 11 : if (MSHeatPump.allocated()) {
490 0 : return;
491 : }
492 :
493 11 : state.dataHVACMultiSpdHP->CurrentModuleObject =
494 11 : "AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed"; // Object type for getting and error messages
495 :
496 22 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
497 11 : state, state.dataHVACMultiSpdHP->CurrentModuleObject, TotalArgs, NumAlphas, NumNumbers);
498 11 : MaxNums = max(MaxNums, NumNumbers);
499 11 : MaxAlphas = max(MaxAlphas, NumAlphas);
500 :
501 11 : Alphas.allocate(MaxAlphas);
502 11 : cAlphaFields.allocate(MaxAlphas);
503 11 : Numbers.dimension(MaxNums, 0.0);
504 11 : cNumericFields.allocate(MaxNums);
505 11 : lAlphaBlanks.dimension(MaxAlphas, true);
506 11 : lNumericBlanks.dimension(MaxNums, true);
507 :
508 22 : state.dataHVACMultiSpdHP->NumMSHeatPumps =
509 11 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHVACMultiSpdHP->CurrentModuleObject);
510 :
511 11 : if (state.dataHVACMultiSpdHP->NumMSHeatPumps <= 0) {
512 0 : ShowSevereError(state, format("No {} objects specified in input file.", state.dataHVACMultiSpdHP->CurrentModuleObject));
513 0 : ErrorsFound = true;
514 : }
515 :
516 : // ALLOCATE ARRAYS
517 11 : MSHeatPump.allocate(state.dataHVACMultiSpdHP->NumMSHeatPumps);
518 11 : state.dataHVACMultiSpdHP->MSHeatPumpReport.allocate(state.dataHVACMultiSpdHP->NumMSHeatPumps);
519 11 : state.dataHVACMultiSpdHP->CheckEquipName.dimension(state.dataHVACMultiSpdHP->NumMSHeatPumps, true);
520 :
521 : // Load arrays with reformulated electric EIR chiller data
522 22 : for (int MSHPNum = 1; MSHPNum <= state.dataHVACMultiSpdHP->NumMSHeatPumps; ++MSHPNum) {
523 11 : auto &thisMSHP = MSHeatPump(MSHPNum);
524 11 : int HeatingCoilInletNode = 0;
525 11 : int HeatingCoilOutletNode = 0;
526 11 : int CoolingCoilInletNode = 0;
527 11 : int CoolingCoilOutletNode = 0;
528 11 : int SuppHeatCoilInletNode = 0;
529 11 : int SuppHeatCoilOutletNode = 0;
530 :
531 22 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
532 11 : state.dataHVACMultiSpdHP->CurrentModuleObject,
533 : MSHPNum,
534 : Alphas,
535 : NumAlphas,
536 : Numbers,
537 : NumNumbers,
538 : IOStatus,
539 : lNumericBlanks,
540 : lAlphaBlanks,
541 : cAlphaFields,
542 : cNumericFields);
543 :
544 11 : thisMSHP.Name = Alphas(1);
545 :
546 11 : ErrorObjectHeader eoh{routineName, state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name};
547 :
548 11 : if (lAlphaBlanks(2)) {
549 0 : thisMSHP.availSched = Sched::GetScheduleAlwaysOn(state);
550 11 : } else if ((thisMSHP.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
551 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
552 0 : ErrorsFound = true;
553 : }
554 :
555 11 : thisMSHP.AirInletNodeName = Alphas(3);
556 11 : thisMSHP.AirOutletNodeName = Alphas(4);
557 11 : thisMSHP.AirInletNodeNum = GetOnlySingleNode(state,
558 11 : Alphas(3),
559 : ErrorsFound,
560 : DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed,
561 11 : Alphas(1),
562 : DataLoopNode::NodeFluidType::Air,
563 : DataLoopNode::ConnectionType::Inlet,
564 : NodeInputManager::CompFluidStream::Primary,
565 : DataLoopNode::ObjectIsParent);
566 :
567 22 : thisMSHP.AirOutletNodeNum = GetOnlySingleNode(state,
568 11 : Alphas(4),
569 : ErrorsFound,
570 : DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed,
571 11 : Alphas(1),
572 : DataLoopNode::NodeFluidType::Air,
573 : DataLoopNode::ConnectionType::Outlet,
574 : NodeInputManager::CompFluidStream::Primary,
575 : DataLoopNode::ObjectIsParent);
576 :
577 11 : BranchNodeConnections::TestCompSet(state, state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
578 :
579 : // Get the Controlling Zone or Location of the engine driven heat pump Thermostat
580 11 : thisMSHP.ControlZoneNum = Util::FindItemInList(Alphas(5), state.dataHeatBal->Zone);
581 11 : thisMSHP.ControlZoneName = Alphas(5);
582 11 : if (thisMSHP.ControlZoneNum == 0) {
583 0 : ShowSevereError(state,
584 0 : format("{}, \"{}\" {} not found: {}",
585 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
586 0 : thisMSHP.Name,
587 : cAlphaFields(5),
588 0 : thisMSHP.ControlZoneName));
589 0 : ErrorsFound = true;
590 : }
591 :
592 : // Get the node number for the zone with the thermostat
593 11 : if (thisMSHP.ControlZoneNum > 0) {
594 11 : AirNodeFound = false;
595 11 : AirLoopFound = false;
596 11 : int ControlledZoneNum = thisMSHP.ControlZoneNum;
597 : // Find the controlled zone number for the specified thermostat location
598 11 : thisMSHP.NodeNumOfControlledZone = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).ZoneNode;
599 : // Determine if furnace is on air loop served by the thermostat location specified
600 11 : for (int zoneInNode = 1; zoneInNode <= state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).NumInletNodes; ++zoneInNode) {
601 11 : int AirLoopNumber = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNodeAirLoopNum(zoneInNode);
602 11 : if (AirLoopNumber > 0) {
603 11 : for (int BranchNum = 1; BranchNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).NumBranches; ++BranchNum) {
604 17 : for (int CompNum = 1;
605 17 : CompNum <= state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).TotalComponents;
606 : ++CompNum) {
607 17 : if (!Util::SameString(state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).Name,
608 28 : thisMSHP.Name) ||
609 22 : !Util::SameString(
610 11 : state.dataAirSystemsData->PrimaryAirSystems(AirLoopNumber).Branch(BranchNum).Comp(CompNum).TypeOf,
611 11 : state.dataHVACMultiSpdHP->CurrentModuleObject)) {
612 6 : continue;
613 : }
614 11 : AirLoopFound = true;
615 11 : thisMSHP.AirLoopNumber = AirLoopNumber;
616 11 : break;
617 : }
618 11 : thisMSHP.ZoneInletNode = state.dataZoneEquip->ZoneEquipConfig(ControlledZoneNum).InletNode(zoneInNode);
619 11 : if (AirLoopFound) {
620 11 : break;
621 : }
622 : }
623 22 : for (int TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumTempControlledZones; ++TstatZoneNum) {
624 11 : if (state.dataZoneCtrls->TempControlledZone(TstatZoneNum).ActualZoneNum != thisMSHP.ControlZoneNum) {
625 0 : continue;
626 : }
627 11 : AirNodeFound = true;
628 : }
629 11 : for (int TstatZoneNum = 1; TstatZoneNum <= state.dataZoneCtrls->NumComfortControlledZones; ++TstatZoneNum) {
630 0 : if (state.dataZoneCtrls->ComfortControlledZone(TstatZoneNum).ActualZoneNum != thisMSHP.ControlZoneNum) {
631 0 : continue;
632 : }
633 0 : AirNodeFound = true;
634 : }
635 14 : for (int TstatZoneNum = 1; TstatZoneNum <= state.dataZoneTempPredictorCorrector->NumStageCtrZone; ++TstatZoneNum) {
636 3 : if (state.dataZoneCtrls->StageControlledZone(TstatZoneNum).ActualZoneNum != thisMSHP.ControlZoneNum) {
637 2 : continue;
638 : }
639 1 : AirNodeFound = true;
640 : }
641 : }
642 11 : if (AirLoopFound) {
643 11 : break;
644 : }
645 : }
646 11 : if (!AirNodeFound) {
647 0 : ShowSevereError(state,
648 0 : format("Did not find Air Node ({}), {} = \"\"{}",
649 : cAlphaFields(5),
650 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
651 0 : thisMSHP.Name));
652 0 : ShowContinueError(state, format("Specified {} = {}", cAlphaFields(5), Alphas(5)));
653 0 : ErrorsFound = true;
654 : }
655 11 : if (!AirLoopFound) {
656 0 : ShowSevereError(
657 0 : state, format("Did not find correct AirLoopHVAC for {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
658 0 : ShowContinueError(state, format("The {} = {} is not served by this Primary Air Loop equipment.", cAlphaFields(5), Alphas(5)));
659 0 : ErrorsFound = true;
660 : }
661 : }
662 :
663 : // Get supply fan data
664 11 : thisMSHP.FanNum = Fans::GetFanIndex(state, Alphas(7));
665 11 : if (thisMSHP.FanNum == 0) {
666 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(7), Alphas(7));
667 0 : ErrorsFound = true;
668 : } else {
669 11 : auto *fan = state.dataFans->fans(thisMSHP.FanNum);
670 11 : thisMSHP.FanName = fan->Name;
671 11 : thisMSHP.fanType = fan->type;
672 11 : thisMSHP.FanInletNode = fan->inletNodeNum;
673 11 : thisMSHP.FanOutletNode = fan->outletNodeNum;
674 33 : BranchNodeConnections::SetUpCompSets(state,
675 11 : state.dataHVACMultiSpdHP->CurrentModuleObject,
676 : thisMSHP.Name,
677 11 : HVAC::fanTypeNames[(int)thisMSHP.fanType],
678 : thisMSHP.FanName,
679 : "UNDEFINED",
680 : "UNDEFINED");
681 : }
682 :
683 : // Get supply fan placement data
684 11 : thisMSHP.fanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(8)));
685 11 : assert(thisMSHP.fanPlace != HVAC::FanPlace::Invalid);
686 :
687 11 : if ((thisMSHP.fanOpModeSched = Sched::GetSchedule(state, Alphas(9))) == nullptr) {
688 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(9), Alphas(9));
689 0 : ErrorsFound = true;
690 : }
691 :
692 11 : if (thisMSHP.fanOpModeSched != nullptr && thisMSHP.fanType == HVAC::FanType::Constant) {
693 0 : if (!thisMSHP.fanOpModeSched->checkMinMaxVals(state, Clusive::Ex, 0.0, Clusive::In, 1.0)) {
694 0 : Sched::ShowSevereBadMinMax(state,
695 : eoh,
696 0 : cAlphaFields(9),
697 0 : Alphas(9),
698 : Clusive::Ex,
699 : 0.0,
700 : Clusive::In,
701 : 1.0,
702 : "Fan mode must be continuous (schedule values > 0) for Fan:ConstantVolume.");
703 0 : ErrorsFound = true;
704 : }
705 : }
706 :
707 11 : if (Util::SameString(Alphas(10), "Coil:Heating:DX:MultiSpeed")) {
708 9 : thisMSHP.HeatCoilType = MultiSpeedHeatingCoil;
709 9 : thisMSHP.HeatCoilNum = state.dataInputProcessing->inputProcessor->getObjectItemNum(state, "Coil:Heating:DX:MultiSpeed", Alphas(11));
710 9 : thisMSHP.DXHeatCoilName = Alphas(11);
711 9 : if (thisMSHP.HeatCoilNum <= 0) {
712 0 : ShowSevereError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
713 0 : ShowContinueError(state, format("{} \"{}\" not found.", cAlphaFields(11), Alphas(11)));
714 0 : ShowContinueError(state, format("{} must be Coil:Heating:DX:MultiSpeed ", cAlphaFields(10)));
715 0 : ShowFatalError(state,
716 0 : format("{}Errors found in getting {} input. Preceding condition(s) causes termination.",
717 : RoutineName,
718 0 : state.dataHVACMultiSpdHP->CurrentModuleObject));
719 0 : ErrorsFound = true;
720 : }
721 9 : LocalError = false;
722 9 : DXCoils::GetDXCoilIndex(state, thisMSHP.DXHeatCoilName, thisMSHP.DXHeatCoilIndex, LocalError, "Coil:Heating:DX:MultiSpeed");
723 9 : if (LocalError) {
724 0 : ShowSevereError(state, format("The index of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
725 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
726 0 : ErrorsFound = true;
727 0 : LocalError = false;
728 : }
729 9 : HeatingCoilInletNode = DXCoils::GetCoilInletNode(state, Alphas(10), Alphas(11), LocalError);
730 9 : if (LocalError) {
731 0 : ShowSevereError(state, format("The inlet node number of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
732 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
733 0 : ErrorsFound = true;
734 0 : LocalError = false;
735 : }
736 9 : HeatingCoilOutletNode = DXCoils::GetCoilOutletNode(state, Alphas(10), Alphas(11), LocalError);
737 9 : if (LocalError) {
738 0 : ShowSevereError(state, format("The outlet node number of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
739 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
740 0 : ErrorsFound = true;
741 0 : LocalError = false;
742 : }
743 9 : thisMSHP.MinOATCompressorHeating = DXCoils::GetMinOATCompressor(state, thisMSHP.DXHeatCoilIndex, LocalError);
744 9 : if (LocalError) {
745 0 : ShowContinueError(state,
746 0 : format("...for heating coil. Occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
747 0 : LocalError = false;
748 : }
749 18 : BranchNodeConnections::SetUpCompSets(state,
750 9 : state.dataHVACMultiSpdHP->CurrentModuleObject,
751 : thisMSHP.Name,
752 : "Coil:Heating:DX:MultiSpeed",
753 : thisMSHP.DXHeatCoilName,
754 : "UNDEFINED",
755 : "UNDEFINED");
756 3 : } else if (Util::SameString(Alphas(10), "Coil:Heating:Electric:MultiStage") ||
757 3 : Util::SameString(Alphas(10), "Coil:Heating:Gas:MultiStage")) {
758 :
759 2 : if (Util::SameString(Alphas(10), "Coil:Heating:Electric:MultiStage")) {
760 1 : thisMSHP.HeatCoilType = HVAC::Coil_HeatingElectric_MultiStage;
761 1 : thisMSHP.HeatCoilNum =
762 1 : state.dataInputProcessing->inputProcessor->getObjectItemNum(state, "Coil:Heating:Electric:MultiStage", Alphas(11));
763 1 : if (thisMSHP.HeatCoilNum <= 0) {
764 0 : ShowSevereError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
765 0 : ShowContinueError(state, format("{} \"{}\" not found.", cAlphaFields(11), Alphas(11)));
766 0 : ShowContinueError(state, format("{} must be Coil:Heating:Electric:MultiStage ", cAlphaFields(10)));
767 0 : ShowFatalError(state,
768 0 : format("{}Errors found in getting {} input. Preceding condition(s) causes termination.",
769 : RoutineName,
770 0 : state.dataHVACMultiSpdHP->CurrentModuleObject));
771 0 : ErrorsFound = true;
772 : }
773 : } else {
774 1 : thisMSHP.HeatCoilType = HVAC::Coil_HeatingGas_MultiStage;
775 1 : thisMSHP.HeatCoilNum =
776 1 : state.dataInputProcessing->inputProcessor->getObjectItemNum(state, "Coil:Heating:Gas:MultiStage", Alphas(11));
777 1 : if (thisMSHP.HeatCoilNum <= 0) {
778 0 : ShowSevereError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
779 0 : ShowContinueError(state, format("{} \"{}\" not found.", cAlphaFields(11), Alphas(11)));
780 0 : ShowContinueError(state, format("{} must be Coil:Heating:Gas:MultiStage ", cAlphaFields(10)));
781 0 : ShowFatalError(state,
782 0 : format("{}Errors found in getting {} input. Preceding condition(s) causes termination.",
783 : RoutineName,
784 0 : state.dataHVACMultiSpdHP->CurrentModuleObject));
785 0 : ErrorsFound = true;
786 : }
787 : }
788 2 : thisMSHP.HeatCoilName = Alphas(11);
789 2 : LocalError = false;
790 2 : if (Util::SameString(Alphas(10), "Coil:Heating:Electric:MultiStage")) {
791 1 : HeatingCoils::GetCoilIndex(state, thisMSHP.HeatCoilName, thisMSHP.HeatCoilIndex, LocalError);
792 : } else {
793 1 : HeatingCoils::GetCoilIndex(state, thisMSHP.HeatCoilName, thisMSHP.HeatCoilIndex, LocalError);
794 : }
795 2 : if (LocalError) {
796 0 : ShowSevereError(state, format("The index of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
797 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
798 0 : ErrorsFound = true;
799 0 : LocalError = false;
800 : }
801 2 : HeatingCoilInletNode = HeatingCoils::GetCoilInletNode(state, Alphas(10), Alphas(11), LocalError);
802 2 : if (LocalError) {
803 0 : ShowSevereError(state, format("The inlet node number of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
804 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
805 0 : ErrorsFound = true;
806 0 : LocalError = false;
807 : }
808 2 : HeatingCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, Alphas(10), Alphas(11), LocalError);
809 2 : if (LocalError) {
810 0 : ShowSevereError(state, format("The outlet node number of {} is not found \"{}\"", cAlphaFields(11), Alphas(11)));
811 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
812 0 : ErrorsFound = true;
813 0 : LocalError = false;
814 : }
815 2 : if (Util::SameString(Alphas(10), "Coil:Heating:Electric:MultiStage")) {
816 2 : BranchNodeConnections::SetUpCompSets(state,
817 1 : state.dataHVACMultiSpdHP->CurrentModuleObject,
818 : thisMSHP.Name,
819 : "Coil:Heating:Electric:MultiStage",
820 : thisMSHP.HeatCoilName,
821 : "UNDEFINED",
822 : "UNDEFINED");
823 : } else {
824 2 : BranchNodeConnections::SetUpCompSets(state,
825 1 : state.dataHVACMultiSpdHP->CurrentModuleObject,
826 : thisMSHP.Name,
827 : "Coil:Heating:Gas:MultiStage",
828 : thisMSHP.HeatCoilName,
829 : "UNDEFINED",
830 : "UNDEFINED");
831 : }
832 0 : } else if (Util::SameString(Alphas(10), "Coil:Heating:Water")) {
833 0 : thisMSHP.HeatCoilType = HVAC::Coil_HeatingWater;
834 0 : ValidateComponent(state, Alphas(10), Alphas(11), IsNotOK, state.dataHVACMultiSpdHP->CurrentModuleObject);
835 0 : if (IsNotOK) {
836 0 : ShowContinueError(state, format("...occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
837 0 : ErrorsFound = true;
838 : } else { // mine data from heating coil object
839 :
840 0 : thisMSHP.HeatCoilName = Alphas(11);
841 : // Get the Heating Coil water Inlet or control Node number
842 0 : errFlag = false;
843 0 : thisMSHP.CoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", thisMSHP.HeatCoilName, errFlag);
844 0 : if (errFlag) {
845 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
846 0 : ErrorsFound = true;
847 : }
848 :
849 : // Get the ReHeat Coil hot water max volume flow rate
850 0 : errFlag = false;
851 0 : thisMSHP.MaxCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisMSHP.HeatCoilName, errFlag);
852 0 : if (errFlag) {
853 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
854 0 : ErrorsFound = true;
855 : }
856 :
857 : // Get the supplemental Heating Coil Inlet Node
858 0 : errFlag = false;
859 0 : HeatingCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", thisMSHP.HeatCoilName, errFlag);
860 0 : thisMSHP.CoilAirInletNode = HeatingCoilInletNode;
861 0 : if (errFlag) {
862 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
863 0 : ErrorsFound = true;
864 : }
865 :
866 : // Get the supplemental Heating Coil Outlet Node
867 0 : errFlag = false;
868 0 : HeatingCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", thisMSHP.HeatCoilName, errFlag);
869 0 : if (errFlag) {
870 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
871 0 : ErrorsFound = true;
872 : }
873 0 : BranchNodeConnections::SetUpCompSets(state,
874 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
875 : thisMSHP.Name,
876 : "Coil:Heating:Water",
877 : thisMSHP.HeatCoilName,
878 0 : state.dataLoopNodes->NodeID(HeatingCoilInletNode),
879 0 : state.dataLoopNodes->NodeID(HeatingCoilOutletNode));
880 : }
881 0 : } else if (Util::SameString(Alphas(10), "Coil:Heating:Steam")) {
882 0 : thisMSHP.HeatCoilType = HVAC::Coil_HeatingSteam;
883 0 : ValidateComponent(state, Alphas(10), Alphas(11), IsNotOK, state.dataHVACMultiSpdHP->CurrentModuleObject);
884 0 : if (IsNotOK) {
885 0 : ShowContinueError(state, format("...occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
886 0 : ErrorsFound = true;
887 : } else { // mine data from heating coil object
888 :
889 0 : thisMSHP.HeatCoilName = Alphas(11);
890 0 : errFlag = false;
891 0 : thisMSHP.HeatCoilNum = SteamCoils::GetSteamCoilIndex(state, Alphas(10), thisMSHP.HeatCoilName, errFlag);
892 0 : if (thisMSHP.HeatCoilNum == 0) {
893 0 : ShowSevereError(
894 : state,
895 0 : format("{} illegal {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, cAlphaFields(10), thisMSHP.HeatCoilName));
896 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
897 0 : ErrorsFound = true;
898 : }
899 :
900 : // Get the supplemental Heating Coil steam inlet node number
901 0 : errFlag = false;
902 0 : thisMSHP.CoilControlNode = SteamCoils::GetCoilAirOutletNode(state, "Coil:Heating:Steam", thisMSHP.HeatCoilName, errFlag);
903 0 : if (errFlag) {
904 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
905 0 : ErrorsFound = true;
906 : }
907 :
908 : // Get the supplemental Heating Coil steam max volume flow rate
909 0 : thisMSHP.MaxCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisMSHP.HeatCoilNum, errFlag);
910 0 : if (thisMSHP.MaxCoilFluidFlow > 0.0) {
911 0 : SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, routineName);
912 0 : thisMSHP.MaxCoilFluidFlow *= SteamDensity;
913 : }
914 :
915 : // Get the supplemental Heating Coil Inlet Node
916 0 : errFlag = false;
917 0 : HeatingCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisMSHP.HeatCoilNum, thisMSHP.HeatCoilName, errFlag);
918 0 : thisMSHP.CoilAirInletNode = HeatingCoilInletNode;
919 0 : if (errFlag) {
920 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
921 0 : ErrorsFound = true;
922 : }
923 :
924 : // Get the supplemental Heating Coil Outlet Node
925 0 : errFlag = false;
926 0 : HeatingCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisMSHP.HeatCoilNum, thisMSHP.HeatCoilName, errFlag);
927 0 : if (errFlag) {
928 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
929 0 : ErrorsFound = true;
930 : }
931 :
932 0 : BranchNodeConnections::SetUpCompSets(state,
933 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
934 : thisMSHP.Name,
935 : "Coil:Heating:Steam",
936 : thisMSHP.HeatCoilName,
937 0 : state.dataLoopNodes->NodeID(HeatingCoilInletNode),
938 0 : state.dataLoopNodes->NodeID(HeatingCoilOutletNode));
939 : }
940 : } else {
941 0 : ShowSevereError(state,
942 0 : format("The allowed {} are Coil:Heating:DX:MultiSpeed, Coil:Heating:Electric:MultiStage, and "
943 : "Coil:Heating:Gas:MultiStage in {} \"{}\"",
944 : cAlphaFields(10),
945 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
946 : Alphas(1)));
947 0 : ShowContinueError(state, format("The entered {} = \"{}\".", cAlphaFields(10), Alphas(10)));
948 0 : ErrorsFound = true;
949 : }
950 :
951 : // thisMSHP.MinOATCompressor = Numbers(1); // deprecated, now uses coil MinOAT inputs
952 :
953 11 : if (Util::SameString(Alphas(12), "Coil:Cooling:DX:MultiSpeed")) {
954 11 : thisMSHP.CoolCoilType = MultiSpeedCoolingCoil;
955 11 : thisMSHP.DXCoolCoilName = Alphas(13);
956 11 : if (state.dataInputProcessing->inputProcessor->getObjectItemNum(state, "Coil:Cooling:DX:MultiSpeed", Alphas(13)) <= 0) {
957 0 : ShowSevereError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
958 0 : ShowContinueError(state, format("{} \"{}\" not found.", cAlphaFields(13), Alphas(13)));
959 0 : ShowContinueError(state, format("{} must be Coil:Cooling:DX:MultiSpeed ", cAlphaFields(12)));
960 0 : ShowFatalError(state,
961 0 : format("{}Errors found in getting {} input. Preceding condition(s) causes termination.",
962 : RoutineName,
963 0 : state.dataHVACMultiSpdHP->CurrentModuleObject));
964 0 : ErrorsFound = true;
965 : }
966 11 : LocalError = false;
967 11 : DXCoils::GetDXCoilIndex(state, thisMSHP.DXCoolCoilName, thisMSHP.DXCoolCoilIndex, LocalError, "Coil:Cooling:DX:MultiSpeed");
968 11 : if (LocalError) {
969 0 : ShowSevereError(state, format("The index of {} is not found \"{}\"", cAlphaFields(13), Alphas(13)));
970 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
971 0 : ErrorsFound = true;
972 0 : LocalError = false;
973 : }
974 11 : CoolingCoilInletNode = DXCoils::GetCoilInletNode(state, Alphas(12), Alphas(13), LocalError);
975 11 : if (LocalError) {
976 0 : ShowSevereError(state, format("The inlet node number of {} is not found \"{}\"", cAlphaFields(13), Alphas(13)));
977 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
978 0 : ErrorsFound = true;
979 0 : LocalError = false;
980 : }
981 11 : CoolingCoilOutletNode = DXCoils::GetCoilOutletNode(state, Alphas(12), Alphas(13), LocalError);
982 11 : if (LocalError) {
983 0 : ShowSevereError(state, format("The outlet node number of {} is not found \"{}\"", cAlphaFields(13), Alphas(13)));
984 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
985 0 : ErrorsFound = true;
986 0 : LocalError = false;
987 : }
988 11 : thisMSHP.MinOATCompressorCooling = DXCoils::GetMinOATCompressor(state, thisMSHP.DXCoolCoilIndex, LocalError);
989 11 : if (LocalError) {
990 0 : ShowContinueError(state,
991 0 : format("...for cooling coil. Occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
992 0 : LocalError = false;
993 : }
994 : } else {
995 0 : ShowSevereError(state,
996 0 : format("The allowed {} is Coil:Cooling:DX:MultiSpeed in {} \"{}\"",
997 : cAlphaFields(12),
998 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
999 : Alphas(1)));
1000 0 : ShowContinueError(state, format("The entered {} = \"{}\".", cAlphaFields(12), Alphas(12)));
1001 0 : ErrorsFound = true;
1002 : }
1003 22 : BranchNodeConnections::SetUpCompSets(state,
1004 11 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1005 : thisMSHP.Name,
1006 : "Coil:Cooling:DX:MultiSpeed",
1007 : thisMSHP.DXCoolCoilName,
1008 : "UNDEFINED",
1009 : "UNDEFINED");
1010 :
1011 : // Get supplemental heating coil data
1012 11 : thisMSHP.SuppHeatCoilName = Alphas(15);
1013 11 : if (Util::SameString(Alphas(14), "Coil:Heating:Fuel")) {
1014 11 : thisMSHP.SuppHeatCoilType = SuppHeatingCoilGas;
1015 11 : errFlag = false;
1016 22 : thisMSHP.SuppHeatCoilNum = HeatingCoils::GetHeatingCoilIndex(state, "Coil:Heating:Fuel", Alphas(15), errFlag);
1017 11 : if (thisMSHP.SuppHeatCoilNum <= 0 || errFlag) {
1018 0 : ShowContinueError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
1019 0 : ShowContinueError(state, format("{} of type Coil:Heating:Fuel \"{}\" not found.", cAlphaFields(15), Alphas(15)));
1020 0 : ErrorsFound = true;
1021 : }
1022 :
1023 : // Get the Supplemental Heating Coil Node Numbers
1024 11 : LocalError = false;
1025 11 : SuppHeatCoilInletNode = HeatingCoils::GetCoilInletNode(state, Alphas(14), Alphas(15), LocalError);
1026 11 : if (LocalError) {
1027 0 : ShowSevereError(state, format("The inlet node number of {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
1028 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
1029 0 : ErrorsFound = true;
1030 0 : LocalError = false;
1031 : }
1032 11 : SuppHeatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, Alphas(14), Alphas(15), LocalError);
1033 11 : if (LocalError) {
1034 0 : ShowSevereError(state, format("The outlet node number of {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
1035 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
1036 0 : ErrorsFound = true;
1037 0 : LocalError = false;
1038 : }
1039 :
1040 : // Get supplemental heating coil capacity to see if it is autosize
1041 11 : thisMSHP.DesignSuppHeatingCapacity = HeatingCoils::GetCoilCapacity(state, Alphas(14), Alphas(15), LocalError);
1042 11 : if (LocalError) {
1043 0 : ShowSevereError(state, format("The capacity {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
1044 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
1045 0 : ErrorsFound = true;
1046 0 : LocalError = false;
1047 : }
1048 22 : BranchNodeConnections::SetUpCompSets(state,
1049 11 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1050 : thisMSHP.Name,
1051 : "Coil:Heating:Fuel",
1052 : thisMSHP.SuppHeatCoilName,
1053 : "UNDEFINED",
1054 : "UNDEFINED");
1055 : }
1056 11 : if (Util::SameString(Alphas(14), "Coil:Heating:Electric")) {
1057 0 : thisMSHP.SuppHeatCoilType = SuppHeatingCoilElec;
1058 0 : errFlag = false;
1059 0 : thisMSHP.SuppHeatCoilNum = HeatingCoils::GetHeatingCoilIndex(state, "Coil:Heating:Electric", Alphas(15), errFlag);
1060 0 : if (thisMSHP.SuppHeatCoilNum <= 0 || errFlag) {
1061 0 : ShowContinueError(state, format("Configuration error in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
1062 0 : ShowContinueError(state, format("{} of type Coil:Heating:Electric \"{}\" not found.", cAlphaFields(15), Alphas(15)));
1063 0 : ErrorsFound = true;
1064 : }
1065 :
1066 : // Get the Supplemental Heating Coil Node Numbers
1067 0 : LocalError = false;
1068 0 : SuppHeatCoilInletNode = HeatingCoils::GetCoilInletNode(state, Alphas(14), Alphas(15), LocalError);
1069 0 : if (LocalError) {
1070 0 : ShowSevereError(state, format("The inlet node number of {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
1071 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
1072 0 : ErrorsFound = true;
1073 0 : LocalError = false;
1074 : }
1075 0 : SuppHeatCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, Alphas(14), Alphas(15), LocalError);
1076 0 : if (LocalError) {
1077 0 : ShowSevereError(state, format("The outlet node number of {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
1078 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
1079 0 : ErrorsFound = true;
1080 0 : LocalError = false;
1081 : }
1082 :
1083 : // Get supplemental heating coil capacity to see if it is autosize
1084 0 : thisMSHP.DesignSuppHeatingCapacity = HeatingCoils::GetCoilCapacity(state, Alphas(14), Alphas(15), LocalError);
1085 0 : if (LocalError) {
1086 0 : ShowSevereError(state, format("The capacity {} is not found \"{}\"", cAlphaFields(15), Alphas(15)));
1087 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
1088 0 : ErrorsFound = true;
1089 0 : LocalError = false;
1090 : }
1091 :
1092 0 : BranchNodeConnections::SetUpCompSets(state,
1093 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1094 : thisMSHP.Name,
1095 : "Coil:Heating:Electric",
1096 : thisMSHP.SuppHeatCoilName,
1097 : "UNDEFINED",
1098 : "UNDEFINED");
1099 : }
1100 :
1101 11 : if (Util::SameString(Alphas(14), "Coil:Heating:Water")) {
1102 0 : thisMSHP.SuppHeatCoilType = HVAC::Coil_HeatingWater;
1103 0 : ValidateComponent(state, Alphas(14), thisMSHP.SuppHeatCoilName, IsNotOK, state.dataHVACMultiSpdHP->CurrentModuleObject);
1104 0 : if (IsNotOK) {
1105 0 : ShowContinueError(state, format("...occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1)));
1106 0 : ErrorsFound = true;
1107 : } else { // mine data from heating coil object
1108 :
1109 : // Get the Heating Coil water Inlet or control Node number
1110 0 : errFlag = false;
1111 0 : thisMSHP.SuppCoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", thisMSHP.SuppHeatCoilName, errFlag);
1112 0 : if (errFlag) {
1113 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1114 0 : ErrorsFound = true;
1115 : }
1116 :
1117 : // Get the ReHeat Coil hot water max volume flow rate
1118 0 : errFlag = false;
1119 0 : thisMSHP.MaxSuppCoilFluidFlow =
1120 0 : WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", thisMSHP.SuppHeatCoilName, errFlag);
1121 0 : if (errFlag) {
1122 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1123 0 : ErrorsFound = true;
1124 : }
1125 :
1126 : // Get the Supplemental Heating Coil Inlet Node
1127 0 : errFlag = false;
1128 0 : SuppHeatCoilInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", thisMSHP.SuppHeatCoilName, errFlag);
1129 0 : thisMSHP.SuppCoilAirInletNode = SuppHeatCoilInletNode;
1130 0 : if (errFlag) {
1131 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1132 0 : ErrorsFound = true;
1133 : }
1134 :
1135 : // Get the Supplemental Heating Coil Outlet Node
1136 0 : errFlag = false;
1137 0 : SuppHeatCoilOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", thisMSHP.SuppHeatCoilName, errFlag);
1138 0 : thisMSHP.SuppCoilAirOutletNode = SuppHeatCoilOutletNode;
1139 0 : if (errFlag) {
1140 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1141 0 : ErrorsFound = true;
1142 : }
1143 0 : BranchNodeConnections::SetUpCompSets(state,
1144 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1145 : thisMSHP.Name,
1146 : "Coil:Heating:Water",
1147 : thisMSHP.SuppHeatCoilName,
1148 0 : state.dataLoopNodes->NodeID(SuppHeatCoilInletNode),
1149 0 : state.dataLoopNodes->NodeID(SuppHeatCoilOutletNode));
1150 : }
1151 : }
1152 11 : if (Util::SameString(Alphas(14), "Coil:Heating:Steam")) {
1153 0 : thisMSHP.SuppHeatCoilType = HVAC::Coil_HeatingSteam;
1154 0 : ValidateComponent(state, Alphas(14), thisMSHP.SuppHeatCoilName, IsNotOK, state.dataHVACMultiSpdHP->CurrentModuleObject);
1155 0 : if (IsNotOK) {
1156 0 : ShowContinueError(state, format("...occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1157 0 : ErrorsFound = true;
1158 : } else { // mine data from heating coil object
1159 :
1160 0 : errFlag = false;
1161 0 : thisMSHP.SuppHeatCoilNum = SteamCoils::GetSteamCoilIndex(state, Alphas(14), thisMSHP.SuppHeatCoilName, errFlag);
1162 0 : if (thisMSHP.SuppHeatCoilNum == 0) {
1163 0 : ShowSevereError(
1164 : state,
1165 0 : format("{} illegal {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, cAlphaFields(14), thisMSHP.SuppHeatCoilName));
1166 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1167 0 : ErrorsFound = true;
1168 : }
1169 :
1170 : // Get the Supplemental Heating Coil steam inlet node number
1171 0 : errFlag = false;
1172 0 : thisMSHP.SuppCoilControlNode = SteamCoils::GetCoilAirOutletNode(state, "Coil:Heating:Steam", thisMSHP.SuppHeatCoilName, errFlag);
1173 0 : if (errFlag) {
1174 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1175 0 : ErrorsFound = true;
1176 : }
1177 :
1178 : // Get the Supplemental Heating Coil steam max volume flow rate
1179 0 : thisMSHP.MaxSuppCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, thisMSHP.SuppHeatCoilNum, errFlag);
1180 0 : if (thisMSHP.MaxSuppCoilFluidFlow > 0.0) {
1181 0 : SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, routineName);
1182 0 : thisMSHP.MaxSuppCoilFluidFlow *= SteamDensity;
1183 : }
1184 :
1185 : // Get the Supplemental Heating Coil Inlet Node
1186 0 : errFlag = false;
1187 0 : SuppHeatCoilInletNode = SteamCoils::GetCoilAirInletNode(state, thisMSHP.SuppHeatCoilNum, thisMSHP.SuppHeatCoilName, errFlag);
1188 0 : thisMSHP.SuppCoilAirInletNode = SuppHeatCoilInletNode;
1189 0 : if (errFlag) {
1190 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1191 0 : ErrorsFound = true;
1192 : }
1193 :
1194 : // Get the Supplemental Heating Coil Outlet Node
1195 0 : errFlag = false;
1196 0 : SuppHeatCoilOutletNode = SteamCoils::GetCoilAirOutletNode(state, thisMSHP.SuppHeatCoilNum, thisMSHP.SuppHeatCoilName, errFlag);
1197 0 : thisMSHP.SuppCoilAirOutletNode = SuppHeatCoilOutletNode;
1198 0 : if (errFlag) {
1199 0 : ShowContinueError(state, format("Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1200 0 : ErrorsFound = true;
1201 : }
1202 :
1203 0 : BranchNodeConnections::SetUpCompSets(state,
1204 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1205 : thisMSHP.Name,
1206 : "Coil:Heating:Steam",
1207 : thisMSHP.SuppHeatCoilName,
1208 0 : state.dataLoopNodes->NodeID(SuppHeatCoilInletNode),
1209 0 : state.dataLoopNodes->NodeID(SuppHeatCoilOutletNode));
1210 : }
1211 : }
1212 :
1213 11 : if (thisMSHP.SuppHeatCoilType == 0) {
1214 0 : ShowSevereError(state,
1215 0 : format("{}, \"{}\", {} is not allowed = {}",
1216 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1217 0 : thisMSHP.Name,
1218 : cAlphaFields(14),
1219 : Alphas(14)));
1220 0 : ShowContinueError(state, "Valid choices are Coil:Heating:Fuel,Coil:Heating:Electric,Coil:Heating:Steam,or Coil:Heating:Water");
1221 0 : ErrorsFound = true;
1222 : }
1223 :
1224 11 : thisMSHP.SuppMaxAirTemp = Numbers(2);
1225 11 : thisMSHP.SuppMaxOATemp = Numbers(3);
1226 11 : if (thisMSHP.SuppMaxOATemp > 21.0) {
1227 0 : ShowSevereError(
1228 : state,
1229 0 : format("{}, \"{}\", {} is greater than 21.0", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cNumericFields(3)));
1230 0 : ShowContinueError(state, format("The input value is {:.2R}", Numbers(3)));
1231 0 : ErrorsFound = true;
1232 : }
1233 22 : OutputReportPredefined::PreDefTableEntry(
1234 11 : state, state.dataOutRptPredefined->pdchDXHeatCoilSuppHiT, thisMSHP.DXHeatCoilName, thisMSHP.SuppMaxOATemp);
1235 :
1236 11 : thisMSHP.AuxOnCyclePower = Numbers(4);
1237 11 : thisMSHP.AuxOffCyclePower = Numbers(5);
1238 11 : if (thisMSHP.AuxOnCyclePower < 0.0) {
1239 0 : ShowSevereError(state,
1240 0 : format("{}, \"{}\", A negative value for {} is not allowed ",
1241 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1242 0 : thisMSHP.Name,
1243 : cNumericFields(4)));
1244 0 : ErrorsFound = true;
1245 : }
1246 11 : if (thisMSHP.AuxOffCyclePower < 0.0) {
1247 0 : ShowSevereError(state,
1248 0 : format("{}, \"{}\", A negative value for {} is not allowed ",
1249 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1250 0 : thisMSHP.Name,
1251 : cNumericFields(5)));
1252 0 : ErrorsFound = true;
1253 : }
1254 :
1255 : // Heat recovery
1256 11 : thisMSHP.DesignHeatRecFlowRate = Numbers(6);
1257 11 : if (thisMSHP.DesignHeatRecFlowRate > 0.0) {
1258 0 : thisMSHP.HeatRecActive = true;
1259 0 : thisMSHP.DesignHeatRecMassFlowRate = Psychrometrics::RhoH2O(Constant::HWInitConvTemp) * thisMSHP.DesignHeatRecFlowRate;
1260 0 : thisMSHP.HeatRecInletNodeNum = GetOnlySingleNode(state,
1261 0 : Alphas(16),
1262 : ErrorsFound,
1263 : DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed,
1264 0 : Alphas(1),
1265 : DataLoopNode::NodeFluidType::Water,
1266 : DataLoopNode::ConnectionType::Inlet,
1267 : NodeInputManager::CompFluidStream::Tertiary,
1268 : DataLoopNode::ObjectIsNotParent);
1269 0 : if (thisMSHP.HeatRecInletNodeNum == 0) {
1270 0 : ShowSevereError(
1271 0 : state, format("{}, \"{}\", Missing {}.", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cAlphaFields(16)));
1272 0 : ErrorsFound = true;
1273 : }
1274 0 : thisMSHP.HeatRecOutletNodeNum = GetOnlySingleNode(state,
1275 0 : Alphas(17),
1276 : ErrorsFound,
1277 : DataLoopNode::ConnectionObjectType::AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed,
1278 0 : Alphas(1),
1279 : DataLoopNode::NodeFluidType::Water,
1280 : DataLoopNode::ConnectionType::Outlet,
1281 : NodeInputManager::CompFluidStream::Tertiary,
1282 : DataLoopNode::ObjectIsNotParent);
1283 0 : if (thisMSHP.HeatRecOutletNodeNum == 0) {
1284 0 : ShowSevereError(
1285 0 : state, format("{}, \"{}\", Missing {}.", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cAlphaFields(17)));
1286 0 : ErrorsFound = true;
1287 : }
1288 0 : BranchNodeConnections::TestCompSet(
1289 0 : state, state.dataHVACMultiSpdHP->CurrentModuleObject, Alphas(1), Alphas(16), Alphas(17), "MSHP Heat Recovery Nodes");
1290 0 : DXCoils::SetMSHPDXCoilHeatRecoveryFlag(state, thisMSHP.DXCoolCoilIndex);
1291 0 : if (thisMSHP.DXHeatCoilIndex > 0) {
1292 0 : DXCoils::SetMSHPDXCoilHeatRecoveryFlag(state, thisMSHP.DXHeatCoilIndex);
1293 : }
1294 : } else {
1295 11 : thisMSHP.HeatRecActive = false;
1296 11 : thisMSHP.DesignHeatRecMassFlowRate = 0.0;
1297 11 : thisMSHP.HeatRecInletNodeNum = 0;
1298 11 : thisMSHP.HeatRecOutletNodeNum = 0;
1299 11 : if (!lAlphaBlanks(16) || !lAlphaBlanks(17)) {
1300 0 : ShowWarningError(state,
1301 0 : format("Since {} = 0.0, heat recovery is inactive for {} = {}",
1302 : cNumericFields(6),
1303 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1304 : Alphas(1)));
1305 0 : ShowContinueError(state, format("However, {} or {} was specified.", cAlphaFields(16), cAlphaFields(17)));
1306 : }
1307 : }
1308 11 : thisMSHP.MaxHeatRecOutletTemp = Numbers(7);
1309 11 : if (thisMSHP.MaxHeatRecOutletTemp < 0.0) {
1310 0 : ShowSevereError(state,
1311 0 : format("{}, \"{}\", The value for {} is below 0.0",
1312 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1313 0 : thisMSHP.Name,
1314 : cNumericFields(7)));
1315 0 : ErrorsFound = true;
1316 : }
1317 11 : if (thisMSHP.MaxHeatRecOutletTemp > 100.0) {
1318 0 : ShowSevereError(state,
1319 0 : format("{}, \"{}\", The value for {} is above 100.0",
1320 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1321 0 : thisMSHP.Name,
1322 : cNumericFields(7)));
1323 0 : ErrorsFound = true;
1324 : }
1325 :
1326 11 : thisMSHP.IdleVolumeAirRate = Numbers(8);
1327 11 : if (thisMSHP.IdleVolumeAirRate < 0.0 && thisMSHP.IdleVolumeAirRate != DataSizing::AutoSize) {
1328 0 : ShowSevereError(
1329 : state,
1330 0 : format(
1331 0 : "{}, \"{}\", {} cannot be less than zero.", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cNumericFields(8)));
1332 0 : ErrorsFound = true;
1333 : }
1334 :
1335 : // AirFlowControl only valid if fan opmode = FanOp::Continuous
1336 11 : if (thisMSHP.IdleVolumeAirRate == 0.0) {
1337 0 : thisMSHP.AirFlowControl = AirflowControl::UseCompressorOnFlow;
1338 : } else {
1339 11 : thisMSHP.AirFlowControl = AirflowControl::UseCompressorOffFlow;
1340 : }
1341 :
1342 : // Initialize last mode of compressor operation
1343 11 : thisMSHP.LastMode = ModeOfOperation::HeatingMode;
1344 :
1345 11 : thisMSHP.NumOfSpeedHeating = Numbers(9);
1346 11 : if (thisMSHP.NumOfSpeedHeating < 2 || thisMSHP.NumOfSpeedHeating > 4) {
1347 2 : if (thisMSHP.HeatCoilType == MultiSpeedHeatingCoil) {
1348 0 : ShowSevereError(state,
1349 0 : format("{}, The maximum {} is 4, and the minimum number is 2",
1350 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1351 : cNumericFields(9)));
1352 0 : ShowContinueError(state, format("The input value is {:.0R}", Numbers(9)));
1353 0 : ErrorsFound = true;
1354 : }
1355 : }
1356 11 : thisMSHP.NumOfSpeedCooling = Numbers(10);
1357 11 : if (thisMSHP.NumOfSpeedCooling < 2 || thisMSHP.NumOfSpeedCooling > 4) {
1358 0 : ShowSevereError(state,
1359 0 : format("{}, The maximum {} is 4, and the minimum number is 2",
1360 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1361 : cNumericFields(10)));
1362 0 : ShowContinueError(state, format("The input value is {:.0R}", Numbers(10)));
1363 0 : ErrorsFound = true;
1364 : }
1365 :
1366 : // Generate a dynamic array for heating
1367 11 : if (thisMSHP.NumOfSpeedHeating > 0) {
1368 11 : thisMSHP.HeatMassFlowRate.allocate(thisMSHP.NumOfSpeedHeating);
1369 11 : thisMSHP.HeatVolumeFlowRate.allocate(thisMSHP.NumOfSpeedHeating);
1370 11 : thisMSHP.HeatingSpeedRatio.allocate(thisMSHP.NumOfSpeedHeating);
1371 11 : thisMSHP.HeatingSpeedRatio = 1.0;
1372 39 : for (i = 1; i <= thisMSHP.NumOfSpeedHeating; ++i) {
1373 28 : thisMSHP.HeatVolumeFlowRate(i) = Numbers(10 + i);
1374 28 : if (thisMSHP.HeatCoilType == MultiSpeedHeatingCoil) {
1375 26 : if (thisMSHP.HeatVolumeFlowRate(i) <= 0.0 && thisMSHP.HeatVolumeFlowRate(i) != DataSizing::AutoSize) {
1376 0 : ShowSevereError(state,
1377 0 : format("{}, \"{}\", {} must be greater than zero.",
1378 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1379 0 : thisMSHP.Name,
1380 : cNumericFields(10 + i)));
1381 0 : ErrorsFound = true;
1382 : }
1383 : }
1384 : }
1385 : // Ensure flow rate at high speed should be greater or equal to the flow rate at low speed
1386 28 : for (i = 2; i <= thisMSHP.NumOfSpeedHeating; ++i) {
1387 17 : if (thisMSHP.HeatVolumeFlowRate(i) == DataSizing::AutoSize) {
1388 0 : continue;
1389 : }
1390 17 : Found = false;
1391 17 : for (j = i - 1; j >= 1; --j) {
1392 17 : if (thisMSHP.HeatVolumeFlowRate(i) != DataSizing::AutoSize) {
1393 17 : Found = true;
1394 17 : break;
1395 : }
1396 : }
1397 17 : if (Found) {
1398 17 : if (thisMSHP.HeatVolumeFlowRate(i) < thisMSHP.HeatVolumeFlowRate(j)) {
1399 0 : ShowSevereError(
1400 : state,
1401 0 : format("{}, \"{}\", {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cNumericFields(10 + i)));
1402 0 : ShowContinueError(state, format(" cannot be less than {}", cNumericFields(10 + j)));
1403 0 : ErrorsFound = true;
1404 : }
1405 : }
1406 : }
1407 : }
1408 :
1409 11 : if (state.dataGlobal->DoCoilDirectSolutions) {
1410 1 : int MaxNumber = std::max(thisMSHP.NumOfSpeedCooling, thisMSHP.NumOfSpeedHeating);
1411 1 : thisMSHP.FullOutput.allocate(MaxNumber);
1412 1 : DXCoils::DisableLatentDegradation(state, thisMSHP.DXCoolCoilIndex);
1413 : }
1414 : // Generate a dynamic array for cooling
1415 11 : if (thisMSHP.NumOfSpeedCooling > 0) {
1416 11 : thisMSHP.CoolMassFlowRate.allocate(thisMSHP.NumOfSpeedCooling);
1417 11 : thisMSHP.CoolVolumeFlowRate.allocate(thisMSHP.NumOfSpeedCooling);
1418 11 : thisMSHP.CoolingSpeedRatio.allocate(thisMSHP.NumOfSpeedCooling);
1419 11 : thisMSHP.CoolingSpeedRatio = 1.0;
1420 45 : for (i = 1; i <= thisMSHP.NumOfSpeedCooling; ++i) {
1421 34 : thisMSHP.CoolVolumeFlowRate(i) = Numbers(14 + i);
1422 34 : if (thisMSHP.CoolVolumeFlowRate(i) <= 0.0 && thisMSHP.CoolVolumeFlowRate(i) != DataSizing::AutoSize) {
1423 0 : ShowSevereError(state,
1424 0 : format("{}, \"{}\", {} must be greater than zero.",
1425 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
1426 0 : thisMSHP.Name,
1427 : cNumericFields(14 + i)));
1428 0 : ErrorsFound = true;
1429 : }
1430 : }
1431 : // Ensure flow rate at high speed should be greater or equal to the flow rate at low speed
1432 34 : for (i = 2; i <= thisMSHP.NumOfSpeedCooling; ++i) {
1433 23 : if (thisMSHP.CoolVolumeFlowRate(i) == DataSizing::AutoSize) {
1434 0 : continue;
1435 : }
1436 23 : Found = false;
1437 23 : for (j = i - 1; j >= 1; --j) {
1438 23 : if (thisMSHP.CoolVolumeFlowRate(i) != DataSizing::AutoSize) {
1439 23 : Found = true;
1440 23 : break;
1441 : }
1442 : }
1443 23 : if (Found) {
1444 23 : if (thisMSHP.CoolVolumeFlowRate(i) < thisMSHP.CoolVolumeFlowRate(j)) {
1445 0 : ShowSevereError(
1446 : state,
1447 0 : format("{}, \"{}\", {}", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name, cNumericFields(14 + i)));
1448 0 : ShowContinueError(state, format(" cannot be less than {}", cNumericFields(14 + j)));
1449 0 : ErrorsFound = true;
1450 : }
1451 : }
1452 : }
1453 : }
1454 :
1455 : // Check node integrity
1456 11 : if (thisMSHP.fanPlace == HVAC::FanPlace::BlowThru) {
1457 11 : if (thisMSHP.FanInletNode != thisMSHP.AirInletNodeNum) {
1458 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1459 0 : ShowContinueError(
1460 0 : state, format("When a blow through fan is specified, the fan inlet node name must be the same as the {}", cAlphaFields(3)));
1461 0 : ShowContinueError(state, format("...Fan inlet node name = {}", state.dataLoopNodes->NodeID(thisMSHP.FanInletNode)));
1462 0 : ShowContinueError(state, format("...{} = {}", cAlphaFields(3), state.dataLoopNodes->NodeID(thisMSHP.AirInletNodeNum)));
1463 0 : ErrorsFound = true;
1464 : }
1465 11 : if (thisMSHP.FanOutletNode != CoolingCoilInletNode) {
1466 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1467 0 : ShowContinueError(
1468 : state,
1469 : "When a blow through fan is specified, the fan outlet node name must be the same as the cooling coil inlet node name.");
1470 0 : ShowContinueError(state, format("...Fan outlet node name = {}", state.dataLoopNodes->NodeID(thisMSHP.FanOutletNode)));
1471 0 : ShowContinueError(state, format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
1472 0 : ErrorsFound = true;
1473 : }
1474 11 : if (CoolingCoilOutletNode != HeatingCoilInletNode) {
1475 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1476 0 : ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
1477 0 : ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
1478 0 : ShowContinueError(state, format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
1479 0 : ErrorsFound = true;
1480 : }
1481 11 : if (HeatingCoilOutletNode != SuppHeatCoilInletNode) {
1482 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1483 0 : ShowContinueError(state,
1484 : "When a blow through fan is specified, the heating coil outlet node name must be the same as the reheat coil "
1485 : "inlet node name.");
1486 0 : ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
1487 0 : ShowContinueError(state, format("...Reheat coil inlet node name = {}", state.dataLoopNodes->NodeID(SuppHeatCoilInletNode)));
1488 0 : ErrorsFound = true;
1489 : }
1490 11 : if (SuppHeatCoilOutletNode != thisMSHP.AirOutletNodeNum) {
1491 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1492 0 : ShowContinueError(state, format("The supplemental heating coil outlet node name must be the same as the {}", cAlphaFields(4)));
1493 0 : ShowContinueError(
1494 0 : state, format("...Supplemental heating coil outlet node name = {}", state.dataLoopNodes->NodeID(SuppHeatCoilOutletNode)));
1495 0 : ShowContinueError(state, format("...{} = {}", cAlphaFields(4), state.dataLoopNodes->NodeID(thisMSHP.AirOutletNodeNum)));
1496 0 : ErrorsFound = true;
1497 : }
1498 : } else {
1499 0 : if (CoolingCoilInletNode != thisMSHP.AirInletNodeNum) {
1500 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1501 0 : ShowContinueError(
1502 : state,
1503 0 : format("When a draw through fan is specified, the cooling coil inlet node name must be the same as the {}", cAlphaFields(3)));
1504 0 : ShowContinueError(state, format("...Cooling coil inlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilInletNode)));
1505 0 : ShowContinueError(state, format("...{} = {}", cAlphaFields(3), state.dataLoopNodes->NodeID(thisMSHP.AirInletNodeNum)));
1506 0 : ErrorsFound = true;
1507 : }
1508 0 : if (CoolingCoilOutletNode != HeatingCoilInletNode) {
1509 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1510 0 : ShowContinueError(state, "The cooling coil outlet node name must be the same as the heating coil inlet node name.");
1511 0 : ShowContinueError(state, format("...Cooling coil outlet node name = {}", state.dataLoopNodes->NodeID(CoolingCoilOutletNode)));
1512 0 : ShowContinueError(state, format("...Heating coil inlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilInletNode)));
1513 0 : ErrorsFound = true;
1514 : }
1515 0 : if (HeatingCoilOutletNode != thisMSHP.FanInletNode) {
1516 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1517 0 : ShowContinueError(
1518 : state,
1519 : "When a draw through fan is specified, the heating coil outlet node name must be the same as the fan inlet node name.");
1520 0 : ShowContinueError(state, format("...Heating coil outlet node name = {}", state.dataLoopNodes->NodeID(HeatingCoilOutletNode)));
1521 0 : ShowContinueError(state, format("...Fan inlet node name = {}", state.dataLoopNodes->NodeID(thisMSHP.FanInletNode)));
1522 0 : ErrorsFound = true;
1523 : }
1524 0 : if (thisMSHP.FanOutletNode != SuppHeatCoilInletNode) {
1525 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1526 0 : ShowContinueError(
1527 : state, "When a draw through fan is specified, the fan outlet node name must be the same as the reheat coil inlet node name.");
1528 0 : ShowContinueError(state, format("...Fan outlet node name = {}", state.dataLoopNodes->NodeID(thisMSHP.FanOutletNode)));
1529 0 : ShowContinueError(state, format("...Reheat coil inlet node name = {}", state.dataLoopNodes->NodeID(SuppHeatCoilInletNode)));
1530 0 : ErrorsFound = true;
1531 : }
1532 0 : if (SuppHeatCoilOutletNode != thisMSHP.AirOutletNodeNum) {
1533 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1534 0 : ShowContinueError(state, format("The reheat coil outlet node name must be the same as the {}", cAlphaFields(4)));
1535 0 : ShowContinueError(state, format("...Reheat coil outlet node name = {}", state.dataLoopNodes->NodeID(SuppHeatCoilOutletNode)));
1536 0 : ShowContinueError(state, format("...{} = {}", cAlphaFields(4), state.dataLoopNodes->NodeID(thisMSHP.AirOutletNodeNum)));
1537 0 : ErrorsFound = true;
1538 : }
1539 : }
1540 :
1541 : // Ensure the numbers of speeds defined in the parent object are equal to the numbers defined in coil objects
1542 11 : if (thisMSHP.HeatCoilType == MultiSpeedHeatingCoil) {
1543 9 : i = DXCoils::GetDXCoilNumberOfSpeeds(state, Alphas(10), Alphas(11), ErrorsFound);
1544 9 : if (thisMSHP.NumOfSpeedHeating != i) {
1545 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1546 0 : ShowContinueError(
1547 0 : state, format("The {} is not equal to the number defined in {} = {}", cNumericFields(9), cAlphaFields(11), Alphas(11)));
1548 0 : ErrorsFound = true;
1549 : }
1550 2 : } else if (thisMSHP.HeatCoilType == HVAC::Coil_HeatingElectric_MultiStage || thisMSHP.HeatCoilType == HVAC::Coil_HeatingGas_MultiStage) {
1551 2 : i = HeatingCoils::GetHeatingCoilNumberOfStages(state, Alphas(10), Alphas(11), ErrorsFound);
1552 2 : if (thisMSHP.NumOfSpeedHeating != i) {
1553 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1554 0 : ShowContinueError(
1555 0 : state, format("The {} is not equal to the number defined in {} = {}", cNumericFields(9), cAlphaFields(11), Alphas(11)));
1556 0 : ErrorsFound = true;
1557 : }
1558 : }
1559 11 : i = DXCoils::GetDXCoilNumberOfSpeeds(state, Alphas(12), Alphas(13), ErrorsFound);
1560 11 : if (thisMSHP.NumOfSpeedCooling != i) {
1561 0 : ShowSevereError(state, format("For {} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, thisMSHP.Name));
1562 0 : ShowContinueError(state,
1563 0 : format("The {} is not equal to the number defined in {} = {}", cNumericFields(10), cAlphaFields(13), Alphas(13)));
1564 0 : ErrorsFound = true;
1565 : }
1566 : }
1567 :
1568 11 : if (ErrorsFound) {
1569 0 : ShowFatalError(state,
1570 0 : format("{}Errors found in getting {} input. Preceding condition(s) causes termination.",
1571 : RoutineName,
1572 0 : state.dataHVACMultiSpdHP->CurrentModuleObject));
1573 : }
1574 : // End of multispeed heat pump
1575 :
1576 11 : int MSHPNum = 0;
1577 22 : for (auto &thisMSHeatPump : state.dataHVACMultiSpdHP->MSHeatPump) {
1578 11 : auto &thisMSHPReport = state.dataHVACMultiSpdHP->MSHeatPumpReport(++MSHPNum);
1579 : // Setup Report Variables for MSHP Equipment
1580 22 : SetupOutputVariable(state,
1581 : "Unitary System Ancillary Electricity Rate",
1582 : Constant::Units::W,
1583 11 : thisMSHeatPump.AuxElecPower,
1584 : OutputProcessor::TimeStepType::System,
1585 : OutputProcessor::StoreType::Average,
1586 11 : thisMSHeatPump.Name);
1587 22 : SetupOutputVariable(state,
1588 : "Unitary System Cooling Ancillary Electricity Energy",
1589 : Constant::Units::J,
1590 11 : thisMSHPReport.AuxElecCoolConsumption,
1591 : OutputProcessor::TimeStepType::System,
1592 : OutputProcessor::StoreType::Sum,
1593 11 : thisMSHeatPump.Name,
1594 : Constant::eResource::Electricity,
1595 : OutputProcessor::Group::HVAC,
1596 : OutputProcessor::EndUseCat::Cooling);
1597 22 : SetupOutputVariable(state,
1598 : "Unitary System Heating Ancillary Electricity Energy",
1599 : Constant::Units::J,
1600 11 : thisMSHPReport.AuxElecHeatConsumption,
1601 : OutputProcessor::TimeStepType::System,
1602 : OutputProcessor::StoreType::Sum,
1603 11 : thisMSHeatPump.Name,
1604 : Constant::eResource::Electricity,
1605 : OutputProcessor::Group::HVAC,
1606 : OutputProcessor::EndUseCat::Heating);
1607 22 : SetupOutputVariable(state,
1608 : "Unitary System Fan Part Load Ratio",
1609 : Constant::Units::None,
1610 11 : thisMSHeatPump.FanPartLoadRatio,
1611 : OutputProcessor::TimeStepType::System,
1612 : OutputProcessor::StoreType::Average,
1613 11 : thisMSHeatPump.Name);
1614 22 : SetupOutputVariable(state,
1615 : "Unitary System Compressor Part Load Ratio",
1616 : Constant::Units::None,
1617 11 : thisMSHeatPump.CompPartLoadRatio,
1618 : OutputProcessor::TimeStepType::System,
1619 : OutputProcessor::StoreType::Average,
1620 11 : thisMSHeatPump.Name);
1621 22 : SetupOutputVariable(state,
1622 : "Unitary System Electricity Rate",
1623 : Constant::Units::W,
1624 11 : thisMSHeatPump.ElecPower,
1625 : OutputProcessor::TimeStepType::System,
1626 : OutputProcessor::StoreType::Average,
1627 11 : thisMSHeatPump.Name);
1628 22 : SetupOutputVariable(state,
1629 : "Unitary System Electricity Energy",
1630 : Constant::Units::J,
1631 11 : thisMSHPReport.ElecPowerConsumption,
1632 : OutputProcessor::TimeStepType::System,
1633 : OutputProcessor::StoreType::Sum,
1634 11 : thisMSHeatPump.Name);
1635 22 : SetupOutputVariable(state,
1636 : "Unitary System DX Coil Cycling Ratio",
1637 : Constant::Units::None,
1638 11 : thisMSHPReport.CycRatio,
1639 : OutputProcessor::TimeStepType::System,
1640 : OutputProcessor::StoreType::Average,
1641 11 : thisMSHeatPump.Name);
1642 22 : SetupOutputVariable(state,
1643 : "Unitary System DX Coil Speed Ratio",
1644 : Constant::Units::None,
1645 11 : thisMSHPReport.SpeedRatio,
1646 : OutputProcessor::TimeStepType::System,
1647 : OutputProcessor::StoreType::Average,
1648 11 : thisMSHeatPump.Name);
1649 11 : SetupOutputVariable(state,
1650 : "Unitary System DX Coil Speed Level",
1651 : Constant::Units::None,
1652 11 : thisMSHPReport.SpeedNum,
1653 : OutputProcessor::TimeStepType::System,
1654 : OutputProcessor::StoreType::Average,
1655 11 : thisMSHeatPump.Name);
1656 22 : SetupOutputVariable(state,
1657 : "Unitary System Total Cooling Rate",
1658 : Constant::Units::W,
1659 11 : thisMSHeatPump.TotCoolEnergyRate,
1660 : OutputProcessor::TimeStepType::System,
1661 : OutputProcessor::StoreType::Average,
1662 11 : thisMSHeatPump.Name);
1663 22 : SetupOutputVariable(state,
1664 : "Unitary System Total Heating Rate",
1665 : Constant::Units::W,
1666 11 : thisMSHeatPump.TotHeatEnergyRate,
1667 : OutputProcessor::TimeStepType::System,
1668 : OutputProcessor::StoreType::Average,
1669 11 : thisMSHeatPump.Name);
1670 22 : SetupOutputVariable(state,
1671 : "Unitary System Sensible Cooling Rate",
1672 : Constant::Units::W,
1673 11 : thisMSHeatPump.SensCoolEnergyRate,
1674 : OutputProcessor::TimeStepType::System,
1675 : OutputProcessor::StoreType::Average,
1676 11 : thisMSHeatPump.Name);
1677 22 : SetupOutputVariable(state,
1678 : "Unitary System Sensible Heating Rate",
1679 : Constant::Units::W,
1680 11 : thisMSHeatPump.SensHeatEnergyRate,
1681 : OutputProcessor::TimeStepType::System,
1682 : OutputProcessor::StoreType::Average,
1683 11 : thisMSHeatPump.Name);
1684 22 : SetupOutputVariable(state,
1685 : "Unitary System Latent Cooling Rate",
1686 : Constant::Units::W,
1687 11 : thisMSHeatPump.LatCoolEnergyRate,
1688 : OutputProcessor::TimeStepType::System,
1689 : OutputProcessor::StoreType::Average,
1690 11 : thisMSHeatPump.Name);
1691 22 : SetupOutputVariable(state,
1692 : "Unitary System Latent Heating Rate",
1693 : Constant::Units::W,
1694 11 : thisMSHeatPump.LatHeatEnergyRate,
1695 : OutputProcessor::TimeStepType::System,
1696 : OutputProcessor::StoreType::Average,
1697 11 : thisMSHeatPump.Name);
1698 11 : if (thisMSHeatPump.HeatRecActive) {
1699 0 : SetupOutputVariable(state,
1700 : "Unitary System Heat Recovery Rate",
1701 : Constant::Units::W,
1702 0 : thisMSHeatPump.HeatRecoveryRate,
1703 : OutputProcessor::TimeStepType::System,
1704 : OutputProcessor::StoreType::Average,
1705 0 : thisMSHeatPump.Name);
1706 0 : SetupOutputVariable(state,
1707 : "Unitary System Heat Recovery Inlet Temperature",
1708 : Constant::Units::C,
1709 0 : thisMSHeatPump.HeatRecoveryInletTemp,
1710 : OutputProcessor::TimeStepType::System,
1711 : OutputProcessor::StoreType::Average,
1712 0 : thisMSHeatPump.Name);
1713 0 : SetupOutputVariable(state,
1714 : "Unitary System Heat Recovery Outlet Temperature",
1715 : Constant::Units::C,
1716 0 : thisMSHeatPump.HeatRecoveryOutletTemp,
1717 : OutputProcessor::TimeStepType::System,
1718 : OutputProcessor::StoreType::Average,
1719 0 : thisMSHeatPump.Name);
1720 0 : SetupOutputVariable(state,
1721 : "Unitary System Heat Recovery Fluid Mass Flow Rate",
1722 : Constant::Units::kg_s,
1723 0 : thisMSHeatPump.HeatRecoveryMassFlowRate,
1724 : OutputProcessor::TimeStepType::System,
1725 : OutputProcessor::StoreType::Average,
1726 0 : thisMSHeatPump.Name);
1727 0 : SetupOutputVariable(state,
1728 : "Unitary System Heat Recovery Energy",
1729 : Constant::Units::J,
1730 0 : thisMSHPReport.HeatRecoveryEnergy,
1731 : OutputProcessor::TimeStepType::System,
1732 : OutputProcessor::StoreType::Sum,
1733 0 : thisMSHeatPump.Name);
1734 : }
1735 : }
1736 11 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
1737 4 : for (auto &thisCoil : state.dataHVACMultiSpdHP->MSHeatPump) {
1738 2 : SetupEMSActuator(state,
1739 : "Coil Speed Control",
1740 : thisCoil.Name,
1741 : "Unitary System DX Coil Speed Value",
1742 : "[]",
1743 2 : thisCoil.EMSOverrideCoilSpeedNumOn,
1744 2 : thisCoil.EMSOverrideCoilSpeedNumValue);
1745 : }
1746 : }
1747 11 : }
1748 :
1749 : //******************************************************************************
1750 :
1751 226090 : void InitMSHeatPump(EnergyPlusData &state,
1752 : int const MSHeatPumpNum, // Engine driven heat pump number
1753 : bool const FirstHVACIteration, // TRUE if first HVAC iteration
1754 : int const AirLoopNum, // air loop index
1755 : Real64 &QZnReq, // Heating/Cooling load for all served zones
1756 : Real64 &OnOffAirFlowRatio // Ratio of compressor ON airflow to average airflow over timestep
1757 : )
1758 : {
1759 :
1760 : // SUBROUTINE INFORMATION:
1761 : // AUTHOR: Lixing Gu, FSEC
1762 : // DATE WRITTEN: July 2007
1763 : // MODIFIED Bereket Nigusse, June 2010 - added a procedure to calculate supply air flow fraction
1764 : // through controlled zone
1765 :
1766 : // PURPOSE OF THIS SUBROUTINE:
1767 : // This subroutine is for initializations of the multispeed heat pump (MSHP) components.
1768 :
1769 : // METHODOLOGY EMPLOYED:
1770 : // Uses the status flags to trigger initializations. The MSHP system is simulated with no load (coils off) to
1771 : // determine the outlet temperature. A setpoint temperature is calculated on FirstHVACIteration = TRUE.
1772 : // Once the setpoint is calculated, the inlet mass flow rate on FirstHVACIteration = FALSE is used to
1773 : // determine the bypass fraction. The simulation converges quickly on mass flow rate. If the zone
1774 : // temperatures float in the deadband, additional iterations are required to converge on mass flow rate.
1775 :
1776 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1777 : static constexpr std::string_view RoutineName("InitMSHeatPump");
1778 : Real64 RhoAir; // Air density at InNode
1779 :
1780 : Real64 QSensUnitOut; // Output of MSHP system with coils off
1781 : Real64 PartLoadFrac; // Part-load ratio
1782 : int ZoneNum;
1783 : int i; // Index to speed
1784 : Real64 DeltaMassRate; // Difference of mass flow rate between inlet node and system outlet node
1785 :
1786 226090 : int NumAirLoopZones(0); // number of zone inlet nodes in an air loop
1787 226090 : Real64 SumOfMassFlowRateMax(0.0); // the sum of mass flow rates at inlet to zones in an airloop
1788 226090 : Real64 CntrlZoneTerminalUnitMassFlowRateMax(0.0); // Maximum mass flow rate through controlled zone terminal unit
1789 : Real64 rho; // local fluid density
1790 : Real64 MdotHR; // local temporary for heat recovery fluid mass flow rate (kg/s)
1791 : Real64 ZoneLoadToCoolSPSequenced;
1792 : Real64 ZoneLoadToHeatSPSequenced;
1793 :
1794 226090 : bool ErrorsFound(false); // flag returned from mining call
1795 226090 : Real64 mdot(0.0); // local temporary for mass flow rate (kg/s)
1796 226090 : Real64 SteamDensity(0.0); // density of steam at 100C, used for steam heating coils
1797 226090 : Real64 CoilMaxVolFlowRate(0.0); // coil fluid maximum volume flow rate
1798 226090 : Real64 QActual(0.0); // coil actual capacity
1799 :
1800 226090 : auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump;
1801 :
1802 226090 : int InNode = MSHeatPump(MSHeatPumpNum).AirInletNodeNum;
1803 226090 : int OutNode = MSHeatPump(MSHeatPumpNum).AirOutletNodeNum;
1804 226090 : int NumOfSpeedCooling = MSHeatPump(MSHeatPumpNum).NumOfSpeedCooling;
1805 226090 : int NumOfSpeedHeating = MSHeatPump(MSHeatPumpNum).NumOfSpeedHeating;
1806 :
1807 226090 : ++state.dataHVACMultiSpdHP->AirLoopPass;
1808 226090 : if (state.dataHVACMultiSpdHP->AirLoopPass > 2) {
1809 113034 : state.dataHVACMultiSpdHP->AirLoopPass = 1;
1810 : }
1811 :
1812 226090 : if (MSHeatPump(MSHeatPumpNum).MyPlantScantFlag && allocated(state.dataPlnt->PlantLoop)) {
1813 : bool errFlag;
1814 11 : if (MSHeatPump(MSHeatPumpNum).HeatRecActive) {
1815 0 : errFlag = false;
1816 0 : PlantUtilities::ScanPlantLoopsForObject(state,
1817 0 : MSHeatPump(MSHeatPumpNum).Name,
1818 : DataPlant::PlantEquipmentType::MultiSpeedHeatPumpRecovery,
1819 0 : MSHeatPump(MSHeatPumpNum).HRPlantLoc,
1820 : errFlag,
1821 : _,
1822 : _,
1823 : _,
1824 : _,
1825 : _);
1826 0 : if (errFlag) {
1827 0 : ShowFatalError(state, "InitMSHeatPump: Program terminated for previous conditions.");
1828 : }
1829 :
1830 0 : MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
1831 : } else {
1832 11 : MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
1833 : }
1834 11 : if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingWater) {
1835 0 : errFlag = false;
1836 0 : PlantUtilities::ScanPlantLoopsForObject(state,
1837 0 : MSHeatPump(MSHeatPumpNum).HeatCoilName,
1838 : DataPlant::PlantEquipmentType::CoilWaterSimpleHeating,
1839 0 : MSHeatPump(MSHeatPumpNum).plantLoc,
1840 : errFlag,
1841 : _,
1842 : _,
1843 : _,
1844 : _,
1845 : _);
1846 0 : if (errFlag) {
1847 0 : ShowFatalError(state, "InitMSHeatPump: Program terminated for previous conditions.");
1848 : }
1849 0 : MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow =
1850 0 : WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).HeatCoilName, ErrorsFound);
1851 :
1852 0 : if (MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow > 0.0) {
1853 0 : rho = state.dataPlnt->PlantLoop(MSHeatPump(MSHeatPumpNum).plantLoc.loopNum)
1854 0 : .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
1855 0 : MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow =
1856 0 : WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).HeatCoilName, ErrorsFound) * rho;
1857 : }
1858 : // fill outlet node for coil
1859 0 : MSHeatPump(MSHeatPumpNum).CoilOutletNode =
1860 0 : DataPlant::CompData::getPlantComponent(state, MSHeatPump(MSHeatPumpNum).plantLoc).NodeNumOut;
1861 0 : MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
1862 :
1863 11 : } else if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingSteam) {
1864 0 : errFlag = false;
1865 0 : PlantUtilities::ScanPlantLoopsForObject(state,
1866 0 : MSHeatPump(MSHeatPumpNum).HeatCoilName,
1867 : DataPlant::PlantEquipmentType::CoilSteamAirHeating,
1868 0 : MSHeatPump(MSHeatPumpNum).plantLoc,
1869 : errFlag,
1870 : _,
1871 : _,
1872 : _,
1873 : _,
1874 : _);
1875 0 : if (errFlag) {
1876 0 : ShowFatalError(state, "InitMSHeatPump: Program terminated for previous conditions.");
1877 : }
1878 0 : MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow =
1879 0 : SteamCoils::GetCoilMaxSteamFlowRate(state, MSHeatPump(MSHeatPumpNum).HeatCoilNum, ErrorsFound);
1880 0 : if (MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow > 0.0) {
1881 0 : SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, RoutineName);
1882 0 : MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow *= SteamDensity;
1883 : }
1884 :
1885 : // fill outlet node for coil
1886 0 : MSHeatPump(MSHeatPumpNum).CoilOutletNode =
1887 0 : DataPlant::CompData::getPlantComponent(state, MSHeatPump(MSHeatPumpNum).plantLoc).NodeNumOut;
1888 0 : MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
1889 : }
1890 11 : if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingWater) {
1891 0 : errFlag = false;
1892 0 : PlantUtilities::ScanPlantLoopsForObject(state,
1893 0 : MSHeatPump(MSHeatPumpNum).SuppHeatCoilName,
1894 : DataPlant::PlantEquipmentType::CoilWaterSimpleHeating,
1895 0 : MSHeatPump(MSHeatPumpNum).SuppPlantLoc,
1896 : errFlag,
1897 : _,
1898 : _,
1899 : _,
1900 : _,
1901 : _);
1902 0 : if (errFlag) {
1903 0 : ShowFatalError(state, "InitMSHeatPump: Program terminated for previous conditions.");
1904 : }
1905 0 : MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow =
1906 0 : WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, ErrorsFound);
1907 :
1908 0 : if (MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow > 0.0) {
1909 0 : rho = state.dataPlnt->PlantLoop(MSHeatPump(MSHeatPumpNum).SuppPlantLoc.loopNum)
1910 0 : .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
1911 0 : MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow =
1912 0 : WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, ErrorsFound) *
1913 : rho;
1914 : }
1915 : // fill outlet node for coil
1916 0 : MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode =
1917 0 : DataPlant::CompData::getPlantComponent(state, MSHeatPump(MSHeatPumpNum).SuppPlantLoc).NodeNumOut;
1918 0 : MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
1919 :
1920 11 : } else if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingSteam) {
1921 0 : errFlag = false;
1922 0 : PlantUtilities::ScanPlantLoopsForObject(state,
1923 0 : MSHeatPump(MSHeatPumpNum).SuppHeatCoilName,
1924 : DataPlant::PlantEquipmentType::CoilSteamAirHeating,
1925 0 : MSHeatPump(MSHeatPumpNum).SuppPlantLoc,
1926 : errFlag,
1927 : _,
1928 : _,
1929 : _,
1930 : _,
1931 : _);
1932 0 : if (errFlag) {
1933 0 : ShowFatalError(state, "InitMSHeatPump: Program terminated for previous conditions.");
1934 : }
1935 0 : MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow =
1936 0 : SteamCoils::GetCoilMaxSteamFlowRate(state, MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum, ErrorsFound);
1937 0 : if (MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow > 0.0) {
1938 0 : SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, RoutineName);
1939 0 : MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow *= SteamDensity;
1940 : }
1941 :
1942 : // fill outlet node for coil
1943 0 : MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode =
1944 0 : DataPlant::CompData::getPlantComponent(state, MSHeatPump(MSHeatPumpNum).SuppPlantLoc).NodeNumOut;
1945 0 : MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
1946 : }
1947 226079 : } else if (MSHeatPump(MSHeatPumpNum).MyPlantScantFlag && !state.dataGlobal->AnyPlantInModel) {
1948 0 : MSHeatPump(MSHeatPumpNum).MyPlantScantFlag = false;
1949 : }
1950 :
1951 226090 : if (!state.dataGlobal->SysSizingCalc && MSHeatPump(MSHeatPumpNum).MySizeFlag) {
1952 11 : MSHeatPump(MSHeatPumpNum).FanVolFlow = state.dataFans->fans(MSHeatPump(MSHeatPumpNum).FanNum)->maxAirFlowRate;
1953 11 : SizeMSHeatPump(state, MSHeatPumpNum);
1954 11 : MSHeatPump(MSHeatPumpNum).FlowFraction = 1.0;
1955 11 : MSHeatPump(MSHeatPumpNum).MySizeFlag = false;
1956 : // Pass the fan cycling schedule index up to the air loop. Set the air loop unitary system flag.
1957 11 : state.dataAirLoop->AirLoopControlInfo(AirLoopNum).cycFanSched = MSHeatPump(MSHeatPumpNum).fanOpModeSched;
1958 11 : state.dataAirLoop->AirLoopControlInfo(AirLoopNum).UnitarySys = true;
1959 11 : state.dataAirLoop->AirLoopControlInfo(AirLoopNum).UnitarySysSimulating =
1960 : false; // affects child coil sizing by allowing coil to size itself instead of parent telling coil what size to use
1961 11 : state.dataAirLoop->AirLoopControlInfo(AirLoopNum).fanOp = MSHeatPump(MSHeatPumpNum).fanOp;
1962 : }
1963 :
1964 226090 : if (allocated(state.dataZoneEquip->ZoneEquipConfig) && MSHeatPump(MSHeatPumpNum).MyCheckFlag) {
1965 11 : int zoneNum = MSHeatPump(MSHeatPumpNum).ControlZoneNum;
1966 11 : int zoneInlet = MSHeatPump(MSHeatPumpNum).ZoneInletNode;
1967 : // setup furnace zone equipment sequence information based on finding matching air terminal
1968 11 : if (state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex > 0) {
1969 11 : int coolingPriority = 0;
1970 11 : int heatingPriority = 0;
1971 11 : state.dataZoneEquip->ZoneEquipList(state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex)
1972 11 : .getPrioritiesForInletNode(state, zoneInlet, coolingPriority, heatingPriority);
1973 11 : MSHeatPump(MSHeatPumpNum).ZoneSequenceCoolingNum = coolingPriority;
1974 11 : MSHeatPump(MSHeatPumpNum).ZoneSequenceHeatingNum = heatingPriority;
1975 : }
1976 11 : MSHeatPump(MSHeatPumpNum).MyCheckFlag = false;
1977 11 : if (MSHeatPump(MSHeatPumpNum).ZoneSequenceCoolingNum == 0 || MSHeatPump(MSHeatPumpNum).ZoneSequenceHeatingNum == 0) {
1978 0 : ShowSevereError(state,
1979 0 : format("AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed, \"{}\": Airloop air terminal in the zone equipment list for "
1980 : "zone = {} not found or is not allowed Zone Equipment Cooling or Heating Sequence = 0.",
1981 0 : MSHeatPump(MSHeatPumpNum).Name,
1982 0 : MSHeatPump(MSHeatPumpNum).ControlZoneName));
1983 0 : ShowFatalError(state,
1984 : "Subroutine InitMSHeatPump: Errors found in getting AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed input. Preceding "
1985 : "condition(s) causes termination.");
1986 : }
1987 : }
1988 :
1989 : // Find the number of zones (zone Inlet Nodes) attached to an air loop from the air loop number
1990 226090 : NumAirLoopZones =
1991 226090 : state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesCooled + state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesHeated;
1992 226090 : if (allocated(state.dataAirLoop->AirToZoneNodeInfo) && MSHeatPump(MSHeatPumpNum).MyFlowFracFlag) {
1993 11 : state.dataHVACMultiSpdHP->FlowFracFlagReady = true;
1994 34 : for (int ZoneInSysIndex = 1; ZoneInSysIndex <= NumAirLoopZones; ++ZoneInSysIndex) {
1995 : // zone inlet nodes for cooling
1996 23 : if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesCooled > 0) {
1997 23 : if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitCoolInletNodes(ZoneInSysIndex) == -999) {
1998 : // the data structure for the zones inlet nodes has not been filled
1999 0 : state.dataHVACMultiSpdHP->FlowFracFlagReady = false;
2000 : }
2001 : }
2002 : // zone inlet nodes for heating
2003 23 : if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).NumZonesHeated > 0) {
2004 0 : if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitHeatInletNodes(ZoneInSysIndex) == -999) {
2005 : // the data structure for the zones inlet nodes has not been filled
2006 0 : state.dataHVACMultiSpdHP->FlowFracFlagReady = false;
2007 : }
2008 : }
2009 : }
2010 : }
2011 226090 : if (allocated(state.dataAirLoop->AirToZoneNodeInfo) && state.dataHVACMultiSpdHP->FlowFracFlagReady) {
2012 226090 : SumOfMassFlowRateMax = 0.0; // initialize the sum of the maximum flows
2013 654944 : for (int ZoneInSysIndex = 1; ZoneInSysIndex <= NumAirLoopZones; ++ZoneInSysIndex) {
2014 428854 : int ZoneInletNodeNum = state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).TermUnitCoolInletNodes(ZoneInSysIndex);
2015 428854 : SumOfMassFlowRateMax += state.dataLoopNodes->Node(ZoneInletNodeNum).MassFlowRateMax;
2016 428854 : if (state.dataAirLoop->AirToZoneNodeInfo(AirLoopNum).CoolCtrlZoneNums(ZoneInSysIndex) == MSHeatPump(MSHeatPumpNum).ControlZoneNum) {
2017 226090 : CntrlZoneTerminalUnitMassFlowRateMax = state.dataLoopNodes->Node(ZoneInletNodeNum).MassFlowRateMax;
2018 : }
2019 : }
2020 226090 : if (SumOfMassFlowRateMax != 0.0 && MSHeatPump(MSHeatPumpNum).MyFlowFracFlag) {
2021 11 : if (CntrlZoneTerminalUnitMassFlowRateMax >= HVAC::SmallAirVolFlow) {
2022 11 : MSHeatPump(MSHeatPumpNum).FlowFraction = CntrlZoneTerminalUnitMassFlowRateMax / SumOfMassFlowRateMax;
2023 : } else {
2024 0 : ShowSevereError(state, format("{} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
2025 0 : ShowContinueError(state, " The Fraction of Supply Air Flow That Goes Through the Controlling Zone is set to 1.");
2026 : }
2027 22 : BaseSizer::reportSizerOutput(state,
2028 11 : state.dataHVACMultiSpdHP->CurrentModuleObject,
2029 11 : MSHeatPump(MSHeatPumpNum).Name,
2030 : "Fraction of Supply Air Flow That Goes Through the Controlling Zone",
2031 11 : MSHeatPump(MSHeatPumpNum).FlowFraction);
2032 11 : MSHeatPump(MSHeatPumpNum).MyFlowFracFlag = false;
2033 : }
2034 : }
2035 :
2036 : // Do the Begin Environment initializations
2037 226090 : if (state.dataGlobal->BeginEnvrnFlag && MSHeatPump(MSHeatPumpNum).MyEnvrnFlag) {
2038 66 : RhoAir = state.dataEnvrn->StdRhoAir;
2039 : // set the mass flow rates from the input volume flow rates
2040 270 : for (i = 1; i <= NumOfSpeedCooling; ++i) {
2041 204 : MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(i) = RhoAir * MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i);
2042 : }
2043 234 : for (i = 1; i <= NumOfSpeedHeating; ++i) {
2044 168 : MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(i) = RhoAir * MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i);
2045 : }
2046 66 : MSHeatPump(MSHeatPumpNum).IdleMassFlowRate = RhoAir * MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate;
2047 : // set the node max and min mass flow rates
2048 66 : state.dataLoopNodes->Node(InNode).MassFlowRateMax =
2049 66 : max(MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(NumOfSpeedCooling), MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(NumOfSpeedHeating));
2050 66 : state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
2051 66 : max(MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(NumOfSpeedCooling), MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(NumOfSpeedHeating));
2052 66 : state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
2053 66 : state.dataLoopNodes->Node(InNode).MassFlowRateMinAvail = 0.0;
2054 66 : state.dataLoopNodes->Node(OutNode) = state.dataLoopNodes->Node(InNode);
2055 66 : MSHeatPump(MSHeatPumpNum).LoadLoss = 0.0;
2056 :
2057 66 : if ((MSHeatPump(MSHeatPumpNum).HeatRecActive) && (!MSHeatPump(MSHeatPumpNum).MyPlantScantFlag)) {
2058 :
2059 0 : rho = state.dataPlnt->PlantLoop(MSHeatPump(MSHeatPumpNum).HRPlantLoc.loopNum)
2060 0 : .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
2061 :
2062 0 : MSHeatPump(MSHeatPumpNum).DesignHeatRecMassFlowRate = MSHeatPump(MSHeatPumpNum).DesignHeatRecFlowRate * rho;
2063 :
2064 0 : PlantUtilities::InitComponentNodes(state,
2065 : 0.0,
2066 0 : MSHeatPump(MSHeatPumpNum).DesignHeatRecMassFlowRate,
2067 0 : MSHeatPump(MSHeatPumpNum).HeatRecInletNodeNum,
2068 0 : MSHeatPump(MSHeatPumpNum).HeatRecOutletNodeNum);
2069 : }
2070 66 : if (MSHeatPump(MSHeatPumpNum).CoilControlNode > 0) {
2071 0 : if (MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow == DataSizing::AutoSize) {
2072 0 : if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingWater) {
2073 0 : WaterCoils::SimulateWaterCoilComponents(
2074 0 : state, MSHeatPump(MSHeatPumpNum).HeatCoilName, FirstHVACIteration, MSHeatPump(MSHeatPumpNum).HeatCoilNum);
2075 :
2076 : CoilMaxVolFlowRate =
2077 0 : WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).HeatCoilName, ErrorsFound);
2078 0 : if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
2079 0 : rho = state.dataPlnt->PlantLoop(MSHeatPump(MSHeatPumpNum).plantLoc.loopNum)
2080 0 : .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
2081 0 : MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow = CoilMaxVolFlowRate * rho;
2082 : }
2083 0 : PlantUtilities::InitComponentNodes(state,
2084 : 0.0,
2085 0 : MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow,
2086 0 : MSHeatPump(MSHeatPumpNum).CoilControlNode,
2087 0 : MSHeatPump(MSHeatPumpNum).CoilOutletNode);
2088 : }
2089 0 : if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingSteam) {
2090 :
2091 0 : SteamCoils::SimulateSteamCoilComponents(state,
2092 0 : MSHeatPump(MSHeatPumpNum).HeatCoilName,
2093 : FirstHVACIteration,
2094 0 : MSHeatPump(MSHeatPumpNum).HeatCoilNum,
2095 0 : 1.0,
2096 : QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
2097 0 : CoilMaxVolFlowRate = SteamCoils::GetCoilMaxSteamFlowRate(state, MSHeatPump(MSHeatPumpNum).HeatCoilNum, ErrorsFound);
2098 :
2099 0 : if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
2100 0 : SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, RoutineName);
2101 0 : MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity;
2102 : }
2103 0 : PlantUtilities::InitComponentNodes(state,
2104 : 0.0,
2105 0 : MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow,
2106 0 : MSHeatPump(MSHeatPumpNum).CoilControlNode,
2107 0 : MSHeatPump(MSHeatPumpNum).CoilOutletNode);
2108 : }
2109 : }
2110 : }
2111 66 : if (MSHeatPump(MSHeatPumpNum).SuppCoilControlNode > 0) {
2112 0 : if (MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow == DataSizing::AutoSize) {
2113 0 : if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingWater) {
2114 0 : WaterCoils::SimulateWaterCoilComponents(
2115 0 : state, MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, FirstHVACIteration, MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum);
2116 :
2117 : CoilMaxVolFlowRate =
2118 0 : WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, ErrorsFound);
2119 0 : if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
2120 0 : rho = state.dataPlnt->PlantLoop(MSHeatPump(MSHeatPumpNum).SuppPlantLoc.loopNum)
2121 0 : .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
2122 0 : MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * rho;
2123 : }
2124 0 : PlantUtilities::InitComponentNodes(state,
2125 : 0.0,
2126 0 : MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow,
2127 0 : MSHeatPump(MSHeatPumpNum).SuppCoilControlNode,
2128 0 : MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode);
2129 : }
2130 0 : if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingSteam) {
2131 :
2132 0 : SteamCoils::SimulateSteamCoilComponents(state,
2133 0 : MSHeatPump(MSHeatPumpNum).SuppHeatCoilName,
2134 : FirstHVACIteration,
2135 0 : MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum,
2136 0 : 1.0,
2137 : QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
2138 0 : CoilMaxVolFlowRate = SteamCoils::GetCoilMaxSteamFlowRate(state, MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum, ErrorsFound);
2139 :
2140 0 : if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
2141 0 : SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, state.dataHVACMultiSpdHP->TempSteamIn, 1.0, RoutineName);
2142 0 : MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow = CoilMaxVolFlowRate * SteamDensity;
2143 : }
2144 0 : PlantUtilities::InitComponentNodes(state,
2145 : 0.0,
2146 0 : MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow,
2147 0 : MSHeatPump(MSHeatPumpNum).SuppCoilControlNode,
2148 0 : MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode);
2149 : }
2150 : }
2151 : }
2152 66 : MSHeatPump(MSHeatPumpNum).MyEnvrnFlag = false;
2153 : } // end one time inits
2154 :
2155 226090 : if (!state.dataGlobal->BeginEnvrnFlag) {
2156 225496 : MSHeatPump(MSHeatPumpNum).MyEnvrnFlag = true;
2157 : }
2158 :
2159 : // IF MSHP system was not autosized and the fan is autosized, check that fan volumetric flow rate is greater than MSHP flow rates
2160 226090 : if (!state.dataGlobal->DoingSizing && MSHeatPump(MSHeatPumpNum).CheckFanFlow) {
2161 11 : state.dataHVACMultiSpdHP->CurrentModuleObject = "AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed";
2162 11 : MSHeatPump(MSHeatPumpNum).FanVolFlow = state.dataFans->fans(MSHeatPump(MSHeatPumpNum).FanNum)->maxAirFlowRate;
2163 11 : if (MSHeatPump(MSHeatPumpNum).FanVolFlow != DataSizing::AutoSize) {
2164 : // Check fan versus system supply air flow rates
2165 11 : if (MSHeatPump(MSHeatPumpNum).FanVolFlow < MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(NumOfSpeedCooling)) {
2166 0 : ShowWarningError(state,
2167 0 : format("{} - air flow rate = {:.7T} in fan object {} is less than the MSHP system air flow rate when cooling is "
2168 : "required ({:.7T}).",
2169 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
2170 0 : MSHeatPump(MSHeatPumpNum).FanVolFlow,
2171 0 : MSHeatPump(MSHeatPumpNum).FanName,
2172 0 : MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(NumOfSpeedCooling)));
2173 0 : ShowContinueError(
2174 : state, " The MSHP system flow rate when cooling is required is reset to the fan flow rate and the simulation continues.");
2175 0 : ShowContinueError(state,
2176 0 : format(" Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
2177 0 : MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(NumOfSpeedCooling) = MSHeatPump(MSHeatPumpNum).FanVolFlow;
2178 : // Check flow rates in other speeds and ensure flow rates are not above the max flow rate
2179 0 : for (i = NumOfSpeedCooling - 1; i >= 1; --i) {
2180 0 : if (MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i) > MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i + 1)) {
2181 0 : ShowContinueError(state,
2182 0 : format(" The MSHP system flow rate when cooling is required is reset to the flow rate at higher speed "
2183 : "and the simulation continues at Speed{}.",
2184 : i));
2185 0 : ShowContinueError(
2186 0 : state, format(" Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
2187 0 : MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i) = MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i + 1);
2188 : }
2189 : }
2190 : }
2191 11 : if (MSHeatPump(MSHeatPumpNum).FanVolFlow < MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(NumOfSpeedHeating)) {
2192 0 : ShowWarningError(state,
2193 0 : format("{} - air flow rate = {:.7T} in fan object {} is less than the MSHP system air flow rate when heating is "
2194 : "required ({:.7T}).",
2195 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
2196 0 : MSHeatPump(MSHeatPumpNum).FanVolFlow,
2197 0 : MSHeatPump(MSHeatPumpNum).FanName,
2198 0 : MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(NumOfSpeedHeating)));
2199 0 : ShowContinueError(
2200 : state, " The MSHP system flow rate when heating is required is reset to the fan flow rate and the simulation continues.");
2201 0 : ShowContinueError(state,
2202 0 : format(" Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
2203 0 : MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(NumOfSpeedHeating) = MSHeatPump(MSHeatPumpNum).FanVolFlow;
2204 0 : for (i = NumOfSpeedHeating - 1; i >= 1; --i) {
2205 0 : if (MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i) > MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i + 1)) {
2206 0 : ShowContinueError(state,
2207 0 : format(" The MSHP system flow rate when heating is required is reset to the flow rate at higher speed "
2208 : "and the simulation continues at Speed{}.",
2209 : i));
2210 0 : ShowContinueError(
2211 : state,
2212 0 : format(" Occurs in {} system = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
2213 0 : MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i) = MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i + 1);
2214 : }
2215 : }
2216 : }
2217 11 : if (MSHeatPump(MSHeatPumpNum).FanVolFlow < MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate &&
2218 0 : MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate != 0.0) {
2219 0 : ShowWarningError(state,
2220 0 : format("{} - air flow rate = {:.7T} in fan object {} is less than the MSHP system air flow rate when no heating "
2221 : "or cooling is needed ({:.7T}).",
2222 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
2223 0 : MSHeatPump(MSHeatPumpNum).FanVolFlow,
2224 0 : MSHeatPump(MSHeatPumpNum).FanName,
2225 0 : MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate));
2226 0 : ShowContinueError(state,
2227 : " The MSHP system flow rate when no heating or cooling is needed is reset to the fan flow rate and the "
2228 : "simulation continues.");
2229 0 : ShowContinueError(state,
2230 0 : format(" Occurs in {} = {}", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump(MSHeatPumpNum).Name));
2231 0 : MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate = MSHeatPump(MSHeatPumpNum).FanVolFlow;
2232 : }
2233 11 : RhoAir = state.dataEnvrn->StdRhoAir;
2234 : // set the mass flow rates from the reset volume flow rates
2235 45 : for (i = 1; i <= NumOfSpeedCooling; ++i) {
2236 34 : MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(i) = RhoAir * MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i);
2237 34 : if (MSHeatPump(MSHeatPumpNum).FanVolFlow > 0.0) {
2238 34 : MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(i) =
2239 34 : MSHeatPump(MSHeatPumpNum).CoolVolumeFlowRate(i) / MSHeatPump(MSHeatPumpNum).FanVolFlow;
2240 : }
2241 : }
2242 39 : for (i = 1; i <= NumOfSpeedHeating; ++i) {
2243 28 : MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(i) = RhoAir * MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i);
2244 28 : if (MSHeatPump(MSHeatPumpNum).FanVolFlow > 0.0) {
2245 28 : MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(i) =
2246 28 : MSHeatPump(MSHeatPumpNum).HeatVolumeFlowRate(i) / MSHeatPump(MSHeatPumpNum).FanVolFlow;
2247 : }
2248 : }
2249 11 : MSHeatPump(MSHeatPumpNum).IdleMassFlowRate = RhoAir * MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate;
2250 11 : if (MSHeatPump(MSHeatPumpNum).FanVolFlow > 0.0) {
2251 11 : MSHeatPump(MSHeatPumpNum).IdleSpeedRatio = MSHeatPump(MSHeatPumpNum).IdleVolumeAirRate / MSHeatPump(MSHeatPumpNum).FanVolFlow;
2252 : }
2253 : // set the node max and min mass flow rates based on reset volume flow rates
2254 11 : state.dataLoopNodes->Node(InNode).MassFlowRateMax =
2255 11 : max(MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(NumOfSpeedCooling), MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(NumOfSpeedHeating));
2256 11 : state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail =
2257 11 : max(MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(NumOfSpeedCooling), MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(NumOfSpeedHeating));
2258 11 : state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
2259 11 : state.dataLoopNodes->Node(InNode).MassFlowRateMinAvail = 0.0;
2260 11 : state.dataLoopNodes->Node(OutNode) = state.dataLoopNodes->Node(InNode);
2261 11 : MSHeatPump(MSHeatPumpNum).CheckFanFlow = false;
2262 : }
2263 : }
2264 :
2265 226090 : if (MSHeatPump(MSHeatPumpNum).fanOpModeSched != nullptr) {
2266 226090 : MSHeatPump(MSHeatPumpNum).fanOp =
2267 226090 : (MSHeatPump(MSHeatPumpNum).fanOpModeSched->getCurrentVal() == 0.0) ? HVAC::FanOp::Cycling : HVAC::FanOp::Continuous;
2268 : }
2269 :
2270 : // Calculate air distribution losses
2271 226090 : if (!FirstHVACIteration && state.dataHVACMultiSpdHP->AirLoopPass == 1) {
2272 51744 : int ZoneInNode = MSHeatPump(MSHeatPumpNum).ZoneInletNode;
2273 51744 : DeltaMassRate = state.dataLoopNodes->Node(OutNode).MassFlowRate -
2274 51744 : state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / MSHeatPump(MSHeatPumpNum).FlowFraction;
2275 51744 : if (DeltaMassRate < 0.0) {
2276 10278 : DeltaMassRate = 0.0;
2277 : }
2278 51744 : Real64 MassFlowRate(0.0); // parent mass flow rate
2279 51744 : Real64 LatentOutput(0.0); // latent output rate
2280 51744 : Real64 TotalOutput(0.0); // total output rate
2281 51744 : Real64 SensibleOutputDelta(0.0); // delta sensible output rate
2282 51744 : Real64 LatentOutputDelta(0.0); // delta latent output rate
2283 51744 : Real64 TotalOutputDelta(0.0); // delta total output rate
2284 51744 : MassFlowRate = state.dataLoopNodes->Node(ZoneInNode).MassFlowRate / MSHeatPump(MSHeatPumpNum).FlowFraction;
2285 51744 : Real64 MinHumRat = state.dataLoopNodes->Node(ZoneInNode).HumRat;
2286 51744 : if (state.dataLoopNodes->Node(OutNode).Temp < state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).NodeNumOfControlledZone).Temp) {
2287 18945 : MinHumRat = state.dataLoopNodes->Node(OutNode).HumRat;
2288 : }
2289 103488 : CalcZoneSensibleLatentOutput(MassFlowRate,
2290 51744 : state.dataLoopNodes->Node(OutNode).Temp,
2291 : MinHumRat,
2292 51744 : state.dataLoopNodes->Node(ZoneInNode).Temp,
2293 : MinHumRat,
2294 51744 : MSHeatPump(MSHeatPumpNum).LoadLoss,
2295 : LatentOutput,
2296 : TotalOutput);
2297 103488 : CalcZoneSensibleLatentOutput(DeltaMassRate,
2298 51744 : state.dataLoopNodes->Node(OutNode).Temp,
2299 : MinHumRat,
2300 51744 : state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).NodeNumOfControlledZone).Temp,
2301 : MinHumRat,
2302 : SensibleOutputDelta,
2303 : LatentOutputDelta,
2304 : TotalOutputDelta);
2305 51744 : MSHeatPump(MSHeatPumpNum).LoadLoss = MSHeatPump(MSHeatPumpNum).LoadLoss + SensibleOutputDelta;
2306 51744 : if (std::abs(MSHeatPump(MSHeatPumpNum).LoadLoss) < 1.0e-6) {
2307 48070 : MSHeatPump(MSHeatPumpNum).LoadLoss = 0.0;
2308 : }
2309 : }
2310 :
2311 : // Returns load only for zones requesting cooling (heating). If in deadband, Qzoneload = 0.
2312 226090 : ZoneNum = MSHeatPump(MSHeatPumpNum).ControlZoneNum;
2313 226090 : if ((MSHeatPump(MSHeatPumpNum).ZoneSequenceCoolingNum > 0) && (MSHeatPump(MSHeatPumpNum).ZoneSequenceHeatingNum > 0)) {
2314 226090 : ZoneLoadToCoolSPSequenced = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(MSHeatPump(MSHeatPumpNum).ControlZoneNum)
2315 226090 : .SequencedOutputRequiredToCoolingSP(MSHeatPump(MSHeatPumpNum).ZoneSequenceCoolingNum);
2316 226090 : ZoneLoadToHeatSPSequenced = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(MSHeatPump(MSHeatPumpNum).ControlZoneNum)
2317 226090 : .SequencedOutputRequiredToHeatingSP(MSHeatPump(MSHeatPumpNum).ZoneSequenceHeatingNum);
2318 226090 : if (ZoneLoadToHeatSPSequenced > HVAC::SmallLoad && ZoneLoadToCoolSPSequenced > HVAC::SmallLoad) {
2319 109560 : QZnReq = ZoneLoadToHeatSPSequenced;
2320 116530 : } else if (ZoneLoadToHeatSPSequenced < (-1.0 * HVAC::SmallLoad) && ZoneLoadToCoolSPSequenced < (-1.0 * HVAC::SmallLoad)) {
2321 87548 : QZnReq = ZoneLoadToCoolSPSequenced;
2322 28982 : } else if (ZoneLoadToHeatSPSequenced <= (-1.0 * HVAC::SmallLoad) && ZoneLoadToCoolSPSequenced >= HVAC::SmallLoad) {
2323 27142 : QZnReq = 0.0;
2324 : } else {
2325 1840 : QZnReq = 0.0; // Autodesk:Init Case added to prevent use of uninitialized value (occurred in MultiSpeedACFurnace example)
2326 : }
2327 226090 : QZnReq /= MSHeatPump(MSHeatPumpNum).FlowFraction;
2328 : } else {
2329 0 : QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired / MSHeatPump(MSHeatPumpNum).FlowFraction;
2330 : }
2331 226090 : if (state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
2332 35744 : QZnReq = 0.0;
2333 : }
2334 :
2335 226090 : if (QZnReq > HVAC::SmallLoad) {
2336 104552 : MSHeatPump(MSHeatPumpNum).HeatCoolMode = ModeOfOperation::HeatingMode;
2337 121538 : } else if (QZnReq < (-1.0 * HVAC::SmallLoad)) {
2338 85792 : MSHeatPump(MSHeatPumpNum).HeatCoolMode = ModeOfOperation::CoolingMode;
2339 : } else {
2340 35746 : MSHeatPump(MSHeatPumpNum).HeatCoolMode = ModeOfOperation::Invalid;
2341 : }
2342 :
2343 : // Determine the staged status
2344 226090 : if (allocated(state.dataZoneCtrls->StageZoneLogic)) {
2345 19424 : if (state.dataZoneCtrls->StageZoneLogic(ZoneNum)) {
2346 19424 : MSHeatPump(MSHeatPumpNum).Staged = true;
2347 19424 : MSHeatPump(MSHeatPumpNum).StageNum = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).StageNum;
2348 : } else {
2349 0 : if (MSHeatPump(MSHeatPumpNum).MyStagedFlag) {
2350 0 : ShowWarningError(state,
2351 : "ZoneControl:Thermostat:StagedDualSetpoint is found, but is not applied to this "
2352 : "AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed object = ");
2353 0 : ShowContinueError(state, format("{}. Please make correction. Simulation continues...", MSHeatPump(MSHeatPumpNum).Name));
2354 0 : MSHeatPump(MSHeatPumpNum).MyStagedFlag = false;
2355 : }
2356 : }
2357 : }
2358 : // Set the inlet node mass flow rate
2359 226090 : if (MSHeatPump(MSHeatPumpNum).fanOp == HVAC::FanOp::Continuous) {
2360 : // constant fan mode
2361 58302 : if (QZnReq > HVAC::SmallLoad && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
2362 29096 : state.dataHVACMultiSpdHP->CompOnMassFlow = MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(1);
2363 29096 : state.dataHVACMultiSpdHP->CompOnFlowRatio = MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(1);
2364 29096 : MSHeatPump(MSHeatPumpNum).LastMode = ModeOfOperation::HeatingMode;
2365 29206 : } else if (QZnReq < (-1.0 * HVAC::SmallLoad) && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
2366 28954 : state.dataHVACMultiSpdHP->CompOnMassFlow = MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(1);
2367 28954 : state.dataHVACMultiSpdHP->CompOnFlowRatio = MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(1);
2368 28954 : MSHeatPump(MSHeatPumpNum).LastMode = ModeOfOperation::CoolingMode;
2369 : } else {
2370 252 : state.dataHVACMultiSpdHP->CompOnMassFlow = MSHeatPump(MSHeatPumpNum).IdleMassFlowRate;
2371 252 : state.dataHVACMultiSpdHP->CompOnFlowRatio = MSHeatPump(MSHeatPumpNum).IdleSpeedRatio;
2372 : }
2373 58302 : state.dataHVACMultiSpdHP->CompOffMassFlow = MSHeatPump(MSHeatPumpNum).IdleMassFlowRate;
2374 58302 : state.dataHVACMultiSpdHP->CompOffFlowRatio = MSHeatPump(MSHeatPumpNum).IdleSpeedRatio;
2375 : } else {
2376 : // cycling fan mode
2377 167788 : if (QZnReq > HVAC::SmallLoad && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
2378 75456 : state.dataHVACMultiSpdHP->CompOnMassFlow = MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(1);
2379 75456 : state.dataHVACMultiSpdHP->CompOnFlowRatio = MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(1);
2380 92332 : } else if (QZnReq < (-1.0 * HVAC::SmallLoad) && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
2381 56838 : state.dataHVACMultiSpdHP->CompOnMassFlow = MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(1);
2382 56838 : state.dataHVACMultiSpdHP->CompOnFlowRatio = MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(1);
2383 : } else {
2384 35494 : state.dataHVACMultiSpdHP->CompOnMassFlow = 0.0;
2385 35494 : state.dataHVACMultiSpdHP->CompOnFlowRatio = 0.0;
2386 : }
2387 167788 : state.dataHVACMultiSpdHP->CompOffMassFlow = 0.0;
2388 167788 : state.dataHVACMultiSpdHP->CompOffFlowRatio = 0.0;
2389 : }
2390 :
2391 : // Set the inlet node mass flow rate
2392 226090 : if (MSHeatPump(MSHeatPumpNum).availSched->getCurrentVal() > 0.0 && state.dataHVACMultiSpdHP->CompOnMassFlow != 0.0) {
2393 172404 : OnOffAirFlowRatio = 1.0;
2394 172404 : if (FirstHVACIteration) {
2395 58313 : state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).AirInletNodeNum).MassFlowRate = state.dataHVACMultiSpdHP->CompOnMassFlow;
2396 58313 : PartLoadFrac = 0.0;
2397 : } else {
2398 114091 : if (MSHeatPump(MSHeatPumpNum).HeatCoolMode != ModeOfOperation::Invalid) {
2399 113965 : PartLoadFrac = 1.0;
2400 : } else {
2401 126 : PartLoadFrac = 0.0;
2402 : }
2403 : }
2404 : } else {
2405 53686 : PartLoadFrac = 0.0;
2406 53686 : state.dataLoopNodes->Node(InNode).MassFlowRate = 0.0;
2407 53686 : state.dataLoopNodes->Node(OutNode).MassFlowRate = 0.0;
2408 53686 : state.dataLoopNodes->Node(OutNode).MassFlowRateMaxAvail = 0.0;
2409 53686 : OnOffAirFlowRatio = 1.0;
2410 : }
2411 :
2412 : // Check availability of DX coils
2413 226090 : if (MSHeatPump(MSHeatPumpNum).availSched->getCurrentVal() > 0.0) {
2414 202378 : if (MSHeatPump(MSHeatPumpNum).HeatCoolMode == ModeOfOperation::CoolingMode) {
2415 135200 : auto *coilAvailSched = DXCoils::GetDXCoilAvailSched( // TODO: Why isn't this stored on the struct?
2416 : state,
2417 : "Coil:Cooling:DX:MultiSpeed",
2418 67600 : MSHeatPump(MSHeatPumpNum).DXCoolCoilName,
2419 : ErrorsFound,
2420 67600 : MSHeatPump(MSHeatPumpNum).DXCoolCoilIndex);
2421 67600 : if (ErrorsFound) {
2422 0 : ShowFatalError(state, "InitMSHeatPump, The previous error causes termination.");
2423 : }
2424 67600 : if (coilAvailSched->getCurrentVal() == 0.0) {
2425 0 : if (MSHeatPump(MSHeatPumpNum).CoolCountAvail == 0) {
2426 0 : ++MSHeatPump(MSHeatPumpNum).CoolCountAvail;
2427 0 : ShowWarningError(
2428 : state,
2429 0 : format("{} is ready to perform cooling, but its DX cooling coil = {} is not available at Available Schedule = {}.",
2430 0 : MSHeatPump(MSHeatPumpNum).Name,
2431 0 : MSHeatPump(MSHeatPumpNum).DXCoolCoilName,
2432 0 : coilAvailSched->Name));
2433 0 : ShowContinueErrorTimeStamp(state, format("Availability schedule returned={:.1R}", coilAvailSched->getCurrentVal()));
2434 : } else {
2435 0 : ++MSHeatPump(MSHeatPumpNum).CoolCountAvail;
2436 0 : ShowRecurringWarningErrorAtEnd(state,
2437 0 : MSHeatPump(MSHeatPumpNum).Name + ": Cooling coil is still not available ...",
2438 0 : MSHeatPump(MSHeatPumpNum).CoolIndexAvail,
2439 0 : coilAvailSched->getCurrentVal(),
2440 0 : coilAvailSched->getCurrentVal());
2441 : }
2442 : }
2443 : }
2444 306930 : if (MSHeatPump(MSHeatPumpNum).HeatCoolMode == ModeOfOperation::HeatingMode &&
2445 104552 : MSHeatPump(MSHeatPumpNum).HeatCoilType == MultiSpeedHeatingCoil) {
2446 160560 : auto *coilAvailSched = DXCoils::GetDXCoilAvailSched(state,
2447 : "Coil:Heating:DX:MultiSpeed",
2448 80280 : MSHeatPump(MSHeatPumpNum).DXHeatCoilName,
2449 : ErrorsFound,
2450 80280 : MSHeatPump(MSHeatPumpNum).DXHeatCoilIndex);
2451 80280 : if (ErrorsFound) {
2452 0 : ShowFatalError(state, "InitMSHeatPump, The previous error causes termination.");
2453 : }
2454 80280 : if (coilAvailSched->getCurrentVal() == 0.0) {
2455 0 : if (MSHeatPump(MSHeatPumpNum).HeatCountAvail == 0) {
2456 0 : ++MSHeatPump(MSHeatPumpNum).HeatCountAvail;
2457 0 : ShowWarningError(
2458 : state,
2459 0 : format("{} is ready to perform heating, but its DX heating coil = {} is not available at Available Schedule = {}.",
2460 0 : MSHeatPump(MSHeatPumpNum).Name,
2461 0 : MSHeatPump(MSHeatPumpNum).DXCoolCoilName,
2462 0 : coilAvailSched->Name));
2463 0 : ShowContinueErrorTimeStamp(state, format("Availability schedule returned={:.1R}", coilAvailSched->getCurrentVal()));
2464 : } else {
2465 0 : ++MSHeatPump(MSHeatPumpNum).HeatCountAvail;
2466 0 : ShowRecurringWarningErrorAtEnd(state,
2467 0 : MSHeatPump(MSHeatPumpNum).Name + ": Heating coil is still not available ...",
2468 0 : MSHeatPump(MSHeatPumpNum).HeatIndexAvail,
2469 0 : coilAvailSched->getCurrentVal(),
2470 0 : coilAvailSched->getCurrentVal());
2471 : }
2472 : }
2473 : }
2474 : }
2475 :
2476 226090 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).CycRatio = 0.0;
2477 226090 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedRatio = 0.0;
2478 226090 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedNum = 0;
2479 :
2480 226090 : CalcMSHeatPump(state,
2481 : MSHeatPumpNum,
2482 : FirstHVACIteration,
2483 : HVAC::CompressorOp::On,
2484 : 1,
2485 : 0.0,
2486 : PartLoadFrac,
2487 : QSensUnitOut,
2488 : QZnReq,
2489 : OnOffAirFlowRatio,
2490 226090 : state.dataHVACMultiSpdHP->SupHeaterLoad);
2491 :
2492 226090 : auto &e = MSHeatPump(MSHeatPumpNum);
2493 : {
2494 226090 : e.TotHeatEnergyRate = 0.0;
2495 226090 : e.SensHeatEnergyRate = 0.0;
2496 226090 : e.LatHeatEnergyRate = 0.0;
2497 226090 : e.TotCoolEnergyRate = 0.0;
2498 226090 : e.SensCoolEnergyRate = 0.0;
2499 226090 : e.LatCoolEnergyRate = 0.0;
2500 : }
2501 : // If unit is scheduled OFF, setpoint is equal to inlet node temperature.
2502 : //!!LKL Discrepancy with < 0
2503 226090 : if (MSHeatPump(MSHeatPumpNum).availSched->getCurrentVal() == 0.0) {
2504 23712 : state.dataLoopNodes->Node(OutNode).Temp = state.dataLoopNodes->Node(InNode).Temp;
2505 23712 : return;
2506 : }
2507 :
2508 374782 : if ((MSHeatPump(MSHeatPumpNum).HeatCoolMode == ModeOfOperation::Invalid && MSHeatPump(MSHeatPumpNum).fanOp == HVAC::FanOp::Cycling) ||
2509 172404 : state.dataHVACMultiSpdHP->CompOnMassFlow == 0.0) {
2510 29974 : QZnReq = 0.0;
2511 29974 : PartLoadFrac = 0.0;
2512 29974 : state.dataLoopNodes->Node(InNode).MassFlowRate = 0.0;
2513 29974 : state.dataLoopNodes->Node(OutNode).MassFlowRateMaxAvail = 0.0;
2514 : }
2515 202378 : MSHeatPump(MSHeatPumpNum).LoadMet = 0.0;
2516 202378 : SetAverageAirFlow(state, MSHeatPumpNum, PartLoadFrac, OnOffAirFlowRatio);
2517 :
2518 : // Init maximum available Heat Recovery flow rate
2519 202378 : if ((MSHeatPump(MSHeatPumpNum).HeatRecActive) && (!MSHeatPump(MSHeatPumpNum).MyPlantScantFlag)) {
2520 0 : if (PartLoadFrac > 0.0) {
2521 0 : if (FirstHVACIteration) {
2522 0 : MdotHR = MSHeatPump(MSHeatPumpNum).DesignHeatRecMassFlowRate;
2523 : } else {
2524 0 : if (MSHeatPump(MSHeatPumpNum).HeatRecoveryMassFlowRate > 0.0) {
2525 0 : MdotHR = MSHeatPump(MSHeatPumpNum).HeatRecoveryMassFlowRate;
2526 : } else {
2527 0 : MdotHR = MSHeatPump(MSHeatPumpNum).DesignHeatRecMassFlowRate;
2528 : }
2529 : }
2530 : } else {
2531 0 : MdotHR = 0.0;
2532 : }
2533 :
2534 0 : PlantUtilities::SetComponentFlowRate(state,
2535 : MdotHR,
2536 0 : MSHeatPump(MSHeatPumpNum).HeatRecInletNodeNum,
2537 0 : MSHeatPump(MSHeatPumpNum).HeatRecOutletNodeNum,
2538 0 : MSHeatPump(MSHeatPumpNum).HRPlantLoc);
2539 : }
2540 :
2541 : // get operating capacity of water and steam coil
2542 202378 : if (FirstHVACIteration) {
2543 68244 : if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingWater) {
2544 : // set air-side and steam-side mass flow rates
2545 0 : state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).CoilAirInletNode).MassFlowRate = state.dataHVACMultiSpdHP->CompOnMassFlow;
2546 0 : mdot = MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow;
2547 0 : PlantUtilities::SetComponentFlowRate(state,
2548 : mdot,
2549 0 : MSHeatPump(MSHeatPumpNum).CoilControlNode,
2550 0 : MSHeatPump(MSHeatPumpNum).CoilOutletNode,
2551 0 : MSHeatPump(MSHeatPumpNum).plantLoc);
2552 : // simulate water coil to find operating capacity
2553 0 : WaterCoils::SimulateWaterCoilComponents(
2554 0 : state, MSHeatPump(MSHeatPumpNum).HeatCoilName, FirstHVACIteration, MSHeatPump(MSHeatPumpNum).HeatCoilNum, QActual);
2555 : } // from IF(MSHeatPump(MSHeatPumpNum)%HeatCoilType == Coil_HeatingWater) THEN
2556 :
2557 68244 : if (MSHeatPump(MSHeatPumpNum).HeatCoilType == HVAC::Coil_HeatingSteam) {
2558 :
2559 : // set air-side and steam-side mass flow rates
2560 0 : state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).CoilAirInletNode).MassFlowRate = state.dataHVACMultiSpdHP->CompOnMassFlow;
2561 0 : mdot = MSHeatPump(MSHeatPumpNum).MaxCoilFluidFlow;
2562 0 : PlantUtilities::SetComponentFlowRate(state,
2563 : mdot,
2564 0 : MSHeatPump(MSHeatPumpNum).CoilControlNode,
2565 0 : MSHeatPump(MSHeatPumpNum).CoilOutletNode,
2566 0 : MSHeatPump(MSHeatPumpNum).plantLoc);
2567 :
2568 : // simulate steam coil to find operating capacity
2569 0 : SteamCoils::SimulateSteamCoilComponents(state,
2570 0 : MSHeatPump(MSHeatPumpNum).HeatCoilName,
2571 : FirstHVACIteration,
2572 0 : MSHeatPump(MSHeatPumpNum).HeatCoilNum,
2573 0 : 1.0,
2574 : QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
2575 :
2576 : } // from IF(MSHeatPump(MSHeatPumpNum)%HeatCoilType == Coil_HeatingSteam) THEN
2577 68244 : if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingWater) {
2578 : // set air-side and steam-side mass flow rates
2579 0 : state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).SuppCoilAirInletNode).MassFlowRate = state.dataHVACMultiSpdHP->CompOnMassFlow;
2580 0 : mdot = MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow;
2581 0 : PlantUtilities::SetComponentFlowRate(state,
2582 : mdot,
2583 0 : MSHeatPump(MSHeatPumpNum).SuppCoilControlNode,
2584 0 : MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode,
2585 0 : MSHeatPump(MSHeatPumpNum).SuppPlantLoc);
2586 : // simulate water coil to find operating capacity
2587 0 : WaterCoils::SimulateWaterCoilComponents(
2588 0 : state, MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, FirstHVACIteration, MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum, QActual);
2589 0 : MSHeatPump(MSHeatPumpNum).DesignSuppHeatingCapacity = QActual;
2590 :
2591 : } // from IF(MSHeatPump(MSHeatPumpNum)%SuppHeatCoilType == Coil_HeatingWater) THEN
2592 :
2593 68244 : if (MSHeatPump(MSHeatPumpNum).SuppHeatCoilType == HVAC::Coil_HeatingSteam) {
2594 :
2595 : // set air-side and steam-side mass flow rates
2596 0 : state.dataLoopNodes->Node(MSHeatPump(MSHeatPumpNum).SuppCoilAirInletNode).MassFlowRate = state.dataHVACMultiSpdHP->CompOnMassFlow;
2597 0 : mdot = MSHeatPump(MSHeatPumpNum).MaxSuppCoilFluidFlow;
2598 0 : PlantUtilities::SetComponentFlowRate(state,
2599 : mdot,
2600 0 : MSHeatPump(MSHeatPumpNum).SuppCoilControlNode,
2601 0 : MSHeatPump(MSHeatPumpNum).SuppCoilOutletNode,
2602 0 : MSHeatPump(MSHeatPumpNum).SuppPlantLoc);
2603 :
2604 : // simulate steam coil to find operating capacity
2605 0 : SteamCoils::SimulateSteamCoilComponents(state,
2606 0 : MSHeatPump(MSHeatPumpNum).SuppHeatCoilName,
2607 : FirstHVACIteration,
2608 0 : MSHeatPump(MSHeatPumpNum).SuppHeatCoilNum,
2609 0 : 1.0,
2610 : QActual); // QCoilReq, simulate any load > 0 to get max capacity of steam coil
2611 0 : MSHeatPump(MSHeatPumpNum).DesignSuppHeatingCapacity =
2612 0 : SteamCoils::GetCoilCapacity(state, "Coil:Heating:Steam", MSHeatPump(MSHeatPumpNum).SuppHeatCoilName, ErrorsFound);
2613 :
2614 : } // from IF(MSHeatPump(MSHeatPumpNum)%SuppHeatCoilType == Coil_HeatingSteam) THEN
2615 : } // from IF( FirstHVACIteration ) THEN
2616 : }
2617 :
2618 : //******************************************************************************
2619 :
2620 11 : void SizeMSHeatPump(EnergyPlusData &state, int const MSHeatPumpNum) // Engine driven heat pump number
2621 : {
2622 : // SUBROUTINE INFORMATION:
2623 : // AUTHOR: Lixing Gu, FSEC
2624 : // DATE WRITTEN: June 2007
2625 :
2626 : // PURPOSE OF THIS SUBROUTINE:
2627 : // This subroutine is for sizing multispeed heat pump airflow rates and flow fraction.
2628 :
2629 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2630 : int NumOfSpeedCooling; // Number of speeds for cooling
2631 : int NumOfSpeedHeating; // Number of speeds for heating
2632 : int i; // Index to speed
2633 :
2634 11 : auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
2635 11 : if (state.dataSize->CurSysNum > 0 && state.dataSize->CurOASysNum == 0) {
2636 11 : state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanNum = MSHeatPump.FanNum;
2637 11 : state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanType = MSHeatPump.fanType;
2638 11 : state.dataAirSystemsData->PrimaryAirSystems(state.dataSize->CurSysNum).supFanPlace = MSHeatPump.fanPlace;
2639 : }
2640 :
2641 11 : NumOfSpeedCooling = MSHeatPump.NumOfSpeedCooling;
2642 11 : NumOfSpeedHeating = MSHeatPump.NumOfSpeedHeating;
2643 :
2644 45 : for (i = NumOfSpeedCooling; i >= 1; --i) {
2645 :
2646 34 : if (MSHeatPump.CoolVolumeFlowRate(i) == DataSizing::AutoSize) {
2647 0 : if (state.dataSize->CurSysNum > 0) {
2648 0 : if (i == NumOfSpeedCooling) {
2649 0 : CheckSysSizing(state, state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name);
2650 0 : MSHeatPump.CoolVolumeFlowRate(i) = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
2651 0 : if (MSHeatPump.FanVolFlow < MSHeatPump.CoolVolumeFlowRate(i) && MSHeatPump.FanVolFlow != DataSizing::AutoSize) {
2652 0 : MSHeatPump.CoolVolumeFlowRate(i) = MSHeatPump.FanVolFlow;
2653 0 : ShowWarningError(state, format("{} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name));
2654 0 : ShowContinueError(state,
2655 : "The supply air flow rate at high speed is less than the autosized value for the supply air flow rate "
2656 : "in cooling mode. Consider autosizing the fan for this simulation.");
2657 0 : ShowContinueError(
2658 : state,
2659 : "The air flow rate at high speed in cooling mode is reset to the supply air flow rate and the simulation continues.");
2660 : }
2661 : } else {
2662 0 : MSHeatPump.CoolVolumeFlowRate(i) = MSHeatPump.CoolVolumeFlowRate(NumOfSpeedCooling) * i / NumOfSpeedCooling;
2663 : }
2664 0 : if (MSHeatPump.CoolVolumeFlowRate(i) < HVAC::SmallAirVolFlow) {
2665 0 : MSHeatPump.CoolVolumeFlowRate = 0.0;
2666 : }
2667 : // Ensure the flow rate at lower speed has to be less or equal to the flow rate at higher speed
2668 0 : if (i != NumOfSpeedCooling) {
2669 0 : if (MSHeatPump.CoolVolumeFlowRate(i) > MSHeatPump.CoolVolumeFlowRate(i + 1)) {
2670 0 : MSHeatPump.CoolVolumeFlowRate(i) = MSHeatPump.CoolVolumeFlowRate(i + 1);
2671 : }
2672 : }
2673 0 : BaseSizer::reportSizerOutput(state,
2674 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
2675 : MSHeatPump.Name,
2676 0 : format("Speed {} Supply Air Flow Rate During Cooling Operation [m3/s]", i),
2677 0 : MSHeatPump.CoolVolumeFlowRate(i));
2678 : }
2679 : }
2680 : }
2681 :
2682 39 : for (i = NumOfSpeedHeating; i >= 1; --i) {
2683 28 : if (MSHeatPump.HeatVolumeFlowRate(i) == DataSizing::AutoSize) {
2684 0 : if (state.dataSize->CurSysNum > 0) {
2685 0 : if (i == NumOfSpeedHeating) {
2686 0 : CheckSysSizing(state, state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name);
2687 0 : MSHeatPump.HeatVolumeFlowRate(i) = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
2688 0 : if (MSHeatPump.FanVolFlow < MSHeatPump.HeatVolumeFlowRate(i) && MSHeatPump.FanVolFlow != DataSizing::AutoSize) {
2689 0 : MSHeatPump.HeatVolumeFlowRate(i) = MSHeatPump.FanVolFlow;
2690 0 : ShowWarningError(state, format("{} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name));
2691 0 : ShowContinueError(state,
2692 : "The supply air flow rate at high speed is less than the autosized value for the maximum air flow rate "
2693 : "in heating mode. Consider autosizing the fan for this simulation.");
2694 0 : ShowContinueError(state,
2695 : "The maximum air flow rate at high speed in heating mode is reset to the supply air flow rate and the "
2696 : "simulation continues.");
2697 : }
2698 : } else {
2699 0 : MSHeatPump.HeatVolumeFlowRate(i) = MSHeatPump.HeatVolumeFlowRate(NumOfSpeedHeating) * i / NumOfSpeedHeating;
2700 : }
2701 0 : if (MSHeatPump.HeatVolumeFlowRate(i) < HVAC::SmallAirVolFlow) {
2702 0 : MSHeatPump.HeatVolumeFlowRate(i) = 0.0;
2703 : }
2704 : // Ensure the flow rate at lower speed has to be less or equal to the flow rate at higher speed
2705 0 : if (i != NumOfSpeedHeating) {
2706 0 : if (MSHeatPump.HeatVolumeFlowRate(i) > MSHeatPump.HeatVolumeFlowRate(i + 1)) {
2707 0 : MSHeatPump.HeatVolumeFlowRate(i) = MSHeatPump.HeatVolumeFlowRate(i + 1);
2708 : }
2709 : }
2710 0 : BaseSizer::reportSizerOutput(state,
2711 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
2712 : MSHeatPump.Name,
2713 0 : format("Speed{}Supply Air Flow Rate During Heating Operation [m3/s]", i),
2714 0 : MSHeatPump.HeatVolumeFlowRate(i));
2715 : }
2716 : }
2717 : }
2718 :
2719 11 : if (MSHeatPump.IdleVolumeAirRate == DataSizing::AutoSize) {
2720 0 : if (state.dataSize->CurSysNum > 0) {
2721 0 : CheckSysSizing(state, state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name);
2722 0 : MSHeatPump.IdleVolumeAirRate = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).DesMainVolFlow;
2723 0 : if (MSHeatPump.FanVolFlow < MSHeatPump.IdleVolumeAirRate && MSHeatPump.FanVolFlow != DataSizing::AutoSize) {
2724 0 : MSHeatPump.IdleVolumeAirRate = MSHeatPump.FanVolFlow;
2725 0 : ShowWarningError(state, format("{} \"{}\"", state.dataHVACMultiSpdHP->CurrentModuleObject, MSHeatPump.Name));
2726 0 : ShowContinueError(state,
2727 : "The supply air flow rate is less than the autosized value for the maximum air flow rate when no heating or "
2728 : "cooling is needed. Consider autosizing the fan for this simulation.");
2729 0 : ShowContinueError(state,
2730 : "The maximum air flow rate when no heating or cooling is needed is reset to the supply air flow rate and the "
2731 : "simulation continues.");
2732 : }
2733 0 : if (MSHeatPump.IdleVolumeAirRate < HVAC::SmallAirVolFlow) {
2734 0 : MSHeatPump.IdleVolumeAirRate = 0.0;
2735 : }
2736 :
2737 0 : BaseSizer::reportSizerOutput(state,
2738 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
2739 : MSHeatPump.Name,
2740 : "Supply Air Flow Rate When No Cooling or Heating is Needed [m3/s]",
2741 : MSHeatPump.IdleVolumeAirRate);
2742 : }
2743 : }
2744 :
2745 11 : if (MSHeatPump.SuppMaxAirTemp == DataSizing::AutoSize) {
2746 0 : if (state.dataSize->CurSysNum > 0) {
2747 0 : if (MSHeatPump.SuppHeatCoilType == 1) { // Gas
2748 0 : CheckZoneSizing(state, "Coil:Heating:Fuel", MSHeatPump.Name);
2749 : } else {
2750 0 : CheckZoneSizing(state, "Coil:Heating:Electric", MSHeatPump.Name);
2751 : }
2752 0 : MSHeatPump.SuppMaxAirTemp = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatSupTemp;
2753 0 : BaseSizer::reportSizerOutput(state,
2754 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
2755 : MSHeatPump.Name,
2756 : "Maximum Supply Air Temperature from Supplemental Heater [C]",
2757 : MSHeatPump.SuppMaxAirTemp);
2758 : }
2759 : }
2760 :
2761 11 : if (MSHeatPump.DesignSuppHeatingCapacity == DataSizing::AutoSize) {
2762 0 : if (state.dataSize->CurSysNum > 0) {
2763 0 : if (MSHeatPump.SuppHeatCoilType == 1) { // Gas
2764 0 : CheckSysSizing(state, "Coil:Heating:Fuel", MSHeatPump.Name);
2765 : } else {
2766 0 : CheckSysSizing(state, "Coil:Heating:Electric", MSHeatPump.Name);
2767 : }
2768 0 : MSHeatPump.DesignSuppHeatingCapacity = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum).HeatCap;
2769 : } else {
2770 0 : MSHeatPump.DesignSuppHeatingCapacity = 0.0;
2771 : }
2772 0 : BaseSizer::reportSizerOutput(state,
2773 0 : state.dataHVACMultiSpdHP->CurrentModuleObject,
2774 : MSHeatPump.Name,
2775 : "Supplemental Heating Coil Nominal Capacity [W]",
2776 : MSHeatPump.DesignSuppHeatingCapacity);
2777 : }
2778 11 : state.dataSize->SuppHeatCap = MSHeatPump.DesignSuppHeatingCapacity;
2779 :
2780 11 : if (MSHeatPump.HeatRecActive) {
2781 0 : PlantUtilities::RegisterPlantCompDesignFlow(state, MSHeatPump.HeatRecInletNodeNum, MSHeatPump.DesignHeatRecFlowRate);
2782 : }
2783 11 : }
2784 :
2785 : //******************************************************************************
2786 :
2787 31715 : void ControlMSHPOutputEMS(EnergyPlusData &state,
2788 : int const MSHeatPumpNum, // Unit index of engine driven heat pump
2789 : bool const FirstHVACIteration, // flag for 1st HVAC iteration in the time step
2790 : HVAC::CompressorOp const compressorOp, // compressor operation; 1=on, 0=off
2791 : HVAC::FanOp const fanOp, // operating mode: FanOp::Cycling | FanOp::Continuous
2792 : Real64 const QZnReq, // cooling or heating output needed by zone [W]
2793 : Real64 const SpeedVal, // continuous speed value
2794 : int &SpeedNum, // discrete speed level
2795 : Real64 &SpeedRatio, // unit speed ratio for DX coils
2796 : Real64 &PartLoadFrac, // unit part load fraction
2797 : Real64 &OnOffAirFlowRatio, // ratio of compressor ON airflow to AVERAGE airflow over timestep
2798 : Real64 &SupHeaterLoad // Supplemental heater load [W]
2799 :
2800 : )
2801 : {
2802 31715 : OnOffAirFlowRatio = 0.0;
2803 31715 : SupHeaterLoad = 0.0;
2804 :
2805 31715 : auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
2806 :
2807 : // Get EMS output
2808 31715 : SpeedNum = ceil(SpeedVal);
2809 31715 : bool useMaxedSpeed = false;
2810 31715 : std::string useMaxedSpeedCoilName;
2811 31715 : if (MSHeatPump.HeatCoolMode == ModeOfOperation::HeatingMode) {
2812 18507 : if (SpeedNum > MSHeatPump.NumOfSpeedHeating) {
2813 0 : SpeedNum = MSHeatPump.NumOfSpeedHeating;
2814 0 : useMaxedSpeed = true;
2815 0 : useMaxedSpeedCoilName = MSHeatPump.DXHeatCoilName;
2816 : }
2817 13208 : } else if (MSHeatPump.HeatCoolMode == ModeOfOperation::CoolingMode) {
2818 12712 : if (SpeedNum > MSHeatPump.NumOfSpeedCooling) {
2819 0 : SpeedNum = MSHeatPump.NumOfSpeedCooling;
2820 0 : useMaxedSpeed = true;
2821 0 : useMaxedSpeedCoilName = MSHeatPump.DXCoolCoilName;
2822 : }
2823 : }
2824 31715 : if (useMaxedSpeed) {
2825 0 : MSHeatPump.CoilSpeedErrIndex++;
2826 0 : ShowRecurringWarningErrorAtEnd(state,
2827 0 : "Wrong coil speed EMS override value, for unit=\"" + useMaxedSpeedCoilName +
2828 : "\". Exceeding maximum coil speed level. Speed level is set to the maximum coil speed level allowed.",
2829 0 : MSHeatPump.CoilSpeedErrIndex,
2830 : SpeedVal,
2831 : SpeedVal,
2832 : _,
2833 : "",
2834 : "");
2835 : }
2836 : // Calculate TempOutput
2837 31715 : Real64 TempOutput = 0.0; // unit output when iteration limit exceeded [W]
2838 :
2839 31715 : if (SpeedNum == 1) {
2840 7704 : SpeedRatio = 0.0;
2841 7704 : if (useMaxedSpeed || floor(SpeedVal) == SpeedVal) {
2842 7704 : PartLoadFrac = 1;
2843 : } else {
2844 0 : PartLoadFrac = SpeedVal - floor(SpeedVal);
2845 : }
2846 7704 : CalcMSHeatPump(state,
2847 : MSHeatPumpNum,
2848 : FirstHVACIteration,
2849 : compressorOp,
2850 : SpeedNum,
2851 : SpeedRatio,
2852 : PartLoadFrac,
2853 : TempOutput,
2854 : QZnReq,
2855 : OnOffAirFlowRatio,
2856 : SupHeaterLoad);
2857 : } else {
2858 24011 : PartLoadFrac = 0.0;
2859 24011 : if (useMaxedSpeed || floor(SpeedVal) == SpeedVal) {
2860 0 : SpeedRatio = 1;
2861 : } else {
2862 24011 : SpeedRatio = SpeedVal - floor(SpeedVal);
2863 : }
2864 24011 : CalcMSHeatPump(state,
2865 : MSHeatPumpNum,
2866 : FirstHVACIteration,
2867 : compressorOp,
2868 : SpeedNum,
2869 : SpeedRatio,
2870 : PartLoadFrac,
2871 : TempOutput,
2872 : QZnReq,
2873 : OnOffAirFlowRatio,
2874 : SupHeaterLoad);
2875 : }
2876 :
2877 31715 : ControlMSHPSupHeater(state,
2878 : MSHeatPumpNum,
2879 : FirstHVACIteration,
2880 : compressorOp,
2881 : fanOp,
2882 : QZnReq,
2883 : TempOutput,
2884 : SpeedNum,
2885 : SpeedRatio,
2886 : PartLoadFrac,
2887 : OnOffAirFlowRatio,
2888 : SupHeaterLoad);
2889 31715 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).CycRatio = PartLoadFrac;
2890 31715 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedRatio = SpeedRatio;
2891 31715 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedNum = SpeedNum;
2892 31715 : }
2893 :
2894 31715 : void ControlMSHPSupHeater(EnergyPlusData &state,
2895 : int const MSHeatPumpNum, // Unit index of engine driven heat pump
2896 : bool const FirstHVACIteration, // flag for 1st HVAC iteration in the time step
2897 : HVAC::CompressorOp const compressorOp, // compressor operation; 1=on, 0=off
2898 : HVAC::FanOp const fanOp, // operating mode: FanOp::Cycling | FanOp::Continuous
2899 : Real64 const QZnReq, // cooling or heating output needed by zone [W]
2900 : int const EMSOutput, // unit full output when compressor is operating [W]
2901 : int const SpeedNum, // Speed number
2902 : Real64 SpeedRatio, // unit speed ratio for DX coils
2903 : Real64 PartLoadFrac, // unit part load fraction
2904 : Real64 OnOffAirFlowRatio, // ratio of compressor ON airflow to AVERAGE airflow over timestep
2905 : Real64 &SupHeaterLoad // Supplemental heater load [W]
2906 :
2907 : )
2908 : {
2909 : // if the DX heating coil cannot meet the load, trim with supplemental heater
2910 : // occurs with constant fan mode when compressor is on or off
2911 : // occurs with cycling fan mode when compressor PLR is equal to 1
2912 31715 : auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
2913 :
2914 31715 : if ((QZnReq > HVAC::SmallLoad && QZnReq > EMSOutput)) {
2915 : Real64 TempOutput;
2916 18467 : if (state.dataEnvrn->OutDryBulbTemp <= MSHeatPump.SuppMaxAirTemp) {
2917 18467 : SupHeaterLoad = QZnReq - EMSOutput;
2918 : } else {
2919 0 : SupHeaterLoad = 0.0;
2920 : }
2921 18467 : CalcMSHeatPump(state,
2922 : MSHeatPumpNum,
2923 : FirstHVACIteration,
2924 : compressorOp,
2925 : SpeedNum,
2926 : SpeedRatio,
2927 : PartLoadFrac,
2928 : TempOutput,
2929 : QZnReq,
2930 : OnOffAirFlowRatio,
2931 : SupHeaterLoad);
2932 : }
2933 :
2934 : // check the outlet of the supplemental heater to be lower than the maximum supplemental heater supply air temperature
2935 31715 : if (state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp > MSHeatPump.SuppMaxAirTemp && SupHeaterLoad > 0.0) {
2936 :
2937 : // If the supply air temperature is to high, turn off the supplemental heater to recalculate the outlet temperature
2938 3520 : SupHeaterLoad = 0.0;
2939 : Real64 QCoilActual; // coil load actually delivered returned to calling component
2940 3520 : CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, SupHeaterLoad, fanOp, QCoilActual);
2941 :
2942 : // If the outlet temperature is below the maximum supplemental heater supply air temperature, reduce the load passed to
2943 : // the supplemental heater, otherwise leave the supplemental heater off. If the supplemental heater is to be turned on,
2944 : // use the outlet conditions when the supplemental heater was off (CALL above) as the inlet conditions for the calculation
2945 : // of supplemental heater load to just meet the maximum supply air temperature from the supplemental heater.
2946 3520 : if (state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp < MSHeatPump.SuppMaxAirTemp) {
2947 3520 : Real64 CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).HumRat);
2948 3520 : SupHeaterLoad = state.dataLoopNodes->Node(MSHeatPump.AirInletNodeNum).MassFlowRate * CpAir *
2949 3520 : (MSHeatPump.SuppMaxAirTemp - state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp);
2950 :
2951 : } else {
2952 0 : SupHeaterLoad = 0.0;
2953 : }
2954 : }
2955 31715 : }
2956 :
2957 194375 : void ControlMSHPOutput(EnergyPlusData &state,
2958 : int const MSHeatPumpNum, // Unit index of engine driven heat pump
2959 : bool const FirstHVACIteration, // flag for 1st HVAC iteration in the time step
2960 : HVAC::CompressorOp const compressorOp, // compressor operation; 1=on, 0=off
2961 : HVAC::FanOp const fanOp, // operating mode: FanOp::Cycling | FanOp::Continuous
2962 : Real64 const QZnReq, // cooling or heating output needed by zone [W]
2963 : int const ZoneNum [[maybe_unused]], // Index to zone number
2964 : int &SpeedNum, // Speed number
2965 : Real64 &SpeedRatio, // unit speed ratio for DX coils
2966 : Real64 &PartLoadFrac, // unit part load fraction
2967 : Real64 &OnOffAirFlowRatio, // ratio of compressor ON airflow to AVERAGE airflow over timestep
2968 : Real64 &SupHeaterLoad // Supplemental heater load [W]
2969 : )
2970 : {
2971 :
2972 : // SUBROUTINE INFORMATION:
2973 : // AUTHOR Lixing Gu
2974 : // DATE WRITTEN June 2007
2975 : // RE-ENGINEERED Revised for multispeed heat pump use based on ControlPTHPOutput
2976 :
2977 : // PURPOSE OF THIS SUBROUTINE:
2978 : // Determine the part load fraction at low speed, and speed ratio at high speed for this time step.
2979 :
2980 : // METHODOLOGY EMPLOYED:
2981 : // Use RegulaFalsi technique to iterate on part-load ratio until convergence is achieved.
2982 :
2983 : // SUBROUTINE PARAMETER DEFINITIONS:
2984 194375 : int constexpr MaxIte(500); // maximum number of iterations
2985 :
2986 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2987 : Real64 FullOutput; // unit full output when compressor is operating [W]
2988 : Real64 LowOutput; // unit full output at low speed [W]
2989 : Real64 TempOutput; // unit output when iteration limit exceeded [W]
2990 : Real64 NoCompOutput; // output when no active compressor [W]
2991 : Real64 ErrorToler; // error tolerance
2992 : int SolFla; // Flag of RegulaFalsi solver
2993 : Real64 CpAir; // air specific heat
2994 : Real64 OutsideDryBulbTemp; // Outside air temperature at external node height
2995 : Real64 QCoilActual; // coil load actually delivered returned to calling component
2996 : int i; // Speed index
2997 :
2998 194375 : SupHeaterLoad = 0.0;
2999 194375 : PartLoadFrac = 0.0;
3000 194375 : SpeedRatio = 0.0;
3001 194375 : SpeedNum = 1;
3002 :
3003 194375 : OutsideDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
3004 :
3005 194375 : auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
3006 :
3007 : //!!LKL Discrepancy with < 0
3008 194375 : if (MSHeatPump.availSched->getCurrentVal() == 0.0) {
3009 64136 : return;
3010 : }
3011 :
3012 : // Get result when DX coil is off
3013 170663 : CalcMSHeatPump(state,
3014 : MSHeatPumpNum,
3015 : FirstHVACIteration,
3016 : compressorOp,
3017 : SpeedNum,
3018 : SpeedRatio,
3019 : PartLoadFrac,
3020 : NoCompOutput,
3021 : QZnReq,
3022 : OnOffAirFlowRatio,
3023 : SupHeaterLoad);
3024 :
3025 : // If cooling and NoCompOutput < QZnReq, the coil needs to be off
3026 : // If heating and NoCompOutput > QZnReq, the coil needs to be off
3027 341326 : if ((QZnReq < (-1.0 * HVAC::SmallLoad) && NoCompOutput < QZnReq) || (QZnReq > HVAC::SmallLoad && NoCompOutput > QZnReq) ||
3028 170663 : std::abs(QZnReq) <= HVAC::SmallLoad) {
3029 29730 : return;
3030 : }
3031 :
3032 : // Get full load result
3033 140933 : PartLoadFrac = 1.0;
3034 140933 : SpeedRatio = 1.0;
3035 140933 : if (MSHeatPump.HeatCoolMode == ModeOfOperation::HeatingMode) {
3036 86045 : SpeedNum = MSHeatPump.NumOfSpeedHeating;
3037 86045 : if (MSHeatPump.Staged && std::abs(MSHeatPump.StageNum) < SpeedNum) {
3038 7240 : SpeedNum = std::abs(MSHeatPump.StageNum);
3039 7240 : if (SpeedNum == 1) {
3040 592 : SpeedRatio = 0.0;
3041 : }
3042 : }
3043 : }
3044 140933 : if (MSHeatPump.HeatCoolMode == ModeOfOperation::CoolingMode) {
3045 54888 : SpeedNum = MSHeatPump.NumOfSpeedCooling;
3046 54888 : if (MSHeatPump.Staged && std::abs(MSHeatPump.StageNum) < SpeedNum) {
3047 6750 : SpeedNum = std::abs(MSHeatPump.StageNum);
3048 6750 : if (SpeedNum == 1) {
3049 794 : SpeedRatio = 0.0;
3050 : }
3051 : }
3052 : }
3053 :
3054 140933 : CalcMSHeatPump(state,
3055 : MSHeatPumpNum,
3056 : FirstHVACIteration,
3057 : compressorOp,
3058 : SpeedNum,
3059 : SpeedRatio,
3060 : PartLoadFrac,
3061 : FullOutput,
3062 : QZnReq,
3063 : OnOffAirFlowRatio,
3064 : SupHeaterLoad);
3065 :
3066 140933 : if (QZnReq < (-1.0 * HVAC::SmallLoad)) {
3067 : // Since we are cooling, we expect FullOutput to be < 0 and FullOutput < NoCompOutput
3068 : // Check that this is the case; if not set PartLoadFrac = 0.0 (off) and return
3069 54888 : if (FullOutput >= 0.0 || FullOutput >= NoCompOutput) {
3070 0 : PartLoadFrac = 0.0;
3071 0 : SpeedRatio = 0.0;
3072 0 : SpeedNum = 0;
3073 0 : return;
3074 : }
3075 : // ! If the QZnReq <= FullOutput the unit needs to run full out
3076 54888 : if (QZnReq <= FullOutput) {
3077 10694 : PartLoadFrac = 1.0;
3078 10694 : SpeedRatio = 1.0;
3079 10694 : if (MSHeatPump.Staged && SpeedNum == 1) {
3080 696 : SpeedRatio = 0.0;
3081 : }
3082 10694 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).CycRatio = PartLoadFrac;
3083 10694 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedRatio = SpeedRatio;
3084 10694 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedNum = SpeedNum;
3085 10694 : return;
3086 : }
3087 44194 : ErrorToler = 0.001; // Error tolerance for convergence from input deck
3088 : } else {
3089 : // Since we are heating, we expect FullOutput to be > 0 and FullOutput > NoCompOutput
3090 : // Check that this is the case; if not set PartLoadFrac = 0.0 (off)
3091 86045 : if (FullOutput <= 0.0 || FullOutput <= NoCompOutput) {
3092 23906 : PartLoadFrac = 0.0;
3093 23906 : SpeedRatio = 0.0;
3094 : // may need supplemental heating so don't return in heating mode
3095 : }
3096 86045 : if (QZnReq >= FullOutput) {
3097 62205 : PartLoadFrac = 1.0;
3098 62205 : SpeedRatio = 1.0;
3099 : // may need supplemental heating so don't return in heating mode
3100 : }
3101 86045 : ErrorToler = 0.001; // Error tolerance for convergence from input deck
3102 : }
3103 :
3104 : // Direct solution
3105 130239 : if (state.dataGlobal->DoCoilDirectSolutions && !MSHeatPump.Staged) {
3106 9094 : Real64 TempOutput0 = 0.0;
3107 9094 : MSHeatPump.FullOutput = 0.0;
3108 :
3109 : // heating
3110 9094 : if (QZnReq > HVAC::SmallLoad && QZnReq < FullOutput) {
3111 6 : CalcMSHeatPump(
3112 : state, MSHeatPumpNum, FirstHVACIteration, compressorOp, 1, 0.0, 0.0, TempOutput0, QZnReq, OnOffAirFlowRatio, SupHeaterLoad);
3113 :
3114 24 : for (int k = 1; k <= MSHeatPump.NumOfSpeedHeating; ++k) {
3115 24 : if (k == 1) {
3116 6 : CalcMSHeatPump(state,
3117 : MSHeatPumpNum,
3118 : FirstHVACIteration,
3119 : compressorOp,
3120 : k,
3121 : 0.0,
3122 : 1.0,
3123 6 : MSHeatPump.FullOutput(k),
3124 : QZnReq,
3125 : OnOffAirFlowRatio,
3126 : SupHeaterLoad);
3127 6 : if (QZnReq <= MSHeatPump.FullOutput(k)) {
3128 0 : SpeedNum = k;
3129 0 : PartLoadFrac = (QZnReq - TempOutput0) / (MSHeatPump.FullOutput(k) - TempOutput0);
3130 0 : CalcMSHeatPump(state,
3131 : MSHeatPumpNum,
3132 : FirstHVACIteration,
3133 : compressorOp,
3134 : k,
3135 : 0.0,
3136 : PartLoadFrac,
3137 : TempOutput,
3138 : QZnReq,
3139 : OnOffAirFlowRatio,
3140 : SupHeaterLoad);
3141 0 : break;
3142 : }
3143 : } else {
3144 18 : CalcMSHeatPump(state,
3145 : MSHeatPumpNum,
3146 : FirstHVACIteration,
3147 : compressorOp,
3148 : k,
3149 : 1.0,
3150 : 1.0,
3151 18 : MSHeatPump.FullOutput(k),
3152 : QZnReq,
3153 : OnOffAirFlowRatio,
3154 : SupHeaterLoad);
3155 18 : if (QZnReq <= MSHeatPump.FullOutput(k)) {
3156 6 : SpeedNum = k;
3157 6 : PartLoadFrac = 1.0;
3158 6 : SpeedRatio = (QZnReq - MSHeatPump.FullOutput(k - 1)) / (MSHeatPump.FullOutput(k) - MSHeatPump.FullOutput(k - 1));
3159 6 : CalcMSHeatPump(state,
3160 : MSHeatPumpNum,
3161 : FirstHVACIteration,
3162 : compressorOp,
3163 : k,
3164 : SpeedRatio,
3165 : 1.0,
3166 : TempOutput,
3167 : QZnReq,
3168 : OnOffAirFlowRatio,
3169 : SupHeaterLoad);
3170 6 : break;
3171 : }
3172 : }
3173 : }
3174 : }
3175 :
3176 : // Cooling
3177 9094 : if (QZnReq < (-1.0 * HVAC::SmallLoad) && QZnReq > FullOutput) {
3178 4386 : CalcMSHeatPump(
3179 : state, MSHeatPumpNum, FirstHVACIteration, compressorOp, 1, 0.0, 0.0, TempOutput0, QZnReq, OnOffAirFlowRatio, SupHeaterLoad);
3180 13493 : for (int k = 1; k <= MSHeatPump.NumOfSpeedCooling; ++k) {
3181 13493 : if (k == 1) {
3182 4386 : CalcMSHeatPump(state,
3183 : MSHeatPumpNum,
3184 : FirstHVACIteration,
3185 : compressorOp,
3186 : k,
3187 : 0.0,
3188 : 1.0,
3189 4386 : MSHeatPump.FullOutput(k),
3190 : QZnReq,
3191 : OnOffAirFlowRatio,
3192 : SupHeaterLoad);
3193 4386 : if (QZnReq >= MSHeatPump.FullOutput(k)) {
3194 158 : SpeedNum = k;
3195 158 : PartLoadFrac = (QZnReq - TempOutput0) / (MSHeatPump.FullOutput(k) - TempOutput0);
3196 158 : CalcMSHeatPump(state,
3197 : MSHeatPumpNum,
3198 : FirstHVACIteration,
3199 : compressorOp,
3200 : k,
3201 : 0.0,
3202 : PartLoadFrac,
3203 : TempOutput,
3204 : QZnReq,
3205 : OnOffAirFlowRatio,
3206 : SupHeaterLoad);
3207 158 : break;
3208 : }
3209 : } else {
3210 9107 : CalcMSHeatPump(state,
3211 : MSHeatPumpNum,
3212 : FirstHVACIteration,
3213 : compressorOp,
3214 : k,
3215 : 1.0,
3216 : 1.0,
3217 9107 : MSHeatPump.FullOutput(k),
3218 : QZnReq,
3219 : OnOffAirFlowRatio,
3220 : SupHeaterLoad);
3221 9107 : if (QZnReq >= MSHeatPump.FullOutput(k)) {
3222 4228 : SpeedNum = k;
3223 4228 : PartLoadFrac = 1.0;
3224 4228 : SpeedRatio = (QZnReq - MSHeatPump.FullOutput(k - 1)) / (MSHeatPump.FullOutput(k) - MSHeatPump.FullOutput(k - 1));
3225 4228 : CalcMSHeatPump(state,
3226 : MSHeatPumpNum,
3227 : FirstHVACIteration,
3228 : compressorOp,
3229 : k,
3230 : SpeedRatio,
3231 : 1.0,
3232 : TempOutput,
3233 : QZnReq,
3234 : OnOffAirFlowRatio,
3235 : SupHeaterLoad);
3236 4228 : break;
3237 : }
3238 : }
3239 : }
3240 : }
3241 : } else {
3242 : // Calculate the part load fraction
3243 121145 : if (((QZnReq > HVAC::SmallLoad && QZnReq < FullOutput) || (QZnReq < (-1.0 * HVAC::SmallLoad) && QZnReq > FullOutput)) &&
3244 63642 : (!MSHeatPump.Staged)) {
3245 : // Check whether the low speed coil can meet the load or not
3246 63337 : CalcMSHeatPump(
3247 : state, MSHeatPumpNum, FirstHVACIteration, compressorOp, 1, 0.0, 1.0, LowOutput, QZnReq, OnOffAirFlowRatio, SupHeaterLoad);
3248 63337 : if ((QZnReq > 0.0 && QZnReq <= LowOutput) || (QZnReq < 0.0 && QZnReq >= LowOutput)) {
3249 45885 : SpeedRatio = 0.0;
3250 45885 : SpeedNum = 1;
3251 211038 : auto f = [&state, MSHeatPumpNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp](
3252 : Real64 const PartLoadFrac) {
3253 : // Calculates residual function ((ActualOutput - QZnReq)/QZnReq); MSHP output depends on PLR which is being varied to zero
3254 : // the residual.
3255 : Real64 ActualOutput; // delivered capacity of MSHP
3256 165153 : Real64 tmpAirFlowRatio = OnOffAirFlowRatio;
3257 165153 : Real64 tmpHeaterLoad = SupHeaterLoad;
3258 165153 : CalcMSHeatPump(state,
3259 : MSHeatPumpNum,
3260 : FirstHVACIteration,
3261 : compressorOp,
3262 : 1,
3263 : 0.0,
3264 : PartLoadFrac,
3265 : ActualOutput,
3266 : QZnReq,
3267 : tmpAirFlowRatio,
3268 : tmpHeaterLoad);
3269 165153 : return (ActualOutput - QZnReq) / QZnReq;
3270 45885 : };
3271 45885 : General::SolveRoot(state, ErrorToler, MaxIte, SolFla, PartLoadFrac, f, 0.0, 1.0);
3272 45885 : if (SolFla == -1) {
3273 0 : if (!state.dataGlobal->WarmupFlag) {
3274 0 : if (state.dataHVACMultiSpdHP->ErrCountCyc == 0) {
3275 0 : ++state.dataHVACMultiSpdHP->ErrCountCyc; // TODO: Why is the error count shared among all heat pump units?
3276 0 : ShowWarningError(state,
3277 0 : format("Iteration limit exceeded calculating DX unit cycling ratio, for unit={}", MSHeatPump.Name));
3278 0 : ShowContinueErrorTimeStamp(state, format("Cycling ratio returned={:.2R}", PartLoadFrac));
3279 : } else {
3280 0 : ++state.dataHVACMultiSpdHP->ErrCountCyc;
3281 0 : ShowRecurringWarningErrorAtEnd(
3282 : state,
3283 0 : MSHeatPump.Name + "\": Iteration limit warning exceeding calculating DX unit cycling ratio continues...",
3284 0 : MSHeatPump.ErrIndexCyc,
3285 : PartLoadFrac,
3286 : PartLoadFrac);
3287 : }
3288 : }
3289 45885 : } else if (SolFla == -2) {
3290 0 : ShowFatalError(
3291 : state,
3292 0 : format("DX unit cycling ratio calculation failed: cycling limits exceeded, for unit={}", MSHeatPump.DXCoolCoilName));
3293 : }
3294 45885 : } else {
3295 : // Check to see which speed to meet the load
3296 17452 : PartLoadFrac = 1.0;
3297 17452 : SpeedRatio = 1.0;
3298 17452 : if (QZnReq < (-1.0 * HVAC::SmallLoad)) { // Cooling
3299 36956 : for (i = 2; i <= MSHeatPump.NumOfSpeedCooling; ++i) {
3300 36956 : CalcMSHeatPump(state,
3301 : MSHeatPumpNum,
3302 : FirstHVACIteration,
3303 : compressorOp,
3304 : i,
3305 : SpeedRatio,
3306 : PartLoadFrac,
3307 : TempOutput,
3308 : QZnReq,
3309 : OnOffAirFlowRatio,
3310 : SupHeaterLoad);
3311 36956 : if (QZnReq >= TempOutput) {
3312 17440 : SpeedNum = i;
3313 17440 : break;
3314 : }
3315 : }
3316 : } else {
3317 36 : for (i = 2; i <= MSHeatPump.NumOfSpeedHeating; ++i) {
3318 36 : CalcMSHeatPump(state,
3319 : MSHeatPumpNum,
3320 : FirstHVACIteration,
3321 : compressorOp,
3322 : i,
3323 : SpeedRatio,
3324 : PartLoadFrac,
3325 : TempOutput,
3326 : QZnReq,
3327 : OnOffAirFlowRatio,
3328 : SupHeaterLoad);
3329 36 : if (QZnReq <= TempOutput) {
3330 12 : SpeedNum = i;
3331 12 : break;
3332 : }
3333 : }
3334 : }
3335 71544 : auto f = [&state, OnOffAirFlowRatio, SupHeaterLoad, MSHeatPumpNum, FirstHVACIteration, compressorOp, SpeedNum, QZnReq](
3336 : Real64 const SpeedRatio) {
3337 : // Calculates residual function ((ActualOutput - QZnReq)/QZnReq) MSHP output depends on PLR which is being varied to zero the
3338 : // residual.
3339 54092 : Real64 localAirFlowRatio = OnOffAirFlowRatio;
3340 54092 : Real64 localHeaterLoad = SupHeaterLoad;
3341 : Real64 ActualOutput;
3342 54092 : CalcMSHeatPump(state,
3343 : MSHeatPumpNum,
3344 : FirstHVACIteration,
3345 : compressorOp,
3346 : SpeedNum,
3347 : SpeedRatio,
3348 : 1.0,
3349 : ActualOutput,
3350 : QZnReq,
3351 : localAirFlowRatio,
3352 : localHeaterLoad);
3353 54092 : return (ActualOutput - QZnReq) / QZnReq;
3354 17452 : };
3355 17452 : General::SolveRoot(state, ErrorToler, MaxIte, SolFla, SpeedRatio, f, 0.0, 1.0);
3356 17452 : if (SolFla == -1) {
3357 0 : if (!state.dataGlobal->WarmupFlag) {
3358 0 : if (state.dataHVACMultiSpdHP->ErrCountVar == 0) {
3359 0 : ++state.dataHVACMultiSpdHP->ErrCountVar;
3360 0 : ShowWarningError(state,
3361 0 : format("Iteration limit exceeded calculating DX unit speed ratio, for unit={}", MSHeatPump.Name));
3362 0 : ShowContinueErrorTimeStamp(state, format("Speed ratio returned=[{:.2R}], Speed number ={}", SpeedRatio, SpeedNum));
3363 : } else {
3364 0 : ++state.dataHVACMultiSpdHP->ErrCountVar;
3365 0 : ShowRecurringWarningErrorAtEnd(
3366 : state,
3367 0 : MSHeatPump.Name + "\": Iteration limit warning exceeding calculating DX unit speed ratio continues...",
3368 0 : MSHeatPump.ErrIndexVar,
3369 : SpeedRatio,
3370 : SpeedRatio);
3371 : }
3372 : }
3373 17452 : } else if (SolFla == -2) {
3374 0 : ShowFatalError(
3375 : state,
3376 0 : format("DX unit compressor speed calculation failed: speed limits exceeded, for unit={}", MSHeatPump.DXCoolCoilName));
3377 : }
3378 : }
3379 63337 : } else {
3380 : // Staged thermostat performance
3381 57808 : if (MSHeatPump.StageNum != 0) {
3382 7545 : SpeedNum = std::abs(MSHeatPump.StageNum);
3383 7545 : if (SpeedNum == 1) {
3384 690 : CalcMSHeatPump(
3385 : state, MSHeatPumpNum, FirstHVACIteration, compressorOp, 1, 0.0, 1.0, LowOutput, QZnReq, OnOffAirFlowRatio, SupHeaterLoad);
3386 690 : SpeedRatio = 0.0;
3387 690 : if ((QZnReq > 0.0 && QZnReq <= LowOutput) || (QZnReq < 0.0 && QZnReq >= LowOutput)) {
3388 916 : auto f = [&state, MSHeatPumpNum, FirstHVACIteration, QZnReq, OnOffAirFlowRatio, SupHeaterLoad, compressorOp](
3389 : Real64 const PartLoadFrac) {
3390 : // Calculates residual function ((ActualOutput - QZnReq)/QZnReq); MSHP output depends on PLR which is being varied to
3391 : // zero the residual.
3392 : Real64 ActualOutput; // delivered capacity of MSHP
3393 818 : Real64 tmpAirFlowRatio = OnOffAirFlowRatio;
3394 818 : Real64 tmpHeaterLoad = SupHeaterLoad;
3395 818 : CalcMSHeatPump(state,
3396 : MSHeatPumpNum,
3397 : FirstHVACIteration,
3398 : compressorOp,
3399 : 1,
3400 : 0.0,
3401 : PartLoadFrac,
3402 : ActualOutput,
3403 : QZnReq,
3404 : tmpAirFlowRatio,
3405 : tmpHeaterLoad);
3406 818 : return (ActualOutput - QZnReq) / QZnReq;
3407 98 : };
3408 98 : General::SolveRoot(state, ErrorToler, MaxIte, SolFla, PartLoadFrac, f, 0.0, 1.0);
3409 98 : if (SolFla == -1) {
3410 0 : if (!state.dataGlobal->WarmupFlag) {
3411 0 : if (state.dataHVACMultiSpdHP->ErrCountCyc == 0) {
3412 0 : ++state.dataHVACMultiSpdHP->ErrCountCyc;
3413 0 : ShowWarningError(
3414 : state,
3415 0 : format("Iteration limit exceeded calculating DX unit cycling ratio, for unit={}", MSHeatPump.Name));
3416 0 : ShowContinueErrorTimeStamp(state, format("Cycling ratio returned={:.2R}", PartLoadFrac));
3417 : } else {
3418 0 : ++state.dataHVACMultiSpdHP->ErrCountCyc;
3419 0 : ShowRecurringWarningErrorAtEnd(
3420 : state,
3421 0 : MSHeatPump.Name + "\": Iteration limit warning exceeding calculating DX unit cycling ratio continues...",
3422 0 : MSHeatPump.ErrIndexCyc,
3423 : PartLoadFrac,
3424 : PartLoadFrac);
3425 : }
3426 : }
3427 98 : } else if (SolFla == -2) {
3428 0 : ShowFatalError(state,
3429 0 : format("DX unit cycling ratio calculation failed: cycling limits exceeded, for unit={}",
3430 0 : MSHeatPump.DXCoolCoilName));
3431 : }
3432 98 : } else {
3433 592 : FullOutput = LowOutput;
3434 592 : PartLoadFrac = 1.0;
3435 : }
3436 : } else {
3437 6855 : if (MSHeatPump.StageNum < 0) {
3438 207 : SpeedNum = min(MSHeatPump.NumOfSpeedCooling, std::abs(MSHeatPump.StageNum));
3439 : } else {
3440 6648 : SpeedNum = min(MSHeatPump.NumOfSpeedHeating, std::abs(MSHeatPump.StageNum));
3441 : }
3442 6855 : CalcMSHeatPump(state,
3443 : MSHeatPumpNum,
3444 : FirstHVACIteration,
3445 : compressorOp,
3446 : SpeedNum,
3447 : 0.0,
3448 : 1.0,
3449 : LowOutput,
3450 : QZnReq,
3451 : OnOffAirFlowRatio,
3452 : SupHeaterLoad);
3453 6855 : if ((QZnReq > 0.0 && QZnReq >= LowOutput) || (QZnReq < 0.0 && QZnReq <= LowOutput)) {
3454 6831 : CalcMSHeatPump(state,
3455 : MSHeatPumpNum,
3456 : FirstHVACIteration,
3457 : compressorOp,
3458 : SpeedNum,
3459 : 1.0,
3460 : 1.0,
3461 : FullOutput,
3462 : QZnReq,
3463 : OnOffAirFlowRatio,
3464 : SupHeaterLoad);
3465 6831 : if ((QZnReq > 0.0 && QZnReq <= FullOutput) || (QZnReq < 0.0 && QZnReq >= FullOutput)) {
3466 : auto f = // (AUTO_OK_LAMBDA)
3467 738 : [&state, OnOffAirFlowRatio, SupHeaterLoad, MSHeatPumpNum, FirstHVACIteration, compressorOp, SpeedNum, QZnReq](
3468 : Real64 const SpeedRatio) {
3469 : // Calculates residual function ((ActualOutput - QZnReq)/QZnReq) MSHP output depends on PLR which is being
3470 : // varied to zero the residual.
3471 555 : Real64 localAirFlowRatio = OnOffAirFlowRatio;
3472 555 : Real64 localHeaterLoad = SupHeaterLoad;
3473 : Real64 ActualOutput;
3474 555 : CalcMSHeatPump(state,
3475 : MSHeatPumpNum,
3476 : FirstHVACIteration,
3477 : compressorOp,
3478 : SpeedNum,
3479 : SpeedRatio,
3480 : 1.0,
3481 : ActualOutput,
3482 : QZnReq,
3483 : localAirFlowRatio,
3484 : localHeaterLoad);
3485 555 : return (ActualOutput - QZnReq) / QZnReq;
3486 183 : };
3487 183 : General::SolveRoot(state, ErrorToler, MaxIte, SolFla, SpeedRatio, f, 0.0, 1.0);
3488 183 : if (SolFla == -1) {
3489 0 : if (!state.dataGlobal->WarmupFlag) {
3490 0 : if (state.dataHVACMultiSpdHP->ErrCountVar == 0) {
3491 0 : ++state.dataHVACMultiSpdHP->ErrCountVar;
3492 0 : ShowWarningError(
3493 : state,
3494 0 : format("Iteration limit exceeded calculating DX unit speed ratio, for unit={}", MSHeatPump.Name));
3495 0 : ShowContinueErrorTimeStamp(
3496 0 : state, format("Speed ratio returned=[{:.2R}], Speed number ={}", SpeedRatio, SpeedNum));
3497 : } else {
3498 0 : ++state.dataHVACMultiSpdHP->ErrCountVar;
3499 0 : ShowRecurringWarningErrorAtEnd(
3500 : state,
3501 0 : MSHeatPump.Name +
3502 : "\": Iteration limit warning exceeding calculating DX unit speed ratio continues...",
3503 0 : MSHeatPump.ErrIndexVar,
3504 : SpeedRatio,
3505 : SpeedRatio);
3506 : }
3507 : }
3508 183 : } else if (SolFla == -2) {
3509 0 : ShowFatalError(state,
3510 0 : format("DX unit compressor speed calculation failed: speed limits exceeded, for unit={}",
3511 0 : MSHeatPump.DXCoolCoilName));
3512 : }
3513 183 : } else {
3514 6648 : SpeedRatio = 1.0;
3515 : }
3516 6831 : } else { // lowOutput provides a larger capacity than needed
3517 24 : SpeedRatio = 0.0;
3518 : }
3519 : }
3520 : }
3521 : }
3522 : }
3523 :
3524 : // if the DX heating coil cannot meet the load, trim with supplemental heater
3525 : // occurs with constant fan mode when compressor is on or off
3526 : // occurs with cycling fan mode when compressor PLR is equal to 1
3527 130239 : if ((QZnReq > HVAC::SmallLoad && QZnReq > FullOutput)) {
3528 62205 : PartLoadFrac = 1.0;
3529 62205 : SpeedRatio = 1.0;
3530 62205 : if (MSHeatPump.Staged && SpeedNum == 1) {
3531 592 : SpeedRatio = 0.0;
3532 : }
3533 62205 : if (OutsideDryBulbTemp <= MSHeatPump.SuppMaxAirTemp) {
3534 62205 : SupHeaterLoad = QZnReq - FullOutput;
3535 : } else {
3536 0 : SupHeaterLoad = 0.0;
3537 : }
3538 62205 : CalcMSHeatPump(state,
3539 : MSHeatPumpNum,
3540 : FirstHVACIteration,
3541 : compressorOp,
3542 : SpeedNum,
3543 : SpeedRatio,
3544 : PartLoadFrac,
3545 : TempOutput,
3546 : QZnReq,
3547 : OnOffAirFlowRatio,
3548 : SupHeaterLoad);
3549 : }
3550 :
3551 : // check the outlet of the supplemental heater to be lower than the maximum supplemental heater supply air temperature
3552 130239 : if (state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp > MSHeatPump.SuppMaxAirTemp && SupHeaterLoad > 0.0) {
3553 :
3554 : // If the supply air temperature is to high, turn off the supplemental heater to recalculate the outlet temperature
3555 10658 : SupHeaterLoad = 0.0;
3556 10658 : CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, SupHeaterLoad, fanOp, QCoilActual);
3557 :
3558 : // If the outlet temperature is below the maximum supplemental heater supply air temperature, reduce the load passed to
3559 : // the supplemental heater, otherwise leave the supplemental heater off. If the supplemental heater is to be turned on,
3560 : // use the outlet conditions when the supplemental heater was off (CALL above) as the inlet conditions for the calculation
3561 : // of supplemental heater load to just meet the maximum supply air temperature from the supplemental heater.
3562 10658 : if (state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp < MSHeatPump.SuppMaxAirTemp) {
3563 10658 : CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).HumRat);
3564 10658 : SupHeaterLoad = state.dataLoopNodes->Node(MSHeatPump.AirInletNodeNum).MassFlowRate * CpAir *
3565 10658 : (MSHeatPump.SuppMaxAirTemp - state.dataLoopNodes->Node(MSHeatPump.AirOutletNodeNum).Temp);
3566 :
3567 : } else {
3568 0 : SupHeaterLoad = 0.0;
3569 : }
3570 : }
3571 :
3572 130239 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).CycRatio = PartLoadFrac;
3573 130239 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedRatio = SpeedRatio;
3574 130239 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).SpeedNum = SpeedNum;
3575 : }
3576 :
3577 : //******************************************************************************
3578 :
3579 1233787 : void CalcMSHeatPump(EnergyPlusData &state,
3580 : int const MSHeatPumpNum, // Engine driven heat pump number
3581 : bool const FirstHVACIteration, // Flag for 1st HVAC iteration
3582 : HVAC::CompressorOp const compressorOp, // Compressor on/off; 1=on, 0=off
3583 : int const SpeedNum, // Speed number
3584 : Real64 const SpeedRatio, // Compressor speed ratio
3585 : Real64 const PartLoadFrac, // Compressor part load fraction
3586 : Real64 &LoadMet, // Load met by unit (W)
3587 : Real64 const QZnReq, // Zone load (W)
3588 : Real64 &OnOffAirFlowRatio, // Ratio of compressor ON airflow to AVERAGE airflow over timestep
3589 : Real64 &SupHeaterLoad // supplemental heater load (W)
3590 : )
3591 : {
3592 : // SUBROUTINE INFORMATION:
3593 : // AUTHOR: Lixing Gu, FSEC
3594 : // DATE WRITTEN: June 2007
3595 :
3596 : // PURPOSE OF THIS SUBROUTINE:
3597 : // This routine will calculates MSHP performance based on given system load
3598 :
3599 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3600 : int OutletNode; // MSHP air outlet node
3601 : int InletNode; // MSHP air inlet node
3602 : Real64 OutsideDryBulbTemp; // Outdoor dry bulb temperature [C]
3603 : Real64 AirMassFlow; // Air mass flow rate [kg/s]
3604 : Real64 SavePartloadRatio;
3605 : Real64 SaveSpeedRatio;
3606 : Real64 QCoilActual; // coil load actually delivered returned to calling component
3607 : Real64 MinWaterFlow; // minimum water flow rate
3608 : Real64 ErrorToler; // supplemental heating coil convergence tolerance
3609 :
3610 1233787 : auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
3611 :
3612 1233787 : OutletNode = MSHeatPump.AirOutletNodeNum;
3613 1233787 : InletNode = MSHeatPump.AirInletNodeNum;
3614 1233787 : if (MSHeatPump.DXHeatCoilIndex > 0) {
3615 925102 : if (state.dataDXCoils->DXCoil(MSHeatPump.DXHeatCoilIndex).IsSecondaryDXCoilInZone) {
3616 0 : OutsideDryBulbTemp =
3617 0 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataDXCoils->DXCoil(MSHeatPump.DXHeatCoilIndex).SecZonePtr).ZT;
3618 : } else {
3619 925102 : OutsideDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
3620 : }
3621 308685 : } else if (MSHeatPump.DXCoolCoilIndex > 0) {
3622 308685 : if (state.dataDXCoils->DXCoil(MSHeatPump.DXCoolCoilIndex).IsSecondaryDXCoilInZone) {
3623 0 : OutsideDryBulbTemp =
3624 0 : state.dataZoneTempPredictorCorrector->zoneHeatBalance(state.dataDXCoils->DXCoil(MSHeatPump.DXCoolCoilIndex).SecZonePtr).ZT;
3625 : } else {
3626 308685 : OutsideDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
3627 : }
3628 : } else {
3629 0 : OutsideDryBulbTemp = state.dataEnvrn->OutDryBulbTemp;
3630 : }
3631 :
3632 1233787 : state.dataHVACMultiSpdHP->SaveCompressorPLR = 0.0;
3633 1233787 : SavePartloadRatio = 0.0;
3634 1233787 : MinWaterFlow = 0.0;
3635 1233787 : ErrorToler = 0.001;
3636 : // Set inlet air mass flow rate based on PLR and compressor on/off air flow rates
3637 1233787 : SetAverageAirFlow(state, MSHeatPumpNum, PartLoadFrac, OnOffAirFlowRatio, SpeedNum, SpeedRatio);
3638 :
3639 1233787 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
3640 : // if blow through, simulate fan then coils
3641 1233787 : if (MSHeatPump.fanPlace == HVAC::FanPlace::BlowThru) {
3642 1233787 : state.dataFans->fans(MSHeatPump.FanNum)->simulate(state, FirstHVACIteration, state.dataHVACMultiSpdHP->FanSpeedRatio);
3643 1233787 : if (QZnReq < (-1.0 * HVAC::SmallLoad)) {
3644 533219 : if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorCooling) {
3645 1599657 : DXCoils::SimDXCoilMultiSpeed(state,
3646 : MSHeatPump.DXCoolCoilName,
3647 : SpeedRatio,
3648 : PartLoadFrac,
3649 533219 : MSHeatPump.DXCoolCoilIndex,
3650 : SpeedNum,
3651 533219 : MSHeatPump.fanOp,
3652 : compressorOp);
3653 533219 : SavePartloadRatio = PartLoadFrac;
3654 533219 : SaveSpeedRatio = SpeedRatio;
3655 : } else {
3656 0 : DXCoils::SimDXCoilMultiSpeed(
3657 0 : state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3658 : }
3659 533219 : state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXCoolCoilIndex);
3660 : } else {
3661 2101704 : DXCoils::SimDXCoilMultiSpeed(
3662 1401136 : state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3663 : }
3664 1233787 : if (MSHeatPump.HeatCoilType == MultiSpeedHeatingCoil) {
3665 925102 : if (QZnReq > HVAC::SmallLoad) {
3666 398727 : if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorHeating) {
3667 13410 : DXCoils::SimDXCoilMultiSpeed(state,
3668 : MSHeatPump.DXHeatCoilName,
3669 : SpeedRatio,
3670 : PartLoadFrac,
3671 4470 : MSHeatPump.DXHeatCoilIndex,
3672 : SpeedNum,
3673 4470 : MSHeatPump.fanOp,
3674 : compressorOp);
3675 4470 : SavePartloadRatio = PartLoadFrac;
3676 4470 : SaveSpeedRatio = SpeedRatio;
3677 : } else {
3678 1182771 : DXCoils::SimDXCoilMultiSpeed(
3679 788514 : state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3680 : }
3681 398727 : state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXHeatCoilIndex);
3682 : } else {
3683 1579125 : DXCoils::SimDXCoilMultiSpeed(
3684 1052750 : state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3685 : }
3686 308685 : } else if (MSHeatPump.HeatCoilType == HVAC::Coil_HeatingElectric_MultiStage ||
3687 191005 : MSHeatPump.HeatCoilType == HVAC::Coil_HeatingGas_MultiStage) {
3688 308685 : if (QZnReq > HVAC::SmallLoad) {
3689 800492 : HeatingCoils::SimulateHeatingCoilComponents(
3690 600369 : state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, PartLoadFrac, SpeedNum, SpeedRatio);
3691 : } else {
3692 542810 : HeatingCoils::SimulateHeatingCoilComponents(
3693 651372 : state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, 0.0, SpeedNum, 0.0);
3694 : }
3695 : } else {
3696 0 : CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, QZnReq, MSHeatPump.fanOp, QCoilActual, PartLoadFrac);
3697 : }
3698 : // Call twice to ensure the fan outlet conditions are updated
3699 1233787 : state.dataFans->fans(MSHeatPump.FanNum)->simulate(state, FirstHVACIteration, state.dataHVACMultiSpdHP->FanSpeedRatio);
3700 1233787 : if (QZnReq < (-1.0 * HVAC::SmallLoad)) {
3701 533219 : if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorCooling) {
3702 1599657 : DXCoils::SimDXCoilMultiSpeed(state,
3703 : MSHeatPump.DXCoolCoilName,
3704 : SpeedRatio,
3705 : PartLoadFrac,
3706 533219 : MSHeatPump.DXCoolCoilIndex,
3707 : SpeedNum,
3708 533219 : MSHeatPump.fanOp,
3709 : compressorOp);
3710 533219 : SavePartloadRatio = PartLoadFrac;
3711 533219 : SaveSpeedRatio = SpeedRatio;
3712 : } else {
3713 0 : DXCoils::SimDXCoilMultiSpeed(
3714 0 : state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3715 : }
3716 533219 : state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXCoolCoilIndex);
3717 : } else {
3718 2101704 : DXCoils::SimDXCoilMultiSpeed(
3719 1401136 : state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3720 : }
3721 1233787 : if (MSHeatPump.HeatCoilType == MultiSpeedHeatingCoil) {
3722 925102 : if (QZnReq > HVAC::SmallLoad) {
3723 398727 : if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorHeating) {
3724 13410 : DXCoils::SimDXCoilMultiSpeed(state,
3725 : MSHeatPump.DXHeatCoilName,
3726 : SpeedRatio,
3727 : PartLoadFrac,
3728 4470 : MSHeatPump.DXHeatCoilIndex,
3729 : SpeedNum,
3730 4470 : MSHeatPump.fanOp,
3731 : compressorOp);
3732 4470 : SavePartloadRatio = PartLoadFrac;
3733 4470 : SaveSpeedRatio = SpeedRatio;
3734 : } else {
3735 1182771 : DXCoils::SimDXCoilMultiSpeed(
3736 788514 : state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3737 : }
3738 398727 : state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXHeatCoilIndex);
3739 : } else {
3740 1579125 : DXCoils::SimDXCoilMultiSpeed(
3741 1052750 : state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3742 : }
3743 308685 : } else if (MSHeatPump.HeatCoilType == HVAC::Coil_HeatingElectric_MultiStage ||
3744 191005 : MSHeatPump.HeatCoilType == HVAC::Coil_HeatingGas_MultiStage) {
3745 308685 : if (QZnReq > HVAC::SmallLoad) {
3746 800492 : HeatingCoils::SimulateHeatingCoilComponents(
3747 600369 : state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, PartLoadFrac, SpeedNum, SpeedRatio);
3748 : } else {
3749 542810 : HeatingCoils::SimulateHeatingCoilComponents(
3750 651372 : state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, 0.0, SpeedNum, 0.0);
3751 : }
3752 : } else {
3753 0 : CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, QZnReq, MSHeatPump.fanOp, QCoilActual, PartLoadFrac);
3754 : }
3755 : // Simulate supplemental heating coil for blow through fan
3756 1233787 : if (MSHeatPump.SuppHeatCoilNum > 0) {
3757 1233787 : CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, SupHeaterLoad, MSHeatPump.fanOp, QCoilActual);
3758 : }
3759 : } else { // otherwise simulate DX coils then fan then supplemental heater
3760 0 : if (QZnReq < (-1.0 * HVAC::SmallLoad)) {
3761 0 : if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorCooling) {
3762 0 : DXCoils::SimDXCoilMultiSpeed(state,
3763 : MSHeatPump.DXCoolCoilName,
3764 : SpeedRatio,
3765 : PartLoadFrac,
3766 0 : MSHeatPump.DXCoolCoilIndex,
3767 : SpeedNum,
3768 0 : MSHeatPump.fanOp,
3769 : compressorOp);
3770 0 : SavePartloadRatio = PartLoadFrac;
3771 0 : SaveSpeedRatio = SpeedRatio;
3772 : } else {
3773 0 : DXCoils::SimDXCoilMultiSpeed(
3774 0 : state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3775 : }
3776 0 : state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXCoolCoilIndex);
3777 : } else {
3778 0 : DXCoils::SimDXCoilMultiSpeed(
3779 0 : state, MSHeatPump.DXCoolCoilName, 0.0, 0.0, MSHeatPump.DXCoolCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3780 : }
3781 0 : if (MSHeatPump.HeatCoilType == MultiSpeedHeatingCoil) {
3782 0 : if (QZnReq > HVAC::SmallLoad) {
3783 0 : if (OutsideDryBulbTemp > MSHeatPump.MinOATCompressorHeating) {
3784 0 : DXCoils::SimDXCoilMultiSpeed(state,
3785 : MSHeatPump.DXHeatCoilName,
3786 : SpeedRatio,
3787 : PartLoadFrac,
3788 0 : MSHeatPump.DXHeatCoilIndex,
3789 : SpeedNum,
3790 0 : MSHeatPump.fanOp,
3791 : compressorOp);
3792 0 : SavePartloadRatio = PartLoadFrac;
3793 0 : SaveSpeedRatio = SpeedRatio;
3794 : } else {
3795 0 : DXCoils::SimDXCoilMultiSpeed(
3796 0 : state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3797 : }
3798 0 : state.dataHVACMultiSpdHP->SaveCompressorPLR = state.dataDXCoils->DXCoilPartLoadRatio(MSHeatPump.DXHeatCoilIndex);
3799 : } else {
3800 0 : DXCoils::SimDXCoilMultiSpeed(
3801 0 : state, MSHeatPump.DXHeatCoilName, 0.0, 0.0, MSHeatPump.DXHeatCoilIndex, SpeedNum, MSHeatPump.fanOp, compressorOp);
3802 : }
3803 0 : } else if (MSHeatPump.HeatCoilType == HVAC::Coil_HeatingElectric_MultiStage ||
3804 0 : MSHeatPump.HeatCoilType == HVAC::Coil_HeatingGas_MultiStage) {
3805 0 : if (QZnReq > HVAC::SmallLoad) {
3806 0 : HeatingCoils::SimulateHeatingCoilComponents(
3807 0 : state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, PartLoadFrac, SpeedNum, SpeedRatio);
3808 : } else {
3809 0 : HeatingCoils::SimulateHeatingCoilComponents(
3810 0 : state, MSHeatPump.HeatCoilName, FirstHVACIteration, _, 0, _, _, MSHeatPump.fanOp, 0.0, SpeedNum, 0.0);
3811 : }
3812 : } else {
3813 0 : CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, QZnReq, MSHeatPump.fanOp, QCoilActual, PartLoadFrac);
3814 : }
3815 0 : state.dataFans->fans(MSHeatPump.FanNum)->simulate(state, FirstHVACIteration, state.dataHVACMultiSpdHP->FanSpeedRatio);
3816 : // Simulate supplemental heating coil for draw through fan
3817 0 : if (MSHeatPump.SuppHeatCoilNum > 0) {
3818 0 : CalcNonDXHeatingCoils(state, MSHeatPumpNum, FirstHVACIteration, SupHeaterLoad, MSHeatPump.fanOp, QCoilActual);
3819 : }
3820 : }
3821 :
3822 : // calculate sensible load met
3823 1233787 : Real64 SensibleOutput(0.0); // sensible output rate
3824 : // calculate sensible load met using delta enthalpy at a constant (minimum) humidity ratio)
3825 1233787 : Real64 MinHumRat = state.dataLoopNodes->Node(MSHeatPump.NodeNumOfControlledZone).HumRat;
3826 1233787 : if (state.dataLoopNodes->Node(OutletNode).Temp < state.dataLoopNodes->Node(MSHeatPump.NodeNumOfControlledZone).Temp) {
3827 576949 : MinHumRat = state.dataLoopNodes->Node(OutletNode).HumRat;
3828 : }
3829 1233787 : SensibleOutput = AirMassFlow * Psychrometrics::PsyDeltaHSenFnTdb2W2Tdb1W1(state.dataLoopNodes->Node(OutletNode).Temp,
3830 : MinHumRat,
3831 1233787 : state.dataLoopNodes->Node(MSHeatPump.NodeNumOfControlledZone).Temp,
3832 : MinHumRat);
3833 1233787 : LoadMet = SensibleOutput - MSHeatPump.LoadLoss;
3834 :
3835 1233787 : MSHeatPump.LoadMet = LoadMet;
3836 1233787 : }
3837 :
3838 226090 : void UpdateMSHeatPump(EnergyPlusData &state, int const MSHeatPumpNum) // Engine driven heat pump number
3839 : {
3840 : // SUBROUTINE INFORMATION:
3841 : // AUTHOR: Lixing Gu, FSEC
3842 : // DATE WRITTEN: June 2007
3843 :
3844 : // PURPOSE OF THIS SUBROUTINE:
3845 : // This routine will update MSHP performance and calculate heat recovery rate and crankcase heater power
3846 :
3847 : // Calculate heat recovery
3848 226090 : if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatRecActive) {
3849 0 : MSHPHeatRecovery(state, MSHeatPumpNum);
3850 : }
3851 :
3852 226090 : if (state.afn->distribution_simulated) {
3853 15068 : state.dataAirLoop->AirLoopAFNInfo(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirLoopNumber).LoopSystemOnMassFlowrate =
3854 15068 : state.dataHVACMultiSpdHP->CompOnMassFlow;
3855 15068 : state.dataAirLoop->AirLoopAFNInfo(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirLoopNumber).LoopSystemOffMassFlowrate =
3856 15068 : state.dataHVACMultiSpdHP->CompOffMassFlow;
3857 15068 : state.dataAirLoop->AirLoopAFNInfo(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirLoopNumber).LoopFanOperationMode =
3858 15068 : state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).fanOp;
3859 15068 : state.dataAirLoop->AirLoopAFNInfo(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirLoopNumber).LoopOnOffFanPartLoadRatio =
3860 15068 : state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).FanPartLoadRatio;
3861 15068 : state.dataAirLoop->AirLoopAFNInfo(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirLoopNumber).LoopCompCycRatio =
3862 15068 : state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum).CycRatio;
3863 : }
3864 226090 : }
3865 :
3866 : //******************************************************************************
3867 :
3868 226090 : void ReportMSHeatPump(EnergyPlusData &state, int const MSHeatPumpNum) // Engine driven heat pump number
3869 : {
3870 : // SUBROUTINE INFORMATION:
3871 : // AUTHOR: Lixing Gu, FSEC
3872 : // DATE WRITTEN: June 2007
3873 :
3874 : // PURPOSE OF THIS SUBROUTINE:
3875 : // This routine will write values to output variables in MSHP
3876 :
3877 226090 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
3878 :
3879 226090 : auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
3880 226090 : auto &MSHeatPumpReport = state.dataHVACMultiSpdHP->MSHeatPumpReport(MSHeatPumpNum);
3881 :
3882 226090 : MSHeatPumpReport.ElecPowerConsumption = MSHeatPump.ElecPower * TimeStepSysSec; // + &
3883 226090 : MSHeatPumpReport.HeatRecoveryEnergy = MSHeatPump.HeatRecoveryRate * TimeStepSysSec;
3884 :
3885 226090 : MSHeatPumpReport.AuxElecHeatConsumption = 0.0;
3886 226090 : MSHeatPumpReport.AuxElecCoolConsumption = 0.0;
3887 :
3888 226090 : MSHeatPump.AuxElecPower = MSHeatPump.AuxOnCyclePower * state.dataHVACMultiSpdHP->SaveCompressorPLR +
3889 226090 : MSHeatPump.AuxOffCyclePower * (1.0 - state.dataHVACMultiSpdHP->SaveCompressorPLR);
3890 226090 : if (MSHeatPump.HeatCoolMode == ModeOfOperation::CoolingMode) {
3891 85792 : MSHeatPumpReport.AuxElecCoolConsumption = MSHeatPump.AuxOnCyclePower * state.dataHVACMultiSpdHP->SaveCompressorPLR * TimeStepSysSec;
3892 : }
3893 226090 : if (MSHeatPump.HeatCoolMode == ModeOfOperation::HeatingMode) {
3894 104552 : MSHeatPumpReport.AuxElecHeatConsumption = MSHeatPump.AuxOnCyclePower * state.dataHVACMultiSpdHP->SaveCompressorPLR * TimeStepSysSec;
3895 : }
3896 226090 : if (MSHeatPump.LastMode == ModeOfOperation::HeatingMode) {
3897 174548 : MSHeatPumpReport.AuxElecHeatConsumption +=
3898 174548 : MSHeatPump.AuxOffCyclePower * (1.0 - state.dataHVACMultiSpdHP->SaveCompressorPLR) * TimeStepSysSec;
3899 : } else {
3900 51542 : MSHeatPumpReport.AuxElecCoolConsumption +=
3901 51542 : MSHeatPump.AuxOffCyclePower * (1.0 - state.dataHVACMultiSpdHP->SaveCompressorPLR) * TimeStepSysSec;
3902 : }
3903 :
3904 226090 : if (MSHeatPump.FirstPass) {
3905 11 : if (!state.dataGlobal->SysSizingCalc) {
3906 11 : DataSizing::resetHVACSizingGlobals(state, state.dataSize->CurZoneEqNum, state.dataSize->CurSysNum, MSHeatPump.FirstPass);
3907 : }
3908 : }
3909 :
3910 : // reset to 1 in case blow through fan configuration (fan resets to 1, but for blow thru fans coil sets back down < 1)
3911 226090 : state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
3912 226090 : }
3913 :
3914 0 : void MSHPHeatRecovery(EnergyPlusData &state, int const MSHeatPumpNum) // Number of the current electric MSHP being simulated
3915 : {
3916 : // SUBROUTINE INFORMATION:
3917 : // AUTHOR: Lixing Gu
3918 : // DATE WRITTEN: June 2007
3919 : // RE-ENGINEERED Revised to calculate MSHP heat recovery rate based on EIR Chiller heat recovery subroutine
3920 : // PURPOSE OF THIS SUBROUTINE:
3921 : // Calculate the heat recovered from MSHP
3922 :
3923 : // SUBROUTINE PARAMETER DEFINITIONS:
3924 : static constexpr std::string_view RoutineName("MSHPHeatRecovery");
3925 :
3926 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3927 : Real64 HeatRecOutletTemp; // Heat reclaim outlet temp [C]
3928 :
3929 0 : auto &mshp = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
3930 : // Begin routine
3931 0 : int HeatRecInNode = mshp.HeatRecInletNodeNum;
3932 0 : int HeatRecOutNode = mshp.HeatRecOutletNodeNum;
3933 :
3934 : // Inlet node to the heat recovery heat exchanger
3935 0 : Real64 HeatRecInletTemp = state.dataLoopNodes->Node(HeatRecInNode).Temp;
3936 :
3937 : // Set heat recovery mass flow rates
3938 0 : Real64 HeatRecMassFlowRate = state.dataLoopNodes->Node(HeatRecInNode).MassFlowRate;
3939 :
3940 0 : Real64 QHeatRec = state.dataHVACGlobal->MSHPWasteHeat;
3941 :
3942 0 : if (HeatRecMassFlowRate > 0.0) {
3943 : // Heat reclaim water inlet specific heat [J/kg-K]
3944 0 : Real64 CpHeatRec = state.dataPlnt->PlantLoop(mshp.HRPlantLoc.loopNum).glycol->getSpecificHeat(state, HeatRecInletTemp, RoutineName);
3945 :
3946 0 : HeatRecOutletTemp = QHeatRec / (HeatRecMassFlowRate * CpHeatRec) + HeatRecInletTemp;
3947 0 : if (HeatRecOutletTemp > mshp.MaxHeatRecOutletTemp) {
3948 0 : HeatRecOutletTemp = max(HeatRecInletTemp, mshp.MaxHeatRecOutletTemp);
3949 0 : QHeatRec = HeatRecMassFlowRate * CpHeatRec * (HeatRecOutletTemp - HeatRecInletTemp);
3950 : }
3951 : } else {
3952 0 : HeatRecOutletTemp = HeatRecInletTemp;
3953 0 : QHeatRec = 0.0;
3954 : }
3955 :
3956 0 : PlantUtilities::SafeCopyPlantNode(state, HeatRecInNode, HeatRecOutNode);
3957 : // changed outputs
3958 0 : state.dataLoopNodes->Node(HeatRecOutNode).Temp = HeatRecOutletTemp;
3959 :
3960 0 : mshp.HeatRecoveryRate = QHeatRec;
3961 0 : mshp.HeatRecoveryInletTemp = HeatRecInletTemp;
3962 0 : mshp.HeatRecoveryOutletTemp = HeatRecOutletTemp;
3963 0 : mshp.HeatRecoveryMassFlowRate = HeatRecMassFlowRate;
3964 0 : }
3965 :
3966 1436165 : void SetAverageAirFlow(EnergyPlusData &state,
3967 : int const MSHeatPumpNum, // Unit index
3968 : Real64 const PartLoadRatio, // unit part load ratio
3969 : Real64 &OnOffAirFlowRatio, // ratio of compressor ON airflow to average airflow over timestep
3970 : ObjexxFCL::Optional_int_const SpeedNum, // Speed number
3971 : ObjexxFCL::Optional<Real64 const> SpeedRatio // Speed ratio
3972 : )
3973 : {
3974 :
3975 : // SUBROUTINE INFORMATION:
3976 : // AUTHOR Lixing
3977 : // DATE WRITTEN June 2007
3978 : // RE-ENGINEERED Resived to meet requirements of multispeed heat pump based on the same subroutine
3979 : // in PTHP module
3980 :
3981 : // PURPOSE OF THIS SUBROUTINE:
3982 : // Set the average air mass flow rates using the part load fraction of the heat pump for this time step
3983 : // Set OnOffAirFlowRatio to be used by DX coils
3984 :
3985 : // Using/Aliasing
3986 1436165 : auto &MSHPMassFlowRateHigh = state.dataHVACGlobal->MSHPMassFlowRateHigh;
3987 1436165 : auto &MSHPMassFlowRateLow = state.dataHVACGlobal->MSHPMassFlowRateLow;
3988 :
3989 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3990 : int InletNode; // inlet node number for PTHPNum
3991 : Real64 AverageUnitMassFlow; // average supply air mass flow rate over time step
3992 :
3993 1436165 : MSHPMassFlowRateLow = 0.0; // Mass flow rate at low speed
3994 1436165 : MSHPMassFlowRateHigh = 0.0; // Mass flow rate at high speed
3995 :
3996 2740394 : if (!state.dataZoneEnergyDemand->CurDeadBandOrSetback(state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).ControlZoneNum) &&
3997 1304229 : present(SpeedNum)) {
3998 1132075 : if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatCoolMode == ModeOfOperation::HeatingMode) {
3999 598850 : if (SpeedNum == 1) {
4000 352420 : state.dataHVACMultiSpdHP->CompOnMassFlow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum);
4001 352420 : state.dataHVACMultiSpdHP->CompOnFlowRatio = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(SpeedNum);
4002 352420 : MSHPMassFlowRateLow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(1);
4003 352420 : MSHPMassFlowRateHigh = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(1);
4004 246430 : } else if (SpeedNum > 1) {
4005 492860 : state.dataHVACMultiSpdHP->CompOnMassFlow =
4006 246430 : SpeedRatio * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum) +
4007 246430 : (1.0 - SpeedRatio) * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum - 1);
4008 492860 : state.dataHVACMultiSpdHP->CompOnFlowRatio =
4009 246430 : SpeedRatio * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(SpeedNum) +
4010 246430 : (1.0 - SpeedRatio) * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(SpeedNum - 1);
4011 246430 : MSHPMassFlowRateLow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum - 1);
4012 246430 : MSHPMassFlowRateHigh = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum);
4013 : }
4014 533225 : } else if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatCoolMode == ModeOfOperation::CoolingMode) {
4015 533219 : if (SpeedNum == 1) {
4016 327608 : state.dataHVACMultiSpdHP->CompOnMassFlow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum);
4017 327608 : state.dataHVACMultiSpdHP->CompOnFlowRatio = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(SpeedNum);
4018 327608 : MSHPMassFlowRateLow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(1);
4019 327608 : MSHPMassFlowRateHigh = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(1);
4020 205611 : } else if (SpeedNum > 1) {
4021 411222 : state.dataHVACMultiSpdHP->CompOnMassFlow =
4022 205611 : SpeedRatio * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum) +
4023 205611 : (1.0 - SpeedRatio) * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum - 1);
4024 411222 : state.dataHVACMultiSpdHP->CompOnFlowRatio =
4025 205611 : SpeedRatio * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(SpeedNum) +
4026 205611 : (1.0 - SpeedRatio) * state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(SpeedNum - 1);
4027 205611 : MSHPMassFlowRateLow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum - 1);
4028 205611 : MSHPMassFlowRateHigh = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum);
4029 : }
4030 : }
4031 : }
4032 1436165 : InletNode = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirInletNodeNum;
4033 :
4034 : // Set up fan flow rate during compressor off time
4035 1436165 : if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).fanOp == HVAC::FanOp::Continuous && present(SpeedNum)) {
4036 466913 : if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).AirFlowControl == AirflowControl::UseCompressorOnFlow &&
4037 0 : state.dataHVACMultiSpdHP->CompOnMassFlow > 0.0) {
4038 0 : if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).LastMode == ModeOfOperation::HeatingMode) {
4039 0 : state.dataHVACMultiSpdHP->CompOffMassFlow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatMassFlowRate(SpeedNum);
4040 0 : state.dataHVACMultiSpdHP->CompOffFlowRatio = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).HeatingSpeedRatio(SpeedNum);
4041 : } else {
4042 0 : state.dataHVACMultiSpdHP->CompOffMassFlow = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolMassFlowRate(SpeedNum);
4043 0 : state.dataHVACMultiSpdHP->CompOffFlowRatio = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).CoolingSpeedRatio(SpeedNum);
4044 : }
4045 : }
4046 : }
4047 :
4048 1436165 : if (present(SpeedNum)) {
4049 1233787 : if (SpeedNum > 1) {
4050 452057 : AverageUnitMassFlow = state.dataHVACMultiSpdHP->CompOnMassFlow;
4051 452057 : state.dataHVACMultiSpdHP->FanSpeedRatio = state.dataHVACMultiSpdHP->CompOnFlowRatio;
4052 : } else {
4053 781730 : AverageUnitMassFlow =
4054 781730 : (PartLoadRatio * state.dataHVACMultiSpdHP->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataHVACMultiSpdHP->CompOffMassFlow);
4055 781730 : if (state.dataHVACMultiSpdHP->CompOffFlowRatio > 0.0) {
4056 547062 : state.dataHVACMultiSpdHP->FanSpeedRatio = (PartLoadRatio * state.dataHVACMultiSpdHP->CompOnFlowRatio) +
4057 273531 : ((1 - PartLoadRatio) * state.dataHVACMultiSpdHP->CompOffFlowRatio);
4058 : } else {
4059 508199 : state.dataHVACMultiSpdHP->FanSpeedRatio = state.dataHVACMultiSpdHP->CompOnFlowRatio;
4060 : }
4061 : }
4062 : } else {
4063 202378 : AverageUnitMassFlow =
4064 202378 : (PartLoadRatio * state.dataHVACMultiSpdHP->CompOnMassFlow) + ((1 - PartLoadRatio) * state.dataHVACMultiSpdHP->CompOffMassFlow);
4065 202378 : if (state.dataHVACMultiSpdHP->CompOffFlowRatio > 0.0) {
4066 58302 : state.dataHVACMultiSpdHP->FanSpeedRatio =
4067 58302 : (PartLoadRatio * state.dataHVACMultiSpdHP->CompOnFlowRatio) + ((1 - PartLoadRatio) * state.dataHVACMultiSpdHP->CompOffFlowRatio);
4068 : } else {
4069 144076 : state.dataHVACMultiSpdHP->FanSpeedRatio = state.dataHVACMultiSpdHP->CompOnFlowRatio;
4070 : }
4071 : }
4072 :
4073 : //!!LKL Discrepancy with > 0
4074 1436165 : if (state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum).availSched->getCurrentVal() == 0.0) {
4075 47424 : state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
4076 47424 : OnOffAirFlowRatio = 0.0;
4077 : } else {
4078 1388741 : state.dataLoopNodes->Node(InletNode).MassFlowRate = AverageUnitMassFlow;
4079 1388741 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = AverageUnitMassFlow;
4080 1388741 : if (AverageUnitMassFlow > 0.0) {
4081 1072743 : OnOffAirFlowRatio = state.dataHVACMultiSpdHP->CompOnMassFlow / AverageUnitMassFlow;
4082 : } else {
4083 315998 : OnOffAirFlowRatio = 0.0;
4084 : }
4085 : }
4086 1436165 : }
4087 :
4088 1247965 : void CalcNonDXHeatingCoils(EnergyPlusData &state,
4089 : int const MSHeatPumpNum, // multispeed heatpump index
4090 : bool const FirstHVACIteration, // flag for first HVAC iteration in the time step
4091 : Real64 const HeatingLoad, // supplemental coil load to be met by unit (watts)
4092 : HVAC::FanOp const fanOp, // fan operation mode
4093 : Real64 &HeatCoilLoadmet, // Heating Load Met
4094 : ObjexxFCL::Optional<Real64 const> PartLoadFrac)
4095 : {
4096 :
4097 : // SUBROUTINE INFORMATION:
4098 : // AUTHOR Bereket Nigusse, FSEC/UCF
4099 : // DATE WRITTEN January 2012
4100 :
4101 : // PURPOSE OF THIS SUBROUTINE:
4102 : // This subroutine simulates the four non dx heating coil types: Gas, Electric, hot water and steam.
4103 :
4104 : // METHODOLOGY EMPLOYED:
4105 : // Simply calls the different heating coil component. The hot water flow rate matching the coil load
4106 : // is calculated iteratively.
4107 :
4108 : // Locals
4109 : static constexpr std::string_view CurrentModuleObject("AirLoopHVAC:UnitaryHeatPump:AirToAir:MultiSpeed");
4110 :
4111 : // SUBROUTINE PARAMETER DEFINITIONS:
4112 1247965 : Real64 constexpr ErrTolerance(0.001); // convergence limit for hotwater coil
4113 1247965 : int constexpr SolveMaxIter(50);
4114 :
4115 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4116 : Real64 QCoilActual; // actual heating load met
4117 : Real64 mdot; // heating coil steam or hot water mass flow rate
4118 : Real64 MinWaterFlow; // coil minimum hot water mass flow rate, kg/s
4119 : Real64 MaxHotWaterFlow; // coil maximum hot water mass flow rate, kg/s
4120 : Real64 HotWaterMdot; // actual hot water mass flow rate
4121 :
4122 : int HeatCoilType;
4123 : int HeatCoilNum;
4124 : Real64 MaxCoilFluidFlow;
4125 : Real64 SteamCoilHeatingLoad;
4126 : int CoilControlNode;
4127 : int CoilOutletNode;
4128 1247965 : PlantLocation plantLoc{};
4129 :
4130 1247965 : QCoilActual = 0.0;
4131 :
4132 1247965 : auto &MSHeatPump = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
4133 :
4134 1247965 : if (present(PartLoadFrac)) {
4135 0 : HeatCoilType = MSHeatPump.HeatCoilType;
4136 0 : state.dataHVACMultiSpdHP->HeatCoilName = MSHeatPump.HeatCoilName;
4137 0 : HeatCoilNum = MSHeatPump.HeatCoilNum;
4138 0 : MaxCoilFluidFlow = MSHeatPump.MaxCoilFluidFlow;
4139 0 : CoilControlNode = MSHeatPump.CoilControlNode;
4140 0 : CoilOutletNode = MSHeatPump.CoilOutletNode;
4141 0 : plantLoc = MSHeatPump.plantLoc;
4142 : } else {
4143 1247965 : HeatCoilType = MSHeatPump.SuppHeatCoilType;
4144 1247965 : state.dataHVACMultiSpdHP->HeatCoilName = MSHeatPump.SuppHeatCoilName;
4145 1247965 : HeatCoilNum = MSHeatPump.SuppHeatCoilNum;
4146 1247965 : MaxCoilFluidFlow = MSHeatPump.MaxSuppCoilFluidFlow;
4147 1247965 : CoilControlNode = MSHeatPump.SuppCoilControlNode;
4148 1247965 : CoilOutletNode = MSHeatPump.SuppCoilOutletNode;
4149 1247965 : plantLoc = MSHeatPump.SuppPlantLoc;
4150 : }
4151 :
4152 1247965 : MSHeatPump.HotWaterPlantLoc = plantLoc;
4153 1247965 : MSHeatPump.HotWaterCoilControlNode = CoilControlNode;
4154 1247965 : MSHeatPump.HotWaterCoilOutletNode = CoilOutletNode;
4155 1247965 : MSHeatPump.HotWaterCoilName = state.dataHVACMultiSpdHP->HeatCoilName;
4156 1247965 : MSHeatPump.HotWaterCoilNum = HeatCoilNum;
4157 :
4158 1247965 : if (HeatingLoad > HVAC::SmallLoad) {
4159 :
4160 161344 : switch (HeatCoilType) {
4161 161344 : case SuppHeatingCoilGas:
4162 : case SuppHeatingCoilElec: {
4163 645376 : HeatingCoils::SimulateHeatingCoilComponents(
4164 484032 : state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatingLoad, HeatCoilNum, QCoilActual, true, fanOp);
4165 161344 : } break;
4166 0 : case HVAC::Coil_HeatingWater: {
4167 0 : if (present(PartLoadFrac)) {
4168 0 : MaxHotWaterFlow = MaxCoilFluidFlow * PartLoadFrac;
4169 0 : PlantUtilities::SetComponentFlowRate(state, MaxHotWaterFlow, CoilControlNode, CoilOutletNode, plantLoc);
4170 0 : WaterCoils::SimulateWaterCoilComponents(
4171 0 : state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, QCoilActual, fanOp);
4172 : } else {
4173 0 : MaxHotWaterFlow = MaxCoilFluidFlow;
4174 0 : PlantUtilities::SetComponentFlowRate(state, MaxHotWaterFlow, CoilControlNode, CoilOutletNode, plantLoc);
4175 0 : WaterCoils::SimulateWaterCoilComponents(
4176 0 : state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, QCoilActual, fanOp);
4177 0 : if (QCoilActual > (HeatingLoad + HVAC::SmallLoad)) {
4178 : // control water flow to obtain output matching HeatingLoad
4179 0 : int SolFlag = 0;
4180 0 : MinWaterFlow = 0.0;
4181 0 : auto f = [&state, MSHeatPumpNum, FirstHVACIteration, HeatingLoad](Real64 const HWFlow) {
4182 : // Calculates residual function (QCoilActual - SupHeatCoilLoad) / SupHeatCoilLoad
4183 : // coil actual output depends on the hot water flow rate which is varied to minimize the residual.
4184 0 : Real64 targetHeatingCoilLoad = HeatingLoad;
4185 0 : Real64 calcHeatingCoilLoad = targetHeatingCoilLoad;
4186 0 : Real64 mdot = HWFlow;
4187 0 : auto &hp = state.dataHVACMultiSpdHP->MSHeatPump(MSHeatPumpNum);
4188 0 : PlantUtilities::SetComponentFlowRate(
4189 0 : state, mdot, hp.HotWaterCoilControlNode, hp.HotWaterCoilOutletNode, hp.HotWaterPlantLoc);
4190 : // simulate the hot water supplemental heating coil
4191 0 : WaterCoils::SimulateWaterCoilComponents(
4192 0 : state, hp.HotWaterCoilName, FirstHVACIteration, hp.HotWaterCoilNum, calcHeatingCoilLoad, hp.fanOp);
4193 0 : if (targetHeatingCoilLoad != 0.0) {
4194 0 : return (calcHeatingCoilLoad - targetHeatingCoilLoad) / targetHeatingCoilLoad;
4195 : } else { // Autodesk:Return Condition added to assure return value is set
4196 0 : return 0.0;
4197 : }
4198 0 : };
4199 0 : General::SolveRoot(state, ErrTolerance, SolveMaxIter, SolFlag, HotWaterMdot, f, MinWaterFlow, MaxHotWaterFlow);
4200 0 : if (SolFlag == -1) {
4201 0 : if (MSHeatPump.HotWaterCoilMaxIterIndex == 0) {
4202 0 : ShowWarningMessage(state,
4203 0 : format("CalcNonDXHeatingCoils: Hot water coil control failed for {}=\"{}\"",
4204 : CurrentModuleObject,
4205 0 : MSHeatPump.Name));
4206 0 : ShowContinueErrorTimeStamp(state, "");
4207 0 : ShowContinueError(state,
4208 0 : format(" Iteration limit [{}] exceeded in calculating hot water mass flow rate", SolveMaxIter));
4209 : }
4210 0 : ShowRecurringWarningErrorAtEnd(
4211 : state,
4212 0 : format("CalcNonDXHeatingCoils: Hot water coil control failed (iteration limit [{}]) for {}=\"{}",
4213 : SolveMaxIter,
4214 : CurrentModuleObject,
4215 0 : MSHeatPump.Name),
4216 0 : MSHeatPump.HotWaterCoilMaxIterIndex);
4217 0 : } else if (SolFlag == -2) {
4218 0 : if (MSHeatPump.HotWaterCoilMaxIterIndex2 == 0) {
4219 0 : ShowWarningMessage(state,
4220 0 : format("CalcNonDXHeatingCoils: Hot water coil control failed (maximum flow limits) for {}=\"{}\"",
4221 : CurrentModuleObject,
4222 0 : MSHeatPump.Name));
4223 0 : ShowContinueErrorTimeStamp(state, "");
4224 0 : ShowContinueError(state, "...Bad hot water maximum flow rate limits");
4225 0 : ShowContinueError(state, format("...Given minimum water flow rate={:.3R} kg/s", MinWaterFlow));
4226 0 : ShowContinueError(state, format("...Given maximum water flow rate={:.3R} kg/s", MaxHotWaterFlow));
4227 : }
4228 0 : ShowRecurringWarningErrorAtEnd(state,
4229 0 : "CalcNonDXHeatingCoils: Hot water coil control failed (flow limits) for " +
4230 0 : std::string{CurrentModuleObject} + "=\"" + MSHeatPump.Name + "\"",
4231 0 : MSHeatPump.HotWaterCoilMaxIterIndex2,
4232 : MaxHotWaterFlow,
4233 : MinWaterFlow,
4234 : _,
4235 : "[kg/s]",
4236 : "[kg/s]");
4237 : }
4238 : // simulate hot water supplemental heating coil
4239 0 : WaterCoils::SimulateWaterCoilComponents(
4240 0 : state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, QCoilActual, fanOp);
4241 : }
4242 : }
4243 0 : } break;
4244 0 : case HVAC::Coil_HeatingSteam: {
4245 0 : if (present(PartLoadFrac)) {
4246 0 : mdot = MSHeatPump.MaxCoilFluidFlow * PartLoadFrac;
4247 0 : SteamCoilHeatingLoad = HeatingLoad * PartLoadFrac;
4248 : } else {
4249 0 : mdot = MSHeatPump.MaxCoilFluidFlow;
4250 0 : SteamCoilHeatingLoad = HeatingLoad;
4251 : }
4252 0 : PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
4253 : // simulate steam supplemental heating coil
4254 0 : SteamCoils::SimulateSteamCoilComponents(
4255 0 : state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, SteamCoilHeatingLoad, QCoilActual, fanOp);
4256 0 : } break;
4257 0 : default:
4258 0 : break;
4259 : }
4260 :
4261 : } else { // end of IF (HeatingLoad > SmallLoad) THEN
4262 :
4263 1086621 : switch (HeatCoilType) {
4264 1086621 : case SuppHeatingCoilGas:
4265 : case SuppHeatingCoilElec: {
4266 4346484 : HeatingCoils::SimulateHeatingCoilComponents(
4267 3259863 : state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatingLoad, HeatCoilNum, QCoilActual, true, fanOp);
4268 1086621 : } break;
4269 0 : case HVAC::Coil_HeatingWater: {
4270 0 : mdot = 0.0;
4271 0 : PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
4272 0 : WaterCoils::SimulateWaterCoilComponents(
4273 0 : state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, QCoilActual, fanOp);
4274 0 : } break;
4275 0 : case HVAC::Coil_HeatingSteam: {
4276 0 : mdot = 0.0;
4277 0 : PlantUtilities::SetComponentFlowRate(state, mdot, CoilControlNode, CoilOutletNode, plantLoc);
4278 : // simulate the steam supplemental heating coil
4279 0 : SteamCoils::SimulateSteamCoilComponents(
4280 0 : state, state.dataHVACMultiSpdHP->HeatCoilName, FirstHVACIteration, HeatCoilNum, HeatingLoad, QCoilActual, fanOp);
4281 0 : } break;
4282 0 : default:
4283 0 : break;
4284 : }
4285 : }
4286 1247965 : HeatCoilLoadmet = QCoilActual;
4287 1247965 : }
4288 :
4289 : } // namespace HVACMultiSpeedHeatPump
4290 :
4291 : } // namespace EnergyPlus
|