LCOV - code coverage report
Current view: top level - EnergyPlus - ThermalChimney.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 68.5 % 543 372
Test Date: 2025-05-22 16:09:37 Functions: 80.0 % 5 4

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

Generated by: LCOV version 2.0-1