-
Notifications
You must be signed in to change notification settings - Fork 1.1k
add Mount classes #1176
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
add Mount classes #1176
Changes from 5 commits
Commits
Show all changes
54 commits
Select commit
Hold shift + click to select a range
cb3c207
add Mount classes, incorporate into Array and PVSystem
kandersolar 8a6d0e6
update pvsystem tests
kandersolar 6d4240e
delete mounts module
kandersolar fc4064b
fix modelchain tests
kandersolar e8f1404
some modifications to SingleAxisTracker
kandersolar 02a2b27
changes from review
kandersolar 0be45ae
stickler
kandersolar 9406ccd
Merge branch 'master' into mount_classes
kandersolar e1bdc67
use dataclasses for mounts
kandersolar 61650e9
update tests
kandersolar fc47003
update docs
kandersolar 887fd3a
whatsnew
kandersolar ecc4737
test mount classes
kandersolar cbb41e1
stickler
kandersolar 9e663d2
more tests
kandersolar 105edb7
another test
kandersolar 6d32c41
fix typo
kandersolar 4a6347e
clean up AbstractMount
kandersolar 1e063ba
remove unnecessary use of dataclasses.field
kandersolar 3dcf106
calculate -> get
kandersolar d4045a3
Merge remote-tracking branch 'upstream/master' into mount_classes
kandersolar b0b551f
Update pvlib/pvsystem.py
kandersolar 515a359
stickler
kandersolar a874b11
test fixes
kandersolar 17195ae
add optional surface_tilt parameter to PVSystem.fuentes_celltemp
kandersolar 93716bb
move racking_model and module_height to the Mounts
kandersolar efe6b3b
fix some tests
kandersolar 74a6be4
remove unnecessary fixture
kandersolar 9da9eb4
Revert "remove unnecessary fixture"
kandersolar 2320ed7
Merge remote-tracking branch 'upstream/master' into mount_classes
kandersolar 6370143
update merged test
kandersolar 6181e96
fix fuentes issue, sort of
kandersolar 47b6884
pep8
kandersolar dbc1193
pep8
kandersolar e0eeef4
remove PVSystem.fuentes_celltemp surface_tilt parameter
kandersolar cf3fe20
placeholder fuentes surface_tilt logic
kandersolar 7c18126
Merge branch 'master' into mount_classes
kandersolar 86292c5
test updates
kandersolar cc5f45a
Merge remote-tracking branch 'upstream/master' into mount_classes
kandersolar 739359e
remove unused imports
kandersolar 59547f5
remove fuentes override complexity
kandersolar bed27c9
stickler
kandersolar 1103f99
update RST pages
kandersolar e6504cd
Merge remote-tracking branch 'upstream/master' into mount_classes
kandersolar 73aba9a
revert unnecessary docs change
kandersolar f3ff722
add link to pvsystem and modelchain pages in api listing
kandersolar 9c0c3ff
other changes from review
kandersolar 35da280
get module_height from mount instead of temperature_model_parameters
kandersolar 1a43ea8
coverage for fuentes module_height parameter
kandersolar c1738e9
deprecate SingleAxisTracker
kandersolar 781b133
suppress SAT deprecation warnings in tests
kandersolar 22341ec
Apply suggestions from code review
kandersolar 6df8408
Tracking -> Tracker
kandersolar 506edbc
Merge branch 'mount_classes' of https://github.com/kanderso-nrel/pvli…
kandersolar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -191,8 +191,7 @@ def __init__(self, | |
|
||
if arrays is None: | ||
self.arrays = (Array( | ||
surface_tilt, | ||
surface_azimuth, | ||
FixedMount(surface_tilt, surface_azimuth), | ||
albedo, | ||
surface_type, | ||
module, | ||
|
@@ -765,7 +764,10 @@ def fuentes_celltemp(self, poa_global, temp_air, wind_speed): | |
wind_speed = self._validate_per_array(wind_speed, system_wide=True) | ||
|
||
def _build_kwargs_fuentes(array): | ||
kwargs = {'surface_tilt': array.surface_tilt} | ||
# TODO: I think there should be an interface function so that | ||
# directly accessing surface_tilt isn't necessary. Doesn't this | ||
# break for SAT? | ||
kwargs = {'surface_tilt': array.mount.surface_tilt} | ||
temp_model_kwargs = _build_kwargs([ | ||
'noct_installed', 'module_height', 'wind_height', 'emissivity', | ||
'absorption', 'surface_tilt', 'module_width', 'module_length'], | ||
|
@@ -1046,22 +1048,26 @@ def temperature_model_parameters(self, value): | |
@property | ||
@_unwrap_single_value | ||
def surface_tilt(self): | ||
return tuple(array.surface_tilt for array in self.arrays) | ||
# TODO: don't access mount attributes directly? | ||
return tuple(array.mount.surface_tilt for array in self.arrays) | ||
|
||
@surface_tilt.setter | ||
def surface_tilt(self, value): | ||
# TODO: don't access mount attributes directly? | ||
for array in self.arrays: | ||
array.surface_tilt = value | ||
array.mount.surface_tilt = value | ||
|
||
@property | ||
@_unwrap_single_value | ||
def surface_azimuth(self): | ||
kandersolar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return tuple(array.surface_azimuth for array in self.arrays) | ||
# TODO: don't access mount attributes directly? | ||
return tuple(array.mount.surface_azimuth for array in self.arrays) | ||
|
||
@surface_azimuth.setter | ||
def surface_azimuth(self, value): | ||
# TODO: don't access mount attributes directly? | ||
for array in self.arrays: | ||
array.surface_azimuth = value | ||
array.mount.surface_azimuth = value | ||
|
||
@property | ||
@_unwrap_single_value | ||
|
@@ -1098,20 +1104,15 @@ class Array: | |
""" | ||
An Array is a set of of modules at the same orientation. | ||
|
||
Specifically, an array is defined by tilt, azimuth, the | ||
Specifically, an array is defined by its mount, the | ||
module parameters, the number of parallel strings of modules | ||
and the number of modules on each string. | ||
|
||
Parameters | ||
---------- | ||
surface_tilt: float or array-like, default 0 | ||
Surface tilt angles in decimal degrees. | ||
The tilt angle is defined as degrees from horizontal | ||
(e.g. surface facing up = 0, surface facing horizon = 90) | ||
|
||
surface_azimuth: float or array-like, default 180 | ||
Azimuth angle of the module surface. | ||
North=0, East=90, South=180, West=270. | ||
mount: FixedMount, SingleAxisTrackerMount, or other, default None | ||
Mounting strategy for the array, used to determine module orientation. | ||
kandersolar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
If not provided, a FixedMount with zero tilt is used. | ||
kandersolar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
albedo : None or float, default None | ||
The ground albedo. If ``None``, will attempt to use | ||
|
@@ -1152,15 +1153,17 @@ class Array: | |
""" | ||
|
||
def __init__(self, | ||
surface_tilt=0, surface_azimuth=180, | ||
mount=None, | ||
albedo=None, surface_type=None, | ||
module=None, module_type=None, | ||
module_parameters=None, | ||
temperature_model_parameters=None, | ||
modules_per_string=1, strings=1, | ||
racking_model=None, name=None): | ||
self.surface_tilt = surface_tilt | ||
self.surface_azimuth = surface_azimuth | ||
if mount is None: | ||
self.mount = FixedMount(0, 180) | ||
else: | ||
self.mount = mount | ||
|
||
self.surface_type = surface_type | ||
if albedo is None: | ||
|
@@ -1189,10 +1192,11 @@ def __init__(self, | |
self.name = name | ||
|
||
def __repr__(self): | ||
attrs = ['name', 'surface_tilt', 'surface_azimuth', 'module', | ||
attrs = ['name', 'mount', 'module', | ||
'albedo', 'racking_model', 'module_type', | ||
'temperature_model_parameters', | ||
'strings', 'modules_per_string'] | ||
|
||
return 'Array:\n ' + '\n '.join( | ||
f'{attr}: {getattr(self, attr)}' for attr in attrs | ||
) | ||
|
@@ -1213,7 +1217,6 @@ def _infer_temperature_model_params(self): | |
return {} | ||
|
||
def _infer_cell_type(self): | ||
|
||
""" | ||
Examines module_parameters and maps the Technology key for the CEC | ||
database and the Material key for the Sandia database to a common | ||
|
@@ -1271,7 +1274,9 @@ def get_aoi(self, solar_zenith, solar_azimuth): | |
aoi : Series | ||
Then angle of incidence. | ||
""" | ||
return irradiance.aoi(self.surface_tilt, self.surface_azimuth, | ||
orientation = self.mount.get_orientation(solar_zenith, solar_azimuth) | ||
return irradiance.aoi(orientation['surface_tilt'], | ||
orientation['surface_azimuth'], | ||
solar_zenith, solar_azimuth) | ||
|
||
def get_irradiance(self, solar_zenith, solar_azimuth, dni, ghi, dhi, | ||
|
@@ -1320,8 +1325,9 @@ def get_irradiance(self, solar_zenith, solar_azimuth, dni, ghi, dhi, | |
if airmass is None: | ||
airmass = atmosphere.get_relative_airmass(solar_zenith) | ||
|
||
return irradiance.get_total_irradiance(self.surface_tilt, | ||
self.surface_azimuth, | ||
orientation = self.mount.get_orientation(solar_zenith, solar_azimuth) | ||
return irradiance.get_total_irradiance(orientation['surface_tilt'], | ||
orientation['surface_azimuth'], | ||
solar_zenith, solar_azimuth, | ||
dni, ghi, dhi, | ||
dni_extra=dni_extra, | ||
|
@@ -1373,6 +1379,54 @@ def get_iam(self, aoi, iam_model='physical'): | |
raise ValueError(model + ' is not a valid IAM model') | ||
|
||
|
||
class FixedMount: | ||
kandersolar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def __init__(self, surface_tilt=0, surface_azimuth=180): | ||
self.surface_tilt = surface_tilt | ||
self.surface_azimuth = surface_azimuth | ||
|
||
def __repr__(self): | ||
return ( | ||
'FixedMount:' | ||
f'\n surface_tilt: {self.surface_tilt}' | ||
f'\n surface_azimuth: {self.surface_azimuth}' | ||
) | ||
|
||
def get_orientation(self, solar_zenith, solar_azimuth): | ||
kandersolar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return { | ||
'surface_tilt': self.surface_tilt, | ||
'surface_azimuth': self.surface_azimuth, | ||
} | ||
|
||
|
||
class SingleAxisTrackerMount: | ||
def __init__(self, axis_tilt, axis_azimuth, max_angle, backtrack, gcr, | ||
cross_axis_tilt): | ||
self.axis_tilt = axis_tilt | ||
self.axis_azimuth = axis_azimuth | ||
self.max_angle = max_angle | ||
self.backtrack = backtrack | ||
self.gcr = gcr | ||
self.cross_axis_tilt = cross_axis_tilt | ||
|
||
def __repr__(self): | ||
attrs = ['axis_tilt', 'axis_azimuth', 'max_angle', | ||
'backtrack', 'gcr', 'cross_axis_tilt'] | ||
|
||
return 'SingleAxisTrackerMount:\n ' + '\n '.join( | ||
f'{attr}: {getattr(self, attr)}' for attr in attrs | ||
) | ||
|
||
def get_orientation(self, solar_zenith, solar_azimuth): | ||
from pvlib import tracking # avoid circular import issue | ||
tracking_data = tracking.singleaxis( | ||
solar_zenith, solar_azimuth, | ||
self.axis_tilt, self.axis_azimuth, | ||
self.max_angle, self.backtrack, | ||
self.gcr, self.cross_axis_tilt | ||
) | ||
return tracking_data | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. still thinking about interface promises... |
||
|
||
|
||
def calcparams_desoto(effective_irradiance, temp_cell, | ||
alpha_sc, a_ref, I_L_ref, I_o_ref, R_sh_ref, R_s, | ||
EgRef=1.121, dEgdT=-0.0002677, | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.