-
Notifications
You must be signed in to change notification settings - Fork 34
Description
The pcell.PVcell() constructor sets Icell, Vcell, and Pcell to None which calls the __setattr__() overload which calls calcCells() and sets Icell, Vcell, and Pcell again!
The constructor calls to self.__setattr__(key, value) look like this:
setting attribute Rs to 0.004267236774264931
setting attribute Rsh to 10.01226369025448
setting attribute Isat1_T0 to 2.28618816125344e-11
setting attribute Isat2 to 1.117455042372326e-06
setting attribute Isc0_T0 to 6.3056
setting attribute aRBD to 0.0001036748445065697
setting attribute bRBD to 0.0
setting attribute VRBD to -5.527260068445654
setting attribute nRBD to 3.284628553041425
setting attribute Eg to 1.1
setting attribute alpha_Isc to 0.0003551
setting attribute Tcell to 298.15
setting attribute Ee to 1.0
setting attribute pvconst to <PVconstants(npts=101)>
setting attribute Icell to None
setting attribute Vcell to None
setting attribute Pcell to None
Since __setattr__() checks to see if pvconst attribute exists, therefore it doesn't calculate Icell, Vcell, and Pcell until the end, but then it sets them again, calling calcCells() again and again and again.
I think just move the pvconst setting in the constructor to the last position, or maybe add an _calc_now flag might be more explicit. something like:
_calc_now = False
def __init__(self, Rs=RS, Rsh=RSH, Isat1_T0=ISAT1_T0, Isat2=ISAT2,
Isc0_T0=ISC0_T0, aRBD=ARBD, bRBD=BRBD, VRBD=VRBD_,
nRBD=NRBD, Eg=EG, alpha_Isc=ALPHA_ISC,
Tcell=TCELL, Ee=1., pvconst=PVconstants()):
# user inputs
self.Rs = Rs #: [ohm] series resistance
self.Rsh = Rsh #: [ohm] shunt resistance
self.Isat1_T0 = Isat1_T0 #: [A] diode one sat. current at T0
self.Isat2 = Isat2 #: [A] diode two saturation current
self.Isc0_T0 = Isc0_T0 #: [A] short circuit current at T0
self.aRBD = aRBD #: reverse breakdown coefficient 1
self.bRBD = bRBD #: reverse breakdown coefficient 2
self.VRBD = VRBD #: [V] reverse breakdown voltage
self.nRBD = nRBD #: reverse breakdown exponent
self.Eg = Eg #: [eV] band gap of cSi
self.alpha_Isc = alpha_Isc #: [1/K] short circuit temp. coeff.
self.Tcell = Tcell #: [K] cell temperature
self.Ee = Ee #: [suns] incident effective irradiance on cell
self.pvconst = pvconst #: configuration constants
self.Icell = None #: cell currents on IV curve [A]
self.Vcell = None #: cell voltages on IV curve [V]
self.Pcell = None #: cell power on IV curve [W]
# set calculation flag
self._calc_now = True # overwrites the class attribute
def __setattr__(self, key, value):
try:
value = np.float64(value)
except (TypeError, ValueError):
pass
super(PVcell, self).__setattr__(key, value)
# after all attributes have been initialized, recalculate IV curve
# every time __setattr__() is called
if self._calc_now:
Icell, Vcell, Pcell = self.calcCell()
super(PVcell, self).__setattr__('Icell', Icell)
super(PVcell, self).__setattr__('Vcell', Vcell)
super(PVcell, self).__setattr__('Pcell', Pcell)
I think this is kinda relevant to #48, or at least the last bit where it says, "all calculations should wait until all new parameters are set," but I thought that was already mentioned in another issue. Maybe the other issue was #15? Anyway, the reason why I think this is relevant to that part of the issue is because if you need to delay calculation of the cell, then just set pvc._calc_now = False and it won't self update until you set it to True again.
But this issue isn't directly related to #48 which is more about creating a single update method that copies cells, modules or strings as needed when updating irradiance, cell-temperature, or any parameter, instead of having methods for each parameter, eg setsuns() and settemps() which are nearly identical and repeated in pvmodules and pvstrings. See the TODO in the code.
This is easy to do in the PVcell.update() method:
def update(self, **kwargs):
"""
Update user-defined constants.
"""
# TODO: use __dict__.update()
# self.__dict__.update(kwargs)
# TODO: check for floats and update IV curve
# * __setattr__ already checks for floats
# turn off calculation flag until all attributes are updated to save time
self._calc_now = False
for k, v in kwargs.iteritems():
setattr(self, k, v)
self._calc_now = True # recalculate