Nektar++
ProcessEquiSpacedOutput.cpp
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////////////
2//
3// File: ProcessEquiSpacedOutput.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: Set up fields as interpolation to equispaced output
32//
33////////////////////////////////////////////////////////////////////////////////
34#include <iostream>
35#include <string>
36using namespace std;
37
38#include <boost/core/ignore_unused.hpp>
39#include <boost/math/special_functions/fpclassify.hpp>
40
45
47
48namespace Nektar
49{
50namespace FieldUtils
51{
52
55 ModuleKey(eProcessModule, "equispacedoutput"),
57 "Write data as equi-spaced output using simplices to represent the "
58 "data for connecting points");
59
61 : ProcessModule(f)
62{
63 m_config["tetonly"] =
64 ConfigOption(true, "0", "Only process tetrahedral elements");
65
66 m_config["modalenergy"] =
67 ConfigOption(true, "0", "Write output as modal energy");
68}
69
71{
72}
73
74void ProcessEquiSpacedOutput::v_Process(po::variables_map &vm)
75{
76 m_f->SetUpExp(vm);
77
78 int nel = m_f->m_exp[0]->GetExpSize();
79 if (!nel)
80 {
81 // Create empty PtsField
82 int nfields = m_f->m_variables.size();
83 int coordim = 3;
84
85 Array<OneD, Array<OneD, NekDouble>> pts(nfields + coordim);
86 for (int i = 0; i < nfields + coordim; ++i)
87 {
88 pts[i] = Array<OneD, NekDouble>(0);
89 }
90 vector<Array<OneD, int>> ptsConn;
91
92 m_f->m_fieldPts =
94 coordim, m_f->m_variables, pts);
95 m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTetBlock);
96 m_f->m_fieldPts->SetConnectivity(ptsConn);
97 return;
98 }
99
100 int coordim = m_f->m_exp[0]->GetCoordim(0);
101 int shapedim = m_f->m_exp[0]->GetExp(0)->GetShapeDimension();
102 int npts = m_f->m_exp[0]->GetTotPoints();
104
105 // Check if we have a homogeneous expansion
106 bool homogeneous1D = false;
107 if (m_f->m_numHomogeneousDir == 1)
108 {
109 coordim++;
110 shapedim++;
111 homogeneous1D = true;
112 }
113 else if (m_f->m_numHomogeneousDir == 2)
114 {
115 ASSERTL0(false, "Homegeneous2D case not supported");
116 }
117
118 // set up the number of points in each element
119 int newpoints = 0;
120 int newtotpoints = 0;
121
122 Array<OneD, int> conn;
123 int prevNcoeffs = 0;
124 int prevNpoints = 0;
125 int cnt = 0;
126
127 // identify face 1 connectivity for prisms
128 map<int, StdRegions::Orientation> face0orient;
129 set<int> prismorient;
131
132 // prepare PtsField
133 vector<int> ppe;
134 vector<Array<OneD, int>> ptsConn;
135 int nfields;
136
137 for (int i = 0; i < nel; ++i)
138 {
139 e = m_f->m_exp[0]->GetExp(i);
140 if (e->DetShapeType() == LibUtilities::ePrism)
141 {
142 StdRegions::Orientation forient = e->GetTraceOrient(0);
143 int fid = e->GetGeom()->GetFid(0);
144 if (face0orient.count(fid))
145 { // face 1 meeting face 1 so reverse this id
146 prismorient.insert(i);
147 }
148 else
149 {
150 // just store if Dir 1 is fwd or bwd
151 if ((forient == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
155 {
156 face0orient[fid] = StdRegions::eBwd;
157 }
158 else
159 {
160 face0orient[fid] = StdRegions::eFwd;
161 }
162 }
163 }
164 }
165
166 for (int i = 0; i < nel; ++i)
167 {
168 e = m_f->m_exp[0]->GetExp(i);
169 if (e->DetShapeType() == LibUtilities::ePrism)
170 {
171 int fid = e->GetGeom()->GetFid(2);
172 // check to see if face 2 meets face 1
173 if (face0orient.count(fid))
174 {
175 // check to see how face 2 is orientated
176 StdRegions::Orientation forient2 = e->GetTraceOrient(2);
177 StdRegions::Orientation forient0 = face0orient[fid];
178
179 // If dir 1 or forient2 is bwd then check agains
180 // face 1 value
181 if ((forient2 == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
185 {
186 if (forient0 == StdRegions::eFwd)
187 {
188 prismorient.insert(i);
189 }
190 }
191 else
192 {
193 if (forient0 == StdRegions::eBwd)
194 {
195 prismorient.insert(i);
196 }
197 }
198 }
199 }
200 }
201
202 for (int i = 0; i < nel; ++i)
203 {
204 e = m_f->m_exp[0]->GetExp(i);
205 if (m_config["tetonly"].m_beenSet && m_config["tetonly"].as<bool>())
206 {
207 if (m_f->m_exp[0]->GetExp(i)->DetShapeType() !=
209 {
210 continue;
211 }
212 }
213
214 switch (e->DetShapeType())
215 {
217 {
218 int npoints0 = e->GetBasis(0)->GetNumPoints();
219
220 newpoints =
222 }
223 break;
225 {
226 int np0 = e->GetBasis(0)->GetNumPoints();
227 int np1 = e->GetBasis(1)->GetNumPoints();
228 int np = max(np0, np1);
229 newpoints =
231 }
232 break;
234 {
235 int np0 = e->GetBasis(0)->GetNumPoints();
236 int np1 = e->GetBasis(1)->GetNumPoints();
237 int np = max(np0, np1);
238
239 newpoints =
241 }
242 break;
244 {
245 int np0 = e->GetBasis(0)->GetNumPoints();
246 int np1 = e->GetBasis(1)->GetNumPoints();
247 int np2 = e->GetBasis(2)->GetNumPoints();
248 int np = max(np0, max(np1, np2));
249
251 np, np, np);
252 }
253 break;
255 {
256 int np0 = e->GetBasis(0)->GetNumPoints();
257 int np1 = e->GetBasis(1)->GetNumPoints();
258 int np2 = e->GetBasis(2)->GetNumPoints();
259 int np = max(np0, max(np1, np2));
260
262 np, np, np);
263 }
264 break;
266 {
267 int np0 = e->GetBasis(0)->GetNumPoints();
268 int np1 = e->GetBasis(1)->GetNumPoints();
269 int np2 = e->GetBasis(2)->GetNumPoints();
270 int np = max(np0, max(np1, np2));
271
273 np, np, np);
274 }
275 break;
277 {
278 int np0 = e->GetBasis(0)->GetNumPoints();
279 int np1 = e->GetBasis(1)->GetNumPoints();
280 int np2 = e->GetBasis(2)->GetNumPoints();
281 int np = max(np0, max(np1, np2));
282
284 np, np, np);
285 }
286 break;
287 default:
288 {
289 ASSERTL0(false, "Points not known");
290 }
291 }
292
293 ppe.push_back(newpoints);
294 newtotpoints += newpoints;
295
296 if (e->DetShapeType() == LibUtilities::ePrism)
297 {
298 bool standard = true;
299
300 if (prismorient.count(i))
301 {
302 standard = false; // reverse direction
303 }
304
305 e->GetSimplexEquiSpacedConnectivity(conn, standard);
306 }
307 else
308 {
309
310 if ((prevNcoeffs != e->GetNcoeffs()) ||
311 (prevNpoints != e->GetTotPoints()))
312 {
313 prevNcoeffs = e->GetNcoeffs();
314 prevNpoints = e->GetTotPoints();
315
316 e->GetSimplexEquiSpacedConnectivity(conn);
317 }
318 }
319 Array<OneD, int> newconn(conn.size());
320 for (int j = 0; j < conn.size(); ++j)
321 {
322 newconn[j] = conn[j] + cnt;
323 }
324
325 ptsConn.push_back(newconn);
326 cnt += newpoints;
327 }
328
329 nfields = m_f->m_variables.size();
330
331 Array<OneD, Array<OneD, NekDouble>> pts(nfields + coordim);
332
333 for (int i = 0; i < nfields + coordim; ++i)
334 {
335 pts[i] = Array<OneD, NekDouble>(newtotpoints);
336 }
337
338 // Interpolate coordinates
339 for (int i = 0; i < coordim; ++i)
340 {
341 coords[i] = Array<OneD, NekDouble>(npts);
342 }
343
344 for (int i = coordim; i < 3; ++i)
345 {
346 coords[i] = NullNekDouble1DArray;
347 }
348
349 m_f->m_exp[0]->GetCoords(coords[0], coords[1], coords[2]);
350
352
353 for (int n = 0; n < coordim; ++n)
354 {
355 cnt = 0;
356 int cnt1 = 0;
357 for (int i = 0; i < nel; ++i)
358 {
359 m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
360 coords[n] + cnt, tmp = pts[n] + cnt1);
361 cnt1 += ppe[i];
362 cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
363 }
364 }
365
366 for (int n = 0; n < m_f->m_variables.size(); ++n)
367 {
368 cnt = 0;
369 int cnt1 = 0;
370
371 if (m_config["modalenergy"].m_beenSet &&
372 m_config["modalenergy"].as<bool>())
373 {
374 Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
375 for (int i = 0; i < nel; ++i)
376 {
377 GenOrthoModes(i, phys + cnt, tmp = pts[coordim + n] + cnt1);
378 cnt1 += ppe[i];
379 cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
380 }
381 }
382 else
383 {
384 Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
385 for (int i = 0; i < nel; ++i)
386 {
387 m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
388 phys + cnt, tmp = pts[coordim + n] + cnt1);
389 cnt1 += ppe[i];
390 cnt += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
391 }
392 }
393 }
394
396 coordim, m_f->m_variables, pts);
397 if (shapedim == 1)
398 {
399 m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsSegBlock);
400 }
401
402 if (shapedim == 2)
403 {
404 m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTriBlock);
405 }
406 else if (shapedim == 3)
407 {
408 m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTetBlock);
409 }
410 m_f->m_fieldPts->SetConnectivity(ptsConn);
411 if (homogeneous1D)
412 {
414 }
415
416 // Save points per element in the point field
417 m_f->m_fieldPts->SetPointsPerElement(ppe);
418
419 // Clear m_exp
420 m_f->m_exp = vector<MultiRegions::ExpListSharedPtr>();
421}
422
424{
426 int nel = m_f->m_exp[0]->GetPlane(0)->GetExpSize();
427 int nPlanes = m_f->m_exp[0]->GetZIDs().size();
428 int npts = m_f->m_fieldPts->GetNpoints();
429 int nptsPerPlane = npts / nPlanes;
430 int coordim = 3;
431
432 if (m_f->m_exp[0]->GetHomogeneousBasis()->GetBasisType() ==
434 m_f->m_exp[0]->GetHomogeneousBasis()->GetPointsType() ==
436 {
437 // Write points with extra plane
439 m_f->m_fieldPts->GetPts(pts);
440 Array<OneD, Array<OneD, NekDouble>> newPts(pts.size());
441 for (int i = 0; i < pts.size(); i++)
442 {
443 newPts[i] = Array<OneD, NekDouble>(npts + nptsPerPlane);
444 // Copy old points
445 Vmath::Vcopy(npts, pts[i], 1, newPts[i], 1);
446 // Get new plane
447 Array<OneD, NekDouble> extraPlane(nptsPerPlane, newPts[i] + npts);
448 if (m_f->m_comm->GetColumnComm()->GetSize() == 1)
449 {
450 if (i == (coordim - 1))
451 {
452 // z-coordinate
453 Vmath::Sadd(nptsPerPlane, m_f->m_exp[0]->GetHomoLen(),
454 pts[i], 1, extraPlane, 1);
455 }
456 else
457 {
458 Vmath::Vcopy(nptsPerPlane, pts[i], 1, extraPlane, 1);
459 }
460 }
461 else
462 {
463 // Determine to and from rank for communication
464 int size = m_f->m_comm->GetColumnComm()->GetSize();
465 int rank = m_f->m_comm->GetColumnComm()->GetRank();
466 int fromRank = (rank + 1) % size;
467 int toRank = (rank == 0) ? size - 1 : rank - 1;
468 // Communicate using SendRecv
469 Array<OneD, NekDouble> send(nptsPerPlane, pts[i]);
470 m_f->m_comm->GetColumnComm()->SendRecv(toRank, send, fromRank,
471 extraPlane);
472 // Adjust z-coordinate of last process
473 if (i == (coordim - 1) && (rank == size - 1))
474 {
475 Vmath::Sadd(nptsPerPlane, m_f->m_exp[0]->GetHomoLen(),
476 extraPlane, 1, extraPlane, 1);
477 }
478 }
479 }
480 m_f->m_fieldPts->SetPts(newPts);
481 // Now extend plane connectivity
482 vector<Array<OneD, int>> oldConn;
483 Array<OneD, int> conn;
484 m_f->m_fieldPts->GetConnectivity(oldConn);
485 vector<Array<OneD, int>> newConn = oldConn;
486 int connPerPlane = oldConn.size() / nPlanes;
487 for (int i = 0; i < connPerPlane; i++)
488 {
489 conn = Array<OneD, int>(oldConn[i].size());
490 for (int j = 0; j < conn.size(); j++)
491 {
492 conn[j] = oldConn[i][j] + npts;
493 }
494 newConn.push_back(conn);
495 }
496 m_f->m_fieldPts->SetConnectivity(newConn);
497
498 nPlanes++;
499 npts += nptsPerPlane;
500 }
501
502 vector<Array<OneD, int>> oldConn;
503 vector<Array<OneD, int>> newConn;
504 Array<OneD, int> conn;
505 m_f->m_fieldPts->GetConnectivity(oldConn);
506
507 // 2DH1D case
508 if (m_f->m_fieldPts->GetPtsType() == LibUtilities::ePtsTriBlock)
509 {
510 for (int i = 0; i < nel; ++i)
511 {
512 int nLines = oldConn[i].size() / 2;
513 // Create array for new connectivity
514 // (2 triangles between each plane for each line)
515 conn = Array<OneD, int>(2 * 3 * nLines * (nPlanes - 1));
516 int cnt = 0;
517 for (int n = 0; n < nLines; n++)
518 {
519 // Define new connectivity with triangles
520 for (int p = 0; p < nPlanes - 1; p++)
521 {
522 conn[cnt++] = oldConn[i + p * nel][2 * n + 0];
523 conn[cnt++] = oldConn[i + p * nel][2 * n + 1];
524 conn[cnt++] = oldConn[i + (p + 1) * nel][2 * n + 0];
525
526 conn[cnt++] = oldConn[i + p * nel][2 * n + 1];
527 conn[cnt++] = oldConn[i + (p + 1) * nel][2 * n + 0];
528 conn[cnt++] = oldConn[i + (p + 1) * nel][2 * n + 1];
529 }
530 }
531 newConn.push_back(conn);
532 }
533 }
534 else if (m_f->m_fieldPts->GetPtsType() == LibUtilities::ePtsTetBlock)
535 {
536 // Get maximum number of points per direction in the mesh
537 int maxN = 0;
538 for (int i = 0; i < nel; ++i)
539 {
540 e = m_f->m_exp[0]->GetPlane(0)->GetExp(i);
541
542 int np0 = e->GetBasis(0)->GetNumPoints();
543 int np1 = e->GetBasis(1)->GetNumPoints();
544 int np = max(np0, np1);
545 maxN = max(np, maxN);
546 }
547
548 // Create a global numbering for points in plane 0
549 Array<OneD, int> vId(nptsPerPlane);
550 int cnt1 = 0;
551 int cnt2 = 0;
552 for (int i = 0; i < nel; ++i)
553 {
554 e = m_f->m_exp[0]->GetPlane(0)->GetExp(i);
555 int np0 = e->GetBasis(0)->GetNumPoints();
556 int np1 = e->GetBasis(1)->GetNumPoints();
557 int np = max(np0, np1);
558 switch (e->DetShapeType())
559 {
561 {
562 int newpoints =
564 np);
565
566 // Vertex numbering
567 vId[cnt1] = e->GetGeom()->GetVid(0);
568 vId[cnt1 + np - 1] = e->GetGeom()->GetVid(1);
569 vId[cnt1 + newpoints - 1] = e->GetGeom()->GetVid(2);
570
571 // Edge numbering
572 StdRegions::Orientation edgeOrient;
573 int edge1 = 0;
574 int edge2 = 0;
575 for (int n = 1; n < np - 1; n++)
576 {
577 // Edge 0
578 edgeOrient = e->GetGeom()->GetEorient(0);
579 if (edgeOrient == StdRegions::eForwards)
580 {
581 vId[cnt1 + n] =
582 4 * nel + maxN * e->GetGeom()->GetEid(0) + n;
583 }
584 else
585 {
586 vId[cnt1 + np - 1 - n] =
587 4 * nel + maxN * e->GetGeom()->GetEid(0) + n;
588 }
589
590 // Edge 1
591 edgeOrient = e->GetGeom()->GetEorient(1);
592 if (edgeOrient == StdRegions::eForwards)
593 {
594 edge1 += np - n;
595 vId[cnt1 + np - 1 + edge1] =
596 4 * nel + maxN * e->GetGeom()->GetEid(1) + n;
597 }
598 else
599 {
600 edge1 += n;
601 vId[cnt1 + newpoints - 1 - edge1] =
602 4 * nel + maxN * e->GetGeom()->GetEid(1) + n;
603 }
604
605 // Edge 2
606 edgeOrient = e->GetGeom()->GetEorient(2);
607 if (edgeOrient == StdRegions::eForwards)
608 {
609 edge2 += n + 1;
610 vId[cnt1 + newpoints - 1 - edge2] =
611 4 * nel + maxN * e->GetGeom()->GetEid(2) + n;
612 }
613 else
614 {
615 edge2 += np + 1 - n;
616 vId[cnt1 + edge2] =
617 4 * nel + maxN * e->GetGeom()->GetEid(2) + n;
618 }
619 }
620
621 // Interior numbering
622 edge2 = 0;
623 for (int n = 1; n < np - 1; n++)
624 {
625 edge2 += np + 1 - n;
626 for (int m = 1; m < np - n - 1; m++)
627 {
628 vId[cnt1 + edge2 + m] =
629 4 * nel + maxN * 4 * nel + cnt2;
630 cnt2++;
631 }
632 }
633 cnt1 += newpoints;
634 }
635 break;
637 {
638 int newpoints =
640 np);
641 // Vertex numbering
642 vId[cnt1] = e->GetGeom()->GetVid(0);
643 vId[cnt1 + np - 1] = e->GetGeom()->GetVid(1);
644 vId[cnt1 + np * np - 1] = e->GetGeom()->GetVid(2);
645 vId[cnt1 + np * (np - 1)] = e->GetGeom()->GetVid(3);
646
647 // Edge numbering
648 StdRegions::Orientation edgeOrient;
649 for (int n = 1; n < np - 1; n++)
650 {
651 // Edge 0
652 edgeOrient = e->GetGeom()->GetEorient(0);
653 if (edgeOrient == StdRegions::eForwards)
654 {
655 vId[cnt1 + n] =
656 4 * nel + maxN * e->GetGeom()->GetEid(0) + n;
657 }
658 else
659 {
660 vId[cnt1 + np - 1 - n] =
661 4 * nel + maxN * e->GetGeom()->GetEid(0) + n;
662 }
663
664 // Edge 1
665 edgeOrient = e->GetGeom()->GetEorient(1);
666 if (edgeOrient == StdRegions::eForwards)
667 {
668 vId[cnt1 + np - 1 + n * np] =
669 4 * nel + maxN * e->GetGeom()->GetEid(1) + n;
670 }
671 else
672 {
673 vId[cnt1 + np * np - 1 - n * np] =
674 4 * nel + maxN * e->GetGeom()->GetEid(1) + n;
675 }
676
677 // Edge 2
678 edgeOrient = e->GetGeom()->GetEorient(2);
679 if (edgeOrient == StdRegions::eForwards)
680 {
681 vId[cnt1 + np * np - 1 - n] =
682 4 * nel + maxN * e->GetGeom()->GetEid(2) + n;
683 }
684 else
685 {
686 vId[cnt1 + np * (np - 1) + n] =
687 4 * nel + maxN * e->GetGeom()->GetEid(2) + n;
688 }
689
690 // Edge 3
691 edgeOrient = e->GetGeom()->GetEorient(3);
692 if (edgeOrient == StdRegions::eForwards)
693 {
694 vId[cnt1 + np * (np - 1) - n * np] =
695 4 * nel + maxN * e->GetGeom()->GetEid(3) + n;
696 }
697 else
698 {
699 vId[cnt1 + n * np] =
700 4 * nel + maxN * e->GetGeom()->GetEid(3) + n;
701 }
702 }
703
704 // Interior numbering
705 for (int n = 1; n < np - 1; n++)
706 {
707 for (int m = 1; m < np - 1; m++)
708 {
709 vId[cnt1 + m * np + n] =
710 4 * nel + maxN * 4 * nel + cnt2;
711 cnt2++;
712 }
713 }
714 cnt1 += newpoints;
715 }
716 break;
717 default:
718 {
719 ASSERTL0(false, "Points not known");
720 }
721 }
722 }
723
724 // Crete new connectivity using homogeneous information
725 for (int i = 0; i < nel; ++i)
726 {
727 int nTris = oldConn[i].size() / 3;
728 // Create array for new connectivity
729 // (3 tetrahedra between each plane for each triangle)
730 conn = Array<OneD, int>(4 * 3 * nTris * (nPlanes - 1));
731 cnt2 = 0;
732 for (int n = 0; n < nTris; n++)
733 {
734 // Get id of vertices in this triangle (on plane 0)
735 int vId0 = vId[oldConn[i][3 * n + 0]];
736 int vId1 = vId[oldConn[i][3 * n + 1]];
737 int vId2 = vId[oldConn[i][3 * n + 2]];
738
739 // Determine ordering based on global Id of pts
740 Array<OneD, int> rot(3);
741 if ((vId0 < vId1) && (vId0 < vId2))
742 {
743 rot[0] = 0;
744 if (vId1 < vId2)
745 {
746 rot[1] = 1;
747 rot[2] = 2;
748 }
749 else
750 {
751 rot[1] = 2;
752 rot[2] = 1;
753 }
754 }
755 else if ((vId1 < vId0) && (vId1 < vId2))
756 {
757 rot[0] = 1;
758 if (vId0 < vId2)
759 {
760 rot[1] = 0;
761 rot[2] = 2;
762 }
763 else
764 {
765 rot[1] = 2;
766 rot[2] = 0;
767 }
768 }
769 else
770 {
771 rot[0] = 2;
772 if (vId0 < vId1)
773 {
774 rot[1] = 0;
775 rot[2] = 1;
776 }
777 else
778 {
779 rot[1] = 1;
780 rot[2] = 0;
781 }
782 }
783
784 // Define new connectivity with tetrahedra
785 for (int p = 0; p < nPlanes - 1; p++)
786 {
787 conn[cnt2++] = oldConn[i + p * nel][3 * n + rot[0]];
788 conn[cnt2++] = oldConn[i + p * nel][3 * n + rot[1]];
789 conn[cnt2++] = oldConn[i + p * nel][3 * n + rot[2]];
790 conn[cnt2++] = oldConn[i + (p + 1) * nel][3 * n + rot[2]];
791
792 conn[cnt2++] = oldConn[i + p * nel][3 * n + rot[0]];
793 conn[cnt2++] = oldConn[i + p * nel][3 * n + rot[1]];
794 conn[cnt2++] = oldConn[i + (p + 1) * nel][3 * n + rot[2]];
795 conn[cnt2++] = oldConn[i + (p + 1) * nel][3 * n + rot[1]];
796
797 conn[cnt2++] = oldConn[i + p * nel][3 * n + rot[0]];
798 conn[cnt2++] = oldConn[i + (p + 1) * nel][3 * n + rot[1]];
799 conn[cnt2++] = oldConn[i + (p + 1) * nel][3 * n + rot[2]];
800 conn[cnt2++] = oldConn[i + (p + 1) * nel][3 * n + rot[0]];
801 }
802 }
803 newConn.push_back(conn);
804 }
805 }
806 else
807 {
808 ASSERTL0(false, "Points type not supported.");
809 }
810
811 m_f->m_fieldPts->SetConnectivity(newConn);
812}
813
815 int n, const Array<OneD, const NekDouble> &phys,
817{
819 e = m_f->m_exp[0]->GetExp(n);
820
821 switch (e->DetShapeType())
822 {
824 {
825 int np0 = e->GetBasis(0)->GetNumPoints();
826 int np1 = e->GetBasis(1)->GetNumPoints();
827 int np = max(np0, np1);
828
829 // to ensure points are correctly projected to np need
830 // to increase the order slightly of coordinates
831 LibUtilities::PointsKey pa(np + 1, e->GetPointsType(0));
832 LibUtilities::PointsKey pb(np, e->GetPointsType(1));
833 Array<OneD, NekDouble> tophys(np * (np + 1));
834
837 StdRegions::StdTriExp OrthoExp(Ba, Bb);
838
839 // interpolate points to new phys points!
840 LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(),
841 e->GetBasis(1)->GetBasisKey(), phys, Ba, Bb,
842 tophys);
843
844 OrthoExp.FwdTrans(tophys, coeffs);
845 break;
846 }
848 {
849 int np0 = e->GetBasis(0)->GetNumPoints();
850 int np1 = e->GetBasis(1)->GetNumPoints();
851 int np = max(np0, np1);
852
853 LibUtilities::PointsKey pa(np + 1, e->GetPointsType(0));
854 LibUtilities::PointsKey pb(np + 1, e->GetPointsType(1));
855 Array<OneD, NekDouble> tophys((np + 1) * (np + 1));
856
859 StdRegions::StdQuadExp OrthoExp(Ba, Bb);
860
861 // interpolate points to new phys points!
862 LibUtilities::Interp2D(e->GetBasis(0)->GetBasisKey(),
863 e->GetBasis(1)->GetBasisKey(), phys, Ba, Bb,
864 tophys);
865
866 OrthoExp.FwdTrans(phys, coeffs);
867 break;
868 }
869 default:
870 ASSERTL0(false, "Shape needs setting up");
871 break;
872 }
873}
874} // namespace FieldUtils
875} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
FieldSharedPtr m_f
Field object.
Definition: Module.h:234
std::map< std::string, ConfigOption > m_config
List of configuration values.
Definition: Module.h:263
virtual void v_Process(po::variables_map &vm) override
Write mesh to output file.
static std::shared_ptr< Module > create(FieldSharedPtr f)
Creates an instance of this class.
void GenOrthoModes(int n, const Array< OneD, const NekDouble > &phys, Array< OneD, NekDouble > &coeffs)
Abstract base class for processing modules.
Definition: Module.h:292
Describes the specification for a Basis.
Definition: Basis.h:47
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
Defines a specification for a set of points.
Definition: Points.h:55
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
void FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function performs the Forward transformation from physical space to coefficient space.
std::shared_ptr< Field > FieldSharedPtr
Definition: Field.hpp:991
std::pair< ModuleType, std::string > ModuleKey
Definition: Module.h:317
ModuleFactory & GetModuleFactory()
Definition: Module.cpp:49
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:158
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:284
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:237
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:138
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:192
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:114
void Interp2D(const BasisKey &fbasis0, const BasisKey &fbasis1, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, Array< OneD, NekDouble > &to)
this function interpolates a 2D function evaluated at the quadrature points of the 2D basis,...
Definition: Interp.cpp:103
@ eFourierEvenlySpaced
1D Evenly-spaced points using Fourier Fit
Definition: PointsType.h:76
@ eOrtho_A
Principle Orthogonal Functions .
Definition: BasisType.h:44
@ eOrtho_B
Principle Orthogonal Functions .
Definition: BasisType.h:46
@ eFourier
Fourier Expansion .
Definition: BasisType.h:57
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:68
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
static Array< OneD, NekDouble > NullNekDouble1DArray
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add scalar y = alpha + x.
Definition: Vmath.cpp:379
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1191
Represents a command-line configuration option.
Definition: Module.h:131