From f04d3a0bf75869ef5587e10ff25793a4fade889e Mon Sep 17 00:00:00 2001 From: James Fulton Date: Mon, 18 Aug 2025 19:19:34 +0000 Subject: [PATCH 1/3] convert loops to numpy --- pvlib/spa.py | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/pvlib/spa.py b/pvlib/spa.py index d4181aaa49..f0e1d328b2 100644 --- a/pvlib/spa.py +++ b/pvlib/spa.py @@ -456,9 +456,7 @@ def julian_ephemeris_millennium(julian_ephemeris_century): @jcompile(nopython=True) def sum_mult_cos_add_mult(arr, x): # shared calculation used for heliocentric longitude, latitude, and radius - s = 0. - for row in range(arr.shape[0]): - s += arr[row, 0] * np.cos(arr[row, 1] + arr[row, 2] * x) + s = (arr[:, [0]] * np.cos(arr[:, [1]] + arr[:, [2]] * np.expand_dims(x, axis=0))).sum(axis=0) return s @jcompile('float64(float64)', nopython=True) @@ -559,22 +557,20 @@ def moon_ascending_longitude(julian_ephemeris_century): nopython=True) def longitude_obliquity_nutation(julian_ephemeris_century, x0, x1, x2, x3, x4, out): - delta_psi_sum = 0.0 - delta_eps_sum = 0.0 - for row in range(NUTATION_YTERM_ARRAY.shape[0]): - a = NUTATION_ABCD_ARRAY[row, 0] - b = NUTATION_ABCD_ARRAY[row, 1] - c = NUTATION_ABCD_ARRAY[row, 2] - d = NUTATION_ABCD_ARRAY[row, 3] - arg = np.radians( - NUTATION_YTERM_ARRAY[row, 0]*x0 + - NUTATION_YTERM_ARRAY[row, 1]*x1 + - NUTATION_YTERM_ARRAY[row, 2]*x2 + - NUTATION_YTERM_ARRAY[row, 3]*x3 + - NUTATION_YTERM_ARRAY[row, 4]*x4 - ) - delta_psi_sum += (a + b * julian_ephemeris_century) * np.sin(arg) - delta_eps_sum += (c + d * julian_ephemeris_century) * np.cos(arg) + a = NUTATION_ABCD_ARRAY[:, [0]] + b = NUTATION_ABCD_ARRAY[:, [1]] + c = NUTATION_ABCD_ARRAY[:, [2]] + d = NUTATION_ABCD_ARRAY[:, [3]] + arg = np.radians( + NUTATION_YTERM_ARRAY[:, [0]]*np.expand_dims(x0, axis=0) + + NUTATION_YTERM_ARRAY[:, [1]]*np.expand_dims(x1, axis=0) + + NUTATION_YTERM_ARRAY[:, [2]]*np.expand_dims(x2, axis=0) + + NUTATION_YTERM_ARRAY[:, [3]]*np.expand_dims(x3, axis=0) + + NUTATION_YTERM_ARRAY[:, [4]]*np.expand_dims(x4, axis=0) + ) + + delta_psi_sum = ((a + b * julian_ephemeris_century) * np.sin(arg)).sum(axis=0) + delta_eps_sum = ((c + d * julian_ephemeris_century) * np.cos(arg)).sum(axis=0) delta_psi = delta_psi_sum*1.0/36000000 delta_eps = delta_eps_sum*1.0/36000000 # seems like we ought to be able to return a tuple here instead From 16af92db119c46eb531a1387dd3a851cbdae92f2 Mon Sep 17 00:00:00 2001 From: James Fulton Date: Mon, 18 Aug 2025 20:26:21 +0000 Subject: [PATCH 2/3] fix numba inference --- pvlib/spa.py | 56 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/pvlib/spa.py b/pvlib/spa.py index f0e1d328b2..d664ffda7b 100644 --- a/pvlib/spa.py +++ b/pvlib/spa.py @@ -456,7 +456,12 @@ def julian_ephemeris_millennium(julian_ephemeris_century): @jcompile(nopython=True) def sum_mult_cos_add_mult(arr, x): # shared calculation used for heliocentric longitude, latitude, and radius - s = (arr[:, [0]] * np.cos(arr[:, [1]] + arr[:, [2]] * np.expand_dims(x, axis=0))).sum(axis=0) + if USE_NUMBA: + s = 0. + for row in range(arr.shape[0]): + s += arr[row, 0] * np.cos(arr[row, 1] + arr[row, 2] * x) + else: + s = (arr[:, [0]] * np.cos(arr[:, [1]] + arr[:, [2]] * np.expand_dims(x, axis=0))).sum(axis=0) return s @jcompile('float64(float64)', nopython=True) @@ -557,20 +562,41 @@ def moon_ascending_longitude(julian_ephemeris_century): nopython=True) def longitude_obliquity_nutation(julian_ephemeris_century, x0, x1, x2, x3, x4, out): - a = NUTATION_ABCD_ARRAY[:, [0]] - b = NUTATION_ABCD_ARRAY[:, [1]] - c = NUTATION_ABCD_ARRAY[:, [2]] - d = NUTATION_ABCD_ARRAY[:, [3]] - arg = np.radians( - NUTATION_YTERM_ARRAY[:, [0]]*np.expand_dims(x0, axis=0) + - NUTATION_YTERM_ARRAY[:, [1]]*np.expand_dims(x1, axis=0) + - NUTATION_YTERM_ARRAY[:, [2]]*np.expand_dims(x2, axis=0) + - NUTATION_YTERM_ARRAY[:, [3]]*np.expand_dims(x3, axis=0) + - NUTATION_YTERM_ARRAY[:, [4]]*np.expand_dims(x4, axis=0) - ) - - delta_psi_sum = ((a + b * julian_ephemeris_century) * np.sin(arg)).sum(axis=0) - delta_eps_sum = ((c + d * julian_ephemeris_century) * np.cos(arg)).sum(axis=0) + + if USE_NUMBA: + delta_psi_sum = 0.0 + delta_eps_sum = 0.0 + for row in range(NUTATION_YTERM_ARRAY.shape[0]): + a = NUTATION_ABCD_ARRAY[row, 0] + b = NUTATION_ABCD_ARRAY[row, 1] + c = NUTATION_ABCD_ARRAY[row, 2] + d = NUTATION_ABCD_ARRAY[row, 3] + arg = np.radians( + NUTATION_YTERM_ARRAY[row, 0]*x0 + + NUTATION_YTERM_ARRAY[row, 1]*x1 + + NUTATION_YTERM_ARRAY[row, 2]*x2 + + NUTATION_YTERM_ARRAY[row, 3]*x3 + + NUTATION_YTERM_ARRAY[row, 4]*x4 + ) + delta_psi_sum += (a + b * julian_ephemeris_century) * np.sin(arg) + delta_eps_sum += (c + d * julian_ephemeris_century) * np.cos(arg) + + else: + a = NUTATION_ABCD_ARRAY[:, [0]] + b = NUTATION_ABCD_ARRAY[:, [1]] + c = NUTATION_ABCD_ARRAY[:, [2]] + d = NUTATION_ABCD_ARRAY[:, [3]] + arg = np.radians( + NUTATION_YTERM_ARRAY[:, [0]]*np.expand_dims(x0, axis=0) + + NUTATION_YTERM_ARRAY[:, [1]]*np.expand_dims(x1, axis=0) + + NUTATION_YTERM_ARRAY[:, [2]]*np.expand_dims(x2, axis=0) + + NUTATION_YTERM_ARRAY[:, [3]]*np.expand_dims(x3, axis=0) + + NUTATION_YTERM_ARRAY[:, [4]]*np.expand_dims(x4, axis=0) + ) + + delta_psi_sum = ((a + b * julian_ephemeris_century) * np.sin(arg)).sum(axis=0) + delta_eps_sum = ((c + d * julian_ephemeris_century) * np.cos(arg)).sum(axis=0) + delta_psi = delta_psi_sum*1.0/36000000 delta_eps = delta_eps_sum*1.0/36000000 # seems like we ought to be able to return a tuple here instead From f79e29d856f20b223219d6bc26de0f48799455ec Mon Sep 17 00:00:00 2001 From: James Fulton Date: Tue, 19 Aug 2025 15:10:09 +0000 Subject: [PATCH 3/3] linting --- pvlib/spa.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/pvlib/spa.py b/pvlib/spa.py index d664ffda7b..f207df9da2 100644 --- a/pvlib/spa.py +++ b/pvlib/spa.py @@ -461,9 +461,12 @@ def sum_mult_cos_add_mult(arr, x): for row in range(arr.shape[0]): s += arr[row, 0] * np.cos(arr[row, 1] + arr[row, 2] * x) else: - s = (arr[:, [0]] * np.cos(arr[:, [1]] + arr[:, [2]] * np.expand_dims(x, axis=0))).sum(axis=0) + s = (arr[:, [0]] * np.cos( + arr[:, [1]] + arr[:, [2]] * np.expand_dims(x, axis=0) + )).sum(axis=0) return s + @jcompile('float64(float64)', nopython=True) def heliocentric_longitude(jme): l0 = sum_mult_cos_add_mult(L0, jme) @@ -562,7 +565,6 @@ def moon_ascending_longitude(julian_ephemeris_century): nopython=True) def longitude_obliquity_nutation(julian_ephemeris_century, x0, x1, x2, x3, x4, out): - if USE_NUMBA: delta_psi_sum = 0.0 delta_eps_sum = 0.0 @@ -594,9 +596,13 @@ def longitude_obliquity_nutation(julian_ephemeris_century, x0, x1, x2, x3, x4, NUTATION_YTERM_ARRAY[:, [4]]*np.expand_dims(x4, axis=0) ) - delta_psi_sum = ((a + b * julian_ephemeris_century) * np.sin(arg)).sum(axis=0) - delta_eps_sum = ((c + d * julian_ephemeris_century) * np.cos(arg)).sum(axis=0) - + delta_psi_sum = ( + (a + b * julian_ephemeris_century) * np.sin(arg) + ).sum(axis=0) + delta_eps_sum = ( + (c + d * julian_ephemeris_century) * np.cos(arg) + ).sum(axis=0) + delta_psi = delta_psi_sum*1.0/36000000 delta_eps = delta_eps_sum*1.0/36000000 # seems like we ought to be able to return a tuple here instead