gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
bezierBasis.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 #include <map>
7 #include <algorithm>
8 #include "bezierBasis.h"
9 #include "GmshDefines.h"
10 #include "GmshMessage.h"
11 #include "pyramidalBasis.h"
12 #include "pointsGenerators.h"
13 #include "BasisFactory.h"
14 #include "Numeric.h"
15 
16 namespace {
17 
18  // Exponents:
19  void generateExponents(FuncSpaceData data, fullMatrix<double> &exp)
20  {
22  }
23 
24  // Matrices generation
25  int nChoosek(int n, int k)
26  {
27  if(n < k || k < 0) {
28  Msg::Error("Wrong argument for combination. (%d, %d)", n, k);
29  return 1;
30  }
31 
32  if(k > n / 2) k = n - k;
33  if(k == 1) return n;
34  if(k == 0) return 1;
35 
36  int c = 1;
37  for(int i = 1; i <= k; i++, n--) (c *= n) /= i;
38  return c;
39  }
40 
41  fullMatrix<double> generateBez2LagMatrix(const fullMatrix<double> &exponent,
42  const fullMatrix<double> &point,
43  int order, int dimSimplex)
44  {
45  if(exponent.size1() != point.size1() || exponent.size2() != point.size2()) {
46  Msg::Error("Wrong sizes for bez2lag matrix generation %d %d -- %d %d",
47  exponent.size1(), point.size1(), exponent.size2(),
48  point.size2());
49  return fullMatrix<double>(1, 1);
50  }
51 
52  int ndofs = exponent.size1();
53  int dim = exponent.size2();
54 
55  fullMatrix<double> bez2Lag(ndofs, ndofs);
56  for(int i = 0; i < ndofs; i++) {
57  for(int j = 0; j < ndofs; j++) {
58  double dd = 1.;
59  {
60  double pointCompl = 1.;
61  int exponentCompl = order;
62  for(int k = 0; k < dimSimplex; k++) {
63  dd *= nChoosek(exponentCompl, (int)exponent(i, k)) *
64  pow(point(j, k), exponent(i, k));
65  pointCompl -= point(j, k);
66  exponentCompl -= (int)exponent(i, k);
67  }
68  dd *= pow(pointCompl, exponentCompl);
69  }
70 
71  for(int k = dimSimplex; k < dim; k++)
72  dd *= nChoosek(order, (int)exponent(i, k)) *
73  pow(point(j, k), exponent(i, k)) *
74  pow(1. - point(j, k), order - exponent(i, k));
75 
76  bez2Lag(j, i) = dd;
77  }
78  }
79  return bez2Lag;
80  }
81 
83  generateBez2LagMatrixPyramid(const fullMatrix<double> &exponent,
84  const fullMatrix<double> &point, bool pyr,
85  int nij, int nk)
86  {
87  // For pyramids, the space is hex-like and thus tensorial.
88  // 'point' is the list of points on a grid.
89  if(exponent.size1() != point.size1() || exponent.size2() != point.size2() ||
90  exponent.size2() != 3) {
91  Msg::Error(
92  "Wrong sizes for pyramid's bez2lag matrix generation %d %d -- %d %d",
93  exponent.size1(), point.size1(), exponent.size2(), point.size2());
94  return fullMatrix<double>(1, 1);
95  }
96 
97  const int ndofs = exponent.size1();
98 
99  int n01 = nij;
100  fullMatrix<double> bez2Lag(ndofs, ndofs);
101  for(int i = 0; i < ndofs; i++) {
102  for(int j = 0; j < ndofs; j++) {
103  if(pyr) n01 = exponent(j, 2) + nij;
104  bez2Lag(i, j) =
105  nChoosek(n01, exponent(j, 0)) * nChoosek(n01, exponent(j, 1)) *
106  nChoosek(nk, exponent(j, 2)) * pow_int(point(i, 0), exponent(j, 0)) *
107  pow_int(point(i, 1), exponent(j, 1)) *
108  pow_int(point(i, 2), exponent(j, 2)) *
109  pow_int(1. - point(i, 0), n01 - exponent(j, 0)) *
110  pow_int(1. - point(i, 1), n01 - exponent(j, 1)) *
111  pow_int(1. - point(i, 2), nk - exponent(j, 2));
112  }
113  }
114  return bez2Lag;
115  }
116 
117  void double2int(const fullMatrix<double> &matDouble, fullMatrix<int> &matInt)
118  {
119  matInt.resize(matDouble.size1(), matDouble.size2());
120  for(int i = 0; i < matDouble.size1(); ++i) {
121  for(int j = 0; j < matDouble.size2(); ++j) {
122  matInt(i, j) = static_cast<int>(matDouble(i, j) + .5);
123  }
124  }
125  }
126 
127  template <typename D>
128  void convertLag2Bez(const fullMatrix<double> &lag, int order, int start,
129  int inc, const fullVector<D> &x, fullMatrix<double> &bez)
130  {
131  // Algorithm to compute Bézier coefficients of f(x), x in [0, 1].
132  // f is given by the Lagrange expansion: the coefficients are 'lag'
133  // and the corresponding Lagrange basis polynomials are constructed with
134  // nodes 'x'. Those nodes should be in [0, 1] if we aim at expanding the
135  // "same" function in Bézier interpolation.
136  // See this paper for the details:
137  // "Computing the Bézier control points of the Lagrangian interpolant in
138  // arbitrary dimension" by M. Ainsworth and M. A. Sánchez
139  const int nColumns = lag.size2();
140  fullMatrix<D> f(order + 1, nColumns);
141  for(int i = start, n = 0; n <= order; i += inc, ++n) {
142  for(int j = 0; j < nColumns; ++j) { f(n, j) = lag(i, j); }
143  }
144  fullVector<D> w(order + 1);
145  w.setAll(0);
146  w(0) = 1;
147  fullMatrix<D> c(order + 1, nColumns);
148  for(int j = 0; j < nColumns; ++j) { c(0, j) = f(0, j); }
149  for(int s = 1; s <= order; ++s) {
150  for(int k = order; k >= s; --k) {
151  for(int j = 0; j < nColumns; ++j) {
152  f(k, j) = (f(k, j) - f(k - 1, j)) / (x(k) - x(k - s));
153  }
154  }
155  for(int k = s; k >= 1; --k) {
156  const D kk = static_cast<D>(k);
157  w(k) =
158  kk / s * w(k - 1) * (1 - x(s - 1)) - (1 - kk / s) * w(k) * x(s - 1);
159  for(int j = 0; j < nColumns; ++j) {
160  c(k, j) =
161  kk / s * c(k - 1, j) + (1 - kk / s) * c(k, j) + f(s, j) * w(k);
162  }
163  }
164  w(0) = -w(0) * x(s - 1);
165  for(int j = 0; j < nColumns; ++j) { c(0, j) = c(0, j) + f(s, j) * w(0); }
166  }
167  for(int i = start, n = 0; n <= order; i += inc, ++n) {
168  for(int j = 0; j < nColumns; ++j) {
169  bez(i, j) = static_cast<double>(c(n, j));
170  }
171  }
172  }
173 
174  void convertLag2Bez(const fullMatrix<double> &lag, int order,
175  const fullVector<double> &x, fullMatrix<double> &bez,
176  int start = -1, int inc = -1)
177  {
178  if(start < 0) start = 0;
179  if(inc < 1) inc = 1;
180  convertLag2Bez<double>(lag, order, start, inc, x, bez);
181  }
182 
183 } // namespace
184 
186  : _funcSpaceData(data), _raiser(nullptr)
187 {
189  _constructPyr();
190  else
191  _construct();
192 }
193 
195 {
196  if(_raiser != nullptr) {
197  delete _raiser;
198  }
199 }
200 
202 {
203  if(_funcSpaceData.getType() == TYPE_PYR) {
204  Msg::Error("This bezierBasis constructor is not for pyramids!");
205  return;
206  }
207 
208  int order = _funcSpaceData.getSpaceOrder();
209 
210  switch(_funcSpaceData.getType()) {
211  case TYPE_PNT:
212  _numLagCoeff = 1;
213  _dimSimplex = 0;
214  break;
215  case TYPE_LIN:
216  _numLagCoeff = order ? 2 : 1;
217  _dimSimplex = 0;
218  break;
219  case TYPE_TRI:
220  _numLagCoeff = order ? 3 : 1;
221  _dimSimplex = 2;
222  break;
223  case TYPE_QUA:
224  _numLagCoeff = order ? 4 : 1;
225  _dimSimplex = 0;
226  break;
227  case TYPE_TET:
228  _numLagCoeff = order ? 4 : 1;
229  _dimSimplex = 3;
230  break;
231  case TYPE_PRI:
232  _numLagCoeff = order ? 6 : 1;
233  _dimSimplex = 2;
234  break;
235  case TYPE_HEX:
236  _numLagCoeff = order ? 8 : 1;
237  _dimSimplex = 0;
238  break;
239  default:
240  Msg::Error("Unknown function space for parentType %d",
242  return;
243  }
244 
245  fullMatrix<double> samplingPntsBezDom;
246  gmshGenerateOrderedPoints(_funcSpaceData, samplingPntsBezDom, true);
247  generateExponents(_funcSpaceData, _exponents);
248 
249  fullMatrix<double> matBez2Lag =
250  generateBez2LagMatrix(_exponents, samplingPntsBezDom, order, _dimSimplex);
251  matBez2Lag.invert(_matrixLag2Bez);
252 
255 }
256 
258 {
259  if(_funcSpaceData.getType() != TYPE_PYR) {
260  Msg::Error("This bezierBasis constructor is for pyramids!");
261  }
262 
263  const bool pyr = _funcSpaceData.getPyramidalSpace();
264  const int nij = _funcSpaceData.getNij(), nk = _funcSpaceData.getNk();
265 
266  _numLagCoeff = nk == 0 ? 4 : 8;
267  _dimSimplex = 0;
268 
269  // Note that the sampling points for the Jacobian determinant of pyramids are
270  // for z in [0, a] with a < 1. The third coordinate of Bezier points should
271  // also be in [0, a]. The same for subpoints.
272  fullMatrix<double> samplingPntsBezDom;
273  gmshGenerateOrderedPoints(_funcSpaceData, samplingPntsBezDom, true);
274  generateExponents(_funcSpaceData, _exponents);
275 
276  fullMatrix<double> matBez2Lag =
277  generateBez2LagMatrixPyramid(_exponents, samplingPntsBezDom, pyr, nij, nk);
278  matBez2Lag.invert(_matrixLag2Bez);
279 
281 }
282 
284 {
285  if(!_raiser) {
286  const_cast<bezierBasis *>(this)->_raiser = new bezierBasisRaiser(this);
287  }
288  return _raiser;
289 }
290 
292 {
293  // Let f and g be two function whose Bezier coefficients f_i, g_i are
294  // given and let F = f*g. The Bézier coefficients of Fcan be computed as
295  // F_i = sum_(j,k) a_jk f_j * g_k
296  // This function compute the coefficients a_jk (and similarly for 3 functions)
297  if(_bfs->getType() == TYPE_PYR) {
299  return;
300  }
301 
302  fullMatrix<int> exp;
303  {
304  const fullMatrix<double> &expD = _bfs->_exponents;
305  double2int(expD, exp);
306  }
307  int order = _bfs->getOrder();
308  int ncoeff = exp.size1();
309  int dim = _bfs->getDim();
310  int dimSimplex = _bfs->getDimSimplex();
311 
312  // Speedup: Since the coefficients (num/den) are invariant from a permutation
313  // of the indices (i, j) or (i, j, k), we fill only the raiser data for
314  // i <= j <= k (and adapt the value to take into account the multiplicity).
315 
316  // Construction of raiser 2
317 
318  std::map<int, int> hashToInd2;
319  {
320  fullMatrix<int> exp2;
321  {
322  fullMatrix<double> expD2;
323  FuncSpaceData data(_bfs->_funcSpaceData, 2 * order);
324  generateExponents(data, expD2);
325  double2int(expD2, exp2);
326  _raiser2.resize(exp2.size1());
327  }
328 
329  for(int i = 0; i < exp2.size1(); ++i) {
330  int hash = 0;
331  for(int l = 0; l < dim; l++) {
332  hash += static_cast<int>(exp2(i, l) * pow_int(2 * order + 1, l));
333  }
334  hashToInd2[hash] = i;
335  }
336  }
337 
338  for(int i = 0; i < ncoeff; i++) {
339  for(int j = i; j < ncoeff; j++) {
340  double num = 1, den = 1;
341  {
342  int compl1 = order;
343  int compl2 = order;
344  int compltot = 2 * order;
345  for(int l = 0; l < dimSimplex; l++) {
346  num *= nChoosek(compl1, exp(i, l)) * nChoosek(compl2, exp(j, l));
347  den *= nChoosek(compltot, exp(i, l) + exp(j, l));
348  compl1 -= exp(i, l);
349  compl2 -= exp(j, l);
350  compltot -= exp(i, l) + exp(j, l);
351  }
352  for(int l = dimSimplex; l < dim; l++) {
353  num *= nChoosek(order, exp(i, l)) * nChoosek(order, exp(j, l));
354  den *= nChoosek(2 * order, exp(i, l) + exp(j, l));
355  }
356  }
357 
358  // taking into account the multiplicity (reminder: i <= j)
359  if(i < j) num *= 2;
360 
361  int hash = 0;
362  for(int l = 0; l < dim; l++) {
363  hash +=
364  static_cast<int>((exp(i, l) + exp(j, l)) * pow_int(2 * order + 1, l));
365  }
366  _raiser2[hashToInd2[hash]].push_back(_data(num / den, i, j));
367  }
368  }
369 
370  // Construction of raiser 3
371 
372  std::map<int, int> hashToInd3;
373  {
374  fullMatrix<int> exp3;
375  {
376  fullMatrix<double> expD3;
377  FuncSpaceData data(_bfs->_funcSpaceData, 3 * order);
378  generateExponents(data, expD3);
379  double2int(expD3, exp3);
380  _raiser3.resize(exp3.size1());
381  }
382 
383  for(int i = 0; i < exp3.size1(); ++i) {
384  int hash = 0;
385  for(int l = 0; l < dim; l++) {
386  hash += static_cast<int>(exp3(i, l) * pow_int(3 * order + 1, l));
387  }
388  hashToInd3[hash] = i;
389  }
390  }
391 
392  for(int i = 0; i < ncoeff; i++) {
393  for(int j = i; j < ncoeff; j++) {
394  for(int k = j; k < ncoeff; ++k) {
395  double num = 1, den = 1;
396  {
397  int compl1 = order;
398  int compl2 = order;
399  int compl3 = order;
400  int compltot = 3 * order;
401  for(int l = 0; l < dimSimplex; l++) {
402  num *= nChoosek(compl1, exp(i, l)) * nChoosek(compl2, exp(j, l)) *
403  nChoosek(compl3, exp(k, l));
404  den *= nChoosek(compltot, exp(i, l) + exp(j, l) + exp(k, l));
405  compl1 -= exp(i, l);
406  compl2 -= exp(j, l);
407  compl3 -= exp(k, l);
408  compltot -= exp(i, l) + exp(j, l) + exp(k, l);
409  }
410  for(int l = dimSimplex; l < dim; l++) {
411  num *= nChoosek(order, exp(i, l)) * nChoosek(order, exp(j, l)) *
412  nChoosek(order, exp(k, l));
413  den *= nChoosek(3 * order, exp(i, l) + exp(j, l) + exp(k, l));
414  }
415  }
416 
417  // taking into account the multiplicity (Reminder: i <= j <= k)
418  if(i < j && j < k)
419  num *= 6;
420  else if(i < j || j < k)
421  num *= 3;
422 
423  int hash = 0;
424  for(int l = 0; l < dim; l++) {
425  hash += static_cast<int>((exp(i, l) + exp(j, l) + exp(k, l)) *
426  pow_int(3 * order + 1, l));
427  }
428  _raiser3[hashToInd3[hash]].push_back(_data(num / den, i, j, k));
429  }
430  }
431  }
432 }
433 
435 {
436  // Let f and g be two function whose Bezier coefficients f_i, g_i are
437  // given and let F = f*g. The Bézier coefficients of Fcan be computed as
438  // F_i = sum_(j,k) a_jk f_j * g_k
439  // This function compute the coefficients a_jk (and similarly for 3 functions)
440  FuncSpaceData fsdata = _bfs->getFuncSpaceData();
441  if(fsdata.getType() != TYPE_PYR) {
442  _fillRaiserData();
443  return;
444  }
445  if(fsdata.getPyramidalSpace()) {
446  Msg::Error("Bezier raiser not implemented for pyramidal space");
447  return;
448  }
449 
450  fullMatrix<int> exp;
451  {
452  const fullMatrix<double> &expD = _bfs->_exponents;
453  double2int(expD, exp);
454  }
455  int ncoeff = exp.size1();
456  int order[3] = {fsdata.getNij(), fsdata.getNij(), fsdata.getNk()};
457  int orderHash = std::max(order[0], order[2]);
458 
459  // Speedup: Since the coefficients (num/den) are invariant from a permutation
460  // of the indices (i, j) or (i, j, k), we fill only the raiser data for i <= j
461  // <= k (and adapt the value to take into account the multiplicity).
462 
463  std::map<int, int> hashToInd2;
464  {
465  fullMatrix<int> exp2;
466  {
467  fullMatrix<double> expD2;
468  FuncSpaceData data(_bfs->_funcSpaceData, 2 * order[0], 2 * order[2]);
469  generateExponents(data, expD2);
470  double2int(expD2, exp2);
471  _raiser2.resize(exp2.size1());
472  }
473 
474  for(int i = 0; i < exp2.size1(); ++i) {
475  int hash = 0;
476  for(int l = 0; l < 3; l++) {
477  hash += static_cast<int>(exp2(i, l) * pow_int(2 * orderHash + 1, l));
478  }
479  hashToInd2[hash] = i;
480  }
481  }
482 
483  for(int i = 0; i < ncoeff; i++) {
484  for(int j = i; j < ncoeff; j++) {
485  double num = 1, den = 1;
486  for(int l = 0; l < 3; l++) {
487  num *= nChoosek(order[l], exp(i, l)) * nChoosek(order[l], exp(j, l));
488  den *= nChoosek(2 * order[l], exp(i, l) + exp(j, l));
489  }
490 
491  // taking into account the multiplicity (reminder: i <= j)
492  if(i < j) num *= 2;
493 
494  int hash = 0;
495  for(int l = 0; l < 3; l++) {
496  hash += static_cast<int>((exp(i, l) + exp(j, l)) *
497  pow_int(2 * orderHash + 1, l));
498  }
499  _raiser2[hashToInd2[hash]].push_back(_data(num / den, i, j));
500  }
501  }
502 
503  // Construction of raiser 3
504 
505  std::map<int, int> hashToInd3;
506  {
507  fullMatrix<int> exp3;
508  {
509  fullMatrix<double> expD3;
510  FuncSpaceData data(_bfs->_funcSpaceData, 3 * order[0], 3 * order[2]);
511  generateExponents(data, expD3);
512  double2int(expD3, exp3);
513  _raiser3.resize(exp3.size1());
514  }
515 
516  for(int i = 0; i < exp3.size1(); ++i) {
517  int hash = 0;
518  for(int l = 0; l < 3; l++) {
519  hash += static_cast<int>(exp3(i, l) * pow_int(3 * orderHash + 1, l));
520  }
521  hashToInd3[hash] = i;
522  }
523  }
524 
525  for(int i = 0; i < ncoeff; i++) {
526  for(int j = i; j < ncoeff; j++) {
527  for(int k = j; k < ncoeff; ++k) {
528  double num = 1, den = 1;
529  for(int l = 0; l < 3; l++) {
530  num *= nChoosek(order[l], exp(i, l)) * nChoosek(order[l], exp(j, l)) *
531  nChoosek(order[l], exp(k, l));
532  den *= nChoosek(3 * order[l], exp(i, l) + exp(j, l) + exp(k, l));
533  }
534 
535  // taking into account the multiplicity (Reminder: i <= j <= k)
536  if(i < j && j < k)
537  num *= 6;
538  else if(i < j || j < k)
539  num *= 3;
540 
541  int hash = 0;
542  for(int l = 0; l < 3; l++) {
543  hash += static_cast<int>((exp(i, l) + exp(j, l) + exp(k, l)) *
544  pow_int(3 * orderHash + 1, l));
545  }
546  _raiser3[hashToInd3[hash]].push_back(_data(num / den, i, j, k));
547  }
548  }
549  }
550 }
551 
553  const fullVector<double> &coeffB,
554  fullVector<double> &coeffSquare) const
555 {
556  coeffSquare.resize(_raiser2.size(), true);
557 
558  if(&coeffA == &coeffB) {
559  for(std::size_t ind = 0; ind < _raiser2.size(); ++ind) {
560  for(std::size_t l = 0; l < _raiser2[ind].size(); ++l) {
561  const _data &d = _raiser2[ind][l];
562  coeffSquare(ind) += d.val * coeffA(d.i) * coeffB(d.j);
563  }
564  }
565  }
566  else {
567  for(std::size_t ind = 0; ind < _raiser2.size(); ++ind) {
568  for(std::size_t l = 0; l < _raiser2[ind].size(); ++l) {
569  const _data &d = _raiser2[ind][l];
570  coeffSquare(ind) +=
571  d.val / 2 * (coeffA(d.i) * coeffB(d.j) + coeffA(d.j) * coeffB(d.i));
572  }
573  }
574  }
575 }
576 
578  const fullVector<double> &coeffB,
579  const fullVector<double> &coeffC,
580  fullVector<double> &coeffCubic) const
581 {
582  coeffCubic.resize(_raiser3.size(), true);
583 
584  if(&coeffA == &coeffB && &coeffB == &coeffC) {
585  for(std::size_t ind = 0; ind < _raiser3.size(); ++ind) {
586  for(std::size_t l = 0; l < _raiser3[ind].size(); ++l) {
587  const _data &d = _raiser3[ind][l];
588  coeffCubic(ind) += d.val * coeffA(d.i) * coeffB(d.j) * coeffC(d.k);
589  }
590  }
591  }
592  else if(&coeffA != &coeffB && &coeffB != &coeffC) {
593  for(std::size_t ind = 0; ind < _raiser3.size(); ++ind) {
594  for(std::size_t l = 0; l < _raiser3[ind].size(); ++l) {
595  const _data &d = _raiser3[ind][l];
596  coeffCubic(ind) += d.val / 6 *
597  (coeffA(d.i) * coeffB(d.j) * coeffC(d.k) +
598  coeffA(d.i) * coeffB(d.k) * coeffC(d.j) +
599  coeffA(d.j) * coeffB(d.i) * coeffC(d.k) +
600  coeffA(d.j) * coeffB(d.k) * coeffC(d.i) +
601  coeffA(d.k) * coeffB(d.i) * coeffC(d.j) +
602  coeffA(d.k) * coeffB(d.j) * coeffC(d.i));
603  }
604  }
605  }
606  else
607  Msg::Error(
608  "bezierBasisRaiser::computeCoeff not implemented for A == B != C "
609  "or A != B == C");
610 }
611 
615 
617  const fullMatrix<double> &orderedLagCoeff, int num)
618  : _numPool(num), _funcSpaceData(fsData),
619  _basis(BasisFactory::getBezierBasis(fsData))
620 {
621  bool abort = false;
622  if(fsData.getSerendipity()) {
623  // Bezier interpolation cannot expand an incomplete function space
624  Msg::Error("Call of Bezier expansion for Serendipity space.");
625  abort = true;
626  }
627  if(!abort && orderedLagCoeff.size1() != _basis->getNumCoeff()) {
628  Msg::Error("Call of Bezier expansion with a wrong number of Lagrange "
629  "coefficients (%d vs %d).", orderedLagCoeff.size1(),
630  _basis->getNumCoeff());
631  abort = true;
632  }
633  if(abort) {
634  _r = 0;
635  _c = 0;
636  _ownData = false;
637  _numPool = -1;
638  return;
639  }
640 
641  _r = orderedLagCoeff.size1();
642  _c = orderedLagCoeff.size2();
643  _ownData = false;
644  if(num == 0 && _pool0)
645  _data = _pool0->giveBlock(this);
646  else if(num == 1 && _pool1)
647  _data = _pool1->giveBlock(this);
648  else {
649  _ownData = true;
650  _data = new double[_r * _c];
651  }
652 
653  _computeCoefficients(orderedLagCoeff.getDataPtr());
654 }
655 
657  const fullVector<double> &orderedLagCoeff, int num)
658  : _numPool(num), _funcSpaceData(fsData),
659  _basis(BasisFactory::getBezierBasis(fsData))
660 {
661  bool abort = false;
662  if(fsData.getSerendipity()) {
663  // Bezier interpolation cannot expand an incomplete function space
664  Msg::Error("Call of Bezier expansion for Serendipity space.");
665  abort = true;
666  }
667  if(!abort && orderedLagCoeff.size() != _basis->getNumCoeff()) {
668  Msg::Error("Call of Bezier expansion with a wrong number of Lagrange "
669  "coefficients (%d vs %d).", orderedLagCoeff.size(),
670  _basis->getNumCoeff());
671  abort = true;
672  }
673  if(abort) {
674  _r = 0;
675  _c = 0;
676  _ownData = false;
677  _numPool = -1;
678  return;
679  }
680 
681  _r = orderedLagCoeff.size();
682  _c = 1;
683  _ownData = false;
684  if(num == 0 && _pool0)
685  _data = _pool0->giveBlock(this);
686  else if(num == 1 && _pool1)
687  _data = _pool1->giveBlock(this);
688  else {
689  _ownData = true;
690  _data = new double[_r * _c];
691  }
692 
693  _computeCoefficients(orderedLagCoeff.getDataPtr());
694 }
695 
697 {
698  _numPool = other._numPool;
700  _basis = other._basis;
701  _r = other._r;
702  _c = other._c;
703  if(swap) {
704  _ownData = other._ownData;
705  _data = other._data;
706  const_cast<bezierCoeff &>(other)._ownData = false;
707  const_cast<bezierCoeff &>(other)._numPool = -1;
708  }
709  else {
710  _ownData = false;
711  if(_numPool == 0 && _pool0)
712  _data = _pool0->giveBlock(this);
713  else if(_numPool == 1 && _pool1)
714  _data = _pool1->giveBlock(this);
715  else {
716  _ownData = true;
717  _data = new double[_r * _c];
718  }
719  for(int i = 0; i < _r * _c; ++i) { _data[i] = other._data[i]; }
720  }
721 }
722 
724 {
725  if(_ownData)
726  delete[] _data;
727  else {
728  if(_numPool == -1) return;
729  if(_numPool == 0 && _pool0)
730  _pool0->releaseBlock(_data, this);
731  else if(_numPool == 1 && _pool1)
732  _pool1->releaseBlock(_data, this);
733  else
734  Msg::Error("Not supposed to be here. destructor bezierCoeff");
735  }
736 }
737 
738 void bezierCoeff::_computeCoefficients(const double *lagCoeffDataConst)
739 {
740  // FIXME: Use Leja order? (if yes, change gmshGenerateOrderedPoints and look
741  // at commit c84dedaa878f5ad58f68ef098979379ed3b57514)
742  const int type = _funcSpaceData.getType();
743  const int order = _funcSpaceData.getSpaceOrder();
744  const int npt = order + 1;
745  const fullMatrix<double> lag(const_cast<double *>(lagCoeffDataConst), _r, _c);
747  fullMatrix<double> bez(_data, _r, _c);
748 
749  switch(type) {
750  case TYPE_TRI:
751  case TYPE_TET:
752  // Note: For simplices, less significant errors in _matrixLag2Bez but
753  // an algorithm exists (see same paper than algo convertLag2Bez), yet
754  // it is complex. It may be implemented in the future if it is necessary.
755  _basis->_matrixLag2Bez.mult(lag, bez);
756  return;
757  case TYPE_LIN: convertLag2Bez(lag, order, x, bez); return;
758  case TYPE_QUA:
759  for(int i = 0; i < npt; ++i) convertLag2Bez(lag, order, x, bez, i, npt);
760  for(int j = 0; j < npt; ++j) convertLag2Bez(bez, order, x, bez, j * npt, 1);
761  return;
762  case TYPE_HEX:
763  for(int ij = 0; ij < npt * npt; ++ij) {
764  convertLag2Bez(lag, order, x, bez, ij, npt * npt);
765  }
766  for(int i = 0; i < npt; ++i) {
767  for(int k = 0; k < npt; ++k) {
768  convertLag2Bez(bez, order, x, bez, i + k * npt * npt, npt);
769  }
770  }
771  for(int jk = 0; jk < npt * npt; ++jk) {
772  convertLag2Bez(bez, order, x, bez, jk * npt, 1);
773  }
774  return;
775  case TYPE_PYR: {
776  // Pyramids space is tensorial like the hex
777  const int nbij = _funcSpaceData.getNij() + 1;
778  const int nbk = _funcSpaceData.getNk() + 1;
779  fullVector<double> xij, xk;
780  gmshGenerateOrderedPointsLine(nbij - 1, xij);
781  gmshGenerateOrderedPointsLine(nbk - 1, xk);
782  for(int ij = 0; ij < nbij * nbij; ++ij) {
783  convertLag2Bez(lag, nbk - 1, xk, bez, ij, nbij * nbij);
784  }
785  for(int i = 0; i < nbij; ++i) {
786  for(int k = 0; k < nbk; ++k) {
787  convertLag2Bez(bez, nbij - 1, xij, bez, i + k * nbij * nbij, nbij);
788  }
789  }
790  for(int jk = 0; jk < nbij * nbk; ++jk) {
791  convertLag2Bez(bez, nbij - 1, xij, bez, jk * nbij, 1);
792  }
793  return;
794  }
795  case TYPE_PRI: {
796  // Prism space is a mix of triangular space and linear space
797  double *lagCoeffData = const_cast<double *>(lagCoeffDataConst);
798  const bezierBasis *fsTri = BasisFactory::getBezierBasis(TYPE_TRI, order);
799  const int nptTri = (order + 2) * (order + 1) / 2;
800  fullVector<double> proxLag;
801  fullVector<double> proxBez;
802  for(int k = 0; k < npt; ++k) {
803  for(int c = 0; c < _c; ++c) {
804  const int inc = c * _r + k * nptTri;
805  proxLag.setAsProxy(lagCoeffData + inc, nptTri);
806  proxBez.setAsProxy(_data + inc, nptTri);
807  fsTri->_matrixLag2Bez.mult(proxLag, proxBez);
808  }
809  }
810  for(int ij = 0; ij < nptTri; ++ij) {
811  convertLag2Bez(bez, order, x, bez, ij, nptTri);
812  }
813  return;
814  }
815  }
816 }
817 
818 void bezierCoeff::usePools(std::size_t size0, std::size_t size1)
819 {
820  if(size0) {
821  if(!_pool0) _pool0 = new bezierCoeffMemoryPool();
822  _pool0->setSizeBlocks(size0);
823  }
824  if(size1) {
825  if(!_pool1) _pool1 = new bezierCoeffMemoryPool();
826  _pool1->setSizeBlocks(size1);
827  }
828 }
829 
831 {
832  delete _pool0;
833  delete _pool1;
834  _pool0 = nullptr;
835  _pool1 = nullptr;
836 }
837 
839 {
840  if(_ownData)
841  Msg::Error("I own data, cannot do that");
842  else
843  _data += diff;
844 }
845 
847 {
848  const int order = _funcSpaceData.getSpaceOrder();
849  switch(_funcSpaceData.getType()) {
850  case TYPE_TRI:
851  switch(i) {
852  case 0: return 0;
853  case 1: return order;
854  case 2: return _r - 1;
855  }
856  case TYPE_QUA:
857  switch(i) {
858  case 0: return 0;
859  case 1: return order;
860  case 2: return _r - 1;
861  case 3: return _r - 1 - order;
862  }
863  case TYPE_TET:
864  switch(i) {
865  case 0: return 0;
866  case 1: return order;
867  case 2: return (order + 2) * (order + 1) / 2 - 1;
868  case 3: return _r - 1;
869  }
870  case TYPE_HEX:
871  switch(i) {
872  case 0: return 0;
873  case 1: return order;
874  case 2: return (order + 1) * (order + 1) - 1;
875  case 3: return (order + 1) * order;
876  case 4: return (order + 1) * (order + 1) * order;
877  case 5: return (order + 1) * (order + 1) * order + order;
878  case 6: return _r - 1;
879  case 7: return (order + 2) * (order + 1) * order;
880  }
881  case TYPE_PRI:
882  switch(i) {
883  case 0: return 0;
884  case 1: return order;
885  case 2: return (order + 2) * (order + 1) / 2 - 1;
886  case 3: return (order + 2) * (order + 1) / 2 * order;
887  case 4: return (order + 2) * (order + 1) / 2 * order + order;
888  case 5: return _r - 1;
889  }
890  case TYPE_PYR:
892  switch(i) {
893  case 0: return 0;
894  case 1: return order;
895  case 2: return (order + 1) * (order + 1) - 1;
896  case 3: return (order + 1) * order;
897  case 4: return _r - 1;
898  }
899  }
900  else {
901  const int nij = _funcSpaceData.getNij();
902  const int nk = _funcSpaceData.getNk();
903  switch(i) {
904  case 0: return 0;
905  case 1: return nij;
906  case 2: return (nij + 1) * (nij + 1) - 1;
907  case 3: return (nij + 1) * nij;
908  case 4: return (nij + 1) * (nij + 1) * nk;
909  case 5: return (nij + 1) * (nij + 1) * nk + nij;
910  case 6: return _r - 1;
911  case 7: return (nij + 1) * (nij + 1) * nk + (nij + 1) * nij;
912  }
913  }
914  default:
915  Msg::Error("type %d not implemented in getIdxCornerCoeff",
917  return 0;
918  }
919 }
920 
922 {
923  const int n = getNumCornerCoeff();
924  v.resize(n);
925  for(int i = 0; i < n; ++i) { v(i) = getCornerCoeff(i); }
926 }
927 
929 {
930  const int n = getNumCornerCoeff();
931  m.resize(n, _c);
932  for(int i = 0; i < n; ++i) {
933  const int k = getIdxCornerCoeff(i);
934  for(int j = 0; j < _c; ++j) { m(i, j) = _data[k + _r * j]; }
935  }
936 }
937 
938 void bezierCoeff::subdivide(std::vector<bezierCoeff *> &subCoeff) const
939 {
940  if(subCoeff.size()) {
941  Msg::Warning("expected empty vector of bezierCoeff");
942  subCoeff.clear();
943  }
944 
945  switch(_funcSpaceData.getType()) {
946  case TYPE_TRI:
947  for(int i = 0; i < 4; ++i) subCoeff.push_back(new bezierCoeff(*this));
948  _subdivideTriangle(*this, 0, subCoeff);
949  return;
950  case TYPE_QUA:
951  for(int i = 0; i < 4; ++i) subCoeff.push_back(new bezierCoeff(*this));
952  _subdivideQuadrangle(*this, subCoeff);
953  return;
954  case TYPE_TET:
955  for(int i = 0; i < 8; ++i) subCoeff.push_back(new bezierCoeff(*this));
956  _subdivideTetrahedron(*this, subCoeff);
957  return;
958  case TYPE_HEX:
959  for(int i = 0; i < 8; ++i) subCoeff.push_back(new bezierCoeff(*this));
960  _subdivideHexahedron(*this, subCoeff);
961  return;
962  case TYPE_PRI:
963  for(int i = 0; i < 8; ++i) subCoeff.push_back(new bezierCoeff(*this));
964  _subdividePrism(*this, subCoeff);
965  return;
966  case TYPE_PYR:
967  for(int i = 0; i < 8; ++i) subCoeff.push_back(new bezierCoeff(*this));
968  _subdividePyramid(*this, subCoeff);
969  return;
970  }
971 }
972 
973 void bezierCoeff::_subdivide(fullMatrix<double> &coeff, int npts, int start)
974 {
975  // One-dimensional De Casteljau algorithm if consecutive data
976  const int dim = coeff.size2();
977  for(int iter = 1; iter < npts; ++iter) {
978  for(int I = start + iter; I < start + 2 * npts - iter; I += 2) {
979  for(int K = 0; K < dim; ++K) {
980  coeff(I, K) = .5 * (coeff(I - 1, K) + coeff(I + 1, K));
981  }
982  }
983  }
984 }
985 
986 void bezierCoeff::_subdivide(fullMatrix<double> &coeff, int npts, int start,
987  int inc)
988 {
989  // One-dimensional De Casteljau algorithm if non-consecutive data
990  const int dim = coeff.size2();
991  for(int iter = 1; iter < npts; ++iter) {
992  for(int i = iter; i < 2 * npts - iter; i += 2) {
993  int I = start + i * inc;
994  for(int K = 0; K < dim; ++K) {
995  coeff(I, K) = .5 * (coeff(I - inc, K) + coeff(I + inc, K));
996  }
997  }
998  }
999 }
1000 
1001 void bezierCoeff::_subdivideTriangle(const bezierCoeff &coeff, int start,
1002  std::vector<bezierCoeff *> &vSubCoeff)
1003 {
1004  const int n = coeff.getPolynomialOrder() + 1;
1005  const int dim = coeff._c;
1006 
1007  bezierCoeff &sub1 = *vSubCoeff[0];
1008  bezierCoeff &sub2 = *vSubCoeff[1];
1009  bezierCoeff &sub3 = *vSubCoeff[2];
1010  bezierCoeff &sub4 = *vSubCoeff[3];
1011 
1012  // copy into first subdomain
1013  if(&coeff != &sub1) _copy(coeff, start, (n + 1) * n / 2, sub1);
1014 
1015  // Subdivide in u direction
1016  // TODO: consider precompute vector<pair<int, int>> for this
1017  for(int iter = 1; iter < n; ++iter) {
1018  for(int j = 0; j < n - iter; ++j) {
1019  for(int i = n - 1 - j; i >= iter; --i) {
1020  const int I = start + _ij2Index(i, j, n);
1021  const int Im = start + _ij2Index(i - 1, j, n);
1022  for(int K = 0; K < dim; ++K) {
1023  sub1(I, K) = .5 * (sub1(Im, K) + sub1(I, K));
1024  }
1025  }
1026  }
1027  }
1028  // Subdivide in v direction
1029  for(int iter = 1; iter < n; ++iter) {
1030  for(int j = n - 1; j >= iter; --j) {
1031  for(int i = 0; i < n - j; ++i) {
1032  const int I = start + _ij2Index(i, j, n);
1033  const int Im = start + _ij2Index(i, j - 1, n);
1034  for(int K = 0; K < dim; ++K) {
1035  sub1(I, K) = .5 * (sub1(Im, K) + sub1(I, K));
1036  }
1037  }
1038  }
1039  }
1040 
1041  _copy(sub1, start, (n + 1) * n / 2, sub2);
1042  //
1043  // TODO: consider precompute vector<tuple<int, int, int>> for this
1044  for(int iter = 1; iter < n; ++iter) {
1045  for(int j = 0; j < n - iter; ++j) {
1046  for(int i = 0; i < n - iter - j; ++i) {
1047  const int I = start + _ij2Index(i, j, n);
1048  const int Ia = start + _ij2Index(i + 1, j, n);
1049  const int Ib = start + _ij2Index(i, j + 1, n);
1050  for(int K = 0; K < dim; ++K) {
1051  sub2(I, K) = sub2(Ia, K) + sub2(Ib, K) - sub2(I, K);
1052  }
1053  }
1054  }
1055  }
1056 
1057  _copy(sub2, start, (n + 1) * n / 2, sub3);
1058  for(int iter = 1; iter < n; ++iter) {
1059  for(int j = 0; j < n - iter; ++j) {
1060  for(int i = n - 1 - j; i >= iter; --i) {
1061  const int I = start + _ij2Index(i, j, n);
1062  const int Ia = start + _ij2Index(i - 1, j, n);
1063  const int Ib = start + _ij2Index(i - 1, j + 1, n);
1064  for(int K = 0; K < dim; ++K) {
1065  sub3(I, K) = sub3(Ia, K) + sub3(Ib, K) - sub3(I, K);
1066  }
1067  }
1068  }
1069  }
1070 
1071  _copy(sub2, start, (n + 1) * n / 2, sub4); // copy 2, not 3
1072  for(int iter = 1; iter < n; ++iter) {
1073  for(int j = n - 1; j >= iter; --j) {
1074  for(int i = 0; i < n - j; ++i) {
1075  const int I = start + _ij2Index(i, j, n);
1076  const int Ia = start + _ij2Index(i, j - 1, n);
1077  const int Ib = start + _ij2Index(i + 1, j - 1, n);
1078  for(int K = 0; K < dim; ++K) {
1079  sub4(I, K) = sub4(Ia, K) + sub4(Ib, K) - sub4(I, K);
1080  }
1081  }
1082  }
1083  }
1084 }
1085 
1087  bezierCoeff &coeff)
1088 {
1089  // TODO: consider precompute vector<pair<int, int>> for subdiv
1090  // consider precompute vector<pair<int, int, int>> for n_crosse_e
1091 
1092  const int dim = coeff.getNumColumns();
1093  switch(which) {
1094  case subdivU:
1095  for(int iter = 1; iter < n; ++iter) {
1096  for(int k = 0; k < n - iter; ++k) {
1097  for(int j = 0; j < n - iter - k; ++j) {
1098  for(int i = n - 1 - j - k; i >= iter; --i) {
1099  const int I = _ijk2Index(i, j, k, n);
1100  const int Im = _ijk2Index(i - 1, j, k, n);
1101  for(int K = 0; K < dim; ++K) {
1102  coeff(I, K) = .5 * (coeff(Im, K) + coeff(I, K));
1103  }
1104  }
1105  }
1106  }
1107  }
1108  return;
1109  case subdivV:
1110  for(int iter = 1; iter < n; ++iter) {
1111  for(int k = 0; k < n - iter; ++k) {
1112  for(int j = n - 1 - k; j >= iter; --j) {
1113  for(int i = 0; i < n - j - k; ++i) {
1114  const int I = _ijk2Index(i, j, k, n);
1115  const int Im = _ijk2Index(i, j - 1, k, n);
1116  for(int K = 0; K < dim; ++K) {
1117  coeff(I, K) = .5 * (coeff(Im, K) + coeff(I, K));
1118  }
1119  }
1120  }
1121  }
1122  }
1123  return;
1124  case subdivW:
1125  for(int iter = 1; iter < n; ++iter) {
1126  for(int k = n - 1; k >= iter; --k) {
1127  for(int j = 0; j < n - k; ++j) {
1128  for(int i = 0; i < n - j - k; ++i) {
1129  const int I = _ijk2Index(i, j, k, n);
1130  const int Im = _ijk2Index(i, j, k - 1, n);
1131  for(int K = 0; K < dim; ++K) {
1132  coeff(I, K) = .5 * (coeff(Im, K) + coeff(I, K));
1133  }
1134  }
1135  }
1136  }
1137  }
1138  return;
1139  // TODO: consider precompute vector<tuple<int, int, int>> for this
1140  case node0CrossEdge12:
1141  for(int iter = 1; iter < n; ++iter) {
1142  for(int k = 0; k < n - iter; ++k) {
1143  for(int j = 0; j < n - iter - k; ++j) {
1144  for(int i = 0; i < n - iter - j - k; ++i) {
1145  const int I = _ijk2Index(i, j, k, n);
1146  const int Ia = _ijk2Index(i + 1, j, k, n);
1147  const int Ib = _ijk2Index(i, j + 1, k, n);
1148  for(int K = 0; K < dim; ++K) {
1149  coeff(I, K) = coeff(Ia, K) + coeff(Ib, K) - coeff(I, K);
1150  }
1151  }
1152  }
1153  }
1154  }
1155  return;
1156  case node3CrossEdge12:
1157  for(int iter = 1; iter < n; ++iter) {
1158  for(int k = n - 1; k >= iter; --k) {
1159  for(int j = 0; j < n - k; ++j) {
1160  for(int i = 0; i < n - j - k; ++i) {
1161  const int I = _ijk2Index(i, j, k, n);
1162  const int Ia = _ijk2Index(i + 1, j, k - 1, n);
1163  const int Ib = _ijk2Index(i, j + 1, k - 1, n);
1164  for(int K = 0; K < dim; ++K) {
1165  coeff(I, K) = coeff(Ia, K) + coeff(Ib, K) - coeff(I, K);
1166  }
1167  }
1168  }
1169  }
1170  }
1171  return;
1172  case node1CrossEdge03:
1173  for(int iter = 1; iter < n; ++iter) {
1174  for(int k = 0; k < n - iter; ++k) {
1175  for(int j = 0; j < n - iter - k; ++j) {
1176  for(int i = n - 1 - j - k; i >= iter; --i) {
1177  const int I = _ijk2Index(i, j, k, n);
1178  const int Ia = _ijk2Index(i - 1, j, k, n);
1179  const int Ib = _ijk2Index(i - 1, j, k + 1, n);
1180  for(int K = 0; K < dim; ++K) {
1181  coeff(I, K) = coeff(Ia, K) + coeff(Ib, K) - coeff(I, K);
1182  }
1183  }
1184  }
1185  }
1186  }
1187  return;
1188  case node2CrossEdge03:
1189  for(int iter = 1; iter < n; ++iter) {
1190  for(int k = 0; k < n - iter; ++k) {
1191  for(int j = n - 1 - k; j >= iter; --j) {
1192  for(int i = 0; i < n - j - k; ++i) {
1193  const int I = _ijk2Index(i, j, k, n);
1194  const int Ia = _ijk2Index(i, j - 1, k, n);
1195  const int Ib = _ijk2Index(i, j - 1, k + 1, n);
1196  for(int K = 0; K < dim; ++K) {
1197  coeff(I, K) = coeff(Ia, K) + coeff(Ib, K) - coeff(I, K);
1198  }
1199  }
1200  }
1201  }
1202  }
1203  }
1204 }
1205 
1207  std::vector<bezierCoeff *> &vSubCoeff)
1208 {
1209  const int n = coeff.getPolynomialOrder() + 1;
1210  const int N = (n + 2) * (n + 1) * n / 6;
1211 
1212  bezierCoeff &sub1 = *vSubCoeff[0];
1213  bezierCoeff &sub2 = *vSubCoeff[1];
1214  bezierCoeff &sub3 = *vSubCoeff[2];
1215  bezierCoeff &sub4 = *vSubCoeff[3];
1216  bezierCoeff &sub5 = *vSubCoeff[4];
1217  bezierCoeff &sub6 = *vSubCoeff[5];
1218  bezierCoeff &sub7 = *vSubCoeff[6];
1219  bezierCoeff &sub8 = *vSubCoeff[7];
1220 
1221  // Corner (0,0,0)
1222  _copy(coeff, 0, N, sub1);
1223  _subdivideTet(subdivU, n, sub1);
1224  _subdivideTet(subdivV, n, sub1);
1225  _subdivideTet(subdivW, n, sub1);
1226 
1227  // Compute 4 middle ones
1228  _copy(sub1, 0, N, sub2);
1229  _subdivideTet(node0CrossEdge12, n, sub2);
1230 
1231  _copy(sub2, 0, N, sub3);
1232  _copy(sub2, 0, N, sub4);
1233  _subdivideTet(node1CrossEdge03, n, sub3);
1234  _subdivideTet(node2CrossEdge03, n, sub4);
1235 
1236  _copy(sub4, 0, N, sub5);
1237  _subdivideTet(node1CrossEdge03, n, sub5);
1238 
1239  // 3 remaining corners
1240  _copy(sub3, 0, N, sub6);
1241  _copy(sub4, 0, N, sub7);
1242  _copy(sub5, 0, N, sub8);
1243  _subdivideTet(node3CrossEdge12, n, sub6);
1244  _subdivideTet(node3CrossEdge12, n, sub7);
1245  _subdivideTet(node0CrossEdge12, n, sub8);
1246  // node 3 cross edge 1-2
1247 }
1248 
1250  std::vector<bezierCoeff *> &subCoeff)
1251 {
1252  const int n = coeff.getPolynomialOrder() + 1;
1253  const int N = 2 * n - 1;
1254  const int dim = coeff._c;
1255  _sub.resize(N * N, dim, false);
1256  for(int i = 0; i < n; ++i) {
1257  for(int j = 0; j < n; ++j) {
1258  const int I1 = i + j * n;
1259  const int I2 = (2 * i) + (2 * j) * N;
1260  for(int k = 0; k < dim; ++k) { _sub(I2, k) = coeff(I1, k); }
1261  }
1262  }
1263  for(int i = 0; i < N; i += 2) { _subdivide(_sub, n, i, N); }
1264  for(int j = 0; j < N; ++j) { _subdivide(_sub, n, j * N); }
1265  _copyQuad(_sub, n, 0, 0, *subCoeff[0]);
1266  _copyQuad(_sub, n, n - 1, 0, *subCoeff[1]);
1267  _copyQuad(_sub, n, 0, n - 1, *subCoeff[2]);
1268  _copyQuad(_sub, n, n - 1, n - 1, *subCoeff[3]);
1269  return;
1270 }
1271 
1273  std::vector<bezierCoeff *> &subCoeff)
1274 {
1275  const int n = coeff.getPolynomialOrder() + 1;
1276  const int N = 2 * n - 1;
1277  const int dim = coeff._c;
1278  _sub.resize(N * N * N, dim, false);
1279  for(int i = 0; i < n; ++i) {
1280  for(int j = 0; j < n; ++j) {
1281  for(int k = 0; k < n; ++k) {
1282  const int I1 = i + j * n + k * n * n;
1283  const int I2 = (2 * i) + (2 * j) * N + (2 * k) * N * N;
1284  for(int k = 0; k < dim; ++k) { _sub(I2, k) = coeff(I1, k); }
1285  }
1286  }
1287  }
1288  for(int i = 0; i < N; i += 2) {
1289  for(int j = 0; j < N; j += 2) { _subdivide(_sub, n, i + j * N, N * N); }
1290  }
1291  for(int i = 0; i < N; i += 2) {
1292  for(int k = 0; k < N; ++k) { _subdivide(_sub, n, i + k * N * N, N); }
1293  }
1294  for(int j = 0; j < N; ++j) {
1295  for(int k = 0; k < N; ++k) { _subdivide(_sub, n, j * N + k * N * N); }
1296  }
1297  _copyHex(_sub, n, 0, 0, 0, *subCoeff[0]);
1298  _copyHex(_sub, n, n - 1, 0, 0, *subCoeff[1]);
1299  _copyHex(_sub, n, 0, n - 1, 0, *subCoeff[2]);
1300  _copyHex(_sub, n, n - 1, n - 1, 0, *subCoeff[3]);
1301  _copyHex(_sub, n, 0, 0, n - 1, *subCoeff[4]);
1302  _copyHex(_sub, n, n - 1, 0, n - 1, *subCoeff[5]);
1303  _copyHex(_sub, n, 0, n - 1, n - 1, *subCoeff[6]);
1304  _copyHex(_sub, n, n - 1, n - 1, n - 1, *subCoeff[7]);
1305  return;
1306 }
1307 
1309  std::vector<bezierCoeff *> &subCoeff)
1310 {
1311  const int n = coeff.getPolynomialOrder() + 1;
1312  const int ntri = (n + 1) * n / 2;
1313  const int N = 2 * n - 1;
1314  const int dim = coeff._c;
1315 
1316  // First, use De Casteljau algorithm in 3rd direction (=> 2 subdomains):
1317  _sub.resize(N * ntri, dim, false);
1318  for(int k = 0; k < n; ++k) {
1319  for(int i = 0; i < ntri; ++i) {
1320  const int I1 = i + k * ntri;
1321  const int I2 = i + (2 * k) * ntri;
1322  for(int l = 0; l < dim; ++l) { _sub(I2, l) = coeff(I1, l); }
1323  }
1324  }
1325  for(int i = 0; i < ntri; ++i) { _subdivide(_sub, n, i, ntri); }
1326 
1327  // Copy first subdomain into subCoeff[0] and second one into subCoeff2[0]
1328  std::vector<bezierCoeff *> subCoeff2;
1329  subCoeff2.push_back(subCoeff[4]);
1330  subCoeff2.push_back(subCoeff[5]);
1331  subCoeff2.push_back(subCoeff[6]);
1332  subCoeff2.push_back(subCoeff[7]);
1333  _copyLine(_sub, n * ntri, 0, *subCoeff[0]);
1334  _copyLine(_sub, n * ntri, (n - 1) * ntri, *subCoeff2[0]);
1335 
1336  // Second, subdivide in the triangular space:
1337  for(int k = 0; k < n; ++k) {
1338  _subdivideTriangle(*subCoeff[0], k * ntri, subCoeff);
1339  _subdivideTriangle(*subCoeff2[0], k * ntri, subCoeff2);
1340  }
1341  return;
1342 }
1343 
1345  std::vector<bezierCoeff *> &subCoeff)
1346 {
1347  const int nij = coeff._funcSpaceData.getNij();
1348  const int nk = coeff._funcSpaceData.getNk();
1349  const int Nij = 2 * nij - 1;
1350  const int Nk = 2 * nk - 1;
1351  const int dim = coeff._c;
1352 
1353  _sub.resize(Nij * Nij * Nk, dim, false);
1354  for(int i = 0; i < nij; ++i) {
1355  for(int j = 0; j < nij; ++j) {
1356  for(int k = 0; k < nk; ++k) {
1357  const int I1 = i + j * nij + k * nij * nij;
1358  const int I2 = (2 * i) + (2 * j) * Nij + (2 * k) * Nij * Nij;
1359  for(int k = 0; k < dim; ++k) { _sub(I2, k) = coeff(I1, k); }
1360  }
1361  }
1362  }
1363  for(int i = 0; i < Nij; i += 2) {
1364  for(int j = 0; j < Nij; j += 2) {
1365  _subdivide(_sub, nk, i + j * Nij, Nij * Nij);
1366  }
1367  }
1368  for(int i = 0; i < Nij; i += 2) {
1369  for(int k = 0; k < Nk; ++k) {
1370  _subdivide(_sub, nij, i + k * Nij * Nij, Nij);
1371  }
1372  }
1373  for(int j = 0; j < Nij; ++j) {
1374  for(int k = 0; k < Nk; ++k) {
1375  _subdivide(_sub, nij, j * Nij + k * Nij * Nij);
1376  }
1377  }
1378  _copyPyr(_sub, nij, nk, 0, 0, 0, *subCoeff[0]);
1379  _copyPyr(_sub, nij, nk, nij - 1, 0, 0, *subCoeff[1]);
1380  _copyPyr(_sub, nij, nk, 0, nij - 1, 0, *subCoeff[2]);
1381  _copyPyr(_sub, nij, nk, nij - 1, nij - 1, 0, *subCoeff[3]);
1382  _copyPyr(_sub, nij, nk, 0, 0, nk - 1, *subCoeff[4]);
1383  _copyPyr(_sub, nij, nk, nij - 1, 0, nk - 1, *subCoeff[5]);
1384  _copyPyr(_sub, nij, nk, 0, nij - 1, nk - 1, *subCoeff[6]);
1385  _copyPyr(_sub, nij, nk, nij - 1, nij - 1, nk - 1, *subCoeff[7]);
1386  return;
1387 }
1388 
1389 void bezierCoeff::_copy(const bezierCoeff &from, int start, int num,
1390  bezierCoeff &to)
1391 {
1392  const int dim = from._c;
1393  for(int i = start; i < start + num; ++i) {
1394  for(int j = 0; j < dim; ++j) { to(i, j) = from(i, j); }
1395  }
1396 }
1397 
1398 void bezierCoeff::_copyLine(const fullMatrix<double> &allSub, int n, int start,
1399  bezierCoeff &sub)
1400 {
1401  const int dim = allSub.size2();
1402  for(int i = 0; i < n; ++i) {
1403  for(int K = 0; K < dim; ++K) { sub(i, K) = allSub(start + i, K); }
1404  }
1405 }
1406 
1407 void bezierCoeff::_copyQuad(const fullMatrix<double> &allSub, int n, int starti,
1408  int startj, bezierCoeff &sub)
1409 {
1410  const int dim = allSub.size2();
1411  const int N = 2 * n - 1;
1412  for(int i = 0; i < n; ++i) {
1413  for(int j = 0; j < n; ++j) {
1414  const int I1 = i + j * n;
1415  const int I2 = (starti + i) + (startj + j) * N;
1416  for(int K = 0; K < dim; ++K) { sub(I1, K) = allSub(I2, K); }
1417  }
1418  }
1419 }
1420 
1421 void bezierCoeff::_copyHex(const fullMatrix<double> &allSub, int n, int starti,
1422  int startj, int startk, bezierCoeff &sub)
1423 {
1424  const int dim = allSub.size2();
1425  const int N = 2 * n - 1;
1426  for(int i = 0; i < n; ++i) {
1427  for(int j = 0; j < n; ++j) {
1428  for(int k = 0; k < n; ++k) {
1429  const int I1 = i + j * n + k * n * n;
1430  const int I2 = (starti + i) + (startj + j) * N + (startk + k) * N * N;
1431  for(int K = 0; K < dim; ++K) { sub(I1, K) = allSub(I2, K); }
1432  }
1433  }
1434  }
1435 }
1436 
1437 void bezierCoeff::_copyPyr(const fullMatrix<double> &allSub, int nij, int nk,
1438  int starti, int startj, int startk, bezierCoeff &sub)
1439 {
1440  const int dim = allSub.size2();
1441  const int Nij = 2 * nij - 1;
1442  for(int i = 0; i < nij; ++i) {
1443  for(int j = 0; j < nij; ++j) {
1444  for(int k = 0; k < nk; ++k) {
1445  const int I1 = i + j * nij + k * nij * nij;
1446  const int I2 =
1447  (starti + i) + (startj + j) * Nij + (startk + k) * Nij * Nij;
1448  for(int K = 0; K < dim; ++K) { sub(I1, K) = allSub(I2, K); }
1449  }
1450  }
1451  }
1452 }
1453 
1455 {
1456  _sizeBlocks = 0;
1457  _numUsedBlocks = 0;
1459  _endOfSearch = 0;
1460 }
1461 
1463 {
1464  if(_numUsedBlocks) {
1465  Msg::Error("Cannot change size of blocks if %d blocks are still being "
1466  "used!",
1467  _numUsedBlocks);
1468  return;
1469  }
1471  _sizeBlocks = size;
1472  _endOfSearch = 0;
1473 }
1474 
1476 {
1478 
1479  if(_numUsedBlocks == _endOfSearch) {
1480  std::size_t idx = _endOfSearch;
1481  if(_bezierCoeff.size() == idx)
1482  _bezierCoeff.push_back(bez);
1483  else if(_bezierCoeff[idx]) {
1484  Msg::Error("this block is being used!?");
1485  return nullptr;
1486  }
1487  else
1488  _bezierCoeff[idx] = bez;
1489  ++_numUsedBlocks;
1490  ++_endOfSearch;
1491  return &_memory.front() + _sizeBlocks * idx;
1492  }
1493 
1494  for(std::size_t i = 0; i < _endOfSearch; ++i) {
1495  std::size_t idx = _currentIndexOfSearch;
1498  if(!_bezierCoeff[idx]) {
1499  _bezierCoeff[idx] = bez;
1500  ++_numUsedBlocks;
1501  return &_memory.front() + _sizeBlocks * idx;
1502  }
1503  }
1504 
1505  // We must never be here. If yes, this means that
1506  // _numUsedBlocks < _endOfSearch
1507  // and _bezierCoeff[i] for i < _endOfSearch are all different from
1508  // NULL which should never happens.
1509  Msg::Error("Wrong state of bezierCoeffMemoryPool."
1510  "_bezierCoeff[i] not correct?");
1511  return nullptr;
1512 }
1513 
1515 {
1516  long diff = block - &_memory.front();
1517  std::size_t idx = diff / _sizeBlocks;
1518  // if (_bezierCoeff[idx] == bez)
1519  // Msg::Info("It's a good guess!");
1520  // else
1521  // Msg::Info("Did not work :'( ");
1522  _bezierCoeff[idx] = nullptr;
1523  if(idx == _endOfSearch - 1) {
1524  do {
1525  --_endOfSearch;
1526  } while(_endOfSearch && !_bezierCoeff[_endOfSearch - 1]);
1527  _bezierCoeff.resize(_endOfSearch);
1529  }
1530  --_numUsedBlocks;
1531 }
1532 
1534 {
1535  if(_numUsedBlocks) {
1536  Msg::Error("I cannot free memory if some is still in use!");
1537  return;
1538  }
1539  // force deallocation:
1540  std::vector<double> dummy;
1541  _memory.swap(dummy);
1542 }
1543 
1545 {
1546  if(_numUsedBlocks < _memory.size() / _sizeBlocks) return;
1547 
1548  double *pointer = &_memory.front();
1549  _memory.resize(_memory.size() + _sizeBlocks);
1550 
1551  if(pointer == &_memory.front()) return;
1552 
1553  // If a reallocation has been performed at a different place of the memory,
1554  // then we need to update pointers
1555 
1556  long diff = &_memory.front() - pointer;
1557  for(std::size_t i = 0; i < _bezierCoeff.size(); ++i) {
1558  if(_bezierCoeff[i]) _bezierCoeff[i]->updateDataPtr(diff);
1559  }
1560 }
bezierBasis::getDimSimplex
int getDimSimplex() const
Definition: bezierBasis.h:44
D
#define D
Definition: DefaultOptions.h:24
bezierBasisRaiser::_data::k
int k
Definition: bezierBasis.h:68
bezierCoeff::usePools
static void usePools(std::size_t size0, std::size_t size1)
Definition: bezierBasis.cpp:818
bezierCoeff::getNumColumns
int getNumColumns() const
Definition: bezierBasis.h:170
BasisFactory
Definition: BasisFactory.h:17
fullVector::setAsProxy
void setAsProxy(const fullVector< scalar > &original, int r_start, int r)
Definition: fullMatrix.h:119
bezierCoeffMemoryPool::releaseBlock
void releaseBlock(double *block, bezierCoeff *bez)
Definition: bezierBasis.cpp:1514
bezierBasisRaiser::_data::j
int j
Definition: bezierBasis.h:68
bezierBasisRaiser::_data::val
double val
Definition: bezierBasis.h:69
pyramidalBasis.h
bezierBasis::_ordered1dBezPoints
fullVector< double > _ordered1dBezPoints
Definition: bezierBasis.h:29
bezierCoeff::getNumCornerCoeff
int getNumCornerCoeff() const
Definition: bezierBasis.h:171
bezierCoeff::_copyPyr
static void _copyPyr(const fullMatrix< double > &allSub, int nij, int nk, int starti, int startj, int startk, bezierCoeff &sub)
Definition: bezierBasis.cpp:1437
gmshGenerateOrderedMonomials
void gmshGenerateOrderedMonomials(FuncSpaceData data, fullMatrix< double > &monomials)
Definition: pointsGenerators.cpp:1165
fullVector
Definition: MElement.h:26
TYPE_LIN
#define TYPE_LIN
Definition: GmshDefines.h:65
bezierBasis::_exponents
fullMatrix< double > _exponents
Definition: bezierBasis.h:27
bezierCoeff::_subdivideTriangle
static void _subdivideTriangle(const bezierCoeff &coeff, int start, std::vector< bezierCoeff * > &subCoeff)
Definition: bezierBasis.cpp:1001
bezierBasis
Definition: bezierBasis.h:20
gmshGenerateOrderedPoints
void gmshGenerateOrderedPoints(FuncSpaceData data, fullMatrix< double > &points, bool onBezierDomain)
Definition: pointsGenerators.cpp:1080
c
static double c(int i, int j, fullMatrix< double > &CA, const std::vector< SPoint3 > &P, const std::vector< SPoint3 > &Q)
Definition: discreteFrechetDistance.cpp:15
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
bezierCoeff::subdivV
@ subdivV
Definition: bezierBasis.h:206
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
TYPE_PNT
#define TYPE_PNT
Definition: GmshDefines.h:64
bezierCoeff::_ij2Index
static int _ij2Index(int i, int j, int n)
Definition: bezierBasis.h:240
bezierBasisRaiser::_raiser2
std::vector< std::vector< _data > > _raiser2
Definition: bezierBasis.h:77
bezierCoeff::_sub
static fullMatrix< double > _sub
Definition: bezierBasis.h:138
fullVector::size
int size() const
Definition: fullMatrix.h:69
bezierCoeff::SubdivisionTet
SubdivisionTet
Definition: bezierBasis.h:204
TYPE_TRI
#define TYPE_TRI
Definition: GmshDefines.h:66
fullVector::resize
bool resize(int r, bool resetValue=true)
Definition: fullMatrix.h:103
bezierCoeffMemoryPool::_numUsedBlocks
std::size_t _numUsedBlocks
Definition: bezierBasis.h:105
bezierCoeff::_r
int _r
Definition: bezierBasis.h:132
bezierBasisRaiser::computeCoeff
void computeCoeff(const fullVector< double > &coeffA, const fullVector< double > &coeffB, fullVector< double > &coeffSquare) const
Definition: bezierBasis.cpp:552
FuncSpaceData::getNij
int getNij() const
Definition: FuncSpaceData.h:81
bezierCoeff::_copyQuad
static void _copyQuad(const fullMatrix< double > &allSub, int n, int starti, int startj, bezierCoeff &sub)
Definition: bezierBasis.cpp:1407
GmshMessage.h
bezierCoeff::_basis
const bezierBasis * _basis
Definition: bezierBasis.h:131
bezierCoeff::_copyHex
static void _copyHex(const fullMatrix< double > &allSub, int n, int starti, int startj, int startk, bezierCoeff &sub)
Definition: bezierBasis.cpp:1421
bezierCoeff::_subdividePyramid
static void _subdividePyramid(const bezierCoeff &coeff, std::vector< bezierCoeff * > &subCoeff)
Definition: bezierBasis.cpp:1344
TYPE_PRI
#define TYPE_PRI
Definition: GmshDefines.h:70
bezierBasis::bezierBasisRaiser
friend class bezierBasisRaiser
Definition: bezierBasis.h:32
bezierCoeffMemoryPool
Definition: bezierBasis.h:99
bezierCoeff::_funcSpaceData
FuncSpaceData _funcSpaceData
Definition: bezierBasis.h:130
bezierBasisRaiser::_fillRaiserData
void _fillRaiserData()
Definition: bezierBasis.cpp:291
bezierBasisRaiser::_data
Definition: bezierBasis.h:64
bezierCoeff::_subdividePrism
static void _subdividePrism(const bezierCoeff &coeff, std::vector< bezierCoeff * > &subCoeff)
Definition: bezierBasis.cpp:1308
bezierCoeff::_computeCoefficients
void _computeCoefficients(const double *lagCoeffData)
Definition: bezierBasis.cpp:738
FuncSpaceData::getPyramidalSpace
bool getPyramidalSpace() const
Definition: FuncSpaceData.h:84
bezierCoeff::_data
double * _data
Definition: bezierBasis.h:133
bezierCoeff::subdivide
void subdivide(std::vector< bezierCoeff * > &subCoeff) const
Definition: bezierBasis.cpp:938
fullMatrix< double >
bezierCoeff::_subdivideTet
static void _subdivideTet(SubdivisionTet which, int n, bezierCoeff &coeff)
Definition: bezierBasis.cpp:1086
bezierBasisRaiser::_bfs
const bezierBasis * _bfs
Definition: bezierBasis.h:78
bezierCoeff::_pool0
static bezierCoeffMemoryPool * _pool0
Definition: bezierBasis.h:136
bezierCoeff::_subdivideTetrahedron
static void _subdivideTetrahedron(const bezierCoeff &coeff, std::vector< bezierCoeff * > &vSubCoeff)
Definition: bezierBasis.cpp:1206
gmshGenerateOrderedPointsLine
void gmshGenerateOrderedPointsLine(int order, fullVector< double > &points)
Definition: pointsGenerators.cpp:1071
bezierCoeff::~bezierCoeff
~bezierCoeff()
Definition: bezierBasis.cpp:723
bezierBasis::_dimSimplex
int _dimSimplex
Definition: bezierBasis.h:24
bezierBasis::_funcSpaceData
const FuncSpaceData _funcSpaceData
Definition: bezierBasis.h:25
pow_int
double pow_int(const double &a, const int &n)
Definition: Numeric.h:39
bezierBasis::getNumCoeff
int getNumCoeff() const
Definition: bezierBasis.h:45
bezierCoeff::_subdivide
static void _subdivide(fullMatrix< double > &coeff, int npts, int start)
Definition: bezierBasis.cpp:973
bezierCoeff
Definition: bezierBasis.h:127
BasisFactory::getBezierBasis
static const bezierBasis * getBezierBasis(FuncSpaceData)
Definition: BasisFactory.cpp:128
bezierCoeff::getPolynomialOrder
int getPolynomialOrder() const
Definition: bezierBasis.h:165
bezierBasis::getOrder
int getOrder() const
Definition: bezierBasis.h:43
swap
void swap(double &a, double &b)
Definition: meshTriangulation.cpp:27
Numeric.h
bezierCoeffMemoryPool::_endOfSearch
std::size_t _endOfSearch
Definition: bezierBasis.h:107
bezierBasisRaiser::_raiser3
std::vector< std::vector< _data > > _raiser3
Definition: bezierBasis.h:77
bezierCoeff::bezierCoeff
bezierCoeff()
Definition: bezierBasis.h:145
bezierCoeff::getIdxCornerCoeff
int getIdxCornerCoeff(int i) const
Definition: bezierBasis.cpp:846
bezierCoeff::updateDataPtr
void updateDataPtr(long diff)
Definition: bezierBasis.cpp:838
GmshDefines.h
bezierCoeff::_copyLine
static void _copyLine(const fullMatrix< double > &allSub, int n, int starti, bezierCoeff &sub)
Definition: bezierBasis.cpp:1398
bezierBasis::_constructPyr
void _constructPyr()
Definition: bezierBasis.cpp:257
bezierCoeff::getCornerCoeffs
void getCornerCoeffs(fullVector< double > &) const
Definition: bezierBasis.cpp:921
FuncSpaceData::getNk
int getNk() const
Definition: FuncSpaceData.h:82
bezierCoeff::_subdivideQuadrangle
static void _subdivideQuadrangle(const bezierCoeff &coeff, std::vector< bezierCoeff * > &subCoeff)
Definition: bezierBasis.cpp:1249
bezierBasis::_samplingPntsLagDomain
fullMatrix< double > _samplingPntsLagDomain
Definition: bezierBasis.h:30
FuncSpaceData::getType
int getType() const
Definition: FuncSpaceData.h:65
bezierBasis::_matrixLag2Bez
fullMatrix< double > _matrixLag2Bez
Definition: bezierBasis.h:28
fullMatrix::size2
int size2() const
Definition: fullMatrix.h:275
bezierCoeff::_pool1
static bezierCoeffMemoryPool * _pool1
Definition: bezierBasis.h:137
TYPE_PYR
#define TYPE_PYR
Definition: GmshDefines.h:69
bezierCoeffMemoryPool::_sizeBlocks
std::size_t _sizeBlocks
Definition: bezierBasis.h:104
bezierCoeff::_ijk2Index
static int _ijk2Index(int i, int j, int k, int n)
Definition: bezierBasis.h:244
FuncSpaceData
Definition: FuncSpaceData.h:16
bezierBasisRaiser::_data::i
int i
Definition: bezierBasis.h:68
bezierCoeff::subdivW
@ subdivW
Definition: bezierBasis.h:207
bezierCoeff::_copy
static void _copy(const bezierCoeff &from, int start, int num, bezierCoeff &to)
Definition: bezierBasis.cpp:1389
bezierCoeffMemoryPool::_bezierCoeff
std::vector< bezierCoeff * > _bezierCoeff
Definition: bezierBasis.h:110
bezierCoeff::node2CrossEdge03
@ node2CrossEdge03
Definition: bezierBasis.h:211
TYPE_QUA
#define TYPE_QUA
Definition: GmshDefines.h:67
bezierCoeff::node1CrossEdge03
@ node1CrossEdge03
Definition: bezierBasis.h:210
bezierBasis::getFuncSpaceData
FuncSpaceData getFuncSpaceData() const
Definition: bezierBasis.h:47
FuncSpaceData::getSerendipity
bool getSerendipity() const
Definition: FuncSpaceData.h:83
fullVector::getDataPtr
const scalar * getDataPtr() const
Definition: fullMatrix.h:70
bezierCoeffMemoryPool::giveBlock
double * giveBlock(bezierCoeff *bez)
Definition: bezierBasis.cpp:1475
fullMatrix::size1
int size1() const
Definition: fullMatrix.h:274
bezierBasis::_numLagCoeff
int _numLagCoeff
Definition: bezierBasis.h:23
bezierCoeffMemoryPool::_checkEnoughMemory
void _checkEnoughMemory()
Definition: bezierBasis.cpp:1544
bezierBasisRaiser
Definition: bezierBasis.h:60
bezierCoeff::releasePools
static void releasePools()
Definition: bezierBasis.cpp:830
bezierCoeff::node3CrossEdge12
@ node3CrossEdge12
Definition: bezierBasis.h:209
bezierCoeff::getCornerCoeff
double getCornerCoeff(int k) const
Definition: bezierBasis.h:173
TYPE_HEX
#define TYPE_HEX
Definition: GmshDefines.h:71
bezierCoeffMemoryPool::bezierCoeffMemoryPool
bezierCoeffMemoryPool()
Definition: bezierBasis.cpp:1454
FuncSpaceData::getSpaceOrder
int getSpaceOrder() const
Definition: FuncSpaceData.h:80
fullMatrix::getDataPtr
const scalar * getDataPtr() const
Definition: fullMatrix.h:287
TYPE_TET
#define TYPE_TET
Definition: GmshDefines.h:68
bezierCoeff::_subdivideHexahedron
static void _subdivideHexahedron(const bezierCoeff &coeff, std::vector< bezierCoeff * > &subCoeff)
Definition: bezierBasis.cpp:1272
bezierCoeff::node0CrossEdge12
@ node0CrossEdge12
Definition: bezierBasis.h:208
bezierBasis::getRaiser
const bezierBasisRaiser * getRaiser() const
Definition: bezierBasis.cpp:283
bezierBasis::_raiser
bezierBasisRaiser * _raiser
Definition: bezierBasis.h:26
bezierBasis::getType
int getType() const
Definition: bezierBasis.h:42
bezierBasis::bezierBasis
bezierBasis(FuncSpaceData data)
Definition: bezierBasis.cpp:185
fullMatrix::mult
void mult(const fullVector< scalar > &x, fullVector< scalar > &y) const
Definition: fullMatrix.h:487
bezierCoeff::subdivU
@ subdivU
Definition: bezierBasis.h:205
pointsGenerators.h
fullMatrix::resize
bool resize(int r, int c, bool resetValue=true)
Definition: fullMatrix.h:307
bezierCoeffMemoryPool::freeMemory
void freeMemory()
Definition: bezierBasis.cpp:1533
bezierBasisRaiser::_fillRaiserDataPyr
void _fillRaiserDataPyr()
Definition: bezierBasis.cpp:434
bezierCoeffMemoryPool::_currentIndexOfSearch
std::size_t _currentIndexOfSearch
Definition: bezierBasis.h:106
bezierBasis.h
bezierCoeff::_c
int _c
Definition: bezierBasis.h:132
bezierBasis::_construct
void _construct()
Definition: bezierBasis.cpp:201
bezierCoeffMemoryPool::_memory
std::vector< double > _memory
Definition: bezierBasis.h:103
bezierCoeff::_numPool
int _numPool
Definition: bezierBasis.h:129
bezierBasis::getDim
int getDim() const
Definition: bezierBasis.h:41
fullMatrix::invert
bool invert(fullMatrix< scalar > &result) const
Definition: fullMatrix.h:641
bezierBasis::~bezierBasis
~bezierBasis()
Definition: bezierBasis.cpp:194
bezierCoeff::_ownData
bool _ownData
Definition: bezierBasis.h:134
BasisFactory.h
bezierCoeffMemoryPool::setSizeBlocks
void setSizeBlocks(std::size_t size)
Definition: bezierBasis.cpp:1462