LCOV - code coverage report
Current view: top level - EnergyPlus - WindowManagerExteriorThermal.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 477 537 88.8 %
Date: 2024-08-23 23:50:59 Functions: 26 26 100.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, 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             : // EnergyPlus headers
      49             : #include <EnergyPlus/Construction.hh>
      50             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      51             : #include <EnergyPlus/DataEnvironment.hh>
      52             : #include <EnergyPlus/DataHeatBalSurface.hh>
      53             : #include <EnergyPlus/DataHeatBalance.hh>
      54             : #include <EnergyPlus/DataSurfaces.hh>
      55             : #include <EnergyPlus/General.hh>
      56             : #include <EnergyPlus/Material.hh>
      57             : #include <EnergyPlus/UtilityRoutines.hh>
      58             : #include <EnergyPlus/WindowManager.hh>
      59             : 
      60             : // Windows library headers
      61             : #include <WCEMultiLayerOptics.hpp>
      62             : #include <WCETarcog.hpp>
      63             : 
      64             : // EnergyPlus headers
      65             : #include <EnergyPlus/WindowManagerExteriorThermal.hh>
      66             : 
      67             : namespace EnergyPlus {
      68             : 
      69             : using namespace DataEnvironment;
      70             : using namespace DataSurfaces;
      71             : using namespace DataHeatBalance;
      72             : using namespace General;
      73             : 
      74             : namespace Window {
      75             : 
      76             :     /////////////////////////////////////////////////////////////////////////////////////////
      77        4032 :     void CalcWindowHeatBalanceExternalRoutines(EnergyPlusData &state,
      78             :                                                int const SurfNum,          // Surface number
      79             :                                                Real64 const HextConvCoeff, // Outside air film conductance coefficient
      80             :                                                Real64 &SurfInsideTemp,     // Inside window surface temperature
      81             :                                                Real64 &SurfOutsideTemp     // Outside surface temperature (C)
      82             :     )
      83             :     {
      84             :         // SUBROUTINE INFORMATION:
      85             :         //       AUTHOR         Simon Vidanovic
      86             :         //       DATE WRITTEN   July 2016
      87             :         //       MODIFIED       na
      88             :         //       RE-ENGINEERED  na
      89             : 
      90             :         // PURPOSE OF THIS SUBROUTINE:
      91             :         // Main wrapper routine to pick-up data from EnergyPlus and then call Windows-CalcEngine routines
      92             :         // to obtain results
      93             : 
      94        4032 :         auto &window = state.dataSurface->SurfaceWindow(SurfNum);
      95        4032 :         auto &surface = state.dataSurface->Surface(SurfNum);
      96        4032 :         int ConstrNum = surface.Construction;
      97        4032 :         auto &construction = state.dataConstruction->Construct(ConstrNum);
      98             : 
      99        4032 :         constexpr Real64 solutionTolerance = 0.02;
     100             : 
     101             :         // Tarcog thermal system for solving heat transfer through the window
     102        4032 :         int activeConstrNum = CWCEHeatTransferFactory::getActiveConstructionNumber(state, surface, SurfNum);
     103        4032 :         auto aFactory = CWCEHeatTransferFactory(state, surface, SurfNum, activeConstrNum); // (AUTO_OK)
     104        4032 :         auto aSystem = aFactory.getTarcogSystem(state, HextConvCoeff);                     // (AUTO_OK_SPTR)
     105        4032 :         aSystem->setTolerance(solutionTolerance);
     106             : 
     107             :         // get previous timestep temperatures solution for faster iterations
     108        4032 :         std::vector<Real64> Guess;
     109        4032 :         int totSolidLayers = construction.TotSolidLayers;
     110             : 
     111             :         // Interior and exterior shading layers have gas between them and IGU but that gas
     112             :         // was not part of construction so it needs to be increased by one
     113        4032 :         if (ANY_SHADE_SCREEN(state.dataSurface->SurfWinShadingFlag(SurfNum)) || ANY_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
     114        2688 :             ++totSolidLayers;
     115             :         }
     116             : 
     117       20160 :         for (int k = 1; k <= 2 * totSolidLayers; ++k) {
     118       16128 :             Guess.push_back(state.dataSurface->SurfaceWindow(SurfNum).thetaFace[k]);
     119             :         }
     120             : 
     121             :         try {
     122        4032 :             aSystem->setInitialGuess(Guess);
     123        4032 :             aSystem->solve();
     124           0 :         } catch (const std::exception &ex) {
     125           0 :             ShowSevereError(state, "Error in Windows Calculation Engine Exterior Module.");
     126           0 :             ShowContinueError(state, ex.what());
     127           0 :         }
     128             : 
     129        4032 :         auto aLayers = aSystem->getSolidLayers(); // (AUTO_OK_OBJ)
     130        4032 :         int i = 1;
     131       12096 :         for (const auto &aLayer : aLayers) { // (AUTO_OK_SPTR)
     132        8064 :             Real64 aTemp = 0;
     133       24192 :             for (auto aSide : FenestrationCommon::EnumSide()) { // (AUTO_OK) I don't understand what this construct is
     134       16128 :                 aTemp = aLayer->getTemperature(aSide);
     135       16128 :                 state.dataWindowManager->thetas[i - 1] = aTemp;
     136       16128 :                 if (i == 1) {
     137        4032 :                     SurfOutsideTemp = aTemp - Constant::Kelvin;
     138             :                 }
     139       16128 :                 ++i;
     140             :             }
     141        8064 :             SurfInsideTemp = aTemp - Constant::Kelvin;
     142        8064 :             if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
     143             :                 Real64 EffShBlEmiss;
     144             :                 Real64 EffGlEmiss;
     145        5376 :                 if (state.dataSurface->SurfWinMovableSlats(SurfNum)) {
     146             :                     EffShBlEmiss =
     147           0 :                         General::Interp(window.EffShBlindEmiss[state.dataSurface->SurfWinSlatsAngIndex(SurfNum)],
     148           0 :                                         window.EffShBlindEmiss[std::min(Material::MaxSlatAngs, state.dataSurface->SurfWinSlatsAngIndex(SurfNum) + 1)],
     149           0 :                                         state.dataSurface->SurfWinSlatsAngInterpFac(SurfNum));
     150             :                     EffGlEmiss =
     151           0 :                         General::Interp(window.EffGlassEmiss[state.dataSurface->SurfWinSlatsAngIndex(SurfNum)],
     152           0 :                                         window.EffGlassEmiss[std::min(Material::MaxSlatAngs, state.dataSurface->SurfWinSlatsAngIndex(SurfNum) + 1)],
     153           0 :                                         state.dataSurface->SurfWinSlatsAngInterpFac(SurfNum));
     154             :                 } else {
     155        5376 :                     EffShBlEmiss = state.dataSurface->SurfaceWindow(SurfNum).EffShBlindEmiss[1];
     156        5376 :                     EffGlEmiss = state.dataSurface->SurfaceWindow(SurfNum).EffGlassEmiss[1];
     157             :                 }
     158        5376 :                 state.dataSurface->SurfWinEffInsSurfTemp(SurfNum) =
     159        5376 :                     (EffShBlEmiss * SurfInsideTemp + EffGlEmiss * (state.dataWindowManager->thetas[2 * totSolidLayers - 3] - Constant::Kelvin)) /
     160        5376 :                     (EffShBlEmiss + EffGlEmiss);
     161             :             }
     162        4032 :         }
     163             : 
     164        4032 :         state.dataHeatBalSurf->SurfHConvInt(SurfNum) = aSystem->getHc(Tarcog::ISO15099::Environment::Indoor);
     165        4032 :         if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum)) || aFactory.isInteriorShade()) {
     166             :             // It is not clear why EnergyPlus keeps this interior calculations separately for interior shade. This does create different
     167             :             // solution from heat transfer from tarcog itself. Need to confirm with LBNL team about this approach. Note that heat flow
     168             :             // through shade (consider case when openings are zero) is different from heat flow obtained by these equations. Will keep
     169             :             // these calculations just to confirm that current exterior engine is giving close results to what is in here. (Simon)
     170        2688 :             int totLayers = aLayers.size();
     171        2688 :             state.dataWindowManager->nglface = 2 * totLayers - 2;
     172        2688 :             state.dataWindowManager->nglfacep = state.dataWindowManager->nglface + 2;
     173        2688 :             auto aShadeLayer = aLayers[totLayers - 1]; // (AUTO_OK_SPTR)
     174        2688 :             auto aGlassLayer = aLayers[totLayers - 2]; // (AUTO_OK_SPTR)
     175        2688 :             Real64 ShadeArea = state.dataSurface->Surface(SurfNum).Area + state.dataSurface->SurfWinDividerArea(SurfNum);
     176        2688 :             auto frontSurface = aShadeLayer->getSurface(FenestrationCommon::Side::Front); // (AUTO_OK_SPTR)
     177        2688 :             auto backSurface = aShadeLayer->getSurface(FenestrationCommon::Side::Back);   // (AUTO_OK_SPTR)
     178        2688 :             Real64 EpsShIR1 = frontSurface->getEmissivity();
     179        2688 :             Real64 EpsShIR2 = backSurface->getEmissivity();
     180        2688 :             Real64 TauShIR = frontSurface->getTransmittance();
     181        2688 :             Real64 RhoShIR1 = max(0.0, 1.0 - TauShIR - EpsShIR1);
     182        2688 :             Real64 RhoShIR2 = max(0.0, 1.0 - TauShIR - EpsShIR2);
     183        2688 :             Real64 glassEmiss = aGlassLayer->getSurface(FenestrationCommon::Side::Back)->getEmissivity();
     184        2688 :             Real64 RhoGlIR2 = 1.0 - glassEmiss;
     185        2688 :             Real64 ShGlReflFacIR = 1.0 - RhoGlIR2 * RhoShIR1;
     186        2688 :             Real64 rmir = state.dataSurface->SurfWinIRfromParentZone(SurfNum) + state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(SurfNum);
     187             :             Real64 NetIRHeatGainShade =
     188        5376 :                 ShadeArea * EpsShIR2 *
     189        2688 :                     (Constant::StefanBoltzmann * pow(state.dataWindowManager->thetas[state.dataWindowManager->nglfacep - 1], 4) - rmir) +
     190        2688 :                 EpsShIR1 * (Constant::StefanBoltzmann * pow(state.dataWindowManager->thetas[state.dataWindowManager->nglfacep - 2], 4) - rmir) *
     191        2688 :                     RhoGlIR2 * TauShIR / ShGlReflFacIR;
     192             :             Real64 NetIRHeatGainGlass =
     193        2688 :                 ShadeArea * (glassEmiss * TauShIR / ShGlReflFacIR) *
     194        2688 :                 (Constant::StefanBoltzmann * pow(state.dataWindowManager->thetas[state.dataWindowManager->nglface - 1], 4) - rmir);
     195        2688 :             Real64 tind = surface.getInsideAirTemperature(state, SurfNum) + Constant::Kelvin;
     196        2688 :             Real64 ConvHeatGainFrZoneSideOfShade = ShadeArea * state.dataHeatBalSurf->SurfHConvInt(SurfNum) *
     197        2688 :                                                    (state.dataWindowManager->thetas[state.dataWindowManager->nglfacep - 1] - tind);
     198        2688 :             state.dataSurface->SurfWinHeatGain(SurfNum) =
     199        2688 :                 state.dataSurface->SurfWinTransSolar(SurfNum) + ConvHeatGainFrZoneSideOfShade + NetIRHeatGainGlass + NetIRHeatGainShade;
     200             : 
     201        2688 :             state.dataSurface->SurfWinGainIRGlazToZoneRep(SurfNum) = NetIRHeatGainGlass;
     202             : 
     203             :             // Effective shade and glass emissivities that are used later for energy calculations.
     204             :             // This needs to be checked as well. (Simon)
     205        2688 :             Real64 EffShBlEmiss = EpsShIR1 * (1.0 + RhoGlIR2 * TauShIR / (1.0 - RhoGlIR2 * RhoShIR2));
     206        2688 :             std::fill(window.EffShBlindEmiss.begin(), window.EffShBlindEmiss.end(), EffShBlEmiss);
     207             : 
     208        2688 :             Real64 EffGlEmiss = glassEmiss * TauShIR / (1.0 - RhoGlIR2 * RhoShIR2);
     209        2688 :             std::fill(window.EffGlassEmiss.begin(), window.EffGlassEmiss.end(), EffGlEmiss);
     210             : 
     211        2688 :             Real64 glassTemperature = aGlassLayer->getSurface(FenestrationCommon::Side::Back)->getTemperature();
     212        2688 :             state.dataSurface->SurfWinEffInsSurfTemp(SurfNum) =
     213        2688 :                 (EffShBlEmiss * SurfInsideTemp + EffGlEmiss * (glassTemperature - Constant::Kelvin)) / (EffShBlEmiss + EffGlEmiss);
     214             : 
     215        2688 :         } else {
     216             :             // Another adoptation to old source that looks suspicious. Check if heat flow through
     217             :             // window is actually matching these values. (Simon)
     218             : 
     219             :             //
     220        1344 :             int totLayers = aLayers.size();
     221        1344 :             auto aGlassLayer = aLayers[totLayers - 1];                                  // (AUTO_OK_SPTR)
     222        1344 :             auto backSurface = aGlassLayer->getSurface(FenestrationCommon::Side::Back); // (AUTO_OK_SPTR)
     223             : 
     224        1344 :             Real64 h_cin = aSystem->getHc(Tarcog::ISO15099::Environment::Indoor);
     225             :             Real64 ConvHeatGainFrZoneSideOfGlass =
     226        1344 :                 surface.Area * h_cin * (backSurface->getTemperature() - aSystem->getAirTemperature(Tarcog::ISO15099::Environment::Indoor));
     227             : 
     228        1344 :             Real64 rmir = state.dataSurface->SurfWinIRfromParentZone(SurfNum) + state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(SurfNum);
     229             :             Real64 NetIRHeatGainGlass =
     230        1344 :                 surface.Area * backSurface->getEmissivity() * (Constant::StefanBoltzmann * pow(backSurface->getTemperature(), 4) - rmir);
     231             : 
     232        1344 :             state.dataSurface->SurfWinEffInsSurfTemp(SurfNum) =
     233        1344 :                 aLayers[totLayers - 1]->getTemperature(FenestrationCommon::Side::Back) - Constant::Kelvin;
     234        1344 :             std::fill(window.EffGlassEmiss.begin(),
     235             :                       window.EffGlassEmiss.end(),
     236        2688 :                       aLayers[totLayers - 1]->getSurface(FenestrationCommon::Side::Back)->getEmissivity());
     237             : 
     238        1344 :             state.dataSurface->SurfWinHeatGain(SurfNum) =
     239        1344 :                 state.dataSurface->SurfWinTransSolar(SurfNum) + ConvHeatGainFrZoneSideOfGlass + NetIRHeatGainGlass;
     240        1344 :             state.dataSurface->SurfWinGainConvGlazToZoneRep(SurfNum) = ConvHeatGainFrZoneSideOfGlass;
     241        1344 :             state.dataSurface->SurfWinGainIRGlazToZoneRep(SurfNum) = NetIRHeatGainGlass;
     242        1344 :         }
     243             : 
     244        4032 :         state.dataSurface->SurfWinLossSWZoneToOutWinRep(SurfNum) =
     245        4032 :             state.dataHeatBal->EnclSolQSWRad(state.dataSurface->Surface(SurfNum).SolarEnclIndex) * surface.Area *
     246        8064 :                 (1 - construction.ReflectSolDiffBack) +
     247        4032 :             state.dataHeatBalSurf->SurfWinInitialBeamSolInTrans(SurfNum);
     248        4032 :         state.dataSurface->SurfWinHeatGain(SurfNum) -=
     249        4032 :             (state.dataSurface->SurfWinLossSWZoneToOutWinRep(SurfNum) + state.dataHeatBalSurf->SurfWinInitialDifSolInTrans(SurfNum) * surface.Area);
     250             : 
     251       10752 :         for (int k = 1; k <= surface.getTotLayers(state); ++k) {
     252        6720 :             window.thetaFace[2 * k - 1] = state.dataWindowManager->thetas[2 * k - 2];
     253        6720 :             window.thetaFace[2 * k] = state.dataWindowManager->thetas[2 * k - 1];
     254             : 
     255             :             // temperatures for reporting
     256        6720 :             state.dataHeatBal->SurfWinFenLaySurfTempFront(SurfNum, k) = state.dataWindowManager->thetas[2 * k - 2] - Constant::Kelvin;
     257        6720 :             state.dataHeatBal->SurfWinFenLaySurfTempBack(SurfNum, k) = state.dataWindowManager->thetas[2 * k - 1] - Constant::Kelvin;
     258             :         }
     259        4032 :     }
     260             : 
     261             :     Real64
     262          41 :     GetIGUUValueForNFRCReport(EnergyPlusData &state, const int surfNum, const int constrNum, const Real64 windowWidth, const Real64 windowHeight)
     263             :     {
     264          41 :         Real64 tilt = 90.0;
     265             : 
     266          41 :         auto &surface = state.dataSurface->Surface(surfNum);
     267          41 :         auto aFactory = CWCEHeatTransferFactory(state, surface, surfNum, constrNum); // (AUTO_OK)
     268             : 
     269          41 :         const auto winterGlassUnit = aFactory.getTarcogSystemForReporting(state, false, windowWidth, windowHeight, tilt); // (AUTO_OK_SPTR)
     270             : 
     271          82 :         return winterGlassUnit->getUValue();
     272          41 :     }
     273             : 
     274          41 :     Real64 GetSHGCValueForNFRCReporting(EnergyPlusData &state, int surfNum, int constrNum, Real64 windowWidth, Real64 windowHeight)
     275             :     {
     276          41 :         Real64 tilt = 90.0;
     277             : 
     278          41 :         auto &surface = state.dataSurface->Surface(surfNum);
     279          41 :         auto aFactory = CWCEHeatTransferFactory(state, surface, surfNum, constrNum); // (AUTO_OK)
     280             : 
     281          41 :         const auto summerGlassUnit = aFactory.getTarcogSystemForReporting(state, true, windowWidth, windowHeight, tilt); // (AUTO_OK_SPTR)
     282          82 :         return summerGlassUnit->getSHGC(state.dataConstruction->Construct(surface.Construction).SolTransNorm);
     283          41 :     }
     284             : 
     285         422 :     void GetWindowAssemblyNfrcForReport(EnergyPlusData &state,
     286             :                                         int const surfNum,
     287             :                                         int constrNum,
     288             :                                         Real64 windowWidth,
     289             :                                         Real64 windowHeight,
     290             :                                         EnergyPlus::DataSurfaces::NfrcVisionType vision,
     291             :                                         Real64 &uvalue,
     292             :                                         Real64 &shgc,
     293             :                                         Real64 &vt)
     294             :     {
     295         422 :         auto &surface = state.dataSurface->Surface(surfNum);
     296         422 :         auto &frameDivider = state.dataSurface->FrameDivider(surface.FrameDivider);
     297             : 
     298         422 :         auto aFactory = CWCEHeatTransferFactory(state, surface, surfNum, constrNum); // (AUTO_OK)
     299             : 
     300        1266 :         for (bool isSummer : {false, true}) {
     301         844 :             constexpr Real64 framehExtConvCoeff = 30.0;
     302         844 :             constexpr Real64 framehIntConvCoeff = 8.0;
     303         844 :             constexpr Real64 tilt = 90.0;
     304             : 
     305         844 :             auto insulGlassUnit = aFactory.getTarcogSystemForReporting(state, isSummer, windowWidth, windowHeight, tilt); // (AUTO_OK_SPTR)
     306             : 
     307         844 :             const double centerOfGlassUvalue = insulGlassUnit->getUValue();
     308             : 
     309         844 :             auto winterGlassUnit = aFactory.getTarcogSystemForReporting(state, false, windowWidth, windowHeight, tilt); // (AUTO_OK_SPTR)
     310             : 
     311         844 :             const double frameUvalue = aFactory.overallUfactorFromFilmsAndCond(frameDivider.FrameConductance, framehIntConvCoeff, framehExtConvCoeff);
     312         844 :             const double frameEdgeUValue = winterGlassUnit->getUValue() * frameDivider.FrEdgeToCenterGlCondRatio; // not sure about this
     313         844 :             const double frameProjectedDimension = frameDivider.FrameWidth;
     314         844 :             const double frameWettedLength = frameProjectedDimension + frameDivider.FrameProjectionIn;
     315         844 :             const double frameAbsorptance = frameDivider.FrameSolAbsorp;
     316             : 
     317         844 :             Tarcog::ISO15099::FrameData frameData{frameUvalue, frameEdgeUValue, frameProjectedDimension, frameWettedLength, frameAbsorptance};
     318             : 
     319             :             const double dividerUvalue =
     320         844 :                 aFactory.overallUfactorFromFilmsAndCond(frameDivider.DividerConductance, framehIntConvCoeff, framehExtConvCoeff);
     321         844 :             const double dividerEdgeUValue = centerOfGlassUvalue * frameDivider.DivEdgeToCenterGlCondRatio; // not sure about this
     322         844 :             const double dividerProjectedDimension = frameDivider.DividerWidth;
     323         844 :             const double dividerWettedLength = dividerProjectedDimension + frameDivider.DividerProjectionIn;
     324         844 :             const double dividerAbsorptance = frameDivider.DividerSolAbsorp;
     325         844 :             const int numHorizDividers = frameDivider.HorDividers;
     326         844 :             const int numVertDividers = frameDivider.VertDividers;
     327             : 
     328             :             Tarcog::ISO15099::FrameData dividerData{
     329         844 :                 dividerUvalue, dividerEdgeUValue, dividerProjectedDimension, dividerWettedLength, dividerAbsorptance};
     330             : 
     331         844 :             const Real64 tVis = state.dataConstruction->Construct(constrNum).VisTransNorm;
     332         844 :             const Real64 tSol = state.dataConstruction->Construct(constrNum).SolTransNorm;
     333             : 
     334         844 :             if (vision == DataSurfaces::NfrcVisionType::Single) {
     335         830 :                 Tarcog::ISO15099::WindowSingleVision window(windowWidth, windowHeight, tVis, tSol, insulGlassUnit);
     336         830 :                 window.setFrameTop(frameData);
     337         830 :                 window.setFrameBottom(frameData);
     338         830 :                 window.setFrameLeft(frameData);
     339         830 :                 window.setFrameRight(frameData);
     340         830 :                 window.setDividers(dividerData, numHorizDividers, numVertDividers);
     341             : 
     342         830 :                 if (isSummer) {
     343         415 :                     vt = window.vt();
     344         415 :                     shgc = window.shgc();
     345             :                 } else {
     346         415 :                     uvalue = window.uValue();
     347             :                 }
     348         844 :             } else if (vision == EnergyPlus::DataSurfaces::NfrcVisionType::DualHorizontal) {
     349           0 :                 Tarcog::ISO15099::DualVisionHorizontal window(windowWidth, windowHeight, tVis, tSol, insulGlassUnit, tVis, tSol, insulGlassUnit);
     350           0 :                 window.setFrameLeft(frameData);
     351           0 :                 window.setFrameRight(frameData);
     352           0 :                 window.setFrameBottomLeft(frameData);
     353           0 :                 window.setFrameBottomRight(frameData);
     354           0 :                 window.setFrameTopLeft(frameData);
     355           0 :                 window.setFrameTopRight(frameData);
     356           0 :                 window.setFrameMeetingRail(frameData);
     357           0 :                 window.setDividers(dividerData, numHorizDividers, numVertDividers);
     358             : 
     359           0 :                 if (isSummer) {
     360           0 :                     vt = window.vt();
     361           0 :                     shgc = window.shgc();
     362             :                 } else {
     363           0 :                     uvalue = window.uValue();
     364             :                 }
     365          14 :             } else if (vision == EnergyPlus::DataSurfaces::NfrcVisionType::DualVertical) {
     366          14 :                 Tarcog::ISO15099::DualVisionVertical window(windowWidth, windowHeight, tVis, tSol, insulGlassUnit, tVis, tSol, insulGlassUnit);
     367          14 :                 window.setFrameTop(frameData);
     368          14 :                 window.setFrameBottom(frameData);
     369          14 :                 window.setFrameTopLeft(frameData);
     370          14 :                 window.setFrameTopRight(frameData);
     371          14 :                 window.setFrameBottomLeft(frameData);
     372          14 :                 window.setFrameBottomRight(frameData);
     373          14 :                 window.setFrameMeetingRail(frameData);
     374          14 :                 window.setDividers(dividerData, numHorizDividers, numVertDividers);
     375             : 
     376          14 :                 if (isSummer) {
     377           7 :                     vt = window.vt();
     378           7 :                     shgc = window.shgc();
     379             :                 } else {
     380           7 :                     uvalue = window.uValue();
     381             :                 }
     382          14 :             } else {
     383           0 :                 Tarcog::ISO15099::WindowSingleVision window(windowWidth, windowHeight, tVis, tSol, insulGlassUnit);
     384           0 :                 window.setFrameTop(frameData);
     385           0 :                 window.setFrameBottom(frameData);
     386           0 :                 window.setFrameLeft(frameData);
     387           0 :                 window.setFrameRight(frameData);
     388           0 :                 window.setDividers(dividerData, numHorizDividers, numVertDividers);
     389             : 
     390           0 :                 if (isSummer) {
     391           0 :                     vt = window.vt();
     392           0 :                     shgc = window.shgc();
     393             :                 } else {
     394           0 :                     uvalue = window.uValue();
     395             :                 }
     396           0 :             }
     397         844 :         }
     398         422 :     }
     399             : 
     400             :     /////////////////////////////////////////////////////////////////////////////////////////
     401             :     //  CWCEHeatTransferFactory
     402             :     /////////////////////////////////////////////////////////////////////////////////////////
     403             : 
     404        4536 :     CWCEHeatTransferFactory::CWCEHeatTransferFactory(EnergyPlusData &state, SurfaceData const &surface, int const t_SurfNum, int const t_ConstrNum)
     405        4536 :         : m_Surface(surface), m_Window(state.dataSurface->SurfaceWindow(t_SurfNum)), m_ShadePosition(ShadePosition::NoShade), m_SurfNum(t_SurfNum),
     406        4536 :           m_SolidLayerIndex(0), m_ConstructionNumber(t_ConstrNum), m_TotLay(getNumOfLayers(state)), m_InteriorBSDFShade(false), m_ExteriorShade(false)
     407             :     {
     408        7726 :         if (!state.dataConstruction->Construct(m_ConstructionNumber).WindowTypeBSDF &&
     409        3190 :             state.dataSurface->SurfWinShadingFlag.size() >= static_cast<size_t>(m_SurfNum)) {
     410        3190 :             if (ANY_SHADE_SCREEN(state.dataSurface->SurfWinShadingFlag(m_SurfNum)) || ANY_BLIND(state.dataSurface->SurfWinShadingFlag(m_SurfNum))) {
     411        2688 :                 m_ConstructionNumber = state.dataSurface->SurfWinActiveShadedConstruction(m_SurfNum);
     412        2688 :                 m_TotLay = getNumOfLayers(state);
     413             :             }
     414             :         }
     415        4536 :         const WinShadingType ShadeFlag = getShadeType(state, m_ConstructionNumber);
     416             : 
     417        4536 :         if (ANY_INTERIOR_SHADE_BLIND(ShadeFlag)) {
     418        2718 :             m_ShadePosition = ShadePosition::Interior;
     419             :         }
     420             : 
     421        1818 :         else if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
     422           6 :             m_ShadePosition = ShadePosition::Exterior;
     423             :         }
     424             : 
     425        1812 :         else if (ANY_BETWEENGLASS_SHADE_BLIND(ShadeFlag)) {
     426           3 :             m_ShadePosition = ShadePosition::Between;
     427             :         }
     428        4536 :     }
     429             : 
     430             :     /////////////////////////////////////////////////////////////////////////////////////////
     431        4032 :     std::shared_ptr<Tarcog::ISO15099::CSingleSystem> CWCEHeatTransferFactory::getTarcogSystem(EnergyPlusData &state, Real64 const t_HextConvCoeff)
     432             :     {
     433        4032 :         auto Indoor = getIndoor(state);                    // (AUTO_OK_SPTR)
     434        4032 :         auto Outdoor = getOutdoor(state, t_HextConvCoeff); // (AUTO_OK_SPTR)
     435        4032 :         auto aIGU = getIGU();                              // (AUTO_OK_OBJ)
     436             : 
     437             :         // pick-up all layers and put them in IGU (this includes gap layers as well)
     438       13440 :         for (int i = 0; i < m_TotLay; ++i) {
     439        9408 :             auto aLayer = getIGULayer(state, i + 1); // (AUTO_OK_SPTR)
     440        9408 :             assert(aLayer != nullptr);
     441             :             // IDF for "standard" windows do not insert gas between glass and shade. Tarcog needs that gas
     442             :             // and it will be created here
     443        9408 :             if (m_ShadePosition == ShadePosition::Interior && i == m_TotLay - 1) {
     444        2688 :                 auto aAirLayer = getShadeToGlassLayer(state, i + 1); // (AUTO_OK_SPTR)
     445        2688 :                 aIGU.addLayer(aAirLayer);
     446        2688 :             }
     447        9408 :             aIGU.addLayer(aLayer);
     448        9408 :             if (m_ShadePosition == ShadePosition::Exterior && i == 0) {
     449           0 :                 auto aAirLayer = getShadeToGlassLayer(state, i + 1); // (AUTO_OK_SPTR)
     450           0 :                 aIGU.addLayer(aAirLayer);
     451           0 :             }
     452        9408 :         }
     453             : 
     454        8064 :         return std::make_shared<Tarcog::ISO15099::CSingleSystem>(aIGU, Indoor, Outdoor);
     455        4032 :     }
     456             : 
     457        1770 :     std::shared_ptr<Tarcog::ISO15099::IIGUSystem> CWCEHeatTransferFactory::getTarcogSystemForReporting(
     458             :         EnergyPlusData &state, bool const useSummerConditions, const Real64 width, const Real64 height, const Real64 tilt)
     459             :     {
     460        1770 :         auto Indoor = getIndoorNfrc(useSummerConditions);   // (AUTO_OK_SPTR)
     461        1770 :         auto Outdoor = getOutdoorNfrc(useSummerConditions); // (AUTO_OK_SPTR)
     462        1770 :         auto aIGU = getIGU(width, height, tilt);            // (AUTO_OK_OBJ)
     463             : 
     464        1770 :         m_SolidLayerIndex = 0;
     465             :         // pick-up all layers and put them in IGU (this includes gap layers as well)
     466        5876 :         for (int i = 0; i < m_TotLay; ++i) {
     467        4106 :             auto aLayer = getIGULayer(state, i + 1); // (AUTO_OK_SPTR)
     468        4106 :             assert(aLayer != nullptr);
     469             :             // IDF for "standard" windows do not insert gas between glass and shade. Tarcog needs that gas
     470             :             // and it will be created here
     471        4106 :             if (m_ShadePosition == ShadePosition::Interior && i == m_TotLay - 1) {
     472          60 :                 auto aAirLayer = getShadeToGlassLayer(state, i + 1); // (AUTO_OK_SPTR)
     473          60 :                 aIGU.addLayer(aAirLayer);
     474          60 :             }
     475        4106 :             aIGU.addLayer(aLayer);
     476        4106 :             if (m_ShadePosition == ShadePosition::Exterior && i == 0) {
     477          12 :                 auto aAirLayer = getShadeToGlassLayer(state, i + 1); // (AUTO_OK_SPTR)
     478          12 :                 aIGU.addLayer(aAirLayer);
     479          12 :             }
     480        4106 :         }
     481             : 
     482        3540 :         return std::make_shared<Tarcog::ISO15099::CSystem>(aIGU, Indoor, Outdoor);
     483        1770 :     }
     484             : 
     485             :     /////////////////////////////////////////////////////////////////////////////////////////
     486       14930 :     Material::MaterialBase *CWCEHeatTransferFactory::getLayerMaterial(EnergyPlusData &state, int const t_Index) const
     487             :     {
     488       14930 :         int ConstrNum = m_ConstructionNumber;
     489             : 
     490             :         // BSDF window do not have special shading flag
     491       25804 :         if (!state.dataConstruction->Construct(ConstrNum).WindowTypeBSDF &&
     492       10874 :             state.dataSurface->SurfWinShadingFlag.size() >= static_cast<size_t>(m_SurfNum)) {
     493       10874 :             if (ANY_SHADE_SCREEN(state.dataSurface->SurfWinShadingFlag(m_SurfNum)) || ANY_BLIND(state.dataSurface->SurfWinShadingFlag(m_SurfNum))) {
     494        6720 :                 ConstrNum = state.dataSurface->SurfWinActiveShadedConstruction(m_SurfNum);
     495             :             }
     496             :         }
     497             : 
     498       14930 :         auto &construction = state.dataConstruction->Construct(ConstrNum);
     499       14930 :         const int LayPtr = construction.LayerPoint(t_Index);
     500       14930 :         return state.dataMaterial->Material(LayPtr);
     501             :     }
     502             : 
     503             :     /////////////////////////////////////////////////////////////////////////////////////////
     504       13514 :     std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getIGULayer(EnergyPlusData &state, int const t_Index)
     505             :     {
     506       13514 :         std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> aLayer = nullptr;
     507             : 
     508       13514 :         auto *material = getLayerMaterial(state, t_Index);
     509             : 
     510       13514 :         Material::Group matGroup = material->group;
     511             : 
     512       13514 :         if ((matGroup == Material::Group::WindowGlass) || (matGroup == Material::Group::WindowSimpleGlazing) ||
     513        3900 :             (matGroup == Material::Group::WindowBlind) || (matGroup == Material::Group::Shade) || (matGroup == Material::Group::Screen) ||
     514             :             (matGroup == Material::Group::ComplexWindowShade)) {
     515       11038 :             ++m_SolidLayerIndex;
     516       11038 :             aLayer = getSolidLayer(state, material, m_SolidLayerIndex);
     517        2476 :         } else if (matGroup == Material::Group::WindowGas || matGroup == Material::Group::WindowGasMixture) {
     518        1124 :             aLayer = getGapLayer(material);
     519        1352 :         } else if (matGroup == Material::Group::ComplexWindowGap) {
     520        1352 :             aLayer = getComplexGapLayer(state, material);
     521             :         }
     522             : 
     523       13514 :         return aLayer;
     524           0 :     }
     525             : 
     526             :     /////////////////////////////////////////////////////////////////////////////////////////
     527        7224 :     int CWCEHeatTransferFactory::getNumOfLayers(EnergyPlusData &state) const
     528             :     {
     529        7224 :         return state.dataConstruction->Construct(m_ConstructionNumber).TotLayers;
     530             :     }
     531             : 
     532             :     /////////////////////////////////////////////////////////////////////////////////////////
     533             :     std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer>
     534       11038 :     CWCEHeatTransferFactory::getSolidLayer(EnergyPlusData &state, Material::MaterialBase const *materialBase, int const t_Index)
     535             :     {
     536             :         // SUBROUTINE INFORMATION:
     537             :         //       AUTHOR         Simon Vidanovic
     538             :         //       DATE WRITTEN   July 2016
     539             :         //       MODIFIED       na
     540             :         //       RE-ENGINEERED  na
     541             : 
     542             :         // PURPOSE OF THIS SUBROUTINE:
     543             :         // Creates solid layer object from material properties in EnergyPlus
     544       11038 :         Real64 emissFront = 0.0;
     545       11038 :         Real64 emissBack = 0.0;
     546       11038 :         Real64 transThermalFront = 0.0;
     547       11038 :         Real64 transThermalBack = 0.0;
     548       11038 :         Real64 thickness = 0.0;
     549       11038 :         Real64 conductivity = 0.0;
     550       11038 :         Real64 createOpenness = false;
     551       11038 :         Real64 Atop = 0.0;
     552       11038 :         Real64 Abot = 0.0;
     553       11038 :         Real64 Aleft = 0.0;
     554       11038 :         Real64 Aright = 0.0;
     555       11038 :         Real64 Afront = 0.0;
     556             : 
     557       11038 :         auto const *material = dynamic_cast<Material::MaterialChild const *>(materialBase);
     558       11038 :         assert(material != nullptr);
     559       11038 :         if (material->group == Material::Group::WindowGlass || material->group == Material::Group::WindowSimpleGlazing) {
     560        8264 :             emissFront = material->AbsorpThermalFront;
     561        8264 :             emissBack = material->AbsorpThermalBack;
     562        8264 :             transThermalFront = material->TransThermal;
     563        8264 :             transThermalBack = material->TransThermal;
     564        8264 :             thickness = material->Thickness;
     565        8264 :             conductivity = material->Conductivity;
     566             :         }
     567       11038 :         if (material->group == Material::Group::WindowBlind) {
     568        1350 :             int blNum = state.dataSurface->SurfWinBlindNumber(m_SurfNum);
     569        1350 :             auto const &blind = state.dataMaterial->Blind(blNum); // This was plain auto, did you mean to make a copy of blind?
     570        1350 :             thickness = blind.SlatThickness;
     571        1350 :             conductivity = blind.SlatConductivity;
     572        1350 :             Atop = blind.BlindTopOpeningMult;
     573        1350 :             Abot = blind.BlindBottomOpeningMult;
     574        1350 :             Aleft = blind.BlindLeftOpeningMult;
     575        1350 :             Aright = blind.BlindRightOpeningMult;
     576        1350 :             Afront = state.dataSurface->SurfWinBlindAirFlowPermeability(m_SurfNum);
     577        1350 :             emissFront = InterpSlatAng(
     578        1350 :                 state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRFrontEmiss);
     579        1350 :             emissBack = InterpSlatAng(
     580        1350 :                 state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRBackEmiss);
     581        1350 :             transThermalFront = InterpSlatAng(
     582        1350 :                 state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRFrontTrans);
     583        1350 :             transThermalBack = InterpSlatAng(
     584        1350 :                 state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRBackTrans);
     585        1350 :             if (t_Index == 1) {
     586           0 :                 m_ExteriorShade = true;
     587             :             }
     588             :         }
     589       11038 :         if (material->group == Material::Group::Shade) {
     590        1416 :             emissFront = material->AbsorpThermal;
     591        1416 :             emissBack = material->AbsorpThermal;
     592        1416 :             transThermalFront = material->TransThermal;
     593        1416 :             transThermalBack = material->TransThermal;
     594        1416 :             thickness = material->Thickness;
     595        1416 :             conductivity = material->Conductivity;
     596        1416 :             Atop = material->WinShadeTopOpeningMult;
     597        1416 :             Abot = material->WinShadeBottomOpeningMult;
     598        1416 :             Aleft = material->WinShadeLeftOpeningMult;
     599        1416 :             Aright = material->WinShadeRightOpeningMult;
     600        1416 :             Afront = material->WinShadeAirFlowPermeability;
     601        1416 :             if (t_Index == 1) {
     602          12 :                 m_ExteriorShade = true;
     603             :             }
     604             :         }
     605       11038 :         if (material->group == Material::Group::Screen) {
     606             :             // Simon: Existing code already takes into account geometry of Woven and scales down
     607             :             // emissivity for openning area.
     608           0 :             emissFront = material->AbsorpThermal;
     609           0 :             emissBack = material->AbsorpThermal;
     610           0 :             transThermalFront = material->TransThermal;
     611           0 :             transThermalBack = material->TransThermal;
     612           0 :             thickness = material->Thickness;
     613           0 :             conductivity = material->Conductivity;
     614           0 :             Atop = material->WinShadeTopOpeningMult;
     615           0 :             Abot = material->WinShadeBottomOpeningMult;
     616           0 :             Aleft = material->WinShadeLeftOpeningMult;
     617           0 :             Aright = material->WinShadeRightOpeningMult;
     618           0 :             Afront = material->WinShadeAirFlowPermeability;
     619           0 :             if (t_Index == 1) {
     620           0 :                 m_ExteriorShade = true;
     621             :             }
     622             :         }
     623             : 
     624       11038 :         if (material->group == Material::Group::ComplexWindowShade) {
     625           8 :             int shdPtr = material->ComplexShadePtr;
     626           8 :             auto const &shade = state.dataMaterial->ComplexShade(shdPtr);
     627           8 :             thickness = shade.Thickness;
     628           8 :             conductivity = shade.Conductivity;
     629           8 :             emissFront = shade.FrontEmissivity;
     630           8 :             emissBack = shade.BackEmissivity;
     631           8 :             transThermalFront = shade.IRTransmittance;
     632           8 :             transThermalBack = shade.IRTransmittance;
     633           8 :             Afront = shade.FrontOpeningMultiplier;
     634           8 :             Atop = shade.TopOpeningMultiplier;
     635           8 :             Abot = shade.BottomOpeningMultiplier;
     636           8 :             Aleft = shade.LeftOpeningMultiplier;
     637           8 :             Aright = shade.RightOpeningMultiplier;
     638           8 :             createOpenness = true;
     639           8 :             m_InteriorBSDFShade = ((2 * t_Index - 1) == m_TotLay);
     640             :         }
     641             : 
     642       11038 :         std::shared_ptr<Tarcog::ISO15099::ISurface> frontSurface = std::make_shared<Tarcog::ISO15099::CSurface>(emissFront, transThermalFront);
     643       11038 :         std::shared_ptr<Tarcog::ISO15099::ISurface> backSurface = std::make_shared<Tarcog::ISO15099::CSurface>(emissBack, transThermalBack);
     644             :         auto aSolidLayer = // (AUTO_OK_SPTR)
     645       11038 :             std::make_shared<Tarcog::ISO15099::CIGUSolidLayer>(thickness, conductivity, frontSurface, backSurface);
     646       11038 :         if (createOpenness) {
     647           8 :             auto aOpenings = std::make_shared<Tarcog::ISO15099::CShadeOpenings>(Atop, Abot, Aleft, Aright, Afront, Afront); // (AUTO_OK_SPTR)
     648           8 :             aSolidLayer = std::make_shared<Tarcog::ISO15099::CIGUShadeLayer>(aSolidLayer, aOpenings);
     649           8 :         }
     650             :         static constexpr double standardizedRadiationIntensity = 783.0;
     651       11038 :         if (state.dataWindowManager->inExtWindowModel->isExternalLibraryModel()) {
     652        8064 :             auto &surface(state.dataSurface->Surface(m_SurfNum));
     653        8064 :             const int ConstrNum = getActiveConstructionNumber(state, surface, m_SurfNum);
     654             :             std::shared_ptr<MultiLayerOptics::CMultiLayerScattered> aLayer =
     655        8064 :                 CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Solar, ConstrNum);
     656             : 
     657             :             // Report is done for normal incidence
     658        8064 :             constexpr Real64 Theta = 0.0;
     659        8064 :             constexpr Real64 Phi = 0.0;
     660             :             const Real64 absCoeff =
     661        8064 :                 aLayer->getAbsorptanceLayer(t_Index, FenestrationCommon::Side::Front, FenestrationCommon::ScatteringSimple::Diffuse, Theta, Phi);
     662        8064 :             aSolidLayer->setSolarAbsorptance(absCoeff, standardizedRadiationIntensity);
     663        8064 :         } else {
     664        2974 :             const Real64 absCoeff{state.dataConstruction->Construct(state.dataSurface->Surface(m_SurfNum).Construction).AbsDiff(t_Index)};
     665        2974 :             aSolidLayer->setSolarAbsorptance(absCoeff, standardizedRadiationIntensity);
     666             :         }
     667       22076 :         return aSolidLayer;
     668       11038 :     }
     669             : 
     670             :     /////////////////////////////////////////////////////////////////////////////////////////
     671        1124 :     std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getGapLayer(Material::MaterialBase const *material) const
     672             :     {
     673             :         // SUBROUTINE INFORMATION:
     674             :         //       AUTHOR         Simon Vidanovic
     675             :         //       DATE WRITTEN   July 2016
     676             :         //       MODIFIED       na
     677             :         //       RE-ENGINEERED  na
     678             : 
     679             :         // PURPOSE OF THIS SUBROUTINE:
     680             :         // Creates gap layer object from material properties in EnergyPlus
     681        1124 :         Real64 constexpr pres = 1e5; // Old code uses this constant pressure
     682        1124 :         Real64 thickness = material->Thickness;
     683        1124 :         auto aGas = getGas(material); // (AUTO_OK_OBJ)
     684        1124 :         std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> aLayer = std::make_shared<Tarcog::ISO15099::CIGUGapLayer>(thickness, pres, aGas);
     685        2248 :         return aLayer;
     686        1124 :     }
     687             : 
     688             :     /////////////////////////////////////////////////////////////////////////////////////////
     689        2760 :     std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getShadeToGlassLayer(EnergyPlusData &state, int const t_Index) const
     690             :     {
     691             :         // SUBROUTINE INFORMATION:
     692             :         //       AUTHOR         Simon Vidanovic
     693             :         //       DATE WRITTEN   August 2016
     694             :         //       MODIFIED       na
     695             :         //       RE-ENGINEERED  na
     696             : 
     697             :         // PURPOSE OF THIS SUBROUTINE:
     698             :         // Creates gap layer object from material properties in EnergyPlus
     699        2760 :         Real64 constexpr pres = 1e5; // Old code uses this constant pressure
     700        2760 :         auto aGas = getAir();        // (AUTO_OK_OBJ)
     701        2760 :         Real64 thickness = 0.0;
     702             : 
     703        2760 :         const WinShadingType ShadeFlag = getShadeType(state, m_ConstructionNumber);
     704             : 
     705        2760 :         if (ShadeFlag == WinShadingType::IntBlind || ShadeFlag == WinShadingType::ExtBlind) {
     706        1344 :             thickness = state.dataMaterial->Blind(state.dataSurface->SurfWinBlindNumber(m_SurfNum)).BlindToGlassDist;
     707             :         }
     708        2760 :         if (ShadeFlag == WinShadingType::IntShade || ShadeFlag == WinShadingType::ExtShade || ShadeFlag == WinShadingType::ExtScreen) {
     709        1416 :             const auto *material = dynamic_cast<Material::MaterialChild *>(getLayerMaterial(state, t_Index));
     710        1416 :             assert(material != nullptr);
     711        1416 :             thickness = material->WinShadeToGlassDist;
     712             :         }
     713        2760 :         std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> aLayer = std::make_shared<Tarcog::ISO15099::CIGUGapLayer>(thickness, pres, aGas);
     714        5520 :         return aLayer;
     715        2760 :     }
     716             : 
     717             :     /////////////////////////////////////////////////////////////////////////////////////////
     718        1352 :     std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getComplexGapLayer(EnergyPlusData &state,
     719             :                                                                                                  Material::MaterialBase const *materialBase) const
     720             :     {
     721             :         // SUBROUTINE INFORMATION:
     722             :         //       AUTHOR         Simon Vidanovic
     723             :         //       DATE WRITTEN   July 2016
     724             :         //       MODIFIED       na
     725             :         //       RE-ENGINEERED  na
     726             : 
     727             :         // PURPOSE OF THIS SUBROUTINE:
     728             :         // Creates gap layer object from material properties in EnergyPlus
     729        1352 :         Real64 constexpr pres = 1e5; // Old code uses this constant pressure
     730        1352 :         auto const *material = dynamic_cast<Material::MaterialChild const *>(materialBase);
     731        1352 :         assert(material != nullptr);
     732        1352 :         Real64 thickness = material->Thickness;
     733        1352 :         Real64 gasPointer = material->GasPointer;
     734        1352 :         auto *gasMaterial = state.dataMaterial->Material(gasPointer);
     735        1352 :         auto aGas = getGas(gasMaterial); // (AUTO_OK_OBJ)
     736        2704 :         return std::make_shared<Tarcog::ISO15099::CIGUGapLayer>(thickness, pres, aGas);
     737        1352 :     }
     738             : 
     739             :     /////////////////////////////////////////////////////////////////////////////////////////
     740        2476 :     Gases::CGas CWCEHeatTransferFactory::getGas(Material::MaterialBase const *materialBase) const
     741             :     {
     742             :         // SUBROUTINE INFORMATION:
     743             :         //       AUTHOR         Simon Vidanovic
     744             :         //       DATE WRITTEN   July 2016
     745             :         //       MODIFIED       na
     746             :         //       RE-ENGINEERED
     747             :         //          April 2021: April 2021: Return of CGas instead of pointer to it
     748             : 
     749             :         // PURPOSE OF THIS SUBROUTINE:
     750             :         // Creates gap layer object from material properties in EnergyPlus
     751        2476 :         auto const *matGas = dynamic_cast<Material::MaterialGasMix const *>(materialBase);
     752        2476 :         assert(matGas != nullptr);
     753        2476 :         const int numGases = matGas->numGases;
     754        2476 :         double constexpr vacuumCoeff = 1.4; // Load vacuum coefficient once it is implemented (Simon).
     755        2476 :         std::string const &gasName = matGas->Name;
     756        2476 :         Gases::CGas aGas;
     757        4994 :         for (int i = 0; i < numGases; ++i) {
     758        2518 :             auto const &gas = matGas->gases[i];
     759        2518 :             Real64 wght = gas.wght;
     760        2518 :             Real64 fract = matGas->gasFracts[i];
     761        2518 :             Gases::CIntCoeff aCon(gas.con.c0, gas.con.c1, gas.con.c2);
     762        2518 :             Gases::CIntCoeff aCp(gas.cp.c0, gas.cp.c1, gas.cp.c2);
     763        2518 :             Gases::CIntCoeff aVis(gas.vis.c0, gas.vis.c1, gas.vis.c2);
     764        2518 :             Gases::CGasData aData(gasName, wght, vacuumCoeff, aCp, aCon, aVis);
     765        2518 :             aGas.addGasItem(fract, aData);
     766        2518 :         }
     767        2476 :         return aGas;
     768           0 :     }
     769             : 
     770             :     /////////////////////////////////////////////////////////////////////////////////////////
     771        2760 :     Gases::CGas CWCEHeatTransferFactory::getAir()
     772             :     {
     773             :         // SUBROUTINE INFORMATION:
     774             :         //       AUTHOR         Simon Vidanovic
     775             :         //       DATE WRITTEN   August 2016
     776             :         //       MODIFIED       na
     777             :         //       RE-ENGINEERED
     778             :         //          April 2021: CGas return from the function instead of pointer to it
     779             : 
     780             :         // PURPOSE OF THIS SUBROUTINE:
     781             :         // Creates air gas layer for tarcog routines
     782        2760 :         return {};
     783             :     }
     784             : 
     785             :     /////////////////////////////////////////////////////////////////////////////////////////
     786        4032 :     std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getIndoor(EnergyPlusData &state) const
     787             :     {
     788             :         // SUBROUTINE INFORMATION:
     789             :         //       AUTHOR         Simon Vidanovic
     790             :         //       DATE WRITTEN   July 2016
     791             :         //       MODIFIED       na
     792             :         //       RE-ENGINEERED  na
     793             : 
     794             :         // PURPOSE OF THIS SUBROUTINE:
     795             :         // Creates indoor environment object from surface properties in EnergyPlus
     796        4032 :         Real64 tin = m_Surface.getInsideAirTemperature(state, m_SurfNum) + Constant::Kelvin;
     797        4032 :         Real64 hcin = state.dataHeatBalSurf->SurfHConvInt(m_SurfNum);
     798             : 
     799        4032 :         Real64 IR = state.dataSurface->SurfWinIRfromParentZone(m_SurfNum) + state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(m_SurfNum);
     800             : 
     801             :         std::shared_ptr<Tarcog::ISO15099::CEnvironment> Indoor =
     802        4032 :             std::make_shared<Tarcog::ISO15099::CIndoorEnvironment>(tin, state.dataEnvrn->OutBaroPress);
     803        4032 :         Indoor->setHCoeffModel(Tarcog::ISO15099::BoundaryConditionsCoeffModel::CalculateH, hcin);
     804        4032 :         Indoor->setEnvironmentIR(IR);
     805        8064 :         return Indoor;
     806           0 :     }
     807             : 
     808             :     /////////////////////////////////////////////////////////////////////////////////////////
     809        4032 :     std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getOutdoor(EnergyPlusData &state, const Real64 t_Hext) const
     810             :     {
     811             :         // SUBROUTINE INFORMATION:
     812             :         //       AUTHOR         Simon Vidanovic
     813             :         //       DATE WRITTEN   July 2016
     814             :         //       MODIFIED       na
     815             :         //       RE-ENGINEERED  na
     816             : 
     817             :         // PURPOSE OF THIS SUBROUTINE:
     818             :         // Creates outdoor environment object from surface properties in EnergyPlus
     819        4032 :         double tout = m_Surface.getOutsideAirTemperature(state, m_SurfNum) + Constant::Kelvin;
     820        4032 :         double IR = m_Surface.getOutsideIR(state, m_SurfNum);
     821             :         // double dirSolRad = SurfQRadSWOutIncident( t_SurfNum ) + QS( Surface( t_SurfNum ).Zone );
     822        4032 :         double swRadiation = m_Surface.getSWIncident(state, m_SurfNum);
     823        4032 :         double tSky = state.dataEnvrn->SkyTempKelvin;
     824        4032 :         double airSpeed = 0.0;
     825        4032 :         if (m_Surface.ExtWind) {
     826        4032 :             airSpeed = state.dataSurface->SurfOutWindSpeed(m_SurfNum);
     827             :         }
     828        4032 :         double fclr = 1 - state.dataEnvrn->CloudFraction;
     829        4032 :         Tarcog::ISO15099::AirHorizontalDirection airDirection = Tarcog::ISO15099::AirHorizontalDirection::Windward;
     830        8064 :         std::shared_ptr<Tarcog::ISO15099::CEnvironment> Outdoor = std::make_shared<Tarcog::ISO15099::COutdoorEnvironment>(
     831        4032 :             tout, airSpeed, swRadiation, airDirection, tSky, Tarcog::ISO15099::SkyModel::AllSpecified, state.dataEnvrn->OutBaroPress, fclr);
     832        4032 :         Outdoor->setHCoeffModel(Tarcog::ISO15099::BoundaryConditionsCoeffModel::HcPrescribed, t_Hext);
     833        4032 :         Outdoor->setEnvironmentIR(IR);
     834        8064 :         return Outdoor;
     835           0 :     }
     836             : 
     837             :     /////////////////////////////////////////////////////////////////////////////////////////
     838        4032 :     Tarcog::ISO15099::CIGU CWCEHeatTransferFactory::getIGU() const
     839             :     {
     840             :         // SUBROUTINE INFORMATION:
     841             :         //       AUTHOR         Simon Vidanovic
     842             :         //       DATE WRITTEN   July 2016
     843             :         //       MODIFIED       na
     844             :         //       RE-ENGINEERED
     845             :         //          April 2021: Return CIGU object rather than pointer to it
     846             : 
     847             :         // PURPOSE OF THIS SUBROUTINE:
     848             :         // Creates IGU object from surface properties in EnergyPlus
     849             : 
     850        4032 :         return {m_Surface.Width, m_Surface.Height, m_Surface.Tilt};
     851             :     }
     852             : 
     853        1770 :     Tarcog::ISO15099::CIGU CWCEHeatTransferFactory::getIGU(double width, double height, double tilt)
     854             :     {
     855             :         // SUBROUTINE INFORMATION:
     856             :         //       AUTHOR         Simon Vidanovic
     857             :         //       DATE WRITTEN   November 2021
     858             :         //       MODIFIED       na
     859             :         //       RE-ENGINEERED
     860             :         //          April 2021: Return CIGU object rather than pointer to it
     861             : 
     862             :         // PURPOSE OF THIS SUBROUTINE:
     863             :         // Creates IGU object for given width, height and tilt
     864             : 
     865        1770 :         return {width, height, tilt};
     866             :     }
     867             : 
     868             :     int
     869       12096 :     CWCEHeatTransferFactory::getActiveConstructionNumber(EnergyPlusData &state, EnergyPlus::DataSurfaces::SurfaceData const &surface, int t_SurfNum)
     870             :     {
     871       12096 :         int result = surface.Construction;
     872       12096 :         const WinShadingType ShadeFlag = state.dataSurface->SurfWinShadingFlag(t_SurfNum);
     873             : 
     874       12096 :         if (ANY_SHADE_SCREEN(ShadeFlag) || ANY_BLIND(ShadeFlag)) {
     875        8064 :             result = state.dataSurface->SurfWinActiveShadedConstruction(t_SurfNum);
     876             :         }
     877             : 
     878       12096 :         return result;
     879             :     }
     880             : 
     881             :     /////////////////////////////////////////////////////////////////////////////////////////
     882        1344 :     bool CWCEHeatTransferFactory::isInteriorShade() const
     883             :     {
     884        1344 :         return m_InteriorBSDFShade;
     885             :     }
     886             : 
     887        1770 :     std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getOutdoorNfrc(bool const useSummerConditions)
     888             :     {
     889             :         // NFRC 100 Section 4.3.1
     890        1770 :         Real64 airTemperature = -18.0 + Constant::Kelvin; // Kelvins
     891        1770 :         Real64 airSpeed = 5.5;                            // meters per second
     892        1770 :         Real64 tSky = -18.0 + Constant::Kelvin;           // Kelvins
     893        1770 :         Real64 solarRadiation = 0.;                       // W/m2
     894        1770 :         if (useSummerConditions) {
     895             :             // NFRC 200 Section 4.3.1
     896         463 :             airTemperature = 32.0 + Constant::Kelvin;
     897         463 :             airSpeed = 2.75;
     898         463 :             tSky = 32.0 + Constant::Kelvin;
     899         463 :             solarRadiation = 783.;
     900             :         }
     901             :         auto Outdoor = // (AUTO_OK_SPTR)
     902        1770 :             Tarcog::ISO15099::Environments::outdoor(airTemperature, airSpeed, solarRadiation, tSky, Tarcog::ISO15099::SkyModel::AllSpecified);
     903        1770 :         Outdoor->setHCoeffModel(Tarcog::ISO15099::BoundaryConditionsCoeffModel::CalculateH);
     904        3540 :         return Outdoor;
     905        1770 :     }
     906             : 
     907        1770 :     std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getIndoorNfrc(bool const useSummerConditions)
     908             :     {
     909             :         // NFRC 100 Section 4.3.1
     910        1770 :         Real64 roomTemperature = 21. + Constant::Kelvin;
     911        1770 :         if (useSummerConditions) {
     912             :             // NFRC 200 Section 4.3.1
     913         463 :             roomTemperature = 24. + Constant::Kelvin;
     914             :         }
     915        1770 :         return Tarcog::ISO15099::Environments::indoor(roomTemperature);
     916             :     }
     917             : 
     918        7296 :     WinShadingType CWCEHeatTransferFactory::getShadeType(EnergyPlusData &state, int ConstrNum)
     919             :     {
     920        7296 :         WinShadingType ShadeFlag = WinShadingType::NoShade;
     921             : 
     922        7296 :         const int TotLay = state.dataConstruction->Construct(ConstrNum).TotLayers;
     923        7296 :         const int TotGlassLay = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
     924        7296 :         const int MatOutside = state.dataConstruction->Construct(ConstrNum).LayerPoint(1);
     925        7296 :         const int MatInside = state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLay);
     926             : 
     927        7296 :         if (state.dataMaterial->Material(MatOutside)->group == Material::Group::Shade) { // Exterior shade present
     928          18 :             ShadeFlag = WinShadingType::ExtShade;
     929        7278 :         } else if (state.dataMaterial->Material(MatOutside)->group == Material::Group::Screen) { // Exterior screen present
     930           0 :             ShadeFlag = WinShadingType::ExtScreen;
     931        7278 :         } else if (state.dataMaterial->Material(MatOutside)->group == Material::Group::WindowBlind) { // Exterior blind present
     932           0 :             ShadeFlag = WinShadingType::ExtBlind;
     933        7278 :         } else if (state.dataMaterial->Material(MatInside)->group == Material::Group::Shade) { // Interior shade present
     934        2778 :             ShadeFlag = WinShadingType::IntShade;
     935        4500 :         } else if (state.dataMaterial->Material(MatInside)->group == Material::Group::WindowBlind) { // Interior blind present
     936        2688 :             ShadeFlag = WinShadingType::IntBlind;
     937        1812 :         } else if (TotGlassLay == 2) {
     938        1645 :             if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(3))->group == Material::Group::Shade)
     939           0 :                 ShadeFlag = WinShadingType::BGShade;
     940        1645 :             if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(3))->group == Material::Group::WindowBlind)
     941           3 :                 ShadeFlag = WinShadingType::BGBlind;
     942         167 :         } else if (TotGlassLay == 3) {
     943           2 :             if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(5))->group == Material::Group::Shade)
     944           0 :                 ShadeFlag = WinShadingType::BGShade;
     945           2 :             if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(5))->group == Material::Group::WindowBlind)
     946           0 :                 ShadeFlag = WinShadingType::BGBlind;
     947             :         }
     948             : 
     949        7296 :         return ShadeFlag;
     950             :     }
     951             : 
     952        1688 :     double CWCEHeatTransferFactory::overallUfactorFromFilmsAndCond(double conductance, double insideFilm, double outsideFilm)
     953             :     {
     954        1688 :         double rOverall(0.);
     955        1688 :         double uFactor(0.);
     956        1688 :         if (insideFilm != 0 && outsideFilm != 0. && conductance != 0.) {
     957         532 :             rOverall = 1 / insideFilm + 1 / conductance + 1 / outsideFilm;
     958             :         }
     959        1688 :         if (rOverall != 0.) {
     960         532 :             uFactor = 1 / rOverall;
     961             :         }
     962        1688 :         return uFactor;
     963             :     }
     964             : 
     965             : } // namespace Window
     966             : } // namespace EnergyPlus

Generated by: LCOV version 1.14