Skip to content

Implement ANTS-2D bifacial irradiance model - #2740

Open
kandersolar wants to merge 78 commits into
pvlib:mainfrom
kandersolar:ants2d
Open

Implement ANTS-2D bifacial irradiance model#2740
kandersolar wants to merge 78 commits into
pvlib:mainfrom
kandersolar:ants2d

Conversation

@kandersolar

@kandersolar kandersolar commented Apr 21, 2026

Copy link
Copy Markdown
Member
  • [ ] Closes #xxxx
  • I am familiar with the contributing guidelines
  • I attest that all AI-generated material has been vetted for accuracy and is in compliance with the pvlib license
  • Tests added
  • Updates entries in docs/sphinx/source/reference for API changes.
  • Adds description and name entries in the appropriate "what's new" file in docs/sphinx/source/whatsnew for all changes. Includes link to the GitHub Issue with :issue:`num` or this Pull Request with :pull:`num`. Includes contributor name and/or GitHub username (link with :ghuser:`user`).
  • New code is fully documented. Includes numpydoc compliant docstrings, examples, and comments where necessary.
  • Pull request is nearly complete and ready for detailed review.
  • Maintainer: Appropriate GitHub Labels (including remote-data) and Milestone are assigned to the Pull Request and linked Issue.

@AdamRJensen, @cwhanse, and I have a paper describing a new bifacial irradiance model called ANTS-2D. It is similar to pvlib's infinite_sheds model, but extended to allow:

  • a discretized module surface (for, e.g., cell-level irradiance values)
  • a discretized ground surface, with variable albedo
  • sloped terrain, in the fashion of pvlib's existing functionality in that area
  • the Perez transposition model, in addition to Hay-Davies and isotropic
  • computation of ground-level irradiance (for agriPV)
  • fast computation by using analytical integrated view factors instead of burdensome numerical integrals

Details available open-access here: https://doi.org/10.1109/JPHOTOV.2026.3677506

This PR is rather large. To summarize:

  • Add g0 and g1 parameters to the view factor functions in pvlib.bifacial.utils. These are analogous to x0 and x1 in vf_row_sky_2d_integ and extend the functions to subset the ground surface.
  • Change vf_ground_sky_2d_integ to use Hottel's crossed-string rule instead of burdensome numerical integration. This makes the npoints and vectorize parameters unnecessary.
  • Change some signatures in pvlib.bifacial.utils to be cleaner with the new calculations.
  • Minor edits in pvlib.bifacial.infinite_sheds to accommodate the utils changes
  • Create pvlib.bifacial.ant2d, which houses the model itself and uses the new utils functionality.

Let me know if it would help reviewers to split it up and review separate PRs, starting with utils.

Comment thread pvlib/bifacial/utils.py
Comment thread pvlib/bifacial/utils.py Outdated
Comment thread pvlib/bifacial/utils.py
Comment thread pvlib/bifacial/utils.py Outdated
Comment thread pvlib/bifacial/utils.py Outdated
kandersolar and others added 4 commits June 17, 2026 13:40

@cwhanse cwhanse left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thorough tests!

Comment thread tests/bifacial/test_ants2d.py Outdated
@williamhobbs

Copy link
Copy Markdown
Contributor

I think the documentation for ants2d.get_irradiance needs clarification on how to model fixed-tilt systems. I.e., how to convert tilt angle and azimuth into tracker_rotation and axis_azimuth (and similar for axis_tilt and cross_axis_slope).

@williamhobbs

Copy link
Copy Markdown
Contributor

In pvlib.irradiance.get_total_irradiance, the input for model for Perez-Driesse is perez-driesse, but here it is perez_driesse. I suggest changing it to perez-driesse for consistency, unless there is a reason to do it differently here.

Comment thread pvlib/bifacial/ants2d.py Outdated
Comment thread pvlib/bifacial/ants2d.py Outdated
Comment thread pvlib/bifacial/ants2d.py Outdated
Comment thread pvlib/bifacial/ants2d.py Outdated
Comment thread pvlib/bifacial/ants2d.py Outdated
Comment thread pvlib/bifacial/ants2d.py Outdated
Comment thread pvlib/bifacial/ants2d.py Outdated
Comment thread pvlib/bifacial/ants2d.py Outdated
@williamhobbs

Copy link
Copy Markdown
Contributor

Could it be worthwhile to return unshaded irradiance, e.g., poa_front_direct_unshaded? It would help with some types of shade loss models [1, 2] and with general loss accounting (e.g., if someone wanted to make waterfall/Sankey charts).

I haven't fully thought through trade-offs and alternatives yet, but I thought it was worth bringing up.

[1] Anderson, Kevin. 2020. Maximizing Yield with Improved Single-Axis Backtracking on Cross-Axis Slopes: Preprint. Golden, CO: National Renewable Energy Laboratory. NREL/CP-5K00-76023. https://www.nlr.gov/docs/fy20osti/76023.pdf

[2] W. Hobbs, K. Anderson, M. Mikofski, and M. Ghiz, “An approach to modeling linear and non-linear self-shading losses with PVlib,” in PV Perform. Model. Collaborative Workshop, Sandia Nat. Lab., May 2024. [Online]. Available: https://www.sandia.gov/app/uploads/sites/243/dlm_uploads/2024/05/2024_PVPMC_hobbs_pvlib_self-shade.pdf

@kandersolar

Copy link
Copy Markdown
Member Author

Could it be worthwhile to return unshaded irradiance, e.g., poa_front_direct_unshaded? [...]

I think this would be easy enough for the direct component, but sky diffuse would need at least a little bit extra to disentangle r2r shading from the reduction due to surface tilt. Currently, it uses a single VF that accounts for both effects.

The alternative would, I think, be to just use get_total_irradiance with the same inputs. Not as convenient for the user, but maybe good enough?

@williamhobbs

Copy link
Copy Markdown
Contributor

Hmm. I think that unshaded direct is all I would need for shade loss modeling. So having that would be convenient.

But I see what you mean about diffuse. And maybe returning unshaded direct but not unshaded diffuse could confuse users?

Anyone else have thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants