I am new to python/numpy. I need to do the following calculation: for an array of discrete times t, calculate $e^{At}$ for a $2\times 2$ matrix $A$
What I did:
def calculate(t_,x_0,v_0,omega_0,c):
# define A
a_11,a_12, a_21, a_22=0,1,-omega_0^2,-c
A =np.matrix([[a_11,a_12], [a_21, a_22]])
print A
# use vectorization
temps = np.array(t_)
A_ = np.array([A for k in range (1,n+1,1)])
temps*A_
x_=scipy.linalg.expm(temps*A)
v_=A*scipy.linalg.expm(temps*A)
return x_,v_
n=10
omega_0=1
c=1
x_0=1
v_0=1
t_ = [float(5*k*np.pi/n) for k in range (1,n+1,1)]
x_, v_ = calculate(t_,x_0,v_0,omega_0,c)
However, I get this error when multiplying A_ (array containing n times A ) and temps (containg the times for which I want to calculate exp(At) :
ValueError: operands could not be broadcast together with shapes (10,) (10,2,2)
As I understand vectorization, each element in A_ would be multiplied by element at the same index from temps; but I think i don't get it right. Any help/ comments much appreciated
This is what I would do.
No attempt at vectorization here. The
expm
function applies to one matrix at a time, and it surely takes the bulk of computation time. No need to worry about the cost of multiplying A by a scalar.A pure
numpy
calculation oft_
is (creates an array instead of a list):A_
isnp.ndarray
. I madeA
anp.ndarray
as well; yours isnp.matrix
, but yourA_
will still benp.ndarray
.np.matrix
can only be 2d, where asA_
is 3d.So
t * A
will be array elementwise multiplication, hence the broadcasting error,(10,) (10,2,2)
.To do that elementwise multiplication right you need something like
But if you want matrix multiplication of the (10,) with (10,2,2), then
einsum
does it easily:np.dot
can't do it because its rule is 'last with 2nd to last'.tensordot
can, but I'm more comfortable witheinsum
.But that
einsum
expression makes it obvious (to me) that I can get the same thing from the elementwise *, by summing on the 1st axis:Or
(t[:,None,None]*A[None,:,:]).cumsum(axis=0)
to get a 2x2 for each time.