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) S = np.dot(np.linalg.inv(F),P)
else: else:
S = np.einsum('ijk,ikl->ijl',np.linalg.inv(F),P) S = np.einsum('ijk,ikl->ijl',np.linalg.inv(F),P)
return S return symmetric(S)
def strain_tensor(F,t,m): def strain_tensor(F,t,m):
@ -168,27 +168,41 @@ def maximum_shear(x):
Symmetric tensor of which the maximum shear is computed. Symmetric tensor of which the maximum shear is computed.
""" """
w = np.linalg.eigvalsh(symmetric(x)) # eigenvalues in ascending order w = eigenvalues(x)
return (w[2] - w[0])*0.5 if np.shape(x) == (3,3) else \ return (w[0] - w[2])*0.5 if np.shape(x) == (3,3) else \
(w[:,2] - w[:,0])*0.5 (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. its multiplicity.
Parameters Parameters
---------- ----------
x : numpy.array of shape (:,3,3) or (3,3) 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 np.linalg.eigvalsh(symmetric(x))
return w[::-1] if np.shape(x) == (3,3) else \
w[:,::-1]
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): def transpose(x):

View File

@ -58,10 +58,23 @@ class TestMechanics:
mechanics.maximum_shear(x[self.c])) 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)) x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.principal_components(x)[self.c], assert np.allclose(mechanics.eigenvalues(x)[self.c],
mechanics.principal_components(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): def test_vectorize_transpose(self):
@ -104,6 +117,13 @@ class TestMechanics:
np.matmul(V,R)) 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): def test_strain_tensor_no_rotation(self):
"""Ensure that left and right stretch give same results for no rotation.""" """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)) 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)) x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.Mises_stress(x)/mechanics.Mises_strain(x), assert np.allclose(mechanics.Mises_stress(x)/mechanics.Mises_strain(x),
1.5) 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)