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