LCOV - code coverage report
Current view: top level - EnergyPlus - PoweredInductionUnits.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 906 1285 70.5 %
Date: 2023-01-17 19:17:23 Functions: 12 12 100.0 %

          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

Generated by: LCOV version 1.13