Skip to content

Commit d6baf97

Browse files
agodbehereAndrew Godbehere
and
Andrew Godbehere
authored
Implemented closed-form solution in detect_clearsky (#2217)
* Implements closed-form solution for optimization problem in clearsky. Updates test. * Revert "Implements closed-form solution for optimization problem in clearsky. Updates test." This reverts commit 94259c5. * Reintroduced changes without re-sorting the imports * pep8 formatting adjustments * Update whatsnew as per comments --------- Co-authored-by: Andrew Godbehere <[email protected]>
1 parent 5d23f14 commit d6baf97

File tree

3 files changed

+19
-24
lines changed

3 files changed

+19
-24
lines changed

docs/sphinx/source/whatsnew/v0.11.1.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ Enhancements
3030
* Added function for calculating wind speed at different heights,
3131
:py:func:`pvlib.atmosphere.windspeed_powerlaw`.
3232
(:issue:`2118`, :pull:`2124`)
33+
* Implemented closed-form solution for alpha in :py:func:`pvlib.clearsky.detect_clearsky`,
34+
obviating the call to scipy.optimize that was prone to runtime errors and minimizing
35+
computation. (:issue:`2171`, :issue:`2216`, :pull:`2217`).
36+
3337

3438
Bug fixes
3539
~~~~~~~~~
@@ -74,3 +78,4 @@ Contributors
7478
* Marcos R. Escudero (:ghuser:`marc-resc`)
7579
* Bernat Nicolau (:ghuser:`BernatNicolau`)
7680
* Eduardo Sarquis (:ghuser:`EduardoSarquis`)
81+
* Andrew B Godbehere (:ghuser:`agodbehere`)

pvlib/clearsky.py

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
import numpy as np
1111
import pandas as pd
12-
from scipy.optimize import minimize_scalar
1312
from scipy.linalg import hankel
1413
import h5py
1514

@@ -874,25 +873,11 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
874873
clear_meas = meas[clear_samples]
875874
clear_clear = clear[clear_samples]
876875

877-
def rmse(alpha):
878-
return np.sqrt(np.mean((clear_meas - alpha*clear_clear)**2))
879-
880-
optimize_result = minimize_scalar(rmse)
881-
if not optimize_result.success:
882-
try:
883-
message = "Optimizer exited unsuccessfully: " \
884-
+ optimize_result.message
885-
except AttributeError:
886-
message = "Optimizer exited unsuccessfully: \
887-
No message explaining the failure was returned. \
888-
If you would like to see this message, please \
889-
update your scipy version (try version 1.8.0 \
890-
or beyond)."
891-
raise RuntimeError(message)
892-
893-
else:
894-
alpha = optimize_result.x
895-
876+
# Compute arg min of MSE between model and observations
877+
C = (clear_clear**2).sum()
878+
if not (pd.isna(C) or C == 0): # safety check
879+
# only update alpha if C is strictly positive
880+
alpha = (clear_meas * clear_clear).sum() / C
896881
if round(alpha*10000) == round(previous_alpha*10000):
897882
break
898883
else:

pvlib/tests/test_clearsky.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -675,13 +675,18 @@ def test_detect_clearsky_missing_index(detect_clearsky_data):
675675
def test_detect_clearsky_not_enough_data(detect_clearsky_data):
676676
expected, cs = detect_clearsky_data
677677
with pytest.raises(ValueError, match='have at least'):
678-
clearsky.detect_clearsky(expected['GHI'], cs['ghi'], window_length=60)
678+
clearsky.detect_clearsky(expected['GHI'], cs['ghi'], window_length=60)
679679

680680

681-
def test_detect_clearsky_optimizer_failed(detect_clearsky_data):
681+
@pytest.mark.parametrize("window_length", [5, 10, 15, 20, 25])
682+
def test_detect_clearsky_optimizer_not_failed(
683+
detect_clearsky_data, window_length
684+
):
682685
expected, cs = detect_clearsky_data
683-
with pytest.raises(RuntimeError, match='Optimizer exited unsuccessfully'):
684-
clearsky.detect_clearsky(expected['GHI'], cs['ghi'], window_length=15)
686+
clear_samples = clearsky.detect_clearsky(
687+
expected["GHI"], cs["ghi"], window_length=window_length
688+
)
689+
assert isinstance(clear_samples, pd.Series)
685690

686691

687692
@pytest.fixture

0 commit comments

Comments
 (0)