elasticipy 3.0.0__py3-none-any.whl → 4.1.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.
@@ -1,138 +1,16 @@
1
- import numpy as np
2
- from Elasticipy.SecondOrderTensor import SymmetricSecondOrderTensor
3
-
4
-
5
- class StrainTensor(SymmetricSecondOrderTensor):
6
- """
7
- Class for manipulating symmetric strain tensors or arrays of symmetric strain tensors.
8
-
9
- """
10
- name = 'Strain tensor'
11
- voigt_map = [1, 1, 1, 2, 2, 2]
12
-
13
- def principal_strains(self):
14
- """
15
- Values of the principals strains.
16
-
17
- If the tensor array is of shape [m,n,...], the results will be of shape [m,n,...,3].
18
-
19
- Returns
20
- -------
21
- np.ndarray
22
- Principal strain values
23
- """
24
- return self.eigvals()
25
-
26
- def volumetric_strain(self):
27
- """
28
- Volumetric change (1st invariant of the strain tensor)
29
-
30
- Returns
31
- -------
32
- numpy.ndarray or float
33
- Volumetric change
34
- """
35
- return self.I1
36
-
37
- def eq_strain(self):
38
- """von Mises equivalent strain"""
39
- return np.sqrt(2/3 * self.ddot(self))
40
-
41
- def elastic_energy(self, stress):
42
- """
43
- Compute the elastic energy.
44
-
45
- Parameters
46
- ----------
47
- stress : StressTensor
48
- Corresponding stress tensor
49
-
50
- Returns
51
- -------
52
- Volumetric elastic energy
53
- """
54
- return 0.5 * self.ddot(stress)
55
-
56
-
57
- class StressTensor(SymmetricSecondOrderTensor):
58
- """
59
- Class for manipulating stress tensors or arrays of stress tensors.
60
- """
61
- name = 'Stress tensor'
62
-
63
- def principal_stresses(self):
64
- """
65
- Values of the principals stresses.
66
-
67
- If the tensor array is of shape [m,n,...], the results will be of shape [m,n,...,3].
68
-
69
- Returns
70
- -------
71
- np.ndarray
72
- Principal stresses
73
- """
74
- return self.eigvals()
75
-
76
- def vonMises(self):
77
- """
78
- von Mises equivalent stress.
79
-
80
- Returns
81
- -------
82
- np.ndarray or float
83
- von Mises equivalent stress
84
-
85
- See Also
86
- --------
87
- Tresca : Tresca equivalent stress
88
- """
89
- return np.sqrt(3 * self.J2)
90
-
91
- def Tresca(self):
92
- """
93
- Tresca(-Guest) equivalent stress.
94
-
95
- Returns
96
- -------
97
- np.ndarray or float
98
- Tresca equivalent stress
99
-
100
- See Also
101
- --------
102
- vonMises : von Mises equivalent stress
103
- """
104
- ps = self.principal_stresses()
105
- return ps[...,0] - ps[...,-1]
106
-
107
- def hydrostatic_pressure(self):
108
- """
109
- Hydrostatic pressure
110
-
111
- Returns
112
- -------
113
- np.ndarray or float
114
-
115
- See Also
116
- --------
117
- sphericalPart : spherical part of the stress
118
- """
119
- return -self.I1/3
120
-
121
- def elastic_energy(self, strain, mode='pair'):
122
- """
123
- Compute the elastic energy.
124
-
125
- Parameters
126
- ----------
127
- strain : StrainTensor
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.
132
-
133
- Returns
134
- -------
135
- numpy.ndarray
136
- Volumetric elastic energy
137
- """
138
- return 0.5 * self.ddot(strain, mode=mode)
1
+ import warnings
2
+ from Elasticipy.tensors.stress_strain import StressTensor as NewStressTensor
3
+ from Elasticipy.tensors.stress_strain import StrainTensor as NewStrainTensor
4
+
5
+ warnings.warn(
6
+ "The module 'Elasticipy.StressStrainTensors' is deprecated and will be removed in a future release. "
7
+ "Please use 'Elasticipy.tensors.stress_strain' instead.",
8
+ DeprecationWarning,
9
+ stacklevel=2
10
+ )
11
+
12
+ class StressTensor(NewStressTensor):
13
+ pass
14
+
15
+ class StrainTensor(NewStrainTensor):
16
+ pass
@@ -1,249 +1,12 @@
1
1
  import warnings
2
+ from Elasticipy.tensors.thermal_expansion import ThermalExpansionTensor as NewThermalExpansionTensor
2
3
 
3
- from Elasticipy.SecondOrderTensor import SymmetricSecondOrderTensor, ALPHABET, is_orix_rotation
4
- from Elasticipy.StressStrainTensors import StrainTensor
5
- import numpy as np
6
- from scipy.spatial.transform import Rotation
4
+ warnings.warn(
5
+ "The module 'Elasticipy.ThermalExpansion' is deprecated and will be removed in a future release. "
6
+ "Please use 'Elasticipy.tensors.thermal_expansion' instead.",
7
+ DeprecationWarning,
8
+ stacklevel=2
9
+ )
7
10
 
8
- class ThermalExpansionTensor(SymmetricSecondOrderTensor):
9
- name = 'Thermal expansion tensor'
10
-
11
- def __mul__(self, other):
12
- if isinstance(other, Rotation) or is_orix_rotation(other):
13
- return super().__mul__(other)
14
- else:
15
- other = np.asarray(other)
16
- other_expanded = other[..., None, None]
17
- other_with_eye = other_expanded * np.ones(3)
18
- new_mat = self.matrix * other_with_eye
19
- return StrainTensor(new_mat)
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
-
92
- def matmul(self, other):
93
- """
94
- Matrix like product with array of float, resulting either in StrainTensor.
95
-
96
- Compute the product between the tensor and a numpy array in a "matrix-product" way,*
97
- that is by computing each of the products. If T.shape=(m,n,o,...) and other.shape=(p,q,r,...), then::
98
-
99
- T.matmul(other).shape = (m,n,o,...,p,q,r,...)
100
-
101
- Parameters
102
- ----------
103
- other : np.ndarray
104
- Value to multiply by.
105
- Returns
106
- -------
107
- StrainTensor
108
- Array fo strain tensors corresponding to all cross-combinations between Thermal expansions and temperature
109
- increases.
110
- """
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):
117
- return super().matmul(other)
118
- else:
119
- return self.apply_temperature(other, mode='cross')
120
-
121
-
122
- @classmethod
123
- def isotropic(cls, alpha):
124
- """
125
- Create an isotropic thermal expansion tensor.
126
-
127
- Parameters
128
- ----------
129
- alpha : float
130
- Thermal expansion coefficient.
131
-
132
- Returns
133
- -------
134
- ThermalExpansionTensor
135
- """
136
- return cls(np.eye(3)*alpha)
137
-
138
- @classmethod
139
- def orthotropic(cls, alpha_11, alpha_22, alpha_33):
140
- """
141
- Create an orthotropic thermal expansion tensor.
142
-
143
- Parameters
144
- ----------
145
- alpha_11, alpha_22, alpha_33 : float
146
- Thermal expansion coefficients along the first, second and third axes, respectively.
147
-
148
- Returns
149
- -------
150
- ThermalExpansionTensor
151
- """
152
- return cls(np.diag([alpha_11, alpha_22, alpha_33]))
153
-
154
- @classmethod
155
- def orthorhombic(cls, *args):
156
- """
157
- Create a thermal expansion tensor corresponding to an orthotropic thermal expansion coefficient.
158
-
159
- This function is an alias for orthotropic().
160
-
161
- Parameters
162
- ----------
163
- args : list
164
- Orthotropic thermal expansion coefficient.
165
-
166
- Returns
167
- -------
168
- ThermalExpansionTensor
169
-
170
- See Also
171
- --------
172
- orthotropic
173
- """
174
- return cls.orthotropic(*args)
175
-
176
- @classmethod
177
- def monoclinic(cls, alpha_11, alpha_22, alpha_33, alpha_13=None, alpha_12=None):
178
- """
179
- Create a thermal expansion tensor for monoclinic symmetry.
180
-
181
- If alpha_13, the Diad || z is assumed. If alpha_12, the Diad || z is assumed. Therefore, these two parameters
182
- are exclusive.
183
-
184
- Parameters
185
- ----------
186
- alpha_11, alpha_22, alpha_33 : float
187
- Thermal expansion coefficient along the first, second and third axes, respectively.
188
- alpha_13 : float, optional
189
- Thermal expansion coefficient corresponding to XZ shear (for Diad || y)
190
- alpha_12: float, optional
191
- Thermal expansion coefficient corresponding to XY shear (for Diad || z)
192
-
193
- Returns
194
- -------
195
- ThermalExpansionTensor
196
- """
197
- matrix = np.diag([alpha_11, alpha_22, alpha_33])
198
- if (alpha_13 is not None) and (alpha_12 is None):
199
- matrix[0, 2] = matrix[2, 0]= alpha_13
200
- elif (alpha_12 is not None) and (alpha_13 is None):
201
- matrix[0, 1] = matrix[1, 0]= alpha_12
202
- elif (alpha_13 is not None) and (alpha_12 is not None):
203
- raise ValueError('alpha_13 and alpha_12 cannot be used together.')
204
- else:
205
- raise ValueError('Either alpha_13 or alpha_12 must be provided.')
206
- return cls(matrix)
207
-
208
-
209
- @classmethod
210
- def triclinic(cls, alpha_11=0., alpha_12=0., alpha_13=0., alpha_22=0., alpha_23=0., alpha_33=0.):
211
- """
212
- Create a thermal expansion tensor for triclinic symmetry.
213
-
214
- Parameters
215
- ----------
216
- alpha_11, alpha_12, alpha_13, alpha_22, alpha_23, alpha_33 : float
217
- Values of the thermal expansion coefficients
218
-
219
- Returns
220
- -------
221
- ThermalExpansionTensor
222
- """
223
- mat = [[alpha_11, alpha_12, alpha_13],
224
- [alpha_12, alpha_22, alpha_23],
225
- [alpha_13, alpha_23, alpha_33]]
226
- return cls(mat)
227
-
228
- @classmethod
229
- def transverse_isotropic(cls, alpha_11, alpha_33):
230
- """
231
- Create a thermal expansion tensor for transverse isotropic symmetry.
232
-
233
- Parameters
234
- ----------
235
- alpha_11 : float
236
- Thermal expansion coefficient along the first and second axes
237
- alpha_33 : float
238
- Thermal expansion coefficient along the third axis
239
-
240
- Returns
241
- -------
242
- ThermalExpansionTensor
243
- """
244
- return cls(np.diag([alpha_11, alpha_11, alpha_33]))
245
-
246
- @property
247
- def volumetric_coefficient(self):
248
- """ Returns the volumetric thermal expansion coefficient."""
249
- return self.I1
11
+ class ThermalExpansionTensor(NewThermalExpansionTensor):
12
+ pass
Elasticipy/gui.py CHANGED
@@ -1,15 +1,15 @@
1
1
  import sys
2
2
 
3
3
  import numpy as np
4
- from PyQt5.QtWidgets import (
4
+ from qtpy.QtWidgets import (
5
5
  QApplication, QMainWindow, QComboBox, QGridLayout, QLabel,
6
6
  QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QWidget, QFrame, QMessageBox
7
7
  )
8
8
  from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
9
9
  from matplotlib.figure import Figure
10
10
 
11
- from Elasticipy.CrystalSymmetries import SYMMETRIES
12
- from Elasticipy.FourthOrderTensor import StiffnessTensor
11
+ from Elasticipy.crystal_symmetries import SYMMETRIES
12
+ from Elasticipy.tensors.elasticity import StiffnessTensor
13
13
 
14
14
  WHICH_OPTIONS = {'Mean': 'mean', 'Max': 'max', 'Min': 'min', 'Std. dev.': 'std'}
15
15
 
@@ -0,0 +1,119 @@
1
+ from Elasticipy.tensors.second_order import SymmetricSecondOrderTensor, SecondOrderTensor, \
2
+ SkewSymmetricSecondOrderTensor
3
+ from Elasticipy.tensors.stress_strain import StressTensor, StrainTensor
4
+ import pandas as pd
5
+ import numpy as np
6
+ import os
7
+ import re
8
+ from pathlib import Path
9
+
10
+ DTYPES={'stress':StressTensor,
11
+ 'strain':StrainTensor,
12
+ 'strain_el':StrainTensor,
13
+ 'strain_pl':StrainTensor,
14
+ 'velgrad':SecondOrderTensor,
15
+ 'defrate':SymmetricSecondOrderTensor,
16
+ 'defrate_pl':SymmetricSecondOrderTensor,
17
+ 'spinrate':SkewSymmetricSecondOrderTensor,
18
+ }
19
+
20
+
21
+ def _list_valid_filenames(folder, startswith='strain'):
22
+ file_list = os.listdir(folder)
23
+ pattern = r'{}\.step\d+'.format(startswith)
24
+ return [f for f in file_list if re.fullmatch(pattern, f)]
25
+
26
+ def from_step_file(file, dtype=None):
27
+ """
28
+ Import data from a single step file given by FEPX.
29
+
30
+ The type of returns is inferred from the data one wants to parse
31
+ (according the `FEPX documentation <https://fepx.info/doc/output.html>`_ ).
32
+
33
+ Parameters
34
+ ----------
35
+ file : str
36
+ Path to the file to read
37
+ dtype : type, optional
38
+ If provided, sets the type of returned array. It can be:
39
+ - float
40
+ - SecondOrderTensor
41
+ - SymmetricSecondOrderTensor
42
+ - SkewSymmetricSecondOrderTensor
43
+ - stressTensor
44
+ - strainTensor
45
+
46
+ Returns
47
+ -------
48
+ SecondOrderTensor or numpy.ndarray
49
+ Array of second-order tensors built from the read data. The array will be of shape (n,), where n is the number
50
+ of elements in the mesh.
51
+ """
52
+ data = pd.read_csv(file, header=None, sep=' ')
53
+ array = data.to_numpy()
54
+ base_name = os.path.splitext(os.path.basename(file))[0]
55
+ if dtype is None:
56
+ if base_name in DTYPES:
57
+ dtype = DTYPES[base_name]
58
+ else:
59
+ dtype = float
60
+ if issubclass(dtype,SymmetricSecondOrderTensor):
61
+ return dtype.from_Voigt(array, voigt_map=[1,1,1,1,1,1])
62
+ elif dtype == SkewSymmetricSecondOrderTensor:
63
+ zeros = np.zeros(array.shape[0])
64
+ mat = np.array([[ zeros, array[:, 0], array[:, 1]],
65
+ [-array[:, 0], zeros, array[:, 2]],
66
+ [-array[:, 1], -array[:, 2], zeros ]]).transpose((2, 0, 1))
67
+ return SkewSymmetricSecondOrderTensor(mat)
68
+ elif dtype == SecondOrderTensor:
69
+ length = array.shape[0]
70
+ return SecondOrderTensor(array.reshape((length,3,3)))
71
+ elif dtype == float:
72
+ return array
73
+
74
+
75
+
76
+ def from_results_folder(folder, dtype=None):
77
+ """
78
+ Import all data of a given field from FEPX results folder.
79
+
80
+ The type of returns is inferred from the data one wants to parse
81
+ (according the `FEPX documentation <https://fepx.info/doc/output.html>`_ ).
82
+
83
+ Parameters
84
+ ----------
85
+ folder : str
86
+ Path to the folder to read the results from
87
+ dtype : type, optional
88
+ If provided, sets the type of returned array. It can be:
89
+ - float
90
+ - SecondOrderTensor
91
+ - SymmetricSecondOrderTensor
92
+ - SkewSymmetricSecondOrderTensor
93
+ - stressTensor
94
+ - strainTensor
95
+
96
+ Returns
97
+ -------
98
+ SecondOrderTensor or numpy.ndarray
99
+ Array of second-order tensors built from the read data. The array will be of shape (m, n), where m is the number
100
+ of time increment n is the number of elements in the mesh.
101
+ """
102
+ dir_path = Path(folder)
103
+ folder_name = dir_path.name
104
+ if not dir_path.is_dir():
105
+ raise ValueError(f"{folder} is not a valid directory.")
106
+ constructor = None
107
+ array = []
108
+ for file in dir_path.iterdir():
109
+ if file.is_file() and file.name.startswith(folder_name):
110
+ data_file = from_step_file(str(file), dtype=dtype)
111
+ if constructor is None:
112
+ constructor = type(data_file)
113
+ elif constructor != type(data_file):
114
+ raise ValueError('The types of data contained in {} seem to be inconsistent.'.format(folder))
115
+ array.append(data_file)
116
+ if constructor == np.ndarray:
117
+ return np.stack(array, axis=0)
118
+ else:
119
+ return constructor.stack(array)
@@ -0,0 +1,103 @@
1
+ from Elasticipy.tensors.second_order import SecondOrderTensor, SymmetricSecondOrderTensor
2
+ from Elasticipy.tensors.stress_strain import StressTensor
3
+ import pandas as pd
4
+ import numpy as np
5
+
6
+ def _rebuild_tensor(F11, F22, F33, F12, F13, F21, F23, F31, F32):
7
+ return np.array([[F11, F12, F13], [F21, F22, F23], [F31, F32, F33]]).transpose((2,0,1))
8
+
9
+ def from_quadrature_file(file, returns='stress'):
10
+ """
11
+ Read data from quadrature output file generated by PRISMS plasticity.
12
+
13
+ These files, usually named QuadratureOutputsXXX.csv (where XXX denotes the time increment), contain large amount of
14
+ data, such as gradient components, stress values, grain ID etc.
15
+
16
+ Parameters
17
+ ----------
18
+ file : str
19
+ Path to quadrature file
20
+ returns : str or list of str or tuple of str
21
+ name(s) of requested field(s). They can be:
22
+ - grain ID
23
+ - phase ID
24
+ - det(J)
25
+ - twin
26
+ - coordinates
27
+ - orientation
28
+ - elastic gradient
29
+ - plastic gradient
30
+ - stress
31
+ Returns
32
+ -------
33
+ ndarray or SecondOrderTensor or StressTensor
34
+ The number of returned values depends on the requested fields.
35
+ """
36
+ data=pd.read_csv(file, header=None, dtype=float, usecols=range(0,37))
37
+ grainID, phaseID, detJ, twin, x, y, z, rot1, rot2, rot3, *other = data.T.to_numpy()
38
+ Fe11, Fe22, Fe33, Fe12, Fe13, Fe21, Fe23, Fe31, Fe32, *FpStress = other
39
+ Fp11, Fp22, Fp33, Fp12, Fp13, Fp21, Fp23, Fp31, Fp32, *stress_compo = FpStress
40
+ if isinstance(returns, str):
41
+ returns_list = (returns,)
42
+ else:
43
+ returns_list = returns
44
+ returned_values = []
45
+ for r in returns_list:
46
+ rl = r.lower()
47
+ if (rl == 'grain id') or (rl == 'grainid'):
48
+ returned_values.append(grainID)
49
+ elif (rl == 'phase id') or (rl == 'phaseid'):
50
+ returned_values.append(phaseID)
51
+ elif rl == 'det(j)':
52
+ returned_values.append(detJ)
53
+ elif rl == 'twin':
54
+ returned_values.append(twin)
55
+ elif rl == 'coordinates':
56
+ returned_values.append(np.array([x, y, z]).T)
57
+ elif rl == 'orientation':
58
+ returned_values.append(np.array([rot1, rot2, rot3]).T)
59
+ elif rl == 'elastic gradient':
60
+ Fe = _rebuild_tensor(Fe11, Fe22, Fe33, Fe12, Fe13, Fe21, Fe23, Fe31, Fe32)
61
+ returned_values.append(SecondOrderTensor(Fe))
62
+ elif rl == 'plastic gradient':
63
+ Fp = _rebuild_tensor(Fp11, Fp22, Fp33, Fp12, Fp13, Fp21, Fp23, Fp31, Fp32)
64
+ returned_values.append(SecondOrderTensor(Fp))
65
+ elif rl == 'stress':
66
+ stress = _rebuild_tensor(*stress_compo)
67
+ returned_values.append(StressTensor(stress))
68
+ else:
69
+ raise ValueError('Unknown return type')
70
+ if isinstance(returns, str):
71
+ return returned_values[0]
72
+ else:
73
+ return tuple(returned_values)
74
+
75
+ def from_stressstrain_file(file):
76
+ """
77
+ Read data from stress-strain file generated by PRISMS plasticity.
78
+
79
+ This file is usually named stressstrain.txt
80
+
81
+ Parameters
82
+ ----------
83
+ file : str
84
+ Path to stress-strain file
85
+
86
+ Returns
87
+ -------
88
+ SymmetricSecondOrderTensor
89
+ Average Green-Lagrange strain tensor
90
+ StressTensor
91
+ Average stress tensor
92
+ """
93
+ data = pd.read_csv(file, sep='\t')
94
+ Exx, Exy, Exz = data['Exx'], data['Exy'], data['Exz']
95
+ Eyy, Eyz = data['Eyy'], data['Eyz']
96
+ Ezz = data['Ezz']
97
+ E = np.array([[Exx, Exy, Exz], [Exy, Eyy, Eyz], [Exz, Eyz, Ezz]]).transpose((2,0,1))
98
+ Txx, Txy, Txz = data['Txx'], data['Txy'], data['Txz']
99
+ Tyy, Tyz = data['Tyy'], data['Tyz']
100
+ Tzz = data['Tzz']
101
+ T = np.array([[Txx, Txy, Txz], [Txy, Tyy, Tyz], [Txz, Tyz, Tzz]]).transpose((2, 0, 1))
102
+ return SymmetricSecondOrderTensor(E), StressTensor(T)
103
+