LCOV - code coverage report
Current view: top level - EnergyPlus - ChilledCeilingPanelSimple.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 7.7 % 794 61
Test Date: 2025-05-22 16:09:37 Functions: 36.4 % 11 4

            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/CoolingCapacitySizing.hh>
      57              : #include <EnergyPlus/BranchNodeConnections.hh>
      58              : #include <EnergyPlus/ChilledCeilingPanelSimple.hh>
      59              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      60              : #include <EnergyPlus/DataEnvironment.hh>
      61              : #include <EnergyPlus/DataHVACGlobals.hh>
      62              : #include <EnergyPlus/DataHeatBalFanSys.hh>
      63              : #include <EnergyPlus/DataHeatBalSurface.hh>
      64              : #include <EnergyPlus/DataHeatBalance.hh>
      65              : #include <EnergyPlus/DataIPShortCuts.hh>
      66              : #include <EnergyPlus/DataSizing.hh>
      67              : #include <EnergyPlus/DataSurfaces.hh>
      68              : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      69              : #include <EnergyPlus/DataZoneEquipment.hh>
      70              : #include <EnergyPlus/FluidProperties.hh>
      71              : #include <EnergyPlus/GeneralRoutines.hh>
      72              : #include <EnergyPlus/HeatBalanceIntRadExchange.hh>
      73              : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
      74              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      75              : #include <EnergyPlus/NodeInputManager.hh>
      76              : #include <EnergyPlus/OutputProcessor.hh>
      77              : #include <EnergyPlus/Plant/DataPlant.hh>
      78              : #include <EnergyPlus/PlantUtilities.hh>
      79              : #include <EnergyPlus/Psychrometrics.hh>
      80              : #include <EnergyPlus/ScheduleManager.hh>
      81              : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      82              : 
      83              : namespace EnergyPlus::CoolingPanelSimple {
      84              : 
      85              : // Module -- (ref: Object: ZoneHVAC:CoolingPanel:RadiantConvective:Water)
      86              : 
      87              : // Module containing the routines dealing with the simple (chilled ceiling) cooling panels
      88              : 
      89              : // MODULE INFORMATION:
      90              : //       AUTHOR         Rick Strand
      91              : //       DATE WRITTEN   Aug 2014
      92              : 
      93              : // PURPOSE OF THIS MODULE:
      94              : // The purpose of this module is to simulate simple chilled ceiling panels.  It is similar to
      95              : // hot water radiant/convective baseboard units and the code for this model used that model as
      96              : // a starting point.
      97              : 
      98              : // REFERENCES:
      99              : // Existing code for hot water baseboard models (radiant-convective variety)
     100              : 
     101              : // USE STATEMENTS:
     102              : // MODULE PARAMETER DEFINITIONS
     103              : std::string const cCMO_CoolingPanel_Simple("ZoneHVAC:CoolingPanel:RadiantConvective:Water");
     104              : 
     105            0 : void SimCoolingPanel(
     106              :     EnergyPlusData &state, std::string const &EquipName, int const ControlledZoneNum, bool const FirstHVACIteration, Real64 &PowerMet, int &CompIndex)
     107              : {
     108              : 
     109              :     // SUBROUTINE INFORMATION:
     110              :     //       AUTHOR         Rick Strand
     111              :     //       DATE WRITTEN   Aug 2014
     112              : 
     113              :     // PURPOSE OF THIS SUBROUTINE:
     114              :     // This subroutine simulates the simple cooling (chilled ceiling) panel.  It borrows heavily
     115              :     // from the hot water radiant-convective baseboard model code.
     116              : 
     117              :     // REFERENCES:
     118              :     // Existing code for hot water baseboard models (radiant-convective variety)
     119              : 
     120              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     121              :     int CoolingPanelNum; // Index of unit in baseboard array
     122              :     Real64 QZnReq;       // Zone load not yet satisfied
     123              :     Real64 MaxWaterFlow;
     124              :     Real64 MinWaterFlow;
     125              : 
     126            0 :     if (state.dataChilledCeilingPanelSimple->GetInputFlag) {
     127            0 :         GetCoolingPanelInput(state);
     128            0 :         state.dataChilledCeilingPanelSimple->GetInputFlag = false;
     129              :     }
     130              : 
     131              :     // Find the correct Baseboard Equipment
     132            0 :     if (CompIndex == 0) {
     133            0 :         CoolingPanelNum = Util::FindItemInList(EquipName,
     134            0 :                                                state.dataChilledCeilingPanelSimple->CoolingPanel,
     135              :                                                &CoolingPanelParams::Name,
     136            0 :                                                (int)state.dataChilledCeilingPanelSimple->CoolingPanel.size());
     137            0 :         if (CoolingPanelNum == 0) {
     138            0 :             ShowFatalError(state, format("SimCoolingPanelSimple: Unit not found={}", EquipName));
     139              :         }
     140            0 :         CompIndex = CoolingPanelNum;
     141              :     } else {
     142            0 :         CoolingPanelNum = CompIndex;
     143            0 :         if (CoolingPanelNum > (int)state.dataChilledCeilingPanelSimple->CoolingPanel.size() || CoolingPanelNum < 1) {
     144            0 :             ShowFatalError(state,
     145            0 :                            format("SimCoolingPanelSimple:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     146              :                                   CoolingPanelNum,
     147            0 :                                   (int)state.dataChilledCeilingPanelSimple->CoolingPanel.size(),
     148              :                                   EquipName));
     149              :         }
     150            0 :         if (state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).CheckEquipName) {
     151            0 :             if (EquipName != state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).Name) {
     152            0 :                 ShowFatalError(state,
     153            0 :                                format("SimCoolingPanelSimple: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     154              :                                       CoolingPanelNum,
     155              :                                       EquipName,
     156            0 :                                       state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).Name));
     157              :             }
     158            0 :             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).CheckEquipName = false;
     159              :         }
     160              :     }
     161              : 
     162            0 :     if (CompIndex > 0) {
     163              : 
     164            0 :         auto &thisCP(state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum));
     165              : 
     166            0 :         InitCoolingPanel(state, CoolingPanelNum, ControlledZoneNum, FirstHVACIteration);
     167              : 
     168            0 :         QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ControlledZoneNum).RemainingOutputReqToCoolSP;
     169              : 
     170              :         // On the first HVAC iteration the system values are given to the controller, but after that
     171              :         // the demand limits are in place and there needs to be feedback to the Zone Equipment
     172            0 :         if (FirstHVACIteration) {
     173            0 :             MaxWaterFlow = thisCP.WaterMassFlowRateMax;
     174            0 :             MinWaterFlow = 0.0;
     175              :         } else {
     176            0 :             MaxWaterFlow = state.dataLoopNodes->Node(thisCP.WaterInletNode).MassFlowRateMaxAvail;
     177            0 :             MinWaterFlow = state.dataLoopNodes->Node(thisCP.WaterInletNode).MassFlowRateMinAvail;
     178              :         }
     179              : 
     180            0 :         switch (thisCP.EquipType) {
     181            0 :         case DataPlant::PlantEquipmentType::CoolingPanel_Simple: { // 'ZoneHVAC:CoolingPanel:RadiantConvective:Water'
     182            0 :             thisCP.CalcCoolingPanel(state, CoolingPanelNum);
     183            0 :         } break;
     184            0 :         default: {
     185            0 :             ShowSevereError(
     186              :                 state,
     187            0 :                 format("SimCoolingPanelSimple: Errors in CoolingPanel={}", state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).Name));
     188            0 :             ShowContinueError(
     189              :                 state,
     190            0 :                 format("Invalid or unimplemented equipment type={}", state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipType));
     191            0 :             ShowFatalError(state, "Preceding condition causes termination.");
     192            0 :         } break;
     193              :         }
     194              : 
     195            0 :         PowerMet = thisCP.TotPower;
     196              : 
     197            0 :         UpdateCoolingPanel(state, CoolingPanelNum);
     198              : 
     199            0 :         state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).ReportCoolingPanel(state);
     200              : 
     201              :     } else {
     202            0 :         ShowFatalError(state, format("SimCoolingPanelSimple: Unit not found={}", EquipName));
     203              :     }
     204            0 : }
     205              : 
     206            0 : void GetCoolingPanelInput(EnergyPlusData &state)
     207              : {
     208              : 
     209              :     // SUBROUTINE INFORMATION:
     210              :     //       AUTHOR         Rick Strand
     211              :     //       DATE WRITTEN   Aug 2014
     212              : 
     213              :     // PURPOSE OF THIS SUBROUTINE:
     214              :     // This subroutine gets the input for the simple cooling panel units.
     215              : 
     216              :     // METHODOLOGY EMPLOYED:
     217              :     // Standard input processor calls--started from Daeho's radiant-convective water baseboard model.
     218              : 
     219              :     // SUBROUTINE PARAMETER DEFINITIONS:
     220              :     static constexpr std::string_view RoutineName("GetCoolingPanelInput:");
     221              :     static constexpr std::string_view routineName = "GetCoolingPanelInput";
     222            0 :     Real64 constexpr MaxFraction(1.0);
     223            0 :     Real64 constexpr MinFraction(0.0);
     224            0 :     Real64 constexpr MaxWaterTempAvg(30.0);       // Maximum limit of average water temperature in degree C
     225            0 :     Real64 constexpr MinWaterTempAvg(0.0);        // Minimum limit of average water temperature in degree C
     226            0 :     Real64 constexpr MaxWaterFlowRate(10.0);      // Maximum limit of water volume flow rate in m3/s
     227            0 :     Real64 constexpr MinWaterFlowRate(0.00001);   // Minimum limit of water volume flow rate in m3/s
     228            0 :     Real64 constexpr WaterMassFlowDefault(0.063); // Default water mass flow rate in kg/s
     229            0 :     int constexpr MinDistribSurfaces(1);          // Minimum number of surfaces that a baseboard heater can radiate to
     230            0 :     Real64 constexpr MinThrottlingRange(0.5);     // Smallest throttling range allowed in degrees Celsius
     231              :     static constexpr std::string_view MeanAirTemperature("MeanAirTemperature");
     232              :     static constexpr std::string_view MeanRadiantTemperature("MeanRadiantTemperature");
     233              :     static constexpr std::string_view OperativeTemperature("OperativeTemperature");
     234              :     static constexpr std::string_view OutsideAirDryBulbTemperature("OutdoorDryBulbTemperature");
     235              :     static constexpr std::string_view OutsideAirWetBulbTemperature("OutdoorWetBulbTemperature");
     236              :     static constexpr std::string_view ZoneTotalLoad("ZoneTotalLoad");
     237              :     static constexpr std::string_view ZoneConvectiveLoad("ZoneConvectiveLoad");
     238              :     static constexpr std::string_view Off("Off");
     239              :     static constexpr std::string_view SimpleOff("SimpleOff");
     240              :     static constexpr std::string_view VariableOff("VariableOff");
     241              : 
     242              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     243              :     int NumAlphas;  // Number of Alphas for each GetobjectItem call
     244              :     int NumNumbers; // Number of Numbers for each GetobjectItem call
     245              :     int SurfNum;    // Surface number Do loop counter
     246              :     int IOStat;
     247            0 :     bool ErrorsFound(false); // If errors detected in input
     248            0 :     int NumCoolingPanels = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCMO_CoolingPanel_Simple);
     249              : 
     250            0 :     auto &s_ipsc = state.dataIPShortCut;
     251              :     // Count total number of baseboard units
     252              : 
     253            0 :     state.dataChilledCeilingPanelSimple->CoolingPanel.allocate(NumCoolingPanels);
     254              : 
     255              :     // Get the data from the user input related to cooling panels
     256            0 :     for (int CoolingPanelNum = 1; CoolingPanelNum <= NumCoolingPanels; ++CoolingPanelNum) {
     257              : 
     258            0 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     259              :                                                                  cCMO_CoolingPanel_Simple,
     260              :                                                                  CoolingPanelNum,
     261            0 :                                                                  s_ipsc->cAlphaArgs,
     262              :                                                                  NumAlphas,
     263            0 :                                                                  s_ipsc->rNumericArgs,
     264              :                                                                  NumNumbers,
     265              :                                                                  IOStat,
     266            0 :                                                                  s_ipsc->lNumericFieldBlanks,
     267            0 :                                                                  s_ipsc->lAlphaFieldBlanks,
     268            0 :                                                                  s_ipsc->cAlphaFieldNames,
     269            0 :                                                                  s_ipsc->cNumericFieldNames);
     270              : 
     271            0 :         ErrorObjectHeader eoh{routineName, cCMO_CoolingPanel_Simple, s_ipsc->cAlphaArgs(1)};
     272              : 
     273            0 :         state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).FieldNames.allocate(NumNumbers);
     274            0 :         state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).FieldNames = "";
     275            0 :         state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).FieldNames = s_ipsc->cNumericFieldNames;
     276              : 
     277            0 :         if (CoolingPanelNum > 1) {
     278            0 :             for (int CoolPanelNumI = 2; CoolPanelNumI <= NumCoolingPanels; ++CoolPanelNumI) {
     279            0 :                 if (s_ipsc->cAlphaArgs(1) == state.dataChilledCeilingPanelSimple->CoolingPanel(CoolPanelNumI).Name) {
     280            0 :                     ErrorsFound = true;
     281            0 :                     ShowSevereError(state, format("{} is used as a name for more than one simple COOLING PANEL.", s_ipsc->cAlphaArgs(1)));
     282            0 :                     ShowContinueError(state, "This is not allowed.");
     283              :                 }
     284              :             }
     285              :         }
     286              : 
     287            0 :         auto &thisCP(state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum));
     288            0 :         thisCP.Name = s_ipsc->cAlphaArgs(1);                                   // Name of this simple cooling panel
     289            0 :         thisCP.EquipType = DataPlant::PlantEquipmentType::CoolingPanel_Simple; //'ZoneHVAC:CoolingPanel:RadiantConvective:Water'
     290              : 
     291              :         // Get schedule
     292            0 :         thisCP.Schedule = s_ipsc->cAlphaArgs(2);
     293            0 :         if (s_ipsc->lAlphaFieldBlanks(2)) {
     294            0 :             thisCP.availSched = Sched::GetScheduleAlwaysOn(state);
     295            0 :         } else if ((thisCP.availSched = Sched::GetSchedule(state, s_ipsc->cAlphaArgs(2))) == nullptr) {
     296            0 :             ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(2), s_ipsc->cAlphaArgs(2));
     297            0 :             ErrorsFound = true;
     298              :         }
     299              : 
     300              :         // Get inlet node number
     301            0 :         thisCP.WaterInletNode = NodeInputManager::GetOnlySingleNode(state,
     302            0 :                                                                     s_ipsc->cAlphaArgs(3),
     303              :                                                                     ErrorsFound,
     304              :                                                                     DataLoopNode::ConnectionObjectType::ZoneHVACCoolingPanelRadiantConvectiveWater,
     305            0 :                                                                     s_ipsc->cAlphaArgs(1),
     306              :                                                                     DataLoopNode::NodeFluidType::Water,
     307              :                                                                     DataLoopNode::ConnectionType::Inlet,
     308              :                                                                     NodeInputManager::CompFluidStream::Primary,
     309              :                                                                     DataLoopNode::ObjectIsNotParent);
     310              : 
     311              :         // Get outlet node number
     312            0 :         thisCP.WaterOutletNode = NodeInputManager::GetOnlySingleNode(state,
     313            0 :                                                                      s_ipsc->cAlphaArgs(4),
     314              :                                                                      ErrorsFound,
     315              :                                                                      DataLoopNode::ConnectionObjectType::ZoneHVACCoolingPanelRadiantConvectiveWater,
     316            0 :                                                                      s_ipsc->cAlphaArgs(1),
     317              :                                                                      DataLoopNode::NodeFluidType::Water,
     318              :                                                                      DataLoopNode::ConnectionType::Outlet,
     319              :                                                                      NodeInputManager::CompFluidStream::Primary,
     320              :                                                                      DataLoopNode::ObjectIsNotParent);
     321            0 :         BranchNodeConnections::TestCompSet(
     322            0 :             state, cCMO_CoolingPanel_Simple, s_ipsc->cAlphaArgs(1), s_ipsc->cAlphaArgs(3), s_ipsc->cAlphaArgs(4), "Chilled Water Nodes");
     323              : 
     324            0 :         thisCP.RatedWaterTemp = s_ipsc->rNumericArgs(1);
     325            0 :         if (thisCP.RatedWaterTemp > MaxWaterTempAvg + 0.001) {
     326            0 :             ShowWarningError(state,
     327            0 :                              format("{}{}=\"{}\", {} was higher than the allowable maximum.",
     328              :                                     RoutineName,
     329              :                                     cCMO_CoolingPanel_Simple,
     330            0 :                                     s_ipsc->cAlphaArgs(1),
     331            0 :                                     s_ipsc->cNumericFieldNames(1)));
     332            0 :             ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxWaterTempAvg));
     333            0 :             thisCP.RatedWaterTemp = MaxWaterTempAvg;
     334            0 :         } else if (thisCP.RatedWaterTemp < MinWaterTempAvg - 0.001) {
     335            0 :             ShowWarningError(state,
     336            0 :                              format("{}{}=\"{}\", {} was lower than the allowable minimum.",
     337              :                                     RoutineName,
     338              :                                     cCMO_CoolingPanel_Simple,
     339            0 :                                     s_ipsc->cAlphaArgs(1),
     340            0 :                                     s_ipsc->cNumericFieldNames(1)));
     341            0 :             ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinWaterTempAvg));
     342            0 :             thisCP.RatedWaterTemp = MinWaterTempAvg;
     343              :         }
     344              : 
     345            0 :         thisCP.RatedZoneAirTemp = s_ipsc->rNumericArgs(2);
     346            0 :         if (thisCP.RatedZoneAirTemp > MaxWaterTempAvg + 0.001) {
     347            0 :             ShowWarningError(state,
     348            0 :                              format("{}{}=\"{}\", {} was higher than the allowable maximum.",
     349              :                                     RoutineName,
     350              :                                     cCMO_CoolingPanel_Simple,
     351            0 :                                     s_ipsc->cAlphaArgs(1),
     352            0 :                                     s_ipsc->cNumericFieldNames(2)));
     353            0 :             ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxWaterTempAvg));
     354            0 :             thisCP.RatedZoneAirTemp = MaxWaterTempAvg;
     355            0 :         } else if (thisCP.RatedZoneAirTemp < MinWaterTempAvg - 0.001) {
     356            0 :             ShowWarningError(state,
     357            0 :                              format("{}{}=\"{}\", {} was lower than the allowable minimum.",
     358              :                                     RoutineName,
     359              :                                     cCMO_CoolingPanel_Simple,
     360            0 :                                     s_ipsc->cAlphaArgs(1),
     361            0 :                                     s_ipsc->cNumericFieldNames(2)));
     362            0 :             ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinWaterTempAvg));
     363            0 :             thisCP.RatedZoneAirTemp = MinWaterTempAvg;
     364              :         }
     365              : 
     366            0 :         thisCP.RatedWaterFlowRate = s_ipsc->rNumericArgs(3);
     367            0 :         if (thisCP.RatedWaterFlowRate < 0.00001 || thisCP.RatedWaterFlowRate > 10.0) {
     368            0 :             ShowWarningError(state,
     369            0 :                              format("{}{}=\"{}\", {} is an invalid Standard Water mass flow rate.",
     370              :                                     RoutineName,
     371              :                                     cCMO_CoolingPanel_Simple,
     372            0 :                                     s_ipsc->cAlphaArgs(1),
     373            0 :                                     s_ipsc->cNumericFieldNames(2)));
     374            0 :             ShowContinueError(state, format("...reset to a default value=[{:.1R}].", WaterMassFlowDefault));
     375            0 :             thisCP.RatedWaterFlowRate = WaterMassFlowDefault;
     376              :         }
     377              : 
     378            0 :         if (Util::SameString(s_ipsc->cAlphaArgs(5), "CoolingDesignCapacity")) {
     379            0 :             thisCP.CoolingCapMethod = DataSizing::CoolingDesignCapacity;
     380            0 :             if (!s_ipsc->lNumericFieldBlanks(4)) {
     381            0 :                 thisCP.ScaledCoolingCapacity = s_ipsc->rNumericArgs(4);
     382            0 :                 if (thisCP.ScaledCoolingCapacity < 0.0 && thisCP.ScaledCoolingCapacity != DataSizing::AutoSize) {
     383            0 :                     ShowSevereError(state, format("{} = {}", cCMO_CoolingPanel_Simple, thisCP.Name));
     384            0 :                     ShowContinueError(state, format("Illegal {} = {:.7T}", s_ipsc->cNumericFieldNames(4), s_ipsc->rNumericArgs(4)));
     385            0 :                     ErrorsFound = true;
     386              :                 }
     387              :             } else {
     388            0 :                 if ((!s_ipsc->lAlphaFieldBlanks(6)) || (!s_ipsc->lAlphaFieldBlanks(7))) {
     389            0 :                     ShowSevereError(state, format("{} = {}", cCMO_CoolingPanel_Simple, thisCP.Name));
     390            0 :                     ShowContinueError(state, format("Input for {} = {}", s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaArgs(5)));
     391            0 :                     ShowContinueError(state, format("Blank field not allowed for {}", s_ipsc->cNumericFieldNames(4)));
     392            0 :                     ErrorsFound = true;
     393              :                 }
     394              :             }
     395            0 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(5), "CapacityPerFloorArea")) {
     396            0 :             thisCP.CoolingCapMethod = DataSizing::CapacityPerFloorArea;
     397            0 :             if (!s_ipsc->lNumericFieldBlanks(5)) {
     398            0 :                 thisCP.ScaledCoolingCapacity = s_ipsc->rNumericArgs(5);
     399            0 :                 if (thisCP.ScaledCoolingCapacity < 0.0) {
     400            0 :                     ShowSevereError(state, format("{} = {}", cCMO_CoolingPanel_Simple, thisCP.Name));
     401            0 :                     ShowContinueError(state, format("Input for {} = {}", s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaArgs(5)));
     402            0 :                     ShowContinueError(state, format("Illegal {} = {:.7T}", s_ipsc->cNumericFieldNames(5), s_ipsc->rNumericArgs(5)));
     403            0 :                     ErrorsFound = true;
     404            0 :                 } else if (thisCP.ScaledCoolingCapacity == DataSizing::AutoSize) {
     405            0 :                     ShowSevereError(state, format("{} = {}", cCMO_CoolingPanel_Simple, thisCP.Name));
     406            0 :                     ShowContinueError(state, format("Input for {} = {}", s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaArgs(5)));
     407            0 :                     ShowContinueError(state, format("Illegal {} = Autosize", s_ipsc->cNumericFieldNames(5)));
     408            0 :                     ErrorsFound = true;
     409              :                 }
     410              :             } else {
     411            0 :                 ShowSevereError(state, format("{} = {}", cCMO_CoolingPanel_Simple, thisCP.Name));
     412            0 :                 ShowContinueError(state, format("Input for {} = {}", s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaArgs(5)));
     413            0 :                 ShowContinueError(state, format("Blank field not allowed for {}", s_ipsc->cNumericFieldNames(5)));
     414            0 :                 ErrorsFound = true;
     415              :             }
     416            0 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(5), "FractionOfAutosizedCoolingCapacity")) {
     417            0 :             thisCP.CoolingCapMethod = DataSizing::FractionOfAutosizedCoolingCapacity;
     418            0 :             if (!s_ipsc->lNumericFieldBlanks(6)) {
     419            0 :                 thisCP.ScaledCoolingCapacity = s_ipsc->rNumericArgs(6);
     420            0 :                 if (thisCP.ScaledCoolingCapacity < 0.0) {
     421            0 :                     ShowSevereError(state, format("{} = {}", cCMO_CoolingPanel_Simple, thisCP.Name));
     422            0 :                     ShowContinueError(state, format("Illegal {} = {:.7T}", s_ipsc->cNumericFieldNames(6), s_ipsc->rNumericArgs(6)));
     423            0 :                     ErrorsFound = true;
     424              :                 }
     425              :             } else {
     426            0 :                 ShowSevereError(state, format("{} = {}", cCMO_CoolingPanel_Simple, thisCP.Name));
     427            0 :                 ShowContinueError(state, format("Input for {} = {}", s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaArgs(5)));
     428            0 :                 ShowContinueError(state, format("Blank field not allowed for {}", s_ipsc->cNumericFieldNames(6)));
     429            0 :                 ErrorsFound = true;
     430              :             }
     431              :         } else {
     432            0 :             ShowSevereError(state, format("{} = {}", cCMO_CoolingPanel_Simple, thisCP.Name));
     433            0 :             ShowContinueError(state, format("Illegal {} = {}", s_ipsc->cAlphaFieldNames(5), s_ipsc->cAlphaArgs(5)));
     434            0 :             ErrorsFound = true;
     435              :         }
     436              : 
     437            0 :         thisCP.WaterVolFlowRateMax = s_ipsc->rNumericArgs(7);
     438            0 :         if ((thisCP.WaterVolFlowRateMax <= MinWaterFlowRate) && thisCP.WaterVolFlowRateMax != DataSizing::AutoSize) {
     439            0 :             ShowWarningError(state,
     440            0 :                              format("{}{}=\"{}\", {} was less than the allowable minimum.",
     441              :                                     RoutineName,
     442              :                                     cCMO_CoolingPanel_Simple,
     443            0 :                                     s_ipsc->cAlphaArgs(1),
     444            0 :                                     s_ipsc->cNumericFieldNames(7)));
     445            0 :             ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinWaterFlowRate));
     446            0 :             thisCP.WaterVolFlowRateMax = MinWaterFlowRate;
     447            0 :         } else if (thisCP.WaterVolFlowRateMax > MaxWaterFlowRate) {
     448            0 :             ShowWarningError(state,
     449            0 :                              format("{}{}=\"{}\", {} was higher than the allowable maximum.",
     450              :                                     RoutineName,
     451              :                                     cCMO_CoolingPanel_Simple,
     452            0 :                                     s_ipsc->cAlphaArgs(1),
     453            0 :                                     s_ipsc->cNumericFieldNames(7)));
     454            0 :             ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxWaterFlowRate));
     455            0 :             thisCP.WaterVolFlowRateMax = MaxWaterFlowRate;
     456              :         }
     457              : 
     458              :         // Process the temperature control type
     459            0 :         if (Util::SameString(s_ipsc->cAlphaArgs(6), MeanAirTemperature)) {
     460            0 :             thisCP.controlType = ClgPanelCtrlType::MAT;
     461            0 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(6), MeanRadiantTemperature)) {
     462            0 :             thisCP.controlType = ClgPanelCtrlType::MRT;
     463            0 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(6), OperativeTemperature)) {
     464            0 :             thisCP.controlType = ClgPanelCtrlType::Operative;
     465            0 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(6), OutsideAirDryBulbTemperature)) {
     466            0 :             thisCP.controlType = ClgPanelCtrlType::ODB;
     467            0 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(6), OutsideAirWetBulbTemperature)) {
     468            0 :             thisCP.controlType = ClgPanelCtrlType::OWB;
     469            0 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(6), ZoneTotalLoad)) {
     470            0 :             thisCP.controlType = ClgPanelCtrlType::ZoneTotalLoad;
     471            0 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(6), ZoneConvectiveLoad)) {
     472            0 :             thisCP.controlType = ClgPanelCtrlType::ZoneConvectiveLoad;
     473              :         } else {
     474            0 :             ShowWarningError(state, format("Invalid {} ={}", s_ipsc->cAlphaFieldNames(6), s_ipsc->cAlphaArgs(6)));
     475            0 :             ShowContinueError(state, format("Occurs in {} = {}", RoutineName, s_ipsc->cAlphaArgs(1)));
     476            0 :             ShowContinueError(state, "Control reset to MAT control for this Simple Cooling Panel.");
     477            0 :             thisCP.controlType = ClgPanelCtrlType::MAT;
     478              :         }
     479              : 
     480            0 :         thisCP.ColdThrottlRange = s_ipsc->rNumericArgs(8);
     481            0 :         if (thisCP.ColdThrottlRange < MinThrottlingRange) {
     482            0 :             ShowWarningError(state, format("{}Cooling throttling range too small, reset to 0.5", cCMO_CoolingPanel_Simple));
     483            0 :             ShowContinueError(state, format("Occurs in Cooling Panel={}", thisCP.Name));
     484            0 :             thisCP.ColdThrottlRange = MinThrottlingRange;
     485              :         }
     486              : 
     487            0 :         thisCP.ColdSetptSchedName = s_ipsc->cAlphaArgs(7);
     488            0 :         if (s_ipsc->lAlphaFieldBlanks(7)) {
     489            0 :             thisCP.coldSetptSched = Sched::GetScheduleAlwaysOff(state);
     490            0 :         } else if ((thisCP.coldSetptSched = Sched::GetSchedule(state, thisCP.ColdSetptSchedName)) == nullptr) {
     491            0 :             ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(7), s_ipsc->cAlphaArgs(7));
     492            0 :             ErrorsFound = true;
     493              :         }
     494              : 
     495            0 :         if (Util::SameString(s_ipsc->cAlphaArgs(8), Off)) {
     496            0 :             thisCP.CondCtrlType = CondCtrl::NONE;
     497            0 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(8), SimpleOff)) {
     498            0 :             thisCP.CondCtrlType = CondCtrl::SIMPLEOFF;
     499            0 :         } else if (Util::SameString(s_ipsc->cAlphaArgs(8), VariableOff)) {
     500            0 :             thisCP.CondCtrlType = CondCtrl::VARIEDOFF;
     501              :         } else {
     502            0 :             thisCP.CondCtrlType = CondCtrl::SIMPLEOFF;
     503              :         }
     504              : 
     505            0 :         thisCP.CondDewPtDeltaT = s_ipsc->rNumericArgs(9);
     506              : 
     507            0 :         thisCP.FracRadiant = s_ipsc->rNumericArgs(10);
     508            0 :         if (thisCP.FracRadiant < MinFraction) {
     509            0 :             ShowWarningError(state,
     510            0 :                              format("{}{}=\"{}\", {} was lower than the allowable minimum.",
     511              :                                     RoutineName,
     512              :                                     cCMO_CoolingPanel_Simple,
     513            0 :                                     s_ipsc->cAlphaArgs(1),
     514            0 :                                     s_ipsc->cNumericFieldNames(10)));
     515            0 :             ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinFraction));
     516            0 :             thisCP.FracRadiant = MinFraction;
     517              :         }
     518            0 :         if (thisCP.FracRadiant > MaxFraction) {
     519            0 :             ShowWarningError(state,
     520            0 :                              format("{}{}=\"{}\", {} was higher than the allowable maximum.",
     521              :                                     RoutineName,
     522              :                                     cCMO_CoolingPanel_Simple,
     523            0 :                                     s_ipsc->cAlphaArgs(1),
     524            0 :                                     s_ipsc->cNumericFieldNames(10)));
     525            0 :             ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxFraction));
     526            0 :             thisCP.FracRadiant = MaxFraction;
     527              :         }
     528              : 
     529              :         // Remaining fraction is added to the zone as convective heat transfer
     530            0 :         if (thisCP.FracRadiant > MaxFraction) {
     531            0 :             ShowWarningError(state,
     532            0 :                              format("{}{}=\"{}\", Fraction Radiant was higher than the allowable maximum.",
     533              :                                     RoutineName,
     534              :                                     cCMO_CoolingPanel_Simple,
     535            0 :                                     s_ipsc->cAlphaArgs(1)));
     536            0 :             thisCP.FracRadiant = MaxFraction;
     537            0 :             thisCP.FracConvect = 0.0;
     538              :         } else {
     539            0 :             thisCP.FracConvect = 1.0 - thisCP.FracRadiant;
     540              :         }
     541              : 
     542            0 :         thisCP.FracDistribPerson = s_ipsc->rNumericArgs(11);
     543            0 :         if (thisCP.FracDistribPerson < MinFraction) {
     544            0 :             ShowWarningError(state,
     545            0 :                              format("{}{}=\"{}\", {} was lower than the allowable minimum.",
     546              :                                     RoutineName,
     547              :                                     cCMO_CoolingPanel_Simple,
     548            0 :                                     s_ipsc->cAlphaArgs(1),
     549            0 :                                     s_ipsc->cNumericFieldNames(11)));
     550            0 :             ShowContinueError(state, format("...reset to minimum value=[{:.3R}].", MinFraction));
     551            0 :             thisCP.FracDistribPerson = MinFraction;
     552              :         }
     553            0 :         if (thisCP.FracDistribPerson > MaxFraction) {
     554            0 :             ShowWarningError(state,
     555            0 :                              format("{}{}=\"{}\", {} was higher than the allowable maximum.",
     556              :                                     RoutineName,
     557              :                                     cCMO_CoolingPanel_Simple,
     558            0 :                                     s_ipsc->cAlphaArgs(1),
     559            0 :                                     s_ipsc->cNumericFieldNames(11)));
     560            0 :             ShowContinueError(state, format("...reset to maximum value=[{:.3R}].", MaxFraction));
     561            0 :             thisCP.FracDistribPerson = MaxFraction;
     562              :         }
     563              : 
     564            0 :         thisCP.TotSurfToDistrib = NumNumbers - 11;
     565            0 :         if ((thisCP.TotSurfToDistrib < MinDistribSurfaces) && (thisCP.FracRadiant > MinFraction)) {
     566            0 :             ShowSevereError(state,
     567            0 :                             format("{}{}=\"{}\", the number of surface/radiant fraction groups entered was less than the allowable minimum.",
     568              :                                    RoutineName,
     569              :                                    cCMO_CoolingPanel_Simple,
     570            0 :                                    s_ipsc->cAlphaArgs(1)));
     571            0 :             ShowContinueError(state, format("...the minimum that must be entered=[{}].", MinDistribSurfaces));
     572            0 :             ErrorsFound = true;
     573            0 :             thisCP.TotSurfToDistrib = 0; // error
     574              :         }
     575              : 
     576            0 :         thisCP.SurfaceName.allocate(thisCP.TotSurfToDistrib);
     577            0 :         thisCP.SurfaceName = "";
     578            0 :         thisCP.SurfacePtr.allocate(thisCP.TotSurfToDistrib);
     579            0 :         thisCP.SurfacePtr = 0;
     580            0 :         thisCP.FracDistribToSurf.allocate(thisCP.TotSurfToDistrib);
     581            0 :         thisCP.FracDistribToSurf = 0.0;
     582              : 
     583              :         // search zone equipment list structure for zone index
     584            0 :         for (int ctrlZone = 1; ctrlZone <= state.dataGlobal->NumOfZones; ++ctrlZone) {
     585            0 :             for (int zoneEquipTypeNum = 1; zoneEquipTypeNum <= state.dataZoneEquip->ZoneEquipList(ctrlZone).NumOfEquipTypes; ++zoneEquipTypeNum) {
     586            0 :                 if (state.dataZoneEquip->ZoneEquipList(ctrlZone).EquipType(zoneEquipTypeNum) == DataZoneEquipment::ZoneEquipType::CoolingPanel &&
     587            0 :                     state.dataZoneEquip->ZoneEquipList(ctrlZone).EquipName(zoneEquipTypeNum) == thisCP.Name) {
     588            0 :                     thisCP.ZonePtr = ctrlZone;
     589              :                 }
     590              :             }
     591              :         }
     592            0 :         if (thisCP.ZonePtr <= 0) {
     593            0 :             ShowSevereError(state, format("{}{}=\"{}\" is not on any ZoneHVAC:EquipmentList.", RoutineName, cCMO_CoolingPanel_Simple, thisCP.Name));
     594            0 :             ErrorsFound = true;
     595            0 :             continue;
     596              :         }
     597              : 
     598            0 :         Real64 AllFracsSummed = thisCP.FracDistribPerson;
     599            0 :         for (SurfNum = 1; SurfNum <= thisCP.TotSurfToDistrib; ++SurfNum) {
     600            0 :             thisCP.SurfaceName(SurfNum) = s_ipsc->cAlphaArgs(SurfNum + 8);
     601            0 :             thisCP.SurfacePtr(SurfNum) = HeatBalanceIntRadExchange::GetRadiantSystemSurface(
     602            0 :                 state, cCMO_CoolingPanel_Simple, thisCP.Name, thisCP.ZonePtr, thisCP.SurfaceName(SurfNum), ErrorsFound);
     603            0 :             thisCP.FracDistribToSurf(SurfNum) = s_ipsc->rNumericArgs(SurfNum + 11);
     604            0 :             if (thisCP.FracDistribToSurf(SurfNum) > MaxFraction) {
     605            0 :                 ShowWarningError(state,
     606            0 :                                  format("{}{}=\"{}\", {}was greater than the allowable maximum.",
     607              :                                         RoutineName,
     608              :                                         cCMO_CoolingPanel_Simple,
     609            0 :                                         s_ipsc->cAlphaArgs(1),
     610            0 :                                         s_ipsc->cNumericFieldNames(SurfNum + 8)));
     611            0 :                 ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxFraction));
     612            0 :                 thisCP.TotSurfToDistrib = MaxFraction;
     613              :             }
     614            0 :             if (thisCP.FracDistribToSurf(SurfNum) < MinFraction) {
     615            0 :                 ShowWarningError(state,
     616            0 :                                  format("{}{}=\"{}\", {}was less than the allowable minimum.",
     617              :                                         RoutineName,
     618              :                                         cCMO_CoolingPanel_Simple,
     619            0 :                                         s_ipsc->cAlphaArgs(1),
     620            0 :                                         s_ipsc->cNumericFieldNames(SurfNum + 8)));
     621            0 :                 ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MinFraction));
     622            0 :                 thisCP.TotSurfToDistrib = MinFraction;
     623              :             }
     624            0 :             if (thisCP.SurfacePtr(SurfNum) != 0) {
     625            0 :                 state.dataSurface->surfIntConv(thisCP.SurfacePtr(SurfNum)).getsRadiantHeat = true;
     626            0 :                 state.dataSurface->allGetsRadiantHeatSurfaceList.emplace_back(thisCP.SurfacePtr(SurfNum));
     627              :             }
     628              : 
     629            0 :             AllFracsSummed += thisCP.FracDistribToSurf(SurfNum);
     630              :         } // Surfaces
     631              : 
     632            0 :         if (AllFracsSummed > (MaxFraction + 0.01)) {
     633            0 :             ShowSevereError(state,
     634            0 :                             format("{}{}=\"{}\", Summed radiant fractions for people + surface groups > 1.0",
     635              :                                    RoutineName,
     636              :                                    cCMO_CoolingPanel_Simple,
     637            0 :                                    s_ipsc->cAlphaArgs(1)));
     638            0 :             ErrorsFound = true;
     639              :         }
     640            0 :         if ((AllFracsSummed < (MaxFraction - 0.01)) &&
     641            0 :             (thisCP.FracRadiant > MinFraction)) { // User didn't distribute all of the | radiation warn that some will be lost
     642            0 :             ShowSevereError(state,
     643            0 :                             format("{}{}=\"{}\", Summed radiant fractions for people + surface groups < 1.0",
     644              :                                    RoutineName,
     645              :                                    cCMO_CoolingPanel_Simple,
     646            0 :                                    s_ipsc->cAlphaArgs(1)));
     647            0 :             ShowContinueError(state, "This would result in some of the radiant energy delivered by the high temp radiant heater being lost.");
     648            0 :             ShowContinueError(state, format("The sum of all radiation fractions to surfaces = {:.5T}", (AllFracsSummed - thisCP.FracDistribPerson)));
     649            0 :             ShowContinueError(state, format("The radiant fraction to people = {:.5T}", thisCP.FracDistribPerson));
     650            0 :             ShowContinueError(state, format("So, all radiant fractions including surfaces and people = {:.5T}", AllFracsSummed));
     651            0 :             ShowContinueError(state,
     652            0 :                               format("This means that the fraction of radiant energy that would be lost from the high temperature radiant heater "
     653              :                                      "would be = {:.5T}",
     654            0 :                                      (1.0 - AllFracsSummed)));
     655            0 :             ShowContinueError(state,
     656            0 :                               format("Please check and correct this so that all radiant energy is accounted for in {} = {}",
     657              :                                      cCMO_CoolingPanel_Simple,
     658            0 :                                      s_ipsc->cAlphaArgs(1)));
     659            0 :             ErrorsFound = true;
     660              :         }
     661              :     }
     662              : 
     663            0 :     if (ErrorsFound) {
     664            0 :         ShowFatalError(state, format("{}{}Errors found getting input. Program terminates.", RoutineName, cCMO_CoolingPanel_Simple));
     665              :     }
     666              : 
     667              :     // Setup Report variables for the Coils
     668            0 :     for (int CoolingPanelNum = 1; CoolingPanelNum <= NumCoolingPanels; ++CoolingPanelNum) {
     669              :         // CurrentModuleObject='ZoneHVAC:CoolingPanel:RadiantConvective:Water'
     670            0 :         auto &thisCP = state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum);
     671            0 :         SetupOutputVariable(state,
     672              :                             "Cooling Panel Total Cooling Rate",
     673              :                             Constant::Units::W,
     674            0 :                             thisCP.Power,
     675              :                             OutputProcessor::TimeStepType::System,
     676              :                             OutputProcessor::StoreType::Average,
     677            0 :                             thisCP.Name);
     678            0 :         SetupOutputVariable(state,
     679              :                             "Cooling Panel Total System Cooling Rate",
     680              :                             Constant::Units::W,
     681            0 :                             thisCP.TotPower,
     682              :                             OutputProcessor::TimeStepType::System,
     683              :                             OutputProcessor::StoreType::Average,
     684            0 :                             thisCP.Name);
     685            0 :         SetupOutputVariable(state,
     686              :                             "Cooling Panel Convective Cooling Rate",
     687              :                             Constant::Units::W,
     688            0 :                             thisCP.ConvPower,
     689              :                             OutputProcessor::TimeStepType::System,
     690              :                             OutputProcessor::StoreType::Average,
     691            0 :                             thisCP.Name);
     692            0 :         SetupOutputVariable(state,
     693              :                             "Cooling Panel Radiant Cooling Rate",
     694              :                             Constant::Units::W,
     695            0 :                             thisCP.RadPower,
     696              :                             OutputProcessor::TimeStepType::System,
     697              :                             OutputProcessor::StoreType::Average,
     698            0 :                             thisCP.Name);
     699              : 
     700            0 :         SetupOutputVariable(state,
     701              :                             "Cooling Panel Total Cooling Energy",
     702              :                             Constant::Units::J,
     703            0 :                             thisCP.Energy,
     704              :                             OutputProcessor::TimeStepType::System,
     705              :                             OutputProcessor::StoreType::Sum,
     706            0 :                             thisCP.Name,
     707              :                             Constant::eResource::EnergyTransfer,
     708              :                             OutputProcessor::Group::HVAC,
     709              :                             OutputProcessor::EndUseCat::CoolingPanel);
     710            0 :         SetupOutputVariable(state,
     711              :                             "Cooling Panel Total System Cooling Energy",
     712              :                             Constant::Units::J,
     713            0 :                             thisCP.TotEnergy,
     714              :                             OutputProcessor::TimeStepType::System,
     715              :                             OutputProcessor::StoreType::Sum,
     716            0 :                             thisCP.Name,
     717              :                             Constant::eResource::EnergyTransfer,
     718              :                             OutputProcessor::Group::HVAC,
     719              :                             OutputProcessor::EndUseCat::CoolingPanel);
     720            0 :         SetupOutputVariable(state,
     721              :                             "Cooling Panel Convective Cooling Energy",
     722              :                             Constant::Units::J,
     723            0 :                             thisCP.ConvEnergy,
     724              :                             OutputProcessor::TimeStepType::System,
     725              :                             OutputProcessor::StoreType::Sum,
     726            0 :                             thisCP.Name);
     727            0 :         SetupOutputVariable(state,
     728              :                             "Cooling Panel Radiant Cooling Energy",
     729              :                             Constant::Units::J,
     730            0 :                             thisCP.RadEnergy,
     731              :                             OutputProcessor::TimeStepType::System,
     732              :                             OutputProcessor::StoreType::Sum,
     733            0 :                             thisCP.Name);
     734              : 
     735            0 :         SetupOutputVariable(state,
     736              :                             "Cooling Panel Water Mass Flow Rate",
     737              :                             Constant::Units::kg_s,
     738            0 :                             thisCP.WaterMassFlowRate,
     739              :                             OutputProcessor::TimeStepType::System,
     740              :                             OutputProcessor::StoreType::Average,
     741            0 :                             thisCP.Name);
     742            0 :         SetupOutputVariable(state,
     743              :                             "Cooling Panel Water Inlet Temperature",
     744              :                             Constant::Units::C,
     745            0 :                             thisCP.WaterInletTemp,
     746              :                             OutputProcessor::TimeStepType::System,
     747              :                             OutputProcessor::StoreType::Average,
     748            0 :                             thisCP.Name);
     749            0 :         SetupOutputVariable(state,
     750              :                             "Cooling Panel Water Outlet Temperature",
     751              :                             Constant::Units::C,
     752            0 :                             thisCP.WaterOutletTemp,
     753              :                             OutputProcessor::TimeStepType::System,
     754              :                             OutputProcessor::StoreType::Average,
     755            0 :                             thisCP.Name);
     756              :     }
     757            0 : }
     758              : 
     759            0 : void InitCoolingPanel(EnergyPlusData &state, int const CoolingPanelNum, int const ControlledZoneNum, bool const FirstHVACIteration)
     760              : {
     761              : 
     762              :     // SUBROUTINE INFORMATION:
     763              :     //       AUTHOR         Rick Strand
     764              :     //       DATE WRITTEN   Sept 2014
     765              : 
     766              :     // PURPOSE OF THIS SUBROUTINE:
     767              :     // This subroutine initializes the cooling panel units, and determines the UA values during simulation.
     768              : 
     769              :     // METHODOLOGY EMPLOYED:
     770              :     // The initialization subroutines borrowed from other sources and heat exchanger formulation for cooling panel.
     771              : 
     772              :     // REFERENCES:
     773              :     // Incropera and DeWitt, Fundamentals of Heat and Mass Transfer
     774              : 
     775              :     // SUBROUTINE PARAMETER DEFINITIONS:
     776              :     static constexpr std::string_view RoutineName("ChilledCeilingPanelSimple:InitCoolingPanel");
     777              : 
     778              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     779              :     Real64 rho; // local fluid density
     780              :     Real64 Cp;  // local fluid specific heat
     781              : 
     782            0 :     auto &thisCP = state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum);
     783            0 :     auto &ThisInNode = state.dataLoopNodes->Node(thisCP.WaterInletNode);
     784              : 
     785            0 :     if (thisCP.ZonePtr <= 0) thisCP.ZonePtr = ControlledZoneNum;
     786              : 
     787              :     // Need to check all units to see if they are on ZoneHVAC:EquipmentList or issue warning
     788            0 :     if (!thisCP.ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
     789            0 :         thisCP.ZoneEquipmentListChecked = true;
     790            0 :         if (!DataZoneEquipment::CheckZoneEquipmentList(state, cCMO_CoolingPanel_Simple, thisCP.Name)) {
     791            0 :             ShowSevereError(state,
     792            0 :                             format("InitCoolingPanel: Unit=[{},{}] is not on any ZoneHVAC:EquipmentList.  It will not be simulated.",
     793              :                                    cCMO_CoolingPanel_Simple,
     794            0 :                                    thisCP.Name));
     795              :         }
     796              :     }
     797              : 
     798            0 :     if (thisCP.SetLoopIndexFlag) {
     799            0 :         if (allocated(state.dataPlnt->PlantLoop)) {
     800            0 :             bool errFlag = false;
     801            0 :             PlantUtilities::ScanPlantLoopsForObject(state, thisCP.Name, thisCP.EquipType, thisCP.plantLoc, errFlag, _, _, _, _, _);
     802            0 :             if (errFlag) {
     803            0 :                 ShowFatalError(state, "InitCoolingPanel: Program terminated for previous conditions.");
     804              :             }
     805            0 :             thisCP.SetLoopIndexFlag = false;
     806              :         }
     807              :     }
     808              : 
     809            0 :     if (!state.dataGlobal->SysSizingCalc) {
     810            0 :         if (thisCP.MySizeFlagCoolPanel && !thisCP.SetLoopIndexFlag) {
     811              :             // for each cooling panel do the sizing once.
     812            0 :             SizeCoolingPanel(state, CoolingPanelNum);
     813            0 :             thisCP.MySizeFlagCoolPanel = false;
     814              : 
     815              :             // set design mass flow rates
     816            0 :             if (thisCP.WaterInletNode > 0) {
     817            0 :                 rho = thisCP.plantLoc.loop->glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
     818            0 :                 thisCP.WaterMassFlowRateMax = rho * thisCP.WaterVolFlowRateMax;
     819            0 :                 PlantUtilities::InitComponentNodes(state, 0.0, thisCP.WaterMassFlowRateMax, thisCP.WaterInletNode, thisCP.WaterOutletNode);
     820              :             }
     821              :         }
     822              :     }
     823              : 
     824              :     // Do the Begin Environment initializations
     825            0 :     if (state.dataGlobal->BeginEnvrnFlag && thisCP.MyEnvrnFlag) {
     826              :         // Initialize
     827              : 
     828            0 :         rho = thisCP.plantLoc.loop->glycol->getDensity(state, Constant::InitConvTemp, RoutineName);
     829              : 
     830            0 :         thisCP.WaterMassFlowRateMax = rho * thisCP.WaterVolFlowRateMax;
     831              : 
     832            0 :         PlantUtilities::InitComponentNodes(state, 0.0, thisCP.WaterMassFlowRateMax, thisCP.WaterInletNode, thisCP.WaterOutletNode);
     833              : 
     834            0 :         ThisInNode.Temp = 7.0;
     835              : 
     836            0 :         Cp = thisCP.plantLoc.loop->glycol->getSpecificHeat(state, ThisInNode.Temp, RoutineName);
     837              : 
     838            0 :         ThisInNode.Enthalpy = Cp * ThisInNode.Temp;
     839            0 :         ThisInNode.Quality = 0.0;
     840            0 :         ThisInNode.Press = 0.0;
     841            0 :         ThisInNode.HumRat = 0.0;
     842              : 
     843            0 :         thisCP.ZeroCPSourceSumHATsurf = 0.0;
     844            0 :         thisCP.CoolingPanelSource = 0.0;
     845            0 :         thisCP.CoolingPanelSrcAvg = 0.0;
     846            0 :         thisCP.LastCoolingPanelSrc = 0.0;
     847            0 :         thisCP.LastSysTimeElapsed = 0.0;
     848            0 :         thisCP.LastTimeStepSys = 0.0;
     849              : 
     850            0 :         thisCP.MyEnvrnFlag = false;
     851              :     }
     852              : 
     853            0 :     if (!state.dataGlobal->BeginEnvrnFlag) {
     854            0 :         thisCP.MyEnvrnFlag = true;
     855              :     }
     856              : 
     857            0 :     if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) {
     858            0 :         int ZoneNum = thisCP.ZonePtr;
     859            0 :         thisCP.ZeroCPSourceSumHATsurf = state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state);
     860            0 :         thisCP.CoolingPanelSrcAvg = 0.0;
     861            0 :         thisCP.LastCoolingPanelSrc = 0.0;
     862            0 :         thisCP.LastSysTimeElapsed = 0.0;
     863            0 :         thisCP.LastTimeStepSys = 0.0;
     864              :     }
     865              : 
     866              :     // Do the every time step initializations
     867            0 :     thisCP.WaterMassFlowRate = ThisInNode.MassFlowRate;
     868            0 :     thisCP.WaterInletTemp = ThisInNode.Temp;
     869            0 :     thisCP.WaterInletEnthalpy = ThisInNode.Enthalpy;
     870            0 :     thisCP.TotPower = 0.0;
     871            0 :     thisCP.Power = 0.0;
     872            0 :     thisCP.ConvPower = 0.0;
     873            0 :     thisCP.RadPower = 0.0;
     874            0 :     thisCP.TotEnergy = 0.0;
     875            0 :     thisCP.Energy = 0.0;
     876            0 :     thisCP.ConvEnergy = 0.0;
     877            0 :     thisCP.RadEnergy = 0.0;
     878            0 : }
     879              : 
     880            0 : void SizeCoolingPanel(EnergyPlusData &state, int const CoolingPanelNum)
     881              : {
     882              :     // SUBROUTINE INFORMATION:
     883              :     //       AUTHOR         Rick Strand
     884              :     //       DATE WRITTEN   Sept 2016
     885              : 
     886              :     // PURPOSE OF THIS SUBROUTINE:
     887              :     // This subroutine sizes the simple chilled ceiling panel.  The process used here
     888              :     // was derived from the low temperature radiant system model and adapted for
     889              :     // cooling only.
     890              : 
     891              :     // SUBROUTINE PARAMETER DEFINITIONS:
     892              :     static constexpr std::string_view RoutineName("SizeCoolingPanel");
     893              : 
     894              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     895            0 :     bool ErrorsFound(false); // If errors detected in input
     896            0 :     bool IsAutoSize(false);  // Indicator to autosize
     897              :     Real64 DesCoilLoad;      // design autosized or user specified capacity
     898              :     Real64 TempSize;         // autosized value of coil input field
     899              :     Real64 rho;
     900              :     Real64 Cp;
     901            0 :     Real64 WaterVolFlowMaxCoolDes(0.0);  // Design chilled water flow for reporting
     902            0 :     Real64 WaterVolFlowMaxCoolUser(0.0); // User hard-sized chilled water flow for reporting
     903              : 
     904            0 :     DesCoilLoad = 0.0;
     905            0 :     state.dataSize->DataScalableCapSizingON = false;
     906              : 
     907            0 :     auto &thisCP(state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum));
     908              : 
     909            0 :     std::string_view const CompType = "ZoneHVAC:CoolingPanel:RadiantConvective:Water";
     910            0 :     std::string_view const CompName = thisCP.Name;
     911              : 
     912            0 :     IsAutoSize = false;
     913            0 :     if (thisCP.ScaledCoolingCapacity == DataSizing::AutoSize) {
     914            0 :         IsAutoSize = true;
     915              :     }
     916              : 
     917            0 :     if (state.dataSize->CurZoneEqNum > 0) {
     918              : 
     919            0 :         auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
     920            0 :         int SizingMethod = HVAC::CoolingCapacitySizing;
     921            0 :         bool PrintFlag = true; // TRUE when sizing information is reported in the eio file
     922            0 :         bool errorsFound = false;
     923            0 :         int CapSizingMethod = thisCP.CoolingCapMethod;
     924            0 :         zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
     925              : 
     926            0 :         if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
     927            0 :             if (CapSizingMethod == DataSizing::CoolingDesignCapacity && thisCP.ScaledCoolingCapacity > 0.0) {
     928            0 :                 TempSize = thisCP.ScaledCoolingCapacity;
     929            0 :                 CoolingCapacitySizer sizerCoolingCapacity;
     930            0 :                 sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     931            0 :                 DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, errorsFound);
     932            0 :             } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
     933            0 :                 state.dataSize->DataScalableCapSizingON = true;
     934            0 :                 TempSize = thisCP.ScaledCoolingCapacity * state.dataHeatBal->Zone(thisCP.ZonePtr).FloorArea;
     935            0 :                 CoolingCapacitySizer sizerCoolingCapacity;
     936            0 :                 sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     937            0 :                 DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, errorsFound);
     938            0 :                 state.dataSize->DataScalableCapSizingON = false;
     939            0 :             } else if (CapSizingMethod == DataSizing::FractionOfAutosizedCoolingCapacity) {
     940            0 :                 if (thisCP.WaterVolFlowRateMax == DataSizing::AutoSize) {
     941            0 :                     ShowSevereError(state, format("{}: auto-sizing cannot be done for {} = {}\".", RoutineName, CompType, thisCP.Name));
     942            0 :                     ShowContinueError(state,
     943              :                                       "The \"SimulationControl\" object must have the field \"Do Zone Sizing Calculation\" set to Yes when the "
     944              :                                       "Cooling Design Capacity Method = \"FractionOfAutosizedCoolingCapacity\".");
     945            0 :                     ErrorsFound = true;
     946              :                 }
     947              :             }
     948              :         } else { // Autosize or hard-size with sizing run
     949            0 :             if (CapSizingMethod == DataSizing::CoolingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
     950              :                 CapSizingMethod == DataSizing::FractionOfAutosizedCoolingCapacity) {
     951            0 :                 if (CapSizingMethod == DataSizing::CoolingDesignCapacity) {
     952            0 :                     if (state.dataSize->ZoneSizingRunDone) {
     953            0 :                         CheckZoneSizing(state, CompType, CompName);
     954            0 :                         state.dataSize->DataConstantUsedForSizing =
     955            0 :                             state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
     956            0 :                         state.dataSize->DataFractionUsedForSizing = 1.0;
     957              :                     }
     958            0 :                     TempSize = thisCP.ScaledCoolingCapacity;
     959            0 :                 } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
     960            0 :                     if (state.dataSize->ZoneSizingRunDone) {
     961            0 :                         CheckZoneSizing(state, CompType, CompName);
     962            0 :                         zoneEqSizing.CoolingCapacity = true;
     963            0 :                         zoneEqSizing.DesCoolingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
     964              :                     }
     965            0 :                     TempSize = thisCP.ScaledCoolingCapacity * state.dataHeatBal->Zone(thisCP.ZonePtr).FloorArea;
     966            0 :                     state.dataSize->DataScalableCapSizingON = true;
     967            0 :                 } else if (CapSizingMethod == DataSizing::FractionOfAutosizedCoolingCapacity) {
     968            0 :                     CheckZoneSizing(state, CompType, CompName);
     969            0 :                     zoneEqSizing.CoolingCapacity = true;
     970            0 :                     zoneEqSizing.DesCoolingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
     971            0 :                     TempSize = zoneEqSizing.DesCoolingLoad * thisCP.ScaledCoolingCapacity;
     972            0 :                     state.dataSize->DataScalableCapSizingON = true;
     973              : 
     974              :                 } else {
     975            0 :                     TempSize = thisCP.ScaledCoolingCapacity;
     976              :                 }
     977            0 :                 CoolingCapacitySizer sizerCoolingCapacity;
     978            0 :                 sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     979            0 :                 DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, errorsFound);
     980            0 :                 state.dataSize->DataConstantUsedForSizing = 0.0;
     981            0 :                 state.dataSize->DataFractionUsedForSizing = 0.0;
     982            0 :                 state.dataSize->DataScalableCapSizingON = false;
     983            0 :             } else {
     984            0 :                 DesCoilLoad = 0.0;
     985              :             }
     986              :         }
     987              :         // finally cooling capacity is saved in this variable
     988            0 :         thisCP.ScaledCoolingCapacity = DesCoilLoad;
     989              :     }
     990              : 
     991            0 :     IsAutoSize = false;
     992            0 :     if (thisCP.WaterVolFlowRateMax == DataSizing::AutoSize) {
     993            0 :         IsAutoSize = true;
     994              :     }
     995            0 :     if (state.dataSize->CurZoneEqNum > 0) {
     996            0 :         if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
     997            0 :             if (thisCP.WaterVolFlowRateMax > 0.0) {
     998            0 :                 BaseSizer::reportSizerOutput(
     999              :                     state, CompType, thisCP.Name, "User-Specified Maximum Cold Water Flow [m3/s]", thisCP.WaterVolFlowRateMax);
    1000              :             }
    1001              :         } else { // Autosize or hard-size with sizing run
    1002            0 :             if (thisCP.WaterInletNode > 0 && thisCP.WaterOutletNode > 0) {
    1003              :                 int PltSizCoolNum =
    1004            0 :                     PlantUtilities::MyPlantSizingIndex(state, CompType, thisCP.Name, thisCP.WaterInletNode, thisCP.WaterOutletNode, ErrorsFound);
    1005            0 :                 if (PltSizCoolNum > 0) {
    1006            0 :                     if (DesCoilLoad >= HVAC::SmallLoad) {
    1007            0 :                         rho = thisCP.plantLoc.loop->glycol->getDensity(state, 5., RoutineName);
    1008            0 :                         Cp = thisCP.plantLoc.loop->glycol->getSpecificHeat(state, 5.0, RoutineName);
    1009            0 :                         WaterVolFlowMaxCoolDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizCoolNum).DeltaT * Cp * rho);
    1010              :                     } else {
    1011            0 :                         WaterVolFlowMaxCoolDes = 0.0;
    1012              :                     }
    1013              :                 } else {
    1014            0 :                     ShowSevereError(state, "Autosizing of water flow requires a cooling loop Sizing:Plant object");
    1015            0 :                     ShowContinueError(state, format("Occurs in ZoneHVAC:CoolingPanel:RadiantConvective:Water Object={}", thisCP.Name));
    1016              :                 }
    1017              :             }
    1018              : 
    1019            0 :             if (IsAutoSize) {
    1020            0 :                 thisCP.WaterVolFlowRateMax = WaterVolFlowMaxCoolDes;
    1021            0 :                 BaseSizer::reportSizerOutput(state, CompType, thisCP.Name, "Design Size Maximum Cold Water Flow [m3/s]", WaterVolFlowMaxCoolDes);
    1022              :             } else { // hard-size with sizing data
    1023            0 :                 if (thisCP.WaterVolFlowRateMax > 0.0 && WaterVolFlowMaxCoolDes > 0.0) {
    1024            0 :                     WaterVolFlowMaxCoolUser = thisCP.WaterVolFlowRateMax;
    1025            0 :                     BaseSizer::reportSizerOutput(state,
    1026              :                                                  CompType,
    1027              :                                                  thisCP.Name,
    1028              :                                                  "Design Size Maximum Cold Water Flow [m3/s]",
    1029              :                                                  WaterVolFlowMaxCoolDes,
    1030              :                                                  "User-Specified Maximum Cold Water Flow [m3/s]",
    1031              :                                                  WaterVolFlowMaxCoolUser);
    1032            0 :                     if (state.dataGlobal->DisplayExtraWarnings) {
    1033            0 :                         if ((std::abs(WaterVolFlowMaxCoolDes - WaterVolFlowMaxCoolUser) / WaterVolFlowMaxCoolUser) >
    1034            0 :                             state.dataSize->AutoVsHardSizingThreshold) {
    1035            0 :                             ShowMessage(state,
    1036            0 :                                         format("SizeCoolingPanel: Potential issue with equipment sizing for "
    1037              :                                                "ZoneHVAC:CoolingPanel:RadiantConvective:Water = \"{}\".",
    1038            0 :                                                thisCP.Name));
    1039            0 :                             ShowContinueError(state, format("User-Specified Maximum Cool Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxCoolUser));
    1040            0 :                             ShowContinueError(state,
    1041            0 :                                               format("differs from Design Size Maximum Cool Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxCoolDes));
    1042            0 :                             ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1043            0 :                             ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1044              :                         }
    1045              :                     }
    1046              :                 }
    1047              :             }
    1048              :         }
    1049              :     }
    1050              : 
    1051            0 :     PlantUtilities::RegisterPlantCompDesignFlow(state, thisCP.WaterInletNode, thisCP.WaterVolFlowRateMax);
    1052              : 
    1053            0 :     if (!thisCP.SizeCoolingPanelUA(state)) {
    1054            0 :         ShowFatalError(state, "SizeCoolingPanelUA: Program terminated for previous conditions.");
    1055              :     }
    1056            0 : }
    1057              : 
    1058            5 : bool CoolingPanelParams::SizeCoolingPanelUA(EnergyPlusData &state)
    1059              : {
    1060              : 
    1061              :     // SUBROUTINE INFORMATION:
    1062              :     //       AUTHOR         Rick Strand
    1063              :     //       DATE WRITTEN   June 2017
    1064              : 
    1065              :     // PURPOSE OF THIS SUBROUTINE:
    1066              :     // This subroutine sizes UA value for the simple chilled ceiling panel.
    1067              : 
    1068              :     // These initializations are mainly the calculation of the UA value for the heat exchanger formulation of the simple cooling panel
    1069              :     Real64 RatCapToTheoMax; // Ratio of unit capacity to theoretical maximum output based on rated parameters
    1070              : 
    1071            5 :     Real64 constexpr Cp = 4120.0; // Just an approximation, don't need to get an exact number
    1072            5 :     Real64 const MDot = this->RatedWaterFlowRate;
    1073            5 :     Real64 const MDotXCp = Cp * MDot;
    1074            5 :     Real64 const Qrated = this->ScaledCoolingCapacity;
    1075            5 :     Real64 const Tinletr = this->RatedWaterTemp;
    1076            5 :     Real64 const Tzoner = this->RatedZoneAirTemp;
    1077              : 
    1078            5 :     if (Tinletr >= Tzoner) {
    1079            2 :         ShowSevereError(state,
    1080            2 :                         format("SizeCoolingPanelUA: Unit=[{},{}] has a rated water temperature that is higher than the rated zone temperature.",
    1081              :                                cCMO_CoolingPanel_Simple,
    1082            1 :                                this->Name));
    1083            2 :         ShowContinueError(state,
    1084              :                           "Such a situation would not lead to cooling and thus the rated water or zone temperature or both should be adjusted.");
    1085            1 :         this->UA = 1.0;
    1086            1 :         return false;
    1087              :     }
    1088              : 
    1089            4 :     if ((Tzoner - Tinletr) < 0.5) {
    1090            1 :         RatCapToTheoMax = std::abs(Qrated) / (MDotXCp * 0.5); // Avoid a divide by zero error
    1091              :     } else {
    1092            3 :         RatCapToTheoMax = std::abs(Qrated) / (MDotXCp * std::abs(Tinletr - Tzoner));
    1093              :     }
    1094            4 :     if ((RatCapToTheoMax < 1.1) && (RatCapToTheoMax > 0.9999)) {
    1095              :         // close to unity with some graciousness given in case the approximation of Cp causes a problem
    1096            1 :         RatCapToTheoMax = 0.9999;
    1097            3 :     } else if (RatCapToTheoMax >= 1.1) {
    1098            2 :         ShowSevereError(state,
    1099            2 :                         format("SizeCoolingPanelUA: Unit=[{},{}] has a cooling capacity that is greater than the maximum possible value.",
    1100              :                                cCMO_CoolingPanel_Simple,
    1101            1 :                                this->Name));
    1102            2 :         ShowContinueError(state, "The result of this is that a UA value is impossible to calculate.");
    1103            2 :         ShowContinueError(state, "Check the rated input for temperatures, flow, and capacity for this unit.");
    1104            2 :         ShowContinueError(state, "The ratio of the capacity to the rated theoretical maximum must be less than unity.");
    1105            2 :         ShowContinueError(state,
    1106              :                           "The most likely cause for this is probably either the capacity (whether autosized or hardwired) being too high, the "
    1107              :                           "rated flow being too low, rated temperatures being too close to each other, or all of those reasons.");
    1108            2 :         ShowContinueError(state,
    1109              :                           "Compare the rated capacity in your input to the product of the rated mass flow rate, Cp of water, and the difference "
    1110              :                           "between the rated temperatures.");
    1111            2 :         ShowContinueError(
    1112              :             state, "If the rated capacity is higher than this product, then the cooling panel would violate the Second Law of Thermodynamics.");
    1113            1 :         this->UA = 1.0;
    1114            1 :         return false;
    1115              :     }
    1116              : 
    1117            3 :     this->UA = -MDotXCp * log(1.0 - RatCapToTheoMax);
    1118            3 :     if (this->UA <= 0.0) {
    1119            0 :         ShowSevereError(state,
    1120            0 :                         format("SizeCoolingPanelUA: Unit=[{},{}] has a zero or negative calculated UA value.", cCMO_CoolingPanel_Simple, this->Name));
    1121            0 :         ShowContinueError(state,
    1122              :                           "This is not allowed.  Please check the rated input parameters for this device to ensure that the values are correct.");
    1123            0 :         return false;
    1124              :     }
    1125              : 
    1126            3 :     return true;
    1127              : }
    1128              : 
    1129            0 : void CoolingPanelParams::CalcCoolingPanel(EnergyPlusData &state, int const CoolingPanelNum)
    1130              : {
    1131              :     // SUBROUTINE INFORMATION:
    1132              :     //       AUTHOR         Rick Strand
    1133              :     //       DATE WRITTEN   Sept 2014
    1134              : 
    1135              :     // PURPOSE OF THIS SUBROUTINE:
    1136              :     // This subroutine calculates both the convective and radiant heat transfer rate
    1137              :     // for the simple cooling panel.  The process used here was derived from the hot
    1138              :     // water baseboard radiant/convective heater and adapted for cooling.
    1139              : 
    1140              :     // REFERENCES:
    1141              :     // Existing code for hot water baseboard models (radiant-convective variety)
    1142              :     // Incropera and DeWitt, Fundamentals of Heat and Mass Transfer
    1143              : 
    1144              :     // SUBROUTINE PARAMETER DEFINITIONS:
    1145            0 :     Real64 constexpr MinFrac(0.0005); // Minimum fraction that delivers radiant heats to surfaces
    1146            0 :     int constexpr Maxiter(20);        // Maximum number of iterations to achieve tolerance
    1147            0 :     Real64 constexpr IterTol(0.005);  // Tolerance of 0.5%
    1148              :     static constexpr std::string_view RoutineName("CalcCoolingPanel");
    1149              : 
    1150              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1151              :     Real64 RadHeat;
    1152              :     Real64 CoolingPanelCool;
    1153              :     Real64 waterMassFlowRate;
    1154              :     Real64 CapacitanceWater;
    1155              :     Real64 NTU;
    1156              :     Real64 Effectiveness;
    1157              :     Real64 Cp;
    1158              :     Real64 MCpEpsAct;
    1159              :     Real64 MCpEpsLow;
    1160              :     Real64 MCpEpsHigh;
    1161              :     Real64 MdotLow;
    1162              :     Real64 MdotHigh;
    1163              :     Real64 FracGuess;
    1164              :     Real64 MdotGuess;
    1165              :     Real64 MCpEpsGuess;
    1166              :     Real64 ControlTemp;
    1167              :     Real64 SetPointTemp;
    1168              :     Real64 OffTempCool;
    1169              :     Real64 FullOnTempCool;
    1170              :     Real64 MassFlowFrac;
    1171              :     Real64 LoadMet;
    1172              :     bool CoolingPanelOn;
    1173              :     Real64 waterOutletTemp;
    1174              : 
    1175            0 :     int ZoneNum = this->ZonePtr;
    1176            0 :     Real64 QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToCoolSP;
    1177            0 :     Real64 waterInletTemp = this->WaterInletTemp;
    1178            0 :     Real64 waterMassFlowRateMax = this->WaterMassFlowRateMax;
    1179            0 :     Real64 Xr = this->FracRadiant;
    1180              : 
    1181            0 :     CoolingPanelOn = this->availSched->getCurrentVal() > 0;
    1182              : 
    1183              :     // Calculate the "zone" temperature for determining the output of the cooling panel
    1184            0 :     auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
    1185            0 :     Real64 Tzone = Xr * thisZoneHB.MRT + ((1.0 - Xr) * thisZoneHB.MAT);
    1186              : 
    1187              :     // Logical controls: if the WaterInletTemperature is higher than Tzone, do not run the panel
    1188            0 :     if (waterInletTemp >= Tzone) CoolingPanelOn = false;
    1189              : 
    1190              :     // Condensation Controls based on dewpoint temperature of the zone.
    1191              :     // The assumption here is that condensation might take place if the inlet water temperature
    1192              :     // is below the dewpoint temperature of the space.  This assumption is made because we are
    1193              :     // probably dealing with a metal panel and the surface temperature of the panel will be very
    1194              :     // close to the inlet water temperature in certain places.  Thus, if the water inlet temperature
    1195              :     // is below the dewpoint temperature, then we might have condensation.  We need to deal with this
    1196              :     // possibility based on the user selected method.  The good news here is that we don't have to
    1197              :     // iterate like in the low temperature radiant systems because the inlet water condition is known
    1198              :     // not calculated.  So, we can deal with this upfront rather than after calculation and then more
    1199              :     // iteration.
    1200              :     Real64 DewPointTemp =
    1201            0 :         Psychrometrics::PsyTdpFnWPb(state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).airHumRat, state.dataEnvrn->OutBaroPress);
    1202              : 
    1203            0 :     if (waterInletTemp < (DewPointTemp + this->CondDewPtDeltaT) && (CoolingPanelOn)) {
    1204              : 
    1205              :         // Condensation is possible so invoke the three possible ways of handling this based on the user's choice...
    1206              : 
    1207            0 :         if (this->CondCtrlType == CondCtrl::NONE) {
    1208              :             // Condensation control is "off" which means don't do anything, simply let it run and ignore condensation
    1209            0 :         } else if (this->CondCtrlType == CondCtrl::SIMPLEOFF) {
    1210              :             // For "simple off", simply turn the simple cooling panel off to avoid condensation
    1211            0 :             waterMassFlowRate = 0.0;
    1212            0 :             CoolingPanelOn = false;
    1213              :             // Produce a warning message so that user knows the system was shut-off due to potential for condensation
    1214            0 :             if (!state.dataGlobal->WarmupFlag) {
    1215            0 :                 if (this->CondErrIndex == 0) { // allow errors up to number of radiant systems
    1216            0 :                     ShowWarningMessage(state,
    1217            0 :                                        format("{} [{}] inlet water temperature below dew-point temperature--potential for condensation exists",
    1218              :                                               cCMO_CoolingPanel_Simple,
    1219            0 :                                               this->Name));
    1220            0 :                     ShowContinueError(state, "Flow to the simple cooling panel will be shut-off to avoid condensation");
    1221            0 :                     ShowContinueError(state, format("Water inlet temperature = {:.2R}", waterInletTemp));
    1222            0 :                     ShowContinueError(state, format("Zone dew-point temperature + safety delta T= {:.2R}", DewPointTemp + this->CondDewPtDeltaT));
    1223            0 :                     ShowContinueErrorTimeStamp(state, "");
    1224            0 :                     ShowContinueError(state,
    1225            0 :                                       format("Note that a {:.4R} C safety was chosen in the input for the shut-off criteria", this->CondDewPtDeltaT));
    1226              :                 }
    1227            0 :                 ShowRecurringWarningErrorAtEnd(state,
    1228            0 :                                                cCMO_CoolingPanel_Simple + " [" + this->Name + "] condensation shut-off occurrence continues.",
    1229            0 :                                                this->CondErrIndex,
    1230              :                                                DewPointTemp,
    1231              :                                                DewPointTemp,
    1232              :                                                _,
    1233              :                                                "C",
    1234              :                                                "C");
    1235              :             }
    1236              : 
    1237            0 :         } else if (this->CondCtrlType == CondCtrl::VARIEDOFF) {
    1238              :             // Varied off is the most complex because it tries to run by reducing the inlet temperature
    1239              :             // As a result of this, there is some bypass/recirculation that has to take place.
    1240              :             // We might not have enough flow rate to meet whatever load we have, but at least
    1241              :             // the system is still running at some partial load and avoiding condensation.
    1242            0 :             waterInletTemp = DewPointTemp + this->CondDewPtDeltaT;
    1243              :         }
    1244              :     }
    1245              : 
    1246              :     // The next IF block is to find the mass flow rate based on what type of control the user has requested.  Load based controls
    1247              :     // vary the flow to meet the zone load calculated by the user-defined thermostat.  Temperature based controls vary the flow
    1248              :     // based on a comparison between the control temperature and the setpoint schedule and throttling range.
    1249              : 
    1250            0 :     if ((this->controlType == ClgPanelCtrlType::ZoneTotalLoad) || (this->controlType == ClgPanelCtrlType::ZoneConvectiveLoad)) {
    1251              : 
    1252            0 :         if (QZnReq < -HVAC::SmallLoad && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) && (CoolingPanelOn)) {
    1253              : 
    1254            0 :             Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, waterInletTemp, RoutineName);
    1255              : 
    1256              :             // Find the actual load: this parameter modifies what the response of the system should be.  For total load control, the system tries
    1257              :             // to meet the QZnReq.  For convective load control, the convective output of the device equals QZnReq which means that the load on
    1258              :             // the panel is higher as is its output.  Total load control will miss the setpoint temperature but will likely get there with time.
    1259              :             // Convective load control will hit the setpoint short term better but will result in overcooling in the long run probably.
    1260            0 :             if (this->controlType == ClgPanelCtrlType::ZoneConvectiveLoad) {
    1261            0 :                 QZnReq = QZnReq / this->FracConvect;
    1262              :             }
    1263              : 
    1264              :             // Now for a small amount of iteration.  Try to find the value of mass flow rate that will come the closest to giving
    1265              :             // the proper value for MCpEpsAct.  Limit iterations to avoid too much time wasting.
    1266            0 :             MCpEpsAct = QZnReq / (waterInletTemp - Tzone);
    1267            0 :             MCpEpsLow = 0.0;
    1268            0 :             MdotLow = 0.0;
    1269            0 :             MCpEpsHigh = waterMassFlowRateMax * Cp * (1.0 - exp(-this->UA / (waterMassFlowRateMax * Cp)));
    1270            0 :             MdotHigh = waterMassFlowRateMax;
    1271            0 :             if (MCpEpsAct <= MCpEpsLow) {
    1272            0 :                 MCpEpsAct = MCpEpsLow;
    1273            0 :                 waterMassFlowRate = 0.0;
    1274            0 :                 state.dataLoopNodes->Node(this->WaterInletNode).MassFlowRate = 0.0;
    1275            0 :                 CoolingPanelOn = false;
    1276            0 :             } else if (MCpEpsAct >= MCpEpsHigh) {
    1277            0 :                 MCpEpsAct = MCpEpsHigh;
    1278            0 :                 waterMassFlowRate = waterMassFlowRateMax;
    1279            0 :                 state.dataLoopNodes->Node(this->WaterInletNode).MassFlowRate = waterMassFlowRateMax;
    1280              :             } else {
    1281            0 :                 for (int iter = 1; iter <= Maxiter; ++iter) {
    1282            0 :                     FracGuess = (MCpEpsAct - MCpEpsLow) / (MCpEpsHigh - MCpEpsLow);
    1283            0 :                     MdotGuess = MdotHigh * FracGuess;
    1284            0 :                     MCpEpsGuess = MdotGuess * Cp * (1.0 - exp(-this->UA / (MdotGuess * Cp)));
    1285            0 :                     if (MCpEpsGuess <= MCpEpsAct) {
    1286            0 :                         MCpEpsLow = MCpEpsGuess;
    1287            0 :                         MdotLow = MdotGuess;
    1288              :                     } else { // MCpEpsGuess > MCpEpsAct
    1289            0 :                         MCpEpsHigh = MCpEpsGuess;
    1290            0 :                         MdotHigh = MdotGuess;
    1291              :                     }
    1292            0 :                     if (((MCpEpsAct - MCpEpsGuess) / MCpEpsAct) <= IterTol) {
    1293            0 :                         waterMassFlowRate = MdotGuess;
    1294            0 :                         state.dataLoopNodes->Node(this->WaterInletNode).MassFlowRate = waterMassFlowRate;
    1295            0 :                         break;
    1296              :                     }
    1297              :                 }
    1298              :             }
    1299              : 
    1300              :         } else {
    1301            0 :             CoolingPanelOn = false;
    1302              :         }
    1303              : 
    1304            0 :     } else { // temperature control rather than zone load control
    1305              : 
    1306            0 :         if (CoolingPanelOn) {
    1307              : 
    1308            0 :             ControlTemp = this->getCoolingPanelControlTemp(state, ZoneNum);
    1309              : 
    1310            0 :             SetPointTemp = this->coldSetptSched->getCurrentVal();
    1311            0 :             OffTempCool = SetPointTemp - 0.5 * this->ColdThrottlRange;
    1312            0 :             FullOnTempCool = SetPointTemp + 0.5 * this->ColdThrottlRange;
    1313              : 
    1314            0 :             if (ControlTemp <= OffTempCool) {
    1315            0 :                 MassFlowFrac = 0.0;
    1316            0 :                 CoolingPanelOn = false;
    1317            0 :             } else if (ControlTemp >= FullOnTempCool) {
    1318            0 :                 MassFlowFrac = 1.0;
    1319              :             } else {
    1320            0 :                 MassFlowFrac = (ControlTemp - OffTempCool) / this->ColdThrottlRange;
    1321            0 :                 if (MassFlowFrac < MinFrac) MassFlowFrac = MinFrac;
    1322              :             }
    1323              : 
    1324            0 :             waterMassFlowRate = MassFlowFrac * waterMassFlowRateMax;
    1325              :         }
    1326              :     }
    1327              : 
    1328            0 :     if (CoolingPanelOn) {
    1329            0 :         PlantUtilities::SetComponentFlowRate(state, waterMassFlowRate, this->WaterInletNode, this->WaterOutletNode, this->plantLoc);
    1330            0 :         if (waterMassFlowRate <= 0.0) CoolingPanelOn = false;
    1331              :     }
    1332              : 
    1333            0 :     if (CoolingPanelOn) {
    1334              :         // Now simulate the system...
    1335            0 :         Cp = this->plantLoc.loop->glycol->getSpecificHeat(state, waterInletTemp, RoutineName);
    1336            0 :         Effectiveness = 1.0 - exp(-this->UA / (waterMassFlowRate * Cp));
    1337            0 :         if (Effectiveness <= 0.0) {
    1338            0 :             Effectiveness = 0.0;
    1339            0 :         } else if (Effectiveness >= 1.0) {
    1340            0 :             Effectiveness = 1.0;
    1341              :         }
    1342            0 :         CoolingPanelCool = (Effectiveness)*waterMassFlowRate * Cp * (waterInletTemp - Tzone);
    1343            0 :         waterOutletTemp = this->WaterInletTemp - (CoolingPanelCool / (waterMassFlowRate * Cp));
    1344            0 :         RadHeat = CoolingPanelCool * this->FracRadiant;
    1345            0 :         state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).CoolingPanelSource = RadHeat;
    1346              : 
    1347            0 :         if (this->FracRadiant <= MinFrac) {
    1348            0 :             LoadMet = CoolingPanelCool;
    1349              :         } else {
    1350              : 
    1351              :             // Now, distribute the radiant energy of all systems to the appropriate surfaces, to people, and the air
    1352            0 :             DistributeCoolingPanelRadGains(state);
    1353              :             // Now "simulate" the system by recalculating the heat balances
    1354            0 :             HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
    1355              : 
    1356            0 :             HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
    1357              : 
    1358              :             // Here an assumption is made regarding radiant heat transfer to people.
    1359              :             // While the radiant heat transfer to people array will be used by the thermal comfort
    1360              :             // routines, the energy transfer to people would get lost from the perspective
    1361              :             // of the heat balance.  So, to avoid this net loss of energy which clearly
    1362              :             // gets added to the zones, we must account for it somehow.  This assumption
    1363              :             // that all energy radiated to people is converted to convective energy is
    1364              :             // not very precise, but at least it conserves energy. The system impact to heat balance
    1365              :             // should include this.
    1366            0 :             LoadMet = (state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - this->ZeroCPSourceSumHATsurf) + (CoolingPanelCool * this->FracConvect) +
    1367            0 :                       (RadHeat * this->FracDistribPerson);
    1368              :         }
    1369            0 :         this->WaterOutletEnthalpy = this->WaterInletEnthalpy - CoolingPanelCool / waterMassFlowRate;
    1370              : 
    1371              :     } else { // cooling panel off
    1372            0 :         CapacitanceWater = 0.0;
    1373            0 :         NTU = 0.0;
    1374            0 :         Effectiveness = 0.0;
    1375            0 :         waterOutletTemp = waterInletTemp;
    1376            0 :         CoolingPanelCool = 0.0;
    1377            0 :         LoadMet = 0.0;
    1378            0 :         RadHeat = 0.0;
    1379            0 :         waterMassFlowRate = 0.0;
    1380            0 :         this->CoolingPanelSource = 0.0;
    1381            0 :         this->WaterOutletEnthalpy = this->WaterInletEnthalpy;
    1382              :     }
    1383              : 
    1384            0 :     this->WaterOutletTemp = waterOutletTemp;
    1385            0 :     this->WaterMassFlowRate = waterMassFlowRate;
    1386            0 :     this->TotPower = LoadMet;
    1387            0 :     this->Power = CoolingPanelCool;
    1388            0 :     this->ConvPower = CoolingPanelCool - RadHeat;
    1389            0 :     this->RadPower = RadHeat;
    1390            0 : }
    1391              : 
    1392            5 : Real64 CoolingPanelParams::getCoolingPanelControlTemp(EnergyPlusData &state, int const ZoneNum) const
    1393              : {
    1394              : 
    1395              :     // SUBROUTINE INFORMATION:
    1396              :     //       AUTHOR         Rick Strand
    1397              :     //       DATE WRITTEN   July 2016
    1398              : 
    1399              :     // METHODOLOGY EMPLOYED:
    1400              :     // This subroutine sets the control temperature for the simple cooling panel.
    1401              : 
    1402              :     // Using/Aliasing
    1403              : 
    1404            5 :     switch (this->controlType) {
    1405            1 :     case ClgPanelCtrlType::MAT: {
    1406            1 :         return state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
    1407              :     } break;
    1408            1 :     case ClgPanelCtrlType::MRT: {
    1409            1 :         return state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MRT;
    1410              :     } break;
    1411            1 :     case ClgPanelCtrlType::Operative: {
    1412            1 :         return 0.5 * (state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT +
    1413            1 :                       state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MRT);
    1414              :     } break;
    1415            1 :     case ClgPanelCtrlType::ODB: {
    1416            1 :         return state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp;
    1417              :     } break;
    1418            1 :     case ClgPanelCtrlType::OWB: {
    1419            1 :         return state.dataHeatBal->Zone(ZoneNum).OutWetBulbTemp;
    1420              :     } break;
    1421            0 :     default: { // Should never get here
    1422            0 :         assert(false);
    1423              :         return -99990; // Compiler wants a return value for every path, so give an invalid value
    1424              :     } break;
    1425              :     }
    1426              : }
    1427              : 
    1428            0 : void UpdateCoolingPanel(EnergyPlusData &state, int const CoolingPanelNum)
    1429              : {
    1430              : 
    1431              :     // SUBROUTINE INFORMATION:
    1432              :     //       AUTHOR         Rick Strand
    1433              :     //       DATE WRITTEN   Sept 2014
    1434              :     //                      February 2001
    1435              :     //       MODIFIED       Aug 2007 Daeho Kang (Add the update of radiant source)
    1436              : 
    1437              :     // REFERENCES:
    1438              :     // Existing code for hot water baseboard models (radiant-convective variety)
    1439              : 
    1440              :     // Using/Aliasing
    1441            0 :     Real64 SysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
    1442            0 :     Real64 TimeStepSys = state.dataHVACGlobal->TimeStepSys;
    1443            0 :     auto &thisCP(state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum));
    1444              : 
    1445              :     // First, update the running average if necessary...
    1446            0 :     if (thisCP.LastSysTimeElapsed == SysTimeElapsed) {
    1447            0 :         thisCP.CoolingPanelSrcAvg -= thisCP.LastCoolingPanelSrc * thisCP.LastTimeStepSys / state.dataGlobal->TimeStepZone;
    1448              :     }
    1449              :     // Update the running average and the "last" values with the current values of the appropriate variables
    1450            0 :     thisCP.CoolingPanelSrcAvg += thisCP.CoolingPanelSource * TimeStepSys / state.dataGlobal->TimeStepZone;
    1451              : 
    1452            0 :     thisCP.LastCoolingPanelSrc = thisCP.CoolingPanelSource;
    1453            0 :     thisCP.LastSysTimeElapsed = SysTimeElapsed;
    1454            0 :     thisCP.LastTimeStepSys = TimeStepSys;
    1455              : 
    1456            0 :     int WaterInletNode = thisCP.WaterInletNode;
    1457            0 :     int WaterOutletNode = thisCP.WaterOutletNode;
    1458              : 
    1459            0 :     auto &ThisInNode(state.dataLoopNodes->Node(WaterInletNode));
    1460            0 :     auto &ThisOutNode(state.dataLoopNodes->Node(WaterOutletNode));
    1461              : 
    1462              :     // Set the outlet water nodes for the panel
    1463            0 :     PlantUtilities::SafeCopyPlantNode(state, WaterInletNode, WaterOutletNode);
    1464            0 :     ThisOutNode.Temp = thisCP.WaterOutletTemp;
    1465            0 :     ThisOutNode.Enthalpy = thisCP.WaterOutletEnthalpy;
    1466            0 :     ThisInNode.MassFlowRate = thisCP.WaterMassFlowRate;
    1467            0 :     ThisOutNode.MassFlowRate = thisCP.WaterMassFlowRate;
    1468            0 :     ThisInNode.MassFlowRateMax = thisCP.WaterMassFlowRateMax;
    1469            0 :     ThisOutNode.MassFlowRateMax = thisCP.WaterMassFlowRateMax;
    1470            0 : }
    1471              : 
    1472       249945 : void UpdateCoolingPanelSourceValAvg(EnergyPlusData &state,
    1473              :                                     bool &CoolingPanelSysOn) // .TRUE. if the radiant system has run this zone time step
    1474              : {
    1475              : 
    1476              :     // SUBROUTINE INFORMATION:
    1477              :     //       AUTHOR         Rick Strand
    1478              :     //       DATE WRITTEN   Sept 2014
    1479              : 
    1480              :     // PURPOSE OF THIS SUBROUTINE:
    1481              :     // To transfer the average value of the heat source over the entire
    1482              :     // zone time step back to the heat balance routines so that the heat
    1483              :     // balance algorithms can simulate one last time with the average source
    1484              :     // to maintain some reasonable amount of continuity and energy balance
    1485              :     // in the temperature and flux histories.
    1486              : 
    1487              :     // METHODOLOGY EMPLOYED:
    1488              :     // All of the record keeping for the average term is done in the Update
    1489              :     // routine so the only other thing that this subroutine does is check to
    1490              :     // see if the system was even on.  If any average term is non-zero, then
    1491              :     // one or more of the radiant systems was running.
    1492              : 
    1493              :     // REFERENCES:
    1494              :     // Existing code for hot water baseboard models (radiant-convective variety)
    1495              : 
    1496       249945 :     CoolingPanelSysOn = false;
    1497              : 
    1498              :     // If this was never allocated, then there are no radiant systems in this input file (just RETURN)
    1499       249945 :     if (!allocated(state.dataChilledCeilingPanelSimple->CoolingPanel)) return;
    1500              : 
    1501              :     // If it was allocated, then we have to check to see if this was running at all...
    1502            0 :     for (int CoolingPanelNum = 1; CoolingPanelNum <= (int)state.dataChilledCeilingPanelSimple->CoolingPanel.size(); ++CoolingPanelNum) {
    1503            0 :         if (state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).CoolingPanelSrcAvg != 0.0) {
    1504            0 :             CoolingPanelSysOn = true;
    1505            0 :             break; // DO loop
    1506              :         }
    1507              :     }
    1508              : 
    1509            0 :     for (auto &cp : state.dataChilledCeilingPanelSimple->CoolingPanel) {
    1510            0 :         cp.CoolingPanelSource = cp.CoolingPanelSrcAvg;
    1511              :     }
    1512              : 
    1513            0 :     DistributeCoolingPanelRadGains(state); // CoolingPanelRadSource has been modified so we need to redistribute gains
    1514              : }
    1515              : 
    1516            0 : void DistributeCoolingPanelRadGains(EnergyPlusData &state)
    1517              : {
    1518              : 
    1519              :     // SUBROUTINE INFORMATION:
    1520              :     //       AUTHOR         Rick Strand
    1521              :     //       DATE WRITTEN   Sept 2014
    1522              : 
    1523              :     // PURPOSE OF THIS SUBROUTINE:
    1524              :     // To distribute the gains from the hot water baseboard heater
    1525              :     // as specified in the user input file.  This includes distribution
    1526              :     // of long wavelength radiant gains to surfaces and "people."
    1527              : 
    1528              :     // METHODOLOGY EMPLOYED:
    1529              :     // We must cycle through all of the radiant systems because each
    1530              :     // surface could feel the effect of more than one radiant system.
    1531              :     // Note that the energy radiated to people is assumed to affect them
    1532              :     // but them it is assumed to be convected to the air.
    1533              : 
    1534              :     // REFERENCES:
    1535              :     // Existing code for hot water baseboard models (radiant-convective variety)
    1536              : 
    1537              :     // SUBROUTINE PARAMETER DEFINITIONS:
    1538            0 :     Real64 constexpr SmallestArea(0.001); // Smallest area in meters squared (to avoid a divide by zero)
    1539              : 
    1540              :     // Initialize arrays
    1541            0 :     for (auto &thisCP : state.dataChilledCeilingPanelSimple->CoolingPanel) {
    1542            0 :         for (int radSurfNum = 1; radSurfNum <= thisCP.TotSurfToDistrib; ++radSurfNum) {
    1543            0 :             int surfNum = thisCP.SurfacePtr(radSurfNum);
    1544            0 :             state.dataHeatBalFanSys->surfQRadFromHVAC(surfNum).CoolingPanel = 0.0;
    1545              :         }
    1546              :     }
    1547            0 :     state.dataHeatBalFanSys->ZoneQCoolingPanelToPerson = 0.0;
    1548              : 
    1549            0 :     for (auto &thisCP : state.dataChilledCeilingPanelSimple->CoolingPanel) {
    1550            0 :         int ZoneNum = thisCP.ZonePtr;
    1551            0 :         if (ZoneNum <= 0) continue;
    1552            0 :         state.dataHeatBalFanSys->ZoneQCoolingPanelToPerson(ZoneNum) += thisCP.CoolingPanelSource * thisCP.FracDistribPerson;
    1553              : 
    1554            0 :         for (int RadSurfNum = 1; RadSurfNum <= thisCP.TotSurfToDistrib; ++RadSurfNum) {
    1555            0 :             int SurfNum = thisCP.SurfacePtr(RadSurfNum);
    1556            0 :             auto &ThisSurf(state.dataSurface->Surface(SurfNum));
    1557            0 :             if (ThisSurf.Area > SmallestArea) {
    1558            0 :                 Real64 ThisSurfIntensity = (thisCP.CoolingPanelSource * thisCP.FracDistribToSurf(RadSurfNum) / ThisSurf.Area);
    1559            0 :                 state.dataHeatBalFanSys->surfQRadFromHVAC(SurfNum).CoolingPanel += ThisSurfIntensity;
    1560              :                 // CR 8074, trap for excessive intensity (throws off surface balance )
    1561            0 :                 if (ThisSurfIntensity > DataHeatBalFanSys::MaxRadHeatFlux) {
    1562            0 :                     ShowSevereError(state, "DistributeCoolingPanelRadGains:  excessive thermal radiation heat flux intensity detected");
    1563            0 :                     ShowContinueError(state, format("Surface = {}", ThisSurf.Name));
    1564            0 :                     ShowContinueError(state, format("Surface area = {:.3R} [m2]", ThisSurf.Area));
    1565            0 :                     ShowContinueError(state, format("Occurs in {} = {}", cCMO_CoolingPanel_Simple, thisCP.Name));
    1566            0 :                     ShowContinueError(state, format("Radiation intensity = {:.2R} [W/m2]", ThisSurfIntensity));
    1567            0 :                     ShowContinueError(state, format("Assign a larger surface area or more surfaces in {}", cCMO_CoolingPanel_Simple));
    1568            0 :                     ShowFatalError(state, "DistributeCoolingPanelRadGains:  excessive thermal radiation heat flux intensity detected");
    1569              :                 }
    1570              :             } else {
    1571            0 :                 ShowSevereError(state, "DistributeCoolingPanelRadGains:  surface not large enough to receive thermal radiation heat flux");
    1572            0 :                 ShowContinueError(state, format("Surface = {}", ThisSurf.Name));
    1573            0 :                 ShowContinueError(state, format("Surface area = {:.3R} [m2]", ThisSurf.Area));
    1574            0 :                 ShowContinueError(state, format("Occurs in {} = {}", cCMO_CoolingPanel_Simple, thisCP.Name));
    1575            0 :                 ShowContinueError(state, format("Assign a larger surface area or more surfaces in {}", cCMO_CoolingPanel_Simple));
    1576            0 :                 ShowFatalError(state, "DistributeCoolingPanelRadGains:  surface not large enough to receive thermal radiation heat flux");
    1577              :             }
    1578              :         }
    1579              :     }
    1580            0 : }
    1581              : 
    1582            1 : void CoolingPanelParams::ReportCoolingPanel(EnergyPlusData &state)
    1583              : {
    1584              : 
    1585              :     // SUBROUTINE INFORMATION:
    1586              :     //       AUTHOR         Rick Strand
    1587              :     //       DATE WRITTEN   Aug 2014
    1588              : 
    1589              :     // REFERENCES:
    1590              :     // Existing code for hot water baseboard models (radiant-convective variety)
    1591              : 
    1592            1 :     Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    1593              : 
    1594              :     // All of the power numbers are negative for cooling.  This is because they will have a negative
    1595              :     // or cooling impact on the surfaces/zones.  However, the output variables are noted as cooling.
    1596              :     // So, their sign should be positive if actually cooling and we need to reverse the sign here.
    1597              :     // This should not have an impact on any of the internal variables or the heat balances because
    1598              :     // those use other variables.
    1599            1 :     this->TotPower = -this->TotPower;
    1600            1 :     this->Power = -this->Power;
    1601            1 :     this->ConvPower = -this->ConvPower;
    1602            1 :     this->RadPower = -this->RadPower;
    1603              : 
    1604            1 :     this->TotEnergy = this->TotPower * TimeStepSysSec;
    1605            1 :     this->Energy = this->Power * TimeStepSysSec;
    1606            1 :     this->ConvEnergy = this->ConvPower * TimeStepSysSec;
    1607            1 :     this->RadEnergy = this->RadPower * TimeStepSysSec;
    1608            1 : }
    1609              : 
    1610              : } // namespace EnergyPlus::CoolingPanelSimple
        

Generated by: LCOV version 2.0-1