forked from DuraMAT/pvpro
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
toddkarin
committed
Sep 10, 2021
1 parent
f038d39
commit fd56e51
Showing
2 changed files
with
226 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
""" | ||
Example for fitting the Desoto single diode model | ||
""" | ||
|
||
import numpy as np | ||
import pandas as pd | ||
from pvpro.fit import fit_singlediode_model | ||
import time | ||
from pvlib.pvsystem import calcparams_desoto, singlediode | ||
from pvlib.ivtools.sdm import fit_desoto_sandia | ||
from pickle import dump | ||
|
||
# Generate synthetic data. | ||
poa_list = np.linspace(200, 1000, 15) | ||
temperature_cell_list = np.linspace(15, 50, 9) | ||
|
||
specs = dict( | ||
alpha_sc=0.053 * 1e-2 * 8.6, | ||
cells_in_series=60, | ||
beta_voc=-0.351 * 1e-2 * 37.0 | ||
) | ||
np.random.seed(0) | ||
|
||
dfs = [] | ||
for rep in range(100): | ||
print(rep) | ||
|
||
module = dict(photocurrent_ref=float(5+5*np.random.rand(1)), | ||
saturation_current_ref=float(10**(-12+4*np.random.rand(1))), | ||
resistance_series_ref=float(0+0.7*np.random.rand(1)), | ||
resistance_shunt_ref=float(50+450*np.random.rand(1)), | ||
diode_factor=float(1.0+1.0*np.random.rand(1)), | ||
) | ||
Vth_ref = 1.381e-23 * (273.15 + 25) / 1.602e-19 | ||
module['nNsVth_ref'] = module['diode_factor'] * specs[ | ||
'cells_in_series'] * Vth_ref | ||
|
||
voltage = np.array([]) | ||
current = np.array([]) | ||
temperature_cell = np.array([]) | ||
poa = np.array([]) | ||
ivcurve_number = np.array([]) | ||
ivcurves = {'v': [], 'i': [], 'v_oc': [], 'ee': [], 'tc': [], 'v_oc': [], | ||
'v_mp': [], 'i_mp': [], 'i_sc': []} | ||
|
||
ivcurve_points = 50 | ||
n = 0 | ||
|
||
temperature_noise = 1 | ||
poa_noise = 0.02 | ||
for j in range(len(poa_list)): | ||
for k in range(len(temperature_cell_list)): | ||
|
||
poa_curr = float(poa_list[j] * np.random.normal(1,poa_noise,1)) | ||
tc_curr = float(temperature_cell_list[k] + np.random.normal(0, temperature_noise, 1)) | ||
IL, I0, Rs, Rsh, nNsVth = calcparams_desoto( | ||
effective_irradiance=poa_curr, | ||
temp_cell=tc_curr, | ||
alpha_sc=specs['alpha_sc'], | ||
a_ref=module['nNsVth_ref'], | ||
I_L_ref=module['photocurrent_ref'], | ||
I_o_ref=module['saturation_current_ref'], | ||
R_sh_ref=module['resistance_shunt_ref'], | ||
R_s=module['resistance_series_ref']) | ||
out = singlediode(IL, I0, Rs, Rsh, nNsVth, ivcurve_pnts=ivcurve_points) | ||
|
||
# Add random noise | ||
# out['i'] = out['i'] + 0.2 * (np.random.rand(len(out['i'])) - 0.5) | ||
|
||
voltage = np.append(voltage, out['v']) | ||
current = np.append(current, out['i']) | ||
temperature_cell = np.append(temperature_cell, | ||
np.repeat(temperature_cell_list[k], | ||
len(out['v']))) | ||
poa = np.append(poa, np.repeat(poa_list[j], len(out['v']))) | ||
ivcurve_number = np.append(ivcurve_number, np.repeat(n, len(out['v']))) | ||
|
||
ivcurves['v'].append(out['v']) | ||
ivcurves['i'].append(out['i']) | ||
ivcurves['v_oc'].append(out['v_oc']) | ||
ivcurves['i_sc'].append(out['i_sc']) | ||
ivcurves['v_mp'].append(out['v_mp']) | ||
ivcurves['i_mp'].append(out['i_mp']) | ||
ivcurves['tc'].append(temperature_cell_list[k]) | ||
ivcurves['ee'].append(poa_list[j]) | ||
|
||
n = n + 1 | ||
|
||
ivcurves.keys() | ||
for key in ['v_oc', 'ee', 'tc', 'v_mp', 'i_mp', 'i_sc']: | ||
ivcurves[key] = np.array(ivcurves[key]) | ||
|
||
# Inspect results. | ||
df = pd.DataFrame() | ||
|
||
# Perform fit using fit_desoto_lbl | ||
start_time = time.time() | ||
ret = fit_singlediode_model(voltage=voltage, | ||
current=current, | ||
temperature_cell=temperature_cell, | ||
poa=poa, | ||
cells_in_series=specs['cells_in_series'], | ||
alpha_isc=specs['alpha_sc'], | ||
linear_solver='lsq_linear', | ||
model='desoto', | ||
tol=1e-12, | ||
verbose=False) | ||
df.loc['fit_singlediode_model','evaluation_time'] = time.time() - start_time | ||
|
||
# Perform fit using fit_desoto_sandia | ||
start_time = time.time() | ||
retds = fit_desoto_sandia(ivcurves, specs=specs) | ||
df.loc['fit_desoto_sandia','evaluation_time'] = time.time() - start_time | ||
|
||
|
||
for key in ['photocurrent_ref', 'saturation_current_ref', | ||
'resistance_shunt_ref', 'resistance_series_ref', 'diode_factor', | ||
'nNsVth_ref']: | ||
df.loc['true', key] = module[key] | ||
df.loc['fit_singlediode_model', key] = ret[key] | ||
df.loc['fit_singlediode_model', 'conductance_shunt_ref'] = 1/ret['resistance_series_ref'] | ||
df.loc['true', 'conductance_shunt_ref'] = 1/module['resistance_shunt_ref'] | ||
|
||
df.loc['fit_desoto_sandia', 'photocurrent_ref'] = retds['I_L_ref'] | ||
df.loc['fit_desoto_sandia', 'saturation_current_ref'] = retds['I_o_ref'] | ||
df.loc['fit_desoto_sandia', 'resistance_shunt_ref'] = retds['R_sh_ref'] | ||
df.loc['fit_desoto_sandia', 'conductance_shunt_ref'] = 1/retds['R_sh_ref'] | ||
df.loc['fit_desoto_sandia', 'resistance_series_ref'] = retds['R_s'] | ||
df.loc['fit_desoto_sandia', 'nNsVth_ref'] = retds['a_ref'] | ||
df.loc['fit_desoto_sandia', 'diode_factor'] = retds['a_ref'] / ( | ||
specs['cells_in_series'] * Vth_ref) | ||
|
||
for model in df.index: | ||
out = singlediode(photocurrent=df.loc[model,'photocurrent_ref'], | ||
saturation_current=df.loc[model,'saturation_current_ref'], | ||
resistance_series=df.loc[model,'resistance_series_ref'], | ||
resistance_shunt=df.loc[model, 'resistance_shunt_ref'], | ||
nNsVth=df.loc[model, 'nNsVth_ref'] | ||
) | ||
for key in out: | ||
df.loc[model,key] = out[key] | ||
pd.set_option('display.float_format', lambda x: '%.2e' % x) | ||
|
||
|
||
df.loc[:, 'log_saturation_current_ref'] = np.log(df.loc[:, 'saturation_current_ref']) | ||
|
||
# print(df.transpose()) | ||
for model in ['fit_singlediode_model','fit_desoto_sandia']: | ||
df.loc[model + '_error',:] = np.abs((df.loc[model,:] - df.loc['true',:])/df.loc['true',:]) | ||
|
||
|
||
|
||
dfs.append(df) | ||
|
||
dump(dfs,open('data/test_fit_singlediode_model_multipoint_out.pkl', "wb" ) ) | ||
|
||
# | ||
# summary = pd.DataFrame() | ||
# for model in ['fit_singlediode_model_error','fit_desoto_sandia_error']: | ||
# for key in df.keys(): | ||
# values = [dfs[k].loc[model, key] for k in range(len(dfs))] | ||
# # summary.loc[model, key + '_mean_abs_fractional_error'] = np.mean(values) | ||
# # summary.loc[model, key + '_max_abs_fractional_error'] = np.max(values) | ||
# summary.loc[model, key + '_P90_abs_fractional_error'] = np.percentile(values,90) | ||
# | ||
# print(summary.transpose()) | ||
# | ||
# |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
""" | ||
Example for fitting the Desoto single diode model | ||
""" | ||
|
||
import numpy as np | ||
import pandas as pd | ||
from pvpro.fit import fit_singlediode_model | ||
import time | ||
from pvlib.pvsystem import calcparams_desoto, singlediode | ||
from pvlib.ivtools.sdm import fit_desoto_sandia | ||
from pickle import dump,load | ||
|
||
|
||
dfs = load(open('data/test_fit_singlediode_model_multipoint_out.pkl', "rb" ) ) | ||
|
||
|
||
summary = pd.DataFrame() | ||
for model in ['fit_singlediode_model_error','fit_desoto_sandia_error']: | ||
for key in dfs[0].keys(): | ||
values = [dfs[k].loc[model, key] for k in range(len(dfs))] | ||
# summary.loc[model, key + '_mean_abs_fractional_error'] = np.mean(values) | ||
# summary.loc[model, key + '_max_abs_fractional_error'] = np.max(values) | ||
summary.loc[key + '_P90_abs_percent_error',model] = np.percentile(values,90) | ||
# summary.loc[key + '_dev_of_error', model] = np.std(values - np.mean(values)) | ||
|
||
|
||
values = [dfs[k].loc['fit_desoto_sandia', 'evaluation_time']/dfs[k].loc['fit_singlediode_model', 'evaluation_time'] for k in range(len(dfs))] | ||
# summary.loc[model, key + '_mean_abs_fractional_error'] = np.mean(values) | ||
# summary.loc[model, key + '_max_abs_fractional_error'] = np.max(values) | ||
summary.loc['median_speedup','fit_singlediode_model_error'] = np.percentile(values,50) | ||
|
||
|
||
# summary.loc['P90 Percent Error',:] = summary.keys() | ||
print(summary[['fit_singlediode_model_error','fit_desoto_sandia_error']]) | ||
|
||
|
||
summary.index | ||
|
||
idx_out = [ | ||
'photocurrent_ref_P90_abs_percent_error', | ||
'log_saturation_current_ref_P90_abs_percent_error', | ||
'diode_factor_P90_abs_percent_error', | ||
# 'saturation_current_ref_P90_abs_percent_error', | ||
'resistance_series_ref_P90_abs_percent_error', | ||
'resistance_shunt_ref_P90_abs_percent_error', | ||
# 'nNsVth_ref_P90_abs_percent_error', | ||
# 'conductance_shunt_ref_P90_abs_percent_error', | ||
'i_sc_P90_abs_percent_error', 'v_oc_P90_abs_percent_error', | ||
'i_mp_P90_abs_percent_error', 'v_mp_P90_abs_percent_error', | ||
'p_mp_P90_abs_percent_error', | ||
# 'i_x_P90_abs_percent_error', | ||
# 'i_xx_P90_abs_percent_error', | ||
] | ||
|
||
with open('test_fit_table.tex','w') as f: | ||
f.write(summary.loc[idx_out].to_latex(float_format='{:.2%}'.format).replace('\_',' ')) |