From 96697f11dbba4d0a61fce465d40858649b0096c3 Mon Sep 17 00:00:00 2001 From: echedey-ls <80125792+echedey-ls@users.noreply.github.com> Date: Wed, 8 Jan 2025 21:41:21 +0000 Subject: [PATCH 1/8] Add cross_axis_tilt to nomenclature.rst Definition via https://pvlib-python.readthedocs.io/en/stable/reference/generated/pvlib.tracking.calc_cross_axis_tilt.html --- docs/sphinx/source/user_guide/nomenclature.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/sphinx/source/user_guide/nomenclature.rst b/docs/sphinx/source/user_guide/nomenclature.rst index f361690f73..61285211e8 100644 --- a/docs/sphinx/source/user_guide/nomenclature.rst +++ b/docs/sphinx/source/user_guide/nomenclature.rst @@ -36,6 +36,18 @@ There is a convention on consistent variable names throughout the library: bhi Beam/direct horizontal irradiance + cross_axis_tilt + Cross-axis tilt angle [°]. + Consider two parallel rows of modules at different height; + ``cross_axis_tilt`` is the angle formed by the line formed by the + intersection between the slope containing the tracker axes and a plane + perpendicular to the tracker axes, and the horizontal plane. + Cross-axis tilt is measured by using a right-handed convention. + For example, trackers with axis azimuth of 180 degrees (heading south) + will have a negative cross-axis tilt if the tracker axes plane slopes + down to the east and positive cross-axis tilt if the tracker axes plane + slopes up to the east. + dhi Diffuse horizontal irradiance From 8eebd5faab3c68992fb29ef9a3e7d74227b23889 Mon Sep 17 00:00:00 2001 From: echedey-ls <80125792+echedey-ls@users.noreply.github.com> Date: Wed, 8 Jan 2025 21:43:44 +0000 Subject: [PATCH 2/8] Rename, cross_axis_slope -> cross_axis_tilt --- .../shading/plot_martinez_shade_loss.py | 2 +- .../plot_shaded_fraction1d_ns_hsat_example.py | 12 +++++------ pvlib/shading.py | 20 +++++++++---------- pvlib/tests/test_shading.py | 4 ++-- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/examples/shading/plot_martinez_shade_loss.py b/docs/examples/shading/plot_martinez_shade_loss.py index 10ce77f741..b30b6e4c12 100644 --- a/docs/examples/shading/plot_martinez_shade_loss.py +++ b/docs/examples/shading/plot_martinez_shade_loss.py @@ -116,7 +116,7 @@ shading_row_rotation=tracker_theta, collector_width=width, pitch=pitch, - cross_axis_slope=cross_axis_tilt, + cross_axis_tilt=cross_axis_tilt, ) # %% diff --git a/docs/examples/shading/plot_shaded_fraction1d_ns_hsat_example.py b/docs/examples/shading/plot_shaded_fraction1d_ns_hsat_example.py index 7eae2ed7aa..9a1e942e5d 100644 --- a/docs/examples/shading/plot_shaded_fraction1d_ns_hsat_example.py +++ b/docs/examples/shading/plot_shaded_fraction1d_ns_hsat_example.py @@ -49,7 +49,7 @@ collector_width = 3.2 # m pitch = 4.15 # m gcr = collector_width / pitch -cross_axis_slope = -5 # degrees +cross_axis_tilt = -5 # degrees surface_to_axis_offset = 0.07 # m # Generate a time range for the simulation @@ -76,7 +76,7 @@ max_angle=(-50, 50), # (min, max) degrees backtrack=False, gcr=gcr, - cross_axis_tilt=cross_axis_slope, + cross_axis_tilt=cross_axis_tilt, )["tracker_theta"] # %% @@ -112,7 +112,7 @@ collector_width=collector_width, pitch=pitch, surface_to_axis_offset=surface_to_axis_offset, - cross_axis_slope=cross_axis_slope, + cross_axis_tilt=cross_axis_tilt, shading_row_rotation=rotation_angle, ), ) @@ -130,7 +130,7 @@ collector_width=collector_width, pitch=pitch, surface_to_axis_offset=surface_to_axis_offset, - cross_axis_slope=cross_axis_slope, + cross_axis_tilt=cross_axis_tilt, shading_row_rotation=rotation_angle, ), # shaded fraction in the evening @@ -143,7 +143,7 @@ collector_width=collector_width, pitch=pitch, surface_to_axis_offset=surface_to_axis_offset, - cross_axis_slope=cross_axis_slope, + cross_axis_tilt=cross_axis_tilt, shading_row_rotation=rotation_angle, ), ) @@ -161,7 +161,7 @@ collector_width=collector_width, pitch=pitch, surface_to_axis_offset=surface_to_axis_offset, - cross_axis_slope=cross_axis_slope, + cross_axis_tilt=cross_axis_tilt, shading_row_rotation=rotation_angle, ), 0, # no shaded fraction in the evening diff --git a/pvlib/shading.py b/pvlib/shading.py index 42aef892f7..0bdd40dbfb 100644 --- a/pvlib/shading.py +++ b/pvlib/shading.py @@ -354,7 +354,7 @@ def shaded_fraction1d( pitch, axis_tilt=0, surface_to_axis_offset=0, - cross_axis_slope=0, + cross_axis_tilt=0, shading_row_rotation=None, ): r""" @@ -397,7 +397,7 @@ def shaded_fraction1d( surface_to_axis_offset : numeric, default 0 Distance between the rotating axis and the collector surface. May be used to account for a torque tube offset. - cross_axis_slope : numeric, default 0 + cross_axis_tilt : numeric, default 0 Angle of the plane containing the rows' axes from horizontal. Right-handed rotation with respect to the rows axes. In degrees :math:`^{\circ}`. @@ -430,7 +430,7 @@ def shaded_fraction1d( +------------------+----------------------------+ | | :math:`\theta_2` | ``shaded_row_rotation`` | Degrees | +------------------+----------------------------+ :math:`^{\circ}` | - | :math:`\beta_c` | ``cross_axis_slope`` | | + | :math:`\beta_c` | ``cross_axis_tilt`` | | +------------------+----------------------------+---------------------+ | :math:`p` | ``pitch`` | Any consistent | +------------------+----------------------------+ length unit across | @@ -452,7 +452,7 @@ def shaded_fraction1d( >>> shaded_fraction1d(solar_zenith=80, solar_azimuth=135, ... axis_azimuth=90, shaded_row_rotation=30, shading_row_rotation=30, ... collector_width=2, pitch=3, axis_tilt=0, - ... surface_to_axis_offset=0.05, cross_axis_slope=0) + ... surface_to_axis_offset=0.05, cross_axis_tilt=0) 0.47755694708090535 **Fixed-tilt north-facing array on sloped terrain** @@ -466,7 +466,7 @@ def shaded_fraction1d( >>> shaded_fraction1d(solar_zenith=80, solar_azimuth=75.5, ... axis_azimuth=270, shaded_row_rotation=50, shading_row_rotation=30, ... collector_width=2.5, pitch=4, axis_tilt=10, - ... surface_to_axis_offset=0.05, cross_axis_slope=0) + ... surface_to_axis_offset=0.05, cross_axis_tilt=0) 0.793244836197256 **N-S single-axis tracker on sloped terrain** @@ -478,7 +478,7 @@ def shaded_fraction1d( >>> shaded_fraction1d(solar_zenith=80, solar_azimuth=90, axis_azimuth=180, ... shaded_row_rotation=-30, collector_width=1.4, pitch=3, axis_tilt=0, - ... surface_to_axis_offset=0.10, cross_axis_slope=7) + ... surface_to_axis_offset=0.10, cross_axis_tilt=7) 0.8242176864434579 Note the previous example only is valid for the shaded fraction of the @@ -493,7 +493,7 @@ def shaded_fraction1d( >>> shaded_fraction1d(solar_zenith=80, solar_azimuth=270, axis_azimuth=180, ... shaded_row_rotation=30, collector_width=1.4, pitch=3, axis_tilt=0, - ... surface_to_axis_offset=0.10, cross_axis_slope=7) + ... surface_to_axis_offset=0.10, cross_axis_tilt=7) 0.018002567182254348 You must switch the input/output depending on the @@ -528,7 +528,7 @@ def shaded_fraction1d( # calculate repeated elements thetas_1_S_diff = shading_row_rotation - projected_solar_zenith thetas_2_S_diff = shaded_row_rotation - projected_solar_zenith - thetaS_rotation_diff = projected_solar_zenith - cross_axis_slope + thetaS_rotation_diff = projected_solar_zenith - cross_axis_tilt cos_theta_2_S_diff_abs = np.abs(cosd(thetas_2_S_diff)) @@ -548,7 +548,7 @@ def shaded_fraction1d( / collector_width * cosd(thetaS_rotation_diff) / cos_theta_2_S_diff_abs - / cosd(cross_axis_slope) + / cosd(cross_axis_tilt) ) ) @@ -660,7 +660,7 @@ def direct_martinez( >>> solar_zenith=80, solar_azimuth=180, >>> axis_azimuth=90, shaded_row_rotation=25, >>> collector_width=0.5, pitch=1, surface_to_axis_offset=0, - >>> cross_axis_slope=5.711, shading_row_rotation=50) + >>> cross_axis_tilt=5.711, shading_row_rotation=50) >>> # calculation of the number of shaded blocks >>> shaded_blocks = np.ceil(total_blocks*shaded_fraction) >>> # apply the Martinez power losses to the calculated shading diff --git a/pvlib/tests/test_shading.py b/pvlib/tests/test_shading.py index f83f2db47b..3887dd8fd9 100644 --- a/pvlib/tests/test_shading.py +++ b/pvlib/tests/test_shading.py @@ -258,7 +258,7 @@ def sf1d_premises_and_expected(): ), ) # fmt: skip - test_data["cross_axis_slope"] = atand( + test_data["cross_axis_tilt"] = atand( (test_data["z_R"] - test_data["z_L"]) / (test_data["x_L"] - test_data["x_R"]) ) @@ -314,7 +314,7 @@ def test_shaded_fraction1d_unprovided_shading_row_rotation(): test_data = pd.DataFrame( columns=[ "shaded_row_rotation", "surface_to_axis_offset", "collector_width", - "solar_zenith", "cross_axis_slope", "pitch", "solar_azimuth", + "solar_zenith", "cross_axis_tilt", "pitch", "solar_azimuth", "axis_azimuth", "expected_sf", ], data=[ From 0aa883697bab97a7e85c5e0849d1f195a93070dc Mon Sep 17 00:00:00 2001 From: echedey-ls <80125792+echedey-ls@users.noreply.github.com> Date: Wed, 8 Jan 2025 21:53:10 +0000 Subject: [PATCH 3/8] Add renamed_kwarg_warning --- pvlib/shading.py | 8 ++++++++ pvlib/tests/test_shading.py | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/pvlib/shading.py b/pvlib/shading.py index 0bdd40dbfb..b3e9f8822e 100644 --- a/pvlib/shading.py +++ b/pvlib/shading.py @@ -7,6 +7,8 @@ import pandas as pd from pvlib.tools import sind, cosd +from pvlib._deprecation import renamed_kwarg_warning + def ground_angle(surface_tilt, gcr, slant_height): """ @@ -344,6 +346,12 @@ def projected_solar_zenith_angle(solar_zenith, solar_azimuth, return theta_T +@renamed_kwarg_warning( + since="0.11.3", + old_param_name="cross_axis_slope", + new_param_name="cross_axis_tilt", + removal="0.13.0", +) def shaded_fraction1d( solar_zenith, solar_azimuth, diff --git a/pvlib/tests/test_shading.py b/pvlib/tests/test_shading.py index 3887dd8fd9..8a0529222b 100644 --- a/pvlib/tests/test_shading.py +++ b/pvlib/tests/test_shading.py @@ -9,6 +9,9 @@ from pvlib import shading from pvlib.tools import atand +from pvlib.tests.conftest import fail_on_pvlib_version +from pvlib._deprecation import pvlibDeprecationWarning + @pytest.fixture def test_system(): @@ -329,6 +332,22 @@ def test_shaded_fraction1d_unprovided_shading_row_rotation(): assert_allclose(sf, expected_sf, atol=1e-2) +@fail_on_pvlib_version("0.13.0") +def test_shaded_fraction1d_renamed_cross_axis_slope2cross_axis_tilt(): + # Tests shaded_fraction1d with cross_axis_slope instead of cross_axis_tilt + with pytest.warns(pvlibDeprecationWarning, match="cross_axis_slope"): + shading.shaded_fraction1d( + solar_zenith=60, + solar_azimuth=90, + axis_azimuth=180, + shaded_row_rotation=30, + collector_width=3, + pitch=7, + surface_to_axis_offset=0, + cross_axis_slope=0, + ) + + @pytest.fixture def direct_martinez_Table2(): """ From 01d5c0b11be881bfec44277304eb386b1d6391d3 Mon Sep 17 00:00:00 2001 From: echedey-ls <80125792+echedey-ls@users.noreply.github.com> Date: Wed, 8 Jan 2025 21:57:31 +0000 Subject: [PATCH 4/8] Fix typo in renamed_kwarg_warning docstring --- pvlib/_deprecation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/_deprecation.py b/pvlib/_deprecation.py index aedb4d5096..06d35959e0 100644 --- a/pvlib/_deprecation.py +++ b/pvlib/_deprecation.py @@ -334,7 +334,7 @@ def renamed_kwarg_warning(since, old_param_name, new_param_name, removal=""): Not compatible with positional-only arguments. .. note:: - Documentation for the function may updated to reflect the new parameter + Affected function docstring may be updated to reflect the new parameter name; it is suggested to add a |.. versionchanged::| directive. Parameters From e72ca3215b0cc98ac20403d5028ebbabe667a2cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Echedey=20Luis=20=C3=81lvarez?= <80125792+echedey-ls@users.noreply.github.com> Date: Sun, 7 Sep 2025 20:20:47 +0100 Subject: [PATCH 5/8] Deprecate in v0.13.1 / Removal in v0.15.0 --- pvlib/shading.py | 4 ++-- pvlib/tests/test_shading.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pvlib/shading.py b/pvlib/shading.py index b3e9f8822e..fa5f534701 100644 --- a/pvlib/shading.py +++ b/pvlib/shading.py @@ -347,10 +347,10 @@ def projected_solar_zenith_angle(solar_zenith, solar_azimuth, @renamed_kwarg_warning( - since="0.11.3", + since="0.13.1", old_param_name="cross_axis_slope", new_param_name="cross_axis_tilt", - removal="0.13.0", + removal="0.15.0", ) def shaded_fraction1d( solar_zenith, diff --git a/pvlib/tests/test_shading.py b/pvlib/tests/test_shading.py index 8a0529222b..986cab3054 100644 --- a/pvlib/tests/test_shading.py +++ b/pvlib/tests/test_shading.py @@ -332,7 +332,7 @@ def test_shaded_fraction1d_unprovided_shading_row_rotation(): assert_allclose(sf, expected_sf, atol=1e-2) -@fail_on_pvlib_version("0.13.0") +@fail_on_pvlib_version("0.15.0") def test_shaded_fraction1d_renamed_cross_axis_slope2cross_axis_tilt(): # Tests shaded_fraction1d with cross_axis_slope instead of cross_axis_tilt with pytest.warns(pvlibDeprecationWarning, match="cross_axis_slope"): From 08bcde47a31521e1d9487f7f6d7f619a961e27ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Echedey=20Luis=20=C3=81lvarez?= <80125792+echedey-ls@users.noreply.github.com> Date: Sun, 7 Sep 2025 20:47:46 +0100 Subject: [PATCH 6/8] move descriptions, link to nomenclature term --- docs/sphinx/source/user_guide/nomenclature.rst | 2 ++ pvlib/shading.py | 4 ++-- pvlib/tracking.py | 14 ++++---------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/docs/sphinx/source/user_guide/nomenclature.rst b/docs/sphinx/source/user_guide/nomenclature.rst index 61285211e8..827fb99edb 100644 --- a/docs/sphinx/source/user_guide/nomenclature.rst +++ b/docs/sphinx/source/user_guide/nomenclature.rst @@ -47,6 +47,8 @@ There is a convention on consistent variable names throughout the library: will have a negative cross-axis tilt if the tracker axes plane slopes down to the east and positive cross-axis tilt if the tracker axes plane slopes up to the east. + Use :func:`~pvlib.tracking.calc_cross_axis_tilt` to calculate + ``cross_axis_tilt`` dhi Diffuse horizontal irradiance diff --git a/pvlib/shading.py b/pvlib/shading.py index fa5f534701..7be2b62ca5 100644 --- a/pvlib/shading.py +++ b/pvlib/shading.py @@ -406,9 +406,9 @@ def shaded_fraction1d( Distance between the rotating axis and the collector surface. May be used to account for a torque tube offset. cross_axis_tilt : numeric, default 0 - Angle of the plane containing the rows' axes from + Angle of the plane containing the rows' axes relative to horizontal. Right-handed rotation with respect to the rows axes. - In degrees :math:`^{\circ}`. + See :term:`cross_axis_tilt`. In degrees :math:`^{\circ}`. shading_row_rotation : numeric, optional Right-handed rotation of the row casting the shadow, with respect to the row axis. In degrees :math:`^{\circ}`. diff --git a/pvlib/tracking.py b/pvlib/tracking.py index afdaab2adf..3e04e7cc5f 100644 --- a/pvlib/tracking.py +++ b/pvlib/tracking.py @@ -9,7 +9,7 @@ def singleaxis(apparent_zenith, apparent_azimuth, axis_tilt=0, axis_azimuth=0, max_angle=90, backtrack=True, gcr=2.0/7.0, cross_axis_tilt=0): - """ + r""" Determine the rotation angle of a single-axis tracker when given particular solar zenith and azimuth angles. @@ -75,15 +75,9 @@ def singleaxis(apparent_zenith, apparent_azimuth, 2/7 is default. ``gcr`` must be <=1. cross_axis_tilt : float, default 0.0 - The angle, relative to horizontal, of the line formed by the - intersection between the slope containing the tracker axes and a plane - perpendicular to the tracker axes. The cross-axis tilt should be - specified using a right-handed convention. For example, trackers with - axis azimuth of 180 degrees (heading south) will have a negative - cross-axis tilt if the tracker axes plane slopes down to the east and - positive cross-axis tilt if the tracker axes plane slopes down to the - west. Use :func:`~pvlib.tracking.calc_cross_axis_tilt` to calculate - ``cross_axis_tilt``. [degrees] + Angle of the plane containing the rows' axes relative to + horizontal. Right-handed rotation with respect to the rows axes. + See :term:`cross_axis_tilt`. In degrees :math:`^{\circ}`. Returns ------- From 3ca225e7352bdeaf22f26b8b9e7ba659a0b32de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Echedey=20Luis=20=C3=81lvarez?= <80125792+echedey-ls@users.noreply.github.com> Date: Sun, 7 Sep 2025 20:57:35 +0100 Subject: [PATCH 7/8] merge fix --- tests/test_shading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_shading.py b/tests/test_shading.py index 986cab3054..a19917774b 100644 --- a/tests/test_shading.py +++ b/tests/test_shading.py @@ -9,7 +9,7 @@ from pvlib import shading from pvlib.tools import atand -from pvlib.tests.conftest import fail_on_pvlib_version +from .conftest import fail_on_pvlib_version from pvlib._deprecation import pvlibDeprecationWarning From c74127c4138233cb5e7e6cddf7253387aa5f2101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Echedey=20Luis=20=C3=81lvarez?= <80125792+echedey-ls@users.noreply.github.com> Date: Sun, 7 Sep 2025 20:57:42 +0100 Subject: [PATCH 8/8] whatsnew --- docs/sphinx/source/whatsnew/v0.13.1.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/sphinx/source/whatsnew/v0.13.1.rst b/docs/sphinx/source/whatsnew/v0.13.1.rst index 26a591e534..58bf5664a4 100644 --- a/docs/sphinx/source/whatsnew/v0.13.1.rst +++ b/docs/sphinx/source/whatsnew/v0.13.1.rst @@ -13,6 +13,7 @@ Deprecations * Deprecate :py:func:`~pvlib.modelchain.get_orientation`. (:pull:`2495`) * Rename parameter name ``aparent_azimuth`` to ``solar_azimuth`` in :py:func:`~pvlib.tracking.singleaxis`. (:issue:`2479`, :pull:`2480`) +* Rename parameter ``cross_axis_slope`` to ``cross_axis_tilt`` in :py:func:`pvlib.shading.shaded_fraction1d`. (:issue:`2334`, :pull:`2543`) Bug fixes ~~~~~~~~~