-
Notifications
You must be signed in to change notification settings - Fork 1.1k
ENH: implementing pvsyst recombination loss current for CdTe and a:Si #504
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 9 commits
4b0df1b
2bd8b13
1650bc6
9d96585
f5d6dda
a62759e
bfa9c5f
79fde5b
1e9434a
3d0deb2
8a1efcb
21157e2
adde5bf
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 |
---|---|---|
@@ -1,3 +1,4 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
Low-level functions for solving the single diode equation. | ||
""" | ||
|
@@ -22,6 +23,8 @@ | |
# rename newton and set keyword arguments | ||
newton = partial(_array_newton, tol=1e-6, maxiter=100, fprime2=None) | ||
|
||
VOLTAGE_BUILTIN = 0.9 # (V) intrinsic voltage for a:Si, CdTe, Mertens et al. | ||
|
||
|
||
def estimate_voc(photocurrent, saturation_current, nNsVth): | ||
""" | ||
|
@@ -62,14 +65,20 @@ def estimate_voc(photocurrent, saturation_current, nNsVth): | |
|
||
|
||
def bishop88(diode_voltage, photocurrent, saturation_current, | ||
resistance_series, resistance_shunt, nNsVth, gradients=False): | ||
resistance_series, resistance_shunt, nNsVth, cells_in_series=None, | ||
d2mutau=0, voltage_builtin=VOLTAGE_BUILTIN, | ||
gradients=False): | ||
""" | ||
Explicit calculation of points on the IV curve described by the single | ||
diode equation [1]. | ||
diode equation [1]_. | ||
|
||
[1] "Computer simulation of the effects of electrical mismatches in | ||
photovoltaic cell interconnection circuits" JW Bishop, Solar Cell (1988) | ||
https://doi.org/10.1016/0379-6787(88)90059-2 | ||
.. warning:: | ||
* Do not use ``d2mutau`` with CEC coefficients. | ||
* Usage of ``d2mutau`` with PVSyst coefficients is required for CdTe and | ||
a:Si modules. | ||
* For PVSyst CdTe and a:Si modules, the ``cells_in_series`` parameter | ||
must only account for a single parallel sub-string if the module has | ||
cells in parallel greater than 1. | ||
|
||
Parameters | ||
---------- | ||
|
@@ -86,6 +95,18 @@ def bishop88(diode_voltage, photocurrent, saturation_current, | |
nNsVth : numeric | ||
product of thermal voltage ``Vth`` [V], diode ideality factor ``n``, | ||
and number of series cells ``Ns`` | ||
cells_in_series : int | ||
|
||
number of cells in series per parallel module sub-string, only required | ||
for PVSyst thin-film recombination loss, if unset default is ``None`` | ||
which raises ``TypeError`` if ``d2mutau`` is set. | ||
d2mutau : numeric | ||
PVSyst thin-film recombination parameter that is the ratio of thickness | ||
of the intrinsic thin-film layer squared :math:`d^2` and the diffusion | ||
length of charge carriers :math:`\\mu \\tau`, in volts [V], defaults to | ||
0[V] | ||
voltage_builtin : numeric | ||
PVSyst thin-film recombination parameter that is the builtin voltage of | ||
the intrinsic thin-film layer, in volts [V], defaults to 0.9[V] | ||
gradients : bool | ||
False returns only I, V, and P. True also returns gradients | ||
|
||
|
@@ -96,22 +117,57 @@ def bishop88(diode_voltage, photocurrent, saturation_current, | |
:math:`\\frac{dI}{dV_d}`, :math:`\\frac{dV}{dV_d}`, | ||
:math:`\\frac{dI}{dV}`, :math:`\\frac{dP}{dV}`, and | ||
:math:`\\frac{d^2 P}{dV dV_d}` | ||
|
||
Notes | ||
----- | ||
The PVSyst thin-film recombination losses parameters ``d2mutau`` and | ||
``voltage_builtin`` are only applied to cadmium-telluride (CdTe) and | ||
amorphous-silicon (a:Si) PV modules, [2]_, [3]_. The builtin voltage should | ||
account for all junctions. *EG*: tandem and triple junction cell would have | ||
|
||
builtin voltages of 1.8[V] and 2.7[V] respectively, based on the default of | ||
0.9[V] for a single junction. | ||
|
||
References | ||
---------- | ||
.. [1] "Computer simulation of the effects of electrical mismatches in | ||
photovoltaic cell interconnection circuits" JW Bishop, Solar Cell (1988) | ||
:doi:`10.1016/0379-6787(88)90059-2` | ||
|
||
.. [2] "Improved equivalent circuit and Analytical Model for Amorphous | ||
Silicon Solar Cells and Modules." J. Mertens, et al., IEEE Transactions | ||
on Electron Devices, Vol 45, No 2, Feb 1998. | ||
:doi:`10.1109/16.658676` | ||
|
||
.. [3] "Performance assessment of a simulation model for PV modules of any | ||
available technology", André Mermoud and Thibault Lejeune, 25th EUPVSEC, | ||
2010 | ||
:doi:`10.4229/25thEUPVSEC2010-4BV.1.114` | ||
""" | ||
# check if need to calculate recombination loss current | ||
i_recomb, v_recomb = 0, np.inf | ||
if d2mutau > 0: | ||
|
||
v_recomb = voltage_builtin * cells_in_series - diode_voltage | ||
i_recomb = photocurrent * d2mutau / v_recomb | ||
|
||
# calculate temporary values to simplify calculations | ||
v_star = diode_voltage / nNsVth # non-dimensional diode voltage | ||
g_sh = 1.0 / resistance_shunt # conductance | ||
i = (photocurrent - saturation_current * np.expm1(v_star) | ||
- diode_voltage * g_sh) | ||
- diode_voltage * g_sh - i_recomb) | ||
v = diode_voltage - i * resistance_series | ||
retval = (i, v, i*v) | ||
if gradients: | ||
# check again if need to calculate recombination loss current gradients | ||
grad_i_recomb = grad_2i_recomb = 0 | ||
|
||
if d2mutau > 0: | ||
grad_i_recomb = i_recomb / v_recomb | ||
grad_2i_recomb = 2 * grad_i_recomb / v_recomb | ||
|
||
g_diode = saturation_current * np.exp(v_star) / nNsVth # conductance | ||
grad_i = -g_diode - g_sh # di/dvd | ||
grad_i = -g_diode - g_sh - grad_i_recomb # di/dvd | ||
grad_v = 1.0 - grad_i * resistance_series # dv/dvd | ||
# dp/dv = d(iv)/dv = v * di/dv + i | ||
grad = grad_i / grad_v # di/dv | ||
grad_p = v * grad + i # dp/dv | ||
grad2i = -g_diode / nNsVth # d2i/dvd | ||
grad2i = -g_diode / nNsVth - grad_2i_recomb # d2i/dvd | ||
grad2v = -grad2i * resistance_series # d2v/dvd | ||
grad2p = ( | ||
grad_v * grad + v * (grad2i/grad_v - grad_i*grad2v/grad_v**2) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,8 @@ | |
|
||
import numpy as np | ||
from pvlib import pvsystem | ||
from pvlib.singlediode_methods import bishop88, estimate_voc | ||
import pytest | ||
from conftest import requires_scipy | ||
|
||
POA = 888 | ||
|
@@ -100,7 +102,7 @@ def test_brentq_spr_e20_327(): | |
|
||
@requires_scipy | ||
def test_brentq_fs_495(): | ||
"""test pvsystem.singlediode with Brent method on SPR-E20-327""" | ||
"""test pvsystem.singlediode with Brent method on FS495""" | ||
fs_495 = CECMOD.First_Solar_FS_495 | ||
x = pvsystem.calcparams_desoto( | ||
effective_irradiance=POA, temp_cell=TCELL, | ||
|
@@ -125,3 +127,66 @@ def test_brentq_fs_495(): | |
method='lambertw') | ||
assert np.isclose(pvs_ixx, ixx) | ||
return isc, voc, imp, vmp, pmp, i, v, pvs | ||
|
||
|
||
# PVsyst parameters for First Solar FS-495 module from PVSyst-6.7.2 database | ||
# I_L_ref derived from Isc_ref conditions: | ||
# I_L_ref = (I_sc_ref + Id + Ish) / (1 - d2mutau/(Vbi*N_s - Vd)) | ||
# where | ||
# Vd = I_sc_ref * R_s | ||
# Id = I_o_ref * (exp(Vd / nNsVt) - 1) | ||
# Ish = Vd / R_sh_ref | ||
PVSYST_FS_495 = { | ||
|
||
'd2mutau': 1.31, 'alpha_sc': 0.00039, 'gamma_ref': 1.48, 'mu_gamma': 0.001, | ||
'I_o_ref': 9.62e-10, 'R_sh_ref': 5000, 'R_sh_0': 12500, 'R_sh_exp': 3.1, | ||
'R_s': 4.6, 'beta_oc': -0.2116, 'EgRef': 1.5, 'cells_in_series': 108, | ||
'cells_in_parallel': 2, 'I_sc_ref': 1.55, 'V_oc_ref': 86.5, | ||
'I_mp_ref': 1.4, 'V_mp_ref': 67.85, 'temp_ref': 25, 'irrad_ref': 1000, | ||
'I_L_ref': 1.5743233463848496 | ||
} | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'poa, temp_cell, expected, tol', | ||
[(PVSYST_FS_495['irrad_ref'], PVSYST_FS_495['temp_ref'], | ||
{'pmp': PVSYST_FS_495['I_mp_ref']*PVSYST_FS_495['V_mp_ref'], | ||
'isc': PVSYST_FS_495['I_sc_ref'], 'voc': PVSYST_FS_495['V_oc_ref']}, | ||
|
||
(5e-4, 0.04)), | ||
(POA, TCELL, {'pmp': 76.26, 'isc': 1.387, 'voc': 79.29}, (1e-3, 1e-3))] | ||
) # DeSoto @(888[W/m**2], 55[degC]) = {Pmp: 72.71, Isc: 1.402, Voc: 75.42) | ||
def test_pvsyst_recombination_loss(poa, temp_cell, expected, tol): | ||
|
||
"""test PVSst recombination loss""" | ||
# first evaluate PVSyst model with thin-film recombination loss current | ||
# at reference conditions | ||
pvsyst_fs_495 = PVSYST_FS_495 | ||
x = pvsystem.calcparams_pvsyst( | ||
effective_irradiance=poa, temp_cell=temp_cell, | ||
alpha_sc=pvsyst_fs_495['alpha_sc'], | ||
gamma_ref=pvsyst_fs_495['gamma_ref'], | ||
mu_gamma=pvsyst_fs_495['mu_gamma'], I_L_ref=pvsyst_fs_495['I_L_ref'], | ||
I_o_ref=pvsyst_fs_495['I_o_ref'], R_sh_ref=pvsyst_fs_495['R_sh_ref'], | ||
R_sh_0=pvsyst_fs_495['R_sh_0'], R_sh_exp=pvsyst_fs_495['R_sh_exp'], | ||
R_s=pvsyst_fs_495['R_s'], | ||
cells_in_series=pvsyst_fs_495['cells_in_series'], | ||
EgRef=pvsyst_fs_495['EgRef'] | ||
) | ||
il_pvsyst, io_pvsyst, rs_pvsyst, rsh_pvsyst, nnsvt_pvsyst = x | ||
voc_est_pvsyst = estimate_voc(photocurrent=il_pvsyst, | ||
saturation_current=io_pvsyst, | ||
nNsVth=nnsvt_pvsyst) | ||
vd_pvsyst = np.linspace(0, voc_est_pvsyst, 1000) | ||
pvsyst = bishop88( | ||
diode_voltage=vd_pvsyst, photocurrent=il_pvsyst, | ||
saturation_current=io_pvsyst, resistance_series=rs_pvsyst, | ||
resistance_shunt=rsh_pvsyst, nNsVth=nnsvt_pvsyst, | ||
d2mutau=pvsyst_fs_495['d2mutau'], | ||
cells_in_series=pvsyst_fs_495['cells_in_series'] | ||
) | ||
# test max power | ||
assert np.isclose(max(pvsyst[2]), expected['pmp'], *tol) | ||
# test short circuit current | ||
isc_pvsyst = np.interp(0, pvsyst[1], pvsyst[0]) | ||
assert np.isclose(isc_pvsyst, expected['isc'], *tol) | ||
# test open circuit current | ||
voc_pvsyst = np.interp(0, pvsyst[0][::-1], pvsyst[1][::-1]) | ||
assert np.isclose(voc_pvsyst, expected['voc'], *tol) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder about the short hand for module type here. I suppose this is fairly low level function so we should not worry too much.