pvlib / pvlib-python

A set of documented functions for simulating the performance of photovoltaic energy systems.
https://pvlib-python.readthedocs.io
BSD 3-Clause "New" or "Revised" License
1.19k stars 997 forks source link

gti_dirint raises 'UnboundLocalError: local variable 'best_ghi' referenced before assignment' #1342

Open kdebrab opened 2 years ago

kdebrab commented 2 years ago

Describe the bug irradiance.gti_dirint fails for surface faced North

To Reproduce

import pvlib
import pandas as pd
times = pd.date_range('2021-11-24', '2021-11-25', freq='h')
latitude, longitude, surface_tilt, surface_azimuth = 51.3, 4.56, 25, 360
solpos = pvlib.solarposition.get_solarposition(times, latitude, longitude)
solar_zenith, solar_azimuth = solpos['apparent_zenith'], solpos['azimuth']
ghi = pvlib.clearsky.simplified_solis(90 - solar_zenith)['ghi']
poa_global = ghi  # this is not correct, but doesn't really matter for the bug report
aoi = pvlib.irradiance.aoi(surface_tilt, surface_azimuth, solar_zenith, solar_azimuth)
pvlib.irradiance.gti_dirint(poa_global, aoi, solar_zenith, solar_azimuth, times, surface_tilt, surface_azimuth)

raises

UnboundLocalError: local variable 'best_ghi' referenced before assignment

The error is not raised e.g. when surface_azimuth = 180.

Versions:

kdebrab commented 2 years ago

The example is not fully correct (I should have converted ghi to the plane before feeding it to gti_dirint), but that doesn't really matter for the bug report.

In this case, the plane doesn't see the sun during the times, so diriving the components would be trivial/impossible (the plane only sees diffuse), but, in any case, the algorithm should not raise an UnboundLocalError.

cwhanse commented 2 years ago

Confirmed. The problem appears to be that _gti_dirint_lt_90 is always called, without checking if any aoi value is less than 90. The test for gti_dirint doesn't hit this corner case.

Maybe put an if block around this line.

wholmgren commented 2 years ago

It's not as simple as putting an if aoi_lt_90.any() around _gti_dirint_lt_90. _gti_dirint_gte_90 requires the best_kt_prime determined in _gti_dirint_lt_90. I don't think we can make this work without going beyond what's in the Marion paper. I suggest we instead return an informative error if insufficient data is supplied with aoi < 90.