LCOV - code coverage report
Current view: top level - EnergyPlus - MundtSimMgr.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 268 302 88.7 %
Date: 2023-01-17 19:17:23 Functions: 10 10 100.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, 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             : // ObjexxFCL Headers
      49             : #include <ObjexxFCL/Array.functions.hh>
      50             : #include <ObjexxFCL/Fmath.hh>
      51             : 
      52             : // EnergyPlus Headers
      53             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      54             : #include <EnergyPlus/DataEnvironment.hh>
      55             : #include <EnergyPlus/DataHeatBalFanSys.hh>
      56             : #include <EnergyPlus/DataHeatBalSurface.hh>
      57             : #include <EnergyPlus/DataHeatBalance.hh>
      58             : #include <EnergyPlus/DataLoopNode.hh>
      59             : #include <EnergyPlus/DataRoomAirModel.hh>
      60             : #include <EnergyPlus/DataSurfaces.hh>
      61             : #include <EnergyPlus/DataZoneEquipment.hh>
      62             : #include <EnergyPlus/InternalHeatGains.hh>
      63             : #include <EnergyPlus/MundtSimMgr.hh>
      64             : #include <EnergyPlus/OutputProcessor.hh>
      65             : #include <EnergyPlus/Psychrometrics.hh>
      66             : #include <EnergyPlus/UtilityRoutines.hh>
      67             : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      68             : 
      69             : namespace EnergyPlus {
      70             : 
      71             : namespace MundtSimMgr {
      72             : 
      73             :     // MODULE INFORMATION:
      74             :     //       AUTHOR         Brent Griffith
      75             :     //       DATE WRITTEN   February 2002
      76             :     //       RE-ENGINEERED  June 2003, EnergyPlus Implementation (CC)
      77             :     //       MODIFIED       February 2004, fix allocate-deallocate problem (CC)
      78             : 
      79             :     // PURPOSE OF THIS MODULE:
      80             :     // This module is the main module for running the
      81             :     // nodal air Mundt model...
      82             : 
      83             :     // METHODOLOGY EMPLOYED:
      84             :     // This module contains all subroutines required by the mundt model.
      85             :     // The following modules from AirToolkit included in this module are:
      86             :     // 1) MundtSimMgr Module,
      87             :     // 2) MundtInputMgr Module, and
      88             :     // 3) DataMundt Module,
      89             : 
      90             :     // REFERENCES:
      91             :     // AirToolkit source code
      92             : 
      93             :     // OTHER NOTES:
      94             :     // na
      95             : 
      96             :     // Data
      97             :     // MODULE PARAMETER DEFINITIONS:
      98             :     Real64 constexpr CpAir(1005.0);   // Specific heat of air
      99             :     Real64 constexpr MinSlope(0.001); // Bound on result from Mundt model
     100             :     Real64 constexpr MaxSlope(5.0);   // Bound on result from Mundt Model
     101             : 
     102             :     // MODULE VARIABLE DECLARATIONS:
     103             : 
     104       17126 :     void ManageMundtModel(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
     105             :     {
     106             : 
     107             :         // SUBROUTINE INFORMATION:
     108             :         //       AUTHOR         Chanvit Chantrasrisalai
     109             :         //       DATE WRITTEN   July 2003
     110             :         //       MODIFIED       February 2004, fix allocate-deallocate problem (CC)
     111             :         //       RE-ENGINEERED  na
     112             : 
     113             :         // PURPOSE OF THIS SUBROUTINE:
     114             :         //   manage the Mundt model
     115             : 
     116       17126 :         auto &MundtFirstTimeFlag = state.dataHeatBal->MundtFirstTimeFlag;
     117             :         bool ErrorsFound;
     118             : 
     119             :         // initialize Mundt model data
     120       17126 :         if (MundtFirstTimeFlag) {
     121           2 :             InitMundtModel(state);
     122           2 :             MundtFirstTimeFlag = false;
     123             :         }
     124             : 
     125             :         // identify the current zone index for zones using Mundt model
     126       17126 :         state.dataMundtSimMgr->MundtZoneNum = state.dataMundtSimMgr->ZoneData(ZoneNum).MundtZoneIndex;
     127             : 
     128             :         // transfer data from surface domain to air domain for the specified zone
     129       17126 :         GetSurfHBDataForMundtModel(state, ZoneNum);
     130             : 
     131             :         // use the Mundt model only for cooling case
     132       17126 :         if ((state.dataMundtSimMgr->SupplyAirVolumeRate > 0.0001) && (state.dataMundtSimMgr->QsysCoolTot > 0.0001)) {
     133             : 
     134             :             // setup Mundt model
     135        8672 :             ErrorsFound = false;
     136        8672 :             SetupMundtModel(state, ZoneNum, ErrorsFound);
     137        8672 :             if (ErrorsFound) ShowFatalError(state, "ManageMundtModel: Errors in setting up Mundt Model. Preceding condition(s) cause termination.");
     138             : 
     139             :             // perform Mundt model calculations
     140        8672 :             CalcMundtModel(state, ZoneNum);
     141             :         }
     142             : 
     143             :         // transfer data from air domain back to surface domain for the specified zone
     144       17126 :         SetSurfHBDataForMundtModel(state, ZoneNum);
     145       17126 :     }
     146             : 
     147             :     //*****************************************************************************************
     148             : 
     149           2 :     void InitMundtModel(EnergyPlusData &state)
     150             :     {
     151             : 
     152             :         // SUBROUTINE INFORMATION:
     153             :         //       AUTHOR         Chanvit Chantrasrisalai
     154             :         //       DATE WRITTEN   February 2004
     155             :         //       MODIFIED       na
     156             :         //       RE-ENGINEERED  na
     157             : 
     158             :         // PURPOSE OF THIS SUBROUTINE:
     159             :         //     initialize Mundt-model variables
     160             : 
     161             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     162             :         int NodeNum;            // index for air nodes
     163             :         int ZoneIndex;          // index for zones
     164             :         int NumOfAirNodes;      // total number of nodes in each zone
     165             :         int NumOfMundtZones;    // number of zones using the Mundt model
     166             :         int MundtZoneIndex;     // index for zones using the Mundt model
     167             :         int MaxNumOfSurfs;      // maximum of number of surfaces
     168             :         int MaxNumOfFloorSurfs; // maximum of number of surfaces
     169             :         int MaxNumOfAirNodes;   // maximum of number of air nodes
     170             :         int MaxNumOfRoomNodes;  // maximum of number of nodes connected to walls
     171             :         int RoomNodesCount;     // number of nodes connected to walls
     172             :         int FloorSurfCount;     // number of nodes connected to walls
     173             :         int AirNodeBeginNum;    // index number of the first air node for this zone
     174             :         int AirNodeNum;         // index for air nodes
     175             :         bool AirNodeFoundFlag;  // flag used for error check
     176             :         bool ErrorsFound;       // true if errors found in init
     177             : 
     178             :         // allocate and initialize zone data
     179           2 :         state.dataMundtSimMgr->ZoneData.allocate(state.dataGlobal->NumOfZones);
     180          10 :         for (auto &e : state.dataMundtSimMgr->ZoneData) {
     181           8 :             e.NumOfSurfs = 0;
     182           8 :             e.MundtZoneIndex = 0;
     183             :         }
     184             : 
     185             :         // get zone data
     186           2 :         NumOfMundtZones = 0;
     187           2 :         MaxNumOfSurfs = 0;
     188           2 :         MaxNumOfFloorSurfs = 0;
     189           2 :         MaxNumOfAirNodes = 0;
     190           2 :         MaxNumOfRoomNodes = 0;
     191           2 :         ErrorsFound = false;
     192          10 :         for (ZoneIndex = 1; ZoneIndex <= state.dataGlobal->NumOfZones; ++ZoneIndex) {
     193           8 :             auto &thisZone = state.dataHeatBal->Zone(ZoneIndex);
     194           8 :             if (state.dataRoomAirMod->AirModel(ZoneIndex).AirModelType == DataRoomAirModel::RoomAirModel::Mundt) {
     195             :                 // find number of zones using the Mundt model
     196           4 :                 ++NumOfMundtZones;
     197             :                 // find maximum number of surfaces in zones using the Mundt model
     198           4 :                 int NumOfSurfs = 0;
     199           8 :                 for (int spaceNum : thisZone.spaceIndexes) {
     200           4 :                     auto &thisSpace = state.dataHeatBal->space(spaceNum);
     201          92 :                     for (int surfNum = thisSpace.HTSurfaceFirst; surfNum <= thisSpace.HTSurfaceLast; ++surfNum) {
     202          88 :                         state.dataMundtSimMgr->ZoneData(ZoneIndex).HBsurfaceIndexes.emplace_back(surfNum);
     203          88 :                         ++NumOfSurfs;
     204             :                     }
     205           4 :                     MaxNumOfSurfs = max(MaxNumOfSurfs, NumOfSurfs);
     206             :                     // find maximum number of air nodes in zones using the Mundt model
     207           4 :                     NumOfAirNodes = state.dataRoomAirMod->TotNumOfZoneAirNodes(ZoneIndex);
     208           4 :                     MaxNumOfAirNodes = max(MaxNumOfAirNodes, NumOfAirNodes);
     209             :                     // assign zone data
     210           4 :                     state.dataMundtSimMgr->ZoneData(ZoneIndex).NumOfSurfs = NumOfSurfs;
     211           4 :                     state.dataMundtSimMgr->ZoneData(ZoneIndex).MundtZoneIndex = NumOfMundtZones;
     212             :                 }
     213             :             }
     214             :         }
     215             : 
     216             :         // allocate and initialize surface and air-node data
     217           2 :         state.dataMundtSimMgr->ID1dSurf.allocate(MaxNumOfSurfs);
     218           2 :         state.dataMundtSimMgr->TheseSurfIDs.allocate(MaxNumOfSurfs);
     219           2 :         state.dataMundtSimMgr->MundtAirSurf.allocate(MaxNumOfSurfs, NumOfMundtZones);
     220           2 :         state.dataMundtSimMgr->LineNode.allocate(MaxNumOfAirNodes, NumOfMundtZones);
     221          46 :         for (int SurfNum = 1; SurfNum <= MaxNumOfSurfs; ++SurfNum)
     222          44 :             state.dataMundtSimMgr->ID1dSurf(SurfNum) = SurfNum;
     223          90 :         for (auto &e : state.dataMundtSimMgr->MundtAirSurf) {
     224          88 :             e.Area = 0.0;
     225          88 :             e.Temp = 25.0;
     226          88 :             e.Hc = 0.0;
     227          88 :             e.TMeanAir = 25.0;
     228             :         }
     229          38 :         for (auto &e : state.dataMundtSimMgr->LineNode) {
     230          36 :             e.AirNodeName.clear();
     231          36 :             e.ClassType = DataRoomAirModel::AirNodeType::Invalid;
     232          36 :             e.Height = 0.0;
     233          36 :             e.Temp = 25.0;
     234             :         }
     235             : 
     236             :         // get constant data (unchanged over time) for surfaces and air nodes
     237           6 :         for (MundtZoneIndex = 1; MundtZoneIndex <= NumOfMundtZones; ++MundtZoneIndex) {
     238          10 :             for (ZoneIndex = 1; ZoneIndex <= state.dataGlobal->NumOfZones; ++ZoneIndex) {
     239          10 :                 auto &thisZone = state.dataHeatBal->Zone(ZoneIndex);
     240          10 :                 if (state.dataMundtSimMgr->ZoneData(ZoneIndex).MundtZoneIndex == MundtZoneIndex) {
     241             :                     // get surface data
     242          92 :                     for (int surfNum = 1; surfNum <= state.dataMundtSimMgr->ZoneData(ZoneIndex).NumOfSurfs; ++surfNum) {
     243          88 :                         state.dataMundtSimMgr->MundtAirSurf(surfNum, MundtZoneIndex).Area =
     244          88 :                             state.dataSurface->Surface(state.dataMundtSimMgr->ZoneData(ZoneIndex).HBsurfaceIndexes(surfNum)).Area;
     245             :                     }
     246             : 
     247             :                     // get air node data
     248           4 :                     RoomNodesCount = 0;
     249           4 :                     FloorSurfCount = 0;
     250          40 :                     for (NodeNum = 1; NodeNum <= state.dataRoomAirMod->TotNumOfZoneAirNodes(ZoneIndex); ++NodeNum) {
     251             : 
     252          36 :                         state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex)
     253          36 :                             .SurfMask.allocate(state.dataMundtSimMgr->ZoneData(ZoneIndex).NumOfSurfs);
     254             : 
     255          36 :                         if (NodeNum == 1) {
     256           4 :                             AirNodeBeginNum = NodeNum;
     257             :                         }
     258             : 
     259             :                         // error check for debugging
     260          36 :                         if (AirNodeBeginNum > state.dataRoomAirMod->TotNumOfAirNodes) {
     261           0 :                             ShowFatalError(state, "An array bound exceeded. Error in InitMundtModel subroutine of MundtSimMgr.");
     262             :                         }
     263             : 
     264          36 :                         AirNodeFoundFlag = false;
     265          54 :                         for (AirNodeNum = AirNodeBeginNum; AirNodeNum <= state.dataRoomAirMod->TotNumOfAirNodes; ++AirNodeNum) {
     266          54 :                             if (UtilityRoutines::SameString(state.dataRoomAirMod->AirNode(AirNodeNum).ZoneName, thisZone.Name)) {
     267          36 :                                 state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).ClassType =
     268          36 :                                     state.dataRoomAirMod->AirNode(AirNodeNum).ClassType;
     269          36 :                                 state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).AirNodeName = state.dataRoomAirMod->AirNode(AirNodeNum).Name;
     270          36 :                                 state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).Height = state.dataRoomAirMod->AirNode(AirNodeNum).Height;
     271          72 :                                 state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).SurfMask =
     272          72 :                                     state.dataRoomAirMod->AirNode(AirNodeNum).SurfMask;
     273         144 :                                 SetupOutputVariable(state,
     274             :                                                     "Room Air Node Air Temperature",
     275             :                                                     OutputProcessor::Unit::C,
     276          36 :                                                     state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).Temp,
     277             :                                                     OutputProcessor::SOVTimeStepType::HVAC,
     278             :                                                     OutputProcessor::SOVStoreType::Average,
     279          72 :                                                     state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).AirNodeName);
     280             : 
     281          36 :                                 AirNodeBeginNum = AirNodeNum + 1;
     282          36 :                                 AirNodeFoundFlag = true;
     283             : 
     284          36 :                                 break;
     285             :                             }
     286             :                         }
     287             : 
     288             :                         // error check for debugging
     289          36 :                         if (!AirNodeFoundFlag) {
     290           0 :                             ShowSevereError(state, "InitMundtModel: Air Node in Zone=\"" + thisZone.Name + "\" is not found.");
     291           0 :                             ErrorsFound = true;
     292           0 :                             continue;
     293             :                         }
     294             : 
     295             :                         // count air nodes connected to walls in each zone
     296          36 :                         if (state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).ClassType == DataRoomAirModel::AirNodeType::MundtRoomAir) {
     297          16 :                             ++RoomNodesCount;
     298             :                         }
     299             : 
     300             :                         // count floors in each zone
     301          36 :                         if (state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).ClassType == DataRoomAirModel::AirNodeType::FloorAir) {
     302           4 :                             FloorSurfCount += count(state.dataMundtSimMgr->LineNode(NodeNum, MundtZoneIndex).SurfMask);
     303             :                         }
     304             :                     }
     305             :                     // got data for this zone so exit the zone loop
     306           4 :                     if (AirNodeFoundFlag) break;
     307             :                 }
     308             :             }
     309             : 
     310           4 :             MaxNumOfRoomNodes = max(MaxNumOfRoomNodes, RoomNodesCount);
     311           4 :             MaxNumOfFloorSurfs = max(MaxNumOfFloorSurfs, FloorSurfCount);
     312             :         }
     313             : 
     314           2 :         if (ErrorsFound) ShowFatalError(state, "InitMundtModel: Preceding condition(s) cause termination.");
     315             : 
     316             :         // allocate arrays
     317           2 :         state.dataMundtSimMgr->RoomNodeIDs.allocate(MaxNumOfRoomNodes);
     318           2 :         state.dataMundtSimMgr->FloorSurfSetIDs.allocate(MaxNumOfFloorSurfs);
     319           2 :         state.dataMundtSimMgr->FloorSurf.allocate(MaxNumOfFloorSurfs);
     320           2 :     }
     321             : 
     322             :     //*****************************************************************************************
     323             : 
     324       17126 :     void GetSurfHBDataForMundtModel(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
     325             :     {
     326             : 
     327             :         // SUBROUTINE INFORMATION:
     328             :         //       AUTHOR         Weixiu Kong
     329             :         //       DATE WRITTEN   April 2003
     330             :         //       MODIFIED       July 2003 (CC)
     331             :         //                      February 2004, fix allocate-deallocate problem (CC)
     332             : 
     333             :         // PURPOSE OF THIS SUBROUTINE:
     334             :         //     map data from surface domain to air domain for each particular zone
     335             : 
     336             :         using Psychrometrics::PsyCpAirFnW;
     337             :         using Psychrometrics::PsyRhoAirFnPbTdbW;
     338             :         using Psychrometrics::PsyWFnTdpPb;
     339             : 
     340             :         Real64 CpAir;            // specific heat
     341             :         int NodeNum;             // index for air nodes
     342             :         Real64 SumSysMCp;        // zone sum of air system MassFlowRate*Cp
     343             :         Real64 SumSysMCpT;       // zone sum of air system MassFlowRate*Cp*T
     344             :         Real64 MassFlowRate;     // mass flowrate
     345             :         Real64 NodeTemp;         // node temperature
     346             :         int ZoneNode;            // index number for specified zone node
     347             :         Real64 ZoneMassFlowRate; // zone mass flowrate
     348             :         int ZoneEquipConfigNum;  // index number for zone equipment configuration
     349             :         Real64 ZoneMult;         // total zone multiplier
     350             :         Real64 RetAirConvGain;
     351             : 
     352       17126 :         auto &Zone(state.dataHeatBal->Zone);
     353             : 
     354             :         // determine ZoneEquipConfigNum for this zone
     355       17126 :         ZoneEquipConfigNum = ZoneNum;
     356             :         // check whether this zone is a controlled zone or not
     357       17126 :         if (!Zone(ZoneNum).IsControlled) {
     358           0 :             ShowFatalError(state, "Zones must be controlled for Mundt air model. No system serves zone " + Zone(ZoneNum).Name);
     359           0 :             return;
     360             :         }
     361             : 
     362             :         // determine information required by Mundt model
     363       17126 :         state.dataMundtSimMgr->ZoneHeight = Zone(ZoneNum).CeilingHeight;
     364       17126 :         state.dataMundtSimMgr->ZoneFloorArea = Zone(ZoneNum).FloorArea;
     365       17126 :         ZoneMult = Zone(ZoneNum).Multiplier * Zone(ZoneNum).ListMultiplier;
     366             : 
     367             :         // supply air flowrate is the same as zone air flowrate
     368       17126 :         ZoneNode = Zone(ZoneNum).SystemZoneNodeNumber;
     369       17126 :         state.dataMundtSimMgr->ZoneAirDensity =
     370       85630 :             PsyRhoAirFnPbTdbW(state,
     371       17126 :                               state.dataEnvrn->OutBaroPress,
     372       17126 :                               state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT,
     373       34252 :                               PsyWFnTdpPb(state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT, state.dataEnvrn->OutBaroPress));
     374       17126 :         ZoneMassFlowRate = state.dataLoopNodes->Node(ZoneNode).MassFlowRate;
     375       17126 :         state.dataMundtSimMgr->SupplyAirVolumeRate = ZoneMassFlowRate / state.dataMundtSimMgr->ZoneAirDensity;
     376       17126 :         auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
     377       17126 :         if (ZoneMassFlowRate <= 0.0001) {
     378             :             // system is off
     379         351 :             state.dataMundtSimMgr->QsysCoolTot = 0.0;
     380             :         } else {
     381             :             // determine supply air conditions
     382       16775 :             SumSysMCp = 0.0;
     383       16775 :             SumSysMCpT = 0.0;
     384       33550 :             for (NodeNum = 1; NodeNum <= state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).NumInletNodes; ++NodeNum) {
     385       16775 :                 NodeTemp = state.dataLoopNodes->Node(state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).InletNode(NodeNum)).Temp;
     386       16775 :                 MassFlowRate = state.dataLoopNodes->Node(state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).InletNode(NodeNum)).MassFlowRate;
     387       16775 :                 CpAir = PsyCpAirFnW(thisZoneHB.ZoneAirHumRat);
     388       16775 :                 SumSysMCp += MassFlowRate * CpAir;
     389       16775 :                 SumSysMCpT += MassFlowRate * CpAir * NodeTemp;
     390             :             }
     391             :             // prevent dividing by zero due to zero supply air flow rate
     392       16775 :             if (SumSysMCp <= 0.0) {
     393           0 :                 state.dataMundtSimMgr->SupplyAirTemp =
     394           0 :                     state.dataLoopNodes->Node(state.dataZoneEquip->ZoneEquipConfig(ZoneEquipConfigNum).InletNode(1)).Temp;
     395             :             } else {
     396             :                 // a weighted average of the inlet temperatures
     397       16775 :                 state.dataMundtSimMgr->SupplyAirTemp = SumSysMCpT / SumSysMCp;
     398             :             }
     399             :             // determine cooling load
     400       16775 :             CpAir = PsyCpAirFnW(thisZoneHB.ZoneAirHumRat);
     401       16775 :             state.dataMundtSimMgr->QsysCoolTot =
     402       16775 :                 -(SumSysMCpT - ZoneMassFlowRate * CpAir * state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT);
     403             :         }
     404             :         // determine heat gains
     405       17126 :         state.dataMundtSimMgr->ConvIntGain = InternalHeatGains::zoneSumAllInternalConvectionGains(state, ZoneNum);
     406       51378 :         state.dataMundtSimMgr->ConvIntGain += state.dataHeatBalFanSys->SumConvHTRadSys(ZoneNum) + state.dataHeatBalFanSys->SumConvPool(ZoneNum) +
     407       34252 :                                               thisZoneHB.SysDepZoneLoadsLagged + thisZoneHB.NonAirSystemResponse / ZoneMult;
     408             : 
     409             :         // Add heat to return air if zonal system (no return air) or cycling system (return air frequently very
     410             :         // low or zero)
     411       17126 :         if (Zone(ZoneNum).NoHeatToReturnAir) {
     412           0 :             RetAirConvGain = InternalHeatGains::zoneSumAllReturnAirConvectionGains(state, ZoneNum, 0);
     413           0 :             state.dataMundtSimMgr->ConvIntGain += RetAirConvGain;
     414             :         }
     415             : 
     416       17126 :         state.dataMundtSimMgr->QventCool =
     417       17126 :             -thisZoneHB.MCPI * (Zone(ZoneNum).OutDryBulbTemp - state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT);
     418             : 
     419             :         // get surface data
     420      393898 :         for (int SurfNum = 1; SurfNum <= state.dataMundtSimMgr->ZoneData(ZoneNum).NumOfSurfs; ++SurfNum) {
     421      376772 :             state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).Temp =
     422      376772 :                 state.dataHeatBalSurf->SurfTempIn(state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum));
     423      376772 :             state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).Hc =
     424      376772 :                 state.dataHeatBalSurf->SurfHConvInt(state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum));
     425             :         }
     426             :     }
     427             : 
     428             :     //*****************************************************************************************
     429             : 
     430        8672 :     void SetupMundtModel(EnergyPlusData &state,
     431             :                          int const ZoneNum, // index number for the specified zone
     432             :                          bool &ErrorsFound  // true if problems setting up model
     433             :     )
     434             :     {
     435             : 
     436             :         // SUBROUTINE INFORMATION:
     437             :         //       AUTHOR         Brent Griffith
     438             :         //       DATE WRITTEN   Febraury 2002
     439             :         //       RE-ENGINEERED  June 2003, EnergyPlus Implementation (CC)
     440             :         //       MODIFIED       February 2004, fix allocate-deallocate problem (CC)
     441             : 
     442             :         // PURPOSE OF THIS SUBROUTINE:
     443             :         //   Subroutine must be called once before main model calculation
     444             :         //   need to pass some zone characteristics only once
     445             :         //   initializes module level variables, collect info from Air Data Manager
     446             : 
     447             :         // METHODOLOGY EMPLOYED:
     448             :         // na
     449             : 
     450             :         // REFERENCES:
     451             :         // na
     452             : 
     453             :         // Using/Aliasing
     454             :         using namespace DataRoomAirModel;
     455             : 
     456             :         // Locals
     457             :         // SUBROUTINE ARGUMENT DEFINITIONS:
     458             : 
     459             :         // SUBROUTINE PARAMETER DEFINITIONS:
     460             :         // na
     461             : 
     462             :         // INTERFACE BLOCK SPECIFICATIONS:
     463             :         // na
     464             : 
     465             :         // DERIVED TYPE DEFINITIONS:
     466             :         // na
     467             : 
     468             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     469             :         int NodeNum; // index for air nodes
     470             :         int SurfNum; // index for surfaces
     471             : 
     472             :         // set up air node ID
     473        8672 :         state.dataMundtSimMgr->NumRoomNodes = 0;
     474       86720 :         for (NodeNum = 1; NodeNum <= state.dataRoomAirMod->TotNumOfZoneAirNodes(ZoneNum); ++NodeNum) {
     475       78048 :             switch (state.dataMundtSimMgr->LineNode(NodeNum, state.dataMundtSimMgr->MundtZoneNum).ClassType) {
     476        8672 :             case AirNodeType::InletAir: { // inlet
     477        8672 :                 state.dataMundtSimMgr->SupplyNodeID = NodeNum;
     478        8672 :             } break;
     479        8672 :             case AirNodeType::FloorAir: { // floor
     480        8672 :                 state.dataMundtSimMgr->MundtFootAirID = NodeNum;
     481        8672 :             } break;
     482        8672 :             case AirNodeType::ControlAir: { // thermostat
     483        8672 :                 state.dataMundtSimMgr->TstatNodeID = NodeNum;
     484        8672 :             } break;
     485        8672 :             case AirNodeType::CeilingAir: { // ceiling
     486        8672 :                 state.dataMundtSimMgr->MundtCeilAirID = NodeNum;
     487        8672 :             } break;
     488       34688 :             case AirNodeType::MundtRoomAir: { // wall
     489       34688 :                 ++state.dataMundtSimMgr->NumRoomNodes;
     490       34688 :                 state.dataMundtSimMgr->RoomNodeIDs(state.dataMundtSimMgr->NumRoomNodes) = NodeNum;
     491       34688 :             } break;
     492        8672 :             case AirNodeType::ReturnAir: { // return
     493        8672 :                 state.dataMundtSimMgr->ReturnNodeID = NodeNum;
     494        8672 :             } break;
     495           0 :             default: {
     496           0 :                 ShowSevereError(state, "SetupMundtModel: Non-Standard Type of Air Node for Mundt Model");
     497           0 :                 ErrorsFound = true;
     498           0 :             } break;
     499             :             }
     500             :         }
     501             : 
     502             :         //  get number of floors in the zone and setup FloorSurfSetIDs
     503        8672 :         if (state.dataMundtSimMgr->MundtFootAirID > 0) {
     504        8672 :             state.dataMundtSimMgr->NumFloorSurfs =
     505        8672 :                 count(state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
     506       17344 :             state.dataMundtSimMgr->FloorSurfSetIDs =
     507       17344 :                 pack(state.dataMundtSimMgr->ID1dSurf,
     508       17344 :                      state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
     509             :             // initialize floor surface data (a must since NumFloorSurfs is varied among zones)
     510       26016 :             for (auto &e : state.dataMundtSimMgr->FloorSurf) {
     511       17344 :                 e.Temp = 25.0;
     512       17344 :                 e.Hc = 0.0;
     513       17344 :                 e.Area = 0.0;
     514             :             }
     515             :             // get floor surface data
     516       26016 :             for (SurfNum = 1; SurfNum <= state.dataMundtSimMgr->NumFloorSurfs; ++SurfNum) {
     517       17344 :                 state.dataMundtSimMgr->FloorSurf(SurfNum).Temp =
     518       17344 :                     state.dataMundtSimMgr->MundtAirSurf(state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), state.dataMundtSimMgr->MundtZoneNum).Temp;
     519       17344 :                 state.dataMundtSimMgr->FloorSurf(SurfNum).Hc =
     520       17344 :                     state.dataMundtSimMgr->MundtAirSurf(state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), state.dataMundtSimMgr->MundtZoneNum).Hc;
     521       17344 :                 state.dataMundtSimMgr->FloorSurf(SurfNum).Area =
     522       17344 :                     state.dataMundtSimMgr->MundtAirSurf(state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), state.dataMundtSimMgr->MundtZoneNum).Area;
     523             :             }
     524             :         } else {
     525           0 :             ShowSevereError(state, "SetupMundtModel: Mundt model has no FloorAirNode, Zone=" + state.dataHeatBal->Zone(ZoneNum).Name);
     526           0 :             ErrorsFound = true;
     527             :         }
     528        8672 :     }
     529             : 
     530             :     //*****************************************************************************************
     531             : 
     532        8672 :     void CalcMundtModel(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
     533             :     {
     534             : 
     535             :         // SUBROUTINE INFORMATION:
     536             :         //       AUTHOR         Brent Griffith
     537             :         //       DATE WRITTEN   September 2001
     538             :         //       RE-ENGINEERED  July 2003, EnergyPlus Implementation (CC)
     539             :         //       MODIFIED       February 2004, fix allocate-deallocate problem (CC)
     540             : 
     541             :         // PURPOSE OF THIS SUBROUTINE:
     542             :         //   Compute the simplified version of Mundt and store results in Air data Manager
     543             :         //   argument passing is plentiful but are IN and nothing out.
     544             :         //   these variables are scaler conditions at current HB day,timestep, and iteration
     545             :         //   This subroutine is USE'ed by heat balance driver (top level module)
     546             : 
     547             :         // METHODOLOGY EMPLOYED:
     548             :         //   apply Mundt's simple model for delta Temp head-foot and update values in Air data manager.
     549             : 
     550             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     551             :         Real64 TAirFoot;        // air temperature at the floor
     552             :         Real64 TAirCeil;        // air temperature at the ceiling
     553             :         Real64 TLeaving;        // air temperature leaving zone (= return air temp)
     554             :         Real64 TControlPoint;   // air temperature at thermostat
     555             :         Real64 Slope;           // vertical air temperature gradient (slope) from Mundt equations
     556             :         Real64 QequipConvFloor; // convective gain at the floor due to internal heat sources
     557             :         Real64 QSensInfilFloor; // convective gain at the floor due to infiltration
     558             :         Real64 FloorSumHAT;     // sum of hci*area*temp at the floor
     559             :         Real64 FloorSumHA;      // sum of hci*area at the floor
     560             :         Real64 TThisNode;       // dummy variable for air node temp
     561             :         int NodeNum;            // index for air nodes
     562             :         int SurfNum;            // index for surfaces
     563             :         int SurfCounted;        // number of surfaces assciated with an air node
     564             : 
     565             :         //   apply floor splits
     566        8672 :         QequipConvFloor = state.dataRoomAirMod->ConvectiveFloorSplit(ZoneNum) * state.dataMundtSimMgr->ConvIntGain;
     567        8672 :         QSensInfilFloor = -state.dataRoomAirMod->InfiltratFloorSplit(ZoneNum) * state.dataMundtSimMgr->QventCool;
     568             : 
     569             :         // Begin computations for Mundt model
     570             : 
     571             :         // do summations for floor surfaces of this zone
     572        8672 :         FloorSumHAT = 0.0;
     573        8672 :         FloorSumHA = 0.0;
     574       26016 :         for (auto const &s : state.dataMundtSimMgr->FloorSurf) {
     575       17344 :             FloorSumHAT += s.Area * s.Hc * s.Temp;
     576       17344 :             FloorSumHA += s.Area * s.Hc;
     577             :         }
     578             : 
     579             :         // Eq 2.2 in ASHRAE RP 1222 Final report
     580        8672 :         TAirFoot =
     581        8672 :             ((state.dataMundtSimMgr->ZoneAirDensity * CpAir * state.dataMundtSimMgr->SupplyAirVolumeRate * state.dataMundtSimMgr->SupplyAirTemp) +
     582        8672 :              (FloorSumHAT) + QequipConvFloor + QSensInfilFloor) /
     583        8672 :             ((state.dataMundtSimMgr->ZoneAirDensity * CpAir * state.dataMundtSimMgr->SupplyAirVolumeRate) + (FloorSumHA));
     584             : 
     585             :         // prevent dividing by zero due to zero cooling load (or zero supply air flow rate)
     586        8672 :         if (state.dataMundtSimMgr->QsysCoolTot <= 0.0) {
     587           0 :             TLeaving = state.dataMundtSimMgr->SupplyAirTemp;
     588             :         } else {
     589             :             // Eq 2.3 in ASHRAE RP 1222 Final report
     590        8672 :             TLeaving =
     591        8672 :                 (state.dataMundtSimMgr->QsysCoolTot / (state.dataMundtSimMgr->ZoneAirDensity * CpAir * state.dataMundtSimMgr->SupplyAirVolumeRate)) +
     592        8672 :                 state.dataMundtSimMgr->SupplyAirTemp;
     593             :         }
     594             : 
     595             :         // Eq 2.4 in ASHRAE RP 1222 Final report
     596       17344 :         Slope = (TLeaving - TAirFoot) /
     597       17344 :                 (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
     598        8672 :                  state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).Height);
     599             :         // check slope
     600        8672 :         if (Slope > MaxSlope) {
     601           0 :             Slope = MaxSlope;
     602           0 :             TAirFoot = TLeaving -
     603           0 :                        (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
     604           0 :                                  state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtFootAirID, state.dataMundtSimMgr->MundtZoneNum).Height));
     605             :         }
     606        8672 :         if (Slope < MinSlope) { // pretty much vertical
     607           3 :             Slope = MinSlope;
     608           3 :             TAirFoot = TLeaving;
     609             :         }
     610             : 
     611             :         // Eq 2.4 in ASHRAE RP 1222 Final report
     612        8672 :         TAirCeil =
     613       17344 :             TLeaving - (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
     614        8672 :                                  state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtCeilAirID, state.dataMundtSimMgr->MundtZoneNum).Height));
     615             : 
     616        8672 :         TControlPoint =
     617       17344 :             TLeaving - (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
     618        8672 :                                  state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Height));
     619             : 
     620             :         // determine air node temperatures in this zone
     621        8672 :         SetNodeResult(state, state.dataMundtSimMgr->SupplyNodeID, state.dataMundtSimMgr->SupplyAirTemp);
     622        8672 :         SetNodeResult(state, state.dataMundtSimMgr->ReturnNodeID, TLeaving);
     623        8672 :         SetNodeResult(state, state.dataMundtSimMgr->MundtCeilAirID, TAirCeil);
     624        8672 :         SetNodeResult(state, state.dataMundtSimMgr->MundtFootAirID, TAirFoot);
     625        8672 :         SetNodeResult(state, state.dataMundtSimMgr->TstatNodeID, TControlPoint);
     626             : 
     627       26016 :         for (SurfNum = 1; SurfNum <= state.dataMundtSimMgr->NumFloorSurfs; ++SurfNum) {
     628       17344 :             SetSurfTmeanAir(state, state.dataMundtSimMgr->FloorSurfSetIDs(SurfNum), TAirFoot);
     629             :         }
     630             : 
     631        8672 :         SurfCounted = count(state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtCeilAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
     632       17344 :         state.dataMundtSimMgr->TheseSurfIDs =
     633       17344 :             pack(state.dataMundtSimMgr->ID1dSurf,
     634       17344 :                  state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->MundtCeilAirID, state.dataMundtSimMgr->MundtZoneNum).SurfMask);
     635       26016 :         for (SurfNum = 1; SurfNum <= SurfCounted; ++SurfNum) {
     636       17344 :             SetSurfTmeanAir(state, state.dataMundtSimMgr->TheseSurfIDs(SurfNum), TAirCeil);
     637             :         }
     638             : 
     639       43360 :         for (NodeNum = 1; NodeNum <= state.dataMundtSimMgr->NumRoomNodes; ++NodeNum) {
     640       34688 :             TThisNode =
     641             :                 TLeaving -
     642       69376 :                 (Slope * (state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Height -
     643       34688 :                           state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->RoomNodeIDs(NodeNum), state.dataMundtSimMgr->MundtZoneNum).Height));
     644       34688 :             SetNodeResult(state, state.dataMundtSimMgr->RoomNodeIDs(NodeNum), TThisNode);
     645       34688 :             SurfCounted =
     646       34688 :                 count(state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->RoomNodeIDs(NodeNum), state.dataMundtSimMgr->MundtZoneNum).SurfMask);
     647       69376 :             state.dataMundtSimMgr->TheseSurfIDs =
     648       69376 :                 pack(state.dataMundtSimMgr->ID1dSurf,
     649       69376 :                      state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->RoomNodeIDs(NodeNum), state.dataMundtSimMgr->MundtZoneNum).SurfMask);
     650      190784 :             for (SurfNum = 1; SurfNum <= SurfCounted; ++SurfNum) {
     651      156096 :                 SetSurfTmeanAir(state, state.dataMundtSimMgr->TheseSurfIDs(SurfNum), TThisNode);
     652             :             }
     653             :         }
     654        8672 :     }
     655             : 
     656             :     //*****************************************************************************************
     657             : 
     658       78048 :     void SetNodeResult(EnergyPlusData &state,
     659             :                        int const NodeID,       // node ID
     660             :                        Real64 const TempResult // temperature for the specified air node
     661             :     )
     662             :     {
     663             : 
     664             :         // SUBROUTINE INFORMATION:
     665             :         //       AUTHOR         Brent Griffith
     666             :         //       DATE WRITTEN   September 2002
     667             :         //       RE-ENGINEERED  April 2003, Weixiu Kong, EnergyPlus Implementation
     668             :         //       MODIFIED       February 2004, fix allocate-deallocate problem (CC)
     669             : 
     670             :         // PURPOSE OF THIS SUBROUTINE:
     671             :         //   provide set routine for reporting results
     672             :         //   to AirDataManager from air model
     673             : 
     674             :         // METHODOLOGY EMPLOYED:
     675             :         // na
     676             : 
     677             :         // REFERENCES:
     678             :         // na
     679             : 
     680             :         // USE STATEMENTS:
     681             :         // na
     682             : 
     683             :         // Locals
     684             :         // SUBROUTINE ARGUMENT DEFINITIONS:
     685             : 
     686             :         // SUBROUTINE PARAMETER DEFINITIONS:
     687             :         // na
     688             : 
     689             :         // INTERFACE BLOCK SPECIFICATIONS:
     690             :         // na
     691             : 
     692             :         // DERIVED TYPE DEFINITIONS:
     693             :         // na
     694             : 
     695             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     696             :         // na
     697             : 
     698       78048 :         state.dataMundtSimMgr->LineNode(NodeID, state.dataMundtSimMgr->MundtZoneNum).Temp = TempResult;
     699       78048 :     }
     700             : 
     701             :     //*****************************************************************************************
     702             : 
     703      190784 :     void SetSurfTmeanAir(EnergyPlusData &state,
     704             :                          int const SurfID,    // surface ID
     705             :                          Real64 const TeffAir // temperature of air node adjacent to the specified surface
     706             :     )
     707             :     {
     708             : 
     709             :         // SUBROUTINE INFORMATION:
     710             :         //       AUTHOR         Brent Griffith
     711             :         //       DATE WRITTEN   September 2002
     712             :         //       RE-ENGINEERED  April 2003, Wiexiu Kong, EnergyPlus Implementation
     713             :         //       MODIFIED       February 2004, fix allocate-deallocate problem (CC)
     714             : 
     715             :         // PURPOSE OF THIS SUBROUTINE:
     716             :         //   provide set routine for air model prediction of
     717             :         //   effective air for single surface
     718             : 
     719      190784 :         state.dataMundtSimMgr->MundtAirSurf(SurfID, state.dataMundtSimMgr->MundtZoneNum).TMeanAir = TeffAir;
     720      190784 :     }
     721             : 
     722             :     //*****************************************************************************************
     723             : 
     724       17126 :     void SetSurfHBDataForMundtModel(EnergyPlusData &state, int const ZoneNum) // index number for the specified zone
     725             :     {
     726             : 
     727             :         // SUBROUTINE INFORMATION:
     728             :         //       AUTHOR         Chanvit Chantrasrisalai
     729             :         //       DATE WRITTEN   July 2003
     730             :         //       MODIFIED       February 2004, fix allocate-deallocate problem (CC)
     731             :         //       RE-ENGINEERED  na
     732             : 
     733             :         // PURPOSE OF THIS SUBROUTINE:
     734             :         //     map data from air domain back to surface domain for each particular zone
     735             : 
     736             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     737             :         int ZoneNodeNum;  // index number of the zone node
     738             :         Real64 DeltaTemp; // dummy variable for temperature difference
     739             : 
     740             :         // get surface info
     741       17126 :         int NumOfSurfs = state.dataMundtSimMgr->ZoneData(ZoneNum).NumOfSurfs;
     742             : 
     743       33901 :         if ((state.dataMundtSimMgr->SupplyAirVolumeRate > 0.0001) &&
     744       16775 :             (state.dataMundtSimMgr->QsysCoolTot > 0.0001)) { // Controlled zone when the system is on
     745             : 
     746        8672 :             if (state.dataRoomAirMod->AirModel(ZoneNum).TempCoupleScheme == DataRoomAirModel::CouplingScheme::Direct) {
     747             :                 // Use direct coupling scheme to report air temperatures back to surface/system domains
     748             :                 // a) Bulk air temperatures -> TempEffBulkAir(SurfNum)
     749      199456 :                 for (int SurfNum = 1; SurfNum <= NumOfSurfs; ++SurfNum) {
     750      190784 :                     int hbSurfNum = state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum);
     751      190784 :                     state.dataHeatBal->SurfTempEffBulkAir(hbSurfNum) =
     752      190784 :                         state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).TMeanAir;
     753             :                     // set flag for reference air temperature
     754      190784 :                     state.dataSurface->SurfTAirRef(hbSurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
     755      190784 :                     state.dataSurface->SurfTAirRefRpt(hbSurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(hbSurfNum)];
     756             :                 }
     757             :                 // b) Average zone air temperature -> ZT(ZoneNum)
     758             :                 // For Mundt model, average room air is the weighted value of floor and ceiling air temps
     759             :                 // TRoomAverage = ( LineNode( MundtCeilAirID, MundtZoneNum ).Temp + LineNode( MundtFootAirID, MundtZoneNum ).Temp ) / 2;
     760             :                 // ZT(ZoneNum) = TRoomAverage
     761             :                 // c) Leaving-zone air temperature -> Node(ZoneNode)%Temp
     762        8672 :                 ZoneNodeNum = state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber;
     763        8672 :                 state.dataLoopNodes->Node(ZoneNodeNum).Temp =
     764        8672 :                     state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
     765             :                 // d) Thermostat air temperature -> TempTstatAir(ZoneNum)
     766        8672 :                 state.dataHeatBalFanSys->TempTstatAir(ZoneNum) =
     767        8672 :                     state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
     768             :             } else {
     769             :                 // Use indirect coupling scheme to report air temperatures back to surface/system domains
     770             :                 // a) Bulk air temperatures -> TempEffBulkAir(SurfNum)
     771           0 :                 for (int SurfNum = 1; SurfNum <= NumOfSurfs; ++SurfNum) {
     772           0 :                     int hbSurfNum = state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum);
     773           0 :                     DeltaTemp = state.dataMundtSimMgr->MundtAirSurf(SurfNum, state.dataMundtSimMgr->MundtZoneNum).TMeanAir -
     774           0 :                                 state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
     775           0 :                     state.dataHeatBal->SurfTempEffBulkAir(hbSurfNum) = state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) + DeltaTemp;
     776             :                     // set flag for reference air temperature
     777           0 :                     state.dataSurface->SurfTAirRef(hbSurfNum) = DataSurfaces::RefAirTemp::AdjacentAirTemp;
     778           0 :                     state.dataSurface->SurfTAirRefRpt(hbSurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(hbSurfNum)];
     779             :                 }
     780             :                 // b) Average zone air temperature -> ZT(ZoneNum)
     781             :                 // For Mundt model, average room air is the weighted value of floor and ceiling air temps
     782             :                 // TRoomAverage = ( LineNode( MundtCeilAirID, MundtZoneNum ).Temp + LineNode( MundtFootAirID, MundtZoneNum ).Temp ) / 2;
     783             :                 // DeltaTemp = TRoomAverage - LineNode( TstatNodeID, MundtZoneNum ).Temp;
     784             :                 // ZT(ZoneNum) = TempZoneThermostatSetPoint(ZoneNum) + DeltaTemp
     785             :                 // c) Leaving-zone air temperature -> Node(ZoneNode)%Temp
     786           0 :                 ZoneNodeNum = state.dataHeatBal->Zone(ZoneNum).SystemZoneNodeNumber;
     787           0 :                 DeltaTemp = state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->ReturnNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp -
     788           0 :                             state.dataMundtSimMgr->LineNode(state.dataMundtSimMgr->TstatNodeID, state.dataMundtSimMgr->MundtZoneNum).Temp;
     789           0 :                 state.dataLoopNodes->Node(ZoneNodeNum).Temp = state.dataHeatBalFanSys->TempZoneThermostatSetPoint(ZoneNum) + DeltaTemp;
     790             :                 // d) Thermostat air temperature -> TempTstatAir(ZoneNum)
     791           0 :                 state.dataHeatBalFanSys->TempTstatAir(ZoneNum) = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum)
     792           0 :                                                                      .ZT; // for indirect coupling, control air temp is equal to mean air temp?
     793             :             }
     794             :             // set flag to indicate that Mundt model is used for this zone at the present time
     795        8672 :             state.dataRoomAirMod->AirModel(ZoneNum).SimAirModel = true;
     796             :         } else { // Controlled zone when the system is off --> Use the mixing model instead of the Mundt model
     797             :             // Bulk air temperatures -> TempEffBulkAir(SurfNum)
     798      194442 :             for (int SurfNum = 1; SurfNum <= NumOfSurfs; ++SurfNum) {
     799      185988 :                 int hbSurfNum = state.dataMundtSimMgr->ZoneData(ZoneNum).HBsurfaceIndexes(SurfNum);
     800      185988 :                 state.dataHeatBal->SurfTempEffBulkAir(hbSurfNum) = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
     801             :                 // set flag for reference air temperature
     802      185988 :                 state.dataSurface->SurfTAirRef(hbSurfNum) = DataSurfaces::RefAirTemp::ZoneMeanAirTemp;
     803      185988 :                 state.dataSurface->SurfTAirRefRpt(hbSurfNum) = DataSurfaces::SurfTAirRefReportVals[state.dataSurface->SurfTAirRef(hbSurfNum)];
     804             :             }
     805             :             // set flag to indicate that Mundt model is NOT used for this zone at the present time
     806        8454 :             state.dataRoomAirMod->AirModel(ZoneNum).SimAirModel = false;
     807             :         }
     808       17126 :     }
     809             : 
     810             :     //*****************************************************************************************
     811             : 
     812             : } // namespace MundtSimMgr
     813             : 
     814        2313 : } // namespace EnergyPlus

Generated by: LCOV version 1.13