LCOV - code coverage report
Current view: top level - EnergyPlus - HeatBalanceHAMTManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 0.0 % 846 0
Test Date: 2025-05-22 16:09:37 Functions: 0.0 % 8 0

            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              : #include <string>
      51              : 
      52              : // ObjexxFCL Headers
      53              : #include <ObjexxFCL/Fmath.hh>
      54              : #include <ObjexxFCL/member.functions.hh>
      55              : 
      56              : // EnergyPlus Headers
      57              : #include <EnergyPlus/Construction.hh>
      58              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      59              : #include <EnergyPlus/DataEnvironment.hh>
      60              : #include <EnergyPlus/DataHeatBalSurface.hh>
      61              : #include <EnergyPlus/DataHeatBalance.hh>
      62              : #include <EnergyPlus/DataIPShortCuts.hh>
      63              : #include <EnergyPlus/DataMoistureBalance.hh>
      64              : #include <EnergyPlus/DataSurfaces.hh>
      65              : #include <EnergyPlus/DisplayRoutines.hh>
      66              : #include <EnergyPlus/General.hh>
      67              : #include <EnergyPlus/HeatBalanceHAMTManager.hh>
      68              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      69              : #include <EnergyPlus/Material.hh>
      70              : #include <EnergyPlus/OutputProcessor.hh>
      71              : #include <EnergyPlus/Psychrometrics.hh>
      72              : #include <EnergyPlus/UtilityRoutines.hh>
      73              : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      74              : 
      75              : namespace EnergyPlus {
      76              : 
      77              : namespace HeatBalanceHAMTManager {
      78              : 
      79              :     // MODULE INFORMATION:
      80              :     //       AUTHOR      Phillip Biddulph
      81              :     //       DATE WRITTEN   June 2008
      82              :     //       MODIFIED
      83              :     //       Bug fixes to make sure HAMT can cope with data limits  ! PDB August 2009
      84              :     //       RE-ENGINEERED
      85              : 
      86              :     // PURPOSE OF THIS MODULE:
      87              :     // Calculate, record and report the one dimentional heat and moisture transfer
      88              :     // through a surface given the material composition of the building surface and
      89              :     // the external and internal Temperatures and Relative Humidities.
      90              : 
      91              :     // METHODOLOGY EMPLOYED:
      92              :     // Each surface is split into "cells", where all characteristics are initiallised.
      93              :     // Cells are matched and links created in the initialisation routine.
      94              :     // The internal and external "surfaces" of the surface are virtual cells to allow for the
      95              :     // input of heat and vapor via heat transfer coefficients, radiation,
      96              :     // and vapor transfer coefficients
      97              :     // Uses Forward (implicit) finite difference alogorithm. Heat transfer is caclulated first,
      98              :     // with the option of including the latent heat, then liquid and vapor transfer. The process is ittereated.
      99              :     // Once the temperatures have converged the internal surface
     100              :     // temperature and vapor densities are passed back to EnergyPlus.
     101              : 
     102              :     // Temperatures and relative humidities are updated once EnergyPlus has checked that
     103              :     // the zone temperatures have converged.
     104              : 
     105              :     // REFERENCES:
     106              :     // K?zel, H.M. (1995) Simultaneous Heat and Moisture Transport in Building Components.
     107              :     // One- and two-dimensional calculation using simple parameters. IRB Verlag 1995
     108              :     // Holman, J.P. (2002) Heat Transfer, Ninth Edition. McGraw-Hill
     109              :     // Winterton, R.H.S. (1997) Heat Transfer. (Oxford Chemistry Primers; 50) Oxford University Press
     110              :     // Kumar Kumaran, M. (1996) IEA ANNEX 24, Final Report, Volume 3
     111              : 
     112              :     // USE STATEMENTS:
     113              : 
     114              :     // Using/Aliasing
     115              :     using namespace DataSurfaces;
     116              :     using DataHeatBalSurface::MinSurfaceTempLimit;
     117              :     using DataHeatBalSurface::MinSurfaceTempLimitBeforeFatal;
     118              :     using namespace DataHeatBalance;
     119              :     using namespace Psychrometrics;
     120              : 
     121            0 :     void ManageHeatBalHAMT(EnergyPlusData &state, int const SurfNum, Real64 &SurfTempInTmp, Real64 &TempSurfOutTmp)
     122              :     {
     123              : 
     124              :         // SUBROUTINE INFORMATION:
     125              :         //       AUTHOR         Phillip Biddulph
     126              :         //       DATE WRITTEN   June 2008
     127              :         //       MODIFIED       na
     128              :         //       RE-ENGINEERED  na
     129              : 
     130              :         // PURPOSE OF THIS SUBROUTINE:
     131              :         // Manages the Heat and Moisture Transfer calculations.
     132              : 
     133              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     134            0 :         if (state.dataHeatBalHAMTMgr->OneTimeFlag) {
     135            0 :             state.dataHeatBalHAMTMgr->OneTimeFlag = false;
     136            0 :             DisplayString(state, "Initialising Heat and Moisture Transfer Model");
     137            0 :             GetHeatBalHAMTInput(state);
     138            0 :             InitHeatBalHAMT(state);
     139              :         }
     140              : 
     141            0 :         CalcHeatBalHAMT(state, SurfNum, SurfTempInTmp, TempSurfOutTmp);
     142            0 :     }
     143              : 
     144            0 :     void GetHeatBalHAMTInput(EnergyPlusData &state)
     145              :     {
     146              : 
     147              :         // SUBROUTINE INFORMATION:
     148              :         //       AUTHOR         Phillip Biddulph
     149              :         //       DATE WRITTEN   June 2008
     150              :         //       MODIFIED       na
     151              :         //       RE-ENGINEERED  na
     152              : 
     153              :         // PURPOSE OF THIS SUBROUTINE:
     154              :         // gets input for the HAMT model
     155              :         static constexpr std::string_view routineName = "GetHeatBalHAMTInput";
     156              : 
     157              :         // SUBROUTINE PARAMETER DEFINITIONS:
     158            0 :         static std::string const cHAMTObject1("MaterialProperty:HeatAndMoistureTransfer:Settings");
     159            0 :         static std::string const cHAMTObject2("MaterialProperty:HeatAndMoistureTransfer:SorptionIsotherm");
     160            0 :         static std::string const cHAMTObject3("MaterialProperty:HeatAndMoistureTransfer:Suction");
     161            0 :         static std::string const cHAMTObject4("MaterialProperty:HeatAndMoistureTransfer:Redistribution");
     162            0 :         static std::string const cHAMTObject5("MaterialProperty:HeatAndMoistureTransfer:Diffusion");
     163            0 :         static std::string const cHAMTObject6("MaterialProperty:HeatAndMoistureTransfer:ThermalConductivity");
     164            0 :         static std::string const cHAMTObject7("SurfaceProperties:VaporCoefficients");
     165              : 
     166              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     167              : 
     168            0 :         Array1D_string AlphaArray;
     169            0 :         Array1D_string cAlphaFieldNames;
     170            0 :         Array1D_string cNumericFieldNames;
     171              : 
     172            0 :         Array1D_bool lAlphaBlanks;
     173            0 :         Array1D_bool lNumericBlanks;
     174              : 
     175            0 :         Array1D<Real64> NumArray;
     176              : 
     177              :         Real64 avdata;
     178              : 
     179              :         int MaxNums;
     180              :         int MaxAlphas;
     181              :         int NumParams;
     182              :         int NumNums;
     183              :         int NumAlphas;
     184              :         int status;
     185              :         int Numid;
     186              : 
     187              :         int HAMTitems;
     188              :         int vtcsid;
     189              : 
     190              :         bool ErrorsFound;
     191              : 
     192            0 :         auto &s_ip = state.dataInputProcessing->inputProcessor;
     193            0 :         auto &s_mat = state.dataMaterial;
     194              : 
     195            0 :         state.dataHeatBalHAMTMgr->watertot.allocate(state.dataSurface->TotSurfaces);
     196            0 :         state.dataHeatBalHAMTMgr->surfrh.allocate(state.dataSurface->TotSurfaces);
     197            0 :         state.dataHeatBalHAMTMgr->surfextrh.allocate(state.dataSurface->TotSurfaces);
     198            0 :         state.dataHeatBalHAMTMgr->surftemp.allocate(state.dataSurface->TotSurfaces);
     199            0 :         state.dataHeatBalHAMTMgr->surfexttemp.allocate(state.dataSurface->TotSurfaces);
     200            0 :         state.dataHeatBalHAMTMgr->surfvp.allocate(state.dataSurface->TotSurfaces);
     201              : 
     202            0 :         state.dataHeatBalHAMTMgr->firstcell.allocate(state.dataSurface->TotSurfaces);
     203            0 :         state.dataHeatBalHAMTMgr->lastcell.allocate(state.dataSurface->TotSurfaces);
     204            0 :         state.dataHeatBalHAMTMgr->Extcell.allocate(state.dataSurface->TotSurfaces);
     205            0 :         state.dataHeatBalHAMTMgr->ExtRadcell.allocate(state.dataSurface->TotSurfaces);
     206            0 :         state.dataHeatBalHAMTMgr->ExtConcell.allocate(state.dataSurface->TotSurfaces);
     207            0 :         state.dataHeatBalHAMTMgr->ExtSkycell.allocate(state.dataSurface->TotSurfaces);
     208            0 :         state.dataHeatBalHAMTMgr->ExtGrncell.allocate(state.dataSurface->TotSurfaces);
     209            0 :         state.dataHeatBalHAMTMgr->Intcell.allocate(state.dataSurface->TotSurfaces);
     210            0 :         state.dataHeatBalHAMTMgr->IntConcell.allocate(state.dataSurface->TotSurfaces);
     211              : 
     212            0 :         state.dataHeatBalHAMTMgr->extvtc.allocate(state.dataSurface->TotSurfaces);
     213            0 :         state.dataHeatBalHAMTMgr->intvtc.allocate(state.dataSurface->TotSurfaces);
     214            0 :         state.dataHeatBalHAMTMgr->extvtcflag.allocate(state.dataSurface->TotSurfaces);
     215            0 :         state.dataHeatBalHAMTMgr->intvtcflag.allocate(state.dataSurface->TotSurfaces);
     216            0 :         state.dataHeatBalHAMTMgr->MyEnvrnFlag.allocate(state.dataSurface->TotSurfaces);
     217              : 
     218            0 :         state.dataHeatBalHAMTMgr->extvtc = -1.0;
     219            0 :         state.dataHeatBalHAMTMgr->intvtc = -1.0;
     220            0 :         state.dataHeatBalHAMTMgr->extvtcflag = false;
     221            0 :         state.dataHeatBalHAMTMgr->intvtcflag = false;
     222            0 :         state.dataHeatBalHAMTMgr->MyEnvrnFlag = true;
     223              : 
     224            0 :         state.dataHeatBalHAMTMgr->latswitch = true;
     225            0 :         state.dataHeatBalHAMTMgr->rainswitch = true;
     226              : 
     227            0 :         MaxAlphas = 0;
     228            0 :         MaxNums = 0;
     229            0 :         s_ip->getObjectDefMaxArgs(state, cHAMTObject1, NumParams, NumAlphas, NumNums);
     230            0 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     231            0 :         MaxNums = max(MaxNums, NumNums);
     232            0 :         s_ip->getObjectDefMaxArgs(state, cHAMTObject2, NumParams, NumAlphas, NumNums);
     233            0 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     234            0 :         MaxNums = max(MaxNums, NumNums);
     235            0 :         s_ip->getObjectDefMaxArgs(state, cHAMTObject3, NumParams, NumAlphas, NumNums);
     236            0 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     237            0 :         MaxNums = max(MaxNums, NumNums);
     238            0 :         s_ip->getObjectDefMaxArgs(state, cHAMTObject4, NumParams, NumAlphas, NumNums);
     239            0 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     240            0 :         MaxNums = max(MaxNums, NumNums);
     241            0 :         s_ip->getObjectDefMaxArgs(state, cHAMTObject5, NumParams, NumAlphas, NumNums);
     242            0 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     243            0 :         MaxNums = max(MaxNums, NumNums);
     244            0 :         s_ip->getObjectDefMaxArgs(state, cHAMTObject6, NumParams, NumAlphas, NumNums);
     245            0 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     246            0 :         MaxNums = max(MaxNums, NumNums);
     247            0 :         s_ip->getObjectDefMaxArgs(state, cHAMTObject7, NumParams, NumAlphas, NumNums);
     248            0 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     249            0 :         MaxNums = max(MaxNums, NumNums);
     250              : 
     251            0 :         ErrorsFound = false;
     252              : 
     253            0 :         AlphaArray.allocate(MaxAlphas);
     254            0 :         cAlphaFieldNames.allocate(MaxAlphas);
     255            0 :         cNumericFieldNames.allocate(MaxNums);
     256            0 :         NumArray.dimension(MaxNums, 0.0);
     257            0 :         lAlphaBlanks.dimension(MaxAlphas, false);
     258            0 :         lNumericBlanks.dimension(MaxNums, false);
     259              : 
     260            0 :         HAMTitems = s_ip->getNumObjectsFound(state, cHAMTObject1); // MaterialProperty:HeatAndMoistureTransfer:Settings
     261            0 :         for (int item = 1; item <= HAMTitems; ++item) {
     262            0 :             s_ip->getObjectItem(state,
     263              :                                 cHAMTObject1,
     264              :                                 item,
     265              :                                 AlphaArray,
     266              :                                 NumAlphas,
     267              :                                 NumArray,
     268              :                                 NumNums,
     269              :                                 status,
     270              :                                 lNumericBlanks,
     271              :                                 lAlphaBlanks,
     272              :                                 cAlphaFieldNames,
     273              :                                 cNumericFieldNames);
     274              : 
     275            0 :             ErrorObjectHeader eoh{routineName, cHAMTObject1, AlphaArray(1)};
     276            0 :             int matNum = Material::GetMaterialNum(state, AlphaArray(1));
     277              : 
     278            0 :             if (matNum == 0) {
     279            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(1), AlphaArray(1));
     280            0 :                 ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
     281            0 :                 ErrorsFound = true;
     282            0 :                 continue;
     283              :             }
     284              : 
     285            0 :             auto *mat = s_mat->materials(matNum);
     286              : 
     287            0 :             if (mat->group != Material::Group::Regular) {
     288            0 :                 ShowSevereCustom(state, eoh, format("{} = \"{}\" is not a regular material.", cAlphaFieldNames(1), AlphaArray(1)));
     289            0 :                 ErrorsFound = true;
     290            0 :                 continue;
     291              :             }
     292              : 
     293            0 :             if (mat->ROnly) {
     294            0 :                 ShowWarningError(state,
     295            0 :                                  format("{} {}=\"{}\" is defined as an R-only value material.", cHAMTObject1, cAlphaFieldNames(1), AlphaArray(1)));
     296            0 :                 continue;
     297              :             }
     298              : 
     299            0 :             auto *matHAMT = new MaterialHAMT;
     300            0 :             matHAMT->Material::MaterialBase::operator=(*mat); // deep copy
     301              : 
     302            0 :             delete mat;
     303            0 :             s_mat->materials(matNum) = matHAMT;
     304              : 
     305            0 :             matHAMT->hasHAMT = true;
     306            0 :             matHAMT->Porosity = NumArray(1);
     307            0 :             matHAMT->iwater = NumArray(2);
     308              :         }
     309              : 
     310            0 :         HAMTitems = s_ip->getNumObjectsFound(state, cHAMTObject2); // MaterialProperty:HeatAndMoistureTransfer:SorptionIsotherm
     311            0 :         for (int item = 1; item <= HAMTitems; ++item) {
     312            0 :             s_ip->getObjectItem(state,
     313              :                                 cHAMTObject2,
     314              :                                 item,
     315              :                                 AlphaArray,
     316              :                                 NumAlphas,
     317              :                                 NumArray,
     318              :                                 NumNums,
     319              :                                 status,
     320              :                                 lNumericBlanks,
     321              :                                 lAlphaBlanks,
     322              :                                 cAlphaFieldNames,
     323              :                                 cNumericFieldNames);
     324              : 
     325            0 :             ErrorObjectHeader eoh{routineName, cHAMTObject2, AlphaArray(1)};
     326            0 :             int matNum = Material::GetMaterialNum(state, AlphaArray(1));
     327              : 
     328            0 :             if (matNum == 0) {
     329            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(1), AlphaArray(1));
     330            0 :                 ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
     331            0 :                 ErrorsFound = true;
     332            0 :                 continue;
     333              :             }
     334              : 
     335            0 :             auto *mat = s_mat->materials(matNum);
     336            0 :             if (!mat->hasHAMT) {
     337            0 :                 ShowSevereCustom(state, eoh, format("{} is not defined for {} = \"{}\"", cHAMTObject1, cAlphaFieldNames(1), AlphaArray(1)));
     338            0 :                 ErrorsFound = true;
     339            0 :                 continue;
     340              :             }
     341              : 
     342            0 :             auto *matHAMT = dynamic_cast<MaterialHAMT *>(mat);
     343            0 :             assert(matHAMT != nullptr);
     344              : 
     345            0 :             Numid = 1;
     346              : 
     347            0 :             matHAMT->niso = int(NumArray(Numid));
     348              : 
     349            0 :             for (int iso = 1; iso <= matHAMT->niso; ++iso) {
     350            0 :                 matHAMT->isorh(iso) = NumArray(++Numid);
     351            0 :                 matHAMT->isodata(iso) = NumArray(++Numid);
     352              :             }
     353              : 
     354            0 :             ++matHAMT->niso;
     355            0 :             matHAMT->isorh(matHAMT->niso) = rhmax;
     356            0 :             matHAMT->isodata(matHAMT->niso) = matHAMT->Porosity * wdensity;
     357              : 
     358            0 :             ++matHAMT->niso;
     359            0 :             matHAMT->isorh(matHAMT->niso) = 0.0;
     360            0 :             matHAMT->isodata(matHAMT->niso) = 0.0;
     361              : 
     362              :             // check the isotherm
     363              : 
     364              :             // - First sort
     365            0 :             for (int jj = 1; jj <= matHAMT->niso - 1; ++jj) {
     366            0 :                 for (int ii = jj + 1; ii <= matHAMT->niso; ++ii) {
     367            0 :                     if (matHAMT->isorh(jj) > matHAMT->isorh(ii)) {
     368              : 
     369            0 :                         Real64 dumrh = matHAMT->isorh(jj);
     370            0 :                         Real64 dumdata = matHAMT->isodata(jj);
     371              : 
     372            0 :                         matHAMT->isorh(jj) = matHAMT->isorh(ii);
     373            0 :                         matHAMT->isodata(jj) = matHAMT->isodata(ii);
     374              : 
     375            0 :                         matHAMT->isorh(ii) = dumrh;
     376            0 :                         matHAMT->isodata(ii) = dumdata;
     377              :                     }
     378              :                 }
     379              :             }
     380              : 
     381              :             //- Now make sure the data rises
     382            0 :             bool isoerrrise = false;
     383            0 :             for (int ii = 1; ii <= 100; ++ii) {
     384            0 :                 bool avflag = true;
     385            0 :                 for (int jj = 1; jj <= matHAMT->niso - 1; ++jj) {
     386            0 :                     if (matHAMT->isodata(jj) > matHAMT->isodata(jj + 1)) {
     387            0 :                         isoerrrise = true;
     388            0 :                         avdata = (matHAMT->isodata(jj) + matHAMT->isodata(jj + 1)) / 2.0;
     389            0 :                         matHAMT->isodata(jj) = avdata;
     390            0 :                         matHAMT->isodata(jj + 1) = avdata;
     391            0 :                         avflag = false;
     392              :                     }
     393              :                 }
     394            0 :                 if (avflag) break;
     395              :             }
     396            0 :             if (isoerrrise) {
     397            0 :                 ShowWarningError(state, format("{}: data not rising - Check material {}", cHAMTObject2, matHAMT->Name));
     398            0 :                 ShowContinueError(state, "Isotherm data has been fixed, and the simulation continues.");
     399              :             }
     400              :         }
     401              : 
     402            0 :         HAMTitems = s_ip->getNumObjectsFound(state, cHAMTObject3); // MaterialProperty:HeatAndMoistureTransfer:Suction
     403            0 :         for (int item = 1; item <= HAMTitems; ++item) {
     404            0 :             s_ip->getObjectItem(state,
     405              :                                 cHAMTObject3,
     406              :                                 item,
     407              :                                 AlphaArray,
     408              :                                 NumAlphas,
     409              :                                 NumArray,
     410              :                                 NumNums,
     411              :                                 status,
     412              :                                 lNumericBlanks,
     413              :                                 lAlphaBlanks,
     414              :                                 cAlphaFieldNames,
     415              :                                 cNumericFieldNames);
     416              : 
     417            0 :             ErrorObjectHeader eoh{routineName, cHAMTObject3, AlphaArray(1)};
     418            0 :             int matNum = Material::GetMaterialNum(state, AlphaArray(1));
     419              : 
     420            0 :             if (matNum == 0) {
     421            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(1), AlphaArray(1));
     422            0 :                 ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
     423            0 :                 ErrorsFound = true;
     424            0 :                 continue;
     425              :             }
     426              : 
     427            0 :             auto *mat = s_mat->materials(matNum);
     428            0 :             if (!mat->hasHAMT) {
     429            0 :                 ShowSevereCustom(state, eoh, format("{} is not defined for {} = \"{}\"", cHAMTObject1, cAlphaFieldNames(1), AlphaArray(1)));
     430            0 :                 ErrorsFound = true;
     431            0 :                 continue;
     432              :             }
     433              : 
     434            0 :             auto *matHAMT = dynamic_cast<MaterialHAMT *>(mat);
     435            0 :             assert(matHAMT != nullptr);
     436              : 
     437            0 :             Numid = 1;
     438              : 
     439            0 :             matHAMT->nsuc = NumArray(Numid);
     440            0 :             for (int suc = 1; suc <= matHAMT->nsuc; ++suc) {
     441            0 :                 matHAMT->sucwater(suc) = NumArray(++Numid);
     442            0 :                 matHAMT->sucdata(suc) = NumArray(++Numid);
     443              :             }
     444              : 
     445            0 :             ++matHAMT->nsuc;
     446            0 :             matHAMT->sucwater(matHAMT->nsuc) = matHAMT->isodata(matHAMT->niso);
     447            0 :             matHAMT->sucdata(matHAMT->nsuc) = matHAMT->sucdata(matHAMT->nsuc - 1);
     448              :         }
     449              : 
     450            0 :         HAMTitems = s_ip->getNumObjectsFound(state, cHAMTObject4); // MaterialProperty:HeatAndMoistureTransfer:Redistribution
     451            0 :         for (int item = 1; item <= HAMTitems; ++item) {
     452            0 :             s_ip->getObjectItem(state,
     453              :                                 cHAMTObject4,
     454              :                                 item,
     455              :                                 AlphaArray,
     456              :                                 NumAlphas,
     457              :                                 NumArray,
     458              :                                 NumNums,
     459              :                                 status,
     460              :                                 lNumericBlanks,
     461              :                                 lAlphaBlanks,
     462              :                                 cAlphaFieldNames,
     463              :                                 cNumericFieldNames);
     464              : 
     465            0 :             ErrorObjectHeader eoh{routineName, cHAMTObject4, AlphaArray(1)};
     466            0 :             int matNum = Material::GetMaterialNum(state, AlphaArray(1));
     467            0 :             if (matNum == 0) {
     468            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(1), AlphaArray(1));
     469            0 :                 ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
     470            0 :                 ErrorsFound = true;
     471            0 :                 continue;
     472              :             }
     473              : 
     474            0 :             auto *mat = s_mat->materials(matNum);
     475            0 :             if (!mat->hasHAMT) {
     476            0 :                 ShowSevereCustom(state, eoh, format("{} is not defined for {} = \"{}\"", cHAMTObject1, cAlphaFieldNames(1), AlphaArray(1)));
     477            0 :                 ErrorsFound = true;
     478            0 :                 continue;
     479              :             }
     480              : 
     481            0 :             auto *matHAMT = dynamic_cast<MaterialHAMT *>(mat);
     482            0 :             assert(matHAMT != nullptr);
     483              : 
     484            0 :             Numid = 1;
     485              : 
     486            0 :             matHAMT->nred = NumArray(Numid);
     487            0 :             for (int red = 1; red <= matHAMT->nred; ++red) {
     488            0 :                 matHAMT->redwater(red) = NumArray(++Numid);
     489            0 :                 matHAMT->reddata(red) = NumArray(++Numid);
     490              :             }
     491              : 
     492            0 :             ++matHAMT->nred;
     493            0 :             matHAMT->redwater(matHAMT->nred) = matHAMT->isodata(matHAMT->niso);
     494            0 :             matHAMT->reddata(matHAMT->nred) = matHAMT->reddata(matHAMT->nred - 1);
     495              :         }
     496              : 
     497            0 :         HAMTitems = s_ip->getNumObjectsFound(state, cHAMTObject5); // MaterialProperty:HeatAndMoistureTransfer:Diffusion
     498            0 :         for (int item = 1; item <= HAMTitems; ++item) {
     499            0 :             s_ip->getObjectItem(state,
     500              :                                 cHAMTObject5,
     501              :                                 item,
     502              :                                 AlphaArray,
     503              :                                 NumAlphas,
     504              :                                 NumArray,
     505              :                                 NumNums,
     506              :                                 status,
     507              :                                 lNumericBlanks,
     508              :                                 lAlphaBlanks,
     509              :                                 cAlphaFieldNames,
     510              :                                 cNumericFieldNames);
     511              : 
     512            0 :             ErrorObjectHeader eoh{routineName, cHAMTObject5, AlphaArray(1)};
     513            0 :             int matNum = Material::GetMaterialNum(state, AlphaArray(1));
     514            0 :             if (matNum == 0) {
     515            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(1), AlphaArray(1));
     516            0 :                 ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
     517            0 :                 ErrorsFound = true;
     518            0 :                 continue;
     519              :             }
     520              : 
     521            0 :             auto *mat = s_mat->materials(matNum);
     522            0 :             if (!mat->hasHAMT) {
     523            0 :                 ShowSevereCustom(state, eoh, format("{} is not defined for {} = \"{}\"", cHAMTObject1, cAlphaFieldNames(1), AlphaArray(1)));
     524            0 :                 ErrorsFound = true;
     525            0 :                 continue;
     526              :             }
     527              : 
     528            0 :             auto *matHAMT = dynamic_cast<MaterialHAMT *>(mat);
     529            0 :             assert(matHAMT != nullptr);
     530              : 
     531            0 :             Numid = 1;
     532              : 
     533            0 :             matHAMT->nmu = NumArray(Numid);
     534            0 :             if (matHAMT->nmu > 0) {
     535            0 :                 for (int mu = 1; mu <= matHAMT->nmu; ++mu) {
     536            0 :                     matHAMT->murh(mu) = NumArray(++Numid);
     537            0 :                     matHAMT->mudata(mu) = NumArray(++Numid);
     538              :                 }
     539              : 
     540            0 :                 ++matHAMT->nmu;
     541            0 :                 matHAMT->murh(matHAMT->nmu) = matHAMT->isorh(matHAMT->niso);
     542            0 :                 matHAMT->mudata(matHAMT->nmu) = matHAMT->mudata(matHAMT->nmu - 1);
     543              :             }
     544              :         }
     545              : 
     546            0 :         HAMTitems = s_ip->getNumObjectsFound(state, cHAMTObject6); // MaterialProperty:HeatAndMoistureTransfer:ThermalConductivity
     547            0 :         for (int item = 1; item <= HAMTitems; ++item) {
     548            0 :             s_ip->getObjectItem(state,
     549              :                                 cHAMTObject6,
     550              :                                 item,
     551              :                                 AlphaArray,
     552              :                                 NumAlphas,
     553              :                                 NumArray,
     554              :                                 NumNums,
     555              :                                 status,
     556              :                                 lNumericBlanks,
     557              :                                 lAlphaBlanks,
     558              :                                 cAlphaFieldNames,
     559              :                                 cNumericFieldNames);
     560              : 
     561            0 :             ErrorObjectHeader eoh{routineName, cHAMTObject6, AlphaArray(1)};
     562            0 :             int matNum = Material::GetMaterialNum(state, AlphaArray(1));
     563            0 :             if (matNum == 0) {
     564            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(1), AlphaArray(1));
     565            0 :                 ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
     566            0 :                 ErrorsFound = true;
     567            0 :                 continue;
     568              :             }
     569              : 
     570            0 :             auto *mat = s_mat->materials(matNum);
     571            0 :             if (!mat->hasHAMT) {
     572            0 :                 ShowSevereCustom(state, eoh, format("{} is not defined for {} = \"{}\"", cHAMTObject1, cAlphaFieldNames(1), AlphaArray(1)));
     573            0 :                 ErrorsFound = true;
     574            0 :                 continue;
     575              :             }
     576              : 
     577            0 :             auto *matHAMT = dynamic_cast<MaterialHAMT *>(mat);
     578            0 :             assert(matHAMT != nullptr);
     579              : 
     580            0 :             Numid = 1;
     581              : 
     582            0 :             matHAMT->ntc = NumArray(Numid);
     583            0 :             if (matHAMT->ntc > 0) {
     584            0 :                 for (int tc = 1; tc <= matHAMT->ntc; ++tc) {
     585            0 :                     ++Numid;
     586            0 :                     matHAMT->tcwater(tc) = NumArray(Numid);
     587            0 :                     ++Numid;
     588            0 :                     matHAMT->tcdata(tc) = NumArray(Numid);
     589              :                 }
     590              : 
     591            0 :                 ++matHAMT->ntc;
     592            0 :                 matHAMT->tcwater(matHAMT->ntc) = matHAMT->isodata(matHAMT->niso);
     593            0 :                 matHAMT->tcdata(matHAMT->ntc) = matHAMT->tcdata(matHAMT->ntc - 1);
     594              :             }
     595              :         }
     596              : 
     597              :         // Vapor Transfer coefficients
     598            0 :         HAMTitems = s_ip->getNumObjectsFound(state, cHAMTObject7); // SurfaceProperties:VaporCoefficients
     599            0 :         for (int item = 1; item <= HAMTitems; ++item) {
     600            0 :             s_ip->getObjectItem(state,
     601              :                                 cHAMTObject7,
     602              :                                 item,
     603              :                                 AlphaArray,
     604              :                                 NumAlphas,
     605              :                                 NumArray,
     606              :                                 NumNums,
     607              :                                 status,
     608              :                                 lNumericBlanks,
     609              :                                 lAlphaBlanks,
     610              :                                 cAlphaFieldNames,
     611              :                                 cNumericFieldNames);
     612              : 
     613            0 :             ErrorObjectHeader eoh{routineName, cHAMTObject7, AlphaArray(1)};
     614            0 :             vtcsid = Util::FindItemInList(AlphaArray(1), state.dataSurface->Surface);
     615            0 :             if (vtcsid == 0) {
     616            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFieldNames(1), AlphaArray(1));
     617            0 :                 ShowContinueError(state, "The basic material must be defined in addition to specifying HeatAndMoistureTransfer properties.");
     618            0 :                 ErrorsFound = true;
     619            0 :                 continue;
     620              :             }
     621              : 
     622            0 :             if (AlphaArray(2) == "YES") {
     623            0 :                 state.dataHeatBalHAMTMgr->extvtcflag(vtcsid) = true;
     624            0 :                 state.dataHeatBalHAMTMgr->extvtc(vtcsid) = NumArray(1);
     625              :             }
     626              : 
     627            0 :             if (AlphaArray(3) == "YES") {
     628            0 :                 state.dataHeatBalHAMTMgr->intvtcflag(vtcsid) = true;
     629            0 :                 state.dataHeatBalHAMTMgr->intvtc(vtcsid) = NumArray(2);
     630              :             }
     631              :         }
     632              : 
     633            0 :         AlphaArray.deallocate();
     634            0 :         cAlphaFieldNames.deallocate();
     635            0 :         cNumericFieldNames.deallocate();
     636            0 :         NumArray.deallocate();
     637            0 :         lAlphaBlanks.deallocate();
     638            0 :         lNumericBlanks.deallocate();
     639              : 
     640            0 :         if (ErrorsFound) {
     641            0 :             ShowFatalError(state, "GetHeatBalHAMTInput: Errors found getting input.  Program terminates.");
     642              :         }
     643            0 :     }
     644              : 
     645            0 :     void InitHeatBalHAMT(EnergyPlusData &state)
     646              :     {
     647              :         // SUBROUTINE INFORMATION:
     648              :         //       AUTHOR         Phillip Biddulph
     649              :         //       DATE WRITTEN   June 2008
     650              :         //       MODIFIED       B. Griffith, Aug 2012 for surface-specific algorithms
     651              :         //       RE-ENGINEERED  na
     652              : 
     653              :         // Using/Aliasing
     654              :         using General::ScanForReports;
     655              : 
     656              :         // Locals
     657              :         // SUBROUTINE PARAMETER DEFINITIONS:
     658            0 :         Real64 constexpr adjdist(0.00005); // Allowable distance between two cells, also used as limit on cell length
     659              :         static constexpr std::string_view RoutineName("InitCombinedHeatAndMoistureFiniteElement: ");
     660              : 
     661              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     662              :         int sid;
     663              :         int conid;
     664              :         int errorCount;
     665              : 
     666              :         Real64 runor;
     667              :         Real64 testlen;
     668              :         Real64 waterd; // water density
     669              :         bool DoReport;
     670              : 
     671            0 :         auto &s_mat = state.dataMaterial;
     672            0 :         auto &s_hbh = state.dataHeatBalHAMTMgr;
     673              : 
     674            0 :         s_hbh->deltat = state.dataGlobal->TimeStepZone * 3600.0;
     675              : 
     676              :         // Check the materials information and work out how many cells are required.
     677            0 :         errorCount = 0;
     678            0 :         s_hbh->TotCellsMax = 0;
     679            0 :         for (int sid = 1; sid <= state.dataSurface->TotSurfaces; ++sid) {
     680            0 :             auto const &surf = state.dataSurface->Surface(sid);
     681            0 :             if (surf.Class == SurfaceClass::Window) continue;
     682            0 :             if (surf.HeatTransferAlgorithm != DataSurfaces::HeatTransferModel::HAMT) continue;
     683              : 
     684            0 :             if (surf.Construction == 0) continue;
     685            0 :             auto const &constr = state.dataConstruction->Construct(surf.Construction);
     686              : 
     687            0 :             for (int lid = 1; lid <= constr.TotLayers; ++lid) {
     688            0 :                 auto *mat = s_mat->materials(constr.LayerPoint(lid));
     689            0 :                 if (mat->ROnly) {
     690            0 :                     ShowSevereError(state, format("{}Construction={} cannot contain R-only value materials.", RoutineName, constr.Name));
     691            0 :                     ShowContinueError(state, format("Reference Material=\"{}\".", mat->Name));
     692            0 :                     ++errorCount;
     693            0 :                     continue;
     694              :                 }
     695              : 
     696            0 :                 auto *matHAMT = dynamic_cast<MaterialHAMT *>(mat);
     697            0 :                 assert(matHAMT != nullptr);
     698              : 
     699            0 :                 if (matHAMT->nmu < 0) {
     700            0 :                     ShowSevereError(state, format("{}Construction={}", RoutineName, constr.Name));
     701            0 :                     ShowContinueError(
     702              :                         state,
     703            0 :                         format("Reference Material=\"{}\" does not have required Water Vapor Diffusion Resistance Factor (mu) data.", matHAMT->Name));
     704            0 :                     ++errorCount;
     705              :                 }
     706              : 
     707            0 :                 if (matHAMT->niso < 0) {
     708            0 :                     ShowSevereError(state, format("{}Construction={}", RoutineName, constr.Name));
     709            0 :                     ShowContinueError(state, format("Reference Material=\"{}\" does not have required isotherm data.", matHAMT->Name));
     710            0 :                     ++errorCount;
     711              :                 }
     712            0 :                 if (matHAMT->nsuc < 0) {
     713            0 :                     ShowSevereError(state, format("{}Construction={}", RoutineName, constr.Name));
     714            0 :                     ShowContinueError(
     715            0 :                         state, format("Reference Material=\"{}\" does not have required liquid transport coefficient (suction) data.", mat->Name));
     716            0 :                     ++errorCount;
     717              :                 }
     718            0 :                 if (matHAMT->nred < 0) {
     719            0 :                     ShowSevereError(state, format("{}Construction={}", RoutineName, constr.Name));
     720            0 :                     ShowContinueError(
     721              :                         state,
     722            0 :                         format("Reference Material=\"{}\" does not have required liquid transport coefficient (redistribution) data.", mat->Name));
     723            0 :                     ++errorCount;
     724              :                 }
     725            0 :                 if (matHAMT->ntc < 0) {
     726            0 :                     if (mat->Conductivity > 0) {
     727            0 :                         ShowWarningError(state, format("{}Construction={}", RoutineName, constr.Name));
     728            0 :                         ShowContinueError(
     729            0 :                             state, format("Reference Material=\"{}\" does not have thermal conductivity data. Using fixed value.", matHAMT->Name));
     730            0 :                         matHAMT->ntc = 2;
     731            0 :                         matHAMT->tcwater(1) = 0.0;
     732            0 :                         matHAMT->tcdata(1) = matHAMT->Conductivity;
     733            0 :                         matHAMT->tcwater(2) = matHAMT->isodata(matHAMT->niso);
     734            0 :                         matHAMT->tcdata(2) = matHAMT->Conductivity;
     735              :                     } else {
     736            0 :                         ShowSevereError(state, format("{}Construction={}", RoutineName, constr.Name));
     737            0 :                         ShowContinueError(state,
     738            0 :                                           format("Reference Material=\"{}\" does not have required thermal conductivity data.", matHAMT->Name));
     739            0 :                         ++errorCount;
     740              :                     }
     741              :                 }
     742              : 
     743              :                 // convert material water content to RH
     744              : 
     745            0 :                 waterd = matHAMT->iwater * matHAMT->Density;
     746            0 :                 interp(matHAMT->niso, matHAMT->isodata, matHAMT->isorh, waterd, matHAMT->irh);
     747              : 
     748            0 :                 matHAMT->divs = int(matHAMT->Thickness / matHAMT->divsize) + matHAMT->divmin;
     749            0 :                 if (matHAMT->divs > matHAMT->divmax) {
     750            0 :                     matHAMT->divs = matHAMT->divmax;
     751              :                 }
     752              :                 // Check length of cell - reduce number of divisions if necessary
     753            0 :                 Real64 const sin_negPIOvr2 = std::sin(-Constant::Pi / 2.0);
     754              :                 while (true) {
     755            0 :                     testlen = matHAMT->Thickness *
     756            0 :                               ((std::sin(Constant::Pi * (-1.0 / double(matHAMT->divs)) - Constant::Pi / 2.0) / 2.0) - (sin_negPIOvr2 / 2.0));
     757            0 :                     if (testlen > adjdist) break;
     758            0 :                     --matHAMT->divs;
     759            0 :                     if (matHAMT->divs < 1) {
     760            0 :                         ShowSevereError(state, format("{}Construction={}", RoutineName, constr.Name));
     761            0 :                         ShowContinueError(state, format("Reference Material=\"{}\" is too thin.", matHAMT->Name));
     762            0 :                         ++errorCount;
     763            0 :                         break;
     764              :                     }
     765              :                 }
     766            0 :                 s_hbh->TotCellsMax += matHAMT->divs;
     767              :             }
     768            0 :             s_hbh->TotCellsMax += 7;
     769              :         }
     770              : 
     771            0 :         if (errorCount > 0) {
     772            0 :             ShowFatalError(state, "CombinedHeatAndMoistureFiniteElement: Incomplete data to start solution, program terminates.");
     773              :         }
     774              : 
     775              :         // Make the cells and initialize
     776            0 :         s_hbh->cells.allocate(s_hbh->TotCellsMax);
     777            0 :         for (auto &e : s_hbh->cells) {
     778            0 :             e.adjs = -1;
     779            0 :             e.adjsl = -1;
     780              :         }
     781              : 
     782            0 :         int cid = 0;
     783              : 
     784              :         // Set up surface cell structure
     785            0 :         for (int sid = 1; sid <= state.dataSurface->TotSurfaces; ++sid) {
     786            0 :             auto &surf = state.dataSurface->Surface(sid);
     787            0 :             if (!surf.HeatTransSurf) continue;
     788            0 :             if (surf.Class == SurfaceClass::Window) continue;
     789            0 :             if (surf.HeatTransferAlgorithm != DataSurfaces::HeatTransferModel::HAMT) continue;
     790              :             // Boundary Cells
     791            0 :             runor = -0.02;
     792              :             // Air Convection Cell
     793            0 :             ++cid;
     794            0 :             s_hbh->firstcell(sid) = cid;
     795            0 :             s_hbh->ExtConcell(sid) = cid;
     796            0 :             auto &airConvCell = s_hbh->cells(cid);
     797            0 :             airConvCell.rh = 0.0;
     798            0 :             airConvCell.sid = sid;
     799            0 :             airConvCell.length(1) = 0.01;
     800            0 :             airConvCell.origin(1) = airConvCell.length(1) / 2.0 + runor;
     801              : 
     802              :             // Air Radiation Cell
     803            0 :             ++cid;
     804            0 :             s_hbh->ExtRadcell(sid) = cid;
     805            0 :             auto &airRadCell = s_hbh->cells(cid);
     806            0 :             airRadCell.rh = 0.0;
     807            0 :             airRadCell.sid = sid;
     808            0 :             airRadCell.length(1) = 0.01;
     809            0 :             airRadCell.origin(1) = airRadCell.length(1) / 2.0 + runor;
     810              : 
     811              :             // Sky Cell
     812            0 :             ++cid;
     813            0 :             s_hbh->ExtSkycell(sid) = cid;
     814            0 :             auto &skyCell = s_hbh->cells(cid);
     815            0 :             skyCell.rh = 0.0;
     816            0 :             skyCell.sid = sid;
     817            0 :             skyCell.length(1) = 0.01;
     818            0 :             skyCell.origin(1) = skyCell.length(1) / 2.0 + runor;
     819              : 
     820              :             // Ground Cell
     821            0 :             ++cid;
     822            0 :             s_hbh->ExtGrncell(sid) = cid;
     823            0 :             auto &groundCell = s_hbh->cells(cid);
     824            0 :             groundCell.rh = 0.0;
     825            0 :             groundCell.sid = sid;
     826            0 :             groundCell.length(1) = 0.01;
     827            0 :             groundCell.origin(1) = groundCell.length(1) / 2.0 + runor;
     828            0 :             runor += groundCell.length(1);
     829              : 
     830              :             // External Virtual Cell
     831            0 :             ++cid;
     832            0 :             s_hbh->Extcell(sid) = cid;
     833            0 :             auto &extVirtCell = s_hbh->cells(cid);
     834            0 :             extVirtCell.rh = 0.0;
     835            0 :             extVirtCell.sid = sid;
     836            0 :             extVirtCell.length(1) = 0.01;
     837            0 :             extVirtCell.origin(1) = extVirtCell.length(1) / 2.0 + runor;
     838            0 :             runor += extVirtCell.length(1);
     839              : 
     840              :             // Material Cells
     841            0 :             auto const &constr = state.dataConstruction->Construct(surf.Construction);
     842            0 :             for (int lid = 1; lid <= constr.TotLayers; ++lid) {
     843            0 :                 auto const *mat = dynamic_cast<const MaterialHAMT *>(s_mat->materials(constr.LayerPoint(lid)));
     844            0 :                 assert(mat != nullptr);
     845              : 
     846            0 :                 for (int did = 1; did <= mat->divs; ++did) {
     847            0 :                     ++cid;
     848              : 
     849            0 :                     auto &matCell = s_hbh->cells(cid);
     850            0 :                     matCell.matid = mat->Num;
     851            0 :                     matCell.sid = sid;
     852              : 
     853            0 :                     matCell.temp = mat->itemp;
     854            0 :                     matCell.tempp1 = mat->itemp;
     855            0 :                     matCell.tempp2 = mat->itemp;
     856              : 
     857            0 :                     matCell.rh = mat->irh;
     858            0 :                     matCell.rhp1 = mat->irh;
     859            0 :                     matCell.rhp2 = mat->irh;
     860              : 
     861            0 :                     matCell.density = mat->Density;
     862            0 :                     matCell.spech = mat->SpecHeat;
     863              : 
     864              :                     // Make cells smaller near the surface
     865            0 :                     matCell.length(1) =
     866            0 :                         mat->Thickness * ((std::sin(Constant::Pi * (-double(did) / double(mat->divs)) - Constant::Pi / 2.0) / 2.0) -
     867            0 :                                           (std::sin(Constant::Pi * (-double(did - 1) / double(mat->divs)) - Constant::Pi / 2.0) / 2.0));
     868              : 
     869            0 :                     matCell.origin(1) = runor + matCell.length(1) / 2.0;
     870            0 :                     runor += matCell.length(1);
     871              : 
     872            0 :                     matCell.volume = matCell.length(1) * state.dataSurface->Surface(sid).Area;
     873              :                 }
     874              :             }
     875              : 
     876              :             // Interior Virtual Cell
     877            0 :             ++cid;
     878            0 :             s_hbh->Intcell(sid) = cid;
     879            0 :             auto &intVirtCell = s_hbh->cells(cid);
     880            0 :             intVirtCell.sid = sid;
     881            0 :             intVirtCell.rh = 0.0;
     882            0 :             intVirtCell.length(1) = 0.01;
     883            0 :             intVirtCell.origin(1) = intVirtCell.length(1) / 2.0 + runor;
     884            0 :             runor += intVirtCell.length(1);
     885              : 
     886              :             // Air Convection Cell
     887            0 :             ++cid;
     888            0 :             s_hbh->lastcell(sid) = cid;
     889            0 :             s_hbh->IntConcell(sid) = cid;
     890            0 :             auto &airConvCell2 = s_hbh->cells(cid);
     891            0 :             airConvCell2.rh = 0.0;
     892            0 :             airConvCell2.sid = sid;
     893            0 :             airConvCell2.length(1) = 0.01;
     894            0 :             airConvCell2.origin(1) = airConvCell2.length(1) / 2.0 + runor;
     895              :         }
     896              : 
     897              :         // Find adjacent cells.
     898            0 :         for (int cid1 = 1; cid1 <= s_hbh->TotCellsMax; ++cid1) {
     899            0 :             for (int cid2 = 1; cid2 <= s_hbh->TotCellsMax; ++cid2) {
     900            0 :                 if (cid1 == cid2) continue;
     901              : 
     902            0 :                 auto &cell1 = s_hbh->cells(cid1);
     903            0 :                 auto &cell2 = s_hbh->cells(cid2);
     904              : 
     905            0 :                 if (cell1.sid != cell2.sid) continue;
     906              : 
     907            0 :                 Real64 high1 = cell1.origin(1) + cell1.length(1) / 2.0;
     908            0 :                 Real64 low2 = cell2.origin(1) - cell2.length(1) / 2.0;
     909            0 :                 if (std::abs(low2 - high1) < adjdist) {
     910            0 :                     int adj1 = 0;
     911            0 :                     for (int ii = 1; ii <= adjmax; ++ii) {
     912            0 :                         ++adj1;
     913            0 :                         if (cell1.adjs(adj1) == -1) break;
     914              :                     }
     915            0 :                     int adj2 = 0;
     916            0 :                     for (int ii = 1; ii <= adjmax; ++ii) {
     917            0 :                         ++adj2;
     918            0 :                         if (cell2.adjs(adj2) == -1) break;
     919              :                     }
     920            0 :                     cell1.adjs(adj1) = cid2;
     921            0 :                     cell2.adjs(adj2) = cid1;
     922              : 
     923            0 :                     cell1.adjsl(adj1) = adj2;
     924            0 :                     cell2.adjsl(adj2) = adj1;
     925              : 
     926            0 :                     sid = cell1.sid;
     927            0 :                     cell1.overlap(adj1) = state.dataSurface->Surface(sid).Area;
     928            0 :                     cell2.overlap(adj2) = state.dataSurface->Surface(sid).Area;
     929            0 :                     cell1.dist(adj1) = cell1.length(1) / 2.0;
     930            0 :                     cell2.dist(adj2) = cell2.length(1) / 2.0;
     931              :                 }
     932              :             }
     933              :         }
     934              : 
     935              :         // Reset surface virtual cell origins and volumes. Initialize report variables.
     936              :         static constexpr std::string_view Format_1966("! <HAMT cells>, Surface Name, Construction Name, Cell Numbers\n");
     937            0 :         print(state.files.eio, Format_1966);
     938              :         static constexpr std::string_view Format_1965("! <HAMT origins>, Surface Name, Construction Name, Cell origins (m) \n");
     939            0 :         print(state.files.eio, Format_1965);
     940              :         // cCurrentModuleObject='MaterialProperty:HeatAndMoistureTransfer:*'
     941            0 :         for (int sid = 1; sid <= state.dataSurface->TotSurfaces; ++sid) {
     942            0 :             if (!state.dataSurface->Surface(sid).HeatTransSurf) continue;
     943            0 :             if (state.dataSurface->Surface(sid).Class == SurfaceClass::Window) continue;
     944            0 :             if (state.dataSurface->Surface(sid).HeatTransferAlgorithm != DataSurfaces::HeatTransferModel::HAMT) continue;
     945            0 :             s_hbh->cells(s_hbh->Extcell(sid)).origin(1) += s_hbh->cells(s_hbh->Extcell(sid)).length(1) / 2.0;
     946            0 :             s_hbh->cells(s_hbh->Intcell(sid)).origin(1) -= s_hbh->cells(s_hbh->Intcell(sid)).length(1) / 2.0;
     947            0 :             s_hbh->cells(s_hbh->Extcell(sid)).volume = 0.0;
     948            0 :             s_hbh->cells(s_hbh->Intcell(sid)).volume = 0.0;
     949            0 :             s_hbh->watertot(sid) = 0.0;
     950            0 :             s_hbh->surfrh(sid) = 0.0;
     951            0 :             s_hbh->surfextrh(sid) = 0.0;
     952            0 :             s_hbh->surftemp(sid) = 0.0;
     953            0 :             s_hbh->surfexttemp(sid) = 0.0;
     954            0 :             s_hbh->surfvp(sid) = 0.0;
     955            0 :             SetupOutputVariable(state,
     956              :                                 "HAMT Surface Average Water Content Ratio",
     957              :                                 Constant::Units::kg_kg,
     958            0 :                                 s_hbh->watertot(sid),
     959              :                                 OutputProcessor::TimeStepType::Zone,
     960              :                                 OutputProcessor::StoreType::Average,
     961            0 :                                 state.dataSurface->Surface(sid).Name);
     962            0 :             SetupOutputVariable(state,
     963              :                                 "HAMT Surface Inside Face Temperature",
     964              :                                 Constant::Units::C,
     965            0 :                                 s_hbh->surftemp(sid),
     966              :                                 OutputProcessor::TimeStepType::Zone,
     967              :                                 OutputProcessor::StoreType::Average,
     968            0 :                                 state.dataSurface->Surface(sid).Name);
     969            0 :             SetupOutputVariable(state,
     970              :                                 "HAMT Surface Inside Face Relative Humidity",
     971              :                                 Constant::Units::Perc,
     972            0 :                                 s_hbh->surfrh(sid),
     973              :                                 OutputProcessor::TimeStepType::Zone,
     974              :                                 OutputProcessor::StoreType::Average,
     975            0 :                                 state.dataSurface->Surface(sid).Name);
     976            0 :             SetupOutputVariable(state,
     977              :                                 "HAMT Surface Inside Face Vapor Pressure",
     978              :                                 Constant::Units::Pa,
     979            0 :                                 s_hbh->surfvp(sid),
     980              :                                 OutputProcessor::TimeStepType::Zone,
     981              :                                 OutputProcessor::StoreType::Average,
     982            0 :                                 state.dataSurface->Surface(sid).Name);
     983            0 :             SetupOutputVariable(state,
     984              :                                 "HAMT Surface Outside Face Temperature",
     985              :                                 Constant::Units::C,
     986            0 :                                 s_hbh->surfexttemp(sid),
     987              :                                 OutputProcessor::TimeStepType::Zone,
     988              :                                 OutputProcessor::StoreType::Average,
     989            0 :                                 state.dataSurface->Surface(sid).Name);
     990            0 :             SetupOutputVariable(state,
     991              :                                 "HAMT Surface Outside Face Relative Humidity",
     992              :                                 Constant::Units::Perc,
     993            0 :                                 s_hbh->surfextrh(sid),
     994              :                                 OutputProcessor::TimeStepType::Zone,
     995              :                                 OutputProcessor::StoreType::Average,
     996            0 :                                 state.dataSurface->Surface(sid).Name);
     997              : 
     998              :             // write cell origins to initialization output file
     999            0 :             conid = state.dataSurface->Surface(sid).Construction;
    1000            0 :             print(state.files.eio, "HAMT cells, {},{}", state.dataSurface->Surface(sid).Name, state.dataConstruction->Construct(conid).Name);
    1001            0 :             for (int concell = 1, concell_end = s_hbh->Intcell(sid) - s_hbh->Extcell(sid) + 1; concell <= concell_end; ++concell) {
    1002            0 :                 print(state.files.eio, ",{:4}", concell);
    1003              :             }
    1004            0 :             print(state.files.eio, "\n");
    1005            0 :             print(state.files.eio, "HAMT origins,{},{}", state.dataSurface->Surface(sid).Name, state.dataConstruction->Construct(conid).Name);
    1006            0 :             for (int cellid = s_hbh->Extcell(sid); cellid <= s_hbh->Intcell(sid); ++cellid) {
    1007            0 :                 print(state.files.eio, ",{:10.7F}", s_hbh->cells(cellid).origin(1));
    1008              :             }
    1009            0 :             print(state.files.eio, "\n");
    1010              : 
    1011            0 :             for (int cellid = s_hbh->Extcell(sid), concell = 1; cellid <= s_hbh->Intcell(sid); ++cellid, ++concell) {
    1012            0 :                 SetupOutputVariable(state,
    1013            0 :                                     format("HAMT Surface Temperature Cell {}", concell),
    1014              :                                     Constant::Units::C,
    1015            0 :                                     s_hbh->cells(cellid).temp,
    1016              :                                     OutputProcessor::TimeStepType::Zone,
    1017              :                                     OutputProcessor::StoreType::Average,
    1018            0 :                                     state.dataSurface->Surface(sid).Name);
    1019              :             }
    1020            0 :             for (int cellid = s_hbh->Extcell(sid), concell = 1; cellid <= s_hbh->Intcell(sid); ++cellid, ++concell) {
    1021            0 :                 SetupOutputVariable(state,
    1022            0 :                                     format("HAMT Surface Water Content Cell {}", concell),
    1023              :                                     Constant::Units::kg_kg,
    1024            0 :                                     s_hbh->cells(cellid).wreport,
    1025              :                                     OutputProcessor::TimeStepType::Zone,
    1026              :                                     OutputProcessor::StoreType::Average,
    1027            0 :                                     state.dataSurface->Surface(sid).Name);
    1028              :             }
    1029            0 :             for (int cellid = s_hbh->Extcell(sid), concell = 1; cellid <= s_hbh->Intcell(sid); ++cellid, ++concell) {
    1030            0 :                 SetupOutputVariable(state,
    1031            0 :                                     format("HAMT Surface Relative Humidity Cell {}", concell),
    1032              :                                     Constant::Units::Perc,
    1033            0 :                                     s_hbh->cells(cellid).rhp,
    1034              :                                     OutputProcessor::TimeStepType::Zone,
    1035              :                                     OutputProcessor::StoreType::Average,
    1036            0 :                                     state.dataSurface->Surface(sid).Name);
    1037              :             }
    1038              :         }
    1039              : 
    1040            0 :         ScanForReports(state, "Constructions", DoReport, "Constructions");
    1041            0 :         if (DoReport) {
    1042              : 
    1043              :             static constexpr std::string_view Format_108("! <Material Nominal Resistance>, Material Name,  Nominal R\n");
    1044            0 :             print(state.files.eio, Format_108);
    1045              : 
    1046            0 :             for (auto const *mat : s_mat->materials) {
    1047              :                 static constexpr std::string_view Format_111("Material Nominal Resistance,{},{:.4R}\n");
    1048            0 :                 print(state.files.eio, Format_111, mat->Name, mat->NominalR);
    1049              :             }
    1050              :         }
    1051            0 :     }
    1052              : 
    1053            0 :     void CalcHeatBalHAMT(EnergyPlusData &state, int const sid, Real64 &SurfTempInTmp, Real64 &TempSurfOutTmp)
    1054              :     {
    1055              :         // SUBROUTINE INFORMATION:
    1056              :         //       AUTHOR         Phillip Biddulph
    1057              :         //       DATE WRITTEN   June 2008
    1058              :         //       MODIFIED       na
    1059              :         //       RE-ENGINEERED  na
    1060              : 
    1061              :         // PURPOSE OF THIS SUBROUTINE:
    1062              :         // To calculate the heat and moisture transfer through the surface
    1063              : 
    1064              :         // Using/Aliasing
    1065              :         using DataSurfaces::OtherSideCondModeledExt;
    1066              : 
    1067              :         // Locals
    1068              :         // SUBROUTINE ARGUMENT DEFINITIONS:
    1069              : 
    1070              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1071            0 :         static std::string const HAMTExt("HAMT-Ext");
    1072            0 :         static std::string const HAMTInt("HAMT-Int");
    1073              : 
    1074              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1075              :         Real64 SurfTempInP;
    1076              :         Real64 RhoIn;
    1077              :         Real64 RhoOut;
    1078              :         Real64 torsum;
    1079              :         Real64 oorsum;
    1080              :         Real64 phioosum;
    1081              :         Real64 phiorsum;
    1082              :         Real64 vpoosum;
    1083              :         Real64 vporsum;
    1084              :         Real64 rhr1;
    1085              :         Real64 rhr2;
    1086              :         Real64 wcap;
    1087              :         Real64 thermr1;
    1088              :         Real64 thermr2;
    1089              :         Real64 tcap;
    1090              :         Real64 qvp;
    1091              :         Real64 vaporr1;
    1092              :         Real64 vaporr2;
    1093              :         Real64 vpdiff;
    1094              :         Real64 sumtp1;
    1095              :         Real64 tempmax;
    1096              :         Real64 tempmin;
    1097              : 
    1098              :         int itter;
    1099              : 
    1100              :         Real64 denominator;
    1101              : 
    1102            0 :         auto &s_mat = state.dataMaterial;
    1103            0 :         auto &s_hbh = state.dataHeatBalHAMTMgr;
    1104              : 
    1105            0 :         if (state.dataGlobal->BeginEnvrnFlag && s_hbh->MyEnvrnFlag(sid)) {
    1106            0 :             auto &extCell = s_hbh->cells(s_hbh->Extcell(sid));
    1107            0 :             extCell.rh = 0.0;
    1108            0 :             extCell.rhp1 = 0.0;
    1109            0 :             extCell.rhp2 = 0.0;
    1110              : 
    1111            0 :             extCell.temp = 10.0;
    1112            0 :             extCell.tempp1 = 10.0;
    1113            0 :             extCell.tempp2 = 10.0;
    1114              : 
    1115            0 :             auto &intCell = s_hbh->cells(s_hbh->Intcell(sid));
    1116            0 :             intCell.rh = 0.0;
    1117            0 :             intCell.rhp1 = 0.0;
    1118            0 :             intCell.rhp2 = 0.0;
    1119              : 
    1120            0 :             intCell.temp = 10.0;
    1121            0 :             intCell.tempp1 = 10.0;
    1122            0 :             intCell.tempp2 = 10.0;
    1123              : 
    1124            0 :             for (int cid = s_hbh->Extcell(sid) + 1; cid <= s_hbh->Intcell(sid) - 1; ++cid) {
    1125            0 :                 auto &cell = s_hbh->cells(cid);
    1126            0 :                 auto const *mat = dynamic_cast<const MaterialHAMT *>(s_mat->materials(cell.matid));
    1127            0 :                 assert(mat != nullptr);
    1128            0 :                 cell.temp = mat->itemp;
    1129            0 :                 cell.tempp1 = mat->itemp;
    1130            0 :                 cell.tempp2 = mat->itemp;
    1131              : 
    1132            0 :                 cell.rh = mat->irh;
    1133            0 :                 cell.rhp1 = mat->irh;
    1134            0 :                 cell.rhp2 = mat->irh;
    1135              :             }
    1136            0 :             s_hbh->MyEnvrnFlag(sid) = false;
    1137              :         }
    1138            0 :         if (!state.dataGlobal->BeginEnvrnFlag) {
    1139            0 :             s_hbh->MyEnvrnFlag(sid) = true;
    1140              :         }
    1141              : 
    1142            0 :         auto &extCell = s_hbh->cells(s_hbh->Extcell(sid));
    1143            0 :         auto &extRadCell = s_hbh->cells(s_hbh->ExtRadcell(sid));
    1144            0 :         auto &extSkyCell = s_hbh->cells(s_hbh->ExtSkycell(sid));
    1145            0 :         auto &extGrnCell = s_hbh->cells(s_hbh->ExtGrncell(sid));
    1146            0 :         auto &extConCell = s_hbh->cells(s_hbh->ExtConcell(sid));
    1147              : 
    1148              :         // Set all the boundary values
    1149            0 :         extRadCell.temp = state.dataMstBal->TempOutsideAirFD(sid);
    1150            0 :         extConCell.temp = state.dataMstBal->TempOutsideAirFD(sid);
    1151            0 :         Real64 spaceMAT = state.dataZoneTempPredictorCorrector->spaceHeatBalance(state.dataSurface->Surface(sid).spaceNum).MAT;
    1152            0 :         if (state.dataSurface->Surface(sid).ExtBoundCond == OtherSideCondModeledExt) {
    1153              :             // CR8046 switch modeled rad temp for sky temp.
    1154            0 :             extSkyCell.temp = state.dataSurface->OSCM(state.dataSurface->Surface(sid).OSCMPtr).TRad;
    1155            0 :             extCell.Qadds = 0.0; // eliminate incident shortwave on underlying surface
    1156              :         } else {
    1157            0 :             extSkyCell.temp = state.dataEnvrn->SkyTemp;
    1158            0 :             extCell.Qadds = state.dataSurface->Surface(sid).Area * state.dataHeatBalSurf->SurfOpaqQRadSWOutAbs(sid);
    1159              :         }
    1160              : 
    1161            0 :         extGrnCell.temp = state.dataMstBal->TempOutsideAirFD(sid);
    1162            0 :         RhoOut = state.dataMstBal->RhoVaporAirOut(sid);
    1163              : 
    1164              :         // Special case when the surface is an internal mass
    1165            0 :         if (state.dataSurface->Surface(sid).ExtBoundCond == sid) {
    1166            0 :             extConCell.temp = spaceMAT;
    1167            0 :             RhoOut = state.dataMstBal->RhoVaporAirIn(sid);
    1168              :         }
    1169              : 
    1170            0 :         RhoIn = state.dataMstBal->RhoVaporAirIn(sid);
    1171              : 
    1172            0 :         extRadCell.htc = state.dataMstBal->HAirFD(sid);
    1173            0 :         extConCell.htc = state.dataMstBal->HConvExtFD(sid);
    1174            0 :         extSkyCell.htc = state.dataMstBal->HSkyFD(sid);
    1175            0 :         extGrnCell.htc = state.dataMstBal->HGrndFD(sid);
    1176              : 
    1177            0 :         auto &intCell = s_hbh->cells(s_hbh->Intcell(sid));
    1178            0 :         auto &intConCell = s_hbh->cells(s_hbh->IntConcell(sid));
    1179              : 
    1180            0 :         intConCell.temp = spaceMAT;
    1181            0 :         intConCell.htc = state.dataMstBal->HConvInFD(sid);
    1182              : 
    1183            0 :         intCell.Qadds = state.dataSurface->Surface(sid).Area *
    1184            0 :                         (state.dataHeatBalSurf->SurfOpaqQRadSWInAbs(sid) + state.dataHeatBalSurf->SurfQdotRadNetLWInPerArea(sid) +
    1185            0 :                          state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(sid) + state.dataHeatBal->SurfQdotRadIntGainsInPerArea(sid) +
    1186            0 :                          state.dataHeatBalSurf->SurfQAdditionalHeatSourceInside(sid));
    1187              : 
    1188            0 :         extConCell.rh = PsyRhFnTdbRhov(state, extConCell.temp, RhoOut, HAMTExt);
    1189            0 :         intConCell.rh = PsyRhFnTdbRhov(state, intConCell.temp, RhoIn, HAMTInt);
    1190              : 
    1191            0 :         if (extConCell.rh > rhmax) {
    1192            0 :             extConCell.rh = rhmax;
    1193              :         }
    1194            0 :         if (intConCell.rh > rhmax) {
    1195            0 :             intConCell.rh = rhmax;
    1196              :         }
    1197              : 
    1198              :         // PDB August 2009 Start! Correction for when no vapour transfer coefficient have been defined.
    1199            0 :         if (s_hbh->extvtcflag(sid)) {
    1200            0 :             extConCell.vtc = s_hbh->extvtc(sid);
    1201              :         } else {
    1202            0 :             if (extConCell.rh > 0) {
    1203            0 :                 extConCell.vtc =
    1204            0 :                     state.dataMstBal->HMassConvExtFD(sid) * RhoOut / (PsyPsatFnTemp(state, state.dataMstBal->TempOutsideAirFD(sid)) * extConCell.rh);
    1205              :             } else {
    1206            0 :                 extConCell.vtc = 10000.0;
    1207              :             }
    1208              :         }
    1209              : 
    1210            0 :         if (s_hbh->intvtcflag(sid)) {
    1211            0 :             intConCell.vtc = s_hbh->intvtc(sid);
    1212            0 :             state.dataMstBal->HMassConvInFD(sid) = intConCell.vtc * PsyPsatFnTemp(state, spaceMAT) * intConCell.rh / RhoIn;
    1213              :         } else {
    1214            0 :             if (intConCell.rh > 0) {
    1215            0 :                 intConCell.vtc = state.dataMstBal->HMassConvInFD(sid) * RhoIn / (PsyPsatFnTemp(state, spaceMAT) * intConCell.rh);
    1216              :             } else {
    1217            0 :                 intConCell.vtc = 10000.0;
    1218              :             }
    1219              :         }
    1220              :         // PDB August 2009 End
    1221              : 
    1222              :         // Initialise
    1223            0 :         for (int cid = s_hbh->firstcell(sid); cid <= s_hbh->Extcell(sid) - 1; ++cid) {
    1224            0 :             auto &cell = s_hbh->cells(cid);
    1225            0 :             cell.tempp1 = cell.temp;
    1226            0 :             cell.tempp2 = cell.temp;
    1227            0 :             cell.rhp1 = cell.rh;
    1228            0 :             cell.rhp2 = cell.rh;
    1229              :         }
    1230            0 :         for (int cid = s_hbh->Intcell(sid) + 1; cid <= s_hbh->lastcell(sid); ++cid) {
    1231            0 :             auto &cell = s_hbh->cells(cid);
    1232            0 :             cell.tempp1 = cell.temp;
    1233            0 :             cell.tempp2 = cell.temp;
    1234            0 :             cell.rhp1 = cell.rh;
    1235            0 :             cell.rhp2 = cell.rh;
    1236              :         }
    1237              : 
    1238            0 :         itter = 0;
    1239              :         while (true) {
    1240            0 :             ++itter;
    1241              :             // Update Moisture values
    1242              : 
    1243            0 :             for (int cid = s_hbh->firstcell(sid); cid <= s_hbh->lastcell(sid); ++cid) {
    1244            0 :                 auto &cell = s_hbh->cells(cid);
    1245            0 :                 cell.vp = RHtoVP(state, cell.rh, cell.temp);
    1246            0 :                 cell.vpp1 = RHtoVP(state, cell.rhp1, cell.tempp1);
    1247            0 :                 cell.vpsat = PsyPsatFnTemp(state, cell.tempp1);
    1248            0 :                 if (cell.matid > 0) {
    1249            0 :                     auto const *mat = dynamic_cast<const MaterialHAMT *>(s_mat->materials(cell.matid));
    1250            0 :                     assert(mat != nullptr);
    1251            0 :                     interp(mat->niso, mat->isorh, mat->isodata, cell.rhp1, cell.water, cell.dwdphi);
    1252            0 :                     if (state.dataEnvrn->IsRain && s_hbh->rainswitch) {
    1253            0 :                         interp(mat->nsuc, mat->sucwater, mat->sucdata, cell.water, cell.dw);
    1254              :                     } else {
    1255            0 :                         interp(mat->nred, mat->redwater, mat->reddata, cell.water, cell.dw);
    1256              :                     }
    1257            0 :                     interp(mat->nmu, mat->murh, mat->mudata, cell.rhp1, cell.mu);
    1258            0 :                     interp(mat->ntc, mat->tcwater, mat->tcdata, cell.water, cell.wthermalc);
    1259              :                 }
    1260              :             }
    1261              : 
    1262              :             // Calculate Heat and Vapor resistances,
    1263            0 :             for (int cid = s_hbh->Extcell(sid); cid <= s_hbh->Intcell(sid); ++cid) {
    1264            0 :                 torsum = 0.0;
    1265            0 :                 oorsum = 0.0;
    1266            0 :                 vpdiff = 0.0;
    1267            0 :                 auto &cell = s_hbh->cells(cid);
    1268            0 :                 for (int ii = 1; ii <= adjmax; ++ii) {
    1269            0 :                     int adj = cell.adjs(ii);
    1270            0 :                     int adjl = cell.adjsl(ii);
    1271            0 :                     if (adj == -1) break;
    1272              : 
    1273            0 :                     if (cell.htc > 0) {
    1274            0 :                         thermr1 = 1.0 / (cell.overlap(ii) * cell.htc);
    1275            0 :                     } else if (cell.matid > 0) {
    1276            0 :                         thermr1 = cell.dist(ii) / (cell.overlap(ii) * cell.wthermalc);
    1277              :                     } else {
    1278            0 :                         thermr1 = 0.0;
    1279              :                     }
    1280              : 
    1281            0 :                     if (cell.vtc > 0) {
    1282            0 :                         vaporr1 = 1.0 / (cell.overlap(ii) * cell.vtc);
    1283            0 :                     } else if (cell.matid > 0) {
    1284            0 :                         vaporr1 = (cell.dist(ii) * cell.mu) / (cell.overlap(ii) * WVDC(cell.tempp1, state.dataEnvrn->OutBaroPress));
    1285              :                     } else {
    1286            0 :                         vaporr1 = 0.0;
    1287              :                     }
    1288              : 
    1289            0 :                     auto &adjCell = s_hbh->cells(adj);
    1290            0 :                     if (adjCell.htc > 0) {
    1291            0 :                         thermr2 = 1.0 / (cell.overlap(ii) * adjCell.htc);
    1292            0 :                     } else if (adjCell.matid > 0) {
    1293            0 :                         thermr2 = adjCell.dist(adjl) / (cell.overlap(ii) * adjCell.wthermalc);
    1294              :                     } else {
    1295            0 :                         thermr2 = 0.0;
    1296              :                     }
    1297              : 
    1298            0 :                     if (adjCell.vtc > 0) {
    1299            0 :                         vaporr2 = 1.0 / (cell.overlap(ii) * adjCell.vtc);
    1300            0 :                     } else if (adjCell.matid > 0) {
    1301            0 :                         vaporr2 = adjCell.mu * adjCell.dist(adjl) / (WVDC(adjCell.tempp1, state.dataEnvrn->OutBaroPress) * cell.overlap(ii));
    1302              :                     } else {
    1303            0 :                         vaporr2 = 0.0;
    1304              :                     }
    1305              : 
    1306            0 :                     if (thermr1 + thermr2 > 0) {
    1307            0 :                         oorsum += 1.0 / (thermr1 + thermr2);
    1308            0 :                         torsum += adjCell.tempp1 / (thermr1 + thermr2);
    1309              :                     }
    1310            0 :                     if (vaporr1 + vaporr2 > 0) {
    1311            0 :                         vpdiff += (adjCell.vp - cell.vp) / (vaporr1 + vaporr2);
    1312              :                     }
    1313              :                 }
    1314              : 
    1315              :                 // Calculate Heat Capacitance
    1316            0 :                 tcap = ((cell.density * cell.spech + cell.water * wspech) * cell.volume);
    1317              : 
    1318              :                 // calculate the latent heat if wanted and check for divergence
    1319            0 :                 qvp = 0.0;
    1320            0 :                 if ((cell.matid > 0) && (s_hbh->latswitch)) {
    1321            0 :                     qvp = vpdiff * whv;
    1322              :                 }
    1323            0 :                 if (std::abs(qvp) > qvplim) {
    1324            0 :                     if (!state.dataGlobal->WarmupFlag) {
    1325            0 :                         ++s_hbh->qvpErrCount;
    1326            0 :                         if (s_hbh->qvpErrCount < 16) {
    1327            0 :                             ShowWarningError(
    1328            0 :                                 state, format("HeatAndMoistureTransfer: Large Latent Heat for Surface {}", state.dataSurface->Surface(sid).Name));
    1329              :                         } else {
    1330            0 :                             ShowRecurringWarningErrorAtEnd(state, "HeatAndMoistureTransfer: Large Latent Heat Errors ", s_hbh->qvpErrReport);
    1331              :                         }
    1332              :                     }
    1333            0 :                     qvp = 0.0;
    1334              :                 }
    1335              : 
    1336              :                 // Calculate the temperature for the next time step
    1337            0 :                 cell.tempp1 = (torsum + qvp + cell.Qadds + (tcap * cell.temp / s_hbh->deltat)) / (oorsum + (tcap / s_hbh->deltat));
    1338              :             }
    1339              : 
    1340              :             // Check for silly temperatures
    1341            0 :             tempmax = maxval(s_hbh->cells, &subcell::tempp1);
    1342            0 :             tempmin = minval(s_hbh->cells, &subcell::tempp1);
    1343            0 :             if (tempmax > state.dataHeatBalSurf->MaxSurfaceTempLimit) {
    1344            0 :                 if (!state.dataGlobal->WarmupFlag) {
    1345            0 :                     if (state.dataSurface->SurfHighTempErrCount(sid) == 0) {
    1346            0 :                         ShowSevereMessage(
    1347              :                             state,
    1348            0 :                             format("HAMT: Temperature (high) out of bounds ({:.2R}) for surface={}", tempmax, state.dataSurface->Surface(sid).Name));
    1349            0 :                         ShowContinueErrorTimeStamp(state, "");
    1350              :                     }
    1351            0 :                     ShowRecurringWarningErrorAtEnd(state,
    1352            0 :                                                    "HAMT: Temperature Temperature (high) out of bounds; Surface=" +
    1353            0 :                                                        state.dataSurface->Surface(sid).Name,
    1354            0 :                                                    state.dataSurface->SurfHighTempErrCount(sid),
    1355              :                                                    tempmax,
    1356              :                                                    tempmax,
    1357              :                                                    _,
    1358              :                                                    "C",
    1359              :                                                    "C");
    1360              :                 }
    1361              :             }
    1362            0 :             if (tempmax > state.dataHeatBalSurf->MaxSurfaceTempLimitBeforeFatal) {
    1363            0 :                 if (!state.dataGlobal->WarmupFlag) {
    1364            0 :                     ShowSevereError(state,
    1365            0 :                                     format("HAMT: HAMT: Temperature (high) out of bounds ( {:.2R}) for surface={}",
    1366              :                                            tempmax,
    1367            0 :                                            state.dataSurface->Surface(sid).Name));
    1368            0 :                     ShowContinueErrorTimeStamp(state, "");
    1369            0 :                     ShowFatalError(state, "Program terminates due to preceding condition.");
    1370              :                 }
    1371              :             }
    1372            0 :             if (tempmin < MinSurfaceTempLimit) {
    1373            0 :                 if (!state.dataGlobal->WarmupFlag) {
    1374            0 :                     if (state.dataSurface->SurfHighTempErrCount(sid) == 0) {
    1375            0 :                         ShowSevereMessage(
    1376              :                             state,
    1377            0 :                             format("HAMT: Temperature (low) out of bounds ({:.2R}) for surface={}", tempmin, state.dataSurface->Surface(sid).Name));
    1378            0 :                         ShowContinueErrorTimeStamp(state, "");
    1379              :                     }
    1380            0 :                     ShowRecurringWarningErrorAtEnd(state,
    1381            0 :                                                    "HAMT: Temperature Temperature (high) out of bounds; Surface=" +
    1382            0 :                                                        state.dataSurface->Surface(sid).Name,
    1383            0 :                                                    state.dataSurface->SurfHighTempErrCount(sid),
    1384              :                                                    tempmin,
    1385              :                                                    tempmin,
    1386              :                                                    _,
    1387              :                                                    "C",
    1388              :                                                    "C");
    1389              :                 }
    1390              :             }
    1391            0 :             if (tempmin < MinSurfaceTempLimitBeforeFatal) {
    1392            0 :                 if (!state.dataGlobal->WarmupFlag) {
    1393            0 :                     ShowSevereError(state,
    1394            0 :                                     format("HAMT: HAMT: Temperature (low) out of bounds ( {:.2R}) for surface={}",
    1395              :                                            tempmin,
    1396            0 :                                            state.dataSurface->Surface(sid).Name));
    1397            0 :                     ShowContinueErrorTimeStamp(state, "");
    1398            0 :                     ShowFatalError(state, "Program terminates due to preceding condition.");
    1399              :                 }
    1400              :             }
    1401              : 
    1402              :             // Calculate the liquid and vapor resisitances
    1403            0 :             for (int cid = s_hbh->Extcell(sid); cid <= s_hbh->Intcell(sid); ++cid) {
    1404            0 :                 phioosum = 0.0;
    1405            0 :                 phiorsum = 0.0;
    1406            0 :                 vpoosum = 0.0;
    1407            0 :                 vporsum = 0.0;
    1408              : 
    1409            0 :                 auto &cell = s_hbh->cells(cid);
    1410            0 :                 for (int ii = 1; ii <= adjmax; ++ii) {
    1411            0 :                     int adj = cell.adjs(ii);
    1412            0 :                     int adjl = cell.adjsl(ii);
    1413            0 :                     if (adj == -1) break;
    1414              : 
    1415            0 :                     if (cell.vtc > 0) {
    1416            0 :                         vaporr1 = 1.0 / (cell.overlap(ii) * cell.vtc);
    1417            0 :                     } else if (cell.matid > 0) {
    1418            0 :                         vaporr1 = (cell.dist(ii) * cell.mu) / (cell.overlap(ii) * WVDC(cell.tempp1, state.dataEnvrn->OutBaroPress));
    1419              :                     } else {
    1420            0 :                         vaporr1 = 0.0;
    1421              :                     }
    1422              : 
    1423            0 :                     auto &adjCell = s_hbh->cells(adj);
    1424            0 :                     if (adjCell.vtc > 0) {
    1425            0 :                         vaporr2 = 1.0 / (cell.overlap(ii) * adjCell.vtc);
    1426            0 :                     } else if (adjCell.matid > 0) {
    1427            0 :                         vaporr2 = (adjCell.dist(adjl) * adjCell.mu) / (cell.overlap(ii) * WVDC(adjCell.tempp1, state.dataEnvrn->OutBaroPress));
    1428              :                     } else {
    1429            0 :                         vaporr2 = 0.0;
    1430              :                     }
    1431            0 :                     if (vaporr1 + vaporr2 > 0) {
    1432            0 :                         vpoosum += 1.0 / (vaporr1 + vaporr2);
    1433            0 :                         vporsum += (adjCell.vpp1 / (vaporr1 + vaporr2));
    1434              :                     }
    1435              : 
    1436            0 :                     if ((cell.dw > 0) && (cell.dwdphi > 0)) {
    1437            0 :                         rhr1 = cell.dist(ii) / (cell.overlap(ii) * cell.dw * cell.dwdphi);
    1438              :                     } else {
    1439            0 :                         rhr1 = 0.0;
    1440              :                     }
    1441            0 :                     if ((adjCell.dw > 0) && (adjCell.dwdphi > 0)) {
    1442            0 :                         rhr2 = adjCell.dist(adjl) / (cell.overlap(ii) * adjCell.dw * adjCell.dwdphi);
    1443              :                     } else {
    1444            0 :                         rhr2 = 0.0;
    1445              :                     }
    1446              : 
    1447              :                     //             IF(rhr1+rhr2>0)THEN
    1448            0 :                     if (rhr1 * rhr2 > 0) {
    1449            0 :                         phioosum += 1.0 / (rhr1 + rhr2);
    1450            0 :                         phiorsum += (adjCell.rhp1 / (rhr1 + rhr2));
    1451              :                     }
    1452              :                 }
    1453              : 
    1454              :                 // Moisture Capacitance
    1455            0 :                 if (cell.dwdphi > 0.0) {
    1456            0 :                     wcap = cell.dwdphi * cell.volume;
    1457              :                 } else {
    1458            0 :                     wcap = 0.0;
    1459              :                 }
    1460              : 
    1461              :                 // Calculate the RH for the next time step
    1462            0 :                 denominator = (phioosum + vpoosum * cell.vpsat + wcap / s_hbh->deltat);
    1463            0 :                 if (denominator != 0.0) {
    1464            0 :                     cell.rhp1 = (phiorsum + vporsum + (wcap * cell.rh) / s_hbh->deltat) / denominator;
    1465              :                 } else {
    1466            0 :                     ShowSevereError(state, "CalcHeatBalHAMT: demoninator in calculating RH is zero.  Check material properties for accuracy.");
    1467            0 :                     ShowContinueError(state, format("...Problem occurs in Material=\"{}\".", s_mat->materials(cell.matid)->Name));
    1468            0 :                     ShowFatalError(state, "Program terminates due to preceding condition.");
    1469              :                 }
    1470              : 
    1471            0 :                 if (cell.rhp1 > rhmax) {
    1472            0 :                     cell.rhp1 = rhmax;
    1473              :                 }
    1474              :             }
    1475              : 
    1476              :             // Check for convergence or too many itterations
    1477            0 :             sumtp1 = 0.0;
    1478            0 :             for (int cid = s_hbh->Extcell(sid); cid <= s_hbh->Intcell(sid); ++cid) {
    1479            0 :                 auto const &cell = s_hbh->cells(cid);
    1480            0 :                 if (sumtp1 < std::abs(cell.tempp2 - cell.tempp1)) {
    1481            0 :                     sumtp1 = std::abs(cell.tempp2 - cell.tempp1);
    1482              :                 }
    1483              :             }
    1484            0 :             if (sumtp1 < convt) {
    1485            0 :                 break;
    1486              :             }
    1487            0 :             if (itter > ittermax) {
    1488            0 :                 break;
    1489              :             }
    1490            0 :             for (int cid = s_hbh->firstcell(sid); cid <= s_hbh->lastcell(sid); ++cid) {
    1491            0 :                 auto &cell = s_hbh->cells(cid);
    1492            0 :                 cell.tempp2 = cell.tempp1;
    1493            0 :                 cell.rhp2 = cell.rhp1;
    1494              :             }
    1495            0 :         }
    1496              : 
    1497              :         // report back to CalcHeatBalanceInsideSurf
    1498            0 :         TempSurfOutTmp = extCell.tempp1;
    1499            0 :         SurfTempInTmp = intCell.tempp1;
    1500              : 
    1501            0 :         SurfTempInP = intCell.rhp1 * PsyPsatFnTemp(state, intCell.tempp1);
    1502              : 
    1503            0 :         state.dataMstBal->RhoVaporSurfIn(sid) = SurfTempInP / (461.52 * (spaceMAT + Constant::Kelvin));
    1504            0 :     }
    1505              : 
    1506            0 :     void UpdateHeatBalHAMT(EnergyPlusData &state, int const sid)
    1507              :     {
    1508              :         // SUBROUTINE INFORMATION:
    1509              :         //       AUTHOR         Phillip Biddulph
    1510              :         //       DATE WRITTEN   June 2008
    1511              :         //       MODIFIED       na
    1512              :         //       RE-ENGINEERED  na
    1513              : 
    1514              :         // PURPOSE OF THIS SUBROUTINE:
    1515              :         // The zone heat balance equation has converged, so now the HAMT values are to be fixed
    1516              :         // ready for the next itteration.
    1517              :         // Fill all the report variables
    1518              : 
    1519              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1520              :         Real64 watermass;
    1521              :         Real64 matmass;
    1522              :         // unused1208    REAL(r64), SAVE :: InOld=0.0D0
    1523              :         // unused1208    REAL(r64), SAVE :: OutOld=0.0D0
    1524              : 
    1525            0 :         auto &s_hbh = state.dataHeatBalHAMTMgr;
    1526              : 
    1527              :         // Update Temperatures and RHs. Calculate report variables
    1528            0 :         matmass = 0.0;
    1529            0 :         watermass = 0.0;
    1530            0 :         for (int cid = s_hbh->firstcell(sid); cid <= s_hbh->lastcell(sid); ++cid) {
    1531            0 :             auto &cell = s_hbh->cells(cid);
    1532              :             // fix HAMT values for this surface
    1533            0 :             cell.temp = cell.tempp1;
    1534            0 :             cell.rh = cell.rhp1;
    1535            0 :             cell.rhp = cell.rh * 100.0;
    1536            0 :             if (cell.density > 0.0) {
    1537            0 :                 cell.wreport = cell.water / cell.density;
    1538            0 :                 watermass += (cell.water * cell.volume);
    1539            0 :                 matmass += (cell.density * cell.volume);
    1540              :             }
    1541              :         }
    1542              : 
    1543            0 :         s_hbh->watertot(sid) = 0.0;
    1544            0 :         if (matmass > 0) s_hbh->watertot(sid) = watermass / matmass;
    1545              : 
    1546            0 :         s_hbh->surfrh(sid) = 100.0 * s_hbh->cells(s_hbh->Intcell(sid)).rh;
    1547            0 :         s_hbh->surfextrh(sid) = 100.0 * s_hbh->cells(s_hbh->Extcell(sid)).rh;
    1548            0 :         s_hbh->surftemp(sid) = s_hbh->cells(s_hbh->Intcell(sid)).temp;
    1549            0 :         s_hbh->surfexttemp(sid) = s_hbh->cells(s_hbh->Extcell(sid)).temp;
    1550            0 :         s_hbh->surfvp(sid) = RHtoVP(state, s_hbh->cells(s_hbh->Intcell(sid)).rh, s_hbh->cells(s_hbh->Intcell(sid)).temp);
    1551            0 :     }
    1552              : 
    1553            0 :     void interp(int const ndata,
    1554              :                 const Array1D<Real64> &xx,
    1555              :                 const Array1D<Real64> &yy,
    1556              :                 Real64 const invalue,
    1557              :                 Real64 &outvalue,
    1558              :                 ObjexxFCL::Optional<Real64> outgrad)
    1559              :     {
    1560              :         // SUBROUTINE INFORMATION:
    1561              :         //       AUTHOR         Phillip Biddulph
    1562              :         //       DATE WRITTEN   June 2008
    1563              :         //       MODIFIED       na
    1564              :         //       RE-ENGINEERED  na
    1565              : 
    1566              :         // PURPOSE OF THIS SUBROUTINE:
    1567              :         // To find a value by searching an array and interpolating between two coordinates
    1568              :         // Also returns the gradient if required.
    1569              : 
    1570              :         // METHODOLOGY EMPLOYED:
    1571              :         // Simple search
    1572              : 
    1573              :         // Argument array dimensioning
    1574            0 :         EP_SIZE_CHECK(xx, ndata);
    1575            0 :         EP_SIZE_CHECK(yy, ndata);
    1576              : 
    1577              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1578              :         Real64 xxlow;
    1579              :         Real64 xxhigh;
    1580              :         Real64 yylow;
    1581              :         Real64 yyhigh;
    1582              :         Real64 mygrad;
    1583              : 
    1584            0 :         mygrad = 0.0;
    1585            0 :         outvalue = 0.0;
    1586              : 
    1587            0 :         if (ndata > 1) {
    1588            0 :             xxlow = xx(1);
    1589            0 :             yylow = yy(1);
    1590            0 :             for (int step = 2; step <= ndata; ++step) {
    1591            0 :                 xxhigh = xx(step);
    1592            0 :                 yyhigh = yy(step);
    1593            0 :                 if (invalue <= xxhigh) break;
    1594            0 :                 xxlow = xxhigh;
    1595            0 :                 yylow = yyhigh;
    1596              :             }
    1597              : 
    1598            0 :             if (xxhigh > xxlow) {
    1599            0 :                 mygrad = (yyhigh - yylow) / (xxhigh - xxlow);
    1600            0 :                 outvalue = (invalue - xxlow) * mygrad + yylow;
    1601              :                 // PDB August 2009 bug fix
    1602            0 :             } else if (std::abs(xxhigh - xxlow) < 0.0000000001) {
    1603            0 :                 outvalue = yylow;
    1604              :             }
    1605              :         }
    1606              : 
    1607            0 :         if (present(outgrad)) {
    1608              :             // return gradient if required
    1609            0 :             outgrad = mygrad;
    1610              :         }
    1611            0 :     }
    1612              : 
    1613            0 :     Real64 RHtoVP(EnergyPlusData &state, Real64 const RH, Real64 const Temperature)
    1614              :     {
    1615              :         // FUNCTION INFORMATION:
    1616              :         //       AUTHOR         Phillip Biddulph
    1617              :         //       DATE WRITTEN   June 2008
    1618              :         //       MODIFIED       na
    1619              :         //       RE-ENGINEERED  na
    1620              : 
    1621              :         // PURPOSE OF THIS FUNCTION:
    1622              :         // Convert Relative Humidity and Temperature to Vapor Pressure
    1623              : 
    1624              :         // Return value
    1625              :         Real64 RHtoVP;
    1626              : 
    1627              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    1628              :         Real64 VPSat;
    1629              : 
    1630            0 :         VPSat = PsyPsatFnTemp(state, Temperature);
    1631              : 
    1632            0 :         RHtoVP = RH * VPSat;
    1633              : 
    1634            0 :         return RHtoVP;
    1635              :     }
    1636              : 
    1637            0 :     Real64 WVDC(Real64 const Temperature, Real64 const ambp)
    1638              :     {
    1639              :         // FUNCTION INFORMATION:
    1640              :         //       AUTHOR         Phillip Biddulph
    1641              :         //       DATE WRITTEN   June 2008
    1642              :         //       MODIFIED       na
    1643              :         //       RE-ENGINEERED  na
    1644              : 
    1645              :         // PURPOSE OF THIS FUNCTION:
    1646              :         // To calculate the Water Vapor Diffusion Coefficient in air
    1647              :         // using the temperature and ambient atmospheric pressor
    1648              : 
    1649              :         // REFERENCES:
    1650              :         // K?zel, H.M. (1995) Simultaneous Heat and Moisture Transport in Building Components.
    1651              :         // One- and two-dimensional calculation using simple parameters. IRB Verlag 1995
    1652              : 
    1653              :         // Return value
    1654              :         Real64 WVDC;
    1655              : 
    1656            0 :         WVDC = (2.e-7 * std::pow(Temperature + Constant::Kelvin, 0.81)) / ambp;
    1657              : 
    1658            0 :         return WVDC;
    1659              :     }
    1660              : 
    1661              :     //                                 COPYRIGHT NOTICE
    1662              : 
    1663              :     //     Portions Copyright (c) University College London 2007.  All rights
    1664              :     //     reserved.
    1665              : 
    1666              :     //     UCL LEGAL NOTICE
    1667              :     //     Neither UCL, members of UCL nor any person or organisation acting on
    1668              :     //     behalf of either:
    1669              : 
    1670              :     //     A. Makes any warranty of representation, express or implied with
    1671              :     //        respect to the accuracy, completeness, or usefulness of the
    1672              :     //        information contained in this program, including any warranty of
    1673              :     //        merchantability or fitness of any purpose with respect to the
    1674              :     //        program, or that the use of any information disclosed in this
    1675              :     //        program may not infringe privately-owned rights, or
    1676              : 
    1677              :     //     B. Assumes any liability with respect to the use of, or for any and
    1678              :     //        all damages resulting from the use of the program or any portion
    1679              :     //        thereof or any information disclosed therein.
    1680              : 
    1681              : } // namespace HeatBalanceHAMTManager
    1682              : 
    1683              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1