Search code examples
pythonnumpyvectorizationeigenvalueabaqus

fastest way to get eigenvalues of many 1d array


I have a (n, m, 6)-array with n and m being more than 10.000. The 6 values are from a symmetric matrix in following order:

[[11, 12, 13], [12, 22, 23], [13, 23, 33]] => (11, 22, 33, 12, 23, 31)

What I want to calculate the eigenvalues and eigenvectors of every matrix. Right now it's implemented with 2 for-loops iterating each dimension, reordering the values into matrix form and calculating the eigenvalues. But I wonder if there is a much faster solution using vectorization?


Solution

  • Best way I've found is to use a (6,3,3) transform matrix to turn the symmetric values into a proper symmetric tensor.

    transf = np.array([[[1.,0.,0.],[0.,0.,0.],[0.,0.,0.]],                #11
                       [[0.,0.,0.],[0.,1.,0.],[0.,0.,0.]],                #22
                       [[0.,0.,0.],[0.,0.,0.],[0.,0.,1.]],                #33
                       [[0.,1.,0.],[1.,0.,0.],[0.,0.,0.]],                #12 & 21
                       [[0.,0.,1.],[0.,0.,0.],[1.,0.,0.]],                #13 & 31
                       [[0.,0.,0.],[0.,0.,1.],[0.,1.,0.]]]).swapaxes(0,1) #23 & 32
    
    e, v = np.linalg.eigh(input.dot(transf))
    

    NON-PROGRAMMING NOTE: Be careful about whether abaqus is outputting real stress/strain or engineering stress/strain, as the resulting transform is different (if I remember correctly for for "real strain" you need the off-diagonal terms to be 0.5 instead of 1.)