LCOV - code coverage report
Current view: top level - EnergyPlus - MoistureBalanceEMPDManager.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 67.8 % 295 200
Test Date: 2025-05-22 16:09:37 Functions: 100.0 % 6 6

            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              : 
      55              : // EnergyPlus Headers
      56              : #include <EnergyPlus/Construction.hh>
      57              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      58              : #include <EnergyPlus/DataEnvironment.hh>
      59              : #include <EnergyPlus/DataHeatBalance.hh>
      60              : #include <EnergyPlus/DataIPShortCuts.hh>
      61              : #include <EnergyPlus/DataMoistureBalance.hh>
      62              : #include <EnergyPlus/DataMoistureBalanceEMPD.hh>
      63              : #include <EnergyPlus/DataSurfaces.hh>
      64              : #include <EnergyPlus/General.hh>
      65              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      66              : #include <EnergyPlus/Material.hh>
      67              : #include <EnergyPlus/MoistureBalanceEMPDManager.hh>
      68              : #include <EnergyPlus/OutputProcessor.hh>
      69              : #include <EnergyPlus/Psychrometrics.hh>
      70              : #include <EnergyPlus/UtilityRoutines.hh>
      71              : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      72              : 
      73              : namespace EnergyPlus::MoistureBalanceEMPDManager {
      74              : 
      75              : // Module containing the routines to calculate moisture adsorption and desorption
      76              : // at interior wall surfaces
      77              : 
      78              : // MODULE INFORMATION:
      79              : //   Authors:        Muthusamy Swami and Lixing Gu
      80              : //   Date written:   August, 1999
      81              : //   Modified:       na
      82              : //   Re-engineered:  Jason Woods and Noel Merket, August 2015
      83              : 
      84              : // PURPOSE OF THIS MODULE:
      85              : // To calculate moisture adsorption and desorption at interior wall surfaces
      86              : // using EMPD model (Effective Moisture Penetration Depth) developed by
      87              : // Florida Solar Energy Center. Input consists of interior surface temperatures
      88              : // and sorption curve of interior layer materials. Output consists of moisture
      89              : // fluxes from wall interior surfaces, which will be used in zone moisture balance.
      90              : 
      91              : // METHODOLOGY EMPLOYED:
      92              : // Add something
      93              : // EMPD is a simplified method of analyzing moisture transport in buildings and
      94              : // is easy to incorporate into existing building energy analysis computer codes.
      95              : // The components of the moisture balance equation involving moisture adsorption
      96              : // and desorption are described in detail where the concept of EMPD is discussed.
      97              : // The assumptions. parameters required, and limitations of the model are also discussed.
      98              : // Results of simulation using the model and comparison with measured data are given.
      99              : // Data of isotherms compiled from the literature of some commonly used building materials are also given.
     100              : 
     101              : // REFERENCES:
     102              : // Kerestecioglu A A., Swami M V., Kamel A A., "Theoretical and computational
     103              : // investigation of simultaneous heat and moisture transfer in buildings: 'Effective
     104              : // penetration depth' theory," ASHRAE Trans., 1990, Vol. 96, Part 1, 447-454
     105              : 
     106              : // Using/Aliasing
     107              : using namespace DataHeatBalance;
     108              : using namespace DataMoistureBalanceEMPD;
     109              : 
     110            2 : Real64 MaterialEMPD::calcDepthFromPeriod(EnergyPlusData &state,
     111              :                                          Real64 const period // in seconds
     112              : )
     113              : {
     114              :     // Assume T, RH, P
     115            2 :     Real64 constexpr T = 24.0; // C
     116            2 :     Real64 constexpr RH = 0.45;
     117            2 :     Real64 constexpr P_amb = 101325; // Pa
     118              : 
     119              :     // Calculate saturation vapor pressure at assumed temperature
     120            2 :     Real64 const PV_sat = Psychrometrics::PsyPsatFnTemp(state, T, "CalcDepthFromPeriod");
     121              : 
     122              :     // Calculate slope of moisture sorption curve
     123            2 :     Real64 const slope_MC = this->moistACoeff * this->moistBCoeff * std::pow(RH, this->moistBCoeff - 1) +
     124            2 :                             this->moistCCoeff * this->moistDCoeff * std::pow(RH, this->moistDCoeff - 1);
     125              : 
     126              :     // Equation for the diffusivity of water vapor in air
     127            2 :     Real64 const diffusivity_air = 2.0e-7 * std::pow(T + 273.15, 0.81) / P_amb;
     128              : 
     129              :     // Convert mu to diffusivity [kg/m^2-s-Pa]
     130            2 :     Real64 const EMPDdiffusivity = diffusivity_air / this->mu;
     131              : 
     132              :     // Calculate penetration depth
     133            2 :     return std::sqrt(EMPDdiffusivity * PV_sat * period / (this->Density * slope_MC * Constant::Pi));
     134              : }
     135              : 
     136            4 : void GetMoistureBalanceEMPDInput(EnergyPlusData &state)
     137              : {
     138              : 
     139              :     // SUBROUTINE INFORMATION:
     140              :     //       AUTHOR         Muthusamy V. Swami and Lixing Gu
     141              :     //       DATE WRITTEN   August 2000
     142              :     //       MODIFIED       na
     143              :     //       RE-ENGINEERED  na
     144              : 
     145              :     // PURPOSE OF THIS SUBROUTINE:
     146              :     // This subroutine is the main driver for initializations within the
     147              :     // heat balance using the EMPD model.
     148              : 
     149              :     static constexpr std::string_view routineName = "GetMoistureBalanceEMPDInput";
     150              : 
     151              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     152              :     int IOStat;                       // IO Status when calling get input subroutine
     153            4 :     Array1D_string MaterialNames(3);  // Number of Material Alpha names defined
     154              :     int MaterialNumAlpha;             // Number of material alpha names being passed
     155              :     int MaterialNumProp;              // Number of material properties being passed
     156            4 :     Array1D<Real64> MaterialProps(9); // Temporary array to transfer material properties
     157            4 :     bool ErrorsFound(false);          // If errors detected in input
     158              : 
     159              :     int EMPDMat;           // EMPD Moisture Material additional properties for each base material
     160            4 :     Array1D_bool EMPDzone; // EMPD property check for each zone
     161              : 
     162            4 :     auto &s_ip = state.dataInputProcessing->inputProcessor;
     163            4 :     auto &s_ipsc = state.dataIPShortCut;
     164            4 :     auto &s_mat = state.dataMaterial;
     165              : 
     166              :     // Load the additional EMPD Material properties
     167            4 :     s_ipsc->cCurrentModuleObject = "MaterialProperty:MoisturePenetrationDepth:Settings";
     168            4 :     EMPDMat = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     169              : 
     170            4 :     if (EMPDMat == 0) {
     171            0 :         ShowSevereError(state, format("EMPD Solution requested, but no \"{}\" objects were found.", s_ipsc->cCurrentModuleObject));
     172            0 :         ErrorsFound = true;
     173              :     }
     174              : 
     175            8 :     for (int Loop = 1; Loop <= EMPDMat; ++Loop) {
     176              : 
     177              :         // Call Input Get routine to retrieve material data
     178           12 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     179            4 :                                                                  s_ipsc->cCurrentModuleObject,
     180              :                                                                  Loop,
     181              :                                                                  MaterialNames,
     182              :                                                                  MaterialNumAlpha,
     183              :                                                                  MaterialProps,
     184              :                                                                  MaterialNumProp,
     185              :                                                                  IOStat,
     186            4 :                                                                  s_ipsc->lNumericFieldBlanks,
     187            4 :                                                                  s_ipsc->lAlphaFieldBlanks,
     188            4 :                                                                  s_ipsc->cAlphaFieldNames,
     189            4 :                                                                  s_ipsc->cNumericFieldNames);
     190              : 
     191            4 :         ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, MaterialNames(1)};
     192              : 
     193              :         // Load the material derived type from the input data.
     194            4 :         int matNum = Material::GetMaterialNum(state, MaterialNames(1));
     195            4 :         if (matNum == 0) {
     196            0 :             ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(1), MaterialNames(1));
     197            0 :             ErrorsFound = true;
     198            0 :             continue;
     199              :         }
     200              : 
     201            4 :         auto *mat = s_mat->materials(matNum);
     202            4 :         if (mat->group != Material::Group::Regular || mat->ROnly) {
     203            0 :             ShowSevereCustom(state, eoh, "Reference Material is not appropriate type for EMPD properties, must have regular properties (L,Cp,K,D)");
     204            0 :             ErrorsFound = true;
     205            0 :             continue;
     206              :         }
     207              : 
     208              :         // This is a regular material and we need to replace/upgrade it with an opaque material (subclass)
     209            4 :         auto *matEMPD = new MaterialEMPD;
     210            4 :         matEMPD->MaterialBase::operator=(*mat); // deep copy parent object (explicitly call operator=)
     211              : 
     212            4 :         delete mat;
     213            4 :         s_mat->materials(matNum) = matEMPD; // This should work, material name remains the same
     214              : 
     215            4 :         matEMPD->hasEMPD = true;
     216              : 
     217              :         // Once the material derived type number is found then load the additional moisture material properties
     218            4 :         matEMPD->mu = MaterialProps(1);
     219            4 :         matEMPD->moistACoeff = MaterialProps(2);
     220            4 :         matEMPD->moistBCoeff = MaterialProps(3);
     221            4 :         matEMPD->moistCCoeff = MaterialProps(4);
     222            4 :         matEMPD->moistDCoeff = MaterialProps(5);
     223            4 :         if (s_ipsc->lNumericFieldBlanks(6) || MaterialProps(6) == Constant::AutoCalculate) {
     224            1 :             matEMPD->surfaceDepth = matEMPD->calcDepthFromPeriod(state, 24 * 3600); // 1 day
     225              :         } else {
     226            3 :             matEMPD->surfaceDepth = MaterialProps(6);
     227              :         }
     228            4 :         if (s_ipsc->lNumericFieldBlanks(7) || MaterialProps(7) == Constant::AutoCalculate) {
     229            1 :             matEMPD->deepDepth = matEMPD->calcDepthFromPeriod(state, 21 * 24 * 3600); // 3 weeks
     230              :         } else {
     231            3 :             matEMPD->deepDepth = MaterialProps(7);
     232              :         }
     233            4 :         matEMPD->coatingThickness = MaterialProps(8);
     234            4 :         matEMPD->muCoating = MaterialProps(9);
     235              : 
     236            4 :         if (matEMPD->deepDepth <= matEMPD->surfaceDepth && matEMPD->deepDepth != 0.0) {
     237            0 :             ShowWarningError(state, format("{}: material=\"{}\"", s_ipsc->cCurrentModuleObject, matEMPD->Name));
     238            0 :             ShowContinueError(state, "Deep-layer penetration depth should be zero or greater than the surface-layer penetration depth.");
     239              :         }
     240              :     }
     241              : 
     242              :     // Ensure at least one interior EMPD surface for each zone
     243            4 :     EMPDzone.dimension(state.dataGlobal->NumOfZones, false);
     244            7 :     for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     245            3 :         auto const &surf = state.dataSurface->Surface(SurfNum);
     246            3 :         if (!surf.HeatTransSurf || surf.Class == DataSurfaces::SurfaceClass::Window) continue; // Heat transfer surface only and not a window
     247            3 :         if (surf.HeatTransferAlgorithm != DataSurfaces::HeatTransferModel::EMPD) continue;
     248              : 
     249            0 :         auto const &constr = state.dataConstruction->Construct(surf.Construction);
     250            0 :         auto const *mat = dynamic_cast<const MaterialEMPD *>(s_mat->materials(constr.LayerPoint(constr.TotLayers)));
     251              :         // assert(mat != nullptr);
     252              : 
     253            0 :         if (mat && mat->mu > 0.0 && surf.Zone > 0) {
     254            0 :             EMPDzone(surf.Zone) = true;
     255              :         } else {
     256            0 :             ++state.dataMoistureBalEMPD->ErrCount;
     257            0 :             if (state.dataMoistureBalEMPD->ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
     258            0 :                 ShowMessage(state, "GetMoistureBalanceEMPDInput: EMPD properties are not assigned to the inside layer of Surfaces");
     259            0 :                 ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
     260              :             }
     261            0 :             if (state.dataGlobal->DisplayExtraWarnings) {
     262            0 :                 ShowMessage(state,
     263            0 :                             format("GetMoistureBalanceEMPDInput: EMPD properties are not assigned to the inside layer in Surface={}", surf.Name));
     264            0 :                 ShowContinueError(state, format("with Construction={}", constr.Name));
     265              :             }
     266              :         }
     267              : 
     268            0 :         if (constr.TotLayers == 1) continue; // One layer construction
     269              : 
     270              :         // Multiple layer construction
     271            0 :         auto const *mat1 = s_mat->materials(constr.LayerPoint(1));
     272            0 :         if (mat1->hasEMPD && surf.ExtBoundCond <= 0) { // The external layer is not exposed to zone
     273            0 :             ShowSevereError(state, format("{}: EMPD properties are assigned to the outside layer in Construction = {}", routineName, constr.Name));
     274            0 :             ShowContinueError(state, format("..Outside layer material with EMPD properties = {}", mat1->Name));
     275            0 :             ShowContinueError(state, "..A material with EMPD properties must be assigned to the inside layer of a construction.");
     276            0 :             ErrorsFound = true;
     277            0 :             continue;
     278              :         }
     279              : 
     280            0 :         for (int Layer = 2; Layer <= constr.TotLayers - 1; ++Layer) {
     281            0 :             auto const *matL = s_mat->materials(constr.LayerPoint(Layer));
     282            0 :             if (matL->hasEMPD) {
     283            0 :                 ShowSevereError(state, format("{}: EMPD properties are assigned to a middle layer in Construction = {}", routineName, constr.Name));
     284            0 :                 ShowContinueError(state, format("..Middle layer material with EMPD properties = {}", matL->Name));
     285            0 :                 ShowContinueError(state, "..A material with EMPD properties must be assigned to the inside layer of a construction.");
     286            0 :                 ErrorsFound = true;
     287              :             }
     288              :         }
     289              :     }
     290              : 
     291            4 :     for (int Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) {
     292            0 :         if (!EMPDzone(Loop)) {
     293            0 :             ShowSevereError(state,
     294            0 :                             format("{}: None of the constructions for zone = {} has an inside layer with EMPD properties",
     295              :                                    routineName,
     296            0 :                                    state.dataHeatBal->Zone(Loop).Name));
     297            0 :             ShowContinueError(state, "..For each zone, the inside layer of at least one construction must have EMPD properties");
     298            0 :             ErrorsFound = true;
     299              :         }
     300              :     }
     301              : 
     302            4 :     EMPDzone.deallocate();
     303              : 
     304            4 :     ReportMoistureBalanceEMPD(state);
     305              : 
     306            4 :     if (ErrorsFound) {
     307            0 :         ShowFatalError(state, "GetMoistureBalanceEMPDInput: Errors found getting EMPD material properties, program terminated.");
     308              :     }
     309            4 : }
     310              : 
     311            3 : void InitMoistureBalanceEMPD(EnergyPlusData &state)
     312              : {
     313              : 
     314              :     // SUBROUTINE INFORMATION:
     315              :     //   Authors:        Muthusamy Swami and Lixing Gu
     316              :     //   Date written:   August, 1999
     317              :     //   Modified:       na
     318              :     //   Re-engineered:  na
     319              : 
     320              :     // PURPOSE OF THIS SUBROUTINE:
     321              :     // Create dynamic array for surface moisture calculation
     322              : 
     323              :     // USE STATEMENTS:
     324              :     using Psychrometrics::PsyRhovFnTdbRh;
     325              :     using Psychrometrics::PsyRhovFnTdbWPb_fast;
     326              : 
     327            3 :     if (state.dataMoistureBalEMPD->InitEnvrnFlag) {
     328            3 :         state.dataMstBalEMPD->RVSurfaceOld.allocate(state.dataSurface->TotSurfaces);
     329            3 :         state.dataMstBalEMPD->RVSurface.allocate(state.dataSurface->TotSurfaces);
     330            3 :         state.dataMstBalEMPD->HeatFluxLatent.allocate(state.dataSurface->TotSurfaces);
     331            3 :         state.dataMoistureBalEMPD->EMPDReportVars.allocate(state.dataSurface->TotSurfaces);
     332            3 :         state.dataMstBalEMPD->RVSurfLayer.allocate(state.dataSurface->TotSurfaces);
     333            3 :         state.dataMstBalEMPD->RVSurfLayerOld.allocate(state.dataSurface->TotSurfaces);
     334            3 :         state.dataMstBalEMPD->RVDeepLayer.allocate(state.dataSurface->TotSurfaces);
     335            3 :         state.dataMstBalEMPD->RVdeepOld.allocate(state.dataSurface->TotSurfaces);
     336            3 :         state.dataMstBalEMPD->RVwall.allocate(state.dataSurface->TotSurfaces);
     337              :     }
     338              : 
     339            6 :     for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     340            3 :         int ZoneNum = state.dataSurface->Surface(SurfNum).Zone;
     341            3 :         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
     342              :         Real64 const rv_air_in_initval =
     343            3 :             min(PsyRhovFnTdbWPb_fast(state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT,
     344            3 :                                      max(state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).airHumRat, 1.0e-5),
     345            3 :                                      state.dataEnvrn->OutBaroPress),
     346            3 :                 PsyRhovFnTdbRh(state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT, 1.0, "InitMoistureBalanceEMPD"));
     347            3 :         state.dataMstBalEMPD->RVSurfaceOld(SurfNum) = rv_air_in_initval;
     348            3 :         state.dataMstBalEMPD->RVSurface(SurfNum) = rv_air_in_initval;
     349            3 :         state.dataMstBalEMPD->RVSurfLayer(SurfNum) = rv_air_in_initval;
     350            3 :         state.dataMstBalEMPD->RVSurfLayerOld(SurfNum) = rv_air_in_initval;
     351            3 :         state.dataMstBalEMPD->RVDeepLayer(SurfNum) = rv_air_in_initval;
     352            3 :         state.dataMstBalEMPD->RVdeepOld(SurfNum) = rv_air_in_initval;
     353            3 :         state.dataMstBalEMPD->RVwall(SurfNum) = rv_air_in_initval;
     354              :     }
     355            3 :     if (!state.dataMoistureBalEMPD->InitEnvrnFlag) return;
     356              :     // Initialize the report variable
     357              : 
     358            3 :     GetMoistureBalanceEMPDInput(state);
     359              : 
     360            6 :     for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     361            3 :         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
     362            3 :         if (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) continue;
     363            3 :         EMPDReportVarsData &rvd = state.dataMoistureBalEMPD->EMPDReportVars(SurfNum);
     364            3 :         const std::string surf_name = state.dataSurface->Surface(SurfNum).Name;
     365            6 :         SetupOutputVariable(state,
     366              :                             "EMPD Surface Inside Face Water Vapor Density",
     367              :                             Constant::Units::kg_m3,
     368            3 :                             rvd.rv_surface,
     369              :                             OutputProcessor::TimeStepType::Zone,
     370              :                             OutputProcessor::StoreType::Average,
     371              :                             surf_name);
     372            6 :         SetupOutputVariable(state,
     373              :                             "EMPD Surface Layer Moisture Content",
     374              :                             Constant::Units::kg_m3,
     375            3 :                             rvd.u_surface_layer,
     376              :                             OutputProcessor::TimeStepType::Zone,
     377              :                             OutputProcessor::StoreType::Average,
     378              :                             surf_name);
     379            6 :         SetupOutputVariable(state,
     380              :                             "EMPD Deep Layer Moisture Content",
     381              :                             Constant::Units::kg_m3,
     382            3 :                             rvd.u_deep_layer,
     383              :                             OutputProcessor::TimeStepType::Zone,
     384              :                             OutputProcessor::StoreType::Average,
     385              :                             surf_name);
     386            6 :         SetupOutputVariable(state,
     387              :                             "EMPD Surface Layer Equivalent Relative Humidity",
     388              :                             Constant::Units::Perc,
     389            3 :                             rvd.RH_surface_layer,
     390              :                             OutputProcessor::TimeStepType::Zone,
     391              :                             OutputProcessor::StoreType::Average,
     392              :                             surf_name);
     393            6 :         SetupOutputVariable(state,
     394              :                             "EMPD Deep Layer Equivalent Relative Humidity",
     395              :                             Constant::Units::Perc,
     396            3 :                             rvd.RH_deep_layer,
     397              :                             OutputProcessor::TimeStepType::Zone,
     398              :                             OutputProcessor::StoreType::Average,
     399              :                             surf_name);
     400            6 :         SetupOutputVariable(state,
     401              :                             "EMPD Surface Layer Equivalent Humidity Ratio",
     402              :                             Constant::Units::kgWater_kgDryAir,
     403            3 :                             rvd.w_surface_layer,
     404              :                             OutputProcessor::TimeStepType::Zone,
     405              :                             OutputProcessor::StoreType::Average,
     406              :                             surf_name);
     407            6 :         SetupOutputVariable(state,
     408              :                             "EMPD Deep Layer Equivalent Humidity Ratio",
     409              :                             Constant::Units::kgWater_kgDryAir,
     410            3 :                             rvd.w_deep_layer,
     411              :                             OutputProcessor::TimeStepType::Zone,
     412              :                             OutputProcessor::StoreType::Average,
     413              :                             surf_name);
     414            6 :         SetupOutputVariable(state,
     415              :                             "EMPD Surface Moisture Flux to Zone",
     416              :                             Constant::Units::kg_m2s,
     417            3 :                             rvd.mass_flux_zone,
     418              :                             OutputProcessor::TimeStepType::Zone,
     419              :                             OutputProcessor::StoreType::Average,
     420              :                             surf_name);
     421            6 :         SetupOutputVariable(state,
     422              :                             "EMPD Deep Layer Moisture Flux",
     423              :                             Constant::Units::kg_m2s,
     424            3 :                             rvd.mass_flux_deep,
     425              :                             OutputProcessor::TimeStepType::Zone,
     426              :                             OutputProcessor::StoreType::Average,
     427              :                             surf_name);
     428            3 :     }
     429              : 
     430            3 :     if (state.dataMoistureBalEMPD->InitEnvrnFlag) state.dataMoistureBalEMPD->InitEnvrnFlag = false;
     431              : }
     432              : 
     433            3 : void CalcMoistureBalanceEMPD(EnergyPlusData &state,
     434              :                              int const SurfNum,
     435              :                              Real64 const SurfTempIn, // INSIDE SURFACE TEMPERATURE at current time step
     436              :                              Real64 const TempZone,   // Zone temperature at current time step.
     437              :                              Real64 &TempSat          // Saturated surface temperature.
     438              : )
     439              : {
     440              : 
     441              :     // SUBROUTINE INFORMATION:
     442              :     //   Authors:        Muthusamy Swami and Lixing Gu
     443              :     //   Date written:   August, 1999
     444              :     //   Modified:       na
     445              :     //   Re-engineered:  na
     446              : 
     447              :     // PURPOSE OF THIS SUBROUTINE:
     448              :     // Calculate surface moisture level using EMPD model
     449              : 
     450              :     // Using/Aliasing
     451              :     using DataMoistureBalanceEMPD::Lam;
     452              :     using Psychrometrics::PsyCpAirFnW;
     453              :     using Psychrometrics::PsyPsatFnTemp;
     454              :     using Psychrometrics::PsyRhFnTdbRhov;
     455              :     using Psychrometrics::PsyRhFnTdbRhovLBnd0C;
     456              :     using Psychrometrics::PsyRhFnTdbWPb;
     457              :     using Psychrometrics::PsyRhoAirFnPbTdbW;
     458              :     using Psychrometrics::PsyRhovFnTdbRh;
     459              :     using Psychrometrics::PsyRhovFnTdbWPb;
     460              :     using Psychrometrics::PsyRhovFnTdbWPb_fast;
     461              :     using Psychrometrics::PsyWFnTdbRhPb;
     462              : 
     463              :     static constexpr std::string_view routineName = "CalcMoistureEMPD";
     464              : 
     465              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     466              :     Real64 hm_deep_layer; // Overall deep-layer transfer coefficient
     467              :     Real64 RSurfaceLayer; // Mass transfer resistance between actual surface and surface layer node
     468              :     Real64 Taver;         // Average zone temperature between current time and previous time
     469              :     //    REAL(r64)    :: Waver     ! Average zone humidity ratio between current time and previous time
     470              :     Real64 RHaver; // Average zone relative humidity {0-1} between current time and previous time
     471              :     Real64 RVaver; // Average zone vapor density
     472              :     Real64 dU_dRH;
     473              :     Real64 PVsurf;        // Surface vapor pressure
     474              :     Real64 PV_surf_layer; // Vapor pressure of surface layer
     475              :     Real64 PV_deep_layer;
     476              :     Real64 PVsat; // saturation vapor pressure at the surface
     477              :     Real64 RH_surf_layer_old;
     478              :     Real64 RH_deep_layer_old;
     479              :     Real64 EMPDdiffusivity;
     480              :     Real64 Rcoating;
     481              :     Real64 RH_surf_layer;
     482              :     Real64 RH_surf_layer_tmp;
     483              :     Real64 RH_deep_layer;
     484              : 
     485            3 :     auto &s_mat = state.dataMaterial;
     486              : 
     487            3 :     if (state.dataGlobal->BeginEnvrnFlag && state.dataMoistureBalEMPD->OneTimeFlag) {
     488            0 :         InitMoistureBalanceEMPD(state);
     489            0 :         state.dataMoistureBalEMPD->OneTimeFlag = false;
     490              :     }
     491              : 
     492            3 :     if (!state.dataGlobal->BeginEnvrnFlag) {
     493            3 :         state.dataMoistureBalEMPD->OneTimeFlag = true;
     494              :     }
     495              : 
     496            3 :     auto const &surface(state.dataSurface->Surface(SurfNum));                // input
     497            3 :     auto &rv_surface(state.dataMstBalEMPD->RVSurface(SurfNum));              // output
     498            3 :     auto const &rv_surface_old(state.dataMstBalEMPD->RVSurfaceOld(SurfNum)); // input
     499            3 :     auto const &h_mass_conv_in_fd(state.dataMstBal->HMassConvInFD(SurfNum)); // input
     500            3 :     auto const &rho_vapor_air_in(state.dataMstBal->RhoVaporAirIn(SurfNum));  // input
     501              :     Real64 RHZone;
     502              :     Real64 mass_flux_surf_deep;
     503              :     Real64 mass_flux_surf_deep_max;
     504              :     Real64 mass_flux_zone_surf;
     505              :     Real64 mass_flux_zone_surf_max;
     506              :     Real64 mass_flux_surf_layer;
     507              :     Real64 mass_flux_deep_layer;
     508              :     Real64 mass_flux_zone;
     509            3 :     auto &rv_surf_layer(state.dataMstBalEMPD->RVSurfLayer(SurfNum));              // output
     510            3 :     auto const &rv_surf_layer_old(state.dataMstBalEMPD->RVSurfLayerOld(SurfNum)); // input
     511              :     Real64 hm_surf_layer;
     512            3 :     auto &rv_deep_layer(state.dataMstBalEMPD->RVDeepLayer(SurfNum));       // output
     513            3 :     auto const &rv_deep_old(state.dataMstBalEMPD->RVdeepOld(SurfNum));     // input
     514            3 :     auto &heat_flux_latent(state.dataMstBalEMPD->HeatFluxLatent(SurfNum)); // output
     515              : 
     516            3 :     heat_flux_latent = 0.0;
     517            3 :     if (!surface.HeatTransSurf) {
     518            0 :         return;
     519              :     }
     520              : 
     521            3 :     auto const &constr = state.dataConstruction->Construct(surface.Construction);
     522            3 :     auto const *mat = dynamic_cast<MaterialEMPD const *>(s_mat->materials(constr.LayerPoint(constr.TotLayers)));
     523            3 :     assert(mat != nullptr);
     524            3 :     if (mat->mu <= 0.0) {
     525            0 :         rv_surface =
     526            0 :             PsyRhovFnTdbWPb(TempZone, state.dataZoneTempPredictorCorrector->zoneHeatBalance(surface.Zone).airHumRat, state.dataEnvrn->OutBaroPress);
     527            0 :         return;
     528              :     }
     529              : 
     530            3 :     Taver = SurfTempIn;
     531              :     // Calculate average vapor density [kg/m^3], and RH for use in material property calculations.
     532            3 :     RVaver = rv_surface_old;
     533            3 :     RHaver = RVaver * 461.52 * (Taver + Constant::Kelvin) * std::exp(-23.7093 + 4111.0 / (Taver + 237.7));
     534              : 
     535              :     // Calculate the saturated vapor pressure, surface vapor pressure and dewpoint. Used to check for condensation in HeatBalanceSurfaceManager
     536            3 :     PVsat = PsyPsatFnTemp(state, Taver, routineName);
     537            3 :     PVsurf = RHaver * std::exp(23.7093 - 4111.0 / (Taver + 237.7));
     538            3 :     TempSat = 4111.0 / (23.7093 - std::log(PVsurf)) + 35.45 - Constant::Kelvin;
     539              : 
     540              :     // Convert vapor resistance factor (user input) to diffusivity. Evaluate at local surface temperature.
     541              :     // 2e-7*T^0.81/P = vapor diffusivity in air. [kg/m-s-Pa]
     542              :     // 461.52 = universal gas constant for water [J/kg-K]
     543              :     // EMPDdiffusivity = [m^2/s]
     544            3 :     EMPDdiffusivity = (2.0e-7 * pow(Taver + Constant::Kelvin, 0.81) / state.dataEnvrn->OutBaroPress) / mat->mu * 461.52 * (Taver + Constant::Kelvin);
     545              : 
     546              :     // Calculate slope of moisture sorption curve at current RH. [kg/kg-RH]
     547            3 :     dU_dRH = mat->moistACoeff * mat->moistBCoeff * pow(RHaver, mat->moistBCoeff - 1) +
     548            3 :              mat->moistCCoeff * mat->moistDCoeff * pow(RHaver, mat->moistDCoeff - 1);
     549              : 
     550              :     // Convert vapor density and temperature of zone air to RH
     551            3 :     RHZone = rho_vapor_air_in * 461.52 * (TempZone + Constant::Kelvin) * std::exp(-23.7093 + 4111.0 / ((TempZone + Constant::Kelvin) - 35.45));
     552              : 
     553              :     // Convert stored vapor density from previous timestep to RH.
     554            3 :     RH_deep_layer_old = PsyRhFnTdbRhov(state, Taver, rv_deep_old);
     555            3 :     RH_surf_layer_old = PsyRhFnTdbRhov(state, Taver, rv_surf_layer_old);
     556              : 
     557              :     // If coating vapor resistance factor equals 0, coating resistance is zero (avoid divide by zero).
     558              :     // Otherwise, calculate coating resistance with coating vapor resistance factor and thickness. [s/m]
     559            3 :     if (mat->muCoating <= 0.0) {
     560            1 :         Rcoating = 0;
     561              :     } else {
     562            2 :         Rcoating = mat->coatingThickness * mat->muCoating * state.dataEnvrn->OutBaroPress /
     563            2 :                    (2.0e-7 * pow(Taver + Constant::Kelvin, 0.81) * 461.52 * (Taver + Constant::Kelvin));
     564              :     }
     565              : 
     566              :     // Calculate mass-transfer coefficient between zone air and center of surface layer. [m/s]
     567            3 :     hm_surf_layer = 1.0 / (0.5 * mat->surfaceDepth / EMPDdiffusivity + 1.0 / h_mass_conv_in_fd + Rcoating);
     568              :     // Calculate mass-transfer coefficient between center of surface layer and center of deep layer. [m/s]
     569              :     // If deep layer depth = 0, set mass-transfer coefficient to zero (simulates with no deep layer).
     570            3 :     if (mat->deepDepth <= 0.0) {
     571            0 :         hm_deep_layer = 0;
     572              :     } else {
     573            3 :         hm_deep_layer = 2.0 * EMPDdiffusivity / (mat->deepDepth + mat->surfaceDepth);
     574              :     }
     575              :     // Calculate resistance between surface-layer/air interface and center of surface layer. [s/m]
     576              :     // This is the physical surface of the material.
     577            3 :     RSurfaceLayer = 1.0 / hm_surf_layer - 1.0 / h_mass_conv_in_fd;
     578              : 
     579              :     // Calculate vapor flux leaving surface layer, entering deep layer, and entering zone.
     580            3 :     mass_flux_surf_deep_max =
     581            3 :         mat->deepDepth * mat->Density * dU_dRH * (RH_surf_layer_old - RH_deep_layer_old) / (state.dataGlobal->TimeStepZone * 3600.0);
     582            3 :     mass_flux_surf_deep = hm_deep_layer * (rv_surf_layer_old - rv_deep_old);
     583            3 :     if (std::abs(mass_flux_surf_deep_max) < std::abs(mass_flux_surf_deep)) {
     584            0 :         mass_flux_surf_deep = mass_flux_surf_deep_max;
     585              :     }
     586              : 
     587            3 :     mass_flux_zone_surf_max = mat->surfaceDepth * mat->Density * dU_dRH * (RHZone - RH_surf_layer_old) / (state.dataGlobal->TimeStepZone * 3600.0);
     588            3 :     mass_flux_zone_surf = hm_surf_layer * (rho_vapor_air_in - rv_surf_layer_old);
     589            3 :     if (std::abs(mass_flux_zone_surf_max) < std::abs(mass_flux_zone_surf)) {
     590            0 :         mass_flux_zone_surf = mass_flux_zone_surf_max;
     591              :     }
     592              : 
     593              :     // mass_flux_surf_layer = -mass_flux_zone_surf + mass_flux_surf_deep;
     594              :     // mass_flux_deep_layer = mass_flux_surf_deep;
     595              :     // mass_flux_zone = -mass_flux_zone_surf;
     596              : 
     597            3 :     mass_flux_surf_layer = hm_surf_layer * (rv_surf_layer_old - rho_vapor_air_in) + hm_deep_layer * (rv_surf_layer_old - rv_deep_old);
     598            3 :     mass_flux_deep_layer = hm_deep_layer * (rv_surf_layer_old - rv_deep_old);
     599            3 :     mass_flux_zone = hm_surf_layer * (rv_surf_layer_old - rho_vapor_air_in);
     600              : 
     601              :     // Calculate new surface layer RH using mass balance on surface layer
     602            3 :     RH_surf_layer_tmp =
     603            3 :         RH_surf_layer_old + state.dataGlobal->TimeStepZone * 3600.0 * (-mass_flux_surf_layer / (mat->Density * mat->surfaceDepth * dU_dRH));
     604              : 
     605              :     //    RH_surf_layer = RH_surf_layer_tmp;
     606              : 
     607            3 :     if (RH_surf_layer_old < RH_deep_layer_old && RH_surf_layer_old < RHZone) {
     608            0 :         if (RHZone > RH_deep_layer_old) {
     609            0 :             if (RH_surf_layer_tmp > RHZone) {
     610            0 :                 RH_surf_layer = RHZone;
     611              :             } else {
     612            0 :                 RH_surf_layer = RH_surf_layer_tmp;
     613              :             }
     614            0 :         } else if (RH_surf_layer_tmp > RH_deep_layer_old) {
     615            0 :             RH_surf_layer = RH_deep_layer_old;
     616              :         } else {
     617            0 :             RH_surf_layer = RH_surf_layer_tmp;
     618              :         }
     619              : 
     620            3 :     } else if (RH_surf_layer_old < RH_deep_layer_old && RH_surf_layer_old > RHZone) {
     621            0 :         if (RH_surf_layer_tmp > RH_deep_layer_old) {
     622            0 :             RH_surf_layer = RH_deep_layer_old;
     623            0 :         } else if (RH_surf_layer_tmp < RHZone) {
     624            0 :             RH_surf_layer = RHZone;
     625              :         } else {
     626            0 :             RH_surf_layer = RH_surf_layer_tmp;
     627              :         }
     628            3 :     } else if (RH_surf_layer_old > RH_deep_layer_old && RH_surf_layer_old < RHZone) {
     629            3 :         if (RH_surf_layer_tmp > RHZone) {
     630            0 :             RH_surf_layer = RHZone;
     631            3 :         } else if (RH_surf_layer_tmp < RH_deep_layer_old) {
     632            0 :             RH_surf_layer = RH_deep_layer_old;
     633              :         } else
     634            3 :             RH_surf_layer = RH_surf_layer_tmp;
     635            0 :     } else if (RHZone < RH_deep_layer_old) {
     636            0 :         if (RH_surf_layer_tmp < RHZone) {
     637            0 :             RH_surf_layer = RHZone;
     638              :         } else {
     639            0 :             RH_surf_layer = RH_surf_layer_tmp;
     640              :         }
     641            0 :     } else if (RH_surf_layer_tmp < RH_deep_layer_old) {
     642            0 :         RH_surf_layer = RH_deep_layer_old;
     643              :     } else {
     644            0 :         RH_surf_layer = RH_surf_layer_tmp;
     645              :     }
     646              : 
     647              :     // Calculate new deep layer RH using mass balance on deep layer (unless depth <= 0).
     648            3 :     if (mat->deepDepth <= 0.0) {
     649            0 :         RH_deep_layer = RH_deep_layer_old;
     650              :     } else {
     651            3 :         RH_deep_layer = RH_deep_layer_old + state.dataGlobal->TimeStepZone * 3600.0 * mass_flux_deep_layer / (mat->Density * mat->deepDepth * dU_dRH);
     652              :     }
     653              :     // Convert calculated RH back to vapor density of surface and deep layers.
     654            3 :     rv_surf_layer = PsyRhovFnTdbRh(state, Taver, RH_surf_layer);
     655            3 :     rv_deep_layer = PsyRhovFnTdbRh(state, Taver, RH_deep_layer);
     656              : 
     657              :     // Calculate surface-layer and deep-layer vapor pressures [Pa]
     658            3 :     PV_surf_layer = RH_surf_layer * std::exp(23.7093 - 4111.0 / (Taver + 237.7));
     659            3 :     PV_deep_layer = RH_deep_layer * std::exp(23.7093 - 4111.0 / (Taver + 237.7));
     660              : 
     661              :     // Calculate vapor density at physical material surface (surface-layer/air interface). This is used to calculate total moisture flow terms for
     662              :     // each zone in HeatBalanceSurfaceManager
     663            3 :     rv_surface = rv_surf_layer - mass_flux_zone * RSurfaceLayer;
     664              : 
     665              :     // Calculate heat flux from latent-sensible conversion due to moisture adsorption [W/m^2]
     666            3 :     heat_flux_latent = mass_flux_zone * Lam;
     667              : 
     668              :     // Put results in the reporting variables
     669              :     // Will add RH and W of deep layer as outputs
     670              :     // Need to also add moisture content (kg/kg) of surface and deep layers, and moisture flow from each surface (kg/s), per Rongpeng's suggestion
     671            3 :     EMPDReportVarsData &rvd = state.dataMoistureBalEMPD->EMPDReportVars(SurfNum);
     672            3 :     rvd.rv_surface = rv_surface;
     673            3 :     rvd.RH_surface_layer = RH_surf_layer * 100.0;
     674            3 :     rvd.RH_deep_layer = RH_deep_layer * 100.0;
     675            3 :     rvd.w_surface_layer = 0.622 * PV_surf_layer / (state.dataEnvrn->OutBaroPress - PV_surf_layer);
     676            3 :     rvd.w_deep_layer = 0.622 * PV_deep_layer / (state.dataEnvrn->OutBaroPress - PV_deep_layer);
     677            3 :     rvd.mass_flux_zone = mass_flux_zone;
     678            3 :     rvd.mass_flux_deep = mass_flux_deep_layer;
     679            3 :     rvd.u_surface_layer = mat->moistACoeff * pow(RH_surf_layer, mat->moistBCoeff) + mat->moistCCoeff * pow(RH_surf_layer, mat->moistDCoeff);
     680            3 :     rvd.u_deep_layer = mat->moistACoeff * pow(RH_deep_layer, mat->moistBCoeff) + mat->moistCCoeff * pow(RH_deep_layer, mat->moistDCoeff);
     681              : }
     682              : 
     683            3 : void UpdateMoistureBalanceEMPD(EnergyPlusData &state, int const SurfNum) // Surface number
     684              : {
     685              : 
     686              :     // SUBROUTINE INFORMATION:
     687              :     //   Authors:        Muthusamy Swami and Lixing Gu
     688              :     //   Date writtenn:  August, 1999
     689              :     //   Modified:       na
     690              :     //   Re-engineered:  na
     691              : 
     692              :     // PURPOSE OF THIS SUBROUTINE:
     693              :     // Update inside surface vapor density
     694              : 
     695            3 :     state.dataMstBalEMPD->RVSurfaceOld(SurfNum) = state.dataMstBalEMPD->RVSurface(SurfNum);
     696            3 :     state.dataMstBalEMPD->RVdeepOld(SurfNum) = state.dataMstBalEMPD->RVDeepLayer(SurfNum);
     697            3 :     state.dataMstBalEMPD->RVSurfLayerOld(SurfNum) = state.dataMstBalEMPD->RVSurfLayer(SurfNum);
     698            3 : }
     699              : 
     700            4 : void ReportMoistureBalanceEMPD(EnergyPlusData &state)
     701              : {
     702              : 
     703              :     // SUBROUTINE INFORMATION:
     704              :     //       AUTHOR         Lixing Gu
     705              :     //       DATE WRITTEN   August 2005
     706              :     //       MODIFIED       na
     707              :     //       RE-ENGINEERED  na
     708              : 
     709              :     // PURPOSE OF THIS SUBROUTINE:
     710              :     // This routine gives a detailed report to the user about
     711              :     // EMPD Properties of each construction.
     712              : 
     713              :     // Using/Aliasing
     714              :     using General::ScanForReports;
     715              : 
     716              :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     717              :     bool DoReport;
     718              : 
     719            4 :     auto &s_mat = state.dataMaterial;
     720              : 
     721           12 :     ScanForReports(state, "Constructions", DoReport, "Constructions");
     722              : 
     723            4 :     if (!DoReport) return;
     724              :     //   Write Descriptions
     725            0 :     print(state.files.eio,
     726              :           "{}",
     727              :           "! <Construction EMPD>, Construction Name, Inside Layer Material Name, Vapor Resistance Factor, a, b, "
     728              :           "c, d, Surface Penetration Depth {m}, Deep Penetration Depth {m}, Coating Vapor Resistance Factor, "
     729              :           "Coating Thickness {m}\n");
     730              : 
     731            0 :     for (int ConstrNum = 1; ConstrNum <= state.dataHeatBal->TotConstructs; ++ConstrNum) {
     732            0 :         auto const &constr = state.dataConstruction->Construct(ConstrNum);
     733            0 :         if (constr.TypeIsWindow) continue;
     734              : 
     735            0 :         auto const *mat = s_mat->materials(constr.LayerPoint(constr.TotLayers));
     736            0 :         if (!mat->hasEMPD) continue;
     737              : 
     738            0 :         auto const *matEMPD = dynamic_cast<MaterialEMPD const *>(mat);
     739            0 :         assert(matEMPD != nullptr);
     740              : 
     741              :         static constexpr std::string_view Format_700(
     742              :             " Construction EMPD, {}, {}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}\n");
     743            0 :         print(state.files.eio,
     744              :               Format_700,
     745            0 :               constr.Name,
     746            0 :               matEMPD->Name,
     747            0 :               matEMPD->mu,
     748            0 :               matEMPD->moistACoeff,
     749            0 :               matEMPD->moistBCoeff,
     750            0 :               matEMPD->moistCCoeff,
     751            0 :               matEMPD->moistDCoeff,
     752            0 :               matEMPD->surfaceDepth,
     753            0 :               matEMPD->deepDepth,
     754            0 :               matEMPD->muCoating,
     755            0 :               matEMPD->coatingThickness);
     756              :     }
     757              : } // ReportMoistureBalanceEMPD()
     758              : 
     759              : } // namespace EnergyPlus::MoistureBalanceEMPDManager
        

Generated by: LCOV version 2.0-1