Vectorized-oriented definition of functions (Python)

Question:

I want to integrate a function using quadpy. I noticed that quadpy passes numpy arrays as arguments to the function. For example, if I define f = lambda x: x**2, then quadpy will integrate passing a vector like x = [0, 0.3, 0.7, 1].

The function I want to integrate is long (300 lines of code) and when I coded it I was thinking in passing two real numbers as arguments, not vectors. Now that I want to integrate or plot, it seems very important that my function can handle vectors. Which methods or tricks do you know to vectorize a function? numpy.vectorize does not seem to work in every case.

In my case, one of the problems is:

def f(t):
   U = np.array([[1, 0,          0        ],
                 [0, np.cos(t),  np.sin(t)],
                 [0, -np.sin(t), np.cos(t)]])
   V = np.array([[np.cos(t),  0,  np.sin(t)],
                 [0,          1,  0        ],
                 [-np.sin(t), 0, np.cos(t)]])

   return U @ V

When I run the code, quadpy replaces, say, np.cos(t) by an array, so the system throws an error telling me that I should specify ‘dtype=object’, and then the program collapses when it tries to operate U @ V over vectors.

How can I deal with these kind of problems? Other problem is that I multiply, say, constant(t)*vector(l),
so the constant becomes a vector, vector(l) becomes an array of arrays, and the system starts to complain again. Should I always define my functions bearing vectorization in mind?

Asked By: user90189

||

Answers:

Check https://github.com/sigma-py/quadpy/wiki/Dimensionality-of-input-and-output-arrays on what the dimensions of the input array mean, and how to construct an output array.

Answered By: Nico Schlömer

I want to show how I vectorized the function I posted. I refactored it as:

def f(t):
   ones = np.ones(t.shape)
   U = np.array([[ones,   0*ones,     0*ones   ],
                 [0*ones, np.cos(t),  np.sin(t)],
                 [0*ones, -np.sin(t), np.cos(t)]])
   V = np.array([[np.cos(t),  0*ones, np.sin(t)],
                 [0*ones,     ones,   0*ones   ],
                 [-np.sin(t), 0,      np.cos(t)]])
   U_theta = np.moveaxis(U_theta, [0, 1], [-2, -1])
   V_phi = np.moveaxis(V_phi, [0, 1], [-2, -1])

   return U @ V
Answered By: user90189