How to map a function over numpy array

I would like to be able to apply a generic function on either scalars numpy 1-D arrays, o numpy 2-D arrays. The example in point is

def stress2d_lefm_cyl(KI, r, qdeg) :
    """Compute stresses in Mode I around a 2D crack, according to LEFM
    q should be input in degrees"""
    sfactor = KI / sqrt(2*pi*r)
    q = radians(qdeg)
    q12 = q/2;        q32 = 3*q/2;
    sq12 = sin(q12);  cq12 = cos(q12);
    sq32 = sin(q32);  cq32 = cos(q32);
    af11 = cq12 * (1 - sq12*sq32);  af22 = cq12 * (1 + sq12*sq32);
    af12 = cq12 * sq12 * cq32
    return sfactor * np.array([af11, af22, af12])

def stress2d_lefm_rect(KI, x, y) :
    """Compute stresses in Mode I around a 2D crack, according to LEFM
    """
    r = sqrt(x**2+y**2)   <-- Error line
    q = atan2(y, x)
    return stress2d_lefm_cyl(KI, r, degrees(q))

delta = 0.5
x = np.arange(-10.0, 10.01, delta)
y = np.arange(0.0, 10.01, delta)
X, Y = np.meshgrid(x, y)
KI = 1
# I want to pass a scalar KI, and either scalar, 1D, or 2D arrays for X,Y (of the same shape, of course)
Z = stress2d_lefm_rect(KI, X, Y)

TypeError: only size-1 arrays can be converted to Python scalars

(I mean to use this for a contour plot). If I now change to

def stress2d_lefm_rect(KI, x, y) :
    """Compute stresses in Mode I around a 2D crack, according to LEFM
    """
    r = lambda x,y: x**2 + y**2   <-- Now this works
    q = lambda x,y: atan2(y, x)   <-- Error line
    return stress2d_lefm_cyl(KI, r(x,y), degrees(q(x,y)))
Z = stress2d_lefm_rect(KI, X, Y)

TypeError: only size-1 arrays can be converted to Python scalars

which boils down to

x = np.array([1.0, 2, 3, 4, 5])
h = lambda x,y: atan2(y,x)  <-- Error
print(h(0,1))   <-- Works
print(h(x, x))  <-- Error

1.5707963267948966

TypeError: only size-1 arrays can be converted to Python scalars

A "similar" question was posted, Most efficient way to map function over numpy array The differences are: 1. I have to (or possibly more) arguments (x,y), which should have the same shape. 2. I am combining also with a scalar argument (KI). 3. atan2 seems to be less "tolerant" than **2. I mean to work with a generic function. 4. I am chaining two functions.

Can this be worked out? Perhaps point 2 can be overcome by multiplying the result somewhere else.

Upvotes: 0

Views: 195

Answers (1)

dalyds
dalyds

Reputation: 76

You should use numpy to apply your function to every element of an array.

Ex :

import numpy as np
np.sqrt(np.square(x) + np.square(y))

Upvotes: 4

Related Questions