-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Shaded Fraction on Sloped Terrains - PR1725 partial continuation #1962
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 109 commits
c87885c
4fc6cd8
2a72f33
d6e8067
13a56d4
f012aae
6dd9a3b
e8743db
6030774
6276382
509699f
5ff8fd8
04126e0
607a246
240b551
997def6
7912055
f068e3e
a5f4a85
a854e27
2d82375
5f24721
049a8cc
a3185df
b9f1a76
f7d1d80
1880f6a
d9f242a
379ca95
62e99ad
4f584ea
238d123
98a254d
4616175
33ffd28
8526bc6
bde3656
51e3750
35738a4
8d679c3
4a907c1
234288d
fb0e5d1
aa4b6e8
18b2187
4163a72
1ebf8ea
de2144f
6aa43f0
c34a2f6
6b9f478
c3a9569
4bb02ab
78c481e
0ce0d68
74b4215
909cc23
e3e73f6
cbb0b04
96b61a8
d2b9291
7ec4d64
bbc6115
39a3ba9
a3ccf3e
e5fffca
457d4b4
f11858e
f321cc1
0ab3720
e6da6e8
4ce1655
60b7e2e
2d23cb2
78a451c
28128f6
f4acf39
104d185
894ff9f
f147881
4d11294
69c76cf
758f5e7
6882dfa
4ef4567
574a1a2
efac0b3
3a726b8
300b912
497a62e
2a34f43
c1b3978
db8edd6
d65e64d
51a2dfa
9038097
5652801
31affba
80ab494
facde21
5a807b7
25a0f19
8bdd469
a2e8be7
9f1fa97
37ab496
6303583
e785292
9b98d9e
3726e4d
4e7e36f
59465c8
9fa2bb4
1be1d3e
0d521ee
f01bd6f
946cca6
5e4bc7d
9a7d5b7
7f1d549
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
""" | ||
shaded_fraction1d N-S horizontal single-axis example | ||
==================================================== | ||
|
||
This example illustrates how to calculate the shaded fraction of three rows | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
in an N-S HSAT configuration. | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
|
||
# %% | ||
# :py:func:`pvlib.shading.shaded_fraction1d` exposes a useful method for the | ||
# calculation of the shaded fraction of the width of a solar collector. Here, | ||
# the width is defined as the dimension perpendicular to the axis of rotation. | ||
# This method for calculating the shaded fraction also applies to fixed-tilt | ||
# systems with little changes. | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# | ||
# Reading its documentation is recommended to understand the parameters and | ||
# the method capabilities. | ||
# | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# Let's start by obtaining the true-tracking angles for each of the rows and | ||
# limiting the angles to the range of -50 to 50 degrees. This decision is | ||
# done to allow significant shade to be used as an example. | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# | ||
# Key functions used in this example are: | ||
# | ||
# 1. :py:func:`pvlib.tracking.singleaxis` to calculate the tracking angles. | ||
# 2. :py:func:`pvlib.shading.projected_solar_zenith_angle` to calculate the | ||
# projected solar zenith angle. | ||
# 3. :py:func:`pvlib.shading.shaded_fraction1d` to calculate the shaded | ||
# fractions. | ||
# | ||
# .. sectionauthor:: Echedey Luis <echelual (at) gmail.com> | ||
|
||
import pvlib | ||
|
||
import numpy as np | ||
import pandas as pd | ||
import matplotlib.pyplot as plt | ||
from matplotlib.dates import DateFormatter | ||
|
||
# Define the solar system parameters | ||
latitude, longitude = 28.51, -13.89 | ||
altitude = pvlib.location.lookup_altitude(latitude, longitude) | ||
|
||
axis_tilt = 3 # degrees | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a comment about what this represents? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me know your opinion on |
||
axis_azimuth = 180 # degrees | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
collector_width = 3.2 # m | ||
pitch = 4.15 # m | ||
gcr = collector_width / pitch | ||
cross_axis_slope = -5 # degrees | ||
AdamRJensen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
surface_to_axis_offset = 0.07 # m | ||
|
||
# Generate a time range for the simulation | ||
times = pd.date_range( | ||
start="2024-01-01T05", | ||
end="2024-01-01T21", | ||
freq="5min", | ||
tz="Atlantic/Canary", | ||
) | ||
|
||
# Calculate the solar position | ||
solar_position = pvlib.solarposition.get_solarposition( | ||
times, latitude, longitude, altitude | ||
) | ||
solar_azimuth = solar_position["azimuth"] | ||
solar_zenith = solar_position["apparent_zenith"] | ||
|
||
# Calculate the tracking angles | ||
rotation_angle = pvlib.tracking.singleaxis( | ||
solar_zenith, | ||
solar_azimuth, | ||
axis_tilt, | ||
axis_azimuth, | ||
max_angle=(-50, 50), # (min, max) degrees | ||
backtrack=False, | ||
gcr=gcr, | ||
cross_axis_tilt=cross_axis_slope, | ||
)["tracker_theta"] | ||
|
||
# %% | ||
# The next step is to calculate the shaded fraction. Special care must be taken | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# to ensure that the shaded or shading tracker roles are correctly assigned | ||
# depending on the solar position. | ||
# This means we will have a result for each row, ``eastmost_shaded_fraction``, | ||
# ``middle_shaded_fraction``, and ``westmost_shaded_fraction``. | ||
# Switching the parameters will be based on the | ||
# sign of :py:func:`pvlib.shading.projected_solar_zenith_angle`. | ||
# | ||
# The following code is verbose to make it easier to understand the process, | ||
# but with some effort you may be able to simplify it. This verbosity also | ||
# allows to change the premises easily per case, e.g., in case of a tracker | ||
# failure or with a different system configuration. | ||
|
||
psza = pvlib.shading.projected_solar_zenith_angle( | ||
solar_zenith, solar_azimuth, axis_tilt, axis_azimuth | ||
) | ||
|
||
# Calculate the shaded fraction for the eastmost row | ||
eastmost_shaded_fraction = np.where( | ||
psza < 0, | ||
0, # no shaded fraction in the morning | ||
# shaded fraction in the evening | ||
pvlib.shading.shaded_fraction1d( | ||
solar_zenith, | ||
solar_azimuth, | ||
axis_azimuth, | ||
shaded_row_rotation=rotation_angle, | ||
axis_tilt=axis_tilt, | ||
collector_width=collector_width, | ||
pitch=pitch, | ||
surface_to_axis_offset=surface_to_axis_offset, | ||
cross_axis_slope=cross_axis_slope, | ||
shading_row_rotation=rotation_angle, | ||
), | ||
) | ||
|
||
# Calculate the shaded fraction for the middle row | ||
middle_shaded_fraction = np.where( | ||
psza < 0, | ||
# shaded fraction in the morning | ||
pvlib.shading.shaded_fraction1d( | ||
solar_zenith, | ||
solar_azimuth, | ||
axis_azimuth, | ||
shaded_row_rotation=rotation_angle, | ||
axis_tilt=axis_tilt, | ||
collector_width=collector_width, | ||
pitch=pitch, | ||
surface_to_axis_offset=surface_to_axis_offset, | ||
cross_axis_slope=cross_axis_slope, | ||
shading_row_rotation=rotation_angle, | ||
), | ||
# shaded fraction in the evening | ||
pvlib.shading.shaded_fraction1d( | ||
solar_zenith, | ||
solar_azimuth, | ||
axis_azimuth, | ||
shaded_row_rotation=rotation_angle, | ||
axis_tilt=axis_tilt, | ||
collector_width=collector_width, | ||
pitch=pitch, | ||
surface_to_axis_offset=surface_to_axis_offset, | ||
cross_axis_slope=cross_axis_slope, | ||
shading_row_rotation=rotation_angle, | ||
), | ||
) | ||
|
||
# Calculate the shaded fraction for the westmost row | ||
westmost_shaded_fraction = np.where( | ||
psza < 0, | ||
# shaded fraction in the morning | ||
pvlib.shading.shaded_fraction1d( | ||
solar_zenith, | ||
solar_azimuth, | ||
axis_azimuth, | ||
shaded_row_rotation=rotation_angle, | ||
axis_tilt=axis_tilt, | ||
collector_width=collector_width, | ||
pitch=pitch, | ||
surface_to_axis_offset=surface_to_axis_offset, | ||
cross_axis_slope=cross_axis_slope, | ||
shading_row_rotation=rotation_angle, | ||
), | ||
0, # no shaded fraction in the evening | ||
) | ||
|
||
# %% | ||
# Plot the shaded fraction result per row | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
plt.plot(times, eastmost_shaded_fraction, label="East-most", color="blue") | ||
plt.plot( | ||
times, | ||
middle_shaded_fraction, | ||
label="Middle", | ||
color="green", | ||
linewidth=3, | ||
linestyle="--", | ||
) | ||
echedey-ls marked this conversation as resolved.
Show resolved
Hide resolved
|
||
plt.plot(times, westmost_shaded_fraction, label="West-most", color="red") | ||
plt.title(r"$shaded\_fraction1d$ of each row vs time") | ||
plt.xlabel("Time") | ||
plt.gca().xaxis.set_major_formatter(DateFormatter("%H:%M")) | ||
plt.ylabel("Shaded Fraction") | ||
plt.legend() | ||
plt.show() | ||
|
||
# %% |
Uh oh!
There was an error while loading. Please reload this page.