PRISMS-PF  v2.1
computeStress.h
Go to the documentation of this file.
1 //implementation to compute stress given the elasticity matrix (CIJ) and strain tensor
2 
3 #ifndef COMPUTESTRESS_MECHANICS_H
4 #define COMPUTESTRESS_MECHANICS_H
5 
6 #include "../../../include/matrixFreePDE.h"
7 
8 //this source file is temporarily treated as a header file (hence
9 //#ifndef's) till library packaging scheme is finalized
10 
11 //#include "anisotropy.h"
12 
13 // Compute stress with displacement-gradient as input
14 
15 // Mathematical formulation (3D): S -> stress vector, R -> stress tensor, C -> stiffness tensor, E -> strain vector
16 //
17 // Generalized Hooke's law:
18 // [ S(0) ] [ C11 C12 C13 C14 C15 C16 ] [ E(0) ]
19 // [ S(1) ] [ C21 C22 C13 C14 C15 C16 ] [ E(1) ]
20 // [ S(2) ] [ C31 C32 C33 C34 C35 C36 ] [ E(2) ]
21 // [ S(3) ] = [ C41 C42 C43 C44 C45 C46 ] [ E(3) ]
22 // [ S(4) ] [ C51 C52 C53 C54 C55 C56 ] [ E(4) ]
23 // [ S(5) ] [ C61 C62 C63 C64 C65 C66 ] [ E(5) ]
24 //
25 // Strain vector definition: (using Ricci calculus notation, where commas in subscript refer to partial derivatives)
26 // E(0) = epsilon1 = epsilon11 = 1/2 ( u1,1 + u1,1 )
27 // E(1) = epsilon2 = epsilon22 = 1/2 ( u2,2 + u2,2 )
28 // E(2) = epsilon3 = epsilon33 = 1/2 ( u3,3 + u3,3 )
29 // E(3) = epsilon4 = 2*epsilon23 = ( u2,3 + u3,2 )
30 // E(4) = epsilon5 = 2*epsilon13 = ( u1,3 + u3,1 )
31 // E(5) = epsilon6 = 2*epsilon12 = ( u1,2 + u2,1 )
32 //
33 // Stress vector definition:
34 // S(0) = R[0][0] = sigma11
35 // S(1) = R[1][1] = sigma22
36 // S(2) = R[2][2] = sigma33
37 // S(3) = R[1][2] = R[2][1] = sigma23 = sigma32
38 // S(4) = R[0][2] = R[2][0] = sigma13 = sigma31
39 // S(5) = R[0][1] = R[1][0] = sigma12 = sigma21
40 
41 // Currently there are four overloaded versions of this function. They treat the cases where CIJ can be a table, a vectorized array, or a tensor
42 // and where strain and R can be vectorized arrays or tensors. Going forward, there may be a better way to reorganize this with templates.
43 
44 // Overloaded function where CIJ is a table, and the stress and strain are vectorized arrays
45 template <int dim>
46 void computeStress(const dealii::Table<2, double>& CIJ, const dealii::VectorizedArray<double> strain[][dim], dealii::VectorizedArray<double> R[][dim]){
47 if (dim==3){
48  dealii::VectorizedArray<double> S[6], E[6];
49  E[0]=strain[0][0]; E[1]=strain[1][1]; E[2]=strain[2][2];
50  //In Voigt notation: Engineering shear strain=2*strain
51  E[3]=strain[1][2]+strain[2][1];
52  E[4]=strain[0][2]+strain[2][0];
53  E[5]=strain[0][1]+strain[1][0];
54  for (unsigned int i=0; i<6; i++){
55  S[i]=0.0;
56  for (unsigned int j=0; j<6; j++){
57  S[i]+=CIJ(i,j)*E[j];
58  }
59  }
60  R[0][0]=S[0]; R[1][1]=S[1]; R[2][2]=S[2];
61  R[1][2]=S[3]; R[0][2]=S[4]; R[0][1]=S[5];
62  R[2][1]=S[3]; R[2][0]=S[4]; R[1][0]=S[5];
63 
64 // Optimized algorithm that skips the zero entries of CIJ for an orthotropic material and is a few percent faster
65 // dealii::VectorizedArray<double> S[6], E[6];
66 // E[0]=strain[0][0]; E[1]=strain[1][1]; E[2]=strain[2][2];
67 // //In Voigt notation: Engineering shear strain=2*strain
68 // E[3]=strain[1][2]+strain[2][1];
69 // E[4]=strain[0][2]+strain[2][0];
70 // E[5]=strain[0][1]+strain[1][0];
71 // for (unsigned int i=0; i<3; i++){
72 // S[i]=0.0;
73 // for (unsigned int j=0; j<3; j++){
74 // S[i]+=CIJ(i,j)*E[j];
75 // }
76 // }
77 //
78 // for (unsigned int i=3; i<6; i++){
79 // S[i]=CIJ(i,i)*E[i];
80 // }
81 // R[0][0]=S[0]; R[1][1]=S[1]; R[2][2]=S[2];
82 // R[1][2]=S[3]; R[0][2]=S[4]; R[0][1]=S[5];
83 // R[2][1]=S[3]; R[2][0]=S[4]; R[1][0]=S[5];
84 }
85 else if (dim==2){
86  dealii::VectorizedArray<double> S[3], E[3];
87  E[0]=strain[0][0]; E[1]=strain[1][1];
88  //In Voigt notation: Engineering shear strain=2*strain
89  E[2]=strain[0][1]+strain[1][0];
90  for (unsigned int i=0; i<3; i++){
91  S[i]=0.0;
92  for (unsigned int j=0; j<3; j++){
93  S[i]+=CIJ(i,j)*E[j];
94  }
95  }
96  R[0][0]=S[0]; R[1][1]=S[1];
97  R[0][1]=S[2]; R[1][0]=S[2];
98 }
99 else {
100  dealii::VectorizedArray<double> S[1], E[1];
101  E[0]=strain[0][0];
102  S[0]=CIJ(0,0)*E[0];
103  R[0][0]=S[0];
104 
105 }
106 }
107 
108 // Overloaded function where CIJ, the strain, and the stress are all vectorized arrays
109 template <int dim>
110 void computeStress(const dealii::VectorizedArray<double> CIJ[2*dim-1+dim/3][2*dim-1+dim/3], const dealii::VectorizedArray<double> strain[][dim], dealii::VectorizedArray<double> R[][dim]){
111 if (dim==3){
112  dealii::VectorizedArray<double> S[6], E[6];
113  E[0]=strain[0][0]; E[1]=strain[1][1]; E[2]=strain[2][2];
114  //In Voigt notation: Engineering shear strain=2*strain
115  E[3]=strain[1][2]+strain[2][1];
116  E[4]=strain[0][2]+strain[2][0];
117  E[5]=strain[0][1]+strain[1][0];
118  for (unsigned int i=0; i<6; i++){
119  S[i]=0.0;
120  for (unsigned int j=0; j<6; j++){
121  S[i]+=CIJ[i][j]*E[j];
122  }
123  }
124  R[0][0]=S[0]; R[1][1]=S[1]; R[2][2]=S[2];
125  R[1][2]=S[3]; R[0][2]=S[4]; R[0][1]=S[5];
126  R[2][1]=S[3]; R[2][0]=S[4]; R[1][0]=S[5];
127 }
128 else if (dim==2){
129  dealii::VectorizedArray<double> S[3], E[3];
130  E[0]=strain[0][0]; E[1]=strain[1][1];
131  //In Voigt notation: Engineering shear strain=2*strain
132  E[2]=strain[0][1]+strain[1][0];
133  for (unsigned int i=0; i<3; i++){
134  S[i]=0.0;
135  for (unsigned int j=0; j<3; j++){
136  S[i]+=CIJ[i][j]*E[j];
137  }
138  }
139  R[0][0]=S[0]; R[1][1]=S[1];
140  R[0][1]=S[2]; R[1][0]=S[2];
141 }
142 else {
143  dealii::VectorizedArray<double> S[1], E[1];
144  E[0]=strain[0][0];
145  S[0]=CIJ[0][0]*E[0];
146  R[0][0]=S[0];
147 
148 }
149 }
150 
151 // Overloaded function where CIJ is stored as a tensor and the strain and stress are vectorized arrays
152 template <int dim>
153 void computeStress(const dealii::Tensor<2, 2*dim-1+dim/3, dealii::VectorizedArray<double> >& CIJ, const dealii::VectorizedArray<double> strain[][dim], dealii::VectorizedArray<double> R[][dim]){
154 if (dim==3){
155  dealii::VectorizedArray<double> S[6], E[6];
156  E[0]=strain[0][0]; E[1]=strain[1][1]; E[2]=strain[2][2];
157  //In Voigt notation: Engineering shear strain=2*strain
158  E[3]=strain[1][2]+strain[2][1];
159  E[4]=strain[0][2]+strain[2][0];
160  E[5]=strain[0][1]+strain[1][0];
161  for (unsigned int i=0; i<6; i++){
162  S[i]=0.0;
163  for (unsigned int j=0; j<6; j++){
164  S[i]+=CIJ[i][j]*E[j];
165  }
166  }
167  R[0][0]=S[0]; R[1][1]=S[1]; R[2][2]=S[2];
168  R[1][2]=S[3]; R[0][2]=S[4]; R[0][1]=S[5];
169  R[2][1]=S[3]; R[2][0]=S[4]; R[1][0]=S[5];
170 }
171 else if (dim==2){
172  dealii::VectorizedArray<double> S[3], E[3];
173  E[0]=strain[0][0]; E[1]=strain[1][1];
174  //In Voigt notation: Engineering shear strain=2*strain
175  E[2]=strain[0][1]+strain[1][0];
176  for (unsigned int i=0; i<3; i++){
177  S[i]=0.0;
178  for (unsigned int j=0; j<3; j++){
179  S[i]+=CIJ[i][j]*E[j];
180  }
181  }
182  R[0][0]=S[0]; R[1][1]=S[1];
183  R[0][1]=S[2]; R[1][0]=S[2];
184 }
185 else {
186  dealii::VectorizedArray<double> S[1], E[1];
187  E[0]=strain[0][0];
188  S[0]=CIJ[0][0]*E[0];
189  R[0][0]=S[0];
190 
191 }
192 }
193 
194 // Overloaded function where CIJ, the strain, and the stress are all stored as tensors
195 template <int dim>
196 void computeStress(const dealii::Tensor<2, 2*dim-1+dim/3, dealii::VectorizedArray<double> >& CIJ, const dealii::Tensor<2, dim, dealii::VectorizedArray<double> > strain, dealii::Tensor<2, dim, dealii::VectorizedArray<double> >& R){
197 
198 dealii::Tensor<1, 2*dim-1+dim/3, dealii::VectorizedArray<double> > S, E;
199 
200 if (dim==3){
201  E[0]=strain[0][0]; E[1]=strain[1][1]; E[2]=strain[2][2];
202  //In Voigt notation: Engineering shear strain=2*strain
203  E[3]=strain[1][2]+strain[2][1];
204  E[4]=strain[0][2]+strain[2][0];
205  E[5]=strain[0][1]+strain[1][0];
206 
207  // Multiply CIJ and E (in the language of Deal.II this is a tensor contraction) to get S
208  S = CIJ*E;
209 
210  R[0][0]=S[0]; R[1][1]=S[1]; R[2][2]=S[2];
211  R[1][2]=S[3]; R[0][2]=S[4]; R[0][1]=S[5];
212  R[2][1]=S[3]; R[2][0]=S[4]; R[1][0]=S[5];
213 }
214 else if (dim==2){
215  E[0]=strain[0][0]; E[1]=strain[1][1];
216  //In Voigt notation: Engineering shear strain=2*strain
217  E[2]=strain[0][1]+strain[1][0];
218 
219  // Multiply CIJ and E (in the language of Deal.II this is a tensor contraction) to get S
220  S = CIJ*E;
221 
222  R[0][0]=S[0]; R[1][1]=S[1];
223  R[0][1]=S[2]; R[1][0]=S[2];
224 
225 }
226 else {
227  R[0][0]=CIJ[0][0]*strain[0][0];
228 }
229 }
230 
231 // Overloaded function where CIJ is a table and the strain and the stress are stored as tensors
232 template <int dim>
233 void computeStress(const dealii::Table<2, double>& CIJ, const dealii::Tensor<2, dim, dealii::VectorizedArray<double> >& strain, dealii::Tensor<2, dim, dealii::VectorizedArray<double> >& R){
234 if (dim==3){
235  dealii::VectorizedArray<double> S[6], E[6];
236  E[0]=strain[0][0]; E[1]=strain[1][1]; E[2]=strain[2][2];
237  //In Voigt notation: Engineering shear strain=2*strain
238  E[3]=strain[1][2]+strain[2][1];
239  E[4]=strain[0][2]+strain[2][0];
240  E[5]=strain[0][1]+strain[1][0];
241  for (unsigned int i=0; i<6; i++){
242  S[i]=0.0;
243  for (unsigned int j=0; j<6; j++){
244  S[i]+=CIJ(i,j)*E[j];
245  }
246  }
247  R[0][0]=S[0]; R[1][1]=S[1]; R[2][2]=S[2];
248  R[1][2]=S[3]; R[0][2]=S[4]; R[0][1]=S[5];
249  R[2][1]=S[3]; R[2][0]=S[4]; R[1][0]=S[5];
250 }
251 else if (dim==2){
252  dealii::VectorizedArray<double> S[3], E[3];
253  E[0]=strain[0][0]; E[1]=strain[1][1];
254  //In Voigt notation: Engineering shear strain=2*strain
255  E[2]=strain[0][1]+strain[1][0];
256  for (unsigned int i=0; i<3; i++){
257  S[i]=0.0;
258  for (unsigned int j=0; j<3; j++){
259  S[i]+=CIJ[i][j]*E[j];
260  }
261  }
262  R[0][0]=S[0]; R[1][1]=S[1];
263  R[0][1]=S[2]; R[1][0]=S[2];
264 }
265 else {
266  dealii::VectorizedArray<double> S[1], E[1];
267  E[0]=strain[0][0];
268  S[0]=CIJ[0][0]*E[0];
269  R[0][0]=S[0];
270 
271 }
272 }
273 
274 #endif
void computeStress(const dealii::Table< 2, double > &CIJ, const dealii::VectorizedArray< double > strain[][dim], dealii::VectorizedArray< double > R[][dim])
Definition: computeStress.h:46