LCOV - code coverage report
Current view: top level - EnergyPlus - BaseboardRadiator.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 74.8 % 507 379
Test Date: 2025-05-22 16:09:37 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        12291 :     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        12291 :         if (state.dataBaseboardRadiator->getInputFlag) {
     118            1 :             GetBaseboardInput(state);
     119            1 :             state.dataBaseboardRadiator->getInputFlag = false;
     120              :         }
     121              : 
     122              :         // Find the correct Baseboard Equipment
     123        12291 :         if (CompIndex == 0) {
     124            3 :             int BaseboardNum = Util::FindItemInList(EquipName, state.dataBaseboardRadiator->baseboards, &BaseboardParams::EquipID);
     125            3 :             if (BaseboardNum == 0) {
     126            0 :                 ShowFatalError(state, format("SimBaseboard: Unit not found={}", EquipName));
     127              :             }
     128            3 :             CompIndex = BaseboardNum;
     129              :         }
     130        12291 :         assert(CompIndex <= (int)state.dataBaseboardRadiator->baseboards.size());
     131        12291 :         auto &thisBaseboard = state.dataBaseboardRadiator->baseboards(CompIndex);
     132        12291 :         if (thisBaseboard.CheckEquipName) {
     133            3 :             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            3 :             thisBaseboard.CheckEquipName = false;
     141              :         }
     142              : 
     143        12291 :         thisBaseboard.InitBaseboard(state, CompIndex);
     144              : 
     145        12291 :         Real64 QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ControlledZoneNum).RemainingOutputReqToHeatSP;
     146        12291 :         Real64 MaxWaterFlow = 0.0;
     147        12291 :         Real64 MinWaterFlow = 0.0;
     148        12291 :         Real64 DummyMdot = 0.0;
     149              : 
     150        12291 :         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         6243 :             thisBaseboard.WaterOutletTemp = thisBaseboard.WaterInletTemp;
     156         6243 :             thisBaseboard.AirOutletTemp = thisBaseboard.AirInletTemp;
     157         6243 :             thisBaseboard.Power = 0.0;
     158         6243 :             thisBaseboard.WaterMassFlowRate = 0.0;
     159              :             // init hot water flow rate to zero
     160         6243 :             DummyMdot = 0.0;
     161         6243 :             PlantUtilities::SetActuatedBranchFlowRate(state, DummyMdot, thisBaseboard.WaterInletNode, thisBaseboard.plantLoc, false);
     162              : 
     163              :         } else {
     164              :             // init hot water flow rate to zero
     165         6048 :             DummyMdot = 0.0;
     166         6048 :             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         6048 :             if (FirstHVACIteration) {
     171         3024 :                 MaxWaterFlow = thisBaseboard.WaterMassFlowRateMax;
     172         3024 :                 MinWaterFlow = 0.0;
     173              :             } else {
     174         3024 :                 MaxWaterFlow = state.dataLoopNodes->Node(thisBaseboard.WaterInletNode).MassFlowRateMaxAvail;
     175         3024 :                 MinWaterFlow = state.dataLoopNodes->Node(thisBaseboard.WaterInletNode).MassFlowRateMinAvail;
     176              :             }
     177              : 
     178        18144 :             ControlCompOutput(state,
     179         6048 :                               thisBaseboard.EquipID,
     180              :                               cCMO_BBRadiator_Water,
     181              :                               CompIndex,
     182              :                               FirstHVACIteration,
     183              :                               QZnReq,
     184              :                               thisBaseboard.WaterInletNode,
     185              :                               MaxWaterFlow,
     186              :                               MinWaterFlow,
     187              :                               thisBaseboard.Offset,
     188         6048 :                               thisBaseboard.ControlCompTypeNum,
     189         6048 :                               thisBaseboard.CompErrIndex,
     190              :                               _,
     191              :                               _,
     192              :                               _,
     193              :                               _,
     194              :                               _,
     195         6048 :                               thisBaseboard.plantLoc);
     196              : 
     197         6048 :             PowerMet = thisBaseboard.Power;
     198              :         }
     199              : 
     200        12291 :         UpdateBaseboard(state, CompIndex);
     201        12291 :         thisBaseboard.Energy = thisBaseboard.Power * state.dataHVACGlobal->TimeStepSysSec;
     202        12291 :     }
     203              : 
     204            2 :     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            2 :         int constexpr iHeatCAPMAlphaNum = 5;                   // get input index to water baseboard Radiator system heating capacity sizing method
     228            2 :         int constexpr iHeatDesignCapacityNumericNum = 1;       // get input index to water baseboard Radiator system electric heating capacity
     229            2 :         int constexpr iHeatCapacityPerFloorAreaNumericNum = 2; // index to baseboard Radiator system electric heating capacity per floor area sizing
     230            2 :         int constexpr iHeatFracOfAutosizedCapacityNumericNum = 3; //  index to baseboard heating capacity fraction of autosized heating capacity
     231              : 
     232            2 :         auto &s_ipsc = state.dataIPShortCut;
     233              : 
     234            2 :         s_ipsc->cCurrentModuleObject = cCMO_BBRadiator_Water;
     235              : 
     236            2 :         int NumConvHWBaseboards = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     237              : 
     238              :         // Calculate total number of baseboard units
     239              : 
     240            2 :         state.dataBaseboardRadiator->baseboards.allocate(NumConvHWBaseboards);
     241              : 
     242            2 :         if (NumConvHWBaseboards > 0) { // Get the data for cooling schemes
     243            2 :             bool ErrorsFound(false);   // If errors detected in input
     244            8 :             for (int ConvHWBaseboardNum = 1; ConvHWBaseboardNum <= NumConvHWBaseboards; ++ConvHWBaseboardNum) {
     245            6 :                 int NumAlphas = 0;
     246            6 :                 int NumNums = 0;
     247            6 :                 int IOStat = 0;
     248              : 
     249           12 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     250            6 :                                                                          s_ipsc->cCurrentModuleObject,
     251              :                                                                          ConvHWBaseboardNum,
     252            6 :                                                                          s_ipsc->cAlphaArgs,
     253              :                                                                          NumAlphas,
     254            6 :                                                                          s_ipsc->rNumericArgs,
     255              :                                                                          NumNums,
     256              :                                                                          IOStat,
     257            6 :                                                                          s_ipsc->lNumericFieldBlanks,
     258            6 :                                                                          s_ipsc->lAlphaFieldBlanks,
     259            6 :                                                                          s_ipsc->cAlphaFieldNames,
     260            6 :                                                                          s_ipsc->cNumericFieldNames);
     261              : 
     262            6 :                 ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     263              : 
     264            6 :                 auto &thisBaseboard = state.dataBaseboardRadiator->baseboards(ConvHWBaseboardNum);
     265            6 :                 thisBaseboard.FieldNames.allocate(NumNums);
     266            6 :                 thisBaseboard.FieldNames = s_ipsc->cNumericFieldNames;
     267              : 
     268              :                 // ErrorsFound will be set to True if problem was found, left untouched otherwise
     269            6 :                 VerifyUniqueBaseboardName(
     270           12 :                     state, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1), ErrorsFound, s_ipsc->cCurrentModuleObject + " Name");
     271              : 
     272            6 :                 thisBaseboard.EquipID = s_ipsc->cAlphaArgs(1); // name of this baseboard
     273            6 :                 thisBaseboard.EquipType = DataPlant::PlantEquipmentType::Baseboard_Conv_Water;
     274            6 :                 thisBaseboard.Schedule = s_ipsc->cAlphaArgs(2);
     275            6 :                 if (s_ipsc->lAlphaFieldBlanks(2)) {
     276            0 :                     thisBaseboard.availSched = Sched::GetScheduleAlwaysOn(state);
     277            6 :                 } 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            6 :                 thisBaseboard.WaterInletNode = GetOnlySingleNode(state,
     283            6 :                                                                  s_ipsc->cAlphaArgs(3),
     284              :                                                                  ErrorsFound,
     285              :                                                                  DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardConvectiveWater,
     286            6 :                                                                  s_ipsc->cAlphaArgs(1),
     287              :                                                                  DataLoopNode::NodeFluidType::Water,
     288              :                                                                  DataLoopNode::ConnectionType::Inlet,
     289              :                                                                  NodeInputManager::CompFluidStream::Primary,
     290              :                                                                  ObjectIsNotParent);
     291              :                 // get outlet node number
     292           12 :                 thisBaseboard.WaterOutletNode = GetOnlySingleNode(state,
     293            6 :                                                                   s_ipsc->cAlphaArgs(4),
     294              :                                                                   ErrorsFound,
     295              :                                                                   DataLoopNode::ConnectionObjectType::ZoneHVACBaseboardConvectiveWater,
     296            6 :                                                                   s_ipsc->cAlphaArgs(1),
     297              :                                                                   DataLoopNode::NodeFluidType::Water,
     298              :                                                                   DataLoopNode::ConnectionType::Outlet,
     299              :                                                                   NodeInputManager::CompFluidStream::Primary,
     300              :                                                                   ObjectIsNotParent);
     301              : 
     302            6 :                 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            6 :                 if (Util::SameString(s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum), "HeatingDesignCapacity")) {
     306            4 :                     thisBaseboard.HeatingCapMethod = HeatingDesignCapacity;
     307            4 :                     if (!s_ipsc->lNumericFieldBlanks(iHeatDesignCapacityNumericNum)) {
     308            4 :                         thisBaseboard.ScaledHeatingCapacity = s_ipsc->rNumericArgs(iHeatDesignCapacityNumericNum);
     309            4 :                         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            2 :                 } else if (Util::SameString(s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum), "CapacityPerFloorArea")) {
     325            1 :                     thisBaseboard.HeatingCapMethod = CapacityPerFloorArea;
     326            1 :                     if (!s_ipsc->lNumericFieldBlanks(iHeatCapacityPerFloorAreaNumericNum)) {
     327            1 :                         thisBaseboard.ScaledHeatingCapacity = s_ipsc->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum);
     328            1 :                         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            1 :                         } 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            1 :                 } else if (Util::SameString(s_ipsc->cAlphaArgs(iHeatCAPMAlphaNum), "FractionOfAutosizedHeatingCapacity")) {
     356            1 :                     thisBaseboard.HeatingCapMethod = FractionOfAutosizedHeatingCapacity;
     357            1 :                     if (!s_ipsc->lNumericFieldBlanks(iHeatFracOfAutosizedCapacityNumericNum)) {
     358            1 :                         thisBaseboard.ScaledHeatingCapacity = s_ipsc->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum);
     359            1 :                         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            6 :                 thisBaseboard.UA = s_ipsc->rNumericArgs(4);
     383            6 :                 thisBaseboard.WaterVolFlowRateMax = s_ipsc->rNumericArgs(5);
     384            6 :                 thisBaseboard.Offset = s_ipsc->rNumericArgs(6);
     385              :                 // Set default convergence tolerance
     386            6 :                 if (thisBaseboard.Offset <= 0.0) {
     387            0 :                     thisBaseboard.Offset = 0.001;
     388              :                 }
     389              : 
     390           12 :                 thisBaseboard.ZonePtr = DataZoneEquipment::GetZoneEquipControlledZoneNum(
     391            6 :                     state, DataZoneEquipment::ZoneEquipType::BaseboardConvectiveWater, thisBaseboard.EquipID);
     392              : 
     393            6 :                 thisBaseboard.checkForZoneSizing(state); // check if any autosizing is being done
     394              :             }
     395              : 
     396            2 :             if (ErrorsFound) {
     397            0 :                 ShowFatalError(state, format("{}Errors found in getting input.  Preceding condition(s) cause termination.", RoutineName));
     398              :             }
     399              :         }
     400              : 
     401            8 :         for (int BaseboardNum = 1; BaseboardNum <= NumConvHWBaseboards; ++BaseboardNum) {
     402              : 
     403              :             // Setup Report variables for the unit
     404              :             // CurrentModuleObject='ZoneHVAC:Baseboard:Convective:Water'
     405            6 :             auto &thisBaseboard = state.dataBaseboardRadiator->baseboards(BaseboardNum);
     406           12 :             SetupOutputVariable(state,
     407              :                                 "Baseboard Total Heating Energy",
     408              :                                 Constant::Units::J,
     409            6 :                                 thisBaseboard.Energy,
     410              :                                 OutputProcessor::TimeStepType::System,
     411              :                                 OutputProcessor::StoreType::Sum,
     412            6 :                                 thisBaseboard.EquipID,
     413              :                                 Constant::eResource::EnergyTransfer,
     414              :                                 OutputProcessor::Group::HVAC,
     415              :                                 OutputProcessor::EndUseCat::Baseboard);
     416              : 
     417           12 :             SetupOutputVariable(state,
     418              :                                 "Baseboard Hot Water Energy",
     419              :                                 Constant::Units::J,
     420            6 :                                 thisBaseboard.Energy,
     421              :                                 OutputProcessor::TimeStepType::System,
     422              :                                 OutputProcessor::StoreType::Sum,
     423            6 :                                 thisBaseboard.EquipID,
     424              :                                 Constant::eResource::PlantLoopHeatingDemand,
     425              :                                 OutputProcessor::Group::HVAC,
     426              :                                 OutputProcessor::EndUseCat::Baseboard);
     427              : 
     428           12 :             SetupOutputVariable(state,
     429              :                                 "Baseboard Total Heating Rate",
     430              :                                 Constant::Units::W,
     431            6 :                                 thisBaseboard.Power,
     432              :                                 OutputProcessor::TimeStepType::System,
     433              :                                 OutputProcessor::StoreType::Average,
     434            6 :                                 thisBaseboard.EquipID);
     435              : 
     436           12 :             SetupOutputVariable(state,
     437              :                                 "Baseboard Hot Water Mass Flow Rate",
     438              :                                 Constant::Units::kg_s,
     439            6 :                                 thisBaseboard.WaterMassFlowRate,
     440              :                                 OutputProcessor::TimeStepType::System,
     441              :                                 OutputProcessor::StoreType::Average,
     442            6 :                                 thisBaseboard.EquipID);
     443              : 
     444           12 :             SetupOutputVariable(state,
     445              :                                 "Baseboard Air Mass Flow Rate",
     446              :                                 Constant::Units::kg_s,
     447            6 :                                 thisBaseboard.AirMassFlowRate,
     448              :                                 OutputProcessor::TimeStepType::System,
     449              :                                 OutputProcessor::StoreType::Average,
     450            6 :                                 thisBaseboard.EquipID);
     451              : 
     452           12 :             SetupOutputVariable(state,
     453              :                                 "Baseboard Air Inlet Temperature",
     454              :                                 Constant::Units::C,
     455            6 :                                 thisBaseboard.AirInletTemp,
     456              :                                 OutputProcessor::TimeStepType::System,
     457              :                                 OutputProcessor::StoreType::Average,
     458            6 :                                 thisBaseboard.EquipID);
     459              : 
     460           12 :             SetupOutputVariable(state,
     461              :                                 "Baseboard Air Outlet Temperature",
     462              :                                 Constant::Units::C,
     463            6 :                                 thisBaseboard.AirOutletTemp,
     464              :                                 OutputProcessor::TimeStepType::System,
     465              :                                 OutputProcessor::StoreType::Average,
     466            6 :                                 thisBaseboard.EquipID);
     467              : 
     468           12 :             SetupOutputVariable(state,
     469              :                                 "Baseboard Water Inlet Temperature",
     470              :                                 Constant::Units::C,
     471            6 :                                 thisBaseboard.WaterInletTemp,
     472              :                                 OutputProcessor::TimeStepType::System,
     473              :                                 OutputProcessor::StoreType::Average,
     474            6 :                                 thisBaseboard.EquipID);
     475              : 
     476           12 :             SetupOutputVariable(state,
     477              :                                 "Baseboard Water Outlet Temperature",
     478              :                                 Constant::Units::C,
     479            6 :                                 thisBaseboard.WaterOutletTemp,
     480              :                                 OutputProcessor::TimeStepType::System,
     481              :                                 OutputProcessor::StoreType::Average,
     482            6 :                                 thisBaseboard.EquipID);
     483              :         }
     484            2 :     }
     485              : 
     486        12291 :     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        12291 :         if (this->SetLoopIndexFlag && allocated(state.dataPlnt->PlantLoop)) {
     499            3 :             bool errFlag = false;
     500            3 :             PlantUtilities::ScanPlantLoopsForObject(state, this->EquipID, this->EquipType, this->plantLoc, errFlag, _, _, _, _, _);
     501            3 :             if (errFlag) {
     502            0 :                 ShowFatalError(state, "InitBaseboard: Program terminated for previous conditions.");
     503              :             }
     504            3 :             this->SetLoopIndexFlag = false;
     505              :         }
     506              : 
     507        12291 :         if (!state.dataGlobal->SysSizingCalc && this->MySizeFlag && !this->SetLoopIndexFlag) {
     508              :             // for each coil, do the sizing once.
     509            3 :             this->SizeBaseboard(state, baseboardNum);
     510              : 
     511            3 :             this->MySizeFlag = false;
     512              :         }
     513              : 
     514              :         // Do the Begin Environment initializations
     515        12291 :         if (state.dataGlobal->BeginEnvrnFlag && this->MyEnvrnFlag && !this->SetLoopIndexFlag) {
     516           12 :             int WaterInletNode = this->WaterInletNode;
     517           12 :             Real64 rho = this->plantLoc.loop->glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
     518           12 :             this->WaterMassFlowRateMax = rho * this->WaterVolFlowRateMax;
     519           12 :             PlantUtilities::InitComponentNodes(state, 0.0, this->WaterMassFlowRateMax, this->WaterInletNode, this->WaterOutletNode);
     520           12 :             state.dataLoopNodes->Node(WaterInletNode).Temp = Constant::HWInitConvTemp;
     521           12 :             Real64 Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, state.dataLoopNodes->Node(WaterInletNode).Temp, RoutineName);
     522           12 :             state.dataLoopNodes->Node(WaterInletNode).Enthalpy = Cp * state.dataLoopNodes->Node(WaterInletNode).Temp;
     523           12 :             state.dataLoopNodes->Node(WaterInletNode).Quality = 0.0;
     524           12 :             state.dataLoopNodes->Node(WaterInletNode).Press = 0.0;
     525           12 :             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           12 :             if (this->AirMassFlowRate <= 0.0) {
     528            2 :                 this->AirMassFlowRate = 2.0 * this->WaterMassFlowRateMax;
     529              :             }
     530           12 :             this->MyEnvrnFlag = false;
     531              :         }
     532              : 
     533        12291 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     534        12219 :             this->MyEnvrnFlag = true;
     535              :         }
     536              : 
     537              :         // Do the every time step initializations
     538        12291 :         int WaterInletNode = this->WaterInletNode;
     539        12291 :         int ZoneNode = state.dataZoneEquip->ZoneEquipConfig(this->ZonePtr).ZoneNode;
     540        12291 :         this->WaterMassFlowRate = state.dataLoopNodes->Node(WaterInletNode).MassFlowRate;
     541        12291 :         this->WaterInletTemp = state.dataLoopNodes->Node(WaterInletNode).Temp;
     542        12291 :         this->WaterInletEnthalpy = state.dataLoopNodes->Node(WaterInletNode).Enthalpy;
     543        12291 :         this->AirInletTemp = state.dataLoopNodes->Node(ZoneNode).Temp;
     544        12291 :         this->AirInletHumRat = state.dataLoopNodes->Node(ZoneNode).HumRat;
     545        12291 :     }
     546              : 
     547            9 :     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            9 :         Real64 constexpr Acc = 0.0001; // Accuracy of result
     566            9 :         int constexpr MaxIte = 500;    // Maximum number of iterations
     567            9 :         static std::string const RoutineName = cCMO_BBRadiator_Water + ":SizeBaseboard";
     568              : 
     569              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     570            9 :         Real64 DesCoilLoad(0.0);
     571              :         Real64 UA0; // lower bound for UA
     572              :         Real64 UA1; // upper bound for UA
     573              :         Real64 UA;
     574            9 :         bool ErrorsFound(false);             // If errors detected in input
     575              :         Real64 rho;                          // local fluid density
     576              :         Real64 Cp;                           // local fluid specific heat
     577            9 :         Real64 WaterVolFlowRateMaxDes(0.0);  // Design water volume flow for reporting
     578            9 :         Real64 WaterVolFlowRateMaxUser(0.0); // User hard-sized volume flow for reporting
     579            9 :         Real64 UADes(0.0);                   // Design UA value for reporting
     580            9 :         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            9 :         int PltSizHeatNum = this->plantLoc.loop->PlantSizNum;
     585              : 
     586            9 :         if (PltSizHeatNum > 0) {
     587              : 
     588            9 :             state.dataSize->DataScalableCapSizingON = false;
     589              : 
     590            9 :             if (state.dataSize->CurZoneEqNum > 0) {
     591            9 :                 bool FlowAutoSize = false; // Indicator to autosizing water volume flow
     592              : 
     593            9 :                 if (this->WaterVolFlowRateMax == DataSizing::AutoSize) {
     594            9 :                     FlowAutoSize = true;
     595              :                 }
     596            9 :                 if (!FlowAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation should continue
     597            0 :                     if (this->WaterVolFlowRateMax > 0.0) {
     598            0 :                         BaseSizer::reportSizerOutput(
     599              :                             state, cCMO_BBRadiator_Water, this->EquipID, "User-Specified Maximum Water Flow Rate [m3/s]", this->WaterVolFlowRateMax);
     600              :                     }
     601              :                 } else {
     602            9 :                     auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
     603            9 :                     auto const &finalZoneSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum);
     604            9 :                     std::string_view const CompType = cCMO_BBRadiator_Water;
     605            9 :                     std::string_view const CompName = this->EquipID;
     606            9 :                     state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
     607            9 :                     state.dataSize->DataZoneNumber = this->ZonePtr;
     608            9 :                     int SizingMethod = HVAC::HeatingCapacitySizing;
     609            9 :                     int FieldNum = 1;
     610            9 :                     std::string const SizingString = format("{} [W]", this->FieldNames(FieldNum));
     611            9 :                     int CapSizingMethod = this->HeatingCapMethod;
     612            9 :                     zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
     613            9 :                     if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
     614              :                         CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
     615              : 
     616            9 :                         if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
     617            7 :                             if (this->ScaledHeatingCapacity == DataSizing::AutoSize) {
     618            6 :                                 zoneEqSizing.DesHeatingLoad = finalZoneSizing.NonAirSysDesHeatLoad;
     619              :                             } else {
     620            1 :                                 zoneEqSizing.DesHeatingLoad = this->ScaledHeatingCapacity;
     621              :                             }
     622            7 :                             zoneEqSizing.HeatingCapacity = true;
     623            7 :                             TempSize = zoneEqSizing.DesHeatingLoad;
     624            2 :                         } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
     625            1 :                             zoneEqSizing.HeatingCapacity = true;
     626            1 :                             zoneEqSizing.DesHeatingLoad =
     627            1 :                                 this->ScaledHeatingCapacity * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
     628            1 :                             TempSize = zoneEqSizing.DesHeatingLoad;
     629            1 :                             state.dataSize->DataScalableCapSizingON = true;
     630            1 :                         } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
     631            1 :                             zoneEqSizing.HeatingCapacity = true;
     632            1 :                             state.dataSize->DataFracOfAutosizedHeatingCapacity = this->ScaledHeatingCapacity;
     633            1 :                             zoneEqSizing.DesHeatingLoad = finalZoneSizing.NonAirSysDesHeatLoad;
     634            1 :                             TempSize = DataSizing::AutoSize;
     635            1 :                             state.dataSize->DataScalableCapSizingON = true;
     636              :                         } else {
     637            0 :                             TempSize = this->ScaledHeatingCapacity;
     638              :                         }
     639            9 :                         bool PrintFlag = false; // TRUE when sizing information is reported in the eio file
     640            9 :                         bool errorsFound = false;
     641            9 :                         HeatingCapacitySizer sizerHeatingCapacity;
     642            9 :                         sizerHeatingCapacity.overrideSizingString(SizingString);
     643            9 :                         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     644            9 :                         DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
     645            9 :                         state.dataSize->DataScalableCapSizingON = false;
     646            9 :                     } else {
     647            0 :                         DesCoilLoad = 0.0;
     648              :                     }
     649              : 
     650            9 :                     if (DesCoilLoad >= SmallLoad) {
     651            9 :                         Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
     652            9 :                         rho = this->plantLoc.loop->glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
     653            9 :                         WaterVolFlowRateMaxDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
     654              :                     } else {
     655            0 :                         WaterVolFlowRateMaxDes = 0.0;
     656              :                     }
     657              : 
     658            9 :                     if (FlowAutoSize) {
     659            9 :                         this->WaterVolFlowRateMax = WaterVolFlowRateMaxDes;
     660            9 :                         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            9 :                 }
     691              : 
     692              :                 // UA sizing
     693            9 :                 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            9 :                 if (this->UA == DataSizing::AutoSize) {
     696            9 :                     UAAutoSize = true;
     697              :                 } else {
     698            0 :                     UAUser = this->UA;
     699              :                 }
     700            9 :                 if (!UAAutoSize && !state.dataSize->ZoneSizingRunDone) { // Simulation should continue
     701            0 :                     if (this->UA > 0.0) {
     702            0 :                         BaseSizer::reportSizerOutput(
     703              :                             state, cCMO_BBRadiator_Water, this->EquipID, "User-Specified U-Factor Times Area Value [W/K]", this->UA);
     704              :                     }
     705              :                 } else {
     706            9 :                     auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
     707            9 :                     auto const &finalZoneSizing = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum);
     708            9 :                     this->WaterInletTemp = state.dataSize->PlantSizData(PltSizHeatNum).ExitTemp;
     709            9 :                     this->AirInletTemp = finalZoneSizing.ZoneTempAtHeatPeak;
     710            9 :                     this->AirInletHumRat = finalZoneSizing.ZoneHumRatAtHeatPeak;
     711            9 :                     rho = this->plantLoc.loop->glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
     712            9 :                     state.dataLoopNodes->Node(this->WaterInletNode).MassFlowRate = rho * this->WaterVolFlowRateMax;
     713              : 
     714            9 :                     std::string_view const CompType = cCMO_BBRadiator_Water;
     715            9 :                     std::string_view const CompName = this->EquipID;
     716            9 :                     state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
     717            9 :                     state.dataSize->DataZoneNumber = this->ZonePtr;
     718            9 :                     int SizingMethod = HVAC::HeatingCapacitySizing;
     719            9 :                     int FieldNum = 1;
     720            9 :                     std::string const SizingString = format("{} [W]", this->FieldNames(FieldNum));
     721            9 :                     int CapSizingMethod = this->HeatingCapMethod;
     722            9 :                     zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
     723            9 :                     if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
     724              :                         CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
     725            9 :                         if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
     726            7 :                             if (this->ScaledHeatingCapacity == DataSizing::AutoSize) {
     727            6 :                                 zoneEqSizing.DesHeatingLoad = finalZoneSizing.NonAirSysDesHeatLoad;
     728              :                             } else {
     729            1 :                                 zoneEqSizing.DesHeatingLoad = this->ScaledHeatingCapacity;
     730              :                             }
     731            7 :                             zoneEqSizing.HeatingCapacity = true;
     732            7 :                             TempSize = zoneEqSizing.DesHeatingLoad;
     733            2 :                         } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
     734            1 :                             zoneEqSizing.HeatingCapacity = true;
     735            1 :                             zoneEqSizing.DesHeatingLoad =
     736            1 :                                 this->ScaledHeatingCapacity * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
     737            1 :                             TempSize = zoneEqSizing.DesHeatingLoad;
     738            1 :                             state.dataSize->DataScalableCapSizingON = true;
     739            1 :                         } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
     740            1 :                             zoneEqSizing.HeatingCapacity = true;
     741            1 :                             state.dataSize->DataFracOfAutosizedHeatingCapacity = this->ScaledHeatingCapacity;
     742            1 :                             zoneEqSizing.DesHeatingLoad = finalZoneSizing.NonAirSysDesHeatLoad;
     743            1 :                             TempSize = DataSizing::AutoSize;
     744            1 :                             state.dataSize->DataScalableCapSizingON = true;
     745              :                         } else {
     746            0 :                             TempSize = this->ScaledHeatingCapacity;
     747              :                         }
     748            9 :                         bool PrintFlag = false;
     749            9 :                         bool errorsFound = false;
     750            9 :                         HeatingCapacitySizer sizerHeatingCapacity;
     751            9 :                         sizerHeatingCapacity.overrideSizingString(SizingString);
     752            9 :                         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     753            9 :                         DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
     754            9 :                         state.dataSize->DataScalableCapSizingON = false;
     755            9 :                     } else {
     756            0 :                         DesCoilLoad = 0.0; // FinalZoneSizing(CurZoneEqNum).NonAirSysDesHeatLoad;
     757              :                     }
     758            9 :                     if (DesCoilLoad >= SmallLoad) {
     759              :                         // pick an air  mass flow rate that is twice the water mass flow rate (CR8842)
     760            9 :                         this->DesAirMassFlowRate = 2.0 * rho * this->WaterVolFlowRateMax;
     761              :                         // set the lower and upper limits on the UA
     762            9 :                         UA0 = 0.001 * DesCoilLoad;
     763            9 :                         UA1 = DesCoilLoad;
     764              : 
     765              :                         // before iterating on a design UA check output at lower UA bound
     766            9 :                         this->UA = UA0;
     767            9 :                         Real64 LoadMet = 0.0;
     768            9 :                         SimHWConvective(state, baseboardNum, LoadMet);
     769            9 :                         if (LoadMet < DesCoilLoad) { // baseboard output should be below design load
     770              :                             // now check output at max UA (where UA = design load)
     771            9 :                             this->UA = UA1;
     772            9 :                             SimHWConvective(state, baseboardNum, LoadMet);
     773              : 
     774            9 :                             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           39 :                                 auto f = [&state, baseboardNum, DesCoilLoad](Real64 UA) {
     777           39 :                                     state.dataBaseboardRadiator->baseboards(baseboardNum).UA = UA;
     778           39 :                                     int localBaseBoardNum = baseboardNum;
     779           39 :                                     Real64 LoadMet = 0.0;
     780           39 :                                     SimHWConvective(state, localBaseBoardNum, LoadMet);
     781           39 :                                     return (DesCoilLoad - LoadMet) / DesCoilLoad;
     782            3 :                                 };
     783            3 :                                 int SolFla = 0;
     784            3 :                                 General::SolveRoot(state, Acc, MaxIte, SolFla, UA, f, UA0, UA1);
     785              :                                 // if the numerical inversion failed, issue error messages.
     786            3 :                                 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            3 :                                 } 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            3 :                                 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            6 :                                 UADes = UA1;
     816            6 :                                 if (UAAutoSize) {
     817           12 :                                     ShowWarningError(state,
     818           12 :                                                      format("SizeBaseboard: Autosizing of HW baseboard UA failed for {}=\"{}\"",
     819              :                                                             cCMO_BBRadiator_Water,
     820            6 :                                                             this->EquipID));
     821           12 :                                     ShowContinueError(
     822           12 :                                         state, format("Design UA set equal to design coil load for {}=\"{}\"", cCMO_BBRadiator_Water, this->EquipID));
     823            6 :                                     ShowContinueError(state, format("Design coil load used during sizing = {:.5R} W.", DesCoilLoad));
     824            6 :                                     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            9 :                     if (UAAutoSize) {
     847            9 :                         this->UA = UADes;
     848            9 :                         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            9 :                 }
     876              :             }
     877              :         } else {
     878              :             // if there is no heating Sizing:Plant object and autosizing was requested, issue an error message
     879            0 :             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            9 :         PlantUtilities::RegisterPlantCompDesignFlow(state, this->WaterInletNode, this->WaterVolFlowRateMax);
     888              : 
     889            9 :         if (ErrorsFound) {
     890            0 :             ShowFatalError(state, "SizeBaseboard: Preceding sizing errors cause program termination");
     891              :         }
     892            9 :     }
     893              : 
     894           11 :     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           11 :         if ((this->UA == DataSizing::AutoSize) || (this->WaterVolFlowRateMax == DataSizing::AutoSize) ||
     902            3 :             ((this->HeatingCapMethod == DataSizing::HeatingDesignCapacity) && (this->ScaledHeatingCapacity == DataSizing::AutoSize)) ||
     903            2 :             ((this->HeatingCapMethod == DataSizing::FractionOfAutosizedHeatingCapacity) && (this->ScaledHeatingCapacity == DataSizing::AutoSize))) {
     904            9 :             CheckZoneSizing(state, cCMO_BBRadiator_Water, this->EquipID);
     905              :         }
     906            8 :     }
     907              : 
     908        77386 :     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        77386 :         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        77386 :         auto &baseboard = state.dataBaseboardRadiator->baseboards(BaseboardNum);
     958              : 
     959        77386 :         ZoneNum = baseboard.ZonePtr;
     960        77386 :         QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToHeatSP;
     961        77386 :         if (baseboard.MySizeFlag)
     962           57 :             QZnReq = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad; // If in sizing, assign design condition
     963              : 
     964        77386 :         WaterInletTemp = baseboard.WaterInletTemp;
     965        77386 :         AirInletTemp = baseboard.AirInletTemp;
     966              : 
     967        77386 :         CpWater = baseboard.plantLoc.loop->glycol->getSpecificHeat(state, WaterInletTemp, RoutineName);
     968        77386 :         CpAir = PsyCpAirFnW(baseboard.AirInletHumRat);
     969              : 
     970        77386 :         if (baseboard.DesAirMassFlowRate > 0.0) { // If UA is autosized, assign design condition
     971        77386 :             AirMassFlowRate = baseboard.DesAirMassFlowRate;
     972              :         } else {
     973            0 :             AirMassFlowRate = baseboard.AirMassFlowRate;
     974              :             // pick a mass flow rate that depends on the max water mass flow rate. CR 8842 changed to factor of 2.0
     975            0 :             if (AirMassFlowRate <= 0.0) AirMassFlowRate = 2.0 * baseboard.WaterMassFlowRateMax;
     976              :         }
     977              : 
     978        77386 :         WaterMassFlowRate = state.dataLoopNodes->Node(baseboard.WaterInletNode).MassFlowRate;
     979        77386 :         CapacitanceAir = CpAir * AirMassFlowRate;
     980              : 
     981       154760 :         if (QZnReq > SmallLoad && (!state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) || baseboard.MySizeFlag) &&
     982       232146 :             (baseboard.availSched->getCurrentVal() > 0 || baseboard.MySizeFlag) && (WaterMassFlowRate > 0.0)) {
     983              : 
     984        71326 :             CapacitanceWater = CpWater * WaterMassFlowRate;
     985        71326 :             CapacitanceMax = max(CapacitanceAir, CapacitanceWater);
     986        71326 :             CapacitanceMin = min(CapacitanceAir, CapacitanceWater);
     987        71326 :             CapacityRatio = CapacitanceMin / CapacitanceMax;
     988        71326 :             NTU = baseboard.UA / CapacitanceMin;
     989              :             // The effectiveness is given by the following formula:
     990              :             // Effectiveness = 1. - EXP((1./CapacityRatio)*(NTU)**0.22*(EXP(-CapacityRatio*(NTU)**0.78)-1.))
     991              :             // To prevent possible underflows (numbers smaller than the computer can handle) we must break
     992              :             // the calculation up into steps and check the size of the exponential arguments.
     993        71326 :             AA = -CapacityRatio * std::pow(NTU, 0.78);
     994        71326 :             if (AA < DataPrecisionGlobals::EXP_LowerLimit) {
     995            0 :                 BB = 0.0;
     996              :             } else {
     997        71326 :                 BB = std::exp(AA);
     998              :             }
     999        71326 :             CC = (1.0 / CapacityRatio) * std::pow(NTU, 0.22) * (BB - 1.0);
    1000        71326 :             if (CC < DataPrecisionGlobals::EXP_LowerLimit) {
    1001          499 :                 Effectiveness = 1.0;
    1002              :             } else {
    1003        70827 :                 Effectiveness = 1.0 - std::exp(CC);
    1004              :             }
    1005        71326 :             AirOutletTemp = AirInletTemp + Effectiveness * CapacitanceMin * (WaterInletTemp - AirInletTemp) / CapacitanceAir;
    1006        71326 :             WaterOutletTemp = WaterInletTemp - CapacitanceAir * (AirOutletTemp - AirInletTemp) / CapacitanceWater;
    1007        71326 :             LoadMet = CapacitanceWater * (WaterInletTemp - WaterOutletTemp);
    1008        71326 :             baseboard.WaterOutletEnthalpy = baseboard.WaterInletEnthalpy - LoadMet / WaterMassFlowRate;
    1009              :         } else {
    1010         6060 :             AirOutletTemp = AirInletTemp;
    1011         6060 :             WaterOutletTemp = WaterInletTemp;
    1012         6060 :             LoadMet = 0.0;
    1013         6060 :             baseboard.WaterOutletEnthalpy = baseboard.WaterInletEnthalpy;
    1014         6060 :             WaterMassFlowRate = 0.0;
    1015              : 
    1016         6060 :             SetActuatedBranchFlowRate(state, WaterMassFlowRate, baseboard.WaterInletNode, baseboard.plantLoc, false);
    1017         6060 :             AirMassFlowRate = 0.0;
    1018              :         }
    1019              : 
    1020        77386 :         baseboard.WaterOutletTemp = WaterOutletTemp;
    1021        77386 :         baseboard.AirOutletTemp = AirOutletTemp;
    1022        77386 :         baseboard.Power = LoadMet;
    1023        77386 :         baseboard.WaterMassFlowRate = WaterMassFlowRate;
    1024        77386 :         baseboard.AirMassFlowRate = AirMassFlowRate;
    1025        77386 :     }
    1026              : 
    1027        12291 :     void UpdateBaseboard(EnergyPlusData &state, int &BaseboardNum)
    1028              :     {
    1029              : 
    1030              :         // SUBROUTINE INFORMATION:
    1031              :         //       AUTHOR         Russ Taylor
    1032              :         //       DATE WRITTEN   Nov 1997
    1033              :         //       MODIFIED       na
    1034              :         //       RE-ENGINEERED  na
    1035              : 
    1036              :         // Using/Aliasing
    1037              :         using PlantUtilities::SafeCopyPlantNode;
    1038              : 
    1039              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1040              :         int WaterInletNode;
    1041              :         int WaterOutletNode;
    1042              : 
    1043        12291 :         auto &baseboard = state.dataBaseboardRadiator;
    1044              : 
    1045        12291 :         WaterInletNode = baseboard->baseboards(BaseboardNum).WaterInletNode;
    1046        12291 :         WaterOutletNode = baseboard->baseboards(BaseboardNum).WaterOutletNode;
    1047              : 
    1048        12291 :         SafeCopyPlantNode(state, WaterInletNode, WaterOutletNode);
    1049              :         // Set the outlet air nodes of the Baseboard
    1050              :         // Set the outlet water nodes for the Coil
    1051        12291 :         state.dataLoopNodes->Node(WaterOutletNode).Temp = baseboard->baseboards(BaseboardNum).WaterOutletTemp;
    1052        12291 :         state.dataLoopNodes->Node(WaterOutletNode).Enthalpy = baseboard->baseboards(BaseboardNum).WaterOutletEnthalpy;
    1053        12291 :     }
    1054              : 
    1055              : } // namespace BaseboardRadiator
    1056              : 
    1057              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1