LCOV - code coverage report
Current view: top level - EnergyPlus - BaseboardRadiator.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 67.3 % 508 342
Test Date: 2025-06-02 07:23:51 Functions: 100.0 % 8 8

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cmath>
      50              : 
      51              : // ObjexxFCL Headers
      52              : #include <ObjexxFCL/Array.functions.hh>
      53              : // #include <ObjexxFCL/Fmath.hh>
      54              : 
      55              : // EnergyPlus Headers
      56              : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
      57              : #include <EnergyPlus/BaseboardRadiator.hh>
      58              : #include <EnergyPlus/BranchNodeConnections.hh>
      59              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      60              : #include <EnergyPlus/DataHVACGlobals.hh>
      61              : #include <EnergyPlus/DataHeatBalance.hh>
      62              : #include <EnergyPlus/DataIPShortCuts.hh>
      63              : #include <EnergyPlus/DataLoopNode.hh>
      64              : #include <EnergyPlus/DataPrecisionGlobals.hh>
      65              : #include <EnergyPlus/DataSizing.hh>
      66              : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      67              : #include <EnergyPlus/DataZoneEquipment.hh>
      68              : #include <EnergyPlus/FluidProperties.hh>
      69              : #include <EnergyPlus/General.hh>
      70              : #include <EnergyPlus/GeneralRoutines.hh>
      71              : #include <EnergyPlus/GlobalNames.hh>
      72              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      73              : #include <EnergyPlus/NodeInputManager.hh>
      74              : #include <EnergyPlus/OutputProcessor.hh>
      75              : #include <EnergyPlus/Plant/DataPlant.hh>
      76              : #include <EnergyPlus/PlantUtilities.hh>
      77              : #include <EnergyPlus/Psychrometrics.hh>
      78              : #include <EnergyPlus/ScheduleManager.hh>
      79              : #include <EnergyPlus/UtilityRoutines.hh>
      80              : 
      81              : namespace EnergyPlus {
      82              : namespace BaseboardRadiator {
      83              : 
      84              :     // Module containing the routines dealing with the BASEBOARD HEATER
      85              :     // component(s).
      86              : 
      87              :     // MODULE INFORMATION:
      88              :     //       AUTHOR         Russ Taylor
      89              :     //       DATE WRITTEN   Jan 1998
      90              :     //       MODIFIED       Fred Buhl, October 1999
      91              :     //       RE-ENGINEERED  na
      92              : 
      93              :     // Using/Aliasing
      94              :     using HVAC::SmallLoad;
      95              : 
      96              :     // Use statements for access to subroutines in other modules
      97              :     using Psychrometrics::PsyCpAirFnW;
      98              :     using Psychrometrics::PsyRhoAirFnPbTdbW;
      99              : 
     100              :     static std::string const cCMO_BBRadiator_Water("ZoneHVAC:Baseboard:Convective:Water");
     101              : 
     102       162355 :     void SimBaseboard(EnergyPlusData &state,
     103              :                       std::string const &EquipName,
     104              :                       int const ControlledZoneNum,
     105              :                       bool const FirstHVACIteration,
     106              :                       Real64 &PowerMet,
     107              :                       int &CompIndex)
     108              :     {
     109              : 
     110              :         // SUBROUTINE INFORMATION:
     111              :         //       AUTHOR         Russ Taylor
     112              :         //       DATE WRITTEN   Nov 1997
     113              : 
     114              :         // PURPOSE OF THIS SUBROUTINE:
     115              :         // This subroutine simulates the Baseboard Radiators.
     116              : 
     117       162355 :         if (state.dataBaseboardRadiator->getInputFlag) {
     118           10 :             GetBaseboardInput(state);
     119           10 :             state.dataBaseboardRadiator->getInputFlag = false;
     120              :         }
     121              : 
     122              :         // Find the correct Baseboard Equipment
     123       162355 :         if (CompIndex == 0) {
     124           31 :             int BaseboardNum = Util::FindItemInList(EquipName, state.dataBaseboardRadiator->baseboards, &BaseboardParams::EquipID);
     125           31 :             if (BaseboardNum == 0) {
     126            0 :                 ShowFatalError(state, format("SimBaseboard: Unit not found={}", EquipName));
     127              :             }
     128           31 :             CompIndex = BaseboardNum;
     129              :         }
     130       162355 :         assert(CompIndex <= (int)state.dataBaseboardRadiator->baseboards.size());
     131       162355 :         auto &thisBaseboard = state.dataBaseboardRadiator->baseboards(CompIndex);
     132       162355 :         if (thisBaseboard.CheckEquipName) {
     133           31 :             if (EquipName != thisBaseboard.EquipID) {
     134            0 :                 ShowFatalError(state,
     135            0 :                                format("SimBaseboard: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     136              :                                       CompIndex,
     137              :                                       EquipName,
     138            0 :                                       thisBaseboard.EquipID));
     139              :             }
     140           31 :             thisBaseboard.CheckEquipName = false;
     141              :         }
     142              : 
     143       162355 :         thisBaseboard.InitBaseboard(state, CompIndex);
     144              : 
     145       162355 :         Real64 QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ControlledZoneNum).RemainingOutputReqToHeatSP;
     146       162355 :         Real64 MaxWaterFlow = 0.0;
     147       162355 :         Real64 MinWaterFlow = 0.0;
     148       162355 :         Real64 DummyMdot = 0.0;
     149              : 
     150       162355 :         if ((QZnReq < SmallLoad) || (thisBaseboard.WaterInletTemp <= thisBaseboard.AirInletTemp)) {
     151              :             //  IF (Baseboard(BaseboardNum)%WaterInletTemp <= Baseboard(BaseboardNum)%AirInletTemp) THEN
     152              :             // The baseboard cannot provide cooling.  Thus, if the zone required load is negative or the water inlet
     153              :             // temperature is lower than the zone air temperature, then we need to shut down the baseboard unit
     154              : 
     155        97929 :             thisBaseboard.WaterOutletTemp = thisBaseboard.WaterInletTemp;
     156        97929 :             thisBaseboard.AirOutletTemp = thisBaseboard.AirInletTemp;
     157        97929 :             thisBaseboard.Power = 0.0;
     158        97929 :             thisBaseboard.WaterMassFlowRate = 0.0;
     159              :             // init hot water flow rate to zero
     160        97929 :             DummyMdot = 0.0;
     161        97929 :             PlantUtilities::SetActuatedBranchFlowRate(state, DummyMdot, thisBaseboard.WaterInletNode, thisBaseboard.plantLoc, false);
     162              : 
     163              :         } else {
     164              :             // init hot water flow rate to zero
     165        64426 :             DummyMdot = 0.0;
     166        64426 :             PlantUtilities::SetActuatedBranchFlowRate(state, DummyMdot, thisBaseboard.WaterInletNode, thisBaseboard.plantLoc, true);
     167              : 
     168              :             // On the first HVAC iteration the system values are given to the controller, but after that
     169              :             // the demand limits are in place and there needs to be feedback to the Zone Equipment
     170        64426 :             if (FirstHVACIteration) {
     171        32225 :                 MaxWaterFlow = thisBaseboard.WaterMassFlowRateMax;
     172        32225 :                 MinWaterFlow = 0.0;
     173              :             } else {
     174        32201 :                 MaxWaterFlow = state.dataLoopNodes->Node(thisBaseboard.WaterInletNode).MassFlowRateMaxAvail;
     175        32201 :                 MinWaterFlow = state.dataLoopNodes->Node(thisBaseboard.WaterInletNode).MassFlowRateMinAvail;
     176              :             }
     177              : 
     178       193278 :             ControlCompOutput(state,
     179        64426 :                               thisBaseboard.EquipID,
     180              :                               cCMO_BBRadiator_Water,
     181              :                               CompIndex,
     182              :                               FirstHVACIteration,
     183              :                               QZnReq,
     184              :                               thisBaseboard.WaterInletNode,
     185              :                               MaxWaterFlow,
     186              :                               MinWaterFlow,
     187              :                               thisBaseboard.Offset,
     188        64426 :                               thisBaseboard.ControlCompTypeNum,
     189        64426 :                               thisBaseboard.CompErrIndex,
     190              :                               _,
     191              :                               _,
     192              :                               _,
     193              :                               _,
     194              :                               _,
     195        64426 :                               thisBaseboard.plantLoc);
     196              : 
     197        64426 :             PowerMet = thisBaseboard.Power;
     198              :         }
     199              : 
     200       162355 :         UpdateBaseboard(state, CompIndex);
     201       162355 :         thisBaseboard.Energy = thisBaseboard.Power * state.dataHVACGlobal->TimeStepSysSec;
     202       162355 :     }
     203              : 
     204           10 :     void GetBaseboardInput(EnergyPlusData &state)
     205              :     {
     206              : 
     207              :         // SUBROUTINE INFORMATION:
     208              :         //       AUTHOR         Russ Taylor
     209              :         //       DATE WRITTEN   Nov 1997
     210              : 
     211              :         // PURPOSE OF THIS SUBROUTINE:
     212              :         // This subroutine gets the input for the Baseboard units.
     213              : 
     214              :         // METHODOLOGY EMPLOYED:
     215              :         // Standard input processor calls.
     216              : 
     217              :         // Using/Aliasing
     218              :         using BranchNodeConnections::TestCompSet;
     219              :         using NodeInputManager::GetOnlySingleNode;
     220              :         using namespace DataLoopNode;
     221              :         using GlobalNames::VerifyUniqueBaseboardName;
     222              :         using namespace DataSizing;
     223              : 
     224              :         // SUBROUTINE PARAMETER DEFINITIONS:
     225              :         static constexpr std::string_view RoutineName = "GetBaseboardInput: "; // include trailing blank space
     226              :         static constexpr std::string_view routineName = "GetBaseboardInput";
     227           10 :         int constexpr iHeatCAPMAlphaNum = 5;                   // get input index to water baseboard Radiator system heating capacity sizing method
     228           10 :         int constexpr iHeatDesignCapacityNumericNum = 1;       // get input index to water baseboard Radiator system electric heating capacity
     229           10 :         int constexpr iHeatCapacityPerFloorAreaNumericNum = 2; // index to baseboard Radiator system electric heating capacity per floor area sizing
     230           10 :         int constexpr iHeatFracOfAutosizedCapacityNumericNum = 3; //  index to baseboard heating capacity fraction of autosized heating capacity
     231              : 
     232           10 :         auto &s_ipsc = state.dataIPShortCut;
     233              : 
     234           10 :         s_ipsc->cCurrentModuleObject = cCMO_BBRadiator_Water;
     235              : 
     236           10 :         int NumConvHWBaseboards = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     237              : 
     238              :         // Calculate total number of baseboard units
     239              : 
     240           10 :         state.dataBaseboardRadiator->baseboards.allocate(NumConvHWBaseboards);
     241              : 
     242           10 :         if (NumConvHWBaseboards > 0) { // Get the data for cooling schemes
     243           10 :             bool ErrorsFound(false);   // If errors detected in input
     244           41 :             for (int ConvHWBaseboardNum = 1; ConvHWBaseboardNum <= NumConvHWBaseboards; ++ConvHWBaseboardNum) {
     245           31 :                 int NumAlphas = 0;
     246           31 :                 int NumNums = 0;
     247           31 :                 int IOStat = 0;
     248              : 
     249           62 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     250           31 :                                                                          s_ipsc->cCurrentModuleObject,
     251              :                                                                          ConvHWBaseboardNum,
     252           31 :                                                                          s_ipsc->cAlphaArgs,
     253              :                                                                          NumAlphas,
     254           31 :                                                                          s_ipsc->rNumericArgs,
     255              :                                                                          NumNums,
     256              :                                                                          IOStat,
     257           31 :                                                                          s_ipsc->lNumericFieldBlanks,
     258           31 :                                                                          s_ipsc->lAlphaFieldBlanks,
     259           31 :                                                                          s_ipsc->cAlphaFieldNames,
     260           31 :                                                                          s_ipsc->cNumericFieldNames);
     261              : 
     262           31 :                 ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     263              : 
     264           31 :                 auto &thisBaseboard = state.dataBaseboardRadiator->baseboards(ConvHWBaseboardNum);
     265           31 :                 thisBaseboard.FieldNames.allocate(NumNums);
     266           31 :                 thisBaseboard.FieldNames = s_ipsc->cNumericFieldNames;
     267              : 
     268              :                 // ErrorsFound will be set to True if problem was found, left untouched otherwise
     269           31 :                 VerifyUniqueBaseboardName(
     270           62 :                     state, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject + " Name");
     271              : 
     272           31 :                 thisBaseboard.EquipID = s_ipsc->cAlphaArgs(1); // name of this baseboard
     273           31 :                 thisBaseboard.EquipType = DataPlant::PlantEquipmentType::Baseboard_Conv_Water;
     274           31 :                 thisBaseboard.Schedule = s_ipsc->cAlphaArgs(2);
     275           31 :                 if (s_ipsc->lAlphaFieldBlanks(2)) {
     276            0 :                     thisBaseboard.availSched = Sched::GetScheduleAlwaysOn(state);
     277           31 :                 } else if ((thisBaseboard.availSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(2))) == nullptr) {
     278            0 :                     ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(2), s_ipsc->cAlphaArgs(2));
     279            0 :                     ErrorsFound = true;
     280              :                 }
     281              :                 // get inlet node number
     282           31 :                 thisBaseboard.WaterInletNode = GetOnlySingleNode(state,
     283           31 :                                                                  s_ipsc->cAlphaArgs(3),
     284              :                                                                  ErrorsFound,
     285              :                                                                  DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardConvectiveWater,
     286           31 :                                                                  s_ipsc->cAlphaArgs(1),
     287              :                                                                  DataLoopNode::NodeFluidType::Water,
     288              :                                                                  DataLoopNode::ConnectionType::Inlet,
     289              :                                                                  NodeInputManager::CompFluidStream::Primary,
     290              :                                                                  ObjectIsNotParent);
     291              :                 // get outlet node number
     292           62 :                 thisBaseboard.WaterOutletNode = GetOnlySingleNode(state,
     293           31 :                                                                   s_ipsc->cAlphaArgs(4),
     294              :                                                                   ErrorsFound,
     295              :                                                                   DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardConvectiveWater,
     296           31 :                                                                   s_ipsc->cAlphaArgs(1),
     297              :                                                                   DataLoopNode::NodeFluidType::Water,
     298              :                                                                   DataLoopNode::ConnectionType::Outlet,
     299              :                                                                   NodeInputManager::CompFluidStream::Primary,
     300              :                                                                   ObjectIsNotParent);
     301              : 
     302           31 :                 TestCompSet(state, cCMO_BBRadiator_Water, s_ipsc->cAlphaArgs(1), s_ipsc->cAlphaArgs(3), s_ipsc->cAlphaArgs(4), "Hot Water Nodes");
     303              : 
     304              :                 // Determine steam baseboard radiator system heating design capacity sizing method
     305           31 :                 if (Util::SameString(s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum), "HeatingDesignCapacity")) {
     306           31 :                     thisBaseboard.HeatingCapMethod = HeatingDesignCapacity;
     307           31 :                     if (!s_ipsc->lNumericFieldBlanks(iHeatDesignCapacityNumericNum)) {
     308           31 :                         thisBaseboard.ScaledHeatingCapacity = s_ipsc->rNumericArgs(iHeatDesignCapacityNumericNum);
     309           31 :                         if (thisBaseboard.ScaledHeatingCapacity < 0.0 && thisBaseboard.ScaledHeatingCapacity != AutoSize) {
     310            0 :                             ShowSevereError(state, format("{} = {}", cCMO_BBRadiator_Water, thisBaseboard.EquipID));
     311            0 :                             ShowContinueError(state,
     312            0 :                                               format("Illegal {} = {:.7T}",
     313            0 :                                                      s_ipsc->cNumericFieldNames(iHeatDesignCapacityNumericNum),
     314            0 :                                                      s_ipsc->rNumericArgs(iHeatDesignCapacityNumericNum)));
     315            0 :                             ErrorsFound = true;
     316              :                         }
     317              :                     } else {
     318            0 :                         ShowSevereError(state, format("{} = {}", cCMO_BBRadiator_Water, thisBaseboard.EquipID));
     319            0 :                         ShowContinueError(
     320            0 :                             state, format("Input for {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
     321            0 :                         ShowContinueError(state, format("Blank field not allowed for {}", s_ipsc->cNumericFieldNames(iHeatDesignCapacityNumericNum)));
     322            0 :                         ErrorsFound = true;
     323              :                     }
     324            0 :                 } else if (Util::SameString(s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum), "CapacityPerFloorArea")) {
     325            0 :                     thisBaseboard.HeatingCapMethod = CapacityPerFloorArea;
     326            0 :                     if (!s_ipsc->lNumericFieldBlanks(iHeatCapacityPerFloorAreaNumericNum)) {
     327            0 :                         thisBaseboard.ScaledHeatingCapacity = s_ipsc->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum);
     328            0 :                         if (thisBaseboard.ScaledHeatingCapacity <= 0.0) {
     329            0 :                             ShowSevereError(state, format("{} = {}", cCMO_BBRadiator_Water, thisBaseboard.EquipID));
     330            0 :                             ShowContinueError(
     331              :                                 state,
     332            0 :                                 format("Input for {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
     333            0 :                             ShowContinueError(state,
     334            0 :                                               format("Illegal {} = {:.7T}",
     335            0 :                                                      s_ipsc->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum),
     336            0 :                                                      s_ipsc->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum)));
     337            0 :                             ErrorsFound = true;
     338            0 :                         } else if (thisBaseboard.ScaledHeatingCapacity == AutoSize) {
     339            0 :                             ShowSevereError(state, format("{} = {}", cCMO_BBRadiator_Water, thisBaseboard.EquipID));
     340            0 :                             ShowContinueError(
     341              :                                 state,
     342            0 :                                 format("Input for {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
     343            0 :                             ShowContinueError(state,
     344            0 :                                               format("Illegal {} = Autosize", s_ipsc->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum)));
     345            0 :                             ErrorsFound = true;
     346              :                         }
     347              :                     } else {
     348            0 :                         ShowSevereError(state, format("{} = {}", cCMO_BBRadiator_Water, thisBaseboard.EquipID));
     349            0 :                         ShowContinueError(
     350            0 :                             state, format("Input for {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
     351            0 :                         ShowContinueError(state,
     352            0 :                                           format("Blank field not allowed for {}", s_ipsc->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum)));
     353            0 :                         ErrorsFound = true;
     354              :                     }
     355            0 :                 } else if (Util::SameString(s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum), "FractionOfAutosizedHeatingCapacity")) {
     356            0 :                     thisBaseboard.HeatingCapMethod = FractionOfAutosizedHeatingCapacity;
     357            0 :                     if (!s_ipsc->lNumericFieldBlanks(iHeatFracOfAutosizedCapacityNumericNum)) {
     358            0 :                         thisBaseboard.ScaledHeatingCapacity = s_ipsc->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum);
     359            0 :                         if (thisBaseboard.ScaledHeatingCapacity < 0.0) {
     360            0 :                             ShowSevereError(state, format("{} = {}", cCMO_BBRadiator_Water, thisBaseboard.EquipID));
     361            0 :                             ShowContinueError(state,
     362            0 :                                               format("Illegal {} = {:.7T}",
     363            0 :                                                      s_ipsc->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum),
     364            0 :                                                      s_ipsc->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum)));
     365            0 :                             ErrorsFound = true;
     366              :                         }
     367              :                     } else {
     368            0 :                         ShowSevereError(state, format("{} = {}", cCMO_BBRadiator_Water, thisBaseboard.EquipID));
     369            0 :                         ShowContinueError(
     370            0 :                             state, format("Input for {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
     371            0 :                         ShowContinueError(
     372            0 :                             state, format("Blank field not allowed for {}", s_ipsc->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum)));
     373            0 :                         ErrorsFound = true;
     374              :                     }
     375              :                 } else {
     376            0 :                     ShowSevereError(state, format("{} = {}", cCMO_BBRadiator_Water, thisBaseboard.EquipID));
     377            0 :                     ShowContinueError(state,
     378            0 :                                       format("Illegal {} = {}", s_ipsc->cAlphaFieldNames(iHeatCAPMAlphaNum), s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum)));
     379            0 :                     ErrorsFound = true;
     380              :                 }
     381              : 
     382           31 :                 thisBaseboard.UA = s_ipsc->rNumericArgs(4);
     383           31 :                 thisBaseboard.WaterVolFlowRateMax = s_ipsc->rNumericArgs(5);
     384           31 :                 thisBaseboard.Offset = s_ipsc->rNumericArgs(6);
     385              :                 // Set default convergence tolerance
     386           31 :                 if (thisBaseboard.Offset <= 0.0) {
     387            0 :                     thisBaseboard.Offset = 0.001;
     388              :                 }
     389              : 
     390           62 :                 thisBaseboard.ZonePtr = DataZoneEquipment::GetZoneEquipControlledZoneNum(
     391           31 :                     state, DataZoneEquipment::ZoneEquipType::BaseboardConvectiveWater, thisBaseboard.EquipID);
     392              : 
     393           31 :                 thisBaseboard.checkForZoneSizing(state); // check if any autosizing is being done
     394              :             }
     395              : 
     396           10 :             if (ErrorsFound) {
     397            0 :                 ShowFatalError(state, format("{}Errors found in getting input.  Preceding condition(s) cause termination.", RoutineName));
     398              :             }
     399              :         }
     400              : 
     401           41 :         for (int BaseboardNum = 1; BaseboardNum <= NumConvHWBaseboards; ++BaseboardNum) {
     402              : 
     403              :             // Setup Report variables for the unit
     404              :             // CurrentModuleObject='ZoneHVAC:Baseboard:Convective:Water'
     405           31 :             auto &thisBaseboard = state.dataBaseboardRadiator->baseboards(BaseboardNum);
     406           62 :             SetupOutputVariable(state,
     407              :                                 "Baseboard Total Heating Energy",
     408              :                                 Constant::Units::J,
     409           31 :                                 thisBaseboard.Energy,
     410              :                                 OutputProcessor::TimeStepType::System,
     411              :                                 OutputProcessor::StoreType::Sum,
     412           31 :                                 thisBaseboard.EquipID,
     413              :                                 Constant::eResource::EnergyTransfer,
     414              :                                 OutputProcessor::Group::HVAC,
     415              :                                 OutputProcessor::EndUseCat::Baseboard);
     416              : 
     417           62 :             SetupOutputVariable(state,
     418              :                                 "Baseboard Hot Water Energy",
     419              :                                 Constant::Units::J,
     420           31 :                                 thisBaseboard.Energy,
     421              :                                 OutputProcessor::TimeStepType::System,
     422              :                                 OutputProcessor::StoreType::Sum,
     423           31 :                                 thisBaseboard.EquipID,
     424              :                                 Constant::eResource::PlantLoopHeatingDemand,
     425              :                                 OutputProcessor::Group::HVAC,
     426              :                                 OutputProcessor::EndUseCat::Baseboard);
     427              : 
     428           62 :             SetupOutputVariable(state,
     429              :                                 "Baseboard Total Heating Rate",
     430              :                                 Constant::Units::W,
     431           31 :                                 thisBaseboard.Power,
     432              :                                 OutputProcessor::TimeStepType::System,
     433              :                                 OutputProcessor::StoreType::Average,
     434           31 :                                 thisBaseboard.EquipID);
     435              : 
     436           62 :             SetupOutputVariable(state,
     437              :                                 "Baseboard Hot Water Mass Flow Rate",
     438              :                                 Constant::Units::kg_s,
     439           31 :                                 thisBaseboard.WaterMassFlowRate,
     440              :                                 OutputProcessor::TimeStepType::System,
     441              :                                 OutputProcessor::StoreType::Average,
     442           31 :                                 thisBaseboard.EquipID);
     443              : 
     444           62 :             SetupOutputVariable(state,
     445              :                                 "Baseboard Air Mass Flow Rate",
     446              :                                 Constant::Units::kg_s,
     447           31 :                                 thisBaseboard.AirMassFlowRate,
     448              :                                 OutputProcessor::TimeStepType::System,
     449              :                                 OutputProcessor::StoreType::Average,
     450           31 :                                 thisBaseboard.EquipID);
     451              : 
     452           62 :             SetupOutputVariable(state,
     453              :                                 "Baseboard Air Inlet Temperature",
     454              :                                 Constant::Units::C,
     455           31 :                                 thisBaseboard.AirInletTemp,
     456              :                                 OutputProcessor::TimeStepType::System,
     457              :                                 OutputProcessor::StoreType::Average,
     458           31 :                                 thisBaseboard.EquipID);
     459              : 
     460           62 :             SetupOutputVariable(state,
     461              :                                 "Baseboard Air Outlet Temperature",
     462              :                                 Constant::Units::C,
     463           31 :                                 thisBaseboard.AirOutletTemp,
     464              :                                 OutputProcessor::TimeStepType::System,
     465              :                                 OutputProcessor::StoreType::Average,
     466           31 :                                 thisBaseboard.EquipID);
     467              : 
     468           62 :             SetupOutputVariable(state,
     469              :                                 "Baseboard Water Inlet Temperature",
     470              :                                 Constant::Units::C,
     471           31 :                                 thisBaseboard.WaterInletTemp,
     472              :                                 OutputProcessor::TimeStepType::System,
     473              :                                 OutputProcessor::StoreType::Average,
     474           31 :                                 thisBaseboard.EquipID);
     475              : 
     476           62 :             SetupOutputVariable(state,
     477              :                                 "Baseboard Water Outlet Temperature",
     478              :                                 Constant::Units::C,
     479           31 :                                 thisBaseboard.WaterOutletTemp,
     480              :                                 OutputProcessor::TimeStepType::System,
     481              :                                 OutputProcessor::StoreType::Average,
     482           31 :                                 thisBaseboard.EquipID);
     483              :         }
     484           10 :     }
     485              : 
     486       162355 :     void BaseboardParams::InitBaseboard(EnergyPlusData &state, int baseboardNum)
     487              :     {
     488              : 
     489              :         // SUBROUTINE INFORMATION:
     490              :         //       AUTHOR         Russ Taylor
     491              :         //       DATE WRITTEN   Nov 1997
     492              : 
     493              :         // PURPOSE OF THIS SUBROUTINE:
     494              :         // This subroutine initializes the Baseboard units during simulation.
     495              : 
     496              :         static constexpr std::string_view RoutineName = "BaseboardRadiator:InitBaseboard";
     497              : 
     498       162355 :         if (this->SetLoopIndexFlag && allocated(state.dataPlnt->PlantLoop)) {
     499           31 :             bool errFlag = false;
     500           31 :             PlantUtilities::ScanPlantLoopsForObject(state, this->EquipID, this->EquipType, this->plantLoc, errFlag, _, _, _, _, _);
     501           31 :             if (errFlag) {
     502            0 :                 ShowFatalError(state, "InitBaseboard: Program terminated for previous conditions.");
     503              :             }
     504           31 :             this->SetLoopIndexFlag = false;
     505              :         }
     506              : 
     507       162355 :         if (!state.dataGlobal->SysSizingCalc && this->MySizeFlag && !this->SetLoopIndexFlag) {
     508              :             // for each coil, do the sizing once.
     509           31 :             this->SizeBaseboard(state, baseboardNum);
     510              : 
     511           31 :             this->MySizeFlag = false;
     512              :         }
     513              : 
     514              :         // Do the Begin Environment initializations
     515       162355 :         if (state.dataGlobal->BeginEnvrnFlag && this->MyEnvrnFlag && !this->SetLoopIndexFlag) {
     516          237 :             int WaterInletNode = this->WaterInletNode;
     517          237 :             Real64 rho = this->plantLoc.loop->glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
     518          237 :             this->WaterMassFlowRateMax = rho * this->WaterVolFlowRateMax;
     519          237 :             PlantUtilities::InitComponentNodes(state, 0.0, this->WaterMassFlowRateMax, this->WaterInletNode, this->WaterOutletNode);
     520          237 :             state.dataLoopNodes->Node(WaterInletNode).Temp = Constant::HWInitConvTemp;
     521          237 :             Real64 Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, state.dataLoopNodes->Node(WaterInletNode).Temp, RoutineName);
     522          237 :             state.dataLoopNodes->Node(WaterInletNode).Enthalpy = Cp * state.dataLoopNodes->Node(WaterInletNode).Temp;
     523          237 :             state.dataLoopNodes->Node(WaterInletNode).Quality = 0.0;
     524          237 :             state.dataLoopNodes->Node(WaterInletNode).Press = 0.0;
     525          237 :             state.dataLoopNodes->Node(WaterInletNode).HumRat = 0.0;
     526              :             // pick a mass flow rate that depends on the max water mass flow rate. CR 8842 changed to factor of 2.0
     527          237 :             if (this->AirMassFlowRate <= 0.0) {
     528           32 :                 this->AirMassFlowRate = 2.0 * this->WaterMassFlowRateMax;
     529              :             }
     530          237 :             this->MyEnvrnFlag = false;
     531              :         }
     532              : 
     533       162355 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     534       161033 :             this->MyEnvrnFlag = true;
     535              :         }
     536              : 
     537              :         // Do the every time step initializations
     538       162355 :         int WaterInletNode = this->WaterInletNode;
     539       162355 :         int ZoneNode = state.dataZoneEquip->ZoneEquipConfig(this->ZonePtr).ZoneNode;
     540       162355 :         this->WaterMassFlowRate = state.dataLoopNodes->Node(WaterInletNode).MassFlowRate;
     541       162355 :         this->WaterInletTemp = state.dataLoopNodes->Node(WaterInletNode).Temp;
     542       162355 :         this->WaterInletEnthalpy = state.dataLoopNodes->Node(WaterInletNode).Enthalpy;
     543       162355 :         this->AirInletTemp = state.dataLoopNodes->Node(ZoneNode).Temp;
     544       162355 :         this->AirInletHumRat = state.dataLoopNodes->Node(ZoneNode).HumRat;
     545       162355 :     }
     546              : 
     547           31 :     void BaseboardParams::SizeBaseboard(EnergyPlusData &state, int baseboardNum)
     548              :     {
     549              : 
     550              :         // SUBROUTINE INFORMATION:
     551              :         //       AUTHOR         Fred Buhl
     552              :         //       DATE WRITTEN   February 2002
     553              :         //       MODIFIED       August 2013 Daeho Kang, add component sizing table entries
     554              :         //                      July 2014, B.Nigusse, added scalable sizing
     555              : 
     556              :         // PURPOSE OF THIS SUBROUTINE:
     557              :         // This subroutine is for sizing hot water baseboard components for which flow rates and UAs have not been
     558              :         // specified in the input.
     559              : 
     560              :         // METHODOLOGY EMPLOYED:
     561              :         // Obtains flow rates from the zone sizing arrays and plant sizing data. UAs are
     562              :         // calculated by numerically inverting the baseboard calculation routine.
     563              : 
     564              :         // SUBROUTINE PARAMETER DEFINITIONS:
     565           31 :         Real64 constexpr Acc = 0.0001; // Accuracy of result
     566           31 :         int constexpr MaxIte = 500;    // Maximum number of iterations
     567           31 :         static std::string const RoutineName = cCMO_BBRadiator_Water + ":SizeBaseboard";
     568              : 
     569              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     570           31 :         Real64 DesCoilLoad(0.0);
     571              :         Real64 UA0; // lower bound for UA
     572              :         Real64 UA1; // upper bound for UA
     573              :         Real64 UA;
     574           31 :         bool ErrorsFound(false);             // If errors detected in input
     575              :         Real64 rho;                          // local fluid density
     576              :         Real64 Cp;                           // local fluid specific heat
     577           31 :         Real64 WaterVolFlowRateMaxDes(0.0);  // Design water volume flow for reporting
     578           31 :         Real64 WaterVolFlowRateMaxUser(0.0); // User hard-sized volume flow for reporting
     579           31 :         Real64 UADes(0.0);                   // Design UA value for reporting
     580           31 :         Real64 UAUser(0.0);                  // User hard-sized value for reporting
     581              :         Real64 TempSize;                     // autosized value of coil input field
     582              : 
     583              :         // find the appropriate heating Plant Sizing object
     584           31 :         int PltSizHeatNum = this->plantLoc.loop->PlantSizNum;
     585              : 
     586           31 :         if (PltSizHeatNum > 0) {
     587              : 
     588           24 :             state.dataSize->DataScalableCapSizingON = false;
     589              : 
     590           24 :             if (state.dataSize->CurZoneEqNum > 0) {
     591           24 :                 bool FlowAutoSize = false; // Indicator to autosizing water volume flow
     592              : 
     593           24 :                 if (this->WaterVolFlowRateMax == DataSizing::AutoSize) {
     594           23 :                     FlowAutoSize = true;
     595              :                 }
     596           24 :                 if (!FlowAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation should continue
     597            1 :                     if (this->WaterVolFlowRateMax > 0.0) {
     598            1 :                         BaseSizer::reportSizerOutput(
     599              :                             state, cCMO_BBRadiator_Water, this->EquipID, "User-Specified Maximum Water Flow Rate [m3/s]", this->WaterVolFlowRateMax);
     600              :                     }
     601              :                 } else {
     602           23 :                     auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
     603           23 :                     auto const &finalZoneSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum);
     604           23 :                     std::string_view const CompType = cCMO_BBRadiator_Water;
     605           23 :                     std::string_view const CompName = this->EquipID;
     606           23 :                     state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
     607           23 :                     state.dataSize->DataZoneNumber = this->ZonePtr;
     608           23 :                     int SizingMethod = HVAC::HeatingCapacitySizing;
     609           23 :                     int FieldNum = 1;
     610           23 :                     std::string const SizingString = format("{} [W]", this->FieldNames(FieldNum));
     611           23 :                     int CapSizingMethod = this->HeatingCapMethod;
     612           23 :                     zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
     613           23 :                     if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
     614              :                         CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
     615              : 
     616           23 :                         if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
     617           23 :                             if (this->ScaledHeatingCapacity == DataSizing::AutoSize) {
     618           23 :                                 zoneEqSizing.DesHeatingLoad = finalZoneSizing.NonAirSysDesHeatLoad;
     619              :                             } else {
     620            0 :                                 zoneEqSizing.DesHeatingLoad = this->ScaledHeatingCapacity;
     621              :                             }
     622           23 :                             zoneEqSizing.HeatingCapacity = true;
     623           23 :                             TempSize = zoneEqSizing.DesHeatingLoad;
     624            0 :                         } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
     625            0 :                             zoneEqSizing.HeatingCapacity = true;
     626            0 :                             zoneEqSizing.DesHeatingLoad =
     627            0 :                                 this->ScaledHeatingCapacity * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
     628            0 :                             TempSize = zoneEqSizing.DesHeatingLoad;
     629            0 :                             state.dataSize->DataScalableCapSizingON = true;
     630            0 :                         } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
     631            0 :                             zoneEqSizing.HeatingCapacity = true;
     632            0 :                             state.dataSize->DataFracOfAutosizedHeatingCapacity = this->ScaledHeatingCapacity;
     633            0 :                             zoneEqSizing.DesHeatingLoad = finalZoneSizing.NonAirSysDesHeatLoad;
     634            0 :                             TempSize = DataSizing::AutoSize;
     635            0 :                             state.dataSize->DataScalableCapSizingON = true;
     636              :                         } else {
     637            0 :                             TempSize = this->ScaledHeatingCapacity;
     638              :                         }
     639           23 :                         bool PrintFlag = false; // TRUE when sizing information is reported in the eio file
     640           23 :                         bool errorsFound = false;
     641           23 :                         HeatingCapacitySizer sizerHeatingCapacity;
     642           23 :                         sizerHeatingCapacity.overrideSizingString(SizingString);
     643           23 :                         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     644           23 :                         DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
     645           23 :                         state.dataSize->DataScalableCapSizingON = false;
     646           23 :                     } else {
     647            0 :                         DesCoilLoad = 0.0;
     648              :                     }
     649              : 
     650           23 :                     if (DesCoilLoad >= SmallLoad) {
     651           23 :                         Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
     652           23 :                         rho = this->plantLoc.loop->glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
     653           23 :                         WaterVolFlowRateMaxDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
     654              :                     } else {
     655            0 :                         WaterVolFlowRateMaxDes = 0.0;
     656              :                     }
     657              : 
     658           23 :                     if (FlowAutoSize) {
     659           23 :                         this->WaterVolFlowRateMax = WaterVolFlowRateMaxDes;
     660           23 :                         BaseSizer::reportSizerOutput(
     661              :                             state, cCMO_BBRadiator_Water, this->EquipID, "Design Size Maximum Water Flow Rate [m3/s]", WaterVolFlowRateMaxDes);
     662              :                     } else { // hard-sized with sizing data
     663            0 :                         if (this->WaterVolFlowRateMax > 0.0 && WaterVolFlowRateMaxDes > 0.0) {
     664            0 :                             WaterVolFlowRateMaxUser = this->WaterVolFlowRateMax;
     665            0 :                             BaseSizer::reportSizerOutput(state,
     666              :                                                          cCMO_BBRadiator_Water,
     667              :                                                          this->EquipID,
     668              :                                                          "Design Size Maximum Water Flow Rate [m3/s]",
     669              :                                                          WaterVolFlowRateMaxDes,
     670              :                                                          "User-Specified Maximum Water Flow Rate [m3/s]",
     671              :                                                          WaterVolFlowRateMaxUser);
     672              :                             // Report a warning to note difference between the two
     673            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
     674            0 :                                 if ((std::abs(WaterVolFlowRateMaxDes - WaterVolFlowRateMaxUser) / WaterVolFlowRateMaxUser) >
     675            0 :                                     state.dataSize->AutoVsHardSizingThreshold) {
     676            0 :                                     ShowMessage(
     677              :                                         state,
     678            0 :                                         format("SizeBaseboard: Potential issue with equipment sizing for ZoneHVAC:Baseboard:Convective:Water=\"{}\".",
     679            0 :                                                this->EquipID));
     680            0 :                                     ShowContinueError(state,
     681            0 :                                                       format("User-Specified Maximum Water Flow Rate of {:.5R} [m3/s]", WaterVolFlowRateMaxUser));
     682            0 :                                     ShowContinueError(
     683            0 :                                         state, format("differs from Design Size Maximum Water Flow Rate of {:.5R} [m3/s]", WaterVolFlowRateMaxDes));
     684            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
     685            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
     686              :                                 }
     687              :                             }
     688              :                         }
     689              :                     }
     690           23 :                 }
     691              : 
     692              :                 // UA sizing
     693           24 :                 bool UAAutoSize = false; // Indicator to autosizing UA
     694              :                 // Set hard-sized values to the local variable to correct a false indication after SolFla function calculation
     695           24 :                 if (this->UA == DataSizing::AutoSize) {
     696           23 :                     UAAutoSize = true;
     697              :                 } else {
     698            1 :                     UAUser = this->UA;
     699              :                 }
     700           24 :                 if (!UAAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation should continue
     701            1 :                     if (this->UA > 0.0) {
     702            1 :                         BaseSizer::reportSizerOutput(
     703              :                             state, cCMO_BBRadiator_Water, this->EquipID, "User-Specified U-Factor Times Area Value [W/K]", this->UA);
     704              :                     }
     705              :                 } else {
     706           23 :                     auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
     707           23 :                     auto const &finalZoneSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum);
     708           23 :                     this->WaterInletTemp = state.dataSize->PlantSizData(PltSizHeatNum).ExitTemp;
     709           23 :                     this->AirInletTemp = finalZoneSizing.ZoneTempAtHeatPeak;
     710           23 :                     this->AirInletHumRat = finalZoneSizing.ZoneHumRatAtHeatPeak;
     711           23 :                     rho = this->plantLoc.loop->glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
     712           23 :                     state.dataLoopNodes->Node(this->WaterInletNode).MassFlowRate = rho * this->WaterVolFlowRateMax;
     713              : 
     714           23 :                     std::string_view const CompType = cCMO_BBRadiator_Water;
     715           23 :                     std::string_view const CompName = this->EquipID;
     716           23 :                     state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
     717           23 :                     state.dataSize->DataZoneNumber = this->ZonePtr;
     718           23 :                     int SizingMethod = HVAC::HeatingCapacitySizing;
     719           23 :                     int FieldNum = 1;
     720           23 :                     std::string const SizingString = format("{} [W]", this->FieldNames(FieldNum));
     721           23 :                     int CapSizingMethod = this->HeatingCapMethod;
     722           23 :                     zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
     723           23 :                     if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
     724              :                         CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
     725           23 :                         if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
     726           23 :                             if (this->ScaledHeatingCapacity == DataSizing::AutoSize) {
     727           23 :                                 zoneEqSizing.DesHeatingLoad = finalZoneSizing.NonAirSysDesHeatLoad;
     728              :                             } else {
     729            0 :                                 zoneEqSizing.DesHeatingLoad = this->ScaledHeatingCapacity;
     730              :                             }
     731           23 :                             zoneEqSizing.HeatingCapacity = true;
     732           23 :                             TempSize = zoneEqSizing.DesHeatingLoad;
     733            0 :                         } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
     734            0 :                             zoneEqSizing.HeatingCapacity = true;
     735            0 :                             zoneEqSizing.DesHeatingLoad =
     736            0 :                                 this->ScaledHeatingCapacity * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
     737            0 :                             TempSize = zoneEqSizing.DesHeatingLoad;
     738            0 :                             state.dataSize->DataScalableCapSizingON = true;
     739            0 :                         } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
     740            0 :                             zoneEqSizing.HeatingCapacity = true;
     741            0 :                             state.dataSize->DataFracOfAutosizedHeatingCapacity = this->ScaledHeatingCapacity;
     742            0 :                             zoneEqSizing.DesHeatingLoad = finalZoneSizing.NonAirSysDesHeatLoad;
     743            0 :                             TempSize = DataSizing::AutoSize;
     744            0 :                             state.dataSize->DataScalableCapSizingON = true;
     745              :                         } else {
     746            0 :                             TempSize = this->ScaledHeatingCapacity;
     747              :                         }
     748           23 :                         bool PrintFlag = false;
     749           23 :                         bool errorsFound = false;
     750           23 :                         HeatingCapacitySizer sizerHeatingCapacity;
     751           23 :                         sizerHeatingCapacity.overrideSizingString(SizingString);
     752           23 :                         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     753           23 :                         DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
     754           23 :                         state.dataSize->DataScalableCapSizingON = false;
     755           23 :                     } else {
     756            0 :                         DesCoilLoad = 0.0; // FinalZoneSizing(CurZoneEqNum).NonAirSysDesHeatLoad;
     757              :                     }
     758           23 :                     if (DesCoilLoad >= SmallLoad) {
     759              :                         // pick an air  mass flow rate that is twice the water mass flow rate (CR8842)
     760           23 :                         this->DesAirMassFlowRate = 2.0 * rho * this->WaterVolFlowRateMax;
     761              :                         // set the lower and upper limits on the UA
     762           23 :                         UA0 = 0.001 * DesCoilLoad;
     763           23 :                         UA1 = DesCoilLoad;
     764              : 
     765              :                         // before iterating on a design UA check output at lower UA bound
     766           23 :                         this->UA = UA0;
     767           23 :                         Real64 LoadMet = 0.0;
     768           23 :                         SimHWConvective(state, baseboardNum, LoadMet);
     769           23 :                         if (LoadMet < DesCoilLoad) { // baseboard output should be below design load
     770              :                             // now check output at max UA (where UA = design load)
     771           23 :                             this->UA = UA1;
     772           23 :                             SimHWConvective(state, baseboardNum, LoadMet);
     773              : 
     774           23 :                             if (LoadMet > DesCoilLoad) { // if the load met is greater than design load, OK to iterate on UA
     775              :                                 // Invert the baseboard model: given the design inlet conditions and the design load, find the design UA.
     776          299 :                                 auto f = [&state, baseboardNum, DesCoilLoad](Real64 UA) {
     777          299 :                                     state.dataBaseboardRadiator->baseboards(baseboardNum).UA = UA;
     778          299 :                                     int localBaseBoardNum = baseboardNum;
     779          299 :                                     Real64 LoadMet = 0.0;
     780          299 :                                     SimHWConvective(state, localBaseBoardNum, LoadMet);
     781          299 :                                     return (DesCoilLoad - LoadMet) / DesCoilLoad;
     782           23 :                                 };
     783           23 :                                 int SolFla = 0;
     784           23 :                                 General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
     785              :                                 // if the numerical inversion failed, issue error messages.
     786           23 :                                 if (SolFla == -1) {
     787            0 :                                     ShowSevereError(state,
     788            0 :                                                     format("SizeBaseboard: Autosizing of HW baseboard UA failed for {}=\"{}\"",
     789              :                                                            cCMO_BBRadiator_Water,
     790            0 :                                                            this->EquipID));
     791            0 :                                     ShowContinueError(state, "Iteration limit exceeded in calculating coil UA");
     792            0 :                                     if (UAAutoSize) {
     793            0 :                                         ErrorsFound = true;
     794              :                                     } else {
     795            0 :                                         ShowContinueError(
     796              :                                             state, "Could not calculate design value for comparison to user value, and the simulation continues");
     797            0 :                                         UA = 0.0;
     798              :                                     }
     799           23 :                                 } else if (SolFla == -2) {
     800            0 :                                     ShowSevereError(state,
     801            0 :                                                     format("SizeBaseboard: Autosizing of HW baseboard UA failed for {}=\"{}\"",
     802              :                                                            cCMO_BBRadiator_Water,
     803            0 :                                                            this->EquipID));
     804            0 :                                     ShowContinueError(state, "Bad starting values for UA");
     805            0 :                                     if (UAAutoSize) {
     806            0 :                                         ErrorsFound = true;
     807              :                                     } else {
     808            0 :                                         ShowContinueError(
     809              :                                             state, "Could not calculate design value for comparison to user value, and the simulation continues");
     810            0 :                                         UA = 0.0;
     811              :                                     }
     812              :                                 }
     813           23 :                                 UADes = UA; // baseboard->baseboards(BaseboardNum)%UA = UA
     814              :                             } else {        // baseboard design load is greater than output at UA = design load so set UA = design load
     815            0 :                                 UADes = UA1;
     816            0 :                                 if (UAAutoSize) {
     817            0 :                                     ShowWarningError(state,
     818            0 :                                                      format("SizeBaseboard: Autosizing of HW baseboard UA failed for {}=\"{}\"",
     819              :                                                             cCMO_BBRadiator_Water,
     820            0 :                                                             this->EquipID));
     821            0 :                                     ShowContinueError(
     822            0 :                                         state, format("Design UA set equal to design coil load for {}=\"{}\"", cCMO_BBRadiator_Water, this->EquipID));
     823            0 :                                     ShowContinueError(state, format("Design coil load used during sizing = {:.5R} W.", DesCoilLoad));
     824            0 :                                     ShowContinueError(state, format("Inlet water temperature used during sizing = {:.5R} C.", this->WaterInletTemp));
     825              :                                 }
     826              :                             }
     827              :                         } else { // baseboard design load is less than output at UA = 0.001 * design load so set UA to minimum value
     828            0 :                             UADes = UA0;
     829            0 :                             if (UAAutoSize) {
     830            0 :                                 ShowWarningError(state,
     831            0 :                                                  format("SizeBaseboard: Autosizing of HW baseboard UA failed for {}=\"{}\"",
     832              :                                                         cCMO_BBRadiator_Water,
     833            0 :                                                         this->EquipID));
     834            0 :                                 ShowContinueError(
     835              :                                     state,
     836            0 :                                     format("Design UA set equal to 0.001 * design coil load for {}=\"{}\"", cCMO_BBRadiator_Water, this->EquipID));
     837            0 :                                 ShowContinueError(state, format("Design coil load used during sizing = {:.5R} W.", DesCoilLoad));
     838            0 :                                 ShowContinueError(state, format("Inlet water temperature used during sizing = {:.5R} C.", this->WaterInletTemp));
     839              :                             }
     840              :                         }
     841              : 
     842              :                     } else {
     843            0 :                         UADes = 0.0;
     844              :                     }
     845              : 
     846           23 :                     if (UAAutoSize) {
     847           23 :                         this->UA = UADes;
     848           23 :                         BaseSizer::reportSizerOutput(
     849              :                             state, cCMO_BBRadiator_Water, this->EquipID, "Design Size U-Factor Times Area Value [W/K]", UADes);
     850              :                     } else {               // Hard-sized with sizing data
     851            0 :                         this->UA = UAUser; // need to put this back as HWBaseboardUAResidual will have reset it, CR9377
     852            0 :                         if (UAUser > 0.0 && UADes > 0.0) {
     853            0 :                             BaseSizer::reportSizerOutput(state,
     854              :                                                          cCMO_BBRadiator_Water,
     855              :                                                          this->EquipID,
     856              :                                                          "Design Size U-Factor Times Area Value [W/K]",
     857              :                                                          UADes,
     858              :                                                          "User-Specified U-Factor Times Area Value [W/K]",
     859              :                                                          UAUser);
     860              :                             // Report difference between design size and hard-sized values
     861            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
     862            0 :                                 if ((std::abs(UADes - UAUser) / UAUser) > state.dataSize->AutoVsHardSizingThreshold) {
     863            0 :                                     ShowMessage(
     864              :                                         state,
     865            0 :                                         format("SizeBaseboard: Potential issue with equipment sizing for ZoneHVAC:Baseboard:Convective:Water=\"{}\".",
     866            0 :                                                this->EquipID));
     867            0 :                                     ShowContinueError(state, format("User-Specified U-Factor Times Area Value of {:.2R} [W/K]", UAUser));
     868            0 :                                     ShowContinueError(state, format("differs from Design Size U-Factor Times Area Value of {:.2R} [W/K]", UADes));
     869            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
     870            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
     871              :                                 }
     872              :                             }
     873              :                         }
     874              :                     }
     875           23 :                 }
     876              :             }
     877              :         } else {
     878              :             // if there is no heating Sizing:Plant object and autosizing was requested, issue an error message
     879            7 :             if (this->WaterVolFlowRateMax == DataSizing::AutoSize || this->UA == DataSizing::AutoSize) {
     880            0 :                 ShowSevereError(state, format("SizeBaseboard: {}=\"{}\"", cCMO_BBRadiator_Water, this->EquipID));
     881            0 :                 ShowContinueError(state, "...Autosizing of hot water baseboard requires a heating loop Sizing:Plant object");
     882            0 :                 ErrorsFound = true;
     883              :             }
     884              :         }
     885              : 
     886              :         // save the design water flow rate for use by the water loop sizing algorithms
     887           31 :         PlantUtilities::RegisterPlantCompDesignFlow(state, this->WaterInletNode, this->WaterVolFlowRateMax);
     888              : 
     889           31 :         if (ErrorsFound) {
     890            0 :             ShowFatalError(state, "SizeBaseboard: Preceding sizing errors cause program termination");
     891              :         }
     892           31 :     }
     893              : 
     894           31 :     void BaseboardParams::checkForZoneSizing(EnergyPlusData &state)
     895              :     {
     896              :         // If any sizing is requested, check that zone sizing has been done
     897              :         // Condition 1: Is UA autosized)?
     898              :         // Condition 2: Is max flow rate  autosized?
     899              :         // Condition 3: Is HeatingDesignCapacity used and autosized)
     900              :         // Condition 4: Is FractionOfAutosizedHeatingCapacity used and heating capacity is autosized
     901           31 :         if ((this->UA == DataSizing::AutoSize) || (this->WaterVolFlowRateMax == DataSizing::AutoSize) ||
     902            8 :             ((this->HeatingCapMethod == DataSizing::HeatingDesignCapacity) && (this->ScaledHeatingCapacity == DataSizing::AutoSize)) ||
     903            1 :             ((this->HeatingCapMethod == DataSizing::FractionOfAutosizedHeatingCapacity) && (this->ScaledHeatingCapacity == DataSizing::AutoSize))) {
     904           30 :             CheckZoneSizing(state, cCMO_BBRadiator_Water, this->EquipID);
     905              :         }
     906           31 :     }
     907              : 
     908       731605 :     void SimHWConvective(EnergyPlusData &state, int &BaseboardNum, Real64 &LoadMet)
     909              :     {
     910              :         // SUBROUTINE INFORMATION:
     911              :         //       AUTHOR         Russ Taylor
     912              :         //       DATE WRITTEN   Nov 1997
     913              :         //       MODIFIED       May 2000 Fred Buhl
     914              :         //       RE-ENGINEERED  na
     915              : 
     916              :         // PURPOSE OF THIS SUBROUTINE: This subroutine calculates the heat exchange rate
     917              :         // in a pure convective baseboard heater.  The heater is assumed to be crossflow
     918              :         // with both fluids unmixed. The air flow is buoyancy driven and a constant air
     919              :         // flow velocity of 0.5m/s is assumed. The solution is by the effectiveness-NTU
     920              :         // method found in Icropera and DeWitt, Fundamentals of Heat and Mass Transfer,
     921              :         // Chapter 11.4, p. 523, eq. 11.33
     922              : 
     923              :         // REFERENCES:
     924              :         // Icropera and DeWitt, Fundamentals of Heat and Mass Transfer,
     925              :         // Chapter 11.4, p. 523, eq. 11.33
     926              : 
     927              :         // Using/Aliasing
     928              :         using namespace DataSizing;
     929              :         using HVAC::SmallLoad;
     930              :         using PlantUtilities::SetActuatedBranchFlowRate;
     931              : 
     932              :         // SUBROUTINE PARAMETER DEFINITIONS:
     933       731605 :         static std::string const RoutineName(cCMO_BBRadiator_Water + ":SimHWConvective");
     934              : 
     935              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     936              :         int ZoneNum;
     937              :         Real64 WaterInletTemp;
     938              :         Real64 AirInletTemp;
     939              :         Real64 CpAir;
     940              :         Real64 CpWater;
     941              :         Real64 AirMassFlowRate;
     942              :         Real64 WaterMassFlowRate;
     943              :         Real64 CapacitanceAir;
     944              :         Real64 CapacitanceWater;
     945              :         Real64 CapacitanceMax;
     946              :         Real64 CapacitanceMin;
     947              :         Real64 CapacityRatio;
     948              :         Real64 NTU;
     949              :         Real64 Effectiveness;
     950              :         Real64 WaterOutletTemp;
     951              :         Real64 AirOutletTemp;
     952              :         Real64 AA;
     953              :         Real64 BB;
     954              :         Real64 CC;
     955              :         Real64 QZnReq;
     956              : 
     957       731605 :         auto &baseboard = state.dataBaseboardRadiator->baseboards(BaseboardNum);
     958              : 
     959       731605 :         ZoneNum = baseboard.ZonePtr;
     960       731605 :         QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP;
     961       731605 :         if (baseboard.MySizeFlag) {
     962          345 :             QZnReq = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad; // If in sizing, assign design condition
     963              :         }
     964              : 
     965       731605 :         WaterInletTemp = baseboard.WaterInletTemp;
     966       731605 :         AirInletTemp = baseboard.AirInletTemp;
     967              : 
     968       731605 :         CpWater = baseboard.plantLoc.loop->glycol->getSpecificHeat(state, WaterInletTemp, RoutineName);
     969       731605 :         CpAir = PsyCpAirFnW(baseboard.AirInletHumRat);
     970              : 
     971       731605 :         if (baseboard.DesAirMassFlowRate > 0.0) { // If UA is autosized, assign design condition
     972       511379 :             AirMassFlowRate = baseboard.DesAirMassFlowRate;
     973              :         } else {
     974       220226 :             AirMassFlowRate = baseboard.AirMassFlowRate;
     975              :             // pick a mass flow rate that depends on the max water mass flow rate. CR 8842 changed to factor of 2.0
     976       220226 :             if (AirMassFlowRate <= 0.0) {
     977        17046 :                 AirMassFlowRate = 2.0 * baseboard.WaterMassFlowRateMax;
     978              :             }
     979              :         }
     980              : 
     981       731605 :         WaterMassFlowRate = state.dataLoopNodes->Node(baseboard.WaterInletNode).MassFlowRate;
     982       731605 :         CapacitanceAir = CpAir * AirMassFlowRate;
     983              : 
     984      1459511 :         if (QZnReq > SmallLoad && (!state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) || baseboard.MySizeFlag) &&
     985      2191116 :             (baseboard.availSched->getCurrentVal() > 0 || baseboard.MySizeFlag) && (WaterMassFlowRate > 0.0)) {
     986              : 
     987       664682 :             CapacitanceWater = CpWater * WaterMassFlowRate;
     988       664682 :             CapacitanceMax = max(CapacitanceAir, CapacitanceWater);
     989       664682 :             CapacitanceMin = min(CapacitanceAir, CapacitanceWater);
     990       664682 :             CapacityRatio = CapacitanceMin / CapacitanceMax;
     991       664682 :             NTU = baseboard.UA / CapacitanceMin;
     992              :             // The effectiveness is given by the following formula:
     993              :             // Effectiveness = 1. - EXP((1./CapacityRatio)*(NTU)**0.22*(EXP(-CapacityRatio*(NTU)**0.78)-1.))
     994              :             // To prevent possible underflows (numbers smaller than the computer can handle) we must break
     995              :             // the calculation up into steps and check the size of the exponential arguments.
     996       664682 :             AA = -CapacityRatio * std::pow(NTU, 0.78);
     997       664682 :             if (AA < DataPrecisionGlobals::EXP_LowerLimit) {
     998            0 :                 BB = 0.0;
     999              :             } else {
    1000       664682 :                 BB = std::exp(AA);
    1001              :             }
    1002       664682 :             CC = (1.0 / CapacityRatio) * std::pow(NTU, 0.22) * (BB - 1.0);
    1003       664682 :             if (CC < DataPrecisionGlobals::EXP_LowerLimit) {
    1004        17101 :                 Effectiveness = 1.0;
    1005              :             } else {
    1006       647581 :                 Effectiveness = 1.0 - std::exp(CC);
    1007              :             }
    1008       664682 :             AirOutletTemp = AirInletTemp + Effectiveness * CapacitanceMin * (WaterInletTemp - AirInletTemp) / CapacitanceAir;
    1009       664682 :             WaterOutletTemp = WaterInletTemp - CapacitanceAir * (AirOutletTemp - AirInletTemp) / CapacitanceWater;
    1010       664682 :             LoadMet = CapacitanceWater * (WaterInletTemp - WaterOutletTemp);
    1011       664682 :             baseboard.WaterOutletEnthalpy = baseboard.WaterInletEnthalpy - LoadMet / WaterMassFlowRate;
    1012              :         } else {
    1013        66923 :             AirOutletTemp = AirInletTemp;
    1014        66923 :             WaterOutletTemp = WaterInletTemp;
    1015        66923 :             LoadMet = 0.0;
    1016        66923 :             baseboard.WaterOutletEnthalpy = baseboard.WaterInletEnthalpy;
    1017        66923 :             WaterMassFlowRate = 0.0;
    1018              : 
    1019        66923 :             SetActuatedBranchFlowRate(state, WaterMassFlowRate, baseboard.WaterInletNode, baseboard.plantLoc, false);
    1020        66923 :             AirMassFlowRate = 0.0;
    1021              :         }
    1022              : 
    1023       731605 :         baseboard.WaterOutletTemp = WaterOutletTemp;
    1024       731605 :         baseboard.AirOutletTemp = AirOutletTemp;
    1025       731605 :         baseboard.Power = LoadMet;
    1026       731605 :         baseboard.WaterMassFlowRate = WaterMassFlowRate;
    1027       731605 :         baseboard.AirMassFlowRate = AirMassFlowRate;
    1028       731605 :     }
    1029              : 
    1030       162355 :     void UpdateBaseboard(EnergyPlusData &state, int &BaseboardNum)
    1031              :     {
    1032              : 
    1033              :         // SUBROUTINE INFORMATION:
    1034              :         //       AUTHOR         Russ Taylor
    1035              :         //       DATE WRITTEN   Nov 1997
    1036              :         //       MODIFIED       na
    1037              :         //       RE-ENGINEERED  na
    1038              : 
    1039              :         // Using/Aliasing
    1040              :         using PlantUtilities::SafeCopyPlantNode;
    1041              : 
    1042              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1043              :         int WaterInletNode;
    1044              :         int WaterOutletNode;
    1045              : 
    1046       162355 :         auto &baseboard = state.dataBaseboardRadiator;
    1047              : 
    1048       162355 :         WaterInletNode = baseboard->baseboards(BaseboardNum).WaterInletNode;
    1049       162355 :         WaterOutletNode = baseboard->baseboards(BaseboardNum).WaterOutletNode;
    1050              : 
    1051       162355 :         SafeCopyPlantNode(state, WaterInletNode, WaterOutletNode);
    1052              :         // Set the outlet air nodes of the Baseboard
    1053              :         // Set the outlet water nodes for the Coil
    1054       162355 :         state.dataLoopNodes->Node(WaterOutletNode).Temp = baseboard->baseboards(BaseboardNum).WaterOutletTemp;
    1055       162355 :         state.dataLoopNodes->Node(WaterOutletNode).Enthalpy = baseboard->baseboards(BaseboardNum).WaterOutletEnthalpy;
    1056       162355 :     }
    1057              : 
    1058              : } // namespace BaseboardRadiator
    1059              : 
    1060              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1