8000 Implement irradiance.complete_irradiance with component sum equations… · sickdabig/pvlib-python@e50def0 · GitHub
[go: up one dir, main page]

Skip to content

Commit e50def0

Browse files
kperrynrelPerrykandersolarcwhansewholmgren
authored
Implement irradiance.complete_irradiance with component sum equations (pvlib#1567)
* added new irradiance function for component sum * added to docstrings * updated docstrings * updated methods with new component_sum_irradiance() function * added associated unit test for the new component sum function * added units tests for the component_sum_irradiance() function * added whatsnew file for v0.9.4 * fixed modelchain error to stop unit test erroring * removed clearsky_dni arg for cases where it's not used * updated naming conventions for component_sum_irradiance function in modelchains * updated the routines to remove pep8 errors, added to clearsky_dni docstring * updated the routine to return dataframe after calculating component sum + other suggestions * updated the PR based on @kanderso-nrel review * made updates based on kanderso-nrel's suggestions * updated all the unit tests to pass * Update pvlib/irradiance.py Co-authored-by: Kevin Anderson <kevin.anderson@nrel.gov> * Update pvlib/irradiance.py Co-authored-by: Kevin Anderson <kevin.anderson@nrel.gov> * moved warning out of dni generation call (just ghi and dhi) * fix sticklerci formatting errors * Update pvlib/irradiance.py Co-authored-by: Kevin Anderson <kevin.anderson@nrel.gov> * updates to name-changed to 'complete_irradiance' * fixed over-indentation error * removed default none from function params * Update docs/sphinx/source/whatsnew/v0.9.4.rst Co-authored-by: Cliff Hansen <cwhanse@sandia.gov> * made updates based on @cwhanse's recommendations * Update pvlib/irradiance.py Co-authored-by: Will Holmgren <william.holmgren@gmail.com> * Update pvlib/irradiance.py Co-authored-by: Will Holmgren <william.holmgren@gmail.com> * changed to pytest error raise based on @wholmgren's recommendation * Made updates to code based on @wholmgren's recommendations * fix pep8 error 2 * updated modelchains to use zenith instead of apparent zenith * check that unit tests run * undo ModelChain.complete_irradiance test changes Co-authored-by: Perry <kperry@nrel.gov> Co-authored-by: Kevin Anderson <kevin.anderson@nrel.gov> Co-authored-by: Cliff Hansen <cwhanse@sandia.gov> Co-authored-by: Will Holmgren <william.holmgren@gmail.com>
1 parent dd6062a commit e50def0

File tree

5 files changed

+233
-91
lines changed

5 files changed

+233
-91
lines changed

docs/sphinx/source/reference/irradiance.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Decomposing and combining irradiance
2828
irradiance.poa_components
2929
irradiance.get_ground_diffuse
3030
irradiance.dni
31+
irradiance.complete_irradiance
3132

3233
Transposition models
3334
--------------------

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@ Deprecations
1010
Enhancements
1111
~~~~~~~~~~~~
1212
* Multiple code style issues fixed that were reported by LGTM analysis. (:issue:`1275`, :pull:`1559`)
13+
* Added a function to calculate one of GHI, DHI, and DNI from values of the other two.
14+
:py:func:`~pvlib.irradiance.complete_irradiance`
15+
(:issue:`1565`, :pull:`1567`)
1316
* Add optional ``return_components`` parameter to :py:func:`pvlib.irradiance.haydavies` to return
1417
individual diffuse irradiance components (:issue:`1553`, :pull:`1568`)
1518

19+
1620
Bug fixes
1721
~~~~~~~~~
1822

1923

20-
2124
Testing
2225
~~~~~~~
2326
* Corrected a flawed test for :py:func:`~pvlib.irradiance.get_ground_diffuse` (:issue:`1569`, :pull:`1575`)
@@ -36,6 +39,7 @@ Requirements
3639

3740
Contributors
3841
~~~~~~~~~~~~
42+
* Kirsten Perry (:ghuser:`kperrynrel`)
3943
* Christian Orner (:ghuser:`chrisorner`)
4044
* Saurabh Aneja (:ghuser:`spaneja`)
4145
* Marcus Boumans (:ghuser:`bowie2211`)

pvlib/irradiance.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import pandas as pd
1313

1414
from pvlib import atmosphere, solarposition, tools
15+
import pvlib # used to avoid dni name collision in complete_irradiance
1516

1617

1718
# see References section of get_ground_diffuse function
@@ -2948,3 +2949,67 @@ def dni(ghi, dhi, zenith, clearsky_dni=None, clearsky_tolerance=1.1,
29482949
(zenith < zenith_threshold_for_zero_dni) &
29492950
(dni > max_dni)] = max_dni
29502951
return dni
2952+
2953+
2954+
def complete_irradiance(solar_zenith,
2955+
ghi=None,
2956+
dhi=None,
2957+
dni=None,
2958+
dni_clear=None):
2959+
r"""
2960+
Use the component sum equations to calculate the missing series, using
2961+
the other available time series. One of the three parameters (ghi, dhi,
2962+
dni) is passed as None, and the other associated series passed are used to
2963+
calculate the missing series value.
2964+
2965+
The "component sum" or "closure" equation relates the three
2966+
primary irradiance components as follows:
2967+
2968+
.. math::
2969+
2970+
GHI = DHI + DNI \cos(\theta_z)
2971+
2972+
Parameters
2973+
----------
2974+
solar_zenith : Series
2975+
Zenith angles in decimal degrees, with datetime index.
2976+
Angles must be >=0 and <=180. Must have the same datetime index
2977+
as ghi, dhi, and dni series, when available.
2978+
ghi : Series, optional
2979+
Pandas series of dni data, with datetime index. Must have the same
2980+
datetime index as dni, dhi, and zenith series, when available.
2981+
dhi : Series, optional
2982+
Pandas series of dni data, with datetime index. Must have the same
2983+
datetime index as ghi, dni, and zenith series, when available.
2984+
dni : Series, optional
2985+
Pandas series of dni data, with datetime index. Must have the same
2986+
datetime index as ghi, dhi, and zenith series, when available.
2987+
dni_clear : Series, optional
2988+
Pandas series of clearsky dni data. Must have the same datetime index
2989+
as ghi, dhi, dni, and zenith series, when available. See
2990+
:py:func:`dni` for details.
2991+
2992+
Returns
2993+
-------
2994+
component_sum_df : Dataframe
2995+
Pandas series of 'ghi', 'dhi', and 'dni' columns with datetime index
2996+
"""
2997+
if ghi is not None and dhi is not None and dni is None:
2998+
dni = pvlib.irradiance.dni(ghi, dhi, solar_zenith,
2999+
clearsky_dni=dni_clear,
3000+
clearsky_tolerance=1.1)
3001+
elif dni is not None and dhi is not None and ghi is None:
3002+
ghi = (dhi + dni * tools.cosd(solar_zenith))
3003+
elif dni is not None and ghi is not None and dhi is None:
3004+
dhi = (ghi - dni * tools.cosd(solar_zenith))
3005+
else:
3006+
raise ValueError(
3007+
"Please check that exactly one of ghi, dhi and dni parameters "
3008+
"is set to None"
3009+
)
3010+
# Merge the outputs into a master dataframe containing 'ghi', 'dhi',
3011+
# and 'dni' columns
3012+
component_sum_df = pd.DataFrame({'ghi': ghi,
3013+
'dhi': dhi,
3014+
'dni': dni})
3015+
return component_sum_df

pvlib/modelchain.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,13 +1289,13 @@ def complete_irradiance(self, weather):
12891289
self._assign_times()
12901290
self.results.solar_position = self.location.get_solarposition(
12911291
self.results.times, method=self.solar_position_method)
1292-
1292+
# Calculate the irradiance using the component sum equations,
1293+
# if needed
12931294
if isinstance(weather, tuple):
12941295
for w in self.results.weather:
12951296
self._complete_irradiance(w)
12961297
else:
12971298
self._complete_irradiance(self.results.weather)
1298-
12991299
return self
13001300

13011301
def _complete_irradiance(self, weather):
@@ -1304,26 +1304,32 @@ def _complete_irradiance(self, weather):
13041304
"Results can be too high or negative.\n" +
13051305
"Help to improve this function on github:\n" +
13061306
"https://github.com/pvlib/pvlib-python \n")
1307-
13081307
if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns:
13091308
clearsky = self.location.get_clearsky(
13101309
weather.index, solar_position=self.results.solar_position)
1311-
weather.loc[:, 'dni'] = pvlib.irradiance.dni(
1312-
weather.loc[:, 'ghi'], weather.loc[:, 'dhi'],
1313-
self.results.solar_position.zenith,
1314-
clearsky_dni=clearsky['dni'],
1315-
clearsky_tolerance=1.1)
1310+
complete_irrad_df = pvlib.irradiance.complete_irradiance(
1311+
solar_zenith=self.results.solar_position.zenith,
1312+
ghi=weather.ghi,
1313+
dhi=weather.dhi,
1314+
dni=None,
1315+
dni_clear=clearsky.dni)
1316+
weather.loc[:, 'dni'] = complete_irrad_df.dni
13161317
elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns:
13171318
warnings.warn(wrn_txt, UserWarning)
1318-
weather.loc[:, 'ghi'] = (
1319-
weather.dhi + weather.dni *
1320-
tools.cosd(self.results.solar_position.zenith)
1321-
)
1319+
complete_irrad_df = pvlib.irradiance.complete_irradiance(
1320+
solar_zenith=self.results.solar_position.zenith,
1321+
ghi=None,
1322+
dhi=weather.dhi,
1323+
dni=weather.dni)
1324+
weather.loc[:, 'ghi'] = complete_irrad_df.ghi
13221325
elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns:
13231326
warnings.warn(wrn_txt, UserWarning)
1324-
weather.loc[:, 'dhi'] = (
1325-
weather.ghi - weather.dni *
1326-
tools.cosd(self.results.solar_position.zenith))
1327+
complete_irrad_df = pvlib.irradiance.complete_irradiance(
1328+
solar_zenith=self.results.solar_position.zenith,
1329+
ghi=weather.ghi,
1330+
dhi=None,
1331+
dni=weather.dni)
1332+
weather.loc[:, 'dhi'] = complete_irrad_df.dhi
13271333

13281334
def _prep_inputs_solar_pos(self, weather):
13291335
"""

0 commit comments

Comments
 (0)
0