LCOV - code coverage report
Current view: top level - EnergyPlus - WindowManagerExteriorOptical.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 60.8 % 301 183
Test Date: 2025-05-22 16:09:37 Functions: 73.8 % 42 31

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : #include <cassert>
      49              : 
      50              : // EnergyPlus headers
      51              : #include <EnergyPlus/Construction.hh>
      52              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      53              : #include <EnergyPlus/DataEnvironment.hh>
      54              : #include <EnergyPlus/DataHeatBalance.hh>
      55              : #include <EnergyPlus/DataSurfaces.hh>
      56              : #include <EnergyPlus/Material.hh>
      57              : #include <EnergyPlus/WindowManager.hh>
      58              : 
      59              : // Windows library headers
      60              : #include <WCEMultiLayerOptics.hpp>
      61              : 
      62              : #include "WindowManagerExteriorData.hh"
      63              : #include "WindowManagerExteriorOptical.hh"
      64              : 
      65              : namespace EnergyPlus {
      66              : 
      67              : using namespace FenestrationCommon;
      68              : using namespace SpectralAveraging;
      69              : using namespace SingleLayerOptics;
      70              : 
      71              : using namespace DataEnvironment;
      72              : using namespace DataSurfaces;
      73              : using namespace DataHeatBalance;
      74              : namespace Window {
      75              : 
      76            0 :     std::shared_ptr<CBSDFLayer> getBSDFLayer(EnergyPlusData &state, const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
      77              :     {
      78              :         // SUBROUTINE INFORMATION:
      79              :         //       AUTHOR         Simon Vidanovic
      80              :         //       DATE WRITTEN   September 2016
      81              :         //       MODIFIED       na
      82              :         //       RE-ENGINEERED  na
      83              : 
      84              :         // PURPOSE OF THIS SUBROUTINE:
      85              :         // BSDF will be created in different ways that is based on material type
      86              : 
      87            0 :         std::shared_ptr<CWCELayerFactory> aFactory = nullptr;
      88            0 :         if (t_Material->group == Material::Group::Glass) {
      89            0 :             aFactory = std::make_shared<CWCESpecularLayerFactory>(t_Material, t_Range);
      90            0 :         } else if (t_Material->group == Material::Group::Blind) {
      91            0 :             aFactory = std::make_shared<CWCEVenetianBlindLayerFactory>(t_Material, t_Range);
      92            0 :         } else if (t_Material->group == Material::Group::Screen) {
      93            0 :             aFactory = std::make_shared<CWCEScreenLayerFactory>(t_Material, t_Range);
      94            0 :         } else if (t_Material->group == Material::Group::Shade) {
      95            0 :             aFactory = std::make_shared<CWCEDiffuseShadeLayerFactory>(t_Material, t_Range);
      96              :         }
      97            0 :         return aFactory->getBSDFLayer(state);
      98            0 :     }
      99              : 
     100           12 :     CScatteringLayer getScatteringLayer(EnergyPlusData &state, const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     101              :     {
     102              :         // SUBROUTINE INFORMATION:
     103              :         //       AUTHOR         Simon Vidanovic
     104              :         //       DATE WRITTEN   May 2017
     105              :         //       MODIFIED       na
     106              :         //       RE-ENGINEERED
     107              :         //          April 2021: returning CScatteringLayer instead of pointer to it
     108              : 
     109              :         // PURPOSE OF THIS SUBROUTINE:
     110              :         // Scattering will be created in different ways that is based on material type
     111              : 
     112           12 :         std::shared_ptr<CWCELayerFactory> aFactory = nullptr;
     113           12 :         if (t_Material->group == Material::Group::Glass || t_Material->group == Material::Group::GlassSimple) {
     114            8 :             aFactory = std::make_shared<CWCESpecularLayerFactory>(t_Material, t_Range);
     115            4 :         } else if (t_Material->group == Material::Group::Blind) {
     116            2 :             aFactory = std::make_shared<CWCEVenetianBlindLayerFactory>(t_Material, t_Range);
     117            2 :         } else if (t_Material->group == Material::Group::Screen) {
     118            0 :             aFactory = std::make_shared<CWCEScreenLayerFactory>(t_Material, t_Range);
     119            2 :         } else if (t_Material->group == Material::Group::Shade) {
     120            2 :             aFactory = std::make_shared<CWCEDiffuseShadeLayerFactory>(t_Material, t_Range);
     121              :         }
     122           24 :         return aFactory->getLayer(state);
     123           12 :     }
     124              : 
     125              :     // void InitWCE_BSDFOpticalData() {
     126              :     //     // SUBROUTINE INFORMATION:
     127              :     //     //       AUTHOR         Simon Vidanovic
     128              :     //     //       DATE WRITTEN   September 2016
     129              :     //     //       MODIFIED       na
     130              :     //     //       RE-ENGINEERED  na
     131              :     //
     132              :     //     // PURPOSE OF THIS SUBROUTINE:
     133              :     //     // Initialize BSDF construction layers in Solar and Visible spectrum.
     134              :     //
     135              :     //     auto aWinConstBSDF = CWindowConstructionsBSDF::instance();
     136              :     //     for ( auto ConstrNum = 1; ConstrNum <= TotConstructs; ++ConstrNum ) {
     137              :     //         auto& construction( Construct( ConstrNum ) );
     138              :     //         if ( construction.isGlazingConstruction() ) {
     139              :     //             for ( auto LayNum = 1; LayNum <= construction.TotLayers; ++LayNum ) {
     140              :     //                 auto& material( dataMaterial.Material( construction.LayerPoint( LayNum ) ) );
     141              :     //                 if ( material->group != WindowGas && material->group != WindowGasMixture &&
     142              :     //                     material->group != ComplexWindowGap && material->group != ComplexWindowShade ) {
     143              :     //                     auto aMaterial = std::make_shared< Material::MaterialBase >();
     144              :     //                     *aMaterial = material;
     145              :     //
     146              :     //                     // This is necessary because rest of EnergyPlus code relies on TransDiff property
     147              :     //                     // of construction. It will basically trigger Window optical calculations if this
     148              :     //                     // property is >0.
     149              :     //                     construction.TransDiff = 0.1;
     150              :     //
     151              :     //                     auto aRange = WavelengthRange::Solar;
     152              :     //                     auto aSolarLayer = getBSDFLayer( aMaterial, aRange );
     153              :     //                     aWinConstBSDF.pushBSDFLayer( aRange, ConstrNum, aSolarLayer );
     154              :     //
     155              :     //                     aRange = WavelengthRange::Visible;
     156              :     //                     auto aVisibleLayer = getBSDFLayer( aMaterial, aRange );
     157              :     //                     aWinConstBSDF.pushBSDFLayer( aRange, ConstrNum, aVisibleLayer );
     158              :     //                 }
     159              :     //
     160              :     //             }
     161              :     //         }
     162              :     //     }
     163              :     // }
     164              : 
     165            3 :     void InitWCE_SimplifiedOpticalData(EnergyPlusData &state)
     166              :     {
     167              :         // SUBROUTINE INFORMATION:
     168              :         //       AUTHOR         Simon Vidanovic
     169              :         //       DATE WRITTEN   May 2017
     170              :         //       MODIFIED       na
     171              :         //       RE-ENGINEERED  na
     172              : 
     173              :         // PURPOSE OF THIS SUBROUTINE:
     174              :         // Initialize scattering construction layers in Solar and Visible spectrum.
     175              : 
     176              :         // Calculate optical properties of blind-type layers entered with MATERIAL:WindowBlind
     177              :         // Calculation from this is used for IR properties. Need to make sure that properties
     178              :         // are calculated with new WCE optical engine (for both blinds and screens)
     179            3 :         auto &s_mat = state.dataMaterial;
     180              : 
     181            3 :         if (s_mat->NumBlinds > 0) CalcWindowBlindProperties(state);
     182              : 
     183              :         // Initialize SurfaceScreen structure
     184            3 :         if (s_mat->NumScreens > 0) CalcWindowScreenProperties(state);
     185              : 
     186            3 :         auto &aWinConstSimp = CWindowConstructionsSimplified::instance(state);
     187            7 :         for (int ConstrNum = 1; ConstrNum <= state.dataHeatBal->TotConstructs; ++ConstrNum) {
     188            4 :             auto &construction = state.dataConstruction->Construct(ConstrNum);
     189            4 :             if (construction.isGlazingConstruction(state)) {
     190           10 :                 for (int LayNum = 1; LayNum <= construction.TotLayers; ++LayNum) {
     191            6 :                     auto const *mat = s_mat->materials(construction.LayerPoint(LayNum));
     192            6 :                     if (mat->group != Material::Group::Gas && mat->group != Material::Group::GasMixture &&
     193            6 :                         mat->group != Material::Group::ComplexWindowGap && mat->group != Material::Group::ComplexShade) {
     194              :                         // This is necessary because rest of EnergyPlus code relies on TransDiff property
     195              :                         // of construction. It will basically trigger Window optical calculations if this
     196              :                         // property is >0.
     197            6 :                         construction.TransDiff = 0.1;
     198              : 
     199            6 :                         WavelengthRange aRange = WavelengthRange::Solar;
     200            6 :                         auto aSolarLayer = getScatteringLayer(state, mat, aRange); // (AUTO_OK_OBJ)
     201            6 :                         aWinConstSimp.pushLayer(aRange, ConstrNum, aSolarLayer);
     202              : 
     203            6 :                         aRange = WavelengthRange::Visible;
     204            6 :                         auto aVisibleLayer = getScatteringLayer(state, mat, aRange); // (AUTO_OK_OBJ)
     205            6 :                         aWinConstSimp.pushLayer(aRange, ConstrNum, aVisibleLayer);
     206            6 :                     }
     207              :                 }
     208              :             }
     209              :         }
     210              : 
     211              :         // Get effective glass and shade/blind emissivities for windows that have interior blind or
     212              :         // shade. These are used to calculate zone MRT contribution from window when
     213              :         // interior blind/shade is deployed.
     214              : 
     215            3 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     216            0 :             auto &surf = state.dataSurface->Surface(SurfNum);
     217            0 :             auto &surfShade = state.dataSurface->surfShades(SurfNum);
     218              : 
     219            0 :             if (!surf.HeatTransSurf) continue;
     220            0 :             if (!state.dataConstruction->Construct(surf.Construction).TypeIsWindow) continue;
     221            0 :             if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) continue; // Irrelevant for Complex Fen
     222            0 :             if (state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) continue;      // not required
     223              : 
     224            0 :             if (surf.activeShadedConstruction == 0) continue;
     225            0 :             auto &constrSh = state.dataConstruction->Construct(surf.activeShadedConstruction);
     226            0 :             int TotLay = constrSh.TotLayers;
     227            0 :             auto const *mat = s_mat->materials(constrSh.LayerPoint(TotLay));
     228              : 
     229            0 :             if (mat->group == Material::Group::Shade) {
     230            0 :                 auto const *matShade = dynamic_cast<Material::MaterialShade const *>(mat);
     231            0 :                 Real64 EpsGlIR = s_mat->materials(constrSh.LayerPoint(TotLay - 1))->AbsorpThermalBack;
     232            0 :                 Real64 RhoGlIR = 1 - EpsGlIR;
     233            0 :                 Real64 TauShIR = matShade->TransThermal;
     234            0 :                 Real64 EpsShIR = matShade->AbsorpThermal;
     235            0 :                 Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
     236            0 :                 surfShade.effShadeEmi = EpsShIR * (1.0 + RhoGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR));
     237            0 :                 surfShade.effGlassEmi = EpsGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR);
     238              : 
     239            0 :             } else if (mat->group == Material::Group::Blind) {
     240            0 :                 Real64 EpsGlIR = s_mat->materials(constrSh.LayerPoint(TotLay - 1))->AbsorpThermalBack;
     241            0 :                 Real64 RhoGlIR = 1 - EpsGlIR;
     242              : 
     243            0 :                 auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(mat);
     244            0 :                 for (int iSlatAng = 0; iSlatAng < Material::MaxSlatAngs; ++iSlatAng) {
     245            0 :                     auto const &btar = matBlind->TARs[iSlatAng];
     246            0 :                     Real64 TauShIR = btar.IR.Ft.Tra;
     247            0 :                     Real64 EpsShIR = btar.IR.Ft.Emi;
     248            0 :                     Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
     249            0 :                     constrSh.effShadeBlindEmi[iSlatAng] = EpsShIR * (1.0 + RhoGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR));
     250            0 :                     constrSh.effGlassEmi[iSlatAng] = EpsGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR);
     251              :                 }
     252              :                 // The following surface assignments previously lived in the WindowManagerExteriorThermal file.
     253              :                 // They were moved here during the Material refactor, however I found that the array index values Lo/Hi
     254              :                 // were making it here still as -1, and this was causing a difficult to diagnose segfault.
     255              :                 // I'm moving these back over there, but open to suggestion if they need to be here.
     256              :                 // surfShade.effShadeEmi = Interp(constrSh.effShadeBlindEmi[surfShade.blind.slatAngIdxLo],
     257              :                 //                                constrSh.effShadeBlindEmi[surfShade.blind.slatAngIdxHi],
     258              :                 //                                surfShade.blind.slatAngInterpFac);
     259              :                 // surfShade.effGlassEmi = Interp(constrSh.effGlassEmi[surfShade.blind.slatAngIdxLo],
     260              :                 //                                constrSh.effGlassEmi[surfShade.blind.slatAngIdxHi],
     261              :                 //                                surfShade.blind.slatAngInterpFac);
     262              :             } // End of check if interior shade or interior blind
     263              :         }     // End of surface loop
     264            3 :     }         // InitWCE_SimplifiedOpticalData()
     265              : 
     266            0 :     Real64 GetSolarTransDirectHemispherical(EnergyPlusData &state, int ConstrNum)
     267              :     {
     268              :         const auto aWinConstSimp = // (AUTO_OK_SHARED_PTR)
     269            0 :             CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Solar, ConstrNum);
     270            0 :         return aWinConstSimp->getPropertySimple(
     271            0 :             0.3, 2.5, FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Front, FenestrationCommon::Scattering::DirectHemispherical);
     272            0 :     }
     273              : 
     274            0 :     Real64 GetVisibleTransDirectHemispherical(EnergyPlusData &state, int ConstrNum)
     275              :     {
     276              :         const auto aWinConstSimp = // (AUTO_OK_SHARED_PTR)
     277            0 :             CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Visible, ConstrNum);
     278            0 :         return aWinConstSimp->getPropertySimple(
     279            0 :             0.38, 0.78, FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Front, FenestrationCommon::Scattering::DirectHemispherical);
     280            0 :     }
     281              : 
     282              :     ///////////////////////////////////////////////////////////////////////////////
     283              :     //   CWCEMaterialFactory
     284              :     ///////////////////////////////////////////////////////////////////////////////
     285           12 :     CWCEMaterialFactory::CWCEMaterialFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     286           12 :         : m_MaterialProperties(t_Material), m_Range(t_Range), m_Initialized(false)
     287              :     {
     288           12 :     }
     289              : 
     290           12 :     std::shared_ptr<CMaterial> CWCEMaterialFactory::getMaterial(EnergyPlusData &state)
     291              :     {
     292           12 :         if (!m_Initialized) {
     293           12 :             init(state);
     294           12 :             m_Initialized = true;
     295              :         }
     296           12 :         return m_Material;
     297              :     }
     298              : 
     299              :     ///////////////////////////////////////////////////////////////////////////////
     300              :     //   CWCESpecularMaterialsFactory
     301              :     ///////////////////////////////////////////////////////////////////////////////
     302            8 :     CWCESpecularMaterialsFactory::CWCESpecularMaterialsFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     303            8 :         : CWCEMaterialFactory(t_Material, t_Range)
     304              :     {
     305            8 :     }
     306              : 
     307            8 :     void CWCESpecularMaterialsFactory::init(EnergyPlusData &state)
     308              :     {
     309            8 :         auto const *matGlass = dynamic_cast<Material::MaterialGlass const *>(m_MaterialProperties);
     310            8 :         assert(matGlass != nullptr);
     311              : 
     312            8 :         if (matGlass->GlassSpectralDataPtr > 0) {
     313            0 :             auto aSolarSpectrum = CWCESpecturmProperties::getDefaultSolarRadiationSpectrum(state); // (AUTO_OK_OBJ)
     314            0 :             std::shared_ptr<CSpectralSampleData> aSampleData = nullptr;
     315            0 :             aSampleData = CWCESpecturmProperties::getSpectralSample(state, matGlass->GlassSpectralDataPtr);
     316              : 
     317            0 :             auto aSample = std::make_shared<CSpectralSample>(aSampleData, aSolarSpectrum); // (AUTO_OK_SHARED_PTR)
     318              : 
     319            0 :             FenestrationCommon::MaterialType aType = MaterialType::Monolithic;
     320            0 :             CWavelengthRange aRange(m_Range);
     321            0 :             Real64 lowLambda = aRange.minLambda();
     322            0 :             Real64 highLambda = aRange.maxLambda();
     323              : 
     324              :             // Do not apply detector data if we do not have spectral data. This will only cause more inaccurate results at the end. (Simon)
     325            0 :             if (m_Range == WavelengthRange::Visible && matGlass->GlassSpectralDataPtr != 0) {
     326            0 :                 const auto aPhotopicResponse = CWCESpecturmProperties::getDefaultVisiblePhotopicResponse(state); // (AUTO_OK_OBJ)
     327            0 :                 aSample->setDetectorData(aPhotopicResponse);
     328            0 :             }
     329              : 
     330            0 :             Real64 thickness = matGlass->Thickness;
     331            0 :             m_Material = std::make_shared<CMaterialSample>(aSample, thickness, aType, lowLambda, highLambda);
     332            0 :         } else {
     333            8 :             if (m_Range == WavelengthRange::Solar) {
     334            4 :                 m_Material = std::make_shared<CMaterialSingleBand>(
     335            4 :                     matGlass->Trans, matGlass->Trans, matGlass->ReflectSolBeamFront, matGlass->ReflectSolBeamBack, m_Range);
     336              :             }
     337            8 :             if (m_Range == WavelengthRange::Visible) {
     338            4 :                 m_Material = std::make_shared<CMaterialSingleBand>(
     339            4 :                     matGlass->TransVis, matGlass->TransVis, matGlass->ReflectVisBeamFront, matGlass->ReflectVisBeamBack, m_Range);
     340              :             }
     341              :         }
     342            8 :     }
     343              : 
     344              :     ///////////////////////////////////////////////////////////////////////////////
     345              :     //   CWCEMaterialDualBandFactory
     346              :     ///////////////////////////////////////////////////////////////////////////////
     347            4 :     CWCEMaterialDualBandFactory::CWCEMaterialDualBandFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     348            4 :         : CWCEMaterialFactory(t_Material, t_Range)
     349              :     {
     350            4 :     }
     351              : 
     352            4 :     void CWCEMaterialDualBandFactory::init([[maybe_unused]] EnergyPlusData &state)
     353              :     {
     354            4 :         if (m_Range == WavelengthRange::Visible) {
     355            2 :             m_Material = createVisibleRangeMaterial(state);
     356              :         } else {
     357            2 :             auto aVisibleRangeMaterial = createVisibleRangeMaterial(state); // (AUTO_OK_OBJ)
     358            2 :             auto aSolarRangeMaterial = createSolarRangeMaterial(state);     // (AUTO_OK_OBJ)
     359              :             // Ratio visible to solar range. It can be calculated from solar spectrum.
     360            2 :             Real64 ratio = 0.49;
     361            2 :             m_Material = std::make_shared<CMaterialDualBand>(aVisibleRangeMaterial, aSolarRangeMaterial, ratio);
     362            2 :         }
     363            4 :     }
     364              : 
     365              :     ///////////////////////////////////////////////////////////////////////////////
     366              :     //   CWCEVenetianBlindMaterialsFactory
     367              :     ///////////////////////////////////////////////////////////////////////////////
     368            2 :     CWCEVenetianBlindMaterialsFactory::CWCEVenetianBlindMaterialsFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     369            2 :         : CWCEMaterialDualBandFactory(t_Material, t_Range)
     370              :     {
     371            2 :     }
     372              : 
     373            2 :     std::shared_ptr<CMaterialSingleBand> CWCEVenetianBlindMaterialsFactory::createVisibleRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     374              :     {
     375            2 :         auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(m_MaterialProperties);
     376            2 :         assert(matBlind != nullptr);
     377              : 
     378            2 :         CWavelengthRange aRange(WavelengthRange::Visible);
     379            2 :         Real64 lowLambda = aRange.minLambda();
     380            2 :         Real64 highLambda = aRange.maxLambda();
     381              : 
     382            2 :         Real64 Tf = matBlind->slatTAR.Vis.Ft.Df.Tra;
     383            2 :         Real64 Tb = matBlind->slatTAR.Vis.Ft.Df.Tra;
     384            2 :         Real64 Rf = matBlind->slatTAR.Vis.Ft.Df.Ref;
     385            2 :         Real64 Rb = matBlind->slatTAR.Vis.Bk.Df.Ref;
     386              : 
     387            4 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     388            2 :     }
     389              : 
     390            1 :     std::shared_ptr<CMaterialSingleBand> CWCEVenetianBlindMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     391              :     {
     392            1 :         auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(m_MaterialProperties);
     393            1 :         assert(matBlind != nullptr);
     394              : 
     395            1 :         CWavelengthRange aRange(WavelengthRange::Solar);
     396            1 :         Real64 lowLambda = aRange.minLambda();
     397            1 :         Real64 highLambda = aRange.maxLambda();
     398              : 
     399            1 :         Real64 Tf = matBlind->slatTAR.Sol.Ft.Df.Tra;
     400            1 :         Real64 Tb = matBlind->slatTAR.Sol.Ft.Df.Tra;
     401            1 :         Real64 Rf = matBlind->slatTAR.Sol.Ft.Df.Ref;
     402            1 :         Real64 Rb = matBlind->slatTAR.Sol.Bk.Df.Ref;
     403              : 
     404            2 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     405            1 :     }
     406              : 
     407              :     ///////////////////////////////////////////////////////////////////////////////
     408              :     //   CWCEScreenMaterialsFactory
     409              :     ///////////////////////////////////////////////////////////////////////////////
     410            0 :     CWCEScreenMaterialsFactory::CWCEScreenMaterialsFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     411            0 :         : CWCEMaterialDualBandFactory(t_Material, t_Range)
     412              :     {
     413              :         // Current EnergyPlus model does not support material transmittance different from zero.
     414              :         // To enable that, it would be necessary to change input in IDF
     415            0 :     }
     416              : 
     417            0 :     std::shared_ptr<CMaterialSingleBand> CWCEScreenMaterialsFactory::createVisibleRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     418              :     {
     419            0 :         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
     420            0 :         assert(matShade != nullptr);
     421            0 :         CWavelengthRange aRange(WavelengthRange::Visible);
     422            0 :         Real64 lowLambda = aRange.minLambda();
     423            0 :         Real64 highLambda = aRange.maxLambda();
     424              : 
     425            0 :         Real64 Tf = 0.0;
     426            0 :         Real64 Tb = 0.0;
     427            0 :         Real64 Rf = matShade->ReflectShadeVis;
     428            0 :         Real64 Rb = matShade->ReflectShadeVis;
     429              : 
     430            0 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     431            0 :     }
     432              : 
     433            0 :     std::shared_ptr<CMaterialSingleBand> CWCEScreenMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     434              :     {
     435            0 :         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
     436            0 :         assert(matShade != nullptr);
     437            0 :         CWavelengthRange aRange(WavelengthRange::Solar);
     438            0 :         Real64 lowLambda = aRange.minLambda();
     439            0 :         Real64 highLambda = aRange.maxLambda();
     440              : 
     441            0 :         Real64 Tf = 0.0;
     442            0 :         Real64 Tb = 0.0;
     443            0 :         Real64 Rf = matShade->ReflectShade;
     444            0 :         Real64 Rb = matShade->ReflectShade;
     445              : 
     446            0 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     447            0 :     }
     448              : 
     449              :     ///////////////////////////////////////////////////////////////////////////////
     450              :     //   CWCEDiffuseShadeMaterialsFactory
     451              :     ///////////////////////////////////////////////////////////////////////////////
     452            2 :     CWCEDiffuseShadeMaterialsFactory::CWCEDiffuseShadeMaterialsFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     453            2 :         : CWCEMaterialDualBandFactory(t_Material, t_Range)
     454              :     {
     455            2 :     }
     456              : 
     457            2 :     std::shared_ptr<CMaterialSingleBand> CWCEDiffuseShadeMaterialsFactory::createVisibleRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     458              :     {
     459            2 :         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
     460            2 :         assert(matShade != nullptr);
     461            2 :         CWavelengthRange aRange(WavelengthRange::Visible);
     462            2 :         Real64 lowLambda = aRange.minLambda();
     463            2 :         Real64 highLambda = aRange.maxLambda();
     464              : 
     465            2 :         Real64 Tf = matShade->TransVis;
     466            2 :         Real64 Tb = matShade->TransVis;
     467            2 :         Real64 Rf = matShade->ReflectShadeVis;
     468            2 :         Real64 Rb = matShade->ReflectShadeVis;
     469              : 
     470            4 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     471            2 :     }
     472              : 
     473            1 :     std::shared_ptr<CMaterialSingleBand> CWCEDiffuseShadeMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     474              :     {
     475            1 :         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
     476            1 :         assert(matShade != nullptr);
     477            1 :         CWavelengthRange aRange(WavelengthRange::Solar);
     478            1 :         Real64 lowLambda = aRange.minLambda();
     479            1 :         Real64 highLambda = aRange.maxLambda();
     480              : 
     481            1 :         Real64 Tf = matShade->Trans;
     482            1 :         Real64 Tb = matShade->Trans;
     483            1 :         Real64 Rf = matShade->ReflectShade;
     484            1 :         Real64 Rb = matShade->ReflectShade;
     485              : 
     486            2 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     487            1 :     }
     488              : 
     489              :     ///////////////////////////////////////////////////////////////////////////////
     490              :     //   CWCECellFactory
     491              :     ///////////////////////////////////////////////////////////////////////////////
     492           12 :     IWCECellDescriptionFactory::IWCECellDescriptionFactory(const Material::MaterialBase *t_Material) : m_Material(t_Material)
     493              :     {
     494           12 :     }
     495              : 
     496              :     ///////////////////////////////////////////////////////////////////////////////
     497              :     //   CWCESpecularCellFactory
     498              :     ///////////////////////////////////////////////////////////////////////////////
     499              : 
     500            8 :     CWCESpecularCellFactory::CWCESpecularCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
     501              :     {
     502            8 :     }
     503              : 
     504            8 :     std::shared_ptr<ICellDescription> CWCESpecularCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
     505              :     {
     506            8 :         return std::make_shared<CSpecularCellDescription>();
     507              :     }
     508              : 
     509              :     ///////////////////////////////////////////////////////////////////////////////
     510              :     //   CWCEVenetianBlindCellFactory
     511              :     ///////////////////////////////////////////////////////////////////////////////
     512            2 :     CWCEVenetianBlindCellFactory::CWCEVenetianBlindCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
     513              :     {
     514            2 :     }
     515              : 
     516            2 :     std::shared_ptr<ICellDescription> CWCEVenetianBlindCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
     517              :     {
     518            2 :         auto *matBlind = dynamic_cast<Material::MaterialBlind const *>(m_Material);
     519            2 :         assert(matBlind != nullptr);
     520              : 
     521            2 :         Real64 slatWidth = matBlind->SlatWidth;
     522            2 :         Real64 slatSpacing = matBlind->SlatSeparation;
     523            2 :         Real64 slatTiltAngle = 90.0 - matBlind->SlatAngle; // Need to convert to WCE system
     524            2 :         Real64 curvatureRadius = 0.0;                      // No curvature radius in current IDF definition
     525            2 :         size_t numOfSlatSegments = 5;                      // Number of segments to use in venetian calculations
     526            2 :         return std::make_shared<CVenetianCellDescription>(slatWidth, slatSpacing, slatTiltAngle, curvatureRadius, numOfSlatSegments);
     527              :     }
     528              : 
     529              :     ///////////////////////////////////////////////////////////////////////////////
     530              :     //   CWCEScreenCellFactory
     531              :     ///////////////////////////////////////////////////////////////////////////////
     532            0 :     CWCEScreenCellFactory::CWCEScreenCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
     533              :     {
     534            0 :     }
     535              : 
     536            0 :     std::shared_ptr<ICellDescription> CWCEScreenCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
     537              :     {
     538            0 :         Real64 diameter = m_Material->Thickness; // Thickness in this case is diameter
     539              :         // ratio is not saved withing material but rather calculated from transmittance
     540            0 :         const Real64 ratio = 1.0 - sqrt(dynamic_cast<Material::MaterialScreen const *>(m_Material)->Trans);
     541            0 :         Real64 spacing = diameter / ratio;
     542            0 :         return std::make_shared<CWovenCellDescription>(diameter, spacing);
     543              :     }
     544              : 
     545              :     ///////////////////////////////////////////////////////////////////////////////
     546              :     //   CWCEDiffuseShadeCellFactory
     547              :     ///////////////////////////////////////////////////////////////////////////////
     548            2 :     CWCEDiffuseShadeCellFactory::CWCEDiffuseShadeCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
     549              :     {
     550            2 :     }
     551              : 
     552            2 :     std::shared_ptr<ICellDescription> CWCEDiffuseShadeCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
     553              :     {
     554            2 :         return std::make_shared<CFlatCellDescription>();
     555              :     }
     556              : 
     557              :     ///////////////////////////////////////////////////////////////////////////////
     558              :     //   CWCEBSDFLayerFactory
     559              :     ///////////////////////////////////////////////////////////////////////////////
     560           12 :     CWCELayerFactory::CWCELayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     561           12 :         : m_Material(t_Material), m_Range(t_Range), m_BSDFInitialized(false), m_SimpleInitialized(false), m_MaterialFactory(nullptr)
     562              :     {
     563           12 :     }
     564              : 
     565           12 :     std::pair<std::shared_ptr<CMaterial>, std::shared_ptr<ICellDescription>> CWCELayerFactory::init(EnergyPlusData &state)
     566              :     {
     567           12 :         createMaterialFactory();
     568           12 :         auto aMaterial = m_MaterialFactory->getMaterial(state); // (AUTO_OK_SHARED_PTR)
     569           12 :         assert(aMaterial != nullptr);
     570           12 :         auto aCellDescription = getCellDescription(state); // (AUTO_OK_SHARED_PTR)
     571           12 :         assert(aCellDescription != nullptr);
     572              : 
     573           24 :         return std::make_pair(aMaterial, aCellDescription);
     574           12 :     }
     575              : 
     576            0 :     std::shared_ptr<CBSDFLayer> CWCELayerFactory::getBSDFLayer(EnergyPlusData &state)
     577              :     {
     578            0 :         if (!m_BSDFInitialized) {
     579            0 :             auto res = init(state);                                      // (AUTO_OK_SHARED_PTR)
     580            0 :             const auto aBSDF = CBSDFHemisphere::create(BSDFBasis::Full); // (AUTO_OK_OBJ)
     581              : 
     582            0 :             CBSDFLayerMaker aMaker(res.first, aBSDF, res.second);
     583            0 :             m_BSDFLayer = aMaker.getLayer();
     584            0 :             m_BSDFInitialized = true;
     585            0 :         }
     586            0 :         return m_BSDFLayer;
     587              :     }
     588              : 
     589           12 :     CScatteringLayer CWCELayerFactory::getLayer(EnergyPlusData &state)
     590              :     {
     591           12 :         if (!m_SimpleInitialized) {
     592           12 :             auto res = init(state); // (AUTO_OK_SHARED_PTR)
     593              : 
     594           12 :             m_ScatteringLayer = CScatteringLayer(res.first, res.second);
     595           12 :             m_SimpleInitialized = true;
     596           12 :         }
     597           12 :         return m_ScatteringLayer;
     598              :     }
     599              : 
     600           12 :     std::shared_ptr<ICellDescription> CWCELayerFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state) const
     601              :     {
     602           12 :         return m_CellFactory->getCellDescription(state);
     603              :     }
     604              : 
     605              :     ///////////////////////////////////////////////////////////////////////////////
     606              :     //   CWCESpecularLayerFactory
     607              :     ///////////////////////////////////////////////////////////////////////////////
     608            8 :     CWCESpecularLayerFactory::CWCESpecularLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     609            8 :         : CWCELayerFactory(t_Material, t_Range)
     610              :     {
     611            8 :         m_CellFactory = std::make_shared<CWCESpecularCellFactory>(t_Material);
     612            8 :     }
     613              : 
     614            8 :     void CWCESpecularLayerFactory::createMaterialFactory()
     615              :     {
     616            8 :         m_MaterialFactory = std::make_shared<CWCESpecularMaterialsFactory>(m_Material, m_Range);
     617            8 :     }
     618              : 
     619              :     ///////////////////////////////////////////////////////////////////////////////
     620              :     //   CWCEVenetianBlindLayerFactory
     621              :     ///////////////////////////////////////////////////////////////////////////////
     622            2 :     CWCEVenetianBlindLayerFactory::CWCEVenetianBlindLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     623            2 :         : CWCELayerFactory(t_Material, t_Range)
     624              :     {
     625            2 :         m_CellFactory = std::make_shared<CWCEVenetianBlindCellFactory>(t_Material);
     626            2 :     }
     627              : 
     628            2 :     void CWCEVenetianBlindLayerFactory::createMaterialFactory()
     629              :     {
     630            2 :         m_MaterialFactory = std::make_shared<CWCEVenetianBlindMaterialsFactory>(m_Material, m_Range);
     631            2 :     }
     632              : 
     633              :     ///////////////////////////////////////////////////////////////////////////////
     634              :     //   CWCEScreenLayerFactory
     635              :     ///////////////////////////////////////////////////////////////////////////////
     636            0 :     CWCEScreenLayerFactory::CWCEScreenLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     637            0 :         : CWCELayerFactory(t_Material, t_Range)
     638              :     {
     639            0 :         m_CellFactory = std::make_shared<CWCEScreenCellFactory>(t_Material);
     640            0 :     }
     641              : 
     642            0 :     void CWCEScreenLayerFactory::createMaterialFactory()
     643              :     {
     644            0 :         m_MaterialFactory = std::make_shared<CWCEScreenMaterialsFactory>(m_Material, m_Range);
     645            0 :     }
     646              : 
     647              :     ///////////////////////////////////////////////////////////////////////////////
     648              :     //   CWCEDiffuseShadeLayerFactory
     649              :     ///////////////////////////////////////////////////////////////////////////////
     650            2 :     CWCEDiffuseShadeLayerFactory::CWCEDiffuseShadeLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     651            2 :         : CWCELayerFactory(t_Material, t_Range)
     652              :     {
     653            2 :         m_CellFactory = std::make_shared<CWCEDiffuseShadeCellFactory>(t_Material);
     654            2 :     }
     655              : 
     656            2 :     void CWCEDiffuseShadeLayerFactory::createMaterialFactory()
     657              :     {
     658            2 :         m_MaterialFactory = std::make_shared<CWCEDiffuseShadeMaterialsFactory>(m_Material, m_Range);
     659            2 :     }
     660              : 
     661              : } // namespace Window
     662              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1