LCOV - code coverage report
Current view: top level - EnergyPlus - ThermalChimney.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 345 534 64.6 %
Date: 2024-08-24 18:31:18 Functions: 5 5 100.0 %

          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 <cmath>
      50             : 
      51             : // ObjexxFCL Headers
      52             : #include <ObjexxFCL/Fmath.hh>
      53             : 
      54             : // EnergyPlus Headers
      55             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      56             : #include <EnergyPlus/DataEnvironment.hh>
      57             : #include <EnergyPlus/DataHVACGlobals.hh>
      58             : #include <EnergyPlus/DataHeatBalSurface.hh>
      59             : #include <EnergyPlus/DataHeatBalance.hh>
      60             : #include <EnergyPlus/DataIPShortCuts.hh>
      61             : #include <EnergyPlus/DataSurfaces.hh>
      62             : #include <EnergyPlus/EMSManager.hh>
      63             : #include <EnergyPlus/General.hh>
      64             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      65             : #include <EnergyPlus/OutputProcessor.hh>
      66             : #include <EnergyPlus/Psychrometrics.hh>
      67             : #include <EnergyPlus/ScheduleManager.hh>
      68             : #include <EnergyPlus/ThermalChimney.hh>
      69             : #include <EnergyPlus/UtilityRoutines.hh>
      70             : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      71             : 
      72             : namespace EnergyPlus {
      73             : 
      74             : namespace ThermalChimney {
      75             :     // Module containing the data for Thermal Chimney system
      76             : 
      77             :     // MODULE INFORMATION:
      78             :     //       AUTHOR         Kwang Ho Lee
      79             :     //       DATE WRITTEN   April 2008
      80             :     //       MODIFIED       na
      81             :     //       RE-ENGINEERED  na
      82             : 
      83             :     // PURPOSE OF THIS MODULE:
      84             :     // To encapsulate the data and algorithyms required to manage the ThermalChimney System Component
      85             : 
      86             :     // METHODOLOGY EMPLOYED:
      87             :     // na
      88             : 
      89             :     // REFERENCES:
      90             :     // 1. N. K. Bansal, R. Mathur and M. S. Bhandari, "Solar Chimney for Enhanced Stack Ventilation",
      91             :     // Building and Environment, 28, pp. 373-377, 1993
      92             :     // 2. K. S. Ong, "A Mathematical Model of a Solar Chimney", Renewable Energy, 28, pp. 1047-1060, 2003
      93             :     // 3. J. Marti-Herrero and M. R. Heras-Celemin, "Dynamic Physical Model for a Solar Chimney",
      94             :     // Solar Energy, 81, pp. 614-622, 2007
      95             : 
      96             :     // OTHER NOTES: none
      97             : 
      98             :     // Using/Aliasing
      99             :     using namespace DataEnvironment;
     100             :     using namespace DataHeatBalance;
     101             :     using namespace DataSurfaces;
     102             :     using namespace DataHeatBalSurface;
     103             : 
     104             :     // Use statements for access to subroutines in other modules
     105             :     using namespace Psychrometrics;
     106             : 
     107     3728073 :     void ManageThermalChimney(EnergyPlusData &state)
     108             :     {
     109             : 
     110             :         // SUBROUTINE INFORMATION:
     111             :         //       AUTHOR         Kwang Ho Lee
     112             :         //       DATE WRITTEN   April 2008
     113             :         //       MODIFIED       na
     114             :         //       RE-ENGINEERED  na
     115             : 
     116             :         // PURPOSE OF THIS SUBROUTINE:
     117             :         // This subroutine manages the simulation of ThermalChimney unit.
     118             :         // This driver manages the calls to all of
     119             :         // the other drivers and simulation algorithms.
     120             : 
     121             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     122     3728073 :         bool ErrorsFound(false);
     123             : 
     124             :         // Obtains and Allocates heat balance related parameters from input file
     125     3728073 :         if (state.dataThermalChimneys->ThermalChimneyGetInputFlag) {
     126         763 :             GetThermalChimney(state, ErrorsFound);
     127         763 :             state.dataThermalChimneys->ThermalChimneyGetInputFlag = false;
     128             :         }
     129             : 
     130     3728073 :         if (state.dataThermalChimneys->TotThermalChimney == 0) return;
     131             : 
     132        8280 :         CalcThermalChimney(state);
     133             : 
     134        8280 :         ReportThermalChimney(state);
     135             :     }
     136             : 
     137         763 :     void GetThermalChimney(EnergyPlusData &state, bool &ErrorsFound) // If errors found in input
     138             :     {
     139             : 
     140             :         // SUBROUTINE INFORMATION:
     141             :         //       AUTHOR         Kwang Ho Lee
     142             :         //       DATE WRITTEN   April 2008
     143             :         //       MODIFIED       na
     144             :         //       RE-ENGINEERED  na
     145             : 
     146             :         // PURPOSE OF THIS SUBROUTINE:
     147             :         // This subroutine obtains input data for ThermalChimney units and
     148             :         // stores it in the ThermalChimney data structure.
     149             : 
     150             :         // Using/Aliasing
     151             : 
     152             :         using ScheduleManager::GetScheduleIndex;
     153             : 
     154             :         // SUBROUTINE PARAMETER DEFINITIONS:
     155         763 :         Real64 constexpr FlowFractionTolerance(0.0001); // Smallest deviation from unity for the sum of all fractions
     156             : 
     157             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     158             :         int NumAlpha;
     159             :         int NumNumber;
     160             :         Real64 AllRatiosSummed;
     161             :         int TCZoneNum;  // Thermal chimney zone counter
     162             :         int TCZoneNum1; // Thermal chimney zone counter
     163             :         int IOStat;
     164             :         int Loop;
     165             :         int Loop1;
     166         763 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     167             : 
     168             :         // Following used for reporting
     169         763 :         state.dataThermalChimneys->ZnRptThermChim.allocate(state.dataGlobal->NumOfZones);
     170             : 
     171         763 :         cCurrentModuleObject = "ZoneThermalChimney";
     172         763 :         state.dataThermalChimneys->TotThermalChimney = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     173             : 
     174         763 :         state.dataThermalChimneys->ThermalChimneySys.allocate(state.dataThermalChimneys->TotThermalChimney);
     175         763 :         state.dataThermalChimneys->ThermalChimneyReport.allocate(state.dataThermalChimneys->TotThermalChimney);
     176             : 
     177         765 :         for (Loop = 1; Loop <= state.dataThermalChimneys->TotThermalChimney; ++Loop) {
     178             : 
     179           4 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     180             :                                                                      cCurrentModuleObject,
     181             :                                                                      Loop,
     182           2 :                                                                      state.dataIPShortCut->cAlphaArgs,
     183             :                                                                      NumAlpha,
     184           2 :                                                                      state.dataIPShortCut->rNumericArgs,
     185             :                                                                      NumNumber,
     186             :                                                                      IOStat,
     187           2 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     188           2 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     189           2 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     190           2 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     191           2 :             if (Util::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound)) {
     192           0 :                 continue;
     193             :             }
     194             : 
     195             :             // First Alpha is Thermal Chimney Name
     196           2 :             state.dataThermalChimneys->ThermalChimneySys(Loop).Name = state.dataIPShortCut->cAlphaArgs(1);
     197             : 
     198             :             // Second Alpha is Zone Name
     199           2 :             state.dataThermalChimneys->ThermalChimneySys(Loop).RealZonePtr =
     200           2 :                 Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(2), state.dataHeatBal->Zone);
     201           2 :             if (state.dataThermalChimneys->ThermalChimneySys(Loop).RealZonePtr == 0) {
     202           0 :                 ShowSevereError(state, format("{}=\"{} invalid Zone", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     203           0 :                 ShowContinueError(
     204           0 :                     state, format("invalid - not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(2), state.dataIPShortCut->cAlphaArgs(2)));
     205           0 :                 ErrorsFound = true;
     206           2 :             } else if (!state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).RealZonePtr).HasWindow) {
     207           0 :                 ShowSevereError(state, format("{}=\"{} invalid Zone", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     208           0 :                 ShowContinueError(state,
     209           0 :                                   format("...invalid - no window(s) in {}=\"{}\".",
     210           0 :                                          state.dataIPShortCut->cAlphaFieldNames(2),
     211           0 :                                          state.dataIPShortCut->cAlphaArgs(2)));
     212           0 :                 ShowContinueError(state, "...thermal chimney zones must have window(s).");
     213           0 :                 ErrorsFound = true;
     214             :             }
     215           2 :             state.dataThermalChimneys->ThermalChimneySys(Loop).RealZoneName = state.dataIPShortCut->cAlphaArgs(2);
     216             : 
     217           2 :             state.dataThermalChimneys->ThermalChimneySys(Loop).SchedName = state.dataIPShortCut->cAlphaArgs(3);
     218           2 :             if (state.dataIPShortCut->lAlphaFieldBlanks(3)) {
     219           0 :                 state.dataThermalChimneys->ThermalChimneySys(Loop).SchedPtr = ScheduleManager::ScheduleAlwaysOn;
     220             :             } else {
     221           2 :                 state.dataThermalChimneys->ThermalChimneySys(Loop).SchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(3));
     222           2 :                 if (state.dataThermalChimneys->ThermalChimneySys(Loop).SchedPtr == 0) {
     223           0 :                     ShowSevereError(state, format("{}=\"{} invalid data", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     224           0 :                     ShowContinueError(
     225             :                         state,
     226           0 :                         format("Invalid-not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
     227           0 :                     ErrorsFound = true;
     228             :                 }
     229             :             }
     230             : 
     231           2 :             state.dataThermalChimneys->ThermalChimneySys(Loop).AbsorberWallWidth = state.dataIPShortCut->rNumericArgs(1);
     232           2 :             if (state.dataThermalChimneys->ThermalChimneySys(Loop).AbsorberWallWidth < 0.0) {
     233           0 :                 ShowSevereError(state,
     234           0 :                                 format("{}=\"{} invalid {} must be >= 0, entered value=[{:.2R}].",
     235             :                                        cCurrentModuleObject,
     236           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
     237           0 :                                        state.dataIPShortCut->cNumericFieldNames(1),
     238           0 :                                        state.dataIPShortCut->rNumericArgs(1)));
     239           0 :                 ErrorsFound = true;
     240             :             }
     241             : 
     242           2 :             state.dataThermalChimneys->ThermalChimneySys(Loop).AirOutletCrossArea = state.dataIPShortCut->rNumericArgs(2);
     243           2 :             if (state.dataThermalChimneys->ThermalChimneySys(Loop).AirOutletCrossArea < 0.0) {
     244           0 :                 ShowSevereError(state,
     245           0 :                                 format("{}=\"{} invalid {} must be >= 0, entered value=[{:.2R}].",
     246             :                                        cCurrentModuleObject,
     247           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
     248           0 :                                        state.dataIPShortCut->cNumericFieldNames(2),
     249           0 :                                        state.dataIPShortCut->rNumericArgs(2)));
     250           0 :                 ErrorsFound = true;
     251             :             }
     252             : 
     253           2 :             state.dataThermalChimneys->ThermalChimneySys(Loop).DischargeCoeff = state.dataIPShortCut->rNumericArgs(3);
     254           4 :             if ((state.dataThermalChimneys->ThermalChimneySys(Loop).DischargeCoeff <= 0.0) ||
     255           2 :                 (state.dataThermalChimneys->ThermalChimneySys(Loop).DischargeCoeff > 1.0)) {
     256           0 :                 ShowSevereError(state,
     257           0 :                                 format("{}=\"{} invalid {} must be > 0 and <=1.0, entered value=[{:.2R}].",
     258             :                                        cCurrentModuleObject,
     259           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
     260           0 :                                        state.dataIPShortCut->cNumericFieldNames(3),
     261           0 :                                        state.dataIPShortCut->rNumericArgs(3)));
     262           0 :                 ErrorsFound = true;
     263             :             }
     264             : 
     265           2 :             state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib = NumAlpha - 3;
     266           2 :             state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr.allocate(state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
     267           2 :             state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr.allocate(state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
     268           2 :             state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName.allocate(state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
     269           4 :             state.dataThermalChimneys->ThermalChimneySys(Loop).DistanceThermChimInlet.allocate(
     270           2 :                 state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
     271           4 :             state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow.allocate(
     272           2 :                 state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
     273           4 :             state.dataThermalChimneys->ThermalChimneySys(Loop).EachAirInletCrossArea.allocate(
     274           2 :                 state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib);
     275             : 
     276           2 :             AllRatiosSummed = 0.0;
     277           4 :             for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
     278           2 :                 state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum) = state.dataIPShortCut->cAlphaArgs(TCZoneNum + 3);
     279           2 :                 state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) =
     280           2 :                     Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(TCZoneNum + 3), state.dataHeatBal->Zone);
     281           2 :                 if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) == 0) {
     282           0 :                     int spaceNum = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(TCZoneNum + 3), state.dataHeatBal->space);
     283           0 :                     if (spaceNum > 0) {
     284           0 :                         state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr(TCZoneNum) = spaceNum;
     285           0 :                         int zoneNum = state.dataHeatBal->space(spaceNum).zoneNum;
     286           0 :                         state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) = zoneNum;
     287             :                     }
     288             :                 }
     289             : 
     290           2 :                 state.dataThermalChimneys->ThermalChimneySys(Loop).DistanceThermChimInlet(TCZoneNum) =
     291           2 :                     state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 1);
     292           2 :                 state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) =
     293           2 :                     state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 2);
     294           2 :                 if (state.dataIPShortCut->lNumericFieldBlanks(3 * TCZoneNum + 2))
     295           0 :                     state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) = 1.0;
     296           2 :                 state.dataThermalChimneys->ThermalChimneySys(Loop).EachAirInletCrossArea(TCZoneNum) =
     297           2 :                     state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 3);
     298             : 
     299             :                 //!! Error trap for zones that do not exist or zones not in the zone the thermal chimney is in
     300           2 :                 if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) == 0) {
     301           0 :                     ShowSevereError(state,
     302           0 :                                     format("{}=\"{} invalid {}=\"{}\" not found.",
     303             :                                            cCurrentModuleObject,
     304           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     305           0 :                                            state.dataIPShortCut->cAlphaFieldNames(TCZoneNum + 3),
     306           0 :                                            state.dataIPShortCut->cAlphaArgs(TCZoneNum + 3)));
     307           0 :                     ErrorsFound = true;
     308           2 :                 } else if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
     309           2 :                            state.dataThermalChimneys->ThermalChimneySys(Loop).RealZonePtr) {
     310           0 :                     ShowSevereError(state,
     311           0 :                                     format("{}=\"{} invalid reference {}=\"{}",
     312             :                                            cCurrentModuleObject,
     313           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     314           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
     315           0 :                                            state.dataIPShortCut->cAlphaArgs(2)));
     316           0 :                     ShowContinueError(state,
     317           0 :                                       format("...must not have same zone as reference= {}=\"{}\".",
     318           0 :                                              state.dataIPShortCut->cAlphaFieldNames(TCZoneNum + 3),
     319           0 :                                              state.dataIPShortCut->cAlphaArgs(TCZoneNum + 3)));
     320           0 :                     ErrorsFound = true;
     321             :                 }
     322             : 
     323           2 :                 if (state.dataThermalChimneys->ThermalChimneySys(Loop).DistanceThermChimInlet(TCZoneNum) < 0.0) {
     324           0 :                     ShowSevereError(state,
     325           0 :                                     format("{}=\"{} invalid {} must be >= 0, entered value=[{:.2R}].",
     326             :                                            cCurrentModuleObject,
     327           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     328           0 :                                            state.dataIPShortCut->cNumericFieldNames(3 * TCZoneNum + 1),
     329           0 :                                            state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 1)));
     330           0 :                     ErrorsFound = true;
     331             :                 }
     332             : 
     333           4 :                 if ((state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) <= 0.0) ||
     334           2 :                     (state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) > 1.0)) {
     335           0 :                     ShowSevereError(state,
     336           0 :                                     format("{}=\"{} invalid {} must be > 0 and <=1.0, entered value=[{:.2R}].",
     337             :                                            cCurrentModuleObject,
     338           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     339           0 :                                            state.dataIPShortCut->cNumericFieldNames(3 * TCZoneNum + 2),
     340           0 :                                            state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 2)));
     341           0 :                     ErrorsFound = true;
     342             :                 }
     343             : 
     344           2 :                 if (state.dataThermalChimneys->ThermalChimneySys(Loop).EachAirInletCrossArea(TCZoneNum) < 0.0) {
     345           0 :                     ShowSevereError(state,
     346           0 :                                     format("{}=\"{} invalid {} must be >= 0, entered value=[{:.2R}].",
     347             :                                            cCurrentModuleObject,
     348           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     349           0 :                                            state.dataIPShortCut->cNumericFieldNames(3 * TCZoneNum + 3),
     350           0 :                                            state.dataIPShortCut->rNumericArgs(3 * TCZoneNum + 3)));
     351           0 :                     ErrorsFound = true;
     352             :                 }
     353             : 
     354           2 :                 AllRatiosSummed += state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum);
     355             : 
     356             :             } // DO TCZoneNum = 1, ThermalChimneySys(Loop)%TotZoneToDistrib
     357             : 
     358             :             // Error trap if the sum of fractions is not equal to 1.0
     359           2 :             if (std::abs(AllRatiosSummed - 1.0) > FlowFractionTolerance) {
     360           0 :                 ShowSevereError(state,
     361           0 :                                 format("{}=\"{} invalid sum of fractions, must be =1.0, entered value (summed from entries)=[{:.4R}].",
     362             :                                        cCurrentModuleObject,
     363           0 :                                        state.dataIPShortCut->cAlphaArgs(1),
     364             :                                        AllRatiosSummed));
     365           0 :                 ErrorsFound = true;
     366             :             }
     367             : 
     368             :         } // DO Loop=1, TotThermalChimney
     369             : 
     370             :         // check infiltration output
     371             :         // setup zone-level infiltration reports
     372         763 :         Array1D_bool RepVarSet;
     373         763 :         RepVarSet.dimension(state.dataGlobal->NumOfZones, true);
     374        4284 :         for (Loop = 1; Loop <= state.dataHeatBal->TotInfiltration; ++Loop) {
     375        3521 :             int zoneNum = state.dataHeatBal->Infiltration(Loop).ZonePtr;
     376        3521 :             if (zoneNum > 0 && !state.dataHeatBal->Zone(zoneNum).zoneOAQuadratureSum) {
     377        3520 :                 RepVarSet(zoneNum) = false;
     378             :             }
     379             :         }
     380             :         // Set up the output variables for thermal chimneys
     381         765 :         for (Loop = 1; Loop <= state.dataThermalChimneys->TotThermalChimney; ++Loop) {
     382           4 :             SetupOutputVariable(state,
     383             :                                 "Zone Thermal Chimney Current Density Air Volume Flow Rate",
     384             :                                 Constant::Units::m3_s,
     385           2 :                                 state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlow,
     386             :                                 OutputProcessor::TimeStepType::System,
     387             :                                 OutputProcessor::StoreType::Average,
     388           2 :                                 state.dataThermalChimneys->ThermalChimneySys(Loop).Name);
     389           4 :             SetupOutputVariable(state,
     390             :                                 "Zone Thermal Chimney Standard Density Air Volume Flow Rate",
     391             :                                 Constant::Units::m3_s,
     392           2 :                                 state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlowStd,
     393             :                                 OutputProcessor::TimeStepType::System,
     394             :                                 OutputProcessor::StoreType::Average,
     395           2 :                                 state.dataThermalChimneys->ThermalChimneySys(Loop).Name);
     396           4 :             SetupOutputVariable(state,
     397             :                                 "Zone Thermal Chimney Mass Flow Rate",
     398             :                                 Constant::Units::kg_s,
     399           2 :                                 state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCMassFlow,
     400             :                                 OutputProcessor::TimeStepType::System,
     401             :                                 OutputProcessor::StoreType::Average,
     402           2 :                                 state.dataThermalChimneys->ThermalChimneySys(Loop).Name);
     403           4 :             SetupOutputVariable(state,
     404             :                                 "Zone Thermal Chimney Outlet Temperature",
     405             :                                 Constant::Units::C,
     406           2 :                                 state.dataThermalChimneys->ThermalChimneyReport(Loop).OutletAirTempThermalChim,
     407             :                                 OutputProcessor::TimeStepType::System,
     408             :                                 OutputProcessor::StoreType::Average,
     409           2 :                                 state.dataThermalChimneys->ThermalChimneySys(Loop).Name);
     410             : 
     411           2 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
     412           0 :                 SetupEMSActuator(state,
     413             :                                  "Zone Thermal Chimney",
     414           0 :                                  state.dataThermalChimneys->ThermalChimneySys(Loop).Name,
     415             :                                  "Air Exchange Flow Rate",
     416             :                                  "[m3/s]",
     417           0 :                                  state.dataThermalChimneys->ThermalChimneySys(Loop).EMSOverrideOn,
     418           0 :                                  state.dataThermalChimneys->ThermalChimneySys(Loop).EMSAirFlowRateValue);
     419             :             }
     420             : 
     421           4 :             for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
     422           4 :                 SetupOutputVariable(state,
     423             :                                     "Zone Thermal Chimney Heat Loss Energy",
     424             :                                     Constant::Units::J,
     425           2 :                                     state.dataThermalChimneys->ZnRptThermChim(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))
     426           2 :                                         .ThermalChimneyHeatLoss,
     427             :                                     OutputProcessor::TimeStepType::System,
     428             :                                     OutputProcessor::StoreType::Sum,
     429           2 :                                     state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     430           4 :                 SetupOutputVariable(state,
     431             :                                     "Zone Thermal Chimney Heat Gain Energy",
     432             :                                     Constant::Units::J,
     433           2 :                                     state.dataThermalChimneys->ZnRptThermChim(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))
     434           2 :                                         .ThermalChimneyHeatGain,
     435             :                                     OutputProcessor::TimeStepType::System,
     436             :                                     OutputProcessor::StoreType::Sum,
     437           2 :                                     state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     438           4 :                 SetupOutputVariable(state,
     439             :                                     "Zone Thermal Chimney Volume",
     440             :                                     Constant::Units::m3,
     441           2 :                                     state.dataThermalChimneys->ZnRptThermChim(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))
     442           2 :                                         .ThermalChimneyVolume,
     443             :                                     OutputProcessor::TimeStepType::System,
     444             :                                     OutputProcessor::StoreType::Sum,
     445           2 :                                     state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     446           4 :                 SetupOutputVariable(state,
     447             :                                     "Zone Thermal Chimney Mass",
     448             :                                     Constant::Units::kg,
     449           2 :                                     state.dataThermalChimneys->ZnRptThermChim(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))
     450           2 :                                         .ThermalChimneyMass,
     451             :                                     OutputProcessor::TimeStepType::System,
     452             :                                     OutputProcessor::StoreType::Sum,
     453           2 :                                     state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     454           2 :                 if (RepVarSet(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum))) {
     455           0 :                     SetupOutputVariable(
     456             :                         state,
     457             :                         "Zone Infiltration Sensible Heat Loss Energy",
     458             :                         Constant::Units::J,
     459           0 :                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilHeatLoss,
     460             :                         OutputProcessor::TimeStepType::System,
     461             :                         OutputProcessor::StoreType::Sum,
     462           0 :                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     463           0 :                     SetupOutputVariable(
     464             :                         state,
     465             :                         "Zone Infiltration Sensible Heat Gain Energy",
     466             :                         Constant::Units::J,
     467           0 :                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilHeatGain,
     468             :                         OutputProcessor::TimeStepType::System,
     469             :                         OutputProcessor::StoreType::Sum,
     470           0 :                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     471           0 :                     SetupOutputVariable(
     472             :                         state,
     473             :                         "Zone Infiltration Latent Heat Loss Energy",
     474             :                         Constant::Units::J,
     475           0 :                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilLatentLoss,
     476             :                         OutputProcessor::TimeStepType::System,
     477             :                         OutputProcessor::StoreType::Sum,
     478           0 :                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     479           0 :                     SetupOutputVariable(
     480             :                         state,
     481             :                         "Zone Infiltration Latent Heat Gain Energy",
     482             :                         Constant::Units::J,
     483           0 :                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilLatentGain,
     484             :                         OutputProcessor::TimeStepType::System,
     485             :                         OutputProcessor::StoreType::Sum,
     486           0 :                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     487           0 :                     SetupOutputVariable(
     488             :                         state,
     489             :                         "Zone Infiltration Total Heat Loss Energy",
     490             :                         Constant::Units::J,
     491           0 :                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilTotalLoss,
     492             :                         OutputProcessor::TimeStepType::System,
     493             :                         OutputProcessor::StoreType::Sum,
     494           0 :                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     495           0 :                     SetupOutputVariable(
     496             :                         state,
     497             :                         "Zone Infiltration Total Heat Gain Energy",
     498             :                         Constant::Units::J,
     499           0 :                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilTotalGain,
     500             :                         OutputProcessor::TimeStepType::System,
     501             :                         OutputProcessor::StoreType::Sum,
     502           0 :                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     503           0 :                     SetupOutputVariable(
     504             :                         state,
     505             :                         "Zone Infiltration Current Density Volume Flow Rate",
     506             :                         Constant::Units::m3_s,
     507           0 :                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilVdotCurDensity,
     508             :                         OutputProcessor::TimeStepType::System,
     509             :                         OutputProcessor::StoreType::Average,
     510           0 :                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     511           0 :                     SetupOutputVariable(
     512             :                         state,
     513             :                         "Zone Infiltration Standard Density Volume Flow Rate",
     514             :                         Constant::Units::m3_s,
     515           0 :                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilVdotStdDensity,
     516             :                         OutputProcessor::TimeStepType::System,
     517             :                         OutputProcessor::StoreType::Average,
     518           0 :                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     519           0 :                     SetupOutputVariable(
     520             :                         state,
     521             :                         "Zone Infiltration Current Density Volume",
     522             :                         Constant::Units::m3,
     523           0 :                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilVolumeCurDensity,
     524             :                         OutputProcessor::TimeStepType::System,
     525             :                         OutputProcessor::StoreType::Sum,
     526           0 :                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     527           0 :                     SetupOutputVariable(
     528             :                         state,
     529             :                         "Zone Infiltration Standard Density Volume",
     530             :                         Constant::Units::m3,
     531           0 :                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilVolumeStdDensity,
     532             :                         OutputProcessor::TimeStepType::System,
     533             :                         OutputProcessor::StoreType::Sum,
     534           0 :                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     535           0 :                     SetupOutputVariable(state,
     536             :                                         "Zone Infiltration Mass",
     537             :                                         Constant::Units::kg,
     538           0 :                                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilMass,
     539             :                                         OutputProcessor::TimeStepType::System,
     540             :                                         OutputProcessor::StoreType::Sum,
     541           0 :                                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     542           0 :                     SetupOutputVariable(state,
     543             :                                         "Zone Infiltration Mass Flow Rate",
     544             :                                         Constant::Units::kg_s,
     545           0 :                                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilMdot,
     546             :                                         OutputProcessor::TimeStepType::System,
     547             :                                         OutputProcessor::StoreType::Average,
     548           0 :                                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     549           0 :                     SetupOutputVariable(
     550             :                         state,
     551             :                         "Zone Infiltration Air Change Rate",
     552             :                         Constant::Units::ach,
     553           0 :                         state.dataHeatBal->ZnAirRpt(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).InfilAirChangeRate,
     554             :                         OutputProcessor::TimeStepType::System,
     555             :                         OutputProcessor::StoreType::Average,
     556           0 :                         state.dataHeatBal->Zone(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)).Name);
     557           0 :                     RepVarSet(state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum)) = false;
     558             :                 }
     559             :             } // DO TCZoneNum = 1, ThermalChimneySys(Loop)%TotZoneToDistrib
     560             :         }     // DO Loop=1, TotThermalChimney
     561             : 
     562             :         //! LKL-more renaming effort and code review might be possible here
     563             :         // Check to make sure there is only one thermal chimney statement per zone
     564         765 :         for (Loop = 1; Loop <= state.dataThermalChimneys->TotThermalChimney; ++Loop) {
     565           2 :             if (state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib > 1) {
     566           0 :                 for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
     567             : 
     568           0 :                     if (state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib >= (TCZoneNum + 1)) {
     569           0 :                         for (TCZoneNum1 = TCZoneNum + 1; TCZoneNum1 <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib;
     570             :                              ++TCZoneNum1) {
     571           0 :                             if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
     572           0 :                                 state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum1)) {
     573           0 :                                 ShowSevereError(state,
     574           0 :                                                 format("Only one ZoneThermalChimney object allowed per zone but zone {} has two ZoneThermalChimney "
     575             :                                                        "objects associated with it",
     576           0 :                                                        state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
     577           0 :                                 ErrorsFound = true;
     578             :                             }
     579             :                         }
     580           0 :                         for (TCZoneNum1 = 1; TCZoneNum1 <= TCZoneNum - 1; ++TCZoneNum1) {
     581           0 :                             if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
     582           0 :                                 state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum1)) {
     583           0 :                                 ShowSevereError(state,
     584           0 :                                                 format("Only one ZoneThermalChimney object allowed per zone but zone {} has two ZoneThermalChimney "
     585             :                                                        "objects associated with it",
     586           0 :                                                        state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
     587           0 :                                 ErrorsFound = true;
     588             :                             }
     589             :                         }
     590             :                     } else { // IF ( ThermalChimneySys(Loop)%TotZoneToDistrib >= (TCZoneNum+1) ) THEN
     591           0 :                         for (TCZoneNum1 = 1; TCZoneNum1 <= TCZoneNum - 1; ++TCZoneNum1) {
     592           0 :                             if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
     593           0 :                                 state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum1)) {
     594           0 :                                 ShowSevereError(state,
     595           0 :                                                 format("Only one ZoneThermalChimney object allowed per zone but zone {} has two ZoneThermalChimney "
     596             :                                                        "objects associated with it",
     597           0 :                                                        state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
     598           0 :                                 ErrorsFound = true;
     599             :                             }
     600             :                         }
     601             :                     } // IF ( ThermalChimneySys(Loop)%TotZoneToDistrib >= (TCZoneNum+1) ) THEN
     602             : 
     603             :                 } // DO TCZoneNum = 1, ThermalChimneySys(Loop)%TotZoneToDistrib
     604             :             }     // IF (ThermalChimneySys(Loop)%TotZoneToDistrib > 1) THEN
     605             :         }         // DO Loop = 1, TotThermalChimney
     606             : 
     607             :         // Check to make sure there is only one thermal chimney statement per zone
     608         763 :         if (state.dataThermalChimneys->TotThermalChimney > 1) {
     609           3 :             for (Loop = 1; Loop <= state.dataThermalChimneys->TotThermalChimney; ++Loop) {
     610             : 
     611           2 :                 if (state.dataThermalChimneys->TotThermalChimney >= (Loop + 1)) {
     612           2 :                     for (Loop1 = Loop + 1; Loop1 <= state.dataThermalChimneys->TotThermalChimney; ++Loop1) {
     613           2 :                         for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
     614           2 :                             for (TCZoneNum1 = 1; TCZoneNum1 <= state.dataThermalChimneys->ThermalChimneySys(Loop1).TotZoneToDistrib; ++TCZoneNum1) {
     615           1 :                                 if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
     616           1 :                                     state.dataThermalChimneys->ThermalChimneySys(Loop1).ZonePtr(TCZoneNum1)) {
     617           0 :                                     ShowSevereError(state,
     618           0 :                                                     format("Only one ZoneThermalChimney object allowed per zone but zone {} has two "
     619             :                                                            "ZoneThermalChimney objects associated with it",
     620           0 :                                                            state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
     621           0 :                                     ErrorsFound = true;
     622             :                                 }
     623             :                             }
     624             :                         }
     625             :                     }
     626           1 :                     for (Loop1 = 1; Loop1 <= Loop - 1; ++Loop1) {
     627           0 :                         for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
     628           0 :                             for (TCZoneNum1 = 1; TCZoneNum1 <= state.dataThermalChimneys->ThermalChimneySys(Loop1).TotZoneToDistrib; ++TCZoneNum1) {
     629           0 :                                 if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
     630           0 :                                     state.dataThermalChimneys->ThermalChimneySys(Loop1).ZonePtr(TCZoneNum1)) {
     631           0 :                                     ShowSevereError(state,
     632           0 :                                                     format("Only one ZoneThermalChimney object allowed per zone but zone {} has two "
     633             :                                                            "ZoneThermalChimney objects associated with it",
     634           0 :                                                            state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
     635           0 :                                     ErrorsFound = true;
     636             :                                 }
     637             :                             }
     638             :                         }
     639             :                     }
     640             :                 } else { // IF ( TotThermalChimney >= (Loop+1) ) THEN
     641           2 :                     for (Loop1 = 1; Loop1 <= Loop - 1; ++Loop1) {
     642           2 :                         for (TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
     643           2 :                             for (TCZoneNum1 = 1; TCZoneNum1 <= state.dataThermalChimneys->ThermalChimneySys(Loop1).TotZoneToDistrib; ++TCZoneNum1) {
     644           1 :                                 if (state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum) ==
     645           1 :                                     state.dataThermalChimneys->ThermalChimneySys(Loop1).ZonePtr(TCZoneNum1)) {
     646           0 :                                     ShowSevereError(state,
     647           0 :                                                     format("Only one ZoneThermalChimney object allowed per zone but zone {} has two "
     648             :                                                            "ZoneThermalChimney objects associated with it",
     649           0 :                                                            state.dataThermalChimneys->ThermalChimneySys(Loop).ZoneName(TCZoneNum)));
     650           0 :                                     ErrorsFound = true;
     651             :                                 }
     652             :                             }
     653             :                         }
     654             :                     }
     655             :                 } // IF ( TotThermalChimney >= (Loop+1) ) THEN
     656             : 
     657             :             } // DO Loop = 1, TotThermalChimney
     658             :         }     // IF (TotThermalChimney > 1) THEN
     659             : 
     660         763 :         if (ErrorsFound) {
     661           0 :             ShowFatalError(state, format("{} Errors found in input.  Preceding condition(s) cause termination.", cCurrentModuleObject));
     662             :         }
     663         763 :     }
     664             : 
     665        8280 :     void CalcThermalChimney(EnergyPlusData &state)
     666             :     {
     667             : 
     668             :         // SUBROUTINE INFORMATION:
     669             :         //       AUTHOR         Kwang Ho Lee
     670             :         //       DATE WRITTEN   April 2008
     671             :         //       MODIFIED       na
     672             :         //       RE-ENGINEERED  na
     673             : 
     674             :         // PURPOSE OF THIS SUBROUTINE:
     675             :         // This subroutine simulates the components making up the ThermalChimney.
     676             : 
     677             :         using ScheduleManager::GetCurrentScheduleValue;
     678             : 
     679        8280 :         int constexpr NTC(15); // Number of subregions in thermal chimney air channel for FINITE DIFFERENCE
     680             : 
     681             :         // To be obtained from other modules and subroutines
     682             :         Real64 SurfTempAbsorberWall;     // Absorber wall surface temperature (K)
     683             :         Real64 SurfTempGlassCover;       // Glass cover surface temperature (K)
     684             :         Real64 ConvTransCoeffWallFluid;  // Absorber wall convection trasnfer coefficient
     685             :         Real64 ConvTransCoeffGlassFluid; // Glass cover convection trasnfer coefficient
     686             : 
     687             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     688             :         // Real local vaiables
     689             :         Real64 minorW; // width of enclosure (narrow dimension)
     690             :         Real64 majorW; // width of major surface
     691             :         Real64 TempmajorW;
     692             : 
     693             :         Real64 RoomAirTemp;
     694             :         Real64 AirSpecHeatThermalChim; // (J/kg*C) or (J/kg*K)
     695             :         Real64 AbsorberWallWidthTC;
     696             :         Real64 TCVolumeAirFlowRate; // (m^3/s)
     697             :         Real64 TCMassAirFlowRate;   // (kg/s)
     698             :         Real64 DischargeCoeffTC;
     699             :         Real64 AirOutletCrossAreaTC;
     700             :         Real64 AirInletCrossArea;
     701             :         Real64 AirRelativeCrossArea;
     702             :         // REAL(r64)                    :: OutletAirTempThermalChim
     703             :         Real64 OverallThermalChimLength;
     704             :         Real64 ThermChimTolerance;
     705        8280 :         Array1D<Real64> TempTCMassAirFlowRate(10);   // Temporary Value of Thermal Chimney Mass Flow Rate ()
     706        8280 :         Array1D<Real64> TempTCVolumeAirFlowRate(10); // Temporary Value of Thermal Chimney Volume Flow Rate ()
     707             :         int IterationLoop;
     708             :         Real64 Process1; // Temporary Variable Used in the Middle of the Calculation
     709             :         Real64 Process2; // Temporary Variable Used in the Middle of the Calculation
     710             :         Real64 Process3; // Temporary Variable Used in the Middle of the Calculation
     711             :         // unused1208  REAL(r64)   :: Process4                            ! Temporary Variable Used in the Middle of the Calculation
     712             :         Real64 AirDensityThermalChim; // (kg/m^3)
     713             :         Real64 AirDensity;            // (kg/m^3)
     714             :         Real64 CpAir;
     715             :         Real64 TemporaryWallSurfTemp;
     716             : 
     717             :         Real64 DeltaL; // OverallThermalChimLength / NTC
     718             :         int ThermChimLoop1;
     719             :         int ThermChimLoop2;
     720       16560 :         Array2D<Real64> EquaCoef(NTC, NTC);    // Coefficients in Linear Algebraic Euqation for FINITE DIFFERENCE
     721        8280 :         Array1D<Real64> EquaConst(NTC);        // Constants in Linear Algebraic Equation for FINITE DIFFERENCE
     722        8280 :         Array1D<Real64> ThermChimSubTemp(NTC); // Air temperature of each thermal chimney air channel subregion
     723             : 
     724       24840 :         for (int Loop = 1; Loop <= state.dataThermalChimneys->TotThermalChimney; ++Loop) {
     725             : 
     726       16560 :             int ZoneNum = state.dataThermalChimneys->ThermalChimneySys(Loop).RealZonePtr;
     727       16560 :             auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
     728             :             // start off with first surface in zone widths
     729       16560 :             int firstSpaceHTSurfaceFirst = state.dataHeatBal->space(state.dataHeatBal->Zone(ZoneNum).spaceIndexes(1)).HTSurfaceFirst;
     730       16560 :             majorW = state.dataSurface->Surface(firstSpaceHTSurfaceFirst).Width;
     731       16560 :             minorW = majorW;
     732       16560 :             TempmajorW = 0.0;
     733       16560 :             TemporaryWallSurfTemp = -10000.0;
     734             : 
     735             :             // determine major width and minor width
     736       33120 :             for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
     737       16560 :                 auto &thisSpace = state.dataHeatBal->space(spaceNum);
     738      149040 :                 for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
     739      132480 :                     if (state.dataSurface->Surface(SurfNum).Class != SurfaceClass::Wall) continue;
     740             : 
     741       82800 :                     if (state.dataSurface->Surface(SurfNum).Width > majorW) {
     742           0 :                         majorW = state.dataSurface->Surface(SurfNum).Width;
     743             :                     }
     744             : 
     745       82800 :                     if (state.dataSurface->Surface(SurfNum).Width < minorW) {
     746       16560 :                         minorW = state.dataSurface->Surface(SurfNum).Width;
     747             :                     }
     748             :                 }
     749             : 
     750      149040 :                 for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
     751      132480 :                     if (state.dataSurface->Surface(SurfNum).Width == majorW) {
     752       66240 :                         if (state.dataHeatBalSurf->SurfTempIn(SurfNum) > TemporaryWallSurfTemp) {
     753       33221 :                             TemporaryWallSurfTemp = state.dataHeatBalSurf->SurfTempIn(SurfNum);
     754       33221 :                             ConvTransCoeffWallFluid = state.dataHeatBalSurf->SurfHConvInt(SurfNum);
     755       33221 :                             SurfTempAbsorberWall = state.dataHeatBalSurf->SurfTempIn(SurfNum) + Constant::Kelvin;
     756             :                         }
     757             :                     }
     758             :                 }
     759             : 
     760      149040 :                 for (int SurfNum = thisSpace.HTSurfaceFirst; SurfNum <= thisSpace.HTSurfaceLast; ++SurfNum) {
     761      132480 :                     if (state.dataSurface->Surface(SurfNum).Class == SurfaceClass::Window) {
     762       16560 :                         if (state.dataSurface->Surface(SurfNum).Width > TempmajorW) {
     763       16560 :                             TempmajorW = state.dataSurface->Surface(SurfNum).Width;
     764       16560 :                             ConvTransCoeffGlassFluid = state.dataHeatBalSurf->SurfHConvInt(SurfNum);
     765       16560 :                             SurfTempGlassCover = state.dataHeatBalSurf->SurfTempIn(SurfNum) + Constant::Kelvin;
     766             :                         }
     767             :                     }
     768             :                 }
     769       16560 :             }
     770             : 
     771       16560 :             AbsorberWallWidthTC = majorW;
     772       16560 :             if (state.dataThermalChimneys->ThermalChimneySys(Loop).AbsorberWallWidth != majorW) {
     773       16560 :                 AbsorberWallWidthTC = state.dataThermalChimneys->ThermalChimneySys(Loop).AbsorberWallWidth;
     774             :             }
     775             : 
     776       16560 :             AirDensityThermalChim = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, thisZoneHB.MAT, thisZoneHB.airHumRat);
     777       16560 :             AirSpecHeatThermalChim = PsyCpAirFnW(thisZoneHB.airHumRat);
     778       16560 :             AirOutletCrossAreaTC = state.dataThermalChimneys->ThermalChimneySys(Loop).AirOutletCrossArea;
     779       16560 :             DischargeCoeffTC = state.dataThermalChimneys->ThermalChimneySys(Loop).DischargeCoeff;
     780             : 
     781       16560 :             AirInletCrossArea = 0.0;
     782       33120 :             for (int TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
     783       16560 :                 AirInletCrossArea += state.dataThermalChimneys->ThermalChimneySys(Loop).EachAirInletCrossArea(TCZoneNum);
     784             :             }
     785             : 
     786       16560 :             RoomAirTemp = 0.0;
     787       33120 :             for (int TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
     788       16560 :                 int tcSpacePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr(TCZoneNum);
     789       16560 :                 if ((state.dataHeatBal->doSpaceHeatBalance) && (tcSpacePtr > 0)) {
     790           0 :                     RoomAirTemp += state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) *
     791           0 :                                    state.dataZoneTempPredictorCorrector->spaceHeatBalance(tcSpacePtr).MAT;
     792             :                 } else {
     793       16560 :                     int tcZonePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum);
     794       16560 :                     RoomAirTemp += state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) *
     795       16560 :                                    state.dataZoneTempPredictorCorrector->zoneHeatBalance(tcZonePtr).MAT;
     796             :                 }
     797             :             }
     798       16560 :             RoomAirTemp += Constant::Kelvin;
     799             : 
     800       16560 :             Process1 = 0.0;
     801       16560 :             Process2 = 0.0;
     802       33120 :             for (int TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
     803       16560 :                 int tcZonePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum);
     804       16560 :                 auto &thisTCZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(tcZonePtr);
     805       16560 :                 Real64 tcZoneMAT = thisTCZoneHB.MAT;
     806       16560 :                 Real64 tcZoneHumRat = thisTCZoneHB.airHumRat;
     807       16560 :                 int tcSpacePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr(TCZoneNum);
     808       16560 :                 if ((state.dataHeatBal->doSpaceHeatBalance) && (tcSpacePtr > 0)) {
     809           0 :                     auto &thisTCspaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(tcSpacePtr);
     810           0 :                     tcZoneMAT = thisTCspaceHB.MAT;
     811           0 :                     tcZoneHumRat = thisTCspaceHB.airHumRat;
     812             :                 }
     813       16560 :                 Real64 tcZoneEnth = PsyHFnTdbW(tcZoneMAT, tcZoneHumRat);
     814       16560 :                 Process1 += tcZoneEnth * state.dataThermalChimneys->ThermalChimneySys(Loop).DistanceThermChimInlet(TCZoneNum) *
     815       16560 :                             state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum);
     816       16560 :                 Process2 += state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum) * tcZoneEnth;
     817             :             }
     818       16560 :             OverallThermalChimLength = Process1 / Process2;
     819             : 
     820       16560 :             DeltaL = OverallThermalChimLength / NTC;
     821             : 
     822             :             // Starting the iteration for mass and volumetric flow rate calculation
     823       16560 :             ThermChimTolerance = 10000000.0; // An impossibly big tolerance
     824      182160 :             for (IterationLoop = 1; IterationLoop <= 10; ++IterationLoop) {
     825             : 
     826      165600 :                 if (IterationLoop == 1) {
     827       16560 :                     TempTCMassAirFlowRate(IterationLoop) = 0.05; // Inital Guess
     828             : 
     829             :                 } else {
     830      149040 :                     TempTCMassAirFlowRate(IterationLoop) = TempTCVolumeAirFlowRate(IterationLoop - 1) * AirDensityThermalChim;
     831             : 
     832      149040 :                     if (std::abs(TempTCMassAirFlowRate(IterationLoop) - TempTCMassAirFlowRate(IterationLoop - 1)) < ThermChimTolerance) {
     833       99602 :                         ThermChimTolerance = std::abs(TempTCMassAirFlowRate(IterationLoop) - TempTCMassAirFlowRate(IterationLoop - 1));
     834       99602 :                         TCMassAirFlowRate = TempTCMassAirFlowRate(IterationLoop);
     835       99602 :                         TCVolumeAirFlowRate = TempTCVolumeAirFlowRate(IterationLoop);
     836             :                     }
     837             : 
     838             :                 } // IF (IterationLoop == 1) THEN
     839             : 
     840             :                 // Calculation of Thermal Chimney Discharge Air Temperature
     841      331200 :                 Process1 = AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid + AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid -
     842      165600 :                            2.0 * TempTCMassAirFlowRate(IterationLoop) * AirSpecHeatThermalChim;
     843      331200 :                 Process2 = AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid + AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid +
     844      165600 :                            2.0 * TempTCMassAirFlowRate(IterationLoop) * AirSpecHeatThermalChim;
     845      165600 :                 Process3 = 2.0 * AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid * SurfTempGlassCover +
     846      165600 :                            2.0 * AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid * SurfTempAbsorberWall;
     847             : 
     848     2649600 :                 for (ThermChimLoop1 = 1; ThermChimLoop1 <= NTC; ++ThermChimLoop1) {
     849    39744000 :                     for (ThermChimLoop2 = 1; ThermChimLoop2 <= NTC; ++ThermChimLoop2) {
     850    37260000 :                         EquaCoef(ThermChimLoop2, ThermChimLoop1) = 0.0;
     851             :                     }
     852             :                 }
     853             : 
     854      165600 :                 EquaCoef(1, 1) = Process2;
     855      165600 :                 EquaConst(1) = Process3 - Process1 * RoomAirTemp;
     856     2484000 :                 for (ThermChimLoop1 = 2; ThermChimLoop1 <= NTC; ++ThermChimLoop1) {
     857     2318400 :                     EquaCoef((ThermChimLoop1 - 1), ThermChimLoop1) = Process1;
     858     2318400 :                     EquaCoef(ThermChimLoop1, ThermChimLoop1) = Process2;
     859     2318400 :                     EquaConst(ThermChimLoop1) = Process3;
     860             :                 }
     861             : 
     862      165600 :                 GaussElimination(EquaCoef, EquaConst, ThermChimSubTemp, NTC);
     863             : 
     864      165600 :                 AirRelativeCrossArea = AirOutletCrossAreaTC / AirInletCrossArea;
     865      165600 :                 if (ThermChimSubTemp(NTC) <= RoomAirTemp) {
     866       49530 :                     TempTCVolumeAirFlowRate(IterationLoop) = 0.0;
     867             :                 } else {
     868      116070 :                     TempTCVolumeAirFlowRate(IterationLoop) = DischargeCoeffTC * AirOutletCrossAreaTC *
     869      232140 :                                                              std::sqrt(2.0 * ((ThermChimSubTemp(NTC) - RoomAirTemp) / RoomAirTemp) * 9.8 *
     870      116070 :                                                                        OverallThermalChimLength / pow_2(1.0 + AirRelativeCrossArea));
     871             :                 }
     872             : 
     873             :             } // DO IterationLoop = 1,10
     874             : 
     875             :             // Calculation of Thermal Chimney Discharge Temperature
     876       16560 :             Process1 = AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid + AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid -
     877       16560 :                        2.0 * TCMassAirFlowRate * AirSpecHeatThermalChim;
     878       16560 :             Process2 = AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid + AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid +
     879       16560 :                        2.0 * TCMassAirFlowRate * AirSpecHeatThermalChim;
     880       16560 :             Process3 = 2.0 * AbsorberWallWidthTC * DeltaL * ConvTransCoeffGlassFluid * SurfTempGlassCover +
     881       16560 :                        2.0 * AbsorberWallWidthTC * DeltaL * ConvTransCoeffWallFluid * SurfTempAbsorberWall;
     882             : 
     883      264960 :             for (ThermChimLoop1 = 1; ThermChimLoop1 <= NTC; ++ThermChimLoop1) {
     884     3974400 :                 for (ThermChimLoop2 = 1; ThermChimLoop2 <= NTC; ++ThermChimLoop2) {
     885     3726000 :                     EquaCoef(ThermChimLoop2, ThermChimLoop1) = 0.0;
     886             :                 }
     887             :             }
     888             : 
     889       16560 :             EquaCoef(1, 1) = Process2;
     890       16560 :             EquaConst(1) = Process3 - Process1 * RoomAirTemp;
     891      248400 :             for (ThermChimLoop1 = 2; ThermChimLoop1 <= NTC; ++ThermChimLoop1) {
     892      231840 :                 EquaCoef((ThermChimLoop1 - 1), ThermChimLoop1) = Process1;
     893      231840 :                 EquaCoef(ThermChimLoop1, ThermChimLoop1) = Process2;
     894      231840 :                 EquaConst(ThermChimLoop1) = Process3;
     895             :             }
     896             : 
     897       16560 :             GaussElimination(EquaCoef, EquaConst, ThermChimSubTemp, NTC);
     898             : 
     899       16560 :             AirRelativeCrossArea = AirOutletCrossAreaTC / AirInletCrossArea;
     900       16560 :             if (ThermChimSubTemp(NTC) <= RoomAirTemp) {
     901        4953 :                 TCVolumeAirFlowRate = 0.0;
     902             :             } else {
     903       23214 :                 TCVolumeAirFlowRate = DischargeCoeffTC * AirOutletCrossAreaTC *
     904       11607 :                                       std::sqrt(2.0 * ((ThermChimSubTemp(NTC) - RoomAirTemp) / RoomAirTemp) * 9.8 * OverallThermalChimLength /
     905       11607 :                                                 pow_2(1.0 + AirRelativeCrossArea));
     906       11607 :                 if (state.dataThermalChimneys->ThermalChimneySys(Loop).EMSOverrideOn) {
     907           0 :                     TCVolumeAirFlowRate = state.dataThermalChimneys->ThermalChimneySys(Loop).EMSAirFlowRateValue;
     908             :                 }
     909             :             }
     910             : 
     911             :             // Now assignment of the overall mass flow rate into each zone
     912       33120 :             for (int TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
     913       16560 :                 int tcZonePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum);
     914       16560 :                 auto &thisTCZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(tcZonePtr);
     915       16560 :                 Real64 tcZoneMAT = thisTCZoneHB.MAT;
     916       16560 :                 Real64 tcZoneHumRat = thisTCZoneHB.airHumRat;
     917       16560 :                 int tcSpacePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr(TCZoneNum);
     918       16560 :                 if ((state.dataHeatBal->doSpaceHeatBalance) && (tcSpacePtr > 0)) {
     919           0 :                     auto &thisTCSpaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(tcSpacePtr);
     920           0 :                     tcZoneMAT = thisTCSpaceHB.MAT;
     921           0 :                     tcZoneHumRat = thisTCSpaceHB.airHumRat;
     922             :                 }
     923             :                 // ToDo - Let this persist to avoid diffs, but should be local
     924       16560 :                 AirDensity = PsyRhoAirFnPbTdbW(state, state.dataEnvrn->OutBaroPress, tcZoneMAT, tcZoneHumRat);
     925       16560 :                 CpAir = PsyCpAirFnW(tcZoneHumRat);
     926             :                 Real64 thisMCPThermChim =
     927       16560 :                     TCVolumeAirFlowRate * AirDensity * CpAir * state.dataThermalChimneys->ThermalChimneySys(Loop).RatioThermChimAirFlow(TCZoneNum);
     928       16560 :                 if (thisMCPThermChim <= 0.0) {
     929        4953 :                     thisMCPThermChim = 0.0;
     930             :                 }
     931       16560 :                 Real64 thisThermChimAMFL = thisMCPThermChim / CpAir;
     932       16560 :                 Real64 thisMCPTThermChim = thisMCPThermChim * state.dataHeatBal->Zone(tcZonePtr).OutDryBulbTemp; // Only zones have an ODB temp value
     933       16560 :                 thisTCZoneHB.MCPThermChim = thisMCPThermChim;
     934       16560 :                 thisTCZoneHB.ThermChimAMFL = thisThermChimAMFL;
     935       16560 :                 thisTCZoneHB.MCPTThermChim = thisMCPTThermChim;
     936       16560 :                 if ((state.dataHeatBal->doSpaceHeatBalance) && (tcSpacePtr > 0)) {
     937           0 :                     auto &thisTCSpaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(tcSpacePtr);
     938           0 :                     thisTCSpaceHB.MCPThermChim = thisMCPThermChim;
     939           0 :                     thisTCSpaceHB.ThermChimAMFL = thisThermChimAMFL;
     940           0 :                     thisTCSpaceHB.MCPTThermChim = thisMCPTThermChim;
     941             :                 }
     942             :             }
     943             : 
     944             :             // ToDo - This should probably be using AirDensityThermalChim here instead of AirDensity which is leftover from the last inlet zone
     945       16560 :             thisZoneHB.MCPThermChim = TCVolumeAirFlowRate * AirDensity * CpAir;
     946       16560 :             if (thisZoneHB.MCPThermChim <= 0.0) {
     947        4953 :                 thisZoneHB.MCPThermChim = 0.0;
     948             :             }
     949       16560 :             thisZoneHB.ThermChimAMFL = thisZoneHB.MCPThermChim / CpAir;
     950       16560 :             thisZoneHB.MCPTThermChim = thisZoneHB.MCPThermChim * state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp;
     951             : 
     952       16560 :             state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlow = TCVolumeAirFlowRate;
     953       16560 :             state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCMassFlow = TCMassAirFlowRate;
     954       16560 :             state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlowStd = TCMassAirFlowRate / state.dataEnvrn->StdRhoAir;
     955       16560 :             if (state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCMassFlow != (TCVolumeAirFlowRate * AirDensityThermalChim)) {
     956        5316 :                 state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCMassFlow =
     957        5316 :                     state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlow * AirDensityThermalChim;
     958             :             }
     959       16560 :             state.dataThermalChimneys->ThermalChimneyReport(Loop).OutletAirTempThermalChim = ThermChimSubTemp(NTC) - Constant::Kelvin;
     960             : 
     961       16560 :             if (GetCurrentScheduleValue(state, state.dataThermalChimneys->ThermalChimneySys(Loop).SchedPtr) <= 0.0) {
     962       16560 :                 for (int TCZoneNum = 1; TCZoneNum <= state.dataThermalChimneys->ThermalChimneySys(Loop).TotZoneToDistrib; ++TCZoneNum) {
     963        8280 :                     int tcZonePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).ZonePtr(TCZoneNum);
     964        8280 :                     auto &thisTCZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(tcZonePtr);
     965        8280 :                     thisTCZoneHB.MCPThermChim = 0.0;
     966        8280 :                     thisTCZoneHB.ThermChimAMFL = 0.0;
     967        8280 :                     thisTCZoneHB.MCPTThermChim = 0.0;
     968        8280 :                     int tcSpacePtr = state.dataThermalChimneys->ThermalChimneySys(Loop).spacePtr(TCZoneNum);
     969        8280 :                     if ((state.dataHeatBal->doSpaceHeatBalance) && (tcSpacePtr > 0)) {
     970           0 :                         auto &thisTCSpaceHB = state.dataZoneTempPredictorCorrector->spaceHeatBalance(tcSpacePtr);
     971           0 :                         thisTCSpaceHB.MCPThermChim = 0.0;
     972           0 :                         thisTCSpaceHB.ThermChimAMFL = 0.0;
     973           0 :                         thisTCSpaceHB.MCPTThermChim = 0.0;
     974             :                     }
     975             :                 }
     976        8280 :                 thisZoneHB.MCPThermChim = 0.0;
     977        8280 :                 thisZoneHB.ThermChimAMFL = 0.0;
     978        8280 :                 thisZoneHB.MCPTThermChim = 0.0;
     979        8280 :                 state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlow = 0.0;
     980        8280 :                 state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCVolumeFlowStd = 0.0;
     981        8280 :                 state.dataThermalChimneys->ThermalChimneyReport(Loop).OverallTCMassFlow = 0.0;
     982        8280 :                 state.dataThermalChimneys->ThermalChimneyReport(Loop).OutletAirTempThermalChim =
     983        8280 :                     state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
     984             :             }
     985             : 
     986             :         } // DO Loop=1, TotThermalChimney
     987        8280 :     }
     988             : 
     989        8280 :     void ReportThermalChimney(EnergyPlusData &state)
     990             :     {
     991             : 
     992             :         // SUBROUTINE INFORMATION:
     993             :         //       AUTHOR         Kwang Ho Lee
     994             :         //       DATE WRITTEN   April 2008
     995             :         //       MODIFIED       na
     996             :         //       RE-ENGINEERED  na
     997             : 
     998             :         // PURPOSE OF THIS SUBROUTINE:
     999             :         // This subroutine fills remaining report variables.
    1000             : 
    1001        8280 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    1002             : 
    1003             :         int ZoneLoop; // Counter for the # of zones (nz)
    1004             :         Real64 AirDensity;
    1005             :         Real64 CpAir;
    1006             : 
    1007       41400 :         for (ZoneLoop = 1; ZoneLoop <= state.dataGlobal->NumOfZones; ++ZoneLoop) { // Start of zone loads report variable update loop ...
    1008       33120 :             auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop);
    1009             : 
    1010             :             // Break the infiltration load into heat gain and loss components.
    1011       66240 :             AirDensity = PsyRhoAirFnPbTdbW(
    1012       33120 :                 state, state.dataEnvrn->OutBaroPress, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop).MAT, thisZoneHB.airHumRat);
    1013       33120 :             CpAir = PsyCpAirFnW(thisZoneHB.airHumRat);
    1014       33120 :             state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyVolume =
    1015       33120 :                 (thisZoneHB.MCPThermChim / CpAir / AirDensity) * TimeStepSysSec;
    1016       33120 :             state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyMass = (thisZoneHB.MCPThermChim / CpAir) * TimeStepSysSec;
    1017             : 
    1018       33120 :             state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatLoss = 0.0;
    1019       33120 :             state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatGain = 0.0;
    1020             : 
    1021       33120 :             if (state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop).ZT > state.dataHeatBal->Zone(ZoneLoop).OutDryBulbTemp) {
    1022             : 
    1023       26179 :                 state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatLoss =
    1024       52358 :                     thisZoneHB.MCPThermChim *
    1025       26179 :                     (state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop).ZT - state.dataHeatBal->Zone(ZoneLoop).OutDryBulbTemp) *
    1026             :                     TimeStepSysSec;
    1027       26179 :                 state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatGain = 0.0;
    1028             : 
    1029        6941 :             } else if (state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop).ZT <= state.dataHeatBal->Zone(ZoneLoop).OutDryBulbTemp) {
    1030             : 
    1031        6941 :                 state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatGain =
    1032       13882 :                     thisZoneHB.MCPThermChim *
    1033        6941 :                     (state.dataHeatBal->Zone(ZoneLoop).OutDryBulbTemp - state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneLoop).ZT) *
    1034             :                     TimeStepSysSec;
    1035        6941 :                 state.dataThermalChimneys->ZnRptThermChim(ZoneLoop).ThermalChimneyHeatLoss = 0.0;
    1036             :             }
    1037             : 
    1038             :         } // ... end of zone loads report variable update loop.
    1039        8280 :     }
    1040             : 
    1041      182160 :     void GaussElimination(Array2A<Real64> EquaCoef, Array1D<Real64> &EquaConst, Array1D<Real64> &ThermChimSubTemp, int const NTC)
    1042             :     {
    1043             :         // PURPOSE OF THIS SUBROUTINE:
    1044             :         // This subroutine sovles linear algebraic equations using Gauss Elimination Method.
    1045             : 
    1046      182160 :         EquaCoef.dim(NTC, NTC);
    1047      182160 :         EP_SIZE_CHECK(EquaConst, NTC);
    1048      182160 :         EP_SIZE_CHECK(ThermChimSubTemp, NTC);
    1049             : 
    1050      182160 :         Array1D<Real64> tempor(NTC);
    1051             :         Real64 tempb;
    1052             :         Real64 TCvalue;
    1053             :         Real64 TCcoefficient;
    1054             :         int pivot;
    1055             :         Real64 ThermalChimSum;
    1056             :         int ThermChimLoop1;
    1057             :         int ThermChimLoop2;
    1058             :         int ThermChimLoop3;
    1059             : 
    1060     2914560 :         for (ThermChimLoop1 = 1; ThermChimLoop1 <= NTC; ++ThermChimLoop1) {
    1061             : 
    1062     2732400 :             TCvalue = std::abs(EquaCoef(ThermChimLoop1, ThermChimLoop1));
    1063     2732400 :             pivot = ThermChimLoop1;
    1064    21859200 :             for (ThermChimLoop2 = ThermChimLoop1 + 1; ThermChimLoop2 <= NTC; ++ThermChimLoop2) {
    1065    19126800 :                 if (std::abs(EquaCoef(ThermChimLoop1, ThermChimLoop2)) > TCvalue) {
    1066           0 :                     TCvalue = std::abs(EquaCoef(ThermChimLoop1, ThermChimLoop2));
    1067           0 :                     pivot = ThermChimLoop2;
    1068             :                 }
    1069             :             }
    1070             : 
    1071     2732400 :             if (pivot != ThermChimLoop1) {
    1072           0 :                 tempor({ThermChimLoop1, NTC}) = EquaCoef({ThermChimLoop1, NTC}, ThermChimLoop1);
    1073           0 :                 tempb = EquaConst(ThermChimLoop1);
    1074           0 :                 EquaCoef({ThermChimLoop1, NTC}, ThermChimLoop1) = EquaCoef({ThermChimLoop1, NTC}, pivot);
    1075           0 :                 EquaConst(ThermChimLoop1) = EquaConst(pivot);
    1076           0 :                 EquaCoef({ThermChimLoop1, NTC}, pivot) = tempor({ThermChimLoop1, NTC});
    1077           0 :                 EquaConst(pivot) = tempb;
    1078             :             }
    1079             : 
    1080    21859200 :             for (ThermChimLoop2 = ThermChimLoop1 + 1; ThermChimLoop2 <= NTC; ++ThermChimLoop2) {
    1081    19126800 :                 TCcoefficient = -EquaCoef(ThermChimLoop1, ThermChimLoop2) / EquaCoef(ThermChimLoop1, ThermChimLoop1);
    1082    19126800 :                 EquaCoef({ThermChimLoop1, NTC}, ThermChimLoop2) += TCcoefficient * EquaCoef({ThermChimLoop1, NTC}, ThermChimLoop1);
    1083    19126800 :                 EquaConst(ThermChimLoop2) += TCcoefficient * EquaConst(ThermChimLoop1);
    1084             :             }
    1085             :         }
    1086             : 
    1087      182160 :         ThermChimSubTemp(NTC) = EquaConst(NTC) / EquaCoef(NTC, NTC);
    1088     2732400 :         for (ThermChimLoop2 = NTC - 1; ThermChimLoop2 >= 1; --ThermChimLoop2) {
    1089     2550240 :             ThermalChimSum = 0.0;
    1090    21677040 :             for (ThermChimLoop3 = ThermChimLoop2 + 1; ThermChimLoop3 <= NTC; ++ThermChimLoop3) {
    1091    19126800 :                 ThermalChimSum += EquaCoef(ThermChimLoop3, ThermChimLoop2) * ThermChimSubTemp(ThermChimLoop3);
    1092             :             }
    1093     2550240 :             ThermChimSubTemp(ThermChimLoop2) = (EquaConst(ThermChimLoop2) - ThermalChimSum) / EquaCoef(ThermChimLoop2, ThermChimLoop2);
    1094             :         }
    1095      182160 :     }
    1096             : 
    1097             :     //        End of Module Subroutines for ThermalChimney
    1098             : 
    1099             :     //*****************************************************************************************
    1100             : 
    1101             : } // namespace ThermalChimney
    1102             : 
    1103             : } // namespace EnergyPlus

Generated by: LCOV version 1.14