LCOV - code coverage report
Current view: top level - EnergyPlus - HVACFourPipeBeam.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 629 803 78.3 %
Date: 2024-08-23 23:50:59 Functions: 17 18 94.4 %

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

Generated by: LCOV version 1.14