Skip to content

Add bifacial scaling to Townsend snow loss model#2756

Open
shethkajal7 wants to merge 2 commits into
pvlib:mainfrom
shethkajal7:add-bifacial-townsend-snow
Open

Add bifacial scaling to Townsend snow loss model#2756
shethkajal7 wants to merge 2 commits into
pvlib:mainfrom
shethkajal7:add-bifacial-townsend-snow

Conversation

@shethkajal7
Copy link
Copy Markdown

@shethkajal7 shethkajal7 commented May 17, 2026

Add optional front_side_fraction argument to loss_townsend for bifacial snow loss adjustment. Includes test coverage for the scaling behavior.

Description

This PR adds an optional front_side_fraction argument to pvlib.snow.loss_townsend.

The new argument allows users to scale the calculated Townsend snow loss by the front-side energy fraction for bifacial systems. This follows the bifacial guidance in Townsend and Previtali (2023), where bifacial snow modeling uses total front + rear POA in the Townsend calculation and then scales the resulting loss by the front-side energy contribution.

The default value is None, so existing behavior is unchanged.

Changes

  • Add optional front_side_fraction keyword argument to loss_townsend
  • Document bifacial usage in the function docstring
  • Add test coverage confirming that front_side_fraction scales the existing Townsend result correctly

Backward compatibility

This change is backward compatible. When front_side_fraction=None, the function follows the existing behavior.

Tests

Ran locally:

python -m pytest tests/test_snow.py -k townsend
python -m ruff check pvlib/snow.py tests/test_snow.py

Both passed.

Checklist

  • Closes Enhancement to Townsend monthly snow loss model for engineering workflows #2755
  • 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:`shethkajal7`).
  • 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.

Add optional front_side_fraction argument to loss_townsend for bifacial snow loss adjustment. Includes test coverage for the scaling behavior.
Comment thread pvlib/snow.py
Comment on lines +322 to +323
rear-side insolation in ``poa_global``. The resulting loss may then be
scaled by the front-side energy fraction using ``front_side_fraction``.
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.

Suggested change
rear-side insolation in ``poa_global``. The resulting loss may then be
scaled by the front-side energy fraction using ``front_side_fraction``.
rear-side insolation in ``poa_global``. The resulting loss is
scaled by the front-side energy fraction ``front_side_fraction``.

Comment thread pvlib/snow.py
Comment on lines +297 to +302
front_side_fraction : numeric or array-like, default None
Optional multiplier applied to the calculated loss fraction. For
bifacial systems, this can be used to scale the snow loss by the
front-side energy fraction from a no-soiling simulation. For example,
use 0.9 when 90% of monthly energy is from the front side and 10% is
from the rear side. If None, no bifacial adjustment is applied. [-]
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.

Suggested change
front_side_fraction : numeric or array-like, default None
Optional multiplier applied to the calculated loss fraction. For
bifacial systems, this can be used to scale the snow loss by the
front-side energy fraction from a no-soiling simulation. For example,
use 0.9 when 90% of monthly energy is from the front side and 10% is
from the rear side. If None, no bifacial adjustment is applied. [-]
front_side_fraction : numeric or array-like, default 1.0
Fraction of monthly energy from front-side insolation (unitless).
Multiplies the calculated loss fraction. For example,
use 0.9 when 90% of monthly energy is from the front side
of a bifacial system and 10% is from the rear side.

Here I think 1.0 is a suitable default.

Comment thread pvlib/snow.py
Comment on lines +399 to +400
if front_side_fraction is not None:
front_side_fraction = np.asarray(front_side_fraction)
Copy link
Copy Markdown
Member

@cwhanse cwhanse May 17, 2026

Choose a reason for hiding this comment

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

I think this if and np.asarray are unnecessary if the default is set to 1.0

@RDaxini RDaxini added this to the v0.15.2 milestone May 18, 2026
Copy link
Copy Markdown
Member

@RDaxini RDaxini left a comment

Choose a reason for hiding this comment

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

Thanks for submitting this PR @shethkajal7.
I have added a few suggestions: use np.full to avoid repetition in the array creation, and a few minor flake8 fixes.
Don't forget to add an entry to the docs/sphinx/source/whatsnew file and list yourself there as a contributor for the next release.

Comment thread tests/test_snow.py
Comment on lines +250 to +251


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.

Deleting this blank space will resolve the flake8 error

Suggested change

Comment thread pvlib/snow.py
front-side energy fraction from a no-soiling simulation. For example,
use 0.9 when 90% of monthly energy is from the front side and 10% is
from the rear side. If None, no bifacial adjustment is applied. [-]

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.

Deleting this blank space will resolve the flake8 error (same below)

Suggested change

Comment thread tests/test_snow.py Outdated
Comment thread tests/test_snow.py
poa_global, slant_height, lower_edge_height,
front_side_fraction=front_side_fraction)

np.testing.assert_allclose(adjusted, unadjusted * front_side_fraction) No newline at end of file
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.

Adding a new line at the end of the file will resolve this flake8 error

Suggested change
np.testing.assert_allclose(adjusted, unadjusted * front_side_fraction)
np.testing.assert_allclose(adjusted, unadjusted * front_side_fraction)

rewrite the test function to avoid repetition in numpy array.

Co-authored-by: Rajiv Daxini <143435106+RDaxini@users.noreply.github.com>
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.

Enhancement to Townsend monthly snow loss model for engineering workflows

3 participants