diff --git a/pvmismatch/parallel_calcs.py b/pvmismatch/parallel_calcs.py index 14b2897..b4879fc 100644 --- a/pvmismatch/parallel_calcs.py +++ b/pvmismatch/parallel_calcs.py @@ -76,7 +76,7 @@ def parallel_calcSystem(pvsys, Vsys): IVmods = np.array([(pvmod.Imod, pvmod.Vmod) for pvmod in pvmods], dtype=float).reshape(tot_mods, 2, 2 * pvsys.pvconst.npts) - Vstring_args = np.append(IVmods, Imodstr,1) + Vstring_args = np.append(IVmods, Imodstr, 1) Vstring = np.sum(np.reshape(pool.map(interpMods, Vstring_args, chunksize), (pvsys.numberStrs, pvsys.numberMods, @@ -84,7 +84,7 @@ def parallel_calcSystem(pvsys, Vsys): # reshape Vstring to reorganize mods in each string # IE (, , ) # add up voltages from each mod to get Vstring - # NOTE: str: 0th dim, mod: 1st dim, npts: 2nd dim + # NOTE: str: 0th dim, mod: 1st dim, npts: 2nd dim Pstring = Istring * Vstring for (pvstr, P, I, V) in zip(pvsys.pvstrs, Pstring, Istring, Vstring): pvstr.Pstring, pvstr.Istring, pvstr.Vstring = P, I, V @@ -146,7 +146,7 @@ def parallel_calcMod(pvmod): # protect main thread if current_process().name != 'MainProcess': raise PVparallel_calcError(__name__) - + procs = pvmod.pvconst.procs if not procs: procs = max(cpu_count() - 2, 1) @@ -162,7 +162,7 @@ def parallel_calcMod(pvmod): IatVrbd = pool.map(partial_calcIatVrbd, zip(pvmod.Vcell.T, pvmod.Icell.T), chunksize) Isc = np.mean(pvmod.Ee) * pvmod.pvconst.Isc0 - Imax = (np.max(IatVrbd) - Isc) * pvmod.pvconst.Imod_pts + Isc # max current + Imax = (np.max(IatVrbd) - Isc) * pvmod.pvconst.Imod_pts + Isc # Imax Imin = np.min(pvmod.Icell) Imin = Imin if Imin < 0 else 0 Ineg = (Imin - Isc) * pvmod.pvconst.Imod_negpts + Isc # min current @@ -171,7 +171,7 @@ def parallel_calcMod(pvmod): start = np.cumsum(pvmod.subStrCells) - pvmod.subStrCells stop = np.cumsum(pvmod.subStrCells) # partial with Imod constant - partial_interpVsubstrcells = partial(interpVsubstrcells,Imod=Imod) + partial_interpVsubstrcells = partial(interpVsubstrcells, Imod=Imod) # interpolate cell voltages Vsubstrcells = np.squeeze(pool.map(partial_interpVsubstrcells, zip(pvmod.Icell.T, pvmod.Vcell.T), chunksize)) diff --git a/pvmismatch/pvmodule.py b/pvmismatch/pvmodule.py index ca1be80..40c3078 100644 --- a/pvmismatch/pvmodule.py +++ b/pvmismatch/pvmodule.py @@ -125,7 +125,7 @@ def calcMod(self): # and some negative current to interpolate all cells # find Icell at Vrbd for all cells in module IatVrbd = [np.interp(self.pvconst.VRBD, Vcell, Icell) for - (Vcell, Icell) in zip(self.Vcell.T, self.Icell.T)] + (Vcell, Icell) in zip(self.Vcell.T, self.Icell.T)] Isc = np.mean(self.Ee) * self.pvconst.Isc0 # max current Imax = (np.max(IatVrbd) - Isc) * self.pvconst.Imod_pts + Isc diff --git a/pvmismatch/pvstring.py b/pvmismatch/pvstring.py index b83d03a..c37dfb9 100644 --- a/pvmismatch/pvstring.py +++ b/pvmismatch/pvstring.py @@ -68,11 +68,35 @@ def calcString(self): Pstring = Istring * Vstring return (Istring, Vstring, Pstring) - def setSuns(self, Ee, cells=None, modules=None): + def setSuns(self, Ee): """ - Set irradiance on cells in modules of string. + Set irradiance on cells in modules of string in system. + If Ee is ... + ... scalar, then sets the entire string to that irradiance. + ... a dictionary, then each key refers to a module in the string, + and the corresponding value are passed to + :meth:`~pvmodules.PVmodules.setSuns()` + + Example:: + Ee={0: {'cells': (1,2,3), 'Ee': (0.9, 0.3, 0.5)}} # set module 0 + Ee=0.91 # set all modules to 0.91 suns + Ee={12: 0.77} # set module with index 12 to 0.77 suns + Ee={8: [0.23 (0, 1, 2)], 7: [(0.45, 0.35), (71, 72)]} + + :param Ee: irradiance [W/m^2] + :type Ee: dict or float """ - pass + if np.isscalar(Ee): + for pvmod in self.pvmods: + pvmod.setSuns(Ee) + else: + for pvmod, cell_Ee in Ee.iteritems(): + if hasattr(cell_Ee, 'keys'): + self.pvmods[pvmod].setSuns(**cell_Ee) + else: + self.pvmods[pvmod].setSuns(*cell_Ee) + # update modules + self.Istring, self.Vstring, self.Pstring = self.calcString() def plotStr(self): """ diff --git a/pvmismatch/pvsystem.py b/pvmismatch/pvsystem.py index d5d51ff..5804641 100644 --- a/pvmismatch/pvsystem.py +++ b/pvmismatch/pvsystem.py @@ -33,7 +33,7 @@ def __init__(self, pvconst=PVconstants(), numberStrs=NUMBERSTRS, if pvmods is None: # use deep copy instead of making each object in a for-loop pvstr = PVstring(self.pvconst, self.numberMods, - numberCells=self.numberCells, Ee=Ee) + numberCells=self.numberCells, Ee=Ee) self.pvstrs = [pvstr] * self.numberStrs pvstrs = [deepcopy(pvstr) for pvstr in self.pvstrs[1:]] self.pvstrs[1:] = pvstrs @@ -48,7 +48,7 @@ def __init__(self, pvconst=PVconstants(), numberStrs=NUMBERSTRS, self.pvstrs = [PVstring(self.pvconst, pvmods=pvmodstr) for pvmodstr in pvmods] pvmodstrNumCells = [pvmodstr[0].numberCells - for pvmodstr in pvmods] + for pvmodstr in pvmods] if any(pvmodstrNumCells != self.numberCells): errString = ('All modules must have the same' + ' number of cells.') @@ -136,23 +136,38 @@ def calcMPP_IscVocFFeff(self): eff = Pmp / Psun return (Imp, Vmp, Pmp, Isc, Voc, FF, eff) - def setSuns(self, Ee, cells=None, modules=None, strings=None): + def setSuns(self, Ee): """ Set irradiance on cells in modules of string in system. + If Ee is ... + ... scalar, then sets the entire system to that irradiance. + ... a dictionary, then each key refers to a pv-string in the system, + and the corresponding value is either a dictionary or a scalar. + If the dictionary's value is another dictionary, then its keys are pv- + modules and its values are either cells and corresponding Ee, cells and + a scalar Ee, a scalar Ee value for all cells or an array of Ee values + for all cells in the module. The values of pv-modules are passed to + :meth:`~pvmodules.PVmodules.setSuns()` + + Example:: + Ee={0: {0: {'cells': (0, 1, 2), 'Ee': (0.9, 0.3, 0.5)}}} + Ee=0.91 # set all modules in all strings to 0.91 suns + Ee={12: 0.77} # set all modules in string with index 12 to 0.77 suns + Ee={3: {8: 0.23, 7: 0.45}} # set module with index 8 to 0.23 suns and + module with index 7 to 0.45 suns in string with index 3 + :param Ee: irradiance [W/m^2] - :type Ee: {float, 3-D iterable} dim-0: strings, dim-1: modules, \ - dim-2: cells - :param cells: id numbers of cells with changing Ee - :type cells: {int, 3-D iterable} same size as Ee, dim-0: strings, \ - dim-1: modules, dim-2: cells - :param modules: id numbers of modules with changing Ee - :type modules: {int, 2-D iterable} same size as Ee, dim-0: strings, \ - dim-1: modules - :param strings: id numbers of strings with changing Ee - :type strings: {int, 1-D iterable} same size as Ee, dim-0: strings - + :type Ee: dict or float """ - pass + if np.isscalar(Ee): + for pvstr in self.pvstrs: + pvstr.setSuns(Ee) + else: + for pvstr, pvmod_Ee in Ee.iteritems(): + self.pvstrs[pvstr].setSuns(pvmod_Ee) + (self.Isys, self.Vsys, self.Psys) = self.calcSystem() + (self.Imp, self.Vmp, self.Pmp, + self.Isc, self.Voc, self.FF, self.eff) = self.calcMPP_IscVocFFeff() def plotSys(self, sysPlot=None): """