Difference between PVFactors and ModelChain effective irradiance #1590
-
When I calculate the effective irradiance with PVFactors and only consider the front surface, I get (slightly) different results than when calculating the effective irradiance with ModelChain. Here is an example with a South Facing Fixed Mount with no losses. I understand that the gcr has an influence on PVFactors calculation (and not on ModelChain) How can I configure PVFactors to match the results of ModelChain ? 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
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS as PARAMS
from pvlib import modelchain
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)
# example array geometry
pvrow_height = 1
pvrow_width = 4
pitch = 10
gcr = pvrow_width / pitch
surface_azimuth = 180 # south-facing array
axis_azimuth = surface_azimuth - 90
albedo = 0.25
surface_tilt = 25
## 1. Calculate the effective Irradiance with ModelChain
mount = pvsystem.FixedMount(surface_tilt=surface_tilt, surface_azimuth=surface_azimuth)
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_']
array = pvsystem.Array(mount=mount,
module_parameters=cec_module,
temperature_model_parameters=temp_model_parameters)
system = pvsystem.PVSystem(arrays=[array],
inverter_parameters=cec_inverter)
mc = modelchain.ModelChain(system, site_location, spectral_model='no_loss', aoi_model='no_loss')
_ = mc.run_model(cs)
## 2. Calculate the effective Irradiance with PVFactors
irrad = pvfactors_timeseries(solar_azimuth=solar_position['azimuth'],
solar_zenith=solar_position['apparent_zenith'],
surface_azimuth=surface_azimuth, # south-facing array
surface_tilt=surface_tilt,
axis_azimuth = axis_azimuth,
timestamps=times,
dni=cs['dni'],
dhi=cs['dhi'],
gcr=gcr,
pvrow_height=pvrow_height,
pvrow_width=pvrow_width,
albedo=albedo,
n_pvrows=3,
index_observed_pvrow=1)
irrad = pd.concat(irrad, axis=1)
#Compare both Effective Irradiance
effec_irr_MC = mc.results.effective_irradiance.sum()
effec_irr_PVFactors = irrad['total_inc_front'].sum() #We consider the Incident irradiance not to include AOI losses
print("MC: ", effec_irr_MC, "PVFactors: ", effec_irr_PVFactors)
>> MC: 437953.13574622635 PVFactors: 441780.10564860125 SImilarly with a Single Axis Tracker facing East to West 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
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS as PARAMS
from pvlib import modelchain
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)
# example array geometry
pvrow_height = 5 # height must be higher than width for trackers
pvrow_width = 4
pitch = 10
gcr = pvrow_width / pitch
surface_azimuth = 90 # Facing East/West
axis_azimuth = surface_azimuth - 90
albedo = 0.25
surface_tilt = 25
# load solar position and tracker orientation for use in pvsystem object
mount = pvsystem.SingleAxisTrackerMount(axis_azimuth=axis_azimuth,
backtrack=False)
# created for use in pvfactors timeseries
orientation = mount.get_orientation(solar_position['apparent_zenith'],
solar_position['azimuth'])
## 1. Calculate the effective Irradiance with ModelChain
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_']
array = pvsystem.Array(mount=mount,
module_parameters=cec_module,
temperature_model_parameters=temp_model_parameters)
system = pvsystem.PVSystem(arrays=[array],
inverter_parameters=cec_inverter)
mc = modelchain.ModelChain(system, site_location, spectral_model='no_loss', aoi_model='no_loss')
_ = mc.run_model(cs)
## 2. Calculate the effective Irradiance with PVFactors
irrad = pvfactors_timeseries(solar_azimuth=solar_position['azimuth'],
solar_zenith=solar_position['apparent_zenith'],
surface_azimuth=orientation['surface_azimuth'], # south-facing array
surface_tilt=orientation['surface_tilt'],
axis_azimuth = axis_azimuth,
timestamps=times,
dni=cs['dni'],
dhi=cs['dhi'],
gcr=gcr,
pvrow_height=pvrow_height,
pvrow_width=pvrow_width,
albedo=albedo,
n_pvrows=3,
index_observed_pvrow=1)
irrad = pd.concat(irrad, axis=1)
#Compare both Effective Irradiance
effec_irr_MC = mc.results.effective_irradiance.sum()
effec_irr_PVFactors = irrad['total_inc_front'].sum() #We consider the Incident irradiance not to include AOI losses
print("MC: ", effec_irr_MC, "PVFactors: ", effec_irr_PVFactors) |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Can you say a bit about why you'd want to do this? If you want the results from ModelChain, why not just use ModelChain (or There are two main sources of difference in your results:
When I reconfigure the fixed tilt script to account for those two differences, the difference in summed irradiance goes nearly to zero (<0.04%). But again it's not clear to me why you would want to do this; pvfactors will be slower for the same answer. P.S., "effective irradiance" usually includes AOI loss (and other effects like soiling and spectrum adjustment); what is being compared here is the incident irradiance aka POA irradiance or GTI. |
Beta Was this translation helpful? Give feedback.
-
Thanks @kanderso-nrel. In fact, when isolating the row and specifying the same transposition model, I get very close results. On the Single-Axis Tracker, I get 0.1% difference with an albedo=0 (that I also specify in my pvsystem.Array) and 0.7% with an albedo=1. The ground diffuse is probably considered differently in both tools. Agreed that I should have rather used mc.results.total_irrad['poa_gloal'] than effective_irradiance to compare POA irradiances. I want to compare the power ouput of results calculated with PVLIB ModelChain with a monofacial panel with the output of the same array adding bifaciality. I agree that it is probably simpler to re-calculate everything with PVFactors but out of curiosity I wanted to understand the level of differences between the 2 modeling approaches. Side question, on a field with important gcr, is it good practice to add the self-shading diffuse losses calculated with pvlib.shading.sky_diffuse_passias to my Model Chain losses ? |
Beta Was this translation helpful? Give feedback.
Can you say a bit about why you'd want to do this? If you want the results from ModelChain, why not just use ModelChain (or
pvlib.irradiance.get_total_irradiance
)? And at some point the difference in results between pvfactors and ModelChain will be due to pvfactors' increased level of simulation detail, so configuring it to match ModelChain seems like a step backwards anyway.There are two main sources of difference in your results:
print(mc)
to see what yours is using), while pvfactors uses the Perez model. Specifytransposition_model='perez'
in the ModelCh…