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