From 3363ace052d9137480ab715a540e997e07dfa088 Mon Sep 17 00:00:00 2001 From: Jesus Polo Date: Wed, 25 Jun 2025 08:07:02 +0200 Subject: [PATCH 1/6] Add polo-smm Add the polo spectral model for BIPV facades --- pvlib/spectrum/mismatch.py | 99 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/pvlib/spectrum/mismatch.py b/pvlib/spectrum/mismatch.py index 980f0d0165..0fbcd80234 100644 --- a/pvlib/spectrum/mismatch.py +++ b/pvlib/spectrum/mismatch.py @@ -710,3 +710,102 @@ def spectral_factor_jrc(airmass, clearsky_index, module_type=None, + coeff[2] * (airmass - 1.5) ) return mismatch + +def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, altitude, + module_type=None, coefficients=None, albedo=0.2): + """ + Estimation of spectral mismatch for BIPV application in vertical facades. + + + + Parameters + ---------- + precipitable_water : numeric + atmospheric precipitable water. [cm] + + airmass_absolute : numeric + absolute (pressure-adjusted) airmass. [unitless] + + aod500 : numeric + atmospheric aerosol optical depth at 500 nm. [unitless] + + aoi : numeric + angle of incidence. [degrees] + + altitude: numeric + altitude over sea level. [m] + + module_type : str, optional + One of the following PV technology strings from [1]_: + + * ``'cdte'`` - anonymous CdTe module. + * ``'monosi'`` - anonymous sc-si module. + * ``'cigs'`` - anonymous copper indium gallium selenide module. + * ``'asi'`` - anonymous amorphous silicon module. + albedo + Ground albedo (default value if 0.2). [unitless] + + coefficients : array-like, optional + user-defined coefficients, if not using one of the default coefficient + sets via the ``module_type`` parameter. + + Returns + ------- + modifier: numeric + spectral mismatch factor (unitless) which is multiplied + with broadband irradiance reaching a module's cells to estimate + effective irradiance, i.e., the irradiance that is converted to + electrical current. + + References + ---------- + [1]. Polo, J., Sanz-saiz, C., Development of spectral mismatch models + for BIPV applications in building façades Abbreviations : Renew. Energy 245, 122820, 2025. + https://doi.org/10.1016/j.renene.2025.122820 + + """ + if module_type is None and coefficients is None: + raise ValueError('Must provide either `module_type` or `coefficients`') + if module_type is not None and coefficients is not None: + raise ValueError('Only one of `module_type` and `coefficients` should ' + 'be provided') + + am_aoi=pvlib.atmosphere.get_relative_airmass(aoi) + pressure=pvlib.atmosphere.alt2pres(altitude) + am90=pvlib.atmosphere.get_absolute_airmass(am_aoi,pressure) + Ram=am90/airmass_absolute + + _coefficients={} + _coefficients['cdte']=( + -0.0009,46.80,49.20,-0.87, 0.00041,0.053 ) + _coefficients['monosi']=( + 0.0027,10.34,9.48,0.307,0.00077,0.006 ) + _coefficients['cigs']=( + 0.0017,2.33,1.30,0.11,0.00098,-0.0177 ) + _coefficients['asi']=( + 0.0024,7.32,7.09,-0.72,-0.0013,0.089 ) + + c={} + c['asi']=(0.0056,-0.020,1.014) + c['cigs']=(-0.0009,-0.0003,1) + c['cdte']=(0.0021,-0.01,1.01) + c['monosi']=(0,-0.003,1.0) + + + if module_type is not None: + coeff = _coefficients[module_type] + c_albedo=c[module_type] + else: + coeff = coefficients + c_albedo=(0.0,0.0,1.0) # 0.2 albedo assumed + albedo=0.2 + + + smm=coeff[0]*Ram+coeff[1]/(coeff[2]+Ram**coeff[3])+coeff[4]/aod500+coeff[5]*np.sqrt(precipitable_water) + # Ground albedo correction + + g=c_albedo[0]*(albedo/0.2)**2+c_albedo[1]*(albedo/0.2)+c_albedo[2] + + + return g*smm + \ No newline at end of file From ceba758c14c346f7e1703e7cadf2aa06c331b25d Mon Sep 17 00:00:00 2001 From: Jesus Polo Date: Wed, 25 Jun 2025 10:39:48 +0200 Subject: [PATCH 2/6] Apply suggestions from code review Co-authored-by: Adam R. Jensen <39184289+AdamRJensen@users.noreply.github.com> --- pvlib/spectrum/mismatch.py | 66 +++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/pvlib/spectrum/mismatch.py b/pvlib/spectrum/mismatch.py index 0fbcd80234..4b194db537 100644 --- a/pvlib/spectrum/mismatch.py +++ b/pvlib/spectrum/mismatch.py @@ -711,13 +711,12 @@ def spectral_factor_jrc(airmass, clearsky_index, module_type=None, ) return mismatch -def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, altitude, - module_type=None, coefficients=None, albedo=0.2): + +def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, + altitude, module_type=None, coefficients=None, + albedo=0.2): """ Estimation of spectral mismatch for BIPV application in vertical facades. - - - Parameters ---------- precipitable_water : numeric @@ -725,16 +724,12 @@ def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, alti airmass_absolute : numeric absolute (pressure-adjusted) airmass. [unitless] - aod500 : numeric atmospheric aerosol optical depth at 500 nm. [unitless] - aoi : numeric angle of incidence. [degrees] - altitude: numeric - altitude over sea level. [m] - + altitude over sea level. [m] module_type : str, optional One of the following PV technology strings from [1]_: @@ -743,11 +738,11 @@ def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, alti * ``'cigs'`` - anonymous copper indium gallium selenide module. * ``'asi'`` - anonymous amorphous silicon module. albedo - Ground albedo (default value if 0.2). [unitless] + Ground albedo (default value if 0.2). [unitless] coefficients : array-like, optional user-defined coefficients, if not using one of the default coefficient - sets via the ``module_type`` parameter. + set via the ``module_type`` parameter. Returns ------- @@ -761,7 +756,7 @@ def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, alti ---------- [1]. Polo, J., Sanz-saiz, C., Development of spectral mismatch models for BIPV applications in building façades Abbreviations : Renew. Energy 245, 122820, 2025. - https://doi.org/10.1016/j.renene.2025.122820 + :doi:`10.1016/j.renene.2025.122820` """ if module_type is None and coefficients is None: @@ -776,36 +771,33 @@ def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, alti Ram=am90/airmass_absolute _coefficients={} - _coefficients['cdte']=( - -0.0009,46.80,49.20,-0.87, 0.00041,0.053 ) - _coefficients['monosi']=( - 0.0027,10.34,9.48,0.307,0.00077,0.006 ) - _coefficients['cigs']=( - 0.0017,2.33,1.30,0.11,0.00098,-0.0177 ) - _coefficients['asi']=( - 0.0024,7.32,7.09,-0.72,-0.0013,0.089 ) - - c={} - c['asi']=(0.0056,-0.020,1.014) - c['cigs']=(-0.0009,-0.0003,1) - c['cdte']=(0.0021,-0.01,1.01) - c['monosi']=(0,-0.003,1.0) + _coefficients = { + 'cdte': (-0.0009, 46.80, 49.20, -0.87, 0.00041, 0.053), + 'monosi': (0.0027, 10.34, 9.48, 0.307, 0.00077, 0.006), + 'cigs': (0.0017, 2.33, 1.30, 0.11, 0.00098, -0.0177), + 'asi': (0.0024, 7.32, 7.09, -0.72, -0.0013, 0.089), + } + c = { + 'asi': (0.0056, -0.020, 1.014), + 'cigs': (-0.0009, -0.0003, 1), + 'cdte': (0.0021, -0.01, 1.01), + 'monosi': (0, -0.003, 1.0), + } if module_type is not None: coeff = _coefficients[module_type] - c_albedo=c[module_type] + c_albedo = c[module_type] else: coeff = coefficients - c_albedo=(0.0,0.0,1.0) # 0.2 albedo assumed - albedo=0.2 - + c_albedo = (0.0, 0.0, 1.0) # 0.2 albedo assumed + albedo = 0.2 - smm=coeff[0]*Ram+coeff[1]/(coeff[2]+Ram**coeff[3])+coeff[4]/aod500+coeff[5]*np.sqrt(precipitable_water) + smm = coeff[0] * Ram + coeff[1] / (coeff[2] + Ram**coeff[3]) \ + + coeff[4] / aod500 + coeff[5]*np.sqrt(precipitable_water) + # Ground albedo correction - - g=c_albedo[0]*(albedo/0.2)**2+c_albedo[1]*(albedo/0.2)+c_albedo[2] - - + g = c_albedo[0] * (albedo/0.2)**2 \ + + c_albedo[1] * (albedo/0.2) + c_albedo[2] + return g*smm - \ No newline at end of file From 36c9b43dbf805ba82f26680cd81dbadfd0d75447 Mon Sep 17 00:00:00 2001 From: Jesus Polo Date: Wed, 25 Jun 2025 11:53:33 +0200 Subject: [PATCH 3/6] Update mismatch.py --- pvlib/spectrum/mismatch.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pvlib/spectrum/mismatch.py b/pvlib/spectrum/mismatch.py index 4b194db537..f10dc5d8dc 100644 --- a/pvlib/spectrum/mismatch.py +++ b/pvlib/spectrum/mismatch.py @@ -755,8 +755,8 @@ def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, References ---------- [1]. Polo, J., Sanz-saiz, C., Development of spectral mismatch models - for BIPV applications in building façades Abbreviations : Renew. Energy 245, 122820, 2025. - :doi:`10.1016/j.renene.2025.122820` + for BIPV applications in building façades Abbreviations : Renew. Energy 245 + ,122820, 2025.:doi:`10.1016/j.renene.2025.122820` """ if module_type is None and coefficients is None: @@ -765,12 +765,12 @@ def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, raise ValueError('Only one of `module_type` and `coefficients` should ' 'be provided') - am_aoi=pvlib.atmosphere.get_relative_airmass(aoi) - pressure=pvlib.atmosphere.alt2pres(altitude) - am90=pvlib.atmosphere.get_absolute_airmass(am_aoi,pressure) - Ram=am90/airmass_absolute + am_aoi = pvlib.atmosphere.get_relative_airmass(aoi) + pressure = pvlib.atmosphere.alt2pres(altitude) + am90 = pvlib.atmosphere.get_absolute_airmass(am_aoi,pressure) + Ram = am90/airmass_absolute - _coefficients={} + _coefficients = {} _coefficients = { 'cdte': (-0.0009, 46.80, 49.20, -0.87, 0.00041, 0.053), 'monosi': (0.0027, 10.34, 9.48, 0.307, 0.00077, 0.006), From eaa90b4281c240991b260198b193af464c6f5309 Mon Sep 17 00:00:00 2001 From: Jesus Polo Date: Wed, 25 Jun 2025 12:09:19 +0200 Subject: [PATCH 4/6] Update mismatch.py --- pvlib/spectrum/mismatch.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pvlib/spectrum/mismatch.py b/pvlib/spectrum/mismatch.py index f10dc5d8dc..375b9f340b 100644 --- a/pvlib/spectrum/mismatch.py +++ b/pvlib/spectrum/mismatch.py @@ -757,19 +757,16 @@ def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, [1]. Polo, J., Sanz-saiz, C., Development of spectral mismatch models for BIPV applications in building façades Abbreviations : Renew. Energy 245 ,122820, 2025.:doi:`10.1016/j.renene.2025.122820` - """ if module_type is None and coefficients is None: raise ValueError('Must provide either `module_type` or `coefficients`') if module_type is not None and coefficients is not None: raise ValueError('Only one of `module_type` and `coefficients` should ' 'be provided') - am_aoi = pvlib.atmosphere.get_relative_airmass(aoi) pressure = pvlib.atmosphere.alt2pres(altitude) - am90 = pvlib.atmosphere.get_absolute_airmass(am_aoi,pressure) + am90 = pvlib.atmosphere.get_absolute_airmass(am_aoi, pressure) Ram = am90/airmass_absolute - _coefficients = {} _coefficients = { 'cdte': (-0.0009, 46.80, 49.20, -0.87, 0.00041, 0.053), @@ -777,27 +774,22 @@ def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, 'cigs': (0.0017, 2.33, 1.30, 0.11, 0.00098, -0.0177), 'asi': (0.0024, 7.32, 7.09, -0.72, -0.0013, 0.089), } - c = { 'asi': (0.0056, -0.020, 1.014), 'cigs': (-0.0009, -0.0003, 1), 'cdte': (0.0021, -0.01, 1.01), 'monosi': (0, -0.003, 1.0), } - - if module_type is not None: + if module_type is not None: coeff = _coefficients[module_type] c_albedo = c[module_type] else: coeff = coefficients c_albedo = (0.0, 0.0, 1.0) # 0.2 albedo assumed albedo = 0.2 - smm = coeff[0] * Ram + coeff[1] / (coeff[2] + Ram**coeff[3]) \ + coeff[4] / aod500 + coeff[5]*np.sqrt(precipitable_water) - # Ground albedo correction g = c_albedo[0] * (albedo/0.2)**2 \ + c_albedo[1] * (albedo/0.2) + c_albedo[2] - return g*smm From 794ed9898ecef4ff735c6260c6d81608e701ed74 Mon Sep 17 00:00:00 2001 From: Jesus Polo Date: Wed, 25 Jun 2025 12:17:39 +0200 Subject: [PATCH 5/6] Update mismatch.py --- pvlib/spectrum/mismatch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/spectrum/mismatch.py b/pvlib/spectrum/mismatch.py index 375b9f340b..df1349d21a 100644 --- a/pvlib/spectrum/mismatch.py +++ b/pvlib/spectrum/mismatch.py @@ -780,7 +780,7 @@ def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, 'cdte': (0.0021, -0.01, 1.01), 'monosi': (0, -0.003, 1.0), } - if module_type is not None: + if module_type is not None: coeff = _coefficients[module_type] c_albedo = c[module_type] else: From 7926a3d821763b6a32d9d8fab7b6cbffa131df23 Mon Sep 17 00:00:00 2001 From: Jesus Polo Date: Wed, 25 Jun 2025 12:51:55 +0200 Subject: [PATCH 6/6] Update mismatch.py --- pvlib/spectrum/mismatch.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pvlib/spectrum/mismatch.py b/pvlib/spectrum/mismatch.py index df1349d21a..da00e28fdc 100644 --- a/pvlib/spectrum/mismatch.py +++ b/pvlib/spectrum/mismatch.py @@ -754,9 +754,9 @@ def spectral_factor_polo(precipitable_water, airmass_absolute, aod500, aoi, References ---------- - [1]. Polo, J., Sanz-saiz, C., Development of spectral mismatch models - for BIPV applications in building façades Abbreviations : Renew. Energy 245 - ,122820, 2025.:doi:`10.1016/j.renene.2025.122820` + [1] J. Polo and C. Sanz-Saiz, 'Development of spectral mismatch models + for BIPV applications in building façades', Renewable Energy, vol. 245, + p. 122820, Jun. 2025,:doi:`10.1016/j.renene.2025.122820` """ if module_type is None and coefficients is None: raise ValueError('Must provide either `module_type` or `coefficients`')