Replies: 2 comments 1 reply
-
|
here's another example: """
Making 2-diode modules from CEC in PVMismatch
"""
from matplotlib import pyplot as plt
import numpy as np
import pvlib
from pvmismatch import *
from pvmismatch.contrib import gen_coeffs
cecmod = pvlib.pvsystem.retrieve_sam('CECMod')
csmods = cecmod.columns[cecmod.T.index.str.startswith('Canadian')]
len(csmods) # 409 modules in CEC library!
cs6x_300m = cecmod[csmods[264]] # CS6X-300M Canadian Solar 300W mono-Si module
args = (
cs6x_300m.I_sc_ref,
cs6x_300m.V_oc_ref,
cs6x_300m.I_mp_ref,
cs6x_300m.V_mp_ref,
cs6x_300m.N_s, # number of series cells
1, # number of parallel sub-strings
25.0) # cell temperature
# try to solve using default coeffs
x, sol = gen_coeffs.gen_two_diode(*args)
# solver fails, so get the last guess before it quit
def last_guess(sol):
isat1 = np.exp(sol.x[0])
isat2 = np.exp(sol.x[1])
rs = sol.x[2] ** 2.0
rsh = sol.x[3] ** 2.0
return isat1, isat2, rs, rsh
x = last_guess(sol)
# the series and shunt resistance solver guess are way off, so reset them
# with something reasonable for a 2-diode model
x, sol = gen_coeffs.gen_two_diode(*args, x0=(x[0], x[1], 0.005, 10.0))
# Hooray, it worked! Note that the 1-diode and 2-diode parametres are so
# different! Anyway, let's make a cell and a module to check the solution.
pvc = pvcell.PVcell(
Isat1_T0=x[0],
Isat2_T0=x[1],
Rs=x[2],
Rsh=x[3],
Isc0_T0=cs6x_300m.I_sc_ref,
alpha_Isc=cs6x_300m.alpha_sc)
np.isclose(pvc.Isc, cs6x_300m.I_sc_ref) # ha-ha, this exact b/c we used it
# open circuit voltage within 1E-3: (45.01267251639085, 45.0)
np.isclose(pvc.Voc*cs6x_300m.N_s, cs6x_300m.V_oc_ref, rtol=1e-3, atol=1e-3)
# get index max power point
mpp = np.argmax(pvc.Pcell)
# max power voltage within 1E-3: (36.50580418834946, 36.5)
np.isclose(pvc.Vcell[mpp][0]*cs6x_300m.N_s, cs6x_300m.V_mp_ref, rtol=1e-3, atol=1e-3)
# max power current within 1E-3: (8.218687568902466, 8.22)
np.isclose(pvc.Icell[mpp][0], cs6x_300m.I_mp_ref, rtol=1e-3, atol=1e-3)
# use pvlib to get the full IV curve using CEC model
params1stc = pvlib.pvsystem.calcparams_cec(effective_irradiance=1000,
temp_cell=25.0, alpha_sc=cs6x_300m.alpha_sc, a_ref=cs6x_300m.a_ref,
I_L_ref=cs6x_300m.I_L_ref, I_o_ref=cs6x_300m.I_o_ref, R_sh_ref=cs6x_300m.R_sh_ref,
R_s=cs6x_300m.R_s, Adjust=cs6x_300m.Adjust)
iv_params1stc = pvlib.pvsystem.singlediode(*params1stc, ivcurve_pnts=100, method='newton')
# use pvmm to get full IV curve using 2-diode model parameters
pvm = pvmodule.PVmodule(cell_pos=pvmodule.STD72, pvcells=[pvc]*72)
# make some comparison plots
pvm.plotMod() # plot the pvmm module
plt.tight_layout()
# get axes for IV curve
f, ax = plt.gcf(), plt.gca()
ax0 = f.axes[0]
ax0.plot(iv_params1stc['v'], iv_params1stc['i'], '--')
ax0.plot(0, iv_params1stc['i_sc'], '|k')
ax0.plot(iv_params1stc['v_oc'], 0, '|k')
ax0.plot(iv_params1stc['v_mp'], iv_params1stc['i_mp'], '|k')
ax0.set_ylim([0, 10])
ax0.plot(0, pvm.Isc.mean(), '_k')
ax0.plot(pvm.Voc.sum(), 0, '|k')
mpp = np.argmax(pvm.Pmod)
ax0.plot(pvm.Vcell[mpp], mpp.Icell[mpp], '_k')
ax0.plot(pvm.Vmod[mpp], pvm.Imod[mpp], '_k')
iv_params1stc['p'] = iv_params1stc['v'] * iv_params1stc['i']
ax1.plot(iv_params1stc['v'], iv_params1stc['p'], '--')
ax1.plot(iv_params1stc['v_mp'], iv_params1stc['p_mp'], '|k')
ax1.plot(pvm.Vmod[mpp], pvm.Pmod[mpp], '_k') |
Beta Was this translation helpful? Give feedback.
-
|
I used the method of this code “def last_guess(sol): The final error is as follows: I didn't find the reason |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
-
Several folks have had convergence issues with
gen_coeffs, but there are some tricks that can help. Under the hood it just usesscipy.optimize.root, which depends strongly on the initial guess. It also has interesting criteria for exiting the solver. Therefore it's important to look at the solver message and the residuals to determine whyscipy.optimize.rootdecided to quit. Sometimes it's not making progress on the solution, but it actually has found a good fit in the least squares sense. The message in this case is usually:The solver solution shows the residuals in
sol.fun. So if the solver quits due to lack of good progress, and the values ofsol.funare all extremely small, that's probably the best solution you can get.Another trick I've found that seems to work sometimes is to restart the solver with the last guess. The 2-diode equations are "stiff" so often one of the guess "blows up" and needs to be reset to a reasonable value before continuing.
Take for example this Canadian Solar CS6X-300M module:
So to restart the solution we need the last guess, which was transformed to log-space and parabolic-space to help it solve better, b/c we expect
Isat1andIsat2to be positive and to change by an order of magnitude or more andRsandRshto be positive.So it's stll not making progress, and in fact there's almost no change from the last run other than the Jacobian is slightly different. we could run it again just in case
Okay, we found a solution that's pretty good actually, but just for fun, let's still see if we can do better? This is a totally random swag, but b/c the fill factor of the fit is slightly low, let's increase
Rshjust to see what happens?This time the solver iterated 500 times, the default max, but was still making good progress so start again!
Anyway there you have it; a few tricks to improve convergence:
sol.funand solver message,sol.messagesol.xand un-transform it to get the last guessPVcelland checkVoc,Icell[np.argmax(Pcell)],Vcell[np.argmax(Pcell)], and the fill factorBeta Was this translation helpful? Give feedback.
All reactions