Last active
November 27, 2019 21:28
-
-
Save mikofski/690fc526b0af1d42f48f2a883cee5fd4 to your computer and use it in GitHub Desktop.
pvlib_gh656
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pvlib | |
import numpy as np | |
import pandas as pd | |
import matplotlib.pyplot as plt | |
# in Brazil so facing north | |
axis_azimuth = 0.0 | |
axis_tilt = 20 | |
max_angle = 75.0 | |
gcr = 0.35 | |
# Brazil, timezone is UTC-3[hrs] | |
starttime = '2017-01-01T00:30:00-0300' | |
stoptime = '2017-12-31T23:59:59-0300' | |
lat, lon = -27.597300, -48.549610 | |
times = pd.DatetimeIndex(pd.date_range( | |
starttime, stoptime, freq='5T')) | |
solpos = pvlib.solarposition.get_solarposition( | |
times, lat, lon) | |
# get the early times | |
ts0 = '2017-01-01 05:30:00-03:00' | |
ts1 = '2017-01-01 12:30:00-03:00' | |
apparent_zenith = solpos['apparent_zenith'][ts0:ts1] | |
azimuth = solpos['azimuth'][ts0:ts1] | |
# current implementation | |
sat = pvlib.tracking.singleaxis( | |
apparent_zenith, azimuth, axis_tilt, axis_azimuth, max_angle, True, gcr) | |
# turn off backtracking and set max angle to 180[deg] | |
sat180no = pvlib.tracking.singleaxis( | |
apparent_zenith, azimuth, axis_tilt, axis_azimuth, max_angle=180, gcr=gcr, backtrack=False) | |
# calculate cos(R) | |
# cos(R) = L / Lx, R is rotation, L is surface length, | |
# Lx is shadow on ground, tracker shades when Lx > x | |
# x is row spacing related to GCR, x = L/GCR | |
lrot = np.cos(np.radians(sat180no.tracker_theta)) | |
# proposed backtracking algorithm for sun below trackers | |
# Note: if tr_rot > 90[deg] then lrot < 0 | |
# which *can* happen at low angles if axis tilt > 0 | |
# tracker should never backtrack more than 90[deg], when lrot = 0 | |
# if sun below trackers then use abs() to reverse direction of trackers | |
cos_rot = np.minimum(np.abs(lrot) / gcr, 1.0) | |
backtrack_rot = np.degrees(np.arccos(cos_rot)) | |
# combine backtracking correction with the true-tracked rotation | |
# Note: arccosine always positive between [-90, 90] so change | |
# sign of backtrack correction depending on which way tracker is rotating | |
tracker_wbacktrack = sat180no.tracker_theta - np.sign(sat180no.tracker_theta) * backtrack_rot | |
# plot figure | |
df = pd.DataFrame({ | |
'sat': sat.tracker_theta, | |
'sat180no': sat180no.tracker_theta, | |
'lrot': lrot, | |
'cos_rot': cos_rot, | |
'backtrack_rot': backtrack_rot, | |
'tracker_wbacktrack': tracker_wbacktrack}) | |
plt.ion() | |
df[['sat', 'sat180no', 'tracker_wbacktrack']].iloc[:25].plot() | |
plt.title('proposed backtracking for sun below tracker') | |
plt.ylabel('tracker rotation [degrees]') | |
plt.yticks(np.arange(-30,200,15)) | |
plt.grid() | |
from shapely.geometry.polygon import LinearRing | |
from shapely import affinity | |
from shapely.geometry import LineString | |
L = 1.6 # length of trackers | |
P = L/gcr # distance between rows | |
f = plt.figure('trackers') # new figure | |
# true track position at 5:30AM | |
tracker_theta = -np.radians(df.sat180no.values[0]) | |
# tracker 1 circle | |
pts1 = np.radians(np.arange(360)) | |
pts1 = np.stack((L/2*np.cos(pts1), L/2*np.sin(pts1)), axis=1) | |
circle1 = LinearRing(pts1) | |
plt.plot(*circle1.xy, ':') | |
# tracker 2 circle | |
pts2 = np.radians(np.arange(360)) | |
pts2 = np.stack((P + L/2*np.cos(pts2), L/2*np.sin(pts2)), axis=1) | |
circle2 = LinearRing(pts2) | |
plt.plot(*circle2.xy, ':') | |
# tracker 1 surface | |
tracker1 = LineString([(-L/2, 0), (L/2, 0)]) | |
plt.plot(*tracker1.xy, '-.') | |
tracker1rot = affinity.rotate( | |
tracker1, tracker_theta, use_radians=True) | |
plt.plot(*tracker1rot.xy) | |
# tracker 2 surface | |
tracker2 = LineString([(P-L/2, 0), (P+L/2, 0)]) | |
plt.plot(*tracker2.xy, '-.') | |
center2 = shapely.geometry.Point((P, 0)) | |
tracker2rot = affinity.rotate( | |
tracker2, angle=tracker_theta, use_radians=True, origin=center2) | |
plt.plot(*tracker2rot.xy) | |
# sunray | |
a, b = tracker2rot.coords | |
d0 = b[0] - P | |
d1 = b[1] - P * np.tan(tracker_theta-np.pi/2) | |
sunray2 = LineString([b, (d0, d1)]) | |
plt.plot(*sunray2.xy, '--') | |
# backtracking | |
tracker_theta = -np.radians(df.tracker_wbacktrack.values[0]) | |
# backtrack tracker 1 surface | |
tracker1 = LineString([(-L/2, 0), (L/2, 0)]) | |
tracker1rot = affinity.rotate( | |
tracker1, tracker_theta, use_radians=True) | |
plt.plot(*tracker1rot.xy) | |
# tracker 2 surface | |
tracker2 = LineString([(P-L/2, 0), (P+L/2, 0)]) | |
center2 = shapely.geometry.Point((P, 0)) | |
tracker2rot = affinity.rotate( | |
tracker2, angle=tracker_theta, use_radians=True, origin=center2) | |
plt.plot(*tracker2rot.xy) | |
# parallel sunrays | |
sun_angle1 = np.arctan2(*reversed(np.diff(sunray1.xy))) | |
# sun_angle2 = np.arctan2(*reversed(np.diff(sunray2.xy))) | |
a, b = tracker1rot.coords | |
c0 = a[0] + P + L | |
c1 = a[1] + (P+L) * np.tan(sun_angle1) | |
sunray1 = LineString([a, (c0, c1)]) | |
plt.plot(*sunray1.xy, '--') | |
# alternate backtracking | |
tracker_theta = -np.radians(df.sat.values[0]) | |
# backtrack tracker 1 surface | |
tracker1 = LineString([(-L/2, 0), (L/2, 0)]) | |
tracker1rot = affinity.rotate( | |
tracker1, tracker_theta, use_radians=True) | |
plt.plot(*tracker1rot.xy) | |
# tracker 2 surface | |
tracker2 = LineString([(P-L/2, 0), (P+L/2, 0)]) | |
center2 = shapely.geometry.Point((P, 0)) | |
tracker2rot = affinity.rotate( | |
tracker2, angle=tracker_theta, use_radians=True, origin=center2) | |
plt.plot(*tracker2rot.xy) | |
plt.gca().axis('equal') | |
plt.ylim([-2,6]) | |
plt.xlim([-2,6]) | |
plt.grid() | |
plt.title('Backtracking with sun below trackers') | |
plt.xlabel('distance between rows') | |
plt.ylabel('height above "system" plane') | |
plt.legend([ | |
'tracker 1', | |
'tracker 2', | |
'tracker 1: system plane', | |
'tracker 1: true track 98.3[deg]', | |
'tracker 2: system plane', | |
'tracker 2: true track 98.3[deg]', | |
'sunray', | |
'tracker 1: backtrack 32.5[deg]', | |
'tracker 2: backtrack 32.5[deg]', | |
'parallel sunray', | |
'tracker 1: alt backtrack -16[deg] or 164[deg]', | |
'tracker 2: alt backtrack -16[deg] or 164[deg]']) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment