Skip to content

Commit 608863f

Browse files
author
anomam
committed
Merge branch 'master' into pvfactors_implementation
2 parents 9970179 + 5d2a6c8 commit 608863f

File tree

5 files changed

+73
-23
lines changed

5 files changed

+73
-23
lines changed

docs/sphinx/source/whatsnew/v0.6.1.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Enhancements
6262
by supplying `pressure=None`. (:issue:`449`)
6363
* Created :py:func:`pvlib.pvsystem.pvsyst_celltemp` to implement PVsyst's cell temperature model. (:issue:`552`)
6464
* Created :py:func:`pvlib.bifacial.pvfactors_timeseries` to use open-source `pvfactors` package to calculate back surface irradiance (:issue:`421`)
65+
* Add `PVSystem` class method :py:func:`~pvlib.pvsystem.PVSystem.pvsyst_celltemp` (:issue:`633`)
6566

6667

6768
Bug fixes
@@ -75,6 +76,8 @@ Bug fixes
7576
* Fix documentation errors when using IPython >= 7.0.
7677
* Fix error in :func:`pvlib.modelchain.ModelChain.infer_spectral_model` (:issue:`619`)
7778
* Fix error in ``pvlib.spa`` when using Python 3.7 on some platforms.
79+
* Fix error in :func:`pvlib.irradiance._delta_kt_prime_dirint` (:issue:`637`). The error affects
80+
the first and last values of DNI calculated by the function :func:`pvlib.irradiance.dirint`
7881

7982

8083
Testing

pvlib/irradiance.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,14 +1558,20 @@ def _dirint_from_dni_ktprime(dni, kt_prime, solar_zenith, use_delta_kt_prime,
15581558

15591559
def _delta_kt_prime_dirint(kt_prime, use_delta_kt_prime, times):
15601560
"""
1561-
Calculate delta kt prime (Perez eqn 2), or return a default value
1561+
Calculate delta_kt_prime (Perez eqn 2 and eqn 3), or return a default value
15621562
for use with :py:func:`_dirint_bins`.
15631563
"""
15641564
if use_delta_kt_prime:
15651565
# Perez eqn 2
1566-
delta_kt_prime = 0.5*((kt_prime - kt_prime.shift(1)).abs().add(
1567-
(kt_prime - kt_prime.shift(-1)).abs(),
1568-
fill_value=0))
1566+
kt_next = kt_prime.shift(-1)
1567+
kt_previous = kt_prime.shift(1)
1568+
# replace nan with values that implement Perez Eq 3 for first and last
1569+
# positions. Use kt_previous and kt_next to handle series of length 1
1570+
kt_next.iloc[-1] = kt_previous.iloc[-1]
1571+
kt_previous.iloc[0] = kt_next.iloc[0]
1572+
delta_kt_prime = 0.5 * ((kt_prime - kt_next).abs().add(
1573+
(kt_prime - kt_previous).abs(),
1574+
fill_value=0))
15691575
else:
15701576
# do not change unless also modifying _dirint_bins
15711577
delta_kt_prime = pd.Series(-1, index=times)

pvlib/pvsystem.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@
4646
}
4747

4848

49+
TEMP_MODELS = {
50+
'sapm': {'open_rack_cell_glassback': (-3.47, -.0594, 3),
51+
'roof_mount_cell_glassback': (-2.98, -.0471, 1),
52+
'open_rack_cell_polymerback': (-3.56, -.0750, 3),
53+
'insulated_back_polymerback': (-2.81, -.0455, 0),
54+
'open_rack_polymer_thinfilm_steel': (-3.58, -.113, 3),
55+
'22x_concentrator_tracker': (-3.23, -.130, 13)},
56+
'pvsyst': {'freestanding': (29.0, 0), 'insulated': (15.0, 0)}
57+
}
58+
4959
# not sure if this belongs in the pvsystem module.
5060
# maybe something more like core.py? It may eventually grow to
5161
# import a lot more functionality from other modules.
@@ -511,6 +521,23 @@ def sapm_effective_irradiance(self, poa_direct, poa_diffuse,
511521
poa_direct, poa_diffuse, airmass_absolute, aoi,
512522
self.module_parameters, reference_irradiance=reference_irradiance)
513523

524+
def pvsyst_celltemp(self, poa_global, wind_speed, temp_air):
525+
"""Uses :py:func:`pvsyst_celltemp` to calculate module temperatures
526+
based on ``self.racking_model`` and the input parameters.
527+
528+
Parameters
529+
----------
530+
See pvsystem.pvsyst_celltemp for details
531+
532+
Returns
533+
-------
534+
See pvsystem.pvsyst_celltemp for details
535+
"""
536+
kwargs = _build_kwargs(['eta_m', 'alpha_absorption'],
537+
self.module_parameters)
538+
return pvsyst_celltemp(poa_global, wind_speed, temp_air,
539+
temp_model=self.racking_model, **kwargs)
540+
514541
def first_solar_spectral_loss(self, pw, airmass_absolute):
515542

516543
"""
@@ -1860,13 +1887,7 @@ def sapm_celltemp(poa_global, wind_speed, temp_air,
18601887
sapm
18611888
'''
18621889

1863-
temp_models = {'open_rack_cell_glassback': [-3.47, -.0594, 3],
1864-
'roof_mount_cell_glassback': [-2.98, -.0471, 1],
1865-
'open_rack_cell_polymerback': [-3.56, -.0750, 3],
1866-
'insulated_back_polymerback': [-2.81, -.0455, 0],
1867-
'open_rack_polymer_thinfilm_steel': [-3.58, -.113, 3],
1868-
'22x_concentrator_tracker': [-3.23, -.130, 13]
1869-
}
1890+
temp_models = TEMP_MODELS['sapm']
18701891

18711892
if isinstance(model, str):
18721893
model = temp_models[model.lower()]
@@ -1880,9 +1901,9 @@ def sapm_celltemp(poa_global, wind_speed, temp_air,
18801901

18811902
E0 = 1000. # Reference irradiance
18821903

1883-
temp_module = pd.Series(poa_global*np.exp(a + b*wind_speed) + temp_air)
1904+
temp_module = pd.Series(poa_global * np.exp(a + b * wind_speed) + temp_air)
18841905

1885-
temp_cell = temp_module + (poa_global / E0)*(deltaT)
1906+
temp_cell = temp_module + (poa_global / E0) * (deltaT)
18861907

18871908
return pd.DataFrame({'temp_cell': temp_cell, 'temp_module': temp_module})
18881909

@@ -1944,7 +1965,7 @@ def pvsyst_celltemp(poa_global, wind_speed, temp_air, eta_m=0.1,
19441965
photovoltaic modules." Progress in Photovoltaics 16(4): 307-315.
19451966
"""
19461967

1947-
temp_models = {"freestanding": (29.0, 0), "insulated": (15.0, 0)}
1968+
temp_models = TEMP_MODELS['pvsyst']
19481969

19491970
if isinstance(temp_model, str):
19501971
natural_convenction_coeff, forced_convection_coeff = temp_models[

pvlib/test/test_irradiance.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -466,13 +466,13 @@ def test_dirint_value():
466466
pressure = 93193.
467467
dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure)
468468
assert_almost_equal(dirint_data.values,
469-
np.array([ 888. , 683.7]), 1)
469+
np.array([868.8, 699.7]), 1)
470470

471471

472472
def test_dirint_nans():
473473
times = pd.DatetimeIndex(start='2014-06-24T12-0700', periods=5, freq='6H')
474474
ghi = pd.Series([np.nan, 1038.62, 1038.62, 1038.62, 1038.62], index=times)
475-
zenith = pd.Series([10.567, np.nan, 10.567, 10.567, 10.567,], index=times)
475+
zenith = pd.Series([10.567, np.nan, 10.567, 10.567, 10.567], index=times)
476476
pressure = pd.Series([93193., 93193., np.nan, 93193., 93193.], index=times)
477477
temp_dew = pd.Series([10, 10, 10, np.nan, 10], index=times)
478478
dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure,
@@ -489,7 +489,7 @@ def test_dirint_tdew():
489489
dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure,
490490
temp_dew=10)
491491
assert_almost_equal(dirint_data.values,
492-
np.array([892.9, 636.5]), 1)
492+
np.array([882.1, 672.6]), 1)
493493

494494

495495
def test_dirint_no_delta_kt():
@@ -559,7 +559,7 @@ def test_gti_dirint():
559559
expected = pd.DataFrame(array(
560560
[[ 21.05796198, 0. , 21.05796198],
561561
[ 288.22574368, 60.59964218, 245.37532576],
562-
[ 930.85454521, 695.8504884 , 276.96897609]]),
562+
[ 931.04078010, 695.94965324, 277.06172442]]),
563563
columns=expected_col_order, index=times)
564564

565565
assert_frame_equal(output, expected)
@@ -583,7 +583,7 @@ def test_gti_dirint():
583583
expected = pd.DataFrame(array(
584584
[[ 21.05796198, 0. , 21.05796198],
585585
[ 289.81109139, 60.52460392, 247.01373353],
586-
[ 932.22047435, 647.68716072, 323.59362885]]),
586+
[ 932.46756378, 648.05001357, 323.49974813]]),
587587
columns=expected_col_order, index=times)
588588

589589
assert_frame_equal(output, expected)
@@ -595,9 +595,9 @@ def test_gti_dirint():
595595
albedo=albedo)
596596

597597
expected = pd.DataFrame(array(
598-
[[ 21.3592591 , 0. , 21.3592591 ],
599-
[ 292.5162373 , 64.42628826, 246.95997198],
600-
[ 941.47847463, 727.07261187, 258.25370648]]),
598+
[[ 21.3592591, 0. , 21.3592591 ],
599+
[ 292.5162373, 64.42628826, 246.95997198],
600+
[ 941.6753031, 727.16311901, 258.36548605]]),
601601
columns=expected_col_order, index=times)
602602

603603
assert_frame_equal(output, expected)
@@ -611,7 +611,7 @@ def test_gti_dirint():
611611
expected = pd.DataFrame(array(
612612
[[ 21.05796198, 0. , 21.05796198],
613613
[ 292.40468994, 36.79559287, 266.3862767 ],
614-
[ 930.72198876, 712.36063132, 261.32196017]]),
614+
[ 931.79627208, 689.81549269, 283.5817439]]),
615615
columns=expected_col_order, index=times)
616616

617617
assert_frame_equal(output, expected)

pvlib/test/test_pvsystem.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,26 @@ def test_pvsyst_celltemp_with_index():
11181118
assert_series_equal(expected, pvtemps)
11191119

11201120

1121+
def test_PVSystem_pvsyst_celltemp(mocker):
1122+
racking_model = 'insulated'
1123+
alpha_absorption = 0.85
1124+
eta_m = 0.17
1125+
module_parameters = {}
1126+
module_parameters['alpha_absorption'] = alpha_absorption
1127+
module_parameters['eta_m'] = eta_m
1128+
system = pvsystem.PVSystem(racking_model=racking_model,
1129+
module_parameters=module_parameters)
1130+
mocker.spy(pvsystem, 'pvsyst_celltemp')
1131+
irrad = 800
1132+
temp = 45
1133+
wind = 0.5
1134+
out = system.pvsyst_celltemp(irrad, wind, temp)
1135+
pvsystem.pvsyst_celltemp.assert_called_once_with(
1136+
irrad, wind, temp, eta_m, alpha_absorption, racking_model)
1137+
assert isinstance(out, float)
1138+
assert out < 90 and out > 70
1139+
1140+
11211141
def test_adrinverter(sam_data):
11221142
inverters = sam_data['adrinverter']
11231143
testinv = 'Ablerex_Electronics_Co___Ltd___' \

0 commit comments

Comments
 (0)