Skip to content

add orgill hollands decomposition #1730

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Jun 29, 2023
1 change: 1 addition & 0 deletions docs/sphinx/source/reference/irradiance/decomposition.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ DNI estimation models
irradiance.dirint
irradiance.dirindex
irradiance.erbs
irradiance.orgill_hollands
irradiance.boland
irradiance.campbell_norman
irradiance.gti_dirint
Expand Down
4 changes: 2 additions & 2 deletions docs/sphinx/source/whatsnew/v0.10.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ Deprecations

Enhancements
~~~~~~~~~~~~
* Added a new irradiance decomposition model :py:func:`pvlib.irradiance.orgill_hollands`. (:pull:`1730`)
* The return values of :py:func:`pvlib.pvsystem.calcparams_desoto`,
:py:func:`pvlib.pvsystem.calcparams_cec`, and
:py:func:`pvlib.pvsystem.calcparams_pvsyst` are all numeric types and have
the same Python type as the `effective_irradiance` and `temp_cell` parameters. (:issue:`1626`, :pull:`1700`)

* Added `map_variables` parameter to :py:func:`pvlib.iotools.read_srml`
and :py:func:`pvlib.iotools.read_srml_month_from_solardat` (:pull:`1773`)
* Allow passing keyword arguments to :py:func:`scipy:scipy.optimize.brentq` and
Expand All @@ -45,7 +45,6 @@ Enhancements
(:issue:`1249`, :pull:`1764`)
* Improved `ModelChainResult.__repr__` (:pull:`1236`)


Bug fixes
~~~~~~~~~

Expand All @@ -71,6 +70,7 @@ Requirements
Contributors
~~~~~~~~~~~~
* Taos Transue (:ghuser:`reepoi`)
* Nicholas Riedel-Lyngskær (:ghuser:`nicorie`)
* Adam R. Jensen (:ghuser:`AdamRJensen`)
* Echedey Luis (:ghuser:`echedey-ls`)
* Cliff Hansen (:ghuser:`cwhanse`)
Expand Down
90 changes: 90 additions & 0 deletions pvlib/irradiance.py
Original file line number Diff line number Diff line change
Expand Up @@ -2227,6 +2227,8 @@ def erbs(ghi, zenith, datetime_or_doy, min_cos_zenith=0.065, max_zenith=87):
--------
dirint
disc
orgill_hollands
boland
"""

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


def orgill_hollands(ghi, zenith, datetime_or_doy, dni_extra=None,
min_cos_zenith=0.065, max_zenith=87):
"""Estimate DNI and DHI from GHI using the Orgill and Hollands model.

The Orgill and Hollands model [1]_ estimates the diffuse fraction DF from
global horizontal irradiance through an empirical relationship between
hourly DF observations (in Toronto, Canada) and the ratio of GHI to
extraterrestrial irradiance, Kt.

Parameters
----------
ghi: numeric
Global horizontal irradiance in W/m^2.
zenith: numeric
True (not refraction-corrected) zenith angles in decimal degrees.
datetime_or_doy : int, float, array, pd.DatetimeIndex
Day of year or array of days of year e.g.
pd.DatetimeIndex.dayofyear, or pd.DatetimeIndex.
dni_extra : None or numeric, default None
Extraterrestrial direct normal irradiance. [W/m2]
min_cos_zenith : numeric, default 0.065
Minimum value of cos(zenith) to allow when calculating global
clearness index `kt`. Equivalent to zenith = 86.273 degrees.
max_zenith : numeric, default 87
Maximum value of zenith to allow in DNI calculation. DNI will be
set to 0 for times with zenith values greater than `max_zenith`.

Returns
-------
data : OrderedDict or DataFrame
Contains the following keys/columns:

* ``dni``: the modeled direct normal irradiance in W/m^2.
* ``dhi``: the modeled diffuse horizontal irradiance in
W/m^2.
* ``kt``: Ratio of global to extraterrestrial irradiance
on a horizontal plane.

References
----------
.. [1] Orgill, J.F., Hollands, K.G.T., Correlation equation for hourly
diffuse radiation on a horizontal surface, Solar Energy 19(4), pp 357–359,
1977. Eqs. 3(a), 3(b) and 3(c)
:doi:`10.1016/0038-092X(77)90006-8`

See Also
--------
dirint
disc
erbs
boland
"""
if dni_extra is None:
dni_extra = get_extra_radiation(datetime_or_doy)

kt = clearness_index(ghi, zenith, dni_extra, min_cos_zenith=min_cos_zenith,
max_clearness_index=1)

# For Kt < 0.35, set the diffuse fraction
df = 1 - 0.249*kt

# For Kt >= 0.35 and Kt <= 0.75, set the diffuse fraction
df = np.where((kt >= 0.35) & (kt <= 0.75),
1.557 - 1.84*kt, df)

# For Kt > 0.75, set the diffuse fraction
df = np.where(kt > 0.75, 0.177, df)

dhi = df * ghi

dni = (ghi - dhi) / tools.cosd(zenith)
bad_values = (zenith > max_zenith) | (ghi < 0) | (dni < 0)
dni = np.where(bad_values, 0, dni)
# ensure that closure relationship remains valid
dhi = np.where(bad_values, ghi, dhi)

data = OrderedDict()
data['dni'] = dni
data['dhi'] = dhi
data['kt'] = kt

if isinstance(datetime_or_doy, pd.DatetimeIndex):
data = pd.DataFrame(data, index=datetime_or_doy)

return data


def boland(ghi, solar_zenith, datetime_or_doy, a_coeff=8.645, b_coeff=0.613,
min_cos_zenith=0.065, max_zenith=87):
r"""
Expand Down Expand Up @@ -2326,6 +2415,7 @@ def boland(ghi, solar_zenith, datetime_or_doy, a_coeff=8.645, b_coeff=0.613,
dirint
disc
erbs
orgill_hollands

Notes
-----
Expand Down
16 changes: 16 additions & 0 deletions pvlib/tests/test_irradiance.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,22 @@ def test_boland():
assert np.allclose(out, expected)


def test_orgill_hollands():
index = pd.DatetimeIndex(['20190101']*3 + ['20190620'])
ghi = pd.Series([0, 50, 1000, 1000], index=index)
zenith = pd.Series([120, 85, 10, 10], index=index)
expected = pd.DataFrame(np.array(
[[0.0, 0.0, 0.0],
[108.731366, 40.5234370, 0.405723511],
[776.155771, 235.635779, 0.718132729],
[835.696102, 177.000000, 0.768214312]]),
columns=['dni', 'dhi', 'kt'], index=index)

out = irradiance.orgill_hollands(ghi, zenith, index)

assert np.allclose(out, expected)


def test_erbs_min_cos_zenith_max_zenith():
# map out behavior under difficult conditions with various
# limiting kwargs settings
Expand Down