LCOV - code coverage report
Current view: top level - EnergyPlus - TranspiredCollector.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 37.7 % 896 338
Test Date: 2025-05-22 16:09:37 Functions: 30.8 % 13 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 <cassert>
      50              : #include <cmath>
      51              : 
      52              : // ObjexxFCL Headers
      53              : #include <ObjexxFCL/Array.functions.hh>
      54              : #include <ObjexxFCL/member.functions.hh>
      55              : 
      56              : // EnergyPlus Headers
      57              : #include <EnergyPlus/BranchNodeConnections.hh>
      58              : #include <EnergyPlus/Construction.hh>
      59              : #include <EnergyPlus/ConvectionCoefficients.hh>
      60              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      61              : #include <EnergyPlus/DataEnvironment.hh>
      62              : #include <EnergyPlus/DataHVACGlobals.hh>
      63              : #include <EnergyPlus/DataHeatBalSurface.hh>
      64              : #include <EnergyPlus/DataHeatBalance.hh>
      65              : #include <EnergyPlus/DataIPShortCuts.hh>
      66              : #include <EnergyPlus/DataLoopNode.hh>
      67              : #include <EnergyPlus/DataSurfaces.hh>
      68              : #include <EnergyPlus/EMSManager.hh>
      69              : #include <EnergyPlus/General.hh>
      70              : #include <EnergyPlus/GeneralRoutines.hh>
      71              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      72              : #include <EnergyPlus/Material.hh>
      73              : #include <EnergyPlus/NodeInputManager.hh>
      74              : #include <EnergyPlus/OutputProcessor.hh>
      75              : #include <EnergyPlus/Psychrometrics.hh>
      76              : #include <EnergyPlus/ScheduleManager.hh>
      77              : #include <EnergyPlus/SolarCollectors.hh>
      78              : #include <EnergyPlus/TranspiredCollector.hh>
      79              : #include <EnergyPlus/UtilityRoutines.hh>
      80              : 
      81              : namespace EnergyPlus {
      82              : 
      83              : namespace TranspiredCollector {
      84              : 
      85              :     // Module containing routines and data dealing with the Transpired Collectors
      86              : 
      87              :     // MODULE INFORMATION:
      88              :     //       AUTHOR         B.T. Griffith
      89              :     //       DATE WRITTEN   November 2004
      90              :     //       MODIFIED       na
      91              :     //       RE-ENGINEERED  na
      92              : 
      93              :     // PURPOSE OF THIS MODULE:
      94              :     // Encapsulates data and routines for simulating unglazed transpired solar collectors (UTSC)
      95              :     //   as a component on the HVAC air system.
      96              : 
      97              :     // METHODOLOGY EMPLOYED:
      98              :     // Two modes, passive and active.  Active is when air is purposely drawn through collector.
      99              :     // Passive is when air exchanges are driven by Natural Ventilation rather than outside air system
     100              : 
     101              :     // REFERENCES:
     102              :     // Heat Exchange effectiveness relations:
     103              :     // Kutscher, C.F. 1994. Heat exchange effectiveness and pressure drop for air flow through perforated plates
     104              :     //     with and without crosswind. Journal of Heat Transfer. May 1994, Vol. 116, p. 391.
     105              :     //     American Society of Mechanical Engineers.
     106              :     // Van Decker, G.W.E., K.G.T. Hollands, and A.P. Brunger. 2001. Heat-exchange relations for unglazed transpired
     107              :     //     solar collectors with circular holes on a square of triangular pitch. Solar Energy. Vol. 71, No. 1. pp 33-45, 2001.
     108              :     // .
     109              : 
     110              :     // OTHER NOTES:
     111              :     // EnergyPlus implementation is unique and adds new modeling not described in Literature.
     112              :     //   See EngineeringReference for details
     113              : 
     114              :     // Using/Aliasing
     115              :     using DataVectorTypes::Vector;
     116              : 
     117              :     int constexpr Layout_Square = 1;
     118              :     int constexpr Layout_Triangle = 2;
     119              :     int constexpr Correlation_Kutscher1994 = 1;
     120              :     int constexpr Correlation_VanDeckerHollandsBrunger2001 = 2;
     121              : 
     122            0 :     void SimTranspiredCollector(EnergyPlusData &state,
     123              :                                 std::string_view CompName, // component name
     124              :                                 int &CompIndex             // component index (to reduce string compares during simulation)
     125              :     )
     126              :     {
     127              : 
     128              :         // SUBROUTINE INFORMATION:
     129              :         //       AUTHOR         B.T. Griffith
     130              :         //       DATE WRITTEN   November 2004
     131              :         //       MODIFIED       na
     132              :         //       RE-ENGINEERED  na
     133              : 
     134              :         // PURPOSE OF THIS SUBROUTINE:
     135              :         // Manage simulation of Transpired Collectors
     136              : 
     137              :         // METHODOLOGY EMPLOYED:
     138              :         // Setup to avoid string comparisons after first call
     139              : 
     140              :         // Using/Aliasing
     141              :         using HVAC::TempControlTol;
     142              : 
     143              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     144              : 
     145            0 :         int UTSCNum(0); // local number index for UTSC
     146              : 
     147            0 :         if (state.dataTranspiredCollector->GetInputFlag) {
     148            0 :             GetTranspiredCollectorInput(state);
     149            0 :             state.dataTranspiredCollector->GetInputFlag = false;
     150              :         }
     151              : 
     152              :         // Find the correct transpired collector with the Component name and/or index
     153            0 :         if (CompIndex == 0) {
     154            0 :             UTSCNum = Util::FindItemInList(CompName, state.dataTranspiredCollector->UTSC);
     155            0 :             if (UTSCNum == 0) {
     156            0 :                 ShowFatalError(state, format("Transpired Collector not found={}", CompName));
     157              :             }
     158            0 :             CompIndex = UTSCNum;
     159              :         } else {
     160            0 :             UTSCNum = CompIndex;
     161            0 :             if (UTSCNum > state.dataTranspiredCollector->NumUTSC || UTSCNum < 1) {
     162            0 :                 ShowFatalError(state,
     163            0 :                                format("SimTranspiredCollector: Invalid CompIndex passed={}, Number of Transpired Collectors={}, UTSC name={}",
     164              :                                       UTSCNum,
     165            0 :                                       state.dataTranspiredCollector->NumUTSC,
     166              :                                       CompName));
     167              :             }
     168            0 :             if (state.dataTranspiredCollector->CheckEquipName(UTSCNum)) {
     169            0 :                 if (CompName != state.dataTranspiredCollector->UTSC(UTSCNum).Name) {
     170            0 :                     ShowFatalError(state,
     171            0 :                                    format("SimTranspiredCollector: Invalid CompIndex passed={}, Transpired Collector name={}, stored Transpired "
     172              :                                           "Collector Name for that index={}",
     173              :                                           UTSCNum,
     174              :                                           CompName,
     175            0 :                                           state.dataTranspiredCollector->UTSC(UTSCNum).Name));
     176              :                 }
     177            0 :                 state.dataTranspiredCollector->CheckEquipName(UTSCNum) = false;
     178              :             }
     179              :         }
     180              : 
     181            0 :         InitTranspiredCollector(state, CompIndex);
     182              : 
     183              :         // Control point of deciding if transpired collector is active or not.
     184            0 :         auto &UTSC_CI = state.dataTranspiredCollector->UTSC(CompIndex);
     185            0 :         auto &InletNode = UTSC_CI.InletNode;
     186            0 :         auto &ControlNode = UTSC_CI.ControlNode;
     187            0 :         UTSC_CI.IsOn = false;
     188            0 :         if ((UTSC_CI.availSched->getCurrentVal() > 0.0) && (UTSC_CI.InletMDot > 0.0)) { // availability Schedule | OA system is setting mass flow
     189            0 :             bool ControlLTSet(false);
     190            0 :             bool ControlLTSchedule(false);
     191            0 :             bool ZoneLTSchedule(false);
     192            0 :             assert(equal_dimensions(InletNode, ControlNode));
     193            0 :             assert(equal_dimensions(InletNode, UTSC_CI.ZoneNode));
     194            0 :             for (int i = InletNode.l(), e = InletNode.u(); i <= e; ++i) {
     195            0 :                 if (state.dataLoopNodes->Node(InletNode(i)).Temp + TempControlTol < state.dataLoopNodes->Node(ControlNode(i)).TempSetPoint)
     196            0 :                     ControlLTSet = true;
     197            0 :                 if (state.dataLoopNodes->Node(InletNode(i)).Temp + TempControlTol < UTSC_CI.freeHeatSetPointSched->getCurrentVal())
     198            0 :                     ControlLTSchedule = true;
     199            0 :                 if (state.dataLoopNodes->Node(UTSC_CI.ZoneNode(i)).Temp + TempControlTol < UTSC_CI.freeHeatSetPointSched->getCurrentVal())
     200            0 :                     ZoneLTSchedule = true;
     201              :             }
     202            0 :             if (ControlLTSet || (ControlLTSchedule && ZoneLTSchedule))
     203            0 :                 UTSC_CI.IsOn = true; // heating required | free heating helpful | free heating helpful
     204              :         }
     205              : 
     206            0 :         if (state.dataTranspiredCollector->UTSC(UTSCNum).IsOn) {
     207            0 :             CalcActiveTranspiredCollector(state, UTSCNum);
     208              :         } else {
     209            0 :             CalcPassiveTranspiredCollector(state, UTSCNum);
     210              :         }
     211              : 
     212            0 :         UpdateTranspiredCollector(state, UTSCNum);
     213            0 :     }
     214              : 
     215            1 :     void GetTranspiredCollectorInput(EnergyPlusData &state)
     216              :     {
     217              : 
     218              :         // SUBROUTINE INFORMATION:
     219              :         //       AUTHOR         B.T. Griffith
     220              :         //       DATE WRITTEN   November 2004
     221              :         //       MODIFIED       na
     222              :         //       RE-ENGINEERED  na
     223              : 
     224              :         // PURPOSE OF THIS SUBROUTINE:
     225              :         //  Retrieve user input and set up data structure
     226              : 
     227              :         // METHODOLOGY EMPLOYED:
     228              :         // usual EnergyPlus input
     229              :         // Extensible UTSC object for underlying heat transfer surfaces and for multisystem
     230              : 
     231              :         static constexpr std::string_view routineName = "GetTranspiredCollectorInput";
     232              : 
     233              :         // Using/Aliasing
     234              :         using BranchNodeConnections::TestCompSet;
     235              :         using DataLoopNode::ObjectIsNotParent;
     236              :         using DataSurfaces::OtherSideCondModeledExt;
     237              :         using DataSurfaces::SurfaceData;
     238              :         using NodeInputManager::GetOnlySingleNode;
     239              : 
     240              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     241              : 
     242            1 :         Array1D_string Alphas; // Alpha items for extensible
     243              :         // Solar Collectors:Unglazed Transpired object
     244              :         int Item;                    // Item to be "gotten"
     245            1 :         Array1D<Real64> Numbers(11); // Numeric items for object
     246              :         int NumAlphas;               // Number of Alphas for each GetObjectItem call
     247              :         int NumNumbers;              // Number of Numbers for each GetObjectItem call
     248              :         int MaxNumAlphas;            // argument for call to GetObjectDefMaxArgs
     249              :         int MaxNumNumbers;           // argument for call to GetObjectDefMaxArgs
     250              :         int Dummy;                   // argument for call to GetObjectDefMaxArgs
     251              :         int IOStatus;                // Used in GetObjectItem
     252            1 :         bool ErrorsFound(false);     // Set to true if errors in input, fatal at end of routine
     253              :         int Found;
     254              :         int AlphaOffset; // local temp var
     255            1 :         std::string Roughness;
     256              :         int ThisSurf;         // do loop counter
     257              :         Real64 AvgAzimuth;    // temp for error checking
     258              :         Real64 AvgTilt;       // temp for error checking
     259              :         int SurfID;           // local surface "pointer"
     260              :         Real64 TiltRads;      // average tilt of collector in radians
     261              :         Real64 tempHdeltaNPL; // temporary variable for buoyancy length scale
     262            1 :         int NumUTSCSplitter(0);
     263            1 :         Array1D_string AlphasSplit; // Alpha items for extensible
     264              :         // Solar Collectors:Unglazed Transpired object
     265              :         int ItemSplit;                        // Item to be "gotten"
     266            1 :         Array1D<Real64> NumbersSplit(1);      // Numeric items for object
     267              :         int NumAlphasSplit;                   // Number of Alphas for each GetObjectItem call
     268              :         int NumNumbersSplit;                  // Number of Numbers for each GetObjectItem call
     269              :         int MaxNumAlphasSplit;                // argument for call to GetObjectDefMaxArgs
     270              :         int MaxNumNumbersSplit;               // argument for call to GetObjectDefMaxArgs
     271              :         int IOStatusSplit;                    // Used in GetObjectItem
     272              :         int NumOASys;                         // do loop counter
     273              :         int ACountBase;                       // counter for alhpasSplit
     274            1 :         Array1D_bool SplitterNameOK;          // check for correct association of
     275            1 :         std::string CurrentModuleObject;      // for ease in renaming.
     276            1 :         std::string CurrentModuleMultiObject; // for ease in renaming.
     277              : 
     278            1 :         CurrentModuleObject = "SolarCollector:UnglazedTranspired";
     279            1 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, Dummy, MaxNumAlphas, MaxNumNumbers);
     280              : 
     281            1 :         if (MaxNumNumbers != 11) {
     282            0 :             ShowSevereError(state,
     283            0 :                             format("GetTranspiredCollectorInput: {} Object Definition indicates not = 11 Number Objects, Number Indicated={}",
     284              :                                    CurrentModuleObject,
     285              :                                    MaxNumNumbers));
     286            0 :             ErrorsFound = true;
     287              :         }
     288            1 :         Alphas.allocate(MaxNumAlphas);
     289            1 :         Numbers = 0.0;
     290            1 :         Alphas = "";
     291              : 
     292            1 :         state.dataTranspiredCollector->NumUTSC = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     293            1 :         CurrentModuleMultiObject = "SolarCollector:UnglazedTranspired:Multisystem";
     294            1 :         NumUTSCSplitter = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleMultiObject);
     295              : 
     296            1 :         state.dataTranspiredCollector->UTSC.allocate(state.dataTranspiredCollector->NumUTSC);
     297            1 :         state.dataTranspiredCollector->CheckEquipName.dimension(state.dataTranspiredCollector->NumUTSC, true);
     298            1 :         SplitterNameOK.dimension(NumUTSCSplitter, false);
     299              : 
     300            2 :         for (Item = 1; Item <= state.dataTranspiredCollector->NumUTSC; ++Item) {
     301            2 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     302              :                                                                      CurrentModuleObject,
     303              :                                                                      Item,
     304              :                                                                      Alphas,
     305              :                                                                      NumAlphas,
     306              :                                                                      Numbers,
     307              :                                                                      NumNumbers,
     308              :                                                                      IOStatus,
     309            1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     310            1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     311            1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     312            1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     313              : 
     314            1 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     315              : 
     316              :             // first handle alphas
     317            1 :             state.dataTranspiredCollector->UTSC(Item).Name = Alphas(1);
     318              : 
     319              :             // now check for multisystem
     320            1 :             if (NumUTSCSplitter > 0) {
     321            0 :                 state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     322              :                     state, CurrentModuleMultiObject, Dummy, MaxNumAlphasSplit, MaxNumNumbersSplit);
     323              : 
     324            0 :                 if (MaxNumNumbersSplit != 0) {
     325            0 :                     ShowSevereError(state,
     326            0 :                                     format("GetTranspiredCollectorInput: {} Object Definition indicates not = 0 Number Objects, Number Indicated={}",
     327              :                                            CurrentModuleMultiObject,
     328              :                                            MaxNumNumbersSplit));
     329            0 :                     ErrorsFound = true;
     330              :                 }
     331            0 :                 if (!allocated(AlphasSplit)) AlphasSplit.allocate(MaxNumAlphasSplit);
     332            0 :                 NumbersSplit = 0.0;
     333            0 :                 AlphasSplit = "";
     334            0 :                 for (ItemSplit = 1; ItemSplit <= NumUTSCSplitter; ++ItemSplit) {
     335            0 :                     state.dataInputProcessing->inputProcessor->getObjectItem(
     336              :                         state, CurrentModuleMultiObject, ItemSplit, AlphasSplit, NumAlphasSplit, NumbersSplit, NumNumbersSplit, IOStatusSplit);
     337            0 :                     if (!(Util::SameString(AlphasSplit(1), Alphas(1)))) continue;
     338            0 :                     SplitterNameOK(ItemSplit) = true;
     339            0 :                     state.dataTranspiredCollector->UTSC(Item).NumOASysAttached = std::floor(NumAlphasSplit / 4.0);
     340            0 :                     if (mod((NumAlphasSplit), 4) != 1) {
     341            0 :                         ShowSevereError(state,
     342            0 :                                         format("GetTranspiredCollectorInput: {} Object Definition indicates not uniform quadtuples of nodes for {}",
     343              :                                                CurrentModuleMultiObject,
     344              :                                                AlphasSplit(1)));
     345            0 :                         ErrorsFound = true;
     346              :                     }
     347            0 :                     state.dataTranspiredCollector->UTSC(Item).InletNode.allocate(state.dataTranspiredCollector->UTSC(Item).NumOASysAttached);
     348            0 :                     state.dataTranspiredCollector->UTSC(Item).InletNode = 0;
     349            0 :                     state.dataTranspiredCollector->UTSC(Item).OutletNode.allocate(state.dataTranspiredCollector->UTSC(Item).NumOASysAttached);
     350            0 :                     state.dataTranspiredCollector->UTSC(Item).OutletNode = 0;
     351            0 :                     state.dataTranspiredCollector->UTSC(Item).ControlNode.allocate(state.dataTranspiredCollector->UTSC(Item).NumOASysAttached);
     352            0 :                     state.dataTranspiredCollector->UTSC(Item).ControlNode = 0;
     353            0 :                     state.dataTranspiredCollector->UTSC(Item).ZoneNode.allocate(state.dataTranspiredCollector->UTSC(Item).NumOASysAttached);
     354            0 :                     state.dataTranspiredCollector->UTSC(Item).ZoneNode = 0;
     355            0 :                     for (NumOASys = 1; NumOASys <= state.dataTranspiredCollector->UTSC(Item).NumOASysAttached; ++NumOASys) {
     356            0 :                         ACountBase = (NumOASys - 1) * 4 + 2;
     357            0 :                         state.dataTranspiredCollector->UTSC(Item).InletNode(NumOASys) =
     358            0 :                             GetOnlySingleNode(state,
     359            0 :                                               AlphasSplit(ACountBase),
     360              :                                               ErrorsFound,
     361              :                                               DataLoopNode::ConnectionObjectType::SolarCollectorUnglazedTranspired,
     362            0 :                                               AlphasSplit(1),
     363              :                                               DataLoopNode::NodeFluidType::Air,
     364              :                                               DataLoopNode::ConnectionType::Inlet,
     365              :                                               static_cast<NodeInputManager::CompFluidStream>(NumOASys),
     366              :                                               ObjectIsNotParent);
     367              : 
     368            0 :                         state.dataTranspiredCollector->UTSC(Item).OutletNode(NumOASys) =
     369            0 :                             GetOnlySingleNode(state,
     370            0 :                                               AlphasSplit(ACountBase + 1),
     371              :                                               ErrorsFound,
     372              :                                               DataLoopNode::ConnectionObjectType::SolarCollectorUnglazedTranspired,
     373            0 :                                               AlphasSplit(1),
     374              :                                               DataLoopNode::NodeFluidType::Air,
     375              :                                               DataLoopNode::ConnectionType::Outlet,
     376              :                                               static_cast<NodeInputManager::CompFluidStream>(NumOASys),
     377              :                                               ObjectIsNotParent);
     378            0 :                         TestCompSet(state,
     379              :                                     CurrentModuleObject,
     380            0 :                                     AlphasSplit(1),
     381            0 :                                     AlphasSplit(ACountBase),
     382            0 :                                     AlphasSplit(ACountBase + 1),
     383              :                                     "Transpired Collector Air Nodes"); // appears that test fails by design??
     384            0 :                         state.dataTranspiredCollector->UTSC(Item).ControlNode(NumOASys) =
     385            0 :                             GetOnlySingleNode(state,
     386            0 :                                               AlphasSplit(ACountBase + 2),
     387              :                                               ErrorsFound,
     388              :                                               DataLoopNode::ConnectionObjectType::SolarCollectorUnglazedTranspired,
     389            0 :                                               AlphasSplit(1),
     390              :                                               DataLoopNode::NodeFluidType::Air,
     391              :                                               DataLoopNode::ConnectionType::Sensor,
     392              :                                               NodeInputManager::CompFluidStream::Primary,
     393              :                                               ObjectIsNotParent);
     394              : 
     395            0 :                         state.dataTranspiredCollector->UTSC(Item).ZoneNode(NumOASys) =
     396            0 :                             GetOnlySingleNode(state,
     397            0 :                                               AlphasSplit(ACountBase + 3),
     398              :                                               ErrorsFound,
     399              :                                               DataLoopNode::ConnectionObjectType::SolarCollectorUnglazedTranspired,
     400            0 :                                               AlphasSplit(1),
     401              :                                               DataLoopNode::NodeFluidType::Air,
     402              :                                               DataLoopNode::ConnectionType::Sensor,
     403              :                                               NodeInputManager::CompFluidStream::Primary,
     404              :                                               ObjectIsNotParent);
     405              : 
     406              :                     } // Each OA System in a Multisystem
     407              :                       // DEALLOCATE(AlphasSplit)
     408              :                 }     // each Multisystem present
     409              :             }         // any UTSC Multisystem present
     410              : 
     411            1 :             state.dataTranspiredCollector->UTSC(Item).OSCMName = Alphas(2);
     412            1 :             Found = Util::FindItemInList(state.dataTranspiredCollector->UTSC(Item).OSCMName, state.dataSurface->OSCM);
     413            1 :             if (Found == 0) {
     414            0 :                 ShowSevereError(state,
     415            0 :                                 format("{} not found={} in {} ={}",
     416            0 :                                        state.dataIPShortCut->cAlphaFieldNames(2),
     417            0 :                                        state.dataTranspiredCollector->UTSC(Item).OSCMName,
     418              :                                        CurrentModuleObject,
     419            0 :                                        state.dataTranspiredCollector->UTSC(Item).Name));
     420            0 :                 ErrorsFound = true;
     421              :             }
     422            1 :             state.dataTranspiredCollector->UTSC(Item).OSCMPtr = Found;
     423            1 :             if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     424            0 :                 state.dataTranspiredCollector->UTSC(Item).availSched = Sched::GetScheduleAlwaysOn(state);
     425            1 :             } else if ((state.dataTranspiredCollector->UTSC(Item).availSched = Sched::GetSchedule(state, Alphas(3))) == nullptr) {
     426            0 :                 ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(3), Alphas(3));
     427            0 :                 ErrorsFound = true;
     428            0 :                 continue;
     429              :             }
     430              : 
     431              :             // now if UTSC(Item)%NumOASysAttached still not set, assume no multisystem
     432            1 :             if (state.dataTranspiredCollector->UTSC(Item).NumOASysAttached == 0) {
     433            1 :                 state.dataTranspiredCollector->UTSC(Item).NumOASysAttached = 1;
     434            1 :                 state.dataTranspiredCollector->UTSC(Item).InletNode.allocate(1);
     435            1 :                 state.dataTranspiredCollector->UTSC(Item).InletNode(1) = 0;
     436            1 :                 state.dataTranspiredCollector->UTSC(Item).OutletNode.allocate(1);
     437            1 :                 state.dataTranspiredCollector->UTSC(Item).OutletNode(1) = 0;
     438            1 :                 state.dataTranspiredCollector->UTSC(Item).ControlNode.allocate(1);
     439            1 :                 state.dataTranspiredCollector->UTSC(Item).ControlNode(1) = 0;
     440            1 :                 state.dataTranspiredCollector->UTSC(Item).ZoneNode.allocate(1);
     441            1 :                 state.dataTranspiredCollector->UTSC(Item).ZoneNode(1) = 0;
     442              : 
     443            1 :                 state.dataTranspiredCollector->UTSC(Item).InletNode(1) =
     444            2 :                     GetOnlySingleNode(state,
     445            1 :                                       Alphas(4),
     446              :                                       ErrorsFound,
     447              :                                       DataLoopNode::ConnectionObjectType::SolarCollectorUnglazedTranspired,
     448            1 :                                       Alphas(1),
     449              :                                       DataLoopNode::NodeFluidType::Air,
     450              :                                       DataLoopNode::ConnectionType::Inlet,
     451              :                                       NodeInputManager::CompFluidStream::Primary,
     452              :                                       ObjectIsNotParent);
     453            1 :                 state.dataTranspiredCollector->UTSC(Item).OutletNode(1) =
     454            3 :                     GetOnlySingleNode(state,
     455            1 :                                       Alphas(5),
     456              :                                       ErrorsFound,
     457              :                                       DataLoopNode::ConnectionObjectType::SolarCollectorUnglazedTranspired,
     458            1 :                                       Alphas(1),
     459              :                                       DataLoopNode::NodeFluidType::Air,
     460              :                                       DataLoopNode::ConnectionType::Outlet,
     461              :                                       NodeInputManager::CompFluidStream::Primary,
     462              :                                       ObjectIsNotParent);
     463            1 :                 TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(4), Alphas(5), "Transpired Collector Air Nodes");
     464              : 
     465            1 :                 state.dataTranspiredCollector->UTSC(Item).ControlNode(1) =
     466            2 :                     GetOnlySingleNode(state,
     467            1 :                                       Alphas(6),
     468              :                                       ErrorsFound,
     469              :                                       DataLoopNode::ConnectionObjectType::SolarCollectorUnglazedTranspired,
     470            1 :                                       Alphas(1),
     471              :                                       DataLoopNode::NodeFluidType::Air,
     472              :                                       DataLoopNode::ConnectionType::Sensor,
     473              :                                       NodeInputManager::CompFluidStream::Primary,
     474              :                                       ObjectIsNotParent);
     475            1 :                 state.dataTranspiredCollector->UTSC(Item).ZoneNode(1) =
     476            3 :                     GetOnlySingleNode(state,
     477            1 :                                       Alphas(7),
     478              :                                       ErrorsFound,
     479              :                                       DataLoopNode::ConnectionObjectType::SolarCollectorUnglazedTranspired,
     480            1 :                                       Alphas(1),
     481              :                                       DataLoopNode::NodeFluidType::Air,
     482              :                                       DataLoopNode::ConnectionType::Sensor,
     483              :                                       NodeInputManager::CompFluidStream::Primary,
     484              :                                       ObjectIsNotParent);
     485              :             } // no splitter
     486              : 
     487            1 :             if (state.dataIPShortCut->lAlphaFieldBlanks(8)) {
     488            0 :                 ShowSevereEmptyField(state, eoh, state.dataIPShortCut->cAlphaFieldNames(8));
     489            0 :                 ErrorsFound = true;
     490            1 :             } else if ((state.dataTranspiredCollector->UTSC(Item).freeHeatSetPointSched = Sched::GetSchedule(state, Alphas(8))) == nullptr) {
     491            0 :                 ShowSevereItemNotFound(state, eoh, state.dataIPShortCut->cAlphaFieldNames(8), Alphas(8));
     492            0 :                 ErrorsFound = true;
     493            0 :                 continue;
     494              :             }
     495              : 
     496            1 :             if (Util::SameString(Alphas(9), "Triangle")) {
     497            1 :                 state.dataTranspiredCollector->UTSC(Item).Layout = Layout_Triangle;
     498            0 :             } else if (Util::SameString(Alphas(9), "Square")) {
     499            0 :                 state.dataTranspiredCollector->UTSC(Item).Layout = Layout_Square;
     500              :             } else {
     501            0 :                 ShowSevereError(state,
     502            0 :                                 format("{} has incorrect entry of {} in {} ={}",
     503            0 :                                        state.dataIPShortCut->cAlphaFieldNames(9),
     504              :                                        Alphas(9),
     505              :                                        CurrentModuleObject,
     506            0 :                                        state.dataTranspiredCollector->UTSC(Item).Name));
     507            0 :                 ErrorsFound = true;
     508            0 :                 continue;
     509              :             }
     510              : 
     511            1 :             if (Util::SameString(Alphas(10), "Kutscher1994")) {
     512            1 :                 state.dataTranspiredCollector->UTSC(Item).Correlation = Correlation_Kutscher1994;
     513            0 :             } else if (Util::SameString(Alphas(10), "VanDeckerHollandsBrunger2001")) {
     514            0 :                 state.dataTranspiredCollector->UTSC(Item).Correlation = Correlation_VanDeckerHollandsBrunger2001;
     515              :             } else {
     516            0 :                 ShowSevereError(state,
     517            0 :                                 format("{} has incorrect entry of {} in {} ={}",
     518            0 :                                        state.dataIPShortCut->cAlphaFieldNames(10),
     519              :                                        Alphas(9),
     520              :                                        CurrentModuleObject,
     521            0 :                                        state.dataTranspiredCollector->UTSC(Item).Name));
     522            0 :                 ErrorsFound = true;
     523            0 :                 continue;
     524              :             }
     525              : 
     526            1 :             Roughness = Alphas(11);
     527              :             // Select the correct Number for the associated ascii name for the roughness type
     528            1 :             if (Util::SameString(Roughness, "VeryRough"))
     529            0 :                 state.dataTranspiredCollector->UTSC(Item).CollRoughness = Material::SurfaceRoughness::VeryRough;
     530            1 :             if (Util::SameString(Roughness, "Rough")) state.dataTranspiredCollector->UTSC(Item).CollRoughness = Material::SurfaceRoughness::Rough;
     531            1 :             if (Util::SameString(Roughness, "MediumRough"))
     532            1 :                 state.dataTranspiredCollector->UTSC(Item).CollRoughness = Material::SurfaceRoughness::MediumRough;
     533            1 :             if (Util::SameString(Roughness, "MediumSmooth"))
     534            0 :                 state.dataTranspiredCollector->UTSC(Item).CollRoughness = Material::SurfaceRoughness::MediumSmooth;
     535            1 :             if (Util::SameString(Roughness, "Smooth")) state.dataTranspiredCollector->UTSC(Item).CollRoughness = Material::SurfaceRoughness::Smooth;
     536            1 :             if (Util::SameString(Roughness, "VerySmooth"))
     537            0 :                 state.dataTranspiredCollector->UTSC(Item).CollRoughness = Material::SurfaceRoughness::VerySmooth;
     538              : 
     539              :             // Was it set?
     540            1 :             if (state.dataTranspiredCollector->UTSC(Item).CollRoughness == Material::SurfaceRoughness::Invalid) {
     541            0 :                 ShowSevereError(state,
     542            0 :                                 format("{} has incorrect entry of {} in {} ={}",
     543            0 :                                        state.dataIPShortCut->cAlphaFieldNames(11),
     544              :                                        Alphas(11),
     545              :                                        CurrentModuleObject,
     546            0 :                                        state.dataTranspiredCollector->UTSC(Item).Name));
     547            0 :                 ErrorsFound = true;
     548              :             }
     549              : 
     550            1 :             AlphaOffset = 11;
     551            1 :             state.dataTranspiredCollector->UTSC(Item).NumSurfs = NumAlphas - AlphaOffset;
     552            1 :             if (state.dataTranspiredCollector->UTSC(Item).NumSurfs == 0) {
     553            0 :                 ShowSevereError(
     554            0 :                     state, format("No underlying surfaces specified in {} ={}", CurrentModuleObject, state.dataTranspiredCollector->UTSC(Item).Name));
     555            0 :                 ErrorsFound = true;
     556            0 :                 continue;
     557              :             }
     558            1 :             state.dataTranspiredCollector->UTSC(Item).SurfPtrs.allocate(state.dataTranspiredCollector->UTSC(Item).NumSurfs);
     559            1 :             state.dataTranspiredCollector->UTSC(Item).SurfPtrs = 0;
     560            3 :             for (ThisSurf = 1; ThisSurf <= state.dataTranspiredCollector->UTSC(Item).NumSurfs; ++ThisSurf) {
     561            2 :                 Found = Util::FindItemInList(Alphas(ThisSurf + AlphaOffset), state.dataSurface->Surface);
     562            2 :                 if (Found == 0) {
     563            0 :                     ShowSevereError(state,
     564            0 :                                     format("Surface Name not found={} in {} ={}",
     565              :                                            Alphas(ThisSurf + AlphaOffset),
     566              :                                            CurrentModuleObject,
     567            0 :                                            state.dataTranspiredCollector->UTSC(Item).Name));
     568            0 :                     ErrorsFound = true;
     569            0 :                     continue;
     570              :                 }
     571              :                 // check that surface is appropriate, Heat transfer, Sun, Wind,
     572            2 :                 if (!state.dataSurface->Surface(Found).HeatTransSurf) {
     573            0 :                     ShowSevereError(state,
     574            0 :                                     format("Surface {} not of Heat Transfer type in {} ={}",
     575              :                                            Alphas(ThisSurf + AlphaOffset),
     576              :                                            CurrentModuleObject,
     577            0 :                                            state.dataTranspiredCollector->UTSC(Item).Name));
     578            0 :                     ErrorsFound = true;
     579            0 :                     continue;
     580              :                 }
     581            2 :                 if (!state.dataSurface->Surface(Found).ExtSolar) {
     582            0 :                     ShowSevereError(state,
     583            0 :                                     format("Surface {} not exposed to sun in {} ={}",
     584              :                                            Alphas(ThisSurf + AlphaOffset),
     585              :                                            CurrentModuleObject,
     586            0 :                                            state.dataTranspiredCollector->UTSC(Item).Name));
     587            0 :                     ErrorsFound = true;
     588            0 :                     continue;
     589              :                 }
     590            2 :                 if (!state.dataSurface->Surface(Found).ExtWind) {
     591            0 :                     ShowSevereError(state,
     592            0 :                                     format("Surface {} not exposed to wind in {} ={}",
     593              :                                            Alphas(ThisSurf + AlphaOffset),
     594              :                                            CurrentModuleObject,
     595            0 :                                            state.dataTranspiredCollector->UTSC(Item).Name));
     596            0 :                     ErrorsFound = true;
     597            0 :                     continue;
     598              :                 }
     599            2 :                 if (state.dataSurface->Surface(Found).ExtBoundCond != OtherSideCondModeledExt) {
     600            0 :                     ShowSevereError(state,
     601            0 :                                     format("Surface {} does not have OtherSideConditionsModel for exterior boundary conditions in {} ={}",
     602              :                                            Alphas(ThisSurf + AlphaOffset),
     603              :                                            CurrentModuleObject,
     604            0 :                                            state.dataTranspiredCollector->UTSC(Item).Name));
     605            0 :                     ErrorsFound = true;
     606            0 :                     continue;
     607              :                 }
     608              :                 // check surface orientation, warn if upside down
     609            2 :                 if ((state.dataSurface->Surface(Found).Tilt < -95.0) || (state.dataSurface->Surface(Found).Tilt > 95.0)) {
     610            0 :                     ShowWarningError(state, format("Suspected input problem with collector surface = {}", Alphas(ThisSurf + AlphaOffset)));
     611            0 :                     ShowContinueError(
     612              :                         state,
     613            0 :                         format("Entered in {} = {}", state.dataIPShortCut->cCurrentModuleObject, state.dataTranspiredCollector->UTSC(Item).Name));
     614            0 :                     ShowContinueError(state, "Surface used for solar collector faces down");
     615            0 :                     ShowContinueError(
     616            0 :                         state, format("Surface tilt angle (degrees from ground outward normal) = {:.2R}", state.dataSurface->Surface(Found).Tilt));
     617              :                 }
     618              : 
     619            2 :                 state.dataTranspiredCollector->UTSC(Item).SurfPtrs(ThisSurf) = Found;
     620              :             }
     621              : 
     622            1 :             if (ErrorsFound) continue; // previous inner do loop may have detected problems that need to be cycle'd again to avoid crash
     623              : 
     624              :             // now that we should have all the surfaces, do some preparations and checks.
     625              : 
     626              :             // are they all similar tilt and azimuth? Issue warnings so people can do it if they really want
     627            1 :             Real64 const surfaceArea(sum_sub(state.dataSurface->Surface, &SurfaceData::Area, state.dataTranspiredCollector->UTSC(Item).SurfPtrs));
     628              :             //            AvgAzimuth = sum( Surface( UTSC( Item ).SurfPtrs ).Azimuth * Surface( UTSC( Item ).SurfPtrs ).Area ) / sum( Surface(
     629              :             // UTSC(  Item
     630              :             //).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced by below
     631            1 :             AvgAzimuth =
     632            2 :                 sum_product_sub(
     633            1 :                     state.dataSurface->Surface, &SurfaceData::Azimuth, &SurfaceData::Area, state.dataTranspiredCollector->UTSC(Item).SurfPtrs) /
     634              :                 surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
     635              :             //            AvgTilt = sum( Surface( UTSC( Item ).SurfPtrs ).Tilt * Surface( UTSC( Item ).SurfPtrs ).Area ) / sum( Surface( UTSC(
     636              :             // Item
     637              :             //).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced by below
     638            2 :             AvgTilt = sum_product_sub(
     639            1 :                           state.dataSurface->Surface, &SurfaceData::Tilt, &SurfaceData::Area, state.dataTranspiredCollector->UTSC(Item).SurfPtrs) /
     640              :                       surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
     641            3 :             for (ThisSurf = 1; ThisSurf <= state.dataTranspiredCollector->UTSC(Item).NumSurfs; ++ThisSurf) {
     642            2 :                 SurfID = state.dataTranspiredCollector->UTSC(Item).SurfPtrs(ThisSurf);
     643            2 :                 if (General::rotAzmDiffDeg(state.dataSurface->Surface(SurfID).Azimuth, AvgAzimuth) > 15.0) {
     644            0 :                     ShowWarningError(state,
     645            0 :                                      format("Surface {} has Azimuth different from others in the group associated with {} ={}",
     646            0 :                                             state.dataSurface->Surface(SurfID).Name,
     647              :                                             CurrentModuleObject,
     648            0 :                                             state.dataTranspiredCollector->UTSC(Item).Name));
     649              :                 }
     650            2 :                 if (std::abs(state.dataSurface->Surface(SurfID).Tilt - AvgTilt) > 10.0) {
     651            0 :                     ShowWarningError(state,
     652            0 :                                      format("Surface {} has Tilt different from others in the group associated with {} ={}",
     653            0 :                                             state.dataSurface->Surface(SurfID).Name,
     654              :                                             CurrentModuleObject,
     655            0 :                                             state.dataTranspiredCollector->UTSC(Item).Name));
     656              :                 }
     657              : 
     658              :                 // test that there are no windows.  Now allow windows
     659              :                 // If (Surface(SurfID)%GrossArea >  Surface(SurfID)%Area) Then
     660              :                 //      Call ShowWarningError(state, 'Surface '//TRIM(Surface(SurfID)%name)//' has a subsurface whose area is not being ' &
     661              :                 //         //'subtracted in the group of surfaces associated with '//TRIM(UTSC(Item)%Name))
     662              :                 // endif
     663              :             }
     664            1 :             state.dataTranspiredCollector->UTSC(Item).Tilt = AvgTilt;
     665            1 :             state.dataTranspiredCollector->UTSC(Item).Azimuth = AvgAzimuth;
     666              : 
     667              :             // find area weighted centroid.
     668              :             //    UTSC(Item)%Centroid%x = SUM(Surface(UTSC(Item)%SurfPtrs)%Centroid%x*Surface(UTSC(Item)%SurfPtrs)%Area) &
     669              :             //                            /SUM(Surface(UTSC(Item)%SurfPtrs)%Area)
     670              :             //    UTSC(Item)%Centroid%y = SUM(Surface(UTSC(Item)%SurfPtrs)%Centroid%y*Surface(UTSC(Item)%SurfPtrs)%Area) &
     671              :             //                            /SUM(Surface(UTSC(Item)%SurfPtrs)%Area)
     672              :             //            UTSC( Item ).Centroid.z = sum( Surface( UTSC( Item ).SurfPtrs ).Centroid.z * Surface( UTSC( Item ).SurfPtrs ).Area ) /
     673              :             // sum(  Surface( UTSC( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced by below
     674            2 :             state.dataTranspiredCollector->UTSC(Item).Centroid.z = sum_product_sub(state.dataSurface->Surface,
     675              :                                                                                    &SurfaceData::Centroid,
     676              :                                                                                    &Vector::z,
     677            1 :                                                                                    state.dataSurface->Surface,
     678              :                                                                                    &SurfaceData::Area,
     679            2 :                                                                                    state.dataTranspiredCollector->UTSC(Item).SurfPtrs) /
     680              :                                                                    surfaceArea; // Autodesk:F2C++ Functions handle array subscript usage
     681              : 
     682              :             // now handle numbers from input object
     683            1 :             state.dataTranspiredCollector->UTSC(Item).HoleDia = Numbers(1);
     684            1 :             state.dataTranspiredCollector->UTSC(Item).Pitch = Numbers(2);
     685            1 :             state.dataTranspiredCollector->UTSC(Item).LWEmitt = Numbers(3);
     686            1 :             state.dataTranspiredCollector->UTSC(Item).SolAbsorp = Numbers(4);
     687            1 :             state.dataTranspiredCollector->UTSC(Item).Height = Numbers(5);
     688            1 :             state.dataTranspiredCollector->UTSC(Item).PlenGapThick = Numbers(6);
     689            1 :             if (state.dataTranspiredCollector->UTSC(Item).PlenGapThick <= 0.0) {
     690            0 :                 ShowSevereError(
     691              :                     state,
     692            0 :                     format("Plenum gap must be greater than Zero in {} ={}", CurrentModuleObject, state.dataTranspiredCollector->UTSC(Item).Name));
     693            0 :                 continue;
     694              :             }
     695            1 :             state.dataTranspiredCollector->UTSC(Item).PlenCrossArea = Numbers(7);
     696            1 :             state.dataTranspiredCollector->UTSC(Item).AreaRatio = Numbers(8);
     697            1 :             state.dataTranspiredCollector->UTSC(Item).CollectThick = Numbers(9);
     698            1 :             state.dataTranspiredCollector->UTSC(Item).Cv = Numbers(10);
     699            1 :             state.dataTranspiredCollector->UTSC(Item).Cd = Numbers(11);
     700              : 
     701              :             // Fill out data we now know
     702              :             // sum areas of HT surface areas
     703              :             //            UTSC( Item ).ProjArea = sum( Surface( UTSC( Item ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced
     704              :             // by  below
     705            1 :             state.dataTranspiredCollector->UTSC(Item).ProjArea = surfaceArea;
     706            1 :             if (state.dataTranspiredCollector->UTSC(Item).ProjArea == 0) {
     707            0 :                 ShowSevereError(state,
     708            0 :                                 format("Gross area of underlying surfaces is zero in {} ={}",
     709              :                                        CurrentModuleObject,
     710            0 :                                        state.dataTranspiredCollector->UTSC(Item).Name));
     711            0 :                 continue;
     712              :             }
     713            1 :             state.dataTranspiredCollector->UTSC(Item).ActualArea =
     714            1 :                 state.dataTranspiredCollector->UTSC(Item).ProjArea * state.dataTranspiredCollector->UTSC(Item).AreaRatio;
     715              :             //  need to update this for slots as well as holes
     716            1 :             switch (state.dataTranspiredCollector->UTSC(Item).Layout) {
     717            1 :             case Layout_Triangle: { // 'TRIANGLE'
     718            1 :                 state.dataTranspiredCollector->UTSC(Item).Porosity =
     719            2 :                     0.907 * pow_2(state.dataTranspiredCollector->UTSC(Item).HoleDia /
     720            1 :                                   state.dataTranspiredCollector->UTSC(Item).Pitch); // Kutscher equation, Triangle layout
     721            1 :             } break;
     722            0 :             case Layout_Square: { // 'SQUARE'
     723            0 :                 state.dataTranspiredCollector->UTSC(Item).Porosity =
     724            0 :                     (Constant::Pi / 4.0) * pow_2(state.dataTranspiredCollector->UTSC(Item).HoleDia) /
     725            0 :                     pow_2(state.dataTranspiredCollector->UTSC(Item).Pitch); // Waterloo equation, square layout
     726            0 :             } break;
     727            0 :             default:
     728            0 :                 break;
     729              :             }
     730            1 :             TiltRads = std::abs(AvgTilt) * Constant::DegToRad;
     731            1 :             tempHdeltaNPL = std::sin(TiltRads) * state.dataTranspiredCollector->UTSC(Item).Height / 4.0;
     732            1 :             state.dataTranspiredCollector->UTSC(Item).HdeltaNPL = max(tempHdeltaNPL, state.dataTranspiredCollector->UTSC(Item).PlenGapThick);
     733              : 
     734            2 :             SetupOutputVariable(state,
     735              :                                 "Solar Collector Heat Exchanger Effectiveness",
     736              :                                 Constant::Units::None,
     737            1 :                                 state.dataTranspiredCollector->UTSC(Item).HXeff,
     738              :                                 OutputProcessor::TimeStepType::System,
     739              :                                 OutputProcessor::StoreType::Average,
     740            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     741            2 :             SetupOutputVariable(state,
     742              :                                 "Solar Collector Leaving Air Temperature",
     743              :                                 Constant::Units::C,
     744            1 :                                 state.dataTranspiredCollector->UTSC(Item).TairHX,
     745              :                                 OutputProcessor::TimeStepType::System,
     746              :                                 OutputProcessor::StoreType::Average,
     747            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     748            2 :             SetupOutputVariable(state,
     749              :                                 "Solar Collector Outside Face Suction Velocity",
     750              :                                 Constant::Units::m_s,
     751            1 :                                 state.dataTranspiredCollector->UTSC(Item).Vsuction,
     752              :                                 OutputProcessor::TimeStepType::System,
     753              :                                 OutputProcessor::StoreType::Average,
     754            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     755            2 :             SetupOutputVariable(state,
     756              :                                 "Solar Collector Surface Temperature",
     757              :                                 Constant::Units::C,
     758            1 :                                 state.dataTranspiredCollector->UTSC(Item).Tcoll,
     759              :                                 OutputProcessor::TimeStepType::System,
     760              :                                 OutputProcessor::StoreType::Average,
     761            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     762            2 :             SetupOutputVariable(state,
     763              :                                 "Solar Collector Plenum Air Temperature",
     764              :                                 Constant::Units::C,
     765            1 :                                 state.dataTranspiredCollector->UTSC(Item).Tplen,
     766              :                                 OutputProcessor::TimeStepType::System,
     767              :                                 OutputProcessor::StoreType::Average,
     768            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     769            2 :             SetupOutputVariable(state,
     770              :                                 "Solar Collector Sensible Heating Rate",
     771              :                                 Constant::Units::W,
     772            1 :                                 state.dataTranspiredCollector->UTSC(Item).SensHeatingRate,
     773              :                                 OutputProcessor::TimeStepType::System,
     774              :                                 OutputProcessor::StoreType::Average,
     775            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     776            2 :             SetupOutputVariable(state,
     777              :                                 "Solar Collector Sensible Heating Energy",
     778              :                                 Constant::Units::J,
     779            1 :                                 state.dataTranspiredCollector->UTSC(Item).SensHeatingEnergy,
     780              :                                 OutputProcessor::TimeStepType::System,
     781              :                                 OutputProcessor::StoreType::Sum,
     782            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name,
     783              :                                 Constant::eResource::SolarAir,
     784              :                                 OutputProcessor::Group::HVAC,
     785              :                                 OutputProcessor::EndUseCat::HeatProduced);
     786              : 
     787            2 :             SetupOutputVariable(state,
     788              :                                 "Solar Collector Natural Ventilation Air Change Rate",
     789              :                                 Constant::Units::ach,
     790            1 :                                 state.dataTranspiredCollector->UTSC(Item).PassiveACH,
     791              :                                 OutputProcessor::TimeStepType::System,
     792              :                                 OutputProcessor::StoreType::Average,
     793            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     794            2 :             SetupOutputVariable(state,
     795              :                                 "Solar Collector Natural Ventilation Mass Flow Rate",
     796              :                                 Constant::Units::kg_s,
     797            1 :                                 state.dataTranspiredCollector->UTSC(Item).PassiveMdotVent,
     798              :                                 OutputProcessor::TimeStepType::System,
     799              :                                 OutputProcessor::StoreType::Average,
     800            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     801            2 :             SetupOutputVariable(state,
     802              :                                 "Solar Collector Wind Natural Ventilation Mass Flow Rate",
     803              :                                 Constant::Units::kg_s,
     804            1 :                                 state.dataTranspiredCollector->UTSC(Item).PassiveMdotWind,
     805              :                                 OutputProcessor::TimeStepType::System,
     806              :                                 OutputProcessor::StoreType::Average,
     807            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     808            2 :             SetupOutputVariable(state,
     809              :                                 "Solar Collector Buoyancy Natural Ventilation Mass Flow Rate",
     810              :                                 Constant::Units::kg_s,
     811            1 :                                 state.dataTranspiredCollector->UTSC(Item).PassiveMdotTherm,
     812              :                                 OutputProcessor::TimeStepType::System,
     813              :                                 OutputProcessor::StoreType::Average,
     814            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     815            2 :             SetupOutputVariable(state,
     816              :                                 "Solar Collector Incident Solar Radiation",
     817              :                                 Constant::Units::W_m2,
     818            1 :                                 state.dataTranspiredCollector->UTSC(Item).Isc,
     819              :                                 OutputProcessor::TimeStepType::System,
     820              :                                 OutputProcessor::StoreType::Average,
     821            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     822            2 :             SetupOutputVariable(state,
     823              :                                 "Solar Collector System Efficiency",
     824              :                                 Constant::Units::None,
     825            1 :                                 state.dataTranspiredCollector->UTSC(Item).UTSCEfficiency,
     826              :                                 OutputProcessor::TimeStepType::System,
     827              :                                 OutputProcessor::StoreType::Average,
     828            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     829            2 :             SetupOutputVariable(state,
     830              :                                 "Solar Collector Surface Efficiency",
     831              :                                 Constant::Units::None,
     832            1 :                                 state.dataTranspiredCollector->UTSC(Item).UTSCCollEff,
     833              :                                 OutputProcessor::TimeStepType::System,
     834              :                                 OutputProcessor::StoreType::Average,
     835            1 :                                 state.dataTranspiredCollector->UTSC(Item).Name);
     836              :         }
     837              : 
     838            1 :         for (ItemSplit = 1; ItemSplit <= NumUTSCSplitter; ++ItemSplit) {
     839            0 :             if (!SplitterNameOK(ItemSplit)) {
     840            0 :                 ShowSevereError(state, "Did not find a match, check names for Solar Collectors:Transpired Collector:Multisystem");
     841            0 :                 ErrorsFound = true;
     842              :             }
     843              :         }
     844              : 
     845            1 :         if (ErrorsFound) {
     846            0 :             ShowFatalError(state, "GetTranspiredCollectorInput: Errors found in input");
     847              :         }
     848              : 
     849            1 :         Alphas.deallocate();
     850            1 :     }
     851              : 
     852            1 :     void InitTranspiredCollector(EnergyPlusData &state, int const UTSCNum) // compindex already checked in calling routine
     853              :     {
     854              : 
     855              :         // SUBROUTINE INFORMATION:
     856              :         //       AUTHOR         B.T. Griffith
     857              :         //       DATE WRITTEN   November 2004
     858              :         //       MODIFIED       B. Griffith, May 2009, added EMS setpoint check
     859              :         //       RE-ENGINEERED  na
     860              : 
     861              :         // Using/Aliasing
     862            1 :         bool DoSetPointTest = state.dataHVACGlobal->DoSetPointTest;
     863              :         using namespace DataLoopNode;
     864              :         using DataSurfaces::SurfaceData;
     865              :         using EMSManager::CheckIfNodeSetPointManagedByEMS;
     866              : 
     867              :         int UTSCUnitNum;
     868              :         int ControlNode;
     869              :         int SplitBranch;
     870              :         int thisUTSC;
     871              :         Real64 Tamb;
     872              : 
     873            1 :         if (state.dataTranspiredCollector->MyOneTimeFlag) {
     874              :             // do various one time setups and pitch adjustments across all UTSC
     875            2 :             for (thisUTSC = 1; thisUTSC <= state.dataTranspiredCollector->NumUTSC; ++thisUTSC) {
     876            1 :                 if (state.dataTranspiredCollector->UTSC(thisUTSC).Layout == Layout_Triangle) {
     877            1 :                     switch (state.dataTranspiredCollector->UTSC(thisUTSC).Correlation) {
     878            1 :                     case Correlation_Kutscher1994: { // Kutscher1994
     879            1 :                         state.dataTranspiredCollector->UTSC(thisUTSC).Pitch = state.dataTranspiredCollector->UTSC(thisUTSC).Pitch;
     880            1 :                     } break;
     881            0 :                     case Correlation_VanDeckerHollandsBrunger2001: { // VanDeckerHollandsBrunger2001
     882            0 :                         state.dataTranspiredCollector->UTSC(thisUTSC).Pitch /= 1.6;
     883            0 :                     } break;
     884            0 :                     default:
     885            0 :                         break;
     886              :                     }
     887              :                 }
     888            1 :                 if (state.dataTranspiredCollector->UTSC(thisUTSC).Layout == Layout_Square) {
     889            0 :                     switch (state.dataTranspiredCollector->UTSC(thisUTSC).Correlation) {
     890            0 :                     case Correlation_Kutscher1994: { // Kutscher1994
     891            0 :                         state.dataTranspiredCollector->UTSC(thisUTSC).Pitch *= 1.6;
     892            0 :                     } break;
     893            0 :                     case Correlation_VanDeckerHollandsBrunger2001: { // VanDeckerHollandsBrunger2001
     894            0 :                         state.dataTranspiredCollector->UTSC(thisUTSC).Pitch = state.dataTranspiredCollector->UTSC(thisUTSC).Pitch;
     895            0 :                     } break;
     896            0 :                     default:
     897            0 :                         break;
     898              :                     }
     899              :                 }
     900              :             }
     901              : 
     902            1 :             state.dataTranspiredCollector->MyEnvrnFlag.dimension(state.dataTranspiredCollector->NumUTSC, true);
     903            1 :             state.dataTranspiredCollector->MyOneTimeFlag = false;
     904              :         } // first time
     905              : 
     906              :         // Check that setpoint is active (from test by RJL in HVACEvapComponent)
     907            1 :         if (!state.dataGlobal->SysSizingCalc && state.dataTranspiredCollector->MySetPointCheckFlag && DoSetPointTest) {
     908            0 :             for (UTSCUnitNum = 1; UTSCUnitNum <= state.dataTranspiredCollector->NumUTSC; ++UTSCUnitNum) {
     909            0 :                 for (SplitBranch = 1; SplitBranch <= state.dataTranspiredCollector->UTSC(UTSCUnitNum).NumOASysAttached; ++SplitBranch) {
     910            0 :                     ControlNode = state.dataTranspiredCollector->UTSC(UTSCUnitNum).ControlNode(SplitBranch);
     911            0 :                     if (ControlNode > 0) {
     912            0 :                         if (state.dataLoopNodes->Node(ControlNode).TempSetPoint == SensedNodeFlagValue) {
     913            0 :                             if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
     914            0 :                                 ShowSevereError(
     915            0 :                                     state, format("Missing temperature setpoint for UTSC {}", state.dataTranspiredCollector->UTSC(UTSCUnitNum).Name));
     916            0 :                                 ShowContinueError(state, " use a Setpoint Manager to establish a setpoint at the unit control node.");
     917            0 :                                 state.dataHVACGlobal->SetPointErrorFlag = true;
     918              :                             } else {
     919              :                                 // need call to EMS to check node
     920            0 :                                 CheckIfNodeSetPointManagedByEMS(state, ControlNode, HVAC::CtrlVarType::Temp, state.dataHVACGlobal->SetPointErrorFlag);
     921            0 :                                 if (state.dataHVACGlobal->SetPointErrorFlag) {
     922            0 :                                     ShowSevereError(
     923              :                                         state,
     924            0 :                                         format("Missing temperature setpoint for UTSC {}", state.dataTranspiredCollector->UTSC(UTSCUnitNum).Name));
     925            0 :                                     ShowContinueError(state, " use a Setpoint Manager to establish a setpoint at the unit control node.");
     926            0 :                                     ShowContinueError(state, "Or add EMS Actuator to provide temperature setpoint at this node");
     927              :                                 }
     928              :                             }
     929              :                         }
     930              :                     }
     931              :                 }
     932              :             }
     933            0 :             state.dataTranspiredCollector->MySetPointCheckFlag = false;
     934              :         }
     935              : 
     936            1 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataTranspiredCollector->MyEnvrnFlag(UTSCNum)) {
     937            1 :             state.dataTranspiredCollector->UTSC(UTSCNum).TplenLast = 22.5;
     938            1 :             state.dataTranspiredCollector->UTSC(UTSCNum).TcollLast = 22.0;
     939              : 
     940            1 :             state.dataTranspiredCollector->MyEnvrnFlag(UTSCNum) = false;
     941              :         }
     942            1 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     943            0 :             state.dataTranspiredCollector->MyEnvrnFlag(UTSCNum) = true;
     944              :         }
     945              : 
     946              :         // determine average ambient temperature
     947            1 :         Real64 sum_area = 0.0;
     948            3 :         for (int SurfNum : state.dataTranspiredCollector->UTSC(UTSCNum).SurfPtrs) {
     949            2 :             sum_area += state.dataSurface->Surface(SurfNum).Area;
     950              :         }
     951            1 :         if (!state.dataEnvrn->IsRain) {
     952            1 :             Real64 sum_produc_area_drybulb = 0.0;
     953            3 :             for (int SurfNum : state.dataTranspiredCollector->UTSC(UTSCNum).SurfPtrs) {
     954            2 :                 sum_produc_area_drybulb += state.dataSurface->Surface(SurfNum).Area * state.dataSurface->SurfOutDryBulbTemp(SurfNum);
     955              :             }
     956            1 :             Tamb = sum_produc_area_drybulb / sum_area;
     957              :         } else { // when raining we use wet bulb not drybulb
     958            0 :             Real64 sum_produc_area_wetbulb = 0.0;
     959            0 :             for (int SurfNum : state.dataTranspiredCollector->UTSC(UTSCNum).SurfPtrs) {
     960            0 :                 sum_produc_area_wetbulb += state.dataSurface->Surface(SurfNum).Area * state.dataSurface->SurfOutWetBulbTemp(SurfNum);
     961              :             }
     962            0 :             Tamb = sum_produc_area_wetbulb / sum_area;
     963              :         }
     964              : 
     965              :         // inits for each iteration
     966              :         //        UTSC( UTSCNum ).InletMDot = sum( Node( UTSC( UTSCNum ).InletNode ).MassFlowRate ); //Autodesk:F2C++ Array subscript usage:
     967              :         // Replaced by below
     968            1 :         state.dataTranspiredCollector->UTSC(UTSCNum).InletMDot =
     969            1 :             sum_sub(state.dataLoopNodes->Node,
     970              :                     &DataLoopNode::NodeData::MassFlowRate,
     971            1 :                     state.dataTranspiredCollector->UTSC(UTSCNum).InletNode); // Autodesk:F2C++ Functions handle array subscript usage
     972            1 :         state.dataTranspiredCollector->UTSC(UTSCNum).IsOn = false;           // initialize then turn on if appropriate
     973            1 :         state.dataTranspiredCollector->UTSC(UTSCNum).Tplen = state.dataTranspiredCollector->UTSC(UTSCNum).TplenLast;
     974            1 :         state.dataTranspiredCollector->UTSC(UTSCNum).Tcoll = state.dataTranspiredCollector->UTSC(UTSCNum).TcollLast;
     975            1 :         state.dataTranspiredCollector->UTSC(UTSCNum).TairHX = Tamb;
     976            1 :         state.dataTranspiredCollector->UTSC(UTSCNum).MdotVent = 0.0;
     977            1 :         state.dataTranspiredCollector->UTSC(UTSCNum).HXeff = 0.0;
     978            1 :         state.dataTranspiredCollector->UTSC(UTSCNum).Isc = 0.0;
     979              : 
     980            1 :         state.dataTranspiredCollector->UTSC(UTSCNum).UTSCEfficiency = 0.0;
     981            1 :         state.dataTranspiredCollector->UTSC(UTSCNum).UTSCCollEff = 0.0;
     982            1 :     }
     983              : 
     984            0 :     void CalcActiveTranspiredCollector(EnergyPlusData &state, int const UTSCNum)
     985              :     {
     986              : 
     987              :         // SUBROUTINE INFORMATION:
     988              :         //       AUTHOR         B.T. Griffith
     989              :         //       DATE WRITTEN   November 2004
     990              :         //       MODIFIED       na
     991              :         //       RE-ENGINEERED  na
     992              : 
     993              :         // Using/Aliasing
     994            0 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
     995              :         using DataSurfaces::SurfaceData;
     996              :         using Psychrometrics::PsyCpAirFnW;
     997              :         using Psychrometrics::PsyHFnTdbW;
     998              :         using Psychrometrics::PsyRhoAirFnPbTdbW;
     999              :         using namespace DataHeatBalance; // , ONLY: SurfQRadSWOutIncident, Construct, Material
    1000              : 
    1001              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1002            0 :         Real64 constexpr nu(15.66e-6); // kinematic viscosity (m**2/s) for air at 300 K
    1003              :         // (Mills 1999 Heat Transfer)
    1004            0 :         Real64 constexpr k(0.0267); // thermal conductivity (W/m K) for air at 300 K
    1005              :         // (Mills 1999 Heat Transfer)
    1006            0 :         Real64 constexpr Sigma(5.6697e-08); // Stefan-Boltzmann constant
    1007              : 
    1008              :         // following arrays are used to temporarily hold results from multiple underlying surfaces
    1009            0 :         Array1D<Real64> HSkyARR;
    1010            0 :         Array1D<Real64> HGroundARR;
    1011            0 :         Array1D<Real64> HAirARR;
    1012            0 :         Array1D<Real64> HPlenARR;
    1013            0 :         Array1D<Real64> LocalWindArr;
    1014            0 :         Array1D<Real64> HSrdSurfARR;
    1015              : 
    1016              :         // working variables
    1017              :         Real64 RhoAir;                        // density of air
    1018              :         Real64 CpAir;                         // specific heat of air
    1019              :         Real64 holeArea;                      // area of perforations, includes corrugation of surface
    1020              :         Real64 Tamb;                          // outdoor drybulb
    1021              :         Real64 A;                             // projected area of collector, from sum of underlying surfaces
    1022              :         Real64 Vholes;                        // mean velocity of air as it passes through collector holes
    1023              :         Real64 Vsuction;                      // mean velocity of air as is approaches the collector
    1024              :         Real64 Vplen;                         // mean velocity of air inside plenum
    1025              :         Real64 HcPlen;                        // surface convection heat transfer coefficient for plenum surfaces
    1026              :         Real64 D;                             // hole diameter
    1027              :         Real64 ReD;                           // Reynolds number for holes
    1028              :         Real64 P;                             // pitch, distance between holes
    1029              :         Real64 Por;                           // porosity, area fraction of collector that is open because of holes
    1030              :         Real64 Mdot;                          // mass flow rate of suction air
    1031              :         Real64 QdotSource;                    // energy flux for source/sink inside collector surface (for hybrid PV UTSC)
    1032              :         int ThisSurf;                         // do loop counter
    1033              :         int NumSurfs;                         // number of underlying HT surfaces associated with UTSC
    1034              :         Material::SurfaceRoughness Roughness; // parameters for surface roughness, defined in DataHeatBalance
    1035              :         Real64 SolAbs;                        // solar absorptivity of collector
    1036              :         Real64 AbsExt;                        // thermal emittance of collector
    1037              :         Real64 TempExt;                       // collector temperature
    1038              :         int SurfPtr;                          // index of surface in main surface structure
    1039              :         Real64 HMovInsul;                     // dummy for call to InitExteriorConvectionCoeff
    1040              :         Real64 HExt;                          // dummy for call to InitExteriorConvectionCoeff
    1041              :         int ConstrNum;                        // index of construction in main construction structure
    1042              :         Real64 AbsThermSurf;                  // thermal emittance of underlying wall.
    1043              :         Real64 TsoK;                          // underlying surface temperature in Kelvin
    1044              :         Real64 TscollK;                       // collector temperature in Kelvin  (lagged)
    1045              :         Real64 AreaSum;                       // sum of contributing surfaces for area-weighted averages.
    1046              :         Real64 Vwind;                         // localized, and area-weighted average for wind speed
    1047              :         Real64 HrSky;                         // radiation coeff for sky, area-weighted average
    1048              :         Real64 HrGround;                      // radiation coeff for ground, area-weighted average
    1049              :         Real64 HrAtm;                         // radiation coeff for air (bulk atmosphere), area-weighted average
    1050              :         Real64 Isc;                           // Incoming combined solar radiation, area-weighted average
    1051              :         Real64 HrPlen;                        // radiation coeff for plenum surfaces, area-weighted average
    1052              :         Real64 Tso;                           // temperature of underlying surface, area-weighted average
    1053              :         Real64 HcWind;                        // convection coeff for high speed wind situations
    1054              :         Real64 NuD;                           // nusselt number for Reynolds based on hole
    1055              :         Real64 U;                             // overall heat exchanger coefficient
    1056              :         Real64 HXeff;                         // effectiveness for heat exchanger
    1057              :         Real64 t;                             // collector thickness
    1058              :         Real64 ReS;                           // Reynolds number based on suction velocity and pitch
    1059              :         Real64 ReW;                           // Reynolds number based on Wind and pitch
    1060              :         Real64 ReB;                           // Reynolds number based on hole velocity and pitch
    1061              :         Real64 ReH;                           // Reynolds number based on hole velocity and diameter
    1062              :         Real64 Tscoll;                        // temperature of collector
    1063              :         Real64 TaHX;                          // leaving air temperature from heat exchanger (entering plenum)
    1064              :         Real64 Taplen;                        // Air temperature in plen and outlet node.
    1065              :         Real64 SensHeatingRate;               // Rate at which the system is heating outdoor air
    1066              :         Real64 AlessHoles;                    // Area for Kutscher's relation
    1067              : 
    1068            0 :         auto &s_mat = state.dataMaterial;
    1069              :         // Active UTSC calculation
    1070              :         // first do common things for both correlations
    1071            0 :         Real64 sum_area = 0.0;
    1072            0 :         for (int SurfNum : state.dataTranspiredCollector->UTSC(UTSCNum).SurfPtrs) {
    1073            0 :             sum_area += state.dataSurface->Surface(SurfNum).Area;
    1074              :         }
    1075            0 :         if (!state.dataEnvrn->IsRain) {
    1076            0 :             Real64 sum_produc_area_drybulb = 0.0;
    1077            0 :             for (int SurfNum : state.dataTranspiredCollector->UTSC(UTSCNum).SurfPtrs) {
    1078            0 :                 sum_produc_area_drybulb += state.dataSurface->Surface(SurfNum).Area * state.dataSurface->SurfOutDryBulbTemp(SurfNum);
    1079              :             }
    1080            0 :             Tamb = sum_produc_area_drybulb / sum_area;
    1081              :         } else { // when raining we use wet bulb not drybulb
    1082            0 :             Real64 sum_produc_area_wetbulb = 0.0;
    1083            0 :             for (int SurfNum : state.dataTranspiredCollector->UTSC(UTSCNum).SurfPtrs) {
    1084            0 :                 sum_produc_area_wetbulb += state.dataSurface->Surface(SurfNum).Area * state.dataSurface->SurfOutWetBulbTemp(SurfNum);
    1085              :             }
    1086            0 :             Tamb = sum_produc_area_wetbulb / sum_area;
    1087              :         }
    1088              : 
    1089            0 :         RhoAir = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, Tamb, state.dataEnvrn->OutHumRat);
    1090              : 
    1091            0 :         CpAir = PsyCpAirFnW(state.dataEnvrn->OutHumRat);
    1092              : 
    1093            0 :         holeArea = state.dataTranspiredCollector->UTSC(UTSCNum).ActualArea * state.dataTranspiredCollector->UTSC(UTSCNum).Porosity;
    1094              : 
    1095            0 :         A = state.dataTranspiredCollector->UTSC(UTSCNum).ProjArea;
    1096              : 
    1097            0 :         Vholes = state.dataTranspiredCollector->UTSC(UTSCNum).InletMDot / RhoAir / holeArea;
    1098              : 
    1099            0 :         Vplen = state.dataTranspiredCollector->UTSC(UTSCNum).InletMDot / RhoAir / state.dataTranspiredCollector->UTSC(UTSCNum).PlenCrossArea;
    1100              : 
    1101            0 :         Vsuction = state.dataTranspiredCollector->UTSC(UTSCNum).InletMDot / RhoAir / A;
    1102              : 
    1103            0 :         if ((Vsuction < 0.001) || (Vsuction > 0.08)) { // warn that collector is not sized well
    1104            0 :             if (state.dataTranspiredCollector->UTSC(UTSCNum).VsucErrIndex == 0) {
    1105            0 :                 ShowWarningMessage(state,
    1106            0 :                                    format("Solar Collector:Unglazed Transpired=\"{}\", Suction velocity is outside of range for a good design",
    1107            0 :                                           state.dataTranspiredCollector->UTSC(UTSCNum).Name));
    1108            0 :                 ShowContinueErrorTimeStamp(state, format("Suction velocity ={:.4R}", Vsuction));
    1109            0 :                 if (Vsuction < 0.003) {
    1110            0 :                     ShowContinueError(state, "Velocity is low -- suggest decreasing area of transpired collector");
    1111              :                 }
    1112            0 :                 if (Vsuction > 0.08) {
    1113            0 :                     ShowContinueError(state, "Velocity is high -- suggest increasing area of transpired collector");
    1114              :                 }
    1115            0 :                 ShowContinueError(state, "Occasional suction velocity messages are not unexpected when simulating actual conditions");
    1116              :             }
    1117            0 :             ShowRecurringWarningErrorAtEnd(state,
    1118            0 :                                            "Solar Collector:Unglazed Transpired=\"" + state.dataTranspiredCollector->UTSC(UTSCNum).Name +
    1119              :                                                "\", Suction velocity is outside of range",
    1120            0 :                                            state.dataTranspiredCollector->UTSC(UTSCNum).VsucErrIndex,
    1121              :                                            Vsuction,
    1122              :                                            Vsuction,
    1123              :                                            _,
    1124              :                                            "[m/s]",
    1125              :                                            "[m/s]");
    1126              :         }
    1127              : 
    1128            0 :         HcPlen = 5.62 + 3.92 * Vplen;
    1129              : 
    1130            0 :         D = state.dataTranspiredCollector->UTSC(UTSCNum).HoleDia;
    1131              : 
    1132            0 :         ReD = Vholes * D / nu;
    1133              : 
    1134            0 :         P = state.dataTranspiredCollector->UTSC(UTSCNum).Pitch;
    1135              : 
    1136            0 :         Por = state.dataTranspiredCollector->UTSC(UTSCNum).Porosity;
    1137              : 
    1138            0 :         Mdot = state.dataTranspiredCollector->UTSC(UTSCNum).InletMDot;
    1139              : 
    1140            0 :         QdotSource = state.dataTranspiredCollector->UTSC(UTSCNum).QdotSource; // for hybrid PV transpired collectors
    1141              : 
    1142              :         // loop through underlying surfaces and collect needed data
    1143              :         // now collect average values for things associated with the underlying surface(s)
    1144            0 :         NumSurfs = state.dataTranspiredCollector->UTSC(UTSCNum).NumSurfs;
    1145            0 :         HSkyARR.dimension(NumSurfs, 0.0);
    1146            0 :         HGroundARR.dimension(NumSurfs, 0.0);
    1147            0 :         HAirARR.dimension(NumSurfs, 0.0);
    1148            0 :         LocalWindArr.dimension(NumSurfs, 0.0);
    1149              :         // ALLOCATE(IscARR(NumSurfs))
    1150              :         // IscARR = 0.0
    1151            0 :         HPlenARR.dimension(NumSurfs, 0.0);
    1152              :         //  ALLOCATE(TsoARR(NumSurfs))
    1153              :         //  TsoARR = 0.0
    1154            0 :         HSrdSurfARR.dimension(NumSurfs, 0.0);
    1155              : 
    1156            0 :         Roughness = state.dataTranspiredCollector->UTSC(UTSCNum).CollRoughness;
    1157            0 :         SolAbs = state.dataTranspiredCollector->UTSC(UTSCNum).SolAbsorp;
    1158            0 :         AbsExt = state.dataTranspiredCollector->UTSC(UTSCNum).LWEmitt;
    1159            0 :         TempExt = state.dataTranspiredCollector->UTSC(UTSCNum).TcollLast;
    1160            0 :         for (ThisSurf = 1; ThisSurf <= NumSurfs; ++ThisSurf) {
    1161            0 :             SurfPtr = state.dataTranspiredCollector->UTSC(UTSCNum).SurfPtrs(ThisSurf);
    1162              :             // Initializations for this surface
    1163            0 :             HMovInsul = 0.0;
    1164            0 :             HExt = 0.0;
    1165            0 :             LocalWindArr(ThisSurf) = state.dataSurface->SurfOutWindSpeed(SurfPtr);
    1166            0 :             Convect::InitExtConvCoeff(state,
    1167              :                                       SurfPtr,
    1168              :                                       HMovInsul,
    1169              :                                       Roughness,
    1170              :                                       AbsExt,
    1171              :                                       TempExt,
    1172              :                                       HExt,
    1173            0 :                                       HSkyARR(ThisSurf),
    1174            0 :                                       HGroundARR(ThisSurf),
    1175            0 :                                       HAirARR(ThisSurf),
    1176            0 :                                       HSrdSurfARR(ThisSurf));
    1177            0 :             ConstrNum = state.dataSurface->Surface(SurfPtr).Construction;
    1178            0 :             AbsThermSurf = s_mat->materials(state.dataConstruction->Construct(ConstrNum).LayerPoint(1))->AbsorpThermal;
    1179            0 :             TsoK = state.dataHeatBalSurf->SurfOutsideTempHist(1)(SurfPtr) + Constant::Kelvin;
    1180            0 :             TscollK = state.dataTranspiredCollector->UTSC(UTSCNum).TcollLast + Constant::Kelvin;
    1181            0 :             HPlenARR(ThisSurf) = Sigma * AbsExt * AbsThermSurf * (pow_4(TscollK) - pow_4(TsoK)) / (TscollK - TsoK);
    1182              :         }
    1183              :         //        AreaSum = sum( Surface( UTSC( UTSCNum ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced by below
    1184              :         auto Area = // (AUTO_OK_OBJ)
    1185            0 :             array_sub(state.dataSurface->Surface,
    1186              :                       &SurfaceData::Area,
    1187            0 :                       state.dataTranspiredCollector->UTSC(UTSCNum)
    1188            0 :                           .SurfPtrs); // Autodesk:F2C++ Copy of subscripted Area array for use below: This makes a copy so review wrt performance
    1189            0 :         AreaSum = sum(Area);
    1190              :         // now figure area-weighted averages from underlying surfaces.
    1191              :         //        Vwind = sum( LocalWindArr * Surface( UTSC( UTSCNum ).SurfPtrs ).Area ) / AreaSum; //Autodesk:F2C++ Array subscript usage:
    1192              :         // Replaced by below
    1193            0 :         Vwind = sum(LocalWindArr * Area) / AreaSum;
    1194            0 :         LocalWindArr.deallocate();
    1195              :         //        HrSky = sum( HSkyARR * Surface( UTSC( UTSCNum ).SurfPtrs ).Area ) / AreaSum; //Autodesk:F2C++ Array subscript usage: Replaced
    1196              :         // by  below
    1197            0 :         HrSky = sum(HSkyARR * Area) / AreaSum;
    1198            0 :         HSkyARR.deallocate();
    1199              :         //        HrGround = sum( HGroundARR * Surface( UTSC( UTSCNum ).SurfPtrs ).Area ) / AreaSum; //Autodesk:F2C++ Array subscript usage:
    1200              :         // Replaced by below
    1201            0 :         HrGround = sum(HGroundARR * Area) / AreaSum;
    1202            0 :         HGroundARR.deallocate();
    1203              :         //        HrAtm = sum( HAirARR * Surface( UTSC( UTSCNum ).SurfPtrs ).Area ) / AreaSum; //Autodesk:F2C++ Array subscript usage: Replaced
    1204              :         // by  below
    1205            0 :         HrAtm = sum(HAirARR * Area) / AreaSum;
    1206            0 :         HAirARR.deallocate();
    1207              :         //        HrPlen = sum( HPlenARR * Surface( UTSC( UTSCNum ).SurfPtrs ).Area ) / AreaSum; //Autodesk:F2C++ Array subscript usage:
    1208              :         // Replaced  by below
    1209            0 :         HrPlen = sum(HPlenARR * Area) / AreaSum;
    1210            0 :         HPlenARR.deallocate();
    1211              : 
    1212              :         //        Isc = sum( SurfQRadSWOutIncident( UTSC( UTSCNum ).SurfPtrs ) * Surface( UTSC( UTSCNum ).SurfPtrs ).Area ) / AreaSum;
    1213              :         ////Autodesk:F2C++ Array subscript usage: Replaced by below
    1214            0 :         Isc = sum_product_sub(state.dataHeatBal->SurfQRadSWOutIncident,
    1215            0 :                               state.dataSurface->Surface,
    1216              :                               &SurfaceData::Area,
    1217            0 :                               state.dataTranspiredCollector->UTSC(UTSCNum).SurfPtrs) /
    1218              :               AreaSum; // Autodesk:F2C++ Functions handle array subscript usage
    1219              :         //        Tso = sum( TH( UTSC( UTSCNum ).SurfPtrs, 1, 1 ) * Surface( UTSC( UTSCNum ).SurfPtrs ).Area ) / AreaSum; //Autodesk:F2C++ Array
    1220              :         // subscript usage: Replaced by below
    1221            0 :         Tso = sum_product_sub(state.dataHeatBalSurf->SurfOutsideTempHist(1),
    1222            0 :                               state.dataSurface->Surface,
    1223              :                               &SurfaceData::Area,
    1224            0 :                               state.dataTranspiredCollector->UTSC(UTSCNum).SurfPtrs) /
    1225              :               AreaSum; // Autodesk:F2C++ Functions handle array subscript usage
    1226              : 
    1227            0 :         if (Vwind > 5.0) {
    1228            0 :             HcWind = 5.62 + 3.9 * (Vwind - 5.0); // McAdams forced convection correlation
    1229              :         } else {
    1230            0 :             HcWind = 0.0;
    1231              :         }
    1232              : 
    1233            0 :         if (state.dataEnvrn->IsRain) HcWind = 1000.0;
    1234              : 
    1235            0 :         HXeff = 0.0; // init
    1236              : 
    1237            0 :         switch (state.dataTranspiredCollector->UTSC(UTSCNum).Correlation) {
    1238            0 :         case Correlation_Kutscher1994: { // Kutscher1994
    1239            0 :             AlessHoles = A - holeArea;
    1240              : 
    1241            0 :             NuD = 2.75 * ((std::pow(P / D, -1.2) * std::pow(ReD, 0.43)) + (0.011 * Por * ReD * std::pow(Vwind / Vsuction, 0.48)));
    1242            0 :             U = k * NuD / D;
    1243            0 :             HXeff = 1.0 - std::exp(-1.0 * ((U * AlessHoles) / (Mdot * CpAir)));
    1244            0 :         } break;
    1245            0 :         case Correlation_VanDeckerHollandsBrunger2001: { // VanDeckerHollandsBrunger2001
    1246            0 :             t = state.dataTranspiredCollector->UTSC(UTSCNum).CollectThick;
    1247            0 :             ReS = Vsuction * P / nu;
    1248            0 :             ReW = Vwind * P / nu;
    1249            0 :             ReB = Vholes * P / nu;
    1250            0 :             ReH = (Vsuction * D) / (nu * Por);
    1251            0 :             if (ReD > 0.0) {
    1252            0 :                 if (ReW > 0.0) {
    1253            0 :                     HXeff = (1.0 - std::pow(1.0 + ReS * max(1.733 * std::pow(ReW, -0.5), 0.02136), -1.0)) *
    1254            0 :                             (1.0 - std::pow(1.0 + 0.2273 * std::sqrt(ReB), -1.0)) * std::exp(-0.01895 * (P / D) - (20.62 / ReH) * (t / D));
    1255              :                 } else {
    1256            0 :                     HXeff = (1.0 - std::pow(1.0 + ReS * 0.02136, -1.0)) * (1.0 - std::pow(1.0 + 0.2273 * std::sqrt(ReB), -1.0)) *
    1257            0 :                             std::exp(-0.01895 * (P / D) - (20.62 / ReH) * (t / D));
    1258              :                 }
    1259              :             } else {
    1260            0 :                 HXeff = 0.0;
    1261              :             }
    1262            0 :         } break;
    1263            0 :         default:
    1264            0 :             break;
    1265              :         }
    1266              : 
    1267              :         // now calculate collector temperature
    1268              : 
    1269            0 :         Tscoll = (Isc * SolAbs + HrAtm * Tamb + HrSky * state.dataEnvrn->SkyTemp + HrGround * Tamb + HrPlen * Tso + HcWind * Tamb +
    1270            0 :                   (Mdot * CpAir / A) * Tamb - (Mdot * CpAir / A) * (1.0 - HXeff) * Tamb + QdotSource) /
    1271            0 :                  (HrAtm + HrSky + HrGround + HrPlen + HcWind + (Mdot * CpAir / A) * HXeff);
    1272              : 
    1273              :         // Heat exchanger leaving temperature
    1274            0 :         TaHX = HXeff * Tscoll + (1.0 - HXeff) * Tamb;
    1275              : 
    1276              :         // now calculate plenum air temperature
    1277              : 
    1278            0 :         Taplen = (Mdot * CpAir * TaHX + HcPlen * A * Tso) / (Mdot * CpAir + HcPlen * A);
    1279              : 
    1280              :         // calculate Sensible Heating Rate
    1281            0 :         if (Taplen > Tamb) {
    1282            0 :             SensHeatingRate = Mdot * CpAir * (Taplen - Tamb);
    1283              :         } else {
    1284            0 :             SensHeatingRate = 0.0;
    1285              :         }
    1286              : 
    1287              :         // now fill results into derived types
    1288            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).Isc = Isc;
    1289            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).HXeff = HXeff;
    1290            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).Tplen = Taplen;
    1291            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).Tcoll = Tscoll;
    1292            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).HrPlen = HrPlen;
    1293            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).HcPlen = HcPlen;
    1294            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).TairHX = TaHX;
    1295            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).InletMDot = Mdot;
    1296            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).InletTempDB = Tamb;
    1297            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).Vsuction = Vsuction;
    1298            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).PlenumVelocity = Vplen;
    1299            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SupOutTemp = Taplen;
    1300            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SupOutHumRat = state.dataEnvrn->OutHumRat; // stays the same with sensible heating
    1301            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SupOutEnth =
    1302            0 :             PsyHFnTdbW(state.dataTranspiredCollector->UTSC(UTSCNum).SupOutTemp, state.dataTranspiredCollector->UTSC(UTSCNum).SupOutHumRat);
    1303            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SupOutMassFlow = Mdot;
    1304            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SensHeatingRate = SensHeatingRate;
    1305            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SensHeatingEnergy = SensHeatingRate * TimeStepSysSec;
    1306            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).PassiveACH = 0.0;
    1307            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).PassiveMdotVent = 0.0;
    1308            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).PassiveMdotWind = 0.0;
    1309            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).PassiveMdotTherm = 0.0;
    1310            0 :         if (Isc > 10.0) {
    1311            0 :             state.dataTranspiredCollector->UTSC(UTSCNum).UTSCEfficiency = SensHeatingRate / (Isc * A);
    1312            0 :             if (TaHX > Tamb) {
    1313            0 :                 state.dataTranspiredCollector->UTSC(UTSCNum).UTSCCollEff = Mdot * CpAir * (TaHX - Tamb) / (Isc * A);
    1314              :             } else {
    1315            0 :                 state.dataTranspiredCollector->UTSC(UTSCNum).UTSCCollEff = 0.0;
    1316              :             }
    1317              :         } else {
    1318            0 :             state.dataTranspiredCollector->UTSC(UTSCNum).UTSCEfficiency = 0.0;
    1319            0 :             state.dataTranspiredCollector->UTSC(UTSCNum).UTSCCollEff = 0.0;
    1320              :         }
    1321            0 :     }
    1322              : 
    1323            0 :     void CalcPassiveTranspiredCollector(EnergyPlusData &state, int const UTSCNum)
    1324              :     {
    1325              : 
    1326              :         // SUBROUTINE INFORMATION:
    1327              :         //       AUTHOR         B.T. Griffith
    1328              :         //       DATE WRITTEN   November 2004
    1329              :         //       MODIFIED       na
    1330              :         //       RE-ENGINEERED  na
    1331              : 
    1332              :         // PURPOSE OF THIS SUBROUTINE:
    1333              :         // model the effect of the a ventilated baffle covering the outside of a heat transfer surface.
    1334              : 
    1335              :         // METHODOLOGY EMPLOYED:
    1336              :         // All the work is done in a subroutine .
    1337              : 
    1338              :         // REFERENCES:
    1339              :         // Nat. Vent. equations from ASHRAE HoF 2001 Chapt. 26
    1340              : 
    1341              :         // Using/Aliasing
    1342              :         using DataSurfaces::SurfaceData;
    1343              :         using Psychrometrics::PsyHFnTdbW;
    1344              :         using Psychrometrics::PsyRhoAirFnPbTdbW;
    1345              :         using Psychrometrics::PsyWFnTdbTwbPb;
    1346              : 
    1347              :         // local working variables
    1348              :         Real64 AspRat; // Aspect Ratio of gap
    1349              :         Real64 TmpTscoll;
    1350              :         Real64 TmpTaPlen;
    1351              :         Real64 RhoAir;
    1352              :         Real64 holeArea;
    1353              :         Real64 Tamb;
    1354              :         Real64 HrPlen;
    1355              :         Real64 HcPlen;
    1356              :         Real64 Isc;
    1357              :         Real64 MdotVent;
    1358              :         Real64 VdotWind;
    1359              :         Real64 VdotThermal;
    1360              :         Real64 Twbamb;
    1361              :         Real64 OutHumRatAmb;
    1362              : 
    1363              :         //        Tamb = sum( Surface( UTSC( UTSCNum ).SurfPtrs ).OutDryBulbTemp * Surface( UTSC( UTSCNum ).SurfPtrs ).Area ) / sum( Surface(
    1364              :         // UTSC( UTSCNum ).SurfPtrs ).Area ); //Autodesk:F2C++ Array subscript usage: Replaced by below
    1365            0 :         Real64 sum_area = 0.0;
    1366            0 :         Real64 sum_produc_area_drybulb = 0.0;
    1367            0 :         Real64 sum_produc_area_wetbulb = 0.0;
    1368            0 :         for (int SurfNum : state.dataTranspiredCollector->UTSC(UTSCNum).SurfPtrs) {
    1369            0 :             sum_area += state.dataSurface->Surface(SurfNum).Area;
    1370            0 :             sum_produc_area_wetbulb += state.dataSurface->Surface(SurfNum).Area * state.dataSurface->SurfOutWetBulbTemp(SurfNum);
    1371            0 :             sum_produc_area_drybulb += state.dataSurface->Surface(SurfNum).Area * state.dataSurface->SurfOutDryBulbTemp(SurfNum);
    1372              :         }
    1373            0 :         Tamb = sum_produc_area_drybulb / sum_area;
    1374            0 :         Twbamb = sum_produc_area_wetbulb / sum_area;
    1375              : 
    1376            0 :         OutHumRatAmb = PsyWFnTdbTwbPb(state, Tamb, Twbamb, state.dataEnvrn->OutBaroPress);
    1377              : 
    1378            0 :         RhoAir = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, Tamb, OutHumRatAmb);
    1379            0 :         holeArea = state.dataTranspiredCollector->UTSC(UTSCNum).ActualArea * state.dataTranspiredCollector->UTSC(UTSCNum).Porosity;
    1380              : 
    1381            0 :         AspRat = state.dataTranspiredCollector->UTSC(UTSCNum).Height / state.dataTranspiredCollector->UTSC(UTSCNum).PlenGapThick;
    1382            0 :         TmpTscoll = state.dataTranspiredCollector->UTSC(UTSCNum).TcollLast;
    1383            0 :         TmpTaPlen = state.dataTranspiredCollector->UTSC(UTSCNum).TplenLast;
    1384              : 
    1385              :         // all the work is done in this routine located in GeneralRoutines.cc
    1386              : 
    1387            0 :         CalcPassiveExteriorBaffleGap(state,
    1388            0 :                                      state.dataTranspiredCollector->UTSC(UTSCNum).SurfPtrs,
    1389              :                                      holeArea,
    1390            0 :                                      state.dataTranspiredCollector->UTSC(UTSCNum).Cv,
    1391            0 :                                      state.dataTranspiredCollector->UTSC(UTSCNum).Cd,
    1392            0 :                                      state.dataTranspiredCollector->UTSC(UTSCNum).HdeltaNPL,
    1393            0 :                                      state.dataTranspiredCollector->UTSC(UTSCNum).SolAbsorp,
    1394            0 :                                      state.dataTranspiredCollector->UTSC(UTSCNum).LWEmitt,
    1395            0 :                                      state.dataTranspiredCollector->UTSC(UTSCNum).Tilt,
    1396              :                                      AspRat,
    1397            0 :                                      state.dataTranspiredCollector->UTSC(UTSCNum).PlenGapThick,
    1398            0 :                                      state.dataTranspiredCollector->UTSC(UTSCNum).CollRoughness,
    1399            0 :                                      state.dataTranspiredCollector->UTSC(UTSCNum).QdotSource,
    1400              :                                      TmpTscoll,
    1401              :                                      TmpTaPlen,
    1402              :                                      HcPlen,
    1403              :                                      HrPlen,
    1404              :                                      Isc,
    1405              :                                      MdotVent,
    1406              :                                      VdotWind,
    1407              :                                      VdotThermal);
    1408              : 
    1409              :         // now fill results into derived types
    1410            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).Isc = Isc;
    1411            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).Tplen = TmpTaPlen;
    1412            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).Tcoll = TmpTscoll;
    1413            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).HrPlen = HrPlen;
    1414            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).HcPlen = HcPlen;
    1415            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).TairHX = Tamb;
    1416            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).InletMDot = 0.0;
    1417            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).InletTempDB = Tamb;
    1418            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).Vsuction = 0.0;
    1419            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).PlenumVelocity = 0.0;
    1420            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SupOutTemp = TmpTaPlen;
    1421            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SupOutHumRat = OutHumRatAmb;
    1422            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SupOutEnth = PsyHFnTdbW(TmpTaPlen, OutHumRatAmb);
    1423            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SupOutMassFlow = 0.0;
    1424            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SensHeatingRate = 0.0;
    1425            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).SensHeatingEnergy = 0.0;
    1426            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).PassiveACH =
    1427            0 :             (MdotVent / RhoAir) *
    1428            0 :             (1.0 / (state.dataTranspiredCollector->UTSC(UTSCNum).ProjArea * state.dataTranspiredCollector->UTSC(UTSCNum).PlenGapThick)) *
    1429              :             Constant::rSecsInHour;
    1430            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).PassiveMdotVent = MdotVent;
    1431            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).PassiveMdotWind = VdotWind * RhoAir;
    1432            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).PassiveMdotTherm = VdotThermal * RhoAir;
    1433            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).UTSCEfficiency = 0.0;
    1434            0 :     }
    1435              : 
    1436            0 :     void UpdateTranspiredCollector(EnergyPlusData &state, int const UTSCNum)
    1437              :     {
    1438              : 
    1439              :         // SUBROUTINE INFORMATION:
    1440              :         //       AUTHOR         B.T. Griffith
    1441              :         //       DATE WRITTEN   November 2004
    1442              :         //       MODIFIED       na
    1443              :         //       RE-ENGINEERED  na
    1444              : 
    1445              :         int OutletNode;
    1446              :         int InletNode;
    1447              :         int thisOSCM;
    1448              :         int thisOASys;
    1449              : 
    1450              :         // update "last" values in Derived type
    1451            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).TplenLast = state.dataTranspiredCollector->UTSC(UTSCNum).Tplen;
    1452            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).TcollLast = state.dataTranspiredCollector->UTSC(UTSCNum).Tcoll;
    1453              : 
    1454              :         // Set the outlet air nodes of the UTSC
    1455              : 
    1456            0 :         if (state.dataTranspiredCollector->UTSC(UTSCNum).IsOn) { // Active
    1457            0 :             if (state.dataTranspiredCollector->UTSC(UTSCNum).NumOASysAttached == 1) {
    1458            0 :                 OutletNode = state.dataTranspiredCollector->UTSC(UTSCNum).OutletNode(1);
    1459            0 :                 InletNode = state.dataTranspiredCollector->UTSC(UTSCNum).InletNode(1);
    1460            0 :                 state.dataLoopNodes->Node(OutletNode).MassFlowRate = state.dataTranspiredCollector->UTSC(UTSCNum).SupOutMassFlow;
    1461            0 :                 state.dataLoopNodes->Node(OutletNode).Temp = state.dataTranspiredCollector->UTSC(UTSCNum).SupOutTemp;
    1462            0 :                 state.dataLoopNodes->Node(OutletNode).HumRat = state.dataTranspiredCollector->UTSC(UTSCNum).SupOutHumRat;
    1463            0 :                 state.dataLoopNodes->Node(OutletNode).Enthalpy = state.dataTranspiredCollector->UTSC(UTSCNum).SupOutEnth;
    1464            0 :             } else if (state.dataTranspiredCollector->UTSC(UTSCNum).NumOASysAttached > 1) {
    1465            0 :                 for (thisOASys = 1; thisOASys <= state.dataTranspiredCollector->UTSC(UTSCNum).NumOASysAttached; ++thisOASys) {
    1466            0 :                     state.dataLoopNodes->Node(state.dataTranspiredCollector->UTSC(UTSCNum).OutletNode(thisOASys)).MassFlowRate =
    1467            0 :                         state.dataLoopNodes->Node(state.dataTranspiredCollector->UTSC(UTSCNum).InletNode(thisOASys))
    1468            0 :                             .MassFlowRate; // system gets what it asked for at inlet
    1469            0 :                     state.dataLoopNodes->Node(state.dataTranspiredCollector->UTSC(UTSCNum).OutletNode(thisOASys)).Temp =
    1470            0 :                         state.dataTranspiredCollector->UTSC(UTSCNum).SupOutTemp;
    1471            0 :                     state.dataLoopNodes->Node(state.dataTranspiredCollector->UTSC(UTSCNum).OutletNode(thisOASys)).HumRat =
    1472            0 :                         state.dataTranspiredCollector->UTSC(UTSCNum).SupOutHumRat;
    1473            0 :                     state.dataLoopNodes->Node(state.dataTranspiredCollector->UTSC(UTSCNum).OutletNode(thisOASys)).Enthalpy =
    1474            0 :                         state.dataTranspiredCollector->UTSC(UTSCNum).SupOutEnth;
    1475              :                 }
    1476              :             }
    1477              :         } else { // Passive and/or bypassed           Note Array assignments in following
    1478              :                  // Autodesk:F2C++ Array subscript usage: Replaced by below
    1479              :             //            Node( UTSC( UTSCNum ).OutletNode ).MassFlowRate = Node( UTSC( UTSCNum ).InletNode ).MassFlowRate;
    1480              :             //            Node( UTSC( UTSCNum ).OutletNode ).Temp = Node( UTSC( UTSCNum ).InletNode ).Temp;
    1481              :             //            Node( UTSC( UTSCNum ).OutletNode ).HumRat = Node( UTSC( UTSCNum ).InletNode ).HumRat;
    1482              :             //            Node( UTSC( UTSCNum ).OutletNode ).Enthalpy = Node( UTSC( UTSCNum ).InletNode ).Enthalpy;
    1483            0 :             auto const &OutletNode = state.dataTranspiredCollector->UTSC(UTSCNum).OutletNode;
    1484            0 :             auto const &InletNode = state.dataTranspiredCollector->UTSC(UTSCNum).InletNode;
    1485            0 :             assert(OutletNode.size() == InletNode.size());
    1486            0 :             for (int io = OutletNode.l(), ii = InletNode.l(), eo = OutletNode.u(); io <= eo; ++io, ++ii) {
    1487            0 :                 auto &outNode = state.dataLoopNodes->Node(OutletNode(io));
    1488            0 :                 auto const &inNode = state.dataLoopNodes->Node(InletNode(ii));
    1489            0 :                 outNode.MassFlowRate = inNode.MassFlowRate;
    1490            0 :                 outNode.Temp = inNode.Temp;
    1491            0 :                 outNode.HumRat = inNode.HumRat;
    1492            0 :                 outNode.Enthalpy = inNode.Enthalpy;
    1493              :             }
    1494              :         }
    1495              : 
    1496              :         // update the OtherSideConditionsModel coefficients.
    1497            0 :         thisOSCM = state.dataTranspiredCollector->UTSC(UTSCNum).OSCMPtr;
    1498              : 
    1499            0 :         state.dataSurface->OSCM(thisOSCM).TConv = state.dataTranspiredCollector->UTSC(UTSCNum).Tplen;
    1500            0 :         state.dataSurface->OSCM(thisOSCM).HConv = state.dataTranspiredCollector->UTSC(UTSCNum).HcPlen;
    1501            0 :         state.dataSurface->OSCM(thisOSCM).TRad = state.dataTranspiredCollector->UTSC(UTSCNum).Tcoll;
    1502            0 :         state.dataSurface->OSCM(thisOSCM).HRad = state.dataTranspiredCollector->UTSC(UTSCNum).HrPlen;
    1503            0 :     }
    1504              : 
    1505            0 :     void SetUTSCQdotSource(EnergyPlusData &state,
    1506              :                            int const UTSCNum,
    1507              :                            Real64 const QSource // source term in Watts
    1508              :     )
    1509              :     {
    1510              : 
    1511              :         // SUBROUTINE INFORMATION:
    1512              :         //       AUTHOR         B. Griffith
    1513              :         //       DATE WRITTEN   November 2004
    1514              :         //       MODIFIED       na
    1515              :         //       RE-ENGINEERED  na
    1516              : 
    1517              :         // PURPOSE OF THIS SUBROUTINE:
    1518              :         // object oriented "Set" routine for updating sink term without exposing variables
    1519              : 
    1520              :         // METHODOLOGY EMPLOYED:
    1521              :         // update derived type with new data , turn power into W/m2
    1522              : 
    1523            0 :         state.dataTranspiredCollector->UTSC(UTSCNum).QdotSource = QSource / state.dataTranspiredCollector->UTSC(UTSCNum).ProjArea;
    1524            0 :     }
    1525              : 
    1526            0 :     void GetTranspiredCollectorIndex(EnergyPlusData &state, int const SurfacePtr, int &UTSCIndex)
    1527              :     {
    1528              : 
    1529              :         // SUBROUTINE INFORMATION:
    1530              :         //       AUTHOR         B. Griffith
    1531              :         //       DATE WRITTEN   November 2004
    1532              :         //       MODIFIED       na
    1533              :         //       RE-ENGINEERED  na
    1534              : 
    1535              :         // PURPOSE OF THIS SUBROUTINE:
    1536              :         // object oriented "Get" routine for establishing correct integer index from outside this module
    1537              : 
    1538              :         // METHODOLOGY EMPLOYED:
    1539              :         // mine Surface derived type for correct index/number of surface
    1540              :         // mine UTSC derived type that has the surface.
    1541              : 
    1542              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1543              :         int UTSCNum;  // temporary
    1544              :         int ThisSurf; // temporary
    1545              :         int thisUTSC;
    1546              :         bool Found;
    1547              : 
    1548            0 :         if (state.dataTranspiredCollector->GetInputFlag) {
    1549            0 :             GetTranspiredCollectorInput(state);
    1550            0 :             state.dataTranspiredCollector->GetInputFlag = false;
    1551              :         }
    1552              : 
    1553            0 :         if (SurfacePtr == 0) {
    1554            0 :             ShowFatalError(
    1555              :                 state,
    1556            0 :                 format("Invalid surface passed to GetTranspiredCollectorIndex, Surface name = {}", state.dataSurface->Surface(SurfacePtr).Name));
    1557              :         }
    1558              : 
    1559            0 :         UTSCNum = 0;
    1560            0 :         Found = false;
    1561            0 :         for (thisUTSC = 1; thisUTSC <= state.dataTranspiredCollector->NumUTSC; ++thisUTSC) {
    1562            0 :             for (ThisSurf = 1; ThisSurf <= state.dataTranspiredCollector->UTSC(thisUTSC).NumSurfs; ++ThisSurf) {
    1563            0 :                 if (SurfacePtr == state.dataTranspiredCollector->UTSC(thisUTSC).SurfPtrs(ThisSurf)) {
    1564            0 :                     Found = true;
    1565            0 :                     UTSCNum = thisUTSC;
    1566              :                 }
    1567              :             }
    1568              :         }
    1569              : 
    1570            0 :         if (!Found) {
    1571            0 :             ShowFatalError(state,
    1572            0 :                            format("Did not find surface in UTSC description in GetTranspiredCollectorIndex, Surface name = {}",
    1573            0 :                                   state.dataSurface->Surface(SurfacePtr).Name));
    1574              :         } else {
    1575              : 
    1576            0 :             UTSCIndex = UTSCNum;
    1577              :         }
    1578            0 :     }
    1579              : 
    1580            0 :     void GetUTSCTsColl(EnergyPlusData &state, int const UTSCNum, Real64 &TsColl)
    1581              :     {
    1582              : 
    1583              :         // SUBROUTINE INFORMATION:
    1584              :         //       AUTHOR         <author>
    1585              :         //       DATE WRITTEN   <date_written>
    1586              :         //       MODIFIED       na
    1587              :         //       RE-ENGINEERED  na
    1588              : 
    1589              :         // PURPOSE OF THIS SUBROUTINE:
    1590              :         // object oriented "Get" routine for collector surface temperature
    1591              : 
    1592              :         // METHODOLOGY EMPLOYED:
    1593              :         // access derived type
    1594              : 
    1595            0 :         TsColl = state.dataTranspiredCollector->UTSC(UTSCNum).Tcoll;
    1596            0 :     }
    1597              : 
    1598            0 :     int GetAirInletNodeNum(EnergyPlusData &state, std::string const &UTSCName, bool &ErrorsFound)
    1599              :     {
    1600              :         // FUNCTION INFORMATION:
    1601              :         //       AUTHOR         Lixing Gu
    1602              :         //       DATE WRITTEN   May 2019
    1603              :         //       MODIFIED       na
    1604              :         //       RE-ENGINEERED  na
    1605              : 
    1606              :         // PURPOSE OF THIS FUNCTION:
    1607              :         // This function looks up the given UTSC and returns the air inlet node number.
    1608              :         // If incorrect UTSC name is given, ErrorsFound is returned as true and node number as zero.
    1609              : 
    1610              :         // Return value
    1611              :         int NodeNum; // node number returned
    1612              : 
    1613              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    1614              :         int WhichUTSC;
    1615              : 
    1616            0 :         if (state.dataTranspiredCollector->GetInputFlag) {
    1617            0 :             GetTranspiredCollectorInput(state);
    1618            0 :             state.dataTranspiredCollector->GetInputFlag = false;
    1619              :         }
    1620              : 
    1621            0 :         WhichUTSC = Util::FindItemInList(UTSCName, state.dataTranspiredCollector->UTSC);
    1622            0 :         if (WhichUTSC != 0) {
    1623            0 :             NodeNum = state.dataTranspiredCollector->UTSC(WhichUTSC).InletNode(1);
    1624              :         } else {
    1625            0 :             ShowSevereError(state, format("GetAirInletNodeNum: Could not find TranspiredCollector = \"{}\"", UTSCName));
    1626            0 :             ErrorsFound = true;
    1627            0 :             NodeNum = 0;
    1628              :         }
    1629              : 
    1630            0 :         return NodeNum;
    1631              :     }
    1632              : 
    1633            0 :     int GetAirOutletNodeNum(EnergyPlusData &state, std::string const &UTSCName, bool &ErrorsFound)
    1634              :     {
    1635              :         // FUNCTION INFORMATION:
    1636              :         //       AUTHOR         Lixing Gu
    1637              :         //       DATE WRITTEN   May 2019
    1638              :         //       MODIFIED       na
    1639              :         //       RE-ENGINEERED  na
    1640              : 
    1641              :         // PURPOSE OF THIS FUNCTION:
    1642              :         // This function looks up the given UTSC and returns the air outlet node number.
    1643              :         // If incorrect UTSC name is given, ErrorsFound is returned as true and node number as zero.
    1644              : 
    1645              :         // Return value
    1646              :         int NodeNum; // node number returned
    1647              : 
    1648              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    1649              :         int WhichUTSC;
    1650              : 
    1651            0 :         if (state.dataTranspiredCollector->GetInputFlag) {
    1652            0 :             GetTranspiredCollectorInput(state);
    1653            0 :             state.dataTranspiredCollector->GetInputFlag = false;
    1654              :         }
    1655              : 
    1656            0 :         WhichUTSC = Util::FindItemInList(UTSCName, state.dataTranspiredCollector->UTSC);
    1657            0 :         if (WhichUTSC != 0) {
    1658            0 :             NodeNum = state.dataTranspiredCollector->UTSC(WhichUTSC).OutletNode(1);
    1659              :         } else {
    1660            0 :             ShowSevereError(state, format("GetAirOutletNodeNum: Could not find TranspiredCollector = \"{}\"", UTSCName));
    1661            0 :             ErrorsFound = true;
    1662            0 :             NodeNum = 0;
    1663              :         }
    1664              : 
    1665            0 :         return NodeNum;
    1666              :     }
    1667              : 
    1668            1 :     void CalcPassiveExteriorBaffleGap(EnergyPlusData &state,
    1669              :                                       const Array1D_int &SurfPtrARR, // Array of indexes pointing to Surface structure in DataSurfaces
    1670              :                                       Real64 const VentArea,         // Area available for venting the gap [m2]
    1671              :                                       Real64 const Cv,               // Orifice coefficient for volume-based discharge, wind-driven [--]
    1672              :                                       Real64 const Cd,               // Orifice coefficient for discharge,  buoyancy-driven [--]
    1673              :                                       Real64 const HdeltaNPL,        // Height difference from neutral pressure level [m]
    1674              :                                       Real64 const SolAbs,           // solar absorptivity of baffle [--]
    1675              :                                       Real64 const AbsExt,           // thermal absorptance/emittance of baffle material [--]
    1676              :                                       Real64 const Tilt,             // Tilt of gap [Degrees]
    1677              :                                       Real64 const AspRat,           // aspect ratio of gap  Height/gap [--]
    1678              :                                       Real64 const GapThick,         // Thickness of air space between baffle and underlying heat transfer surface
    1679              :                                       Material::SurfaceRoughness const Roughness, // Roughness index (1-6), see DataHeatBalance parameters
    1680              :                                       Real64 const QdotSource,                    // Source/sink term, e.g. electricity exported from solar cell [W]
    1681              :                                       Real64 &TsBaffle,                           // Temperature of baffle (both sides) use lagged value on input [C]
    1682              :                                       Real64 &TaGap, // Temperature of air gap (assumed mixed) use lagged value on input [C]
    1683              :                                       ObjexxFCL::Optional<Real64> HcGapRpt,
    1684              :                                       ObjexxFCL::Optional<Real64> HrGapRpt,
    1685              :                                       ObjexxFCL::Optional<Real64> IscRpt,
    1686              :                                       ObjexxFCL::Optional<Real64> MdotVentRpt,
    1687              :                                       ObjexxFCL::Optional<Real64> VdotWindRpt,
    1688              :                                       ObjexxFCL::Optional<Real64> VdotBuoyRpt)
    1689              :     {
    1690              : 
    1691              :         // SUBROUTINE INFORMATION:
    1692              :         //       AUTHOR         B.T. Griffith
    1693              :         //       DATE WRITTEN   November 2004
    1694              :         //       MODIFIED       BG March 2007 outdoor conditions from surface for height-dependent conditions
    1695              : 
    1696              :         // PURPOSE OF THIS SUBROUTINE:
    1697              :         // model the effect of the a ventilated baffle covering the outside of a heat transfer surface.
    1698              :         // return calculated temperatures and certain intermediate values for reporting
    1699              : 
    1700              :         // METHODOLOGY EMPLOYED:
    1701              :         // Heat balances on baffle and air space.
    1702              :         // Natural ventilation calculations use buoyancy and wind.
    1703              : 
    1704              :         // REFERENCES:
    1705              :         // Nat. Vent. equations from ASHRAE HoF 2001 Chapt. 26
    1706              : 
    1707              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1708            1 :         Real64 constexpr g = 9.807;          // gravitational constant (m/s**2)
    1709            1 :         Real64 constexpr nu = 15.66e-6;      // kinematic viscosity (m**2/s) for air at 300 K (Mills 1999 Heat Transfer)
    1710            1 :         Real64 constexpr k = 0.0267;         // thermal conductivity (W/m K) for air at 300 K (Mills 1999 Heat Transfer)
    1711            1 :         Real64 constexpr Sigma = 5.6697e-08; // Stefan-Boltzmann constant
    1712              :         static constexpr std::string_view RoutineName = "CalcPassiveExteriorBaffleGap";
    1713              :         // INTERFACE BLOCK SPECIFICATIONS:
    1714              : 
    1715              :         // DERIVED TYPE DEFINITIONS:
    1716              : 
    1717              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1718              : 
    1719              :         // following arrays are used to temporarily hold results from multiple underlying surfaces
    1720            1 :         Array1D<Real64> HSkyARR;
    1721            1 :         Array1D<Real64> HGroundARR;
    1722            1 :         Array1D<Real64> HAirARR;
    1723            1 :         Array1D<Real64> HPlenARR;
    1724            1 :         Array1D<Real64> HExtARR;
    1725            1 :         Array1D<Real64> LocalWindArr;
    1726            1 :         Array1D<Real64> HSrdSurfARR;
    1727              : 
    1728              :         // local working variables
    1729              :         Real64 Tamb;                  // outdoor drybulb
    1730              :         Real64 VdotThermal;           // Volume flow rate of nat. vent due to buoyancy
    1731              :         Real64 LocalOutDryBulbTemp;   // OutDryBulbTemp for here
    1732              :         Real64 LocalWetBulbTemp;      // OutWetBulbTemp for here
    1733              :         Real64 LocalOutHumRat;        // OutHumRat for here
    1734            1 :         bool ICSCollectorIsOn(false); // ICS collector has OSCM on
    1735              :         int CollectorNum;             // current solar collector index
    1736              :         Real64 ICSWaterTemp;          // ICS solar collector water temp
    1737              :         Real64 ICSULossbottom;        // ICS solar collector bottom loss Conductance
    1738            1 :         Real64 sum_area = 0.0;
    1739            1 :         Real64 sum_produc_area_drybulb = 0.0;
    1740            1 :         Real64 sum_produc_area_wetbulb = 0.0;
    1741              : 
    1742            1 :         auto &s_mat = state.dataMaterial;
    1743              : 
    1744            2 :         for (int SurfNum : SurfPtrARR) {
    1745            1 :             sum_area += state.dataSurface->Surface(SurfNum).Area;
    1746            1 :             sum_produc_area_drybulb += state.dataSurface->Surface(SurfNum).Area * state.dataSurface->SurfOutDryBulbTemp(SurfNum);
    1747            1 :             sum_produc_area_wetbulb += state.dataSurface->Surface(SurfNum).Area * state.dataSurface->SurfOutWetBulbTemp(SurfNum);
    1748              :         }
    1749              :         //    LocalOutDryBulbTemp = sum( Surface( SurfPtrARR ).Area * Surface( SurfPtrARR ).OutDryBulbTemp ) / sum( Surface( SurfPtrARR ).Area );
    1750            1 :         LocalOutDryBulbTemp = sum_produc_area_drybulb / sum_area; // Autodesk:F2C++ Functions handle array subscript usage
    1751              :         //    LocalWetBulbTemp = sum( Surface( SurfPtrARR ).Area * Surface( SurfPtrARR ).OutWetBulbTemp ) / sum( Surface( SurfPtrARR ).Area );
    1752            1 :         LocalWetBulbTemp = sum_produc_area_wetbulb / sum_area;
    1753              : 
    1754            1 :         LocalOutHumRat = Psychrometrics::PsyWFnTdbTwbPb(state, LocalOutDryBulbTemp, LocalWetBulbTemp, state.dataEnvrn->OutBaroPress, RoutineName);
    1755              : 
    1756            1 :         Real64 RhoAir = Psychrometrics::PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, LocalOutDryBulbTemp, LocalOutHumRat, RoutineName);
    1757            1 :         Real64 CpAir = Psychrometrics::PsyCpAirFnW(LocalOutHumRat);
    1758            1 :         if (!state.dataEnvrn->IsRain) {
    1759            1 :             Tamb = LocalOutDryBulbTemp;
    1760              :         } else { // when raining we use wetbulb not drybulb
    1761            0 :             Tamb = LocalWetBulbTemp;
    1762              :         }
    1763            1 :         Real64 A = sum_area;        // projected area of baffle from sum of underlying surfaces
    1764            1 :         Real64 TmpTsBaf = TsBaffle; // baffle temperature
    1765              : 
    1766              :         // loop through underlying surfaces and collect needed data
    1767            1 :         int NumSurfs = size(SurfPtrARR); // number of underlying HT surfaces associated with UTSC
    1768            1 :         HSkyARR.dimension(NumSurfs, 0.0);
    1769            1 :         HGroundARR.dimension(NumSurfs, 0.0);
    1770            1 :         HAirARR.dimension(NumSurfs, 0.0);
    1771            1 :         LocalWindArr.dimension(NumSurfs, 0.0);
    1772            1 :         HPlenARR.dimension(NumSurfs, 0.0);
    1773            1 :         HExtARR.dimension(NumSurfs, 0.0);
    1774            1 :         HSrdSurfARR.dimension(NumSurfs, 0.0);
    1775              : 
    1776            2 :         for (int ThisSurf = 1; ThisSurf <= NumSurfs; ++ThisSurf) {
    1777            1 :             int SurfPtr = SurfPtrARR(ThisSurf);
    1778              :             // Initializations for this surface
    1779            1 :             Real64 HMovInsul = 0.0;
    1780            1 :             LocalWindArr(ThisSurf) = state.dataSurface->SurfOutWindSpeed(SurfPtr);
    1781            1 :             Convect::InitExtConvCoeff(state,
    1782              :                                       SurfPtr,
    1783              :                                       HMovInsul,
    1784              :                                       Roughness,
    1785              :                                       AbsExt,
    1786              :                                       TmpTsBaf,
    1787            1 :                                       HExtARR(ThisSurf),
    1788            1 :                                       HSkyARR(ThisSurf),
    1789            1 :                                       HGroundARR(ThisSurf),
    1790            1 :                                       HAirARR(ThisSurf),
    1791            1 :                                       HSrdSurfARR(ThisSurf));
    1792            1 :             int ConstrNum = state.dataSurface->Surface(SurfPtr).Construction;
    1793            1 :             Real64 AbsThermSurf = s_mat->materials(state.dataConstruction->Construct(ConstrNum).LayerPoint(1))->AbsorpThermal;
    1794            1 :             Real64 TsoK = state.dataHeatBalSurf->SurfOutsideTempHist(1)(SurfPtr) + Constant::Kelvin;
    1795            1 :             Real64 TsBaffK = TmpTsBaf + Constant::Kelvin;
    1796            1 :             if (TsBaffK == TsoK) {        // avoid divide by zero
    1797            0 :                 HPlenARR(ThisSurf) = 0.0; // no net heat transfer if same temperature
    1798              :             } else {
    1799            1 :                 HPlenARR(ThisSurf) = Sigma * AbsExt * AbsThermSurf * (pow_4(TsBaffK) - pow_4(TsoK)) / (TsBaffK - TsoK);
    1800              :             }
    1801              :             // Added for ICS collector OSCM
    1802            1 :             if (state.dataSurface->SurfIsICS(SurfPtr)) {
    1803            1 :                 ICSCollectorIsOn = true;
    1804            1 :                 CollectorNum = state.dataSurface->SurfICSPtr(SurfPtr);
    1805              :             }
    1806              :         }
    1807              : 
    1808            1 :         if (ICSCollectorIsOn) {
    1809            1 :             if (state.dataGlobal->BeginEnvrnFlag && state.dataGeneralRoutines->MyICSEnvrnFlag) {
    1810            1 :                 ICSULossbottom = 0.40;
    1811            1 :                 ICSWaterTemp = 20.0;
    1812              :             } else {
    1813            0 :                 if (!state.dataSolarCollectors->Collector.allocated()) {
    1814            0 :                     ICSULossbottom = 0.40;
    1815            0 :                     ICSWaterTemp = 20.0;
    1816              :                 } else {
    1817            0 :                     ICSULossbottom = state.dataSolarCollectors->Collector(CollectorNum).UbLoss;
    1818            0 :                     ICSWaterTemp = state.dataSolarCollectors->Collector(CollectorNum).TempOfWater;
    1819            0 :                     state.dataGeneralRoutines->MyICSEnvrnFlag = false;
    1820              :                 }
    1821              :             }
    1822              :         }
    1823            1 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    1824            0 :             state.dataGeneralRoutines->MyICSEnvrnFlag = true;
    1825              :         }
    1826              :         if (A == 0.0) { // should have been caught earlier
    1827              :         }
    1828              :         Array1D<Real64> Area(
    1829            1 :             array_sub(state.dataSurface->Surface,
    1830              :                       &DataSurfaces::SurfaceData::Area,
    1831            1 :                       SurfPtrARR)); // Autodesk:F2C++ Copy of subscripted Area array for use below: This makes a copy so review wrt performance
    1832              :         // now figure area-weighted averages from underlying surfaces.
    1833            1 :         Real64 Vwind = sum(LocalWindArr * Area) / A; // area weighted average of wind velocity
    1834            1 :         LocalWindArr.deallocate();
    1835            1 :         Real64 HrSky = sum(HSkyARR * Area) / A; // radiation coeff for sky, area-weighted average
    1836            1 :         HSkyARR.deallocate();
    1837            1 :         Real64 HrGround = sum(HGroundARR * Area) / A; // radiation coeff for ground, area-weighted average
    1838            1 :         HGroundARR.deallocate();
    1839            1 :         Real64 HrAtm = sum(HAirARR * Area) / A; // radiation coeff for air (bulk atmosphere), area-weighted average
    1840            1 :         HAirARR.deallocate();
    1841            1 :         Real64 HrPlen = sum(HPlenARR * Area) / A; // radiation coeff for plenum surfaces, area-weighted average
    1842            1 :         HPlenARR.deallocate();
    1843            1 :         Real64 HExt = sum(HExtARR * Area) / A; // dummy for call to InitExteriorConvectionCoeff
    1844            1 :         HExtARR.deallocate();
    1845            1 :         HSrdSurfARR.deallocate();
    1846              : 
    1847            1 :         if (state.dataEnvrn->IsRain) HExt = 1000.0;
    1848              : 
    1849              :         // temperature of underlying surface, area-weighted average
    1850              :         Real64 Tso =
    1851            1 :             sum_product_sub(state.dataHeatBalSurf->SurfOutsideTempHist(1), state.dataSurface->Surface, &DataSurfaces::SurfaceData::Area, SurfPtrARR) /
    1852            1 :             A;
    1853              :         // Incoming combined solar radiation, area-weighted average
    1854              :         Real64 Isc =
    1855            1 :             sum_product_sub(state.dataHeatBal->SurfQRadSWOutIncident, state.dataSurface->Surface, &DataSurfaces::SurfaceData::Area, SurfPtrARR) / A;
    1856              :         // average of surface temps , for Beta in Grashoff no.
    1857            1 :         Real64 TmeanK = 0.5 * (TmpTsBaf + Tso) + Constant::Kelvin;
    1858              :         // Grasshof number for natural convection calc
    1859            1 :         Real64 Gr = g * pow_3(GapThick) * std::abs(Tso - TmpTsBaf) * pow_2(RhoAir) / (TmeanK * pow_2(nu));
    1860              : 
    1861            1 :         Real64 NuPlen = PassiveGapNusseltNumber(AspRat, Tilt, TmpTsBaf, Tso, Gr); // intentionally switch Tso to Tsi
    1862            1 :         Real64 HcPlen = NuPlen * (k / GapThick);                                  // surface convection heat transfer coefficient for plenum surfaces
    1863              : 
    1864              :         // now model natural ventilation of plenum gap.
    1865            1 :         Real64 VdotWind = Cv * (VentArea / 2.0) * Vwind; // volume flow rate of nat. vent due to wind
    1866              : 
    1867            1 :         if (TaGap > Tamb) {
    1868            1 :             VdotThermal = Cd * (VentArea / 2.0) * std::sqrt(2.0 * g * HdeltaNPL * (TaGap - Tamb) / (TaGap + Constant::Kelvin));
    1869            0 :         } else if (TaGap == Tamb) {
    1870            0 :             VdotThermal = 0.0;
    1871              :         } else {
    1872            0 :             if ((std::abs(Tilt) < 5.0) || (std::abs(Tilt - 180.0) < 5.0)) {
    1873            0 :                 VdotThermal = 0.0; // stable buoyancy situation
    1874              :             } else {
    1875            0 :                 VdotThermal = Cd * (VentArea / 2.0) * std::sqrt(2.0 * g * HdeltaNPL * (Tamb - TaGap) / (Tamb + Constant::Kelvin));
    1876              :             }
    1877              :         }
    1878              : 
    1879            1 :         Real64 VdotVent = VdotWind + VdotThermal; // total volume flow rate of nat vent
    1880            1 :         Real64 MdotVent = VdotVent * RhoAir;      // total mass flow rate of nat vent
    1881              : 
    1882              :         // now calculate baffle temperature
    1883            1 :         if (!ICSCollectorIsOn) {
    1884            0 :             TsBaffle = (Isc * SolAbs + HExt * Tamb + HrAtm * Tamb + HrSky * state.dataEnvrn->SkyTemp + HrGround * Tamb + HrPlen * Tso +
    1885            0 :                         HcPlen * TaGap + QdotSource) /
    1886            0 :                        (HExt + HrAtm + HrSky + HrGround + HrPlen + HcPlen);
    1887              :         } else {
    1888              : 
    1889            1 :             TsBaffle = (ICSULossbottom * ICSWaterTemp + HrPlen * Tso + HcPlen * TaGap + QdotSource) / (ICSULossbottom + HrPlen + HcPlen);
    1890              :         }
    1891              :         // now calculate gap air temperature
    1892              : 
    1893            1 :         TaGap = (HcPlen * A * Tso + MdotVent * CpAir * Tamb + HcPlen * A * TsBaffle) / (HcPlen * A + MdotVent * CpAir + HcPlen * A);
    1894              : 
    1895            1 :         if (present(HcGapRpt)) HcGapRpt = HcPlen;
    1896            1 :         if (present(HrGapRpt)) HrGapRpt = HrPlen;
    1897            1 :         if (present(IscRpt)) IscRpt = Isc;
    1898            1 :         if (present(MdotVentRpt)) MdotVentRpt = MdotVent;
    1899            1 :         if (present(VdotWindRpt)) VdotWindRpt = VdotWind;
    1900            1 :         if (present(VdotBuoyRpt)) VdotBuoyRpt = VdotThermal;
    1901            1 :     }
    1902              : 
    1903              :     //****************************************************************************
    1904              : 
    1905            1 :     Real64 PassiveGapNusseltNumber(Real64 const AspRat, // Aspect Ratio of Gap height to gap width
    1906              :                                    Real64 const Tilt,   // Tilt of gap, degrees
    1907              :                                    Real64 const Tso,    // Temperature of gap surface closest to outside (K)
    1908              :                                    Real64 const Tsi,    // Temperature of gap surface closest to zone (K)
    1909              :                                    Real64 const Gr      // Gap gas Grashof number
    1910              :     )
    1911              :     {
    1912              : 
    1913              :         // SUBROUTINE INFORMATION:
    1914              :         //       AUTHOR         Adapted by B. Griffith from Fred Winkelmann's from NusseltNumber in WindowManager.cc
    1915              :         //       DATE WRITTEN   September 2001
    1916              :         //       MODIFIED       B. Griffith November 2004  (same models but slightly different for general use)
    1917              : 
    1918              :         // PURPOSE OF THIS SUBROUTINE:
    1919              :         // Finds the Nusselt number for air-filled gaps between isothermal solid layers.
    1920              : 
    1921              :         // METHODOLOGY EMPLOYED:
    1922              :         // Based on methodology in Chapter 5 of the July 18, 2001 draft of ISO 15099,
    1923              :         // "Thermal Performance of Windows, Doors and Shading Devices--Detailed Calculations."
    1924              :         // The equation numbers below correspond to those in the standard.
    1925              : 
    1926              :         // REFERENCES:
    1927              :         // Window5 source code; ISO 15099
    1928              : 
    1929              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1930            1 :         Real64 constexpr Pr(0.71); // Prandtl number for air
    1931              : 
    1932              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS
    1933              :         Real64 gnu901; // Nusselt number temporary variables for
    1934              : 
    1935            1 :         Real64 tiltr = Tilt * Constant::DegToRad;
    1936            1 :         Real64 Ra = Gr * Pr; // Rayleigh number
    1937              : 
    1938            1 :         if (Ra <= 1.0e4) {
    1939            0 :             gnu901 = 1.0 + 1.7596678e-10 * std::pow(Ra, 2.2984755); // eq. 51
    1940              :         }
    1941            1 :         if (Ra > 1.0e4 && Ra <= 5.0e4) gnu901 = 0.028154 * std::pow(Ra, 0.4134); // eq. 50
    1942            1 :         if (Ra > 5.0e4) gnu901 = 0.0673838 * std::pow(Ra, 1.0 / 3.0);            // eq. 49
    1943              : 
    1944            1 :         Real64 gnu902 = 0.242 * std::pow(Ra / AspRat, 0.272); // eq. 52
    1945            1 :         Real64 gnu90 = max(gnu901, gnu902);
    1946              : 
    1947            1 :         if (Tso > Tsi) {                                  // window heated from above
    1948            0 :             return 1.0 + (gnu90 - 1.0) * std::sin(tiltr); // eq. 53
    1949            1 :         } else if (Tilt >= 60.0) {
    1950            0 :             Real64 g = 0.5 * std::pow(1.0 + std::pow(Ra / 3160.0, 20.6), -0.1);     // eq. 47
    1951            0 :             Real64 gnu601a = 1.0 + pow_7(0.0936 * std::pow(Ra, 0.314) / (1.0 + g)); // eq. 45
    1952            0 :             Real64 gnu601 = std::pow(gnu601a, 0.142857);
    1953              : 
    1954              :             // For any aspect ratio
    1955            0 :             Real64 gnu602 = (0.104 + 0.175 / AspRat) * std::pow(Ra, 0.283); // eq. 46
    1956            0 :             Real64 gnu60 = max(gnu601, gnu602);
    1957              : 
    1958              :             // linear interpolation for layers inclined at angles between 60 and 90 deg
    1959            0 :             return ((90.0 - Tilt) * gnu60 + (Tilt - 60.0) * gnu90) / 30.0;
    1960              :         } else { // eq. 42
    1961            1 :             Real64 cra = Ra * std::cos(tiltr);
    1962            1 :             Real64 a = 1.0 - 1708.0 / cra;
    1963            1 :             Real64 b = std::pow(cra / 5830.0, 0.33333) - 1.0;
    1964            1 :             Real64 gnua = (std::abs(a) + a) / 2.0;
    1965            1 :             Real64 gnub = (std::abs(b) + b) / 2.0;
    1966            1 :             Real64 ang = 1708.0 * std::pow(std::sin(1.8 * tiltr), 1.6);
    1967            1 :             return 1.0 + 1.44 * gnua * (1.0 - ang / cra) + gnub;
    1968              :         }
    1969              :     }
    1970              : 
    1971              : } // namespace TranspiredCollector
    1972              : 
    1973              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1