Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 44 additions & 9 deletions pvmismatch/pvmismatch_lib/pvmodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,11 @@ def __init__(self, cell_pos=STD96, pvcells=None, pvconst=PVconstants(),
self.cellArea = cellArea #: [cm^2] cell area
if pvcells is None:
# faster to use copy instead of making each object in a for-loop
# use copy instead of deepcopy to keey same pvconst for all objects
# use copy instead of deepcopy to keep same pvconst for all objects
# PVcell.calcCell() creates new np.ndarray if attributes change
pvcells = PVcell(pvconst=self.pvconst)
if isinstance(pvcells, PVcell):
pvcells = [copy(pvcells) for _ in xrange(self.numberCells)]
pvcells = [pvcells] * self.numberCells
if len(pvcells) != self.numberCells:
# TODO: use pvexception
raise Exception(
Expand Down Expand Up @@ -235,21 +235,56 @@ def setSuns(self, Ee, cells=None):
"""
if cells is None:
if np.isscalar(Ee):
for pvc in self.pvcells:
new_pvcells = range(self.numberCells) # new list of cells
old_pvcells = dict.fromkeys(self.pvcells) # same as set(pvcells)
for cell_id, pvcell in enumerate(self.pvcells):
if old_pvcells[pvcell] is None:
new_pvcells[cell_id] = copy(pvcell)
old_pvcells[pvcell] = new_pvcells[cell_id]
else:
new_pvcells[cell_id] = old_pvcells[pvcell]
self.pvcells = new_pvcells
pvcell_set = old_pvcells.itervalues()
for pvc in pvcell_set:
pvc.Ee = Ee
elif np.size(Ee) == self.numberCells:
for pvc, Ee_idx in zip(self.pvcells, Ee):
pvc.Ee = Ee_idx
self.pvcells = copy(self.pvcells) # copy list first
for cell_idx, Ee_idx in enumerate(Ee):
self.pvcells[cell_idx] = copy(self.pvcells[cell_idx])
self.pvcells[cell_idx].Ee = Ee_idx
else:
raise Exception("Input irradiance value (Ee) for each cell!")
else:
Ncells = np.size(cells)
self.pvcells = copy(self.pvcells) # copy list first
if np.isscalar(Ee):
for cell_idx in cells:
self.pvcells[cell_idx].Ee = Ee
cells_to_update = [self.pvcells[i] for i in cells]
old_pvcells = dict.fromkeys(cells_to_update)
for cell_id, pvcell in zip(cells, cells_to_update):
if old_pvcells[pvcell] is None:
self.pvcells[cell_id] = copy(pvcell)
self.pvcells[cell_id].Ee = Ee
old_pvcells[pvcell] = self.pvcells[cell_id]
else:
self.pvcells[cell_id] = old_pvcells[pvcell]
elif np.size(Ee) == Ncells:
for cell_idx, Ee_idx in zip(cells, Ee):
self.pvcells[cell_idx].Ee = Ee_idx
# Find unique irradiance values
# TODO possible "cleaner" alternative by grouping cells into tuples that match the set irradiance
# E.g: pvsys.setSuns({X: {Y: {'Ee': (0.33, 0.99), 'cells': [(2, 3), 17]}}})
cells = np.array(cells)
Ee = np.array(Ee)
unique_ee = np.unique(Ee)
for a_Ee in unique_ee:
cells_subset = cells[np.where(Ee == a_Ee)]
cells_to_update = [self.pvcells[i] for i in cells_subset]
old_pvcells = dict.fromkeys(cells_to_update)
for cell_id, pvcell in zip(cells_subset, cells_to_update):
if old_pvcells[pvcell] is None:
self.pvcells[cell_id] = copy(pvcell)
self.pvcells[cell_id].Ee = a_Ee
old_pvcells[pvcell] = self.pvcells[cell_id]
else:
self.pvcells[cell_id] = old_pvcells[pvcell]
else:
raise Exception("Input irradiance value (Ee) for each cell!")
self.Imod, self.Vmod, self.Pmod, self.Isubstr, self.Vsubstr = self.calcMod()
Expand Down
25 changes: 20 additions & 5 deletions pvmismatch/pvmismatch_lib/pvstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""

import numpy as np
from copy import deepcopy
from copy import copy
from matplotlib import pyplot as plt
# use absolute imports instead of relative, so modules are portable
from pvmismatch.pvmismatch_lib.pvconstants import PVconstants, NUMBERMODS
Expand All @@ -30,7 +30,7 @@ def __init__(self, numberMods=NUMBERMODS, pvmods=None,
# use deepcopy instead of making each object in for-loop, 2x faster
pvmods = PVmodule(pvconst=self.pvconst)
if isinstance(pvmods, PVmodule):
pvmods = [deepcopy(pvmods) for _ in xrange(self.numberMods)]
pvmods = [pvmods] * self.numberMods
# reset pvconsts in all pvcells and pvmodules
for p in pvmods:
for c in p.pvcells:
Expand Down Expand Up @@ -87,11 +87,23 @@ def setSuns(self, Ee):

"""
if np.isscalar(Ee):
new_pvmods = range(self.numberMods) # new list of modules
old_pvmods = dict.fromkeys(self.pvmods) # same as set(pvmods)
for mod_id, pvmod in enumerate(self.pvmods):
if old_pvmods[pvmod] is None:
new_pvmods[mod_id] = copy(pvmod)
old_pvmods[pvmod] = new_pvmods[mod_id]
else:
new_pvmods[mod_id] = old_pvmods[pvmod]
self.pvmods = new_pvmods
for pvmod in iter(self.pvmods):
pvmod.setSuns(Ee)
else:
self.pvmods = copy(self.pvmods) # copy list first
try:
for pvmod, cell_Ee in Ee.iteritems():
pvmod = int(pvmod)
self.pvmods[pvmod] = copy(self.pvmods[pvmod])
if hasattr(cell_Ee, 'keys'):
self.pvmods[pvmod].setSuns(**cell_Ee)
else:
Expand All @@ -100,9 +112,12 @@ def setSuns(self, Ee):
except TypeError:
self.pvmods[pvmod].setSuns(cell_Ee)
except AttributeError:
Ee = Ee[0]
for pvmod in iter(self.pvmods):
pvmod.setSuns(Ee)
# Ee was a list? just take first item in list
if len(Ee) > 1:
raise TypeError('Irradiance, Ee, should be scalar or dict')
for mod_id, pvmod in enumerate(self.pvmods):
self.pvmods[mod_id] = copy(pvmod)
self.pvmods[mod_id].setSuns(Ee[0])
# update modules
self.Istring, self.Vstring, self.Pstring = self.calcString()

Expand Down
6 changes: 4 additions & 2 deletions pvmismatch/pvmismatch_lib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""

import numpy as np
from copy import deepcopy
from copy import copy
from matplotlib import pyplot as plt
# use absolute imports instead of relative, so modules are portable
from pvmismatch.pvmismatch_lib.pvconstants import PVconstants, NUMBERMODS, \
Expand Down Expand Up @@ -34,7 +34,7 @@ def __init__(self, pvconst=PVconstants(), numberStrs=NUMBERSTRS,
pvconst=self.pvconst)
# use deep copy instead of making each object in a for-loop
if isinstance(pvstrs, PVstring):
pvstrs = [deepcopy(pvstrs) for _ in xrange(self.numberStrs)]
pvstrs = [pvstrs] * self.numberStrs
if len(pvstrs) != self.numberStrs:
# TODO: use pvmismatch excecptions
raise Exception("Number of strings don't match.")
Expand Down Expand Up @@ -118,6 +118,8 @@ def setSuns(self, Ee):
pvstr.setSuns(Ee)
else:
for pvstr, pvmod_Ee in Ee.iteritems():
pvstr = int(pvstr)
self.pvstrs[pvstr] = copy(self.pvstrs[pvstr])
self.pvstrs[pvstr].setSuns(pvmod_Ee)
self.Isys, self.Vsys, self.Psys = self.calcSystem()
(self.Imp, self.Vmp, self.Pmp,
Expand Down
106 changes: 106 additions & 0 deletions pvmismatch/tests/test_setsuns.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
import numpy as np
from nose.tools import ok_
from pvmismatch.pvmismatch_lib.pvsystem import PVsystem
import logging

logging.basicConfig(level=logging.DEBUG)
LOGGER = logging.getLogger(__name__)


def test_basic():
Expand Down Expand Up @@ -48,3 +52,105 @@ def test_set_str_2():
Ee = {1: .1}
pvsys.setSuns(Ee)
ok_(np.isclose(pvsys.Pmp, 29136.544447716446))


def test_gh34_35():
pvsys = PVsystem()
# display unique id numbers
LOGGER.debug('\n*** unique id numbers ***')
LOGGER.debug('pvstrs:\n%r', set(pvsys.pvstrs))
LOGGER.debug('pvmods:\n%r', set([x for y in pvsys.pvmods for x in y]))
LOGGER.debug(
'pvcells:\n%r',
{hex(int(id(z))): z for y in pvsys.pvmods for x in y for z in x.pvcells}
)
# test strings references same object
assert pvsys.pvstrs[0] == pvsys.pvstrs[1]
# modules references same object
assert pvsys.pvmods[0][0] == pvsys.pvmods[1][1]
# cells reference same object
assert pvsys.pvmods[0][0].pvcells[0] == pvsys.pvmods[1][1].pvcells[1]

# test set suns on just string #2
pvsys.setSuns({2: 0.88})
# display unique id numbers
LOGGER.debug('pvstrs:\n%r', set(pvsys.pvstrs))
LOGGER.debug('pvmods:\n%r', set([x for y in pvsys.pvmods for x in y]))
LOGGER.debug(
'pvcells:\n%r',
{hex(int(id(z))): z for y in pvsys.pvmods for x in y for z in x.pvcells}
)
# test other string not changed
assert (pvsys.pvstrs[0].pvmods[0].Ee == 1.0).all()
assert (pvsys.pvstrs[1].pvmods[1].Ee == 1.0).all()
# test all modules in string #2 changed
assert (pvsys.pvstrs[2].pvmods[0].Ee == 0.88).all()
assert (pvsys.pvstrs[2].pvmods[2].Ee == 0.88).all()
# test strings references same object
assert pvsys.pvstrs[0] == pvsys.pvstrs[1]
# modules references same object
assert pvsys.pvmods[0][0] == pvsys.pvmods[1][1]
# cells reference same object
assert pvsys.pvmods[0][0].pvcells[0] == pvsys.pvmods[1][1].pvcells[1]
assert pvsys.pvmods[2][0].pvcells[0] == pvsys.pvmods[2][2].pvcells[2]

# test set suns on just module #4 in string #2
pvsys.setSuns({2: {4: 0.75}})
# display unique id numbers
LOGGER.debug('pvstrs:\n%r', set(pvsys.pvstrs))
LOGGER.debug('pvmods:\n%r', set([x for y in pvsys.pvmods for x in y]))
LOGGER.debug(
'pvcells:\n%r',
{hex(int(id(z))): z for y in pvsys.pvmods for x in y for z in x.pvcells}
)
assert (pvsys.pvstrs[0].pvmods[0].Ee == 1.0).all()
assert (pvsys.pvstrs[1].pvmods[1].Ee == 1.0).all()
assert (pvsys.pvstrs[1].pvmods[4].Ee == 1.0).all()
assert (pvsys.pvstrs[2].pvmods[0].Ee == 0.88).all()
assert (pvsys.pvstrs[2].pvmods[2].Ee == 0.88).all()
assert (pvsys.pvstrs[2].pvmods[4].Ee == 0.75).all()
assert pvsys.pvstrs[0] == pvsys.pvstrs[1]
assert pvsys.pvmods[0][0] == pvsys.pvmods[1][1]
assert pvsys.pvmods[0][0].pvcells[0] == pvsys.pvmods[1][1].pvcells[1]

# set just cells #0 and #2 in module #4 in string #2
pvsys.setSuns({2: {4: {'Ee': 0.66, 'cells': [0, 2]}}})
# display unique id numbers
LOGGER.debug('pvstrs:\n%r', set(pvsys.pvstrs))
LOGGER.debug('pvmods:\n%r', set([x for y in pvsys.pvmods for x in y]))
LOGGER.debug(
'pvcells:\n%r',
{hex(int(id(z))): z for y in pvsys.pvmods for x in y for z in x.pvcells}
)
assert (pvsys.pvstrs[0].pvmods[0].Ee == 1.0).all()
assert (pvsys.pvstrs[1].pvmods[1].Ee == 1.0).all()
assert (pvsys.pvstrs[1].pvmods[4].Ee == 1.0).all()
assert (pvsys.pvstrs[2].pvmods[0].Ee == 0.88).all()
assert (pvsys.pvstrs[2].pvmods[2].Ee == 0.88).all()
assert pvsys.pvstrs[2].pvmods[4].pvcells[0].Ee == 0.66
assert pvsys.pvstrs[2].pvmods[4].pvcells[1].Ee == 0.75
assert pvsys.pvstrs[2].pvmods[4].pvcells[2].Ee == 0.66
assert pvsys.pvstrs[0] == pvsys.pvstrs[1]
assert pvsys.pvmods[0][0] == pvsys.pvmods[1][1]
assert pvsys.pvmods[0][0].pvcells[0] == pvsys.pvmods[1][1].pvcells[1]
assert pvsys.pvstrs[2].pvmods[4].pvcells[0] == pvsys.pvstrs[2].pvmods[4].pvcells[2]

# set cells 3 and 4 to one irradiance and 5 to another. should only make two new cell objects
pvsys.setSuns({2: {4: {'Ee': (0.33, 0.99, 0.33), 'cells': (3, 4, 5)}}})
assert (pvsys.pvstrs[0].pvmods[0].Ee == 1.0).all()
assert (pvsys.pvstrs[1].pvmods[1].Ee == 1.0).all()
assert (pvsys.pvstrs[1].pvmods[4].Ee == 1.0).all()
assert (pvsys.pvstrs[2].pvmods[0].Ee == 0.88).all()
assert (pvsys.pvstrs[2].pvmods[2].Ee == 0.88).all()
assert pvsys.pvstrs[2].pvmods[4].pvcells[0].Ee == 0.66
assert pvsys.pvstrs[2].pvmods[4].pvcells[1].Ee == 0.75
assert pvsys.pvstrs[2].pvmods[4].pvcells[2].Ee == 0.66
assert pvsys.pvstrs[0] == pvsys.pvstrs[1]
assert pvsys.pvmods[0][0] == pvsys.pvmods[1][1]
assert pvsys.pvmods[0][0].pvcells[0] == pvsys.pvmods[1][1].pvcells[1]
assert pvsys.pvstrs[2].pvmods[4].pvcells[0] == pvsys.pvstrs[2].pvmods[4].pvcells[2]
assert pvsys.pvstrs[2].pvmods[4].pvcells[3].Ee == 0.33
assert pvsys.pvstrs[2].pvmods[4].pvcells[4].Ee == 0.99
assert pvsys.pvstrs[2].pvmods[4].pvcells[5].Ee == 0.33
assert pvsys.pvstrs[2].pvmods[4].pvcells[3] == pvsys.pvstrs[2].pvmods[4].pvcells[5]