elasticipy 2.8.10__py3-none-any.whl → 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- Elasticipy/FourthOrderTensor.py +360 -44
- Elasticipy/Plasticity.py +222 -15
- Elasticipy/SecondOrderTensor.py +338 -66
- Elasticipy/StressStrainTensors.py +13 -8
- Elasticipy/ThermalExpansion.py +88 -17
- {elasticipy-2.8.10.dist-info → elasticipy-3.0.0.dist-info}/METADATA +2 -1
- elasticipy-3.0.0.dist-info/RECORD +15 -0
- {elasticipy-2.8.10.dist-info → elasticipy-3.0.0.dist-info}/WHEEL +1 -1
- elasticipy-2.8.10.dist-info/RECORD +0 -15
- {elasticipy-2.8.10.dist-info → elasticipy-3.0.0.dist-info}/LICENSE +0 -0
- {elasticipy-2.8.10.dist-info → elasticipy-3.0.0.dist-info}/top_level.txt +0 -0
|
@@ -29,13 +29,14 @@ class StrainTensor(SymmetricSecondOrderTensor):
|
|
|
29
29
|
|
|
30
30
|
Returns
|
|
31
31
|
-------
|
|
32
|
-
|
|
32
|
+
numpy.ndarray or float
|
|
33
33
|
Volumetric change
|
|
34
34
|
"""
|
|
35
35
|
return self.I1
|
|
36
36
|
|
|
37
37
|
def eq_strain(self):
|
|
38
|
-
|
|
38
|
+
"""von Mises equivalent strain"""
|
|
39
|
+
return np.sqrt(2/3 * self.ddot(self))
|
|
39
40
|
|
|
40
41
|
def elastic_energy(self, stress):
|
|
41
42
|
"""
|
|
@@ -101,9 +102,9 @@ class StressTensor(SymmetricSecondOrderTensor):
|
|
|
101
102
|
vonMises : von Mises equivalent stress
|
|
102
103
|
"""
|
|
103
104
|
ps = self.principal_stresses()
|
|
104
|
-
return ps[
|
|
105
|
+
return ps[...,0] - ps[...,-1]
|
|
105
106
|
|
|
106
|
-
def
|
|
107
|
+
def hydrostatic_pressure(self):
|
|
107
108
|
"""
|
|
108
109
|
Hydrostatic pressure
|
|
109
110
|
|
|
@@ -117,17 +118,21 @@ class StressTensor(SymmetricSecondOrderTensor):
|
|
|
117
118
|
"""
|
|
118
119
|
return -self.I1/3
|
|
119
120
|
|
|
120
|
-
def elastic_energy(self, strain):
|
|
121
|
+
def elastic_energy(self, strain, mode='pair'):
|
|
121
122
|
"""
|
|
122
123
|
Compute the elastic energy.
|
|
123
124
|
|
|
124
125
|
Parameters
|
|
125
126
|
----------
|
|
126
127
|
strain : StrainTensor
|
|
127
|
-
Corresponding strain tensor
|
|
128
|
+
Corresponding elastic strain tensor
|
|
129
|
+
mode : str, optional
|
|
130
|
+
If 'pair' (default), the elastic energies are computed element-wise. Broadcasting rule applies.
|
|
131
|
+
If 'cross', each cross-combination of stress and strain are considered.
|
|
128
132
|
|
|
129
133
|
Returns
|
|
130
134
|
-------
|
|
131
|
-
|
|
135
|
+
numpy.ndarray
|
|
136
|
+
Volumetric elastic energy
|
|
132
137
|
"""
|
|
133
|
-
return 0.5 * self.ddot(strain)
|
|
138
|
+
return 0.5 * self.ddot(strain, mode=mode)
|
Elasticipy/ThermalExpansion.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
from Elasticipy.SecondOrderTensor import SymmetricSecondOrderTensor, ALPHABET, is_orix_rotation
|
|
2
4
|
from Elasticipy.StressStrainTensors import StrainTensor
|
|
3
5
|
import numpy as np
|
|
4
6
|
from scipy.spatial.transform import Rotation
|
|
@@ -7,7 +9,7 @@ class ThermalExpansionTensor(SymmetricSecondOrderTensor):
|
|
|
7
9
|
name = 'Thermal expansion tensor'
|
|
8
10
|
|
|
9
11
|
def __mul__(self, other):
|
|
10
|
-
if isinstance(other, Rotation):
|
|
12
|
+
if isinstance(other, Rotation) or is_orix_rotation(other):
|
|
11
13
|
return super().__mul__(other)
|
|
12
14
|
else:
|
|
13
15
|
other = np.asarray(other)
|
|
@@ -16,36 +18,105 @@ class ThermalExpansionTensor(SymmetricSecondOrderTensor):
|
|
|
16
18
|
new_mat = self.matrix * other_with_eye
|
|
17
19
|
return StrainTensor(new_mat)
|
|
18
20
|
|
|
21
|
+
def apply_temperature(self, temperature, mode='pair'):
|
|
22
|
+
"""
|
|
23
|
+
Apply temperature increase to the thermal expansion tensor, or to the array.
|
|
24
|
+
|
|
25
|
+
Application can be made pair-wise, or considering all cross-combinations (see below).
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
temperature : float or numpy.ndarray
|
|
30
|
+
mode : str, optional
|
|
31
|
+
If "pair" (default), the temperatures are applied pair-wise on the tensor array. Broadcasting rule applies
|
|
32
|
+
If "cross", all cross combinations are considered. Therefore, if ``C=A.apply_temperature(T, mode="cross")``,
|
|
33
|
+
then ``C.shape=A.shape + T.shape``.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
StrainTensor
|
|
38
|
+
Strain corresponding to the applied temperature increase(s).
|
|
39
|
+
|
|
40
|
+
Examples
|
|
41
|
+
--------
|
|
42
|
+
Let consider a transverse isotropic case (e.g. carbon fibers):
|
|
43
|
+
>>> from Elasticipy.ThermalExpansion import ThermalExpansionTensor as ThEx
|
|
44
|
+
>>> alpha = ThEx.transverse_isotropic(alpha_11=5.6e-6, alpha_33=-0.4e-6)
|
|
45
|
+
|
|
46
|
+
Now apply temperature increases:
|
|
47
|
+
>>> T = [0, 1, 2]
|
|
48
|
+
>>> eps = alpha.apply_temperature(T)
|
|
49
|
+
|
|
50
|
+
We get a strain tensor of the same shape as the applied temperatures:
|
|
51
|
+
>>> eps
|
|
52
|
+
Strain tensor
|
|
53
|
+
Shape=(3,)
|
|
54
|
+
>>> eps[-1]
|
|
55
|
+
Strain tensor
|
|
56
|
+
[[ 1.12e-05 0.00e+00 0.00e+00]
|
|
57
|
+
[ 0.00e+00 1.12e-05 0.00e+00]
|
|
58
|
+
[ 0.00e+00 0.00e+00 -8.00e-07]]
|
|
59
|
+
|
|
60
|
+
Now let's rotate the thermal expansions:
|
|
61
|
+
>>> from scipy.spatial.transform import Rotation
|
|
62
|
+
>>> rot = Rotation.random(3) # Set of 3 random 3D rotations
|
|
63
|
+
>>> alpha_rotated = alpha * rot
|
|
64
|
+
|
|
65
|
+
If we want to combine each rotated thermal expansion with the corresponding temperature increase:
|
|
66
|
+
>>> eps_rotated_pair = alpha_rotated * T # Equivalent to alpha_rotated.apply_temperature(T)
|
|
67
|
+
>>> eps_rotated_pair
|
|
68
|
+
Strain tensor
|
|
69
|
+
Shape=(3,)
|
|
70
|
+
|
|
71
|
+
Conversely, if we want to evaluate all cross-combinations of thermal expansions and temperature increases:
|
|
72
|
+
|
|
73
|
+
>>> eps_rotated_cross = alpha_rotated.apply_temperature(T, mode='cross')
|
|
74
|
+
>>> eps_rotated_cross
|
|
75
|
+
Strain tensor
|
|
76
|
+
Shape=(3, 3)
|
|
77
|
+
|
|
78
|
+
"""
|
|
79
|
+
temperature = np.asarray(temperature)
|
|
80
|
+
if mode == 'pair':
|
|
81
|
+
matrix = self.matrix*temperature[...,np.newaxis,np.newaxis]
|
|
82
|
+
elif mode == 'cross':
|
|
83
|
+
indices_self = ALPHABET[:self.ndim]
|
|
84
|
+
indices_temp = ALPHABET[:len(temperature.shape)].upper()
|
|
85
|
+
ein_str = indices_self + 'ij,' + indices_temp + '->' + indices_self + indices_temp + 'ij'
|
|
86
|
+
matrix = np.einsum(ein_str, self.matrix, temperature)
|
|
87
|
+
else:
|
|
88
|
+
raise ValueError('Invalid mode. It could be either "pair" or "cross".')
|
|
89
|
+
return StrainTensor(matrix)
|
|
90
|
+
|
|
91
|
+
|
|
19
92
|
def matmul(self, other):
|
|
20
93
|
"""
|
|
21
|
-
Matrix like product with array of
|
|
94
|
+
Matrix like product with array of float, resulting either in StrainTensor.
|
|
22
95
|
|
|
23
|
-
Compute the product between the tensor and
|
|
96
|
+
Compute the product between the tensor and a numpy array in a "matrix-product" way,*
|
|
24
97
|
that is by computing each of the products. If T.shape=(m,n,o,...) and other.shape=(p,q,r,...), then::
|
|
25
98
|
|
|
26
99
|
T.matmul(other).shape = (m,n,o,...,p,q,r,...)
|
|
27
100
|
|
|
28
101
|
Parameters
|
|
29
102
|
----------
|
|
30
|
-
other : np.ndarray
|
|
103
|
+
other : np.ndarray
|
|
31
104
|
Value to multiply by.
|
|
32
105
|
Returns
|
|
33
106
|
-------
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
StrainTensor.
|
|
107
|
+
StrainTensor
|
|
108
|
+
Array fo strain tensors corresponding to all cross-combinations between Thermal expansions and temperature
|
|
109
|
+
increases.
|
|
38
110
|
"""
|
|
39
|
-
|
|
111
|
+
warnings.warn(
|
|
112
|
+
'matmul() is deprecated and will be removed in a future version. Use dot(tensor,mode="cross") or '
|
|
113
|
+
'rotate(rotation,mode="cross") instead.',
|
|
114
|
+
DeprecationWarning,
|
|
115
|
+
stacklevel=2)
|
|
116
|
+
if isinstance(other, Rotation) or is_orix_rotation(other):
|
|
40
117
|
return super().matmul(other)
|
|
41
118
|
else:
|
|
42
|
-
|
|
43
|
-
leading_shape = self.shape
|
|
44
|
-
leading_other_shape = other.shape
|
|
45
|
-
matrix_expanded = self.matrix.reshape(leading_shape + (1, 1, 3, 3)) # (m, n, 1, 1, 3, 3)
|
|
46
|
-
other_expanded = other.reshape((1, 1) + leading_other_shape + (1, 1)) # (1, 1, o, p, 1, 1)
|
|
47
|
-
new_mat = matrix_expanded * other_expanded
|
|
48
|
-
return StrainTensor(np.squeeze(new_mat))
|
|
119
|
+
return self.apply_temperature(other, mode='cross')
|
|
49
120
|
|
|
50
121
|
|
|
51
122
|
@classmethod
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: elasticipy
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: A Python library for elasticity tensor computations
|
|
5
5
|
Author-email: Dorian Depriester <dorian.dep@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -36,6 +36,7 @@ Requires-Dist: mp_api; extra == "dev"
|
|
|
36
36
|
[](https://doi.org/10.5281/zenodo.14501849)
|
|
37
37
|
[](https://codecov.io/gh/DorianDepriester/Elasticipy)
|
|
38
38
|

|
|
39
|
+
[](https://joss.theoj.org/papers/8cce91b782f17f52e9ee30916cd86ad5)
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Elasticipy/CrystalSymmetries.py,sha256=DAX-XPgYqI2nFvf6anCVvZ5fLM0CNSDJ7r2h15l3Hoc,3958
|
|
2
|
+
Elasticipy/FourthOrderTensor.py,sha256=slRB4WL5JZKA8YP7jXMaQs9PRkhi1-RWDGhVNL2VuYA,63944
|
|
3
|
+
Elasticipy/Plasticity.py,sha256=vfL4Ckpk-GgpxXjGXEd4dTSIZJDr28wh_Za5S7PM3WI,11375
|
|
4
|
+
Elasticipy/PoleFigure.py,sha256=G3Sz7ssX2KKY96g3XEvcaOYFmEat9JUCdb2A91XbA6w,3531
|
|
5
|
+
Elasticipy/SecondOrderTensor.py,sha256=USsX2Jg_H8t67P10csPFVxmXJ40PPH7D94Kod_pdD7Y,52261
|
|
6
|
+
Elasticipy/SphericalFunction.py,sha256=X6hrjwCiZkLjiUQ8WO2W4vLNOlbQ4jLWsloOg33IlL4,41244
|
|
7
|
+
Elasticipy/StressStrainTensors.py,sha256=gEPo69Bnu4qBEeyYc4Rn-T213E-fTmTh_QNwAdVCX_U,3261
|
|
8
|
+
Elasticipy/ThermalExpansion.py,sha256=pXAa6CJ7_Yr02ZfUNcjFL7l6o0Bc-O1E3IjEM7yfYy4,8629
|
|
9
|
+
Elasticipy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
Elasticipy/gui.py,sha256=zyVnvp6IIi3FDR5hWfIJrOP28Y7XkP4wc71XXMyGpeo,11247
|
|
11
|
+
elasticipy-3.0.0.dist-info/LICENSE,sha256=qNthTMSjVkIDM1_BREgVFQHdn1wVNQi9pwWVfTIazMA,1074
|
|
12
|
+
elasticipy-3.0.0.dist-info/METADATA,sha256=-aOaNihsY1m4e1NANFp-EMtTWgQ63vPNS0AlbWRAkLk,3961
|
|
13
|
+
elasticipy-3.0.0.dist-info/WHEEL,sha256=nn6H5-ilmfVryoAQl3ZQ2l8SH5imPWFpm1A5FgEuFV4,91
|
|
14
|
+
elasticipy-3.0.0.dist-info/top_level.txt,sha256=k4zSQzJR5P4vzlHlhWUaxNgvgloq4KIp8oca2X8gQOw,11
|
|
15
|
+
elasticipy-3.0.0.dist-info/RECORD,,
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
Elasticipy/CrystalSymmetries.py,sha256=DAX-XPgYqI2nFvf6anCVvZ5fLM0CNSDJ7r2h15l3Hoc,3958
|
|
2
|
-
Elasticipy/FourthOrderTensor.py,sha256=LuqLxcWeonumxgVCjTIvcIjCkAqMK4ZNBlpGLvXGPeA,54105
|
|
3
|
-
Elasticipy/Plasticity.py,sha256=V-jSEf1lKhxKh4yeQs9msZThdT-m_O9KPKVreLk4AvY,4299
|
|
4
|
-
Elasticipy/PoleFigure.py,sha256=G3Sz7ssX2KKY96g3XEvcaOYFmEat9JUCdb2A91XbA6w,3531
|
|
5
|
-
Elasticipy/SecondOrderTensor.py,sha256=P1zPuqfmsPc8HP8izmfDcE80Zbq-UpOs0V1PiEoSmBs,43797
|
|
6
|
-
Elasticipy/SphericalFunction.py,sha256=X6hrjwCiZkLjiUQ8WO2W4vLNOlbQ4jLWsloOg33IlL4,41244
|
|
7
|
-
Elasticipy/StressStrainTensors.py,sha256=nZO6kEePOApdt6Y5anGl47RUhrDkHYtX50jtfKmB0jc,2926
|
|
8
|
-
Elasticipy/ThermalExpansion.py,sha256=nfPTXuqI4fJe14YLzYn8zfSjpYaep8URRYawj8xzjfo,6012
|
|
9
|
-
Elasticipy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
Elasticipy/gui.py,sha256=zyVnvp6IIi3FDR5hWfIJrOP28Y7XkP4wc71XXMyGpeo,11247
|
|
11
|
-
elasticipy-2.8.10.dist-info/LICENSE,sha256=qNthTMSjVkIDM1_BREgVFQHdn1wVNQi9pwWVfTIazMA,1074
|
|
12
|
-
elasticipy-2.8.10.dist-info/METADATA,sha256=XpTe1cDSCEFNlJ4OlwpNrYqrskP49DFahVnRurWrMxA,3811
|
|
13
|
-
elasticipy-2.8.10.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
14
|
-
elasticipy-2.8.10.dist-info/top_level.txt,sha256=k4zSQzJR5P4vzlHlhWUaxNgvgloq4KIp8oca2X8gQOw,11
|
|
15
|
-
elasticipy-2.8.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|