Nektar++
Loading...
Searching...
No Matches
LocTraceToTraceMap.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: LocTraceToTraceMap.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: Local trace to general trace mapping information
32//
33///////////////////////////////////////////////////////////////////////////////
34
44
45using namespace std;
46
48{
49
53
54/**
55 * @brief Set up trace to trace mapping components.
56 *
57 * @param locExp Expansion list of full dimension problem.
58 * @param trace Expansion list of one dimension lower trace.
59 * @param elmtToTrace Mapping from elemental facets to trace.
60 * @param leftAdjacents Vector of bools denoting forwards-oriented traces.
61 *
62 * @todo Add 1D support
63 */
65 const ExpList &locExp, const ExpListSharedPtr &trace,
67 &elmtToTrace,
68 const vector<bool> &LeftAdjacents)
69{
70 const std::shared_ptr<LocalRegions::ExpansionVector> exp = locExp.GetExp();
71 // Assume that all the elements have same dimension
72 m_expdim = (*exp)[0]->GetShapeDimension();
73
82
83 if (m_expdim == 3)
84 {
88 }
89
93
95
96 int cnt, n, e, phys_offset;
97
98 int nexp = exp->size();
99 m_nTracePts = trace->GetTotPoints();
100
101 // Count number of traces and points required for maps
102 int nFwdPts = 0;
103 int nBwdPts = 0;
104 int nFwdCoeffs = 0;
105 int nBwdCoeffs = 0;
106 int nLocTraces = 0; // num of total local traces
108 m_nLocTracePts = 0;
109
110 for (cnt = n = 0; n < nexp; ++n)
111 {
112 elmt = (*exp)[n];
113
114 for (int i = 0; i < elmt->GetNtraces(); ++i, ++cnt)
115 {
116 int nLocPts = elmt->GetTraceNumPoints(i);
117 m_nLocTracePts += nLocPts;
118 nLocTraces++;
119
120 if (LeftAdjacents[cnt])
121 {
122 nFwdPts += elmtToTrace[n][i]->GetTotPoints();
123 nFwdCoeffs += elmtToTrace[n][i]->GetNcoeffs();
124 m_nFwdLocTracePts += nLocPts;
125 }
126 else
127 {
128 nBwdPts += elmtToTrace[n][i]->GetTotPoints();
129 nBwdCoeffs += elmtToTrace[n][i]->GetNcoeffs();
130 }
131 }
132 }
133
135
139
142
143 m_nTraceCoeffs[0] = nFwdCoeffs;
144 m_nTraceCoeffs[1] = nBwdCoeffs;
145
146 m_traceCoeffsToElmtMap[0] = Array<OneD, int>(nFwdCoeffs + nBwdCoeffs);
148 m_traceCoeffsToElmtTrace[0] = Array<OneD, int>(nFwdCoeffs + nBwdCoeffs);
150 m_traceCoeffsToElmtSign[0] = Array<OneD, int>(nFwdCoeffs + nBwdCoeffs);
152
153 //------ new entry variables ----------
158
159 // size of total loc traces
161
162 // Gather information about trace interpolations
163 map<TraceInterpPoints, vector<pair<int, int>>, cmpop> TraceInterpMap;
164
165 vector<vector<int>> TraceOrder;
166 TraceOrder.resize(nexp);
167 vector<vector<int>> ElmtPhysTraceOffset;
168 ElmtPhysTraceOffset.resize(nexp);
169 int ntrace;
170 int fwdcnt = 0;
171 int bwdcnt = 0;
172 int neoffset = 0;
173 // Generate a map of similar traces with the same
174 // interpolation requirements
175
176 for (cnt = n = 0; n < nexp; ++n)
177 {
178 elmt = (*exp)[n];
179 ntrace = elmt->GetNtraces();
180 TraceOrder[n].resize(ntrace);
181 ElmtPhysTraceOffset[n].resize(ntrace);
182
187
188 int coeffoffset = locExp.GetCoeff_Offset(n);
189 for (e = 0; e < ntrace; ++e, ++cnt)
190 {
191 LocalRegions::ExpansionSharedPtr elmttrace = elmtToTrace[n][e];
192 StdRegions::Orientation orient = elmt->GetTraceOrient(e);
193
194 LibUtilities::PointsKey fromPointsKey0, fromPointsKey1;
195 LibUtilities::PointsKey toPointsKey0, toPointsKey1;
196 Array<OneD, int> P(2, -1);
197
198 switch (m_expdim)
199 {
200 case 1:
201 {
202 fromPointsKey0 = elmt->GetBasis(0)->GetPointsKey();
203 fromPointsKey1 =
205 // dummy info since no interpolation is required in this
206 // case.
207 toPointsKey0 =
209 toPointsKey1 =
211 }
212 break;
213 case 2:
214 {
215 int dir0 = elmt->GetGeom()->GetDir(e, 0);
216
217 fromPointsKey0 = elmt->GetBasis(dir0)->GetPointsKey();
218 fromPointsKey1 =
220
221 toPointsKey0 = elmttrace->GetBasis(0)->GetPointsKey();
222 toPointsKey1 =
224
225 P[0] = elmttrace->GetBasisNumModes(0);
226 }
227 break;
228 case 3:
229 {
230 int dir0 = elmt->GetGeom()->GetDir(e, 0);
231 int dir1 = elmt->GetGeom()->GetDir(e, 1);
232
233 fromPointsKey0 = elmt->GetBasis(dir0)->GetPointsKey();
234 fromPointsKey1 = elmt->GetBasis(dir1)->GetPointsKey();
235
237 {
238 toPointsKey0 = elmttrace->GetBasis(0)->GetPointsKey();
239 toPointsKey1 = elmttrace->GetBasis(1)->GetPointsKey();
240 P[0] = elmttrace->GetBasisNumModes(0);
241 P[1] = elmttrace->GetBasisNumModes(1);
242 }
243 else // transpose points key evaluation
244 {
245 toPointsKey0 = elmttrace->GetBasis(1)->GetPointsKey();
246 toPointsKey1 = elmttrace->GetBasis(0)->GetPointsKey();
247 P[0] = elmttrace->GetBasisNumModes(1);
248 P[1] = elmttrace->GetBasisNumModes(0);
249 }
250 }
251 break;
252 }
253
254 TraceInterpPoints fpoint(fromPointsKey0, fromPointsKey1,
255 toPointsKey0, toPointsKey1);
256
257 pair<int, int> epf(n, e);
258 TraceInterpMap[fpoint].push_back(epf);
259 TraceOrder[n][e] = cnt;
260
261 ElmtPhysTraceOffset[n][e] = neoffset;
262 neoffset += elmt->GetTraceNumPoints(e);
263
264 // Setup for coefficient mapping from trace normal flux
265 // to elements
268 // Test shows we should swap P0 and P1 before calling
269 // GetTraceToElementMap if orientation is transposed.
270 // This is contrary to ReOrientTracePhysMap
271 elmt->GetTraceToElementMap(e, map, sign, orient, P[0], P[1]);
272
273 int order_t = elmttrace->GetNcoeffs();
274 int t_offset = trace->GetCoeff_Offset(elmttrace->GetElmtId());
275
276 double fac = 1.0;
277
278 if (elmt->GetTraceExp(e)->GetRightAdjacentElementExp())
279 {
280 if (elmttrace->GetRightAdjacentElementExp()
281 ->GetGeom()
282 ->GetGlobalID() == elmt->GetGeom()->GetGlobalID())
283 {
284 fac = -1.0;
285 }
286 }
287
288 if (LeftAdjacents[cnt])
289 {
290 m_traceCoeffsEntry[n][e] = fwdcnt;
291 for (int i = 0; i < order_t; ++i)
292 {
293 m_traceCoeffsToElmtMap[0][fwdcnt] = coeffoffset + map[i];
294 m_traceCoeffsToElmtTrace[0][fwdcnt] = t_offset + i;
295 m_traceCoeffsToElmtSign[0][fwdcnt++] = fac * sign[i];
296 }
297 }
298 else
299 {
300 m_traceCoeffsEntry[n][e] = nFwdCoeffs + bwdcnt;
301 for (int i = 0; i < order_t; ++i)
302 {
303 m_traceCoeffsToElmtMap[1][bwdcnt] = coeffoffset + map[i];
304 m_traceCoeffsToElmtTrace[1][bwdcnt] = t_offset + i;
305 m_traceCoeffsToElmtSign[1][bwdcnt++] = fac * sign[i];
306 }
307 }
308
309 // Get the start pos of this local trace in the trace phys space
311 trace->GetPhys_Offset(elmttrace->GetElmtId());
312
313 // //-----debug------
314 // if (orient>=9 || P[0]!=P[1])
315 // {
316 // int dir0 = elmt->GetGeom()->GetDir(e, 0);
317 // int dir1 = elmt->GetGeom()->GetDir(e, 1);
318 // std::cout << "n = " << n << " e = " << e
319 // << " orient =" << orient << std::endl;
320 // std::cout << " glotrace nm0, nm1 = " << P[0] << ", "<< P[1]
321 // << std::endl; std::cout << " locTrace nm0, nm1 = " <<
322 // elmt->GetBasisNumModes(dir0)
323 // << ", "<< elmt->GetBasisNumModes(dir1) << std::endl;
324 // }
325 }
326 }
327
328 int nInterpType = TraceInterpMap.size();
329
330 // need to decide on 1D case here !!!!!
331 for (int i = 0; i < 2; ++i)
332 {
338 m_interpNtraces[i] = Array<OneD, int>(nInterpType, 0);
339 }
340
341 if (m_expdim > 2)
342 {
343 for (int i = 0; i < 2; ++i)
344 {
347 m_interpEndPtI1[i] =
349 }
350 }
351
352 int ntracepts, ntracepts1;
353 int cnt1 = 0;
354 int cnt2 = 0; // counter for traces
355 int cntFwd = 0;
356 int cntBwd = 0; // counter for loc trace points
357 int cntFwd1 = 0;
358 int cntBwd1 = 0; // counter for trace points
359 int set;
360 Array<OneD, int> traceids;
361 Array<OneD, int> locTraceToTraceMap;
362 cnt = 0;
363
364 for (auto it = TraceInterpMap.begin(); it != TraceInterpMap.end();
365 ++it, ++cnt1)
366 {
367 LibUtilities::PointsKey fromPointsKey0 = std::get<0>(it->first);
368 LibUtilities::PointsKey fromPointsKey1 = std::get<1>(it->first);
369 LibUtilities::PointsKey toPointsKey0 = std::get<2>(it->first);
370 LibUtilities::PointsKey toPointsKey1 = std::get<3>(it->first);
371
372 bool fwdSet = false;
373 bool bwdSet = false;
374
375 for (int f = 0; f < it->second.size(); ++f, ++cnt2)
376 {
377 n = it->second[f].first;
378 e = it->second[f].second;
379
380 StdRegions::StdExpansionSharedPtr elmttrace = elmtToTrace[n][e];
381
382 elmt = (*exp)[n];
383 phys_offset = locExp.GetPhys_Offset(n);
384
385 // Mapping of new edge order to one that loops over elmts
386 // then set up mapping of faces in standard cartesian order
387 elmt->GetTracePhysMap(e, traceids);
388
389 ntracepts = elmt->GetTraceNumPoints(e);
390 ntracepts1 = elmttrace->GetTotPoints();
391
392 StdRegions::Orientation orient = elmt->GetTraceOrient(e);
393
394 // toPoints have already been swapped. But here we need original
395 // elmttrace points (w.r.t local axes). So swap back if orient >= 9
396 if (orient >= 9)
397 {
398 elmt->ReOrientTracePhysMap(orient, locTraceToTraceMap,
399 toPointsKey1.GetNumPoints(),
400 toPointsKey0.GetNumPoints());
401 }
402 else
403 {
404 elmt->ReOrientTracePhysMap(orient, locTraceToTraceMap,
405 toPointsKey0.GetNumPoints(),
406 toPointsKey1.GetNumPoints());
407 }
408
409 int offset = trace->GetPhys_Offset(elmtToTrace[n][e]->GetElmtId());
410
411 if (LeftAdjacents[TraceOrder[n][e]])
412 {
413 m_locTracePtsEntry[n][e] = cntFwd;
414 for (int i = 0; i < ntracepts; ++i)
415 {
416 m_locTraceToFieldMap[cntFwd + i] =
417 phys_offset + traceids[i];
418 }
419
420 for (int i = 0; i < ntracepts; ++i)
421 {
422 m_locTraceToElmtTraceMap[0][cntFwd + i] =
423 ElmtPhysTraceOffset[n][e] + i;
424 }
425
426 m_interpTracePtsEntry[n][e] = cntFwd1;
427 for (int i = 0; i < ntracepts1; ++i)
428 {
429 m_locInterpTraceToTraceMap[0][cntFwd1 + i] =
430 offset + locTraceToTraceMap[i];
431 }
432
433 cntFwd += ntracepts;
434 cntFwd1 += ntracepts1;
435 set = 0;
436 }
437 else
438 {
439 m_locTracePtsEntry[n][e] = m_nFwdLocTracePts + cntBwd;
440 for (int i = 0; i < ntracepts; ++i)
441 {
443 phys_offset + traceids[i];
444 }
445
446 for (int i = 0; i < ntracepts; ++i)
447 {
448 m_locTraceToElmtTraceMap[1][cntBwd + i] =
449 ElmtPhysTraceOffset[n][e] + i;
450 }
451
452 // it doesn't matter if it is fwd or bwd
453 m_interpTracePtsEntry[n][e] = cntBwd1;
454 for (int i = 0; i < ntracepts1; ++i)
455 {
456 m_locInterpTraceToTraceMap[1][cntBwd1 + i] =
457 offset + locTraceToTraceMap[i];
458 }
459
460 cntBwd += ntracepts;
461 cntBwd1 += ntracepts1;
462 set = 1;
463 }
464
465 m_interpNtraces[set][cnt1] += 1;
466 m_interpTraceIndex[n][e] = cnt1;
467 // For each unique interpolation type, set the interp matrix only
468 // once either for fwdSet or bwdSet
469 if ((fwdSet == false && set == 0) || (bwdSet == false && set == 1))
470 {
471 m_interpPoints[set][cnt1] = it->first;
472
473 switch (m_expdim)
474 {
475 case 1:
476 {
477 // Always no interplation in this case
478 m_interpTrace[set][cnt1] = eNoInterp;
479 }
480 break;
481 case 2:
482 {
483 if (fromPointsKey0 == toPointsKey0)
484 {
485 m_interpTrace[set][cnt1] = eNoInterp;
486 }
487 else
488 {
489 m_interpTrace[set][cnt1] = eInterpDir0;
490 m_interpTraceI0[set][cnt1] =
491 LibUtilities::PointsManager()[fromPointsKey0]
492 ->GetI(toPointsKey0);
493 m_interpFromTraceI0[set][cnt1] =
494 LibUtilities::PointsManager()[toPointsKey0]
495 ->GetI(fromPointsKey0);
496 // Check to see if we can
497 // just interpolate endpoint
498 if (fromPointsKey0.GetNumPoints() + 1 ==
499 toPointsKey0.GetNumPoints())
500 {
501 if (((fromPointsKey0.GetPointsType() ==
502 LibUtilities::eGaussRadauMAlpha1Beta0) &&
503 (toPointsKey0.GetPointsType() ==
505 ((fromPointsKey0.GetPointsType() ==
507 (toPointsKey0.GetPointsType() ==
509 {
510 m_interpTrace[set][cnt1] = eInterpEndPtDir0;
511
512 int fnp0 = fromPointsKey0.GetNumPoints();
513 int tnp0 = toPointsKey0.GetNumPoints();
514
515 m_interpEndPtI0[set][cnt1] =
517
518 Vmath::Vcopy(fnp0,
519 m_interpTraceI0[set][cnt1]
520 ->GetPtr()
521 .data() +
522 tnp0 - 1,
523 tnp0,
524 &m_interpEndPtI0[set][cnt1][0],
525 1);
526 }
527 }
528 }
529 }
530 break;
531 case 3:
532 {
533 if (fromPointsKey0 == toPointsKey0)
534 {
535 if (fromPointsKey1 == toPointsKey1)
536 {
537 m_interpTrace[set][cnt1] = eNoInterp;
538 }
539 else
540 {
541 m_interpTrace[set][cnt1] = eInterpDir1;
542 m_interpTraceI1[set][cnt1] =
544 [fromPointsKey1]
545 ->GetI(toPointsKey1);
546 m_interpFromTraceI1[set][cnt1] =
547 LibUtilities::PointsManager()[toPointsKey1]
548 ->GetI(fromPointsKey1);
549
550 // Check to see if we can just
551 // interpolate endpoint
552 if (fromPointsKey1.GetNumPoints() + 1 ==
553 toPointsKey1.GetNumPoints())
554 {
555 if (((fromPointsKey1.GetPointsType() ==
556 LibUtilities::
557 eGaussRadauMAlpha1Beta0) &&
558 (toPointsKey1.GetPointsType() ==
561 ((fromPointsKey1.GetPointsType() ==
563 (toPointsKey1.GetPointsType() ==
565 {
566 m_interpTrace[set][cnt1] =
568 int fnp1 =
569 fromPointsKey1.GetNumPoints();
570 int tnp1 = toPointsKey1.GetNumPoints();
571 m_interpEndPtI1[set][cnt1] =
574 fnp1,
575 m_interpTraceI1[set][cnt1]
576 ->GetPtr()
577 .data() +
578 tnp1 - 1,
579 tnp1,
580 &m_interpEndPtI1[set][cnt1][0], 1);
581 }
582 }
583 }
584 }
585 else
586 {
587 if (fromPointsKey1 == toPointsKey1)
588 {
589 m_interpTrace[set][cnt1] = eInterpDir0;
590 m_interpTraceI0[set][cnt1] =
592 [fromPointsKey0]
593 ->GetI(toPointsKey0);
594 m_interpFromTraceI0[set][cnt1] =
595 LibUtilities::PointsManager()[toPointsKey0]
596 ->GetI(fromPointsKey0);
597
598 // Check to see if we can just
599 // interpolate endpoint
600 if (fromPointsKey0.GetNumPoints() + 1 ==
601 toPointsKey0.GetNumPoints())
602 {
603 if (((fromPointsKey0.GetPointsType() ==
604 LibUtilities::
605 eGaussRadauMAlpha1Beta0) &&
606 (toPointsKey0.GetPointsType() ==
609 ((fromPointsKey0.GetPointsType() ==
611 (toPointsKey0.GetPointsType() ==
613 {
614 m_interpTrace[set][cnt1] =
616 int fnp0 =
617 fromPointsKey0.GetNumPoints();
618 int tnp0 = toPointsKey0.GetNumPoints();
619 m_interpEndPtI0[set][cnt1] =
622 fnp0,
623 m_interpTraceI0[set][cnt1]
624 ->GetPtr()
625 .data() +
626 tnp0 - 1,
627 tnp0,
628 &m_interpEndPtI0[set][cnt1][0], 1);
629 }
630 }
631 }
632 else
633 {
634 m_interpTrace[set][cnt1] = eInterpBothDirs;
635 m_interpTraceI0[set][cnt1] =
637 [fromPointsKey0]
638 ->GetI(toPointsKey0);
639 m_interpFromTraceI0[set][cnt1] =
640 LibUtilities::PointsManager()[toPointsKey0]
641 ->GetI(fromPointsKey0);
642 m_interpTraceI1[set][cnt1] =
644 [fromPointsKey1]
645 ->GetI(toPointsKey1);
646 m_interpFromTraceI1[set][cnt1] =
647 LibUtilities::PointsManager()[toPointsKey1]
648 ->GetI(fromPointsKey1);
649
650 // check to see if we can just
651 // interpolate endpoint
652 if (fromPointsKey0.GetNumPoints() + 1 ==
653 toPointsKey0.GetNumPoints())
654 {
655 if (((fromPointsKey0.GetPointsType() ==
656 LibUtilities::
657 eGaussRadauMAlpha1Beta0) &&
658 (toPointsKey0.GetPointsType() ==
661 ((fromPointsKey0.GetPointsType() ==
663 (toPointsKey0.GetPointsType() ==
665 {
666 m_interpTrace[set][cnt1] =
668 int fnp0 =
669 fromPointsKey0.GetNumPoints();
670 int tnp0 = toPointsKey0.GetNumPoints();
671 m_interpEndPtI0[set][cnt1] =
674 fnp0,
675 m_interpTraceI0[set][cnt1]
676 ->GetPtr()
677 .data() +
678 tnp0 - 1,
679 tnp0,
680 &m_interpEndPtI0[set][cnt1][0], 1);
681 }
682 }
683 }
684 }
685 }
686 }
687
688 if (set == 0)
689 {
690 fwdSet = true;
691 }
692 else
693 {
694 bwdSet = true;
695 }
696 }
697 }
698 }
699
700 TraceLocToElmtLocCoeffMap(locExp, trace);
701 FindElmtNeighbors(locExp, trace);
702
703 //---- Below is to construct traceFieldMap and traceInterp essential -----
704
705 auto collections = locExp.GetCollections();
706
707 m_collExpOffset = Array<OneD, int>(collections.size(), 0);
708
709 for (int cid = 1; cid < collections.size(); ++cid)
710 {
711 m_collExpOffset[cid] = m_collExpOffset[cid - 1] +
712 collections[cid - 1].GetExpVector().size();
713 }
714
717
718 // map<{shape, orient, dir, typid}, orientationid>
719 std::map<std::tuple<int, int, int, int>, int> map_locTraceToTrace;
720
721 // temporary
722 std::vector<Array<OneD, int>> orientationMaps;
723
724 int cntLocTrace = 0;
725 int elmtId = 0;
726 for (int cid = 0; cid < collections.size(); ++cid)
727 {
728 auto pCollExp = collections[cid].GetExpVector();
729 auto pGeomData = collections[cid].GetGeomSharedPtr();
730
731 auto exp =
732 std::dynamic_pointer_cast<LocalRegions::Expansion>(pCollExp[0]);
733
734 // directly assign the same name variables
735 m_traceInterp[cid].m_interpTrace = m_interpTrace;
736 m_traceInterp[cid].m_interpTraceI0 = m_interpTraceI0;
737 m_traceInterp[cid].m_interpTraceI1 = m_interpTraceI1;
738 m_traceInterp[cid].m_interpFromTraceI0 = m_interpFromTraceI0;
739 m_traceInterp[cid].m_interpFromTraceI1 = m_interpFromTraceI1;
740 m_traceInterp[cid].m_interpPoints = m_interpPoints;
741 m_traceInterp[cid].m_interpEndPtI0 = m_interpEndPtI0;
742 m_traceInterp[cid].m_interpEndPtI1 = m_interpEndPtI1;
743 m_traceInterp[cid].m_interpNtraces = m_interpNtraces;
744
745 m_traceInterp[cid].m_maxTraceSize = 1;
746 for (int dir = 0; dir < 2; ++dir)
747 {
748 for (int typid = 0; typid < m_interpPoints[dir].size(); ++typid)
749 {
750 if (m_expdim == 3)
751 {
752 int fnp0 =
753 std::get<0>(m_interpPoints[dir][typid]).GetNumPoints();
754 int fnp1 =
755 std::get<1>(m_interpPoints[dir][typid]).GetNumPoints();
756 int tnp0 =
757 std::get<2>(m_interpPoints[dir][typid]).GetNumPoints();
758 int tnp1 =
759 std::get<3>(m_interpPoints[dir][typid]).GetNumPoints();
760
761 int tmp = std::max(fnp0 * fnp1, tnp0 * tnp1);
762 m_traceInterp[cid].m_maxTraceSize =
763 std::max(tmp, m_traceInterp[cid].m_maxTraceSize);
764 }
765 else
766 {
767 int fnp0 =
768 std::get<0>(m_interpPoints[dir][typid]).GetNumPoints();
769 int tnp0 =
770 std::get<2>(m_interpPoints[dir][typid]).GetNumPoints();
771 int tmp = std::max(fnp0, tnp0);
772 m_traceInterp[cid].m_maxTraceSize =
773 std::max(tmp, m_traceInterp[cid].m_maxTraceSize);
774 }
775 }
776 }
777
778 // reshape m_interpTraceIndex of this collection from (n,e) to (e,n)
779 // and stored in m_traceInterp
780 m_traceInterp[cid].m_interpTraceIndex =
781 Array<OneD, Array<OneD, int>>(exp->GetNtraces());
782 for (int e = 0; e < exp->GetNtraces(); e++)
783 {
784 m_traceInterp[cid].m_interpTraceIndex[e] =
785 Array<OneD, int>(pCollExp.size(), 0);
786 }
787
788 // Get trace to elmt map from first exp and stored
789 m_traceFieldMap[cid].m_locTracePhysToElmtMaps =
790 Array<OneD, Array<OneD, int>>(exp->GetNtraces());
791
792 for (int e = 0; e < exp->GetNtraces(); e++)
793 {
794 exp->GetTracePhysMap(
795 e, m_traceFieldMap[cid].m_locTracePhysToElmtMaps[e]);
796 }
797
798 // Allocate memory for orientations
799 m_traceFieldMap[cid].m_orientationIds =
800 Array<OneD, Array<OneD, int>>(exp->GetNtraces());
801 for (int e = 0; e < exp->GetNtraces(); e++)
802 {
803 m_traceFieldMap[cid].m_orientationIds[e] =
804 Array<OneD, int>(pCollExp.size(), 0);
805 }
806
807 // allocate memory for locToTraceId
808 m_traceFieldMap[cid].m_locToTraceId =
809 Array<OneD, Array<OneD, int>>(exp->GetNtraces());
810 for (int e = 0; e < exp->GetNtraces(); e++)
811 {
812 m_traceFieldMap[cid].m_locToTraceId[e] =
813 Array<OneD, int>(pCollExp.size(), 0);
814 }
815 // clear the maps : so each collection has its own maps
816 // However, even if we disable this, things won't go wrong
817 // Just have bigger arrays storing redundant data
818 orientationMaps.clear();
819 map_locTraceToTrace.clear();
820
821 int cntCollLocTrace = 0;
822 for (int n = 0; n < pCollExp.size(); n++, elmtId++)
823 {
824 auto locExp =
825 std::dynamic_pointer_cast<LocalRegions::Expansion>(pCollExp[n]);
826 for (int e = 0; e < locExp->GetNtraces(); e++, cntCollLocTrace++)
827 {
828 int dir = 0;
829 if (!LeftAdjacents[cntLocTrace + cntCollLocTrace])
830 {
831 dir = 1;
832 }
833 int typid = m_interpTraceIndex[elmtId][e];
834 int orient = static_cast<int>(locExp->GetTraceOrient(e));
835 int shape = 0;
836 switch (locExp->GetShapeDimension())
837 {
838 case 1:
839 shape = static_cast<int>(LibUtilities::ePoint);
840 break;
841 case 2:
842 shape = static_cast<int>(
843 locExp->GetGeom()->GetEdge(e)->GetShapeType());
844 break;
845 case 3:
846 shape = static_cast<int>(
847 locExp->GetGeom()->GetFace(e)->GetShapeType());
848 break;
849 }
850 auto thisKey =
851 std::tuple<int, int, int, int>{shape, orient, dir, typid};
852 if (map_locTraceToTrace.find(thisKey) ==
853 map_locTraceToTrace.end())
854 {
855 // insert new item
856 Array<OneD, int> thisMapArray;
857 auto tnp0 =
858 std::get<2>(m_interpPoints[dir][typid]).GetNumPoints();
859 auto tnp1 =
860 std::get<3>(m_interpPoints[dir][typid]).GetNumPoints();
861 exp->ReOrientTracePhysMap(locExp->GetTraceOrient(e),
862 thisMapArray, tnp0, tnp1);
863 orientationMaps.push_back(thisMapArray);
864 m_traceFieldMap[cid].m_orientationIds[e][n] =
865 orientationMaps.size() - 1;
866 map_locTraceToTrace[thisKey] = orientationMaps.size() - 1;
867 }
868 else // already exist
869 {
870 m_traceFieldMap[cid].m_orientationIds[e][n] =
871 map_locTraceToTrace[thisKey];
872 }
873
874 std::array<LibUtilities::BasisKey, 3> thisExpKeys{
877
878 m_traceInterp[cid].m_interpTraceIndex[e][n] =
879 m_interpTraceIndex[elmtId][e];
880 m_traceFieldMap[cid].m_locToTraceId[e][n] =
881 elmtToTrace[elmtId][e]->GetElmtId();
882 }
883 }
884
885 // copy orientationMaps to m_traceFieldMap[cid] because orientationMaps
886 // are std::vector
887 m_traceFieldMap[cid].m_orientationMaps =
888 Array<OneD, Array<OneD, int>>(orientationMaps.size());
889 for (int i = 0; i < orientationMaps.size(); ++i)
890 {
891 m_traceFieldMap[cid].m_orientationMaps[i] = orientationMaps[i];
892 }
893
894 // reshape LeftAdjacents from (n,e) to (e,n) and copy to
895 // m_traceFieldMap[cid].m_isLocTraceLeftAdjacent
896 m_traceFieldMap[cid].m_isLocTraceLeftAdjacent =
897 Array<OneD, Array<OneD, bool>>(exp->GetNtraces());
898 for (int e = 0; e < exp->GetNtraces(); e++)
899 {
900 m_traceFieldMap[cid].m_isLocTraceLeftAdjacent[e] =
901 Array<OneD, bool>(pCollExp.size(), false);
902 for (int n = 0; n < pCollExp.size(); n++)
903 {
904 m_traceFieldMap[cid].m_isLocTraceLeftAdjacent[e][n] =
905 LeftAdjacents[cntLocTrace + n * exp->GetNtraces() + e];
906 }
907 }
908
909 // copy the m_locToTracePhysOffset with offset to a new array
910 // reshape from (n,e) to (e,n) and assgin to m_traceFieldMap[cid]
911 m_traceFieldMap[cid].m_locToTracePhysOffset =
912 Array<OneD, Array<OneD, int>>(exp->GetNtraces());
913 for (int e = 0; e < exp->GetNtraces(); e++)
914 {
915 m_traceFieldMap[cid].m_locToTracePhysOffset[e] =
916 Array<OneD, int>(pCollExp.size(), 0);
917 for (int n = 0; n < pCollExp.size(); n++)
918 {
919 m_traceFieldMap[cid].m_locToTracePhysOffset[e][n] =
920 m_locToTracePhysOffset[cntLocTrace + n * exp->GetNtraces() +
921 e];
922 }
923 }
924
925 // update counters
926 cntLocTrace += cntCollLocTrace;
927 }
928}
929
931 const int cid)
932{
933 return m_traceInterp[cid];
934}
935
941
943 const ExpListSharedPtr &tracelist, const int ndim)
944{
945 switch (ndim)
946 {
947 case 2:
949 break;
950 case 3:
952 break;
953 default:
955 "CalcLocTracePhysToTraceIDMap not coded");
956 }
957}
958
960 const ExpListSharedPtr &tracelist)
961{
962 std::shared_ptr<LocalRegions::ExpansionVector> traceExp =
963 tracelist->GetExp();
964 int ntotTrace = (*traceExp).size();
965 int ntPnts, noffset;
966
971
972 Array<OneD, NekDouble> tracePnts(m_nTracePts, 0.0);
973 for (int nt = 0; nt < ntotTrace; nt++)
974 {
975 ntPnts = tracelist->GetTotPoints(nt);
976 noffset = tracelist->GetPhys_Offset(nt);
977 for (int i = 0; i < ntPnts; i++)
978 {
979 tracePnts[noffset + i] = NekDouble(nt);
980 }
981 }
982
983 Array<OneD, Array<OneD, NekDouble>> loctracePntsLR(2);
984 loctracePntsLR[0] = Array<OneD, NekDouble>(m_nFwdLocTracePts, 0.0);
985 loctracePntsLR[1] =
987
988 for (int dir = 0; dir < 2; dir++)
989 {
990 int cnt = 0;
991 int cnt1 = 0;
992
995 tracePnts.data(), m_locInterpTraceToTraceMap[dir].data(),
996 tmp.data());
997
998 for (int i = 0; i < m_interpTrace[dir].size(); ++i)
999 {
1000 if (m_interpNtraces[dir][i])
1001 {
1002 LibUtilities::PointsKey fromPointsKey0 =
1003 std::get<0>(m_interpPoints[dir][i]);
1004 LibUtilities::PointsKey toPointsKey0 =
1005 std::get<2>(m_interpPoints[dir][i]);
1006
1007 int fnp = fromPointsKey0.GetNumPoints();
1008 int tnp = toPointsKey0.GetNumPoints();
1009 int nedges = m_interpNtraces[dir][i];
1010
1011 for (int ne = 0; ne < nedges; ne++)
1012 {
1013 Vmath::Fill(fnp, tmp[cnt1], &loctracePntsLR[dir][cnt], 1);
1014 cnt += fnp;
1015 cnt1 += tnp;
1016 }
1017 }
1018 }
1019 }
1020
1021 NekDouble error = 0.0;
1022 for (int nlr = 0; nlr < 2; nlr++)
1023 {
1024 for (int i = 0; i < loctracePntsLR[nlr].size(); i++)
1025 {
1027 std::round(loctracePntsLR[nlr][i]);
1028 error += abs(loctracePntsLR[nlr][i] -
1030 }
1031 }
1032 error = error / NekDouble(m_nLocTracePts);
1034 "m_LocTracephysToTraceIDMap may not be integer !!");
1035}
1036
1038 const ExpListSharedPtr &tracelist)
1039{
1040 std::shared_ptr<LocalRegions::ExpansionVector> traceExp =
1041 tracelist->GetExp();
1042 int ntotTrace = (*traceExp).size();
1043 int ntPnts, noffset;
1044
1049
1050 Array<OneD, NekDouble> tracePnts(m_nTracePts, 0.0);
1051 for (int nt = 0; nt < ntotTrace; nt++)
1052 {
1053 ntPnts = tracelist->GetTotPoints(nt);
1054 noffset = tracelist->GetPhys_Offset(nt);
1055 for (int i = 0; i < ntPnts; i++)
1056 {
1057 tracePnts[noffset + i] = NekDouble(nt);
1058 }
1059 }
1060
1061 Array<OneD, Array<OneD, NekDouble>> loctracePntsLR(2);
1062 loctracePntsLR[0] = Array<OneD, NekDouble>(m_nFwdLocTracePts, 0.0);
1063 loctracePntsLR[1] =
1065
1066 for (int dir = 0; dir < 2; dir++)
1067 {
1068 int cnt = 0;
1069 int cnt1 = 0;
1070
1071 // tmp space assuming forward map is of size of trace
1074 tracePnts.data(), m_locInterpTraceToTraceMap[dir].data(),
1075 tmp.data());
1076
1077 for (int i = 0; i < m_interpTrace[dir].size(); ++i)
1078 {
1079 if (m_interpNtraces[dir][i])
1080 {
1081 LibUtilities::PointsKey fromPointsKey0 =
1082 std::get<0>(m_interpPoints[dir][i]);
1083 LibUtilities::PointsKey fromPointsKey1 =
1084 std::get<1>(m_interpPoints[dir][i]);
1085 LibUtilities::PointsKey toPointsKey0 =
1086 std::get<2>(m_interpPoints[dir][i]);
1087 LibUtilities::PointsKey toPointsKey1 =
1088 std::get<3>(m_interpPoints[dir][i]);
1089
1090 int fnp0 = fromPointsKey0.GetNumPoints();
1091 int fnp1 = fromPointsKey1.GetNumPoints();
1092 int tnp0 = toPointsKey0.GetNumPoints();
1093 int tnp1 = toPointsKey1.GetNumPoints();
1094
1095 int nfttl = fnp0 * fnp1;
1096
1097 for (int ne = 0; ne < m_interpNtraces[dir][i]; ne++)
1098 {
1099 Vmath::Fill(nfttl, tmp[cnt1], &loctracePntsLR[dir][cnt], 1);
1100 cnt += nfttl;
1101 cnt1 += tnp0 * tnp1;
1102 }
1103 }
1104 }
1105 }
1106
1107 NekDouble error = 0.0;
1108 for (int nlr = 0; nlr < 2; nlr++)
1109 {
1110 for (int i = 0; i < loctracePntsLR[nlr].size(); i++)
1111 {
1113 std::round(loctracePntsLR[nlr][i]);
1114 error += abs(loctracePntsLR[nlr][i] -
1116 }
1117 }
1118 error = error / NekDouble(m_nLocTracePts);
1120 "m_LocTracephysToTraceIDMap may not be integer !!");
1121}
1122
1123/**
1124 * @brief Set up maps between coefficients on trace and in cells.
1125 *
1126 * @param locExp Expansion list in elements
1127 * @param trace Expansion list on traces.
1128 */
1130 const ExpList &locExp, const ExpListSharedPtr &trace)
1131{
1132 const std::shared_ptr<LocalRegions::ExpansionVector> exptrac =
1133 trace->GetExp();
1134 size_t ntrace = exptrac->size();
1135
1136 Array<OneD, Array<OneD, int>> LRAdjExpid{2};
1137 Array<OneD, Array<OneD, bool>> LRAdjflag{2};
1138
1139 TensorOfArray3D<int> elmtLRMap{2};
1140 TensorOfArray3D<int> elmtLRSign{2};
1141
1142 for (int lr = 0; lr < 2; ++lr)
1143 {
1144 LRAdjExpid[lr] = Array<OneD, int>{ntrace, 0};
1145 LRAdjflag[lr] = Array<OneD, bool>{ntrace, false};
1146 elmtLRMap[lr] = Array<OneD, Array<OneD, int>>{ntrace};
1147 elmtLRSign[lr] = Array<OneD, Array<OneD, int>>{ntrace};
1148 for (int i = 0; i < ntrace; ++i)
1149 {
1150 size_t ncoeff = trace->GetNcoeffs(i);
1151 elmtLRMap[lr][i] = Array<OneD, int>{ncoeff, 0};
1152 elmtLRSign[lr][i] = Array<OneD, int>{ncoeff, 0};
1153 }
1154 }
1155
1156 const Array<OneD, const pair<int, int>> field_coeffToElmt =
1157 locExp.GetCoeffsToElmt();
1158 const Array<OneD, const pair<int, int>> trace_coeffToElmt =
1159 trace->GetCoeffsToElmt();
1160
1161 for (int lr = 0; lr < 2; ++lr)
1162 {
1163 int ntotcoeffs = m_nTraceCoeffs[lr];
1164 for (int i = 0; i < ntotcoeffs; ++i)
1165 {
1166 int ncoeffField = m_traceCoeffsToElmtMap[lr][i];
1167 int ncoeffTrace = m_traceCoeffsToElmtTrace[lr][i];
1168 int sign = m_traceCoeffsToElmtSign[lr][i];
1169
1170 int ntraceelmt = trace_coeffToElmt[ncoeffTrace].first;
1171 int ntracelocN = trace_coeffToElmt[ncoeffTrace].second;
1172
1173 int nfieldelmt = field_coeffToElmt[ncoeffField].first;
1174 int nfieldlocN = field_coeffToElmt[ncoeffField].second;
1175
1176 LRAdjflag[lr][ntraceelmt] = true;
1177 LRAdjExpid[lr][ntraceelmt] = nfieldelmt;
1178
1179 elmtLRMap[lr][ntraceelmt][ntracelocN] = nfieldlocN;
1180 elmtLRSign[lr][ntraceelmt][ntracelocN] = sign;
1181 }
1182 }
1183 m_leftRightAdjacentExpId = LRAdjExpid;
1184 m_leftRightAdjacentExpFlag = LRAdjflag;
1187}
1188
1190 const ExpListSharedPtr &trace)
1191{
1192 const std::shared_ptr<LocalRegions::ExpansionVector> exptrac =
1193 trace->GetExp();
1194 int ntrace = exptrac->size();
1195
1196 const std::shared_ptr<LocalRegions::ExpansionVector> exp = locExp.GetExp();
1197 int nexp = exp->size();
1198
1199 Array<OneD, Array<OneD, int>> LRAdjExpid(2);
1200 Array<OneD, Array<OneD, bool>> LRAdjflag(2);
1201 LRAdjExpid = m_leftRightAdjacentExpId;
1202 LRAdjflag = m_leftRightAdjacentExpFlag;
1203
1204 std::set<std::pair<int, int>> neighborSet;
1205 int ntmp0, ntmp1;
1206 for (int nt = 0; nt < ntrace; nt++)
1207 {
1208 if (LRAdjflag[0][nt] && LRAdjflag[1][nt])
1209 {
1210 ntmp0 = LRAdjExpid[0][nt];
1211 ntmp1 = LRAdjExpid[1][nt];
1212
1213 ASSERTL0(ntmp0 != ntmp1,
1214 " ntmp0==ntmp1, trace inside a element?? ");
1215
1216 std::set<std::pair<int, int>>::iterator it = neighborSet.begin();
1217 neighborSet.insert(it, std::make_pair(ntmp0, ntmp1));
1218 neighborSet.insert(it, std::make_pair(ntmp1, ntmp0));
1219 }
1220 }
1221
1222 Array<OneD, int> ElemIndex(nexp, 0);
1223 for (std::set<std::pair<int, int>>::iterator it = neighborSet.begin();
1224 it != neighborSet.end(); ++it)
1225 {
1226 int ncurrent = it->first;
1227 ElemIndex[ncurrent]++;
1228 }
1229
1230 Array<OneD, Array<OneD, int>> ElemNeighbsId(nexp);
1231 Array<OneD, Array<OneD, int>> tmpId(nexp);
1232 Array<OneD, int> ElemNeighbsNumb(nexp, -1);
1233 Vmath::Vcopy(nexp, ElemIndex, 1, ElemNeighbsNumb, 1);
1234 for (int ne = 0; ne < nexp; ne++)
1235 {
1236 int neighb = ElemNeighbsNumb[ne];
1237 ElemNeighbsId[ne] = Array<OneD, int>(neighb, -1);
1238 tmpId[ne] = Array<OneD, int>(neighb, -1);
1239 }
1240
1241 for (int ne = 0; ne < nexp; ne++)
1242 {
1243 ElemIndex[ne] = 0;
1244 }
1245 for (std::set<std::pair<int, int>>::iterator it = neighborSet.begin();
1246 it != neighborSet.end(); ++it)
1247 {
1248 int ncurrent = it->first;
1249 int neighbor = it->second;
1250 ElemNeighbsId[ncurrent][ElemIndex[ncurrent]] = neighbor;
1251 ElemIndex[ncurrent]++;
1252 }
1253
1254 // pickout repeated indexes
1255 for (int ne = 0; ne < nexp; ne++)
1256 {
1257 ElemIndex[ne] = 0;
1258 for (int nb = 0; nb < ElemNeighbsNumb[ne]; nb++)
1259 {
1260 int neighbId = ElemNeighbsId[ne][nb];
1261 bool found = false;
1262 for (int nc = 0; nc < ElemIndex[ne]; nc++)
1263 {
1264 if (ElemNeighbsId[ne][nb] == tmpId[ne][nc])
1265 {
1266 found = true;
1267 }
1268 }
1269 if (!found)
1270 {
1271 tmpId[ne][ElemIndex[ne]] = neighbId;
1272 ElemIndex[ne]++;
1273 }
1274 }
1275 }
1276 ElemNeighbsNumb = ElemIndex;
1277 for (int ne = 0; ne < nexp; ne++)
1278 {
1279 int neighb = ElemNeighbsNumb[ne];
1280 if (neighb > 0)
1281 {
1282 ElemNeighbsId[ne] = Array<OneD, int>(neighb, -1);
1283 Vmath::Vcopy(neighb, tmpId[ne], 1, ElemNeighbsId[ne], 1);
1284 }
1285 }
1286
1287 // check errors
1288 for (int ne = 0; ne < nexp; ne++)
1289 {
1290 for (int nb = 0; nb < ElemNeighbsNumb[ne]; nb++)
1291 {
1292 ASSERTL0((ElemNeighbsId[ne][nb] >= 0) &&
1293 (ElemNeighbsId[ne][nb] <= nexp),
1294 "Element id <0 or >number of total elements")
1295 }
1296 }
1297
1298 m_ElemNeighbsNumb = ElemNeighbsNumb;
1299 m_ElemNeighbsId = ElemNeighbsId;
1300}
1301
1302/**
1303 * @brief Gather the local elemental traces in physical space from
1304 * field using #m_locTraceToFieldMap. Note traces are blocked together
1305 * in similar trace point ordering
1306 *
1307 * @param field Solution field in physical space
1308 * @param faces Resulting local traces.
1309 */
1312{
1313 // The static cast is necessary because m_locTraceToFieldMap should be
1314 // Array<OneD, size_t> ... or at least the same type as
1315 // m_locTraceToFieldMap.size() ...
1316 Vmath::Gathr(static_cast<int>(m_locTraceToFieldMap.size()), field,
1317 m_locTraceToFieldMap, faces);
1318}
1319
1320/**
1321 * @brief Reverse process of LocTracesFromField()
1322 * Add the local traces in physical space to field using
1323 * #m_locTraceToFieldMap.
1324 *
1325 * @param field Solution field in physical space
1326 * @param faces local traces.
1327 */
1330{
1331 size_t nfield = field.size();
1332 Array<OneD, NekDouble> tmp{nfield, 0.0};
1333 Vmath::Assmb(m_locTraceToFieldMap.size(), faces.data(),
1334 m_locTraceToFieldMap.data(), tmp.data());
1335 Vmath::Vadd(nfield, tmp, 1, field, 1, field, 1);
1336}
1337
1338/**
1339 * @brief Gather the forwards-oriented local traces in physical space from field
1340 * using #m_locTraceToFieldMap.
1341 *
1342 * @param field Solution field in physical space
1343 * @param faces Resulting local forwards-oriented traces.
1344 */
1350
1351/**
1352 * @brief Reshuffle local elemental traces in physical space so that
1353 * similar faces points are blocked together so they can then be
1354 * interpolated with InterpLocTraceToTrace method.
1355 *
1356 * @param loctrace local traces in physical space
1357 * @param reshuffle traces ordered in reshuffled format of similar patterns.
1358 */
1360 const int dir, const Array<OneD, const NekDouble> &loctraces,
1361 Array<OneD, NekDouble> reshuffle)
1362{
1363 ASSERTL1(dir < 2, "option dir out of range, "
1364 " dir=0 is fwd, dir=1 is bwd");
1365
1366 Vmath::Gathr(static_cast<int>(m_locTraceToElmtTraceMap[dir].size()),
1367 loctraces, m_locTraceToElmtTraceMap[dir], reshuffle);
1368}
1369
1370/**
1371 * @brief Unshuffle local elemental traces in physical space from
1372 * similar faces points are blocked together to the local elemental trace format
1373 *
1374 * @param loctrace local traces in physical space
1375 * @param reshuffle traces ordered in reshuffled format of similar patterns.
1376 */
1378 const int dir, const Array<OneD, const NekDouble> &loctraces,
1379 Array<OneD, NekDouble> unshuffle)
1380{
1381 ASSERTL1(dir < 2, "option dir out of range, "
1382 " dir=0 is fwd, dir=1 is bwd");
1383
1384 if (m_locTraceToElmtTraceMap[dir].size()) // single elemt check
1385 {
1386 Vmath::Scatr(m_locTraceToElmtTraceMap[dir].size(), loctraces,
1387 m_locTraceToElmtTraceMap[dir], unshuffle);
1388 }
1389}
1390
1392 const int dir, const Array<OneD, const NekDouble> &loctraces,
1393 Array<OneD, NekDouble> &traces)
1394{
1395 switch (m_expdim)
1396 {
1397 case 1: // Essentially do copy
1399 loctraces.data(),
1400 m_locInterpTraceToTraceMap[dir].data(), traces.data());
1401 break;
1402 case 2:
1403 InterpLocEdgesToTrace(dir, loctraces, traces);
1404 break;
1405 case 3:
1406 InterpLocFacesToTrace(dir, loctraces, traces);
1407 break;
1408 default:
1409 NEKERROR(ErrorUtil::efatal, "Not set up");
1410 break;
1411 }
1412}
1413
1414/**
1415 * @brief Interpolate local trace edges to global trace edge point distributions
1416 * where required.
1417 *
1418 * @param dir Selects forwards (0) or backwards (1) direction.
1419 * @param locfaces Local trace edge storage.
1420 * @param faces Global trace edge storage
1421 */
1423 const int dir, const Array<OneD, const NekDouble> &locedges,
1425{
1426 ASSERTL1(dir < 2, "option dir out of range, "
1427 " dir=0 is fwd, dir=1 is bwd");
1428
1429 int cnt = 0;
1430 int cnt1 = 0;
1431
1432 // tmp space assuming forward map is of size of trace
1434
1435 for (int i = 0; i < m_interpTrace[dir].size(); ++i)
1436 {
1437 // Check if there are edges to interpolate
1438 if (m_interpNtraces[dir][i])
1439 {
1440 // Get to/from points
1441 LibUtilities::PointsKey fromPointsKey0 =
1442 std::get<0>(m_interpPoints[dir][i]);
1443 LibUtilities::PointsKey toPointsKey0 =
1444 std::get<2>(m_interpPoints[dir][i]);
1445
1446 int fnp = fromPointsKey0.GetNumPoints();
1447 int tnp = toPointsKey0.GetNumPoints();
1448 int nedges = m_interpNtraces[dir][i];
1449
1450 // Do interpolation here if required
1451 switch (m_interpTrace[dir][i])
1452 {
1453 case eNoInterp: // Just copy
1454 {
1455 if (fnp == tnp) // identical points : just copy all points
1456 {
1457 Vmath::Vcopy(nedges * fnp, locedges.data() + cnt, 1,
1458 tmp.data() + cnt1, 1);
1459 }
1460 else // copy interior points and fill in end points (if any)
1461 {
1462 int fbegin, fend, fsize;
1463 int tbegin, tend, tsize;
1465 fbegin, fend);
1467 tbegin, tend);
1468 fsize = fend - fbegin;
1469 tsize = tend - tbegin;
1470 ASSERTL0(
1471 fsize == tsize,
1472 "Quad ranges mismatch in InterpLocEdgesToTrace!");
1473 for (int k = 0; k < nedges; ++k)
1474 {
1476 fsize, locedges.data() + cnt + fnp * k + fbegin,
1477 1, tmp.data() + cnt1 + tnp * k + tbegin, 1);
1478 // fill 0 ~ tbegin with tbegin
1479 Vmath::Fill(tbegin, tmp[cnt1 + tnp * k + tbegin],
1480 tmp.data() + cnt1 + tnp * k, 1);
1481 // fill tend ~ tnp with tend
1482 Vmath::Fill(tnp - tend,
1483 tmp[cnt1 + tnp * k + tend - 1],
1484 tmp.data() + cnt1 + tnp * k + tend, 1);
1485 }
1486 }
1487 }
1488 break;
1489 case eInterpDir0:
1490 {
1491 DNekMatSharedPtr I0 = m_interpTraceI0[dir][i];
1492 Blas::Dgemm('N', 'N', tnp, nedges, fnp, 1.0,
1493 I0->GetPtr().data(), tnp, locedges.data() + cnt,
1494 fnp, 0.0, tmp.data() + cnt1, tnp);
1495 }
1496 break;
1497 case eInterpEndPtDir0:
1498 {
1500
1501 for (int k = 0; k < nedges; ++k)
1502 {
1503 Vmath::Vcopy(fnp, &locedges[cnt + k * fnp], 1,
1504 &tmp[cnt1 + k * tnp], 1);
1505
1506 tmp[cnt1 + k * tnp + tnp - 1] = Blas::Ddot(
1507 fnp, locedges.data() + cnt + k * fnp, 1, &I0[0], 1);
1508 }
1509 }
1510 break;
1511 default:
1513 "Invalid interpolation type for 2D elements");
1514 break;
1515 }
1516
1517 cnt += nedges * fnp;
1518 cnt1 += nedges * tnp;
1519 }
1520 }
1521
1522 Vmath::Scatr(m_locInterpTraceToTraceMap[dir].size(), tmp.data(),
1523 m_locInterpTraceToTraceMap[dir].data(), edges.data());
1524}
1525
1526/**
1527 * @brief Interpolate local faces to trace face point distributions where
1528 * required.
1529 *
1530 * @param dir Selects forwards (0) or backwards (1) direction.
1531 * @param locfaces Local trace face storage.
1532 * @param faces Global trace face storage
1533 */
1535 const int dir, const Array<OneD, const NekDouble> &locfaces,
1537{
1538 ASSERTL1(dir < 2, "option dir out of range, "
1539 " dir=0 is fwd, dir=1 is bwd");
1540
1541 int cnt1 = 0;
1542 int cnt = 0;
1543
1544 // tmp space assuming forward map is of size of trace
1546
1547 for (int i = 0; i < m_interpTrace[dir].size(); ++i)
1548 {
1549 // Check if there are faces to interpolate
1550 if (m_interpNtraces[dir][i])
1551 {
1552 // Get to/from points
1553 LibUtilities::PointsKey fromPointsKey0 =
1554 std::get<0>(m_interpPoints[dir][i]);
1555 LibUtilities::PointsKey fromPointsKey1 =
1556 std::get<1>(m_interpPoints[dir][i]);
1557 LibUtilities::PointsKey toPointsKey0 =
1558 std::get<2>(m_interpPoints[dir][i]);
1559 LibUtilities::PointsKey toPointsKey1 =
1560 std::get<3>(m_interpPoints[dir][i]);
1561
1562 int fnp0 = fromPointsKey0.GetNumPoints();
1563 int fnp1 = fromPointsKey1.GetNumPoints();
1564 int tnp0 = toPointsKey0.GetNumPoints();
1565 int tnp1 = toPointsKey1.GetNumPoints();
1566 int nfaces = m_interpNtraces[dir][i];
1567 int nfromfacepts = fnp0 * fnp1;
1568 int ntofacepts = tnp0 * tnp1;
1569
1570 // Do interpolation here if required
1571 switch (m_interpTrace[dir][i])
1572 {
1573 case eNoInterp: // Just copy
1574 {
1575 if (fnp0 == tnp0 && fnp1 == tnp1)
1576 {
1577 Vmath::Vcopy(nfaces * nfromfacepts,
1578 locfaces.data() + cnt, 1,
1579 tmp.data() + cnt1, 1);
1580 }
1581 else
1582 {
1583 int fbegin0, fend0, fbegin1, fend1;
1584 int tbegin0, tend0, tbegin1, tend1;
1586 fbegin0, fend0);
1588 tbegin0, tend0);
1590 fbegin1, fend1);
1592 tbegin1, tend1);
1593 ASSERTL0(
1594 fend0 - fbegin0 == tend0 - tbegin0 &&
1595 fend1 - fbegin1 == tend1 - tbegin1,
1596 "Quad ranges mismatch in InterpLocFacesToTrace!");
1597 for (int j = 0; j < nfaces; ++j)
1598 {
1599 for (int k = fbegin1, l = tbegin1; k < fend1;
1600 ++k, ++l)
1601 {
1603 fend0 - fbegin0,
1604 locfaces.data() + cnt + j * nfromfacepts +
1605 k * fnp0 + fbegin0,
1606 1,
1607 tmp.data() + cnt1 + j * ntofacepts +
1608 l * tnp0 + tbegin0,
1609 1);
1610 }
1611 }
1612 }
1613 }
1614 break;
1615 case eInterpDir0:
1616 {
1617 DNekMatSharedPtr I0 = m_interpTraceI0[dir][i];
1618 Blas::Dgemm('N', 'N', tnp0, tnp1 * nfaces, fnp0, 1.0,
1619 I0->GetPtr().data(), tnp0,
1620 locfaces.data() + cnt, fnp0, 0.0,
1621 tmp.data() + cnt1, tnp0);
1622 }
1623 break;
1624 case eInterpEndPtDir0:
1625 {
1626 int nfaces = m_interpNtraces[dir][i];
1627 for (int k = 0; k < fnp0; ++k)
1628 {
1629 Vmath::Vcopy(nfaces * fnp1, locfaces.data() + cnt + k,
1630 fnp0, tmp.data() + cnt1 + k, tnp0);
1631 }
1632
1634 Blas::Dgemv('T', fnp0, tnp1 * nfaces, 1.0,
1635 tmp.data() + cnt1, tnp0, I0.data(), 1, 0.0,
1636 tmp.data() + cnt1 + tnp0 - 1, tnp0);
1637 }
1638 break;
1639 case eInterpDir1:
1640 {
1641 DNekMatSharedPtr I1 = m_interpTraceI1[dir][i];
1642 for (int j = 0; j < nfaces; ++j)
1643 {
1644 Blas::Dgemm('N', 'T', tnp0, tnp1, fnp1, 1.0,
1645 locfaces.data() + cnt + j * fnp0 * fnp1,
1646 tnp0, I1->GetPtr().data(), tnp1, 0.0,
1647 tmp.data() + cnt1 + j * tnp0 * tnp1, tnp0);
1648 }
1649 }
1650 break;
1651 case eInterpEndPtDir1:
1652 {
1654 for (int j = 0; j < nfaces; ++j)
1655 {
1656 // copy all points
1657 Vmath::Vcopy(fnp0 * fnp1,
1658 locfaces.data() + cnt + j * fnp0 * fnp1, 1,
1659 tmp.data() + cnt1 + j * tnp0 * tnp1, 1);
1660
1661 // interpolate end points
1662 for (int k = 0; k < tnp0; ++k)
1663 {
1664 tmp[cnt1 + k + (j + 1) * tnp0 * tnp1 - tnp0] =
1665 Blas::Ddot(fnp1,
1666 locfaces.data() + cnt +
1667 j * fnp0 * fnp1 + k,
1668 fnp0, &I1[0], 1);
1669 }
1670 }
1671 }
1672 break;
1673 case eInterpBothDirs:
1674 {
1675 DNekMatSharedPtr I0 = m_interpTraceI0[dir][i];
1676 DNekMatSharedPtr I1 = m_interpTraceI1[dir][i];
1677 Array<OneD, NekDouble> wsp(nfaces * fnp0 * tnp1);
1678
1679 for (int j = 0; j < nfaces; ++j)
1680 {
1681 Blas::Dgemm('N', 'T', fnp0, tnp1, fnp1, 1.0,
1682 locfaces.data() + cnt + j * fnp0 * fnp1,
1683 fnp0, I1->GetPtr().data(), tnp1, 0.0,
1684 wsp.data() + j * fnp0 * tnp1, fnp0);
1685 }
1686 Blas::Dgemm('N', 'N', tnp0, tnp1 * nfaces, fnp0, 1.0,
1687 I0->GetPtr().data(), tnp0, wsp.data(), fnp0,
1688 0.0, tmp.data() + cnt1, tnp0);
1689 }
1690 break;
1692 {
1693 DNekMatSharedPtr I1 = m_interpTraceI1[dir][i];
1695
1696 for (int j = 0; j < nfaces; ++j)
1697 {
1698 Blas::Dgemm('N', 'T', fnp0, tnp1, fnp1, 1.0,
1699 locfaces.data() + cnt + j * fnp0 * fnp1,
1700 fnp0, I1->GetPtr().data(), tnp1, 0.0,
1701 tmp.data() + cnt1 + j * tnp0 * tnp1, tnp0);
1702 }
1703
1704 Blas::Dgemv('T', fnp0, tnp1 * nfaces, 1.0,
1705 tmp.data() + cnt1, tnp0, I0.data(), 1, 0.0,
1706 tmp.data() + cnt1 + tnp0 - 1, tnp0);
1707 }
1708 break;
1709 default:
1710 ASSERTL0(false, "Interplation case needs implementing");
1711 break;
1712 }
1713 cnt += nfaces * nfromfacepts;
1714 cnt1 += nfaces * ntofacepts;
1715 }
1716 }
1717
1718 Vmath::Scatr(m_locInterpTraceToTraceMap[dir].size(), tmp.data(),
1719 m_locInterpTraceToTraceMap[dir].data(), faces.data());
1720}
1721
1723 const int dir, const Array<OneD, const NekDouble> &trace,
1724 Array<OneD, NekDouble> &loctrace)
1725{
1726 switch (m_expdim)
1727 {
1728 case 2:
1729 InterpLocEdgesToTraceTranspose(dir, trace, loctrace);
1730 break;
1731 case 3:
1732 InterpLocFacesToTraceTranspose(dir, trace, loctrace);
1733 break;
1734 default:
1735 NEKERROR(ErrorUtil::efatal, "Not set up");
1736 break;
1737 }
1738}
1739
1740/**
1741 * @brief Transpose of Interp local edges to trace
1742 *
1743 * @param dir Selects forwards (0) or backwards (1) direction.
1744 * @param edges Global trace edge
1745 * @param locedges Local trace edge
1746 */
1748 const int dir, const Array<OneD, const NekDouble> &edges,
1749 Array<OneD, NekDouble> &locedges)
1750{
1751 ASSERTL1(dir < 2, "option dir out of range, "
1752 " dir=0 is fwd, dir=1 is bwd");
1753
1754 int cnt = 0;
1755 int cnt1 = 0;
1756
1757 // tmp space assuming forward map is of size of trace
1758 Array<OneD, NekDouble> tmp{size_t(m_nTracePts), 0.0};
1759 Vmath::Gathr((int)m_locInterpTraceToTraceMap[dir].size(), edges.data(),
1760 m_locInterpTraceToTraceMap[dir].data(), tmp.data());
1761
1762 for (int i = 0; i < m_interpTrace[dir].size(); ++i)
1763 {
1764 // Check if there are edges to interpolate
1765 if (m_interpNtraces[dir][i])
1766 {
1767 // Get to/from points
1768 LibUtilities::PointsKey fromPointsKey0 =
1769 std::get<0>(m_interpPoints[dir][i]);
1770 LibUtilities::PointsKey toPointsKey0 =
1771 std::get<2>(m_interpPoints[dir][i]);
1772
1773 int fnp = fromPointsKey0.GetNumPoints();
1774 int tnp = toPointsKey0.GetNumPoints();
1775 int nedges = m_interpNtraces[dir][i];
1776
1777 // Do interpolation here if required
1778 switch (m_interpTrace[dir][i])
1779 {
1780 case eNoInterp: // Just copy
1781 {
1782 int fbegin, fsize;
1783 int tbegin, tsize;
1784 LibUtilities::GetEffectiveQuadRange(fromPointsKey0, fbegin,
1785 fsize);
1786 LibUtilities::GetEffectiveQuadRange(toPointsKey0, tbegin,
1787 tsize);
1788 fsize = fsize - fbegin;
1789 tsize = tsize - tbegin;
1790 ASSERTL0(fsize == tsize, "Quad ranges mismatch in "
1791 "InterpLocEdgesToTraceTranspose!");
1792 for (int k = 0; k < nedges; ++k)
1793 {
1794 Vmath::Zero(fnp, locedges.data() + cnt + fnp * k, 1);
1796 fsize, tmp.data() + cnt1 + tnp * k + tbegin, 1,
1797 locedges.data() + cnt + fnp * k + fbegin, 1);
1798 }
1799 }
1800 break;
1801 case eInterpDir0:
1802 {
1803 DNekMatSharedPtr I0 = m_interpTraceI0[dir][i];
1804 Blas::Dgemm('T', 'N', fnp, nedges, tnp, 1.0,
1805 I0->GetPtr().data(), tnp, tmp.data() + cnt1,
1806 tnp, 0.0, locedges.data() + cnt, fnp);
1807 }
1808 break;
1809 case eInterpEndPtDir0:
1810 {
1812
1813 for (int k = 0; k < nedges; ++k)
1814 {
1815 Vmath::Vcopy(fnp, &tmp[cnt1 + k * tnp], 1,
1816 &locedges[cnt + k * fnp], 1);
1817
1818 Vmath::Svtvp(fnp, tmp[cnt1 + k * tnp + tnp - 1], &I0[0],
1819 1, locedges.data() + cnt + k * fnp, 1,
1820 locedges.data() + cnt + k * fnp, 1);
1821 }
1822 }
1823 break;
1824 default:
1826 "Invalid interpolation type for 2D elements");
1827 break;
1828 }
1829
1830 cnt += nedges * fnp;
1831 cnt1 += nedges * tnp;
1832 }
1833 }
1834}
1835
1836/**
1837 * @brief transpose of interp local faces to trace
1838 *
1839 * @param dir Selects forwards (0) or backwards (1) direction.
1840 * @param loctraces Local trace
1841 * @param traces trace .
1842 */
1844 const int dir, const Array<OneD, const NekDouble> &traces,
1845 Array<OneD, NekDouble> &loctraces)
1846{
1847 ASSERTL1(dir < 2, "option dir out of range, "
1848 " dir=0 is fwd, dir=1 is bwd");
1849
1850 int cnt = 0;
1851 int cnt1 = 0;
1852
1853 // tmp space assuming forward map is of size of trace
1854 Array<OneD, NekDouble> tmp{size_t(m_nTracePts), 0.0};
1855 // The static cast is necessary because m_locInterpTraceToTraceMap should be
1856 // Array<OneD, size_t> ... or at least the same type as
1857 // m_locInterpTraceToTraceMap.size() ...
1858 Vmath::Gathr(static_cast<int>(m_locInterpTraceToTraceMap[dir].size()),
1859 traces.data(), m_locInterpTraceToTraceMap[dir].data(),
1860 tmp.data());
1861
1862 for (int i = 0; i < m_interpTrace[dir].size(); ++i)
1863 {
1864 // Check if there are elementboundaries to interpolate
1865 if (m_interpNtraces[dir][i])
1866 {
1867 // Get to/from points
1868 LibUtilities::PointsKey fromPointsKey0 =
1869 std::get<0>(m_interpPoints[dir][i]);
1870 LibUtilities::PointsKey fromPointsKey1 =
1871 std::get<1>(m_interpPoints[dir][i]);
1872 LibUtilities::PointsKey toPointsKey0 =
1873 std::get<2>(m_interpPoints[dir][i]);
1874 LibUtilities::PointsKey toPointsKey1 =
1875 std::get<3>(m_interpPoints[dir][i]);
1876 // Here the f(from) and t(to) are chosen to be consistent with
1877 // InterpLocFacesToTrace
1878 int fnp0 = fromPointsKey0.GetNumPoints();
1879 int fnp1 = fromPointsKey1.GetNumPoints();
1880 int tnp0 = toPointsKey0.GetNumPoints();
1881 int tnp1 = toPointsKey1.GetNumPoints();
1882 int nfaces = m_interpNtraces[dir][i];
1883 int nfromfacepts = fnp0 * fnp1;
1884 int ntofacepts = tnp0 * tnp1;
1885
1886 // Do transpose interpolation here if required
1887 switch (m_interpTrace[dir][i])
1888 {
1889 case eNoInterp: // Just copy
1890 {
1891 int fbegin0, fend0, fbegin1, fend1;
1892 int tbegin0, tend0, tbegin1, tend1;
1893 LibUtilities::GetEffectiveQuadRange(fromPointsKey0, fbegin0,
1894 fend0);
1895 LibUtilities::GetEffectiveQuadRange(toPointsKey0, tbegin0,
1896 tend0);
1897 LibUtilities::GetEffectiveQuadRange(fromPointsKey1, fbegin1,
1898 fend1);
1899 LibUtilities::GetEffectiveQuadRange(toPointsKey1, tbegin1,
1900 tend1);
1901 // overwrite end by size
1902 fend0 = fend0 - fbegin0;
1903 tend0 = tend0 - tbegin0;
1904 ASSERTL0(fend0 == tend0 &&
1905 fend1 - fbegin1 == tend1 - tbegin1,
1906 "Quad ranges mismatch in "
1907 "InterpLocFacesToTraceTranspose!");
1908 for (int j = 0; j < nfaces; ++j)
1909 {
1910 for (int k = fbegin1, l = tbegin1; k < fend1; ++k, ++l)
1911 {
1912 Vmath::Vcopy(fend0,
1913 tmp.data() + cnt1 + j * ntofacepts +
1914 l * tnp0 + tbegin0,
1915 1,
1916 loctraces.data() + cnt +
1917 j * nfromfacepts + k * fnp0 +
1918 fbegin0,
1919 1);
1920 }
1921 }
1922 }
1923 break;
1924 case eInterpDir0:
1925 {
1926 DNekMatSharedPtr I0 = m_interpTraceI0[dir][i];
1927 Blas::Dgemm('T', 'N', fnp0, tnp1, tnp0, 1.0,
1928 I0->GetPtr().data(), tnp0, tmp.data() + cnt1,
1929 tnp0, 0.0, loctraces.data() + cnt, fnp0);
1930 }
1931 break;
1932 case eInterpEndPtDir0:
1933 {
1934 for (int k = 0; k < fnp0; ++k)
1935 {
1936 Vmath::Vcopy(nfaces * fnp1, tmp.data() + cnt1 + k, tnp0,
1937 loctraces.data() + cnt + k, fnp0);
1938 }
1939
1941 for (int k = 0; k < tnp1 * nfaces; k++)
1942 {
1943 Vmath::Svtvp(fnp0, tmp[cnt1 + tnp0 - 1 + k * tnp0],
1944 &I0[0], 1,
1945 loctraces.data() + cnt + k * fnp0, 1,
1946 loctraces.data() + cnt + k * fnp0, 1);
1947 }
1948 }
1949 break;
1950 case eInterpDir1:
1951 {
1952 DNekMatSharedPtr I1 = m_interpTraceI1[dir][i];
1953
1954 for (int j = 0; j < m_interpNtraces[dir][i]; ++j)
1955 {
1956 Blas::Dgemm('N', 'N', tnp0, fnp1, tnp1, 1.0,
1957 tmp.data() + cnt1 + j * tnp0 * tnp1, tnp0,
1958 I1->GetPtr().data(), tnp1, 0.0,
1959 loctraces.data() + cnt + j * fnp0 * fnp1,
1960 tnp0);
1961 }
1962 }
1963 break;
1964 case eInterpEndPtDir1:
1965 {
1967 for (int j = 0; j < m_interpNtraces[dir][i]; ++j)
1968 {
1970 fnp0 * fnp1, tmp.data() + cnt1 + j * tnp0 * tnp1, 1,
1971 loctraces.data() + cnt + j * fnp0 * fnp1, 1);
1972
1973 for (int k = 0; k < fnp1; k++)
1974 {
1976 fnp0, I1[k],
1977 &tmp[cnt1 + (j + 1) * tnp0 * tnp1 - tnp0], 1,
1978 &loctraces[cnt + j * fnp0 * fnp1 + k * fnp0], 1,
1979 &loctraces[cnt + j * fnp0 * fnp1 + k * fnp0],
1980 1);
1981 }
1982 }
1983 }
1984 break;
1985 case eInterpBothDirs:
1986 {
1987 DNekMatSharedPtr I0 = m_interpTraceI0[dir][i];
1988 DNekMatSharedPtr I1 = m_interpTraceI1[dir][i];
1989
1991 size_t(m_interpNtraces[dir][i] * fnp0 * tnp1)};
1992
1993 Blas::Dgemm('T', 'N', fnp0, tnp1 * m_interpNtraces[dir][i],
1994 tnp0, 1.0, I0->GetPtr().data(), tnp0,
1995 tmp.data() + cnt1, tnp0, 0.0, wsp.data(), fnp0);
1996
1997 for (int j = 0; j < m_interpNtraces[dir][i]; ++j)
1998 {
1999 Blas::Dgemm('N', 'N', fnp0, fnp1, tnp1, 1.0,
2000 wsp.data() + j * fnp0 * tnp1, fnp0,
2001 I1->GetPtr().data(), tnp1, 0.0,
2002 loctraces.data() + cnt + j * fnp0 * fnp1,
2003 fnp0);
2004 }
2005 }
2006 break;
2008 {
2009 DNekMatSharedPtr I1 = m_interpTraceI1[dir][i];
2011
2013 size_t(m_interpNtraces[dir][i] * fnp0 * tnp1)};
2014
2015 for (int k = 0; k < tnp1 * m_interpNtraces[dir][i]; k++)
2016 {
2017 Vmath::Svtvp(fnp0, tmp[cnt1 + tnp0 - 1 + k * tnp0],
2018 &I0[0], 1, tmp.data() + cnt1 + k * tnp0, 1,
2019 wsp.data() + k * fnp0, 1);
2020 }
2021
2022 for (int j = 0; j < m_interpNtraces[dir][i]; ++j)
2023 {
2024 Blas::Dgemm('N', 'N', fnp0, fnp1, tnp1, 1.0,
2025 wsp.data() + j * fnp0 * tnp1, fnp0,
2026 I1->GetPtr().data(), tnp1, 0.0,
2027 loctraces.data() + cnt + j * fnp0 * fnp1,
2028 fnp0);
2029 }
2030 }
2031 break;
2032 }
2033 cnt += nfaces * nfromfacepts;
2034 cnt1 += nfaces * ntofacepts;
2035 }
2036 }
2037}
2038
2040 const int dir, const Array<OneD, NekDouble> &traces,
2041 Array<OneD, NekDouble> &loctraces)
2042{
2043 switch (m_expdim)
2044 {
2045 case 1: // Essentially do copy
2047 static_cast<int>(m_locInterpTraceToTraceMap[dir].size()),
2048 traces.data(), m_locInterpTraceToTraceMap[dir].data(),
2049 loctraces.data());
2050 break;
2051 case 2:
2052 InterpTraceToLocEdges(dir, traces, loctraces);
2053 break;
2054 case 3:
2055 InterpTraceToLocFaces(dir, traces, loctraces);
2056 break;
2057 default:
2058 ASSERTL0(false, "Not set up");
2059 break;
2060 }
2061}
2062
2063/**
2064 * @brief Interpolate global trace edge to local trace edges point
2065 * distributions where required.
2066 *
2067 * @param dir Selects forwards (0) or backwards (1) direction.
2068 * @param locfaces Local trace edge storage.
2069 * @param faces Global trace edge storage
2070 */
2072 const int dir, const Array<OneD, const NekDouble> &edges,
2073 Array<OneD, NekDouble> &locedges)
2074{
2075 ASSERTL1(dir < 2, "option dir out of range, "
2076 " dir=0 is fwd, dir=1 is bwd");
2077
2078 int cnt = 0;
2079 int cnt1 = 0;
2080
2082
2083 // unshuffles trace into lcoally orientated format.
2084 Vmath::Gathr(static_cast<int>(m_locInterpTraceToTraceMap[dir].size()),
2085 edges.data(), m_locInterpTraceToTraceMap[dir].data(),
2086 tmp.data());
2087
2088 for (int i = 0; i < m_interpTrace[dir].size(); ++i)
2089 {
2090 // Check if there are edges to interpolate
2091 if (m_interpNtraces[dir][i])
2092 {
2093 // Get to/from points
2094 LibUtilities::PointsKey fromPointsKey0 =
2095 std::get<2>(m_interpPoints[dir][i]);
2096 LibUtilities::PointsKey toPointsKey0 =
2097 std::get<0>(m_interpPoints[dir][i]);
2098
2099 int fnp = fromPointsKey0.GetNumPoints();
2100 int tnp = toPointsKey0.GetNumPoints();
2101 int nedges = m_interpNtraces[dir][i];
2102
2103 // Do interpolation here if required
2104 switch (m_interpTrace[dir][i])
2105 {
2106 case eNoInterp: // Just copy
2107 {
2108 int fbegin, fend;
2109 int tbegin, tend;
2110 LibUtilities::GetEffectiveQuadRange(fromPointsKey0, fbegin,
2111 fend);
2112 LibUtilities::GetEffectiveQuadRange(toPointsKey0, tbegin,
2113 tend);
2114 // overwrite fend by size
2115 fend = fend - fbegin;
2116 tend = tend - tbegin;
2117 ASSERTL0(fend == tend,
2118 "Quad ranges mismatch in InterpTraceToLocEdges!");
2119 for (int k = 0; k < nedges; ++k)
2120 {
2121 Vmath::Zero(tnp, locedges.data() + cnt1 + tnp * k, 1);
2123 fend, tmp.data() + cnt + fnp * k + fbegin, 1,
2124 locedges.data() + cnt1 + tnp * k + tbegin, 1);
2125 }
2126 }
2127 break;
2128 case eInterpDir0:
2129 {
2131 Blas::Dgemm('N', 'N', tnp, nedges, fnp, 1.0,
2132 I0->GetPtr().data(), tnp, tmp.data() + cnt, fnp,
2133 0.0, locedges.data() + cnt1, tnp);
2134 }
2135 break;
2136 case eInterpEndPtDir0:
2137 {
2138 // Just copy points back
2139 for (int k = 0; k < nedges; ++k)
2140 {
2141 // Should be tnp rather than fnp on first argument.
2142 Vmath::Vcopy(tnp, &tmp[cnt + k * fnp], 1,
2143 &locedges[cnt1 + k * tnp], 1);
2144 }
2145 }
2146 break;
2147 default:
2148 ASSERTL0(false,
2149 "Invalid interpolation type for 2D elements");
2150 break;
2151 }
2152
2153 cnt += nedges * fnp;
2154 cnt1 += nedges * tnp;
2155 }
2156 }
2157}
2158
2159/**
2160 * @brief Interpolate global trace edge to local trace edges point
2161 * distributions where required.
2162 *
2163 * @param dir Selects forwards (0) or backwards (1) direction.
2164 * @param locfaces Local trace edge storage.
2165 * @param faces Global trace edge storage
2166 */
2168 const int dir, const Array<OneD, const NekDouble> &faces,
2169 Array<OneD, NekDouble> &locfaces)
2170{
2171 ASSERTL1(dir < 2, "option dir out of range, "
2172 " dir=0 is fwd, dir=1 is bwd");
2173
2174 int cnt = 0;
2175 int cnt1 = 0;
2176
2178
2179 // unshuffles trace into lcoally orientated format.
2180 Vmath::Gathr(static_cast<int>(m_locInterpTraceToTraceMap[dir].size()),
2181 faces.data(), m_locInterpTraceToTraceMap[dir].data(),
2182 tmp.data());
2183
2184 for (int i = 0; i < m_interpTrace[dir].size(); ++i)
2185 {
2186 // Check if there are faces to interpolate
2187 if (m_interpNtraces[dir][i])
2188 {
2189 // Get to/from points
2190 LibUtilities::PointsKey fromPointsKey0 =
2191 std::get<2>(m_interpPoints[dir][i]);
2192 LibUtilities::PointsKey fromPointsKey1 =
2193 std::get<3>(m_interpPoints[dir][i]);
2194 LibUtilities::PointsKey toPointsKey0 =
2195 std::get<0>(m_interpPoints[dir][i]);
2196 LibUtilities::PointsKey toPointsKey1 =
2197 std::get<1>(m_interpPoints[dir][i]);
2198
2199 int fnp0 = fromPointsKey0.GetNumPoints();
2200 int fnp1 = fromPointsKey1.GetNumPoints();
2201 int tnp0 = toPointsKey0.GetNumPoints();
2202 int tnp1 = toPointsKey1.GetNumPoints();
2203 int nfaces = m_interpNtraces[dir][i];
2204 int nfromfacepts = fnp0 * fnp1;
2205 int ntofacepts = tnp0 * tnp1;
2206
2207 // Do interpolation here if required
2208 switch (m_interpTrace[dir][i])
2209 {
2210 case eNoInterp: // Just copy
2211 {
2212 int fbegin0, fend0, fbegin1, fend1;
2213 int tbegin0, tend0, tbegin1, tend1;
2214 LibUtilities::GetEffectiveQuadRange(fromPointsKey0, fbegin0,
2215 fend0);
2216 LibUtilities::GetEffectiveQuadRange(toPointsKey0, tbegin0,
2217 tend0);
2218 LibUtilities::GetEffectiveQuadRange(fromPointsKey1, fbegin1,
2219 fend1);
2220 LibUtilities::GetEffectiveQuadRange(toPointsKey1, tbegin1,
2221 tend1);
2222 // overwrite end by size
2223 fend0 = fend0 - fbegin0;
2224 tend0 = tend0 - tbegin0;
2225 ASSERTL0(fend0 == tend0 &&
2226 fend1 - fbegin1 == tend1 - tbegin1,
2227 "Quad ranges mismatch in InterpTraceToLocFaces!");
2228 for (int j = 0; j < nfaces; ++j)
2229 {
2230 Vmath::Zero(ntofacepts,
2231 locfaces.data() + cnt1 + ntofacepts * j, 1);
2232 for (int k = fbegin1, l = tbegin1; k < fend1; ++k, ++l)
2233 {
2234 Vmath::Vcopy(fend0,
2235 tmp.data() + cnt + j * nfromfacepts +
2236 k * fnp0 + fbegin0,
2237 1,
2238 locfaces.data() + cnt1 +
2239 ntofacepts * j + l * tnp0 +
2240 tbegin0,
2241 1);
2242 }
2243 }
2244 }
2245 break;
2246 case eInterpDir0:
2247 {
2249 Blas::Dgemm('N', 'N', tnp0, tnp1 * nfaces, fnp0, 1.0,
2250 I0->GetPtr().data(), tnp0, tmp.data() + cnt,
2251 fnp0, 0.0, locfaces.data() + cnt1, tnp0);
2252 }
2253 break;
2254 case eInterpDir1:
2255 {
2257 for (int j = 0; j < nfaces; ++j)
2258 {
2259 Blas::Dgemm('N', 'T', tnp0, tnp1, fnp1, 1.0,
2260 tmp.data() + cnt + j * fnp0 * fnp1, tnp0,
2261 I1->GetPtr().data(), tnp1, 0.0,
2262 locfaces.data() + cnt1 + j * tnp0 * tnp1,
2263 tnp0);
2264 }
2265 }
2266 break;
2267 case eInterpEndPtDir0:
2268 {
2269 for (int j = 0; j < nfaces * tnp1; ++j)
2270 {
2271 Vmath::Vcopy(tnp0, tmp.data() + cnt + j * fnp0, 1,
2272 locfaces.data() + cnt1 + j * tnp0, 1);
2273 }
2274 }
2275 break;
2276 case eInterpEndPtDir1:
2277 {
2278 for (int j = 0; j < nfaces; ++j)
2279 {
2280 // copy all points missing off top verex in dir 1
2282 tnp0 * tnp1, tmp.data() + cnt + j * fnp0 * fnp1, 1,
2283 locfaces.data() + cnt1 + j * tnp0 * tnp1, 1);
2284 }
2285 }
2286 break;
2287 case eInterpBothDirs:
2288 {
2291 Array<OneD, NekDouble> wsp(nfaces * fnp0 * tnp1 * fnp0);
2292
2293 for (int j = 0; j < nfaces; ++j)
2294 {
2295 Blas::Dgemm('N', 'T', fnp0, tnp1, fnp1, 1.0,
2296 tmp.data() + cnt + j * fnp0 * fnp1, fnp0,
2297 I1->GetPtr().data(), tnp1, 0.0,
2298 wsp.data() + j * fnp0 * tnp1, fnp0);
2299 }
2300
2301 Blas::Dgemm('N', 'N', tnp0, tnp1 * nfaces, fnp0, 1.0,
2302 I0->GetPtr().data(), tnp0, wsp.data(), fnp0,
2303 0.0, locfaces.data() + cnt1, tnp0);
2304 }
2305 break;
2307 {
2309 for (int j = 0; j < nfaces; ++j)
2310 {
2311 Blas::Dgemm('N', 'T', tnp0, tnp1, fnp1, 1.0,
2312 tmp.data() + cnt + j * fnp0 * fnp1, fnp0,
2313 I1->GetPtr().data(), tnp1, 0.0,
2314 locfaces.data() + cnt1 + j * tnp0 * tnp1,
2315 tnp0);
2316 }
2317 }
2318 break;
2319 default:
2320 ASSERTL0(false, "Interpolation case not implemneted (yet)");
2321 break;
2322 }
2323 cnt += nfaces * nfromfacepts;
2324 cnt1 += nfaces * ntofacepts;
2325 }
2326 }
2327}
2328
2329/**
2330 * @brief Add contributions from trace coefficients to the elemental field
2331 * storage.
2332 *
2333 * @param trace Array of global trace coefficients.
2334 * @param field Array containing field coefficients storage.
2335 */
2338{
2339 int nvals = m_nTraceCoeffs[0] + m_nTraceCoeffs[1];
2340 for (int i = 0; i < nvals; ++i)
2341 {
2342 field[m_traceCoeffsToElmtMap[0][i]] +=
2344 trace[m_traceCoeffsToElmtTrace[0][i]];
2345 }
2346}
2347
2348/**
2349 * @brief Add contributions from backwards or forwards oriented trace
2350 * coefficients to the elemental field storage.
2351 *
2352 * @param dir Selects forwards (0) or backwards (1) direction
2353 * @param trace Array of global trace coefficients.
2354 * @param field Array containing field coefficients storage.
2355 */
2357 const int dir, const Array<OneD, const NekDouble> &trace,
2359{
2360 int nvals = m_nTraceCoeffs[dir];
2361 for (int i = 0; i < nvals; ++i)
2362 {
2363 field[m_traceCoeffsToElmtMap[dir][i]] +=
2364 m_traceCoeffsToElmtSign[dir][i] *
2365 trace[m_traceCoeffsToElmtTrace[dir][i]];
2366 }
2367}
2368
2369} // namespace Nektar::MultiRegions
#define ASSERTL0(condition, msg)
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
#define sign(a, b)
return the sign(b)*a
Definition Polylib.cpp:47
Defines a specification for a set of points.
Definition Points.h:50
PointsType GetPointsType() const
Definition Points.h:90
size_t GetNumPoints() const
Definition Points.h:85
Base class for all multi-elemental spectral/hp expansions.
Definition ExpList.h:99
const Collections::CollectionVector & GetCollections() const
This function returns collections.
Definition ExpList.h:1071
const Array< OneD, const std::pair< int, int > > & GetCoeffsToElmt() const
Get m_coeffs to elemental value map.
Definition ExpList.h:2199
int GetCoeff_Offset(int n) const
Get the start offset position for a local contiguous list of coeffs correspoinding to element n.
Definition ExpList.h:2159
int GetShapeDimension()
This function returns the dimension of the shape of the element eid.
Definition ExpList.h:1985
const std::shared_ptr< LocalRegions::ExpansionVector > GetExp() const
This function returns the vector of elements in the expansion.
Definition ExpList.h:2151
int GetPhys_Offset(int n) const
Get the start offset position for a local contiguous list of quadrature points in a full array corres...
Definition ExpList.h:2166
Array< OneD, Array< OneD, Array< OneD, int > > > m_traceCoeffToLeftRightExpCoeffMap
The map of every coeff from current trace to the left & right adjacent expasion coeffs.
Array< OneD, Array< OneD, int > > m_traceCoeffsToElmtSign
Sign array for mapping from forwards/backwards trace coefficients to local trace storage.
Array< OneD, Array< OneD, int > > m_interpNtraces
Number of edges/faces on a 2D/3D element that require interpolation.
Array< OneD, Array< OneD, int > > m_locTraceToElmtTraceMap
A mapping from the local elemental trace points, arranged as all forwards traces followed by backward...
void InterpLocEdgesToTraceTranspose(const int dir, const Array< OneD, const NekDouble > &edges, Array< OneD, NekDouble > &locedges)
Transpose of interp local edges to Trace methods.
void InterpLocTracesToTraceTranspose(const int dir, const Array< OneD, const NekDouble > &traces, Array< OneD, NekDouble > &loctraces)
Array< OneD, Array< OneD, int > > m_traceCoeffsToElmtTrace
Mapping from forwards/backwards trace coefficients to the position of the trace element in global sto...
Array< OneD, Array< OneD, int > > m_leftRightAdjacentExpId
The expansion ID that are the left & right adjacent to current trace.
LocTraceToTraceMap(const ExpList &locExp, const ExpListSharedPtr &trace, const Array< OneD, Array< OneD, LocalRegions::ExpansionSharedPtr > > &elmtToTrace, const std::vector< bool > &LeftAdjacents)
Set up trace to trace mapping components.
Array< OneD, Array< OneD, DNekMatSharedPtr > > m_interpFromTraceI1
Interpolation matrices for either 2D edges or first coordinate of 3D face using going "from' to 'to' ...
Array< OneD, Array< OneD, Array< OneD, NekDouble > > > m_interpEndPtI0
Mapping to hold first coordinate direction endpoint interpolation, which can be more optimal if using...
void LocTracesFromField(const Array< OneD, const NekDouble > &field, Array< OneD, NekDouble > faces)
Gather the local elemental traces in physical space from field using m_locTraceToFieldMap....
void CalcLocTracePhysToTraceIDMap_3D(const ExpListSharedPtr &tracelist)
int m_nLocTracePts
The number of local trace points.
void InterpLocEdgesToTrace(const int dir, const Array< OneD, const NekDouble > &locfaces, Array< OneD, NekDouble > &edges)
Interpolate local trace edges to global trace edge point distributions where required.
int m_nTracePts
The number of global trace points.
void UnshuffleLocTraces(const int dir, const Array< OneD, const NekDouble > &loctraces, Array< OneD, NekDouble > unshuffle)
Unshuffle local elemental traces in physical space from similar faces points are blocked together to ...
void InterpLocTracesToTrace(const int dir, const Array< OneD, const NekDouble > &loctraces, Array< OneD, NekDouble > &traces)
Array< OneD, Array< OneD, bool > > m_leftRightAdjacentExpFlag
Flag indicates whether the expansion that are the left & right adjacent to current trace exists.
void CalcLocTracePhysToTraceIDMap(const ExpListSharedPtr &tracelist, const int ndim)
void AddLocTracesToField(const Array< OneD, const NekDouble > &faces, Array< OneD, NekDouble > &field)
Reverse process of LocTracesFromField() Add the local traces in physical space to field using m_locTr...
int m_nTraceCoeffs[2]
Number of forwards/backwards trace coefficients.
int m_nFwdLocTracePts
The number of forward trace points. A local trace element is ‘forward’ if it is the side selected for...
Array< OneD, TraceFieldMapEssential > m_traceFieldMap
Array< OneD, Array< OneD, Array< OneD, int > > > m_traceCoeffToLeftRightExpCoeffSign
The sign of every coeff from current trace to the left & right adjacent expasion coeffs.
void InterpTraceToLocFaces(const int dir, const Array< OneD, const NekDouble > &faces, Array< OneD, NekDouble > &locfaces)
Interpolate global trace edge to local trace edges point distributions where required.
Array< OneD, Array< OneD, Array< OneD, NekDouble > > > m_interpEndPtI1
Mapping to hold second coordinate direction endpoint interpolation, which can be more optimal if usin...
void TraceLocToElmtLocCoeffMap(const ExpList &locExp, const ExpListSharedPtr &trace)
Set up maps between coefficients on trace and in cells.
Array< OneD, Array< OneD, int > > m_traceCoeffsToElmtMap
Mapping from forwards/backwards trace coefficients to elemental coefficient storage.
int m_expdim
Expansion Dimension we have setup for trace mapping.
Array< OneD, Array< OneD, InterpLocTraceToTrace > > m_interpTrace
A mapping holding the type of interpolation needed for each local trace. Dimension 0 holds forward tr...
void FwdLocTracesFromField(const Array< OneD, const NekDouble > &field, Array< OneD, NekDouble > faces)
Gather the forwards-oriented local traces in physical space from field using m_locTraceToFieldMap.
Array< OneD, Array< OneD, int > > m_locInterpTraceToTraceMap
A mapping from local trace points to the global trace. Dimension 0 holds forward traces,...
void InterpTraceToLocEdges(const int dir, const Array< OneD, const NekDouble > &edges, Array< OneD, NekDouble > &locedges)
Interpolate global trace edge to local trace edges point distributions where required.
Array< OneD, Array< OneD, int > > m_ElemNeighbsId
Array< OneD, Array< OneD, TraceInterpPoints > > m_interpPoints
Interpolation points key distributions to each of the local to global mappings.
Array< OneD, int > m_locTraceToFieldMap
A mapping from the local elemental trace points, arranged as all forwards traces followed by backward...
Array< OneD, Array< OneD, int > > m_interpTracePtsEntry
start entry of each global trace in m_locInterpTraceToTraceMap, referenced by element and trace id
Array< OneD, Array< OneD, DNekMatSharedPtr > > m_interpFromTraceI0
Interpolation matrices for either 2D edges or first coordinate of 3D face using going "from' to 'to' ...
Array< OneD, TraceInterpEssential > m_traceInterp
void AddTraceCoeffsToFieldCoeffs(const Array< OneD, const NekDouble > &trace, Array< OneD, NekDouble > &field)
Add contributions from trace coefficients to the elemental field storage.
void InterpLocFacesToTraceTranspose(const int dir, const Array< OneD, const NekDouble > &traces, Array< OneD, NekDouble > &loctraces)
Transpose of interp local faces to Trace methods.
Array< OneD, Array< OneD, int > > m_locTracePtsEntry
start entry of each local trace in m_locTraceToFieldMap, referenced by element and trace id
Array< OneD, Array< OneD, DNekMatSharedPtr > > m_interpTraceI1
Interpolation matrices for the second coordinate of 3D face, not used in 2D.
Array< OneD, Array< OneD, DNekMatSharedPtr > > m_interpTraceI0
Interpolation matrices for either 2D edges or first coordinate of 3D face.
Array< OneD, Array< OneD, int > > m_traceCoeffsEntry
start entry of each global trace in m_traceCoeffsToElmtMap, referenced by element and trace id
const TraceFieldMapEssential & GetTraceFieldMapEssential(const int cid)
void FindElmtNeighbors(const ExpList &locExp, const ExpListSharedPtr &trace)
void InterpTraceToLocTrace(const int dir, const Array< OneD, NekDouble > &traces, Array< OneD, NekDouble > &loctraces)
Array< OneD, Array< OneD, int > > m_interpTraceIndex
subscript of m_interpTrace, referenced by element and trace id
void ReshuffleLocTracesForInterp(const int dir, const Array< OneD, const NekDouble > &loctraces, Array< OneD, NekDouble > reshuffle)
Reshuffle local elemental traces in physical space so that similar faces points are blocked together ...
void CalcLocTracePhysToTraceIDMap_2D(const ExpListSharedPtr &tracelist)
Array< OneD, Array< OneD, int > > m_LocTracephysToTraceIDMap
void InterpLocFacesToTrace(const int dir, const Array< OneD, const NekDouble > &locfaces, Array< OneD, NekDouble > faces)
Interpolate local faces to trace face point distributions where required.
const TraceInterpEssential & GetTraceInterpEssential(const int cid)
static void Dgemv(const char &trans, const int &m, const int &n, const double &alpha, const double *a, const int &lda, const double *x, const int &incx, const double &beta, double *y, const int &incy)
BLAS level 2: Matrix vector multiply y = alpha A x plus beta y where A[m x n].
Definition Blas.hpp:211
static double Ddot(const int &n, const double *x, const int &incx, const double *y, const int &incy)
BLAS level 1: output = .
Definition Blas.hpp:163
static void Dgemm(const char &transa, const char &transb, const int &m, const int &n, const int &k, const double &alpha, const double *a, const int &lda, const double *b, const int &ldb, const double &beta, double *c, const int &ldc)
BLAS level 3: Matrix-matrix multiply C = A x B where op(A)[m x k], op(B)[k x n], C[m x n] DGEMM perfo...
Definition Blas.hpp:383
void GetEffectiveQuadRange(const LibUtilities::PointsKey &pkey, int &q_begin, int &q_end)
static const BasisKey NullBasisKey(eNoBasisType, 0, NullPointsKey)
Defines a null basis with no type or points.
PointsManagerT & PointsManager(void)
@ eGaussLegendreWithMP
1D Gauss-Legendre quadrature points with additional x=-1 and x=1 end points
Definition PointsType.h:95
@ eGaussLobattoLegendre
1D Gauss-Lobatto-Legendre quadrature points
Definition PointsType.h:51
@ eGaussLegendreWithM
1D Gauss-Legendre quadrature points with additional x=-1 point
Definition PointsType.h:97
@ P
Monomial polynomials .
Definition BasisType.h:62
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition Expansion.h:66
std::tuple< LibUtilities::PointsKey, LibUtilities::PointsKey, LibUtilities::PointsKey, LibUtilities::PointsKey > TraceInterpPoints
Map holding points distributions required for interpolation of local traces onto global trace in two ...
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
static const NekDouble kNekZeroTol
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
std::shared_ptr< DNekMat > DNekMatSharedPtr
void Gathr(I n, const T *x, const I *y, T *z)
Gather vector z[i] = x[y[i]].
Definition Vmath.hpp:507
void Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Svtvp (scalar times vector plus vector): z = alpha*x + y.
Definition Vmath.hpp:396
void Scatr(int n, const T *x, const int *y, T *z)
Scatter vector z[y[i]] = x[i].
Definition Vmath.hpp:539
void Assmb(int n, const T *x, const int *y, T *z)
Assemble z[y[i]] += x[i]; z should be zero'd first.
Definition Vmath.hpp:577
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition Vmath.hpp:180
void Zero(int n, T *x, const int incx)
Zero vector.
Definition Vmath.hpp:273
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition Vmath.hpp:54
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition Vmath.hpp:825
STL namespace.
scalarT< T > abs(scalarT< T > in)
Definition scalar.hpp:295