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