Skip to content

Shunt resistance light dependence #91

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ pvmismatch.sublime-workspace

# files
*.pyc
*.orig

# build
dist/
pvmismatch.egg-info/
build/
Makefile
version.py
__pycache__/

# docs
!docs/_templates/
Expand All @@ -28,7 +28,7 @@ testPV/
benchmark_*/
.coverage
.cache/
__pycache__/
.pytest_cache/

# virtualenv
venv/
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ history is also on `GitHub <https://github.com/SunPower/releases/>`__.
:target: https://travis-ci.org/SunPower/PVMismatch

Other Projects that use PVMismatch
-----
----------------------------------
System level mismatch loss calculator using PVMismatch tool (STC and Annual energy loss)
https://github.com/SunPower/MismatchLossStudy
5 changes: 3 additions & 2 deletions pv_tk.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
@author: marko
"""
from pvmismatch.pvmismatch_tk.pvapplication_tk import PVapplicaton
from Tkinter import Tk
from tkinter import Tk
import sys
import re

Expand All @@ -19,6 +19,7 @@ def showHelpError(argvs_):
errMsg = errMsg + 'is not valid. See "wm_geometry help" above.'
raise Exception(errMsg)


if __name__ == "__main__":
nargv = len(sys.argv) # number of user arguments
argvs = sys.argv[1:] # will be empty if only sys.argv[0]
Expand Down Expand Up @@ -59,7 +60,7 @@ def showHelpError(argvs_):
dims = None
if dims is not None:
dim_reset_or_dims = lambda dims: (not dims) * 'reset' + dims
print "dimensions: {}".format(dim_reset_or_dims(dims))
print("dimensions: {}".format(dim_reset_or_dims(dims)))
root = Tk()
app = PVapplicaton(root)
root.geometry(dims)
Expand Down
54 changes: 35 additions & 19 deletions pvmismatch/contrib/gen_coeffs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,43 @@
import numpy as np
from scipy import optimize
from pvmismatch.contrib.gen_coeffs import diode, two_diode
from pvmismatch.pvmismatch_lib.pvcell import ISAT1_T0, ISAT2_T0, RS, RSH
from pvmismatch.pvmismatch_lib.pvcell import ISAT1_T0, ISAT2_T0, RS, RSH_E0

# IEC 61853 test matrix
TC_C = [15.0, 25.0, 50.0, 75.0]
IRR_W_M2 = [100.0, 200.0, 400.0, 600.0, 800.0, 1000.0, 1100.0]
TEST_MAT = np.meshgrid(TC_C, IRR_W_M2)
TEST_MAT = np.meshgrid(TC_C, IRR_W_M2) #: IEC61853 test matrix

def gen_iec_61853_from_sapm(pvmodule):
"""
Generate an IEC 61853 test from Sandia Array Performance Model (sapm).

:param pvmodule: PV module to be tested
:type pvmodule: dict
:param dict pvmodule: PV module to be tested
:returns: a pandas dataframe with columns ``i_mp``, ``v_mp``, ``i_sc``, and
``v_oc`` and rows corresponding to the IEC61853 test conditions

Module is a dictionary according to :def:`pvlib.pvsystem.sapm`.
Module is a dictionary according to ``pvlib.pvsystem.sapm``.
"""
tc, irr = TEST_MAT
return sapm(irr / 1000.0, tc, pvmodule)


def gen_two_diode(isc, voc, imp, vmp, nseries, nparallel,
tc, x0 = None, *args, **kwargs):
tc, ee, x0=None, *args, **kwargs):
"""
Generate two-diode model parameters for ``pvcell`` given
Generate two-diode model parameters for ``pvcell`` given.

:param numeric isc: short circuit current [A]
:param numeric voc: open circuit voltage [V]
:param numeric imp: max power current [A]
:param numeric vmp: max power voltage [V]
:param int nseries: number of cells in series
:param int nparallel: number of parallel substrings in PV module
:param numeric tc: cell temperature [C]
:param numeric ee: effective irradiance [suns]
:param x0: optional list of initial guesses, default is ``None``
:returns: tuple ``(isat1, isat2, rs, rsh)`` of generated coefficients and
the solver output
"""
isc_cell = isc / nparallel
voc_cell = voc / nseries
Expand All @@ -39,7 +52,7 @@ def gen_two_diode(isc, voc, imp, vmp, nseries, nparallel,
isat1 = ISAT1_T0 # [A]
isat2 = ISAT2_T0
rs = RS # [ohms]
rsh = RSH # [ohms]
rsh = RSH_E0 # [ohms]
else:
isat1 = x0[0]
isat2 = x0[1]
Expand All @@ -48,7 +61,7 @@ def gen_two_diode(isc, voc, imp, vmp, nseries, nparallel,
x = np.array([np.log(isat1), np.log(isat2), np.sqrt(rs), np.sqrt(rsh)])
sol = optimize.root(
fun=residual_two_diode, x0=x,
args=(isc_cell, voc_cell, imp_cell, vmp_cell, tc),
args=(isc_cell, voc_cell, imp_cell, vmp_cell, tc, ee),
jac=True,
*args, **kwargs
)
Expand Down Expand Up @@ -78,17 +91,18 @@ def gen_sapm(iec_61853):
return isc0, alpha_isc



def residual_two_diode(x, isc, voc, imp, vmp, tc):
def residual_two_diode(x, isc, voc, imp, vmp, tc, ee):
"""
Objective function to solve 2-diode model.
:param x: parameters isat1, isat2, rs and rsh
:param isc: short circuit current [A] at tc [C]
:param voc: open circuit voltage [V] at tc [C]
:param imp: max power current [A] at tc [C]
:param vmp: max power voltage [V] at tc [C]

:param x: parameters ``isat1``, ``isat2``, ``rs``, and ``rsh``
:param isc: short circuit current [A] at ``tc`` [C]
:param voc: open circuit voltage [V] at ``tc`` [C]
:param imp: max power current [A] at ``tc`` [C]
:param vmp: max power voltage [V] at ``tc`` [C]
:param tc: cell temperature [C]
:return: norm of the residuals its sensitivity
:param ee: effective irradiance [suns]
:returns: norm of the residuals and the Jacobian matrix
"""
# Constants
q = diode.QE # [C/electron] elementary electric charge
Expand All @@ -99,11 +113,13 @@ def residual_two_diode(x, isc, voc, imp, vmp, tc):
vt = kb * tck / q # [V] thermal voltage
# Rescale Variables
isat1_t0 = np.exp(x[0])
isat2 = np.exp(x[1])
isat2_t0 = np.exp(x[1])
rs = x[2] ** 2.0
rsh = x[3] ** 2.0
rsh_e0 = x[3] ** 2.0
rsh = rsh_e0 / ee
# first diode saturation current
isat1 = diode.isat_t(tc, isat1_t0)
isat2 = diode.isat_t(tc, isat2_t0)
# Short Circuit
vd_isc, _ = diode.fvd(vc=0.0, ic=isc, rs=rs)
id1_isc, _ = diode.fid(isat=isat1, vd=vd_isc, m=1.0, vt=vt)
Expand Down
141 changes: 87 additions & 54 deletions pvmismatch/contrib/gen_coeffs/example.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-

"""
Generate coefficients example.
"""

from __future__ import (
absolute_import, division, print_function, unicode_literals)
import os
import sys
from pvmismatch.contrib import gen_coeffs
from pvmismatch import *
from matplotlib import pyplot as plt
Expand All @@ -22,60 +29,86 @@

iec61853 = gen_coeffs.gen_iec_61853_from_sapm(gen_coeffs.PVMODULES[PROD_NAME])
iec61853['i_mp'] = iec61853['p_mp'] / iec61853['v_mp']
#isc0, alpha_isc = gen_coeffs.gen_sapm(iec61853)
#x, sol = gen_coeffs.gen_two_diode(ISC0, VOC0, IMP0, VMP0, NS, NP, T0)
x, sol = gen_coeffs.gen_two_diode(
iec61853['i_sc'], iec61853['v_oc'], iec61853['i_mp'],
iec61853['v_mp'], NS, NP, tc=TC, method='lm',
x0=(2.25e-11, 1.5e-6, 0.004, 10.0)
)
isat1, isat2, rs, rsh = x

pvc = pvcell.PVcell(
Rs=rs, Rsh=rsh, Isat1_T0=isat1, Isat2_T0=isat2,
Isc0_T0=ISC0/NP, alpha_Isc=AISC
)
f1 = plt.figure()
isc0, alpha_isc = gen_coeffs.gen_sapm(iec61853)
assert np.isclose(isc0, ISC0)
assert np.isclose(alpha_isc, AISC)

for m, _tc in enumerate(gen_coeffs.TC_C):
pvc.Tcell = _tc + 273.15
plt.subplot(2, 2, m+1)
plt.xlim([0, 0.8])
plt.ylim([0, 8])
res_norm = 0
for n, _irr in enumerate(gen_coeffs.IRR_W_M2):
pvc.Ee = _irr / 1000.0
plt.plot(pvc.Vcell, pvc.Icell, '-', pvc.Vcell, pvc.Pcell, ':')
plt.plot(
iec61853['v_mp'][n][m]/NS, iec61853['i_mp'][n][m]/NP, 'x',
iec61853['v_oc'][n][m]/NS, 0.0, 'x',
0.0, iec61853['i_sc'][n][m]/NP, 'x',
iec61853['v_mp'][n][m]/NS, iec61853['p_mp'][n][m]/NS/NP, 'o',
if __name__ == '__main__':
test_cond = 'STC'
if len(sys.argv) > 1:
test_cond = sys.argv[1]
if test_cond.upper() == 'STC':
x, sol = gen_coeffs.gen_two_diode(ISC0, VOC0, IMP0, VMP0, NS, NP, T0, E0)
else:
x, sol = gen_coeffs.gen_two_diode(
iec61853['i_sc'], iec61853['v_oc'], iec61853['i_mp'],
iec61853['v_mp'], NS, NP, tc=TC, ee=IRR/1000., method='lm',
x0=(2.25e-11, 1.5e-6, 0.004, 10.0)
)
res_norm += (
pvc.calcIcell(iec61853['v_mp'][n][m]/NS)
- iec61853['i_mp'][n][m]/NP
)**2 / (iec61853['i_mp'][n][m]/NP)**2
res_norm += (
pvc.calcVcell(iec61853['i_mp'][n][m]/NP)
- iec61853['v_mp'][n][m]/NS
)**2 / (iec61853['v_mp'][n][m]/NS)**2
res_norm += (
pvc.calcVcell(0.0) - iec61853['v_oc'][n][m]/NS
)**2 / (iec61853['v_oc'][n][m]/NS)**2
res_norm += (
pvc.calcIcell(0.0) - iec61853['i_sc'][n][m]/NP
)**2 / (iec61853['i_sc'][n][m]/NP)**2
rel_diff = (pvc.Pcell.max()*NS*NP - iec61853['p_mp'][n][m]) / PMP0
plt.annotate('$\Delta_{rel}$ = %.2g%%' % (rel_diff*100),
(0.65, iec61853['p_mp'][n][m]/NS/NP))
plt.annotate('norm of residuals = %g' % np.sqrt(res_norm / (7*4)),
(0.5, 7.5))
plt.grid(True)
plt.title(
'PVMismatch Generated Coefficients for %s at Tc = %g' % (PROD_NAME, _tc)
isat1, isat2, rs, rsh = x

pvc = pvcell.PVcell(
Rs=rs, Rsh_E0=rsh, Isat1_T0=isat1, Isat2_T0=isat2,
Isc0_T0=ISC0/NP, alpha_Isc=AISC
)
plt.xlabel('voltage')
plt.ylabel('current [A]')
plt.xlabel('voltage [V]')
f1.show()
f1 = plt.figure(figsize=(16, 10))

for m, _tc in enumerate(gen_coeffs.TC_C):
pvc.Tcell = _tc + 273.15
plt.subplot(2, 2, m+1)
plt.xlim([0, round(VOC0/NS*1.25, 2)])
plt.ylim([0, round(ISC0/NP*1.25, 1)])
res_norm = 0
for n, _irr in enumerate(gen_coeffs.IRR_W_M2):
pvc.Ee = _irr / 1000.0
plt.plot(pvc.Vcell, pvc.Icell, '-', pvc.Vcell, pvc.Pcell, ':')
plt.plot(
iec61853['v_mp'][n][m]/NS, iec61853['i_mp'][n][m]/NP, 'x',
iec61853['v_oc'][n][m]/NS, 0.0, 'x',
0.0, iec61853['i_sc'][n][m]/NP, 'x',
iec61853['v_mp'][n][m]/NS, iec61853['p_mp'][n][m]/NS/NP, 'o',
)
res_norm += (
pvc.calcIcell(iec61853['v_mp'][n][m]/NS)
- iec61853['i_mp'][n][m]/NP
)**2 / (IMP0/NP)**2
res_norm += (
pvc.calcVcell(iec61853['i_mp'][n][m]/NP)
- iec61853['v_mp'][n][m]/NS
)**2 / (VMP0/NS)**2
res_norm += (
pvc.calcVcell(0.0) - iec61853['v_oc'][n][m]/NS
)**2 / (VOC0/NS)**2
res_norm += (
pvc.calcIcell(0.0) - iec61853['i_sc'][n][m]/NP
)**2 / (ISC0/NP)**2
rel_diff = (pvc.Pcell.max()*NS*NP - iec61853['p_mp'][n][m]) / PMP0
plt.annotate('$\Delta_{STC}$ = %.2g%%' % (rel_diff*100),
(0.65, iec61853['p_mp'][n][m]/NS/NP))
plt.annotate('$E_e$ = %.2g[suns]' % (_irr/1000),
(0.05, 0.05+iec61853['i_sc'][n][m]/NP))
plt.annotate('STC RMSE = %.2g%%' % (np.sqrt(res_norm / (7*4))*100),
(0.65, 7.5))
plt.annotate('$I_{sat,1}$ = %.4g' % isat1,
(0.65, 7.2))
plt.annotate('$I_{sat,2}$ = %.4g' % isat2,
(0.65, 6.9))
plt.annotate('$R_s$ = %.4g' % rs,
(0.65, 6.6))
plt.annotate('$R_{sh}$ = %.4g' % rsh,
(0.65, 6.3))

plt.grid(True)
plt.title(
'PVMismatch Generated Coefficients for %s at Tc = %g' % (PROD_NAME, _tc)
)
plt.xlabel('voltage')
plt.ylabel('current [A], power [W]')
plt.xlabel('voltage [V]')
plt.tight_layout()
if len(sys.argv) > 2:
test_save_dir = sys.argv[2]
os.makedirs(test_save_dir, exist_ok=True)
f1.savefig(os.path.join(test_save_dir, sys.argv[1]))
else:
f1.show()
2 changes: 1 addition & 1 deletion pvmismatch/contrib/gen_coeffs/tests/test_diode.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""

from pvmismatch.pvmismatch_lib.pvcell import (
RS as RS_2, RSH as RSH_2, ISAT1_T0 as ISAT1_2, ISAT2_T0 as ISAT2_2
RS as RS_2, RSH_E0 as RSH_2, ISAT1_T0 as ISAT1_2, ISAT2_T0 as ISAT2_2
)
from pvmismatch.contrib.gen_coeffs import diode
from pvmismatch.contrib.gen_coeffs import PVMODULES
Expand Down
Loading