eigenvalues is more specific name than principal components

This commit is contained in:
Martin Diehl 2020-02-15 13:56:15 +01:00
parent a8e2ee0a86
commit 79533b075e
2 changed files with 107 additions and 54 deletions

View File

@ -37,7 +37,7 @@ def PK2(F,P):
S = np.dot(np.linalg.inv(F),P)
else:
S = np.einsum('ijk,ikl->ijl',np.linalg.inv(F),P)
return S
return symmetric(S)
def strain_tensor(F,t,m):
@ -168,27 +168,41 @@ def maximum_shear(x):
Symmetric tensor of which the maximum shear is computed.
"""
w = np.linalg.eigvalsh(symmetric(x)) # eigenvalues in ascending order
return (w[2] - w[0])*0.5 if np.shape(x) == (3,3) else \
(w[:,2] - w[:,0])*0.5
w = eigenvalues(x)
return (w[0] - w[2])*0.5 if np.shape(x) == (3,3) else \
(w[:,0] - w[:,2])*0.5
def principal_components(x):
def eigenvalues(x):
"""
Return the principal components of a symmetric tensor.
Return the eigenvalues, i.e. principal components, of a symmetric tensor.
The principal components (eigenvalues) are sorted in descending order, each repeated according to
The eigenvalues are sorted in ascending order, each repeated according to
its multiplicity.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Symmetric tensor of which the principal compontents are computed.
Symmetric tensor of which the eigenvalues are computed.
"""
w = np.linalg.eigvalsh(symmetric(x)) # eigenvalues in ascending order
return w[::-1] if np.shape(x) == (3,3) else \
w[:,::-1]
return np.linalg.eigvalsh(symmetric(x))
def eigenvectors(x):
"""
Return eigenvectors of a symmetric tensor.
The eigenvalues are sorted in ascending order of their associated eigenvalues.
Parameters
----------
x : numpy.array of shape (:,3,3) or (3,3)
Symmetric tensor of which the eigenvectors are computed.
"""
(u,v) = np.linalg.eigh(symmetric(x))
return v
def transpose(x):

View File

@ -58,10 +58,23 @@ class TestMechanics:
mechanics.maximum_shear(x[self.c]))
def test_vectorize_principal_components(self):
def test_vectorize_eigenvalues(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.principal_components(x)[self.c],
mechanics.principal_components(x[self.c]))
assert np.allclose(mechanics.eigenvalues(x)[self.c],
mechanics.eigenvalues(x[self.c]))
def test_vectorize_eigenvectors(self):
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.eigenvectors(x)[self.c],
mechanics.eigenvectors(x[self.c]))
def test_vectorize_PK2(self):
F = np.random.random((self.n,3,3))
P = np.random.random((self.n,3,3))
assert np.allclose(mechanics.PK2(F,P)[self.c],
mechanics.PK2(F[self.c],P[self.c]))
def test_vectorize_transpose(self):
@ -104,6 +117,13 @@ class TestMechanics:
np.matmul(V,R))
def test_PK2(self):
"""Ensure 2. Piola-Kirchhoff stress is symmetrized 1. Piola-Kirchhoff stress for no deformation."""
P = np.random.random((self.n,3,3))
assert np.allclose(mechanics.PK2(np.broadcast_to(np.eye(3),(self.n,3,3)),P),
mechanics.symmetric(P))
def test_strain_tensor_no_rotation(self):
"""Ensure that left and right stretch give same results for no rotation."""
F = np.broadcast_to(np.eye(3),[self.n,3,3])*np.random.random((self.n,3,3))
@ -186,3 +206,22 @@ class TestMechanics:
x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.Mises_stress(x)/mechanics.Mises_strain(x),
1.5)
def test_eigenvalues(self):
"""Ensure that the characteristic polynomial can be solved."""
A = mechanics.symmetric(np.random.random((self.n,3,3)))
lambd = mechanics.eigenvalues(A)
s = np.random.randint(self.n)
for i in range(3):
assert np.allclose(np.linalg.det(A[s]-lambd[s,i]*np.eye(3)),.0)
def test_eigenvalues_and_vectors(self):
"""Ensure that eigenvalues and -vectors are the solution to the characteristic polynomial."""
A = mechanics.symmetric(np.random.random((self.n,3,3)))
lambd = mechanics.eigenvalues(A)
x = mechanics.eigenvectors(A)
s = np.random.randint(self.n)
for i in range(3):
assert np.allclose(np.dot(A[s]-lambd[s,i]*np.eye(3),x[s,:,i]),.0)