-
Notifications
You must be signed in to change notification settings - Fork 1.1k
port pvl_adrinverter #288
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
port pvl_adrinverter #288
Changes from 7 commits
5de8bb7
745b8db
3861cbe
6b2a3ee
c796e75
9f94353
a08c873
07f3b1c
18ec0ea
a850c3d
5e03946
8406263
91bb7fa
eee4a7d
7b7e3ee
e21ac2e
0a6f142
716fed0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -462,6 +462,9 @@ def snlinverter(self, v_dc, p_dc): | |
""" | ||
return snlinverter(v_dc, p_dc, self.inverter_parameters) | ||
|
||
def adrinverter(self, v_dc, p_dc): | ||
return adrinverter(v_dc, p_dc, self.inverter_parameters) | ||
|
||
def scale_voltage_current_power(self, data): | ||
""" | ||
Scales the voltage, current, and power of the DataFrames | ||
|
@@ -1056,6 +1059,7 @@ def retrieve_sam(name=None, path=None): | |
* CEC module database | ||
* Sandia Module database | ||
* CEC Inverter database | ||
* Anton Driesse Inverter database | ||
|
||
and return it as a pandas DataFrame. | ||
|
||
|
@@ -1070,6 +1074,7 @@ def retrieve_sam(name=None, path=None): | |
(CEC is only current inverter db available; tag kept for | ||
backwards compatibility) | ||
* 'SandiaMod' - returns the Sandia Module database | ||
* 'ADRInverter' - returns the ADR Inverter database | ||
|
||
path : None or string | ||
Path to the SAM file. May also be a URL. | ||
|
@@ -1122,6 +1127,8 @@ def retrieve_sam(name=None, path=None): | |
elif name == 'sandiamod': | ||
csvdata = os.path.join( | ||
data_path, 'sam-library-sandia-modules-2015-6-30.csv') | ||
elif name == 'adrinverter': | ||
csvdata = os.path.join(data_path, 'adr-library.csv') | ||
elif name in ['cecinverter', 'sandiainverter']: | ||
# Allowing either, to provide for old code, | ||
# while aligning with current expectations | ||
|
@@ -1171,6 +1178,13 @@ def _parse_raw_sam_df(csvdata): | |
|
||
df.index = parsedindex | ||
df = df.transpose() | ||
if 'ADRCoefficients' in df.index: | ||
ad_ce = 'ADRCoefficients' | ||
# for each inverter, parses a string of coefficients like | ||
# ' 1.33, 2.11, 3.12' into a list containing floats: | ||
# [1.33, 2.11, 3.12] | ||
df.loc[ad_ce] = df.loc[ad_ce].map(lambda x: list( | ||
map(float, x.strip(' []').split()))) | ||
|
||
return df | ||
|
||
|
@@ -2037,6 +2051,108 @@ def snlinverter(v_dc, p_dc, inverter): | |
return ac_power | ||
|
||
|
||
def adrinverter(v_dc, p_dc, inverter): | ||
r''' | ||
Converts DC power and voltage to AC power using Anton Driesse's | ||
Grid-Connected PV Inverter efficiency model | ||
|
||
Parameters | ||
---------- | ||
v_dc : numeric | ||
A scalar or pandas series of DC voltages, in volts, which are provided | ||
as input to the inverter. If Vdc and Pdc are vectors, they must be | ||
of the same size. v_dc must be >= 0. (V) | ||
|
||
p_dc : numeric | ||
A scalar or pandas series of DC powers, in watts, which are provided | ||
as input to the inverter. If Vdc and Pdc are vectors, they must be | ||
of the same size. p_dc must be >= 0. (W) | ||
|
||
inverter : dict-like | ||
A dict-like object defining the inverter to be used, giving the | ||
inverter performance parameters according to the model | ||
developed by Anton Driesse [1]. | ||
A set of inverter performance parameters may be loaded from the | ||
supplied data table using retrievesam. | ||
See Notes for required keys. | ||
|
||
Returns | ||
------- | ||
ac_power : numeric | ||
A numpy array or pandas series of modeled AC power output given the | ||
input DC voltage, v_dc, and input DC power, p_dc. When ac_power would | ||
be greater than pac_max, it is set to p_max to represent inverter | ||
"clipping". When ac_power would be less than -p_nt (energy consumed | ||
rather than produced) then ac_power is set to -p_nt to represent | ||
nightly power losses. ac_power is not adjusted for maximum power point | ||
tracking (MPPT) voltage windows or maximum current limits of the | ||
inverter. | ||
|
||
Notes | ||
----- | ||
|
||
Required inverter keys are: | ||
|
||
====== ============================================================ | ||
Column Description | ||
====== ============================================================ | ||
p_nom The nominal power value used to normalize all power values, | ||
typically the DC power needed to produce maximum AC power output, | ||
(W). | ||
|
||
v_nom The nominal DC voltage value used to normalize DC voltage values, | ||
typically the level at which the highest efficiency is achieved, | ||
(V). | ||
|
||
pac_max The maximum AC output power value, used to clip the output if | ||
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.
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. should the column header be longer or the variables shorter? 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. A longer Column header by one = sign. You'll also need to add one space between all of the Column and the Description sections so that the table stays properly formatted. I guess you should probably also make the Description header longer and/or make the text fit within the existing Description header. I'm pretty sure that Sphinx would build the table in its present form and spit out a warning. It's not a big deal if it's just one table, but every silly warning makes it slightly harder to identify other issues with the documentation. If you actually build the docs and don't see a warning then we can ignore all this. |
||
needed, (W). | ||
|
||
ce_list This is a list of 9 coefficients that capture the influence | ||
of input voltage and power on inverter losses, and thereby | ||
efficiency. | ||
|
||
p_nt ac-power consumed by inverter at night (night tare) to maintain | ||
circuitry required to sense PV array voltage, (W). | ||
====== ============================================================ | ||
|
||
References | ||
---------- | ||
[1] Beyond the Curves: Modeling the Electrical Efficiency | ||
of Photovoltaic Inverters, PVSC 2008, Anton Driesse et. al. | ||
|
||
See also | ||
-------- | ||
sapm | ||
singlediode | ||
''' | ||
|
||
p_nom = inverter['Pnom'] | ||
v_nom = inverter['Vnom'] | ||
pac_max = inverter['Pacmax'] | ||
p_nt = inverter['Pnt'] | ||
ce_list = inverter['ADRCoefficients'] | ||
|
||
pdc = p_dc/p_nom | ||
vdc = v_dc/v_nom | ||
poly = np.array([pdc**0, pdc, pdc**2, vdc-1, pdc*(vdc-1), | ||
pdc**2*(vdc-1), 1/vdc-1, pdc*(1./vdc-1), | ||
pdc**2*(1./vdc-1)]) | ||
|
||
p_loss = np.dot(np.array(ce_list), poly) | ||
ac_power = p_nom * (pdc-p_loss) | ||
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. the name "ac_power" seems to be breaking the naming pattern... |
||
|
||
p_nt = -1*np.absolute(p_nt) | ||
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. Earlier versions of the cec/sam/sandia database were not consistent: most inverters had positive p_nt but many were negative. The latest sam database I looked at had only positve values. 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. so 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. That was just background info. The absolute() shouldn't be needed, but makes it more robust. |
||
|
||
ac_power = np.where((ac_power < p_nt) | (vdc == 0), p_nt, ac_power) | ||
|
||
ac_power = np.where(ac_power > pac_max, pac_max, ac_power) | ||
|
||
if isinstance(p_dc, pd.Series): | ||
ac_power = pd.Series(ac_power, index=pdc.index) | ||
|
||
return ac_power | ||
|
||
|
||
def scale_voltage_current_power(data, voltage=1, current=1): | ||
""" | ||
Scales the voltage, current, and power of the DataFrames | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,8 +33,8 @@ def cec_dc_snl_ac_system(sam_data): | |
module_parameters['b'] = 0.05 | ||
module_parameters['EgRef'] = 1.121 | ||
module_parameters['dEgdT'] = -0.0002677 | ||
inverters = sam_data['cecinverter'] | ||
inverter = inverters['ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_'].copy() | ||
inverters = sam_data['adrinverter'] | ||
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. maybe I'm forgetting something, but don't we want a new test here instead of changing the existing test? 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. on a second read, maybe this is ok because all of the methods are still being tested in some way. Is that right? 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. Yea they are, I think the coverage is the same- this was something I was debating as well. 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. ok with me to leave it alone then 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'm only now realizing that this change to the 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. good catch |
||
inverter = inverters['Zigor__Sunzet_3_TL_US_240V__CEC_2011_'].copy() | ||
system = PVSystem(module_parameters=module_parameters, | ||
inverter_parameters=inverter) | ||
return system | ||
|
@@ -173,7 +173,7 @@ def poadc(mc): | |
@requires_scipy | ||
@pytest.mark.parametrize('dc_model, expected', [ | ||
('sapm', [181.604438144, -2.00000000e-02]), | ||
('singlediode', [181.044109596, -2.00000000e-02]), | ||
('singlediode', [154.61940956, -25.00000000e-02]), | ||
('pvwatts', [190.028186986, 0]), | ||
(poadc, [189.183065667, 0]) # user supplied function | ||
]) | ||
|
@@ -201,8 +201,7 @@ def acdc(mc): | |
@requires_scipy | ||
@pytest.mark.parametrize('ac_model, expected', [ | ||
('snlinverter', [181.604438144, -2.00000000e-02]), | ||
pytest.mark.xfail(raises=NotImplementedError) | ||
(('adrinverter', [179.7178188, -2.00000000e-02])), | ||
('adrinverter', [154.61940956, -25.00000000e-02]), | ||
('pvwatts', [190.028186986, 0]), | ||
(acdc, [199.845296258, 0]) # user supplied function | ||
]) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -139,6 +139,7 @@ def sam_data(): | |
data['cecmod'] = pvsystem.retrieve_sam('cecmod') | ||
data['sandiamod'] = pvsystem.retrieve_sam('sandiamod') | ||
data['cecinverter'] = pvsystem.retrieve_sam('cecinverter') | ||
data['adrinverter'] = pvsystem.retrieve_sam('adrinverter') | ||
return data | ||
|
||
|
||
|
@@ -577,6 +578,16 @@ def test_snlinverter(sam_data): | |
pacs = pvsystem.snlinverter(vdcs, pdcs, inverters[testinv]) | ||
assert_series_equal(pacs, pd.Series([-0.020000, 132.004308, 250.000000])) | ||
|
||
def test_adrinverter(sam_data): | ||
inverters = sam_data['adrinverter'] | ||
testinv = 'Zigor__Sunzet_3_TL_US_240V__CEC_2011_' | ||
vdcs = pd.Series(np.linspace(0,50,3)) | ||
idcs = pd.Series(np.linspace(0,11,3)) | ||
pdcs = idcs * vdcs | ||
|
||
pacs = pvsystem.adrinverter(vdcs, pdcs, inverters[testinv]) | ||
assert_series_equal(pacs, pd.Series([-0.25000, 105.635043, 503.769061])) | ||
|
||
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. This test may catch some types of future bugs, but it's not a good PV example. The current, voltage and power ranges are way too small for this Zigor model inverter. Another idea might be to use some voltage and current combinations found in the pdf file on the CEC/gosolar website and look for the results of the model to be approxiamtely equal. |
||
|
||
def test_PVSystem_snlinverter(sam_data): | ||
inverters = sam_data['cecinverter'] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameters in this particular file were generated using the CEC efficiency measurements available to me as of 2013-10. It might be good to add the date suffix. I'm looking into doing an update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok I will add a date suffix