Nektar++
Loading...
Searching...
No Matches
PrismGeom.cpp
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////////////
2//
3// File: PrismGeom.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: Prismatic geometry definition.
32//
33////////////////////////////////////////////////////////////////////////////////
34
42
44{
45
46const unsigned int PrismGeom::VertexEdgeConnectivity[6][3] = {
47 {0, 3, 4}, {0, 1, 5}, {1, 2, 6}, {2, 3, 7}, {4, 5, 8}, {6, 7, 8}};
48const unsigned int PrismGeom::VertexFaceConnectivity[6][3] = {
49 {0, 1, 4}, {0, 1, 2}, {0, 2, 3}, {0, 3, 4}, {1, 2, 4}, {2, 3, 4}};
50const unsigned int PrismGeom::EdgeFaceConnectivity[9][2] = {
51 {0, 1}, {0, 2}, {0, 3}, {0, 4}, {1, 4}, {1, 2}, {2, 3}, {3, 4}, {2, 4}};
52const unsigned int PrismGeom::EdgeNormalToFaceVert[5][4] = {
53 {4, 5, 6, 7}, {1, 3, 8, -1}, {0, 2, 4, 7}, {1, 3, 8, -1}, {0, 2, 5, 6}};
54
60
65
66PrismGeom::PrismGeom(int id, std::array<Geometry2D *, kNfaces> faces)
67 : Geometry3D(faces[0]->GetEdge(0)->GetVertex(0)->GetCoordim())
68{
70 m_globalID = id;
71 m_faces = faces;
72
73 /// Set up local objects.
78}
79
80int PrismGeom::v_GetDir(const int faceidx, const int facedir) const
81{
82 if (faceidx == 0)
83 {
84 return facedir;
85 }
86 else if (faceidx == 1 || faceidx == 3)
87 {
88 return 2 * facedir;
89 }
90 else
91 {
92 return 1 + facedir;
93 }
94}
95
97{
98 if (!m_setupState)
99 {
100 v_Setup();
101 }
102 v_FillGeom();
103
104 GeomType Gtype = eRegular;
105
106 // check to see if expansions are linear
107 if (m_xmap->GetBasisNumModes(0) != 2 || m_xmap->GetBasisNumModes(1) != 2 ||
108 m_xmap->GetBasisNumModes(2) != 2)
109 {
110 Gtype = eDeformed;
111 }
112
113 // check to see if all quadrilateral faces are parallelograms
114 if (Gtype == eRegular)
115 {
117 for (int i = 0; i < 3; ++i)
118 {
120 NekDouble A = (*m_verts[0])(i);
121 NekDouble B = (*m_verts[1])(i);
122 NekDouble C = (*m_verts[2])(i);
123 NekDouble D = (*m_verts[3])(i);
124 NekDouble E = (*m_verts[4])(i);
125 NekDouble F = (*m_verts[5])(i);
126 m_isoParameter[i][0] = 0.25 * (B + C + E + F);
127
128 m_isoParameter[i][1] = 0.25 * (-A + B + C - D); // xi1
129 m_isoParameter[i][2] = 0.25 * (-B + C - E + F); // xi2
130 m_isoParameter[i][3] = 0.25 * (-A - D + E + F); // xi3
131
132 m_isoParameter[i][4] = 0.25 * (A - B + C - D); // xi1*xi2
133 m_isoParameter[i][5] = 0.25 * (A - D - E + F); // xi2*xi3
134 NekDouble tmp = fabs(m_isoParameter[i][1]) +
135 fabs(m_isoParameter[i][2]) +
136 fabs(m_isoParameter[i][3]);
138 for (int d = 4; d < 6; ++d)
139 {
140 if (fabs(m_isoParameter[i][d]) > tmp)
141 {
142 Gtype = eDeformed;
143 }
144 }
145 }
146 }
147
148 if (Gtype == eRegular)
149 {
151 }
152
153 return Gtype;
154}
155
164
165int PrismGeom::v_GetVertexEdgeMap(const int i, const int j) const
166{
167 return VertexEdgeConnectivity[i][j];
168}
169
170int PrismGeom::v_GetVertexFaceMap(const int i, const int j) const
171{
172 return VertexFaceConnectivity[i][j];
173}
174
175int PrismGeom::v_GetEdgeFaceMap(const int i, const int j) const
176{
177 return EdgeFaceConnectivity[i][j];
178}
179
180int PrismGeom::v_GetEdgeNormalToFaceVert(const int i, const int j) const
181{
182 return EdgeNormalToFaceVert[i][j];
183}
184
186{
187 // find edge 0
188 int i, j;
189 unsigned int check;
190
191 // First set up the 4 bottom edges
192 int f; // Connected face index
193 for (f = 1; f < 5; f++)
194 {
195 int nEdges = m_faces[f]->GetNumEdges();
196 check = 0;
197 for (i = 0; i < 4; i++)
198 {
199 for (j = 0; j < nEdges; j++)
200 {
201 if (m_faces[0]->GetEid(i) == m_faces[f]->GetEid(j))
202 {
203 m_edges[f - 1] =
204 static_cast<SegGeom *>((m_faces[0])->GetEdge(i));
205 check++;
206 }
207 }
208 }
209
210 if (check < 1)
211 {
212 std::ostringstream errstrm;
213 errstrm << "Connected faces do not share an edge. Faces ";
214 errstrm << (m_faces[0])->GetGlobalID() << ", "
215 << (m_faces[f])->GetGlobalID();
216 NEKERROR(ErrorUtil::efatal, errstrm.str());
217 }
218 else if (check > 1)
219 {
220 std::ostringstream errstrm;
221 errstrm << "Connected faces share more than one edge. Faces ";
222 errstrm << (m_faces[0])->GetGlobalID() << ", "
223 << (m_faces[f])->GetGlobalID();
224 NEKERROR(ErrorUtil::efatal, errstrm.str());
225 }
226 }
227
228 // Then, set up the 4 vertical edges
229 check = 0;
230 for (i = 0; i < 3; i++) // Set up the vertical edge :face(1) and face(4)
231 {
232 for (j = 0; j < 4; j++)
233 {
234 if ((m_faces[1])->GetEid(i) == (m_faces[4])->GetEid(j))
235 {
236 m_edges[4] = static_cast<SegGeom *>((m_faces[1])->GetEdge(i));
237 check++;
238 }
239 }
240 }
241 if (check < 1)
242 {
243 std::ostringstream errstrm;
244 errstrm << "Connected faces do not share an edge. Faces ";
245 errstrm << (m_faces[1])->GetGlobalID() << ", "
246 << (m_faces[4])->GetGlobalID();
247 NEKERROR(ErrorUtil::efatal, errstrm.str());
248 }
249 else if (check > 1)
250 {
251 std::ostringstream errstrm;
252 errstrm << "Connected faces share more than one edge. Faces ";
253 errstrm << (m_faces[1])->GetGlobalID() << ", "
254 << (m_faces[4])->GetGlobalID();
255 NEKERROR(ErrorUtil::efatal, errstrm.str());
256 }
257 // Set up vertical edges: face(1) through face(4)
258 for (f = 1; f < 4; f++)
259 {
260 check = 0;
261 for (i = 0; i < m_faces[f]->GetNumEdges(); i++)
262 {
263 for (j = 0; j < m_faces[f + 1]->GetNumEdges(); j++)
264 {
265 if ((m_faces[f])->GetEid(i) == (m_faces[f + 1])->GetEid(j))
266 {
267 m_edges[f + 4] =
268 static_cast<SegGeom *>((m_faces[f])->GetEdge(i));
269 check++;
270 }
271 }
272 }
273
274 if (check < 1)
275 {
276 std::ostringstream errstrm;
277 errstrm << "Connected faces do not share an edge. Faces ";
278 errstrm << (m_faces[f])->GetGlobalID() << ", "
279 << (m_faces[f + 1])->GetGlobalID();
280 NEKERROR(ErrorUtil::efatal, errstrm.str());
281 }
282 else if (check > 1)
283 {
284 std::ostringstream errstrm;
285 errstrm << "Connected faces share more than one edge. Faces ";
286 errstrm << (m_faces[f])->GetGlobalID() << ", "
287 << (m_faces[f + 1])->GetGlobalID();
288 NEKERROR(ErrorUtil::efatal, errstrm.str());
289 }
290 }
291
292 // Finally, set up the 1 top edge
293 check = 0;
294 for (i = 0; i < 4; i++)
295 {
296 for (j = 0; j < 4; j++)
297 {
298 if ((m_faces[2])->GetEid(i) == (m_faces[4])->GetEid(j))
299 {
300 m_edges[8] = static_cast<SegGeom *>((m_faces[2])->GetEdge(i));
301 check++;
302 }
303 }
304 }
305
306 if (check < 1)
307 {
308 std::ostringstream errstrm;
309 errstrm << "Connected faces do not share an edge. Faces ";
310 errstrm << (m_faces[1])->GetGlobalID() << ", "
311 << (m_faces[3])->GetGlobalID();
312 NEKERROR(ErrorUtil::efatal, errstrm.str());
313 }
314 else if (check > 1)
315 {
316 std::ostringstream errstrm;
317 errstrm << "Connected faces share more than one edge. Faces ";
318 errstrm << (m_faces[1])->GetGlobalID() << ", "
319 << (m_faces[3])->GetGlobalID();
320 NEKERROR(ErrorUtil::efatal, errstrm.str());
321 }
322}
323
325{
326
327 // Set up the first 2 vertices (i.e. vertex 0,1)
328 if ((m_edges[0]->GetVid(0) == m_edges[1]->GetVid(0)) ||
329 (m_edges[0]->GetVid(0) == m_edges[1]->GetVid(1)))
330 {
331 m_verts[0] = m_edges[0]->GetVertex(1);
332 m_verts[1] = m_edges[0]->GetVertex(0);
333 }
334 else if ((m_edges[0]->GetVid(1) == m_edges[1]->GetVid(0)) ||
335 (m_edges[0]->GetVid(1) == m_edges[1]->GetVid(1)))
336 {
337 m_verts[0] = m_edges[0]->GetVertex(0);
338 m_verts[1] = m_edges[0]->GetVertex(1);
339 }
340 else
341 {
342 std::ostringstream errstrm;
343 errstrm << "Connected edges do not share a vertex. Edges ";
344 errstrm << m_edges[0]->GetGlobalID() << ", "
345 << m_edges[1]->GetGlobalID();
346 NEKERROR(ErrorUtil::efatal, errstrm.str());
347 }
348
349 // set up the other bottom vertices (i.e. vertex 2,3)
350 for (int i = 1; i < 3; i++)
351 {
352 if (m_edges[i]->GetVid(0) == m_verts[i]->GetGlobalID())
353 {
354 m_verts[i + 1] = m_edges[i]->GetVertex(1);
355 }
356 else if (m_edges[i]->GetVid(1) == m_verts[i]->GetGlobalID())
357 {
358 m_verts[i + 1] = m_edges[i]->GetVertex(0);
359 }
360 else
361 {
362 std::ostringstream errstrm;
363 errstrm << "Connected edges do not share a vertex. Edges ";
364 errstrm << m_edges[i]->GetGlobalID() << ", "
365 << m_edges[i - 1]->GetGlobalID();
366 NEKERROR(ErrorUtil::efatal, errstrm.str());
367 }
368 }
369
370 // set up top vertices
371 // First, set up vertices 4,5
372 if ((m_edges[8]->GetVid(0) == m_edges[4]->GetVid(0)) ||
373 (m_edges[8]->GetVid(0) == m_edges[4]->GetVid(1)))
374 {
375 m_verts[4] = m_edges[8]->GetVertex(0);
376 m_verts[5] = m_edges[8]->GetVertex(1);
377 }
378 else if ((m_edges[8]->GetVid(1) == m_edges[4]->GetVid(0)) ||
379 (m_edges[8]->GetVid(1) == m_edges[4]->GetVid(1)))
380 {
381 m_verts[4] = m_edges[8]->GetVertex(1);
382 m_verts[5] = m_edges[8]->GetVertex(0);
383 }
384 else
385 {
386 std::ostringstream errstrm;
387 errstrm << "Connected edges do not share a vertex. Edges ";
388 errstrm << m_edges[8]->GetGlobalID();
389 NEKERROR(ErrorUtil::efatal, errstrm.str());
390 }
391}
392
394{
395
396 // This 2D array holds the local id's of all the vertices
397 // for every edge. For every edge, they are ordered to what we
398 // define as being Forwards
399 const unsigned int edgeVerts[kNedges][2] = {
400 {0, 1}, {1, 2}, {3, 2}, {0, 3}, {0, 4}, {1, 4}, {2, 5}, {3, 5}, {4, 5}};
401
402 int i;
403 for (i = 0; i < kNedges; i++)
404 {
405 if (m_edges[i]->GetVid(0) == m_verts[edgeVerts[i][0]]->GetGlobalID())
406 {
408 }
409 else if (m_edges[i]->GetVid(0) ==
410 m_verts[edgeVerts[i][1]]->GetGlobalID())
411 {
413 }
414 else
415 {
417 "Could not find matching vertex for the edge");
418 }
419 }
420}
421
423{
424 int f, i;
425
426 // These arrays represent the vector of the A and B
427 // coordinate of the local elemental coordinate system
428 // where A corresponds with the coordinate direction xi_i
429 // with the lowest index i (for that particular face)
430 // Coordinate 'B' then corresponds to the other local
431 // coordinate (i.e. with the highest index)
432 Array<OneD, NekDouble> elementAaxis(m_coordim);
433 Array<OneD, NekDouble> elementBaxis(m_coordim);
434
435 // These arrays correspond to the local coordinate
436 // system of the face itself (i.e. the Geometry2D)
437 // faceAaxis correspond to the xi_0 axis
438 // faceBaxis correspond to the xi_1 axis
441
442 // This is the base vertex of the face (i.e. the Geometry2D)
443 // This corresponds to thevertex with local ID 0 of the
444 // Geometry2D
445 unsigned int baseVertex;
446
447 // The length of the vectors above
448 NekDouble elementAaxis_length;
449 NekDouble elementBaxis_length;
450 NekDouble faceAaxis_length;
451 NekDouble faceBaxis_length;
452
453 // This 2D array holds the local id's of all the vertices
454 // for every face. For every face, they are ordered in such
455 // a way that the implementation below allows a unified approach
456 // for all faces.
457 const unsigned int faceVerts[kNfaces][QuadGeom::kNverts] = {
458 {0, 1, 2, 3},
459 {0, 1, 4, 0}, // This is triangle requires only three vertices
460 {1, 2, 5, 4},
461 {3, 2, 5, 0}, // This is triangle requires only three vertices
462 {0, 3, 5, 4},
463 };
464
465 NekDouble dotproduct1 = 0.0;
466 NekDouble dotproduct2 = 0.0;
467
468 unsigned int orientation;
469
470 // Loop over all the faces to set up the orientation
471 for (f = 0; f < kNqfaces + kNtfaces; f++)
472 {
473 // initialisation
474 elementAaxis_length = 0.0;
475 elementBaxis_length = 0.0;
476 faceAaxis_length = 0.0;
477 faceBaxis_length = 0.0;
478
479 dotproduct1 = 0.0;
480 dotproduct2 = 0.0;
481
482 baseVertex = m_faces[f]->GetVid(0);
483
484 // We are going to construct the vectors representing the A
485 // and B axis of every face. These vectors will be constructed
486 // as a vector-representation of the edges of the
487 // face. However, for both coordinate directions, we can
488 // represent the vectors by two different edges. That's why we
489 // need to make sure that we pick the edge to which the
490 // baseVertex of the Geometry2D-representation of the face
491 // belongs...
492
493 // Compute the length of edges on a base-face
494 if (f == 1 || f == 3)
495 { // Face is a Triangle
496 if (baseVertex == m_verts[faceVerts[f][0]]->GetGlobalID())
497 {
498 for (i = 0; i < m_coordim; i++)
499 {
500 elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
501 (*m_verts[faceVerts[f][0]])[i];
502 elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
503 (*m_verts[faceVerts[f][0]])[i];
504 }
505 }
506 else if (baseVertex == m_verts[faceVerts[f][1]]->GetGlobalID())
507 {
508 for (i = 0; i < m_coordim; i++)
509 {
510 elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
511 (*m_verts[faceVerts[f][0]])[i];
512 elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
513 (*m_verts[faceVerts[f][1]])[i];
514 }
515 }
516 else if (baseVertex == m_verts[faceVerts[f][2]]->GetGlobalID())
517 {
518 for (i = 0; i < m_coordim; i++)
519 {
520 elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
521 (*m_verts[faceVerts[f][2]])[i];
522 elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
523 (*m_verts[faceVerts[f][0]])[i];
524 }
525 }
526 else
527 {
529 "Could not find matching vertex for the face");
530 }
531 }
532 else
533 { // Face is a Quad
534 if (baseVertex == m_verts[faceVerts[f][0]]->GetGlobalID())
535 {
536 for (i = 0; i < m_coordim; i++)
537 {
538 elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
539 (*m_verts[faceVerts[f][0]])[i];
540 elementBaxis[i] = (*m_verts[faceVerts[f][3]])[i] -
541 (*m_verts[faceVerts[f][0]])[i];
542 }
543 }
544 else if (baseVertex == m_verts[faceVerts[f][1]]->GetGlobalID())
545 {
546 for (i = 0; i < m_coordim; i++)
547 {
548 elementAaxis[i] = (*m_verts[faceVerts[f][1]])[i] -
549 (*m_verts[faceVerts[f][0]])[i];
550 elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
551 (*m_verts[faceVerts[f][1]])[i];
552 }
553 }
554 else if (baseVertex == m_verts[faceVerts[f][2]]->GetGlobalID())
555 {
556 for (i = 0; i < m_coordim; i++)
557 {
558 elementAaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
559 (*m_verts[faceVerts[f][3]])[i];
560 elementBaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
561 (*m_verts[faceVerts[f][1]])[i];
562 }
563 }
564 else if (baseVertex == m_verts[faceVerts[f][3]]->GetGlobalID())
565 {
566 for (i = 0; i < m_coordim; i++)
567 {
568 elementAaxis[i] = (*m_verts[faceVerts[f][2]])[i] -
569 (*m_verts[faceVerts[f][3]])[i];
570 elementBaxis[i] = (*m_verts[faceVerts[f][3]])[i] -
571 (*m_verts[faceVerts[f][0]])[i];
572 }
573 }
574 else
575 {
577 "Could not find matching vertex for the face");
578 }
579 }
580 // Now, construct the edge-vectors of the local coordinates of
581 // the Geometry2D-representation of the face
582 for (i = 0; i < m_coordim; i++)
583 {
584 int v = m_faces[f]->GetNumVerts() - 1;
585 faceAaxis[i] =
586 (*m_faces[f]->GetVertex(1))[i] - (*m_faces[f]->GetVertex(0))[i];
587 faceBaxis[i] =
588 (*m_faces[f]->GetVertex(v))[i] - (*m_faces[f]->GetVertex(0))[i];
589
590 elementAaxis_length += pow(elementAaxis[i], 2);
591 elementBaxis_length += pow(elementBaxis[i], 2);
592 faceAaxis_length += pow(faceAaxis[i], 2);
593 faceBaxis_length += pow(faceBaxis[i], 2);
594 }
595
596 elementAaxis_length = sqrt(elementAaxis_length);
597 elementBaxis_length = sqrt(elementBaxis_length);
598 faceAaxis_length = sqrt(faceAaxis_length);
599 faceBaxis_length = sqrt(faceBaxis_length);
600
601 // Calculate the inner product of both the A-axis
602 // (i.e. Elemental A axis and face A axis)
603 for (i = 0; i < m_coordim; i++)
604 {
605 dotproduct1 += elementAaxis[i] * faceAaxis[i];
606 }
607
608 orientation = 0;
609
610 // if the innerproduct is equal to the (absolute value of the ) products
611 // of the lengths of both vectors, then, the coordinate systems will NOT
612 // be transposed
613 if (fabs(elementAaxis_length * faceAaxis_length - fabs(dotproduct1)) <
615 {
616 // if the inner product is negative, both A-axis point
617 // in reverse direction
618 if (dotproduct1 < 0.0)
619 {
620 orientation += 2;
621 }
622
623 // calculate the inner product of both B-axis
624 for (i = 0; i < m_coordim; i++)
625 {
626 dotproduct2 += elementBaxis[i] * faceBaxis[i];
627 }
628 if (fabs(
629 fabs(dotproduct2 / elementBaxis_length / faceBaxis_length) -
631 {
633 "These vectors should be parallel");
634 }
635
636 // if the inner product is negative, both B-axis point
637 // in reverse direction
638 if (dotproduct2 < 0.0)
639 {
640 orientation++;
641 }
642 }
643 // The coordinate systems are transposed
644 else
645 {
646 orientation = 4;
647
648 // Calculate the inner product between the elemental A-axis
649 // and the B-axis of the face (which are now the corresponding axis)
650 dotproduct1 = 0.0;
651 for (i = 0; i < m_coordim; i++)
652 {
653 dotproduct1 += elementAaxis[i] * faceBaxis[i];
654 }
655
656 // check that both these axis are indeed parallel
657 if (fabs(fabs(dotproduct1) / elementAaxis_length /
658 faceBaxis_length -
660 {
662 "These vectors should be parallel");
663 }
664
665 // if the result is negative, both axis point in reverse
666 // directions
667 if (dotproduct1 < 0.0)
668 {
669 orientation += 2;
670 }
671
672 // Do the same for the other two corresponding axis
673 dotproduct2 = 0.0;
674 for (i = 0; i < m_coordim; i++)
675 {
676 dotproduct2 += elementBaxis[i] * faceAaxis[i];
677 }
678
679 if (fabs(fabs(dotproduct2) / elementBaxis_length /
680 faceAaxis_length -
682 {
684 "These vectors should be parallel");
685 }
686
687 if (dotproduct2 < 0.0)
688 {
689 orientation++;
690 }
691 }
692
693 orientation = orientation + 5;
694
695 if ((f == 1) || (f == 3)) // check triange orientation
696 {
697 ASSERTL0(
699 "Orientation of triangular face (id = " +
700 std::to_string(m_faces[f]->GetGlobalID()) +
701 ") is inconsistent with face " + std::to_string(f) +
702 " of prism element (id = " + std::to_string(m_globalID) +
703 ") since Dir2 is aligned with Dir1. Mesh setup "
704 "needs investigation");
705 }
706
707 // Fill the m_forient array
708 m_forient[f] = (StdRegions::Orientation)orientation;
709 }
710}
711
712void PrismGeom::v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces)
713{
714 Geometry::v_Reset(curvedEdges, curvedFaces);
715
716 for (int i = 0; i < 5; ++i)
717 {
718 m_faces[i]->Reset(curvedEdges, curvedFaces);
719 }
720}
721
723{
724 if (!m_setupState)
725 {
726 for (int i = 0; i < 5; ++i)
727 {
728 m_faces[i]->Setup();
729 }
730 SetUpXmap();
731 SetUpCoeffs(m_xmap->GetNcoeffs());
732
733 // check to see if expansions are linear
734 m_straightEdge = 1;
735 if (m_xmap->GetBasisNumModes(0) != 2 ||
736 m_xmap->GetBasisNumModes(1) != 2 ||
737 m_xmap->GetBasisNumModes(2) != 2)
738 {
739 m_straightEdge = 0;
740 }
741
742 m_setupState = true;
743 }
744}
745
746/**
747 * @brief Set up the #m_xmap object by determining the order of each
748 * direction from derived faces.
749 */
751{
752 std::vector<int> tmp;
753 int order0, order1;
754
755 if (m_forient[0] < 9)
756 {
757 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(0));
758 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(2));
759 order0 = *std::max_element(tmp.begin(), tmp.end());
760 }
761 else
762 {
763 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(1));
764 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(3));
765 order0 = *std::max_element(tmp.begin(), tmp.end());
766 }
767
768 if (m_forient[0] < 9)
769 {
770 tmp.clear();
771 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(1));
772 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(3));
773 tmp.push_back(m_faces[2]->GetXmap()->GetTraceNcoeffs(2));
774 order1 = *std::max_element(tmp.begin(), tmp.end());
775 }
776 else
777 {
778 tmp.clear();
779 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(0));
780 tmp.push_back(m_faces[0]->GetXmap()->GetTraceNcoeffs(2));
781 tmp.push_back(m_faces[2]->GetXmap()->GetTraceNcoeffs(2));
782 order1 = *std::max_element(tmp.begin(), tmp.end());
783 }
784
785 tmp.clear();
786 tmp.push_back(order0);
787 tmp.push_back(order1);
788 tmp.push_back(m_faces[1]->GetXmap()->GetTraceNcoeffs(1));
789 tmp.push_back(m_faces[1]->GetXmap()->GetTraceNcoeffs(2));
790 tmp.push_back(m_faces[3]->GetXmap()->GetTraceNcoeffs(1));
791 tmp.push_back(m_faces[3]->GetXmap()->GetTraceNcoeffs(2));
792 int order2 = *std::max_element(tmp.begin(), tmp.end());
793
794 std::array<LibUtilities::BasisKey, 3> basis = {
797 LibUtilities::PointsKey(order0 + 1,
801 LibUtilities::PointsKey(order1 + 1,
806 LibUtilities::eGaussRadauMAlpha1Beta0))};
807
808 m_xmap = GetStdPrismFactory().CreateInstance(basis);
809}
810
811/**
812 * @brief Put all quadrature information into face/edge structure and
813 * backward transform.
814 *
815 * Note verts, edges, and faces are listed according to anticlockwise
816 * convention but points in _coeffs have to be in array format from left
817 * to right.
818 */
820{
821 if (m_state == ePtsFilled)
822 {
823 return;
824 }
825
826 int i, j, k;
827
828 for (i = 0; i < kNfaces; i++)
829 {
830 m_faces[i]->FillGeom();
831
832 int nFaceCoeffs = m_faces[i]->GetXmap()->GetNcoeffs();
833
834 Array<OneD, unsigned int> mapArray(nFaceCoeffs);
835 Array<OneD, int> signArray(nFaceCoeffs);
836
837 if (m_forient[i] < 9)
838 {
839 m_xmap->GetTraceToElementMap(
840 i, mapArray, signArray, m_forient[i],
841 m_faces[i]->GetXmap()->GetTraceNcoeffs(0),
842 m_faces[i]->GetXmap()->GetTraceNcoeffs(1));
843 }
844 else
845 {
846 m_xmap->GetTraceToElementMap(
847 i, mapArray, signArray, m_forient[i],
848 m_faces[i]->GetXmap()->GetTraceNcoeffs(1),
849 m_faces[i]->GetXmap()->GetTraceNcoeffs(0));
850 }
851
852 for (j = 0; j < m_coordim; j++)
853 {
854 const Array<OneD, const NekDouble> &coeffs =
855 m_faces[i]->GetCoeffs(j);
856
857 for (k = 0; k < nFaceCoeffs; k++)
858 {
859 NekDouble v = signArray[k] * coeffs[k];
860 m_coeffs[j][mapArray[k]] = v;
861 }
862 }
863 }
864
866}
867
868} // 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
void v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces) override
Reset this geometry object: unset the current state, zero Geometry::m_coeffs and remove allocated Geo...
GeomFactorsUniquePtr v_GenGeomFactors(LibUtilities::PointsKeyVector &keyTgt) override
Used by Expansion to generate associated GeomFactors.
static const unsigned int EdgeFaceConnectivity[9][2]
Definition PrismGeom.h:131
int v_GetVertexFaceMap(const int i, const int j) const override
Returns the standard element face IDs that are connected to a given vertex.
void SetUpXmap()
Set up the m_xmap object by determining the order of each direction from derived faces.
int v_GetDir(const int faceidx, const int facedir) const override
Returns the element coordinate direction corresponding to a given face coordinate direction.
Definition PrismGeom.cpp:80
void v_FillGeom() override
Put all quadrature information into face/edge structure and backward transform.
GeomType v_CalcGeomType() override
Definition PrismGeom.cpp:96
std::array< PointGeom *, kNverts > m_verts
Definition PrismGeom.h:116
static const unsigned int EdgeNormalToFaceVert[5][4]
Definition PrismGeom.h:132
int v_GetEdgeFaceMap(const int i, const int j) const override
Returns the standard element edge IDs that are connected to a given face.
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.
static const unsigned int VertexFaceConnectivity[6][3]
Definition PrismGeom.h:130
std::array< Geometry2D *, kNfaces > m_faces
Definition PrismGeom.h:118
std::array< StdRegions::Orientation, kNedges > m_eorient
Definition PrismGeom.h:119
std::array< StdRegions::Orientation, kNfaces > m_forient
Definition PrismGeom.h:120
static const unsigned int VertexEdgeConnectivity[6][3]
Definition PrismGeom.h:129
std::array< SegGeom *, kNedges > m_edges
Definition PrismGeom.h:117
int v_GetVertexEdgeMap(const int i, const int j) const override
Returns the standard element edge IDs that are connected to a given vertex.
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
@ eModified_B
Principle Modified Functions .
Definition BasisType.h:49
@ eModified_A
Principle Modified Functions .
Definition BasisType.h:48
static const NekDouble kNekZeroTol
unique_ptr_objpool< GeomFactors > GeomFactorsUniquePtr
Definition Geometry.h:62
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.
XmapFactory< StdRegions::StdPrismExp, 3 > & GetStdPrismFactory()
Definition PrismGeom.cpp:55
@ ePtsFilled
Geometric information has been generated.
scalarT< T > sqrt(scalarT< T > in)
Definition scalar.hpp:290