diff --git a/.gitignore b/.gitignore index 37fc2f7..9fb9c78 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ pvmismatch.sublime-workspace # files *.pyc -*.orig # build dist/ @@ -18,6 +17,7 @@ pvmismatch.egg-info/ build/ Makefile version.py +__pycache__/ # docs !docs/_templates/ @@ -28,7 +28,7 @@ testPV/ benchmark_*/ .coverage .cache/ -__pycache__/ +.pytest_cache/ # virtualenv venv/ diff --git a/README.rst b/README.rst index 9382c3d..461bb22 100644 --- a/README.rst +++ b/README.rst @@ -35,6 +35,6 @@ history is also on `GitHub `__. :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 diff --git a/pv_tk.py b/pv_tk.py index 9a61305..a7f874b 100755 --- a/pv_tk.py +++ b/pv_tk.py @@ -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 @@ -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] @@ -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) diff --git a/pvmismatch/contrib/gen_coeffs/__init__.py b/pvmismatch/contrib/gen_coeffs/__init__.py index ea9e616..944d55c 100644 --- a/pvmismatch/contrib/gen_coeffs/__init__.py +++ b/pvmismatch/contrib/gen_coeffs/__init__.py @@ -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 @@ -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] @@ -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 ) @@ -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 @@ -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) diff --git a/pvmismatch/contrib/gen_coeffs/example.py b/pvmismatch/contrib/gen_coeffs/example.py index aa24659..c7dc0bc 100644 --- a/pvmismatch/contrib/gen_coeffs/example.py +++ b/pvmismatch/contrib/gen_coeffs/example.py @@ -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 @@ -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() diff --git a/pvmismatch/contrib/gen_coeffs/tests/test_diode.py b/pvmismatch/contrib/gen_coeffs/tests/test_diode.py index eea9933..cc18815 100644 --- a/pvmismatch/contrib/gen_coeffs/tests/test_diode.py +++ b/pvmismatch/contrib/gen_coeffs/tests/test_diode.py @@ -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 diff --git a/pvmismatch/contrib/module_mismatch_simulator.py b/pvmismatch/contrib/module_mismatch_simulator.py index 2e676c1..ef39e51 100755 --- a/pvmismatch/contrib/module_mismatch_simulator.py +++ b/pvmismatch/contrib/module_mismatch_simulator.py @@ -2,27 +2,33 @@ ''' Created on Mar 29, 2013 + This script allows the user to dynamically investigate the IV and PV characteristics of a single module. The user chooses the modules size--72 or 96 -cells. A UI is then generated that allows the user to change the size, location, +cells. A GUI is then generated that allows the user to change the size, location, and irradiance level of a single "shade rectangle". Outputs include cell, substring, and module level IV and PV curves as well as a module diagram showing the shade location, any reverse biased cells, and any active diodes. + @author: bmeyers ''' # ============================================================================== # Importing standard libraries # ============================================================================== -import matplotlib.pyplot as plt -import matplotlib.gridspec as gridspec +from __future__ import ( + absolute_import, division, unicode_literals, print_function) +import json +from functools import partial +from copy import deepcopy +import os import numpy as np from scipy.interpolate import interp1d +import matplotlib.pyplot as plt +import matplotlib.gridspec as gridspec from matplotlib.widgets import Slider from matplotlib.widgets import Button -import json -from functools import partial -from copy import deepcopy +from past.builtins import raw_input, xrange # ============================================================================== # Import PVmismatch items @@ -32,8 +38,8 @@ from pvmismatch import PVsystem, PVmodule, PVcell, PVconstants from pvmismatch.pvmismatch_lib.pvmodule import STD72, STD96, STD128 except ImportError: - print "PVMismatch not found on path! Please use 'pip install -e path/to/pvmismatch'" - print "or 'export PYTHONPATH=path/to/pvmismatch:$PYTHONPATH' first." + print("PVMismatch not found on path! Please use 'pip install -e path/to/pvmismatch'") + print("or 'export PYTHONPATH=path/to/pvmismatch:$PYTHONPATH' first.") import sys sys.exit(-1) @@ -74,8 +80,8 @@ class ShadeObj(object): def __init__(self, pershade=90, shd_width=1, shd_height=1, shd_x=4, shd_y=6, numberCells=96): modHeight = modheight(numberCells) - module = np.empty([numberCells / modHeight, modHeight], dtype=int) - for n in range(numberCells / modHeight): + module = np.empty([numberCells // modHeight, modHeight], dtype=int) + for n in range(numberCells // modHeight): if n % 2 == 0: module[n] = np.arange(n * modHeight, (n + 1) * modHeight, 1) else: @@ -155,8 +161,8 @@ def plotting_calcs(pvmod, ivp=None): reversebias = [n for n in range(len(ivp.Icell.T)) if -np.interp(-ivp.Imp, -ivp.Icell.T[n], -ivp.Vcell.T[n]) < 0] boolindx = np.array(reversebias) - module = np.empty([pvmod.numberCells / ivp.modHeight, ivp.modHeight], dtype=int) - for n in range(pvmod.numberCells / ivp.modHeight): + module = np.empty([pvmod.numberCells // ivp.modHeight, ivp.modHeight], dtype=int) + for n in range(pvmod.numberCells // ivp.modHeight): if n % 2 == 0: module[n] = np.arange(n * ivp.modHeight, (n + 1) * ivp.modHeight, 1) else: @@ -427,7 +433,7 @@ def full_update(val, output=None, ivp0=None, plotobjs=None): output['ax12'], output['ax03'], output['ax_4'], output['x'], output['y']) plt.draw() t1 = (sw * sh, s_ps.val, ivp0.Pmp, 100 * ivp0.Pmp / Pmp0) - print '{0:^6} {1:^6,.2f} {2:^6,.2f} {3:^7,.2f}'.format(*t1) + print('{0:^6} {1:^6,.2f} {2:^6,.2f} {3:^7,.2f}'.format(*t1)) def set_the_shade(val): @@ -435,16 +441,18 @@ def set_the_shade(val): def save_the_shade(val): + this_dir = os.getcwd() + save_dir = os.path.join(this_dir, 'JSONshade') + os.makedirs(save_dir, exist_ok=True) dicts = [] for shd in ivp0.shade: dicts.append({'ps': shd.pershade, 'sw': shd.sw, 'sh': shd.sh, 'sy': shd.sy, 'sx': shd.sx, 'numberCells': pvmod1.numberCells}) filename = raw_input("File name? ") - filename = 'JSONshade/' + filename + '.json' - fo = open(filename, 'w') - shades_json = json.dump(dicts, fo, sort_keys=True, indent=2) - fo.close() + filename = os.path.join(save_dir, filename + '.json') + with open(filename, 'w') as fo: + json.dump(dicts, fo, sort_keys=True, indent=2) def clear_last_full(val, update=None): @@ -465,10 +473,10 @@ def clear_last_full(val, update=None): plotobjs = PlotObjs() update = partial(full_update, output=output, ivp0=ivp0, plotobjs=plotobjs) ClearLast = partial(clear_last_full, update=update) - print "Pmp0: {}".format(Pmp0) - print "" - print '{0:6} {1:^6} {2:^6} {3:^7}'.format('#Cells', '%Shade', 'Pmp', '%ofPmp0') - print '----------------------------' + print("Pmp0: {}".format(Pmp0)) + print("") + print('{0:6} {1:^6} {2:^6} {3:^7}'.format('#Cells', '%Shade', 'Pmp', '%ofPmp0')) + print('----------------------------') ps0 = 90 sw0 = 1 sh0 = 1 diff --git a/pvmismatch/contrib/tiled_reference_module.py b/pvmismatch/contrib/tiled_reference_module.py index a36c1b0..7c21e7e 100644 --- a/pvmismatch/contrib/tiled_reference_module.py +++ b/pvmismatch/contrib/tiled_reference_module.py @@ -14,9 +14,9 @@ # Cell parameters RS = 0.0181123 # [ohm] series resistance - RSH = 58.082 # [ohm] shunt resistance + RSH_E0 = 58.082 # [ohm] shunt resistance ISAT1_T0 = 2.9885E-11 # [A] diode one saturation current - ISAT2 = 1.6622E-07 # [A] diode two saturation current + ISAT2_T0 = 1.6622E-07 # [A] diode two saturation current ISC0_T0 = 1.437 # [A] reference short circuit current ARBD = 9.0E-4 # reverse breakdown coefficient 1 BRBD = -0.056 # reverse breakdown coefficient 2 @@ -36,21 +36,21 @@ NUMBERSTRS = 1 # number of strings in parallel # System definition - tiledCell = pvcell.PVcell(Rs=RS, Rsh=RSH, Isat1_T0=ISAT1_T0, Isat2=ISAT2, - Isc0_T0=ISC0_T0, aRBD=ARBD, VRBD=VRBD_, bRBD=BRBD, - nRBD=NRBD, Eg=EG, alpha_Isc=ALPHA_ISC, - Tcell=TCELL) + tiledCell = pvcell.PVcell(Rs=RS, Rsh_E0=RSH_E0, Isat1_T0=ISAT1_T0, Isat2_T0=ISAT2_T0, + Isc0_T0=ISC0_T0, aRBD=ARBD, VRBD=VRBD_, bRBD=BRBD, + nRBD=NRBD, Eg=EG, alpha_Isc=ALPHA_ISC, + Tcell=TCELL) tiledModule = pvmodule.PVmodule(cell_pos=pvmodule.PCT492, pvcells=tiledCell, Vbypass=VBYPASS, cellArea=CELLAREA) # Tiled module with partial cross-ties tiledSystem = pvsystem.PVsystem(pvconst=pvconstants.PVconstants(npts=NPTS), pvmods=tiledModule, numberStrs=NUMBERSTRS, numberMods=NUMBERMODS) - print 'Imp = ' + str(tiledSystem.Imp) + ' A' - print 'Vmp = ' + str(tiledSystem.Vmp) + ' V' - print 'Pmp = ' + str(tiledSystem.Pmp) + ' W' - print 'Isc = ' + str(tiledSystem.Isc) + ' A' - print 'Voc = ' + str(tiledSystem.Voc) + ' V' - print 'FF = ' + str(100*tiledSystem.FF) + ' %' - print 'Efficiency = ' + str(100*tiledSystem.eff) + ' %' + print('Imp = ' + str(tiledSystem.Imp) + ' A') + print('Vmp = ' + str(tiledSystem.Vmp) + ' V') + print('Pmp = ' + str(tiledSystem.Pmp) + ' W') + print('Isc = ' + str(tiledSystem.Isc) + ' A') + print('Voc = ' + str(tiledSystem.Voc) + ' V') + print('FF = ' + str(100*tiledSystem.FF) + ' %') + print('Efficiency = ' + str(100*tiledSystem.eff) + ' %') figure = tiledSystem.plotSys() plt.show() diff --git a/pvmismatch/docs/api/contrib.rst b/pvmismatch/docs/api/contrib.rst new file mode 100644 index 0000000..223496f --- /dev/null +++ b/pvmismatch/docs/api/contrib.rst @@ -0,0 +1,45 @@ +.. _contrib: + +Contributions +============= + +.. automodule:: pvmismatch.contrib + +Generate Coefficients +--------------------- + +.. automodule:: pvmismatch.contrib.gen_coeffs + :members: + +Example +~~~~~~~ +Run the example in :mod:`~pvmismatch.contrib.gen_coeffs`:: + + python pvmismatch/contrib/gen_coeffs/example.py STC ./examples + +This creates a figure ``examples/STC.png`` which calculates the coefficients +using only STC conditions, and displays the power error relative to STC, and +the RMSE of the IV curve relative to ``IMP0``, ``VMP0``, ``ISC0``, and +``VOC0``. + +.. image:: examples/STC.png + +Run the example again with ``IEC61853`` as the first argument:: + + python pvmismatch/contrib/gen_coeffs/example.py IEC61853 ./examples + +This creates a figure ``examples/IEC61853.png`` which calculates the +coefficients using the IEC61853 test conditions, and displays the power error +relative to STC, and the RMSE of the IV curve relative to ``IMP0``, ``VMP0``, +``ISC0``, and ``VOC0``. + +.. image:: examples/IEC61853.png + +Note: You can see that the lack of irradiance correction on shunt resistance +in PVMismatch causes a larger error when the IEC61853 test results are used. + +Module Mismatch Simulator +------------------------- + +.. automodule:: pvmismatch.contrib.module_mismatch_simulator + diff --git a/pvmismatch/docs/api/examples/STC.png b/pvmismatch/docs/api/examples/STC.png new file mode 100644 index 0000000..7024842 Binary files /dev/null and b/pvmismatch/docs/api/examples/STC.png differ diff --git a/pvmismatch/docs/api/examples/iec61853.png b/pvmismatch/docs/api/examples/iec61853.png new file mode 100644 index 0000000..1004031 Binary files /dev/null and b/pvmismatch/docs/api/examples/iec61853.png differ diff --git a/pvmismatch/docs/conf.py b/pvmismatch/docs/conf.py index 5c0a118..2afa5b6 100644 --- a/pvmismatch/docs/conf.py +++ b/pvmismatch/docs/conf.py @@ -266,7 +266,7 @@ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { - 'numpy': ('http://docs.scipy.org/doc/numpy/', None), - 'scipy': ('http://docs.scipy.org/doc/scipy/reference/', None), - 'python': ('http://docs.python.org/', None)} + 'numpy': ('https://docs.scipy.org/doc/numpy', None), + 'scipy': ('https://docs.scipy.org/doc/scipy/reference', None), + 'python': ('https://docs.python.org/3', None)} diff --git a/pvmismatch/docs/index.rst b/pvmismatch/docs/index.rst index 567c696..8e7ebac 100644 --- a/pvmismatch/docs/index.rst +++ b/pvmismatch/docs/index.rst @@ -31,6 +31,7 @@ Contents: api/pvmodule api/pvstring api/pvsystem + api/contrib Indices and tables diff --git a/pvmismatch/pvmismatch_lib/pvcell.py b/pvmismatch/pvmismatch_lib/pvcell.py index 080e449..e59ab39 100644 --- a/pvmismatch/pvmismatch_lib/pvcell.py +++ b/pvmismatch/pvmismatch_lib/pvcell.py @@ -14,7 +14,7 @@ # Defaults RS = 0.004267236774264931 # [ohm] series resistance -RSH = 10.01226369025448 # [ohm] shunt resistance +RSH_E0 = 10.01226369025448 # [ohm] shunt resistance ISAT1_T0 = 2.286188161253440E-11 # [A] diode one saturation current ISAT2_T0 = 1.117455042372326E-6 # [A] diode two saturation current ISC0_T0 = 6.3056 # [A] reference short circuit current @@ -27,14 +27,15 @@ ALPHA_ISC = 0.0003551 # [1/K] short circuit current temperature coefficient EPS = np.finfo(np.float64).eps + class PVcell(object): """ Class for PV cells. :param Rs: series resistance [ohms] - :param Rsh: shunt resistance [ohms] - :param Isat1_T0: first saturation diode current at ref temp [A] - :param Isat2_T0: second saturation diode current [A] + :param Rsh_E0: shunt resistance at ref irradiance[ohms] + :param Isat1_T0: first saturation diode current at ref temperature [A] + :param Isat2_T0: second saturation diode current at ref temperature [A] :param Isc0_T0: short circuit current at ref temp [A] :param aRBD: reverse breakdown coefficient 1 :param bRBD: reverse breakdown coefficient 2 @@ -50,13 +51,13 @@ class PVcell(object): _calc_now = False #: if True ``calcCells()`` is called in ``__setattr__`` - def __init__(self, Rs=RS, Rsh=RSH, Isat1_T0=ISAT1_T0, Isat2_T0=ISAT2_T0, + def __init__(self, Rs=RS, Rsh_E0=RSH_E0, Isat1_T0=ISAT1_T0, Isat2_T0=ISAT2_T0, Isc0_T0=ISC0_T0, aRBD=ARBD, bRBD=BRBD, VRBD=VRBD_, nRBD=NRBD, Eg=EG, alpha_Isc=ALPHA_ISC, Tcell=TCELL, Ee=1., pvconst=PVconstants()): # user inputs self.Rs = Rs #: [ohm] series resistance - self.Rsh = Rsh #: [ohm] shunt resistance + self.Rsh_E0 = Rsh_E0 #: [ohm] shunt resistance at E0 self.Isat1_T0 = Isat1_T0 #: [A] diode one sat. current at T0 self.Isat2_T0 = Isat2_T0 #: [A] diode two saturation current self.Isc0_T0 = Isc0_T0 #: [A] short circuit current at T0 @@ -133,6 +134,10 @@ def Aph(self): # photogenerated current coefficient return 1. + (Idiode1_sc + Idiode2_sc + Ishunt_sc) / self.Isc + @property + def Rsh(self): + return self.Rsh_E0 / self.Ee + @property def Isat1(self): """ @@ -185,7 +190,7 @@ def _VocSTC(self): Vdiode_sc = self.Isc0_T0 * self.Rs # diode voltage at SC Idiode1_sc = self.Isat1_T0 * (np.exp(Vdiode_sc / self.Vt) - 1.) Idiode2_sc = self.Isat2_T0 * (np.exp(Vdiode_sc / 2. / self.Vt) - 1.) - Ishunt_sc = Vdiode_sc / self.Rsh # diode voltage at SC + Ishunt_sc = Vdiode_sc / self.Rsh_E0 # diode voltage at SC # photogenerated current coefficient Aph = 1. + (Idiode1_sc + Idiode2_sc + Ishunt_sc) / self.Isc0_T0 # estimated Voc at STC @@ -234,7 +239,7 @@ def calcCell(self): fRBD = 1. - Vdiode / self.VRBD # use epsilon = 2.2204460492503131e-16 to avoid "divide by zero" fRBD[fRBD == 0] = EPS - Vdiode_norm = Vdiode / self.Rsh / self.Isc0_T0 + Vdiode_norm = Vdiode / self.Rsh_E0 / self.Isc0_T0 fRBD = self.Isc0_T0 * fRBD ** (-self.nRBD) IRBD = (self.aRBD * Vdiode_norm + self.bRBD * Vdiode_norm ** 2) * fRBD Icell = self.Igen - Idiode1 - Idiode2 - Ishunt - IRBD diff --git a/pvmismatch/pvmismatch_tk/advCnf_tk.py b/pvmismatch/pvmismatch_tk/advCnf_tk.py index 0dc98f6..495da81 100644 --- a/pvmismatch/pvmismatch_tk/advCnf_tk.py +++ b/pvmismatch/pvmismatch_tk/advCnf_tk.py @@ -4,10 +4,12 @@ @author: mmikofski """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) +from tkinter.constants import W, E, RIGHT +from tkinter import Frame, Label, Button, DoubleVar, Entry, IntVar +import tkinter.font as tkFont -from Tkconstants import W, E, RIGHT -from Tkinter import Frame, Label, Button, DoubleVar, Entry, IntVar -import tkFont PVAPP_TXT = 'PVmismatch' INTEGERS = '0123456789' @@ -36,29 +38,45 @@ def __init__(self, pvapp, top): # variables cellnum = self.cellnum = IntVar(self, name='cellnum') Rs = self.Rs = DoubleVar(self, name='Rs') - Rsh = self.Rsh = DoubleVar(self, name='Rsh') + Rsh_E0 = self.Rsh_E0 = DoubleVar(self, name='Rsh_E0') Isat1_T0 = self.Isat1_T0 = DoubleVar(self, name='Isat1_T0') - Isat2 = self.Isat2 = DoubleVar(self, name='Isat2') - Rs.set("{:10.4e}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].Rs)) - Rsh.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].Rsh)) - Isat1_T0.set("{:10.4e}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].Isat1_T0)) - Isat2.set("{:10.4e}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].Isat2)) + Isat2_T0 = self.Isat2_T0 = DoubleVar(self, name='Isat2_T0') + Rs.set("{:10.4e}".format(pvapp.pvSys.pvmods[ + cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get()) + ][ + (cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get() + ].pvcells[cellnum.get() % pvapp.numCells.get()].Rs)) + Rsh_E0.set("{:10.4f}".format(pvapp.pvSys.pvmods[ + cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get()) + ][ + (cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get() + ].pvcells[cellnum.get() % pvapp.numCells.get()].Rsh_E0)) + Isat1_T0.set("{:10.4e}".format(pvapp.pvSys.pvmods[ + cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get()) + ][ + (cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get() + ].pvcells[cellnum.get() % pvapp.numCells.get()].Isat1_T0)) + Isat2_T0.set("{:10.4e}".format(pvapp.pvSys.pvmods[ + cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get()) + ][ + (cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get() + ].pvcells[cellnum.get() % pvapp.numCells.get()].Isat2_T0)) Aph = self.Aph = DoubleVar(self, name='Aph') Isc0_T0 = self.Isc0_T0 = DoubleVar(self, name='Isc0_T0') Tcell = self.Tcell = DoubleVar(self, name='Tcell') Vbypass = self.Vbypass = DoubleVar(self, name='Vbypasss') - Aph.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].Aph)) - Isc0_T0.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].Isc0_T0)) - Tcell.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].Tcell)) - Vbypass.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].Vbypass)) + Aph.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].Aph)) + Isc0_T0.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get()// (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].Isc0_T0)) + Tcell.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].Tcell)) + Vbypass.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get()].Vbypass)) aRBD = self.aRBD = DoubleVar(self, name='aRBD') VRBD = self.VRBD = DoubleVar(self, name='VRBD') nRBD = self.nRBD = DoubleVar(self, name='nRBD') cellArea = self.cellArea = DoubleVar(self, name='cellArea') - aRBD.set("{:10.4e}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].aRBD)) - VRBD.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].VRBD)) - nRBD.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].nRBD)) - cellArea.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].cellArea)) + aRBD.set("{:10.4e}".format(pvapp.pvSys.pvmods[cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].aRBD)) + VRBD.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].VRBD)) + nRBD.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[cellnum.get() % pvapp.numCells.get()].nRBD)) + cellArea.set("{:10.4f}".format(pvapp.pvSys.pvmods[cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get())][(cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get()].cellArea)) # must register vcmd and invcmd as Tcl functions vcmd = (self.register(self.validateWidget), @@ -72,10 +90,10 @@ def __init__(self, pvapp, top): text='Advanced Configuration', font=CAPTION_FONT).grid(row=_row, columnspan=3, sticky=W) _row += 1 - # cellnum, Rs, Rsh, Isat1_T0 + # cellnum, Rs, Rsh_E0, Isat1_T0 Label(self, text='cell #').grid(row=_row, sticky=W) Label(self, text='Rs [Ohms]').grid(row=_row + 1, sticky=W) - Label(self, text='Rsh [Ohms]').grid(row=(_row + 2), sticky=W) + Label(self, text='Rsh_E0 [Ohms]').grid(row=(_row + 2), sticky=W) Label(self, text='Isat1_T0 [A]').grid(row=(_row + 3), sticky=W) cellnumEntry = Entry(self, textvariable=cellnum, width=12, justify=RIGHT, name='cellnumEntry', validatecommand=vcmd, @@ -85,7 +103,7 @@ def __init__(self, pvapp, top): name='rsEntry', validatecommand=vcmd, invalidcommand=invcmd, validate='all') RsEntry.grid(row=_row + 1, column=1) - RshEntry = Entry(self, textvariable=Rsh, width=12, justify=RIGHT, + RshEntry = Entry(self, textvariable=Rsh_E0, width=12, justify=RIGHT, name='rshEntry', validatecommand=vcmd, invalidcommand=invcmd, validate='all') RshEntry.grid(row=(_row + 2), column=1) @@ -95,15 +113,15 @@ def __init__(self, pvapp, top): validate='all') Isat1_T0Entry.grid(row=(_row + 3), column=1) _row += 4 # row 2, 3, 4, 5 - # Isat2, Isc0_T0, Tcell, Vbypasss - Label(self, text='Isat2 [A]').grid(row=(_row), sticky=W) + # Isat2_T0, Isc0_T0, Tcell, Vbypasss + Label(self, text='Isat2_T0 [A]').grid(row=(_row), sticky=W) Label(self, text='Isc0_T0 [A]').grid(row=(_row + 1), sticky=W) Label(self, text='Tcell [K]').grid(row=(_row + 2), sticky=W) Label(self, text='Vbypass [V]').grid(row=(_row + 3), sticky=W) - Isat2Entry = Entry(self, textvariable=Isat2, width=12, justify=RIGHT, + Isat2_T0Entry = Entry(self, textvariable=Isat2_T0, width=12, justify=RIGHT, name='isat2Entry', validatecommand=vcmd, invalidcommand=invcmd, validate='all') - Isat2Entry.grid(row=(_row), column=1) + Isat2_T0Entry.grid(row=(_row), column=1) Isc01_T0Entry = Entry(self, textvariable=Isc0_T0, width=12, justify=RIGHT, name='isc01_T0Entry', validatecommand=vcmd, invalidcommand=invcmd, @@ -156,8 +174,8 @@ def okay(self): self.pvapp.msgtext.set('Invalid series resistance!') self.bell() return - Rsh = self.Rsh.get() - if not (0 < Rsh <= validationConstants["advCnf"]["Rsh"]): + Rsh_E0 = self.Rsh_E0.get() + if not (0 < Rsh_E0 <= validationConstants["advCnf"]["Rsh_E0"]): self.pvapp.msgtext.set('Invalid shunt resistance!') self.bell() return @@ -166,8 +184,8 @@ def okay(self): self.pvapp.msgtext.set('Invalid diode-1 saturation current!') self.bell() return - Isat2 = self.Isat2.get() - if not 0 < Isat2 <= validationConstants["advCnf"]["Isat2"]: + Isat2_T0 = self.Isat2_T0.get() + if not 0 < Isat2_T0 <= validationConstants["advCnf"]["Isat2_T0"]: self.pvapp.msgtext.set('Invalid diode-2 saturation current!') self.bell() return @@ -219,8 +237,8 @@ def okay(self): # update PVconstants self.pvapp.msgtext.set(messagetext["pvapplication"]["Ready"]) pvapp = self.pvapp - kwargs = {'Rs': Rs, 'Rsh': Rsh, 'Isat1_T0': Isat1_T0, 'Isat2': Isat2, 'Isc0_T0': Isc0_T0, 'Tcell': Tcell, 'aRBD': aRBD, 'VRBD': VRBD, 'nRBD': nRBD} - pvapp.pvSys.pvmods[self.cellnum.get() / (pvapp.numCells.get() * pvapp.numMods.get())][(self.cellnum.get() / pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[self.cellnum.get() % pvapp.numCells.get()].update( + kwargs = {'Rs': Rs, 'Rsh_E0': Rsh_E0, 'Isat1_T0': Isat1_T0, 'Isat2_T0': Isat2_T0, 'Isc0_T0': Isc0_T0, 'Tcell': Tcell, 'aRBD': aRBD, 'VRBD': VRBD, 'nRBD': nRBD} + pvapp.pvSys.pvmods[self.cellnum.get() // (pvapp.numCells.get() * pvapp.numMods.get())][(self.cellnum.get() // pvapp.numCells.get()) % pvapp.numMods.get()].pvcells[self.cellnum.get() % pvapp.numCells.get()].update( **kwargs ) # cellArea, Vbypass updated by module # update PVapplication_tk @@ -248,8 +266,8 @@ def okay(self): def validateWidget(self, *args): # W = Tkinter.W = 'w' is already used, so use W_ instead (d, i, P, s, S, v, V, W_) = args # @UnusedVariable # IGNORE:W0612 - print "OnValidate:", - print("d={}, i={}, P={}, s={}, S={}, v={}, V={}, W={}".format(*args)) + print("OnValidate:", + "d={}, i={}, P={}, s={}, S={}, v={}, V={}, W={}".format(*args)) if W_ == '.advCnfTop.advCnf.rsEntry': valType = FLOATS valTest = lambda val: float(val) # IGNORE:W0108 @@ -304,8 +322,8 @@ def validateWidget(self, *args): def invalidWidget(self, *args): (d, i, P, s, S, v, V, W_) = args # @UnusedVariable # IGNORE:W0612 - print "OnInvalid: ", - print("d={}, i={}, P={}, s={}, S={}, v={}, V={}, W={}".format(*args)) + print("OnInvalid: ", + "d={}, i={}, P={}, s={}, S={}, v={}, V={}, W={}".format(*args)) if W_ == ".advCnfTop.advCnf.rsEntry": errText = 'Invalid series resistance!' elif W_ == ".advCnfTop.advCnf.rshEntry": diff --git a/pvmismatch/pvmismatch_tk/pvapplication_tk.py b/pvmismatch/pvmismatch_tk/pvapplication_tk.py index 3c5f97d..19d0b70 100644 --- a/pvmismatch/pvmismatch_tk/pvapplication_tk.py +++ b/pvmismatch/pvmismatch_tk/pvapplication_tk.py @@ -5,14 +5,14 @@ @author: marko """ from PIL import Image, ImageTk -from Tkconstants import RIGHT, LEFT, BOTH, E, W, HORIZONTAL -from Tkinter import Frame, Label, Button, Toplevel, OptionMenu, Scale, Entry, \ +from tkinter.constants import RIGHT, LEFT, BOTH, E, W, HORIZONTAL +from tkinter import Frame, Label, Button, Toplevel, OptionMenu, Scale, Entry, \ Message, Spinbox, IntVar, StringVar, DoubleVar from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, \ NavigationToolbar2TkAgg from threading import Thread -from tkFont import nametofont -import Queue +from tkinter.font import nametofont +from queue import Queue import json import logging import numpy as np @@ -118,7 +118,7 @@ def new_function(*args, **kwargs): results are fed to the queue. Destroy master and return the original_function's results. """ - queue = Queue.Queue() + queue = Queue() queuefun = setqueue(original_function, queue) thread = Thread(target=queuefun, args=args, kwargs=kwargs) thread.start() diff --git a/pvmismatch/pvmismatch_tk/pvexceptions.py b/pvmismatch/pvmismatch_tk/pvexceptions.py index ffae56a..3c941a2 100644 --- a/pvmismatch/pvmismatch_tk/pvexceptions.py +++ b/pvmismatch/pvmismatch_tk/pvexceptions.py @@ -20,4 +20,4 @@ def __init__(self, argname, argvalue): # IGNORE:W0231 def __str__(self): return ('Invalid value, %s, for argument "%s".' % (self.argvalue, - self.argname)) + self.argname)) diff --git a/pvmismatch/pvmismatch_tk/pvmodule_tk.py b/pvmismatch/pvmismatch_tk/pvmodule_tk.py index e67c167..4d7f05a 100644 --- a/pvmismatch/pvmismatch_tk/pvmodule_tk.py +++ b/pvmismatch/pvmismatch_tk/pvmodule_tk.py @@ -5,8 +5,8 @@ @author: marko """ -from Tkinter import Frame, Label, Button, OptionMenu, IntVar -#from Tkinter import Menu, Entry +from tkinter import Frame, Label, Button, OptionMenu, IntVar +# from tkinter import Menu, Entry MODULE_SIZES = [72, 96, 128] diff --git a/pvmismatch/pvmismatch_tk/pvstring_tk.py b/pvmismatch/pvmismatch_tk/pvstring_tk.py index 1f8d582..738fe47 100644 --- a/pvmismatch/pvmismatch_tk/pvstring_tk.py +++ b/pvmismatch/pvmismatch_tk/pvstring_tk.py @@ -5,9 +5,9 @@ @author: mmikofski """ -from Tkinter import Frame, Label, Button, Toplevel -#from Tkinter import IntVar -#import tkFont +from tkinter import Frame, Label, Button, Toplevel +# from tkinter import IntVar +# import tk.font as tkFont # use absolute imports instead of relative, so modules are portable from pvmismatch.pvmismatch_tk.pvmodule_tk import PVmodule_tk diff --git a/pvmismatch/pvmismatch_tk/pvsystem_tk.py b/pvmismatch/pvmismatch_tk/pvsystem_tk.py index 6d4921d..7f6b53f 100644 --- a/pvmismatch/pvmismatch_tk/pvsystem_tk.py +++ b/pvmismatch/pvmismatch_tk/pvsystem_tk.py @@ -5,7 +5,7 @@ @author: marko """ -from Tkinter import Frame, Label, Button +from tkinter import Frame, Label, Button class PVsystem_tk(Frame): diff --git a/pvmismatch/tests/calc_series_test_iv.dat b/pvmismatch/tests/calc_series_test_iv.dat index 7be9ede..2ab074d 100644 --- a/pvmismatch/tests/calc_series_test_iv.dat +++ b/pvmismatch/tests/calc_series_test_iv.dat @@ -1,2 +1,2 @@ 2.669945233166134102e+01 2.613033010303713155e+01 2.557469250959322693e+01 2.503222004986441007e+01 2.450260079257066792e+01 2.398553019725125068e+01 2.348071093914845164e+01 2.298785273824064745e+01 2.250667219232610350e+01 2.203689261406170630e+01 2.157824387186283133e+01 2.113046223457288164e+01 2.069329021981323180e+01 2.026647644592624076e+01 1.984977548742640252e+01 1.944294773387629860e+01 1.904575925210638232e+01 1.865798165169922740e+01 1.827939195366099412e+01 1.790977246220460728e+01 1.754891063957073527e+01 1.719659898381486585e+01 1.685263490949001763e+01 1.651682063115647736e+01 1.618896304965170074e+01 1.586887364105483300e+01 1.555636834828217019e+01 1.525126747525101578e+01 1.495339558355128418e+01 1.466258139156528628e+01 1.437865767597778088e+01 1.410146117561958334e+01 1.383083249758950473e+01 1.356661602560063784e+01 1.330865983049817913e+01 1.305681558289752431e+01 1.281093846789221047e+01 1.257088710178278745e+01 1.233652345077869228e+01 1.210771275162635519e+01 1.188432343411796666e+01 1.166622704543624067e+01 1.145329817629179381e+01 1.124541438881058397e+01 1.104245614612993975e+01 1.084430674366276648e+01 1.065085224199032155e+01 1.046198140134505472e+01 1.027758561764573564e+01 1.009755886004822045e+01 9.921797609975804733e+00 9.750200801594225197e+00 9.582669763697001741e+00 9.419108162967756215e+00 9.259421948586846085e+00 9.103519298150462902e+00 8.951310564871141295e+00 8.802708226029247740e+00 8.657626832645895831e+00 8.515982960348219777e+00 8.377695161398937884e+00 8.242683917862414944e+00 8.110871595880457363e+00 7.982182401031483465e+00 7.856542334747352641e+00 7.733879151762913295e+00 7.614122318573662618e+00 7.497202972877762051e+00 7.383053883978968557e+00 7.271609414127802040e+00 7.162805480778679623e+00 7.056579519741313256e+00 6.952870449205181380e+00 6.851618634616425396e+00 6.752765854386900912e+00 6.656255266415761263e+00 6.562031375404206557e+00 6.470040000944737635e+00 6.380228246366428380e+00 6.292544468318435946e+00 6.206938247074130999e+00 6.123360357538877530e+00 6.041762740944727206e+00 5.962098477215771908e+00 5.884321757988263180e+00 5.808387860270016745e+00 5.734253120723862729e+00 5.661874910560483087e+00 5.591211611026082551e+00 5.522222589470886511e+00 5.454868175984623591e+00 5.389109640585640015e+00 5.324909170950475890e+00 5.262229850671099385e+00 5.201035638027317276e+00 5.141291345262154699e+00 5.082962618348275896e+00 5.026015917233788599e+00 4.970418496556138876e+00 4.916138386812934691e+00 4.863144375978934342e+00 4.665905457314873495e+00 4.182628064891606101e+00 3.687626587096517916e+00 3.180616603056682923e+00 2.661306791980807773e+00 2.129398765770248669e+00 1.584586897569462582e+00 1.026558146157324991e+00 4.549918760777433846e-01 -1.304403265928240074e-01 -7.300748429472481149e-01 -1.344256214527769444e+00 -1.973337341294657321e+00 -2.617679684397408835e+00 -3.277653473865444589e+00 -3.953637921336954797e+00 -4.646021437948490096e+00 -5.355201857510766494e+00 -6.081586665098067890e+00 -6.825593231183582965e+00 -7.587649051454682159e+00 -8.368191992445758842e+00 -9.167670543130160610e+00 -9.986544072615838985e+00 -1.082528309409206102e+01 -1.168436953518000010e+01 -1.256429701484118056e+01 -1.346557112700434899e+01 -1.438870973107231066e+01 -1.533424324947684880e+01 -1.630271497245186296e+01 -1.729468137020035101e+01 -1.831071241263431659e+01 -1.935139189687142647e+01 -2.041731778267660502e+01 -2.150910253604138234e+01 -2.262737348109812530e+01 -2.377277316057160661e+01 -2.494595970497513804e+01 -2.614760721076295980e+01 -2.737840612765662485e+01 -2.863906365536769982e+01 -2.993030414994466071e+01 -3.125286953997778738e+01 -3.260751975290073545e+01 -3.399503315163427430e+01 -3.541620698182261862e+01 -3.687185782991939220e+01 -3.836282209238692076e+01 -3.988995645627768738e+01 -4.145413839147469304e+01 -4.305626665487333327e+01 -4.469726180679434435e+01 -4.637806673992485429e+01 -4.809964722109126001e+01 -4.986299244617508464e+01 -5.166911560849125351e+01 -5.351905448095446616e+01 -5.541387201236889126e+01 -5.735465693818375144e+01 -5.934252440606522327e+01 -6.137861661664456392e+01 -6.346410347981056077e+01 -6.560018328692328282e+01 -6.778808339933530647e+01 -7.002906095361628047e+01 -7.232440358388598156e+01 -7.467543016167068970e+01 -7.708349155370805761e+01 -7.954997139813623619e+01 -8.207628689951283718e+01 -8.466388964312061205e+01 -8.731426642902799529e+01 -9.002894012638344634e+01 -9.280947054843453259e+01 -9.565745534877466127e+01 -9.857453093933244759e+01 -1.015623734306307853e+02 -1.046226995948563427e+02 -1.077572678522927987e+02 -1.109678792816842758e+02 -1.142563786551096712e+02 -1.176246554979629764e+02 -1.210746451746476282e+02 -1.246083300006099108e+02 -1.282277403813492640e+02 -1.319349559790607316e+02 -1.357321069075796629e+02 -1.396213749563148383e+02 -1.436049948438740955e+02 -1.476852555021023647e+02 -1.518645013912690445e+02 -1.561451338471624979e+02 -1.605296124608632056e+02 -1.650204564919905863e+02 -1.696202463162337892e+02 -1.743316249079991564e+02 -1.791572993590264389e+02 -1.841000424338451182e+02 -1.891626941629658916e+02 -1.943481634747227247e+02 --1.658825367061012912e+01 -1.657850974204069416e+01 -1.656899668359963584e+01 -1.655970902510971499e+01 -1.655042917632658117e+01 -1.654097103762063625e+01 -1.653173699761180515e+01 -1.652261843680760478e+01 -1.651325342581841937e+01 -1.650411030698226966e+01 -1.649492950953737846e+01 -1.648569026559598427e+01 -1.647666993391565526e+01 -1.646786332764578731e+01 -1.645926538283167062e+01 -1.645087115550263235e+01 -1.644267581882917284e+01 -1.643467466034742941e+01 -1.642652678184029469e+01 -1.641821862653110031e+01 -1.641010732250925841e+01 -1.640218820563117674e+01 -1.639445429998721693e+01 -1.638628668885698048e+01 -1.637831259899660452e+01 -1.637052744516306291e+01 -1.636289549842984314e+01 -1.635491221966638875e+01 -1.634711809464927512e+01 -1.633932891258334408e+01 -1.633110801853167260e+01 -1.632308190822163851e+01 -1.631524596649755665e+01 -1.630759568755402711e+01 -1.630012667234505841e+01 -1.629266055741767261e+01 -1.628485564466355484e+01 -1.627723565949759177e+01 -1.626964171658705638e+01 -1.626144520268983484e+01 -1.625344289487716765e+01 -1.624514950831694193e+01 -1.623692815302517545e+01 -1.622890159240355246e+01 -1.622106521103744114e+01 -1.621341450286865538e+01 -1.620441639445639481e+01 -1.619525700108422228e+01 -1.618631462801433685e+01 -1.617758413322372135e+01 -1.616906049652311594e+01 -1.616042503368588967e+01 -1.615094785208763284e+01 -1.614142248096893439e+01 -1.613173770191218637e+01 -1.612157690771130802e+01 -1.611023808780480593e+01 -1.609872687209907127e+01 -1.608748840016694004e+01 -1.607609507978980190e+01 -1.606334268857064274e+01 -1.605089244921732217e+01 -1.603706456414053605e+01 -1.602165250583331613e+01 -1.600529241322813334e+01 -1.598678052725880150e+01 -1.596663147657240955e+01 -1.594435540343845403e+01 -1.591740029220724928e+01 -1.588379603924751393e+01 -1.584104755458223224e+01 -1.577867130305049415e+01 -1.566736970957890662e+01 -1.536092043635840909e+01 -1.455831210324631186e+01 -1.360092413392142596e+01 -1.265185585323075301e+01 -1.172154623852128452e+01 -1.081279591369598592e+01 -1.019796654513543643e+01 -1.012977886666629956e+01 -1.009711297008852604e+01 -1.007184243130435775e+01 -1.004885109160030865e+01 -1.002731209210761243e+01 -1.000530453304772216e+01 -9.981940187750595328e+00 -9.956839671683859194e+00 -9.927353871121455953e+00 -9.892265656201432833e+00 -9.848905920387606372e+00 -9.788337638206783708e+00 -9.693388761463495484e+00 -9.510065199300123950e+00 -9.126274923702730746e+00 -8.580389957406246992e+00 -8.003133374102789688e+00 -7.430670376863545812e+00 -6.868730619617537059e+00 -6.318753350967470261e+00 -5.781535991720929246e+00 -4.196263978427374752e+00 -3.956725586367259684e+00 -9.681888502074271763e-01 1.748625169587196160e+00 1.804165678659417793e+00 1.837420148329907521e+00 1.863698505909859193e+00 1.886412329500557039e+00 1.906931428541684292e+00 1.925945541160445140e+00 1.943896171380533833e+00 1.961069787124253727e+00 1.977647083083672541e+00 1.993775861994055099e+00 2.009571828932967819e+00 2.025117618240481754e+00 2.040479955530687839e+00 2.055729421182836525e+00 2.070895724205689348e+00 2.086029239644477506e+00 2.101135804863898393e+00 2.116272502819317225e+00 2.131472432980459075e+00 2.146778709499642002e+00 2.162273192859198279e+00 2.177980925454079841e+00 2.193933003375795554e+00 2.210137411497759885e+00 2.226577105394924594e+00 2.243298138342863624e+00 2.260307683007822366e+00 2.277611323759699324e+00 2.295212534827342221e+00 2.313141666359838755e+00 2.331406284844972809e+00 2.350002613502004678e+00 2.368955100364965816e+00 2.388280961157951410e+00 2.407987536244760918e+00 2.428072402897706983e+00 2.448566228136398681e+00 2.469479984338478928e+00 2.490815446002351941e+00 2.512587176713643178e+00 2.534815172990771526e+00 2.557512916515305879e+00 2.580682746447858555e+00 2.604342062640564226e+00 2.628509665653279370e+00 2.653198815664808308e+00 2.678418591502695456e+00 2.704180932139538918e+00 2.730507272700479326e+00 2.757411880863014364e+00 2.784910427393878951e+00 2.813034983972834802e+00 2.841810360716647388e+00 2.871256567551667693e+00 2.901389910663110250e+00 2.932227130357230038e+00 2.963785408121344389e+00 2.996082374092789991e+00 3.029133481574262987e+00 3.062959862109677633e+00 3.097581266559303437e+00 3.133017145226553168e+00 3.169287444849655966e+00 3.206412618140574544e+00 3.244413633747178949e+00 3.283311986635701452e+00 3.323129708891178424e+00 3.363889380934250717e+00 3.405614143153397499e+00 3.448327707952343779e+00 3.492054372213049263e+00 3.536817757332599399e+00 3.582643279626384292e+00 3.629558239898170946e+00 3.677589426329106903e+00 3.726764278621995441e+00 3.777108388565715735e+00 3.828651720321440521e+00 3.881425026286948299e+00 3.935455518824635401e+00 3.990775771654498705e+00 4.047416802534871572e+00 4.105410468759623122e+00 4.164789809319351832e+00 4.225589683232351845e+00 4.287842197433228364e+00 4.351584761883257713e+00 4.416853326063013618e+00 4.483684803693658516e+00 4.552117152173255299e+00 4.622189372413656017e+00 4.693941512438208008e+00 4.767414490745045974e+00 4.842649365866655842e+00 4.919690053166894117e+00 4.998579994344287236e+00 5.079363954522465363e+00 +-1.658880064381333241e+01 -1.657905663275937158e+01 -1.656954349378815294e+01 -1.656025575667613836e+01 -1.655097583113375492e+01 -1.654151761748727978e+01 -1.653228350431353988e+01 -1.652326818183378521e+01 -1.651395850188531256e+01 -1.650481525933309257e+01 -1.649588865440981067e+01 -1.648668037345530735e+01 -1.647765983345734497e+01 -1.646885302380567495e+01 -1.646025488042862861e+01 -1.645186045924136309e+01 -1.644366493330289813e+01 -1.643566359004054789e+01 -1.642751553113095042e+01 -1.641920719969369813e+01 -1.641109572371693659e+01 -1.640317643895819089e+01 -1.639544479168835522e+01 -1.638752386363611180e+01 -1.637954951086434008e+01 -1.637176410034876284e+01 -1.636416315534033217e+01 -1.635659667652509341e+01 -1.634880213815632288e+01 -1.634101255253258600e+01 -1.633279126448490004e+01 -1.632476476951409694e+01 -1.631692845224329247e+01 -1.630927780665115279e+01 -1.630180843348085062e+01 -1.629451603771040880e+01 -1.628691241685724478e+01 -1.627929190300544349e+01 -1.627169744393561501e+01 -1.626350042610884472e+01 -1.625549762630660666e+01 -1.624768444277716029e+01 -1.623965755848015746e+01 -1.623163023510905134e+01 -1.622379310906584493e+01 -1.621614167386414707e+01 -1.620761502182235958e+01 -1.619853049534921396e+01 -1.618958709689924547e+01 -1.618085560102363729e+01 -1.617233098695748694e+01 -1.616369456991216680e+01 -1.615421645671456830e+01 -1.614496291548454110e+01 -1.613592862527184479e+01 -1.612653333716714954e+01 -1.611526457678397151e+01 -1.610375141540228583e+01 -1.609251104389453957e+01 -1.608111586894984413e+01 -1.606836166710477443e+01 -1.605590966002603892e+01 -1.604264843906554816e+01 -1.602774342692730869e+01 -1.601189070025567673e+01 -1.599408829748028182e+01 -1.597411181790824131e+01 -1.595183234651220161e+01 -1.592566251522248066e+01 -1.589272991840343074e+01 -1.584997643244849819e+01 -1.578759529812637652e+01 -1.567628893755597730e+01 -1.537148645933553226e+01 -1.457036987162097930e+01 -1.361371822841036661e+01 -1.266464113629502997e+01 -1.173607042261158107e+01 -1.082813292426842899e+01 -1.021329016862959804e+01 -1.014695233727355372e+01 -1.011630145616454257e+01 -1.009282902176224717e+01 -1.007329045367355747e+01 -1.005380530007725071e+01 -1.003490711576330696e+01 -1.001535182432750126e+01 -9.995596506512718804e+00 -9.973408505204028884e+00 -9.949379690242997398e+00 -9.921931786004670073e+00 -9.888624787337647604e+00 -9.846235512592620864e+00 -9.787094512027117332e+00 -9.693351201767208991e+00 -9.503221407468549486e+00 -9.042165483100029988e+00 -8.341614486291527797e+00 -7.604747131833715201e+00 -6.877249661638065170e+00 -6.165161454562002596e+00 -4.213515924858922901e+00 -4.045984936050838421e+00 -2.682831670549268743e+00 1.752101950250986473e+00 1.805427377069297457e+00 1.838183827599904951e+00 1.864281546019037616e+00 1.886867933130828678e+00 1.907300725487146353e+00 1.926259439321199807e+00 1.944167845514729098e+00 1.961309166599608300e+00 1.977862636135153451e+00 1.993969343960166896e+00 2.009747233608532024e+00 2.025278839712518320e+00 2.040627209040307477e+00 2.055865216829772191e+00 2.071022983942128359e+00 2.086147061486247622e+00 2.101246522967571195e+00 2.116375849358925976e+00 2.131570243623182925e+00 2.146873362997017143e+00 2.162365928001829918e+00 2.178072948870811043e+00 2.194023443293668496e+00 2.210227285556026544e+00 2.226665670780302975e+00 2.243385553159214840e+00 2.260394722593984440e+00 2.277697413595277887e+00 2.295297791306158519e+00 2.313226281250316152e+00 2.331490626087862505e+00 2.350086359305545436e+00 2.369038329310286795e+00 2.388363743963196395e+00 2.408069936783067355e+00 2.428154479069803084e+00 2.448648032620847736e+00 2.469561319745206873e+00 2.490896620777932391e+00 2.512668229624717142e+00 2.534895953749347619e+00 2.557593492019480053e+00 2.580763324040451501e+00 2.604422531031258981e+00 2.628589953904426402e+00 2.653279098845533035e+00 2.678498813570719062e+00 2.704261148181663188e+00 2.730587530878102243e+00 2.757492161858335233e+00 2.784990837903119409e+00 2.813115760839558277e+00 2.841891512828516486e+00 2.871338104011955661e+00 2.901471840795930568e+00 2.932309463712897468e+00 2.963868154481856365e+00 2.996165543477453674e+00 3.029217084245447555e+00 3.063043908578713559e+00 3.097665767592520325e+00 3.133102111851466809e+00 3.169372888361305485e+00 3.206498550108011436e+00 3.244500066020112428e+00 3.283398931351312555e+00 3.323217178481088219e+00 3.363977388131666135e+00 3.405702701000427268e+00 3.448416829807492423e+00 3.492144071758890966e+00 3.536908048583643271e+00 3.582734176937124815e+00 3.629649757971334267e+00 3.677681580224101410e+00 3.726857083763564837e+00 3.777201860752798623e+00 3.828745875736252469e+00 3.881519881504276626e+00 3.935551090821364451e+00 3.990872077819363817e+00 4.047513860678452424e+00 4.105508297124574213e+00 4.164888426590885651e+00 4.225689108548976058e+00 4.287942450397743244e+00 4.351685862574017349e+00 4.416955295045461583e+00 4.483787662032150401e+00 4.552220921443154822e+00 4.622294074713737544e+00 4.694047170403350400e+00 4.767521127559239957e+00 4.842757005276326687e+00 4.919798719494540507e+00 4.998689712502466520e+00 5.079474750028095897e+00 diff --git a/pvmismatch/tests/test_setsuns.py b/pvmismatch/tests/test_setsuns.py index 3dd877f..5d749de 100644 --- a/pvmismatch/tests/test_setsuns.py +++ b/pvmismatch/tests/test_setsuns.py @@ -16,28 +16,28 @@ def test_basic(): pvsys = PVsystem() pvsys.setSuns(.75) - ok_(np.isclose(pvsys.Pmp, 23901.66450809984)) + ok_(np.isclose(pvsys.Pmp, 23975.249137290117)) def test_dictionary(): pvsys = PVsystem() Ee = {1: {3: {'cells': np.arange(30), 'Ee': [.25] * 30}}} pvsys.setSuns(Ee) - ok_(np.isclose(pvsys.Pmp, 31610.641289630337)) + ok_(np.isclose(pvsys.Pmp, 31612.243752486283)) def test_set_mod_1(): pvsys = PVsystem() Ee = {1: {3: [.2], 0: [.1]}} pvsys.setSuns(Ee) - ok_(np.isclose(pvsys.Pmp, 29555.687509091586)) + ok_(np.isclose(pvsys.Pmp, 29573.207099602125)) def test_set_mod_2(): pvsys = PVsystem() Ee = {1: {3: .2, 0: .1}} pvsys.setSuns(Ee) - ok_(np.isclose(pvsys.Pmp, 29555.687509091586)) + ok_(np.isclose(pvsys.Pmp, 29573.207099602125)) # 1001 points linear: [ 29579.12191565] @@ -45,7 +45,7 @@ def test_set_str_1(): pvsys = PVsystem() Ee = {1: [.1]} pvsys.setSuns(Ee) - ok_(np.isclose(pvsys.Pmp, 29131.92967897601)) + ok_(np.isclose(pvsys.Pmp, 29159.47988039567)) # 1001 points linear: [ 29141.73034719] @@ -53,7 +53,7 @@ def test_set_str_2(): pvsys = PVsystem() Ee = {1: .1} pvsys.setSuns(Ee) - ok_(np.isclose(pvsys.Pmp, 29131.92967897601)) + ok_(np.isclose(pvsys.Pmp, 29159.47988039567)) # 1001 points linear: [ 29141.73034719]