Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linear shade gh1690 #1725

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open

Linear shade gh1690 #1725

wants to merge 13 commits into from

Conversation

mikofski
Copy link
Member

@mikofski mikofski commented May 4, 2023

add functions to get shaded fraction and calculate linear shade loss
ICYMI: @williamhobbs

Example:

>>> from pvlib import shading
# trivial case with tracker and psz at 45-deg no cross-axis slope, and gcr=0.8
>>> fs = shading.tracker_shaded_fraction(45.0, 0.8, 45.0, 0)
>>> loss = shading.linear_shade_loss(fs, 0.2)
>>> P_no_shade = 100  # [kWdc]  DC output from modules
>>> P_linear_shade = P_no_shade * (1-loss)  # [kWdc] output after loss
# 90.71067811865476 [kWdc]

@mikofski mikofski self-assigned this May 4, 2023
docs/sphinx/source/reference/tracking.rst Outdated Show resolved Hide resolved
pvlib/tracking.py Outdated Show resolved Hide resolved
pvlib/tracking.py Outdated Show resolved Hide resolved
pvlib/tracking.py Outdated Show resolved Hide resolved
@kandersolar kandersolar added this to the 0.9.6 milestone May 4, 2023
- move linear shade loss to shading module
- don't use ternary, doesn't work on vectors, instead use np.where()
- set cross axis default to zero
- test vectors
- update docs
- of github.com:mikofski/pvlib-python into linear_shade_gh1690
- applicable to other monolithic thin film like CIGS, not just CdTe
- only when shade is perpendicular to scribe lines
@mikofski
Copy link
Member Author

mikofski commented May 6, 2023

@kandersolar & @williamhobbs thanks for the feedback! I've addressed it. Can you review again?

@mikofski
Copy link
Member Author

mikofski commented May 6, 2023

👀 derivations and figures added to tracker_shaded_fraction() docstring

Copy link
Member

@AdamRJensen AdamRJensen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this function do the same as this existing function:

def _shaded_fraction(solar_zenith, solar_azimuth, surface_tilt,

Comment on lines +208 to +210
projected_solar_zenith : numeric
Zenith angle in degrees of the solar vector projected into the plane
perpendicular to the tracker axes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like it would be a lot easier for the user if the parameter was simply solar_zenith and the calculation to the projected solar zenith could be done behind the scenes (there should be a function for that in pvlib somewhere).

Copy link
Member Author

@mikofski mikofski May 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The calculation for psz requires at least one additional argument, the solar azimuth and is not a trivial calculation:

sp = pvl.solarposition.get_solarposition(times, latitude, longitude, ...)
proj_zenith = np.degrees(np.arctan2(
    np.sin(np.radians(sp.azimuth))*np.sin(np.radians(sp.apparent_zenith)),
    np.cos(np.radians(sp.apparent_zenith))))

It is already in pvlib here:

wid = np.degrees(np.arctan2(xp, zp))

which made me discover a typo in the comments here:

# vector (xp, yp, zp) in the (y, z) plane, which is normal to the panel and

should be the (x, z) plane, which is corrected lower down here:

# Calculate angle from x-y plane to projection of sun vector onto x-z plane

Anyway, I agree, it would be helpful to have PSZ as it's own function. And if it already exists in addition to tracking.py:432 then we should consolidate. I think it's out of scope for this PR, though so I'll open another one for that.

Copy link
Member Author

@mikofski mikofski May 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created #1734 to propose a stand alone PSZ function, but in the process, realized that the existing use in tracking.py actually calculates the solar vector as observed in the reference frame of the tracker axes, which may be tilted north or south. So this new function would need to be generalized to different reference frames.

I'm coming around to this idea. One instant advantage of this standalone function would be generalization of this linear shade loss function to arbitrary slopes that have both NS and EW tilt! Thanks! However, I still think it's best to address separately, then return to this function to enhance it with the axis tilt and the solar azimuth.

pvlib/shading.py Outdated Show resolved Hide resolved
pvlib/shading.py Outdated
def tracker_shaded_fraction(tracker_theta, gcr, projected_solar_zenith,
cross_axis_slope=0):
r"""
Shade fraction (FS) for trackers with a common angle on an east-west slope.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Shade fraction (FS) for trackers with a common angle on an east-west slope.
Shade fraction for trackers with a common angle on an east-west slope.

The acronym is never used anywhere

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this function do the same as this existing function: pvlib.bifacial.infinite_sheds._shaded_fraction()

They differ in that the new function allows the array to be on a cross axis slope. If we adapt the infinite sheds model to allow arbitrary orientation, then we could reuse this function, but that work was delayed due to some questions about where the horizon should be and what the sky and ground view factors would include. Until those issues are resolve and that enhancement is implemented, this new shaded fraction function is more generalized.

Copy link
Member Author

@mikofski mikofski May 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The acronym is never used anywhere

It was the acronym that @williamhobbs used in #1689 and it's used on L269 in the source and L301 in the docstring example. Anyway, I'm not attached to it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used "FS" for shaded fraction because Lorenzo 2011 used it, but I think it is confusing - should it be Fs, it's easily confused with "First Solar" in this context, etc.

@kandersolar
Copy link
Member

@mikofski can you comment on the relationship between this shaded fraction calculation and the one in section 6 of Slope-Aware Backtracking? They seem quite similar in spirit, to me at least.

One thing I notice is that the cross-axis slope currently seems to be a left-handed rotation (assuming it is defined on the same axis as the tracker and sun angles), see here:

In [9]: tracker_shaded_fraction(tracker_theta=80, gcr=0.5, projected_solar_zenith=80, cross_axis_slope=0)
Out[9]: array(0.65270364)

In [10]: tracker_shaded_fraction(tracker_theta=80, gcr=0.5, projected_solar_zenith=80, cross_axis_slope=10)
Out[10]: array(1.)

In [11]: tracker_shaded_fraction(tracker_theta=80, gcr=0.5, projected_solar_zenith=80, cross_axis_slope=-10)
Out[11]: array(0.30540729)

@williamhobbs
Copy link
Contributor

@AdamRJensen Did you tell me this week that if this used surface_tilt instead of tracker_theta, that it would also work for fixed tilt systems? That would be nice, but maybe I misunderstood.

Semi-related, do we need an array azimuth input, or is this only suitable for trackers with 180 deg azimuth? My implementation only worked for that case, but it maybe isn't ideal. We do have some true-tracking projects with not-180 azimuths (e.g., 168 deg). This might be scope-creep...

@kandersolar kandersolar modified the milestones: 0.9.6, 0.10.0 May 16, 2023
@kandersolar kandersolar modified the milestones: 0.10.0, v0.10.2 Jul 6, 2023
@echedey-ls
Copy link
Contributor

What is pending to do in this PR? It has become of interest to me because I'd like to contribute a losses model that benefits from this calculation. (Conversation at G Groups, from end of September & start of October)

@mikofski
Copy link
Member Author

mikofski commented Nov 3, 2023

What is pending to do in this PR? It has become of interest to me because I'd like to contribute a losses model that benefits from this calculation. (Conversation at G Groups, from end of September & start of October)

We got stuck considering consolidation & reuse of some private or intermediate calculations elsewhere (tracking & infinite sheds) that would either require extra work or would generalize this function to more relaxed conditions. Currently this is only good for N-S tracker (or possibly E-W fixed tilt) systems with perpendicular cross axis slopes.

Another sticking point was whether user should have to calculate PSZ (projected solar zenith) or not. I opened a separate issue for that.

So I’m not sure where we go from here. I think @williamhobbs submitted some PR’s recently that may have helped move this one forward as well?

@williamhobbs
Copy link
Contributor

williamhobbs commented Nov 3, 2023

I think @williamhobbs submitted some PR’s recently that may have helped move this one forward as well?

@echedey-ls, @mikofski is correct, this PR https://github.com.mcas.ms/pvlib/pvlib-python/pull/1871 will let users get shaded fraction from infinite_sheds.get_irradiance and .get_irradiance_poa. It can be used for bifacial and monofacial systems with any azimuth, but not on sloped terrain.

@mikofski
Copy link
Member Author

mikofski commented Nov 4, 2023

@echedey-ls if you’re interested in helping resolve the blockers and pushing this across the finish line that would be great. This PR is still important to me specifically because it provides a r2r shading solution for sloping terrain.

@echedey-ls
Copy link
Contributor

@mikofski I'm interested in it too for the linked conversation model, but I've got to have a deeper look at the discussion and the code.

echedey-ls added a commit to echedey-ls/pvlib-python that referenced this pull request Nov 9, 2023
Reported at: pvlib#1725 (comment)

Confirmed via "Slope-Aware Backtracking for Single-Axis Trackers", paragraph after Eq. 1

Co-Authored-By: Mark Mikofski <[email protected]>
@cwhanse cwhanse mentioned this pull request Dec 8, 2023
15 tasks
@kandersolar kandersolar modified the milestones: v0.10.3, v0.10.4 Dec 20, 2023
@echedey-ls
Copy link
Contributor

@mikofski I'd like to start working on this PR based on the work of #1904 if you don't mind. I'd open a new PR based on this branch, although I also want to keep the conversations. IDK if I can be given write permission just for a branch, I don't think so...

@mikofski
Copy link
Member Author

mikofski commented Feb 3, 2024

Thanks! It’s okay to branch my branch, looking forward to seeing this closed finally!

echedey-ls added a commit to echedey-ls/pvlib-python that referenced this pull request Feb 15, 2024
Reported at: pvlib#1725 (comment)

Confirmed via "Slope-Aware Backtracking for Single-Axis Trackers", paragraph after Eq. 1

Co-Authored-By: Mark Mikofski <[email protected]>
kandersolar added a commit that referenced this pull request Mar 8, 2024
* Function prototype

* Update shading.rst

* Update shading.py

* Minimal test

* Implementation

From NREL paper

* Fix, fix, fix, fix & format

* Format issues

* Extend tests (compare with singleaxis) & format with ruff

* Format fixes

* Upgrade tests

* Array -> Axis

* type

* Whatsnew

* xd

* bruh

* Minor Python optimization a la tracking.singleaxis

* Comment and minor optimizations

* Typo found by Mikofski

Reported at: #1725 (comment)

Confirmed via "Slope-Aware Backtracking for Single-Axis Trackers", paragraph after Eq. 1

Co-Authored-By: Mark Mikofski <[email protected]>

* Surface -> Axis

Co-Authored-By: Kevin Anderson <[email protected]>

* Elevation -> Zenith

Co-Authored-By: Kevin Anderson <[email protected]>

* Elev -> Zenith

Co-Authored-By: Kevin Anderson <[email protected]>

* Update shading.py

* Update docstring

Co-Authored-By: Anton Driesse <[email protected]>

* Add comments from `tracking.singleaxis`

Co-Authored-By: Will Holmgren <[email protected]>
Co-Authored-By: Mark Mikofski <[email protected]>

* Singleaxis implementation port & test addition, based on old pvlib.tracking.singleaxis

* Update v0.10.4.rst

* Linter

* Code review

Co-Authored-By: Cliff Hansen <[email protected]>

* Add Fig 5 [1] (still gotta check the built output)

* Add caption, change size and describe in alternate text

* rST fixes ?

* Figures have captions, images do not

https://pandemic-overview.readthedocs.io/en/latest/myGuides/reStructuredText-Images-and-Figures-Examples.html#id18

* Flip arguments order

* I forgot 💀

* Linter are you happy now?

* Remove port test and add edge cases test

Co-Authored-By: Kevin Anderson <[email protected]>

* Update test_shading.py

Co-Authored-By: Kevin Anderson <[email protected]>

* Indentation xd

* Update test_shading.py

* I forgot how to code

* Align data

* Docstring suggestion from Kevin

Co-Authored-By: Kevin Anderson <[email protected]>

* Update link to example?

* Link, please work

* Update shading.py

* Update shading.py

* Update shading.py

* Update shading.py

* Update shading.py

* Update shading.py

* Update shading.py

* Update shading.py

* Lintaaaaaaarrrgh

Fixed the link finally

* Update pvlib/shading.py

Co-authored-by: Kevin Anderson <[email protected]>

---------

Co-authored-by: Mark Mikofski <[email protected]>
Co-authored-by: Kevin Anderson <[email protected]>
Co-authored-by: Anton Driesse <[email protected]>
Co-authored-by: Will Holmgren <[email protected]>
Co-authored-by: Cliff Hansen <[email protected]>
Co-authored-by: Kevin Anderson <[email protected]>
@kandersolar kandersolar modified the milestones: v0.10.4, v0.10.5 Mar 18, 2024
@kandersolar kandersolar modified the milestones: v0.10.5, 0.11.0 May 3, 2024
@kandersolar kandersolar modified the milestones: 0.11.0, v0.11.1 Jun 21, 2024
@kandersolar kandersolar removed this from the v0.11.1 milestone Sep 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants