From ee5e4cbbb5998c33124d1b7ad1d35c2749218f69 Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Fri, 13 May 2016 16:55:54 -0700 Subject: [PATCH 1/3] implement scaling function and method --- pvlib/modelchain.py | 2 ++ pvlib/pvsystem.py | 72 ++++++++++++++++++++++++++++++++++++- pvlib/test/test_pvsystem.py | 25 +++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 09f5336718..d3714a6488 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -342,6 +342,8 @@ def run_model(self, times, irradiance=None, weather=None): self.airmass['airmass_absolute'], self.aoi) + self.dc = self.system.scale_voltage_current_power(self.dc) + self.ac = self.system.snlinverter(self.dc['v_mp'], self.dc['p_mp']) return self diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index c909f7f92f..951271efb4 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -35,6 +35,15 @@ class PVSystem(object): See the :py:class:`LocalizedPVSystem` class for an object model that describes an installed PV system. + The class supports basic system topologies consisting of: + + * `N` total modules arranged in series + (`series_modules=N`, `parallel_modules=1`). + * `M` total modules arranged in parallel + (`series_modules=1`, `parallel_modules=M`). + * `NxM` total modules arranged in `M` strings of `N` modules each + (`series_modules=N`, `parallel_modules=M`). + The class is complementary to the module-level functions. The attributes should generally be things that don't change about @@ -69,6 +78,12 @@ class PVSystem(object): module_parameters : None, dict or Series Module parameters as defined by the SAPM, CEC, or other. + series_modules: int or float + Number of modules in series in a string. + + parallel_modules: int or float. + Number of modules or strings in parallel. + inverter : None, string The model name of the inverters. May be used to look up the inverter_parameters dictionary @@ -95,7 +110,7 @@ def __init__(self, surface_tilt=0, surface_azimuth=180, albedo=None, surface_type=None, module=None, module_parameters=None, - series_modules=None, parallel_modules=None, + series_modules=1, parallel_modules=1, inverter=None, inverter_parameters=None, racking_model='open_rack_cell_glassback', **kwargs): @@ -363,6 +378,27 @@ def snlinverter(self, v_dc, p_dc): """ return snlinverter(self.inverter_parameters, v_dc, p_dc) + def scale_voltage_current_power(self, data): + """ + Scales the voltage, current, and power of the DataFrames + returned by :py:func:`singlediode` and :py:func:`sapm` + by `self.series_modules` and `self.parallel_modules`. + + Parameters + ---------- + data: DataFrame + Must contain columns `'v_mp', 'v_oc', 'i_mp' ,'i_x', 'i_xx', + 'i_sc', 'p_mp'`. + + Returns + ------- + scaled_data: DataFrame + A scaled copy of the input data. + """ + + return scale_voltage_current_power(data, voltage=self.series_modules, + current=self.parallel_modules) + def localize(self, location=None, latitude=None, longitude=None, **kwargs): """Creates a LocalizedPVSystem object using this object @@ -1668,3 +1704,37 @@ def snlinverter(inverter, v_dc, p_dc): ac_power = ac_power.ix[0] return ac_power + + +def scale_voltage_current_power(data, voltage=1, current=1): + """ + Scales the voltage, current, and power of the DataFrames + returned by :py:func:`singlediode` and :py:func:`sapm`. + + Parameters + ---------- + data: DataFrame + Must contain columns `'v_mp', 'v_oc', 'i_mp' ,'i_x', 'i_xx', + 'i_sc', 'p_mp'`. + voltage: numeric + The amount by which to multiply the voltages. + current: numeric + The amount by which to multiply the currents. + + Returns + ------- + scaled_data: DataFrame + A scaled copy of the input data. + `'p_mp'` is scaled by `voltage * current`. + """ + + # as written, only works with a DataFrame + # could make it work with a dict, but it would be more verbose + data = data.copy() + voltages = ['v_mp', 'v_oc'] + currents = ['i_mp' ,'i_x', 'i_xx', 'i_sc'] + data[voltages] *= voltage + data[currents] *= current + data['p_mp'] *= voltage * current + + return data diff --git a/pvlib/test/test_pvsystem.py b/pvlib/test/test_pvsystem.py index 7253dfcbbb..3bd6dadc7e 100644 --- a/pvlib/test/test_pvsystem.py +++ b/pvlib/test/test_pvsystem.py @@ -300,6 +300,31 @@ def test_PVSystem_singlediode_floats(): assert_almost_equals(expected[k], v, 5) +def test_scale_voltage_current_power(): + data = pd.DataFrame( + np.array([[2, 1.5, 10, 8, 12, 0.5, 1.5]]), + columns=['i_sc', 'i_mp', 'v_oc', 'v_mp', 'p_mp', 'i_x', 'i_xx'], + index=[0]) + expected = pd.DataFrame( + np.array([[6, 4.5, 20, 16, 72, 1.5, 4.5]]), + columns=['i_sc', 'i_mp', 'v_oc', 'v_mp', 'p_mp', 'i_x', 'i_xx'], + index=[0]) + out = pvsystem.scale_voltage_current_power(data, voltage=2, current=3) + + +def test_PVSystem_scale_voltage_current_power(): + data = pd.DataFrame( + np.array([[2, 1.5, 10, 8, 12, 0.5, 1.5]]), + columns=['i_sc', 'i_mp', 'v_oc', 'v_mp', 'p_mp', 'i_x', 'i_xx'], + index=[0]) + expected = pd.DataFrame( + np.array([[6, 4.5, 20, 16, 72, 1.5, 4.5]]), + columns=['i_sc', 'i_mp', 'v_oc', 'v_mp', 'p_mp', 'i_x', 'i_xx'], + index=[0]) + system = pvsystem.PVSystem(series_modules=2, parallel_modules=3) + out = system.scale_voltage_current_power(data) + + def test_sapm_celltemp(): default = pvsystem.sapm_celltemp(900, 5, 20) assert_almost_equals(43.509, default.ix[0, 'temp_cell'], 3) From 9efc1def8079e4a5934cf8ac3d6236c9c915f59c Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Mon, 16 May 2016 12:08:41 -0700 Subject: [PATCH 2/3] update whatsnew --- docs/sphinx/source/whatsnew/v0.3.3.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sphinx/source/whatsnew/v0.3.3.txt b/docs/sphinx/source/whatsnew/v0.3.3.txt index 322fb2dc48..a6e05fd827 100644 --- a/docs/sphinx/source/whatsnew/v0.3.3.txt +++ b/docs/sphinx/source/whatsnew/v0.3.3.txt @@ -10,6 +10,8 @@ Enhancements ~~~~~~~~~~~~ * Adds the Erbs model. (:issue:`2`) +* Adds the ``scale_voltage_current_power`` function and ``PVSystem`` method + to support simple array modeling. (:issue:`159`) Bug fixes From f3badb06b7a32980984e7d5cebf3a0fded88c58a Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Fri, 20 May 2016 09:27:31 -0700 Subject: [PATCH 3/3] update doc strings to see system topo --- pvlib/pvsystem.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index 951271efb4..f6cc44ee3a 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -79,10 +79,10 @@ class PVSystem(object): Module parameters as defined by the SAPM, CEC, or other. series_modules: int or float - Number of modules in series in a string. + See system topology discussion above. - parallel_modules: int or float. - Number of modules or strings in parallel. + parallel_modules: int or float + See system topology discussion above. inverter : None, string The model name of the inverters.