some insights from continuum mechanics formulated as test

This commit is contained in:
Martin Diehl 2019-12-23 11:25:07 +01:00
parent 27d6b91f18
commit aec9c601d6
2 changed files with 62 additions and 10 deletions

View File

@ -92,21 +92,27 @@ def deviatoric_part(x):
x - np.einsum('ijk,i->ijk',np.broadcast_to(np.eye(3),[x.shape[0],3,3]),spherical_part(x)) x - np.einsum('ijk,i->ijk',np.broadcast_to(np.eye(3),[x.shape[0],3,3]),spherical_part(x))
def spherical_part(x): def spherical_part(x,tensor=False):
""" """
Return spherical (hydrostatic) part of a tensor. Return spherical (hydrostatic) part of a tensor.
A single scalar is returned, i.e. the hydrostatic part is not mapped on the 3rd order identity
matrix.
Parameters Parameters
---------- ----------
x : numpy.array of shape (:,3,3) or (3,3) x : numpy.array of shape (:,3,3) or (3,3)
Tensor of which the hydrostatic part is computed. Tensor of which the hydrostatic part is computed.
tensor : bool, optional
Map spherical part onto identity tensor. Default is false
""" """
return np.trace(x)/3.0 if np.shape(x) == (3,3) else \ if x.shape == (3,3):
np.trace(x,axis1=1,axis2=2)/3.0 sph = np.trace(x)/3.0
return sph if not tensor else np.eye(3)*sph
else:
sph = np.trace(x,axis1=1,axis2=2)/3.0
if not tensor:
return sph
else:
return np.einsum('ijk,i->ijk',np.broadcast_to(np.eye(3),(x.shape[0],3,3)),sph)
def Mises_stress(sigma): def Mises_stress(sigma):

View File

@ -30,8 +30,8 @@ class TestMechanics:
def test_vectorize_spherical_part(self): def test_vectorize_spherical_part(self):
x = np.random.random((self.n,3,3)) x = np.random.random((self.n,3,3))
assert np.allclose(mechanics.spherical_part(x)[self.c], assert np.allclose(mechanics.spherical_part(x,True)[self.c],
mechanics.spherical_part(x[self.c])) mechanics.spherical_part(x[self.c],True))
def test_vectorize_Mises_stress(self): def test_vectorize_Mises_stress(self):
@ -94,6 +94,15 @@ class TestMechanics:
assert np.allclose(mechanics.Cauchy(np.broadcast_to(np.eye(3),(self.n,3,3)),P), assert np.allclose(mechanics.Cauchy(np.broadcast_to(np.eye(3),(self.n,3,3)),P),
mechanics.symmetric(P)) mechanics.symmetric(P))
def test_polar_decomposition(self):
"""F = RU = VR."""
F = np.broadcast_to(np.eye(3),[self.n,3,3])*np.random.random((self.n,3,3))
R = mechanics.rotational_part(F)
V = mechanics.left_stretch(F)
U = mechanics.right_stretch(F)
assert np.allclose(np.matmul(R,U),
np.matmul(V,R))
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."""
@ -102,6 +111,12 @@ class TestMechanics:
assert np.allclose(mechanics.strain_tensor(F,'U',m), assert np.allclose(mechanics.strain_tensor(F,'U',m),
mechanics.strain_tensor(F,'V',m)) mechanics.strain_tensor(F,'V',m))
def test_strain_tensor_rotation_equivalence(self):
"""Ensure that left and right strain differ only by a rotation."""
F = np.random.random((self.n,3,3))
m = np.random.random()*5.0-2.5
assert np.allclose(np.linalg.det(mechanics.strain_tensor(F,'U',m)),
np.linalg.det(mechanics.strain_tensor(F,'V',m)))
def test_strain_tensor_rotation(self): def test_strain_tensor_rotation(self):
"""Ensure that pure rotation results in no strain.""" """Ensure that pure rotation results in no strain."""
@ -111,15 +126,46 @@ class TestMechanics:
assert np.allclose(mechanics.strain_tensor(F,t,m), assert np.allclose(mechanics.strain_tensor(F,t,m),
0.0) 0.0)
def test_rotation_determinant(self):
"""
Ensure that the determinant of the rotational part is +- 1.
Should be +1, but random F might contain a reflection.
"""
x = np.random.random((self.n,3,3))
assert np.allclose(np.abs(np.linalg.det(mechanics.rotational_part(x))),
1.0)
def test_spherical_deviatoric_part(self): def test_spherical_deviatoric_part(self):
"""Ensure that full tensor is sum of spherical and deviatoric part.""" """Ensure that full tensor is sum of spherical and deviatoric part."""
x = np.random.random((self.n,3,3)) x = np.random.random((self.n,3,3))
sph = np.broadcast_to(np.eye(3),(self.n,3,3))\ sph = mechanics.spherical_part(x,True)
* np.repeat(mechanics.spherical_part(x),9).reshape(self.n,3,3)
assert np.allclose(sph + mechanics.deviatoric_part(x), assert np.allclose(sph + mechanics.deviatoric_part(x),
x) x)
def test_deviatoric_Mises(self):
"""Ensure that Mises equivalent stress depends only on deviatoric part."""
x = np.random.random((self.n,3,3))
full = mechanics.Mises_stress(x)
dev = mechanics.Mises_stress(mechanics.deviatoric_part(x))
assert np.allclose(full,
dev)
def test_spherical_mapping(self):
"""Ensure that mapping to tensor is correct."""
x = np.random.random((self.n,3,3))
tensor = mechanics.spherical_part(x,True)
scalar = mechanics.spherical_part(x)
assert np.allclose(np.linalg.det(tensor),
scalar**3.0)
def test_spherical_Mises(self):
"""Ensure that Mises equivalent strrain of spherical strain is 0."""
x = np.random.random((self.n,3,3))
sph = mechanics.spherical_part(x,True)
assert np.allclose(mechanics.Mises_strain(sph),
0.0)
def test_symmetric(self): def test_symmetric(self):
"""Ensure that a symmetric tensor is half of the sum of a tensor and its transpose.""" """Ensure that a symmetric tensor is half of the sum of a tensor and its transpose."""