Skip to content

Commit b4db6e2

Browse files
mikofskiwholmgren
authored andcommitted
NREL bird clearsky (#276)
* add requirements.txt to install into virtualenv and ignore venv/ * add Bird clearsky model * move clearsky.py into clearsky/core.py just for fun, let's try it out * fix path to data in clearsky to LinkeTurbidities.mat * add BIRD workbook to data for testing Signed-off-by: Mark Mikofski <[email protected]> * move test_bird to test_clearsky and move bird to clearsky core module * revert api changes * add spencer and pvcdron eot to solarposition, fix test and 2pi * add equation of time test * compare eot from spencer and pvcdrom to spa-python * add note about coefficients in spencer 1971 and more references * addressing comments in PR 276 * clean up docstrings for bird model, fix pub date to 1981, add references section, add attribution to daryl myers * add spaces between colon and parameter to ineichen and simplified_solis models to correspond to numpydoc style * revert changes in 457615d, change pvlib-path back to dirname of clearsky.py file, remove added clearsky_path * start to change bird function signature to conform to existing clear sky algos, and strip out some of the complicated algos like the relative airmass, declination and solpos * change args aod_380nm to aod380 and aod_500nm to aod500. * clean up eot docstrings, add references, use external linking * add declination formulas to solarposition.py * added both cooper-69 and spencer-71 * replacing calls in bird to calls to new formulas for declination, eot, dayangle * make bird function signature similar to other clearsky methods * remove day_angle, relative airmass, eot, zenith, declination, extraterrestrial dni calcs, and pass values in as needed * change o3_cm to ozone, h2o_cm to precipitable_water, b_a to asymmetry and alb to albedo * replace pstar, patm and am_press with absolute airmass method from atmosphere * testvalues no longer needed * use irradiance.extraradiation() and remove etr() * add analytical solar zenith angle and hour angle methods to solar position module * add all parameters to docstring for bird clearsky * also add returns * remove defaults for aod, since should be supplied TODO: change input to broadband when linke turbidity PR is complete * remove times, not needed anymore * remove commented relative airmass(method="kasten1966") since passed as arg * remove extraradiation(method="spencer") since passed as arg * change etr_ to etr since no more etr TODO: change all variables to easier names * add seinfeld and pandis to declination references * finish hour angle calc * add all parameters to docstring for bird clearsky * also add returns * remove defaults for aod, since should be supplied TODO: change input to broadband when linke turbidity PR is complete * remove times, not needed anymore * remove commented relative airmass(method="kasten1966") since passed as arg * remove extraradiation(method="spencer") since passed as arg * change etr_ to etr since no more etr TODO: change all variables to easier names * add seinfeld and pandis to declination references * finish hour angle calc * set night values to zero * save ze_cos once, instead of recalculating * simplify/shorten some lines now that np.where(airmass > 0,<calc>,0.0) is gone * calculate diffuse_horiz return value prior to return line * update test_bird() with new function signature * update docs * add to what's new for v0.4.4 * add new solar position formulas and bird clear sky to api * move links to references, and space references to make numpydoc happy * add see also for eot, declination and solar_zenith_analytical * add missing requirements * add it to min build too * remove dependence on xlrd - use csv file instead of xls file - NOTE: I made this file by changing all cells' format to General, fitting column size to content width to show all significant figures, then saving as csv, new file is less than 370kb vs 1.2mb - use pandas read_csv instead of xlrd, way easier :) - remove requirements.txt, can't be bothered * move low precision solar position correlations to new api section * add Daryl R. Myers, "Solar Radiation" CRC Press (2013) reference * fix some sphinx-build errors in solar-position, explicit emphasis start with no end for "*Note" (missing closing "*" for emphasis in `nrel_earthsun_distance` and `spa_python` * use numpydoc linked references for spencer71 equation of time * test keywords in bird clear sky model * add BIRD_08_16_2012_patm.csv for 2nd bird test data * fix docs by moving text before parameters so not indented * test scalars in bird model * add test data file * lower case Spencer71 in docs and solarposition * fix lower case 's' in spencer71 * output OrderedDict or DataFrame * fix link * update docstring returns to OrderedDict/DataFrame * provide note on solar vs apparent zenith and testing * quotes for 'direct_horizontal' in docstring returns * add tests for solarposition low-accuracy formulas * move whats new note from 0.4.4 to 0.4.5 * test declination and solar-zenith * correct spelling of Rayleigh
1 parent 2e2f7a8 commit b4db6e2

File tree

8 files changed

+18105
-16
lines changed

8 files changed

+18105
-16
lines changed

docs/sphinx/source/api.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ unless you know that you need a different function.
4646
solarposition.pyephem
4747
solarposition.spa_c
4848

49+
4950
Additional functions for quantities closely related to solar position.
5051

5152
.. autosummary::
@@ -65,6 +66,19 @@ algorithm.
6566
spa
6667

6768

69+
Correlations and analytical expressions for low precision solar position
70+
calculations.
71+
72+
.. autosummary::
73+
:toctree: generated/
74+
75+
solarposition.solar_zenith_analytical
76+
solarposition.declination_spencer71
77+
solarposition.declination_cooper69
78+
solarposition.equation_of_time_spencer71
79+
solarposition.equation_of_time_pvcdrom
80+
solarposition.hour_angle
81+
6882
Clear sky
6983
=========
7084

@@ -77,6 +91,7 @@ Clear sky
7791
clearsky.simplified_solis
7892
clearsky.haurwitz
7993
clearsky.detect_clearsky
94+
clearsky.bird
8095

8196

8297
Airmass and atmospheric models

docs/sphinx/source/whatsnew/v0.4.5.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ Bug fixes
99

1010
* Fix pandas 0.20 incompatibilities in Location.get_clearsky,
1111
solarposition.ephemeris (:issue:`325`)
12+
* Added NREL Bird clear sky model. (:issue:`276`)
13+
* Added lower accuracy formulas for equation of time, declination, hour angle
14+
and solar zenith.
1215

1316

1417
Contributors
1518
~~~~~~~~~~~~
1619

1720
* Will Holmgren
21+
* Mark Mikofski

pvlib/clearsky.py

Lines changed: 132 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import numpy as np
1313
import pandas as pd
1414

15-
from pvlib import tools
15+
from pvlib import tools, atmosphere, solarposition, irradiance
1616

1717

1818
def ineichen(apparent_zenith, airmass_absolute, linke_turbidity,
@@ -31,19 +31,19 @@ def ineichen(apparent_zenith, airmass_absolute, linke_turbidity,
3131
3232
Parameters
3333
-----------
34-
apparent_zenith: numeric
34+
apparent_zenith : numeric
3535
Refraction corrected solar zenith angle in degrees.
3636
37-
airmass_absolute: numeric
37+
airmass_absolute : numeric
3838
Pressure corrected airmass.
3939
40-
linke_turbidity: numeric
40+
linke_turbidity : numeric
4141
Linke Turbidity.
4242
43-
altitude: numeric
43+
altitude : numeric
4444
Altitude above sea level in meters.
4545
46-
dni_extra: numeric
46+
dni_extra : numeric
4747
Extraterrestrial irradiance. The units of ``dni_extra``
4848
determine the units of the output.
4949
@@ -349,24 +349,24 @@ def simplified_solis(apparent_elevation, aod700=0.1, precipitable_water=1.,
349349
350350
Parameters
351351
----------
352-
apparent_elevation: numeric
352+
apparent_elevation : numeric
353353
The apparent elevation of the sun above the horizon (deg).
354354
355-
aod700: numeric
355+
aod700 : numeric
356356
The aerosol optical depth at 700 nm (unitless).
357357
Algorithm derived for values between 0 and 0.45.
358358
359-
precipitable_water: numeric
359+
precipitable_water : numeric
360360
The precipitable water of the atmosphere (cm).
361361
Algorithm derived for values between 0.2 and 10 cm.
362362
Values less than 0.2 will be assumed to be equal to 0.2.
363363
364-
pressure: numeric
364+
pressure : numeric
365365
The atmospheric pressure (Pascals).
366366
Algorithm derived for altitudes between sea level and 7000 m,
367367
or 101325 and 41000 Pascals.
368368
369-
dni_extra: numeric
369+
dni_extra : numeric
370370
Extraterrestrial irradiance. The units of ``dni_extra``
371371
determine the units of the output.
372372
@@ -720,3 +720,124 @@ def rmse(alpha):
720720
return clear_samples, components, alpha
721721
else:
722722
return clear_samples
723+
724+
725+
def bird(zenith, airmass_relative, aod380, aod500, precipitable_water,
726+
ozone=0.3, pressure=101325., dni_extra=1364., asymmetry=0.85,
727+
albedo=0.2):
728+
"""
729+
Bird Simple Clear Sky Broadband Solar Radiation Model
730+
731+
Based on NREL Excel implementation by Daryl R. Myers [1, 2].
732+
733+
Bird and Hulstrom define the zenith as the "angle between a line to the sun
734+
and the local zenith". There is no distinction in the paper between solar
735+
zenith and apparent (or refracted) zenith, but the relative airmass is
736+
defined using the Kasten 1966 expression, which requires apparent zenith.
737+
Although the formulation for calculated zenith is never explicitly defined
738+
in the report, since the purpose was to compare existing clear sky models
739+
with "rigorous radiative transfer models" (RTM) it is possible that apparent
740+
zenith was obtained as output from the RTM. However, the implentation
741+
presented in PVLIB is tested against the NREL Excel implementation by Daryl
742+
Myers which uses an analytical expression for solar zenith instead of
743+
apparent zenith.
744+
745+
Parameters
746+
----------
747+
zenith : numeric
748+
Solar or apparent zenith angle in degrees - see note above
749+
airmass_relative : numeric
750+
Relative airmass
751+
aod380 : numeric
752+
Aerosol optical depth [cm] measured at 380[nm]
753+
aod500 : numeric
754+
Aerosol optical depth [cm] measured at 500[nm]
755+
precipitable_water : numeric
756+
Precipitable water [cm]
757+
ozone : numeric
758+
Atmospheric ozone [cm], defaults to 0.3[cm]
759+
pressure : numeric
760+
Ambient pressure [Pa], defaults to 101325[Pa]
761+
dni_extra : numeric
762+
Extraterrestrial radiation [W/m^2], defaults to 1364[W/m^2]
763+
asymmetry : numeric
764+
Asymmetry factor, defaults to 0.85
765+
albedo : numeric
766+
Albedo, defaults to 0.2
767+
768+
Returns
769+
-------
770+
clearsky : DataFrame (if Series input) or OrderedDict of arrays
771+
DataFrame/OrderedDict contains the columns/keys
772+
``'dhi', 'dni', 'ghi', 'direct_horizontal'`` in [W/m^2].
773+
774+
See also
775+
--------
776+
pvlib.atmosphere.bird_hulstrom80_aod_bb
777+
pvlib.atmosphere.relativeairmass
778+
779+
References
780+
----------
781+
[1] R. E. Bird and R. L Hulstrom, "A Simplified Clear Sky model for Direct
782+
and Diffuse Insolation on Horizontal Surfaces" SERI Technical Report
783+
SERI/TR-642-761, Feb 1981. Solar Energy Research Institute, Golden, CO.
784+
785+
[2] Daryl R. Myers, "Solar Radiation: Practical Modeling for Renewable
786+
Energy Applications", pp. 46-51 CRC Press (2013)
787+
788+
`NREL Bird Clear Sky Model <http://rredc.nrel.gov/solar/models/clearsky/>`_
789+
790+
`SERI/TR-642-761 <http://rredc.nrel.gov/solar/pubs/pdfs/tr-642-761.pdf>`_
791+
792+
`Error Reports <http://rredc.nrel.gov/solar/models/clearsky/error_reports.html>`_
793+
"""
794+
etr = dni_extra # extraradiation
795+
ze_rad = np.deg2rad(zenith) # zenith in radians
796+
airmass = airmass_relative
797+
# Bird clear sky model
798+
am_press = atmosphere.absoluteairmass(airmass, pressure)
799+
t_rayleigh = (
800+
np.exp(-0.0903 * am_press ** 0.84 * (
801+
1.0 + am_press - am_press ** 1.01
802+
))
803+
)
804+
am_o3 = ozone*airmass
805+
t_ozone = (
806+
1.0 - 0.1611 * am_o3 * (1.0 + 139.48 * am_o3) ** -0.3034 -
807+
0.002715 * am_o3 / (1.0 + 0.044 * am_o3 + 0.0003 * am_o3 ** 2.0)
808+
)
809+
t_gases = np.exp(-0.0127 * am_press ** 0.26)
810+
am_h2o = airmass * precipitable_water
811+
t_water = (
812+
1.0 - 2.4959 * am_h2o / (
813+
(1.0 + 79.034 * am_h2o) ** 0.6828 + 6.385 * am_h2o
814+
)
815+
)
816+
bird_huldstrom = atmosphere.bird_hulstrom80_aod_bb(aod380, aod500)
817+
t_aerosol = np.exp(
818+
-(bird_huldstrom ** 0.873) *
819+
(1.0 + bird_huldstrom - bird_huldstrom ** 0.7088) * airmass ** 0.9108
820+
)
821+
taa = 1.0 - 0.1 * (1.0 - airmass + airmass ** 1.06) * (1.0 - t_aerosol)
822+
rs = 0.0685 + (1.0 - asymmetry) * (1.0 - t_aerosol / taa)
823+
id_ = 0.9662 * etr * t_aerosol * t_water * t_gases * t_ozone * t_rayleigh
824+
ze_cos = np.where(zenith < 90, np.cos(ze_rad), 0.0)
825+
id_nh = id_ * ze_cos
826+
ias = (
827+
etr * ze_cos * 0.79 * t_ozone * t_gases * t_water * taa *
828+
(0.5 * (1.0 - t_rayleigh) + asymmetry * (1.0 - (t_aerosol / taa))) / (
829+
1.0 - airmass + airmass ** 1.02
830+
)
831+
)
832+
gh = (id_nh + ias) / (1.0 - albedo * rs)
833+
diffuse_horiz = gh - id_nh
834+
# TODO: be DRY, use decorator to wrap methods that need to return either
835+
# OrderedDict or DataFrame instead of repeating this boilerplate code
836+
irrads = OrderedDict()
837+
irrads['direct_horizontal'] = id_nh
838+
irrads['ghi'] = gh
839+
irrads['dni'] = id_
840+
irrads['dhi'] = diffuse_horiz
841+
if isinstance(irrads['dni'], pd.Series):
842+
irrads = pd.DataFrame.from_dict(irrads)
843+
return irrads

0 commit comments

Comments
 (0)