pvlib 0.11.1__py3-none-any.whl → 0.12.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pvlib/__init__.py +1 -0
- pvlib/_deprecation.py +73 -0
- pvlib/atmosphere.py +77 -7
- pvlib/bifacial/infinite_sheds.py +4 -3
- pvlib/bifacial/utils.py +2 -1
- pvlib/clearsky.py +35 -22
- pvlib/iam.py +4 -4
- pvlib/iotools/midc.py +1 -1
- pvlib/iotools/psm3.py +1 -1
- pvlib/iotools/pvgis.py +10 -12
- pvlib/iotools/tmy.py +3 -69
- pvlib/irradiance.py +112 -55
- pvlib/ivtools/sdm.py +75 -52
- pvlib/location.py +73 -33
- pvlib/modelchain.py +18 -35
- pvlib/pvsystem.py +139 -94
- pvlib/snow.py +64 -28
- pvlib/solarposition.py +46 -30
- pvlib/spa.py +4 -2
- pvlib/spectrum/__init__.py +0 -1
- pvlib/spectrum/irradiance.py +2 -64
- pvlib/spectrum/mismatch.py +3 -3
- pvlib/spectrum/spectrl2.py +2 -1
- pvlib/temperature.py +49 -3
- pvlib/tools.py +6 -5
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/METADATA +14 -11
- pvlib-0.12.0.dist-info/RECORD +75 -0
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/WHEEL +1 -1
- pvlib/data/BIRD_08_16_2012.csv +0 -8761
- pvlib/data/BIRD_08_16_2012_patm.csv +0 -8761
- pvlib/data/Burlington, United States SolarAnywhere Time Series 2021 Lat_44_465 Lon_-73_205 TMY3 format.csv +0 -8762
- pvlib/data/Burlington, United States SolarAnywhere Time Series 20210101 to 20210103 Lat_44_4675 Lon_-73_2075 SA format.csv +0 -578
- pvlib/data/Burlington, United States SolarAnywhere Typical GHI Year Lat_44_465 Lon_-73_205 SA format.csv +0 -74
- pvlib/data/CPS SCH275KTL-DO-US-800-250kW_275kVA_1.OND +0 -146
- pvlib/data/CRNS0101-05-2019-AZ_Tucson_11_W.txt +0 -4
- pvlib/data/CRN_with_problems.txt +0 -3
- pvlib/data/ET-M772BH550GL.PAN +0 -75
- pvlib/data/NLD_Amsterdam062400_IWEC.epw +0 -8768
- pvlib/data/PVsyst_demo.csv +0 -10757
- pvlib/data/PVsyst_demo_model.csv +0 -3588
- pvlib/data/SRML-day-EUPO1801.txt +0 -1441
- pvlib/data/abq19056.dat +0 -6
- pvlib/data/aod550_tcwv_20121101_test.nc +0 -0
- pvlib/data/bishop88_numerical_precision.csv +0 -101
- pvlib/data/bsrn-lr0100-pay0616.dat +0 -86901
- pvlib/data/bsrn-pay0616.dat.gz +0 -0
- pvlib/data/cams_mcclear_1min_verbose.csv +0 -60
- pvlib/data/cams_mcclear_monthly.csv +0 -42
- pvlib/data/cams_radiation_1min_verbose.csv +0 -72
- pvlib/data/cams_radiation_monthly.csv +0 -47
- pvlib/data/detect_clearsky_data.csv +0 -35
- pvlib/data/detect_clearsky_threshold_data.csv +0 -126
- pvlib/data/greensboro_kimber_soil_manwash.dat +0 -8761
- pvlib/data/greensboro_kimber_soil_nowash.dat +0 -8761
- pvlib/data/inverter_fit_snl_meas.csv +0 -127
- pvlib/data/inverter_fit_snl_sim.csv +0 -19
- pvlib/data/ivtools_numdiff.csv +0 -52
- pvlib/data/midc_20181014.txt +0 -1441
- pvlib/data/midc_raw_20181018.txt +0 -1441
- pvlib/data/midc_raw_short_header_20191115.txt +0 -1441
- pvlib/data/msn19056.dat +0 -6
- pvlib/data/precise_iv_curves1.json +0 -10251
- pvlib/data/precise_iv_curves2.json +0 -10251
- pvlib/data/precise_iv_curves_parameter_sets1.csv +0 -33
- pvlib/data/precise_iv_curves_parameter_sets2.csv +0 -33
- pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA2_10kWp_CIS_5_2a_2013_2014.json +0 -1
- pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA_30deg_0deg_2016_2016.csv +0 -35
- pvlib/data/pvgis_tmy_meta.json +0 -32
- pvlib/data/pvgis_tmy_test.dat +0 -8761
- pvlib/data/pvwatts_8760_rackmount.csv +0 -8779
- pvlib/data/pvwatts_8760_roofmount.csv +0 -8779
- pvlib/data/singleaxis_tracker_wslope.csv +0 -8761
- pvlib/data/spectrl2_example_spectra.csv +0 -123
- pvlib/data/surfrad-slv16001.dat +0 -1442
- pvlib/data/test_psm3_2017.csv +0 -17521
- pvlib/data/test_psm3_2019_5min.csv +0 -289
- pvlib/data/test_psm3_tmy-2017.csv +0 -8761
- pvlib/data/test_read_psm3.csv +0 -17523
- pvlib/data/test_read_pvgis_horizon.csv +0 -49
- pvlib/data/tmy_45.000_8.000_2005_2020.csv +0 -8789
- pvlib/data/tmy_45.000_8.000_2005_2020.epw +0 -8768
- pvlib/data/tmy_45.000_8.000_2005_2020.json +0 -1
- pvlib/data/tmy_45.000_8.000_2005_2020.txt +0 -8761
- pvlib/data/tmy_45.000_8.000_userhorizon.json +0 -1
- pvlib/data/variables_style_rules.csv +0 -56
- pvlib/spa_c_files/README.md +0 -81
- pvlib/spa_c_files/cspa_py.pxd +0 -43
- pvlib/spa_c_files/spa_py.pyx +0 -30
- pvlib/tests/__init__.py +0 -0
- pvlib/tests/bifacial/__init__.py +0 -0
- pvlib/tests/bifacial/test_infinite_sheds.py +0 -317
- pvlib/tests/bifacial/test_losses_models.py +0 -54
- pvlib/tests/bifacial/test_pvfactors.py +0 -82
- pvlib/tests/bifacial/test_utils.py +0 -192
- pvlib/tests/conftest.py +0 -476
- pvlib/tests/iotools/__init__.py +0 -0
- pvlib/tests/iotools/test_acis.py +0 -213
- pvlib/tests/iotools/test_bsrn.py +0 -131
- pvlib/tests/iotools/test_crn.py +0 -95
- pvlib/tests/iotools/test_epw.py +0 -23
- pvlib/tests/iotools/test_midc.py +0 -89
- pvlib/tests/iotools/test_panond.py +0 -32
- pvlib/tests/iotools/test_psm3.py +0 -198
- pvlib/tests/iotools/test_pvgis.py +0 -644
- pvlib/tests/iotools/test_sodapro.py +0 -298
- pvlib/tests/iotools/test_solaranywhere.py +0 -287
- pvlib/tests/iotools/test_solargis.py +0 -68
- pvlib/tests/iotools/test_solcast.py +0 -324
- pvlib/tests/iotools/test_solrad.py +0 -152
- pvlib/tests/iotools/test_srml.py +0 -124
- pvlib/tests/iotools/test_surfrad.py +0 -75
- pvlib/tests/iotools/test_tmy.py +0 -133
- pvlib/tests/ivtools/__init__.py +0 -0
- pvlib/tests/ivtools/test_sde.py +0 -230
- pvlib/tests/ivtools/test_sdm.py +0 -407
- pvlib/tests/ivtools/test_utils.py +0 -173
- pvlib/tests/spectrum/__init__.py +0 -0
- pvlib/tests/spectrum/conftest.py +0 -40
- pvlib/tests/spectrum/test_irradiance.py +0 -138
- pvlib/tests/spectrum/test_mismatch.py +0 -304
- pvlib/tests/spectrum/test_response.py +0 -124
- pvlib/tests/spectrum/test_spectrl2.py +0 -72
- pvlib/tests/test_albedo.py +0 -84
- pvlib/tests/test_atmosphere.py +0 -204
- pvlib/tests/test_clearsky.py +0 -878
- pvlib/tests/test_conftest.py +0 -81
- pvlib/tests/test_iam.py +0 -555
- pvlib/tests/test_inverter.py +0 -213
- pvlib/tests/test_irradiance.py +0 -1441
- pvlib/tests/test_location.py +0 -356
- pvlib/tests/test_modelchain.py +0 -2020
- pvlib/tests/test_numerical_precision.py +0 -124
- pvlib/tests/test_pvarray.py +0 -71
- pvlib/tests/test_pvsystem.py +0 -2495
- pvlib/tests/test_scaling.py +0 -207
- pvlib/tests/test_shading.py +0 -391
- pvlib/tests/test_singlediode.py +0 -608
- pvlib/tests/test_snow.py +0 -212
- pvlib/tests/test_soiling.py +0 -230
- pvlib/tests/test_solarposition.py +0 -933
- pvlib/tests/test_spa.py +0 -425
- pvlib/tests/test_temperature.py +0 -470
- pvlib/tests/test_tools.py +0 -146
- pvlib/tests/test_tracking.py +0 -474
- pvlib/tests/test_transformer.py +0 -60
- pvlib-0.11.1.dist-info/RECORD +0 -192
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info/licenses}/AUTHORS.md +0 -0
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info/licenses}/LICENSE +0 -0
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/top_level.txt +0 -0
pvlib/tests/test_pvsystem.py
DELETED
|
@@ -1,2495 +0,0 @@
|
|
|
1
|
-
from collections import OrderedDict
|
|
2
|
-
import itertools
|
|
3
|
-
|
|
4
|
-
import numpy as np
|
|
5
|
-
from numpy import nan, array
|
|
6
|
-
import pandas as pd
|
|
7
|
-
|
|
8
|
-
import pytest
|
|
9
|
-
from .conftest import assert_series_equal, assert_frame_equal
|
|
10
|
-
from numpy.testing import assert_allclose
|
|
11
|
-
import unittest.mock as mock
|
|
12
|
-
|
|
13
|
-
from pvlib import inverter, pvsystem
|
|
14
|
-
from pvlib import iam as _iam
|
|
15
|
-
from pvlib import irradiance
|
|
16
|
-
from pvlib import spectrum
|
|
17
|
-
from pvlib.location import Location
|
|
18
|
-
from pvlib.pvsystem import FixedMount
|
|
19
|
-
from pvlib import temperature
|
|
20
|
-
from pvlib._deprecation import pvlibDeprecationWarning
|
|
21
|
-
from pvlib.tools import cosd
|
|
22
|
-
from pvlib.singlediode import VOLTAGE_BUILTIN
|
|
23
|
-
from pvlib.tests.test_singlediode import get_pvsyst_fs_495
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@pytest.mark.parametrize('iam_model,model_params', [
|
|
27
|
-
('ashrae', {'b': 0.05}),
|
|
28
|
-
('physical', {'K': 4, 'L': 0.002, 'n': 1.526}),
|
|
29
|
-
('martin_ruiz', {'a_r': 0.16}),
|
|
30
|
-
])
|
|
31
|
-
def test_PVSystem_get_iam(mocker, iam_model, model_params):
|
|
32
|
-
m = mocker.spy(_iam, iam_model)
|
|
33
|
-
system = pvsystem.PVSystem(module_parameters=model_params)
|
|
34
|
-
thetas = 1
|
|
35
|
-
iam = system.get_iam(thetas, iam_model=iam_model)
|
|
36
|
-
m.assert_called_with(thetas, **model_params)
|
|
37
|
-
assert iam < 1.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def test_PVSystem_multi_array_get_iam():
|
|
41
|
-
model_params = {'b': 0.05}
|
|
42
|
-
system = pvsystem.PVSystem(
|
|
43
|
-
arrays=[pvsystem.Array(mount=pvsystem.FixedMount(0, 180),
|
|
44
|
-
module_parameters=model_params),
|
|
45
|
-
pvsystem.Array(mount=pvsystem.FixedMount(0, 180),
|
|
46
|
-
module_parameters=model_params)]
|
|
47
|
-
)
|
|
48
|
-
iam = system.get_iam((1, 5), iam_model='ashrae')
|
|
49
|
-
assert len(iam) == 2
|
|
50
|
-
assert iam[0] != iam[1]
|
|
51
|
-
with pytest.raises(ValueError,
|
|
52
|
-
match="Length mismatch for per-array parameter"):
|
|
53
|
-
system.get_iam((1,), iam_model='ashrae')
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def test_PVSystem_get_iam_sapm(sapm_module_params, mocker):
|
|
57
|
-
system = pvsystem.PVSystem(module_parameters=sapm_module_params)
|
|
58
|
-
mocker.spy(_iam, 'sapm')
|
|
59
|
-
aoi = 0
|
|
60
|
-
out = system.get_iam(aoi, 'sapm')
|
|
61
|
-
_iam.sapm.assert_called_once_with(aoi, sapm_module_params)
|
|
62
|
-
assert_allclose(out, 1.0, atol=0.01)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def test_PVSystem_get_iam_interp(mocker):
|
|
66
|
-
interp_module_params = {'iam_ref': (1., 0.8), 'theta_ref': (0., 80.)}
|
|
67
|
-
system = pvsystem.PVSystem(module_parameters=interp_module_params)
|
|
68
|
-
spy = mocker.spy(_iam, 'interp')
|
|
69
|
-
aoi = ((0., 40., 80.),)
|
|
70
|
-
expected = (1., 0.9, 0.8)
|
|
71
|
-
out = system.get_iam(aoi, iam_model='interp')
|
|
72
|
-
assert_allclose(out, expected)
|
|
73
|
-
spy.assert_called_once_with(aoi[0], **interp_module_params)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def test__normalize_sam_product_names():
|
|
77
|
-
|
|
78
|
-
BAD_NAMES = [' -.()[]:+/",', 'Module[1]']
|
|
79
|
-
NORM_NAMES = ['____________', 'Module_1_']
|
|
80
|
-
|
|
81
|
-
norm_names = pvsystem._normalize_sam_product_names(BAD_NAMES)
|
|
82
|
-
assert list(norm_names) == NORM_NAMES
|
|
83
|
-
|
|
84
|
-
BAD_NAMES = ['Module[1]', 'Module(1)']
|
|
85
|
-
NORM_NAMES = ['Module_1_', 'Module_1_']
|
|
86
|
-
|
|
87
|
-
with pytest.warns(UserWarning):
|
|
88
|
-
norm_names = pvsystem._normalize_sam_product_names(BAD_NAMES)
|
|
89
|
-
assert list(norm_names) == NORM_NAMES
|
|
90
|
-
|
|
91
|
-
BAD_NAMES = ['Module[1]', 'Module[1]']
|
|
92
|
-
NORM_NAMES = ['Module_1_', 'Module_1_']
|
|
93
|
-
|
|
94
|
-
with pytest.warns(UserWarning):
|
|
95
|
-
norm_names = pvsystem._normalize_sam_product_names(BAD_NAMES)
|
|
96
|
-
assert list(norm_names) == NORM_NAMES
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def test_PVSystem_get_iam_invalid(sapm_module_params, mocker):
|
|
100
|
-
system = pvsystem.PVSystem(module_parameters=sapm_module_params)
|
|
101
|
-
with pytest.raises(ValueError):
|
|
102
|
-
system.get_iam(45, iam_model='not_a_model')
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def test_retrieve_sam_raises_exceptions():
|
|
106
|
-
"""
|
|
107
|
-
Raise an exception if an invalid parameter is provided to `retrieve_sam()`.
|
|
108
|
-
"""
|
|
109
|
-
with pytest.raises(ValueError, match="Please provide either"):
|
|
110
|
-
pvsystem.retrieve_sam()
|
|
111
|
-
with pytest.raises(ValueError, match="Please provide either.*, not both."):
|
|
112
|
-
pvsystem.retrieve_sam(name="this_surely_wont_work", path="wont_work")
|
|
113
|
-
with pytest.raises(KeyError, match="Invalid name"):
|
|
114
|
-
pvsystem.retrieve_sam(name="this_surely_wont_work")
|
|
115
|
-
with pytest.raises(FileNotFoundError):
|
|
116
|
-
pvsystem.retrieve_sam(path="this_surely_wont_work.csv")
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def test_retrieve_sam_databases():
|
|
120
|
-
"""Test the expected keys are retrieved from each database."""
|
|
121
|
-
keys_per_database = {
|
|
122
|
-
"cecmod": {'Technology', 'Bifacial', 'STC', 'PTC', 'A_c', 'Length',
|
|
123
|
-
'Width', 'N_s', 'I_sc_ref', 'V_oc_ref', 'I_mp_ref',
|
|
124
|
-
'V_mp_ref', 'alpha_sc', 'beta_oc', 'T_NOCT', 'a_ref',
|
|
125
|
-
'I_L_ref', 'I_o_ref', 'R_s', 'R_sh_ref', 'Adjust',
|
|
126
|
-
'gamma_r', 'BIPV', 'Version', 'Date'},
|
|
127
|
-
"sandiamod": {'Vintage', 'Area', 'Material', 'Cells_in_Series',
|
|
128
|
-
'Parallel_Strings', 'Isco', 'Voco', 'Impo', 'Vmpo',
|
|
129
|
-
'Aisc', 'Aimp', 'C0', 'C1', 'Bvoco', 'Mbvoc', 'Bvmpo',
|
|
130
|
-
'Mbvmp', 'N', 'C2', 'C3', 'A0', 'A1', 'A2', 'A3', 'A4',
|
|
131
|
-
'B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'DTC', 'FD', 'A',
|
|
132
|
-
'B', 'C4', 'C5', 'IXO', 'IXXO', 'C6', 'C7', 'Notes'},
|
|
133
|
-
"adrinverter": {'Manufacturer', 'Model', 'Source', 'Vac', 'Vintage',
|
|
134
|
-
'Pacmax', 'Pnom', 'Vnom', 'Vmin', 'Vmax',
|
|
135
|
-
'ADRCoefficients', 'Pnt', 'Vdcmax', 'Idcmax',
|
|
136
|
-
'MPPTLow', 'MPPTHi', 'TambLow', 'TambHi', 'Weight',
|
|
137
|
-
'PacFitErrMax', 'YearOfData'},
|
|
138
|
-
"cecinverter": {'Vac', 'Paco', 'Pdco', 'Vdco', 'Pso', 'C0', 'C1', 'C2',
|
|
139
|
-
'C3', 'Pnt', 'Vdcmax', 'Idcmax', 'Mppt_low',
|
|
140
|
-
'Mppt_high', 'CEC_Date', 'CEC_Type'}
|
|
141
|
-
} # fmt: skip
|
|
142
|
-
item_per_database = {
|
|
143
|
-
"cecmod": "Itek_Energy_LLC_iT_300_HE",
|
|
144
|
-
"sandiamod": "Canadian_Solar_CS6X_300M__2013_",
|
|
145
|
-
"adrinverter": "Sainty_Solar__SSI_4K4U_240V__CEC_2011_",
|
|
146
|
-
"cecinverter": "ABB__PVI_3_0_OUTD_S_US__208V_",
|
|
147
|
-
}
|
|
148
|
-
# duplicate the cecinverter items for sandiainverter, for backwards compat
|
|
149
|
-
keys_per_database["sandiainverter"] = keys_per_database["cecinverter"]
|
|
150
|
-
item_per_database["sandiainverter"] = item_per_database["cecinverter"]
|
|
151
|
-
|
|
152
|
-
for database in keys_per_database.keys():
|
|
153
|
-
data = pvsystem.retrieve_sam(database)
|
|
154
|
-
assert set(data.index) == keys_per_database[database]
|
|
155
|
-
assert item_per_database[database] in data.columns
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
def test_sapm(sapm_module_params):
|
|
159
|
-
|
|
160
|
-
times = pd.date_range(start='2015-01-01', periods=5, freq='12h')
|
|
161
|
-
effective_irradiance = pd.Series([-1000, 500, 1100, np.nan, 1000],
|
|
162
|
-
index=times)
|
|
163
|
-
temp_cell = pd.Series([10, 25, 50, 25, np.nan], index=times)
|
|
164
|
-
|
|
165
|
-
out = pvsystem.sapm(effective_irradiance, temp_cell, sapm_module_params)
|
|
166
|
-
|
|
167
|
-
expected = pd.DataFrame(np.array(
|
|
168
|
-
[[-5.0608322, -4.65037767, np.nan, np.nan, np.nan,
|
|
169
|
-
-4.91119927, -4.16721569],
|
|
170
|
-
[2.545575, 2.28773882, 56.86182059, 47.21121608, 108.00693168,
|
|
171
|
-
2.48357383, 1.71782772],
|
|
172
|
-
[5.65584763, 5.01709903, 54.1943277, 42.51861718, 213.32011294,
|
|
173
|
-
5.52987899, 3.46796463],
|
|
174
|
-
[np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
|
|
175
|
-
[np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan]]),
|
|
176
|
-
columns=['i_sc', 'i_mp', 'v_oc', 'v_mp', 'p_mp', 'i_x', 'i_xx'],
|
|
177
|
-
index=times)
|
|
178
|
-
|
|
179
|
-
assert_frame_equal(out, expected, check_less_precise=4)
|
|
180
|
-
|
|
181
|
-
out = pvsystem.sapm(1000, 25, sapm_module_params)
|
|
182
|
-
|
|
183
|
-
expected = OrderedDict()
|
|
184
|
-
expected['i_sc'] = sapm_module_params['Isco']
|
|
185
|
-
expected['i_mp'] = sapm_module_params['Impo']
|
|
186
|
-
expected['v_oc'] = sapm_module_params['Voco']
|
|
187
|
-
expected['v_mp'] = sapm_module_params['Vmpo']
|
|
188
|
-
expected['p_mp'] = sapm_module_params['Impo'] * sapm_module_params['Vmpo']
|
|
189
|
-
expected['i_x'] = sapm_module_params['IXO']
|
|
190
|
-
expected['i_xx'] = sapm_module_params['IXXO']
|
|
191
|
-
|
|
192
|
-
for k, v in expected.items():
|
|
193
|
-
assert_allclose(out[k], v, atol=1e-4)
|
|
194
|
-
|
|
195
|
-
# just make sure it works with Series input
|
|
196
|
-
pvsystem.sapm(effective_irradiance, temp_cell,
|
|
197
|
-
pd.Series(sapm_module_params))
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
def test_PVSystem_sapm(sapm_module_params, mocker):
|
|
201
|
-
mocker.spy(pvsystem, 'sapm')
|
|
202
|
-
system = pvsystem.PVSystem(module_parameters=sapm_module_params)
|
|
203
|
-
effective_irradiance = 500
|
|
204
|
-
temp_cell = 25
|
|
205
|
-
out = system.sapm(effective_irradiance, temp_cell)
|
|
206
|
-
pvsystem.sapm.assert_called_once_with(effective_irradiance, temp_cell,
|
|
207
|
-
sapm_module_params)
|
|
208
|
-
assert_allclose(out['p_mp'], 100, 10)
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
def test_PVSystem_multi_array_sapm(sapm_module_params):
|
|
212
|
-
system = pvsystem.PVSystem(
|
|
213
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
214
|
-
module_parameters=sapm_module_params),
|
|
215
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
216
|
-
module_parameters=sapm_module_params)]
|
|
217
|
-
)
|
|
218
|
-
effective_irradiance = (100, 500)
|
|
219
|
-
temp_cell = (15, 25)
|
|
220
|
-
sapm_one, sapm_two = system.sapm(effective_irradiance, temp_cell)
|
|
221
|
-
assert sapm_one['p_mp'] != sapm_two['p_mp']
|
|
222
|
-
sapm_one_flip, sapm_two_flip = system.sapm(
|
|
223
|
-
(effective_irradiance[1], effective_irradiance[0]),
|
|
224
|
-
(temp_cell[1], temp_cell[0])
|
|
225
|
-
)
|
|
226
|
-
assert sapm_one_flip['p_mp'] == sapm_two['p_mp']
|
|
227
|
-
assert sapm_two_flip['p_mp'] == sapm_one['p_mp']
|
|
228
|
-
with pytest.raises(ValueError,
|
|
229
|
-
match="Length mismatch for per-array parameter"):
|
|
230
|
-
system.sapm(effective_irradiance, 10)
|
|
231
|
-
with pytest.raises(ValueError,
|
|
232
|
-
match="Length mismatch for per-array parameter"):
|
|
233
|
-
system.sapm(500, temp_cell)
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
def test_sapm_spectral_loss_deprecated(sapm_module_params):
|
|
237
|
-
with pytest.warns(pvlibDeprecationWarning,
|
|
238
|
-
match='Use pvlib.spectrum.spectral_factor_sapm'):
|
|
239
|
-
pvsystem.sapm_spectral_loss(1, sapm_module_params)
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
def test_PVSystem_sapm_spectral_loss(sapm_module_params, mocker):
|
|
243
|
-
mocker.spy(spectrum, 'spectral_factor_sapm')
|
|
244
|
-
system = pvsystem.PVSystem(module_parameters=sapm_module_params)
|
|
245
|
-
airmass = 2
|
|
246
|
-
out = system.sapm_spectral_loss(airmass)
|
|
247
|
-
spectrum.spectral_factor_sapm.assert_called_once_with(airmass,
|
|
248
|
-
sapm_module_params)
|
|
249
|
-
assert_allclose(out, 1, atol=0.5)
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
def test_PVSystem_multi_array_sapm_spectral_loss(sapm_module_params):
|
|
253
|
-
system = pvsystem.PVSystem(
|
|
254
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
255
|
-
module_parameters=sapm_module_params),
|
|
256
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
257
|
-
module_parameters=sapm_module_params)]
|
|
258
|
-
)
|
|
259
|
-
loss_one, loss_two = system.sapm_spectral_loss(2)
|
|
260
|
-
assert loss_one == loss_two
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
# this test could be improved to cover all cell types.
|
|
264
|
-
# could remove the need for specifying spectral coefficients if we don't
|
|
265
|
-
# care about the return value at all
|
|
266
|
-
@pytest.mark.parametrize('module_parameters,module_type,coefficients', [
|
|
267
|
-
({'Technology': 'mc-Si'}, 'multisi', None),
|
|
268
|
-
({'Material': 'Multi-c-Si'}, 'multisi', None),
|
|
269
|
-
({'first_solar_spectral_coefficients': (
|
|
270
|
-
0.84, -0.03, -0.008, 0.14, 0.04, -0.002)},
|
|
271
|
-
None,
|
|
272
|
-
(0.84, -0.03, -0.008, 0.14, 0.04, -0.002))
|
|
273
|
-
])
|
|
274
|
-
def test_PVSystem_first_solar_spectral_loss(module_parameters, module_type,
|
|
275
|
-
coefficients, mocker):
|
|
276
|
-
mocker.spy(spectrum, 'spectral_factor_firstsolar')
|
|
277
|
-
system = pvsystem.PVSystem(module_parameters=module_parameters)
|
|
278
|
-
pw = 3
|
|
279
|
-
airmass_absolute = 3
|
|
280
|
-
out = system.first_solar_spectral_loss(pw, airmass_absolute)
|
|
281
|
-
spectrum.spectral_factor_firstsolar.assert_called_once_with(
|
|
282
|
-
pw, airmass_absolute, module_type, coefficients)
|
|
283
|
-
assert_allclose(out, 1, atol=0.5)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
def test_PVSystem_multi_array_first_solar_spectral_loss():
|
|
287
|
-
system = pvsystem.PVSystem(
|
|
288
|
-
arrays=[
|
|
289
|
-
pvsystem.Array(
|
|
290
|
-
mount=pvsystem.FixedMount(0, 180),
|
|
291
|
-
module_parameters={'Technology': 'mc-Si'},
|
|
292
|
-
module_type='multisi'
|
|
293
|
-
),
|
|
294
|
-
pvsystem.Array(
|
|
295
|
-
mount=pvsystem.FixedMount(0, 180),
|
|
296
|
-
module_parameters={'Technology': 'mc-Si'},
|
|
297
|
-
module_type='multisi'
|
|
298
|
-
)
|
|
299
|
-
]
|
|
300
|
-
)
|
|
301
|
-
loss_one, loss_two = system.first_solar_spectral_loss(1, 3)
|
|
302
|
-
assert loss_one == loss_two
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
@pytest.mark.parametrize('test_input,expected', [
|
|
306
|
-
([1000, 100, 5, 45], 1140.0510967821877),
|
|
307
|
-
([np.array([np.nan, 1000, 1000]),
|
|
308
|
-
np.array([100, np.nan, 100]),
|
|
309
|
-
np.array([1.1, 1.1, 1.1]),
|
|
310
|
-
np.array([10, 10, 10])],
|
|
311
|
-
np.array([np.nan, np.nan, 1081.1574])),
|
|
312
|
-
([pd.Series([1000]), pd.Series([100]), pd.Series([1.1]),
|
|
313
|
-
pd.Series([10])],
|
|
314
|
-
pd.Series([1081.1574]))
|
|
315
|
-
])
|
|
316
|
-
def test_sapm_effective_irradiance(sapm_module_params, test_input, expected):
|
|
317
|
-
test_input.append(sapm_module_params)
|
|
318
|
-
out = pvsystem.sapm_effective_irradiance(*test_input)
|
|
319
|
-
if isinstance(test_input, pd.Series):
|
|
320
|
-
assert_series_equal(out, expected, check_less_precise=4)
|
|
321
|
-
else:
|
|
322
|
-
assert_allclose(out, expected, atol=1e-1)
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
def test_PVSystem_sapm_effective_irradiance(sapm_module_params, mocker):
|
|
326
|
-
system = pvsystem.PVSystem(module_parameters=sapm_module_params)
|
|
327
|
-
mocker.spy(pvsystem, 'sapm_effective_irradiance')
|
|
328
|
-
|
|
329
|
-
poa_direct = 900
|
|
330
|
-
poa_diffuse = 100
|
|
331
|
-
airmass_absolute = 1.5
|
|
332
|
-
aoi = 0
|
|
333
|
-
p = (sapm_module_params['A4'], sapm_module_params['A3'],
|
|
334
|
-
sapm_module_params['A2'], sapm_module_params['A1'],
|
|
335
|
-
sapm_module_params['A0'])
|
|
336
|
-
f1 = np.polyval(p, airmass_absolute)
|
|
337
|
-
expected = f1 * (poa_direct + sapm_module_params['FD'] * poa_diffuse)
|
|
338
|
-
out = system.sapm_effective_irradiance(
|
|
339
|
-
poa_direct, poa_diffuse, airmass_absolute, aoi)
|
|
340
|
-
pvsystem.sapm_effective_irradiance.assert_called_once_with(
|
|
341
|
-
poa_direct, poa_diffuse, airmass_absolute, aoi, sapm_module_params)
|
|
342
|
-
assert_allclose(out, expected, atol=0.1)
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
def test_PVSystem_multi_array_sapm_effective_irradiance(sapm_module_params):
|
|
346
|
-
system = pvsystem.PVSystem(
|
|
347
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
348
|
-
module_parameters=sapm_module_params),
|
|
349
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
350
|
-
module_parameters=sapm_module_params)]
|
|
351
|
-
)
|
|
352
|
-
poa_direct = (500, 900)
|
|
353
|
-
poa_diffuse = (50, 100)
|
|
354
|
-
aoi = (0, 10)
|
|
355
|
-
airmass_absolute = 1.5
|
|
356
|
-
irrad_one, irrad_two = system.sapm_effective_irradiance(
|
|
357
|
-
poa_direct, poa_diffuse, airmass_absolute, aoi
|
|
358
|
-
)
|
|
359
|
-
assert irrad_one != irrad_two
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
@pytest.fixture
|
|
363
|
-
def two_array_system(pvsyst_module_params, cec_module_params):
|
|
364
|
-
"""Two-array PVSystem.
|
|
365
|
-
|
|
366
|
-
Both arrays are identical.
|
|
367
|
-
"""
|
|
368
|
-
temperature_model = temperature.TEMPERATURE_MODEL_PARAMETERS['sapm'][
|
|
369
|
-
'open_rack_glass_glass'
|
|
370
|
-
]
|
|
371
|
-
# Need u_v to be non-zero so wind-speed changes cell temperature
|
|
372
|
-
# under the pvsyst model.
|
|
373
|
-
temperature_model['u_v'] = 1.0
|
|
374
|
-
# parameter for fuentes temperature model
|
|
375
|
-
temperature_model['noct_installed'] = 45
|
|
376
|
-
# parameters for noct_sam temperature model
|
|
377
|
-
temperature_model['noct'] = 45.
|
|
378
|
-
temperature_model['module_efficiency'] = 0.2
|
|
379
|
-
module_params = {**pvsyst_module_params, **cec_module_params}
|
|
380
|
-
return pvsystem.PVSystem(
|
|
381
|
-
arrays=[
|
|
382
|
-
pvsystem.Array(
|
|
383
|
-
mount=pvsystem.FixedMount(0, 180),
|
|
384
|
-
temperature_model_parameters=temperature_model,
|
|
385
|
-
module_parameters=module_params
|
|
386
|
-
),
|
|
387
|
-
pvsystem.Array(
|
|
388
|
-
mount=pvsystem.FixedMount(0, 180),
|
|
389
|
-
temperature_model_parameters=temperature_model,
|
|
390
|
-
module_parameters=module_params
|
|
391
|
-
)
|
|
392
|
-
]
|
|
393
|
-
)
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
@pytest.mark.parametrize("poa_direct, poa_diffuse, aoi",
|
|
397
|
-
[(20, (10, 10), (20, 20)),
|
|
398
|
-
((20, 20), (10,), (20, 20)),
|
|
399
|
-
((20, 20), (10, 10), 20)])
|
|
400
|
-
def test_PVSystem_sapm_effective_irradiance_value_error(
|
|
401
|
-
poa_direct, poa_diffuse, aoi, two_array_system):
|
|
402
|
-
with pytest.raises(ValueError,
|
|
403
|
-
match="Length mismatch for per-array parameter"):
|
|
404
|
-
two_array_system.sapm_effective_irradiance(
|
|
405
|
-
poa_direct, poa_diffuse, 10, aoi
|
|
406
|
-
)
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
def test_PVSystem_sapm_celltemp(mocker):
|
|
410
|
-
a, b, deltaT = (-3.47, -0.0594, 3) # open_rack_glass_glass
|
|
411
|
-
temp_model_params = {'a': a, 'b': b, 'deltaT': deltaT}
|
|
412
|
-
system = pvsystem.PVSystem(temperature_model_parameters=temp_model_params)
|
|
413
|
-
mocker.spy(temperature, 'sapm_cell')
|
|
414
|
-
temps = 25
|
|
415
|
-
irrads = 1000
|
|
416
|
-
winds = 1
|
|
417
|
-
out = system.get_cell_temperature(irrads, temps, winds, model='sapm')
|
|
418
|
-
temperature.sapm_cell.assert_called_once_with(irrads, temps, winds, a, b,
|
|
419
|
-
deltaT)
|
|
420
|
-
assert_allclose(out, 57, atol=1)
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
def test_PVSystem_sapm_celltemp_kwargs(mocker):
|
|
424
|
-
temp_model_params = temperature.TEMPERATURE_MODEL_PARAMETERS['sapm'][
|
|
425
|
-
'open_rack_glass_glass']
|
|
426
|
-
system = pvsystem.PVSystem(temperature_model_parameters=temp_model_params)
|
|
427
|
-
mocker.spy(temperature, 'sapm_cell')
|
|
428
|
-
temps = 25
|
|
429
|
-
irrads = 1000
|
|
430
|
-
winds = 1
|
|
431
|
-
out = system.get_cell_temperature(irrads, temps, winds, model='sapm')
|
|
432
|
-
temperature.sapm_cell.assert_called_once_with(irrads, temps, winds,
|
|
433
|
-
temp_model_params['a'],
|
|
434
|
-
temp_model_params['b'],
|
|
435
|
-
temp_model_params['deltaT'])
|
|
436
|
-
assert_allclose(out, 57, atol=1)
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
def test_PVSystem_multi_array_sapm_celltemp_different_arrays():
|
|
440
|
-
temp_model_one = temperature.TEMPERATURE_MODEL_PARAMETERS['sapm'][
|
|
441
|
-
'open_rack_glass_glass']
|
|
442
|
-
temp_model_two = temperature.TEMPERATURE_MODEL_PARAMETERS['sapm'][
|
|
443
|
-
'close_mount_glass_glass']
|
|
444
|
-
system = pvsystem.PVSystem(
|
|
445
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
446
|
-
temperature_model_parameters=temp_model_one),
|
|
447
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
448
|
-
temperature_model_parameters=temp_model_two)]
|
|
449
|
-
)
|
|
450
|
-
temp_one, temp_two = system.get_cell_temperature(
|
|
451
|
-
(1000, 1000), 25, 1, model='sapm'
|
|
452
|
-
)
|
|
453
|
-
assert temp_one != temp_two
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
def test_PVSystem_pvsyst_celltemp(mocker):
|
|
457
|
-
parameter_set = 'insulated'
|
|
458
|
-
temp_model_params = temperature.TEMPERATURE_MODEL_PARAMETERS['pvsyst'][
|
|
459
|
-
parameter_set]
|
|
460
|
-
alpha_absorption = 0.85
|
|
461
|
-
module_efficiency = 0.17
|
|
462
|
-
module_parameters = {'alpha_absorption': alpha_absorption,
|
|
463
|
-
'module_efficiency': module_efficiency}
|
|
464
|
-
system = pvsystem.PVSystem(module_parameters=module_parameters,
|
|
465
|
-
temperature_model_parameters=temp_model_params)
|
|
466
|
-
mocker.spy(temperature, 'pvsyst_cell')
|
|
467
|
-
irrad = 800
|
|
468
|
-
temp = 45
|
|
469
|
-
wind = 0.5
|
|
470
|
-
out = system.get_cell_temperature(irrad, temp, wind_speed=wind,
|
|
471
|
-
model='pvsyst')
|
|
472
|
-
temperature.pvsyst_cell.assert_called_once_with(
|
|
473
|
-
irrad, temp, wind_speed=wind, u_c=temp_model_params['u_c'],
|
|
474
|
-
u_v=temp_model_params['u_v'], module_efficiency=module_efficiency,
|
|
475
|
-
alpha_absorption=alpha_absorption)
|
|
476
|
-
assert (out < 90) and (out > 70)
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
def test_PVSystem_faiman_celltemp(mocker):
|
|
480
|
-
u0, u1 = 25.0, 6.84 # default values
|
|
481
|
-
temp_model_params = {'u0': u0, 'u1': u1}
|
|
482
|
-
system = pvsystem.PVSystem(temperature_model_parameters=temp_model_params)
|
|
483
|
-
mocker.spy(temperature, 'faiman')
|
|
484
|
-
temps = 25
|
|
485
|
-
irrads = 1000
|
|
486
|
-
winds = 1
|
|
487
|
-
out = system.get_cell_temperature(irrads, temps, winds, model='faiman')
|
|
488
|
-
temperature.faiman.assert_called_once_with(irrads, temps, winds, u0, u1)
|
|
489
|
-
assert_allclose(out, 56.4, atol=1e-1)
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
def test_PVSystem_noct_celltemp(mocker):
|
|
493
|
-
poa_global, temp_air, wind_speed, noct, module_efficiency = (
|
|
494
|
-
1000., 25., 1., 45., 0.2)
|
|
495
|
-
expected = 55.230790492
|
|
496
|
-
temp_model_params = {'noct': noct, 'module_efficiency': module_efficiency}
|
|
497
|
-
system = pvsystem.PVSystem(temperature_model_parameters=temp_model_params)
|
|
498
|
-
mocker.spy(temperature, 'noct_sam')
|
|
499
|
-
out = system.get_cell_temperature(poa_global, temp_air, wind_speed,
|
|
500
|
-
model='noct_sam')
|
|
501
|
-
temperature.noct_sam.assert_called_once_with(
|
|
502
|
-
poa_global, temp_air, wind_speed, noct, module_efficiency,
|
|
503
|
-
effective_irradiance=None)
|
|
504
|
-
assert_allclose(out, expected)
|
|
505
|
-
# different types
|
|
506
|
-
out = system.get_cell_temperature(np.array(poa_global), np.array(temp_air),
|
|
507
|
-
np.array(wind_speed), model='noct_sam')
|
|
508
|
-
assert_allclose(out, expected)
|
|
509
|
-
dr = pd.date_range(start='2020-01-01 12:00:00', end='2020-01-01 13:00:00',
|
|
510
|
-
freq='1h')
|
|
511
|
-
out = system.get_cell_temperature(pd.Series(index=dr, data=poa_global),
|
|
512
|
-
pd.Series(index=dr, data=temp_air),
|
|
513
|
-
pd.Series(index=dr, data=wind_speed),
|
|
514
|
-
model='noct_sam')
|
|
515
|
-
assert_series_equal(out, pd.Series(index=dr, data=expected))
|
|
516
|
-
# now use optional arguments
|
|
517
|
-
temp_model_params.update({'transmittance_absorptance': 0.8,
|
|
518
|
-
'array_height': 2,
|
|
519
|
-
'mount_standoff': 2.0})
|
|
520
|
-
expected = 60.477703576
|
|
521
|
-
system = pvsystem.PVSystem(temperature_model_parameters=temp_model_params)
|
|
522
|
-
out = system.get_cell_temperature(poa_global, temp_air, wind_speed,
|
|
523
|
-
effective_irradiance=1100.,
|
|
524
|
-
model='noct_sam')
|
|
525
|
-
assert_allclose(out, expected)
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
def test_PVSystem_noct_celltemp_error():
|
|
529
|
-
poa_global, temp_air, wind_speed, module_efficiency = (1000., 25., 1., 0.2)
|
|
530
|
-
temp_model_params = {'module_efficiency': module_efficiency}
|
|
531
|
-
system = pvsystem.PVSystem(temperature_model_parameters=temp_model_params)
|
|
532
|
-
with pytest.raises(KeyError):
|
|
533
|
-
system.get_cell_temperature(poa_global, temp_air, wind_speed,
|
|
534
|
-
model='noct_sam')
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
@pytest.mark.parametrize("model",
|
|
538
|
-
['faiman', 'pvsyst', 'sapm', 'fuentes', 'noct_sam'])
|
|
539
|
-
def test_PVSystem_multi_array_celltemp_functions(model, two_array_system):
|
|
540
|
-
times = pd.date_range(start='2020-08-25 11:00', freq='h', periods=3)
|
|
541
|
-
irrad_one = pd.Series(1000, index=times)
|
|
542
|
-
irrad_two = pd.Series(500, index=times)
|
|
543
|
-
temp_air = pd.Series(25, index=times)
|
|
544
|
-
wind_speed = pd.Series(1, index=times)
|
|
545
|
-
|
|
546
|
-
temp_one, temp_two = two_array_system.get_cell_temperature(
|
|
547
|
-
(irrad_one, irrad_two), temp_air, wind_speed, model=model)
|
|
548
|
-
assert (temp_one != temp_two).all()
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
@pytest.mark.parametrize("model",
|
|
552
|
-
['faiman', 'pvsyst', 'sapm', 'fuentes', 'noct_sam'])
|
|
553
|
-
def test_PVSystem_multi_array_celltemp_multi_temp(model, two_array_system):
|
|
554
|
-
times = pd.date_range(start='2020-08-25 11:00', freq='h', periods=3)
|
|
555
|
-
irrad = pd.Series(1000, index=times)
|
|
556
|
-
temp_air_one = pd.Series(25, index=times)
|
|
557
|
-
temp_air_two = pd.Series(5, index=times)
|
|
558
|
-
wind_speed = pd.Series(1, index=times)
|
|
559
|
-
temp_one, temp_two = two_array_system.get_cell_temperature(
|
|
560
|
-
(irrad, irrad),
|
|
561
|
-
(temp_air_one, temp_air_two),
|
|
562
|
-
wind_speed,
|
|
563
|
-
model=model
|
|
564
|
-
)
|
|
565
|
-
assert (temp_one != temp_two).all()
|
|
566
|
-
temp_one_swtich, temp_two_switch = two_array_system.get_cell_temperature(
|
|
567
|
-
(irrad, irrad),
|
|
568
|
-
(temp_air_two, temp_air_one),
|
|
569
|
-
wind_speed,
|
|
570
|
-
model=model
|
|
571
|
-
)
|
|
572
|
-
assert_series_equal(temp_one, temp_two_switch)
|
|
573
|
-
assert_series_equal(temp_two, temp_one_swtich)
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
@pytest.mark.parametrize("model",
|
|
577
|
-
['faiman', 'pvsyst', 'sapm', 'fuentes', 'noct_sam'])
|
|
578
|
-
def test_PVSystem_multi_array_celltemp_multi_wind(model, two_array_system):
|
|
579
|
-
times = pd.date_range(start='2020-08-25 11:00', freq='h', periods=3)
|
|
580
|
-
irrad = pd.Series(1000, index=times)
|
|
581
|
-
temp_air = pd.Series(25, index=times)
|
|
582
|
-
wind_speed_one = pd.Series(1, index=times)
|
|
583
|
-
wind_speed_two = pd.Series(5, index=times)
|
|
584
|
-
temp_one, temp_two = two_array_system.get_cell_temperature(
|
|
585
|
-
(irrad, irrad),
|
|
586
|
-
temp_air,
|
|
587
|
-
(wind_speed_one, wind_speed_two),
|
|
588
|
-
model=model
|
|
589
|
-
)
|
|
590
|
-
assert (temp_one != temp_two).all()
|
|
591
|
-
temp_one_swtich, temp_two_switch = two_array_system.get_cell_temperature(
|
|
592
|
-
(irrad, irrad),
|
|
593
|
-
temp_air,
|
|
594
|
-
(wind_speed_two, wind_speed_one),
|
|
595
|
-
model=model
|
|
596
|
-
)
|
|
597
|
-
assert_series_equal(temp_one, temp_two_switch)
|
|
598
|
-
assert_series_equal(temp_two, temp_one_swtich)
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
def test_PVSystem_get_cell_temperature_invalid():
|
|
602
|
-
system = pvsystem.PVSystem()
|
|
603
|
-
with pytest.raises(ValueError, match='not a valid'):
|
|
604
|
-
system.get_cell_temperature(1000, 25, 1, 'not_a_model')
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
@pytest.mark.parametrize("model",
|
|
608
|
-
['faiman', 'pvsyst', 'sapm', 'fuentes', 'noct_sam'])
|
|
609
|
-
def test_PVSystem_multi_array_celltemp_temp_too_short(
|
|
610
|
-
model, two_array_system):
|
|
611
|
-
with pytest.raises(ValueError,
|
|
612
|
-
match="Length mismatch for per-array parameter"):
|
|
613
|
-
two_array_system.get_cell_temperature((1000, 1000), (1,), 1,
|
|
614
|
-
model=model)
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
@pytest.mark.parametrize("model",
|
|
618
|
-
['faiman', 'pvsyst', 'sapm', 'fuentes', 'noct_sam'])
|
|
619
|
-
def test_PVSystem_multi_array_celltemp_temp_too_long(
|
|
620
|
-
model, two_array_system):
|
|
621
|
-
with pytest.raises(ValueError,
|
|
622
|
-
match="Length mismatch for per-array parameter"):
|
|
623
|
-
two_array_system.get_cell_temperature((1000, 1000), (1, 1, 1), 1,
|
|
624
|
-
model=model)
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
@pytest.mark.parametrize("model",
|
|
628
|
-
['faiman', 'pvsyst', 'sapm', 'fuentes', 'noct_sam'])
|
|
629
|
-
def test_PVSystem_multi_array_celltemp_wind_too_short(
|
|
630
|
-
model, two_array_system):
|
|
631
|
-
with pytest.raises(ValueError,
|
|
632
|
-
match="Length mismatch for per-array parameter"):
|
|
633
|
-
two_array_system.get_cell_temperature((1000, 1000), 25, (1,),
|
|
634
|
-
model=model)
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
@pytest.mark.parametrize("model",
|
|
638
|
-
['faiman', 'pvsyst', 'sapm', 'fuentes', 'noct_sam'])
|
|
639
|
-
def test_PVSystem_multi_array_celltemp_wind_too_long(
|
|
640
|
-
model, two_array_system):
|
|
641
|
-
with pytest.raises(ValueError,
|
|
642
|
-
match="Length mismatch for per-array parameter"):
|
|
643
|
-
two_array_system.get_cell_temperature((1000, 1000), 25, (1, 1, 1),
|
|
644
|
-
model=model)
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
@pytest.mark.parametrize("model",
|
|
648
|
-
['faiman', 'pvsyst', 'sapm', 'fuentes', 'noct_sam'])
|
|
649
|
-
def test_PVSystem_multi_array_celltemp_poa_length_mismatch(
|
|
650
|
-
model, two_array_system):
|
|
651
|
-
with pytest.raises(ValueError,
|
|
652
|
-
match="Length mismatch for per-array parameter"):
|
|
653
|
-
two_array_system.get_cell_temperature(1000, 25, 1, model=model)
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
def test_PVSystem_fuentes_celltemp(mocker):
|
|
657
|
-
noct_installed = 45
|
|
658
|
-
temp_model_params = {'noct_installed': noct_installed, 'surface_tilt': 0}
|
|
659
|
-
system = pvsystem.PVSystem(temperature_model_parameters=temp_model_params)
|
|
660
|
-
spy = mocker.spy(temperature, 'fuentes')
|
|
661
|
-
index = pd.date_range('2019-01-01 11:00', freq='h', periods=3)
|
|
662
|
-
temps = pd.Series(25, index)
|
|
663
|
-
irrads = pd.Series(1000, index)
|
|
664
|
-
winds = pd.Series(1, index)
|
|
665
|
-
out = system.get_cell_temperature(irrads, temps, winds, model='fuentes')
|
|
666
|
-
assert_series_equal(spy.call_args[0][0], irrads)
|
|
667
|
-
assert_series_equal(spy.call_args[0][1], temps)
|
|
668
|
-
assert_series_equal(spy.call_args[0][2], winds)
|
|
669
|
-
assert spy.call_args[0][3] == noct_installed
|
|
670
|
-
assert_series_equal(out, pd.Series([52.85, 55.85, 55.85], index,
|
|
671
|
-
name='tmod'))
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
def test_PVSystem_fuentes_module_height(mocker):
|
|
675
|
-
# check that fuentes picks up Array.mount.module_height correctly
|
|
676
|
-
# (temperature.fuentes defaults to 5 for module_height)
|
|
677
|
-
array = pvsystem.Array(mount=FixedMount(module_height=3),
|
|
678
|
-
temperature_model_parameters={'noct_installed': 45})
|
|
679
|
-
spy = mocker.spy(temperature, 'fuentes')
|
|
680
|
-
index = pd.date_range('2019-01-01 11:00', freq='h', periods=3)
|
|
681
|
-
temps = pd.Series(25, index)
|
|
682
|
-
irrads = pd.Series(1000, index)
|
|
683
|
-
winds = pd.Series(1, index)
|
|
684
|
-
_ = array.get_cell_temperature(irrads, temps, winds, model='fuentes')
|
|
685
|
-
assert spy.call_args[1]['module_height'] == 3
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
def test_Array__infer_temperature_model_params():
|
|
689
|
-
array = pvsystem.Array(mount=FixedMount(0, 180,
|
|
690
|
-
racking_model='open_rack'),
|
|
691
|
-
module_parameters={},
|
|
692
|
-
module_type='glass_polymer')
|
|
693
|
-
expected = temperature.TEMPERATURE_MODEL_PARAMETERS[
|
|
694
|
-
'sapm']['open_rack_glass_polymer']
|
|
695
|
-
assert expected == array._infer_temperature_model_params()
|
|
696
|
-
array = pvsystem.Array(mount=FixedMount(0, 180,
|
|
697
|
-
racking_model='freestanding'),
|
|
698
|
-
module_parameters={},
|
|
699
|
-
module_type='glass_polymer')
|
|
700
|
-
expected = temperature.TEMPERATURE_MODEL_PARAMETERS[
|
|
701
|
-
'pvsyst']['freestanding']
|
|
702
|
-
assert expected == array._infer_temperature_model_params()
|
|
703
|
-
array = pvsystem.Array(mount=FixedMount(0, 180,
|
|
704
|
-
racking_model='insulated'),
|
|
705
|
-
module_parameters={},
|
|
706
|
-
module_type=None)
|
|
707
|
-
expected = temperature.TEMPERATURE_MODEL_PARAMETERS[
|
|
708
|
-
'pvsyst']['insulated']
|
|
709
|
-
assert expected == array._infer_temperature_model_params()
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
def test_Array__infer_cell_type():
|
|
713
|
-
array = pvsystem.Array(mount=pvsystem.FixedMount(0, 180),
|
|
714
|
-
module_parameters={})
|
|
715
|
-
assert array._infer_cell_type() is None
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
def _calcparams_correct_Python_type_numeric_type_cases():
|
|
719
|
-
"""
|
|
720
|
-
An auxilary function used in the unit tests named
|
|
721
|
-
``test_calcparams_*_returns_correct_Python_type``.
|
|
722
|
-
|
|
723
|
-
Returns
|
|
724
|
-
-------
|
|
725
|
-
Returns a list of tuples of functions intended for transforming a
|
|
726
|
-
Python scalar into a numeric type: scalar, np.ndarray, or pandas.Series
|
|
727
|
-
"""
|
|
728
|
-
return list(itertools.product(*(2 * [[
|
|
729
|
-
# scalars (e.g. Python floats)
|
|
730
|
-
lambda x: x,
|
|
731
|
-
# np.ndarrays (0d and 1d-arrays)
|
|
732
|
-
np.array,
|
|
733
|
-
lambda x: np.array([x]),
|
|
734
|
-
# pd.Series (1d-arrays)
|
|
735
|
-
pd.Series
|
|
736
|
-
]])))
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
def _calcparams_correct_Python_type_check(out_value, numeric_args):
|
|
740
|
-
"""
|
|
741
|
-
An auxilary function used in the unit tests named
|
|
742
|
-
``test_calcparams_*_returns_correct_Python_type``.
|
|
743
|
-
|
|
744
|
-
Parameters
|
|
745
|
-
----------
|
|
746
|
-
out_value: numeric
|
|
747
|
-
A value returned by a pvsystem.calcparams_ function.
|
|
748
|
-
|
|
749
|
-
numeric_args: numeric
|
|
750
|
-
An iterable of the numeric-type arguments to the pvsystem.calcparams_
|
|
751
|
-
functions: ``effective_irradiance`` and ``temp_cell``.
|
|
752
|
-
|
|
753
|
-
Returns
|
|
754
|
-
-------
|
|
755
|
-
bool indicating whether ``out_value`` has the correct Python type
|
|
756
|
-
based on the Python types of ``effective_irradiance`` and
|
|
757
|
-
``temp_cell``.
|
|
758
|
-
"""
|
|
759
|
-
if any(isinstance(a, pd.Series) for a in numeric_args):
|
|
760
|
-
return isinstance(out_value, pd.Series)
|
|
761
|
-
elif any(isinstance(a, np.ndarray) for a in numeric_args):
|
|
762
|
-
return isinstance(out_value, np.ndarray) # 0d or 1d-arrays
|
|
763
|
-
return np.isscalar(out_value)
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
@pytest.mark.parametrize('numeric_type_funcs',
|
|
767
|
-
_calcparams_correct_Python_type_numeric_type_cases())
|
|
768
|
-
def test_calcparams_desoto_returns_correct_Python_type(numeric_type_funcs,
|
|
769
|
-
cec_module_params):
|
|
770
|
-
numeric_args = dict(
|
|
771
|
-
effective_irradiance=numeric_type_funcs[0](800.0),
|
|
772
|
-
temp_cell=numeric_type_funcs[1](25),
|
|
773
|
-
)
|
|
774
|
-
out = pvsystem.calcparams_desoto(
|
|
775
|
-
**numeric_args,
|
|
776
|
-
alpha_sc=cec_module_params['alpha_sc'],
|
|
777
|
-
a_ref=cec_module_params['a_ref'],
|
|
778
|
-
I_L_ref=cec_module_params['I_L_ref'],
|
|
779
|
-
I_o_ref=cec_module_params['I_o_ref'],
|
|
780
|
-
R_sh_ref=cec_module_params['R_sh_ref'],
|
|
781
|
-
R_s=cec_module_params['R_s'],
|
|
782
|
-
EgRef=1.121,
|
|
783
|
-
dEgdT=-0.0002677
|
|
784
|
-
)
|
|
785
|
-
|
|
786
|
-
assert all(_calcparams_correct_Python_type_check(a, numeric_args.values())
|
|
787
|
-
for a in out)
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
@pytest.mark.parametrize('numeric_type_funcs',
|
|
791
|
-
_calcparams_correct_Python_type_numeric_type_cases())
|
|
792
|
-
def test_calcparams_cec_returns_correct_Python_type(numeric_type_funcs,
|
|
793
|
-
cec_module_params):
|
|
794
|
-
numeric_args = dict(
|
|
795
|
-
effective_irradiance=numeric_type_funcs[0](800.0),
|
|
796
|
-
temp_cell=numeric_type_funcs[1](25),
|
|
797
|
-
)
|
|
798
|
-
out = pvsystem.calcparams_cec(
|
|
799
|
-
**numeric_args,
|
|
800
|
-
alpha_sc=cec_module_params['alpha_sc'],
|
|
801
|
-
a_ref=cec_module_params['a_ref'],
|
|
802
|
-
I_L_ref=cec_module_params['I_L_ref'],
|
|
803
|
-
I_o_ref=cec_module_params['I_o_ref'],
|
|
804
|
-
R_sh_ref=cec_module_params['R_sh_ref'],
|
|
805
|
-
R_s=cec_module_params['R_s'],
|
|
806
|
-
Adjust=cec_module_params['Adjust'],
|
|
807
|
-
EgRef=1.121,
|
|
808
|
-
dEgdT=-0.0002677
|
|
809
|
-
)
|
|
810
|
-
|
|
811
|
-
assert all(_calcparams_correct_Python_type_check(a, numeric_args.values())
|
|
812
|
-
for a in out)
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
@pytest.mark.parametrize('numeric_type_funcs',
|
|
816
|
-
_calcparams_correct_Python_type_numeric_type_cases())
|
|
817
|
-
def test_calcparams_pvsyst_returns_correct_Python_type(numeric_type_funcs,
|
|
818
|
-
pvsyst_module_params):
|
|
819
|
-
numeric_args = dict(
|
|
820
|
-
effective_irradiance=numeric_type_funcs[0](800.0),
|
|
821
|
-
temp_cell=numeric_type_funcs[1](25),
|
|
822
|
-
)
|
|
823
|
-
out = pvsystem.calcparams_pvsyst(
|
|
824
|
-
**numeric_args,
|
|
825
|
-
alpha_sc=pvsyst_module_params['alpha_sc'],
|
|
826
|
-
gamma_ref=pvsyst_module_params['gamma_ref'],
|
|
827
|
-
mu_gamma=pvsyst_module_params['mu_gamma'],
|
|
828
|
-
I_L_ref=pvsyst_module_params['I_L_ref'],
|
|
829
|
-
I_o_ref=pvsyst_module_params['I_o_ref'],
|
|
830
|
-
R_sh_ref=pvsyst_module_params['R_sh_ref'],
|
|
831
|
-
R_sh_0=pvsyst_module_params['R_sh_0'],
|
|
832
|
-
R_s=pvsyst_module_params['R_s'],
|
|
833
|
-
cells_in_series=pvsyst_module_params['cells_in_series'],
|
|
834
|
-
EgRef=pvsyst_module_params['EgRef']
|
|
835
|
-
)
|
|
836
|
-
|
|
837
|
-
assert all(_calcparams_correct_Python_type_check(a, numeric_args.values())
|
|
838
|
-
for a in out)
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
def test_calcparams_desoto_all_scalars(cec_module_params):
|
|
842
|
-
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_desoto(
|
|
843
|
-
effective_irradiance=800.0,
|
|
844
|
-
temp_cell=25,
|
|
845
|
-
alpha_sc=cec_module_params['alpha_sc'],
|
|
846
|
-
a_ref=cec_module_params['a_ref'],
|
|
847
|
-
I_L_ref=cec_module_params['I_L_ref'],
|
|
848
|
-
I_o_ref=cec_module_params['I_o_ref'],
|
|
849
|
-
R_sh_ref=cec_module_params['R_sh_ref'],
|
|
850
|
-
R_s=cec_module_params['R_s'],
|
|
851
|
-
EgRef=1.121,
|
|
852
|
-
dEgdT=-0.0002677
|
|
853
|
-
)
|
|
854
|
-
|
|
855
|
-
assert np.isclose(IL, 6.036, atol=1e-4, rtol=0)
|
|
856
|
-
assert np.isclose(I0, 1.94e-9, atol=1e-4, rtol=0)
|
|
857
|
-
assert np.isclose(Rs, 0.094, atol=1e-4, rtol=0)
|
|
858
|
-
assert np.isclose(Rsh, 19.65, atol=1e-4, rtol=0)
|
|
859
|
-
assert np.isclose(nNsVth, 0.473, atol=1e-4, rtol=0)
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
def test_calcparams_cec_all_scalars(cec_module_params):
|
|
863
|
-
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_cec(
|
|
864
|
-
effective_irradiance=800.0,
|
|
865
|
-
temp_cell=25,
|
|
866
|
-
alpha_sc=cec_module_params['alpha_sc'],
|
|
867
|
-
a_ref=cec_module_params['a_ref'],
|
|
868
|
-
I_L_ref=cec_module_params['I_L_ref'],
|
|
869
|
-
I_o_ref=cec_module_params['I_o_ref'],
|
|
870
|
-
R_sh_ref=cec_module_params['R_sh_ref'],
|
|
871
|
-
R_s=cec_module_params['R_s'],
|
|
872
|
-
Adjust=cec_module_params['Adjust'],
|
|
873
|
-
EgRef=1.121,
|
|
874
|
-
dEgdT=-0.0002677
|
|
875
|
-
)
|
|
876
|
-
|
|
877
|
-
assert np.isclose(IL, 6.036, atol=1e-4, rtol=0)
|
|
878
|
-
assert np.isclose(I0, 1.94e-9, atol=1e-4, rtol=0)
|
|
879
|
-
assert np.isclose(Rs, 0.094, atol=1e-4, rtol=0)
|
|
880
|
-
assert np.isclose(Rsh, 19.65, atol=1e-4, rtol=0)
|
|
881
|
-
assert np.isclose(nNsVth, 0.473, atol=1e-4, rtol=0)
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
def test_calcparams_pvsyst_all_scalars(pvsyst_module_params):
|
|
885
|
-
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_pvsyst(
|
|
886
|
-
effective_irradiance=800.0,
|
|
887
|
-
temp_cell=50,
|
|
888
|
-
alpha_sc=pvsyst_module_params['alpha_sc'],
|
|
889
|
-
gamma_ref=pvsyst_module_params['gamma_ref'],
|
|
890
|
-
mu_gamma=pvsyst_module_params['mu_gamma'],
|
|
891
|
-
I_L_ref=pvsyst_module_params['I_L_ref'],
|
|
892
|
-
I_o_ref=pvsyst_module_params['I_o_ref'],
|
|
893
|
-
R_sh_ref=pvsyst_module_params['R_sh_ref'],
|
|
894
|
-
R_sh_0=pvsyst_module_params['R_sh_0'],
|
|
895
|
-
R_s=pvsyst_module_params['R_s'],
|
|
896
|
-
cells_in_series=pvsyst_module_params['cells_in_series'],
|
|
897
|
-
EgRef=pvsyst_module_params['EgRef'])
|
|
898
|
-
|
|
899
|
-
assert np.isclose(IL, 4.8200, atol=1e-4, rtol=0)
|
|
900
|
-
assert np.isclose(I0, 1.47e-7, atol=1e-4, rtol=0)
|
|
901
|
-
assert np.isclose(Rs, 0.500, atol=1e-4, rtol=0)
|
|
902
|
-
assert np.isclose(Rsh, 305.757, atol=1e-4, rtol=0)
|
|
903
|
-
assert np.isclose(nNsVth, 1.7961, atol=1e-4, rtol=0)
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
def test_calcparams_desoto(cec_module_params):
|
|
907
|
-
times = pd.date_range(start='2015-01-01', periods=3, freq='12h')
|
|
908
|
-
df = pd.DataFrame({
|
|
909
|
-
'effective_irradiance': [0.0, 800.0, 800.0],
|
|
910
|
-
'temp_cell': [25, 25, 50]
|
|
911
|
-
}, index=times)
|
|
912
|
-
|
|
913
|
-
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_desoto(
|
|
914
|
-
df['effective_irradiance'],
|
|
915
|
-
df['temp_cell'],
|
|
916
|
-
alpha_sc=cec_module_params['alpha_sc'],
|
|
917
|
-
a_ref=cec_module_params['a_ref'],
|
|
918
|
-
I_L_ref=cec_module_params['I_L_ref'],
|
|
919
|
-
I_o_ref=cec_module_params['I_o_ref'],
|
|
920
|
-
R_sh_ref=cec_module_params['R_sh_ref'],
|
|
921
|
-
R_s=cec_module_params['R_s'],
|
|
922
|
-
EgRef=1.121,
|
|
923
|
-
dEgdT=-0.0002677
|
|
924
|
-
)
|
|
925
|
-
|
|
926
|
-
assert_series_equal(IL, pd.Series([0.0, 6.036, 6.096], index=times),
|
|
927
|
-
check_less_precise=3)
|
|
928
|
-
assert_series_equal(I0, pd.Series([0.0, 1.94e-9, 7.419e-8], index=times),
|
|
929
|
-
check_less_precise=3)
|
|
930
|
-
assert_series_equal(Rs, pd.Series([0.094, 0.094, 0.094], index=times),
|
|
931
|
-
check_less_precise=3)
|
|
932
|
-
assert_series_equal(Rsh, pd.Series([np.inf, 19.65, 19.65], index=times),
|
|
933
|
-
check_less_precise=3)
|
|
934
|
-
assert_series_equal(nNsVth, pd.Series([0.473, 0.473, 0.5127], index=times),
|
|
935
|
-
check_less_precise=3)
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
def test_calcparams_cec(cec_module_params):
|
|
939
|
-
times = pd.date_range(start='2015-01-01', periods=3, freq='12h')
|
|
940
|
-
df = pd.DataFrame({
|
|
941
|
-
'effective_irradiance': [0.0, 800.0, 800.0],
|
|
942
|
-
'temp_cell': [25, 25, 50]
|
|
943
|
-
}, index=times)
|
|
944
|
-
|
|
945
|
-
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_cec(
|
|
946
|
-
df['effective_irradiance'],
|
|
947
|
-
df['temp_cell'],
|
|
948
|
-
alpha_sc=cec_module_params['alpha_sc'],
|
|
949
|
-
a_ref=cec_module_params['a_ref'],
|
|
950
|
-
I_L_ref=cec_module_params['I_L_ref'],
|
|
951
|
-
I_o_ref=cec_module_params['I_o_ref'],
|
|
952
|
-
R_sh_ref=cec_module_params['R_sh_ref'],
|
|
953
|
-
R_s=cec_module_params['R_s'],
|
|
954
|
-
Adjust=cec_module_params['Adjust'],
|
|
955
|
-
EgRef=1.121,
|
|
956
|
-
dEgdT=-0.0002677
|
|
957
|
-
)
|
|
958
|
-
|
|
959
|
-
assert_series_equal(IL, pd.Series([0.0, 6.036, 6.0896], index=times),
|
|
960
|
-
check_less_precise=3)
|
|
961
|
-
assert_series_equal(I0, pd.Series([0.0, 1.94e-9, 7.419e-8], index=times),
|
|
962
|
-
check_less_precise=3)
|
|
963
|
-
assert_series_equal(Rs, pd.Series([0.094, 0.094, 0.094], index=times),
|
|
964
|
-
check_less_precise=3)
|
|
965
|
-
assert_series_equal(Rsh, pd.Series([np.inf, 19.65, 19.65], index=times),
|
|
966
|
-
check_less_precise=3)
|
|
967
|
-
assert_series_equal(nNsVth, pd.Series([0.473, 0.473, 0.5127], index=times),
|
|
968
|
-
check_less_precise=3)
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
def test_calcparams_cec_extra_params_propagation(cec_module_params, mocker):
|
|
972
|
-
"""
|
|
973
|
-
See bug #1215.
|
|
974
|
-
|
|
975
|
-
When calling `calcparams_cec`, the parameters `EgRef`, `dEgdT`, `irrad_ref`
|
|
976
|
-
and `temp_ref` must not be ignored.
|
|
977
|
-
|
|
978
|
-
Since, internally, this function is calling `calcparams_desoto`, this test
|
|
979
|
-
checks that the latter is called with the expected parameters instead of
|
|
980
|
-
some default values.
|
|
981
|
-
"""
|
|
982
|
-
times = pd.date_range(start='2015-01-01', periods=3, freq='12h')
|
|
983
|
-
effective_irradiance = pd.Series([0.0, 800.0, 800.0], index=times)
|
|
984
|
-
temp_cell = pd.Series([25, 25, 50], index=times)
|
|
985
|
-
extra_parameters = dict(
|
|
986
|
-
EgRef=1.123,
|
|
987
|
-
dEgdT=-0.0002688,
|
|
988
|
-
irrad_ref=1100,
|
|
989
|
-
temp_ref=23,
|
|
990
|
-
)
|
|
991
|
-
m = mocker.spy(pvsystem, 'calcparams_desoto')
|
|
992
|
-
pvsystem.calcparams_cec(
|
|
993
|
-
effective_irradiance=effective_irradiance,
|
|
994
|
-
temp_cell=temp_cell,
|
|
995
|
-
alpha_sc=cec_module_params['alpha_sc'],
|
|
996
|
-
a_ref=cec_module_params['a_ref'],
|
|
997
|
-
I_L_ref=cec_module_params['I_L_ref'],
|
|
998
|
-
I_o_ref=cec_module_params['I_o_ref'],
|
|
999
|
-
R_sh_ref=cec_module_params['R_sh_ref'],
|
|
1000
|
-
R_s=cec_module_params['R_s'],
|
|
1001
|
-
Adjust=cec_module_params['Adjust'],
|
|
1002
|
-
**extra_parameters,
|
|
1003
|
-
)
|
|
1004
|
-
assert m.call_count == 1
|
|
1005
|
-
assert m.call_args[1] == extra_parameters
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
def test_calcparams_pvsyst(pvsyst_module_params):
|
|
1009
|
-
times = pd.date_range(start='2015-01-01', periods=2, freq='12h')
|
|
1010
|
-
df = pd.DataFrame({
|
|
1011
|
-
'effective_irradiance': [0.0, 800.0],
|
|
1012
|
-
'temp_cell': [25, 50]
|
|
1013
|
-
}, index=times)
|
|
1014
|
-
|
|
1015
|
-
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_pvsyst(
|
|
1016
|
-
df['effective_irradiance'],
|
|
1017
|
-
df['temp_cell'],
|
|
1018
|
-
alpha_sc=pvsyst_module_params['alpha_sc'],
|
|
1019
|
-
gamma_ref=pvsyst_module_params['gamma_ref'],
|
|
1020
|
-
mu_gamma=pvsyst_module_params['mu_gamma'],
|
|
1021
|
-
I_L_ref=pvsyst_module_params['I_L_ref'],
|
|
1022
|
-
I_o_ref=pvsyst_module_params['I_o_ref'],
|
|
1023
|
-
R_sh_ref=pvsyst_module_params['R_sh_ref'],
|
|
1024
|
-
R_sh_0=pvsyst_module_params['R_sh_0'],
|
|
1025
|
-
R_s=pvsyst_module_params['R_s'],
|
|
1026
|
-
cells_in_series=pvsyst_module_params['cells_in_series'],
|
|
1027
|
-
EgRef=pvsyst_module_params['EgRef'])
|
|
1028
|
-
|
|
1029
|
-
assert_series_equal(
|
|
1030
|
-
IL.round(decimals=3), pd.Series([0.0, 4.8200], index=times))
|
|
1031
|
-
assert_series_equal(
|
|
1032
|
-
I0.round(decimals=3), pd.Series([0.0, 1.47e-7], index=times))
|
|
1033
|
-
assert_series_equal(
|
|
1034
|
-
Rs.round(decimals=3), pd.Series([0.500, 0.500], index=times))
|
|
1035
|
-
assert_series_equal(
|
|
1036
|
-
Rsh.round(decimals=3), pd.Series([1000.0, 305.757], index=times))
|
|
1037
|
-
assert_series_equal(
|
|
1038
|
-
nNsVth.round(decimals=4), pd.Series([1.6186, 1.7961], index=times))
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
def test_PVSystem_calcparams_desoto(cec_module_params, mocker):
|
|
1042
|
-
mocker.spy(pvsystem, 'calcparams_desoto')
|
|
1043
|
-
module_parameters = cec_module_params.copy()
|
|
1044
|
-
module_parameters['EgRef'] = 1.121
|
|
1045
|
-
module_parameters['dEgdT'] = -0.0002677
|
|
1046
|
-
system = pvsystem.PVSystem(module_parameters=module_parameters)
|
|
1047
|
-
effective_irradiance = np.array([0, 800])
|
|
1048
|
-
temp_cell = 25
|
|
1049
|
-
IL, I0, Rs, Rsh, nNsVth = system.calcparams_desoto(effective_irradiance,
|
|
1050
|
-
temp_cell)
|
|
1051
|
-
pvsystem.calcparams_desoto.assert_called_once_with(
|
|
1052
|
-
effective_irradiance,
|
|
1053
|
-
temp_cell,
|
|
1054
|
-
alpha_sc=cec_module_params['alpha_sc'],
|
|
1055
|
-
a_ref=cec_module_params['a_ref'],
|
|
1056
|
-
I_L_ref=cec_module_params['I_L_ref'],
|
|
1057
|
-
I_o_ref=cec_module_params['I_o_ref'],
|
|
1058
|
-
R_sh_ref=cec_module_params['R_sh_ref'],
|
|
1059
|
-
R_s=cec_module_params['R_s'],
|
|
1060
|
-
EgRef=module_parameters['EgRef'],
|
|
1061
|
-
dEgdT=module_parameters['dEgdT']
|
|
1062
|
-
)
|
|
1063
|
-
|
|
1064
|
-
assert_allclose(IL, np.array([0.0, 6.036]), atol=1e-1)
|
|
1065
|
-
assert_allclose(I0, np.array([2.0e-9, 2.0e-9]), atol=1.0e-9)
|
|
1066
|
-
assert_allclose(Rs, np.array([0.1, 0.1]), atol=0.1)
|
|
1067
|
-
assert_allclose(Rsh, np.array([np.inf, 20]), atol=1)
|
|
1068
|
-
assert_allclose(nNsVth, np.array([0.5, 0.5]), atol=0.1)
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
def test_PVSystem_calcparams_pvsyst(pvsyst_module_params, mocker):
|
|
1072
|
-
mocker.spy(pvsystem, 'calcparams_pvsyst')
|
|
1073
|
-
module_parameters = pvsyst_module_params.copy()
|
|
1074
|
-
system = pvsystem.PVSystem(module_parameters=module_parameters)
|
|
1075
|
-
effective_irradiance = np.array([0, 800])
|
|
1076
|
-
temp_cell = np.array([25, 50])
|
|
1077
|
-
IL, I0, Rs, Rsh, nNsVth = system.calcparams_pvsyst(effective_irradiance,
|
|
1078
|
-
temp_cell)
|
|
1079
|
-
pvsystem.calcparams_pvsyst.assert_called_once_with(
|
|
1080
|
-
effective_irradiance,
|
|
1081
|
-
temp_cell,
|
|
1082
|
-
alpha_sc=pvsyst_module_params['alpha_sc'],
|
|
1083
|
-
gamma_ref=pvsyst_module_params['gamma_ref'],
|
|
1084
|
-
mu_gamma=pvsyst_module_params['mu_gamma'],
|
|
1085
|
-
I_L_ref=pvsyst_module_params['I_L_ref'],
|
|
1086
|
-
I_o_ref=pvsyst_module_params['I_o_ref'],
|
|
1087
|
-
R_sh_ref=pvsyst_module_params['R_sh_ref'],
|
|
1088
|
-
R_sh_0=pvsyst_module_params['R_sh_0'],
|
|
1089
|
-
R_s=pvsyst_module_params['R_s'],
|
|
1090
|
-
cells_in_series=pvsyst_module_params['cells_in_series'],
|
|
1091
|
-
EgRef=pvsyst_module_params['EgRef'],
|
|
1092
|
-
R_sh_exp=pvsyst_module_params['R_sh_exp']
|
|
1093
|
-
)
|
|
1094
|
-
|
|
1095
|
-
assert_allclose(IL, np.array([0.0, 4.8200]), atol=1)
|
|
1096
|
-
assert_allclose(I0, np.array([0.0, 1.47e-7]), atol=1.0e-5)
|
|
1097
|
-
assert_allclose(Rs, np.array([0.5, 0.5]), atol=0.1)
|
|
1098
|
-
assert_allclose(Rsh, np.array([1000, 305.757]), atol=50)
|
|
1099
|
-
assert_allclose(nNsVth, np.array([1.6186, 1.7961]), atol=0.1)
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
@pytest.mark.parametrize('calcparams', [pvsystem.PVSystem.calcparams_pvsyst,
|
|
1103
|
-
pvsystem.PVSystem.calcparams_desoto,
|
|
1104
|
-
pvsystem.PVSystem.calcparams_cec])
|
|
1105
|
-
def test_PVSystem_multi_array_calcparams(calcparams, two_array_system):
|
|
1106
|
-
params_one, params_two = calcparams(
|
|
1107
|
-
two_array_system, (1000, 500), (30, 20)
|
|
1108
|
-
)
|
|
1109
|
-
assert params_one != params_two
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
@pytest.mark.parametrize('calcparams, irrad, celltemp',
|
|
1113
|
-
[ (f, irrad, celltemp)
|
|
1114
|
-
for f in (pvsystem.PVSystem.calcparams_desoto,
|
|
1115
|
-
pvsystem.PVSystem.calcparams_cec,
|
|
1116
|
-
pvsystem.PVSystem.calcparams_pvsyst)
|
|
1117
|
-
for irrad, celltemp in [(1, (1, 1)), ((1, 1), 1)]])
|
|
1118
|
-
def test_PVSystem_multi_array_calcparams_value_error(
|
|
1119
|
-
calcparams, irrad, celltemp, two_array_system):
|
|
1120
|
-
with pytest.raises(ValueError,
|
|
1121
|
-
match='Length mismatch for per-array parameter'):
|
|
1122
|
-
calcparams(two_array_system, irrad, celltemp)
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
@pytest.fixture(params=[
|
|
1126
|
-
{ # Can handle all python scalar inputs
|
|
1127
|
-
'Rsh': 20.,
|
|
1128
|
-
'Rs': 0.1,
|
|
1129
|
-
'nNsVth': 0.5,
|
|
1130
|
-
'I': 3.,
|
|
1131
|
-
'I0': 6.e-7,
|
|
1132
|
-
'IL': 7.,
|
|
1133
|
-
'V_expected': 7.5049875193450521
|
|
1134
|
-
},
|
|
1135
|
-
{ # Can handle all rank-0 array inputs
|
|
1136
|
-
'Rsh': np.array(20.),
|
|
1137
|
-
'Rs': np.array(0.1),
|
|
1138
|
-
'nNsVth': np.array(0.5),
|
|
1139
|
-
'I': np.array(3.),
|
|
1140
|
-
'I0': np.array(6.e-7),
|
|
1141
|
-
'IL': np.array(7.),
|
|
1142
|
-
'V_expected': np.array(7.5049875193450521)
|
|
1143
|
-
},
|
|
1144
|
-
{ # Can handle all rank-1 singleton array inputs
|
|
1145
|
-
'Rsh': np.array([20.]),
|
|
1146
|
-
'Rs': np.array([0.1]),
|
|
1147
|
-
'nNsVth': np.array([0.5]),
|
|
1148
|
-
'I': np.array([3.]),
|
|
1149
|
-
'I0': np.array([6.e-7]),
|
|
1150
|
-
'IL': np.array([7.]),
|
|
1151
|
-
'V_expected': np.array([7.5049875193450521])
|
|
1152
|
-
},
|
|
1153
|
-
{ # Can handle all rank-1 non-singleton array inputs with infinite shunt
|
|
1154
|
-
# resistance, Rsh=inf gives V=Voc=nNsVth*(np.log(IL + I0) - np.log(I0)
|
|
1155
|
-
# at I=0
|
|
1156
|
-
'Rsh': np.array([np.inf, 20.]),
|
|
1157
|
-
'Rs': np.array([0.1, 0.1]),
|
|
1158
|
-
'nNsVth': np.array([0.5, 0.5]),
|
|
1159
|
-
'I': np.array([0., 3.]),
|
|
1160
|
-
'I0': np.array([6.e-7, 6.e-7]),
|
|
1161
|
-
'IL': np.array([7., 7.]),
|
|
1162
|
-
'V_expected': np.array([0.5*(np.log(7. + 6.e-7) - np.log(6.e-7)),
|
|
1163
|
-
7.5049875193450521])
|
|
1164
|
-
},
|
|
1165
|
-
{ # Can handle mixed inputs with a rank-2 array with infinite shunt
|
|
1166
|
-
# resistance, Rsh=inf gives V=Voc=nNsVth*(np.log(IL + I0) - np.log(I0)
|
|
1167
|
-
# at I=0
|
|
1168
|
-
'Rsh': np.array([[np.inf, np.inf], [np.inf, np.inf]]),
|
|
1169
|
-
'Rs': np.array([0.1]),
|
|
1170
|
-
'nNsVth': np.array(0.5),
|
|
1171
|
-
'I': 0.,
|
|
1172
|
-
'I0': np.array([6.e-7]),
|
|
1173
|
-
'IL': np.array([7.]),
|
|
1174
|
-
'V_expected': 0.5*(np.log(7. + 6.e-7) - np.log(6.e-7))*np.ones((2, 2))
|
|
1175
|
-
},
|
|
1176
|
-
{ # Can handle ideal series and shunt, Rsh=inf and Rs=0 give
|
|
1177
|
-
# V = nNsVth*(np.log(IL - I + I0) - np.log(I0))
|
|
1178
|
-
'Rsh': np.inf,
|
|
1179
|
-
'Rs': 0.,
|
|
1180
|
-
'nNsVth': 0.5,
|
|
1181
|
-
'I': np.array([7., 7./2., 0.]),
|
|
1182
|
-
'I0': 6.e-7,
|
|
1183
|
-
'IL': 7.,
|
|
1184
|
-
'V_expected': np.array([0., 0.5*(np.log(7. - 7./2. + 6.e-7) -
|
|
1185
|
-
np.log(6.e-7)), 0.5*(np.log(7. + 6.e-7) -
|
|
1186
|
-
np.log(6.e-7))])
|
|
1187
|
-
},
|
|
1188
|
-
{ # Can handle only ideal series resistance, no closed form solution
|
|
1189
|
-
'Rsh': 20.,
|
|
1190
|
-
'Rs': 0.,
|
|
1191
|
-
'nNsVth': 0.5,
|
|
1192
|
-
'I': 3.,
|
|
1193
|
-
'I0': 6.e-7,
|
|
1194
|
-
'IL': 7.,
|
|
1195
|
-
'V_expected': 7.804987519345062
|
|
1196
|
-
},
|
|
1197
|
-
{ # Can handle all python scalar inputs with big LambertW arg
|
|
1198
|
-
'Rsh': 500.,
|
|
1199
|
-
'Rs': 10.,
|
|
1200
|
-
'nNsVth': 4.06,
|
|
1201
|
-
'I': 0.,
|
|
1202
|
-
'I0': 6.e-10,
|
|
1203
|
-
'IL': 1.2,
|
|
1204
|
-
'V_expected': 86.320000493521079
|
|
1205
|
-
},
|
|
1206
|
-
{ # Can handle all python scalar inputs with bigger LambertW arg
|
|
1207
|
-
# 1000 W/m^2 on a Canadian Solar 220M with 20 C ambient temp
|
|
1208
|
-
# github issue 225 (this appears to be from PR 226 not issue 225)
|
|
1209
|
-
'Rsh': 190.,
|
|
1210
|
-
'Rs': 1.065,
|
|
1211
|
-
'nNsVth': 2.89,
|
|
1212
|
-
'I': 0.,
|
|
1213
|
-
'I0': 7.05196029e-08,
|
|
1214
|
-
'IL': 10.491262,
|
|
1215
|
-
'V_expected': 54.303958833791455
|
|
1216
|
-
},
|
|
1217
|
-
{ # Can handle all python scalar inputs with bigger LambertW arg
|
|
1218
|
-
# 1000 W/m^2 on a Canadian Solar 220M with 20 C ambient temp
|
|
1219
|
-
# github issue 225
|
|
1220
|
-
'Rsh': 381.68,
|
|
1221
|
-
'Rs': 1.065,
|
|
1222
|
-
'nNsVth': 2.681527737715915,
|
|
1223
|
-
'I': 0.,
|
|
1224
|
-
'I0': 1.8739027472625636e-09,
|
|
1225
|
-
'IL': 5.1366949999999996,
|
|
1226
|
-
'V_expected': 58.19323124611128
|
|
1227
|
-
},
|
|
1228
|
-
{ # Verify mixed solution type indexing logic
|
|
1229
|
-
'Rsh': np.array([np.inf, 190., 381.68]),
|
|
1230
|
-
'Rs': 1.065,
|
|
1231
|
-
'nNsVth': np.array([2.89, 2.89, 2.681527737715915]),
|
|
1232
|
-
'I': 0.,
|
|
1233
|
-
'I0': np.array([7.05196029e-08, 7.05196029e-08, 1.8739027472625636e-09]),
|
|
1234
|
-
'IL': np.array([10.491262, 10.491262, 5.1366949999999996]),
|
|
1235
|
-
'V_expected': np.array([2.89*np.log1p(10.491262/7.05196029e-08),
|
|
1236
|
-
54.303958833791455, 58.19323124611128])
|
|
1237
|
-
}])
|
|
1238
|
-
def fixture_v_from_i(request):
|
|
1239
|
-
return request.param
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
@pytest.mark.parametrize(
|
|
1243
|
-
'method, atol', [('lambertw', 1e-11), ('brentq', 1e-11), ('newton', 1e-8)]
|
|
1244
|
-
)
|
|
1245
|
-
def test_v_from_i(fixture_v_from_i, method, atol):
|
|
1246
|
-
# Solution set loaded from fixture
|
|
1247
|
-
Rsh = fixture_v_from_i['Rsh']
|
|
1248
|
-
Rs = fixture_v_from_i['Rs']
|
|
1249
|
-
nNsVth = fixture_v_from_i['nNsVth']
|
|
1250
|
-
I = fixture_v_from_i['I']
|
|
1251
|
-
I0 = fixture_v_from_i['I0']
|
|
1252
|
-
IL = fixture_v_from_i['IL']
|
|
1253
|
-
V_expected = fixture_v_from_i['V_expected']
|
|
1254
|
-
|
|
1255
|
-
V = pvsystem.v_from_i(I, IL, I0, Rs, Rsh, nNsVth, method=method)
|
|
1256
|
-
|
|
1257
|
-
assert isinstance(V, type(V_expected))
|
|
1258
|
-
if isinstance(V, np.ndarray):
|
|
1259
|
-
assert isinstance(V.dtype, type(V_expected.dtype))
|
|
1260
|
-
assert V.shape == V_expected.shape
|
|
1261
|
-
assert_allclose(V, V_expected, atol=atol)
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
def test_i_from_v_from_i(fixture_v_from_i):
|
|
1265
|
-
# Solution set loaded from fixture
|
|
1266
|
-
Rsh = fixture_v_from_i['Rsh']
|
|
1267
|
-
Rs = fixture_v_from_i['Rs']
|
|
1268
|
-
nNsVth = fixture_v_from_i['nNsVth']
|
|
1269
|
-
current = fixture_v_from_i['I']
|
|
1270
|
-
I0 = fixture_v_from_i['I0']
|
|
1271
|
-
IL = fixture_v_from_i['IL']
|
|
1272
|
-
V = fixture_v_from_i['V_expected']
|
|
1273
|
-
|
|
1274
|
-
# Convergence criteria
|
|
1275
|
-
atol = 1.e-11
|
|
1276
|
-
|
|
1277
|
-
I_expected = pvsystem.i_from_v(V, IL, I0, Rs, Rsh, nNsVth,
|
|
1278
|
-
method='lambertw')
|
|
1279
|
-
assert_allclose(current, I_expected, atol=atol)
|
|
1280
|
-
|
|
1281
|
-
current = pvsystem.i_from_v(V, IL, I0, Rs, Rsh, nNsVth)
|
|
1282
|
-
|
|
1283
|
-
assert isinstance(current, type(I_expected))
|
|
1284
|
-
if isinstance(current, np.ndarray):
|
|
1285
|
-
assert isinstance(current.dtype, type(I_expected.dtype))
|
|
1286
|
-
assert current.shape == I_expected.shape
|
|
1287
|
-
assert_allclose(current, I_expected, atol=atol)
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
@pytest.fixture(params=[
|
|
1291
|
-
{ # Can handle all python scalar inputs
|
|
1292
|
-
'Rsh': 20.,
|
|
1293
|
-
'Rs': 0.1,
|
|
1294
|
-
'nNsVth': 0.5,
|
|
1295
|
-
'V': 7.5049875193450521,
|
|
1296
|
-
'I0': 6.e-7,
|
|
1297
|
-
'IL': 7.,
|
|
1298
|
-
'I_expected': 3.
|
|
1299
|
-
},
|
|
1300
|
-
{ # Can handle all rank-0 array inputs
|
|
1301
|
-
'Rsh': np.array(20.),
|
|
1302
|
-
'Rs': np.array(0.1),
|
|
1303
|
-
'nNsVth': np.array(0.5),
|
|
1304
|
-
'V': np.array(7.5049875193450521),
|
|
1305
|
-
'I0': np.array(6.e-7),
|
|
1306
|
-
'IL': np.array(7.),
|
|
1307
|
-
'I_expected': np.array(3.)
|
|
1308
|
-
},
|
|
1309
|
-
{ # Can handle all rank-1 singleton array inputs
|
|
1310
|
-
'Rsh': np.array([20.]),
|
|
1311
|
-
'Rs': np.array([0.1]),
|
|
1312
|
-
'nNsVth': np.array([0.5]),
|
|
1313
|
-
'V': np.array([7.5049875193450521]),
|
|
1314
|
-
'I0': np.array([6.e-7]),
|
|
1315
|
-
'IL': np.array([7.]),
|
|
1316
|
-
'I_expected': np.array([3.])
|
|
1317
|
-
},
|
|
1318
|
-
{ # Can handle all rank-1 non-singleton array inputs with a zero
|
|
1319
|
-
# series resistance, Rs=0 gives I=IL=Isc at V=0
|
|
1320
|
-
'Rsh': np.array([20., 20.]),
|
|
1321
|
-
'Rs': np.array([0., 0.1]),
|
|
1322
|
-
'nNsVth': np.array([0.5, 0.5]),
|
|
1323
|
-
'V': np.array([0., 7.5049875193450521]),
|
|
1324
|
-
'I0': np.array([6.e-7, 6.e-7]),
|
|
1325
|
-
'IL': np.array([7., 7.]),
|
|
1326
|
-
'I_expected': np.array([7., 3.])
|
|
1327
|
-
},
|
|
1328
|
-
{ # Can handle mixed inputs with a rank-2 array with zero series
|
|
1329
|
-
# resistance, Rs=0 gives I=IL=Isc at V=0
|
|
1330
|
-
'Rsh': np.array([20.]),
|
|
1331
|
-
'Rs': np.array([[0., 0.], [0., 0.]]),
|
|
1332
|
-
'nNsVth': np.array(0.5),
|
|
1333
|
-
'V': 0.,
|
|
1334
|
-
'I0': np.array([6.e-7]),
|
|
1335
|
-
'IL': np.array([7.]),
|
|
1336
|
-
'I_expected': np.array([[7., 7.], [7., 7.]])
|
|
1337
|
-
},
|
|
1338
|
-
{ # Can handle ideal series and shunt, Rsh=inf and Rs=0 give
|
|
1339
|
-
# V_oc = nNsVth*(np.log(IL + I0) - np.log(I0))
|
|
1340
|
-
'Rsh': np.inf,
|
|
1341
|
-
'Rs': 0.,
|
|
1342
|
-
'nNsVth': 0.5,
|
|
1343
|
-
'V': np.array([0., 0.5*(np.log(7. + 6.e-7) - np.log(6.e-7))/2.,
|
|
1344
|
-
0.5*(np.log(7. + 6.e-7) - np.log(6.e-7))]),
|
|
1345
|
-
'I0': 6.e-7,
|
|
1346
|
-
'IL': 7.,
|
|
1347
|
-
'I_expected': np.array([7., 7. - 6.e-7*np.expm1((np.log(7. + 6.e-7) -
|
|
1348
|
-
np.log(6.e-7))/2.), 0.])
|
|
1349
|
-
},
|
|
1350
|
-
{ # Can handle only ideal shunt resistance, no closed form solution
|
|
1351
|
-
'Rsh': np.inf,
|
|
1352
|
-
'Rs': 0.1,
|
|
1353
|
-
'nNsVth': 0.5,
|
|
1354
|
-
'V': 7.5049875193450521,
|
|
1355
|
-
'I0': 6.e-7,
|
|
1356
|
-
'IL': 7.,
|
|
1357
|
-
'I_expected': 3.2244873645510923
|
|
1358
|
-
}])
|
|
1359
|
-
def fixture_i_from_v(request):
|
|
1360
|
-
return request.param
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
@pytest.mark.parametrize(
|
|
1364
|
-
'method, atol', [('lambertw', 1e-11), ('brentq', 1e-11), ('newton', 1e-11)]
|
|
1365
|
-
)
|
|
1366
|
-
def test_i_from_v(fixture_i_from_v, method, atol):
|
|
1367
|
-
# Solution set loaded from fixture
|
|
1368
|
-
Rsh = fixture_i_from_v['Rsh']
|
|
1369
|
-
Rs = fixture_i_from_v['Rs']
|
|
1370
|
-
nNsVth = fixture_i_from_v['nNsVth']
|
|
1371
|
-
V = fixture_i_from_v['V']
|
|
1372
|
-
I0 = fixture_i_from_v['I0']
|
|
1373
|
-
IL = fixture_i_from_v['IL']
|
|
1374
|
-
I_expected = fixture_i_from_v['I_expected']
|
|
1375
|
-
|
|
1376
|
-
current = pvsystem.i_from_v(V, IL, I0, Rs, Rsh, nNsVth, method=method)
|
|
1377
|
-
|
|
1378
|
-
assert isinstance(current, type(I_expected))
|
|
1379
|
-
if isinstance(current, np.ndarray):
|
|
1380
|
-
assert isinstance(current.dtype, type(I_expected.dtype))
|
|
1381
|
-
assert current.shape == I_expected.shape
|
|
1382
|
-
assert_allclose(current, I_expected, atol=atol)
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
def test_PVSystem_i_from_v(mocker):
|
|
1386
|
-
system = pvsystem.PVSystem()
|
|
1387
|
-
m = mocker.patch('pvlib.pvsystem.i_from_v', autospec=True)
|
|
1388
|
-
args = (7.5049875193450521, 7, 6e-7, 0.1, 20, 0.5)
|
|
1389
|
-
system.i_from_v(*args)
|
|
1390
|
-
m.assert_called_once_with(*args)
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
def test_i_from_v_size():
|
|
1394
|
-
with pytest.raises(ValueError):
|
|
1395
|
-
pvsystem.i_from_v([7.5] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5)
|
|
1396
|
-
with pytest.raises(ValueError):
|
|
1397
|
-
pvsystem.i_from_v([7.5] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5,
|
|
1398
|
-
method='brentq')
|
|
1399
|
-
with pytest.raises(ValueError):
|
|
1400
|
-
pvsystem.i_from_v([7.5] * 3, np.array([7., 7.]), 6e-7, 0.1, 20, 0.5,
|
|
1401
|
-
method='newton')
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
def test_v_from_i_size():
|
|
1405
|
-
with pytest.raises(ValueError):
|
|
1406
|
-
pvsystem.v_from_i([3.] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5)
|
|
1407
|
-
with pytest.raises(ValueError):
|
|
1408
|
-
pvsystem.v_from_i([3.] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5,
|
|
1409
|
-
method='brentq')
|
|
1410
|
-
with pytest.raises(ValueError):
|
|
1411
|
-
pvsystem.v_from_i([3.] * 3, np.array([7., 7.]), 6e-7, [0.1], 20, 0.5,
|
|
1412
|
-
method='newton')
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
def test_mpp_floats():
|
|
1416
|
-
"""test max_power_point"""
|
|
1417
|
-
IL, I0, Rs, Rsh, nNsVth = (7, 6e-7, .1, 20, .5)
|
|
1418
|
-
out = pvsystem.max_power_point(IL, I0, Rs, Rsh, nNsVth, method='brentq')
|
|
1419
|
-
expected = {'i_mp': 6.1362673597376753, # 6.1390251797935704, lambertw
|
|
1420
|
-
'v_mp': 6.2243393757884284, # 6.221535886625464, lambertw
|
|
1421
|
-
'p_mp': 38.194210547580511} # 38.194165464983037} lambertw
|
|
1422
|
-
assert isinstance(out, dict)
|
|
1423
|
-
for k, v in out.items():
|
|
1424
|
-
assert np.isclose(v, expected[k])
|
|
1425
|
-
out = pvsystem.max_power_point(IL, I0, Rs, Rsh, nNsVth, method='newton')
|
|
1426
|
-
for k, v in out.items():
|
|
1427
|
-
assert np.isclose(v, expected[k])
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
def test_mpp_recombination():
|
|
1431
|
-
"""test max_power_point"""
|
|
1432
|
-
pvsyst_fs_495 = get_pvsyst_fs_495()
|
|
1433
|
-
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_pvsyst(
|
|
1434
|
-
effective_irradiance=pvsyst_fs_495['irrad_ref'],
|
|
1435
|
-
temp_cell=pvsyst_fs_495['temp_ref'],
|
|
1436
|
-
alpha_sc=pvsyst_fs_495['alpha_sc'],
|
|
1437
|
-
gamma_ref=pvsyst_fs_495['gamma_ref'],
|
|
1438
|
-
mu_gamma=pvsyst_fs_495['mu_gamma'], I_L_ref=pvsyst_fs_495['I_L_ref'],
|
|
1439
|
-
I_o_ref=pvsyst_fs_495['I_o_ref'], R_sh_ref=pvsyst_fs_495['R_sh_ref'],
|
|
1440
|
-
R_sh_0=pvsyst_fs_495['R_sh_0'], R_sh_exp=pvsyst_fs_495['R_sh_exp'],
|
|
1441
|
-
R_s=pvsyst_fs_495['R_s'],
|
|
1442
|
-
cells_in_series=pvsyst_fs_495['cells_in_series'],
|
|
1443
|
-
EgRef=pvsyst_fs_495['EgRef'])
|
|
1444
|
-
out = pvsystem.max_power_point(
|
|
1445
|
-
IL, I0, Rs, Rsh, nNsVth,
|
|
1446
|
-
d2mutau=pvsyst_fs_495['d2mutau'],
|
|
1447
|
-
NsVbi=VOLTAGE_BUILTIN*pvsyst_fs_495['cells_in_series'],
|
|
1448
|
-
method='brentq')
|
|
1449
|
-
expected_imp = pvsyst_fs_495['I_mp_ref']
|
|
1450
|
-
expected_vmp = pvsyst_fs_495['V_mp_ref']
|
|
1451
|
-
expected_pmp = expected_imp*expected_vmp
|
|
1452
|
-
expected = {'i_mp': expected_imp,
|
|
1453
|
-
'v_mp': expected_vmp,
|
|
1454
|
-
'p_mp': expected_pmp}
|
|
1455
|
-
assert isinstance(out, dict)
|
|
1456
|
-
for k, v in out.items():
|
|
1457
|
-
assert np.isclose(v, expected[k], 0.01)
|
|
1458
|
-
out = pvsystem.max_power_point(
|
|
1459
|
-
IL, I0, Rs, Rsh, nNsVth,
|
|
1460
|
-
d2mutau=pvsyst_fs_495['d2mutau'],
|
|
1461
|
-
NsVbi=VOLTAGE_BUILTIN*pvsyst_fs_495['cells_in_series'],
|
|
1462
|
-
method='newton')
|
|
1463
|
-
for k, v in out.items():
|
|
1464
|
-
assert np.isclose(v, expected[k], 0.01)
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
def test_mpp_array():
|
|
1468
|
-
"""test max_power_point"""
|
|
1469
|
-
IL, I0, Rs, Rsh, nNsVth = (np.array([7, 7]), 6e-7, .1, 20, .5)
|
|
1470
|
-
out = pvsystem.max_power_point(IL, I0, Rs, Rsh, nNsVth, method='brentq')
|
|
1471
|
-
expected = {'i_mp': [6.1362673597376753] * 2,
|
|
1472
|
-
'v_mp': [6.2243393757884284] * 2,
|
|
1473
|
-
'p_mp': [38.194210547580511] * 2}
|
|
1474
|
-
assert isinstance(out, dict)
|
|
1475
|
-
for k, v in out.items():
|
|
1476
|
-
assert np.allclose(v, expected[k])
|
|
1477
|
-
out = pvsystem.max_power_point(IL, I0, Rs, Rsh, nNsVth, method='newton')
|
|
1478
|
-
for k, v in out.items():
|
|
1479
|
-
assert np.allclose(v, expected[k])
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
def test_mpp_series():
|
|
1483
|
-
"""test max_power_point"""
|
|
1484
|
-
idx = ['2008-02-17T11:30:00-0800', '2008-02-17T12:30:00-0800']
|
|
1485
|
-
IL, I0, Rs, Rsh, nNsVth = (np.array([7, 7]), 6e-7, .1, 20, .5)
|
|
1486
|
-
IL = pd.Series(IL, index=idx)
|
|
1487
|
-
out = pvsystem.max_power_point(IL, I0, Rs, Rsh, nNsVth, method='brentq')
|
|
1488
|
-
expected = pd.DataFrame({'i_mp': [6.1362673597376753] * 2,
|
|
1489
|
-
'v_mp': [6.2243393757884284] * 2,
|
|
1490
|
-
'p_mp': [38.194210547580511] * 2},
|
|
1491
|
-
index=idx)
|
|
1492
|
-
assert isinstance(out, pd.DataFrame)
|
|
1493
|
-
for k, v in out.items():
|
|
1494
|
-
assert np.allclose(v, expected[k])
|
|
1495
|
-
out = pvsystem.max_power_point(IL, I0, Rs, Rsh, nNsVth, method='newton')
|
|
1496
|
-
for k, v in out.items():
|
|
1497
|
-
assert np.allclose(v, expected[k])
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
def test_singlediode_series(cec_module_params):
|
|
1501
|
-
times = pd.date_range(start='2015-01-01', periods=2, freq='12h')
|
|
1502
|
-
effective_irradiance = pd.Series([0.0, 800.0], index=times)
|
|
1503
|
-
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_desoto(
|
|
1504
|
-
effective_irradiance,
|
|
1505
|
-
temp_cell=25,
|
|
1506
|
-
alpha_sc=cec_module_params['alpha_sc'],
|
|
1507
|
-
a_ref=cec_module_params['a_ref'],
|
|
1508
|
-
I_L_ref=cec_module_params['I_L_ref'],
|
|
1509
|
-
I_o_ref=cec_module_params['I_o_ref'],
|
|
1510
|
-
R_sh_ref=cec_module_params['R_sh_ref'],
|
|
1511
|
-
R_s=cec_module_params['R_s'],
|
|
1512
|
-
EgRef=1.121,
|
|
1513
|
-
dEgdT=-0.0002677
|
|
1514
|
-
)
|
|
1515
|
-
out = pvsystem.singlediode(IL, I0, Rs, Rsh, nNsVth)
|
|
1516
|
-
assert isinstance(out, pd.DataFrame)
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
def test_singlediode_array():
|
|
1520
|
-
# github issue 221
|
|
1521
|
-
photocurrent = np.linspace(0, 10, 11)
|
|
1522
|
-
resistance_shunt = 16
|
|
1523
|
-
resistance_series = 0.094
|
|
1524
|
-
nNsVth = 0.473
|
|
1525
|
-
saturation_current = 1.943e-09
|
|
1526
|
-
|
|
1527
|
-
sd = pvsystem.singlediode(photocurrent, saturation_current,
|
|
1528
|
-
resistance_series, resistance_shunt, nNsVth,
|
|
1529
|
-
method='lambertw')
|
|
1530
|
-
|
|
1531
|
-
expected_i = np.array([
|
|
1532
|
-
0., 0.54614798740338, 1.435026463529, 2.3621366610078, 3.2953968319952,
|
|
1533
|
-
4.2303869378787, 5.1655276691892, 6.1000269648604, 7.0333996177802,
|
|
1534
|
-
7.9653036915959, 8.8954716265647])
|
|
1535
|
-
expected_v = np.array([
|
|
1536
|
-
0., 7.0966259059555, 7.9961986643428, 8.2222496810656, 8.3255927555753,
|
|
1537
|
-
8.3766915453915, 8.3988872440242, 8.4027948807891, 8.3941399580559,
|
|
1538
|
-
8.3763655188855, 8.3517057522791])
|
|
1539
|
-
|
|
1540
|
-
assert_allclose(sd['i_mp'], expected_i, atol=1e-8)
|
|
1541
|
-
assert_allclose(sd['v_mp'], expected_v, atol=1e-8)
|
|
1542
|
-
|
|
1543
|
-
sd = pvsystem.singlediode(photocurrent, saturation_current,
|
|
1544
|
-
resistance_series, resistance_shunt, nNsVth)
|
|
1545
|
-
expected = pvsystem.i_from_v(sd['v_mp'], photocurrent, saturation_current,
|
|
1546
|
-
resistance_series, resistance_shunt, nNsVth,
|
|
1547
|
-
method='lambertw')
|
|
1548
|
-
assert_allclose(sd['i_mp'], expected, atol=1e-8)
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
def test_singlediode_floats():
|
|
1552
|
-
out = pvsystem.singlediode(7., 6.e-7, .1, 20., .5, method='lambertw')
|
|
1553
|
-
expected = {'i_xx': 4.264060478,
|
|
1554
|
-
'i_mp': 6.136267360,
|
|
1555
|
-
'v_oc': 8.106300147,
|
|
1556
|
-
'p_mp': 38.19421055,
|
|
1557
|
-
'i_x': 6.7558815684,
|
|
1558
|
-
'i_sc': 6.965172322,
|
|
1559
|
-
'v_mp': 6.224339375,
|
|
1560
|
-
'i': None,
|
|
1561
|
-
'v': None}
|
|
1562
|
-
assert isinstance(out, dict)
|
|
1563
|
-
for k, v in out.items():
|
|
1564
|
-
if k in ['i', 'v']:
|
|
1565
|
-
assert v is None
|
|
1566
|
-
else:
|
|
1567
|
-
assert_allclose(v, expected[k], atol=1e-6)
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
def test_singlediode_floats_expected():
|
|
1571
|
-
out = pvsystem.singlediode(7., 6e-7, .1, 20., .5, method='lambertw')
|
|
1572
|
-
expected = {'i_xx': 4.264060478,
|
|
1573
|
-
'i_mp': 6.136267360,
|
|
1574
|
-
'v_oc': 8.106300147,
|
|
1575
|
-
'p_mp': 38.19421055,
|
|
1576
|
-
'i_x': 6.7558815684,
|
|
1577
|
-
'i_sc': 6.965172322,
|
|
1578
|
-
'v_mp': 6.224339375}
|
|
1579
|
-
assert isinstance(out, dict)
|
|
1580
|
-
for k, v in out.items():
|
|
1581
|
-
assert_allclose(v, expected[k], atol=1e-6)
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
def test_singlediode_series_expected(cec_module_params):
|
|
1585
|
-
times = pd.date_range(start='2015-06-01', periods=3, freq='6h')
|
|
1586
|
-
effective_irradiance = pd.Series([0.0, 400.0, 800.0], index=times)
|
|
1587
|
-
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_desoto(
|
|
1588
|
-
effective_irradiance,
|
|
1589
|
-
temp_cell=25,
|
|
1590
|
-
alpha_sc=cec_module_params['alpha_sc'],
|
|
1591
|
-
a_ref=cec_module_params['a_ref'],
|
|
1592
|
-
I_L_ref=cec_module_params['I_L_ref'],
|
|
1593
|
-
I_o_ref=cec_module_params['I_o_ref'],
|
|
1594
|
-
R_sh_ref=cec_module_params['R_sh_ref'],
|
|
1595
|
-
R_s=cec_module_params['R_s'],
|
|
1596
|
-
EgRef=1.121,
|
|
1597
|
-
dEgdT=-0.0002677)
|
|
1598
|
-
|
|
1599
|
-
out = pvsystem.singlediode(IL, I0, Rs, Rsh, nNsVth, method='lambertw')
|
|
1600
|
-
|
|
1601
|
-
expected = OrderedDict([('i_sc', array([0., 3.01079860, 6.00726296])),
|
|
1602
|
-
('v_oc', array([0., 9.96959733, 10.29603253])),
|
|
1603
|
-
('i_mp', array([0., 2.656285960, 5.290525645])),
|
|
1604
|
-
('v_mp', array([0., 8.321092255, 8.409413795])),
|
|
1605
|
-
('p_mp', array([0., 22.10320053, 44.49021934])),
|
|
1606
|
-
('i_x', array([0., 2.884132006, 5.746202281])),
|
|
1607
|
-
('i_xx', array([0., 2.052691562, 3.909673879]))])
|
|
1608
|
-
|
|
1609
|
-
for k, v in out.items():
|
|
1610
|
-
assert_allclose(v, expected[k], atol=1e-2)
|
|
1611
|
-
|
|
1612
|
-
out = pvsystem.singlediode(IL, I0, Rs, Rsh, nNsVth)
|
|
1613
|
-
|
|
1614
|
-
expected['i_mp'] = pvsystem.i_from_v(out['v_mp'], IL, I0, Rs, Rsh, nNsVth,
|
|
1615
|
-
method='lambertw')
|
|
1616
|
-
expected['v_mp'] = pvsystem.v_from_i(out['i_mp'], IL, I0, Rs, Rsh, nNsVth,
|
|
1617
|
-
method='lambertw')
|
|
1618
|
-
|
|
1619
|
-
for k, v in out.items():
|
|
1620
|
-
assert_allclose(v, expected[k], atol=1e-6)
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
def test_scale_voltage_current_power():
|
|
1624
|
-
data = pd.DataFrame(
|
|
1625
|
-
np.array([[2, 1.5, 10, 8, 12, 0.5, 1.5]]),
|
|
1626
|
-
columns=['i_sc', 'i_mp', 'v_oc', 'v_mp', 'p_mp', 'i_x', 'i_xx'],
|
|
1627
|
-
index=[0])
|
|
1628
|
-
expected = pd.DataFrame(
|
|
1629
|
-
np.array([[6, 4.5, 20, 16, 72, 1.5, 4.5]]),
|
|
1630
|
-
columns=['i_sc', 'i_mp', 'v_oc', 'v_mp', 'p_mp', 'i_x', 'i_xx'],
|
|
1631
|
-
index=[0])
|
|
1632
|
-
out = pvsystem.scale_voltage_current_power(data, voltage=2, current=3)
|
|
1633
|
-
assert_frame_equal(out, expected, check_less_precise=5)
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
def test_PVSystem_scale_voltage_current_power(mocker):
|
|
1637
|
-
data = None
|
|
1638
|
-
system = pvsystem.PVSystem(modules_per_string=2, strings_per_inverter=3)
|
|
1639
|
-
m = mocker.patch(
|
|
1640
|
-
'pvlib.pvsystem.scale_voltage_current_power', autospec=True)
|
|
1641
|
-
system.scale_voltage_current_power(data)
|
|
1642
|
-
m.assert_called_once_with(data, voltage=2, current=3)
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
def test_PVSystem_multi_scale_voltage_current_power(mocker):
|
|
1646
|
-
data = (1, 2)
|
|
1647
|
-
system = pvsystem.PVSystem(
|
|
1648
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
1649
|
-
modules_per_string=2, strings=3),
|
|
1650
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
1651
|
-
modules_per_string=3, strings=5)]
|
|
1652
|
-
)
|
|
1653
|
-
m = mocker.patch(
|
|
1654
|
-
'pvlib.pvsystem.scale_voltage_current_power', autospec=True
|
|
1655
|
-
)
|
|
1656
|
-
system.scale_voltage_current_power(data)
|
|
1657
|
-
m.assert_has_calls(
|
|
1658
|
-
[mock.call(1, voltage=2, current=3),
|
|
1659
|
-
mock.call(2, voltage=3, current=5)],
|
|
1660
|
-
any_order=True
|
|
1661
|
-
)
|
|
1662
|
-
with pytest.raises(ValueError,
|
|
1663
|
-
match="Length mismatch for per-array parameter"):
|
|
1664
|
-
system.scale_voltage_current_power(None)
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
def test_PVSystem_get_ac_sandia(cec_inverter_parameters, mocker):
|
|
1668
|
-
inv_fun = mocker.spy(inverter, 'sandia')
|
|
1669
|
-
system = pvsystem.PVSystem(
|
|
1670
|
-
inverter=cec_inverter_parameters['Name'],
|
|
1671
|
-
inverter_parameters=cec_inverter_parameters,
|
|
1672
|
-
)
|
|
1673
|
-
vdcs = pd.Series(np.linspace(0, 50, 3))
|
|
1674
|
-
idcs = pd.Series(np.linspace(0, 11, 3))
|
|
1675
|
-
pdcs = idcs * vdcs
|
|
1676
|
-
pacs = system.get_ac('sandia', pdcs, v_dc=vdcs)
|
|
1677
|
-
inv_fun.assert_called_once()
|
|
1678
|
-
assert_series_equal(pacs, pd.Series([-0.020000, 132.004308, 250.000000]))
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
def test_PVSystem_get_ac_sandia_multi(cec_inverter_parameters, mocker):
|
|
1682
|
-
inv_fun = mocker.spy(inverter, 'sandia_multi')
|
|
1683
|
-
system = pvsystem.PVSystem(
|
|
1684
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(0, 180)),
|
|
1685
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180))],
|
|
1686
|
-
inverter=cec_inverter_parameters['Name'],
|
|
1687
|
-
inverter_parameters=cec_inverter_parameters,
|
|
1688
|
-
)
|
|
1689
|
-
vdcs = pd.Series(np.linspace(0, 50, 3))
|
|
1690
|
-
idcs = pd.Series(np.linspace(0, 11, 3)) / 2
|
|
1691
|
-
pdcs = idcs * vdcs
|
|
1692
|
-
pacs = system.get_ac('sandia', (pdcs, pdcs), v_dc=(vdcs, vdcs))
|
|
1693
|
-
inv_fun.assert_called_once()
|
|
1694
|
-
assert_series_equal(pacs, pd.Series([-0.020000, 132.004308, 250.000000]))
|
|
1695
|
-
with pytest.raises(ValueError,
|
|
1696
|
-
match="Length mismatch for per-array parameter"):
|
|
1697
|
-
system.get_ac('sandia', vdcs, (pdcs, pdcs))
|
|
1698
|
-
with pytest.raises(ValueError,
|
|
1699
|
-
match="Length mismatch for per-array parameter"):
|
|
1700
|
-
system.get_ac('sandia', vdcs, (pdcs,))
|
|
1701
|
-
with pytest.raises(ValueError,
|
|
1702
|
-
match="Length mismatch for per-array parameter"):
|
|
1703
|
-
system.get_ac('sandia', (vdcs, vdcs), (pdcs, pdcs, pdcs))
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
def test_PVSystem_get_ac_pvwatts(pvwatts_system_defaults, mocker):
|
|
1707
|
-
mocker.spy(inverter, 'pvwatts')
|
|
1708
|
-
pdc = 50
|
|
1709
|
-
out = pvwatts_system_defaults.get_ac('pvwatts', pdc)
|
|
1710
|
-
inverter.pvwatts.assert_called_once_with(
|
|
1711
|
-
pdc, **pvwatts_system_defaults.inverter_parameters)
|
|
1712
|
-
assert out < pdc
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
def test_PVSystem_get_ac_pvwatts_kwargs(pvwatts_system_kwargs, mocker):
|
|
1716
|
-
mocker.spy(inverter, 'pvwatts')
|
|
1717
|
-
pdc = 50
|
|
1718
|
-
out = pvwatts_system_kwargs.get_ac('pvwatts', pdc)
|
|
1719
|
-
inverter.pvwatts.assert_called_once_with(
|
|
1720
|
-
pdc, **pvwatts_system_kwargs.inverter_parameters)
|
|
1721
|
-
assert out < pdc
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
def test_PVSystem_get_ac_pvwatts_multi(
|
|
1725
|
-
pvwatts_system_defaults, pvwatts_system_kwargs, mocker):
|
|
1726
|
-
mocker.spy(inverter, 'pvwatts_multi')
|
|
1727
|
-
expected = [pd.Series([0.0, 48.123524, 86.400000]),
|
|
1728
|
-
pd.Series([0.0, 45.893550, 85.500000])]
|
|
1729
|
-
systems = [pvwatts_system_defaults, pvwatts_system_kwargs]
|
|
1730
|
-
for base_sys, exp in zip(systems, expected):
|
|
1731
|
-
system = pvsystem.PVSystem(
|
|
1732
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(0, 180)),
|
|
1733
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180),)],
|
|
1734
|
-
inverter_parameters=base_sys.inverter_parameters,
|
|
1735
|
-
)
|
|
1736
|
-
pdcs = pd.Series([0., 25., 50.])
|
|
1737
|
-
pacs = system.get_ac('pvwatts', (pdcs, pdcs))
|
|
1738
|
-
assert_series_equal(pacs, exp)
|
|
1739
|
-
assert inverter.pvwatts_multi.call_count == 2
|
|
1740
|
-
with pytest.raises(ValueError,
|
|
1741
|
-
match="Length mismatch for per-array parameter"):
|
|
1742
|
-
system.get_ac('pvwatts', (pdcs,))
|
|
1743
|
-
with pytest.raises(ValueError,
|
|
1744
|
-
match="Length mismatch for per-array parameter"):
|
|
1745
|
-
system.get_ac('pvwatts', pdcs)
|
|
1746
|
-
with pytest.raises(ValueError,
|
|
1747
|
-
match="Length mismatch for per-array parameter"):
|
|
1748
|
-
system.get_ac('pvwatts', (pdcs, pdcs, pdcs))
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
@pytest.mark.parametrize('model', ['sandia', 'adr', 'pvwatts'])
|
|
1752
|
-
def test_PVSystem_get_ac_single_array_tuple_input(
|
|
1753
|
-
model,
|
|
1754
|
-
pvwatts_system_defaults,
|
|
1755
|
-
cec_inverter_parameters,
|
|
1756
|
-
adr_inverter_parameters):
|
|
1757
|
-
vdcs = {
|
|
1758
|
-
'sandia': pd.Series(np.linspace(0, 50, 3)),
|
|
1759
|
-
'pvwatts': None,
|
|
1760
|
-
'adr': pd.Series([135, 154, 390, 420, 551])
|
|
1761
|
-
}
|
|
1762
|
-
pdcs = {'adr': pd.Series([135, 1232, 1170, 420, 551]),
|
|
1763
|
-
'sandia': pd.Series(np.linspace(0, 11, 3)) * vdcs['sandia'],
|
|
1764
|
-
'pvwatts': 50}
|
|
1765
|
-
inverter_parameters = {
|
|
1766
|
-
'sandia': cec_inverter_parameters,
|
|
1767
|
-
'adr': adr_inverter_parameters,
|
|
1768
|
-
'pvwatts': pvwatts_system_defaults.inverter_parameters
|
|
1769
|
-
}
|
|
1770
|
-
expected = {
|
|
1771
|
-
'adr': pd.Series([np.nan, 1161.5745, 1116.4459, 382.6679, np.nan]),
|
|
1772
|
-
'sandia': pd.Series([-0.020000, 132.004308, 250.000000])
|
|
1773
|
-
}
|
|
1774
|
-
system = pvsystem.PVSystem(
|
|
1775
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(0, 180))],
|
|
1776
|
-
inverter_parameters=inverter_parameters[model]
|
|
1777
|
-
)
|
|
1778
|
-
ac = system.get_ac(p_dc=(pdcs[model],), v_dc=(vdcs[model],), model=model)
|
|
1779
|
-
if model == 'pvwatts':
|
|
1780
|
-
assert ac < pdcs['pvwatts']
|
|
1781
|
-
else:
|
|
1782
|
-
assert_series_equal(ac, expected[model])
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
def test_PVSystem_get_ac_adr(adr_inverter_parameters, mocker):
|
|
1786
|
-
mocker.spy(inverter, 'adr')
|
|
1787
|
-
system = pvsystem.PVSystem(
|
|
1788
|
-
inverter_parameters=adr_inverter_parameters,
|
|
1789
|
-
)
|
|
1790
|
-
vdcs = pd.Series([135, 154, 390, 420, 551])
|
|
1791
|
-
pdcs = pd.Series([135, 1232, 1170, 420, 551])
|
|
1792
|
-
pacs = system.get_ac('adr', pdcs, vdcs)
|
|
1793
|
-
assert_series_equal(pacs, pd.Series([np.nan, 1161.5745, 1116.4459,
|
|
1794
|
-
382.6679, np.nan]))
|
|
1795
|
-
inverter.adr.assert_called_once_with(vdcs, pdcs,
|
|
1796
|
-
system.inverter_parameters)
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
def test_PVSystem_get_ac_adr_multi(adr_inverter_parameters):
|
|
1800
|
-
system = pvsystem.PVSystem(
|
|
1801
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(0, 180)),
|
|
1802
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180))],
|
|
1803
|
-
inverter_parameters=adr_inverter_parameters,
|
|
1804
|
-
)
|
|
1805
|
-
pdcs = pd.Series([135, 1232, 1170, 420, 551])
|
|
1806
|
-
with pytest.raises(ValueError,
|
|
1807
|
-
match="The adr inverter function cannot be used"):
|
|
1808
|
-
system.get_ac(model='adr', p_dc=pdcs)
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
def test_PVSystem_get_ac_invalid(cec_inverter_parameters):
|
|
1812
|
-
system = pvsystem.PVSystem(
|
|
1813
|
-
inverter_parameters=cec_inverter_parameters,
|
|
1814
|
-
)
|
|
1815
|
-
pdcs = pd.Series(np.linspace(0, 50, 3))
|
|
1816
|
-
with pytest.raises(ValueError, match="is not a valid AC power model"):
|
|
1817
|
-
system.get_ac(model='not_a_model', p_dc=pdcs)
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
def test_PVSystem_creation():
|
|
1821
|
-
pv_system = pvsystem.PVSystem(module='blah', inverter='blarg')
|
|
1822
|
-
# ensure that parameter attributes are dict-like. GH 294
|
|
1823
|
-
pv_system.inverter_parameters['Paco'] = 1
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
def test_PVSystem_multiple_array_creation():
|
|
1827
|
-
array_one = pvsystem.Array(pvsystem.FixedMount(surface_tilt=32))
|
|
1828
|
-
array_two = pvsystem.Array(pvsystem.FixedMount(surface_tilt=15),
|
|
1829
|
-
module_parameters={'pdc0': 1})
|
|
1830
|
-
pv_system = pvsystem.PVSystem(arrays=[array_one, array_two])
|
|
1831
|
-
assert pv_system.arrays[0].module_parameters == {}
|
|
1832
|
-
assert pv_system.arrays[1].module_parameters == {'pdc0': 1}
|
|
1833
|
-
assert pv_system.arrays == (array_one, array_two)
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
def test_PVSystem_get_aoi():
|
|
1837
|
-
system = pvsystem.PVSystem(surface_tilt=32, surface_azimuth=135)
|
|
1838
|
-
aoi = system.get_aoi(30, 225)
|
|
1839
|
-
assert np.round(aoi, 4) == 42.7408
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
def test_PVSystem_multiple_array_get_aoi():
|
|
1843
|
-
system = pvsystem.PVSystem(
|
|
1844
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(surface_tilt=15,
|
|
1845
|
-
surface_azimuth=135)),
|
|
1846
|
-
pvsystem.Array(pvsystem.FixedMount(surface_tilt=32,
|
|
1847
|
-
surface_azimuth=135))]
|
|
1848
|
-
)
|
|
1849
|
-
aoi_one, aoi_two = system.get_aoi(30, 225)
|
|
1850
|
-
assert np.round(aoi_two, 4) == 42.7408
|
|
1851
|
-
assert aoi_two != aoi_one
|
|
1852
|
-
assert aoi_one > 0
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
@pytest.fixture
|
|
1856
|
-
def solar_pos():
|
|
1857
|
-
times = pd.date_range(start='20160101 1200-0700',
|
|
1858
|
-
end='20160101 1800-0700', freq='6h')
|
|
1859
|
-
location = Location(latitude=32, longitude=-111)
|
|
1860
|
-
return location.get_solarposition(times)
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
def test_PVSystem_get_irradiance(solar_pos):
|
|
1864
|
-
system = pvsystem.PVSystem(surface_tilt=32, surface_azimuth=135)
|
|
1865
|
-
irrads = pd.DataFrame({'dni':[900,0], 'ghi':[600,0], 'dhi':[100,0]},
|
|
1866
|
-
index=solar_pos.index)
|
|
1867
|
-
|
|
1868
|
-
irradiance = system.get_irradiance(solar_pos['apparent_zenith'],
|
|
1869
|
-
solar_pos['azimuth'],
|
|
1870
|
-
irrads['dni'],
|
|
1871
|
-
irrads['ghi'],
|
|
1872
|
-
irrads['dhi'])
|
|
1873
|
-
|
|
1874
|
-
expected = pd.DataFrame(data=np.array(
|
|
1875
|
-
[[883.65494055, 745.86141676, 137.79352379, 126.397131, 11.39639279],
|
|
1876
|
-
[0., -0., 0., 0., 0.]]),
|
|
1877
|
-
columns=['poa_global', 'poa_direct',
|
|
1878
|
-
'poa_diffuse', 'poa_sky_diffuse',
|
|
1879
|
-
'poa_ground_diffuse'],
|
|
1880
|
-
index=solar_pos.index)
|
|
1881
|
-
assert_frame_equal(irradiance, expected, check_less_precise=2)
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
def test_PVSystem_get_irradiance_albedo(solar_pos):
|
|
1885
|
-
system = pvsystem.PVSystem(surface_tilt=32, surface_azimuth=135)
|
|
1886
|
-
irrads = pd.DataFrame({'dni': [900, 0], 'ghi': [600, 0], 'dhi': [100, 0],
|
|
1887
|
-
'albedo': [0.5, 0.5]},
|
|
1888
|
-
index=solar_pos.index)
|
|
1889
|
-
# albedo as a Series
|
|
1890
|
-
irradiance = system.get_irradiance(solar_pos['apparent_zenith'],
|
|
1891
|
-
solar_pos['azimuth'],
|
|
1892
|
-
irrads['dni'],
|
|
1893
|
-
irrads['ghi'],
|
|
1894
|
-
irrads['dhi'],
|
|
1895
|
-
albedo=irrads['albedo'])
|
|
1896
|
-
expected = pd.DataFrame(data=np.array(
|
|
1897
|
-
[[895.05134334, 745.86141676, 149.18992658, 126.397131, 22.79279558],
|
|
1898
|
-
[0., -0., 0., 0., 0.]]),
|
|
1899
|
-
columns=['poa_global', 'poa_direct', 'poa_diffuse', 'poa_sky_diffuse',
|
|
1900
|
-
'poa_ground_diffuse'],
|
|
1901
|
-
index=solar_pos.index)
|
|
1902
|
-
assert_frame_equal(irradiance, expected, check_less_precise=2)
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
def test_PVSystem_get_irradiance_model(mocker, solar_pos):
|
|
1906
|
-
spy_perez = mocker.spy(irradiance, 'perez')
|
|
1907
|
-
spy_haydavies = mocker.spy(irradiance, 'haydavies')
|
|
1908
|
-
system = pvsystem.PVSystem(surface_tilt=32, surface_azimuth=135)
|
|
1909
|
-
irrads = pd.DataFrame({'dni': [900, 0], 'ghi': [600, 0], 'dhi': [100, 0]},
|
|
1910
|
-
index=solar_pos.index)
|
|
1911
|
-
system.get_irradiance(solar_pos['apparent_zenith'],
|
|
1912
|
-
solar_pos['azimuth'],
|
|
1913
|
-
irrads['dni'],
|
|
1914
|
-
irrads['ghi'],
|
|
1915
|
-
irrads['dhi'])
|
|
1916
|
-
spy_haydavies.assert_called_once()
|
|
1917
|
-
system.get_irradiance(solar_pos['apparent_zenith'],
|
|
1918
|
-
solar_pos['azimuth'],
|
|
1919
|
-
irrads['dni'],
|
|
1920
|
-
irrads['ghi'],
|
|
1921
|
-
irrads['dhi'],
|
|
1922
|
-
model='perez')
|
|
1923
|
-
spy_perez.assert_called_once()
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
def test_PVSystem_multi_array_get_irradiance(solar_pos):
|
|
1927
|
-
array_one = pvsystem.Array(pvsystem.FixedMount(surface_tilt=32,
|
|
1928
|
-
surface_azimuth=135))
|
|
1929
|
-
array_two = pvsystem.Array(pvsystem.FixedMount(surface_tilt=5,
|
|
1930
|
-
surface_azimuth=150))
|
|
1931
|
-
system = pvsystem.PVSystem(arrays=[array_one, array_two])
|
|
1932
|
-
|
|
1933
|
-
irrads = pd.DataFrame({'dni': [900, 0], 'ghi': [600, 0], 'dhi': [100, 0]},
|
|
1934
|
-
index=solar_pos.index)
|
|
1935
|
-
array_one_expected = array_one.get_irradiance(
|
|
1936
|
-
solar_pos['apparent_zenith'],
|
|
1937
|
-
solar_pos['azimuth'],
|
|
1938
|
-
irrads['dni'], irrads['ghi'], irrads['dhi']
|
|
1939
|
-
)
|
|
1940
|
-
array_two_expected = array_two.get_irradiance(
|
|
1941
|
-
solar_pos['apparent_zenith'],
|
|
1942
|
-
solar_pos['azimuth'],
|
|
1943
|
-
irrads['dni'], irrads['ghi'], irrads['dhi']
|
|
1944
|
-
)
|
|
1945
|
-
array_one_irrad, array_two_irrad = system.get_irradiance(
|
|
1946
|
-
solar_pos['apparent_zenith'],
|
|
1947
|
-
solar_pos['azimuth'],
|
|
1948
|
-
irrads['dni'], irrads['ghi'], irrads['dhi']
|
|
1949
|
-
)
|
|
1950
|
-
assert_frame_equal(
|
|
1951
|
-
array_one_irrad, array_one_expected, check_less_precise=2
|
|
1952
|
-
)
|
|
1953
|
-
assert_frame_equal(
|
|
1954
|
-
array_two_irrad, array_two_expected, check_less_precise=2
|
|
1955
|
-
)
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
def test_PVSystem_multi_array_get_irradiance_multi_irrad(solar_pos):
|
|
1959
|
-
"""Test a system with two identical arrays but different irradiance.
|
|
1960
|
-
|
|
1961
|
-
Because only the irradiance is different we expect the same output
|
|
1962
|
-
when only one GHI/DHI/DNI input is given, but different output
|
|
1963
|
-
for each array when different GHI/DHI/DNI input is given. For the later
|
|
1964
|
-
case we verify that the correct irradiance data is passed to each array.
|
|
1965
|
-
"""
|
|
1966
|
-
array_one = pvsystem.Array(pvsystem.FixedMount(0, 180))
|
|
1967
|
-
array_two = pvsystem.Array(pvsystem.FixedMount(0, 180))
|
|
1968
|
-
system = pvsystem.PVSystem(arrays=[array_one, array_two])
|
|
1969
|
-
|
|
1970
|
-
irrads = pd.DataFrame({'dni': [900, 0], 'ghi': [600, 0], 'dhi': [100, 0]},
|
|
1971
|
-
index=solar_pos.index)
|
|
1972
|
-
irrads_two = pd.DataFrame(
|
|
1973
|
-
{'dni': [0, 900], 'ghi': [0, 600], 'dhi': [0, 100]},
|
|
1974
|
-
index=solar_pos.index
|
|
1975
|
-
)
|
|
1976
|
-
array_irrad = system.get_irradiance(
|
|
1977
|
-
solar_pos['apparent_zenith'],
|
|
1978
|
-
solar_pos['azimuth'],
|
|
1979
|
-
(irrads['dhi'], irrads['dhi']),
|
|
1980
|
-
(irrads['ghi'], irrads['ghi']),
|
|
1981
|
-
(irrads['dni'], irrads['dni'])
|
|
1982
|
-
)
|
|
1983
|
-
assert_frame_equal(array_irrad[0], array_irrad[1])
|
|
1984
|
-
array_irrad = system.get_irradiance(
|
|
1985
|
-
solar_pos['apparent_zenith'],
|
|
1986
|
-
solar_pos['azimuth'],
|
|
1987
|
-
(irrads['dhi'], irrads_two['dhi']),
|
|
1988
|
-
(irrads['ghi'], irrads_two['ghi']),
|
|
1989
|
-
(irrads['dni'], irrads_two['dni'])
|
|
1990
|
-
)
|
|
1991
|
-
array_one_expected = array_one.get_irradiance(
|
|
1992
|
-
solar_pos['apparent_zenith'],
|
|
1993
|
-
solar_pos['azimuth'],
|
|
1994
|
-
irrads['dhi'], irrads['ghi'], irrads['dni']
|
|
1995
|
-
)
|
|
1996
|
-
array_two_expected = array_two.get_irradiance(
|
|
1997
|
-
solar_pos['apparent_zenith'],
|
|
1998
|
-
solar_pos['azimuth'],
|
|
1999
|
-
irrads_two['dhi'], irrads_two['ghi'], irrads_two['dni']
|
|
2000
|
-
)
|
|
2001
|
-
assert not array_irrad[0].equals(array_irrad[1])
|
|
2002
|
-
assert_frame_equal(array_irrad[0], array_one_expected)
|
|
2003
|
-
assert_frame_equal(array_irrad[1], array_two_expected)
|
|
2004
|
-
with pytest.raises(ValueError,
|
|
2005
|
-
match="Length mismatch for per-array parameter"):
|
|
2006
|
-
system.get_irradiance(
|
|
2007
|
-
solar_pos['apparent_zenith'],
|
|
2008
|
-
solar_pos['azimuth'],
|
|
2009
|
-
(irrads['dhi'], irrads_two['dhi'], irrads['dhi']),
|
|
2010
|
-
(irrads['ghi'], irrads_two['ghi']),
|
|
2011
|
-
irrads['dni']
|
|
2012
|
-
)
|
|
2013
|
-
array_irrad = system.get_irradiance(
|
|
2014
|
-
solar_pos['apparent_zenith'],
|
|
2015
|
-
solar_pos['azimuth'],
|
|
2016
|
-
(irrads['dhi'], irrads_two['dhi']),
|
|
2017
|
-
irrads['ghi'],
|
|
2018
|
-
irrads['dni']
|
|
2019
|
-
)
|
|
2020
|
-
assert_frame_equal(array_irrad[0], array_one_expected)
|
|
2021
|
-
assert not array_irrad[0].equals(array_irrad[1])
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
def test_Array_get_irradiance(solar_pos):
|
|
2025
|
-
array = pvsystem.Array(pvsystem.FixedMount(surface_tilt=32,
|
|
2026
|
-
surface_azimuth=135))
|
|
2027
|
-
irrads = pd.DataFrame({'dni': [900, 0], 'ghi': [600, 0], 'dhi': [100, 0]},
|
|
2028
|
-
index=solar_pos.index)
|
|
2029
|
-
# defaults for kwargs
|
|
2030
|
-
modeled = array.get_irradiance(
|
|
2031
|
-
solar_pos['apparent_zenith'],
|
|
2032
|
-
solar_pos['azimuth'],
|
|
2033
|
-
irrads['dni'], irrads['ghi'], irrads['dhi']
|
|
2034
|
-
)
|
|
2035
|
-
expected = pd.DataFrame(
|
|
2036
|
-
data=np.array(
|
|
2037
|
-
[[883.65494055, 745.86141676, 137.79352379, 126.397131,
|
|
2038
|
-
11.39639279],
|
|
2039
|
-
[0., -0., 0., 0., 0.]]),
|
|
2040
|
-
columns=['poa_global', 'poa_direct', 'poa_diffuse', 'poa_sky_diffuse',
|
|
2041
|
-
'poa_ground_diffuse'],
|
|
2042
|
-
index=solar_pos.index
|
|
2043
|
-
)
|
|
2044
|
-
assert_frame_equal(modeled, expected, check_less_precise=5)
|
|
2045
|
-
# with specified kwargs, use isotropic sky diffuse because it's easier
|
|
2046
|
-
modeled = array.get_irradiance(
|
|
2047
|
-
solar_pos['apparent_zenith'],
|
|
2048
|
-
solar_pos['azimuth'],
|
|
2049
|
-
irrads['dni'], irrads['ghi'], irrads['dhi'],
|
|
2050
|
-
albedo=0.5, model='isotropic'
|
|
2051
|
-
)
|
|
2052
|
-
sky_diffuse = irradiance.isotropic(array.mount.surface_tilt, irrads['dhi'])
|
|
2053
|
-
ground_diff = irradiance.get_ground_diffuse(
|
|
2054
|
-
array.mount.surface_tilt, irrads['ghi'], 0.5, surface_type=None)
|
|
2055
|
-
aoi = irradiance.aoi(array.mount.surface_tilt, array.mount.surface_azimuth,
|
|
2056
|
-
solar_pos['apparent_zenith'], solar_pos['azimuth'])
|
|
2057
|
-
direct = irrads['dni'] * cosd(aoi)
|
|
2058
|
-
expected = sky_diffuse + ground_diff + direct
|
|
2059
|
-
assert_series_equal(expected, expected, check_less_precise=5)
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
def test_PVSystem___repr__():
|
|
2063
|
-
system = pvsystem.PVSystem(
|
|
2064
|
-
module='blah', inverter='blarg', name='pv ftw',
|
|
2065
|
-
temperature_model_parameters={'a': -3.56})
|
|
2066
|
-
|
|
2067
|
-
expected = """PVSystem:
|
|
2068
|
-
name: pv ftw
|
|
2069
|
-
Array:
|
|
2070
|
-
name: None
|
|
2071
|
-
mount: FixedMount(surface_tilt=0, surface_azimuth=180, racking_model=None, module_height=None)
|
|
2072
|
-
module: blah
|
|
2073
|
-
albedo: 0.25
|
|
2074
|
-
module_type: None
|
|
2075
|
-
temperature_model_parameters: {'a': -3.56}
|
|
2076
|
-
strings: 1
|
|
2077
|
-
modules_per_string: 1
|
|
2078
|
-
inverter: blarg""" # noqa: E501
|
|
2079
|
-
assert system.__repr__() == expected
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
def test_PVSystem_multi_array___repr__():
|
|
2083
|
-
system = pvsystem.PVSystem(
|
|
2084
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(surface_tilt=30,
|
|
2085
|
-
surface_azimuth=100)),
|
|
2086
|
-
pvsystem.Array(pvsystem.FixedMount(surface_tilt=20,
|
|
2087
|
-
surface_azimuth=220),
|
|
2088
|
-
name='foo')],
|
|
2089
|
-
inverter='blarg',
|
|
2090
|
-
)
|
|
2091
|
-
expected = """PVSystem:
|
|
2092
|
-
name: None
|
|
2093
|
-
Array:
|
|
2094
|
-
name: None
|
|
2095
|
-
mount: FixedMount(surface_tilt=30, surface_azimuth=100, racking_model=None, module_height=None)
|
|
2096
|
-
module: None
|
|
2097
|
-
albedo: 0.25
|
|
2098
|
-
module_type: None
|
|
2099
|
-
temperature_model_parameters: {}
|
|
2100
|
-
strings: 1
|
|
2101
|
-
modules_per_string: 1
|
|
2102
|
-
Array:
|
|
2103
|
-
name: foo
|
|
2104
|
-
mount: FixedMount(surface_tilt=20, surface_azimuth=220, racking_model=None, module_height=None)
|
|
2105
|
-
module: None
|
|
2106
|
-
albedo: 0.25
|
|
2107
|
-
module_type: None
|
|
2108
|
-
temperature_model_parameters: {}
|
|
2109
|
-
strings: 1
|
|
2110
|
-
modules_per_string: 1
|
|
2111
|
-
inverter: blarg""" # noqa: E501
|
|
2112
|
-
assert expected == system.__repr__()
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
def test_Array___repr__():
|
|
2116
|
-
array = pvsystem.Array(
|
|
2117
|
-
mount=pvsystem.FixedMount(surface_tilt=10, surface_azimuth=100,
|
|
2118
|
-
racking_model='close_mount'),
|
|
2119
|
-
albedo=0.15, module_type='glass_glass',
|
|
2120
|
-
temperature_model_parameters={'a': -3.56},
|
|
2121
|
-
module_parameters={'foo': 'bar'},
|
|
2122
|
-
modules_per_string=100,
|
|
2123
|
-
strings=10, module='baz',
|
|
2124
|
-
name='biz'
|
|
2125
|
-
)
|
|
2126
|
-
expected = """Array:
|
|
2127
|
-
name: biz
|
|
2128
|
-
mount: FixedMount(surface_tilt=10, surface_azimuth=100, racking_model='close_mount', module_height=None)
|
|
2129
|
-
module: baz
|
|
2130
|
-
albedo: 0.15
|
|
2131
|
-
module_type: glass_glass
|
|
2132
|
-
temperature_model_parameters: {'a': -3.56}
|
|
2133
|
-
strings: 10
|
|
2134
|
-
modules_per_string: 100""" # noqa: E501
|
|
2135
|
-
assert array.__repr__() == expected
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
def test_pvwatts_dc_scalars():
|
|
2139
|
-
expected = 88.65
|
|
2140
|
-
out = pvsystem.pvwatts_dc(900, 30, 100, -0.003)
|
|
2141
|
-
assert_allclose(out, expected)
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
def test_pvwatts_dc_arrays():
|
|
2145
|
-
irrad_trans = np.array([np.nan, 900, 900])
|
|
2146
|
-
temp_cell = np.array([30, np.nan, 30])
|
|
2147
|
-
irrad_trans, temp_cell = np.meshgrid(irrad_trans, temp_cell)
|
|
2148
|
-
expected = np.array([[nan, 88.65, 88.65],
|
|
2149
|
-
[nan, nan, nan],
|
|
2150
|
-
[nan, 88.65, 88.65]])
|
|
2151
|
-
out = pvsystem.pvwatts_dc(irrad_trans, temp_cell, 100, -0.003)
|
|
2152
|
-
assert_allclose(out, expected, equal_nan=True)
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
def test_pvwatts_dc_series():
|
|
2156
|
-
irrad_trans = pd.Series([np.nan, 900, 900])
|
|
2157
|
-
temp_cell = pd.Series([30, np.nan, 30])
|
|
2158
|
-
expected = pd.Series(np.array([ nan, nan, 88.65]))
|
|
2159
|
-
out = pvsystem.pvwatts_dc(irrad_trans, temp_cell, 100, -0.003)
|
|
2160
|
-
assert_series_equal(expected, out)
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
def test_pvwatts_losses_default():
|
|
2164
|
-
expected = 14.075660688264469
|
|
2165
|
-
out = pvsystem.pvwatts_losses()
|
|
2166
|
-
assert_allclose(out, expected)
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
def test_pvwatts_losses_arrays():
|
|
2170
|
-
expected = np.array([nan, 14.934904])
|
|
2171
|
-
age = np.array([nan, 1])
|
|
2172
|
-
out = pvsystem.pvwatts_losses(age=age)
|
|
2173
|
-
assert_allclose(out, expected)
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
def test_pvwatts_losses_series():
|
|
2177
|
-
expected = pd.Series([nan, 14.934904])
|
|
2178
|
-
age = pd.Series([nan, 1])
|
|
2179
|
-
out = pvsystem.pvwatts_losses(age=age)
|
|
2180
|
-
assert_series_equal(expected, out)
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
@pytest.fixture
|
|
2184
|
-
def pvwatts_system_defaults():
|
|
2185
|
-
module_parameters = {'pdc0': 100, 'gamma_pdc': -0.003}
|
|
2186
|
-
inverter_parameters = {'pdc0': 90}
|
|
2187
|
-
system = pvsystem.PVSystem(module_parameters=module_parameters,
|
|
2188
|
-
inverter_parameters=inverter_parameters)
|
|
2189
|
-
return system
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
@pytest.fixture
|
|
2193
|
-
def pvwatts_system_kwargs():
|
|
2194
|
-
module_parameters = {'pdc0': 100, 'gamma_pdc': -0.003, 'temp_ref': 20}
|
|
2195
|
-
inverter_parameters = {'pdc0': 90, 'eta_inv_nom': 0.95, 'eta_inv_ref': 1.0}
|
|
2196
|
-
system = pvsystem.PVSystem(module_parameters=module_parameters,
|
|
2197
|
-
inverter_parameters=inverter_parameters)
|
|
2198
|
-
return system
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
def test_PVSystem_pvwatts_dc(pvwatts_system_defaults, mocker):
|
|
2202
|
-
mocker.spy(pvsystem, 'pvwatts_dc')
|
|
2203
|
-
irrad = 900
|
|
2204
|
-
temp_cell = 30
|
|
2205
|
-
expected = 90
|
|
2206
|
-
out = pvwatts_system_defaults.pvwatts_dc(irrad, temp_cell)
|
|
2207
|
-
pvsystem.pvwatts_dc.assert_called_once_with(
|
|
2208
|
-
irrad, temp_cell,
|
|
2209
|
-
**pvwatts_system_defaults.arrays[0].module_parameters)
|
|
2210
|
-
assert_allclose(expected, out, atol=10)
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
def test_PVSystem_pvwatts_dc_kwargs(pvwatts_system_kwargs, mocker):
|
|
2214
|
-
mocker.spy(pvsystem, 'pvwatts_dc')
|
|
2215
|
-
irrad = 900
|
|
2216
|
-
temp_cell = 30
|
|
2217
|
-
expected = 90
|
|
2218
|
-
out = pvwatts_system_kwargs.pvwatts_dc(irrad, temp_cell)
|
|
2219
|
-
pvsystem.pvwatts_dc.assert_called_once_with(
|
|
2220
|
-
irrad, temp_cell, **pvwatts_system_kwargs.arrays[0].module_parameters)
|
|
2221
|
-
assert_allclose(expected, out, atol=10)
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
def test_PVSystem_multiple_array_pvwatts_dc():
|
|
2225
|
-
array_one_module_parameters = {
|
|
2226
|
-
'pdc0': 100, 'gamma_pdc': -0.003, 'temp_ref': 20
|
|
2227
|
-
}
|
|
2228
|
-
array_one = pvsystem.Array(
|
|
2229
|
-
pvsystem.FixedMount(0, 180),
|
|
2230
|
-
module_parameters=array_one_module_parameters
|
|
2231
|
-
)
|
|
2232
|
-
array_two_module_parameters = {
|
|
2233
|
-
'pdc0': 150, 'gamma_pdc': -0.002, 'temp_ref': 25
|
|
2234
|
-
}
|
|
2235
|
-
array_two = pvsystem.Array(
|
|
2236
|
-
pvsystem.FixedMount(0, 180),
|
|
2237
|
-
module_parameters=array_two_module_parameters
|
|
2238
|
-
)
|
|
2239
|
-
system = pvsystem.PVSystem(arrays=[array_one, array_two])
|
|
2240
|
-
irrad_one = 900
|
|
2241
|
-
irrad_two = 500
|
|
2242
|
-
temp_cell_one = 30
|
|
2243
|
-
temp_cell_two = 20
|
|
2244
|
-
expected_one = pvsystem.pvwatts_dc(irrad_one, temp_cell_one,
|
|
2245
|
-
**array_one_module_parameters)
|
|
2246
|
-
expected_two = pvsystem.pvwatts_dc(irrad_two, temp_cell_two,
|
|
2247
|
-
**array_two_module_parameters)
|
|
2248
|
-
dc_one, dc_two = system.pvwatts_dc((irrad_one, irrad_two),
|
|
2249
|
-
(temp_cell_one, temp_cell_two))
|
|
2250
|
-
assert dc_one == expected_one
|
|
2251
|
-
assert dc_two == expected_two
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
def test_PVSystem_multiple_array_pvwatts_dc_value_error():
|
|
2255
|
-
system = pvsystem.PVSystem(
|
|
2256
|
-
arrays=[pvsystem.Array(pvsystem.FixedMount(0, 180)),
|
|
2257
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180)),
|
|
2258
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180))]
|
|
2259
|
-
)
|
|
2260
|
-
error_message = 'Length mismatch for per-array parameter'
|
|
2261
|
-
with pytest.raises(ValueError, match=error_message):
|
|
2262
|
-
system.pvwatts_dc(10, (1, 1, 1))
|
|
2263
|
-
with pytest.raises(ValueError, match=error_message):
|
|
2264
|
-
system.pvwatts_dc((10, 10), (1, 1, 1))
|
|
2265
|
-
with pytest.raises(ValueError, match=error_message):
|
|
2266
|
-
system.pvwatts_dc((10, 10, 10, 10), (1, 1, 1))
|
|
2267
|
-
with pytest.raises(ValueError, match=error_message):
|
|
2268
|
-
system.pvwatts_dc((1, 1, 1), 1)
|
|
2269
|
-
with pytest.raises(ValueError, match=error_message):
|
|
2270
|
-
system.pvwatts_dc((1, 1, 1), (1,))
|
|
2271
|
-
with pytest.raises(ValueError, match=error_message):
|
|
2272
|
-
system.pvwatts_dc((1,), 1)
|
|
2273
|
-
with pytest.raises(ValueError, match=error_message):
|
|
2274
|
-
system.pvwatts_dc((1, 1, 1, 1), (1, 1))
|
|
2275
|
-
with pytest.raises(ValueError, match=error_message):
|
|
2276
|
-
system.pvwatts_dc(2, 3)
|
|
2277
|
-
with pytest.raises(ValueError, match=error_message):
|
|
2278
|
-
# ValueError is raised for non-tuple iterable with correct length
|
|
2279
|
-
system.pvwatts_dc((1, 1, 1), pd.Series([1, 2, 3]))
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
def test_PVSystem_pvwatts_losses(pvwatts_system_defaults, mocker):
|
|
2283
|
-
mocker.spy(pvsystem, 'pvwatts_losses')
|
|
2284
|
-
age = 1
|
|
2285
|
-
pvwatts_system_defaults.losses_parameters = dict(age=age)
|
|
2286
|
-
expected = 15
|
|
2287
|
-
out = pvwatts_system_defaults.pvwatts_losses()
|
|
2288
|
-
pvsystem.pvwatts_losses.assert_called_once_with(age=age)
|
|
2289
|
-
assert out < expected
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
def test_PVSystem_num_arrays():
|
|
2293
|
-
system_one = pvsystem.PVSystem()
|
|
2294
|
-
system_two = pvsystem.PVSystem(arrays=[
|
|
2295
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180)),
|
|
2296
|
-
pvsystem.Array(pvsystem.FixedMount(0, 180))])
|
|
2297
|
-
assert system_one.num_arrays == 1
|
|
2298
|
-
assert system_two.num_arrays == 2
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
def test_PVSystem_at_least_one_array():
|
|
2302
|
-
with pytest.raises(ValueError,
|
|
2303
|
-
match="PVSystem must have at least one Array"):
|
|
2304
|
-
pvsystem.PVSystem(arrays=[])
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
def test_PVSystem_single_array():
|
|
2308
|
-
# GH 1831
|
|
2309
|
-
single_array = pvsystem.Array(pvsystem.FixedMount())
|
|
2310
|
-
system = pvsystem.PVSystem(arrays=single_array)
|
|
2311
|
-
assert isinstance(system.arrays, tuple)
|
|
2312
|
-
assert system.arrays[0] is single_array
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
def test_combine_loss_factors():
|
|
2316
|
-
test_index = pd.date_range(start='1990/01/01T12:00', periods=365, freq='d')
|
|
2317
|
-
loss_1 = pd.Series(.10, index=test_index)
|
|
2318
|
-
loss_2 = pd.Series(.05, index=pd.date_range(start='1990/01/01T12:00',
|
|
2319
|
-
periods=365*2, freq='d'))
|
|
2320
|
-
loss_3 = pd.Series(.02, index=pd.date_range(start='1990/01/01',
|
|
2321
|
-
periods=12, freq='MS'))
|
|
2322
|
-
expected = pd.Series(.1621, index=test_index)
|
|
2323
|
-
out = pvsystem.combine_loss_factors(test_index, loss_1, loss_2, loss_3)
|
|
2324
|
-
assert_series_equal(expected, out)
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
def test_no_extra_kwargs():
|
|
2328
|
-
with pytest.raises(TypeError, match="arbitrary_kwarg"):
|
|
2329
|
-
pvsystem.PVSystem(arbitrary_kwarg='value')
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
def test_AbstractMount_constructor():
|
|
2333
|
-
match = "Can't instantiate abstract class AbstractMount"
|
|
2334
|
-
with pytest.raises(TypeError, match=match):
|
|
2335
|
-
_ = pvsystem.AbstractMount()
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
@pytest.fixture
|
|
2339
|
-
def fixed_mount():
|
|
2340
|
-
return pvsystem.FixedMount(20, 180)
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
@pytest.fixture
|
|
2344
|
-
def single_axis_tracker_mount():
|
|
2345
|
-
return pvsystem.SingleAxisTrackerMount(axis_tilt=10, axis_azimuth=170,
|
|
2346
|
-
max_angle=45, backtrack=False,
|
|
2347
|
-
gcr=0.4, cross_axis_tilt=-5)
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
def test_FixedMount_constructor(fixed_mount):
|
|
2351
|
-
assert fixed_mount.surface_tilt == 20
|
|
2352
|
-
assert fixed_mount.surface_azimuth == 180
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
def test_FixedMount_get_orientation(fixed_mount):
|
|
2356
|
-
expected = {'surface_tilt': 20, 'surface_azimuth': 180}
|
|
2357
|
-
assert fixed_mount.get_orientation(45, 130) == expected
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
def test_SingleAxisTrackerMount_constructor(single_axis_tracker_mount):
|
|
2361
|
-
expected = dict(axis_tilt=10, axis_azimuth=170, max_angle=45,
|
|
2362
|
-
backtrack=False, gcr=0.4, cross_axis_tilt=-5)
|
|
2363
|
-
for attr_name, expected_value in expected.items():
|
|
2364
|
-
assert getattr(single_axis_tracker_mount, attr_name) == expected_value
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
def test_SingleAxisTrackerMount_get_orientation(single_axis_tracker_mount):
|
|
2368
|
-
expected = {'surface_tilt': 19.29835284, 'surface_azimuth': 229.7643755}
|
|
2369
|
-
actual = single_axis_tracker_mount.get_orientation(45, 190)
|
|
2370
|
-
for key, expected_value in expected.items():
|
|
2371
|
-
err_msg = f"{key} value incorrect"
|
|
2372
|
-
assert actual[key] == pytest.approx(expected_value), err_msg
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
def test_SingleAxisTrackerMount_get_orientation_asymmetric_max():
|
|
2376
|
-
mount = pvsystem.SingleAxisTrackerMount(max_angle=(-30, 45))
|
|
2377
|
-
expected = {'surface_tilt': [45, 30], 'surface_azimuth': [90, 270]}
|
|
2378
|
-
actual = mount.get_orientation([60, 60], [90, 270])
|
|
2379
|
-
for key, expected_value in expected.items():
|
|
2380
|
-
err_msg = f"{key} value incorrect"
|
|
2381
|
-
assert actual[key] == pytest.approx(expected_value), err_msg
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
def test_dc_ohms_from_percent():
|
|
2385
|
-
expected = .1425
|
|
2386
|
-
out = pvsystem.dc_ohms_from_percent(38, 8, 3, 1, 1)
|
|
2387
|
-
assert_allclose(out, expected)
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
def test_PVSystem_dc_ohms_from_percent(mocker):
|
|
2391
|
-
mocker.spy(pvsystem, 'dc_ohms_from_percent')
|
|
2392
|
-
|
|
2393
|
-
expected = .1425
|
|
2394
|
-
system = pvsystem.PVSystem(losses_parameters={'dc_ohmic_percent': 3},
|
|
2395
|
-
module_parameters={'I_mp_ref': 8,
|
|
2396
|
-
'V_mp_ref': 38})
|
|
2397
|
-
out = system.dc_ohms_from_percent()
|
|
2398
|
-
|
|
2399
|
-
pvsystem.dc_ohms_from_percent.assert_called_once_with(
|
|
2400
|
-
dc_ohmic_percent=3,
|
|
2401
|
-
vmp_ref=38,
|
|
2402
|
-
imp_ref=8,
|
|
2403
|
-
modules_per_string=1,
|
|
2404
|
-
strings=1
|
|
2405
|
-
)
|
|
2406
|
-
|
|
2407
|
-
assert_allclose(out, expected)
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
def test_dc_ohmic_losses():
|
|
2411
|
-
expected = 9.12
|
|
2412
|
-
out = pvsystem.dc_ohmic_losses(.1425, 8)
|
|
2413
|
-
assert_allclose(out, expected)
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
def test_Array_dc_ohms_from_percent(mocker):
|
|
2417
|
-
mocker.spy(pvsystem, 'dc_ohms_from_percent')
|
|
2418
|
-
|
|
2419
|
-
expected = .1425
|
|
2420
|
-
|
|
2421
|
-
array = pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
2422
|
-
array_losses_parameters={'dc_ohmic_percent': 3},
|
|
2423
|
-
module_parameters={'I_mp_ref': 8,
|
|
2424
|
-
'V_mp_ref': 38})
|
|
2425
|
-
out = array.dc_ohms_from_percent()
|
|
2426
|
-
pvsystem.dc_ohms_from_percent.assert_called_with(
|
|
2427
|
-
dc_ohmic_percent=3,
|
|
2428
|
-
vmp_ref=38,
|
|
2429
|
-
imp_ref=8,
|
|
2430
|
-
modules_per_string=1,
|
|
2431
|
-
strings=1
|
|
2432
|
-
)
|
|
2433
|
-
assert_allclose(out, expected)
|
|
2434
|
-
|
|
2435
|
-
array = pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
2436
|
-
array_losses_parameters={'dc_ohmic_percent': 3},
|
|
2437
|
-
module_parameters={'Impo': 8,
|
|
2438
|
-
'Vmpo': 38})
|
|
2439
|
-
out = array.dc_ohms_from_percent()
|
|
2440
|
-
pvsystem.dc_ohms_from_percent.assert_called_with(
|
|
2441
|
-
dc_ohmic_percent=3,
|
|
2442
|
-
vmp_ref=38,
|
|
2443
|
-
imp_ref=8,
|
|
2444
|
-
modules_per_string=1,
|
|
2445
|
-
strings=1
|
|
2446
|
-
)
|
|
2447
|
-
assert_allclose(out, expected)
|
|
2448
|
-
|
|
2449
|
-
array = pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
2450
|
-
array_losses_parameters={'dc_ohmic_percent': 3},
|
|
2451
|
-
module_parameters={'Impp': 8,
|
|
2452
|
-
'Vmpp': 38})
|
|
2453
|
-
out = array.dc_ohms_from_percent()
|
|
2454
|
-
|
|
2455
|
-
pvsystem.dc_ohms_from_percent.assert_called_with(
|
|
2456
|
-
dc_ohmic_percent=3,
|
|
2457
|
-
vmp_ref=38,
|
|
2458
|
-
imp_ref=8,
|
|
2459
|
-
modules_per_string=1,
|
|
2460
|
-
strings=1
|
|
2461
|
-
)
|
|
2462
|
-
assert_allclose(out, expected)
|
|
2463
|
-
|
|
2464
|
-
with pytest.raises(ValueError,
|
|
2465
|
-
match=('Parameters for Vmp and Imp could not be found '
|
|
2466
|
-
'in the array module parameters. Module '
|
|
2467
|
-
'parameters must include one set of '
|
|
2468
|
-
'{"V_mp_ref", "I_mp_Ref"}, '
|
|
2469
|
-
'{"Vmpo", "Impo"}, or '
|
|
2470
|
-
'{"Vmpp", "Impp"}.')):
|
|
2471
|
-
array = pvsystem.Array(pvsystem.FixedMount(0, 180),
|
|
2472
|
-
array_losses_parameters={'dc_ohmic_percent': 3})
|
|
2473
|
-
out = array.dc_ohms_from_percent()
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
@pytest.mark.parametrize('model,keys', [
|
|
2477
|
-
('sapm', ('a', 'b', 'deltaT')),
|
|
2478
|
-
('fuentes', ('noct_installed',)),
|
|
2479
|
-
('noct_sam', ('noct', 'module_efficiency'))
|
|
2480
|
-
])
|
|
2481
|
-
def test_Array_temperature_missing_parameters(model, keys):
|
|
2482
|
-
# test that a nice error is raised when required temp params are missing
|
|
2483
|
-
array = pvsystem.Array(pvsystem.FixedMount(0, 180))
|
|
2484
|
-
index = pd.date_range('2019-01-01', freq='h', periods=5)
|
|
2485
|
-
temps = pd.Series(25, index)
|
|
2486
|
-
irrads = pd.Series(1000, index)
|
|
2487
|
-
winds = pd.Series(1, index)
|
|
2488
|
-
|
|
2489
|
-
for key in keys:
|
|
2490
|
-
match = f"Missing required parameter '{key}'"
|
|
2491
|
-
params = {k: 1 for k in keys} # dummy values
|
|
2492
|
-
params.pop(key) # remove each key in turn
|
|
2493
|
-
array.temperature_model_parameters = params
|
|
2494
|
-
with pytest.raises(KeyError, match=match):
|
|
2495
|
-
array.get_cell_temperature(irrads, temps, winds, model)
|