0

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.

2
  • 1
    math.tan only works with scalar values. np.tan works with array inputs. Commented Dec 17, 2019 at 15:55
  • 1
    You really just need to use numpy functions and it will all work out as expected. Maybe use this? docs.scipy.org/doc/numpy/reference/generated/numpy.arctan2.html Commented Dec 17, 2019 at 15:55

1 Answer 1

4

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

Sign up to request clarification or add additional context in comments.

4 Comments

Similarly, you can use np.arctan2(y,x) but x and y should have the same shape, which is not your case.
As a side note, r is equal to eucildean distance in your case, so you can use : from scipy.spatial.distance import euclidean; euclidean(x,y)
Yes, I had to use np.arctan2. My arrays were ok, both the same shape.
Note: I didn't need np.square, **2 worked fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.