suanPan
shape.h
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (C) 2017-2023 Theodore Chang
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  ******************************************************************************/
29 #ifndef SHAPE_H
30 #define SHAPE_H
31 
32 #include <suanPan.h>
33 
34 namespace interpolation {
35  template<typename T> Row<T> linear(const T X, const T Y) { return {1., X, Y, X * Y}; }
36 
37  template<typename T> Row<T> linear(const T X, const T Y, const T Z) { return {1., X, Y, Z, X * Y, Y * Z, Z * X}; }
38 
39  template<typename T> Row<T> linear(const Col<T>& C) { return C.size() == 2 ? linear(C(0), C(1)) : linear(C(0), C(1), C(2)); }
40 
41  template<typename T> Row<T> quadratic(const T X, const T Y) { return {1., X, Y, X * X, X * Y, Y * Y, X * X * Y, X * Y * Y, X * X * Y * Y}; }
42 
43  template<typename T> Row<T> quadratic(const Col<T>& C) { return quadratic(C(0), C(1)); }
44 
45  template<typename T> Row<T> cubic(const T X, const T Y) { return {1., X, Y, X * X, X * Y, Y * Y, X * X * X, X * X * Y, X * Y * Y, Y * Y * Y}; }
46 
47  template<typename T> Row<T> cubic(const Col<T>& C) { return cubic(C(0), C(1)); }
48 } // namespace interpolation
49 
50 namespace area {
51  template<typename T> T triangle(const Mat<T>& EC);
52 
53  template<typename T> T shoelace(const Mat<T>& C);
54 } // namespace area
55 
56 namespace shape {
57  template<typename T> Mat<T> truss(T int_pts, unsigned order = 0, unsigned num_node = 2);
58  template<typename T> Col<T> beam(T int_pts, unsigned order, double length);
59  template<typename T> Mat<T> triangle(const Col<T>& int_pts, unsigned order);
60  template<typename T> Mat<T> quad(const Mat<T>& int_pts, unsigned order, unsigned num_node = 4);
61  template<typename T> Mat<T> cube(const Mat<T>& int_pts, unsigned order, unsigned num_node = 8);
62 
63  namespace plate {
64  template<typename T> Mat<T> triangle(const Col<T>& int_pts, unsigned order, unsigned num_node, const Mat<T>& nodes);
65  template<typename T> Mat<T> quad(const Col<T>& int_pts, unsigned order, unsigned num_node = 4);
66  } // namespace plate
67 
68  template<typename T> Mat<T> stress(T X, T Y, unsigned S);
69 
70  template<typename T> Mat<T> stress(const Col<T>& C, unsigned S);
71  template<typename T> Mat<T> stress5(const Col<T>& C);
72  template<typename T> Mat<T> stress7(const Col<T>& C);
73  template<typename T> Mat<T> stress9(const Col<T>& C);
74  template<typename T> Mat<T> stress11(const Col<T>& C);
75 
76  template<typename T> Mat<T> stress5(T X, T Y);
77  template<typename T> Mat<T> stress7(T X, T Y);
78  template<typename T> Mat<T> stress9(T X, T Y);
79  template<typename T> Mat<T> stress11(T X, T Y);
80 
81  inline mat stress5(const vec& C);
82  inline mat stress7(const vec& C);
83  inline mat stress9(const vec& C);
84  inline mat stress11(const vec& C);
85 
86  template<typename T> Mat<T> strain(T X, T Y, T V, unsigned S);
87 
88  template<typename T> Mat<T> strain(const Col<T>& C, T V, unsigned S);
89  template<typename T> Mat<T> strain5(T X, T Y, T V);
90  template<typename T> Mat<T> strain7(T X, T Y, T V);
91  template<typename T> Mat<T> strain9(T X, T Y, T V);
92  template<typename T> Mat<T> strain11(T X, T Y, T V);
93 
94  template<typename T> Mat<T> strain5(const Col<T>& C, T V);
95  template<typename T> Mat<T> strain7(const Col<T>& C, T V);
96  template<typename T> Mat<T> strain9(const Col<T>& C, T V);
97  template<typename T> Mat<T> strain11(const Col<T>& C, T V);
98 
99  inline mat strain5(const vec& C, double V);
100  inline mat strain7(const vec& C, double V);
101  inline mat strain9(const vec& C, double V);
102  inline mat strain11(const vec& C, double V);
103 
104  template<typename T> Mat<T> linear_stress(T X, T Y);
105 } // namespace shape
106 
107 template<typename T> T area::triangle(const Mat<T>& EC) { return .5 * (EC(0, 0) * (EC(1, 1) - EC(2, 1)) + EC(1, 0) * (EC(2, 1) - EC(0, 1)) + EC(2, 0) * (EC(0, 1) - EC(1, 1))); }
108 
109 template<typename T> T area::shoelace(const Mat<T>& C) {
110  suanpan_assert([&] { if(2 != C.n_cols) throw invalid_argument("need two columns"); });
111 
112  const auto S = C.n_rows;
113  Mat<T> E = arma::resize(C, S + 1, C.n_cols);
114 
115  E.tail_rows(1) = C.head_rows(1);
116 
117  const vec& X = E.col(0);
118  const vec& Y = E.col(1);
119 
120  return .5 * fabs(arma::dot(X.head(S), Y.tail(S)) - arma::dot(X.tail(S), Y.head(S)));
121 }
122 
123 template<typename T> Mat<T> shape::truss(const T int_pts, const unsigned order, const unsigned num_node) {
124  Mat<T> N(1, num_node);
125 
126  if(const auto& X = int_pts; num_node == 2) {
127  if(order == 0) {
128  N(0, 0) = 1. - X;
129  N(0, 1) = 1. + X;
130  }
131  else N(0, 0) = -(N(0, 1) = 1.);
132  N *= .5;
133  }
134  else if(num_node == 3) {
135  if(order == 0) {
136  const auto XX = X * X;
137  N(0, 0) = .5 * (XX - X);
138  N(0, 1) = 1. - XX;
139  N(0, 2) = .5 * (XX + X);
140  }
141  else {
142  N(0, 0) = X - .5;
143  N(0, 1) = -2. * X;
144  N(0, 2) = X + .5;
145  }
146  }
147 
148  return N;
149 }
150 
151 template<typename T> Col<T> shape::beam(const T int_pts, const unsigned order, const double length) {
152  Col<T> N(4);
153 
154  const auto XP = 1. + int_pts;
155  const auto XM = 1. - int_pts;
156  const auto XPP = XP * XP;
157  const auto XMM = XM * XM;
158 
159  if(order == 0) {
160  N(0) = 2. * XMM * (XP + 1.);
161  N(1) = length * XMM * XP;
162  N(2) = 2. * XPP * (XM + 1.);
163  N(3) = length * XM * XPP;
164  }
165  else if(order == 1) {
166  N(0) = -6. * XP * XM;
167  N(1) = length * XM * (3. * int_pts + 1.);
168  N(2) = 6. * XP * XM;
169  N(3) = length * XP * (3. * int_pts - 1.);
170  }
171 
172  N *= .125;
173 
174  return N;
175 }
176 
184 template<typename T> Mat<T> shape::triangle(const Col<T>& int_pts, const unsigned order) {
185  Mat<T> N;
186 
187  if(order != 0 && order != 1) throw invalid_argument("order needs to be either 0 or 1");
188 
189  N.zeros(order + 1llu, 6);
190 
191  if(const auto &X = int_pts(0), &Y = int_pts(1); order == 0) {
192  N(0, 0) = 1.;
193  N(0, 1) = X;
194  N(0, 2) = Y;
195  N(0, 3) = X * Y;
196  N(0, 4) = X * X;
197  N(0, 5) = Y * Y;
198  }
199  else if(order == 1) {
200  N(0, 1) = N(1, 2) = 1.;
201  N(0, 4) = 2. * (N(1, 3) = X);
202  N(1, 5) = 2. * (N(0, 3) = Y);
203  }
204 
205  return N;
206 }
207 
208 template<typename T> Mat<T> shape::quad(const Mat<T>& int_pts, const unsigned order, const unsigned num_node) {
209  Mat<T> N;
210 
211  if(order != 0 && order != 1) throw invalid_argument("order needs to be either 0 or 1");
212  if(num_node < 4 || num_node > 8) throw invalid_argument("number of nodes must between 4 and 8");
213 
214  N.zeros(order + 1llu, num_node);
215 
216  const auto& X = int_pts(0);
217  const auto& Y = int_pts(1);
218 
219  if(const auto XP = 1. + X, XM = 1. - X, YP = 1. + Y, YM = 1. - Y; 8 == num_node) {
220  if(const auto XX = X * X, YY = Y * Y, XY = X * Y; 0 == order) {
221  N(0, 7) = .5 * XM * (1. - YY);
222  N(0, 6) = .5 * (1. - XX) * YP;
223  N(0, 5) = .5 * XP * (1. - YY);
224  N(0, 4) = .5 * (1. - XX) * YM;
225  N(0, 0) = .25 * XM * YM - .5 * (N(0, 4) + N(0, 7));
226  N(0, 1) = .25 * XP * YM - .5 * (N(0, 4) + N(0, 5));
227  N(0, 2) = .25 * XP * YP - .5 * (N(0, 5) + N(0, 6));
228  N(0, 3) = .25 * XM * YP - .5 * (N(0, 6) + N(0, 7));
229  }
230  else if(1 == order) {
231  const auto X2 = .5 * X;
232  const auto Y2 = .5 * Y;
233  const auto X4 = .25 * X;
234  const auto Y4 = .25 * Y;
235  const auto X24 = .25 * XX;
236  const auto Y24 = .25 * YY;
237  const auto XY2 = .5 * XY;
238  N(1, 7) = XY - Y;
239  N(1, 6) = .5 - .5 * XX;
240  N(1, 5) = -Y - XY;
241  N(1, 4) = .5 * XX - .5;
242  N(1, 3) = Y2 - X4 - XY2 + X24;
243  N(1, 2) = X4 + Y2 + XY2 + X24;
244  N(1, 1) = Y2 - X4 + XY2 - X24;
245  N(1, 0) = X4 + Y2 - XY2 - X24;
246  N(0, 7) = .5 * YY - .5;
247  N(0, 6) = -X - XY;
248  N(0, 5) = .5 - .5 * YY;
249  N(0, 4) = XY - X;
250  N(0, 3) = X2 - Y4 + XY2 - Y24;
251  N(0, 2) = X2 + Y4 + XY2 + Y24;
252  N(0, 1) = X2 - Y4 - XY2 + Y24;
253  N(0, 0) = X2 + Y4 - XY2 - Y24;
254  }
255  }
256  else {
257  if(0 == order) {
258  N(0, 3) = XM * YP;
259  N(0, 2) = XP * YP;
260  N(0, 1) = XP * YM;
261  N(0, 0) = XM * YM;
262  }
263  else if(1 == order) {
264  N(1, 1) = -(N(1, 2) = XP);
265  N(1, 0) = -(N(1, 3) = XM);
266  N(0, 3) = -(N(0, 2) = YP);
267  N(0, 0) = -(N(0, 1) = YM);
268  }
269  N *= .25;
270  if(5 <= num_node) {
271  if(0 == order) {
272  N(0, 4) = .25 * (1. - X * X) * (1. - Y);
273  N(0, 0) -= .5 * N(0, 4);
274  N(0, 1) -= .5 * N(0, 4);
275  }
276  else {
277  N(0, 4) = -.5 * X * (1. - Y);
278  N(1, 4) = -.25 * (1. - X * X);
279  N(0, 0) -= .5 * N(0, 4);
280  N(0, 1) -= .5 * N(0, 4);
281  N(1, 0) -= .5 * N(1, 4);
282  N(1, 1) -= .5 * N(1, 4);
283  }
284  }
285  if(6 <= num_node) {
286  if(0 == order) {
287  N(0, 5) = .25 * (1. - Y * Y) * (1. + X);
288  N(0, 1) -= .5 * N(0, 5);
289  N(0, 2) -= .5 * N(0, 5);
290  }
291  else {
292  N(0, 5) = .25 * (1. - Y * Y);
293  N(1, 5) = -.5 * Y * (1. + X);
294  N(0, 1) -= .5 * N(0, 5);
295  N(0, 2) -= .5 * N(0, 5);
296  N(1, 1) -= .5 * N(1, 5);
297  N(1, 2) -= .5 * N(1, 5);
298  }
299  }
300  if(7 <= num_node) {
301  if(0 == order) {
302  N(0, 6) = .25 * (1. - X * X) * (1. + Y);
303  N(0, 2) -= .5 * N(0, 6);
304  N(0, 3) -= .5 * N(0, 6);
305  }
306  else {
307  N(0, 6) = -.5 * X * (1. + Y);
308  N(1, 6) = .25 * (1. - X * X);
309  N(0, 2) -= .5 * N(0, 6);
310  N(0, 3) -= .5 * N(0, 6);
311  N(1, 2) -= .5 * N(1, 6);
312  N(1, 3) -= .5 * N(1, 6);
313  }
314  }
315  }
316 
317  return N;
318 }
319 
320 template<typename T> Mat<T> shape::cube(const Mat<T>& int_pts, const unsigned order, const unsigned num_node) {
321  Mat<T> N;
322 
323  if(order == 0) N.zeros(1, num_node);
324  else if(order == 1) N.zeros(3, num_node);
325  else throw invalid_argument("order needs to be either 0 or 1");
326 
327  const auto& X = int_pts(0);
328  const auto& Y = int_pts(1);
329  const auto& Z = int_pts(2);
330 
331  const auto XP = 1. + X;
332  const auto XM = 1. - X;
333  const auto YP = 1. + Y;
334  const auto YM = 1. - Y;
335  const auto ZP = 1. + Z;
336  const auto ZM = 1. - Z;
337 
338  if(num_node == 8) {
339  if(order == 0) {
340  N(0, 0) = XM * YM * ZM;
341  N(0, 1) = XP * YM * ZM;
342  N(0, 2) = XP * YP * ZM;
343  N(0, 3) = XM * YP * ZM;
344  N(0, 4) = XM * YM * ZP;
345  N(0, 5) = XP * YM * ZP;
346  N(0, 6) = XP * YP * ZP;
347  N(0, 7) = XM * YP * ZP;
348  }
349  else if(order == 1) {
350  N(0, 0) = -YM * ZM;
351  N(0, 1) = YM * ZM;
352  N(0, 2) = YP * ZM;
353  N(0, 3) = -YP * ZM;
354  N(0, 4) = -YM * ZP;
355  N(0, 5) = YM * ZP;
356  N(0, 6) = YP * ZP;
357  N(0, 7) = -YP * ZP;
358  N(1, 0) = -XM * ZM;
359  N(1, 1) = -XP * ZM;
360  N(1, 2) = XP * ZM;
361  N(1, 3) = XM * ZM;
362  N(1, 4) = -XM * ZP;
363  N(1, 5) = -XP * ZP;
364  N(1, 6) = XP * ZP;
365  N(1, 7) = XM * ZP;
366  N(2, 0) = -XM * YM;
367  N(2, 1) = -XP * YM;
368  N(2, 2) = -XP * YP;
369  N(2, 3) = -XM * YP;
370  N(2, 4) = XM * YM;
371  N(2, 5) = XP * YM;
372  N(2, 6) = XP * YP;
373  N(2, 7) = XM * YP;
374  }
375  N *= .125;
376 
377  return N;
378  }
379 
380  if(num_node == 20) {
381  if(const auto XX = XP * XM, YY = YP * YM, ZZ = ZP * ZM; order == 0) {
382  N(0, 0) = .125 * XM * YM * ZM * (-2. - X - Y - Z);
383  N(0, 1) = .125 * XP * YM * ZM * (-2. + X - Y - Z);
384  N(0, 2) = .125 * XP * YP * ZM * (-2. + X + Y - Z);
385  N(0, 3) = .125 * XM * YP * ZM * (-2. - X + Y - Z);
386  N(0, 4) = .125 * XM * YM * ZP * (-2. - X - Y + Z);
387  N(0, 5) = .125 * XP * YM * ZP * (-2. + X - Y + Z);
388  N(0, 6) = .125 * XP * YP * ZP * (-2. + X + Y + Z);
389  N(0, 7) = .125 * XM * YP * ZP * (-2. - X + Y + Z);
390  N(0, 8) = .25 * XX * YM * ZM;
391  N(0, 9) = .25 * YY * XP * ZM;
392  N(0, 10) = .25 * XX * YP * ZM;
393  N(0, 11) = .25 * YY * XM * ZM;
394  N(0, 12) = .25 * XX * YM * ZP;
395  N(0, 13) = .25 * YY * XP * ZP;
396  N(0, 14) = .25 * XX * YP * ZP;
397  N(0, 15) = .25 * YY * XM * ZP;
398  N(0, 16) = .25 * ZZ * XM * YM;
399  N(0, 17) = .25 * ZZ * XP * YM;
400  N(0, 18) = .25 * ZZ * XP * YP;
401  N(0, 19) = .25 * ZZ * XM * YP;
402  }
403  else if(order == 1) {
404  N(0, 0) = YM * ZM * (2. * X + Y + Z + 1.) * .125;
405  N(0, 1) = YM * ZM * (2. * X - Y - Z - 1.) * .125;
406  N(0, 2) = YP * ZM * (2. * X + Y - Z - 1.) * .125;
407  N(0, 3) = YP * ZM * (2. * X - Y + Z + 1.) * .125;
408  N(0, 4) = YM * ZP * (2. * X + Y - Z + 1.) * .125;
409  N(0, 5) = YM * ZP * (2. * X - Y + Z - 1.) * .125;
410  N(0, 6) = YP * ZP * (2. * X + Y + Z - 1.) * .125;
411  N(0, 7) = YP * ZP * (2. * X - Y - Z + 1.) * .125;
412  N(1, 0) = XM * ZM * (2. * Y + X + Z + 1.) * .125;
413  N(1, 1) = XP * ZM * (2. * Y - X + Z + 1.) * .125;
414  N(1, 2) = XP * ZM * (2. * Y + X - Z - 1.) * .125;
415  N(1, 3) = XM * ZM * (2. * Y - X - Z - 1.) * .125;
416  N(1, 4) = XM * ZP * (2. * Y + X - Z + 1.) * .125;
417  N(1, 5) = XP * ZP * (2. * Y - X - Z + 1.) * .125;
418  N(1, 6) = XP * ZP * (2. * Y + X + Z - 1.) * .125;
419  N(1, 7) = XM * ZP * (2. * Y - X + Z - 1.) * .125;
420  N(2, 0) = XM * YM * (2. * Z + X + Y + 1.) * .125;
421  N(2, 1) = XP * YM * (2. * Z + Y - X + 1.) * .125;
422  N(2, 2) = XP * YP * (2. * Z - X - Y + 1.) * .125;
423  N(2, 3) = XM * YP * (2. * Z + X - Y + 1.) * .125;
424  N(2, 4) = XM * YM * (2. * Z - X - Y - 1.) * .125;
425  N(2, 5) = XP * YM * (2. * Z + X - Y - 1.) * .125;
426  N(2, 6) = XP * YP * (2. * Z + X + Y - 1.) * .125;
427  N(2, 7) = XM * YP * (2. * Z - X + Y - 1.) * .125;
428 
429  N(0, 8) = -X * YM * ZM * .5;
430  N(0, 9) = YY * ZM * .25;
431  N(0, 10) = -X * YP * ZM * .5;
432  N(0, 11) = -YY * ZM * .25;
433  N(1, 8) = -XX * ZM * .25;
434  N(1, 9) = -Y * XP * ZM * .5;
435  N(1, 10) = XX * ZM * .25;
436  N(1, 11) = -Y * XM * ZM * .5;
437  N(2, 8) = -XX * YM * .25;
438  N(2, 9) = -XP * YY * .25;
439  N(2, 10) = -XX * YP * .25;
440  N(2, 11) = -XM * YY * .25;
441 
442  N(0, 12) = -X * YM * ZP * .5;
443  N(0, 13) = YY * ZP * .25;
444  N(0, 14) = -X * YP * ZP * .5;
445  N(0, 15) = -YY * ZP * .25;
446  N(1, 12) = -XX * ZP * .25;
447  N(1, 13) = -Y * XP * ZP * .5;
448  N(1, 14) = XX * ZP * .25;
449  N(1, 15) = -Y * XM * ZP * .5;
450  N(2, 12) = XX * YM * .25;
451  N(2, 13) = XP * YY * .25;
452  N(2, 14) = XX * YP * .25;
453  N(2, 15) = XM * YY * .25;
454 
455  N(0, 16) = -YM * ZZ * .25;
456  N(0, 17) = YM * ZZ * .25;
457  N(0, 18) = YP * ZZ * .25;
458  N(0, 19) = -YP * ZZ * .25;
459  N(1, 16) = -XM * ZZ * .25;
460  N(1, 17) = -XP * ZZ * .25;
461  N(1, 18) = XP * ZZ * .25;
462  N(1, 19) = XM * ZZ * .25;
463  N(2, 16) = -Z * XM * YM * .5;
464  N(2, 17) = -Z * XP * YM * .5;
465  N(2, 18) = -Z * XP * YP * .5;
466  N(2, 19) = -Z * XM * YP * .5;
467  }
468 
469  return N;
470  }
471 
472  throw invalid_argument("not supported");
473 }
474 
475 template<typename T> Mat<T> shape::stress(const T X, const T Y, const unsigned S) {
476  Mat<T> N = zeros(3, S);
477 
478  for(auto I = 0; I < 3; ++I) N(I, I) = 1.;
479 
480  if(S >= 5) {
481  N(0, 4) = Y;
482  N(1, 3) = X;
483  if(S >= 7) {
484  N(2, 5) = -(N(0, 6) = X);
485  N(2, 6) = -(N(1, 5) = Y);
486  if(S >= 9) {
487  const auto X2 = X * X;
488  const auto Y2 = Y * Y;
489  const auto XY = X * Y;
490  N(1, 7) = N(0, 8) = 2. * XY;
491  N(2, 7) = -X2;
492  N(2, 8) = -Y2;
493  if(S == 11) {
494  N(1, 9) = 2. * X2 + (N(1, 10) = -Y2);
495  N(0, 10) = 2. * Y2 + (N(0, 9) = -X2);
496  N(2, 10) = N(2, 9) = 2. * XY;
497  }
498  }
499  }
500  }
501 
502  return N;
503 }
504 
505 template<typename T> Mat<T> shape::stress(const Col<T>& C, const unsigned S) { return stress(C(0), C(1), S); }
506 
507 template<typename T> Mat<T> shape::stress5(const Col<T>& C) { return stress(C, 5); }
508 
509 template<typename T> Mat<T> shape::stress7(const Col<T>& C) { return stress(C, 7); }
510 
511 template<typename T> Mat<T> shape::stress9(const Col<T>& C) { return stress(C, 9); }
512 
513 template<typename T> Mat<T> shape::stress11(const Col<T>& C) { return stress(C, 11); }
514 
515 template<typename T> Mat<T> shape::stress5(const T X, const T Y) { return stress(X, Y, 5); }
516 
517 template<typename T> Mat<T> shape::stress7(const T X, const T Y) { return stress(X, Y, 7); }
518 
519 template<typename T> Mat<T> shape::stress9(const T X, const T Y) { return stress(X, Y, 9); }
520 
521 template<typename T> Mat<T> shape::stress11(const T X, const T Y) { return stress(X, Y, 11); }
522 
523 template<typename T> Mat<T> shape::strain(const T X, const T Y, const T V, const unsigned S) {
524  Mat<T> N(3, S, fill::zeros);
525 
526  N(0, 0) = N(1, 1) = 1.;
527 
528  N(2, 2) = 2. + 2. * V;
529 
530  N(0, 1) = N(1, 0) = -V;
531 
532  if(S >= 5) {
533  N(0, 3) = -V * (N(1, 3) = X);
534  N(1, 4) = -V * (N(0, 4) = Y);
535  if(S >= 7) {
536  N(0, 5) = N(1, 4);
537  N(0, 6) = N(1, 3);
538 
539  N(1, 5) = N(0, 4);
540  N(1, 6) = N(0, 3);
541 
542  N(2, 5) = -X * N(2, 2);
543  N(2, 6) = -Y * N(2, 2);
544  if(S >= 9) {
545  const auto X2 = X * X, Y2 = Y * Y, XY = X * Y;
546 
547  N(1, 8) = N(0, 7) = -V * (N(1, 7) = N(0, 8) = 2. * XY);
548 
549  N(2, 7) = -X2 * N(2, 2);
550  N(2, 8) = -Y2 * N(2, 2);
551  if(S == 11) {
552  N(0, 9) = V * Y2 - (2. * V + 1.) * X2;
553  N(1, 9) = (2. + V) * X2 - Y2;
554 
555  N(0, 10) = (2. + V) * Y2 - X2;
556  N(1, 10) = V * X2 - (2. * V + 1.) * Y2;
557 
558  N(2, 10) = N(2, 9) = 2. * XY * N(2, 2);
559  }
560  }
561  }
562  }
563 
564  return N;
565 }
566 
567 template<typename T> Mat<T> shape::strain(const Col<T>& C, const T V, const unsigned S) { return strain(C(0), C(1), V, S); }
568 
569 template<typename T> Mat<T> shape::strain5(const T X, const T Y, const T V) { return strain(X, Y, V, 5); }
570 
571 template<typename T> Mat<T> shape::strain7(const T X, const T Y, const T V) { return strain(X, Y, V, 7); }
572 
573 template<typename T> Mat<T> shape::strain9(const T X, const T Y, const T V) { return strain(X, Y, V, 9); }
574 
575 template<typename T> Mat<T> shape::strain11(const T X, const T Y, const T V) { return strain(X, Y, V, 11); }
576 
577 template<typename T> Mat<T> shape::strain5(const Col<T>& C, const T V) { return strain(C, V, 5); }
578 
579 template<typename T> Mat<T> shape::strain7(const Col<T>& C, const T V) { return strain(C, V, 7); }
580 
581 template<typename T> Mat<T> shape::strain9(const Col<T>& C, const T V) { return strain(C, V, 9); }
582 
583 template<typename T> Mat<T> shape::strain11(const Col<T>& C, const T V) { return strain(C, V, 11); }
584 
585 template<typename T> Mat<T> shape::linear_stress(T X, T Y) {
586  Mat<T> N = eye(3, 9);
587  N.cols(3, 5) = X * eye(3, 3);
588  N.cols(6, 8) = Y * eye(3, 3);
589 
590  return N;
591 }
592 
593 template<typename T> Mat<T> shape::plate::triangle(const Col<T>& int_pts, const unsigned order, const unsigned num_node, const Mat<T>& nodes) {
594  suanpan_assert([&] { if(order > 1 || (num_node != 3 && num_node != 6) || (nodes.n_cols != 2) || nodes.n_rows < 3) throw invalid_argument("not supported"); });
595 
596  Mat<T> N;
597 
598  if(order == 0) N.zeros(1, 3llu * num_node);
599  else if(order == 1) N.zeros(3, 3llu * num_node);
600  else throw invalid_argument("order needs to be either 0 or 1");
601 
602  Mat<T> TEMP(3, 3);
603  TEMP.row(0).fill(1.);
604  TEMP.rows(1, 2) = nodes.rows(0, 2).t();
605 
606  const Mat<T> A = inv(TEMP);
607  const Col<T> W = solve(TEMP, vec{1., int_pts(0), int_pts(1)});
608 
609  const vec L = std::initializer_list<double>{W(0), W(1), W(2), W(0), W(1)};
610  const vec B = std::initializer_list<double>{A(0, 1), A(1, 1), A(2, 1), A(0, 1), A(1, 1)};
611  const vec C = std::initializer_list<double>{A(0, 2), A(1, 2), A(2, 2), A(0, 2), A(1, 2)};
612 
613  const auto DA = A.cols(1, 2);
614 
615  if(3 == num_node) {
616  if(0 == order) {
617  auto IDX = 0;
618  for(auto I = 0; I < 3; ++I) {
619  const auto J = I + 1;
620  const auto K = J + 1;
621  N(IDX++) = L(I) * (1. - L(J) * L(J) - L(K) * L(K)) + L(I) * L(I) * (L(J) + L(K));
622  N(IDX++) = B(J) * L(I) * L(K) * (L(I) + .5 * L(J)) - B(K) * L(I) * L(J) * (L(I) + .5 * L(K));
623  N(IDX++) = C(J) * L(I) * L(K) * (L(I) + .5 * L(J)) - C(K) * L(I) * L(J) * (L(I) + .5 * L(K));
624  }
625  }
626  else {
627  mat DNDL(3, 3);
628  auto IDX = 0;
629  for(auto I = 0; I < 3; ++I) {
630  const auto J = I + 1;
631  const auto K = J + 1;
632 
633  DNDL(0, 0) = L(J) + L(K);
634  DNDL(1, 1) = DNDL(2, 2) = -L(I);
635  DNDL(0, 1) = DNDL(1, 0) = L(I) - L(J);
636  DNDL(0, 2) = DNDL(2, 0) = L(I) - L(K);
637  DNDL(1, 2) = DNDL(2, 1) = 0.;
638 
639  mat DD = DA.t() * DNDL * DA;
640 
641  N(0, IDX) = -2. * DD(0, 0);
642  N(1, IDX) = -2. * DD(1, 1);
643  N(2, IDX++) = -2. * (DD(0, 1) + DD(1, 0));
644 
645  DNDL(0, 0) = 4. * (B(J) * L(K) - B(K) * L(J));
646  DNDL(1, 1) = DNDL(2, 2) = 0.;
647  DNDL(0, 1) = DNDL(1, 0) = (B(J) - B(K)) * L(K) - 4 * B(K) * L(I);
648  DNDL(0, 2) = DNDL(2, 0) = 4. * B(J) * L(I) + (B(J) - B(K)) * L(J);
649  DNDL(1, 2) = DNDL(2, 1) = L(I) * (B(J) - B(K));
650 
651  DD = DA.t() * DNDL * DA;
652 
653  N(0, IDX) = -.5 * DD(0, 0);
654  N(1, IDX) = -.5 * DD(1, 1);
655  N(2, IDX++) = -.5 * (DD(0, 1) + DD(1, 0));
656 
657  DNDL(0, 0) = 4. * (C(J) * L(K) - C(K) * L(J));
658  DNDL(0, 1) = DNDL(1, 0) = (C(J) - C(K)) * L(K) - 4 * C(K) * L(I);
659  DNDL(0, 2) = DNDL(2, 0) = 4. * C(J) * L(I) + (C(J) - C(K)) * L(J);
660  DNDL(1, 2) = DNDL(2, 1) = L(I) * (C(J) - C(K));
661 
662  DD = DA.t() * DNDL * DA;
663 
664  N(0, IDX) = -.5 * DD(0, 0);
665  N(1, IDX) = -.5 * DD(1, 1);
666  N(2, IDX++) = -.5 * (DD(0, 1) + DD(1, 0));
667  }
668  }
669  }
670 
671  return N;
672 }
673 
674 template<typename T> Mat<T> shape::plate::quad(const Col<T>& int_pts, const unsigned order, const unsigned num_node) {
675  Mat<T> N;
676 
677  if(order == 0) N.zeros(1, 3llu * num_node);
678  else if(order == 1) N.zeros(2, 6llu * num_node);
679  else throw invalid_argument("order needs to be either 0 or 1");
680 
681  const auto& X = int_pts(0);
682  const auto& Y = int_pts(1);
683 
684  return N;
685 }
686 
687 mat shape::stress5(const vec& C) { return stress(C, 5); }
688 
689 mat shape::stress7(const vec& C) { return stress(C, 7); }
690 
691 mat shape::stress9(const vec& C) { return stress(C, 9); }
692 
693 mat shape::stress11(const vec& C) { return stress(C, 11); }
694 
695 mat shape::strain5(const vec& C, const double V) { return strain(C, V, 5); }
696 
697 mat shape::strain7(const vec& C, const double V) { return strain(C, V, 7); }
698 
699 mat shape::strain9(const vec& C, const double V) { return strain(C, V, 9); }
700 
701 mat shape::strain11(const vec& C, const double V) { return strain(C, V, 11); }
702 
703 #endif
704 
Mat< T > strain9(T X, T Y, T V)
Definition: shape.h:573
Mat< T > quad(const Mat< T > &int_pts, unsigned order, unsigned num_node=4)
Definition: shape.h:208
Mat< T > stress(T X, T Y, unsigned S)
Definition: shape.h:475
Mat< T > strain(T X, T Y, T V, unsigned S)
Definition: shape.h:523
Mat< T > strain(const Col< T > &C, T V, unsigned S)
Definition: shape.h:567
Mat< T > stress7(const Col< T > &C)
Definition: shape.h:509
Mat< T > triangle(const Col< T > &int_pts, unsigned order)
compute the shape function or its derivative of six node triangle in global coordinate system
Definition: shape.h:184
Col< T > beam(T int_pts, unsigned order, double length)
Definition: shape.h:151
T shoelace(const Mat< T > &C)
Definition: shape.h:109
T triangle(const Mat< T > &EC)
Definition: shape.h:107
Mat< T > strain5(T X, T Y, T V)
Definition: shape.h:569
Mat< T > truss(T int_pts, unsigned order=0, unsigned num_node=2)
Definition: shape.h:123
Mat< T > stress5(const Col< T > &C)
Definition: shape.h:507
Mat< T > linear_stress(T X, T Y)
Definition: shape.h:585
Mat< T > quad(const Col< T > &int_pts, unsigned order, unsigned num_node=4)
Definition: shape.h:674
Mat< T > stress9(const Col< T > &C)
Definition: shape.h:511
Mat< T > strain11(T X, T Y, T V)
Definition: shape.h:575
Mat< T > cube(const Mat< T > &int_pts, unsigned order, unsigned num_node=8)
Definition: shape.h:320
Mat< T > stress11(const Col< T > &C)
Definition: shape.h:513
Mat< T > stress(const Col< T > &C, unsigned S)
Definition: shape.h:505
Mat< T > triangle(const Col< T > &int_pts, unsigned order, unsigned num_node, const Mat< T > &nodes)
Definition: shape.h:593
Mat< T > strain7(T X, T Y, T V)
Definition: shape.h:571
Definition: shape.h:50
Definition: shape.h:34
Row< T > cubic(const T X, const T Y)
Definition: shape.h:45
Row< T > linear(const T X, const T Y)
Definition: shape.h:35
Row< T > quadratic(const T X, const T Y)
Definition: shape.h:41
Definition: shape.h:56
void suanpan_assert(const std::function< void()> &F)
Definition: suanPan.h:284