I am using Numba to speed up a series of functions as shown below. if I set the step_size
variable in function PosMomentSingle
to a float (e.g. step_size = 0.5
), instead of an integer (e.g step_size = 1.0
), I get the following error:
Cannot unify array(float32, 1d, C) and array(float64, 1d, C) for 'axle_coords.2', defined at <ipython-input-182-37c789ca2187> (12)
File "<ipython-input-182-37c789ca2187>", line 12:
def nbSimpleSpanMoment(L, axles, spacings, step_size):
<source elided>
while np.min(axle_coords) < L:
I found it quite hard to understand what the problem is, but my guess is there is an issue with the function after @jit
(nbSimpleSpanMoment
), with some kind of a datatype mismatch. I tried setting all variables to float32, then to float64 (e.g. L = np.float32(L)
) but whatever I try creates a new set of errors. Since the error message is quite cryptic, I am unable to debug the issue. Can someone with numba experience explain what I am doing wrong here?
I placed my code below to recreate the problem.
Thank you for the help!
import numba as nb
import numpy as np
@nb.vectorize(nopython=True)
def nbvectMoment(L,x):
if x<L/2.0:
return 0.5*x
else:
return 0.5*(L-x)
@nb.jit(nopython=True)
def nbSimpleSpanMoment(L, axles, spacings, step_size):
travel = L + np.sum(spacings)
maxmoment = 0
axle_coords = -np.cumsum(spacings)
moment_inf = np.empty_like(axles)
while np.min(axle_coords) < L:
axle_coords = axle_coords + step_size
y = nbvectMoment(L,axle_coords)
for k in range(y.shape[0]):
if axle_coords[k] >=0 and axle_coords[k] <= L:
moment_inf[k] = y[k]
else:
moment_inf[k] = 0.0
moment = np.sum(moment_inf * axles)
if maxmoment < moment:
maxmoment = moment
return np.around(maxmoment,1)
def PosMomentSingle(current_axles, current_spacings):
data_list = []
for L in range (1,201):
L=float(L)
if L <= 40:
step_size = 0.5
else:
step_size = 0.5
axles = np.array(current_axles, dtype='f')
spacings = np.array(current_spacings, dtype='f')
axles_inv = axles[::-1]
spacings_inv = spacings[::-1]
spacings = np.insert(spacings,0,0)
spacings_inv = np.insert(spacings_inv,0,0)
left_to_right = nbSimpleSpanMoment(L, axles, spacings, step_size)
right_to_left = nbSimpleSpanMoment(L, axles_inv, spacings_inv, step_size)
data_list.append(max(left_to_right, right_to_left))
return data_list
load_effects = []
for v in range(14,31):
load_effects.append(PosMomentSingle([8, 32, 32], [14, v]))
load_effects = np.array(load_effects)
After removing all type conversions in your code, the following error was returned
TypingError: Cannot unify array(int64, 1d, C) and array(float64, 1d, C) for 'axle_coords.2'
This helped me to trace back the error to the dtype
of spacings
. In your code this initialized as a C compatible single
, which seems to be different from a python float32
, see here. After changing this to np.float64
the code now runs.
The code below now runs and unify error does not occur anymore.
import numba as nb
import numpy as np
@nb.vectorize(nopython=True)
def nbvectMoment(L,x):
if x<L/2.0:
return 0.5*x
else:
return 0.5*(L-x)
@nb.jit(nopython=True)
def nbSimpleSpanMoment(L, axles, spacings, step_size):
travel = L + np.sum(spacings)
maxmoment = 0
axle_coords = -np.cumsum(spacings)
moment_inf = np.empty_like(axles)
while np.min(axle_coords) < L:
axle_coords = axle_coords + step_size
y = nbvectMoment(L,axle_coords)
for k in range(y.shape[0]):
if axle_coords[k] >=0 and axle_coords[k] <= L:
moment_inf[k] = y[k]
else:
moment_inf[k] = 0.0
moment = np.sum(moment_inf * axles)
if maxmoment < moment:
maxmoment = moment
return np.around(maxmoment,1)
def PosMomentSingle(current_axles, current_spacings):
data_list = []
for L in range (1,201):
L=float(L)
if L <= 40:
step_size = 0.5
else:
step_size = 0.5
axles = np.array(current_axles, np.float32)
spacings = np.array(current_spacings, dtype=np.float64)
axles_inv = axles[::-1]
spacings_inv = spacings[::-1]
spacings = np.insert(spacings,0,0)
spacings_inv = np.insert(spacings_inv,0,0)
left_to_right = nbSimpleSpanMoment(L, axles, spacings, step_size)
right_to_left = nbSimpleSpanMoment(L, axles_inv, spacings_inv, step_size)
data_list.append(max(left_to_right, right_to_left))
return data_list
load_effects = []
for v in range(14,31):
load_effects.append(PosMomentSingle([8, 32, 32], [14, v]))
load_effects = np.array(load_effects)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With