LCOV - code coverage report
Current view: top level - EnergyPlus - WindowManagerExteriorOptical.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 73.4 % 308 226
Test Date: 2025-06-02 07:23:51 Functions: 78.6 % 42 33

            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           16 :     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           16 :         std::shared_ptr<CWCELayerFactory> aFactory = nullptr;
     113           16 :         if (t_Material->group == Material::Group::Glass || t_Material->group == Material::Group::GlassSimple) {
     114           12 :             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           32 :         return aFactory->getLayer(state);
     123           16 :     }
     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) {
     182            1 :             CalcWindowBlindProperties(state);
     183              :         }
     184              : 
     185              :         // Initialize SurfaceScreen structure
     186            3 :         if (s_mat->NumScreens > 0) {
     187            0 :             CalcWindowScreenProperties(state);
     188              :         }
     189              : 
     190            3 :         auto &aWinConstSimp = CWindowConstructionsSimplified::instance(state);
     191           23 :         for (int ConstrNum = 1; ConstrNum <= state.dataHeatBal->TotConstructs; ++ConstrNum) {
     192           20 :             auto &construction = state.dataConstruction->Construct(ConstrNum);
     193           20 :             if (construction.isGlazingConstruction(state)) {
     194           14 :                 for (int LayNum = 1; LayNum <= construction.TotLayers; ++LayNum) {
     195            9 :                     auto const *mat = s_mat->materials(construction.LayerPoint(LayNum));
     196            9 :                     if (mat->group != Material::Group::Gas && mat->group != Material::Group::GasMixture &&
     197            9 :                         mat->group != Material::Group::ComplexWindowGap && mat->group != Material::Group::ComplexShade) {
     198              :                         // This is necessary because rest of EnergyPlus code relies on TransDiff property
     199              :                         // of construction. It will basically trigger Window optical calculations if this
     200              :                         // property is >0.
     201            8 :                         construction.TransDiff = 0.1;
     202              : 
     203            8 :                         WavelengthRange aRange = WavelengthRange::Solar;
     204            8 :                         auto aSolarLayer = getScatteringLayer(state, mat, aRange); // (AUTO_OK_OBJ)
     205            8 :                         aWinConstSimp.pushLayer(aRange, ConstrNum, aSolarLayer);
     206              : 
     207            8 :                         aRange = WavelengthRange::Visible;
     208            8 :                         auto aVisibleLayer = getScatteringLayer(state, mat, aRange); // (AUTO_OK_OBJ)
     209            8 :                         aWinConstSimp.pushLayer(aRange, ConstrNum, aVisibleLayer);
     210            8 :                     }
     211              :                 }
     212              :             }
     213              :         }
     214              : 
     215              :         // Get effective glass and shade/blind emissivities for windows that have interior blind or
     216              :         // shade. These are used to calculate zone MRT contribution from window when
     217              :         // interior blind/shade is deployed.
     218              : 
     219           24 :         for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
     220           21 :             auto &surf = state.dataSurface->Surface(SurfNum);
     221           21 :             auto &surfShade = state.dataSurface->surfShades(SurfNum);
     222              : 
     223           21 :             if (!surf.HeatTransSurf) {
     224            0 :                 continue;
     225              :             }
     226           21 :             if (!state.dataConstruction->Construct(surf.Construction).TypeIsWindow) {
     227           18 :                 continue;
     228              :             }
     229            3 :             if (state.dataSurface->SurfWinWindowModelType(SurfNum) == WindowModel::BSDF) {
     230            0 :                 continue; // Irrelevant for Complex Fen
     231              :             }
     232            3 :             if (state.dataConstruction->Construct(surf.Construction).WindowTypeEQL) {
     233            0 :                 continue; // not required
     234              :             }
     235              : 
     236            3 :             if (surf.activeShadedConstruction == 0) {
     237            1 :                 continue;
     238              :             }
     239            2 :             auto &constrSh = state.dataConstruction->Construct(surf.activeShadedConstruction);
     240            2 :             int TotLay = constrSh.TotLayers;
     241            2 :             auto const *mat = s_mat->materials(constrSh.LayerPoint(TotLay));
     242              : 
     243            2 :             if (mat->group == Material::Group::Shade) {
     244            1 :                 auto const *matShade = dynamic_cast<Material::MaterialShade const *>(mat);
     245            1 :                 Real64 EpsGlIR = s_mat->materials(constrSh.LayerPoint(TotLay - 1))->AbsorpThermalBack;
     246            1 :                 Real64 RhoGlIR = 1 - EpsGlIR;
     247            1 :                 Real64 TauShIR = matShade->TransThermal;
     248            1 :                 Real64 EpsShIR = matShade->AbsorpThermal;
     249            1 :                 Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
     250            1 :                 surfShade.effShadeEmi = EpsShIR * (1.0 + RhoGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR));
     251            1 :                 surfShade.effGlassEmi = EpsGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR);
     252              : 
     253            1 :             } else if (mat->group == Material::Group::Blind) {
     254            1 :                 Real64 EpsGlIR = s_mat->materials(constrSh.LayerPoint(TotLay - 1))->AbsorpThermalBack;
     255            1 :                 Real64 RhoGlIR = 1 - EpsGlIR;
     256              : 
     257            1 :                 auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(mat);
     258          182 :                 for (int iSlatAng = 0; iSlatAng < Material::MaxSlatAngs; ++iSlatAng) {
     259          181 :                     auto const &btar = matBlind->TARs[iSlatAng];
     260          181 :                     Real64 TauShIR = btar.IR.Ft.Tra;
     261          181 :                     Real64 EpsShIR = btar.IR.Ft.Emi;
     262          181 :                     Real64 RhoShIR = max(0.0, 1.0 - TauShIR - EpsShIR);
     263          181 :                     constrSh.effShadeBlindEmi[iSlatAng] = EpsShIR * (1.0 + RhoGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR));
     264          181 :                     constrSh.effGlassEmi[iSlatAng] = EpsGlIR * TauShIR / (1.0 - RhoGlIR * RhoShIR);
     265              :                 }
     266              :                 // The following surface assignments previously lived in the WindowManagerExteriorThermal file.
     267              :                 // They were moved here during the Material refactor, however I found that the array index values Lo/Hi
     268              :                 // were making it here still as -1, and this was causing a difficult to diagnose segfault.
     269              :                 // I'm moving these back over there, but open to suggestion if they need to be here.
     270              :                 // surfShade.effShadeEmi = Interp(constrSh.effShadeBlindEmi[surfShade.blind.slatAngIdxLo],
     271              :                 //                                constrSh.effShadeBlindEmi[surfShade.blind.slatAngIdxHi],
     272              :                 //                                surfShade.blind.slatAngInterpFac);
     273              :                 // surfShade.effGlassEmi = Interp(constrSh.effGlassEmi[surfShade.blind.slatAngIdxLo],
     274              :                 //                                constrSh.effGlassEmi[surfShade.blind.slatAngIdxHi],
     275              :                 //                                surfShade.blind.slatAngInterpFac);
     276              :             } // End of check if interior shade or interior blind
     277              :         } // End of surface loop
     278            3 :     } // InitWCE_SimplifiedOpticalData()
     279              : 
     280            3 :     Real64 GetSolarTransDirectHemispherical(EnergyPlusData &state, int ConstrNum)
     281              :     {
     282              :         const auto aWinConstSimp = // (AUTO_OK_SHARED_PTR)
     283            3 :             CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Solar, ConstrNum);
     284            3 :         return aWinConstSimp->getPropertySimple(
     285            6 :             0.3, 2.5, FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Front, FenestrationCommon::Scattering::DirectHemispherical);
     286            3 :     }
     287              : 
     288            3 :     Real64 GetVisibleTransDirectHemispherical(EnergyPlusData &state, int ConstrNum)
     289              :     {
     290              :         const auto aWinConstSimp = // (AUTO_OK_SHARED_PTR)
     291            3 :             CWindowConstructionsSimplified::instance(state).getEquivalentLayer(state, FenestrationCommon::WavelengthRange::Visible, ConstrNum);
     292            3 :         return aWinConstSimp->getPropertySimple(
     293            6 :             0.38, 0.78, FenestrationCommon::PropertySimple::T, FenestrationCommon::Side::Front, FenestrationCommon::Scattering::DirectHemispherical);
     294            3 :     }
     295              : 
     296              :     ///////////////////////////////////////////////////////////////////////////////
     297              :     //   CWCEMaterialFactory
     298              :     ///////////////////////////////////////////////////////////////////////////////
     299           16 :     CWCEMaterialFactory::CWCEMaterialFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     300           16 :         : m_MaterialProperties(t_Material), m_Range(t_Range), m_Initialized(false)
     301              :     {
     302           16 :     }
     303              : 
     304           16 :     std::shared_ptr<CMaterial> CWCEMaterialFactory::getMaterial(EnergyPlusData &state)
     305              :     {
     306           16 :         if (!m_Initialized) {
     307           16 :             init(state);
     308           16 :             m_Initialized = true;
     309              :         }
     310           16 :         return m_Material;
     311              :     }
     312              : 
     313              :     ///////////////////////////////////////////////////////////////////////////////
     314              :     //   CWCESpecularMaterialsFactory
     315              :     ///////////////////////////////////////////////////////////////////////////////
     316           12 :     CWCESpecularMaterialsFactory::CWCESpecularMaterialsFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     317           12 :         : CWCEMaterialFactory(t_Material, t_Range)
     318              :     {
     319           12 :     }
     320              : 
     321           12 :     void CWCESpecularMaterialsFactory::init(EnergyPlusData &state)
     322              :     {
     323           12 :         auto const *matGlass = dynamic_cast<Material::MaterialGlass const *>(m_MaterialProperties);
     324           12 :         assert(matGlass != nullptr);
     325              : 
     326           12 :         if (matGlass->GlassSpectralDataPtr > 0) {
     327            0 :             auto aSolarSpectrum = CWCESpecturmProperties::getDefaultSolarRadiationSpectrum(state); // (AUTO_OK_OBJ)
     328            0 :             std::shared_ptr<CSpectralSampleData> aSampleData = nullptr;
     329            0 :             aSampleData = CWCESpecturmProperties::getSpectralSample(state, matGlass->GlassSpectralDataPtr);
     330              : 
     331            0 :             auto aSample = std::make_shared<CSpectralSample>(aSampleData, aSolarSpectrum); // (AUTO_OK_SHARED_PTR)
     332              : 
     333            0 :             FenestrationCommon::MaterialType aType = MaterialType::Monolithic;
     334            0 :             CWavelengthRange aRange(m_Range);
     335            0 :             Real64 lowLambda = aRange.minLambda();
     336            0 :             Real64 highLambda = aRange.maxLambda();
     337              : 
     338              :             // Do not apply detector data if we do not have spectral data. This will only cause more inaccurate results at the end. (Simon)
     339            0 :             if (m_Range == WavelengthRange::Visible && matGlass->GlassSpectralDataPtr != 0) {
     340            0 :                 const auto aPhotopicResponse = CWCESpecturmProperties::getDefaultVisiblePhotopicResponse(state); // (AUTO_OK_OBJ)
     341            0 :                 aSample->setDetectorData(aPhotopicResponse);
     342            0 :             }
     343              : 
     344            0 :             Real64 thickness = matGlass->Thickness;
     345            0 :             m_Material = std::make_shared<CMaterialSample>(aSample, thickness, aType, lowLambda, highLambda);
     346            0 :         } else {
     347           12 :             if (m_Range == WavelengthRange::Solar) {
     348            6 :                 m_Material = std::make_shared<CMaterialSingleBand>(
     349            6 :                     matGlass->Trans, matGlass->Trans, matGlass->ReflectSolBeamFront, matGlass->ReflectSolBeamBack, m_Range);
     350              :             }
     351           12 :             if (m_Range == WavelengthRange::Visible) {
     352            6 :                 m_Material = std::make_shared<CMaterialSingleBand>(
     353            6 :                     matGlass->TransVis, matGlass->TransVis, matGlass->ReflectVisBeamFront, matGlass->ReflectVisBeamBack, m_Range);
     354              :             }
     355              :         }
     356           12 :     }
     357              : 
     358              :     ///////////////////////////////////////////////////////////////////////////////
     359              :     //   CWCEMaterialDualBandFactory
     360              :     ///////////////////////////////////////////////////////////////////////////////
     361            4 :     CWCEMaterialDualBandFactory::CWCEMaterialDualBandFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     362            4 :         : CWCEMaterialFactory(t_Material, t_Range)
     363              :     {
     364            4 :     }
     365              : 
     366            4 :     void CWCEMaterialDualBandFactory::init([[maybe_unused]] EnergyPlusData &state)
     367              :     {
     368            4 :         if (m_Range == WavelengthRange::Visible) {
     369            2 :             m_Material = createVisibleRangeMaterial(state);
     370              :         } else {
     371            2 :             auto aVisibleRangeMaterial = createVisibleRangeMaterial(state); // (AUTO_OK_OBJ)
     372            2 :             auto aSolarRangeMaterial = createSolarRangeMaterial(state);     // (AUTO_OK_OBJ)
     373              :             // Ratio visible to solar range. It can be calculated from solar spectrum.
     374            2 :             Real64 ratio = 0.49;
     375            2 :             m_Material = std::make_shared<CMaterialDualBand>(aVisibleRangeMaterial, aSolarRangeMaterial, ratio);
     376            2 :         }
     377            4 :     }
     378              : 
     379              :     ///////////////////////////////////////////////////////////////////////////////
     380              :     //   CWCEVenetianBlindMaterialsFactory
     381              :     ///////////////////////////////////////////////////////////////////////////////
     382            2 :     CWCEVenetianBlindMaterialsFactory::CWCEVenetianBlindMaterialsFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     383            2 :         : CWCEMaterialDualBandFactory(t_Material, t_Range)
     384              :     {
     385            2 :     }
     386              : 
     387            2 :     std::shared_ptr<CMaterialSingleBand> CWCEVenetianBlindMaterialsFactory::createVisibleRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     388              :     {
     389            2 :         auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(m_MaterialProperties);
     390            2 :         assert(matBlind != nullptr);
     391              : 
     392            2 :         CWavelengthRange aRange(WavelengthRange::Visible);
     393            2 :         Real64 lowLambda = aRange.minLambda();
     394            2 :         Real64 highLambda = aRange.maxLambda();
     395              : 
     396            2 :         Real64 Tf = matBlind->slatTAR.Vis.Ft.Df.Tra;
     397            2 :         Real64 Tb = matBlind->slatTAR.Vis.Ft.Df.Tra;
     398            2 :         Real64 Rf = matBlind->slatTAR.Vis.Ft.Df.Ref;
     399            2 :         Real64 Rb = matBlind->slatTAR.Vis.Bk.Df.Ref;
     400              : 
     401            4 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     402            2 :     }
     403              : 
     404            1 :     std::shared_ptr<CMaterialSingleBand> CWCEVenetianBlindMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     405              :     {
     406            1 :         auto const *matBlind = dynamic_cast<Material::MaterialBlind const *>(m_MaterialProperties);
     407            1 :         assert(matBlind != nullptr);
     408              : 
     409            1 :         CWavelengthRange aRange(WavelengthRange::Solar);
     410            1 :         Real64 lowLambda = aRange.minLambda();
     411            1 :         Real64 highLambda = aRange.maxLambda();
     412              : 
     413            1 :         Real64 Tf = matBlind->slatTAR.Sol.Ft.Df.Tra;
     414            1 :         Real64 Tb = matBlind->slatTAR.Sol.Ft.Df.Tra;
     415            1 :         Real64 Rf = matBlind->slatTAR.Sol.Ft.Df.Ref;
     416            1 :         Real64 Rb = matBlind->slatTAR.Sol.Bk.Df.Ref;
     417              : 
     418            2 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     419            1 :     }
     420              : 
     421              :     ///////////////////////////////////////////////////////////////////////////////
     422              :     //   CWCEScreenMaterialsFactory
     423              :     ///////////////////////////////////////////////////////////////////////////////
     424            0 :     CWCEScreenMaterialsFactory::CWCEScreenMaterialsFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     425            0 :         : CWCEMaterialDualBandFactory(t_Material, t_Range)
     426              :     {
     427              :         // Current EnergyPlus model does not support material transmittance different from zero.
     428              :         // To enable that, it would be necessary to change input in IDF
     429            0 :     }
     430              : 
     431            0 :     std::shared_ptr<CMaterialSingleBand> CWCEScreenMaterialsFactory::createVisibleRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     432              :     {
     433            0 :         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
     434            0 :         assert(matShade != nullptr);
     435            0 :         CWavelengthRange aRange(WavelengthRange::Visible);
     436            0 :         Real64 lowLambda = aRange.minLambda();
     437            0 :         Real64 highLambda = aRange.maxLambda();
     438              : 
     439            0 :         Real64 Tf = 0.0;
     440            0 :         Real64 Tb = 0.0;
     441            0 :         Real64 Rf = matShade->ReflectShadeVis;
     442            0 :         Real64 Rb = matShade->ReflectShadeVis;
     443              : 
     444            0 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     445            0 :     }
     446              : 
     447            0 :     std::shared_ptr<CMaterialSingleBand> CWCEScreenMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     448              :     {
     449            0 :         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
     450            0 :         assert(matShade != nullptr);
     451            0 :         CWavelengthRange aRange(WavelengthRange::Solar);
     452            0 :         Real64 lowLambda = aRange.minLambda();
     453            0 :         Real64 highLambda = aRange.maxLambda();
     454              : 
     455            0 :         Real64 Tf = 0.0;
     456            0 :         Real64 Tb = 0.0;
     457            0 :         Real64 Rf = matShade->ReflectShade;
     458            0 :         Real64 Rb = matShade->ReflectShade;
     459              : 
     460            0 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     461            0 :     }
     462              : 
     463              :     ///////////////////////////////////////////////////////////////////////////////
     464              :     //   CWCEDiffuseShadeMaterialsFactory
     465              :     ///////////////////////////////////////////////////////////////////////////////
     466            2 :     CWCEDiffuseShadeMaterialsFactory::CWCEDiffuseShadeMaterialsFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     467            2 :         : CWCEMaterialDualBandFactory(t_Material, t_Range)
     468              :     {
     469            2 :     }
     470              : 
     471            2 :     std::shared_ptr<CMaterialSingleBand> CWCEDiffuseShadeMaterialsFactory::createVisibleRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     472              :     {
     473            2 :         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
     474            2 :         assert(matShade != nullptr);
     475            2 :         CWavelengthRange aRange(WavelengthRange::Visible);
     476            2 :         Real64 lowLambda = aRange.minLambda();
     477            2 :         Real64 highLambda = aRange.maxLambda();
     478              : 
     479            2 :         Real64 Tf = matShade->TransVis;
     480            2 :         Real64 Tb = matShade->TransVis;
     481            2 :         Real64 Rf = matShade->ReflectShadeVis;
     482            2 :         Real64 Rb = matShade->ReflectShadeVis;
     483              : 
     484            4 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     485            2 :     }
     486              : 
     487            1 :     std::shared_ptr<CMaterialSingleBand> CWCEDiffuseShadeMaterialsFactory::createSolarRangeMaterial([[maybe_unused]] EnergyPlusData &state)
     488              :     {
     489            1 :         auto const *matShade = dynamic_cast<Material::MaterialShade const *>(m_MaterialProperties);
     490            1 :         assert(matShade != nullptr);
     491            1 :         CWavelengthRange aRange(WavelengthRange::Solar);
     492            1 :         Real64 lowLambda = aRange.minLambda();
     493            1 :         Real64 highLambda = aRange.maxLambda();
     494              : 
     495            1 :         Real64 Tf = matShade->Trans;
     496            1 :         Real64 Tb = matShade->Trans;
     497            1 :         Real64 Rf = matShade->ReflectShade;
     498            1 :         Real64 Rb = matShade->ReflectShade;
     499              : 
     500            2 :         return std::make_shared<CMaterialSingleBand>(Tf, Tb, Rf, Rb, lowLambda, highLambda);
     501            1 :     }
     502              : 
     503              :     ///////////////////////////////////////////////////////////////////////////////
     504              :     //   CWCECellFactory
     505              :     ///////////////////////////////////////////////////////////////////////////////
     506           16 :     IWCECellDescriptionFactory::IWCECellDescriptionFactory(const Material::MaterialBase *t_Material) : m_Material(t_Material)
     507              :     {
     508           16 :     }
     509              : 
     510              :     ///////////////////////////////////////////////////////////////////////////////
     511              :     //   CWCESpecularCellFactory
     512              :     ///////////////////////////////////////////////////////////////////////////////
     513              : 
     514           12 :     CWCESpecularCellFactory::CWCESpecularCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
     515              :     {
     516           12 :     }
     517              : 
     518           12 :     std::shared_ptr<ICellDescription> CWCESpecularCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
     519              :     {
     520           12 :         return std::make_shared<CSpecularCellDescription>();
     521              :     }
     522              : 
     523              :     ///////////////////////////////////////////////////////////////////////////////
     524              :     //   CWCEVenetianBlindCellFactory
     525              :     ///////////////////////////////////////////////////////////////////////////////
     526            2 :     CWCEVenetianBlindCellFactory::CWCEVenetianBlindCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
     527              :     {
     528            2 :     }
     529              : 
     530            2 :     std::shared_ptr<ICellDescription> CWCEVenetianBlindCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
     531              :     {
     532            2 :         auto *matBlind = dynamic_cast<Material::MaterialBlind const *>(m_Material);
     533            2 :         assert(matBlind != nullptr);
     534              : 
     535            2 :         Real64 slatWidth = matBlind->SlatWidth;
     536            2 :         Real64 slatSpacing = matBlind->SlatSeparation;
     537            2 :         Real64 slatTiltAngle = 90.0 - matBlind->SlatAngle; // Need to convert to WCE system
     538            2 :         Real64 curvatureRadius = 0.0;                      // No curvature radius in current IDF definition
     539            2 :         size_t numOfSlatSegments = 5;                      // Number of segments to use in venetian calculations
     540            2 :         return std::make_shared<CVenetianCellDescription>(slatWidth, slatSpacing, slatTiltAngle, curvatureRadius, numOfSlatSegments);
     541              :     }
     542              : 
     543              :     ///////////////////////////////////////////////////////////////////////////////
     544              :     //   CWCEScreenCellFactory
     545              :     ///////////////////////////////////////////////////////////////////////////////
     546            0 :     CWCEScreenCellFactory::CWCEScreenCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
     547              :     {
     548            0 :     }
     549              : 
     550            0 :     std::shared_ptr<ICellDescription> CWCEScreenCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
     551              :     {
     552            0 :         Real64 diameter = m_Material->Thickness; // Thickness in this case is diameter
     553              :         // ratio is not saved withing material but rather calculated from transmittance
     554            0 :         const Real64 ratio = 1.0 - sqrt(dynamic_cast<Material::MaterialScreen const *>(m_Material)->Trans);
     555            0 :         Real64 spacing = diameter / ratio;
     556            0 :         return std::make_shared<CWovenCellDescription>(diameter, spacing);
     557              :     }
     558              : 
     559              :     ///////////////////////////////////////////////////////////////////////////////
     560              :     //   CWCEDiffuseShadeCellFactory
     561              :     ///////////////////////////////////////////////////////////////////////////////
     562            2 :     CWCEDiffuseShadeCellFactory::CWCEDiffuseShadeCellFactory(const Material::MaterialBase *t_Material) : IWCECellDescriptionFactory(t_Material)
     563              :     {
     564            2 :     }
     565              : 
     566            2 :     std::shared_ptr<ICellDescription> CWCEDiffuseShadeCellFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state)
     567              :     {
     568            2 :         return std::make_shared<CFlatCellDescription>();
     569              :     }
     570              : 
     571              :     ///////////////////////////////////////////////////////////////////////////////
     572              :     //   CWCEBSDFLayerFactory
     573              :     ///////////////////////////////////////////////////////////////////////////////
     574           16 :     CWCELayerFactory::CWCELayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     575           16 :         : m_Material(t_Material), m_Range(t_Range), m_BSDFInitialized(false), m_SimpleInitialized(false), m_MaterialFactory(nullptr)
     576              :     {
     577           16 :     }
     578              : 
     579           16 :     std::pair<std::shared_ptr<CMaterial>, std::shared_ptr<ICellDescription>> CWCELayerFactory::init(EnergyPlusData &state)
     580              :     {
     581           16 :         createMaterialFactory();
     582           16 :         auto aMaterial = m_MaterialFactory->getMaterial(state); // (AUTO_OK_SHARED_PTR)
     583           16 :         assert(aMaterial != nullptr);
     584           16 :         auto aCellDescription = getCellDescription(state); // (AUTO_OK_SHARED_PTR)
     585           16 :         assert(aCellDescription != nullptr);
     586              : 
     587           32 :         return std::make_pair(aMaterial, aCellDescription);
     588           16 :     }
     589              : 
     590            0 :     std::shared_ptr<CBSDFLayer> CWCELayerFactory::getBSDFLayer(EnergyPlusData &state)
     591              :     {
     592            0 :         if (!m_BSDFInitialized) {
     593            0 :             auto res = init(state);                                      // (AUTO_OK_SHARED_PTR)
     594            0 :             const auto aBSDF = CBSDFHemisphere::create(BSDFBasis::Full); // (AUTO_OK_OBJ)
     595              : 
     596            0 :             CBSDFLayerMaker aMaker(res.first, aBSDF, res.second);
     597            0 :             m_BSDFLayer = aMaker.getLayer();
     598            0 :             m_BSDFInitialized = true;
     599            0 :         }
     600            0 :         return m_BSDFLayer;
     601              :     }
     602              : 
     603           16 :     CScatteringLayer CWCELayerFactory::getLayer(EnergyPlusData &state)
     604              :     {
     605           16 :         if (!m_SimpleInitialized) {
     606           16 :             auto res = init(state); // (AUTO_OK_SHARED_PTR)
     607              : 
     608           16 :             m_ScatteringLayer = CScatteringLayer(res.first, res.second);
     609           16 :             m_SimpleInitialized = true;
     610           16 :         }
     611           16 :         return m_ScatteringLayer;
     612              :     }
     613              : 
     614           16 :     std::shared_ptr<ICellDescription> CWCELayerFactory::getCellDescription([[maybe_unused]] EnergyPlusData &state) const
     615              :     {
     616           16 :         return m_CellFactory->getCellDescription(state);
     617              :     }
     618              : 
     619              :     ///////////////////////////////////////////////////////////////////////////////
     620              :     //   CWCESpecularLayerFactory
     621              :     ///////////////////////////////////////////////////////////////////////////////
     622           12 :     CWCESpecularLayerFactory::CWCESpecularLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     623           12 :         : CWCELayerFactory(t_Material, t_Range)
     624              :     {
     625           12 :         m_CellFactory = std::make_shared<CWCESpecularCellFactory>(t_Material);
     626           12 :     }
     627              : 
     628           12 :     void CWCESpecularLayerFactory::createMaterialFactory()
     629              :     {
     630           12 :         m_MaterialFactory = std::make_shared<CWCESpecularMaterialsFactory>(m_Material, m_Range);
     631           12 :     }
     632              : 
     633              :     ///////////////////////////////////////////////////////////////////////////////
     634              :     //   CWCEVenetianBlindLayerFactory
     635              :     ///////////////////////////////////////////////////////////////////////////////
     636            2 :     CWCEVenetianBlindLayerFactory::CWCEVenetianBlindLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     637            2 :         : CWCELayerFactory(t_Material, t_Range)
     638              :     {
     639            2 :         m_CellFactory = std::make_shared<CWCEVenetianBlindCellFactory>(t_Material);
     640            2 :     }
     641              : 
     642            2 :     void CWCEVenetianBlindLayerFactory::createMaterialFactory()
     643              :     {
     644            2 :         m_MaterialFactory = std::make_shared<CWCEVenetianBlindMaterialsFactory>(m_Material, m_Range);
     645            2 :     }
     646              : 
     647              :     ///////////////////////////////////////////////////////////////////////////////
     648              :     //   CWCEScreenLayerFactory
     649              :     ///////////////////////////////////////////////////////////////////////////////
     650            0 :     CWCEScreenLayerFactory::CWCEScreenLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     651            0 :         : CWCELayerFactory(t_Material, t_Range)
     652              :     {
     653            0 :         m_CellFactory = std::make_shared<CWCEScreenCellFactory>(t_Material);
     654            0 :     }
     655              : 
     656            0 :     void CWCEScreenLayerFactory::createMaterialFactory()
     657              :     {
     658            0 :         m_MaterialFactory = std::make_shared<CWCEScreenMaterialsFactory>(m_Material, m_Range);
     659            0 :     }
     660              : 
     661              :     ///////////////////////////////////////////////////////////////////////////////
     662              :     //   CWCEDiffuseShadeLayerFactory
     663              :     ///////////////////////////////////////////////////////////////////////////////
     664            2 :     CWCEDiffuseShadeLayerFactory::CWCEDiffuseShadeLayerFactory(const Material::MaterialBase *t_Material, const WavelengthRange t_Range)
     665            2 :         : CWCELayerFactory(t_Material, t_Range)
     666              :     {
     667            2 :         m_CellFactory = std::make_shared<CWCEDiffuseShadeCellFactory>(t_Material);
     668            2 :     }
     669              : 
     670            2 :     void CWCEDiffuseShadeLayerFactory::createMaterialFactory()
     671              :     {
     672            2 :         m_MaterialFactory = std::make_shared<CWCEDiffuseShadeMaterialsFactory>(m_Material, m_Range);
     673            2 :     }
     674              : 
     675              : } // namespace Window
     676              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1