-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add Batzelis 2017 simple nonlinear PV model #2563
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
Changes from all commits
d2d4d91
c674f1b
d8988c6
e24e62f
994a853
6f94408
1e61d09
7d431ab
839d0b5
0fde334
55cb1eb
e641956
e7ec33c
8becc1a
006ebb0
4d726b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |
| """ | ||
|
|
||
| import numpy as np | ||
| import pandas as pd | ||
| from pvlib.tools import _golden_sect_DataFrame | ||
|
|
||
| from scipy.optimize import brentq, newton | ||
|
|
@@ -949,3 +950,85 @@ def _pwr_optfcn(df, loc): | |
| df['resistance_shunt'], df['nNsVth']) | ||
|
|
||
| return current * df[loc] | ||
|
|
||
|
|
||
| def batzelis(photocurrent, saturation_current, resistance_series, | ||
| resistance_shunt, nNsVth): | ||
|
Comment on lines
+955
to
+956
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kandersolar Was adding this SDE solver to the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we discussed it. I'm not in favor of adding it as a |
||
| """ | ||
| Estimate maximum power, open-circuit, and short-circuit points from | ||
| single-diode equation parameters using Batzelis's method. | ||
|
|
||
| This method is described in Section II.B of [1]_. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| photocurrent : numeric | ||
| Light-generated current. [A] | ||
| saturation_current : numeric | ||
| Diode saturation current. [A] | ||
| resistance_series : numeric | ||
| Series resistance. [Ohm] | ||
| resistance_shunt : numeric | ||
| Shunt resistance. [Ohm] | ||
| nNsVth : numeric | ||
| The product of the usual diode ideality factor (n, unitless), | ||
| number of cells in series (Ns), and cell thermal voltage at | ||
| specified effective irradiance and cell temperature. [V] | ||
|
|
||
| Returns | ||
| ------- | ||
| dict | ||
| The returned dict-like object contains the keys/columns: | ||
|
|
||
| * ``p_mp`` - power at maximum power point. [W] | ||
| * ``i_mp`` - current at maximum power point. [A] | ||
| * ``v_mp`` - voltage at maximum power point. [V] | ||
| * ``i_sc`` - short circuit current. [A] | ||
| * ``v_oc`` - open circuit voltage. [V] | ||
|
|
||
| References | ||
| ---------- | ||
| .. [1] E. I. Batzelis, "Simple PV Performance Equations Theoretically Well | ||
| Founded on the Single-Diode Model," Journal of Photovoltaics vol. 7, | ||
| no. 5, pp. 1400-1409, Sep 2017, :doi:`10.1109/JPHOTOV.2017.2711431` | ||
| """ | ||
| # convenience variables | ||
| Iph = photocurrent | ||
| Is = saturation_current | ||
| Rsh = resistance_shunt | ||
| Rs = resistance_series | ||
| a = nNsVth | ||
|
|
||
| # Eqs 3-4 | ||
| isc = Iph / (Rs / Rsh + 1) # manipulated to handle Rsh=np.inf correctly | ||
| with np.errstate(divide='ignore'): # zero Iph | ||
| voc = a * np.log(Iph / Is) | ||
|
|
||
| # Eqs 5-8 | ||
| w = np.real(lambertw(np.e * Iph / Is)) | ||
| # vmp = (1 + Rs/Rsh) * a * (w - 1) - Rs * Iph * (1 - 1/w) # not needed | ||
| with np.errstate(divide='ignore', invalid='ignore'): # zero Iph -> zero w | ||
| imp = Iph * (1 - 1/w) - a * (w - 1) / Rsh | ||
kandersolar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| vmp = a * (w - 1) - Rs * imp | ||
|
|
||
| vmp = np.where(Iph > 0, vmp, 0) | ||
| voc = np.where(Iph > 0, voc, 0) | ||
| imp = np.where(Iph > 0, imp, 0) | ||
| isc = np.where(Iph > 0, isc, 0) | ||
|
|
||
| out = { | ||
| 'p_mp': imp * vmp, | ||
| 'i_mp': imp, | ||
| 'v_mp': vmp, | ||
| 'i_sc': isc, | ||
| 'v_oc': voc, | ||
| } | ||
|
|
||
| # if pandas in, ensure pandas out | ||
| pandas_inputs = [ | ||
| x for x in [Iph, Is, Rsh, Rs, a] if isinstance(x, pd.Series)] | ||
| if pandas_inputs: | ||
| out = pd.DataFrame(out, index=pandas_inputs[0].index) | ||
|
|
||
| return out | ||
Uh oh!
There was an error while loading. Please reload this page.