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

Generated by: LCOV version 2.0-1