Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/Autosizing/Base.hh>
57 : #include <EnergyPlus/BranchNodeConnections.hh>
58 : #include <EnergyPlus/Data/EnergyPlusData.hh>
59 : #include <EnergyPlus/DataDefineEquip.hh>
60 : #include <EnergyPlus/DataEnvironment.hh>
61 : #include <EnergyPlus/DataHVACGlobals.hh>
62 : #include <EnergyPlus/DataLoopNode.hh>
63 : #include <EnergyPlus/DataSizing.hh>
64 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
65 : #include <EnergyPlus/DataZoneEquipment.hh>
66 : #include <EnergyPlus/FluidProperties.hh>
67 : #include <EnergyPlus/General.hh>
68 : #include <EnergyPlus/GeneralRoutines.hh>
69 : #include <EnergyPlus/HVACSingleDuctInduc.hh>
70 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
71 : #include <EnergyPlus/MixerComponent.hh>
72 : #include <EnergyPlus/NodeInputManager.hh>
73 : #include <EnergyPlus/OutputProcessor.hh>
74 : #include <EnergyPlus/Plant/DataPlant.hh>
75 : #include <EnergyPlus/PlantUtilities.hh>
76 : #include <EnergyPlus/Psychrometrics.hh>
77 : #include <EnergyPlus/ScheduleManager.hh>
78 : #include <EnergyPlus/UtilityRoutines.hh>
79 : #include <EnergyPlus/WaterCoils.hh>
80 :
81 : namespace EnergyPlus {
82 :
83 : namespace HVACSingleDuctInduc {
84 :
85 : // Module containing routines dealing terminal 4 pipe induction terminal units
86 :
87 : // MODULE INFORMATION:
88 : // AUTHOR Fred Buhl
89 : // DATE WRITTEN June 15 2004
90 : // MODIFIED Brent Griffith, Sept 2010, plant upgrades, fluid props
91 : // RE-ENGINEERED na
92 :
93 : // PURPOSE OF THIS MODULE:
94 : // To encapsulate the data and algorithms needed to simulate 4 pipe induction terminal units
95 :
96 : // METHODOLOGY EMPLOYED:
97 : // The terminal boxes are modeled as compound components: heating coil, cooling coil and
98 : // mixer. The combined components are controlled to meet the zone load.
99 :
100 : // Using/Aliasing
101 : using namespace DataLoopNode;
102 : using namespace ScheduleManager;
103 : using DataHVACGlobals::SmallAirVolFlow;
104 : using DataHVACGlobals::SmallLoad;
105 : using DataHVACGlobals::SmallMassFlow;
106 : using Psychrometrics::PsyCpAirFnW;
107 : using Psychrometrics::PsyHFnTdbW;
108 : using Psychrometrics::PsyRhoAirFnPbTdbW;
109 :
110 12104 : void SimIndUnit(EnergyPlusData &state,
111 : std::string_view CompName, // name of the terminal unit
112 : bool const FirstHVACIteration, // TRUE if first HVAC iteration in time step
113 : int const ZoneNum, // index of zone served by the terminal unit
114 : int const ZoneNodeNum, // zone node number of zone served by the terminal unit
115 : int &CompIndex // which terminal unit in data structure
116 : )
117 : {
118 :
119 : // SUBROUTINE INFORMATION:
120 : // AUTHOR Fred Buhl
121 : // DATE WRITTEN June 18 2004
122 : // MODIFIED na
123 : // RE-ENGINEERED na
124 :
125 : // PURPOSE OF THIS SUBROUTINE:
126 : // Manages the simulation of a passive (no fan) induction terminal unit.
127 : // Called from SimZoneAirLoopEquipment in module ZoneAirLoopEquipmentManager.
128 :
129 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
130 : int IUNum; // index of terminal unit being simulated
131 :
132 : // First time SimIndUnit is called, get the input for all the passive terminal induction units
133 12104 : if (state.dataHVACSingleDuctInduc->GetIUInputFlag) {
134 1 : GetIndUnits(state);
135 1 : state.dataHVACSingleDuctInduc->GetIUInputFlag = false;
136 : }
137 :
138 12104 : auto &IndUnit = state.dataHVACSingleDuctInduc->IndUnit;
139 :
140 : // Get the induction unit index
141 12104 : if (CompIndex == 0) {
142 4 : IUNum = UtilityRoutines::FindItemInList(CompName, state.dataHVACSingleDuctInduc->IndUnit);
143 4 : if (IUNum == 0) {
144 0 : ShowFatalError(state, "SimIndUnit: Induction Unit not found=" + std::string{CompName});
145 : }
146 4 : CompIndex = IUNum;
147 : } else {
148 12100 : IUNum = CompIndex;
149 12100 : if (IUNum > state.dataHVACSingleDuctInduc->NumIndUnits || IUNum < 1) {
150 0 : ShowFatalError(state,
151 0 : format("SimIndUnit: Invalid CompIndex passed={}, Number of Induction Units={}, System name={}",
152 : CompIndex,
153 0 : state.dataHVACSingleDuctInduc->NumIndUnits,
154 0 : CompName));
155 : }
156 12100 : if (state.dataHVACSingleDuctInduc->CheckEquipName(IUNum)) {
157 4 : if (CompName != IndUnit(IUNum).Name) {
158 0 : ShowFatalError(state,
159 0 : format("SimIndUnit: Invalid CompIndex passed={}, Induction Unit name={}, stored Induction Unit for that index={}",
160 : CompIndex,
161 : CompName,
162 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name));
163 : }
164 4 : state.dataHVACSingleDuctInduc->CheckEquipName(IUNum) = false;
165 : }
166 : }
167 :
168 12104 : state.dataSize->CurTermUnitSizingNum =
169 12104 : state.dataDefineEquipment->AirDistUnit(state.dataHVACSingleDuctInduc->IndUnit(IUNum).ADUNum).TermUnitSizingNum;
170 : // initialize the unit
171 12104 : InitIndUnit(state, IUNum, FirstHVACIteration);
172 :
173 12104 : state.dataSize->TermUnitIU = true;
174 :
175 : // Select the correct unit type
176 12104 : switch (state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType_Num) {
177 12104 : case SingleDuct_CV::FourPipeInduc: {
178 12104 : SimFourPipeIndUnit(state, IUNum, ZoneNum, ZoneNodeNum, FirstHVACIteration);
179 12104 : } break;
180 0 : default: {
181 0 : ShowSevereError(state, "Illegal Induction Unit Type used=" + state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType);
182 0 : ShowContinueError(state, "Occurs in Induction Unit=" + state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
183 0 : ShowFatalError(state, "Preceding condition causes termination.");
184 0 : } break;
185 : }
186 :
187 12104 : state.dataSize->TermUnitIU = false;
188 :
189 : // the tasks usually done by the Update and Report routines are not required in a compound terminal unit.
190 :
191 : // Update the current unit's outlet nodes. No update needed
192 :
193 : // Fill the report variables. There are no report variables
194 12104 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).ReportIndUnit(state);
195 12104 : }
196 :
197 2 : void GetIndUnits(EnergyPlusData &state)
198 : {
199 :
200 : // SUBROUTINE INFORMATION:
201 : // AUTHOR Fred Buhl
202 : // DATE WRITTEN June 15 2004
203 : // MODIFIED na
204 : // RE-ENGINEERED na
205 :
206 : // PURPOSE OF THIS SUBROUTINE:
207 : // Obtains input data for passive induction air terminal units and stores it in the
208 : // induction terminal unit data structures
209 :
210 : // METHODOLOGY EMPLOYED:
211 : // Uses "Get" routines to read in data.
212 :
213 : // Using/Aliasing
214 : using BranchNodeConnections::SetUpCompSets;
215 : using BranchNodeConnections::TestCompSet;
216 : using NodeInputManager::GetOnlySingleNode;
217 : using namespace DataSizing;
218 :
219 : using MixerComponent::GetZoneMixerIndex;
220 : using WaterCoils::GetCoilWaterInletNode;
221 :
222 : // SUBROUTINE PARAMETER DEFINITIONS:
223 : static constexpr std::string_view RoutineName("GetIndUnits "); // include trailing blank space
224 :
225 : int IUIndex; // loop index
226 : int IUNum; // current fan coil number
227 4 : std::string CurrentModuleObject; // for ease in getting objects
228 4 : Array1D_string Alphas; // Alpha input items for object
229 4 : Array1D_string cAlphaFields; // Alpha field names
230 4 : Array1D_string cNumericFields; // Numeric field names
231 4 : Array1D<Real64> Numbers; // Numeric input items for object
232 4 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
233 4 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
234 2 : int NumAlphas(0); // Number of Alphas for each GetObjectItem call
235 2 : int NumNumbers(0); // Number of Numbers for each GetObjectItem call
236 2 : int TotalArgs(0); // Total number of alpha and numeric arguments (max) for a
237 : // certain object in the input file
238 : int IOStatus; // Used in GetObjectItem
239 2 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
240 : bool IsNotOK; // Flag to verify name
241 : int CtrlZone; // controlled zome do loop index
242 : int SupAirIn; // controlled zone supply air inlet index
243 : bool AirNodeFound;
244 : int ADUNum;
245 : bool errFlag;
246 :
247 2 : auto &ZoneEquipConfig(state.dataZoneEquip->ZoneEquipConfig);
248 :
249 : // find the number of each type of induction unit
250 2 : CurrentModuleObject = "AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction";
251 2 : state.dataHVACSingleDuctInduc->NumFourPipes = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
252 2 : state.dataHVACSingleDuctInduc->NumIndUnits = state.dataHVACSingleDuctInduc->NumFourPipes;
253 : // allocate the data structures
254 2 : state.dataHVACSingleDuctInduc->IndUnit.allocate(state.dataHVACSingleDuctInduc->NumIndUnits);
255 2 : state.dataHVACSingleDuctInduc->CheckEquipName.dimension(state.dataHVACSingleDuctInduc->NumIndUnits, true);
256 :
257 2 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, TotalArgs, NumAlphas, NumNumbers);
258 :
259 2 : Alphas.allocate(NumAlphas);
260 2 : cAlphaFields.allocate(NumAlphas);
261 2 : cNumericFields.allocate(NumNumbers);
262 2 : Numbers.dimension(NumNumbers, 0.0);
263 2 : lAlphaBlanks.dimension(NumAlphas, true);
264 2 : lNumericBlanks.dimension(NumNumbers, true);
265 :
266 : // loop over Series PIUs; get and load the input data
267 6 : for (IUIndex = 1; IUIndex <= state.dataHVACSingleDuctInduc->NumFourPipes; ++IUIndex) {
268 :
269 4 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
270 : CurrentModuleObject,
271 : IUIndex,
272 : Alphas,
273 : NumAlphas,
274 : Numbers,
275 : NumNumbers,
276 : IOStatus,
277 : lNumericBlanks,
278 : lAlphaBlanks,
279 : cAlphaFields,
280 : cNumericFields);
281 :
282 4 : IUNum = IUIndex;
283 4 : UtilityRoutines::IsNameEmpty(state, Alphas(1), CurrentModuleObject, ErrorsFound);
284 :
285 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name = Alphas(1);
286 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType = CurrentModuleObject;
287 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType_Num = SingleDuct_CV::FourPipeInduc;
288 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Sched = Alphas(2);
289 4 : if (lAlphaBlanks(2)) {
290 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
291 : } else {
292 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).SchedPtr = GetScheduleIndex(state, Alphas(2)); // convert schedule name to pointer
293 4 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).SchedPtr == 0) {
294 0 : ShowSevereError(state,
295 0 : std::string{RoutineName} + CurrentModuleObject + ": invalid " + cAlphaFields(2) + " entered =" + Alphas(2) +
296 0 : " for " + cAlphaFields(1) + '=' + Alphas(1));
297 0 : ErrorsFound = true;
298 : }
299 : }
300 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow = Numbers(1);
301 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio = Numbers(2);
302 4 : if (lNumericBlanks(2)) state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio = 2.5;
303 :
304 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode =
305 8 : GetOnlySingleNode(state,
306 4 : Alphas(3),
307 : ErrorsFound,
308 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeInduction,
309 4 : Alphas(1),
310 : DataLoopNode::NodeFluidType::Air,
311 : DataLoopNode::ConnectionType::Inlet,
312 : NodeInputManager::CompFluidStream::Primary,
313 : ObjectIsParent,
314 4 : cAlphaFields(3));
315 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).SecAirInNode =
316 8 : GetOnlySingleNode(state,
317 4 : Alphas(4),
318 : ErrorsFound,
319 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeInduction,
320 4 : Alphas(1),
321 : DataLoopNode::NodeFluidType::Air,
322 : DataLoopNode::ConnectionType::Inlet,
323 : NodeInputManager::CompFluidStream::Primary,
324 : ObjectIsParent,
325 4 : cAlphaFields(4));
326 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode =
327 8 : GetOnlySingleNode(state,
328 4 : Alphas(5),
329 : ErrorsFound,
330 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeInduction,
331 4 : Alphas(1),
332 : DataLoopNode::NodeFluidType::Air,
333 : DataLoopNode::ConnectionType::Outlet,
334 : NodeInputManager::CompFluidStream::Primary,
335 : ObjectIsParent,
336 4 : cAlphaFields(5));
337 :
338 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType = Alphas(6); // type (key) of heating coil
339 4 : if (UtilityRoutines::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType, "Coil:Heating:Water")) {
340 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HeatingCoilType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
341 : }
342 :
343 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil = Alphas(7); // name of heating coil object
344 4 : IsNotOK = false;
345 8 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWControlNode = GetCoilWaterInletNode(
346 8 : state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil, IsNotOK);
347 4 : if (IsNotOK) {
348 0 : ShowContinueError(state, "In " + CurrentModuleObject + " = " + state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
349 0 : ShowContinueError(state, "..Only Coil:Heating:Water is allowed.");
350 0 : ErrorsFound = true;
351 : }
352 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow = Numbers(3);
353 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinVolHotWaterFlow = Numbers(4);
354 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HotControlOffset = Numbers(5);
355 :
356 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType = Alphas(8); // type (key) of cooling coil
357 :
358 4 : if (UtilityRoutines::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, "Coil:Cooling:Water")) {
359 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CoolingCoilType = DataPlant::PlantEquipmentType::CoilWaterCooling;
360 0 : } else if (UtilityRoutines::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, "Coil:Cooling:Water:DetailedGeometry")) {
361 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CoolingCoilType = DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling;
362 : }
363 :
364 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil = Alphas(9); // name of cooling coil object
365 4 : IsNotOK = false;
366 8 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWControlNode = GetCoilWaterInletNode(
367 8 : state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil, IsNotOK);
368 4 : if (IsNotOK) {
369 0 : ShowContinueError(state, "In " + CurrentModuleObject + " = " + state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
370 0 : ShowContinueError(state, "..Only Coil:Cooling:Water or Coil:Cooling:Water:DetailedGeometry is allowed.");
371 0 : ErrorsFound = true;
372 : }
373 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow = Numbers(6);
374 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinVolColdWaterFlow = Numbers(7);
375 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).ColdControlOffset = Numbers(8);
376 :
377 : // Get the Zone Mixer name and check that it is OK
378 4 : errFlag = false;
379 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MixerName = Alphas(10);
380 8 : GetZoneMixerIndex(state,
381 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MixerName,
382 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Mixer_Num,
383 : errFlag,
384 : CurrentModuleObject);
385 4 : if (errFlag) {
386 0 : ShowContinueError(state, "...specified in " + CurrentModuleObject + " = " + state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
387 0 : ErrorsFound = true;
388 : }
389 :
390 : // Add heating coil to component sets array
391 20 : SetUpCompSets(state,
392 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
393 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
394 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType,
395 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil,
396 4 : Alphas(4),
397 4 : "UNDEFINED");
398 : // Add cooling coil to component sets array
399 16 : SetUpCompSets(state,
400 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
401 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
402 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType,
403 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
404 : "UNDEFINED",
405 4 : "UNDEFINED");
406 :
407 : // Register component set data
408 12 : TestCompSet(state,
409 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
410 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
411 4 : state.dataLoopNodes->NodeID(state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode),
412 4 : state.dataLoopNodes->NodeID(state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode),
413 : "Air Nodes");
414 :
415 4 : AirNodeFound = false;
416 24 : for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
417 20 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
418 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).ADUNum = ADUNum;
419 : }
420 : }
421 : // one assumes if there isn't one assigned, it's an error?
422 4 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).ADUNum == 0) {
423 0 : ShowSevereError(state,
424 0 : std::string{RoutineName} + "No matching Air Distribution Unit, for Unit = [" +
425 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + ',' +
426 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "].");
427 0 : ShowContinueError(
428 0 : state, "...should have outlet node=" + state.dataLoopNodes->NodeID(state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode));
429 0 : ErrorsFound = true;
430 : } else {
431 : // Fill the Zone Equipment data with the supply air inlet node number of this unit.
432 28 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
433 24 : if (!ZoneEquipConfig(CtrlZone).IsControlled) continue;
434 36 : for (SupAirIn = 1; SupAirIn <= ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
435 20 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode == ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
436 4 : if (ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode > 0) {
437 0 : ShowSevereError(state, "Error in connecting a terminal unit to a zone");
438 0 : ShowContinueError(state,
439 0 : state.dataLoopNodes->NodeID(state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode) +
440 : " already connects to another zone");
441 0 : ShowContinueError(state,
442 0 : "Occurs for terminal unit " + state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + " = " +
443 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
444 0 : ShowContinueError(state, "Check terminal unit node names for errors");
445 0 : ErrorsFound = true;
446 : } else {
447 4 : ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode =
448 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode;
449 4 : ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode =
450 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode;
451 4 : state.dataDefineEquipment->AirDistUnit(state.dataHVACSingleDuctInduc->IndUnit(IUNum).ADUNum).TermUnitSizingNum =
452 4 : ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
453 4 : state.dataDefineEquipment->AirDistUnit(state.dataHVACSingleDuctInduc->IndUnit(IUNum).ADUNum).ZoneEqNum = CtrlZone;
454 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneNum = CtrlZone;
455 : }
456 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneInNodeIndex = SupAirIn;
457 4 : AirNodeFound = true;
458 4 : break;
459 : }
460 : }
461 : }
462 4 : if (!AirNodeFound) {
463 0 : ShowSevereError(
464 0 : state, "The outlet air node from the " + CurrentModuleObject + " = " + state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
465 0 : ShowContinueError(state, "did not have a matching Zone Equipment Inlet Node, Node =" + Alphas(3));
466 0 : ErrorsFound = true;
467 : }
468 : }
469 : // report variable for all single duct air terminals
470 16 : SetupOutputVariable(state,
471 : "Zone Air Terminal Outdoor Air Volume Flow Rate",
472 : OutputProcessor::Unit::m3_s,
473 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutdoorAirFlowRate,
474 : OutputProcessor::SOVTimeStepType::System,
475 : OutputProcessor::SOVStoreType::Average,
476 8 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
477 : }
478 :
479 2 : Alphas.deallocate();
480 2 : cAlphaFields.deallocate();
481 2 : cNumericFields.deallocate();
482 2 : Numbers.deallocate();
483 2 : lAlphaBlanks.deallocate();
484 2 : lNumericBlanks.deallocate();
485 2 : if (ErrorsFound) {
486 0 : ShowFatalError(state, std::string{RoutineName} + "Errors found in getting input. Preceding conditions cause termination.");
487 : }
488 2 : }
489 :
490 12104 : void InitIndUnit(EnergyPlusData &state,
491 : int const IUNum, // number of the current induction unit being simulated
492 : bool const FirstHVACIteration // TRUE if first air loop solution this HVAC step
493 : )
494 : {
495 :
496 : // SUBROUTINE INFORMATION:
497 : // AUTHOR Fred Buhl
498 : // DATE WRITTEN June 21 2004
499 : // MODIFIED na
500 : // RE-ENGINEERED na
501 :
502 : // PURPOSE OF THIS SUBROUTINE:
503 : // This subroutine is for initialization of the passive induction
504 : // terminal boxes
505 :
506 : // METHODOLOGY EMPLOYED:
507 : // Uses the status flags to trigger initializations.
508 :
509 : // Using/Aliasing
510 :
511 : using DataZoneEquipment::CheckZoneEquipmentList;
512 : using FluidProperties::GetDensityGlycol;
513 : using PlantUtilities::InitComponentNodes;
514 : using PlantUtilities::ScanPlantLoopsForObject;
515 :
516 : // SUBROUTINE PARAMETER DEFINITIONS:
517 : static constexpr std::string_view RoutineName("InitIndUnit");
518 :
519 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
520 : int PriNode; // primary air inlet node number
521 : int SecNode; // secondary air inlet node number
522 : int OutletNode; // unit air outlet node
523 : int HotConNode; // hot water control node number
524 : int ColdConNode; // cold water control node number
525 : Real64 IndRat; // unit induction ratio
526 : Real64 RhoAir; // air density at outside pressure and standard temperature and humidity
527 :
528 : int Loop; // Loop checking control variable
529 : Real64 rho; // local fluid density
530 : int HWOutletNode; // local node index for hot water coil's outlet node
531 : int CWOutletNode; // local node index for cold water coil's outlet node
532 12104 : bool errFlag(false);
533 :
534 12104 : auto &ZoneEquipmentListChecked = state.dataHVACSingleDuctInduc->ZoneEquipmentListChecked;
535 :
536 : // Do the one time initializations
537 12104 : if (state.dataHVACSingleDuctInduc->MyOneTimeFlag) {
538 :
539 1 : state.dataHVACSingleDuctInduc->MyEnvrnFlag.allocate(state.dataHVACSingleDuctInduc->NumIndUnits);
540 1 : state.dataHVACSingleDuctInduc->MySizeFlag.allocate(state.dataHVACSingleDuctInduc->NumIndUnits);
541 1 : state.dataHVACSingleDuctInduc->MyPlantScanFlag.allocate(state.dataHVACSingleDuctInduc->NumIndUnits);
542 1 : state.dataHVACSingleDuctInduc->MyAirDistInitFlag.allocate(state.dataHVACSingleDuctInduc->NumIndUnits);
543 1 : state.dataHVACSingleDuctInduc->MyEnvrnFlag = true;
544 1 : state.dataHVACSingleDuctInduc->MySizeFlag = true;
545 1 : state.dataHVACSingleDuctInduc->MyPlantScanFlag = true;
546 1 : state.dataHVACSingleDuctInduc->MyAirDistInitFlag = true;
547 1 : state.dataHVACSingleDuctInduc->MyOneTimeFlag = false;
548 : }
549 :
550 12104 : if (state.dataHVACSingleDuctInduc->MyPlantScanFlag(IUNum) && allocated(state.dataPlnt->PlantLoop)) {
551 4 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).HeatingCoilType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) {
552 4 : errFlag = false;
553 16 : ScanPlantLoopsForObject(state,
554 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil,
555 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HeatingCoilType,
556 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc,
557 : errFlag,
558 : _,
559 : _,
560 : _,
561 : _,
562 : _);
563 : }
564 4 : if (errFlag) {
565 0 : ShowContinueError(state,
566 0 : "Reference Unit=\"" + state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name +
567 0 : "\", type=" + state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType);
568 : }
569 4 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).CoolingCoilType == DataPlant::PlantEquipmentType::CoilWaterCooling ||
570 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CoolingCoilType == DataPlant::PlantEquipmentType::CoilWaterDetailedFlatCooling) {
571 4 : errFlag = false;
572 16 : ScanPlantLoopsForObject(state,
573 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
574 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CoolingCoilType,
575 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc,
576 : errFlag,
577 : _,
578 : _,
579 : _,
580 : _,
581 : _);
582 : }
583 4 : if (errFlag) {
584 0 : ShowContinueError(state,
585 0 : "Reference Unit=\"" + state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name +
586 0 : "\", type=" + state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType);
587 0 : ShowFatalError(state, "InitIndUnit: Program terminated for previous conditions.");
588 : }
589 4 : state.dataHVACSingleDuctInduc->MyPlantScanFlag(IUNum) = false;
590 12100 : } else if (state.dataHVACSingleDuctInduc->MyPlantScanFlag(IUNum) && !state.dataGlobal->AnyPlantInModel) {
591 0 : state.dataHVACSingleDuctInduc->MyPlantScanFlag(IUNum) = false;
592 : }
593 :
594 12104 : if (state.dataHVACSingleDuctInduc->MyAirDistInitFlag(IUNum)) {
595 : // save the induction ratio in the term unit sizing array for use in the system sizing calculation
596 12 : if (state.dataSize->CurTermUnitSizingNum > 0) {
597 12 : state.dataSize->TermUnitSizing(state.dataSize->CurTermUnitSizingNum).InducRat =
598 12 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio;
599 : }
600 12 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).AirLoopNum == 0) {
601 16 : if ((state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneNum > 0) &&
602 8 : (state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneInNodeIndex > 0)) {
603 8 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).AirLoopNum =
604 8 : state.dataZoneEquip->ZoneEquipConfig(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneNum)
605 8 : .InletNodeAirLoopNum(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CtrlZoneInNodeIndex);
606 8 : state.dataDefineEquipment->AirDistUnit(state.dataHVACSingleDuctInduc->IndUnit(IUNum).ADUNum).AirLoopNum =
607 8 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).AirLoopNum;
608 : }
609 : } else {
610 4 : state.dataHVACSingleDuctInduc->MyAirDistInitFlag(IUNum) = false;
611 : }
612 : }
613 12104 : if (!ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
614 1 : ZoneEquipmentListChecked = true;
615 : // Check to see if there is a Air Distribution Unit on the Zone Equipment List
616 5 : for (Loop = 1; Loop <= state.dataHVACSingleDuctInduc->NumIndUnits; ++Loop) {
617 4 : if (state.dataHVACSingleDuctInduc->IndUnit(Loop).ADUNum == 0) continue;
618 12 : if (CheckZoneEquipmentList(state,
619 : "ZONEHVAC:AIRDISTRIBUTIONUNIT",
620 8 : state.dataDefineEquipment->AirDistUnit(state.dataHVACSingleDuctInduc->IndUnit(Loop).ADUNum).Name))
621 4 : continue;
622 0 : ShowSevereError(state,
623 0 : "InitIndUnit: ADU=[Air Distribution Unit," +
624 0 : state.dataDefineEquipment->AirDistUnit(state.dataHVACSingleDuctInduc->IndUnit(Loop).ADUNum).Name +
625 : "] is not on any ZoneHVAC:EquipmentList.");
626 0 : ShowContinueError(state,
627 0 : "...Unit=[" + state.dataHVACSingleDuctInduc->IndUnit(Loop).UnitType + ',' +
628 0 : state.dataHVACSingleDuctInduc->IndUnit(Loop).Name + "] will not be simulated.");
629 : }
630 : }
631 :
632 12104 : if (!state.dataGlobal->SysSizingCalc && state.dataHVACSingleDuctInduc->MySizeFlag(IUNum)) {
633 :
634 4 : SizeIndUnit(state, IUNum);
635 4 : state.dataHVACSingleDuctInduc->MySizeFlag(IUNum) = false;
636 : }
637 :
638 : // Do the Begin Environment initializations
639 12104 : if (state.dataGlobal->BeginEnvrnFlag && state.dataHVACSingleDuctInduc->MyEnvrnFlag(IUNum)) {
640 24 : RhoAir = state.dataEnvrn->StdRhoAir;
641 24 : PriNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode;
642 24 : SecNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).SecAirInNode;
643 24 : OutletNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode;
644 24 : IndRat = state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio;
645 : // set the mass flow rates from the input volume flow rates
646 24 : if (UtilityRoutines::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
647 24 : "AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction")) {
648 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirMassFlow =
649 24 : RhoAir * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow;
650 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow =
651 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirMassFlow / (1.0 + IndRat);
652 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow =
653 24 : IndRat * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirMassFlow / (1.0 + IndRat);
654 24 : state.dataLoopNodes->Node(PriNode).MassFlowRateMax = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow;
655 24 : state.dataLoopNodes->Node(PriNode).MassFlowRateMin = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow;
656 24 : state.dataLoopNodes->Node(SecNode).MassFlowRateMax = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow;
657 24 : state.dataLoopNodes->Node(SecNode).MassFlowRateMin = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow;
658 24 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMax = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirMassFlow;
659 : }
660 :
661 24 : HotConNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWControlNode;
662 24 : if (HotConNode > 0 && !state.dataHVACSingleDuctInduc->MyPlantScanFlag(IUNum)) {
663 :
664 48 : rho = GetDensityGlycol(state,
665 24 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc.loopNum).FluidName,
666 : DataGlobalConstants::HWInitConvTemp,
667 24 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc.loopNum).FluidIndex,
668 : RoutineName);
669 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxHotWaterFlow =
670 24 : rho * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow;
671 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinHotWaterFlow =
672 24 : rho * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinVolHotWaterFlow;
673 : // get component outlet node from plant structure
674 24 : HWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc).NodeNumOut;
675 48 : InitComponentNodes(state,
676 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinHotWaterFlow,
677 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxHotWaterFlow,
678 : HotConNode,
679 : HWOutletNode);
680 : }
681 :
682 24 : ColdConNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWControlNode;
683 24 : if (ColdConNode > 0) {
684 48 : rho = GetDensityGlycol(state,
685 24 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc.loopNum).FluidName,
686 : DataGlobalConstants::CWInitConvTemp,
687 24 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc.loopNum).FluidIndex,
688 : RoutineName);
689 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxColdWaterFlow =
690 24 : rho * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow;
691 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinColdWaterFlow =
692 24 : rho * state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinVolColdWaterFlow;
693 :
694 24 : CWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc).NodeNumOut;
695 48 : InitComponentNodes(state,
696 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinColdWaterFlow,
697 24 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxColdWaterFlow,
698 : ColdConNode,
699 : CWOutletNode);
700 : }
701 :
702 24 : state.dataHVACSingleDuctInduc->MyEnvrnFlag(IUNum) = false;
703 : } // end one time inits
704 :
705 12104 : if (!state.dataGlobal->BeginEnvrnFlag) {
706 11964 : state.dataHVACSingleDuctInduc->MyEnvrnFlag(IUNum) = true;
707 : }
708 :
709 12104 : PriNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode;
710 12104 : SecNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).SecAirInNode;
711 :
712 : // Do the start of HVAC time step initializations
713 12104 : if (FirstHVACIteration) {
714 : // check for upstream zero flow. If nonzero and schedule ON, set primary flow to max
715 12120 : if (GetCurrentScheduleValue(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).SchedPtr) > 0.0 &&
716 6052 : state.dataLoopNodes->Node(PriNode).MassFlowRate > 0.0) {
717 6032 : if (UtilityRoutines::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
718 6032 : "AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction")) {
719 6032 : state.dataLoopNodes->Node(PriNode).MassFlowRate = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow;
720 6032 : state.dataLoopNodes->Node(SecNode).MassFlowRate = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow;
721 : }
722 : } else {
723 36 : state.dataLoopNodes->Node(PriNode).MassFlowRate = 0.0;
724 36 : state.dataLoopNodes->Node(SecNode).MassFlowRate = 0.0;
725 : }
726 : // reset the max and min avail flows
727 12120 : if (GetCurrentScheduleValue(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).SchedPtr) > 0.0 &&
728 6052 : state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail > 0.0) {
729 6032 : if (UtilityRoutines::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
730 6032 : "AirTerminal:SingleDuct:ConstantVolume:FourPipeInduction")) {
731 6032 : state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow;
732 6032 : state.dataLoopNodes->Node(PriNode).MassFlowRateMinAvail = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxPriAirMassFlow;
733 6032 : state.dataLoopNodes->Node(SecNode).MassFlowRateMaxAvail = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow;
734 6032 : state.dataLoopNodes->Node(SecNode).MassFlowRateMinAvail = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxSecAirMassFlow;
735 : }
736 : } else {
737 36 : state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail = 0.0;
738 36 : state.dataLoopNodes->Node(PriNode).MassFlowRateMinAvail = 0.0;
739 36 : state.dataLoopNodes->Node(SecNode).MassFlowRateMaxAvail = 0.0;
740 36 : state.dataLoopNodes->Node(SecNode).MassFlowRateMinAvail = 0.0;
741 : }
742 : }
743 12104 : }
744 :
745 4 : void SizeIndUnit(EnergyPlusData &state, int const IUNum)
746 : {
747 :
748 : // SUBROUTINE INFORMATION:
749 : // AUTHOR Fred Buhl
750 : // DATE WRITTEN June 22 2004
751 : // MODIFIED August 2013 Daeho Kang, add component sizing table entries
752 : // RE-ENGINEERED na
753 :
754 : // PURPOSE OF THIS SUBROUTINE:
755 : // This subroutine is for sizing induction terminal units for which flow rates have not been
756 : // specified in the input
757 :
758 : // METHODOLOGY EMPLOYED:
759 : // Accesses zone sizing array for air flow rates and zone and plant sizing arrays to
760 : // calculate coil water flow rates.
761 :
762 : // Using/Aliasing
763 : using namespace DataSizing;
764 : using FluidProperties::GetDensityGlycol;
765 : using FluidProperties::GetSpecificHeatGlycol;
766 :
767 : using PlantUtilities::MyPlantSizingIndex;
768 : using WaterCoils::GetCoilWaterInletNode;
769 : using WaterCoils::GetCoilWaterOutletNode;
770 : using WaterCoils::SetCoilDesFlow;
771 :
772 : // SUBROUTINE PARAMETER DEFINITIONS:
773 : static constexpr std::string_view RoutineName("SizeIndUnit");
774 :
775 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
776 : int PltSizHeatNum; // index of plant sizing object for 1st heating loop
777 : int PltSizCoolNum; // index of plant sizing object for 1st cooling loop
778 : Real64 DesCoilLoad;
779 : Real64 DesPriVolFlow;
780 : Real64 RhoAir;
781 : Real64 CpAir;
782 4 : int CoilWaterInletNode(0);
783 4 : int CoilWaterOutletNode(0);
784 : bool ErrorsFound;
785 : Real64 Cp; // local fluid specific heat
786 : Real64 rho; // local fluid density
787 : bool IsAutoSize;
788 : Real64 MaxTotAirVolFlowDes; // Desing size maximum air volume flow for reproting
789 : Real64 MaxTotAirVolFlowUser; // User hard-sized maximum air volume flow for reporting
790 : Real64 MaxVolHotWaterFlowDes; // Desing size maximum hot water flow for reproting
791 : Real64 MaxVolHotWaterFlowUser; // User hard-sized maximum hot water flow for reporting
792 : Real64 MaxVolColdWaterFlowDes; // Desing size maximum cold water flow for reproting
793 : Real64 MaxVolColdWaterFlowUser; // User hard-sized maximum cold water flow for reporting
794 :
795 4 : PltSizHeatNum = 0;
796 4 : PltSizCoolNum = 0;
797 4 : DesPriVolFlow = 0.0;
798 4 : CpAir = 0.0;
799 4 : RhoAir = state.dataEnvrn->StdRhoAir;
800 4 : ErrorsFound = false;
801 4 : IsAutoSize = false;
802 4 : MaxTotAirVolFlowDes = 0.0;
803 4 : MaxTotAirVolFlowUser = 0.0;
804 4 : MaxVolHotWaterFlowDes = 0.0;
805 4 : MaxVolHotWaterFlowUser = 0.0;
806 4 : MaxVolColdWaterFlowDes = 0.0;
807 4 : MaxVolColdWaterFlowUser = 0.0;
808 :
809 4 : auto &TermUnitSizing(state.dataSize->TermUnitSizing);
810 :
811 4 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow == AutoSize) {
812 4 : IsAutoSize = true;
813 : }
814 :
815 4 : if (state.dataSize->CurZoneEqNum > 0) {
816 4 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
817 0 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow > 0.0) {
818 0 : BaseSizer::reportSizerOutput(state,
819 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
820 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
821 : "User-Specified Maximum Total Air Flow Rate [m3/s]",
822 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow);
823 : }
824 : } else {
825 4 : CheckZoneSizing(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
826 4 : if (state.dataSize->CurTermUnitSizingNum > 0) {
827 4 : MaxTotAirVolFlowDes = max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlow,
828 4 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow);
829 : } else {
830 0 : MaxTotAirVolFlowDes = 0.0;
831 : }
832 4 : if (MaxTotAirVolFlowDes < SmallAirVolFlow) {
833 0 : MaxTotAirVolFlowDes = 0.0;
834 : }
835 4 : if (IsAutoSize) {
836 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow = MaxTotAirVolFlowDes;
837 12 : BaseSizer::reportSizerOutput(state,
838 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
839 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
840 : "Design Size Maximum Total Air Flow Rate [m3/s]",
841 4 : MaxTotAirVolFlowDes);
842 : } else {
843 0 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow > 0.0 && MaxTotAirVolFlowDes > 0.0) {
844 0 : MaxTotAirVolFlowUser = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow;
845 0 : BaseSizer::reportSizerOutput(state,
846 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
847 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
848 : "Design Size Maximum Total Air Flow Rate [m3/s]",
849 : MaxTotAirVolFlowDes,
850 : "User-Specified Maximum Total Air Flow Rate [m3/s]",
851 0 : MaxTotAirVolFlowUser);
852 0 : if (state.dataGlobal->DisplayExtraWarnings) {
853 0 : if ((std::abs(MaxTotAirVolFlowDes - MaxTotAirVolFlowUser) / MaxTotAirVolFlowUser) >
854 0 : state.dataSize->AutoVsHardSizingThreshold) {
855 0 : ShowMessage(state,
856 0 : "SizeHVACSingleDuctInduction: Potential issue with equipment sizing for " +
857 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + " = \"" +
858 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "\".");
859 0 : ShowContinueError(state, format("User-Specified Maximum Total Air Flow Rate of {:.5R} [m3/s]", MaxTotAirVolFlowUser));
860 0 : ShowContinueError(
861 0 : state, format("differs from Design Size Maximum Total Air Flow Rate of {:.5R} [m3/s]", MaxTotAirVolFlowDes));
862 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
863 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
864 : }
865 : }
866 : }
867 : }
868 : }
869 : }
870 :
871 4 : IsAutoSize = false;
872 4 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow == AutoSize) {
873 4 : IsAutoSize = true;
874 : }
875 4 : if ((state.dataSize->CurZoneEqNum > 0) && (state.dataSize->CurTermUnitSizingNum > 0)) {
876 4 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
877 0 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow > 0.0) {
878 0 : BaseSizer::reportSizerOutput(state,
879 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
880 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
881 : "User-Specified Maximum Hot Water Flow Rate [m3/s]",
882 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow);
883 : }
884 : } else {
885 4 : CheckZoneSizing(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
886 :
887 4 : if (UtilityRoutines::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType, "Coil:Heating:Water")) {
888 :
889 4 : CoilWaterInletNode =
890 8 : GetCoilWaterInletNode(state, "Coil:Heating:Water", state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil, ErrorsFound);
891 4 : CoilWaterOutletNode =
892 8 : GetCoilWaterOutletNode(state, "Coil:Heating:Water", state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil, ErrorsFound);
893 4 : if (IsAutoSize) {
894 8 : PltSizHeatNum = MyPlantSizingIndex(state,
895 : "Coil:Heating:Water",
896 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil,
897 : CoilWaterInletNode,
898 : CoilWaterOutletNode,
899 : ErrorsFound);
900 4 : if (PltSizHeatNum > 0) {
901 :
902 4 : if (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatMassFlow >= SmallAirVolFlow) {
903 8 : DesPriVolFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow /
904 4 : (1.0 + state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio);
905 4 : CpAir = PsyCpAirFnW(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).HeatDesHumRat);
906 : // the design heating coil load is the zone load minus whatever the central system does. Note that
907 : // DesHeatCoilInTempTU is really the primary air inlet temperature for the unit.
908 4 : if (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtHeatPeak > 0.0) {
909 4 : DesCoilLoad =
910 4 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesHeatLoad -
911 8 : CpAir * RhoAir * DesPriVolFlow *
912 8 : (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU -
913 4 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtHeatPeak);
914 : } else {
915 0 : DesCoilLoad = CpAir * RhoAir * DesPriVolFlow *
916 0 : (state.dataSize->ZoneSizThermSetPtLo(state.dataSize->CurZoneEqNum) -
917 0 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU);
918 : }
919 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).DesHeatingLoad = DesCoilLoad;
920 8 : Cp = GetSpecificHeatGlycol(
921 : state,
922 4 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc.loopNum).FluidName,
923 : DataGlobalConstants::HWInitConvTemp,
924 4 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc.loopNum).FluidIndex,
925 : RoutineName);
926 :
927 8 : rho = GetDensityGlycol(
928 : state,
929 4 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc.loopNum).FluidName,
930 : DataGlobalConstants::HWInitConvTemp,
931 4 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc.loopNum).FluidIndex,
932 : RoutineName);
933 :
934 4 : MaxVolHotWaterFlowDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
935 4 : MaxVolHotWaterFlowDes = max(MaxVolHotWaterFlowDes, 0.0);
936 : } else {
937 0 : MaxVolHotWaterFlowDes = 0.0;
938 : }
939 : } else {
940 0 : ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
941 0 : ShowContinueError(state,
942 0 : "Occurs in" + state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType +
943 0 : " Object=" + state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
944 0 : ErrorsFound = true;
945 : }
946 : }
947 4 : if (IsAutoSize) {
948 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow = MaxVolHotWaterFlowDes;
949 12 : BaseSizer::reportSizerOutput(state,
950 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
951 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
952 : "Design Size Maximum Hot Water Flow Rate [m3/s]",
953 4 : MaxVolHotWaterFlowDes);
954 16 : BaseSizer::reportSizerOutput(
955 : state,
956 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
957 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
958 : "Design Size Inlet Air Temperature [C]",
959 8 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU);
960 16 : BaseSizer::reportSizerOutput(
961 : state,
962 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
963 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
964 : "Design Size Inlet Air Humidity Ratio [kgWater/kgDryAir]",
965 8 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInHumRatTU);
966 : } else {
967 0 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow > 0.0 && MaxVolHotWaterFlowDes > 0.0) {
968 0 : MaxVolHotWaterFlowUser = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow;
969 0 : BaseSizer::reportSizerOutput(state,
970 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
971 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
972 : "Design Size Maximum Hot Water Flow Rate [m3/s]",
973 : MaxVolHotWaterFlowDes,
974 : "User-Specified Maximum Hot Water Flow Rate [m3/s]",
975 0 : MaxVolHotWaterFlowUser);
976 0 : if (state.dataGlobal->DisplayExtraWarnings) {
977 0 : if ((std::abs(MaxVolHotWaterFlowDes - MaxVolHotWaterFlowUser) / MaxVolHotWaterFlowUser) >
978 0 : state.dataSize->AutoVsHardSizingThreshold) {
979 0 : ShowMessage(state,
980 0 : "SizeHVACSingleDuctInduction: Potential issue with equipment sizing for " +
981 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + " = \"" +
982 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "\".");
983 0 : ShowContinueError(state,
984 0 : format("User-Specified Maximum Hot Water Flow Rate of {:.5R} [m3/s]", MaxVolHotWaterFlowUser));
985 0 : ShowContinueError(
986 : state,
987 0 : format("differs from Design Size Maximum Hot Water Flow Rate of {:.5R} [m3/s]", MaxVolHotWaterFlowDes));
988 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
989 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
990 : }
991 : }
992 : }
993 : }
994 : } else {
995 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow = 0.0;
996 : }
997 : }
998 : }
999 :
1000 4 : IsAutoSize = false;
1001 4 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow == AutoSize) {
1002 4 : IsAutoSize = true;
1003 : }
1004 4 : if ((state.dataSize->CurZoneEqNum > 0) && (state.dataSize->CurTermUnitSizingNum > 0)) {
1005 4 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
1006 0 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow > 0.0) {
1007 0 : BaseSizer::reportSizerOutput(state,
1008 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
1009 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
1010 : "User-Specified Maximum Cold Water Flow Rate [m3/s]",
1011 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow);
1012 : }
1013 : } else {
1014 4 : CheckZoneSizing(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
1015 :
1016 8 : if (UtilityRoutines::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, "Coil:Cooling:Water") ||
1017 4 : UtilityRoutines::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, "Coil:Cooling:Water:DetailedGeometry")) {
1018 :
1019 8 : CoilWaterInletNode = GetCoilWaterInletNode(state,
1020 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType,
1021 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
1022 : ErrorsFound);
1023 8 : CoilWaterOutletNode = GetCoilWaterOutletNode(state,
1024 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType,
1025 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
1026 : ErrorsFound);
1027 4 : if (IsAutoSize) {
1028 12 : PltSizCoolNum = MyPlantSizingIndex(state,
1029 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType,
1030 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
1031 : CoilWaterInletNode,
1032 : CoilWaterOutletNode,
1033 : ErrorsFound);
1034 4 : if (PltSizCoolNum > 0) {
1035 :
1036 4 : if (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolMassFlow >= SmallAirVolFlow) {
1037 8 : DesPriVolFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow /
1038 4 : (1.0 + state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio);
1039 4 : CpAir = PsyCpAirFnW(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).CoolDesHumRat);
1040 : // the design cooling coil load is the zone load minus whatever the central system does. Note that
1041 : // DesCoolCoilInTempTU is really the primary air inlet temperature for the unit.
1042 4 : if (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtCoolPeak > 0.0) {
1043 4 : DesCoilLoad =
1044 4 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).NonAirSysDesCoolLoad -
1045 8 : CpAir * RhoAir * DesPriVolFlow *
1046 8 : (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtCoolPeak -
1047 4 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolCoilInTempTU);
1048 : } else {
1049 0 : DesCoilLoad = CpAir * RhoAir * DesPriVolFlow *
1050 0 : (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolCoilInTempTU -
1051 0 : state.dataSize->ZoneSizThermSetPtHi(state.dataSize->CurZoneEqNum));
1052 : }
1053 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).DesCoolingLoad = DesCoilLoad;
1054 8 : Cp = GetSpecificHeatGlycol(
1055 : state,
1056 4 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc.loopNum).FluidName,
1057 : 5.0,
1058 4 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc.loopNum).FluidIndex,
1059 : RoutineName);
1060 :
1061 8 : rho = GetDensityGlycol(
1062 : state,
1063 4 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc.loopNum).FluidName,
1064 : 5.0,
1065 4 : state.dataPlnt->PlantLoop(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc.loopNum).FluidIndex,
1066 : RoutineName);
1067 :
1068 4 : MaxVolColdWaterFlowDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizCoolNum).DeltaT * Cp * rho);
1069 4 : MaxVolColdWaterFlowDes = max(MaxVolColdWaterFlowDes, 0.0);
1070 : } else {
1071 0 : MaxVolColdWaterFlowDes = 0.0;
1072 : }
1073 : } else {
1074 0 : ShowSevereError(state, "Autosizing of water flow requires a cooling loop Sizing:Plant object");
1075 0 : ShowContinueError(state,
1076 0 : "Occurs in" + state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType +
1077 0 : " Object=" + state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name);
1078 0 : ErrorsFound = true;
1079 : }
1080 : }
1081 4 : if (IsAutoSize) {
1082 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow = MaxVolColdWaterFlowDes;
1083 12 : BaseSizer::reportSizerOutput(state,
1084 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
1085 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
1086 : "Design Size Maximum Cold Water Flow Rate [m3/s]",
1087 4 : MaxVolColdWaterFlowDes);
1088 : } else {
1089 0 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow > 0.0 && MaxVolColdWaterFlowDes > 0.0) {
1090 0 : MaxVolColdWaterFlowUser = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow;
1091 0 : BaseSizer::reportSizerOutput(state,
1092 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
1093 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name,
1094 : "Design Size Maximum Cold Water Flow Rate [m3/s]",
1095 : MaxVolColdWaterFlowDes,
1096 : "User-Specified Maximum Cold Water Flow Rate [m3/s]",
1097 0 : MaxVolColdWaterFlowUser);
1098 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1099 0 : if ((std::abs(MaxVolColdWaterFlowDes - MaxVolColdWaterFlowUser) / MaxVolColdWaterFlowUser) >
1100 0 : state.dataSize->AutoVsHardSizingThreshold) {
1101 0 : ShowMessage(state,
1102 0 : "SizeHVACSingleDuctInduction: Potential issue with equipment sizing for " +
1103 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + " = \"" +
1104 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "\".");
1105 0 : ShowContinueError(
1106 0 : state, format("User-Specified Maximum Cold Water Flow Rate of {:.5R} [m3/s]", MaxVolColdWaterFlowUser));
1107 0 : ShowContinueError(
1108 : state,
1109 0 : format("differs from Design Size Maximum Cold Water Flow Rate of {:.5R} [m3/s]", MaxVolColdWaterFlowDes));
1110 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1111 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1112 : }
1113 : }
1114 : }
1115 : }
1116 : } else {
1117 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow = 0.0;
1118 : }
1119 : }
1120 : }
1121 :
1122 4 : if (state.dataSize->CurTermUnitSizingNum > 0) {
1123 : // note we save the induced air flow for use by the hw and cw coil sizing routines
1124 12 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirVolFlow *
1125 8 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio /
1126 4 : (1.0 + state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio);
1127 : // save the max hot and cold water flows for use in coil sizing
1128 4 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).MaxHWVolFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolHotWaterFlow;
1129 4 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).MaxCWVolFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxVolColdWaterFlow;
1130 : // save the design load used for reporting
1131 4 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).DesCoolingLoad = state.dataHVACSingleDuctInduc->IndUnit(IUNum).DesCoolingLoad;
1132 4 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).DesHeatingLoad = state.dataHVACSingleDuctInduc->IndUnit(IUNum).DesHeatingLoad;
1133 : // save the induction ratio for use in subsequent sizing calcs
1134 4 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).InducRat = state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio;
1135 4 : if (UtilityRoutines::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType, "Coil:Heating:Water")) {
1136 12 : SetCoilDesFlow(state,
1137 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoilType,
1138 4 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil,
1139 4 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow,
1140 : ErrorsFound);
1141 : }
1142 4 : if (UtilityRoutines::SameString(state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType, "Coil:Cooling:Water:DetailedGeometry")) {
1143 0 : SetCoilDesFlow(state,
1144 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoilType,
1145 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil,
1146 0 : TermUnitSizing(state.dataSize->CurTermUnitSizingNum).AirVolFlow,
1147 : ErrorsFound);
1148 : }
1149 : }
1150 4 : }
1151 :
1152 12104 : void SimFourPipeIndUnit(EnergyPlusData &state,
1153 : int const IUNum, // number of the current unit being simulated
1154 : int const ZoneNum, // number of zone being served
1155 : int const ZoneNodeNum, // zone node number
1156 : bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep
1157 : )
1158 : {
1159 :
1160 : // SUBROUTINE INFORMATION:
1161 : // AUTHOR Fred Buhl
1162 : // DATE WRITTEN June 23 2004
1163 : // MODIFIED na
1164 : // RE-ENGINEERED na
1165 :
1166 : // PURPOSE OF THIS SUBROUTINE:
1167 : // Simulate a 4 pipe induction unit; adjust its heating or cooling
1168 : // coil outputs to match the zone load.
1169 :
1170 : // METHODOLOGY EMPLOYED:
1171 : // (1) From the zone load and the primary air inlet conditions calculate the coil load
1172 : // in the secondary air stream
1173 : // (2) If there is a cooling coil load, set the heating coil off and control the cooling
1174 : // coil to meet the coil load
1175 : // (3) If there is a heating coil load, control the heating coil to meet the load and keep
1176 : // the cooling coil off.
1177 :
1178 : // Using/Aliasing
1179 : using namespace DataZoneEnergyDemands;
1180 :
1181 : using General::SolveRoot;
1182 : using PlantUtilities::SetComponentFlowRate;
1183 :
1184 : // SUBROUTINE PARAMETER DEFINITIONS:
1185 12104 : int constexpr SolveMaxIter(50);
1186 :
1187 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1188 : Real64 QZnReq; // heating or cooling needed by zone [Watts]
1189 : Real64 QToHeatSetPt; // [W] remaining load to heating setpoint
1190 : Real64 QToCoolSetPt; // [W] remaining load to cooling setpoint
1191 : Real64 PowerMet; // power supplied
1192 : bool UnitOn; // TRUE if unit is on
1193 : Real64 MaxHotWaterFlow; // maximum water flow for heating [kg/s]
1194 : Real64 MinHotWaterFlow; // minimum water flow for heating [kg/s]
1195 : Real64 MaxColdWaterFlow; // maximum water flow for cooling [kg/s]
1196 : Real64 MinColdWaterFlow; // minimum water flow for cooling [kg/s]
1197 : Real64 HWFlow; // hot water flow [kg/s]
1198 : Real64 CWFlow; // cold water flow [kg/s]
1199 : int PriNode; // unit primary air inlet node
1200 : int SecNode; // unit secondary air inlet node
1201 : int OutletNode; // unit air outlet node
1202 : int HotControlNode; // hot water coil inlet node
1203 : int ColdControlNode; // cold water coil inlet node
1204 : Real64 QPriOnly; // unit output with no zone coils active
1205 : Real64 PriAirMassFlow; // primary air mass flow rate [kg/s]
1206 : Real64 SecAirMassFlow; // secondary air mass flow rate [kg/s]
1207 : Real64 InducRat; // Induction Ratio
1208 : int SolFlag;
1209 : Real64 ErrTolerance;
1210 : int HWOutletNode;
1211 : int CWOutletNode;
1212 12104 : UnitOn = true;
1213 12104 : PowerMet = 0.0;
1214 12104 : InducRat = state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio;
1215 12104 : PriNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode;
1216 12104 : SecNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).SecAirInNode;
1217 12104 : OutletNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode;
1218 12104 : HotControlNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWControlNode;
1219 12104 : HWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc).NodeNumOut;
1220 12104 : ColdControlNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWControlNode;
1221 12104 : CWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc).NodeNumOut;
1222 12104 : PriAirMassFlow = state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail;
1223 12104 : SecAirMassFlow = InducRat * PriAirMassFlow;
1224 12104 : QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired;
1225 12104 : QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP;
1226 12104 : QToCoolSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToCoolSP;
1227 : // On the first HVAC iteration the system values are given to the controller, but after that
1228 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
1229 :
1230 12104 : MaxHotWaterFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxHotWaterFlow;
1231 12104 : SetComponentFlowRate(state, MaxHotWaterFlow, HotControlNode, HWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc);
1232 :
1233 12104 : MinHotWaterFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinHotWaterFlow;
1234 12104 : SetComponentFlowRate(state, MinHotWaterFlow, HotControlNode, HWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc);
1235 :
1236 12104 : MaxColdWaterFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxColdWaterFlow;
1237 12104 : SetComponentFlowRate(state, MaxColdWaterFlow, ColdControlNode, CWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc);
1238 :
1239 12104 : MinColdWaterFlow = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MinColdWaterFlow;
1240 12104 : SetComponentFlowRate(state, MinColdWaterFlow, ColdControlNode, CWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc);
1241 :
1242 12104 : if (GetCurrentScheduleValue(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).SchedPtr) <= 0.0) UnitOn = false;
1243 12104 : if (PriAirMassFlow <= SmallMassFlow) UnitOn = false;
1244 :
1245 : // Set the unit's air inlet nodes mass flow rates
1246 12104 : state.dataLoopNodes->Node(PriNode).MassFlowRate = PriAirMassFlow;
1247 12104 : state.dataLoopNodes->Node(SecNode).MassFlowRate = SecAirMassFlow;
1248 : // initialize the water inlet nodes to minimum
1249 : // fire the unit at min water flow
1250 12104 : CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, MinColdWaterFlow, QPriOnly);
1251 : // the load to be met by the secondary air stream coils is QZnReq-PowerMet
1252 :
1253 12104 : if (UnitOn) {
1254 :
1255 12056 : if (QToHeatSetPt - QPriOnly > SmallLoad) {
1256 : // heating coil
1257 : // check that it can meet the load
1258 10226 : CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MaxHotWaterFlow, MinColdWaterFlow, PowerMet);
1259 10226 : if (PowerMet > QToHeatSetPt + SmallLoad) {
1260 10222 : ErrTolerance = state.dataHVACSingleDuctInduc->IndUnit(IUNum).HotControlOffset;
1261 : auto f =
1262 394012 : [&state, IUNum, FirstHVACIteration, ZoneNodeNum, MinColdWaterFlow, QToHeatSetPt, QPriOnly, PowerMet](Real64 const HWFlow) {
1263 : Real64 UnitOutput;
1264 197006 : CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, HWFlow, MinColdWaterFlow, UnitOutput);
1265 197006 : return (QToHeatSetPt - UnitOutput) / (PowerMet - QPriOnly);
1266 10222 : };
1267 10222 : SolveRoot(state, ErrTolerance, SolveMaxIter, SolFlag, HWFlow, f, MinHotWaterFlow, MaxHotWaterFlow);
1268 10222 : if (SolFlag == -1) {
1269 0 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWCoilFailNum1 == 0) {
1270 0 : ShowWarningMessage(state,
1271 0 : "SimFourPipeIndUnit: Hot water coil control failed for " +
1272 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + "=\"" +
1273 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "\"");
1274 0 : ShowContinueErrorTimeStamp(state, "");
1275 0 : ShowContinueError(state, format(" Iteration limit [{}] exceeded in calculating hot water mass flow rate", SolveMaxIter));
1276 : }
1277 0 : ShowRecurringWarningErrorAtEnd(
1278 : state,
1279 0 : format("SimFourPipeIndUnit: Hot water coil control failed (iteration limit [{}]) for {}=\"{}\"",
1280 : SolveMaxIter,
1281 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
1282 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name),
1283 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWCoilFailNum1);
1284 10222 : } else if (SolFlag == -2) {
1285 0 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWCoilFailNum2 == 0) {
1286 0 : ShowWarningMessage(state,
1287 0 : "SimFourPipeIndUnit: Hot water coil control failed (maximum flow limits) for " +
1288 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + "=\"" +
1289 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "\"");
1290 0 : ShowContinueErrorTimeStamp(state, "");
1291 0 : ShowContinueError(state, "...Bad hot water maximum flow rate limits");
1292 0 : ShowContinueError(state, format("...Given minimum water flow rate={:.3R} kg/s", MinHotWaterFlow));
1293 0 : ShowContinueError(state, format("...Given maximum water flow rate={:.3R} kg/s", MaxHotWaterFlow));
1294 : }
1295 0 : ShowRecurringWarningErrorAtEnd(state,
1296 0 : "SimFourPipeIndUnit: Hot water coil control failed (flow limits) for " +
1297 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + "=\"" +
1298 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "\"",
1299 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWCoilFailNum2,
1300 : MaxHotWaterFlow,
1301 : MinHotWaterFlow,
1302 : _,
1303 : "[kg/s]",
1304 : "[kg/s]");
1305 : }
1306 : }
1307 1830 : } else if (QToCoolSetPt - QPriOnly < -SmallLoad) {
1308 : // cooling coil
1309 : // check that it can meet the load
1310 1802 : CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, MaxColdWaterFlow, PowerMet);
1311 1802 : if (PowerMet < QToCoolSetPt - SmallLoad) {
1312 1712 : ErrTolerance = state.dataHVACSingleDuctInduc->IndUnit(IUNum).ColdControlOffset;
1313 : auto f =
1314 37252 : [&state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, QToCoolSetPt, QPriOnly, PowerMet](Real64 const CWFlow) {
1315 : Real64 UnitOutput;
1316 18626 : CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, CWFlow, UnitOutput);
1317 18626 : return (QToCoolSetPt - UnitOutput) / (PowerMet - QPriOnly);
1318 1712 : };
1319 1712 : SolveRoot(state, ErrTolerance, SolveMaxIter, SolFlag, CWFlow, f, MinColdWaterFlow, MaxColdWaterFlow);
1320 1712 : if (SolFlag == -1) {
1321 0 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWCoilFailNum1 == 0) {
1322 0 : ShowWarningMessage(state,
1323 0 : "SimFourPipeIndUnit: Cold water coil control failed for " +
1324 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + "=\"" +
1325 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "\"");
1326 0 : ShowContinueErrorTimeStamp(state, "");
1327 0 : ShowContinueError(state,
1328 0 : format(" Iteration limit [{}] exceeded in calculating cold water mass flow rate", SolveMaxIter));
1329 : }
1330 0 : ShowRecurringWarningErrorAtEnd(state,
1331 0 : format("SimFourPipeIndUnit: Cold water coil control failed (iteration limit [{}]) for {}=\"{}",
1332 : SolveMaxIter,
1333 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType,
1334 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name),
1335 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWCoilFailNum1);
1336 1712 : } else if (SolFlag == -2) {
1337 0 : if (state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWCoilFailNum2 == 0) {
1338 0 : ShowWarningMessage(state,
1339 0 : "SimFourPipeIndUnit: Cold water coil control failed (maximum flow limits) for " +
1340 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + "=\"" +
1341 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "\"");
1342 0 : ShowContinueErrorTimeStamp(state, "");
1343 0 : ShowContinueError(state, "...Bad cold water maximum flow rate limits");
1344 0 : ShowContinueError(state, format("...Given minimum water flow rate={:.3R} kg/s", MinColdWaterFlow));
1345 0 : ShowContinueError(state, format("...Given maximum water flow rate={:.3R} kg/s", MaxColdWaterFlow));
1346 : }
1347 0 : ShowRecurringWarningErrorAtEnd(state,
1348 0 : "SimFourPipeIndUnit: Cold water coil control failed (flow limits) for " +
1349 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).UnitType + "=\"" +
1350 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).Name + "\"",
1351 0 : state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWCoilFailNum2,
1352 : MaxColdWaterFlow,
1353 : MinColdWaterFlow,
1354 : _,
1355 : "[kg/s]",
1356 : "[kg/s]");
1357 : }
1358 : }
1359 : } else {
1360 28 : CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, MinColdWaterFlow, PowerMet);
1361 : }
1362 :
1363 : } else {
1364 : // unit off
1365 48 : CalcFourPipeIndUnit(state, IUNum, FirstHVACIteration, ZoneNodeNum, MinHotWaterFlow, MinColdWaterFlow, PowerMet);
1366 : }
1367 12104 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMax = state.dataHVACSingleDuctInduc->IndUnit(IUNum).MaxTotAirMassFlow;
1368 :
1369 : // At this point we are done. There is no output to report or pass back up: the output provided is calculated
1370 : // one level up in the calling routine SimZoneAirLoopEquipment. All the inlet and outlet flow rates and
1371 : // conditions have been set by CalcFourPipeIndUnit either explicitly or as a result of the simple component calls.
1372 12104 : }
1373 :
1374 132024 : void CalcFourPipeIndUnit(EnergyPlusData &state,
1375 : int const IUNum, // Unit index
1376 : bool const FirstHVACIteration, // flag for 1st HVAV iteration in the time step
1377 : int const ZoneNode, // zone node number
1378 : Real64 const HWFlow, // hot water flow (kg/s)
1379 : Real64 const CWFlow, // cold water flow (kg/s)
1380 : Real64 &LoadMet // load met by unit (watts)
1381 : )
1382 : {
1383 :
1384 : // SUBROUTINE INFORMATION:
1385 : // AUTHOR Fred Buhl
1386 : // DATE WRITTEN June 2004
1387 : // MODIFIED na
1388 : // RE-ENGINEERED na
1389 :
1390 : // PURPOSE OF THIS SUBROUTINE:
1391 : // Simulate the components making up the 4 pipe induction unit.
1392 :
1393 : // METHODOLOGY EMPLOYED:
1394 : // Simulates the unit components sequentially in the air flow direction.
1395 :
1396 : // REFERENCES:
1397 : // na
1398 :
1399 : // Using/Aliasing
1400 : using MixerComponent::SimAirMixer;
1401 : using PlantUtilities::SetComponentFlowRate;
1402 : using WaterCoils::SimulateWaterCoilComponents;
1403 :
1404 : // Locals
1405 : // SUBROUTINE ARGUMENT DEFINITIONS:
1406 :
1407 : // SUBROUTINE PARAMETER DEFINITIONS:
1408 : // na
1409 :
1410 : // INTERFACE BLOCK SPECIFICATIONS
1411 : // na
1412 :
1413 : // DERIVED TYPE DEFINITIONS
1414 : // na
1415 :
1416 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1417 : int OutletNode; // unit air outlet node
1418 : int PriNode; // unit primary air inlet node
1419 : int HotControlNode; // the hot water inlet node
1420 : int ColdControlNode; // the cold water inlet node
1421 : Real64 PriAirMassFlow; // primary air mass flow rate [kg/s]
1422 : Real64 SecAirMassFlow; // secondary air mass flow rate [kg/s]
1423 : Real64 TotAirMassFlow; // total air mass flow rate [kg/s]
1424 : Real64 InducRat; // induction ratio
1425 : Real64 mdotHW; // local temporary hot water flow rate [kg/s]
1426 : Real64 mdotCW; // local temporary cold water flow rate [kg/s]
1427 : int HWOutletNode;
1428 : int CWOutletNode;
1429 :
1430 132024 : PriNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).PriAirInNode;
1431 132024 : OutletNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).OutAirNode;
1432 132024 : PriAirMassFlow = state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail;
1433 132024 : InducRat = state.dataHVACSingleDuctInduc->IndUnit(IUNum).InducRatio;
1434 132024 : SecAirMassFlow = InducRat * PriAirMassFlow;
1435 132024 : TotAirMassFlow = PriAirMassFlow + SecAirMassFlow;
1436 132024 : HotControlNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWControlNode;
1437 132024 : HWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc).NodeNumOut;
1438 :
1439 132024 : ColdControlNode = state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWControlNode;
1440 132024 : CWOutletNode = DataPlant::CompData::getPlantComponent(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc).NodeNumOut;
1441 :
1442 132024 : mdotHW = HWFlow;
1443 132024 : SetComponentFlowRate(state, mdotHW, HotControlNode, HWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HWPlantLoc);
1444 :
1445 : // Node(HotControlNode)%MassFlowRate = HWFlow
1446 :
1447 132024 : mdotCW = CWFlow;
1448 132024 : SetComponentFlowRate(state, mdotCW, ColdControlNode, CWOutletNode, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CWPlantLoc);
1449 : // Node(ColdControlNode)%MassFlowRate = CWFlow
1450 :
1451 396072 : SimulateWaterCoilComponents(
1452 264048 : state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil, FirstHVACIteration, state.dataHVACSingleDuctInduc->IndUnit(IUNum).HCoil_Num);
1453 396072 : SimulateWaterCoilComponents(
1454 264048 : state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil, FirstHVACIteration, state.dataHVACSingleDuctInduc->IndUnit(IUNum).CCoil_Num);
1455 132024 : SimAirMixer(state, state.dataHVACSingleDuctInduc->IndUnit(IUNum).MixerName, state.dataHVACSingleDuctInduc->IndUnit(IUNum).Mixer_Num);
1456 396072 : LoadMet = TotAirMassFlow * Psychrometrics::PsyDeltaHSenFnTdb2W2Tdb1W1(state.dataLoopNodes->Node(OutletNode).Temp,
1457 132024 : state.dataLoopNodes->Node(OutletNode).HumRat,
1458 132024 : state.dataLoopNodes->Node(ZoneNode).Temp,
1459 132024 : state.dataLoopNodes->Node(ZoneNode).HumRat);
1460 132024 : }
1461 :
1462 6 : bool FourPipeInductionUnitHasMixer(EnergyPlusData &state, std::string_view CompName) // component (mixer) name
1463 : {
1464 :
1465 : // FUNCTION INFORMATION:
1466 : // AUTHOR Linda Lawrie
1467 : // DATE WRITTEN September 2011
1468 : // MODIFIED na
1469 : // RE-ENGINEERED na
1470 :
1471 : // PURPOSE OF THIS FUNCTION:
1472 : // Given a mixer name, this routine determines if that mixer is found on
1473 : // PIUnits.
1474 :
1475 : // Return value
1476 : bool YesNo; // True if found
1477 :
1478 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
1479 : int ItemNum;
1480 :
1481 6 : auto &GetIUInputFlag = state.dataHVACSingleDuctInduc->GetIUInputFlag;
1482 :
1483 6 : if (GetIUInputFlag) {
1484 1 : GetIndUnits(state);
1485 1 : GetIUInputFlag = false;
1486 : }
1487 :
1488 6 : YesNo = false;
1489 6 : if (state.dataHVACSingleDuctInduc->NumIndUnits > 0) {
1490 4 : ItemNum = UtilityRoutines::FindItemInList(CompName, state.dataHVACSingleDuctInduc->IndUnit, &IndUnitData::MixerName);
1491 4 : if (ItemNum > 0) YesNo = true;
1492 : }
1493 :
1494 6 : return YesNo;
1495 : }
1496 :
1497 12104 : void IndUnitData::ReportIndUnit(EnergyPlusData &state)
1498 : {
1499 : // Purpose: this subroutine for reporting
1500 :
1501 : // set zone OA volume flow rate
1502 12104 : this->CalcOutdoorAirVolumeFlowRate(state);
1503 12104 : }
1504 :
1505 12104 : void IndUnitData::CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state)
1506 : {
1507 : // calculates zone outdoor air volume flow rate using the supply air flow rate and OA fraction
1508 12104 : if (this->AirLoopNum > 0) {
1509 24200 : this->OutdoorAirFlowRate = (state.dataLoopNodes->Node(this->PriAirInNode).MassFlowRate / state.dataEnvrn->StdRhoAir) *
1510 12100 : state.dataAirLoop->AirLoopFlow(this->AirLoopNum).OAFrac;
1511 : } else {
1512 4 : this->OutdoorAirFlowRate = 0.0;
1513 : }
1514 12104 : }
1515 :
1516 : } // namespace HVACSingleDuctInduc
1517 :
1518 2313 : } // namespace EnergyPlus
|