0

I am using pvlib to calculate diffuse and direct incoming solar radiation at the surface and this works well. I account for clouds, albedo, sea-ice etc. when calculating the total incoming shortwave radiation at the surface.

....
transmittance = (1.0 - cloud_covers) * 0.75
# irrads is a DataFrame containing ghi, dni, dhi

irrads = pvlib.irradiance.liujordan(solpos['apparent_zenith'].to_numpy(), transmittance, am_abs_array)

total_irrad = pvlib.irradiance.get_total_irradiance(surface_tilt,
                                                    surface_azimuth,
                                                    apparent_zenith,
                                                    azimuth,
                                                    irrads['dni'],
                                                    irrads['ghi'],
                                                    irrads['dhi'],
                                                    albedo=albedo)
sw_dr = total_irrad['poa_direct']
sw_df = total_irrad['poa_diffuse']

Now, using the direct (sw_dr) and diffuse (sw_df) shortwave radiation, I wanted to calculate the UV index by 1) Calculating the spectral distribution of the incoming solar radiation by multiplying by the solar energy spectrum 2) Consider only the contribution from the irradiance in the wavelengths 280-400 nm (sw_dr_λ_280-400).

The contribution of each wavelength interval dλ to the direct and diffuse shortwave radiation is weighted by its amount of solar energy under the standard solar spectra ASTM E-490 AM0 (Shanmugam and Ahn, 2007), which is available as a table in the supplementary of Séférian et al. 2018 for wavelengths 200-4000 nm. My understanding is that this gives me the direct and diffuse shortwave radiation as a function of wavelength at 10 nm intervals. To calculate the UV index I used the equation found here:

uvi = np.sum(sw_dr_λ_280_400*erythema_spectrum_λ) * 40.0

Where the erythema_spectrum is the weighting per wavelength band (10 nm) for the effect of erythema.

When I calculate the UVI values using this approach, the values are too high and I wonder if my approach is flawed or whether I am doing something wrong here. Is there anyone else who has calculated UVI using pvlib?

I appreciate your help. Cheers, Trond

Update: I fixed the function above to be more correct. When I calculate UVI north of 30N (0-360E) for January 15 I get an average UVI of 14 but a maximum of 264. This is what it looks like: enter image description here

Update 2: Based on @Cliff H's comment below I divided my values by 25. The new values are within the range for UVI so this seems correct. See plot for UVI for June 2015. enter image description here

Trond Kristiansen
  • 2,379
  • 23
  • 48
  • The range may be correct now, but are the values realistic? If I understand correctly, you are assuming a fixed spectral distribution at all times and places. Maybe this is good enough for your purposes; but if not, I would suggest looking for some data on ozone and taking into account its effect on UV. – adr Dec 02 '20 at 22:00
  • @adr I agree that I am not considering ozone (which obviously is important). I am using climate projections to see how UV light will change in the future accounting for changes in sea-ice, snow, albedo, etc. I realize that I can access "Total Column Ozone" or "Tropospheric Ozone" and include the effect of spatially varying ozone content. Do you have any suggestions for a relationship between UV and ozone? – Trond Kristiansen Dec 02 '20 at 22:18

1 Answers1

1

I don't recognize a conceptual error. What do you get when you integrate the spectral direct irradiance? I'd expect to recover the sw_dr broadband value. Something to check. The line of code that calculates uvi looks odd. sw_dr from total_irrad is a Series, sw_dr(λ[280:400]) indicates that sw_dr is a function.

Cliff H
  • 314
  • 1
  • 3
  • thanks for your comment. I updated the function as it was written to look like a function but based on Python code. It is more correct now. – Trond Kristiansen Dec 02 '20 at 16:43
  • 1
    maybe that formula is computing the total UV effect which is different than the usual UV index? It appears that the effect is divided by 25 to get the index. https://www.epa.gov/sunsafety/calculating-uv-index-0, https://en.wikipedia.org/wiki/Ultraviolet_index – Cliff H Dec 02 '20 at 19:27
  • When I divide my numbers by 25 I get values from 0-12.9 which seems exactly what the UVI should fall within. I guess you are right that I have calculated the total UV effect and need to divide by 25, although it is very unclear to me where the number 25 comes from or what it represents. I compared the UV values calculated using pvlib with Copernicus reanalysis for 2015 and the values are very close so this seems correct. See UVI plot for July 2015. Thank you. – Trond Kristiansen Dec 02 '20 at 21:35
  • @TrondKristiansen this might make an interesting addition to the [example gallery](https://pvlib-python.readthedocs.io/en/stable/auto_examples/index.html), if that interests you! – kevinsa5 Dec 02 '20 at 23:03
  • 1
    @kevinsa5 Sure. I would have to modify the calculations as it is rather complex right now and make a simplified version more suitable as an example. – Trond Kristiansen Dec 02 '20 at 23:51
  • @cliff-h Cliff - any chance you could recommend (have an example) of how I can add the effect of ozone into the calculations of irradiance using pvlib? I see that ozone is used in the Bird clear sky calculations, but not in the Liujordan and get_total_irradiance calls I use. I need the effect of both clouds and ozone to be included. Thanks! – Trond Kristiansen Dec 03 '20 at 17:04
  • @TrondKristiansen I'm not sure that pvlib functions have the resolution to account for ozone. The UV index pertains to irradiance at wavelengths of 350nm or below, but the clearsky and diffuse/direct separation models in pvlib are generally calibrated for broadband shortwave irradiance (300nm to 2400nm, bandwidth varies by model), The contribution to SW irradiance from between 300 and 350nm is very small, so I don't think it's reasonable to view these models as accurate for that portion of the spectrum. The Bird model includes an ozone term because ozone has an absorption band around 1000nm. – Cliff H Dec 06 '20 at 16:01