SecondOrderFunctions.h
Go to the documentation of this file.
1 //
2 // This file is part of the FFEA simulation package
3 //
4 // Copyright (c) by the Theory and Development FFEA teams,
5 // as they appear in the README.md file.
6 //
7 // FFEA is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // FFEA is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with FFEA. If not, see <http://www.gnu.org/licenses/>.
19 //
20 // To help us fund FFEA development, we humbly ask that you cite
21 // the research papers on the package.
22 //
23 
24 #ifndef SECONDORDERFUNCTIONS_H_INCLUDED
25 #define SECONDORDERFUNCTIONS_H_INCLUDED
26 
27 #define GRAD_PSI_1 0
28 #define GRAD_PSI_2 1
29 #define GRAD_PSI_3 2
30 #define GRAD_PSI_4 3
31 #define GRAD_PSI_5 4
32 #define GRAD_PSI_6 5
33 #define GRAD_PSI_7 6
34 #define GRAD_PSI_8 7
35 #define GRAD_PSI_9 8
36 #define GRAD_PSI_10 9
37 
38 #define DS_BY_DX 0
39 #define DT_BY_DX 1
40 #define DU_BY_DX 2
41 #define DS_BY_DY 3
42 #define DT_BY_DY 4
43 #define DU_BY_DY 5
44 #define DS_BY_DZ 6
45 #define DT_BY_DZ 7
46 #define DU_BY_DZ 8
47 
48 
49 #include "mesh_node.h"
50 
51 namespace SecondOrderFunctions {
52 
53  struct stu {
54  scalar s, t, u;
55  };
56 
57  struct abcd {
58  scalar a, b, c, d;
59  };
60 
61  static stu stu_lookup[10] ={
62  {0, 0, 0},
63  {1, 0, 0},
64  {0, 1, 0},
65  {0, 0, 1},
66  {.5, 0, 0},
67  {0, .5, 0},
68  {0, 0, .5},
69  {.5, .5, 0},
70  {.5, 0, .5},
71  {0, .5, .5}
72  };
73 
74  static void calc_psi(scalar psi[10], scalar s, scalar t, scalar u) {
75  scalar r = 1 - s - t - u;
76  psi[0] = (2 * r - 1) * r;
77  psi[1] = (2 * s - 1) * s;
78  psi[2] = (2 * t - 1) * t;
79  psi[3] = (2 * u - 1) * u;
80  psi[4] = 4 * r * s;
81  psi[5] = 4 * r * t;
82  psi[6] = 4 * r * u;
83  psi[7] = 4 * s * t;
84  psi[8] = 4 * s * u;
85  psi[9] = 4 * t * u;
86  }
87 
88  static void calc_grad_psi(vector3 grad_psi[10], scalar s, scalar t, scalar u, scalar J_inv[9]) {
89  scalar dpsi1_by_dstu = 4 * (s + t + u) - 3;
90  grad_psi[GRAD_PSI_1].x = dpsi1_by_dstu * (J_inv[DS_BY_DX] + J_inv[DT_BY_DX] + J_inv[DU_BY_DX]);
91  grad_psi[GRAD_PSI_1].y = dpsi1_by_dstu * (J_inv[DS_BY_DY] + J_inv[DT_BY_DY] + J_inv[DU_BY_DY]);
92  grad_psi[GRAD_PSI_1].z = dpsi1_by_dstu * (J_inv[DS_BY_DZ] + J_inv[DT_BY_DZ] + J_inv[DU_BY_DZ]);
93 
94  scalar dpsi2_by_ds = 4 * s - 1;
95  grad_psi[GRAD_PSI_2].x = dpsi2_by_ds * J_inv[DS_BY_DX];
96  grad_psi[GRAD_PSI_2].y = dpsi2_by_ds * J_inv[DS_BY_DY];
97  grad_psi[GRAD_PSI_2].z = dpsi2_by_ds * J_inv[DS_BY_DZ];
98 
99  scalar dpsi3_by_dt = 4 * t - 1;
100  grad_psi[GRAD_PSI_3].x = dpsi3_by_dt * J_inv[DT_BY_DX];
101  grad_psi[GRAD_PSI_3].y = dpsi3_by_dt * J_inv[DT_BY_DY];
102  grad_psi[GRAD_PSI_3].z = dpsi3_by_dt * J_inv[DT_BY_DZ];
103 
104  scalar dpsi4_by_du = 4 * u - 1;
105  grad_psi[GRAD_PSI_4].x = dpsi4_by_du * J_inv[DU_BY_DX];
106  grad_psi[GRAD_PSI_4].y = dpsi4_by_du * J_inv[DU_BY_DY];
107  grad_psi[GRAD_PSI_4].z = dpsi4_by_du * J_inv[DU_BY_DZ];
108 
109  scalar dpsi5_by_ds = 4 * (1 - 2 * s - t - u), dpsi5_by_dtu = -4 * s;
110  grad_psi[GRAD_PSI_5].x = dpsi5_by_ds * J_inv[DS_BY_DX] + dpsi5_by_dtu * (J_inv[DT_BY_DX] + J_inv[DU_BY_DX]);
111  grad_psi[GRAD_PSI_5].y = dpsi5_by_ds * J_inv[DS_BY_DY] + dpsi5_by_dtu * (J_inv[DT_BY_DY] + J_inv[DU_BY_DY]);
112  grad_psi[GRAD_PSI_5].z = dpsi5_by_ds * J_inv[DS_BY_DZ] + dpsi5_by_dtu * (J_inv[DT_BY_DZ] + J_inv[DU_BY_DZ]);
113 
114  scalar dpsi6_by_dt = 4 * (1 - s - 2 * t - u), dpsi6_by_dsu = -4 * t;
115  grad_psi[GRAD_PSI_6].x = dpsi6_by_dt * J_inv[DT_BY_DX] + dpsi6_by_dsu * (J_inv[DS_BY_DX] + J_inv[DU_BY_DX]);
116  grad_psi[GRAD_PSI_6].y = dpsi6_by_dt * J_inv[DT_BY_DY] + dpsi6_by_dsu * (J_inv[DS_BY_DY] + J_inv[DU_BY_DY]);
117  grad_psi[GRAD_PSI_6].z = dpsi6_by_dt * J_inv[DT_BY_DZ] + dpsi6_by_dsu * (J_inv[DS_BY_DZ] + J_inv[DU_BY_DZ]);
118 
119  scalar dpsi7_by_du = 4 * (1 - s - t - 2 * u), dpsi7_by_dst = -4 * u;
120  grad_psi[GRAD_PSI_7].x = dpsi7_by_du * J_inv[DU_BY_DX] + dpsi7_by_dst * (J_inv[DS_BY_DX] + J_inv[DT_BY_DX]);
121  grad_psi[GRAD_PSI_7].y = dpsi7_by_du * J_inv[DU_BY_DY] + dpsi7_by_dst * (J_inv[DS_BY_DY] + J_inv[DT_BY_DY]);
122  grad_psi[GRAD_PSI_7].z = dpsi7_by_du * J_inv[DU_BY_DZ] + dpsi7_by_dst * (J_inv[DS_BY_DZ] + J_inv[DT_BY_DZ]);
123 
124  scalar dpsi8_by_ds = 4 * t, dpsi8_by_dt = 4 * s;
125  grad_psi[GRAD_PSI_8].x = dpsi8_by_ds * J_inv[DS_BY_DX] + dpsi8_by_dt * J_inv[DT_BY_DX];
126  grad_psi[GRAD_PSI_8].y = dpsi8_by_ds * J_inv[DS_BY_DY] + dpsi8_by_dt * J_inv[DT_BY_DY];
127  grad_psi[GRAD_PSI_8].z = dpsi8_by_ds * J_inv[DS_BY_DZ] + dpsi8_by_dt * J_inv[DT_BY_DZ];
128 
129  scalar dpsi9_by_ds = 4 * u, dpsi9_by_du = 4 * s;
130  grad_psi[GRAD_PSI_9].x = dpsi9_by_ds * J_inv[DS_BY_DX] + dpsi9_by_du * J_inv[DU_BY_DX];
131  grad_psi[GRAD_PSI_9].y = dpsi9_by_ds * J_inv[DS_BY_DY] + dpsi9_by_du * J_inv[DU_BY_DY];
132  grad_psi[GRAD_PSI_9].z = dpsi9_by_ds * J_inv[DS_BY_DZ] + dpsi9_by_du * J_inv[DU_BY_DZ];
133 
134  scalar dpsi10_by_dt = 4 * u, dpsi10_by_du = 4 * t;
135  grad_psi[GRAD_PSI_10].x = dpsi10_by_dt * J_inv[DT_BY_DX] + dpsi10_by_du * J_inv[DU_BY_DX];
136  grad_psi[GRAD_PSI_10].y = dpsi10_by_dt * J_inv[DT_BY_DY] + dpsi10_by_du * J_inv[DU_BY_DY];
137  grad_psi[GRAD_PSI_10].z = dpsi10_by_dt * J_inv[DT_BY_DZ] + dpsi10_by_du * J_inv[DU_BY_DZ];
138 
139  // for(int i = 0; i < 10; i++) {
140  // printf("dpsi%d/dx = %+e\n", i + 1, grad_psi[i].x);
141  // printf("dpsi%d/dy = %+e\n", i + 1, grad_psi[i].y);
142  // printf("dpsi%d/dz = %+e\n", i + 1, grad_psi[i].z);
143  // }
144  }
145 
147  static void calc_jacobian_column_coefficients(mesh_node *n[10], abcd J_coeff[3][3]) {
148  // dx/ds
149  J_coeff[0][0].a = 4 * (n[0]->pos.x + n[1]->pos.x - 2 * n[4]->pos.x);
150  J_coeff[0][0].b = 4 * (n[0]->pos.x - n[4]->pos.x - n[5]->pos.x + n[7]->pos.x);
151  J_coeff[0][0].c = 4 * (n[0]->pos.x - n[4]->pos.x - n[6]->pos.x + n[8]->pos.x);
152  J_coeff[0][0].d = 4 * n[4]->pos.x - 3 * n[0]->pos.x - n[1]->pos.x;
153 
154  // dy/ds
155  J_coeff[1][0].a = 4 * (n[0]->pos.y + n[1]->pos.y - 2 * n[4]->pos.y);
156  J_coeff[1][0].b = 4 * (n[0]->pos.y - n[4]->pos.y - n[5]->pos.y + n[7]->pos.y);
157  J_coeff[1][0].c = 4 * (n[0]->pos.y - n[4]->pos.y - n[6]->pos.y + n[8]->pos.y);
158  J_coeff[1][0].d = 4 * n[4]->pos.y - 3 * n[0]->pos.y - n[1]->pos.y;
159 
160  // dz/ds
161  J_coeff[2][0].a = 4 * (n[0]->pos.z + n[1]->pos.z - 2 * n[4]->pos.z);
162  J_coeff[2][0].b = 4 * (n[0]->pos.z - n[4]->pos.z - n[5]->pos.z + n[7]->pos.z);
163  J_coeff[2][0].c = 4 * (n[0]->pos.z - n[4]->pos.z - n[6]->pos.z + n[8]->pos.z);
164  J_coeff[2][0].d = 4 * n[4]->pos.z - 3 * n[0]->pos.z - n[1]->pos.z;
165 
166 
167  // dx/dt
168  J_coeff[0][1].a = 4 * (n[0]->pos.x - n[4]->pos.x - n[5]->pos.x + n[7]->pos.x);
169  J_coeff[0][1].b = 4 * (n[0]->pos.x + n[2]->pos.x - 2 * n[5]->pos.x);
170  J_coeff[0][1].c = 4 * (n[0]->pos.x - n[5]->pos.x - n[6]->pos.x + n[9]->pos.x);
171  J_coeff[0][1].d = 4 * n[5]->pos.x - 3 * n[0]->pos.x - n[2]->pos.x;
172 
173  // dy/dt
174  J_coeff[1][1].a = 4 * (n[0]->pos.y - n[4]->pos.y - n[5]->pos.y + n[7]->pos.y);
175  J_coeff[1][1].b = 4 * (n[0]->pos.y + n[2]->pos.y - 2 * n[5]->pos.y);
176  J_coeff[1][1].c = 4 * (n[0]->pos.y - n[5]->pos.y - n[6]->pos.y + n[9]->pos.y);
177  J_coeff[1][1].d = 4 * n[5]->pos.y - 3 * n[0]->pos.y - n[2]->pos.y;
178 
179  // dz/dt
180  J_coeff[2][1].a = 4 * (n[0]->pos.z - n[4]->pos.z - n[5]->pos.z + n[7]->pos.z);
181  J_coeff[2][1].b = 4 * (n[0]->pos.z + n[2]->pos.z - 2 * n[5]->pos.z);
182  J_coeff[2][1].c = 4 * (n[0]->pos.z - n[5]->pos.z - n[6]->pos.z + n[9]->pos.z);
183  J_coeff[2][1].d = 4 * n[5]->pos.z - 3 * n[0]->pos.z - n[2]->pos.z;
184 
185 
186  // dx/du
187  J_coeff[0][2].a = 4 * (n[0]->pos.x - n[4]->pos.x - n[6]->pos.x + n[8]->pos.x);
188  J_coeff[0][2].b = 4 * (n[0]->pos.x - n[5]->pos.x - n[6]->pos.x + n[9]->pos.x);
189  J_coeff[0][2].c = 4 * (n[0]->pos.x + n[3]->pos.x - 2 * n[6]->pos.x);
190  J_coeff[0][2].d = 4 * n[6]->pos.x - 3 * n[0]->pos.x - n[3]->pos.x;
191 
192  // dy/du
193  J_coeff[1][2].a = 4 * (n[0]->pos.y - n[4]->pos.y - n[6]->pos.y + n[8]->pos.y);
194  J_coeff[1][2].b = 4 * (n[0]->pos.y - n[5]->pos.y - n[6]->pos.y + n[9]->pos.y);
195  J_coeff[1][2].c = 4 * (n[0]->pos.y + n[3]->pos.y - 2 * n[6]->pos.y);
196  J_coeff[1][2].d = 4 * n[6]->pos.y - 3 * n[0]->pos.y - n[3]->pos.y;
197 
198  // dz/du
199  J_coeff[2][2].a = 4 * (n[0]->pos.z - n[4]->pos.z - n[6]->pos.z + n[8]->pos.z);
200  J_coeff[2][2].b = 4 * (n[0]->pos.z - n[5]->pos.z - n[6]->pos.z + n[9]->pos.z);
201  J_coeff[2][2].c = 4 * (n[0]->pos.z + n[3]->pos.z - 2 * n[6]->pos.z);
202  J_coeff[2][2].d = 4 * n[6]->pos.z - 3 * n[0]->pos.z - n[3]->pos.z;
203  }
204 
205  static scalar calc_det_J(abcd J_coeff[3][3], scalar s, scalar t, scalar u, scalar J_inv[9]) {
206  scalar J[3][3];
207 
208  // Construct Jacobian for the part of the element at (s, t, u)
209  for (int i = 0; i < 3; i++) {
210  for (int j = 0; j < 3; j++) {
211  J[i][j] = J_coeff[i][j].a * s + J_coeff[i][j].b * t + J_coeff[i][j].c * u + J_coeff[i][j].d;
212  }
213  }
214 
215  // Invert the Jacobian and transpose it to obtain the derivatives of local coordinates wrt cartesian coords
216  J_inv[DS_BY_DX] = J[2][2] * J[1][1] - J[2][1] * J[1][2];
217  J_inv[DS_BY_DY] = J[2][1] * J[0][2] - J[2][2] * J[0][1];
218  J_inv[DS_BY_DZ] = J[1][2] * J[0][1] - J[1][1] * J[0][2];
219 
220  J_inv[DT_BY_DX] = J[2][0] * J[1][2] - J[2][2] * J[1][0];
221  J_inv[DT_BY_DY] = J[2][2] * J[0][0] - J[2][0] * J[0][2];
222  J_inv[DT_BY_DZ] = J[1][0] * J[0][2] - J[1][2] * J[0][0];
223 
224  J_inv[DU_BY_DX] = J[2][1] * J[1][0] - J[2][0] * J[1][1];
225  J_inv[DU_BY_DY] = J[2][0] * J[0][1] - J[2][1] * J[0][0];
226  J_inv[DU_BY_DZ] = J[1][1] * J[0][0] - J[1][0] * J[0][1];
227 
228  // Calculate determinant
229  scalar det = J[0][0] * J_inv[DS_BY_DX] + J[1][0] * J_inv[DS_BY_DY] + J[2][0] * J_inv[DS_BY_DZ];
230 
231  for (int i = 0; i < 9; i++) {
232  J_inv[i] /= det;
233  }
234 
235 
236  // printf("J:\n");
237  // printf("%+e %+e %+e\n", J[0][0], J[0][1], J[0][2]);
238  // printf("%+e %+e %+e\n", J[1][0], J[1][1], J[1][2]);
239  // printf("%+e %+e %+e\n", J[2][0], J[2][1], J[2][2]);
240 
241  // printf("J_inv:\n");
242  // printf("%+e %+e %+e\n", J_inv[0], J_inv[1], J_inv[2]);
243  // printf("%+e %+e %+e\n", J_inv[3], J_inv[4], J_inv[5]);
244  // printf("%+e %+e %+e\n", J_inv[6], J_inv[7], J_inv[8]);
245 
246 
247  return fabs(det);
248  }
249 
250 }
251 
252 #endif
scalar b
Definition: SecondOrderFunctions.h:58
#define DS_BY_DZ
Definition: SecondOrderFunctions.h:44
scalar t
Definition: SecondOrderFunctions.h:54
scalar u
Definition: SecondOrderFunctions.h:54
#define DS_BY_DX
Definition: SecondOrderFunctions.h:38
scalar & x
Definition: mat_vec_types.h:93
scalar d
Definition: SecondOrderFunctions.h:58
Definition: SecondOrderFunctions.h:57
scalar & y
Definition: mat_vec_types.h:94
scalar & z
Definition: mat_vec_types.h:95
#define DS_BY_DY
Definition: SecondOrderFunctions.h:41
#define GRAD_PSI_2
Definition: SecondOrderFunctions.h:28
#define GRAD_PSI_10
Definition: SecondOrderFunctions.h:36
#define DU_BY_DX
Definition: SecondOrderFunctions.h:40
#define GRAD_PSI_5
Definition: SecondOrderFunctions.h:31
#define GRAD_PSI_1
Definition: SecondOrderFunctions.h:27
static scalar calc_det_J(abcd J_coeff[3][3], scalar s, scalar t, scalar u, scalar J_inv[9])
Definition: SecondOrderFunctions.cpp:160
#define GRAD_PSI_8
Definition: SecondOrderFunctions.h:34
#define DU_BY_DZ
Definition: SecondOrderFunctions.h:46
#define DT_BY_DY
Definition: SecondOrderFunctions.h:42
static stu stu_lookup[10]
Definition: SecondOrderFunctions.h:61
scalar c
Definition: SecondOrderFunctions.h:58
#define GRAD_PSI_9
Definition: SecondOrderFunctions.h:35
#define GRAD_PSI_7
Definition: SecondOrderFunctions.h:33
#define GRAD_PSI_4
Definition: SecondOrderFunctions.h:30
Definition: mesh_node.h:39
#define DT_BY_DX
Definition: SecondOrderFunctions.h:39
vector3 pos
Definition: mesh_node.h:52
static void calc_jacobian_column_coefficients(mesh_node *n[10], abcd J_coeff[3][3])
Definition: SecondOrderFunctions.cpp:102
#define GRAD_PSI_6
Definition: SecondOrderFunctions.h:32
static void calc_grad_psi(vector3 grad_psi[10], scalar s, scalar t, scalar u, scalar J_inv[9])
Definition: SecondOrderFunctions.cpp:42
scalar a
Definition: SecondOrderFunctions.h:58
static void calc_psi(scalar psi[10], scalar s, scalar t, scalar u)
Definition: SecondOrderFunctions.cpp:28
scalar s
Definition: SecondOrderFunctions.h:54
Definition: SecondOrderFunctions.cpp:26
static const int i
index of ith thing
Definition: rod_math_v9.h:63
Definition: SecondOrderFunctions.h:53
#define GRAD_PSI_3
Definition: SecondOrderFunctions.h:29
Definition: mat_vec_types.h:90
#define DT_BY_DZ
Definition: SecondOrderFunctions.h:45
double scalar
Definition: mat_vec_types.h:36
#define DU_BY_DY
Definition: SecondOrderFunctions.h:43