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/DataHeatBalFanSys.hh>
63 : #include <EnergyPlus/DataIPShortCuts.hh>
64 : #include <EnergyPlus/DataLoopNode.hh>
65 : #include <EnergyPlus/DataPrecisionGlobals.hh>
66 : #include <EnergyPlus/DataSizing.hh>
67 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
68 : #include <EnergyPlus/DataZoneEquipment.hh>
69 : #include <EnergyPlus/Fans.hh>
70 : #include <EnergyPlus/FluidProperties.hh>
71 : #include <EnergyPlus/General.hh>
72 : #include <EnergyPlus/GeneralRoutines.hh>
73 : #include <EnergyPlus/GlobalNames.hh>
74 : #include <EnergyPlus/HVACFan.hh>
75 : #include <EnergyPlus/HeatingCoils.hh>
76 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
77 : #include <EnergyPlus/MixerComponent.hh>
78 : #include <EnergyPlus/NodeInputManager.hh>
79 : #include <EnergyPlus/OutputProcessor.hh>
80 : #include <EnergyPlus/Plant/DataPlant.hh>
81 : #include <EnergyPlus/PlantUtilities.hh>
82 : #include <EnergyPlus/PoweredInductionUnits.hh>
83 : #include <EnergyPlus/Psychrometrics.hh>
84 : #include <EnergyPlus/ScheduleManager.hh>
85 : #include <EnergyPlus/SteamCoils.hh>
86 : #include <EnergyPlus/UtilityRoutines.hh>
87 : #include <EnergyPlus/WaterCoils.hh>
88 :
89 : namespace EnergyPlus::PoweredInductionUnits {
90 :
91 : // Module containing routines dealing with Series and Parallel fan powered terminal boxes
92 :
93 : // MODULE INFORMATION:
94 : // AUTHOR Fred Buhl
95 : // DATE WRITTEN August 2000
96 : // MODIFIED Brent Griffith, Sept 2010, plant upgrades, fluid properties
97 : // RE-ENGINEERED na
98 :
99 : // PURPOSE OF THIS MODULE:
100 : // To encapsulate the data and algorithms needed to simulate Series and Parallel
101 : // fan powered induction terminal boxes.
102 :
103 : // METHODOLOGY EMPLOYED:
104 : // The terminal boxes are modeled as a collection of components: air mixer,
105 : // fan, and heating coil plus an integrated control
106 : // algorithm that adjusts the primary air flow and the heating coil output
107 : // to meet the zone load.
108 :
109 : // Using/Aliasing
110 : using namespace DataLoopNode;
111 : using DataHVACGlobals::SmallAirVolFlow;
112 : using DataHVACGlobals::SmallLoad;
113 : using DataHVACGlobals::SmallMassFlow;
114 : using DataHVACGlobals::SmallTempDiff;
115 : using namespace ScheduleManager;
116 : using Psychrometrics::PsyCpAirFnW;
117 : using Psychrometrics::PsyHFnTdbW;
118 : using Psychrometrics::PsyRhoAirFnPbTdbW;
119 : using SteamCoils::SimulateSteamCoilComponents;
120 : using namespace FluidProperties;
121 :
122 : constexpr const char *fluidNameSteam("STEAM");
123 : constexpr const char *fluidNameWater("WATER");
124 :
125 120828 : void SimPIU(EnergyPlusData &state,
126 : std::string_view CompName, // name of the PIU
127 : bool const FirstHVACIteration, // TRUE if first HVAC iteration in time step
128 : int const ZoneNum, // index of zone served by PIU
129 : int const ZoneNodeNum, // zone node number of zone served by PIU
130 : int &CompIndex // PIU Index in PIU names
131 : )
132 : {
133 :
134 : // SUBROUTINE INFORMATION:
135 : // AUTHOR Fred Buhl
136 : // DATE WRITTEN March 2000
137 : // MODIFIED na
138 : // RE-ENGINEERED na
139 :
140 : // PURPOSE OF THIS SUBROUTINE:
141 : // Manages the simulation of a fan powered induction terminal unit.
142 : // Called from SimZoneAirLoopEquipmentin module ZoneAirLoopEquipmentManager.
143 :
144 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
145 : int PIUNum; // index of powered induction unit being simulated
146 :
147 : // First time SimPIU is called, get the input for all the fan coil units
148 120828 : if (state.dataPowerInductionUnits->GetPIUInputFlag) {
149 11 : GetPIUs(state);
150 11 : state.dataPowerInductionUnits->GetPIUInputFlag = false;
151 : }
152 :
153 : // Get the powered induction unit index
154 120828 : if (CompIndex == 0) {
155 34 : PIUNum = UtilityRoutines::FindItemInList(CompName, state.dataPowerInductionUnits->PIU);
156 34 : if (PIUNum == 0) {
157 0 : ShowFatalError(state, "SimPIU: PIU Unit not found=" + std::string{CompName});
158 : }
159 34 : CompIndex = PIUNum;
160 : } else {
161 120794 : PIUNum = CompIndex;
162 120794 : if (PIUNum > state.dataPowerInductionUnits->NumPIUs || PIUNum < 1) {
163 0 : ShowFatalError(state,
164 0 : format("SimPIU: Invalid CompIndex passed={}, Number of PIU Units={}, PIU Unit name={}",
165 : CompIndex,
166 0 : state.dataPowerInductionUnits->NumPIUs,
167 0 : CompName));
168 : }
169 120794 : if (state.dataPowerInductionUnits->CheckEquipName(PIUNum)) {
170 34 : if (CompName != state.dataPowerInductionUnits->PIU(PIUNum).Name) {
171 0 : ShowFatalError(state,
172 0 : format("SimPIU: Invalid CompIndex passed={}, PIU Unit name={}, stored PIU Unit Name for that index={}",
173 : CompIndex,
174 : CompName,
175 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name));
176 : }
177 34 : state.dataPowerInductionUnits->CheckEquipName(PIUNum) = false;
178 : }
179 : }
180 :
181 120828 : state.dataSize->CurTermUnitSizingNum =
182 120828 : state.dataDefineEquipment->AirDistUnit(state.dataPowerInductionUnits->PIU(PIUNum).ADUNum).TermUnitSizingNum;
183 : // initialize the unit
184 120828 : InitPIU(state, PIUNum, FirstHVACIteration);
185 :
186 120828 : state.dataSize->TermUnitPIU = true;
187 :
188 : // Select the correct unit type
189 120828 : switch (state.dataPowerInductionUnits->PIU(PIUNum).UnitType_Num) {
190 :
191 106578 : case DataDefineEquip::ZnAirLoopEquipType::SingleDuct_SeriesPIU_Reheat: { // 'AirTerminal:SingleDuct:SeriesPIU:Reheat'
192 :
193 106578 : CalcSeriesPIU(state, PIUNum, ZoneNum, ZoneNodeNum, FirstHVACIteration);
194 106578 : break;
195 : }
196 14250 : case DataDefineEquip::ZnAirLoopEquipType::SingleDuct_ParallelPIU_Reheat: { // 'AirTerminal:SingleDuct:ParallelPIU:Reheat'
197 :
198 14250 : CalcParallelPIU(state, PIUNum, ZoneNum, ZoneNodeNum, FirstHVACIteration);
199 14250 : break;
200 : }
201 0 : default:
202 0 : ShowSevereError(state, "Illegal PI Unit Type used=" + state.dataPowerInductionUnits->PIU(PIUNum).UnitType);
203 0 : ShowContinueError(state, "Occurs in PI Unit=" + state.dataPowerInductionUnits->PIU(PIUNum).Name);
204 0 : ShowFatalError(state, "Preceding condition causes termination.");
205 0 : break;
206 : }
207 :
208 120828 : state.dataSize->TermUnitPIU = false;
209 :
210 : // Update the current unit's outlet nodes
211 : // no update needed: reheat coil updates outlet node; inlet nodes' mass flow rate set by Calc routine
212 :
213 : // Fill the report variables
214 120828 : ReportPIU(state, PIUNum);
215 120828 : }
216 :
217 15 : void GetPIUs(EnergyPlusData &state)
218 : {
219 :
220 : // SUBROUTINE INFORMATION:
221 : // AUTHOR Fred Buhl
222 : // DATE WRITTEN August 2000
223 : // MODIFIED na
224 : // RE-ENGINEERED na
225 :
226 : // PURPOSE OF THIS SUBROUTINE:
227 : // Obtains input data for powered induction unit terminal boxes and stores it
228 : // in PIU data structures
229 :
230 : // METHODOLOGY EMPLOYED:
231 : // Uses "Get" routines to read in data.
232 :
233 : // Using/Aliasing
234 : using BranchNodeConnections::SetUpCompSets;
235 : using BranchNodeConnections::TestCompSet;
236 :
237 : using FluidProperties::FindRefrigerant;
238 : using NodeInputManager::GetOnlySingleNode;
239 : using SteamCoils::GetCoilSteamInletNode;
240 : using WaterCoils::GetCoilWaterInletNode;
241 :
242 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
243 : int PIUIndex; // loop index
244 : int PIUNum; // current fan coil number
245 : int NumAlphas; // Number of Alpha input fields for each GetObjectItem call
246 : int NumNumbers; // Number of Numeric input fields for each GetObjectItem call
247 : int IOStatus; // Used in GetObjectItem
248 15 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
249 : bool IsNotOK; // Flag to verify name
250 : int CtrlZone; // controlled zome do loop index
251 : int SupAirIn; // controlled zone supply air inlet index
252 : bool AirNodeFound;
253 : int ADUNum;
254 : static constexpr std::string_view RoutineName("GetPIUs: "); // include trailing blank space
255 : bool SteamMessageNeeded;
256 : int FanType_Num; // integer representation of fan type
257 :
258 : // find the number of each type of fan coil unit
259 15 : SteamMessageNeeded = true;
260 15 : state.dataPowerInductionUnits->NumSeriesPIUs =
261 30 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:SeriesPIU:Reheat");
262 15 : state.dataPowerInductionUnits->NumParallelPIUs =
263 30 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "AirTerminal:SingleDuct:ParallelPIU:Reheat");
264 15 : state.dataPowerInductionUnits->NumPIUs = state.dataPowerInductionUnits->NumSeriesPIUs + state.dataPowerInductionUnits->NumParallelPIUs;
265 : // allocate the data structures
266 15 : state.dataPowerInductionUnits->PIU.allocate(state.dataPowerInductionUnits->NumPIUs);
267 15 : state.dataPowerInductionUnits->PiuUniqueNames.reserve(static_cast<unsigned>(state.dataPowerInductionUnits->NumPIUs));
268 15 : state.dataPowerInductionUnits->CheckEquipName.dimension(state.dataPowerInductionUnits->NumPIUs, true);
269 15 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
270 : // loop over Series PIUs; get and load the input data
271 45 : for (PIUIndex = 1; PIUIndex <= state.dataPowerInductionUnits->NumSeriesPIUs; ++PIUIndex) {
272 :
273 30 : cCurrentModuleObject = "AirTerminal:SingleDuct:SeriesPIU:Reheat";
274 :
275 210 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
276 : cCurrentModuleObject,
277 : PIUIndex,
278 30 : state.dataIPShortCut->cAlphaArgs,
279 : NumAlphas,
280 30 : state.dataIPShortCut->rNumericArgs,
281 : NumNumbers,
282 : IOStatus,
283 30 : state.dataIPShortCut->lNumericFieldBlanks,
284 30 : state.dataIPShortCut->lAlphaFieldBlanks,
285 30 : state.dataIPShortCut->cAlphaFieldNames,
286 30 : state.dataIPShortCut->cNumericFieldNames);
287 :
288 30 : PIUNum = PIUIndex;
289 60 : GlobalNames::VerifyUniqueInterObjectName(state,
290 30 : state.dataPowerInductionUnits->PiuUniqueNames,
291 30 : state.dataIPShortCut->cAlphaArgs(1),
292 : cCurrentModuleObject,
293 30 : state.dataIPShortCut->cAlphaFieldNames(1),
294 : ErrorsFound);
295 30 : state.dataPowerInductionUnits->PIU(PIUNum).Name = state.dataIPShortCut->cAlphaArgs(1);
296 30 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType = cCurrentModuleObject;
297 30 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType_Num = DataDefineEquip::ZnAirLoopEquipType::SingleDuct_SeriesPIU_Reheat;
298 30 : state.dataPowerInductionUnits->PIU(PIUNum).Sched = state.dataIPShortCut->cAlphaArgs(2);
299 30 : if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
300 4 : state.dataPowerInductionUnits->PIU(PIUNum).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
301 : } else {
302 26 : state.dataPowerInductionUnits->PIU(PIUNum).SchedPtr =
303 26 : GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2)); // convert schedule name to pointer
304 26 : if (state.dataPowerInductionUnits->PIU(PIUNum).SchedPtr == 0) {
305 0 : ShowSevereError(state,
306 0 : std::string{RoutineName} + cCurrentModuleObject + ": invalid " + state.dataIPShortCut->cAlphaFieldNames(2) +
307 0 : " entered =" + state.dataIPShortCut->cAlphaArgs(2) + " for " + state.dataIPShortCut->cAlphaFieldNames(1) + '=' +
308 0 : state.dataIPShortCut->cAlphaArgs(1));
309 0 : ErrorsFound = true;
310 : }
311 : }
312 :
313 30 : state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirVolFlow = state.dataIPShortCut->rNumericArgs(1);
314 30 : state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow = state.dataIPShortCut->rNumericArgs(2);
315 30 : state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac = state.dataIPShortCut->rNumericArgs(3);
316 :
317 30 : state.dataPowerInductionUnits->PIU(PIUNum).HCoilType =
318 60 : static_cast<HtgCoilType>(getEnumerationValue(HCoilNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(9))));
319 30 : switch (state.dataPowerInductionUnits->PIU(PIUNum).HCoilType) {
320 30 : case HtgCoilType::SimpleHeating: {
321 30 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_PlantType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
322 30 : break;
323 : }
324 0 : case HtgCoilType::Electric:
325 : case HtgCoilType::Gas: {
326 0 : break;
327 : }
328 0 : case HtgCoilType::SteamAirHeating: {
329 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_PlantType = DataPlant::PlantEquipmentType::CoilSteamAirHeating;
330 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_FluidIndex = FindRefrigerant(state, "Steam");
331 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).HCoil_FluidIndex == 0) {
332 0 : ShowSevereError(state, std::string{RoutineName} + "Steam Properties for " + state.dataIPShortCut->cAlphaArgs(1) + " not found.");
333 0 : if (SteamMessageNeeded) ShowContinueError(state, "Steam Fluid Properties should have been included in the input file.");
334 0 : ErrorsFound = true;
335 0 : SteamMessageNeeded = false;
336 : }
337 0 : break;
338 : }
339 0 : default: {
340 0 : ShowSevereError(state, "Illegal " + state.dataIPShortCut->cAlphaFieldNames(9) + " = " + state.dataIPShortCut->cAlphaArgs(9));
341 0 : ShowContinueError(state, "Occurs in " + cCurrentModuleObject + " = " + state.dataPowerInductionUnits->PIU(PIUNum).Name);
342 0 : ErrorsFound = true;
343 : }
344 : }
345 :
346 30 : state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode =
347 60 : GetOnlySingleNode(state,
348 30 : state.dataIPShortCut->cAlphaArgs(3),
349 : ErrorsFound,
350 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctSeriesPIUReheat,
351 30 : state.dataIPShortCut->cAlphaArgs(1),
352 : DataLoopNode::NodeFluidType::Air,
353 : DataLoopNode::ConnectionType::Inlet,
354 : NodeInputManager::CompFluidStream::Primary,
355 : ObjectIsParent,
356 30 : state.dataIPShortCut->cAlphaFieldNames(3));
357 :
358 30 : state.dataPowerInductionUnits->PIU(PIUNum).SecAirInNode =
359 60 : GetOnlySingleNode(state,
360 30 : state.dataIPShortCut->cAlphaArgs(4),
361 : ErrorsFound,
362 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctSeriesPIUReheat,
363 30 : state.dataIPShortCut->cAlphaArgs(1),
364 : DataLoopNode::NodeFluidType::Air,
365 : DataLoopNode::ConnectionType::Inlet,
366 : NodeInputManager::CompFluidStream::Primary,
367 : ObjectIsParent,
368 30 : state.dataIPShortCut->cAlphaFieldNames(4));
369 :
370 30 : state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode =
371 60 : GetOnlySingleNode(state,
372 30 : state.dataIPShortCut->cAlphaArgs(5),
373 : ErrorsFound,
374 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctSeriesPIUReheat,
375 30 : state.dataIPShortCut->cAlphaArgs(1),
376 : DataLoopNode::NodeFluidType::Air,
377 : DataLoopNode::ConnectionType::Outlet,
378 : NodeInputManager::CompFluidStream::Primary,
379 : ObjectIsParent,
380 30 : state.dataIPShortCut->cAlphaFieldNames(5));
381 :
382 30 : state.dataPowerInductionUnits->PIU(PIUNum).HCoilInAirNode =
383 60 : GetOnlySingleNode(state,
384 30 : state.dataIPShortCut->cAlphaArgs(6),
385 : ErrorsFound,
386 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctSeriesPIUReheat,
387 30 : state.dataIPShortCut->cAlphaArgs(1),
388 : DataLoopNode::NodeFluidType::Air,
389 : DataLoopNode::ConnectionType::Internal,
390 : NodeInputManager::CompFluidStream::Primary,
391 : ObjectIsParent,
392 30 : state.dataIPShortCut->cAlphaFieldNames(6));
393 : // The reheat coil control node is necessary for hot water reheat, but not necessary for
394 : // electric or gas reheat.
395 30 : if (state.dataPowerInductionUnits->PIU(PIUNum).HCoilType == HtgCoilType::SimpleHeating) {
396 30 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlNode =
397 30 : GetCoilWaterInletNode(state, state.dataIPShortCut->cAlphaArgs(9), state.dataIPShortCut->cAlphaArgs(10), ErrorsFound);
398 : }
399 30 : if (state.dataPowerInductionUnits->PIU(PIUNum).HCoilType == HtgCoilType::SteamAirHeating) {
400 0 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlNode =
401 0 : GetCoilSteamInletNode(state, state.dataIPShortCut->cAlphaArgs(9), state.dataIPShortCut->cAlphaArgs(10), ErrorsFound);
402 : }
403 30 : state.dataPowerInductionUnits->PIU(PIUNum).MixerName = state.dataIPShortCut->cAlphaArgs(7); // name of zone mixer object
404 30 : state.dataPowerInductionUnits->PIU(PIUNum).FanName = state.dataIPShortCut->cAlphaArgs(8); // name of fan object
405 :
406 : // find fan type
407 : // test if Fan:SystemModel fan of this name exists
408 30 : if (HVACFan::checkIfFanNameIsAFanSystem(state, state.dataPowerInductionUnits->PIU(PIUNum).FanName)) {
409 2 : state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num = DataHVACGlobals::FanType_SystemModelObject;
410 4 : state.dataHVACFan->fanObjs.emplace_back(
411 4 : new HVACFan::FanSystem(state, state.dataPowerInductionUnits->PIU(PIUNum).FanName)); // call constructor
412 2 : state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index =
413 2 : HVACFan::getFanObjectVectorIndex(state, state.dataPowerInductionUnits->PIU(PIUNum).FanName);
414 2 : state.dataPowerInductionUnits->PIU(PIUNum).FanAvailSchedPtr =
415 2 : state.dataHVACFan->fanObjs[state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index]->availSchedIndex;
416 : } else {
417 28 : bool isNotOkay(false);
418 28 : ValidateComponent(state, "FAN:CONSTANTVOLUME", state.dataPowerInductionUnits->PIU(PIUNum).FanName, isNotOkay, "GetPIUs");
419 28 : if (isNotOkay) {
420 0 : ShowContinueError(
421 0 : state, "In " + state.dataPowerInductionUnits->PIU(PIUNum).UnitType + " = " + state.dataPowerInductionUnits->PIU(PIUNum).Name);
422 0 : ErrorsFound = true;
423 : }
424 28 : state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num = DataHVACGlobals::FanType_SimpleConstVolume;
425 28 : Fans::GetFanType(state, state.dataPowerInductionUnits->PIU(PIUNum).FanName, FanType_Num, ErrorsFound);
426 56 : state.dataPowerInductionUnits->PIU(PIUNum).FanAvailSchedPtr = Fans::GetFanAvailSchPtr(
427 56 : state, DataHVACGlobals::cFanTypes(FanType_Num), state.dataPowerInductionUnits->PIU(PIUNum).FanName, ErrorsFound);
428 : }
429 :
430 30 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil = state.dataIPShortCut->cAlphaArgs(10); // name of heating coil object
431 60 : ValidateComponent(state,
432 30 : HCoilNamesUC[static_cast<int>(state.dataPowerInductionUnits->PIU(PIUNum).HCoilType)],
433 30 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
434 : IsNotOK,
435 60 : cCurrentModuleObject + " - Heating Coil");
436 30 : if (IsNotOK) {
437 0 : ShowContinueError(state, "In " + cCurrentModuleObject + " = " + state.dataPowerInductionUnits->PIU(PIUNum).Name);
438 0 : ErrorsFound = true;
439 : }
440 30 : state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow = state.dataIPShortCut->rNumericArgs(4);
441 30 : state.dataPowerInductionUnits->PIU(PIUNum).MinVolHotWaterFlow = state.dataIPShortCut->rNumericArgs(5);
442 30 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlOffset = state.dataIPShortCut->rNumericArgs(6);
443 : // Set default convergence tolerance
444 30 : if (state.dataPowerInductionUnits->PIU(PIUNum).HotControlOffset <= 0.0) {
445 0 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlOffset = 0.001;
446 : }
447 :
448 : // Add fan to component sets array
449 120 : SetUpCompSets(state,
450 30 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
451 30 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
452 : "UNDEFINED",
453 30 : state.dataIPShortCut->cAlphaArgs(8),
454 : "UNDEFINED",
455 90 : state.dataIPShortCut->cAlphaArgs(6));
456 :
457 : // Add reheat coil to component sets array
458 180 : SetUpCompSets(state,
459 30 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
460 30 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
461 30 : state.dataIPShortCut->cAlphaArgs(9),
462 30 : state.dataIPShortCut->cAlphaArgs(10),
463 30 : state.dataIPShortCut->cAlphaArgs(6),
464 30 : state.dataIPShortCut->cAlphaArgs(5));
465 :
466 : // Register component set data
467 90 : TestCompSet(state,
468 30 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
469 30 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
470 30 : state.dataLoopNodes->NodeID(state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode),
471 30 : state.dataLoopNodes->NodeID(state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode),
472 : "Air Nodes");
473 :
474 30 : AirNodeFound = false;
475 176 : for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
476 146 : if (state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
477 30 : state.dataPowerInductionUnits->PIU(PIUNum).ADUNum = ADUNum;
478 30 : state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum = state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode;
479 : }
480 : }
481 : // one assumes if there isn't one assigned, it's an error?
482 30 : if (state.dataPowerInductionUnits->PIU(PIUNum).ADUNum == 0) {
483 0 : ShowSevereError(state,
484 0 : std::string{RoutineName} + "No matching Air Distribution Unit, for PIU = [" +
485 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType + ',' + state.dataPowerInductionUnits->PIU(PIUNum).Name + "].");
486 0 : ShowContinueError(state,
487 0 : "...should have outlet node = " + state.dataLoopNodes->NodeID(state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode));
488 0 : ErrorsFound = true;
489 : } else {
490 :
491 : // Fill the Zone Equipment data with the supply air inlet node number of this unit.
492 202 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
493 172 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
494 262 : for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
495 146 : if (state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
496 30 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode =
497 30 : state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode;
498 30 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode =
499 30 : state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode;
500 30 : state.dataDefineEquipment->AirDistUnit(state.dataPowerInductionUnits->PIU(PIUNum).ADUNum).TermUnitSizingNum =
501 30 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
502 30 : state.dataDefineEquipment->AirDistUnit(state.dataPowerInductionUnits->PIU(PIUNum).ADUNum).ZoneEqNum = CtrlZone;
503 30 : AirNodeFound = true;
504 30 : state.dataPowerInductionUnits->PIU(PIUNum).CtrlZoneNum = CtrlZone; // fill index for later use in finding air loop index
505 30 : state.dataPowerInductionUnits->PIU(PIUNum).ctrlZoneInNodeIndex = SupAirIn;
506 30 : break;
507 : }
508 : }
509 : }
510 30 : if (!AirNodeFound) {
511 0 : ShowSevereError(
512 0 : state, "The outlet air node from the " + cCurrentModuleObject + " Unit = " + state.dataPowerInductionUnits->PIU(PIUNum).Name);
513 0 : ShowContinueError(state, "did not have a matching Zone Equipment Inlet Node, Node = " + state.dataIPShortCut->cAlphaArgs(5));
514 0 : ErrorsFound = true;
515 : }
516 : }
517 : }
518 :
519 19 : for (PIUIndex = 1; PIUIndex <= state.dataPowerInductionUnits->NumParallelPIUs; ++PIUIndex) {
520 :
521 4 : cCurrentModuleObject = "AirTerminal:SingleDuct:ParallelPIU:Reheat";
522 :
523 28 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
524 : cCurrentModuleObject,
525 : PIUIndex,
526 4 : state.dataIPShortCut->cAlphaArgs,
527 : NumAlphas,
528 4 : state.dataIPShortCut->rNumericArgs,
529 : NumNumbers,
530 : IOStatus,
531 4 : state.dataIPShortCut->lNumericFieldBlanks,
532 4 : state.dataIPShortCut->lAlphaFieldBlanks,
533 4 : state.dataIPShortCut->cAlphaFieldNames,
534 4 : state.dataIPShortCut->cNumericFieldNames);
535 :
536 4 : PIUNum = PIUIndex + state.dataPowerInductionUnits->NumSeriesPIUs;
537 8 : GlobalNames::VerifyUniqueInterObjectName(state,
538 4 : state.dataPowerInductionUnits->PiuUniqueNames,
539 4 : state.dataIPShortCut->cAlphaArgs(1),
540 : cCurrentModuleObject,
541 4 : state.dataIPShortCut->cAlphaFieldNames(1),
542 : ErrorsFound);
543 4 : state.dataPowerInductionUnits->PIU(PIUNum).Name = state.dataIPShortCut->cAlphaArgs(1);
544 4 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType = cCurrentModuleObject;
545 4 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType_Num = DataDefineEquip::ZnAirLoopEquipType::SingleDuct_ParallelPIU_Reheat;
546 4 : state.dataPowerInductionUnits->PIU(PIUNum).Sched = state.dataIPShortCut->cAlphaArgs(2);
547 4 : if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
548 0 : state.dataPowerInductionUnits->PIU(PIUNum).SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
549 : } else {
550 4 : state.dataPowerInductionUnits->PIU(PIUNum).SchedPtr =
551 4 : GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2)); // convert schedule name to pointer
552 4 : if (state.dataPowerInductionUnits->PIU(PIUNum).SchedPtr == 0) {
553 0 : ShowSevereError(state,
554 0 : std::string{RoutineName} + cCurrentModuleObject + ": invalid " + state.dataIPShortCut->cAlphaFieldNames(2) +
555 0 : " entered =" + state.dataIPShortCut->cAlphaArgs(2) + " for " + state.dataIPShortCut->cAlphaFieldNames(1) + '=' +
556 0 : state.dataIPShortCut->cAlphaArgs(1));
557 0 : ErrorsFound = true;
558 : }
559 : }
560 4 : state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow = state.dataIPShortCut->rNumericArgs(1);
561 4 : state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirVolFlow = state.dataIPShortCut->rNumericArgs(2);
562 4 : state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac = state.dataIPShortCut->rNumericArgs(3);
563 4 : state.dataPowerInductionUnits->PIU(PIUNum).FanOnFlowFrac = state.dataIPShortCut->rNumericArgs(4);
564 4 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "COIL:HEATING:WATER")) {
565 4 : state.dataPowerInductionUnits->PIU(PIUNum).HCoilType = HtgCoilType::SimpleHeating;
566 4 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_PlantType = DataPlant::PlantEquipmentType::CoilWaterSimpleHeating;
567 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "COIL:HEATING:FUEL")) {
568 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoilType = HtgCoilType::Gas;
569 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "COIL:HEATING:STEAM")) {
570 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoilType = HtgCoilType::SteamAirHeating;
571 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_PlantType = DataPlant::PlantEquipmentType::CoilSteamAirHeating;
572 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_FluidIndex = FindRefrigerant(state, "Steam");
573 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).HCoil_FluidIndex == 0) {
574 0 : ShowSevereError(state, std::string{RoutineName} + "Steam Properties for " + state.dataIPShortCut->cAlphaArgs(1) + " not found.");
575 0 : if (SteamMessageNeeded) ShowContinueError(state, "Steam Fluid Properties should have been included in the input file.");
576 0 : ErrorsFound = true;
577 0 : SteamMessageNeeded = false;
578 : }
579 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "COIL:HEATING:ELECTRIC")) {
580 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoilType = HtgCoilType::Electric;
581 : } else {
582 0 : ShowSevereError(state, "Illegal " + state.dataIPShortCut->cAlphaFieldNames(9) + " = " + state.dataIPShortCut->cAlphaArgs(9));
583 0 : ShowContinueError(state, "Occurs in " + cCurrentModuleObject + " = " + state.dataPowerInductionUnits->PIU(PIUNum).Name);
584 0 : ErrorsFound = true;
585 : }
586 :
587 4 : state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode =
588 8 : GetOnlySingleNode(state,
589 4 : state.dataIPShortCut->cAlphaArgs(3),
590 : ErrorsFound,
591 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctParallelPIUReheat,
592 4 : state.dataIPShortCut->cAlphaArgs(1),
593 : DataLoopNode::NodeFluidType::Air,
594 : DataLoopNode::ConnectionType::Inlet,
595 : NodeInputManager::CompFluidStream::Primary,
596 : ObjectIsParent,
597 4 : state.dataIPShortCut->cAlphaFieldNames(3));
598 :
599 4 : state.dataPowerInductionUnits->PIU(PIUNum).SecAirInNode =
600 8 : GetOnlySingleNode(state,
601 4 : state.dataIPShortCut->cAlphaArgs(4),
602 : ErrorsFound,
603 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctParallelPIUReheat,
604 4 : state.dataIPShortCut->cAlphaArgs(1),
605 : DataLoopNode::NodeFluidType::Air,
606 : DataLoopNode::ConnectionType::Inlet,
607 : NodeInputManager::CompFluidStream::Primary,
608 : ObjectIsParent,
609 4 : state.dataIPShortCut->cAlphaFieldNames(4));
610 :
611 4 : state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode =
612 8 : GetOnlySingleNode(state,
613 4 : state.dataIPShortCut->cAlphaArgs(5),
614 : ErrorsFound,
615 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctParallelPIUReheat,
616 4 : state.dataIPShortCut->cAlphaArgs(1),
617 : DataLoopNode::NodeFluidType::Air,
618 : DataLoopNode::ConnectionType::Outlet,
619 : NodeInputManager::CompFluidStream::Primary,
620 : ObjectIsParent,
621 4 : state.dataIPShortCut->cAlphaFieldNames(5));
622 :
623 4 : state.dataPowerInductionUnits->PIU(PIUNum).HCoilInAirNode =
624 8 : GetOnlySingleNode(state,
625 4 : state.dataIPShortCut->cAlphaArgs(6),
626 : ErrorsFound,
627 : DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctParallelPIUReheat,
628 4 : state.dataIPShortCut->cAlphaArgs(1),
629 : DataLoopNode::NodeFluidType::Air,
630 : DataLoopNode::ConnectionType::Internal,
631 : NodeInputManager::CompFluidStream::Primary,
632 : ObjectIsParent,
633 4 : state.dataIPShortCut->cAlphaFieldNames(6));
634 4 : if (state.dataPowerInductionUnits->PIU(PIUNum).HCoilType == HtgCoilType::SimpleHeating) {
635 4 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlNode =
636 4 : GetCoilWaterInletNode(state, state.dataIPShortCut->cAlphaArgs(9), state.dataIPShortCut->cAlphaArgs(10), ErrorsFound);
637 : }
638 4 : if (state.dataPowerInductionUnits->PIU(PIUNum).HCoilType == HtgCoilType::SteamAirHeating) {
639 0 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlNode =
640 0 : GetCoilSteamInletNode(state, state.dataIPShortCut->cAlphaArgs(9), state.dataIPShortCut->cAlphaArgs(10), ErrorsFound);
641 : }
642 4 : state.dataPowerInductionUnits->PIU(PIUNum).MixerName = state.dataIPShortCut->cAlphaArgs(7); // name of zone mixer object
643 4 : state.dataPowerInductionUnits->PIU(PIUNum).FanName = state.dataIPShortCut->cAlphaArgs(8); // name of fan object
644 : // find fan type
645 : // test if Fan:SystemModel fan of this name exists
646 4 : if (HVACFan::checkIfFanNameIsAFanSystem(state, state.dataPowerInductionUnits->PIU(PIUNum).FanName)) {
647 2 : state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num = DataHVACGlobals::FanType_SystemModelObject;
648 4 : state.dataHVACFan->fanObjs.emplace_back(
649 4 : new HVACFan::FanSystem(state, state.dataPowerInductionUnits->PIU(PIUNum).FanName)); // call constructor
650 2 : state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index =
651 2 : HVACFan::getFanObjectVectorIndex(state, state.dataPowerInductionUnits->PIU(PIUNum).FanName);
652 2 : state.dataPowerInductionUnits->PIU(PIUNum).FanAvailSchedPtr =
653 2 : state.dataHVACFan->fanObjs[state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index]->availSchedIndex;
654 : } else {
655 2 : bool isNotOkay(false);
656 2 : ValidateComponent(state, "FAN:CONSTANTVOLUME", state.dataPowerInductionUnits->PIU(PIUNum).FanName, isNotOkay, "GetPIUs");
657 2 : if (isNotOkay) {
658 0 : ShowContinueError(
659 0 : state, "In " + state.dataPowerInductionUnits->PIU(PIUNum).UnitType + " = " + state.dataPowerInductionUnits->PIU(PIUNum).Name);
660 0 : ErrorsFound = true;
661 : }
662 2 : state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num = DataHVACGlobals::FanType_SimpleConstVolume;
663 2 : Fans::GetFanType(state, state.dataPowerInductionUnits->PIU(PIUNum).FanName, FanType_Num, ErrorsFound);
664 4 : state.dataPowerInductionUnits->PIU(PIUNum).FanAvailSchedPtr = Fans::GetFanAvailSchPtr(
665 4 : state, DataHVACGlobals::cFanTypes(FanType_Num), state.dataPowerInductionUnits->PIU(PIUNum).FanName, ErrorsFound);
666 : }
667 4 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil = state.dataIPShortCut->cAlphaArgs(10); // name of heating coil object
668 8 : ValidateComponent(state,
669 4 : HCoilNamesUC[static_cast<int>(state.dataPowerInductionUnits->PIU(PIUNum).HCoilType)],
670 4 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
671 : IsNotOK,
672 8 : cCurrentModuleObject + " - Heating Coil");
673 4 : if (IsNotOK) {
674 0 : ShowContinueError(state, "In " + cCurrentModuleObject + " = " + state.dataPowerInductionUnits->PIU(PIUNum).Name);
675 0 : ErrorsFound = true;
676 : }
677 4 : state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow = state.dataIPShortCut->rNumericArgs(5);
678 4 : state.dataPowerInductionUnits->PIU(PIUNum).MinVolHotWaterFlow = state.dataIPShortCut->rNumericArgs(6);
679 4 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlOffset = state.dataIPShortCut->rNumericArgs(7);
680 : // Set default convergence tolerance
681 4 : if (state.dataPowerInductionUnits->PIU(PIUNum).HotControlOffset <= 0.0) {
682 0 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlOffset = 0.001;
683 : }
684 :
685 : // Add fan to component sets array
686 16 : SetUpCompSets(state,
687 4 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
688 4 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
689 : "UNDEFINED",
690 4 : state.dataIPShortCut->cAlphaArgs(8),
691 4 : state.dataIPShortCut->cAlphaArgs(4),
692 8 : "UNDEFINED");
693 :
694 : // Add reheat coil to component sets array
695 24 : SetUpCompSets(state,
696 4 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
697 4 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
698 4 : state.dataIPShortCut->cAlphaArgs(9),
699 4 : state.dataIPShortCut->cAlphaArgs(10),
700 4 : state.dataIPShortCut->cAlphaArgs(6),
701 4 : state.dataIPShortCut->cAlphaArgs(5));
702 :
703 : // Register component set data
704 12 : TestCompSet(state,
705 4 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
706 4 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
707 4 : state.dataLoopNodes->NodeID(state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode),
708 4 : state.dataLoopNodes->NodeID(state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode),
709 : "Air Nodes");
710 :
711 4 : AirNodeFound = false;
712 20 : for (ADUNum = 1; ADUNum <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++ADUNum) {
713 16 : if (state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode == state.dataDefineEquipment->AirDistUnit(ADUNum).OutletNodeNum) {
714 : // AirDistUnit(ADUNum)%InletNodeNum = PIU(PIUNum)%InletNodeNum
715 4 : state.dataDefineEquipment->AirDistUnit(ADUNum).InletNodeNum = state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode;
716 4 : state.dataPowerInductionUnits->PIU(PIUNum).ADUNum = ADUNum;
717 : }
718 : }
719 : // one assumes if there isn't one assigned, it's an error?
720 4 : if (state.dataPowerInductionUnits->PIU(PIUNum).ADUNum == 0) {
721 0 : ShowSevereError(state,
722 0 : std::string{RoutineName} + "No matching Air Distribution Unit, for PIU = [" +
723 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType + ',' + state.dataPowerInductionUnits->PIU(PIUNum).Name + "].");
724 0 : ShowContinueError(state,
725 0 : "...should have outlet node = " + state.dataLoopNodes->NodeID(state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode));
726 0 : ErrorsFound = true;
727 : } else {
728 :
729 : // Fill the Zone Equipment data with the supply air inlet node number of this unit.
730 4 : AirNodeFound = false;
731 22 : for (CtrlZone = 1; CtrlZone <= state.dataGlobal->NumOfZones; ++CtrlZone) {
732 18 : if (!state.dataZoneEquip->ZoneEquipConfig(CtrlZone).IsControlled) continue;
733 32 : for (SupAirIn = 1; SupAirIn <= state.dataZoneEquip->ZoneEquipConfig(CtrlZone).NumInletNodes; ++SupAirIn) {
734 16 : if (state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode == state.dataZoneEquip->ZoneEquipConfig(CtrlZone).InletNode(SupAirIn)) {
735 4 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).InNode =
736 4 : state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode;
737 4 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).OutNode =
738 4 : state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode;
739 4 : state.dataDefineEquipment->AirDistUnit(state.dataPowerInductionUnits->PIU(PIUNum).ADUNum).TermUnitSizingNum =
740 4 : state.dataZoneEquip->ZoneEquipConfig(CtrlZone).AirDistUnitCool(SupAirIn).TermUnitSizingIndex;
741 4 : state.dataDefineEquipment->AirDistUnit(state.dataPowerInductionUnits->PIU(PIUNum).ADUNum).ZoneEqNum = CtrlZone;
742 4 : state.dataPowerInductionUnits->PIU(PIUNum).CtrlZoneNum = CtrlZone;
743 4 : state.dataPowerInductionUnits->PIU(PIUNum).ctrlZoneInNodeIndex = SupAirIn;
744 4 : AirNodeFound = true;
745 : }
746 : }
747 : }
748 4 : if (!AirNodeFound) {
749 0 : ShowSevereError(
750 0 : state, "The outlet air node from the " + cCurrentModuleObject + " Unit = " + state.dataPowerInductionUnits->PIU(PIUNum).Name);
751 0 : ShowContinueError(state, "did not have a matching Zone Equipment Inlet Node, Node = " + state.dataIPShortCut->cAlphaArgs(5));
752 0 : ErrorsFound = true;
753 : }
754 : }
755 : }
756 :
757 15 : if (ErrorsFound) {
758 0 : ShowFatalError(state, std::string{RoutineName} + "Errors found in getting input. Preceding conditions cause termination.");
759 : }
760 :
761 49 : for (PIUNum = 1; PIUNum <= state.dataPowerInductionUnits->NumPIUs; ++PIUNum) {
762 : // Setup Report variables for the PIUs
763 136 : SetupOutputVariable(state,
764 : "Zone Air Terminal Primary Damper Position",
765 : OutputProcessor::Unit::None,
766 34 : state.dataPowerInductionUnits->PIU(PIUNum).PriDamperPosition,
767 : OutputProcessor::SOVTimeStepType::System,
768 : OutputProcessor::SOVStoreType::Average,
769 68 : state.dataPowerInductionUnits->PIU(PIUNum).Name);
770 136 : SetupOutputVariable(state,
771 : "Zone Air Terminal Heating Rate",
772 : OutputProcessor::Unit::W,
773 34 : state.dataPowerInductionUnits->PIU(PIUNum).HeatingRate,
774 : OutputProcessor::SOVTimeStepType::System,
775 : OutputProcessor::SOVStoreType::Average,
776 68 : state.dataPowerInductionUnits->PIU(PIUNum).Name);
777 136 : SetupOutputVariable(state,
778 : "Zone Air Terminal Heating Energy",
779 : OutputProcessor::Unit::J,
780 34 : state.dataPowerInductionUnits->PIU(PIUNum).HeatingEnergy,
781 : OutputProcessor::SOVTimeStepType::System,
782 : OutputProcessor::SOVStoreType::Summed,
783 68 : state.dataPowerInductionUnits->PIU(PIUNum).Name);
784 136 : SetupOutputVariable(state,
785 : "Zone Air Terminal Sensible Cooling Rate",
786 : OutputProcessor::Unit::W,
787 34 : state.dataPowerInductionUnits->PIU(PIUNum).SensCoolRate,
788 : OutputProcessor::SOVTimeStepType::System,
789 : OutputProcessor::SOVStoreType::Average,
790 68 : state.dataPowerInductionUnits->PIU(PIUNum).Name);
791 136 : SetupOutputVariable(state,
792 : "Zone Air Terminal Sensible Cooling Energy",
793 : OutputProcessor::Unit::J,
794 34 : state.dataPowerInductionUnits->PIU(PIUNum).SensCoolEnergy,
795 : OutputProcessor::SOVTimeStepType::System,
796 : OutputProcessor::SOVStoreType::Summed,
797 68 : state.dataPowerInductionUnits->PIU(PIUNum).Name);
798 136 : SetupOutputVariable(state,
799 : "Zone Air Terminal Outdoor Air Volume Flow Rate",
800 : OutputProcessor::Unit::m3_s,
801 34 : state.dataPowerInductionUnits->PIU(PIUNum).OutdoorAirFlowRate,
802 : OutputProcessor::SOVTimeStepType::System,
803 : OutputProcessor::SOVStoreType::Average,
804 68 : state.dataPowerInductionUnits->PIU(PIUNum).Name);
805 : }
806 15 : }
807 :
808 120828 : void InitPIU(EnergyPlusData &state,
809 : int const PIUNum, // number of the current fan coil unit being simulated
810 : bool const FirstHVACIteration // TRUE if first zone equip this HVAC step
811 : )
812 : {
813 :
814 : // SUBROUTINE INFORMATION:
815 : // AUTHOR Fred Buhl
816 : // DATE WRITTEN August 2000
817 : // MODIFIED na
818 : // RE-ENGINEERED na
819 :
820 : // PURPOSE OF THIS SUBROUTINE:
821 : // This subroutine is for initializations of the powered induction unit
822 : // terminal boxe.
823 :
824 : // METHODOLOGY EMPLOYED:
825 : // Uses the status flags to trigger initializations.
826 :
827 : // Using/Aliasing
828 :
829 : using DataZoneEquipment::CheckZoneEquipmentList;
830 : using PlantUtilities::InitComponentNodes;
831 : using PlantUtilities::ScanPlantLoopsForObject;
832 :
833 : // SUBROUTINE PARAMETER DEFINITIONS:
834 : static constexpr std::string_view RoutineName("InitPIU");
835 :
836 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
837 : int PriNode; // primary air inlet node number
838 : int SecNode; // secondary air inlet node number
839 : int HotConNode; // hot water control node number in PIU
840 : int OutletNode; // unit air outlet node number
841 : Real64 RhoAir; // air density at outside pressure and standard temperature and humidity
842 120828 : auto &MyEnvrnFlag = state.dataPowerInductionUnits->MyEnvrnFlag;
843 120828 : auto &MySizeFlag = state.dataPowerInductionUnits->MySizeFlag;
844 120828 : auto &MyPlantScanFlag = state.dataPowerInductionUnits->MyPlantScanFlag;
845 : int Loop; // Loop checking control variable
846 : Real64 rho; // local plant fluid density
847 : bool errFlag;
848 :
849 : // Do the one time initializations
850 120828 : if (state.dataPowerInductionUnits->MyOneTimeFlag) {
851 :
852 11 : MyEnvrnFlag.allocate(state.dataPowerInductionUnits->NumPIUs);
853 11 : MySizeFlag.allocate(state.dataPowerInductionUnits->NumPIUs);
854 11 : MyPlantScanFlag.allocate(state.dataPowerInductionUnits->NumPIUs);
855 11 : MyEnvrnFlag = true;
856 11 : MySizeFlag = true;
857 11 : MyPlantScanFlag = true;
858 11 : state.dataPowerInductionUnits->MyOneTimeFlag = false;
859 : }
860 :
861 120828 : if (MyPlantScanFlag(PIUNum) && allocated(state.dataPlnt->PlantLoop)) {
862 34 : if ((state.dataPowerInductionUnits->PIU(PIUNum).HCoil_PlantType == DataPlant::PlantEquipmentType::CoilWaterSimpleHeating) ||
863 0 : (state.dataPowerInductionUnits->PIU(PIUNum).HCoil_PlantType == DataPlant::PlantEquipmentType::CoilSteamAirHeating)) {
864 34 : errFlag = false;
865 136 : ScanPlantLoopsForObject(state,
866 34 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
867 34 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_PlantType,
868 34 : state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc,
869 : errFlag,
870 : _,
871 : _,
872 : _,
873 : _,
874 : _);
875 34 : if (errFlag) {
876 0 : ShowFatalError(state, "InitPIU: Program terminated due to previous condition(s).");
877 : }
878 34 : state.dataPowerInductionUnits->PIU(PIUNum).HotCoilOutNodeNum =
879 34 : DataPlant::CompData::getPlantComponent(state, state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc).NodeNumOut;
880 : }
881 34 : MyPlantScanFlag(PIUNum) = false;
882 120794 : } else if (MyPlantScanFlag(PIUNum) && !state.dataGlobal->AnyPlantInModel) {
883 0 : MyPlantScanFlag(PIUNum) = false;
884 : }
885 :
886 120828 : if (!state.dataPowerInductionUnits->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
887 11 : state.dataPowerInductionUnits->ZoneEquipmentListChecked = true;
888 : // Check to see if there is a Air Distribution Unit on the Zone Equipment List
889 45 : for (Loop = 1; Loop <= state.dataPowerInductionUnits->NumPIUs; ++Loop) {
890 34 : if (state.dataPowerInductionUnits->PIU(Loop).ADUNum == 0) continue;
891 102 : if (CheckZoneEquipmentList(state,
892 : "ZoneHVAC:AirDistributionUnit",
893 68 : state.dataDefineEquipment->AirDistUnit(state.dataPowerInductionUnits->PIU(Loop).ADUNum).Name))
894 34 : continue;
895 0 : ShowSevereError(state,
896 0 : "InitPIU: ADU=[Air Distribution Unit," +
897 0 : state.dataDefineEquipment->AirDistUnit(state.dataPowerInductionUnits->PIU(Loop).ADUNum).Name +
898 : "] is not on any ZoneHVAC:EquipmentList.");
899 0 : ShowContinueError(state,
900 0 : "...PIU=[" + state.dataPowerInductionUnits->PIU(Loop).UnitType + ',' + state.dataPowerInductionUnits->PIU(Loop).Name +
901 : "] will not be simulated.");
902 : }
903 : }
904 :
905 120828 : if (!state.dataGlobal->SysSizingCalc && MySizeFlag(PIUNum) && !MyPlantScanFlag(PIUNum)) {
906 :
907 34 : SizePIU(state, PIUNum);
908 :
909 34 : HotConNode = state.dataPowerInductionUnits->PIU(PIUNum).HotControlNode;
910 34 : if (HotConNode > 0) {
911 : // plant upgrade note? why no separate handling of steam coil? add it ?
912 68 : rho = GetDensityGlycol(state,
913 34 : state.dataPlnt->PlantLoop(state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc.loopNum).FluidName,
914 : DataGlobalConstants::HWInitConvTemp,
915 34 : state.dataPlnt->PlantLoop(state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc.loopNum).FluidIndex,
916 : RoutineName);
917 :
918 34 : state.dataPowerInductionUnits->PIU(PIUNum).MaxHotWaterFlow = rho * state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow;
919 34 : state.dataPowerInductionUnits->PIU(PIUNum).MinHotWaterFlow = rho * state.dataPowerInductionUnits->PIU(PIUNum).MinVolHotWaterFlow;
920 136 : InitComponentNodes(state,
921 34 : state.dataPowerInductionUnits->PIU(PIUNum).MinHotWaterFlow,
922 34 : state.dataPowerInductionUnits->PIU(PIUNum).MaxHotWaterFlow,
923 34 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlNode,
924 34 : state.dataPowerInductionUnits->PIU(PIUNum).HotCoilOutNodeNum);
925 : }
926 :
927 34 : MySizeFlag(PIUNum) = false;
928 : }
929 :
930 : // Do the Begin Environment initializations
931 120828 : if (state.dataGlobal->BeginEnvrnFlag && MyEnvrnFlag(PIUNum)) {
932 202 : RhoAir = state.dataEnvrn->StdRhoAir;
933 202 : PriNode = state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode;
934 202 : SecNode = state.dataPowerInductionUnits->PIU(PIUNum).SecAirInNode;
935 202 : OutletNode = state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode;
936 : // set the mass flow rates from the input volume flow rates
937 202 : if (state.dataPowerInductionUnits->PIU(PIUNum).UnitType == "AirTerminal:SingleDuct:SeriesPIU:Reheat") {
938 : // series
939 178 : state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow = RhoAir * state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirVolFlow;
940 178 : state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow = RhoAir * state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow;
941 178 : state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirMassFlow =
942 178 : RhoAir * state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac * state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow;
943 178 : state.dataLoopNodes->Node(PriNode).MassFlowRateMax = state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow;
944 178 : state.dataLoopNodes->Node(PriNode).MassFlowRateMin = state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirMassFlow;
945 178 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMax = state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow;
946 : } else {
947 : // parallel
948 24 : state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow = RhoAir * state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow;
949 24 : state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirMassFlow =
950 24 : RhoAir * state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac * state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow;
951 24 : state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirMassFlow = RhoAir * state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirVolFlow;
952 24 : state.dataPowerInductionUnits->PIU(PIUNum).FanOnAirMassFlow =
953 24 : RhoAir * state.dataPowerInductionUnits->PIU(PIUNum).FanOnFlowFrac * state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow;
954 24 : state.dataLoopNodes->Node(PriNode).MassFlowRateMax = state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow;
955 24 : state.dataLoopNodes->Node(PriNode).MassFlowRateMin = state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirMassFlow;
956 24 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMax = state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow;
957 : }
958 :
959 404 : if (((state.dataPowerInductionUnits->PIU(PIUNum).HCoilType == HtgCoilType::SimpleHeating) ||
960 404 : (state.dataPowerInductionUnits->PIU(PIUNum).HCoilType == HtgCoilType::SteamAirHeating)) &&
961 202 : !MyPlantScanFlag(PIUNum)) {
962 808 : InitComponentNodes(state,
963 202 : state.dataPowerInductionUnits->PIU(PIUNum).MinHotWaterFlow,
964 202 : state.dataPowerInductionUnits->PIU(PIUNum).MaxHotWaterFlow,
965 202 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlNode,
966 202 : state.dataPowerInductionUnits->PIU(PIUNum).HotCoilOutNodeNum);
967 : }
968 :
969 202 : if (state.dataPowerInductionUnits->PIU(PIUNum).AirLoopNum == 0) { // fill air loop index
970 34 : if (state.dataPowerInductionUnits->PIU(PIUNum).CtrlZoneNum > 0 && state.dataPowerInductionUnits->PIU(PIUNum).ctrlZoneInNodeIndex > 0) {
971 34 : state.dataPowerInductionUnits->PIU(PIUNum).AirLoopNum =
972 34 : state.dataZoneEquip->ZoneEquipConfig(state.dataPowerInductionUnits->PIU(PIUNum).CtrlZoneNum)
973 34 : .InletNodeAirLoopNum(state.dataPowerInductionUnits->PIU(PIUNum).ctrlZoneInNodeIndex);
974 34 : state.dataDefineEquipment->AirDistUnit(state.dataPowerInductionUnits->PIU(PIUNum).ADUNum).AirLoopNum =
975 34 : state.dataPowerInductionUnits->PIU(PIUNum).AirLoopNum;
976 : }
977 : }
978 :
979 202 : MyEnvrnFlag(PIUNum) = false;
980 : } // end one time inits
981 :
982 120828 : if (!state.dataGlobal->BeginEnvrnFlag) {
983 119420 : MyEnvrnFlag(PIUNum) = true;
984 : }
985 :
986 120828 : PriNode = state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode;
987 120828 : SecNode = state.dataPowerInductionUnits->PIU(PIUNum).SecAirInNode;
988 :
989 : // Do the start of HVAC time step initializations
990 120828 : if (FirstHVACIteration) {
991 : // check for upstream zero flow. If nonzero and schedule ON, set primary flow to max
992 116444 : if (GetCurrentScheduleValue(state, state.dataPowerInductionUnits->PIU(PIUNum).SchedPtr) > 0.0 &&
993 58214 : state.dataLoopNodes->Node(PriNode).MassFlowRate > 0.0) {
994 56194 : if (state.dataPowerInductionUnits->PIU(PIUNum).UnitType == "AirTerminal:SingleDuct:SeriesPIU:Reheat") {
995 49103 : state.dataLoopNodes->Node(PriNode).MassFlowRate = state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow;
996 49103 : state.dataLoopNodes->Node(SecNode).MassFlowRate = max(
997 49103 : 0.0, state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow - state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow);
998 : } else {
999 7091 : state.dataLoopNodes->Node(PriNode).MassFlowRate = state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow;
1000 7091 : state.dataLoopNodes->Node(SecNode).MassFlowRate = state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirMassFlow;
1001 : }
1002 : } else {
1003 2036 : state.dataLoopNodes->Node(PriNode).MassFlowRate = 0.0;
1004 2036 : state.dataLoopNodes->Node(SecNode).MassFlowRate = 0.0;
1005 : }
1006 : // reset the max and min avail flows
1007 116444 : if (GetCurrentScheduleValue(state, state.dataPowerInductionUnits->PIU(PIUNum).SchedPtr) > 0.0 &&
1008 58214 : state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail > 0.0) {
1009 56194 : if (state.dataPowerInductionUnits->PIU(PIUNum).UnitType == "AirTerminal:SingleDuct:SeriesPIU:Reheat") {
1010 49103 : state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail = state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow;
1011 49103 : state.dataLoopNodes->Node(PriNode).MassFlowRateMinAvail = state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirMassFlow;
1012 49103 : state.dataLoopNodes->Node(SecNode).MassFlowRateMaxAvail = max(
1013 49103 : 0.0, state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow - state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirMassFlow);
1014 49103 : state.dataLoopNodes->Node(SecNode).MassFlowRateMinAvail = max(
1015 49103 : 0.0, state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow - state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow);
1016 : } else {
1017 7091 : state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail = state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow;
1018 7091 : state.dataLoopNodes->Node(PriNode).MassFlowRateMinAvail = state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirMassFlow;
1019 7091 : state.dataLoopNodes->Node(SecNode).MassFlowRateMaxAvail = state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirMassFlow;
1020 7091 : state.dataLoopNodes->Node(SecNode).MassFlowRateMinAvail = 0.0;
1021 : }
1022 : } else {
1023 2036 : state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail = 0.0;
1024 2036 : state.dataLoopNodes->Node(PriNode).MassFlowRateMinAvail = 0.0;
1025 2036 : state.dataLoopNodes->Node(SecNode).MassFlowRateMaxAvail = 0.0;
1026 2036 : state.dataLoopNodes->Node(SecNode).MassFlowRateMinAvail = 0.0;
1027 : }
1028 : }
1029 :
1030 : // Do the following initializations every time step
1031 :
1032 : // None needed
1033 120828 : }
1034 :
1035 34 : void SizePIU(EnergyPlusData &state, int const PIUNum)
1036 : {
1037 :
1038 : // SUBROUTINE INFORMATION:
1039 : // AUTHOR Fred Buhl
1040 : // DATE WRITTEN January 2002
1041 : // MODIFIED August 2013 Daeho Kang, add component sizing table entries
1042 : // RE-ENGINEERED na
1043 :
1044 : // PURPOSE OF THIS SUBROUTINE:
1045 : // This subroutine is for sizing PIU terminal units for which flow rates have not been
1046 : // specified in the input.
1047 :
1048 : // METHODOLOGY EMPLOYED:
1049 : // Obtains flow rates from the zone or system sizing arrays.
1050 :
1051 : // Using/Aliasing
1052 : using namespace DataSizing;
1053 : using FluidProperties::GetDensityGlycol;
1054 : using FluidProperties::GetSpecificHeatGlycol;
1055 : using SteamCoils::GetCoilSteamInletNode;
1056 : using SteamCoils::GetCoilSteamOutletNode;
1057 : using WaterCoils::GetCoilWaterInletNode;
1058 : using WaterCoils::GetCoilWaterOutletNode;
1059 : using WaterCoils::SetCoilDesFlow;
1060 :
1061 : using PlantUtilities::MyPlantSizingIndex;
1062 :
1063 : // SUBROUTINE PARAMETER DEFINITIONS:
1064 : static constexpr std::string_view RoutineName("SizePIU");
1065 :
1066 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1067 : int PltSizHeatNum; // index of plant sizing object for 1st heating loop
1068 : Real64 CoilInTemp;
1069 : Real64 CoilOutTemp;
1070 : Real64 CoilOutHumRat;
1071 : Real64 DesCoilLoad;
1072 : Real64 DesMassFlow;
1073 :
1074 : Real64 TempSteamIn;
1075 : Real64 EnthSteamInDry;
1076 : Real64 EnthSteamOutWet;
1077 : Real64 LatentHeatSteam;
1078 : Real64 SteamDensity;
1079 34 : int CoilWaterInletNode(0);
1080 34 : int CoilWaterOutletNode(0);
1081 34 : int CoilSteamInletNode(0);
1082 34 : int CoilSteamOutletNode(0);
1083 : bool ErrorsFound;
1084 : Real64 rho;
1085 : Real64 Cp;
1086 34 : int DummyWaterIndex(1);
1087 : bool IsAutoSize; // Indicator to autosize
1088 : bool IsMaxPriFlowAutoSize; // Indicate if the maximum terminal flow is autosize
1089 : int AirLoopNum; // Air loop number
1090 : int SysSizNum; // System sizing number
1091 : Real64 MaxPriAirVolFlowDes; // Autosized maximum primary air flow for reporting
1092 : Real64 MaxPriAirVolFlowUser; // Hardsized maximum primary air flow for reporting
1093 : Real64 MaxTotAirVolFlowDes; // Autosized maximum air flow for reporting
1094 : Real64 MaxTotAirVolFlowUser; // Hardsized maximum air flow for reporting
1095 : Real64 MaxSecAirVolFlowDes; // Autosized maximum secondary air flow for reporting
1096 : Real64 MaxSecAirVolFlowUser; // Hardsized maximum secondary air flow for reporting
1097 : Real64 MinPriAirFlowFracDes; // Autosized minimum primary air flow fraction for reporting
1098 : Real64 MinPriAirFlowFracUser; // Hardsized minimum primary air flow fraction for reporting
1099 : Real64 FanOnFlowFracDes; // Autosized fan on flow fraction for reporting
1100 : Real64 FanOnFlowFracUser; // Hardsized fan on flow fraction for reporting
1101 : Real64 MaxVolHotWaterFlowDes; // Autosized maximum hot water flow for reporting
1102 : Real64 MaxVolHotWaterFlowUser; // Hardsized maximum hot water flow for reporting
1103 : Real64 MaxVolHotSteamFlowDes; // Autosized maximum hot steam flow for reporting
1104 : Real64 MaxVolHotSteamFlowUser; // Hardsized maximum hot steam flow for reporting
1105 :
1106 34 : PltSizHeatNum = 0;
1107 34 : DesMassFlow = 0.0;
1108 34 : DesCoilLoad = 0.0;
1109 34 : ErrorsFound = false;
1110 34 : IsAutoSize = false;
1111 34 : IsMaxPriFlowAutoSize = false;
1112 34 : MaxPriAirVolFlowDes = 0.0;
1113 34 : MaxPriAirVolFlowUser = 0.0;
1114 34 : MaxTotAirVolFlowDes = 0.0;
1115 34 : MaxTotAirVolFlowUser = 0.0;
1116 34 : MaxSecAirVolFlowDes = 0.0;
1117 34 : MaxSecAirVolFlowUser = 0.0;
1118 34 : MinPriAirFlowFracDes = 0.0;
1119 34 : MinPriAirFlowFracUser = 0.0;
1120 34 : FanOnFlowFracDes = 0.0;
1121 34 : FanOnFlowFracUser = 0.0;
1122 34 : MaxVolHotWaterFlowDes = 0.0;
1123 34 : MaxVolHotWaterFlowUser = 0.0;
1124 34 : MaxVolHotSteamFlowDes = 0.0;
1125 34 : MaxVolHotSteamFlowUser = 0.0;
1126 34 : AirLoopNum = 0;
1127 34 : SysSizNum = 0;
1128 :
1129 34 : auto &TermUnitSizing(state.dataSize->TermUnitSizing);
1130 34 : auto &CurTermUnitSizingNum(state.dataSize->CurTermUnitSizingNum);
1131 :
1132 34 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow == AutoSize) {
1133 34 : IsAutoSize = true;
1134 : }
1135 34 : if ((state.dataSize->CurZoneEqNum > 0) && (CurTermUnitSizingNum > 0)) {
1136 34 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1137 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow > 0.0) {
1138 0 : BaseSizer::reportSizerOutput(state,
1139 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1140 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1141 : "User-Specified Maximum Primary Air Flow Rate [m3/s]",
1142 0 : state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow);
1143 : }
1144 : } else {
1145 34 : CheckZoneSizing(state, state.dataPowerInductionUnits->PIU(PIUNum).UnitType, state.dataPowerInductionUnits->PIU(PIUNum).Name);
1146 34 : MaxPriAirVolFlowDes = max(state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesCoolVolFlow,
1147 34 : state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesHeatVolFlow);
1148 34 : if (MaxPriAirVolFlowDes < SmallAirVolFlow) {
1149 0 : MaxPriAirVolFlowDes = 0.0;
1150 : }
1151 :
1152 34 : if (IsAutoSize) {
1153 34 : state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow = MaxPriAirVolFlowDes;
1154 34 : IsMaxPriFlowAutoSize = true;
1155 102 : BaseSizer::reportSizerOutput(state,
1156 34 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1157 34 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1158 : "Design Size Maximum Primary Air Flow Rate [m3/s]",
1159 34 : MaxPriAirVolFlowDes);
1160 : } else {
1161 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow > 0.0 && MaxPriAirVolFlowDes > 0.0) {
1162 0 : MaxPriAirVolFlowUser = state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow;
1163 0 : BaseSizer::reportSizerOutput(state,
1164 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1165 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1166 : "Design Size Maximum Primary Air Flow Rate [m3/s]",
1167 : MaxPriAirVolFlowDes,
1168 : "User-Specified Maximum Primary Air Flow Rate [m3/s]",
1169 0 : MaxPriAirVolFlowUser);
1170 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1171 0 : if ((std::abs(MaxPriAirVolFlowDes - MaxPriAirVolFlowUser) / MaxPriAirVolFlowUser) >
1172 0 : state.dataSize->AutoVsHardSizingThreshold) {
1173 0 : ShowMessage(state,
1174 0 : "SizePIU: Potential issue with equipment sizing for " + state.dataPowerInductionUnits->PIU(PIUNum).UnitType +
1175 0 : ' ' + state.dataPowerInductionUnits->PIU(PIUNum).Name);
1176 0 : ShowContinueError(state, format("User-Specified Primary Air Flow Rate of {:.5R} [m3/s]", MaxPriAirVolFlowUser));
1177 0 : ShowContinueError(state, format("differs from Design Size Primary Air Flow Rate of {:.5R} [m3/s]", MaxPriAirVolFlowDes));
1178 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1179 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1180 : }
1181 : }
1182 : }
1183 : }
1184 : }
1185 : }
1186 :
1187 34 : IsAutoSize = false;
1188 34 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirVolFlow == AutoSize) {
1189 30 : IsAutoSize = true;
1190 : }
1191 34 : if ((state.dataSize->CurZoneEqNum > 0) && (CurTermUnitSizingNum > 0)) {
1192 34 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1193 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirVolFlow > 0.0) {
1194 0 : BaseSizer::reportSizerOutput(state,
1195 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1196 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1197 : "User-Specified Maximum Air Flow Rate [m3/s]",
1198 0 : state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirVolFlow);
1199 : }
1200 : } else {
1201 34 : CheckZoneSizing(state, state.dataPowerInductionUnits->PIU(PIUNum).UnitType, state.dataPowerInductionUnits->PIU(PIUNum).Name);
1202 34 : MaxTotAirVolFlowDes = max(state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesCoolVolFlow,
1203 34 : state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesHeatVolFlow);
1204 34 : if (MaxTotAirVolFlowDes < SmallAirVolFlow) {
1205 0 : MaxTotAirVolFlowDes = 0.0;
1206 : }
1207 34 : if (IsAutoSize) {
1208 30 : state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirVolFlow = MaxTotAirVolFlowDes;
1209 90 : BaseSizer::reportSizerOutput(state,
1210 30 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1211 30 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1212 : "Design Size Maximum Air Flow Rate [m3/s]",
1213 30 : MaxTotAirVolFlowDes);
1214 : } else {
1215 4 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirVolFlow > 0.0 && MaxTotAirVolFlowDes > 0.0) {
1216 0 : MaxTotAirVolFlowUser = state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirVolFlow;
1217 0 : BaseSizer::reportSizerOutput(state,
1218 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1219 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1220 : "Design Size Maximum Air Flow Rate [m3/s]",
1221 : MaxTotAirVolFlowDes,
1222 : "User-Specified Maximum Air Flow Rate [m3/s]",
1223 0 : MaxTotAirVolFlowUser);
1224 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1225 0 : if ((std::abs(MaxTotAirVolFlowDes - MaxTotAirVolFlowUser) / MaxTotAirVolFlowUser) >
1226 0 : state.dataSize->AutoVsHardSizingThreshold) {
1227 0 : ShowMessage(state,
1228 0 : "SizePIU: Potential issue with equipment sizing for " + state.dataPowerInductionUnits->PIU(PIUNum).UnitType +
1229 0 : ' ' + state.dataPowerInductionUnits->PIU(PIUNum).Name);
1230 0 : ShowContinueError(state, format("User-Specified Maximum Air Flow Rate of {:.5R} [m3/s]", MaxTotAirVolFlowUser));
1231 0 : ShowContinueError(state, format("differs from Design Size Maximum Air Flow Rate of {:.5R} [m3/s]", MaxTotAirVolFlowDes));
1232 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1233 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1234 : }
1235 : }
1236 : }
1237 : }
1238 : }
1239 : }
1240 :
1241 : // if a sizing run has been done, check if system sizing has been done for this system
1242 34 : bool SizingDesRunThisAirSys = false;
1243 34 : if (state.dataSize->SysSizingRunDone) {
1244 68 : AirLoopNum = state.dataZoneEquip->ZoneEquipConfig(state.dataPowerInductionUnits->PIU(PIUNum).CtrlZoneNum)
1245 34 : .InletNodeAirLoopNum(state.dataPowerInductionUnits->PIU(PIUNum).ctrlZoneInNodeIndex);
1246 34 : if (AirLoopNum > 0) {
1247 34 : CheckThisAirSystemForSizing(state, AirLoopNum, SizingDesRunThisAirSys);
1248 : }
1249 :
1250 : // get system sizing id if a sizing run has been done for this system
1251 34 : if (SizingDesRunThisAirSys) {
1252 68 : SysSizNum = UtilityRoutines::FindItemInList(
1253 68 : state.dataSize->FinalSysSizing(AirLoopNum).AirPriLoopName, state.dataSize->SysSizInput, &SystemSizingInputData::AirPriLoopName);
1254 34 : if (SysSizNum == 0) SysSizNum = 1; // use first when none applicable
1255 : }
1256 : }
1257 :
1258 34 : IsAutoSize = false;
1259 34 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirVolFlow == AutoSize) {
1260 4 : IsAutoSize = true;
1261 : }
1262 34 : if ((state.dataSize->CurZoneEqNum > 0) && (CurTermUnitSizingNum > 0)) {
1263 34 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1264 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirVolFlow > 0.0) {
1265 0 : BaseSizer::reportSizerOutput(state,
1266 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1267 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1268 : "User-Specified Maximum Secondary Air Flow Rate [m3/s]",
1269 0 : state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirVolFlow);
1270 : }
1271 : } else {
1272 34 : CheckZoneSizing(state, state.dataPowerInductionUnits->PIU(PIUNum).UnitType, state.dataPowerInductionUnits->PIU(PIUNum).Name);
1273 34 : MaxSecAirVolFlowDes = max(state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesCoolVolFlow,
1274 34 : state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesHeatVolFlow);
1275 34 : if (MaxSecAirVolFlowDes < SmallAirVolFlow) {
1276 0 : MaxSecAirVolFlowDes = 0.0;
1277 : }
1278 34 : if (IsAutoSize) {
1279 4 : state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirVolFlow = MaxSecAirVolFlowDes;
1280 12 : BaseSizer::reportSizerOutput(state,
1281 4 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1282 4 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1283 : "Design Size Maximum Secondary Air Flow Rate [m3/s]",
1284 4 : MaxSecAirVolFlowDes);
1285 : } else {
1286 30 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirVolFlow > 0.0 && MaxSecAirVolFlowDes > 0.0) {
1287 0 : MaxSecAirVolFlowUser = state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirVolFlow;
1288 0 : BaseSizer::reportSizerOutput(state,
1289 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1290 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1291 : "Design Size Maximum Secondary Air Flow Rate [m3/s]",
1292 : MaxSecAirVolFlowDes,
1293 : "User-Specified Maximum Secondary Air Flow Rate [m3/s]",
1294 0 : MaxSecAirVolFlowUser);
1295 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1296 0 : if ((std::abs(MaxSecAirVolFlowDes - MaxSecAirVolFlowUser) / MaxSecAirVolFlowUser) >
1297 0 : state.dataSize->AutoVsHardSizingThreshold) {
1298 0 : ShowMessage(state,
1299 0 : "SizePIU: Potential issue with equipment sizing for " + state.dataPowerInductionUnits->PIU(PIUNum).UnitType +
1300 0 : ' ' + state.dataPowerInductionUnits->PIU(PIUNum).Name);
1301 0 : ShowContinueError(state, format("User-Specified Maximum Secondary Air Flow Rate of {:.5R} [m3/s]", MaxSecAirVolFlowUser));
1302 0 : ShowContinueError(
1303 0 : state, format("differs from Design Size Maximum Secondary Air Flow Rate of {:.5R} [m3/s]", MaxSecAirVolFlowDes));
1304 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1305 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1306 : }
1307 : }
1308 : }
1309 : }
1310 : }
1311 : }
1312 :
1313 34 : IsAutoSize = false;
1314 34 : if (state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac == AutoSize) {
1315 34 : IsAutoSize = true;
1316 : }
1317 34 : if ((state.dataSize->CurZoneEqNum > 0) && (CurTermUnitSizingNum > 0)) {
1318 34 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1319 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac > 0.0) {
1320 0 : BaseSizer::reportSizerOutput(state,
1321 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1322 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1323 : "User-Specified Minimum Primary Air Flow Fraction",
1324 0 : state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac);
1325 : }
1326 : } else {
1327 34 : CheckZoneSizing(state, state.dataPowerInductionUnits->PIU(PIUNum).UnitType, state.dataPowerInductionUnits->PIU(PIUNum).Name);
1328 68 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow >= SmallAirVolFlow &&
1329 34 : state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).MinOA >= SmallAirVolFlow) {
1330 34 : MinPriAirFlowFracDes =
1331 34 : state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).MinOA / state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow;
1332 : } else {
1333 0 : MinPriAirFlowFracDes = 0.0;
1334 : }
1335 34 : if (SizingDesRunThisAirSys) {
1336 34 : if (state.dataSize->SysSizInput(SysSizNum).SystemOAMethod == SysOAMethod::SP) { // 62.1 simplified procedure
1337 2 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow > 0.0) {
1338 4 : MinPriAirFlowFracDes = 1.5 *
1339 2 : max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VozClgByZone,
1340 4 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VozHtgByZone) /
1341 2 : state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow;
1342 :
1343 : // adjust maximum flow rate
1344 2 : if (MinPriAirFlowFracDes > 1.0 && IsMaxPriFlowAutoSize) {
1345 0 : state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow *= MinPriAirFlowFracDes;
1346 0 : MinPriAirFlowFracDes = 1.0;
1347 0 : ShowWarningError(state,
1348 0 : "SingleDuctSystem:SizeSys: Autosized maximum air flow rate for " +
1349 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name +
1350 : " was increased to meet the zone primary air flow determined according to the ASHRAE Standard 62.1 "
1351 : "Simplified Procedure.");
1352 2 : } else if (MinPriAirFlowFracDes > 1.0) {
1353 0 : ShowWarningError(state,
1354 0 : "SingleDuctSystem:SizeSys: Maximum primary air flow rate for " +
1355 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name + " is potentially too low.");
1356 0 : ShowContinueError(state,
1357 : "The flow is lower than the minimum primary air flow rate calculated following the ASHRAE Standard "
1358 : "62.1 Simplified Procedure:");
1359 0 : ShowContinueError(state,
1360 0 : format(" User-specified maximum primary air flow rate: {:.3R} m3/s.",
1361 0 : state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow));
1362 0 : ShowContinueError(state,
1363 0 : format(" Calculated minimum primary air flow rate: {:.3R} m3/s.",
1364 0 : state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow * MinPriAirFlowFracDes));
1365 0 : MinPriAirFlowFracDes = 1.0;
1366 : }
1367 : }
1368 : }
1369 : }
1370 34 : if (IsAutoSize) {
1371 34 : if (SizingDesRunThisAirSys) {
1372 34 : if (state.dataSize->SysSizInput(SysSizNum).SystemOAMethod == SysOAMethod::SP) {
1373 2 : state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).VpzMinByZoneSPSized = true;
1374 : }
1375 : }
1376 34 : state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac = MinPriAirFlowFracDes;
1377 102 : BaseSizer::reportSizerOutput(state,
1378 34 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1379 34 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1380 : "Design Size Minimum Primary Air Flow Fraction",
1381 34 : MinPriAirFlowFracDes);
1382 : } else {
1383 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac > 0.0 && MinPriAirFlowFracDes > 0.0) {
1384 0 : MinPriAirFlowFracUser = state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac;
1385 0 : BaseSizer::reportSizerOutput(state,
1386 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1387 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1388 : "Design Size Minimum Primary Air Flow Fraction",
1389 : MinPriAirFlowFracDes,
1390 : "User-Specified Minimum Primary Air Flow Fraction",
1391 0 : MinPriAirFlowFracUser);
1392 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1393 0 : if ((std::abs(MinPriAirFlowFracDes - MinPriAirFlowFracUser) / MinPriAirFlowFracUser) >
1394 0 : state.dataSize->AutoVsHardSizingThreshold) {
1395 0 : ShowMessage(state,
1396 0 : "SizePIU: Potential issue with equipment sizing for " + state.dataPowerInductionUnits->PIU(PIUNum).UnitType +
1397 0 : ' ' + state.dataPowerInductionUnits->PIU(PIUNum).Name);
1398 0 : ShowContinueError(state, format("User-Specified Minimum Primary Air Flow Fraction of {:.1R}", MinPriAirFlowFracUser));
1399 0 : ShowContinueError(state,
1400 0 : format("differs from Design Size Minimum Primary Air Flow Fraction of {:.1R}", MinPriAirFlowFracDes));
1401 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1402 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1403 : }
1404 : }
1405 : }
1406 : }
1407 : }
1408 : }
1409 :
1410 34 : if (CurTermUnitSizingNum > 0) {
1411 :
1412 34 : if (state.dataPowerInductionUnits->PIU(PIUNum).UnitType_Num == DataDefineEquip::ZnAirLoopEquipType::SingleDuct_SeriesPIU_Reheat) {
1413 30 : TermUnitSizing(CurTermUnitSizingNum).AirVolFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirVolFlow;
1414 4 : } else if (state.dataPowerInductionUnits->PIU(PIUNum).UnitType_Num == DataDefineEquip::ZnAirLoopEquipType::SingleDuct_ParallelPIU_Reheat) {
1415 4 : TermUnitSizing(CurTermUnitSizingNum).AirVolFlow =
1416 8 : state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirVolFlow +
1417 4 : state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac * state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirVolFlow;
1418 : }
1419 : }
1420 :
1421 34 : IsAutoSize = false;
1422 34 : if (state.dataPowerInductionUnits->PIU(PIUNum).FanOnFlowFrac == AutoSize) {
1423 4 : IsAutoSize = true;
1424 : }
1425 34 : if (state.dataSize->CurZoneEqNum > 0) {
1426 34 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1427 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).FanOnFlowFrac > 0.0) {
1428 0 : BaseSizer::reportSizerOutput(state,
1429 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1430 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1431 : "User-Specified Fan On Flow Fraction",
1432 0 : state.dataPowerInductionUnits->PIU(PIUNum).FanOnFlowFrac);
1433 : }
1434 : } else {
1435 34 : CheckZoneSizing(state, state.dataPowerInductionUnits->PIU(PIUNum).UnitType, state.dataPowerInductionUnits->PIU(PIUNum).Name);
1436 34 : FanOnFlowFracDes = state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac;
1437 34 : if (IsAutoSize) {
1438 4 : state.dataPowerInductionUnits->PIU(PIUNum).FanOnFlowFrac = FanOnFlowFracDes;
1439 12 : BaseSizer::reportSizerOutput(state,
1440 4 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1441 4 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1442 : "Design Size Fan On Flow Fraction",
1443 4 : FanOnFlowFracDes);
1444 : } else {
1445 30 : if (state.dataPowerInductionUnits->PIU(PIUNum).FanOnFlowFrac > 0.0 && FanOnFlowFracDes > 0.0) {
1446 0 : FanOnFlowFracUser = state.dataPowerInductionUnits->PIU(PIUNum).FanOnFlowFrac;
1447 0 : BaseSizer::reportSizerOutput(state,
1448 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1449 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1450 : "Design Size Fan On Flow Fraction",
1451 : FanOnFlowFracDes,
1452 : "User-Specified Fan On Flow Fraction",
1453 0 : FanOnFlowFracUser);
1454 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1455 0 : if ((std::abs(FanOnFlowFracDes - FanOnFlowFracUser) / FanOnFlowFracUser) > state.dataSize->AutoVsHardSizingThreshold) {
1456 0 : ShowMessage(state,
1457 0 : "SizePIU: Potential issue with equipment sizing for " + state.dataPowerInductionUnits->PIU(PIUNum).UnitType +
1458 0 : ' ' + state.dataPowerInductionUnits->PIU(PIUNum).Name);
1459 0 : ShowContinueError(state, format("User-Specified Fan On Flow Fraction of {:.1R}", FanOnFlowFracUser));
1460 0 : ShowContinueError(state, format("differs from Design Size Fan On Flow Fraction of {:.1R}", FanOnFlowFracDes));
1461 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1462 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1463 : }
1464 : }
1465 : }
1466 : }
1467 : }
1468 : }
1469 :
1470 34 : IsAutoSize = false;
1471 34 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow == AutoSize) { //.or.()) THEN
1472 34 : IsAutoSize = true;
1473 : }
1474 34 : if ((state.dataSize->CurZoneEqNum > 0) && (CurTermUnitSizingNum > 0)) {
1475 34 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1476 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow > 0.0) {
1477 0 : BaseSizer::reportSizerOutput(state,
1478 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1479 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1480 : "User-Specified Maximum Reheat Water Flow Rate [m3/s]",
1481 0 : state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow);
1482 : }
1483 : } else {
1484 34 : CheckZoneSizing(state, state.dataPowerInductionUnits->PIU(PIUNum).UnitType, state.dataPowerInductionUnits->PIU(PIUNum).Name);
1485 34 : if (UtilityRoutines::SameString(HCoilNamesUC[static_cast<int>(state.dataPowerInductionUnits->PIU(PIUNum).HCoilType)],
1486 34 : "Coil:Heating:Water")) {
1487 :
1488 34 : CoilWaterInletNode =
1489 68 : GetCoilWaterInletNode(state, "Coil:Heating:Water", state.dataPowerInductionUnits->PIU(PIUNum).HCoil, ErrorsFound);
1490 34 : CoilWaterOutletNode =
1491 68 : GetCoilWaterOutletNode(state, "Coil:Heating:Water", state.dataPowerInductionUnits->PIU(PIUNum).HCoil, ErrorsFound);
1492 34 : if (IsAutoSize) {
1493 68 : PltSizHeatNum = MyPlantSizingIndex(state,
1494 : "Coil:Heating:Water",
1495 34 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
1496 : CoilWaterInletNode,
1497 : CoilWaterOutletNode,
1498 : ErrorsFound);
1499 34 : if (PltSizHeatNum > 0) {
1500 :
1501 34 : if (state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesHeatMassFlow >= SmallAirVolFlow) {
1502 102 : CoilInTemp = state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesHeatCoilInTempTU *
1503 34 : state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac +
1504 68 : state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).ZoneTempAtHeatPeak *
1505 34 : (1.0 - state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac);
1506 34 : CoilOutTemp = state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).HeatDesTemp;
1507 34 : CoilOutHumRat = state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).HeatDesHumRat;
1508 34 : DesMassFlow = state.dataEnvrn->StdRhoAir * TermUnitSizing(CurTermUnitSizingNum).AirVolFlow;
1509 34 : DesCoilLoad = PsyCpAirFnW(CoilOutHumRat) * DesMassFlow * (CoilOutTemp - CoilInTemp);
1510 :
1511 34 : rho =
1512 68 : GetDensityGlycol(state,
1513 34 : state.dataPlnt->PlantLoop(state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc.loopNum).FluidName,
1514 : DataGlobalConstants::HWInitConvTemp,
1515 34 : state.dataPlnt->PlantLoop(state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc.loopNum).FluidIndex,
1516 : RoutineName);
1517 68 : Cp = GetSpecificHeatGlycol(
1518 : state,
1519 34 : state.dataPlnt->PlantLoop(state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc.loopNum).FluidName,
1520 : DataGlobalConstants::HWInitConvTemp,
1521 34 : state.dataPlnt->PlantLoop(state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc.loopNum).FluidIndex,
1522 : RoutineName);
1523 :
1524 34 : MaxVolHotWaterFlowDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
1525 : } else {
1526 0 : MaxVolHotWaterFlowDes = 0.0;
1527 : }
1528 : } else {
1529 0 : ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
1530 0 : ShowContinueError(state,
1531 0 : "Occurs in" + state.dataPowerInductionUnits->PIU(PIUNum).UnitType +
1532 0 : " Object=" + state.dataPowerInductionUnits->PIU(PIUNum).Name);
1533 0 : ErrorsFound = true;
1534 : }
1535 : }
1536 34 : if (IsAutoSize) {
1537 34 : state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow = MaxVolHotWaterFlowDes;
1538 102 : BaseSizer::reportSizerOutput(state,
1539 34 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1540 34 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1541 : "Design Size Maximum Reheat Water Flow Rate [m3/s]",
1542 34 : MaxVolHotWaterFlowDes);
1543 136 : BaseSizer::reportSizerOutput(state,
1544 34 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1545 34 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1546 : "Design Size Reheat Coil Inlet Air Temperature [C]",
1547 68 : state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesHeatCoilInTempTU);
1548 136 : BaseSizer::reportSizerOutput(state,
1549 34 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1550 34 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1551 : "Design Size Reheat Coil Inlet Air Humidity Ratio [kgWater/kgDryAir]",
1552 68 : state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesHeatCoilInHumRatTU);
1553 : } else { // Hardsize with sizing data
1554 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow > 0.0 && MaxVolHotWaterFlowDes > 0.0) {
1555 0 : MaxVolHotWaterFlowUser = state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow;
1556 0 : BaseSizer::reportSizerOutput(state,
1557 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1558 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1559 : "Design Size Maximum Reheat Water Flow Rate [m3/s]",
1560 : MaxVolHotWaterFlowDes,
1561 : "User-Specified Maximum Reheat Water Flow Rate [m3/s]",
1562 0 : MaxVolHotWaterFlowUser);
1563 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1564 0 : if ((std::abs(MaxVolHotWaterFlowDes - MaxVolHotWaterFlowUser) / MaxVolHotWaterFlowUser) >
1565 0 : state.dataSize->AutoVsHardSizingThreshold) {
1566 0 : ShowMessage(state,
1567 0 : "SizePIU: Potential issue with equipment sizing for " +
1568 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType + ' ' +
1569 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name);
1570 0 : ShowContinueError(state,
1571 0 : format("User-Specified Maximum Reheat Water Flow Rate of {:.5R} [m3/s]", MaxVolHotWaterFlowUser));
1572 0 : ShowContinueError(
1573 0 : state, format("differs from Design Size Maximum Reheat Water Flow Rate of {:.5R} [m3/s]", MaxVolHotWaterFlowDes));
1574 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1575 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1576 : }
1577 : }
1578 : }
1579 : }
1580 : } else {
1581 0 : state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow = 0.0;
1582 : }
1583 : }
1584 : }
1585 :
1586 34 : IsAutoSize = false;
1587 34 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotSteamFlow == AutoSize) {
1588 0 : IsAutoSize = true;
1589 : }
1590 34 : if ((state.dataSize->CurZoneEqNum > 0) && (CurTermUnitSizingNum > 0)) {
1591 34 : if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation continue
1592 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow > 0.0) {
1593 0 : BaseSizer::reportSizerOutput(state,
1594 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1595 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1596 : "User-Specified Maximum Reheat Steam Flow Rate [m3/s]",
1597 0 : state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow);
1598 : }
1599 : } else {
1600 34 : if (UtilityRoutines::SameString(HCoilNames[static_cast<int>(state.dataPowerInductionUnits->PIU(PIUNum).HCoilType)],
1601 34 : "Coil:Heating:Steam")) {
1602 :
1603 0 : CoilSteamInletNode =
1604 0 : GetCoilSteamInletNode(state, "Coil:Heating:Steam", state.dataPowerInductionUnits->PIU(PIUNum).HCoil, ErrorsFound);
1605 0 : CoilSteamOutletNode =
1606 0 : GetCoilSteamOutletNode(state, "Coil:Heating:Steam", state.dataPowerInductionUnits->PIU(PIUNum).HCoil, ErrorsFound);
1607 0 : if (IsAutoSize) {
1608 0 : PltSizHeatNum = MyPlantSizingIndex(state,
1609 : "Coil:Heating:Steam",
1610 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
1611 : CoilSteamInletNode,
1612 : CoilSteamOutletNode,
1613 : ErrorsFound);
1614 0 : if (PltSizHeatNum > 0) {
1615 :
1616 0 : if (state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesHeatMassFlow >= SmallAirVolFlow) {
1617 0 : CoilInTemp = state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).DesHeatCoilInTempTU *
1618 0 : state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac +
1619 0 : state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).ZoneTempAtHeatPeak *
1620 0 : (1.0 - state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac);
1621 0 : CoilOutTemp = state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).HeatDesTemp;
1622 0 : CoilOutHumRat = state.dataSize->TermUnitFinalZoneSizing(CurTermUnitSizingNum).HeatDesHumRat;
1623 0 : DesMassFlow = state.dataEnvrn->StdRhoAir * TermUnitSizing(CurTermUnitSizingNum).AirVolFlow;
1624 0 : DesCoilLoad = PsyCpAirFnW(CoilOutHumRat) * DesMassFlow * (CoilOutTemp - CoilInTemp);
1625 0 : TempSteamIn = 100.00;
1626 0 : EnthSteamInDry = GetSatEnthalpyRefrig(
1627 0 : state, fluidNameSteam, TempSteamIn, 1.0, state.dataPowerInductionUnits->PIU(PIUNum).HCoil_FluidIndex, RoutineName);
1628 0 : EnthSteamOutWet = GetSatEnthalpyRefrig(
1629 0 : state, fluidNameSteam, TempSteamIn, 0.0, state.dataPowerInductionUnits->PIU(PIUNum).HCoil_FluidIndex, RoutineName);
1630 0 : LatentHeatSteam = EnthSteamInDry - EnthSteamOutWet;
1631 0 : SteamDensity = GetSatDensityRefrig(
1632 0 : state, fluidNameSteam, TempSteamIn, 1.0, state.dataPowerInductionUnits->PIU(PIUNum).HCoil_FluidIndex, RoutineName);
1633 0 : Cp = GetSpecificHeatGlycol(
1634 0 : state, fluidNameWater, state.dataSize->PlantSizData(PltSizHeatNum).ExitTemp, DummyWaterIndex, RoutineName);
1635 0 : MaxVolHotSteamFlowDes =
1636 0 : DesCoilLoad / (SteamDensity * (LatentHeatSteam + state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp));
1637 : } else {
1638 0 : MaxVolHotSteamFlowDes = 0.0;
1639 : }
1640 : } else {
1641 0 : ShowSevereError(state, "Autosizing of Steam flow requires a heating loop Sizing:Plant object");
1642 0 : ShowContinueError(state,
1643 0 : "Occurs in" + state.dataPowerInductionUnits->PIU(PIUNum).UnitType +
1644 0 : " Object=" + state.dataPowerInductionUnits->PIU(PIUNum).Name);
1645 0 : ErrorsFound = true;
1646 : }
1647 : }
1648 0 : if (IsAutoSize) {
1649 0 : state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotSteamFlow = MaxVolHotSteamFlowDes;
1650 0 : BaseSizer::reportSizerOutput(state,
1651 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1652 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1653 : "Design Size Maximum Reheat Steam Flow [m3/s]",
1654 0 : MaxVolHotSteamFlowDes);
1655 : } else {
1656 0 : if (state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotSteamFlow > 0.0 && MaxVolHotSteamFlowDes > 0.0) {
1657 0 : MaxVolHotSteamFlowUser = state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotSteamFlow;
1658 0 : BaseSizer::reportSizerOutput(state,
1659 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1660 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name,
1661 : "Design Size Maximum Reheat Steam Flow [m3/s]",
1662 : MaxVolHotSteamFlowDes,
1663 : "User-Specified Maximum Reheat Steam Flow [m3/s]",
1664 0 : MaxVolHotSteamFlowUser);
1665 0 : if (state.dataGlobal->DisplayExtraWarnings) {
1666 0 : if ((std::abs(MaxVolHotSteamFlowDes - MaxVolHotSteamFlowUser) / MaxVolHotSteamFlowUser) >
1667 0 : state.dataSize->AutoVsHardSizingThreshold) {
1668 0 : ShowMessage(state,
1669 0 : "SizePIU: Potential issue with equipment sizing for " +
1670 0 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType + ' ' +
1671 0 : state.dataPowerInductionUnits->PIU(PIUNum).Name);
1672 0 : ShowContinueError(state, format("User-Specified Maximum Reheat Steam Flow of {:.5R} [m3/s]", MaxVolHotSteamFlowUser));
1673 0 : ShowContinueError(
1674 0 : state, format("differs from Design Size Maximum Reheat Steam Flow of {:.5R} [m3/s]", MaxVolHotSteamFlowDes));
1675 0 : ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
1676 0 : ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
1677 : }
1678 : }
1679 : }
1680 : }
1681 : } else {
1682 34 : state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotSteamFlow = 0.0;
1683 : }
1684 : }
1685 : }
1686 :
1687 34 : if (CurTermUnitSizingNum > 0) {
1688 34 : TermUnitSizing(CurTermUnitSizingNum).MinFlowFrac = state.dataPowerInductionUnits->PIU(PIUNum).MinPriAirFlowFrac;
1689 34 : TermUnitSizing(CurTermUnitSizingNum).MaxHWVolFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotWaterFlow;
1690 34 : TermUnitSizing(CurTermUnitSizingNum).MaxSTVolFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxVolHotSteamFlow;
1691 34 : TermUnitSizing(CurTermUnitSizingNum).DesHeatingLoad = DesCoilLoad; // coil report
1692 34 : TermUnitSizing(CurTermUnitSizingNum).InducesPlenumAir = state.dataPowerInductionUnits->PIU(PIUNum).InducesPlenumAir;
1693 34 : if (state.dataPowerInductionUnits->PIU(PIUNum).HCoilType == HtgCoilType::SimpleHeating) {
1694 102 : SetCoilDesFlow(state,
1695 34 : HCoilNamesUC[static_cast<int>(state.dataPowerInductionUnits->PIU(PIUNum).HCoilType)],
1696 34 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
1697 34 : TermUnitSizing(CurTermUnitSizingNum).AirVolFlow,
1698 : ErrorsFound);
1699 : }
1700 : }
1701 :
1702 34 : if (ErrorsFound) {
1703 0 : ShowFatalError(state, "Preceding sizing errors cause program termination");
1704 : }
1705 34 : }
1706 :
1707 106578 : void CalcSeriesPIU(EnergyPlusData &state,
1708 : int const PIUNum, // number of the current PIU being simulated
1709 : int const ZoneNum, // number of zone being served
1710 : int const ZoneNode, // zone node number
1711 : bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep
1712 : )
1713 : {
1714 :
1715 : // SUBROUTINE INFORMATION:
1716 : // AUTHOR Fred Buhl
1717 : // DATE WRITTEN August 2000
1718 : // MODIFIED na
1719 : // RE-ENGINEERED na
1720 :
1721 : // PURPOSE OF THIS SUBROUTINE:
1722 : // Simulate a series powered induction unit; adjust its primary air flow
1723 : // and reheat coil output to match the zone load.
1724 :
1725 : // METHODOLOGY EMPLOYED:
1726 : // If unit is on and there is a cooling load:
1727 : // (1) simulates mixer and fan at max secondary air flow and heating coil
1728 : // off. Obtains fan temperature increase.
1729 : // (2) Calculates primary and secomdary air flow to meet zone load and
1730 : // resimulates mixer, fan, and (off) coil.
1731 : // If unit is on and there is a heating load
1732 : // (1) sets primary air flow to a minimum.
1733 : // (2) simulates mixer and fan
1734 : // (3) if reheat is hot water, calls ControlCompOutput to simulate hot
1735 : // water coil and adjust water flow to match coil output to the zone load.
1736 : // (4) if reheat is electric or gas calls SimulateHeatingCoilComponents to
1737 : // simulate coil at coil output that matches the zone load
1738 :
1739 : // REFERENCES:
1740 : // na
1741 :
1742 : // Using/Aliasing
1743 : using namespace DataZoneEnergyDemands;
1744 : using FluidProperties::GetDensityGlycol;
1745 : using FluidProperties::GetSpecificHeatGlycol;
1746 : using HeatingCoils::SimulateHeatingCoilComponents;
1747 : using MixerComponent::SimAirMixer;
1748 : using PlantUtilities::SetComponentFlowRate;
1749 : using SteamCoils::SimulateSteamCoilComponents;
1750 : using WaterCoils::SimulateWaterCoilComponents;
1751 :
1752 : // Locals
1753 : // SUBROUTINE ARGUMENT DEFINITIONS:
1754 :
1755 : // SUBROUTINE PARAMETER DEFINITIONS:
1756 :
1757 : // INTERFACE BLOCK SPECIFICATIONS
1758 :
1759 : // DERIVED TYPE DEFINITIONS
1760 : // na
1761 :
1762 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1763 : Real64 QZnReq; // heating or cooling needed by zone [Watts]
1764 : Real64 QToHeatSetPt; // [W] remaining load to heating setpoint
1765 : Real64 QActualHeating; // the heating load seen by the reheat coil [W]
1766 : Real64 PowerMet; // power supplied
1767 106578 : bool UnitOn(true); // TRUE if unit is on
1768 106578 : bool PriOn(true); // TRUE if primary air available
1769 106578 : bool HCoilOn(true); // TRUE if heating coil is on
1770 106578 : int ControlNode(0); // the hot water or cold water inlet node
1771 : Real64 ControlOffset; // tolerance for output control
1772 : Real64 MaxWaterFlow; // maximum water flow for heating or cooling [kg/s]
1773 : Real64 MinWaterFlow; // minimum water flow for heating or cooling [kg/s]
1774 : int OutletNode; // unit air outlet node
1775 : int PriNode; // unit primary air inlet node
1776 : int SecNode; // unit secondary air inlet node
1777 : int HCoilInAirNode; // air inlet node of reheat coil
1778 : Real64 QCoilReq; // required heating coil outlet to meet zone load
1779 : Real64 PriAirMassFlow; // primary air mass flow rate [kg/s]
1780 : Real64 PriAirMassFlowMax; // max primary air mass flow rate [kg/s]
1781 : Real64 PriAirMassFlowMin; // min primary air mass flow rate [kg/s]
1782 : Real64 SecAirMassFlow; // secondary air mass flow rate [kg/s]
1783 : Real64 CpAirZn; // zone air specific heat [J/kg-C]
1784 106578 : Real64 FanDeltaTemp(0.0); // fan temperature rise [C]
1785 106578 : Real64 OutletTempNeeded(0.0); // unit outlet temperature needed to meet cooling load
1786 106578 : Real64 MixTempNeeded(0.0); // mixer outlet temperature needed to meet cooling load
1787 : Real64 MinSteamFlow;
1788 : Real64 MaxSteamFlow;
1789 : Real64 mdot; // local plant fluid flow rate kg/s
1790 : // Initialize local fan flags to global system flags
1791 : bool PIUTurnFansOn =
1792 106578 : (state.dataHVACGlobal->TurnFansOn || state.dataHVACGlobal->TurnZoneFansOnlyOn); // If True, overrides fan schedule and cycles PIU fan on
1793 106578 : bool PIUTurnFansOff = state.dataHVACGlobal->TurnFansOff; // If True, overrides fan schedule and PIUTurnFansOn and cycles PIU fan off
1794 :
1795 : // initialize local variables
1796 106578 : ControlOffset = state.dataPowerInductionUnits->PIU(PIUNum).HotControlOffset;
1797 106578 : OutletNode = state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode;
1798 106578 : PriNode = state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode;
1799 106578 : SecNode = state.dataPowerInductionUnits->PIU(PIUNum).SecAirInNode;
1800 106578 : HCoilInAirNode = state.dataPowerInductionUnits->PIU(PIUNum).HCoilInAirNode;
1801 106578 : ControlNode = state.dataPowerInductionUnits->PIU(PIUNum).HotControlNode;
1802 106578 : PriAirMassFlow = state.dataLoopNodes->Node(PriNode).MassFlowRate;
1803 106578 : PriAirMassFlowMax = state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail;
1804 106578 : PriAirMassFlowMin = state.dataLoopNodes->Node(PriNode).MassFlowRateMinAvail;
1805 106578 : SecAirMassFlow = state.dataLoopNodes->Node(SecNode).MassFlowRate;
1806 106578 : QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired;
1807 106578 : QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP;
1808 106578 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(ZoneNode).HumRat);
1809 :
1810 : // On the first HVAC iteration the system values are given to the controller, but after that
1811 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
1812 106578 : if (ControlNode > 0) {
1813 106578 : if (FirstHVACIteration) {
1814 51096 : MaxWaterFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxHotWaterFlow;
1815 51096 : MinWaterFlow = state.dataPowerInductionUnits->PIU(PIUNum).MinHotWaterFlow;
1816 51096 : MaxSteamFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxHotWaterFlow; // Need TO change THESE******************************
1817 51096 : MinSteamFlow = state.dataPowerInductionUnits->PIU(PIUNum).MinHotWaterFlow;
1818 : } else {
1819 55482 : MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
1820 55482 : MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
1821 55482 : MaxSteamFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
1822 55482 : MinSteamFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
1823 : }
1824 : }
1825 106578 : if (GetCurrentScheduleValue(state, state.dataPowerInductionUnits->PIU(PIUNum).SchedPtr) <= 0.0) UnitOn = false;
1826 106578 : if ((GetCurrentScheduleValue(state, state.dataPowerInductionUnits->PIU(PIUNum).FanAvailSchedPtr) <= 0.0 || PIUTurnFansOff) && !PIUTurnFansOn)
1827 98 : UnitOn = false;
1828 106578 : if (PriAirMassFlow <= SmallMassFlow || PriAirMassFlowMax <= SmallMassFlow) PriOn = false;
1829 : // Set the mass flow rates
1830 106578 : if (UnitOn) {
1831 : // unit is on
1832 106480 : if (!PriOn) {
1833 : // no primary air flow
1834 4430 : PriAirMassFlow = 0.0;
1835 : // PIU fan off if there is no heating load, also reset fan flag if fan should be off
1836 4430 : if (QZnReq <= SmallLoad) {
1837 2035 : SecAirMassFlow = 0.0;
1838 2035 : PIUTurnFansOn = false;
1839 : } else {
1840 2395 : SecAirMassFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow;
1841 : }
1842 102050 : } else if (state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) || std::abs(QZnReq) < SmallLoad) {
1843 : // in deadband or very small load: set primary air flow to the minimum
1844 21863 : PriAirMassFlow = PriAirMassFlowMin;
1845 21863 : SecAirMassFlow = max(0.0, state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow - PriAirMassFlow);
1846 80187 : } else if (QZnReq > SmallLoad) {
1847 : // heating: set primary air flow to the minimum
1848 43976 : PriAirMassFlow = PriAirMassFlowMin;
1849 43976 : SecAirMassFlow = max(0.0, state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow - PriAirMassFlow);
1850 : } else {
1851 : // cooling: set the primary air flow rate to meet the load.
1852 : // First calculate the fan temperature rise
1853 : // use only secondary air for this calculation
1854 36211 : state.dataLoopNodes->Node(PriNode).MassFlowRate = 0.0;
1855 36211 : state.dataLoopNodes->Node(SecNode).MassFlowRate = state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow;
1856 72422 : SimAirMixer(
1857 72422 : state, state.dataPowerInductionUnits->PIU(PIUNum).MixerName, state.dataPowerInductionUnits->PIU(PIUNum).Mixer_Num); // fire the mixer
1858 36211 : if (state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num == DataHVACGlobals::FanType_SystemModelObject) {
1859 3397 : state.dataHVACFan->fanObjs[state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index]->simulate(
1860 : state, _, PIUTurnFansOn, PIUTurnFansOff, _);
1861 32814 : } else if (state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num == DataHVACGlobals::FanType_SimpleConstVolume) {
1862 98442 : Fans::SimulateFanComponents(state,
1863 32814 : state.dataPowerInductionUnits->PIU(PIUNum).FanName,
1864 : FirstHVACIteration,
1865 32814 : state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index,
1866 : _,
1867 : PIUTurnFansOn,
1868 : PIUTurnFansOff); // fire the fan
1869 : }
1870 :
1871 36211 : FanDeltaTemp = state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(SecNode).Temp;
1872 : // using the required zone load, calculate the air temperature needed to meet the load
1873 : // PIU(PIUNum)%MaxTotAirMassFlow * CpAirZn * (OutletTempNeeded - state.dataLoopNodes->Node(ZoneNodeNum)%Temp) = QZnReq
1874 36211 : OutletTempNeeded =
1875 36211 : state.dataLoopNodes->Node(ZoneNode).Temp + QZnReq / (state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow * CpAirZn);
1876 36211 : MixTempNeeded = OutletTempNeeded - FanDeltaTemp;
1877 36211 : if (MixTempNeeded <= state.dataLoopNodes->Node(PriNode).Temp) {
1878 8606 : PriAirMassFlow = PriAirMassFlowMax;
1879 27605 : } else if (MixTempNeeded >= state.dataLoopNodes->Node(PriNode).Temp && MixTempNeeded >= state.dataLoopNodes->Node(SecNode).Temp) {
1880 0 : PriAirMassFlow = PriAirMassFlowMin;
1881 : } else {
1882 82815 : PriAirMassFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow *
1883 27605 : (state.dataLoopNodes->Node(SecNode).Temp - MixTempNeeded) /
1884 27605 : max(SmallTempDiff, state.dataLoopNodes->Node(SecNode).Temp - state.dataLoopNodes->Node(PriNode).Temp);
1885 27605 : PriAirMassFlow = min(max(PriAirMassFlow, PriAirMassFlowMin), PriAirMassFlowMax);
1886 : }
1887 36211 : SecAirMassFlow = max(0.0, state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow - PriAirMassFlow);
1888 : }
1889 : } else {
1890 : // unit is off ; no flow
1891 98 : PriAirMassFlow = 0.0;
1892 98 : SecAirMassFlow = 0.0;
1893 : }
1894 : // Set inlet node flowrates
1895 106578 : state.dataLoopNodes->Node(PriNode).MassFlowRate = PriAirMassFlow;
1896 106578 : state.dataLoopNodes->Node(SecNode).MassFlowRate = SecAirMassFlow;
1897 106578 : if (PriAirMassFlowMax == 0) {
1898 4522 : state.dataPowerInductionUnits->PIU(PIUNum).PriDamperPosition = 0;
1899 : } else {
1900 102056 : state.dataPowerInductionUnits->PIU(PIUNum).PriDamperPosition = PriAirMassFlow / PriAirMassFlowMax;
1901 : }
1902 : // now that inlet airflows have been set, the terminal bos components can be simulated.
1903 :
1904 : // fire the mixer
1905 106578 : SimAirMixer(state, state.dataPowerInductionUnits->PIU(PIUNum).MixerName, state.dataPowerInductionUnits->PIU(PIUNum).Mixer_Num);
1906 : // fire the fan
1907 106578 : if (state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num == DataHVACGlobals::FanType_SystemModelObject) {
1908 6948 : state.dataHVACFan->fanObjs[state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index]->simulate(state, _, PIUTurnFansOn, PIUTurnFansOff, _);
1909 99630 : } else if (state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num == DataHVACGlobals::FanType_SimpleConstVolume) {
1910 298890 : Fans::SimulateFanComponents(state,
1911 99630 : state.dataPowerInductionUnits->PIU(PIUNum).FanName,
1912 : FirstHVACIteration,
1913 99630 : state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index,
1914 : _,
1915 : PIUTurnFansOn,
1916 : PIUTurnFansOff); // fire the fan
1917 : }
1918 : // check if heating coil is off
1919 213156 : QActualHeating = QToHeatSetPt - state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
1920 106578 : (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp);
1921 369012 : if ((!UnitOn) || (QActualHeating < SmallLoad) ||
1922 202296 : (state.dataHeatBalFanSys->TempControlType(ZoneNum) == DataHVACGlobals::ThermostatType::SingleCooling) ||
1923 : (PriAirMassFlow > PriAirMassFlowMin)) {
1924 60236 : HCoilOn = false;
1925 : }
1926 : // fire the heating coil
1927 :
1928 106578 : switch (state.dataPowerInductionUnits->PIU(PIUNum).HCoilType) {
1929 :
1930 106578 : case HtgCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
1931 106578 : if (!HCoilOn) {
1932 : // call the reheat coil with the NO FLOW condition
1933 60236 : mdot = 0.0;
1934 180708 : SetComponentFlowRate(state,
1935 : mdot,
1936 60236 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlNode,
1937 60236 : state.dataPowerInductionUnits->PIU(PIUNum).HotCoilOutNodeNum,
1938 60236 : state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc);
1939 :
1940 180708 : SimulateWaterCoilComponents(
1941 120472 : state, state.dataPowerInductionUnits->PIU(PIUNum).HCoil, FirstHVACIteration, state.dataPowerInductionUnits->PIU(PIUNum).HCoil_Index);
1942 : } else {
1943 : // control water flow to obtain output matching QZnReq
1944 324394 : ControlCompOutput(state,
1945 46342 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
1946 46342 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
1947 46342 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_Index,
1948 : FirstHVACIteration,
1949 : QActualHeating,
1950 : ControlNode,
1951 : MaxWaterFlow,
1952 : MinWaterFlow,
1953 : ControlOffset,
1954 46342 : state.dataPowerInductionUnits->PIU(PIUNum).ControlCompTypeNum,
1955 46342 : state.dataPowerInductionUnits->PIU(PIUNum).CompErrIndex,
1956 : HCoilInAirNode,
1957 : OutletNode,
1958 : _,
1959 : _,
1960 : _,
1961 46342 : state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc);
1962 : }
1963 106578 : break;
1964 : }
1965 0 : case HtgCoilType::SteamAirHeating: { // COIL:STEAM:AIRHEATING
1966 0 : if (!HCoilOn) {
1967 0 : QCoilReq = 0.0;
1968 : } else {
1969 0 : QCoilReq = QToHeatSetPt - state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
1970 0 : (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp);
1971 : }
1972 0 : SimulateSteamCoilComponents(state,
1973 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
1974 : FirstHVACIteration,
1975 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_Index,
1976 : QCoilReq);
1977 :
1978 0 : break;
1979 : }
1980 0 : case HtgCoilType::Electric: { // COIL:ELECTRIC:HEATING
1981 0 : if (!HCoilOn) {
1982 0 : QCoilReq = 0.0;
1983 : } else {
1984 0 : QCoilReq = QToHeatSetPt - state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
1985 0 : (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp);
1986 : }
1987 0 : SimulateHeatingCoilComponents(state,
1988 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
1989 : FirstHVACIteration,
1990 : QCoilReq,
1991 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_Index);
1992 :
1993 0 : break;
1994 : }
1995 0 : case HtgCoilType::Gas: { // COIL:GAS:HEATING
1996 0 : if (!HCoilOn) {
1997 0 : QCoilReq = 0.0;
1998 : } else {
1999 0 : QCoilReq = QToHeatSetPt - state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
2000 0 : (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp);
2001 : }
2002 0 : SimulateHeatingCoilComponents(state,
2003 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
2004 : FirstHVACIteration,
2005 : QCoilReq,
2006 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_Index);
2007 0 : break;
2008 : }
2009 0 : default:
2010 0 : break;
2011 : }
2012 :
2013 213156 : PowerMet = state.dataLoopNodes->Node(OutletNode).MassFlowRate *
2014 213156 : (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(ZoneNode).HumRat) -
2015 106578 : PsyHFnTdbW(state.dataLoopNodes->Node(ZoneNode).Temp, state.dataLoopNodes->Node(ZoneNode).HumRat));
2016 106578 : state.dataPowerInductionUnits->PIU(PIUNum).HeatingRate = max(0.0, PowerMet);
2017 106578 : state.dataPowerInductionUnits->PIU(PIUNum).SensCoolRate = std::abs(min(DataPrecisionGlobals::constant_zero, PowerMet));
2018 106578 : if (state.dataLoopNodes->Node(OutletNode).MassFlowRate == 0.0) {
2019 2135 : state.dataLoopNodes->Node(PriNode).MassFlowRate = 0.0;
2020 2135 : state.dataLoopNodes->Node(SecNode).MassFlowRate = 0.0;
2021 : }
2022 106578 : if (state.dataPowerInductionUnits->PIU(PIUNum).InducesPlenumAir) {
2023 3650 : state.dataHVACGlobal->PlenumInducedMassFlow = state.dataLoopNodes->Node(SecNode).MassFlowRate;
2024 : } else {
2025 102928 : state.dataHVACGlobal->PlenumInducedMassFlow = 0.0;
2026 : }
2027 106578 : state.dataDefineEquipment->AirDistUnit(state.dataPowerInductionUnits->PIU(PIUNum).ADUNum).MassFlowRatePlenInd =
2028 106578 : state.dataHVACGlobal->PlenumInducedMassFlow;
2029 106578 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMax = state.dataPowerInductionUnits->PIU(PIUNum).MaxTotAirMassFlow;
2030 106578 : }
2031 :
2032 14250 : void CalcParallelPIU(EnergyPlusData &state,
2033 : int const PIUNum, // number of the current PIU being simulated
2034 : int const ZoneNum, // number of zone being served
2035 : int const ZoneNode, // zone node number
2036 : bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep
2037 : )
2038 : {
2039 :
2040 : // SUBROUTINE INFORMATION:
2041 : // AUTHOR Fred Buhl
2042 : // DATE WRITTEN August 2000
2043 : // MODIFIED September 2016, March 2017
2044 :
2045 : // PURPOSE OF THIS SUBROUTINE:
2046 : // Simulate a parallel powered induction unit; adjust its primary air flow
2047 : // and reheat coil output to match the zone load.
2048 :
2049 : // METHODOLOGY EMPLOYED:
2050 : // If unit is on and there is a cooling load:
2051 : // (1) simulate fan at max secondary air flow and heating coil
2052 : // off. Obtains fan temperature increase.
2053 : // (2) Calculates primary and secomdary air flow to meet zone load.
2054 : // (a) Assume fan is off and calculate primary air flow to meet cooling load.
2055 : // (b1) If calculated primary air flow is above the fan turn on ratio, fan is off.
2056 : // Otherwise fan is on; calculate mixed secondary and primary air flow that
2057 : // will meet the zone load
2058 : // (b2) If the fan turn on ratio is zero, then the fan is on only if reheat is needed.
2059 : // (3) Simulate fan, mixer, and (off) heating coil to obtain zone inlet conditions.
2060 : // If unit is on and there is a heating load
2061 : // (1) sets primary air flow to a minimum.
2062 : // (2) simulates fan and mixer
2063 : // (3) if reheat is hot water, calls ControlCompOutput to simulate hot
2064 : // water coil and adjust water flow to match coil output to the zone load.
2065 : // (4) if reheat is electric or gas calls SimulateHeatingCoilComponents to
2066 : // simulate coil at coil output that matches the zone load
2067 :
2068 : using namespace DataZoneEnergyDemands;
2069 : using HeatingCoils::SimulateHeatingCoilComponents;
2070 : using MixerComponent::SimAirMixer;
2071 : using PlantUtilities::SetComponentFlowRate;
2072 : using SteamCoils::SimulateSteamCoilComponents;
2073 : using WaterCoils::SimulateWaterCoilComponents;
2074 :
2075 : Real64 QZnReq; // heating or cooling needed by zone [Watts]
2076 : Real64 QToHeatSetPt; // [W] remaining load to heating setpoint
2077 : Real64 QActualHeating; // the heating load seen by the reheat coil [W]
2078 : Real64 PowerMet; // power supplied
2079 14250 : bool UnitOn(true); // TRUE if unit is on
2080 14250 : bool PriOn(true); // TRUE if primary air available
2081 14250 : bool HCoilOn(true); // TRUE if heating coil is on
2082 14250 : int ControlNode(0); // the hot water or cold water inlet node
2083 : Real64 ControlOffset; // tolerance for output control
2084 : Real64 MaxWaterFlow; // maximum water flow for heating or cooling [kg/s]
2085 : Real64 MinWaterFlow; // minimum water flow for heating or cooling [kg/s]
2086 : int OutletNode; // unit air outlet node
2087 : int PriNode; // unit primary air inlet node
2088 : int SecNode; // unit secondary air inlet node
2089 : int HCoilInAirNode; // air inlet node of reheat coil
2090 : Real64 QCoilReq; // required heating coil outlet to meet zone load
2091 : Real64 PriAirMassFlow; // primary air mass flow rate [kg/s]
2092 : Real64 PriAirMassFlowMax; // max primary air mass flow rate [kg/s]
2093 : Real64 PriAirMassFlowMin; // min primary air mass flow rate [kg/s]
2094 : Real64 SecAirMassFlow; // secondary air mass flow rate [kg/s]
2095 : Real64 CpAirZn; // zone air specific heat [J/kg-C]
2096 14250 : Real64 FanDeltaTemp(0.0); // fan temperature rise [C]
2097 : Real64 mdot; // local fluid flow rate kg/s
2098 :
2099 : // initialize local variables
2100 14250 : ControlOffset = state.dataPowerInductionUnits->PIU(PIUNum).HotControlOffset;
2101 14250 : OutletNode = state.dataPowerInductionUnits->PIU(PIUNum).OutAirNode;
2102 14250 : PriNode = state.dataPowerInductionUnits->PIU(PIUNum).PriAirInNode;
2103 14250 : SecNode = state.dataPowerInductionUnits->PIU(PIUNum).SecAirInNode;
2104 14250 : HCoilInAirNode = state.dataPowerInductionUnits->PIU(PIUNum).HCoilInAirNode;
2105 14250 : ControlNode = state.dataPowerInductionUnits->PIU(PIUNum).HotControlNode;
2106 14250 : PriAirMassFlow = state.dataLoopNodes->Node(PriNode).MassFlowRate;
2107 14250 : PriAirMassFlowMax = state.dataLoopNodes->Node(PriNode).MassFlowRateMaxAvail;
2108 14250 : PriAirMassFlowMin = state.dataLoopNodes->Node(PriNode).MassFlowRateMinAvail;
2109 14250 : SecAirMassFlow = state.dataLoopNodes->Node(SecNode).MassFlowRate;
2110 14250 : QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputRequired;
2111 14250 : QToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP;
2112 14250 : CpAirZn = PsyCpAirFnW(state.dataLoopNodes->Node(ZoneNode).HumRat);
2113 : // Initialize local fan flags to global system flags
2114 : bool PIUTurnFansOn =
2115 14250 : (state.dataHVACGlobal->TurnFansOn || state.dataHVACGlobal->TurnZoneFansOnlyOn); // If True, overrides fan schedule and cycles PIU fan on
2116 14250 : bool PIUTurnFansOff = state.dataHVACGlobal->TurnFansOff; // If True, overrides fan schedule and PIUTurnFansOn and cycles PIU fan off
2117 :
2118 : // On the first HVAC iteration the system values are given to the controller, but after that
2119 : // the demand limits are in place and there needs to be feedback to the Zone Equipment
2120 14250 : if (ControlNode > 0) {
2121 14250 : if (FirstHVACIteration) {
2122 7134 : MaxWaterFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxHotWaterFlow;
2123 7134 : MinWaterFlow = state.dataPowerInductionUnits->PIU(PIUNum).MinHotWaterFlow;
2124 : } else {
2125 7116 : MaxWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMaxAvail;
2126 7116 : MinWaterFlow = state.dataLoopNodes->Node(ControlNode).MassFlowRateMinAvail;
2127 : }
2128 : }
2129 14250 : if (GetCurrentScheduleValue(state, state.dataPowerInductionUnits->PIU(PIUNum).SchedPtr) <= 0.0) UnitOn = false;
2130 14250 : if (PriAirMassFlow <= SmallMassFlow || PriAirMassFlowMax <= SmallMassFlow) PriOn = false;
2131 : // Set the mass flow rates
2132 14250 : if (UnitOn) {
2133 : // unit is on
2134 : // Calculate if reheat is needed
2135 14236 : bool ReheatRequired = false;
2136 : Real64 qMinPrimary =
2137 14236 : PriAirMassFlowMin * (CpAirZn * min(-SmallTempDiff, (state.dataLoopNodes->Node(PriNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp)));
2138 14236 : if (qMinPrimary < QToHeatSetPt) ReheatRequired = true;
2139 :
2140 14236 : if (!PriOn) {
2141 : // no primary air flow
2142 767 : PriAirMassFlow = 0.0;
2143 : // PIU fan off if there is no heating load, also reset fan flag if fan should be off
2144 767 : if (QZnReq <= SmallLoad) {
2145 46 : SecAirMassFlow = 0.0;
2146 46 : PIUTurnFansOn = false;
2147 : } else {
2148 721 : SecAirMassFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirMassFlow;
2149 721 : PIUTurnFansOn = (state.dataHVACGlobal->TurnFansOn || state.dataHVACGlobal->TurnZoneFansOnlyOn);
2150 : }
2151 13469 : } else if (state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) || std::abs(QZnReq) < SmallLoad) {
2152 : // in deadband or very small load: set primary air flow to the minimum
2153 2600 : PriAirMassFlow = PriAirMassFlowMin;
2154 : // PIU fan off if reheat is not needed, also reset fan flag if fan should be off
2155 2600 : if (ReheatRequired) {
2156 2503 : SecAirMassFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirMassFlow;
2157 2503 : PIUTurnFansOn = true;
2158 : } else {
2159 97 : SecAirMassFlow = 0.0;
2160 97 : PIUTurnFansOn = false;
2161 : }
2162 10869 : } else if (QZnReq > SmallLoad) {
2163 : // heating: set primary air flow to the minimum
2164 5493 : PriAirMassFlow = PriAirMassFlowMin;
2165 5493 : SecAirMassFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirMassFlow;
2166 : } else {
2167 : // cooling: set the primary air flow rate to meet the load.
2168 : // First calculate the fan temperature rise
2169 5376 : state.dataLoopNodes->Node(SecNode).MassFlowRate = state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirMassFlow;
2170 5376 : state.dataLoopNodes->Node(SecNode).MassFlowRateMaxAvail = state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirMassFlow;
2171 5376 : state.dataLoopNodes->Node(PriNode).MassFlowRate = 0.0;
2172 :
2173 5376 : if (state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num == DataHVACGlobals::FanType_SystemModelObject) {
2174 3395 : state.dataHVACFan->fanObjs[state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index]->simulate(
2175 : state, _, PIUTurnFansOn, PIUTurnFansOff, _);
2176 1981 : } else if (state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num == DataHVACGlobals::FanType_SimpleConstVolume) {
2177 5943 : Fans::SimulateFanComponents(state,
2178 1981 : state.dataPowerInductionUnits->PIU(PIUNum).FanName,
2179 : FirstHVACIteration,
2180 1981 : state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index,
2181 : _,
2182 : PIUTurnFansOn,
2183 : PIUTurnFansOff); // fire the fan
2184 : }
2185 10752 : SimAirMixer(
2186 10752 : state, state.dataPowerInductionUnits->PIU(PIUNum).MixerName, state.dataPowerInductionUnits->PIU(PIUNum).Mixer_Num); // fire the mixer
2187 5376 : FanDeltaTemp = state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(SecNode).Temp;
2188 : // Assuming the fan is off, calculate the primary air flow needed to meet the zone cooling demand.
2189 : // CpAir*PriAirMassFlow*(Node(PriNode)%Temp - Node(ZoneNodeNum)%Temp) = QZnReq
2190 5376 : PriAirMassFlow =
2191 5376 : QZnReq / (CpAirZn * min(-SmallTempDiff, (state.dataLoopNodes->Node(PriNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp)));
2192 5376 : PriAirMassFlow = min(max(PriAirMassFlow, PriAirMassFlowMin), PriAirMassFlowMax);
2193 : // check for fan on or off
2194 5376 : if ((PriAirMassFlow > state.dataPowerInductionUnits->PIU(PIUNum).FanOnAirMassFlow) && !ReheatRequired) {
2195 4964 : SecAirMassFlow = 0.0; // Fan is off unless reheat is required; no secondary air; also reset fan flag
2196 4964 : PIUTurnFansOn = false;
2197 : } else {
2198 : // fan is on; recalc primary air flow
2199 : // CpAir*PriAirMassFlow*(Node(PriNode)%Temp - Node(ZoneNodeNum)%Temp) +
2200 : // CpAir*SecAirMassFlow*(Node(SecNode)%Temp + FanDeltaTemp - Node(ZoneNodeNum)%Temp) = QZnReq
2201 412 : PriAirMassFlow =
2202 412 : (QZnReq -
2203 412 : CpAirZn * SecAirMassFlow * (state.dataLoopNodes->Node(SecNode).Temp + FanDeltaTemp - state.dataLoopNodes->Node(ZoneNode).Temp)) /
2204 412 : (CpAirZn * min(-SmallTempDiff, (state.dataLoopNodes->Node(PriNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp)));
2205 412 : PriAirMassFlow = min(max(PriAirMassFlow, PriAirMassFlowMin), PriAirMassFlowMax);
2206 412 : SecAirMassFlow = state.dataPowerInductionUnits->PIU(PIUNum).MaxSecAirMassFlow;
2207 : }
2208 : }
2209 : } else {
2210 : // unit is off; no flow
2211 14 : PriAirMassFlow = 0.0;
2212 14 : SecAirMassFlow = 0.0;
2213 : }
2214 : // Set inlet node flowrates
2215 14250 : state.dataLoopNodes->Node(PriNode).MassFlowRate = PriAirMassFlow;
2216 14250 : state.dataLoopNodes->Node(SecNode).MassFlowRate = SecAirMassFlow;
2217 14250 : state.dataLoopNodes->Node(SecNode).MassFlowRateMaxAvail = SecAirMassFlow;
2218 14250 : if (PriAirMassFlowMax == 0) {
2219 780 : state.dataPowerInductionUnits->PIU(PIUNum).PriDamperPosition = 0;
2220 : } else {
2221 13470 : state.dataPowerInductionUnits->PIU(PIUNum).PriDamperPosition = PriAirMassFlow / PriAirMassFlowMax;
2222 : }
2223 : // now that inlet airflows have been set, the terminal box components can be simulated.
2224 : // fire the fan
2225 :
2226 14250 : if (state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num == DataHVACGlobals::FanType_SystemModelObject) {
2227 6948 : state.dataHVACFan->fanObjs[state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index]->simulate(state, _, PIUTurnFansOn, PIUTurnFansOff, _);
2228 7302 : } else if (state.dataPowerInductionUnits->PIU(PIUNum).Fan_Num == DataHVACGlobals::FanType_SimpleConstVolume) {
2229 21906 : Fans::SimulateFanComponents(state,
2230 7302 : state.dataPowerInductionUnits->PIU(PIUNum).FanName,
2231 : FirstHVACIteration,
2232 7302 : state.dataPowerInductionUnits->PIU(PIUNum).Fan_Index,
2233 : _,
2234 : PIUTurnFansOn,
2235 : PIUTurnFansOff); // fire the fan
2236 : }
2237 : // fire the mixer
2238 14250 : SimAirMixer(state, state.dataPowerInductionUnits->PIU(PIUNum).MixerName, state.dataPowerInductionUnits->PIU(PIUNum).Mixer_Num);
2239 : // check if heating coil is off
2240 28500 : QActualHeating = QToHeatSetPt - state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
2241 14250 : (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp);
2242 51748 : if ((!UnitOn) || (QActualHeating < SmallLoad) ||
2243 29461 : (state.dataHeatBalFanSys->TempControlType(ZoneNum) == DataHVACGlobals::ThermostatType::SingleCooling) ||
2244 : (PriAirMassFlow > PriAirMassFlowMin)) {
2245 8051 : HCoilOn = false;
2246 : }
2247 : // fire the heating coil
2248 14250 : switch (state.dataPowerInductionUnits->PIU(PIUNum).HCoilType) {
2249 :
2250 14250 : case HtgCoilType::SimpleHeating: { // COIL:WATER:SIMPLEHEATING
2251 14250 : if (!HCoilOn) {
2252 : // call the reheat coil with the NO FLOW condition
2253 8051 : mdot = 0.0;
2254 24153 : SetComponentFlowRate(state,
2255 : mdot,
2256 8051 : state.dataPowerInductionUnits->PIU(PIUNum).HotControlNode,
2257 8051 : state.dataPowerInductionUnits->PIU(PIUNum).HotCoilOutNodeNum,
2258 8051 : state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc);
2259 24153 : SimulateWaterCoilComponents(
2260 16102 : state, state.dataPowerInductionUnits->PIU(PIUNum).HCoil, FirstHVACIteration, state.dataPowerInductionUnits->PIU(PIUNum).HCoil_Index);
2261 : } else {
2262 : // control water flow to obtain output matching QZnReq
2263 43393 : ControlCompOutput(state,
2264 6199 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
2265 6199 : state.dataPowerInductionUnits->PIU(PIUNum).UnitType,
2266 6199 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_Index,
2267 : FirstHVACIteration,
2268 : QActualHeating,
2269 : ControlNode,
2270 : MaxWaterFlow,
2271 : MinWaterFlow,
2272 : ControlOffset,
2273 6199 : state.dataPowerInductionUnits->PIU(PIUNum).ControlCompTypeNum,
2274 6199 : state.dataPowerInductionUnits->PIU(PIUNum).CompErrIndex,
2275 : HCoilInAirNode,
2276 : OutletNode,
2277 : _,
2278 : _,
2279 : _,
2280 6199 : state.dataPowerInductionUnits->PIU(PIUNum).HWplantLoc);
2281 : }
2282 14250 : break;
2283 : }
2284 0 : case HtgCoilType::SteamAirHeating: { // COIL:STEAM:AIRHEATING
2285 0 : if (!HCoilOn) {
2286 0 : QCoilReq = 0.0;
2287 : } else {
2288 0 : QCoilReq = QToHeatSetPt - state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
2289 0 : (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp);
2290 : }
2291 0 : SimulateSteamCoilComponents(state,
2292 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
2293 : FirstHVACIteration,
2294 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_Index,
2295 : QCoilReq);
2296 0 : break;
2297 : }
2298 0 : case HtgCoilType::Electric: { // COIL:ELECTRIC:HEATING
2299 0 : if (!HCoilOn) {
2300 0 : QCoilReq = 0.0;
2301 : } else {
2302 0 : QCoilReq = QToHeatSetPt - state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
2303 0 : (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp);
2304 : }
2305 0 : SimulateHeatingCoilComponents(state,
2306 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
2307 : FirstHVACIteration,
2308 : QCoilReq,
2309 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_Index);
2310 :
2311 0 : break;
2312 : }
2313 0 : case HtgCoilType::Gas: { // COIL:GAS:HEATING
2314 0 : if (!HCoilOn) {
2315 0 : QCoilReq = 0.0;
2316 : } else {
2317 0 : QCoilReq = QToHeatSetPt - state.dataLoopNodes->Node(HCoilInAirNode).MassFlowRate * CpAirZn *
2318 0 : (state.dataLoopNodes->Node(HCoilInAirNode).Temp - state.dataLoopNodes->Node(ZoneNode).Temp);
2319 : }
2320 0 : SimulateHeatingCoilComponents(state,
2321 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil,
2322 : FirstHVACIteration,
2323 : QCoilReq,
2324 0 : state.dataPowerInductionUnits->PIU(PIUNum).HCoil_Index);
2325 0 : break;
2326 : }
2327 0 : default:
2328 0 : break;
2329 : }
2330 28500 : PowerMet = state.dataLoopNodes->Node(OutletNode).MassFlowRate *
2331 28500 : (PsyHFnTdbW(state.dataLoopNodes->Node(OutletNode).Temp, state.dataLoopNodes->Node(ZoneNode).HumRat) -
2332 14250 : PsyHFnTdbW(state.dataLoopNodes->Node(ZoneNode).Temp, state.dataLoopNodes->Node(ZoneNode).HumRat));
2333 14250 : state.dataPowerInductionUnits->PIU(PIUNum).HeatingRate = max(0.0, PowerMet);
2334 14250 : state.dataPowerInductionUnits->PIU(PIUNum).SensCoolRate = std::abs(min(DataPrecisionGlobals::constant_zero, PowerMet));
2335 14250 : if (state.dataLoopNodes->Node(OutletNode).MassFlowRate == 0.0) {
2336 70 : state.dataLoopNodes->Node(PriNode).MassFlowRate = 0.0;
2337 70 : state.dataLoopNodes->Node(SecNode).MassFlowRate = 0.0;
2338 : }
2339 14250 : if (state.dataPowerInductionUnits->PIU(PIUNum).InducesPlenumAir) {
2340 3650 : state.dataHVACGlobal->PlenumInducedMassFlow = state.dataLoopNodes->Node(SecNode).MassFlowRate;
2341 : } else {
2342 10600 : state.dataHVACGlobal->PlenumInducedMassFlow = 0.0;
2343 : }
2344 14250 : state.dataDefineEquipment->AirDistUnit(state.dataPowerInductionUnits->PIU(PIUNum).ADUNum).MassFlowRatePlenInd =
2345 14250 : state.dataHVACGlobal->PlenumInducedMassFlow;
2346 14250 : state.dataLoopNodes->Node(OutletNode).MassFlowRateMax = state.dataPowerInductionUnits->PIU(PIUNum).MaxPriAirMassFlow;
2347 14250 : }
2348 :
2349 120828 : void ReportPIU(EnergyPlusData &state, int const PIUNum) // number of the current fan coil unit being simulated
2350 : {
2351 :
2352 : // SUBROUTINE INFORMATION:
2353 : // AUTHOR Fred Buhl
2354 : // DATE WRITTEN August 2000
2355 : // MODIFIED na
2356 : // RE-ENGINEERED na
2357 :
2358 : // PURPOSE OF THIS SUBROUTINE:
2359 : // Fills some of the report variables for the PIU terminal boxes
2360 :
2361 : // METHODOLOGY EMPLOYED:
2362 : // NA
2363 :
2364 : // REFERENCES:
2365 : // na
2366 :
2367 : // Using/Aliasing
2368 120828 : auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
2369 :
2370 : // Locals
2371 : // SUBROUTINE ARGUMENT DEFINITIONS:
2372 :
2373 : // SUBROUTINE PARAMETER DEFINITIONS:
2374 : // na
2375 :
2376 : // INTERFACE BLOCK SPECIFICATIONS
2377 : // na
2378 :
2379 : // DERIVED TYPE DEFINITIONS
2380 : // na
2381 :
2382 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2383 :
2384 120828 : state.dataPowerInductionUnits->PIU(PIUNum).HeatingEnergy =
2385 120828 : state.dataPowerInductionUnits->PIU(PIUNum).HeatingRate * TimeStepSys * DataGlobalConstants::SecInHour;
2386 120828 : state.dataPowerInductionUnits->PIU(PIUNum).SensCoolEnergy =
2387 120828 : state.dataPowerInductionUnits->PIU(PIUNum).SensCoolRate * TimeStepSys * DataGlobalConstants::SecInHour;
2388 :
2389 : // set zone OA Volume flow rate
2390 120828 : state.dataPowerInductionUnits->PIU(PIUNum).CalcOutdoorAirVolumeFlowRate(state);
2391 120828 : }
2392 :
2393 : // ===================== Utilities =====================================
2394 :
2395 40 : bool PIUnitHasMixer(EnergyPlusData &state, std::string_view CompName) // component (mixer) name
2396 : {
2397 :
2398 : // FUNCTION INFORMATION:
2399 : // AUTHOR Linda Lawrie
2400 : // DATE WRITTEN September 2011
2401 : // MODIFIED na
2402 : // RE-ENGINEERED na
2403 :
2404 : // PURPOSE OF THIS FUNCTION:
2405 : // Given a mixer name, this routine determines if that mixer is found on
2406 : // PIUnits.
2407 :
2408 : // Return value
2409 : bool YesNo; // True if found
2410 :
2411 : // FUNCTION LOCAL VARIABLE DECLARATIONS:
2412 : int ItemNum;
2413 :
2414 40 : if (state.dataPowerInductionUnits->GetPIUInputFlag) {
2415 2 : GetPIUs(state);
2416 2 : state.dataPowerInductionUnits->GetPIUInputFlag = false;
2417 : }
2418 :
2419 40 : YesNo = false;
2420 40 : if (state.dataPowerInductionUnits->NumPIUs > 0) {
2421 34 : ItemNum = UtilityRoutines::FindItemInList(CompName, state.dataPowerInductionUnits->PIU, &PowIndUnitData::MixerName);
2422 34 : if (ItemNum > 0) YesNo = true;
2423 : }
2424 :
2425 40 : return YesNo;
2426 : }
2427 :
2428 9 : void PIUInducesPlenumAir(EnergyPlusData &state, int const NodeNum) // induced air node number
2429 : {
2430 :
2431 : // SUBROUTINE INFORMATION:
2432 : // AUTHOR Fred Buhl
2433 : // DATE WRITTEN January 2012
2434 : // MODIFIED na
2435 : // RE-ENGINEERED na
2436 :
2437 : // PURPOSE OF THIS FUNCTION:
2438 : // Marks a PIU air terminal unit as obtaining its induced air from
2439 : // a plenum.
2440 :
2441 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2442 : int PIUIndex;
2443 :
2444 9 : if (state.dataPowerInductionUnits->GetPIUInputFlag) {
2445 2 : GetPIUs(state);
2446 2 : state.dataPowerInductionUnits->GetPIUInputFlag = false;
2447 : }
2448 :
2449 12 : for (PIUIndex = 1; PIUIndex <= state.dataPowerInductionUnits->NumPIUs; ++PIUIndex) {
2450 5 : if (NodeNum == state.dataPowerInductionUnits->PIU(PIUIndex).SecAirInNode) {
2451 2 : state.dataPowerInductionUnits->PIU(PIUIndex).InducesPlenumAir = true;
2452 2 : break;
2453 : }
2454 : }
2455 9 : }
2456 :
2457 120828 : void PowIndUnitData::CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state)
2458 : {
2459 : // calculates zone outdoor air volume flow rate using the supply air flow rate and OA fraction
2460 120828 : if (this->AirLoopNum > 0) {
2461 241588 : this->OutdoorAirFlowRate = (state.dataLoopNodes->Node(this->PriAirInNode).MassFlowRate / state.dataEnvrn->StdRhoAir) *
2462 120794 : state.dataAirLoop->AirLoopFlow(this->AirLoopNum).OAFrac;
2463 : } else {
2464 34 : this->OutdoorAirFlowRate = 0.0;
2465 : }
2466 120828 : }
2467 :
2468 2313 : } // namespace EnergyPlus::PoweredInductionUnits
|