@@ -698,3 +698,104 @@ def spectral_factor_jrc(airmass, clearsky_index, module_type=None,
698698 + coeff [2 ] * (airmass - 1.5 )
699699 )
700700 return mismatch
701+
702+
703+ def spectral_factor_polo (precipitable_water , airmass_absolute , aod500 , aoi ,
704+ pressure , module_type = None , coefficients = None ,
705+ albedo = 0.2 ):
706+ """
707+ Estimate the spectral mismatch for BIPV application in vertical facades.
708+
709+ The model's authors note that this model could also be applied to
710+ vertical bifacial ground-mount systems [1]_, although it has not been
711+ validated in that context.
712+
713+ Parameters
714+ ----------
715+ precipitable_water : numeric
716+ Atmospheric precipitable water. [cm]
717+ airmass_absolute : numeric
718+ Absolute (pressure-adjusted) airmass. See :term:`airmass_absolute`.
719+ [unitless]
720+ aod500 : numeric
721+ Atmospheric aerosol optical depth at 500 nm. [unitless]
722+ aoi : numeric
723+ Angle of incidence on the vertical surface. See :term:`aoi`.
724+ [degrees]
725+ pressure : numeric
726+ Atmospheric pressure. See :term:`pressure`. [Pa]
727+ module_type : str, optional
728+ One of the following PV technology strings from [1]_:
729+
730+ * ``'cdte'`` - anonymous CdTe module.
731+ * ``'monosi'`` - anonymous monocrystalline silicon module.
732+ * ``'cigs'`` - anonymous copper indium gallium selenide module.
733+ * ``'asi'`` - anonymous amorphous silicon module.
734+ coefficients : array-like, optional
735+ User-defined coefficients, if not using one of the coefficient
736+ sets via the ``module_type`` parameter. Must have nine elements.
737+ The first six elements correspond to the [p1, p2, p3, p4, b, c]
738+ parameters of the SMM model. The last three elements corresponds
739+ to the [c1, c2, c3] parameters of the albedo correction factor.
740+ albedo : numeric, default 0.2
741+ Ground albedo. See :term:`albedo`. [unitless]
742+
743+ Returns
744+ -------
745+ modifier: numeric
746+ spectral mismatch factor (unitless) which is multiplied
747+ with broadband irradiance reaching a module's cells to estimate
748+ effective irradiance, i.e., the irradiance that is converted to
749+ electrical current.
750+
751+ Notes
752+ -----
753+ The Polo model was developed using only SMM values computed for scenarios
754+ when the sun is visible from the module's surface (i.e., for ``aoi<90``),
755+ and no provision was made in [1]_ for the case of ``aoi>90``. This would
756+ create issues in the air mass calculation internal to the model.
757+ Following discussion with the model's author, the pvlib implementation
758+ handles ``aoi>90`` by truncating the input ``aoi`` to a maximum of
759+ 90 degrees.
760+
761+ References
762+ ----------
763+ .. [1] J. Polo and C. Sanz-Saiz, 'Development of spectral mismatch models
764+ for BIPV applications in building façades', Renewable Energy, vol. 245,
765+ p. 122820, Jun. 2025, :doi:`10.1016/j.renene.2025.122820`
766+ """
767+ if module_type is None and coefficients is None :
768+ raise ValueError ('Must provide either `module_type` or `coefficients`' )
769+ if module_type is not None and coefficients is not None :
770+ raise ValueError ('Only one of `module_type` and `coefficients` should '
771+ 'be provided' )
772+ # prevent nan for aoi greater than 90; see docstring Notes
773+ aoi = np .clip (aoi , a_min = None , a_max = 90 )
774+ f_aoi_rel = pvlib .atmosphere .get_relative_airmass (aoi ,
775+ model = 'kastenyoung1989' )
776+ f_aoi = pvlib .atmosphere .get_absolute_airmass (f_aoi_rel , pressure )
777+ Ram = f_aoi / airmass_absolute
778+ _coefficients = {
779+ 'cdte' : (- 0.0009 , 46.80 , 49.20 , - 0.87 , 0.00041 , 0.053 ),
780+ 'monosi' : (0.0027 , 10.34 , 9.48 , 0.31 , 0.00077 , 0.006 ),
781+ 'cigs' : (0.0017 , 2.33 , 1.30 , 0.11 , 0.00098 , - 0.018 ),
782+ 'asi' : (0.0024 , 7.32 , 7.09 , - 0.72 , - 0.0013 , 0.089 ),
783+ }
784+ c = {
785+ 'asi' : (0.0056 , - 0.020 , 1.014 ),
786+ 'cigs' : (- 0.0009 , - 0.0003 , 1 ),
787+ 'cdte' : (0.0021 , - 0.01 , 1.01 ),
788+ 'monosi' : (0 , - 0.003 , 1.0 ),
789+ }
790+ if module_type is not None :
791+ coeff = _coefficients [module_type ]
792+ c_albedo = c [module_type ]
793+ else :
794+ coeff = coefficients [:6 ]
795+ c_albedo = coefficients [6 :]
796+ smm = coeff [0 ] * Ram + coeff [1 ] / (coeff [2 ] + Ram ** coeff [3 ]) \
797+ + coeff [4 ] / aod500 + coeff [5 ]* np .sqrt (precipitable_water )
798+ # Ground albedo correction
799+ g = c_albedo [0 ] * (albedo / 0.2 )** 2 \
800+ + c_albedo [1 ] * (albedo / 0.2 ) + c_albedo [2 ]
801+ return g * smm
0 commit comments