Note
Click here to download the full example code
Solar Tracking Art¶
Art based on variants of the single-axis tracking equations.
This example plays around with the cross-axis tilt parameter of the “slope-aware backtracking” method described in 1).
References¶
- 1
Kevin Anderson and Mark Mikofski, “Slope-Aware Backtracking for Single-Axis Trackers”, Technical Report NREL/TP-5K00-76626, July 2020. https://www.nrel.gov/docs/fy20osti/76626.pdf
import pvlib
import pandas as pd
from numpy import sin, cos, arctan2, arccos, radians, degrees, sign, array
import matplotlib.pyplot as plt
import imageio
import io
times = pd.date_range('2019-06-01', '2019-06-02', freq='5s', tz='Etc/GMT+5')
location = pvlib.location.Location(40, -80)
solpos = location.get_solarposition(times)
gcr = 0.5
beta_a = 0
beta_s = radians(solpos.elevation)
gamma_s = radians(solpos.azimuth)
s = array([
cos(beta_s) * sin(gamma_s),
cos(beta_s) * cos(gamma_s),
sin(beta_s)
])
frames = []
for i, beta_c in enumerate(radians(range(-90, 90, 2))):
fig = plt.figure()
for gamma_a in radians([0, 180]):
sp = array([
s[0] * cos(gamma_a) - s[1] * sin(gamma_a),
s[0] * sin(gamma_a) * cos(beta_a) + s[1] * cos(beta_a) * cos(gamma_a) - s[2]*sin(beta_a),
s[0] * sin(gamma_a) * sin(beta_a) + s[1] * sin(beta_a) * cos(gamma_a) + s[2]*cos(beta_a)
])
theta_t = arctan2(sp[0], sp[2])
theta_t = pd.Series(theta_t, index=times)
numerator = abs(cos(theta_t - beta_c))
denominator = gcr * cos(beta_c)
arg = numerator / denominator
arg[abs(arg) > 1] = 1
theta_c = -sign(theta_t) * arccos(arg)
theta_c[theta_c.isnull() & (beta_s > 0)] = 0
degrees(theta_t).plot()
degrees(theta_t + theta_c).plot()
plt.title(fr"$\beta_c$={degrees(beta_c):0.01f}$\degree$")
plt.ylabel(r"Tracker Angle [$\degree$]")
buffer = io.BytesIO()
plt.savefig(buffer)
if beta_c == 0:
# repeat frames at beta_c=0 for visual effect
for i in range(10):
frames.append(buffer)
thumbnail = fig
else:
frames.append(buffer)
plt.close(fig) # only close if not using for thumbnail
thumbnail.show()

with imageio.get_writer('../../images/solar-tracking-art.gif', mode='I') as writer:
for buffer in frames:
buffer.seek(0)
image = imageio.imread(buffer)
writer.append_data(image)

Total running time of the script: ( 1 minutes 26.422 seconds)