gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
HighOrder.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 // Contributor(s):
7 // Koen Hillewaert
8 //
9 
10 #include <sstream>
11 #include <vector>
12 #include "GmshConfig.h"
13 #include "GModel.h"
14 #include "HighOrder.h"
15 #include "MLine.h"
16 #include "MTriangle.h"
17 #include "MQuadrangle.h"
18 #include "MTetrahedron.h"
19 #include "MHexahedron.h"
20 #include "MPrism.h"
21 #include "MPyramid.h"
22 #include "GmshMessage.h"
23 #include "OS.h"
24 #include "fullMatrix.h"
25 #include "BasisFactory.h"
26 #include "nodalBasis.h"
27 #include "InnerVertexPlacement.h"
28 #include "Context.h"
29 #include "MFace.h"
30 #include "ExtrudeParams.h"
31 
32 // for each pair of vertices (an edge), we build a list of vertices that are the
33 // high order representation of the edge. The ordering of vertices in the list
34 // is supposed to be (by construction) consistent with the ordering of the pair.
35 // FIXME: replace this by std::map<MEdge, std::vector<MVertex *>,
36 // MEdgeLessThan>!
37 typedef std::map<std::pair<MVertex *, MVertex *>, std::vector<MVertex *> >
39 
40 // for each face (a list of vertices) we build a list of vertices that are the
41 // high order representation of the face
42 typedef std::map<MFace, std::vector<MVertex *>, MFaceLessThan> faceContainer;
43 
44 // Functions that help optimizing placement of points on geometry
45 
46 // The aim here is to build a polynomial representation that consist
47 // in polynomial segments of equal length
48 
49 static double mylength(GEdge *ge, int i, double *u)
50 {
51  return ge->length(u[i], u[i + 1], 10);
52 }
53 
54 static void myresid(int N, GEdge *ge, double *u, fullVector<double> &r,
55  double *weight = nullptr)
56 {
57  double L[100];
58  for(int i = 0; i < N - 1; i++) L[i] = mylength(ge, i, u);
59  if(weight)
60  for(int i = 0; i < N - 2; i++)
61  r(i) = L[i + 1] / weight[i + 1] - L[i] / weight[i];
62  else
63  for(int i = 0; i < N - 2; i++) r(i) = L[i + 1] - L[i];
64 }
65 
66 static bool computeEquidistantParameters(GEdge *ge, double u0, double uN, int N,
67  double *u, double underRelax)
68 {
69  const double PRECISION = 1.e-6;
70  const int MAX_ITER = 50;
71  const double eps = (uN - u0) * 1.e-5;
72 
73  // newton algorithm
74  // N is the total number of points (3 for quadratic, 4 for cubic ...)
75  // u[0] = u0;
76  // u[N-1] = uN;
77  // initialize as equidistant in parameter space
78  u[0] = u0;
79  double du = (uN - u0) / (N - 1);
80  for(int i = 1; i < N; i++) { u[i] = u[i - 1] + du; }
81 
82  // return true;
83 
84  // create the tangent matrix
85  const int M = N - 2;
86  fullMatrix<double> J(M, M);
87  fullVector<double> DU(M);
88  fullVector<double> R(M);
89  fullVector<double> Rp(M);
90 
91  int iter = 1;
92 
93  while(iter < MAX_ITER) {
94  iter++;
95  myresid(N, ge, u, R);
96 
97  for(int i = 0; i < M; i++) {
98  u[i + 1] += eps;
99  myresid(N, ge, u, Rp);
100  for(int j = 0; j < M; j++) { J(i, j) = (Rp(j) - R(j)) / eps; }
101  u[i + 1] -= eps;
102  }
103 
104  if(M == 1)
105  DU(0) = R(0) / J(0, 0);
106  else
107  J.luSolve(R, DU);
108 
109  for(int i = 0; i < M; i++) { u[i + 1] -= underRelax * DU(i); }
110 
111  if(u[1] < u0) break;
112  if(u[N - 2] > uN) break;
113 
114  double newt_norm = DU.norm();
115  if(newt_norm < PRECISION) { return true; }
116  }
117  return false;
118 }
119 
120 static bool computeGLLParametersP6(GEdge *ge, double u0, double uN, int N,
121  double *u, double underRelax)
122 {
123  static const double GLLQL[7] = {
124  -1.000000000000000, -0.830223896278567, -0.468848793470714, 0,
125  0.468848793470714, 0.830223896278567, 1.000000000000000};
126  double weight[6];
127  for(int i = 0; i < 6; ++i) { weight[i] = GLLQL[i + 1] - GLLQL[i]; }
128 
129  const double PRECISION = 1.e-6;
130  const int MAX_ITER = 50;
131  const double eps = (uN - u0) * 1.e-5;
132 
133  // newton algorithm
134  // N is the total number of points (3 for quadratic, 4 for cubic ...)
135  // u[0] = u0;
136  // u[N-1] = uN;
137  // initialize as equidistant in parameter space
138  u[0] = u0;
139  u[N - 1] = uN;
140  double uMiddle = .5 * (u0 + uN);
141  double du = .5 * (uN - u0);
142  for(int i = 1; i < N - 1; i++) { u[i] = uMiddle + GLLQL[i] * du; }
143 
144  // create the tangent matrix
145  const int M = N - 2;
146  fullMatrix<double> J(M, M);
147  fullVector<double> DU(M);
148  fullVector<double> R(M);
149  fullVector<double> Rp(M);
150 
151  int iter = 1;
152 
153  while(iter < MAX_ITER) {
154  iter++;
155  myresid(N, ge, u, R, weight);
156 
157  for(int i = 0; i < M; i++) {
158  u[i + 1] += eps;
159  myresid(N, ge, u, Rp, weight);
160  for(int j = 0; j < M; j++) { J(i, j) = (Rp(j) - R(j)) / eps; }
161  u[i + 1] -= eps;
162  }
163 
164  if(M == 1)
165  DU(0) = R(0) / J(0, 0);
166  else
167  J.luSolve(R, DU);
168 
169  for(int i = 0; i < M; i++) { u[i + 1] -= underRelax * DU(i); }
170 
171  if(u[1] < u0) break;
172  if(u[N - 2] > uN) break;
173 
174  double newt_norm = DU.norm();
175  if(newt_norm < PRECISION) { return true; }
176  }
177  return false;
178 }
179 
180 static bool computeEquidistantParameters(GFace *gf, double u0, double uN,
181  double v0, double vN, SPoint3 &p0,
182  SPoint3 &pN, int N, bool geodesic,
183  double *u, double *v)
184 {
185  const int NI = N - 1;
186  u[0] = u0;
187  v[0] = v0;
188  u[NI] = uN;
189  v[NI] = vN;
190  const double fact = 1. / (double)NI;
191  for(int i = 1; i < NI; i++) {
192  const double t = i * fact;
193  u[i] = u0 + (uN - u0) * t;
194  v[i] = v0 + (vN - v0) * t;
195  // only use closestPoint for non-plane surfaces (for performance reasons -
196  // it's very slow in OpenCASCADE)
197  if(geodesic && gf->geomType() != GEntity::Plane) {
198  SPoint3 pc(t * pN + (1. - t) * p0);
199  double guess[2] = {u[i], v[i]};
200  GPoint gp = gf->closestPoint(pc, guess);
201  if(gp.succeeded()) {
202  u[i] = gp.u();
203  v[i] = gp.v();
204  }
205  }
206  }
207  return true;
208 }
209 
210 static fullMatrix<double> *lob2lagP6 = nullptr;
211 
213 {
214  const double lobPt[7] = {
215  -1.000000000000000, -0.830223896278567, -0.468848793470714, 0,
216  0.468848793470714, 0.830223896278567, 1.000000000000000};
217  const double lagPt[7] = {
218  -1.000000000000000, -0.666666666666666, -0.333333333333333, 0,
219  0.333333333333333, 0.666666666666666, 1.000000000000000};
220  const int ndofs = 7;
221 
222  const double monomial[7] = {0, 1, 2, 3, 4, 5, 6};
223 
224  fullMatrix<double> Vandermonde(ndofs, ndofs);
225  for(int i = 0; i < ndofs; i++) {
226  for(int j = 0; j < ndofs; j++) {
227  Vandermonde(i, j) = pow_int(lobPt[i], monomial[j]);
228  }
229  }
230 
231  fullMatrix<double> coefficient(ndofs, ndofs);
232  Vandermonde.invert(coefficient);
233 
234  lob2lagP6 = new fullMatrix<double>(ndofs, ndofs);
235 
236  for(int i = 0; i < ndofs; i++) {
237  for(int j = 0; j < ndofs; j++) {
238  Vandermonde(i, j) = pow_int(lagPt[i], monomial[j]);
239  }
240  }
241 
242  Vandermonde.mult(coefficient, (*lob2lagP6));
243 }
244 
245 // Creation of high-order edge vertices
246 
247 static bool getEdgeVerticesOnGeo(GEdge *ge, MVertex *v0, MVertex *v1,
248  std::vector<MVertex *> &ve, int nPts = 1)
249 {
250  static bool GLLquad = false;
251  static const double relaxFail = 1e-2;
252  double u0 = 0., u1 = 0., US[100];
253  bool reparamOK = reparamMeshVertexOnEdge(v0, ge, u0);
254  if(ge->periodic(0) && ge->getEndVertex() &&
255  ge->getEndVertex()->getNumMeshVertices() > 0 &&
256  v1 == ge->getEndVertex()->mesh_vertices[0])
257  u1 = ge->parBounds(0).high();
258  else
259  reparamOK &= reparamMeshVertexOnEdge(v1, ge, u1);
260 
261  if(reparamOK) {
262  double uMin = std::min(u0, u1), uMax = std::max(u0, u1);
263  bool failed = true;
264  double relax = 1.;
265  while(failed && (relax > relaxFail)) {
266  if(GLLquad)
267  failed = !computeGLLParametersP6(ge, uMin, uMax, nPts + 2, US, relax);
268  else
269  failed =
270  !computeEquidistantParameters(ge, uMin, uMax, nPts + 2, US, relax);
271  relax *= 0.5;
272  }
273  if(failed) {
274  Msg::Warning(
275  "Failed to compute equidistant parameters (relax = %g, value = %g) "
276  "for edge %d-%d parametrized with %g %g on curve %d",
277  relax, US[1], v0->getNum(), v1->getNum(), u0, u1, ge->tag());
278  US[0] = uMin;
279  const double du = (uMax - uMin) / (nPts + 1);
280  for(int i = 1; i <= nPts; i++) US[i] = US[i - 1] + du;
281  }
282  }
283  else
284  Msg::Error("Cannot reparametrize a mesh node in high order meshing");
285 
286  if(!reparamOK) return false;
287 
288  if(GLLquad) {
289  fullMatrix<double> M(7, 3);
290  M(0, 0) = u0 < u1 ? v0->x() : v1->x();
291  M(0, 1) = u0 < u1 ? v0->y() : v1->y();
292  M(0, 2) = u0 < u1 ? v0->z() : v1->z();
293  M(6, 0) = u0 < u1 ? v1->x() : v0->x();
294  M(6, 1) = u0 < u1 ? v1->y() : v0->y();
295  M(6, 2) = u0 < u1 ? v1->z() : v0->z();
296  for(int j = 0; j < nPts; j++) {
297  int count = u0 < u1 ? j + 1 : nPts + 1 - (j + 1);
298  GPoint pc = ge->point(US[count]);
299  M(j + 1, 0) = pc.x();
300  M(j + 1, 1) = pc.y();
301  M(j + 1, 2) = pc.z();
302  }
303  fullMatrix<double> Mlag(7, 3);
305  lob2lagP6->mult(M, Mlag);
306 
307  for(int j = 0; j < nPts; j++) {
308  MVertex *v;
309  int count = u0 < u1 ? j + 1 : nPts + 1 - (j + 1);
310  // FIXME US[count] false!!!
311  v = new MEdgeVertex(Mlag(count, 0), Mlag(count, 1), Mlag(count, 2), ge,
312  US[count]);
313  // this destroys the ordering of the mesh vertices on the edge
314  ve.push_back(v);
315  }
316  }
317  else {
318  for(int j = 0; j < nPts; j++) {
319  MVertex *v;
320  int count = u0 < u1 ? j + 1 : nPts + 1 - (j + 1);
321  GPoint pc = ge->point(US[count]);
322  v = new MEdgeVertex(pc.x(), pc.y(), pc.z(), ge, US[count]);
323  // this destroys the ordering of the mesh vertices on the edge
324  ve.push_back(v);
325  }
326  }
327 
328  // GLLquad = false;
329  return true;
330 }
331 
332 static bool getEdgeVerticesOnGeo(GFace *gf, MVertex *v0, MVertex *v1,
333  std::vector<MVertex *> &ve, int nPts = 1)
334 {
335  SPoint2 p0, p1;
336  double US[100], VS[100];
337  bool reparamOK = reparamMeshEdgeOnFace(v0, v1, gf, p0, p1);
338  if(reparamOK) {
339  SPoint3 pnt0, pnt1;
340  if(nPts >= 30)
341  computeEquidistantParameters(gf, p0[0], p1[0], p0[1], p1[1], pnt0, pnt1,
342  nPts + 2, false, US, VS);
343  else {
344  pnt0 = v0->point();
345  pnt1 = v1->point();
346  // warning: using the geodesic is sometimes a bad idea when the edge is
347  // "far away" from the surface (e.g. on the diameter of a circle!);
348  // however removing this can cause failures on surfaces with singular
349  // parametrizations like spheroids (see #1271)
350  computeEquidistantParameters(gf, p0[0], p1[0], p0[1], p1[1], pnt0, pnt1,
351  nPts + 2, true, US, VS);
352  }
353  }
354  else {
355  Msg::Error("Cannot reparametrize mesh edge %lu-%lu on surface %d",
356  v0->getNum(), v1->getNum(), gf->tag());
357  return false;
358  }
359 
360  for(int j = 0; j < nPts; j++) {
361  GPoint pc = gf->point(US[j + 1], VS[j + 1]);
362  MVertex *v =
363  new MFaceVertex(pc.x(), pc.y(), pc.z(), gf, US[j + 1], VS[j + 1]);
364  ve.push_back(v);
365  }
366 
367  return true;
368 }
369 
370 static void interpVerticesInExistingEdge(GEntity *ge, const MElement *edgeEl,
371  std::vector<MVertex *> &veEdge,
372  int nPts)
373 {
374  fullMatrix<double> points;
375  points = edgeEl->getFunctionSpace(nPts + 1)->points;
376  for(int k = 2; k < nPts + 2; k++) {
377  SPoint3 pos;
378  edgeEl->pnt(points(k, 0), 0., 0., pos);
379  MVertex *v = new MVertex(pos.x(), pos.y(), pos.z(), ge);
380  veEdge.push_back(v);
381  }
382 }
383 
384 inline static bool getMinMaxVert(MVertex *v0, MVertex *v1, MVertex *&vMin,
385  MVertex *&vMax)
386 {
387  const bool increasing = (v0->getNum() < v1->getNum());
388  if(increasing) {
389  vMin = v0;
390  vMax = v1;
391  }
392  else {
393  vMin = v1;
394  vMax = v0;
395  }
396  return increasing;
397 }
398 
399 // Get new interior vertices for a 1D element
400 static void getEdgeVertices(GEdge *ge, MElement *ele,
401  std::vector<MVertex *> &ve,
402  edgeContainer &edgeVertices, bool linear,
403  int nPts = 1)
404 {
405  if(!ge->haveParametrization()) linear = true;
406 
407  std::vector<MVertex *> veOld;
408  ele->getVertices(veOld);
409  MVertex *vMin, *vMax;
410  const bool increasing = getMinMaxVert(veOld[0], veOld[1], vMin, vMax);
411  std::pair<MVertex *, MVertex *> p(vMin, vMax);
412 
413  std::vector<MVertex *> veEdge;
414  // Get vertices on geometry if asked
415  bool gotVertOnGeo =
416  linear ? false : getEdgeVerticesOnGeo(ge, veOld[0], veOld[1], veEdge, nPts);
417  // If not on geometry, create from mesh interpolation
418  if(!gotVertOnGeo) interpVerticesInExistingEdge(ge, ele, veEdge, nPts);
419  if(edgeVertices.count(p) == 0) {
420  if(increasing) // Add newly created vertices to list
421  edgeVertices[p].insert(edgeVertices[p].end(), veEdge.begin(),
422  veEdge.end());
423  else
424  edgeVertices[p].insert(edgeVertices[p].end(), veEdge.rbegin(),
425  veEdge.rend());
426  }
427  else if(p.first != p.second) {
428  // Vertices already exist and edge is not a degenerated edge
429  Msg::Error(
430  "Mesh edges from different curves share nodes: create a finer mesh "
431  "(curve involved: %d)",
432  ge->tag());
433  }
434  ve.insert(ve.end(), veEdge.begin(), veEdge.end());
435 }
436 
437 // Get new interior vertices for an edge in a 2D element
438 static void getEdgeVertices(GFace *gf, MElement *ele,
439  std::vector<MVertex *> &ve,
440  edgeContainer &edgeVertices, bool linear,
441  int nPts = 1)
442 {
443  if(!gf->haveParametrization()) linear = true;
444 
445  for(int i = 0; i < ele->getNumEdges(); i++) {
446  std::vector<MVertex *> veOld;
447  ele->getEdgeVertices(i, veOld);
448  MVertex *vMin, *vMax;
449  const bool increasing = getMinMaxVert(veOld[0], veOld[1], vMin, vMax);
450  std::pair<MVertex *, MVertex *> p(vMin, vMax);
451  std::vector<MVertex *> veEdge;
452 
453  auto eIter = edgeVertices.find(p);
454 
455  if(eIter != edgeVertices.end()) { // Vertices already exist
456  std::vector<MVertex *> &eVtcs = eIter->second;
457  if(increasing)
458  veEdge.assign(eVtcs.begin(), eVtcs.end());
459  else
460  veEdge.assign(eVtcs.rbegin(), eVtcs.rend());
461  }
462  else { // Vertices do not exist, create them
463  // Get vertices on geometry if asked
464  bool gotVertOnGeo =
465  linear ? false :
466  getEdgeVerticesOnGeo(gf, veOld[0], veOld[1], veEdge, nPts);
467  if(!gotVertOnGeo) {
468  // If not on geometry, create from mesh interpolation
469  const MLineN edgeEl(veOld, ele->getPolynomialOrder());
470  interpVerticesInExistingEdge(gf, &edgeEl, veEdge, nPts);
471  }
472 
473  std::vector<MVertex *> &eVtcs = edgeVertices[p];
474 
475  if(increasing) // Add newly created vertices to list
476  eVtcs.insert(eVtcs.end(), veEdge.begin(), veEdge.end());
477  else
478  eVtcs.insert(eVtcs.end(), veEdge.rbegin(), veEdge.rend());
479  }
480  ve.insert(ve.end(), veEdge.begin(), veEdge.end());
481  }
482 }
483 
484 // Get new interior vertices for an edge in a 3D element
485 static void getEdgeVertices(GRegion *gr, MElement *ele,
486  std::vector<MVertex *> &ve,
487  edgeContainer &edgeVertices, int nPts = 1)
488 {
489  for(int i = 0; i < ele->getNumEdges(); i++) {
490  std::vector<MVertex *> veOld;
491  ele->getEdgeVertices(i, veOld);
492  MVertex *vMin, *vMax;
493  const bool increasing = getMinMaxVert(veOld[0], veOld[1], vMin, vMax);
494  std::pair<MVertex *, MVertex *> p(vMin, vMax);
495  std::vector<MVertex *> veEdge;
496  if(edgeVertices.count(p)) { // Vertices already exist
497  if(increasing)
498  veEdge.assign(edgeVertices[p].begin(), edgeVertices[p].end());
499  else
500  veEdge.assign(edgeVertices[p].rbegin(), edgeVertices[p].rend());
501  }
502  else { // Vertices do not exist, create them
503  const MLineN edgeEl(veOld, ele->getPolynomialOrder());
504  interpVerticesInExistingEdge(gr, &edgeEl, veEdge, nPts);
505  if(increasing) // Add newly created vertices to list
506  edgeVertices[p].insert(edgeVertices[p].end(), veEdge.begin(),
507  veEdge.end());
508  else
509  edgeVertices[p].insert(edgeVertices[p].end(), veEdge.rbegin(),
510  veEdge.rend());
511  }
512  ve.insert(ve.end(), veEdge.begin(), veEdge.end());
513  }
514 }
515 
516 // Creation of high-order face vertices
517 
518 static void reorientTrianglePoints(std::vector<MVertex *> &vtcs,
519  int orientation, bool swap)
520 {
521  int nbPts = vtcs.size();
522  if(nbPts <= 1) return;
523  std::vector<MVertex *> tmp(nbPts);
524  int interiorOrder = (int)((sqrt(1. + 8. * nbPts) - 3) / 2);
525  int pos = 0;
526  for(int o = interiorOrder; o > 0; o -= 3) {
527  if(swap) {
528  tmp[pos] = vtcs[pos];
529  tmp[pos + 1] = vtcs[pos + 2];
530  tmp[pos + 2] = vtcs[pos + 1];
531  for(int i = 0; i < 3 * (o - 1); i++)
532  tmp[pos + 3 + i] = vtcs[pos + 3 * o - i - 1];
533  }
534  else {
535  for(int i = 0; i < 3 * o; i++) tmp[pos + i] = vtcs[pos + i];
536  }
537  for(int i = 0; i < 3; i++) {
538  int ri = (i + orientation) % 3;
539  vtcs[pos + ri] = tmp[pos + i];
540  for(int j = 0; j < o - 1; j++)
541  vtcs[pos + 3 + (o - 1) * ri + j] = tmp[pos + 3 + (o - 1) * i + j];
542  }
543  pos += 3 * o;
544  }
545 }
546 
547 static void reorientQuadPoints(std::vector<MVertex *> &vtcs, int orientation,
548  bool swap, int order)
549 {
550  int nbPts = vtcs.size();
551  if(nbPts <= 1) return;
552  std::vector<MVertex *> tmp(nbPts);
553 
554  int start = 0;
555  while(1) {
556  // CORNERS
557  int index = 0;
558  if(order == 0) { start++; }
559  else {
560  int i1(0), i2(0), i3(0), i4(0);
561  if(!swap) {
562  if(orientation == 0) {
563  i1 = 0;
564  i2 = 1;
565  i3 = 2;
566  i4 = 3;
567  }
568  else if(orientation == 1) {
569  i1 = 3;
570  i2 = 0;
571  i3 = 1;
572  i4 = 2;
573  }
574  else if(orientation == 2) {
575  i1 = 2;
576  i2 = 3;
577  i3 = 0;
578  i4 = 1;
579  }
580  else if(orientation == 3) {
581  i1 = 1;
582  i2 = 2;
583  i3 = 3;
584  i4 = 0;
585  }
586  }
587  else {
588  if(orientation == 0) {
589  i1 = 0;
590  i2 = 3;
591  i3 = 2;
592  i4 = 1;
593  }
594  else if(orientation == 3) {
595  i1 = 3;
596  i2 = 2;
597  i3 = 1;
598  i4 = 0;
599  }
600  else if(orientation == 2) {
601  i1 = 2;
602  i2 = 1;
603  i3 = 0;
604  i4 = 3;
605  }
606  else if(orientation == 1) {
607  i1 = 1;
608  i2 = 0;
609  i3 = 3;
610  i4 = 2;
611  }
612  }
613 
614  int indices[4] = {i1, i2, i3, i4};
615  for(int i = 0; i < 4; i++) tmp[i] = vtcs[start + indices[i]];
616  for(int i = 0; i < 4; i++) vtcs[start + i] = tmp[i];
617 
618  // EDGES
619  start += 4;
620  for(int iEdge = 0; iEdge < 4; iEdge++) {
621  int p1 = indices[iEdge];
622  int p2 = indices[(iEdge + 1) % 4];
623  int nbP = order - 1;
624  if(p1 == 0 && p2 == 1) {
625  for(int i = start + 0 * nbP; i < start + 1 * nbP; i++)
626  tmp[index++] = vtcs[i];
627  }
628  else if(p1 == 1 && p2 == 2) {
629  for(int i = start + 1 * nbP; i < start + 2 * nbP; i++)
630  tmp[index++] = vtcs[i];
631  }
632  else if(p1 == 2 && p2 == 3) {
633  for(int i = start + 2 * nbP; i < start + 3 * nbP; i++)
634  tmp[index++] = vtcs[i];
635  }
636  else if(p1 == 3 && p2 == 0) {
637  for(int i = start + 3 * nbP; i < start + 4 * nbP; i++)
638  tmp[index++] = vtcs[i];
639  }
640  else if(p1 == 1 && p2 == 0) {
641  for(int i = start + 1 * nbP - 1; i >= start + 0 * nbP; i--)
642  tmp[index++] = vtcs[i];
643  }
644  else if(p1 == 2 && p2 == 1) {
645  for(int i = start + 2 * nbP - 1; i >= start + 1 * nbP; i--)
646  tmp[index++] = vtcs[i];
647  }
648  else if(p1 == 3 && p2 == 2) {
649  for(int i = start + 3 * nbP - 1; i >= start + 2 * nbP; i--)
650  tmp[index++] = vtcs[i];
651  }
652  else if(p1 == 0 && p2 == 3) {
653  for(int i = start + 4 * nbP - 1; i >= start + 3 * nbP; i--)
654  tmp[index++] = vtcs[i];
655  }
656  else
657  Msg::Error("Something wrong in reorientQuadPoints");
658  }
659  for(int i = 0; i < index; i++) vtcs[start + i] = tmp[i];
660  start += index;
661  }
662 
663  order -= 2;
664  if(start >= (int)vtcs.size()) break;
665  }
666 }
667 
669  const fullMatrix<double> &coefficients,
670  const std::vector<MVertex *> &vertices,
671  std::vector<MVertex *> &vFace)
672 {
673  for(int k = 0; k < coefficients.size1(); k++) {
674  double x(0), y(0), z(0);
675  for(int j = 0; j < coefficients.size2(); j++) {
676  MVertex *v = vertices[j];
677  x += coefficients(k, j) * v->x();
678  y += coefficients(k, j) * v->y();
679  z += coefficients(k, j) * v->z();
680  }
681  vFace.push_back(new MVertex(x, y, z, ge));
682  }
683 }
684 
686  const fullMatrix<double> &coefficients,
687  const std::vector<MVertex *> &vertices,
688  std::vector<MVertex *> &vf)
689 {
690  // special case for 9 node quads...
691  if(coefficients.size1() != 1 || vertices.size() != 8) return false;
692 
693  // ...on surfaces with recombined extruded meshes, generated by translation...
695  if(!ep || !ep->mesh.ExtrudeMesh || !ep->mesh.Recombine ||
696  ep->geo.Mode != EXTRUDED_ENTITY || ep->geo.Type != TRANSLATE)
697  return false;
698 
699  // ...then this is exact
700  interpVerticesInExistingFace(gf, coefficients, vertices, vf);
701  return true;
702 }
703 
704 static void getFaceVerticesOnGeo(GFace *gf,
705  const fullMatrix<double> &coefficients,
706  const std::vector<MVertex *> &vertices,
707  std::vector<MVertex *> &vf)
708 {
709  SPoint2 pts[1000];
710  bool reparamOK = true;
711  for(std::size_t k = 0; k < vertices.size(); ++k)
712  reparamOK &= reparamMeshVertexOnFace(vertices[k], gf, pts[k]);
713  for(int k = 0; k < coefficients.size1(); k++) {
714  double X(0), Y(0), Z(0), GUESS[2] = {0, 0};
715  for(int j = 0; j < coefficients.size2(); j++) {
716  MVertex *vt = vertices[j];
717  X += coefficients(k, j) * vt->x();
718  Y += coefficients(k, j) * vt->y();
719  Z += coefficients(k, j) * vt->z();
720  if(reparamOK) {
721  GUESS[0] += coefficients(k, j) * pts[j][0];
722  GUESS[1] += coefficients(k, j) * pts[j][1];
723  }
724  }
725  MVertex *v;
726  if(reparamOK) {
727  // closestPoint is absolutely necessary when the parameterization is
728  // degenerate
729  GPoint gp;
730  if(gf->geomType() == GEntity::Plane) {
731  gp = gf->point(SPoint2(GUESS[0], GUESS[1]));
732  }
733  else {
734  gp = gf->closestPoint(SPoint3(X, Y, Z), GUESS);
735  }
736  if(gp.g()) {
737  v = new MFaceVertex(gp.x(), gp.y(), gp.z(), gf, gp.u(), gp.v());
738  }
739  else {
740  v = new MVertex(X, Y, Z, gf);
741  }
742  }
743  else {
744  GPoint gp = gf->closestPoint(SPoint3(X, Y, Z), GUESS);
745  if(gp.succeeded())
746  v = new MVertex(gp.x(), gp.y(), gp.z(), gf);
747  else
748  v = new MVertex(X, Y, Z, gf);
749  }
750  vf.push_back(v);
751  }
752 }
753 
754 // Get new interior vertices for a 2D element
755 static void getFaceVertices(GFace *gf, MElement *ele,
756  std::vector<MVertex *> &newVertices,
757  faceContainer &faceVertices, bool linear,
758  int nPts = 1)
759 {
760  if(!gf->haveParametrization()) linear = true;
761 
762  std::vector<MVertex *> boundaryVertices;
763  {
764  std::size_t nCorner = ele->getNumPrimaryVertices();
765  boundaryVertices.reserve(nCorner + newVertices.size());
766  ele->getVertices(boundaryVertices);
767  boundaryVertices.resize(nCorner);
768  boundaryVertices.insert(boundaryVertices.end(), newVertices.begin(),
769  newVertices.end());
770  }
771  int type = ele->getType();
772  fullMatrix<double> *coefficients = getInnerVertexPlacement(type, nPts + 1);
773  std::vector<MVertex *> vFace;
774  if(!linear) { // Get vertices on geometry if asked...
775  // special case for 2nd order quads on surfaces generated by extrusion
776  // (translation): this allows to speed up a common case (extruded OCC
777  // models) by orders of magnitudes, where OCC closestPoint() is atrociously
778  // slow
779  if(!getFaceVerticesOnExtrudedGeo(gf, *coefficients, boundaryVertices,
780  vFace))
781  getFaceVerticesOnGeo(gf, *coefficients, boundaryVertices, vFace);
782  }
783  else { // ... otherwise, create from mesh interpolation
784  interpVerticesInExistingFace(gf, *coefficients, boundaryVertices, vFace);
785  }
786 
787  MFace face = ele->getFace(0);
788  faceVertices[face].insert(faceVertices[face].end(), vFace.begin(),
789  vFace.end());
790  newVertices.insert(newVertices.end(), vFace.begin(), vFace.end());
791 }
792 
793 static int retrieveFaceBoundaryVertices(int k, int type, int nPts,
794  const std::vector<MVertex *> &vCorner,
795  const std::vector<MVertex *> &vEdges,
796  std::vector<MVertex *> &v)
797 {
798  v.clear();
799  int nCorner;
800  switch(type) {
801  case TYPE_TET:
802  v.push_back(vCorner[MTetrahedron::faces_tetra(k, 0)]);
803  v.push_back(vCorner[MTetrahedron::faces_tetra(k, 1)]);
804  v.push_back(vCorner[MTetrahedron::faces_tetra(k, 2)]);
805  for(int i = 0; i < 3; ++i) {
806  int edge = MTetrahedron::faces2edge_tetra(k, i);
807  int n = std::abs(edge) - 1;
808  v.insert(v.end(), vEdges.begin() + n * nPts,
809  vEdges.begin() + (n + 1) * nPts);
810  if(edge < 0) std::reverse(v.end() - nPts, v.end());
811  }
812  return TYPE_TRI;
813  case TYPE_HEX:
814  v.push_back(vCorner[MHexahedron::faces_hexa(k, 0)]);
815  v.push_back(vCorner[MHexahedron::faces_hexa(k, 1)]);
816  v.push_back(vCorner[MHexahedron::faces_hexa(k, 2)]);
817  v.push_back(vCorner[MHexahedron::faces_hexa(k, 3)]);
818  for(int i = 0; i < 4; ++i) {
819  int edge = MHexahedron::faces2edge_hexa(k, i);
820  int n = std::abs(edge) - 1;
821  v.insert(v.end(), vEdges.begin() + n * nPts,
822  vEdges.begin() + (n + 1) * nPts);
823  if(edge < 0) std::reverse(v.end() - nPts, v.end());
824  }
825  return TYPE_QUA;
826  case TYPE_PRI:
827  nCorner = k < 2 ? 3 : 4;
828  v.push_back(vCorner[MPrism::faces_prism(k, 0)]);
829  v.push_back(vCorner[MPrism::faces_prism(k, 1)]);
830  v.push_back(vCorner[MPrism::faces_prism(k, 2)]);
831  if(nCorner == 4) v.push_back(vCorner[MPrism::faces_prism(k, 3)]);
832  for(int i = 0; i < nCorner; ++i) {
833  int edge = MPrism::faces2edge_prism(k, i);
834  int n = std::abs(edge) - 1;
835  v.insert(v.end(), vEdges.begin() + n * nPts,
836  vEdges.begin() + (n + 1) * nPts);
837  if(edge < 0) std::reverse(v.end() - nPts, v.end());
838  }
839  return nCorner == 3 ? TYPE_TRI : TYPE_QUA;
840  case TYPE_PYR:
841  nCorner = k < 4 ? 3 : 4;
842  v.push_back(vCorner[MPyramid::faces_pyramid(k, 0)]);
843  v.push_back(vCorner[MPyramid::faces_pyramid(k, 1)]);
844  v.push_back(vCorner[MPyramid::faces_pyramid(k, 2)]);
845  if(nCorner == 4) v.push_back(vCorner[MPyramid::faces_pyramid(k, 3)]);
846  for(int i = 0; i < nCorner; ++i) {
847  int edge = MPyramid::faces2edge_pyramid(k, i);
848  int n = std::abs(edge) - 1;
849  v.insert(v.end(), vEdges.begin() + n * nPts,
850  vEdges.begin() + (n + 1) * nPts);
851  if(edge < 0) std::reverse(v.end() - nPts, v.end());
852  }
853  return nCorner == 3 ? TYPE_TRI : TYPE_QUA;
854  default: return -1;
855  }
856 }
857 
858 // Get new face (excluding edge) vertices for a face of a 3D element
859 static void getFaceVertices(GRegion *gr, MElement *ele,
860  std::vector<MVertex *> &newVertices,
861  faceContainer &faceVertices, int nPts = 1)
862 {
863  std::vector<MVertex *> vCorner;
864  ele->getVertices(vCorner);
865  // NB: We can get more than corner vertices but we use only corners
866 
867  for(int i = 0; i < ele->getNumFaces(); i++) {
868  MFace face = ele->getFace(i);
869  std::vector<MVertex *> vFace;
870  auto fIter = faceVertices.find(face);
871  if(fIter != faceVertices.end()) { // Vertices already exist
872  std::vector<MVertex *> vtcs = fIter->second;
873  int orientation;
874  bool swap;
875  if(fIter->first.computeCorrespondence(face, orientation, swap)) {
876  // Check correspondence and apply permutation if needed
877  if(face.getNumVertices() == 3 && nPts > 1)
878  reorientTrianglePoints(vtcs, orientation, swap);
879  else if(face.getNumVertices() == 4)
880  reorientQuadPoints(vtcs, orientation, swap, nPts - 1);
881  }
882  else
883  Msg::Error(
884  "Error in face lookup for retrieval of high order face nodes");
885  vFace.assign(vtcs.begin(), vtcs.end());
886  }
887  else { // Vertices do not exist, create them by interpolation
888  std::vector<MVertex *> faceBoundaryVertices;
889  int type = retrieveFaceBoundaryVertices(
890  i, ele->getType(), nPts, vCorner, newVertices, faceBoundaryVertices);
891  fullMatrix<double> *coefficients =
892  getInnerVertexPlacement(type, nPts + 1);
893  interpVerticesInExistingFace(gr, *coefficients, faceBoundaryVertices,
894  vFace);
895  faceVertices[face].insert(faceVertices[face].end(), vFace.begin(),
896  vFace.end());
897  }
898  newVertices.insert(newVertices.end(), vFace.begin(), vFace.end());
899  }
900 }
901 
902 // Get new interior vertices for a 3D element
903 static void getVolumeVertices(GRegion *gr, MElement *ele,
904  std::vector<MVertex *> &newVertices, int nPts = 1)
905 {
906  std::vector<MVertex *> boundaryVertices;
907  {
908  std::size_t nCorner = ele->getNumPrimaryVertices();
909  boundaryVertices.reserve(nCorner + newVertices.size());
910  ele->getVertices(boundaryVertices);
911  boundaryVertices.resize(nCorner);
912  boundaryVertices.insert(boundaryVertices.end(), newVertices.begin(),
913  newVertices.end());
914  }
915  int type = ele->getType();
916  fullMatrix<double> &coefficients = *getInnerVertexPlacement(type, nPts + 1);
917 
918  for(int k = 0; k < coefficients.size1(); k++) {
919  double x(0), y(0), z(0);
920  for(int j = 0; j < coefficients.size2(); j++) {
921  MVertex *v = boundaryVertices[j];
922  x += coefficients(k, j) * v->x();
923  y += coefficients(k, j) * v->y();
924  z += coefficients(k, j) * v->z();
925  }
926  MVertex *v = new MVertex(x, y, z, gr);
927  newVertices.push_back(v);
928  }
929 }
930 
931 // Creation of high-order elements
932 
933 static void setHighOrder(GEdge *ge, edgeContainer &edgeVertices, bool linear,
934  int nbPts = 1)
935 {
936  std::vector<MLine *> lines2;
937  for(std::size_t i = 0; i < ge->lines.size(); i++) {
938  MLine *l = ge->lines[i];
939  std::vector<MVertex *> ve;
940  getEdgeVertices(ge, l, ve, edgeVertices, linear, nbPts);
941  if(nbPts == 1)
942  lines2.push_back(
943  new MLine3(l->getVertex(0), l->getVertex(1), ve[0], l->getPartition()));
944  else
945  lines2.push_back(
946  new MLineN(l->getVertex(0), l->getVertex(1), ve, l->getPartition()));
947  delete l;
948  }
949  ge->lines = lines2;
950  ge->deleteVertexArrays();
951 }
952 
954  edgeContainer &edgeVertices,
955  faceContainer &faceVertices, bool linear,
956  bool incomplete, int nPts)
957 {
958  std::vector<MVertex *> v;
959  getEdgeVertices(gf, t, v, edgeVertices, linear, nPts);
960  if(nPts == 1) {
961  return new MTriangle6(t->getVertex(0), t->getVertex(1), t->getVertex(2),
962  v[0], v[1], v[2], 0, t->getPartition());
963  }
964  else {
965  if(!incomplete) getFaceVertices(gf, t, v, faceVertices, linear, nPts);
966  return new MTriangleN(t->getVertex(0), t->getVertex(1), t->getVertex(2), v,
967  nPts + 1, 0, t->getPartition());
968  }
969 }
970 
972  edgeContainer &edgeVertices,
973  faceContainer &faceVertices, bool linear,
974  bool incomplete, int nPts)
975 {
976  std::vector<MVertex *> v;
977  getEdgeVertices(gf, q, v, edgeVertices, linear, nPts);
978  if(incomplete) {
979  if(nPts == 1) {
980  return new MQuadrangle8(q->getVertex(0), q->getVertex(1), q->getVertex(2),
981  q->getVertex(3), v[0], v[1], v[2], v[3], 0,
982  q->getPartition());
983  }
984  else {
985  return new MQuadrangleN(q->getVertex(0), q->getVertex(1), q->getVertex(2),
986  q->getVertex(3), v, nPts + 1, 0,
987  q->getPartition());
988  }
989  }
990  else {
991  getFaceVertices(gf, q, v, faceVertices, linear, nPts);
992  if(nPts == 1) {
993  return new MQuadrangle9(q->getVertex(0), q->getVertex(1), q->getVertex(2),
994  q->getVertex(3), v[0], v[1], v[2], v[3], v[4], 0,
995  q->getPartition());
996  }
997  else {
998  return new MQuadrangleN(q->getVertex(0), q->getVertex(1), q->getVertex(2),
999  q->getVertex(3), v, nPts + 1, 0,
1000  q->getPartition());
1001  }
1002  }
1003 }
1004 
1005 static void setHighOrder(GFace *gf, edgeContainer &edgeVertices,
1006  faceContainer &faceVertices, bool linear,
1007  bool incomplete, int nPts = 1)
1008 {
1009  std::vector<MTriangle *> triangles2;
1010  for(std::size_t i = 0; i < gf->triangles.size(); i++) {
1011  MTriangle *t = gf->triangles[i];
1012  MTriangle *tNew =
1013  setHighOrder(t, gf, edgeVertices, faceVertices, linear, incomplete, nPts);
1014  triangles2.push_back(tNew);
1015  delete t;
1016  }
1017  gf->triangles = triangles2;
1018 
1019  std::vector<MQuadrangle *> quadrangles2;
1020  for(std::size_t i = 0; i < gf->quadrangles.size(); i++) {
1021  MQuadrangle *q = gf->quadrangles[i];
1022  MQuadrangle *qNew =
1023  setHighOrder(q, gf, edgeVertices, faceVertices, linear, incomplete, nPts);
1024  quadrangles2.push_back(qNew);
1025  delete q;
1026  }
1027  gf->quadrangles = quadrangles2;
1028  gf->deleteVertexArrays();
1029 }
1030 
1032  edgeContainer &edgeVertices,
1033  faceContainer &faceVertices, bool incomplete,
1034  int nPts)
1035 {
1036  std::vector<MVertex *> v;
1037  getEdgeVertices(gr, t, v, edgeVertices, nPts);
1038  if(nPts == 1) {
1039  return new MTetrahedron10(t->getVertex(0), t->getVertex(1), t->getVertex(2),
1040  t->getVertex(3), v[0], v[1], v[2], v[3], v[4],
1041  v[5], 0, t->getPartition());
1042  }
1043  else {
1044  if(!incomplete) {
1045  getFaceVertices(gr, t, v, faceVertices, nPts);
1046  getVolumeVertices(gr, t, v, nPts);
1047  }
1048  return new MTetrahedronN(t->getVertex(0), t->getVertex(1), t->getVertex(2),
1049  t->getVertex(3), v, nPts + 1, 0,
1050  t->getPartition());
1051  }
1052 }
1053 
1055  edgeContainer &edgeVertices,
1056  faceContainer &faceVertices, bool incomplete,
1057  int nPts)
1058 {
1059  std::vector<MVertex *> v;
1060  getEdgeVertices(gr, h, v, edgeVertices, nPts);
1061  if(incomplete) {
1062  if(nPts == 1) {
1063  return new MHexahedron20(
1064  h->getVertex(0), h->getVertex(1), h->getVertex(2), h->getVertex(3),
1065  h->getVertex(4), h->getVertex(5), h->getVertex(6), h->getVertex(7),
1066  v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10],
1067  v[11], 0, h->getPartition());
1068  }
1069  else {
1070  return new MHexahedronN(h->getVertex(0), h->getVertex(1), h->getVertex(2),
1071  h->getVertex(3), h->getVertex(4), h->getVertex(5),
1072  h->getVertex(6), h->getVertex(7), v, nPts + 1, 0,
1073  h->getPartition());
1074  }
1075  }
1076  else {
1077  getFaceVertices(gr, h, v, faceVertices, nPts);
1078  getVolumeVertices(gr, h, v, nPts);
1079  if(nPts == 1) {
1080  return new MHexahedron27(
1081  h->getVertex(0), h->getVertex(1), h->getVertex(2), h->getVertex(3),
1082  h->getVertex(4), h->getVertex(5), h->getVertex(6), h->getVertex(7),
1083  v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10],
1084  v[11], v[12], v[13], v[14], v[15], v[16], v[17], v[18], 0,
1085  h->getPartition());
1086  }
1087  else {
1088  return new MHexahedronN(h->getVertex(0), h->getVertex(1), h->getVertex(2),
1089  h->getVertex(3), h->getVertex(4), h->getVertex(5),
1090  h->getVertex(6), h->getVertex(7), v, nPts + 1, 0,
1091  h->getPartition());
1092  }
1093  }
1094 }
1095 
1096 static MPrism *setHighOrder(MPrism *p, GRegion *gr, edgeContainer &edgeVertices,
1097  faceContainer &faceVertices, bool incomplete,
1098  int nPts)
1099 {
1100  std::vector<MVertex *> v;
1101  getEdgeVertices(gr, p, v, edgeVertices, nPts);
1102  if(incomplete) {
1103  if(nPts == 1) {
1104  return new MPrism15(p->getVertex(0), p->getVertex(1), p->getVertex(2),
1105  p->getVertex(3), p->getVertex(4), p->getVertex(5),
1106  v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8],
1107  0, p->getPartition());
1108  }
1109  else {
1110  return new MPrismN(p->getVertex(0), p->getVertex(1), p->getVertex(2),
1111  p->getVertex(3), p->getVertex(4), p->getVertex(5), v,
1112  nPts + 1, 0, p->getPartition());
1113  }
1114  }
1115  else {
1116  getFaceVertices(gr, p, v, faceVertices, nPts);
1117  if(nPts == 1) {
1118  return new MPrism18(p->getVertex(0), p->getVertex(1), p->getVertex(2),
1119  p->getVertex(3), p->getVertex(4), p->getVertex(5),
1120  v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8],
1121  v[9], v[10], v[11], 0, p->getPartition());
1122  }
1123  else {
1124  getVolumeVertices(gr, p, v, nPts);
1125  return new MPrismN(p->getVertex(0), p->getVertex(1), p->getVertex(2),
1126  p->getVertex(3), p->getVertex(4), p->getVertex(5), v,
1127  nPts + 1, 0, p->getPartition());
1128  }
1129  }
1130 }
1131 
1133  edgeContainer &edgeVertices,
1134  faceContainer &faceVertices, bool incomplete,
1135  int nPts)
1136 {
1137  std::vector<MVertex *> v;
1138  getEdgeVertices(gr, p, v, edgeVertices, nPts);
1139  if(!incomplete) {
1140  getFaceVertices(gr, p, v, faceVertices, nPts);
1141  if(nPts > 1) { getVolumeVertices(gr, p, v, nPts); }
1142  }
1143  return new MPyramidN(p->getVertex(0), p->getVertex(1), p->getVertex(2),
1144  p->getVertex(3), p->getVertex(4), v, nPts + 1, 0,
1145  p->getPartition());
1146 }
1147 
1148 static void setHighOrder(GRegion *gr, edgeContainer &edgeVertices,
1149  faceContainer &faceVertices, bool incomplete,
1150  int nPts = 1)
1151 {
1152  std::vector<MTetrahedron *> tetrahedra2;
1153  for(std::size_t i = 0; i < gr->tetrahedra.size(); i++) {
1154  MTetrahedron *t = gr->tetrahedra[i];
1155  MTetrahedron *tNew =
1156  setHighOrder(t, gr, edgeVertices, faceVertices, incomplete, nPts);
1157  tetrahedra2.push_back(tNew);
1158  delete t;
1159  }
1160  gr->tetrahedra = tetrahedra2;
1161 
1162  std::vector<MHexahedron *> hexahedra2;
1163  for(std::size_t i = 0; i < gr->hexahedra.size(); i++) {
1164  MHexahedron *h = gr->hexahedra[i];
1165  MHexahedron *hNew =
1166  setHighOrder(h, gr, edgeVertices, faceVertices, incomplete, nPts);
1167  hexahedra2.push_back(hNew);
1168  delete h;
1169  }
1170  gr->hexahedra = hexahedra2;
1171 
1172  std::vector<MPrism *> prisms2;
1173  for(std::size_t i = 0; i < gr->prisms.size(); i++) {
1174  MPrism *p = gr->prisms[i];
1175  MPrism *pNew =
1176  setHighOrder(p, gr, edgeVertices, faceVertices, incomplete, nPts);
1177  prisms2.push_back(pNew);
1178  delete p;
1179  }
1180  gr->prisms = prisms2;
1181 
1182  std::vector<MPyramid *> pyramids2;
1183  for(std::size_t i = 0; i < gr->pyramids.size(); i++) {
1184  MPyramid *p = gr->pyramids[i];
1185  MPyramid *pNew =
1186  setHighOrder(p, gr, edgeVertices, faceVertices, incomplete, nPts);
1187  pyramids2.push_back(pNew);
1188  delete p;
1189  }
1190  gr->pyramids = pyramids2;
1191 
1192  gr->deleteVertexArrays();
1193 }
1194 
1195 // High-level functions
1196 
1197 template <class T>
1198 static void setFirstOrder(GEntity *e, std::vector<T *> &elements,
1199  bool onlyVisible, bool skipDiscrete)
1200 {
1201  if(onlyVisible && !e->getVisibility()) return;
1202  if(skipDiscrete && e->isFullyDiscrete()) return;
1203  std::vector<T *> elements1;
1204  for(std::size_t i = 0; i < elements.size(); i++) {
1205  T *ele = elements[i];
1206  std::size_t n = ele->getNumPrimaryVertices();
1207  std::vector<MVertex *> v1;
1208  v1.reserve(n);
1209  for(std::size_t j = 0; j < n; j++) v1.push_back(ele->getVertex(j));
1210  elements1.push_back(new T(v1, 0, ele->getPartition()));
1211  delete ele;
1212  }
1213  elements = elements1;
1214  e->deleteVertexArrays();
1215 }
1216 
1217 static void deleteHighOrderVertices(GEntity *e, bool onlyVisible,
1218  bool skipDiscrete)
1219 {
1220  if(onlyVisible && !e->getVisibility()) return;
1221  if(skipDiscrete && e->isFullyDiscrete()) return;
1222  std::vector<MVertex *> v1;
1223  for(std::size_t i = 0; i < e->mesh_vertices.size(); i++) {
1224  if(e->mesh_vertices[i]->getPolynomialOrder() > 1)
1225  delete e->mesh_vertices[i];
1226  else
1227  v1.push_back(e->mesh_vertices[i]);
1228  }
1229  e->mesh_vertices = v1;
1230  e->deleteVertexArrays();
1231 }
1232 
1233 void SetOrder1(GModel *m, bool onlyVisible, bool skipDiscrete)
1234 {
1235  m->destroyMeshCaches();
1236 
1237  // replace all elements with first order elements
1238  for(auto it = m->firstEdge(); it != m->lastEdge(); ++it) {
1239  setFirstOrder(*it, (*it)->lines, onlyVisible, skipDiscrete);
1240  }
1241  for(auto it = m->firstFace(); it != m->lastFace(); ++it) {
1242  setFirstOrder(*it, (*it)->triangles, onlyVisible, skipDiscrete);
1243  setFirstOrder(*it, (*it)->quadrangles, onlyVisible, skipDiscrete);
1244  }
1245  for(auto it = m->firstRegion(); it != m->lastRegion(); ++it) {
1246  setFirstOrder(*it, (*it)->tetrahedra, onlyVisible, skipDiscrete);
1247  setFirstOrder(*it, (*it)->hexahedra, onlyVisible, skipDiscrete);
1248  setFirstOrder(*it, (*it)->prisms, onlyVisible, skipDiscrete);
1249  setFirstOrder(*it, (*it)->pyramids, onlyVisible, skipDiscrete);
1250  }
1251 
1252  // remove all high order vertices
1253  for(auto it = m->firstEdge(); it != m->lastEdge(); ++it)
1254  deleteHighOrderVertices(*it, onlyVisible, skipDiscrete);
1255  for(auto it = m->firstFace(); it != m->lastFace(); ++it)
1256  deleteHighOrderVertices(*it, onlyVisible, skipDiscrete);
1257  for(auto it = m->firstRegion(); it != m->lastRegion(); ++it)
1258  deleteHighOrderVertices(*it, onlyVisible, skipDiscrete);
1259 }
1260 
1261 void checkHighOrderTriangles(const char *cc, GModel *m,
1262  std::vector<MElement *> &bad, double &minJGlob)
1263 {
1264  bad.clear();
1265  minJGlob = 1.0;
1266  double minGGlob = 1.0;
1267  double avg = 0.0;
1268  int count = 0, nbfair = 0;
1269  for(auto it = m->firstFace(); it != m->lastFace(); ++it) {
1270  for(std::size_t i = 0; i < (*it)->triangles.size(); i++) {
1271  MTriangle *t = (*it)->triangles[i];
1272  double disto_ = t->distoShapeMeasure();
1273  double gamma_ = t->gammaShapeMeasure();
1274  double disto = disto_;
1275  minJGlob = std::min(minJGlob, disto);
1276  minGGlob = std::min(minGGlob, gamma_);
1277  avg += disto;
1278  count++;
1279  if(disto < 0)
1280  bad.push_back(t);
1281  else if(disto < 0.2)
1282  nbfair++;
1283  }
1284  /*
1285  for(std::size_t i = 0; i < (*it)->quadrangles.size(); i++){
1286  MQuadrangle *t = (*it)->quadrangles[i];
1287  double disto_ = t->distoShapeMeasure();
1288  double gamma_ = t->gammaShapeMeasure();
1289  double disto = disto_;
1290  minJGlob = std::min(minJGlob, disto);
1291  minGGlob = std::min(minGGlob, gamma_);
1292  avg += disto; count++;
1293  if (disto < 0) bad.push_back(t);
1294  else if (disto < 0.2) nbfair++;
1295  }
1296  */
1297  }
1298  if(!count) return;
1299  if(minJGlob > 0)
1300  Msg::Info(
1301  "%s: worst distortion = %g (%d elements in ]0, 0.2]); worst gamma = %g",
1302  cc, minJGlob, nbfair, minGGlob);
1303  else
1304  Msg::Warning(
1305  "%s: worst distortion = %g (avg = %g, %d elements with jac. < 0); "
1306  "worst gamma = %g",
1307  cc, minJGlob, avg / (count ? count : 1), bad.size(), minGGlob);
1308 }
1309 
1310 void checkHighOrderTetrahedron(const char *cc, GModel *m,
1311  std::vector<MElement *> &bad, double &minJGlob)
1312 {
1313  bad.clear();
1314  minJGlob = 1.0;
1315  double avg = 0.0;
1316  int count = 0, nbfair = 0;
1317  for(auto it = m->firstRegion(); it != m->lastRegion(); ++it) {
1318  for(std::size_t i = 0; i < (*it)->tetrahedra.size(); i++) {
1319  MTetrahedron *t = (*it)->tetrahedra[i];
1320  double disto_ = t->distoShapeMeasure();
1321  minJGlob = std::min(minJGlob, disto_);
1322  avg += disto_;
1323  count++;
1324  if(disto_ < 0)
1325  bad.push_back(t);
1326  else if(disto_ < 0.2)
1327  nbfair++;
1328  }
1329  }
1330  if(!count) return;
1331 
1332  if(minJGlob > 0)
1333  Msg::Info("%s: worst distortion = %g (%d elements in ]0, 0.2])", cc,
1334  minJGlob, nbfair);
1335  else
1336  Msg::Warning(
1337  "%s: worst distortion = %g (avg = %g, %d elements with jac. < 0)", cc,
1338  minJGlob, avg / (count ? count : 1), bad.size());
1339 }
1340 
1341 static int getOrder(GEntity *ge)
1342 {
1343  for(std::size_t i = 0; i < ge->getNumMeshElements(); i++)
1344  return ge->getMeshElement(i)->getPolynomialOrder();
1345  return 0;
1346 }
1347 
1348 static void setHighOrderFromExistingMesh(GEdge *ge, edgeContainer &edgeVertices)
1349 {
1350  for(std::size_t i = 0; i < ge->getNumMeshElements(); i++) {
1351  MElement *e = ge->getMeshElement(i);
1352  std::vector<MVertex *> v;
1353  e->getVertices(v);
1354  MVertex *vMin, *vMax;
1355  getMinMaxVert(v[0], v[1], vMin, vMax);
1356  std::pair<MVertex *, MVertex *> p(vMin, vMax);
1357  if(edgeVertices.count(p) == 0) {
1358  for(std::size_t j = e->getNumPrimaryVertices(); j < e->getNumVertices();
1359  j++) {
1360  edgeVertices[p].push_back(v[j]);
1361  }
1362  }
1363  }
1364 }
1365 
1366 static void setHighOrderFromExistingMesh(GFace *gf, edgeContainer &edgeVertices,
1367  faceContainer &faceVertices)
1368 {
1369  for(std::size_t i = 0; i < gf->getNumMeshElements(); i++) {
1370  MElement *e = gf->getMeshElement(i);
1371  for(int j = 0; j < e->getNumEdges(); j++) {
1372  MEdge edg = e->getEdge(j);
1373  MVertex *vMin, *vMax;
1374  getMinMaxVert(edg.getVertex(0), edg.getVertex(1), vMin, vMax);
1375  std::pair<MVertex *, MVertex *> p(vMin, vMax);
1376  if(edgeVertices.count(p) == 0) {
1377  std::vector<MVertex *> edgv;
1378  e->getEdgeVertices(j, edgv);
1379  for(std::size_t k = 2; k < edgv.size(); k++) {
1380  edgeVertices[p].push_back(edgv[k]);
1381  }
1382  }
1383  }
1384  MFace f = e->getFace(0);
1385  std::vector<MVertex *> facev;
1386  if(faceVertices.count(f) == 0) {
1387  e->getFaceVertices(0, facev);
1388  for(std::size_t j = e->getNumPrimaryVertices() + e->getNumEdgeVertices();
1389  j < facev.size(); j++) {
1390  faceVertices[f].push_back(facev[j]);
1391  }
1392  }
1393  }
1394 }
1395 
1396 void SetOrderN(GModel *m, int order, bool linear, bool incomplete,
1397  bool onlyVisible)
1398 {
1399  if(CTX::instance()->abortOnError && Msg::GetErrorCount()) return;
1400 
1401  // replace all the elements in the mesh with second order elements
1402  // by creating unique vertices on the edges/faces of the mesh:
1403  //
1404  // - if linear is set to true, new vertices are created by linear
1405  // interpolation between existing ones. If not, new vertices are
1406  // created on the exact geometry, provided that the geometrical
1407  // edges/faces are discretized with 1D/2D elements. (I.e., if
1408  // there are only 3D elements in the mesh then any new vertices on
1409  // the boundary will always be created by linear interpolation,
1410  // whether linear is set or not.)
1411  //
1412  // - if incomplete is set to true, we only create new vertices on
1413  // edges (creating 8-node quads, 20-node hexas, etc., instead of
1414  // 9-node quads, 27-node hexas, etc.)
1415 
1416  // - if onlyVisible is true, then only the visible entities will be curved.
1417 
1418  int nPts = order - 1;
1419 
1420  char msg[256];
1421  sprintf(msg, "Meshing order %d (curvilinear %s)...", order,
1422  linear ? "off" : "on");
1423 
1424  Msg::StatusBar(true, msg);
1425 
1426  double t1 = Cpu(), w1 = TimeOfDay();
1427 
1428  m->destroyMeshCaches();
1429 
1430  // Keep track of vertex/entities created
1431  edgeContainer edgeVertices;
1432  faceContainer faceVertices;
1433 
1434  int counter = 0;
1435  int nTot = m->getNumEdges() + m->getNumFaces() + m->getNumRegions();
1437 
1438  // TODO: we can leak nodes of discrete entities with existing high-order
1439  // nodes, if we ask a mesh with a different order
1440 
1441  for(auto it = m->firstEdge(); it != m->lastEdge(); ++it) {
1442  Msg::Info("Meshing curve %d order %d", (*it)->tag(), order);
1443  Msg::ProgressMeter(++counter, false, msg);
1444  if(onlyVisible && !(*it)->getVisibility()) continue;
1445  if(getOrder(*it) != order)
1446  setHighOrder(*it, edgeVertices, linear, nPts);
1447  else
1448  setHighOrderFromExistingMesh(*it, edgeVertices);
1449  }
1450 
1451  for(auto it = m->firstFace(); it != m->lastFace(); ++it) {
1452  Msg::Info("Meshing surface %d order %d", (*it)->tag(), order);
1453  Msg::ProgressMeter(++counter, false, msg);
1454  if(onlyVisible && !(*it)->getVisibility()) continue;
1455  if(getOrder(*it) != order)
1456  setHighOrder(*it, edgeVertices, faceVertices, linear, incomplete, nPts);
1457  else
1458  setHighOrderFromExistingMesh(*it, edgeVertices, faceVertices);
1459  if((*it)->getColumns() != nullptr) (*it)->getColumns()->clearElementData();
1460  }
1461 
1462  for(auto it = m->firstRegion(); it != m->lastRegion(); ++it) {
1463  Msg::Info("Meshing volume %d order %d", (*it)->tag(), order);
1464  Msg::ProgressMeter(++counter, false, msg);
1465  if(onlyVisible && !(*it)->getVisibility()) continue;
1466  if(getOrder(*it) != order)
1467  setHighOrder(*it, edgeVertices, faceVertices, incomplete, nPts);
1468  if((*it)->getColumns() != nullptr) (*it)->getColumns()->clearElementData();
1469  }
1470 
1471  // store nodes in entities
1473 
1475  double t2 = Cpu(), w2 = TimeOfDay();
1476 
1477  if(!linear) {
1478  std::vector<MElement *> bad;
1479  double worst;
1480  checkHighOrderTriangles("Surface mesh", m, bad, worst);
1481  checkHighOrderTetrahedron("Volume mesh", m, bad, worst);
1482  }
1483 
1484  Msg::StatusBar(true, "Done meshing order %d (Wall %gs, CPU %gs)", order,
1485  w2 - w1, t2 - t1);
1486 }
MPyramidN
Definition: MPyramid.h:250
MTetrahedronN
Definition: MTetrahedron.h:372
MHexahedronN
Definition: MHexahedron.h:610
GPoint::succeeded
bool succeeded() const
Definition: GPoint.h:63
SetOrderN
void SetOrderN(GModel *m, int order, bool linear, bool incomplete, bool onlyVisible)
Definition: HighOrder.cpp:1396
MTriangle.h
GEdge::periodic
virtual bool periodic(int dim) const
Definition: GEdge.h:219
TimeOfDay
double TimeOfDay()
Definition: OS.cpp:399
MPrism::faces_prism
static int faces_prism(const int face, const int vert)
Definition: MPrism.h:188
GModel::firstEdge
eiter firstEdge()
Definition: GModel.h:356
MEdge
Definition: MEdge.h:14
GEdge::getMeshElement
MElement * getMeshElement(std::size_t index) const
Definition: GEdge.cpp:173
MPrism15
Definition: MPrism.h:263
nodalBasis::points
fullMatrix< double > points
Definition: nodalBasis.h:16
GPoint::y
double y() const
Definition: GPoint.h:22
fullVector< double >
MTetrahedron
Definition: MTetrahedron.h:34
myresid
static void myresid(int N, GEdge *ge, double *u, fullVector< double > &r, double *weight=nullptr)
Definition: HighOrder.cpp:54
MLine::getVertex
virtual MVertex * getVertex(int num)
Definition: MLine.h:45
GFace
Definition: GFace.h:33
MLine3
Definition: MLine.h:128
GFace::triangles
std::vector< MTriangle * > triangles
Definition: GFace.h:428
MQuadrangle::getVertex
virtual MVertex * getVertex(int num)
Definition: MQuadrangle.h:64
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
GEdge::lines
std::vector< MLine * > lines
Definition: GEdge.h:42
getInnerVertexPlacement
fullMatrix< double > * getInnerVertexPlacement(int type, int order)
Definition: InnerVertexPlacement.cpp:33
SPoint2
Definition: SPoint2.h:12
OS.h
MElement::getFaceVertices
virtual void getFaceVertices(const int num, std::vector< MVertex * > &v) const
Definition: MElement.h:225
MTetrahedron::faces_tetra
static int faces_tetra(const int face, const int vert)
Definition: MTetrahedron.h:188
setFirstOrder
static void setFirstOrder(GEntity *e, std::vector< T * > &elements, bool onlyVisible, bool skipDiscrete)
Definition: HighOrder.cpp:1198
lob2lagP6
static fullMatrix< double > * lob2lagP6
Definition: HighOrder.cpp:210
MVertex
Definition: MVertex.h:24
MTriangle::gammaShapeMeasure
virtual double gammaShapeMeasure()
Definition: MTriangle.cpp:115
nodalBasis.h
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
fullVector::norm
scalar norm() const
Msg::StatusBar
static void StatusBar(bool log, const char *fmt,...)
Definition: GmshMessage.cpp:686
MVertex::z
double z() const
Definition: MVertex.h:62
reparamMeshVertexOnFace
bool reparamMeshVertexOnFace(MVertex const *v, const GFace *gf, SPoint2 &param, bool onSurface, bool failOnSeam, int dir)
Definition: MVertex.cpp:522
GFace::extrude
ExtrudeParams * extrude
Definition: GFace.h:357
SPoint3
Definition: SPoint3.h:14
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
MVertex::getNum
std::size_t getNum() const
Definition: MVertex.h:86
GFace::meshAttributes
struct GFace::@18 meshAttributes
GFace::point
virtual GPoint point(double par1, double par2) const =0
TYPE_TRI
#define TYPE_TRI
Definition: GmshDefines.h:66
InnerVertexPlacement.h
MTetrahedron10
Definition: MTetrahedron.h:233
MTriangle::getVertex
virtual MVertex * getVertex(int num)
Definition: MTriangle.h:62
MPyramid
Definition: MPyramid.h:32
GEdge::length
double length() const
Definition: GEdge.h:170
MPrism
Definition: MPrism.h:34
MVertex::point
SPoint3 point() const
Definition: MVertex.h:67
MElement::getEdgeVertices
virtual void getEdgeVertices(const int num, std::vector< MVertex * > &v) const
Definition: MElement.h:221
interpVerticesInExistingFace
static void interpVerticesInExistingFace(GEntity *ge, const fullMatrix< double > &coefficients, const std::vector< MVertex * > &vertices, std::vector< MVertex * > &vFace)
Definition: HighOrder.cpp:668
GModel::destroyMeshCaches
void destroyMeshCaches()
Definition: GModel.cpp:214
GmshMessage.h
MLine.h
getEdgeVertices
static void getEdgeVertices(GEdge *ge, MElement *ele, std::vector< MVertex * > &ve, edgeContainer &edgeVertices, bool linear, int nPts=1)
Definition: HighOrder.cpp:400
w1
const double w1
Definition: GaussQuadratureHex.cpp:18
ExtrudeParams::geo
struct ExtrudeParams::@15 geo
GEntity
Definition: GEntity.h:31
GPoint
Definition: GPoint.h:13
GEntity::getNumMeshVertices
std::size_t getNumMeshVertices()
Definition: GEntity.h:376
TYPE_PRI
#define TYPE_PRI
Definition: GmshDefines.h:70
GFace::closestPoint
virtual GPoint closestPoint(const SPoint3 &queryPoint, const double initialGuess[2]) const
Definition: GFace.cpp:1323
reparamMeshVertexOnEdge
bool reparamMeshVertexOnEdge(MVertex *v, const GEdge *ge, double &param)
Definition: MVertex.cpp:592
GFace::quadrangles
std::vector< MQuadrangle * > quadrangles
Definition: GFace.h:429
reorientTrianglePoints
static void reorientTrianglePoints(std::vector< MVertex * > &vtcs, int orientation, bool swap)
Definition: HighOrder.cpp:518
GEntity::Plane
@ Plane
Definition: GEntity.h:105
MLine
Definition: MLine.h:21
GPoint::z
double z() const
Definition: GPoint.h:23
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
MHexahedron::faces_hexa
static int faces_hexa(const int face, const int vert)
Definition: MHexahedron.h:198
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
GRegion::hexahedra
std::vector< MHexahedron * > hexahedra
Definition: GRegion.h:164
getOrder
static int getOrder(GEntity *ge)
Definition: HighOrder.cpp:1341
fullMatrix< double >
MElement::getEdge
virtual MEdge getEdge(int num) const =0
computeGLLParametersP6
static bool computeGLLParametersP6(GEdge *ge, double u0, double uN, int N, double *u, double underRelax)
Definition: HighOrder.cpp:120
GModel::lastFace
fiter lastFace()
Definition: GModel.h:359
MFace
Definition: MFace.h:20
MQuadrangleN
Definition: MQuadrangle.h:449
MFace.h
ExtrudeParams::mesh
struct ExtrudeParams::@14 mesh
MEdge::getVertex
MVertex * getVertex(std::size_t i) const
Definition: MEdge.h:39
MPrism::getVertex
virtual MVertex * getVertex(int num)
Definition: MPrism.h:71
GPoint::u
double u() const
Definition: GPoint.h:27
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
MElement::getType
virtual int getType() const =0
pow_int
double pow_int(const double &a, const int &n)
Definition: Numeric.h:39
MPyramid::faces2edge_pyramid
static int faces2edge_pyramid(const int face, const int edge)
Definition: MPyramid.h:187
reorientQuadPoints
static void reorientQuadPoints(std::vector< MVertex * > &vtcs, int orientation, bool swap, int order)
Definition: HighOrder.cpp:547
MHexahedron.h
MEdgeVertex
Definition: MVertex.h:137
HighOrder.h
MElement::getNumFaces
virtual int getNumFaces()=0
GEntity::getNumMeshElements
virtual std::size_t getNumMeshElements() const
Definition: GEntity.h:348
EXTRUDED_ENTITY
#define EXTRUDED_ENTITY
Definition: ExtrudeParams.h:17
getEdgeVerticesOnGeo
static bool getEdgeVerticesOnGeo(GEdge *ge, MVertex *v0, MVertex *v1, std::vector< MVertex * > &ve, int nPts=1)
Definition: HighOrder.cpp:247
MQuadrangle8
Definition: MQuadrangle.h:203
swap
void swap(double &a, double &b)
Definition: meshTriangulation.cpp:27
MTetrahedron::getVertex
virtual MVertex * getVertex(int num)
Definition: MTetrahedron.h:67
MElement::getNumEdgeVertices
virtual int getNumEdgeVertices() const
Definition: MElement.h:155
MElement::getFace
virtual MFace getFace(int num) const =0
GModel
Definition: GModel.h:44
Msg::StopProgressMeter
static void StopProgressMeter()
Definition: GmshMessage.cpp:318
Cpu
double Cpu()
Definition: OS.cpp:366
MPyramid::faces_pyramid
static int faces_pyramid(const int face, const int vert)
Definition: MPyramid.h:181
GModel::vertices
std::set< GVertex *, GEntityPtrLessThan > vertices
Definition: GModel.h:146
reparamMeshEdgeOnFace
bool reparamMeshEdgeOnFace(MVertex *v1, MVertex *v2, GFace *gf, SPoint2 &param1, SPoint2 &param2)
Definition: MVertex.cpp:474
MHexahedron::getVertex
virtual MVertex * getVertex(int num)
Definition: MHexahedron.h:66
MLineN
Definition: MLine.h:207
ExtrudeParams.h
faceContainer
std::map< MFace, std::vector< MVertex * >, MFaceLessThan > faceContainer
Definition: HighOrder.cpp:42
retrieveFaceBoundaryVertices
static int retrieveFaceBoundaryVertices(int k, int type, int nPts, const std::vector< MVertex * > &vCorner, const std::vector< MVertex * > &vEdges, std::vector< MVertex * > &v)
Definition: HighOrder.cpp:793
getFaceVerticesOnGeo
static void getFaceVerticesOnGeo(GFace *gf, const fullMatrix< double > &coefficients, const std::vector< MVertex * > &vertices, std::vector< MVertex * > &vf)
Definition: HighOrder.cpp:704
MPyramid.h
MTriangleN
Definition: MTriangle.h:315
GEntity::geomType
virtual GeomType geomType() const
Definition: GEntity.h:238
GModel::firstFace
fiter firstFace()
Definition: GModel.h:355
interpVerticesInExistingEdge
static void interpVerticesInExistingEdge(GEntity *ge, const MElement *edgeEl, std::vector< MVertex * > &veEdge, int nPts)
Definition: HighOrder.cpp:370
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
ExtrudeParams::Recombine
bool Recombine
Definition: ExtrudeParams.h:37
createMatLob2LagP6
void createMatLob2LagP6()
Definition: HighOrder.cpp:212
MPrism::faces2edge_prism
static int faces2edge_prism(const int face, const int edge)
Definition: MPrism.h:194
edgeContainer
std::map< std::pair< MVertex *, MVertex * >, std::vector< MVertex * > > edgeContainer
Definition: HighOrder.cpp:38
setHighOrder
static void setHighOrder(GEdge *ge, edgeContainer &edgeVertices, bool linear, int nbPts=1)
Definition: HighOrder.cpp:933
MHexahedron
Definition: MHexahedron.h:28
ExtrudeParams::Mode
int Mode
Definition: ExtrudeParams.h:49
GModel::getNumRegions
std::size_t getNumRegions() const
Definition: GModel.h:344
MElement
Definition: MElement.h:30
getFaceVerticesOnExtrudedGeo
static bool getFaceVerticesOnExtrudedGeo(GFace *gf, const fullMatrix< double > &coefficients, const std::vector< MVertex * > &vertices, std::vector< MVertex * > &vf)
Definition: HighOrder.cpp:685
GEntity::tag
int tag() const
Definition: GEntity.h:280
MFaceVertex
Definition: MVertex.h:168
GModel::getNumFaces
std::size_t getNumFaces() const
Definition: GModel.h:345
GPoint::g
const GEntity * g() const
Definition: GPoint.h:29
deleteHighOrderVertices
static void deleteHighOrderVertices(GEntity *e, bool onlyVisible, bool skipDiscrete)
Definition: HighOrder.cpp:1217
GRegion
Definition: GRegion.h:28
ExtrudeParams::ExtrudeMesh
bool ExtrudeMesh
Definition: ExtrudeParams.h:36
GModel::getNumEdges
std::size_t getNumEdges() const
Definition: GModel.h:346
GRegion::prisms
std::vector< MPrism * > prisms
Definition: GRegion.h:165
fullMatrix::size2
int size2() const
Definition: fullMatrix.h:275
MPrismN
Definition: MPrism.h:536
GFace::getMeshElement
MElement * getMeshElement(std::size_t index) const
Definition: GFace.cpp:234
MTriangle
Definition: MTriangle.h:26
TYPE_PYR
#define TYPE_PYR
Definition: GmshDefines.h:69
GRegion::pyramids
std::vector< MPyramid * > pyramids
Definition: GRegion.h:166
MElement::pnt
virtual void pnt(double u, double v, double w, SPoint3 &p) const
Definition: MElement.cpp:1072
checkHighOrderTriangles
void checkHighOrderTriangles(const char *cc, GModel *m, std::vector< MElement * > &bad, double &minJGlob)
Definition: HighOrder.cpp:1261
setHighOrderFromExistingMesh
static void setHighOrderFromExistingMesh(GEdge *ge, edgeContainer &edgeVertices)
Definition: HighOrder.cpp:1348
MElement::getVertices
void getVertices(std::vector< MVertex * > &verts)
Definition: MElement.h:103
GModel::firstRegion
riter firstRegion()
Definition: GModel.h:354
MHexahedron27
Definition: MHexahedron.h:420
TYPE_QUA
#define TYPE_QUA
Definition: GmshDefines.h:67
GModel::lastRegion
riter lastRegion()
Definition: GModel.h:358
MHexahedron::faces2edge_hexa
static int faces2edge_hexa(const int face, const int edge)
Definition: MHexahedron.h:204
MPrism18
Definition: MPrism.h:413
Context.h
GEntity::getMeshElement
virtual MElement * getMeshElement(std::size_t index) const
Definition: GEntity.h:363
MTetrahedron.h
GEdge::parBounds
virtual Range< double > parBounds(int i) const =0
MTriangle6
Definition: MTriangle.h:191
fullMatrix::size1
int size1() const
Definition: fullMatrix.h:274
MHexahedron20
Definition: MHexahedron.h:251
z
const double z
Definition: GaussQuadratureQuad.cpp:56
MQuadrangle.h
MElement::getNumPrimaryVertices
std::size_t getNumPrimaryVertices() const
Definition: MElement.h:160
MPyramid::getVertex
virtual MVertex * getVertex(int num)
Definition: MPyramid.h:74
GEdge::point
virtual GPoint point(double p) const =0
Msg::StartProgressMeter
static void StartProgressMeter(int ntotal)
Definition: GmshMessage.cpp:312
MTetrahedron::faces2edge_tetra
static int faces2edge_tetra(const int face, const int edge)
Definition: MTetrahedron.h:193
GEdge
Definition: GEdge.h:26
GModel::pruneMeshVertexAssociations
void pruneMeshVertexAssociations()
Definition: GModel.cpp:2527
TYPE_HEX
#define TYPE_HEX
Definition: GmshDefines.h:71
MPrism.h
TYPE_TET
#define TYPE_TET
Definition: GmshDefines.h:68
MQuadrangle9
Definition: MQuadrangle.h:325
fullMatrix::luSolve
bool luSolve(const fullVector< scalar > &rhs, fullVector< scalar > &result)
Definition: fullMatrix.h:603
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
ExtrudeParams::Type
int Type
Definition: ExtrudeParams.h:50
getVolumeVertices
static void getVolumeVertices(GRegion *gr, MElement *ele, std::vector< MVertex * > &newVertices, int nPts=1)
Definition: HighOrder.cpp:903
GPoint::v
double v() const
Definition: GPoint.h:28
GModel::lastEdge
eiter lastEdge()
Definition: GModel.h:360
MFaceLessThan
Definition: MFace.h:130
GModel.h
fullMatrix::mult
void mult(const fullVector< scalar > &x, fullVector< scalar > &y) const
Definition: fullMatrix.h:487
MFace::getNumVertices
std::size_t getNumVertices() const
Definition: MFace.h:29
GEdge::getNumMeshElements
std::size_t getNumMeshElements() const
Definition: GEdge.h:201
MVertex::y
double y() const
Definition: MVertex.h:61
MElement::getPolynomialOrder
virtual int getPolynomialOrder() const
Definition: MElement.h:78
GEdge::getEndVertex
virtual GVertex * getEndVertex() const
Definition: GEdge.h:64
ElementType::getNumVertices
int getNumVertices(int type)
Definition: ElementType.cpp:456
computeEquidistantParameters
static bool computeEquidistantParameters(GEdge *ge, double u0, double uN, int N, double *u, double underRelax)
Definition: HighOrder.cpp:66
MElement::distoShapeMeasure
double distoShapeMeasure()
Definition: MElement.h:273
MElement::getFunctionSpace
virtual const nodalBasis * getFunctionSpace(int order=-1, bool serendip=false) const
Definition: MElement.cpp:666
TRANSLATE
#define TRANSLATE
Definition: ExtrudeParams.h:21
GEntity::isFullyDiscrete
virtual bool isFullyDiscrete()
Definition: GEntity.h:256
GFace::getNumMeshElements
std::size_t getNumMeshElements() const
Definition: GFace.cpp:181
MElement::getPartition
virtual int getPartition() const
Definition: MElement.h:92
Msg::ProgressMeter
static void ProgressMeter(int n, bool log, const char *fmt,...)
Definition: GmshMessage.cpp:783
ExtrudeParams
Definition: ExtrudeParams.h:26
GPoint::x
double x() const
Definition: GPoint.h:21
GEntity::getVisibility
virtual char getVisibility()
Definition: GEntity.cpp:35
MElement::getNumEdges
virtual int getNumEdges() const =0
getFaceVertices
static void getFaceVertices(GFace *gf, MElement *ele, std::vector< MVertex * > &newVertices, faceContainer &faceVertices, bool linear, int nPts=1)
Definition: HighOrder.cpp:755
MQuadrangle
Definition: MQuadrangle.h:26
GEntity::deleteVertexArrays
void deleteVertexArrays()
Definition: GEntity.cpp:27
fullMatrix.h
getMinMaxVert
static bool getMinMaxVert(MVertex *v0, MVertex *v1, MVertex *&vMin, MVertex *&vMax)
Definition: HighOrder.cpp:384
fullMatrix::invert
bool invert(fullMatrix< scalar > &result) const
Definition: fullMatrix.h:641
Msg::GetErrorCount
static int GetErrorCount()
Definition: GmshMessage.cpp:347
mylength
static double mylength(GEdge *ge, int i, double *u)
Definition: HighOrder.cpp:49
GRegion::tetrahedra
std::vector< MTetrahedron * > tetrahedra
Definition: GRegion.h:163
GEntity::haveParametrization
virtual bool haveParametrization()
Definition: GEntity.h:251
MVertex::x
double x() const
Definition: MVertex.h:60
BasisFactory.h
SetOrder1
void SetOrder1(GModel *m, bool onlyVisible, bool skipDiscrete)
Definition: HighOrder.cpp:1233
checkHighOrderTetrahedron
void checkHighOrderTetrahedron(const char *cc, GModel *m, std::vector< MElement * > &bad, double &minJGlob)
Definition: HighOrder.cpp:1310