gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
orthogonalBasis.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 //
6 // Contributed by Amaury Johnen
7 
8 #include <cmath>
9 #include <vector>
10 #include <algorithm>
11 #include "orthogonalBasis.h"
12 #include "FuncSpaceData.h"
13 #include "Numeric.h"
14 
16  : _type(_data.getType()), _order(_data.getSpaceOrder())
17 {
18 }
19 
20 void orthogonalBasis::f(double u, double v, double w, double *sf) const
21 {
22  static double sf0[100];
23  static double sf1[100];
24  int k = 0;
25  switch(_type) {
26  case TYPE_LIN: LegendrePolynomials::f(_order, u, sf); return;
27  case TYPE_TRI:
28  if(u >= 1.) {
29  for(int k = 0; k <= _order; ++k) { sf[k] = k + 1; }
30  for(int k = _order; k < (_order + 1) * (_order + 2) / 2; ++k) {
31  sf[k] = 0;
32  }
33  return;
34  }
35  LegendrePolynomials::f(_order, 2 * v / (1 - u) - 1, sf0);
36  for(int i = 0; i <= _order; ++i) {
37  JacobiPolynomials::f(_order - i, 2 * i + 1, 0, 2 * u - 1, sf1);
38  double coeff = pow_int(1 - u, i);
39  for(int j = 0; j <= _order - i; ++j) { sf1[j] *= coeff; }
40  for(int j = 0; j <= _order - i; ++j) { sf[k++] = sf0[i] * sf1[j]; }
41  }
42  return;
43  case TYPE_QUA:
46  for(int i = 0; i <= _order; ++i) {
47  for(int j = 0; j <= _order; ++j) { sf[k++] = sf0[i] * sf1[j]; }
48  }
49  return;
50  }
51 }
52 
53 void orthogonalBasis::integralfSquared(double *val) const
54 {
55  int k = 0;
56  switch(_type) {
57  case TYPE_LIN:
58  for(int i = 0; i <= _order; ++i) { val[i] = 2. / (1 + 2 * i); }
59  return;
60  case TYPE_TRI:
61  for(int i = 0; i <= _order; ++i) {
62  for(int j = 0; j <= _order - i; ++j) {
63  val[k++] = .5 / (1 + i + j) / (1 + 2 * i);
64  }
65  }
66  return;
67  case TYPE_QUA:
68  for(int i = 0; i <= _order; ++i) {
69  for(int j = 0; j <= _order; ++j) {
70  val[k++] = 4. / (1 + 2 * i) / (1 + 2 * j);
71  }
72  }
73  }
74 }
75 
77  void f(int n, double u, double *val)
78  {
79  val[0] = 1;
80 
81  for(int i = 0; i < n; i++) {
82  double a1i = i + 1;
83  double a3i = 2. * i + 1;
84  double a4i = i;
85 
86  val[i + 1] = a3i * u * val[i];
87  if(i > 0) val[i + 1] -= a4i * val[i - 1];
88  val[i + 1] /= a1i;
89  }
90  }
91 
92  void fc(int n, double u, double *val)
93  {
94  f(n, u, val);
95  for(int i = 2; i < n + 1; ++i) {
96  if(i % 2)
97  val[i] -= u;
98  else
99  val[i] -= 1;
100  }
101  }
102 
103  void df(int n, double u, double *val)
104  {
105  // Indeterminate form for u == -1 and u == 1
106  if((u == 1.) || (u == -1.)) {
107  for(int k = 0; k <= n; k++) val[k] = 0.5 * k * (k + 1);
108  if((u == -1.) && (n >= 2))
109  for(int k = 2; k <= n; k += 2) val[k] = -val[k];
110  return;
111  }
112 
113  // Now general case
114 
115  // Values of the Legendre polynomials
116  std::vector<double> tmp(n + 1);
117  f(n, u, &(tmp[0]));
118 
119  // First value of the derivative
120  val[0] = 0;
121  double g2 = (1. - u * u);
122 
123  // Values of the derivative for orders > 1 computed from the values of the
124  // polynomials
125  for(int i = 1; i <= n; i++) {
126  double g1 = -u * i;
127  double g0 = (double)i;
128  val[i] = (g1 * tmp[i] + g0 * tmp[i - 1]) / g2;
129  }
130  }
131 } // namespace LegendrePolynomials
132 
133 namespace JacobiPolynomials {
134  void f(int n, double alpha, double beta, double u, double *val)
135  {
136  const double alphaPlusBeta = alpha + beta;
137  const double a2MinusB2 = alpha * alpha - beta * beta;
138  val[0] = 1.;
139  if(n >= 1)
140  val[1] = 0.5 * (2. * (alpha + 1.) + (alphaPlusBeta + 2.) * (u - 1.));
141 
142  for(int i = 1; i < n; i++) {
143  double ii = (double)i;
144  double twoI = 2. * ii;
145 
146  double a1i =
147  2. * (ii + 1.) * (ii + alphaPlusBeta + 1.) * (twoI + alphaPlusBeta);
148  double a2i = (twoI + alphaPlusBeta + 1.) * (a2MinusB2);
149  double a3i = Pochhammer(twoI + alphaPlusBeta, 3);
150  double a4i =
151  2. * (ii + alpha) * (ii + beta) * (twoI + alphaPlusBeta + 2.);
152 
153  val[i + 1] = ((a2i + a3i * u) * val[i] - a4i * val[i - 1]) / a1i;
154  }
155  }
156 
157  void df(int n, double alpha, double beta, double u, double *val)
158  {
159  const double alphaPlusBeta = alpha + beta;
160 
161  // Indeterminate form for u == -1 and u == 1
162  // TODO: Extend to non-integer alpha & beta?
163  if((u == 1.) || (u == -1.)) {
164  // alpha or beta in formula, depending on u
165  int coeff = (u == 1.) ? (int)alpha : (int)beta;
166 
167  // Compute factorial
168  const int fMax = std::max(n, 1) + coeff;
169  std::vector<double> fact(fMax + 1);
170  fact[0] = 1.;
171  for(int i = 1; i <= fMax; i++) fact[i] = i * fact[i - 1];
172 
173  // Compute formula (with appropriate sign at even orders for u == -1)
174  val[0] = 0.;
175  for(int k = 1; k <= n; k++)
176  val[k] = 0.5 * (k + alphaPlusBeta + 1) * fact[k + coeff] /
177  (fact[coeff + 1] * fact[k - 1]);
178  if((u == -1.) && (n >= 2))
179  for(int k = 2; k <= n; k += 2) val[k] = -val[k];
180 
181  return;
182  }
183 
184  // Now general case
185 
186  // Values of the Jacobi polynomials
187  std::vector<double> tmp(n + 1);
188  f(n, alpha, beta, u, &(tmp[0]));
189 
190  // First 2 values of the derivatives
191  val[0] = 0;
192  if(n >= 1) val[1] = 0.5 * (alphaPlusBeta + 2.);
193 
194  // Values of the derivative for orders > 1 computed from the values of the
195  // polynomials
196  for(int i = 2; i <= n; i++) {
197  double ii = (double)i;
198  double aa = (2. * ii + alphaPlusBeta);
199  double g2 = aa * (1. - u * u);
200  double g1 = ii * (alpha - beta - aa * u);
201  double g0 = 2. * (ii + alpha) * (ii + beta);
202  val[i] = (g1 * tmp[i] + g0 * tmp[i - 1]) / g2;
203  }
204  }
205 } // namespace JacobiPolynomials
orthogonalBasis.h
orthogonalBasis::_type
const int _type
Definition: orthogonalBasis.h:18
TYPE_LIN
#define TYPE_LIN
Definition: GmshDefines.h:65
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
TYPE_TRI
#define TYPE_TRI
Definition: GmshDefines.h:66
orthogonalBasis::integralfSquared
void integralfSquared(double *val) const
Definition: orthogonalBasis.cpp:53
LegendrePolynomials::fc
void fc(int n, double u, double *val)
Definition: orthogonalBasis.cpp:92
JacobiPolynomials::f
void f(int n, double alpha, double beta, double u, double *val)
Definition: orthogonalBasis.cpp:134
JacobiPolynomials
Definition: orthogonalBasis.cpp:133
pow_int
double pow_int(const double &a, const int &n)
Definition: Numeric.h:39
ElementType::getType
int getType(int parentType, int order, bool serendip=false)
Definition: ElementType.cpp:757
orthogonalBasis::f
void f(double u, double v, double w, double *sf) const
Definition: orthogonalBasis.cpp:20
Numeric.h
LegendrePolynomials
Definition: orthogonalBasis.cpp:76
orthogonalBasis::orthogonalBasis
orthogonalBasis()
LegendrePolynomials::df
void df(int n, double u, double *val)
Definition: orthogonalBasis.cpp:103
FuncSpaceData
Definition: FuncSpaceData.h:16
TYPE_QUA
#define TYPE_QUA
Definition: GmshDefines.h:67
FuncSpaceData.h
orthogonalBasis::_order
const int _order
Definition: orthogonalBasis.h:19
JacobiPolynomials::df
void df(int n, double alpha, double beta, double u, double *val)
Definition: orthogonalBasis.cpp:157
JacobiPolynomials::Pochhammer
double Pochhammer(double x, int n)
Definition: orthogonalBasis.h:41