Closed
Description
PR #190 replaced a numerical solution for v_oc with an analytical solution. @cwhanse warned that the analytical solution is prone to numerical overflow for modules with large Voc. Cliff's suggested test passed, though, so I figured that we were in good shape and the difference could be attributed to something about Python vs. Matlab. Well, I found a situation where the analytical solution does fail...
In [76]: module_parameters = modules['Canadian_Solar_CS5P_220M'].copy()
...: module_parameters['EgRef'] = 1.121
...: module_parameters['dEgdT'] = -0.0002677
In [77]: IL, I0, Rs, Rsh, nNsVth = pvlib.pvsystem.calcparams_desoto(1000, 30, module_parameters['alpha_sc'], module_parameters, module_parameters['EgRef'], module_parameters['dEgdT'])
In [78]: IL, I0, Rs, Rsh, nNsVth
Out[78]: (5.1366949999999996, 1.8739027472625636e-09, 1.065, 381.68, 2.681527737715915)
In [79]: I = 0
# the line in v_from_i that fails
In [80]: I0 * Rsh / nNsVth * np.exp(Rsh * (-I + IL + I0) / nNsVth)
Out[80]: inf
Following pvlib matlab's v_from_i, we can calculate the lambertw term in log space...
In [81]: logargW = (np.log(I0) + np.log(Rsh) - np.log(nNsVth) +
...: Rsh * (-I + IL + I0) / nNsVth)
In [82]: w = logargW
...: for i in range(0, 3):
...: w = w * (1 - np.log(w) + logargW) / (1 + w)
...: lambertwterm_log = w
...:
In [83]: lambertwterm_log
Out[83]: 709.43905979862768
I'll put this in a PR soon.