Skip to content

Commit f1c16f2

Browse files
spanejacwhansekandersolar
authored
gallery example for bifacial modeling with pvfactors (#1394)
* adding initial gallery examples * updating bifacial examples added pvfactors into setup.py, cleaned up some white spacing, and hoping for the best... * gallery_updates * whatsnew * updates from comments * comment update * updated comments, warnings, and variables * whitespace * small edits * Apply suggestions from code review Co-authored-by: Cliff Hansen <[email protected]> * Update docs/sphinx/source/whatsnew/v0.9.1.rst Co-authored-by: Cliff Hansen <[email protected]> Co-authored-by: Kevin Anderson <[email protected]>
1 parent 46e11a9 commit f1c16f2

File tree

5 files changed

+244
-1
lines changed

5 files changed

+244
-1
lines changed

docs/examples/bifacial/README.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Bifacial Modeling
2+
-----------------
3+
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
"""
2+
Bifacial Modeling - modelchain
3+
==============================
4+
5+
Example of bifacial modeling using pvfactors and ModelChain
6+
"""
7+
8+
# %%
9+
# This example shows how to complete a bifacial modeling example using the
10+
# :py:class:`pvlib.modelchain.ModelChain` with the
11+
# :py:func:`pvlib.bifacial.pvfactors.pvfactors_timeseries` function
12+
# to transpose GHI data to both front and rear Plane of Array (POA) irradiance.
13+
#
14+
# Unfortunately ``ModelChain`` does not yet support bifacial simulation
15+
# directly so we have to do the bifacial irradiance simulation ourselves.
16+
# Once the combined front + rear irradiance is known, we can pass that
17+
# to ``ModelChain`` and proceed as usual.
18+
#
19+
# Future versions of pvlib may make it easier to do bifacial modeling
20+
# with ``ModelChain``.
21+
22+
import pandas as pd
23+
from pvlib import pvsystem
24+
from pvlib import location
25+
from pvlib import modelchain
26+
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS as PARAMS
27+
from pvlib.bifacial.pvfactors import pvfactors_timeseries
28+
import warnings
29+
30+
# supressing shapely warnings that occur on import of pvfactors
31+
warnings.filterwarnings(action='ignore', module='pvfactors')
32+
33+
# create site location and times characteristics
34+
lat, lon = 36.084, -79.817
35+
tz = 'Etc/GMT+5'
36+
times = pd.date_range('2021-06-21', '2021-6-22', freq='1T', tz=tz)
37+
38+
# create site system characteristics
39+
axis_tilt = 0
40+
axis_azimuth = 180
41+
gcr = 0.35
42+
max_angle = 60
43+
pvrow_height = 3
44+
pvrow_width = 4
45+
albedo = 0.2
46+
bifaciality = 0.75
47+
48+
# load temperature parameters and module/inverter specifications
49+
temp_model_parameters = PARAMS['sapm']['open_rack_glass_glass']
50+
cec_modules = pvsystem.retrieve_sam('CECMod')
51+
cec_module = cec_modules['Trina_Solar_TSM_300DEG5C_07_II_']
52+
cec_inverters = pvsystem.retrieve_sam('cecinverter')
53+
cec_inverter = cec_inverters['ABB__MICRO_0_25_I_OUTD_US_208__208V_']
54+
55+
# create a location for site, and get solar position and clearsky data
56+
site_location = location.Location(lat, lon, tz=tz, name='Greensboro, NC')
57+
solar_position = site_location.get_solarposition(times)
58+
cs = site_location.get_clearsky(times)
59+
60+
# load solar position and tracker orientation for use in pvsystem object
61+
sat_mount = pvsystem.SingleAxisTrackerMount(axis_tilt=axis_tilt,
62+
axis_azimuth=axis_azimuth,
63+
max_angle=max_angle,
64+
backtrack=True,
65+
gcr=gcr)
66+
67+
# created for use in pvfactors timeseries
68+
orientation = sat_mount.get_orientation(solar_position['apparent_zenith'],
69+
solar_position['azimuth'])
70+
71+
# get rear and front side irradiance from pvfactors transposition engine
72+
# explicity simulate on pvarray with 3 rows, with sensor placed in middle row
73+
# users may select different values depending on needs
74+
irrad = pvfactors_timeseries(solar_position['azimuth'],
75+
solar_position['apparent_zenith'],
76+
orientation['surface_azimuth'],
77+
orientation['surface_tilt'],
78+
axis_azimuth,
79+
times,
80+
cs['dni'],
81+
cs['dhi'],
82+
gcr,
83+
pvrow_height,
84+
pvrow_width,
85+
albedo,
86+
n_pvrows=3,
87+
index_observed_pvrow=1
88+
)
89+
90+
# turn into pandas DataFrame
91+
irrad = pd.concat(irrad, axis=1)
92+
93+
# create bifacial effective irradiance using aoi-corrected timeseries values
94+
irrad['effective_irradiance'] = (
95+
irrad['total_abs_front'] + (irrad['total_abs_back'] * bifaciality)
96+
)
97+
98+
# %%
99+
# With effective irradiance, we can pass data to ModelChain for
100+
# bifacial simulation.
101+
102+
# dc arrays
103+
array = pvsystem.Array(mount=sat_mount,
104+
module_parameters=cec_module,
105+
temperature_model_parameters=temp_model_parameters)
106+
107+
# create system object
108+
system = pvsystem.PVSystem(arrays=[array],
109+
inverter_parameters=cec_inverter)
110+
111+
# ModelChain requires the parameter aoi_loss to have a value. pvfactors
112+
# applies surface reflection models in the calculation of front and back
113+
# irradiance, so assign aoi_model='no_loss' to avoid double counting
114+
# reflections.
115+
mc_bifi = modelchain.ModelChain(system, site_location, aoi_model='no_loss')
116+
mc_bifi.run_model_from_effective_irradiance(irrad)
117+
118+
# plot results
119+
mc_bifi.results.ac.plot(title='Bifacial Simulation on June Solstice',
120+
ylabel='AC Power')
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
"""
2+
Bifacial Modeling - procedural
3+
==============================
4+
5+
Example of bifacial modeling using pvfactors and procedural method
6+
"""
7+
8+
# %%
9+
# This example shows how to complete a bifacial modeling example using the
10+
# :py:func:`pvlib.pvsystem.pvwatts_dc` with the
11+
# :py:func:`pvlib.bifacial.pvfactors.pvfactors_timeseries` function to
12+
# transpose GHI data to both front and rear Plane of Array (POA) irradiance.
13+
14+
import pandas as pd
15+
from pvlib import location
16+
from pvlib import tracking
17+
from pvlib.bifacial.pvfactors import pvfactors_timeseries
18+
from pvlib import temperature
19+
from pvlib import pvsystem
20+
import matplotlib.pyplot as plt
21+
import warnings
22+
23+
# supressing shapely warnings that occur on import of pvfactors
24+
warnings.filterwarnings(action='ignore', module='pvfactors')
25+
26+
# using Greensboro, NC for this example
27+
lat, lon = 36.084, -79.817
28+
tz = 'Etc/GMT+5'
29+
times = pd.date_range('2021-06-21', '2021-06-22', freq='1T', tz=tz)
30+
31+
# create location object and get clearsky data
32+
site_location = location.Location(lat, lon, tz=tz, name='Greensboro, NC')
33+
cs = site_location.get_clearsky(times)
34+
35+
# get solar position data
36+
solar_position = site_location.get_solarposition(times)
37+
38+
# set ground coverage ratio and max_angle to
39+
# pull orientation data for a single-axis tracker
40+
gcr = 0.35
41+
max_phi = 60
42+
orientation = tracking.singleaxis(solar_position['apparent_zenith'],
43+
solar_position['azimuth'],
44+
max_angle=max_phi,
45+
backtrack=True,
46+
gcr=gcr
47+
)
48+
49+
# set axis_azimuth, albedo, pvrow width and height, and use
50+
# the pvfactors engine for both front and rear-side absorbed irradiance
51+
axis_azimuth = 180
52+
pvrow_height = 3
53+
pvrow_width = 4
54+
albedo = 0.2
55+
56+
# explicity simulate on pvarray with 3 rows, with sensor placed in middle row
57+
# users may select different values depending on needs
58+
irrad = pvfactors_timeseries(solar_position['azimuth'],
59+
solar_position['apparent_zenith'],
60+
orientation['surface_azimuth'],
61+
orientation['surface_tilt'],
62+
axis_azimuth,
63+
cs.index,
64+
cs['dni'],
65+
cs['dhi'],
66+
gcr,
67+
pvrow_height,
68+
pvrow_width,
69+
albedo,
70+
n_pvrows=3,
71+
index_observed_pvrow=1
72+
)
73+
74+
# turn into pandas DataFrame
75+
irrad = pd.concat(irrad, axis=1)
76+
77+
# using bifaciality factor and pvfactors results, create effective irradiance
78+
bifaciality = 0.75
79+
effective_irrad_bifi = irrad['total_abs_front'] + (irrad['total_abs_back']
80+
* bifaciality)
81+
82+
# get cell temperature using the Faiman model
83+
temp_cell = temperature.faiman(effective_irrad_bifi, temp_air=25,
84+
wind_speed=1)
85+
86+
# using the pvwatts_dc model and parameters detailed above,
87+
# set pdc0 and return DC power for both bifacial and monofacial
88+
pdc0 = 1
89+
gamma_pdc = -0.0043
90+
pdc_bifi = pvsystem.pvwatts_dc(effective_irrad_bifi,
91+
temp_cell,
92+
pdc0,
93+
gamma_pdc=gamma_pdc
94+
).fillna(0)
95+
pdc_bifi.plot(title='Bifacial Simulation on June Solstice', ylabel='DC Power')
96+
97+
# %%
98+
# For illustration, perform monofacial simulation using pvfactors front-side
99+
# irradiance (AOI-corrected), and plot along with bifacial results.
100+
101+
effective_irrad_mono = irrad['total_abs_front']
102+
pdc_mono = pvsystem.pvwatts_dc(effective_irrad_mono,
103+
temp_cell,
104+
pdc0,
105+
gamma_pdc=gamma_pdc
106+
).fillna(0)
107+
108+
# plot monofacial results
109+
plt.figure()
110+
plt.title('Bifacial vs Monofacial Simulation - June Solstice')
111+
pdc_bifi.plot(label='Bifacial')
112+
pdc_mono.plot(label='Monofacial')
113+
plt.ylabel('DC Power')
114+
plt.legend()
115+
# sphinx_gallery_thumbnail_number = 2

docs/sphinx/source/whatsnew/v0.9.1.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ Documentation
5353
~~~~~~~~~~~~~
5454
* Fix documentation return error in :py:meth:`pvlib.forecast.ForecastModel.cloud_cover_to_transmittance_linear`
5555
(:issue:`1367`, :pull:`1370`)
56+
* Add gallery example illustrating bifacial simulation using the
57+
:py:func:`pvlib.bifacial.pvfactors_timeseries` function and either
58+
:py:class:`pvlib.modelchain.ModelChain` or procedural functions.
59+
(:pull:`1394`)
5660
* Fix some typos (:pull:`1414`)
5761

5862
Requirements
@@ -69,4 +73,5 @@ Contributors
6973
* Kevin Anderson (:ghuser:`kanderso-nrel`)
7074
* Adam R. Jensen (:ghuser:`AdamRJensen`)
7175
* Johann Loux (:ghuser:`JoLo90`)
76+
* Saurabh Aneja (:ghuser:`spaneja`)
7277
* Jack Kelly (:ghuser:`JackKelly`)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
'doc': ['ipython', 'matplotlib', 'sphinx == 3.1.2',
6060
'pydata-sphinx-theme == 0.8.0', 'sphinx-gallery',
6161
'docutils == 0.15.2', 'pillow', 'netcdf4', 'siphon',
62-
'sphinx-toggleprompt >= 0.0.5'],
62+
'sphinx-toggleprompt >= 0.0.5', 'pvfactors'],
6363
'test': TESTS_REQUIRE
6464
}
6565
EXTRAS_REQUIRE['all'] = sorted(set(sum(EXTRAS_REQUIRE.values(), [])))

0 commit comments

Comments
 (0)