LCOV - code coverage report
Current view: top level - EnergyPlus - TranspiredCollector.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 695 902 77.1 %
Date: 2024-08-24 18:31:18 Functions: 10 13 76.9 %

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

Generated by: LCOV version 1.14