Skip to content

RuntimeWarning: invalid value encountered in divide when using singlediode() #2671

Description

@jwhitaker-gridcog

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)

To Reproduce

import pvlib
import numpy as np

pvlib.pvsystem.singlediode(0., 1e-12, 0.5, np.inf, 1.8)

Expected behavior
No warning.

Screenshots

Versions:

  • pvlib.__version__: 0.4.0
  • pandas.__version__: 2.3.
  • python: 3.12
  • numpy.__version__: 2.3.5
  • scipy.__version__: 1.17.0

Additional context

Poking a little bit, it looks like your call to scipy find_minimum may not obey the constraints they require. Scipy doco states (https://docs.scipy.org/doc/scipy-1.17.0/reference/generated/scipy.optimize.elementwise.find_minimum.html)

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...

Thanks!

Activity

  1. cwhanse commented on Jan 30, 2026

    @cwhanse
    Member

    Verified that the warning raises when v_oc = 0.. As for what to do about it, three options come to mind:

    1. 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.
    2. 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.
    3. 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.

  2. jwhitaker-gridcog commented on Jan 31, 2026

    @jwhitaker-gridcog
    Author

    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'?

  3. Blizzeq commented on Sep 22, 2026

    @Blizzeq

    I opened #2862 for this. It fixes the bracket passed to find_minimum when v_oc is 0 rather than suppressing the warning.

  4. added a commit that references this issue on Sep 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions