LCOV - code coverage report
Current view: top level - EnergyPlus - WindowManagerExteriorOptical.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 224 292 76.7 %
Date: 2023-01-17 19:17:23 Functions: 35 44 79.5 %

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

Generated by: LCOV version 1.13