Skip to content

Commit 627ff3b

Browse files
authored
Merge branch 'pvlib:main' into main
2 parents 0e60277 + 26de2f0 commit 627ff3b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1423
-889
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pvlib/spa_c_files/spa_tester.c
4040

4141
# generated documentation
4242
docs/sphinx/source/reference/generated
43+
docs/sphinx/source/reference/*/generated
4344
docs/sphinx/source/savefig
4445
docs/sphinx/source/gallery
4546

benchmarks/asv.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
"build": "",
118118
"numpy": "1.16.0",
119119
"pandas": "0.25.0",
120-
"scipy": "1.2.0",
120+
"scipy": "1.4.0",
121121
// Note: these don't have a minimum in setup.py
122122
"h5py": "2.10.0",
123123
"ephem": "3.7.6.0",

ci/requirements-py3.10.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ dependencies:
2323
- python=3.10
2424
- pytz
2525
- requests
26-
- scipy >= 1.2.0
26+
- scipy >= 1.4.0
2727
- shapely # pvfactors dependency
2828
# - siphon # conda-forge
2929
- statsmodels

ci/requirements-py3.7-min.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ dependencies:
1717
- h5py==3.1.0
1818
- numpy==1.16.0
1919
- pandas==0.25.0
20-
- scipy==1.2.0
20+
- scipy==1.4.0
2121
- pytest-rerunfailures # conda version is >3.6
2222
- pytest-remotedata # conda package is 0.3.0, needs > 0.3.1
2323
- requests-mock

ci/requirements-py3.7.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ dependencies:
2323
- python=3.7
2424
- pytz
2525
- requests
26-
- scipy >= 1.2.0
26+
- scipy >= 1.4.0
2727
- shapely # pvfactors dependency
2828
- siphon # conda-forge
2929
- statsmodels

ci/requirements-py3.8.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ dependencies:
2323
- python=3.8
2424
- pytz
2525
- requests
26-
- scipy >= 1.2.0
26+
- scipy >= 1.4.0
2727
- shapely # pvfactors dependency
2828
- siphon # conda-forge
2929
- statsmodels

ci/requirements-py3.9.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ dependencies:
2323
- python=3.9
2424
- pytz
2525
- requests
26-
- scipy >= 1.2.0
26+
- scipy >= 1.4.0
2727
- shapely # pvfactors dependency
2828
# - siphon # conda-forge
2929
- statsmodels

docs/examples/adr-pvarray/README.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ADR Model for PV Module Efficiency
2+
----------------------------------
3+
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
"""
2+
Obtaining ADR model parameters from IEC 61853 matrix measurements
3+
=================================================================
4+
5+
There's a fitting function provided in pvlib to do exactly that.
6+
7+
Since PV module efficiency varies with irradiance and temperature
8+
what better way to train a model than using efficiency measurement
9+
over a broad range of temperature and irradiance levels?
10+
The standard IEC 61853-1 defines a standard matrix of conditions
11+
for such measurements and this example shows how the ADR model
12+
parameters can be determined with just a few lines of code using
13+
functions in pvlib-python.
14+
15+
Author: Anton Driesse
16+
"""
17+
18+
from io import StringIO
19+
import pandas as pd
20+
import matplotlib.pyplot as plt
21+
22+
from pvlib.pvarray import pvefficiency_adr, fit_pvefficiency_adr
23+
24+
# %% The text on this line is not displayed
25+
#
26+
# Here are some matrix measurements:
27+
#
28+
29+
iec61853data = '''
30+
irradiance temperature p_mp
31+
0 100 15.0 30.159
32+
1 200 15.0 63.057
33+
2 400 15.0 129.849
34+
3 600 15.0 197.744
35+
4 800 15.0 264.825
36+
5 1000 15.0 330.862
37+
6 100 25.0 29.250
38+
7 200 25.0 61.137
39+
8 400 25.0 126.445
40+
9 600 25.0 192.278
41+
10 800 25.0 257.561
42+
11 1000 25.0 322.305
43+
12 1100 25.0 354.174
44+
15 400 50.0 117.062
45+
16 600 50.0 177.959
46+
17 800 50.0 238.626
47+
18 1000 50.0 298.954
48+
19 1100 50.0 328.413
49+
23 600 75.0 162.966
50+
24 800 75.0 218.585
51+
25 1000 75.0 273.651
52+
26 1100 75.0 301.013
53+
'''
54+
df = pd.read_csv(StringIO(iec61853data), delim_whitespace=True)
55+
56+
# %%
57+
#
58+
# Now calculate the normalized or relative efficiency values
59+
# and use the fitting function to determine the parameters.
60+
# The parameters (shown below) can now be used to
61+
# simulate the module operating in a PV system.
62+
#
63+
64+
P_REF = 322.305 # (W) STC value from the table above
65+
G_REF = 1000. # (W/m2)
66+
67+
df['eta_rel'] = (df['p_mp'] / P_REF) / (df['irradiance'] / G_REF)
68+
69+
adr_params = fit_pvefficiency_adr(df['irradiance'], df['temperature'],
70+
df['eta_rel'])
71+
72+
for k, v in adr_params.items():
73+
print('%-5s = %8.5f' % (k, v))
74+
75+
# %%
76+
#
77+
# Compare the model output to the original measurements.
78+
# The chart below shows minor differences but due to their random nature
79+
# they are most likely evidence of the limitations of measurement accuracy.
80+
#
81+
82+
eta_rel_adr = pvefficiency_adr(df['irradiance'],
83+
df['temperature'], **adr_params)
84+
85+
plt.figure()
86+
plt.plot(df['irradiance'], df['eta_rel'], 'oc', ms=8)
87+
plt.plot(df['irradiance'], eta_rel_adr, '.k')
88+
plt.legend(['Lab measurements', 'ADR model fit'], loc='lower right')
89+
plt.xlabel('Irradiance [W/m²]')
90+
plt.ylabel('Relative efficiency [-]')
91+
plt.grid(alpha=0.5)
92+
plt.xlim(0, 1200)
93+
plt.ylim(0.7, 1.1)
94+
plt.show()
95+
96+
# %%
97+
#
98+
# References
99+
# ----------
100+
# .. [1] A. Driesse and J. S. Stein, "From IEC 61853 power measurements
101+
# to PV system simulations", Sandia Report No. SAND2020-3877, 2020.
102+
# :doi:`10.2172/1615179`
103+
#
104+
# .. [2] A. Driesse, M. Theristis and J. S. Stein, "A New Photovoltaic Module
105+
# Efficiency Model for Energy Prediction and Rating," in IEEE Journal
106+
# of Photovoltaics, vol. 11, no. 2, pp. 527-534, March 2021.
107+
# :doi:`10.1109/JPHOTOV.2020.3045677`
108+
#
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
"""
2+
Fast simulation using the ADR efficiency model starting from PVsyst parameters
3+
==============================================================================
4+
5+
Would you like to increase simulation speed by a factor of 4000+?
6+
7+
Simulation using single-diode models can be slow because the maximum
8+
power point is usually found by an iterative search.
9+
In this example we use the PVsyst single diode model to generate
10+
a matrix of efficiency values, then determine the ADR model
11+
parameters to approximate the behavior of the PVsyst model.
12+
This way both PVsyst and ADR models can simulate the same PV module type.
13+
14+
To compare simulation speed, we run them using ``timeit``.
15+
16+
Author: Anton Driesse
17+
"""
18+
19+
import numpy as np
20+
import matplotlib.pyplot as plt
21+
22+
from pvlib.pvsystem import calcparams_pvsyst, max_power_point
23+
from pvlib.pvarray import fit_pvefficiency_adr, pvefficiency_adr
24+
25+
from timeit import timeit
26+
27+
# %% The text on this line is not displayed
28+
#
29+
# Generate a matrix of power values
30+
#
31+
32+
pvsyst_params = {'alpha_sc': 0.0015,
33+
'gamma_ref': 1.20585,
34+
'mu_gamma': -9.41066e-05,
35+
'I_L_ref': 5.9301,
36+
'I_o_ref': 2.9691e-10,
37+
'R_sh_ref': 1144,
38+
'R_sh_0': 3850,
39+
'R_s': 0.6,
40+
'cells_in_series': 96,
41+
'R_sh_exp': 5.5,
42+
'EgRef': 1.12,
43+
}
44+
45+
G_REF = 1000
46+
T_REF = 25
47+
48+
params_stc = calcparams_pvsyst(G_REF, T_REF, **pvsyst_params)
49+
mpp_stc = max_power_point(*params_stc)
50+
51+
P_REF = mpp_stc['p_mp']
52+
53+
g, t = np.meshgrid(np.linspace(100, 1100, 11),
54+
np.linspace(0, 75, 4))
55+
56+
adjusted_params = calcparams_pvsyst(g, t, **pvsyst_params)
57+
mpp = max_power_point(*adjusted_params)
58+
p_mp = mpp['p_mp']
59+
60+
print('irradiance')
61+
print(g[:1].round(0))
62+
63+
print('maximum power')
64+
print(p_mp.round(1))
65+
66+
# %%
67+
#
68+
# Convert power matrix to efficiency and fit the ADR model to all the points
69+
#
70+
71+
eta_rel_pvs = (p_mp / P_REF) / (g / G_REF)
72+
73+
adr_params = fit_pvefficiency_adr(g, t, eta_rel_pvs, dict_output=True)
74+
75+
for k, v in adr_params.items():
76+
print('%-5s = %8.5f' % (k, v))
77+
78+
# %%
79+
#
80+
# Compare the ADR model output to the PVsyst model output
81+
#
82+
83+
eta_rel_adr = pvefficiency_adr(g, t, **adr_params)
84+
mbe = np.mean(eta_rel_adr - eta_rel_pvs)
85+
rmse = np.sqrt(np.mean(np.square(eta_rel_adr - eta_rel_pvs)))
86+
87+
plt.figure()
88+
plt.plot(g.flat, eta_rel_pvs.flat, 'oc', ms=8)
89+
plt.plot(g.flat, eta_rel_adr.flat, '.k')
90+
plt.grid(alpha=0.5)
91+
plt.xlim(0, 1200)
92+
plt.ylim(0.7, 1.1)
93+
94+
plt.xlabel('Irradiance [W/m²]')
95+
plt.ylabel('Relative efficiency [-]')
96+
plt.legend(['PVsyst model output', 'ADR model fit'], loc='lower right')
97+
plt.title('Differences: mean %.5f, RMS %.5f' % (mbe, rmse))
98+
plt.show()
99+
100+
# %%
101+
#
102+
# Generate some random irradiance and temperature data
103+
#
104+
105+
g = np.random.uniform(0, 1200, 8760)
106+
t = np.random.uniform(20, 80, 8760)
107+
108+
109+
def run_adr():
110+
eta_rel = pvefficiency_adr(g, t, **adr_params)
111+
p_adr = P_REF * eta_rel * (g / G_REF)
112+
return p_adr
113+
114+
115+
def run_pvsyst():
116+
adjusted_params = calcparams_pvsyst(g, t, **pvsyst_params)
117+
mpp = max_power_point(*adjusted_params)
118+
p_pvs = mpp['p_mp']
119+
return p_pvs
120+
121+
122+
elapsed_adr = timeit('run_adr()', number=1, globals=globals())
123+
elapsed_pvs = timeit('run_pvsyst()', number=1, globals=globals())
124+
125+
print('Elapsed time for the PVsyst model: %9.6f s' % elapsed_pvs)
126+
print('Elapsed time for the ADR model: %9.6f s' % elapsed_adr)
127+
print('ADR acceleration ratio: %9.0f x' % (elapsed_pvs/elapsed_adr))
128+
129+
# %%
130+
#
131+
# That's fast, but is it accurate?
132+
# Run them again to compare the simulated power values
133+
#
134+
135+
p_pvs = run_pvsyst()
136+
p_adr = run_adr()
137+
138+
mbe = np.mean(p_adr - p_pvs)
139+
rmse = np.sqrt(np.mean(np.square(p_adr - p_pvs)))
140+
141+
# sphinx_gallery_thumbnail_number = 2
142+
plt.figure()
143+
pc = plt.scatter(p_pvs, p_adr-p_pvs, c=t, cmap='jet')
144+
plt.colorbar()
145+
pc.set_alpha(0.25)
146+
plt.ylim(-1.4, 1.4)
147+
plt.grid(alpha=0.5)
148+
149+
plt.xlabel('Power calculated using the PVsyst model [W]')
150+
plt.ylabel('ADR model power - PVsyst model power [W]')
151+
plt.title('Differences: mean %.2f W, RMS %.2f W' % (mbe, rmse))
152+
plt.show()
153+
154+
# %%
155+
#
156+
# There are some small systematic differences between the original
157+
# PVsyst model output and the ADR fit. But these differences are
158+
# much smaller than the typical uncertainty in measured output
159+
# of modules of this type. The PVsyst model and the parameters
160+
# we started with are of course also only approximations of the
161+
# true module behavior.
162+
#
163+
164+
# %%
165+
#
166+
# References
167+
# ----------
168+
# .. [1] A. Driesse and J. S. Stein, "From IEC 61853 power measurements
169+
# to PV system simulations", Sandia Report No. SAND2020-3877, 2020.
170+
# :doi:`10.2172/1615179`
171+
#
172+
# .. [2] A. Driesse, M. Theristis and J. S. Stein, "A New Photovoltaic Module
173+
# Efficiency Model for Energy Prediction and Rating," in IEEE Journal
174+
# of Photovoltaics, vol. 11, no. 2, pp. 527-534, March 2021.
175+
# :doi:`10.1109/JPHOTOV.2020.3045677`
176+
#

0 commit comments

Comments
 (0)