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 <AirflowNetwork/Solver.hpp>
57 : #include <EnergyPlus/Autosizing/Base.hh>
58 : #include <EnergyPlus/BranchNodeConnections.hh>
59 : #include <EnergyPlus/Data/EnergyPlusData.hh>
60 : #include <EnergyPlus/DataContaminantBalance.hh>
61 : #include <EnergyPlus/DataConvergParams.hh>
62 : #include <EnergyPlus/DataDefineEquip.hh>
63 : #include <EnergyPlus/DataEnvironment.hh>
64 : #include <EnergyPlus/DataHVACGlobals.hh>
65 : #include <EnergyPlus/DataHeatBalFanSys.hh>
66 : #include <EnergyPlus/DataHeatBalance.hh>
67 : #include <EnergyPlus/DataIPShortCuts.hh>
68 : #include <EnergyPlus/DataLoopNode.hh>
69 : #include <EnergyPlus/DataSizing.hh>
70 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
71 : #include <EnergyPlus/DataZoneEquipment.hh>
72 : #include <EnergyPlus/EMSManager.hh>
73 : #include <EnergyPlus/Fans.hh>
74 : #include <EnergyPlus/FluidProperties.hh>
75 : #include <EnergyPlus/General.hh>
76 : #include <EnergyPlus/GeneralRoutines.hh>
77 : #include <EnergyPlus/GlobalNames.hh>
78 : #include <EnergyPlus/HVACFan.hh>
79 : #include <EnergyPlus/HeatingCoils.hh>
80 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
81 : #include <EnergyPlus/NodeInputManager.hh>
82 : #include <EnergyPlus/OutputProcessor.hh>
83 : #include <EnergyPlus/Plant/DataPlant.hh>
84 : #include <EnergyPlus/PlantUtilities.hh>
85 : #include <EnergyPlus/Psychrometrics.hh>
86 : #include <EnergyPlus/ReportCoilSelection.hh>
87 : #include <EnergyPlus/ScheduleManager.hh>
88 : #include <EnergyPlus/SingleDuct.hh>
89 : #include <EnergyPlus/SteamCoils.hh>
90 : #include <EnergyPlus/UtilityRoutines.hh>
91 : #include <EnergyPlus/WaterCoils.hh>
92 : #include <EnergyPlus/ZoneAirLoopEquipmentManager.hh>
93 :
94 : namespace EnergyPlus::SingleDuct {
95 :
96 : // Module containing the Single Duct Systems as a single component/ or really a single driver
97 :
98 : // MODULE INFORMATION:
99 : // AUTHOR Richard J. Liesen
100 : // DATE WRITTEN January 2000
101 : // MODIFIED na
102 : // RE-ENGINEERED na
103 :
104 : // PURPOSE OF THIS MODULE:
105 : // To encapsulate the data and algorithms required to
106 : // simulate single duct systems as a single driver or inter-connecting controllers.
107 :
108 : // Using/Aliasing
109 : using namespace DataLoopNode;
110 : using BranchNodeConnections::SetUpCompSets;
111 : using BranchNodeConnections::TestCompSet;
112 : using DataHVACGlobals::ATMixer_InletSide;
113 : using DataHVACGlobals::ATMixer_SupplySide;
114 : using DataHVACGlobals::SmallAirVolFlow;
115 : using DataHVACGlobals::SmallLoad;
116 : using DataHVACGlobals::SmallMassFlow;
117 : using namespace DataSizing;
118 : using Psychrometrics::PsyCpAirFnW;
119 : using Psychrometrics::PsyRhoAirFnPbTdbW;
120 : using namespace FluidProperties;
121 : using namespace ScheduleManager;
122 : using namespace SteamCoils;
123 :
124 : static constexpr std::string_view fluidNameSteam("STEAM");
125 : static constexpr std::string_view fluidNameWater("WATER");
126 :
127 32682712 : void SimulateSingleDuct(
128 : EnergyPlusData &state, std::string_view CompName, bool const FirstHVACIteration, int const ZoneNum, int const ZoneNodeNum, int &CompIndex)
129 : {
130 :
131 : // SUBROUTINE INFORMATION:
132 : // AUTHOR Richard Liesen
133 : // DATE WRITTEN January 2000
134 : // MODIFIED na
135 : // RE-ENGINEERED na
136 :
137 : // PURPOSE OF THIS SUBROUTINE:
138 : // This subroutine manages Sys system simulation.
139 : // It is called from the ManageZoneEquip
140 : // at the system time step.
141 :
142 : // Using/Aliasing
143 :
144 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
145 : int SysNum; // The Sys that you are currently loading input into
146 :
147 : // Obtains and Allocates Sys related parameters from input file
148 32682712 : if (state.dataSingleDuct->GetInputFlag) { // First time subroutine has been entered
149 504 : GetSysInput(state);
150 504 : state.dataSingleDuct->GetInputFlag = false;
151 : }
152 :
153 : // Find the correct SysNumber with the Component Name
154 32682712 : if (CompIndex == 0) {
155 3309 : SysNum = UtilityRoutines::FindItemInList(CompName, state.dataSingleDuct->sd_airterminal, &SingleDuctAirTerminal::SysName);
156 3309 : if (SysNum == 0) {
157 0 : ShowFatalError(state, "SimulateSingleDuct: System not found=" + std::string{CompName});
158 : }
159 3309 : CompIndex = SysNum;
160 : } else {
161 32679403 : SysNum = CompIndex;
162 32679403 : if (SysNum > state.dataSingleDuct->NumSDAirTerminal || SysNum < 1) {
163 0 : ShowFatalError(state,
164 0 : format("SimulateSingleDuct: Invalid CompIndex passed={}, Number of Systems={}, System name={}",
165 : CompIndex,
166 0 : state.dataSingleDuct->NumSDAirTerminal,
167 0 : CompName));
168 : }
169 32679403 : if (state.dataSingleDuct->CheckEquipName(SysNum)) {
170 3304 : if (CompName != state.dataSingleDuct->sd_airterminal(SysNum).SysName) {
171 0 : ShowFatalError(state,
172 0 : format("SimulateSingleDuct: Invalid CompIndex passed={}, System name={}, stored System Name for that index={}",
173 : CompIndex,
174 : CompName,
175 0 : state.dataSingleDuct->sd_airterminal(SysNum).SysName));
176 : }
177 3304 : state.dataSingleDuct->CheckEquipName(SysNum) = false;
178 : }
179 : }
180 :
181 32682712 : auto &thisATU(state.dataSingleDuct->sd_airterminal(SysNum));
182 :
183 32682712 : state.dataSize->TermUnitSingDuct = true;
184 32682712 : state.dataSize->CurTermUnitSizingNum = state.dataDefineEquipment->AirDistUnit(thisATU.ADUNum).TermUnitSizingNum;
185 :
186 : // With the correct SysNum Initialize the system
187 32682712 : thisATU.InitSys(state, FirstHVACIteration); // Initialize all Sys related parameters
188 :
189 : // Calculate the Correct Sys Model with the current SysNum
190 32682712 : switch (thisATU.SysType_Num) {
191 1679042 : case SysType::SingleDuctConstVolReheat: // AirTerminal:SingleDuct:ConstantVolume:Reheat
192 1679042 : thisATU.SimConstVol(state, FirstHVACIteration, ZoneNum, ZoneNodeNum);
193 1679042 : break;
194 7471141 : case SysType::SingleDuctConstVolNoReheat: // AirTerminal:SingleDuct:ConstantVolume:NoReheat
195 7471141 : thisATU.SimConstVolNoReheat(state);
196 7471141 : break;
197 23432728 : case SysType::SingleDuctVAVReheat: // SINGLE DUCT:VAV:REHEAT
198 : case SysType::SingleDuctVAVNoReheat: // SINGLE DUCT:VAV:NOREHEAT
199 23432728 : thisATU.SimVAV(state, FirstHVACIteration, ZoneNum, ZoneNodeNum);
200 23432728 : break;
201 31064 : case SysType::SingleDuctVAVReheatVSFan: // SINGLE DUCT:VAV:REHEAT:VS FAN
202 31064 : thisATU.SimVAVVS(state, FirstHVACIteration, ZoneNum, ZoneNodeNum);
203 31064 : break;
204 68737 : case SysType::SingleDuctCBVAVReheat: // SINGLE DUCT:VAVHEATANDCOOL:REHEAT
205 : case SysType::SingleDuctCBVAVNoReheat: // SINGLE DUCT:VAVHEATANDCOOL:NOREHEAT
206 68737 : thisATU.SimCBVAV(state, FirstHVACIteration, ZoneNum, ZoneNodeNum);
207 68737 : break;
208 0 : default:
209 : // assert(false);
210 0 : break;
211 : }
212 :
213 : // Report the current Sys
214 32682712 : thisATU.ReportSys(state);
215 :
216 32682712 : state.dataSize->TermUnitSingDuct = false;
217 32682712 : }
218 :
219 : // Get Input Section of the Module
220 : //******************************************************************************
221 :
222 504 : void GetSysInput(EnergyPlusData &state)
223 : {
224 :
225 : // SUBROUTINE INFORMATION:
226 : // AUTHOR Richard Liesen
227 : // DATE WRITTEN April 1998
228 : // MODIFIED na
229 : // RE-ENGINEERED na
230 :
231 : // PURPOSE OF THIS SUBROUTINE:
232 : // This subroutine is the main routine to call other input routines and Get routines
233 :
234 : // METHODOLOGY EMPLOYED:
235 : // Uses the status flags to trigger events.
236 :
237 : // Using/Aliasing
238 : using NodeInputManager::GetOnlySingleNode;
239 : using SteamCoils::GetCoilAirOutletNode;
240 : using SteamCoils::GetCoilSteamInletNode;
241 : using SteamCoils::GetSteamCoilIndex;
242 : using WaterCoils::GetCoilOutletNode;
243 : using WaterCoils::GetCoilWaterInletNode;
244 504 : auto &GetHeatingCoilCapacity(HeatingCoils::GetCoilCapacity);
245 504 : auto &GetHeatingCoilOutletNode(HeatingCoils::GetCoilOutletNode);
246 : using Fans::GetFanInletNode;
247 : using Fans::GetFanOutletNode;
248 : using namespace DataHeatBalance;
249 :
250 : // SUBROUTINE PARAMETER DEFINITIONS:
251 : static constexpr std::string_view RoutineName("GetSysInput: "); // include trailing blank
252 :
253 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
254 :
255 : int NumZoneSiz;
256 : int ZoneSizIndex;
257 : int IOStat;
258 504 : bool ErrorsFound(false); // If errors detected in input
259 : bool IsNotOK; // Flag to verify name
260 : int CtrlZone; // controlled zone do loop index
261 : int SupAirIn; // controlled zone supply air inlet index
262 : int ADUNum; // air distribution unit index
263 1008 : std::string CurrentModuleObject; // for ease in getting objects
264 1008 : Array1D_string Alphas; // Alpha input items for object
265 1008 : Array1D_string cAlphaFields; // Alpha field names
266 1008 : Array1D_string cNumericFields; // Numeric field names
267 1008 : Array1D<Real64> Numbers; // Numeric input items for object
268 1008 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
269 1008 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
270 :
271 : // certain object in the input file
272 1008 : std::string AirTermSysInletNodeName; // air terminal single duct system inlet node name
273 1008 : std::string AirTermSysOutletNodeName; // air terminal single duct system outlet node name
274 :
275 504 : state.dataSingleDuct->NumVAVSysGSI = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:VAV:Reheat");
276 504 : state.dataSingleDuct->NumNoRHVAVSysGSI =
277 1008 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:VAV:NoReheat");
278 504 : state.dataSingleDuct->NumConstVolSys =
279 1008 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:ConstantVolume:Reheat");
280 504 : state.dataSingleDuct->NumCVNoReheatSysGSI =
281 1008 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:ConstantVolume:NoReheat");
282 504 : state.dataSingleDuct->NumVAVVSGSI =
283 1008 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:VAV:Reheat:VariableSpeedFan");
284 504 : state.dataSingleDuct->NumCBVAVSysGSI =
285 1008 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:VAV:HeatAndCool:Reheat");
286 504 : state.dataSingleDuct->NumNoRHCBVAVSysGSI =
287 1008 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:VAV:HeatAndCool:NoReheat");
288 1512 : state.dataSingleDuct->NumSDAirTerminal = state.dataSingleDuct->NumVAVSysGSI + state.dataSingleDuct->NumConstVolSys +
289 1512 : state.dataSingleDuct->NumCVNoReheatSysGSI + state.dataSingleDuct->NumNoRHVAVSysGSI +
290 1512 : state.dataSingleDuct->NumVAVVSGSI + state.dataSingleDuct->NumCBVAVSysGSI +
291 504 : state.dataSingleDuct->NumNoRHCBVAVSysGSI;
292 :
293 504 : state.dataSingleDuct->sd_airterminal.allocate(state.dataSingleDuct->NumSDAirTerminal);
294 504 : state.dataSingleDuct->SysUniqueNames.reserve(static_cast<unsigned>(state.dataSingleDuct->NumSDAirTerminal));
295 504 : state.dataSingleDuct->CheckEquipName.dimension(state.dataSingleDuct->NumSDAirTerminal, true);
296 :
297 2520 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
298 : "AirTerminal:SingleDuct:VAV:Reheat",
299 504 : state.dataSingleDuct->TotalArgsGSI,
300 504 : state.dataSingleDuct->NumAlphasGSI,
301 1008 : state.dataSingleDuct->NumNumsGSI);
302 504 : state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
303 504 : state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
304 2520 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
305 : "AirTerminal:SingleDuct:VAV:NoReheat",
306 504 : state.dataSingleDuct->TotalArgsGSI,
307 504 : state.dataSingleDuct->NumAlphasGSI,
308 1008 : state.dataSingleDuct->NumNumsGSI);
309 504 : state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
310 504 : state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
311 2520 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
312 : "AirTerminal:SingleDuct:ConstantVolume:Reheat",
313 504 : state.dataSingleDuct->TotalArgsGSI,
314 504 : state.dataSingleDuct->NumAlphasGSI,
315 1008 : state.dataSingleDuct->NumNumsGSI);
316 504 : state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
317 504 : state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
318 2520 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
319 : "AirTerminal:SingleDuct:ConstantVolume:NoReheat",
320 504 : state.dataSingleDuct->TotalArgsGSI,
321 504 : state.dataSingleDuct->NumAlphasGSI,
322 1008 : state.dataSingleDuct->NumNumsGSI);
323 504 : state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
324 504 : state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
325 2520 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
326 : "AirTerminal:SingleDuct:VAV:Reheat:VariableSpeedFan",
327 504 : state.dataSingleDuct->TotalArgsGSI,
328 504 : state.dataSingleDuct->NumAlphasGSI,
329 1008 : state.dataSingleDuct->NumNumsGSI);
330 504 : state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
331 504 : state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
332 2520 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
333 : "AirTerminal:SingleDuct:VAV:HeatAndCool:Reheat",
334 504 : state.dataSingleDuct->TotalArgsGSI,
335 504 : state.dataSingleDuct->NumAlphasGSI,
336 1008 : state.dataSingleDuct->NumNumsGSI);
337 504 : state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
338 504 : state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
339 2520 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state,
340 : "AirTerminal:SingleDuct:VAV:HeatAndCool:NoReheat",
341 504 : state.dataSingleDuct->TotalArgsGSI,
342 504 : state.dataSingleDuct->NumAlphasGSI,
343 1008 : state.dataSingleDuct->NumNumsGSI);
344 504 : state.dataSingleDuct->MaxNumsGSI = max(state.dataSingleDuct->MaxNumsGSI, state.dataSingleDuct->NumNumsGSI);
345 504 : state.dataSingleDuct->MaxAlphasGSI = max(state.dataSingleDuct->MaxAlphasGSI, state.dataSingleDuct->NumAlphasGSI);
346 :
347 504 : Alphas.allocate(state.dataSingleDuct->MaxAlphasGSI);
348 504 : cAlphaFields.allocate(state.dataSingleDuct->MaxAlphasGSI);
349 504 : cNumericFields.allocate(state.dataSingleDuct->MaxNumsGSI);
350 504 : Numbers.dimension(state.dataSingleDuct->MaxNumsGSI, 0.0);
351 504 : lAlphaBlanks.dimension(state.dataSingleDuct->MaxAlphasGSI, true);
352 504 : lNumericBlanks.dimension(state.dataSingleDuct->MaxNumsGSI, true);
353 :
354 : // Start Loading the System Input
355 2604 : for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumVAVSysGSI;
356 2100 : ++state.dataSingleDuct->SysIndexGSI) {
357 :
358 2100 : CurrentModuleObject = "AirTerminal:SingleDuct:VAV:Reheat";
359 :
360 8400 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
361 : CurrentModuleObject,
362 2100 : state.dataSingleDuct->SysIndexGSI,
363 : Alphas,
364 2100 : state.dataSingleDuct->NumAlphasGSI,
365 : Numbers,
366 2100 : state.dataSingleDuct->NumNumsGSI,
367 : IOStat,
368 : lNumericBlanks,
369 : lAlphaBlanks,
370 : cAlphaFields,
371 : cNumericFields);
372 :
373 2100 : state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI;
374 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysNum = state.dataSingleDuct->SysNumGSI;
375 4200 : GlobalNames::VerifyUniqueInterObjectName(
376 4200 : state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
377 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName = Alphas(1);
378 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType = CurrentModuleObject;
379 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysType_Num = SysType::SingleDuctVAVReheat;
380 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp = Alphas(7);
381 2100 : if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp, "Coil:Heating:Fuel")) {
382 57 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::Gas;
383 2043 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
384 2043 : "Coil:Heating:Electric")) {
385 259 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::Electric;
386 1784 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
387 1784 : "Coil:Heating:Water")) {
388 1776 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::SimpleHeating;
389 1776 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_PlantType =
390 : DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
391 8 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
392 8 : "Coil:Heating:Steam")) {
393 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::SteamAirHeating;
394 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_PlantType =
395 : DataPlant::PlantEquipmentType::CoilSteamAirHeating;
396 0 : } else if (!state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp.empty()) {
397 0 : ShowSevereError(
398 0 : state, "Illegal " + cAlphaFields(8) + " = " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp + '.');
399 0 : ShowContinueError(state,
400 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
401 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
402 0 : ErrorsFound = true;
403 : }
404 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName = Alphas(8);
405 6300 : ValidateComponent(state,
406 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
407 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
408 : IsNotOK,
409 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType);
410 2100 : if (IsNotOK) {
411 0 : ShowContinueError(state,
412 0 : "In " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
413 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
414 0 : ErrorsFound = true;
415 : }
416 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Schedule = Alphas(2);
417 2100 : if (lAlphaBlanks(2)) {
418 23 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
419 : } else {
420 2077 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = GetScheduleIndex(state, Alphas(2));
421 2077 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr == 0) {
422 0 : ShowSevereError(state, cAlphaFields(2) + " = " + Alphas(2) + " not found.");
423 0 : ShowContinueError(state,
424 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
425 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
426 0 : ErrorsFound = true;
427 : }
428 : }
429 : // For node connections, this object is both a parent and a non-parent, because the
430 : // VAV damper is not called out as a separate component, its nodes must be connected
431 : // as ObjectIsNotParent. But for the reheat coil, the nodes are connected as ObjectIsParent
432 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum =
433 4200 : GetOnlySingleNode(state,
434 2100 : Alphas(3),
435 : ErrorsFound,
436 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVReheat,
437 2100 : Alphas(1),
438 : DataLoopNode::NodeFluidType::Air,
439 : DataLoopNode::ConnectionType::Outlet,
440 : NodeInputManager::CompFluidStream::Primary,
441 : ObjectIsNotParent,
442 2100 : cAlphaFields(3));
443 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum =
444 4200 : GetOnlySingleNode(state,
445 2100 : Alphas(4),
446 : ErrorsFound,
447 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVReheat,
448 2100 : Alphas(1),
449 : DataLoopNode::NodeFluidType::Air,
450 : DataLoopNode::ConnectionType::Inlet,
451 : NodeInputManager::CompFluidStream::Primary,
452 : ObjectIsNotParent,
453 2100 : cAlphaFields(4));
454 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFlowRate = Numbers(1);
455 :
456 2100 : if (UtilityRoutines::SameString(Alphas(5), "Constant")) {
457 2064 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod = MinFlowFraction::Constant;
458 36 : } else if (UtilityRoutines::SameString(Alphas(5), "FixedFlowRate")) {
459 3 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod = MinFlowFraction::Fixed;
460 33 : } else if (UtilityRoutines::SameString(Alphas(5), "Scheduled")) {
461 33 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod = MinFlowFraction::Scheduled;
462 : } else {
463 0 : ShowSevereError(state, cAlphaFields(5) + " = " + Alphas(5) + " not found.");
464 0 : ShowContinueError(state,
465 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
466 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
467 0 : ErrorsFound = true;
468 : }
469 :
470 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = Numbers(2);
471 2100 : if (lNumericBlanks(2)) {
472 52 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ConstantMinAirFracSetByUser = false;
473 52 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DesignMinAirFrac = 0.0;
474 : } else {
475 2048 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ConstantMinAirFracSetByUser = true;
476 2048 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DesignMinAirFrac = Numbers(2);
477 2048 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod == MinFlowFraction::Fixed) {
478 1 : ShowWarningError(state, "Since " + cAlphaFields(5) + " = " + Alphas(5) + ", input for " + cNumericFields(2) + " will be ignored.");
479 3 : ShowContinueError(state,
480 2 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
481 1 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
482 1 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = 0.0;
483 : }
484 : }
485 :
486 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFixedMinAir = Numbers(3);
487 2100 : if (lNumericBlanks(3)) {
488 2097 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FixedMinAirSetByUser = false;
489 2097 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DesignMinAirFrac = 0.0;
490 : } else {
491 3 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FixedMinAirSetByUser = true;
492 3 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DesignMinAirFrac = Numbers(3);
493 3 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod == MinFlowFraction::Constant) {
494 0 : ShowWarningError(state, "Since " + cAlphaFields(5) + " = " + Alphas(5) + ", input for " + cNumericFields(3) + " will be ignored.");
495 0 : ShowContinueError(state,
496 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
497 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
498 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFixedMinAir = 0.0;
499 : }
500 : }
501 :
502 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracSchPtr = GetScheduleIndex(state, Alphas(6));
503 4167 : if ((state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracSchPtr == 0) &&
504 2067 : (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod == MinFlowFraction::Scheduled)) {
505 0 : ShowSevereError(state, cAlphaFields(6) + " = " + Alphas(6) + " not found.");
506 0 : ShowContinueError(state,
507 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
508 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
509 0 : ShowContinueError(state, "A valid schedule is required");
510 0 : ErrorsFound = true;
511 2133 : } else if ((state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracSchPtr > 0) &&
512 33 : (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod == MinFlowFraction::Scheduled)) {
513 : // check range of values in schedule
514 66 : if (!CheckScheduleValueMinMax(
515 33 : state, state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracSchPtr, ">=", 0.0, "<=", 1.0)) {
516 0 : ShowSevereError(state, "Error found in " + cAlphaFields(6) + " = " + Alphas(6));
517 0 : ShowContinueError(state,
518 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
519 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
520 0 : ShowContinueError(state, "Schedule values must be (>=0., <=1.)");
521 : }
522 : }
523 :
524 : // The reheat coil control node is necessary for hot water and steam reheat, but not necessary for
525 : // electric or gas reheat.
526 4143 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num != HeatingCoilType::Gas &&
527 2043 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num != HeatingCoilType::Electric) {
528 1784 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
529 8 : IsNotOK = false;
530 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatControlNode =
531 16 : GetCoilSteamInletNode(state,
532 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
533 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
534 : IsNotOK);
535 8 : if (IsNotOK) {
536 0 : ShowContinueError(state,
537 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
538 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
539 0 : ErrorsFound = true;
540 : }
541 : } else {
542 1776 : IsNotOK = false;
543 1776 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatControlNode =
544 3552 : GetCoilWaterInletNode(state,
545 1776 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
546 1776 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
547 : IsNotOK);
548 1776 : if (IsNotOK) {
549 0 : ShowContinueError(state,
550 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
551 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
552 0 : ErrorsFound = true;
553 : }
554 : }
555 : }
556 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode =
557 4200 : GetOnlySingleNode(state,
558 2100 : Alphas(9),
559 : ErrorsFound,
560 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVReheat,
561 2100 : Alphas(1),
562 : DataLoopNode::NodeFluidType::Air,
563 : DataLoopNode::ConnectionType::Outlet,
564 : NodeInputManager::CompFluidStream::Primary,
565 : ObjectIsParent,
566 2100 : cAlphaFields(9));
567 2100 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
568 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatSteamVolFlow = Numbers(4);
569 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatSteamVolFlow = Numbers(5);
570 : } else {
571 2092 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatWaterVolFlow = Numbers(4);
572 2092 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatWaterVolFlow = Numbers(5);
573 : }
574 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset = Numbers(6);
575 : // Set default convergence tolerance
576 2100 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset <= 0.0) {
577 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset = 0.001;
578 : }
579 2100 : if (UtilityRoutines::SameString(Alphas(10), "Reverse")) {
580 52 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperHeatingAction = Action::Reverse;
581 2048 : } else if (UtilityRoutines::SameString(Alphas(10), "Normal")) {
582 937 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperHeatingAction = Action::Normal;
583 1111 : } else if (UtilityRoutines::SameString(Alphas(10), "ReverseWithLimits")) {
584 1111 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperHeatingAction = Action::ReverseWithLimits;
585 : } else {
586 0 : ShowSevereError(state, cAlphaFields(10) + " = " + Alphas(10) + " not found.");
587 0 : ShowContinueError(state,
588 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
589 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
590 0 : ErrorsFound = true;
591 : }
592 :
593 : // Register component set data
594 6300 : TestCompSet(state,
595 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
596 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
597 2100 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum),
598 2100 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode),
599 : "Air Nodes");
600 :
601 42048 : for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
602 84096 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode ==
603 42048 : state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
604 2100 : state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum =
605 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
606 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum = ADUNum;
607 2100 : break;
608 : }
609 : }
610 : // one assumes if there isn't one assigned, it's an error?
611 2100 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum == 0) {
612 0 : ShowSevereError(state,
613 0 : std::string{RoutineName} + "No matching Air Distribution Unit, for System = [" +
614 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + ',' +
615 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName + "].");
616 0 : ShowContinueError(
617 : state,
618 0 : "...should have outlet node = " +
619 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode));
620 0 : ErrorsFound = true;
621 : } else {
622 :
623 : // Fill the Zone Equipment data with the inlet node number of this unit.
624 89497 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
625 87397 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
626 164732 : for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
627 165096 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode ==
628 82548 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
629 2100 : if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
630 0 : ShowSevereError(state, "Error in connecting a terminal unit to a zone");
631 0 : ShowContinueError(state,
632 0 : state.dataLoopNodes->NodeID(
633 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode) +
634 : " already connects to another zone");
635 0 : ShowContinueError(state,
636 0 : "Occurs for terminal unit " +
637 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
638 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
639 0 : ShowContinueError(state, "Check terminal unit node names for errors");
640 0 : ErrorsFound = true;
641 : } else {
642 2100 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode =
643 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
644 2100 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode =
645 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode;
646 2100 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
647 4200 : .TermUnitSizingNum = state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
648 2100 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
649 4200 : .ZoneEqNum = CtrlZone;
650 : }
651 :
652 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneNum = CtrlZone;
653 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneInNodeIndex = SupAirIn;
654 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFloorArea =
655 4200 : state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
656 2100 : state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
657 : }
658 : }
659 : }
660 : }
661 2100 : if (Numbers(7) == DataGlobalConstants::AutoCalculate) {
662 2077 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFlowRateDuringReheat = Numbers(7);
663 : } else {
664 23 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFlowRateDuringReheat =
665 23 : Numbers(7) * state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFloorArea;
666 : }
667 :
668 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFractionDuringReheat = Numbers(8);
669 :
670 2100 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperHeatingAction != Action::ReverseWithLimits) {
671 989 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFlowRateDuringReheat > 0.0) {
672 0 : ShowWarningError(state, "Since " + cAlphaFields(10) + " = " + Alphas(10) + ", input for " + cNumericFields(7) + " will be ignored.");
673 0 : ShowContinueError(state,
674 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
675 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
676 : }
677 989 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFractionDuringReheat > 0.0) {
678 15 : ShowWarningError(state, "Since " + cAlphaFields(10) + " = " + Alphas(10) + ", input for " + cNumericFields(8) + " will be ignored.");
679 45 : ShowContinueError(state,
680 30 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
681 15 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
682 : }
683 : }
684 :
685 : // Maximum reheat air temperature, i.e. the maximum supply air temperature leaving the reheat coil
686 2100 : if (!lNumericBlanks(9)) {
687 367 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatTemp = Numbers(9);
688 367 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatTempSetByUser = true;
689 : } else {
690 : // user does not specify maximum supply air temperature
691 : // sd_airterminal(SysNum)%MaxReheatTemp = 35.0D0 !C
692 1733 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatTempSetByUser = false;
693 : }
694 :
695 2100 : if (!lAlphaBlanks(11)) {
696 290 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OARequirementsPtr =
697 290 : UtilityRoutines::FindItemInList(Alphas(11), state.dataSize->OARequirements);
698 290 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OARequirementsPtr == 0) {
699 0 : ShowSevereError(state, cAlphaFields(11) + " = " + Alphas(11) + " not found.");
700 0 : ShowContinueError(state,
701 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
702 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
703 0 : ErrorsFound = true;
704 : } else {
705 290 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).NoOAFlowInputFromUser = false;
706 : }
707 : }
708 :
709 2100 : if (lAlphaBlanks(12)) {
710 2095 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFrac = 1.0;
711 2095 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchExist = false;
712 : } else {
713 5 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchPtr = GetScheduleIndex(state, Alphas(12));
714 5 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchPtr == 0) {
715 0 : ShowSevereError(state, cAlphaFields(12) + " = " + Alphas(12) + " not found.");
716 0 : ShowContinueError(state,
717 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
718 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
719 0 : ErrorsFound = true;
720 : }
721 5 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchExist = true;
722 : }
723 :
724 2100 : ValidateComponent(state, Alphas(7), Alphas(8), IsNotOK, state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType);
725 2100 : if (IsNotOK) {
726 0 : ShowContinueError(state,
727 0 : "In " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
728 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
729 0 : ErrorsFound = true;
730 : }
731 :
732 : // Add reheat coil to component sets array
733 12600 : SetUpCompSets(state,
734 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
735 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
736 2100 : Alphas(7),
737 2100 : Alphas(8),
738 2100 : Alphas(3),
739 2100 : Alphas(9));
740 :
741 : // Setup the Average damper Position output variable
742 8400 : SetupOutputVariable(state,
743 : "Zone Air Terminal VAV Damper Position",
744 : OutputProcessor::Unit::None,
745 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperPosition,
746 : OutputProcessor::SOVTimeStepType::System,
747 : OutputProcessor::SOVStoreType::Average,
748 4200 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
749 8400 : SetupOutputVariable(state,
750 : "Zone Air Terminal Minimum Air Flow Fraction",
751 : OutputProcessor::Unit::None,
752 2100 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracReport,
753 : OutputProcessor::SOVTimeStepType::System,
754 : OutputProcessor::SOVStoreType::Average,
755 4200 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
756 :
757 : } // end Number of Sys Loop
758 :
759 513 : for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumCBVAVSysGSI;
760 9 : ++state.dataSingleDuct->SysIndexGSI) {
761 :
762 9 : CurrentModuleObject = "AirTerminal:SingleDuct:VAV:HeatAndCool:Reheat";
763 :
764 36 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
765 : CurrentModuleObject,
766 9 : state.dataSingleDuct->SysIndexGSI,
767 : Alphas,
768 9 : state.dataSingleDuct->NumAlphasGSI,
769 : Numbers,
770 9 : state.dataSingleDuct->NumNumsGSI,
771 : IOStat,
772 : lNumericBlanks,
773 : lAlphaBlanks,
774 : cAlphaFields,
775 : cNumericFields);
776 :
777 9 : state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI;
778 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysNum = state.dataSingleDuct->SysNumGSI;
779 18 : GlobalNames::VerifyUniqueInterObjectName(
780 18 : state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
781 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName = Alphas(1);
782 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType = CurrentModuleObject;
783 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysType_Num = SysType::SingleDuctCBVAVReheat;
784 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp = Alphas(5);
785 9 : if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp, "Coil:Heating:Fuel")) {
786 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::Gas;
787 9 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
788 9 : "Coil:Heating:Electric")) {
789 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::Electric;
790 0 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
791 0 : "Coil:Heating:Water")) {
792 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::SimpleHeating;
793 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_PlantType =
794 : DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
795 0 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
796 0 : "Coil:Heating:Steam")) {
797 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::SteamAirHeating;
798 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_PlantType =
799 : DataPlant::PlantEquipmentType::CoilSteamAirHeating;
800 0 : } else if (!state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp.empty()) {
801 0 : ShowSevereError(
802 0 : state, "Illegal " + cAlphaFields(5) + " = " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp + '.');
803 0 : ShowContinueError(state,
804 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
805 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
806 0 : ErrorsFound = true;
807 : }
808 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName = Alphas(6);
809 27 : ValidateComponent(state,
810 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
811 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
812 : IsNotOK,
813 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType);
814 9 : if (IsNotOK) {
815 0 : ShowContinueError(state,
816 0 : "In " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
817 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
818 0 : ErrorsFound = true;
819 : }
820 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Schedule = Alphas(2);
821 9 : if (lAlphaBlanks(2)) {
822 1 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
823 : } else {
824 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = GetScheduleIndex(state, Alphas(2));
825 8 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr == 0) {
826 0 : ShowSevereError(state, cAlphaFields(2) + " = " + Alphas(2) + " not found.");
827 0 : ShowContinueError(state,
828 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
829 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
830 0 : ErrorsFound = true;
831 : }
832 : }
833 : // For node connections, this object is both a parent and a non-parent, because the
834 : // VAV damper is not called out as a separate component, its nodes must be connected
835 : // as ObjectIsNotParent. But for the reheat coil, the nodes are connected as ObjectIsParent
836 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum =
837 18 : GetOnlySingleNode(state,
838 9 : Alphas(3),
839 : ErrorsFound,
840 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVHeatAndCoolReheat,
841 9 : Alphas(1),
842 : DataLoopNode::NodeFluidType::Air,
843 : DataLoopNode::ConnectionType::Outlet,
844 : NodeInputManager::CompFluidStream::Primary,
845 : ObjectIsNotParent,
846 9 : cAlphaFields(3));
847 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum =
848 18 : GetOnlySingleNode(state,
849 9 : Alphas(4),
850 : ErrorsFound,
851 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVHeatAndCoolReheat,
852 9 : Alphas(1),
853 : DataLoopNode::NodeFluidType::Air,
854 : DataLoopNode::ConnectionType::Inlet,
855 : NodeInputManager::CompFluidStream::Primary,
856 : ObjectIsNotParent,
857 9 : cAlphaFields(4));
858 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFlowRate = Numbers(1);
859 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = Numbers(2);
860 9 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes < 0.0) {
861 0 : ShowWarningError(state,
862 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " \"" +
863 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName + "\"");
864 0 : ShowContinueError(state, cNumericFields(2) + " must be greater than or equal to 0. Resetting to 0 and the simulation continues.");
865 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = 0.0;
866 : }
867 9 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes > 1.0) {
868 0 : ShowWarningError(state,
869 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " \"" +
870 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName + "\"");
871 0 : ShowContinueError(state, cNumericFields(2) + " must be less than or equal to 1. Resetting to 1 and the simulation continues.");
872 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = 1.0;
873 : }
874 : // The reheat coil control node is necessary for hot water and steam reheat, but not necessary for
875 : // electric or gas reheat.
876 18 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::Gas ||
877 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::Electric) {
878 : } else {
879 0 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
880 0 : IsNotOK = false;
881 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatControlNode =
882 0 : GetCoilSteamInletNode(state,
883 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
884 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
885 : IsNotOK);
886 0 : if (IsNotOK) {
887 0 : ShowContinueError(state,
888 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
889 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
890 0 : ErrorsFound = true;
891 : }
892 : } else {
893 0 : IsNotOK = false;
894 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatControlNode =
895 0 : GetCoilWaterInletNode(state,
896 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
897 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
898 : IsNotOK);
899 0 : if (IsNotOK) {
900 0 : ShowContinueError(state,
901 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
902 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
903 0 : ErrorsFound = true;
904 : }
905 : }
906 : // END IF
907 : }
908 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode =
909 18 : GetOnlySingleNode(state,
910 9 : Alphas(7),
911 : ErrorsFound,
912 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVHeatAndCoolReheat,
913 9 : Alphas(1),
914 : DataLoopNode::NodeFluidType::Air,
915 : DataLoopNode::ConnectionType::Outlet,
916 : NodeInputManager::CompFluidStream::Primary,
917 : ObjectIsParent,
918 9 : cAlphaFields(7));
919 9 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
920 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatSteamVolFlow = Numbers(3);
921 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatSteamVolFlow = Numbers(4);
922 : } else {
923 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatWaterVolFlow = Numbers(3);
924 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatWaterVolFlow = Numbers(4);
925 : }
926 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset = Numbers(5);
927 : // Set default convergence tolerance
928 9 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset <= 0.0) {
929 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset = 0.001;
930 : }
931 :
932 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperHeatingAction = Action::Reverse;
933 :
934 : // Register component set data
935 27 : TestCompSet(state,
936 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
937 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
938 9 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum),
939 9 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode),
940 : "Air Nodes");
941 :
942 17 : for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
943 34 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode ==
944 17 : state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
945 9 : state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum =
946 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
947 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum = ADUNum;
948 9 : break;
949 : }
950 : }
951 : // one assumes if there isn't one assigned, it's an error?
952 9 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum == 0) {
953 0 : ShowSevereError(state,
954 0 : std::string{RoutineName} + "No matching Air Distribution Unit, for System = [" +
955 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + ',' +
956 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName + "].");
957 0 : ShowContinueError(
958 : state,
959 0 : "...should have outlet node = " +
960 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode));
961 0 : ErrorsFound = true;
962 : } else {
963 :
964 : // Fill the Zone Equipment data with the inlet node number of this unit
965 39 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
966 30 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
967 58 : for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
968 58 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode ==
969 29 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
970 9 : if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
971 0 : ShowSevereError(state, "Error in connecting a terminal unit to a zone");
972 0 : ShowContinueError(state,
973 0 : state.dataLoopNodes->NodeID(
974 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode) +
975 : " already connects to another zone");
976 0 : ShowContinueError(state,
977 0 : "Occurs for terminal unit " +
978 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
979 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
980 0 : ShowContinueError(state, "Check terminal unit node names for errors");
981 0 : ErrorsFound = true;
982 : } else {
983 9 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode =
984 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
985 9 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode =
986 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode;
987 9 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
988 18 : .TermUnitSizingNum = state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
989 9 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
990 18 : .ZoneEqNum = CtrlZone;
991 : }
992 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneNum = CtrlZone;
993 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneInNodeIndex = SupAirIn;
994 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFloorArea =
995 18 : state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
996 9 : state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
997 : }
998 : }
999 : }
1000 : }
1001 9 : if (!lNumericBlanks(6)) {
1002 3 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatTemp = Numbers(6);
1003 3 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatTempSetByUser = true;
1004 : } else {
1005 : // user does not specify maximum supply air temperature
1006 : // sd_airterminal(SysNum)%MaxReheatTemp = 35.0D0 !C
1007 6 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatTempSetByUser = false;
1008 : }
1009 :
1010 9 : ValidateComponent(state, Alphas(5), Alphas(6), IsNotOK, state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType);
1011 9 : if (IsNotOK) {
1012 0 : ShowContinueError(state,
1013 0 : "In " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1014 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1015 0 : ErrorsFound = true;
1016 : }
1017 :
1018 9 : if (lAlphaBlanks(8)) {
1019 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFrac = 1.0;
1020 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchExist = false;
1021 : } else {
1022 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchPtr = GetScheduleIndex(state, Alphas(8));
1023 0 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchPtr == 0) {
1024 0 : ShowSevereError(state, cAlphaFields(8) + " = " + Alphas(8) + " not found.");
1025 0 : ShowContinueError(state,
1026 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1027 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1028 0 : ErrorsFound = true;
1029 : }
1030 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchExist = true;
1031 : }
1032 :
1033 : // Add reheat coil to component sets array
1034 54 : SetUpCompSets(state,
1035 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
1036 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
1037 9 : Alphas(5),
1038 9 : Alphas(6),
1039 9 : Alphas(3),
1040 9 : Alphas(7));
1041 :
1042 : // Setup the Average damper Position output variable
1043 36 : SetupOutputVariable(state,
1044 : "Zone Air Terminal VAV Damper Position",
1045 : OutputProcessor::Unit::None,
1046 9 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperPosition,
1047 : OutputProcessor::SOVTimeStepType::System,
1048 : OutputProcessor::SOVStoreType::Average,
1049 18 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1050 :
1051 : } // end Number of VAVHeatandCool Sys Loop
1052 :
1053 504 : CurrentModuleObject = "AirTerminal:SingleDuct:ConstantVolume:Reheat";
1054 :
1055 769 : for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumConstVolSys;
1056 265 : ++state.dataSingleDuct->SysIndexGSI) {
1057 :
1058 1060 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1059 : CurrentModuleObject,
1060 265 : state.dataSingleDuct->SysIndexGSI,
1061 : Alphas,
1062 265 : state.dataSingleDuct->NumAlphasGSI,
1063 : Numbers,
1064 265 : state.dataSingleDuct->NumNumsGSI,
1065 : IOStat,
1066 : lNumericBlanks,
1067 : lAlphaBlanks,
1068 : cAlphaFields,
1069 : cNumericFields);
1070 :
1071 265 : state.dataSingleDuct->SysNumGSI =
1072 265 : state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI + state.dataSingleDuct->NumCBVAVSysGSI;
1073 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysNum = state.dataSingleDuct->SysNumGSI;
1074 530 : GlobalNames::VerifyUniqueInterObjectName(
1075 530 : state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1076 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName = Alphas(1);
1077 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType = CurrentModuleObject;
1078 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysType_Num = SysType::SingleDuctConstVolReheat;
1079 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp = Alphas(5);
1080 265 : if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp, "Coil:Heating:Fuel")) {
1081 38 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::Gas;
1082 227 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
1083 227 : "Coil:Heating:Electric")) {
1084 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::Electric;
1085 223 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
1086 223 : "Coil:Heating:Water")) {
1087 223 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::SimpleHeating;
1088 223 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_PlantType =
1089 : DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
1090 0 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
1091 0 : "Coil:Heating:Steam")) {
1092 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::SteamAirHeating;
1093 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_PlantType =
1094 : DataPlant::PlantEquipmentType::CoilSteamAirHeating;
1095 : } else {
1096 0 : ShowSevereError(
1097 0 : state, "Illegal " + cAlphaFields(5) + " = " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp + '.');
1098 0 : ShowContinueError(state,
1099 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1100 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1101 0 : ErrorsFound = true;
1102 : }
1103 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName = Alphas(6);
1104 795 : ValidateComponent(state,
1105 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
1106 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
1107 : IsNotOK,
1108 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType);
1109 265 : if (IsNotOK) {
1110 0 : ShowContinueError(state,
1111 0 : "In " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1112 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1113 0 : ErrorsFound = true;
1114 : }
1115 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Schedule = Alphas(2);
1116 265 : if (lAlphaBlanks(2)) {
1117 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
1118 : } else {
1119 261 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = GetScheduleIndex(state, Alphas(2));
1120 261 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr == 0) {
1121 0 : ShowSevereError(state, cAlphaFields(2) + " = " + Alphas(2) + " not found.");
1122 0 : ShowContinueError(state,
1123 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1124 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1125 0 : ErrorsFound = true;
1126 : }
1127 : }
1128 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum =
1129 530 : GetOnlySingleNode(state,
1130 265 : Alphas(3),
1131 : ErrorsFound,
1132 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeReheat,
1133 265 : Alphas(1),
1134 : DataLoopNode::NodeFluidType::Air,
1135 : DataLoopNode::ConnectionType::Outlet,
1136 : NodeInputManager::CompFluidStream::Primary,
1137 : ObjectIsParent,
1138 265 : cAlphaFields(3));
1139 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum =
1140 530 : GetOnlySingleNode(state,
1141 265 : Alphas(4),
1142 : ErrorsFound,
1143 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeReheat,
1144 265 : Alphas(1),
1145 : DataLoopNode::NodeFluidType::Air,
1146 : DataLoopNode::ConnectionType::Inlet,
1147 : NodeInputManager::CompFluidStream::Primary,
1148 : ObjectIsParent,
1149 265 : cAlphaFields(4));
1150 : // The reheat coil control node is necessary for hot water reheat, but not necessary for
1151 : // electric or gas reheat.
1152 492 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::Gas ||
1153 227 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::Electric) {
1154 : } else {
1155 223 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
1156 0 : IsNotOK = false;
1157 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatControlNode =
1158 0 : GetCoilSteamInletNode(state,
1159 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
1160 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
1161 : IsNotOK);
1162 0 : if (IsNotOK) {
1163 0 : ShowContinueError(state,
1164 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1165 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1166 0 : ErrorsFound = true;
1167 : }
1168 : } else {
1169 223 : IsNotOK = false;
1170 223 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatControlNode =
1171 446 : GetCoilWaterInletNode(state,
1172 223 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
1173 223 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
1174 : IsNotOK);
1175 223 : if (IsNotOK) {
1176 0 : ShowContinueError(state,
1177 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1178 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1179 0 : ErrorsFound = true;
1180 : }
1181 : }
1182 : }
1183 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode =
1184 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum;
1185 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFlowRate = Numbers(1);
1186 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = 0.0;
1187 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod = MinFlowFraction::MinFracNotUsed;
1188 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperHeatingAction = Action::HeatingNotUsed;
1189 265 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
1190 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatSteamVolFlow = Numbers(2);
1191 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatSteamVolFlow = Numbers(3);
1192 : } else {
1193 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatWaterVolFlow = Numbers(2);
1194 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatWaterVolFlow = Numbers(3);
1195 : }
1196 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset = Numbers(4);
1197 : // Set default convergence tolerance
1198 265 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset <= 0.0) {
1199 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset = 0.001;
1200 : }
1201 :
1202 : // Maximum reheat air temperature, i.e. the maximum supply air temperature leaving the reheat coil
1203 265 : if (!lNumericBlanks(5)) {
1204 3 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatTemp = Numbers(5);
1205 3 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatTempSetByUser = true;
1206 : } else {
1207 : // user does not specify maximum supply air temperature
1208 : // sd_airterminal(SysNum)%MaxReheatTemp = 35.0D0 !C
1209 262 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatTempSetByUser = false;
1210 : }
1211 : // Register component set data
1212 795 : TestCompSet(state,
1213 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
1214 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
1215 265 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum),
1216 265 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum),
1217 : "Air Nodes");
1218 :
1219 549 : for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
1220 1098 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode ==
1221 549 : state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
1222 265 : state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum =
1223 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
1224 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum = ADUNum;
1225 265 : break;
1226 : }
1227 : }
1228 : // one assumes if there isn't one assigned, it's an error?
1229 265 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum == 0) {
1230 0 : ShowSevereError(state,
1231 0 : std::string{RoutineName} + "No matching Air Distribution Unit, for System = [" +
1232 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + ',' +
1233 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName + "].");
1234 0 : ShowContinueError(
1235 : state,
1236 0 : "...should have outlet node = " +
1237 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode));
1238 0 : ErrorsFound = true;
1239 : } else {
1240 :
1241 : // Fill the Zone Equipment data with the inlet node number of this unit.
1242 1185 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
1243 920 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
1244 1710 : for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
1245 1710 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum ==
1246 855 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
1247 265 : if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
1248 0 : ShowSevereError(state, "Error in connecting a terminal unit to a zone");
1249 0 : ShowContinueError(
1250 : state,
1251 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum) +
1252 : " already connects to another zone");
1253 0 : ShowContinueError(state,
1254 0 : "Occurs for terminal unit " +
1255 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1256 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1257 0 : ShowContinueError(state, "Check terminal unit node names for errors");
1258 0 : ErrorsFound = true;
1259 : } else {
1260 265 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode =
1261 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
1262 265 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode =
1263 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum;
1264 265 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
1265 530 : .TermUnitSizingNum = state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
1266 265 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
1267 530 : .ZoneEqNum = CtrlZone;
1268 : }
1269 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneNum = CtrlZone;
1270 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneInNodeIndex = SupAirIn;
1271 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFloorArea =
1272 530 : state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
1273 265 : state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
1274 : }
1275 : }
1276 : }
1277 : }
1278 :
1279 265 : ValidateComponent(state, Alphas(5), Alphas(6), IsNotOK, state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType);
1280 265 : if (IsNotOK) {
1281 0 : ShowContinueError(state,
1282 0 : "In " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1283 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1284 0 : ErrorsFound = true;
1285 : }
1286 :
1287 : // Add reheat coil to component sets array
1288 1590 : SetUpCompSets(state,
1289 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
1290 265 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
1291 265 : Alphas(5),
1292 265 : Alphas(6),
1293 265 : Alphas(4),
1294 265 : Alphas(3));
1295 :
1296 : // Setup the Average damper Position output variable
1297 : // BG removed 9-10-2009 during work on CR 7770, constant volume has no damper
1298 : // CALL SetupOutputVariable(state, 'Damper Position', Sys(SysNum)%DamperPosition, &
1299 : // 'System','Average',Sys(SysNum)%SysName)
1300 :
1301 : } // End Number of Sys Loop
1302 :
1303 504 : CurrentModuleObject = "AirTerminal:SingleDuct:ConstantVolume:NoReheat";
1304 :
1305 1342 : for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumCVNoReheatSysGSI;
1306 838 : ++state.dataSingleDuct->SysIndexGSI) {
1307 :
1308 3352 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1309 : CurrentModuleObject,
1310 838 : state.dataSingleDuct->SysIndexGSI,
1311 : Alphas,
1312 838 : state.dataSingleDuct->NumAlphasGSI,
1313 : Numbers,
1314 838 : state.dataSingleDuct->NumNumsGSI,
1315 : IOStat,
1316 : lNumericBlanks,
1317 : lAlphaBlanks,
1318 : cAlphaFields,
1319 : cNumericFields);
1320 :
1321 2514 : state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI +
1322 1676 : state.dataSingleDuct->NumCBVAVSysGSI + state.dataSingleDuct->NumConstVolSys;
1323 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysNum = state.dataSingleDuct->SysNumGSI;
1324 1676 : GlobalNames::VerifyUniqueInterObjectName(
1325 1676 : state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1326 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName = Alphas(1);
1327 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType = CurrentModuleObject;
1328 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysType_Num = SysType::SingleDuctConstVolNoReheat;
1329 :
1330 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Schedule = Alphas(2);
1331 838 : if (lAlphaBlanks(2)) {
1332 110 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
1333 : } else {
1334 728 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = GetScheduleIndex(state, Alphas(2));
1335 728 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr == 0) {
1336 0 : ShowSevereError(state, cAlphaFields(2) + " = " + Alphas(2) + " not found.");
1337 0 : ShowContinueError(state,
1338 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1339 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1340 0 : ErrorsFound = true;
1341 : }
1342 : }
1343 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum =
1344 1676 : GetOnlySingleNode(state,
1345 838 : Alphas(3),
1346 : ErrorsFound,
1347 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeNoReheat,
1348 838 : Alphas(1),
1349 : DataLoopNode::NodeFluidType::Air,
1350 : DataLoopNode::ConnectionType::Inlet,
1351 : NodeInputManager::CompFluidStream::Primary,
1352 : ObjectIsNotParent,
1353 838 : cAlphaFields(3));
1354 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum =
1355 1676 : GetOnlySingleNode(state,
1356 838 : Alphas(4),
1357 : ErrorsFound,
1358 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeNoReheat,
1359 838 : Alphas(1),
1360 : DataLoopNode::NodeFluidType::Air,
1361 : DataLoopNode::ConnectionType::Outlet,
1362 : NodeInputManager::CompFluidStream::Primary,
1363 : ObjectIsNotParent,
1364 838 : cAlphaFields(4));
1365 :
1366 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFlowRate = Numbers(1);
1367 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = 0.0;
1368 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod = MinFlowFraction::MinFracNotUsed;
1369 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperHeatingAction = Action::HeatingNotUsed;
1370 :
1371 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatControlNode = 0;
1372 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode =
1373 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum;
1374 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatWaterVolFlow = 0.0;
1375 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatSteamVolFlow = 0.0;
1376 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatWaterVolFlow = 0.0;
1377 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatSteamVolFlow = 0.0;
1378 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset = 0.000001;
1379 :
1380 : // Register component set data
1381 2514 : TestCompSet(state,
1382 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
1383 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
1384 838 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum),
1385 838 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum),
1386 : "Air Nodes");
1387 :
1388 6745 : for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
1389 13490 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum ==
1390 6745 : state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
1391 838 : state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum =
1392 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
1393 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum = ADUNum;
1394 838 : break;
1395 : }
1396 : }
1397 : // one assumes if there isn't one assigned, it's an error?
1398 838 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum == 0) {
1399 0 : ShowSevereError(state,
1400 0 : std::string{RoutineName} + "No matching Air Distribution Unit, for System = [" +
1401 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + ',' +
1402 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName + "].");
1403 0 : ShowContinueError(state,
1404 0 : "...should have outlet node = " +
1405 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum));
1406 0 : ErrorsFound = true;
1407 : } else {
1408 :
1409 : // Fill the Zone Equipment data with the inlet node number of this unit.
1410 16557 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
1411 15719 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
1412 35186 : for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
1413 42270 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum ==
1414 21135 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
1415 838 : if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
1416 0 : ShowSevereError(state, "Error in connecting a terminal unit to a zone");
1417 0 : ShowContinueError(
1418 : state,
1419 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum) +
1420 : " already connects to another zone");
1421 0 : ShowContinueError(state,
1422 0 : "Occurs for terminal unit " +
1423 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1424 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1425 0 : ShowContinueError(state, "Check terminal unit node names for errors");
1426 0 : ErrorsFound = true;
1427 : } else {
1428 838 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode =
1429 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
1430 838 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode =
1431 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum;
1432 838 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
1433 1676 : .TermUnitSizingNum = state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
1434 838 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
1435 1676 : .ZoneEqNum = CtrlZone;
1436 : }
1437 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneNum = CtrlZone;
1438 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneInNodeIndex = SupAirIn;
1439 838 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFloorArea =
1440 1676 : state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
1441 838 : state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
1442 : }
1443 : }
1444 : }
1445 : }
1446 :
1447 838 : if (lAlphaBlanks(5)) {
1448 836 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).NoOAFlowInputFromUser = true;
1449 : } else {
1450 2 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OARequirementsPtr =
1451 2 : UtilityRoutines::FindItemInList(Alphas(5), state.dataSize->OARequirements);
1452 2 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OARequirementsPtr == 0) {
1453 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + Alphas(1) + "\", invalid data.");
1454 0 : ShowContinueError(state, "..invalid " + cAlphaFields(5) + "=\"" + Alphas(5) + "\".");
1455 0 : ErrorsFound = true;
1456 : } else {
1457 2 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).NoOAFlowInputFromUser = false;
1458 : }
1459 : }
1460 :
1461 838 : if (lAlphaBlanks(6)) {
1462 837 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OAPerPersonMode =
1463 : DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
1464 : } else {
1465 1 : if (Alphas(6) == "CURRENTOCCUPANCY") {
1466 1 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OAPerPersonMode =
1467 : DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
1468 0 : } else if (Alphas(6) == "DESIGNOCCUPANCY") {
1469 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OAPerPersonMode =
1470 : DataZoneEquipment::PerPersonVentRateMode::ByDesignLevel;
1471 : } else {
1472 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OAPerPersonMode =
1473 : DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
1474 0 : ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + Alphas(1) + "\", invalid data.");
1475 0 : ShowContinueError(state,
1476 0 : "..invalid " + cAlphaFields(6) + "=\"" + Alphas(6) + "\". The default input of CurrentOccupancy is assigned");
1477 : }
1478 : }
1479 :
1480 838 : if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
1481 : // model results related actuators
1482 1036 : SetupEMSActuator(state,
1483 : "AirTerminal:SingleDuct:ConstantVolume:NoReheat",
1484 259 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
1485 : "Mass Flow Rate",
1486 : "[kg/s]",
1487 259 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).EMSOverrideAirFlow,
1488 777 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).EMSMassFlowRateValue);
1489 : // model input related internal variables
1490 777 : SetupEMSInternalVariable(state,
1491 : "AirTerminal:SingleDuct:ConstantVolume:NoReheat Maximum Mass Flow Rate",
1492 259 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
1493 : "[kg/s]",
1494 777 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).AirMassFlowRateMax);
1495 : }
1496 :
1497 : } // End Number of Sys Loop
1498 :
1499 589 : for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumNoRHVAVSysGSI;
1500 85 : ++state.dataSingleDuct->SysIndexGSI) {
1501 :
1502 85 : CurrentModuleObject = "AirTerminal:SingleDuct:VAV:NoReheat";
1503 :
1504 340 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1505 : CurrentModuleObject,
1506 85 : state.dataSingleDuct->SysIndexGSI,
1507 : Alphas,
1508 85 : state.dataSingleDuct->NumAlphasGSI,
1509 : Numbers,
1510 85 : state.dataSingleDuct->NumNumsGSI,
1511 : IOStat,
1512 : lNumericBlanks,
1513 : lAlphaBlanks,
1514 : cAlphaFields,
1515 : cNumericFields);
1516 :
1517 255 : state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI +
1518 255 : state.dataSingleDuct->NumCBVAVSysGSI + state.dataSingleDuct->NumConstVolSys +
1519 85 : state.dataSingleDuct->NumCVNoReheatSysGSI;
1520 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysNum = state.dataSingleDuct->SysNumGSI;
1521 170 : GlobalNames::VerifyUniqueInterObjectName(
1522 170 : state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1523 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName = Alphas(1);
1524 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType = CurrentModuleObject;
1525 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysType_Num = SysType::SingleDuctVAVNoReheat;
1526 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp = "";
1527 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName = "";
1528 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Schedule = Alphas(2);
1529 85 : if (lAlphaBlanks(2)) {
1530 25 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
1531 : } else {
1532 60 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = GetScheduleIndex(state, Alphas(2));
1533 60 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr == 0) {
1534 0 : ShowSevereError(state, cAlphaFields(2) + " = " + Alphas(2) + " not found.");
1535 0 : ShowContinueError(state,
1536 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1537 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1538 0 : ErrorsFound = true;
1539 : }
1540 : }
1541 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum =
1542 170 : GetOnlySingleNode(state,
1543 85 : Alphas(3),
1544 : ErrorsFound,
1545 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVNoReheat,
1546 85 : Alphas(1),
1547 : DataLoopNode::NodeFluidType::Air,
1548 : DataLoopNode::ConnectionType::Outlet,
1549 : NodeInputManager::CompFluidStream::Primary,
1550 : ObjectIsNotParent,
1551 85 : cAlphaFields(3));
1552 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum =
1553 170 : GetOnlySingleNode(state,
1554 85 : Alphas(4),
1555 : ErrorsFound,
1556 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVNoReheat,
1557 85 : Alphas(1),
1558 : DataLoopNode::NodeFluidType::Air,
1559 : DataLoopNode::ConnectionType::Inlet,
1560 : NodeInputManager::CompFluidStream::Primary,
1561 : ObjectIsNotParent,
1562 85 : cAlphaFields(4));
1563 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFlowRate = Numbers(1);
1564 :
1565 85 : if (UtilityRoutines::SameString(Alphas(5), "Constant")) {
1566 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod = MinFlowFraction::Constant;
1567 0 : } else if (UtilityRoutines::SameString(Alphas(5), "FixedFlowRate")) {
1568 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod = MinFlowFraction::Fixed;
1569 0 : } else if (UtilityRoutines::SameString(Alphas(5), "Scheduled")) {
1570 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod = MinFlowFraction::Scheduled;
1571 : } else {
1572 0 : ShowSevereError(state, cAlphaFields(5) + " = " + Alphas(5) + " not found.");
1573 0 : ShowContinueError(state,
1574 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1575 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1576 0 : ErrorsFound = true;
1577 : }
1578 :
1579 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = Numbers(2);
1580 85 : if (lNumericBlanks(2)) {
1581 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ConstantMinAirFracSetByUser = false;
1582 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = 0.0;
1583 : } else {
1584 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ConstantMinAirFracSetByUser = true;
1585 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = Numbers(2);
1586 85 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod == MinFlowFraction::Fixed) {
1587 0 : ShowWarningError(state, "Since " + cAlphaFields(5) + " = " + Alphas(5) + ", input for " + cNumericFields(2) + " will be ignored.");
1588 0 : ShowContinueError(state,
1589 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1590 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1591 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = 0.0;
1592 : }
1593 : }
1594 :
1595 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFixedMinAir = Numbers(3);
1596 85 : if (lNumericBlanks(3)) {
1597 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FixedMinAirSetByUser = false;
1598 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DesignFixedMinAir = 0.0;
1599 : } else {
1600 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FixedMinAirSetByUser = true;
1601 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DesignFixedMinAir = Numbers(3);
1602 0 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod == MinFlowFraction::Constant) {
1603 0 : ShowWarningError(state, "Since " + cAlphaFields(5) + " = " + Alphas(5) + ", input for " + cNumericFields(3) + " will be ignored.");
1604 0 : ShowContinueError(state,
1605 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1606 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1607 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFixedMinAir = 0.0;
1608 : }
1609 : }
1610 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracSchPtr = GetScheduleIndex(state, Alphas(6));
1611 170 : if ((state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracSchPtr == 0) &&
1612 85 : (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod == MinFlowFraction::Scheduled)) {
1613 0 : ShowSevereError(state, cAlphaFields(6) + " = " + Alphas(6) + " not found.");
1614 0 : ShowContinueError(state,
1615 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1616 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1617 0 : ShowContinueError(state, "A valid schedule is required");
1618 0 : ErrorsFound = true;
1619 85 : } else if ((state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracSchPtr > 0) &&
1620 0 : (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracMethod == MinFlowFraction::Scheduled)) {
1621 : // check range of values in schedule
1622 0 : if (!CheckScheduleValueMinMax(
1623 0 : state, state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracSchPtr, ">=", 0.0, "<=", 1.0)) {
1624 0 : ShowSevereError(state, "Error found in " + cAlphaFields(6) + " = " + Alphas(6));
1625 0 : ShowContinueError(state,
1626 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1627 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1628 0 : ShowContinueError(state, "Schedule values must be (>=0., <=1.)");
1629 : }
1630 : }
1631 :
1632 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatControlNode = 0;
1633 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode =
1634 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum;
1635 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatWaterVolFlow = 0.0;
1636 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatSteamVolFlow = 0.0;
1637 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatWaterVolFlow = 0.0;
1638 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatSteamVolFlow = 0.0;
1639 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset = 0.000001;
1640 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperHeatingAction = Action::HeatingNotUsed;
1641 :
1642 : // Register component set data
1643 255 : TestCompSet(state,
1644 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
1645 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
1646 85 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum),
1647 85 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum),
1648 : "Air Nodes");
1649 :
1650 312 : for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
1651 624 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum ==
1652 312 : state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
1653 85 : state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum =
1654 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
1655 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum = ADUNum;
1656 85 : break;
1657 : }
1658 : }
1659 : // one assumes if there isn't one assigned, it's an error?
1660 85 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum == 0) {
1661 0 : ShowSevereError(state,
1662 0 : std::string{RoutineName} + "No matching Air Distribution Unit, for System = [" +
1663 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + ',' +
1664 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName + "].");
1665 0 : ShowContinueError(
1666 : state,
1667 0 : "...should have outlet node = " +
1668 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode));
1669 0 : ErrorsFound = true;
1670 : } else {
1671 :
1672 : // Fill the Zone Equipment data with the inlet node number of this unit.
1673 566 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
1674 481 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
1675 1094 : for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
1676 1394 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode ==
1677 697 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
1678 85 : if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
1679 0 : ShowSevereError(state, "Error in connecting a terminal unit to a zone");
1680 0 : ShowContinueError(state,
1681 0 : state.dataLoopNodes->NodeID(
1682 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode) +
1683 : " already connects to another zone");
1684 0 : ShowContinueError(state,
1685 0 : "Occurs for terminal unit " +
1686 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1687 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1688 0 : ShowContinueError(state, "Check terminal unit node names for errors");
1689 0 : ErrorsFound = true;
1690 : } else {
1691 85 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode =
1692 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
1693 85 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode =
1694 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode;
1695 85 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
1696 170 : .TermUnitSizingNum = state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
1697 85 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
1698 170 : .ZoneEqNum = CtrlZone;
1699 : }
1700 :
1701 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneNum = CtrlZone;
1702 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneInNodeIndex = SupAirIn;
1703 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFloorArea =
1704 170 : state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
1705 85 : state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
1706 : }
1707 : }
1708 : }
1709 : }
1710 85 : if (!lAlphaBlanks(7)) {
1711 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OARequirementsPtr =
1712 0 : UtilityRoutines::FindItemInList(Alphas(7), state.dataSize->OARequirements);
1713 0 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OARequirementsPtr == 0) {
1714 0 : ShowSevereError(state, cAlphaFields(7) + " = " + Alphas(7) + " not found.");
1715 0 : ShowContinueError(state,
1716 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1717 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1718 0 : ErrorsFound = true;
1719 : } else {
1720 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).NoOAFlowInputFromUser = false;
1721 : }
1722 : }
1723 :
1724 85 : if (lAlphaBlanks(8)) {
1725 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFrac = 1.0;
1726 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchExist = false;
1727 : } else {
1728 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchPtr = GetScheduleIndex(state, Alphas(8));
1729 0 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchPtr == 0) {
1730 0 : ShowSevereError(state, cAlphaFields(8) + " = " + Alphas(8) + " not found.");
1731 0 : ShowContinueError(state,
1732 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1733 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1734 0 : ErrorsFound = true;
1735 : }
1736 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchExist = true;
1737 : }
1738 :
1739 : // Setup the Average damper Position output variable
1740 340 : SetupOutputVariable(state,
1741 : "Zone Air Terminal VAV Damper Position",
1742 : OutputProcessor::Unit::None,
1743 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperPosition,
1744 : OutputProcessor::SOVTimeStepType::System,
1745 : OutputProcessor::SOVStoreType::Average,
1746 170 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1747 340 : SetupOutputVariable(state,
1748 : "Zone Air Terminal Minimum Air Flow Fraction",
1749 : OutputProcessor::Unit::None,
1750 85 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracReport,
1751 : OutputProcessor::SOVTimeStepType::System,
1752 : OutputProcessor::SOVStoreType::Average,
1753 170 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1754 :
1755 : } // end Number of Sys Loop
1756 :
1757 508 : for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumNoRHCBVAVSysGSI;
1758 4 : ++state.dataSingleDuct->SysIndexGSI) {
1759 :
1760 4 : CurrentModuleObject = "AirTerminal:SingleDuct:VAV:HeatAndCool:NoReheat";
1761 :
1762 16 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1763 : CurrentModuleObject,
1764 4 : state.dataSingleDuct->SysIndexGSI,
1765 : Alphas,
1766 4 : state.dataSingleDuct->NumAlphasGSI,
1767 : Numbers,
1768 4 : state.dataSingleDuct->NumNumsGSI,
1769 : IOStat,
1770 : lNumericBlanks,
1771 : lAlphaBlanks,
1772 : cAlphaFields,
1773 : cNumericFields);
1774 :
1775 12 : state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI +
1776 12 : state.dataSingleDuct->NumCBVAVSysGSI + state.dataSingleDuct->NumConstVolSys +
1777 8 : state.dataSingleDuct->NumCVNoReheatSysGSI + state.dataSingleDuct->NumNoRHVAVSysGSI;
1778 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysNum = state.dataSingleDuct->SysNumGSI;
1779 8 : GlobalNames::VerifyUniqueInterObjectName(
1780 8 : state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1781 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName = Alphas(1);
1782 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType = CurrentModuleObject;
1783 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysType_Num = SysType::SingleDuctCBVAVNoReheat;
1784 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp = "";
1785 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName = "";
1786 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Schedule = Alphas(2);
1787 4 : if (lAlphaBlanks(2)) {
1788 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
1789 : } else {
1790 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = GetScheduleIndex(state, Alphas(2));
1791 4 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr == 0) {
1792 0 : ShowSevereError(state, cAlphaFields(2) + " = " + Alphas(2) + " not found.");
1793 0 : ShowContinueError(state,
1794 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1795 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1796 0 : ErrorsFound = true;
1797 : }
1798 : }
1799 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum =
1800 8 : GetOnlySingleNode(state,
1801 4 : Alphas(3),
1802 : ErrorsFound,
1803 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVHeatAndCoolNoReheat,
1804 4 : Alphas(1),
1805 : DataLoopNode::NodeFluidType::Air,
1806 : DataLoopNode::ConnectionType::Outlet,
1807 : NodeInputManager::CompFluidStream::Primary,
1808 : ObjectIsNotParent,
1809 4 : cAlphaFields(3));
1810 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum =
1811 8 : GetOnlySingleNode(state,
1812 4 : Alphas(4),
1813 : ErrorsFound,
1814 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctVAVHeatAndCoolNoReheat,
1815 4 : Alphas(1),
1816 : DataLoopNode::NodeFluidType::Air,
1817 : DataLoopNode::ConnectionType::Inlet,
1818 : NodeInputManager::CompFluidStream::Primary,
1819 : ObjectIsNotParent,
1820 4 : cAlphaFields(4));
1821 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFlowRate = Numbers(1);
1822 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = Numbers(2);
1823 4 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes < 0.0) {
1824 0 : ShowWarningError(state,
1825 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = \"" +
1826 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1827 0 : ShowContinueError(state, cNumericFields(2) + " must be greater than or equal to 0. Resetting to 0 and the simulation continues.");
1828 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = 0.0;
1829 : }
1830 4 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes > 1.0) {
1831 0 : ShowWarningError(state,
1832 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = \"" +
1833 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1834 0 : ShowContinueError(state, cNumericFields(2) + " must be less than or equal to 1. Resetting to 1 and the simulation continues.");
1835 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = 1.0;
1836 : }
1837 :
1838 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatControlNode = 0;
1839 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode =
1840 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum;
1841 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatWaterVolFlow = 0.0;
1842 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatSteamVolFlow = 0.0;
1843 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatWaterVolFlow = 0.0;
1844 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatSteamVolFlow = 0.0;
1845 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset = 0.000001;
1846 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperHeatingAction = Action::HeatingNotUsed;
1847 :
1848 : // Register component set data
1849 12 : TestCompSet(state,
1850 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
1851 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
1852 4 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum),
1853 4 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum),
1854 : "Air Nodes");
1855 :
1856 12 : for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
1857 24 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum ==
1858 12 : state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
1859 4 : state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum =
1860 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
1861 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum = ADUNum;
1862 4 : break;
1863 : }
1864 : }
1865 : // one assumes if there isn't one assigned, it's an error?
1866 4 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum == 0) {
1867 0 : ShowSevereError(state,
1868 0 : std::string{RoutineName} + "No matching Air Distribution Unit, for System = [" +
1869 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + ',' +
1870 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName + "].");
1871 0 : ShowContinueError(
1872 : state,
1873 0 : "...should have outlet node = " +
1874 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode));
1875 0 : ErrorsFound = true;
1876 : } else {
1877 :
1878 : // Fill the Zone Equipment data with the inlet node number of this unit.
1879 16 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
1880 12 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
1881 24 : for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
1882 24 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode ==
1883 12 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
1884 4 : if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
1885 0 : ShowSevereError(state, "Error in connecting a terminal unit to a zone");
1886 0 : ShowContinueError(state,
1887 0 : state.dataLoopNodes->NodeID(
1888 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode) +
1889 : " already connects to another zone");
1890 0 : ShowContinueError(state,
1891 0 : "Occurs for terminal unit " +
1892 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1893 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1894 0 : ShowContinueError(state, "Check terminal unit node names for errors");
1895 0 : ErrorsFound = true;
1896 : } else {
1897 4 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode =
1898 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
1899 4 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode =
1900 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode;
1901 4 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
1902 8 : .TermUnitSizingNum = state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
1903 4 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
1904 8 : .ZoneEqNum = CtrlZone;
1905 : }
1906 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneNum = CtrlZone;
1907 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneInNodeIndex = SupAirIn;
1908 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFloorArea =
1909 8 : state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
1910 4 : state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
1911 : }
1912 : }
1913 : }
1914 : }
1915 :
1916 4 : if (lAlphaBlanks(5)) {
1917 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFrac = 1.0;
1918 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchExist = false;
1919 : } else {
1920 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchPtr = GetScheduleIndex(state, Alphas(5));
1921 0 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchPtr == 0) {
1922 0 : ShowSevereError(state, cAlphaFields(5) + " = " + Alphas(5) + " not found.");
1923 0 : ShowContinueError(state,
1924 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
1925 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1926 0 : ErrorsFound = true;
1927 : }
1928 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchExist = true;
1929 : }
1930 :
1931 : // Setup the Average damper Position output variable
1932 16 : SetupOutputVariable(state,
1933 : "Zone Air Terminal VAV Damper Position",
1934 : OutputProcessor::Unit::None,
1935 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperPosition,
1936 : OutputProcessor::SOVTimeStepType::System,
1937 : OutputProcessor::SOVStoreType::Average,
1938 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1939 :
1940 : } // end Number of VAVHeatandCool:NoReheat Sys Loop
1941 :
1942 : // read in the SINGLE DUCT:VAV:REHEAT:VS FAN data
1943 512 : for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumVAVVSGSI;
1944 8 : ++state.dataSingleDuct->SysIndexGSI) {
1945 :
1946 8 : CurrentModuleObject = "AirTerminal:SingleDuct:VAV:Reheat:VariableSpeedFan";
1947 :
1948 32 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1949 : CurrentModuleObject,
1950 8 : state.dataSingleDuct->SysIndexGSI,
1951 : Alphas,
1952 8 : state.dataSingleDuct->NumAlphasGSI,
1953 : Numbers,
1954 8 : state.dataSingleDuct->NumNumsGSI,
1955 : IOStat,
1956 : lNumericBlanks,
1957 : lAlphaBlanks,
1958 : cAlphaFields,
1959 : cNumericFields);
1960 :
1961 24 : state.dataSingleDuct->SysNumGSI = state.dataSingleDuct->SysIndexGSI + state.dataSingleDuct->NumVAVSysGSI +
1962 24 : state.dataSingleDuct->NumCBVAVSysGSI + state.dataSingleDuct->NumConstVolSys +
1963 24 : state.dataSingleDuct->NumCVNoReheatSysGSI + state.dataSingleDuct->NumNoRHVAVSysGSI +
1964 8 : state.dataSingleDuct->NumNoRHCBVAVSysGSI;
1965 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysNum = state.dataSingleDuct->SysNumGSI;
1966 16 : GlobalNames::VerifyUniqueInterObjectName(
1967 16 : state, state.dataSingleDuct->SysUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
1968 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName = Alphas(1);
1969 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType = CurrentModuleObject;
1970 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysType_Num = SysType::SingleDuctVAVReheatVSFan;
1971 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp = Alphas(7);
1972 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName = Alphas(8);
1973 8 : IsNotOK = false;
1974 8 : if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp, "Coil:Heating:Fuel")) {
1975 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::Gas;
1976 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode =
1977 0 : GetHeatingCoilOutletNode(state,
1978 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
1979 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
1980 : IsNotOK);
1981 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatCoilMaxCapacity =
1982 0 : GetHeatingCoilCapacity(state,
1983 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
1984 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
1985 : IsNotOK);
1986 0 : if (IsNotOK)
1987 0 : ShowContinueError(state,
1988 0 : "Occurs for terminal unit " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType +
1989 0 : " = " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
1990 8 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
1991 8 : "Coil:Heating:Electric")) {
1992 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::Electric;
1993 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode =
1994 0 : GetHeatingCoilOutletNode(state,
1995 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
1996 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
1997 : IsNotOK);
1998 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatCoilMaxCapacity =
1999 0 : GetHeatingCoilCapacity(state,
2000 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
2001 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
2002 : IsNotOK);
2003 0 : if (IsNotOK)
2004 0 : ShowContinueError(state,
2005 0 : "Occurs for terminal unit " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType +
2006 0 : " = " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2007 8 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
2008 8 : "Coil:Heating:Water")) {
2009 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::SimpleHeating;
2010 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_PlantType =
2011 : DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
2012 0 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
2013 0 : "Coil:Heating:Steam")) {
2014 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num = HeatingCoilType::SteamAirHeating;
2015 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_PlantType =
2016 : DataPlant::PlantEquipmentType::CoilSteamAirHeating;
2017 0 : } else if (!state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp.empty()) {
2018 0 : ShowSevereError(
2019 0 : state, "Illegal " + cAlphaFields(7) + " = " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp + '.');
2020 0 : ShowContinueError(state,
2021 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2022 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2023 0 : ErrorsFound = true;
2024 : }
2025 24 : ValidateComponent(state,
2026 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
2027 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
2028 : IsNotOK,
2029 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType);
2030 8 : if (IsNotOK) {
2031 0 : ShowContinueError(state,
2032 0 : "In " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2033 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2034 0 : ErrorsFound = true;
2035 : }
2036 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanType = Alphas(5);
2037 8 : if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanType, "Fan:VariableVolume")) {
2038 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Fan_Num = DataHVACGlobals::FanType_SimpleVAV;
2039 4 : } else if (UtilityRoutines::SameString(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanType, "Fan:SystemModel")) {
2040 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Fan_Num = DataHVACGlobals::FanType_SystemModelObject;
2041 0 : } else if (!state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanType.empty()) {
2042 0 : ShowSevereError(
2043 0 : state, "Illegal " + cAlphaFields(5) + " = " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanType + '.');
2044 0 : ShowContinueError(state,
2045 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2046 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2047 0 : ErrorsFound = true;
2048 : }
2049 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanName = Alphas(6);
2050 24 : ValidateComponent(state,
2051 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanType,
2052 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanName,
2053 : IsNotOK,
2054 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType);
2055 8 : if (IsNotOK) {
2056 0 : ShowContinueError(state,
2057 0 : "In " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2058 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2059 0 : ErrorsFound = true;
2060 : }
2061 8 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Fan_Num == DataHVACGlobals::FanType_SystemModelObject) {
2062 8 : state.dataHVACFan->fanObjs.emplace_back(
2063 12 : new HVACFan::FanSystem(state,
2064 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI)
2065 8 : .FanName)); // call constructor, safe here because get input is not using DataIPShortCuts.
2066 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Fan_Index =
2067 4 : HVACFan::getFanObjectVectorIndex(state, state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanName);
2068 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum =
2069 4 : state.dataHVACFan->fanObjs[state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Fan_Index]->outletNodeNum;
2070 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum =
2071 4 : state.dataHVACFan->fanObjs[state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Fan_Index]->inletNodeNum;
2072 4 : state.dataHVACFan->fanObjs[state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Fan_Index]->fanIsSecondaryDriver = true;
2073 4 : } else if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Fan_Num == DataHVACGlobals::FanType_SimpleVAV) {
2074 4 : IsNotOK = false;
2075 :
2076 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum =
2077 8 : GetFanOutletNode(state,
2078 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanType,
2079 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanName,
2080 : IsNotOK);
2081 4 : if (IsNotOK) {
2082 0 : ShowContinueError(state,
2083 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2084 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2085 0 : ErrorsFound = true;
2086 : }
2087 :
2088 4 : IsNotOK = false;
2089 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum =
2090 8 : GetFanInletNode(state,
2091 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanType,
2092 4 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).FanName,
2093 : IsNotOK);
2094 4 : if (IsNotOK) {
2095 0 : ShowContinueError(state,
2096 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2097 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2098 0 : ErrorsFound = true;
2099 : }
2100 : }
2101 :
2102 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).Schedule = Alphas(2);
2103 8 : if (lAlphaBlanks(2)) {
2104 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
2105 : } else {
2106 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr = GetScheduleIndex(state, Alphas(2));
2107 8 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SchedPtr == 0) {
2108 0 : ShowSevereError(state, cAlphaFields(2) + " = " + Alphas(2) + " not found.");
2109 0 : ShowContinueError(state,
2110 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2111 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2112 0 : ErrorsFound = true;
2113 : }
2114 : }
2115 :
2116 8 : AirTermSysInletNodeName = state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum);
2117 8 : if (!UtilityRoutines::SameString(Alphas(3), AirTermSysInletNodeName)) {
2118 0 : ShowWarningError(state,
2119 0 : std::string{RoutineName} + "Invalid air terminal object air inlet node name in " +
2120 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2121 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2122 0 : ShowContinueError(state, " Specified air inlet node name is = " + Alphas(3) + ".");
2123 0 : ShowContinueError(state, " Expected air inlet node name is = " + AirTermSysInletNodeName + ".");
2124 : // ErrorsFound = true;
2125 : }
2126 :
2127 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxAirVolFlowRate = Numbers(1);
2128 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxHeatAirVolFlowRate = Numbers(2);
2129 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneMinAirFracDes = Numbers(3);
2130 : // The reheat coil control node is necessary for hot water reheat, but not necessary for
2131 : // electric or gas reheat.
2132 16 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::Gas ||
2133 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::Electric) {
2134 : // IF(.NOT. lAlphaBlanks(6)) THEN
2135 : // CALL ShowWarningError(state, 'In '//TRIM(sd_airterminal(SysNum)%SysType)//' = ' // TRIM(sd_airterminal(SysNum)%SysName) &
2136 : // // ' the '//TRIM(cAlphaFields(6))//' is not needed and will be ignored.')
2137 : // CALL ShowContinueError(state, ' It is used for hot water reheat coils only.')
2138 : // END IF
2139 : } else {
2140 : // IF(lAlphaBlanks(6)) THEN
2141 : // CALL ShowSevereError(state, 'In '//TRIM(sd_airterminal(SysNum)%SysType)//' = ' // TRIM(sd_airterminal(SysNum)%SysName) &
2142 : // // ' the '//TRIM(cAlphaFields(6))//' is undefined')
2143 : // ErrorsFound=.TRUE.
2144 : // END IF
2145 8 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
2146 0 : IsNotOK = false;
2147 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatControlNode =
2148 0 : GetCoilSteamInletNode(state,
2149 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
2150 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
2151 : IsNotOK);
2152 0 : if (IsNotOK) {
2153 0 : ShowContinueError(state,
2154 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2155 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2156 0 : ErrorsFound = true;
2157 : } else {
2158 : // A4, \field Unit supply air outlet node
2159 : // \note same as heating coil air outlet node
2160 : // \note same as zone inlet node
2161 : // \type alpha
2162 0 : IsNotOK = false;
2163 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode =
2164 0 : GetCoilAirOutletNode(state,
2165 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
2166 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
2167 : IsNotOK);
2168 0 : if (IsNotOK) {
2169 0 : ShowContinueError(state,
2170 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2171 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2172 0 : ErrorsFound = true;
2173 : }
2174 : }
2175 : // GetOnlySingleNode(state, Alphas(6),ErrorsFound,sd_airterminal(SysNum)%SysType,Alphas(1), &
2176 : // DataLoopNode::NodeFluidType::Steam,DataLoopNode::NodeConnectionType::Actuator,1,ObjectIsParent)
2177 : } else {
2178 8 : IsNotOK = false;
2179 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatControlNode =
2180 16 : GetCoilWaterInletNode(state,
2181 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
2182 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
2183 : IsNotOK);
2184 8 : if (IsNotOK) {
2185 0 : ShowContinueError(state,
2186 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2187 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2188 0 : ErrorsFound = true;
2189 : } else {
2190 : // A4, \field Unit supply air outlet node
2191 : // \note same as heating coil air outlet node
2192 : // \note same as zone inlet node
2193 : // \type alpha
2194 8 : IsNotOK = false;
2195 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode =
2196 16 : GetCoilOutletNode(state,
2197 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp,
2198 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatName,
2199 : IsNotOK);
2200 8 : if (IsNotOK) {
2201 0 : ShowContinueError(state,
2202 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2203 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2204 0 : ErrorsFound = true;
2205 : }
2206 : }
2207 : // GetOnlySingleNode(state, Alphas(6),ErrorsFound,sd_airterminal(SysNum)%SysType,Alphas(1), &
2208 : // DataLoopNode::NodeFluidType::Water,DataLoopNode::NodeConnectionType::Actuator,1,ObjectIsParent)
2209 : }
2210 : }
2211 : // A4, \field Unit supply air outlet node
2212 : // \note same as heating coil air outlet node
2213 : // \note same as zone inlet node
2214 : // \type alpha
2215 : // sd_airterminal(SysNum)%ReheatAirOutletNode = &
2216 : // GetOnlySingleNode(state, Alphas(4),ErrorsFound,sd_airterminal(SysNum)%SysType,Alphas(1), &
2217 : // DataLoopNode::NodeFluidType::Air,DataLoopNode::NodeConnectionType::Outlet,1,ObjectIsParent)
2218 8 : AirTermSysOutletNodeName =
2219 8 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode);
2220 8 : if (!UtilityRoutines::SameString(Alphas(4), AirTermSysOutletNodeName)) {
2221 0 : ShowWarningError(state,
2222 0 : std::string{RoutineName} + "Invalid air terminal object air outlet node name in " +
2223 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2224 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2225 0 : ShowContinueError(state, " Specified air outlet node name is = " + Alphas(4) + ".");
2226 0 : ShowContinueError(state, " Expected air outlet node name is = " + AirTermSysOutletNodeName + ".");
2227 : // ErrorsFound = true;
2228 : }
2229 :
2230 8 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
2231 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatSteamVolFlow = Numbers(4);
2232 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatSteamVolFlow = Numbers(5);
2233 : } else {
2234 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MaxReheatWaterVolFlow = Numbers(4);
2235 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).MinReheatWaterVolFlow = Numbers(5);
2236 : }
2237 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset = Numbers(6);
2238 : // Set default convergence tolerance
2239 8 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset <= 0.0) {
2240 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ControllerOffset = 0.001;
2241 : }
2242 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperHeatingAction = Action::HeatingNotUsed;
2243 :
2244 : // Register component set data
2245 24 : TestCompSet(state,
2246 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
2247 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
2248 8 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum),
2249 8 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode),
2250 : "Air Nodes");
2251 :
2252 20 : for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
2253 40 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode ==
2254 20 : state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
2255 8 : state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum =
2256 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
2257 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum = ADUNum;
2258 8 : break;
2259 : }
2260 : }
2261 : // one assumes if there isn't one assigned, it's an error?
2262 8 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum == 0) {
2263 0 : ShowSevereError(state,
2264 0 : std::string{RoutineName} + "No matching Air Distribution Unit, for System = [" +
2265 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + ',' +
2266 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName + "].");
2267 0 : ShowContinueError(
2268 : state,
2269 0 : "...should have outlet node = " +
2270 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode));
2271 0 : ErrorsFound = true;
2272 : } else {
2273 :
2274 : // Fill the Zone Equipment data with the inlet node number of this unit.
2275 : // what if not found? error?
2276 8 : IsNotOK = true;
2277 64 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
2278 56 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
2279 80 : for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
2280 80 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode ==
2281 40 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
2282 8 : IsNotOK = false;
2283 8 : if (state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
2284 0 : ShowSevereError(state, "Error in connecting a terminal unit to a zone");
2285 0 : ShowContinueError(state,
2286 0 : state.dataLoopNodes->NodeID(
2287 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode) +
2288 : " already connects to another zone");
2289 0 : ShowContinueError(state,
2290 0 : "Occurs for terminal unit " +
2291 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2292 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2293 0 : ShowContinueError(state, "Check terminal unit node names for errors");
2294 0 : ErrorsFound = true;
2295 : } else {
2296 8 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode =
2297 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum;
2298 8 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode =
2299 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode;
2300 8 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
2301 16 : .TermUnitSizingNum = state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
2302 8 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ADUNum)
2303 16 : .ZoneEqNum = CtrlZone;
2304 : }
2305 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneNum = CtrlZone;
2306 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).CtrlZoneInNodeIndex = SupAirIn;
2307 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneFloorArea =
2308 16 : state.dataHeatBal->Zone(CtrlZone).FloorArea * state.dataHeatBal->Zone(CtrlZone).Multiplier *
2309 8 : state.dataHeatBal->Zone(CtrlZone).ListMultiplier;
2310 : }
2311 : }
2312 : }
2313 : }
2314 8 : if (IsNotOK) {
2315 0 : ShowWarningError(state, "Did not Match Supply Air Outlet Node to any Zone Node");
2316 0 : ShowContinueError(state,
2317 0 : "..Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2318 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2319 : }
2320 :
2321 8 : if (lAlphaBlanks(9)) {
2322 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFrac = 1.0;
2323 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchExist = false;
2324 : } else {
2325 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchPtr = GetScheduleIndex(state, Alphas(9));
2326 0 : if (state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchPtr == 0) {
2327 0 : ShowSevereError(state, cAlphaFields(9) + " = " + Alphas(9) + " not found.");
2328 0 : ShowContinueError(state,
2329 0 : "Occurs in " + state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType + " = " +
2330 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2331 0 : ErrorsFound = true;
2332 : }
2333 0 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ZoneTurndownMinAirFracSchExist = true;
2334 : }
2335 :
2336 : // Add reheat coil to component sets array
2337 48 : SetUpCompSets(state,
2338 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
2339 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
2340 8 : Alphas(7),
2341 8 : Alphas(8),
2342 8 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum),
2343 8 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).ReheatAirOutletNode));
2344 : // Add fan to component sets array
2345 48 : SetUpCompSets(state,
2346 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).sysType,
2347 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName,
2348 8 : Alphas(5),
2349 8 : Alphas(6),
2350 8 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).InletNodeNum),
2351 8 : state.dataLoopNodes->NodeID(state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).OutletNodeNum));
2352 :
2353 : // Setup the Average damper Position output variable
2354 32 : SetupOutputVariable(state,
2355 : "Zone Air Terminal VAV Damper Position",
2356 : OutputProcessor::Unit::None,
2357 8 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).DamperPosition,
2358 : OutputProcessor::SOVTimeStepType::System,
2359 : OutputProcessor::SOVStoreType::Average,
2360 16 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysNumGSI).SysName);
2361 : }
2362 :
2363 : // common report variable for all single duct air terminals
2364 3813 : for (int sdIndex = 1; sdIndex <= state.dataSingleDuct->NumSDAirTerminal; ++sdIndex) {
2365 13236 : SetupOutputVariable(state,
2366 : "Zone Air Terminal Outdoor Air Volume Flow Rate",
2367 : OutputProcessor::Unit::m3_s,
2368 3309 : state.dataSingleDuct->sd_airterminal(sdIndex).OutdoorAirFlowRate,
2369 : OutputProcessor::SOVTimeStepType::System,
2370 : OutputProcessor::SOVStoreType::Average,
2371 6618 : state.dataSingleDuct->sd_airterminal(sdIndex).SysName);
2372 : }
2373 :
2374 : // Error check to see if a single duct air terminal is assigned to zone that has zone secondary recirculation
2375 : // specified in the Sizing:Zone object
2376 :
2377 504 : NumZoneSiz = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Sizing:Zone");
2378 504 : if (NumZoneSiz > 0) {
2379 3199 : for (state.dataSingleDuct->SysIndexGSI = 1; state.dataSingleDuct->SysIndexGSI <= state.dataSingleDuct->NumSDAirTerminal;
2380 2861 : ++state.dataSingleDuct->SysIndexGSI) {
2381 98707 : for (ZoneSizIndex = 1; ZoneSizIndex <= NumZoneSiz; ++ZoneSizIndex) {
2382 95850 : if (state.dataGlobal->DoZoneSizing) {
2383 191146 : if (state.dataSize->FinalZoneSizing(ZoneSizIndex).ZoneNum ==
2384 95573 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysIndexGSI).CtrlZoneNum) {
2385 2509 : if (state.dataSize->FinalZoneSizing(ZoneSizIndex).ZoneSecondaryRecirculation > 0.0) {
2386 12 : ShowWarningError(state,
2387 8 : std::string{RoutineName} + "A zone secondary recirculation fraction is specified for zone served by ");
2388 12 : ShowContinueError(state,
2389 8 : "...terminal unit \"" +
2390 12 : state.dataSingleDuct->sd_airterminal(state.dataSingleDuct->SysIndexGSI).SysName +
2391 : "\" , that indicates a single path system");
2392 4 : ShowContinueError(state, "...The zone secondary recirculation for that zone was set to 0.0");
2393 4 : state.dataSize->FinalZoneSizing(ZoneSizIndex).ZoneSecondaryRecirculation = 0.0;
2394 4 : goto SizLoop_exit;
2395 : }
2396 : }
2397 : }
2398 : }
2399 2857 : SizLoop_exit:;
2400 : }
2401 : }
2402 :
2403 504 : Alphas.deallocate();
2404 504 : cAlphaFields.deallocate();
2405 504 : cNumericFields.deallocate();
2406 504 : Numbers.deallocate();
2407 504 : lAlphaBlanks.deallocate();
2408 504 : lNumericBlanks.deallocate();
2409 :
2410 504 : if (ErrorsFound) {
2411 0 : ShowFatalError(state, std::string{RoutineName} + "Errors found in input. Preceding condition(s) cause termination.");
2412 : }
2413 504 : }
2414 :
2415 : // End of Get Input subroutines for the Module
2416 : //******************************************************************************
2417 :
2418 : // Beginning Initialization Section of the Module
2419 : //******************************************************************************
2420 :
2421 32682712 : void SingleDuctAirTerminal::InitSys(EnergyPlusData &state, bool const FirstHVACIteration)
2422 : {
2423 :
2424 : // SUBROUTINE INFORMATION:
2425 : // AUTHOR Richard J. Liesen
2426 : // DATE WRITTEN January 2000
2427 : // MODIFIED na
2428 : // RE-ENGINEERED na
2429 :
2430 : // PURPOSE OF THIS SUBROUTINE:
2431 : // This subroutine is for initializations of the Sys Components.
2432 :
2433 : // METHODOLOGY EMPLOYED:
2434 : // Uses the status flags to trigger events.
2435 :
2436 : // Using/Aliasing
2437 :
2438 : using DataZoneEquipment::CheckZoneEquipmentList;
2439 : using PlantUtilities::InitComponentNodes;
2440 : using PlantUtilities::ScanPlantLoopsForObject;
2441 32682712 : auto &GetHeatingCoilCapacity(HeatingCoils::GetCoilCapacity);
2442 :
2443 : // SUBROUTINE PARAMETER DEFINITIONS:
2444 : static constexpr std::string_view RoutineName("InitSys");
2445 : static constexpr std::string_view RoutineNameFull("InitHVACSingleDuct");
2446 :
2447 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2448 : int InletNode;
2449 : int OutletNode;
2450 : int SysIndex;
2451 : // static Array1D_bool MyEnvrnFlag;
2452 : // static Array1D_bool MySizeFlag;
2453 : // static Array1D_bool GetGasElecHeatCoilCap; // Gets autosized value of coil capacity
2454 : Real64 SteamTemp;
2455 : Real64 SteamDensity;
2456 : Real64 rho;
2457 : bool errFlag;
2458 :
2459 : // static Array1D_bool PlantLoopScanFlag;
2460 :
2461 : // Do the Begin Simulation initializations
2462 32682712 : if (state.dataSingleDuct->InitSysFlag) {
2463 :
2464 : // MyEnvrnFlag.allocate(NumSDAirTerminal);
2465 : // MySizeFlag.allocate(NumSDAirTerminal);
2466 : // PlantLoopScanFlag.allocate(NumSDAirTerminal);
2467 : // GetGasElecHeatCoilCap.allocate(NumSDAirTerminal);
2468 : // MyEnvrnFlag = true;
2469 : // MySizeFlag = true;
2470 : // PlantLoopScanFlag = true;
2471 : // GetGasElecHeatCoilCap = true;
2472 504 : state.dataSingleDuct->InitSysFlag = false;
2473 : }
2474 :
2475 32682712 : if (this->PlantLoopScanFlag && allocated(state.dataPlnt->PlantLoop)) {
2476 4611 : if ((this->ReheatComp_PlantType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) ||
2477 1302 : (this->ReheatComp_PlantType == DataPlant::PlantEquipmentType::CoilSteamAirHeating)) {
2478 : // setup plant topology indices for plant fed heating coils
2479 2015 : errFlag = false;
2480 2015 : ScanPlantLoopsForObject(state, this->ReheatName, this->ReheatComp_PlantType, this->HWplantLoc, errFlag, _, _, _, _, _);
2481 :
2482 2015 : if (errFlag) {
2483 0 : ShowContinueError(state, "Reference Unit=\"" + this->SysName + "\", type=" + this->sysType);
2484 0 : ShowFatalError(state, "InitSys: Program terminated for previous conditions.");
2485 : }
2486 :
2487 2015 : this->ReheatCoilOutletNode = DataPlant::CompData::getPlantComponent(state, this->HWplantLoc).NodeNumOut;
2488 :
2489 2015 : this->PlantLoopScanFlag = false;
2490 : } else {
2491 1294 : this->PlantLoopScanFlag = false;
2492 : }
2493 32679403 : } else if (this->PlantLoopScanFlag && !state.dataGlobal->AnyPlantInModel) {
2494 0 : this->PlantLoopScanFlag = false;
2495 : }
2496 :
2497 32682712 : if (!state.dataSingleDuct->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
2498 504 : state.dataSingleDuct->ZoneEquipmentListChecked = true;
2499 : // Check to see if there is a Air Distribution Unit on the Zone Equipment List
2500 3813 : for (SysIndex = 1; SysIndex <= state.dataSingleDuct->NumSDAirTerminal; ++SysIndex) {
2501 3309 : if (state.dataSingleDuct->sd_airterminal(SysIndex).ADUNum == 0) continue;
2502 9927 : if (CheckZoneEquipmentList(state,
2503 : "ZoneHVAC:AirDistributionUnit",
2504 6618 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(SysIndex).ADUNum).Name))
2505 3309 : continue;
2506 0 : ShowSevereError(state,
2507 0 : "InitSingleDuctSystems: ADU=[Air Distribution Unit," +
2508 0 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->sd_airterminal(SysIndex).ADUNum).Name +
2509 : "] is not on any ZoneHVAC:EquipmentList.");
2510 0 : ShowContinueError(state,
2511 0 : "...System=[" + state.dataSingleDuct->sd_airterminal(SysIndex).sysType + ',' +
2512 0 : state.dataSingleDuct->sd_airterminal(SysIndex).SysName + "] will not be simulated.");
2513 : }
2514 : }
2515 :
2516 : // get current time step air terminal box turndown minimum flow fraction
2517 32682712 : if (this->ZoneTurndownMinAirFracSchExist) {
2518 18720 : this->ZoneTurndownMinAirFrac = ScheduleManager::GetCurrentScheduleValue(state, this->ZoneTurndownMinAirFracSchPtr);
2519 : } else {
2520 32663992 : this->ZoneTurndownMinAirFrac = 1.0;
2521 : }
2522 :
2523 32682712 : if (!state.dataGlobal->SysSizingCalc && this->MySizeFlag) {
2524 :
2525 3304 : this->SizeSys(state);
2526 :
2527 3304 : this->MySizeFlag = false;
2528 : }
2529 :
2530 32682712 : if (this->GetGasElecHeatCoilCap) {
2531 3309 : if (this->ReheatComp_Num == HeatingCoilType::Electric || this->ReheatComp_Num == HeatingCoilType::Gas) {
2532 367 : if (this->ReheatCoilMaxCapacity == AutoSize) {
2533 0 : errFlag = false;
2534 0 : this->ReheatCoilMaxCapacity = GetHeatingCoilCapacity(state, this->ReheatComp, this->ReheatName, errFlag);
2535 0 : if (errFlag) ShowContinueError(state, "Occurs for terminal unit " + this->sysType + " = " + this->SysName);
2536 : }
2537 734 : if (this->ReheatCoilMaxCapacity != AutoSize) {
2538 367 : this->GetGasElecHeatCoilCap = false;
2539 : }
2540 : } else {
2541 2942 : this->GetGasElecHeatCoilCap = false;
2542 : }
2543 : }
2544 :
2545 : // Do the Begin Environment initializations
2546 32682712 : if (state.dataGlobal->BeginEnvrnFlag && this->MyEnvrnFlag) {
2547 :
2548 : // Set the outlet node max mass flow rate to the Max Air Flow specified for the Sys
2549 21199 : OutletNode = this->OutletNodeNum;
2550 21199 : InletNode = this->InletNodeNum;
2551 21199 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMax = this->MaxAirVolFlowRate * state.dataEnvrn->StdRhoAir;
2552 21199 : this->AirMassFlowRateMax = this->MaxAirVolFlowRate * state.dataEnvrn->StdRhoAir;
2553 21199 : this->HeatAirMassFlowRateMax = this->MaxHeatAirVolFlowRate * state.dataEnvrn->StdRhoAir;
2554 21199 : state.dataLoopNodes->Node(InletNode).MassFlowRateMax = this->MaxAirVolFlowRate * state.dataEnvrn->StdRhoAir;
2555 21199 : this->MassFlowDiff = 1.0e-10 * this->AirMassFlowRateMax;
2556 :
2557 21199 : if (this->HWplantLoc.loopNum > 0 && this->ReheatComp_Num != HeatingCoilType::SteamAirHeating) { // protect early calls before plant is setup
2558 27066 : rho = GetDensityGlycol(state,
2559 13533 : state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).FluidName,
2560 : DataGlobalConstants::HWInitConvTemp,
2561 13533 : state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).FluidIndex,
2562 : RoutineName);
2563 : } else {
2564 7666 : rho = 1000.0;
2565 : }
2566 :
2567 21199 : this->MaxReheatWaterFlow = rho * this->MaxReheatWaterVolFlow;
2568 21199 : this->MinReheatWaterFlow = rho * this->MinReheatWaterVolFlow;
2569 :
2570 21199 : this->AirMassFlowDuringReheatMax = this->MaxAirVolFlowRateDuringReheat * state.dataEnvrn->StdRhoAir;
2571 :
2572 : // set the upstream leakage flowrate - remove from here - done in ZoneAirLoopEquipmentManager::SimZoneAirLoopEquipment
2573 :
2574 21199 : if (this->ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
2575 48 : SteamTemp = 100.0;
2576 48 : SteamDensity = GetSatDensityRefrig(state, fluidNameSteam, SteamTemp, 1.0, this->FluidIndex, RoutineNameFull);
2577 48 : this->MaxReheatSteamFlow = SteamDensity * this->MaxReheatSteamVolFlow;
2578 48 : this->MinReheatSteamFlow = SteamDensity * this->MinReheatSteamVolFlow;
2579 : }
2580 :
2581 : // get current environment air terminal box turndown minimum flow fraction
2582 21199 : Real64 CurrentEnvZoneTurndownMinAirFrac = 1.0;
2583 21199 : if (this->ZoneTurndownMinAirFracSchExist) {
2584 80 : CurrentEnvZoneTurndownMinAirFrac = ScheduleManager::GetScheduleMinValue(state, this->ZoneTurndownMinAirFracSchPtr);
2585 : }
2586 28325 : if ((this->SysType_Num == SysType::SingleDuctVAVReheat || this->SysType_Num == SysType::SingleDuctCBVAVReheat) ||
2587 7126 : (this->SysType_Num == SysType::SingleDuctCBVAVNoReheat)) {
2588 : // need the lowest schedule value
2589 14093 : if (this->ZoneMinAirFracMethod == MinFlowFraction::Scheduled) {
2590 218 : this->ZoneMinAirFracDes = GetScheduleMinValue(state, this->ZoneMinAirFracSchPtr);
2591 : }
2592 14093 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMin =
2593 14093 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMax * this->ZoneMinAirFracDes * CurrentEnvZoneTurndownMinAirFrac;
2594 14093 : state.dataLoopNodes->Node(InletNode).MassFlowRateMin =
2595 14093 : state.dataLoopNodes->Node(InletNode).MassFlowRateMax * this->ZoneMinAirFracDes * CurrentEnvZoneTurndownMinAirFrac;
2596 : } else {
2597 7106 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMin = 0.0;
2598 7106 : state.dataLoopNodes->Node(InletNode).MassFlowRateMin = 0.0;
2599 : }
2600 21199 : if ((this->ReheatControlNode > 0) && !this->PlantLoopScanFlag) {
2601 13581 : if (this->ReheatComp_Num == HeatingCoilType::SteamAirHeating) {
2602 48 : InitComponentNodes(state, this->MinReheatSteamFlow, this->MaxReheatSteamFlow, this->ReheatControlNode, this->ReheatCoilOutletNode);
2603 : } else {
2604 13533 : InitComponentNodes(state, this->MinReheatWaterFlow, this->MaxReheatWaterFlow, this->ReheatControlNode, this->ReheatCoilOutletNode);
2605 : }
2606 : }
2607 : // Find air loop associated with terminal unit
2608 21199 : if ((this->CtrlZoneNum > 0) && (this->CtrlZoneInNodeIndex > 0)) {
2609 21199 : this->AirLoopNum = state.dataZoneEquip->ZoneEquipConfig(this->CtrlZoneNum).InletNodeAirLoopNum(this->CtrlZoneInNodeIndex);
2610 21199 : state.dataDefineEquipment->AirDistUnit(this->ADUNum).AirLoopNum = this->AirLoopNum;
2611 : }
2612 :
2613 21199 : this->MyEnvrnFlag = false;
2614 : }
2615 :
2616 32682712 : if (!state.dataGlobal->BeginEnvrnFlag) {
2617 32532951 : this->MyEnvrnFlag = true;
2618 : }
2619 :
2620 : // Initialize the Inlet Nodes of the air side of air terminal
2621 32682712 : InletNode = this->InletNodeNum;
2622 32682712 : OutletNode = this->OutletNodeNum;
2623 :
2624 32682712 : Real64 mDotFromOARequirement(0.0);
2625 :
2626 32682712 : if (this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
2627 7471141 : if (!this->NoOAFlowInputFromUser) {
2628 6382 : mDotFromOARequirement = this->AirMassFlowRateMax;
2629 6382 : int airLoopNum(0);
2630 6382 : Real64 airLoopOAFrac(0.0);
2631 6382 : airLoopNum = this->AirLoopNum;
2632 6382 : if (airLoopNum > 0) {
2633 6373 : airLoopOAFrac = state.dataAirLoop->AirLoopFlow(airLoopNum).OAFrac;
2634 6373 : bool UseOccSchFlag = false;
2635 6373 : if (this->OAPerPersonMode == DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel) UseOccSchFlag = true;
2636 6373 : if (airLoopOAFrac > 0.0) {
2637 : Real64 vDotOAReq =
2638 6357 : DataSizing::calcDesignSpecificationOutdoorAir(state, this->OARequirementsPtr, this->CtrlZoneNum, UseOccSchFlag, true);
2639 6357 : mDotFromOARequirement = vDotOAReq * state.dataEnvrn->StdRhoAir / airLoopOAFrac;
2640 6357 : mDotFromOARequirement = min(mDotFromOARequirement, this->AirMassFlowRateMax);
2641 : } else {
2642 16 : mDotFromOARequirement = this->AirMassFlowRateMax;
2643 : }
2644 : }
2645 : }
2646 : }
2647 :
2648 32682712 : if (this->ZoneMinAirFracMethod == MinFlowFraction::Scheduled) {
2649 292010 : this->ZoneMinAirFracDes = GetCurrentScheduleValue(state, this->ZoneMinAirFracSchPtr);
2650 : // now reset inlet node min avail
2651 292010 : state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = this->AirMassFlowRateMax * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac;
2652 : }
2653 :
2654 32682712 : if (FirstHVACIteration) {
2655 : // The first time through set the mass flow rate to the Max
2656 12654999 : if ((state.dataLoopNodes->Node(InletNode).MassFlowRate > 0.0) && (GetCurrentScheduleValue(state, this->SchedPtr) > 0.0)) {
2657 10088615 : if (!(state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated)) {
2658 10088599 : state.dataLoopNodes->Node(InletNode).MassFlowRate = this->AirMassFlowRateMax;
2659 : }
2660 : } else {
2661 2566384 : state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
2662 : }
2663 12654999 : if ((state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail > 0.0) && (GetCurrentScheduleValue(state, this->SchedPtr) > 0.0)) {
2664 10088922 : if (!(state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated)) {
2665 10088906 : if (this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
2666 2221516 : if (this->NoOAFlowInputFromUser) {
2667 2218333 : state.dataLoopNodes->Node(InletNode).MassFlowRate = this->AirMassFlowRateMax;
2668 2218333 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = this->AirMassFlowRateMax;
2669 : } else {
2670 3183 : state.dataLoopNodes->Node(InletNode).MassFlowRate = mDotFromOARequirement;
2671 3183 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = mDotFromOARequirement;
2672 : }
2673 2221516 : if (this->EMSOverrideAirFlow) {
2674 0 : state.dataLoopNodes->Node(InletNode).MassFlowRate = this->EMSMassFlowRateValue;
2675 0 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = this->EMSMassFlowRateValue;
2676 : }
2677 : } else {
2678 7867390 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = this->AirMassFlowRateMax;
2679 : }
2680 : }
2681 : } else {
2682 2566077 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = 0.0;
2683 : }
2684 :
2685 12654999 : if ((state.dataLoopNodes->Node(InletNode).MassFlowRate > 0.0) && (GetCurrentScheduleValue(state, this->SchedPtr) > 0.0)) {
2686 10088625 : if (!(state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated)) {
2687 10088609 : state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail =
2688 10088609 : this->AirMassFlowRateMax * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac;
2689 : }
2690 : } else {
2691 2566374 : state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = 0.0;
2692 : }
2693 : // reset the mass flow rate histories
2694 12654999 : this->MassFlow1 = 0.0;
2695 12654999 : this->MassFlow2 = 0.0;
2696 12654999 : this->MassFlow3 = 0.0;
2697 12654999 : this->MassFlow3 = 0.0;
2698 :
2699 : } else {
2700 20027713 : if (this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
2701 4662621 : if (!this->EMSOverrideAirFlow) {
2702 4662621 : if ((state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail > 0.0) && (GetCurrentScheduleValue(state, this->SchedPtr) > 0.0)) {
2703 4017174 : if (this->NoOAFlowInputFromUser) {
2704 4013996 : if (state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail < state.dataLoopNodes->Node(InletNode).MassFlowRateMax) {
2705 1350735 : state.dataLoopNodes->Node(InletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail;
2706 2663261 : } else if (state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail > state.dataLoopNodes->Node(InletNode).MassFlowRateMin) {
2707 50361 : state.dataLoopNodes->Node(InletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail;
2708 : } else {
2709 2612900 : state.dataLoopNodes->Node(InletNode).MassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail;
2710 : }
2711 : } else {
2712 3178 : state.dataLoopNodes->Node(InletNode).MassFlowRate = mDotFromOARequirement;
2713 : // but also apply constraints
2714 3178 : state.dataLoopNodes->Node(InletNode).MassFlowRate =
2715 3178 : min(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail);
2716 3178 : state.dataLoopNodes->Node(InletNode).MassFlowRate =
2717 3178 : min(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMax);
2718 3178 : state.dataLoopNodes->Node(InletNode).MassFlowRate =
2719 3178 : max(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail);
2720 3178 : state.dataLoopNodes->Node(InletNode).MassFlowRate =
2721 3178 : max(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMin);
2722 : }
2723 : } else {
2724 645447 : state.dataLoopNodes->Node(InletNode).MassFlowRate = 0.0;
2725 645447 : state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail = 0.0;
2726 645447 : state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail = 0.0;
2727 : }
2728 : } else { // EMS override on
2729 0 : state.dataLoopNodes->Node(InletNode).MassFlowRate = this->EMSMassFlowRateValue;
2730 : // but also apply constraints
2731 0 : state.dataLoopNodes->Node(InletNode).MassFlowRate =
2732 0 : min(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail);
2733 0 : state.dataLoopNodes->Node(InletNode).MassFlowRate =
2734 0 : min(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMax);
2735 0 : state.dataLoopNodes->Node(InletNode).MassFlowRate =
2736 0 : max(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail);
2737 0 : state.dataLoopNodes->Node(InletNode).MassFlowRate =
2738 0 : max(state.dataLoopNodes->Node(InletNode).MassFlowRate, state.dataLoopNodes->Node(InletNode).MassFlowRateMin);
2739 : }
2740 : }
2741 : }
2742 :
2743 : // Do a check and make sure that the max and min available(control) flow is
2744 : // between the physical max and min while operating.
2745 32682712 : this->sd_airterminalInlet.AirMassFlowRateMaxAvail = min(this->AirMassFlowRateMax, state.dataLoopNodes->Node(InletNode).MassFlowRateMaxAvail);
2746 32682712 : this->sd_airterminalInlet.AirMassFlowRateMinAvail =
2747 32682712 : min(max(state.dataLoopNodes->Node(OutletNode).MassFlowRateMin, state.dataLoopNodes->Node(InletNode).MassFlowRateMinAvail),
2748 : this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
2749 :
2750 : // Do the following initializations (every time step): This should be the info from
2751 : // the previous components outlets or the node data in this section.
2752 : // Load the node data in this section for the component simulation
2753 32682712 : this->sd_airterminalInlet.AirMassFlowRate = state.dataLoopNodes->Node(InletNode).MassFlowRate;
2754 32682712 : this->sd_airterminalInlet.AirTemp = state.dataLoopNodes->Node(InletNode).Temp;
2755 32682712 : this->sd_airterminalInlet.AirHumRat = state.dataLoopNodes->Node(InletNode).HumRat;
2756 32682712 : this->sd_airterminalInlet.AirEnthalpy = state.dataLoopNodes->Node(InletNode).Enthalpy;
2757 :
2758 : // update to the current minimum air flow fraction
2759 32682712 : this->ZoneMinAirFrac = this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac;
2760 32682712 : }
2761 :
2762 3304 : void SingleDuctAirTerminal::SizeSys(EnergyPlusData &state)
2763 : {
2764 :
2765 : // SUBROUTINE INFORMATION:
2766 : // AUTHOR Fred Buhl
2767 : // DATE WRITTEN September 2001
2768 : // MODIFIED August 2013 Daeho Kang, add component sizing table entries
2769 :
2770 : // PURPOSE OF THIS SUBROUTINE:
2771 : // This subroutine is for sizing Sys Components for which flow rates have not been
2772 : // specified in the input.
2773 :
2774 : // METHODOLOGY EMPLOYED:
2775 : // Obtains flow rates from the zone or system sizing arrays.
2776 :
2777 : // Using/Aliasing
2778 : using FluidProperties::GetDensityGlycol;
2779 : using FluidProperties::GetSpecificHeatGlycol;
2780 : using General::SafeDivide;
2781 : using PlantUtilities::MyPlantSizingIndex;
2782 : using SteamCoils::GetCoilSteamInletNode;
2783 : using SteamCoils::GetCoilSteamOutletNode;
2784 : using WaterCoils::GetCoilWaterInletNode;
2785 : using WaterCoils::GetCoilWaterOutletNode;
2786 : using WaterCoils::SetCoilDesFlow;
2787 :
2788 : // SUBROUTINE PARAMETER DEFINITIONS:
2789 : static constexpr std::string_view RoutineName("SizeSys");
2790 : static constexpr std::string_view RoutineNameFull("SizeHVACSingleDuct");
2791 :
2792 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2793 : int PltSizHeatNum; // index of plant sizing object for 1st heating loop
2794 : Real64 DesMassFlow;
2795 : Real64 TempSteamIn;
2796 : Real64 EnthSteamOutWet;
2797 : Real64 EnthSteamInDry;
2798 : Real64 LatentHeatSteam;
2799 : Real64 SteamDensity;
2800 :
2801 : bool ErrorsFound;
2802 : bool PlantSizingErrorsFound;
2803 : Real64 rho; // local fluid density
2804 : Real64 Cp; // local fluid specific heat
2805 : bool IsAutoSize;
2806 : bool IsMaxFlowAutoSize; // Indicate if the maximum terminal flow is autosize
2807 : int AirLoopNum; // Air loop number
2808 : int SysSizNum; // System sizing number
2809 3304 : Real64 MinMinFlowRatio(0.0); // the minimum minimum flow ratio
2810 : Real64 MaxAirVolFlowRateDes; // Autosized maximum air flow rate for reporting
2811 : Real64 MaxAirVolFlowRateUser; // Hardsized maximum air flow rate for reporting
2812 : Real64 MaxHeatAirVolFlowRateDes; // Autosized maximum heating air flow rate for reporting
2813 : Real64 MaxHeatAirVolFlowRateUser; // Hardsized maximum heating air flow rate for reporting
2814 : Real64 MinAirFlowFracDes; // Autosized minimum cooling air flow fraction for reporting
2815 : Real64 MinAirFlowFracUser; // User input minimum cooling air flow fraction for reporting
2816 : Real64 FixedMinAirDes; // Autosized minimum cooling air flow rate for reporting [m3/s]
2817 : Real64 FixedMinAirUser; // User input minimum cooling air flow rate for reporting [m3/s]
2818 : Real64 MaxAirVolFlowRateDuringReheatDes; // Autosized maximum air flow durign reheat for reporting
2819 : Real64 MaxAirVolFlowRateDuringReheatUser; // Hardsized maximum air flow durign reheat for reporting
2820 : Real64 MaxAirVolFractionDuringReheatDes; // Autosized maximum air fraction durign reheat for reporting
2821 : Real64 MaxAirVolFractionDuringReheatUser; // Hardsized maximum air flow durign reheat for reporting
2822 : Real64 MaxReheatWaterVolFlowDes; // Autosized reheat water flow or reporting
2823 : Real64 MaxReheatWaterVolFlowUser; // Hardsized reheat water flow for reporting
2824 : Real64 MaxReheatSteamVolFlowDes; // Autosized reheat steam flow for reporting
2825 : Real64 MaxReheatSteamVolFlowUser; // Hardsized reheat steam flow for reporting
2826 :
2827 3304 : PltSizHeatNum = 0;
2828 3304 : DesMassFlow = 0.0;
2829 3304 : ErrorsFound = false;
2830 3304 : IsAutoSize = false;
2831 3304 : IsMaxFlowAutoSize = false;
2832 3304 : MaxAirVolFlowRateDes = 0.0;
2833 3304 : MaxAirVolFlowRateUser = 0.0;
2834 3304 : MaxHeatAirVolFlowRateDes = 0.0;
2835 3304 : MaxHeatAirVolFlowRateUser = 0.0;
2836 3304 : MinAirFlowFracDes = 0.0;
2837 3304 : MinAirFlowFracUser = 0.0;
2838 3304 : FixedMinAirDes = 0.0;
2839 3304 : FixedMinAirUser = 0.0;
2840 3304 : MaxAirVolFlowRateDuringReheatDes = 0.0;
2841 3304 : MaxAirVolFlowRateDuringReheatUser = 0.0;
2842 3304 : MaxAirVolFractionDuringReheatDes = 0.0;
2843 3304 : MaxAirVolFractionDuringReheatUser = 0.0;
2844 3304 : MaxReheatWaterVolFlowDes = 0.0;
2845 3304 : MaxReheatWaterVolFlowUser = 0.0;
2846 3304 : MaxReheatSteamVolFlowDes = 0.0;
2847 3304 : MaxReheatSteamVolFlowUser = 0.0;
2848 3304 : MinMinFlowRatio = 0.0;
2849 3304 : AirLoopNum = 0;
2850 3304 : SysSizNum = 0;
2851 :
2852 3304 : int ZoneNum = this->CtrlZoneNum;
2853 :
2854 3304 : auto &TermUnitSizing(state.dataSize->TermUnitSizing);
2855 :
2856 3304 : if (this->MaxAirVolFlowRate == AutoSize) {
2857 2738 : IsAutoSize = true;
2858 : }
2859 :
2860 3304 : if (state.dataSize->CurTermUnitSizingNum > 0) {
2861 3304 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
2862 507 : if (this->MaxAirVolFlowRate > 0.0) {
2863 1014 : BaseSizer::reportSizerOutput(
2864 507 : state, this->sysType, this->SysName, "User-Specified Maximum Air Flow Rate [m3/s]", this->MaxAirVolFlowRate);
2865 : }
2866 : } else { // Autosize or hard-size with sizing run
2867 :
2868 2797 : CheckZoneSizing(state, this->sysType, this->SysName);
2869 :
2870 2797 : MaxAirVolFlowRateDes = max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlow,
2871 2797 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow);
2872 :
2873 2797 : if (MaxAirVolFlowRateDes < SmallAirVolFlow) {
2874 0 : MaxAirVolFlowRateDes = 0.0;
2875 : }
2876 2797 : if (IsAutoSize) {
2877 2738 : this->MaxAirVolFlowRate = MaxAirVolFlowRateDes;
2878 2738 : IsMaxFlowAutoSize = true;
2879 2738 : BaseSizer::reportSizerOutput(state, this->sysType, this->SysName, "Design Size Maximum Air Flow Rate [m3/s]", MaxAirVolFlowRateDes);
2880 : } else { // Hard-size with sizing data
2881 59 : if (this->MaxAirVolFlowRate > 0.0 && MaxAirVolFlowRateDes > 0.0) {
2882 59 : MaxAirVolFlowRateUser = this->MaxAirVolFlowRate;
2883 118 : BaseSizer::reportSizerOutput(state,
2884 : this->sysType,
2885 : this->SysName,
2886 : "Design Size Maximum Air Flow Rate [m3/s]",
2887 : MaxAirVolFlowRateDes,
2888 : "User-Specified Maximum Air Flow Rate [m3/s]",
2889 59 : MaxAirVolFlowRateUser);
2890 59 : if (state.dataGlobal->DisplayExtraWarnings) {
2891 0 : if ((std::abs(MaxAirVolFlowRateDes - MaxAirVolFlowRateUser) / MaxAirVolFlowRateUser) >
2892 0 : state.dataSize->AutoVsHardSizingThreshold) {
2893 0 : ShowMessage(state,
2894 0 : "SizeHVACSingleDuct: Potential issue with equipment sizing for " + this->sysType + " = \"" + this->SysName +
2895 : "\".");
2896 0 : ShowContinueError(state, format("User-Specified Maximum Air Flow Rate of {:.5R} [m3/s]", MaxAirVolFlowRateUser));
2897 0 : ShowContinueError(state, format("differs from Design Size Maximum Air Flow Rate of {:.5R} [m3/s]", MaxAirVolFlowRateDes));
2898 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
2899 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
2900 : }
2901 : }
2902 : }
2903 : }
2904 : }
2905 : }
2906 :
2907 3304 : IsAutoSize = false;
2908 3304 : if (this->MaxHeatAirVolFlowRate == AutoSize) {
2909 8 : IsAutoSize = true;
2910 : }
2911 3304 : if (state.dataSize->CurTermUnitSizingNum > 0) {
2912 3304 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation should continue
2913 507 : state.dataSingleDuct->UserInputMaxHeatAirVolFlowRateSS = this->MaxHeatAirVolFlowRate;
2914 507 : if (this->MaxHeatAirVolFlowRate > 0.0) {
2915 0 : BaseSizer::reportSizerOutput(
2916 0 : state, this->sysType, this->SysName, "User-Specified Maximum Heating Air Flow Rate [m3/s]", this->MaxHeatAirVolFlowRate);
2917 : }
2918 : } else {
2919 2797 : CheckZoneSizing(state, this->sysType, this->SysName);
2920 2797 : MaxHeatAirVolFlowRateDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow;
2921 2797 : if (MaxHeatAirVolFlowRateDes < SmallAirVolFlow) {
2922 9 : MaxHeatAirVolFlowRateDes = 0.0;
2923 : }
2924 2797 : if (IsAutoSize) {
2925 8 : this->MaxHeatAirVolFlowRate = MaxHeatAirVolFlowRateDes;
2926 8 : state.dataSingleDuct->UserInputMaxHeatAirVolFlowRateSS = 0.0;
2927 16 : BaseSizer::reportSizerOutput(
2928 8 : state, this->sysType, this->SysName, "Design Size Maximum Heating Air Flow Rate [m3/s]", MaxHeatAirVolFlowRateDes);
2929 : } else { // Hard-size with sizing data
2930 2789 : if (this->MaxHeatAirVolFlowRate > 0.0 && MaxHeatAirVolFlowRateDes > 0.0) {
2931 0 : MaxHeatAirVolFlowRateUser = this->MaxHeatAirVolFlowRate;
2932 0 : state.dataSingleDuct->UserInputMaxHeatAirVolFlowRateSS = this->MaxHeatAirVolFlowRate;
2933 0 : BaseSizer::reportSizerOutput(state,
2934 : this->sysType,
2935 : this->SysName,
2936 : "Design Size Maximum Heating Air Flow Rate [m3/s]",
2937 : MaxHeatAirVolFlowRateDes,
2938 : "User-Specified Maximum Heating Air Flow Rate [m3/s]",
2939 0 : MaxHeatAirVolFlowRateUser);
2940 0 : if (state.dataGlobal->DisplayExtraWarnings) {
2941 0 : if ((std::abs(MaxHeatAirVolFlowRateDes - MaxHeatAirVolFlowRateUser) / MaxHeatAirVolFlowRateUser) >
2942 0 : state.dataSize->AutoVsHardSizingThreshold) {
2943 0 : ShowMessage(state,
2944 0 : "SizeHVACSingleDuct: Potential issue with equipment sizing for " + this->sysType + " = \"" + this->SysName +
2945 : "\".");
2946 0 : ShowContinueError(state,
2947 0 : format("User-Specified Maximum Heating Air Flow Rate of {:.5R} [m3/s]", MaxHeatAirVolFlowRateUser));
2948 0 : ShowContinueError(
2949 0 : state, format("differs from Design Size Maximum Heating Air Flow Rate of {:.5R} [m3/s]", MaxHeatAirVolFlowRateDes));
2950 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
2951 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
2952 : }
2953 : }
2954 : }
2955 : }
2956 : }
2957 : }
2958 :
2959 : // get design day terminal unit turndown minimum flow fraction
2960 3304 : if (this->ZoneTurndownMinAirFracSchExist) {
2961 5 : this->ZoneTurndownMinAirFrac = ScheduleManager::GetCurrentScheduleValue(state, this->ZoneTurndownMinAirFracSchPtr);
2962 : } else {
2963 3299 : this->ZoneTurndownMinAirFrac = 1.0;
2964 : }
2965 :
2966 : // if a sizing run has been done, check if system sizing has been done for this system
2967 3304 : bool SizingDesRunThisAirSys = false;
2968 3304 : if (state.dataSize->SysSizingRunDone) {
2969 2772 : AirLoopNum = state.dataZoneEquip->ZoneEquipConfig(this->CtrlZoneNum).InletNodeAirLoopNum(this->CtrlZoneInNodeIndex);
2970 2772 : if (AirLoopNum > 0) {
2971 2772 : CheckThisAirSystemForSizing(state, AirLoopNum, SizingDesRunThisAirSys);
2972 : }
2973 :
2974 : // get system sizing id if a sizing run has been done for this system
2975 2772 : if (SizingDesRunThisAirSys) {
2976 5536 : SysSizNum = UtilityRoutines::FindItemInList(
2977 5536 : state.dataSize->FinalSysSizing(AirLoopNum).AirPriLoopName, state.dataSize->SysSizInput, &SystemSizingInputData::AirPriLoopName);
2978 2768 : if (SysSizNum == 0) SysSizNum = 1; // use first when none applicable
2979 : }
2980 : }
2981 :
2982 3304 : IsAutoSize = false;
2983 3304 : if (this->ZoneMinAirFracDes == AutoSize) {
2984 45 : IsAutoSize = true;
2985 : }
2986 3304 : if (this->ZoneMinAirFracMethod == MinFlowFraction::Constant) {
2987 2170 : if (state.dataSize->ZoneSizingRunDone) {
2988 2123 : if (state.dataSize->CurTermUnitSizingNum > 0) {
2989 : // use the combined defaults or other user inputs stored in DesCoolVolFlowMin
2990 2123 : if (this->MaxAirVolFlowRate > 0.0) {
2991 2123 : MinAirFlowFracDes = min(1.0,
2992 2123 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlowMin /
2993 2123 : this->MaxAirVolFlowRate);
2994 : } else {
2995 0 : MinAirFlowFracDes = 0.0;
2996 : }
2997 : }
2998 : } else {
2999 : // if no zone sizing values available; use max of min frac = 0.2 and 0.000762 [m3/s-m2]
3000 47 : if (this->MaxAirVolFlowRate > 0.0) {
3001 141 : MinMinFlowRatio = (0.000762 * state.dataHeatBal->Zone(ZoneNum).FloorArea * state.dataHeatBal->Zone(ZoneNum).Multiplier *
3002 47 : state.dataHeatBal->Zone(ZoneNum).ListMultiplier) /
3003 47 : this->MaxAirVolFlowRate;
3004 47 : MinAirFlowFracDes = max(0.2, MinMinFlowRatio);
3005 : } else {
3006 0 : MinAirFlowFracDes = 0.0;
3007 : }
3008 : }
3009 2170 : if (SizingDesRunThisAirSys) {
3010 2123 : if (state.dataSize->SysSizInput(SysSizNum).SystemOAMethod == SysOAMethod::SP) { // 62.1 simplified procedure
3011 4 : if (this->MaxAirVolFlowRate > 0.0) {
3012 8 : MinAirFlowFracDes = 1.5 *
3013 4 : max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VozClgByZone,
3014 8 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VozHtgByZone) /
3015 4 : this->MaxAirVolFlowRate;
3016 :
3017 : // adjust maximum flow rate
3018 4 : if (MinAirFlowFracDes > 1.0 && IsMaxFlowAutoSize) {
3019 0 : this->MaxAirVolFlowRate *= MinAirFlowFracDes;
3020 0 : MinAirFlowFracDes = 1.0;
3021 0 : ShowWarningError(state,
3022 0 : "SingleDuctSystem:SizeSys: Autosized maximum air flow rate for " + this->SysName +
3023 : " was increased to meet the zone primary air flow determined according to the ASHRAE Standard 62.1 "
3024 : "Simplified Procedure.");
3025 4 : } else if (MinAirFlowFracDes > 1.0) {
3026 0 : ShowWarningError(state, "SingleDuctSystem:SizeSys: Maximum air flow rate for " + this->SysName + " is potentially too low.");
3027 0 : ShowContinueError(
3028 : state,
3029 : "The flow is lower than the minimum flow rate calculated following the ASHRAE Standard 62.1 Simplified Procedure:");
3030 0 : ShowContinueError(state, format(" User-specified maximum air flow rate: {:.3R} m3/s.", this->MaxAirVolFlowRate));
3031 0 : ShowContinueError(state,
3032 0 : format(" Calculated minimum air flow rate: {:.3R} m3/s.", this->MaxAirVolFlowRate * MinAirFlowFracDes));
3033 0 : MinAirFlowFracDes = 1.0;
3034 : }
3035 : }
3036 : }
3037 : }
3038 2170 : if (IsAutoSize) {
3039 : // report out autosized result and save value in Sys array
3040 129 : BaseSizer::reportSizerOutput(state,
3041 : this->sysType,
3042 : this->SysName,
3043 : "Design Size Constant Minimum Air Flow Fraction",
3044 86 : MinAirFlowFracDes * this->ZoneTurndownMinAirFrac);
3045 43 : if (SizingDesRunThisAirSys) {
3046 43 : if (state.dataSize->SysSizInput(SysSizNum).SystemOAMethod == SysOAMethod::SP) {
3047 4 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VpzMinByZoneSPSized = true;
3048 : }
3049 : }
3050 43 : this->ZoneMinAirFracDes = MinAirFlowFracDes;
3051 : } else {
3052 : // report out hard (user set) value and issue warning if appropriate
3053 2127 : MinAirFlowFracUser = this->ZoneMinAirFracDes;
3054 6381 : BaseSizer::reportSizerOutput(state,
3055 : this->sysType,
3056 : this->SysName,
3057 : "Design Size Constant Minimum Air Flow Fraction",
3058 2127 : MinAirFlowFracDes * this->ZoneTurndownMinAirFrac,
3059 : "User-Specified Constant Minimum Air Flow Fraction",
3060 6381 : MinAirFlowFracUser * this->ZoneTurndownMinAirFrac);
3061 2127 : if (state.dataGlobal->DisplayExtraWarnings) {
3062 55 : if ((std::abs(MinAirFlowFracDes - MinAirFlowFracUser) / MinAirFlowFracUser) > state.dataSize->AutoVsHardSizingThreshold) {
3063 153 : ShowMessage(state,
3064 102 : "SizeHVACSingleDuct: Potential issue with equipment sizing for " + this->sysType + " = \"" + this->SysName + "\".");
3065 51 : ShowContinueError(state, format("User-Specified Minimum Cooling Air Flow Fraction of {:.5R} [m3/s]", MinAirFlowFracUser));
3066 153 : ShowContinueError(state,
3067 102 : format("differs from Design Size Minimum Cooling Air Flow Fraction of {:.5R} [m3/s]", MinAirFlowFracDes));
3068 51 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3069 51 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3070 : }
3071 : }
3072 : }
3073 : // report out the min air flow rate set by min air flow frac
3074 6510 : BaseSizer::reportSizerOutput(state,
3075 : this->sysType,
3076 : this->SysName,
3077 : "Design Size Minimum Air Flow Rate [m3/s]",
3078 4340 : this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac);
3079 : } else {
3080 1134 : if (IsAutoSize) {
3081 2 : this->ZoneMinAirFracDes = 0.0;
3082 : }
3083 : }
3084 :
3085 3304 : IsAutoSize = false;
3086 3304 : if (this->ZoneFixedMinAir == AutoSize) {
3087 2124 : IsAutoSize = true;
3088 : }
3089 3304 : if (this->ZoneMinAirFracMethod == MinFlowFraction::Fixed) {
3090 3 : if (state.dataSize->ZoneSizingRunDone) {
3091 2 : if (state.dataSize->CurTermUnitSizingNum > 0) {
3092 : // use the combined defaults or other user inputs stored in DesCoolVolFlowMin
3093 2 : if (this->MaxAirVolFlowRate > 0.0) {
3094 2 : FixedMinAirDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlowMin;
3095 : } else {
3096 0 : MinAirFlowFracDes = 0.0;
3097 : }
3098 : }
3099 : } else {
3100 : // if no zone sizing values available; use max of min frac = 0.2 and 0.000762 [m3/s-m2]
3101 1 : if (this->MaxAirVolFlowRate > 0.0) {
3102 1 : FixedMinAirDes = max(0.2 * this->MaxAirVolFlowRate,
3103 1 : 0.000762 * state.dataHeatBal->Zone(ZoneNum).FloorArea * state.dataHeatBal->Zone(ZoneNum).Multiplier *
3104 1 : state.dataHeatBal->Zone(ZoneNum).ListMultiplier);
3105 : } else {
3106 0 : MinAirFlowFracDes = 0.0;
3107 : }
3108 : }
3109 3 : if (SizingDesRunThisAirSys) {
3110 2 : if (state.dataSize->SysSizInput(SysSizNum).SystemOAMethod == SysOAMethod::SP) { // 62.1 simplified procedure
3111 2 : if (this->MaxAirVolFlowRate > 0.0) {
3112 2 : FixedMinAirDes = 1.5 * max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VozClgByZone,
3113 2 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VozHtgByZone);
3114 :
3115 : // adjust maximum flow rate
3116 2 : if (FixedMinAirDes > this->MaxAirVolFlowRate && IsMaxFlowAutoSize) {
3117 0 : this->MaxAirVolFlowRate = FixedMinAirDes;
3118 0 : ShowWarningError(state,
3119 0 : "SingleDuctSystem:SizeSys: Autosized maximum air flow rate for " + this->SysName +
3120 : " was increased to meet the zone primary air flow determined according to the ASHRAE Standard 62.1 "
3121 : "Simplified Procedure.");
3122 2 : } else if (FixedMinAirDes > this->MaxAirVolFlowRate) {
3123 0 : ShowWarningError(state, "SingleDuctSystem:SizeSys: Maximum air flow rate for " + this->SysName + " is potentially too low.");
3124 0 : ShowContinueError(
3125 : state,
3126 : "The flow is lower than the minimum flow rate calculated following the ASHRAE Standard 62.1 Simplified Procedure:");
3127 0 : ShowContinueError(state, format(" User-specified maximum air flow rate: {:.3R} m3/s.", this->MaxAirVolFlowRate));
3128 0 : ShowContinueError(state, format(" Calculated minimum air flow rate: {:.3R} m3/s.", FixedMinAirDes));
3129 0 : FixedMinAirDes = this->MaxAirVolFlowRate;
3130 : }
3131 : }
3132 : }
3133 : }
3134 3 : if (IsAutoSize) {
3135 : // report out autosized result and save value in Sys array
3136 6 : BaseSizer::reportSizerOutput(
3137 4 : state, this->sysType, this->SysName, "Design Size Fixed Minimum Air Flow Rate [m3/s]", FixedMinAirDes * this->ZoneTurndownMinAirFrac);
3138 2 : if (SizingDesRunThisAirSys) {
3139 2 : if (state.dataSize->SysSizInput(SysSizNum).SystemOAMethod == SysOAMethod::SP) {
3140 2 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VpzMinByZoneSPSized = true;
3141 : }
3142 : }
3143 2 : this->ZoneFixedMinAir = FixedMinAirDes;
3144 : } else {
3145 : // report out hard (user set) value and issue warning if appropriate
3146 1 : FixedMinAirUser = this->ZoneFixedMinAir;
3147 3 : BaseSizer::reportSizerOutput(state,
3148 : this->sysType,
3149 : this->SysName,
3150 : "Design Size Fixed Minimum Air Flow Rate [m3/s]",
3151 1 : FixedMinAirDes * this->ZoneTurndownMinAirFrac,
3152 : "User-Specified Fixed Minimum Air Flow Rate [m3/s]",
3153 3 : FixedMinAirUser * this->ZoneTurndownMinAirFrac);
3154 1 : if (state.dataGlobal->DisplayExtraWarnings) {
3155 0 : if ((std::abs(FixedMinAirDes - FixedMinAirUser) / FixedMinAirUser) > state.dataSize->AutoVsHardSizingThreshold) {
3156 0 : ShowMessage(state,
3157 0 : "SizeHVACSingleDuct: Potential issue with equipment sizing for " + this->sysType + " = \"" + this->SysName + "\".");
3158 0 : ShowContinueError(state, format("User-Specified Minimum Cooling Air Flow Rate of {:.5R} [m3/s]", FixedMinAirUser));
3159 0 : ShowContinueError(state, format("differs from Design Size Minimum Cooling Air Flow Rate of {:.5R} [m3/s]", FixedMinAirDes));
3160 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3161 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3162 : }
3163 : }
3164 : }
3165 : // report out the min air flow frac set by the min air flow rate
3166 3 : if (this->MaxAirVolFlowRate > 0.0) {
3167 9 : BaseSizer::reportSizerOutput(state,
3168 : this->sysType,
3169 : this->SysName,
3170 : "Design Size Minimum Air Flow Fraction [m3/s]",
3171 6 : this->ZoneFixedMinAir * this->ZoneTurndownMinAirFrac / this->MaxAirVolFlowRate);
3172 : }
3173 : } else {
3174 3301 : if (IsAutoSize) {
3175 2122 : this->ZoneFixedMinAir = 0.0;
3176 : }
3177 : }
3178 :
3179 3304 : if (this->ZoneMinAirFracMethod == MinFlowFraction::Scheduled) {
3180 : // need a value for sizing.
3181 33 : if (this->ConstantMinAirFracSetByUser) {
3182 3 : this->ZoneMinAirFracDes = this->DesignMinAirFrac;
3183 : // if both inputs are defined, use the max
3184 3 : if (this->FixedMinAirSetByUser) {
3185 0 : this->ZoneMinAirFracDes = min(1.0, max(this->ZoneMinAirFracDes, SafeDivide(this->DesignFixedMinAir, this->MaxAirVolFlowRate)));
3186 : }
3187 : // if only fixed is defined, use the value
3188 30 : } else if (this->FixedMinAirSetByUser) {
3189 0 : this->ZoneMinAirFracDes = min(1.0, SafeDivide(this->DesignFixedMinAir, this->MaxAirVolFlowRate));
3190 : } else {
3191 : // use an average of min and max in schedule
3192 30 : this->ZoneMinAirFracDes =
3193 30 : (GetScheduleMinValue(state, this->ZoneMinAirFracSchPtr) + GetScheduleMaxValue(state, this->ZoneMinAirFracSchPtr)) / 2.0;
3194 : }
3195 : }
3196 :
3197 3304 : if (this->ZoneMinAirFracMethod == MinFlowFraction::Fixed) {
3198 : // need a value for sizing.
3199 3 : this->ZoneMinAirFracDes = min(1.0, SafeDivide(this->ZoneFixedMinAir, this->MaxAirVolFlowRate));
3200 : }
3201 :
3202 3304 : if (this->DamperHeatingAction == Action::ReverseWithLimits) {
3203 1111 : if (state.dataSize->ZoneSizingRunDone) {
3204 1089 : if (state.dataSize->CurTermUnitSizingNum > 0) {
3205 : // if zone sizing run done, set the design max reheat air flow to the value from the design calcs
3206 1089 : MaxAirVolFlowRateDuringReheatDes = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlowMax;
3207 : }
3208 : } else {
3209 : // if no design calc use 0.002032 [m3/s-m2] times floor area. That's .40 cfm/ft2
3210 22 : MaxAirVolFlowRateDuringReheatDes = min(0.002032 * this->ZoneFloorArea, this->MaxAirVolFlowRate);
3211 : }
3212 : // check that result is not greater than the max flow or less than the min flow.
3213 1111 : MaxAirVolFlowRateDuringReheatDes = min(MaxAirVolFlowRateDuringReheatDes, this->MaxAirVolFlowRate);
3214 1111 : MaxAirVolFlowRateDuringReheatDes = max(MaxAirVolFlowRateDuringReheatDes, (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes));
3215 1111 : if (this->MaxAirVolFlowRate > 0.0) {
3216 1111 : MaxAirVolFractionDuringReheatDes = MaxAirVolFlowRateDuringReheatDes / this->MaxAirVolFlowRate;
3217 : } else {
3218 0 : MaxAirVolFractionDuringReheatDes = 0.0;
3219 : }
3220 2199 : if (this->MaxAirVolFlowRateDuringReheat == DataGlobalConstants::AutoCalculate &&
3221 1088 : this->MaxAirVolFractionDuringReheat == DataGlobalConstants::AutoCalculate) {
3222 : // if both inputs are autosize (the default) report both out and save in the Sys array.
3223 1474 : BaseSizer::reportSizerOutput(
3224 737 : state, this->sysType, this->SysName, "Design Size Maximum Flow Fraction during Reheat []", MaxAirVolFractionDuringReheatDes);
3225 737 : if (this->ZoneFloorArea > 0.0) {
3226 2211 : BaseSizer::reportSizerOutput(state,
3227 : this->sysType,
3228 : this->SysName,
3229 : "Design Size Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
3230 1474 : MaxAirVolFlowRateDuringReheatDes / this->ZoneFloorArea);
3231 : }
3232 737 : this->MaxAirVolFlowRateDuringReheat = MaxAirVolFlowRateDuringReheatDes;
3233 737 : this->MaxAirVolFractionDuringReheat = MaxAirVolFractionDuringReheatDes;
3234 725 : } else if (this->MaxAirVolFlowRateDuringReheat == DataGlobalConstants::AutoCalculate &&
3235 351 : this->MaxAirVolFractionDuringReheat != DataGlobalConstants::AutoCalculate) {
3236 : // if max reheat flow fraction was input, set the max reheat flow design value correspondingly, report both out.
3237 : // Check for optional caution message that user input value is not within 10% of the design value.
3238 351 : MaxAirVolFlowRateDuringReheatDes = this->MaxAirVolFractionDuringReheat * this->MaxAirVolFlowRate;
3239 351 : MaxAirVolFractionDuringReheatUser = this->MaxAirVolFractionDuringReheat;
3240 702 : BaseSizer::reportSizerOutput(state,
3241 : this->sysType,
3242 : this->SysName,
3243 : "Design Size Maximum Flow Fraction during Reheat []",
3244 : MaxAirVolFractionDuringReheatDes,
3245 : "User-Specified Maximum Flow Fraction during Reheat []",
3246 351 : MaxAirVolFractionDuringReheatUser);
3247 351 : if (this->ZoneFloorArea > 0.0) {
3248 1053 : BaseSizer::reportSizerOutput(state,
3249 : this->sysType,
3250 : this->SysName,
3251 : "Design Size Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
3252 702 : MaxAirVolFlowRateDuringReheatDes / this->ZoneFloorArea);
3253 : }
3254 351 : this->MaxAirVolFlowRateDuringReheat = MaxAirVolFlowRateDuringReheatDes;
3255 702 : if (state.dataGlobal->DisplayExtraWarnings) {
3256 0 : if ((std::abs(MaxAirVolFractionDuringReheatDes - MaxAirVolFractionDuringReheatUser) / MaxAirVolFractionDuringReheatUser) >
3257 0 : state.dataSize->AutoVsHardSizingThreshold) {
3258 0 : ShowMessage(state,
3259 0 : "SizeHVACSingleDuct: Potential issue with equipment sizing for " + this->sysType + " = \"" + this->SysName + "\".");
3260 0 : ShowContinueError(state,
3261 0 : format("User-Specified Maximum Flow Fraction during Reheat of {:.5R} []", MaxAirVolFractionDuringReheatUser));
3262 0 : ShowContinueError(
3263 0 : state, format("differs from Design Size Maximum Flow Fraction during Reheat of {:.5R} []", MaxAirVolFractionDuringReheatDes));
3264 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3265 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3266 : }
3267 : }
3268 46 : } else if (this->MaxAirVolFlowRateDuringReheat != DataGlobalConstants::AutoCalculate &&
3269 23 : this->MaxAirVolFractionDuringReheat == DataGlobalConstants::AutoCalculate) {
3270 : // if max reheat flow was input set the design max reheat flow frac to the corresponding value, report both out, save the design value
3271 : // of the flow frac in Sys. Check for optional caution message that user input value is not within 10% of the design value.
3272 23 : if (this->MaxAirVolFlowRate > 0.0) {
3273 23 : MaxAirVolFractionDuringReheatDes = MaxAirVolFlowRateDuringReheatDes / this->MaxAirVolFlowRate;
3274 : } else {
3275 0 : MaxAirVolFractionDuringReheatDes = 0.0;
3276 : }
3277 23 : MaxAirVolFlowRateDuringReheatUser = this->MaxAirVolFlowRateDuringReheat;
3278 46 : BaseSizer::reportSizerOutput(
3279 23 : state, this->sysType, this->SysName, "Design Size Maximum Flow Fraction during Reheat []", MaxAirVolFractionDuringReheatDes);
3280 23 : if (this->ZoneFloorArea > 0.0) {
3281 69 : BaseSizer::reportSizerOutput(state,
3282 : this->sysType,
3283 : this->SysName,
3284 : "Design Size Maximum Flow per Zone Floor Area during Reheat [ m3/s-m2 ]",
3285 23 : MaxAirVolFlowRateDuringReheatDes / this->ZoneFloorArea,
3286 : "User-Specified Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
3287 69 : MaxAirVolFlowRateDuringReheatUser / this->ZoneFloorArea);
3288 : }
3289 23 : this->MaxAirVolFractionDuringReheat = MaxAirVolFractionDuringReheatDes;
3290 46 : if (state.dataGlobal->DisplayExtraWarnings) {
3291 0 : if ((std::abs(MaxAirVolFlowRateDuringReheatDes - MaxAirVolFlowRateDuringReheatUser) / MaxAirVolFlowRateDuringReheatUser) >
3292 0 : state.dataSize->AutoVsHardSizingThreshold) {
3293 0 : ShowMessage(state,
3294 0 : "SizeHVACSingleDuct: Potential issue with equipment sizing for " + this->sysType + " = \"" + this->SysName + "\".");
3295 0 : ShowContinueError(state,
3296 0 : format("User-Specified Maximum Flow per Zone Floor Area during Reheat of {:.5R} [m3/s-m2]",
3297 0 : MaxAirVolFlowRateDuringReheatUser));
3298 0 : ShowContinueError(state,
3299 0 : format("differs from Design Size Maximum Flow per Zone Floor Area during Reheat of {:.5R} [m3/s-m2]",
3300 0 : MaxAirVolFlowRateDuringReheatDes));
3301 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3302 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3303 : }
3304 : }
3305 : } else {
3306 : // both fields have user input. Report both out, use the larger of the 2 values. Note that only sd_airterminal( SysNum
3307 : // ).MaxAirVolFlowRateDuringReheat is used subsequently. Check both inputs for optional caution message that user input value is not
3308 : // within 10% of the design value.
3309 0 : MaxAirVolFlowRateDuringReheatUser = this->MaxAirVolFlowRateDuringReheat;
3310 0 : MaxAirVolFractionDuringReheatUser = this->MaxAirVolFractionDuringReheat;
3311 0 : BaseSizer::reportSizerOutput(state,
3312 : this->sysType,
3313 : this->SysName,
3314 : "Design Size Maximum Flow Fraction during Reheat []",
3315 : MaxAirVolFractionDuringReheatDes,
3316 : "User-Specified Maximum Flow Fraction during Reheat []",
3317 0 : MaxAirVolFractionDuringReheatUser);
3318 0 : if (this->ZoneFloorArea > 0.0) {
3319 0 : BaseSizer::reportSizerOutput(state,
3320 : this->sysType,
3321 : this->SysName,
3322 : "Design Size Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
3323 0 : MaxAirVolFlowRateDuringReheatDes / this->ZoneFloorArea,
3324 : "User-Specified Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
3325 0 : MaxAirVolFlowRateDuringReheatUser / this->ZoneFloorArea);
3326 : }
3327 0 : this->MaxAirVolFlowRateDuringReheat =
3328 0 : max(this->MaxAirVolFlowRateDuringReheat, this->MaxAirVolFractionDuringReheat * this->MaxAirVolFlowRate);
3329 0 : if (state.dataGlobal->DisplayExtraWarnings) {
3330 0 : if ((std::abs(MaxAirVolFractionDuringReheatDes - MaxAirVolFractionDuringReheatUser) / MaxAirVolFractionDuringReheatUser) >
3331 0 : state.dataSize->AutoVsHardSizingThreshold) {
3332 0 : ShowMessage(state,
3333 0 : "SizeHVACSingleDuct: Potential issue with equipment sizing for " + this->sysType + " = \"" + this->SysName + "\".");
3334 0 : ShowContinueError(state,
3335 0 : format("User-Specified Maximum Flow Fraction during Reheat of {:.5R} []", MaxAirVolFractionDuringReheatUser));
3336 0 : ShowContinueError(
3337 0 : state, format("differs from Design Size Maximum Flow Fraction during Reheat of {:.5R} []", MaxAirVolFractionDuringReheatDes));
3338 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3339 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3340 : }
3341 : }
3342 0 : if (state.dataGlobal->DisplayExtraWarnings) {
3343 0 : if ((std::abs(MaxAirVolFlowRateDuringReheatDes - MaxAirVolFlowRateDuringReheatUser) / MaxAirVolFlowRateDuringReheatUser) >
3344 0 : state.dataSize->AutoVsHardSizingThreshold) {
3345 0 : ShowMessage(state,
3346 0 : "SizeHVACSingleDuct: Potential issue with equipment sizing for " + this->sysType + " = \"" + this->SysName + "\".");
3347 0 : ShowContinueError(state,
3348 0 : format("User-Specified Maximum Flow per Zone Floor Area during Reheat of {:.5R} [m3/s-m2]",
3349 0 : MaxAirVolFlowRateDuringReheatUser));
3350 0 : ShowContinueError(state,
3351 0 : format("differs from Design Size Maximum Flow per Zone Floor Area during Reheat of {:.5R} [m3/s-m2]",
3352 0 : MaxAirVolFlowRateDuringReheatDes));
3353 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3354 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3355 : }
3356 : }
3357 : }
3358 : // check that MaxAirVolFlowRateDuringReheat is greater than the min and less than the max
3359 1111 : this->MaxAirVolFlowRateDuringReheat = min(MaxAirVolFlowRateDuringReheatDes, this->MaxAirVolFlowRate);
3360 1111 : this->MaxAirVolFlowRateDuringReheat = max(MaxAirVolFlowRateDuringReheatDes, (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes));
3361 2193 : } else if (this->DamperHeatingAction == Action::Normal) {
3362 : // for Normal action, max reheat flow is equal to the minimum. Report it.
3363 937 : if (this->ZoneFloorArea > 0.0) {
3364 2811 : BaseSizer::reportSizerOutput(state,
3365 : this->sysType,
3366 : this->SysName,
3367 : "Design Size Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
3368 1874 : (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes) / this->ZoneFloorArea);
3369 : }
3370 1874 : BaseSizer::reportSizerOutput(
3371 937 : state, this->sysType, this->SysName, "Design Size Maximum Flow Fraction during Reheat []", this->ZoneMinAirFracDes);
3372 : // zero the ReverseActioWithLimits inputs
3373 937 : this->MaxAirVolFlowRateDuringReheat = max(this->MaxAirVolFlowRateDuringReheat, 0.0);
3374 937 : this->MaxAirVolFractionDuringReheat = max(this->MaxAirVolFractionDuringReheat, 0.0);
3375 1256 : } else if (this->DamperHeatingAction == Action::Reverse) {
3376 : // for ReverseAction, max reheat flow is equal to the maximum. Report it.
3377 61 : if (this->ZoneFloorArea > 0.0) {
3378 183 : BaseSizer::reportSizerOutput(state,
3379 : this->sysType,
3380 : this->SysName,
3381 : "Design Size Maximum Flow per Zone Floor Area during Reheat [m3/s-m2]",
3382 122 : this->MaxAirVolFlowRate / this->ZoneFloorArea);
3383 : }
3384 61 : BaseSizer::reportSizerOutput(state, this->sysType, this->SysName, "Design Size Maximum Flow Fraction during Reheat []", 1.0);
3385 : // zero the ReverseActioWithLimits inputs
3386 61 : this->MaxAirVolFlowRateDuringReheat = max(this->MaxAirVolFlowRateDuringReheat, 0.0);
3387 61 : this->MaxAirVolFractionDuringReheat = max(this->MaxAirVolFractionDuringReheat, 0.0);
3388 : }
3389 :
3390 3304 : if (state.dataSize->CurTermUnitSizingNum > 0) {
3391 3304 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult = 1.0;
3392 3304 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult = 1.0;
3393 3304 : if (state.dataSize->ZoneSizingRunDone) {
3394 : // set air flow rate used to size heating coils, ZoneTurndownMinAirFrac defaults to 1 for those TU types that do not use it
3395 2797 : if (this->SysType_Num == SysType::SingleDuctVAVReheatVSFan) {
3396 8 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
3397 16 : max(state.dataSingleDuct->UserInputMaxHeatAirVolFlowRateSS,
3398 8 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatVolFlow,
3399 8 : this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac);
3400 2789 : } else if (this->SysType_Num == SysType::SingleDuctConstVolReheat || this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
3401 639 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
3402 639 : max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatVolFlow,
3403 639 : this->MaxAirVolFlowRate * this->ZoneTurndownMinAirFrac);
3404 : } else {
3405 2150 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
3406 2150 : max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatVolFlow,
3407 2150 : this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac);
3408 : }
3409 : } else {
3410 507 : if (this->SysType_Num == SysType::SingleDuctVAVReheatVSFan) {
3411 0 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
3412 0 : max(this->MaxHeatAirVolFlowRate, this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac);
3413 507 : } else if (this->SysType_Num == SysType::SingleDuctConstVolReheat || this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
3414 459 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow = this->MaxAirVolFlowRate;
3415 : } else {
3416 48 : if (this->DamperHeatingAction == Action::Reverse) {
3417 0 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow = this->MaxAirVolFlowRate;
3418 48 : } else if (this->DamperHeatingAction == Action::ReverseWithLimits) {
3419 22 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
3420 22 : max(this->MaxAirVolFlowRateDuringReheat, (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac));
3421 : } else {
3422 26 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow =
3423 26 : this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac;
3424 : }
3425 : }
3426 : }
3427 :
3428 3304 : if (TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow > SmallAirVolFlow) {
3429 3304 : if (this->DamperHeatingAction == Action::ReverseWithLimits) {
3430 1111 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
3431 2222 : min(this->MaxAirVolFlowRateDuringReheat, this->MaxAirVolFlowRate) /
3432 1111 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
3433 1111 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult =
3434 1111 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult;
3435 2193 : } else if (this->DamperHeatingAction == Action::Reverse) {
3436 61 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
3437 61 : this->MaxAirVolFlowRate / TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
3438 61 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult =
3439 61 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult;
3440 2132 : } else if (this->DamperHeatingAction == Action::Normal && this->MaxAirVolFlowRateDuringReheat > 0.0) {
3441 0 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
3442 0 : min(this->MaxAirVolFlowRateDuringReheat, (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac)) /
3443 0 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
3444 0 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult = 1.0;
3445 2132 : } else if (this->DamperHeatingAction == Action::Normal && this->MaxAirVolFlowRateDuringReheat == 0.0) {
3446 937 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
3447 1874 : (this->MaxAirVolFlowRate * this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac) /
3448 937 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
3449 937 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult = 1.0;
3450 : } else {
3451 1195 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
3452 1195 : this->MaxAirVolFlowRate / TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
3453 1195 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult =
3454 1195 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult;
3455 : }
3456 3304 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult =
3457 3304 : max(1.0, TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult);
3458 3304 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult =
3459 3304 : max(1.0, TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult);
3460 : } else {
3461 0 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatAirFlowMult = 1.0;
3462 0 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult = 1.0;
3463 : }
3464 3304 : if (this->ReheatComp_Index > 0) {
3465 3598 : state.dataRptCoilSelection->coilSelectionReportObj->setCoilReheatMultiplier(
3466 1799 : state, this->ReheatName, this->ReheatComp, TermUnitSizing(state.dataSize->CurTermUnitSizingNum).ReheatLoadMult);
3467 : }
3468 : }
3469 :
3470 3304 : IsAutoSize = false;
3471 3304 : if (this->MaxReheatWaterVolFlow == AutoSize) {
3472 1991 : IsAutoSize = true;
3473 : }
3474 3304 : if (state.dataSize->CurTermUnitSizingNum > 0) {
3475 3304 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) {
3476 507 : if (this->MaxReheatWaterVolFlow > 0.0) {
3477 432 : BaseSizer::reportSizerOutput(
3478 216 : state, this->sysType, this->SysName, "User-Specified Maximum Reheat Water Flow Rate [m3/s]", this->MaxReheatWaterVolFlow);
3479 : }
3480 : } else {
3481 2797 : CheckZoneSizing(state, this->sysType, this->SysName);
3482 2797 : if (UtilityRoutines::SameString(this->ReheatComp, "Coil:Heating:Water")) {
3483 1791 : state.dataSingleDuct->CoilWaterInletNodeSS = GetCoilWaterInletNode(state, "Coil:Heating:Water", this->ReheatName, ErrorsFound);
3484 1791 : state.dataSingleDuct->CoilWaterOutletNodeSS = GetCoilWaterOutletNode(state, "Coil:Heating:Water", this->ReheatName, ErrorsFound);
3485 1791 : if (IsAutoSize) {
3486 1737 : PlantSizingErrorsFound = false;
3487 5211 : PltSizHeatNum = MyPlantSizingIndex(state,
3488 : "Coil:Heating:Water",
3489 : this->ReheatName,
3490 1737 : state.dataSingleDuct->CoilWaterInletNodeSS,
3491 1737 : state.dataSingleDuct->CoilWaterOutletNodeSS,
3492 : PlantSizingErrorsFound);
3493 1737 : if (PlantSizingErrorsFound) {
3494 0 : ShowContinueError(state, "...Occurs in " + this->sysType + ':' + this->SysName);
3495 0 : ErrorsFound = true;
3496 : }
3497 1737 : if (PltSizHeatNum > 0) {
3498 1737 : state.dataSingleDuct->CoilInTempSS =
3499 1737 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU;
3500 1737 : DesMassFlow = state.dataEnvrn->StdRhoAir * TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
3501 1737 : state.dataSingleDuct->DesZoneHeatLoadSS =
3502 1737 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatLoad;
3503 1737 : state.dataSingleDuct->ZoneDesTempSS =
3504 1737 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtHeatPeak;
3505 1737 : state.dataSingleDuct->ZoneDesHumRatSS =
3506 1737 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneHumRatAtHeatPeak;
3507 : // the coil load is the zone design heating load plus (or minus!) the reheat load
3508 1737 : state.dataSingleDuct->DesCoilLoadSS =
3509 3474 : state.dataSingleDuct->DesZoneHeatLoadSS + PsyCpAirFnW(state.dataSingleDuct->ZoneDesHumRatSS) * DesMassFlow *
3510 1737 : (state.dataSingleDuct->ZoneDesTempSS - state.dataSingleDuct->CoilInTempSS);
3511 1737 : if (state.dataSingleDuct->DesCoilLoadSS >= SmallLoad) {
3512 :
3513 3474 : rho = GetDensityGlycol(state,
3514 1737 : state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).FluidName,
3515 : DataGlobalConstants::HWInitConvTemp,
3516 1737 : state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).FluidIndex,
3517 : RoutineName);
3518 :
3519 3474 : Cp = GetSpecificHeatGlycol(state,
3520 1737 : state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).FluidName,
3521 : DataGlobalConstants::HWInitConvTemp,
3522 1737 : state.dataPlnt->PlantLoop(this->HWplantLoc.loopNum).FluidIndex,
3523 : RoutineName);
3524 :
3525 1737 : MaxReheatWaterVolFlowDes =
3526 1737 : state.dataSingleDuct->DesCoilLoadSS / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
3527 : } else {
3528 0 : MaxReheatWaterVolFlowDes = 0.0;
3529 : }
3530 : } else {
3531 0 : ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
3532 0 : ShowContinueError(state, "Occurs in AirTerminal Object=" + this->SysName);
3533 0 : ErrorsFound = true;
3534 : }
3535 : }
3536 1791 : if (IsAutoSize) {
3537 1737 : this->MaxReheatWaterVolFlow = MaxReheatWaterVolFlowDes;
3538 3474 : BaseSizer::reportSizerOutput(
3539 1737 : state, this->sysType, this->SysName, "Design Size Maximum Reheat Water Flow Rate [m3/s]", MaxReheatWaterVolFlowDes);
3540 5211 : BaseSizer::reportSizerOutput(state,
3541 : this->sysType,
3542 : this->SysName,
3543 : "Design Size Reheat Coil Sizing Air Volume Flow Rate [m3/s]",
3544 3474 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow);
3545 5211 : BaseSizer::reportSizerOutput(state,
3546 : this->sysType,
3547 : this->SysName,
3548 : "Design Size Reheat Coil Sizing Inlet Air Temperature [C]",
3549 3474 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU);
3550 5211 : BaseSizer::reportSizerOutput(state,
3551 : this->sysType,
3552 : this->SysName,
3553 : "Design Size Reheat Coil Sizing Inlet Air Humidity Ratio [kgWater/kgDryAir]",
3554 3474 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInHumRatTU);
3555 : } else { // Hard-size with sizing data
3556 54 : if (this->MaxReheatWaterVolFlow > 0.0 && MaxReheatWaterVolFlowDes > 0.0) {
3557 0 : MaxReheatWaterVolFlowUser = this->MaxReheatWaterVolFlow;
3558 0 : BaseSizer::reportSizerOutput(state,
3559 : this->sysType,
3560 : this->SysName,
3561 : "Design Size Maximum Reheat Water Flow Rate [m3/s]",
3562 : MaxReheatWaterVolFlowDes,
3563 : "User-Specified Maximum Reheat Water Flow Rate [m3/s]",
3564 0 : MaxReheatWaterVolFlowUser);
3565 0 : if (state.dataGlobal->DisplayExtraWarnings) {
3566 0 : if ((std::abs(MaxReheatWaterVolFlowDes - MaxReheatWaterVolFlowUser) / MaxReheatWaterVolFlowUser) >
3567 0 : state.dataSize->AutoVsHardSizingThreshold) {
3568 0 : ShowMessage(state,
3569 0 : "SizeHVACSingleDuct: Potential issue with equipment sizing for " + this->sysType + " = \"" +
3570 0 : this->SysName + "\".");
3571 0 : ShowContinueError(
3572 0 : state, format("User-Specified Maximum Reheat Water Flow Rate of {:.5R} [m3/s]", MaxReheatWaterVolFlowUser));
3573 0 : ShowContinueError(
3574 : state,
3575 0 : format("differs from Design Size Maximum Reheat Water Flow Rate of {:.5R} [m3/s]", MaxReheatWaterVolFlowDes));
3576 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3577 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3578 : }
3579 : }
3580 : }
3581 : }
3582 : }
3583 : }
3584 : } else {
3585 0 : this->MaxReheatWaterVolFlow = 0.0;
3586 : }
3587 :
3588 3304 : IsAutoSize = false;
3589 3304 : if (this->MaxReheatSteamVolFlow == AutoSize) {
3590 8 : IsAutoSize = true;
3591 : }
3592 3304 : if (state.dataSize->CurTermUnitSizingNum > 0) {
3593 3304 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) {
3594 507 : if (this->MaxReheatSteamVolFlow > 0.0) {
3595 0 : BaseSizer::reportSizerOutput(
3596 0 : state, this->sysType, this->SysName, "User-Specified Maximum Reheat Steam Flow Rate [m3/s]", this->MaxReheatSteamVolFlow);
3597 : }
3598 : } else {
3599 2797 : CheckZoneSizing(state, this->sysType, this->SysName);
3600 2797 : if (UtilityRoutines::SameString(this->ReheatComp, "Coil:Heating:Steam")) {
3601 8 : state.dataSingleDuct->CoilSteamInletNodeSS = GetCoilSteamInletNode(state, "Coil:Heating:Steam", this->ReheatName, ErrorsFound);
3602 8 : state.dataSingleDuct->CoilSteamOutletNodeSS = GetCoilSteamOutletNode(state, "Coil:Heating:Steam", this->ReheatName, ErrorsFound);
3603 8 : if (IsAutoSize) {
3604 8 : PlantSizingErrorsFound = false;
3605 24 : PltSizHeatNum = MyPlantSizingIndex(state,
3606 : "Coil:Heating:Steam",
3607 : this->ReheatName,
3608 8 : state.dataSingleDuct->CoilSteamInletNodeSS,
3609 8 : state.dataSingleDuct->CoilSteamOutletNodeSS,
3610 : PlantSizingErrorsFound);
3611 8 : if (PlantSizingErrorsFound) {
3612 0 : ShowContinueError(state, "...Occurs in " + this->sysType + ':' + this->SysName);
3613 0 : ErrorsFound = true;
3614 : }
3615 8 : if (PltSizHeatNum > 0) {
3616 8 : state.dataSingleDuct->CoilInTempSS =
3617 8 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU;
3618 8 : DesMassFlow = state.dataEnvrn->StdRhoAir * TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow;
3619 8 : state.dataSingleDuct->DesZoneHeatLoadSS =
3620 8 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatLoad;
3621 8 : state.dataSingleDuct->ZoneDesTempSS =
3622 8 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtHeatPeak;
3623 8 : state.dataSingleDuct->ZoneDesHumRatSS =
3624 8 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneHumRatAtHeatPeak;
3625 : // the coil load is the zone design heating load plus (or minus!) the reheat load
3626 8 : state.dataSingleDuct->DesCoilLoadSS =
3627 16 : state.dataSingleDuct->DesZoneHeatLoadSS + PsyCpAirFnW(state.dataSingleDuct->ZoneDesHumRatSS) * DesMassFlow *
3628 8 : (state.dataSingleDuct->ZoneDesTempSS - state.dataSingleDuct->CoilInTempSS);
3629 8 : if (state.dataSingleDuct->DesCoilLoadSS >= SmallLoad) {
3630 8 : TempSteamIn = 100.00;
3631 8 : EnthSteamInDry = GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 1.0, this->FluidIndex, RoutineNameFull);
3632 8 : EnthSteamOutWet = GetSatEnthalpyRefrig(state, fluidNameSteam, TempSteamIn, 0.0, this->FluidIndex, RoutineNameFull);
3633 8 : LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
3634 8 : SteamDensity = GetSatDensityRefrig(state, fluidNameSteam, TempSteamIn, 1.0, this->FluidIndex, RoutineNameFull);
3635 :
3636 16 : Cp = GetSpecificHeatGlycol(state,
3637 : fluidNameWater,
3638 8 : state.dataSize->PlantSizData(PltSizHeatNum).ExitTemp,
3639 8 : state.dataSingleDuct->DummyWaterIndexSS,
3640 : RoutineName);
3641 16 : MaxReheatSteamVolFlowDes = state.dataSingleDuct->DesCoilLoadSS /
3642 8 : (SteamDensity * (LatentHeatSteam + state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp));
3643 : } else {
3644 0 : MaxReheatSteamVolFlowDes = 0.0;
3645 : }
3646 : } else {
3647 0 : ShowSevereError(state, "Autosizing of Steam flow requires a heating loop Sizing:Plant object");
3648 0 : ShowContinueError(state, "Occurs in AirTerminal:SingleDuct:ConstantVolume:Reheat Object=" + this->SysName);
3649 0 : ErrorsFound = true;
3650 : }
3651 : }
3652 8 : if (IsAutoSize) {
3653 8 : this->MaxReheatSteamVolFlow = MaxReheatSteamVolFlowDes;
3654 16 : BaseSizer::reportSizerOutput(
3655 8 : state, this->sysType, this->SysName, "Design Size Maximum Reheat Steam Flow Rate [m3/s]", MaxReheatSteamVolFlowDes);
3656 : } else {
3657 0 : if (this->MaxReheatSteamVolFlow > 0.0 && MaxReheatSteamVolFlowDes > 0.0) {
3658 0 : MaxReheatSteamVolFlowUser = this->MaxReheatSteamVolFlow;
3659 0 : BaseSizer::reportSizerOutput(state,
3660 : this->sysType,
3661 : this->SysName,
3662 : "Design Size Maximum Reheat Steam Flow Rate [m3/s]",
3663 : MaxReheatSteamVolFlowDes,
3664 : "User-Specified Maximum Reheat Steam Flow Rate [m3/s]",
3665 0 : MaxReheatSteamVolFlowUser);
3666 0 : if (state.dataGlobal->DisplayExtraWarnings) {
3667 0 : if ((std::abs(MaxReheatSteamVolFlowDes - MaxReheatSteamVolFlowUser) / MaxReheatSteamVolFlowUser) >
3668 0 : state.dataSize->AutoVsHardSizingThreshold) {
3669 0 : ShowMessage(state,
3670 0 : "SizeHVACSingleDuct: Potential issue with equipment sizing for " + this->sysType + " = \"" +
3671 0 : this->SysName + "\".");
3672 0 : ShowContinueError(
3673 0 : state, format("User-Specified Maximum Reheat Steam Flow Rate of {:.5R} [m3/s]", MaxReheatSteamVolFlowUser));
3674 0 : ShowContinueError(
3675 : state,
3676 0 : format("differs from Design Size Maximum Reheat Steam Flow Rate of {:.5R} [m3/s]", MaxReheatSteamVolFlowDes));
3677 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
3678 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
3679 : }
3680 : }
3681 : }
3682 : }
3683 : }
3684 : }
3685 : } else {
3686 0 : this->MaxReheatSteamVolFlow = 0.0;
3687 : }
3688 :
3689 3304 : if (state.dataSize->CurTermUnitSizingNum > 0) {
3690 3304 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).MinFlowFrac = this->ZoneMinAirFracDes * this->ZoneTurndownMinAirFrac;
3691 3304 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).MaxHWVolFlow = this->MaxReheatWaterVolFlow;
3692 3304 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).MaxSTVolFlow = this->MaxReheatSteamVolFlow;
3693 3304 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).DesHeatingLoad = state.dataSingleDuct->DesCoilLoadSS; // Coil Summary report
3694 3304 : if (this->ReheatComp_Num == HeatingCoilType::SimpleHeating) {
3695 2007 : if (this->DamperHeatingAction == Action::Normal) {
3696 753 : SetCoilDesFlow(state, this->ReheatComp, this->ReheatName, this->ZoneMinAirFracDes * this->MaxAirVolFlowRate, ErrorsFound);
3697 : } else {
3698 1254 : SetCoilDesFlow(
3699 1254 : state, this->ReheatComp, this->ReheatName, TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow, ErrorsFound);
3700 : }
3701 : }
3702 : }
3703 :
3704 3304 : if (this->MaxAirVolFlowRateDuringReheat > 0.0) {
3705 : // check for inconsistent dual max input
3706 1111 : if (this->MaxAirVolFlowRateDuringReheat < (this->ZoneMinAirFracDes * this->MaxAirVolFlowRate)) {
3707 : // Only warn when really out of bounds
3708 0 : if ((this->ZoneMinAirFracDes * this->MaxAirVolFlowRate) - this->MaxAirVolFlowRateDuringReheat > 1.e-8) {
3709 0 : ShowWarningError(state,
3710 : "SingleDuctSystem:SizeSys: Air Terminal Unit flow limits are not consistent, minimum flow limit is larger than "
3711 : "reheat maximum");
3712 0 : ShowContinueError(state, "Air Terminal Unit name = " + this->SysName);
3713 0 : ShowContinueError(state,
3714 0 : format("Maximum terminal flow during reheat = {:.6R} [m3/s] or flow fraction = {:.4R}",
3715 : this->MaxAirVolFlowRateDuringReheat,
3716 0 : (this->MaxAirVolFlowRateDuringReheat / this->MaxAirVolFlowRate)));
3717 0 : ShowContinueError(state,
3718 0 : format("Minimum terminal flow = {:.6R} [m3/s] or flow fraction = {:.4R}",
3719 0 : (this->ZoneMinAirFracDes * this->MaxAirVolFlowRate),
3720 0 : this->ZoneMinAirFracDes));
3721 0 : ShowContinueError(state, "The reheat maximum flow limit will be replaced by the minimum limit, and the simulation continues");
3722 : }
3723 0 : this->MaxAirVolFlowRateDuringReheat = (this->ZoneMinAirFracDes * this->MaxAirVolFlowRate);
3724 : }
3725 : }
3726 :
3727 3304 : if (ErrorsFound) {
3728 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
3729 : }
3730 3304 : }
3731 :
3732 : // End Initialization Section of the Module
3733 : //******************************************************************************
3734 :
3735 : // Begin Algorithm Section of the Module
3736 : //******************************************************************************
3737 :
3738 23432728 : void SingleDuctAirTerminal::SimVAV(EnergyPlusData &state, bool const FirstHVACIteration, int const ZoneNum, int const ZoneNodeNum)
3739 : {
3740 :
3741 : // SUBROUTINE INFORMATION:
3742 : // AUTHOR Richard J. Liesen
3743 : // DATE WRITTEN January 2000
3744 : // MODIFIED Fred Buhl: added reverse action damper heating action: August 2001
3745 : // KHL/TH 7/2010: revise to support dual max
3746 : // FB/KHL/TH 9/2010: added maximum supply air temperature leaving reheat coil
3747 : // TH 3/2012: added supply air flow adjustment based on zone maximum outdoor
3748 : // air fraction - a TRACE feature
3749 : // Brent Griffith, 5/2012, general cleanup, fix negatives CR 8767, fix phantom coil flows CR 8854
3750 : // RE-ENGINEERED na
3751 :
3752 : // PURPOSE OF THIS SUBROUTINE:
3753 : // This subroutine simulates the simple single duct volume VAV.
3754 :
3755 : // METHODOLOGY EMPLOYED:
3756 : // There is method to this madness.
3757 :
3758 : // REFERENCES:
3759 : // na
3760 :
3761 : // Using/Aliasing
3762 : using namespace DataZoneEnergyDemands;
3763 : // unused USE DataHeatBalFanSys, ONLY: Mat
3764 : using DataHVACGlobals::SmallLoad;
3765 : using HeatingCoils::SimulateHeatingCoilComponents;
3766 : using PlantUtilities::SetActuatedBranchFlowRate;
3767 : using SteamCoils::SimulateSteamCoilComponents;
3768 : using WaterCoils::SimulateWaterCoilComponents;
3769 :
3770 : // Locals
3771 : // SUBROUTINE ARGUMENT DEFINITIONS:
3772 :
3773 : // SUBROUTINE PARAMETER DEFINITIONS:
3774 :
3775 : // INTERFACE BLOCK SPECIFICATIONS
3776 : // na
3777 :
3778 : // DERIVED TYPE DEFINITIONS
3779 : // na
3780 :
3781 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
3782 : Real64 MassFlow; // [kg/sec] Total Mass Flow Rate from Hot & Cold Inlets
3783 : Real64 QTotLoad; // [Watts] Remaining load required for this zone
3784 : Real64 QZnReq; // [Watts] Load calculated for heating coil
3785 : Real64 QToHeatSetPt; // [W] remaining load to heating setpoint
3786 : Real64 CpAirAvg;
3787 : Real64 DeltaTemp;
3788 : int SysOutletNode; // The node number of the terminal unit outlet node
3789 : int SysInletNode; // the node number of the terminal unit inlet node
3790 : int WaterControlNode; // This is the Actuated Reheat Control Node
3791 : Real64 MaxFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
3792 : Real64 MinFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
3793 : Real64 QActualHeating; // the heating load seen by the reheat coil
3794 : Real64 QHeatingDelivered; // the actual output from heating coil
3795 : Real64 LeakLoadMult; // load multiplier to adjust for downstream leaks
3796 : Real64 MinFlowFrac; // minimum flow fraction (and minimum damper position)
3797 : Real64 MassFlowBasedOnOA; // supply air mass flow rate based on zone OA requirements
3798 : Real64 AirLoopOAFrac; // fraction of outside air entering air loop
3799 : Real64 DummyMdot; // temporary mass flow rate argument
3800 :
3801 : // Note to the perplexed
3802 : // The SINGLE DUCT:VAV:REHEAT terminal unit originally contained 2 components: a damper
3803 : // and a reheat coil. The damper has become a virtual component - it consists only of
3804 : // an air inlet node and an air outlet node. The damper is upstream of the heating coil.
3805 : // sd_airterminal(SysNum)%InletNodeNum is the inlet node to the terminal unit and the damper
3806 : // sd_airterminal(SysNum)%OutletNodeNum is the outlet node of the damper and the inlet node of the heating coil
3807 : // sd_airterminal(SysNum)%ReheatAirOutletNode is the outlet node of the terminal unit and the heating coil
3808 :
3809 : // The calculated load from the Heat Balance
3810 23432728 : LeakLoadMult = state.dataDefineEquipment->AirDistUnit(this->ADUNum).LeakLoadMult;
3811 23432728 : QTotLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired * LeakLoadMult;
3812 23432728 : QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP * LeakLoadMult;
3813 23432728 : SysOutletNode = this->ReheatAirOutletNode;
3814 23432728 : SysInletNode = this->InletNodeNum;
3815 23432728 : CpAirAvg = PsyCpAirFnW(0.5 * (state.dataLoopNodes->Node(ZoneNodeNum).HumRat + this->sd_airterminalInlet.AirHumRat));
3816 23432728 : MinFlowFrac = this->ZoneMinAirFrac;
3817 23432728 : MassFlowBasedOnOA = 0.0;
3818 23432728 : state.dataSingleDuct->ZoneTempSDAT = state.dataLoopNodes->Node(ZoneNodeNum).Temp;
3819 23432728 : state.dataSingleDuct->MinMassAirFlowSDAT = MinFlowFrac * state.dataEnvrn->StdRhoAir * this->MaxAirVolFlowRate;
3820 :
3821 : // Then depending on if the Load is for heating or cooling it is handled differently. First
3822 : // the massflow rate for cooling is determined to meet the entire load. Then
3823 : // if the massflow is below the minimum or greater than the Max it is set to either the Min
3824 : // or the Max as specified for the VAV model.
3825 38296557 : if ((QTotLoad < 0.0) && (this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0) &&
3826 37896410 : (state.dataHeatBalFanSys->TempControlType(ZoneNum) != DataHVACGlobals::ThermostatType::SingleHeating) &&
3827 7223370 : (GetCurrentScheduleValue(state, this->SchedPtr) > 0.0)) {
3828 : // Calculate the flow required for cooling
3829 :
3830 7223370 : DeltaTemp = CpAirAvg * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSDAT);
3831 :
3832 : // Need to check DeltaTemp and ensure that it is not zero
3833 7223370 : if (DeltaTemp != 0.0) {
3834 7223042 : MassFlow = QTotLoad / DeltaTemp;
3835 : } else {
3836 328 : MassFlow = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
3837 : }
3838 :
3839 : // Apply the zone maximum outdoor air fraction FOR VAV boxes - a TRACE feature
3840 7223370 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).SupplyAirAdjustFactor > 1.0) {
3841 0 : MassFlow *= state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).SupplyAirAdjustFactor;
3842 : }
3843 :
3844 : // calculate supply air flow rate based on user specified OA requirement
3845 7223370 : this->CalcOAMassFlow(state, MassFlowBasedOnOA, AirLoopOAFrac);
3846 7223370 : MassFlow = max(MassFlow, MassFlowBasedOnOA);
3847 :
3848 : // used for normal acting damper
3849 7223370 : state.dataSingleDuct->MinMassAirFlowSDAT = max(state.dataSingleDuct->MinMassAirFlowSDAT, MassFlowBasedOnOA);
3850 7223370 : state.dataSingleDuct->MinMassAirFlowSDAT = max(state.dataSingleDuct->MinMassAirFlowSDAT, this->sd_airterminalInlet.AirMassFlowRateMinAvail);
3851 7223370 : state.dataSingleDuct->MinMassAirFlowSDAT = min(state.dataSingleDuct->MinMassAirFlowSDAT, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
3852 :
3853 : // limit the OA based supply air flow rate based on optional user input
3854 : // Check to see if the flow is < the Min or > the Max air Fraction to the zone; then set to min or max
3855 7223370 : MassFlow = max(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMinAvail);
3856 7223370 : MassFlow = min(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
3857 :
3858 7223370 : if (state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated && state.afn->VAVTerminalRatio > 0.0) {
3859 0 : MassFlow *= state.afn->VAVTerminalRatio;
3860 0 : if (MassFlow > state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate) {
3861 0 : MassFlow = state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate;
3862 : }
3863 : }
3864 :
3865 45226567 : } else if ((this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0) &&
3866 29034151 : (QTotLoad >= 0.0 || state.dataHeatBalFanSys->TempControlType(ZoneNum) == DataHVACGlobals::ThermostatType::SingleHeating) &&
3867 12807851 : (GetCurrentScheduleValue(state, this->SchedPtr) > 0.0)) {
3868 : // IF (sd_airterminal(SysNum)%DamperHeatingAction .EQ. ReverseAction .AND. this->sd_airterminalInlet%AirMassFlowRateMinAvail <=
3869 : // SmallMassFlow) THEN
3870 : // special case for heating: reverse action and damper allowed to close - set the minimum flow rate to a small but nonzero value
3871 : // MassFlow = 0.01d0*this->sd_airterminalInlet%AirMassFlowRateMaxAvail
3872 : // ELSE
3873 : // usual case for heating: set the air mass flow rate to the minimum
3874 12807851 : MassFlow = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
3875 : // END IF
3876 :
3877 : // Apply the zone maximum outdoor air fraction for VAV boxes - a TRACE feature
3878 12807851 : if (state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).SupplyAirAdjustFactor > 1.0) {
3879 0 : MassFlow *= state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).SupplyAirAdjustFactor;
3880 : }
3881 :
3882 : // calculate supply air flow rate based on user specified OA requirement
3883 12807851 : this->CalcOAMassFlow(state, MassFlowBasedOnOA, AirLoopOAFrac);
3884 12807851 : MassFlow = max(MassFlow, MassFlowBasedOnOA);
3885 :
3886 : // Check to see if the flow is < the Min or > the Max air Fraction to the zone; then set to min or max
3887 12807851 : if (MassFlow <= this->sd_airterminalInlet.AirMassFlowRateMinAvail) {
3888 12409328 : MassFlow = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
3889 398523 : } else if (MassFlow >= this->sd_airterminalInlet.AirMassFlowRateMaxAvail) {
3890 300189 : MassFlow = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
3891 : }
3892 :
3893 : // the AirflowNetwork model overrids the mass flow rate value
3894 12807851 : if (state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated && state.afn->VAVTerminalRatio > 0.0) {
3895 0 : MassFlow *= state.afn->VAVTerminalRatio;
3896 0 : if (MassFlow > state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate) {
3897 0 : MassFlow = state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate;
3898 : }
3899 : }
3900 :
3901 : } else {
3902 : // System is Off set massflow to 0.0
3903 3401507 : MassFlow = 0.0;
3904 3401507 : AirLoopOAFrac = 0.0;
3905 : }
3906 :
3907 : // look for bang-bang condition: flow rate oscillating between 2 values during the air loop / zone
3908 : // equipment iteration. If detected, set flow rate to previous value.
3909 29526932 : if (((std::abs(MassFlow - this->MassFlow2) < this->MassFlowDiff) || (std::abs(MassFlow - this->MassFlow3) < this->MassFlowDiff)) &&
3910 6094204 : (std::abs(MassFlow - this->MassFlow1) >= this->MassFlowDiff)) {
3911 14435 : if (MassFlow > 0.0) MassFlow = this->MassFlow1;
3912 : }
3913 :
3914 : // Move data to the damper outlet node
3915 23432728 : this->sd_airterminalOutlet.AirTemp = this->sd_airterminalInlet.AirTemp;
3916 23432728 : this->sd_airterminalOutlet.AirHumRat = this->sd_airterminalInlet.AirHumRat;
3917 23432728 : this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
3918 23432728 : this->sd_airterminalOutlet.AirMassFlowRateMaxAvail = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
3919 23432728 : this->sd_airterminalOutlet.AirMassFlowRateMinAvail = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
3920 23432728 : this->sd_airterminalOutlet.AirEnthalpy = this->sd_airterminalInlet.AirEnthalpy;
3921 :
3922 : // ! Calculate the Damper Position when there is a Max air flow specified.
3923 : // If (MassFlow == 0.0D0) THEN
3924 : // sd_airterminal(SysNum)%DamperPosition = 0.0D0
3925 : // ELSE IF (this->sd_airterminalInlet%AirMassFlowRateMaxAvail > this->sd_airterminalInlet%AirMassFlowRateMinAvail) THEN
3926 : // sd_airterminal(SysNum)%DamperPosition = ((MassFlow-this->sd_airterminalInlet%AirMassFlowRateMinAvail) / &
3927 : // (this->sd_airterminalInlet%AirMassFlowRateMaxAvail-this->sd_airterminalInlet%AirMassFlowRateMinAvail)) *
3928 : // &
3929 : // (1.0d0-MinFlowFrac) + MinFlowFrac
3930 : // ELSE
3931 : // sd_airterminal(SysNum)%DamperPosition = 1.0D0
3932 : // END IF
3933 :
3934 23432728 : if (MassFlow == 0.0) {
3935 3402227 : this->DamperPosition = 0.0;
3936 3402227 : this->ZoneMinAirFracReport = 0.0;
3937 20030501 : } else if ((MassFlow > 0.0) && (MassFlow < this->AirMassFlowRateMax)) {
3938 15601961 : this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
3939 15601961 : this->ZoneMinAirFracReport = this->ZoneMinAirFrac;
3940 4428540 : } else if (MassFlow == this->AirMassFlowRateMax) {
3941 4428540 : this->DamperPosition = 1.0;
3942 4428540 : this->ZoneMinAirFracReport = this->ZoneMinAirFrac;
3943 : }
3944 :
3945 : // Need to make sure that the damper outlets are passed to the coil inlet
3946 23432728 : this->UpdateSys(state);
3947 :
3948 : // At the current air mass flow rate, calculate heating coil load
3949 23432728 : QActualHeating = QToHeatSetPt - MassFlow * CpAirAvg * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSDAT); // reheat needed
3950 :
3951 : // do the reheat calculation if there's some air nass flow (or the damper action is "reverse action"), the flow is <= minimum ,
3952 : // there's a heating requirement, and there's a thermostat with a heating setpoint
3953 : // Reverse damper option is working only for water coils for now.
3954 34710853 : if ((MassFlow > SmallMassFlow) && (QActualHeating > 0.0) &&
3955 11278125 : (state.dataHeatBalFanSys->TempControlType(ZoneNum) != DataHVACGlobals::ThermostatType::SingleCooling)) {
3956 : // At this point we know that there is a heating requirement: i.e., the heating coil needs to
3957 : // be activated (there's a zone heating load or there's a reheat requirement). There are 3 possible
3958 : // situations: 1) the coil load can be met by variable temperature air (below the max heat temp) at
3959 : // the minimum air mass flow rate; 2) the coil load can be met by variable air flow rate with the air
3960 : // temperature fixed at the max heat temp; 3) the load cannot be met (we will run at max air temp and
3961 : // max air flow rate). We check for condition 2 by assuming the air temperatute is at the max heat temp
3962 : // and solving for the air mass flow rate that will meet the load. If the flow rate is between the min and
3963 : // max we are in condition 2.
3964 :
3965 10274604 : state.dataSingleDuct->QZoneMax2SDAT = QToHeatSetPt;
3966 :
3967 : // fill dual-max reheat flow limit, if any
3968 10274604 : if (this->DamperHeatingAction == Action::Reverse) {
3969 86487 : state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT = this->AirMassFlowRateMax;
3970 10188117 : } else if (this->DamperHeatingAction == Action::ReverseWithLimits) {
3971 5202128 : state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT = this->AirMassFlowDuringReheatMax;
3972 4985989 : } else if (this->DamperHeatingAction == Action::Normal) {
3973 4914258 : state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT = this->ZoneMinAirFrac * this->AirMassFlowRateMax;
3974 : } else {
3975 : // used for AIRTERMINAL_SINGLEDUCT_VAV_NOREHEAT or SingleDuctVAVNoReheat
3976 71731 : state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT = this->AirMassFlowRateMax;
3977 : }
3978 :
3979 : // determine flow based on leaving reheat temperature limit
3980 10274604 : if (this->MaxReheatTempSetByUser) {
3981 :
3982 1908370 : state.dataSingleDuct->MaxHeatTempSDAT = this->MaxReheatTemp;
3983 1908370 : if (QToHeatSetPt > SmallLoad) { // zone has a positive load to heating setpoint
3984 1606096 : state.dataSingleDuct->MassFlowReqToLimitLeavingTempSDAT =
3985 1606096 : QToHeatSetPt / (CpAirAvg * (state.dataSingleDuct->MaxHeatTempSDAT - state.dataSingleDuct->ZoneTempSDAT));
3986 : } else {
3987 302274 : state.dataSingleDuct->MassFlowReqToLimitLeavingTempSDAT = 0.0;
3988 : }
3989 : }
3990 :
3991 : // (re)apply limits to find air mass flow
3992 10274604 : MassFlow = max(MassFlow, state.dataSingleDuct->MassFlowReqToLimitLeavingTempSDAT);
3993 10274604 : MassFlow = min(MassFlow, state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT);
3994 10274604 : MassFlow = max(MassFlow, MassFlowBasedOnOA);
3995 10274604 : MassFlow = min(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
3996 10274604 : MassFlow = max(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMinAvail);
3997 :
3998 10274604 : if (state.afn->distribution_simulated && state.afn->AirflowNetworkFanActivated && state.afn->VAVTerminalRatio > 0.0) {
3999 0 : MassFlow *= state.afn->VAVTerminalRatio;
4000 0 : if (MassFlow > state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate) {
4001 0 : MassFlow = state.dataLoopNodes->Node(this->InletNodeNum).MassFlowRate;
4002 : }
4003 : }
4004 :
4005 : // now make any corrections to heating coil loads
4006 10274604 : if (this->MaxReheatTempSetByUser) {
4007 1908370 : state.dataSingleDuct->QZoneMaxRHTempLimitSDAT =
4008 1908370 : MassFlow * CpAirAvg * (state.dataSingleDuct->MaxHeatTempSDAT - state.dataSingleDuct->ZoneTempSDAT);
4009 1908370 : state.dataSingleDuct->QZoneMax2SDAT = min(state.dataSingleDuct->QZoneMaxRHTempLimitSDAT, QToHeatSetPt);
4010 : }
4011 :
4012 10274604 : this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
4013 :
4014 10274604 : this->UpdateSys(state);
4015 :
4016 : // Now do the heating coil calculation for each heating coil type
4017 10274604 : switch (this->ReheatComp_Num) { // Reverse damper option is working only for water coils for now.
4018 : // hot water heating coil
4019 8990011 : case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
4020 : // Determine the load required to pass to the Component controller
4021 : // Although this equation looks strange (using temp instead of deltaT), it is corrected later in ControlCompOutput
4022 : // and is working as-is, temperature setpoints are maintained as expected.
4023 8990011 : QZnReq = state.dataSingleDuct->QZoneMax2SDAT + MassFlow * CpAirAvg * state.dataSingleDuct->ZoneTempSDAT;
4024 :
4025 : // Initialize hot water flow rate to zero.
4026 8990011 : DummyMdot = 0.0;
4027 8990011 : SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
4028 : // On the first HVAC iteration the system values are given to the controller, but after that
4029 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
4030 8990011 : if (FirstHVACIteration) {
4031 3639726 : MaxFlowWater = this->MaxReheatWaterFlow;
4032 3639726 : MinFlowWater = this->MinReheatWaterFlow;
4033 : } else {
4034 5350285 : WaterControlNode = this->ReheatControlNode;
4035 5350285 : MaxFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMaxAvail;
4036 5350285 : MinFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMinAvail;
4037 : }
4038 :
4039 : // Simulate the reheat coil at constant air flow. Control by varying the
4040 : // hot water flow rate.
4041 : // FB use QActualHeating, change ControlCompOutput to use new
4042 8990011 : ControlCompOutput(state,
4043 : this->ReheatName,
4044 : this->ReheatComp,
4045 : this->ReheatComp_Index,
4046 : FirstHVACIteration,
4047 : QZnReq,
4048 : this->ReheatControlNode,
4049 : MaxFlowWater,
4050 : MinFlowWater,
4051 : this->ControllerOffset,
4052 : this->ControlCompTypeNum,
4053 : this->CompErrIndex,
4054 : _,
4055 : SysOutletNode,
4056 : MassFlow,
4057 : _,
4058 : _,
4059 : this->HWplantLoc);
4060 :
4061 : // If reverse action damper and the hot water flow is at maximum, simulate the
4062 : // hot water coil with fixed (maximum) hot water flow but allow the air flow to
4063 : // vary up to the maximum (air damper opens to try to meet zone load)
4064 8990011 : if (this->DamperHeatingAction == Action::Reverse || this->DamperHeatingAction == Action::ReverseWithLimits) {
4065 4685564 : if (state.dataLoopNodes->Node(this->ReheatControlNode).MassFlowRate == MaxFlowWater) {
4066 : // fill limits for air flow for controller
4067 1401211 : state.dataSingleDuct->MinAirMassFlowRevActSVAV = this->AirMassFlowRateMax * this->ZoneMinAirFrac;
4068 1401211 : state.dataSingleDuct->MinAirMassFlowRevActSVAV =
4069 1401211 : min(state.dataSingleDuct->MinAirMassFlowRevActSVAV, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
4070 1401211 : state.dataSingleDuct->MinAirMassFlowRevActSVAV =
4071 1401211 : max(state.dataSingleDuct->MinAirMassFlowRevActSVAV, this->sd_airterminalInlet.AirMassFlowRateMinAvail);
4072 :
4073 1401211 : state.dataSingleDuct->MaxAirMassFlowRevActSVAV = this->AirMassFlowRateMax;
4074 1401211 : state.dataSingleDuct->MaxAirMassFlowRevActSVAV =
4075 1401211 : min(state.dataSingleDuct->MaxAirMassFlowRevActSVAV, state.dataSingleDuct->MaxDeviceAirMassFlowReheatSDAT);
4076 1401211 : state.dataSingleDuct->MaxAirMassFlowRevActSVAV =
4077 1401211 : max(state.dataSingleDuct->MaxAirMassFlowRevActSVAV, state.dataSingleDuct->MinAirMassFlowRevActSVAV);
4078 1401211 : state.dataSingleDuct->MaxAirMassFlowRevActSVAV =
4079 1401211 : min(state.dataSingleDuct->MaxAirMassFlowRevActSVAV, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
4080 :
4081 1401211 : state.dataLoopNodes->Node(this->OutletNodeNum).MassFlowRateMaxAvail =
4082 1401211 : state.dataSingleDuct->MaxAirMassFlowRevActSVAV; // suspect, check how/if used in ControlCompOutput
4083 5604844 : ControlCompOutput(state,
4084 : this->ReheatName,
4085 : this->ReheatComp,
4086 : this->ReheatComp_Index,
4087 : FirstHVACIteration,
4088 1401211 : state.dataSingleDuct->QZoneMax2SDAT,
4089 : this->OutletNodeNum,
4090 1401211 : state.dataSingleDuct->MaxAirMassFlowRevActSVAV,
4091 1401211 : state.dataSingleDuct->MinAirMassFlowRevActSVAV,
4092 : this->ControllerOffset,
4093 : this->ControlCompTypeNum,
4094 : this->CompErrIndex,
4095 : ZoneNodeNum,
4096 : SysOutletNode); // why not QZnReq ?
4097 : // air flow controller, not on plant, don't pass plant topology info
4098 : // reset terminal unit inlet air mass flow to new value.
4099 1401211 : state.dataLoopNodes->Node(this->OutletNodeNum).MassFlowRateMaxAvail = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
4100 1401211 : MassFlow = state.dataLoopNodes->Node(SysOutletNode).MassFlowRate;
4101 :
4102 : // ! look for bang-bang condition: flow rate oscillating between 2 values during the air loop / zone
4103 : // ! equipment iteration. If detected, set flow rate to previous value and recalc HW flow.
4104 3919541 : if (((std::abs(MassFlow - this->MassFlow2) < this->MassFlowDiff) ||
4105 1685491 : (std::abs(MassFlow - this->MassFlow3) < this->MassFlowDiff)) &&
4106 284280 : (std::abs(MassFlow - this->MassFlow1) >= this->MassFlowDiff)) {
4107 933 : if (MassFlow > 0.0) MassFlow = this->MassFlow1;
4108 933 : this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
4109 933 : this->UpdateSys(state);
4110 :
4111 : // Although this equation looks strange (using temp instead of deltaT), it is corrected later in ControlCompOutput
4112 : // and is working as-is, temperature setpoints are maintained as expected.
4113 933 : QZnReq = state.dataSingleDuct->QZoneMax2SDAT + MassFlow * CpAirAvg * state.dataSingleDuct->ZoneTempSDAT;
4114 933 : ControlCompOutput(state,
4115 : this->ReheatName,
4116 : this->ReheatComp,
4117 : this->ReheatComp_Index,
4118 : FirstHVACIteration,
4119 : QZnReq,
4120 : this->ReheatControlNode,
4121 : MaxFlowWater,
4122 : MinFlowWater,
4123 : this->ControllerOffset,
4124 : this->ControlCompTypeNum,
4125 : this->CompErrIndex,
4126 : _,
4127 : SysOutletNode,
4128 : MassFlow,
4129 : _,
4130 : _,
4131 : this->HWplantLoc);
4132 : }
4133 :
4134 1401211 : this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
4135 : // reset OA report variable
4136 1401211 : this->UpdateSys(state);
4137 : } // IF (Node(sd_airterminal(SysNum)%ReheatControlNode)%MassFlowRate .EQ. MaxFlowWater) THEN
4138 : } // IF (sd_airterminal(SysNum)%DamperHeatingAction .EQ. ReverseAction) THEN
4139 :
4140 : // Recalculate the Damper Position.
4141 8990011 : if (MassFlow == 0.0) {
4142 0 : this->DamperPosition = 0.0;
4143 0 : this->ZoneMinAirFracReport = 0.0;
4144 8990011 : } else if ((MassFlow > 0.0) && (MassFlow < this->AirMassFlowRateMax)) {
4145 5446460 : this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
4146 5446460 : this->ZoneMinAirFracReport = this->ZoneMinAirFrac;
4147 3543551 : } else if (MassFlow == this->AirMassFlowRateMax) {
4148 3543551 : this->DamperPosition = 1.0;
4149 3543551 : this->ZoneMinAirFracReport = this->ZoneMinAirFrac;
4150 : }
4151 8990011 : } break;
4152 10899 : case HeatingCoilType::SteamAirHeating: { // ! COIL:STEAM:AIRHEATING
4153 : // Determine the load required to pass to the Component controller
4154 10899 : QZnReq =
4155 10899 : state.dataSingleDuct->QZoneMax2SDAT - MassFlow * CpAirAvg * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSDAT);
4156 :
4157 : // Simulate reheat coil for the VAV system
4158 10899 : SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, QZnReq);
4159 10899 : } break;
4160 1119492 : case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
4161 : // Determine the load required to pass to the Component controller
4162 1119492 : QZnReq =
4163 1119492 : state.dataSingleDuct->QZoneMax2SDAT - MassFlow * CpAirAvg * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSDAT);
4164 :
4165 : // Simulate reheat coil for the VAV system
4166 1119492 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index);
4167 1119492 : } break;
4168 82471 : case HeatingCoilType::Gas: { // COIL:GAS:HEATING
4169 : // Determine the load required to pass to the Component controller
4170 82471 : QZnReq =
4171 82471 : state.dataSingleDuct->QZoneMax2SDAT - MassFlow * CpAirAvg * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSDAT);
4172 :
4173 : // Simulate reheat coil for the VAV system
4174 82471 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index, QHeatingDelivered);
4175 82471 : } break;
4176 71731 : case HeatingCoilType::None: { // blank
4177 : // I no reheat is defined then assume that the damper is the only component.
4178 : // If something else is there that is not a reheat coil or a blank then give the error message
4179 71731 : } break;
4180 0 : default: {
4181 0 : ShowFatalError(state, "Invalid Reheat Component=" + this->ReheatComp);
4182 0 : } break;
4183 : }
4184 :
4185 : // the COIL is OFF the properties are calculated for this special case.
4186 : } else {
4187 13158124 : switch (this->ReheatComp_Num) {
4188 10328516 : case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
4189 : // Simulate reheat coil for the Const Volume system
4190 10328516 : DummyMdot = 0.0;
4191 10328516 : SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
4192 : // call the reheat coil with the NO FLOW condition to make sure that the Node values
4193 : // are passed through to the coil outlet correctly
4194 10328516 : SimulateWaterCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index);
4195 10328516 : } break;
4196 18741 : case HeatingCoilType::SteamAirHeating: { // COIL:STEAM:AIRHEATING
4197 : // Simulate reheat coil for the VAV system
4198 18741 : SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, 0.0);
4199 18741 : } break;
4200 2119510 : case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
4201 : // Simulate reheat coil for the VAV system
4202 2119510 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
4203 2119510 : } break;
4204 401084 : case HeatingCoilType::Gas: { // COIL:GAS:HEATING
4205 : // Simulate reheat coil for the VAV system
4206 401084 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
4207 401084 : } break;
4208 290273 : case HeatingCoilType::None: { // blank
4209 : // If no reheat is defined then assume that the damper is the only component.
4210 : // If something else is that is not a reheat coil or a blank then give the error message
4211 290273 : } break;
4212 0 : default: {
4213 0 : ShowFatalError(state, "Invalid Reheat Component=" + this->ReheatComp);
4214 0 : } break;
4215 : }
4216 : }
4217 :
4218 : // push the flow rate history
4219 23432728 : this->MassFlow3 = this->MassFlow2;
4220 23432728 : this->MassFlow2 = this->MassFlow1;
4221 23432728 : this->MassFlow1 = MassFlow;
4222 23432728 : }
4223 :
4224 20031221 : void SingleDuctAirTerminal::CalcOAMassFlow(EnergyPlusData &state,
4225 : Real64 &SAMassFlow, // outside air based on optional user input
4226 : Real64 &AirLoopOAFrac // outside air based on optional user input
4227 : ) const
4228 : {
4229 :
4230 : // FUNCTION INFORMATION:
4231 : // AUTHOR R. Raustad (FSEC)
4232 : // DATE WRITTEN Jan 2010
4233 : // MODIFIED Mangesh Basarkar, 06/2011: Modifying outside air based on airloop DCV flag
4234 : // RE-ENGINEERED na
4235 :
4236 : // PURPOSE OF THIS FUNCTION:
4237 : // Calculates the amount of outside air required based on optional user input.
4238 : // Zone multipliers are included and are applied in GetInput.
4239 :
4240 : // METHODOLOGY EMPLOYED:
4241 : // User input defines method used to calculate OA.
4242 :
4243 : // REFERENCES:
4244 :
4245 : // Using/Aliasing
4246 : using Psychrometrics::PsyRhoAirFnPbTdbW;
4247 :
4248 : // Locals
4249 : // SUBROUTINE ARGUMENT DEFINITIONS:
4250 :
4251 : // FUNCTION PARAMETER DEFINITIONS:
4252 20031221 : bool constexpr UseMinOASchFlag(true); // Always use min OA schedule in calculations.
4253 :
4254 : // FUNCTION PARAMETER DEFINITIONS:
4255 : // na
4256 :
4257 : // INTERFACE BLOCK SPECIFICATIONS
4258 : // na
4259 :
4260 : // DERIVED TYPE DEFINITIONS
4261 : // na
4262 :
4263 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
4264 : Real64 OAVolumeFlowRate; // outside air volume flow rate (m3/s)
4265 : Real64 OAMassFlow; // outside air mass flow rate (kg/s)
4266 :
4267 : // initialize OA flow rate and OA report variable
4268 20031221 : SAMassFlow = 0.0;
4269 20031221 : AirLoopOAFrac = 0.0;
4270 20031221 : int AirLoopNum = this->AirLoopNum;
4271 :
4272 : // Calculate the amount of OA based on optional user inputs
4273 20031221 : if (AirLoopNum > 0) {
4274 20030933 : AirLoopOAFrac = state.dataAirLoop->AirLoopFlow(AirLoopNum).OAFrac;
4275 : // If no additional input from user, RETURN from subroutine
4276 20030933 : if (this->NoOAFlowInputFromUser) return;
4277 : // Calculate outdoor air flow rate, zone multipliers are applied in GetInput
4278 2433415 : if (AirLoopOAFrac > 0.0) {
4279 4866830 : OAVolumeFlowRate = DataSizing::calcDesignSpecificationOutdoorAir(
4280 4866830 : state, this->OARequirementsPtr, this->CtrlZoneNum, state.dataAirLoop->AirLoopControlInfo(AirLoopNum).AirLoopDCVFlag, UseMinOASchFlag);
4281 2433415 : OAMassFlow = OAVolumeFlowRate * state.dataEnvrn->StdRhoAir;
4282 :
4283 : // convert OA mass flow rate to supply air flow rate based on air loop OA fraction
4284 2433415 : SAMassFlow = OAMassFlow / AirLoopOAFrac;
4285 : }
4286 : }
4287 : }
4288 :
4289 68737 : void SingleDuctAirTerminal::SimCBVAV(EnergyPlusData &state, bool const FirstHVACIteration, int const ZoneNum, int const ZoneNodeNum)
4290 : {
4291 :
4292 : // SUBROUTINE INFORMATION:
4293 : // AUTHOR Richard Raustad
4294 : // DATE WRITTEN August 2006
4295 : // MODIFIED KHL/TH 10/2010: added maximum supply air temperature leaving reheat coil
4296 : // RE-ENGINEERED na
4297 :
4298 : // PURPOSE OF THIS SUBROUTINE:
4299 : // This subroutine simulates the VAV box with varying airflow in heating and cooling.
4300 : // Modified version of SimVAV.
4301 :
4302 : // METHODOLOGY EMPLOYED:
4303 : // na
4304 :
4305 : // REFERENCES:
4306 : // na
4307 :
4308 : // Using/Aliasing
4309 : using namespace DataZoneEnergyDemands;
4310 : using DataHVACGlobals::SmallLoad;
4311 : // unused USE DataHeatBalFanSys, ONLY: Mat
4312 : using HeatingCoils::SimulateHeatingCoilComponents;
4313 : using SteamCoils::SimulateSteamCoilComponents;
4314 : using WaterCoils::SimulateWaterCoilComponents;
4315 : // unused USE DataHeatBalFanSys, ONLY: ZoneThermostatSetPointHi, ZoneThermostatSetPointLo
4316 : using PlantUtilities::SetActuatedBranchFlowRate;
4317 :
4318 : // Locals
4319 : // SUBROUTINE ARGUMENT DEFINITIONS:
4320 :
4321 : // SUBROUTINE PARAMETER DEFINITIONS:
4322 :
4323 : // INTERFACE BLOCK SPECIFICATIONS
4324 : // na
4325 :
4326 : // DERIVED TYPE DEFINITIONS
4327 : // na
4328 :
4329 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4330 : Real64 MassFlow; // Total Mass Flow Rate from Hot & Cold Inlets [kg/sec]
4331 : Real64 QTotLoad; // Total load based on thermostat setpoint temperature [Watts]
4332 : Real64 QZnReq; // Total load to be met by terminal heater [Watts]
4333 : Real64 QToHeatSetPt; // Remaining load to heating setpoint [W]
4334 : Real64 QSupplyAir; // Zone load met by VAVHeatandCool system
4335 : Real64 CpAirZn; // Specific heat of zone air [J/kg-C]
4336 : Real64 CpAirSysIn; // Specific heat of VAVHeatandCool box entering air [J/kg-C]
4337 : Real64 DeltaTemp; // Temperature difference multiplied by specific heat [J/kg]
4338 : Real64 MaxFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
4339 : Real64 MinFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
4340 : Real64 LeakLoadMult; // Load multiplier to adjust for downstream leaks
4341 : int SysOutletNode; // The node number of the terminal unit outlet node
4342 : int SysInletNode; // The node number of the terminal unit inlet node
4343 : int WaterControlNode; // This is the Actuated Reheat Control Node
4344 : Real64 DummyMdot;
4345 : Real64 QActualHeating;
4346 : Real64 MinFlowFrac; // minimum flow fraction (and minimum damper position)
4347 :
4348 : // sd_airterminal(SysNum)%InletNodeNum is the inlet node to the terminal unit and the damper
4349 : // sd_airterminal(SysNum)%OutletNodeNum is the outlet node of the damper and the inlet node of the heating coil
4350 : // sd_airterminal(SysNum)%ReheatAirOutletNode is the outlet node of the terminal unit and the heating coil
4351 :
4352 : // The calculated load from the Heat Balance
4353 68737 : LeakLoadMult = state.dataDefineEquipment->AirDistUnit(this->ADUNum).LeakLoadMult;
4354 68737 : QTotLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired * LeakLoadMult;
4355 68737 : QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP * LeakLoadMult;
4356 68737 : SysOutletNode = this->ReheatAirOutletNode;
4357 68737 : SysInletNode = this->InletNodeNum;
4358 68737 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(ZoneNodeNum).HumRat);
4359 68737 : MinFlowFrac = this->ZoneMinAirFrac;
4360 68737 : state.dataSingleDuct->MinMassAirFlowSCBVAV = MinFlowFrac * state.dataEnvrn->StdRhoAir * this->MaxAirVolFlowRate;
4361 68737 : state.dataSingleDuct->ZoneTempSCBVAV = state.dataLoopNodes->Node(ZoneNodeNum).Temp;
4362 :
4363 : // Then depending on if the Load is for heating or cooling it is handled differently. First
4364 : // the massflow rate for cooling is determined to meet the entire load. Then
4365 : // if the massflow is below the minimum or greater than the Max it is set to either the Min
4366 : // or the Max as specified for the VAV model.
4367 68737 : if (this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0) {
4368 : // Calculate the flow required for cooling
4369 44059 : CpAirSysIn = PsyCpAirFnW(this->sd_airterminalInlet.AirHumRat);
4370 44059 : DeltaTemp = CpAirSysIn * this->sd_airterminalInlet.AirTemp - CpAirZn * state.dataSingleDuct->ZoneTempSCBVAV;
4371 :
4372 : // Need to check DeltaTemp and ensure that it is not zero
4373 44059 : if (DeltaTemp != 0.0) {
4374 44050 : MassFlow = QTotLoad / DeltaTemp;
4375 : } else {
4376 9 : MassFlow = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
4377 : }
4378 :
4379 : // Check to see if the flow is < the Min or > the Max air Fraction to the zone; then set to min or max
4380 44059 : MassFlow = max(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMinAvail);
4381 44059 : MassFlow = min(MassFlow, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
4382 : } else {
4383 : // System is Off set massflow to 0.0
4384 24678 : MassFlow = 0.0;
4385 : }
4386 : // look for bang-bang condition: flow rate oscillating between 2 values during the air loop / zone
4387 : // equipment iteration. If detected, set flow rate to previous value.
4388 94270 : if (((std::abs(MassFlow - this->MassFlow2) < this->MassFlowDiff) || (std::abs(MassFlow - this->MassFlow3) < this->MassFlowDiff)) &&
4389 25533 : (std::abs(MassFlow - this->MassFlow1) >= this->MassFlowDiff)) {
4390 0 : MassFlow = this->MassFlow1;
4391 : }
4392 :
4393 : // Move data to the damper outlet node
4394 68737 : this->sd_airterminalOutlet.AirTemp = this->sd_airterminalInlet.AirTemp;
4395 68737 : this->sd_airterminalOutlet.AirHumRat = this->sd_airterminalInlet.AirHumRat;
4396 68737 : this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
4397 68737 : this->sd_airterminalOutlet.AirMassFlowRateMaxAvail = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
4398 68737 : this->sd_airterminalOutlet.AirMassFlowRateMinAvail = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
4399 68737 : this->sd_airterminalOutlet.AirEnthalpy = this->sd_airterminalInlet.AirEnthalpy;
4400 :
4401 : // Calculate the Damper Position when there is a Max air flow specified.
4402 68737 : if (this->AirMassFlowRateMax == 0.0) {
4403 13 : this->DamperPosition = 0.0;
4404 : } else {
4405 68724 : this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
4406 : }
4407 :
4408 : // Need to make sure that the damper outlets are passed to the coil inlet
4409 68737 : this->UpdateSys(state);
4410 :
4411 68737 : QActualHeating = QToHeatSetPt - MassFlow * CpAirZn * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCBVAV);
4412 :
4413 89114 : if ((MassFlow > SmallMassFlow) && (QActualHeating > 0.0) &&
4414 20377 : (state.dataHeatBalFanSys->TempControlType(ZoneNum) != DataHVACGlobals::ThermostatType::SingleCooling)) {
4415 : // VAVHeatandCool boxes operate at varying mass flow rates when reheating, VAV boxes operate at min flow
4416 : // (MassFlow <= this->sd_airterminalInlet%AirMassFlowRateMinAvail) .AND. &
4417 : // Per Fred Buhl, don't use DeadBandOrSetback to determine if heaters operate
4418 : // (.NOT. DeadBandOrSetback(ZoneNum))) Then
4419 :
4420 : // At this point we know that there is a heating requirement: i.e., the heating coil needs to
4421 : // be activated (there's a zone heating load or there's a reheat requirement). There are 3 possible
4422 : // situations: 1) the coil load can be met by variable temperature air (below the max heat temp) at
4423 : // the minimum air mass flow rate; 2) the coil load can be met by variable air flow rate with the air
4424 : // temperature fixed at the max heat temp; 3) the load cannot be met (we will run at max air temp and
4425 : // max air flow rate). We check for condition 2 by assuming the air temperatute is at the max heat temp
4426 : // and solving for the air mass flow rate that will meet the load. If the flow rate is between the min and
4427 : // max we are in condition 2.
4428 :
4429 20377 : state.dataSingleDuct->QZoneMax2SCBVAV = QToHeatSetPt;
4430 :
4431 20377 : if (this->MaxReheatTempSetByUser) {
4432 :
4433 5043 : state.dataSingleDuct->MaxHeatTempSCBVAV = this->MaxReheatTemp;
4434 5043 : if (QToHeatSetPt > SmallLoad) { // zone has a positive load to heating setpoint
4435 5043 : state.dataSingleDuct->MassFlowReqSCBVAV =
4436 5043 : QToHeatSetPt / (CpAirZn * (state.dataSingleDuct->MaxHeatTempSCBVAV - state.dataSingleDuct->ZoneTempSCBVAV));
4437 : } else {
4438 0 : state.dataSingleDuct->MassFlowReqSCBVAV = MassFlow;
4439 : }
4440 :
4441 5043 : state.dataSingleDuct->QZoneMax3SCBVAV =
4442 5043 : CpAirZn * (state.dataSingleDuct->MaxHeatTempSCBVAV - state.dataSingleDuct->ZoneTempSCBVAV) * MassFlow;
4443 :
4444 5043 : state.dataSingleDuct->MassFlowActualSCBVAV = MassFlow;
4445 :
4446 5043 : if (state.dataSingleDuct->QZoneMax3SCBVAV < QToHeatSetPt) {
4447 2419 : state.dataSingleDuct->MassFlowActualSCBVAV = state.dataSingleDuct->MassFlowReqSCBVAV;
4448 : // QZoneMax3 = CpAirZn * (MaxHeatTemp - ZoneTemp) * MassFlowActual
4449 : }
4450 :
4451 5043 : if (state.dataSingleDuct->MassFlowActualSCBVAV <= state.dataSingleDuct->MinMassAirFlowSCBVAV) {
4452 0 : state.dataSingleDuct->MassFlowActualSCBVAV = state.dataSingleDuct->MinMassAirFlowSCBVAV;
4453 5043 : } else if (state.dataSingleDuct->MassFlowActualSCBVAV >= this->AirMassFlowRateMax) {
4454 3820 : state.dataSingleDuct->MassFlowActualSCBVAV = this->AirMassFlowRateMax;
4455 : }
4456 :
4457 10086 : state.dataSingleDuct->QZoneMaxSCBVAV = CpAirZn * state.dataSingleDuct->MassFlowActualSCBVAV *
4458 5043 : (state.dataSingleDuct->MaxHeatTempSCBVAV - state.dataSingleDuct->ZoneTempSCBVAV);
4459 :
4460 : // temporary variable
4461 5043 : state.dataSingleDuct->QZoneMax2SCBVAV = min(state.dataSingleDuct->QZoneMaxSCBVAV, QToHeatSetPt);
4462 :
4463 5043 : MassFlow = state.dataSingleDuct->MassFlowActualSCBVAV;
4464 :
4465 : } // IF (sd_airterminal(SysNum)%MaxReheatTempSetByUser) THEN
4466 :
4467 20377 : this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
4468 :
4469 20377 : this->UpdateSys(state);
4470 :
4471 20377 : switch (this->ReheatComp_Num) { // hot water heating coil
4472 0 : case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
4473 : // Determine the load required to pass to the Component controller
4474 : // Although this equation looks strange (using temp instead of deltaT), it is corrected later in ControlCompOutput
4475 : // and is working as-is, temperature setpoints are maintained as expected.
4476 0 : QZnReq = state.dataSingleDuct->QZoneMax2SCBVAV + MassFlow * CpAirZn * state.dataLoopNodes->Node(ZoneNodeNum).Temp;
4477 0 : if (QZnReq < SmallLoad) QZnReq = 0.0;
4478 :
4479 : // Initialize hot water flow rate to zero.
4480 : // Node(sd_airterminal(SysNum)%ReheatControlNode)%MassFlowRate = 0.0D0
4481 0 : DummyMdot = 0.0;
4482 0 : SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
4483 : // On the first HVAC iteration the system values are given to the controller, but after that
4484 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
4485 0 : if (FirstHVACIteration) {
4486 0 : MaxFlowWater = this->MaxReheatWaterFlow;
4487 0 : MinFlowWater = this->MinReheatWaterFlow;
4488 : } else {
4489 0 : WaterControlNode = this->ReheatControlNode;
4490 0 : MaxFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMaxAvail;
4491 0 : MinFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMinAvail;
4492 : }
4493 :
4494 : // Simulate the reheat coil at constant air flow. Control by varying the
4495 : // hot water flow rate.
4496 0 : ControlCompOutput(state,
4497 : this->ReheatName,
4498 : this->ReheatComp,
4499 : this->ReheatComp_Index,
4500 : FirstHVACIteration,
4501 : QZnReq,
4502 : this->ReheatControlNode,
4503 : MaxFlowWater,
4504 : MinFlowWater,
4505 : this->ControllerOffset,
4506 : this->ControlCompTypeNum,
4507 : this->CompErrIndex,
4508 : _,
4509 : SysOutletNode,
4510 : MassFlow,
4511 : _,
4512 : _,
4513 : this->HWplantLoc);
4514 :
4515 : // If reverse action damper and the hot water flow is at maximum, simulate the
4516 : // hot water coil with fixed (maximum) hot water flow but allow the air flow to
4517 : // vary up to the maximum (air damper opens to try to meet zone load).
4518 0 : if (this->DamperHeatingAction == Action::Reverse) {
4519 0 : if (state.dataLoopNodes->Node(this->ReheatControlNode).MassFlowRate == this->MaxReheatWaterFlow) {
4520 0 : ControlCompOutput(state,
4521 : this->ReheatName,
4522 : this->ReheatComp,
4523 : this->ReheatComp_Index,
4524 : FirstHVACIteration,
4525 0 : state.dataSingleDuct->QZoneMax2SCBVAV,
4526 : this->OutletNodeNum,
4527 : this->sd_airterminalInlet.AirMassFlowRateMaxAvail,
4528 : this->sd_airterminalInlet.AirMassFlowRateMinAvail,
4529 : this->ControllerOffset,
4530 : this->ControlCompTypeNum,
4531 : this->CompErrIndex,
4532 : ZoneNodeNum,
4533 : SysOutletNode);
4534 : // ! air flow controller, not on plant, don't pass plant topology info
4535 :
4536 : // reset terminal unit inlet air mass flow to new value.
4537 0 : MassFlow = state.dataLoopNodes->Node(SysOutletNode).MassFlowRate;
4538 0 : this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
4539 0 : this->UpdateSys(state);
4540 : }
4541 : // look for bang-bang condition: flow rate oscillating between 2 values during the air loop / zone
4542 : // equipment iteration. If detected, set flow rate to previous value and recalc HW flow.
4543 0 : if (((std::abs(MassFlow - this->MassFlow2) < this->MassFlowDiff) || (std::abs(MassFlow - this->MassFlow3) < this->MassFlowDiff)) &&
4544 0 : (std::abs(MassFlow - this->MassFlow1) >= this->MassFlowDiff)) {
4545 0 : MassFlow = this->MassFlow1;
4546 0 : this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
4547 0 : this->UpdateSys(state);
4548 0 : ControlCompOutput(state,
4549 : this->ReheatName,
4550 : this->ReheatComp,
4551 : this->ReheatComp_Index,
4552 : FirstHVACIteration,
4553 : QZnReq,
4554 : this->ReheatControlNode,
4555 : MaxFlowWater,
4556 : MinFlowWater,
4557 : this->ControllerOffset,
4558 : this->ControlCompTypeNum,
4559 : this->CompErrIndex,
4560 : _,
4561 : SysOutletNode,
4562 : MassFlow,
4563 : _,
4564 : _,
4565 : this->HWplantLoc);
4566 : }
4567 : // recalculate damper position
4568 0 : if (this->AirMassFlowRateMax == 0.0) {
4569 0 : this->DamperPosition = 0.0;
4570 : } else {
4571 0 : this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
4572 : }
4573 : }
4574 0 : } break;
4575 0 : case HeatingCoilType::SteamAirHeating: { // ! COIL:STEAM:AIRHEATING
4576 : // Determine the load required to pass to the Component controller
4577 0 : QZnReq = state.dataSingleDuct->QZoneMax2SCBVAV -
4578 0 : MassFlow * CpAirZn * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCBVAV);
4579 0 : if (QZnReq < SmallLoad) QZnReq = 0.0;
4580 :
4581 : // Simulate reheat coil for the VAV system
4582 0 : SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, QZnReq);
4583 0 : } break;
4584 13167 : case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
4585 : // Determine the load required to pass to the Component controller
4586 13167 : QSupplyAir = MassFlow * CpAirZn * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCBVAV);
4587 13167 : QZnReq = state.dataSingleDuct->QZoneMax2SCBVAV - QSupplyAir;
4588 13167 : if (QZnReq < SmallLoad) QZnReq = 0.0;
4589 :
4590 : // Simulate reheat coil for the VAV system
4591 13167 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index);
4592 13167 : } break;
4593 0 : case HeatingCoilType::Gas: { // COIL:GAS:HEATING
4594 : // Determine the load required to pass to the Component controller
4595 0 : QZnReq = state.dataSingleDuct->QZoneMax2SCBVAV -
4596 0 : MassFlow * CpAirZn * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCBVAV);
4597 0 : if (QZnReq < SmallLoad) QZnReq = 0.0;
4598 :
4599 : // Simulate reheat coil for the VAV system
4600 0 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index);
4601 0 : } break;
4602 7210 : case HeatingCoilType::None: { // blank
4603 : // If no reheat is defined then assume that the damper is the only component.
4604 : // If something else is there that is not a reheat coil then give the error message below.
4605 7210 : } break;
4606 0 : default: {
4607 0 : ShowFatalError(state, "Invalid Reheat Component=" + this->ReheatComp);
4608 0 : } break;
4609 : }
4610 :
4611 : // the COIL is OFF the properties are calculated for this special case.
4612 : } else {
4613 48360 : switch (this->ReheatComp_Num) {
4614 0 : case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
4615 : // Simulate reheat coil for the Const Volume system
4616 : // Node(sd_airterminal(SysNum)%ReheatControlNode)%MassFlowRate = 0.0D0
4617 : // Initialize hot water flow rate to zero.
4618 0 : DummyMdot = 0.0;
4619 0 : SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
4620 :
4621 : // call the reheat coil with the NO FLOW condition to make sure that the Node values
4622 : // are passed through to the coil outlet correctly
4623 0 : SimulateWaterCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index);
4624 0 : } break;
4625 0 : case HeatingCoilType::SteamAirHeating: { // COIL:STEAM:AIRHEATING
4626 : // Simulate reheat coil for the VAV system
4627 0 : SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, 0.0);
4628 0 : } break;
4629 33900 : case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
4630 : // Simulate reheat coil for the VAV system
4631 33900 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
4632 33900 : } break;
4633 0 : case HeatingCoilType::Gas: { // COIL:GAS:HEATING
4634 : // Simulate reheat coil for the VAV system
4635 0 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
4636 0 : } break;
4637 14460 : case HeatingCoilType::None: { // blank
4638 : // If no reheat is defined then assume that the damper is the only component.
4639 : // If something else is there that is not a reheat coil then give the error message
4640 14460 : } break;
4641 0 : default: {
4642 0 : ShowFatalError(state, "Invalid Reheat Component=" + this->ReheatComp);
4643 0 : } break;
4644 : }
4645 : }
4646 : // push the flow rate history
4647 68737 : this->MassFlow3 = this->MassFlow2;
4648 68737 : this->MassFlow2 = this->MassFlow1;
4649 68737 : this->MassFlow1 = MassFlow;
4650 68737 : }
4651 :
4652 31064 : void SingleDuctAirTerminal::SimVAVVS(EnergyPlusData &state, bool const FirstHVACIteration, int const ZoneNum, int const ZoneNodeNum)
4653 : {
4654 :
4655 : // SUBROUTINE INFORMATION:
4656 : // AUTHOR Fred Buhl
4657 : // DATE WRITTEN July 2004
4658 : // MODIFIED na
4659 : // RE-ENGINEERED na
4660 :
4661 : // PURPOSE OF THIS SUBROUTINE:
4662 : // This subroutine simulates a single duct VAV terminal unit with a variable-speed fan upstream
4663 : // and a reheat coil on the downstream side.
4664 :
4665 : // METHODOLOGY EMPLOYED:
4666 : // Define a compound component in CalcVAVVS. Break the heating/cooling load into 4 regions based
4667 : // on equip on/off combinations. Assign the heating load to the appropriate region and iteratively
4668 : // solve for the appropriate control variable value using Regula-Falsi solver.
4669 :
4670 : // Using/Aliasing
4671 : using namespace DataZoneEnergyDemands;
4672 : using General::SolveRoot;
4673 : using SteamCoils::GetCoilCapacity;
4674 :
4675 : // SUBROUTINE PARAMETER DEFINITIONS:
4676 31064 : Real64 constexpr BigLoad(1.0e+20);
4677 :
4678 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
4679 31064 : Real64 MassFlow = 0; // [kg/sec] Total Mass Flow Rate from Hot & Cold Inlets
4680 : Real64 QTotLoad; // [Watts]
4681 : // unused REAL(r64) :: QZnReq ! [Watts]
4682 : Real64 CpAirZn;
4683 : // unused REAL(r64) :: CpAirSysIn
4684 : // unused REAL(r64) :: DeltaTemp
4685 : int SysOutletNode; // The node number of the terminal unit outlet node
4686 : int SysInletNode; // the node number of the terminal unit inlet node
4687 : int WaterControlNode; // This is the Actuated Reheat Control Node
4688 : int SteamControlNode;
4689 : Real64 MaxFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
4690 : Real64 MinFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
4691 : Real64 MaxFlowSteam; // This is the value passed to the Controller depending if FirstHVACIteration or not
4692 : Real64 MinFlowSteam; // This is the value passed to the Controller depending if FirstHVACIteration or not
4693 : Real64 HWFlow; // the hot water flow rate [kg/s]
4694 : Real64 QCoolFanOnMax; // max cooling - fan at max flow; note that cooling is always < 0. [W]
4695 : Real64 QCoolFanOnMin; // min active cooling with fan on - fan at lowest speed. [W]
4696 : Real64 QHeatFanOnMax; // max heating - fan at heat flow max, hot water flow at max [W]
4697 : Real64 QHeatFanOnMin; // min heating - fan at min flow, hot water at max flow [W]
4698 : Real64 QHeatFanOffMax; // max heating - fan off, hot water flow at max [W]
4699 : Real64 QNoHeatFanOff; // min heating - fan off, hot water at min flow [W]
4700 : HeatingCoilType HCType; // heating coil type
4701 : int FanType; // fan type (as a number)
4702 : Real64 HCLoad; // load passed to a gas or electric heating coil [W]
4703 : int FanOp; // 1 if fan is on; 0 if off.
4704 : Real64 MaxCoolMassFlow; // air flow at max cooling [kg/s]
4705 : Real64 MaxHeatMassFlow; // air flow at max heating [kg/s]
4706 : Real64 MinMassFlow; // minimum air flow rate [kg/s]
4707 : Real64 UnitFlowToler; // flow rate tolerance
4708 : Real64 QDelivered;
4709 : Real64 FracDelivered;
4710 : int SolFlag;
4711 : Real64 ErrTolerance;
4712 : Real64 MaxSteamCap; // steam coil capacity at full load
4713 : bool ErrorsFound; // returned from mining function call
4714 :
4715 : // The calculated load from the Heat Balance
4716 31064 : QTotLoad = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired;
4717 31064 : SysOutletNode = this->ReheatAirOutletNode;
4718 31064 : SysInletNode = this->InletNodeNum;
4719 31064 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(ZoneNodeNum).HumRat);
4720 31064 : HCType = this->ReheatComp_Num;
4721 31064 : FanType = this->Fan_Num;
4722 31064 : MaxCoolMassFlow = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
4723 31064 : MaxHeatMassFlow = min(this->HeatAirMassFlowRateMax, this->sd_airterminalInlet.AirMassFlowRateMaxAvail);
4724 31064 : MinMassFlow = MaxCoolMassFlow * this->ZoneMinAirFrac;
4725 31064 : UnitFlowToler = 0.001 * DataConvergParams::HVACFlowRateToler;
4726 31064 : QDelivered = 0.0;
4727 31064 : HWFlow = 0.0;
4728 31064 : if (this->sd_airterminalInlet.AirMassFlowRateMaxAvail <= 0.0 || state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
4729 7914 : MassFlow = 0.0;
4730 7914 : FanOp = 0;
4731 7914 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, 0.0, 0.0, FanType, MassFlow, FanOp, QDelivered);
4732 7914 : return;
4733 : }
4734 :
4735 23150 : if (HCType == HeatingCoilType::SimpleHeating) {
4736 23150 : WaterControlNode = this->ReheatControlNode;
4737 23150 : HCLoad = 0.0;
4738 23150 : if (FirstHVACIteration) {
4739 11572 : MaxFlowWater = this->MaxReheatWaterFlow;
4740 11572 : MinFlowWater = this->MinReheatWaterFlow;
4741 : } else {
4742 11578 : WaterControlNode = this->ReheatControlNode;
4743 11578 : MaxFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMaxAvail;
4744 11578 : MinFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMinAvail;
4745 : }
4746 : } else {
4747 0 : WaterControlNode = 0;
4748 0 : HCLoad = BigLoad;
4749 0 : MaxFlowWater = 0.0;
4750 0 : MinFlowWater = 0.0;
4751 : }
4752 :
4753 23150 : if (HCType == HeatingCoilType::SteamAirHeating) {
4754 0 : SteamControlNode = this->ReheatControlNode;
4755 0 : HCLoad = 0.0;
4756 0 : if (FirstHVACIteration) {
4757 0 : MaxFlowSteam = this->MaxReheatSteamFlow;
4758 0 : MinFlowSteam = this->MinReheatSteamFlow;
4759 : } else {
4760 0 : MaxFlowSteam = state.dataLoopNodes->Node(SteamControlNode).MassFlowRateMaxAvail;
4761 0 : MinFlowSteam = state.dataLoopNodes->Node(SteamControlNode).MassFlowRateMinAvail;
4762 : }
4763 : } else {
4764 23150 : SteamControlNode = 0;
4765 23150 : HCLoad = BigLoad;
4766 23150 : MaxFlowSteam = 0.0;
4767 23150 : MinFlowSteam = 0.0;
4768 : }
4769 :
4770 : // define 3 load regions and assign the current load to the correct region.
4771 : // region 1: active cooling with fan on
4772 23150 : FanOp = 1;
4773 23150 : if (HCType == HeatingCoilType::SteamAirHeating) {
4774 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowSteam, 0.0, FanType, MaxCoolMassFlow, FanOp, QCoolFanOnMax);
4775 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowSteam, 0.0, FanType, MinMassFlow, FanOp, QCoolFanOnMin);
4776 : // region 2: active heating with fan on
4777 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowSteam, BigLoad, FanType, MaxHeatMassFlow, FanOp, QHeatFanOnMax);
4778 0 : MaxSteamCap = GetCoilCapacity(state, this->ReheatComp, this->ReheatName, ErrorsFound);
4779 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowSteam, 0.0, FanType, MinMassFlow, FanOp, QHeatFanOnMin);
4780 : // region 3: active heating with fan off
4781 0 : FanOp = 0;
4782 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowSteam, BigLoad, FanType, MinMassFlow, FanOp, QHeatFanOffMax);
4783 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowSteam, 0.0, FanType, MinMassFlow, FanOp, QNoHeatFanOff);
4784 : } else {
4785 23150 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowWater, 0.0, FanType, MaxCoolMassFlow, FanOp, QCoolFanOnMax);
4786 23150 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowWater, 0.0, FanType, MinMassFlow, FanOp, QCoolFanOnMin);
4787 : // region 2: active heating with fan on
4788 23150 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, BigLoad, FanType, MaxHeatMassFlow, FanOp, QHeatFanOnMax);
4789 23150 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, 0.0, FanType, MinMassFlow, FanOp, QHeatFanOnMin);
4790 : // region 3: active heating with fan off
4791 23150 : FanOp = 0;
4792 23150 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, BigLoad, FanType, MinMassFlow, FanOp, QHeatFanOffMax);
4793 23150 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowWater, 0.0, FanType, MinMassFlow, FanOp, QNoHeatFanOff);
4794 : }
4795 :
4796 : // Active cooling with fix for issue #5592
4797 32314 : if (QTotLoad < (-1.0 * SmallLoad) && QTotLoad < (QCoolFanOnMin - SmallLoad) && this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0 &&
4798 9164 : !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
4799 : // check that it can meet the load
4800 9164 : FanOp = 1;
4801 9164 : if (QCoolFanOnMax < QTotLoad - SmallLoad) {
4802 9164 : Real64 MinHWFlow = (HCType == HeatingCoilType::SteamAirHeating) ? MinFlowSteam : MinFlowWater;
4803 :
4804 318178 : auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, MinHWFlow, FanType, FanOp, QTotLoad](Real64 const SupplyAirMassFlow) {
4805 45454 : Real64 UnitOutput = 0.0; // cooling output [W] (cooling is negative)
4806 :
4807 90908 : state.dataSingleDuct->sd_airterminal(this->SysNum)
4808 90908 : .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinHWFlow, 0.0, FanType, SupplyAirMassFlow, FanOp, UnitOutput);
4809 90908 : return (QTotLoad - UnitOutput) / QTotLoad;
4810 9164 : };
4811 :
4812 9164 : SolveRoot(state, UnitFlowToler, 50, SolFlag, MassFlow, f, MinMassFlow, MaxCoolMassFlow);
4813 9164 : if (SolFlag == -1) {
4814 0 : if (this->IterationLimit == 0) {
4815 0 : ShowWarningError(state, "Supply air flow control failed in VS VAV terminal unit " + this->SysName);
4816 0 : ShowContinueError(state, " Iteration limit exceeded in calculating air flow rate");
4817 : }
4818 0 : ShowRecurringWarningErrorAtEnd(
4819 0 : state, "Supply air flow Iteration limit exceeded in VS VAV terminal unit " + this->SysName, this->IterationLimit);
4820 9164 : } else if (SolFlag == -2) {
4821 0 : if (this->IterationFailed == 0) {
4822 0 : ShowWarningError(state, "Supply air flow control failed in VS VAV terminal unit " + this->SysName);
4823 0 : ShowContinueError(state, " Bad air flow limits");
4824 : }
4825 0 : ShowRecurringWarningErrorAtEnd(
4826 0 : state, "Supply air flow control failed in VS VAV terminal unit " + this->SysName, this->IterationFailed);
4827 : }
4828 :
4829 : } else {
4830 :
4831 0 : MassFlow = MaxCoolMassFlow;
4832 :
4833 0 : if (HCType == HeatingCoilType::SteamAirHeating) {
4834 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowSteam, 0.0, FanType, MassFlow, FanOp, QDelivered);
4835 : } else {
4836 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowWater, 0.0, FanType, MassFlow, FanOp, QDelivered);
4837 : }
4838 : }
4839 :
4840 : // no active heating or cooling
4841 41972 : } else if ((QTotLoad >= QCoolFanOnMin - SmallLoad && QTotLoad <= QNoHeatFanOff + SmallLoad &&
4842 27986 : this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0) ||
4843 27944 : (this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0 && state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum))) {
4844 14 : MassFlow = MinMassFlow;
4845 14 : FanOp = 0;
4846 14 : if (HCType == HeatingCoilType::SteamAirHeating) {
4847 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowSteam, QTotLoad, FanType, MassFlow, FanOp, QNoHeatFanOff);
4848 : } else {
4849 14 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MinFlowWater, 0.0, FanType, MassFlow, FanOp, QNoHeatFanOff);
4850 : }
4851 :
4852 : // active heating
4853 27944 : } else if (QTotLoad > QNoHeatFanOff + SmallLoad && this->sd_airterminalInlet.AirMassFlowRateMaxAvail > 0.0 &&
4854 13972 : !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum)) {
4855 : // hot water coil
4856 13972 : if (HCType == HeatingCoilType::SimpleHeating) {
4857 13972 : if (QTotLoad < QHeatFanOffMax - SmallLoad) {
4858 : // vary HW flow, leave air flow at minimum
4859 7595 : ErrTolerance = this->ControllerOffset;
4860 7595 : MassFlow = MinMassFlow;
4861 7595 : FanOp = 0;
4862 :
4863 846685 : auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, MassFlow, FanType, FanOp, QTotLoad](Real64 const HWMassFlow) {
4864 120955 : Real64 UnitOutput = 0.0; // heating output [W]
4865 120955 : Real64 QSteamLoad = 0.0; // proportional load to calculate steam flow [W]
4866 :
4867 241910 : state.dataSingleDuct->sd_airterminal(this->SysNum)
4868 241910 : .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, HWMassFlow, QSteamLoad, FanType, MassFlow, FanOp, UnitOutput);
4869 :
4870 241910 : return (QTotLoad - UnitOutput) / QTotLoad;
4871 7595 : };
4872 :
4873 7595 : SolveRoot(state, ErrTolerance, 500, SolFlag, HWFlow, f, MinFlowWater, MaxFlowWater);
4874 7595 : if (SolFlag == -1) {
4875 0 : ShowRecurringWarningErrorAtEnd(state, "Hot Water flow control failed in VS VAV terminal unit " + this->SysName, this->ErrCount1);
4876 0 : ShowRecurringContinueErrorAtEnd(
4877 : state, "...Iteration limit (500) exceeded in calculating the hot water flow rate", this->ErrCount1c);
4878 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, HWFlow, 0.0, FanType, MassFlow, FanOp, QDelivered);
4879 7595 : } else if (SolFlag == -2) {
4880 0 : ShowRecurringWarningErrorAtEnd(
4881 0 : state, "Hot Water flow control failed (bad air flow limits) in VS VAV terminal unit " + this->SysName, this->ErrCount2);
4882 : }
4883 6377 : } else if (QTotLoad >= QHeatFanOffMax - SmallLoad && QTotLoad <= QHeatFanOnMin + SmallLoad) {
4884 14 : MassFlow = MinMassFlow;
4885 14 : FanOp = 0;
4886 14 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, 0.0, FanType, MassFlow, FanOp, QDelivered);
4887 6363 : } else if (QTotLoad > QHeatFanOnMin + SmallLoad && QTotLoad < QHeatFanOnMax - SmallLoad) {
4888 : // set hot water flow to max and vary the supply air flow rate
4889 6345 : FanOp = 1;
4890 332038 : auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, FanType, FanOp, QTotLoad](Real64 const SupplyAirMassFlow) {
4891 47434 : Real64 UnitOutput = 0.0; // heating output [W]
4892 94868 : state.dataSingleDuct->sd_airterminal(this->SysNum)
4893 94868 : .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, QTotLoad, FanType, SupplyAirMassFlow, FanOp, UnitOutput);
4894 :
4895 94868 : return (QTotLoad - UnitOutput) / QTotLoad;
4896 6345 : };
4897 6345 : SolveRoot(state, UnitFlowToler, 50, SolFlag, MassFlow, f, MinMassFlow, MaxHeatMassFlow);
4898 6345 : if (SolFlag == -1) {
4899 0 : if (this->IterationLimit == 0) {
4900 0 : ShowWarningError(state, "Supply air flow control failed in VS VAV terminal unit " + this->SysName);
4901 0 : ShowContinueError(state, " Iteration limit exceeded in calculating air flow rate");
4902 : }
4903 0 : ShowRecurringWarningErrorAtEnd(
4904 0 : state, "Supply air flow Iteration limit exceeded in VS VAV terminal unit " + this->SysName, this->IterationLimit);
4905 6345 : } else if (SolFlag == -2) {
4906 0 : if (this->IterationFailed == 0) {
4907 0 : ShowWarningError(state, "Supply air flow control failed in VS VAV terminal unit " + this->SysName);
4908 0 : ShowContinueError(state, " Bad air flow limits");
4909 : }
4910 0 : ShowRecurringWarningErrorAtEnd(
4911 0 : state, "Supply air flow control failed in VS VAV terminal unit " + this->SysName, this->IterationFailed);
4912 6345 : }
4913 : } else {
4914 18 : MassFlow = MaxHeatMassFlow;
4915 18 : FanOp = 1;
4916 18 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, 0.0, FanType, MassFlow, FanOp, QDelivered);
4917 : }
4918 0 : } else if (HCType == HeatingCoilType::SteamAirHeating) {
4919 : // IF (QTotLoad > QNoHeatFanOff + SmallLoad .AND. QTotLoad < QHeatFanOffMax - SmallLoad) THEN
4920 0 : if (QTotLoad < QHeatFanOffMax - SmallLoad) {
4921 0 : ErrTolerance = this->ControllerOffset;
4922 0 : MassFlow = MinMassFlow;
4923 0 : FanOp = 0;
4924 : auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, MassFlow, FanType, FanOp, QTotLoad, MinFlowSteam, MaxFlowSteam, MaxSteamCap](
4925 0 : Real64 const HWMassFlow) {
4926 0 : Real64 UnitOutput = 0.0; // heating output [W]
4927 0 : Real64 QSteamLoad = 0.0; // proportional load to calculate steam flow [W]
4928 :
4929 : // vary the load to be met by the steam coil to converge on a steam flow rate to meet the load
4930 : // backwards way of varying steam flow rate. Steam coil calculates a flow rate to meet a load.
4931 0 : if ((MaxFlowSteam - MinFlowSteam) == 0.0) {
4932 0 : QSteamLoad = QTotLoad; // Use QTotLoad, bad starting value error for RegulaFalsi will occur
4933 : } else {
4934 0 : QSteamLoad = MaxSteamCap * HWMassFlow / (MaxFlowSteam - MinFlowSteam);
4935 : }
4936 0 : state.dataSingleDuct->sd_airterminal(this->SysNum)
4937 0 : .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, HWMassFlow, QSteamLoad, FanType, MassFlow, FanOp, UnitOutput);
4938 :
4939 0 : return (QTotLoad - UnitOutput) / QTotLoad;
4940 0 : };
4941 0 : SolveRoot(state, ErrTolerance, 500, SolFlag, HWFlow, f, MinFlowSteam, MaxFlowSteam);
4942 0 : if (SolFlag == -1) {
4943 0 : ShowRecurringWarningErrorAtEnd(state, "Steam flow control failed in VS VAV terminal unit " + this->SysName, this->ErrCount1);
4944 0 : ShowRecurringContinueErrorAtEnd(
4945 : state, "...Iteration limit (500) exceeded in calculating the hot water flow rate", this->ErrCount1c);
4946 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, HWFlow, 0.0, FanType, MassFlow, FanOp, QDelivered);
4947 0 : } else if (SolFlag == -2) {
4948 0 : ShowRecurringWarningErrorAtEnd(
4949 0 : state, "Steam flow control failed (bad air flow limits) in VS VAV terminal unit " + this->SysName, this->ErrCount2);
4950 : }
4951 0 : } else if (QTotLoad >= QHeatFanOffMax - SmallLoad && QTotLoad <= QHeatFanOnMin + SmallLoad) {
4952 0 : MassFlow = MinMassFlow;
4953 0 : FanOp = 0;
4954 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowWater, 0.0, FanType, MassFlow, FanOp, QDelivered);
4955 0 : } else if (QTotLoad > QHeatFanOnMin + SmallLoad && QTotLoad < QHeatFanOnMax - SmallLoad) {
4956 0 : FanOp = 1;
4957 :
4958 0 : auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, MaxFlowSteam, FanType, FanOp, QTotLoad](Real64 const SupplyAirMassFlow) {
4959 0 : Real64 UnitOutput = 0.0; // heating output [W]
4960 :
4961 0 : state.dataSingleDuct->sd_airterminal(this->SysNum)
4962 0 : .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, MaxFlowSteam, QTotLoad, FanType, SupplyAirMassFlow, FanOp, UnitOutput);
4963 :
4964 0 : return (QTotLoad - UnitOutput) / QTotLoad;
4965 0 : };
4966 :
4967 0 : SolveRoot(state, UnitFlowToler, 50, SolFlag, MassFlow, f, MinMassFlow, MaxHeatMassFlow);
4968 0 : if (SolFlag == -1) {
4969 0 : if (this->IterationLimit == 0) {
4970 0 : ShowWarningError(state, "Steam heating coil control failed in VS VAV terminal unit " + this->SysName);
4971 0 : ShowContinueError(state, " Iteration limit exceeded in calculating air flow rate");
4972 : }
4973 0 : ShowRecurringWarningErrorAtEnd(
4974 0 : state, "Steam heating coil iteration limit exceeded in VS VAV terminal unit " + this->SysName, this->IterationLimit);
4975 0 : } else if (SolFlag == -2) {
4976 0 : if (this->IterationFailed == 0) {
4977 0 : ShowWarningError(state, "Steam heating coil control failed in VS VAV terminal unit " + this->SysName);
4978 0 : ShowContinueError(state, " Bad air flow limits");
4979 : }
4980 0 : ShowRecurringWarningErrorAtEnd(
4981 0 : state, "Steam heating coil control failed in VS VAV terminal unit " + this->SysName, this->IterationFailed);
4982 0 : }
4983 : } else {
4984 0 : MassFlow = MaxHeatMassFlow;
4985 0 : FanOp = 1;
4986 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, QTotLoad, QTotLoad, FanType, MassFlow, FanOp, QDelivered);
4987 : }
4988 0 : } else if (HCType == HeatingCoilType::Gas || HCType == HeatingCoilType::Electric) {
4989 0 : if (QTotLoad <= QHeatFanOnMin + SmallLoad) {
4990 : // vary heating coil power, leave mass flow at minimum
4991 0 : MassFlow = MinMassFlow;
4992 0 : FanOp = 0;
4993 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, 0.0, QTotLoad, FanType, MassFlow, FanOp, QDelivered);
4994 0 : } else if (QTotLoad > QHeatFanOnMin + SmallLoad && QTotLoad < QHeatFanOnMax - SmallLoad) {
4995 0 : FanOp = 1;
4996 :
4997 0 : auto f = [&state, this, FirstHVACIteration, ZoneNodeNum, FanType, FanOp, QTotLoad](Real64 const HeatingFrac) {
4998 0 : Real64 MaxHeatOut{this->ReheatCoilMaxCapacity}; // maximum heating output [W]
4999 : Real64 UnitOutput; // heating output [W]
5000 : Real64 AirMassFlowRate; // [kg/s]
5001 : Real64 HeatOut; // heating coil output [W]
5002 :
5003 0 : HeatOut = HeatingFrac * MaxHeatOut;
5004 0 : AirMassFlowRate = max(HeatingFrac * state.dataSingleDuct->sd_airterminal(this->SysNum).HeatAirMassFlowRateMax,
5005 0 : state.dataSingleDuct->sd_airterminal(this->SysNum).sd_airterminalInlet.AirMassFlowRateMaxAvail *
5006 0 : state.dataSingleDuct->sd_airterminal(this->SysNum).ZoneMinAirFrac);
5007 :
5008 0 : state.dataSingleDuct->sd_airterminal(this->SysNum)
5009 0 : .CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, 0.0, HeatOut, FanType, AirMassFlowRate, FanOp, UnitOutput);
5010 :
5011 0 : return (QTotLoad - UnitOutput) / QTotLoad;
5012 0 : };
5013 :
5014 0 : SolveRoot(state, UnitFlowToler, 50, SolFlag, FracDelivered, f, 0.0, 1.0);
5015 0 : MassFlow = state.dataLoopNodes->Node(SysInletNode).MassFlowRate;
5016 0 : if (SolFlag == -1) {
5017 0 : if (this->IterationLimit == 0) {
5018 0 : ShowWarningError(state, "Heating coil control failed in VS VAV terminal unit " + this->SysName);
5019 0 : ShowContinueError(state, " Iteration limit exceeded in calculating air flow rate");
5020 : }
5021 0 : ShowRecurringWarningErrorAtEnd(
5022 0 : state, "Heating coil control iteration limit exceeded in VS VAV terminal unit " + this->SysName, this->IterationLimit);
5023 0 : } else if (SolFlag == -2) {
5024 0 : if (this->IterationFailed == 0) {
5025 0 : ShowWarningError(state, "Heating coil control failed in VS VAV terminal unit " + this->SysName);
5026 0 : ShowContinueError(state, " Bad air flow limits");
5027 : }
5028 0 : ShowRecurringWarningErrorAtEnd(
5029 0 : state, "Heating coil control failed in VS VAV terminal unit " + this->SysName, this->IterationFailed);
5030 0 : }
5031 : } else {
5032 0 : MassFlow = MaxHeatMassFlow;
5033 0 : FanOp = 1;
5034 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, 0.0, QTotLoad, FanType, MassFlow, FanOp, QDelivered);
5035 0 : }
5036 : } else {
5037 0 : ShowFatalError(state, "Invalid Reheat Component=" + this->ReheatComp);
5038 : }
5039 :
5040 : } else {
5041 :
5042 0 : MassFlow = 0.0;
5043 0 : FanOp = 0;
5044 0 : this->CalcVAVVS(state, FirstHVACIteration, ZoneNodeNum, 0.0, 0.0, FanType, MassFlow, FanOp, QDelivered);
5045 : }
5046 :
5047 : // Move mass flow rates to the damper outlet node
5048 23150 : this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
5049 23150 : this->sd_airterminalOutlet.AirMassFlowRateMaxAvail = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
5050 23150 : this->sd_airterminalOutlet.AirMassFlowRateMinAvail = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
5051 :
5052 : // calculate VAV damper Position.
5053 23150 : if (this->AirMassFlowRateMax == 0.0) {
5054 0 : this->DamperPosition = 0.0;
5055 : } else {
5056 23150 : this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
5057 : }
5058 : // update the air terminal outlet node data
5059 23150 : this->UpdateSys(state);
5060 : }
5061 :
5062 1679042 : void SingleDuctAirTerminal::SimConstVol(EnergyPlusData &state, bool const FirstHVACIteration, int const ZoneNum, int const ZoneNodeNum)
5063 : {
5064 :
5065 : // SUBROUTINE INFORMATION:
5066 : // AUTHOR Richard J. Liesen
5067 : // DATE WRITTEN February 2000
5068 : // MODIFIED FB/KHL/TH 2/2011: added maximum supply air temperature leaving reheat coil
5069 : // RE-ENGINEERED na
5070 :
5071 : // PURPOSE OF THIS SUBROUTINE:
5072 : // This subroutine simulates the simple single duct constant volume systems.
5073 :
5074 : // METHODOLOGY EMPLOYED:
5075 : // There is method to this madness.
5076 :
5077 : // REFERENCES:
5078 : // na
5079 :
5080 : // Using/Aliasing
5081 : using namespace DataZoneEnergyDemands;
5082 : // unused USE DataHeatBalFanSys, ONLY: Mat
5083 : using HeatingCoils::SimulateHeatingCoilComponents;
5084 : using PlantUtilities::SetActuatedBranchFlowRate;
5085 : using SteamCoils::SimulateSteamCoilComponents;
5086 : using WaterCoils::SimulateWaterCoilComponents;
5087 :
5088 : // Locals
5089 : // SUBROUTINE ARGUMENT DEFINITIONS:
5090 :
5091 : // SUBROUTINE PARAMETER DEFINITIONS:
5092 :
5093 : // INTERFACE BLOCK SPECIFICATIONS
5094 : // na
5095 :
5096 : // DERIVED TYPE DEFINITIONS
5097 : // na
5098 :
5099 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5100 : Real64 MassFlow; // [kg/sec] Total Mass Flow Rate from Hot & Cold Inlets
5101 : Real64 QZnReq; // [Watts]
5102 : Real64 QToHeatSetPt; // [W] remaining load to heating setpoint
5103 : Real64 CpAir;
5104 : int WaterControlNode; // This is the Actuated Reheat Control Node
5105 : Real64 MaxFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
5106 : Real64 MinFlowWater; // This is the value passed to the Controller depending if FirstHVACIteration or not
5107 : Real64 QActualHeating; // the heating load seen by the reheat coil
5108 : Real64 DummyMdot; // local fluid mass flow rate
5109 :
5110 1679042 : QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP; // The calculated load from the Heat Balance
5111 1679042 : MassFlow = this->sd_airterminalInlet.AirMassFlowRateMaxAvail; // System massflow is set to the Available
5112 1679042 : state.dataSingleDuct->QMax2SCV = QToHeatSetPt;
5113 1679042 : state.dataSingleDuct->ZoneTempSCV = state.dataLoopNodes->Node(ZoneNodeNum).Temp;
5114 1679042 : CpAir = PsyCpAirFnW(state.dataLoopNodes->Node(ZoneNodeNum).HumRat); // zone air specific heat
5115 1679042 : if (this->MaxReheatTempSetByUser) {
5116 10665 : state.dataSingleDuct->TAirMaxSCV = this->MaxReheatTemp;
5117 10665 : state.dataSingleDuct->QMaxSCV = CpAir * MassFlow * (state.dataSingleDuct->TAirMaxSCV - state.dataSingleDuct->ZoneTempSCV);
5118 10665 : state.dataSingleDuct->QMax2SCV = min(QToHeatSetPt, state.dataSingleDuct->QMaxSCV);
5119 : } // if (this->MaxReheatTempSetByUser) {
5120 :
5121 2680060 : if (((this->sd_airterminalInlet.AirMassFlowRateMaxAvail == 0.0) && (this->sd_airterminalInlet.AirMassFlowRateMinAvail == 0.0)) ||
5122 1001018 : (this->sd_airterminalInlet.AirMassFlowRate == 0.0)) {
5123 : // System is Off set massflow to 0.0
5124 678024 : MassFlow = 0.0;
5125 : }
5126 :
5127 : // Calculate the Damper Position when there is a Max air flow specified.
5128 1679042 : if (this->AirMassFlowRateMax == 0.0) {
5129 43 : this->DamperPosition = 0.0;
5130 : } else {
5131 1678999 : this->DamperPosition = MassFlow / this->AirMassFlowRateMax;
5132 : }
5133 :
5134 : // make sure the inlet node flow rate is updated if the mass flow has been limited
5135 1679042 : this->sd_airterminalOutlet.AirMassFlowRate = MassFlow;
5136 1679042 : this->sd_airterminalOutlet.AirMassFlowRateMaxAvail = this->sd_airterminalInlet.AirMassFlowRateMaxAvail;
5137 1679042 : this->sd_airterminalOutlet.AirMassFlowRateMinAvail = this->sd_airterminalInlet.AirMassFlowRateMinAvail;
5138 1679042 : this->UpdateSys(state);
5139 :
5140 1679042 : QActualHeating = QToHeatSetPt - MassFlow * CpAir * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCV); // reheat needed
5141 : // Now the massflow for reheating has been determined. If it is zero, or in SetBack, or the
5142 : // system scheduled OFF then not operational and shut the system down.
5143 2442511 : if ((MassFlow > SmallMassFlow) && (QActualHeating > 0.0) &&
5144 763469 : (state.dataHeatBalFanSys->TempControlType(ZoneNum) != DataHVACGlobals::ThermostatType::SingleCooling)) {
5145 :
5146 486019 : switch (this->ReheatComp_Num) {
5147 434210 : case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
5148 : // Determine the load required to pass to the Component controller
5149 434210 : QZnReq = state.dataSingleDuct->QMax2SCV + MassFlow * CpAir * state.dataSingleDuct->ZoneTempSCV;
5150 :
5151 : // Before Iterating through the Reheat Coil and Controller set the flags for the
5152 : // Do Loop to initialized conditions.
5153 : // Node(sd_airterminal(SysNum)%ReheatControlNode)%MassFlowRate = 0.0D0
5154 : // Initialize hot water flow rate to zero.
5155 434210 : DummyMdot = 0.0;
5156 434210 : SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
5157 :
5158 : // On the first HVAC iteration the system values are given to the controller, but after that
5159 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
5160 434210 : if (FirstHVACIteration) {
5161 218673 : MaxFlowWater = this->MaxReheatWaterFlow;
5162 218673 : MinFlowWater = this->MinReheatWaterFlow;
5163 : } else {
5164 215537 : WaterControlNode = this->ReheatControlNode;
5165 215537 : MaxFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMaxAvail;
5166 215537 : MinFlowWater = state.dataLoopNodes->Node(WaterControlNode).MassFlowRateMinAvail;
5167 : }
5168 :
5169 : // Simulate reheat coil for the Const Volume system
5170 : // Set Converged to True & when controller is not converged it will set to False.
5171 434210 : ControlCompOutput(state,
5172 : this->ReheatName,
5173 : this->ReheatComp,
5174 : this->ReheatComp_Index,
5175 : FirstHVACIteration,
5176 : QZnReq,
5177 : this->ReheatControlNode,
5178 : MaxFlowWater,
5179 : MinFlowWater,
5180 : this->ControllerOffset,
5181 : this->ControlCompTypeNum,
5182 : this->CompErrIndex,
5183 : _,
5184 : this->ReheatAirOutletNode,
5185 : MassFlow,
5186 : _,
5187 : _,
5188 : this->HWplantLoc);
5189 :
5190 434210 : } break;
5191 0 : case HeatingCoilType::SteamAirHeating: { // COIL:STEAM:STEAMAIRHEATING
5192 : // Determine the load required to pass to the Component controller
5193 0 : QZnReq = state.dataSingleDuct->QMax2SCV - MassFlow * CpAir * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCV);
5194 :
5195 : // Simulate reheat coil for the VAV system
5196 0 : SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, QZnReq);
5197 0 : } break;
5198 4581 : case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
5199 : // Determine the load required to pass to the Component controller
5200 4581 : QZnReq = state.dataSingleDuct->QMax2SCV - MassFlow * CpAir * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCV);
5201 :
5202 : // Simulate reheat coil for the VAV system
5203 4581 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index);
5204 :
5205 4581 : } break;
5206 47228 : case HeatingCoilType::Gas: { // COIL:GAS:HEATING
5207 : // Determine the load required to pass to the Component controller
5208 47228 : QZnReq = state.dataSingleDuct->QMax2SCV - MassFlow * CpAir * (this->sd_airterminalInlet.AirTemp - state.dataSingleDuct->ZoneTempSCV);
5209 :
5210 : // Simulate reheat coil for the VAV system
5211 47228 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, QZnReq, this->ReheatComp_Index);
5212 47228 : } break;
5213 0 : default: {
5214 0 : ShowFatalError(state, "Invalid Reheat Component=" + this->ReheatComp);
5215 0 : } break;
5216 : }
5217 :
5218 : // the COIL is OFF the properties are calculated for this special case.
5219 : } else {
5220 1193023 : switch (this->ReheatComp_Num) {
5221 964587 : case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
5222 : // Simulate reheat coil for the Const Volume system
5223 : // Node(sd_airterminal(SysNum)%ReheatControlNode)%MassFlowRate = 0.0D0
5224 : // Initialize hot water flow rate to zero.
5225 964587 : DummyMdot = 0.0;
5226 964587 : SetActuatedBranchFlowRate(state, DummyMdot, this->ReheatControlNode, this->HWplantLoc, true);
5227 :
5228 : // call the reheat coil with the NO FLOW condition to make sure that the Node values
5229 : // are passed through to the coil outlet correctly
5230 964587 : SimulateWaterCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index);
5231 964587 : } break;
5232 0 : case HeatingCoilType::SteamAirHeating: { // COIL:STEAM:AIRHEATING
5233 : // Simulate reheat coil for the Const Volume system
5234 0 : SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, 0.0);
5235 0 : } break;
5236 20559 : case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
5237 : // Simulate reheat coil for the Const Volume system
5238 20559 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
5239 20559 : } break;
5240 207877 : case HeatingCoilType::Gas: { // COIL:GAS:HEATING
5241 : // Simulate reheat coil for the Const Volume system
5242 207877 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, 0.0, this->ReheatComp_Index);
5243 207877 : } break;
5244 0 : default: {
5245 0 : ShowFatalError(state, "Invalid Reheat Component=" + this->ReheatComp);
5246 0 : } break;
5247 : }
5248 : }
5249 1679042 : }
5250 :
5251 7471141 : void SingleDuctAirTerminal::SimConstVolNoReheat(EnergyPlusData &state)
5252 : {
5253 :
5254 : // PURPOSE OF THIS SUBROUTINE:
5255 : // Sets outlet flow rate and conditions for singleduct constantvolume with no reheat air terminal.
5256 :
5257 7471141 : this->sd_airterminalOutlet = this->sd_airterminalInlet;
5258 :
5259 : // update the air terminal outlet node data
5260 7471141 : this->UpdateSys(state);
5261 7471141 : }
5262 :
5263 360703 : void SingleDuctAirTerminal::CalcVAVVS(EnergyPlusData &state,
5264 : bool const FirstHVACIteration, // flag for 1st HVAV iteration in the time step
5265 : int const ZoneNode, // zone node number
5266 : Real64 const HWFlow, // hot water flow (kg/s)
5267 : Real64 const HCoilReq, // gas or elec coil demand requested
5268 : int const FanType, // type of fan
5269 : Real64 const AirFlow, // air flow rate (kg/s)
5270 : int const FanOn, // 1 means fan is on
5271 : Real64 &LoadMet // load met by unit (watts)
5272 : )
5273 : {
5274 :
5275 : // SUBROUTINE INFORMATION:
5276 : // AUTHOR Fred Buhl
5277 : // DATE WRITTEN July 2004
5278 : // MODIFIED na
5279 : // RE-ENGINEERED na
5280 :
5281 : // PURPOSE OF THIS SUBROUTINE:
5282 : // Simulate the components making up the VAV terminal unit with variable speed fan.
5283 :
5284 : // METHODOLOGY EMPLOYED:
5285 : // Simulates the unit components sequentially in the air flow direction.
5286 :
5287 : // REFERENCES:
5288 : // na
5289 :
5290 : // Using/Aliasing
5291 : using HeatingCoils::SimulateHeatingCoilComponents;
5292 : using PlantUtilities::SetComponentFlowRate;
5293 : using SteamCoils::SimulateSteamCoilComponents;
5294 : using WaterCoils::SimulateWaterCoilComponents;
5295 :
5296 : // Locals
5297 : // SUBROUTINE ARGUMENT DEFINITIONS:
5298 :
5299 : // SUBROUTINE PARAMETER DEFINITIONS:
5300 : // na
5301 :
5302 : // INTERFACE BLOCK SPECIFICATIONS
5303 : // na
5304 :
5305 : // DERIVED TYPE DEFINITIONS
5306 : // na
5307 :
5308 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5309 : int FanInNode; // unit air inlet node (fan inlet)
5310 : int FanOutNode; // fan outlet node (heating coil inlet node)
5311 : int HCOutNode; // unit air outlet node (heating coil air outlet node)
5312 : int HotControlNode; // the hot water inlet node
5313 : Real64 AirMassFlow; // total air mass flow rate [kg/s]
5314 : Real64 CpAirZn; // zone air specific heat [J/kg-C]
5315 : bool TurnFansOffSav; // save the fan off flag
5316 : Real64 mdot;
5317 :
5318 360703 : TurnFansOffSav = state.dataHVACGlobal->TurnFansOff;
5319 360703 : FanInNode = this->InletNodeNum;
5320 360703 : FanOutNode = this->OutletNodeNum;
5321 360703 : HCOutNode = this->ReheatAirOutletNode;
5322 360703 : HotControlNode = this->ReheatControlNode;
5323 360703 : AirMassFlow = AirFlow;
5324 360703 : state.dataLoopNodes->Node(FanInNode).MassFlowRate = AirMassFlow;
5325 360703 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(ZoneNode).HumRat);
5326 360703 : if (FanType == DataHVACGlobals::FanType_SimpleVAV && FanOn == 1) {
5327 99203 : Fans::SimulateFanComponents(state, this->FanName, FirstHVACIteration, this->Fan_Index);
5328 261500 : } else if (FanType == DataHVACGlobals::FanType_SystemModelObject && FanOn == 1) {
5329 86303 : state.dataHVACFan->fanObjs[this->Fan_Index]->simulate(state, _, _, _, _);
5330 :
5331 : } else { // pass through conditions
5332 175197 : state.dataHVACGlobal->TurnFansOff = true;
5333 175197 : if (FanType == DataHVACGlobals::FanType_SimpleVAV) {
5334 102954 : Fans::SimulateFanComponents(state, this->FanName, FirstHVACIteration, this->Fan_Index);
5335 72243 : } else if (FanType == DataHVACGlobals::FanType_SystemModelObject) {
5336 72243 : state.dataHVACFan->fanObjs[this->Fan_Index]->simulate(state, _, _, state.dataHVACGlobal->TurnFansOff, _);
5337 : }
5338 175197 : state.dataHVACGlobal->TurnFansOff = TurnFansOffSav;
5339 175197 : state.dataLoopNodes->Node(FanOutNode).MassFlowRate = state.dataLoopNodes->Node(FanInNode).MassFlowRate;
5340 175197 : state.dataLoopNodes->Node(FanOutNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(FanInNode).MassFlowRateMaxAvail;
5341 175197 : state.dataLoopNodes->Node(FanOutNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(FanInNode).MassFlowRateMinAvail;
5342 : }
5343 360703 : switch (this->ReheatComp_Num) {
5344 360703 : case HeatingCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
5345 360703 : mdot = HWFlow;
5346 360703 : if (this->HWplantLoc.loopNum > 0) {
5347 360703 : SetComponentFlowRate(state, mdot, this->ReheatControlNode, this->ReheatCoilOutletNode, this->HWplantLoc);
5348 : }
5349 :
5350 360703 : SimulateWaterCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index);
5351 360703 : } break;
5352 0 : case HeatingCoilType::SteamAirHeating: { // HW Flow is steam mass flow here
5353 0 : mdot = HWFlow;
5354 0 : if (this->HWplantLoc.loopNum > 0) {
5355 0 : SetComponentFlowRate(state, mdot, this->ReheatControlNode, this->ReheatCoilOutletNode, this->HWplantLoc);
5356 : }
5357 0 : SimulateSteamCoilComponents(state, this->ReheatName, FirstHVACIteration, this->ReheatComp_Index, HCoilReq);
5358 0 : } break;
5359 0 : case HeatingCoilType::Electric: { // COIL:ELECTRIC:HEATING
5360 0 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, HCoilReq, this->ReheatComp_Index);
5361 0 : } break;
5362 0 : case HeatingCoilType::Gas: { // COIL:GAS:HEATING
5363 0 : SimulateHeatingCoilComponents(state, this->ReheatName, FirstHVACIteration, HCoilReq, this->ReheatComp_Index);
5364 0 : } break;
5365 0 : default: {
5366 0 : ShowFatalError(state, "Invalid Reheat Component=" + this->ReheatComp);
5367 0 : } break;
5368 : }
5369 :
5370 360703 : LoadMet = AirMassFlow * CpAirZn * (state.dataLoopNodes->Node(HCOutNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp);
5371 360703 : }
5372 :
5373 : // End Algorithm Section of the Module
5374 : // *****************************************************************************
5375 :
5376 : // Beginning of Update subroutines for the Sys Module
5377 : // *****************************************************************************
5378 :
5379 44371923 : void SingleDuctAirTerminal::UpdateSys(EnergyPlusData &state) const
5380 : {
5381 :
5382 : // SUBROUTINE INFORMATION:
5383 : // AUTHOR Richard J. Liesen
5384 : // DATE WRITTEN january 2000
5385 : // MODIFIED na
5386 : // RE-ENGINEERED na
5387 :
5388 : // PURPOSE OF THIS SUBROUTINE:
5389 : // This subroutine updates the Syss.
5390 :
5391 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5392 : int OutletNode;
5393 : int InletNode;
5394 :
5395 44371923 : OutletNode = this->OutletNodeNum;
5396 44371923 : InletNode = this->InletNodeNum;
5397 :
5398 54007871 : if (this->SysType_Num == SysType::SingleDuctVAVReheat || this->SysType_Num == SysType::SingleDuctCBVAVReheat ||
5399 28416349 : this->SysType_Num == SysType::SingleDuctCBVAVNoReheat || this->SysType_Num == SysType::SingleDuctVAVNoReheat ||
5400 9173333 : this->SysType_Num == SysType::SingleDuctConstVolNoReheat) {
5401 : // Set the outlet air nodes of the Sys
5402 42669731 : state.dataLoopNodes->Node(OutletNode).MassFlowRate = this->sd_airterminalOutlet.AirMassFlowRate;
5403 42669731 : state.dataLoopNodes->Node(OutletNode).Temp = this->sd_airterminalOutlet.AirTemp;
5404 42669731 : state.dataLoopNodes->Node(OutletNode).HumRat = this->sd_airterminalOutlet.AirHumRat;
5405 42669731 : state.dataLoopNodes->Node(OutletNode).Enthalpy = this->sd_airterminalOutlet.AirEnthalpy;
5406 : // Set the outlet nodes for properties that just pass through & not used
5407 42669731 : state.dataLoopNodes->Node(OutletNode).Quality = state.dataLoopNodes->Node(InletNode).Quality;
5408 42669731 : state.dataLoopNodes->Node(OutletNode).Press = state.dataLoopNodes->Node(InletNode).Press;
5409 : }
5410 :
5411 : // After all of the Outlets are updated the mass flow information needs to be
5412 : // passed back to the system inlet.
5413 44371923 : state.dataLoopNodes->Node(InletNode).MassFlowRate = this->sd_airterminalOutlet.AirMassFlowRate;
5414 44371923 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMaxAvail =
5415 44371923 : min(this->sd_airterminalOutlet.AirMassFlowRateMaxAvail, state.dataLoopNodes->Node(OutletNode).MassFlowRateMax);
5416 44371923 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMinAvail = this->sd_airterminalOutlet.AirMassFlowRateMinAvail;
5417 :
5418 44371923 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
5419 84486 : state.dataLoopNodes->Node(OutletNode).CO2 = state.dataLoopNodes->Node(InletNode).CO2;
5420 : }
5421 :
5422 44371923 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
5423 34971 : state.dataLoopNodes->Node(OutletNode).GenContam = state.dataLoopNodes->Node(InletNode).GenContam;
5424 : }
5425 44371923 : }
5426 :
5427 : // End of Update subroutines for the Sys Module
5428 : // *****************************************************************************
5429 :
5430 : // Beginning of Reporting subroutines for the Sys Module
5431 : // *****************************************************************************
5432 :
5433 32682712 : void SingleDuctAirTerminal::ReportSys(EnergyPlusData &state) // unused1208
5434 : {
5435 :
5436 : // SUBROUTINE INFORMATION:
5437 : // AUTHOR Unknown
5438 : // DATE WRITTEN Unknown
5439 : // MODIFIED na
5440 : // RE-ENGINEERED na
5441 :
5442 : // PURPOSE OF THIS SUBROUTINE:
5443 : // This subroutine updates the Sys report variables.
5444 :
5445 : // METHODOLOGY EMPLOYED:
5446 : // There is method to this madness.
5447 :
5448 : // REFERENCES:
5449 : // na
5450 :
5451 : // USE STATEMENTS:
5452 : // na
5453 :
5454 : // Locals
5455 : // SUBROUTINE ARGUMENT DEFINITIONS:
5456 :
5457 : // SUBROUTINE PARAMETER DEFINITIONS:
5458 : // na
5459 :
5460 : // INTERFACE BLOCK SPECIFICATIONS
5461 : // na
5462 :
5463 : // DERIVED TYPE DEFINITIONS
5464 : // na
5465 :
5466 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5467 :
5468 : // Still needs to report the Sys power from this component
5469 :
5470 : // set zone OA volume flow rate
5471 32682712 : this->CalcOutdoorAirVolumeFlowRate(state);
5472 32682712 : }
5473 :
5474 111 : void GetHVACSingleDuctSysIndex(EnergyPlusData &state,
5475 : std::string const &SDSName,
5476 : int &SDSIndex,
5477 : bool &ErrorsFound,
5478 : std::string_view const ThisObjectType,
5479 : Optional_int DamperInletNode, // Damper inlet node number
5480 : Optional_int DamperOutletNode // Damper outlet node number
5481 : )
5482 : {
5483 :
5484 : // SUBROUTINE INFORMATION:
5485 : // AUTHOR Lixing Gu
5486 : // DATE WRITTEN February 2006
5487 : // MODIFIED na
5488 : // RE-ENGINEERED na
5489 :
5490 : // PURPOSE OF THIS SUBROUTINE:
5491 : // This subroutine sets an index for a given single duct system -- issues error message if that system
5492 : // is not a legal system.
5493 :
5494 111 : if (state.dataSingleDuct->GetInputFlag) { // First time subroutine has been entered
5495 0 : GetSysInput(state);
5496 0 : state.dataSingleDuct->GetInputFlag = false;
5497 : }
5498 :
5499 111 : SDSIndex = UtilityRoutines::FindItemInList(SDSName, state.dataSingleDuct->sd_airterminal, &SingleDuctAirTerminal::SysName);
5500 111 : if (SDSIndex == 0) {
5501 0 : if (!ThisObjectType.empty()) {
5502 0 : ShowSevereError(state, fmt::format("{}, GetHVACSingleDuctSysIndex: Single duct system not found={}", ThisObjectType, SDSName));
5503 : } else {
5504 0 : ShowSevereError(state, "GetHVACSingleDuctSysIndex: Single duct system not found=" + SDSName);
5505 : }
5506 0 : ErrorsFound = true;
5507 : } else {
5508 201 : if ((state.dataSingleDuct->sd_airterminal(SDSIndex).SysType_Num != SysType::SingleDuctConstVolReheat) &&
5509 90 : (state.dataSingleDuct->sd_airterminal(SDSIndex).SysType_Num != SysType::SingleDuctVAVReheat)) {
5510 0 : if (!ThisObjectType.empty()) {
5511 0 : ShowSevereError(state, fmt::format("{}, GetHVACSingleDuctSysIndex: Could not find allowed types={}", ThisObjectType, SDSName));
5512 : } else {
5513 0 : ShowSevereError(state, "GetHVACSingleDuctSysIndex: Could not find allowed types=" + SDSName);
5514 : }
5515 0 : ShowContinueError(state, "The allowed types are: AirTerminal:SingleDuct:ConstantVolume:Reheat and AirTerminal:SingleDuct:VAV:Reheat");
5516 0 : ErrorsFound = true;
5517 : }
5518 111 : if (state.dataSingleDuct->sd_airterminal(SDSIndex).SysType_Num == SysType::SingleDuctVAVReheat) {
5519 90 : if (present(DamperInletNode)) DamperInletNode = state.dataSingleDuct->sd_airterminal(SDSIndex).InletNodeNum;
5520 90 : if (present(DamperOutletNode)) DamperOutletNode = state.dataSingleDuct->sd_airterminal(SDSIndex).OutletNodeNum;
5521 : }
5522 : }
5523 111 : }
5524 :
5525 1478855 : void SimATMixer(EnergyPlusData &state, std::string const &SysName, bool const FirstHVACIteration, int &SysIndex)
5526 : {
5527 :
5528 : // SUBROUTINE INFORMATION:
5529 : // AUTHOR
5530 : // DATE WRITTEN March 2012
5531 : // MODIFIED na
5532 : // RE-ENGINEERED na
5533 :
5534 : // PURPOSE OF THIS SUBROUTINE
5535 : // Simulate an Air Terminal Mixer component
5536 :
5537 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5538 :
5539 1478855 : if (state.dataSingleDuct->GetATMixerFlag) {
5540 0 : state.dataSingleDuct->GetATMixerFlag = false;
5541 : }
5542 :
5543 1478855 : if (SysIndex == 0) {
5544 0 : state.dataSingleDuct->SysNumSATM = UtilityRoutines::FindItemInList(SysName, state.dataSingleDuct->SysATMixer);
5545 0 : SysIndex = state.dataSingleDuct->SysNumSATM;
5546 0 : if (state.dataSingleDuct->SysNumSATM == 0) {
5547 0 : ShowFatalError(state, "Object " + SysName + " not found");
5548 : }
5549 : } else {
5550 1478855 : state.dataSingleDuct->SysNumSATM = SysIndex;
5551 : }
5552 :
5553 1478855 : state.dataSingleDuct->SysATMixer(state.dataSingleDuct->SysNumSATM).InitATMixer(state, FirstHVACIteration);
5554 :
5555 1478855 : CalcATMixer(state, state.dataSingleDuct->SysNumSATM);
5556 :
5557 1478855 : UpdateATMixer(state, state.dataSingleDuct->SysNumSATM);
5558 1478855 : }
5559 :
5560 202454 : void GetATMixers(EnergyPlusData &state)
5561 : {
5562 :
5563 : // SUBROUTINE INFORMATION:
5564 : // AUTHOR
5565 : // DATE WRITTEN March 2012
5566 : // MODIFIED na
5567 : // RE-ENGINEERED na
5568 :
5569 : // PURPOSE OF THIS SUBROUTINE
5570 : // Get input for inlet side air terminal mixers and store it in the inlet side air terminal mixer array
5571 :
5572 : // METHODOLOGY EMPLOYED:
5573 : // Use the Get routines from the InputProcessor module.
5574 :
5575 : // Using/Aliasing
5576 : using DataZoneEquipment::EquipmentData;
5577 : using DataZoneEquipment::SubEquipmentData;
5578 : using NodeInputManager::GetOnlySingleNode;
5579 : using namespace DataLoopNode;
5580 : using BranchNodeConnections::TestCompSet;
5581 : using DataHVACGlobals::ATMixer_InletSide;
5582 : using DataHVACGlobals::ATMixer_SupplySide;
5583 :
5584 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
5585 : int NumNums; // Number of REAL(r64) numbers returned by GetObjectItem
5586 : int NumAlphas; // Number of alphanumerics returned by GetObjectItem
5587 : int ATMixerNum; // Index of inlet side mixer air terminal unit
5588 : int IOStat;
5589 : static constexpr std::string_view RoutineName("GetATMixers: "); // include trailing blank space
5590 202454 : bool ErrorsFound(false); // Error flag
5591 : int NodeNum; // Index to node number
5592 : int CtrlZone; // Index to control zone
5593 : bool ZoneNodeNotFound; // Flag for error checking
5594 : bool errFlag; // error flag from component validation
5595 :
5596 202454 : if (!state.dataSingleDuct->GetATMixerFlag) {
5597 202262 : return;
5598 : }
5599 192 : state.dataSingleDuct->GetATMixerFlag = false;
5600 192 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
5601 192 : cCurrentModuleObject = "AirTerminal:SingleDuct:Mixer";
5602 192 : state.dataSingleDuct->NumATMixers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
5603 192 : state.dataSingleDuct->SysATMixer.allocate(state.dataSingleDuct->NumATMixers);
5604 :
5605 : // make sure the input data is read in only once
5606 192 : if (state.dataZoneAirLoopEquipmentManager->GetAirDistUnitsFlag) {
5607 : // Need air distribution units first
5608 41 : ZoneAirLoopEquipmentManager::GetZoneAirLoopEquipment(state);
5609 41 : state.dataZoneAirLoopEquipmentManager->GetAirDistUnitsFlag = false;
5610 : }
5611 :
5612 241 : for (ATMixerNum = 1; ATMixerNum <= state.dataSingleDuct->NumATMixers; ++ATMixerNum) {
5613 343 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
5614 : cCurrentModuleObject,
5615 : ATMixerNum,
5616 49 : state.dataIPShortCut->cAlphaArgs,
5617 : NumAlphas,
5618 49 : state.dataIPShortCut->rNumericArgs,
5619 : NumNums,
5620 : IOStat,
5621 49 : state.dataIPShortCut->lNumericFieldBlanks,
5622 49 : state.dataIPShortCut->lAlphaFieldBlanks,
5623 49 : state.dataIPShortCut->cAlphaFieldNames,
5624 49 : state.dataIPShortCut->cNumericFieldNames);
5625 49 : UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
5626 49 : state.dataSingleDuct->SysATMixer(ATMixerNum).Name = state.dataIPShortCut->cAlphaArgs(1);
5627 49 : if (state.dataIPShortCut->cAlphaArgs(7) == "INLETSIDE") {
5628 27 : state.dataSingleDuct->SysATMixer(ATMixerNum).MixerType = ATMixer_InletSide; // inlet side mixer
5629 22 : } else if (state.dataIPShortCut->cAlphaArgs(7) == "SUPPLYSIDE") {
5630 22 : state.dataSingleDuct->SysATMixer(ATMixerNum).MixerType = ATMixer_SupplySide; // supply side mixer
5631 : }
5632 49 : if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:WATERTOAIRHEATPUMP") {
5633 10 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 1;
5634 39 : } else if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:FOURPIPEFANCOIL") {
5635 10 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 2;
5636 29 : } else if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:PACKAGEDTERMINALAIRCONDITIONER") {
5637 9 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 3;
5638 20 : } else if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:PACKAGEDTERMINALHEATPUMP") {
5639 5 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 4;
5640 15 : } else if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:VARIABLEREFRIGERANTFLOW") {
5641 0 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 5;
5642 15 : } else if (state.dataIPShortCut->cAlphaArgs(2) == "AIRLOOPHVAC:UNITARYSYSTEM") {
5643 5 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 6;
5644 10 : } else if (state.dataIPShortCut->cAlphaArgs(2) == "ZONEHVAC:UNITVENTILATOR") {
5645 5 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitType = 7;
5646 : }
5647 :
5648 49 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitName = state.dataIPShortCut->cAlphaArgs(3);
5649 :
5650 98 : ValidateComponent(
5651 98 : state, state.dataIPShortCut->cAlphaArgs(2), state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneHVACUnitName, errFlag, cCurrentModuleObject);
5652 :
5653 49 : state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode =
5654 98 : GetOnlySingleNode(state,
5655 49 : state.dataIPShortCut->cAlphaArgs(4),
5656 : ErrorsFound,
5657 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctMixer,
5658 49 : state.dataIPShortCut->cAlphaArgs(1),
5659 : DataLoopNode::NodeFluidType::Air,
5660 : DataLoopNode::ConnectionType::Outlet,
5661 : NodeInputManager::CompFluidStream::Primary,
5662 : ObjectIsNotParent,
5663 49 : state.dataIPShortCut->cAlphaFieldNames(4));
5664 :
5665 98 : state.dataSingleDuct->SysATMixer(ATMixerNum).PriInNode = GetOnlySingleNode(state,
5666 49 : state.dataIPShortCut->cAlphaArgs(5),
5667 : ErrorsFound,
5668 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctMixer,
5669 49 : state.dataIPShortCut->cAlphaArgs(1),
5670 : DataLoopNode::NodeFluidType::Air,
5671 : DataLoopNode::ConnectionType::Inlet,
5672 : NodeInputManager::CompFluidStream::Primary,
5673 : ObjectIsNotParent,
5674 49 : state.dataIPShortCut->cAlphaFieldNames(5));
5675 98 : state.dataSingleDuct->SysATMixer(ATMixerNum).SecInNode = GetOnlySingleNode(state,
5676 49 : state.dataIPShortCut->cAlphaArgs(6),
5677 : ErrorsFound,
5678 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctMixer,
5679 49 : state.dataIPShortCut->cAlphaArgs(1),
5680 : DataLoopNode::NodeFluidType::Air,
5681 : DataLoopNode::ConnectionType::Inlet,
5682 : NodeInputManager::CompFluidStream::Primary,
5683 : ObjectIsNotParent,
5684 49 : state.dataIPShortCut->cAlphaFieldNames(6));
5685 :
5686 49 : if (state.dataIPShortCut->lAlphaFieldBlanks(8)) {
5687 30 : state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser = true;
5688 : } else {
5689 19 : state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr =
5690 19 : UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(8), state.dataSize->OARequirements);
5691 19 : if (state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr == 0) {
5692 0 : ShowSevereError(state,
5693 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid data.");
5694 0 : ShowContinueError(state,
5695 0 : "..invalid " + state.dataIPShortCut->cAlphaFieldNames(8) + "=\"" + state.dataIPShortCut->cAlphaArgs(8) + "\".");
5696 0 : ErrorsFound = true;
5697 : } else {
5698 19 : state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser = false;
5699 : }
5700 : }
5701 :
5702 49 : if (state.dataIPShortCut->lAlphaFieldBlanks(9)) {
5703 40 : state.dataSingleDuct->SysATMixer(ATMixerNum).OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
5704 : } else {
5705 9 : if (state.dataIPShortCut->cAlphaArgs(9) == "CURRENTOCCUPANCY") {
5706 9 : state.dataSingleDuct->SysATMixer(ATMixerNum).OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
5707 0 : } else if (state.dataIPShortCut->cAlphaArgs(9) == "DESIGNOCCUPANCY") {
5708 0 : state.dataSingleDuct->SysATMixer(ATMixerNum).OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::ByDesignLevel;
5709 : } else {
5710 0 : state.dataSingleDuct->SysATMixer(ATMixerNum).OAPerPersonMode = DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel;
5711 0 : ShowWarningError(state,
5712 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", invalid data.");
5713 0 : ShowContinueError(state,
5714 0 : "..invalid " + state.dataIPShortCut->cAlphaFieldNames(9) + "=\"" + state.dataIPShortCut->cAlphaArgs(9) +
5715 : "\". The default input of CurrentOccupancy is assigned");
5716 : }
5717 : }
5718 :
5719 : // Check for dupes in the three nodes.
5720 49 : if (state.dataSingleDuct->SysATMixer(ATMixerNum).SecInNode == state.dataSingleDuct->SysATMixer(ATMixerNum).PriInNode) {
5721 0 : ShowSevereError(state,
5722 0 : cCurrentModuleObject + " = " + state.dataSingleDuct->SysATMixer(ATMixerNum).Name + ' ' +
5723 0 : state.dataIPShortCut->cAlphaArgs(5) + " = " +
5724 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).PriInNode) + " duplicates the " +
5725 0 : state.dataIPShortCut->cAlphaArgs(4) + '.');
5726 0 : ErrorsFound = true;
5727 49 : } else if (state.dataSingleDuct->SysATMixer(ATMixerNum).SecInNode == state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode) {
5728 0 : ShowSevereError(state,
5729 0 : cCurrentModuleObject + " = " + state.dataSingleDuct->SysATMixer(ATMixerNum).Name + ' ' +
5730 0 : state.dataIPShortCut->cAlphaArgs(6) + " = " +
5731 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode) + " duplicates the " +
5732 0 : state.dataIPShortCut->cAlphaArgs(4) + '.');
5733 0 : ErrorsFound = true;
5734 : }
5735 :
5736 49 : if (state.dataSingleDuct->SysATMixer(ATMixerNum).PriInNode == state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode) {
5737 0 : ShowSevereError(state,
5738 0 : cCurrentModuleObject + " = " + state.dataSingleDuct->SysATMixer(ATMixerNum).Name + ' ' +
5739 0 : state.dataIPShortCut->cAlphaArgs(6) + " = " +
5740 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode) + " duplicates the " +
5741 0 : state.dataIPShortCut->cAlphaArgs(5) + '.');
5742 0 : ErrorsFound = true;
5743 : }
5744 :
5745 148 : for (int ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
5746 148 : if (state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
5747 49 : state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum = state.dataSingleDuct->SysATMixer(ATMixerNum).PriInNode;
5748 49 : state.dataSingleDuct->SysATMixer(ATMixerNum).ADUNum = ADUNum;
5749 49 : break;
5750 : }
5751 : }
5752 : // one assumes if there isn't one assigned, it's an error?
5753 49 : if (state.dataSingleDuct->SysATMixer(ATMixerNum).ADUNum == 0) {
5754 0 : ShowSevereError(state,
5755 0 : std::string{RoutineName} + "No matching Air Distribution Unit, for System = [" + cCurrentModuleObject + ',' +
5756 0 : state.dataSingleDuct->SysATMixer(ATMixerNum).Name + "].");
5757 0 : ShowContinueError(
5758 0 : state, "...should have outlet node = " + state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode));
5759 0 : ErrorsFound = true;
5760 : } else {
5761 :
5762 49 : if (state.dataSingleDuct->SysATMixer(ATMixerNum).MixerType == ATMixer_InletSide) {
5763 : // Air Terminal inlet node must be the same as a zone exhaust node
5764 27 : ZoneNodeNotFound = true;
5765 94 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
5766 93 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
5767 103 : for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumExhaustNodes; ++NodeNum) {
5768 126 : if (state.dataSingleDuct->SysATMixer(ATMixerNum).SecInNode ==
5769 63 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).ExhaustNode(NodeNum)) {
5770 26 : ZoneNodeNotFound = false;
5771 26 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->SysATMixer(ATMixerNum).ADUNum).ZoneEqNum = CtrlZone;
5772 26 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum = CtrlZone;
5773 : // Must wait until InitATMixer to fill other zone equip config data because ultimate zone inlet node is not known yet
5774 : // for inlet side mixers
5775 26 : if (!state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser) {
5776 10 : bool UseOccSchFlag = false;
5777 10 : bool UseMinOASchFlag = false;
5778 10 : state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate =
5779 30 : DataSizing::calcDesignSpecificationOutdoorAir(state,
5780 10 : state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr,
5781 10 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum,
5782 : UseOccSchFlag,
5783 : UseMinOASchFlag);
5784 : }
5785 26 : goto ControlledZoneLoop_exit;
5786 : }
5787 : }
5788 : }
5789 1 : ControlledZoneLoop_exit:;
5790 27 : if (ZoneNodeNotFound) {
5791 1 : bool ZoneNodeFoundAgain = false;
5792 4 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
5793 9 : for (int Num = 1; Num <= state.dataZoneEquip->ZoneEquipList(CtrlZone).NumOfEquipTypes; ++Num) {
5794 12 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3),
5795 13 : state.dataZoneEquip->ZoneEquipList(CtrlZone).EquipName(Num)) &&
5796 1 : UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(2),
5797 1 : state.dataZoneEquip->ZoneEquipList(CtrlZone).EquipType(Num))) {
5798 1 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->SysATMixer(ATMixerNum).ADUNum).ZoneEqNum = CtrlZone;
5799 1 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum = CtrlZone;
5800 : // Must wait until InitATMixer to fill other zone equip config data because ultimate zone inlet node is not known yet
5801 : // for inlet side mixers
5802 1 : if (!state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser) {
5803 1 : bool UseOccSchFlag = false;
5804 1 : bool UseMinOASchFlag = false;
5805 1 : state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate =
5806 3 : DataSizing::calcDesignSpecificationOutdoorAir(state,
5807 1 : state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr,
5808 1 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum,
5809 : UseOccSchFlag,
5810 : UseMinOASchFlag);
5811 : }
5812 1 : ZoneNodeFoundAgain = true;
5813 1 : break;
5814 : }
5815 : }
5816 4 : if (ZoneNodeFoundAgain) break;
5817 : }
5818 1 : if (!ZoneNodeFoundAgain) {
5819 0 : ShowSevereError(state,
5820 0 : cCurrentModuleObject + " = \"" + state.dataSingleDuct->SysATMixer(ATMixerNum).Name +
5821 : "\". Inlet Side Air Terminal Mixer air inlet node name must be the same as either a zone exhaust node "
5822 : "name or an induced "
5823 : "air node in ZonePlenum.");
5824 0 : ShowContinueError(state, "..Zone exhaust node name is specified in ZoneHVAC:EquipmentConnections object.");
5825 0 : ShowContinueError(state, "..Induced Air Outlet Node name is specified in AirLoopHVAC:ReturnPlenum object.");
5826 0 : ShowContinueError(state,
5827 0 : "..Inlet Side CONNECTED Air Terminal Mixer inlet node name = " +
5828 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).SecInNode));
5829 0 : ErrorsFound = true;
5830 : }
5831 : }
5832 : }
5833 :
5834 49 : if (state.dataSingleDuct->SysATMixer(ATMixerNum).MixerType == ATMixer_SupplySide) {
5835 22 : ZoneNodeNotFound = true;
5836 106 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
5837 106 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
5838 148 : for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++NodeNum) {
5839 172 : if (state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode ==
5840 86 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(NodeNum)) {
5841 22 : ZoneNodeNotFound = false;
5842 22 : state.dataDefineEquipment->AirDistUnit(state.dataSingleDuct->SysATMixer(ATMixerNum).ADUNum).ZoneEqNum = CtrlZone;
5843 22 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum = CtrlZone;
5844 : // Wait until InitATMixer to fill other zone equip config data
5845 :
5846 22 : if (!state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser) {
5847 8 : bool UseOccSchFlag = false;
5848 8 : bool UseMinOASchFlag = false;
5849 8 : state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate =
5850 24 : DataSizing::calcDesignSpecificationOutdoorAir(state,
5851 8 : state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr,
5852 8 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum,
5853 : UseOccSchFlag,
5854 : UseMinOASchFlag);
5855 : }
5856 22 : goto ControlZoneLoop_exit;
5857 : }
5858 : }
5859 : }
5860 0 : ControlZoneLoop_exit:;
5861 22 : if (ZoneNodeNotFound) {
5862 0 : ShowSevereError(state,
5863 0 : cCurrentModuleObject + " = \"" + state.dataSingleDuct->SysATMixer(ATMixerNum).Name +
5864 : "\". Supply Side Air Terminal Mixer air outlet node name must be the same as a zone inlet node name.");
5865 0 : ShowContinueError(state, "..Zone inlet node name is specified in ZoneHVAC:EquipmentConnections object.");
5866 0 : ShowContinueError(state,
5867 0 : "..Supply Side connected Air Terminal Mixer outlet node name = " +
5868 0 : state.dataLoopNodes->NodeID(state.dataSingleDuct->SysATMixer(ATMixerNum).MixedAirOutNode));
5869 0 : ErrorsFound = true;
5870 : }
5871 : }
5872 : }
5873 98 : TestCompSet(state,
5874 : cCurrentModuleObject,
5875 49 : state.dataSingleDuct->SysATMixer(ATMixerNum).Name,
5876 49 : state.dataIPShortCut->cAlphaArgs(5),
5877 49 : state.dataIPShortCut->cAlphaArgs(4),
5878 : "Air Nodes");
5879 :
5880 49 : if (state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr == 0) {
5881 30 : if (state.dataSize->ZoneSizingInput.allocated()) {
5882 180 : for (int SizingInputNum = 1; SizingInputNum <= state.dataSize->NumZoneSizingInput; ++SizingInputNum) {
5883 150 : if (state.dataSize->ZoneSizingInput(SizingInputNum).ZoneNum == state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum) {
5884 30 : if (state.dataSize->ZoneSizingInput(SizingInputNum).ZoneDesignSpecOAIndex == 0) {
5885 0 : ShowWarningError(state,
5886 0 : std::string{RoutineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
5887 : "\", invalid data.");
5888 0 : ShowContinueError(state,
5889 0 : state.dataIPShortCut->cAlphaFieldNames(8) +
5890 : " is blank in both the mixer and the Sizing:Zone object for the same zone.");
5891 0 : ShowContinueError(state, "The mixer outdoor airflow rate is set to zero.");
5892 0 : state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate = 0.0;
5893 : } else {
5894 30 : state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr =
5895 30 : state.dataSize->ZoneSizingInput(SizingInputNum).ZoneDesignSpecOAIndex;
5896 30 : state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate =
5897 60 : DataSizing::calcDesignSpecificationOutdoorAir(state,
5898 30 : state.dataSingleDuct->SysATMixer(ATMixerNum).OARequirementsPtr,
5899 30 : state.dataSingleDuct->SysATMixer(ATMixerNum).ZoneNum,
5900 : false,
5901 : false);
5902 30 : state.dataSingleDuct->SysATMixer(ATMixerNum).NoOAFlowInputFromUser = false;
5903 : }
5904 : }
5905 : }
5906 : } else {
5907 0 : ShowWarningError(state,
5908 0 : state.dataIPShortCut->cAlphaFieldNames(8) +
5909 : "is blank and there is no Sizing:Zone for the same zone. The mixer outdoor airflow rate is set to zero.");
5910 0 : state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate = 0.0;
5911 : }
5912 : }
5913 49 : state.dataSingleDuct->SysATMixer(ATMixerNum).MassFlowRateMaxAvail =
5914 49 : state.dataSingleDuct->SysATMixer(ATMixerNum).DesignPrimaryAirVolRate * state.dataEnvrn->StdRhoAir;
5915 : }
5916 :
5917 192 : if (ErrorsFound) {
5918 0 : ShowFatalError(state, std::string{RoutineName} + "Errors found in input. Program terminates.");
5919 : }
5920 : }
5921 :
5922 1478904 : void AirTerminalMixerData::InitATMixer(EnergyPlusData &state, bool const FirstHVACIteration)
5923 : {
5924 : // Purpose: Initialize the AirTerminalMixers data structure with node data
5925 1478904 : if (this->OneTimeInitFlag) {
5926 : {
5927 49 : auto &thisADU(state.dataDefineEquipment->AirDistUnit(this->ADUNum));
5928 : {
5929 49 : auto &thisZoneEqConfig(state.dataZoneEquip->ZoneEquipConfig(thisADU.ZoneEqNum));
5930 98 : for (int SupAirIn = 1; SupAirIn <= thisZoneEqConfig.NumInletNodes; ++SupAirIn) {
5931 49 : if (this->ZoneInletNode == thisZoneEqConfig.InletNode(SupAirIn)) {
5932 49 : thisZoneEqConfig.AirDistUnitCool(SupAirIn).InNode = this->PriInNode;
5933 49 : thisZoneEqConfig.AirDistUnitCool(SupAirIn).OutNode = this->MixedAirOutNode;
5934 49 : thisZoneEqConfig.AirDistUnitHeat(SupAirIn).InNode = this->PriInNode;
5935 49 : thisZoneEqConfig.AirDistUnitHeat(SupAirIn).OutNode = this->MixedAirOutNode;
5936 49 : thisADU.TermUnitSizingNum = thisZoneEqConfig.AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
5937 49 : this->CtrlZoneInNodeIndex = SupAirIn;
5938 : {
5939 49 : auto &thisTermUnitSizingData(state.dataSize->TermUnitSizing(thisADU.TermUnitSizingNum));
5940 49 : thisTermUnitSizingData.ADUName = thisADU.Name;
5941 : // Fill TermUnitSizing with specs from DesignSpecification:AirTerminal:Sizing if there is one attached to this
5942 : // terminal unit
5943 49 : if (thisADU.AirTerminalSizingSpecIndex > 0) {
5944 : {
5945 0 : auto const &thisAirTermSizingSpec(state.dataSize->AirTerminalSizingSpec(thisADU.AirTerminalSizingSpecIndex));
5946 0 : thisTermUnitSizingData.SpecDesCoolSATRatio = thisAirTermSizingSpec.DesCoolSATRatio;
5947 0 : thisTermUnitSizingData.SpecDesHeatSATRatio = thisAirTermSizingSpec.DesHeatSATRatio;
5948 0 : thisTermUnitSizingData.SpecDesSensCoolingFrac = thisAirTermSizingSpec.DesSensCoolingFrac;
5949 0 : thisTermUnitSizingData.SpecDesSensHeatingFrac = thisAirTermSizingSpec.DesSensHeatingFrac;
5950 0 : thisTermUnitSizingData.SpecMinOAFrac = thisAirTermSizingSpec.MinOAFrac;
5951 : }
5952 : }
5953 : }
5954 : }
5955 : }
5956 : }
5957 : }
5958 49 : this->OneTimeInitFlag = false;
5959 : }
5960 :
5961 : // Keep trying until we find it, the airloopnum, that is
5962 1478904 : if (this->OneTimeInitFlag2) {
5963 448 : this->AirLoopNum = state.dataZoneEquip->ZoneEquipConfig(state.dataDefineEquipment->AirDistUnit(this->ADUNum).ZoneEqNum)
5964 224 : .InletNodeAirLoopNum(this->CtrlZoneInNodeIndex);
5965 224 : state.dataDefineEquipment->AirDistUnit(this->ADUNum).AirLoopNum = this->AirLoopNum;
5966 224 : if (this->AirLoopNum > 0) {
5967 49 : this->OneTimeInitFlag2 = false;
5968 : }
5969 : }
5970 :
5971 : // Every iteration
5972 1478904 : Real64 mDotFromOARequirement(0.0);
5973 1478904 : Real64 vDotOAReq(0.0);
5974 1478904 : if (!this->NoOAFlowInputFromUser) {
5975 1478904 : Real64 airLoopOAFrac(0.0);
5976 1478904 : bool UseOccSchFlag = false;
5977 1478904 : if (this->OAPerPersonMode == DataZoneEquipment::PerPersonVentRateMode::DCVByCurrentLevel) UseOccSchFlag = true;
5978 1478904 : if (this->AirLoopNum > 0) {
5979 1478729 : airLoopOAFrac = state.dataAirLoop->AirLoopFlow(this->AirLoopNum).OAFrac;
5980 1478729 : if (airLoopOAFrac > 0.0) {
5981 1265223 : vDotOAReq = DataSizing::calcDesignSpecificationOutdoorAir(state, this->OARequirementsPtr, this->ZoneNum, UseOccSchFlag, true);
5982 1265223 : mDotFromOARequirement = vDotOAReq * state.dataEnvrn->StdRhoAir / airLoopOAFrac;
5983 : } else {
5984 213506 : mDotFromOARequirement = state.dataLoopNodes->Node(this->PriInNode).MassFlowRate;
5985 : }
5986 : }
5987 1478904 : if (FirstHVACIteration) {
5988 713955 : state.dataLoopNodes->Node(this->PriInNode).MassFlowRate = mDotFromOARequirement;
5989 713955 : state.dataLoopNodes->Node(this->PriInNode).MassFlowRateMaxAvail = this->MassFlowRateMaxAvail;
5990 713955 : state.dataLoopNodes->Node(this->PriInNode).MassFlowRateMinAvail = 0.0;
5991 : } else {
5992 764949 : state.dataLoopNodes->Node(this->PriInNode).MassFlowRate = mDotFromOARequirement;
5993 :
5994 764949 : state.dataLoopNodes->Node(this->PriInNode).MassFlowRate =
5995 764949 : min(state.dataLoopNodes->Node(this->PriInNode).MassFlowRate, state.dataLoopNodes->Node(this->PriInNode).MassFlowRateMaxAvail);
5996 764949 : state.dataLoopNodes->Node(this->PriInNode).MassFlowRate =
5997 764949 : max(state.dataLoopNodes->Node(this->PriInNode).MassFlowRate, state.dataLoopNodes->Node(this->PriInNode).MassFlowRateMinAvail);
5998 764949 : state.dataLoopNodes->Node(this->PriInNode).MassFlowRate =
5999 764949 : max(state.dataLoopNodes->Node(this->PriInNode).MassFlowRate, state.dataLoopNodes->Node(this->PriInNode).MassFlowRateMin);
6000 : }
6001 : }
6002 1478904 : if (this->MixerType == ATMixer_InletSide) {
6003 877173 : state.dataLoopNodes->Node(this->PriInNode).MassFlowRate =
6004 877173 : min(state.dataLoopNodes->Node(this->PriInNode).MassFlowRate, state.dataLoopNodes->Node(this->MixedAirOutNode).MassFlowRate);
6005 : }
6006 1478904 : }
6007 :
6008 1478855 : void CalcATMixer(EnergyPlusData &state, int const SysNum)
6009 : {
6010 :
6011 : // SUBROUTINE INFORMATION:
6012 : // AUTHOR
6013 : // DATE WRITTEN March 2012
6014 : // MODIFIED na
6015 : // RE-ENGINEERED na
6016 :
6017 : // PURPOSE OF THIS SUBROUTINE
6018 : // Calculate the mixed air flow and conditions in the air terminal mixer
6019 :
6020 : // METHODOLOGY EMPLOYED:
6021 :
6022 : // REFERENCES:
6023 :
6024 : // Using/Aliasing
6025 : using Psychrometrics::PsyTdbFnHW;
6026 :
6027 : // Locals
6028 : // SUBROUTINE ARGUMENT DEFINITIONS
6029 :
6030 : // SUBROUTINE PARAMETER DEFINITIONS:
6031 :
6032 : // INTERFACE BLOCK SPECIFICATIONS
6033 : // na
6034 :
6035 : // DERIVED TYPE DEFINITIONS
6036 : // na
6037 :
6038 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6039 :
6040 1478855 : state.dataSingleDuct->PriEnthalpyCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).PriInNode).Enthalpy;
6041 1478855 : state.dataSingleDuct->PriHumRatCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).PriInNode).HumRat;
6042 1478855 : state.dataSingleDuct->PriTempCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).PriInNode).Temp;
6043 1478855 : state.dataSingleDuct->PriMassFlowRateCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).PriInNode).MassFlowRate;
6044 :
6045 1478855 : state.dataSingleDuct->SecAirMassFlowRateCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).SecInNode).MassFlowRate;
6046 1478855 : state.dataSingleDuct->SecAirEnthalpyCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).SecInNode).Enthalpy;
6047 1478855 : state.dataSingleDuct->SecAirHumRatCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).SecInNode).HumRat;
6048 1478855 : state.dataSingleDuct->SecAirTempCATM = state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).SecInNode).Temp;
6049 :
6050 1478855 : if (state.dataSingleDuct->SysATMixer(SysNum).MixerType == ATMixer_SupplySide) {
6051 601709 : state.dataSingleDuct->MixedAirMassFlowRateCATM = state.dataSingleDuct->SecAirMassFlowRateCATM + state.dataSingleDuct->PriMassFlowRateCATM;
6052 : } else {
6053 : // for inlet side mixer, the mixed air flow has been set, but we don't know the secondary flow
6054 877146 : state.dataSingleDuct->MixedAirMassFlowRateCATM =
6055 877146 : state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).MixedAirOutNode).MassFlowRate;
6056 877146 : state.dataSingleDuct->SecAirMassFlowRateCATM =
6057 877146 : max(state.dataSingleDuct->MixedAirMassFlowRateCATM - state.dataSingleDuct->PriMassFlowRateCATM, 0.0);
6058 877146 : state.dataLoopNodes->Node(state.dataSingleDuct->SysATMixer(SysNum).SecInNode).MassFlowRate = state.dataSingleDuct->SecAirMassFlowRateCATM;
6059 2631438 : if (std::abs(state.dataSingleDuct->PriMassFlowRateCATM + state.dataSingleDuct->SecAirMassFlowRateCATM -
6060 1754292 : state.dataSingleDuct->MixedAirMassFlowRateCATM) > SmallMassFlow) {
6061 0 : ShowSevereError(state,
6062 0 : "CalcATMixer: Invalid mass flow rates in AirTerminal:SingleDuct:Mixer=" + state.dataSingleDuct->SysATMixer(SysNum).Name);
6063 0 : ShowContinueErrorTimeStamp(state,
6064 0 : format("Primary mass flow rate={:.6R}Secondary mass flow rate={:.6R}Mixed mass flow rate={:.6R}",
6065 0 : state.dataSingleDuct->PriMassFlowRateCATM,
6066 0 : state.dataSingleDuct->SecAirMassFlowRateCATM,
6067 0 : state.dataSingleDuct->MixedAirMassFlowRateCATM));
6068 0 : ShowFatalError(state, "Simulation terminates.");
6069 : }
6070 : }
6071 : // now calculate the mixed (outlet) conditions
6072 1478855 : if (state.dataSingleDuct->MixedAirMassFlowRateCATM > 0.0) {
6073 4173669 : state.dataSingleDuct->MixedAirEnthalpyCATM = (state.dataSingleDuct->SecAirMassFlowRateCATM * state.dataSingleDuct->SecAirEnthalpyCATM +
6074 2782446 : state.dataSingleDuct->PriMassFlowRateCATM * state.dataSingleDuct->PriEnthalpyCATM) /
6075 1391223 : state.dataSingleDuct->MixedAirMassFlowRateCATM;
6076 4173669 : state.dataSingleDuct->MixedAirHumRatCATM = (state.dataSingleDuct->SecAirMassFlowRateCATM * state.dataSingleDuct->SecAirHumRatCATM +
6077 2782446 : state.dataSingleDuct->PriMassFlowRateCATM * state.dataSingleDuct->PriHumRatCATM) /
6078 1391223 : state.dataSingleDuct->MixedAirMassFlowRateCATM;
6079 : // Mixed air temperature is calculated from the mixed air enthalpy and humidity ratio.
6080 1391223 : state.dataSingleDuct->MixedAirTempCATM = PsyTdbFnHW(state.dataSingleDuct->MixedAirEnthalpyCATM, state.dataSingleDuct->MixedAirHumRatCATM);
6081 : }
6082 :
6083 1478855 : state.dataSingleDuct->SysATMixer(SysNum).MixedAirMassFlowRate = state.dataSingleDuct->MixedAirMassFlowRateCATM;
6084 1478855 : state.dataSingleDuct->SysATMixer(SysNum).MixedAirEnthalpy = state.dataSingleDuct->MixedAirEnthalpyCATM;
6085 1478855 : state.dataSingleDuct->SysATMixer(SysNum).MixedAirHumRat = state.dataSingleDuct->MixedAirHumRatCATM;
6086 1478855 : state.dataSingleDuct->SysATMixer(SysNum).MixedAirTemp = state.dataSingleDuct->MixedAirTempCATM;
6087 1478855 : }
6088 :
6089 1478855 : void UpdateATMixer(EnergyPlusData &state, int const SysNum)
6090 : {
6091 :
6092 : // SUBROUTINE INFORMATION:
6093 : // AUTHOR
6094 : // DATE WRITTEN March 2012
6095 : // MODIFIED na
6096 : // RE-ENGINEERED na
6097 :
6098 : // PURPOSE OF THIS SUBROUTINE
6099 : // Move the results of CalcATMixer to the affected nodes
6100 :
6101 : // METHODOLOGY EMPLOYED:
6102 :
6103 : // REFERENCES:
6104 :
6105 : // Using/Aliasing
6106 : using namespace DataLoopNode;
6107 :
6108 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6109 1478855 : int PriInNode = state.dataSingleDuct->SysATMixer(SysNum).PriInNode;
6110 1478855 : int SecInNode = state.dataSingleDuct->SysATMixer(SysNum).SecInNode;
6111 1478855 : int MixedAirOutNode = state.dataSingleDuct->SysATMixer(SysNum).MixedAirOutNode;
6112 :
6113 : // mixed air data
6114 1478855 : state.dataLoopNodes->Node(MixedAirOutNode).Temp = state.dataSingleDuct->SysATMixer(SysNum).MixedAirTemp;
6115 1478855 : state.dataLoopNodes->Node(MixedAirOutNode).HumRat = state.dataSingleDuct->SysATMixer(SysNum).MixedAirHumRat;
6116 1478855 : state.dataLoopNodes->Node(MixedAirOutNode).Enthalpy = state.dataSingleDuct->SysATMixer(SysNum).MixedAirEnthalpy;
6117 1478855 : state.dataLoopNodes->Node(MixedAirOutNode).Press = state.dataSingleDuct->SysATMixer(SysNum).MixedAirPressure;
6118 1478855 : state.dataLoopNodes->Node(MixedAirOutNode).MassFlowRate = state.dataSingleDuct->SysATMixer(SysNum).MixedAirMassFlowRate;
6119 :
6120 1478855 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
6121 320474 : if (state.dataSingleDuct->SysATMixer(SysNum).MixedAirMassFlowRate <= DataHVACGlobals::VerySmallMassFlow) {
6122 9292 : state.dataLoopNodes->Node(MixedAirOutNode).CO2 = state.dataLoopNodes->Node(PriInNode).CO2;
6123 : } else {
6124 311182 : state.dataLoopNodes->Node(MixedAirOutNode).CO2 =
6125 622364 : (state.dataLoopNodes->Node(SecInNode).MassFlowRate * state.dataLoopNodes->Node(SecInNode).CO2 +
6126 622364 : state.dataLoopNodes->Node(PriInNode).MassFlowRate * state.dataLoopNodes->Node(PriInNode).CO2) /
6127 311182 : state.dataLoopNodes->Node(MixedAirOutNode).MassFlowRate;
6128 : }
6129 : }
6130 :
6131 1478855 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
6132 0 : if (state.dataSingleDuct->SysATMixer(SysNum).MixedAirMassFlowRate <= DataHVACGlobals::VerySmallMassFlow) {
6133 0 : state.dataLoopNodes->Node(MixedAirOutNode).GenContam = state.dataLoopNodes->Node(PriInNode).GenContam;
6134 : } else {
6135 0 : state.dataLoopNodes->Node(MixedAirOutNode).GenContam =
6136 0 : (state.dataLoopNodes->Node(SecInNode).MassFlowRate * state.dataLoopNodes->Node(SecInNode).GenContam +
6137 0 : state.dataLoopNodes->Node(PriInNode).MassFlowRate * state.dataLoopNodes->Node(PriInNode).GenContam) /
6138 0 : state.dataLoopNodes->Node(MixedAirOutNode).MassFlowRate;
6139 : }
6140 : }
6141 :
6142 : // update ADU flow data - because SimATMixer is called from the various zone equipment so the updates in SimZoneAirLoopEquipment won't work
6143 1478855 : int aduNum = state.dataSingleDuct->SysATMixer(SysNum).ADUNum;
6144 1478855 : state.dataDefineEquipment->AirDistUnit(aduNum).MassFlowRateTU = state.dataLoopNodes->Node(PriInNode).MassFlowRate;
6145 1478855 : state.dataDefineEquipment->AirDistUnit(aduNum).MassFlowRateZSup = state.dataLoopNodes->Node(PriInNode).MassFlowRate;
6146 1478855 : state.dataDefineEquipment->AirDistUnit(aduNum).MassFlowRateSup = state.dataLoopNodes->Node(PriInNode).MassFlowRate;
6147 1478855 : }
6148 :
6149 754 : void GetATMixer(EnergyPlusData &state,
6150 : std::string const &ZoneEquipName, // zone unit name name
6151 : std::string &ATMixerName, // air terminal mixer name
6152 : int &ATMixerNum, // air terminal mixer index
6153 : int &ATMixerType, // air teminal mixer type
6154 : int &ATMixerPriNode, // air terminal mixer primary air node number
6155 : int &ATMixerSecNode, // air terminal mixer secondary air node number
6156 : int &ATMixerOutNode, // air terminal mixer outlet air node number
6157 : int const ZoneEquipOutletNode // zone equipment outlet node (used with inlet side mixers)
6158 : )
6159 : {
6160 :
6161 : // SUBROUTINE INFORMATION:
6162 : // AUTHOR Fred Buhl
6163 : // DATE WRITTEN April 2012
6164 : // MODIFIED na
6165 : // RE-ENGINEERED na
6166 :
6167 : // PURPOSE OF THIS SUBROUTINE:
6168 : // This subroutine gets: 1) the index of the named AT Mixer in the SysATMixer data array
6169 : // 2) the node number of the primary air inlet node of the AT Mixer
6170 : // 3) set the AT Mixer ultimate zone inlet node
6171 :
6172 : int ATMixerIndex; // local air terminal mixer index
6173 :
6174 754 : if (state.dataSingleDuct->GetATMixerFlag) {
6175 184 : GetATMixers(state);
6176 184 : state.dataSingleDuct->GetATMixerFlag = false;
6177 : }
6178 :
6179 754 : if (state.dataSingleDuct->NumATMixers <= 0) {
6180 704 : ATMixerNum = 0;
6181 704 : ATMixerName = "";
6182 704 : ATMixerPriNode = 0;
6183 704 : ATMixerSecNode = 0;
6184 704 : ATMixerOutNode = 0;
6185 704 : ATMixerType = 0;
6186 704 : return;
6187 : }
6188 :
6189 50 : ATMixerIndex = UtilityRoutines::FindItemInList(ZoneEquipName, state.dataSingleDuct->SysATMixer, &AirTerminalMixerData::ZoneHVACUnitName);
6190 50 : if (ATMixerIndex > 0) {
6191 49 : ATMixerNum = ATMixerIndex;
6192 49 : ATMixerName = state.dataSingleDuct->SysATMixer(ATMixerIndex).Name;
6193 49 : ATMixerPriNode = state.dataSingleDuct->SysATMixer(ATMixerIndex).PriInNode;
6194 49 : ATMixerSecNode = state.dataSingleDuct->SysATMixer(ATMixerIndex).SecInNode;
6195 49 : ATMixerOutNode = state.dataSingleDuct->SysATMixer(ATMixerIndex).MixedAirOutNode;
6196 49 : ATMixerType = state.dataSingleDuct->SysATMixer(ATMixerIndex).MixerType;
6197 49 : if (ATMixerType == ATMixer_InletSide) {
6198 27 : state.dataSingleDuct->SysATMixer(ATMixerIndex).ZoneInletNode = ZoneEquipOutletNode;
6199 : } else {
6200 22 : state.dataSingleDuct->SysATMixer(ATMixerIndex).ZoneInletNode = ATMixerOutNode;
6201 : }
6202 49 : state.dataSingleDuct->SysATMixer(ATMixerNum).InitATMixer(state, false);
6203 : } else {
6204 1 : ATMixerNum = 0;
6205 1 : ATMixerName = "";
6206 1 : ATMixerPriNode = 0;
6207 1 : ATMixerSecNode = 0;
6208 1 : ATMixerOutNode = 0;
6209 1 : ATMixerType = 0;
6210 : }
6211 : }
6212 :
6213 0 : void SetATMixerPriFlow(EnergyPlusData &state,
6214 : int const ATMixerNum, // Air terminal mixer index
6215 : Optional<Real64 const> PriAirMassFlowRate // Air terminal mixer primary air mass flow rate [kg/s]
6216 : )
6217 : {
6218 :
6219 : // SUBROUTINE INFORMATION:
6220 : // AUTHOR Fred Buhl
6221 : // DATE WRITTEN April 2012
6222 : // MODIFIED na
6223 : // RE-ENGINEERED na
6224 :
6225 : // PURPOSE OF THIS SUBROUTINE:
6226 : // This Subroutine sets the primary air mass flow rate on the primary air inlet
6227 : // node of a terminal unit mixer component.
6228 :
6229 : // METHODOLOGY EMPLOYED:
6230 : // The flow is set to either the input PriAirMassFlowRate if this optional input
6231 : // parameter is present, or to the maximum available mass flow rate of the primary
6232 : // air inlet node.
6233 :
6234 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
6235 : int PriAirNode; // air terminal mixer primary air inlet node number
6236 :
6237 0 : if (ATMixerNum <= 0) return;
6238 0 : PriAirNode = state.dataSingleDuct->SysATMixer(ATMixerNum).PriInNode;
6239 0 : if (present(PriAirMassFlowRate)) {
6240 0 : state.dataLoopNodes->Node(PriAirNode).MassFlowRate = PriAirMassFlowRate;
6241 : } else {
6242 0 : state.dataLoopNodes->Node(PriAirNode).MassFlowRate = state.dataLoopNodes->Node(PriAirNode).MassFlowRateMaxAvail;
6243 : }
6244 : }
6245 :
6246 78 : void setATMixerSizingProperties(EnergyPlusData &state,
6247 : int const inletATMixerIndex, // index to ATMixer at inlet of zone equipment
6248 : int const controlledZoneNum, // controlled zone number
6249 : int const curZoneEqNum // current zone equipment being simulated
6250 : )
6251 : {
6252 78 : auto &ZoneEqSizing(state.dataSize->ZoneEqSizing);
6253 78 : auto &FinalSysSizing(state.dataSize->FinalSysSizing);
6254 78 : auto &FinalZoneSizing(state.dataSize->FinalZoneSizing);
6255 :
6256 113 : if (inletATMixerIndex == 0) return; // protect this function from bad inputs
6257 78 : if (controlledZoneNum == 0) return;
6258 78 : if (curZoneEqNum == 0) return;
6259 78 : if (state.dataSingleDuct->SysATMixer(inletATMixerIndex).MixerType == DataHVACGlobals::No_ATMixer) return;
6260 :
6261 : // ATMixer properties only affect coil sizing when the mixer is on the inlet side of zone equipment
6262 78 : if (state.dataSingleDuct->SysATMixer(inletATMixerIndex).MixerType == DataHVACGlobals::ATMixer_SupplySide) {
6263 : // check if user has selected No to account for DOAS system
6264 35 : if (FinalZoneSizing.allocated() && state.dataSingleDuct->SysATMixer(inletATMixerIndex).printWarning) {
6265 22 : if (!FinalZoneSizing(curZoneEqNum).AccountForDOAS && FinalZoneSizing(curZoneEqNum).DOASControlStrategy != DOANeutralSup) {
6266 2 : ShowWarningError(state, "AirTerminal:SingleDuct:Mixer: " + state.dataSingleDuct->SysATMixer(inletATMixerIndex).Name);
6267 2 : ShowContinueError(
6268 : state,
6269 : " Supply side Air Terminal Mixer does not adjust zone equipment coil sizing and may result in inappropriately sized coils.");
6270 6 : ShowContinueError(state,
6271 4 : " Set Account for Dedicated Outdoor Air System = Yes in Sizing:Zone object for zone = " +
6272 2 : FinalZoneSizing(curZoneEqNum).ZoneName);
6273 : }
6274 22 : state.dataSingleDuct->SysATMixer(inletATMixerIndex).printWarning = false;
6275 : }
6276 35 : return; // do nothing else if this is a supply side ATMixer
6277 : }
6278 : // check if user has selected Yes to account for DOAS system
6279 43 : if (FinalZoneSizing.allocated() && state.dataSingleDuct->SysATMixer(inletATMixerIndex).printWarning) {
6280 43 : if (FinalZoneSizing(curZoneEqNum).AccountForDOAS && FinalZoneSizing(curZoneEqNum).DOASControlStrategy != DOANeutralSup) {
6281 0 : ShowWarningError(state, "AirTerminal:SingleDuct:Mixer: " + state.dataSingleDuct->SysATMixer(inletATMixerIndex).Name);
6282 0 : ShowContinueError(state, " Inlet side Air Terminal Mixer automatically adjusts zone equipment coil sizing.");
6283 0 : ShowContinueError(state,
6284 0 : " Set Account for Dedicated Outdoor Air System = No in Sizing:Zone object for zone = " +
6285 0 : FinalZoneSizing(curZoneEqNum).ZoneName);
6286 0 : state.dataSingleDuct->SysATMixer(inletATMixerIndex).printWarning = false;
6287 : }
6288 : }
6289 :
6290 : // proceed to set ATMixer properties used for sizing coils
6291 :
6292 : int airLoopIndex = // find air loop associated with ATMixer
6293 43 : state.dataZoneEquip->ZoneEquipConfig(controlledZoneNum)
6294 43 : .InletNodeAirLoopNum(state.dataSingleDuct->SysATMixer(inletATMixerIndex).CtrlZoneInNodeIndex);
6295 :
6296 : // must be a system sizing run or calculations are not possible
6297 43 : bool SizingDesRunThisAirSys = false; // Sizing:System object found flag
6298 43 : CheckThisAirSystemForSizing(state, airLoopIndex, SizingDesRunThisAirSys); // check for Sizing:System object
6299 :
6300 43 : if (SizingDesRunThisAirSys) {
6301 :
6302 : // set ATMixer outlet air flow rate in ZoneEqSizing array for ATMixer. If this value > 0, then the Sizer will know an ATMixer exists
6303 43 : ZoneEqSizing(curZoneEqNum).ATMixerVolFlow = state.dataSingleDuct->SysATMixer(inletATMixerIndex).DesignPrimaryAirVolRate;
6304 :
6305 : // If air loop has heating coil use SA conditions, else if OA sys has coils then use precool conditions, else use OA conditions
6306 43 : if (state.dataAirSystemsData->PrimaryAirSystems(airLoopIndex).CentralHeatCoilExists) {
6307 : // if central heating coil exists, ATMixer outlet is assumed to be at supply air conditions described in sizing input
6308 5 : ZoneEqSizing(curZoneEqNum).ATMixerHeatPriDryBulb = FinalSysSizing(airLoopIndex).HeatSupTemp;
6309 5 : ZoneEqSizing(curZoneEqNum).ATMixerHeatPriHumRat = FinalSysSizing(airLoopIndex).HeatSupHumRat;
6310 38 : } else if (state.dataAirSystemsData->PrimaryAirSystems(airLoopIndex).NumOAHeatCoils > 0) {
6311 : // if no central heating coil exists and an outdoor air coil does exist, then ATMixer outlet is mixture of preheat and return
6312 0 : if (FinalSysSizing(airLoopIndex).DesMainVolFlow == 0.0) { // protect divide by 0
6313 : // doesn't matter, just pick a condition
6314 0 : ZoneEqSizing(curZoneEqNum).ATMixerHeatPriDryBulb = FinalSysSizing(airLoopIndex).PreheatTemp;
6315 0 : ZoneEqSizing(curZoneEqNum).ATMixerHeatPriHumRat = FinalSysSizing(airLoopIndex).PreheatHumRat;
6316 : } else {
6317 : // mix preheat condition with return air condition based on OA frac. OA frac should nearly always be 1.
6318 : // OA frac is based on air loop fraction, not ATMixer flow fraction since air loop can serve multiple ATMixers
6319 0 : Real64 OutAirFrac = FinalSysSizing(airLoopIndex).DesOutAirVolFlow / FinalSysSizing(airLoopIndex).DesMainVolFlow;
6320 0 : OutAirFrac = min(1.0, max(0.0, OutAirFrac));
6321 :
6322 : // calculate humrat based on simple mixing
6323 : Real64 CoilInHumRatForSizing =
6324 0 : OutAirFrac * FinalSysSizing(airLoopIndex).PreheatHumRat + (1 - OutAirFrac) * FinalSysSizing(airLoopIndex).HeatRetHumRat;
6325 :
6326 : // calculate enthalpy based on simple mixing
6327 : Real64 CoilInEnthalpyForSizing =
6328 0 : OutAirFrac * Psychrometrics::PsyHFnTdbW(FinalSysSizing(airLoopIndex).PreheatTemp, FinalSysSizing(airLoopIndex).PreheatHumRat) +
6329 0 : (1 - OutAirFrac) *
6330 0 : Psychrometrics::PsyHFnTdbW(FinalSysSizing(airLoopIndex).HeatRetTemp, FinalSysSizing(airLoopIndex).HeatRetHumRat);
6331 :
6332 : // back calculate temperature based on humrat and enthalpy state points
6333 0 : Real64 CoilInTempForSizing = Psychrometrics::PsyTdbFnHW(CoilInEnthalpyForSizing, CoilInHumRatForSizing);
6334 :
6335 0 : ZoneEqSizing(curZoneEqNum).ATMixerHeatPriDryBulb = CoilInTempForSizing;
6336 0 : ZoneEqSizing(curZoneEqNum).ATMixerHeatPriHumRat = CoilInHumRatForSizing;
6337 : }
6338 : } else {
6339 : // else no coils exist in air loop so mix OA condition with return air condition
6340 38 : if (FinalSysSizing(airLoopIndex).DesMainVolFlow == 0.0) { // protect divide by 0
6341 : // doesn't matter, just pick a condition
6342 0 : ZoneEqSizing(curZoneEqNum).ATMixerHeatPriDryBulb = FinalSysSizing(airLoopIndex).HeatOutTemp;
6343 0 : ZoneEqSizing(curZoneEqNum).ATMixerHeatPriHumRat = FinalSysSizing(airLoopIndex).HeatOutHumRat;
6344 : } else {
6345 : // OA frac is based on air loop fraction, not ATMixer flow fraction since air loop can serve multiple ATMixers
6346 38 : Real64 OutAirFrac = FinalSysSizing(airLoopIndex).DesOutAirVolFlow / FinalSysSizing(airLoopIndex).DesMainVolFlow;
6347 38 : OutAirFrac = min(1.0, max(0.0, OutAirFrac));
6348 :
6349 : // calculate humrat based on simple mixing
6350 : Real64 CoilInHumRatForSizing =
6351 38 : OutAirFrac * FinalSysSizing(airLoopIndex).HeatOutHumRat + (1 - OutAirFrac) * FinalSysSizing(airLoopIndex).HeatRetHumRat;
6352 :
6353 : // calculate enthalpy based on simple mixing
6354 : Real64 CoilInEnthalpyForSizing =
6355 38 : OutAirFrac * Psychrometrics::PsyHFnTdbW(FinalSysSizing(airLoopIndex).HeatOutTemp, FinalSysSizing(airLoopIndex).HeatOutHumRat) +
6356 76 : (1 - OutAirFrac) *
6357 76 : Psychrometrics::PsyHFnTdbW(FinalSysSizing(airLoopIndex).HeatRetTemp, FinalSysSizing(airLoopIndex).HeatRetHumRat);
6358 :
6359 : // back calculate temperature based on humrat and enthalpy state points
6360 38 : Real64 CoilInTempForSizing = Psychrometrics::PsyTdbFnHW(CoilInEnthalpyForSizing, CoilInHumRatForSizing);
6361 :
6362 38 : ZoneEqSizing(curZoneEqNum).ATMixerHeatPriDryBulb = CoilInTempForSizing;
6363 38 : ZoneEqSizing(curZoneEqNum).ATMixerHeatPriHumRat = CoilInHumRatForSizing;
6364 : }
6365 : }
6366 :
6367 : // If air loop has cooling coil use SA conditions, else if OA sys has coils then use precool conditions, else use OA conditions
6368 43 : if (state.dataAirSystemsData->PrimaryAirSystems(airLoopIndex).CentralCoolCoilExists) {
6369 : // if central cooling coil exists, ATMixer outlet is assumed to be at supply air conditions described in sizing input
6370 5 : ZoneEqSizing(curZoneEqNum).ATMixerCoolPriDryBulb = FinalSysSizing(airLoopIndex).CoolSupTemp;
6371 5 : ZoneEqSizing(curZoneEqNum).ATMixerCoolPriHumRat = FinalSysSizing(airLoopIndex).CoolSupHumRat;
6372 38 : } else if (state.dataAirSystemsData->PrimaryAirSystems(airLoopIndex).NumOACoolCoils > 0) {
6373 : // if no central cooling coil exists and an outdoor air coil does exist, then ATMixer outlet is mixture of precool and return
6374 0 : if (FinalSysSizing(airLoopIndex).DesMainVolFlow == 0.0) { // protect divide by 0
6375 : // doesn't matter, just pick a condition
6376 0 : ZoneEqSizing(curZoneEqNum).ATMixerCoolPriDryBulb = FinalSysSizing(airLoopIndex).PrecoolTemp;
6377 0 : ZoneEqSizing(curZoneEqNum).ATMixerCoolPriHumRat = FinalSysSizing(airLoopIndex).PrecoolHumRat;
6378 : } else {
6379 : // mix precool condition with return air condition based on OA frac. OA frac should nearly always be 1.
6380 : // OA frac is based on air loop fraction, not ATMixer flow fraction since air loop can serve multiple ATMixers
6381 0 : Real64 OutAirFrac = FinalSysSizing(airLoopIndex).DesOutAirVolFlow / FinalSysSizing(airLoopIndex).DesMainVolFlow;
6382 0 : OutAirFrac = min(1.0, max(0.0, OutAirFrac));
6383 :
6384 : // calculate humrat based on simple mixing
6385 : Real64 CoilInHumRatForSizing =
6386 0 : OutAirFrac * FinalSysSizing(airLoopIndex).PrecoolHumRat + (1 - OutAirFrac) * FinalSysSizing(airLoopIndex).RetHumRatAtCoolPeak;
6387 :
6388 : // calculate enthalpy based on simple mixing
6389 : Real64 CoilInEnthalpyForSizing =
6390 0 : OutAirFrac * Psychrometrics::PsyHFnTdbW(FinalSysSizing(airLoopIndex).PrecoolTemp, FinalSysSizing(airLoopIndex).PrecoolHumRat) +
6391 0 : (1 - OutAirFrac) *
6392 0 : Psychrometrics::PsyHFnTdbW(FinalSysSizing(airLoopIndex).RetTempAtCoolPeak, FinalSysSizing(airLoopIndex).RetHumRatAtCoolPeak);
6393 :
6394 : // back calculate temperature based on humrat and enthalpy state points
6395 0 : Real64 CoilInTempForSizing = Psychrometrics::PsyTdbFnHW(CoilInEnthalpyForSizing, CoilInHumRatForSizing);
6396 :
6397 0 : ZoneEqSizing(curZoneEqNum).ATMixerCoolPriDryBulb = CoilInTempForSizing;
6398 0 : ZoneEqSizing(curZoneEqNum).ATMixerCoolPriHumRat = CoilInHumRatForSizing;
6399 : }
6400 : } else {
6401 : // else no coils exist in air loop so mix OA condition with return air condition
6402 38 : if (FinalSysSizing(airLoopIndex).DesMainVolFlow == 0.0) { // protect divide by 0
6403 : // doesn't matter, just pick a condition
6404 0 : ZoneEqSizing(curZoneEqNum).ATMixerCoolPriDryBulb = FinalSysSizing(airLoopIndex).OutTempAtCoolPeak;
6405 0 : ZoneEqSizing(curZoneEqNum).ATMixerCoolPriHumRat = FinalSysSizing(airLoopIndex).OutHumRatAtCoolPeak;
6406 : } else {
6407 : // OA frac is based on air loop fraction, not ATMixer flow fraction since air loop can serve multiple ATMixers
6408 38 : Real64 OutAirFrac = FinalSysSizing(airLoopIndex).DesOutAirVolFlow / FinalSysSizing(airLoopIndex).DesMainVolFlow;
6409 38 : OutAirFrac = min(1.0, max(0.0, OutAirFrac));
6410 :
6411 : // calculate humrat based on simple mixing
6412 38 : Real64 CoilInHumRatForSizing = OutAirFrac * FinalSysSizing(airLoopIndex).OutHumRatAtCoolPeak +
6413 38 : (1 - OutAirFrac) * FinalSysSizing(airLoopIndex).RetHumRatAtCoolPeak;
6414 :
6415 : // calculate enthalpy based on simple mixing
6416 38 : Real64 CoilInEnthalpyForSizing = OutAirFrac * Psychrometrics::PsyHFnTdbW(FinalSysSizing(airLoopIndex).OutTempAtCoolPeak,
6417 38 : FinalSysSizing(airLoopIndex).OutHumRatAtCoolPeak) +
6418 76 : (1 - OutAirFrac) * Psychrometrics::PsyHFnTdbW(FinalSysSizing(airLoopIndex).RetTempAtCoolPeak,
6419 76 : FinalSysSizing(airLoopIndex).RetHumRatAtCoolPeak);
6420 :
6421 : // back calculate temperature based on humrat and enthalpy state points
6422 38 : Real64 CoilInTempForSizing = Psychrometrics::PsyTdbFnHW(CoilInEnthalpyForSizing, CoilInHumRatForSizing);
6423 :
6424 38 : ZoneEqSizing(curZoneEqNum).ATMixerCoolPriDryBulb = CoilInTempForSizing;
6425 38 : ZoneEqSizing(curZoneEqNum).ATMixerCoolPriHumRat = CoilInHumRatForSizing;
6426 : }
6427 : }
6428 :
6429 : } else {
6430 : // warn user that system sizing is needed to size coils when AT Mixer is used ?
6431 : // if there were a message here then this function should only be called when SizingDesRunThisZone is true
6432 : }
6433 : }
6434 :
6435 32682712 : void SingleDuctAirTerminal::CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state)
6436 : {
6437 : // calculates zone outdoor air volume flow rate using the supply air flow rate and OA fraction
6438 32682712 : if (this->AirLoopNum > 0) {
6439 32673825 : this->OutdoorAirFlowRate =
6440 32673825 : (this->sd_airterminalOutlet.AirMassFlowRate / state.dataEnvrn->StdRhoAir) * state.dataAirLoop->AirLoopFlow(this->AirLoopNum).OAFrac;
6441 : } else {
6442 8887 : this->OutdoorAirFlowRate = 0.0;
6443 : }
6444 32682712 : }
6445 :
6446 : // End of Reporting subroutines for the Sys Module
6447 : // *****************************************************************************
6448 :
6449 2313 : } // namespace EnergyPlus::SingleDuct
|