Help explaining bifacial panel irradiance result with backtracking

36 views
Skip to first unread message

Ben Farmer

unread,
Jun 18, 2025, 6:16:58 AMJun 18
to pvlib-python
Hi all,

I apologise in advance if I am making a rookie error here, but I am having trouble interpreting the results of the pvlib.bifacial.infinite_sheds.get_irradiance function for a tracked system with backtrack=True. Specifically the
backtracking somehow makes no difference, which is bizarre to me because that is a totally separate calculation. I can only suppose I am somehow passing in the tracking information incorrectly, though it seemed straightforward. So perhaps there is something else I am doing wrong or don't understand.

Here's my minimal example:

```
import pvlib
import pandas as pd

tz = 'Australia/Melbourne'
dts = pd.date_range(start="2024-01-01", end="2024-01-02", freq='30min', tz=tz, name="Datetime")
df = pd.DataFrame(index=dts)
lat = -36.479
lon = 146.172
gcr = 4/7
axis_tilt = 0  # Flat ground
axis_azimuth = 0  # N-S orientation
max_angle = 90
height = 2
pitch = 5

# Simple clearsky irradiance
loc = pvlib.location.Location(lat, lon, tz)
df_i = loc.get_clearsky(dts)

# Sun position data
solpos = pvlib.solarposition.get_solarposition(dts, lat, lon)

# Tracking
def get_df_tracking(backtrack):
    return pvlib.tracking.singleaxis(
        solpos.apparent_zenith, solpos.azimuth, axis_tilt, axis_azimuth, max_angle=90, backtrack=backtrack, gcr=gcr
        )

# Panel irradiance
def panel_irr(df_tracking, df_irr, bifacial):
    if bifacial:
        # Parameters set to reduce back panel illumination to zero, for easier comparison to single-face result
        irr = pvlib.bifacial.infinite_sheds.get_irradiance(
            df_tracking.surface_tilt, df_tracking.surface_azimuth, solpos.apparent_zenith, solpos.azimuth, gcr, height, pitch,
            df_irr.ghi, df_irr.dhi, df_irr.dni, albedo=0.18, model='isotropic', iam_front=1,
            bifaciality=0, shade_factor=1, transmission_factor=1, vectorize=False
            )
    else:
        poa_sky_diffuse = pvlib.irradiance.isotropic(df_tracking.surface_tilt, df_irr.dhi)
        poa_ground_diffuse = pvlib.irradiance.get_ground_diffuse(df_tracking.surface_tilt, df_irr.ghi, surface_type='urban')
        irr = pvlib.irradiance.poa_components(df_tracking.aoi, df_irr.dni, poa_sky_diffuse, poa_ground_diffuse)
    return irr

df_p_irr = []
names = []
for bifacial in [True, False]:
    for backtrack in [True, False]:
        df_tracking = get_df_tracking(backtrack)
        df_p_irr += [panel_irr(df_tracking, df_i, bifacial)]
        names += [f"backtrack={backtrack}; bifacial={bifacial}"]

df_comb = pd.concat([df.poa_global for df in df_p_irr], axis=1)
df_comb.columns = names
df_comb.plot(ylabel="poa_global", style=[".-", ".-", "--", "--"])
```

which produces the attached output.

The bifacial=False case makes sense to me, the irradiance is better without the backtracking since the panels point at the sun longer, and we don't consider shading outside of the tracking calculation.

But it is weird to me that the irradiance comes out the same for backtrack=True/False in the bifacial case. I guess the only explanation I can think of is that the bifacial computation uses the infinite sheds model, which should account for shading, and maybe it works out that the backtracking tracks backwards at exactly the right amount to minimise the impact of the shading? I mean that's kind of the point of it, but in that case shouldn't the bifacial calculation show a worse result without backtracking? Either way I am surprised it comes out so identically. Ok they aren't quite identical, but the impact seems extremely minimal, especially compared to the alternate calculation that neglects shading.

Best regards,

Ben

P.S. The bifacial calculation shows less irradiance overall, which would be odd, but I purposefully blocked all light to the back panel and the calculation is a little different, so I am not worried about that. Unless you think I should be :).

output.png

Echedey Luis Álvarez

unread,
Jun 18, 2025, 6:29:07 AMJun 18
to pvlib-...@googlegroups.com

Hi Ben,

I think the problem relies in the cited section down below, in bifaciality=0 ; the returned irradiances look like they are effective (else there wouldn't be a bifaciality factor) so setting it to zero means to ignore all the calculated irradiance in the back. So yeah, you can also use that piece of code to compare against monofacial modules.

Best,
Echedey.

Ben Farmer

unread,
Jun 18, 2025, 6:53:13 AMJun 18
to Echedey Luis Álvarez, pvlib-...@googlegroups.com
Hi Echedey,

Oh I know that much, but in your output I still see the same issue with backtracking. I turned off the back panel on purpose since it didn't seem relevant for my issue.

My question is why doesn't the bifacial=True, backtrack=False case look more like the bifacial=False, backtrack=False case? Is it just how the shading effect works out?

Regards,

Ben

--
You received this message because you are subscribed to the Google Groups "pvlib-python" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pvlib-python...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/pvlib-python/ce6a0491-3c08-4100-8d89-8e688cc2cef0%40gmail.com.

kevina...@gmail.com

unread,
Jun 18, 2025, 7:37:13 AMJun 18
to pvlib-python
Yes, it is due to shading.  Think about the column of beam irradiance incident on the array as a whole when the sun is low in the sky.  Regardless of whether the array is truetracking or backtracking, that entire column is going to get collected by the array -- it's just a matter of whether it is spread evenly across the module surface (backtracking) or concentrated in the upper portion (truetracking).  Mathematically, backtracking is the strategy that walks the tightrope that prevents shading without sacrificing any beam irradiance.

The infinite_sheds module reports the average irradiance across the module surface, so that uniformity difference gets smoothed out and you end up with the same overall beam contribution either way.  The only remaining difference is then from the diffuse components, and you'll notice that the backtracking case is slightly higher due to the better view factor to the sky.

Kevin

Ben Farmer

unread,
Jun 20, 2025, 9:57:21 AMJun 20
to kevina...@gmail.com, pvlib-python
Hi Kevin, 

Ah ok cool, thanks for that explanation. Good to know it all makes sense! 

Regards, 

Ben

Reply all
Reply to author
Forward
0 new messages