Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spa_python with numba fails with array input #2166

Open
markveillette opened this issue Aug 14, 2024 · 4 comments
Open

spa_python with numba fails with array input #2166

markveillette opened this issue Aug 14, 2024 · 4 comments

Comments

@markveillette
Copy link

Describe the bug
I'm trying to call pvlib.solarposition.spa_python with arrays for time, latitudes and longitudes. It works fine by default, but I get an error if I use how='numba' with the same inputs.

To Reproduce
The following reproduces my error:

import pandas as pd
import numpy as np
import pvlib

N = 100
dates = pd.date_range(start='2020-01-01',end='2050-01-01',periods=N)
lats = np.linspace(-60,60,N)
lons = np.linspace(-80,80,N)

# works fine
print('Testing without numba')
pvlib.solarposition.spa_python(dates, latitude=lats, longitude=lons)
print('worked!')

# fails
print('Testing with numba')
pvlib.solarposition.spa_python(dates, latitude=lats, longitude=lons, how='numba')

The error I get is

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[1], line 17
     15 # fails
     16 print('Testing with numba')
---> 17 pvlib.solarposition.spa_python(dates, latitude=lats, longitude=lons, how='numba')

File ..../lib/python3.11/site-packages/pvlib/solarposition.py:385, in spa_python(time, latitude, longitude, altitude, pressure, temperature, delta_t, atmos_refract, how, numthreads)
    380 spa = _spa_python_import(how)
    382 delta_t = delta_t or spa.calculate_deltat(time.year, time.month)
    384 app_zenith, zenith, app_elevation, elevation, azimuth, eot = \
--> 385     spa.solar_position(unixtime, lat, lon, elev, pressure, temperature,
    386                        delta_t, atmos_refract, numthreads)
    388 result = pd.DataFrame({'apparent_zenith': app_zenith, 'zenith': zenith,
    389                        'apparent_elevation': app_elevation,
    390                        'elevation': elevation, 'azimuth': azimuth,
    391                        'equation_of_time': eot},
    392                       index=time)
    394 return result

File .../lib/python3.11/site-packages/pvlib/spa.py:1088, in solar_position(unixtime, lat, lon, elev, pressure, temp, delta_t, atmos_refract, numthreads, sst, esd)
   1085 else:
   1086     do_calc = solar_position_numpy
-> 1088 result = do_calc(unixtime, lat, lon, elev, pressure,
   1089                  temp, delta_t, atmos_refract, numthreads,
   1090                  sst, esd)
   1092 if not isinstance(result, np.ndarray):
   1093     try:

File .../python3.11/site-packages/pvlib/spa.py:923, in solar_position_numba(unixtime, lat, lon, elev, pressure, temp, delta_t, atmos_refract, numthreads, sst, esd)
    919 """Calculate the solar position using the numba compiled functions
    920 and multiple threads. Very slow if functions are not numba compiled.
    921 """
    922 # these args are the same for each thread
--> 923 loc_args = np.array([lat, lon, elev, pressure, temp, delta_t,
    924                      atmos_refract, sst, esd])
    926 # construct dims x ulength array to put the results in
    927 ulength = unixtime.shape[0]

ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (9,) + inhomogeneous part.

Expected behavior
Both calls to spa_python should give same result, given the inputs are identical.

Versions:

  • pvlib.__version__: 0.11.0
  • pandas.__version__: 2.2.2
  • python:3.11
  • numba : 0.60.0
@kandersolar
Copy link
Member

I'm inclined to consider this a feature request rather than a bug report since spa_python's docstring specifies that latitude and longitude are of type float (not array). Arrays being allowed with how='numpy' is coincidental :)

It seems possible to modify the numba code to allow arrays for lat/lon, although the code might be a little ugly.

@markveillette do you need specifically the SPA for your application, or would a faster (but somewhat less accurate) solar position algorithm be acceptable?

@markveillette
Copy link
Author

fair enough! That makes total sense, appreciate you looking at this so quickly.

For my use case, yes, I am okay with fast-but-not-perfectly-accurate. e.g. <1 degree error.

I've found a some repos online that offer this, e.g. https://github.com/david-salac/Fast-SZA-and-SAA-computation/tree/master
or @leaver2000 's https://github.com/leaver2000/fast_spa. If you have other alternatives that handle array inputs I can definitely look into them.

@AdamRJensen
Copy link
Member

AdamRJensen commented Aug 14, 2024

SG2 was developed for a mesh of latitudes and longitudes: https://github.com/gschwind/sg2

Works for python < 3.12

@kandersolar
Copy link
Member

Another option in pvlib is pvlib.solarposition.ephemeris. I'd expect it to work with array input for lat/lon, although also coincidentally.

A future version of pvlib may have even better alternatives.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants