Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
0922056
initial re-structure attempt
martin-springer Nov 21, 2025
508fbd3
update notebook workflow
martin-springer Nov 21, 2025
8c96e3a
update flake8 workflo
martin-springer Nov 21, 2025
b15571b
exclude standoff from workflow
martin-springer Nov 21, 2025
6fb3464
update readme
martin-springer Nov 21, 2025
b5e7a33
re-run notebook
martin-springer Nov 21, 2025
88d9085
exclude tools scripts from flake8
martin-springer Nov 21, 2025
e2a1015
conditionally deploy jb books
martin-springer Nov 21, 2025
85324f4
update notebook
martin-springer Nov 21, 2025
cbce416
remove tool notebooks from notebook checks
martin-springer Nov 21, 2025
08e7dfd
fix in actual notebook
martin-springer Nov 21, 2025
77d8269
exclude scripts from jb workflow
martin-springer Nov 21, 2025
0ddb746
restrict to jupyter book < 2
martin-springer Nov 21, 2025
614ade1
fix logo path and references
martin-springer Nov 21, 2025
501da1f
jupyter book v2 initial implementation
martin-springer Nov 21, 2025
f0f874c
Merge branch 'development' into restructure_notebooks
RDaxini Nov 26, 2025
0eb13cf
Merge branch 'development' into jupyter_book_v2
RDaxini Nov 26, 2025
88992f4
update 03 pysam api nb and py
RDaxini Nov 26, 2025
8fca368
remove pysam single loc nb from nbval workflow
RDaxini Nov 26, 2025
df2e43a
update 03 pysam api nb and py
RDaxini Nov 26, 2025
5095a43
remove pysam single loc nb from nbval workflow
RDaxini Nov 26, 2025
085a3d3
pysamv1 --> pvsamv1
martin-springer Dec 1, 2025
a5a0c43
pysamv1->pvsamv1
RDaxini Dec 1, 2025
8b63eed
updates to readme's
martin-springer Dec 2, 2025
410cbad
deploy books to gh-pages-dev
martin-springer Dec 2, 2025
0921a69
use html instead of site
martin-springer Dec 2, 2025
3206cf5
deploy on PR's to development
martin-springer Dec 2, 2025
4ab1b2b
pages subdirectory approach for preview
martin-springer Dec 2, 2025
cd9694b
remove year from copyright
martin-springer Dec 2, 2025
8285080
another try to get development pages to show up
martin-springer Dec 2, 2025
a1f454c
update main readme's
martin-springer Dec 2, 2025
f58064b
include tools notebooks
martin-springer Dec 2, 2025
957404c
toc levels
martin-springer Dec 2, 2025
0887a0a
Merge branch 'restructure_notebooks' into jupyter_book_v2
martin-springer Dec 2, 2025
dfa3e2b
max toc depth
martin-springer Dec 2, 2025
09c3f49
update workflow for v2
martin-springer Dec 2, 2025
8710c42
error check to make workflow fail if books fail
martin-springer Dec 2, 2025
d969526
update myst config
martin-springer Dec 2, 2025
2621071
update workflow site flag
martin-springer Dec 2, 2025
88e53b2
titles only
martin-springer Dec 2, 2025
7c02b9a
attempt to fix notebook header levels
martin-springer Dec 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ exclude =
.venv
build
tutorials_and_tools/tutorials_and_tools/*.py
tutorials/**/scripts/*.py
tools/**/scripts/*.py
28 changes: 16 additions & 12 deletions .github/workflows/deploy-books.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ on:
push:
branches:
- main
- development
pull_request:
branches:
- development
- main
# If your git repository has the Jupyter Book within some-subfolder next to
# unrelated files, you can make this run only if a file within that specific
# folder has been modified.
Expand All @@ -16,9 +21,8 @@ on:
jobs:
deploy-book:
runs-on: ubuntu-latest
environment:
name: github-pages
permissions:
contents: write
pages: write
id-token: write
steps:
Expand Down Expand Up @@ -47,15 +51,15 @@ jobs:
# Build the book
- name: Build the book
run: |
jupyter-book build tutorials_and_tools
cd tutorials
jupyter-book build --site .

# Upload the book's HTML as an artifact
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: "tutorials_and_tools/_build/html"

# Deploy the book's HTML to GitHub Pages
# Deploy to gh-pages using peaceiris action for all branches
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: tutorials/_build/html
publish_branch: gh-pages
destination_dir: ${{ github.ref == 'refs/heads/main' && '.' || 'dev-preview' }}
keep_files: ${{ github.ref != 'refs/heads/main' }}
2 changes: 1 addition & 1 deletion .github/workflows/flake8.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ jobs:
run: echo '::add-matcher::.github/workflows/flake8-linter-matcher.json'
- name: Run flake8 on changed files only
run: |
git diff origin/$GITHUB_BASE_REF HEAD -- "*.py" | flake8 --config=.flake8 --diff
git diff origin/$GITHUB_BASE_REF HEAD --name-only -- "*.py" | grep -v -E "(tutorials/.*/scripts/|tools/.*/scripts/)" | xargs -r git diff origin/$GITHUB_BASE_REF HEAD -- | flake8 --config=.flake8 --diff
37 changes: 18 additions & 19 deletions .github/workflows/nbval.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,21 @@ jobs:
env:
# Notebooks with estimated runtime in seconds (format: "notebook:runtime")
ALL_NOTEBOOKS: |
"1 - Basics, Humidity, Design.ipynb:10"
"2 - Degradation.ipynb:5"
"3 - Spectral Degradation.ipynb:5"
"4 - Weather Database Access.ipynb:15"
"ASTM Live Demo.ipynb:10"
"B-O LID - Accelerated Test.ipynb:10"
"Custom-Functions-Nopython.ipynb:30"
"LETID - Accelerated Test.ipynb:120"
"LETID - Outdoor LETID.ipynb:30"
"LETID - Outdoor Scenario Based on Accelerated Test Result.ipynb:45"
"LETID - Passivated Wafer.ipynb:80"
"Monte Carlo - Arrhenius.ipynb:180"
"Monte Carlo - Standoff.ipynb:30"
"Tools - Edge Seal Oxygen Ingress.ipynb:15"
"Van't Hoff Degradation Model.ipynb:5"
"Geospatial - Local Scenario.ipynb:1"
"01_basics/01_basics_humidity_design.ipynb:10"
"01_basics/02_degradation.ipynb:5"
"01_basics/03_spectral_degradation.ipynb:5"
"01_basics/04_weather_database_access.ipynb:15"
"02_degradation/01_bo_lid_accelerated_test.ipynb:10"
"02_degradation/02_letid_accelerated_test.ipynb:120"
"02_degradation/03_letid_outdoor.ipynb:30"
"02_degradation/04_letid_outdoor_scenario.ipynb:45"
"02_degradation/05_letid_passivated_wafer.ipynb:80"
"02_degradation/06_vant_hoff_degradation_model.ipynb:5"
"03_monte_carlo/01_arrhenius.ipynb:180"
"03_monte_carlo/02_standoff.ipynb:30"
"04_geospatial/01_local_scenario.ipynb:1"
"05_advanced/01_custom_functions_nopython.ipynb:30"
"07_workshop_demos/01_astm_live_demo.ipynb:10"
steps:
- name: Calculate batch matrix
id: set-matrix
Expand Down Expand Up @@ -150,7 +149,7 @@ jobs:
fail-fast: false
matrix: ${{ fromJson(needs.calculate-batches.outputs.matrix) }}
env:
NOTEBOOK_DIR: "tutorials_and_tools/tutorials_and_tools"
NOTEBOOK_DIR: "tutorials"
SANITIZE_CFG: "nbval_sanitization_rules.cfg"
ALL_NOTEBOOKS: ${{ needs.calculate-batches.outputs.notebooks }}
BATCH_ASSIGNMENTS: ${{ needs.calculate-batches.outputs.batch_assignments }}
Expand All @@ -167,14 +166,14 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('tutorials_and_tools/requirements.txt', 'pyproject.toml') }}
key: ${{ runner.os }}-pip-${{ hashFiles('tutorials/requirements.txt', 'pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-

- name: Install notebook environment
run: |
python -m pip install --upgrade pip wheel
pip install --timeout=300 -r tutorials_and_tools/requirements.txt
pip install --timeout=300 -r tutorials/requirements.txt
pip install --timeout=300 -e .[test]
pip install nbval global_land_mask dotenv imageio nrel-pysam
pip install nbconvert[webpdf]
Expand Down
21 changes: 10 additions & 11 deletions .github/workflows/testbook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@ jobs:
notebook-testbook-check:
runs-on: ubuntu-latest
env:
NOTEBOOK_DIR: "tutorials_and_tools/tutorials_and_tools"
NOTEBOOK_DIR: "tutorials"
TESTBOOK_NOTEBOOK_LIST: |
"API Call Required - PYSam.ipynb"
"API Call Required - load_nsrdb_distributed.ipynb"
"HPC Connection Required - Scenario - Geographical Features.ipynb"
"HPC Connection Required - Scenario - Geospatial.ipynb"
"HPC Connection Required - Scenario - Non-uniform Mountain Prefferential Downselect.ipynb"
"HPC Connection Required - Scenario - Single Location.ipynb"
"HPC Connection Required - Scenario - Temperature.ipynb"
"HPC Connection Required - Tools - Module Standoff for IEC TS 63126.ipynb"
"HPC Connection Required - Geospatial Templates.ipynb"
"05_advanced/03_pysam_api.ipynb"
"05_advanced/04_nsrdb_distributed_api.ipynb"
"04_geospatial/03_scenario_geographical_features.ipynb"
"04_geospatial/04_scenario_geospatial.ipynb"
"04_geospatial/05_scenario_mountain_downselect.ipynb"
"04_geospatial/06_scenario_single_location.ipynb"
"04_geospatial/07_scenario_temperature.ipynb"
"04_geospatial/02_geospatial_templates.ipynb"

steps:
- uses: actions/checkout@v4
Expand All @@ -27,7 +26,7 @@ jobs:
- name: Install notebook environment
run: |
python -m pip install --upgrade pip wheel
pip install --timeout=300 -r tutorials_and_tools/requirements.txt
pip install --timeout=300 -r tutorials/requirements.txt
pip install --timeout=300 -e .[test]
pip install testbook
pip install global_land_mask dotenv imageio nrel-pysam
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ instance/
docs/sphinx/_build/

# tutorial jupyter-book
_build/
pvdeg_tutorials/_build/
tutorials/_build/
tutorials_and_tools/_build/

# PyBuilder
target/
Expand Down
14 changes: 11 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
exclude: '^(docs/source/|tutorials_and_tools/_build/)'
exclude: '^(docs/source/|tutorials/_build/)'
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
Expand All @@ -14,9 +14,17 @@ repos:
rev: 25.9.0
hooks:
- id: black
exclude: '^tutorials_and_tools/'
exclude: '^(tutorials/|tools/)'
- repo: https://github.com/PyCQA/flake8
rev: 7.3.0 # Use the desired flake8 version
hooks:
- id: flake8
exclude: '^tutorials_and_tools/'
exclude: '^(tutorials/|tools/)'
- repo: https://github.com/mwouts/jupytext
rev: v1.18.1
hooks:
- id: jupytext
args: [--sync, --pipe, black]
files: '^(tutorials/|tools/).*\.ipynb$'
additional_dependencies:
- black==25.9.0
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BSD 3-Clause License

Copyright 2020-2023 Alliance for Sustainable Energy, LLC
Copyright 2020 Alliance for Sustainable Energy, LLC

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Expand Down
95 changes: 74 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<tr>
<td>Publications</td>
<td>
<a href="https://doi.org/10.5281/zenodo.8088578"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.8088578.svg" alt="DOI"></a>
<a href="https://zenodo.org/records/8088578/latest"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.8088578.svg" alt="DOI"></a>
</td>
</tr>
<tr>
Expand All @@ -39,20 +39,40 @@



# PV Degradation Tools (pvdeg)
# PVDeg: Python Package for Modeling Degradation in Photovoltaic Systems

This repository contains functions for calculating degradation of photovoltaic modules. For example, functions to calculate front and rear relative Humidity, as well as Acceleration Factors. A degradation calculation function is also being developed, considering humidity and spectral irradiances models.
PVDeg is an open-source Python package for modeling photovoltaic (PV) degradation, developed at the National Renewable Energy Laboratory (NREL) and supported by the Durable Module Materials (DuraMAT) consortium. It provides modular functions, materials databases, and calculation workflows for simulating degradation mechanisms (e.g., LeTID, hydrolysis, UV exposure) using weather data from the National Solar Radiation Database (NSRDB) and the Photovoltaic Geographical Information System (PVGIS). By integrating Monte Carlo uncertainty propagation and geospatial processing, PVDeg enables field-relevant predictions and uncertainty quantification of module reliability and lifetime.

## Key Features

- **Core Degradation Functions**: Dedicated functions for physical degradation mechanisms including moisture ingress, LeTID, UV exposure, and thermal stress
- **Scenario Class**: Simplified workflow interface for complex multi-parameter degradation studies
- **Geospatial Analysis**: Large-scale spatial analyses with parallel processing across geographic regions
- **Monte Carlo Framework**: Uncertainty quantification through parameter distribution sampling
- **Material Databases**: Curated degradation parameters, kinetic coefficients, and material properties
- **Weather Data Integration**: Seamless access to NSRDB and PVGIS meteorological data
- **Standards Support**: Contributions to IEC TS 63126 and other standardization efforts
## Example Applications

PVDeg has been adopted in multiple studies across the PV reliability community:

- **Thermal Stability and IEC TS 63126 Compliance**: Calculate effective standoff distances and generate public maps supporting the IEC TS 63126 standard
- **Light and Elevated Temperature Induced Degradation (LeTID)**: Integrated into international interlaboratory comparison studies and field-aged array analyses
- **Geospatial Performance Modeling**: Coupled with GeoGridFusion to streamline weather-data storage and spatial queries for large-scale degradation simulations
- **Agrivoltaics and System-Level Modeling**: Combined with PySAM to assess degradation-driven yield losses in dual-use agrivoltaic systems
- **Material-Property Parameterization**: Studies of UV-induced polymer degradation and moisture-related failures in encapsulants and backsheets

Tutorials
=========

### Jupyter Book

For in depth Tutorials you can run online, see our [jupyter-book](https://nrel.github.io/PVDegradationTools/intro.html) [![Jupyter Book Badge](https://jupyterbook.org/badge.svg)](https://nrel.github.io/PVDegradationTools/intro.html)
For in depth tutorials you can run online, see our [Jupyter Book](https://nrel.github.io/PVDegradationTools/intro.html)

Clicking on the rocket-icon on the top allows you to launch the journals on [Google Colaboratory](https://colab.research.google.com/) for interactive mode.
Just uncomment the first line `pip install ...` to install the environment on each journal if you follow this mode.
**Development Preview:** Preview the latest development changes at [dev-preview](https://nrel.github.io/PVDegradationTools/dev-preview/intro.html)

Clicking on the rocket-icon on the top allows you to launch the notebooks on [Google Colaboratory](https://colab.research.google.com/) for interactive mode.
Just uncomment the first line `pip install ...` to install the environment on each notebook if you follow this mode.

### Binder

Expand Down Expand Up @@ -88,24 +108,45 @@ You can also run the tutorial locally in a virtual environment, i.e., `venv` or
```

1. Use the file explorer in Jupyter lab to browse to `tutorials`
and start the first Tutorial.
and start the first Tutorial. Tutorials are organized into the following categories:
- `01_basics/` - Introduction to PVDeg fundamentals
- `02_degradation/` - Degradation mechanism modeling (LID, LeTID, Van't Hoff)
- `03_monte_carlo/` - Monte Carlo uncertainty analysis
- `04_geospatial/` - Geospatial and HPC scenarios
- `05_advanced/` - Advanced topics and API access
- `06_nrel_hpc/` - NREL HPC-specific workflows (requires HPC access)
- `07_workshop_demos/` - Workshop and demonstration notebooks

For analysis tools, see the separate Tools section.


Documentation
=============

Documentation is available in [ReadTheDocs](https://PVDegradationTools.readthedocs.io) where you can find more details on the API functions.
Full API documentation is available at [ReadTheDocs](https://PVDegradationTools.readthedocs.io) where you can find detailed information on all functions, classes, and modules.


Installation
============

Relative Humidity and Acceleration Factors for Solar Modules releases may be installed using the ``pip`` and ``conda`` tools. Compatible with Python 3.5 and above.
PVDeg releases may be installed using the `pip` and `conda` tools. Compatible with Python 3.10 and above.

Install with:

pip install pvdeg

### Optional Dependencies

PVDeg offers optional dependency groups for specific use cases:

pip install pvdeg[sam] # Install with PySAM support
pip install pvdeg[docs] # Install documentation tools
pip install pvdeg[test] # Install testing tools
pip install pvdeg[books] # Install Jupyter Book tools
pip install pvdeg[all] # Install all optional dependencies

### Developer Installation

For developer installation, clone the repository, navigate to the folder location and install as:

pip install -e .[all]
Expand All @@ -116,13 +157,11 @@ Running jupyter notebooks using anaconda prompt
Note that in order to run notebooks cleanly and validate outputs, use the following
commands to run either one notebook:

jupyter nbconvert --to notebook --execute --inplace "tutorials_and_tools/
tutorials_and_tools/Monte Carlo - Arrhenius.ipynb"
jupyter nbconvert --to notebook --execute --inplace "tutorials/01_basics/01_basics_humidity_design.ipynb"

or all notebooks inside the tutorials and tools folder:
or all notebooks inside a specific tutorial category:

jupyter nbconvert --to notebook --execute --inplace "tutorials_and_tools/
tutorials_and_tools/*.ipynb"
jupyter nbconvert --to notebook --execute --inplace "tutorials/01_basics/*.ipynb"

This avoids formatting issues that may arise depending on your own local environment
or IDE.
Expand All @@ -135,26 +174,40 @@ License


Contributing
=======
============

We welcome contributions to this software. Please read the copyright license agreement (cla-1.0.md), with instructions on signing it in sign-CLA.md.

We welcome contributiosn to this software, but please read the copyright license agreement (cla-1.0.md), with instructions on signing it in sign-CLA.md. For questions, email us.
All code, documentation, and discussion contributors are acknowledged for their contributions to the PVDeg project.


Getting support
===============

If you suspect that you may have discovered a bug or if you'd like to
change something about pvdeg, then please make an issue on our
[GitHub issues page](hhttps://github.com/NREL/PVDegradationTools/issues).
change something about PVDeg, then please make an issue on our
[GitHub issues page](https://github.com/NREL/PVDegradationTools/issues).


Citing
======

If you use this functions in a published work, please cite:
If you use PVDeg in a published work, please cite:

**JOSS Paper (In Review):**

Daxini, R., Ovaitt, S., Springer, M., Ford, T., & Kempe, M. (2025). PVDeg: a python package for modeling degradation on solar photovoltaic systems. Journal of Open Source Software (In Review).

**Latest Release:**

[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.8088578.svg)](https://zenodo.org/records/8088578/latest)

**Software Record:**

Holsapple, Derek, Ayala Pelaez, Silvana, Kempe, Michael. "PV Degradation Tools", NREL Github 2020, Software Record SWR-20-71.

And/or the specific release from Zenodo:

Martin Springer, Tobin Ford, Rajiv Daxini, Matthew Brown, Silvana Ovaitt, Joseph Karas, Mark Campanelli, Derek M Holsapple, Kevin Anderson, Michael Kempe. (2025). NREL/PVDegradationTools: 0.6.1 (0.6.1). Zenodo. https://doi.org/10.5281/zenodo.17265988
Acknowledgements
================

This work was authored by the National Renewable Energy Laboratory, operated by Alliance for Sustainable Energy, LLC, for the U.S. Department of Energy (DOE) under Contract No. DE-AC36-08GO28308. Funding provided as part of the Durable Modules Materials Consortium (DuraMAT), an Energy Materials Network Consortium funded by the U.S. Department of Energy, Office of Energy Efficiency and Renewable Energy, Solar Energy Technologies Office Agreement Number 32509. The research was performed using computational resources sponsored by the Department of Energy's Office of Energy Efficiency and Renewable Energy and located at the National Renewable Energy Laboratory. The views expressed in the article do not necessarily represent the views of the DOE or the U.S. Government. The U.S. Government retains and the publisher, by accepting the article for publication, acknowledges that the U.S. Government retains a nonexclusive, paid-up, irrevocable, worldwide license to publish or reproduce the published form of this work, or allow others to do so, for U.S. Government purposes.
9 changes: 9 additions & 0 deletions jupytext.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Jupytext configuration
# Sync notebooks to scripts/ subdirectories as Python files with percent format

# Default formats for notebooks
formats = "ipynb,scripts//py:percent"

# Notebook metadata filter (reduce diff noise)
notebook_metadata_filter = "-all"
cell_metadata_filter = "-all"
4 changes: 2 additions & 2 deletions pvdeg/pysam.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ def pysam(
pv_model: str
choose pySam photovoltaic system model.
Some models are less thorough and run faster.
pvwatts8 is ~50x faster than pysamv1 but only calculates 46 parameters while
pysamv1 calculates 195.
pvwatts8 is ~50x faster than pvsamv1 but only calculates 46 parameters while
pvsamv1 calculates 195.

options: ``pvwatts8``, ``pvsamv1``

Expand Down
Loading