-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add desoto and pvsyst as dc_model options to ModelChain #555
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
Changes from all commits
b4737d3
e7fb500
4c621c6
9777ba6
f2d8fe1
3a3afc6
df3a55f
219e8f4
db66d66
7bf8a30
b5ed45f
85e9aac
230349c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
from pvlib.tracking import SingleAxisTracker | ||
import pvlib.irradiance # avoid name conflict with full import | ||
from pvlib.pvsystem import DC_MODEL_PARAMS | ||
from pvlib._deprecation import pvlibDeprecationWarning | ||
|
||
|
||
def basic_chain(times, latitude, longitude, | ||
|
@@ -251,8 +252,8 @@ class ModelChain(object): | |
dc_model: None, str, or function, default None | ||
If None, the model will be inferred from the contents of | ||
system.module_parameters. Valid strings are 'sapm', | ||
'singlediode', 'pvwatts'. The ModelChain instance will be passed | ||
as the first argument to a user-defined function. | ||
'desoto', 'pvsyst', 'pvwatts'. The ModelChain instance will | ||
be passed as the first argument to a user-defined function. | ||
|
||
ac_model: None, str, or function, default None | ||
If None, the model will be inferred from the contents of | ||
|
@@ -379,10 +380,19 @@ def dc_model(self, model): | |
str(missing_params)) | ||
if model == 'sapm': | ||
self._dc_model = self.sapm | ||
elif model == 'singlediode': | ||
self._dc_model = self.singlediode | ||
elif model == 'desoto': | ||
self._dc_model = self.desoto | ||
elif model == 'pvsyst': | ||
self._dc_model = self.pvsyst | ||
elif model == 'pvwatts': | ||
self._dc_model = self.pvwatts_dc | ||
elif model == 'singlediode': | ||
warnings.warn('DC model keyword singlediode used for ' | ||
'ModelChain object. singlediode is ' | ||
'ambiguous, use desoto instead. singlediode ' | ||
'keyword will be removed in v0.7.0 and ' | ||
'later', pvlibDeprecationWarning) | ||
self._dc_model = self.desoto | ||
else: | ||
raise ValueError(model + ' is not a valid DC power model') | ||
else: | ||
|
@@ -393,7 +403,10 @@ def infer_dc_model(self): | |
if set(['A0', 'A1', 'C7']) <= params: | ||
return self.sapm, 'sapm' | ||
elif set(['a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', 'R_s']) <= params: | ||
return self.singlediode, 'singlediode' | ||
return self.desoto, 'desoto' | ||
elif set(['gamma_ref', 'mu_gamma', 'I_L_ref', 'I_o_ref', | ||
'R_sh_ref', 'R_sh_0', 'R_sh_exp', 'R_s']) <= params: | ||
return self.pvsyst, 'pvsyst' | ||
elif set(['pdc0', 'gamma_pdc']) <= params: | ||
return self.pvwatts_dc, 'pvwatts' | ||
else: | ||
|
@@ -408,7 +421,44 @@ def sapm(self): | |
|
||
return self | ||
|
||
def desoto(self): | ||
(photocurrent, saturation_current, resistance_series, | ||
resistance_shunt, nNsVth) = ( | ||
self.system.calcparams_desoto(self.effective_irradiance, | ||
self.temps['temp_cell'])) | ||
|
||
self.diode_params = (photocurrent, saturation_current, | ||
resistance_series, | ||
resistance_shunt, nNsVth) | ||
|
||
self.dc = self.system.singlediode( | ||
photocurrent, saturation_current, resistance_series, | ||
resistance_shunt, nNsVth) | ||
|
||
self.dc = self.system.scale_voltage_current_power(self.dc).fillna(0) | ||
|
||
return self | ||
|
||
def pvsyst(self): | ||
(photocurrent, saturation_current, resistance_series, | ||
resistance_shunt, nNsVth) = ( | ||
self.system.calcparams_pvsyst(self.effective_irradiance, | ||
self.temps['temp_cell'])) | ||
|
||
self.diode_params = (photocurrent, saturation_current, | ||
resistance_series, | ||
resistance_shunt, nNsVth) | ||
|
||
self.dc = self.system.singlediode( | ||
photocurrent, saturation_current, resistance_series, | ||
resistance_shunt, nNsVth) | ||
|
||
self.dc = self.system.scale_voltage_current_power(self.dc).fillna(0) | ||
|
||
return self | ||
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. I don't love the very similar copy/paste code. But it's explicit and that is important too. So I lean towards this approach. 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. I would mark this with There are only two lines of difference between these: --- desoto.py
+++ pvsyst.py
@@ -1,7 +1,7 @@
-def desoto(self):
+def pvsyst(self):
(photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth) = (
- self.system.calcparams_desoto(self.effective_irradiance,
+ self.system.calcparams_pvsyst(self.effective_irradiance,
self.temps['temp_cell']))
self.diode_params = (photocurrent, saturation_current,
You could add a tiny dispatcher that you delegate this common task to that is DRY and IMHO also explicit: def desoto(self):
"""calculate desoto model"""
return self._model_dispatcher(self.system.calcparams_desoto, 'desoto')
def pvsyst(self):
"""calculate pvsyst model"""
return self._model_dispatcher(self.system.calcparams_pvsyst, 'pvsyst')
def _model_dispatcher(self, model_calcparams, model_name=None):
"""
Delegate that dispatches the model
Parameters
----------
model_calcparams : function
A function that calculates the models parameters given irradiance and cell temperature.
model_name : str
Optional string that may be used to further distinguish the model in the future.
"""
(photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth) = (
model_calcparams(self.effective_irradiance,
self.temps['temp_cell']))
self.diode_params = (photocurrent, saturation_current,
resistance_series,
resistance_shunt, nNsVth)
self.dc = self.system.singlediode(
photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)
self.dc = self.system.scale_voltage_current_power(self.dc).fillna(0)
return self 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. Either approach is ok with me at this point. Keep in mind that we've had discussions elsewhere about whether or not it even makes sense to define these model-specific methods on 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. okay, me too, I fine either way 😁 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. @mikofski that's a good suggestion. You are right that we have more diode models waiting - CEC hasn't been connected up yet. But we will (at least I hope) also have 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. Let's keep the bite small, merge this, and take up improvements in another pull request. |
||
|
||
def singlediode(self): | ||
"""Deprecated""" | ||
(photocurrent, saturation_current, resistance_series, | ||
resistance_shunt, nNsVth) = ( | ||
self.system.calcparams_desoto(self.effective_irradiance, | ||
|
Uh oh!
There was an error while loading. Please reload this page.