Efficient extraction of eigenvalues from a list of tensors
When you manipulate FEM results you generally have either a: * scalar field, * vector field, * tensor field.
With tensorial results, it is often useful to extract the eigenvalues in order to find the principal values.
I have found that it is easier to store the components of the tensors in a 6 column pandas dataframe (because of the symmetric property of stress and strain tensors)
import pandas as pd
node = [1001, 1002, 1003, 1004] #when dealing with FEM results you should remember at which element/node the result is computed (in the example, let's assume that we look at node from 1001 to 1004)
tensor1= [1,1,1,0,0,0] #eigen : 1
tensor2= [4,-1,0,2,2,1] #eigen : 5.58443, -1.77931, -0.805118
tensor3= [1,6,5,3,3,1] #eigen : 8.85036, 4.46542, -1.31577
tensor4= [1,2,3,0,0,0] #eigen : 1, 2, 3
df = pd.DataFrame([tensor1, tensor2, tensor3, tensor4], columns=["XX","YY","ZZ","XY","XZ","YZ"])
df.index = node
df
XX | YY | ZZ | XY | XZ | YZ | |
---|---|---|---|---|---|---|
1001 | 1 | 1 | 1 | 0 | 0 | 0 |
1002 | 4 | -1 | 0 | 2 | 2 | 1 |
1003 | 1 | 6 | 5 | 3 | 3 | 1 |
1004 | 1 | 2 | 3 | 0 | 0 | 0 |
If you want to extract the eigenvalues of a tensor with numpy you have to pass a n by n ndarray to the eigenvalue function. In order to avoid having to loop over each node, this oneliner is highly optimized and will help you invert a large number of tensors efficiently.
The steps are basically, create a list of n by n values (here n=3) in the right order => reshape it to a list of tensors => pass it to the eigenvals function
import numpy as np
from numpy import linalg as LA
eigenvals = LA.eigvals(df[["XX","XY","XZ","XY","YY","YZ","XZ","YZ","ZZ"]].values.reshape(len(df),3,3))
eigenvals
array([[ 1. , 1. , 1. ],
[ 5.58442834, -0.80511809, -1.77931025],
[-1.31577211, 8.85035616, 4.46541595],
[ 1. , 2. , 3. ]])