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