27 #ifndef DUBValues_HPP_
28 #define DUBValues_HPP_
30 #include <deal.II/base/quadrature_lib.h>
31 #include <deal.II/base/tensor.h>
33 #include <deal.II/fe/fe.h>
34 #include <deal.II/fe/fe_q.h>
48 template <
unsigned int dim>
56 const double tol = 1e-10;
62 const unsigned int alpha,
63 const unsigned int beta,
64 const double eval_point)
const;
71 std::array<unsigned int, dim>
105 const dealii::Point<dim> &quadrature_point)
const;
108 dealii::Tensor<1, dim>
110 const dealii::Point<dim> &quadrature_point)
const;
120 std::array<unsigned int, 2>
124 unsigned int c = poly_degree + 1;
125 unsigned int c_seq = c;
126 while (
n > c_seq - 1)
133 j = poly_degree + 1 - c;
142 std::array<unsigned int, 3>
145 unsigned int i, j,
k;
146 unsigned int p = poly_degree;
147 unsigned int c1 = (p + 1) * (p + 2) / 2;
148 unsigned int c1_seq = c1;
150 while (
n > c1_seq - 1)
153 c1 = (p + 1) * (p + 2) / 2;
158 unsigned int n2 =
n - (c1_seq - c1) + 1;
159 unsigned int c2 = p + 1;
160 unsigned int c2_seq = c2;
168 j = poly_degree - i + 1 - c2;
169 k = n2 - (c2_seq - c2) - 1;
174 template <
unsigned int dim>
177 const unsigned int alpha,
178 const unsigned int beta,
179 const double eval_point)
const
184 return static_cast<double>(
185 (alpha - beta + (alpha + beta + 2.0) * eval_point) / 2.0);
188 const double apb = alpha + beta;
191 double polyn1 =
static_cast<double>(
192 (alpha - beta + (alpha + beta + 2.0) * eval_point) / 2.0);
193 double a1, a2, a3, a4;
195 for (
unsigned int k = 2;
k <=
n; ++
k)
197 a1 = 2.0 *
static_cast<double>(
k) *
static_cast<double>(
k + apb) *
198 static_cast<double>(2.0 *
k + apb - 2.0);
199 a2 =
static_cast<double>(2.0 *
k + apb - 1.0) *
200 static_cast<double>(alpha * alpha - beta * beta);
201 a3 =
static_cast<double>(2.0 *
k + apb - 2.0) *
202 static_cast<double>(2.0 *
k + apb - 1.0) *
203 static_cast<double>(2.0 *
k + apb);
204 a4 = 2.0 *
static_cast<double>(
k + alpha - 1.0) *
205 static_cast<double>(
k + beta - 1.0) *
206 static_cast<double>(2.0 *
k + apb);
212 poly = (a2 + a3 * eval_point) * polyn1 - a4 * polyn2;
221 template <
unsigned int dim>
229 unsigned int denominator = 1;
230 unsigned int nominator = 1;
232 for (
unsigned int i = 1; i <= dim; i++)
235 nominator *= poly_degree + i;
238 return (
int)(nominator / denominator);
241 template <
unsigned int dim>
249 unsigned int denominator = 1;
250 unsigned int nominator = 1;
252 for (
unsigned int i = 1; i <= dim; i++)
255 nominator *= degree + i;
258 return (
int)(nominator / denominator);
265 const dealii::Point<2> &quadrature_point)
const
267 AssertThrow(function_no < dofs_per_cell,
268 dealii::StandardExceptions::ExcMessage(
269 "function_no outside the limit."));
271 const auto fun_coeff = fun_coeff_conversion(function_no);
273 const int i = fun_coeff[0];
274 const int j = fun_coeff[1];
275 const double csi = quadrature_point[0];
276 const double eta = quadrature_point[1];
279 if (csi + eta > 1.0 + tol || csi < -tol || eta < -tol)
285 if (std::abs(1 - eta) > this->tol)
286 a = 2.0 * csi / (1 - eta) - 1.0;
289 const double r = sqrt((2 * i + 1) * 2 * (i + j + 1) / pow(4, i));
290 const double pi = this->eval_jacobi_polynomial(i, 0, 0, a);
291 const double pj = this->eval_jacobi_polynomial(j, 2 * i + 1, 0, b);
293 return r * pow(2, i) * pow(1 - eta, i) * pi * pj;
300 const dealii::Point<3> &quadrature_point)
const
302 AssertThrow(function_no < dofs_per_cell,
303 dealii::StandardExceptions::ExcMessage(
304 "function_no outside the limit."));
306 const auto fun_coeff = fun_coeff_conversion(function_no);
308 const int i = fun_coeff[0];
309 const int j = fun_coeff[1];
310 const int k = fun_coeff[2];
311 const double csi = quadrature_point[0];
312 const double eta = quadrature_point[1];
313 const double ni = quadrature_point[2];
316 if (csi + eta + ni > 1.0 + tol || csi < -tol || eta < -tol || ni < -tol)
322 if (std::abs(-eta - ni + 1.) > this->tol)
323 a = 2. * csi / (-eta - ni + 1.) - 1.;
324 if (std::abs(1 - ni) > this->tol)
325 b = 2. * eta / (1. - ni) - 1.;
329 sqrt(8 * pow(2, 4 * i + 2 * j + 3) * (2 * i + 2 * j + 2 *
k + 3) *
330 (2 * i + 2 * j + 2) * (2 * i + 1) / pow(2, 4 * i + 2 * j + 6));
331 const double pi = this->eval_jacobi_polynomial(i, 0, 0, a);
332 const double pj = this->eval_jacobi_polynomial(j, 2 * i + 1, 0, b);
333 const double pk = this->eval_jacobi_polynomial(
k, 2 * i + 2 * j + 2, 0, c);
335 return r * pi * pow((1. - b) / 2., i) * pj * pow((1. - c) / 2., i + j) * pk;
342 const dealii::Point<2> &quadrature_point)
const
344 AssertThrow(function_no < dofs_per_cell,
345 dealii::StandardExceptions::ExcMessage(
346 "function_no outside the limit."));
348 const auto fun_coeff = fun_coeff_conversion(function_no);
350 const int i = fun_coeff[0];
351 const int j = fun_coeff[1];
352 const double csi = quadrature_point[0];
353 const double eta = quadrature_point[1];
355 dealii::Tensor<1, 2> grad;
358 if (csi + eta > 1.0 + tol || csi < -tol || eta < -tol)
364 if (std::abs(1 - eta) > this->tol)
365 a = 2.0 * csi / (1 - eta) - 1.0;
368 const double r = sqrt((2 * i + 1) * 2 * (i + j + 1) / pow(4, i));
369 const double pi = this->eval_jacobi_polynomial(i, 0, 0, a);
370 const double pj = this->eval_jacobi_polynomial(j, 2 * i + 1, 0, b);
373 if (i == 0 && j == 0)
378 else if (i == 0 && j != 0)
381 grad[1] = r * (j + 2) * eval_jacobi_polynomial(j - 1, 2, 1, b);
383 else if (i != 0 && j == 0)
385 grad[0] = r * pow(2, i) * pow(1 - eta, i - 1) * (i + 1) *
386 eval_jacobi_polynomial(i - 1, 1, 1, a);
387 grad[1] = r * pow(2, i) *
388 (-i * pow(1 - eta, i - 1) * pi +
389 csi * pow(1 - eta, i - 2) * (i + 1) *
390 eval_jacobi_polynomial(i - 1, 1, 1, a));
394 grad[0] = r * pow(2, i) * pow(1 - eta, i - 1) * (i + 1) *
395 eval_jacobi_polynomial(i - 1, 1, 1, a) *
396 eval_jacobi_polynomial(j, 2 * i + 1, 0, b);
397 grad[1] = r * pow(2, i) *
398 (-i * pow(1 - eta, i - 1) * pi * pj +
399 csi * pow(1 - eta, i - 2) * (i + 1) *
400 eval_jacobi_polynomial(i - 1, 1, 1, a) * pj +
401 pow(1 - eta, i) * (2 * i + j + 2) * pi *
402 eval_jacobi_polynomial(j - 1, 2 * i + 2, 1, b));
412 const dealii::Point<3> &quadrature_point)
const
414 AssertThrow(function_no < dofs_per_cell,
415 dealii::StandardExceptions::ExcMessage(
416 "function_no outside the limit."));
418 const auto fun_coeff = fun_coeff_conversion(function_no);
420 const int i = fun_coeff[0];
421 const int j = fun_coeff[1];
422 const int k = fun_coeff[2];
423 const double csi = quadrature_point[0];
424 const double eta = quadrature_point[1];
425 const double ni = quadrature_point[2];
427 dealii::Tensor<1, 3> grad;
430 if (csi + eta + ni > 1.0 + tol || csi < -tol || eta < -tol || ni < -tol)
435 if (std::abs(-eta - ni + 1.) > this->tol)
436 a = 2. * csi / (-eta - ni + 1.) - 1;
437 if (std::abs(1. - ni) > this->tol)
438 b = 2. * eta / (1. - ni) - 1.;
442 sqrt(8 * pow(2, 4 * i + 2 * j + 3) * (2 * i + 2 * j + 2 *
k + 3) *
443 (2 * i + 2 * j + 2) * (2 * i + 1) / pow(2, 4 * i + 2 * j + 6));
444 const double pi = this->eval_jacobi_polynomial(i, 0, 0, a);
445 const double pj = this->eval_jacobi_polynomial(j, 2 * i + 1, 0, b);
446 const double pk = this->eval_jacobi_polynomial(
k, 2 * i + 2 * j + 2, 0, c);
449 double dPi_csi = 0.0, dPi_eta = 0.0, dPi_ni = 0.0;
450 double db_csi = 0.0, db_eta = 0.0, db_ni = 0.0;
451 double dPj_csi = 0.0, dPj_eta = 0.0, dPj_ni = 0.0;
452 double dc_csi = 0.0, dc_eta = 0.0, dc_ni = 0.0;
453 double dPk_csi = 0.0, dPk_eta = 0.0, dPk_ni = 0.0;
457 dPi_csi =
static_cast<double>(i + 1.) * 1. / (-eta - ni + 1.) *
458 eval_jacobi_polynomial(i - 1, 1, 1, a);
459 dPi_eta =
static_cast<double>(i + 1.) * csi / pow(-eta - ni + 1., 2.) *
460 eval_jacobi_polynomial(i - 1, 1, 1, a);
461 dPi_ni =
static_cast<double>(i + 1.) * csi / pow(-eta - ni + 1., 2.) *
462 eval_jacobi_polynomial(i - 1, 1, 1, a);
465 db_eta = -
static_cast<double>(i) / (1. - ni) * pow((1. - b) / 2., i - 1.);
466 db_ni = -
static_cast<double>(i) * eta / pow(1. - ni, 2) *
467 pow((1. - b) / 2, i - 1.);
473 dPj_eta =
static_cast<double>(2. * i + j + 2.) / (1. - ni) *
474 eval_jacobi_polynomial(j - 1, 2 * i + 2, 1, b);
475 dPj_ni = eta *
static_cast<double>(2. * i + j + 2.) / pow(1. - ni, 2.) *
476 eval_jacobi_polynomial(j - 1, 2 * i + 2, 1, b);
483 dc_ni = -
static_cast<double>(i + j) * pow((1. - c) / 2., i + j - 1.);
490 dPk_ni =
static_cast<double>(2. * i + 2. * j +
k + 3.) *
491 eval_jacobi_polynomial(
k - 1, 2 * i + 2 * j + 3, 1, c);
495 r * (dPi_csi * pow((1. - b) / 2., i) * pj * pow((1. - c) / 2., i + j) * pk +
496 pi * db_csi * pj * pow((1. - c) / 2., i + j) * pk +
497 pi * pow((1. - b) / 2., i) * dPj_csi * pow((1. - c) / 2., i + j) * pk +
498 pi * pow((1. - b) / 2., i) * pj * dc_csi * pk +
499 pi * pow((1. - b) / 2., i) * pj * pow((1. - c) / 2., i + j) * dPk_csi);
502 r * (dPi_eta * pow((1. - b) / 2., i) * pj * pow((1. - c) / 2., i + j) * pk +
503 pi * db_eta * pj * pow((1. - c) / 2., i + j) * pk +
504 pi * pow((1. - b) / 2., i) * dPj_eta * pow((1. - c) / 2., i + j) * pk +
505 pi * pow((1. - b) / 2., i) * pj * dc_eta * pk +
506 pi * pow((1. - b) / 2., i) * pj * pow((1. - c) / 2., i + j) * dPk_eta);
509 r * (dPi_ni * pow((1. - b) / 2., i) * pj * pow((1. - c) / 2., i + j) * pk +
510 pi * db_ni * pj * pow((1. - c) / 2., i + j) * pk +
511 pi * pow((1. - b) / 2., i) * dPj_ni * pow((1. - c) / 2., i + j) * pk +
512 pi * pow((1. - b) / 2., i) * pj * dc_ni * pk +
513 pi * pow((1. - b) / 2., i) * pj * pow((1. - c) / 2., i + j) * dPk_ni);
Class representing the Dubiner basis functions definitions.
dealii::Tensor< 1, dim > shape_grad(const unsigned int function_no, const dealii::Point< dim > &quadrature_point) const
Evaluation of the Dubiner basis functions gradients.
double eval_jacobi_polynomial(const unsigned int n, const unsigned int alpha, const unsigned int beta, const double eval_point) const
Evaluation of the -Jacobi polynomial (used to evaluate Dubiner basis).
std::array< unsigned int, dim > fun_coeff_conversion(const unsigned int n) const
Conversion from the FEM basis taxonomy ( basis function, basis function ) to the Dubiner basis taxo...
virtual ~DUBValues()=default
Default destructor.
const double tol
Default tolerance.
const unsigned int poly_degree
Polynomial degree used.
double shape_value(const unsigned int function_no, const dealii::Point< dim > &quadrature_point) const
Evaluation of the Dubiner basis functions.
unsigned int get_dofs_per_cell(const unsigned int degree) const
Same as get_dofs_per_cell() but with variable space degree.
unsigned int dofs_per_cell
Number of degrees of freedom.
unsigned int get_dofs_per_cell() const
Return the number of degrees of freedom per element.