Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/sphinx/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ DNI estimation models
irradiance.dirint
irradiance.dirindex
irradiance.erbs
irradiance.liujordan
irradiance.campbell_norman
irradiance.gti_dirint

Clearness index models
Expand Down Expand Up @@ -520,7 +520,7 @@ Processing data
forecast.ForecastModel.cloud_cover_to_ghi_linear
forecast.ForecastModel.cloud_cover_to_irradiance_clearsky_scaling
forecast.ForecastModel.cloud_cover_to_transmittance_linear
forecast.ForecastModel.cloud_cover_to_irradiance_liujordan
forecast.ForecastModel.cloud_cover_to_irradiance_campbel_norman
forecast.ForecastModel.cloud_cover_to_irradiance
forecast.ForecastModel.kelvin_to_celsius
forecast.ForecastModel.isobaric_to_ambient_temperature
Expand Down
8 changes: 7 additions & 1 deletion docs/sphinx/source/whatsnew/v0.8.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Breaking changes

Deprecations
~~~~~~~~~~~~

* ``pvlib.irradiance.liujordan`` is deprecated.

Enhancements
~~~~~~~~~~~~
Expand All @@ -21,6 +21,12 @@ Enhancements
multiple MPPTs (:issue:`457`, :pull:`1085`)
* Added optional ``attributes`` parameter to :py:func:`pvlib.iotools.get_psm3`
and added the option of fetching 5- and 15-minute PSM3 data. (:pull:`1086`)
* Added :py:func:`pvlib.irradiance.campbell_norman` for estimating DNI, DHI and GHI
from extraterrestrial irradiance. This function replaces ``pvlib.irradiance.liujordan``;
users of ``pvlib.irradiance.liujordan`` should note that :py:func:`pvlib.irradiance.campbell_norman`
expects different parameters.
* :py:meth:`pvlib.forecast.Forecast.cloud_cover_to_irradiance_campbell_norman`
replaces ``pvlib.forecast.Forecast.cloud_cover_to_irradiance_liujordan``.

Bug fixes
~~~~~~~~~
Expand Down
57 changes: 52 additions & 5 deletions pvlib/forecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
from xml.etree.ElementTree import ParseError

from pvlib.location import Location
from pvlib.irradiance import liujordan, get_extra_radiation, disc
from pvlib.irradiance import campbell_norman, get_extra_radiation, disc
from pvlib.irradiance import _liujordan
from siphon.catalog import TDSCatalog
from siphon.ncss import NCSS

import warnings
from pvlib._deprecation import deprecated


warnings.warn(
'The forecast module algorithms and features are highly experimental. '
Expand Down Expand Up @@ -526,8 +529,48 @@ def cloud_cover_to_transmittance_linear(self, cloud_cover, offset=0.75,

return transmittance

def cloud_cover_to_irradiance_campbell_norman(self, cloud_cover, **kwargs):
"""
Estimates irradiance from cloud cover in the following steps:

1. Determine transmittance using a function of cloud cover e.g.
:py:meth:`~ForecastModel.cloud_cover_to_transmittance_linear`
2. Calculate GHI, DNI, DHI using the
:py:func:`pvlib.irradiance.campbell_norman` model

Parameters
----------
cloud_cover : Series

Returns
-------
irradiance : DataFrame
Columns include ghi, dni, dhi
"""
# in principle, get_solarposition could use the forecast
# pressure, temp, etc., but the cloud cover forecast is not
# accurate enough to justify using these minor corrections
solar_position = self.location.get_solarposition(cloud_cover.index)
dni_extra = get_extra_radiation(cloud_cover.index)

transmittance = self.cloud_cover_to_transmittance_linear(cloud_cover,
**kwargs)

irrads = campbell_norman(solar_position['apparent_zenith'],
transmittance, dni_extra=dni_extra)
irrads = irrads.fillna(0)

return irrads

@deprecated(
'0.8',
alternative='Forecast.cloud_cover_to_irradiance_campbell_norman',
name='Forecast.cloud_cover_to_irradiance_liujordan',
removal='0.9')
def cloud_cover_to_irradiance_liujordan(self, cloud_cover, **kwargs):
"""
Deprecated. Use cloud_cover_to_irradiance_campbell_norman instead.

Estimates irradiance from cloud cover in the following steps:

1. Determine transmittance using a function of cloud cover e.g.
Expand All @@ -554,9 +597,9 @@ def cloud_cover_to_irradiance_liujordan(self, cloud_cover, **kwargs):
transmittance = self.cloud_cover_to_transmittance_linear(cloud_cover,
**kwargs)

irrads = liujordan(solar_position['apparent_zenith'],
transmittance, airmass['airmass_absolute'],
dni_extra=dni_extra)
irrads = _liujordan(solar_position['apparent_zenith'],
transmittance, airmass['airmass_absolute'],
dni_extra=dni_extra)
irrads = irrads.fillna(0)

return irrads
Expand All @@ -571,7 +614,8 @@ def cloud_cover_to_irradiance(self, cloud_cover, how='clearsky_scaling',
cloud_cover : Series
how : str, default 'clearsky_scaling'
Selects the method for conversion. Can be one of
clearsky_scaling or liujordan.
clearsky_scaling or campbell_norman. Method liujordan is
deprecated.
**kwargs
Passed to the selected method.

Expand All @@ -585,6 +629,9 @@ def cloud_cover_to_irradiance(self, cloud_cover, how='clearsky_scaling',
if how == 'clearsky_scaling':
irrads = self.cloud_cover_to_irradiance_clearsky_scaling(
cloud_cover, **kwargs)
elif how == 'campbell_norman':
irrads = self.cloud_cover_to_irradiance_campbell_norman(
cloud_cover, **kwargs)
elif how == 'liujordan':
irrads = self.cloud_cover_to_irradiance_liujordan(
cloud_cover, **kwargs)
Expand Down
63 changes: 62 additions & 1 deletion pvlib/irradiance.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

from pvlib import atmosphere, solarposition, tools

from pvlib._deprecation import deprecated


# see References section of grounddiffuse function
SURFACE_ALBEDOS = {'urban': 0.18,
'grass': 0.20,
Expand Down Expand Up @@ -2184,7 +2187,61 @@ def erbs(ghi, zenith, datetime_or_doy, min_cos_zenith=0.065, max_zenith=87):
return data


def liujordan(zenith, transmittance, airmass, dni_extra=1367.0):
def campbell_norman(zenith, transmittance, pressure=101325.0,
dni_extra=1367.0):
'''
Determine DNI, DHI, GHI from extraterrestrial flux, transmittance,
and atmospheric pressure.

Parameters
----------
zenith: pd.Series
True (not refraction-corrected) zenith angles in decimal
degrees. If Z is a vector it must be of the same size as all
other vector inputs. Z must be >=0 and <=180.

transmittance: float
Atmospheric transmittance between 0 and 1.

pressure: float, default 101325.0
Air pressure

dni_extra: float, default 1367.0
Direct irradiance incident at the top of the atmosphere.

Returns
-------
irradiance: DataFrame
Modeled direct normal irradiance, direct horizontal irradiance,
and global horizontal irradiance in W/m^2

References
----------
.. [1] Campbell, G. S., J. M. Norman (1998) An Introduction to
Environmental Biophysics. 2nd Ed. New York: Springer.
'''

tau = transmittance

airmass = atmosphere.get_relative_airmass(zenith, model='simple')
airmass = atmosphere.get_absolute_airmass(airmass, pressure=pressure)
dni = dni_extra*tau**airmass
cos_zen = tools.cosd(zenith)
dhi = 0.3 * (1.0 - tau**airmass) * dni_extra * cos_zen
ghi = dhi + dni * cos_zen

irrads = OrderedDict()
irrads['ghi'] = ghi
irrads['dni'] = dni
irrads['dhi'] = dhi

if isinstance(ghi, pd.Series):
irrads = pd.DataFrame(irrads)

return irrads


def _liujordan(zenith, transmittance, airmass, dni_extra=1367.0):
'''
Determine DNI, DHI, GHI from extraterrestrial flux, transmittance,
and optical air mass number.
Expand Down Expand Up @@ -2242,6 +2299,10 @@ def liujordan(zenith, transmittance, airmass, dni_extra=1367.0):
return irrads


liujordan = deprecated('0.8', alternative='campbellnormam',
name='liujordan', removal='0.9')(_liujordan)


def _get_perez_coefficients(perezmodel):
'''
Find coefficients for the Perez model
Expand Down
4 changes: 2 additions & 2 deletions pvlib/tests/test_forecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
requires_siphon,
has_siphon,
skip_windows,
requires_recent_cftime,
requires_recent_cftime
)
from conftest import RERUNS, RERUNS_DELAY

Expand Down Expand Up @@ -69,7 +69,7 @@ def model(request):
@pytest.mark.remote_data
@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
def test_process_data(model):
for how in ['liujordan', 'clearsky_scaling']:
for how in ['campbell_norman', 'clearsky_scaling']:
if model.raw_data.empty:
warnings.warn('Could not test {} process_data with how={} '
'because raw_data was empty'.format(model, how))
Expand Down
21 changes: 18 additions & 3 deletions pvlib/tests/test_irradiance.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

from pvlib import irradiance

from conftest import requires_ephem, requires_numba
from conftest import requires_ephem, requires_numba, fail_on_pvlib_version
from pvlib._deprecation import pvlibDeprecationWarning


# fixtures create realistic test input data
Expand Down Expand Up @@ -285,13 +286,27 @@ def test_get_sky_diffuse_invalid():
model='invalid')


@fail_on_pvlib_version('0.9')
def test_liujordan():
expected = pd.DataFrame(np.array(
[[863.859736967, 653.123094076, 220.65905025]]),
columns=['ghi', 'dni', 'dhi'],
index=[0])
out = irradiance.liujordan(
pd.Series([10]), pd.Series([0.5]), pd.Series([1.1]), dni_extra=1400)
with pytest.warns(pvlibDeprecationWarning):
out = irradiance.liujordan(
pd.Series([10]), pd.Series([0.5]), pd.Series([1.1]),
dni_extra=1400)
assert_frame_equal(out, expected)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is going to emit a deprecation warning and we want to avoid that. We could delete it or we could skip the new test_deprecated_09 test, add @fail_on_pvlib_version('0.9') around this test, and add the with pytest.warns... here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the option after "or"



def test_campbell_norman():
expected = pd.DataFrame(np.array(
[[863.859736967, 653.123094076, 220.65905025]]),
columns=['ghi', 'dni', 'dhi'],
index=[0])
out = irradiance.campbell_norman(
pd.Series([10]), pd.Series([0.5]), pd.Series([109764.21013135818]),
dni_extra=1400)
assert_frame_equal(out, expected)


Expand Down