PRISMS-PF Manual v3.0-pre
Loading...
Searching...
No Matches
computeStress.h
1// implementation to compute stress given the elasticity matrix (CIJ) and strain
2// tensor
3
4#ifndef COMPUTESTRESS_MECHANICS_H
5#define COMPUTESTRESS_MECHANICS_H
6
7#include <deal.II/base/table.h>
8#include <deal.II/base/vectorization.h>
9
10// this source file is temporarily treated as a header file (hence
11// #ifndef's) till library packaging scheme is finalized
12
13// #include "anisotropy.h"
14
15// Compute stress with displacement-gradient as input
16
17// Mathematical formulation (3D): S -> stress vector, R -> stress tensor, C ->
18// stiffness tensor, E -> strain vector
19//
20// Generalized Hooke's law:
21// [ S(0) ] [ C11 C12 C13 C14 C15 C16 ] [ E(0) ]
22// [ S(1) ] [ C21 C22 C13 C14 C15 C16 ] [ E(1) ]
23// [ S(2) ] [ C31 C32 C33 C34 C35 C36 ] [ E(2) ]
24// [ S(3) ] = [ C41 C42 C43 C44 C45 C46 ] [ E(3) ]
25// [ S(4) ] [ C51 C52 C53 C54 C55 C56 ] [ E(4) ]
26// [ S(5) ] [ C61 C62 C63 C64 C65 C66 ] [ E(5) ]
27//
28// Strain vector definition: (using Ricci calculus notation, where commas in
29// subscript refer to partial derivatives) E(0) = epsilon1 = epsilon11 = 1/2 (
30// u1,1 + u1,1 ) E(1) = epsilon2 = epsilon22 = 1/2 ( u2,2 + u2,2 ) E(2) =
31// epsilon3 = epsilon33 = 1/2 ( u3,3 + u3,3 ) E(3) = epsilon4 = 2*epsilon23 = (
32// u2,3 + u3,2 ) E(4) = epsilon5 = 2*epsilon13 = ( u1,3 + u3,1 ) E(5) = epsilon6
33// = 2*epsilon12 = ( u1,2 + u2,1 )
34//
35// Stress vector definition:
36// S(0) = R[0][0] = sigma11
37// S(1) = R[1][1] = sigma22
38// S(2) = R[2][2] = sigma33
39// S(3) = R[1][2] = R[2][1] = sigma23 = sigma32
40// S(4) = R[0][2] = R[2][0] = sigma13 = sigma31
41// S(5) = R[0][1] = R[1][0] = sigma12 = sigma21
42
43// Currently there are four overloaded versions of this function. They treat the
44// cases where CIJ can be a table, a vectorized array, or a tensor and where
45// strain and R can be vectorized arrays or tensors. Going forward, there may be
46// a better way to reorganize this with templates.
47
48// Overloaded function where CIJ is a table, and the stress and strain are
49// vectorized arrays
50template <int dim>
51void
52computeStress(const dealii::Table<2, double> &CIJ,
53 const dealii::VectorizedArray<double> strain[][dim],
54 dealii::VectorizedArray<double> R[][dim])
55{
56 if (dim == 3)
57 {
58 dealii::VectorizedArray<double> S[6], E[6];
59 E[0] = strain[0][0];
60 E[1] = strain[1][1];
61 E[2] = strain[2][2];
62 // In Voigt notation: Engineering shear strain=2*strain
63 E[3] = strain[1][2] + strain[2][1];
64 E[4] = strain[0][2] + strain[2][0];
65 E[5] = strain[0][1] + strain[1][0];
66 for (unsigned int i = 0; i < 6; i++)
67 {
68 S[i] = 0.0;
69 for (unsigned int j = 0; j < 6; j++)
70 {
71 S[i] += CIJ(i, j) * E[j];
72 }
73 }
74 R[0][0] = S[0];
75 R[1][1] = S[1];
76 R[2][2] = S[2];
77 R[1][2] = S[3];
78 R[0][2] = S[4];
79 R[0][1] = S[5];
80 R[2][1] = S[3];
81 R[2][0] = S[4];
82 R[1][0] = S[5];
83
84 // Optimized algorithm that skips the zero entries of CIJ for an
85 // orthotropic material and is a few percent faster
86 // dealii::VectorizedArray<double> S[6], E[6];
87 // E[0]=strain[0][0]; E[1]=strain[1][1]; E[2]=strain[2][2];
88 // //In Voigt notation: Engineering shear strain=2*strain
89 // E[3]=strain[1][2]+strain[2][1];
90 // E[4]=strain[0][2]+strain[2][0];
91 // E[5]=strain[0][1]+strain[1][0];
92 // for (unsigned int i=0; i<3; i++){
93 // S[i]=0.0;
94 // for (unsigned int j=0; j<3; j++){
95 // S[i]+=CIJ(i,j)*E[j];
96 // }
97 // }
98 //
99 // for (unsigned int i=3; i<6; i++){
100 // S[i]=CIJ(i,i)*E[i];
101 // }
102 // R[0][0]=S[0]; R[1][1]=S[1]; R[2][2]=S[2];
103 // R[1][2]=S[3]; R[0][2]=S[4]; R[0][1]=S[5];
104 // R[2][1]=S[3]; R[2][0]=S[4]; R[1][0]=S[5];
105 }
106 else if (dim == 2)
107 {
108 dealii::VectorizedArray<double> S[3], E[3];
109 E[0] = strain[0][0];
110 E[1] = strain[1][1];
111 // In Voigt notation: Engineering shear strain=2*strain
112 E[2] = strain[0][1] + strain[1][0];
113 for (unsigned int i = 0; i < 3; i++)
114 {
115 S[i] = 0.0;
116 for (unsigned int j = 0; j < 3; j++)
117 {
118 S[i] += CIJ(i, j) * E[j];
119 }
120 }
121 R[0][0] = S[0];
122 R[1][1] = S[1];
123 R[0][1] = S[2];
124 R[1][0] = S[2];
125 }
126 else
127 {
128 dealii::VectorizedArray<double> S[1], E[1];
129 E[0] = strain[0][0];
130 S[0] = CIJ(0, 0) * E[0];
131 R[0][0] = S[0];
132 }
133}
134
135// Overloaded function where CIJ, the strain, and the stress are all vectorized
136// arrays
137template <int dim>
138void
139computeStress(
140 const dealii::VectorizedArray<double> CIJ[2 * dim - 1 + dim / 3][2 * dim - 1 + dim / 3],
141 const dealii::VectorizedArray<double> strain[][dim],
142 dealii::VectorizedArray<double> R[][dim])
143{
144 if (dim == 3)
145 {
146 dealii::VectorizedArray<double> S[6], E[6];
147 E[0] = strain[0][0];
148 E[1] = strain[1][1];
149 E[2] = strain[2][2];
150 // In Voigt notation: Engineering shear strain=2*strain
151 E[3] = strain[1][2] + strain[2][1];
152 E[4] = strain[0][2] + strain[2][0];
153 E[5] = strain[0][1] + strain[1][0];
154 for (unsigned int i = 0; i < 6; i++)
155 {
156 S[i] = 0.0;
157 for (unsigned int j = 0; j < 6; j++)
158 {
159 S[i] += CIJ[i][j] * E[j];
160 }
161 }
162 R[0][0] = S[0];
163 R[1][1] = S[1];
164 R[2][2] = S[2];
165 R[1][2] = S[3];
166 R[0][2] = S[4];
167 R[0][1] = S[5];
168 R[2][1] = S[3];
169 R[2][0] = S[4];
170 R[1][0] = S[5];
171 }
172 else if (dim == 2)
173 {
174 dealii::VectorizedArray<double> S[3], E[3];
175 E[0] = strain[0][0];
176 E[1] = strain[1][1];
177 // In Voigt notation: Engineering shear strain=2*strain
178 E[2] = strain[0][1] + strain[1][0];
179 for (unsigned int i = 0; i < 3; i++)
180 {
181 S[i] = 0.0;
182 for (unsigned int j = 0; j < 3; j++)
183 {
184 S[i] += CIJ[i][j] * E[j];
185 }
186 }
187 R[0][0] = S[0];
188 R[1][1] = S[1];
189 R[0][1] = S[2];
190 R[1][0] = S[2];
191 }
192 else
193 {
194 dealii::VectorizedArray<double> S[1], E[1];
195 E[0] = strain[0][0];
196 S[0] = CIJ[0][0] * E[0];
197 R[0][0] = S[0];
198 }
199}
200
201// Overloaded function where CIJ is stored as a tensor and the strain and stress
202// are vectorized arrays
203template <int dim>
204void
205computeStress(
206 const dealii::Tensor<2, 2 * dim - 1 + dim / 3, dealii::VectorizedArray<double>> &CIJ,
207 const dealii::VectorizedArray<double> strain[][dim],
208 dealii::VectorizedArray<double> R[][dim])
209{
210 if (dim == 3)
211 {
212 dealii::VectorizedArray<double> S[6], E[6];
213 E[0] = strain[0][0];
214 E[1] = strain[1][1];
215 E[2] = strain[2][2];
216 // In Voigt notation: Engineering shear strain=2*strain
217 E[3] = strain[1][2] + strain[2][1];
218 E[4] = strain[0][2] + strain[2][0];
219 E[5] = strain[0][1] + strain[1][0];
220 for (unsigned int i = 0; i < 6; i++)
221 {
222 S[i] = 0.0;
223 for (unsigned int j = 0; j < 6; j++)
224 {
225 S[i] += CIJ[i][j] * E[j];
226 }
227 }
228 R[0][0] = S[0];
229 R[1][1] = S[1];
230 R[2][2] = S[2];
231 R[1][2] = S[3];
232 R[0][2] = S[4];
233 R[0][1] = S[5];
234 R[2][1] = S[3];
235 R[2][0] = S[4];
236 R[1][0] = S[5];
237 }
238 else if (dim == 2)
239 {
240 dealii::VectorizedArray<double> S[3], E[3];
241 E[0] = strain[0][0];
242 E[1] = strain[1][1];
243 // In Voigt notation: Engineering shear strain=2*strain
244 E[2] = strain[0][1] + strain[1][0];
245 for (unsigned int i = 0; i < 3; i++)
246 {
247 S[i] = 0.0;
248 for (unsigned int j = 0; j < 3; j++)
249 {
250 S[i] += CIJ[i][j] * E[j];
251 }
252 }
253 R[0][0] = S[0];
254 R[1][1] = S[1];
255 R[0][1] = S[2];
256 R[1][0] = S[2];
257 }
258 else
259 {
260 dealii::VectorizedArray<double> S[1], E[1];
261 E[0] = strain[0][0];
262 S[0] = CIJ[0][0] * E[0];
263 R[0][0] = S[0];
264 }
265}
266
267// Overloaded function where CIJ, the strain, and the stress are all stored as
268// tensors
269template <int dim>
270void
271computeStress(
272 const dealii::Tensor<2, 2 * dim - 1 + dim / 3, dealii::VectorizedArray<double>> &CIJ,
273 const dealii::Tensor<2, dim, dealii::VectorizedArray<double>> strain,
274 dealii::Tensor<2, dim, dealii::VectorizedArray<double>> &R)
275{
276 dealii::Tensor<1, 2 * dim - 1 + dim / 3, dealii::VectorizedArray<double>> S, E;
277
278 if (dim == 3)
279 {
280 E[0] = strain[0][0];
281 E[1] = strain[1][1];
282 E[2] = strain[2][2];
283 // In Voigt notation: Engineering shear strain=2*strain
284 E[3] = strain[1][2] + strain[2][1];
285 E[4] = strain[0][2] + strain[2][0];
286 E[5] = strain[0][1] + strain[1][0];
287
288 // Multiply CIJ and E (in the language of Deal.II this is a tensor
289 // contraction) to get S
290 S = CIJ * E;
291
292 R[0][0] = S[0];
293 R[1][1] = S[1];
294 R[2][2] = S[2];
295 R[1][2] = S[3];
296 R[0][2] = S[4];
297 R[0][1] = S[5];
298 R[2][1] = S[3];
299 R[2][0] = S[4];
300 R[1][0] = S[5];
301 }
302 else if (dim == 2)
303 {
304 E[0] = strain[0][0];
305 E[1] = strain[1][1];
306 // In Voigt notation: Engineering shear strain=2*strain
307 E[2] = strain[0][1] + strain[1][0];
308
309 // Multiply CIJ and E (in the language of Deal.II this is a tensor
310 // contraction) to get S
311 S = CIJ * E;
312
313 R[0][0] = S[0];
314 R[1][1] = S[1];
315 R[0][1] = S[2];
316 R[1][0] = S[2];
317 }
318 else
319 {
320 R[0][0] = CIJ[0][0] * strain[0][0];
321 }
322}
323
324// Overloaded function where CIJ is a table and the strain and the stress are
325// stored as tensors
326template <int dim>
327void
328computeStress(const dealii::Table<2, double> &CIJ,
329 const dealii::Tensor<2, dim, dealii::VectorizedArray<double>> &strain,
330 dealii::Tensor<2, dim, dealii::VectorizedArray<double>> &R)
331{
332 if (dim == 3)
333 {
334 dealii::VectorizedArray<double> S[6], E[6];
335 E[0] = strain[0][0];
336 E[1] = strain[1][1];
337 E[2] = strain[2][2];
338 // In Voigt notation: Engineering shear strain=2*strain
339 E[3] = strain[1][2] + strain[2][1];
340 E[4] = strain[0][2] + strain[2][0];
341 E[5] = strain[0][1] + strain[1][0];
342 for (unsigned int i = 0; i < 6; i++)
343 {
344 S[i] = 0.0;
345 for (unsigned int j = 0; j < 6; j++)
346 {
347 S[i] += CIJ(i, j) * E[j];
348 }
349 }
350 R[0][0] = S[0];
351 R[1][1] = S[1];
352 R[2][2] = S[2];
353 R[1][2] = S[3];
354 R[0][2] = S[4];
355 R[0][1] = S[5];
356 R[2][1] = S[3];
357 R[2][0] = S[4];
358 R[1][0] = S[5];
359 }
360 else if (dim == 2)
361 {
362 dealii::VectorizedArray<double> S[3], E[3];
363 E[0] = strain[0][0];
364 E[1] = strain[1][1];
365 // In Voigt notation: Engineering shear strain=2*strain
366 E[2] = strain[0][1] + strain[1][0];
367 for (unsigned int i = 0; i < 3; i++)
368 {
369 S[i] = 0.0;
370 for (unsigned int j = 0; j < 3; j++)
371 {
372 S[i] += CIJ[i][j] * E[j];
373 }
374 }
375 R[0][0] = S[0];
376 R[1][1] = S[1];
377 R[0][1] = S[2];
378 R[1][0] = S[2];
379 }
380 else
381 {
382 dealii::VectorizedArray<double> S[1], E[1];
383 E[0] = strain[0][0];
384 S[0] = CIJ[0][0] * E[0];
385 R[0][0] = S[0];
386 }
387}
388
389#endif