pvlib / pvlib-python

A set of documented functions for simulating the performance of photovoltaic energy systems.
https://pvlib-python.readthedocs.io
BSD 3-Clause "New" or "Revised" License
1.13k stars 955 forks source link

Add shaded fraction (FS) calculation for true-tracking on flat terrain #1689

Closed williamhobbs closed 1 month ago

williamhobbs commented 1 year ago

Is your feature request related to a problem? Please describe. It would be useful to have a shaded fraction calculation for true-tracking on flat terrain. It could be used in modeling thin film projects with (approximately) linear power loss due to self-shade.

image

Describe the solution you'd like An implementation of equations 1-6 in Lorenzo 2011 [1], where inputs are:

And the output is shaded fraction (0-1) of each shaded row.

Describe alternatives you've considered Custom implementations would not be difficult, but a built-in function would be nice. More robust versions that can account for non-horizontal tracker rotation axis, non-flat terrain, etc., would be nice, but are more difficult.

Additional context Here's the description we used in a 2023 PVRW poster on the topic [2], adapted from [1]:

Calculate the ideal tracker angle,

ω = arctan(cos(θA) * sin(θel) / sin(θA))

where θel is solar elevation and θA is solar azimuth. Then calculate the shaded fraction of the array, FS, as

FS = max[0, (1-cos(ω)/GCR)]

where GCR is the row spacing divided by tracker table width.

[1] E. Lorenzo, L Narvarte, and J Muñoz. 2011. "Tracking and back-tracking". Progress in Photovoltaics: Research and Applications 19: 747-753. https://doi.org/10.1002/pip.1085 [2] I. Azad, W. Hobbs, "Improved PV expected energy modeling with a simple self-shading model". NREL PVRW 2023. (proceedings pending) [3] K. Anderson, W. Hobbs. "Improved CdTe PLR Estimates: Self-Shading and Spectral Mismatch". NREL PVRW, 2022. https://www.osti.gov/biblio/1846944

AdamRJensen commented 1 year ago

I think the math would be relatively simple also for calculating shading for conditions where the actual tracker rotation angle is not necessarily equal to true tracking. This would be a more general implementation and useful for more scenarios, e.g., it could be used for fixed-tilt systems.

In either case, I support this addition - even if for just having a method for detecting when shading is occurring.

mikofski commented 1 year ago

Wow I actually have code already ready for this including flipped terrain. I’m presenting it in a poster at pvpmc in may! Shall we compare?

mikofski commented 1 year ago

@williamhobbs & @AdamRJensen I’ll send you my Jupyter notebooks and post a or here. @jdnewmil has looked it over too

williamhobbs commented 1 year ago

@AdamRJensen and @mikofski, thanks for the quick replies! @cwhanse saw our poster at PVRW and suggested that this, along with https://github.com/pvlib/pvlib-python/issues/1690, could make for a good pvlib addition.

I like @AdamRJensen's ideas:

I think the math would be relatively simple also for calculating shading for conditions where the actual tracker rotation angle is not necessarily equal to true tracking. This would be a more general implementation and useful for more scenarios, e.g., it could be used for fixed-tilt systems.

@mikofski - should "flipped terrain" in your comment be "sloped terrain"?

What I proposed above also does not allow for anything other than North-South aligned trackers, which is not ideal.

mikofski commented 1 year ago

Ha yes auto correct! (Shakes first!)

cwhanse commented 1 year ago

Is this already in pvlib.bifacial.infinite_sheds here?

AdamRJensen commented 1 year ago

Is this already in pvlib.bifacial.infinite_sheds here?

I'm quite confident that @cwhanse is correct. It certainly seems like Equation 32 of @kanderso-nrel's report on Slope-Aware Backtracking for Single-Axis Trackers.

Seems like the _shaded_fraction function should just be made public and perhaps moved to a less specific module.

kandersolar commented 1 year ago

Is this already in pvlib.bifacial.infinite_sheds here?

717 originally had that code as a public function in pvlib.shading but later changed it to be private. I can't quite remember why. Maybe we couldn't quickly agree on a public interface and didn't want to hold up the rest of the PR.

It certainly seems like Equation 32

This infinite_sheds function implements a special case of it where the axis tilt and cross-axis slope are zero, I believe.

One limitation of Eq 32 is that it assumes the shaded and shading rows are tracking together (i.e. they have the same rotation angle). I have a generalized equation that addresses that limitation but it does not yet appear in any publication. I think whatever we implement now should have an eye towards being extendable in the future to that generalization (probably just adding a kwarg for the second rotation angle).