Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Autosizing/Base.hh>
57 : #include <EnergyPlus/BranchNodeConnections.hh>
58 : #include <EnergyPlus/Data/EnergyPlusData.hh>
59 : #include <EnergyPlus/DataAirSystems.hh>
60 : #include <EnergyPlus/DataEnvironment.hh>
61 : #include <EnergyPlus/DataHVACGlobals.hh>
62 : #include <EnergyPlus/DataIPShortCuts.hh>
63 : #include <EnergyPlus/DataLoopNode.hh>
64 : #include <EnergyPlus/DataSizing.hh>
65 : #include <EnergyPlus/DataZoneEquipment.hh>
66 : #include <EnergyPlus/DesiccantDehumidifiers.hh>
67 : #include <EnergyPlus/Fans.hh>
68 : #include <EnergyPlus/FluidProperties.hh>
69 : #include <EnergyPlus/General.hh>
70 : #include <EnergyPlus/GeneralRoutines.hh>
71 : #include <EnergyPlus/GlobalNames.hh>
72 : #include <EnergyPlus/HVACDXHeatPumpSystem.hh>
73 : #include <EnergyPlus/HVACFan.hh>
74 : #include <EnergyPlus/HVACHXAssistedCoolingCoil.hh>
75 : #include <EnergyPlus/HeatRecovery.hh>
76 : #include <EnergyPlus/HeatingCoils.hh>
77 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
78 : #include <EnergyPlus/NodeInputManager.hh>
79 : #include <EnergyPlus/OutAirNodeManager.hh>
80 : #include <EnergyPlus/OutdoorAirUnit.hh>
81 : #include <EnergyPlus/OutputProcessor.hh>
82 : #include <EnergyPlus/PlantUtilities.hh>
83 : #include <EnergyPlus/Psychrometrics.hh>
84 : #include <EnergyPlus/ScheduleManager.hh>
85 : #include <EnergyPlus/SteamCoils.hh>
86 : #include <EnergyPlus/UnitarySystem.hh>
87 : #include <EnergyPlus/UtilityRoutines.hh>
88 : #include <EnergyPlus/WaterCoils.hh>
89 : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
90 :
91 : namespace EnergyPlus {
92 :
93 : namespace OutdoorAirUnit {
94 : // Module containing the routines dealing with the outdoor air unit
95 :
96 : // MODULE INFORMATION:
97 : // AUTHOR Young Tae Chae, Rick Strand
98 : // DATE WRITTEN AUG. 2009
99 : // MODIFIED
100 : // Feb 2013 Bereket Nigusse, FSEC
101 : // Added DX Coil Model For 100% OA systems
102 : // RE-ENGINEERED na
103 :
104 : // PURPOSE OF THIS MODULE:
105 : // Simulate zone outdoor air unit.
106 :
107 : // METHODOLOGY EMPLOYED:
108 : // Systems are modeled as a collection of components:
109 : // fan, heat recovery, dehumidifier, heating coil and/or cooling coil plus an integrated control
110 : // algorithm that adjusts the hot or cold water flow to meet the setpoint
111 : // condition.
112 :
113 : // Using/Aliasing
114 : using namespace DataLoopNode;
115 : using DataHVACGlobals::BlowThru;
116 : using DataHVACGlobals::ContFanCycCoil;
117 : using DataHVACGlobals::DrawThru;
118 : using DataHVACGlobals::SmallAirVolFlow;
119 : using DataHVACGlobals::SmallLoad;
120 : using DataHVACGlobals::SmallMassFlow;
121 : using namespace ScheduleManager;
122 : using namespace Psychrometrics;
123 : using namespace FluidProperties;
124 :
125 : // component types addressed by this module
126 : constexpr static std::string_view ZoneHVACOAUnit = {"ZoneHVAC:OutdoorAirUnit"};
127 : constexpr static std::string_view ZoneHVACEqList = {"ZoneHVAC:OutdoorAirUnit:EquipmentList"};
128 :
129 66066 : void SimOutdoorAirUnit(EnergyPlusData &state,
130 : std::string_view CompName, // name of the outdoor air unit
131 : int const ZoneNum, // number of zone being served
132 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
133 : Real64 &PowerMet, // Sensible power supplied (W)
134 : Real64 &LatOutputProvided, // Latent add/removal supplied by window AC (kg/s), dehumid = negative
135 : int &CompIndex)
136 : {
137 :
138 : // SUBROUTINE INFORMATION:
139 : // AUTHOR Rick Strand
140 : // DATE WRITTEN May 2000
141 : // MODIFIED na
142 : // RE-ENGINEERED
143 : // This is re-engineered by Rick Strand and Young T. Chae for OutdoorAirUnit (July, 2009)
144 :
145 : // PURPOSE OF THIS SUBROUTINE:
146 : // This is the main driver subroutine for the outdoor air control unit simulation.
147 :
148 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
149 : int OAUnitNum; // index of outdoor air unit being simulated
150 :
151 66066 : if (state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) {
152 2 : GetOutdoorAirUnitInputs(state);
153 2 : state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false;
154 : }
155 :
156 : // Find the correct Outdoor Air Unit
157 :
158 66066 : if (CompIndex == 0) {
159 12 : OAUnitNum = UtilityRoutines::FindItemInList(CompName, state.dataOutdoorAirUnit->OutAirUnit);
160 12 : if (OAUnitNum == 0) {
161 0 : ShowFatalError(state, "ZoneHVAC:OutdoorAirUnit not found=" + std::string{CompName});
162 : }
163 12 : CompIndex = OAUnitNum;
164 : } else {
165 66054 : OAUnitNum = CompIndex;
166 66054 : if (OAUnitNum > state.dataOutdoorAirUnit->NumOfOAUnits || OAUnitNum < 1) {
167 0 : ShowFatalError(state,
168 0 : format("SimOutdoorAirUnit: Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
169 : OAUnitNum,
170 0 : state.dataOutdoorAirUnit->NumOfOAUnits,
171 0 : CompName));
172 : }
173 66054 : if (state.dataOutdoorAirUnit->CheckEquipName(OAUnitNum)) {
174 12 : if (CompName != state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).Name) {
175 0 : ShowFatalError(state,
176 0 : format("SimOutdoorAirUnit: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
177 : OAUnitNum,
178 : CompName,
179 0 : state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).Name));
180 : }
181 12 : state.dataOutdoorAirUnit->CheckEquipName(OAUnitNum) = false;
182 : }
183 : }
184 :
185 66066 : state.dataSize->ZoneEqOutdoorAirUnit = true;
186 :
187 66066 : if (state.dataGlobal->ZoneSizingCalc || state.dataGlobal->SysSizingCalc) return;
188 :
189 66054 : InitOutdoorAirUnit(state, OAUnitNum, ZoneNum, FirstHVACIteration);
190 :
191 66054 : CalcOutdoorAirUnit(state, OAUnitNum, ZoneNum, FirstHVACIteration, PowerMet, LatOutputProvided);
192 :
193 66054 : ReportOutdoorAirUnit(state, OAUnitNum);
194 :
195 66054 : state.dataSize->ZoneEqOutdoorAirUnit = false;
196 : }
197 :
198 2 : void GetOutdoorAirUnitInputs(EnergyPlusData &state)
199 : {
200 :
201 : // SUBROUTINE INFORMATION:
202 : // AUTHOR Young Tae Chae, Rick Strand
203 : // DATE WRITTEN July 2009
204 : // MODIFIED July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
205 : // RE-ENGINEERED na
206 :
207 : // PURPOSE OF THIS SUBROUTINE:
208 : // This subroutine obtains the input for the outdoor air control unit and sets
209 : // up the appropriate derived type.
210 :
211 : // METHODOLOGY EMPLOYED:
212 : // Standard EnergyPlus methodology.
213 :
214 : // REFERENCES:
215 : // Fred Buhl's fan coil module (FanCoilUnits.cc)
216 : // Kwang Ho Lee's Unit Ventilator Module (UnitVentilator.cc)
217 : // Young Tae Chae's Ventilated Slab System (VentilatedSlab.cc)
218 : // Mixed Air.cc
219 :
220 : // Using/Aliasing
221 : using BranchNodeConnections::SetUpCompSets;
222 : using BranchNodeConnections::TestCompSet;
223 : using FluidProperties::FindRefrigerant;
224 : using NodeInputManager::GetOnlySingleNode;
225 : using ScheduleManager::GetScheduleIndex;
226 : using SteamCoils::GetCoilAirInletNode;
227 : using SteamCoils::GetCoilAirOutletNode;
228 : using SteamCoils::GetCoilMaxSteamFlowRate;
229 : using SteamCoils::GetCoilSteamInletNode;
230 : using SteamCoils::GetCoilSteamOutletNode;
231 : using SteamCoils::GetSteamCoilIndex;
232 : using namespace DataLoopNode;
233 : using OutAirNodeManager::CheckAndAddAirNodeNumber;
234 : using WaterCoils::GetCoilWaterInletNode;
235 : using WaterCoils::GetWaterCoilIndex;
236 2 : auto &GetWCoilInletNode(WaterCoils::GetCoilInletNode);
237 2 : auto &GetWCoilOutletNode(WaterCoils::GetCoilOutletNode);
238 : using HeatingCoils::GetCoilInletNode;
239 : using HeatingCoils::GetCoilOutletNode;
240 : using WaterCoils::GetCoilWaterOutletNode;
241 2 : auto &GetHeatingCoilIndex(HeatingCoils::GetCoilIndex);
242 2 : auto &GetElecCoilInletNode(HeatingCoils::GetCoilInletNode);
243 2 : auto &GetElecCoilOutletNode(HeatingCoils::GetCoilOutletNode);
244 2 : auto &GetHXAssistedCoilFlowRate(HVACHXAssistedCoolingCoil::GetCoilMaxWaterFlowRate);
245 2 : auto &GetWHXCoilInletNode(HVACHXAssistedCoolingCoil::GetCoilInletNode);
246 2 : auto &GetWHXCoilOutletNode(HVACHXAssistedCoolingCoil::GetCoilOutletNode);
247 : using DataHVACGlobals::cFanTypes;
248 :
249 : using Fans::GetFanAvailSchPtr;
250 : using Fans::GetFanDesignVolumeFlowRate;
251 : using Fans::GetFanIndex;
252 : using Fans::GetFanType;
253 :
254 : // SUBROUTINE PARAMETER DEFINITIONS:
255 : static constexpr std::string_view RoutineName("GetOutdoorAirUnitInputs: "); // include trailing blank space
256 :
257 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
258 :
259 : int NumNums; // Number of real numbers returned by GetObjectItem
260 : int NumAlphas; // Number of alphanumerics returned by GetObjectItem
261 : int IOStat;
262 : int OAUnitNum;
263 : int CompNum;
264 4 : std::string ComponentListName;
265 : int NumInList;
266 : int InListNum;
267 : int ListNum;
268 2 : bool ErrorsFound(false);
269 2 : int MaxNums(0); // Maximum number of numeric input fields
270 2 : int MaxAlphas(0); // Maximum number of alpha input fields
271 2 : int TotalArgs(0); // Total number of alpha and numeric arguments (max) for a
272 : bool IsValid; // Set for outside air node check
273 4 : Array1D_string cAlphaArgs; // Alpha input items for object
274 4 : std::string CurrentModuleObject; // Object type for getting and messages
275 4 : Array1D_string cAlphaFields; // Alpha field names
276 4 : Array1D_string cNumericFields; // Numeric field names
277 4 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
278 4 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
279 4 : Array1D<Real64> NumArray;
280 4 : Array1D_string AlphArray;
281 2 : bool errFlag(false);
282 :
283 : // Figure out how many outdoor air units there are in the input file
284 :
285 2 : if (!state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) return;
286 :
287 2 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, ZoneHVACOAUnit, TotalArgs, NumAlphas, NumNums);
288 2 : MaxNums = max(MaxNums, NumNums);
289 2 : MaxAlphas = max(MaxAlphas, NumAlphas);
290 2 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, ZoneHVACEqList, TotalArgs, NumAlphas, NumNums);
291 2 : MaxNums = max(MaxNums, NumNums);
292 2 : MaxAlphas = max(MaxAlphas, NumAlphas);
293 :
294 2 : AlphArray.allocate(MaxAlphas);
295 2 : cAlphaFields.allocate(MaxAlphas);
296 2 : NumArray.dimension(MaxNums, 0.0);
297 2 : cNumericFields.allocate(MaxNums);
298 2 : lAlphaBlanks.dimension(MaxAlphas, true);
299 2 : lNumericBlanks.dimension(MaxNums, true);
300 2 : cAlphaArgs.allocate(NumAlphas);
301 :
302 2 : CurrentModuleObject = ZoneHVACOAUnit;
303 2 : state.dataOutdoorAirUnit->NumOfOAUnits = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
304 :
305 2 : state.dataOutdoorAirUnit->OutAirUnit.allocate(state.dataOutdoorAirUnit->NumOfOAUnits);
306 2 : state.dataOutdoorAirUnit->SupplyFanUniqueNames.reserve(static_cast<unsigned>(state.dataOutdoorAirUnit->NumOfOAUnits));
307 2 : state.dataOutdoorAirUnit->ExhaustFanUniqueNames.reserve(static_cast<unsigned>(state.dataOutdoorAirUnit->NumOfOAUnits));
308 2 : state.dataOutdoorAirUnit->ComponentListUniqueNames.reserve(static_cast<unsigned>(state.dataOutdoorAirUnit->NumOfOAUnits));
309 2 : state.dataOutdoorAirUnit->MyOneTimeErrorFlag.dimension(state.dataOutdoorAirUnit->NumOfOAUnits, true);
310 2 : state.dataOutdoorAirUnit->CheckEquipName.dimension(state.dataOutdoorAirUnit->NumOfOAUnits, true);
311 :
312 2 : auto &OutAirUnit(state.dataOutdoorAirUnit->OutAirUnit);
313 :
314 14 : for (OAUnitNum = 1; OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits; ++OAUnitNum) {
315 :
316 24 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
317 : CurrentModuleObject,
318 : OAUnitNum,
319 12 : state.dataIPShortCut->cAlphaArgs,
320 : NumAlphas,
321 : NumArray,
322 : NumNums,
323 : IOStat,
324 : lNumericBlanks,
325 : lAlphaBlanks,
326 : cAlphaFields,
327 : cNumericFields);
328 12 : UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), CurrentModuleObject, ErrorsFound);
329 :
330 : // A1
331 12 : OutAirUnit(OAUnitNum).Name = state.dataIPShortCut->cAlphaArgs(1);
332 :
333 : // A2
334 12 : OutAirUnit(OAUnitNum).SchedName = state.dataIPShortCut->cAlphaArgs(2);
335 12 : if (lAlphaBlanks(2)) {
336 0 : OutAirUnit(OAUnitNum).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
337 : } else {
338 12 : OutAirUnit(OAUnitNum).SchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2)); // convert schedule name to pointer
339 12 : if (OutAirUnit(OAUnitNum).SchedPtr == 0) {
340 0 : ShowSevereError(state,
341 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
342 0 : state.dataIPShortCut->cAlphaArgs(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\" not found.");
343 0 : ErrorsFound = true;
344 : }
345 : }
346 :
347 : // A3
348 12 : OutAirUnit(OAUnitNum).ZoneName = state.dataIPShortCut->cAlphaArgs(3);
349 12 : OutAirUnit(OAUnitNum).ZonePtr = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->Zone);
350 :
351 12 : if (OutAirUnit(OAUnitNum).ZonePtr == 0) {
352 0 : if (lAlphaBlanks(3)) {
353 0 : ShowSevereError(state,
354 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
355 0 : state.dataIPShortCut->cAlphaArgs(3) + " is required but input is blank.");
356 : } else {
357 0 : ShowSevereError(state,
358 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
359 0 : state.dataIPShortCut->cAlphaArgs(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\" not found.");
360 : }
361 0 : ErrorsFound = true;
362 : }
363 12 : OutAirUnit(OAUnitNum).ZoneNodeNum = state.dataHeatBal->Zone(OutAirUnit(OAUnitNum).ZonePtr).SystemZoneNodeNumber;
364 : // Outside air information:
365 : // N1
366 12 : OutAirUnit(OAUnitNum).OutAirVolFlow = NumArray(1);
367 : // A4
368 12 : OutAirUnit(OAUnitNum).OutAirSchedName = state.dataIPShortCut->cAlphaArgs(4);
369 : // convert schedule name to pointer
370 12 : OutAirUnit(OAUnitNum).OutAirSchedPtr = GetScheduleIndex(state, OutAirUnit(OAUnitNum).OutAirSchedName);
371 12 : if (OutAirUnit(OAUnitNum).OutAirSchedPtr == 0) {
372 0 : ShowSevereError(state,
373 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " + cAlphaFields(4) +
374 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\" not found.");
375 0 : ErrorsFound = true;
376 : }
377 :
378 : // A5
379 12 : OutAirUnit(OAUnitNum).SFanName = state.dataIPShortCut->cAlphaArgs(5);
380 36 : GlobalNames::IntraObjUniquenessCheck(state,
381 12 : state.dataIPShortCut->cAlphaArgs(5),
382 : CurrentModuleObject,
383 12 : cAlphaFields(5),
384 12 : state.dataOutdoorAirUnit->SupplyFanUniqueNames,
385 : ErrorsFound);
386 12 : errFlag = false;
387 12 : if (HVACFan::checkIfFanNameIsAFanSystem(state, OutAirUnit(OAUnitNum).SFanName)) { // no object type in input, so check if Fan:SystemModel
388 6 : OutAirUnit(OAUnitNum).SFanType = DataHVACGlobals::FanType_SystemModelObject;
389 6 : state.dataHVACFan->fanObjs.emplace_back(new HVACFan::FanSystem(state, OutAirUnit(OAUnitNum).SFanName)); // call constructor
390 6 : OutAirUnit(OAUnitNum).SFan_Index = HVACFan::getFanObjectVectorIndex(state, OutAirUnit(OAUnitNum).SFanName);
391 6 : OutAirUnit(OAUnitNum).SFanMaxAirVolFlow = state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).SFan_Index]->designAirVolFlowRate;
392 6 : OutAirUnit(OAUnitNum).SFanAvailSchedPtr = state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).SFan_Index]->availSchedIndex;
393 : } else {
394 18 : GetFanType(
395 18 : state, OutAirUnit(OAUnitNum).SFanName, OutAirUnit(OAUnitNum).SFanType, errFlag, CurrentModuleObject, OutAirUnit(OAUnitNum).Name);
396 :
397 6 : OutAirUnit(OAUnitNum).SFanMaxAirVolFlow =
398 12 : GetFanDesignVolumeFlowRate(state, cFanTypes(OutAirUnit(OAUnitNum).SFanType), OutAirUnit(OAUnitNum).SFanName, errFlag);
399 6 : if (!errFlag) {
400 6 : OutAirUnit(OAUnitNum).SFanAvailSchedPtr =
401 6 : GetFanAvailSchPtr(state, cFanTypes(OutAirUnit(OAUnitNum).SFanType), OutAirUnit(OAUnitNum).SFanName, errFlag);
402 : // get fan index
403 6 : GetFanIndex(state, OutAirUnit(OAUnitNum).SFanName, OutAirUnit(OAUnitNum).SFan_Index, ErrorsFound);
404 : } else {
405 0 : ErrorsFound = true;
406 : }
407 : }
408 : // A6 :Fan Place
409 12 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), "BlowThrough")) OutAirUnit(OAUnitNum).FanPlace = BlowThru;
410 12 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), "DrawThrough")) OutAirUnit(OAUnitNum).FanPlace = DrawThru;
411 12 : if (OutAirUnit(OAUnitNum).FanPlace == 0) {
412 0 : ShowSevereError(state, "Invalid " + cAlphaFields(6) + " = " + state.dataIPShortCut->cAlphaArgs(6));
413 0 : ShowContinueError(state, "Occurs in " + std::string{CurrentModuleObject} + " = " + state.dataIPShortCut->cAlphaArgs(1));
414 0 : ErrorsFound = true;
415 : }
416 :
417 : // A7
418 :
419 12 : if (lAlphaBlanks(7)) {
420 0 : OutAirUnit(OAUnitNum).ExtFan = false;
421 0 : if (!state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance) {
422 0 : ShowWarningError(state,
423 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " + cAlphaFields(7) +
424 : " is blank.");
425 0 : ShowContinueError(state,
426 : "Unbalanced mass flow rates between supply from outdoor air and exhaust from zone air will be introduced.");
427 : }
428 12 : } else if (!lAlphaBlanks(7)) {
429 12 : OutAirUnit(OAUnitNum).ExtFanName = state.dataIPShortCut->cAlphaArgs(7);
430 36 : GlobalNames::IntraObjUniquenessCheck(state,
431 12 : state.dataIPShortCut->cAlphaArgs(7),
432 : CurrentModuleObject,
433 12 : cAlphaFields(7),
434 12 : state.dataOutdoorAirUnit->ExhaustFanUniqueNames,
435 : ErrorsFound);
436 12 : errFlag = false;
437 12 : if (HVACFan::checkIfFanNameIsAFanSystem(state,
438 12 : OutAirUnit(OAUnitNum).ExtFanName)) { // no object type in input, so check if Fan:SystemModel
439 6 : OutAirUnit(OAUnitNum).ExtFanType = DataHVACGlobals::FanType_SystemModelObject;
440 6 : state.dataHVACFan->fanObjs.emplace_back(new HVACFan::FanSystem(state, OutAirUnit(OAUnitNum).ExtFanName)); // call constructor
441 6 : OutAirUnit(OAUnitNum).ExtFan_Index = HVACFan::getFanObjectVectorIndex(state, OutAirUnit(OAUnitNum).ExtFanName);
442 6 : OutAirUnit(OAUnitNum).EFanMaxAirVolFlow = state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).ExtFan_Index]->designAirVolFlowRate;
443 6 : OutAirUnit(OAUnitNum).ExtFanAvailSchedPtr = state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).ExtFan_Index]->availSchedIndex;
444 : } else {
445 18 : GetFanType(state,
446 6 : OutAirUnit(OAUnitNum).ExtFanName,
447 6 : OutAirUnit(OAUnitNum).ExtFanType,
448 : errFlag,
449 : CurrentModuleObject,
450 6 : OutAirUnit(OAUnitNum).Name);
451 6 : OutAirUnit(OAUnitNum).EFanMaxAirVolFlow =
452 12 : GetFanDesignVolumeFlowRate(state, cFanTypes(OutAirUnit(OAUnitNum).ExtFanType), OutAirUnit(OAUnitNum).ExtFanName, errFlag);
453 6 : if (!errFlag) {
454 6 : OutAirUnit(OAUnitNum).ExtFanAvailSchedPtr =
455 6 : GetFanAvailSchPtr(state, cFanTypes(OutAirUnit(OAUnitNum).ExtFanType), OutAirUnit(OAUnitNum).ExtFanName, errFlag);
456 : // get fan index
457 6 : GetFanIndex(state, OutAirUnit(OAUnitNum).ExtFanName, OutAirUnit(OAUnitNum).ExtFan_Index, ErrorsFound);
458 : } else {
459 0 : ErrorsFound = true;
460 : }
461 : }
462 12 : OutAirUnit(OAUnitNum).ExtFan = true;
463 : }
464 :
465 : // N2
466 12 : OutAirUnit(OAUnitNum).ExtAirVolFlow = NumArray(2);
467 12 : if ((OutAirUnit(OAUnitNum).ExtFan) && (!state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance)) {
468 12 : if (NumArray(2) != NumArray(1)) {
469 0 : ShowWarningError(state,
470 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " + cNumericFields(1) +
471 0 : " and " + cNumericFields(2) + " are not equal. This may cause unbalanced flow.");
472 0 : ShowContinueError(state, format("{}={:.3R}= and {}{:.3R}", cNumericFields(1), NumArray(1), cNumericFields(2), NumArray(2)));
473 : }
474 : }
475 : // A8
476 12 : OutAirUnit(OAUnitNum).ExtAirSchedName = state.dataIPShortCut->cAlphaArgs(8);
477 : // convert schedule name to pointer
478 12 : OutAirUnit(OAUnitNum).ExtOutAirSchedPtr = GetScheduleIndex(state, OutAirUnit(OAUnitNum).ExtAirSchedName);
479 12 : if (OutAirUnit(OAUnitNum).ExtFan) {
480 12 : if ((OutAirUnit(OAUnitNum).ExtOutAirSchedPtr == 0) || (lNumericBlanks(2))) {
481 0 : ShowSevereError(state,
482 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " + cAlphaFields(8) +
483 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(8) + "\" not found.");
484 0 : ErrorsFound = true;
485 : } else {
486 12 : if ((OutAirUnit(OAUnitNum).ExtOutAirSchedPtr != OutAirUnit(OAUnitNum).OutAirSchedPtr) &&
487 0 : (!state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance)) {
488 0 : ShowWarningError(
489 : state,
490 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
491 : "\", different schedule inputs for outdoor air and exhaust air schedules may cause unbalanced mass flow.");
492 0 : ShowContinueError(state,
493 0 : cAlphaFields(4) + "=" + state.dataIPShortCut->cAlphaArgs(4) + " and " + cAlphaFields(8) + "=" +
494 0 : state.dataIPShortCut->cAlphaArgs(8));
495 : }
496 : }
497 : }
498 :
499 12 : if (OutAirUnit(OAUnitNum).ExtFan) {
500 24 : SetUpCompSets(state,
501 : CurrentModuleObject,
502 12 : OutAirUnit(OAUnitNum).Name,
503 : "UNDEFINED",
504 12 : state.dataIPShortCut->cAlphaArgs(7),
505 : "UNDEFINED",
506 24 : "UNDEFINED");
507 : }
508 :
509 : // Process the unit control type
510 12 : if (!lAlphaBlanks(9)) {
511 12 : constexpr std::array<std::string_view, static_cast<int>(OAUnitCtrlType::Num)> ctrlTypeNamesUC = {
512 : "NEUTRALCONTROL", "INVALID-UNCONDITIONED", "TEMPERATURECONTROL"};
513 12 : auto tmpCtrlType = static_cast<OAUnitCtrlType>(getEnumerationValue(ctrlTypeNamesUC, state.dataIPShortCut->cAlphaArgs(9)));
514 12 : switch (tmpCtrlType) {
515 12 : case OAUnitCtrlType::Neutral:
516 : case OAUnitCtrlType::Temperature:
517 12 : OutAirUnit(OAUnitNum).controlType = tmpCtrlType;
518 12 : break;
519 0 : default:
520 0 : break; // just leave it alone, nothing was done here
521 : }
522 : } else {
523 0 : ShowSevereError(state,
524 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " + cAlphaFields(9) +
525 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(9) + "\".");
526 0 : ShowContinueError(state, "Control reset to Unconditioned Control.");
527 0 : OutAirUnit(OAUnitNum).controlType = OAUnitCtrlType::Neutral;
528 : }
529 :
530 : // A10:High Control Temp :
531 12 : OutAirUnit(OAUnitNum).HiCtrlTempSched = state.dataIPShortCut->cAlphaArgs(10);
532 12 : OutAirUnit(OAUnitNum).HiCtrlTempSchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(10));
533 12 : if ((OutAirUnit(OAUnitNum).HiCtrlTempSchedPtr == 0) && (!lAlphaBlanks(10))) {
534 0 : ShowSevereError(state,
535 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " + cAlphaFields(10) +
536 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(9) + "\" not found.");
537 0 : ErrorsFound = true;
538 : }
539 :
540 : // A11:Low Control Temp :
541 12 : OutAirUnit(OAUnitNum).LoCtrlTempSched = state.dataIPShortCut->cAlphaArgs(11);
542 12 : OutAirUnit(OAUnitNum).LoCtrlTempSchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(11));
543 12 : if ((OutAirUnit(OAUnitNum).LoCtrlTempSchedPtr == 0) && (!lAlphaBlanks(11))) {
544 0 : ShowSevereError(state,
545 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " + cAlphaFields(11) +
546 0 : "=\"" + state.dataIPShortCut->cAlphaArgs(10) + "\" not found.");
547 0 : ErrorsFound = true;
548 : }
549 :
550 12 : OutAirUnit(OAUnitNum).CompOutSetTemp = 0.0;
551 :
552 : // A12~A15 : Node Condition
553 :
554 : // Main air nodes (except outside air node):
555 :
556 12 : OutAirUnit(OAUnitNum).AirOutletNode = GetOnlySingleNode(state,
557 12 : state.dataIPShortCut->cAlphaArgs(13),
558 : ErrorsFound,
559 : DataLoopNode::ConnectionObjectType::ZoneHVACOutdoorAirUnit,
560 12 : state.dataIPShortCut->cAlphaArgs(1),
561 : DataLoopNode::NodeFluidType::Air,
562 : DataLoopNode::ConnectionType::Outlet,
563 : NodeInputManager::CompFluidStream::Primary,
564 12 : ObjectIsParent);
565 12 : if (!lAlphaBlanks(14)) {
566 12 : OutAirUnit(OAUnitNum).AirInletNode = GetOnlySingleNode(state,
567 12 : state.dataIPShortCut->cAlphaArgs(14),
568 : ErrorsFound,
569 : DataLoopNode::ConnectionObjectType::ZoneHVACOutdoorAirUnit,
570 12 : state.dataIPShortCut->cAlphaArgs(1),
571 : DataLoopNode::NodeFluidType::Air,
572 : DataLoopNode::ConnectionType::Inlet,
573 : NodeInputManager::CompFluidStream::Primary,
574 12 : ObjectIsParent);
575 : } else {
576 0 : if (OutAirUnit(OAUnitNum).ExtFan) {
577 0 : ShowSevereError(state,
578 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
579 0 : cAlphaFields(14) + " cannot be blank when there is an exhaust fan.");
580 0 : ErrorsFound = true;
581 : }
582 : }
583 :
584 12 : OutAirUnit(OAUnitNum).SFanOutletNode = GetOnlySingleNode(state,
585 12 : state.dataIPShortCut->cAlphaArgs(15),
586 : ErrorsFound,
587 : DataLoopNode::ConnectionObjectType::ZoneHVACOutdoorAirUnit,
588 12 : state.dataIPShortCut->cAlphaArgs(1),
589 : DataLoopNode::NodeFluidType::Air,
590 : DataLoopNode::ConnectionType::Internal,
591 : NodeInputManager::CompFluidStream::Primary,
592 12 : ObjectIsNotParent);
593 :
594 : // Set connection type to 'OutdoorAir', because this is hardwired to OA conditions
595 12 : OutAirUnit(OAUnitNum).OutsideAirNode = GetOnlySingleNode(state,
596 12 : state.dataIPShortCut->cAlphaArgs(12),
597 : ErrorsFound,
598 : DataLoopNode::ConnectionObjectType::ZoneHVACOutdoorAirUnit,
599 12 : state.dataIPShortCut->cAlphaArgs(1),
600 : DataLoopNode::NodeFluidType::Air,
601 : DataLoopNode::ConnectionType::OutsideAirReference,
602 : NodeInputManager::CompFluidStream::Primary,
603 12 : ObjectIsNotParent);
604 :
605 12 : if (!lAlphaBlanks(12)) {
606 12 : CheckAndAddAirNodeNumber(state, OutAirUnit(OAUnitNum).OutsideAirNode, IsValid);
607 12 : if (!IsValid) {
608 0 : ShowWarningError(state,
609 0 : std::string{CurrentModuleObject} + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
610 0 : "\", Adding OutdoorAir:Node=" + state.dataIPShortCut->cAlphaArgs(12));
611 : }
612 : }
613 :
614 : // When the fan position is "BlowThru", Each node is set up
615 :
616 12 : if (OutAirUnit(OAUnitNum).FanPlace == BlowThru) {
617 24 : SetUpCompSets(state,
618 : CurrentModuleObject,
619 6 : OutAirUnit(OAUnitNum).Name,
620 : "UNDEFINED",
621 6 : state.dataIPShortCut->cAlphaArgs(5),
622 6 : state.dataIPShortCut->cAlphaArgs(12),
623 12 : state.dataIPShortCut->cAlphaArgs(15));
624 : }
625 :
626 : // A16 : component list
627 :
628 36 : GlobalNames::IntraObjUniquenessCheck(state,
629 12 : state.dataIPShortCut->cAlphaArgs(16),
630 : CurrentModuleObject,
631 12 : cAlphaFields(16),
632 12 : state.dataOutdoorAirUnit->ComponentListUniqueNames,
633 : ErrorsFound);
634 12 : ComponentListName = state.dataIPShortCut->cAlphaArgs(16);
635 12 : OutAirUnit(OAUnitNum).ComponentListName = ComponentListName;
636 12 : if (!lAlphaBlanks(16)) {
637 12 : ListNum = state.dataInputProcessing->inputProcessor->getObjectItemNum(state, ZoneHVACEqList, ComponentListName);
638 12 : if (ListNum > 0) {
639 12 : state.dataInputProcessing->inputProcessor->getObjectItem(
640 : state, ZoneHVACEqList, ListNum, AlphArray, NumAlphas, NumArray, NumNums, IOStat);
641 12 : NumInList = (NumAlphas - 1) / 2; // potential problem if puts in type but not name
642 12 : if (mod(NumAlphas - 1, 2) != 0) ++NumInList;
643 12 : OutAirUnit(OAUnitNum).NumComponents = NumInList;
644 12 : OutAirUnit(OAUnitNum).OAEquip.allocate(NumInList);
645 :
646 : // Get information of component
647 51 : for (InListNum = 1; InListNum <= NumInList; ++InListNum) {
648 39 : OutAirUnit(OAUnitNum).OAEquip(InListNum).ComponentName = AlphArray(InListNum * 2 + 1);
649 :
650 39 : OutAirUnit(OAUnitNum).OAEquip(InListNum).Type =
651 78 : static_cast<CompType>(getEnumerationValue(CompTypeNamesUC, UtilityRoutines::MakeUPPERCase(AlphArray(InListNum * 2))));
652 :
653 39 : CompNum = InListNum;
654 :
655 : // Coil Types
656 39 : switch (OutAirUnit(OAUnitNum).OAEquip(InListNum).Type) {
657 6 : case CompType::WaterCoil_Cooling: {
658 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilType = DataPlant::PlantEquipmentType::CoilWaterCooling;
659 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex =
660 12 : GetWaterCoilIndex(state,
661 6 : CompTypeNamesUC[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
662 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
663 : ErrorsFound);
664 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirInletNode =
665 12 : GetWCoilInletNode(state,
666 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
667 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
668 : ErrorsFound);
669 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirOutletNode =
670 12 : GetWCoilOutletNode(state,
671 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
672 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
673 : ErrorsFound);
674 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilWaterInletNode =
675 12 : GetCoilWaterInletNode(state,
676 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
677 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
678 : ErrorsFound);
679 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilWaterOutletNode =
680 12 : GetCoilWaterOutletNode(state,
681 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
682 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
683 : ErrorsFound);
684 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).MaxVolWaterFlow =
685 12 : WaterCoils::GetCoilMaxWaterFlowRate(state,
686 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
687 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
688 : ErrorsFound);
689 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).MinVolWaterFlow = 0.0;
690 6 : break;
691 : }
692 6 : case CompType::WaterCoil_SimpleHeat: {
693 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
694 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex =
695 12 : GetWaterCoilIndex(state,
696 6 : CompTypeNamesUC[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
697 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
698 : ErrorsFound);
699 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirInletNode =
700 12 : GetWCoilInletNode(state,
701 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
702 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
703 : ErrorsFound);
704 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirOutletNode =
705 12 : GetWCoilOutletNode(state, "Coil:Heating:Water", OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName, ErrorsFound);
706 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilWaterInletNode =
707 12 : GetCoilWaterInletNode(state,
708 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
709 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
710 : ErrorsFound);
711 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilWaterOutletNode =
712 12 : GetCoilWaterOutletNode(state,
713 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
714 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
715 : ErrorsFound);
716 12 : OutAirUnit(OAUnitNum).OAEquip(CompNum).MaxVolWaterFlow = WaterCoils::GetCoilMaxWaterFlowRate(
717 12 : state, "Coil:Heating:Water", OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName, ErrorsFound);
718 6 : OutAirUnit(OAUnitNum).OAEquip(CompNum).MinVolWaterFlow = 0.0;
719 6 : break;
720 : }
721 0 : case CompType::SteamCoil_AirHeat: {
722 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilType = DataPlant::PlantEquipmentType::CoilSteamAirHeating;
723 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex =
724 0 : GetSteamCoilIndex(state,
725 0 : CompTypeNamesUC[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
726 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
727 : ErrorsFound);
728 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirInletNode =
729 0 : GetCoilAirInletNode(state,
730 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex,
731 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
732 : ErrorsFound);
733 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirOutletNode =
734 0 : GetCoilAirOutletNode(state,
735 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex,
736 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
737 : ErrorsFound);
738 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilWaterInletNode =
739 0 : GetCoilSteamInletNode(state,
740 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex,
741 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
742 : ErrorsFound);
743 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilWaterOutletNode =
744 0 : GetCoilSteamOutletNode(state,
745 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
746 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
747 : ErrorsFound);
748 :
749 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).MaxVolWaterFlow =
750 0 : GetCoilMaxSteamFlowRate(state, OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex, ErrorsFound);
751 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).MinVolWaterFlow = 0.0;
752 : // below: no extra error needed if steam properties not in input
753 : // file because getting the steam coil will have done that.
754 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).FluidIndex = FindRefrigerant(state, "Steam");
755 0 : break;
756 : }
757 0 : case CompType::WaterCoil_DetailedCool: {
758 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex =
759 0 : GetWaterCoilIndex(state,
760 0 : CompTypeNamesUC[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
761 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
762 : ErrorsFound);
763 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilType = DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling;
764 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirInletNode =
765 0 : GetWCoilInletNode(state,
766 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
767 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
768 : ErrorsFound);
769 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirOutletNode =
770 0 : GetWCoilOutletNode(state,
771 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
772 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
773 : ErrorsFound);
774 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilWaterInletNode =
775 0 : GetCoilWaterInletNode(state,
776 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
777 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
778 : ErrorsFound);
779 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilWaterOutletNode =
780 0 : GetCoilWaterOutletNode(state,
781 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
782 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
783 : ErrorsFound);
784 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).MaxVolWaterFlow =
785 0 : WaterCoils::GetCoilMaxWaterFlowRate(state,
786 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
787 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
788 : ErrorsFound);
789 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).MinVolWaterFlow = 0.0;
790 0 : break;
791 : }
792 0 : case CompType::WaterCoil_CoolingHXAsst: {
793 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirInletNode =
794 0 : GetWHXCoilInletNode(state,
795 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
796 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
797 : ErrorsFound);
798 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirOutletNode =
799 0 : GetWHXCoilOutletNode(state,
800 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
801 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
802 : ErrorsFound);
803 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilWaterInletNode =
804 0 : GetCoilWaterInletNode(state,
805 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
806 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
807 : ErrorsFound);
808 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilWaterOutletNode =
809 0 : GetCoilWaterOutletNode(state,
810 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
811 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
812 : ErrorsFound);
813 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).MaxVolWaterFlow =
814 0 : GetHXAssistedCoilFlowRate(state,
815 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
816 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
817 : ErrorsFound);
818 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).MinVolWaterFlow = 0.0;
819 0 : break;
820 : }
821 4 : case CompType::Coil_ElectricHeat: {
822 : // Get OutAirUnit( OAUnitNum ).OAEquip( CompNum ).ComponentIndex, 2 types of mining functions to choose from
823 8 : GetHeatingCoilIndex(state,
824 4 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
825 4 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex,
826 : ErrorsFound);
827 4 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirInletNode =
828 8 : GetElecCoilInletNode(state,
829 4 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
830 4 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
831 : ErrorsFound);
832 4 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirOutletNode =
833 8 : GetElecCoilOutletNode(state,
834 4 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
835 4 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
836 : ErrorsFound);
837 4 : break;
838 : }
839 2 : case CompType::Coil_GasHeat: {
840 : // Get OutAirUnit( OAUnitNum ).OAEquip( CompNum ).ComponentIndex, 2 types of mining functions to choose from
841 4 : GetHeatingCoilIndex(state,
842 2 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
843 2 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex,
844 : ErrorsFound);
845 2 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirInletNode =
846 4 : GetCoilInletNode(state,
847 2 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
848 2 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
849 : ErrorsFound);
850 2 : OutAirUnit(OAUnitNum).OAEquip(CompNum).CoilAirOutletNode =
851 4 : GetCoilOutletNode(state,
852 2 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)],
853 2 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
854 : ErrorsFound);
855 2 : break;
856 : }
857 8 : case CompType::DXSystem: {
858 : // set the data for 100% DOAS DX cooling coil
859 : // is a different function call needed here? similar to one in HVACDXSystem
860 : // CheckDXCoolingCoilInOASysExists(state, OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName);
861 8 : break;
862 : }
863 1 : case CompType::DXHeatPumpSystem: {
864 1 : break;
865 : }
866 0 : case CompType::UnitarySystemModel: {
867 0 : UnitarySystems::UnitarySys thisSys;
868 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).compPointer = thisSys.factory(state,
869 : DataHVACGlobals::UnitarySys_AnyCoilType,
870 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
871 : false,
872 : OAUnitNum);
873 0 : UnitarySystems::UnitarySys::checkUnitarySysCoilInOASysExists(
874 0 : state, OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName, OAUnitNum);
875 :
876 : // Heat recovery
877 0 : break;
878 : }
879 10 : case CompType::HeatXchngrFP:
880 : case CompType::HeatXchngrSL: {
881 : // CASE('HEATEXCHANGER:DESICCANT:BALANCEDFLOW')
882 : // OutAirUnit(OAUnitNum)%OAEquip(CompNum)%Type= CompType::HeatXchngr
883 :
884 : // Desiccant Dehumidifier
885 10 : break;
886 : }
887 2 : case CompType::Desiccant: {
888 : // Futher Enhancement
889 : // CASE('DEHUMIDIFIER:DESICCANT:SYSTEM')
890 : // OutAirUnit(OAUnitNum)%OAEquip(CompNum)%Type= CompType::Desiccant
891 2 : break;
892 : }
893 0 : default: {
894 0 : ShowSevereError(state,
895 0 : format("{}= \"{}\" invalid Outside Air Component=\"{}\".",
896 : CurrentModuleObject,
897 : AlphArray(1),
898 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(CompNum).Type)]));
899 0 : ErrorsFound = true;
900 : }
901 : }
902 :
903 : // Add equipment to component sets array
904 : // Node set up
905 39 : if (OutAirUnit(OAUnitNum).FanPlace == BlowThru) {
906 22 : if (InListNum == 1) { // the component is the first one
907 24 : SetUpCompSets(state,
908 : "ZoneHVAC:OutdoorAirUnit",
909 6 : OutAirUnit(OAUnitNum).Name,
910 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(InListNum).Type)],
911 6 : OutAirUnit(OAUnitNum).OAEquip(InListNum).ComponentName,
912 6 : state.dataIPShortCut->cAlphaArgs(15),
913 12 : "UNDEFINED");
914 16 : } else if (InListNum != NumInList) { // the component is placed in b/w components
915 30 : SetUpCompSets(state,
916 : "ZoneHVAC:OutdoorAirUnit",
917 10 : OutAirUnit(OAUnitNum).Name,
918 10 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(InListNum).Type)],
919 10 : OutAirUnit(OAUnitNum).OAEquip(InListNum).ComponentName,
920 : "UNDEFINED",
921 20 : "UNDEFINED");
922 6 : } else if (InListNum == NumInList) { // the component is the last one
923 24 : SetUpCompSets(state,
924 : "ZoneHVAC:OutdoorAirUnit",
925 6 : OutAirUnit(OAUnitNum).Name,
926 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(InListNum).Type)],
927 6 : OutAirUnit(OAUnitNum).OAEquip(InListNum).ComponentName,
928 : "UNDEFINED",
929 18 : state.dataIPShortCut->cAlphaArgs(13));
930 : }
931 : // If fan is on the end of equipment.
932 17 : } else if (OutAirUnit(OAUnitNum).FanPlace == DrawThru) {
933 17 : if (InListNum == 1) {
934 24 : SetUpCompSets(state,
935 : "ZoneHVAC:OutdoorAirUnit",
936 6 : OutAirUnit(OAUnitNum).Name,
937 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(InListNum).Type)],
938 6 : OutAirUnit(OAUnitNum).OAEquip(InListNum).ComponentName,
939 6 : state.dataIPShortCut->cAlphaArgs(12),
940 12 : "UNDEFINED");
941 11 : } else if (InListNum != NumInList) {
942 15 : SetUpCompSets(state,
943 : "ZoneHVAC:OutdoorAirUnit",
944 5 : OutAirUnit(OAUnitNum).Name,
945 5 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(InListNum).Type)],
946 5 : OutAirUnit(OAUnitNum).OAEquip(InListNum).ComponentName,
947 : "UNDEFINED",
948 10 : "UNDEFINED");
949 6 : } else if (InListNum == NumInList) {
950 18 : SetUpCompSets(state,
951 : "ZoneHVAC:OutdoorAirUnit",
952 6 : OutAirUnit(OAUnitNum).Name,
953 6 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(InListNum).Type)],
954 6 : OutAirUnit(OAUnitNum).OAEquip(InListNum).ComponentName,
955 : "UNDEFINED",
956 12 : "UNDEFINED");
957 : }
958 : }
959 : // Must call after SetUpCompSets since this will add another CoilSystem:Cooling:DX object in CompSets
960 39 : if (CompTypeNamesUC[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(InListNum).Type)] == "COILSYSTEM:COOLING:DX") {
961 8 : UnitarySystems::UnitarySys::checkUnitarySysCoilInOASysExists(
962 8 : state, OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName, OAUnitNum);
963 : }
964 : } // End Inlist
965 :
966 : // In case of draw through, the last component is linked with the zone air supply node
967 12 : if (OutAirUnit(OAUnitNum).FanPlace == DrawThru) {
968 18 : SetUpCompSets(state,
969 : CurrentModuleObject,
970 6 : OutAirUnit(OAUnitNum).Name,
971 : "UNDEFINED",
972 6 : state.dataIPShortCut->cAlphaArgs(5),
973 : "UNDEFINED",
974 18 : state.dataIPShortCut->cAlphaArgs(13));
975 : }
976 :
977 : } else { // when ListNum<0
978 0 : ShowSevereError(state,
979 0 : std::string{CurrentModuleObject} + " = \"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " +
980 0 : cAlphaFields(16) + "=\"" + state.dataIPShortCut->cAlphaArgs(16) + "\" not found.");
981 0 : ErrorsFound = true;
982 : }
983 : } else { // when Equipment list is left blanked
984 0 : ShowSevereError(state,
985 0 : std::string{CurrentModuleObject} + " = \"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid " + cAlphaFields(16) +
986 : " is blank and must be entered.");
987 0 : ErrorsFound = true;
988 : }
989 12 : if (!lAlphaBlanks(17)) {
990 0 : OutAirUnit(OAUnitNum).AvailManagerListName = state.dataIPShortCut->cAlphaArgs(17);
991 : }
992 : }
993 :
994 2 : if (ErrorsFound) {
995 0 : ShowFatalError(state, std::string{RoutineName} + "Errors found in getting " + std::string{CurrentModuleObject} + '.');
996 : }
997 :
998 2 : AlphArray.deallocate();
999 2 : cAlphaFields.deallocate();
1000 2 : NumArray.deallocate();
1001 2 : cNumericFields.deallocate();
1002 2 : lAlphaBlanks.deallocate();
1003 2 : lNumericBlanks.deallocate();
1004 :
1005 2 : state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false;
1006 :
1007 : // Setup Report variables for the zone outdoor air unit CurrentModuleObject='ZoneHVAC:OutdoorAirUnit'
1008 14 : for (OAUnitNum = 1; OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits; ++OAUnitNum) {
1009 48 : SetupOutputVariable(state,
1010 : "Zone Outdoor Air Unit Total Heating Rate",
1011 : OutputProcessor::Unit::W,
1012 12 : OutAirUnit(OAUnitNum).TotHeatingRate,
1013 : OutputProcessor::SOVTimeStepType::System,
1014 : OutputProcessor::SOVStoreType::Average,
1015 24 : OutAirUnit(OAUnitNum).Name);
1016 48 : SetupOutputVariable(state,
1017 : "Zone Outdoor Air Unit Total Heating Energy",
1018 : OutputProcessor::Unit::J,
1019 12 : OutAirUnit(OAUnitNum).TotHeatingEnergy,
1020 : OutputProcessor::SOVTimeStepType::System,
1021 : OutputProcessor::SOVStoreType::Summed,
1022 24 : OutAirUnit(OAUnitNum).Name);
1023 48 : SetupOutputVariable(state,
1024 : "Zone Outdoor Air Unit Sensible Heating Rate",
1025 : OutputProcessor::Unit::W,
1026 12 : OutAirUnit(OAUnitNum).SensHeatingRate,
1027 : OutputProcessor::SOVTimeStepType::System,
1028 : OutputProcessor::SOVStoreType::Average,
1029 24 : OutAirUnit(OAUnitNum).Name);
1030 48 : SetupOutputVariable(state,
1031 : "Zone Outdoor Air Unit Sensible Heating Energy",
1032 : OutputProcessor::Unit::J,
1033 12 : OutAirUnit(OAUnitNum).SensHeatingEnergy,
1034 : OutputProcessor::SOVTimeStepType::System,
1035 : OutputProcessor::SOVStoreType::Summed,
1036 24 : OutAirUnit(OAUnitNum).Name);
1037 48 : SetupOutputVariable(state,
1038 : "Zone Outdoor Air Unit Latent Heating Rate",
1039 : OutputProcessor::Unit::W,
1040 12 : OutAirUnit(OAUnitNum).LatHeatingRate,
1041 : OutputProcessor::SOVTimeStepType::System,
1042 : OutputProcessor::SOVStoreType::Average,
1043 24 : OutAirUnit(OAUnitNum).Name);
1044 48 : SetupOutputVariable(state,
1045 : "Zone Outdoor Air Unit Latent Heating Energy",
1046 : OutputProcessor::Unit::J,
1047 12 : OutAirUnit(OAUnitNum).LatHeatingEnergy,
1048 : OutputProcessor::SOVTimeStepType::System,
1049 : OutputProcessor::SOVStoreType::Summed,
1050 24 : OutAirUnit(OAUnitNum).Name);
1051 48 : SetupOutputVariable(state,
1052 : "Zone Outdoor Air Unit Total Cooling Rate",
1053 : OutputProcessor::Unit::W,
1054 12 : OutAirUnit(OAUnitNum).TotCoolingRate,
1055 : OutputProcessor::SOVTimeStepType::System,
1056 : OutputProcessor::SOVStoreType::Average,
1057 24 : OutAirUnit(OAUnitNum).Name);
1058 48 : SetupOutputVariable(state,
1059 : "Zone Outdoor Air Unit Total Cooling Energy",
1060 : OutputProcessor::Unit::J,
1061 12 : OutAirUnit(OAUnitNum).TotCoolingEnergy,
1062 : OutputProcessor::SOVTimeStepType::System,
1063 : OutputProcessor::SOVStoreType::Summed,
1064 24 : OutAirUnit(OAUnitNum).Name);
1065 48 : SetupOutputVariable(state,
1066 : "Zone Outdoor Air Unit Sensible Cooling Rate",
1067 : OutputProcessor::Unit::W,
1068 12 : OutAirUnit(OAUnitNum).SensCoolingRate,
1069 : OutputProcessor::SOVTimeStepType::System,
1070 : OutputProcessor::SOVStoreType::Average,
1071 24 : OutAirUnit(OAUnitNum).Name);
1072 48 : SetupOutputVariable(state,
1073 : "Zone Outdoor Air Unit Sensible Cooling Energy",
1074 : OutputProcessor::Unit::J,
1075 12 : OutAirUnit(OAUnitNum).SensCoolingEnergy,
1076 : OutputProcessor::SOVTimeStepType::System,
1077 : OutputProcessor::SOVStoreType::Summed,
1078 24 : OutAirUnit(OAUnitNum).Name);
1079 48 : SetupOutputVariable(state,
1080 : "Zone Outdoor Air Unit Latent Cooling Rate",
1081 : OutputProcessor::Unit::W,
1082 12 : OutAirUnit(OAUnitNum).LatCoolingRate,
1083 : OutputProcessor::SOVTimeStepType::System,
1084 : OutputProcessor::SOVStoreType::Average,
1085 24 : OutAirUnit(OAUnitNum).Name);
1086 48 : SetupOutputVariable(state,
1087 : "Zone Outdoor Air Unit Latent Cooling Energy",
1088 : OutputProcessor::Unit::J,
1089 12 : OutAirUnit(OAUnitNum).LatCoolingEnergy,
1090 : OutputProcessor::SOVTimeStepType::System,
1091 : OutputProcessor::SOVStoreType::Summed,
1092 24 : OutAirUnit(OAUnitNum).Name);
1093 48 : SetupOutputVariable(state,
1094 : "Zone Outdoor Air Unit Air Mass Flow Rate",
1095 : OutputProcessor::Unit::kg_s,
1096 12 : OutAirUnit(OAUnitNum).AirMassFlow,
1097 : OutputProcessor::SOVTimeStepType::System,
1098 : OutputProcessor::SOVStoreType::Average,
1099 24 : OutAirUnit(OAUnitNum).Name);
1100 48 : SetupOutputVariable(state,
1101 : "Zone Outdoor Air Unit Fan Electricity Rate",
1102 : OutputProcessor::Unit::W,
1103 12 : OutAirUnit(OAUnitNum).ElecFanRate,
1104 : OutputProcessor::SOVTimeStepType::System,
1105 : OutputProcessor::SOVStoreType::Average,
1106 24 : OutAirUnit(OAUnitNum).Name);
1107 48 : SetupOutputVariable(state,
1108 : "Zone Outdoor Air Unit Fan Electricity Energy",
1109 : OutputProcessor::Unit::J,
1110 12 : OutAirUnit(OAUnitNum).ElecFanEnergy,
1111 : OutputProcessor::SOVTimeStepType::System,
1112 : OutputProcessor::SOVStoreType::Summed,
1113 24 : OutAirUnit(OAUnitNum).Name);
1114 48 : SetupOutputVariable(state,
1115 : "Zone Outdoor Air Unit Fan Availability Status",
1116 : OutputProcessor::Unit::None,
1117 12 : OutAirUnit(OAUnitNum).AvailStatus,
1118 : OutputProcessor::SOVTimeStepType::System,
1119 : OutputProcessor::SOVStoreType::Average,
1120 24 : OutAirUnit(OAUnitNum).Name);
1121 : //! Note that the outdoor air unit fan electric is NOT metered because this value is already metered through the fan component
1122 : }
1123 : }
1124 :
1125 66054 : void InitOutdoorAirUnit(EnergyPlusData &state,
1126 : int const OAUnitNum, // index for the current outdoor air unit
1127 : int const ZoneNum, // number of zone being served
1128 : bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep
1129 : )
1130 : {
1131 :
1132 : // SUBROUTINE INFORMATION:
1133 : // AUTHOR Young Tae Chae, Rick Strand
1134 : // DATE WRITTEN July 2009
1135 : // MODIFIED July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
1136 : // RE-ENGINEERED na
1137 :
1138 : // PURPOSE OF THIS SUBROUTINE:
1139 : // This subroutine initializes all of the data elements which are necessary
1140 : // to simulate a zone outdoor air control unit.
1141 :
1142 : // METHODOLOGY EMPLOYED:
1143 : // Uses the status flags to trigger initializations.
1144 :
1145 : // REFERENCES:
1146 : // na
1147 :
1148 : // Using/Aliasing
1149 66054 : auto &ZoneComp = state.dataHVACGlobal->ZoneComp;
1150 66054 : auto &ZoneCompTurnFansOff = state.dataHVACGlobal->ZoneCompTurnFansOff;
1151 66054 : auto &ZoneCompTurnFansOn = state.dataHVACGlobal->ZoneCompTurnFansOn;
1152 :
1153 : using DataZoneEquipment::CheckZoneEquipmentList;
1154 : using FluidProperties::GetDensityGlycol;
1155 : using HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil;
1156 : using PlantUtilities::InitComponentNodes;
1157 : using PlantUtilities::ScanPlantLoopsForObject;
1158 : using ScheduleManager::GetCurrentScheduleValue;
1159 : using SteamCoils::GetCoilMaxSteamFlowRate;
1160 : using WaterCoils::SimulateWaterCoilComponents;
1161 :
1162 : // SUBROUTINE PARAMETER DEFINITIONS:
1163 : static constexpr std::string_view CurrentModuleObject("ZoneHVAC:OutdoorAirUnit");
1164 : static constexpr std::string_view RoutineName("SizeOutdoorAirUnit");
1165 :
1166 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1167 : int Loop;
1168 66054 : auto &MyEnvrnFlag = state.dataOutdoorAirUnit->MyEnvrnFlag;
1169 66054 : auto &MyPlantScanFlag = state.dataOutdoorAirUnit->MyPlantScanFlag;
1170 66054 : auto &MyZoneEqFlag = state.dataOutdoorAirUnit->MyZoneEqFlag; // used to set up zone equipment availability managers
1171 : int InNode; // inlet node number in outdoor air unit
1172 : int OutNode; // outlet node number in outdoor air unit
1173 : int OutsideAirNode; // outside air node number outdoor air unit
1174 : Real64 OAFrac; // possible outside air fraction
1175 : Real64 EAFrac; // possible exhaust air fraction
1176 : Real64 RhoAir; // air density at InNode
1177 : int compLoop; // local do loop index
1178 : Real64 rho;
1179 : bool errFlag;
1180 :
1181 : // Do the one time initializations
1182 :
1183 66054 : auto &OutAirUnit(state.dataOutdoorAirUnit->OutAirUnit);
1184 :
1185 66054 : if (state.dataOutdoorAirUnit->MyOneTimeFlag) {
1186 :
1187 2 : MyEnvrnFlag.allocate(state.dataOutdoorAirUnit->NumOfOAUnits);
1188 2 : state.dataOutdoorAirUnit->MySizeFlag.allocate(state.dataOutdoorAirUnit->NumOfOAUnits);
1189 2 : MyPlantScanFlag.allocate(state.dataOutdoorAirUnit->NumOfOAUnits);
1190 2 : MyZoneEqFlag.allocate(state.dataOutdoorAirUnit->NumOfOAUnits);
1191 2 : MyEnvrnFlag = true;
1192 2 : state.dataOutdoorAirUnit->MySizeFlag = true;
1193 2 : MyPlantScanFlag = true;
1194 2 : MyZoneEqFlag = true;
1195 2 : state.dataOutdoorAirUnit->MyOneTimeFlag = false;
1196 : }
1197 :
1198 66054 : if (allocated(ZoneComp)) {
1199 66054 : if (MyZoneEqFlag(OAUnitNum)) { // initialize the name of each availability manager list and zone number
1200 24 : ZoneComp(DataZoneEquipment::ZoneEquip::OutdoorAirUnit).ZoneCompAvailMgrs(OAUnitNum).AvailManagerListName =
1201 24 : OutAirUnit(OAUnitNum).AvailManagerListName;
1202 12 : ZoneComp(DataZoneEquipment::ZoneEquip::OutdoorAirUnit).ZoneCompAvailMgrs(OAUnitNum).ZoneNum = ZoneNum;
1203 12 : MyZoneEqFlag(OAUnitNum) = false;
1204 : }
1205 66054 : OutAirUnit(OAUnitNum).AvailStatus = ZoneComp(DataZoneEquipment::ZoneEquip::OutdoorAirUnit).ZoneCompAvailMgrs(OAUnitNum).AvailStatus;
1206 : }
1207 :
1208 66054 : if (MyPlantScanFlag(OAUnitNum) && allocated(state.dataPlnt->PlantLoop)) {
1209 51 : for (compLoop = 1; compLoop <= OutAirUnit(OAUnitNum).NumComponents; ++compLoop) {
1210 :
1211 39 : CompType Type = OutAirUnit(OAUnitNum).OAEquip(compLoop).Type;
1212 :
1213 39 : switch (Type) {
1214 12 : case CompType::WaterCoil_Cooling:
1215 : case CompType::WaterCoil_DetailedCool:
1216 : case CompType::WaterCoil_SimpleHeat:
1217 : case CompType::SteamCoil_AirHeat:
1218 :
1219 : {
1220 12 : errFlag = false;
1221 48 : ScanPlantLoopsForObject(state,
1222 12 : OutAirUnit(OAUnitNum).OAEquip(compLoop).ComponentName,
1223 12 : OutAirUnit(OAUnitNum).OAEquip(compLoop).CoilType,
1224 12 : OutAirUnit(OAUnitNum).OAEquip(compLoop).plantLoc,
1225 : errFlag,
1226 : _,
1227 : _,
1228 : _,
1229 : _,
1230 : _);
1231 12 : if (errFlag) {
1232 0 : ShowFatalError(state, "InitOutdoorAirUnit: Program terminated for previous conditions.");
1233 : }
1234 12 : break;
1235 : }
1236 27 : default:
1237 27 : break;
1238 : }
1239 : }
1240 :
1241 12 : MyPlantScanFlag(OAUnitNum) = false;
1242 66042 : } else if (MyPlantScanFlag(OAUnitNum) && !state.dataGlobal->AnyPlantInModel) {
1243 0 : MyPlantScanFlag(OAUnitNum) = false;
1244 : }
1245 :
1246 : // need to check all zone outdoor air control units to see if they are on Zone Equipment List or issue warning
1247 66054 : if (!state.dataOutdoorAirUnit->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
1248 2 : state.dataOutdoorAirUnit->ZoneEquipmentListChecked = true;
1249 14 : for (Loop = 1; Loop <= state.dataOutdoorAirUnit->NumOfOAUnits; ++Loop) {
1250 12 : if (CheckZoneEquipmentList(state, CurrentModuleObject, OutAirUnit(Loop).Name)) continue;
1251 0 : ShowSevereError(state,
1252 0 : "InitOutdoorAirUnit: Zone Outdoor Air Unit=[" + std::string{CurrentModuleObject} + ',' + OutAirUnit(Loop).Name +
1253 : "] is not on any ZoneHVAC:EquipmentList. It will not be simulated.");
1254 : }
1255 : }
1256 :
1257 66054 : if (!state.dataGlobal->SysSizingCalc && state.dataOutdoorAirUnit->MySizeFlag(OAUnitNum) && !MyPlantScanFlag(OAUnitNum)) {
1258 :
1259 12 : SizeOutdoorAirUnit(state, OAUnitNum);
1260 :
1261 12 : state.dataOutdoorAirUnit->MySizeFlag(OAUnitNum) = false;
1262 : }
1263 :
1264 : // Do the one time initializations
1265 66054 : if (state.dataGlobal->BeginEnvrnFlag && MyEnvrnFlag(OAUnitNum)) {
1266 : // Node Conditions
1267 :
1268 72 : OutNode = OutAirUnit(OAUnitNum).AirOutletNode;
1269 72 : OutsideAirNode = OutAirUnit(OAUnitNum).OutsideAirNode;
1270 : // Outdoor Air flow rate conditions
1271 72 : RhoAir = state.dataEnvrn->StdRhoAir;
1272 72 : OAFrac = GetCurrentScheduleValue(state, OutAirUnit(OAUnitNum).OutAirSchedPtr);
1273 72 : OutAirUnit(OAUnitNum).OutAirMassFlow = RhoAir * OAFrac * OutAirUnit(OAUnitNum).OutAirVolFlow;
1274 72 : OutAirUnit(OAUnitNum).SMaxAirMassFlow = RhoAir * OAFrac * OutAirUnit(OAUnitNum).SFanMaxAirVolFlow;
1275 :
1276 72 : if (OutAirUnit(OAUnitNum).ExtFan) {
1277 72 : InNode = OutAirUnit(OAUnitNum).AirInletNode;
1278 : // set the exhaust air mass flow rate from input
1279 72 : if (OutAirUnit(OAUnitNum).ExtFan) {
1280 72 : EAFrac = GetCurrentScheduleValue(state, OutAirUnit(OAUnitNum).ExtOutAirSchedPtr);
1281 72 : OutAirUnit(OAUnitNum).ExtAirMassFlow = RhoAir * EAFrac * OutAirUnit(OAUnitNum).ExtAirVolFlow;
1282 72 : OutAirUnit(OAUnitNum).EMaxAirMassFlow = RhoAir * EAFrac * OutAirUnit(OAUnitNum).EFanMaxAirVolFlow;
1283 0 : } else if (!OutAirUnit(OAUnitNum).ExtFan) {
1284 0 : OutAirUnit(OAUnitNum).ExtAirMassFlow = OutAirUnit(OAUnitNum).OutAirMassFlow;
1285 0 : OutAirUnit(OAUnitNum).EMaxAirMassFlow = OutAirUnit(OAUnitNum).SMaxAirMassFlow;
1286 : }
1287 72 : state.dataLoopNodes->Node(InNode).MassFlowRateMax = OutAirUnit(OAUnitNum).EMaxAirMassFlow;
1288 72 : state.dataLoopNodes->Node(InNode).MassFlowRateMin = 0.0;
1289 : }
1290 : // set the node max and min mass flow rates
1291 72 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMax = OutAirUnit(OAUnitNum).SMaxAirMassFlow;
1292 72 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMin = 0.0;
1293 72 : state.dataLoopNodes->Node(OutNode).MassFlowRate = OutAirUnit(OAUnitNum).EMaxAirMassFlow;
1294 :
1295 72 : if (!MyPlantScanFlag(OAUnitNum)) {
1296 306 : for (compLoop = 1; compLoop <= OutAirUnit(OAUnitNum).NumComponents; ++compLoop) {
1297 432 : if ((OutAirUnit(OAUnitNum).OAEquip(compLoop).Type == CompType::WaterCoil_Cooling) ||
1298 198 : (OutAirUnit(OAUnitNum).OAEquip(compLoop).Type == CompType::WaterCoil_DetailedCool)) {
1299 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxVolWaterFlow =
1300 72 : WaterCoils::GetCoilMaxWaterFlowRate(state,
1301 36 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(compLoop).Type)],
1302 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).ComponentName,
1303 : errFlag);
1304 72 : rho = GetDensityGlycol(state,
1305 36 : state.dataPlnt->PlantLoop(OutAirUnit(OAUnitNum).OAEquip(compLoop).plantLoc.loopNum).FluidName,
1306 : DataGlobalConstants::CWInitConvTemp,
1307 36 : state.dataPlnt->PlantLoop(OutAirUnit(OAUnitNum).OAEquip(compLoop).plantLoc.loopNum).FluidIndex,
1308 : RoutineName);
1309 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxWaterMassFlow = rho * OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxVolWaterFlow;
1310 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MinWaterMassFlow = rho * OutAirUnit(OAUnitNum).OAEquip(compLoop).MinVolWaterFlow;
1311 144 : InitComponentNodes(state,
1312 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MinWaterMassFlow,
1313 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxWaterMassFlow,
1314 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).CoilWaterInletNode,
1315 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).CoilWaterOutletNode);
1316 : }
1317 :
1318 234 : if (OutAirUnit(OAUnitNum).OAEquip(compLoop).Type == CompType::WaterCoil_SimpleHeat) {
1319 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxVolWaterFlow =
1320 72 : WaterCoils::GetCoilMaxWaterFlowRate(state,
1321 36 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(compLoop).Type)],
1322 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).ComponentName,
1323 : errFlag);
1324 72 : rho = GetDensityGlycol(state,
1325 36 : state.dataPlnt->PlantLoop(OutAirUnit(OAUnitNum).OAEquip(compLoop).plantLoc.loopNum).FluidName,
1326 : DataGlobalConstants::HWInitConvTemp,
1327 36 : state.dataPlnt->PlantLoop(OutAirUnit(OAUnitNum).OAEquip(compLoop).plantLoc.loopNum).FluidIndex,
1328 : RoutineName);
1329 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxWaterMassFlow = rho * OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxVolWaterFlow;
1330 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MinWaterMassFlow = rho * OutAirUnit(OAUnitNum).OAEquip(compLoop).MinVolWaterFlow;
1331 144 : InitComponentNodes(state,
1332 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MinWaterMassFlow,
1333 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxWaterMassFlow,
1334 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).CoilWaterInletNode,
1335 36 : OutAirUnit(OAUnitNum).OAEquip(compLoop).CoilWaterOutletNode);
1336 : }
1337 234 : if (OutAirUnit(OAUnitNum).OAEquip(compLoop).Type == CompType::SteamCoil_AirHeat) {
1338 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxVolWaterFlow =
1339 0 : GetCoilMaxSteamFlowRate(state, OutAirUnit(OAUnitNum).OAEquip(compLoop).ComponentIndex, errFlag);
1340 : Real64 rho =
1341 0 : GetSatDensityRefrig(state,
1342 0 : state.dataPlnt->PlantLoop(OutAirUnit(OAUnitNum).OAEquip(compLoop).plantLoc.loopNum).FluidName,
1343 : DataGlobalConstants::SteamInitConvTemp,
1344 : 1.0,
1345 0 : state.dataPlnt->PlantLoop(OutAirUnit(OAUnitNum).OAEquip(compLoop).plantLoc.loopNum).FluidIndex,
1346 0 : RoutineName);
1347 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxWaterMassFlow = rho * OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxVolWaterFlow;
1348 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MinWaterMassFlow = rho * OutAirUnit(OAUnitNum).OAEquip(compLoop).MinVolWaterFlow;
1349 0 : InitComponentNodes(state,
1350 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MinWaterMassFlow,
1351 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxWaterMassFlow,
1352 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).CoilWaterInletNode,
1353 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).CoilWaterOutletNode);
1354 : }
1355 234 : if (OutAirUnit(OAUnitNum).OAEquip(compLoop).Type == CompType::WaterCoil_CoolingHXAsst) {
1356 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxVolWaterFlow =
1357 0 : WaterCoils::GetCoilMaxWaterFlowRate(state,
1358 0 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(compLoop).Type)],
1359 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).ComponentName,
1360 : errFlag);
1361 0 : rho = GetDensityGlycol(state,
1362 0 : state.dataPlnt->PlantLoop(OutAirUnit(OAUnitNum).OAEquip(compLoop).plantLoc.loopNum).FluidName,
1363 : DataGlobalConstants::CWInitConvTemp,
1364 0 : state.dataPlnt->PlantLoop(OutAirUnit(OAUnitNum).OAEquip(compLoop).plantLoc.loopNum).FluidIndex,
1365 : RoutineName);
1366 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxWaterMassFlow = rho * OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxVolWaterFlow;
1367 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MinWaterMassFlow = rho * OutAirUnit(OAUnitNum).OAEquip(compLoop).MinVolWaterFlow;
1368 0 : InitComponentNodes(state,
1369 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MinWaterMassFlow,
1370 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).MaxWaterMassFlow,
1371 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).CoilWaterInletNode,
1372 0 : OutAirUnit(OAUnitNum).OAEquip(compLoop).CoilWaterOutletNode);
1373 : }
1374 : }
1375 : }
1376 72 : MyEnvrnFlag(OAUnitNum) = false;
1377 :
1378 : } // ...end start of environment inits
1379 :
1380 66054 : if (!state.dataGlobal->BeginEnvrnFlag) MyEnvrnFlag(OAUnitNum) = true;
1381 :
1382 : // These initializations are done every iteration...
1383 : // Set all the output variable
1384 66054 : OutAirUnit(OAUnitNum).TotHeatingRate = 0.0;
1385 66054 : OutAirUnit(OAUnitNum).SensHeatingRate = 0.0;
1386 66054 : OutAirUnit(OAUnitNum).LatHeatingRate = 0.0;
1387 66054 : OutAirUnit(OAUnitNum).TotCoolingRate = 0.0;
1388 66054 : OutAirUnit(OAUnitNum).SensCoolingRate = 0.0;
1389 66054 : OutAirUnit(OAUnitNum).LatCoolingRate = 0.0;
1390 66054 : OutAirUnit(OAUnitNum).AirMassFlow = 0.0;
1391 66054 : OutAirUnit(OAUnitNum).ElecFanRate = 0.0;
1392 : // Node Set
1393 :
1394 66054 : OutNode = OutAirUnit(OAUnitNum).AirOutletNode;
1395 66054 : OutsideAirNode = OutAirUnit(OAUnitNum).OutsideAirNode;
1396 66054 : RhoAir = state.dataEnvrn->StdRhoAir;
1397 66054 : OAFrac = GetCurrentScheduleValue(state, OutAirUnit(OAUnitNum).OutAirSchedPtr);
1398 :
1399 : // set the mass flow rates from the input volume flow rates
1400 66054 : if (OAFrac > 0.0 || (ZoneCompTurnFansOn && !ZoneCompTurnFansOff)) { // fan is available
1401 64772 : OutAirUnit(OAUnitNum).OutAirMassFlow = RhoAir * OAFrac * OutAirUnit(OAUnitNum).OutAirVolFlow;
1402 : } else {
1403 1282 : OutAirUnit(OAUnitNum).OutAirMassFlow = 0.0;
1404 : }
1405 :
1406 : // set the exhaust air mass flow rate from input
1407 66054 : if (OutAirUnit(OAUnitNum).ExtFan) {
1408 66054 : InNode = OutAirUnit(OAUnitNum).AirInletNode;
1409 66054 : EAFrac = GetCurrentScheduleValue(state, OutAirUnit(OAUnitNum).ExtOutAirSchedPtr);
1410 66054 : if (OutAirUnit(OAUnitNum).ExtFanAvailSchedPtr > 0.0) {
1411 66054 : OutAirUnit(OAUnitNum).ExtAirMassFlow = RhoAir * EAFrac * OutAirUnit(OAUnitNum).ExtAirVolFlow;
1412 : } else {
1413 0 : OutAirUnit(OAUnitNum).ExtAirMassFlow = 0.0;
1414 : }
1415 66054 : state.dataLoopNodes->Node(InNode).MassFlowRate = OutAirUnit(OAUnitNum).ExtAirMassFlow;
1416 66054 : state.dataLoopNodes->Node(InNode).MassFlowRateMaxAvail = OutAirUnit(OAUnitNum).ExtAirMassFlow;
1417 66054 : state.dataLoopNodes->Node(InNode).MassFlowRateMinAvail = 0.0;
1418 0 : } else if (!OutAirUnit(OAUnitNum).ExtFan) {
1419 0 : OutAirUnit(OAUnitNum).ExtAirMassFlow = 0.0;
1420 : }
1421 :
1422 : // First, set the flow conditions up so that there is flow through the unit
1423 :
1424 66054 : state.dataLoopNodes->Node(OutNode).MassFlowRate = OutAirUnit(OAUnitNum).OutAirMassFlow;
1425 66054 : state.dataLoopNodes->Node(OutNode).MassFlowRateMaxAvail = OutAirUnit(OAUnitNum).OutAirMassFlow;
1426 66054 : state.dataLoopNodes->Node(OutNode).MassFlowRateMinAvail = 0.0;
1427 66054 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = OutAirUnit(OAUnitNum).OutAirMassFlow;
1428 66054 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMaxAvail = OutAirUnit(OAUnitNum).OutAirMassFlow;
1429 66054 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMinAvail = 0.0;
1430 :
1431 : // Just in case the system is off and conditions do not get sent through
1432 : // the system for some reason, set the outlet conditions equal to the inlet
1433 : // conditions of the zone outdoor air control unit
1434 66054 : if (OutAirUnit(OAUnitNum).ExtFan) {
1435 66054 : state.dataLoopNodes->Node(OutNode).Temp = state.dataLoopNodes->Node(InNode).Temp;
1436 66054 : state.dataLoopNodes->Node(OutNode).Press = state.dataLoopNodes->Node(InNode).Press;
1437 66054 : state.dataLoopNodes->Node(OutNode).HumRat = state.dataLoopNodes->Node(InNode).HumRat;
1438 66054 : state.dataLoopNodes->Node(OutNode).Enthalpy = state.dataLoopNodes->Node(InNode).Enthalpy;
1439 : } else {
1440 0 : state.dataLoopNodes->Node(OutNode).Temp = state.dataLoopNodes->Node(OutsideAirNode).Temp;
1441 0 : state.dataLoopNodes->Node(OutNode).Press = state.dataLoopNodes->Node(OutsideAirNode).Press;
1442 0 : state.dataLoopNodes->Node(OutNode).HumRat = state.dataLoopNodes->Node(OutsideAirNode).HumRat;
1443 0 : state.dataLoopNodes->Node(OutNode).Enthalpy = state.dataLoopNodes->Node(OutsideAirNode).Enthalpy;
1444 : }
1445 : // These initializations only need to be done once at the start of the iterations...
1446 66054 : if (FirstHVACIteration || state.dataHVACGlobal->ShortenTimeStepSys) {
1447 : // Initialize the outside air conditions...
1448 38502 : state.dataLoopNodes->Node(OutsideAirNode).Temp = state.dataLoopNodes->Node(OutsideAirNode).OutAirDryBulb;
1449 38502 : state.dataLoopNodes->Node(OutsideAirNode).HumRat = state.dataEnvrn->OutHumRat;
1450 38502 : state.dataLoopNodes->Node(OutsideAirNode).Press = state.dataEnvrn->OutBaroPress;
1451 : }
1452 66054 : }
1453 :
1454 12 : void SizeOutdoorAirUnit(EnergyPlusData &state, int const OAUnitNum)
1455 : {
1456 :
1457 : // SUBROUTINE INFORMATION:
1458 : // AUTHOR Young Tae Chae, Rick Strand
1459 : // DATE WRITTEN July 2009
1460 : // MODIFIED Brent Griffith, March 2010, autosize OA flow rate
1461 : // August 2013 Daeho Kang, add component sizing table entries
1462 : // RE-ENGINEERED na
1463 :
1464 : // PURPOSE OF THIS SUBROUTINE:
1465 : // This subroutine is for sizing zoen outdoor air control unit components for which flow rates have not been
1466 : // specified in the input.
1467 :
1468 : // METHODOLOGY EMPLOYED:
1469 : // Obtains flow rates from the zone sizing arrays and plant sizing data.
1470 :
1471 : // Using/Aliasing
1472 : using namespace DataSizing;
1473 : using DataHVACGlobals::cFanTypes;
1474 :
1475 : using Fans::GetFanDesignVolumeFlowRate;
1476 :
1477 : using HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil;
1478 : using PlantUtilities::MyPlantSizingIndex;
1479 : using SteamCoils::SimulateSteamCoilComponents;
1480 : using WaterCoils::SimulateWaterCoilComponents;
1481 :
1482 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1483 : int PltSizHeatNum; // index of plant sizing object for 1st heating loop
1484 : int PltSizCoolNum; // index of plant sizing object for 1st cooling loop
1485 : bool ErrorsFound;
1486 : Real64 RhoAir;
1487 : int CompNum;
1488 : bool IsAutoSize; // Indicator to autosize
1489 : Real64 OutAirVolFlowDes; // Autosized outdoor air flow for reporting
1490 : Real64 OutAirVolFlowUser; // Hardsized outdoor air flow for reporting
1491 : Real64 ExtAirVolFlowDes; // Autosized exhaust air flow for reporting
1492 : Real64 ExtAirVolFlowUser; // Hardsized exhaust air flow for reporting
1493 : Real64 MaxVolWaterFlowDes; // Autosized maximum water flow for reporting
1494 : Real64 MaxVolWaterFlowUser; // Hardsized maximum water flow for reporting
1495 :
1496 12 : PltSizCoolNum = 0;
1497 12 : PltSizHeatNum = 0;
1498 12 : ErrorsFound = false;
1499 12 : RhoAir = state.dataEnvrn->StdRhoAir;
1500 12 : IsAutoSize = false;
1501 12 : OutAirVolFlowDes = 0.0;
1502 12 : OutAirVolFlowUser = 0.0;
1503 12 : ExtAirVolFlowDes = 0.0;
1504 12 : ExtAirVolFlowUser = 0.0;
1505 12 : MaxVolWaterFlowDes = 0.0;
1506 12 : MaxVolWaterFlowUser = 0.0;
1507 :
1508 12 : auto &OutAirUnit(state.dataOutdoorAirUnit->OutAirUnit);
1509 12 : auto &ZoneEqSizing(state.dataSize->ZoneEqSizing);
1510 12 : auto &DataFanEnumType(state.dataSize->DataFanEnumType);
1511 :
1512 12 : if (OutAirUnit(OAUnitNum).SFanType == DataHVACGlobals::FanType_SystemModelObject) {
1513 6 : DataFanEnumType = DataAirSystems::ObjectVectorOOFanSystemModel;
1514 : } else {
1515 6 : DataFanEnumType = DataAirSystems::StructArrayLegacyFanModels;
1516 : }
1517 12 : state.dataSize->DataFanIndex = OutAirUnit(OAUnitNum).SFan_Index;
1518 12 : if (OutAirUnit(OAUnitNum).FanPlace == BlowThru) {
1519 6 : state.dataSize->DataFanPlacement = DataSizing::ZoneFanPlacement::BlowThru;
1520 6 : } else if (OutAirUnit(OAUnitNum).FanPlace == DrawThru) {
1521 6 : state.dataSize->DataFanPlacement = DataSizing::ZoneFanPlacement::DrawThru;
1522 : }
1523 :
1524 12 : if (OutAirUnit(OAUnitNum).OutAirVolFlow == AutoSize) {
1525 5 : IsAutoSize = true;
1526 : }
1527 :
1528 12 : if (state.dataSize->CurZoneEqNum > 0) {
1529 12 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1530 0 : if (OutAirUnit(OAUnitNum).OutAirVolFlow > 0.0) {
1531 0 : BaseSizer::reportSizerOutput(state,
1532 : ZoneHVACOAUnit,
1533 0 : OutAirUnit(OAUnitNum).Name,
1534 : "User-Specified Outdoor Air Flow Rate [m3/s]",
1535 0 : OutAirUnit(OAUnitNum).OutAirVolFlow);
1536 : }
1537 : } else {
1538 12 : CheckZoneSizing(state, std::string(ZoneHVACOAUnit), OutAirUnit(OAUnitNum).Name);
1539 12 : OutAirVolFlowDes = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).MinOA;
1540 12 : if (OutAirVolFlowDes < SmallAirVolFlow) {
1541 0 : OutAirVolFlowDes = 0.0;
1542 : }
1543 12 : if (IsAutoSize) {
1544 5 : OutAirUnit(OAUnitNum).OutAirVolFlow = OutAirVolFlowDes;
1545 10 : BaseSizer::reportSizerOutput(
1546 5 : state, ZoneHVACOAUnit, OutAirUnit(OAUnitNum).Name, "Design Size Outdoor Air Flow Rate [m3/s]", OutAirVolFlowDes);
1547 : } else {
1548 7 : if (OutAirUnit(OAUnitNum).OutAirVolFlow > 0.0 && OutAirVolFlowDes > 0.0) {
1549 7 : OutAirVolFlowUser = OutAirUnit(OAUnitNum).OutAirVolFlow;
1550 14 : BaseSizer::reportSizerOutput(
1551 7 : state, ZoneHVACOAUnit, OutAirUnit(OAUnitNum).Name, "User-Specified Outdoor Air Flow Rate [m3/s]", OutAirVolFlowUser);
1552 7 : if (state.dataGlobal->DisplayExtraWarnings) {
1553 0 : if ((std::abs(OutAirVolFlowDes - OutAirVolFlowUser) / OutAirVolFlowUser) > state.dataSize->AutoVsHardSizingThreshold) {
1554 0 : BaseSizer::reportSizerOutput(
1555 0 : state, ZoneHVACOAUnit, OutAirUnit(OAUnitNum).Name, "Design Size Outdoor Air Flow Rate [m3/s]", OutAirVolFlowDes);
1556 0 : ShowMessage(state,
1557 0 : "SizeOutdoorAirUnit: Potential issue with equipment sizing for ZoneHVAC:OutdoorAirUnit " +
1558 0 : OutAirUnit(OAUnitNum).Name);
1559 0 : ShowContinueError(state, format("User-Specified Outdoor Air Flow Rate of {:.5R} [m3/s]", OutAirVolFlowUser));
1560 0 : ShowContinueError(state, format("differs from Design Size Outdoor Air Flow Rate of {:.5R} [m3/s]", OutAirVolFlowDes));
1561 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1562 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1563 : }
1564 : }
1565 : }
1566 : }
1567 : }
1568 : }
1569 :
1570 12 : IsAutoSize = false;
1571 12 : if (OutAirUnit(OAUnitNum).ExtAirVolFlow == AutoSize) {
1572 5 : IsAutoSize = true;
1573 : }
1574 12 : if (state.dataSize->CurZoneEqNum > 0) {
1575 12 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1576 0 : if (OutAirUnit(OAUnitNum).ExtAirVolFlow > 0.0) {
1577 0 : BaseSizer::reportSizerOutput(state,
1578 : ZoneHVACOAUnit,
1579 0 : OutAirUnit(OAUnitNum).Name,
1580 : "User-Specified Exhaust Air Flow Rate [m3/s]",
1581 0 : OutAirUnit(OAUnitNum).ExtAirVolFlow);
1582 : }
1583 : } else {
1584 : // set exhaust flow equal to the oa inlet flow
1585 12 : ExtAirVolFlowDes = OutAirUnit(OAUnitNum).OutAirVolFlow;
1586 12 : if (IsAutoSize) {
1587 5 : OutAirUnit(OAUnitNum).ExtAirVolFlow = ExtAirVolFlowDes;
1588 10 : BaseSizer::reportSizerOutput(
1589 5 : state, ZoneHVACOAUnit, OutAirUnit(OAUnitNum).Name, "Design Size Exhaust Air Flow Rate [m3/s]", ExtAirVolFlowDes);
1590 : } else {
1591 7 : if (OutAirUnit(OAUnitNum).ExtAirVolFlow > 0.0 && ExtAirVolFlowDes > 0.0) {
1592 7 : ExtAirVolFlowUser = OutAirUnit(OAUnitNum).ExtAirVolFlow;
1593 14 : BaseSizer::reportSizerOutput(
1594 7 : state, ZoneHVACOAUnit, OutAirUnit(OAUnitNum).Name, "User-Specified Exhaust Air Flow Rate [m3/s]", ExtAirVolFlowUser);
1595 7 : if (state.dataGlobal->DisplayExtraWarnings) {
1596 0 : if ((std::abs(ExtAirVolFlowDes - ExtAirVolFlowUser) / ExtAirVolFlowUser) > state.dataSize->AutoVsHardSizingThreshold) {
1597 0 : BaseSizer::reportSizerOutput(
1598 0 : state, ZoneHVACOAUnit, OutAirUnit(OAUnitNum).Name, "Design Size Exhaust Air Flow Rate [m3/s]", ExtAirVolFlowDes);
1599 0 : ShowMessage(state,
1600 0 : "SizeOutdoorAirUnit: Potential issue with equipment sizing for ZoneHVAC:OutdoorAirUnit " +
1601 0 : OutAirUnit(OAUnitNum).Name);
1602 0 : ShowContinueError(state, format("User-Specified Exhaust Air Flow Rate of {:.5R} [m3/s]", ExtAirVolFlowUser));
1603 0 : ShowContinueError(state, format("differs from Design Size Exhaust Air Flow Rate of {:.5R} [m3/s]", ExtAirVolFlowDes));
1604 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1605 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1606 : }
1607 : }
1608 : }
1609 : }
1610 : }
1611 : }
1612 :
1613 12 : ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingAirFlow = true;
1614 12 : ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingAirFlow = true;
1615 12 : ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingAirVolFlow = OutAirUnit(OAUnitNum).OutAirVolFlow;
1616 12 : ZoneEqSizing(state.dataSize->CurZoneEqNum).HeatingAirVolFlow = OutAirUnit(OAUnitNum).OutAirVolFlow;
1617 12 : ZoneEqSizing(state.dataSize->CurZoneEqNum).OAVolFlow = OutAirUnit(OAUnitNum).OutAirVolFlow;
1618 :
1619 12 : if (OutAirUnit(OAUnitNum).SFanMaxAirVolFlow == AutoSize) {
1620 5 : if (OutAirUnit(OAUnitNum).SFanType != DataHVACGlobals::FanType_SystemModelObject) {
1621 1 : Fans::SimulateFanComponents(state, OutAirUnit(OAUnitNum).SFanName, true, OutAirUnit(OAUnitNum).SFan_Index, _, false, false);
1622 1 : OutAirUnit(OAUnitNum).SFanMaxAirVolFlow =
1623 2 : GetFanDesignVolumeFlowRate(state, cFanTypes(OutAirUnit(OAUnitNum).SFanType), OutAirUnit(OAUnitNum).SFanName, ErrorsFound);
1624 :
1625 : } else {
1626 4 : state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).SFan_Index]->simulate(state, _, _, _, _);
1627 4 : OutAirUnit(OAUnitNum).SFanMaxAirVolFlow = state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).SFan_Index]->designAirVolFlowRate;
1628 : }
1629 : }
1630 12 : if (OutAirUnit(OAUnitNum).ExtFan) {
1631 12 : if (OutAirUnit(OAUnitNum).EFanMaxAirVolFlow == AutoSize) {
1632 6 : if (OutAirUnit(OAUnitNum).ExtFanType != DataHVACGlobals::FanType_SystemModelObject) {
1633 :
1634 1 : Fans::SimulateFanComponents(state, OutAirUnit(OAUnitNum).ExtFanName, true, OutAirUnit(OAUnitNum).ExtFan_Index);
1635 1 : OutAirUnit(OAUnitNum).EFanMaxAirVolFlow =
1636 2 : GetFanDesignVolumeFlowRate(state, cFanTypes(OutAirUnit(OAUnitNum).ExtFanType), OutAirUnit(OAUnitNum).ExtFanName, ErrorsFound);
1637 : } else {
1638 5 : state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).ExtFan_Index]->simulate(state, _, _, _, _);
1639 5 : OutAirUnit(OAUnitNum).EFanMaxAirVolFlow = state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).ExtFan_Index]->designAirVolFlowRate;
1640 : }
1641 : }
1642 : }
1643 :
1644 51 : for (CompNum = 1; CompNum <= OutAirUnit(OAUnitNum).NumComponents; ++CompNum) {
1645 72 : if ((OutAirUnit(OAUnitNum).OAEquip(CompNum).Type == CompType::WaterCoil_Cooling) ||
1646 33 : (OutAirUnit(OAUnitNum).OAEquip(CompNum).Type == CompType::WaterCoil_DetailedCool)) {
1647 6 : if (OutAirUnit(OAUnitNum).OAEquip(CompNum).MaxVolWaterFlow == AutoSize) {
1648 3 : SimulateWaterCoilComponents(state,
1649 1 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
1650 : true,
1651 1 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex,
1652 : _,
1653 : 1,
1654 : 0.0);
1655 : }
1656 : }
1657 39 : if (OutAirUnit(OAUnitNum).OAEquip(CompNum).Type == CompType::WaterCoil_SimpleHeat) {
1658 6 : if (OutAirUnit(OAUnitNum).OAEquip(CompNum).MaxVolWaterFlow == AutoSize) {
1659 9 : SimulateWaterCoilComponents(state,
1660 3 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
1661 : true,
1662 3 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex,
1663 : _,
1664 : 1,
1665 : 0.0);
1666 : }
1667 : }
1668 39 : if (OutAirUnit(OAUnitNum).OAEquip(CompNum).Type == CompType::SteamCoil_AirHeat) {
1669 0 : if (OutAirUnit(OAUnitNum).OAEquip(CompNum).MaxVolWaterFlow == AutoSize) {
1670 0 : SimulateSteamCoilComponents(
1671 0 : state, OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName, true, OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex);
1672 : }
1673 : }
1674 39 : if (OutAirUnit(OAUnitNum).OAEquip(CompNum).Type == CompType::WaterCoil_CoolingHXAsst) {
1675 0 : if (OutAirUnit(OAUnitNum).OAEquip(CompNum).MaxVolWaterFlow == AutoSize) {
1676 0 : SimHXAssistedCoolingCoil(state,
1677 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentName,
1678 : true,
1679 : DataHVACGlobals::CompressorOperation::On,
1680 : 0.0,
1681 0 : OutAirUnit(OAUnitNum).OAEquip(CompNum).ComponentIndex,
1682 : ContFanCycCoil);
1683 : }
1684 : }
1685 : }
1686 :
1687 12 : if (ErrorsFound) {
1688 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
1689 : }
1690 12 : }
1691 :
1692 66054 : void CalcOutdoorAirUnit(EnergyPlusData &state,
1693 : int &OAUnitNum, // number of the current unit being simulated
1694 : int const ZoneNum, // number of zone being served
1695 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
1696 : Real64 &PowerMet, // power supplied
1697 : Real64 &LatOutputProvided // Latent power supplied (kg/s), negative = dehumidification
1698 : )
1699 : {
1700 :
1701 : // SUBROUTINE INFORMATION:
1702 : // AUTHOR Young Tae Chae, Rick Strand
1703 : // DATE WRITTEN June 2008
1704 : // MODIFIED July 2012, Chandan Sharma - FSEC: Added zone sys avail managers
1705 : // RE-ENGINEERED na
1706 :
1707 : // PURPOSE OF THIS SUBROUTINE:
1708 : // This subroutine mainly controls the action of the outdoor air unit
1709 : // (or more exactly, it controls the coil outlet temperature of the unit)
1710 : // based on the user input for controls and the defined controls
1711 : // algorithms.
1712 :
1713 : // METHODOLOGY EMPLOYED:
1714 : // Outdoor air unit is controlled based on user input and what is happening in the
1715 : // simulation.
1716 : // Note: controls are strictly temperature based and do not factor
1717 : // humidity into the equation (not an enthalpy economy cycle but rather
1718 : // a simple return air cycle).
1719 :
1720 : // REFERENCES:
1721 : // ASHRAE Systems and Equipment Handbook (SI), 1996. page 31.3
1722 :
1723 : // USE STATEMENTS:
1724 :
1725 : // Using/Aliasing
1726 66054 : auto &ZoneCompTurnFansOff = state.dataHVACGlobal->ZoneCompTurnFansOff;
1727 66054 : auto &ZoneCompTurnFansOn = state.dataHVACGlobal->ZoneCompTurnFansOn;
1728 : using HeatingCoils::CheckHeatingCoilSchedule;
1729 : using HVACHXAssistedCoolingCoil::CheckHXAssistedCoolingCoilSchedule;
1730 : using ScheduleManager::GetCurrentScheduleValue;
1731 :
1732 : // Locals
1733 :
1734 : // SUBROUTINE ARGUMENT DEFINITIONS:
1735 :
1736 : // SUBROUTINE PARAMETER DEFINITIONS:
1737 : // INTERFACE BLOCK SPECIFICATIONS
1738 :
1739 : // DERIVED TYPE DEFINITIONS
1740 : // na
1741 :
1742 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1743 : Real64 DesOATemp; // Design OA Temp degree C
1744 : Real64 AirMassFlow; // air mass flow rate [kg/s]
1745 : int ControlNode; // the hot water or cold water inlet node
1746 : int InletNode; // Unit air inlet node
1747 : int SFanOutletNode; // Unit supply fan outlet node
1748 : int OutletNode; // air outlet node
1749 : int OutsideAirNode; // outside air node
1750 : Real64 QTotUnitOut; // total unit output [watts]
1751 : Real64 QUnitOut; // heating or sens. cooling provided by fan coil unit [watts]
1752 : Real64 LatLoadMet; // heating or sens. cooling provided by fan coil unit [watts]
1753 : Real64 MinHumRat; // desired temperature after mixing inlet and outdoor air [degrees C]
1754 : Real64 SetPointTemp; // temperature that will be used to control the radiant system [Celsius]
1755 : Real64 HiCtrlTemp; // Current high point in setpoint temperature range
1756 : Real64 LoCtrlTemp; // Current low point in setpoint temperature range
1757 : Real64 AirInEnt; // RE-calcualte the Enthalpy of supply air
1758 : Real64 AirOutletTemp;
1759 : Operation OperatingMode;
1760 : Real64 ZoneSupAirEnt; // Specific humidity ratio of inlet air (kg moisture / kg moist air)
1761 : // Latent output
1762 : Real64 LatentOutput; // Latent (moisture) add/removal rate, negative is dehumidification [kg/s]
1763 : Real64 SpecHumOut; // Specific humidity ratio of outlet air (kg moisture / kg moist air)
1764 : Real64 SpecHumIn; // Specific humidity ratio of inlet air (kg moisture / kg moist air)
1765 : Real64 ZoneAirEnt; // zone air enthalphy J/kg
1766 :
1767 66054 : auto &OutAirUnit(state.dataOutdoorAirUnit->OutAirUnit);
1768 :
1769 : // initialize local variables
1770 66054 : ControlNode = 0;
1771 66054 : QUnitOut = 0.0;
1772 66054 : if (OutAirUnit(OAUnitNum).ExtFan) InletNode = OutAirUnit(OAUnitNum).AirInletNode;
1773 66054 : SFanOutletNode = OutAirUnit(OAUnitNum).SFanOutletNode;
1774 66054 : OutletNode = OutAirUnit(OAUnitNum).AirOutletNode;
1775 66054 : OutsideAirNode = OutAirUnit(OAUnitNum).OutsideAirNode;
1776 66054 : OperatingMode = OutAirUnit(OAUnitNum).OperatingMode;
1777 66054 : OAUnitCtrlType UnitControlType = OutAirUnit(OAUnitNum).controlType;
1778 66054 : AirOutletTemp = 0.0;
1779 66054 : OutAirUnit(OAUnitNum).CompOutSetTemp = 0.0;
1780 66054 : OutAirUnit(OAUnitNum).FanEffect = false;
1781 :
1782 198162 : if ((GetCurrentScheduleValue(state, OutAirUnit(OAUnitNum).SchedPtr) <= 0) ||
1783 130826 : (GetCurrentScheduleValue(state, OutAirUnit(OAUnitNum).OutAirSchedPtr) <= 0) ||
1784 130826 : ((GetCurrentScheduleValue(state, OutAirUnit(OAUnitNum).SFanAvailSchedPtr) <= 0) && !ZoneCompTurnFansOn) || ZoneCompTurnFansOff) {
1785 : // System is off or has no load upon the unit; set the flow rates to zero and then
1786 : // simulate the components with the no flow conditions
1787 1282 : if (OutAirUnit(OAUnitNum).ExtFan) state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
1788 1282 : if (OutAirUnit(OAUnitNum).ExtFan) state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = 0.0;
1789 1282 : if (OutAirUnit(OAUnitNum).ExtFan) state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = 0.0;
1790 1282 : state.dataLoopNodes->Node(SFanOutletNode).MassFlowRate = 0.0;
1791 1282 : state.dataLoopNodes->Node(SFanOutletNode).MassFlowRateMaxAvail = 0.0;
1792 1282 : state.dataLoopNodes->Node(SFanOutletNode).MassFlowRateMinAvail = 0.0;
1793 1282 : state.dataLoopNodes->Node(OutletNode).MassFlowRate = 0.0;
1794 1282 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail = 0.0;
1795 1282 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMinAvail = 0.0;
1796 1282 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = 0.0;
1797 1282 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMaxAvail = 0.0;
1798 1282 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRateMinAvail = 0.0;
1799 1282 : AirMassFlow = state.dataLoopNodes->Node(SFanOutletNode).MassFlowRate;
1800 :
1801 : // Node condition
1802 1282 : if (OutAirUnit(OAUnitNum).ExtFan) {
1803 1282 : state.dataLoopNodes->Node(InletNode).Temp = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
1804 1282 : state.dataLoopNodes->Node(SFanOutletNode).Temp = state.dataLoopNodes->Node(InletNode).Temp;
1805 : } else {
1806 0 : state.dataLoopNodes->Node(SFanOutletNode).Temp = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
1807 : }
1808 1282 : state.dataLoopNodes->Node(OutletNode).Temp = state.dataLoopNodes->Node(SFanOutletNode).Temp;
1809 :
1810 1282 : if (OutAirUnit(OAUnitNum).FanPlace == BlowThru) {
1811 0 : if (OutAirUnit(OAUnitNum).SFanType != DataHVACGlobals::FanType_SystemModelObject) {
1812 0 : Fans::SimulateFanComponents(state,
1813 0 : OutAirUnit(OAUnitNum).SFanName,
1814 : FirstHVACIteration,
1815 0 : OutAirUnit(OAUnitNum).SFan_Index,
1816 : _,
1817 : ZoneCompTurnFansOn,
1818 : ZoneCompTurnFansOff);
1819 : } else {
1820 0 : state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).SFan_Index]->simulate(state, _, ZoneCompTurnFansOn, ZoneCompTurnFansOff, _);
1821 : }
1822 :
1823 0 : SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
1824 0 : if (OutAirUnit(OAUnitNum).ExtFan) {
1825 0 : if (OutAirUnit(OAUnitNum).ExtFanType != DataHVACGlobals::FanType_SystemModelObject) {
1826 0 : Fans::SimulateFanComponents(state,
1827 0 : OutAirUnit(OAUnitNum).ExtFanName,
1828 : FirstHVACIteration,
1829 0 : OutAirUnit(OAUnitNum).ExtFan_Index,
1830 : _,
1831 : ZoneCompTurnFansOn,
1832 : ZoneCompTurnFansOff); // why not turn on/off flags here?
1833 : } else {
1834 0 : state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).ExtFan_Index]->simulate(
1835 : state, _, ZoneCompTurnFansOn, ZoneCompTurnFansOff, _);
1836 : }
1837 : }
1838 :
1839 1282 : } else if (OutAirUnit(OAUnitNum).FanPlace == DrawThru) {
1840 1282 : SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
1841 1282 : if (OutAirUnit(OAUnitNum).SFanType != DataHVACGlobals::FanType_SystemModelObject) {
1842 0 : Fans::SimulateFanComponents(state,
1843 0 : OutAirUnit(OAUnitNum).SFanName,
1844 : FirstHVACIteration,
1845 0 : OutAirUnit(OAUnitNum).SFan_Index,
1846 : _,
1847 : ZoneCompTurnFansOn,
1848 : ZoneCompTurnFansOff);
1849 : } else {
1850 1282 : state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).SFan_Index]->simulate(state, _, ZoneCompTurnFansOn, ZoneCompTurnFansOff, _);
1851 : }
1852 1282 : if (OutAirUnit(OAUnitNum).ExtFan) {
1853 1282 : if (OutAirUnit(OAUnitNum).ExtFanType != DataHVACGlobals::FanType_SystemModelObject) {
1854 0 : Fans::SimulateFanComponents(state,
1855 0 : OutAirUnit(OAUnitNum).ExtFanName,
1856 : FirstHVACIteration,
1857 0 : OutAirUnit(OAUnitNum).ExtFan_Index,
1858 : _,
1859 : ZoneCompTurnFansOn,
1860 : ZoneCompTurnFansOff);
1861 : } else {
1862 1282 : state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).ExtFan_Index]->simulate(
1863 : state, _, ZoneCompTurnFansOn, ZoneCompTurnFansOff, _);
1864 : }
1865 : }
1866 : }
1867 :
1868 : } else { // System On
1869 :
1870 : // Flowrate Check
1871 64772 : if (state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate > 0.0) {
1872 64772 : state.dataLoopNodes->Node(OutsideAirNode).MassFlowRate = OutAirUnit(OAUnitNum).OutAirMassFlow;
1873 : }
1874 :
1875 : // Fan Positioning Check
1876 :
1877 64772 : if (OutAirUnit(OAUnitNum).ExtFan) {
1878 64772 : state.dataLoopNodes->Node(InletNode).MassFlowRate = OutAirUnit(OAUnitNum).ExtAirMassFlow;
1879 : }
1880 :
1881 : // Air mass balance check
1882 64772 : if ((std::abs(OutAirUnit(OAUnitNum).ExtAirMassFlow - OutAirUnit(OAUnitNum).OutAirMassFlow) > 0.001) &&
1883 0 : (!state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance)) {
1884 0 : if (!OutAirUnit(OAUnitNum).FlowError) {
1885 0 : ShowWarningError(state, "Air mass flow between zone supply and exhaust is not balanced. Only the first occurrence is reported.");
1886 0 : ShowContinueError(state, "Occurs in ZoneHVAC:OutdoorAirUnit Object= " + OutAirUnit(OAUnitNum).Name);
1887 0 : ShowContinueError(state,
1888 : "Air mass balance is required by other outdoor air units: Fan:ZoneExhaust, ZoneMixing, ZoneCrossMixing, or "
1889 : "other air flow control inputs.");
1890 0 : ShowContinueErrorTimeStamp(state,
1891 0 : format("The outdoor mass flow rate = {:.3R} and the exhaust mass flow rate = {:.3R}.",
1892 0 : OutAirUnit(OAUnitNum).OutAirMassFlow,
1893 0 : OutAirUnit(OAUnitNum).ExtAirMassFlow));
1894 0 : OutAirUnit(OAUnitNum).FlowError = true;
1895 : }
1896 : }
1897 :
1898 64772 : if (OutAirUnit(OAUnitNum).FanPlace == BlowThru) {
1899 33027 : if (OutAirUnit(OAUnitNum).SFanType != DataHVACGlobals::FanType_SystemModelObject) {
1900 50103 : Fans::SimulateFanComponents(state,
1901 16701 : OutAirUnit(OAUnitNum).SFanName,
1902 : FirstHVACIteration,
1903 16701 : OutAirUnit(OAUnitNum).SFan_Index,
1904 : _,
1905 : ZoneCompTurnFansOn,
1906 : ZoneCompTurnFansOff);
1907 : } else {
1908 16326 : state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).SFan_Index]->simulate(state, _, ZoneCompTurnFansOn, ZoneCompTurnFansOff, _);
1909 : }
1910 33027 : DesOATemp = state.dataLoopNodes->Node(SFanOutletNode).Temp;
1911 31745 : } else if (OutAirUnit(OAUnitNum).FanPlace == DrawThru) {
1912 31745 : DesOATemp = state.dataLoopNodes->Node(OutsideAirNode).Temp;
1913 : }
1914 :
1915 : // Control type check
1916 64772 : switch (UnitControlType) {
1917 31745 : case OAUnitCtrlType::Neutral: {
1918 31745 : SetPointTemp = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
1919 : // Neutral Control Condition
1920 31745 : if (DesOATemp == SetPointTemp) {
1921 0 : OutAirUnit(OAUnitNum).OperatingMode = Operation::NeutralMode;
1922 0 : AirOutletTemp = DesOATemp;
1923 0 : OutAirUnit(OAUnitNum).CompOutSetTemp = DesOATemp;
1924 0 : SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
1925 : } else {
1926 31745 : if (DesOATemp < SetPointTemp) { // Heating MODE
1927 17054 : OutAirUnit(OAUnitNum).OperatingMode = Operation::HeatingMode;
1928 17054 : AirOutletTemp = SetPointTemp;
1929 17054 : OutAirUnit(OAUnitNum).CompOutSetTemp = AirOutletTemp;
1930 17054 : SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
1931 14691 : } else if (DesOATemp > SetPointTemp) { // Cooling Mode
1932 14691 : OutAirUnit(OAUnitNum).OperatingMode = Operation::CoolingMode;
1933 14691 : AirOutletTemp = SetPointTemp;
1934 14691 : OutAirUnit(OAUnitNum).CompOutSetTemp = AirOutletTemp;
1935 14691 : SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
1936 : }
1937 : }
1938 : // SetPoint Temperature Condition
1939 31745 : } break;
1940 33027 : case OAUnitCtrlType::Temperature: {
1941 33027 : SetPointTemp = DesOATemp;
1942 33027 : HiCtrlTemp = GetCurrentScheduleValue(state, OutAirUnit(OAUnitNum).HiCtrlTempSchedPtr);
1943 33027 : LoCtrlTemp = GetCurrentScheduleValue(state, OutAirUnit(OAUnitNum).LoCtrlTempSchedPtr);
1944 33027 : if ((DesOATemp <= HiCtrlTemp) && (DesOATemp >= LoCtrlTemp)) {
1945 0 : OutAirUnit(OAUnitNum).OperatingMode = Operation::NeutralMode;
1946 0 : AirOutletTemp = DesOATemp;
1947 0 : OutAirUnit(OAUnitNum).CompOutSetTemp = DesOATemp;
1948 0 : SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
1949 : } else {
1950 33027 : if (SetPointTemp < LoCtrlTemp) {
1951 13437 : OutAirUnit(OAUnitNum).OperatingMode = Operation::HeatingMode;
1952 13437 : AirOutletTemp = LoCtrlTemp;
1953 13437 : OutAirUnit(OAUnitNum).CompOutSetTemp = AirOutletTemp;
1954 13437 : SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
1955 19590 : } else if (SetPointTemp > HiCtrlTemp) {
1956 19590 : OutAirUnit(OAUnitNum).OperatingMode = Operation::CoolingMode;
1957 19590 : AirOutletTemp = HiCtrlTemp;
1958 19590 : OutAirUnit(OAUnitNum).CompOutSetTemp = AirOutletTemp;
1959 19590 : SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
1960 : }
1961 : }
1962 33027 : } break;
1963 0 : default:
1964 0 : break;
1965 : }
1966 :
1967 : // Fan positioning
1968 64772 : if (OutAirUnit(OAUnitNum).FanPlace == DrawThru) {
1969 31745 : if (OutAirUnit(OAUnitNum).SFanType != DataHVACGlobals::FanType_SystemModelObject) {
1970 50103 : Fans::SimulateFanComponents(state,
1971 16701 : OutAirUnit(OAUnitNum).SFanName,
1972 : FirstHVACIteration,
1973 16701 : OutAirUnit(OAUnitNum).SFan_Index,
1974 : _,
1975 : ZoneCompTurnFansOn,
1976 : ZoneCompTurnFansOff);
1977 : } else {
1978 15044 : state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).SFan_Index]->simulate(state, _, ZoneCompTurnFansOn, ZoneCompTurnFansOff, _);
1979 : }
1980 :
1981 31745 : OutAirUnit(OAUnitNum).FanEffect = true; // RE-Simulation to take over the supply fan effect
1982 31745 : OutAirUnit(OAUnitNum).FanCorTemp = (state.dataLoopNodes->Node(OutletNode).Temp - OutAirUnit(OAUnitNum).CompOutSetTemp);
1983 31745 : SimZoneOutAirUnitComps(state, OAUnitNum, FirstHVACIteration);
1984 31745 : if (OutAirUnit(OAUnitNum).SFanType != DataHVACGlobals::FanType_SystemModelObject) {
1985 50103 : Fans::SimulateFanComponents(state,
1986 16701 : OutAirUnit(OAUnitNum).SFanName,
1987 : FirstHVACIteration,
1988 16701 : OutAirUnit(OAUnitNum).SFan_Index,
1989 : _,
1990 : ZoneCompTurnFansOn,
1991 : ZoneCompTurnFansOff);
1992 : } else {
1993 15044 : state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).SFan_Index]->simulate(state, _, ZoneCompTurnFansOn, ZoneCompTurnFansOff, _);
1994 : }
1995 31745 : OutAirUnit(OAUnitNum).FanEffect = false;
1996 : }
1997 64772 : if (OutAirUnit(OAUnitNum).ExtFan) {
1998 64772 : if (OutAirUnit(OAUnitNum).ExtFanType != DataHVACGlobals::FanType_SystemModelObject) {
1999 100206 : Fans::SimulateFanComponents(state,
2000 33402 : OutAirUnit(OAUnitNum).ExtFanName,
2001 : FirstHVACIteration,
2002 33402 : OutAirUnit(OAUnitNum).ExtFan_Index,
2003 : _,
2004 : ZoneCompTurnFansOn,
2005 : ZoneCompTurnFansOff);
2006 : } else {
2007 31370 : state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).ExtFan_Index]->simulate(state, _, ZoneCompTurnFansOn, ZoneCompTurnFansOff, _);
2008 : }
2009 : }
2010 : } // ...end of system ON/OFF IF-THEN block
2011 :
2012 66054 : AirMassFlow = state.dataLoopNodes->Node(OutletNode).MassFlowRate;
2013 66054 : MinHumRat = min(state.dataLoopNodes->Node(OutletNode).HumRat, state.dataLoopNodes->Node(OutAirUnit(OAUnitNum).ZoneNodeNum).HumRat);
2014 :
2015 66054 : AirInEnt = PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, MinHumRat); // zone supply air node enthalpy
2016 66054 : ZoneAirEnt = PsyHFnTdbW(state.dataLoopNodes->Node(OutAirUnit(OAUnitNum).ZoneNodeNum).Temp, MinHumRat); // zone air enthalpy
2017 66054 : QUnitOut = AirMassFlow * (AirInEnt - ZoneAirEnt); // Senscooling
2018 :
2019 : // CR9155 Remove specific humidity calculations
2020 66054 : SpecHumOut = state.dataLoopNodes->Node(OutletNode).HumRat;
2021 66054 : SpecHumIn = state.dataLoopNodes->Node(OutAirUnit(OAUnitNum).ZoneNodeNum).HumRat;
2022 66054 : LatentOutput = AirMassFlow * (SpecHumOut - SpecHumIn); // Latent rate (kg/s), dehumid = negative
2023 :
2024 66054 : ZoneAirEnt = PsyHFnTdbW(state.dataLoopNodes->Node(OutAirUnit(OAUnitNum).ZoneNodeNum).Temp,
2025 66054 : state.dataLoopNodes->Node(OutAirUnit(OAUnitNum).ZoneNodeNum).HumRat);
2026 :
2027 66054 : ZoneSupAirEnt = PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(OutletNode).HumRat);
2028 66054 : QTotUnitOut = AirMassFlow * (ZoneSupAirEnt - ZoneAirEnt);
2029 66054 : LatLoadMet = QTotUnitOut - QUnitOut; // watts
2030 :
2031 : // Report variables...
2032 :
2033 66054 : if (QUnitOut < 0.0) {
2034 44827 : OutAirUnit(OAUnitNum).SensCoolingRate = std::abs(QUnitOut);
2035 44827 : OutAirUnit(OAUnitNum).SensHeatingRate = 0.0;
2036 : } else {
2037 21227 : OutAirUnit(OAUnitNum).SensCoolingRate = 0.0;
2038 21227 : OutAirUnit(OAUnitNum).SensHeatingRate = QUnitOut;
2039 : }
2040 :
2041 66054 : if (QTotUnitOut < 0.0) {
2042 51391 : OutAirUnit(OAUnitNum).TotCoolingRate = std::abs(QTotUnitOut);
2043 51391 : OutAirUnit(OAUnitNum).TotHeatingRate = 0.0;
2044 : } else {
2045 14663 : OutAirUnit(OAUnitNum).TotCoolingRate = 0.0;
2046 14663 : OutAirUnit(OAUnitNum).TotHeatingRate = QTotUnitOut;
2047 : }
2048 :
2049 66054 : if (LatLoadMet < 0.0) {
2050 46168 : OutAirUnit(OAUnitNum).LatCoolingRate = std::abs(LatLoadMet);
2051 46168 : OutAirUnit(OAUnitNum).LatHeatingRate = 0.0;
2052 : } else {
2053 19886 : OutAirUnit(OAUnitNum).LatCoolingRate = 0.0;
2054 19886 : OutAirUnit(OAUnitNum).LatHeatingRate = LatLoadMet;
2055 : }
2056 :
2057 : // OutAirUnit( OAUnitNum ).ElecFanRate = FanElecPower; //Issue #5524 this would only get the last fan called, not both if there are two
2058 66054 : OutAirUnit(OAUnitNum).ElecFanRate = 0.0;
2059 66054 : if (OutAirUnit(OAUnitNum).SFanType != DataHVACGlobals::FanType_SystemModelObject) {
2060 33402 : OutAirUnit(OAUnitNum).ElecFanRate += Fans::GetFanPower(state, OutAirUnit(OAUnitNum).SFan_Index);
2061 : } else {
2062 32652 : OutAirUnit(OAUnitNum).ElecFanRate += state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).SFan_Index]->fanPower();
2063 : }
2064 66054 : if (OutAirUnit(OAUnitNum).ExtFan) {
2065 66054 : if (OutAirUnit(OAUnitNum).ExtFanType != DataHVACGlobals::FanType_SystemModelObject) {
2066 33402 : OutAirUnit(OAUnitNum).ElecFanRate += Fans::GetFanPower(state, OutAirUnit(OAUnitNum).ExtFan_Index);
2067 : } else {
2068 32652 : OutAirUnit(OAUnitNum).ElecFanRate += state.dataHVACFan->fanObjs[OutAirUnit(OAUnitNum).ExtFan_Index]->fanPower();
2069 : }
2070 : }
2071 :
2072 66054 : PowerMet = QUnitOut;
2073 66054 : LatOutputProvided = LatentOutput;
2074 66054 : }
2075 :
2076 97799 : void SimZoneOutAirUnitComps(EnergyPlusData &state, int const OAUnitNum, bool const FirstHVACIteration)
2077 : {
2078 :
2079 : // SUBROUTINE INFORMATION:
2080 : // AUTHOR Fred Buhl
2081 : // DATE WRITTEN Oct 1998
2082 : // MODIFIED na
2083 : // RE-ENGINEERED na
2084 :
2085 : // PURPOSE OF THIS SUBROUTINE
2086 : // Simulate the controllers and components in the outside air system.
2087 :
2088 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2089 : int EquipNum;
2090 : int CurOAUnitNum;
2091 195598 : std::string EquipType;
2092 195598 : std::string EquipName;
2093 : bool FatalErrorFlag;
2094 : bool Sim;
2095 :
2096 97799 : FatalErrorFlag = false;
2097 97799 : CurOAUnitNum = OAUnitNum;
2098 97799 : Sim = true;
2099 97799 : auto &OutAirUnit(state.dataOutdoorAirUnit->OutAirUnit);
2100 402330 : for (EquipNum = 1; EquipNum <= OutAirUnit(OAUnitNum).NumComponents; ++EquipNum) {
2101 304531 : EquipName = OutAirUnit(OAUnitNum).OAEquip(EquipNum).ComponentName;
2102 1218124 : SimOutdoorAirEquipComps(state,
2103 : OAUnitNum,
2104 304531 : CompTypeNames[static_cast<int>(OutAirUnit(OAUnitNum).OAEquip(EquipNum).Type)],
2105 : EquipName,
2106 : EquipNum,
2107 304531 : OutAirUnit(OAUnitNum).OAEquip(EquipNum).Type,
2108 : FirstHVACIteration,
2109 304531 : OutAirUnit(OAUnitNum).OAEquip(EquipNum).ComponentIndex,
2110 : Sim);
2111 : }
2112 :
2113 97799 : CurOAUnitNum = 0;
2114 97799 : }
2115 :
2116 304531 : void SimOutdoorAirEquipComps(EnergyPlusData &state,
2117 : int const OAUnitNum, // actual outdoor air unit num
2118 : std::string_view EquipType, // the component type
2119 : std::string const &EquipName, // the component Name
2120 : int const EquipNum,
2121 : [[maybe_unused]] CompType const CompTypeNum, // Component Type -- Integerized for this module
2122 : bool const FirstHVACIteration,
2123 : int &CompIndex,
2124 : bool const Sim // if TRUE, simulate component
2125 : )
2126 : {
2127 :
2128 : // SUBROUTINE INFORMATION:
2129 : // AUTHOR Young Tae Chae, Rick Strand
2130 : // DATE WRITTEN June 2008
2131 : // MODIFIED
2132 : // RE-ENGINEERED na
2133 :
2134 : // PURPOSE OF THIS SUBROUTINE:
2135 : // Outdoor air unit has various coil options. This subroutine defines the coil loads and execute
2136 : // to simulate each components
2137 : // METHODOLOGY EMPLOYED:
2138 :
2139 : // REFERENCES:
2140 :
2141 : // USE STATEMENTS:
2142 :
2143 : // Using/Aliasing
2144 : using DataHVACGlobals::SmallLoad;
2145 : using DesiccantDehumidifiers::SimDesiccantDehumidifier;
2146 : using HeatRecovery::SimHeatRecovery;
2147 : using HVACDXHeatPumpSystem::SimDXHeatPumpSystem;
2148 : using HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil;
2149 : using ScheduleManager::GetCurrentScheduleValue;
2150 : using WaterCoils::SimulateWaterCoilComponents;
2151 :
2152 : // SUBROUTINE LOCAL VARIABLE DEFINITIONS
2153 : Real64 OAMassFlow;
2154 : Real64 QCompReq;
2155 : int UnitNum;
2156 : Real64 MaxWaterFlow;
2157 : Real64 MinWaterFlow;
2158 : int ControlNode;
2159 : Real64 CpAirZn;
2160 : int SimCompNum;
2161 : CompType EquipTypeNum;
2162 : int WCCoilInletNode;
2163 : int WCCoilOutletNode;
2164 : int WHCoilInletNode;
2165 : int WHCoilOutletNode;
2166 : Real64 QUnitOut;
2167 304531 : int DXSystemIndex(0);
2168 : Real64 CompAirOutTemp;
2169 : Real64 FanEffect;
2170 : bool DrawFan; // fan position If .True., the temperature increasing by fan operating is considered
2171 : Real64 Dxsystemouttemp;
2172 304531 : auto &HeatActive = state.dataOutdoorAirUnit->HeatActive;
2173 304531 : auto &CoolActive = state.dataOutdoorAirUnit->CoolActive;
2174 :
2175 304531 : auto &OutAirUnit(state.dataOutdoorAirUnit->OutAirUnit);
2176 :
2177 304531 : UnitNum = OAUnitNum;
2178 304531 : CompAirOutTemp = OutAirUnit(OAUnitNum).CompOutSetTemp;
2179 304531 : Operation OpMode = OutAirUnit(OAUnitNum).OperatingMode;
2180 304531 : SimCompNum = EquipNum;
2181 304531 : EquipTypeNum = OutAirUnit(OAUnitNum).OAEquip(SimCompNum).Type;
2182 304531 : OAMassFlow = OutAirUnit(OAUnitNum).OutAirMassFlow;
2183 304531 : DrawFan = OutAirUnit(OAUnitNum).FanEffect;
2184 304531 : DXSystemIndex = 0;
2185 :
2186 : // check the fan positioning
2187 304531 : if (DrawFan) {
2188 89793 : FanEffect = OutAirUnit(OAUnitNum).FanCorTemp; // Heat effect by fan
2189 : } else {
2190 214738 : FanEffect = 0.0;
2191 : }
2192 :
2193 : // checking equipment index
2194 :
2195 : {
2196 304531 : switch (EquipTypeNum) {
2197 : // Heat recovery
2198 75781 : case CompType::HeatXchngrFP: // 'HeatExchanger:AirToAir:FlatPlate',
2199 : case CompType::HeatXchngrSL: // 'HeatExchanger:AirToAir:SensibleAndLatent',
2200 : // 'HeatExchanger:Desiccant:BalancedFlow' - unused
2201 : {
2202 :
2203 75781 : if (Sim) {
2204 75781 : SimHeatRecovery(state, EquipName, FirstHVACIteration, CompIndex, ContFanCycCoil, _, _, _, _, false, false);
2205 : }
2206 75781 : } break;
2207 : // Desiccant Dehumidifier
2208 11009 : case CompType::Desiccant: { // 'Dehumidifier:Desiccant:NoFans'
2209 11009 : if (Sim) {
2210 11009 : SimDesiccantDehumidifier(state, EquipName, FirstHVACIteration, CompIndex);
2211 : }
2212 :
2213 11009 : } break;
2214 53763 : case CompType::WaterCoil_SimpleHeat: { // ('Coil:Heating:Water')
2215 :
2216 53763 : if (Sim) {
2217 53763 : ControlNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilWaterInletNode;
2218 53763 : MaxWaterFlow = OutAirUnit(OAUnitNum).OAEquip(EquipNum).MaxWaterMassFlow;
2219 53763 : MinWaterFlow = OutAirUnit(OAUnitNum).OAEquip(EquipNum).MinWaterMassFlow;
2220 : // On the first HVAC iteration the system values are given to the controller, but after that
2221 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
2222 53763 : if ((!FirstHVACIteration) && (ControlNode > 0)) {
2223 27939 : MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
2224 27939 : MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
2225 : }
2226 53763 : WHCoilInletNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilAirInletNode;
2227 53763 : WHCoilOutletNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilAirOutletNode;
2228 :
2229 53763 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(WHCoilInletNode).HumRat);
2230 :
2231 81820 : if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::CoolingMode) ||
2232 28057 : (state.dataLoopNodes->Node(WHCoilInletNode).Temp > CompAirOutTemp)) {
2233 25746 : QCompReq = 0.0;
2234 : } else {
2235 28017 : QCompReq = CpAirZn * OAMassFlow * ((CompAirOutTemp - state.dataLoopNodes->Node(WHCoilInletNode).Temp) - FanEffect);
2236 28017 : if (std::abs(QCompReq) < SmallLoad) QCompReq = 0.0;
2237 28017 : if (QCompReq < 0.0) QCompReq = 0.0; // coil can heat only
2238 : }
2239 :
2240 322578 : ControlCompOutput(state,
2241 53763 : OutAirUnit(OAUnitNum).Name,
2242 107526 : std::string(ZoneHVACOAUnit),
2243 : UnitNum,
2244 : FirstHVACIteration,
2245 : QCompReq,
2246 : ControlNode,
2247 : MaxWaterFlow,
2248 : MinWaterFlow,
2249 : 0.0001,
2250 53763 : OutAirUnit(OAUnitNum).ControlCompTypeNum,
2251 53763 : OutAirUnit(OAUnitNum).CompErrIndex,
2252 : _,
2253 : _,
2254 : _,
2255 : 2,
2256 : SimCompNum,
2257 53763 : OutAirUnit(OAUnitNum).OAEquip(EquipNum).plantLoc);
2258 : }
2259 53763 : } break;
2260 0 : case CompType::SteamCoil_AirHeat: { // 'Coil:Heating:Steam'
2261 0 : if (Sim) {
2262 0 : CalcOAUnitCoilComps(state, UnitNum, FirstHVACIteration, SimCompNum, QUnitOut);
2263 : }
2264 0 : } break;
2265 44036 : case CompType::Coil_ElectricHeat: // 'Coil:Heating:Electric'
2266 : case CompType::Coil_GasHeat: { // 'Coil:Heating:Fuel'
2267 44036 : if (Sim) {
2268 : // stand-alone coils are temperature controlled (do not pass QCoilReq in argument list, QCoilReq overrides temp SP)
2269 44036 : CalcOAUnitCoilComps(state, UnitNum, FirstHVACIteration, SimCompNum, QUnitOut);
2270 : }
2271 44036 : } break;
2272 : // water cooling coil Types
2273 33027 : case CompType::WaterCoil_Cooling: { // 'Coil:Cooling:Water'
2274 33027 : if (Sim) {
2275 33027 : ControlNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilWaterInletNode;
2276 33027 : MaxWaterFlow = OutAirUnit(OAUnitNum).OAEquip(EquipNum).MaxWaterMassFlow;
2277 33027 : MinWaterFlow = OutAirUnit(OAUnitNum).OAEquip(EquipNum).MinWaterMassFlow;
2278 : // On the first HVAC iteration the system values are given to the controller, but after that
2279 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
2280 33027 : if ((!FirstHVACIteration) && (ControlNode > 0)) {
2281 17148 : MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
2282 17148 : MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
2283 : }
2284 33027 : WCCoilInletNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilAirInletNode;
2285 33027 : WCCoilOutletNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilAirOutletNode;
2286 :
2287 33027 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(WCCoilInletNode).HumRat);
2288 33027 : OAMassFlow = OutAirUnit(OAUnitNum).OutAirMassFlow;
2289 50605 : if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::HeatingMode) ||
2290 17578 : (state.dataLoopNodes->Node(WCCoilInletNode).Temp < CompAirOutTemp)) {
2291 18919 : QCompReq = 0.0;
2292 18919 : state.dataLoopNodes->Node(WCCoilOutletNode).Temp = state.dataLoopNodes->Node(WCCoilInletNode).Temp;
2293 18919 : state.dataLoopNodes->Node(WCCoilOutletNode).HumRat = state.dataLoopNodes->Node(WCCoilInletNode).HumRat;
2294 18919 : state.dataLoopNodes->Node(WCCoilOutletNode).MassFlowRate = state.dataLoopNodes->Node(WCCoilInletNode).MassFlowRate;
2295 :
2296 : } else {
2297 :
2298 14108 : QCompReq = CpAirZn * OAMassFlow * ((CompAirOutTemp - state.dataLoopNodes->Node(WCCoilInletNode).Temp) - FanEffect);
2299 14108 : if (std::abs(QCompReq) < SmallLoad) QCompReq = 0.0;
2300 14108 : if (QCompReq > 0.0) QCompReq = 0.0; // coil can cool only
2301 : }
2302 :
2303 198162 : ControlCompOutput(state,
2304 33027 : OutAirUnit(OAUnitNum).Name,
2305 66054 : std::string(ZoneHVACOAUnit),
2306 : UnitNum,
2307 : FirstHVACIteration,
2308 : QCompReq,
2309 : ControlNode,
2310 : MaxWaterFlow,
2311 : MinWaterFlow,
2312 : 0.001,
2313 33027 : OutAirUnit(OAUnitNum).ControlCompTypeNum,
2314 33027 : OutAirUnit(OAUnitNum).CompErrIndex,
2315 : _,
2316 : _,
2317 : _,
2318 : 1,
2319 : SimCompNum,
2320 33027 : OutAirUnit(OAUnitNum).OAEquip(EquipNum).plantLoc);
2321 : }
2322 33027 : } break;
2323 0 : case CompType::WaterCoil_DetailedCool: { // 'Coil:Cooling:Water:DetailedGeometry'
2324 0 : if (Sim) {
2325 0 : ControlNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilWaterInletNode;
2326 0 : MaxWaterFlow = OutAirUnit(OAUnitNum).OAEquip(EquipNum).MaxWaterMassFlow;
2327 0 : MinWaterFlow = OutAirUnit(OAUnitNum).OAEquip(EquipNum).MinWaterMassFlow;
2328 : // On the first HVAC iteration the system values are given to the controller, but after that
2329 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
2330 0 : if ((!FirstHVACIteration) && (ControlNode > 0)) {
2331 0 : MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
2332 0 : MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
2333 : }
2334 0 : WCCoilInletNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilAirInletNode;
2335 0 : WCCoilOutletNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilAirOutletNode;
2336 :
2337 0 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(WCCoilInletNode).HumRat);
2338 0 : OAMassFlow = OutAirUnit(OAUnitNum).OutAirMassFlow;
2339 :
2340 0 : if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::HeatingMode) ||
2341 0 : (state.dataLoopNodes->Node(WCCoilInletNode).Temp < CompAirOutTemp)) {
2342 0 : QCompReq = 0.0;
2343 : } else {
2344 :
2345 0 : QCompReq = CpAirZn * OAMassFlow * ((CompAirOutTemp - state.dataLoopNodes->Node(WCCoilInletNode).Temp) - FanEffect);
2346 0 : if (std::abs(QCompReq) < SmallLoad) QCompReq = 0.0;
2347 0 : if (QCompReq > 0.0) QCompReq = 0.0; // coil can cool only
2348 : }
2349 :
2350 0 : ControlCompOutput(state,
2351 0 : OutAirUnit(OAUnitNum).Name,
2352 : "ZONEHVAC:OUTDOORAIRUNIT",
2353 : UnitNum,
2354 : FirstHVACIteration,
2355 : QCompReq,
2356 : ControlNode,
2357 : MaxWaterFlow,
2358 : MinWaterFlow,
2359 : 0.001,
2360 0 : OutAirUnit(OAUnitNum).ControlCompTypeNum,
2361 0 : OutAirUnit(OAUnitNum).CompErrIndex,
2362 : _,
2363 : _,
2364 : _,
2365 : 1,
2366 : SimCompNum,
2367 0 : OutAirUnit(OAUnitNum).OAEquip(EquipNum).plantLoc);
2368 : }
2369 0 : } break;
2370 0 : case CompType::WaterCoil_CoolingHXAsst: { // 'CoilSystem:Cooling:Water:HeatExchangerAssisted'
2371 0 : if (Sim) {
2372 0 : ControlNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilWaterInletNode;
2373 0 : MaxWaterFlow = OutAirUnit(OAUnitNum).OAEquip(EquipNum).MaxWaterMassFlow;
2374 0 : MinWaterFlow = 0.0;
2375 : // On the first HVAC iteration the system values are given to the controller, but after that
2376 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
2377 0 : if ((!FirstHVACIteration) && (ControlNode > 0)) {
2378 0 : MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
2379 0 : MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
2380 : }
2381 0 : WCCoilInletNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilAirInletNode;
2382 0 : WCCoilOutletNode = OutAirUnit(OAUnitNum).OAEquip(EquipNum).CoilAirOutletNode;
2383 0 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(WCCoilInletNode).HumRat);
2384 0 : OAMassFlow = OutAirUnit(OAUnitNum).OutAirMassFlow;
2385 0 : if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::HeatingMode) ||
2386 0 : (state.dataLoopNodes->Node(WCCoilInletNode).Temp < CompAirOutTemp)) {
2387 0 : QCompReq = 0.0;
2388 : } else {
2389 0 : QCompReq = CpAirZn * OAMassFlow * ((CompAirOutTemp - state.dataLoopNodes->Node(WCCoilInletNode).Temp) - FanEffect);
2390 0 : if (std::abs(QCompReq) < SmallLoad) QCompReq = 0.0;
2391 0 : if (QCompReq > 0.0) QCompReq = 0.0; // coil can cool only
2392 : }
2393 0 : ControlCompOutput(state,
2394 0 : OutAirUnit(OAUnitNum).Name,
2395 : "ZONEHVAC:OUTDOORAIRUNIT",
2396 : UnitNum,
2397 : FirstHVACIteration,
2398 : QCompReq,
2399 : ControlNode,
2400 : MaxWaterFlow,
2401 : MinWaterFlow,
2402 : 0.001,
2403 0 : OutAirUnit(OAUnitNum).ControlCompTypeNum,
2404 0 : OutAirUnit(OAUnitNum).CompErrIndex,
2405 : _,
2406 : _,
2407 : _,
2408 : 1,
2409 : SimCompNum,
2410 0 : OutAirUnit(OAUnitNum).OAEquip(EquipNum).plantLoc);
2411 : }
2412 0 : } break;
2413 75781 : case CompType::DXSystem: { // CoilSystem:Cooling:DX old 'CompType:UnitaryCoolOnly'
2414 75781 : if (Sim) {
2415 75781 : if (OutAirUnit(OAUnitNum).OAEquip(SimCompNum).compPointer == nullptr) {
2416 16 : UnitarySystems::UnitarySys thisSys;
2417 8 : OutAirUnit(OAUnitNum).OAEquip(SimCompNum).compPointer =
2418 16 : thisSys.factory(state,
2419 : DataHVACGlobals::UnitarySys_AnyCoilType,
2420 8 : OutAirUnit(OAUnitNum).OAEquip(SimCompNum).ComponentName,
2421 : false,
2422 : OAUnitNum);
2423 8 : UnitarySystems::UnitarySys::checkUnitarySysCoilInOASysExists(
2424 8 : state, OutAirUnit(OAUnitNum).OAEquip(SimCompNum).ComponentName, OAUnitNum);
2425 : }
2426 75781 : if (((OpMode == Operation::NeutralMode) && (OutAirUnit(OAUnitNum).controlType == OAUnitCtrlType::Temperature)) ||
2427 : (OpMode == Operation::HeatingMode)) {
2428 35003 : Dxsystemouttemp = 100.0; // There is no cooling demand for the DX system.
2429 : } else {
2430 40778 : Dxsystemouttemp = CompAirOutTemp - FanEffect;
2431 : }
2432 75781 : Real64 sensOut = 0.0;
2433 75781 : Real64 latOut = 0.0;
2434 75781 : OutAirUnit(OAUnitNum)
2435 75781 : .OAEquip(SimCompNum)
2436 151562 : .compPointer->simulate(state,
2437 : EquipName,
2438 : FirstHVACIteration,
2439 : -1,
2440 : DXSystemIndex,
2441 : HeatActive,
2442 : CoolActive,
2443 : UnitNum,
2444 : Dxsystemouttemp,
2445 : false,
2446 : sensOut,
2447 75781 : latOut);
2448 : }
2449 75781 : } break;
2450 11134 : case CompType::DXHeatPumpSystem: {
2451 11134 : if (Sim) {
2452 11134 : if (((OpMode == Operation::NeutralMode) && (OutAirUnit(OAUnitNum).controlType == OAUnitCtrlType::Temperature)) ||
2453 : (OpMode == Operation::CoolingMode)) {
2454 6506 : Dxsystemouttemp = -20.0; // There is no heating demand for the DX system.
2455 : } else {
2456 4628 : Dxsystemouttemp = CompAirOutTemp - FanEffect;
2457 : }
2458 11134 : SimDXHeatPumpSystem(state, EquipName, FirstHVACIteration, -1, DXSystemIndex, UnitNum, Dxsystemouttemp);
2459 : }
2460 11134 : } break;
2461 : // RAR need new CompType:UnitarySystem object here
2462 0 : case CompType::UnitarySystemModel: { // 'CompType:UnitarySystem'
2463 0 : if (Sim) {
2464 : // This may have to be done in the unitary system object since there can be both cooling and heating
2465 0 : if (((OpMode == Operation::NeutralMode) && (OutAirUnit(OAUnitNum).controlType == OAUnitCtrlType::Temperature)) &&
2466 : (OpMode == Operation::HeatingMode)) {
2467 0 : Dxsystemouttemp = 100.0; // There is no cooling demand.
2468 0 : } else if (((OpMode == Operation::NeutralMode) && (OutAirUnit(OAUnitNum).controlType == OAUnitCtrlType::Temperature)) &&
2469 : (OpMode == Operation::CoolingMode)) {
2470 0 : Dxsystemouttemp = -20.0; // There is no heating demand.
2471 : } else {
2472 0 : Dxsystemouttemp = CompAirOutTemp - FanEffect;
2473 : }
2474 0 : Real64 sensOut = 0.0;
2475 0 : Real64 latOut = 0.0;
2476 0 : OutAirUnit(OAUnitNum)
2477 0 : .OAEquip(SimCompNum)
2478 0 : .compPointer->simulate(state,
2479 : EquipName,
2480 : FirstHVACIteration,
2481 : -1,
2482 : DXSystemIndex,
2483 : HeatActive,
2484 : CoolActive,
2485 : UnitNum,
2486 : Dxsystemouttemp,
2487 : false,
2488 : sensOut,
2489 0 : latOut);
2490 : }
2491 0 : } break;
2492 0 : default: {
2493 0 : ShowFatalError(state, format("Invalid Outdoor Air Unit Component={}", EquipType)); // validate
2494 0 : } break;
2495 : }
2496 : }
2497 304531 : }
2498 :
2499 808831 : void CalcOAUnitCoilComps(EnergyPlusData &state,
2500 : int const CompNum, // actual outdoor air unit num
2501 : bool const FirstHVACIteration,
2502 : int const EquipIndex, // Component Type -- Integerized for this module
2503 : Real64 &LoadMet)
2504 : {
2505 :
2506 : // SUBROUTINE INFORMATION:
2507 : // AUTHOR Young Tae Chae, Rick Strand
2508 : // DATE WRITTEN June 2009
2509 : // MODIFIED
2510 : // RE-ENGINEERED na
2511 :
2512 : // PURPOSE OF THIS SUBROUTINE:
2513 : // This subroutine mainly controls the action of water components in the unit
2514 :
2515 : // METHODOLOGY EMPLOYED:
2516 :
2517 : // REFERENCES:
2518 :
2519 : // USE STATEMENTS:
2520 :
2521 : // Using/Aliasing
2522 : using DataHVACGlobals::SmallLoad;
2523 : using HVACHXAssistedCoolingCoil::SimHXAssistedCoolingCoil;
2524 : using SteamCoils::SimulateSteamCoilComponents;
2525 : using WaterCoils::SimulateWaterCoilComponents;
2526 :
2527 : // SUBROUTINE ARGUMENT DEFINITIONS:
2528 :
2529 : // Locals
2530 : // SUBROUTINE LOCAL VARIABLE DEFINITIONS
2531 : int OAUnitNum;
2532 : Real64 CpAirZn;
2533 : int CoilIndex;
2534 : Operation OpMode;
2535 : Real64 AirMassFlow;
2536 : Real64 FanEffect;
2537 : bool DrawFan; // Fan Flag
2538 : int InletNode;
2539 : int OutletNode;
2540 : Real64 QCompReq; // Actual equipment load
2541 : CompType CoilTypeNum;
2542 : Real64 CoilAirOutTemp;
2543 : int CompoNum;
2544 :
2545 808831 : auto &OutAirUnit(state.dataOutdoorAirUnit->OutAirUnit);
2546 :
2547 808831 : CoilIndex = 0;
2548 808831 : OAUnitNum = CompNum;
2549 808831 : CompoNum = EquipIndex;
2550 808831 : CoilTypeNum = OutAirUnit(OAUnitNum).OAEquip(CompoNum).Type;
2551 808831 : OpMode = OutAirUnit(OAUnitNum).OperatingMode;
2552 808831 : CoilAirOutTemp = OutAirUnit(OAUnitNum).CompOutSetTemp;
2553 808831 : DrawFan = OutAirUnit(OAUnitNum).FanEffect;
2554 808831 : if (DrawFan) {
2555 207993 : FanEffect = OutAirUnit(OAUnitNum).FanCorTemp;
2556 : } else {
2557 600838 : FanEffect = 0.0;
2558 : }
2559 :
2560 : {
2561 808831 : switch (CoilTypeNum) {
2562 33027 : case CompType::Coil_ElectricHeat: {
2563 33027 : InletNode = OutAirUnit(OAUnitNum).OAEquip(CompoNum).CoilAirInletNode;
2564 33027 : OutletNode = OutAirUnit(OAUnitNum).OAEquip(CompoNum).CoilAirOutletNode;
2565 46464 : if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::CoolingMode) ||
2566 13437 : (state.dataLoopNodes->Node(InletNode).Temp > CoilAirOutTemp)) {
2567 19732 : QCompReq = 0.0;
2568 : } else {
2569 13295 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(InletNode).HumRat);
2570 26590 : QCompReq = state.dataLoopNodes->Node(InletNode).MassFlowRate * CpAirZn *
2571 13295 : ((CoilAirOutTemp - state.dataLoopNodes->Node(InletNode).Temp) - FanEffect);
2572 13295 : if (std::abs(QCompReq) < SmallLoad) QCompReq = 0.0;
2573 : }
2574 :
2575 33027 : if (QCompReq <= 0.0) {
2576 19732 : QCompReq = 0.0; // a heating coil can only heat, not cool
2577 19732 : state.dataLoopNodes->Node(OutletNode).Temp = state.dataLoopNodes->Node(InletNode).Temp;
2578 19732 : state.dataLoopNodes->Node(OutletNode).HumRat = state.dataLoopNodes->Node(InletNode).HumRat;
2579 19732 : state.dataLoopNodes->Node(OutletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
2580 : }
2581 66054 : HeatingCoils::SimulateHeatingCoilComponents(
2582 33027 : state, OutAirUnit(OAUnitNum).OAEquip(CompoNum).ComponentName, FirstHVACIteration, QCompReq, CoilIndex);
2583 :
2584 33027 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
2585 66054 : LoadMet = AirMassFlow * (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat) -
2586 33027 : PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat));
2587 :
2588 33027 : } break;
2589 11009 : case CompType::Coil_GasHeat: { // 'Coil:Heating:Steam'
2590 11009 : InletNode = OutAirUnit(OAUnitNum).OAEquip(CompoNum).CoilAirInletNode;
2591 11009 : OutletNode = OutAirUnit(OAUnitNum).OAEquip(CompoNum).CoilAirOutletNode;
2592 15488 : if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::CoolingMode) ||
2593 4479 : (state.dataLoopNodes->Node(InletNode).Temp > CoilAirOutTemp)) {
2594 6573 : QCompReq = 0.0;
2595 : } else {
2596 4436 : state.dataLoopNodes->Node(OutletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
2597 4436 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(InletNode).HumRat);
2598 8872 : QCompReq = state.dataLoopNodes->Node(InletNode).MassFlowRate * CpAirZn *
2599 4436 : ((CoilAirOutTemp - state.dataLoopNodes->Node(InletNode).Temp) - FanEffect);
2600 4436 : if (std::abs(QCompReq) < SmallLoad) QCompReq = 0.0;
2601 : }
2602 11009 : if (QCompReq <= 0.0) {
2603 6573 : QCompReq = 0.0; // a heating coil can only heat, not cool
2604 6573 : state.dataLoopNodes->Node(OutletNode).Temp = state.dataLoopNodes->Node(InletNode).Temp;
2605 6573 : state.dataLoopNodes->Node(OutletNode).HumRat = state.dataLoopNodes->Node(InletNode).HumRat;
2606 6573 : state.dataLoopNodes->Node(OutletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
2607 : }
2608 22018 : HeatingCoils::SimulateHeatingCoilComponents(
2609 11009 : state, OutAirUnit(OAUnitNum).OAEquip(CompoNum).ComponentName, FirstHVACIteration, QCompReq, CoilIndex);
2610 :
2611 11009 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
2612 22018 : LoadMet = AirMassFlow * (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat) -
2613 11009 : PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat));
2614 :
2615 11009 : } break;
2616 0 : case CompType::SteamCoil_AirHeat: { // 'Coil:Heating:Steam'
2617 0 : InletNode = OutAirUnit(OAUnitNum).OAEquip(CompoNum).CoilAirInletNode;
2618 0 : OutletNode = OutAirUnit(OAUnitNum).OAEquip(CompoNum).CoilAirOutletNode;
2619 0 : if ((OpMode == Operation::NeutralMode) || (OpMode == Operation::CoolingMode) ||
2620 0 : (state.dataLoopNodes->Node(InletNode).Temp > CoilAirOutTemp)) {
2621 0 : QCompReq = 0.0;
2622 : } else {
2623 0 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(InletNode).HumRat);
2624 0 : QCompReq = state.dataLoopNodes->Node(InletNode).MassFlowRate * CpAirZn *
2625 0 : ((CoilAirOutTemp - state.dataLoopNodes->Node(InletNode).Temp) - FanEffect);
2626 0 : if (std::abs(QCompReq) < SmallLoad) QCompReq = 0.0;
2627 : }
2628 0 : if (QCompReq <= 0.0) {
2629 0 : QCompReq = 0.0; // a heating coil can only heat, not cool
2630 0 : state.dataLoopNodes->Node(OutletNode).Temp = state.dataLoopNodes->Node(InletNode).Temp;
2631 0 : state.dataLoopNodes->Node(OutletNode).HumRat = state.dataLoopNodes->Node(InletNode).HumRat;
2632 0 : state.dataLoopNodes->Node(OutletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
2633 : }
2634 0 : SimulateSteamCoilComponents(state, OutAirUnit(OAUnitNum).OAEquip(CompoNum).ComponentName, FirstHVACIteration, CoilIndex, QCompReq);
2635 0 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
2636 0 : LoadMet = AirMassFlow * (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat) -
2637 0 : PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat));
2638 :
2639 0 : } break;
2640 764795 : case CompType::WaterCoil_SimpleHeat: // 'Coil:Heating:Water')
2641 : case CompType::WaterCoil_Cooling: // 'Coil:Cooling:Water'
2642 : case CompType::WaterCoil_DetailedCool: {
2643 764795 : SimulateWaterCoilComponents(state, OutAirUnit(OAUnitNum).OAEquip(CompoNum).ComponentName, FirstHVACIteration, CoilIndex);
2644 764795 : InletNode = OutAirUnit(OAUnitNum).OAEquip(CompoNum).CoilAirInletNode;
2645 764795 : OutletNode = OutAirUnit(OAUnitNum).OAEquip(CompoNum).CoilAirOutletNode;
2646 764795 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
2647 1529590 : LoadMet = AirMassFlow * (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat) -
2648 764795 : PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat));
2649 :
2650 764795 : } break;
2651 0 : case CompType::WaterCoil_CoolingHXAsst: {
2652 0 : SimHXAssistedCoolingCoil(state,
2653 0 : OutAirUnit(OAUnitNum).OAEquip(CompoNum).ComponentName,
2654 : FirstHVACIteration,
2655 : DataHVACGlobals::CompressorOperation::On,
2656 : 0.0,
2657 : CoilIndex,
2658 : ContFanCycCoil);
2659 0 : InletNode = OutAirUnit(OAUnitNum).OAEquip(CompoNum).CoilAirInletNode;
2660 0 : OutletNode = OutAirUnit(OAUnitNum).OAEquip(CompoNum).CoilAirOutletNode;
2661 0 : AirMassFlow = state.dataLoopNodes->Node(InletNode).MassFlowRate;
2662 0 : LoadMet = AirMassFlow * (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat) -
2663 0 : PsyHFnTdbW(state.dataLoopNodes->Node(InletNode).Temp, state.dataLoopNodes->Node(InletNode).HumRat));
2664 0 : } break;
2665 0 : default:
2666 0 : ShowFatalError(state, format("Invalid Coil Type = {}", CoilTypeNum)); // validate
2667 0 : break;
2668 : }
2669 : }
2670 808831 : }
2671 :
2672 : // SUBROUTINE UpdateOutdoorAirUnit
2673 :
2674 : // No update routine needed in this module since all of the updates happen on
2675 : // the Node derived type directly and these updates are done by other routines.
2676 :
2677 : // END SUBROUTINE UpdateOutdoorAirUnit
2678 :
2679 66054 : void ReportOutdoorAirUnit(EnergyPlusData &state,
2680 : int const OAUnitNum) // Index for the outdoor air unit under consideration within the derived types
2681 : {
2682 :
2683 : // SUBROUTINE INFORMATION:
2684 : // AUTHOR Young T. Chae
2685 : // DATE WRITTEN Oct. 2009
2686 : // MODIFIED na
2687 : // RE-ENGINEERED na
2688 :
2689 : // PURPOSE OF THIS SUBROUTINE:
2690 : // This subroutine simply produces output for the outdoor air unit.
2691 : // METHODOLOGY EMPLOYED:
2692 : // Standard EnergyPlus methodology.
2693 :
2694 : // Using/Aliasing
2695 66054 : auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
2696 :
2697 66054 : auto &OutAirUnit(state.dataOutdoorAirUnit->OutAirUnit);
2698 66054 : OutAirUnit(OAUnitNum).TotHeatingEnergy = OutAirUnit(OAUnitNum).TotHeatingRate * TimeStepSys * DataGlobalConstants::SecInHour;
2699 66054 : OutAirUnit(OAUnitNum).SensHeatingEnergy = OutAirUnit(OAUnitNum).SensHeatingRate * TimeStepSys * DataGlobalConstants::SecInHour;
2700 66054 : OutAirUnit(OAUnitNum).LatHeatingEnergy = OutAirUnit(OAUnitNum).LatHeatingRate * TimeStepSys * DataGlobalConstants::SecInHour;
2701 66054 : OutAirUnit(OAUnitNum).SensCoolingEnergy = OutAirUnit(OAUnitNum).SensCoolingRate * TimeStepSys * DataGlobalConstants::SecInHour;
2702 66054 : OutAirUnit(OAUnitNum).LatCoolingEnergy = OutAirUnit(OAUnitNum).LatCoolingRate * TimeStepSys * DataGlobalConstants::SecInHour;
2703 66054 : OutAirUnit(OAUnitNum).TotCoolingEnergy = OutAirUnit(OAUnitNum).TotCoolingRate * TimeStepSys * DataGlobalConstants::SecInHour;
2704 66054 : OutAirUnit(OAUnitNum).AirMassFlow = OutAirUnit(OAUnitNum).OutAirMassFlow;
2705 66054 : OutAirUnit(OAUnitNum).ElecFanEnergy = OutAirUnit(OAUnitNum).ElecFanRate * TimeStepSys * DataGlobalConstants::SecInHour;
2706 :
2707 66054 : if (OutAirUnit(OAUnitNum).FirstPass) { // reset sizing flags so other zone equipment can size normally
2708 12 : if (!state.dataGlobal->SysSizingCalc) {
2709 12 : DataSizing::resetHVACSizingGlobals(state, state.dataSize->CurZoneEqNum, 0, OutAirUnit(OAUnitNum).FirstPass);
2710 : }
2711 : }
2712 66054 : }
2713 :
2714 3522 : int GetOutdoorAirUnitOutAirNode(EnergyPlusData &state, int const OAUnitNum)
2715 : {
2716 :
2717 : // FUNCTION INFORMATION:
2718 : // AUTHOR B Griffith
2719 : // DATE WRITTEN Dec 2006
2720 : // MODIFIED na
2721 : // RE-ENGINEERED na
2722 :
2723 : // PURPOSE OF THIS FUNCTION:
2724 : // lookup function for OA inlet node
2725 :
2726 : // Return value
2727 : int GetOutdoorAirUnitOutAirNode;
2728 :
2729 3522 : if (state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) {
2730 0 : OutdoorAirUnit::GetOutdoorAirUnitInputs(state);
2731 0 : state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false;
2732 : }
2733 :
2734 3522 : GetOutdoorAirUnitOutAirNode = 0;
2735 3522 : if (OAUnitNum > 0 && OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits) {
2736 3522 : GetOutdoorAirUnitOutAirNode = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).OutsideAirNode;
2737 : }
2738 :
2739 3522 : return GetOutdoorAirUnitOutAirNode;
2740 : }
2741 :
2742 3522 : int GetOutdoorAirUnitZoneInletNode(EnergyPlusData &state, int const OAUnitNum)
2743 : {
2744 :
2745 : // FUNCTION INFORMATION:
2746 : // AUTHOR B Griffith
2747 : // DATE WRITTEN Dec 2006
2748 : // MODIFIED na
2749 : // RE-ENGINEERED na
2750 :
2751 : // PURPOSE OF THIS FUNCTION:
2752 : // lookup function for OA inlet node
2753 :
2754 : // Return value
2755 : int GetOutdoorAirUnitZoneInletNode;
2756 :
2757 3522 : if (state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) {
2758 0 : OutdoorAirUnit::GetOutdoorAirUnitInputs(state);
2759 0 : state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false;
2760 : }
2761 :
2762 3522 : GetOutdoorAirUnitZoneInletNode = 0;
2763 3522 : if (OAUnitNum > 0 && OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits) {
2764 3522 : GetOutdoorAirUnitZoneInletNode = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).AirOutletNode;
2765 : }
2766 :
2767 3522 : return GetOutdoorAirUnitZoneInletNode;
2768 : }
2769 :
2770 3522 : int GetOutdoorAirUnitReturnAirNode(EnergyPlusData &state, int const OAUnitNum)
2771 : {
2772 :
2773 : // FUNCTION INFORMATION:
2774 : // AUTHOR B Griffith
2775 : // DATE WRITTEN Dec 2006
2776 : // MODIFIED na
2777 : // RE-ENGINEERED na
2778 :
2779 : // PURPOSE OF THIS FUNCTION:
2780 : // lookup function for OA inlet node
2781 :
2782 : // Return value
2783 : int GetOutdoorAirUnitReturnAirNode;
2784 :
2785 3522 : if (state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag) {
2786 0 : OutdoorAirUnit::GetOutdoorAirUnitInputs(state);
2787 0 : state.dataOutdoorAirUnit->GetOutdoorAirUnitInputFlag = false;
2788 : }
2789 :
2790 3522 : GetOutdoorAirUnitReturnAirNode = 0;
2791 3522 : if (OAUnitNum > 0 && OAUnitNum <= state.dataOutdoorAirUnit->NumOfOAUnits) {
2792 3522 : GetOutdoorAirUnitReturnAirNode = state.dataOutdoorAirUnit->OutAirUnit(OAUnitNum).AirInletNode;
2793 : }
2794 :
2795 3522 : return GetOutdoorAirUnitReturnAirNode;
2796 : }
2797 :
2798 : } // namespace OutdoorAirUnit
2799 :
2800 2313 : } // namespace EnergyPlus
|