Skip to content

Commit 27a92b0

Browse files
committed
Update average_photon_energy.py
continuing creation
1 parent 2c3bb4a commit 27a92b0

File tree

1 file changed

+86
-7
lines changed

1 file changed

+86
-7
lines changed

docs/examples/spectrum/average_photon_energy.py

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@
2525
# import the required packages and define some basic system parameters and
2626
# and meteorological conditions.
2727
# %%
28-
from pvlib import spectrum, solarposition, irradiance, atmosphere
28+
import numpy as np
2929
import pandas as pd
3030
import matplotlib.pyplot as plt
31+
from scipy.integrate import trapezoid
32+
from pvlib import spectrum, solarposition, irradiance, atmosphere
3133

3234
lat, lon = 39.742, -105.18 # NREL SRRL location
3335
tilt = 25
@@ -38,7 +40,7 @@
3840
ozone = 0.31 # atm-cm
3941
albedo = 0.2
4042

41-
times = pd.date_range('2023-01-01 12:00', freq='D', periods=7,
43+
times = pd.date_range('2023-01-01 08:00', freq='h', periods=9,
4244
tz='America/Denver')
4345
solpos = solarposition.get_solarposition(times, lat, lon)
4446
aoi = irradiance.aoi(tilt, azimuth, solpos.apparent_zenith, solpos.azimuth)
@@ -58,7 +60,7 @@
5860
# The next section will show how to convert this output into a suitable
5961
# input for :pyfunc:`~average_photon_energy`.
6062

61-
spectra = spectrum.spectrl2(
63+
spectra_components = spectrum.spectrl2(
6264
apparent_zenith=solpos.apparent_zenith,
6365
aoi=aoi,
6466
surface_tilt=tilt,
@@ -69,11 +71,89 @@
6971
ozone=ozone,
7072
aerosol_turbidity_500nm=tau500,
7173
)
74+
7275
# %%
73-
# another section
74-
# --------------------------------
76+
# Visualising the spectral data
77+
# -----------------------------
78+
# Let's take a look at the spectral irradiance data simulated on the hour for
79+
# eight hours on the first day of 2023.
80+
81+
plt.figure()
82+
plt.plot(spectra_components['wavelength'], spectra_components['poa_global'])
83+
plt.xlim(200, 2700)
84+
plt.ylim(0, 1.8)
85+
plt.ylabel(r"Irradiance (Wm⁻²nm⁻¹")
86+
plt.xlabel(r"Wavelength (nm)")
87+
time_labels = times.strftime("%H:%M")
88+
labels = [
89+
"{}, AM {:0.02f}".format(*vals)
90+
for vals in zip(time_labels, relative_airmass)
91+
]
92+
plt.legend(labels)
93+
plt.show()
94+
95+
# Given the changing irradiance throughout the day, it is not obvious from
96+
# inspection how the relative distribution of light changes as a function of
97+
# wavelength. We can normalise the spectral irradiance curves to get an idea
98+
# of this shift in the shape of the spectrum over the course of the day. In
99+
# this example, we normalise by dividing each spectral irradiance value by the
100+
# total irradiance, as calculated by integrating the entire spectral irradiance
101+
# distribution with respect to wavelength.
102+
103+
poa_global = spectra_components['poa_global']
104+
wavelength = spectra_components['wavelength']
105+
106+
broadband_irradiance = np.array([trapezoid(poa_global[:, i], wavelength)
107+
for i in range(poa_global.shape[1])])
108+
109+
poa_global_normalised = poa_global / broadband_irradiance
110+
111+
# Plot the normalised spectra
112+
113+
plt.figure()
114+
plt.plot(wavelength, poa_global_normalised)
115+
plt.xlim(200, 2700)
116+
plt.ylim(0, 0.0018)
117+
plt.ylabel(r"Normalised Irradiance (nm⁻¹)")
118+
plt.xlabel(r"Wavelength (nm)")
119+
time_labels = times.strftime("%H:%M")
120+
labels = [
121+
"{}, AM {:0.02f}".format(*vals)
122+
for vals in zip(time_labels, relative_airmass)
123+
]
124+
plt.legend(labels)
125+
plt.show()
126+
127+
# Now we can see from XX figure numbers? XX that at the start and end of the
128+
# day, the spectrum is red shifted, meaning there is a greater proportion of
129+
# longer wavelength radiation. Meanwhile, during the middle of the day there is
130+
# a blue shift in the spectral distribution, indicating a greater prevalence of
131+
# shorter wavelength radiation.
132+
133+
# How can we quantify this shift? That is where the average photon energy comes
134+
# into play.
135+
75136
# %%
76-
#
137+
# Calculating the average photon energy
138+
# -------------------------------------
139+
# To calculate the APE, first we must convert our output spectra from from the
140+
# simulation into a compatible input for
141+
# :pyfunc:`pvlib.spectrum.average_photon_energy`. Since we have more than one
142+
# spectral irradiance distribution, a :py:class:`pandas.DataFrame` is
143+
# appropriate. We also need to set the column headers as wavelength, so each
144+
# row is a single spectral irradiance distribution. It is important to remember
145+
# here that the calculation of APE is dependent on the integration limits, i.e.
146+
# the wavelength range of the spectral irradiance input. APE values are only
147+
# comparable if calculated between the same integration limits. In this case,
148+
# our APE values are calculated between 300nm and 4000nm.
149+
150+
spectra = pd.DataFrame(poa_global).T # convert to dataframe and transpose
151+
spectra.index = time_labels # add time index
152+
spectra.columns = wavelength # add wavelength column headers
153+
154+
ape = spectrum.average_photon_energy(spectra)
155+
156+
# XX table? add values / arrow(s) to graph XX
77157

78158
# %%
79159
# References
@@ -90,4 +170,3 @@
90170
# Energy 286 :doi:`10.1016/j.energy.2023.129461`
91171
# .. [4] Bird Simple Spectral Model: spectrl2_2.c.
92172
# https://www.nrel.gov/grid/solar-resource/spectral.html
93-

0 commit comments

Comments
 (0)