-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add agrivPV gallery example #2459
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
Merged
Merged
Changes from 6 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
0d4652f
Add agrivPV gallery example
AdamRJensen e07b8c7
Update v0.12.1.rst
AdamRJensen 5995974
Fix rendering
AdamRJensen be52070
Fix spelling mistakes
AdamRJensen e27f412
Fix typo
AdamRJensen c2877b2
Apply suggestions from code review
AdamRJensen 14105e6
Fix stickler
AdamRJensen 239b0bf
Improve intro text
AdamRJensen a7097f2
Implement feedback from Ioannis
AdamRJensen 23247c1
Update input values to match European Energy's site
AdamRJensen 223d954
Merge branch 'main' into agripv-gallery-example
AdamRJensen f7220ee
Fix linter
AdamRJensen c5034d7
Merge branch 'agripv-gallery-example' of https://github.com/AdamRJens…
AdamRJensen 5c39a3c
Break url in multiple lines
AdamRJensen 4bf03bb
Update thumbnail path
AdamRJensen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
156 changes: 156 additions & 0 deletions
156
docs/examples/agrivoltaics/plot_agrivoltaics_ground_irradiance.py
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
""" | ||
AgriPV with infinite sheds | ||
========================== | ||
|
||
Irradiance at crop level between rows | ||
""" | ||
|
||
# %% | ||
# This example demonstrates how to calculate irradiance at crop level | ||
# for an agriPV system using pvlib's infinite sheds model. | ||
# For an overview of agrivPV concepts and performance, the reader | ||
# is referred to :doi:`10.69766/XAEU5008`. | ||
# | ||
# The first steps are to define the plant location and to calculate solar position | ||
# and clearsky irradiance for a single day as an example. | ||
# | ||
# .. figure:: ../../_images/agrivoltaics_system.jpg | ||
# :align: center | ||
# :width: 75% | ||
# :alt: Photo of an agriPV system | ||
# | ||
# Photo of an agriPV system. | ||
# *Source: Adam R. Jensen* | ||
|
||
import pvlib | ||
from pvlib.tools import cosd # we'll want this later | ||
AdamRJensen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
import pandas as pd | ||
import matplotlib.pyplot as plt | ||
|
||
location = pvlib.location.Location(latitude=55, longitude=10) | ||
|
||
times = pd.date_range('2020-06-28', periods=24*60, freq='1min', tz='UTC') | ||
|
||
solpos = location.get_solarposition(times) | ||
|
||
clearsky = location.get_clearsky(times, model='ineichen') | ||
|
||
# %% | ||
# Next, we need to define the plant layout: | ||
|
||
height = 3 # [m] height of torque above ground | ||
pitch = 12 # [m] row spacing | ||
row_width = 2 * 2 # [m] two modules in portrait, each 2 m long | ||
gcr = row_width / pitch # ground coverage ratio [unitless] | ||
axis_azimuth = 0 # [degrees] north-south tracking axis | ||
max_angle = 50 # [degrees] maximum rotation angle | ||
|
||
# %% | ||
# Before running the infinite sheds model, we need to know the orientation | ||
# of the trackers. For a single-axis tracker, this can be calculated as: | ||
|
||
tracking_orientations = pvlib.tracking.singleaxis( | ||
apparent_zenith=solpos['apparent_zenith'], | ||
apparent_azimuth=solpos['azimuth'], | ||
axis_azimuth=axis_azimuth, | ||
max_angle=max_angle, | ||
backtrack=True, | ||
gcr=gcr, | ||
) | ||
|
||
# %% | ||
# For agrivPV systems, the local albedo is dependent on crop growth and thus | ||
# changes throughout the seasons. In this example, we only simulate one | ||
# day and thus use a constant value. Similarly, we will assume a constant | ||
# air temperature to avoid getting external data. Both albedo and air temperature | ||
# could be defined as Series with the same index as used for the solar position | ||
# calculations. | ||
|
||
albedo = 0.25 # [unitless] | ||
temp_air = 18 # [degrees C] | ||
|
||
# %% | ||
# Now, we are ready to calculate the front and rear-side irradiance using | ||
# the pvlib infinite sheds model. | ||
|
||
dni_extra = pvlib.irradiance.get_extra_radiation(times) | ||
|
||
irradiance = pvlib.bifacial.infinite_sheds.get_irradiance( | ||
surface_tilt=tracking_orientations['surface_tilt'], | ||
surface_azimuth=tracking_orientations['surface_azimuth'], | ||
solar_zenith=solpos['apparent_zenith'], | ||
solar_azimuth=solpos['azimuth'], | ||
gcr=gcr, | ||
height=height, | ||
pitch=pitch, | ||
ghi=clearsky['ghi'], | ||
dhi=clearsky['dhi'], | ||
dni=clearsky['dni'], | ||
albedo=albedo, | ||
model='haydavies', | ||
dni_extra=dni_extra, | ||
bifaciality=0.8, | ||
AdamRJensen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
|
||
# %% | ||
# Once the in-plane irradiance is known, we can estimate the PV array power. | ||
# For simplicity, we use the PVWatts model: | ||
|
||
N_tables = 108 | ||
AdamRJensen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
modules_per_table = 14 | ||
pdc0_per_module = 380 # [W] STC rating | ||
pdc0 = pdc0_per_module * modules_per_table * N_tables | ||
|
||
gamma_pdc = -0.004 # [1/degrees C] | ||
|
||
temp_cell = pvlib.temperature.faiman( | ||
poa_global=irradiance['poa_global'], | ||
temp_air=temp_air, | ||
) | ||
|
||
power_dc = pvlib.pvsystem.pvwatts_dc( | ||
g_poa_effective=irradiance['poa_global'], | ||
temp_cell=temp_cell, | ||
pdc0=pdc0, | ||
gamma_pdc=gamma_pdc) | ||
|
||
power_dc.divide(1000).plot() | ||
plt.ylabel('DC power [kW]') | ||
plt.show() | ||
|
||
# %% | ||
# In addition to the power output of the PV array, we are also interested | ||
# in how much irradiance reaches the crops under the array. In this case | ||
# we calculate the average irradiance on the ground between two rows, using | ||
# the infinite sheds utility functions. | ||
# | ||
# This consists of two parts. First we determine the diffuse irradiance on | ||
# ground and second we calculate the fraction of the ground that is unshaded | ||
# (i.e., receives DNI). | ||
|
||
vf_ground_sky = pvlib.bifacial.utils.vf_ground_sky_2d_integ( | ||
surface_tilt=tracking_orientations['surface_tilt'], | ||
gcr=gcr, | ||
height=height, | ||
pitch=pitch, | ||
) | ||
|
||
unshaded_ground_fraction = pvlib.bifacial.utils._unshaded_ground_fraction( | ||
surface_tilt=tracking_orientations['surface_tilt'], | ||
surface_azimuth=tracking_orientations['surface_azimuth'], | ||
solar_zenith=solpos['apparent_zenith'], | ||
solar_azimuth=solpos['azimuth'], | ||
gcr=gcr, | ||
) | ||
|
||
crop_avg_irradiance = (unshaded_ground_fraction * clearsky['dni'] | ||
* cosd(solpos['apparent_zenith']) | ||
+ vf_ground_sky * clearsky['dhi']) | ||
|
||
fig, ax = plt.subplots() | ||
clearsky['ghi'].plot(ax=ax, label='Horizontal irradiance above panels') | ||
crop_avg_irradiance.plot(ax=ax, label='Horizontal irradiance at crop level') | ||
ax.legend(loc='upper center') | ||
ax.set_ylabel('Irradiance [W/m$^2$]') | ||
ax.set_ylim(-10, 1050) | ||
plt.show() |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.