Skip to content

Commit 11a3660

Browse files
authored
Merge branch 'main' into userguide-temperature
2 parents 94d2a71 + 03fb340 commit 11a3660

File tree

12 files changed

+185
-36
lines changed

12 files changed

+185
-36
lines changed

.github/workflows/pytest-remote-data.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
strategy:
5757
fail-fast: false # don't cancel other matrix jobs when one fails
5858
matrix:
59-
python-version: ["3.10", "3.11", "3.12", "3.13"]
59+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
6060
suffix: [''] # the alternative to "-min"
6161
include:
6262
- python-version: "3.10"

.github/workflows/pytest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
fail-fast: false # don't cancel other matrix jobs when one fails
1313
matrix:
1414
os: [ubuntu-latest, macos-latest, windows-latest]
15-
python-version: ["3.10", "3.11", "3.12", "3.13"]
15+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
1616
environment-type: [conda, bare]
1717
suffix: [''] # placeholder as an alternative to "-min"
1818
include:

.github/workflows/top-ranked-issues.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ jobs:
3131
3232
- name: Run update_top_ranking_issues.py
3333
run: |
34-
python ./scripts/update_top_ranking_issues.py
34+
python .github/workflows/update_top_ranking_issues.py

ci/requirements-py3.14.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: test_env
2+
channels:
3+
- defaults
4+
- conda-forge
5+
dependencies:
6+
- coveralls
7+
- cython
8+
- ephem
9+
- h5py
10+
# - numba # not available for py 3.14 as of 2025-11-03
11+
- numpy >= 1.21.2
12+
- pandas >= 1.3.3
13+
- pip
14+
- pytest
15+
- pytest-cov
16+
- pytest-mock
17+
- requests-mock
18+
- pytest-timeout
19+
- pytest-rerunfailures
20+
- conda-forge::pytest-remotedata # version in default channel is old
21+
- python=3.14
22+
- pytz
23+
- requests
24+
- scipy >= 1.7.2
25+
- statsmodels
26+
- pip:
27+
# - nrel-pysam>=2.0 # not available for py 3.14 as of 2025-11-03
28+
- solarfactors

docs/sphinx/source/whatsnew/v0.13.2.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,26 @@ Enhancements
3737
:py:func:`~pvlib.singlediode.bishop88_mpp`,
3838
:py:func:`~pvlib.singlediode.bishop88_v_from_i`, and
3939
:py:func:`~pvlib.singlediode.bishop88_i_from_v`. (:issue:`2497`, :pull:`2498`)
40+
* Add Marion 2008 non-linear irradiance adjustment factor to
41+
:py:func:`pvlib.pvsystem.pvwatts_dc`. (:issue:`2566`, :pull:`2569`)
4042
* Accelerate :py:func:`~pvlib.pvsystem.singlediode` when scipy>=1.15 is
4143
installed. (:issue:`2497`, :pull:`2571`)
4244
* Add :py:func:`~pvlib.iotools.get_era5`, a function for accessing
4345
ERA5 reanalysis data. (:pull:`2573`)
4446

45-
4647
Documentation
4748
~~~~~~~~~~~~~
4849
* Provide an overview of single-diode modeling functionality in :ref:`singlediode`. (:pull:`2565`)
4950
* Provide an overview of temperature modeling functionality in :ref:`temperature`. (:pull:`2591`)
51+
* Fix typo in parameter name ``atmos_refract`` in :py:func:`pvlib.solarposition.spa_python`
52+
and :py:func:`pvlib.spa.solar_position`. (:issue:`2532`, :pull:`2592`)
5053

5154

5255
Testing
5356
~~~~~~~
57+
* Add Python 3.14 to test suite. (:pull:`2590`)
58+
* Update pytest configuration in ``pyproject.toml`` to work with pytest 9.0.
59+
(:pull:`2596`)
5460

5561

5662
Benchmarking
@@ -67,4 +73,6 @@ Maintenance
6773

6874
Contributors
6975
~~~~~~~~~~~~
76+
* Will Hobbs (:ghuser:`williamhobbs`)
7077
* Cliff Hansen (:ghuser:`cwhanse`)
78+
* Joseph Radford (:ghuser:`josephradford`)

pvlib/inverter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,8 @@ def pvwatts(pdc, pdc0, eta_inv_nom=0.96, eta_inv_ref=0.9637):
388388
389389
References
390390
----------
391-
.. [1] A. P. Dobos, "PVWatts Version 5 Manual,"
392-
http://pvwatts.nrel.gov/downloads/pvwattsv5.pdf (2014).
391+
.. [1] A. P. Dobos, "PVWatts Version 5 Manual", NREL, Golden, CO, USA,
392+
Technical Report NREL/TP-6A20-62641, 2014, :doi:`10.2172/1158421`.
393393
"""
394394

395395
pac0 = eta_inv_nom * pdc0

pvlib/pvsystem.py

Lines changed: 90 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2886,53 +2886,117 @@ def scale_voltage_current_power(data, voltage=1, current=1):
28862886

28872887
@renamed_kwarg_warning(
28882888
"0.13.0", "g_poa_effective", "effective_irradiance")
2889-
def pvwatts_dc(effective_irradiance, temp_cell, pdc0, gamma_pdc, temp_ref=25.):
2889+
def pvwatts_dc(effective_irradiance, temp_cell, pdc0, gamma_pdc, temp_ref=25.,
2890+
k=None, cap_adjustment=False):
28902891
r"""
2891-
Implements NREL's PVWatts DC power model. The PVWatts DC model [1]_ is:
2892-
2893-
.. math::
2894-
2895-
P_{dc} = \frac{G_{poa eff}}{1000} P_{dc0} ( 1 + \gamma_{pdc} (T_{cell} - T_{ref}))
2896-
2897-
Note that ``pdc0`` is also used as a symbol in
2898-
:py:func:`pvlib.inverter.pvwatts`. ``pdc0`` in this function refers to the DC
2899-
power of the modules at reference conditions. ``pdc0`` in
2900-
:py:func:`pvlib.inverter.pvwatts` refers to the DC power input limit of
2901-
the inverter.
2892+
Implement NREL's PVWatts (Version 5) DC power model.
29022893
29032894
Parameters
29042895
----------
29052896
effective_irradiance: numeric
2906-
Irradiance transmitted to the PV cells. To be
2907-
fully consistent with PVWatts, the user must have already
2908-
applied angle of incidence losses, but not soiling, spectral,
2909-
etc. [W/m^2]
2897+
Irradiance transmitted to the PV cells. To be fully consistent with
2898+
PVWatts, the user must have already applied angle of incidence losses,
2899+
but not soiling, spectral, etc. [Wm⁻²]
29102900
temp_cell: numeric
29112901
Cell temperature [C].
29122902
pdc0: numeric
2913-
Power of the modules at 1000 W/m^2 and cell reference temperature. [W]
2903+
Power of the modules at 1000 Wm⁻² and cell reference temperature. [W]
29142904
gamma_pdc: numeric
2915-
The temperature coefficient of power. Typically -0.002 to
2916-
-0.005 per degree C. [1/C]
2905+
The temperature coefficient of power. Typically -0.002 to -0.005 per
2906+
degree C. [1/°C]
29172907
temp_ref: numeric, default 25.0
2918-
Cell reference temperature. PVWatts defines it to be 25 C and
2919-
is included here for flexibility. [C]
2908+
Cell reference temperature. PVWatts defines it to be 25 °C and is
2909+
included here for flexibility. [°C]
2910+
k: numeric, optional
2911+
Irradiance correction factor, defined in [2]_. Typically positive.
2912+
[unitless]
2913+
cap_adjustment: Boolean, default False
2914+
If True, only apply the optional adjustment at and below 1000 Wm⁻²
29202915
29212916
Returns
29222917
-------
29232918
pdc: numeric
29242919
DC power. [W]
29252920
2921+
Notes
2922+
-----
2923+
The PVWatts Version 5 DC model [1]_ is:
2924+
2925+
.. math::
2926+
2927+
P_{dc} = \frac{G_{poa eff}}{1000} P_{dc0} ( 1 + \gamma_{pdc} (T_{cell} - T_{ref}))
2928+
2929+
This model has also been referred to as the power temperature coefficient
2930+
model.
2931+
2932+
An optional adjustment can be applied to :math:`P_{dc}` as described in
2933+
[2]_. The adjustment accounts for the variation in module efficiency with
2934+
irradiance. The piece-wise adjustment to power is parameterized by `k`,
2935+
where `k` is the reduction in actual power at 200 Wm⁻² relative to power
2936+
calculated at 200 Wm⁻² as 0.2*`pdc0`. For example, a module that is rated
2937+
at 500 W at STC but produces 95 W at 200 Wm⁻² (a 5% relative reduction in
2938+
efficiency) would have a value of `k` = 0.01.
2939+
2940+
.. math::
2941+
2942+
k=\frac{0.2P_{dc0}-P_{200}}{P_{dc0}}
2943+
2944+
For positive `k` values, and `k` is typically positive, this adjustment
2945+
would also increase relative efficiency when irradiance is above 1000 Wm⁻².
2946+
This may not be desired, as modules with nonlinear irradiance response
2947+
often have peak efficiency near 1000 Wm⁻², and it is either flat or
2948+
declining at higher irradiance. An optional parameter, `cap_adjustment`,
2949+
can address this by modifying the adjustment from [2]_ to only apply below
2950+
1000 Wm⁻².
2951+
2952+
Note that ``pdc0`` is also used as a symbol in
2953+
:py:func:`pvlib.inverter.pvwatts`. ``pdc0`` in this function refers to the
2954+
DC power of the modules at reference conditions. ``pdc0`` in
2955+
:py:func:`pvlib.inverter.pvwatts` refers to the DC power input limit of
2956+
the inverter.
2957+
29262958
References
29272959
----------
2928-
.. [1] A. P. Dobos, "PVWatts Version 5 Manual"
2929-
http://pvwatts.nrel.gov/downloads/pvwattsv5.pdf
2930-
(2014).
2960+
.. [1] A. P. Dobos, "PVWatts Version 5 Manual", NREL, Golden, CO, USA,
2961+
Technical Report NREL/TP-6A20-62641, 2014, :doi:`10.2172/1158421`.
2962+
.. [2] B. Marion, "Comparison of Predictive Models for Photovoltaic
2963+
Module Performance," In Proc. 33rd IEEE Photovoltaic Specialists
2964+
Conference (PVSC), San Diego, CA, USA, 2008, pp. 1-6,
2965+
:doi:`10.1109/PVSC.2008.4922586`.
2966+
Pre-print: https://docs.nrel.gov/docs/fy08osti/42511.pdf
29312967
""" # noqa: E501
29322968

29332969
pdc = (effective_irradiance * 0.001 * pdc0 *
29342970
(1 + gamma_pdc * (temp_cell - temp_ref)))
29352971

2972+
# apply Marion's correction if k is provided
2973+
if k is not None:
2974+
2975+
# preserve input types
2976+
index = pdc.index if isinstance(pdc, pd.Series) else None
2977+
is_scalar = np.isscalar(pdc)
2978+
2979+
# calculate error adjustments
2980+
err_1 = k * (1 - (1 - effective_irradiance / 200)**4)
2981+
err_2 = k * (1000 - effective_irradiance) / (1000 - 200)
2982+
err = np.where(effective_irradiance <= 200, err_1, err_2)
2983+
2984+
# cap adjustment, if needed
2985+
if cap_adjustment:
2986+
err = np.where(effective_irradiance >= 1000, 0, err)
2987+
2988+
# make error adjustment
2989+
pdc = pdc - pdc0 * err
2990+
2991+
# set negative power to zero
2992+
pdc = np.where(pdc < 0, 0, pdc)
2993+
2994+
# preserve input types
2995+
if index is not None:
2996+
pdc = pd.Series(pdc, index=index)
2997+
elif is_scalar:
2998+
pdc = float(pdc)
2999+
29363000
return pdc
29373001

29383002

@@ -2971,9 +3035,8 @@ def pvwatts_losses(soiling=2, shading=3, snow=0, mismatch=2, wiring=2,
29713035
29723036
References
29733037
----------
2974-
.. [1] A. P. Dobos, "PVWatts Version 5 Manual"
2975-
http://pvwatts.nrel.gov/downloads/pvwattsv5.pdf
2976-
(2014).
3038+
.. [1] A. P. Dobos, "PVWatts Version 5 Manual", NREL, Golden, CO, USA,
3039+
Technical Report NREL/TP-6A20-62641, 2014, :doi:`10.2172/1158421`.
29773040
"""
29783041

29793042
params = [soiling, shading, snow, mismatch, wiring, connections, lid,

pvlib/solarposition.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ def spa_python(time, latitude, longitude,
314314
using time.year and time.month from pandas.DatetimeIndex.
315315
For most simulations the default delta_t is sufficient.
316316
The USNO has historical and forecasted delta_t [3]_.
317-
atmos_refrac : float, optional
317+
atmos_refract : float, optional
318318
The approximate atmospheric refraction (in degrees)
319319
at sunrise and sunset.
320320
how : str, optional, default 'numpy'

pvlib/spa.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1057,7 +1057,7 @@ def solar_position(unixtime, lat, lon, elev, pressure, temp, delta_t,
10571057
degrees C; used for atmospheric correction
10581058
delta_t : float or array
10591059
Difference between terrestrial time and UT1.
1060-
atmos_refrac : float
1060+
atmos_refract : float
10611061
The approximate atmospheric refraction (in degrees)
10621062
at sunrise and sunset.
10631063
numthreads: int, optional, default 8

0 commit comments

Comments
 (0)