Skip to content

Commit 645eefe

Browse files
committed
implement voltage, current, power scaling function and method (#171)
* implement scaling function and method * update whatsnew * update doc strings to see system topo
1 parent e1bd29b commit 645eefe

File tree

4 files changed

+100
-1
lines changed

4 files changed

+100
-1
lines changed

docs/sphinx/source/whatsnew/v0.3.3.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Enhancements
1010
~~~~~~~~~~~~
1111

1212
* Adds the Erbs model. (:issue:`2`)
13+
* Adds the ``scale_voltage_current_power`` function and ``PVSystem`` method
14+
to support simple array modeling. (:issue:`159`)
1315

1416

1517
Bug fixes

pvlib/modelchain.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ def run_model(self, times, irradiance=None, weather=None):
342342
self.airmass['airmass_absolute'],
343343
self.aoi)
344344

345+
self.dc = self.system.scale_voltage_current_power(self.dc)
346+
345347
self.ac = self.system.snlinverter(self.dc['v_mp'], self.dc['p_mp'])
346348

347349
return self

pvlib/pvsystem.py

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ class PVSystem(object):
3535
See the :py:class:`LocalizedPVSystem` class for an object model that
3636
describes an installed PV system.
3737
38+
The class supports basic system topologies consisting of:
39+
40+
* `N` total modules arranged in series
41+
(`series_modules=N`, `parallel_modules=1`).
42+
* `M` total modules arranged in parallel
43+
(`series_modules=1`, `parallel_modules=M`).
44+
* `NxM` total modules arranged in `M` strings of `N` modules each
45+
(`series_modules=N`, `parallel_modules=M`).
46+
3847
The class is complementary to the module-level functions.
3948
4049
The attributes should generally be things that don't change about
@@ -69,6 +78,12 @@ class PVSystem(object):
6978
module_parameters : None, dict or Series
7079
Module parameters as defined by the SAPM, CEC, or other.
7180
81+
series_modules: int or float
82+
See system topology discussion above.
83+
84+
parallel_modules: int or float
85+
See system topology discussion above.
86+
7287
inverter : None, string
7388
The model name of the inverters.
7489
May be used to look up the inverter_parameters dictionary
@@ -95,7 +110,7 @@ def __init__(self,
95110
surface_tilt=0, surface_azimuth=180,
96111
albedo=None, surface_type=None,
97112
module=None, module_parameters=None,
98-
series_modules=None, parallel_modules=None,
113+
series_modules=1, parallel_modules=1,
99114
inverter=None, inverter_parameters=None,
100115
racking_model='open_rack_cell_glassback',
101116
**kwargs):
@@ -363,6 +378,27 @@ def snlinverter(self, v_dc, p_dc):
363378
"""
364379
return snlinverter(self.inverter_parameters, v_dc, p_dc)
365380

381+
def scale_voltage_current_power(self, data):
382+
"""
383+
Scales the voltage, current, and power of the DataFrames
384+
returned by :py:func:`singlediode` and :py:func:`sapm`
385+
by `self.series_modules` and `self.parallel_modules`.
386+
387+
Parameters
388+
----------
389+
data: DataFrame
390+
Must contain columns `'v_mp', 'v_oc', 'i_mp' ,'i_x', 'i_xx',
391+
'i_sc', 'p_mp'`.
392+
393+
Returns
394+
-------
395+
scaled_data: DataFrame
396+
A scaled copy of the input data.
397+
"""
398+
399+
return scale_voltage_current_power(data, voltage=self.series_modules,
400+
current=self.parallel_modules)
401+
366402
def localize(self, location=None, latitude=None, longitude=None,
367403
**kwargs):
368404
"""Creates a LocalizedPVSystem object using this object
@@ -1668,3 +1704,37 @@ def snlinverter(inverter, v_dc, p_dc):
16681704
ac_power = ac_power.ix[0]
16691705

16701706
return ac_power
1707+
1708+
1709+
def scale_voltage_current_power(data, voltage=1, current=1):
1710+
"""
1711+
Scales the voltage, current, and power of the DataFrames
1712+
returned by :py:func:`singlediode` and :py:func:`sapm`.
1713+
1714+
Parameters
1715+
----------
1716+
data: DataFrame
1717+
Must contain columns `'v_mp', 'v_oc', 'i_mp' ,'i_x', 'i_xx',
1718+
'i_sc', 'p_mp'`.
1719+
voltage: numeric
1720+
The amount by which to multiply the voltages.
1721+
current: numeric
1722+
The amount by which to multiply the currents.
1723+
1724+
Returns
1725+
-------
1726+
scaled_data: DataFrame
1727+
A scaled copy of the input data.
1728+
`'p_mp'` is scaled by `voltage * current`.
1729+
"""
1730+
1731+
# as written, only works with a DataFrame
1732+
# could make it work with a dict, but it would be more verbose
1733+
data = data.copy()
1734+
voltages = ['v_mp', 'v_oc']
1735+
currents = ['i_mp' ,'i_x', 'i_xx', 'i_sc']
1736+
data[voltages] *= voltage
1737+
data[currents] *= current
1738+
data['p_mp'] *= voltage * current
1739+
1740+
return data

pvlib/test/test_pvsystem.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,31 @@ def test_PVSystem_singlediode_floats():
300300
assert_almost_equals(expected[k], v, 5)
301301

302302

303+
def test_scale_voltage_current_power():
304+
data = pd.DataFrame(
305+
np.array([[2, 1.5, 10, 8, 12, 0.5, 1.5]]),
306+
columns=['i_sc', 'i_mp', 'v_oc', 'v_mp', 'p_mp', 'i_x', 'i_xx'],
307+
index=[0])
308+
expected = pd.DataFrame(
309+
np.array([[6, 4.5, 20, 16, 72, 1.5, 4.5]]),
310+
columns=['i_sc', 'i_mp', 'v_oc', 'v_mp', 'p_mp', 'i_x', 'i_xx'],
311+
index=[0])
312+
out = pvsystem.scale_voltage_current_power(data, voltage=2, current=3)
313+
314+
315+
def test_PVSystem_scale_voltage_current_power():
316+
data = pd.DataFrame(
317+
np.array([[2, 1.5, 10, 8, 12, 0.5, 1.5]]),
318+
columns=['i_sc', 'i_mp', 'v_oc', 'v_mp', 'p_mp', 'i_x', 'i_xx'],
319+
index=[0])
320+
expected = pd.DataFrame(
321+
np.array([[6, 4.5, 20, 16, 72, 1.5, 4.5]]),
322+
columns=['i_sc', 'i_mp', 'v_oc', 'v_mp', 'p_mp', 'i_x', 'i_xx'],
323+
index=[0])
324+
system = pvsystem.PVSystem(series_modules=2, parallel_modules=3)
325+
out = system.scale_voltage_current_power(data)
326+
327+
303328
def test_sapm_celltemp():
304329
default = pvsystem.sapm_celltemp(900, 5, 20)
305330
assert_almost_equals(43.509, default.ix[0, 'temp_cell'], 3)

0 commit comments

Comments
 (0)