Nektar++
Loading...
Searching...
No Matches
StdExpansion3D.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: StdExpansion3D.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: Daughter of StdExpansion. This class contains routine
32// which are common to 3D expansion. Typically this inolves physiocal
33// space operations.
34//
35///////////////////////////////////////////////////////////////////////////////
36
38
43
44#ifdef max
45#undef max
46#endif
47
48namespace Nektar::StdRegions
49{
50// Declaretion of scalar routine
53
55 [[maybe_unused]] int numcoeffs,
56 [[maybe_unused]] const LibUtilities::BasisKey &Ba,
57 [[maybe_unused]] const LibUtilities::BasisKey &Bb,
58 [[maybe_unused]] const LibUtilities::BasisKey &Bc)
59{
60}
61
66 const Array<OneD, const NekDouble> &inarray,
68 const bool Deformed, [[maybe_unused]] bool CollDir0,
69 [[maybe_unused]] bool CollDir1, [[maybe_unused]] bool CollDir2)
70{
71 v_IProductWRTBaseKernel(base0, base1, base2, inarray, outarray, jac,
72 Deformed, CollDir0, CollDir1, CollDir2);
73}
74
76{
77 ASSERTL1((dir == 0) || (dir == 1) || (dir == 2), "Invalid direction.");
78
79 const int nq0 = m_base[0]->GetNumPoints();
80 const int nq1 = m_base[1]->GetNumPoints();
81 const int nq2 = m_base[2]->GetNumPoints();
82 const int nq = nq0 * nq1 * nq2;
83
84 const bool CollDir0 = m_base[0]->Collocation();
85 const bool CollDir1 = m_base[1]->Collocation();
86 const bool CollDir2 = m_base[2]->Collocation();
87
88 Array<OneD, NekDouble> in(nq, 0.0);
90 Array<OneD, NekDouble> one(1, 1.0);
91
92 for (int i = 0; i < nq; i++)
93 {
94 int l = i % nq0;
95 int m = (i / nq0) % nq1;
96 int n = i / (nq0 * nq1);
97
98 // initialise with inverse of weights t
99 in[i] = 1.0 / (m_weights[0][l] * m_weights[1][m] * m_weights[2][n]);
100
101 // do standard iproduct
102 if (dir == 0)
103 {
104 v_IProductWRTBaseKernel(m_base[0]->GetDbdata(),
105 m_base[1]->GetBdata(),
106 m_base[2]->GetBdata(), in, out, one, false,
107 false, CollDir1, CollDir2);
108 }
109 else if (dir == 1)
110 {
111 v_IProductWRTBaseKernel(m_base[0]->GetBdata(),
112 m_base[1]->GetDbdata(),
113 m_base[2]->GetBdata(), in, out, one, false,
114 CollDir0, false, CollDir2);
115 }
116 else // dir == 2
117 {
118 v_IProductWRTBaseKernel(m_base[0]->GetBdata(),
119 m_base[1]->GetBdata(),
120 m_base[2]->GetDbdata(), in, out, one, false,
121 CollDir0, CollDir1, false);
122 }
123 in[i] = 0.0;
124
125 for (int j = 0; j < m_ncoeffs; j++)
126 {
127 (*mat)(j, i) = out[j];
128 }
129 }
130}
131
135{
136 const int nquad0 = m_base[0]->GetNumPoints();
137 const int nquad1 = m_base[1]->GetNumPoints();
138 const int nquad2 = m_base[2]->GetNumPoints();
139
140 bool Deriv0 = (out_d0.size() > 0);
141 bool Deriv1 = (out_d1.size() > 0);
142 bool Deriv2 = (out_d2.size() > 0);
143 const NekDouble *D0 = m_base[0]->GetD()->GetRawPtr();
144 const NekDouble *D1 = m_base[1]->GetD()->GetRawPtr();
145 const NekDouble *D2 = m_base[2]->GetD()->GetRawPtr();
146
148 // copy inarray data if inarray and outarray are the same.
149 if ((inarray.data() == out_d0.data()) ||
150 (inarray.data() == out_d1.data()) || (inarray.data() == out_d2.data()))
151 {
152 Array<OneD, NekDouble> wsp(nquad0 * nquad1 * nquad2);
153 CopyArray(inarray, wsp);
154 intmp = wsp;
155 }
156 else
157 {
158 intmp = inarray;
159 }
160
161 // Switch statment using boost_pp and macros. This unfolls into a
162 // nested switch statement which runs from SMIN to SMAX for quadratrure
163 // order. If you want to see it unwrapped compile in verbose mode and add
164 // --preprocess to the c++ command. Default case
165#undef PHYSDERIV_DEF
166#define PHYSDERIV_DEF \
167 PhysDerivTensor3DKernel(nquad0, nquad1, nquad2, \
168 (const vec_t *)intmp.data(), (const vec_t *)D0, \
169 (const vec_t *)D1, (const vec_t *)D2, \
170 (vec_t *)out_d0.data(), (vec_t *)out_d1.data(), \
171 (vec_t *)out_d2.data(), Deriv0, Deriv1, Deriv2)
172
173 // Loop case over quarature points
174#undef PHYSDERIV_Q
175#define PHYSDERIV_Q(r, i) \
176 case NQ1(i): \
177 PhysDerivTensor3DKernel( \
178 NQ1(i), NQ1(i), NQ1(i), (const vec_t *)intmp.data(), \
179 (const vec_t *)D0, (const vec_t *)D1, (const vec_t *)D2, \
180 (vec_t *)out_d0.data(), (vec_t *)out_d1.data(), \
181 (vec_t *)out_d2.data(), Deriv0, Deriv1, Deriv2); \
182 break;
183
184 // templated cases on standard quadrature
185 // usage where quad order goes from SMIN to SMAX
186 if ((nquad0 == nquad1) && (nquad1 == nquad2))
187 {
188 switch (nquad0)
189 {
190 BOOST_PP_FOR((SMIN, SMAX), STDLEV1TEST, STDLEV1UPDATE, PHYSDERIV_Q);
191 default:
193 break;
194 }
195 }
196 else
197 {
199 }
200}
201
203 const Array<OneD, const NekDouble> &inarray,
204 Array<OneD, NekDouble> &outarray)
205{
206 switch (dir)
207 {
208 case 0:
209 {
210 v_PhysDeriv(inarray, outarray, NullNekDouble1DArray,
212 break;
213 }
214
215 case 1:
216 {
217 v_PhysDeriv(inarray, NullNekDouble1DArray, outarray,
219 break;
220 }
221
222 case 2:
223 {
225 outarray);
226 break;
227 }
228
229 default:
230 {
231 ASSERTL1(false, "input dir is out of range");
232 }
233 break;
234 }
235}
236
238 const Array<OneD, const NekDouble> &coords,
239 const Array<OneD, const NekDouble> &physvals)
240{
242
243 WARNINGL2(coords[0] >= -1 - NekConstants::kNekZeroTol, "coord[0] < -1");
244 WARNINGL2(coords[0] <= 1 + NekConstants::kNekZeroTol, "coord[0] > 1");
245 WARNINGL2(coords[1] >= -1 - NekConstants::kNekZeroTol, "coord[1] < -1");
246 WARNINGL2(coords[1] <= 1 + NekConstants::kNekZeroTol, "coord[1] > 1");
247 WARNINGL2(coords[2] >= -1 - NekConstants::kNekZeroTol, "coord[2] < -1");
248 WARNINGL2(coords[2] <= 1 + NekConstants::kNekZeroTol, "coord[2] > 1");
249
250 // Obtain local collapsed coordinate from Cartesian coordinate.
251 LocCoordToLocCollapsed(coords, eta);
252
253 const int nq0 = m_base[0]->GetNumPoints();
254 const int nq1 = m_base[1]->GetNumPoints();
255 const int nq2 = m_base[2]->GetNumPoints();
256
257 Array<OneD, NekDouble> wsp1(nq1 * nq2), wsp2(nq2);
258
259 // Construct the 2D square...
260 const NekDouble *ptr = &physvals[0];
261 for (int i = 0; i < nq1 * nq2; ++i, ptr += nq0)
262 {
263 wsp1[i] = StdExpansion::BaryEvaluate<0>(eta[0], ptr);
264 }
265
266 for (int i = 0; i < nq2; ++i)
267 {
268 wsp2[i] = StdExpansion::BaryEvaluate<1>(eta[1], &wsp1[i * nq1]);
269 }
270
271 return StdExpansion::BaryEvaluate<2>(eta[2], &wsp2[0]);
272}
273
274/**
275 * \f$
276 * \begin{array}{rcl}
277 * I_{pqr} = (\phi_{pqr}, u)_{\delta} & = &
278 * \sum_{i=0}^{nq_0} \sum_{j=0}^{nq_1} \sum_{k=0}^{nq_2}
279 * \psi_{p}^{a}(\xi_{1i}) \psi_{q}^{a}(\xi_{2j}) \psi_{r}^{a}(\xi_{3k})
280 * w_i w_j w_k u(\xi_{1,i} \xi_{2,j} \xi_{3,k})
281 *
282 * J_{i,j,k}\\ & = & \sum_{i=0}^{nq_0} \psi_p^a(\xi_{1,i})
283 * \sum_{j=0}^{nq_1} \psi_{q}^a(\xi_{2,j})
284 * \sum_{k=0}^{nq_2} \psi_{r}^a
285 * u(\xi_{1i},\xi_{2j},\xi_{3k}) J_{i,j,k}
286 * \end{array} \f$ \n
287 * where
288 * \f$ \phi_{pqr} (\xi_1 , \xi_2 , \xi_3)
289 * = \psi_p^a( \xi_1) \psi_{q}^a(\xi_2) \psi_{r}^a(\xi_3) \f$ \n
290 * which can be implemented as \n
291 * \f$f_{r} (\xi_{3k})
292 * = \sum_{k=0}^{nq_3} \psi_{r}^a u(\xi_{1i},\xi_{2j}, \xi_{3k})
293 * J_{i,j,k} = {\bf B_3 U} \f$ \n
294 * \f$ g_{q} (\xi_{3k})
295 * = \sum_{j=0}^{nq_1} \psi_{q}^a(\xi_{2j}) f_{r}(\xi_{3k})
296 * = {\bf B_2 F} \f$ \n
297 * \f$ (\phi_{pqr}, u)_{\delta}
298 * = \sum_{k=0}^{nq_0} \psi_{p}^a (\xi_{3k}) g_{q} (\xi_{3k})
299 * = {\bf B_1 G} \f$
300 *
301 * @param inarray Physical space function definition
302 * @param outarray Inner product with respect to basis
303 *
304 *
305 * This is a wrapper function around \a IProductWRTBaseKernel()
306 */
308 const Array<OneD, const NekDouble> &inarray,
309 Array<OneD, NekDouble> &outarray)
310{
311 const bool CollDir0 = m_base[0]->Collocation();
312 const bool CollDir1 = m_base[1]->Collocation();
313 const bool CollDir2 = m_base[2]->Collocation();
314
315 if (CollDir0 && CollDir1 && CollDir2)
316 {
317 MultiplyByStdQuadratureMetric(inarray, outarray);
318 }
319 else
320 {
321 const Array<OneD, const NekDouble> one(1, 1.0);
322 v_IProductWRTBaseKernel(m_base[0]->GetBdata(), m_base[1]->GetBdata(),
323 m_base[2]->GetBdata(), inarray, outarray, one,
324 false, CollDir0, CollDir1, CollDir2);
325 }
326}
327
330 const Array<OneD, const NekDouble> &physvals)
331{
332 NekDouble value;
333
334 int Qx = m_base[0]->GetNumPoints();
335 int Qy = m_base[1]->GetNumPoints();
336 int Qz = m_base[2]->GetNumPoints();
337
338 Array<OneD, NekDouble> sumFactorization_qr =
339 Array<OneD, NekDouble>(Qy * Qz);
340 Array<OneD, NekDouble> sumFactorization_r = Array<OneD, NekDouble>(Qz);
341
342 // Lagrangian interpolation matrix
343 NekDouble *interpolatingNodes = nullptr;
344
345 // Interpolate first coordinate direction
346 interpolatingNodes = &I[0]->GetPtr()[0];
347
348 Blas::Dgemv('T', Qx, Qy * Qz, 1.0, &physvals[0], Qx, &interpolatingNodes[0],
349 1, 0.0, &sumFactorization_qr[0], 1);
350
351 // Interpolate in second coordinate direction
352 interpolatingNodes = &I[1]->GetPtr()[0];
353
354 Blas::Dgemv('T', Qy, Qz, 1.0, &sumFactorization_qr[0], Qy,
355 &interpolatingNodes[0], 1, 0.0, &sumFactorization_r[0], 1);
356
357 // Interpolate in third coordinate direction
358 interpolatingNodes = &I[2]->GetPtr()[0];
359 value = Vmath::Dot(Qz, interpolatingNodes, 1, &sumFactorization_r[0], 1);
360
361 return value;
362}
363
365 const Array<OneD, const NekDouble> &inarray,
366 Array<OneD, NekDouble> &outarray)
367{
368 int nquad0 = m_base[0]->GetNumPoints();
369 int nquad1 = m_base[1]->GetNumPoints();
370 int nquad2 = m_base[2]->GetNumPoints();
371
372 int cnt = 0;
373 for (int i = 0; i < nquad2; ++i)
374 {
375 NekDouble w2 = m_weights[2][i];
376 for (int j = 0; j < nquad1; ++j)
377 {
378 NekDouble w1w2 = m_weights[1][j] * w2;
379 for (int k = 0; k < nquad0; ++k, ++cnt)
380 {
381 outarray[cnt] = inarray[cnt] * m_weights[0][k] * w1w2;
382 }
383 }
384 }
385}
386
387/**
388 * @param inarray Input coefficients.
389 * @param output Output coefficients.
390 * @param mkey Matrix key
391 */
393 const Array<OneD, const NekDouble> &inarray,
395{
396 if (mkey.GetNVarCoeff() == 0 &&
399 {
400 // This implementation is only valid when there are no
401 // coefficients associated to the Laplacian operator
402 int nqtot = GetTotPoints();
403
404 // Allocate temporary storage
405 Array<OneD, NekDouble> wsp0(7 * nqtot);
406 Array<OneD, NekDouble> wsp1(wsp0 + nqtot);
407
408 if (!(m_base[0]->Collocation() && m_base[1]->Collocation() &&
409 m_base[2]->Collocation()))
410 {
411 // LAPLACIAN MATRIX OPERATION
412 // wsp0 = u = B * u_hat
413 // wsp1 = du_dxi1 = D_xi1 * wsp0 = D_xi1 * u
414 // wsp2 = du_dxi2 = D_xi2 * wsp0 = D_xi2 * u
415 BwdTrans(inarray, wsp0);
416 LaplacianMatrixOp_MatFree_Kernel(wsp0, outarray, wsp1);
417 }
418 else
419 {
420 LaplacianMatrixOp_MatFree_Kernel(inarray, outarray, wsp1);
421 }
422 }
423 else
424 {
426 mkey);
427 }
428}
429
431 const Array<OneD, const NekDouble> &inarray,
433{
434 if (mkey.GetNVarCoeff() == 0 &&
436 {
437 using std::max;
438
439 int nquad0 = m_base[0]->GetNumPoints();
440 int nquad1 = m_base[1]->GetNumPoints();
441 int nquad2 = m_base[2]->GetNumPoints();
442 int nmodes0 = m_base[0]->GetNumModes();
443 int nmodes1 = m_base[1]->GetNumModes();
444 int nmodes2 = m_base[2]->GetNumModes();
445 int wspsize = max(nquad0 * nmodes2 * (nmodes1 + nquad1),
446 nquad0 * nquad1 * (nquad2 + nmodes0) +
447 nmodes0 * nmodes1 * nquad2);
448
450
451 Array<OneD, NekDouble> wsp0(8 * wspsize);
452 Array<OneD, NekDouble> wsp1(wsp0 + 1 * wspsize);
453 Array<OneD, NekDouble> wsp2(wsp0 + 2 * wspsize);
454
455 if (!(m_base[0]->Collocation() && m_base[1]->Collocation() &&
456 m_base[2]->Collocation()))
457 {
458 // MASS MATRIX OPERATION
459 // The following is being calculated:
460 // wsp0 = B * u_hat = u
461 // wsp1 = W * wsp0
462 // outarray = B^T * wsp1 = B^T * W * B * u_hat = M * u_hat
463 BwdTrans(inarray, wsp0);
464 IProductWRTBase(wsp0, outarray);
465 LaplacianMatrixOp_MatFree_Kernel(wsp0, wsp1, wsp2);
466 }
467 else
468 {
469 // specialised implementation for the classical spectral
470 // element method
471 MultiplyByQuadratureMetric(inarray, outarray);
472 LaplacianMatrixOp_MatFree_Kernel(inarray, wsp1, wsp2);
473 }
474
475 // outarray = lambda * outarray + wsp1
476 // = (lambda * M + L ) * u_hat
477 Vmath::Svtvp(m_ncoeffs, lambda, &outarray[0], 1, &wsp1[0], 1,
478 &outarray[0], 1);
479 }
480 else
481 {
483 mkey);
484 }
485}
486
488{
489 NEKERROR(ErrorUtil::efatal, "This function is not valid or not defined");
490 return 0;
491}
492
493int StdExpansion3D::v_GetEdgeNcoeffs([[maybe_unused]] const int i) const
494{
495 NEKERROR(ErrorUtil::efatal, "This function is not valid or not defined");
496 return 0;
497}
498
500 [[maybe_unused]] const int tid,
501 [[maybe_unused]] Array<OneD, unsigned int> &maparray,
502 [[maybe_unused]] Array<OneD, int> &signarray,
503 [[maybe_unused]] Orientation traceOrient)
504{
505 NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape");
506}
507
510 Array<OneD, int> &signarray,
511 Orientation traceOrient, int P,
512 int Q)
513{
514 Array<OneD, unsigned int> map1, map2;
515 GetTraceCoeffMap(tid, map1);
516 GetElmtTraceToTraceMap(tid, map2, signarray, traceOrient, P, Q);
517
518 if (maparray.size() != map2.size())
519 {
520 maparray = Array<OneD, unsigned int>(map2.size());
521 }
522
523 for (int i = 0; i < map2.size(); ++i)
524 {
525 maparray[i] = map1[map2[i]];
526 }
527}
528
529/**
530 * @brief This method produces a mapping @param idmap which
531 * reorientates face data according to the input parameter @param
532 * Orient. The sign convention is assumed to take the element local
533 * face to a global trace face and this is denoted by the boolean
534 * Forwards, i..e globaltrace[i] = localtrace[idmap[i]]. If the
535 * boolean is set to Forwards == false then a mapping is produced
536 * which maps the gloabl trace back to the local elemental trace such that
537 * localtrace[i] = globaltrace[idmap[i]].
538 */
540 const StdRegions::Orientation orient, Array<OneD, int> &idmap,
541 const int nq0, const int nq1, bool Forwards)
542{
543 if (idmap.size() != nq0 * nq1)
544 {
545 idmap = Array<OneD, int>(nq0 * nq1);
546 }
547
548 switch (orient)
549 {
550 case StdRegions::eDir1FwdDir1_Dir2FwdDir2: // Used in Tri & Quad faces
551 // eseentially straight copy
552 for (int i = 0; i < nq0 * nq1; ++i)
553 {
554 idmap[i] = i;
555 }
556 break;
557 case StdRegions::eDir1BwdDir1_Dir2FwdDir2: // Used in Tri & Quad faces
558 {
559 // Direction A negative and B positive
560 for (int j = 0; j < nq1; j++)
561 {
562 for (int i = 0; i < nq0; ++i)
563 {
564 idmap[j * nq0 + i] = nq0 - 1 - i + j * nq0;
565 }
566 }
567 }
568 break;
570 {
571 // Direction A positive and B negative
572 for (int j = 0; j < nq1; j++)
573 {
574 for (int i = 0; i < nq0; ++i)
575 {
576 idmap[j * nq0 + i] = nq0 * (nq1 - 1 - j) + i;
577 }
578 }
579 }
580 break;
582 {
583 // Direction A negative and B negative
584 for (int j = 0; j < nq1; j++)
585 {
586 for (int i = 0; i < nq0; ++i)
587 {
588 idmap[j * nq0 + i] = nq0 * nq1 - 1 - j * nq0 - i;
589 }
590 }
591 }
592 break;
594 {
595 // Transposed, Direction A and B positive
596 if (Forwards)
597 {
598 for (int i = 0; i < nq0; ++i)
599 {
600 for (int j = 0; j < nq1; ++j)
601 {
602 idmap[i * nq1 + j] = i + j * nq0;
603 }
604 }
605 }
606 else // inverse case - different if nq0 != nq1
607 {
608 for (int j = 0; j < nq1; ++j)
609 {
610 for (int i = 0; i < nq0; ++i)
611 {
612 idmap[j * nq0 + i] = i * nq1 + j;
613 }
614 }
615 }
616 }
617 break;
619 {
620 // Transposed, Direction A positive with mapped direction
621 // B and direction B negative with mapped direction A
622 if (Forwards)
623 {
624 for (int i = 0; i < nq0; ++i)
625 {
626 for (int j = 0; j < nq1; ++j)
627 {
628 idmap[i * nq1 + j] = i + nq0 * (nq1 - 1) - j * nq0;
629 }
630 }
631 }
632 else
633 {
634 for (int j = 0; j < nq1; ++j)
635 {
636 for (int i = 0; i < nq0; ++i)
637 {
638 idmap[j * nq0 + i] = nq1 - 1 - j + i * nq1;
639 }
640 }
641 }
642 }
643 break;
645 {
646 // Transposed, Direction A negative with mapped directon B and
647 // direction B positive with mapped direction A
648 if (Forwards)
649 {
650 for (int i = 0; i < nq0; ++i)
651 {
652 for (int j = 0; j < nq1; ++j)
653 {
654 idmap[i * nq1 + j] = nq0 - 1 - i + j * nq0;
655 }
656 }
657 }
658 else
659 {
660 for (int j = 0; j < nq1; ++j)
661 {
662 for (int i = 0; i < nq0; ++i)
663 {
664 idmap[j * nq0 + i] = nq1 * (nq0 - 1) - i * nq1 + j;
665 }
666 }
667 }
668 }
669 break;
671 {
672 // Transposed, Direction A and B negative
673 if (Forwards)
674 {
675 for (int i = 0; i < nq0; ++i)
676 {
677 for (int j = 0; j < nq1; ++j)
678 {
679 idmap[i * nq1 + j] = nq0 * nq1 - 1 - i - j * nq0;
680 }
681 }
682 }
683 else
684 {
685 for (int j = 0; j < nq1; ++j)
686 {
687 for (int i = 0; i < nq0; ++i)
688 {
689 idmap[j * nq0 + i] = nq0 * nq1 - 1 - j - i * nq1;
690 }
691 }
692 }
693 }
694 break;
695 default:
696 ASSERTL0(false, "Unknow orientation");
697 break;
698 }
699}
700
702 [[maybe_unused]] const int facedir,
703 const LibUtilities::BasisSharedPtr &faceDirBasis)
704{
705 auto faceDirBasisType = faceDirBasis->GetBasisType();
706 auto pointsType = faceDirBasis->GetPointsType();
707 auto nummodes = faceDirBasis->GetNumModes();
708 auto numpoints = faceDirBasis->GetNumPoints();
709
710 switch (faceDirBasisType)
711 {
715 {
717 switch (pointsType)
718 {
720 case LibUtilities::eGaussRadauMAlpha2Beta0:
721 case LibUtilities::eGaussRadauMAlpha1Beta0:
722 {
723 numpoints = numpoints + 1;
725 }
726 break;
728 {
729 numpoints = numpoints + 1;
731 }
732 break;
733 default: // do not change points
734 {
735 pType = faceDirBasis->GetPointsType();
736 }
737 }
738 const LibUtilities::PointsKey pkey(numpoints, pType);
740 pkey);
741 }
743 {
744 const LibUtilities::PointsKey pkey(
747 pkey);
748 }
752 {
754 switch (pointsType)
755 {
757 case LibUtilities::eGaussRadauMAlpha2Beta0:
758 case LibUtilities::eGaussRadauMAlpha1Beta0:
759 {
760 numpoints = numpoints + 1;
762 }
763 break;
765 {
766 numpoints = numpoints + 1;
768 }
769 break;
770 default: // do not change points
771 {
772 pType = faceDirBasis->GetPointsType();
773 break;
774 }
775 }
776 const LibUtilities::PointsKey pkey(numpoints, pType);
778 pkey);
779 }
780 default:
781 {
782 NEKERROR(ErrorUtil::efatal, "expansion type unknown");
783 break;
784 }
785 }
786
787 // Keep things happy by returning a value.
789}
790
792 const int facedir, const LibUtilities::BasisSharedPtr &faceDirBasis,
793 bool UseGLL)
794{
795 auto faceDirBasisType = faceDirBasis->GetBasisType();
796 auto pointsType = faceDirBasis->GetPointsType();
797 auto nummodes = faceDirBasis->GetNumModes();
798 auto numpoints = faceDirBasis->GetNumPoints();
799
800 switch (faceDirBasisType)
801 {
806 {
809 switch (facedir) // determine the basis type
810 {
811 case 0:
812 {
814
815 switch (pointsType) // determine the points type
816 {
818 // case LibUtilities::eGaussRadauMAlpha2Beta0: don't
819 // this this is posssible
820 case LibUtilities::eGaussRadauMAlpha1Beta0:
821 {
823 numpoints + 1,
825 }
826 break;
828 {
830 numpoints + 1,
832 }
833 break;
834 default: // For other points type, just return the
835 // points key
836 {
837 pkey = faceDirBasis->GetPointsKey();
838 }
839 }
840 }
841 break;
842 case 1: // this never appears together with Modified_A
843 {
845
846 switch (pointsType) // determine the points type
847 {
849 case LibUtilities::eGaussRadauMAlpha2Beta0:
850 case LibUtilities::eGaussRadauMAlpha1Beta0:
851 {
852 if (UseGLL) // force to use GLL
853 {
855 numpoints + 1,
857 }
858 else
859 {
861 numpoints,
862 LibUtilities::eGaussRadauMAlpha1Beta0);
863 }
864 }
865 break;
866 default: // For other points type, just return the
867 // points key
868 {
869 pkey = faceDirBasis->GetPointsKey();
870 }
871 }
872 }
873 break;
874 default:
875 {
876 NEKERROR(ErrorUtil::efatal, "invalid value to flag");
877 break;
878 }
879 }
880 return LibUtilities::BasisKey(bType, nummodes, pkey);
881 }
882
884 {
885 switch (facedir)
886 {
887 case 0:
888 {
889 const LibUtilities::PointsKey pkey(
892 nummodes, pkey);
893 }
894 break;
895 case 1:
896 {
897 const LibUtilities::PointsKey pkey(
898 numpoints, LibUtilities::eGaussRadauMAlpha1Beta0);
900 nummodes, pkey);
901 }
902 break;
903 default:
904 {
905 NEKERROR(ErrorUtil::efatal, "invalid value to flag");
906 break;
907 }
908 }
909 break;
910 }
911
916 {
919 switch (facedir) // determine the basis type
920 {
921 case 0:
922 {
924
925 switch (pointsType) // determine the points type
926 {
928 case LibUtilities::eGaussRadauMAlpha2Beta0:
929 case LibUtilities::eGaussRadauMAlpha1Beta0:
930 {
932 numpoints + 1,
934 }
935 break;
937 {
939 numpoints + 1,
941 }
942 break;
943 default: // For other points type, just return the
944 // points key
945 {
946 pkey = faceDirBasis->GetPointsKey();
947 }
948 }
949 }
950 break;
951 case 1: // this never appears together with Ortho_A
952 {
954
955 switch (pointsType) // determine the points type
956 {
958 case LibUtilities::eGaussRadauMAlpha2Beta0:
959 {
961 numpoints,
962 LibUtilities::eGaussRadauMAlpha1Beta0);
963 }
964 break;
965 default: // For other points type, just return the
966 // points key
967 {
968 pkey = faceDirBasis->GetPointsKey();
969 }
970 }
971 }
972 break;
973 default:
974 {
975 NEKERROR(ErrorUtil::efatal, "invalid value to flag");
976 break;
977 }
978 }
979 return LibUtilities::BasisKey(bType, nummodes, pkey);
980 }
981 default:
982 {
983 NEKERROR(ErrorUtil::efatal, "expansion type unknown");
984 break;
985 }
986 }
987
988 // Keep things happy by returning a value.
990}
991
992void StdExpansion3D::v_PhysInterp(std::shared_ptr<StdExpansion> fromExp,
993 const Array<OneD, const NekDouble> &fromData,
995 [[maybe_unused]] bool Transpose)
996{
997
998 LibUtilities::Interp3D(fromExp->GetBasis(0)->GetPointsKey(),
999 fromExp->GetBasis(1)->GetPointsKey(),
1000 fromExp->GetBasis(2)->GetPointsKey(), fromData,
1001 m_base[0]->GetPointsKey(), m_base[1]->GetPointsKey(),
1002 m_base[2]->GetPointsKey(), toData);
1003}
1004
1005} // namespace Nektar::StdRegions
#define ASSERTL0(condition, msg)
#define WARNINGL2(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 PHYSDERIV_Q(r, i)
#define PHYSDERIV_DEF
#define STDLEV1UPDATE(r, state)
#define STDLEV1TEST(r, state)
Describes the specification for a Basis.
Definition Basis.h:45
BasisType GetBasisType() const
Return type of expansion basis.
Definition Basis.h:131
Defines a specification for a set of points.
Definition Points.h:50
void IProductWRTBaseKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const Array< OneD, NekDouble > &jac, const bool Deformed, bool CollDir0=false, bool CollDir1=false, bool CollDir2=false)
void v_ReOrientTracePhysMap(const StdRegions::Orientation orient, Array< OneD, int > &idmap, const int nq0, const int nq1, bool Forwards) override
This method produces a mapping.
virtual int v_GetNedges(void) const
virtual void v_GetEdgeInteriorToElementMap(const int tid, Array< OneD, unsigned int > &maparray, Array< OneD, int > &signarray, Orientation traceOrient=eForwards)
void v_HelmholtzMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey) override
void v_MultiplyByStdQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
void v_IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
void v_LaplacianMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey) override
virtual int v_GetEdgeNcoeffs(const int i) const
void v_PhysInterp(std::shared_ptr< StdExpansion > fromExp, const Array< OneD, const NekDouble > &fromData, Array< OneD, NekDouble > &toData, bool Transpose) override
NekDouble v_PhysEvaluateInterp(const Array< OneD, DNekMatSharedPtr > &I, const Array< OneD, const NekDouble > &physvals) override
virtual void v_IProductWRTBaseKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const Array< OneD, NekDouble > &jac, const bool Deformed, bool CollDir0=false, bool CollDir1=false, bool CollDir2=false)=0
void v_GenStdMatBwdDeriv(const int dir, DNekMatSharedPtr &mat) override
void v_GetTraceToElementMap(const int tid, Array< OneD, unsigned int > &maparray, Array< OneD, int > &signarray, Orientation traceOrient, int P, int Q) override
NekDouble v_StdPhysEvaluate(const Array< OneD, const NekDouble > &coords, const Array< OneD, const NekDouble > &physvals) override
This function evaluates the expansion at a single (arbitrary) point of the domain.
void PhysTensorDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d0, Array< OneD, NekDouble > &out_d1, Array< OneD, NekDouble > &out_d2)
Calculate the 3D derivative in the local tensor/collapsed coordinate at the physical points.
void v_PhysDeriv(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
Calculate the derivative of the physical points in a given direction.
int GetTotPoints() const
This function returns the total number of quadrature points used in the element.
void GetElmtTraceToTraceMap(const unsigned int tid, Array< OneD, unsigned int > &maparray, Array< OneD, int > &signarray, Orientation traceOrient=eForwards, int P=-1, int Q=-1)
void LaplacianMatrixOp_MatFree_GenericImpl(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
void LocCoordToLocCollapsed(const Array< OneD, const NekDouble > &xi, Array< OneD, NekDouble > &eta)
Convert local cartesian coordinate xi into local collapsed coordinates eta.
void GetTraceCoeffMap(const unsigned int traceid, Array< OneD, unsigned int > &maparray)
void IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
this function calculates the inner product of a given function f with the different modes of the expa...
void BwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function performs the Backward transformation from coefficient space to physical space.
void MultiplyByQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
void MultiplyByStdQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
void HelmholtzMatrixOp_MatFree_GenericImpl(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
Array< OneD, LibUtilities::BasisSharedPtr > m_base
std::vector< Array< OneD, const NekDouble > > m_weights
void LaplacianMatrixOp_MatFree_Kernel(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp)
NekDouble GetConstFactor(const ConstFactorType &factor) const
bool ConstFactorExists(const ConstFactorType &factor) const
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:152
std::shared_ptr< Basis > BasisSharedPtr
static const BasisKey NullBasisKey(eNoBasisType, 0, NullPointsKey)
Defines a null basis with no type or points.
void Interp3D(const BasisKey &fbasis0, const BasisKey &fbasis1, const BasisKey &fbasis2, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, const BasisKey &tbasis2, Array< OneD, NekDouble > &to)
this function interpolates a 3D function evaluated at the quadrature points of the 3D basis,...
Definition Interp.cpp:162
@ eGaussRadauMLegendre
1D Gauss-Radau-Legendre quadrature points, pinned at x=-1
Definition PointsType.h:47
@ 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
@ eModified_B
Principle Modified Functions .
Definition BasisType.h:49
@ eOrtho_A
Principle Orthogonal Functions .
Definition BasisType.h:42
@ eModified_C
Principle Modified Functions .
Definition BasisType.h:50
@ eGLL_Lagrange
Lagrange for SEM basis .
Definition BasisType.h:56
@ eOrtho_C
Principle Orthogonal Functions .
Definition BasisType.h:46
@ eModifiedPyr_C
Principle Modified Functions.
Definition BasisType.h:53
@ eOrtho_B
Principle Orthogonal Functions .
Definition BasisType.h:44
@ eModified_A
Principle Modified Functions .
Definition BasisType.h:48
@ eOrthoPyr_C
Principle Orthogonal Functions .
Definition BasisType.h:51
static const PointsKey NullPointsKey(0, eNoPointsType)
static const NekDouble kNekZeroTol
LibUtilities::BasisKey EvaluateQuadFaceBasisKey(const int facedir, const LibUtilities::BasisSharedPtr &faceDirBasis)
LibUtilities::BasisKey EvaluateTriFaceBasisKey(const int facedir, const LibUtilities::BasisSharedPtr &faceDirBasis, bool UseGLL)
tinysimd::scalarT< double > vec_t
static Array< OneD, NekDouble > NullNekDouble1DArray
NekMatrix< InnerMatrixType, BlockMatrixTag > Transpose(NekMatrix< InnerMatrixType, BlockMatrixTag > &rhs)
std::shared_ptr< DNekMat > DNekMatSharedPtr
void CopyArray(const Array< OneD, ConstDataType > &source, Array< OneD, DataType > &dest)
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
T Dot(int n, const T *w, const T *x)
dot product
Definition Vmath.hpp:761
scalarT< T > max(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:305