Skip to content

Commit aa3b2ac

Browse files
committed
Merge branch 'master' of https://github.com/pvlib/pvlib-python into detect_clearsky
2 parents 055a7c3 + 7a99b34 commit aa3b2ac

File tree

10 files changed

+231
-35
lines changed

10 files changed

+231
-35
lines changed

docs/sphinx/source/api.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ DNI estimation models
181181
irradiance.dirint
182182
irradiance.dirindex
183183
irradiance.erbs
184-
irradiance.liujordan
184+
irradiance.campbell_norman
185185
irradiance.gti_dirint
186186

187187
Clearness index models
@@ -295,6 +295,7 @@ Inverter models (DC to AC conversion)
295295
inverter.sandia_multi
296296
inverter.adr
297297
inverter.pvwatts
298+
inverter.pvwatts_multi
298299

299300
Functions for fitting inverter models
300301

@@ -325,7 +326,6 @@ Pvsyst model
325326
.. autosummary::
326327
:toctree: generated/
327328

328-
pvsystem.calcparams_pvsyst
329329
temperature.pvsyst_cell
330330
pvsystem.calcparams_pvsyst
331331
pvsystem.singlediode
@@ -521,7 +521,7 @@ Processing data
521521
forecast.ForecastModel.cloud_cover_to_ghi_linear
522522
forecast.ForecastModel.cloud_cover_to_irradiance_clearsky_scaling
523523
forecast.ForecastModel.cloud_cover_to_transmittance_linear
524-
forecast.ForecastModel.cloud_cover_to_irradiance_liujordan
524+
forecast.ForecastModel.cloud_cover_to_irradiance_campbell_norman
525525
forecast.ForecastModel.cloud_cover_to_irradiance
526526
forecast.ForecastModel.kelvin_to_celsius
527527
forecast.ForecastModel.isobaric_to_ambient_temperature

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Breaking changes
99

1010
Deprecations
1111
~~~~~~~~~~~~
12-
12+
* ``pvlib.irradiance.liujordan`` is deprecated.
1313

1414
Enhancements
1515
~~~~~~~~~~~~
@@ -22,15 +22,25 @@ Enhancements
2222

2323
* Added :py:func:`pvlib.inverter.sandia_multi` for modeling inverters with
2424
multiple MPPTs (:issue:`457`, :pull:`1085`)
25+
* Added :py:func:`pvlib.inverter.sandia_multi` and :py:func:`pvlib.inverter.pvwatts_multi`
26+
for modeling inverters with multiple MPPTs (:issue:`457`, :pull:`1085`, :pull:`1106`)
2527
* Added optional ``attributes`` parameter to :py:func:`pvlib.iotools.get_psm3`
2628
and added the option of fetching 5- and 15-minute PSM3 data. (:pull:`1086`)
29+
* Added :py:func:`pvlib.irradiance.campbell_norman` for estimating DNI, DHI and GHI
30+
from extraterrestrial irradiance. This function replaces ``pvlib.irradiance.liujordan``;
31+
users of ``pvlib.irradiance.liujordan`` should note that :py:func:`pvlib.irradiance.campbell_norman`
32+
expects different parameters.
33+
* :py:meth:`pvlib.forecast.Forecast.cloud_cover_to_irradiance_campbell_norman`
34+
replaces ``pvlib.forecast.Forecast.cloud_cover_to_irradiance_liujordan``.
2735

2836
Bug fixes
2937
~~~~~~~~~
3038
* Fix issue with :py:func:`pvlib.temperature.fuentes` with timezone-aware
3139
inputs. (:issue:`1071`, :pull:`1072`)
3240
* Raise ``ValueError`` from :py:meth:`pvlib.modelchain.ModelChain.prepare_inputs`
3341
when input does not have a 'dhi' column. (:issue:`1092`, :pull:`1093`)
42+
* Add missing modules (including ``shading`` and ``scaling``) to ``__init__.py``.
43+
(:pull:`1103`)
3444

3545
Testing
3646
~~~~~~~

pvlib/__init__.py

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
from pvlib.version import __version__ # noqa: F401
2-
from pvlib import tools # noqa: F401
3-
from pvlib import atmosphere # noqa: F401
4-
from pvlib import clearsky # noqa: F401
5-
# from pvlib import forecast # noqa: F401
6-
from pvlib import irradiance # noqa: F401
7-
from pvlib import location # noqa: F401
8-
from pvlib import solarposition # noqa: F401
9-
from pvlib import iotools # noqa: F401
10-
from pvlib import ivtools # noqa: F401
11-
from pvlib import tracking # noqa: F401
12-
from pvlib import pvsystem # noqa: F401
13-
from pvlib import spa # noqa: F401
14-
from pvlib import modelchain # noqa: F401
15-
from pvlib import singlediode # noqa: F401
16-
from pvlib import bifacial # noqa: F401
17-
from pvlib import soiling # noqa: F401
18-
from pvlib import snow # noqa: F401
2+
3+
from pvlib import ( # noqa: F401
4+
atmosphere,
5+
bifacial,
6+
clearsky,
7+
# forecast
8+
iam,
9+
inverter,
10+
iotools,
11+
irradiance,
12+
ivtools,
13+
location,
14+
modelchain,
15+
pvsystem,
16+
scaling,
17+
shading,
18+
singlediode,
19+
snow,
20+
soiling,
21+
solarposition,
22+
spa,
23+
temperature,
24+
tools,
25+
tracking,
26+
)

pvlib/forecast.py

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
from xml.etree.ElementTree import ParseError
1010

1111
from pvlib.location import Location
12-
from pvlib.irradiance import liujordan, get_extra_radiation, disc
12+
from pvlib.irradiance import campbell_norman, get_extra_radiation, disc
13+
from pvlib.irradiance import _liujordan
1314
from siphon.catalog import TDSCatalog
1415
from siphon.ncss import NCSS
1516

1617
import warnings
18+
from pvlib._deprecation import deprecated
19+
1720

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

527530
return transmittance
528531

532+
def cloud_cover_to_irradiance_campbell_norman(self, cloud_cover, **kwargs):
533+
"""
534+
Estimates irradiance from cloud cover in the following steps:
535+
536+
1. Determine transmittance using a function of cloud cover e.g.
537+
:py:meth:`~ForecastModel.cloud_cover_to_transmittance_linear`
538+
2. Calculate GHI, DNI, DHI using the
539+
:py:func:`pvlib.irradiance.campbell_norman` model
540+
541+
Parameters
542+
----------
543+
cloud_cover : Series
544+
545+
Returns
546+
-------
547+
irradiance : DataFrame
548+
Columns include ghi, dni, dhi
549+
"""
550+
# in principle, get_solarposition could use the forecast
551+
# pressure, temp, etc., but the cloud cover forecast is not
552+
# accurate enough to justify using these minor corrections
553+
solar_position = self.location.get_solarposition(cloud_cover.index)
554+
dni_extra = get_extra_radiation(cloud_cover.index)
555+
556+
transmittance = self.cloud_cover_to_transmittance_linear(cloud_cover,
557+
**kwargs)
558+
559+
irrads = campbell_norman(solar_position['apparent_zenith'],
560+
transmittance, dni_extra=dni_extra)
561+
irrads = irrads.fillna(0)
562+
563+
return irrads
564+
565+
@deprecated(
566+
'0.8',
567+
alternative='Forecast.cloud_cover_to_irradiance_campbell_norman',
568+
name='Forecast.cloud_cover_to_irradiance_liujordan',
569+
removal='0.9')
529570
def cloud_cover_to_irradiance_liujordan(self, cloud_cover, **kwargs):
530571
"""
572+
Deprecated. Use cloud_cover_to_irradiance_campbell_norman instead.
573+
531574
Estimates irradiance from cloud cover in the following steps:
532575
533576
1. Determine transmittance using a function of cloud cover e.g.
@@ -554,9 +597,9 @@ def cloud_cover_to_irradiance_liujordan(self, cloud_cover, **kwargs):
554597
transmittance = self.cloud_cover_to_transmittance_linear(cloud_cover,
555598
**kwargs)
556599

557-
irrads = liujordan(solar_position['apparent_zenith'],
558-
transmittance, airmass['airmass_absolute'],
559-
dni_extra=dni_extra)
600+
irrads = _liujordan(solar_position['apparent_zenith'],
601+
transmittance, airmass['airmass_absolute'],
602+
dni_extra=dni_extra)
560603
irrads = irrads.fillna(0)
561604

562605
return irrads
@@ -571,7 +614,8 @@ def cloud_cover_to_irradiance(self, cloud_cover, how='clearsky_scaling',
571614
cloud_cover : Series
572615
how : str, default 'clearsky_scaling'
573616
Selects the method for conversion. Can be one of
574-
clearsky_scaling or liujordan.
617+
clearsky_scaling or campbell_norman. Method liujordan is
618+
deprecated.
575619
**kwargs
576620
Passed to the selected method.
577621
@@ -585,6 +629,9 @@ def cloud_cover_to_irradiance(self, cloud_cover, how='clearsky_scaling',
585629
if how == 'clearsky_scaling':
586630
irrads = self.cloud_cover_to_irradiance_clearsky_scaling(
587631
cloud_cover, **kwargs)
632+
elif how == 'campbell_norman':
633+
irrads = self.cloud_cover_to_irradiance_campbell_norman(
634+
cloud_cover, **kwargs)
588635
elif how == 'liujordan':
589636
irrads = self.cloud_cover_to_irradiance_liujordan(
590637
cloud_cover, **kwargs)

pvlib/inverter.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ def adr(v_dc, p_dc, inverter, vtol=0.10):
328328

329329
def pvwatts(pdc, pdc0, eta_inv_nom=0.96, eta_inv_ref=0.9637):
330330
r"""
331-
Implements NREL's PVWatts inverter model.
331+
NREL's PVWatts inverter model.
332332
333333
The PVWatts inverter model [1]_ calculates inverter efficiency :math:`\eta`
334334
as a function of input DC power
@@ -348,7 +348,7 @@ def pvwatts(pdc, pdc0, eta_inv_nom=0.96, eta_inv_ref=0.9637):
348348
349349
Parameters
350350
----------
351-
pdc: numeric
351+
pdc : numeric
352352
DC power. Same unit as ``pdc0``.
353353
pdc0: numeric
354354
DC input limit of the inverter. Same unit as ``pdc``.
@@ -371,6 +371,10 @@ def pvwatts(pdc, pdc0, eta_inv_nom=0.96, eta_inv_ref=0.9637):
371371
:py:func:`pvlib.pvsystem.pvwatts_dc` refers to the DC power of the modules
372372
at reference conditions.
373373
374+
See Also
375+
--------
376+
pvlib.inverter.pvwatts_multi
377+
374378
References
375379
----------
376380
.. [1] A. P. Dobos, "PVWatts Version 5 Manual,"
@@ -396,6 +400,39 @@ def pvwatts(pdc, pdc0, eta_inv_nom=0.96, eta_inv_ref=0.9637):
396400
return power_ac
397401

398402

403+
def pvwatts_multi(pdc, pdc0, eta_inv_nom=0.96, eta_inv_ref=0.9637):
404+
r"""
405+
Extend NREL's PVWatts inverter model for multiple MPP inputs.
406+
407+
DC input power is summed over MPP inputs to obtain the DC power
408+
input to the PVWatts inverter model. See :py:func:`pvlib.inverter.pvwatts`
409+
for details.
410+
411+
Parameters
412+
----------
413+
pdc : tuple, list or array of numeric
414+
DC power on each MPPT input of the inverter. If type is array, must
415+
be 2d with axis 0 being the MPPT inputs. Same unit as ``pdc0``.
416+
pdc0: numeric
417+
DC input limit of the inverter. Same unit as ``pdc``.
418+
eta_inv_nom: numeric, default 0.96
419+
Nominal inverter efficiency. [unitless]
420+
eta_inv_ref: numeric, default 0.9637
421+
Reference inverter efficiency. PVWatts defines it to be 0.9637
422+
and is included here for flexibility. [unitless]
423+
424+
Returns
425+
-------
426+
power_ac: numeric
427+
AC power. Same unit as ``pdc0``.
428+
429+
See Also
430+
--------
431+
pvlib.inverter.pvwatts
432+
"""
433+
return pvwatts(sum(pdc), pdc0, eta_inv_nom, eta_inv_ref)
434+
435+
399436
def fit_sandia(ac_power, dc_power, dc_voltage, dc_voltage_level, p_ac_0, p_nt):
400437
r'''
401438
Determine parameters for the Sandia inverter model.

pvlib/irradiance.py

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
from pvlib import atmosphere, solarposition, tools
1515

16+
from pvlib._deprecation import deprecated
17+
18+
1619
# see References section of grounddiffuse function
1720
SURFACE_ALBEDOS = {'urban': 0.18,
1821
'grass': 0.20,
@@ -2184,7 +2187,61 @@ def erbs(ghi, zenith, datetime_or_doy, min_cos_zenith=0.065, max_zenith=87):
21842187
return data
21852188

21862189

2187-
def liujordan(zenith, transmittance, airmass, dni_extra=1367.0):
2190+
def campbell_norman(zenith, transmittance, pressure=101325.0,
2191+
dni_extra=1367.0):
2192+
'''
2193+
Determine DNI, DHI, GHI from extraterrestrial flux, transmittance,
2194+
and atmospheric pressure.
2195+
2196+
Parameters
2197+
----------
2198+
zenith: pd.Series
2199+
True (not refraction-corrected) zenith angles in decimal
2200+
degrees. If Z is a vector it must be of the same size as all
2201+
other vector inputs. Z must be >=0 and <=180.
2202+
2203+
transmittance: float
2204+
Atmospheric transmittance between 0 and 1.
2205+
2206+
pressure: float, default 101325.0
2207+
Air pressure
2208+
2209+
dni_extra: float, default 1367.0
2210+
Direct irradiance incident at the top of the atmosphere.
2211+
2212+
Returns
2213+
-------
2214+
irradiance: DataFrame
2215+
Modeled direct normal irradiance, direct horizontal irradiance,
2216+
and global horizontal irradiance in W/m^2
2217+
2218+
References
2219+
----------
2220+
.. [1] Campbell, G. S., J. M. Norman (1998) An Introduction to
2221+
Environmental Biophysics. 2nd Ed. New York: Springer.
2222+
'''
2223+
2224+
tau = transmittance
2225+
2226+
airmass = atmosphere.get_relative_airmass(zenith, model='simple')
2227+
airmass = atmosphere.get_absolute_airmass(airmass, pressure=pressure)
2228+
dni = dni_extra*tau**airmass
2229+
cos_zen = tools.cosd(zenith)
2230+
dhi = 0.3 * (1.0 - tau**airmass) * dni_extra * cos_zen
2231+
ghi = dhi + dni * cos_zen
2232+
2233+
irrads = OrderedDict()
2234+
irrads['ghi'] = ghi
2235+
irrads['dni'] = dni
2236+
irrads['dhi'] = dhi
2237+
2238+
if isinstance(ghi, pd.Series):
2239+
irrads = pd.DataFrame(irrads)
2240+
2241+
return irrads
2242+
2243+
2244+
def _liujordan(zenith, transmittance, airmass, dni_extra=1367.0):
21882245
'''
21892246
Determine DNI, DHI, GHI from extraterrestrial flux, transmittance,
21902247
and optical air mass number.
@@ -2242,6 +2299,10 @@ def liujordan(zenith, transmittance, airmass, dni_extra=1367.0):
22422299
return irrads
22432300

22442301

2302+
liujordan = deprecated('0.8', alternative='campbellnormam',
2303+
name='liujordan', removal='0.9')(_liujordan)
2304+
2305+
22452306
def _get_perez_coefficients(perezmodel):
22462307
'''
22472308
Find coefficients for the Perez model

pvlib/tests/iotools/test_psm3.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ def test_get_psm3_singleyear(nrel_api_key):
9393

9494
@pytest.mark.remote_data
9595
@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
96-
@pytest.mark.xfail(strict=True, reason='github 1091')
9796
def test_get_psm3_5min(nrel_api_key):
9897
"""test get_psm3 for 5-minute data"""
9998
header, data = psm3.get_psm3(LATITUDE, LONGITUDE, nrel_api_key,

pvlib/tests/test_forecast.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
requires_siphon,
1111
has_siphon,
1212
skip_windows,
13-
requires_recent_cftime,
13+
requires_recent_cftime
1414
)
1515
from conftest import RERUNS, RERUNS_DELAY
1616

@@ -69,7 +69,7 @@ def model(request):
6969
@pytest.mark.remote_data
7070
@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
7171
def test_process_data(model):
72-
for how in ['liujordan', 'clearsky_scaling']:
72+
for how in ['campbell_norman', 'clearsky_scaling']:
7373
if model.raw_data.empty:
7474
warnings.warn('Could not test {} process_data with how={} '
7575
'because raw_data was empty'.format(model, how))

0 commit comments

Comments
 (0)