diff --git a/ci/requirements-py35.yml b/ci/requirements-py35.yml index 65b5c76d00..5fc0077991 100644 --- a/ci/requirements-py35.yml +++ b/ci/requirements-py35.yml @@ -24,4 +24,5 @@ dependencies: - shapely # pvfactors dependency - siphon # conda-forge - pip: + - nrel-pysam - pvfactors==1.0.1 diff --git a/ci/requirements-py36.yml b/ci/requirements-py36.yml index a21bce2579..e415f67c7d 100644 --- a/ci/requirements-py36.yml +++ b/ci/requirements-py36.yml @@ -24,4 +24,5 @@ dependencies: - shapely # pvfactors dependency - siphon # conda-forge - pip: + - nrel-pysam - pvfactors==1.0.1 diff --git a/ci/requirements-py37.yml b/ci/requirements-py37.yml index 3783e8f772..1a6809fba6 100644 --- a/ci/requirements-py37.yml +++ b/ci/requirements-py37.yml @@ -24,4 +24,5 @@ dependencies: - shapely # pvfactors dependency - siphon # conda-forge - pip: + - nrel-pysam - pvfactors==1.0.1 diff --git a/docs/sphinx/source/api.rst b/docs/sphinx/source/api.rst index 8af2bf0f40..6e93dc5807 100644 --- a/docs/sphinx/source/api.rst +++ b/docs/sphinx/source/api.rst @@ -294,6 +294,14 @@ PVWatts model pvsystem.pvwatts_losses pvsystem.pvwatts_losses +Functions for fitting PV models +------------------------------- +.. autosummary:: + :toctree: generated/ + + ivtools.fit_sde_sandia + ivtools.fit_sdm_cec_sam + Other ----- diff --git a/docs/sphinx/source/whatsnew/v0.7.0.rst b/docs/sphinx/source/whatsnew/v0.7.0.rst index d9045a5cfb..9405eac906 100644 --- a/docs/sphinx/source/whatsnew/v0.7.0.rst +++ b/docs/sphinx/source/whatsnew/v0.7.0.rst @@ -104,6 +104,26 @@ Documentation ~~~~~~~~~~~~~ * Corrected docstring for `pvsystem.PVSystem.sapm` +API Changes +~~~~~~~~~~~ + + +Enhancements +~~~~~~~~~~~~ +* Add `ivtools` module to contain functions for IV model fitting. +* Add :py:func:`~pvlib.ivtools.fit_sde_sandia`, a simple method to fit + the single diode equation to an IV curve. +* Add :py:func:`~pvlib.ivtools.fit_sdm_cec_sam`, a wrapper for the CEC single + diode model fitting function '6parsolve' from NREL's System Advisor Model. + + +Bug fixes +~~~~~~~~~ + + +Testing +~~~~~~~ + Removal of prior version deprecations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Removed `irradiance.extraradiation`. @@ -119,6 +139,7 @@ Contributors ~~~~~~~~~~~~ * Mark Campanellli (:ghuser:`markcampanelli`) * Will Holmgren (:ghuser:`wholmgren`) +* Cliff Hansen (:ghuser:`cwhanse`) * Oscar Dowson (:ghuser:`odow`) * Anton Driesse (:ghuser:`adriesse`) * Alexander Morgan (:ghuser:`alexandermorgan`) diff --git a/pvlib/__init__.py b/pvlib/__init__.py index a1fb92eadd..f4e3de4146 100644 --- a/pvlib/__init__.py +++ b/pvlib/__init__.py @@ -7,6 +7,7 @@ from pvlib import location from pvlib import solarposition from pvlib import iotools +from pvlib import ivtools from pvlib import tracking from pvlib import pvsystem from pvlib import spa diff --git a/pvlib/ivtools.py b/pvlib/ivtools.py new file mode 100644 index 0000000000..353a0b8a9a --- /dev/null +++ b/pvlib/ivtools.py @@ -0,0 +1,350 @@ +# -*- coding: utf-8 -*- +""" +Created on Fri Mar 29 10:34:10 2019 + +@author: cwhanse +""" + +import numpy as np + + +def fit_sdm_cec_sam(celltype, v_mp, i_mp, v_oc, i_sc, alpha_sc, beta_voc, + gamma_pmp, cells_in_series, temp_ref=25): + """ + Estimates parameters for the CEC single diode model (SDM) using the SAM + SDK. + + Parameters + ---------- + celltype : str + Value is one of 'monoSi', 'multiSi', 'polySi', 'cis', 'cigs', 'cdte', + 'amorphous' + v_mp : float + Voltage at maximum power point [V] + i_mp : float + Current at maximum power point [A] + v_oc : float + Open circuit voltage [V] + i_sc : float + Short circuit current [A] + alpha_sc : float + Temperature coefficient of short circuit current [A/C] + beta_voc : float + Temperature coefficient of open circuit voltage [V/C] + gamma_pmp : float + Temperature coefficient of power at maximum point point [%/C] + cells_in_series : int + Number of cells in series + temp_ref : float, default 25 + Reference temperature condition [C] + + Returns + ------- + tuple of the following elements: + + * I_L_ref : float + The light-generated current (or photocurrent) at reference + conditions [A] + + * I_o_ref : float + The dark or diode reverse saturation current at reference + conditions [A] + + * R_sh_ref : float + The shunt resistance at reference conditions, in ohms. + + * R_s : float + The series resistance at reference conditions, in ohms. + + * a_ref : float + The product of the usual diode ideality factor ``n`` (unitless), + number of cells in series ``Ns``, and cell thermal voltage at + reference conditions [V] + + * Adjust : float + The adjustment to the temperature coefficient for short circuit + current, in percent. + + Raises + ------ + ImportError if NREL-PySAM is not installed. + + RuntimeError if parameter extraction is not successful. + + Notes + ----- + Inputs ``v_mp``, ``v_oc``, ``i_mp`` and ``i_sc`` are assumed to be from a + single IV curve at constant irradiance and cell temperature. Irradiance is + not explicitly used by the fitting procedure. The irradiance level at which + the input IV curve is determined and the specified cell temperature + ``temp_ref`` are the reference conditions for the output parameters + ``I_L_ref``, ``I_o_ref``, ``R_sh_ref``, ``R_s``, ``a_ref`` and ``Adjust``. + + References + ---------- + [1] A. Dobos, "An Improved Coefficient Calculator for the California + Energy Commission 6 Parameter Photovoltaic Module Model", Journal of + Solar Energy Engineering, vol 134, 2012. + """ + + try: + from PySAM import PySSC + except ImportError: + raise ImportError("Requires NREL's PySAM package at " + "https://pypi.org/project/NREL-PySAM/.") + + datadict = {'tech_model': '6parsolve', 'financial_model': 'none', + 'celltype': celltype, 'Vmp': v_mp, + 'Imp': i_mp, 'Voc': v_oc, 'Isc': i_sc, 'alpha_isc': alpha_sc, + 'beta_voc': beta_voc, 'gamma_pmp': gamma_pmp, + 'Nser': cells_in_series, 'Tref': temp_ref} + + result = PySSC.ssc_sim_from_dict(datadict) + if result['cmod_success'] == 1: + return tuple([result[k] for k in ['Il', 'Io', 'Rsh', 'Rs', 'a', + 'Adj']]) + else: + raise RuntimeError('Parameter estimation failed') + + +def fit_sde_sandia(voltage, current, v_oc=None, i_sc=None, v_mp_i_mp=None, + vlim=0.2, ilim=0.1): + r""" + Fits the single diode equation (SDE) to an IV curve. + + Parameters + ---------- + voltage : ndarray + 1D array of `float` type containing voltage at each point on the IV + curve, increasing from 0 to ``v_oc`` inclusive [V] + + current : ndarray + 1D array of `float` type containing current at each point on the IV + curve, from ``i_sc`` to 0 inclusive [A] + + v_oc : float, default None + Open circuit voltage [V]. If not provided, ``v_oc`` is taken as the + last point in the ``voltage`` array. + + i_sc : float, default None + Short circuit current [A]. If not provided, ``i_sc`` is taken as the + first point in the ``current`` array. + + v_mp_i_mp : tuple of float, default None + Voltage, current at maximum power point in units of [V], [A]. + If not provided, the maximum power point is found at the maximum of + ``voltage`` \times ``current``. + + vlim : float, default 0.2 + Defines portion of IV curve where the exponential term in the single + diode equation can be neglected, i.e. + ``voltage`` <= ``vlim`` x ``v_oc`` [V] + + ilim : float, default 0.1 + Defines portion of the IV curve where the exponential term in the + single diode equation is signficant, approximately defined by + ``current`` < (1 - ``ilim``) x ``i_sc`` [A] + + Returns + ------- + tuple of the following elements: + + * photocurrent : float + photocurrent [A] + * saturation_current : float + dark (saturation) current [A] + * resistance_shunt : float + shunt (parallel) resistance, in ohms + * resistance_series : float + series resistance, in ohms + * nNsVth : float + product of thermal voltage ``Vth`` [V], diode ideality factor + ``n``, and number of series cells ``Ns`` + + Raises + ------ + RuntimeError if parameter extraction is not successful. + + Notes + ----- + Inputs ``voltage``, ``current``, ``v_oc``, ``i_sc`` and ``v_mp_i_mp`` are + assumed to be from a single IV curve at constant irradiance and cell + temperature. + + :py:func:`fit_single_diode_sandia` obtains values for the five parameters + for the single diode equation [1]: + + .. math:: + + I = I_{L} - I_{0} (\exp \frac{V + I R_{s}}{nNsVth} - 1) + - \frac{V + I R_{s}}{R_{sh}} + + See :py:func:`pvsystem.singlediode` for definition of the parameters. + + The extraction method [2] proceeds in six steps. + + 1. In the single diode equation, replace :math:`R_{sh} = 1/G_{p}` and + re-arrange + + .. math:: + + I = \frac{I_{L}}{1 + G_{p} R_{s}} - \frac{G_{p} V}{1 + G_{p} R_{s}} + - \frac{I_{0}}{1 + G_{p} R_{s}} (\exp(\frac{V + I R_{s}}{nNsVth}) - 1) + + 2. The linear portion of the IV curve is defined as + :math:`V \le vlim \times v_oc`. Over this portion of the IV curve, + + .. math:: + + \frac{I_{0}}{1 + G_{p} R_{s}} (\exp(\frac{V + I R_{s}}{nNsVth}) - 1) + \approx 0 + + 3. Fit the linear portion of the IV curve with a line. + + .. math:: + + I &\approx \frac{I_{L}}{1 + G_{p} R_{s}} - \frac{G_{p} V}{1 + G_{p} + R_{s}} \\ + &= \beta_{0} + \beta_{1} V + + 4. The exponential portion of the IV curve is defined by + :math:`\beta_{0} + \beta_{1} \times V - I > ilim \times i_sc`. + Over this portion of the curve, :math:`exp((V + IRs)/nNsVth) >> 1` + so that + + .. math:: + + \exp(\frac{V + I R_{s}}{nNsVth}) - 1 \approx + \exp(\frac{V + I R_{s}}{nNsVth}) + + 5. Fit the exponential portion of the IV curve. + + .. math:: + + \log(\beta_{0} - \beta_{1} V - I) + &\approx \log(\frac{I_{0}}{1 + G_{p} R_{s}} + \frac{V}{nNsVth} + + \frac{I R_{s}}{nNsVth} \\ + &= \beta_{2} + beta_{3} V + \beta_{4} I + + 6. Calculate values for ``IL, I0, Rs, Rsh,`` and ``nNsVth`` from the + regression coefficents :math:`\beta_{0}, \beta_{1}, \beta_{3}` and + :math:`\beta_{4}`. + + + References + ---------- + [1] S.R. Wenham, M.A. Green, M.E. Watt, "Applied Photovoltaics" ISBN + 0 86758 909 4 + [2] C. B. Jones, C. W. Hansen, Single Diode Parameter Extraction from + In-Field Photovoltaic I-V Curves on a Single Board Computer, 46th IEEE + Photovoltaic Specialist Conference, Chicago, IL, 2019 + """ + + # If not provided, extract v_oc, i_sc, v_mp and i_mp from the IV curve data + if v_oc is None: + v_oc = voltage[-1] + if i_sc is None: + i_sc = current[0] + if v_mp_i_mp is not None: + v_mp, i_mp = v_mp_i_mp + else: + v_mp, i_mp = _find_mp(voltage, current) + + # Find beta0 and beta1 from linear portion of the IV curve + beta0, beta1 = _find_beta0_beta1(voltage, current, vlim, v_oc) + + # Find beta3 and beta4 from the exponential portion of the IV curve + beta3, beta4 = _find_beta3_beta4(voltage, current, beta0, beta1, ilim, + i_sc) + + # calculate single diode parameters from regression coefficients + return _calculate_sde_parameters(beta0, beta1, beta3, beta4, v_mp, i_mp, + v_oc) + + +def _find_mp(voltage, current): + """ + Finds voltage and current at maximum power point. + + Parameters + ---------- + voltage : ndarray + 1D array containing voltage at each point on the IV curve, increasing + from 0 to v_oc inclusive, of `float` type [V] + + current : ndarray + 1D array containing current at each point on the IV curve, decreasing + from i_sc to 0 inclusive, of `float` type [A] + + Returns + ------- + v_mp, i_mp : tuple + voltage ``v_mp`` and current ``i_mp`` at the maximum power point [V], + [A] + """ + p = voltage * current + idx = np.argmax(p) + return voltage[idx], current[idx] + + +def _calc_I0(IL, I, V, Gp, Rs, nNsVth): + return (IL - I - Gp * V - Gp * Rs * I) / np.exp((V + Rs * I) / nNsVth) + + +def _find_beta0_beta1(v, i, vlim, v_oc): + # Get intercept and slope of linear portion of IV curve. + # Start with V =< vlim * v_oc, extend by adding points until slope is + # negative (downward). + beta0 = np.nan + beta1 = np.nan + first_idx = np.searchsorted(v, vlim * v_oc) + for idx in range(first_idx, len(v)): + coef = np.polyfit(v[:idx], i[:idx], deg=1) + if coef[0] < 0: + # intercept term + beta0 = coef[1].item() + # sign change of slope to get positive parameter value + beta1 = -coef[0].item() + break + if any(np.isnan([beta0, beta1])): + raise RuntimeError("Parameter extraction failed: beta0={}, beta1={}" + .format(beta0, beta1)) + else: + return beta0, beta1 + + +def _find_beta3_beta4(voltage, current, beta0, beta1, ilim, i_sc): + # Subtract the IV curve from the linear fit. + y = beta0 - beta1 * voltage - current + x = np.array([np.ones_like(voltage), voltage, current]).T + # Select points where y > ilim * i_sc to regress log(y) onto x + idx = (y > ilim * i_sc) + result = np.linalg.lstsq(x[idx], np.log(y[idx]), rcond=None) + coef = result[0] + beta3 = coef[1].item() + beta4 = coef[2].item() + if any(np.isnan([beta3, beta4])): + raise RuntimeError("Parameter extraction failed: beta3={}, beta4={}" + .format(beta3, beta4)) + else: + return beta3, beta4 + + +def _calculate_sde_parameters(beta0, beta1, beta3, beta4, v_mp, i_mp, v_oc): + nNsVth = 1.0 / beta3 + Rs = beta4 / beta3 + Gp = beta1 / (1.0 - Rs * beta1) + Rsh = 1.0 / Gp + IL = (1 + Gp * Rs) * beta0 + # calculate I0 + I0_vmp = _calc_I0(IL, i_mp, v_mp, Gp, Rs, nNsVth) + I0_voc = _calc_I0(IL, 0, v_oc, Gp, Rs, nNsVth) + if any(np.isnan([I0_vmp, I0_voc])) or ((I0_vmp <= 0) and (I0_voc <= 0)): + raise RuntimeError("Parameter extraction failed: I0 is undetermined.") + elif (I0_vmp > 0) and (I0_voc > 0): + I0 = 0.5 * (I0_vmp + I0_voc) + elif (I0_vmp > 0): + I0 = I0_vmp + else: # I0_voc > 0 + I0 = I0_voc + return (IL, I0, Rsh, Rs, nNsVth) diff --git a/pvlib/test/conftest.py b/pvlib/test/conftest.py index 1c690c2555..8789bf99f4 100644 --- a/pvlib/test/conftest.py +++ b/pvlib/test/conftest.py @@ -151,6 +151,15 @@ def has_numba(): reason='requires pvfactors') +try: + import PySAM # noqa: F401 + has_pysam = True +except ImportError: + has_pysam = False + +requires_pysam = pytest.mark.skipif(not has_pysam, reason="requires PySAM") + + @pytest.fixture(scope="session") def sam_data(): data = {} diff --git a/pvlib/test/test_ivtools.py b/pvlib/test/test_ivtools.py new file mode 100644 index 0000000000..d4aca050c4 --- /dev/null +++ b/pvlib/test/test_ivtools.py @@ -0,0 +1,242 @@ +# -*- coding: utf-8 -*- +""" +Created on Thu May 9 10:51:15 2019 + +@author: cwhanse +""" + +import numpy as np +import pandas as pd +import pytest +from pvlib import pvsystem +from pvlib import ivtools +from pvlib.test.conftest import requires_scipy, requires_pysam + + +@pytest.fixture +def get_test_iv_params(): + return {'IL': 8.0, 'I0': 5e-10, 'Rsh': 1000, 'Rs': 0.2, 'nNsVth': 1.61864} + + +@pytest.fixture +def get_cec_params_cansol_cs5p_220p(): + return {'input': {'V_mp_ref': 46.6, 'I_mp_ref': 4.73, 'V_oc_ref': 58.3, + 'I_sc_ref': 5.05, 'alpha_sc': 0.0025, + 'beta_voc': -0.19659, 'gamma_pmp': -0.43, + 'cells_in_series': 96}, + 'output': {'a_ref': 2.3674, 'I_L_ref': 5.056, 'I_o_ref': 1.01e-10, + 'R_sh_ref': 837.51, 'R_s': 1.004, 'Adjust': 2.3}} + + +@requires_scipy +def test_fit_sde_sandia(get_test_iv_params, get_bad_iv_curves): + test_params = get_test_iv_params + testcurve = pvsystem.singlediode(photocurrent=test_params['IL'], + saturation_current=test_params['I0'], + resistance_shunt=test_params['Rsh'], + resistance_series=test_params['Rs'], + nNsVth=test_params['nNsVth'], + ivcurve_pnts=300) + expected = tuple(test_params[k] for k in ['IL', 'I0', 'Rsh', 'Rs', + 'nNsVth']) + result = ivtools.fit_sde_sandia(voltage=testcurve['v'], + current=testcurve['i']) + assert np.allclose(result, expected, rtol=5e-5) + result = ivtools.fit_sde_sandia(voltage=testcurve['v'], + current=testcurve['i'], + v_oc=testcurve['v_oc'], + i_sc=testcurve['i_sc']) + assert np.allclose(result, expected, rtol=5e-5) + result = ivtools.fit_sde_sandia(voltage=testcurve['v'], + current=testcurve['i'], + v_oc=testcurve['v_oc'], + i_sc=testcurve['i_sc'], + v_mp_i_mp=(testcurve['v_mp'], + testcurve['i_mp'])) + assert np.allclose(result, expected, rtol=5e-5) + result = ivtools.fit_sde_sandia(voltage=testcurve['v'], + current=testcurve['i'], vlim=0.1) + assert np.allclose(result, expected, rtol=5e-5) + + +@requires_scipy +def test_fit_sde_sandia_bad_iv(get_bad_iv_curves): + # bad IV curves for coverage of if/then in _calculate_sde_parameters + v1, i1, v2, i2 = get_bad_iv_curves + result = ivtools.fit_sde_sandia(voltage=v1, current=i1) + assert np.allclose(result, (-2.4322856072799985, 8.854688976836396, + -63.56227601452038, 111.18558915546389, + -137.9965046659527)) + result = ivtools.fit_sde_sandia(voltage=v2, current=i2) + assert np.allclose(result, (2.62405311949227, 1.8657963912925288, + 110.35202827739991, -65.652554411442, + 174.49362093001415)) + + +@requires_pysam +def test_fit_sdm_cec_sam(get_cec_params_cansol_cs5p_220p): + input_data = get_cec_params_cansol_cs5p_220p['input'] + I_L_ref, I_o_ref, R_sh_ref, R_s, a_ref, Adjust = \ + ivtools.fit_sdm_cec_sam( + celltype='polySi', v_mp=input_data['V_mp_ref'], + i_mp=input_data['I_mp_ref'], v_oc=input_data['V_oc_ref'], + i_sc=input_data['I_sc_ref'], alpha_sc=input_data['alpha_sc'], + beta_voc=input_data['beta_voc'], + gamma_pmp=input_data['gamma_pmp'], + cells_in_series=input_data['cells_in_series']) + expected = pd.Series(get_cec_params_cansol_cs5p_220p['output']) + modeled = pd.Series(index=expected.index, data=np.nan) + modeled['a_ref'] = a_ref + modeled['I_L_ref'] = I_L_ref + modeled['I_o_ref'] = I_o_ref + modeled['R_sh_ref'] = R_sh_ref + modeled['R_s'] = R_s + modeled['Adjust'] = Adjust + assert np.allclose(modeled.values, expected.values, rtol=5e-2) + # test for fitting failure + with pytest.raises(RuntimeError): + I_L_ref, I_o_ref, R_sh_ref, R_s, a_ref, Adjust = \ + ivtools.fit_sdm_cec_sam( + celltype='polySi', v_mp=0.45, i_mp=5.25, v_oc=0.55, i_sc=5.5, + alpha_sc=0.00275, beta_voc=0.00275, gamma_pmp=0.0055, + cells_in_series=1, temp_ref=25) + + +@pytest.fixture +def get_bad_iv_curves(): + # v1, i1 produces a bad value for I0_voc + v1 = np.array([0, 0.338798867469060, 0.677597734938121, 1.01639660240718, + 1.35519546987624, 1.69399433734530, 2.03279320481436, + 2.37159207228342, 2.71039093975248, 3.04918980722154, + 3.38798867469060, 3.72678754215966, 4.06558640962873, + 4.40438527709779, 4.74318414456685, 5.08198301203591, + 5.42078187950497, 5.75958074697403, 6.09837961444309, + 6.43717848191215, 6.77597734938121, 7.11477621685027, + 7.45357508431933, 7.79237395178839, 8.13117281925745, + 8.46997168672651, 8.80877055419557, 9.14756942166463, + 9.48636828913369, 9.82516715660275, 10.1639660240718, + 10.5027648915409, 10.8415637590099, 11.1803626264790, + 11.5191614939481, 11.8579603614171, 12.1967592288862, + 12.5355580963552, 12.8743569638243, 13.2131558312934, + 13.5519546987624, 13.8907535662315, 14.2295524337005, + 14.5683513011696, 14.9071501686387, 15.2459490361077, + 15.5847479035768, 15.9235467710458, 16.2623456385149, + 16.6011445059840, 16.9399433734530, 17.2787422409221, + 17.6175411083911, 17.9563399758602, 18.2951388433293, + 18.6339377107983, 18.9727365782674, 19.3115354457364, + 19.6503343132055, 19.9891331806746, 20.3279320481436, + 20.6667309156127, 21.0055297830817, 21.3443286505508, + 21.6831275180199, 22.0219263854889, 22.3607252529580, + 22.6995241204270, 23.0383229878961, 23.3771218553652, + 23.7159207228342, 24.0547195903033, 24.3935184577724, + 24.7323173252414, 25.0711161927105, 25.4099150601795, + 25.7487139276486, 26.0875127951177, 26.4263116625867, + 26.7651105300558, 27.1039093975248, 27.4427082649939, + 27.7815071324630, 28.1203059999320, 28.4591048674011, + 28.7979037348701, 29.1367026023392, 29.4755014698083, + 29.8143003372773, 30.1530992047464, 30.4918980722154, + 30.8306969396845, 31.1694958071536, 31.5082946746226, + 31.8470935420917, 32.1858924095607, 32.5246912770298, + 32.8634901444989, 33.2022890119679, 33.5410878794370]) + i1 = np.array([3.39430882774470, 2.80864492110761, 3.28358165429196, + 3.41191190551673, 3.11975662808148, 3.35436585834612, + 3.23953272899809, 3.60307083325333, 2.80478101508277, + 2.80505102853845, 3.16918996870373, 3.21088388439857, + 3.46332865310431, 3.09224155015883, 3.17541550741062, + 3.32470179290389, 3.33224664316240, 3.07709000050741, + 2.89141245343405, 3.01365768561537, 3.23265176770231, + 3.32253647634228, 2.97900657569736, 3.31959549243966, + 3.03375461550111, 2.97579298978937, 3.25432831375159, + 2.89178382564454, 3.00341909207567, 3.72637492250097, + 3.28379856976360, 2.96516169245835, 3.25658381110230, + 3.41655911533139, 3.02718097944604, 3.11458376760376, + 3.24617304369762, 3.45935502367636, 3.21557333256913, + 3.27611176482650, 2.86954135732485, 3.32416319254657, + 3.15277467598732, 3.08272557013770, 3.15602202666259, + 3.49432799877150, 3.53863997177632, 3.10602611478455, + 3.05373911151821, 3.09876772570781, 2.97417228624287, + 2.84573593699237, 3.16288578405195, 3.06533173612783, + 3.02118336639575, 3.34374977225502, 2.97255164138821, + 3.19286135682863, 3.10999753817133, 3.26925354620079, + 3.11957809501529, 3.20155017481720, 3.31724984405837, + 3.42879043512927, 3.17933067619240, 3.47777362613969, + 3.20708912539777, 3.48205761174907, 3.16804363684327, + 3.14055472378230, 3.13445657434470, 2.91152696252998, + 3.10984113847427, 2.80443349399489, 3.23146278164875, + 2.94521083406108, 3.17388903141715, 3.05930294897030, + 3.18985234673287, 3.27946609274898, 3.33717523113602, + 2.76394303462702, 3.19375132937510, 2.82628616689450, + 2.85238527394143, 2.82975892599489, 2.79196912313914, + 2.72860792049395, 2.75585977414140, 2.44280222448805, + 2.36052347370628, 2.26785071765738, 2.10868255743462, + 2.06165739407987, 1.90047259509385, 1.39925575828709, + 1.24749015957606, 0.867823806536762, 0.432752457749993, 0]) + # v2, i2 produces a bad value for I0_vmp + v2 = np.array([0, 0.365686097622586, 0.731372195245173, 1.09705829286776, + 1.46274439049035, 1.82843048811293, 2.19411658573552, + 2.55980268335810, 2.92548878098069, 3.29117487860328, + 3.65686097622586, 4.02254707384845, 4.38823317147104, + 4.75391926909362, 5.11960536671621, 5.48529146433880, + 5.85097756196138, 6.21666365958397, 6.58234975720655, + 6.94803585482914, 7.31372195245173, 7.67940805007431, + 8.04509414769690, 8.41078024531949, 8.77646634294207, + 9.14215244056466, 9.50783853818725, 9.87352463580983, + 10.2392107334324, 10.6048968310550, 10.9705829286776, + 11.3362690263002, 11.7019551239228, 12.0676412215454, + 12.4333273191679, 12.7990134167905, 13.1646995144131, + 13.5303856120357, 13.8960717096583, 14.2617578072809, + 14.6274439049035, 14.9931300025260, 15.3588161001486, + 15.7245021977712, 16.0901882953938, 16.4558743930164, + 16.8215604906390, 17.1872465882616, 17.5529326858841, + 17.9186187835067, 18.2843048811293, 18.6499909787519, + 19.0156770763745, 19.3813631739971, 19.7470492716197, + 20.1127353692422, 20.4784214668648, 20.8441075644874, + 21.2097936621100, 21.5754797597326, 21.9411658573552, + 22.3068519549778, 22.6725380526004, 23.0382241502229, + 23.4039102478455, 23.7695963454681, 24.1352824430907, + 24.5009685407133, 24.8666546383359, 25.2323407359585, + 25.5980268335810, 25.9637129312036, 26.3293990288262, + 26.6950851264488, 27.0607712240714, 27.4264573216940, + 27.7921434193166, 28.1578295169392, 28.5235156145617, + 28.8892017121843, 29.2548878098069, 29.6205739074295, + 29.9862600050521, 30.3519461026747, 30.7176322002973, + 31.0833182979198, 31.4490043955424, 31.8146904931650, + 32.1803765907876, 32.5460626884102, 32.9117487860328, + 33.2774348836554, 33.6431209812779, 34.0088070789005, + 34.3744931765231, 34.7401792741457, 35.1058653717683, + 35.4715514693909, 35.8372375670135, 36.2029236646360]) + i2 = np.array([6.49218806928330, 6.49139336899548, 6.17810697175204, + 6.75197816263663, 6.59529074137515, 6.18164578868300, + 6.38709397931910, 6.30685422248427, 6.44640615548925, + 6.88727230397772, 6.42074852785591, 6.46348580823746, + 6.38642309763941, 5.66356277572311, 6.61010381702082, + 6.33288284311125, 6.22475343933610, 6.30651399433833, + 6.44435022944051, 6.43741711131908, 6.03536180208946, + 6.23814639328170, 5.97229140403242, 6.20790000748341, + 6.22933550182341, 6.22992127804882, 6.13400871899299, + 6.83491312449950, 6.07952797245846, 6.35837746415450, + 6.41972128662324, 6.85256717258275, 6.25807797296759, + 6.25124948151766, 6.22229212812413, 6.72249444167406, + 6.41085549981649, 6.75792874870056, 6.22096181559171, + 6.47839564388996, 6.56010208597432, 6.63300966556949, + 6.34617546039339, 6.79812221146153, 6.14486056194136, + 6.14979256889311, 6.16883037644880, 6.57309183229605, + 6.40064681038509, 6.18861448239873, 6.91340138179698, + 5.94164388433788, 6.23638991745862, 6.31898940411710, + 6.45247884556830, 6.58081455524297, 6.64915284801713, + 6.07122119270245, 6.41398258148256, 6.62144271089614, + 6.36377197712687, 6.51487678829345, 6.53418950147730, + 6.18886469125371, 6.26341063475750, 6.83488211680259, + 6.62699397226695, 6.41286837534735, 6.44060085001851, + 6.48114130629288, 6.18607038456406, 6.16923370572396, + 6.64223126283631, 6.07231852289266, 5.79043710204375, + 6.48463886529882, 6.36263392044401, 6.11212476454494, + 6.14573900812925, 6.12568047243240, 6.43836230231577, + 6.02505694060219, 6.13819468942244, 6.22100593815064, + 6.02394682666345, 5.89016573063789, 5.74448527739202, + 5.50415294280017, 5.31883018164157, 4.87476769510305, + 4.74386713755523, 4.60638346931628, 4.06177345572680, + 3.73334482123538, 3.13848311672243, 2.71638862600768, + 2.02963773590165, 1.49291145092070, 0.818343889647352, 0]) + + return v1, i1, v2, i2 diff --git a/setup.py b/setup.py index f2e320ccbb..a492b695e8 100755 --- a/setup.py +++ b/setup.py @@ -44,8 +44,8 @@ TESTS_REQUIRE = ['nose', 'pytest', 'pytest-cov', 'pytest-mock', 'pytest-timeout'] EXTRAS_REQUIRE = { - 'optional': ['ephem', 'cython', 'netcdf4', 'numba', 'pvfactors', 'scipy', - 'siphon', 'tables'], + 'optional': ['ephem', 'cython', 'netcdf4', 'nrel-pysam', 'numba', + 'pvfactors', 'scipy', 'siphon', 'tables'], 'doc': ['ipython', 'matplotlib', 'sphinx', 'sphinx_rtd_theme'], 'test': TESTS_REQUIRE }