Skip to content

Commit fa9dc9b

Browse files
nicoriecwhanseAdamRJensen
authored
add orgill hollands decomposition (#1730)
* add orgill hollands decomposition * Fix Stickler * Update pvlib/irradiance.py correct spelling to 'boland' Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/irradiance.py correct citation formating Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/irradiance.py correct citation formatting Co-authored-by: Cliff Hansen <[email protected]> * Update pvlib/irradiance.py correct spelling 'boland' Co-authored-by: Cliff Hansen <[email protected]> * Update irradiance.py adding dni_extra argument per cliff's suggestion. * Remove edits to boland * Fix references and add output description * Update decomposition.rst Update docs * Update test_irradiance.py Adding a test * Update test_irradiance.py fixing the perilous outcome of copy/pasting the test_boland function. * Update v0.10.0.rst Adding Orgill Hollands model to list of enhancements. --------- Co-authored-by: Cliff Hansen <[email protected]> Co-authored-by: Adam R. Jensen <[email protected]>
1 parent cfd6e78 commit fa9dc9b

File tree

4 files changed

+109
-2
lines changed

4 files changed

+109
-2
lines changed

docs/sphinx/source/reference/irradiance/decomposition.rst

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ DNI estimation models
1212
irradiance.dirint
1313
irradiance.dirindex
1414
irradiance.erbs
15+
irradiance.orgill_hollands
1516
irradiance.boland
1617
irradiance.campbell_norman
1718
irradiance.gti_dirint

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ Deprecations
2929

3030
Enhancements
3131
~~~~~~~~~~~~
32+
* Added a new irradiance decomposition model :py:func:`pvlib.irradiance.orgill_hollands`. (:pull:`1730`)
3233
* The return values of :py:func:`pvlib.pvsystem.calcparams_desoto`,
3334
:py:func:`pvlib.pvsystem.calcparams_cec`, and
3435
:py:func:`pvlib.pvsystem.calcparams_pvsyst` are all numeric types and have
3536
the same Python type as the `effective_irradiance` and `temp_cell` parameters. (:issue:`1626`, :pull:`1700`)
36-
3737
* Added `map_variables` parameter to :py:func:`pvlib.iotools.read_srml`
3838
and :py:func:`pvlib.iotools.read_srml_month_from_solardat` (:pull:`1773`)
3939
* Allow passing keyword arguments to :py:func:`scipy:scipy.optimize.brentq` and
@@ -45,7 +45,6 @@ Enhancements
4545
(:issue:`1249`, :pull:`1764`)
4646
* Improved `ModelChainResult.__repr__` (:pull:`1236`)
4747

48-
4948
Bug fixes
5049
~~~~~~~~~
5150

@@ -71,6 +70,7 @@ Requirements
7170
Contributors
7271
~~~~~~~~~~~~
7372
* Taos Transue (:ghuser:`reepoi`)
73+
* Nicholas Riedel-Lyngskær (:ghuser:`nicorie`)
7474
* Adam R. Jensen (:ghuser:`AdamRJensen`)
7575
* Echedey Luis (:ghuser:`echedey-ls`)
7676
* Cliff Hansen (:ghuser:`cwhanse`)

pvlib/irradiance.py

+90
Original file line numberDiff line numberDiff line change
@@ -2227,6 +2227,8 @@ def erbs(ghi, zenith, datetime_or_doy, min_cos_zenith=0.065, max_zenith=87):
22272227
--------
22282228
dirint
22292229
disc
2230+
orgill_hollands
2231+
boland
22302232
"""
22312233

22322234
dni_extra = get_extra_radiation(datetime_or_doy)
@@ -2265,6 +2267,93 @@ def erbs(ghi, zenith, datetime_or_doy, min_cos_zenith=0.065, max_zenith=87):
22652267
return data
22662268

22672269

2270+
def orgill_hollands(ghi, zenith, datetime_or_doy, dni_extra=None,
2271+
min_cos_zenith=0.065, max_zenith=87):
2272+
"""Estimate DNI and DHI from GHI using the Orgill and Hollands model.
2273+
2274+
The Orgill and Hollands model [1]_ estimates the diffuse fraction DF from
2275+
global horizontal irradiance through an empirical relationship between
2276+
hourly DF observations (in Toronto, Canada) and the ratio of GHI to
2277+
extraterrestrial irradiance, Kt.
2278+
2279+
Parameters
2280+
----------
2281+
ghi: numeric
2282+
Global horizontal irradiance in W/m^2.
2283+
zenith: numeric
2284+
True (not refraction-corrected) zenith angles in decimal degrees.
2285+
datetime_or_doy : int, float, array, pd.DatetimeIndex
2286+
Day of year or array of days of year e.g.
2287+
pd.DatetimeIndex.dayofyear, or pd.DatetimeIndex.
2288+
dni_extra : None or numeric, default None
2289+
Extraterrestrial direct normal irradiance. [W/m2]
2290+
min_cos_zenith : numeric, default 0.065
2291+
Minimum value of cos(zenith) to allow when calculating global
2292+
clearness index `kt`. Equivalent to zenith = 86.273 degrees.
2293+
max_zenith : numeric, default 87
2294+
Maximum value of zenith to allow in DNI calculation. DNI will be
2295+
set to 0 for times with zenith values greater than `max_zenith`.
2296+
2297+
Returns
2298+
-------
2299+
data : OrderedDict or DataFrame
2300+
Contains the following keys/columns:
2301+
2302+
* ``dni``: the modeled direct normal irradiance in W/m^2.
2303+
* ``dhi``: the modeled diffuse horizontal irradiance in
2304+
W/m^2.
2305+
* ``kt``: Ratio of global to extraterrestrial irradiance
2306+
on a horizontal plane.
2307+
2308+
References
2309+
----------
2310+
.. [1] Orgill, J.F., Hollands, K.G.T., Correlation equation for hourly
2311+
diffuse radiation on a horizontal surface, Solar Energy 19(4), pp 357–359,
2312+
1977. Eqs. 3(a), 3(b) and 3(c)
2313+
:doi:`10.1016/0038-092X(77)90006-8`
2314+
2315+
See Also
2316+
--------
2317+
dirint
2318+
disc
2319+
erbs
2320+
boland
2321+
"""
2322+
if dni_extra is None:
2323+
dni_extra = get_extra_radiation(datetime_or_doy)
2324+
2325+
kt = clearness_index(ghi, zenith, dni_extra, min_cos_zenith=min_cos_zenith,
2326+
max_clearness_index=1)
2327+
2328+
# For Kt < 0.35, set the diffuse fraction
2329+
df = 1 - 0.249*kt
2330+
2331+
# For Kt >= 0.35 and Kt <= 0.75, set the diffuse fraction
2332+
df = np.where((kt >= 0.35) & (kt <= 0.75),
2333+
1.557 - 1.84*kt, df)
2334+
2335+
# For Kt > 0.75, set the diffuse fraction
2336+
df = np.where(kt > 0.75, 0.177, df)
2337+
2338+
dhi = df * ghi
2339+
2340+
dni = (ghi - dhi) / tools.cosd(zenith)
2341+
bad_values = (zenith > max_zenith) | (ghi < 0) | (dni < 0)
2342+
dni = np.where(bad_values, 0, dni)
2343+
# ensure that closure relationship remains valid
2344+
dhi = np.where(bad_values, ghi, dhi)
2345+
2346+
data = OrderedDict()
2347+
data['dni'] = dni
2348+
data['dhi'] = dhi
2349+
data['kt'] = kt
2350+
2351+
if isinstance(datetime_or_doy, pd.DatetimeIndex):
2352+
data = pd.DataFrame(data, index=datetime_or_doy)
2353+
2354+
return data
2355+
2356+
22682357
def boland(ghi, solar_zenith, datetime_or_doy, a_coeff=8.645, b_coeff=0.613,
22692358
min_cos_zenith=0.065, max_zenith=87):
22702359
r"""
@@ -2326,6 +2415,7 @@ def boland(ghi, solar_zenith, datetime_or_doy, a_coeff=8.645, b_coeff=0.613,
23262415
dirint
23272416
disc
23282417
erbs
2418+
orgill_hollands
23292419
23302420
Notes
23312421
-----

pvlib/tests/test_irradiance.py

+16
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,22 @@ def test_boland():
821821
assert np.allclose(out, expected)
822822

823823

824+
def test_orgill_hollands():
825+
index = pd.DatetimeIndex(['20190101']*3 + ['20190620'])
826+
ghi = pd.Series([0, 50, 1000, 1000], index=index)
827+
zenith = pd.Series([120, 85, 10, 10], index=index)
828+
expected = pd.DataFrame(np.array(
829+
[[0.0, 0.0, 0.0],
830+
[108.731366, 40.5234370, 0.405723511],
831+
[776.155771, 235.635779, 0.718132729],
832+
[835.696102, 177.000000, 0.768214312]]),
833+
columns=['dni', 'dhi', 'kt'], index=index)
834+
835+
out = irradiance.orgill_hollands(ghi, zenith, index)
836+
837+
assert np.allclose(out, expected)
838+
839+
824840
def test_erbs_min_cos_zenith_max_zenith():
825841
# map out behavior under difficult conditions with various
826842
# limiting kwargs settings

0 commit comments

Comments
 (0)