pvlib-python
pvlib-python copied to clipboard
Applied PVsyst-type losses in ModelChain
I would like to start a discussion around developing features that implement PVsyst style losses that act as direct physical operators rather than as percentage factors on just the dc section of the ModelChain
. For instance, implementing soiling losses as monthly percentage inputs that operate on the irradiance input leading to effective irradiance, DC ohmic losses as a percentage at STC loss from which a resistance value is calculated and operates on the current of the DC output, and/or AC ohmic Losses as a STC loss percentage that operates on the output of the ac_model.
It is my understanding that loss models in the ModelChain are currently implemented as a single operation after the dc_model
has been run and before the ac_model
and only affect the dc outputs. Therefore "pvsyst_losses" functionality would not be an additional loss model at the losses_model
part of the chain, but would require extra steps added to the chain.
I wanted to bring this up and open it for discussion about preferred ways to implement this. For instance , a soiling_loss function could be added that executes before the aoi_model.
This potentially depreciates the losses_model as a single self-contained function.
I suppose what I am suggesting is to remove the losses_model in favor of new functions like soiling_losses, dc_losses, ac_losses. What to run for each of these could then be defined per model strategy whether it is pvwatts, sapm, or pvsyst, etc,. If this strategy seems valid I would like to attempt a pull request to begin implementing it.
The only legacy interface for loss models is in ModelChain.losses_model
, which sits between ModelChain.dc_model
and ModelChain.ac_model
in the various run_model
methods. The current options for losses_model
are PVSystem.pvwatts_losses
and ModelChain.no_extra_losses
. We could rename losses_model
to something more specific dc_losses
as you suggest, and preserve the PVWatts function at that stage. That creates space to name and insert other loss model methods, e.g., poa_losses
for soiling and snow.
Or perhaps instead of renaming losses_model
, it could be kept as a ModelChain
attribute where a user could specify it to be either 'pvwatts' or 'pvsyst'? Then instead of the ModelChain.losses_model
being a function, it is a label that gets used to decide which functions to run at various losses methods.
And if it is 'pvsyst' then there would be 'pvsyst' specific keys in the 'losses_parameters' that are used by PVSystem
.
Is this a place to display first passes at code for comment and checks? Here is something I am working on for a pvsyst style dc ohmic loss. Users would pass a 'dc_ohmic_percent' as a 'losses_parameter' when creating PVSystem
. There would be a PVSystem
method to calculate the equivalent resistance from that:
def equivalent_resistance_from_percent_stc(self):
vmp = self.modules_per_string * self.module_parameters['V_mp_ref']
imp = self.strings_per_inverter * self.module_parameters['I_mp_ref']
Rw = (self.losses_parameters['dc_ohmic_percent'] / 100) * (vmp / imp)
return Rw
And an accompanying ModelChain
method that would apply that to dc output:
def ohmic_loss_from_percent_stc(self.system):
Rw = equivalent_resistance_from_percent_stc(self)
ohmic_loss_fraction = Rw * (self.dc['i_mp']/self.dc['v_mp'])
ohmic_loss = ohmic_loss_fraction * self.dc['p_mp']
self.dc['p_mp'] = self.dc['p_mp'] - ohmic_loss
return self
I have more work for testing and documentation and writing in checks for the 'dc_ohmic_percent' parameter before making a pull request, but if there is any feedback in the meantime about this approach I am happy to hear it.
Or perhaps instead of renaming
losses_model
, it could be kept as aModelChain
attribute where a user could specify it to be either 'pvwatts' or 'pvsyst'? Then instead of theModelChain.losses_model
being a function, it is a label that gets used to decide which functions to run at various losses methods.
I think this is how it works now. There's some internal plumbing using a decorator @losses_model.setter
that marks code which is executed when a value e.g. 'pvwatts' is assigned to ModelChain.losses_model
. In effect, assigning ModelChain.losses_model = 'pvwatts'
also sets a value for Modelchain._losses_model
which is a function handle. Then when ModelChain.losses_model
is referenced, the decorator @property
marks code that is run, i.e., executes the function ModelChain._losses_model
.
And if it is 'pvsyst' then there would be 'pvsyst' specific keys in the 'losses_parameters' that are used by
PVSystem
.
Yes. We would need to add a new method ModelChain.pvsyst_losses
to handle the calculation.
Is this a place to display first passes at code for comment and checks? Here is something I am working on for a pvsyst style dc ohmic loss. Users would pass a 'dc_ohmic_percent' as a 'losses_parameter' when creating
PVSystem
. There would be aPVSystem
method to calculate the equivalent resistance from that:def equivalent_resistance_from_percent_stc(self): vmp = self.modules_per_string * self.module_parameters['V_mp_ref'] imp = self.strings_per_inverter * self.module_parameters['I_mp_ref'] Rw = (self.losses_parameters['dc_ohmic_percent'] / 100) * (vmp / imp) return Rw
And an accompanying
ModelChain
method that would apply that to dc output:def ohmic_loss_from_percent_stc(self.system): Rw = equivalent_resistance_from_percent_stc(self) ohmic_loss_fraction = Rw * (self.dc['i_mp']/self.dc['v_mp']) ohmic_loss = ohmic_loss_fraction * self.dc['p_mp'] self.dc['p_mp'] = self.dc['p_mp'] - ohmic_loss return self
I have more work for testing and documentation and writing in checks for the 'dc_ohmic_percent' parameter before making a pull request, but if there is any feedback in the meantime about this approach I am happy to hear it.
That looks to be in the right direction. I'm not sure about the ModelChain
method, we'll need to look at it in the context of executing a losses
model.