diff --git a/docs/examples/bifacial/README.rst b/docs/examples/bifacial/README.rst new file mode 100644 index 0000000000..1c29b82ead --- /dev/null +++ b/docs/examples/bifacial/README.rst @@ -0,0 +1,3 @@ +Bifacial Modeling +----------------- + diff --git a/docs/examples/bifacial/plot_bifi_model_mc.py b/docs/examples/bifacial/plot_bifi_model_mc.py new file mode 100644 index 0000000000..caa5cf7ce4 --- /dev/null +++ b/docs/examples/bifacial/plot_bifi_model_mc.py @@ -0,0 +1,120 @@ +""" +Bifacial Modeling - modelchain +============================== + +Example of bifacial modeling using pvfactors and 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.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.bifacial.pvfactors import pvfactors_timeseries +import warnings + +# supressing shapely warnings that occur on import of pvfactors +warnings.filterwarnings(action='ignore', module='pvfactors') + +# 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 +# explicity simulate on pvarray with 3 rows, with sensor placed in middle row +# users may select different values depending on needs +irrad = 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, + n_pvrows=3, + index_observed_pvrow=1 + ) + +# 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) + +# ModelChain requires the parameter aoi_loss to have a value. pvfactors +# applies surface reflection models in the calculation of front and back +# irradiance, so assign aoi_model='no_loss' to avoid double counting +# reflections. +mc_bifi = modelchain.ModelChain(system, site_location, aoi_model='no_loss') +mc_bifi.run_model_from_effective_irradiance(irrad) + +# plot results +mc_bifi.results.ac.plot(title='Bifacial Simulation on June Solstice', + ylabel='AC Power') diff --git a/docs/examples/bifacial/plot_bifi_model_pvwatts.py b/docs/examples/bifacial/plot_bifi_model_pvwatts.py new file mode 100644 index 0000000000..3a0a7674a6 --- /dev/null +++ b/docs/examples/bifacial/plot_bifi_model_pvwatts.py @@ -0,0 +1,115 @@ +""" +Bifacial Modeling - procedural +============================== + +Example of bifacial modeling using pvfactors and 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.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.bifacial.pvfactors import pvfactors_timeseries +from pvlib import temperature +from pvlib import pvsystem +import matplotlib.pyplot as plt +import warnings + +# supressing shapely warnings that occur on import of pvfactors +warnings.filterwarnings(action='ignore', module='pvfactors') + +# 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 + +# explicity simulate on pvarray with 3 rows, with sensor placed in middle row +# users may select different values depending on needs +irrad = 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, + n_pvrows=3, + index_observed_pvrow=1 + ) + +# turn into pandas DataFrame +irrad = pd.concat(irrad, axis=1) + +# using bifaciality factor and pvfactors results, create effective irradiance +bifaciality = 0.75 +effective_irrad_bifi = irrad['total_abs_front'] + (irrad['total_abs_back'] + * bifaciality) + +# get cell temperature using the Faiman model +temp_cell = temperature.faiman(effective_irrad_bifi, 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 diff --git a/docs/sphinx/source/whatsnew/v0.9.1.rst b/docs/sphinx/source/whatsnew/v0.9.1.rst index ddd747d2d0..363fca15a9 100644 --- a/docs/sphinx/source/whatsnew/v0.9.1.rst +++ b/docs/sphinx/source/whatsnew/v0.9.1.rst @@ -53,6 +53,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 the + :py:func:`pvlib.bifacial.pvfactors_timeseries` function and either + :py:class:`pvlib.modelchain.ModelChain` or procedural functions. + (:pull:`1394`) * Fix some typos (:pull:`1414`) Requirements @@ -69,4 +73,5 @@ Contributors * Kevin Anderson (:ghuser:`kanderso-nrel`) * Adam R. Jensen (:ghuser:`AdamRJensen`) * Johann Loux (:ghuser:`JoLo90`) +* Saurabh Aneja (:ghuser:`spaneja`) * Jack Kelly (:ghuser:`JackKelly`) diff --git a/setup.py b/setup.py index 5b92e0ff4e..7301f5eab6 100755 --- a/setup.py +++ b/setup.py @@ -59,7 +59,7 @@ 'doc': ['ipython', 'matplotlib', 'sphinx == 3.1.2', 'pydata-sphinx-theme == 0.8.0', '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(), [])))