6 #ifndef SHAPE_FUNCTIONS_H
7 #define SHAPE_FUNCTIONS_H
18 element(
double *x,
double *y,
double *
z,
int numNodes = 0)
28 _x =
new double[numNodes];
29 _y =
new double[numNodes];
30 _z =
new double[numNodes];
31 for(
int i = 0; i < numNodes; i++) {
46 virtual void getXYZ(
int num,
double &x,
double &y,
double &
z)
56 virtual void getNode(
int num,
double &u,
double &v,
double &w) = 0;
58 virtual void getEdge(
int num,
int &start,
int &end) = 0;
66 double getJacobian(
double u,
double v,
double w,
double jac[3][3])
68 jac[0][0] = jac[0][1] = jac[0][2] = 0.;
69 jac[1][0] = jac[1][1] = jac[1][2] = 0.;
70 jac[2][0] = jac[2][1] = jac[2][2] = 0.;
76 jac[0][0] +=
_x[i] * s[0];
77 jac[0][1] +=
_y[i] * s[0];
78 jac[0][2] +=
_z[i] * s[0];
79 jac[1][0] +=
_x[i] * s[1];
80 jac[1][1] +=
_y[i] * s[1];
81 jac[1][2] +=
_z[i] * s[1];
82 jac[2][0] +=
_x[i] * s[2];
83 jac[2][1] +=
_y[i] * s[2];
84 jac[2][2] +=
_z[i] * s[2];
87 jac[0][0] * jac[1][1] * jac[2][2] + jac[0][2] * jac[1][0] * jac[2][1] +
88 jac[0][1] * jac[1][2] * jac[2][0] - jac[0][2] * jac[1][1] * jac[2][0] -
89 jac[0][0] * jac[1][2] * jac[2][1] - jac[0][1] * jac[1][0] * jac[2][2]);
93 jac[0][0] +=
_x[i] * s[0];
94 jac[0][1] +=
_y[i] * s[0];
95 jac[0][2] +=
_z[i] * s[0];
96 jac[1][0] +=
_x[i] * s[1];
97 jac[1][1] +=
_y[i] * s[1];
98 jac[1][2] +=
_z[i] * s[1];
101 double a[3], b[3],
c[3];
102 a[0] =
_x[1] -
_x[0];
103 a[1] =
_y[1] -
_y[0];
104 a[2] =
_z[1] -
_z[0];
105 b[0] =
_x[2] -
_x[0];
106 b[1] =
_y[2] -
_y[0];
107 b[2] =
_z[2] -
_z[0];
114 std::pow(jac[0][0] * jac[1][1] - jac[0][1] * jac[1][0], 2) +
115 std::pow(jac[0][2] * jac[1][0] - jac[0][0] * jac[1][2], 2) +
116 std::pow(jac[0][1] * jac[1][2] - jac[0][2] * jac[1][1], 2));
120 jac[0][0] +=
_x[i] * s[0];
121 jac[0][1] +=
_y[i] * s[0];
122 jac[0][2] +=
_z[i] * s[0];
125 double a[3], b[3],
c[3];
126 a[0] =
_x[1] -
_x[0];
127 a[1] =
_y[1] -
_y[0];
128 a[2] =
_z[1] -
_z[0];
129 if((std::abs(a[0]) >= std::abs(a[1]) &&
130 std::abs(a[0]) >= std::abs(a[2])) ||
131 (std::abs(a[1]) >= std::abs(a[0]) &&
132 std::abs(a[1]) >= std::abs(a[2]))) {
150 return std::sqrt(std::pow(jac[0][0], 2) + std::pow(jac[0][1], 2) +
151 std::pow(jac[0][2], 2));
152 default: jac[0][0] = jac[1][1] = jac[2][2] = 1.;
return 1.;
155 double interpolate(
double val[],
double u,
double v,
double w,
int stride = 1)
168 int stride = 1,
double invjac[3][3] =
nullptr)
170 double dfdu[3] = {0., 0., 0.};
175 dfdu[0] += val[j] * s[0];
176 dfdu[1] += val[j] * s[1];
177 dfdu[2] += val[j] * s[2];
180 if(invjac) {
matvec(invjac, dfdu,
f); }
182 double jac[3][3], inv[3][3];
191 double fx[3], fy[3], fz[3], jac[3][3], inv[3][3];
197 f[0] = fz[1] - fy[2];
198 f[1] = -(fz[0] - fx[2]);
199 f[2] = fy[0] - fx[1];
204 double fx[3], fy[3], fz[3], jac[3][3], inv[3][3];
210 return fx[0] + fy[1] + fz[2];
216 double u, v, w, weight, jac[3][3];
220 sum += d * weight * det;
227 double ones[8] = {1., 1., 1., 1., 1., 1., 1., 1.};
229 double sum = 0, sumabs = 0.;
232 sumabs += std::abs(val[i]);
235 if(sumabs) res = area * (1 + sum / sumabs) * 0.5;
240 Msg::Error(
"integrateCirculation not available for this element");
245 Msg::Error(
"integrateFlux not available for this element");
248 virtual void xyz2uvw(
double xyz[3],
double uvw[3])
253 uvw[0] = uvw[1] = uvw[2] = 0.0;
255 int iter = 1, maxiter = 20;
256 double error = 1., tol = 1.e-6;
258 while(error > tol && iter < maxiter) {
260 if(!
getJacobian(uvw[0], uvw[1], uvw[2], jac))
break;
262 double xn = 0., yn = 0., zn = 0.;
273 double un = uvw[0] + inv[0][0] * (xyz[0] - xn) +
274 inv[1][0] * (xyz[1] - yn) + inv[2][0] * (xyz[2] - zn);
275 double vn = uvw[1] + inv[0][1] * (xyz[0] - xn) +
276 inv[1][1] * (xyz[1] - yn) + inv[2][1] * (xyz[2] - zn);
277 double wn = uvw[2] + inv[0][2] * (xyz[0] - xn) +
278 inv[1][2] * (xyz[1] - yn) + inv[2][2] * (xyz[2] - zn);
280 error = std::sqrt(std::pow(un - uvw[0], 2) + std::pow(vn - uvw[1], 2) +
281 std::pow(wn - uvw[2], 2));
289 virtual int isInside(
double u,
double v,
double w) = 0;
297 std::sqrt(std::pow(
_x[n1] -
_x[n2], 2) + std::pow(
_y[n1] -
_y[n2], 2) +
298 std::pow(
_z[n1] -
_z[n2], 2));
307 point(
double *x,
double *y,
double *
z,
int numNodes = 0)
313 void getNode(
int num,
double &u,
double &v,
double &w) { u = v = w = 0.; }
315 void getEdge(
int num,
int &start,
int &end) { start = end = 0; }
317 void getGaussPoint(
int num,
double &u,
double &v,
double &w,
double &weight)
325 case 0: s = 1.;
break;
326 default: s = 0.;
break;
331 s[0] = s[1] = s[2] = 0.;
333 void xyz2uvw(
double xyz[3],
double uvw[3]) { uvw[0] = uvw[1] = uvw[2] = 0.; }
337 if(std::abs(u) > TOL || std::abs(v) > TOL || std::abs(w) > TOL)
return 0;
344 line(
double *x,
double *y,
double *
z,
int numNodes = 0)
350 void getNode(
int num,
double &u,
double &v,
double &w)
354 case 0: u = -1.;
break;
355 case 1: u = 1.;
break;
356 default: u = 0.;
break;
366 void getGaussPoint(
int num,
double &u,
double &v,
double &w,
double &weight)
368 if(num < 0 || num > 0)
return;
375 case 0: s = 0.5 * (1. - u);
break;
376 case 1: s = 0.5 * (1. + u);
break;
377 default: s = 0.;
break;
393 default: s[0] = s[1] = s[2] = 0.;
break;
398 double t[3] = {
_x[1] -
_x[0],
_y[1] -
_y[0],
_z[1] -
_z[0]};
401 for(
int i = 0; i < 3; i++) v[i] =
integrate(&val[i], 3);
407 if(u < -(1. + TOL) || u > (1. + TOL) || std::abs(v) > TOL ||
416 triangle(
double *x,
double *y,
double *
z,
int numNodes = 0)
422 void getNode(
int num,
double &u,
double &v,
double &w)
460 default: start = end = 0;
break;
464 void getGaussPoint(
int num,
double &u,
double &v,
double &w,
double &weight)
473 if(num < 0 || num > 0)
return;
474 u = v = 0.333333333333333;
481 case 0: s = 1. - u - v;
break;
482 case 1: s = u;
break;
483 case 2: s = v;
break;
484 default: s = 0.;
break;
505 default: s[0] = s[1] = s[2] = 0.;
break;
510 double t1[3] = {
_x[1] -
_x[0],
_y[1] -
_y[0],
_z[1] -
_z[0]};
511 double t2[3] = {
_x[2] -
_x[0],
_y[2] -
_y[0],
_z[2] -
_z[0]};
516 for(
int i = 0; i < 3; i++) v[i] =
integrate(&val[i], 3);
521 const double O[3] = {
_x[0],
_y[0],
_z[0]};
523 const double d[3] = {xyz[0] -
O[0], xyz[1] -
O[1], xyz[2] -
O[2]};
524 const double d1[3] = {
_x[1] -
O[0],
_y[1] -
O[1],
_z[1] -
O[2]};
525 const double d2[3] = {
_x[2] -
O[0],
_y[2] -
O[1],
_z[2] -
O[2]};
527 const double Jxy = d1[0] * d2[1] - d1[1] * d2[0];
528 const double Jxz = d1[0] * d2[2] - d1[2] * d2[0];
529 const double Jyz = d1[1] * d2[2] - d1[2] * d2[1];
531 if((std::abs(Jxy) > std::abs(Jxz)) && (std::abs(Jxy) > std::abs(Jyz))) {
532 uvw[0] = (d[0] * d2[1] - d[1] * d2[0]) / Jxy;
533 uvw[1] = (d[1] * d1[0] - d[0] * d1[1]) / Jxy;
535 else if(std::abs(Jxz) > std::abs(Jyz)) {
536 uvw[0] = (d[0] * d2[2] - d[2] * d2[0]) / Jxz;
537 uvw[1] = (d[2] * d1[0] - d[0] * d1[2]) / Jxz;
540 uvw[0] = (d[1] * d2[2] - d[2] * d2[1]) / Jyz;
541 uvw[1] = (d[2] * d1[1] - d[1] * d1[2]) / Jyz;
548 if(u < -TOL || v < -TOL || u > ((1. + TOL) - v) || std::abs(w) > TOL)
562 void getNode(
int num,
double &u,
double &v,
double &w)
608 default: start = end = 0;
break;
612 void getGaussPoint(
int num,
double &u,
double &v,
double &w,
double &weight)
614 static double u4[4] = {0.577350269189, -0.577350269189, 0.577350269189,
616 static double v4[4] = {0.577350269189, 0.577350269189, -0.577350269189,
618 static double p4[4] = {1., 1., 1., 1.};
619 if(num < 0 || num > 3)
return;
628 case 0: s = 0.25 * (1. - u) * (1. - v);
break;
629 case 1: s = 0.25 * (1. + u) * (1. - v);
break;
630 case 2: s = 0.25 * (1. + u) * (1. + v);
break;
631 case 3: s = 0.25 * (1. - u) * (1. + v);
break;
632 default: s = 0.;
break;
639 s[0] = -0.25 * (1. - v);
640 s[1] = -0.25 * (1. - u);
644 s[0] = 0.25 * (1. - v);
645 s[1] = -0.25 * (1. + u);
649 s[0] = 0.25 * (1. + v);
650 s[1] = 0.25 * (1. + u);
654 s[0] = -0.25 * (1. + v);
655 s[1] = 0.25 * (1. - u);
658 default: s[0] = s[1] = s[2] = 0.;
break;
663 double t1[3] = {
_x[1] -
_x[0],
_y[1] -
_y[0],
_z[1] -
_z[0]};
664 double t2[3] = {
_x[2] -
_x[0],
_y[2] -
_y[0],
_z[2] -
_z[0]};
669 for(
int i = 0; i < 3; i++) v[i] =
integrate(&val[i], 3);
675 if(u < -(1. + TOL) || v < -(1. + TOL) || u > (1. + TOL) || v > (1. + TOL) ||
690 void getNode(
int num,
double &u,
double &v,
double &w)
748 default: start = end = 0;
break;
752 void getGaussPoint(
int num,
double &u,
double &v,
double &w,
double &weight)
754 static double u4[4] = {0.138196601125, 0.138196601125, 0.138196601125,
756 static double v4[4] = {0.138196601125, 0.138196601125, 0.585410196625,
758 static double w4[4] = {0.138196601125, 0.585410196625, 0.138196601125,
760 static double p4[4] = {0.0416666666667, 0.0416666666667, 0.0416666666667,
762 if(num < 0 || num > 3)
return;
771 case 0: s = 1. - u - v - w;
break;
772 case 1: s = u;
break;
773 case 2: s = v;
break;
774 case 3: s = w;
break;
775 default: s = 0.;
break;
801 default: s[0] = s[1] = s[2] = 0.;
break;
806 double mat[3][3], b[3];
807 mat[0][0] =
_x[1] -
_x[0];
808 mat[0][1] =
_x[2] -
_x[0];
809 mat[0][2] =
_x[3] -
_x[0];
810 mat[1][0] =
_y[1] -
_y[0];
811 mat[1][1] =
_y[2] -
_y[0];
812 mat[1][2] =
_y[3] -
_y[0];
813 mat[2][0] =
_z[1] -
_z[0];
814 mat[2][1] =
_z[2] -
_z[0];
815 mat[2][2] =
_z[3] -
_z[0];
816 b[0] = xyz[0] -
_x[0];
817 b[1] = xyz[1] -
_y[0];
818 b[2] = xyz[2] -
_z[0];
820 sys3x3(mat, b, uvw, &det);
825 if(u < (-TOL) || v < (-TOL) || w < (-TOL) || u > ((1. + TOL) - v - w))
839 void getNode(
int num,
double &u,
double &v,
double &w)
941 default: start = end = 0;
break;
945 void getGaussPoint(
int num,
double &u,
double &v,
double &w,
double &weight)
947 static double u6[6] = {0.40824826, 0.40824826, -0.40824826,
948 -0.40824826, -0.81649658, 0.81649658};
949 static double v6[6] = {0.70710678, -0.70710678, 0.70710678,
950 -0.70710678, 0., 0.};
951 static double w6[6] = {-0.57735027, -0.57735027, 0.57735027,
952 0.57735027, -0.57735027, 0.57735027};
953 static double p6[6] = {1.3333333333, 1.3333333333, 1.3333333333,
954 1.3333333333, 1.3333333333, 1.3333333333};
955 if(num < 0 || num > 5)
return;
964 case 0: s = (1. - u) * (1. - v) * (1. - w) * 0.125;
break;
965 case 1: s = (1. + u) * (1. - v) * (1. - w) * 0.125;
break;
966 case 2: s = (1. + u) * (1. + v) * (1. - w) * 0.125;
break;
967 case 3: s = (1. - u) * (1. + v) * (1. - w) * 0.125;
break;
968 case 4: s = (1. - u) * (1. - v) * (1. + w) * 0.125;
break;
969 case 5: s = (1. + u) * (1. - v) * (1. + w) * 0.125;
break;
970 case 6: s = (1. + u) * (1. + v) * (1. + w) * 0.125;
break;
971 case 7: s = (1. - u) * (1. + v) * (1. + w) * 0.125;
break;
972 default: s = 0.;
break;
979 s[0] = -0.125 * (1. - v) * (1. - w);
980 s[1] = -0.125 * (1. - u) * (1. - w);
981 s[2] = -0.125 * (1. - u) * (1. - v);
984 s[0] = 0.125 * (1. - v) * (1. - w);
985 s[1] = -0.125 * (1. + u) * (1. - w);
986 s[2] = -0.125 * (1. + u) * (1. - v);
989 s[0] = 0.125 * (1. + v) * (1. - w);
990 s[1] = 0.125 * (1. + u) * (1. - w);
991 s[2] = -0.125 * (1. + u) * (1. + v);
994 s[0] = -0.125 * (1. + v) * (1. - w);
995 s[1] = 0.125 * (1. - u) * (1. - w);
996 s[2] = -0.125 * (1. - u) * (1. + v);
999 s[0] = -0.125 * (1. - v) * (1. + w);
1000 s[1] = -0.125 * (1. - u) * (1. + w);
1001 s[2] = 0.125 * (1. - u) * (1. - v);
1004 s[0] = 0.125 * (1. - v) * (1. + w);
1005 s[1] = -0.125 * (1. + u) * (1. + w);
1006 s[2] = 0.125 * (1. + u) * (1. - v);
1009 s[0] = 0.125 * (1. + v) * (1. + w);
1010 s[1] = 0.125 * (1. + u) * (1. + w);
1011 s[2] = 0.125 * (1. + u) * (1. + v);
1014 s[0] = -0.125 * (1. + v) * (1. + w);
1015 s[1] = 0.125 * (1. - u) * (1. + w);
1016 s[2] = 0.125 * (1. - u) * (1. + v);
1018 default: s[0] = s[1] = s[2] = 0.;
break;
1024 if(u < -(1. + TOL) || v < -(1. + TOL) || w < -(1. + TOL) ||
1025 u > (1. + TOL) || v > (1. + TOL) || w > (1. + TOL))
1033 prism(
double *x,
double *y,
double *
z,
int numNodes = 0)
1039 void getNode(
int num,
double &u,
double &v,
double &w)
1119 default: start = end = 0;
break;
1125 static double u6[6] = {0.166666666666666, 0.333333333333333,
1126 0.166666666666666, 0.166666666666666,
1127 0.333333333333333, 0.166666666666666};
1128 static double v6[6] = {0.166666666666666, 0.166666666666666,
1129 0.333333333333333, 0.166666666666666,
1130 0.166666666666666, 0.333333333333333};
1131 static double w6[6] = {-0.577350269189, -0.577350269189, -0.577350269189,
1132 0.577350269189, 0.577350269189, 0.577350269189};
1133 static double p6[6] = {
1134 0.166666666666666, 0.166666666666666, 0.166666666666666,
1135 0.166666666666666, 0.166666666666666, 0.166666666666666,
1137 if(num < 0 || num > 5)
return;
1146 case 0: s = (1. - u - v) * (1. - w) * 0.5;
break;
1147 case 1: s = u * (1. - w) * 0.5;
break;
1148 case 2: s = v * (1. - w) * 0.5;
break;
1149 case 3: s = (1. - u - v) * (1. + w) * 0.5;
break;
1150 case 4: s = u * (1. + w) * 0.5;
break;
1151 case 5: s = v * (1. + w) * 0.5;
break;
1152 default: s = 0.;
break;
1159 s[0] = -0.5 * (1. - w);
1160 s[1] = -0.5 * (1. - w);
1161 s[2] = -0.5 * (1. - u - v);
1164 s[0] = 0.5 * (1. - w);
1170 s[1] = 0.5 * (1. - w);
1174 s[0] = -0.5 * (1. + w);
1175 s[1] = -0.5 * (1. + w);
1176 s[2] = 0.5 * (1. - u - v);
1179 s[0] = 0.5 * (1. + w);
1185 s[1] = 0.5 * (1. + w);
1188 default: s[0] = s[1] = s[2] = 0.;
break;
1194 if(w > (1. + TOL) || w < -(1. + TOL) || u < (-TOL) || v < (-TOL) ||
1195 u > ((1. + TOL) - v))
1203 pyramid(
double *x,
double *y,
double *
z,
int numNodes = 0)
1209 void getNode(
int num,
double &u,
double &v,
double &w)
1280 default: start = end = 0;
break;
1286 static double u8[8] = {0.2631840555694285, -0.2631840555694285,
1287 0.2631840555694285, -0.2631840555694285,
1288 0.5066163033492386, -0.5066163033492386,
1289 0.5066163033492386, -0.5066163033492386};
1290 static double v8[8] = {0.2631840555694285, 0.2631840555694285,
1291 -0.2631840555694285, -0.2631840555694285,
1292 0.5066163033492386, 0.5066163033492386,
1293 -0.5066163033492386, -0.5066163033492386};
1294 static double w8[8] = {0.544151844011225, 0.544151844011225,
1295 0.544151844011225, 0.544151844011225,
1296 0.122514822655441, 0.122514822655441,
1297 0.122514822655441, 0.122514822655441};
1298 static double p8[8] = {0.100785882079825, 0.100785882079825,
1299 0.100785882079825, 0.100785882079825,
1300 0.232547451253508, 0.232547451253508,
1301 0.232547451253508, 0.232547451253508};
1302 if(num < 0 || num > 7)
return;
1312 if(w != 1. && num != 4)
1313 r = u * v * w / (1. - w);
1317 case 0: s = 0.25 * ((1. - u) * (1. - v) - w + r);
break;
1318 case 1: s = 0.25 * ((1. + u) * (1. - v) - w - r);
break;
1319 case 2: s = 0.25 * ((1. + u) * (1. + v) - w + r);
break;
1320 case 3: s = 0.25 * ((1. - u) * (1. + v) - w - r);
break;
1321 case 4: s = w;
break;
1322 default: s = 0.;
break;
1354 default: s[0] = s[1] = s[2] = 0.;
break;
1360 s[0] = 0.25 * (-(1. - v) + v * w / (1. - w));
1361 s[1] = 0.25 * (-(1. - u) + u * w / (1. - w));
1363 0.25 * (-1. + u * v / (1. - w) + u * v * w / std::pow(1. - w, 2));
1366 s[0] = 0.25 * ((1. - v) - v * w / (1. - w));
1367 s[1] = 0.25 * (-(1. + u) - u * w / (1. - w));
1369 0.25 * (-1. - u * v / (1. - w) - u * v * w / std::pow(1. - w, 2));
1372 s[0] = 0.25 * ((1. + v) + v * w / (1. - w));
1373 s[1] = 0.25 * ((1. + u) + u * w / (1. - w));
1375 0.25 * (-1. + u * v / (1. - w) + u * v * w / std::pow(1. - w, 2));
1378 s[0] = 0.25 * (-(1. + v) - v * w / (1. - w));
1379 s[1] = 0.25 * ((1. - u) - u * w / (1. - w));
1381 0.25 * (-1. - u * v / (1. - w) - u * v * w / std::pow(1. - w, 2));
1388 default: s[0] = s[1] = s[2] = 0.;
break;
1395 if(u < (w - (1. + TOL)) || u > ((1. + TOL) - w) || v < (w - (1. + TOL)) ||
1396 v > ((1. + TOL) - w) || w < (-TOL) || w > (1. + TOL))
1408 case 0:
return new point(x, y,
z,
copy ? numNodes : 0);
1409 case 1:
return new line(x, y,
z,
copy ? numNodes : 0);
1418 else if(numNodes == 6)
1419 return new prism(x, y,
z,
copy ? numNodes : 0);
1420 else if(numNodes == 5)
1424 default:
Msg::Error(
"Unknown type of element in factory");
return nullptr;