LCOV - code coverage report
Current view: top level - EnergyPlus - HVACFourPipeBeam.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 613 767 79.9 %
Date: 2023-01-17 19:17:23 Functions: 18 19 94.7 %

          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/AirTerminalUnit.hh>
      57             : #include <EnergyPlus/Autosizing/Base.hh>
      58             : #include <EnergyPlus/BranchNodeConnections.hh>
      59             : #include <EnergyPlus/CurveManager.hh>
      60             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      61             : #include <EnergyPlus/DataContaminantBalance.hh>
      62             : #include <EnergyPlus/DataDefineEquip.hh>
      63             : #include <EnergyPlus/DataEnvironment.hh>
      64             : #include <EnergyPlus/DataHVACGlobals.hh>
      65             : #include <EnergyPlus/DataIPShortCuts.hh>
      66             : #include <EnergyPlus/DataLoopNode.hh>
      67             : #include <EnergyPlus/DataSizing.hh>
      68             : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      69             : #include <EnergyPlus/DataZoneEquipment.hh>
      70             : #include <EnergyPlus/FluidProperties.hh>
      71             : #include <EnergyPlus/General.hh>
      72             : #include <EnergyPlus/GeneralRoutines.hh>
      73             : #include <EnergyPlus/HVACFourPipeBeam.hh>
      74             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      75             : #include <EnergyPlus/NodeInputManager.hh>
      76             : #include <EnergyPlus/OutputProcessor.hh>
      77             : #include <EnergyPlus/Plant/DataPlant.hh>
      78             : #include <EnergyPlus/PlantUtilities.hh>
      79             : #include <EnergyPlus/Psychrometrics.hh>
      80             : #include <EnergyPlus/ScheduleManager.hh>
      81             : #include <EnergyPlus/UtilityRoutines.hh>
      82             : 
      83             : namespace EnergyPlus {
      84             : 
      85             : namespace FourPipeBeam {
      86             : 
      87             :     //    HVACFourPipeBeam::HVACFourPipeBeam(){}
      88             :     ///// Note use of shared_ptr here is not a good pattern, not to be replicated without further discussion.
      89          15 :     std::shared_ptr<AirTerminalUnit> HVACFourPipeBeam::fourPipeBeamFactory(EnergyPlusData &state, std::string objectName)
      90             :     {
      91             : 
      92             :         using BranchNodeConnections::TestCompSet;
      93             :         using DataLoopNode::ObjectIsNotParent;
      94             :         using DataLoopNode::ObjectIsParent;
      95             :         using NodeInputManager::GetOnlySingleNode;
      96             :         using namespace DataSizing;
      97             :         using Curve::GetCurveIndex;
      98             :         using ScheduleManager::GetScheduleIndex;
      99             :         static constexpr std::string_view routineName("FourPipeBeamFactory "); // include trailing blank space
     100             : 
     101             :         int beamIndex; // loop index
     102             : 
     103          15 :         int NumAlphas(0);  // Number of Alphas for each GetObjectItem call
     104          15 :         int NumNumbers(0); // Number of Numbers for each GetObjectItem call
     105             : 
     106             :         //  certain object in the input file
     107             :         int IOStatus; // Used in GetObjectItem
     108          15 :         bool errFlag = false;
     109          15 :         bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
     110          15 :         bool found = false;
     111             :         int ctrlZone; // controlled zome do loop index
     112             :         int supAirIn; // controlled zone supply air inlet index
     113             :         bool airNodeFound;
     114             :         int aDUIndex;
     115             : 
     116             :         ///// Note use of shared_ptr here is not a good pattern, not to be replicated without further discussion.
     117          30 :         std::shared_ptr<HVACFourPipeBeam> thisBeam(new HVACFourPipeBeam());
     118          15 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     119             :         // find the number of cooled beam units
     120          15 :         cCurrentModuleObject = "AirTerminal:SingleDuct:ConstantVolume:FourPipeBeam";
     121             : 
     122          15 :         NumAlphas = 16;
     123          15 :         NumNumbers = 11;
     124             : 
     125             :         // find beam index from name
     126          15 :         beamIndex = state.dataInputProcessing->inputProcessor->getObjectItemNum(state, cCurrentModuleObject, objectName);
     127          15 :         if (beamIndex > 0) {
     128         105 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     129             :                                                                      cCurrentModuleObject,
     130             :                                                                      beamIndex,
     131          15 :                                                                      state.dataIPShortCut->cAlphaArgs,
     132             :                                                                      NumAlphas,
     133          15 :                                                                      state.dataIPShortCut->rNumericArgs,
     134             :                                                                      NumNumbers,
     135             :                                                                      IOStatus,
     136          15 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     137          15 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     138          15 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     139          15 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     140          15 :             found = true;
     141             :         } else {
     142           0 :             ErrorsFound = true;
     143             :         }
     144             : 
     145          15 :         errFlag = false;
     146          15 :         GlobalNames::VerifyUniqueADUName(state, cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1), errFlag, cCurrentModuleObject + " Name");
     147          15 :         if (errFlag) {
     148           0 :             ErrorsFound = true;
     149             :         }
     150          15 :         thisBeam->name = state.dataIPShortCut->cAlphaArgs(1);
     151          15 :         thisBeam->unitType = cCurrentModuleObject;
     152             : 
     153          15 :         if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
     154           0 :             thisBeam->airAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
     155             :         } else {
     156          15 :             thisBeam->airAvailSchedNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2)); // convert schedule name to pointer
     157          15 :             if (thisBeam->airAvailSchedNum == 0) {
     158           0 :                 ShowSevereError(state,
     159           0 :                                 std::string{routineName} + cCurrentModuleObject + ": invalid " + state.dataIPShortCut->cAlphaFieldNames(2) +
     160           0 :                                     " entered =" + state.dataIPShortCut->cAlphaArgs(2) + " for " + state.dataIPShortCut->cAlphaFieldNames(1) + '=' +
     161           0 :                                     state.dataIPShortCut->cAlphaArgs(1));
     162           0 :                 ErrorsFound = true;
     163             :             }
     164             :         }
     165          15 :         if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     166           0 :             thisBeam->coolingAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
     167             :         } else {
     168          15 :             thisBeam->coolingAvailSchedNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3)); // convert schedule name to index
     169          15 :             if (thisBeam->coolingAvailSchedNum == 0) {
     170           0 :                 ShowSevereError(state,
     171           0 :                                 std::string{routineName} + cCurrentModuleObject + ": invalid " + state.dataIPShortCut->cAlphaFieldNames(3) +
     172           0 :                                     " entered =" + state.dataIPShortCut->cAlphaArgs(3) + " for " + state.dataIPShortCut->cAlphaFieldNames(1) + '=' +
     173           0 :                                     state.dataIPShortCut->cAlphaArgs(1));
     174           0 :                 ErrorsFound = true;
     175             :             }
     176             :         }
     177          15 :         if (state.dataIPShortCut->lAlphaFieldBlanks(4)) {
     178           0 :             thisBeam->heatingAvailSchedNum = DataGlobalConstants::ScheduleAlwaysOn;
     179             :         } else {
     180          15 :             thisBeam->heatingAvailSchedNum = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(4)); // convert schedule name to index
     181          15 :             if (thisBeam->heatingAvailSchedNum == 0) {
     182           0 :                 ShowSevereError(state,
     183           0 :                                 std::string{routineName} + cCurrentModuleObject + ": invalid " + state.dataIPShortCut->cAlphaFieldNames(4) +
     184           0 :                                     " entered =" + state.dataIPShortCut->cAlphaArgs(4) + " for " + state.dataIPShortCut->cAlphaFieldNames(1) + '=' +
     185           0 :                                     state.dataIPShortCut->cAlphaArgs(1));
     186           0 :                 ErrorsFound = true;
     187             :             }
     188             :         }
     189             : 
     190          30 :         thisBeam->airInNodeNum = GetOnlySingleNode(state,
     191          15 :                                                    state.dataIPShortCut->cAlphaArgs(5),
     192             :                                                    ErrorsFound,
     193             :                                                    DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeBeam,
     194          15 :                                                    state.dataIPShortCut->cAlphaArgs(1),
     195             :                                                    DataLoopNode::NodeFluidType::Air,
     196             :                                                    DataLoopNode::ConnectionType::Inlet,
     197             :                                                    NodeInputManager::CompFluidStream::Primary,
     198             :                                                    ObjectIsNotParent,
     199          15 :                                                    state.dataIPShortCut->cAlphaFieldNames(5));
     200          30 :         thisBeam->airOutNodeNum = GetOnlySingleNode(state,
     201          15 :                                                     state.dataIPShortCut->cAlphaArgs(6),
     202             :                                                     ErrorsFound,
     203             :                                                     DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeBeam,
     204          15 :                                                     state.dataIPShortCut->cAlphaArgs(1),
     205             :                                                     DataLoopNode::NodeFluidType::Air,
     206             :                                                     DataLoopNode::ConnectionType::Outlet,
     207             :                                                     NodeInputManager::CompFluidStream::Primary,
     208             :                                                     ObjectIsNotParent,
     209          15 :                                                     state.dataIPShortCut->cAlphaFieldNames(6));
     210          15 :         if (state.dataIPShortCut->lAlphaFieldBlanks(7) && state.dataIPShortCut->lAlphaFieldBlanks(8)) { // no chilled water nodes, no beam cooling
     211           0 :             thisBeam->beamCoolingPresent = false;
     212          15 :         } else if (state.dataIPShortCut->lAlphaFieldBlanks(7) &&
     213           0 :                    !state.dataIPShortCut->lAlphaFieldBlanks(8)) { // outlet node but no inlet node for chilled water
     214           0 :             thisBeam->beamCoolingPresent = false;
     215           0 :             ShowWarningError(state,
     216           0 :                              std::string{routineName} + cCurrentModuleObject + ": missing " + state.dataIPShortCut->cAlphaFieldNames(7) + " for " +
     217           0 :                                  state.dataIPShortCut->cAlphaFieldNames(1) + '=' + state.dataIPShortCut->cAlphaArgs(1) +
     218             :                                  ", simulation continues with no beam cooling");
     219          30 :         } else if (!state.dataIPShortCut->lAlphaFieldBlanks(7) &&
     220          15 :                    state.dataIPShortCut->lAlphaFieldBlanks(8)) { // inlet node but no outlet node for chilled water
     221           0 :             thisBeam->beamCoolingPresent = false;
     222           0 :             ShowWarningError(state,
     223           0 :                              std::string{routineName} + cCurrentModuleObject + ": missing " + state.dataIPShortCut->cAlphaFieldNames(8) + " for " +
     224           0 :                                  state.dataIPShortCut->cAlphaFieldNames(1) + '=' + state.dataIPShortCut->cAlphaArgs(1) +
     225             :                                  ", simulation continues with no beam cooling");
     226             :         } else {
     227          15 :             thisBeam->beamCoolingPresent = true;
     228          30 :             thisBeam->cWInNodeNum = GetOnlySingleNode(state,
     229          15 :                                                       state.dataIPShortCut->cAlphaArgs(7),
     230             :                                                       ErrorsFound,
     231             :                                                       DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeBeam,
     232          15 :                                                       state.dataIPShortCut->cAlphaArgs(1),
     233             :                                                       DataLoopNode::NodeFluidType::Water,
     234             :                                                       DataLoopNode::ConnectionType::Inlet,
     235             :                                                       NodeInputManager::CompFluidStream::Secondary,
     236             :                                                       ObjectIsParent,
     237          15 :                                                       state.dataIPShortCut->cAlphaFieldNames(7));
     238          30 :             thisBeam->cWOutNodeNum = GetOnlySingleNode(state,
     239          15 :                                                        state.dataIPShortCut->cAlphaArgs(8),
     240             :                                                        ErrorsFound,
     241             :                                                        DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeBeam,
     242          15 :                                                        state.dataIPShortCut->cAlphaArgs(1),
     243             :                                                        DataLoopNode::NodeFluidType::Water,
     244             :                                                        DataLoopNode::ConnectionType::Outlet,
     245             :                                                        NodeInputManager::CompFluidStream::Secondary,
     246             :                                                        ObjectIsParent,
     247          15 :                                                        state.dataIPShortCut->cAlphaFieldNames(8));
     248             :         }
     249          15 :         if (state.dataIPShortCut->lAlphaFieldBlanks(9) && state.dataIPShortCut->lAlphaFieldBlanks(10)) { // no hot water nodes, no beam heating
     250           0 :             thisBeam->beamHeatingPresent = false;
     251          15 :         } else if (state.dataIPShortCut->lAlphaFieldBlanks(9) &&
     252           0 :                    !state.dataIPShortCut->lAlphaFieldBlanks(10)) { // outlet node but no inlet node for hot water
     253           0 :             thisBeam->beamHeatingPresent = false;
     254           0 :             ShowWarningError(state,
     255           0 :                              std::string{routineName} + cCurrentModuleObject + ": missing " + state.dataIPShortCut->cAlphaFieldNames(9) + " for " +
     256           0 :                                  state.dataIPShortCut->cAlphaFieldNames(1) + '=' + state.dataIPShortCut->cAlphaArgs(1) +
     257             :                                  ", simulation continues with no beam heating");
     258          30 :         } else if (!state.dataIPShortCut->lAlphaFieldBlanks(9) &&
     259          15 :                    state.dataIPShortCut->lAlphaFieldBlanks(10)) { // inlet node but no outlet node for hot water
     260           0 :             thisBeam->beamHeatingPresent = false;
     261           0 :             ShowWarningError(state,
     262           0 :                              std::string{routineName} + cCurrentModuleObject + ": missing " + state.dataIPShortCut->cAlphaFieldNames(10) + " for " +
     263           0 :                                  state.dataIPShortCut->cAlphaFieldNames(1) + '=' + state.dataIPShortCut->cAlphaArgs(1) +
     264             :                                  ", simulation continues with no beam heating");
     265             :         } else {
     266          15 :             thisBeam->beamHeatingPresent = true;
     267          30 :             thisBeam->hWInNodeNum = GetOnlySingleNode(state,
     268          15 :                                                       state.dataIPShortCut->cAlphaArgs(9),
     269             :                                                       ErrorsFound,
     270             :                                                       DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeBeam,
     271          15 :                                                       state.dataIPShortCut->cAlphaArgs(1),
     272             :                                                       DataLoopNode::NodeFluidType::Water,
     273             :                                                       DataLoopNode::ConnectionType::Inlet,
     274             :                                                       NodeInputManager::CompFluidStream::Secondary,
     275             :                                                       ObjectIsParent,
     276          15 :                                                       state.dataIPShortCut->cAlphaFieldNames(9));
     277          30 :             thisBeam->hWOutNodeNum = GetOnlySingleNode(state,
     278          15 :                                                        state.dataIPShortCut->cAlphaArgs(10),
     279             :                                                        ErrorsFound,
     280             :                                                        DataLoopNode::ConnectionObjectType::AirTerminalSingleDuctConstantVolumeFourPipeBeam,
     281          15 :                                                        state.dataIPShortCut->cAlphaArgs(1),
     282             :                                                        DataLoopNode::NodeFluidType::Water,
     283             :                                                        DataLoopNode::ConnectionType::Outlet,
     284             :                                                        NodeInputManager::CompFluidStream::Secondary,
     285             :                                                        ObjectIsParent,
     286          15 :                                                        state.dataIPShortCut->cAlphaFieldNames(10));
     287             :         }
     288          15 :         thisBeam->vDotDesignPrimAir = state.dataIPShortCut->rNumericArgs(1);
     289          15 :         if (thisBeam->vDotDesignPrimAir == AutoSize) {
     290          15 :             thisBeam->vDotDesignPrimAirWasAutosized = true;
     291             :         }
     292          15 :         thisBeam->vDotDesignCW = state.dataIPShortCut->rNumericArgs(2);
     293          15 :         if (thisBeam->vDotDesignCW == AutoSize && thisBeam->beamCoolingPresent) {
     294          15 :             thisBeam->vDotDesignCWWasAutosized = true;
     295             :         }
     296          15 :         thisBeam->vDotDesignHW = state.dataIPShortCut->rNumericArgs(3);
     297          15 :         if (thisBeam->vDotDesignHW == AutoSize && thisBeam->beamHeatingPresent) {
     298          15 :             thisBeam->vDotDesignHWWasAutosized = true;
     299             :         }
     300          15 :         thisBeam->totBeamLength = state.dataIPShortCut->rNumericArgs(4);
     301          15 :         if (thisBeam->totBeamLength == AutoSize) {
     302          15 :             thisBeam->totBeamLengthWasAutosized = true;
     303             :         }
     304          15 :         thisBeam->vDotNormRatedPrimAir = state.dataIPShortCut->rNumericArgs(5);
     305          15 :         thisBeam->qDotNormRatedCooling = state.dataIPShortCut->rNumericArgs(6);
     306          15 :         thisBeam->deltaTempRatedCooling = state.dataIPShortCut->rNumericArgs(7);
     307          15 :         thisBeam->vDotNormRatedCW = state.dataIPShortCut->rNumericArgs(8);
     308             : 
     309          15 :         thisBeam->modCoolingQdotDeltaTFuncNum = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(11));
     310          15 :         if (thisBeam->modCoolingQdotDeltaTFuncNum == 0 && thisBeam->beamCoolingPresent) {
     311           0 :             ShowSevereError(state, std::string{routineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
     312           0 :             ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(11) + '=' + state.dataIPShortCut->cAlphaArgs(11));
     313           0 :             ErrorsFound = true;
     314             :         }
     315          15 :         thisBeam->modCoolingQdotAirFlowFuncNum = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(12));
     316          15 :         if (thisBeam->modCoolingQdotAirFlowFuncNum == 0 && thisBeam->beamCoolingPresent) {
     317           0 :             ShowSevereError(state, std::string{routineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
     318           0 :             ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(12) + '=' + state.dataIPShortCut->cAlphaArgs(12));
     319           0 :             ErrorsFound = true;
     320             :         }
     321          15 :         thisBeam->modCoolingQdotCWFlowFuncNum = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(13));
     322          15 :         if (thisBeam->modCoolingQdotCWFlowFuncNum == 0 && thisBeam->beamCoolingPresent) {
     323           0 :             ShowSevereError(state, std::string{routineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
     324           0 :             ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(13) + '=' + state.dataIPShortCut->cAlphaArgs(13));
     325           0 :             ErrorsFound = true;
     326             :         }
     327          15 :         thisBeam->qDotNormRatedHeating = state.dataIPShortCut->rNumericArgs(9);
     328          15 :         thisBeam->deltaTempRatedHeating = state.dataIPShortCut->rNumericArgs(10);
     329          15 :         thisBeam->vDotNormRatedHW = state.dataIPShortCut->rNumericArgs(11);
     330          15 :         thisBeam->modHeatingQdotDeltaTFuncNum = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(14));
     331          15 :         if (thisBeam->modHeatingQdotDeltaTFuncNum == 0 && thisBeam->beamHeatingPresent) {
     332           0 :             ShowSevereError(state, std::string{routineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
     333           0 :             ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(14) + '=' + state.dataIPShortCut->cAlphaArgs(14));
     334           0 :             ErrorsFound = true;
     335             :         }
     336          15 :         thisBeam->modHeatingQdotAirFlowFuncNum = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(15));
     337          15 :         if (thisBeam->modHeatingQdotAirFlowFuncNum == 0 && thisBeam->beamHeatingPresent) {
     338           0 :             ShowSevereError(state, std::string{routineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
     339           0 :             ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(15) + '=' + state.dataIPShortCut->cAlphaArgs(15));
     340           0 :             ErrorsFound = true;
     341             :         }
     342          15 :         thisBeam->modHeatingQdotHWFlowFuncNum = GetCurveIndex(state, state.dataIPShortCut->cAlphaArgs(16));
     343          15 :         if (thisBeam->modHeatingQdotHWFlowFuncNum == 0 && thisBeam->beamHeatingPresent) {
     344           0 :             ShowSevereError(state, std::string{routineName} + cCurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\"");
     345           0 :             ShowContinueError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(16) + '=' + state.dataIPShortCut->cAlphaArgs(16));
     346           0 :             ErrorsFound = true;
     347             :         }
     348             :         // Register component set data
     349          30 :         TestCompSet(state,
     350             :                     cCurrentModuleObject,
     351          15 :                     thisBeam->name,
     352          15 :                     state.dataLoopNodes->NodeID(thisBeam->airInNodeNum),
     353          15 :                     state.dataLoopNodes->NodeID(thisBeam->airOutNodeNum),
     354             :                     "Air Nodes");
     355          15 :         if (thisBeam->beamCoolingPresent) {
     356          30 :             TestCompSet(state,
     357             :                         cCurrentModuleObject,
     358          15 :                         thisBeam->name,
     359          15 :                         state.dataLoopNodes->NodeID(thisBeam->cWInNodeNum),
     360          15 :                         state.dataLoopNodes->NodeID(thisBeam->cWOutNodeNum),
     361             :                         "Chilled Water Nodes");
     362             :         }
     363          15 :         if (thisBeam->beamHeatingPresent) {
     364          30 :             TestCompSet(state,
     365             :                         cCurrentModuleObject,
     366          15 :                         thisBeam->name,
     367          15 :                         state.dataLoopNodes->NodeID(thisBeam->hWInNodeNum),
     368          15 :                         state.dataLoopNodes->NodeID(thisBeam->hWOutNodeNum),
     369             :                         "Hot Water Nodes");
     370             :         }
     371             : 
     372             :         // Setup the Cooled Beam reporting variables
     373          15 :         if (thisBeam->beamCoolingPresent) {
     374          60 :             SetupOutputVariable(state,
     375             :                                 "Zone Air Terminal Beam Sensible Cooling Energy",
     376             :                                 OutputProcessor::Unit::J,
     377          15 :                                 thisBeam->beamCoolingEnergy,
     378             :                                 OutputProcessor::SOVTimeStepType::System,
     379             :                                 OutputProcessor::SOVStoreType::Summed,
     380          15 :                                 thisBeam->name,
     381             :                                 _,
     382             :                                 "ENERGYTRANSFER",
     383             :                                 "COOLINGCOILS",
     384             :                                 _,
     385          15 :                                 "System");
     386          60 :             SetupOutputVariable(state,
     387             :                                 "Zone Air Terminal Beam Sensible Cooling Rate",
     388             :                                 OutputProcessor::Unit::W,
     389          15 :                                 thisBeam->beamCoolingRate,
     390             :                                 OutputProcessor::SOVTimeStepType::System,
     391             :                                 OutputProcessor::SOVStoreType::Average,
     392          30 :                                 thisBeam->name);
     393             :         }
     394          15 :         if (thisBeam->beamHeatingPresent) {
     395          60 :             SetupOutputVariable(state,
     396             :                                 "Zone Air Terminal Beam Sensible Heating Energy",
     397             :                                 OutputProcessor::Unit::J,
     398          15 :                                 thisBeam->beamHeatingEnergy,
     399             :                                 OutputProcessor::SOVTimeStepType::System,
     400             :                                 OutputProcessor::SOVStoreType::Summed,
     401          15 :                                 thisBeam->name,
     402             :                                 _,
     403             :                                 "ENERGYTRANSFER",
     404             :                                 "HEATINGCOILS",
     405             :                                 _,
     406          15 :                                 "System");
     407          60 :             SetupOutputVariable(state,
     408             :                                 "Zone Air Terminal Beam Sensible Heating Rate",
     409             :                                 OutputProcessor::Unit::W,
     410          15 :                                 thisBeam->beamHeatingRate,
     411             :                                 OutputProcessor::SOVTimeStepType::System,
     412             :                                 OutputProcessor::SOVStoreType::Average,
     413          30 :                                 thisBeam->name);
     414             :         }
     415          60 :         SetupOutputVariable(state,
     416             :                             "Zone Air Terminal Primary Air Sensible Cooling Energy",
     417             :                             OutputProcessor::Unit::J,
     418          15 :                             thisBeam->supAirCoolingEnergy,
     419             :                             OutputProcessor::SOVTimeStepType::System,
     420             :                             OutputProcessor::SOVStoreType::Summed,
     421          30 :                             thisBeam->name);
     422          60 :         SetupOutputVariable(state,
     423             :                             "Zone Air Terminal Primary Air Sensible Cooling Rate",
     424             :                             OutputProcessor::Unit::W,
     425          15 :                             thisBeam->supAirCoolingRate,
     426             :                             OutputProcessor::SOVTimeStepType::System,
     427             :                             OutputProcessor::SOVStoreType::Average,
     428          30 :                             thisBeam->name);
     429          60 :         SetupOutputVariable(state,
     430             :                             "Zone Air Terminal Primary Air Sensible Heating Energy",
     431             :                             OutputProcessor::Unit::J,
     432          15 :                             thisBeam->supAirHeatingEnergy,
     433             :                             OutputProcessor::SOVTimeStepType::System,
     434             :                             OutputProcessor::SOVStoreType::Summed,
     435          30 :                             thisBeam->name);
     436          60 :         SetupOutputVariable(state,
     437             :                             "Zone Air Terminal Primary Air Sensible Heating Rate",
     438             :                             OutputProcessor::Unit::W,
     439          15 :                             thisBeam->supAirHeatingRate,
     440             :                             OutputProcessor::SOVTimeStepType::System,
     441             :                             OutputProcessor::SOVStoreType::Average,
     442          30 :                             thisBeam->name);
     443          60 :         SetupOutputVariable(state,
     444             :                             "Zone Air Terminal Primary Air Flow Rate",
     445             :                             OutputProcessor::Unit::m3_s,
     446          15 :                             thisBeam->primAirFlow,
     447             :                             OutputProcessor::SOVTimeStepType::System,
     448             :                             OutputProcessor::SOVStoreType::Average,
     449          30 :                             thisBeam->name);
     450             : 
     451          60 :         SetupOutputVariable(state,
     452             :                             "Zone Air Terminal Outdoor Air Volume Flow Rate",
     453             :                             OutputProcessor::Unit::m3_s,
     454          15 :                             thisBeam->OutdoorAirFlowRate,
     455             :                             OutputProcessor::SOVTimeStepType::System,
     456             :                             OutputProcessor::SOVStoreType::Average,
     457          30 :                             thisBeam->name);
     458             : 
     459          15 :         airNodeFound = false;
     460         255 :         for (aDUIndex = 1; aDUIndex <= (int)state.dataDefineEquipment->AirDistUnit.size(); ++aDUIndex) {
     461         240 :             if (thisBeam->airOutNodeNum == state.dataDefineEquipment->AirDistUnit(aDUIndex).OutletNodeNum) {
     462          15 :                 thisBeam->aDUNum = aDUIndex;
     463          15 :                 state.dataDefineEquipment->AirDistUnit(aDUIndex).InletNodeNum = thisBeam->airInNodeNum;
     464             :             }
     465             :         }
     466             :         // assumes if there isn't one assigned, it's an error
     467          15 :         if (thisBeam->aDUNum == 0) {
     468           0 :             ShowSevereError(state,
     469           0 :                             std::string{routineName} + "No matching Air Distribution Unit, for Unit = [" + cCurrentModuleObject + ',' +
     470           0 :                                 thisBeam->name + "].");
     471           0 :             ShowContinueError(state, "...should have outlet node=" + state.dataLoopNodes->NodeID(thisBeam->airOutNodeNum));
     472           0 :             ErrorsFound = true;
     473             :         } else {
     474             : 
     475             :             // Fill the Zone Equipment data with the supply air inlet node number of this unit.
     476         300 :             for (ctrlZone = 1; ctrlZone <= state.dataGlobal->NumOfZones; ++ctrlZone) {
     477         285 :                 if (!state.dataZoneEquip->ZoneEquipConfig(ctrlZone).IsControlled) continue;
     478         465 :                 for (supAirIn = 1; supAirIn <= state.dataZoneEquip->ZoneEquipConfig(ctrlZone).NumInletNodes; ++supAirIn) {
     479         240 :                     if (thisBeam->airOutNodeNum == state.dataZoneEquip->ZoneEquipConfig(ctrlZone).InletNode(supAirIn)) {
     480          15 :                         thisBeam->zoneIndex = ctrlZone;
     481          15 :                         thisBeam->zoneNodeIndex = state.dataZoneEquip->ZoneEquipConfig(ctrlZone).ZoneNode;
     482          15 :                         thisBeam->ctrlZoneInNodeIndex = supAirIn;
     483          15 :                         state.dataZoneEquip->ZoneEquipConfig(ctrlZone).AirDistUnitCool(supAirIn).InNode = thisBeam->airInNodeNum;
     484          15 :                         state.dataZoneEquip->ZoneEquipConfig(ctrlZone).AirDistUnitCool(supAirIn).OutNode = thisBeam->airOutNodeNum;
     485          15 :                         state.dataDefineEquipment->AirDistUnit(thisBeam->aDUNum).TermUnitSizingNum =
     486          15 :                             state.dataZoneEquip->ZoneEquipConfig(ctrlZone).AirDistUnitCool(supAirIn).TermUnitSizingIndex;
     487          15 :                         thisBeam->termUnitSizingNum = state.dataDefineEquipment->AirDistUnit(thisBeam->aDUNum).TermUnitSizingNum;
     488          15 :                         state.dataDefineEquipment->AirDistUnit(thisBeam->aDUNum).ZoneEqNum = ctrlZone;
     489          15 :                         if (thisBeam->beamHeatingPresent) {
     490          15 :                             state.dataZoneEquip->ZoneEquipConfig(ctrlZone).AirDistUnitHeat(supAirIn).InNode = thisBeam->airInNodeNum;
     491          15 :                             state.dataZoneEquip->ZoneEquipConfig(ctrlZone).AirDistUnitHeat(supAirIn).OutNode = thisBeam->airOutNodeNum;
     492             :                         }
     493          15 :                         airNodeFound = true;
     494          15 :                         break;
     495             :                     }
     496             :                 }
     497             :             }
     498             :         }
     499          15 :         if (!airNodeFound) {
     500           0 :             ShowSevereError(state, "The outlet air node from the " + cCurrentModuleObject + " = " + thisBeam->name);
     501           0 :             ShowContinueError(state, "did not have a matching Zone Equipment Inlet Node, Node =" + state.dataIPShortCut->cAlphaArgs(5));
     502           0 :             ErrorsFound = true;
     503             :         }
     504             : 
     505          15 :         if (found && !ErrorsFound) {
     506          15 :             state.dataFourPipeBeam->FourPipeBeams.push_back(thisBeam);
     507          15 :             return thisBeam;
     508             :         } else {
     509           0 :             ShowFatalError(state, std::string{routineName} + "Errors found in getting input. Preceding conditions cause termination.");
     510           0 :             return nullptr;
     511             :         }
     512             :     }
     513             : 
     514          60 :     int HVACFourPipeBeam::getAirLoopNum()
     515             :     {
     516          60 :         return airLoopNum;
     517             :     }
     518             : 
     519           0 :     int HVACFourPipeBeam::getZoneIndex()
     520             :     {
     521           0 :         return zoneIndex;
     522             :     }
     523             : 
     524         165 :     Real64 HVACFourPipeBeam::getPrimAirDesignVolFlow()
     525             :     {
     526         165 :         return vDotDesignPrimAir;
     527             :     }
     528             : 
     529          15 :     int HVACFourPipeBeam::getTermUnitSizingIndex()
     530             :     {
     531          15 :         return termUnitSizingNum;
     532             :     }
     533             : 
     534      249285 :     void HVACFourPipeBeam::simulate(EnergyPlusData &state,
     535             :                                     bool const FirstHVACIteration, // TRUE if first HVAC iteration in time step
     536             :                                     Real64 &NonAirSysOutput        // convective cooling by the beam system [W]
     537             :     )
     538             :     {
     539             : 
     540             :         // initialize the unit
     541      249285 :         this->init(state, FirstHVACIteration);
     542             : 
     543             :         // control and simulate the beam
     544      249285 :         if (!this->mySizeFlag) {
     545      249270 :             this->control(state, FirstHVACIteration, NonAirSysOutput);
     546             : 
     547             :             // Update the current unit's outlet nodes.
     548      249270 :             this->update(state);
     549             : 
     550             :             // Fill the report variables.
     551      249270 :             this->report(state);
     552             :         }
     553      249285 :     }
     554             : 
     555      249285 :     void HVACFourPipeBeam::init(EnergyPlusData &state,
     556             :                                 bool const FirstHVACIteration // TRUE if first air loop solution this HVAC step
     557             :     )
     558             :     {
     559             : 
     560             :         // Using
     561             :         using DataZoneEquipment::CheckZoneEquipmentList;
     562             :         using PlantUtilities::InitComponentNodes;
     563             :         using PlantUtilities::ScanPlantLoopsForObject;
     564             :         using PlantUtilities::SetComponentFlowRate;
     565             :         using ScheduleManager::GetCurrentScheduleValue;
     566             : 
     567             :         static constexpr std::string_view routineName("HVACFourPipeBeam::init");
     568             : 
     569      249285 :         bool errFlag = false;
     570             : 
     571      249285 :         if (this->plantLoopScanFlag && allocated(state.dataPlnt->PlantLoop)) {
     572          15 :             errFlag = false;
     573          15 :             if (this->beamCoolingPresent) {
     574          15 :                 ScanPlantLoopsForObject(state,
     575             :                                         this->name,
     576             :                                         DataPlant::PlantEquipmentType::FourPipeBeamAirTerminal,
     577             :                                         this->cWplantLoc,
     578             :                                         errFlag,
     579             :                                         _,
     580             :                                         _,
     581             :                                         _,
     582             :                                         this->cWInNodeNum,
     583             :                                         _);
     584          15 :                 if (errFlag) {
     585           0 :                     ShowFatalError(state, std::string{routineName} + " Program terminated for previous conditions.");
     586             :                 }
     587             :             }
     588          15 :             if (this->beamHeatingPresent) {
     589          15 :                 ScanPlantLoopsForObject(state,
     590             :                                         this->name,
     591             :                                         DataPlant::PlantEquipmentType::FourPipeBeamAirTerminal,
     592             :                                         this->hWplantLoc,
     593             :                                         errFlag,
     594             :                                         _,
     595             :                                         _,
     596             :                                         _,
     597             :                                         this->hWInNodeNum,
     598             :                                         _);
     599          15 :                 if (errFlag) {
     600           0 :                     ShowFatalError(state, std::string{routineName} + " Program terminated for previous conditions.");
     601             :                 }
     602             :             }
     603          15 :             this->plantLoopScanFlag = false;
     604             :         }
     605             : 
     606      249285 :         if (!this->zoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
     607             :             // Check to see if there is a Air Distribution Unit on the Zone Equipment List
     608          15 :             if (this->aDUNum != 0) {
     609          15 :                 if (!CheckZoneEquipmentList(state, "ZONEHVAC:AIRDISTRIBUTIONUNIT", state.dataDefineEquipment->AirDistUnit(this->aDUNum).Name)) {
     610           0 :                     ShowSevereError(state,
     611           0 :                                     std::string{routineName} + ": ADU=[Air Distribution Unit," +
     612           0 :                                         state.dataDefineEquipment->AirDistUnit(this->aDUNum).Name + "] is not on any ZoneHVAC:EquipmentList.");
     613           0 :                     ShowContinueError(state, "...Unit=[" + this->unitType + ',' + this->name + "] will not be simulated.");
     614             :                 }
     615          15 :                 this->zoneEquipmentListChecked = true;
     616             :             }
     617             :         }
     618             : 
     619      249285 :         if (!state.dataGlobal->SysSizingCalc && this->mySizeFlag && !this->plantLoopScanFlag) {
     620             :             //    if ( SysSizingCalc && this->mySizeFlag && ! this->plantLoopScanFlag ) {
     621          15 :             this->airLoopNum = state.dataZoneEquip->ZoneEquipConfig(this->zoneIndex).InletNodeAirLoopNum(this->ctrlZoneInNodeIndex);
     622          15 :             state.dataDefineEquipment->AirDistUnit(this->aDUNum).AirLoopNum = this->airLoopNum;
     623          15 :             this->set_size(state);          // calculate autosize values (in any) and convert volume flow rates to mass flow rates
     624          15 :             if (this->beamCoolingPresent) { // initialize chilled water design mass flow rate in plant routines
     625          15 :                 InitComponentNodes(state, 0.0, this->mDotDesignCW, this->cWInNodeNum, this->cWOutNodeNum);
     626             :             }
     627          15 :             if (this->beamHeatingPresent) { // initialize hot water design mass flow rate in plant routines
     628          15 :                 InitComponentNodes(state, 0.0, this->mDotDesignHW, this->hWInNodeNum, this->hWOutNodeNum);
     629             :             }
     630          15 :             this->mySizeFlag = false;
     631             :         }
     632             : 
     633             :         // Do the Begin Environment initializations
     634      249285 :         if (state.dataGlobal->BeginEnvrnFlag && this->myEnvrnFlag) {
     635             : 
     636         180 :             state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRateMax = this->mDotDesignPrimAir;
     637         180 :             state.dataLoopNodes->Node(this->airOutNodeNum).MassFlowRateMax = this->mDotDesignPrimAir;
     638         180 :             state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRateMin = 0.0;
     639         180 :             state.dataLoopNodes->Node(this->airOutNodeNum).MassFlowRateMin = 0.0;
     640             : 
     641         180 :             if (this->beamCoolingPresent) { // initialize chilled water design mass flow rate in plant routines
     642         180 :                 InitComponentNodes(state, 0.0, this->mDotDesignCW, this->cWInNodeNum, this->cWOutNodeNum);
     643             :             }
     644         180 :             if (this->beamHeatingPresent) { // initialize hot water design mass flow rate in plant routines
     645         180 :                 InitComponentNodes(state, 0.0, this->mDotDesignHW, this->hWInNodeNum, this->hWOutNodeNum);
     646             :             }
     647             : 
     648         180 :             if (this->airLoopNum == 0) { // fill air loop index
     649           0 :                 if (this->zoneIndex > 0 && this->ctrlZoneInNodeIndex > 0) {
     650           0 :                     this->airLoopNum = state.dataZoneEquip->ZoneEquipConfig(this->zoneIndex).InletNodeAirLoopNum(this->ctrlZoneInNodeIndex);
     651             :                 }
     652             :             }
     653             : 
     654         180 :             this->myEnvrnFlag = false;
     655             :         } // end one time inits
     656             : 
     657      249285 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     658      246930 :             this->myEnvrnFlag = true;
     659             :         }
     660             : 
     661             :         // Do the start of HVAC time step initializations
     662      249285 :         if (FirstHVACIteration) {
     663             :             // check availability schedules and set flags
     664       93735 :             if (GetCurrentScheduleValue(state, this->airAvailSchedNum) > 0.0) {
     665       34905 :                 this->airAvailable = true;
     666             :             } else {
     667       58830 :                 this->airAvailable = false;
     668             :             }
     669       93735 :             if (this->airAvailable && beamCoolingPresent && (GetCurrentScheduleValue(state, this->coolingAvailSchedNum) > 0.0)) {
     670       34905 :                 this->coolingAvailable = true;
     671             :             } else {
     672       58830 :                 this->coolingAvailable = false;
     673             :             }
     674       93735 :             if (this->airAvailable && beamHeatingPresent && (GetCurrentScheduleValue(state, this->heatingAvailSchedNum) > 0.0)) {
     675       34905 :                 this->heatingAvailable = true;
     676             :             } else {
     677       58830 :                 this->heatingAvailable = false;
     678             :             }
     679             :             // check for upstream zero flow. If nonzero and air available, set primary flow to max
     680       93735 :             if (this->airAvailable && state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRate > 0.0) {
     681       34905 :                 state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRate = this->mDotDesignPrimAir;
     682             :             } else {
     683       58830 :                 state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRate = 0.0;
     684             :             }
     685             :             // reset the max and min avail flows
     686       93735 :             if (this->airAvailable && state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRateMaxAvail > 0.0) {
     687       34905 :                 state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRateMaxAvail = this->mDotDesignPrimAir;
     688       34905 :                 state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRateMinAvail = this->mDotDesignPrimAir;
     689             :             } else {
     690       58830 :                 state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRateMaxAvail = 0.0;
     691       58830 :                 state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRateMinAvail = 0.0;
     692             :             }
     693             :         }
     694             : 
     695             :         // do these initializations every time step
     696      249285 :         if (beamCoolingPresent) {
     697      249285 :             this->cWTempIn = state.dataLoopNodes->Node(this->cWInNodeNum).Temp;
     698      249285 :             this->cWTempOut = this->cWTempIn;
     699             :         }
     700      249285 :         if (beamHeatingPresent) {
     701      249285 :             this->hWTempIn = state.dataLoopNodes->Node(this->hWInNodeNum).Temp;
     702      249285 :             this->hWTempOut = this->hWTempIn;
     703             :         }
     704      249285 :         this->mDotSystemAir = state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRateMaxAvail;
     705      249285 :         state.dataLoopNodes->Node(this->airInNodeNum).MassFlowRate = this->mDotSystemAir;
     706      249285 :         this->tDBZoneAirTemp = state.dataLoopNodes->Node(this->zoneNodeIndex).Temp;
     707      249285 :         this->tDBSystemAir = state.dataLoopNodes->Node(this->airInNodeNum).Temp;
     708      249285 :         this->cpZoneAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(this->zoneNodeIndex).HumRat);
     709      249285 :         this->cpSystemAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(this->airInNodeNum).HumRat);
     710      249285 :         this->qDotBeamCooling = 0.0;
     711      249285 :         this->qDotBeamHeating = 0.0;
     712      249285 :         this->supAirCoolingRate = 0.0;
     713      249285 :         this->supAirHeatingRate = 0.0;
     714      249285 :         this->beamCoolingRate = 0.0;
     715      249285 :         this->beamHeatingRate = 0.0;
     716      249285 :         this->primAirFlow = 0.0;
     717             : 
     718      249285 :     } // init
     719             : 
     720          15 :     void HVACFourPipeBeam::set_size(EnergyPlusData &state)
     721             :     {
     722             : 
     723             :         // Using
     724             :         using namespace DataSizing;
     725             :         using FluidProperties::GetDensityGlycol;
     726             :         using FluidProperties::GetSpecificHeatGlycol;
     727             :         using PlantUtilities::MyPlantSizingIndex;
     728             :         using PlantUtilities::RegisterPlantCompDesignFlow;
     729             :         using Psychrometrics::PsyCpAirFnW;
     730             :         using namespace std::placeholders;
     731             : 
     732             :         static constexpr std::string_view routineName("HVACFourPipeBeam::set_size ");
     733             : 
     734          15 :         bool ErrorsFound = false;
     735             :         Real64 rho;                     // local fluid density
     736             :         bool noHardSizeAnchorAvailable; // aid for complex logic surrounding mix of hard size and autosizes
     737          15 :         Real64 cpAir = 0.0;
     738             :         int SolFlag;
     739          15 :         Real64 ErrTolerance = 0.001;
     740             : 
     741          15 :         Real64 mDotAirSolutionHeating = 0.0;
     742          15 :         Real64 mDotAirSolutionCooling = 0.0;
     743          15 :         Real64 originalTermUnitSizeMaxVDot = 0.0;
     744          15 :         Real64 originalTermUnitSizeCoolVDot = 0.0;
     745          15 :         Real64 originalTermUnitSizeHeatVDot = 0.0;
     746             : 
     747             :         // convert rated primary flow rate to mass flow rate using standard pressure and dry air at 20.0
     748          15 :         this->mDotNormRatedPrimAir = this->vDotNormRatedPrimAir * state.dataEnvrn->rhoAirSTP;
     749             : 
     750          15 :         noHardSizeAnchorAvailable = false;
     751             : 
     752          15 :         if (state.dataSize->CurTermUnitSizingNum > 0) {
     753          30 :             originalTermUnitSizeMaxVDot = std::max(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlow,
     754          30 :                                                    state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow);
     755          15 :             originalTermUnitSizeCoolVDot = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolVolFlow;
     756          15 :             originalTermUnitSizeHeatVDot = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatVolFlow;
     757             :         }
     758             : 
     759          30 :         if (this->totBeamLengthWasAutosized && this->vDotDesignPrimAirWasAutosized && this->vDotDesignCWWasAutosized &&
     760          15 :             this->vDotDesignHWWasAutosized) {
     761          15 :             noHardSizeAnchorAvailable = true;
     762           0 :         } else if (this->totBeamLengthWasAutosized && this->vDotDesignPrimAirWasAutosized && this->vDotDesignCWWasAutosized && !beamHeatingPresent) {
     763           0 :             noHardSizeAnchorAvailable = true;
     764           0 :         } else if (this->totBeamLengthWasAutosized && this->vDotDesignPrimAirWasAutosized && !this->beamCoolingPresent &&
     765           0 :                    this->vDotDesignHWWasAutosized) {
     766           0 :             noHardSizeAnchorAvailable = true;
     767           0 :         } else if (!this->totBeamLengthWasAutosized) { // the simplest case is where length is not autosized
     768             :             // use the normalized rated values (likely defaulted ) with length to calculate any that are autosized
     769           0 :             if (this->vDotDesignPrimAirWasAutosized) {
     770           0 :                 this->vDotDesignPrimAir = this->vDotNormRatedPrimAir * this->totBeamLength;
     771             :             }
     772           0 :             if (this->vDotDesignCWWasAutosized) {
     773           0 :                 this->vDotDesignCW = this->vDotNormRatedCW * this->totBeamLength;
     774             :             }
     775           0 :             if (vDotDesignHWWasAutosized) {
     776           0 :                 this->vDotDesignHW = this->vDotNormRatedHW * this->totBeamLength;
     777             :             }
     778             :         } else { // need to find beam length
     779             :             // the next simplest case is if the supply air rate is given
     780           0 :             if (!this->vDotDesignPrimAirWasAutosized) { //
     781             :                 // find length from air flow rate and then proceed
     782           0 :                 this->totBeamLength = this->vDotDesignPrimAir / this->vDotNormRatedPrimAir;
     783           0 :                 if (this->vDotDesignCWWasAutosized) {
     784           0 :                     this->vDotDesignCW = this->vDotNormRatedCW * this->totBeamLength;
     785             :                 }
     786           0 :                 if (vDotDesignHWWasAutosized) {
     787           0 :                     this->vDotDesignHW = this->vDotNormRatedHW * this->totBeamLength;
     788             :                 }
     789             :             } else {                                                               // both air and length are autosized
     790           0 :                 if (this->beamCoolingPresent && !this->vDotDesignCWWasAutosized) { // we have a chilled water flow rate to use
     791           0 :                     this->totBeamLength = this->vDotDesignCW / this->vDotNormRatedCW;
     792           0 :                     this->vDotDesignPrimAir = this->vDotNormRatedPrimAir * this->totBeamLength;
     793           0 :                     if (vDotDesignHWWasAutosized) {
     794           0 :                         this->vDotDesignHW = this->vDotNormRatedHW * this->totBeamLength;
     795             :                     }
     796           0 :                 } else if (this->beamHeatingPresent && !this->vDotDesignHWWasAutosized) { // we have a hot water flow rate to use
     797           0 :                     this->totBeamLength = this->vDotDesignHW / this->vDotNormRatedHW;
     798           0 :                     this->vDotDesignPrimAir = this->vDotNormRatedPrimAir * this->totBeamLength;
     799           0 :                     if (this->vDotDesignCWWasAutosized) { // don't think it can come here but...
     800           0 :                         this->vDotDesignCW = this->vDotNormRatedCW * this->totBeamLength;
     801             :                     }
     802             :                 } else {
     803             :                     // should not come here, developer exception
     804             :                 }
     805             :             } // no air flow rate
     806             :         }     // no beam length
     807             : 
     808          30 :         if (noHardSizeAnchorAvailable && (state.dataSize->CurZoneEqNum > 0) &&
     809          15 :             (state.dataSize->CurTermUnitSizingNum > 0)) { // need to use central sizing results to calculate
     810             : 
     811             :             // set up for solver
     812             : 
     813          15 :             CheckZoneSizing(state, this->unitType, this->name);
     814             :             // minimum flow rate is from air flow rate on the terminal unit final zone size ( typically ventilation minimum and may be too low)
     815          15 :             Real64 minFlow(0.0);
     816          15 :             Real64 maxFlowCool(0.0);
     817          30 :             minFlow = std::min(state.dataEnvrn->StdRhoAir * originalTermUnitSizeMaxVDot,
     818          45 :                                state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).MinOA * state.dataEnvrn->StdRhoAir);
     819          15 :             minFlow = std::max(0.0, minFlow);
     820             :             // max flow is as if the air supply was sufficient to provide all the conditioning
     821             : 
     822          15 :             if (beamCoolingPresent) {
     823          15 :                 cpAir = PsyCpAirFnW(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolCoilInHumRatTU);
     824             : 
     825          45 :                 if ((state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtCoolPeak -
     826          30 :                      state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolCoilInTempTU) >
     827             :                     2.0) { // avoid div by zero and blow up
     828          30 :                     maxFlowCool = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolLoad /
     829          30 :                                   (cpAir * (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtCoolPeak -
     830          15 :                                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolCoilInTempTU));
     831             :                 } else {
     832           0 :                     maxFlowCool = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolLoad / (cpAir * 2.0);
     833             :                 }
     834          15 :                 if (minFlow * 3.0 >= maxFlowCool) {
     835           0 :                     minFlow = maxFlowCool / 3.0; // make sure min is significantly lower than max.
     836             :                 }
     837             : 
     838          15 :                 int pltSizCoolNum = MyPlantSizingIndex(state, "four pipe beam unit", this->name, this->cWInNodeNum, this->cWOutNodeNum, ErrorsFound);
     839          15 :                 if (pltSizCoolNum == 0) {
     840           0 :                     ShowSevereError(state, "Autosizing of water flow requires a cooling loop Sizing:Plant object");
     841           0 :                     ShowContinueError(state, "Occurs in " + this->unitType + " Object=" + this->name);
     842           0 :                     ErrorsFound = true;
     843             :                 } else {
     844          15 :                     this->cWTempIn = state.dataSize->PlantSizData(pltSizCoolNum).ExitTemp;
     845             :                 }
     846          15 :                 this->mDotHW = 0.0;
     847          15 :                 this->tDBZoneAirTemp = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtCoolPeak;
     848          15 :                 this->tDBSystemAir = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolCoilInTempTU;
     849          15 :                 this->cpZoneAir = PsyCpAirFnW(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneHumRatAtCoolPeak);
     850          15 :                 this->cpSystemAir = PsyCpAirFnW(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolCoilInHumRatTU);
     851          15 :                 this->qDotZoneReq = -1.0 * state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolLoad;
     852          15 :                 this->qDotZoneToCoolSetPt = -1.0 * state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesCoolLoad;
     853          15 :                 this->airAvailable = true;
     854          15 :                 this->coolingAvailable = true;
     855          15 :                 this->heatingAvailable = false;
     856        2160 :                 auto f = [&state, this](Real64 const airFlow) {
     857             :                     static constexpr std::string_view routineName("Real64 HVACFourPipeBeam::residualSizing ");
     858          45 :                     this->mDotSystemAir = airFlow;
     859         135 :                     this->vDotDesignPrimAir = this->mDotSystemAir / state.dataEnvrn->StdRhoAir;
     860         135 :                     this->totBeamLength = this->vDotDesignPrimAir / this->vDotNormRatedPrimAir;
     861          45 :                     if (this->vDotDesignCWWasAutosized) {
     862         135 :                         this->vDotDesignCW = this->vDotNormRatedCW * this->totBeamLength;
     863          90 :                         Real64 const rho = FluidProperties::GetDensityGlycol(state,
     864          90 :                                                                              state.dataPlnt->PlantLoop(this->cWplantLoc.loopNum).FluidName,
     865             :                                                                              DataGlobalConstants::CWInitConvTemp,
     866          90 :                                                                              state.dataPlnt->PlantLoop(this->cWplantLoc.loopNum).FluidIndex,
     867          45 :                                                                              routineName);
     868          90 :                         this->mDotNormRatedCW = this->vDotNormRatedCW * rho;
     869          90 :                         this->mDotCW = this->vDotDesignCW * rho;
     870          45 :                         if (this->beamCoolingPresent) {
     871         180 :                             PlantUtilities::InitComponentNodes(state, 0.0, this->mDotCW, this->cWInNodeNum, this->cWOutNodeNum);
     872             :                         }
     873             :                     }
     874          45 :                     if (vDotDesignHWWasAutosized) {
     875         135 :                         this->vDotDesignHW = this->vDotNormRatedHW * this->totBeamLength;
     876          90 :                         Real64 const rho = FluidProperties::GetDensityGlycol(state,
     877          90 :                                                                              state.dataPlnt->PlantLoop(this->hWplantLoc.loopNum).FluidName,
     878             :                                                                              DataGlobalConstants::HWInitConvTemp,
     879          90 :                                                                              state.dataPlnt->PlantLoop(this->hWplantLoc.loopNum).FluidIndex,
     880          45 :                                                                              routineName);
     881          90 :                         this->mDotNormRatedHW = this->vDotNormRatedHW * rho;
     882          90 :                         this->mDotHW = this->vDotDesignHW * rho;
     883          45 :                         if (this->beamHeatingPresent) {
     884         180 :                             PlantUtilities::InitComponentNodes(state, 0.0, this->mDotHW, this->hWInNodeNum, this->hWOutNodeNum);
     885             :                         }
     886             :                     }
     887          45 :                     this->calc(state);
     888          45 :                     if (this->qDotZoneReq != 0.0) {
     889         135 :                         return ((this->qDotZoneReq - this->qDotTotalDelivered) / this->qDotZoneReq);
     890             :                     } else {
     891           0 :                         return 1.0;
     892             :                     }
     893          15 :                 };
     894          15 :                 General::SolveRoot(state, ErrTolerance, 50, SolFlag, mDotAirSolutionCooling, f, minFlow, maxFlowCool);
     895          15 :                 if (SolFlag == -1) {
     896           0 :                     ShowWarningError(state, "Cooling load sizing search failed in four pipe beam unit called " + this->name);
     897           0 :                     ShowContinueError(state, "  Iteration limit exceeded in calculating size for design cooling load");
     898          15 :                 } else if (SolFlag == -2) {
     899           0 :                     ShowWarningError(state, "Cooling load sizing search failed in four pipe beam unit called " + this->name);
     900           0 :                     ShowContinueError(state, "  Bad size limits");
     901             :                 }
     902             :             }
     903             : 
     904          15 :             if (beamHeatingPresent) {
     905          15 :                 cpAir = PsyCpAirFnW(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInHumRatTU);
     906          15 :                 Real64 maxFlowHeat = 0.0;
     907          45 :                 if ((state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU -
     908          30 :                      state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtHeatPeak) >
     909             :                     2.0) { // avoid div by zero and blow up
     910           0 :                     maxFlowHeat = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatLoad /
     911           0 :                                   (cpAir * (state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU -
     912           0 :                                             state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtHeatPeak));
     913             :                 } else {
     914          15 :                     maxFlowHeat = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatLoad / (cpAir * 2.0);
     915             :                 }
     916             : 
     917          15 :                 int pltSizHeatNum = MyPlantSizingIndex(state, "four pipe beam unit", this->name, this->hWInNodeNum, this->hWOutNodeNum, ErrorsFound);
     918          15 :                 if (pltSizHeatNum == 0) {
     919           0 :                     ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
     920           0 :                     ShowContinueError(state, "Occurs in " + this->unitType + " Object=" + this->name);
     921           0 :                     ErrorsFound = true;
     922             :                 } else {
     923          15 :                     this->hWTempIn = state.dataSize->PlantSizData(pltSizHeatNum).ExitTemp;
     924             :                 }
     925          15 :                 this->mDotCW = 0.0;
     926          15 :                 this->tDBZoneAirTemp = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneTempAtHeatPeak;
     927          15 :                 this->tDBSystemAir = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInTempTU;
     928          15 :                 this->cpZoneAir = PsyCpAirFnW(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).ZoneHumRatAtHeatPeak);
     929          15 :                 this->cpSystemAir = PsyCpAirFnW(state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatCoilInHumRatTU);
     930          15 :                 this->qDotZoneReq = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatLoad;
     931          15 :                 this->qDotZoneToHeatSetPt = state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).DesHeatLoad;
     932          15 :                 this->airAvailable = true;
     933          15 :                 this->heatingAvailable = true;
     934          15 :                 this->coolingAvailable = false;
     935        2160 :                 auto f = [&state, this](Real64 const airFlow) {
     936             :                     static constexpr std::string_view routineName("Real64 HVACFourPipeBeam::residualSizing ");
     937          45 :                     this->mDotSystemAir = airFlow;
     938         135 :                     this->vDotDesignPrimAir = this->mDotSystemAir / state.dataEnvrn->StdRhoAir;
     939         135 :                     this->totBeamLength = this->vDotDesignPrimAir / this->vDotNormRatedPrimAir;
     940          45 :                     if (this->vDotDesignCWWasAutosized) {
     941         135 :                         this->vDotDesignCW = this->vDotNormRatedCW * this->totBeamLength;
     942          90 :                         Real64 const rho = FluidProperties::GetDensityGlycol(state,
     943          90 :                                                                              state.dataPlnt->PlantLoop(this->cWplantLoc.loopNum).FluidName,
     944             :                                                                              DataGlobalConstants::CWInitConvTemp,
     945          90 :                                                                              state.dataPlnt->PlantLoop(this->cWplantLoc.loopNum).FluidIndex,
     946          45 :                                                                              routineName);
     947          90 :                         this->mDotNormRatedCW = this->vDotNormRatedCW * rho;
     948          90 :                         this->mDotCW = this->vDotDesignCW * rho;
     949          45 :                         if (this->beamCoolingPresent) {
     950         180 :                             PlantUtilities::InitComponentNodes(state, 0.0, this->mDotCW, this->cWInNodeNum, this->cWOutNodeNum);
     951             :                         }
     952             :                     }
     953          45 :                     if (vDotDesignHWWasAutosized) {
     954         135 :                         this->vDotDesignHW = this->vDotNormRatedHW * this->totBeamLength;
     955          90 :                         Real64 const rho = FluidProperties::GetDensityGlycol(state,
     956          90 :                                                                              state.dataPlnt->PlantLoop(this->hWplantLoc.loopNum).FluidName,
     957             :                                                                              DataGlobalConstants::HWInitConvTemp,
     958          90 :                                                                              state.dataPlnt->PlantLoop(this->hWplantLoc.loopNum).FluidIndex,
     959          45 :                                                                              routineName);
     960          90 :                         this->mDotNormRatedHW = this->vDotNormRatedHW * rho;
     961          90 :                         this->mDotHW = this->vDotDesignHW * rho;
     962          45 :                         if (this->beamHeatingPresent) {
     963         180 :                             PlantUtilities::InitComponentNodes(state, 0.0, this->mDotHW, this->hWInNodeNum, this->hWOutNodeNum);
     964             :                         }
     965             :                     }
     966          45 :                     this->calc(state);
     967          45 :                     if (this->qDotZoneReq != 0.0) {
     968         135 :                         return ((this->qDotZoneReq - this->qDotTotalDelivered) / this->qDotZoneReq);
     969             :                     } else {
     970           0 :                         return 1.0;
     971             :                     }
     972          15 :                 };
     973          15 :                 General::SolveRoot(state, ErrTolerance, 50, SolFlag, mDotAirSolutionHeating, f, 0.0, maxFlowHeat);
     974          15 :                 if (SolFlag == -1) {
     975           0 :                     ShowWarningError(state, "Heating load sizing search failed in four pipe beam unit called " + this->name);
     976           0 :                     ShowContinueError(state, "  Iteration limit exceeded in calculating size for design heating load");
     977          15 :                 } else if (SolFlag == -2) {
     978           0 :                     ShowWarningError(state, "Heating load sizing search failed in four pipe beam unit called " + this->name);
     979           0 :                     ShowContinueError(state, "  Bad size limits");
     980             :                 }
     981             :             }
     982             : 
     983             :             // take the larger of heating and cooling
     984          15 :             this->mDotDesignPrimAir = std::max(mDotAirSolutionHeating, mDotAirSolutionCooling);
     985             :             // make sure this is higher than the zone OA requirement
     986          15 :             this->mDotDesignPrimAir =
     987          15 :                 std::max(this->mDotDesignPrimAir,
     988          30 :                          state.dataSize->TermUnitFinalZoneSizing(state.dataSize->CurTermUnitSizingNum).MinOA * state.dataEnvrn->StdRhoAir);
     989          15 :             this->vDotDesignPrimAir = this->mDotDesignPrimAir / state.dataEnvrn->StdRhoAir;
     990          15 :             this->totBeamLength = this->vDotDesignPrimAir / this->vDotNormRatedPrimAir;
     991          15 :             if (this->vDotDesignCWWasAutosized) {
     992          15 :                 this->vDotDesignCW = this->vDotNormRatedCW * this->totBeamLength;
     993             :             }
     994          15 :             if (vDotDesignHWWasAutosized) {
     995          15 :                 this->vDotDesignHW = this->vDotNormRatedHW * this->totBeamLength;
     996             :             }
     997             :         }
     998             :         // fill in mass flow rate versions of working variables (regardless of autosizing )
     999          15 :         this->mDotDesignPrimAir = this->vDotDesignPrimAir * state.dataEnvrn->StdRhoAir;
    1000             : 
    1001          15 :         if ((originalTermUnitSizeMaxVDot > 0.0) && (originalTermUnitSizeMaxVDot != this->vDotDesignPrimAir) && (state.dataSize->CurZoneEqNum > 0)) {
    1002          15 :             if ((state.dataSize->SysSizingRunDone) && (this->airLoopNum > 0)) {
    1003             :                 // perturb system size to handle change in system size calculated without knowing about 4 pipe beam
    1004             :                 // Note that this approach is not necessarily appropriate for coincident system design option
    1005             :                 // and it might be moved to make such adjustments in SizingManager::ManageSystemSizingAdjustments()
    1006          15 :                 state.dataSize->FinalSysSizing(this->airLoopNum).DesMainVolFlow += (this->vDotDesignPrimAir - originalTermUnitSizeMaxVDot);
    1007          15 :                 state.dataSize->FinalSysSizing(this->airLoopNum).DesCoolVolFlow += (this->vDotDesignPrimAir - originalTermUnitSizeCoolVDot);
    1008          15 :                 state.dataSize->FinalSysSizing(this->airLoopNum).DesHeatVolFlow += (this->vDotDesignPrimAir - originalTermUnitSizeHeatVDot);
    1009          15 :                 state.dataSize->FinalSysSizing(this->airLoopNum).MassFlowAtCoolPeak +=
    1010          15 :                     (this->vDotDesignPrimAir - originalTermUnitSizeCoolVDot) * state.dataEnvrn->StdRhoAir;
    1011             : 
    1012          45 :                 BaseSizer::reportSizerOutput(state,
    1013             :                                              this->unitType,
    1014             :                                              this->name,
    1015             :                                              "AirLoopHVAC Design Supply Air Flow Rate Adjustment [m3/s]",
    1016          30 :                                              (this->vDotDesignPrimAir - originalTermUnitSizeMaxVDot));
    1017             :             } else {
    1018           0 :                 ShowSevereError(state, "Four pipe beam requires system sizing. Turn on system sizing.");
    1019           0 :                 ShowFatalError(state, "Program terminating due to previous errors");
    1020             :             }
    1021             :         }
    1022             : 
    1023          15 :         if (this->beamCoolingPresent) {
    1024          30 :             rho = FluidProperties::GetDensityGlycol(state,
    1025          15 :                                                     state.dataPlnt->PlantLoop(this->cWplantLoc.loopNum).FluidName,
    1026             :                                                     DataGlobalConstants::CWInitConvTemp,
    1027          15 :                                                     state.dataPlnt->PlantLoop(this->cWplantLoc.loopNum).FluidIndex,
    1028             :                                                     routineName);
    1029          15 :             this->mDotNormRatedCW = this->vDotNormRatedCW * rho;
    1030          15 :             this->mDotDesignCW = this->vDotDesignCW * rho;
    1031          15 :             PlantUtilities::InitComponentNodes(state, 0.0, this->mDotDesignCW, this->cWInNodeNum, this->cWOutNodeNum);
    1032             :         }
    1033          15 :         if (this->beamHeatingPresent) {
    1034          30 :             rho = FluidProperties::GetDensityGlycol(state,
    1035          15 :                                                     state.dataPlnt->PlantLoop(this->hWplantLoc.loopNum).FluidName,
    1036             :                                                     DataGlobalConstants::HWInitConvTemp,
    1037          15 :                                                     state.dataPlnt->PlantLoop(this->hWplantLoc.loopNum).FluidIndex,
    1038             :                                                     routineName);
    1039          15 :             this->mDotNormRatedHW = this->vDotNormRatedHW * rho;
    1040          15 :             this->mDotDesignHW = this->vDotDesignHW * rho;
    1041          15 :             PlantUtilities::InitComponentNodes(state, 0.0, this->mDotDesignHW, this->hWInNodeNum, this->hWOutNodeNum);
    1042             :         }
    1043             : 
    1044             :         // report final sizes if autosized
    1045          15 :         if (this->vDotDesignPrimAirWasAutosized) {
    1046          15 :             BaseSizer::reportSizerOutput(state, this->unitType, this->name, "Supply Air Flow Rate [m3/s]", this->vDotDesignPrimAir);
    1047             :         }
    1048          15 :         if (this->vDotDesignCWWasAutosized) {
    1049          15 :             BaseSizer::reportSizerOutput(state, this->unitType, this->name, "Maximum Total Chilled Water Flow Rate [m3/s]", this->vDotDesignCW);
    1050             :         }
    1051          15 :         if (this->vDotDesignHWWasAutosized) {
    1052          15 :             BaseSizer::reportSizerOutput(state, this->unitType, this->name, "Maximum Total Hot Water Flow Rate [m3/s]", this->vDotDesignHW);
    1053             :         }
    1054          15 :         if (this->totBeamLengthWasAutosized) {
    1055          15 :             BaseSizer::reportSizerOutput(state, this->unitType, this->name, "Zone Total Beam Length [m]", this->totBeamLength);
    1056             :         }
    1057             :         // save the design water volume flow rate for use by the water loop sizing algorithms
    1058          15 :         if (this->vDotDesignCW > 0.0 && this->beamCoolingPresent) {
    1059          15 :             RegisterPlantCompDesignFlow(state, this->cWInNodeNum, this->vDotDesignCW);
    1060             :         }
    1061          15 :         if (this->vDotDesignHW > 0.0 && this->beamHeatingPresent) {
    1062          15 :             RegisterPlantCompDesignFlow(state, this->hWInNodeNum, this->vDotDesignHW);
    1063             :         }
    1064          15 :         if (ErrorsFound) {
    1065           0 :             ShowFatalError(state, "Preceding four pipe beam sizing errors cause program termination");
    1066             :         }
    1067             : 
    1068          15 :     } // set_size
    1069             : 
    1070      249270 :     void HVACFourPipeBeam::control(EnergyPlusData &state,
    1071             :                                    [[maybe_unused]] bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
    1072             :                                    Real64 &NonAirSysOutput                         // convective cooling by the beam system [W]
    1073             :     )
    1074             :     {
    1075             : 
    1076             :         // Using/Aliasing
    1077             :         using namespace DataZoneEnergyDemands;
    1078             :         using PlantUtilities::SetComponentFlowRate;
    1079             :         using namespace std::placeholders;
    1080             : 
    1081      249270 :         bool dOASMode = false; // true if unit is operating as DOAS terminal with no heating or cooling by beam
    1082             : 
    1083             :         int SolFlag;
    1084             :         Real64 ErrTolerance;
    1085             : 
    1086      249270 :         NonAirSysOutput = 0.0; // initialize
    1087             : 
    1088      379425 :         if (this->mDotSystemAir < DataHVACGlobals::VerySmallMassFlow ||
    1089      130155 :             (!this->airAvailable && !this->coolingAvailable && !this->heatingAvailable)) { // unit is off
    1090      119115 :             this->mDotHW = 0.0;
    1091      119115 :             if (this->beamHeatingPresent) {
    1092      119115 :                 SetComponentFlowRate(state, this->mDotHW, this->hWInNodeNum, this->hWOutNodeNum, this->hWplantLoc);
    1093             :             }
    1094      119115 :             this->hWTempOut = this->hWTempIn;
    1095             :             // assume if there is still flow that unit has an internal bypass and convector does not still heat
    1096      119115 :             this->mDotCW = 0.0;
    1097      119115 :             this->cWTempOut = this->cWTempIn;
    1098      119115 :             if (this->beamCoolingPresent) {
    1099      119115 :                 SetComponentFlowRate(state, this->mDotCW, this->cWInNodeNum, this->cWOutNodeNum, this->cWplantLoc);
    1100             :             }
    1101             :             // assume if there is still flow that unit has an internal bypass and convector does not still cool
    1102             :             // don't even need to run calc
    1103      119115 :             return;
    1104             :         }
    1105             : 
    1106      130155 :         if (this->airAvailable && this->mDotSystemAir > DataHVACGlobals::VerySmallMassFlow && !this->coolingAvailable && !this->heatingAvailable) {
    1107           0 :             dOASMode = true;
    1108           0 :             this->mDotHW = 0.0;
    1109           0 :             if (this->beamHeatingPresent) {
    1110           0 :                 SetComponentFlowRate(state, this->mDotHW, this->hWInNodeNum, this->hWOutNodeNum, this->hWplantLoc);
    1111             :             }
    1112             :             // assume if there is still flow that unit has an internal bypass and convector does not still heat
    1113           0 :             this->hWTempOut = this->hWTempIn;
    1114           0 :             this->mDotCW = 0.0;
    1115           0 :             if (this->beamCoolingPresent) {
    1116           0 :                 SetComponentFlowRate(state, this->mDotCW, this->cWInNodeNum, this->cWOutNodeNum, this->cWplantLoc);
    1117             :             }
    1118             :             // assume if there is still flow that unit has an internal bypass and convector does not still cool
    1119           0 :             this->cWTempOut = this->cWTempIn;
    1120           0 :             this->calc(state);
    1121             : 
    1122           0 :             return;
    1123             :         }
    1124             : 
    1125             :         // get zone loads
    1126      130155 :         this->qDotZoneReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(this->zoneIndex).RemainingOutputRequired;
    1127      130155 :         this->qDotZoneToHeatSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(this->zoneIndex).RemainingOutputReqToHeatSP;
    1128      130155 :         this->qDotZoneToCoolSetPt = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(this->zoneIndex).RemainingOutputReqToCoolSP;
    1129             : 
    1130             :         // decide if beam is in heating or cooling
    1131             : 
    1132      130155 :         this->qDotSystemAir = this->mDotSystemAir * ((this->cpSystemAir * this->tDBSystemAir) - (this->cpZoneAir * this->tDBZoneAirTemp));
    1133             : 
    1134      130155 :         this->qDotBeamReq = this->qDotZoneReq - this->qDotSystemAir;
    1135             : 
    1136      130155 :         if (this->qDotBeamReq < -DataHVACGlobals::SmallLoad && this->coolingAvailable) { // beam cooling needed
    1137             :             // first calc with max chilled water flow
    1138       67858 :             this->mDotHW = 0.0;
    1139       67858 :             if (this->beamHeatingPresent) {
    1140       67858 :                 SetComponentFlowRate(state, this->mDotHW, this->hWInNodeNum, this->hWOutNodeNum, this->hWplantLoc);
    1141             :             }
    1142       67858 :             this->hWTempOut = this->hWTempIn;
    1143       67858 :             this->mDotCW = this->mDotDesignCW;
    1144       67858 :             this->calc(state);
    1145       67858 :             if (this->qDotBeamCooling < (qDotBeamReq - DataHVACGlobals::SmallLoad)) {
    1146             :                 // can overcool, modulate chilled water flow rate to meet load
    1147       60366 :                 this->qDotBeamCoolingMax = this->qDotBeamCooling;
    1148       60366 :                 ErrTolerance = 0.01;
    1149     3028080 :                 auto f = [&state, this](Real64 const cWFlow) {
    1150      378510 :                     this->mDotHW = 0.0;
    1151      378510 :                     this->mDotCW = cWFlow;
    1152      378510 :                     this->calc(state);
    1153      378510 :                     if (this->qDotBeamCoolingMax != 0.0) {
    1154     1514040 :                         return (((this->qDotZoneToCoolSetPt - this->qDotSystemAir) - this->qDotBeamCooling) / this->qDotBeamCoolingMax);
    1155             :                     } else {
    1156           0 :                         return 1.0;
    1157             :                     }
    1158       60366 :                 };
    1159       60366 :                 General::SolveRoot(state, ErrTolerance, 50, SolFlag, this->mDotCW, f, 0.0, this->mDotDesignCW);
    1160       60366 :                 if (SolFlag == -1) {
    1161             :                     // ShowWarningError( "Cold water control failed in four pipe beam unit called " + this->name );
    1162             :                     // ShowContinueError(state,  "  Iteration limit exceeded in calculating cold water mass flow rate" );
    1163       60122 :                 } else if (SolFlag == -2) {
    1164             :                     // ShowWarningError( "Cold water control failed in four pipe beam unit called " + this->name );
    1165             :                     // ShowContinueError(state,  "  Bad cold water flow limits" );
    1166             :                 }
    1167       60366 :                 this->calc(state);
    1168       60366 :                 NonAirSysOutput = this->qDotBeamCooling;
    1169       60366 :                 return;
    1170             :             } else { // can run flat out without overcooling, which we just did
    1171        7492 :                 NonAirSysOutput = this->qDotBeamCooling;
    1172        7492 :                 return;
    1173             :             }
    1174             : 
    1175       62297 :         } else if (qDotBeamReq > DataHVACGlobals::SmallLoad && this->heatingAvailable) { // beam heating needed
    1176             :             // first calc with max hot water flow
    1177       62294 :             this->mDotCW = 0.0;
    1178       62294 :             if (this->beamCoolingPresent) {
    1179       62294 :                 SetComponentFlowRate(state, this->mDotCW, this->cWInNodeNum, this->cWOutNodeNum, this->cWplantLoc);
    1180             :             }
    1181       62294 :             this->cWTempOut = this->cWTempIn;
    1182       62294 :             this->mDotHW = this->mDotDesignHW;
    1183       62294 :             this->calc(state);
    1184       62294 :             if (this->qDotBeamHeating > (qDotBeamReq + DataHVACGlobals::SmallLoad)) {
    1185       48113 :                 this->qDotBeamHeatingMax = this->qDotBeamHeating;
    1186             :                 // can overheat, modulate hot water flow to meet load
    1187       48113 :                 ErrTolerance = 0.01;
    1188     1931576 :                 auto f = [&state, this](Real64 const hWFlow) {
    1189      241447 :                     this->mDotHW = hWFlow;
    1190      241447 :                     this->mDotCW = 0.0;
    1191      241447 :                     this->calc(state);
    1192      241447 :                     if (this->qDotBeamHeatingMax != 0.0) {
    1193      965788 :                         return (((this->qDotZoneToHeatSetPt - this->qDotSystemAir) - this->qDotBeamHeating) / this->qDotBeamHeatingMax);
    1194             :                     } else {
    1195           0 :                         return 1.0;
    1196             :                     }
    1197       48113 :                 };
    1198       48113 :                 General::SolveRoot(state, ErrTolerance, 50, SolFlag, this->mDotHW, f, 0.0, this->mDotDesignHW);
    1199       48113 :                 if (SolFlag == -1) {
    1200             :                     // ShowWarningError( "Hot water control failed in four pipe beam unit called " + this->name );
    1201             :                     // ShowContinueError(state,  "  Iteration limit exceeded in calculating hot water mass flow rate" );
    1202       48113 :                 } else if (SolFlag == -2) {
    1203             :                     // ShowWarningError( "Hot water control failed in four pipe beam called " + this->name );
    1204             :                     // ShowContinueError(state,  "  Bad hot water flow limits" );
    1205             :                 }
    1206       48113 :                 this->calc(state);
    1207       48113 :                 NonAirSysOutput = this->qDotBeamHeating;
    1208       48113 :                 return;
    1209             : 
    1210             :             } else { // can run flat out without overheating, which we just did
    1211       14181 :                 NonAirSysOutput = this->qDotBeamHeating;
    1212       14181 :                 return;
    1213             :             }
    1214             : 
    1215             :         } else {
    1216           3 :             this->mDotHW = 0.0;
    1217           3 :             if (this->beamHeatingPresent) {
    1218           3 :                 SetComponentFlowRate(state, this->mDotHW, this->hWInNodeNum, this->hWOutNodeNum, this->hWplantLoc);
    1219             :             }
    1220           3 :             this->hWTempOut = this->hWTempIn;
    1221             :             // assume if there is still flow that unit has an internal bypass and convector does not still heat
    1222           3 :             this->mDotCW = 0.0;
    1223           3 :             this->cWTempOut = this->cWTempIn;
    1224           3 :             if (this->beamCoolingPresent) {
    1225           3 :                 SetComponentFlowRate(state, this->mDotCW, this->cWInNodeNum, this->cWOutNodeNum, this->cWplantLoc);
    1226             :             }
    1227             :             // assume if there is still flow that unit has an internal bypass and convector does not still cool
    1228             :             // don't even need to run calc
    1229           3 :             return;
    1230             :         }
    1231             :     }
    1232             : 
    1233      858678 :     void HVACFourPipeBeam::calc(EnergyPlusData &state)
    1234             :     {
    1235             : 
    1236             :         // Using/Aliasing
    1237             :         using FluidProperties::GetDensityGlycol;
    1238             :         using FluidProperties::GetSpecificHeatGlycol;
    1239             :         using PlantUtilities::SetComponentFlowRate;
    1240             : 
    1241             :         // Locals
    1242             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    1243             : 
    1244             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1245             :         static constexpr std::string_view routineName("HVACFourPipeBeam::calc ");
    1246             : 
    1247             :         // INTERFACE BLOCK SPECIFICATIONS
    1248             :         // na
    1249             : 
    1250             :         // DERIVED TYPE DEFINITIONS
    1251             :         // na
    1252             : 
    1253             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1254             :         Real64 fModCoolCWMdot;  // Cooling capacity modification factor function of chilled water flow rate
    1255             :         Real64 fModCoolDeltaT;  // Cooling capacity modification factor function of air-water temperature difference
    1256             :         Real64 fModCoolAirMdot; // Cooling capacity modification factor function of primary air flow rate
    1257             :         Real64 fModHeatHWMdot;  // Heating capacity modification factor function of hot water flow rate
    1258             :         Real64 fModHeatDeltaT;  // Heating capacity modification factor function of water - air temperature difference
    1259             :         Real64 fModHeatAirMdot; // Heating capacity modification factor function of primary air flow rate
    1260             :         Real64 cp;              // local fluid specific heat
    1261             : 
    1262      858678 :         this->qDotBeamHeating = 0.0;
    1263      858678 :         this->qDotBeamCooling = 0.0;
    1264      858678 :         this->qDotSystemAir = this->mDotSystemAir * ((this->cpSystemAir * this->tDBSystemAir) - (this->cpZoneAir * this->tDBZoneAirTemp));
    1265             : 
    1266      858678 :         if (this->coolingAvailable && this->mDotCW > DataHVACGlobals::VerySmallMassFlow) {
    1267             :             // test chilled water flow against plant, it might not all be available
    1268      446413 :             SetComponentFlowRate(state, this->mDotCW, this->cWInNodeNum, this->cWOutNodeNum, this->cWplantLoc);
    1269      446413 :             fModCoolCWMdot =
    1270      892826 :                 Curve::CurveValue(state, this->modCoolingQdotCWFlowFuncNum, ((this->mDotCW / this->totBeamLength) / this->mDotNormRatedCW));
    1271      446413 :             fModCoolDeltaT =
    1272      892826 :                 Curve::CurveValue(state, this->modCoolingQdotDeltaTFuncNum, ((this->tDBZoneAirTemp - this->cWTempIn) / this->deltaTempRatedCooling));
    1273      892826 :             fModCoolAirMdot = Curve::CurveValue(
    1274      446413 :                 state, this->modCoolingQdotAirFlowFuncNum, ((this->mDotSystemAir / this->totBeamLength) / this->mDotNormRatedPrimAir));
    1275      446413 :             this->qDotBeamCooling = -1.0 * this->qDotNormRatedCooling * fModCoolDeltaT * fModCoolAirMdot * fModCoolCWMdot * this->totBeamLength;
    1276      892826 :             cp = GetSpecificHeatGlycol(state,
    1277      446413 :                                        state.dataPlnt->PlantLoop(this->cWplantLoc.loopNum).FluidName,
    1278             :                                        this->cWTempIn,
    1279      446413 :                                        state.dataPlnt->PlantLoop(this->cWplantLoc.loopNum).FluidIndex,
    1280             :                                        routineName);
    1281      446413 :             if (this->mDotCW > 0.0) {
    1282      446396 :                 this->cWTempOut = this->cWTempIn - (this->qDotBeamCooling / (this->mDotCW * cp));
    1283             :             } else {
    1284          17 :                 this->cWTempOut = this->cWTempIn;
    1285             :             }
    1286             :             // check if non physical temperature rise, can't be warmer than air
    1287      892826 :             if (this->cWTempOut > (std::max(this->tDBSystemAir, this->tDBZoneAirTemp) - 1.0)) {
    1288             :                 // throw recurring warning as this indicates a problem in beam model input
    1289           0 :                 ShowRecurringWarningErrorAtEnd(state,
    1290           0 :                                                std::string{routineName} + " four pipe beam name " + this->name +
    1291             :                                                    ", chilled water outlet temperature is too warm. Capacity was limited. check beam capacity input ",
    1292             :                                                this->cWTempOutErrorCount,
    1293             :                                                this->cWTempOut,
    1294             :                                                this->cWTempOut);
    1295             :                 //  restrict it within 1.0 C of warmest air and recalculate cooling
    1296           0 :                 this->cWTempOut = (std::max(this->tDBSystemAir, this->tDBZoneAirTemp) - 1.0);
    1297           0 :                 this->qDotBeamCooling = this->mDotCW * cp * (this->cWTempIn - this->cWTempOut);
    1298             :             }
    1299             :         } else {
    1300      412265 :             this->mDotCW = 0.0;
    1301      412265 :             if (this->beamCoolingPresent) {
    1302      412265 :                 SetComponentFlowRate(state, this->mDotCW, this->cWInNodeNum, this->cWOutNodeNum, this->cWplantLoc);
    1303             :             }
    1304      412265 :             this->cWTempOut = this->cWTempIn;
    1305      412265 :             this->qDotBeamCooling = 0.0;
    1306             :         }
    1307      858678 :         if (this->heatingAvailable && this->mDotHW > DataHVACGlobals::VerySmallMassFlow) {
    1308             :             // test hot water flow against plant, it might not all be available
    1309      280547 :             SetComponentFlowRate(state, this->mDotHW, this->hWInNodeNum, this->hWOutNodeNum, this->hWplantLoc);
    1310      280547 :             fModHeatHWMdot =
    1311      561094 :                 Curve::CurveValue(state, this->modHeatingQdotHWFlowFuncNum, ((this->mDotHW / this->totBeamLength) / this->mDotNormRatedHW));
    1312      280547 :             fModHeatDeltaT =
    1313      561094 :                 Curve::CurveValue(state, this->modHeatingQdotDeltaTFuncNum, ((this->hWTempIn - this->tDBZoneAirTemp) / this->deltaTempRatedHeating));
    1314      561094 :             fModHeatAirMdot = Curve::CurveValue(
    1315      280547 :                 state, this->modHeatingQdotAirFlowFuncNum, ((this->mDotSystemAir / this->totBeamLength) / this->mDotNormRatedPrimAir));
    1316      280547 :             this->qDotBeamHeating = this->qDotNormRatedHeating * fModHeatDeltaT * fModHeatAirMdot * fModHeatHWMdot * this->totBeamLength;
    1317      561094 :             cp = GetSpecificHeatGlycol(state,
    1318      280547 :                                        state.dataPlnt->PlantLoop(this->hWplantLoc.loopNum).FluidName,
    1319             :                                        this->hWTempIn,
    1320      280547 :                                        state.dataPlnt->PlantLoop(this->hWplantLoc.loopNum).FluidIndex,
    1321             :                                        routineName);
    1322      280547 :             if (this->mDotHW > 0.0) {
    1323      280379 :                 this->hWTempOut = this->hWTempIn - (this->qDotBeamHeating / (this->mDotHW * cp));
    1324             :             } else {
    1325         168 :                 this->hWTempOut = this->hWTempIn;
    1326             :             }
    1327             :             // check if non physical temperature drop, can't be cooler than air
    1328      561094 :             if (this->hWTempOut < (std::min(this->tDBSystemAir, this->tDBZoneAirTemp) + 1.0)) {
    1329             :                 // throw recurring warning as this indicates a problem in beam model input
    1330           0 :                 ShowRecurringWarningErrorAtEnd(state,
    1331           0 :                                                std::string{routineName} + " four pipe beam name " + this->name +
    1332             :                                                    ", hot water outlet temperature is too cool. Capacity was limited. check beam capacity input ",
    1333             :                                                this->hWTempOutErrorCount,
    1334             :                                                this->hWTempOut,
    1335             :                                                this->hWTempOut);
    1336             :                 //  restrict it within 1.0 C of warmest air and recalculate cooling
    1337           0 :                 this->hWTempOut = (std::min(this->tDBSystemAir, this->tDBZoneAirTemp) + 1.0);
    1338           0 :                 this->qDotBeamHeating = this->mDotHW * cp * (this->hWTempIn - this->hWTempOut);
    1339             :             }
    1340             :         } else {
    1341      578131 :             this->mDotHW = 0.0;
    1342      578131 :             if (this->beamHeatingPresent) {
    1343      578131 :                 SetComponentFlowRate(state, this->mDotHW, this->hWInNodeNum, this->hWOutNodeNum, this->hWplantLoc);
    1344             :             }
    1345      578131 :             this->hWTempOut = this->hWTempIn;
    1346      578131 :             this->qDotBeamHeating = 0.0;
    1347             :         }
    1348             : 
    1349      858678 :         this->qDotTotalDelivered = this->qDotSystemAir + this->qDotBeamCooling + this->qDotBeamHeating;
    1350      858678 :     }
    1351             : 
    1352      249270 :     void HVACFourPipeBeam::update(EnergyPlusData &state) const // update node date elsewhere in EnergyPlus, does not change state of this
    1353             :     {
    1354      249270 :         auto &Node(state.dataLoopNodes->Node);
    1355             : 
    1356             :         using PlantUtilities::SafeCopyPlantNode;
    1357             : 
    1358             :         // Set the outlet air nodes of the unit; note that all quantities are unchanged from inlet to outlet
    1359      249270 :         Node(this->airOutNodeNum).MassFlowRate = Node(this->airInNodeNum).MassFlowRate;
    1360      249270 :         Node(this->airOutNodeNum).Temp = Node(this->airInNodeNum).Temp;
    1361      249270 :         Node(this->airOutNodeNum).HumRat = Node(this->airInNodeNum).HumRat;
    1362      249270 :         Node(this->airOutNodeNum).Enthalpy = Node(this->airInNodeNum).Enthalpy;
    1363      249270 :         Node(this->airOutNodeNum).Quality = Node(this->airInNodeNum).Quality;
    1364      249270 :         Node(this->airOutNodeNum).Press = Node(this->airInNodeNum).Press;
    1365      249270 :         Node(this->airOutNodeNum).MassFlowRateMin = Node(this->airInNodeNum).MassFlowRateMin;
    1366      249270 :         Node(this->airOutNodeNum).MassFlowRateMax = Node(this->airInNodeNum).MassFlowRateMax;
    1367      249270 :         Node(this->airOutNodeNum).MassFlowRateMinAvail = Node(this->airInNodeNum).MassFlowRateMinAvail;
    1368      249270 :         Node(this->airOutNodeNum).MassFlowRateMaxAvail = Node(this->airInNodeNum).MassFlowRateMaxAvail;
    1369             : 
    1370      249270 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1371           0 :             Node(this->airOutNodeNum).CO2 = Node(this->airInNodeNum).CO2;
    1372             :         }
    1373             : 
    1374      249270 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1375           0 :             Node(this->airOutNodeNum).GenContam = Node(this->airInNodeNum).GenContam;
    1376             :         }
    1377             : 
    1378             :         // Set the outlet water nodes for the unit
    1379             : 
    1380      249270 :         if (this->beamCoolingPresent) {
    1381      249270 :             SafeCopyPlantNode(state, this->cWInNodeNum, this->cWOutNodeNum);
    1382      249270 :             Node(this->cWOutNodeNum).Temp = this->cWTempOut;
    1383             :         }
    1384      249270 :         if (this->beamHeatingPresent) {
    1385      249270 :             SafeCopyPlantNode(state, this->hWInNodeNum, this->hWOutNodeNum);
    1386      249270 :             Node(this->hWOutNodeNum).Temp = this->hWTempOut;
    1387             :         }
    1388      249270 :     }
    1389             : 
    1390      249270 :     void HVACFourPipeBeam::report(EnergyPlusData &state) // fill out local output variables for reporting
    1391             :     {
    1392             : 
    1393             :         Real64 ReportingConstant;
    1394             : 
    1395      249270 :         ReportingConstant = state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    1396             : 
    1397      249270 :         if (this->beamCoolingPresent) {
    1398      249270 :             this->beamCoolingRate = std::abs(this->qDotBeamCooling); // report var has positive sign convention
    1399      249270 :             this->beamCoolingEnergy = this->beamCoolingRate * ReportingConstant;
    1400             :         }
    1401      249270 :         if (this->beamHeatingPresent) {
    1402      249270 :             this->beamHeatingRate = this->qDotBeamHeating;
    1403      249270 :             this->beamHeatingEnergy = this->beamHeatingRate * ReportingConstant;
    1404             :         }
    1405      249270 :         if (qDotSystemAir <= 0.0) { // cooling
    1406      245912 :             this->supAirCoolingRate = std::abs(this->qDotSystemAir);
    1407      245912 :             this->supAirHeatingRate = 0.0;
    1408             :         } else {
    1409        3358 :             this->supAirHeatingRate = this->qDotSystemAir;
    1410        3358 :             this->supAirCoolingRate = 0.0;
    1411             :         }
    1412      249270 :         this->supAirCoolingEnergy = this->supAirCoolingRate * ReportingConstant;
    1413      249270 :         this->supAirHeatingEnergy = this->supAirHeatingRate * ReportingConstant;
    1414             : 
    1415      249270 :         this->primAirFlow = this->mDotSystemAir / state.dataEnvrn->StdRhoAir;
    1416             : 
    1417      249270 :         this->CalcOutdoorAirVolumeFlowRate(state);
    1418      249270 :     }
    1419             : 
    1420      249270 :     void HVACFourPipeBeam::CalcOutdoorAirVolumeFlowRate(EnergyPlusData &state)
    1421             :     {
    1422             :         // calculates zone outdoor air volume flow rate using the supply air flow rate and OA fraction
    1423      249270 :         if (this->airLoopNum > 0) {
    1424      498540 :             this->OutdoorAirFlowRate = (state.dataLoopNodes->Node(this->airOutNodeNum).MassFlowRate / state.dataEnvrn->StdRhoAir) *
    1425      249270 :                                        state.dataAirLoop->AirLoopFlow(this->airLoopNum).OAFrac;
    1426             :         } else {
    1427           0 :             this->OutdoorAirFlowRate = 0.0;
    1428             :         }
    1429      249270 :     }
    1430             : 
    1431             : } // namespace FourPipeBeam
    1432             : 
    1433        2313 : } // namespace EnergyPlus

Generated by: LCOV version 1.13