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 : // ObjexxFCL Headers
49 : #include <ObjexxFCL/Array.functions.hh>
50 : #include <ObjexxFCL/Fmath.hh>
51 :
52 : // EnergyPlus Headers
53 : #include <EnergyPlus/Autosizing/Base.hh>
54 : #include <EnergyPlus/BranchNodeConnections.hh>
55 : #include <EnergyPlus/Data/EnergyPlusData.hh>
56 : #include <EnergyPlus/DataContaminantBalance.hh>
57 : #include <EnergyPlus/DataDefineEquip.hh>
58 : #include <EnergyPlus/DataEnvironment.hh>
59 : #include <EnergyPlus/DataHVACGlobals.hh>
60 : #include <EnergyPlus/DataHeatBalance.hh>
61 : #include <EnergyPlus/DataLoopNode.hh>
62 : #include <EnergyPlus/DataSizing.hh>
63 : #include <EnergyPlus/DataZoneEquipment.hh>
64 : #include <EnergyPlus/General.hh>
65 : #include <EnergyPlus/GeneralRoutines.hh>
66 : #include <EnergyPlus/GlobalNames.hh>
67 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
68 : #include <EnergyPlus/NodeInputManager.hh>
69 : #include <EnergyPlus/Psychrometrics.hh>
70 : #include <EnergyPlus/ScheduleManager.hh>
71 : #include <EnergyPlus/UnitarySystem.hh>
72 : #include <EnergyPlus/UtilityRoutines.hh>
73 : #include <EnergyPlus/ZoneEquipmentManager.hh>
74 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
75 :
76 : namespace EnergyPlus::DataZoneEquipment {
77 :
78 : // MODULE INFORMATION
79 : // AUTHOR: Russ Taylor
80 : // DATE WRITTEN: June 1998
81 :
82 : // PURPOSE OF THIS MODULE:
83 : // This module contains variable declarations for zone equipment configuration data
84 :
85 : Array1D_string const cValidSysAvailManagerCompTypes(NumValidSysAvailZoneComponents,
86 : {"ZoneHVAC:FourPipeFanCoil",
87 : "ZoneHVAC:PackagedTerminalHeatPump",
88 : "ZoneHVAC:PackagedTerminalAirConditioner",
89 : "ZoneHVAC:WaterToAirHeatPump",
90 : "ZoneHVAC:WindowAirConditioner",
91 : "ZoneHVAC:UnitHeater",
92 : "ZoneHVAC:UnitVentilator",
93 : "ZoneHVAC:EnergyRecoveryVentilator",
94 : "ZoneHVAC:VentilatedSlab",
95 : "ZoneHVAC:OutdoorAirUnit",
96 : "ZoneHVAC:TerminalUnit:VariableRefrigerantFlow",
97 : "ZoneHVAC:IdealLoadsAirSystem",
98 : "ZoneHVAC:EvaporativeCoolerUnit",
99 : "ZoneHVAC:HybridUnitaryHVAC"});
100 :
101 : constexpr std::array<std::string_view, static_cast<int>(ZoneEquipType::Num)> zoneEquipTypeNamesUC = {
102 : "DUMMY", // DUMMY,
103 :
104 : "ZONEHVAC:FOURPIPEFANCOIL", // FanCoilFourPipe
105 : "ZONEHVAC:PACKAGEDTERMINALHEATPUMP", // PackagedTerminalHeatPump
106 : "ZONEHVAC:PACKAGEDTERMINALAIRCONDITIONER", // PackagedTerminalAirConditioner
107 : "ZONEHVAC:WATERTOAIRHEATPUMP", // PackagedTerminalHeatPumpWaterToAir
108 : "ZONEHVAC:WINDOWAIRCONDITIONER", // WindowAirConditioner
109 : "ZONEHVAC:UNITHEATER", // UnitHeater
110 : "ZONEHVAC:UNITVENTILATOR", // UnitVentilator
111 : "ZONEHVAC:ENERGYRECOVERYVENTILATOR", // EnergyRecoveryVentilator
112 : "ZONEHVAC:VENTILATEDSLAB", // VentilatedSlab
113 : "ZONEHVAC:OUTDOORAIRUNIT", // OutdoorAirUnit
114 : "ZONEHVAC:TERMINALUNIT:VARIABLEREFRIGERANTFLOW", // VariableRefrigerantFlowTerminal
115 : "ZONEHVAC:IDEALLOADSAIRSYSTEM", // IdealLoadsAirSystem
116 : "ZONEHVAC:EVAPORATIVECOOLERUNIT", // EvaporativeCooler
117 : "ZONEHVAC:HYBRIDUNITARYHVAC", // HybridEvaporativeCooler,
118 :
119 : // last zone equipment type to use zone availability manager. The above list must not change or
120 : // NumValidSysAvailZoneComponents must also change.
121 :
122 : "ZONEHVAC:AIRDISTRIBUTIONUNIT", // AirDistributionUnit
123 : "ZONEHVAC:BASEBOARD:CONVECTIVE:WATER", // BaseboardWaterConvective
124 : "ZONEHVAC:BASEBOARD:CONVECTIVE:ELECTRIC", // BaseboardElectricConvective
125 : "ZONEHVAC:BASEBOARD:RADIANTCONVECTIVE:STEAM", // BaseboardSteam
126 : "ZONEHVAC:BASEBOARD:RADIANTCONVECTIVE:WATER", // BaseboardWater
127 : "ZONEHVAC:BASEBOARD:RADIANTCONVECTIVE:ELECTRIC", // BaseboardElectric
128 : "ZONEHVAC:HIGHTEMPERATURERADIANT", // HighTempRadiant
129 : "ZONEHVAC:LOWTEMPERATURERADIANT:VARIABLEFLOW", // LowTempRadiant
130 : "FAN:ZONEEXHAUST", // ExhaustFan
131 : "HEATEXCHANGER:AIRTOAIR:FLATPLATE", // HeatExchanger
132 : "WATERHEATER:HEATPUMP:PUMPEDCONDENSER", // HeatPumpWaterHeater
133 : "ZONEHVAC:DEHUMIDIFIER:DX", // DXDehumidifier
134 : "ZONEHVAC:REFRIGERATIONCHILLERSET", // RefrigerationAirChillerSet
135 : "ZONEHVAC:FORCEDAIR:USERDEFINED", // UserDefinedVACForcedAir
136 : "ZONEHVAC:COOLINGPANEL:RADIANTCONVECTIVE:WATER", // CoolingPanel
137 : "AIRLOOPHVAC:UNITARYSYSTEM", // UnitarySystem
138 : "AIRTERMINAL:DUALDUCT:CONSTANTVOLUME", // AirTerminalDualDuctConstantVolume
139 : "AIRTERMINAL:DUALDUCT:VAV", // AirTerminalDualDuctVAV
140 : "AIRTERMINAL:SINGLEDUCT:CONSTANTVOLUME:REHEAT", // AirTerminalSingleDuctConstantVolumeReheat
141 : "AIRTERMINAL:SINGLEDUCT:CONSTANTVOLUME:NOREHEAT", // AirTerminalSingleDuctConstantVolumeNoReheat
142 : "AIRTERMINAL:SINGLEDUCT:VAV:REHEAT", // AirTerminalSingleDuctVAVReheat
143 : "AIRTERMINAL:SINGLEDUCT:VAV:NOREHEAT", // AirTerminalSingleDuctVAVNoReheat
144 : "AIRTERMINAL:SINGLEDUCT:SERIESPIU:REHEAT", // AirTerminalSingleDuctSeriesPIUReheat
145 : "AIRTERMINAL:SINGLEDUCT:PARALLELPIU:REHEAT", // AirTerminalSingleDuctParallelPIUReheat
146 : "AIRTERMINAL:SINGLEDUCT:CONSTANTVOLUME:FOURPIPEINDUCTION", // AirTerminalSingleDuctCAVFourPipeInduction
147 : "AIRTERMINAL:SINGLEDUCT:VAV:REHEAT:VARIABLESPEEDFAN", // AirTerminalSingleDuctVAVReheatVariableSpeedFan
148 : "AIRTERMINAL:SINGLEDUCT:VAV:HEATANDCOOL:REHEAT", // AirTerminalSingleDuctVAVHeatAndCoolReheat
149 : "AIRTERMINAL:SINGLEDUCT:VAV:HEATANDCOOL:NOREHEAT", // AirTerminalSingleDuctVAVHeatAndCoolNoReheat
150 : "AIRTERMINAL:SINGLEDUCT:CONSTANTVOLUME:COOLEDBEAM", // AirTerminalSingleDuctConstantVolumeCooledBeam
151 : "AIRTERMINAL:DUALDUCT:VAV:OUTDOORAIR", // AirTerminalDualDuctVAVOutdoorAir
152 : "AIRLOOPHVACRETURNAIR" // AirLoopHVACReturnAir
153 : };
154 :
155 : static constexpr std::array<std::string_view, static_cast<int>(LoadDist::Num)> LoadDistNamesUC = {
156 : "SEQUENTIALLOAD", "UNIFORMLOAD", "UNIFORMPLR", "SEQUENTIALUNIFORMPLR"};
157 :
158 : static constexpr std::array<std::string_view, static_cast<int>(ZoneEquipTstatControl::Num)> zoneEquipTstatControlNamesUC = {
159 : "SINGLESPACE", "MAXIMUM", "IDEAL"};
160 :
161 : static constexpr std::array<std::string_view, static_cast<int>(SpaceEquipSizingBasis::Num)> spaceEquipSizingBasisNamesUC = {
162 : "DESIGNCOOLINGLOAD", "DESIGNHEATINGLOAD", "FLOORAREA", "VOLUME", "PERIMETERLENGTH"};
163 :
164 796 : void GetZoneEquipmentData(EnergyPlusData &state)
165 : {
166 :
167 : // SUBROUTINE INFORMATION:
168 : // AUTHOR Russ Taylor
169 : // DATE WRITTEN June 1997
170 : // MODIFIED Aug 2003, FCW: set ZoneEquipConfig number for each zone
171 :
172 : // PURPOSE OF THIS SUBROUTINE:
173 : // Get all the system related equipment which may be attached to
174 : // a zone
175 :
176 : // Using/Aliasing
177 : using NodeInputManager::CheckUniqueNodeNames;
178 : using NodeInputManager::CheckUniqueNodeNumbers;
179 : using NodeInputManager::EndUniqueNodeCheck;
180 : using NodeInputManager::GetNodeNums;
181 : using NodeInputManager::GetOnlySingleNode;
182 : using NodeInputManager::InitUniqueNodeCheck;
183 : using namespace DataLoopNode;
184 : using namespace ScheduleManager;
185 :
186 : // SUBROUTINE PARAMETER DEFINITIONS:
187 : static constexpr std::string_view RoutineName("GetZoneEquipmentData: "); // include trailing blank space
188 :
189 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
190 : int NumAlphas;
191 : int NumNums;
192 : int IOStat;
193 796 : Array1D_string AlphArray;
194 796 : Array1D<Real64> NumArray;
195 : int MaxAlphas;
196 : int MaxNums;
197 : int NumParams;
198 796 : Array1D_int NodeNums;
199 : bool IsNotOK; // Flag to verify nam
200 796 : std::string CurrentModuleObject; // Object type for getting and error messages
201 796 : Array1D_string cAlphaFields; // Alpha field names
202 796 : Array1D_string cNumericFields; // Numeric field names
203 796 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
204 796 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
205 :
206 : struct EquipListAudit
207 : {
208 : // Members
209 : std::string ObjectType;
210 : std::string ObjectName;
211 : int OnListNum;
212 :
213 : // Default Constructor
214 698 : EquipListAudit() : OnListNum(0)
215 : {
216 698 : }
217 : };
218 : // Object Data
219 796 : Array1D<EquipListAudit> ZoneEquipListAcct;
220 :
221 : // Look in the input file for zones with air loop and zone equipment attached
222 :
223 796 : int numControlledZones = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:EquipmentConnections");
224 796 : int numControlledSpaces = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "SpaceHVAC:EquipmentConnections");
225 796 : state.dataZoneEquip->NumOfZoneEquipLists = state.dataInputProcessing->inputProcessor->getNumObjectsFound(
226 : state, "ZoneHVAC:EquipmentList"); // Look for lists of equipment data - there should
227 : // be as many of these as there are controlled zones
228 796 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "NodeList", NumParams, NumAlphas, NumNums);
229 796 : NodeNums.dimension(NumParams, 0);
230 796 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "ZoneHVAC:EquipmentList", NumParams, NumAlphas, NumNums);
231 796 : MaxAlphas = NumAlphas;
232 796 : MaxNums = NumNums;
233 796 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "ZoneHVAC:EquipmentConnections", NumParams, NumAlphas, NumNums);
234 796 : MaxAlphas = max(MaxAlphas, NumAlphas);
235 796 : MaxNums = max(MaxNums, NumNums);
236 796 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "SpaceHVAC:EquipmentConnections", NumParams, NumAlphas, NumNums);
237 796 : MaxAlphas = max(MaxAlphas, NumAlphas);
238 796 : MaxNums = max(MaxNums, NumNums);
239 796 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "AirLoopHVAC:SupplyPath", NumParams, NumAlphas, NumNums);
240 796 : MaxAlphas = max(MaxAlphas, NumAlphas);
241 796 : MaxNums = max(MaxNums, NumNums);
242 796 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "AirLoopHVAC:ReturnPath", NumParams, NumAlphas, NumNums);
243 796 : MaxAlphas = max(MaxAlphas, NumAlphas);
244 796 : MaxNums = max(MaxNums, NumNums);
245 796 : AlphArray.allocate(MaxAlphas);
246 796 : NumArray.dimension(MaxNums, 0.0);
247 796 : cAlphaFields.allocate(MaxAlphas);
248 796 : cNumericFields.allocate(MaxNums);
249 796 : lAlphaBlanks.dimension(MaxAlphas, true);
250 796 : lNumericBlanks.dimension(MaxNums, true);
251 :
252 796 : if (!allocated(state.dataZoneEquip->SupplyAirPath)) {
253 : // Look for and read in the air supply path
254 : // component (splitters) information for each zone
255 796 : state.dataZoneEquip->NumSupplyAirPaths = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirLoopHVAC:SupplyPath");
256 796 : state.dataZoneEquip->SupplyAirPath.allocate(state.dataZoneEquip->NumSupplyAirPaths);
257 : }
258 :
259 796 : if (!allocated(state.dataZoneEquip->ReturnAirPath)) {
260 : // Look for and read in the air return path
261 : // component (mixers & plenums) information for each zone
262 796 : state.dataZoneEquip->NumReturnAirPaths = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirLoopHVAC:ReturnPath");
263 796 : state.dataZoneEquip->ReturnAirPath.allocate(state.dataZoneEquip->NumReturnAirPaths);
264 : }
265 :
266 796 : state.dataZoneEquip->ZoneEquipConfig.allocate(state.dataGlobal->NumOfZones); // Allocate the array containing the configuration data for each zone
267 796 : if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) {
268 4 : state.dataZoneEquip->spaceEquipConfig.allocate(
269 2 : state.dataGlobal->numSpaces); // Allocate the array containing the configuration data for each space
270 : }
271 796 : state.dataZoneEquip->ZoneEquipList.allocate(state.dataGlobal->NumOfZones);
272 796 : state.dataZoneEquip->ZoneEquipAvail.dimension(state.dataGlobal->NumOfZones, Avail::Status::NoAction);
273 796 : state.dataZoneEquip->UniqueZoneEquipListNames.reserve(state.dataGlobal->NumOfZones);
274 :
275 796 : if (state.dataZoneEquip->NumOfZoneEquipLists != numControlledZones) {
276 0 : ShowSevereError(state,
277 0 : format("{}Number of Zone Equipment lists [{}] not equal Number of Controlled Zones [{}]",
278 : RoutineName,
279 0 : state.dataZoneEquip->NumOfZoneEquipLists,
280 : numControlledZones));
281 0 : ShowContinueError(state, "..Each Controlled Zone [ZoneHVAC:EquipmentConnections] must have a corresponding (unique) ZoneHVAC:EquipmentList");
282 0 : ShowFatalError(state, "GetZoneEquipment: Incorrect number of zone equipment lists");
283 : }
284 :
285 796 : if (numControlledZones > state.dataGlobal->NumOfZones) {
286 0 : ShowSevereError(state,
287 0 : format("{}Number of Controlled Zone objects [{}] greater than Number of Zones [{}]",
288 : RoutineName,
289 : numControlledZones,
290 0 : state.dataGlobal->NumOfZones));
291 0 : ShowFatalError(state, format("{}Too many ZoneHVAC:EquipmentConnections objects.", RoutineName));
292 : }
293 :
294 796 : InitUniqueNodeCheck(state, "ZoneHVAC:EquipmentConnections");
295 :
296 796 : int overallEquipCount = 0;
297 796 : int locTermUnitSizingCounter = 0; // will increment for every zone inlet node
298 :
299 : // auto &Zone(state.dataHeatBal->Zone);
300 :
301 5115 : for (int controlledZoneLoop = 1; controlledZoneLoop <= numControlledZones; ++controlledZoneLoop) {
302 4319 : CurrentModuleObject = "ZoneHVAC:EquipmentConnections";
303 4319 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
304 : CurrentModuleObject,
305 : controlledZoneLoop,
306 : AlphArray,
307 : NumAlphas,
308 : NumArray,
309 : NumNums,
310 : IOStat,
311 : lNumericBlanks,
312 : lAlphaBlanks,
313 : cAlphaFields,
314 : cNumericFields); // Get Equipment | data for one zone
315 :
316 4319 : int zoneOrSpaceNum = Util::FindItemInList(AlphArray(1), state.dataHeatBal->Zone);
317 4319 : std::string_view zsString = "Zone";
318 :
319 4319 : if (zoneOrSpaceNum == 0) {
320 0 : ShowSevereError(state, format("{}{}: {}=\"{}\"", RoutineName, CurrentModuleObject, cAlphaFields(1), AlphArray(1)));
321 0 : ShowContinueError(state,
322 0 : format("..Requested Controlled {} not among {}s, remaining items for this object not processed.", zsString, zsString));
323 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
324 0 : continue;
325 : }
326 4319 : bool isControlledAlready = state.dataHeatBal->Zone(zoneOrSpaceNum).IsControlled;
327 4319 : if (isControlledAlready) {
328 0 : ShowSevereError(state, format("{}{}: {}=\"{}\"", RoutineName, CurrentModuleObject, cAlphaFields(1), AlphArray(1)));
329 0 : ShowContinueError(state,
330 0 : format("..Duplicate Controlled {} entered, only one {} per {} is allowed.", zsString, CurrentModuleObject, zsString));
331 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
332 0 : continue;
333 : }
334 4319 : state.dataHeatBal->Zone(zoneOrSpaceNum).IsControlled = true;
335 4319 : bool isSpace = false;
336 4319 : processZoneEquipmentInput(state,
337 : CurrentModuleObject,
338 : zoneOrSpaceNum,
339 : isSpace,
340 : locTermUnitSizingCounter,
341 : overallEquipCount,
342 4319 : state.dataZoneEquip->ZoneEquipConfig(zoneOrSpaceNum),
343 : AlphArray,
344 : cAlphaFields,
345 : lAlphaBlanks,
346 : NodeNums);
347 4319 : state.dataHeatBal->Zone(zoneOrSpaceNum).SystemZoneNodeNumber = state.dataZoneEquip->ZoneEquipConfig(zoneOrSpaceNum).ZoneNode;
348 : } // end loop over controlled zones
349 799 : for (int controlledSpaceLoop = 1; controlledSpaceLoop <= numControlledSpaces; ++controlledSpaceLoop) {
350 3 : CurrentModuleObject = "SpaceHVAC:EquipmentConnections";
351 3 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
352 : CurrentModuleObject,
353 : controlledSpaceLoop,
354 : AlphArray,
355 : NumAlphas,
356 : NumArray,
357 : NumNums,
358 : IOStat,
359 : lNumericBlanks,
360 : lAlphaBlanks,
361 : cAlphaFields,
362 : cNumericFields); // Get Equipment | data for one zone
363 :
364 3 : int zoneOrSpaceNum = Util::FindItemInList(AlphArray(1), state.dataHeatBal->space);
365 3 : std::string_view zsString = "Space";
366 :
367 3 : if (zoneOrSpaceNum == 0) {
368 0 : ShowSevereError(state, format("{}{}: {}=\"{}\"", RoutineName, CurrentModuleObject, cAlphaFields(1), AlphArray(1)));
369 0 : ShowContinueError(state,
370 0 : format("..Requested Controlled {} not among {}s, remaining items for this object not processed.", zsString, zsString));
371 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
372 0 : continue;
373 : }
374 3 : bool isControlledAlready = state.dataHeatBal->space(zoneOrSpaceNum).IsControlled;
375 3 : if (isControlledAlready) {
376 0 : ShowSevereError(state, format("{}{}: {}=\"{}\"", RoutineName, CurrentModuleObject, cAlphaFields(1), AlphArray(1)));
377 0 : ShowContinueError(state,
378 0 : format("..Duplicate Controlled {} entered, only one {} per {} is allowed.", zsString, CurrentModuleObject, zsString));
379 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
380 0 : continue;
381 : }
382 3 : state.dataHeatBal->space(zoneOrSpaceNum).IsControlled = true;
383 3 : bool isSpace = true;
384 3 : processZoneEquipmentInput(state,
385 : CurrentModuleObject,
386 : zoneOrSpaceNum,
387 : isSpace,
388 : locTermUnitSizingCounter,
389 : overallEquipCount,
390 3 : state.dataZoneEquip->spaceEquipConfig(zoneOrSpaceNum),
391 : AlphArray,
392 : cAlphaFields,
393 : lAlphaBlanks,
394 : NodeNums);
395 3 : state.dataHeatBal->space(zoneOrSpaceNum).SystemZoneNodeNumber = state.dataZoneEquip->spaceEquipConfig(zoneOrSpaceNum).ZoneNode;
396 : } // end loop over controlled spaces
397 :
398 796 : if (state.dataHeatBal->doSpaceHeatBalanceSizing || state.dataHeatBal->doSpaceHeatBalanceSimulation) {
399 : // Auto-assign the system node name for spaces in controlled zones that do not have a SpaceHVAC:EquipmentConnections input
400 14 : for (auto &thisZone : state.dataHeatBal->Zone) {
401 12 : if (!thisZone.IsControlled) continue;
402 10 : int spaceCount = 0;
403 24 : for (int spaceNum : thisZone.spaceIndexes) {
404 14 : ++spaceCount;
405 14 : if (state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber == 0) {
406 11 : std::string spaceNodeName = format("{}-Space {}", state.dataLoopNodes->NodeID(thisZone.SystemZoneNodeNumber), spaceCount);
407 11 : int spaceNodeNum = GetOnlySingleNode(state,
408 : spaceNodeName,
409 11 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
410 : DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections,
411 11 : AlphArray(1),
412 : DataLoopNode::NodeFluidType::Air,
413 : DataLoopNode::ConnectionType::ZoneNode,
414 : NodeInputManager::CompFluidStream::Primary,
415 : DataLoopNode::ObjectIsNotParent);
416 11 : state.dataHeatBal->space(spaceNum).SystemZoneNodeNumber = spaceNodeNum;
417 11 : }
418 10 : }
419 2 : }
420 : }
421 : // Allocate TermUnitSizing array and set zone number
422 796 : if (locTermUnitSizingCounter > 0) {
423 672 : state.dataSize->NumAirTerminalUnits = locTermUnitSizingCounter;
424 672 : state.dataSize->TermUnitSizing.allocate(state.dataSize->NumAirTerminalUnits);
425 5476 : for (int loopZoneNum = 1; loopZoneNum <= state.dataGlobal->NumOfZones; ++loopZoneNum) {
426 : {
427 4804 : auto &thisZoneEqConfig = state.dataZoneEquip->ZoneEquipConfig(loopZoneNum);
428 9277 : for (int loopNodeNum = 1; loopNodeNum <= thisZoneEqConfig.NumInletNodes; ++loopNodeNum) {
429 4473 : state.dataSize->TermUnitSizing(thisZoneEqConfig.AirDistUnitCool(loopNodeNum).TermUnitSizingIndex).CtrlZoneNum = loopZoneNum;
430 : }
431 : }
432 : }
433 : }
434 796 : if (state.dataZoneEquip->GetZoneEquipmentDataErrorsFound) {
435 0 : ShowWarningError(state, format("{}{}, duplicate items NOT CHECKED due to previous errors.", RoutineName, CurrentModuleObject));
436 0 : overallEquipCount = 0;
437 : }
438 796 : if (overallEquipCount > 0) {
439 698 : ZoneEquipListAcct.allocate(overallEquipCount);
440 698 : overallEquipCount = 0;
441 5017 : for (int Loop1 = 1; Loop1 <= numControlledZones; ++Loop1) {
442 8815 : for (int Loop2 = 1; Loop2 <= state.dataZoneEquip->ZoneEquipList(Loop1).NumOfEquipTypes; ++Loop2) {
443 4496 : ++overallEquipCount;
444 4496 : ZoneEquipListAcct(overallEquipCount).ObjectType = state.dataZoneEquip->ZoneEquipList(Loop1).EquipType(Loop2);
445 4496 : ZoneEquipListAcct(overallEquipCount).ObjectName = state.dataZoneEquip->ZoneEquipList(Loop1).EquipName(Loop2);
446 4496 : ZoneEquipListAcct(overallEquipCount).OnListNum = Loop1;
447 : }
448 : }
449 : // Now check for uniqueness
450 5194 : for (int Loop1 = 1; Loop1 <= overallEquipCount; ++Loop1) {
451 76422 : for (int Loop2 = Loop1 + 1; Loop2 <= overallEquipCount; ++Loop2) {
452 124818 : if (ZoneEquipListAcct(Loop1).ObjectType != ZoneEquipListAcct(Loop2).ObjectType ||
453 52892 : ZoneEquipListAcct(Loop1).ObjectName != ZoneEquipListAcct(Loop2).ObjectName)
454 71926 : continue;
455 : // Duplicated -- not allowed
456 0 : ShowSevereError(state, format("{}{}, duplicate items in ZoneHVAC:EquipmentList.", RoutineName, CurrentModuleObject));
457 0 : ShowContinueError(state,
458 0 : format("Equipment: Type={}, Name={}", ZoneEquipListAcct(Loop1).ObjectType, ZoneEquipListAcct(Loop1).ObjectName));
459 0 : ShowContinueError(state,
460 0 : format("Found on List=\"{}\".", state.dataZoneEquip->ZoneEquipList(ZoneEquipListAcct(Loop1).OnListNum).Name));
461 0 : ShowContinueError(
462 : state,
463 0 : format("Equipment Duplicated on List=\"{}\".", state.dataZoneEquip->ZoneEquipList(ZoneEquipListAcct(Loop2).OnListNum).Name));
464 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
465 : }
466 : }
467 698 : ZoneEquipListAcct.deallocate();
468 : }
469 :
470 : // map ZoneEquipConfig%EquipListIndex to ZoneEquipList%Name
471 :
472 5852 : for (int ControlledZoneLoop = 1; ControlledZoneLoop <= state.dataGlobal->NumOfZones; ++ControlledZoneLoop) {
473 5056 : state.dataZoneEquip->GetZoneEquipmentDataFound = Util::FindItemInList(
474 5056 : state.dataZoneEquip->ZoneEquipList(ControlledZoneLoop).Name, state.dataZoneEquip->ZoneEquipConfig, &EquipConfiguration::EquipListName);
475 5056 : if (state.dataZoneEquip->GetZoneEquipmentDataFound > 0)
476 5056 : state.dataZoneEquip->ZoneEquipConfig(state.dataZoneEquip->GetZoneEquipmentDataFound).EquipListIndex = ControlledZoneLoop;
477 : } // end loop over controlled zones
478 :
479 796 : EndUniqueNodeCheck(state, "ZoneHVAC:EquipmentConnections");
480 :
481 796 : auto &ip = state.dataInputProcessing->inputProcessor;
482 :
483 796 : CurrentModuleObject = "SpaceHVAC:ZoneEquipmentSplitter";
484 796 : auto instances = ip->epJSON.find(CurrentModuleObject);
485 796 : if (instances != ip->epJSON.end()) {
486 1 : auto const &objectSchemaProps = ip->getObjectSchemaProps(state, CurrentModuleObject);
487 1 : auto &instancesValue = instances.value();
488 1 : int numZoneEqSplitters = instancesValue.size();
489 1 : state.dataZoneEquip->zoneEquipSplitter.resize(numZoneEqSplitters);
490 1 : int zeqSplitterNum = -1;
491 2 : for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
492 1 : ++zeqSplitterNum;
493 1 : auto const &objectFields = instance.value();
494 1 : auto &thisZeqSplitter = state.dataZoneEquip->zoneEquipSplitter[zeqSplitterNum];
495 1 : thisZeqSplitter.Name = Util::makeUPPER(instance.key());
496 1 : thisZeqSplitter.spaceEquipType = DataLoopNode::ConnectionObjectType::SpaceHVACZoneEquipmentSplitter;
497 1 : ip->markObjectAsUsed(CurrentModuleObject, instance.key());
498 :
499 2 : std::string zoneName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_name");
500 1 : int zoneNum = Util::FindItemInList(zoneName, state.dataHeatBal->Zone);
501 1 : if (zoneNum == 0) {
502 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZeqSplitter.Name));
503 0 : ShowContinueError(state, format("..Zone Name={} not found, remaining items for this object not processed.", zoneName));
504 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
505 0 : continue;
506 : }
507 1 : if (!state.dataHeatBal->Zone(zoneNum).IsControlled) {
508 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZeqSplitter.Name));
509 0 : ShowContinueError(
510 : state,
511 0 : format("..Zone Name={} is not a controlled zone. A ZoneHVAC:EquipmentConfiguration object is required for this zone.", zoneName));
512 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
513 0 : continue;
514 : }
515 :
516 1 : processZoneEquipSplitterInput(state, CurrentModuleObject, zeqSplitterNum, zoneNum, objectSchemaProps, objectFields, thisZeqSplitter);
517 2 : }
518 : } // end loop over zone equipment splitters
519 :
520 796 : CurrentModuleObject = "SpaceHVAC:ZoneEquipmentMixer";
521 796 : instances = ip->epJSON.find(CurrentModuleObject);
522 796 : if (instances != ip->epJSON.end()) {
523 1 : auto const &objectSchemaProps = ip->getObjectSchemaProps(state, CurrentModuleObject);
524 1 : auto &instancesValue = instances.value();
525 1 : int numZoneEqMixers = instancesValue.size();
526 1 : state.dataZoneEquip->zoneEquipMixer.resize(numZoneEqMixers);
527 1 : int zeqMixerNum = -1;
528 2 : for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
529 1 : ++zeqMixerNum;
530 1 : auto const &objectFields = instance.value();
531 1 : auto &thisZeqMixer = state.dataZoneEquip->zoneEquipMixer[zeqMixerNum];
532 1 : thisZeqMixer.Name = Util::makeUPPER(instance.key());
533 1 : thisZeqMixer.spaceEquipType = DataLoopNode::ConnectionObjectType::SpaceHVACZoneEquipmentMixer;
534 1 : ip->markObjectAsUsed(CurrentModuleObject, instance.key());
535 :
536 2 : std::string zoneName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_name");
537 1 : int zoneNum = Util::FindItemInList(zoneName, state.dataHeatBal->Zone);
538 1 : if (zoneNum == 0) {
539 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZeqMixer.Name));
540 0 : ShowContinueError(state, format("..Zone Name={} not found, remaining items for this object not processed.", zoneName));
541 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
542 0 : continue;
543 : }
544 1 : if (!state.dataHeatBal->Zone(zoneNum).IsControlled) {
545 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZeqMixer.Name));
546 0 : ShowContinueError(
547 : state,
548 0 : format("..Zone Name={} is not a controlled zone. A ZoneHVAC:EquipmentConfiguration object is required for this zone.", zoneName));
549 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
550 0 : continue;
551 : }
552 :
553 1 : processZoneEquipMixerInput(state, CurrentModuleObject, zoneNum, objectSchemaProps, objectFields, thisZeqMixer);
554 2 : }
555 : } // end loop over zone equipment mixers
556 :
557 796 : CurrentModuleObject = "SpaceHVAC:ZoneReturnMixer";
558 796 : instances = ip->epJSON.find(CurrentModuleObject);
559 796 : if (instances != ip->epJSON.end()) {
560 1 : auto const &objectSchemaProps = ip->getObjectSchemaProps(state, CurrentModuleObject);
561 1 : auto &instancesValue = instances.value();
562 1 : int numZoneRetMixers = instancesValue.size();
563 1 : state.dataZoneEquip->zoneReturnMixer.resize(numZoneRetMixers);
564 1 : int zeqRetNum = -1;
565 2 : for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {
566 1 : ++zeqRetNum;
567 1 : auto const &objectFields = instance.value();
568 1 : auto &thisZretMixer = state.dataZoneEquip->zoneReturnMixer[zeqRetNum];
569 1 : thisZretMixer.Name = Util::makeUPPER(instance.key());
570 1 : thisZretMixer.spaceEquipType = DataLoopNode::ConnectionObjectType::SpaceHVACZoneReturnMixer;
571 1 : ip->markObjectAsUsed(CurrentModuleObject, instance.key());
572 :
573 2 : std::string zoneName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_name");
574 1 : int zoneNum = Util::FindItemInList(zoneName, state.dataHeatBal->Zone);
575 1 : if (zoneNum == 0) {
576 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZretMixer.Name));
577 0 : ShowContinueError(state, format("..Zone Name={} not found, remaining items for this object not processed.", zoneName));
578 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
579 0 : continue;
580 : }
581 1 : if (!state.dataHeatBal->Zone(zoneNum).IsControlled) {
582 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, CurrentModuleObject, thisZretMixer.Name));
583 0 : ShowContinueError(
584 : state,
585 0 : format("..Zone Name={} is not a controlled zone. A ZoneHVAC:EquipmentConfiguration object is required for this zone.", zoneName));
586 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
587 0 : continue;
588 : }
589 :
590 1 : processZoneReturnMixerInput(state, CurrentModuleObject, zoneNum, objectSchemaProps, objectFields, zeqRetNum);
591 2 : }
592 : } // end loop over zone return mixers
593 :
594 796 : CurrentModuleObject = "AirLoopHVAC:SupplyPath";
595 2012 : for (int PathNum = 1; PathNum <= state.dataZoneEquip->NumSupplyAirPaths; ++PathNum) {
596 :
597 1216 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
598 : CurrentModuleObject,
599 : PathNum,
600 : AlphArray,
601 : NumAlphas,
602 : NumArray,
603 : NumNums,
604 : IOStat,
605 : lNumericBlanks,
606 : lAlphaBlanks,
607 : cAlphaFields,
608 : cNumericFields); // data for one zone
609 1216 : state.dataZoneEquip->SupplyAirPath(PathNum).Name = AlphArray(1);
610 1216 : state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents = nint((double(NumAlphas) - 2.0) / 2.0);
611 :
612 2432 : state.dataZoneEquip->SupplyAirPath(PathNum).InletNodeNum = GetOnlySingleNode(state,
613 1216 : AlphArray(2),
614 1216 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
615 : DataLoopNode::ConnectionObjectType::AirLoopHVACSupplyPath,
616 1216 : AlphArray(1),
617 : DataLoopNode::NodeFluidType::Air,
618 : DataLoopNode::ConnectionType::Inlet,
619 : NodeInputManager::CompFluidStream::Primary,
620 : ObjectIsParent);
621 :
622 1216 : state.dataZoneEquip->SupplyAirPath(PathNum).ComponentType.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
623 1216 : state.dataZoneEquip->SupplyAirPath(PathNum).ComponentTypeEnum.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
624 1216 : state.dataZoneEquip->SupplyAirPath(PathNum).ComponentTypeEnum = DataZoneEquipment::AirLoopHVACZone::Invalid;
625 1216 : state.dataZoneEquip->SupplyAirPath(PathNum).ComponentName.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
626 1216 : state.dataZoneEquip->SupplyAirPath(PathNum).ComponentIndex.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
627 1216 : state.dataZoneEquip->SupplyAirPath(PathNum).SplitterIndex.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
628 1216 : state.dataZoneEquip->SupplyAirPath(PathNum).PlenumIndex.allocate(state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents);
629 :
630 1216 : int Counter = 3;
631 :
632 2439 : for (int CompNum = 1; CompNum <= state.dataZoneEquip->SupplyAirPath(PathNum).NumOfComponents; ++CompNum) {
633 :
634 1223 : if ((AlphArray(Counter) == "AIRLOOPHVAC:ZONESPLITTER") || (AlphArray(Counter) == "AIRLOOPHVAC:SUPPLYPLENUM")) {
635 :
636 1223 : state.dataZoneEquip->SupplyAirPath(PathNum).ComponentType(CompNum) = AlphArray(Counter);
637 1223 : state.dataZoneEquip->SupplyAirPath(PathNum).ComponentName(CompNum) = AlphArray(Counter + 1);
638 2446 : ValidateComponent(state,
639 1223 : state.dataZoneEquip->SupplyAirPath(PathNum).ComponentType(CompNum),
640 1223 : state.dataZoneEquip->SupplyAirPath(PathNum).ComponentName(CompNum),
641 : IsNotOK,
642 : CurrentModuleObject);
643 1223 : state.dataZoneEquip->SupplyAirPath(PathNum).ComponentIndex(CompNum) = 0;
644 1223 : state.dataZoneEquip->SupplyAirPath(PathNum).SplitterIndex(CompNum) = 0;
645 1223 : state.dataZoneEquip->SupplyAirPath(PathNum).PlenumIndex(CompNum) = 0;
646 1223 : state.dataZoneEquip->SupplyAirPath(PathNum).ComponentTypeEnum(CompNum) =
647 2446 : (AirLoopHVACZone)getEnumValue(AirLoopHVACTypeNamesUC, AlphArray(Counter));
648 : } else {
649 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cAlphaFields(1), state.dataZoneEquip->SupplyAirPath(PathNum).Name));
650 0 : ShowContinueError(state, format("Unhandled component type =\"{}\".", AlphArray(Counter)));
651 0 : ShowContinueError(state, R"(Must be "AirLoopHVAC:ZoneSplitter" or "AirLoopHVAC:SupplyPlenum")");
652 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
653 : }
654 :
655 1223 : Counter += 2;
656 : }
657 :
658 1216 : state.dataZoneEquip->SupplyAirPath(PathNum).NumOutletNodes = 0;
659 1216 : state.dataZoneEquip->SupplyAirPath(PathNum).NumNodes = 0;
660 :
661 : } // end loop over supply air paths
662 :
663 796 : CurrentModuleObject = "AirLoopHVAC:ReturnPath";
664 1995 : for (int PathNum = 1; PathNum <= state.dataZoneEquip->NumReturnAirPaths; ++PathNum) {
665 :
666 1199 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
667 : CurrentModuleObject,
668 : PathNum,
669 : AlphArray,
670 : NumAlphas,
671 : NumArray,
672 : NumNums,
673 : IOStat,
674 : lNumericBlanks,
675 : lAlphaBlanks,
676 : cAlphaFields,
677 : cNumericFields); // data for one zone
678 1199 : state.dataZoneEquip->ReturnAirPath(PathNum).Name = AlphArray(1);
679 1199 : state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents = nint((double(NumAlphas) - 2.0) / 2.0);
680 :
681 2398 : state.dataZoneEquip->ReturnAirPath(PathNum).OutletNodeNum = GetOnlySingleNode(state,
682 1199 : AlphArray(2),
683 1199 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
684 : DataLoopNode::ConnectionObjectType::AirLoopHVACReturnPath,
685 1199 : AlphArray(1),
686 : DataLoopNode::NodeFluidType::Air,
687 : DataLoopNode::ConnectionType::Outlet,
688 : NodeInputManager::CompFluidStream::Primary,
689 : ObjectIsParent);
690 :
691 1199 : state.dataZoneEquip->ReturnAirPath(PathNum).ComponentType.allocate(state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents);
692 1199 : state.dataZoneEquip->ReturnAirPath(PathNum).ComponentTypeEnum.allocate(state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents);
693 1199 : state.dataZoneEquip->ReturnAirPath(PathNum).ComponentTypeEnum = DataZoneEquipment::AirLoopHVACZone::Invalid;
694 1199 : state.dataZoneEquip->ReturnAirPath(PathNum).ComponentName.allocate(state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents);
695 1199 : state.dataZoneEquip->ReturnAirPath(PathNum).ComponentIndex.allocate(state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents);
696 :
697 1199 : int Counter = 3;
698 :
699 2513 : for (int CompNum = 1; CompNum <= state.dataZoneEquip->ReturnAirPath(PathNum).NumOfComponents; ++CompNum) {
700 :
701 1314 : if ((AlphArray(Counter) == "AIRLOOPHVAC:ZONEMIXER") || (AlphArray(Counter) == "AIRLOOPHVAC:RETURNPLENUM")) {
702 :
703 1314 : state.dataZoneEquip->ReturnAirPath(PathNum).ComponentType(CompNum) = AlphArray(Counter);
704 1314 : state.dataZoneEquip->ReturnAirPath(PathNum).ComponentName(CompNum) = AlphArray(Counter + 1);
705 1314 : state.dataZoneEquip->ReturnAirPath(PathNum).ComponentIndex(CompNum) = 0;
706 2628 : ValidateComponent(state,
707 1314 : state.dataZoneEquip->ReturnAirPath(PathNum).ComponentType(CompNum),
708 1314 : state.dataZoneEquip->ReturnAirPath(PathNum).ComponentName(CompNum),
709 : IsNotOK,
710 : CurrentModuleObject);
711 1314 : if (IsNotOK) {
712 0 : ShowContinueError(state, format("In {} = {}", CurrentModuleObject, state.dataZoneEquip->ReturnAirPath(PathNum).Name));
713 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
714 : }
715 1314 : state.dataZoneEquip->ReturnAirPath(PathNum).ComponentTypeEnum(CompNum) =
716 2628 : static_cast<AirLoopHVACZone>(getEnumValue(AirLoopHVACTypeNamesUC, AlphArray(Counter)));
717 : } else {
718 0 : ShowSevereError(state, format("{}{}=\"{}\"", RoutineName, cAlphaFields(1), state.dataZoneEquip->ReturnAirPath(PathNum).Name));
719 0 : ShowContinueError(state, format("Unhandled component type =\"{}\".", AlphArray(Counter)));
720 0 : ShowContinueError(state, R"(Must be "AirLoopHVAC:ZoneMixer" or "AirLoopHVAC:ReturnPlenum")");
721 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
722 : }
723 :
724 1314 : Counter += 2;
725 : }
726 :
727 : } // end loop over return air paths
728 :
729 796 : AlphArray.deallocate();
730 796 : NumArray.deallocate();
731 796 : cAlphaFields.deallocate();
732 796 : cNumericFields.deallocate();
733 796 : lAlphaBlanks.deallocate();
734 796 : lNumericBlanks.deallocate();
735 :
736 796 : if (state.dataZoneEquip->GetZoneEquipmentDataErrorsFound) {
737 0 : ShowFatalError(state, format("{}Errors found in getting Zone Equipment input.", RoutineName));
738 : }
739 796 : }
740 :
741 4322 : void processZoneEquipmentInput(EnergyPlusData &state,
742 : std::string_view zoneEqModuleObject,
743 : int const zoneOrSpaceNum,
744 : bool const isSpace,
745 : int &locTermUnitSizingCounter,
746 : int &overallEquipCount,
747 : DataZoneEquipment::EquipConfiguration &thisEquipConfig,
748 : Array1D_string &AlphArray,
749 : Array1D_string &cAlphaFields, // Alpha field names
750 : Array1D_bool &lAlphaBlanks, // Logical array, alpha field input BLANK = .TRUE.
751 : Array1D_int &NodeNums)
752 : {
753 : static constexpr std::string_view RoutineName("processZoneEquipmentInput: "); // include trailing blank space
754 4322 : std::string_view zsString = "Zone";
755 4322 : int spaceFieldShift = 0;
756 4322 : if (isSpace) {
757 3 : zsString = "Space";
758 3 : spaceFieldShift = -1;
759 : }
760 :
761 4322 : thisEquipConfig.IsControlled = true;
762 4322 : thisEquipConfig.ZoneName = AlphArray(1); // for x-referencing with the geometry data
763 :
764 4322 : bool IsNotOK = false;
765 8644 : GlobalNames::IntraObjUniquenessCheck(
766 4322 : state, AlphArray(2), zoneEqModuleObject, cAlphaFields(2), state.dataZoneEquip->UniqueZoneEquipListNames, IsNotOK);
767 4322 : if (IsNotOK) {
768 0 : ShowContinueError(state, format("..another Controlled Zone has been assigned that {}.", cAlphaFields(2)));
769 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
770 : }
771 4322 : thisEquipConfig.EquipListName = AlphArray(2); // the name of the list containing all the zone eq.
772 4322 : std::string const InletNodeListName = AlphArray(3 + spaceFieldShift);
773 4322 : std::string const ExhaustNodeListName = AlphArray(4 + spaceFieldShift);
774 4322 : thisEquipConfig.ZoneNode = GetOnlySingleNode(state,
775 4322 : AlphArray(5 + spaceFieldShift),
776 4322 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
777 : DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections,
778 4322 : AlphArray(1),
779 : DataLoopNode::NodeFluidType::Air,
780 : DataLoopNode::ConnectionType::ZoneNode,
781 : NodeInputManager::CompFluidStream::Primary,
782 : DataLoopNode::ObjectIsNotParent); // all zone air state variables are
783 4322 : if (thisEquipConfig.ZoneNode == 0) {
784 0 : ShowSevereError(state, format("{}{}: {}=\"{}\", invalid", RoutineName, zoneEqModuleObject, cAlphaFields(1), AlphArray(1)));
785 0 : ShowContinueError(state, format("{} must be present.", cAlphaFields(5 + spaceFieldShift)));
786 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
787 : } else {
788 4322 : bool UniqueNodeError = false;
789 4322 : NodeInputManager::CheckUniqueNodeNames(
790 4322 : state, cAlphaFields(5 + spaceFieldShift), UniqueNodeError, AlphArray(5 + spaceFieldShift), AlphArray(1));
791 4322 : if (UniqueNodeError) {
792 : // ShowContinueError(state, format("Occurs for {} = {}", trim( cAlphaFields( 1 ) ), trim( AlphArray( 1 ) )));
793 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
794 : }
795 : }
796 :
797 4322 : std::string ReturnNodeListName = AlphArray(6 + spaceFieldShift);
798 4322 : if (lAlphaBlanks(7)) {
799 4317 : thisEquipConfig.ReturnFlowSchedPtrNum = ScheduleManager::ScheduleAlwaysOn;
800 : } else {
801 5 : thisEquipConfig.ReturnFlowSchedPtrNum = ScheduleManager::GetScheduleIndex(state, AlphArray(7 + spaceFieldShift));
802 5 : if (thisEquipConfig.ReturnFlowSchedPtrNum == 0) {
803 0 : ShowSevereError(state,
804 0 : format("{}{}: invalid {} entered ={} for {}={}",
805 : RoutineName,
806 : zoneEqModuleObject,
807 : cAlphaFields(7),
808 : AlphArray(7),
809 : cAlphaFields(1),
810 : AlphArray(1)));
811 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
812 : }
813 : }
814 4322 : std::string ReturnFlowBasisNodeListName = AlphArray(8 + spaceFieldShift);
815 :
816 : // Read in the equipment type, name and sequence information
817 : // for each equipment list
818 :
819 4322 : if (!isSpace) {
820 4319 : std::string CurrentModuleObject = "ZoneHVAC:EquipmentList";
821 4319 : auto &ip = state.dataInputProcessing->inputProcessor;
822 :
823 4319 : int ZoneEquipListNum = ip->getObjectItemNum(state, CurrentModuleObject, thisEquipConfig.EquipListName);
824 :
825 4319 : if (ZoneEquipListNum <= 0) {
826 0 : ShowSevereError(state, format("{}{} not found = {}", RoutineName, CurrentModuleObject, thisEquipConfig.EquipListName));
827 0 : ShowContinueError(state, format("In ZoneHVAC:EquipmentConnections object, for Zone = {}", thisEquipConfig.ZoneName));
828 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
829 : } else {
830 4319 : auto const &epListFields = ip->getJSONObjectItem(state, CurrentModuleObject, thisEquipConfig.EquipListName);
831 :
832 4319 : auto const &objectSchemaProps = ip->getObjectSchemaProps(state, CurrentModuleObject);
833 :
834 4319 : EquipList &thisZoneEquipList = state.dataZoneEquip->ZoneEquipList(zoneOrSpaceNum);
835 :
836 4319 : thisZoneEquipList.Name = thisEquipConfig.EquipListName;
837 :
838 8638 : std::string loadDistName = ip->getAlphaFieldValue(epListFields, objectSchemaProps, "load_distribution_scheme");
839 4319 : thisZoneEquipList.LoadDistScheme =
840 4319 : static_cast<DataZoneEquipment::LoadDist>(getEnumValue(DataZoneEquipment::LoadDistNamesUC, Util::makeUPPER(loadDistName)));
841 4319 : if (thisZoneEquipList.LoadDistScheme == DataZoneEquipment::LoadDist::Invalid) {
842 0 : ShowSevereError(state, format("{}{} = \"{}, Invalid choice\".", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
843 0 : ShowContinueError(state, format("...load_distribution_scheme=\"{}\".", loadDistName));
844 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
845 : }
846 :
847 4319 : auto extensibles = epListFields.find("equipment");
848 4319 : if (extensibles != epListFields.end()) {
849 4319 : auto &extensiblesArray = extensibles.value();
850 4319 : thisZoneEquipList.NumOfEquipTypes = static_cast<int>(extensiblesArray.size());
851 :
852 : // Increment overall count of equipment
853 4319 : overallEquipCount += thisZoneEquipList.NumOfEquipTypes;
854 :
855 4319 : thisZoneEquipList.EquipTypeName.allocate(thisZoneEquipList.NumOfEquipTypes);
856 4319 : thisZoneEquipList.EquipType.allocate(thisZoneEquipList.NumOfEquipTypes);
857 4319 : thisZoneEquipList.compPointer.resize(thisZoneEquipList.NumOfEquipTypes + 1);
858 4319 : thisZoneEquipList.EquipName.allocate(thisZoneEquipList.NumOfEquipTypes);
859 4319 : thisZoneEquipList.EquipIndex.allocate(thisZoneEquipList.NumOfEquipTypes);
860 4319 : thisZoneEquipList.zoneEquipSplitterIndex.allocate(thisZoneEquipList.NumOfEquipTypes);
861 4319 : thisZoneEquipList.EquipData.allocate(thisZoneEquipList.NumOfEquipTypes);
862 4319 : thisZoneEquipList.CoolingPriority.allocate(thisZoneEquipList.NumOfEquipTypes);
863 4319 : thisZoneEquipList.HeatingPriority.allocate(thisZoneEquipList.NumOfEquipTypes);
864 4319 : thisZoneEquipList.CoolingCapacity.allocate(thisZoneEquipList.NumOfEquipTypes);
865 4319 : thisZoneEquipList.HeatingCapacity.allocate(thisZoneEquipList.NumOfEquipTypes);
866 4319 : thisZoneEquipList.SequentialCoolingFractionSchedPtr.allocate(thisZoneEquipList.NumOfEquipTypes);
867 4319 : thisZoneEquipList.SequentialHeatingFractionSchedPtr.allocate(thisZoneEquipList.NumOfEquipTypes);
868 9217 : for (int eqNum = 1; eqNum <= thisZoneEquipList.NumOfEquipTypes; ++eqNum) {
869 4898 : thisZoneEquipList.EquipTypeName(eqNum) = "";
870 4898 : thisZoneEquipList.EquipType(eqNum) = DataZoneEquipment::ZoneEquipType::Invalid;
871 4898 : thisZoneEquipList.EquipName(eqNum) = "";
872 4898 : thisZoneEquipList.EquipIndex(eqNum) = 0;
873 4898 : thisZoneEquipList.zoneEquipSplitterIndex(eqNum) = -1;
874 4898 : thisZoneEquipList.compPointer[eqNum] = nullptr;
875 4898 : thisZoneEquipList.CoolingPriority(eqNum) = 0;
876 4898 : thisZoneEquipList.HeatingPriority(eqNum) = 0;
877 4898 : thisZoneEquipList.CoolingCapacity(eqNum) = 0;
878 4898 : thisZoneEquipList.HeatingCapacity(eqNum) = 0;
879 4898 : thisZoneEquipList.SequentialCoolingFractionSchedPtr(eqNum) = 0;
880 4898 : thisZoneEquipList.SequentialHeatingFractionSchedPtr(eqNum) = 0;
881 : }
882 :
883 4319 : auto const &extensionSchemaProps = objectSchemaProps["equipment"]["items"]["properties"];
884 :
885 4319 : int ZoneEquipTypeNum = 0;
886 9217 : for (auto &extensibleInstance : extensiblesArray) {
887 4898 : ++ZoneEquipTypeNum;
888 :
889 4898 : thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum) =
890 9796 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_object_type");
891 4898 : thisZoneEquipList.EquipName(ZoneEquipTypeNum) =
892 9796 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_name");
893 :
894 9796 : ValidateComponent(state,
895 4898 : thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum),
896 4898 : thisZoneEquipList.EquipName(ZoneEquipTypeNum),
897 : IsNotOK,
898 : CurrentModuleObject);
899 4898 : if (IsNotOK) {
900 0 : ShowContinueError(state, format("In {}={}", CurrentModuleObject, thisZoneEquipList.Name));
901 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
902 : }
903 :
904 : // If not present, this return 0
905 9796 : thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum) =
906 4898 : ip->getIntFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_cooling_sequence");
907 :
908 9796 : if ((thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum) < 0) ||
909 4898 : (thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum) > thisZoneEquipList.NumOfEquipTypes)) {
910 0 : ShowSevereError(state, format("{}{} = \"{}\".", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
911 0 : ShowContinueError(
912 0 : state, format("invalid zone_equipment_cooling_sequence=[{}].", thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum)));
913 0 : ShowContinueError(state, "equipment sequence must be > 0 and <= number of equipments in the list.");
914 0 : if (thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum) > 0) {
915 0 : ShowContinueError(state, format("only {} in the list.", thisZoneEquipList.NumOfEquipTypes));
916 : }
917 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
918 : }
919 :
920 9796 : thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum) =
921 4898 : ip->getIntFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_heating_or_no_load_sequence");
922 9796 : if ((thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum) < 0) ||
923 4898 : (thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum) > thisZoneEquipList.NumOfEquipTypes)) {
924 0 : ShowSevereError(state, format("{}{} = \"{}\".", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
925 0 : ShowContinueError(
926 0 : state, format("invalid zone_equipment_heating_sequence=[{}].", thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum)));
927 0 : ShowContinueError(state, "equipment sequence must be > 0 and <= number of equipments in the list.");
928 0 : if (thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum) > 0) {
929 0 : ShowContinueError(state, format("only {} in the list.", thisZoneEquipList.NumOfEquipTypes));
930 : }
931 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
932 : }
933 :
934 : std::string coolingSchName =
935 9796 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_sequential_cooling_fraction_schedule_name");
936 4898 : if (coolingSchName.empty()) {
937 4879 : thisZoneEquipList.SequentialCoolingFractionSchedPtr(ZoneEquipTypeNum) = ScheduleManager::ScheduleAlwaysOn;
938 : } else {
939 38 : thisZoneEquipList.SequentialCoolingFractionSchedPtr(ZoneEquipTypeNum) =
940 19 : ScheduleManager::GetScheduleIndex(state, coolingSchName);
941 19 : if (thisZoneEquipList.SequentialCoolingFractionSchedPtr(ZoneEquipTypeNum) == 0) {
942 0 : ShowSevereError(state, format("{}{} = \"{}\".", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
943 0 : ShowContinueError(state,
944 0 : format("invalid zone_equipment_sequential_cooling_fraction_schedule_name=[{}].", coolingSchName));
945 0 : ShowContinueError(state, "Schedule does not exist.");
946 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
947 : }
948 : }
949 :
950 : std::string heatingSchName =
951 9796 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "zone_equipment_sequential_heating_fraction_schedule_name");
952 4898 : if (heatingSchName.empty()) {
953 4879 : thisZoneEquipList.SequentialHeatingFractionSchedPtr(ZoneEquipTypeNum) = ScheduleManager::ScheduleAlwaysOn;
954 : } else {
955 38 : thisZoneEquipList.SequentialHeatingFractionSchedPtr(ZoneEquipTypeNum) =
956 19 : ScheduleManager::GetScheduleIndex(state, heatingSchName);
957 19 : if (thisZoneEquipList.SequentialHeatingFractionSchedPtr(ZoneEquipTypeNum) == 0) {
958 0 : ShowSevereError(state, format("{}{} = \"{}\".", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
959 0 : ShowContinueError(state,
960 0 : format("invalid zone_equipment_sequential_heating_fraction_schedule_name=[{}].", coolingSchName));
961 0 : ShowContinueError(state, "Schedule does not exist.");
962 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
963 : }
964 : }
965 :
966 : // do this here for initial prototype, but later will call all the equipment in a separate function to see who is on - maybe
967 4898 : if (thisZoneEquipList.HeatingPriority(ZoneEquipTypeNum) > 0) {
968 4898 : ++thisZoneEquipList.NumAvailHeatEquip;
969 : }
970 4898 : if (thisZoneEquipList.CoolingPriority(ZoneEquipTypeNum) > 0) {
971 4898 : ++thisZoneEquipList.NumAvailCoolEquip;
972 : }
973 :
974 9796 : thisZoneEquipList.EquipType(ZoneEquipTypeNum) = static_cast<ZoneEquipType>(
975 4898 : getEnumValue(zoneEquipTypeNamesUC, Util::makeUPPER(thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum))));
976 :
977 4898 : if (thisZoneEquipList.EquipType(ZoneEquipTypeNum) == ZoneEquipType::UnitarySystem ||
978 4877 : thisZoneEquipList.EquipType(ZoneEquipTypeNum) == ZoneEquipType::PackagedTerminalAirConditioner ||
979 14482 : thisZoneEquipList.EquipType(ZoneEquipTypeNum) == ZoneEquipType::PackagedTerminalHeatPump ||
980 4707 : thisZoneEquipList.EquipType(ZoneEquipTypeNum) == ZoneEquipType::PackagedTerminalHeatPumpWaterToAir) {
981 : // loop index accesses correct pointer to equipment on this equipment list
982 : // EquipIndex is used to access specific equipment for a single class of equipment (e.g., PTAC 1, 2 and 3)
983 218 : thisZoneEquipList.compPointer[ZoneEquipTypeNum] = UnitarySystems::UnitarySys::factory(
984 218 : state, HVAC::UnitarySysType::Unitary_AnyCoilType, thisZoneEquipList.EquipName(ZoneEquipTypeNum), true, 0);
985 218 : thisZoneEquipList.EquipIndex(ZoneEquipTypeNum) = thisZoneEquipList.compPointer[ZoneEquipTypeNum]->getEquipIndex();
986 : }
987 :
988 4898 : if (thisZoneEquipList.EquipType(ZoneEquipTypeNum) == ZoneEquipType::Invalid) {
989 49 : if (thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum) == "ZONEHVAC:LOWTEMPERATURERADIANT:CONSTANTFLOW" ||
990 11 : thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum) == "ZONEHVAC:LOWTEMPERATURERADIANT:ELECTRIC") {
991 36 : thisZoneEquipList.EquipType(ZoneEquipTypeNum) = ZoneEquipType::LowTemperatureRadiant;
992 2 : } else if (thisZoneEquipList.EquipTypeName(ZoneEquipTypeNum) == "WATERHEATER:HEATPUMP:WRAPPEDCONDENSER") {
993 2 : thisZoneEquipList.EquipType(ZoneEquipTypeNum) = DataZoneEquipment::ZoneEquipType::HeatPumpWaterHeater;
994 : } else {
995 0 : ShowSevereError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
996 0 : ShowContinueError(state, format("..Invalid Equipment Type = {}", thisZoneEquipList.EquipType(ZoneEquipTypeNum)));
997 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
998 : }
999 : }
1000 9217 : }
1001 : } // End parsing all extensible Zone Equipment info
1002 :
1003 : // Check for multiple assignments
1004 9217 : for (int ZoneEquipTypeNum = 1; ZoneEquipTypeNum <= thisZoneEquipList.NumOfEquipTypes; ++ZoneEquipTypeNum) {
1005 4898 : if (count_eq(thisZoneEquipList.CoolingPriority, ZoneEquipTypeNum) > 1) {
1006 0 : ShowSevereError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
1007 0 : ShowContinueError(state,
1008 0 : format("...multiple assignments for Zone Equipment Cooling Sequence={}, must be 1-1 correspondence between "
1009 : "sequence assignments and number of equipments.",
1010 : ZoneEquipTypeNum));
1011 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1012 4898 : } else if (count_eq(thisZoneEquipList.CoolingPriority, ZoneEquipTypeNum) == 0) {
1013 0 : ShowWarningError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
1014 0 : ShowContinueError(state,
1015 0 : format("...zero assigned to Zone Equipment Cooling Sequence={}, apparent gap in sequence assignments in "
1016 : "this equipment list.",
1017 : ZoneEquipTypeNum));
1018 : }
1019 4898 : if (count_eq(thisZoneEquipList.HeatingPriority, ZoneEquipTypeNum) > 1) {
1020 0 : ShowSevereError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
1021 0 : ShowContinueError(state,
1022 0 : format("...multiple assignments for Zone Equipment Heating or No-Load Sequence={}, must be 1-1 "
1023 : "correspondence between sequence assignments and number of equipments.",
1024 : ZoneEquipTypeNum));
1025 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1026 4898 : } else if (count_eq(thisZoneEquipList.HeatingPriority, ZoneEquipTypeNum) == 0) {
1027 0 : ShowWarningError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, thisZoneEquipList.Name));
1028 0 : ShowContinueError(state,
1029 0 : format("...zero assigned to Zone Equipment Heating or No-Load Sequence={}, apparent gap in sequence "
1030 : "assignments in this equipment list.",
1031 : ZoneEquipTypeNum));
1032 : }
1033 : }
1034 4319 : } // End ZoneHVAC:EquipmentList
1035 4319 : }
1036 4322 : bool NodeListError = false;
1037 4322 : int NumNodes = 0;
1038 8644 : GetNodeNums(state,
1039 : InletNodeListName,
1040 : NumNodes,
1041 : NodeNums,
1042 : NodeListError,
1043 : DataLoopNode::NodeFluidType::Air,
1044 : (isSpace ? DataLoopNode::ConnectionObjectType::SpaceHVACEquipmentConnections
1045 : : DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections),
1046 4322 : thisEquipConfig.ZoneName,
1047 : DataLoopNode::ConnectionType::ZoneInlet,
1048 : NodeInputManager::CompFluidStream::Primary,
1049 : DataLoopNode::ObjectIsNotParent);
1050 :
1051 4322 : if (!NodeListError) {
1052 4322 : thisEquipConfig.NumInletNodes = NumNodes;
1053 :
1054 4322 : thisEquipConfig.InletNode.allocate(NumNodes);
1055 4322 : thisEquipConfig.InletNodeAirLoopNum.allocate(NumNodes);
1056 4322 : thisEquipConfig.InletNodeADUNum.allocate(NumNodes);
1057 4322 : thisEquipConfig.AirDistUnitCool.allocate(NumNodes);
1058 4322 : thisEquipConfig.AirDistUnitHeat.allocate(NumNodes);
1059 :
1060 8798 : for (int NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
1061 4476 : thisEquipConfig.InletNode(NodeNum) = NodeNums(NodeNum);
1062 4476 : bool UniqueNodeError = false;
1063 4476 : NodeInputManager::CheckUniqueNodeNumbers(state, "Zone Air Inlet Nodes", UniqueNodeError, NodeNums(NodeNum), thisEquipConfig.ZoneName);
1064 4476 : if (UniqueNodeError) {
1065 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1066 : }
1067 4476 : thisEquipConfig.InletNodeAirLoopNum(NodeNum) = 0;
1068 4476 : thisEquipConfig.InletNodeADUNum(NodeNum) = 0;
1069 4476 : thisEquipConfig.AirDistUnitCool(NodeNum).InNode = 0;
1070 4476 : thisEquipConfig.AirDistUnitHeat(NodeNum).InNode = 0;
1071 4476 : thisEquipConfig.AirDistUnitCool(NodeNum).OutNode = 0;
1072 4476 : thisEquipConfig.AirDistUnitHeat(NodeNum).OutNode = 0;
1073 4476 : if (!isSpace) {
1074 4473 : ++locTermUnitSizingCounter;
1075 4473 : thisEquipConfig.AirDistUnitCool(NodeNum).TermUnitSizingIndex = locTermUnitSizingCounter;
1076 4473 : thisEquipConfig.AirDistUnitHeat(NodeNum).TermUnitSizingIndex = locTermUnitSizingCounter;
1077 : }
1078 : }
1079 : } else {
1080 0 : ShowContinueError(
1081 : state,
1082 0 : format("Invalid Zone Air Inlet Node or NodeList Name in ZoneHVAC:EquipmentConnections object, for Zone = {}", thisEquipConfig.ZoneName));
1083 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1084 : }
1085 :
1086 4322 : NodeListError = false;
1087 8644 : GetNodeNums(state,
1088 : ExhaustNodeListName,
1089 : NumNodes,
1090 : NodeNums,
1091 : NodeListError,
1092 : DataLoopNode::NodeFluidType::Air,
1093 : (isSpace ? DataLoopNode::ConnectionObjectType::SpaceHVACEquipmentConnections
1094 : : DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections),
1095 4322 : thisEquipConfig.ZoneName,
1096 : DataLoopNode::ConnectionType::ZoneExhaust,
1097 : NodeInputManager::CompFluidStream::Primary,
1098 : DataLoopNode::ObjectIsNotParent);
1099 :
1100 4322 : if (!NodeListError) {
1101 4322 : thisEquipConfig.NumExhaustNodes = NumNodes;
1102 :
1103 4322 : thisEquipConfig.ExhaustNode.allocate(NumNodes);
1104 :
1105 5170 : for (int NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
1106 848 : thisEquipConfig.ExhaustNode(NodeNum) = NodeNums(NodeNum);
1107 848 : bool UniqueNodeError = false;
1108 848 : NodeInputManager::CheckUniqueNodeNumbers(state, "Zone Air Exhaust Nodes", UniqueNodeError, NodeNums(NodeNum), thisEquipConfig.ZoneName);
1109 848 : if (UniqueNodeError) {
1110 : // ShowContinueError(state, format("Occurs for Zone = {}", trim( AlphArray( 1 ) )));
1111 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1112 : }
1113 : }
1114 : } else {
1115 0 : ShowContinueError(
1116 : state,
1117 0 : format("Invalid Zone Air Exhaust Node or NodeList Name in ZoneHVAC:EquipmentConnections object, for Zone={}", thisEquipConfig.ZoneName));
1118 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1119 : }
1120 :
1121 4322 : NodeListError = false;
1122 8644 : GetNodeNums(state,
1123 : ReturnNodeListName,
1124 : NumNodes,
1125 : NodeNums,
1126 : NodeListError,
1127 : DataLoopNode::NodeFluidType::Air,
1128 : (isSpace ? DataLoopNode::ConnectionObjectType::SpaceHVACEquipmentConnections
1129 : : DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections),
1130 4322 : thisEquipConfig.ZoneName,
1131 : DataLoopNode::ConnectionType::ZoneReturn,
1132 : NodeInputManager::CompFluidStream::Primary,
1133 : DataLoopNode::ObjectIsNotParent);
1134 :
1135 4322 : if (!NodeListError) {
1136 4322 : thisEquipConfig.NumReturnNodes = NumNodes;
1137 :
1138 4322 : thisEquipConfig.ReturnNode.allocate(NumNodes);
1139 4322 : thisEquipConfig.returnNodeSpaceMixerIndex.allocate(NumNodes);
1140 8648 : for (int &mixIndex : thisEquipConfig.returnNodeSpaceMixerIndex) {
1141 4326 : mixIndex = -1;
1142 : }
1143 4322 : thisEquipConfig.ReturnNodeAirLoopNum.allocate(NumNodes);
1144 4322 : thisEquipConfig.ReturnNodeRetPathNum.allocate(NumNodes);
1145 4322 : thisEquipConfig.ReturnNodeRetPathCompNum.allocate(NumNodes);
1146 4322 : thisEquipConfig.ReturnNodeInletNum.allocate(NumNodes);
1147 4322 : thisEquipConfig.FixedReturnFlow.allocate(NumNodes);
1148 4322 : thisEquipConfig.ReturnNodePlenumNum.allocate(NumNodes);
1149 4322 : thisEquipConfig.ReturnNodeExhaustNodeNum.allocate(NumNodes);
1150 4322 : thisEquipConfig.SharedExhaustNode.allocate(NumNodes);
1151 4322 : thisEquipConfig.ReturnNode = 0; // initialize to zero here
1152 4322 : thisEquipConfig.ReturnNodeAirLoopNum = 0; // initialize to zero here
1153 4322 : thisEquipConfig.ReturnNodeInletNum = 0; // initialize to zero here
1154 4322 : thisEquipConfig.ReturnNodeRetPathNum = 0;
1155 4322 : thisEquipConfig.ReturnNodeRetPathCompNum = 0;
1156 4322 : thisEquipConfig.FixedReturnFlow = false; // initialize to false here
1157 4322 : thisEquipConfig.ReturnNodePlenumNum = 0; // initialize to zero here
1158 4322 : thisEquipConfig.ReturnNodeExhaustNodeNum = 0; // initialize to zero here
1159 4322 : thisEquipConfig.SharedExhaustNode = LightReturnExhaustConfig::NoExhast; // initialize to zero here
1160 :
1161 8648 : for (int NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
1162 4326 : thisEquipConfig.ReturnNode(NodeNum) = NodeNums(NodeNum);
1163 4326 : bool UniqueNodeError = false;
1164 4326 : NodeInputManager::CheckUniqueNodeNumbers(state, "Zone Return Air Nodes", UniqueNodeError, NodeNums(NodeNum), thisEquipConfig.ZoneName);
1165 4326 : if (UniqueNodeError) {
1166 : // ShowContinueError(state, format("Occurs for Zone = {}", trim( AlphArray( 1 ) )));
1167 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1168 : }
1169 : }
1170 : } else {
1171 0 : ShowContinueError(
1172 : state,
1173 0 : format("Invalid Zone Return Air Node or NodeList Name in ZoneHVAC:EquipmentConnections object, for Zone={}", thisEquipConfig.ZoneName));
1174 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1175 : }
1176 :
1177 4322 : NodeListError = false;
1178 8644 : GetNodeNums(state,
1179 : ReturnFlowBasisNodeListName,
1180 : NumNodes,
1181 : NodeNums,
1182 : NodeListError,
1183 : DataLoopNode::NodeFluidType::Air,
1184 : (isSpace ? DataLoopNode::ConnectionObjectType::SpaceHVACEquipmentConnections
1185 : : DataLoopNode::ConnectionObjectType::ZoneHVACEquipmentConnections),
1186 4322 : thisEquipConfig.ZoneName,
1187 : DataLoopNode::ConnectionType::Sensor,
1188 : NodeInputManager::CompFluidStream::Primary,
1189 : DataLoopNode::ObjectIsNotParent);
1190 :
1191 4322 : if (!NodeListError) {
1192 4322 : thisEquipConfig.NumReturnFlowBasisNodes = NumNodes;
1193 :
1194 4322 : thisEquipConfig.ReturnFlowBasisNode.allocate(NumNodes);
1195 :
1196 4322 : for (int NodeNum = 1; NodeNum <= NumNodes; ++NodeNum) {
1197 0 : thisEquipConfig.ReturnFlowBasisNode(NodeNum) = NodeNums(NodeNum);
1198 : }
1199 : } else {
1200 0 : ShowContinueError(
1201 : state,
1202 0 : format("Invalid Zone Return Air Node 1 Flow Rate Basis Node or NodeList Name in ZoneHVAC:EquipmentConnections object, for Zone={}",
1203 0 : thisEquipConfig.ZoneName));
1204 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1205 : }
1206 4322 : }
1207 :
1208 1 : void processZoneEquipSplitterInput(EnergyPlusData &state,
1209 : std::string_view zeqSplitterModuleObject,
1210 : int const zeqSplitterNum,
1211 : int const zoneNum,
1212 : InputProcessor::json const objectSchemaProps,
1213 : InputProcessor::json const objectFields,
1214 : DataZoneEquipment::ZoneEquipmentSplitter &thisZeqSplitter)
1215 :
1216 : {
1217 : static constexpr std::string_view RoutineName("processZoneEquipSplitterInput: "); // include trailing blank space
1218 1 : auto &ip = state.dataInputProcessing->inputProcessor;
1219 2 : std::string const zeqTypeName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_equipment_object_type");
1220 1 : thisZeqSplitter.zoneEquipType = DataZoneEquipment::ZoneEquipType(getEnumValue(zoneEquipTypeNamesUC, zeqTypeName));
1221 : // SpaceHVAC TODO: Copied this block from processZoneEquipmentInput section for ZoneHVAC:EquipmentList - seems this could be simplified
1222 1 : if (thisZeqSplitter.zoneEquipType == ZoneEquipType::Invalid) {
1223 0 : if (zeqTypeName == "ZONEHVAC:LOWTEMPERATURERADIANT:CONSTANTFLOW" || zeqTypeName == "ZONEHVAC:LOWTEMPERATURERADIANT:ELECTRIC") {
1224 0 : thisZeqSplitter.zoneEquipType = ZoneEquipType::LowTemperatureRadiant;
1225 0 : } else if (zeqTypeName == "WATERHEATER:HEATPUMP:WRAPPEDCONDENSER") {
1226 0 : thisZeqSplitter.zoneEquipType = DataZoneEquipment::ZoneEquipType::HeatPumpWaterHeater;
1227 : } else {
1228 0 : ShowSevereError(state, format("{}{} = {}", RoutineName, zeqSplitterModuleObject, thisZeqSplitter.Name));
1229 0 : ShowContinueError(state, format("..Invalid Equipment Type = {}", zeqTypeName));
1230 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1231 : }
1232 : }
1233 :
1234 1 : thisZeqSplitter.zoneEquipName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_equipment_name");
1235 :
1236 : // Search zone equipment list for matching equip type and name
1237 1 : bool found = false;
1238 1 : auto &thisZoneEqList = state.dataZoneEquip->ZoneEquipList(state.dataZoneEquip->ZoneEquipConfig(zoneNum).EquipListIndex);
1239 1 : for (int eqCount = 1; eqCount <= thisZoneEqList.NumOfEquipTypes; ++eqCount) {
1240 1 : if (thisZeqSplitter.zoneEquipType == thisZoneEqList.EquipType(eqCount)) {
1241 1 : if (thisZeqSplitter.zoneEquipName == thisZoneEqList.EquipName(eqCount)) {
1242 1 : found = true;
1243 : // Set index in zone equipment list pointing to this SpaceHVAC:ZoneEquipmentSplitter
1244 1 : thisZoneEqList.zoneEquipSplitterIndex = zeqSplitterNum;
1245 : // SpaceHVAC TODO: Outletnodes aren't know yet - need to set this in a later init
1246 : // thisZeqSplitter.zoneEquipOutletNodeNum = thisZoneEqList.EquipData(eqCount).OutletNodeNums(1);
1247 1 : break;
1248 : }
1249 : }
1250 : }
1251 1 : if (!found) {
1252 0 : ShowSevereError(state, format("{}{} = {}", RoutineName, zeqSplitterModuleObject, thisZeqSplitter.Name));
1253 0 : ShowContinueError(
1254 0 : state, format(".. Zone Equipment Object Type={} and Zone Equipment Name={} not found", zeqTypeName, thisZeqSplitter.zoneEquipName));
1255 0 : ShowContinueError(state, format(".. in ZoneHVAC:EquipmentList={}", thisZoneEqList.Name));
1256 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1257 0 : return;
1258 : }
1259 :
1260 1 : bool objectIsParent = true;
1261 1 : thisZeqSplitter.zoneEquipOutletNodeNum =
1262 2 : GetOnlySingleNode(state,
1263 2 : ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_equipment_outlet_node_name"),
1264 1 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
1265 : thisZeqSplitter.spaceEquipType,
1266 1 : thisZeqSplitter.Name,
1267 : DataLoopNode::NodeFluidType::Air,
1268 : DataLoopNode::ConnectionType::Inlet,
1269 : NodeInputManager::CompFluidStream::Primary,
1270 : objectIsParent);
1271 :
1272 1 : thisZeqSplitter.tstatControl = DataZoneEquipment::ZoneEquipTstatControl(
1273 1 : getEnumValue(zoneEquipTstatControlNamesUC, ip->getAlphaFieldValue(objectFields, objectSchemaProps, "thermostat_control_method")));
1274 1 : if (thisZeqSplitter.tstatControl == DataZoneEquipment::ZoneEquipTstatControl::SingleSpace) {
1275 2 : std::string spaceName = ip->getAlphaFieldValue(objectFields, objectSchemaProps, "control_space_name");
1276 1 : thisZeqSplitter.controlSpaceIndex = Util::FindItemInList(spaceName, state.dataHeatBal->space);
1277 1 : if (thisZeqSplitter.controlSpaceIndex == 0) {
1278 0 : ShowSevereError(state, format("{}{}={}", RoutineName, zeqSplitterModuleObject, thisZeqSplitter.Name));
1279 0 : ShowContinueError(state, format("Space Name={} not found.", spaceName));
1280 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1281 : }
1282 1 : }
1283 1 : thisZeqSplitter.spaceSizingBasis = DataZoneEquipment::SpaceEquipSizingBasis(
1284 1 : getEnumValue(spaceEquipSizingBasisNamesUC, ip->getAlphaFieldValue(objectFields, objectSchemaProps, "space_fraction_method")));
1285 :
1286 1 : auto extensibles = objectFields.find("spaces");
1287 1 : auto const &extensionSchemaProps = objectSchemaProps["spaces"]["items"]["properties"];
1288 1 : if (extensibles != objectFields.end()) {
1289 1 : auto &extensiblesArray = extensibles.value();
1290 1 : int const numSpaces = extensiblesArray.size();
1291 1 : thisZeqSplitter.spaces.resize(numSpaces);
1292 1 : int spaceCount = -1;
1293 4 : for (auto &extensibleInstance : extensiblesArray) {
1294 3 : ++spaceCount;
1295 3 : auto &thisZeqSpace = thisZeqSplitter.spaces[spaceCount];
1296 6 : std::string const spaceName = ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_name");
1297 3 : thisZeqSpace.spaceIndex = Util::FindItemInList(spaceName, state.dataHeatBal->space);
1298 3 : if (thisZeqSpace.spaceIndex == 0) {
1299 0 : ShowSevereError(state, format("{}{}={}", RoutineName, zeqSplitterModuleObject, thisZeqSplitter.Name));
1300 0 : ShowContinueError(state, format("Space Name={} not found.", spaceName));
1301 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1302 : } else {
1303 3 : thisZeqSpace.fraction = ip->getRealFieldValue(extensibleInstance, extensionSchemaProps, "space_fraction");
1304 3 : thisZeqSpace.spaceNodeNum =
1305 6 : GetOnlySingleNode(state,
1306 6 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_supply_node_name"),
1307 3 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
1308 : thisZeqSplitter.spaceEquipType,
1309 3 : thisZeqSplitter.Name,
1310 : DataLoopNode::NodeFluidType::Air,
1311 : DataLoopNode::ConnectionType::Outlet,
1312 : NodeInputManager::CompFluidStream::Primary,
1313 : objectIsParent);
1314 3 : if (thisZeqSplitter.controlSpaceIndex == thisZeqSpace.spaceIndex) {
1315 1 : thisZeqSplitter.controlSpaceNumber = spaceCount;
1316 : }
1317 : }
1318 4 : }
1319 : }
1320 1 : }
1321 :
1322 1 : void processZoneEquipMixerInput(EnergyPlusData &state,
1323 : std::string_view zeqMixerModuleObject,
1324 : int const zoneNum,
1325 : InputProcessor::json const objectSchemaProps,
1326 : InputProcessor::json const objectFields,
1327 : DataZoneEquipment::ZoneEquipmentMixer &thisZeqMixer)
1328 :
1329 : {
1330 : static constexpr std::string_view RoutineName("processZoneEquipMixerInput: "); // include trailing blank space
1331 1 : auto &ip = state.dataInputProcessing->inputProcessor;
1332 1 : bool objectIsParent = true;
1333 2 : thisZeqMixer.outletNodeNum = GetOnlySingleNode(state,
1334 2 : ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_equipment_inlet_node_name"),
1335 1 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
1336 : thisZeqMixer.spaceEquipType,
1337 1 : thisZeqMixer.Name,
1338 : DataLoopNode::NodeFluidType::Air,
1339 : DataLoopNode::ConnectionType::Outlet,
1340 : NodeInputManager::CompFluidStream::Primary,
1341 : objectIsParent);
1342 : // Check zone exhaust nodes
1343 1 : bool found = false;
1344 1 : auto &thisZoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(zoneNum);
1345 1 : for (int exhNodeNum : thisZoneEquipConfig.ExhaustNode) {
1346 1 : if (thisZeqMixer.outletNodeNum == exhNodeNum) {
1347 1 : found = true;
1348 1 : break;
1349 : }
1350 : }
1351 1 : if (!found) {
1352 0 : ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZeqMixer.Name));
1353 0 : ShowContinueError(state,
1354 0 : format("Zone Equipment Inlet Node Name={} is not an exhaust node for ZoneHVAC:EquipmentConnections={}.",
1355 0 : state.dataLoopNodes->NodeID(thisZeqMixer.outletNodeNum),
1356 0 : thisZoneEquipConfig.ZoneName));
1357 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1358 : }
1359 :
1360 1 : thisZeqMixer.spaceSizingBasis = DataZoneEquipment::SpaceEquipSizingBasis(
1361 1 : getEnumValue(spaceEquipSizingBasisNamesUC, ip->getAlphaFieldValue(objectFields, objectSchemaProps, "space_fraction_method")));
1362 :
1363 1 : auto extensibles = objectFields.find("spaces");
1364 1 : auto const &extensionSchemaProps = objectSchemaProps["spaces"]["items"]["properties"];
1365 1 : if (extensibles != objectFields.end()) {
1366 1 : auto &extensiblesArray = extensibles.value();
1367 1 : int const numSpaces = extensiblesArray.size();
1368 1 : thisZeqMixer.spaces.resize(numSpaces);
1369 1 : int spaceCount = -1;
1370 2 : for (auto &extensibleInstance : extensiblesArray) {
1371 1 : ++spaceCount;
1372 1 : auto &thisZeqSpace = thisZeqMixer.spaces[spaceCount];
1373 2 : std::string const spaceName = ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_name");
1374 1 : thisZeqSpace.spaceIndex = Util::FindItemInList(spaceName, state.dataHeatBal->space);
1375 1 : if (thisZeqSpace.spaceIndex == 0) {
1376 0 : ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZeqMixer.Name));
1377 0 : ShowContinueError(state, format("Space Name={} not found.", spaceName));
1378 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1379 : } else {
1380 1 : thisZeqSpace.fraction = ip->getRealFieldValue(extensibleInstance, extensionSchemaProps, "space_fraction");
1381 2 : thisZeqSpace.spaceNodeNum = GetOnlySingleNode(state,
1382 2 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_node_name"),
1383 1 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
1384 : thisZeqMixer.spaceEquipType,
1385 1 : thisZeqMixer.Name,
1386 : DataLoopNode::NodeFluidType::Air,
1387 : DataLoopNode::ConnectionType::Inlet,
1388 : NodeInputManager::CompFluidStream::Primary,
1389 : objectIsParent);
1390 : // Check space exhaust nodes
1391 1 : bool found = false;
1392 1 : auto &thisSpaceEquipConfig = state.dataZoneEquip->spaceEquipConfig(thisZeqSpace.spaceIndex);
1393 1 : for (int exhNodeNum : thisSpaceEquipConfig.ExhaustNode) {
1394 1 : if (thisZeqSpace.spaceNodeNum == exhNodeNum) {
1395 1 : found = true;
1396 1 : break;
1397 : }
1398 : }
1399 1 : if (!found) {
1400 0 : ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZeqMixer.Name));
1401 0 : ShowContinueError(state,
1402 0 : format("Space Node Name={} is not an exhaust node for SpaceHVAC:EquipmentConnections={}.",
1403 0 : state.dataLoopNodes->NodeID(thisZeqSpace.spaceNodeNum),
1404 0 : thisSpaceEquipConfig.ZoneName));
1405 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1406 : }
1407 : }
1408 2 : }
1409 : }
1410 1 : }
1411 :
1412 1 : void processZoneReturnMixerInput(EnergyPlusData &state,
1413 : std::string_view zeqMixerModuleObject,
1414 : int const zoneNum,
1415 : InputProcessor::json const objectSchemaProps,
1416 : InputProcessor::json const objectFields,
1417 : int mixerIndex)
1418 :
1419 : {
1420 : static constexpr std::string_view RoutineName("processZoneReturnMixerInput: "); // include trailing blank space
1421 1 : auto &ip = state.dataInputProcessing->inputProcessor;
1422 1 : bool objectIsParent = true;
1423 1 : auto &thisZretMixer = state.dataZoneEquip->zoneReturnMixer[mixerIndex];
1424 2 : thisZretMixer.outletNodeNum = GetOnlySingleNode(state,
1425 2 : ip->getAlphaFieldValue(objectFields, objectSchemaProps, "zone_return_air_node_name"),
1426 1 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
1427 : thisZretMixer.spaceEquipType,
1428 1 : thisZretMixer.Name,
1429 : DataLoopNode::NodeFluidType::Air,
1430 : DataLoopNode::ConnectionType::Outlet,
1431 : NodeInputManager::CompFluidStream::Primary,
1432 : objectIsParent);
1433 : // Check zone return nodes
1434 1 : bool found = false;
1435 1 : auto &thisZoneEquipConfig = state.dataZoneEquip->ZoneEquipConfig(zoneNum);
1436 1 : int nodeCounter = 0;
1437 1 : for (int retNodeNum : thisZoneEquipConfig.ReturnNode) {
1438 1 : ++nodeCounter;
1439 1 : if (thisZretMixer.outletNodeNum == retNodeNum) {
1440 1 : found = true;
1441 : // Zone return node is fed by a space return mixer
1442 1 : thisZoneEquipConfig.returnNodeSpaceMixerIndex(nodeCounter) = mixerIndex;
1443 1 : break;
1444 : }
1445 : }
1446 1 : if (!found) {
1447 0 : ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZretMixer.Name));
1448 0 : ShowContinueError(state,
1449 0 : format("Zone Equipment Return Air Node Name={} is not a return air node for ZoneHVAC:EquipmentConnections={}.",
1450 0 : state.dataLoopNodes->NodeID(thisZretMixer.outletNodeNum),
1451 0 : thisZoneEquipConfig.ZoneName));
1452 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1453 : }
1454 :
1455 1 : auto extensibles = objectFields.find("spaces");
1456 1 : auto const &extensionSchemaProps = objectSchemaProps["spaces"]["items"]["properties"];
1457 1 : if (extensibles != objectFields.end()) {
1458 1 : auto &extensiblesArray = extensibles.value();
1459 1 : int const numSpaces = extensiblesArray.size();
1460 1 : thisZretMixer.spaces.resize(numSpaces);
1461 1 : int spaceCount = -1;
1462 4 : for (auto &extensibleInstance : extensiblesArray) {
1463 3 : ++spaceCount;
1464 3 : auto &thisZeqSpace = thisZretMixer.spaces[spaceCount];
1465 6 : std::string const spaceName = ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_name");
1466 3 : thisZeqSpace.spaceIndex = Util::FindItemInList(spaceName, state.dataHeatBal->space);
1467 3 : if (thisZeqSpace.spaceIndex == 0) {
1468 0 : ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZretMixer.Name));
1469 0 : ShowContinueError(state, format("Space Name={} not found.", spaceName));
1470 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1471 : } else {
1472 3 : thisZeqSpace.spaceNodeNum =
1473 6 : GetOnlySingleNode(state,
1474 6 : ip->getAlphaFieldValue(extensibleInstance, extensionSchemaProps, "space_return_air_node_name"),
1475 3 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound,
1476 : thisZretMixer.spaceEquipType,
1477 3 : thisZretMixer.Name,
1478 : DataLoopNode::NodeFluidType::Air,
1479 : DataLoopNode::ConnectionType::Inlet,
1480 : NodeInputManager::CompFluidStream::Primary,
1481 : objectIsParent);
1482 : // Check space return nodes
1483 3 : bool found = false;
1484 3 : auto &thisSpaceEquipConfig = state.dataZoneEquip->spaceEquipConfig(thisZeqSpace.spaceIndex);
1485 3 : for (int retNodeNum : thisSpaceEquipConfig.ReturnNode) {
1486 3 : if (thisZeqSpace.spaceNodeNum == retNodeNum) {
1487 3 : found = true;
1488 3 : break;
1489 : }
1490 : }
1491 3 : if (!found) {
1492 0 : ShowSevereError(state, format("{}{}={}", RoutineName, zeqMixerModuleObject, thisZretMixer.Name));
1493 0 : ShowContinueError(state,
1494 0 : format("Space Return Air Node Name={} is not a return air node for SpaceHVAC:EquipmentConnections={}.",
1495 0 : state.dataLoopNodes->NodeID(thisZeqSpace.spaceNodeNum),
1496 0 : thisSpaceEquipConfig.ZoneName));
1497 0 : state.dataZoneEquip->GetZoneEquipmentDataErrorsFound = true;
1498 : }
1499 : }
1500 4 : }
1501 : }
1502 1 : }
1503 :
1504 4415 : bool CheckZoneEquipmentList(EnergyPlusData &state,
1505 : std::string_view const ComponentType, // Type of component
1506 : std::string_view const ComponentName, // Name of component
1507 : ObjexxFCL::Optional_int CtrlZoneNum)
1508 : {
1509 :
1510 : // FUNCTION INFORMATION:
1511 : // AUTHOR Linda Lawrie
1512 : // DATE WRITTEN May 2007
1513 : // MODIFIED na
1514 : // RE-ENGINEERED na
1515 :
1516 : // PURPOSE OF THIS FUNCTION:
1517 : // Provides a way to check if a component name is listed on a zone equipment list.
1518 :
1519 : // Return value
1520 : bool IsOnList; // True if item is on a list, false if not.
1521 :
1522 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
1523 : int Loop;
1524 : int ListLoop;
1525 : int CtrlZoneNumLocal;
1526 :
1527 4415 : CtrlZoneNumLocal = 0;
1528 4415 : IsOnList = false;
1529 68535 : for (Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) { // NumOfZoneEquipLists
1530 68535 : if (state.dataZoneEquip->ZoneEquipList(Loop).Name.empty()) continue; // dimensioned by NumOfZones. Only valid ones have names.
1531 138452 : for (ListLoop = 1; ListLoop <= state.dataZoneEquip->ZoneEquipList(Loop).NumOfEquipTypes; ++ListLoop) {
1532 :
1533 78080 : if (!Util::SameString(state.dataZoneEquip->ZoneEquipList(Loop).EquipTypeName(ListLoop), ComponentType)) continue;
1534 59453 : if (ComponentName == "*") {
1535 0 : IsOnList = true;
1536 0 : CtrlZoneNumLocal = Loop;
1537 0 : goto EquipList_exit;
1538 : }
1539 59453 : if (!Util::SameString(state.dataZoneEquip->ZoneEquipList(Loop).EquipName(ListLoop), ComponentName)) continue;
1540 4415 : IsOnList = true;
1541 4415 : CtrlZoneNumLocal = Loop;
1542 4415 : goto EquipList_exit;
1543 : }
1544 : }
1545 0 : EquipList_exit:;
1546 4415 : if (present(CtrlZoneNum)) {
1547 0 : CtrlZoneNum = CtrlZoneNumLocal;
1548 : }
1549 4415 : return IsOnList;
1550 : }
1551 :
1552 7 : int GetControlledZoneIndex(EnergyPlusData &state, std::string const &ZoneName) // Zone name to match into Controlled Zone structure
1553 : {
1554 :
1555 : // FUNCTION INFORMATION:
1556 : // AUTHOR Linda Lawrie
1557 : // DATE WRITTEN March 2008
1558 :
1559 : // PURPOSE OF THIS FUNCTION:
1560 : // This function returns the index into the Controlled Zone Equipment structure
1561 : // of the indicated zone.
1562 :
1563 7 : return Util::FindItemInList(ZoneName, state.dataZoneEquip->ZoneEquipConfig, &EquipConfiguration::ZoneName);
1564 : }
1565 :
1566 4 : int FindControlledZoneIndexFromSystemNodeNumberForZone(EnergyPlusData &state,
1567 : int const TrialZoneNodeNum) // Node number to match into Controlled Zone structure
1568 : {
1569 :
1570 : // FUNCTION INFORMATION:
1571 : // AUTHOR Brent Griffith
1572 : // DATE WRITTEN August 2013
1573 :
1574 : // PURPOSE OF THIS FUNCTION:
1575 : // This function returns the zone number for the indicated
1576 : // zone node num. Returns 0 if did not find zone node in any Zone
1577 :
1578 4 : int ControlledZoneIndex = 0; // Index into Controlled Zone structure
1579 :
1580 19 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
1581 16 : if (state.dataZoneEquip->ZoneEquipConfig(ZoneNum).IsControlled) {
1582 16 : if (TrialZoneNodeNum == state.dataZoneEquip->ZoneEquipConfig(ZoneNum).ZoneNode) {
1583 : // found it.
1584 1 : ControlledZoneIndex = ZoneNum;
1585 1 : break;
1586 : }
1587 : }
1588 : }
1589 :
1590 4 : return ControlledZoneIndex;
1591 : }
1592 :
1593 227 : int GetSystemNodeNumberForZone(EnergyPlusData &state, int const zoneNum)
1594 : {
1595 :
1596 : // FUNCTION INFORMATION:
1597 : // AUTHOR Linda Lawrie
1598 : // DATE WRITTEN March 2008
1599 :
1600 : // PURPOSE OF THIS FUNCTION:
1601 : // This function returns the system node number for the indicated
1602 : // zone. Returns 0 if the Zone is not a controlled zone.
1603 :
1604 227 : int SystemZoneNodeNumber = 0; // System node number for controlled zone
1605 :
1606 227 : if (zoneNum > 0) {
1607 227 : if (state.dataZoneEquip->ZoneEquipConfig(zoneNum).IsControlled) {
1608 227 : SystemZoneNodeNumber = state.dataZoneEquip->ZoneEquipConfig(zoneNum).ZoneNode;
1609 : }
1610 : }
1611 :
1612 227 : return SystemZoneNodeNumber;
1613 : }
1614 :
1615 122 : int GetReturnAirNodeForZone(EnergyPlusData &state,
1616 : int const zoneNum,
1617 : std::string const &NodeName, // Return air node name to match (may be blank)
1618 : std::string const &calledFromDescription // String identifying the calling function and object
1619 : )
1620 : {
1621 :
1622 : // FUNCTION INFORMATION:
1623 : // AUTHOR Linda Lawrie
1624 : // DATE WRITTEN March 2008
1625 : // MODIFIED Feb 2017 expanded for multiple return nodes in a zone
1626 :
1627 : // PURPOSE OF THIS FUNCTION:
1628 : // This function returns the return air node number for the indicated
1629 : // zone and node name. If NodeName is blank, return the first return node number,
1630 : // otherwise return the node number of the matching return node name.
1631 : // Returns 0 if the Zone is not a controlled zone or the node name does not match.
1632 :
1633 : // Return value
1634 122 : int ReturnAirNodeNumber = 0; // Return Air node number for controlled zone
1635 :
1636 122 : ReturnAirNodeNumber = 0; // default is not found
1637 122 : if (zoneNum > 0) {
1638 : {
1639 122 : auto const &thisZoneEquip(state.dataZoneEquip->ZoneEquipConfig(zoneNum));
1640 122 : if (thisZoneEquip.IsControlled) {
1641 122 : if (NodeName.empty()) {
1642 : // If NodeName is blank, return first return node number, but warn if there are multiple return nodes for this zone
1643 122 : ReturnAirNodeNumber = thisZoneEquip.ReturnNode(1);
1644 122 : if (thisZoneEquip.NumReturnNodes > 1) {
1645 0 : ShowWarningError(state,
1646 0 : format("GetReturnAirNodeForZone: {}, request for zone return node is ambiguous.", calledFromDescription));
1647 0 : ShowContinueError(state,
1648 0 : format("Zone={} has {} return nodes. First return node will be used.",
1649 0 : thisZoneEquip.ZoneName,
1650 0 : thisZoneEquip.NumReturnNodes));
1651 : }
1652 : } else {
1653 0 : for (int nodeCount = 1; nodeCount <= thisZoneEquip.NumReturnNodes; ++nodeCount) {
1654 0 : int curNodeNum = thisZoneEquip.ReturnNode(nodeCount);
1655 0 : if (NodeName == state.dataLoopNodes->NodeID(curNodeNum)) {
1656 0 : ReturnAirNodeNumber = curNodeNum;
1657 : }
1658 : }
1659 : }
1660 : }
1661 : }
1662 : }
1663 :
1664 122 : return ReturnAirNodeNumber;
1665 : }
1666 :
1667 4329 : int GetReturnNumForZone(EnergyPlusData &state,
1668 : int const zoneNum,
1669 : std::string const &NodeName // Return air node name to match (may be blank)
1670 : )
1671 : {
1672 :
1673 : // PURPOSE OF THIS FUNCTION:
1674 : // This function returns the zone return number (not the node number) for the indicated
1675 : // zone and node name. If NodeName is blank, return 1 (the first return node)
1676 : // otherwise return the index of the matching return node name.
1677 : // Returns 0 if the Zone is not a controlled zone or the node name does not match.
1678 :
1679 : // Return value
1680 4329 : int ReturnIndex = 0; // Return number for the given zone (not the node number)
1681 :
1682 4329 : if (zoneNum > 0) {
1683 4329 : if (state.dataZoneEquip->ZoneEquipConfig(zoneNum).IsControlled) {
1684 4195 : if (NodeName.empty()) {
1685 : // If NodeName is blank, return first return node number
1686 4194 : ReturnIndex = 1;
1687 : } else {
1688 2 : for (int nodeCount = 1; nodeCount <= state.dataZoneEquip->ZoneEquipConfig(zoneNum).NumReturnNodes; ++nodeCount) {
1689 1 : int curNodeNum = state.dataZoneEquip->ZoneEquipConfig(zoneNum).ReturnNode(nodeCount);
1690 1 : if (NodeName == state.dataLoopNodes->NodeID(curNodeNum)) {
1691 1 : ReturnIndex = nodeCount;
1692 : }
1693 : }
1694 : }
1695 : }
1696 : }
1697 :
1698 4329 : return ReturnIndex;
1699 : }
1700 :
1701 1 : bool VerifyLightsExhaustNodeForZone(EnergyPlusData &state, int const ZoneNum, int const ZoneExhaustNodeNum)
1702 : {
1703 1 : bool exhaustNodeError = true;
1704 :
1705 1 : for (int ExhaustNum = 1; ExhaustNum <= state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumExhaustNodes; ++ExhaustNum) {
1706 1 : if (ZoneExhaustNodeNum == state.dataZoneEquip->ZoneEquipConfig(ZoneNum).ExhaustNode(ExhaustNum)) {
1707 1 : exhaustNodeError = false;
1708 1 : break;
1709 : }
1710 : }
1711 :
1712 1 : return exhaustNodeError;
1713 : }
1714 :
1715 483 : void EquipList::getPrioritiesForInletNode(EnergyPlusData &state,
1716 : int const inletNodeNum, // Zone inlet node number to match
1717 : int &coolingPriority, // Cooling priority num for matching equipment
1718 : int &heatingPriority // Heating priority num for matching equipment
1719 : )
1720 : {
1721 483 : bool equipFound = false;
1722 599 : for (int equipNum = 1; equipNum <= this->NumOfEquipTypes; ++equipNum) {
1723 599 : if (this->EquipType(equipNum) == DataZoneEquipment::ZoneEquipType::AirDistributionUnit) {
1724 488 : if (inletNodeNum == state.dataDefineEquipment->AirDistUnit(this->EquipIndex(equipNum)).OutletNodeNum) {
1725 483 : equipFound = true;
1726 : }
1727 : }
1728 599 : if (equipFound) {
1729 483 : coolingPriority = this->CoolingPriority(equipNum);
1730 483 : heatingPriority = this->HeatingPriority(equipNum);
1731 483 : break;
1732 : }
1733 : }
1734 : // Set MinAirLoopIterationsAfterFirst for equipment that uses sequenced loads, based on zone equip load distribution scheme
1735 483 : int minIterations = state.dataHVACGlobal->MinAirLoopIterationsAfterFirst;
1736 483 : if (this->LoadDistScheme == DataZoneEquipment::LoadDist::Sequential) {
1737 : // Sequential needs one extra iterations up to the highest airterminal unit equipment number
1738 477 : minIterations = max(coolingPriority, heatingPriority, minIterations);
1739 6 : } else if (this->LoadDistScheme == DataZoneEquipment::LoadDist::Uniform) {
1740 : // Uniform needs one extra iteration which is the default
1741 4 : } else if (this->LoadDistScheme == DataZoneEquipment::LoadDist::UniformPLR) {
1742 : // UniformPLR needs two extra iterations, regardless of unit equipment number
1743 2 : minIterations = max(2, minIterations);
1744 2 : } else if (this->LoadDistScheme == DataZoneEquipment::LoadDist::SequentialUniformPLR) {
1745 : // SequentialUniformPLR needs one extra iterations up to the highest airterminal unit equipment number plus one more
1746 2 : minIterations = max((coolingPriority + 1), (heatingPriority + 1), minIterations);
1747 : }
1748 483 : state.dataHVACGlobal->MinAirLoopIterationsAfterFirst = minIterations;
1749 483 : }
1750 :
1751 85427192 : Real64 EquipList::SequentialHeatingFraction(EnergyPlusData &state, const int equipNum)
1752 : {
1753 85427192 : return ScheduleManager::GetCurrentScheduleValue(state, SequentialHeatingFractionSchedPtr(equipNum));
1754 : }
1755 :
1756 84790204 : Real64 EquipList::SequentialCoolingFraction(EnergyPlusData &state, const int equipNum)
1757 : {
1758 84790204 : return ScheduleManager::GetCurrentScheduleValue(state, SequentialCoolingFractionSchedPtr(equipNum));
1759 : }
1760 :
1761 216 : int GetZoneEquipControlledZoneNum(EnergyPlusData &state, DataZoneEquipment::ZoneEquipType const zoneEquipType, std::string const &EquipmentName)
1762 : {
1763 : static constexpr std::string_view RoutineName("GetZoneEquipControlledZoneNum: ");
1764 216 : int ControlZoneNum = 0;
1765 :
1766 1045 : for (int CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
1767 1045 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
1768 2395 : for (int Num = 1; Num <= state.dataZoneEquip->ZoneEquipList(CtrlZone).NumOfEquipTypes; ++Num) {
1769 2377 : if (zoneEquipType == state.dataZoneEquip->ZoneEquipList(CtrlZone).EquipType(Num) &&
1770 722 : Util::SameString(EquipmentName, state.dataZoneEquip->ZoneEquipList(CtrlZone).EquipName(Num))) {
1771 216 : return ControlZoneNum = CtrlZone;
1772 : }
1773 : }
1774 : }
1775 0 : ShowSevereError(state,
1776 0 : fmt::format("{}{}=\"{}\" is not on any ZoneHVAC:Equipmentlist. It will not be simulated.",
1777 : RoutineName,
1778 0 : zoneEquipTypeNamesUC[(int)zoneEquipType],
1779 : EquipmentName));
1780 0 : return ControlZoneNum;
1781 : }
1782 :
1783 1 : void CheckSharedExhaust(EnergyPlusData &state)
1784 : {
1785 1 : int ExhastNodeNum = 0;
1786 7 : for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
1787 6 : if (state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumReturnNodes < 2) continue;
1788 0 : for (int nodeCount = 1; nodeCount <= state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumReturnNodes; ++nodeCount) {
1789 0 : if (state.dataZoneEquip->ZoneEquipConfig(ZoneNum).SharedExhaustNode(nodeCount) == LightReturnExhaustConfig::Shared) continue;
1790 0 : ExhastNodeNum = state.dataZoneEquip->ZoneEquipConfig(ZoneNum).ReturnNodeExhaustNodeNum(nodeCount);
1791 0 : if (ExhastNodeNum > 0) {
1792 0 : state.dataZoneEquip->ZoneEquipConfig(ZoneNum).SharedExhaustNode(nodeCount) = LightReturnExhaustConfig::Single;
1793 0 : for (int nodeCount1 = nodeCount + 1; nodeCount1 <= state.dataZoneEquip->ZoneEquipConfig(ZoneNum).NumReturnNodes; ++nodeCount1) {
1794 0 : if (ExhastNodeNum == state.dataZoneEquip->ZoneEquipConfig(ZoneNum).ReturnNodeExhaustNodeNum(nodeCount1)) {
1795 0 : state.dataZoneEquip->ZoneEquipConfig(ZoneNum).SharedExhaustNode(nodeCount) = LightReturnExhaustConfig::Multi;
1796 0 : state.dataZoneEquip->ZoneEquipConfig(ZoneNum).SharedExhaustNode(nodeCount1) = LightReturnExhaustConfig::Shared;
1797 : }
1798 : }
1799 : }
1800 : }
1801 : }
1802 1 : }
1803 :
1804 51185428 : void EquipConfiguration::setTotalInletFlows(EnergyPlusData &state)
1805 : {
1806 51185428 : this->TotInletAirMassFlowRate = 0.0;
1807 51185428 : Real64 TotInletAirMassFlowRateMax = 0.0;
1808 51185428 : Real64 TotInletAirMassFlowRateMaxAvail = 0.0;
1809 51185428 : Real64 TotInletAirMassFlowRateMin = 0.0;
1810 51185428 : Real64 TotInletAirMassFlowRateMinAvail = 0.0;
1811 103475924 : for (int NodeNum = 1; NodeNum <= this->NumInletNodes; ++NodeNum) {
1812 : {
1813 52290496 : auto const &thisNode(state.dataLoopNodes->Node(this->InletNode(NodeNum)));
1814 52290496 : this->TotInletAirMassFlowRate += thisNode.MassFlowRate;
1815 52290496 : TotInletAirMassFlowRateMax += thisNode.MassFlowRateMax;
1816 52290496 : TotInletAirMassFlowRateMaxAvail += thisNode.MassFlowRateMaxAvail;
1817 52290496 : TotInletAirMassFlowRateMin += thisNode.MassFlowRateMin;
1818 52290496 : TotInletAirMassFlowRateMinAvail += thisNode.MassFlowRateMinAvail;
1819 : }
1820 : }
1821 51185428 : auto &zoneSpaceNode = state.dataLoopNodes->Node(this->ZoneNode);
1822 51185428 : zoneSpaceNode.MassFlowRate = this->TotInletAirMassFlowRate;
1823 51185428 : zoneSpaceNode.MassFlowRateMax = TotInletAirMassFlowRateMax;
1824 51185428 : zoneSpaceNode.MassFlowRateMaxAvail = TotInletAirMassFlowRateMaxAvail;
1825 51185428 : zoneSpaceNode.MassFlowRateMin = TotInletAirMassFlowRateMin;
1826 51185428 : zoneSpaceNode.MassFlowRateMinAvail = TotInletAirMassFlowRateMinAvail;
1827 51185428 : }
1828 :
1829 83763 : void scaleInletFlows(EnergyPlusData &state, int const zoneNodeNum, int const spaceNodeNum, Real64 const frac)
1830 : {
1831 83763 : assert(zoneNodeNum > 0);
1832 83763 : assert(spaceNodeNum > 0);
1833 83763 : auto &zoneNode = state.dataLoopNodes->Node(zoneNodeNum);
1834 83763 : auto &spaceNode = state.dataLoopNodes->Node(spaceNodeNum);
1835 83763 : spaceNode.MassFlowRate = zoneNode.MassFlowRate * frac;
1836 83763 : spaceNode.MassFlowRateMax = zoneNode.MassFlowRateMax * frac;
1837 83763 : spaceNode.MassFlowRateMaxAvail = zoneNode.MassFlowRateMaxAvail * frac;
1838 83763 : spaceNode.MassFlowRateMin = zoneNode.MassFlowRateMin * frac;
1839 83763 : spaceNode.MassFlowRateMinAvail = zoneNode.MassFlowRateMinAvail * frac;
1840 83763 : }
1841 :
1842 2 : void ZoneEquipmentSplitterMixer::size(EnergyPlusData &state)
1843 : {
1844 4 : bool anyAutoSize = std::any_of(spaces.begin(), spaces.end(), [](ZoneEquipSplitterMixerSpace &s) { return s.fraction == DataSizing::AutoSize; });
1845 2 : if (!anyAutoSize) return;
1846 :
1847 : // Calculate total of space fraction basis value across all spaces for this splitter or mixer
1848 : // including spaces which are not autosized here.
1849 2 : Real64 spacesTotal = 0.0;
1850 2 : switch (this->spaceSizingBasis) {
1851 2 : case DataZoneEquipment::SpaceEquipSizingBasis::DesignCoolingLoad:
1852 6 : for (auto &thisSpace : this->spaces) {
1853 4 : spacesTotal += state.dataSize->FinalSpaceSizing(thisSpace.spaceIndex).DesCoolLoad;
1854 2 : }
1855 2 : break;
1856 0 : case DataZoneEquipment::SpaceEquipSizingBasis::DesignHeatingLoad:
1857 0 : for (auto &thisSpace : this->spaces) {
1858 0 : spacesTotal += state.dataSize->FinalSpaceSizing(thisSpace.spaceIndex).DesHeatLoad;
1859 0 : }
1860 0 : break;
1861 0 : case DataZoneEquipment::SpaceEquipSizingBasis::FloorArea:
1862 0 : for (auto &thisSpace : this->spaces) {
1863 0 : spacesTotal += state.dataHeatBal->space(thisSpace.spaceIndex).FloorArea;
1864 0 : }
1865 0 : break;
1866 0 : case DataZoneEquipment::SpaceEquipSizingBasis::Volume:
1867 0 : for (auto &thisSpace : this->spaces) {
1868 0 : spacesTotal += state.dataHeatBal->space(thisSpace.spaceIndex).Volume;
1869 0 : }
1870 0 : break;
1871 0 : case DataZoneEquipment::SpaceEquipSizingBasis::PerimeterLength:
1872 0 : ShowFatalError(state,
1873 0 : format("ZoneEquipmentSplitterMixer::size: Space Fraction Method={} not supported for {}={}",
1874 0 : DataZoneEquipment::spaceEquipSizingBasisNamesUC[(int)this->spaceSizingBasis],
1875 0 : BranchNodeConnections::ConnectionObjectTypeNames[(int)this->spaceEquipType],
1876 0 : this->Name));
1877 0 : break;
1878 0 : default:
1879 : // If method is not set, then return
1880 0 : return;
1881 : break;
1882 : }
1883 :
1884 2 : if (spacesTotal < 0.00001) {
1885 0 : ShowSevereError(state,
1886 0 : format("ZoneEquipmentSplitterMixer::size: Total {} is zero for {}={}. Unable to autosize Space Fractions.",
1887 0 : DataZoneEquipment::spaceEquipSizingBasisNamesUC[(int)this->spaceSizingBasis],
1888 0 : BranchNodeConnections::ConnectionObjectTypeNames[(int)this->spaceEquipType],
1889 0 : this->Name));
1890 0 : Real64 spaceFrac = 1.0 / (int)this->spaces.size();
1891 0 : ShowContinueError(state, format("Setting space fractions to 1/number of spaces = {}.", spaceFrac));
1892 0 : for (auto &thisSpace : this->spaces) {
1893 0 : thisSpace.fraction = spaceFrac;
1894 0 : }
1895 0 : return;
1896 : }
1897 :
1898 : // Calculate space fractions
1899 2 : int spaceCounter = 0;
1900 6 : for (auto &thisSpace : this->spaces) {
1901 4 : ++spaceCounter;
1902 4 : if (thisSpace.fraction == DataSizing::AutoSize) {
1903 4 : switch (this->spaceSizingBasis) {
1904 4 : case DataZoneEquipment::SpaceEquipSizingBasis::DesignCoolingLoad:
1905 4 : thisSpace.fraction = state.dataSize->FinalSpaceSizing(thisSpace.spaceIndex).DesCoolLoad / spacesTotal;
1906 4 : break;
1907 0 : case DataZoneEquipment::SpaceEquipSizingBasis::DesignHeatingLoad:
1908 0 : thisSpace.fraction = state.dataSize->FinalSpaceSizing(thisSpace.spaceIndex).DesHeatLoad / spacesTotal;
1909 0 : break;
1910 0 : case DataZoneEquipment::SpaceEquipSizingBasis::FloorArea:
1911 0 : thisSpace.fraction = state.dataHeatBal->space(thisSpace.spaceIndex).FloorArea / spacesTotal;
1912 0 : break;
1913 0 : case DataZoneEquipment::SpaceEquipSizingBasis::Volume:
1914 0 : thisSpace.fraction = state.dataHeatBal->space(thisSpace.spaceIndex).Volume / spacesTotal;
1915 0 : break;
1916 0 : case DataZoneEquipment::SpaceEquipSizingBasis::PerimeterLength:
1917 0 : ShowFatalError(state,
1918 0 : format("ZoneEquipmentSplitterMixer::size: Space Fraction Method={} not supported for {}={}",
1919 0 : DataZoneEquipment::spaceEquipSizingBasisNamesUC[(int)this->spaceSizingBasis],
1920 0 : BranchNodeConnections::ConnectionObjectTypeNames[(int)this->spaceEquipType],
1921 0 : this->Name));
1922 0 : break;
1923 0 : default:
1924 0 : break;
1925 : }
1926 16 : BaseSizer::reportSizerOutput(state,
1927 4 : BranchNodeConnections::ConnectionObjectTypeNames[(int)this->spaceEquipType],
1928 : this->Name,
1929 8 : format("Space {} Fraction", spaceCounter),
1930 : thisSpace.fraction);
1931 : }
1932 2 : }
1933 : }
1934 :
1935 8928 : void ZoneMixer::setOutletConditions(EnergyPlusData &state)
1936 : {
1937 8928 : if (this->outletNodeNum == 0) return;
1938 :
1939 8928 : Real64 sumEnthalpy = 0.0;
1940 8928 : Real64 sumHumRat = 0.0;
1941 8928 : Real64 sumCO2 = 0.0;
1942 8928 : Real64 sumGenContam = 0.0;
1943 8928 : Real64 sumPressure = 0.0;
1944 8928 : Real64 sumFractions = 0.0;
1945 8928 : auto &outletNode = state.dataLoopNodes->Node(this->outletNodeNum);
1946 26784 : for (auto &mixerSpace : this->spaces) {
1947 17856 : auto &spaceOutletNode = state.dataLoopNodes->Node(mixerSpace.spaceNodeNum);
1948 17856 : sumEnthalpy += spaceOutletNode.Enthalpy * mixerSpace.fraction;
1949 17856 : sumHumRat += spaceOutletNode.HumRat * mixerSpace.fraction;
1950 17856 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
1951 0 : sumCO2 += spaceOutletNode.CO2 * mixerSpace.fraction;
1952 : }
1953 17856 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
1954 0 : sumGenContam += spaceOutletNode.GenContam * mixerSpace.fraction;
1955 : }
1956 17856 : sumPressure += spaceOutletNode.Press * mixerSpace.fraction;
1957 17856 : sumFractions += mixerSpace.fraction;
1958 8928 : }
1959 :
1960 : // For SpaceHVAC:ZoneReturnMixer, the fractions are dynamic and could be zero if there is no flow
1961 8928 : if (sumFractions > 0) {
1962 8917 : outletNode.Enthalpy = sumEnthalpy / sumFractions;
1963 8917 : outletNode.HumRat = sumHumRat / sumFractions;
1964 8917 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
1965 0 : outletNode.CO2 = sumCO2 / sumFractions;
1966 : }
1967 8917 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
1968 0 : outletNode.GenContam = sumGenContam / sumFractions;
1969 : }
1970 8917 : outletNode.Press = sumPressure / sumFractions;
1971 :
1972 : // Use Enthalpy and humidity ratio to get outlet temperature from psych chart
1973 8917 : outletNode.Temp = Psychrometrics::PsyTdbFnHW(outletNode.Enthalpy, outletNode.HumRat);
1974 : }
1975 : }
1976 :
1977 4464 : void ZoneReturnMixer::setInletConditions(EnergyPlusData &state)
1978 : {
1979 17856 : for (auto &mixerSpace : this->spaces) {
1980 13392 : auto &spaceOutletNode = state.dataLoopNodes->Node(mixerSpace.spaceNodeNum);
1981 13392 : int spaceZoneNodeNum = state.dataZoneEquip->spaceEquipConfig(mixerSpace.spaceIndex).ZoneNode;
1982 13392 : auto &spaceNode = state.dataLoopNodes->Node(spaceZoneNodeNum);
1983 13392 : spaceOutletNode.Temp = spaceNode.Temp;
1984 13392 : spaceOutletNode.HumRat = spaceNode.HumRat;
1985 13392 : spaceOutletNode.Enthalpy = spaceNode.Enthalpy;
1986 13392 : spaceOutletNode.Press = spaceNode.Press;
1987 13392 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
1988 0 : spaceOutletNode.CO2 = spaceNode.CO2;
1989 : }
1990 13392 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
1991 0 : spaceOutletNode.GenContam = spaceNode.GenContam;
1992 : }
1993 4464 : }
1994 4464 : }
1995 4464 : void ZoneEquipmentMixer::setInletFlows(EnergyPlusData &state)
1996 : {
1997 4464 : if (this->outletNodeNum == 0) return;
1998 :
1999 4464 : auto &equipInletNode = state.dataLoopNodes->Node(this->outletNodeNum);
2000 8928 : for (auto &mixerSpace : this->spaces) {
2001 4464 : auto &spaceOutletNode = state.dataLoopNodes->Node(mixerSpace.spaceNodeNum);
2002 4464 : spaceOutletNode.MassFlowRate = equipInletNode.MassFlowRate * mixerSpace.fraction;
2003 4464 : spaceOutletNode.MassFlowRateMaxAvail = equipInletNode.MassFlowRateMaxAvail * mixerSpace.fraction;
2004 4464 : spaceOutletNode.MassFlowRateMinAvail = equipInletNode.MassFlowRateMinAvail * mixerSpace.fraction;
2005 4464 : }
2006 : }
2007 :
2008 4464 : void ZoneReturnMixer::setInletFlows(EnergyPlusData &state)
2009 : {
2010 4464 : if (this->outletNodeNum == 0) return;
2011 4464 : auto &outletNode = state.dataLoopNodes->Node(this->outletNodeNum);
2012 :
2013 4464 : Real64 sumMixerInletMassFlow = 0;
2014 17856 : for (auto const &mixerSpace : this->spaces) {
2015 : // calc return flows for spaces feeding this mixer
2016 13392 : auto &spaceEquipConfig = state.dataZoneEquip->spaceEquipConfig(mixerSpace.spaceIndex);
2017 13392 : Real64 outletMassFlowRate = outletNode.MassFlowRate; // calcReturnFlows might adjust this parameter value, so make a copy here
2018 13392 : Real64 spaceReturnFlow = 0.0;
2019 13392 : spaceEquipConfig.calcReturnFlows(state, outletMassFlowRate, spaceReturnFlow);
2020 13392 : sumMixerInletMassFlow += spaceReturnFlow;
2021 4464 : }
2022 :
2023 17856 : for (auto &mixerSpace : this->spaces) {
2024 13392 : auto &spaceOutletNode = state.dataLoopNodes->Node(mixerSpace.spaceNodeNum);
2025 : // For return mixer, fraction is calculated every time step, not a user input
2026 13392 : if (sumMixerInletMassFlow > 0.0) {
2027 13359 : mixerSpace.fraction = spaceOutletNode.MassFlowRate / sumMixerInletMassFlow;
2028 : } else {
2029 33 : mixerSpace.fraction = 0.0;
2030 : }
2031 13392 : spaceOutletNode.MassFlowRate = outletNode.MassFlowRate * mixerSpace.fraction;
2032 13392 : spaceOutletNode.MassFlowRateMaxAvail = outletNode.MassFlowRateMaxAvail * mixerSpace.fraction;
2033 13392 : spaceOutletNode.MassFlowRateMinAvail = outletNode.MassFlowRateMinAvail * mixerSpace.fraction;
2034 4464 : }
2035 : }
2036 :
2037 8928 : void ZoneEquipmentSplitter::adjustLoads(EnergyPlusData &state, int zoneNum, int equipTypeNum)
2038 : {
2039 8928 : auto &thisZoneEnergyDemand = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum);
2040 8928 : auto &thisZoneMoistureDemand = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum);
2041 8928 : Real64 sensibleRatio = 1.0;
2042 8928 : Real64 latentRatio = 1.0;
2043 8928 : switch (this->tstatControl) {
2044 0 : case DataZoneEquipment::ZoneEquipTstatControl::Ideal:
2045 0 : return;
2046 : break; // Do nothing
2047 8928 : case DataZoneEquipment::ZoneEquipTstatControl::SingleSpace: {
2048 8928 : Real64 controlSpaceFrac = this->spaces[this->controlSpaceNumber].fraction;
2049 8928 : if (controlSpaceFrac > 0.0) {
2050 8928 : if (thisZoneEnergyDemand.RemainingOutputRequired != 0.0) {
2051 8900 : sensibleRatio = (state.dataZoneEnergyDemand->spaceSysEnergyDemand(this->controlSpaceIndex).RemainingOutputRequired /
2052 8900 : thisZoneEnergyDemand.RemainingOutputRequired) /
2053 : controlSpaceFrac;
2054 : }
2055 8928 : if (thisZoneMoistureDemand.RemainingOutputRequired != 0.0) {
2056 0 : latentRatio = (state.dataZoneEnergyDemand->spaceSysMoistureDemand(this->controlSpaceIndex).RemainingOutputRequired /
2057 0 : thisZoneMoistureDemand.RemainingOutputRequired) /
2058 : controlSpaceFrac;
2059 : }
2060 : }
2061 8928 : } break;
2062 0 : case DataZoneEquipment::ZoneEquipTstatControl::Maximum: {
2063 0 : int maxSpaceIndex = 0;
2064 0 : Real64 maxDeltaTemp = 0.0; // Only positive deltaTemps are relevant
2065 0 : Real64 maxSpaceFrac = 1.0;
2066 0 : for (auto &splitterSpace : this->spaces) {
2067 : Real64 spaceTemp =
2068 0 : state.dataZoneTempPredictorCorrector->spaceHeatBalance(splitterSpace.spaceIndex).T1; // Based on calcPredictedSystemLoad usage
2069 0 : Real64 spaceDeltaTemp = max((state.dataHeatBalFanSys->ZoneThermostatSetPointLo(zoneNum) - spaceTemp),
2070 0 : (spaceTemp - state.dataHeatBalFanSys->ZoneThermostatSetPointHi(zoneNum)));
2071 0 : if (spaceDeltaTemp > maxDeltaTemp) {
2072 0 : maxSpaceIndex = splitterSpace.spaceIndex;
2073 0 : maxSpaceFrac = splitterSpace.fraction;
2074 0 : maxDeltaTemp = spaceDeltaTemp;
2075 : }
2076 0 : }
2077 0 : if ((maxSpaceIndex > 0) && (maxSpaceFrac > 0.0)) {
2078 0 : if (thisZoneEnergyDemand.RemainingOutputRequired != 0.0) {
2079 0 : sensibleRatio = (state.dataZoneEnergyDemand->spaceSysEnergyDemand(maxSpaceIndex).RemainingOutputRequired /
2080 0 : thisZoneEnergyDemand.RemainingOutputRequired) /
2081 : maxSpaceFrac;
2082 : }
2083 0 : if (thisZoneMoistureDemand.RemainingOutputRequired != 0.0) {
2084 0 : latentRatio = (state.dataZoneEnergyDemand->spaceSysMoistureDemand(maxSpaceIndex).RemainingOutputRequired /
2085 0 : thisZoneMoistureDemand.RemainingOutputRequired) /
2086 : maxSpaceFrac;
2087 : }
2088 : }
2089 0 : } break;
2090 0 : default:
2091 0 : break;
2092 : }
2093 : // Save unadjusted zone loads to restore later
2094 8928 : this->saveZoneSysSensibleDemand = thisZoneEnergyDemand;
2095 8928 : this->saveZoneSysMoistureDemand = thisZoneMoistureDemand;
2096 : // Apply zone load adjustment
2097 17856 : ZoneEquipmentManager::adjustSystemOutputRequired(sensibleRatio,
2098 : latentRatio,
2099 8928 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum),
2100 8928 : state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum),
2101 : equipTypeNum);
2102 : }
2103 :
2104 8928 : void ZoneEquipmentSplitter::distributeOutput(EnergyPlusData &state,
2105 : int const zoneNum,
2106 : Real64 const sysOutputProvided,
2107 : Real64 const latOutputProvided,
2108 : Real64 const nonAirSysOutput,
2109 : int const equipTypeNum)
2110 : {
2111 35712 : for (auto &splitterSpace : this->spaces) {
2112 26784 : if (this->tstatControl != DataZoneEquipment::ZoneEquipTstatControl::Ideal) {
2113 : // Restore zone loads to unadjusted values (for all ZoneEquipTstatControl types except Ideal)
2114 26784 : state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum) = this->saveZoneSysSensibleDemand;
2115 26784 : state.dataZoneEnergyDemand->ZoneSysMoistureDemand(zoneNum) = this->saveZoneSysMoistureDemand;
2116 : }
2117 :
2118 26784 : Real64 spaceFraction = splitterSpace.fraction;
2119 26784 : if (this->tstatControl == DataZoneEquipment::ZoneEquipTstatControl::Ideal) {
2120 : // Proportion output by sensible space load / zone load (varies every timestep, overrides outputFraction)
2121 0 : auto &thisZoneSysEnergyDemand = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(zoneNum);
2122 0 : if (thisZoneSysEnergyDemand.RemainingOutputRequired != 0.0) {
2123 0 : spaceFraction = state.dataZoneEnergyDemand->spaceSysEnergyDemand(splitterSpace.spaceIndex).RemainingOutputRequired /
2124 0 : thisZoneSysEnergyDemand.RemainingOutputRequired;
2125 : }
2126 : }
2127 :
2128 26784 : Real64 spaceSysOutputProvided = sysOutputProvided * spaceFraction;
2129 26784 : Real64 spaceLatOutputProvided = latOutputProvided * spaceFraction;
2130 26784 : state.dataZoneTempPredictorCorrector->spaceHeatBalance(splitterSpace.spaceIndex).NonAirSystemResponse += nonAirSysOutput * spaceFraction;
2131 26784 : if (this->zoneEquipOutletNodeNum > 0 && splitterSpace.spaceNodeNum > 0) {
2132 26784 : auto &equipOutletNode = state.dataLoopNodes->Node(this->zoneEquipOutletNodeNum);
2133 26784 : auto &spaceInletNode = state.dataLoopNodes->Node(splitterSpace.spaceNodeNum);
2134 26784 : spaceInletNode.MassFlowRate = equipOutletNode.MassFlowRate * spaceFraction;
2135 26784 : spaceInletNode.MassFlowRateMaxAvail = equipOutletNode.MassFlowRateMaxAvail * spaceFraction;
2136 26784 : spaceInletNode.MassFlowRateMinAvail = equipOutletNode.MassFlowRateMinAvail * spaceFraction;
2137 26784 : spaceInletNode.Temp = equipOutletNode.Temp;
2138 26784 : spaceInletNode.HumRat = equipOutletNode.HumRat;
2139 26784 : spaceInletNode.CO2 = equipOutletNode.CO2;
2140 : }
2141 26784 : ZoneEquipmentManager::updateSystemOutputRequired(state,
2142 : zoneNum,
2143 : spaceSysOutputProvided,
2144 : spaceLatOutputProvided,
2145 26784 : state.dataZoneEnergyDemand->spaceSysEnergyDemand(splitterSpace.spaceIndex),
2146 26784 : state.dataZoneEnergyDemand->spaceSysMoistureDemand(splitterSpace.spaceIndex),
2147 : equipTypeNum);
2148 8928 : }
2149 8928 : }
2150 :
2151 42226 : void EquipConfiguration::beginEnvirnInit(EnergyPlusData &state)
2152 : {
2153 42226 : auto &zoneNode = state.dataLoopNodes->Node(this->ZoneNode);
2154 42226 : zoneNode.Temp = 20.0;
2155 42226 : zoneNode.MassFlowRate = 0.0;
2156 42226 : zoneNode.Quality = 1.0;
2157 42226 : zoneNode.Press = state.dataEnvrn->OutBaroPress;
2158 42226 : zoneNode.HumRat = state.dataEnvrn->OutHumRat;
2159 42226 : zoneNode.Enthalpy = Psychrometrics::PsyHFnTdbW(zoneNode.Temp, zoneNode.HumRat);
2160 42226 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
2161 317 : zoneNode.CO2 = state.dataContaminantBalance->OutdoorCO2;
2162 : }
2163 42226 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
2164 117 : zoneNode.GenContam = state.dataContaminantBalance->OutdoorGC;
2165 : }
2166 :
2167 86242 : for (int const nodeNum : this->InletNode) {
2168 44016 : auto &inNode = state.dataLoopNodes->Node(nodeNum);
2169 44016 : inNode.Temp = 20.0;
2170 44016 : inNode.MassFlowRate = 0.0;
2171 44016 : inNode.Quality = 1.0;
2172 44016 : inNode.Press = state.dataEnvrn->OutBaroPress;
2173 44016 : inNode.HumRat = state.dataEnvrn->OutHumRat;
2174 44016 : inNode.Enthalpy = Psychrometrics::PsyHFnTdbW(inNode.Temp, inNode.HumRat);
2175 44016 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
2176 281 : inNode.CO2 = state.dataContaminantBalance->OutdoorCO2;
2177 : }
2178 44016 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
2179 81 : inNode.GenContam = state.dataContaminantBalance->OutdoorGC;
2180 : }
2181 : }
2182 :
2183 50672 : for (int const nodeNum : this->ExhaustNode) {
2184 8446 : auto &exhNode = state.dataLoopNodes->Node(nodeNum);
2185 8446 : exhNode.Temp = 20.0;
2186 8446 : exhNode.MassFlowRate = 0.0;
2187 8446 : exhNode.Quality = 1.0;
2188 8446 : exhNode.Press = state.dataEnvrn->OutBaroPress;
2189 8446 : exhNode.HumRat = state.dataEnvrn->OutHumRat;
2190 8446 : exhNode.Enthalpy = Psychrometrics::PsyHFnTdbW(exhNode.Temp, exhNode.HumRat);
2191 8446 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
2192 130 : exhNode.CO2 = state.dataContaminantBalance->OutdoorCO2;
2193 : }
2194 8446 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
2195 30 : exhNode.GenContam = state.dataContaminantBalance->OutdoorGC;
2196 : }
2197 : }
2198 :
2199 : // BG CR 7122 following resets return air node.
2200 42226 : int NumRetNodes = this->NumReturnNodes;
2201 42226 : if (NumRetNodes > 0) {
2202 84489 : for (int const nodeNum : this->ReturnNode) {
2203 42272 : auto &returnNode = state.dataLoopNodes->Node(nodeNum);
2204 42272 : returnNode.Temp = 20.0;
2205 42272 : returnNode.MassFlowRate = 0.0;
2206 42272 : returnNode.Quality = 1.0;
2207 42272 : returnNode.Press = state.dataEnvrn->OutBaroPress;
2208 42272 : returnNode.HumRat = state.dataEnvrn->OutHumRat;
2209 42272 : returnNode.Enthalpy = Psychrometrics::PsyHFnTdbW(returnNode.Temp, returnNode.HumRat);
2210 42272 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
2211 317 : returnNode.CO2 = state.dataContaminantBalance->OutdoorCO2;
2212 : }
2213 42272 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
2214 117 : returnNode.GenContam = state.dataContaminantBalance->OutdoorGC;
2215 : }
2216 : }
2217 : }
2218 42226 : }
2219 :
2220 50656903 : void EquipConfiguration::hvacTimeStepInit(EnergyPlusData &state, bool FirstHVACIteration)
2221 : {
2222 50656903 : auto &zoneNode = state.dataLoopNodes->Node(this->ZoneNode);
2223 50656903 : this->ExcessZoneExh = 0.0;
2224 :
2225 50656903 : if (FirstHVACIteration) {
2226 30216861 : for (int const nodeNum : this->ExhaustNode) {
2227 4466703 : auto &exhNode = state.dataLoopNodes->Node(nodeNum);
2228 4466703 : exhNode.Temp = zoneNode.Temp;
2229 4466703 : exhNode.HumRat = zoneNode.HumRat;
2230 4466703 : exhNode.Enthalpy = zoneNode.Enthalpy;
2231 4466703 : exhNode.Press = zoneNode.Press;
2232 4466703 : exhNode.Quality = zoneNode.Quality;
2233 4466703 : exhNode.MassFlowRate = 0.0;
2234 4466703 : exhNode.MassFlowRateMaxAvail = 0.0;
2235 4466703 : exhNode.MassFlowRateMinAvail = 0.0;
2236 4466703 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
2237 113007 : exhNode.CO2 = zoneNode.CO2;
2238 : }
2239 4466703 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
2240 74282 : exhNode.GenContam = zoneNode.GenContam;
2241 : }
2242 : }
2243 : }
2244 50656903 : }
2245 :
2246 51174061 : void EquipConfiguration::calcReturnFlows(EnergyPlusData &state,
2247 : Real64 &ExpTotalReturnMassFlow, // Expected total return air mass flow rate
2248 : Real64 &FinalTotalReturnMassFlow // Final total return air mass flow rate
2249 : )
2250 : {
2251 51174061 : int numRetNodes = this->NumReturnNodes;
2252 51174061 : Real64 totReturnFlow = 0.0; // Total flow to all return nodes in the zone (kg/s)
2253 51174061 : Real64 totVarReturnFlow =
2254 : 0.0; // Total variable return flow, for return nodes connected to an airloop with an OA system or not with specified flow (kg/s)
2255 51174061 : Real64 returnSchedFrac = ScheduleManager::GetCurrentScheduleValue(state, this->ReturnFlowSchedPtrNum);
2256 51174061 : this->FixedReturnFlow = false;
2257 51174061 : FinalTotalReturnMassFlow = 0.0;
2258 51174061 : this->TotAvailAirLoopOA = 0.0;
2259 :
2260 : // Set initial flow rate for each return node
2261 102435869 : for (int returnNum = 1; returnNum <= numRetNodes; ++returnNum) {
2262 51261808 : int retNode = this->ReturnNode(returnNum);
2263 :
2264 51261808 : if (retNode > 0) {
2265 51261808 : Real64 returnNodeMassFlow = 0.0;
2266 51261808 : auto &retNodeData(state.dataLoopNodes->Node(retNode));
2267 :
2268 51261808 : int inletNum = this->ReturnNodeInletNum(returnNum); // which inlet node matches this return node (same airloop)
2269 51261808 : int ADUNum = 0;
2270 51261808 : if (inletNum > 0) ADUNum = this->InletNodeADUNum(inletNum);
2271 51261808 : int airLoop = this->ReturnNodeAirLoopNum(returnNum);
2272 51261808 : Real64 airLoopReturnFrac = 1.0;
2273 51261808 : if (airLoop > 0) {
2274 : // Establish corresponding airloop inlet(s) mass flow rate and set return node max/min/maxavail
2275 36327653 : Real64 inletMassFlow = 0.0;
2276 36327653 : int maxMinNodeNum = 0;
2277 36327653 : auto &thisAirLoopFlow(state.dataAirLoop->AirLoopFlow(airLoop));
2278 36327653 : if (ADUNum > 0) {
2279 : // Zone return node could carry supply flow to zone without leaks plus any induced flow from plenum (but don't include other
2280 : // secondary flows from exhaust nodes)
2281 36187676 : inletMassFlow = state.dataDefineEquipment->AirDistUnit(ADUNum).MassFlowRateZSup +
2282 36187676 : state.dataDefineEquipment->AirDistUnit(ADUNum).MassFlowRatePlenInd;
2283 36187676 : maxMinNodeNum = state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum;
2284 139977 : } else if (inletNum > 0) {
2285 : // If not connected to an ADU, then use the inlet node flow
2286 139977 : inletMassFlow = state.dataLoopNodes->Node(this->InletNode(inletNum)).MassFlowRate;
2287 139977 : maxMinNodeNum = this->InletNode(inletNum);
2288 : }
2289 36327653 : if (maxMinNodeNum > 0) {
2290 36327653 : auto const &maxMinNodeData(state.dataLoopNodes->Node(maxMinNodeNum));
2291 36327653 : retNodeData.MassFlowRateMax = maxMinNodeData.MassFlowRateMax;
2292 36327653 : retNodeData.MassFlowRateMin = maxMinNodeData.MassFlowRateMin;
2293 36327653 : retNodeData.MassFlowRateMaxAvail = maxMinNodeData.MassFlowRateMaxAvail;
2294 : } else {
2295 0 : auto const &zoneNodeData(state.dataLoopNodes->Node(this->ZoneNode));
2296 0 : retNodeData.MassFlowRateMax = zoneNodeData.MassFlowRateMax;
2297 0 : retNodeData.MassFlowRateMin = zoneNodeData.MassFlowRateMin;
2298 0 : retNodeData.MassFlowRateMaxAvail = zoneNodeData.MassFlowRateMaxAvail;
2299 : }
2300 :
2301 36327653 : airLoopReturnFrac = thisAirLoopFlow.DesReturnFrac;
2302 36327653 : if (state.dataAirSystemsData->PrimaryAirSystems(airLoop).OASysExists && (thisAirLoopFlow.MaxOutAir > 0.0)) {
2303 : // Set return flow as fraction of matching inlet node flow if there is an OA system and available OA flow > 0.0
2304 33903382 : returnNodeMassFlow = airLoopReturnFrac * inletMassFlow;
2305 33903382 : this->TotAvailAirLoopOA += thisAirLoopFlow.MaxOutAir;
2306 : } else {
2307 : // Set return flow to matching inlet node flow
2308 2424271 : returnNodeMassFlow = inletMassFlow;
2309 2424271 : this->FixedReturnFlow(returnNum) = true;
2310 : }
2311 : } else {
2312 14934155 : returnNodeMassFlow = 0.0;
2313 : }
2314 :
2315 : // Return node 1 is special
2316 51261808 : if (returnNum == 1) {
2317 : // Make no return air flow adjustments during sizing
2318 51170413 : if ((state.dataGlobal->DoingSizing) && numRetNodes == 1) {
2319 9371496 : returnNodeMassFlow = ExpTotalReturnMassFlow;
2320 9371496 : if (airLoop > 0) {
2321 0 : if (!state.dataAirSystemsData->PrimaryAirSystems(airLoop).OASysExists ||
2322 0 : (state.dataAirLoop->AirLoopFlow(airLoop).MaxOutAir == 0.0)) {
2323 0 : ExpTotalReturnMassFlow = max(0.0, ExpTotalReturnMassFlow - this->ZoneExhBalanced + this->ZoneExh);
2324 0 : returnNodeMassFlow = ExpTotalReturnMassFlow;
2325 : }
2326 : }
2327 41798917 : } else if (!state.dataGlobal->DoingSizing) {
2328 41779347 : if (this->NumReturnFlowBasisNodes > 0) {
2329 : // Set base return air flow rate for node 1 using basis node flow rates
2330 0 : Real64 basisNodesMassFlow = 0.0;
2331 0 : for (int nodeNum = 1; nodeNum <= this->NumReturnFlowBasisNodes; ++nodeNum) {
2332 0 : basisNodesMassFlow += state.dataLoopNodes->Node(this->ReturnFlowBasisNode(nodeNum)).MassFlowRate;
2333 : }
2334 0 : returnNodeMassFlow = max(0.0, (basisNodesMassFlow * returnSchedFrac));
2335 0 : this->FixedReturnFlow(returnNum) = true;
2336 : } else {
2337 : // If only 1 return node, use the standard return mass flow
2338 41779347 : if ((numRetNodes == 1) && !this->FixedReturnFlow(returnNum)) {
2339 39426901 : returnNodeMassFlow = max(0.0, (ExpTotalReturnMassFlow * returnSchedFrac * airLoopReturnFrac));
2340 : }
2341 : }
2342 : }
2343 : }
2344 51261808 : totReturnFlow += returnNodeMassFlow;
2345 51261808 : retNodeData.MassFlowRate = returnNodeMassFlow;
2346 51261808 : retNodeData.MassFlowRateMinAvail = 0.0;
2347 51261808 : if (!this->FixedReturnFlow(returnNum)) totVarReturnFlow += returnNodeMassFlow;
2348 : }
2349 : }
2350 :
2351 : // if zone mass balance true, set to expected return flow
2352 51174061 : if (state.dataHeatBal->ZoneAirMassFlow.ZoneFlowAdjustment != DataHeatBalance::AdjustmentType::NoAdjustReturnAndMixing) {
2353 : // applies zone return flow schedule multiplier
2354 597505 : ExpTotalReturnMassFlow = returnSchedFrac * ExpTotalReturnMassFlow;
2355 : // set air flow rate for each return node
2356 597505 : Real64 zoneTotReturnFlow = 0.0;
2357 597505 : Real64 returnNodeMassFlow = 0.0;
2358 1195010 : for (int returnNum = 1; returnNum <= numRetNodes; ++returnNum) {
2359 597505 : int retNode = this->ReturnNode(returnNum);
2360 597505 : if (retNode > 0) {
2361 597505 : if (numRetNodes == 1) {
2362 597505 : returnNodeMassFlow = ExpTotalReturnMassFlow;
2363 : } else { // multiple return nodes
2364 0 : if (ExpTotalReturnMassFlow > 0.0) {
2365 0 : Real64 returnAdjFactor = state.dataLoopNodes->Node(retNode).MassFlowRate / ExpTotalReturnMassFlow;
2366 0 : returnNodeMassFlow = returnAdjFactor * ExpTotalReturnMassFlow;
2367 : } else {
2368 0 : returnNodeMassFlow = 0.0;
2369 : }
2370 : }
2371 : }
2372 597505 : zoneTotReturnFlow += returnNodeMassFlow;
2373 : }
2374 : // Adjust return node flows if zone total return flow is > 0
2375 597505 : if (zoneTotReturnFlow > 0.0) {
2376 986042 : for (int returnNum = 1; returnNum <= numRetNodes; ++returnNum) {
2377 493021 : int retNode = this->ReturnNode(returnNum);
2378 493021 : if (retNode > 0) {
2379 493021 : if (numRetNodes == 1) {
2380 : // set it to expected return flows
2381 493021 : state.dataLoopNodes->Node(retNode).MassFlowRate = ExpTotalReturnMassFlow;
2382 493021 : FinalTotalReturnMassFlow = ExpTotalReturnMassFlow;
2383 : } else { // multiple return nodes, adjust nodes flow
2384 0 : Real64 newReturnFlow = 0.0;
2385 0 : Real64 returnAdjFactor = ExpTotalReturnMassFlow / zoneTotReturnFlow;
2386 0 : Real64 curReturnFlow = state.dataLoopNodes->Node(retNode).MassFlowRate;
2387 0 : newReturnFlow = curReturnFlow * returnAdjFactor;
2388 0 : state.dataLoopNodes->Node(retNode).MassFlowRate = newReturnFlow;
2389 0 : FinalTotalReturnMassFlow += newReturnFlow;
2390 : }
2391 : }
2392 : }
2393 : } else {
2394 104484 : FinalTotalReturnMassFlow = ExpTotalReturnMassFlow;
2395 : }
2396 : } else {
2397 : // Adjust return flows if greater than expected (i.e. there is exhaust or mixing flow reducing the total available for return)
2398 50576556 : if ((totReturnFlow > ExpTotalReturnMassFlow) && (totVarReturnFlow > 0.0)) {
2399 0 : Real64 newReturnFlow = 0.0;
2400 0 : Real64 returnAdjFactor = (1 - ((totReturnFlow - ExpTotalReturnMassFlow) / totVarReturnFlow)); // Return flow adjustment factor
2401 0 : for (int returnNum = 1; returnNum <= numRetNodes; ++returnNum) {
2402 0 : int retNode = this->ReturnNode(returnNum);
2403 0 : Real64 curReturnFlow = state.dataLoopNodes->Node(retNode).MassFlowRate;
2404 0 : if (retNode > 0) {
2405 0 : if (!this->FixedReturnFlow(returnNum)) {
2406 0 : newReturnFlow = curReturnFlow * returnAdjFactor;
2407 0 : FinalTotalReturnMassFlow += newReturnFlow;
2408 0 : state.dataLoopNodes->Node(retNode).MassFlowRate = newReturnFlow;
2409 : } else {
2410 0 : FinalTotalReturnMassFlow += curReturnFlow;
2411 : }
2412 : }
2413 : }
2414 0 : } else {
2415 50576556 : FinalTotalReturnMassFlow = totReturnFlow;
2416 : }
2417 : }
2418 51174061 : }
2419 :
2420 : } // namespace EnergyPlus::DataZoneEquipment
|