Skip to content

refactor pvcell.PVcell.__setattr__ or constructor to only set Icell, Vcell, and Pcell only once #59

@mikofski

Description

@mikofski

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions