Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion benchmarks/benchmarks/infinite_sheds.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def setup(self, vectorize):
self.tracking = tracking.singleaxis(
self.solar_position['apparent_zenith'],
self.solar_position['azimuth'],
axis_tilt=0,
axis_slope=0,
axis_azimuth=0,
max_angle=60,
backtrack=True,
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/benchmarks/tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def time_singleaxis(self):
with np.errstate(invalid='ignore'):
tracking.singleaxis(self.solar_position.apparent_zenith,
self.solar_position.azimuth,
axis_tilt=0,
axis_slope=0,
axis_azimuth=0,
max_angle=60,
backtrack=True,
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/bifacial/plot_bifi_model_mc.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
times = pd.date_range('2021-06-21', '2021-6-22', freq='1T', tz=tz)

# create site system characteristics
axis_tilt = 0
axis_slope = 0
axis_azimuth = 180
gcr = 0.35
max_angle = 60
Expand All @@ -65,7 +65,7 @@
cs = site_location.get_clearsky(times)

# load solar position and tracker orientation for use in pvsystem object
sat_mount = pvsystem.SingleAxisTrackerMount(axis_tilt=axis_tilt,
sat_mount = pvsystem.SingleAxisTrackerMount(axis_slope=axis_slope,
axis_azimuth=axis_azimuth,
max_angle=max_angle,
backtrack=True,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def calculate_poa(tmy, solar_position, surface_tilt, surface_azimuth):
# single-axis tracking:
orientation = tracking.singleaxis(solar_position['apparent_zenith'],
solar_position['azimuth'],
axis_tilt=0, # flat array
axis_slope=0, # flat array
axis_azimuth=180, # south-facing azimuth
max_angle=60, # a common maximum rotation
backtrack=True, # backtrack for a c-Si array
Expand Down
14 changes: 7 additions & 7 deletions docs/examples/shading/plot_martinez_shade_loss.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
gcr = width / pitch # ground coverage ratio
N_modules_per_row = 6
axis_azimuth = 180 # N-S axis
axis_tilt = 0 # flat because the axis is perpendicular to the slope
cross_axis_tilt = -7 # 7 degrees downward to the east
axis_slope = 0 # flat because the axis is perpendicular to the slope
cross_axis_slope = -7 # 7 degrees downward to the east

latitude, longitude = 40.2712, -3.7277
locus = pvlib.location.Location(
Expand Down Expand Up @@ -91,12 +91,12 @@
tracking_result = pvlib.tracking.singleaxis(
apparent_zenith=solar_apparent_zenith,
solar_azimuth=solar_azimuth,
axis_tilt=axis_tilt,
axis_slope=axis_slope,
axis_azimuth=axis_azimuth,
max_angle=(-90 + cross_axis_tilt, 90 + cross_axis_tilt), # (min, max)
max_angle=(-90 + cross_axis_slope, 90 + cross_axis_slope), # (min, max)
backtrack=False,
gcr=gcr,
cross_axis_tilt=cross_axis_tilt,
cross_axis_slope=cross_axis_slope,
)

tracker_theta, aoi, surface_tilt, surface_azimuth = (
Expand All @@ -111,12 +111,12 @@
solar_apparent_zenith,
solar_azimuth,
axis_azimuth,
axis_tilt=axis_tilt,
axis_slope=axis_slope,
shaded_row_rotation=tracker_theta,
shading_row_rotation=tracker_theta,
collector_width=width,
pitch=pitch,
cross_axis_slope=cross_axis_tilt,
cross_axis_slope=cross_axis_slope,
)

# %%
Expand Down
16 changes: 8 additions & 8 deletions docs/examples/shading/plot_shaded_fraction1d_ns_hsat_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
latitude, longitude = 28.51, -13.89
altitude = pvlib.location.lookup_altitude(latitude, longitude)

axis_tilt = 3 # degrees, positive is upwards in the axis_azimuth direction
axis_slope = 3 # degrees, positive is upwards in the axis_azimuth direction
axis_azimuth = 180 # degrees, N-S tracking axis
collector_width = 3.2 # m
pitch = 4.15 # m
Expand All @@ -71,12 +71,12 @@
rotation_angle = pvlib.tracking.singleaxis(
solar_zenith,
solar_azimuth,
axis_tilt,
axis_slope,
axis_azimuth,
max_angle=(-50, 50), # (min, max) degrees
backtrack=False,
gcr=gcr,
cross_axis_tilt=cross_axis_slope,
cross_axis_slope=cross_axis_slope,
)["tracker_theta"]

# %%
Expand All @@ -95,7 +95,7 @@
# failure or with a different system configuration.

psza = pvlib.shading.projected_solar_zenith_angle(
solar_zenith, solar_azimuth, axis_tilt, axis_azimuth
solar_zenith, solar_azimuth, axis_slope, axis_azimuth
)

# Calculate the shaded fraction for the eastmost row
Expand All @@ -108,7 +108,7 @@
solar_azimuth,
axis_azimuth,
shaded_row_rotation=rotation_angle,
axis_tilt=axis_tilt,
axis_slope=axis_slope,
collector_width=collector_width,
pitch=pitch,
surface_to_axis_offset=surface_to_axis_offset,
Expand All @@ -126,7 +126,7 @@
solar_azimuth,
axis_azimuth,
shaded_row_rotation=rotation_angle,
axis_tilt=axis_tilt,
axis_slope=axis_slope,
collector_width=collector_width,
pitch=pitch,
surface_to_axis_offset=surface_to_axis_offset,
Expand All @@ -139,7 +139,7 @@
solar_azimuth,
axis_azimuth,
shaded_row_rotation=rotation_angle,
axis_tilt=axis_tilt,
axis_slope=axis_slope,
collector_width=collector_width,
pitch=pitch,
surface_to_axis_offset=surface_to_axis_offset,
Expand All @@ -157,7 +157,7 @@
solar_azimuth,
axis_azimuth,
shaded_row_rotation=rotation_angle,
axis_tilt=axis_tilt,
axis_slope=axis_slope,
collector_width=collector_width,
pitch=pitch,
surface_to_axis_offset=surface_to_axis_offset,
Expand Down
6 changes: 3 additions & 3 deletions docs/examples/solar-tracking/plot_discontinuous_tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

class DiscontinuousTrackerMount(pvsystem.SingleAxisTrackerMount):
# inherit from SingleAxisTrackerMount so that we get the
# constructor and tracking attributes (axis_tilt etc) automatically
# constructor and tracking attributes (axis_slope etc) automatically

def get_orientation(self, solar_zenith, solar_azimuth):
# Different trackers update at different rates; in this example we'll
Expand All @@ -37,9 +37,9 @@ def get_orientation(self, solar_zenith, solar_azimuth):

tracking_data_15min = tracking.singleaxis(
zenith_subset, azimuth_subset,
self.axis_tilt, self.axis_azimuth,
self.axis_slope, self.axis_azimuth,
self.max_angle, self.backtrack,
self.gcr, self.cross_axis_tilt
self.gcr, self.cross_axis_slope
)
# propagate the 15-minute positions to 1-minute stair-stepped values:
tracking_data_1min = tracking_data_15min.reindex(solar_zenith.index,
Expand Down
4 changes: 2 additions & 2 deletions docs/examples/solar-tracking/plot_single_axis_tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
truetracking_angles = tracking.singleaxis(
apparent_zenith=solpos['apparent_zenith'],
solar_azimuth=solpos['azimuth'],
axis_tilt=0,
axis_slope=0,
axis_azimuth=180,
max_angle=90,
backtrack=False, # for true-tracking
Expand Down Expand Up @@ -62,7 +62,7 @@
backtracking_angles = tracking.singleaxis(
apparent_zenith=solpos['apparent_zenith'],
solar_azimuth=solpos['azimuth'],
axis_tilt=0,
axis_slope=0,
axis_azimuth=180,
max_angle=90,
backtrack=True,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
# calculating the backtracking angle requires knowledge of the relative spacing
# of adjacent tracker rows. This example shows how the backtracking angle
# changes based on a vertical offset between rows caused by sloped terrain.
# It uses :py:func:`pvlib.tracking.calc_axis_tilt` and
# :py:func:`pvlib.tracking.calc_cross_axis_tilt` to calculate the necessary
# It uses :py:func:`pvlib.tracking.calc_axis_slope` and
# :py:func:`pvlib.tracking.calc_cross_axis_slope` to calculate the necessary
# array geometry parameters and :py:func:`pvlib.tracking.singleaxis` to
# calculate the backtracking angles.
#
Expand Down Expand Up @@ -97,20 +97,20 @@

# compare the backtracking angle at various terrain slopes
fig, ax = plt.subplots()
for cross_axis_tilt in [0, 5, 10]:
for cross_axis_slope in [0, 5, 10]:
tracker_data = tracking.singleaxis(
apparent_zenith=solpos['apparent_zenith'],
solar_azimuth=solpos['azimuth'],
axis_tilt=0, # flat because the axis is perpendicular to the slope
axis_slope=0, # flat because the axis is perpendicular to the slope
axis_azimuth=180, # N-S axis, azimuth facing south
max_angle=90,
backtrack=True,
gcr=gcr,
cross_axis_tilt=cross_axis_tilt)
cross_axis_slope=cross_axis_slope)

# tracker rotation is undefined at night
backtracking_position = tracker_data['tracker_theta'].fillna(0)
label = 'cross-axis tilt: {}°'.format(cross_axis_tilt)
label = 'cross-axis tilt: {}°'.format(cross_axis_slope)
backtracking_position.plot(label=label, ax=ax)

plt.legend()
Expand Down Expand Up @@ -141,14 +141,14 @@
axis_azimuth = 180 # tracker axis is still N-S

# calculate the tracker axis tilt, assuming that the axis follows the terrain:
axis_tilt = tracking.calc_axis_tilt(slope_azimuth, slope_tilt, axis_azimuth)
axis_slope = tracking.calc_axis_slope(slope_azimuth, slope_tilt, axis_azimuth)

# calculate the cross-axis tilt:
cross_axis_tilt = tracking.calc_cross_axis_tilt(slope_azimuth, slope_tilt,
axis_azimuth, axis_tilt)
cross_axis_slope = tracking.calc_cross_axis_slope(slope_azimuth, slope_tilt,
axis_azimuth, axis_slope)

print('Axis tilt:', '{:0.01f}°'.format(axis_tilt))
print('Cross-axis tilt:', '{:0.01f}°'.format(cross_axis_tilt))
print('Axis tilt:', '{:0.01f}°'.format(axis_slope))
print('Cross-axis tilt:', '{:0.01f}°'.format(cross_axis_slope))

# %%
# And now we can pass use these values to generate the tracker curve as
Expand All @@ -157,18 +157,18 @@
tracker_data = tracking.singleaxis(
apparent_zenith=solpos['apparent_zenith'],
solar_azimuth=solpos['azimuth'],
axis_tilt=axis_tilt, # no longer flat because the terrain imparts a tilt
axis_slope=axis_slope, # no longer flat because the terrain imparts a tilt
axis_azimuth=axis_azimuth,
max_angle=90,
backtrack=True,
gcr=gcr,
cross_axis_tilt=cross_axis_tilt)
cross_axis_slope=cross_axis_slope)

backtracking_position = tracker_data['tracker_theta'].fillna(0)
backtracking_position.plot()

title_template = 'Axis tilt: {:0.01f}° Cross-axis tilt: {:0.01f}°'
plt.title(title_template.format(axis_tilt, cross_axis_tilt))
plt.title(title_template.format(axis_slope, cross_axis_slope))
plt.show()

# %%
Expand Down
4 changes: 2 additions & 2 deletions docs/sphinx/source/reference/tracking.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ Tracking
:toctree: generated/

tracking.singleaxis
tracking.calc_axis_tilt
tracking.calc_cross_axis_tilt
tracking.calc_axis_slope
tracking.calc_cross_axis_slope
tracking.calc_surface_orientation
14 changes: 14 additions & 0 deletions docs/sphinx/source/user_guide/extras/nomenclature.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ There is a convention on consistent variable names throughout the library:
bhi
Beam/direct horizontal irradiance

cross_axis_slope
Cross-axis tilt angle. [°]
Consider two parallel rows of modules at different height;
``cross_axis_slope`` is the angle formed 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° (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.
Use :func:`~pvlib.tracking.calc_cross_axis_slope` to calculate
``cross_axis_slope``

dhi
Diffuse horizontal irradiance

Expand Down
11 changes: 11 additions & 0 deletions docs/sphinx/source/whatsnew/v0.13.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ v0.13.2 (Anticipated December, 2025)

Breaking Changes
~~~~~~~~~~~~~~~~
* Rename ``axis_tilt`` and ``cross_axis_tilt`` to ``axis_slope`` and ``cross_axis_slope`` all through the project. Affects:

- :py:func:`pvlib.shading.shaded_fraction1d` parameters ``cross_axis_tilt`` and ``axis_tilt``
- :py:func:`pvlib.shading.projected_solar_zenith_angle` parameter ``axis_tilt``
- :py:func:`pvlib.tracking.singleaxis` parameters ``cross_axis_tilt`` and ``axis_tilt``
- :py:func:`pvlib.tracking.calc_surface_orientation` parameter ``axis_tilt``
- :py:func:`!pvlib.tracking.calc_axis_tilt` function is renamed to :py:func:`~pvlib.tracking.calc_axis_slope`
- :py:func:`!pvlib.tracking.calc_cross_axis_tilt` function is renamed to :py:func:`~pvlib.tracking.calc_cross_axis_slope`, and its parameter ``axis_tilt``
- :py:class:`pvlib.pvsystem.SingleAxisTrackerMount` dataclass fields ``axis_tilt`` and ``cross_axis_tilt``

(:issue:`2334`, :pull:`2543`)


Deprecations
Expand Down
6 changes: 3 additions & 3 deletions docs/sphinx/source/whatsnew/v0.8.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,14 @@ Enhancements
* Added ``racking_model``, ``module_type``, and ``temperature_model_parameters`` to
:py:class:`~pvlib.pvsystem.PVSystem` and :py:class:`~pvlib.tracking.SingleAxisTracker`
repr methods. (:issue:`1027`)
* Added :py:func:`~pvlib.tracking.calc_axis_tilt` to calculate the
tracker axes tilt and :py:func:`~pvlib.tracking.calc_cross_axis_tilt` to
* Added :py:func:`!pvlib.tracking.calc_axis_tilt` to calculate the
tracker axes tilt and :py:func:`!pvlib.tracking.calc_cross_axis_tilt` to
calculate the cross-axis tilt, which is 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. (:pull:`823`)
* Added ``cross_axis_tilt`` argument to :py:func:`~pvlib.tracking.singleaxis`
and :py:func:`~pvlib.tracking.SingleAxisTracker` which defaults to zero. Use
:py:func:`~pvlib.tracking.calc_cross_axis_tilt` to calculate the cross-axis
:py:func:`!pvlib.tracking.calc_cross_axis_tilt` to calculate the cross-axis
tilt angle if necessary. (:pull:`823`)
* Added ability for :py:func:`pvlib.soiling.hsu` to accept arbitrary time intervals. (:pull:`980`)
* Added :py:func:`pvlib.temperature.fuentes` for cell temperature modeling. (:pull:`1037`)
Expand Down
2 changes: 1 addition & 1 deletion pvlib/_deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pvlib/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1257,7 +1257,7 @@ def _prep_inputs_tracking(self):
self.results.solar_position['azimuth'])
self.results.tracking['surface_tilt'] = (
self.results.tracking['surface_tilt']
.fillna(self.system.axis_tilt))
.fillna(self.system.axis_slope))
self.results.tracking['surface_azimuth'] = (
self.results.tracking['surface_azimuth']
.fillna(self.system.axis_azimuth))
Expand Down
Loading