Search code examples
pythontypesjitnumba

Typing error during njit compilation when providing explicit types with numba


I am trying to jit compile a function in python using "nopython" mode. The function compiles when I do not provide type information by simply using the @numba.njit decorator.

Here is the function definition with the decorator applied and typing information included:

from numba import njit, float64, int64

@njit(float64(float64, int64))
def PowerCurve(flow, head):
    if head==326:
        if flow<(10.788/3.03):  #speed no load approximation
            return 0
        else:
            return 3.03*flow - 10.788   #approximating power for each gross head using equation to avoid interpolation
    elif head==328:
        if flow<(10.939/3.0525):
            return 0
        else:
            return 3.0525*flow - 10.969
    elif head==330:
        if flow<(10.982/3.0683):
            return 0
        else:
            return 3.0683*flow - 10.982
    elif head==332:
        if flow<(11.006/3.0842):
            return 0
        else:
            return 3.0842*flow - 11.006
    elif head==334:
        if flow<(11.025/3.1001):
            return 0
        else:
            return 3.1001*flow - 11.025
    elif head==336:
        if flow<(11.043/3.116):
            return 0
        else:
            return 3.116*flow - 11.043
    elif head==338:
        if flow<(11.063/3.1317):
            return 0
        else:
            return 3.1317*flow - 11.063
    elif head==340:
        if flow<(11.086/3.1477):
            return 0
        else:
            return 3.1477*flow - 11.086
    elif head==342:
        if flow<(11.103/3.1636):
            return 0
        else:
            return 3.1636*flow - 11.103
    elif head==344:
        if flow<(11.135/3.1798):
            return 0
        else:
            return 3.1798*flow - 11.135
    elif head==346:
        if flow<(11.315/3.2021):
            return 0
        else:
            return 3.2021*flow - 11.315
    elif head==348:
        if flow<(11.344/3.2181):
            return 0
        else:
            return 3.2181*flow - 11.344

When I run this piece of code without calling the function I get the following error:

 Traceback (most recent call last):
  File "Optimize.py", line 516, in <module>
    @njit(float64(float64, int64))
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\decorators.py", line 199, in wrapper
    disp.compile(sig)
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\dispatcher.py", line 579, in compile
    cres = self._compiler.compile(args, return_type)
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\dispatcher.py", line 80, in compile
    flags=flags, locals=self.locals)
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\compiler.py", line 740, in compile_extra
    return pipeline.compile_extra(func)
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\compiler.py", line 360, in compile_extra
    return self._compile_bytecode()
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\compiler.py", line 699, in _compile_bytecode
    return self._compile_core()
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\compiler.py", line 686, in _compile_core
    res = pm.run(self.status)
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\compiler.py", line 246, in run
    raise patched_exception
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\compiler.py", line 238, in run
    stage()
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\compiler.py", line 452, in stage_nopython_frontend
    self.locals)
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\compiler.py", line 841, in type_inference_stage
    infer.propagate()
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\typeinfer.py", line 773, in propagate
    raise errors[0]
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\typeinfer.py", line 129, in propagate
    constraint(typeinfer)
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\typeinfer.py", line 154, in __call__
    typeinfer.copy_type(self.src, self.dst, loc=self.loc)
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\typeinfer.py", line 791, in copy_type
    unified = self.typevars[dest_var].union(self.typevars[src_var], loc=loc)
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\typeinfer.py", line 83, in union
    self.add_type(other.type, loc=loc)
  File "C:\Users\patri\Miniconda3\lib\site-packages\numba\typeinfer.py", line 47, in add_type
    loc=loc)
numba.errors.TypingError: Failed at nopython (nopython frontend)
No conversion from none to float64 for '$442.2', defined at None
File "Optimize.py", line 577
[1] During: typing of assignment at Optimize.py (577)

The line of the function that this error message is referring to includes this: return 3.2181*flow - 11.344. When I debugged this function I noticed that the value of flow at this line is None. Can anybody tell me what I'm doing wrong here and how typing information can be included?


Solution

  • Each Python function implicitly returns None if no final return is given. That's why it says No conversion from none to float64. Numba and Python can't be certain that you will always pass in a head that matches any of your branches and then it would return None. But with the signature you specified that it may only return float64s!

    In your case (if it wasn't an oversight) just include an return 0. after all the if and elif branches:

    ...
    elif head==348:
        if flow<(11.344/3.2181):
            return 0
        else:
            return 3.2181*flow - 11.344
    return 0