|
| 1 | +""" |
| 2 | +N. Martin & J. M. Ruiz Spectral Mismatch Modifier |
| 3 | +================================================= |
| 4 | +
|
| 5 | +How to use this correction factor to adjust the POA global irradiance. |
| 6 | +""" |
| 7 | + |
| 8 | +# %% |
| 9 | +# Effectiveness of a material to convert incident sunlight to current depends |
| 10 | +# on the incident light wavelength. During the day, the spectral distribution |
| 11 | +# of the incident irradiance varies from the standard testing spectra, |
| 12 | +# introducing a small difference between the expected and the real output. |
| 13 | +# In [1]_, N. Martín and J. M. Ruiz propose 3 mismatch factors, one for each |
| 14 | +# irradiance component. These mismatch modifiers are calculated with the help |
| 15 | +# of the airmass, the clearness index and three experimental fitting |
| 16 | +# parameters. In the same paper, these parameters have been obtained for m-Si, |
| 17 | +# p-Si and a-Si modules. |
| 18 | +# With :py:func:`pvlib.spectrum.martin_ruiz` we are able to make use of these |
| 19 | +# already computed values or provide ours. |
| 20 | +# |
| 21 | +# References |
| 22 | +# ---------- |
| 23 | +# .. [1] Martín, N. and Ruiz, J.M. (1999), A new method for the spectral |
| 24 | +# characterisation of PV modules. Prog. Photovolt: Res. Appl., 7: 299-310. |
| 25 | +# :doi:`10.1002/(SICI)1099-159X(199907/08)7:4<299::AID-PIP260>3.0.CO;2-0` |
| 26 | +# |
| 27 | +# Calculating the incident and modified global irradiance |
| 28 | +# ------------------------------------------------------- |
| 29 | +# |
| 30 | +# This mismatch modifier is applied to the irradiance components, so first |
| 31 | +# step is to get them. We define an hypothetical POA surface and use a TMY to |
| 32 | +# compute them from a TMY. |
| 33 | + |
| 34 | +import matplotlib.pyplot as plt |
| 35 | +from pvlib import spectrum, irradiance, iotools, location |
| 36 | + |
| 37 | +surface_tilt = 40 |
| 38 | +surface_azimuth = 180 # Pointing South |
| 39 | +# We will need some location to start with & the TMY |
| 40 | +site = location.Location(40.4534, -3.7270, altitude=664, |
| 41 | + name='IES-UPM, Madrid') |
| 42 | + |
| 43 | +pvgis_data, _, _, _ = iotools.get_pvgis_tmy(site.latitude, site.longitude, |
| 44 | + map_variables=True, |
| 45 | + startyear=2005, endyear=2015) |
| 46 | +# Coerce a year: above function returns typical months of different years |
| 47 | +pvgis_data.index = [ts.replace(year=2022) for ts in pvgis_data.index] |
| 48 | +# Select days to show |
| 49 | +weather_data = pvgis_data['2022-10-03':'2022-10-07'] |
| 50 | + |
| 51 | +# Then calculate all we need to get the irradiance components |
| 52 | +solar_pos = site.get_solarposition(weather_data.index) |
| 53 | + |
| 54 | +extra_rad = irradiance.get_extra_radiation(weather_data.index) |
| 55 | + |
| 56 | +poa_sky_diffuse = irradiance.haydavies(surface_tilt, surface_azimuth, |
| 57 | + weather_data['dhi'], |
| 58 | + weather_data['dni'], |
| 59 | + extra_rad, |
| 60 | + solar_pos['apparent_zenith'], |
| 61 | + solar_pos['azimuth']) |
| 62 | + |
| 63 | +poa_ground_diffuse = irradiance.get_ground_diffuse(surface_tilt, |
| 64 | + weather_data['ghi']) |
| 65 | + |
| 66 | +aoi = irradiance.aoi(surface_tilt, surface_azimuth, |
| 67 | + solar_pos['apparent_zenith'], solar_pos['azimuth']) |
| 68 | + |
| 69 | +# %% |
| 70 | +# Let's consider this the irradiance components without spectral modifiers. |
| 71 | +# We can calculate the mismatch before and then create a "poa_irrad" var for |
| 72 | +# modified components directly, but we want to show the output difference. |
| 73 | +# Also, note that :py:func:`pvlib.spectrum.martin_ruiz` result is designed to |
| 74 | +# make it easy to multiply each modifier and the irradiance component with a |
| 75 | +# single line of code, if you get this dataframe before. |
| 76 | + |
| 77 | +poa_irrad = irradiance.poa_components(aoi, weather_data['dni'], |
| 78 | + poa_sky_diffuse, poa_ground_diffuse) |
| 79 | + |
| 80 | +# %% |
| 81 | +# Here comes the modifier. Let's calculate it with the airmass and clearness |
| 82 | +# index. |
| 83 | +# First, let's find the airmass and the clearness index. |
| 84 | +# Little caution: default values for this model were fitted obtaining the |
| 85 | +# airmass through the `'kasten1966'` method, which is not used by default. |
| 86 | + |
| 87 | +airmass = site.get_airmass(solar_position=solar_pos, model='kasten1966') |
| 88 | +clearness_index = irradiance.clearness_index(weather_data['ghi'], |
| 89 | + solar_pos['zenith'], extra_rad) |
| 90 | + |
| 91 | +# Get the spectral mismatch modifiers |
| 92 | +spectral_modifiers = spectrum.martin_ruiz(clearness_index, |
| 93 | + airmass['airmass_absolute'], |
| 94 | + module_type='monosi') |
| 95 | + |
| 96 | +# %% |
| 97 | +# And then we can find the 3 modified components of the POA irradiance |
| 98 | +# by means of a simple multiplication. |
| 99 | +# Note, however, that neither this does modify ``poa_global`` nor |
| 100 | +# ``poa_diffuse``, so we should update the dataframe afterwards. |
| 101 | + |
| 102 | +poa_irrad_modified = poa_irrad * spectral_modifiers |
| 103 | + |
| 104 | +# We want global modified irradiance |
| 105 | +poa_irrad_modified['poa_global'] = (poa_irrad_modified['poa_direct'] |
| 106 | + + poa_irrad_modified['poa_sky_diffuse'] |
| 107 | + + poa_irrad_modified['poa_ground_diffuse']) |
| 108 | +# Don't forget to update `'poa_diffuse'` if you want to use it |
| 109 | +# poa_irrad_modified['poa_diffuse'] = \ |
| 110 | +# (poa_irrad_modified['poa_sky_diffuse'] |
| 111 | +# + poa_irrad_modified['poa_ground_diffuse']) |
| 112 | + |
| 113 | +# %% |
| 114 | +# Finally, let's plot the incident vs modified global irradiance, and their |
| 115 | +# difference. |
| 116 | + |
| 117 | +poa_irrad_global_diff = (poa_irrad['poa_global'] |
| 118 | + - poa_irrad_modified['poa_global']) |
| 119 | +poa_irrad['poa_global'].plot() |
| 120 | +poa_irrad_modified['poa_global'].plot() |
| 121 | +poa_irrad_global_diff.plot() |
| 122 | +plt.legend(['Incident', 'Modified', 'Difference']) |
| 123 | +plt.ylabel('POA Global irradiance [W/m²]') |
| 124 | +plt.show() |
0 commit comments