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