LCOV - code coverage report
Current view: top level - EnergyPlus - WindowManagerExteriorThermal.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 456 513 88.9 %
Date: 2023-01-17 19:17:23 Functions: 28 28 100.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // EnergyPlus headers
      49             : #include <EnergyPlus/BITF.hh>
      50             : #include <EnergyPlus/Construction.hh>
      51             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      52             : #include <EnergyPlus/DataEnvironment.hh>
      53             : #include <EnergyPlus/DataHeatBalSurface.hh>
      54             : #include <EnergyPlus/DataHeatBalance.hh>
      55             : #include <EnergyPlus/DataSurfaces.hh>
      56             : #include <EnergyPlus/General.hh>
      57             : #include <EnergyPlus/Material.hh>
      58             : #include <EnergyPlus/UtilityRoutines.hh>
      59             : #include <EnergyPlus/WindowManager.hh>
      60             : 
      61             : // Windows library headers
      62             : #include <WCEMultiLayerOptics.hpp>
      63             : #include <WCETarcog.hpp>
      64             : 
      65             : // EnergyPlus headers
      66             : #include <EnergyPlus/WindowManagerExteriorThermal.hh>
      67             : 
      68             : namespace EnergyPlus {
      69             : 
      70             : using namespace DataEnvironment;
      71             : using namespace DataSurfaces;
      72             : using namespace DataHeatBalance;
      73             : using namespace General;
      74             : 
      75             : namespace WindowManager {
      76             : 
      77             :     /////////////////////////////////////////////////////////////////////////////////////////
      78        4032 :     void CalcWindowHeatBalanceExternalRoutines(EnergyPlusData &state,
      79             :                                                int const SurfNum,          // Surface number
      80             :                                                Real64 const HextConvCoeff, // Outside air film conductance coefficient
      81             :                                                Real64 &SurfInsideTemp,     // Inside window surface temperature
      82             :                                                Real64 &SurfOutsideTemp     // Outside surface temperature (C)
      83             :     )
      84             :     {
      85             :         // SUBROUTINE INFORMATION:
      86             :         //       AUTHOR         Simon Vidanovic
      87             :         //       DATE WRITTEN   July 2016
      88             :         //       MODIFIED       na
      89             :         //       RE-ENGINEERED  na
      90             : 
      91             :         // PURPOSE OF THIS SUBROUTINE:
      92             :         // Main wrapper routine to pick-up data from EnergyPlus and then call Windows-CalcEngine routines
      93             :         // to obtain results
      94             : 
      95        4032 :         auto &window(state.dataSurface->SurfaceWindow(SurfNum));
      96        4032 :         auto &surface(state.dataSurface->Surface(SurfNum));
      97        4032 :         auto ConstrNum = surface.Construction;
      98        4032 :         auto &construction(state.dataConstruction->Construct(ConstrNum));
      99             : 
     100        4032 :         auto const solutionTolerance = 0.02;
     101             : 
     102             :         // Tarcog thermal system for solving heat transfer through the window
     103        4032 :         const auto activeConstrNum{CWCEHeatTransferFactory::getActiveConstructionNumber(state, surface, SurfNum)};
     104        8064 :         auto aFactory = CWCEHeatTransferFactory(state, surface, SurfNum, activeConstrNum);
     105        8064 :         auto aSystem = aFactory.getTarcogSystem(state, HextConvCoeff);
     106        4032 :         aSystem->setTolerance(solutionTolerance);
     107             : 
     108             :         // get previous timestep temperatures solution for faster iterations
     109        8064 :         std::vector<Real64> Guess;
     110        4032 :         auto totSolidLayers = construction.TotSolidLayers;
     111             : 
     112             :         // Interior and exterior shading layers have gas between them and IGU but that gas
     113             :         // was not part of construction so it needs to be increased by one
     114        4032 :         if (ANY_SHADE_SCREEN(state.dataSurface->SurfWinShadingFlag(SurfNum)) || ANY_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
     115        2688 :             ++totSolidLayers;
     116             :         }
     117             : 
     118       20160 :         for (auto k = 1; k <= 2 * totSolidLayers; ++k) {
     119       16128 :             Guess.push_back(state.dataSurface->SurfaceWindow(SurfNum).ThetaFace(k));
     120             :         }
     121             : 
     122             :         try {
     123        4032 :             aSystem->setInitialGuess(Guess);
     124        4032 :             aSystem->solve();
     125           0 :         } catch (const std::exception &ex) {
     126           0 :             ShowSevereError(state, "Error in Windows Calculation Engine Exterior Module.");
     127           0 :             ShowContinueError(state, ex.what());
     128             :         }
     129             : 
     130        8064 :         auto aLayers = aSystem->getSolidLayers();
     131        4032 :         auto i = 1;
     132       12096 :         for (const auto &aLayer : aLayers) {
     133        8064 :             Real64 aTemp = 0;
     134       24192 :             for (auto aSide : FenestrationCommon::EnumSide()) {
     135       16128 :                 aTemp = aLayer->getTemperature(aSide);
     136       16128 :                 state.dataWindowManager->thetas[i - 1] = aTemp;
     137       16128 :                 if (i == 1) {
     138        4032 :                     SurfOutsideTemp = aTemp - DataGlobalConstants::KelvinConv;
     139             :                 }
     140       16128 :                 ++i;
     141             :             }
     142        8064 :             SurfInsideTemp = aTemp - DataGlobalConstants::KelvinConv;
     143        8064 :             if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum))) {
     144             :                 Real64 EffShBlEmiss;
     145             :                 Real64 EffGlEmiss;
     146        5376 :                 if (state.dataSurface->SurfWinMovableSlats(SurfNum)) {
     147           0 :                     EffShBlEmiss =
     148           0 :                         General::InterpGeneral(window.EffShBlindEmiss(state.dataSurface->SurfWinSlatsAngIndex(SurfNum)),
     149           0 :                                                window.EffShBlindEmiss(std::min(MaxSlatAngs, state.dataSurface->SurfWinSlatsAngIndex(SurfNum) + 1)),
     150           0 :                                                state.dataSurface->SurfWinSlatsAngInterpFac(SurfNum));
     151           0 :                     EffGlEmiss =
     152           0 :                         General::InterpGeneral(window.EffGlassEmiss(state.dataSurface->SurfWinSlatsAngIndex(SurfNum)),
     153           0 :                                                window.EffGlassEmiss(std::min(MaxSlatAngs, state.dataSurface->SurfWinSlatsAngIndex(SurfNum) + 1)),
     154           0 :                                                state.dataSurface->SurfWinSlatsAngInterpFac(SurfNum));
     155             :                 } else {
     156        5376 :                     EffShBlEmiss = state.dataSurface->SurfaceWindow(SurfNum).EffShBlindEmiss(1);
     157        5376 :                     EffGlEmiss = state.dataSurface->SurfaceWindow(SurfNum).EffGlassEmiss(1);
     158             :                 }
     159        5376 :                 state.dataSurface->SurfWinEffInsSurfTemp(SurfNum) =
     160       10752 :                     (EffShBlEmiss * SurfInsideTemp +
     161       16128 :                      EffGlEmiss * (state.dataWindowManager->thetas[2 * totSolidLayers - 3] - state.dataWindowManager->TKelvin)) /
     162        5376 :                     (EffShBlEmiss + EffGlEmiss);
     163             :             }
     164             :         }
     165             : 
     166        4032 :         state.dataHeatBalSurf->SurfHConvInt(SurfNum) = aSystem->getHc(Tarcog::ISO15099::Environment::Indoor);
     167        4032 :         if (ANY_INTERIOR_SHADE_BLIND(state.dataSurface->SurfWinShadingFlag(SurfNum)) || aFactory.isInteriorShade()) {
     168             :             // It is not clear why EnergyPlus keeps this interior calculations separately for interior shade. This does create different
     169             :             // solution from heat transfer from tarcog itself. Need to confirm with LBNL team about this approach. Note that heat flow
     170             :             // through shade (consider case when openings are zero) is different from heat flow obtained by these equations. Will keep
     171             :             // these calculations just to confirm that current exterior engine is giving close results to what is in here. (Simon)
     172        2688 :             auto totLayers = aLayers.size();
     173        2688 :             state.dataWindowManager->nglface = 2 * totLayers - 2;
     174        2688 :             state.dataWindowManager->nglfacep = state.dataWindowManager->nglface + 2;
     175        5376 :             auto aShadeLayer = aLayers[totLayers - 1];
     176        5376 :             auto aGlassLayer = aLayers[totLayers - 2];
     177        2688 :             auto ShadeArea = state.dataSurface->Surface(SurfNum).Area + state.dataSurface->SurfWinDividerArea(SurfNum);
     178        5376 :             auto frontSurface = aShadeLayer->getSurface(FenestrationCommon::Side::Front);
     179        5376 :             auto backSurface = aShadeLayer->getSurface(FenestrationCommon::Side::Back);
     180        2688 :             auto EpsShIR1 = frontSurface->getEmissivity();
     181        2688 :             auto EpsShIR2 = backSurface->getEmissivity();
     182        2688 :             auto TauShIR = frontSurface->getTransmittance();
     183        2688 :             auto RhoShIR1 = max(0.0, 1.0 - TauShIR - EpsShIR1);
     184        2688 :             auto RhoShIR2 = max(0.0, 1.0 - TauShIR - EpsShIR2);
     185        2688 :             auto glassEmiss = aGlassLayer->getSurface(FenestrationCommon::Side::Back)->getEmissivity();
     186        2688 :             auto RhoGlIR2 = 1.0 - glassEmiss;
     187        2688 :             auto ShGlReflFacIR = 1.0 - RhoGlIR2 * RhoShIR1;
     188        2688 :             auto rmir = state.dataSurface->SurfWinIRfromParentZone(SurfNum) + state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(SurfNum);
     189             :             auto NetIRHeatGainShade =
     190        5376 :                 ShadeArea * EpsShIR2 *
     191        5376 :                     (state.dataWindowManager->sigma * pow(state.dataWindowManager->thetas[state.dataWindowManager->nglfacep - 1], 4) - rmir) +
     192        5376 :                 EpsShIR1 * (state.dataWindowManager->sigma * pow(state.dataWindowManager->thetas[state.dataWindowManager->nglfacep - 2], 4) - rmir) *
     193        2688 :                     RhoGlIR2 * TauShIR / ShGlReflFacIR;
     194             :             auto NetIRHeatGainGlass =
     195        2688 :                 ShadeArea * (glassEmiss * TauShIR / ShGlReflFacIR) *
     196        5376 :                 (state.dataWindowManager->sigma * pow(state.dataWindowManager->thetas[state.dataWindowManager->nglface - 1], 4) - rmir);
     197        2688 :             auto tind = surface.getInsideAirTemperature(state, SurfNum) + DataGlobalConstants::KelvinConv;
     198        2688 :             auto ConvHeatGainFrZoneSideOfShade = ShadeArea * state.dataHeatBalSurf->SurfHConvInt(SurfNum) *
     199        2688 :                                                  (state.dataWindowManager->thetas[state.dataWindowManager->nglfacep - 1] - tind);
     200        2688 :             state.dataSurface->SurfWinHeatGain(SurfNum) =
     201        2688 :                 state.dataSurface->SurfWinTransSolar(SurfNum) + ConvHeatGainFrZoneSideOfShade + NetIRHeatGainGlass + NetIRHeatGainShade;
     202             : 
     203        2688 :             state.dataSurface->SurfWinGainIRGlazToZoneRep(SurfNum) = NetIRHeatGainGlass;
     204             : 
     205             :             // Effective shade and glass emissivities that are used later for energy calculations.
     206             :             // This needs to be checked as well. (Simon)
     207        2688 :             auto EffShBlEmiss = EpsShIR1 * (1.0 + RhoGlIR2 * TauShIR / (1.0 - RhoGlIR2 * RhoShIR2));
     208        2688 :             state.dataSurface->SurfaceWindow(SurfNum).EffShBlindEmiss = EffShBlEmiss;
     209             : 
     210        2688 :             auto EffGlEmiss = glassEmiss * TauShIR / (1.0 - RhoGlIR2 * RhoShIR2);
     211        2688 :             state.dataSurface->SurfaceWindow(SurfNum).EffGlassEmiss = EffGlEmiss;
     212             : 
     213        2688 :             auto glassTemperature = aGlassLayer->getSurface(FenestrationCommon::Side::Back)->getTemperature();
     214        2688 :             state.dataSurface->SurfWinEffInsSurfTemp(SurfNum) =
     215        2688 :                 (EffShBlEmiss * SurfInsideTemp + EffGlEmiss * (glassTemperature - DataGlobalConstants::KelvinConv)) / (EffShBlEmiss + EffGlEmiss);
     216             : 
     217             :         } else {
     218             :             // Another adoptation to old source that looks suspicious. Check if heat flow through
     219             :             // window is actually matching these values. (Simon)
     220             : 
     221             :             //
     222        1344 :             auto totLayers = aLayers.size();
     223        2688 :             auto aGlassLayer = aLayers[totLayers - 1];
     224        2688 :             auto backSurface = aGlassLayer->getSurface(FenestrationCommon::Side::Back);
     225             : 
     226        1344 :             auto h_cin = aSystem->getHc(Tarcog::ISO15099::Environment::Indoor);
     227             :             auto ConvHeatGainFrZoneSideOfGlass =
     228        1344 :                 surface.Area * h_cin * (backSurface->getTemperature() - aSystem->getAirTemperature(Tarcog::ISO15099::Environment::Indoor));
     229             : 
     230        1344 :             auto rmir = state.dataSurface->SurfWinIRfromParentZone(SurfNum) + state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(SurfNum);
     231             :             auto NetIRHeatGainGlass =
     232        1344 :                 surface.Area * backSurface->getEmissivity() * (state.dataWindowManager->sigma * pow(backSurface->getTemperature(), 4) - rmir);
     233             : 
     234        1344 :             state.dataSurface->SurfWinEffInsSurfTemp(SurfNum) =
     235        1344 :                 aLayers[totLayers - 1]->getTemperature(FenestrationCommon::Side::Back) - state.dataWindowManager->TKelvin;
     236        2688 :             state.dataSurface->SurfaceWindow(SurfNum).EffGlassEmiss =
     237        4032 :                 aLayers[totLayers - 1]->getSurface(FenestrationCommon::Side::Back)->getEmissivity();
     238             : 
     239        1344 :             state.dataSurface->SurfWinHeatGain(SurfNum) =
     240        1344 :                 state.dataSurface->SurfWinTransSolar(SurfNum) + ConvHeatGainFrZoneSideOfGlass + NetIRHeatGainGlass;
     241        1344 :             state.dataSurface->SurfWinGainConvGlazToZoneRep(SurfNum) = ConvHeatGainFrZoneSideOfGlass;
     242        1344 :             state.dataSurface->SurfWinGainIRGlazToZoneRep(SurfNum) = NetIRHeatGainGlass;
     243             :         }
     244             : 
     245        4032 :         auto TransDiff = construction.TransDiff;
     246        4032 :         state.dataSurface->SurfWinLossSWZoneToOutWinRep(SurfNum) =
     247        4032 :             state.dataHeatBal->EnclSolQSWRad(state.dataSurface->Surface(SurfNum).SolarEnclIndex) * surface.Area * TransDiff;
     248        4032 :         state.dataSurface->SurfWinHeatGain(SurfNum) -= state.dataSurface->SurfWinLossSWZoneToOutWinRep(SurfNum);
     249             : 
     250       10752 :         for (auto k = 1; k <= surface.getTotLayers(state); ++k) {
     251        6720 :             state.dataSurface->SurfaceWindow(SurfNum).ThetaFace(2 * k - 1) = state.dataWindowManager->thetas[2 * k - 2];
     252        6720 :             state.dataSurface->SurfaceWindow(SurfNum).ThetaFace(2 * k) = state.dataWindowManager->thetas[2 * k - 1];
     253             : 
     254             :             // temperatures for reporting
     255        6720 :             state.dataHeatBal->SurfWinFenLaySurfTempFront(SurfNum, k) = state.dataWindowManager->thetas[2 * k - 2] - DataGlobalConstants::KelvinConv;
     256        6720 :             state.dataHeatBal->SurfWinFenLaySurfTempBack(SurfNum, k) = state.dataWindowManager->thetas[2 * k - 1] - DataGlobalConstants::KelvinConv;
     257             :         }
     258        4032 :     }
     259             : 
     260             :     Real64
     261          41 :     GetIGUUValueForNFRCReport(EnergyPlusData &state, const int surfNum, const int constrNum, const Real64 windowWidth, const Real64 windowHeight)
     262             :     {
     263          41 :         const auto tilt{90.0};
     264             : 
     265          41 :         auto &surface(state.dataSurface->Surface(surfNum));
     266          82 :         auto aFactory = CWCEHeatTransferFactory(state, surface, surfNum, constrNum);
     267             : 
     268          82 :         const auto winterGlassUnit = aFactory.getTarcogSystemForReporting(state, false, windowWidth, windowHeight, tilt);
     269             : 
     270          82 :         return winterGlassUnit->getUValue();
     271             :     }
     272             : 
     273          41 :     Real64 GetSHGCValueForNFRCReporting(EnergyPlusData &state, int surfNum, int constrNum, Real64 windowWidth, Real64 windowHeight)
     274             :     {
     275          41 :         const auto tilt{90.0};
     276             : 
     277          41 :         auto &surface(state.dataSurface->Surface(surfNum));
     278          82 :         auto aFactory = CWCEHeatTransferFactory(state, surface, surfNum, constrNum);
     279             : 
     280          82 :         const auto summerGlassUnit = aFactory.getTarcogSystemForReporting(state, true, windowWidth, windowHeight, tilt);
     281          82 :         return summerGlassUnit->getSHGC(state.dataConstruction->Construct(surface.Construction).SolTransNorm);
     282             :     }
     283             : 
     284         422 :     void GetWindowAssemblyNfrcForReport(EnergyPlusData &state,
     285             :                                         int const surfNum,
     286             :                                         int constrNum,
     287             :                                         Real64 windowWidth,
     288             :                                         Real64 windowHeight,
     289             :                                         EnergyPlus::DataSurfaces::NfrcVisionType vision,
     290             :                                         Real64 &uvalue,
     291             :                                         Real64 &shgc,
     292             :                                         Real64 &vt)
     293             :     {
     294         422 :         auto &surface(state.dataSurface->Surface(surfNum));
     295         422 :         auto &frameDivider(state.dataSurface->FrameDivider(surface.FrameDivider));
     296             : 
     297         844 :         auto aFactory = CWCEHeatTransferFactory(state, surface, surfNum, constrNum);
     298             : 
     299        1266 :         for (bool isSummer : {false, true}) {
     300         844 :             constexpr auto framehExtConvCoeff{30.0};
     301         844 :             constexpr auto framehIntConvCoeff{8.0};
     302         844 :             const auto tilt{90.0};
     303             : 
     304        1688 :             auto insulGlassUnit = aFactory.getTarcogSystemForReporting(state, isSummer, windowWidth, windowHeight, tilt);
     305             : 
     306         844 :             const double centerOfGlassUvalue = insulGlassUnit->getUValue();
     307             : 
     308        1688 :             auto winterGlassUnit = aFactory.getTarcogSystemForReporting(state, false, windowWidth, windowHeight, tilt);
     309             : 
     310         844 :             const double frameUvalue = aFactory.overallUfactorFromFilmsAndCond(frameDivider.FrameConductance, framehIntConvCoeff, framehExtConvCoeff);
     311         844 :             const double frameEdgeUValue{winterGlassUnit->getUValue() * frameDivider.FrEdgeToCenterGlCondRatio}; // not sure about this
     312         844 :             const double frameProjectedDimension{frameDivider.FrameWidth};
     313         844 :             const double frameWettedLength{frameProjectedDimension + frameDivider.FrameProjectionIn};
     314         844 :             const double frameAbsorptance{frameDivider.FrameSolAbsorp};
     315             : 
     316         844 :             Tarcog::ISO15099::FrameData frameData{frameUvalue, frameEdgeUValue, frameProjectedDimension, frameWettedLength, frameAbsorptance};
     317             : 
     318             :             const double dividerUvalue =
     319         844 :                 aFactory.overallUfactorFromFilmsAndCond(frameDivider.DividerConductance, framehIntConvCoeff, framehExtConvCoeff);
     320         844 :             const double dividerEdgeUValue{centerOfGlassUvalue * frameDivider.DivEdgeToCenterGlCondRatio}; // not sure about this
     321         844 :             const double dividerProjectedDimension{frameDivider.DividerWidth};
     322         844 :             const double dividerWettedLength{dividerProjectedDimension + frameDivider.DividerProjectionIn};
     323         844 :             const double dividerAbsorptance{frameDivider.DividerSolAbsorp};
     324         844 :             const int numHorizDividers{frameDivider.HorDividers};
     325         844 :             const int numVertDividers{frameDivider.VertDividers};
     326             : 
     327             :             Tarcog::ISO15099::FrameData dividerData{
     328         844 :                 dividerUvalue, dividerEdgeUValue, dividerProjectedDimension, dividerWettedLength, dividerAbsorptance};
     329             : 
     330         844 :             const auto tVis{state.dataConstruction->Construct(constrNum).VisTransNorm};
     331         844 :             const auto tSol{state.dataConstruction->Construct(constrNum).SolTransNorm};
     332             : 
     333         844 :             if (vision == EnergyPlus::DataSurfaces::NfrcVisionType::Single) {
     334        1660 :                 auto window = Tarcog::ISO15099::WindowSingleVision(windowWidth, windowHeight, tVis, tSol, insulGlassUnit);
     335         830 :                 window.setFrameTop(frameData);
     336         830 :                 window.setFrameBottom(frameData);
     337         830 :                 window.setFrameLeft(frameData);
     338         830 :                 window.setFrameRight(frameData);
     339         830 :                 window.setDividers(dividerData, numHorizDividers, numVertDividers);
     340             : 
     341         830 :                 if (isSummer) {
     342         415 :                     vt = window.vt();
     343         415 :                     shgc = window.shgc();
     344             :                 } else {
     345         415 :                     uvalue = window.uValue();
     346             :                 }
     347          14 :             } else if (vision == EnergyPlus::DataSurfaces::NfrcVisionType::DualHorizontal) {
     348             :                 auto window =
     349           0 :                     Tarcog::ISO15099::DualVisionHorizontal(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          28 :                 auto window = Tarcog::ISO15099::DualVisionVertical(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             :             } else {
     383           0 :                 auto window = Tarcog::ISO15099::WindowSingleVision(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             :             }
     397             :         }
     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        9072 :           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 auto ShadeFlag{getShadeType(state, m_ConstructionNumber)};
     416             : 
     417        4536 :         if (ANY_INTERIOR_SHADE_BLIND(ShadeFlag)) {
     418        2718 :             m_ShadePosition = ShadePosition::Interior;
     419             :         }
     420             : 
     421        4536 :         if (ANY_EXTERIOR_SHADE_BLIND_SCREEN(ShadeFlag)) {
     422           6 :             m_ShadePosition = ShadePosition::Exterior;
     423             :         }
     424             : 
     425        4536 :         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        8064 :         auto Indoor = getIndoor(state);
     434        8064 :         auto Outdoor = getOutdoor(state, t_HextConvCoeff);
     435        8064 :         auto aIGU = getIGU();
     436             : 
     437             :         // pick-up all layers and put them in IGU (this includes gap layers as well)
     438       13440 :         for (auto i = 0; i < m_TotLay; ++i) {
     439       18816 :             auto aLayer = getIGULayer(state, i + 1);
     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        5376 :                 auto aAirLayer = getShadeToGlassLayer(state, i + 1);
     445        2688 :                 aIGU.addLayer(aAirLayer);
     446             :             }
     447        9408 :             aIGU.addLayer(aLayer);
     448        9408 :             if (m_ShadePosition == ShadePosition::Exterior && i == 0) {
     449           0 :                 auto aAirLayer = getShadeToGlassLayer(state, i + 1);
     450           0 :                 aIGU.addLayer(aAirLayer);
     451             :             }
     452             :         }
     453             : 
     454        4032 :         auto aSystem = std::make_shared<Tarcog::ISO15099::CSingleSystem>(aIGU, Indoor, Outdoor);
     455             : 
     456        8064 :         return aSystem;
     457             :     }
     458             : 
     459        1770 :     std::shared_ptr<Tarcog::ISO15099::IIGUSystem> CWCEHeatTransferFactory::getTarcogSystemForReporting(
     460             :         EnergyPlusData &state, bool const useSummerConditions, const Real64 width, const Real64 height, const Real64 tilt)
     461             :     {
     462        3540 :         auto Indoor = getIndoorNfrc(useSummerConditions);
     463        3540 :         auto Outdoor = getOutdoorNfrc(useSummerConditions);
     464        3540 :         auto aIGU = getIGU(width, height, tilt);
     465             : 
     466        1770 :         m_SolidLayerIndex = 0;
     467             :         // pick-up all layers and put them in IGU (this includes gap layers as well)
     468        5876 :         for (auto i = 0; i < m_TotLay; ++i) {
     469        8212 :             auto aLayer = getIGULayer(state, i + 1);
     470        4106 :             assert(aLayer != nullptr);
     471             :             // IDF for "standard" windows do not insert gas between glass and shade. Tarcog needs that gas
     472             :             // and it will be created here
     473        4106 :             if (m_ShadePosition == ShadePosition::Interior && i == m_TotLay - 1) {
     474         120 :                 auto aAirLayer = getShadeToGlassLayer(state, i + 1);
     475          60 :                 aIGU.addLayer(aAirLayer);
     476             :             }
     477        4106 :             aIGU.addLayer(aLayer);
     478        4106 :             if (m_ShadePosition == ShadePosition::Exterior && i == 0) {
     479          24 :                 auto aAirLayer = getShadeToGlassLayer(state, i + 1);
     480          12 :                 aIGU.addLayer(aAirLayer);
     481             :             }
     482             :         }
     483             : 
     484        3540 :         return std::make_shared<Tarcog::ISO15099::CSystem>(aIGU, Indoor, Outdoor);
     485             :     }
     486             : 
     487             :     /////////////////////////////////////////////////////////////////////////////////////////
     488       14930 :     Material::MaterialProperties *CWCEHeatTransferFactory::getLayerMaterial(EnergyPlusData &state, int const t_Index) const
     489             :     {
     490       14930 :         auto ConstrNum = m_ConstructionNumber;
     491             : 
     492             :         // BSDF window do not have special shading flag
     493       25804 :         if (!state.dataConstruction->Construct(ConstrNum).WindowTypeBSDF &&
     494       10874 :             state.dataSurface->SurfWinShadingFlag.size() >= static_cast<size_t>(m_SurfNum)) {
     495       10874 :             if (ANY_SHADE_SCREEN(state.dataSurface->SurfWinShadingFlag(m_SurfNum)) || ANY_BLIND(state.dataSurface->SurfWinShadingFlag(m_SurfNum))) {
     496        6720 :                 ConstrNum = state.dataSurface->SurfWinActiveShadedConstruction(m_SurfNum);
     497             :             }
     498             :         }
     499             : 
     500       14930 :         auto &construction(state.dataConstruction->Construct(ConstrNum));
     501       14930 :         const auto LayPtr = construction.LayerPoint(t_Index);
     502       14930 :         return &state.dataMaterial->Material(LayPtr);
     503             :     }
     504             : 
     505             :     /////////////////////////////////////////////////////////////////////////////////////////
     506       13514 :     std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getIGULayer(EnergyPlusData &state, int const t_Index)
     507             :     {
     508       13514 :         std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> aLayer = nullptr;
     509             : 
     510       13514 :         auto material = getLayerMaterial(state, t_Index);
     511             : 
     512       13514 :         auto matGroup = material->Group;
     513             : 
     514       13514 :         if (BITF_TEST_ANY(BITF(matGroup),
     515             :                           BITF(DataHeatBalance::MaterialGroup::WindowGlass) | BITF(DataHeatBalance::MaterialGroup::WindowSimpleGlazing) |
     516             :                               BITF(DataHeatBalance::MaterialGroup::WindowBlind) | BITF(DataHeatBalance::MaterialGroup::Shade) |
     517             :                               BITF(DataHeatBalance::MaterialGroup::Screen) | BITF(DataHeatBalance::MaterialGroup::ComplexWindowShade))) {
     518       11038 :             ++m_SolidLayerIndex;
     519       11038 :             aLayer = getSolidLayer(state, *material, m_SolidLayerIndex);
     520        2476 :         } else if (matGroup == DataHeatBalance::MaterialGroup::WindowGas || matGroup == DataHeatBalance::MaterialGroup::WindowGasMixture) {
     521        1124 :             aLayer = getGapLayer(*material);
     522        1352 :         } else if (matGroup == DataHeatBalance::MaterialGroup::ComplexWindowGap) {
     523        1352 :             aLayer = getComplexGapLayer(state, *material);
     524             :         }
     525             : 
     526       13514 :         return aLayer;
     527             :     }
     528             : 
     529             :     /////////////////////////////////////////////////////////////////////////////////////////
     530        7224 :     int CWCEHeatTransferFactory::getNumOfLayers(EnergyPlusData &state) const
     531             :     {
     532        7224 :         return state.dataConstruction->Construct(m_ConstructionNumber).TotLayers;
     533             :     }
     534             : 
     535             :     /////////////////////////////////////////////////////////////////////////////////////////
     536             :     std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer>
     537       11038 :     CWCEHeatTransferFactory::getSolidLayer(EnergyPlusData &state, Material::MaterialProperties const &material, int const t_Index)
     538             :     {
     539             :         // SUBROUTINE INFORMATION:
     540             :         //       AUTHOR         Simon Vidanovic
     541             :         //       DATE WRITTEN   July 2016
     542             :         //       MODIFIED       na
     543             :         //       RE-ENGINEERED  na
     544             : 
     545             :         // PURPOSE OF THIS SUBROUTINE:
     546             :         // Creates solid layer object from material properties in EnergyPlus
     547       11038 :         auto emissFront = 0.0;
     548       11038 :         auto emissBack = 0.0;
     549       11038 :         auto transThermalFront = 0.0;
     550       11038 :         auto transThermalBack = 0.0;
     551       11038 :         auto thickness = 0.0;
     552       11038 :         auto conductivity = 0.0;
     553       11038 :         auto createOpenness = false;
     554       11038 :         auto Atop = 0.0;
     555       11038 :         auto Abot = 0.0;
     556       11038 :         auto Aleft = 0.0;
     557       11038 :         auto Aright = 0.0;
     558       11038 :         auto Afront = 0.0;
     559             : 
     560       11038 :         if (material.Group == DataHeatBalance::MaterialGroup::WindowGlass || material.Group == DataHeatBalance::MaterialGroup::WindowSimpleGlazing) {
     561        8264 :             emissFront = material.AbsorpThermalFront;
     562        8264 :             emissBack = material.AbsorpThermalBack;
     563        8264 :             transThermalFront = material.TransThermal;
     564        8264 :             transThermalBack = material.TransThermal;
     565        8264 :             thickness = material.Thickness;
     566        8264 :             conductivity = material.Conductivity;
     567             :         }
     568       11038 :         if (material.Group == DataHeatBalance::MaterialGroup::WindowBlind) {
     569        1350 :             auto blNum = state.dataSurface->SurfWinBlindNumber(m_SurfNum);
     570        2700 :             auto blind = state.dataHeatBal->Blind(blNum);
     571        1350 :             thickness = blind.SlatThickness;
     572        1350 :             conductivity = blind.SlatConductivity;
     573        1350 :             Atop = blind.BlindTopOpeningMult;
     574        1350 :             Abot = blind.BlindBottomOpeningMult;
     575        1350 :             Aleft = blind.BlindLeftOpeningMult;
     576        1350 :             Aright = blind.BlindRightOpeningMult;
     577        1350 :             Afront = state.dataSurface->SurfWinBlindAirFlowPermeability(m_SurfNum);
     578        4050 :             emissFront = InterpSlatAng(
     579        2700 :                 state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRFrontEmiss);
     580        4050 :             emissBack = InterpSlatAng(
     581        2700 :                 state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRBackEmiss);
     582        4050 :             transThermalFront = InterpSlatAng(
     583        2700 :                 state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRFrontTrans);
     584        4050 :             transThermalBack = InterpSlatAng(
     585        2700 :                 state.dataSurface->SurfWinSlatAngThisTS(m_SurfNum), state.dataSurface->SurfWinMovableSlats(m_SurfNum), blind.IRBackTrans);
     586        1350 :             if (t_Index == 1) {
     587           0 :                 m_ExteriorShade = true;
     588             :             }
     589             :         }
     590       11038 :         if (material.Group == DataHeatBalance::MaterialGroup::Shade) {
     591        1416 :             emissFront = material.AbsorpThermal;
     592        1416 :             emissBack = material.AbsorpThermal;
     593        1416 :             transThermalFront = material.TransThermal;
     594        1416 :             transThermalBack = material.TransThermal;
     595        1416 :             thickness = material.Thickness;
     596        1416 :             conductivity = material.Conductivity;
     597        1416 :             Atop = material.WinShadeTopOpeningMult;
     598        1416 :             Abot = material.WinShadeBottomOpeningMult;
     599        1416 :             Aleft = material.WinShadeLeftOpeningMult;
     600        1416 :             Aright = material.WinShadeRightOpeningMult;
     601        1416 :             Afront = material.WinShadeAirFlowPermeability;
     602        1416 :             if (t_Index == 1) {
     603          12 :                 m_ExteriorShade = true;
     604             :             }
     605             :         }
     606       11038 :         if (material.Group == DataHeatBalance::MaterialGroup::Screen) {
     607             :             // Simon: Existing code already takes into account geometry of Woven and scales down
     608             :             // emissivity for openning area.
     609           0 :             emissFront = material.AbsorpThermal;
     610           0 :             emissBack = material.AbsorpThermal;
     611           0 :             transThermalFront = material.TransThermal;
     612           0 :             transThermalBack = material.TransThermal;
     613           0 :             thickness = material.Thickness;
     614           0 :             conductivity = material.Conductivity;
     615           0 :             Atop = material.WinShadeTopOpeningMult;
     616           0 :             Abot = material.WinShadeBottomOpeningMult;
     617           0 :             Aleft = material.WinShadeLeftOpeningMult;
     618           0 :             Aright = material.WinShadeRightOpeningMult;
     619           0 :             Afront = material.WinShadeAirFlowPermeability;
     620           0 :             if (t_Index == 1) {
     621           0 :                 m_ExteriorShade = true;
     622             :             }
     623             :         }
     624       11038 :         if (material.Group == DataHeatBalance::MaterialGroup::ComplexWindowShade) {
     625           8 :             auto shdPtr = material.ComplexShadePtr;
     626           8 :             auto &shade(state.dataHeatBal->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       22076 :         std::shared_ptr<Tarcog::ISO15099::ISurface> frontSurface = std::make_shared<Tarcog::ISO15099::CSurface>(emissFront, transThermalFront);
     643       22076 :         std::shared_ptr<Tarcog::ISO15099::ISurface> backSurface = std::make_shared<Tarcog::ISO15099::CSurface>(emissBack, transThermalBack);
     644       22076 :         auto aSolidLayer = std::make_shared<Tarcog::ISO15099::CIGUSolidLayer>(thickness, conductivity, frontSurface, backSurface);
     645       11038 :         if (createOpenness) {
     646          16 :             auto aOpenings = std::make_shared<Tarcog::ISO15099::CShadeOpenings>(Atop, Abot, Aleft, Aright, Afront, Afront);
     647           8 :             aSolidLayer = std::make_shared<Tarcog::ISO15099::CIGUShadeLayer>(aSolidLayer, aOpenings);
     648             :         }
     649             :         static constexpr double standardizedRadiationIntensity{783.0};
     650       11038 :         if (state.dataWindowManager->inExtWindowModel->isExternalLibraryModel()) {
     651        8064 :             auto &surface(state.dataSurface->Surface(m_SurfNum));
     652        8064 :             const auto ConstrNum{getActiveConstructionNumber(state, surface, m_SurfNum)};
     653             :             std::shared_ptr<MultiLayerOptics::CMultiLayerScattered> aLayer =
     654       16128 :                 CWindowConstructionsSimplified::instance().getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Solar, ConstrNum);
     655             : 
     656             :             // Report is done for normal incidence
     657        8064 :             const auto Theta{0.0};
     658        8064 :             const auto Phi{0.0};
     659             :             const auto absCoeff =
     660        8064 :                 aLayer->getAbsorptanceLayer(t_Index, FenestrationCommon::Side::Front, FenestrationCommon::ScatteringSimple::Diffuse, Theta, Phi);
     661        8064 :             aSolidLayer->setSolarAbsorptance(absCoeff, standardizedRadiationIntensity);
     662             :         } else {
     663        2974 :             const auto absCoeff{state.dataConstruction->Construct(state.dataSurface->Surface(m_SurfNum).Construction).AbsDiff(t_Index)};
     664        2974 :             aSolidLayer->setSolarAbsorptance(absCoeff, standardizedRadiationIntensity);
     665             :         }
     666       22076 :         return aSolidLayer;
     667             :     }
     668             : 
     669             :     /////////////////////////////////////////////////////////////////////////////////////////
     670        1124 :     std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getGapLayer(Material::MaterialProperties const &material) const
     671             :     {
     672             :         // SUBROUTINE INFORMATION:
     673             :         //       AUTHOR         Simon Vidanovic
     674             :         //       DATE WRITTEN   July 2016
     675             :         //       MODIFIED       na
     676             :         //       RE-ENGINEERED  na
     677             : 
     678             :         // PURPOSE OF THIS SUBROUTINE:
     679             :         // Creates gap layer object from material properties in EnergyPlus
     680        1124 :         auto const pres = 1e5; // Old code uses this constant pressure
     681        1124 :         auto thickness = material.Thickness;
     682        2248 :         auto aGas = getGas(material);
     683        1124 :         std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> aLayer = std::make_shared<Tarcog::ISO15099::CIGUGapLayer>(thickness, pres, aGas);
     684        2248 :         return aLayer;
     685             :     }
     686             : 
     687             :     /////////////////////////////////////////////////////////////////////////////////////////
     688        2760 :     std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getShadeToGlassLayer(EnergyPlusData &state, int const t_Index) const
     689             :     {
     690             :         // SUBROUTINE INFORMATION:
     691             :         //       AUTHOR         Simon Vidanovic
     692             :         //       DATE WRITTEN   August 2016
     693             :         //       MODIFIED       na
     694             :         //       RE-ENGINEERED  na
     695             : 
     696             :         // PURPOSE OF THIS SUBROUTINE:
     697             :         // Creates gap layer object from material properties in EnergyPlus
     698        2760 :         auto const pres = 1e5; // Old code uses this constant pressure
     699        5520 :         auto aGas = getAir();
     700        2760 :         auto thickness = 0.0;
     701             : 
     702        2760 :         const auto ShadeFlag{getShadeType(state, m_ConstructionNumber)};
     703             : 
     704        2760 :         if (ShadeFlag == WinShadingType::IntBlind || ShadeFlag == WinShadingType::ExtBlind) {
     705        1344 :             thickness = state.dataHeatBal->Blind(state.dataSurface->SurfWinBlindNumber(m_SurfNum)).BlindToGlassDist;
     706             :         }
     707        2760 :         if (ShadeFlag == WinShadingType::IntShade || ShadeFlag == WinShadingType::ExtShade || ShadeFlag == WinShadingType::ExtScreen) {
     708        1416 :             const auto material = getLayerMaterial(state, t_Index);
     709        1416 :             thickness = material->WinShadeToGlassDist;
     710             :         }
     711        2760 :         std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> aLayer = std::make_shared<Tarcog::ISO15099::CIGUGapLayer>(thickness, pres, aGas);
     712        5520 :         return aLayer;
     713             :     }
     714             : 
     715             :     /////////////////////////////////////////////////////////////////////////////////////////
     716        1352 :     std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> CWCEHeatTransferFactory::getComplexGapLayer(EnergyPlusData &state,
     717             :                                                                                                  Material::MaterialProperties const &material) const
     718             :     {
     719             :         // SUBROUTINE INFORMATION:
     720             :         //       AUTHOR         Simon Vidanovic
     721             :         //       DATE WRITTEN   July 2016
     722             :         //       MODIFIED       na
     723             :         //       RE-ENGINEERED  na
     724             : 
     725             :         // PURPOSE OF THIS SUBROUTINE:
     726             :         // Creates gap layer object from material properties in EnergyPlus
     727        1352 :         auto const pres = 1e5; // Old code uses this constant pressure
     728        1352 :         auto thickness = material.Thickness;
     729        1352 :         auto gasPointer = material.GasPointer;
     730        1352 :         auto &gasMaterial(state.dataMaterial->Material(gasPointer));
     731        2704 :         auto aGas = getGas(gasMaterial);
     732        1352 :         std::shared_ptr<Tarcog::ISO15099::CBaseIGULayer> aLayer = std::make_shared<Tarcog::ISO15099::CIGUGapLayer>(thickness, pres, aGas);
     733        2704 :         return aLayer;
     734             :     }
     735             : 
     736             :     /////////////////////////////////////////////////////////////////////////////////////////
     737        2476 :     Gases::CGas CWCEHeatTransferFactory::getGas(Material::MaterialProperties const &material) const
     738             :     {
     739             :         // SUBROUTINE INFORMATION:
     740             :         //       AUTHOR         Simon Vidanovic
     741             :         //       DATE WRITTEN   July 2016
     742             :         //       MODIFIED       na
     743             :         //       RE-ENGINEERED
     744             :         //          April 2021: April 2021: Return of CGas instead of pointer to it
     745             : 
     746             :         // PURPOSE OF THIS SUBROUTINE:
     747             :         // Creates gap layer object from material properties in EnergyPlus
     748        2476 :         const auto numGases = material.NumberOfGasesInMixture;
     749        2476 :         auto const vacuumCoeff = 1.4; // Load vacuum coefficient once it is implemented (Simon).
     750        4952 :         const auto gasName = material.Name;
     751        2476 :         Gases::CGas aGas;
     752        4994 :         for (auto i = 1; i <= numGases; ++i) {
     753        2518 :             auto wght = material.GasWght(i);
     754        2518 :             auto fract = material.GasFract(i);
     755        5036 :             std::vector<double> gcon;
     756        5036 :             std::vector<double> gvis;
     757        5036 :             std::vector<double> gcp;
     758       10072 :             for (auto j = 1; j <= 3; ++j) {
     759        7554 :                 gcon.push_back(material.GasCon(j, i));
     760        7554 :                 gvis.push_back(material.GasVis(j, i));
     761        7554 :                 gcp.push_back(material.GasCp(j, i));
     762             :             }
     763        2518 :             auto aCon = Gases::CIntCoeff(gcon[0], gcon[1], gcon[2]);
     764        2518 :             auto aCp = Gases::CIntCoeff(gcp[0], gcp[1], gcp[2]);
     765        2518 :             auto aVis = Gases::CIntCoeff(gvis[0], gvis[1], gvis[2]);
     766        5036 :             auto aData = Gases::CGasData(gasName, wght, vacuumCoeff, aCp, aCon, aVis);
     767        2518 :             aGas.addGasItem(fract, aData);
     768             :         }
     769        4952 :         return aGas;
     770             :     }
     771             : 
     772             :     /////////////////////////////////////////////////////////////////////////////////////////
     773        2760 :     Gases::CGas CWCEHeatTransferFactory::getAir()
     774             :     {
     775             :         // SUBROUTINE INFORMATION:
     776             :         //       AUTHOR         Simon Vidanovic
     777             :         //       DATE WRITTEN   August 2016
     778             :         //       MODIFIED       na
     779             :         //       RE-ENGINEERED
     780             :         //          April 2021: CGas return from the function instead of pointer to it
     781             : 
     782             :         // PURPOSE OF THIS SUBROUTINE:
     783             :         // Creates air gas layer for tarcog routines
     784        2760 :         return {};
     785             :     }
     786             : 
     787             :     /////////////////////////////////////////////////////////////////////////////////////////
     788        4032 :     std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getIndoor(EnergyPlusData &state) const
     789             :     {
     790             :         // SUBROUTINE INFORMATION:
     791             :         //       AUTHOR         Simon Vidanovic
     792             :         //       DATE WRITTEN   July 2016
     793             :         //       MODIFIED       na
     794             :         //       RE-ENGINEERED  na
     795             : 
     796             :         // PURPOSE OF THIS SUBROUTINE:
     797             :         // Creates indoor environment object from surface properties in EnergyPlus
     798        4032 :         auto tin = m_Surface.getInsideAirTemperature(state, m_SurfNum) + DataGlobalConstants::KelvinConv;
     799        4032 :         auto hcin = state.dataHeatBalSurf->SurfHConvInt(m_SurfNum);
     800             : 
     801        4032 :         auto IR = state.dataSurface->SurfWinIRfromParentZone(m_SurfNum) + state.dataHeatBalSurf->SurfQdotRadHVACInPerArea(m_SurfNum);
     802             : 
     803             :         std::shared_ptr<Tarcog::ISO15099::CEnvironment> Indoor =
     804        4032 :             std::make_shared<Tarcog::ISO15099::CIndoorEnvironment>(tin, state.dataEnvrn->OutBaroPress);
     805        4032 :         Indoor->setHCoeffModel(Tarcog::ISO15099::BoundaryConditionsCoeffModel::CalculateH, hcin);
     806        4032 :         Indoor->setEnvironmentIR(IR);
     807        4032 :         return Indoor;
     808             :     }
     809             : 
     810             :     /////////////////////////////////////////////////////////////////////////////////////////
     811        4032 :     std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getOutdoor(EnergyPlusData &state, const Real64 t_Hext) const
     812             :     {
     813             :         // SUBROUTINE INFORMATION:
     814             :         //       AUTHOR         Simon Vidanovic
     815             :         //       DATE WRITTEN   July 2016
     816             :         //       MODIFIED       na
     817             :         //       RE-ENGINEERED  na
     818             : 
     819             :         // PURPOSE OF THIS SUBROUTINE:
     820             :         // Creates outdoor environment object from surface properties in EnergyPlus
     821        4032 :         double tout = m_Surface.getOutsideAirTemperature(state, m_SurfNum) + DataGlobalConstants::KelvinConv;
     822        4032 :         double IR = m_Surface.getOutsideIR(state, m_SurfNum);
     823             :         // double dirSolRad = SurfQRadSWOutIncident( t_SurfNum ) + QS( Surface( t_SurfNum ).Zone );
     824        4032 :         double swRadiation = m_Surface.getSWIncident(state, m_SurfNum);
     825        4032 :         double tSky = state.dataEnvrn->SkyTempKelvin;
     826        4032 :         double airSpeed = 0.0;
     827        4032 :         if (m_Surface.ExtWind) {
     828        4032 :             airSpeed = state.dataSurface->SurfOutWindSpeed(m_SurfNum);
     829             :         }
     830        4032 :         double fclr = 1 - state.dataEnvrn->CloudFraction;
     831        4032 :         Tarcog::ISO15099::AirHorizontalDirection airDirection = Tarcog::ISO15099::AirHorizontalDirection::Windward;
     832        8064 :         std::shared_ptr<Tarcog::ISO15099::CEnvironment> Outdoor = std::make_shared<Tarcog::ISO15099::COutdoorEnvironment>(
     833        8064 :             tout, airSpeed, swRadiation, airDirection, tSky, Tarcog::ISO15099::SkyModel::AllSpecified, state.dataEnvrn->OutBaroPress, fclr);
     834        4032 :         Outdoor->setHCoeffModel(Tarcog::ISO15099::BoundaryConditionsCoeffModel::HcPrescribed, t_Hext);
     835        4032 :         Outdoor->setEnvironmentIR(IR);
     836        4032 :         return Outdoor;
     837             :     }
     838             : 
     839             :     /////////////////////////////////////////////////////////////////////////////////////////
     840        4032 :     Tarcog::ISO15099::CIGU CWCEHeatTransferFactory::getIGU() const
     841             :     {
     842             :         // SUBROUTINE INFORMATION:
     843             :         //       AUTHOR         Simon Vidanovic
     844             :         //       DATE WRITTEN   July 2016
     845             :         //       MODIFIED       na
     846             :         //       RE-ENGINEERED
     847             :         //          April 2021: Return CIGU object rather than pointer to it
     848             : 
     849             :         // PURPOSE OF THIS SUBROUTINE:
     850             :         // Creates IGU object from surface properties in EnergyPlus
     851             : 
     852        4032 :         return {m_Surface.Width, m_Surface.Height, m_Surface.Tilt};
     853             :     }
     854             : 
     855        1770 :     Tarcog::ISO15099::CIGU CWCEHeatTransferFactory::getIGU(double width, double height, double tilt)
     856             :     {
     857             :         // SUBROUTINE INFORMATION:
     858             :         //       AUTHOR         Simon Vidanovic
     859             :         //       DATE WRITTEN   November 2021
     860             :         //       MODIFIED       na
     861             :         //       RE-ENGINEERED
     862             :         //          April 2021: Return CIGU object rather than pointer to it
     863             : 
     864             :         // PURPOSE OF THIS SUBROUTINE:
     865             :         // Creates IGU object for given width, height and tilt
     866             : 
     867        1770 :         return {width, height, tilt};
     868             :     }
     869             : 
     870             :     int
     871       12096 :     CWCEHeatTransferFactory::getActiveConstructionNumber(EnergyPlusData &state, EnergyPlus::DataSurfaces::SurfaceData const &surface, int t_SurfNum)
     872             :     {
     873       12096 :         auto result{surface.Construction};
     874       12096 :         const auto ShadeFlag = state.dataSurface->SurfWinShadingFlag(t_SurfNum);
     875             : 
     876       12096 :         if (ANY_SHADE_SCREEN(ShadeFlag) || ANY_BLIND(ShadeFlag)) {
     877        8064 :             result = state.dataSurface->SurfWinActiveShadedConstruction(t_SurfNum);
     878             :         }
     879             : 
     880       12096 :         return result;
     881             :     }
     882             : 
     883             :     /////////////////////////////////////////////////////////////////////////////////////////
     884        1344 :     bool CWCEHeatTransferFactory::isInteriorShade() const
     885             :     {
     886        1344 :         return m_InteriorBSDFShade;
     887             :     }
     888             : 
     889        1770 :     std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getOutdoorNfrc(bool const useSummerConditions)
     890             :     {
     891             :         // NFRC 100 Section 4.3.1
     892        1770 :         auto airTemperature{-18.0 + DataGlobalConstants::KelvinConv}; // Kelvins
     893        1770 :         auto airSpeed{5.5};                                           // meters per second
     894        1770 :         auto tSky{-18.0 + DataGlobalConstants::KelvinConv};           // Kelvins
     895        1770 :         auto solarRadiation{0.};                                      // W/m2
     896        1770 :         if (useSummerConditions) {
     897             :             // NFRC 200 Section 4.3.1
     898         463 :             airTemperature = 32.0 + DataGlobalConstants::KelvinConv;
     899         463 :             airSpeed = 2.75;
     900         463 :             tSky = 32.0 + DataGlobalConstants::KelvinConv;
     901         463 :             solarRadiation = 783.;
     902             :         }
     903             :         auto Outdoor =
     904        3540 :             Tarcog::ISO15099::Environments::outdoor(airTemperature, airSpeed, solarRadiation, tSky, Tarcog::ISO15099::SkyModel::AllSpecified);
     905        1770 :         Outdoor->setHCoeffModel(Tarcog::ISO15099::BoundaryConditionsCoeffModel::CalculateH);
     906        3540 :         return Outdoor;
     907             :     }
     908             : 
     909        1770 :     std::shared_ptr<Tarcog::ISO15099::CEnvironment> CWCEHeatTransferFactory::getIndoorNfrc(bool const useSummerConditions)
     910             :     {
     911             :         // NFRC 100 Section 4.3.1
     912        1770 :         auto roomTemperature{21. + DataGlobalConstants::KelvinConv};
     913        1770 :         if (useSummerConditions) {
     914             :             // NFRC 200 Section 4.3.1
     915         463 :             roomTemperature = 24. + DataGlobalConstants::KelvinConv;
     916             :         }
     917        3540 :         auto Indoor = Tarcog::ISO15099::Environments::indoor(roomTemperature);
     918        3540 :         return Indoor;
     919             :     }
     920             : 
     921        7296 :     WinShadingType CWCEHeatTransferFactory::getShadeType(EnergyPlusData &state, int ConstrNum)
     922             :     {
     923        7296 :         WinShadingType ShadeFlag{WinShadingType::NoShade};
     924             : 
     925        7296 :         const auto TotLay = state.dataConstruction->Construct(ConstrNum).TotLayers;
     926        7296 :         const auto TotGlassLay = state.dataConstruction->Construct(ConstrNum).TotGlassLayers;
     927        7296 :         const auto MatOutside = state.dataConstruction->Construct(ConstrNum).LayerPoint(1);
     928        7296 :         const auto MatInside = state.dataConstruction->Construct(ConstrNum).LayerPoint(TotLay);
     929             : 
     930        7296 :         if (state.dataMaterial->Material(MatOutside).Group == DataHeatBalance::MaterialGroup::Shade) { // Exterior shade present
     931          18 :             ShadeFlag = WinShadingType::ExtShade;
     932        7278 :         } else if (state.dataMaterial->Material(MatOutside).Group == DataHeatBalance::MaterialGroup::Screen) { // Exterior screen present
     933           0 :             const auto MatShade = MatOutside;
     934           0 :             const auto ScNum = state.dataMaterial->Material(MatShade).ScreenDataPtr;
     935             :             // Orphaned constructs with exterior screen are ignored
     936           0 :             if (ScNum > 0) ShadeFlag = WinShadingType::ExtScreen;
     937        7278 :         } else if (state.dataMaterial->Material(MatOutside).Group == DataHeatBalance::MaterialGroup::WindowBlind) { // Exterior blind present
     938           0 :             ShadeFlag = WinShadingType::ExtBlind;
     939        7278 :         } else if (state.dataMaterial->Material(MatInside).Group == DataHeatBalance::MaterialGroup::Shade) { // Interior shade present
     940        2778 :             ShadeFlag = WinShadingType::IntShade;
     941        4500 :         } else if (state.dataMaterial->Material(MatInside).Group == DataHeatBalance::MaterialGroup::WindowBlind) { // Interior blind present
     942        2688 :             ShadeFlag = WinShadingType::IntBlind;
     943        1812 :         } else if (TotGlassLay == 2) {
     944        1645 :             if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(3)).Group ==
     945             :                 DataHeatBalance::MaterialGroup::Shade)
     946           0 :                 ShadeFlag = WinShadingType::BGShade;
     947        1645 :             if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(3)).Group ==
     948             :                 DataHeatBalance::MaterialGroup::WindowBlind)
     949           3 :                 ShadeFlag = WinShadingType::BGBlind;
     950         167 :         } else if (TotGlassLay == 3) {
     951           2 :             if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(5)).Group ==
     952             :                 DataHeatBalance::MaterialGroup::Shade)
     953           0 :                 ShadeFlag = WinShadingType::BGShade;
     954           2 :             if (state.dataMaterial->Material(state.dataConstruction->Construct(ConstrNum).LayerPoint(5)).Group ==
     955             :                 DataHeatBalance::MaterialGroup::WindowBlind)
     956           0 :                 ShadeFlag = WinShadingType::BGBlind;
     957             :         }
     958             : 
     959        7296 :         return ShadeFlag;
     960             :     }
     961             : 
     962        1688 :     double CWCEHeatTransferFactory::overallUfactorFromFilmsAndCond(double conductance, double insideFilm, double outsideFilm)
     963             :     {
     964        1688 :         double rOverall(0.);
     965        1688 :         double uFactor(0.);
     966        1688 :         if (insideFilm != 0 && outsideFilm != 0. && conductance != 0.) {
     967         532 :             rOverall = 1 / insideFilm + 1 / conductance + 1 / outsideFilm;
     968             :         }
     969        1688 :         if (rOverall != 0.) {
     970         532 :             uFactor = 1 / rOverall;
     971             :         }
     972        1688 :         return uFactor;
     973             :     }
     974             : 
     975             : } // namespace WindowManager
     976        2313 : } // namespace EnergyPlus

Generated by: LCOV version 1.13