pvlib 0.12.0__py3-none-any.whl → 0.13.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,401 @@
1
+ import numpy as np
2
+
3
+ from scipy import constants
4
+ from scipy import optimize
5
+
6
+ from pvlib.ivtools.utils import rectify_iv_curve
7
+ from pvlib.ivtools.sde import _fit_sandia_cocontent
8
+
9
+ from pvlib.ivtools.sdm._fit_desoto_pvsyst_sandia import (
10
+ _extract_sdm_params, _initial_iv_params, _update_iv_params
11
+ )
12
+
13
+ CONSTANTS = {'E0': 1000.0, 'T0': 25.0, 'k': constants.k, 'q': constants.e}
14
+
15
+
16
+ def fit_desoto(v_mp, i_mp, v_oc, i_sc, alpha_sc, beta_voc, cells_in_series,
17
+ EgRef=1.121, dEgdT=-0.0002677, temp_ref=25, irrad_ref=1000,
18
+ init_guess={}, root_kwargs={}):
19
+ """
20
+ Calculates the parameters for the De Soto single diode model.
21
+
22
+ This procedure (described in [1]_) fits the De Soto model [2]_ using
23
+ common specifications given by manufacturers in the
24
+ datasheets of PV modules.
25
+
26
+ The solution is found using :py:func:`scipy.optimize.root`,
27
+ with the default solver method 'hybr'.
28
+ No restriction is put on the fit variables, e.g. series
29
+ or shunt resistance could go negative. Nevertheless, if it happens,
30
+ check carefully the inputs and their units. For example, ``alpha_sc`` and
31
+ ``beta_voc`` are often given in %/K in manufacturers datasheets but should
32
+ be given in A/K and V/K here.
33
+
34
+ The parameters returned by this function can be used by
35
+ :py:func:`pvlib.pvsystem.calcparams_desoto` to calculate single diode
36
+ equation parameters at different irradiance and cell temperature.
37
+
38
+ Parameters
39
+ ----------
40
+ v_mp: float
41
+ Module voltage at the maximum-power point at reference conditions. [V]
42
+ i_mp: float
43
+ Module current at the maximum-power point at reference conditions. [A]
44
+ v_oc: float
45
+ Open-circuit voltage at reference conditions. [V]
46
+ i_sc: float
47
+ Short-circuit current at reference conditions. [A]
48
+ alpha_sc: float
49
+ The short-circuit current (``i_sc``) temperature coefficient of the
50
+ module. [A/K]
51
+ beta_voc: float
52
+ The open-circuit voltage (``v_oc``) temperature coefficient of the
53
+ module. [V/K]
54
+ cells_in_series: integer
55
+ Number of cell in the module.
56
+ EgRef: float, default 1.121 eV - value for silicon
57
+ Energy of bandgap of semi-conductor used. [eV]
58
+ dEgdT: float, default -0.0002677 - value for silicon
59
+ Variation of bandgap according to temperature. [1/K]
60
+ temp_ref: float, default 25
61
+ Reference temperature condition. [C]
62
+ irrad_ref: float, default 1000
63
+ Reference irradiance condition. [Wm⁻²]
64
+ init_guess: dict, optional
65
+ Initial values for optimization. Keys can be `'Rsh_0'`, `'a_0'`,
66
+ `'IL_0'`, `'Io_0'`, `'Rs_0'`.
67
+ root_kwargs : dictionary, optional
68
+ Dictionary of arguments to pass onto scipy.optimize.root()
69
+
70
+ Returns
71
+ -------
72
+ dict with the following elements:
73
+ I_L_ref: float
74
+ Light-generated current at reference conditions. [A]
75
+ I_o_ref: float
76
+ Diode saturation current at reference conditions. [A]
77
+ R_s: float
78
+ Series resistance. [ohm]
79
+ R_sh_ref: float
80
+ Shunt resistance at reference conditions. [ohm].
81
+ a_ref: float
82
+ Modified ideality factor at reference conditions.
83
+ The product of the usual diode ideality factor (n, unitless),
84
+ number of cells in series (Ns), and cell thermal voltage at
85
+ specified effective irradiance and cell temperature.
86
+ alpha_sc: float
87
+ The short-circuit current (i_sc) temperature coefficient of the
88
+ module. [A/K]
89
+ EgRef: float
90
+ Energy of bandgap of semi-conductor used. [eV]
91
+ dEgdT: float
92
+ Variation of bandgap according to temperature. [1/K]
93
+ irrad_ref: float
94
+ Reference irradiance condition. [Wm⁻²]
95
+ temp_ref: float
96
+ Reference temperature condition. [C]
97
+
98
+ scipy.optimize.OptimizeResult
99
+ Optimization result of scipy.optimize.root().
100
+ See scipy.optimize.OptimizeResult for more details.
101
+
102
+ References
103
+ ----------
104
+ .. [1] J. A Duffie, W. A Beckman, "Solar Engineering of Thermal Processes",
105
+ 4th ed., Wiley, 2013. :doi:`10.1002/9781118671603`
106
+ .. [2] W. De Soto et al., "Improvement and validation of a model for
107
+ photovoltaic array performance", Solar Energy, vol 80, pp. 78-88,
108
+ 2006. :doi:`10.1016/j.solener.2005.06.010`
109
+
110
+ """
111
+
112
+ # Constants
113
+ k = constants.value('Boltzmann constant in eV/K') # in eV/K
114
+ Tref = temp_ref + 273.15 # [K]
115
+
116
+ # initial guesses of variables for computing convergence:
117
+ # Default values are taken from [1], p753
118
+ init_guess_keys = ['IL_0', 'Io_0', 'Rs_0', 'Rsh_0', 'a_0'] # order matters
119
+ init = {key: None for key in init_guess_keys}
120
+ init['IL_0'] = i_sc
121
+ init['a_0'] = 1.5*k*Tref*cells_in_series
122
+ init['Io_0'] = i_sc * np.exp(-v_oc/init['a_0'])
123
+ init['Rs_0'] = (init['a_0']*np.log1p((init['IL_0'] - i_mp)/init['Io_0'])
124
+ - v_mp) / i_mp
125
+ init['Rsh_0'] = 100.0
126
+ # overwrite if optional init_guess is provided
127
+ for key in init_guess:
128
+ if key in init_guess_keys:
129
+ init[key] = init_guess[key]
130
+ else:
131
+ raise ValueError(f"'{key}' is not a valid name;"
132
+ f" allowed values are {init_guess_keys}")
133
+ # params_i : initial values vector
134
+ params_i = np.array([init[k] for k in init_guess_keys])
135
+
136
+ # specs of module
137
+ specs = (i_sc, v_oc, i_mp, v_mp, beta_voc, alpha_sc, EgRef, dEgdT,
138
+ Tref, k)
139
+
140
+ # computing with system of equations described in [1]
141
+ optimize_result = optimize.root(_system_of_equations_desoto, x0=params_i,
142
+ args=(specs,), **root_kwargs)
143
+
144
+ if optimize_result.success:
145
+ sdm_params = optimize_result.x
146
+ else:
147
+ raise RuntimeError(
148
+ 'Parameter estimation failed:\n' + optimize_result.message)
149
+
150
+ # results
151
+ return ({'I_L_ref': sdm_params[0],
152
+ 'I_o_ref': sdm_params[1],
153
+ 'R_s': sdm_params[2],
154
+ 'R_sh_ref': sdm_params[3],
155
+ 'a_ref': sdm_params[4],
156
+ 'alpha_sc': alpha_sc,
157
+ 'EgRef': EgRef,
158
+ 'dEgdT': dEgdT,
159
+ 'irrad_ref': irrad_ref,
160
+ 'temp_ref': temp_ref},
161
+ optimize_result)
162
+
163
+
164
+ def _system_of_equations_desoto(params, specs):
165
+ """Evaluates the systems of equations used to solve for the single
166
+ diode equation parameters. Function designed to be used by
167
+ scipy.optimize.root in fit_desoto.
168
+
169
+ Parameters
170
+ ----------
171
+ params: ndarray
172
+ Array with parameters of the De Soto single diode model. Must be
173
+ given in the following order: IL, Io, a, Rs, Rsh
174
+ specs: tuple
175
+ Specifications of pv module given by manufacturer. Must be given
176
+ in the following order: Isc, Voc, Imp, Vmp, beta_oc, alpha_sc
177
+
178
+ Returns
179
+ -------
180
+ value of the system of equations to solve with scipy.optimize.root().
181
+ """
182
+
183
+ # six input known variables
184
+ Isc, Voc, Imp, Vmp, beta_oc, alpha_sc, EgRef, dEgdT, Tref, k = specs
185
+
186
+ # five parameters vector to find
187
+ IL, Io, Rs, Rsh, a = params
188
+
189
+ # five equation vector
190
+ y = [0, 0, 0, 0, 0]
191
+
192
+ # 1st equation - short-circuit - eq(3) in [1]
193
+ y[0] = Isc - IL + Io * np.expm1(Isc * Rs / a) + Isc * Rs / Rsh
194
+
195
+ # 2nd equation - open-circuit Tref - eq(4) in [1]
196
+ y[1] = -IL + Io * np.expm1(Voc / a) + Voc / Rsh
197
+
198
+ # 3rd equation - Imp & Vmp - eq(5) in [1]
199
+ y[2] = Imp - IL + Io * np.expm1((Vmp + Imp * Rs) / a) \
200
+ + (Vmp + Imp * Rs) / Rsh
201
+
202
+ # 4th equation - Pmp derivated=0 - eq23.2.6 in [2]
203
+ # caution: eq(6) in [1] has a sign error
204
+ y[3] = Imp \
205
+ - Vmp * ((Io / a) * np.exp((Vmp + Imp * Rs) / a) + 1.0 / Rsh) \
206
+ / (1.0 + (Io * Rs / a) * np.exp((Vmp + Imp * Rs) / a) + Rs / Rsh)
207
+
208
+ # 5th equation - open-circuit T2 - eq (4) at temperature T2 in [1]
209
+ T2 = Tref + 2
210
+ Voc2 = (T2 - Tref) * beta_oc + Voc # eq (7) in [1]
211
+ a2 = a * T2 / Tref # eq (8) in [1]
212
+ IL2 = IL + alpha_sc * (T2 - Tref) # eq (11) in [1]
213
+ Eg2 = EgRef * (1 + dEgdT * (T2 - Tref)) # eq (10) in [1]
214
+ Io2 = Io * (T2 / Tref)**3 * np.exp(1 / k * (EgRef/Tref - Eg2/T2)) # eq (9)
215
+ y[4] = -IL2 + Io2 * np.expm1(Voc2 / a2) + Voc2 / Rsh # eq (4) at T2
216
+
217
+ return y
218
+
219
+
220
+ def fit_desoto_sandia(ivcurves, specs, const=None, maxiter=5, eps1=1.e-3):
221
+ """
222
+ Estimate parameters for the De Soto module performance model.
223
+
224
+ Parameters
225
+ ----------
226
+ ivcurves : dict
227
+ i : array
228
+ One array element for each IV curve. The jth element is itself an
229
+ array of current for jth IV curve (same length as v[j]) [A]
230
+ v : array
231
+ One array element for each IV curve. The jth element is itself an
232
+ array of voltage for jth IV curve (same length as i[j]) [V]
233
+ ee : array
234
+ effective irradiance for each IV curve, i.e., POA broadband
235
+ irradiance adjusted by solar spectrum modifier [W / m^2]
236
+ tc : array
237
+ cell temperature for each IV curve [C]
238
+ i_sc : array
239
+ short circuit current for each IV curve [A]
240
+ v_oc : array
241
+ open circuit voltage for each IV curve [V]
242
+ i_mp : array
243
+ current at max power point for each IV curve [A]
244
+ v_mp : array
245
+ voltage at max power point for each IV curve [V]
246
+
247
+ specs : dict
248
+ cells_in_series : int
249
+ number of cells in series
250
+ alpha_sc : float
251
+ temperature coefficient of Isc [A/C]
252
+ beta_voc : float
253
+ temperature coefficient of Voc [V/C]
254
+
255
+ const : dict
256
+ E0 : float
257
+ effective irradiance at STC, default 1000 [W/m^2]
258
+ T0 : float
259
+ cell temperature at STC, default 25 [C]
260
+ k : float
261
+ Boltzmann's constant [J/K]
262
+ q : float
263
+ elementary charge [Coulomb]
264
+
265
+ maxiter : int, default 5
266
+ input that sets the maximum number of iterations for the parameter
267
+ updating part of the algorithm.
268
+
269
+ eps1: float, default 1e-3
270
+ Tolerance for the IV curve fitting. The parameter updating stops when
271
+ absolute values of the percent change in mean, max and standard
272
+ deviation of Imp, Vmp and Pmp between iterations are all less than
273
+ eps1, or when the number of iterations exceeds maxiter.
274
+
275
+ Returns
276
+ -------
277
+ dict
278
+ I_L_ref : float
279
+ Light current at STC [A]
280
+ I_o_ref : float
281
+ Dark current at STC [A]
282
+ EgRef : float
283
+ Effective band gap at STC [eV]
284
+ R_s : float
285
+ Series resistance at STC [ohm]
286
+ R_sh_ref : float
287
+ Shunt resistance at STC [ohm]
288
+ cells_in_series : int
289
+ Number of cells in series
290
+ iph : array
291
+ Light current for each IV curve [A]
292
+ io : array
293
+ Dark current for each IV curve [A]
294
+ rs : array
295
+ Series resistance for each IV curve [ohm]
296
+ rsh : array
297
+ Shunt resistance for each IV curve [ohm]
298
+ a_ref : float
299
+ The product of the usual diode ideality factor (n, unitless),
300
+ number of cells in series (Ns), and cell thermal voltage at
301
+ reference conditions, in units of V.
302
+ dEgdT : float
303
+ The temperature dependence of the energy bandgap (Eg) at reference
304
+ conditions [1/K].
305
+ u : array
306
+ Boolean for each IV curve indicating that the parameter values
307
+ are deemed reasonable by the private function ``_filter_params``
308
+
309
+ Notes
310
+ -----
311
+ The De Soto module performance model is described in [1]_. The fitting
312
+ method is documented in [2]_, [3]_. Ported from PVLib Matlab [4]_.
313
+
314
+ References
315
+ ----------
316
+ .. [1] W. De Soto et al., "Improvement and validation of a model for
317
+ photovoltaic array performance", Solar Energy, vol 80, pp. 78-88,
318
+ 2006. :doi:`10.1016/j.solener.2005.06.010`
319
+ .. [2] C. Hansen, Parameter Estimation for Single Diode Models of
320
+ Photovoltaic Modules, Sandia National Laboratories Report SAND2015-2065.
321
+ :doi:`10.2172/1177157`
322
+ .. [3] C. Hansen, Estimation of Parameters for Single Diode Models using
323
+ Measured IV Curves, Proc. of the 39th IEEE PVSC, June 2013.
324
+ :doi:`10.1109/PVSC.2013.6744135`
325
+ .. [4] PVLib MATLAB https://github.com/sandialabs/MATLAB_PV_LIB
326
+ """
327
+
328
+ if const is None:
329
+ const = CONSTANTS
330
+
331
+ ee = ivcurves['ee']
332
+ tc = ivcurves['tc']
333
+ tck = tc + 273.15
334
+ isc = ivcurves['i_sc']
335
+ voc = ivcurves['v_oc']
336
+ imp = ivcurves['i_mp']
337
+ vmp = ivcurves['v_mp']
338
+
339
+ # Cell Thermal Voltage
340
+ vth = const['k'] / const['q'] * tck
341
+
342
+ n = len(voc)
343
+
344
+ # Initial estimate of Rsh used to obtain the diode factor gamma0 and diode
345
+ # temperature coefficient mu_gamma. Rsh is estimated using the co-content
346
+ # integral method.
347
+
348
+ rsh = np.ones(n)
349
+ for j in range(n):
350
+ voltage, current = rectify_iv_curve(ivcurves['v'][j], ivcurves['i'][j])
351
+ # initial estimate of Rsh, from integral over voltage regression
352
+ # [5] Step 3a; [6] Step 3a
353
+ _, _, _, rsh[j], _ = _fit_sandia_cocontent(
354
+ voltage, current, vth[j] * specs['cells_in_series'])
355
+
356
+ n0 = _fit_desoto_sandia_diode(ee, voc, vth, tc, specs, const)
357
+
358
+ bad_n = np.isnan(n0) or not np.isreal(n0)
359
+
360
+ if bad_n:
361
+ raise RuntimeError(
362
+ "Failed to estimate the diode (ideality) factor parameter;"
363
+ " aborting parameter estimation.")
364
+
365
+ nnsvth = n0 * specs['cells_in_series'] * vth
366
+
367
+ # For each IV curve, sequentially determine initial values for Io, Rs,
368
+ # and Iph [5] Step 3a; [6] Step 3
369
+ iph, io, rs, u = _initial_iv_params(ivcurves, ee, voc, isc, rsh,
370
+ nnsvth)
371
+
372
+ # Update values for each IV curve to converge at vmp, imp, voc and isc
373
+ iph, io, rs, rsh, u = _update_iv_params(voc, isc, vmp, imp, ee,
374
+ iph, io, rs, rsh, nnsvth, u,
375
+ maxiter, eps1)
376
+
377
+ # get single diode models from converged values for each IV curve
378
+ desoto = _extract_sdm_params(ee, tc, iph, io, rs, rsh, n0, u,
379
+ specs, const, model='desoto')
380
+ # Add parameters estimated in this function
381
+ desoto['a_ref'] = n0 * specs['cells_in_series'] * const['k'] / \
382
+ const['q'] * (const['T0'] + 273.15)
383
+ desoto['cells_in_series'] = specs['cells_in_series']
384
+
385
+ return desoto
386
+
387
+
388
+ def _fit_desoto_sandia_diode(ee, voc, vth, tc, specs, const):
389
+ # estimates the diode factor for the De Soto model.
390
+ # Helper function for fit_desoto_sandia
391
+ try:
392
+ import statsmodels.api as sm
393
+ except ImportError:
394
+ raise ImportError(
395
+ 'Parameter extraction using Sandia method requires statsmodels')
396
+
397
+ x = specs['cells_in_series'] * vth * np.log(ee / const['E0'])
398
+ y = voc - specs['beta_voc'] * (tc - const['T0'])
399
+ new_x = sm.add_constant(x)
400
+ res = sm.RLM(y, new_x).fit()
401
+ return np.array(res.params)[1]