-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Implement PVSystem.get_ac #1147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
51f4346
c0769e7
18434f6
607cf4c
cb06bbc
1766912
36dac15
7a3f3f7
b53e48f
fc3eafc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -852,7 +852,75 @@ def i_from_v(self, resistance_shunt, resistance_series, nNsVth, voltage, | |
return i_from_v(resistance_shunt, resistance_series, nNsVth, voltage, | ||
saturation_current, photocurrent) | ||
|
||
# inverter now specified by self.inverter_parameters | ||
def get_ac(self, model, p_dc, v_dc=None): | ||
r"""Calculates AC power from p_dc using the inverter model indicated | ||
by model and self.inverter_parameters. | ||
|
||
Parameters | ||
---------- | ||
model : str | ||
Must be one of 'sandia', 'adr', or 'pvwatts'. | ||
p_dc : numeric, or tuple, list or array of numeric | ||
DC power on each MPPT input of the inverter. Use tuple, list or | ||
array for inverters with multiple MPPT inputs. If type is array, | ||
p_dc must be 2d with axis 0 being the MPPT inputs. [W] | ||
v_dc : numeric, or tuple, list or array of numeric | ||
DC voltage on each MPPT input of the inverter. Required when | ||
model='sandia' or model='adr'. Use tuple, list or | ||
array for inverters with multiple MPPT inputs. If type is array, | ||
v_dc must be 2d with axis 0 being the MPPT inputs. [V] | ||
|
||
Returns | ||
------- | ||
power_ac : numeric | ||
AC power output for the inverter. [W] | ||
|
||
Raises | ||
------ | ||
ValueError | ||
If model is not one of 'sandia', 'adr' or 'pvwatts'. | ||
ValueError | ||
If model='adr' and the PVSystem has more than one array. | ||
|
||
See also | ||
-------- | ||
pvlib.inverter.sandia | ||
pvlib.inverter.sandia_multi | ||
pvlib.inverter.adr | ||
pvlib.inverter.pvwatts | ||
pvlib.inverter.pvwatts_multi | ||
""" | ||
model = model.lower() | ||
multiple_arrays = self.num_arrays > 1 | ||
if model == 'sandia': | ||
if multiple_arrays: | ||
p_dc = self._validate_per_array(p_dc) | ||
wholmgren marked this conversation as resolved.
Show resolved
Hide resolved
|
||
v_dc = self._validate_per_array(v_dc) | ||
inv_fun = inverter.sandia_multi | ||
else: | ||
inv_fun = inverter.sandia | ||
return inv_fun(v_dc, p_dc, self.inverter_parameters) | ||
elif model == 'pvwatts': | ||
kwargs = _build_kwargs(['eta_inv_nom', 'eta_inv_ref'], | ||
self.inverter_parameters) | ||
if multiple_arrays: | ||
p_dc = self._validate_per_array(p_dc) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove this line assuming we move the validation call above the |
||
inv_fun = inverter.pvwatts_multi | ||
else: | ||
inv_fun = inverter.pvwatts | ||
return inv_fun(p_dc, self.inverter_parameters['pdc0'], **kwargs) | ||
elif model == 'adr': | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we need to handle the case that |
||
if multiple_arrays: | ||
raise ValueError( | ||
'The adr inverter function cannot be used for an inverter', | ||
wholmgren marked this conversation as resolved.
Show resolved
Hide resolved
|
||
' with multiple MPPT inputs') | ||
else: | ||
return inverter.adr(v_dc, p_dc, self.inverter_parameters) | ||
else: | ||
raise ValueError( | ||
model + ' is not a valid AC power model.', | ||
' model must be one of "sandia", "adr" or "pvwatts"') | ||
|
||
def snlinverter(self, v_dc, p_dc): | ||
"""Uses :py:func:`pvlib.inverter.sandia` to calculate AC power based on | ||
``self.inverter_parameters`` and the input voltage and power. | ||
|
@@ -969,7 +1037,6 @@ def pvwatts_multi(self, p_dc): | |
self.inverter_parameters) | ||
return inverter.pvwatts_multi(p_dc, self.inverter_parameters['pdc0'], | ||
**kwargs) | ||
|
||
@property | ||
@_unwrap_single_value | ||
def module_parameters(self): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1374,6 +1374,21 @@ def test_PVSystem_multi_scale_voltage_current_power(mocker): | |
system.scale_voltage_current_power(None) | ||
|
||
|
||
def test_PVSystem_get_ac_sandia(cec_inverter_parameters, mocker): | ||
inv_fun = mocker.spy(inverter, 'sandia') | ||
system = pvsystem.PVSystem( | ||
inverter=cec_inverter_parameters['Name'], | ||
inverter_parameters=cec_inverter_parameters, | ||
) | ||
vdcs = pd.Series(np.linspace(0, 50, 3)) | ||
idcs = pd.Series(np.linspace(0, 11, 3)) | ||
pdcs = idcs * vdcs | ||
pacs = system.get_ac('sandia', vdcs, pdcs) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand why this test passed in the CI because I think we had a similar issue with the CI in the last year. Maybe there's something wrong in our configuration. |
||
assert_series_equal(pacs, pd.Series([-0.020000, 132.004308, 250.000000])) | ||
inv_fun.assert_called_once() | ||
|
||
|
||
# remove after deprecation period for PVSystem.snlinverter | ||
def test_PVSystem_snlinverter(cec_inverter_parameters): | ||
system = pvsystem.PVSystem( | ||
inverter=cec_inverter_parameters['Name'], | ||
|
@@ -1387,6 +1402,31 @@ def test_PVSystem_snlinverter(cec_inverter_parameters): | |
assert_series_equal(pacs, pd.Series([-0.020000, 132.004308, 250.000000])) | ||
|
||
|
||
def test_PVSystem_get_ac_sandia_multi(cec_inverter_parameters, mocker): | ||
inv_fun = mocker.spy(inverter, 'sandia_multi') | ||
system = pvsystem.PVSystem( | ||
arrays=[pvsystem.Array(), pvsystem.Array()], | ||
inverter=cec_inverter_parameters['Name'], | ||
inverter_parameters=cec_inverter_parameters, | ||
) | ||
vdcs = pd.Series(np.linspace(0, 50, 3)) | ||
idcs = pd.Series(np.linspace(0, 11, 3)) / 2 | ||
pdcs = idcs * vdcs | ||
pacs = system.get_ac('sandia', (vdcs, vdcs), (pdcs, pdcs)) | ||
assert_series_equal(pacs, pd.Series([-0.020000, 132.004308, 250.000000])) | ||
inv_fun.assert_called_once() | ||
with pytest.raises(ValueError, | ||
match="Length mismatch for per-array parameter"): | ||
system.get_ac('sandia', vdcs, (pdcs, pdcs)) | ||
with pytest.raises(ValueError, | ||
match="Length mismatch for per-array parameter"): | ||
system.get_ac('sandia', vdcs, (pdcs,)) | ||
with pytest.raises(ValueError, | ||
match="Length mismatch for per-array parameter"): | ||
system.get_ac('sandia', (vdcs, vdcs), (pdcs, pdcs, pdcs)) | ||
|
||
|
||
# remove after deprecation period for PVSystem.sandia_multi | ||
def test_PVSystem_sandia_multi(cec_inverter_parameters): | ||
system = pvsystem.PVSystem( | ||
arrays=[pvsystem.Array(), pvsystem.Array()], | ||
|
@@ -1409,6 +1449,7 @@ def test_PVSystem_sandia_multi(cec_inverter_parameters): | |
system.sandia_multi((vdcs, vdcs), (pdcs, pdcs, pdcs)) | ||
|
||
|
||
# remove after deprecation period for PVSystem.sandia_multi | ||
def test_PVSystem_sandia_multi_single_array(cec_inverter_parameters): | ||
system = pvsystem.PVSystem( | ||
arrays=[pvsystem.Array()], | ||
|
@@ -1431,6 +1472,84 @@ def test_PVSystem_sandia_multi_single_array(cec_inverter_parameters): | |
system.sandia_multi((vdcs,), (pdcs, pdcs)) | ||
|
||
|
||
def test_PVSystem_get_ac_pvwatts(pvwatts_system_defaults, mocker): | ||
mocker.spy(inverter, 'pvwatts') | ||
pdc = 50 | ||
out = pvwatts_system_defaults.get_ac('pvwatts', pdc) | ||
inverter.pvwatts.assert_called_once_with( | ||
pdc, **pvwatts_system_defaults.inverter_parameters) | ||
assert out < pdc | ||
|
||
|
||
def test_PVSystem_get_ac_pvwatts_kwargs(pvwatts_system_kwargs, mocker): | ||
mocker.spy(inverter, 'pvwatts') | ||
pdc = 50 | ||
out = pvwatts_system_kwargs.get_ac('pvwatts', pdc) | ||
inverter.pvwatts.assert_called_once_with( | ||
pdc, **pvwatts_system_kwargs.inverter_parameters) | ||
assert out < pdc | ||
|
||
|
||
def test_PVSystem_get_ac_pvwatts_multi( | ||
pvwatts_system_defaults, pvwatts_system_kwargs, mocker): | ||
mocker.spy(inverter, 'pvwatts_multi') | ||
expected = [pd.Series([0.0, 48.123524, 86.400000]), | ||
pd.Series([0.0, 45.893550, 85.500000])] | ||
systems = [pvwatts_system_defaults, pvwatts_system_kwargs] | ||
for base_sys, exp in zip(systems, expected): | ||
system = pvsystem.PVSystem( | ||
arrays=[pvsystem.Array(), pvsystem.Array()], | ||
inverter_parameters=base_sys.inverter_parameters, | ||
) | ||
pdcs = pd.Series([0., 25., 50.]) | ||
pacs = system.get_ac('pvwatts', (pdcs, pdcs)) | ||
assert_series_equal(pacs, exp) | ||
assert inverter.pvwatts_multi.call_count == 2 | ||
with pytest.raises(ValueError, | ||
match="Length mismatch for per-array parameter"): | ||
system.get_ac('pvwatts', (pdcs,)) | ||
with pytest.raises(ValueError, | ||
match="Length mismatch for per-array parameter"): | ||
system.get_ac('pvwatts', pdcs) | ||
with pytest.raises(ValueError, | ||
match="Length mismatch for per-array parameter"): | ||
system.get_ac('pvwatts', (pdcs, pdcs, pdcs)) | ||
|
||
|
||
def test_PVSystem_get_ac_adr(adr_inverter_parameters, mocker): | ||
mocker.spy(inverter, 'adr') | ||
system = pvsystem.PVSystem( | ||
inverter_parameters=adr_inverter_parameters, | ||
) | ||
vdcs = pd.Series([135, 154, 390, 420, 551]) | ||
pdcs = pd.Series([135, 1232, 1170, 420, 551]) | ||
pacs = system.get_ac('adr', pdcs, vdcs) | ||
assert_series_equal(pacs, pd.Series([np.nan, 1161.5745, 1116.4459, | ||
382.6679, np.nan])) | ||
inverter.adr.assert_called_once_with(vdcs, pdcs, | ||
system.inverter_parameters) | ||
|
||
|
||
def test_PVSystem_get_ac_adr_multi(adr_inverter_parameters): | ||
system = pvsystem.PVSystem( | ||
arrays=[pvsystem.Array(), pvsystem.Array()], | ||
inverter_parameters=adr_inverter_parameters, | ||
) | ||
pdcs = pd.Series([135, 1232, 1170, 420, 551]) | ||
with pytest.raises(ValueError, | ||
match="The adr inverter function cannot be used"): | ||
system.get_ac(model='adr', p_dc=pdcs) | ||
|
||
|
||
def test_PVSystem_get_ac_invalid(cec_inverter_parameters): | ||
system = pvsystem.PVSystem( | ||
inverter_parameters=cec_inverter_parameters, | ||
) | ||
pdcs = pd.Series(np.linspace(0, 50, 3)) | ||
with pytest.raises(ValueError, match="is not a valid AC power model"): | ||
system.get_ac(model='not_a_model', p_dc=pdcs) | ||
|
||
|
||
def test_PVSystem_creation(): | ||
pv_system = pvsystem.PVSystem(module='blah', inverter='blarg') | ||
# ensure that parameter attributes are dict-like. GH 294 | ||
|
@@ -1891,6 +2010,7 @@ def test_PVSystem_pvwatts_losses(pvwatts_system_defaults, mocker): | |
assert out < expected | ||
|
||
|
||
# remove after deprecation period for PVSystem.pvwatts_ac | ||
def test_PVSystem_pvwatts_ac(pvwatts_system_defaults, mocker): | ||
mocker.spy(inverter, 'pvwatts') | ||
pdc = 50 | ||
|
@@ -1900,6 +2020,7 @@ def test_PVSystem_pvwatts_ac(pvwatts_system_defaults, mocker): | |
assert out < pdc | ||
|
||
|
||
# remove after deprecation period for PVSystem.pvwatts_ac | ||
def test_PVSystem_pvwatts_ac_kwargs(pvwatts_system_kwargs, mocker): | ||
mocker.spy(inverter, 'pvwatts') | ||
pdc = 50 | ||
|
@@ -1909,6 +2030,7 @@ def test_PVSystem_pvwatts_ac_kwargs(pvwatts_system_kwargs, mocker): | |
assert out < pdc | ||
|
||
|
||
# remove after deprecation period for PVSystem.pvwatts_ac | ||
def test_PVSystem_pvwatts_multi(pvwatts_system_defaults, | ||
pvwatts_system_kwargs): | ||
expected = [pd.Series([0.0, 48.123524, 86.400000]), | ||
|
Uh oh!
There was an error while loading. Please reload this page.