LCOV - code coverage report
Current view: top level - EnergyPlus - MoistureBalanceEMPDManager.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 229 309 74.1 %
Date: 2023-01-17 19:17:23 Functions: 7 8 87.5 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // 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           0 : Real64 CalcDepthFromPeriod(EnergyPlusData &state,
     111             :                            Real64 const period,                    // in seconds
     112             :                            Material::MaterialProperties const &mat // material
     113             : )
     114             : {
     115             : 
     116             :     // Assume T, RH, P
     117           0 :     Real64 constexpr T = 24.0; // C
     118           0 :     Real64 constexpr RH = 0.45;
     119           0 :     Real64 constexpr P_amb = 101325; // Pa
     120             : 
     121             :     // Calculate saturation vapor pressure at assumed temperature
     122           0 :     Real64 const PV_sat = Psychrometrics::PsyPsatFnTemp(state, T, "CalcDepthFromPeriod");
     123             : 
     124             :     // Calculate slope of moisture sorption curve
     125             :     Real64 const slope_MC =
     126           0 :         mat.MoistACoeff * mat.MoistBCoeff * std::pow(RH, mat.MoistBCoeff - 1) + mat.MoistCCoeff * mat.MoistDCoeff * std::pow(RH, mat.MoistDCoeff - 1);
     127             : 
     128             :     // Equation for the diffusivity of water vapor in air
     129           0 :     Real64 const diffusivity_air = 2.0e-7 * std::pow(T + 273.15, 0.81) / P_amb;
     130             : 
     131             :     // Convert mu to diffusivity [kg/m^2-s-Pa]
     132           0 :     Real64 const EMPDdiffusivity = diffusivity_air / mat.EMPDmu;
     133             : 
     134             :     // Calculate penetration depth
     135           0 :     Real64 const PenetrationDepth = std::sqrt(EMPDdiffusivity * PV_sat * period / (mat.Density * slope_MC * DataGlobalConstants::Pi));
     136             : 
     137           0 :     return PenetrationDepth;
     138             : }
     139             : 
     140           2 : void GetMoistureBalanceEMPDInput(EnergyPlusData &state)
     141             : {
     142             : 
     143             :     // SUBROUTINE INFORMATION:
     144             :     //       AUTHOR         Muthusamy V. Swami and Lixing Gu
     145             :     //       DATE WRITTEN   August 2000
     146             :     //       MODIFIED       na
     147             :     //       RE-ENGINEERED  na
     148             : 
     149             :     // PURPOSE OF THIS SUBROUTINE:
     150             :     // This subroutine is the main driver for initializations within the
     151             :     // heat balance using the EMPD model.
     152             : 
     153             :     // Using/Aliasing
     154             : 
     155             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     156             :     int IOStat;                       // IO Status when calling get input subroutine
     157           4 :     Array1D_string MaterialNames(3);  // Number of Material Alpha names defined
     158             :     int MaterNum;                     // Counter to keep track of the material number
     159             :     int MaterialNumAlpha;             // Number of material alpha names being passed
     160             :     int MaterialNumProp;              // Number of material properties being passed
     161           4 :     Array1D<Real64> MaterialProps(9); // Temporary array to transfer material properties
     162           2 :     bool ErrorsFound(false);          // If errors detected in input
     163             : 
     164             :     int EMPDMat; // EMPD Moisture Material additional properties for each base material
     165             :     int Loop;
     166             :     int Layer;
     167             :     int SurfNum;           // Surface number
     168             :     int MatNum;            // Material number at interior layer
     169             :     int ConstrNum;         // Construction number
     170           4 :     Array1D_bool EMPDzone; // EMPD property check for each zone
     171           2 :     auto &ErrCount = state.dataMoistureBalEMPD->ErrCount;
     172           2 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     173             : 
     174             :     // Load the additional EMPD Material properties
     175           2 :     cCurrentModuleObject = "MaterialProperty:MoisturePenetrationDepth:Settings";
     176           2 :     EMPDMat = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     177             : 
     178           2 :     if (EMPDMat == 0) {
     179           0 :         ShowSevereError(state, "EMPD Solution requested, but no \"" + cCurrentModuleObject + "\" objects were found.");
     180           0 :         ErrorsFound = true;
     181             :     }
     182             : 
     183           8 :     for (Loop = 1; Loop <= EMPDMat; ++Loop) {
     184             : 
     185             :         // Call Input Get routine to retrieve material data
     186          30 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     187             :                                                                  cCurrentModuleObject,
     188             :                                                                  Loop,
     189             :                                                                  MaterialNames,
     190             :                                                                  MaterialNumAlpha,
     191             :                                                                  MaterialProps,
     192             :                                                                  MaterialNumProp,
     193             :                                                                  IOStat,
     194           6 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     195           6 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     196           6 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     197           6 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     198             : 
     199             :         // Load the material derived type from the input data.
     200           6 :         MaterNum = UtilityRoutines::FindItemInList(MaterialNames(1), state.dataMaterial->Material);
     201           6 :         if (MaterNum == 0) {
     202           0 :             ShowSevereError(state,
     203           0 :                             cCurrentModuleObject + ": invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + " entered=" + MaterialNames(1) +
     204             :                                 ", must match to a valid Material name.");
     205           0 :             ErrorsFound = true;
     206           0 :             continue;
     207             :         }
     208             : 
     209             :         // See if Material was defined with R only.  (No density is defined then and not applicable for EMPD).
     210             :         //  What about materials other than "regular materials" (e.g. Glass, Air, etc)
     211           6 :         if (state.dataMaterial->Material(MaterNum).Group == DataHeatBalance::MaterialGroup::RegularMaterial && MaterialProps(1) > 0.0) {
     212           6 :             if (state.dataMaterial->Material(MaterNum).ROnly) {
     213             :                 //        CALL ShowSevereError('EMPD base material = "'//TRIM(dataMaterial.Material(MaterNum)%Name)//  &
     214             :                 //                             '" was Material:NoMass. It cannot be used for EMPD calculations.')
     215           0 :                 ShowContinueError(state, "..Only Material base materials are allowed to have EMPD properties.");
     216           0 :                 ShowSevereError(state,
     217           0 :                                 cCurrentModuleObject + ": Reference Material is not appropriate type for EMPD properties, material=" +
     218           0 :                                     state.dataMaterial->Material(MaterNum).Name + ", must have regular properties (L,Cp,K,D)");
     219           0 :                 ErrorsFound = true;
     220             :             }
     221             :         }
     222           6 :         if (state.dataMaterial->Material(MaterNum).Group != DataHeatBalance::MaterialGroup::RegularMaterial) {
     223             :             //      CALL ShowSevereError('GetMoistureBalanceEMPDInput: Only Material:Regular base materials are allowed '// &
     224             :             //                           'to have EMPD properties, material = '// TRIM(dataMaterial.Material(MaterNum)%Name))
     225           0 :             ShowSevereError(state,
     226           0 :                             cCurrentModuleObject + ": Reference Material is not appropriate type for EMPD properties, material=" +
     227           0 :                                 state.dataMaterial->Material(MaterNum).Name + ", must have regular properties (L,Cp,K,D)");
     228           0 :             ErrorsFound = true;
     229             :         }
     230             : 
     231             :         // Once the material derived type number is found then load the additional moisture material properties
     232           6 :         auto &material(state.dataMaterial->Material(MaterNum));
     233           6 :         material.EMPDmu = MaterialProps(1);
     234           6 :         material.MoistACoeff = MaterialProps(2);
     235           6 :         material.MoistBCoeff = MaterialProps(3);
     236           6 :         material.MoistCCoeff = MaterialProps(4);
     237           6 :         material.MoistDCoeff = MaterialProps(5);
     238           6 :         if (state.dataIPShortCut->lNumericFieldBlanks(6) || MaterialProps(6) == DataGlobalConstants::AutoCalculate) {
     239           0 :             material.EMPDSurfaceDepth = CalcDepthFromPeriod(state, 24 * 3600, material); // 1 day
     240             :         } else {
     241           6 :             material.EMPDSurfaceDepth = MaterialProps(6);
     242             :         }
     243           6 :         if (state.dataIPShortCut->lNumericFieldBlanks(7) || MaterialProps(7) == DataGlobalConstants::AutoCalculate) {
     244           0 :             material.EMPDDeepDepth = CalcDepthFromPeriod(state, 21 * 24 * 3600, material); // 3 weeks
     245             :         } else {
     246           6 :             material.EMPDDeepDepth = MaterialProps(7);
     247             :         }
     248           6 :         material.EMPDCoatingThickness = MaterialProps(8);
     249           6 :         material.EMPDmuCoating = MaterialProps(9);
     250             : 
     251           6 :         if (material.EMPDDeepDepth <= material.EMPDSurfaceDepth && material.EMPDDeepDepth != 0.0) {
     252           0 :             ShowWarningError(state, cCurrentModuleObject + ": material=\"" + material.Name + "\"");
     253           0 :             ShowContinueError(state, "Deep-layer penetration depth should be zero or greater than the surface-layer penetration depth.");
     254             :         }
     255             :     }
     256             : 
     257             :     // Ensure at least one interior EMPD surface for each zone
     258           2 :     EMPDzone.dimension(state.dataGlobal->NumOfZones, false);
     259          58 :     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     260          56 :         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf || state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window)
     261          10 :             continue; // Heat transfer surface only and not a window
     262          46 :         if (state.dataSurface->Surface(SurfNum).HeatTransferAlgorithm != DataSurfaces::HeatTransferModel::EMPD) continue;
     263          43 :         ConstrNum = state.dataSurface->Surface(SurfNum).Construction;
     264          43 :         MatNum = state.dataConstruction->Construct(ConstrNum).LayerPoint(state.dataConstruction->Construct(ConstrNum).TotLayers);
     265          43 :         if (state.dataMaterial->Material(MatNum).EMPDmu > 0.0 && state.dataSurface->Surface(SurfNum).Zone > 0) {
     266          43 :             EMPDzone(state.dataSurface->Surface(SurfNum).Zone) = true;
     267             :         } else {
     268           0 :             ++ErrCount;
     269           0 :             if (ErrCount == 1 && !state.dataGlobal->DisplayExtraWarnings) {
     270           0 :                 ShowMessage(state, "GetMoistureBalanceEMPDInput: EMPD properties are not assigned to the inside layer of Surfaces");
     271           0 :                 ShowContinueError(state, "...use Output:Diagnostics,DisplayExtraWarnings; to show more details on individual surfaces.");
     272             :             }
     273           0 :             if (state.dataGlobal->DisplayExtraWarnings) {
     274           0 :                 ShowMessage(state,
     275           0 :                             "GetMoistureBalanceEMPDInput: EMPD properties are not assigned to the inside layer in Surface=" +
     276           0 :                                 state.dataSurface->Surface(SurfNum).Name);
     277           0 :                 ShowContinueError(state, "with Construction=" + state.dataConstruction->Construct(ConstrNum).Name);
     278             :             }
     279             :         }
     280          43 :         if (state.dataConstruction->Construct(ConstrNum).TotLayers == 1) { // One layer construction
     281          15 :             continue;
     282             :         } else { // Multiple layer construction
     283          28 :             if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(1)).EMPDMaterialProps &&
     284           0 :                 state.dataSurface->Surface(SurfNum).ExtBoundCond <= 0) { // The external layer is not exposed to zone
     285           0 :                 ShowSevereError(state,
     286           0 :                                 "GetMoistureBalanceEMPDInput: EMPD properties are assigned to the outside layer in Construction=" +
     287           0 :                                     state.dataConstruction->Construct(ConstrNum).Name);
     288           0 :                 ShowContinueError(state,
     289           0 :                                   "..Outside layer material with EMPD properties = " +
     290           0 :                                       state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(1)).Name);
     291           0 :                 ShowContinueError(state, "..A material with EMPD properties must be assigned to the inside layer of a construction.");
     292           0 :                 ErrorsFound = true;
     293             :             }
     294          68 :             for (Layer = 2; Layer <= state.dataConstruction->Construct(ConstrNum).TotLayers - 1; ++Layer) {
     295          40 :                 if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(Layer)).EMPDMaterialProps) {
     296           0 :                     ShowSevereError(state,
     297           0 :                                     "GetMoistureBalanceEMPDInput: EMPD properties are assigned to a middle layer in Construction=" +
     298           0 :                                         state.dataConstruction->Construct(ConstrNum).Name);
     299           0 :                     ShowContinueError(state,
     300           0 :                                       "..Middle layer material with EMPD properties = " +
     301           0 :                                           state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(Layer)).Name);
     302           0 :                     ShowContinueError(state, "..A material with EMPD properties must be assigned to the inside layer of a construction.");
     303           0 :                     ErrorsFound = true;
     304             :                 }
     305             :             }
     306             :         }
     307             :     }
     308             : 
     309           9 :     for (Loop = 1; Loop <= state.dataGlobal->NumOfZones; ++Loop) {
     310           7 :         if (!EMPDzone(Loop)) {
     311           0 :             ShowSevereError(state,
     312           0 :                             "GetMoistureBalanceEMPDInput: None of the constructions for zone = " + state.dataHeatBal->Zone(Loop).Name +
     313             :                                 " has an inside layer with EMPD properties");
     314           0 :             ShowContinueError(state, "..For each zone, the inside layer of at least one construction must have EMPD properties");
     315           0 :             ErrorsFound = true;
     316             :         }
     317             :     }
     318             : 
     319           2 :     EMPDzone.deallocate();
     320             : 
     321           2 :     ReportMoistureBalanceEMPD(state);
     322             : 
     323           2 :     if (ErrorsFound) {
     324           0 :         ShowFatalError(state, "GetMoistureBalanceEMPDInput: Errors found getting EMPD material properties, program terminated.");
     325             :     }
     326           2 : }
     327             : 
     328          14 : void InitMoistureBalanceEMPD(EnergyPlusData &state)
     329             : {
     330             : 
     331             :     // SUBROUTINE INFORMATION:
     332             :     //   Authors:        Muthusamy Swami and Lixing Gu
     333             :     //   Date written:   August, 1999
     334             :     //   Modified:       na
     335             :     //   Re-engineered:  na
     336             : 
     337             :     // PURPOSE OF THIS SUBROUTINE:
     338             :     // Create dynamic array for surface moisture calculation
     339             : 
     340             :     // USE STATEMENTS:
     341             :     using Psychrometrics::PsyRhovFnTdbRh;
     342             :     using Psychrometrics::PsyRhovFnTdbWPb_fast;
     343             : 
     344             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     345             :     int ZoneNum;
     346             :     int SurfNum;
     347             : 
     348          14 :     if (state.dataMoistureBalEMPD->InitEnvrnFlag) {
     349           2 :         state.dataMstBalEMPD->RVSurfaceOld.allocate(state.dataSurface->TotSurfaces);
     350           2 :         state.dataMstBalEMPD->RVSurface.allocate(state.dataSurface->TotSurfaces);
     351           2 :         state.dataMstBalEMPD->HeatFluxLatent.allocate(state.dataSurface->TotSurfaces);
     352           2 :         state.dataMoistureBalEMPD->EMPDReportVars.allocate(state.dataSurface->TotSurfaces);
     353           2 :         state.dataMstBalEMPD->RVSurfLayer.allocate(state.dataSurface->TotSurfaces);
     354           2 :         state.dataMstBalEMPD->RVSurfLayerOld.allocate(state.dataSurface->TotSurfaces);
     355           2 :         state.dataMstBalEMPD->RVDeepLayer.allocate(state.dataSurface->TotSurfaces);
     356           2 :         state.dataMstBalEMPD->RVdeepOld.allocate(state.dataSurface->TotSurfaces);
     357           2 :         state.dataMstBalEMPD->RVwall.allocate(state.dataSurface->TotSurfaces);
     358             :     }
     359             : 
     360         538 :     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     361         524 :         ZoneNum = state.dataSurface->Surface(SurfNum).Zone;
     362         524 :         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
     363             :         Real64 const rv_air_in_initval =
     364        1936 :             min(PsyRhovFnTdbWPb_fast(state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT,
     365         484 :                                      max(state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).ZoneAirHumRat, 1.0e-5),
     366         484 :                                      state.dataEnvrn->OutBaroPress),
     367         968 :                 PsyRhovFnTdbRh(state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT, 1.0, "InitMoistureBalanceEMPD"));
     368         484 :         state.dataMstBalEMPD->RVSurfaceOld(SurfNum) = rv_air_in_initval;
     369         484 :         state.dataMstBalEMPD->RVSurface(SurfNum) = rv_air_in_initval;
     370         484 :         state.dataMstBalEMPD->RVSurfLayer(SurfNum) = rv_air_in_initval;
     371         484 :         state.dataMstBalEMPD->RVSurfLayerOld(SurfNum) = rv_air_in_initval;
     372         484 :         state.dataMstBalEMPD->RVDeepLayer(SurfNum) = rv_air_in_initval;
     373         484 :         state.dataMstBalEMPD->RVdeepOld(SurfNum) = rv_air_in_initval;
     374         484 :         state.dataMstBalEMPD->RVwall(SurfNum) = rv_air_in_initval;
     375             :     }
     376          14 :     if (!state.dataMoistureBalEMPD->InitEnvrnFlag) return;
     377             :     // Initialize the report variable
     378             : 
     379           2 :     GetMoistureBalanceEMPDInput(state);
     380             : 
     381          58 :     for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     382          66 :         if (!state.dataSurface->Surface(SurfNum).HeatTransSurf) continue;
     383          52 :         if (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) continue;
     384          46 :         EMPDReportVarsData &rvd = state.dataMoistureBalEMPD->EMPDReportVars(SurfNum);
     385          92 :         const std::string surf_name = state.dataSurface->Surface(SurfNum).Name;
     386          92 :         SetupOutputVariable(state,
     387             :                             "EMPD Surface Inside Face Water Vapor Density",
     388             :                             OutputProcessor::Unit::kg_m3,
     389             :                             rvd.rv_surface,
     390             :                             OutputProcessor::SOVTimeStepType::Zone,
     391             :                             OutputProcessor::SOVStoreType::State,
     392          46 :                             surf_name);
     393          92 :         SetupOutputVariable(state,
     394             :                             "EMPD Surface Layer Moisture Content",
     395             :                             OutputProcessor::Unit::kg_m3,
     396             :                             rvd.u_surface_layer,
     397             :                             OutputProcessor::SOVTimeStepType::Zone,
     398             :                             OutputProcessor::SOVStoreType::State,
     399          46 :                             surf_name);
     400          92 :         SetupOutputVariable(state,
     401             :                             "EMPD Deep Layer Moisture Content",
     402             :                             OutputProcessor::Unit::kg_m3,
     403             :                             rvd.u_deep_layer,
     404             :                             OutputProcessor::SOVTimeStepType::Zone,
     405             :                             OutputProcessor::SOVStoreType::State,
     406          46 :                             surf_name);
     407          92 :         SetupOutputVariable(state,
     408             :                             "EMPD Surface Layer Equivalent Relative Humidity",
     409             :                             OutputProcessor::Unit::Perc,
     410             :                             rvd.RH_surface_layer,
     411             :                             OutputProcessor::SOVTimeStepType::Zone,
     412             :                             OutputProcessor::SOVStoreType::State,
     413          46 :                             surf_name);
     414          92 :         SetupOutputVariable(state,
     415             :                             "EMPD Deep Layer Equivalent Relative Humidity",
     416             :                             OutputProcessor::Unit::Perc,
     417             :                             rvd.RH_deep_layer,
     418             :                             OutputProcessor::SOVTimeStepType::Zone,
     419             :                             OutputProcessor::SOVStoreType::State,
     420          46 :                             surf_name);
     421          92 :         SetupOutputVariable(state,
     422             :                             "EMPD Surface Layer Equivalent Humidity Ratio",
     423             :                             OutputProcessor::Unit::kgWater_kgDryAir,
     424             :                             rvd.w_surface_layer,
     425             :                             OutputProcessor::SOVTimeStepType::Zone,
     426             :                             OutputProcessor::SOVStoreType::State,
     427          46 :                             surf_name);
     428          92 :         SetupOutputVariable(state,
     429             :                             "EMPD Deep Layer Equivalent Humidity Ratio",
     430             :                             OutputProcessor::Unit::kgWater_kgDryAir,
     431             :                             rvd.w_deep_layer,
     432             :                             OutputProcessor::SOVTimeStepType::Zone,
     433             :                             OutputProcessor::SOVStoreType::State,
     434          46 :                             surf_name);
     435          92 :         SetupOutputVariable(state,
     436             :                             "EMPD Surface Moisture Flux to Zone",
     437             :                             OutputProcessor::Unit::kg_m2s,
     438             :                             rvd.mass_flux_zone,
     439             :                             OutputProcessor::SOVTimeStepType::Zone,
     440             :                             OutputProcessor::SOVStoreType::State,
     441          46 :                             surf_name);
     442          92 :         SetupOutputVariable(state,
     443             :                             "EMPD Deep Layer Moisture Flux",
     444             :                             OutputProcessor::Unit::kg_m2s,
     445             :                             rvd.mass_flux_deep,
     446             :                             OutputProcessor::SOVTimeStepType::Zone,
     447             :                             OutputProcessor::SOVStoreType::State,
     448          46 :                             surf_name);
     449             :     }
     450             : 
     451           2 :     if (state.dataMoistureBalEMPD->InitEnvrnFlag) state.dataMoistureBalEMPD->InitEnvrnFlag = false;
     452             : }
     453             : 
     454      699139 : void CalcMoistureBalanceEMPD(EnergyPlusData &state,
     455             :                              int const SurfNum,
     456             :                              Real64 const SurfTempIn, // INSIDE SURFACE TEMPERATURE at current time step
     457             :                              Real64 const TempZone,   // Zone temperature at current time step.
     458             :                              Real64 &TempSat          // Saturated surface temperature.
     459             : )
     460             : {
     461             : 
     462             :     // SUBROUTINE INFORMATION:
     463             :     //   Authors:        Muthusamy Swami and Lixing Gu
     464             :     //   Date written:   August, 1999
     465             :     //   Modified:       na
     466             :     //   Re-engineered:  na
     467             : 
     468             :     // PURPOSE OF THIS SUBROUTINE:
     469             :     // Calculate surface moisture level using EMPD model
     470             : 
     471             :     // Using/Aliasing
     472             :     using DataMoistureBalanceEMPD::Lam;
     473             :     using Psychrometrics::PsyCpAirFnW;
     474             :     using Psychrometrics::PsyPsatFnTemp;
     475             :     using Psychrometrics::PsyRhFnTdbRhov;
     476             :     using Psychrometrics::PsyRhFnTdbRhovLBnd0C;
     477             :     using Psychrometrics::PsyRhFnTdbWPb;
     478             :     using Psychrometrics::PsyRhoAirFnPbTdbW;
     479             :     using Psychrometrics::PsyRhovFnTdbRh;
     480             :     using Psychrometrics::PsyRhovFnTdbWPb;
     481             :     using Psychrometrics::PsyRhovFnTdbWPb_fast;
     482             :     using Psychrometrics::PsyWFnTdbRhPb;
     483             : 
     484             :     static constexpr std::string_view RoutineName("CalcMoistureEMPD");
     485             : 
     486             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     487             :     int NOFITR;           // Number of iterations
     488             :     int MatNum;           // Material number at interior layer
     489             :     int ConstrNum;        // Construction number
     490             :     Real64 hm_deep_layer; // Overall deep-layer transfer coefficient
     491             :     Real64 RSurfaceLayer; // Mass transfer resistance between actual surface and surface layer node
     492             :     Real64 Taver;         // Average zone temperature between current time and previous time
     493             :     //    REAL(r64)    :: Waver     ! Average zone humidity ratio between current time and previous time
     494             :     Real64 RHaver; // Average zone relative humidity {0-1} between current time and previous time
     495             :     Real64 RVaver; // Average zone vapor density
     496             :     Real64 dU_dRH;
     497             :     int Flag; // Convergence flag (0 - converged)
     498      699139 :     auto &OneTimeFlag = state.dataMoistureBalEMPD->OneTimeFlag;
     499             :     Real64 PVsurf;        // Surface vapor pressure
     500             :     Real64 PV_surf_layer; // Vapor pressure of surface layer
     501             :     Real64 PV_deep_layer;
     502             :     Real64 PVsat; // saturation vapor pressure at the surface
     503             :     Real64 RH_surf_layer_old;
     504             :     Real64 RH_deep_layer_old;
     505             :     Real64 EMPDdiffusivity;
     506             :     Real64 Rcoating;
     507             :     Real64 RH_surf_layer;
     508             :     Real64 RH_surf_layer_tmp;
     509             :     Real64 RH_deep_layer;
     510             : 
     511      699139 :     if (state.dataGlobal->BeginEnvrnFlag && OneTimeFlag) {
     512          14 :         InitMoistureBalanceEMPD(state);
     513          14 :         OneTimeFlag = false;
     514             :     }
     515             : 
     516      699139 :     if (!state.dataGlobal->BeginEnvrnFlag) {
     517      696421 :         OneTimeFlag = true;
     518             :     }
     519             : 
     520      699139 :     auto const &surface(state.dataSurface->Surface(SurfNum));                // input
     521      699139 :     auto &rv_surface(state.dataMstBalEMPD->RVSurface(SurfNum));              // output
     522      699139 :     auto const &rv_surface_old(state.dataMstBalEMPD->RVSurfaceOld(SurfNum)); // input
     523      699139 :     auto const &h_mass_conv_in_fd(state.dataMstBal->HMassConvInFD(SurfNum)); // input
     524      699139 :     auto const &rho_vapor_air_in(state.dataMstBal->RhoVaporAirIn(SurfNum));  // input
     525             :     Real64 RHZone;
     526             :     Real64 mass_flux_surf_deep;
     527             :     Real64 mass_flux_surf_deep_max;
     528             :     Real64 mass_flux_zone_surf;
     529             :     Real64 mass_flux_zone_surf_max;
     530             :     Real64 mass_flux_surf_layer;
     531             :     Real64 mass_flux_deep_layer;
     532             :     Real64 mass_flux_zone;
     533      699139 :     auto &rv_surf_layer(state.dataMstBalEMPD->RVSurfLayer(SurfNum));              // output
     534      699139 :     auto const &rv_surf_layer_old(state.dataMstBalEMPD->RVSurfLayerOld(SurfNum)); // input
     535             :     Real64 hm_surf_layer;
     536      699139 :     auto &rv_deep_layer(state.dataMstBalEMPD->RVDeepLayer(SurfNum));       // output
     537      699139 :     auto const &rv_deep_old(state.dataMstBalEMPD->RVdeepOld(SurfNum));     // input
     538      699139 :     auto &heat_flux_latent(state.dataMstBalEMPD->HeatFluxLatent(SurfNum)); // output
     539             : 
     540      699139 :     heat_flux_latent = 0.0;
     541      699139 :     Flag = 1;
     542      699139 :     NOFITR = 0;
     543      699139 :     if (!surface.HeatTransSurf) {
     544           0 :         return;
     545             :     }
     546      699139 :     ConstrNum = surface.Construction;
     547     1398278 :     MatNum = state.dataConstruction->Construct(ConstrNum).LayerPoint(
     548      699139 :         state.dataConstruction->Construct(ConstrNum).TotLayers); // Then find the material pointer
     549             : 
     550      699139 :     auto const &material(state.dataMaterial->Material(MatNum));
     551      699139 :     if (material.EMPDmu <= 0.0) {
     552           0 :         rv_surface = PsyRhovFnTdbWPb(
     553           0 :             TempZone, state.dataZoneTempPredictorCorrector->zoneHeatBalance(surface.Zone).ZoneAirHumRat, state.dataEnvrn->OutBaroPress);
     554           0 :         return;
     555             :     }
     556             : 
     557      699139 :     Taver = SurfTempIn;
     558             :     // Calculate average vapor density [kg/m^3], and RH for use in material property calculations.
     559      699139 :     RVaver = rv_surface_old;
     560      699139 :     RHaver = RVaver * 461.52 * (Taver + DataGlobalConstants::KelvinConv) * std::exp(-23.7093 + 4111.0 / (Taver + 237.7));
     561             : 
     562             :     // Calculate the saturated vapor pressure, surface vapor pressure and dewpoint. Used to check for condensation in HeatBalanceSurfaceManager
     563      699139 :     PVsat = PsyPsatFnTemp(state, Taver, RoutineName);
     564      699139 :     PVsurf = RHaver * std::exp(23.7093 - 4111.0 / (Taver + 237.7));
     565      699139 :     TempSat = 4111.0 / (23.7093 - std::log(PVsurf)) + 35.45 - DataGlobalConstants::KelvinConv;
     566             : 
     567             :     // Convert vapor resistance factor (user input) to diffusivity. Evaluate at local surface temperature.
     568             :     // 2e-7*T^0.81/P = vapor diffusivity in air. [kg/m-s-Pa]
     569             :     // 461.52 = universal gas constant for water [J/kg-K]
     570             :     // EMPDdiffusivity = [m^2/s]
     571     1398278 :     EMPDdiffusivity = (2.0e-7 * pow(Taver + DataGlobalConstants::KelvinConv, 0.81) / state.dataEnvrn->OutBaroPress) / material.EMPDmu * 461.52 *
     572      699139 :                       (Taver + DataGlobalConstants::KelvinConv);
     573             : 
     574             :     // Calculate slope of moisture sorption curve at current RH. [kg/kg-RH]
     575     1398278 :     dU_dRH = material.MoistACoeff * material.MoistBCoeff * pow(RHaver, material.MoistBCoeff - 1) +
     576      699139 :              material.MoistCCoeff * material.MoistDCoeff * pow(RHaver, material.MoistDCoeff - 1);
     577             : 
     578             :     // Convert vapor density and temperature of zone air to RH
     579     1398278 :     RHZone = rho_vapor_air_in * 461.52 * (TempZone + DataGlobalConstants::KelvinConv) *
     580      699139 :              std::exp(-23.7093 + 4111.0 / ((TempZone + DataGlobalConstants::KelvinConv) - 35.45));
     581             : 
     582             :     // Convert stored vapor density from previous timestep to RH.
     583      699139 :     RH_deep_layer_old = PsyRhFnTdbRhov(state, Taver, rv_deep_old);
     584      699139 :     RH_surf_layer_old = PsyRhFnTdbRhov(state, Taver, rv_surf_layer_old);
     585             : 
     586             :     // If coating vapor resistance factor equals 0, coating resistance is zero (avoid divide by zero).
     587             :     // Otherwise, calculate coating resistance with coating vapor resistance factor and thickness. [s/m]
     588      699139 :     if (material.EMPDmuCoating <= 0.0) {
     589      699139 :         Rcoating = 0;
     590             :     } else {
     591           0 :         Rcoating = material.EMPDCoatingThickness * material.EMPDmuCoating * state.dataEnvrn->OutBaroPress /
     592           0 :                    (2.0e-7 * pow(Taver + DataGlobalConstants::KelvinConv, 0.81) * 461.52 * (Taver + DataGlobalConstants::KelvinConv));
     593             :     }
     594             : 
     595             :     // Calculate mass-transfer coefficient between zone air and center of surface layer. [m/s]
     596      699139 :     hm_surf_layer = 1.0 / (0.5 * material.EMPDSurfaceDepth / EMPDdiffusivity + 1.0 / h_mass_conv_in_fd + Rcoating);
     597             :     // Calculate mass-transfer coefficient between center of surface layer and center of deep layer. [m/s]
     598             :     // If deep layer depth = 0, set mass-transfer coefficient to zero (simulates with no deep layer).
     599      699139 :     if (material.EMPDDeepDepth <= 0.0) {
     600      123219 :         hm_deep_layer = 0;
     601             :     } else {
     602      575920 :         hm_deep_layer = 2.0 * EMPDdiffusivity / (material.EMPDDeepDepth + material.EMPDSurfaceDepth);
     603             :     }
     604             :     // Calculate resistance between surface-layer/air interface and center of surface layer. [s/m]
     605             :     // This is the physical surface of the material.
     606      699139 :     RSurfaceLayer = 1.0 / hm_surf_layer - 1.0 / h_mass_conv_in_fd;
     607             : 
     608             :     // Calculate vapor flux leaving surface layer, entering deep layer, and entering zone.
     609      699139 :     mass_flux_surf_deep_max =
     610      699139 :         material.EMPDDeepDepth * material.Density * dU_dRH * (RH_surf_layer_old - RH_deep_layer_old) / (state.dataGlobal->TimeStepZone * 3600.0);
     611      699139 :     mass_flux_surf_deep = hm_deep_layer * (rv_surf_layer_old - rv_deep_old);
     612      699139 :     if (std::abs(mass_flux_surf_deep_max) < std::abs(mass_flux_surf_deep)) {
     613           0 :         mass_flux_surf_deep = mass_flux_surf_deep_max;
     614             :     }
     615             : 
     616      699139 :     mass_flux_zone_surf_max =
     617      699139 :         material.EMPDSurfaceDepth * material.Density * dU_dRH * (RHZone - RH_surf_layer_old) / (state.dataGlobal->TimeStepZone * 3600.0);
     618      699139 :     mass_flux_zone_surf = hm_surf_layer * (rho_vapor_air_in - rv_surf_layer_old);
     619      699139 :     if (std::abs(mass_flux_zone_surf_max) < std::abs(mass_flux_zone_surf)) {
     620       10625 :         mass_flux_zone_surf = mass_flux_zone_surf_max;
     621             :     }
     622             : 
     623             :     // mass_flux_surf_layer = -mass_flux_zone_surf + mass_flux_surf_deep;
     624             :     // mass_flux_deep_layer = mass_flux_surf_deep;
     625             :     // mass_flux_zone = -mass_flux_zone_surf;
     626             : 
     627      699139 :     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);
     628      699139 :     mass_flux_deep_layer = hm_deep_layer * (rv_surf_layer_old - rv_deep_old);
     629      699139 :     mass_flux_zone = hm_surf_layer * (rv_surf_layer_old - rho_vapor_air_in);
     630             : 
     631             :     // Calculate new surface layer RH using mass balance on surface layer
     632      699139 :     RH_surf_layer_tmp = RH_surf_layer_old +
     633      699139 :                         state.dataGlobal->TimeStepZone * 3600.0 * (-mass_flux_surf_layer / (material.Density * material.EMPDSurfaceDepth * dU_dRH));
     634             : 
     635             :     //    RH_surf_layer = RH_surf_layer_tmp;
     636             : 
     637      699139 :     if (RH_surf_layer_old < RH_deep_layer_old && RH_surf_layer_old < RHZone) {
     638      398926 :         if (RHZone > RH_deep_layer_old) {
     639      107133 :             if (RH_surf_layer_tmp > RHZone) {
     640           3 :                 RH_surf_layer = RHZone;
     641             :             } else {
     642      107130 :                 RH_surf_layer = RH_surf_layer_tmp;
     643             :             }
     644       92330 :         } else if (RH_surf_layer_tmp > RH_deep_layer_old) {
     645           0 :             RH_surf_layer = RH_deep_layer_old;
     646             :         } else {
     647       92330 :             RH_surf_layer = RH_surf_layer_tmp;
     648             :         }
     649             : 
     650      499676 :     } else if (RH_surf_layer_old < RH_deep_layer_old && RH_surf_layer_old > RHZone) {
     651      422456 :         if (RH_surf_layer_tmp > RH_deep_layer_old) {
     652         184 :             RH_surf_layer = RH_deep_layer_old;
     653      211044 :         } else if (RH_surf_layer_tmp < RHZone) {
     654        1732 :             RH_surf_layer = RHZone;
     655             :         } else {
     656      209312 :             RH_surf_layer = RH_surf_layer_tmp;
     657             :         }
     658      288448 :     } else if (RH_surf_layer_old > RH_deep_layer_old && RH_surf_layer_old < RHZone) {
     659      217948 :         if (RH_surf_layer_tmp > RHZone) {
     660         559 :             RH_surf_layer = RHZone;
     661      108415 :         } else if (RH_surf_layer_tmp < RH_deep_layer_old) {
     662         582 :             RH_surf_layer = RH_deep_layer_old;
     663             :         } else
     664      107833 :             RH_surf_layer = RH_surf_layer_tmp;
     665      179474 :     } else if (RHZone < RH_deep_layer_old) {
     666       92467 :         if (RH_surf_layer_tmp < RHZone) {
     667           1 :             RH_surf_layer = RHZone;
     668             :         } else {
     669       92466 :             RH_surf_layer = RH_surf_layer_tmp;
     670             :         }
     671       87007 :     } else if (RH_surf_layer_tmp < RH_deep_layer_old) {
     672         246 :         RH_surf_layer = RH_deep_layer_old;
     673             :     } else {
     674       86761 :         RH_surf_layer = RH_surf_layer_tmp;
     675             :     }
     676             : 
     677             :     // Calculate new deep layer RH using mass balance on deep layer (unless depth <= 0).
     678      699139 :     if (material.EMPDDeepDepth <= 0.0) {
     679      123219 :         RH_deep_layer = RH_deep_layer_old;
     680             :     } else {
     681      575920 :         RH_deep_layer =
     682      575920 :             RH_deep_layer_old + state.dataGlobal->TimeStepZone * 3600.0 * mass_flux_deep_layer / (material.Density * material.EMPDDeepDepth * dU_dRH);
     683             :     }
     684             :     // Convert calculated RH back to vapor density of surface and deep layers.
     685      699139 :     rv_surf_layer = PsyRhovFnTdbRh(state, Taver, RH_surf_layer);
     686      699139 :     rv_deep_layer = PsyRhovFnTdbRh(state, Taver, RH_deep_layer);
     687             : 
     688             :     // Calculate surface-layer and deep-layer vapor pressures [Pa]
     689      699139 :     PV_surf_layer = RH_surf_layer * std::exp(23.7093 - 4111.0 / (Taver + 237.7));
     690      699139 :     PV_deep_layer = RH_deep_layer * std::exp(23.7093 - 4111.0 / (Taver + 237.7));
     691             : 
     692             :     // Calculate vapor density at physical material surface (surface-layer/air interface). This is used to calculate total moisture flow terms for
     693             :     // each zone in HeatBalanceSurfaceManager
     694      699139 :     rv_surface = rv_surf_layer - mass_flux_zone * RSurfaceLayer;
     695             : 
     696             :     // Calculate heat flux from latent-sensible conversion due to moisture adsorption [W/m^2]
     697      699139 :     heat_flux_latent = mass_flux_zone * Lam;
     698             : 
     699             :     // Put results in the reporting variables
     700             :     // Will add RH and W of deep layer as outputs
     701             :     // 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
     702      699139 :     EMPDReportVarsData &rvd = state.dataMoistureBalEMPD->EMPDReportVars(SurfNum);
     703      699139 :     rvd.rv_surface = rv_surface;
     704      699139 :     rvd.RH_surface_layer = RH_surf_layer * 100.0;
     705      699139 :     rvd.RH_deep_layer = RH_deep_layer * 100.0;
     706      699139 :     rvd.w_surface_layer = 0.622 * PV_surf_layer / (state.dataEnvrn->OutBaroPress - PV_surf_layer);
     707      699139 :     rvd.w_deep_layer = 0.622 * PV_deep_layer / (state.dataEnvrn->OutBaroPress - PV_deep_layer);
     708      699139 :     rvd.mass_flux_zone = mass_flux_zone;
     709      699139 :     rvd.mass_flux_deep = mass_flux_deep_layer;
     710      699139 :     rvd.u_surface_layer =
     711      699139 :         material.MoistACoeff * pow(RH_surf_layer, material.MoistBCoeff) + material.MoistCCoeff * pow(RH_surf_layer, material.MoistDCoeff);
     712      699139 :     rvd.u_deep_layer =
     713      699139 :         material.MoistACoeff * pow(RH_deep_layer, material.MoistBCoeff) + material.MoistCCoeff * pow(RH_deep_layer, material.MoistDCoeff);
     714             : }
     715             : 
     716      150018 : void UpdateMoistureBalanceEMPD(EnergyPlusData &state, int const SurfNum) // Surface number
     717             : {
     718             : 
     719             :     // SUBROUTINE INFORMATION:
     720             :     //   Authors:        Muthusamy Swami and Lixing Gu
     721             :     //   Date writtenn:  August, 1999
     722             :     //   Modified:       na
     723             :     //   Re-engineered:  na
     724             : 
     725             :     // PURPOSE OF THIS SUBROUTINE:
     726             :     // Update inside surface vapor density
     727             : 
     728      150018 :     state.dataMstBalEMPD->RVSurfaceOld(SurfNum) = state.dataMstBalEMPD->RVSurface(SurfNum);
     729      150018 :     state.dataMstBalEMPD->RVdeepOld(SurfNum) = state.dataMstBalEMPD->RVDeepLayer(SurfNum);
     730      150018 :     state.dataMstBalEMPD->RVSurfLayerOld(SurfNum) = state.dataMstBalEMPD->RVSurfLayer(SurfNum);
     731      150018 : }
     732             : 
     733           2 : void ReportMoistureBalanceEMPD(EnergyPlusData &state)
     734             : {
     735             : 
     736             :     // SUBROUTINE INFORMATION:
     737             :     //       AUTHOR         Lixing Gu
     738             :     //       DATE WRITTEN   August 2005
     739             :     //       MODIFIED       na
     740             :     //       RE-ENGINEERED  na
     741             : 
     742             :     // PURPOSE OF THIS SUBROUTINE:
     743             :     // This routine gives a detailed report to the user about
     744             :     // EMPD Properties of each construction.
     745             : 
     746             :     // Using/Aliasing
     747             :     using General::ScanForReports;
     748             : 
     749             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     750             :     bool DoReport;
     751             : 
     752             :     int ConstrNum;
     753             :     int MatNum;
     754             : 
     755           2 :     ScanForReports(state, "Constructions", DoReport, "Constructions");
     756             : 
     757           2 :     if (!DoReport) return;
     758             :     //   Write Descriptions
     759           2 :     print(state.files.eio,
     760             :           "{}",
     761             :           "! <Construction EMPD>, Construction Name, Inside Layer Material Name, Vapor Resistance Factor, a, b, "
     762             :           "c, d, Surface Penetration Depth {m}, Deep Penetration Depth {m}, Coating Vapor Resistance Factor, "
     763           2 :           "Coating Thickness {m}\n");
     764             : 
     765          13 :     for (ConstrNum = 1; ConstrNum <= state.dataHeatBal->TotConstructs; ++ConstrNum) {
     766          11 :         if (state.dataConstruction->Construct(ConstrNum).TypeIsWindow) continue;
     767           9 :         MatNum = state.dataConstruction->Construct(ConstrNum).LayerPoint(state.dataConstruction->Construct(ConstrNum).TotLayers);
     768           9 :         if (state.dataMaterial->Material(MatNum).EMPDMaterialProps) {
     769             :             static constexpr std::string_view Format_700(
     770             :                 " Construction EMPD, {}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}, {:8.4F}\n");
     771           0 :             print(state.files.eio,
     772             :                   Format_700,
     773           0 :                   state.dataConstruction->Construct(ConstrNum).Name,
     774           0 :                   state.dataMaterial->Material(MatNum).Name,
     775           0 :                   state.dataMaterial->Material(MatNum).EMPDmu,
     776           0 :                   state.dataMaterial->Material(MatNum).MoistACoeff,
     777           0 :                   state.dataMaterial->Material(MatNum).MoistBCoeff,
     778           0 :                   state.dataMaterial->Material(MatNum).MoistCCoeff,
     779           0 :                   state.dataMaterial->Material(MatNum).MoistDCoeff,
     780           0 :                   state.dataMaterial->Material(MatNum).EMPDSurfaceDepth,
     781           0 :                   state.dataMaterial->Material(MatNum).EMPDDeepDepth,
     782           0 :                   state.dataMaterial->Material(MatNum).EMPDmuCoating,
     783           0 :                   state.dataMaterial->Material(MatNum).EMPDCoatingThickness);
     784             :         }
     785             :     }
     786             : }
     787             : 
     788        2313 : } // namespace EnergyPlus::MoistureBalanceEMPDManager

Generated by: LCOV version 1.13