-
Notifications
You must be signed in to change notification settings - Fork 42
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
Add detailed PV model (pvsamv1) #99
Merged
Merged
Changes from 15 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
d27518d
Improve value assignment in power_source
Matthew-Boyd 5ba2820
Add detailed PV model (pvsamv1)
Matthew-Boyd 5c3a671
Add custom PV model capability
Matthew-Boyd 99a1ca2
Fix test interaction
Matthew-Boyd 67f9690
Properly enforce coherence between detailed plant attributes
Matthew-Boyd 83ee966
Verify capacity from electrical parameters
Matthew-Boyd 65e81ec
Explicitly specify use of detailed pv model (pvsamv1)
Matthew-Boyd 8390997
Refactor find_strings_per_inverter into size_electrical_parameters
Matthew-Boyd 09a38e7
Refactor find_modules_per_string and add test
Matthew-Boyd bbcdc5a
Demonstrate use of autosizing electrical parameters
Matthew-Boyd 312df60
Move electrical sizing test to test_layout file
Matthew-Boyd 307bf18
Add documentation of new PV model options and their default behavior
Matthew-Boyd 32c5949
Add detailed pv model getters and setters
Matthew-Boyd 216011b
Utilize system capacity property setter
Matthew-Boyd e1729d7
Fix docstrings in pv_design_utils.py
Matthew-Boyd ba4e32c
Fix subarray designation
Matthew-Boyd 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 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 |
---|---|---|
@@ -0,0 +1,147 @@ | ||
from typing import Union, Optional, Sequence, Any | ||
|
||
import PySAM.Pvsamv1 as Pvsam | ||
import PySAM.Singleowner as Singleowner | ||
|
||
from hybrid.power_source import * | ||
from hybrid.layout.pv_design_utils import * | ||
from hybrid.layout.pv_layout import PVLayout, PVGridParameters | ||
from hybrid.dispatch.power_sources.pv_dispatch import PvDispatch | ||
|
||
|
||
class DetailedPVPlant(PowerSource): | ||
_system_model: Pvsam.Pvsamv1 | ||
_financial_model: Union[Any, Singleowner.Singleowner] | ||
_layout: Union[Any, PVLayout] | ||
_dispatch: PvDispatch | ||
|
||
def __init__(self, | ||
site: SiteInfo, | ||
pv_config: dict): | ||
""" | ||
|
||
:param pv_config: dict, with following keys: | ||
'tech_config': dict, contains parameters for pvsamv1 technology model | ||
'fin_config': dict, contains `model_type` and any inputs for chosen financial model type | ||
'layout_params': optional DetailedPVParameters, the design vector w/ values. Required for layout modeling | ||
'layout_config': optional dict, contains all keys for PVLayoutConfig dataclass. Required for layout modeling | ||
""" | ||
system_model = Pvsam.default("FlatPlatePVSingleOwner") | ||
financial_model = Singleowner.from_existing(system_model, "FlatPlatePVSingleOwner") | ||
|
||
super().__init__("SolarPlant", site, system_model, financial_model) | ||
|
||
self._system_model.SolarResource.solar_resource_data = self.site.solar_resource.data | ||
|
||
self.dc_degradation = [0] | ||
|
||
params: Optional[PVGridParameters] = None | ||
if 'layout_params' in pv_config.keys(): | ||
params: PVGridParameters = pv_config['layout_params'] | ||
self._layout = PVLayout(site, system_model, params) | ||
|
||
self._dispatch: PvDispatch = None | ||
|
||
if 'tech_config' in pv_config.keys(): | ||
self.processed_assign(pv_config['tech_config']) | ||
|
||
def processed_assign(self, params): | ||
""" | ||
Assign attributes from dictionary with additional processing | ||
to enforce coherence between attributes | ||
""" | ||
self.assign(params) | ||
calculated_system_capacity = verify_capacity_from_electrical_parameters( | ||
system_capacity_target=self.system_capacity, | ||
n_strings=self.n_strings, | ||
modules_per_string=self.modules_per_string, | ||
module_power=self.module_power | ||
) | ||
self.system_capacity = calculated_system_capacity | ||
|
||
@property | ||
def system_capacity(self) -> float: | ||
"""pass through to established name property""" | ||
return self.system_capacity_kw | ||
|
||
@system_capacity.setter | ||
def system_capacity(self, size_kw: float): | ||
"""pass through to established name setter""" | ||
self.system_capacity_kw = size_kw | ||
|
||
@property | ||
def system_capacity_kw(self) -> float: | ||
return self._system_model.value('system_capacity') # [kW] DC | ||
|
||
@system_capacity_kw.setter | ||
def system_capacity_kw(self, size_kw: float): | ||
""" | ||
Sets the system capacity | ||
:param size_kw: DC system size in kW | ||
:return: | ||
""" | ||
self._system_model.value('system_capacity', size_kw) | ||
|
||
@property | ||
def dc_degradation(self) -> float: | ||
"""Annual DC degradation for lifetime simulations [%/year]""" | ||
return self._system_model.Lifetime.dc_degradation | ||
|
||
@dc_degradation.setter | ||
def dc_degradation(self, dc_deg_per_year: Sequence): | ||
self._system_model.Lifetime.dc_degradation = dc_deg_per_year | ||
|
||
@property | ||
def dc_ac_ratio(self) -> float: | ||
return self.system_capacity / (self.n_inverters * self.inverter_power) | ||
|
||
@property | ||
def module_power(self) -> float: | ||
"""Module power in kW""" | ||
return get_module_power(self._system_model) * 1e-3 | ||
|
||
@property | ||
def inverter_power(self) -> float: | ||
"""Inverter power in kW""" | ||
return get_inverter_power(self._system_model) * 1e-3 | ||
|
||
@property | ||
def modules_per_string(self) -> float: | ||
"""Modules per string""" | ||
return self._system_model.SystemDesign.subarray1_modules_per_string | ||
|
||
@modules_per_string.setter | ||
def modules_per_string(self, _modules_per_string: float): | ||
"""Sets the modules per string and updates the system capacity""" | ||
self._system_model.SystemDesign.subarray1_modules_per_string = _modules_per_string | ||
self._system_model.SystemDesign.subarray1_modules_per_string = 0 | ||
self._system_model.SystemDesign.subarray1_modules_per_string = 0 | ||
self._system_model.SystemDesign.subarray1_modules_per_string = 0 | ||
self.system_capacity = self.module_power * _modules_per_string * self.n_strings | ||
|
||
@property | ||
def n_strings(self) -> float: | ||
"""Total number of strings""" | ||
return self._system_model.SystemDesign.subarray1_nstrings \ | ||
+ self._system_model.SystemDesign.subarray2_nstrings \ | ||
+ self._system_model.SystemDesign.subarray3_nstrings \ | ||
+ self._system_model.SystemDesign.subarray4_nstrings | ||
|
||
@n_strings.setter | ||
def n_strings(self, _n_strings: float): | ||
"""Sets the total number of strings and updates the system capacity""" | ||
self._system_model.SystemDesign.subarray1_nstrings = _n_strings | ||
self._system_model.SystemDesign.subarray2_nstrings = 0 | ||
self._system_model.SystemDesign.subarray3_nstrings = 0 | ||
self._system_model.SystemDesign.subarray4_nstrings = 0 | ||
self.system_capacity = self.module_power * self.modules_per_string * _n_strings | ||
|
||
@property | ||
def n_inverters(self) -> float: | ||
"""Total number of inverters""" | ||
return self._system_model.SystemDesign.inverter_count | ||
|
||
@n_inverters.setter | ||
def n_inverters(self, _n_inverters: float): | ||
"""Sets the total number of inverters""" | ||
self._system_model.SystemDesign.inverter_count = _n_inverters |
This file contains 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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be subarray2-4?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agh, darn it! Thanks for the catch!