Nektar++
Loading...
Searching...
No Matches
PyrGeom.cpp
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////////////
2//
3// File: PyrGeom.cpp
4//
5// For more information, please see: http://www.nektar.info/
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: Pyramidic geometry information.
32//
33////////////////////////////////////////////////////////////////////////////////
34
36
43
45{
46const unsigned int PyrGeom::EdgeNormalToFaceVert[5][4] = {
47 {4, 5, 6, 7}, {1, 3, 6, 7}, {0, 2, 4, 7}, {1, 3, 4, 5}, {0, 2, 5, 6}};
48
54
59
60PyrGeom::PyrGeom(int id, std::array<Geometry2D *, kNfaces> faces)
61 : Geometry3D(faces[0]->GetEdge(0)->GetVertex(0)->GetCoordim())
62{
64 m_globalID = id;
65
66 /// Copy the face pointers
67 for (int i = 0; i < kNfaces; i++)
68 {
69 m_faces[i] = faces[i];
70 }
71
76}
77
79{
80 if (!m_setupState)
81 {
82 v_Setup();
83 }
84 v_FillGeom();
85
86 GeomType Gtype = eRegular;
87
88 // check to see if expansions are linear
89 if (m_xmap->GetBasisNumModes(0) != 2 || m_xmap->GetBasisNumModes(1) != 2 ||
90 m_xmap->GetBasisNumModes(2) != 2)
91 {
92 Gtype = eDeformed;
93 }
94
95 // check to see if all quadrilateral faces are parallelograms
96 if (Gtype == eRegular)
97 {
99 for (int i = 0; i < 3; ++i)
100 {
102 NekDouble A = (*m_verts[0])(i);
103 NekDouble B = (*m_verts[1])(i);
104 NekDouble C = (*m_verts[2])(i);
105 NekDouble D = (*m_verts[3])(i);
106 NekDouble E = (*m_verts[4])(i);
107 m_isoParameter[i][0] = 0.25 * (-A + B + C + D + E + E);
108
109 m_isoParameter[i][1] = 0.25 * (-A + B + C - D); // xi1
110 m_isoParameter[i][2] = 0.25 * (-A - B + C + D); // xi2
111 m_isoParameter[i][3] = 0.5 * (-A + E); // xi3
112
113 m_isoParameter[i][4] = 0.25 * (A - B + C - D); // xi1*xi2
114 NekDouble tmp = fabs(m_isoParameter[i][1]) +
115 fabs(m_isoParameter[i][2]) +
116 fabs(m_isoParameter[i][3]);
117 if (fabs(m_isoParameter[i][4]) > tmp * NekConstants::kNekZeroTol)
118 {
119 Gtype = eDeformed;
120 }
121 }
122 }
123
124 if (Gtype == eRegular)
125 {
127 }
128
129 return Gtype;
130}
131
140
141int PyrGeom::v_GetDir(const int faceidx, const int facedir) const
142{
143 if (faceidx == 0)
144 {
145 return facedir;
146 }
147 else if (faceidx == 1 || faceidx == 3)
148 {
149 return 2 * facedir;
150 }
151 else
152 {
153 return 1 + facedir;
154 }
155}
156
157int PyrGeom::v_GetEdgeNormalToFaceVert(const int i, const int j) const
158{
159 return EdgeNormalToFaceVert[i][j];
160}
161
163{
164 // find edge 0
165 int i, j;
166 unsigned int check;
167
168 // First set up the 4 bottom edges
169 int f;
170 for (f = 1; f < 5; f++)
171 {
172 int nEdges = m_faces[f]->GetNumEdges();
173 check = 0;
174 for (i = 0; i < 4; i++)
175 {
176 for (j = 0; j < nEdges; j++)
177 {
178 if (m_faces[0]->GetEid(i) == m_faces[f]->GetEid(j))
179 {
180 m_edges[f - 1] =
181 static_cast<SegGeom *>((m_faces[0])->GetEdge(i));
182 check++;
183 }
184 }
185 }
186
187 if (check < 1)
188 {
189 std::ostringstream errstrm;
190 errstrm << "Connected faces do not share an edge. Faces ";
191 errstrm << (m_faces[0])->GetGlobalID() << ", "
192 << (m_faces[f])->GetGlobalID();
193 NEKERROR(ErrorUtil::efatal, errstrm.str());
194 }
195 else if (check > 1)
196 {
197 std::ostringstream errstrm;
198 errstrm << "Connected faces share more than one edge. Faces ";
199 errstrm << (m_faces[0])->GetGlobalID() << ", "
200 << (m_faces[f])->GetGlobalID();
201 NEKERROR(ErrorUtil::efatal, errstrm.str());
202 }
203 }
204
205 // Then, set up the 4 vertical edges
206 check = 0;
207 for (i = 0; i < 3; i++) // Set up the vertical edge :face(1) and face(4)
208 {
209 for (j = 0; j < 3; j++)
210 {
211 if ((m_faces[1])->GetEid(i) == (m_faces[4])->GetEid(j))
212 {
213 m_edges[4] = static_cast<SegGeom *>((m_faces[1])->GetEdge(i));
214 check++;
215 }
216 }
217 }
218 if (check < 1)
219 {
220 std::ostringstream errstrm;
221 errstrm << "Connected faces do not share an edge. Faces ";
222 errstrm << (m_faces[1])->GetGlobalID() << ", "
223 << (m_faces[4])->GetGlobalID();
224 NEKERROR(ErrorUtil::efatal, errstrm.str());
225 }
226 else if (check > 1)
227 {
228 std::ostringstream errstrm;
229 errstrm << "Connected faces share more than one edge. Faces ";
230 errstrm << (m_faces[1])->GetGlobalID() << ", "
231 << (m_faces[4])->GetGlobalID();
232 NEKERROR(ErrorUtil::efatal, errstrm.str());
233 }
234
235 // Set up vertical edges: face(1) through face(4)
236 for (f = 1; f < 4; f++)
237 {
238 check = 0;
239 for (i = 0; i < m_faces[f]->GetNumEdges(); i++)
240 {
241 for (j = 0; j < m_faces[f + 1]->GetNumEdges(); j++)
242 {
243 if ((m_faces[f])->GetEid(i) == (m_faces[f + 1])->GetEid(j))
244 {
245 m_edges[f + 4] =
246 static_cast<SegGeom *>((m_faces[f])->GetEdge(i));
247 check++;
248 }
249 }
250 }
251
252 if (check < 1)
253 {
254 std::ostringstream errstrm;
255 errstrm << "Connected faces do not share an edge. Faces ";
256 errstrm << (m_faces[f])->GetGlobalID() << ", "
257 << (m_faces[f + 1])->GetGlobalID();
258 NEKERROR(ErrorUtil::efatal, errstrm.str());
259 }
260 else if (check > 1)
261 {
262 std::ostringstream errstrm;
263 errstrm << "Connected faces share more than one edge. Faces ";
264 errstrm << (m_faces[f])->GetGlobalID() << ", "
265 << (m_faces[f + 1])->GetGlobalID();
266 NEKERROR(ErrorUtil::efatal, errstrm.str());
267 }
268 }
269}
270
272{
273 // Set up the first 2 vertices (i.e. vertex 0,1)
274 if (m_edges[0]->GetVid(0) == m_edges[1]->GetVid(0) ||
275 m_edges[0]->GetVid(0) == m_edges[1]->GetVid(1))
276 {
277 m_verts[0] = m_edges[0]->GetVertex(1);
278 m_verts[1] = m_edges[0]->GetVertex(0);
279 }
280 else if (m_edges[0]->GetVid(1) == m_edges[1]->GetVid(0) ||
281 m_edges[0]->GetVid(1) == m_edges[1]->GetVid(1))
282 {
283 m_verts[0] = m_edges[0]->GetVertex(0);
284 m_verts[1] = m_edges[0]->GetVertex(1);
285 }
286 else
287 {
288 std::ostringstream errstrm;
289 errstrm << "Connected edges do not share a vertex. Edges ";
290 errstrm << m_edges[0]->GetGlobalID() << ", "
291 << m_edges[1]->GetGlobalID();
292 NEKERROR(ErrorUtil::efatal, errstrm.str());
293 }
294
295 // set up the other bottom vertices (i.e. vertex 2,3)
296 for (int i = 1; i < 3; i++)
297 {
298 if (m_edges[i]->GetVid(0) == m_verts[i]->GetGlobalID())
299 {
300 m_verts[i + 1] = m_edges[i]->GetVertex(1);
301 }
302 else if (m_edges[i]->GetVid(1) == m_verts[i]->GetGlobalID())
303 {
304 m_verts[i + 1] = m_edges[i]->GetVertex(0);
305 }
306 else
307 {
308 std::ostringstream errstrm;
309 errstrm << "Connected edges do not share a vertex. Edges ";
310 errstrm << m_edges[i]->GetGlobalID() << ", "
311 << m_edges[i - 1]->GetGlobalID();
312 NEKERROR(ErrorUtil::efatal, errstrm.str());
313 }
314 }
315
316 // set up top vertex
317 if (m_edges[4]->GetVid(0) == m_verts[0]->GetGlobalID())
318 {
319 m_verts[4] = m_edges[4]->GetVertex(1);
320 }
321 else
322 {
323 m_verts[4] = m_edges[4]->GetVertex(0);
324 }
325
326 int check = 0;
327 for (int i = 5; i < 8; ++i)
328 {
329 if ((m_edges[i]->GetVid(0) == m_verts[i - 4]->GetGlobalID() &&
330 m_edges[i]->GetVid(1) == m_verts[4]->GetGlobalID()) ||
331 (m_edges[i]->GetVid(1) == m_verts[i - 4]->GetGlobalID() &&
332 m_edges[i]->GetVid(0) == m_verts[4]->GetGlobalID()))
333 {
334 check++;
335 }
336 }
337 if (check != 3)
338 {
339 std::ostringstream errstrm;
340 errstrm << "Connected edges do not share a vertex. Edges ";
341 errstrm << m_edges[3]->GetGlobalID() << ", "
342 << m_edges[2]->GetGlobalID();
343 NEKERROR(ErrorUtil::efatal, errstrm.str());
344 }
345}
346
348{
349 // This 2D array holds the local id's of all the vertices for every
350 // edge. For every edge, they are ordered to what we define as being
351 // Forwards.
352 const unsigned int edgeVerts[kNedges][2] = {{0, 1}, {1, 2}, {3, 2}, {0, 3},
353 {0, 4}, {1, 4}, {2, 4}, {3, 4}};
354
355 int i;
356 for (i = 0; i < kNedges; i++)
357 {
358 if (m_edges[i]->GetVid(0) == m_verts[edgeVerts[i][0]]->GetGlobalID())
359 {
361 }
362 else if (m_edges[i]->GetVid(0) ==
363 m_verts[edgeVerts[i][1]]->GetGlobalID())
364 {
366 }
367 else
368 {
370 "Could not find matching vertex for the edge");
371 }
372 }
373}
374
376{
377 int f, i;
378
379 // These arrays represent the vector of the A and B coordinate of
380 // the local elemental coordinate system where A corresponds with
381 // the coordinate direction xi_i with the lowest index i (for that
382 // particular face) Coordinate 'B' then corresponds to the other
383 // local coordinate (i.e. with the highest index)
384 Array<OneD, NekDouble> elementAaxis(m_coordim);
385 Array<OneD, NekDouble> elementBaxis(m_coordim);
386
387 // These arrays correspond to the local coordinate
388 // system of the face itself (i.e. the Geometry2D)
389 // faceAaxis correspond to the xi_0 axis
390 // faceBaxis correspond to the xi_1 axis
393
394 // This is the base vertex of the face (i.e. the Geometry2D) This
395 // corresponds to thevertex with local ID 0 of the Geometry2D
396 unsigned int baseVertex;
397
398 // The lenght of the vectors above
399 NekDouble elementAaxis_length;
400 NekDouble elementBaxis_length;
401 NekDouble faceAaxis_length;
402 NekDouble faceBaxis_length;
403
404 // This 2D array holds the local id's of all the vertices for every
405 // face. For every face, they are ordered in such a way that the
406 // implementation below allows a unified approach for all faces.
407 const unsigned int faceVerts[kNfaces][4] = {
408 {0, 1, 2, 3},
409 {0, 1, 4, 0}, // Last four elements are triangles which only
410 {1, 2, 4, 0}, // require three vertices.
411 {3, 2, 4, 0},
412 {0, 3, 4, 0}};
413
414 NekDouble dotproduct1 = 0.0;
415 NekDouble dotproduct2 = 0.0;
416
417 unsigned int orientation;
418
419 // Loop over all the faces to set up the orientation
420 for (f = 0; f < kNqfaces + kNtfaces; f++)
421 {
422 // initialisation
423 elementAaxis_length = 0.0;
424 elementBaxis_length = 0.0;
425 faceAaxis_length = 0.0;
426 faceBaxis_length = 0.0;
427
428 dotproduct1 = 0.0;
429 dotproduct2 = 0.0;
430
431 baseVertex = m_faces[f]->GetVid(0);
432
433 // We are going to construct the vectors representing the A and
434 // B axis of every face. These vectors will be constructed as a
435 // vector-representation of the edges of the face. However, for
436 // both coordinate directions, we can represent the vectors by
437 // two different edges. That's why we need to make sure that we
438 // pick the edge to which the baseVertex of the
439 // Geometry2D-representation of the face belongs...
440
441 // Compute the length of edges on a base-face
442 if (f > 0)
443 {
444 if (baseVertex == m_verts[faceVerts[f][0]]->GetGlobalID())
445 {
446 for (i = 0; i < m_coordim; i++)
447 {
448 elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
449 (*m_verts[faceVerts[f][0]])[i];
450 elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
451 (*m_verts[faceVerts[f][0]])[i];
452 }
453 }
454 else if (baseVertex == m_verts[faceVerts[f][1]]->GetGlobalID())
455 {
456 for (i = 0; i < m_coordim; i++)
457 {
458 elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
459 (*m_verts[faceVerts[f][0]])[i];
460 elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
461 (*m_verts[faceVerts[f][1]])[i];
462 }
463 }
464 else if (baseVertex == m_verts[faceVerts[f][2]]->GetGlobalID())
465 {
466 for (i = 0; i < m_coordim; i++)
467 {
468 elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
469 (*m_verts[faceVerts[f][2]])[i];
470 elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
471 (*m_verts[faceVerts[f][0]])[i];
472 }
473 }
474 else
475 {
477 "Could not find matching vertex for the face");
478 }
479 }
480 else
481 {
482 if (baseVertex == m_verts[faceVerts[f][0]]->GetGlobalID())
483 {
484 for (i = 0; i < m_coordim; i++)
485 {
486 elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
487 (*m_verts[faceVerts[f][0]])[i];
488 elementBaxis[i] = (*m_verts[faceVerts[f][3]])[i] -
489 (*m_verts[faceVerts[f][0]])[i];
490 }
491 }
492 else if (baseVertex == m_verts[faceVerts[f][1]]->GetGlobalID())
493 {
494 for (i = 0; i < m_coordim; i++)
495 {
496 elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
497 (*m_verts[faceVerts[f][0]])[i];
498 elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
499 (*m_verts[faceVerts[f][1]])[i];
500 }
501 }
502 else if (baseVertex == m_verts[faceVerts[f][2]]->GetGlobalID())
503 {
504 for (i = 0; i < m_coordim; i++)
505 {
506 elementAaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
507 (*m_verts[faceVerts[f][3]])[i];
508 elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
509 (*m_verts[faceVerts[f][1]])[i];
510 }
511 }
512 else if (baseVertex == m_verts[faceVerts[f][3]]->GetGlobalID())
513 {
514 for (i = 0; i < m_coordim; i++)
515 {
516 elementAaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
517 (*m_verts[faceVerts[f][3]])[i];
518 elementBaxis[i] = (*m_verts[faceVerts[f][3]])[i] -
519 (*m_verts[faceVerts[f][0]])[i];
520 }
521 }
522 else
523 {
525 "Could not find matching vertex for the face");
526 }
527 }
528
529 // Now, construct the edge-vectors of the local coordinates of
530 // the Geometry2D-representation of the face
531 for (i = 0; i < m_coordim; i++)
532 {
533 int v = m_faces[f]->GetNumVerts() - 1;
534 faceAaxis[i] =
535 (*m_faces[f]->GetVertex(1))[i] - (*m_faces[f]->GetVertex(0))[i];
536 faceBaxis[i] =
537 (*m_faces[f]->GetVertex(v))[i] - (*m_faces[f]->GetVertex(0))[i];
538
539 elementAaxis_length += pow(elementAaxis[i], 2);
540 elementBaxis_length += pow(elementBaxis[i], 2);
541 faceAaxis_length += pow(faceAaxis[i], 2);
542 faceBaxis_length += pow(faceBaxis[i], 2);
543 }
544
545 elementAaxis_length = sqrt(elementAaxis_length);
546 elementBaxis_length = sqrt(elementBaxis_length);
547 faceAaxis_length = sqrt(faceAaxis_length);
548 faceBaxis_length = sqrt(faceBaxis_length);
549
550 // Calculate the inner product of both the A-axis
551 // (i.e. Elemental A axis and face A axis)
552 for (i = 0; i < m_coordim; i++)
553 {
554 dotproduct1 += elementAaxis[i] * faceAaxis[i];
555 }
556
557 NekDouble norm =
558 fabs(dotproduct1) / elementAaxis_length / faceAaxis_length;
559 orientation = 0;
560
561 // if the innerproduct is equal to the (absolute value of the ) products
562 // of the lengths of both vectors, then, the coordinate systems will NOT
563 // be transposed
564 if (fabs(norm - 1.0) < NekConstants::kNekZeroTol)
565 {
566 // if the inner product is negative, both A-axis point
567 // in reverse direction
568 if (dotproduct1 < 0.0)
569 {
570 orientation += 2;
571 }
572
573 // calculate the inner product of both B-axis
574 for (i = 0; i < m_coordim; i++)
575 {
576 dotproduct2 += elementBaxis[i] * faceBaxis[i];
577 }
578
579 norm = fabs(dotproduct2) / elementBaxis_length / faceBaxis_length;
580
581 // check that both these axis are indeed parallel
582 if (fabs(norm - 1.0) >= NekConstants::kNekZeroTol)
583 {
585 "These vectors should be parallel");
586 }
587
588 // if the inner product is negative, both B-axis point
589 // in reverse direction
590 if (dotproduct2 < 0.0)
591 {
592 orientation++;
593 }
594 }
595 // The coordinate systems are transposed
596 else
597 {
598 orientation = 4;
599
600 // Calculate the inner product between the elemental A-axis
601 // and the B-axis of the face (which are now the corresponding axis)
602 dotproduct1 = 0.0;
603 for (i = 0; i < m_coordim; i++)
604 {
605 dotproduct1 += elementAaxis[i] * faceBaxis[i];
606 }
607
608 norm = fabs(dotproduct1) / elementAaxis_length / faceBaxis_length;
609 if (fabs(norm - 1.0) >= NekConstants::kNekZeroTol)
610 {
612 "These vectors should be parallel");
613 }
614
615 // if the result is negative, both axis point in reverse
616 // directions
617 if (dotproduct1 < 0.0)
618 {
619 orientation += 2;
620 }
621
622 // Do the same for the other two corresponding axis
623 dotproduct2 = 0.0;
624 for (i = 0; i < m_coordim; i++)
625 {
626 dotproduct2 += elementBaxis[i] * faceAaxis[i];
627 }
628
629 norm = fabs(dotproduct2) / elementBaxis_length / faceAaxis_length;
630
631 // check that both these axis are indeed parallel
632 if (fabs(norm - 1.0) >= NekConstants::kNekZeroTol)
633 {
635 "These vectors should be parallel");
636 }
637
638 if (dotproduct2 < 0.0)
639 {
640 orientation++;
641 }
642 }
643
644 orientation = orientation + 5;
645
646 if (f != 0) // check triangle orientation
647 {
648 ASSERTL0(
650 "Orientation of triangular face (id = " +
651 std::to_string(m_faces[f]->GetGlobalID()) +
652 ") is inconsistent with face " + std::to_string(f) +
653 " of pyramid element (id = " + std::to_string(m_globalID) +
654 ") since Dir2 is aligned with Dir1. Mesh setup "
655 "needs investigation");
656 }
657
658 // Fill the m_forient array
659 m_forient[f] = (StdRegions::Orientation)orientation;
660 }
661}
662
663void PyrGeom::v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces)
664{
665 Geometry::v_Reset(curvedEdges, curvedFaces);
666
667 for (int i = 0; i < 5; ++i)
668 {
669 m_faces[i]->Reset(curvedEdges, curvedFaces);
670 }
671
672 SetUpXmap();
673 SetUpCoeffs(m_xmap->GetNcoeffs());
674}
675
677{
678 if (!m_setupState)
679 {
680 for (int i = 0; i < 5; ++i)
681 {
682 m_faces[i]->Setup();
683 }
684 SetUpXmap();
685 SetUpCoeffs(m_xmap->GetNcoeffs());
686
687 // check to see if expansions are linear
688 m_straightEdge = 1;
689 if (m_xmap->GetBasisNumModes(0) != 2 ||
690 m_xmap->GetBasisNumModes(1) != 2 ||
691 m_xmap->GetBasisNumModes(2) != 2)
692 {
693 m_straightEdge = 0;
694 }
695
696 m_setupState = true;
697 }
698}
699
700/**
701 * @brief Set up the #m_xmap object by determining the order of each
702 * direction from derived faces.
703 */
705{
706 std::vector<int> tmp;
707 int order0, order1;
708
709 if (m_forient[0] < 9)
710 {
711 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(0));
712 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(2));
713 order0 = *max_element(tmp.begin(), tmp.end());
714 }
715 else
716 {
717 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(1));
718 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(3));
719 order0 = *max_element(tmp.begin(), tmp.end());
720 }
721
722 if (m_forient[0] < 9)
723 {
724 tmp.clear();
725 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(1));
726 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(3));
727 tmp.push_back(m_faces[2]->GetXmap()->GetTraceNcoeffs(2));
728 order1 = *max_element(tmp.begin(), tmp.end());
729 }
730 else
731 {
732 tmp.clear();
733 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(0));
734 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(2));
735 tmp.push_back(m_faces[2]->GetXmap()->GetTraceNcoeffs(2));
736 order1 = *max_element(tmp.begin(), tmp.end());
737 }
738
739 tmp.clear();
740 tmp.push_back(order0);
741 tmp.push_back(order1);
742 tmp.push_back(m_faces[1]->GetXmap()->GetTraceNcoeffs(1));
743 tmp.push_back(m_faces[1]->GetXmap()->GetTraceNcoeffs(2));
744 tmp.push_back(m_faces[3]->GetXmap()->GetTraceNcoeffs(1));
745 tmp.push_back(m_faces[3]->GetXmap()->GetTraceNcoeffs(2));
746 int order2 = *max_element(tmp.begin(), tmp.end());
747
748 std::array<LibUtilities::BasisKey, 3> basis = {
751 LibUtilities::PointsKey(order0 + 1,
755 LibUtilities::PointsKey(order1 + 1,
760 LibUtilities::eGaussRadauMAlpha2Beta0))};
761
762 m_xmap = GetStdPyrFactory().CreateInstance(basis);
763}
764
765/**
766 * @brief Put all quadrature information into face/edge structure and
767 * backward transform.
768 *
769 * Note verts, edges, and faces are listed according to anticlockwise
770 * convention but points in _coeffs have to be in array format from left
771 * to right.
772 */
774{
775 if (m_state == ePtsFilled)
776 {
777 return;
778 }
779
780 int i, j, k;
781
782 for (i = 0; i < kNfaces; i++)
783 {
784 m_faces[i]->FillGeom();
785
786 int nFaceCoeffs = m_faces[i]->GetXmap()->GetNcoeffs();
787
788 Array<OneD, unsigned int> mapArray(nFaceCoeffs);
789 Array<OneD, int> signArray(nFaceCoeffs);
790
791 if (m_forient[i] < 9)
792 {
793 m_xmap->GetTraceToElementMap(
794 i, mapArray, signArray, m_forient[i],
795 m_faces[i]->GetXmap()->GetTraceNcoeffs(0),
796 m_faces[i]->GetXmap()->GetTraceNcoeffs(1));
797 }
798 else
799 {
800 m_xmap->GetTraceToElementMap(
801 i, mapArray, signArray, m_forient[i],
802 m_faces[i]->GetXmap()->GetTraceNcoeffs(1),
803 m_faces[i]->GetXmap()->GetTraceNcoeffs(0));
804 }
805
806 for (j = 0; j < m_coordim; j++)
807 {
808 const Array<OneD, const NekDouble> &coeffs =
809 m_faces[i]->GetCoeffs(j);
810
811 for (k = 0; k < nFaceCoeffs; k++)
812 {
813 NekDouble v = signArray[k] * coeffs[k];
814 m_coeffs[j][mapArray[k]] = v;
815 }
816 }
817 }
818
820}
821
822} // namespace Nektar::SpatialDomains
#define ASSERTL0(condition, msg)
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Describes the specification for a Basis.
Definition Basis.h:45
Defines a specification for a set of points.
Definition Points.h:50
static std::unique_ptr< DataType, UniquePtrDeleter > AllocateUniquePtr(const Args &...args)
3D geometry information
Definition Geometry3D.h:50
bool m_setupState
Wether or not the setup routines have been run.
Definition Geometry.h:190
GeomState m_state
Enumeration to dictate whether coefficients are filled.
Definition Geometry.h:188
void SetUpCoeffs(const int nCoeffs)
Initialise the Geometry::m_coeffs array.
Definition Geometry.h:694
int GetVid(int i) const
Returns global id of vertex i of this object.
Definition Geometry.h:345
Array< OneD, Array< OneD, NekDouble > > m_isoParameter
Definition Geometry.h:199
virtual void v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces)
Reset this geometry object: unset the current state, zero Geometry::m_coeffs and remove allocated Geo...
Definition Geometry.cpp:366
int GetGlobalID(void) const
Get the ID of this object.
Definition Geometry.h:314
PointGeom * GetVertex(int i) const
Returns vertex i of this object.
Definition Geometry.h:353
std::vector< Array< OneD, NekDouble > > m_coeffs
Array containing expansion coefficients of m_xmap.
Definition Geometry.h:196
LibUtilities::ShapeType m_shapeType
Type of shape.
Definition Geometry.h:192
StdRegions::StdExpansionSharedPtr m_xmap
mapping containing isoparametric transformation.
Definition Geometry.h:186
StdRegions::StdExpansionSharedPtr GetXmap() const
Return the mapping object Geometry::m_xmap that represents the coordinate transformation from standar...
Definition Geometry.h:440
Geometry1D * GetEdge(int i) const
Returns edge i of this object.
Definition Geometry.h:361
int m_coordim
Coordinate dimension of this geometry object.
Definition Geometry.h:184
int GetEid(int i) const
Get the ID of edge i of this object.
Definition Geometry.cpp:83
std::array< Geometry2D *, kNfaces > m_faces
Definition PyrGeom.h:115
std::array< SegGeom *, kNedges > m_edges
Definition PyrGeom.h:114
std::array< StdRegions::Orientation, kNfaces > m_forient
Definition PyrGeom.h:117
GeomFactorsUniquePtr v_GenGeomFactors(LibUtilities::PointsKeyVector &keyTgt) override
Used by Expansion to generate associated GeomFactors.
Definition PyrGeom.cpp:132
static const int kNfaces
Definition PyrGeom.h:55
int v_GetDir(const int faceidx, const int facedir) const override
Returns the element coordinate direction corresponding to a given face coordinate direction.
Definition PyrGeom.cpp:141
std::array< StdRegions::Orientation, kNedges > m_eorient
Definition PyrGeom.h:116
void SetUpXmap()
Set up the m_xmap object by determining the order of each direction from derived faces.
Definition PyrGeom.cpp:704
static const int kNedges
Definition PyrGeom.h:52
void v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces) override
Reset this geometry object: unset the current state, zero Geometry::m_coeffs and remove allocated Geo...
Definition PyrGeom.cpp:663
static const int kNtfaces
Definition PyrGeom.h:54
static const int kNqfaces
Definition PyrGeom.h:53
static const unsigned int EdgeNormalToFaceVert[5][4]
Definition PyrGeom.h:126
GeomType v_CalcGeomType() override
Definition PyrGeom.cpp:78
void v_FillGeom() override
Put all quadrature information into face/edge structure and backward transform.
Definition PyrGeom.cpp:773
std::array< PointGeom *, kNverts > m_verts
Definition PyrGeom.h:113
int v_GetEdgeNormalToFaceVert(const int i, const int j) const override
Returns the standard lement edge IDs that are normal to a given face vertex.
Definition PyrGeom.cpp:157
A simple factory for Xmap objects that is based on the element type, the basis and quadrature selecti...
std::vector< PointsKey > PointsKeyVector
Definition Points.h:313
@ eGaussLobattoLegendre
1D Gauss-Lobatto-Legendre quadrature points
Definition PointsType.h:51
@ eModifiedPyr_C
Principle Modified Functions.
Definition BasisType.h:53
@ eModified_A
Principle Modified Functions .
Definition BasisType.h:48
static const NekDouble kNekZeroTol
unique_ptr_objpool< GeomFactors > GeomFactorsUniquePtr
Definition Geometry.h:62
XmapFactory< StdRegions::StdPyrExp, 3 > & GetStdPyrFactory()
Definition PyrGeom.cpp:49
std::map< int, CurveUniquePtr > CurveMap
Definition Geometry.h:71
GeomType
Indicates the type of element geometry.
@ eRegular
Geometry is straight-sided with constant geometric factors.
@ eDeformed
Geometry is curved or has non-constant factors.
@ ePtsFilled
Geometric information has been generated.
scalarT< T > sqrt(scalarT< T > in)
Definition scalar.hpp:290