You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
RuntimeWarning: invalid value encountered in divide when using singlediode() #2671
Describe the bug
Since version 0.14, calling singediode() sometimes results in
/home/jarrad/src/.../.venv/lib/python3.12/site-packages/scipy/optimize/_chandrupatla.py:437: RuntimeWarning: invalid value encountered in divide
C = A / (A + B)
init:
The abscissae of a standard scalar minimization bracket. A bracket is valid if arrays x1, x2, x3 = init satisfy x1 < x2 < x3 and func(x1) >= func(x2) <= func(x3), where one of the inequalities is strict. Arrays must be broadcastable with one another and the arrays of args.
Looking at the PR where this was implemented, it looks like care was taken to obey the second invariant, but the first might have gotten missed. When you set init = (-1, 0.8*v_oc, v_oc), if v_oc == 0 then x2 < x3 gets broken. I haven't proven that this is the cause of the warning, but I am suspicious...
Verified that the warning raises when v_oc = 0.. As for what to do about it, three options come to mind:
ignore it with no action. I'd like to think v_oc = 0 is operationally irrelevant, but perhaps it's a common irritant to have the warning raised.
wrap the call to find_minimum with with np.errstate(divide='ignore') I'm on the fence here, I'd hate to unintentionally cover up some bug we want to detect. But I think the risk of hiding a bug is small. Division by zero would happen in the optimized function, which uses singlediode._lambertw_i_from_v. There's plenty of divisions in that function, but all the calculations are simple arithmetic, or handled by scipy's lambertw.
change to init = (-1., 0.8*v_oc - 0.2, v_oc). 0.8*v_oc - 0.2 is the point that is 80% of the distance along the interval (-1., v_oc) and that should be safe even for v_oc <= 0.
We don't want to add a small positive number to v_oc, e.g., init = (-1., 0.8*v_oc, v_oc + 1e-10) that could return positive voltages for v_mp.
I'll note that the current function returns a reasonable result despite the division by 0 warning.
thanks for looking into it. fwiw the breaking of scipy's invariants worried me more than the warning - it might work now on the couple of situations we poked at, but what if they update and do some optimization that doesn't work anymore when this req isn't met? or even if they just add input validation? what happens if a user wants to run with numpy in a strict mode with divide='raise'?
I again (#2571 (comment)) find myself leaning towards skipping the optimization entirely for this degenerate v_oc=0 case. It would be nice to be able to cleanly route all cases through scipy, but to me it seems like the required contortions are not any cleaner than a simple masking alternative.
Skipping the optimization based on input conditions (e.g., photocurrent < 1e-15 or similar) is preferable to covering up the effects by something like "if v_oc small then v_mp = 0"
Activity
cwhanse commentedon Jan 30, 2026
Verified that the warning raises when
v_oc = 0.. As for what to do about it, three options come to mind:v_oc = 0is operationally irrelevant, but perhaps it's a common irritant to have the warning raised.find_minimumwithwith np.errstate(divide='ignore')I'm on the fence here, I'd hate to unintentionally cover up some bug we want to detect. But I think the risk of hiding a bug is small. Division by zero would happen in the optimized function, which usessinglediode._lambertw_i_from_v. There's plenty of divisions in that function, but all the calculations are simple arithmetic, or handled by scipy'slambertw.init = (-1., 0.8*v_oc - 0.2, v_oc).0.8*v_oc - 0.2is the point that is 80% of the distance along the interval (-1., v_oc) and that should be safe even for v_oc <= 0.We don't want to add a small positive number to
v_oc, e.g.,init = (-1., 0.8*v_oc, v_oc + 1e-10)that could return positive voltages for v_mp.I'll note that the current function returns a reasonable result despite the division by 0 warning.
jwhitaker-gridcog commentedon Jan 31, 2026
thanks for looking into it. fwiw the breaking of scipy's invariants worried me more than the warning - it might work now on the couple of situations we poked at, but what if they update and do some optimization that doesn't work anymore when this req isn't met? or even if they just add input validation? what happens if a user wants to run with numpy in a strict mode with divide='raise'?
Blizzeq commentedon Sep 22, 2026
I opened #2862 for this. It fixes the bracket passed to
find_minimumwhenv_ocis 0 rather than suppressing the warning.Move whatsnew entry to v0.16.2
kandersolar commentedon Oct 15, 2026
I again (#2571 (comment)) find myself leaning towards skipping the optimization entirely for this degenerate
v_oc=0case. It would be nice to be able to cleanly route all cases through scipy, but to me it seems like the required contortions are not any cleaner than a simple masking alternative.cwhanse commentedon Oct 15, 2026
Skipping the optimization based on input conditions (e.g., photocurrent < 1e-15 or similar) is preferable to covering up the effects by something like "if v_oc small then v_mp = 0"