8 template <
int D,
int S
ide>
9 MoFEMErrorCode BernsteinBezier::generateIndicesVertex(
const int N,
int *alpha) {
11 alpha[(
D + 1) * Side + Side] =
N;
15 template <
int D,
int S
ide>
18 constexpr
int edge_nodes[6][2] = {{0, 1}, {1, 2}, {2, 0},
19 {0, 3}, {1, 3}, {2, 3}};
21 std::fill(alpha, &alpha[(
D + 1) *
NBEDGE_H1(
N)], 0);
22 for (
int n =
N - 1;
n != 0; --
n) {
26 alpha[edge_nodes[Side][0]] =
n;
27 alpha[edge_nodes[Side][1]] =
N -
n;
33 template <
int D,
int S
ide>
36 constexpr
int tri_nodes[4][3] = {{0, 1, 3}, {1, 2, 3}, {0, 2, 3}, {0, 1, 2}};
39 for (
int n0 = 1; n0 !=
N - 1; ++n0) {
40 for (
int n1 = 1; n1 !=
N - n0; ++n1) {
49 alpha[tri_nodes[Side][0]] = n0;
50 alpha[tri_nodes[Side][1]] = n1;
51 alpha[tri_nodes[Side][2]] =
N - n0 - n1;
63 for (
int n0 = 1; n0 !=
N - 1; ++n0) {
64 for (
int n1 = 1; n1 !=
N - n0; ++n1) {
65 for (
int n2 = 1; n2 !=
N - n0 - n1; ++n2) {
69 alpha[3] =
N - n0 - n1 - n2;
80 CHKERR generateIndicesVertex<1, 0>(
N, alpha);
81 CHKERR generateIndicesVertex<1, 1>(
N, alpha);
87 return generateIndicesEdgeOnSimplex<1, 0>(
N, alpha);
93 CHKERR generateIndicesVertex<2, 0>(
N, alpha);
94 CHKERR generateIndicesVertex<2, 1>(
N, alpha);
95 CHKERR generateIndicesVertex<2, 2>(
N, alpha);
102 CHKERR generateIndicesEdgeOnSimplex<2, 0>(
N[0], alpha[0]);
103 CHKERR generateIndicesEdgeOnSimplex<2, 1>(
N[1], alpha[1]);
104 CHKERR generateIndicesEdgeOnSimplex<2, 2>(
N[2], alpha[2]);
113 return generateIndicesEdgeOnSimplex<2, 0>(
N, alpha);
115 return generateIndicesEdgeOnSimplex<2, 1>(
N, alpha);
117 return generateIndicesEdgeOnSimplex<2, 2>(
N, alpha);
120 "Wrong side number, on triangle are edges from 0 to 2");
125 return generateIndicesTriOnSimplex<2, 3>(
N, alpha);
131 CHKERR generateIndicesVertex<3, 0>(
N, alpha);
132 CHKERR generateIndicesVertex<3, 1>(
N, alpha);
133 CHKERR generateIndicesVertex<3, 2>(
N, alpha);
134 CHKERR generateIndicesVertex<3, 3>(
N, alpha);
141 CHKERR generateIndicesEdgeOnSimplex<3, 0>(
N[0], alpha[0]);
142 CHKERR generateIndicesEdgeOnSimplex<3, 1>(
N[1], alpha[1]);
143 CHKERR generateIndicesEdgeOnSimplex<3, 2>(
N[2], alpha[2]);
144 CHKERR generateIndicesEdgeOnSimplex<3, 3>(
N[3], alpha[3]);
145 CHKERR generateIndicesEdgeOnSimplex<3, 4>(
N[4], alpha[4]);
146 CHKERR generateIndicesEdgeOnSimplex<3, 5>(
N[5], alpha[5]);
156 return generateIndicesEdgeOnSimplex<3, 0>(
N, alpha);
158 return generateIndicesEdgeOnSimplex<3, 1>(
N, alpha);
160 return generateIndicesEdgeOnSimplex<3, 2>(
N, alpha);
162 return generateIndicesEdgeOnSimplex<3, 3>(
N, alpha);
164 return generateIndicesEdgeOnSimplex<3, 4>(
N, alpha);
166 return generateIndicesEdgeOnSimplex<3, 5>(
N, alpha);
169 "Wrong side number, on tetrahedron are edges from 0 to 5");
177 CHKERR generateIndicesTriOnSimplex<3, 0>(
N[0], alpha[0]);
178 CHKERR generateIndicesTriOnSimplex<3, 1>(
N[1], alpha[1]);
179 CHKERR generateIndicesTriOnSimplex<3, 2>(
N[2], alpha[2]);
180 CHKERR generateIndicesTriOnSimplex<3, 3>(
N[3], alpha[3]);
185 const int N,
int *alpha) {
189 return generateIndicesTriOnSimplex<3, 0>(
N, alpha);
191 return generateIndicesTriOnSimplex<3, 1>(
N, alpha);
193 return generateIndicesTriOnSimplex<3, 2>(
N, alpha);
195 return generateIndicesTriOnSimplex<3, 3>(
N, alpha);
198 "Wrong side number, on tetrahedron are from from 0 to 3");
204 return generateIndicesTetOnSimplex(
N, alpha);
209 const int N,
const int n_alpha,
const int *alpha,
const int *diff,
210 const int n_alpha_diff,
const int *alpha_diff,
double *
c) {
213 std::fill(
c, &
c[n_alpha * n_alpha_diff], 0);
214 int abs_diff = diff[0];
215 for (
int d = 1;
d !=
D + 1; ++
d)
218 const double b = boost::math::factorial<double>(
N) /
219 boost::math::factorial<double>(
N - abs_diff);
221 for (
int i = 0;
i != n_alpha; ++
i) {
222 for (
int j = 0;
j != n_alpha_diff; ++
j) {
224 for (;
d !=
D + 1; ++
d)
225 if (alpha_diff[(
D + 1) *
j +
d] + diff[
d] != alpha[(
D + 1) *
i +
d])
228 c[
i * n_alpha_diff +
j] = b;
238 const int N,
const int n_alpha,
const int *alpha,
const int *diff,
239 const int n_alpha_diff,
const int *alpha_diff,
double *
c) {
240 return genrateDerivativeIndices<1>(
N, n_alpha, alpha, diff, n_alpha_diff,
245 const int N,
const int n_alpha,
const int *alpha,
const int *diff,
246 const int n_alpha_diff,
const int *alpha_diff,
double *
c) {
247 return genrateDerivativeIndices<2>(
N, n_alpha, alpha, diff, n_alpha_diff,
252 const int N,
const int n_alpha,
const int *alpha,
const int *diff,
253 const int n_alpha_diff,
const int *alpha_diff,
double *
c) {
254 return genrateDerivativeIndices<3>(
N, n_alpha, alpha, diff, n_alpha_diff,
260 BernsteinBezier::domainPoints(
const int N,
const int n_x,
const int n_alpha,
261 const int *alpha,
const double *x_k,
267 x_alpha, &x_alpha[1], &x_alpha[2]);
268 for (
int n0 = 0; n0 != n_alpha; ++n0) {
271 x_k, &x_k[1], &x_k[2]);
272 for (
int n1 = 0; n1 != n_x; ++n1) {
273 t_x_alpha(
i) +=
static_cast<double>(*alpha) * t_x_k(
i);
277 t_x_alpha(
i) /=
static_cast<double>(
N);
289 return domainPoints<3>(
N, n_x, n_alpha, alpha, x_k, x_alpha);
292 template <
int D,
bool GRAD_BASE>
294 BernsteinBezier::baseFunctions(
const int N,
const int gdim,
const int n_alpha,
295 const int *alpha,
const double *
lambda,
296 const double *grad_lambda,
double *base,
300 const int *
const alpha0 = alpha;
301 const double fN = boost::math::factorial<double>(
N);
302 constexpr
int MAX_ALPHA = 12;
303 int max_alpha = *std::max_element(alpha, &alpha[(
D + 1) * n_alpha]);
304 if(max_alpha > MAX_ALPHA)
306 "Is assumed maximal order not to be bigger than %d", MAX_ALPHA);
307 std::array<
double, (
D + 1) * (MAX_ALPHA + 1)> pow_alpha;
308 std::array<
double, (MAX_ALPHA + 1)> factorial_alpha;
309 std::array<double, D + 1> terms, diff_terms;
310 const double *
const grad_lambda0 = grad_lambda;
312 factorial_alpha[0] = 1;
314 factorial_alpha[1] = 1;
316 for (
int a = 2;
a <= max_alpha; ++
a)
317 factorial_alpha[
a] = factorial_alpha[
a - 1] *
a;
319 for (
int g = 0;
g != gdim; ++
g) {
322 const size_t shift = (MAX_ALPHA + 1) *
n;
323 double *pow_alpha_ptr = &pow_alpha[shift];
326 if (max_alpha >= 1) {
332 for (
int a = 2;
a <= max_alpha; ++
a) {
333 const double p = (*pow_alpha_ptr) * (*lambda);
339 for (
int n0 = 0; n0 != n_alpha; ++n0) {
341 grad_lambda = grad_lambda0;
343 double f = factorial_alpha[(*alpha)];
344 double *terms_ptr = terms.data();
345 double *diff_terms_ptr = diff_terms.data();
346 *terms_ptr = pow_alpha[(*alpha)];
349 *diff_terms_ptr = (*alpha) * pow_alpha[(*alpha) - 1];
358 for (
int n1 = 1; n1 <
D + 1;
359 ++n1, ++alpha, ++terms_ptr, ++diff_terms_ptr) {
360 f *= factorial_alpha[(*alpha)];
361 const size_t shift = (MAX_ALPHA + 1) * n1;
362 *terms_ptr = pow_alpha[shift + (*alpha)];
365 *diff_terms_ptr = (*alpha) * pow_alpha[shift + (*alpha) - 1];
372 const double b = fN /
f;
377 double *terms_ptr = terms.data();
378 double *diff_terms_ptr = diff_terms.data();
379 double z = *diff_terms_ptr;
382 for (
int n2 = 1; n2 !=
D + 1; ++n2, ++terms_ptr)
385 for (
int d = 0;
d !=
D; ++
d, ++grad_lambda)
386 grad_base[
d] = z * (*grad_lambda);
388 for (
int n1 = 1; n1 <
D + 1; ++n1) {
392 for (terms_ptr = terms.data(); n2 != n1; ++n2, ++terms_ptr)
398 for (; n2 <
D + 1; ++n2, ++terms_ptr)
401 for (
int d = 0;
d !=
D; ++
d, ++grad_lambda)
402 grad_base[
d] += z * (*grad_lambda);
406 for (
int d = 0;
d !=
D; ++
d)
420 const int N,
const int gdim,
const int n_alpha,
const int *alpha,
421 const double *
lambda,
const double *grad_lambda,
double *base,
424 return baseFunctions<1, true>(
N, gdim, n_alpha, alpha,
lambda, grad_lambda,
427 return baseFunctions<1, false>(
N, gdim, n_alpha, alpha,
lambda, grad_lambda,
432 const int N,
const int gdim,
const int n_alpha,
const int *alpha,
433 const double *
lambda,
const double *grad_lambda,
double *base,
436 return baseFunctions<2, true>(
N, gdim, n_alpha, alpha,
lambda, grad_lambda,
439 return baseFunctions<2, false>(
N, gdim, n_alpha, alpha,
lambda, grad_lambda,
444 const int N,
const int gdim,
const int n_alpha,
const int *alpha,
445 const double *
lambda,
const double *grad_lambda,
double *base,
448 return baseFunctions<3, true>(
N, gdim, n_alpha, alpha,
lambda, grad_lambda,
451 return baseFunctions<3, false>(
N, gdim, n_alpha, alpha,
lambda, grad_lambda,