elasticipy 2.9.0__tar.gz → 3.0.0__tar.gz

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.
Files changed (88) hide show
  1. {elasticipy-2.9.0 → elasticipy-3.0.0}/JOSS/paper.bib +4 -2
  2. {elasticipy-2.9.0/src/elasticipy.egg-info → elasticipy-3.0.0}/PKG-INFO +2 -1
  3. {elasticipy-2.9.0 → elasticipy-3.0.0}/README.md +1 -0
  4. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/Plasticity.rst +34 -34
  5. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/Tutorial_StiffnessTensor.rst +1 -1
  6. elasticipy-3.0.0/docs/source/Tutorials/Tutorial_StressStrain.rst +231 -0
  7. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/Tutorial_ThermalExpansion.rst +9 -5
  8. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/index.rst +4 -0
  9. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/Elasticipy/FourthOrderTensor.py +360 -44
  10. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/Elasticipy/Plasticity.py +105 -55
  11. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/Elasticipy/SecondOrderTensor.py +243 -54
  12. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/Elasticipy/StressStrainTensors.py +9 -5
  13. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/Elasticipy/ThermalExpansion.py +88 -17
  14. {elasticipy-2.9.0 → elasticipy-3.0.0/src/elasticipy.egg-info}/PKG-INFO +2 -1
  15. {elasticipy-2.9.0 → elasticipy-3.0.0}/tests/test_StiffnessTensor.py +147 -9
  16. {elasticipy-2.9.0 → elasticipy-3.0.0}/tests/test_StressStrainTensors.py +168 -16
  17. {elasticipy-2.9.0 → elasticipy-3.0.0}/tests/test_ThermalExpansion.py +15 -0
  18. {elasticipy-2.9.0 → elasticipy-3.0.0}/tests/test_plasticity.py +32 -15
  19. elasticipy-2.9.0/docs/source/Tutorials/Tutorial_StressStrain.rst +0 -445
  20. {elasticipy-2.9.0 → elasticipy-3.0.0}/.github/workflows/Codecov.yml +0 -0
  21. {elasticipy-2.9.0 → elasticipy-3.0.0}/.github/workflows/JOSS build.yml +0 -0
  22. {elasticipy-2.9.0 → elasticipy-3.0.0}/.github/workflows/cloc.yml +0 -0
  23. {elasticipy-2.9.0 → elasticipy-3.0.0}/.github/workflows/python-publish.yml +0 -0
  24. {elasticipy-2.9.0 → elasticipy-3.0.0}/.readthedocs.yaml +0 -0
  25. {elasticipy-2.9.0 → elasticipy-3.0.0}/CODE_OF_CONDUCT.md +0 -0
  26. {elasticipy-2.9.0 → elasticipy-3.0.0}/CONTRIBUTING.md +0 -0
  27. {elasticipy-2.9.0 → elasticipy-3.0.0}/Examples/Elasticipy_vs_pymatgen.py +0 -0
  28. {elasticipy-2.9.0 → elasticipy-3.0.0}/Examples/Elate_vs_Elasticipy.py +0 -0
  29. {elasticipy-2.9.0 → elasticipy-3.0.0}/Examples/Example_Stiffness_tensor.py +0 -0
  30. {elasticipy-2.9.0 → elasticipy-3.0.0}/Examples/Example_StressStrain_arrays.py +0 -0
  31. {elasticipy-2.9.0 → elasticipy-3.0.0}/Examples/Example_WaveVelocity.py +0 -0
  32. {elasticipy-2.9.0 → elasticipy-3.0.0}/Examples/MaterialsProject.json +0 -0
  33. {elasticipy-2.9.0 → elasticipy-3.0.0}/Examples/Multiple_phases.py +0 -0
  34. {elasticipy-2.9.0 → elasticipy-3.0.0}/Examples/essai_plasticity.py +0 -0
  35. {elasticipy-2.9.0 → elasticipy-3.0.0}/Examples/example_readwrite.py +0 -0
  36. {elasticipy-2.9.0 → elasticipy-3.0.0}/JOSS/ElasticipyVSpymatgen.png +0 -0
  37. {elasticipy-2.9.0 → elasticipy-3.0.0}/JOSS/Nye.png +0 -0
  38. {elasticipy-2.9.0 → elasticipy-3.0.0}/JOSS/Plot_E.png +0 -0
  39. {elasticipy-2.9.0 → elasticipy-3.0.0}/JOSS/YoungModulus.png +0 -0
  40. {elasticipy-2.9.0 → elasticipy-3.0.0}/JOSS/paper.md +0 -0
  41. {elasticipy-2.9.0 → elasticipy-3.0.0}/LICENSE +0 -0
  42. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/_static/images/HyperSphericalCoordinates.png +0 -0
  43. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/index.rst +0 -0
  44. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Elasticipy.FourthOrderTensor.rst +0 -0
  45. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Elasticipy.Plasticity.rst +0 -0
  46. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Elasticipy.SecondOrderTensor.rst +0 -0
  47. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Elasticipy.SphericalFunction.rst +0 -0
  48. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Elasticipy.StressStrainTensors.rst +0 -0
  49. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Elasticipy.rst +0 -0
  50. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/GUI.rst +0 -0
  51. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/Tutorial_AveragingMethods.rst +0 -0
  52. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/Tutorial_MultiplePhases.rst +0 -0
  53. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/Tutorial_ReadWriteFiles.rst +0 -0
  54. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/Tutorial_wave-velocities.rst +0 -0
  55. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/Cyclic.png +0 -0
  56. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/E_PF.png +0 -0
  57. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/E_VRH_sections.png +0 -0
  58. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/E_hill_fiber.png +0 -0
  59. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/E_plot3D.png +0 -0
  60. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/E_xyz_sections.png +0 -0
  61. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/GUI.png +0 -0
  62. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/G_plot3D.png +0 -0
  63. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/G_plot3D_min.png +0 -0
  64. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/G_xyz_sections.png +0 -0
  65. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/Incremental.png +0 -0
  66. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/Shear.png +0 -0
  67. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/Stress-controlled.png +0 -0
  68. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/StressStrain-controlled.png +0 -0
  69. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/WaveVelocities.png +0 -0
  70. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials/images/plot_volumeFraction.png +0 -0
  71. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/Tutorials.rst +0 -0
  72. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/conf.py +0 -0
  73. {elasticipy-2.9.0 → elasticipy-3.0.0}/docs/source/modules.rst +0 -0
  74. {elasticipy-2.9.0 → elasticipy-3.0.0}/pyproject.toml +0 -0
  75. {elasticipy-2.9.0 → elasticipy-3.0.0}/requirements.txt +0 -0
  76. {elasticipy-2.9.0 → elasticipy-3.0.0}/setup.cfg +0 -0
  77. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/Elasticipy/CrystalSymmetries.py +0 -0
  78. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/Elasticipy/PoleFigure.py +0 -0
  79. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/Elasticipy/SphericalFunction.py +0 -0
  80. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/Elasticipy/__init__.py +0 -0
  81. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/Elasticipy/gui.py +0 -0
  82. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/elasticipy.egg-info/SOURCES.txt +0 -0
  83. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/elasticipy.egg-info/dependency_links.txt +0 -0
  84. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/elasticipy.egg-info/requires.txt +0 -0
  85. {elasticipy-2.9.0 → elasticipy-3.0.0}/src/elasticipy.egg-info/top_level.txt +0 -0
  86. {elasticipy-2.9.0 → elasticipy-3.0.0}/tests/MaterialsProject.json +0 -0
  87. {elasticipy-2.9.0 → elasticipy-3.0.0}/tests/__init__.py +0 -0
  88. {elasticipy-2.9.0 → elasticipy-3.0.0}/tests/test_SphericalFunction.py +0 -0
@@ -6,6 +6,7 @@ pages = {314-319},
6
6
  year = {2013},
7
7
  issn = {0927-0256},
8
8
  url = {https://doi.org/10.1016/j.commatsci.2012.10.028},
9
+ doi = {10.1016/j.commatsci.2012.10.028},
9
10
  author = {Shyue Ping Ong and William Davidson Richards and Anubhav Jain and Geoffroy Hautier and Michael Kocher and Shreyas Cholia and Dan Gunter and Vincent L. Chevrier and Kristin A. Persson and Gerbrand Ceder},
10
11
  keywords = {Materials, Project, Design, Thermodynamics, High-throughput},
11
12
  }
@@ -33,7 +34,8 @@ journal = {Journal of Physics: Condensed Matter},
33
34
  pages={175--192},
34
35
  year={2011},
35
36
  publisher={The Geological Society of London London},
36
- url={http://dx.doi.org/10.1144/SP360.10}
37
+ url={http://dx.doi.org/10.1144/SP360.10},
38
+ doi={10.1144/SP360.10}
37
39
  }
38
40
 
39
41
  @book{nye,
@@ -124,4 +126,4 @@ DOI = {10.5194/se-11-259-2020}
124
126
  doi = {10.1038/s41586-020-2649-2},
125
127
  publisher = {Springer Science and Business Media {LLC}},
126
128
  url = {https://doi.org/10.1038/s41586-020-2649-2}
127
- }
129
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: elasticipy
3
- Version: 2.9.0
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
  [![DOI](https://zenodo.org/badge/876162900.svg)](https://doi.org/10.5281/zenodo.14501849)
37
37
  [![codecov](https://codecov.io/gh/DorianDepriester/Elasticipy/graph/badge.svg?token=VUZPEUPBH1)](https://codecov.io/gh/DorianDepriester/Elasticipy)
38
38
  ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/Elasticipy)
39
+ [![status](https://joss.theoj.org/papers/8cce91b782f17f52e9ee30916cd86ad5/status.svg)](https://joss.theoj.org/papers/8cce91b782f17f52e9ee30916cd86ad5)
39
40
 
40
41
 
41
42
 
@@ -6,6 +6,7 @@
6
6
  [![DOI](https://zenodo.org/badge/876162900.svg)](https://doi.org/10.5281/zenodo.14501849)
7
7
  [![codecov](https://codecov.io/gh/DorianDepriester/Elasticipy/graph/badge.svg?token=VUZPEUPBH1)](https://codecov.io/gh/DorianDepriester/Elasticipy)
8
8
  ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/Elasticipy)
9
+ [![status](https://joss.theoj.org/papers/8cce91b782f17f52e9ee30916cd86ad5/status.svg)](https://joss.theoj.org/papers/8cce91b782f17f52e9ee30916cd86ad5)
9
10
 
10
11
 
11
12
 
@@ -63,17 +63,17 @@ So now, the plastic strain can be computed using an iterative approach:
63
63
 
64
64
  >>> plastic_strain = StrainTensor.zeros(n_step)
65
65
  >>> for i in range(1, n_step):
66
- strain_increment = JC.compute_strain_increment(stress[i])
67
- plastic_strain[i] = plastic_strain[i-1] + strain_increment
66
+ ... strain_increment = JC.compute_strain_increment(stress[i])
67
+ ... plastic_strain[i] = plastic_strain[i-1] + strain_increment
68
68
 
69
69
  That's all. Finally, let us plot the applied stress as a function of the overall elongation:
70
70
 
71
71
  >>> from matplotlib import pyplot as plt
72
72
  >>> elong = elastic_strain.C[0,0]+plastic_strain.C[0,0]
73
73
  >>> fig, ax = plt.subplots()
74
- >>> ax.plot(elong, stress_mag, label='Stress-controlled')
75
- >>> ax.set_xlabel(r'$\varepsilon_{xx}$')
76
- >>> ax.set_ylabel('Tensile stress (MPa)')
74
+ >>> ax.plot(elong, stress_mag, label='Stress-controlled') # doctest: +SKIP
75
+ >>> ax.set_xlabel(r'$\varepsilon_{xx}$') # doctest: +SKIP
76
+ >>> ax.set_ylabel('Tensile stress (MPa)') # doctest: +SKIP
77
77
 
78
78
  .. image:: images/Stress-controlled.png
79
79
 
@@ -90,22 +90,22 @@ to add a subroutine (optimization loop) to find the tensile stress so that the a
90
90
  >>> plastic_strain = StrainTensor.zeros(n_step)
91
91
  >>> JC.reset_strain()
92
92
  >>> for i in range(1, n_step):
93
- def fun(tensile_stress):
94
- trial_stress = StressTensor.tensile([1,0,0], tensile_stress)
95
- trial_elastic_strain = C.inv() * trial_stress
96
- trial_strain_increment = JC.compute_strain_increment(trial_stress, apply_strain=False)
97
- trial_plastic_strain = plastic_strain[i - 1] + trial_strain_increment
98
- trial_elongation = trial_plastic_strain.C[0,0] + trial_elastic_strain.C[0,0]
99
- return (trial_elongation - elong[i])**2
100
- s = minimize_scalar(fun)
101
- stress.C[0,0][i] = s.x
102
- strain_increment = JC.compute_strain_increment(stress[i])
103
- plastic_strain[i] = plastic_strain[i-1] + strain_increment
93
+ ... def fun(tensile_stress):
94
+ ... trial_stress = StressTensor.tensile([1,0,0], tensile_stress)
95
+ ... trial_elastic_strain = C.inv() * trial_stress
96
+ ... trial_strain_increment = JC.compute_strain_increment(trial_stress, apply_strain=False)
97
+ ... trial_plastic_strain = plastic_strain[i - 1] + trial_strain_increment
98
+ ... trial_elongation = trial_plastic_strain.C[0,0] + trial_elastic_strain.C[0,0]
99
+ ... return (trial_elongation - elong[i])**2
100
+ ... s = minimize_scalar(fun)
101
+ ... stress.C[0,0][i] = s.x
102
+ ... strain_increment = JC.compute_strain_increment(stress[i])
103
+ ... plastic_strain[i] = plastic_strain[i-1] + strain_increment
104
104
 
105
105
  Finally, let's plot the corresponding tensile curve ontop of that of the stress-controlled tensile test:
106
106
 
107
- >>> ax.plot(elong, stress.C[0,0], label='Strain-controlled', linestyle='dotted')
108
- >>> ax.legend()
107
+ >>> ax.plot(elong, stress.C[0,0], label='Strain-controlled', linestyle='dotted') # doctest: +SKIP
108
+ >>> ax.legend() # doctest: +SKIP
109
109
 
110
110
  .. image:: images/StressStrain-controlled.png
111
111
 
@@ -115,10 +115,10 @@ Incremental loading
115
115
  Here, we have only considered monotonic loading, but we can also consider different loading path, such as incremental:
116
116
 
117
117
  >>> load_path = [np.linspace(0,0.1),
118
- np.linspace(0.1,0.099),
119
- np.linspace(0.099,0.2),
120
- np.linspace(0.2,0.199),
121
- np.linspace(0.199,0.3)]
118
+ ... np.linspace(0.1,0.099),
119
+ ... np.linspace(0.099,0.2),
120
+ ... np.linspace(0.2,0.199),
121
+ ... np.linspace(0.199,0.3)]
122
122
  >>> elong = np.concatenate(load_path)
123
123
  >>> n_step = len(elong)
124
124
 
@@ -128,9 +128,9 @@ or cyclic:
128
128
 
129
129
 
130
130
  >>> load_path = [np.linspace(0,0.1),
131
- np.linspace(0.1,-0.2),
132
- np.linspace(-0.2,0.3),
133
- np.linspace(0.3,-0.4)]
131
+ ... np.linspace(0.1,-0.2),
132
+ ... np.linspace(-0.2,0.3),
133
+ ... np.linspace(0.3,-0.4)]
134
134
  >>> elong = np.concatenate(load_path)
135
135
  >>> n_step = len(elong)
136
136
 
@@ -166,15 +166,15 @@ For instance, one can highlight the difference between the J2 and Tresca plastic
166
166
  >>> elastic_strain = C.inv() * stress
167
167
  >>> fig, ax = plt.subplots()
168
168
  >>> for j, model in enumerate(models):
169
- plastic_strain = StrainTensor.zeros(n_step)
170
- for i in range(1, n_step):
171
- strain_increment = model.compute_strain_increment(stress[i])
172
- plastic_strain[i] = plastic_strain[i-1] + strain_increment
173
- eps_xy = elastic_strain.C[0,1]+plastic_strain.C[0,1]
174
- ax.plot(eps_xy, stress_mag, label=labels[j])
175
- >>> ax.set_xlabel(r'$\varepsilon_{xy}$')
176
- >>> ax.set_ylabel('Shear stress (MPa)')
177
- >>> ax.legend()
169
+ ... plastic_strain = StrainTensor.zeros(n_step)
170
+ ... for i in range(1, n_step):
171
+ ... strain_increment = model.compute_strain_increment(stress[i])
172
+ ... plastic_strain[i] = plastic_strain[i-1] + strain_increment
173
+ ... eps_xy = elastic_strain.C[0,1]+plastic_strain.C[0,1]
174
+ ... ax.plot(eps_xy, stress_mag, label=labels[j])
175
+ >>> ax.set_xlabel(r'$\varepsilon_{xy}$') # doctest: +SKIP
176
+ >>> ax.set_ylabel('Shear stress (MPa)') # doctest: +SKIP
177
+ >>> ax.legend() # doctest: +SKIP
178
178
 
179
179
 
180
180
  .. image:: images/Shear.png
@@ -55,7 +55,7 @@ deviation of the Young modulus:
55
55
  Another way to evidence anisotropy is to use the universal anisotropy factor [1]_:
56
56
 
57
57
  >>> C.universal_anisotropy
58
- 5.14100955164141
58
+ 5.1410095516414085
59
59
 
60
60
  Shear moduli and Poisson ratios
61
61
  -------------------------------
@@ -0,0 +1,231 @@
1
+ Stress and strain tensors
2
+ =========================
3
+
4
+ This tutorial illustrates how we work on strain and stress tensors, and how Elasticipy handles arrays of tensors.
5
+
6
+ Single tensors
7
+ --------------
8
+ Let's start with basic operations with the stress tensor. For instance, we can compute the von Mises and Tresca
9
+ equivalent stresses:
10
+
11
+
12
+ .. doctest::
13
+
14
+ >>> from Elasticipy.StressStrainTensors import StressTensor, StrainTensor
15
+ >>> stress = StressTensor.shear([1, 0, 0], [0, 1, 0], 1.0) # Unit XY shear stress
16
+ >>> print(stress.vonMises(), stress.Tresca())
17
+ 1.7320508075688772 2.0
18
+
19
+ So now, let's have a look on the strain tensor, and compute the principal strains and the volumetric change:
20
+
21
+ >>> strain = StrainTensor.shear([1,0,0], [0,1,0], 1e-3) # XY Shear strain with 1e-3 mag.
22
+ >>> print(strain.principal_strains())
23
+ [ 0.001 0. -0.001]
24
+ >>> print(strain.volumetric_strain())
25
+ 0.0
26
+ >>> stress = StressTensor.shear([1, 0, 0], [0, 1, 0], 1.0) # Unit XY shear stress
27
+ >>> print(stress.vonMises(), stress.Tresca())
28
+ 1.7320508075688772 2.0
29
+
30
+ Linear elasticity
31
+ --------------------------------
32
+ This section is dedicated to linear elasticity, hence introducing the fourth-order stiffness tensor.
33
+ As an example, create a stiffness tensor corresponding to steel:
34
+
35
+ >>> from Elasticipy.FourthOrderTensor import StiffnessTensor
36
+ >>> C = StiffnessTensor.isotropic(E=210e3, nu=0.28)
37
+ >>> print(C)
38
+ Stiffness tensor (in Voigt notation):
39
+ [[268465.90909091 104403.40909091 104403.40909091 0.
40
+ 0. 0. ]
41
+ [104403.40909091 268465.90909091 104403.40909091 0.
42
+ 0. 0. ]
43
+ [104403.40909091 104403.40909091 268465.90909091 0.
44
+ 0. 0. ]
45
+ [ 0. 0. 0. 82031.25
46
+ 0. 0. ]
47
+ [ 0. 0. 0. 0.
48
+ 82031.25 0. ]
49
+ [ 0. 0. 0. 0.
50
+ 0. 82031.25 ]]
51
+ Symmetry: isotropic
52
+
53
+
54
+ Considering the previous strain, evaluate the corresponding stress:
55
+
56
+ >>> sigma = C * strain
57
+ >>> print(sigma)
58
+ Stress tensor
59
+ [[ 0. 164.0625 0. ]
60
+ [164.0625 0. 0. ]
61
+ [ 0. 0. 0. ]]
62
+
63
+ Conversely, one can compute the compliance tensor:
64
+
65
+ >>> S = C.inv()
66
+ >>> print(S)
67
+ Compliance tensor (in Voigt notation):
68
+ [[ 4.76190476e-06 -1.33333333e-06 -1.33333333e-06 0.00000000e+00
69
+ 0.00000000e+00 0.00000000e+00]
70
+ [-1.33333333e-06 4.76190476e-06 -1.33333333e-06 0.00000000e+00
71
+ 0.00000000e+00 0.00000000e+00]
72
+ [-1.33333333e-06 -1.33333333e-06 4.76190476e-06 0.00000000e+00
73
+ 0.00000000e+00 0.00000000e+00]
74
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.21904762e-05
75
+ 0.00000000e+00 0.00000000e+00]
76
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00
77
+ 1.21904762e-05 0.00000000e+00]
78
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00
79
+ 0.00000000e+00 1.21904762e-05]]
80
+ Symmetry: isotropic
81
+
82
+ and check that we retrieve the correct (initial) strain:
83
+
84
+ >>> print(S * sigma)
85
+ Strain tensor
86
+ [[0. 0.001 0. ]
87
+ [0.001 0. 0. ]
88
+ [0. 0. 0. ]]
89
+
90
+ .. _multidimensional-arrays:
91
+
92
+ Multidimensional tensor arrays
93
+ ------------------------------
94
+ Elasticipy allows to process thousands of tensors at one, with the aid of tensor arrays.
95
+ As an illustration, we consider the anisotropic behaviour of ferrite:
96
+
97
+ >>> C = StiffnessTensor.fromCrystalSymmetry(symmetry='cubic', phase_name='ferrite',
98
+ ... C11=274, C12=175, C44=89)
99
+ >>> print(C)
100
+ Stiffness tensor (in Voigt notation) for ferrite:
101
+ [[274. 175. 175. 0. 0. 0.]
102
+ [175. 274. 175. 0. 0. 0.]
103
+ [175. 175. 274. 0. 0. 0.]
104
+ [ 0. 0. 0. 89. 0. 0.]
105
+ [ 0. 0. 0. 0. 89. 0.]
106
+ [ 0. 0. 0. 0. 0. 89.]]
107
+ Symmetry: cubic
108
+
109
+ Let's start by creating an array of 10 stresses:
110
+
111
+ >>> import numpy as np
112
+ >>> n_array = 10
113
+ >>> shear_stress = np.linspace(0, 100, n_array)
114
+ >>> sigma = StressTensor.shear([1,0,0],[0,1,0], shear_stress) # Array of stresses corresponding to X-Y shear
115
+ >>> print(sigma[0]) # Check the initial value of the stress...
116
+ Stress tensor
117
+ [[0. 0. 0.]
118
+ [0. 0. 0.]
119
+ [0. 0. 0.]]
120
+ >>> print(sigma[-1]) # ...and the final value.
121
+ Stress tensor
122
+ [[ 0. 100. 0.]
123
+ [100. 0. 0.]
124
+ [ 0. 0. 0.]]
125
+
126
+ The corresponding strain array is evaluated with the same syntax as before:
127
+
128
+ >>> eps = C.inv() * sigma
129
+ >>> print(eps[0]) # Now check the initial value of strain...
130
+ Strain tensor
131
+ [[0. 0. 0.]
132
+ [0. 0. 0.]
133
+ [0. 0. 0.]]
134
+ >>> print(eps[-1]) # ...and the final value.
135
+ Strain tensor
136
+ [[0. 0.56179775 0. ]
137
+ [0.56179775 0. 0. ]
138
+ [0. 0. 0. ]]
139
+
140
+ We can for instance compute the corresponding elastic energies:
141
+
142
+ >>> print(eps.elastic_energy(sigma))
143
+ [ 0. 0.69357747 2.77430989 6.24219725 11.09723956 17.33943682
144
+ 24.96878901 33.98529616 44.38895825 56.17977528]
145
+
146
+ Another application of working with an array of stress tensors is to check whether a tensor field complies with the
147
+ balance of linear momentum (see `here <https://en.wikiversity.org/wiki/Continuum_mechanics/Balance_of_linear_momentum>`_
148
+ for details) or not. For instance, if we want to compute the divergence of ``sigma``:
149
+
150
+ >>> sigma.div()
151
+ array([[ 0. , 11.11111111, 0. ],
152
+ [ 0. , 11.11111111, 0. ],
153
+ [ 0. , 11.11111111, 0. ],
154
+ [ 0. , 11.11111111, 0. ],
155
+ [ 0. , 11.11111111, 0. ],
156
+ [ 0. , 11.11111111, 0. ],
157
+ [ 0. , 11.11111111, 0. ],
158
+ [ 0. , 11.11111111, 0. ],
159
+ [ 0. , 11.11111111, 0. ],
160
+ [ 0. , 11.11111111, 0. ]])
161
+
162
+ Here, the *i*-th row provides the divergence vector for the *i*-th stress tensor.
163
+ See `the full documentation <../Elasticipy.SecondOrderTensor.html#Elasticipy.SecondOrderTensor.SecondOrderTensor.div>`_ for
164
+ details about this function.
165
+
166
+ .. _strain_rotations:
167
+
168
+ Apply rotations
169
+ ---------------
170
+ Rotations can be applied on the tensors. If multiple rotations are applied at once, this results in tensor arrays.
171
+ Rotations are defined by ``scipy.transform.Rotation``
172
+ (see `here <https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.transform.Rotation.html>`__ for details).
173
+
174
+ >>> from scipy.spatial.transform import Rotation
175
+
176
+ For example, let's consider a random set of 1000 rotations:
177
+
178
+ >>> n_ori = 1000
179
+ >>> random_state = 1234 # This is just to ensure reproducibility
180
+ >>> rotations = Rotation.random(n_ori, random_state=random_state)
181
+
182
+ These rotations can be applied on the strain tensor
183
+
184
+ >>> eps_rotated = eps.rotate(rotations, mode='cross')
185
+
186
+
187
+ Option ``mode='cross'`` allows to compute all combinations of strains and rotation, resulting in a kind of 2D matrix of
188
+ strain tensors:
189
+
190
+ >>> print(eps_rotated.shape)
191
+ (10, 1000)
192
+
193
+ Therefore, we can compute the corresponding rotated stress array:
194
+
195
+ >>> sigma_rotated = C * eps_rotated
196
+ >>> print(sigma_rotated.shape) # Check out the shape of the stresses
197
+ (10, 1000)
198
+
199
+ And get the stress back to the initial coordinate system:
200
+
201
+ >>> sigma = sigma_rotated * rotations.inv() # Go back to initial frame
202
+
203
+ As opposed to the ``rotate(..., mode='cross')`` (see above), we use ``*`` here to keep the same
204
+ dimensionality (perform element-wise multiplication). It is equivalent to:
205
+
206
+ >>> sigma = sigma_rotated.rotate(rotations.inv())
207
+
208
+ Finally, we can estimate the mean stresses among all the orientations:
209
+
210
+ >>> sigma_mean = sigma.mean(axis=1) # Compute the mean over all orientations
211
+ >>> print(sigma_mean[-1]) # random
212
+ Stress tensor
213
+ [[ 5.35134832e-01 8.22419895e+01 2.02619662e-01]
214
+ [ 8.22419895e+01 -4.88440590e-01 -1.52733598e-01]
215
+ [ 2.02619662e-01 -1.52733598e-01 -4.66942413e-02]]
216
+
217
+ Actually, a more straightforward method is to define a set of rotated stiffness tensors, and compute their Reuss average:
218
+
219
+ >>> C_rotated = C * rotations
220
+ >>> C_Voigt = C_rotated.Voigt_average()
221
+
222
+ Which yields the same results in terms of stress:
223
+
224
+ >>> sigma_Voigt = C_Voigt * eps
225
+ >>> print(sigma_Voigt[-1])
226
+ Stress tensor
227
+ [[ 5.35134832e-01 8.22419895e+01 2.02619662e-01]
228
+ [ 8.22419895e+01 -4.88440590e-01 -1.52733598e-01]
229
+ [ 2.02619662e-01 -1.52733598e-01 -4.66942413e-02]]
230
+
231
+ See :ref:`here<Averaging methods>` for further details about the averaging methods.
@@ -77,20 +77,24 @@ If we want to consider multiple orientations at once, we can create an array of
77
77
  Shape=(10000,)
78
78
 
79
79
  If we want to compute the strain for each combination of orientations and temperatures in ``[0,1,2]`` (as done above),
80
- we can use the ``matmul`` operator:
80
+ we can use the ``apply_temperature()`` operator with ``mode='cross'``:
81
81
 
82
- >>> eps = alpha_rotated.matmul([0,1,2])
82
+ >>> eps = alpha_rotated.apply_temperature([0,1,2], mode='cross')
83
83
  >>> print(eps)
84
84
  Strain tensor
85
85
  Shape=(10000, 3)
86
86
 
87
+ .. note::
88
+
89
+ Above, we have used ``*``, which is just a shortcut for ``apply_temperature(...,mode='pair')``.
90
+
87
91
  For instance we can check out the maximum value for initial (0°) and final (2°) temperatures:
88
92
 
89
93
  >>> eps[:,0].max() # 0 because it corresponds to 0°
90
94
  Strain tensor
91
- [[ 0. -0. -0.]
92
- [-0. 0. -0.]
93
- [-0. -0. 0.]]
95
+ [[0. 0. 0.]
96
+ [0. 0. 0.]
97
+ [0. 0. 0.]]
94
98
  >>> eps[:,-1].max()
95
99
  Strain tensor
96
100
  [[1.12000000e-05 5.99947076e-06 5.99905095e-06]
@@ -32,6 +32,10 @@ Welcome to Elasticipy's Documentation!
32
32
  .. image:: https://img.shields.io/pypi/pyversions/Elasticipy
33
33
  :alt: PyPI - Python Version
34
34
 
35
+ .. image:: https://joss.theoj.org/papers/8cce91b782f17f52e9ee30916cd86ad5/status.svg
36
+ :alt: JOSS status
37
+ :target: https://joss.theoj.org/papers/8cce91b782f17f52e9ee30916cd86ad5
38
+
35
39
 
36
40
 
37
41
  Purpose of this package