Skip to content

gallery example for bifacial modeling with pvfactors #1394

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 14 commits into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/examples/bifacial/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Bifacial Modeling
-----------------

108 changes: 108 additions & 0 deletions docs/examples/bifacial/plot_bifi_model_mc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"""
Bifacial Modeling - modelchain
==============================

Example of bifacial modeling using the modelchain
"""

# %%
# This example shows how to complete a bifacial modeling example using the
# :py:class:`pvlib.modelchain.ModelChain` with the
# :py:func:`pvlib.bifacial.pvfactors_timeseries` function to transpose
# GHI data to both front and rear Plane of Array (POA) irradiance.
#
# Unfortunately ``ModelChain`` does not yet support bifacial simulation
# directly so we have to do the bifacial irradiance simulation ourselves.
# Once the combined front + rear irradiance is known, we can pass that
# to ``ModelChain`` and proceed as usual.
#
# Future versions of pvlib may make it easier to do bifacial modeling
# with ``ModelChain``.

import pandas as pd
from pvlib import pvsystem
from pvlib import location
from pvlib import modelchain
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS as PARAMS
from pvlib import bifacial

# create site location and times characteristics
lat, lon = 36.084, -79.817
tz = 'Etc/GMT+5'
times = pd.date_range('2021-06-21', '2021-6-22', freq='1T', tz=tz)

# create site system characteristics
axis_tilt = 0
axis_azimuth = 180
gcr = 0.35
max_angle = 60
pvrow_height = 3
pvrow_width = 4
albedo = 0.2
bifaciality = 0.75

# load temperature parameters and module/inverter specifications
temp_model_parameters = PARAMS['sapm']['open_rack_glass_glass']
cec_modules = pvsystem.retrieve_sam('CECMod')
cec_module = cec_modules['Trina_Solar_TSM_300DEG5C_07_II_']
cec_inverters = pvsystem.retrieve_sam('cecinverter')
cec_inverter = cec_inverters['ABB__MICRO_0_25_I_OUTD_US_208__208V_']

# create a location for site, and get solar position and clearsky data
site_location = location.Location(lat, lon, tz=tz, name='Greensboro, NC')
solar_position = site_location.get_solarposition(times)
cs = site_location.get_clearsky(times)

# load solar position and tracker orientation for use in pvsystem object
sat_mount = pvsystem.SingleAxisTrackerMount(axis_tilt=axis_tilt,
axis_azimuth=axis_azimuth,
max_angle=max_angle,
backtrack=True,
gcr=gcr)

# created for use in pvfactors timeseries
orientation = sat_mount.get_orientation(solar_position['apparent_zenith'],
solar_position['azimuth'])

# get rear and front side irradiance from pvfactors transposition engine
irrad = bifacial.pvfactors_timeseries(solar_position['azimuth'],
solar_position['apparent_zenith'],
orientation['surface_azimuth'],
orientation['surface_tilt'],
axis_azimuth,
times,
cs['dni'],
cs['dhi'],
gcr,
pvrow_height,
pvrow_width,
albedo)

# turn into pandas DataFrame
irrad = pd.concat(irrad, axis=1)

# create bifacial effective irradiance using aoi-corrected timeseries values
irrad['effective_irradiance'] = (
irrad['total_abs_front'] + (irrad['total_abs_back'] * bifaciality)
)

# %%
# With effective irradiance, we can pass data to ModelChain for
# bifacial simulation.

# dc arrays
array = pvsystem.Array(mount=sat_mount,
module_parameters=cec_module,
temperature_model_parameters=temp_model_parameters)

# create system object
system = pvsystem.PVSystem(arrays=[array],
inverter_parameters=cec_inverter)

# create modelchain object for bifacial system and run bifacial simulation
mc_bifi = modelchain.ModelChain(system, site_location, aoi_model='no_loss')
mc_bifi.run_model_from_effective_irradiance(irrad)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a small inelegance that specifying aoi_model is necessary for a ModelChain that only uses run_model_from_effective_irradiance. I don't see a way around it, so I don't think there's anything to be done in this PR, just thinking out loud about the ModelChain design.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could default to None but then we'd need to check for a valid model in other run_model methods.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Converted to #1411


# plot results
mc_bifi.results.ac.plot(title='Bifacial Simulation on June Solstice',
ylabel='AC Power')
111 changes: 111 additions & 0 deletions docs/examples/bifacial/plot_bifi_model_pvwatts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"""
Bifacial Modeling - procedural
==============================

Example of bifacial modeling using procedural method
"""

# %%
# This example shows how to complete a bifacial modeling example using the
# :py:func:`pvlib.pvsystem.pvwatts_dc` with the
# :py:func:`pvlib.bifacial.pvfactors_timeseries` function to transpose
# GHI data to both front and rear Plane of Array (POA) irradiance.

import pandas as pd
from pvlib import location
from pvlib import tracking
from pvlib import bifacial
from pvlib import temperature
from pvlib import pvsystem
import matplotlib.pyplot as plt

# using Greensboro, NC for this example
lat, lon = 36.084, -79.817
tz = 'Etc/GMT+5'
times = pd.date_range('2021-06-21', '2021-06-22', freq='1T', tz=tz)

# create location object and get clearsky data
site_location = location.Location(lat, lon, tz=tz, name='Greensboro, NC')
cs = site_location.get_clearsky(times)

# get solar position data
solar_position = site_location.get_solarposition(times)

# set ground coverage ratio and max_angle to
# pull orientation data for a single-axis tracker
gcr = 0.35
max_phi = 60
orientation = tracking.singleaxis(solar_position['apparent_zenith'],
solar_position['azimuth'],
max_angle=max_phi,
backtrack=True,
gcr=gcr
)

# set axis_azimuth, albedo, pvrow width and height, and use
# the pvfactors engine for both front and rear-side absorbed irradiance
axis_azimuth = 180
pvrow_height = 3
pvrow_width = 4
albedo = 0.2
irrad = bifacial.pvfactors_timeseries(solar_position['azimuth'],
solar_position['apparent_zenith'],
orientation['surface_azimuth'],
orientation['surface_tilt'],
axis_azimuth,
cs.index,
cs['dni'],
cs['dhi'],
gcr,
pvrow_height,
pvrow_width,
albedo
)

# turn into pandas DataFrame
irrad = pd.concat(irrad, axis=1)

# using bifaciality factor and pvfactors results, create effective
# irradiance data
bifaciality = 0.75
effective_irrad_bifi = irrad['total_abs_front'] + (irrad['total_abs_back']
* bifaciality)


# get cell temperature using the Faiman model
# it is worth noting that this example uses total frontside incident
# irradiance, however, for bifacial modeling, total irradiance (inclusive of
# front and rear side) may be needed.
temp_cell = temperature.faiman(irrad['total_inc_front'], temp_air=25,
wind_speed=1)

# using the pvwatts_dc model and parameters detailed above,
# set pdc0 and return DC power for both bifacial and monofacial
pdc0 = 1
gamma_pdc = -0.0043
pdc_bifi = pvsystem.pvwatts_dc(effective_irrad_bifi,
temp_cell,
pdc0,
gamma_pdc=gamma_pdc
).fillna(0)
pdc_bifi.plot(title='Bifacial Simulation on June Solstice', ylabel='DC Power')

# %%
# For illustration, perform monofacial simulation using pvfactors front-side
# irradiance (AOI-corrected), and plot along with bifacial results.

effective_irrad_mono = irrad['total_abs_front']
pdc_mono = pvsystem.pvwatts_dc(effective_irrad_mono,
temp_cell,
pdc0,
gamma_pdc=gamma_pdc
).fillna(0)

# plot monofacial results
plt.figure()
plt.title('Bifacial vs Monofacial Simulation - June Solstice')
pdc_bifi.plot(label='Bifacial')
pdc_mono.plot(label='Monofacial')
plt.ylabel('DC Power')
plt.legend()
# sphinx_gallery_thumbnail_number = 2
6 changes: 5 additions & 1 deletion docs/sphinx/source/whatsnew/v0.9.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ Documentation
~~~~~~~~~~~~~
* Fix documentation return error in :py:meth:`pvlib.forecast.ForecastModel.cloud_cover_to_transmittance_linear`
(:issue:`1367`, :pull:`1370`)

* Add gallery example illustrating bifacial simulation using :py:class:`pvlib.modelchain.ModelChain`
and the :py:func:`pvlib.bifacial.pvfactors_timeseries` function (:pull:`1394`)
* Add gallery example illustrating bifacial simulation using procedural functions
and the :py:func:`pvlib.bifacial.pvfactors_timeseries` function (:pull:`1394`)

Requirements
~~~~~~~~~~~~
Expand All @@ -46,3 +49,4 @@ Contributors
* Kevin Anderson (:ghuser:`kanderso-nrel`)
* Adam R. Jensen (:ghuser:`AdamRJensen`)
* Johann Loux (:ghuser:`JoLo90`)
* Saurabh Aneja (:ghuser:`spaneja`)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
'doc': ['ipython', 'matplotlib', 'sphinx == 3.1.2',
'pydata-sphinx-theme', 'sphinx-gallery', 'docutils == 0.15.2',
'pillow', 'netcdf4', 'siphon',
'sphinx-toggleprompt >= 0.0.5'],
'sphinx-toggleprompt >= 0.0.5', 'pvfactors'],
'test': TESTS_REQUIRE
}
EXTRAS_REQUIRE['all'] = sorted(set(sum(EXTRAS_REQUIRE.values(), [])))
Expand Down