Nektar++
Loading...
Searching...
No Matches
StdTriExp.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: StdTriExp.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: Triangle routines built upon StdExpansion2D
32//
33///////////////////////////////////////////////////////////////////////////////
34
36
37using namespace std;
38
39namespace Nektar::StdRegions
40{
42 const LibUtilities::BasisKey &Bb)
43 : StdExpansion(LibUtilities::StdTriData::getNumberOfCoefficients(
44 Ba.GetNumModes(), Bb.GetNumModes()),
45 2, Ba, Bb),
46 StdExpansion2D(LibUtilities::StdTriData::getNumberOfCoefficients(
47 Ba.GetNumModes(), Bb.GetNumModes()),
48 Ba, Bb)
49{
50 ASSERTL0(Ba.GetNumModes() <= Bb.GetNumModes(),
51 "order in 'a' direction is higher than order "
52 "in 'b' direction");
53}
54
55//-------------------------------
56// Integration Methods
57//-------------------------------
59{
60 int i;
61 int nquad1 = m_base[1]->GetNumPoints();
62 Array<OneD, NekDouble> w1_tmp(nquad1);
63
67
68 switch (m_base[1]->GetPointsType())
69 {
70 case LibUtilities::eGaussRadauMAlpha1Beta0: // (0,1) Jacobi Inner
71 // product
72 {
73 Vmath::Smul(nquad1, 0.5, w1, 1, w1_tmp, 1);
74 break;
75 }
76 default:
77 {
78 // include jacobian factor on whatever coordinates are defined.
79 for (i = 0; i < nquad1; ++i)
80 {
81 w1_tmp[i] = 0.5 * (1 - z1[i]) * w1[i];
82 }
83 break;
84 }
85 }
86
87 return StdExpansion2D::Integral(inarray, w0, w1_tmp);
88}
89
90//-----------------------------
91// Differentiation Methods
92//-----------------------------
93
94/**
95 * \brief Calculate the derivative of the physical points.
96 *
97 * \f$ \frac{\partial u}{\partial x_1} = \left .
98 * \frac{2.0}{1-\eta_2} \frac{\partial u}{\partial d\eta_1}
99 * \right |_{\eta_2}\f$
100 *
101 * \f$ \frac{\partial u}{\partial x_2} = \left .
102 * \frac{1+\eta_1}{1-\eta_2} \frac{\partial u}{\partial d\eta_1}
103 * \right |_{\eta_2} + \left . \frac{\partial u}{\partial d\eta_2}
104 * \right |_{\eta_1} \f$
105 */
109 [[maybe_unused]] Array<OneD, NekDouble> &out_d2)
110{
111 int i;
112 int nquad0 = m_base[0]->GetNumPoints();
113 int nquad1 = m_base[1]->GetNumPoints();
114 Array<OneD, NekDouble> wsp(std::max(nquad0, nquad1));
115
116 const Array<OneD, const NekDouble> &z0 = m_base[0]->GetZ();
117 const Array<OneD, const NekDouble> &z1 = m_base[1]->GetZ();
118
119 // set up geometric factor: 2/(1-z1)
120 Vmath::Sadd(nquad1, -1.0, z1, 1, wsp, 1);
121 Vmath::Sdiv(nquad1, -2.0, wsp, 1, wsp, 1);
122
123 if (out_d0.size() > 0)
124 {
125 PhysTensorDeriv(inarray, out_d0, out_d1);
126
127 for (i = 0; i < nquad1; ++i)
128 {
129 Blas::Dscal(nquad0, wsp[i], &out_d0[0] + i * nquad0, 1);
130 }
131
132 // if no d1 required do not need to calculate both deriv
133 if (out_d1.size() > 0)
134 {
135 // set up geometric factor: (1+z0)/2
136 Vmath::Sadd(nquad0, 1.0, z0, 1, wsp, 1);
137 Vmath::Smul(nquad0, 0.5, wsp, 1, wsp, 1);
138
139 for (i = 0; i < nquad1; ++i)
140 {
141 Vmath::Vvtvp(nquad0, &wsp[0], 1, &out_d0[0] + i * nquad0, 1,
142 &out_d1[0] + i * nquad0, 1,
143 &out_d1[0] + i * nquad0, 1);
144 }
145 }
146 }
147 else if (out_d1.size() > 0)
148 {
149 Array<OneD, NekDouble> diff0(nquad0 * nquad1);
150 PhysTensorDeriv(inarray, diff0, out_d1);
151
152 for (i = 0; i < nquad1; ++i)
153 {
154 Blas::Dscal(nquad0, wsp[i], &diff0[0] + i * nquad0, 1);
155 }
156
157 Vmath::Sadd(nquad0, 1.0, z0, 1, wsp, 1);
158 Vmath::Smul(nquad0, 0.5, wsp, 1, wsp, 1);
159
160 for (i = 0; i < nquad1; ++i)
161 {
162 Vmath::Vvtvp(nquad0, &wsp[0], 1, &diff0[0] + i * nquad0, 1,
163 &out_d1[0] + i * nquad0, 1, &out_d1[0] + i * nquad0,
164 1);
165 }
166 }
167}
168
169void StdTriExp::v_PhysDeriv(const int dir,
170 const Array<OneD, const NekDouble> &inarray,
171 Array<OneD, NekDouble> &outarray)
172{
173 switch (dir)
174 {
175 case 0:
176 {
177 v_PhysDeriv(inarray, outarray, NullNekDouble1DArray);
178 break;
179 }
180 case 1:
181 {
182 v_PhysDeriv(inarray, NullNekDouble1DArray, outarray);
183 break;
184 }
185 default:
186 {
187 ASSERTL1(false, "input dir is out of range");
188 break;
189 }
190 }
191}
192
196 [[maybe_unused]] Array<OneD, NekDouble> &out_d2)
197{
198 StdTriExp::v_PhysDeriv(inarray, out_d0, out_d1);
199}
200
201//---------------------------------------
202// Transforms
203//---------------------------------------
204
205/**
206 * \brief Backward tranform for triangular elements
207 *
208 * @note 'q' (base[1]) runs fastest in this element.
209 */
211 Array<OneD, NekDouble> &outarray)
212{
213 v_BwdTrans_SumFac(inarray, outarray);
214}
215
217 Array<OneD, NekDouble> &outarray)
218{
220 m_base[0]->GetNumModes());
221
222 BwdTrans_SumFacKernel(m_base[0]->GetBdata(), m_base[1]->GetBdata(), inarray,
223 outarray, wsp);
224}
225
227 const Array<OneD, const NekDouble> &base0,
228 const Array<OneD, const NekDouble> &base1,
229 const Array<OneD, const NekDouble> &inarray,
231 [[maybe_unused]] bool doCheckCollDir0,
232 [[maybe_unused]] bool doCheckCollDir1)
233{
234 int i;
235 int mode;
236 int nquad0 = m_base[0]->GetNumPoints();
237 int nquad1 = m_base[1]->GetNumPoints();
238 int nmodes0 = m_base[0]->GetNumModes();
239 int nmodes1 = m_base[1]->GetNumModes();
240
241 ASSERTL1(wsp.size() >= nquad1 * nmodes0,
242 "Workspace size is not sufficient");
245 "Basis[1] is not of general tensor type");
246
247 for (i = mode = 0; i < nmodes0; ++i)
248 {
249 Blas::Dgemv('N', nquad1, nmodes1 - i, 1.0, base1.data() + mode * nquad1,
250 nquad1, &inarray[0] + mode, 1, 0.0, &wsp[0] + i * nquad1,
251 1);
252 mode += nmodes1 - i;
253 }
254
255 // fix for modified basis by splitting top vertex mode
257 {
258 Blas::Daxpy(nquad1, inarray[1], base1.data() + nquad1, 1,
259 &wsp[0] + nquad1, 1);
260 }
261
262 Blas::Dgemm('N', 'T', nquad0, nquad1, nmodes0, 1.0, base0.data(), nquad0,
263 &wsp[0], nquad1, 0.0, &outarray[0], nquad0);
264}
265
267 Array<OneD, NekDouble> &outarray)
268{
269 v_IProductWRTBase(inarray, outarray);
270
271 // get Mass matrix inverse
272 StdMatrixKey masskey(eInvMass, DetShapeType(), *this);
273 DNekMatSharedPtr matsys = GetStdMatrix(masskey);
274
275 // copy inarray in case inarray == outarray
276 NekVector<NekDouble> in(m_ncoeffs, outarray, eCopy);
278
279 out = (*matsys) * in;
280}
281
283 const Array<OneD, const NekDouble> &inarray,
284 Array<OneD, NekDouble> &outarray)
285{
286 int i, j;
287 int npoints[2] = {m_base[0]->GetNumPoints(), m_base[1]->GetNumPoints()};
288 int nmodes[2] = {m_base[0]->GetNumModes(), m_base[1]->GetNumModes()};
289
290 fill(outarray.data(), outarray.data() + m_ncoeffs, 0.0);
291
292 Array<OneD, NekDouble> physEdge[3];
293 Array<OneD, NekDouble> coeffEdge[3];
294 for (i = 0; i < 3; i++)
295 {
296 physEdge[i] = Array<OneD, NekDouble>(npoints[i != 0]);
297 coeffEdge[i] = Array<OneD, NekDouble>(nmodes[i != 0]);
298 }
299
300 for (i = 0; i < npoints[0]; i++)
301 {
302 physEdge[0][i] = inarray[i];
303 }
304
305 for (i = 0; i < npoints[1]; i++)
306 {
307 physEdge[1][i] = inarray[npoints[0] - 1 + i * npoints[0]];
308 physEdge[2][i] =
309 inarray[(npoints[1] - 1) * npoints[0] - i * npoints[0]];
310 }
311
312 StdSegExpSharedPtr segexp[2] = {
314 m_base[0]->GetBasisKey()),
316 m_base[1]->GetBasisKey())};
317
319 Array<OneD, int> signArray;
321
322 for (i = 0; i < 3; i++)
323 {
324 segexp[i != 0]->FwdTransBndConstrained(physEdge[i], coeffEdge[i]);
325
326 GetTraceToElementMap(i, mapArray, signArray);
327 for (j = 0; j < nmodes[i != 0]; j++)
328 {
329 sign = (NekDouble)signArray[j];
330 outarray[mapArray[j]] = sign * coeffEdge[i][j];
331 }
332 }
333
336
337 StdMatrixKey masskey(eMass, DetShapeType(), *this);
338 MassMatrixOp(outarray, tmp0, masskey);
339 v_IProductWRTBase(inarray, tmp1);
340
341 Vmath::Vsub(m_ncoeffs, tmp1, 1, tmp0, 1, tmp1, 1);
342
343 // get Mass matrix inverse (only of interior DOF)
344 // use block (1,1) of the static condensed system
345 // note: this block alreay contains the inverse matrix
346 DNekMatSharedPtr matsys =
347 (m_stdStaticCondMatrixManager[masskey])->GetBlock(1, 1);
348
349 int nBoundaryDofs = v_NumBndryCoeffs();
350 int nInteriorDofs = m_ncoeffs - nBoundaryDofs;
351
352 Array<OneD, NekDouble> rhs(nInteriorDofs);
353 Array<OneD, NekDouble> result(nInteriorDofs);
354
355 v_GetInteriorMap(mapArray);
356
357 for (i = 0; i < nInteriorDofs; i++)
358 {
359 rhs[i] = tmp1[mapArray[i]];
360 }
361
362 Blas::Dgemv('N', nInteriorDofs, nInteriorDofs, 1.0, &(matsys->GetPtr())[0],
363 nInteriorDofs, rhs.data(), 1, 0.0, result.data(), 1);
364
365 for (i = 0; i < nInteriorDofs; i++)
366 {
367 outarray[mapArray[i]] = result[i];
368 }
369}
370
371//---------------------------------------
372// Inner product functions
373//---------------------------------------
374
375/**
376 * \brief Calculate the inner product of inarray with respect to the
377 * basis B=base0[p]*base1[pq] and put into outarray.
378 *
379 * \f$
380 * \begin{array}{rcl}
381 * I_{pq} = (\phi^A_q \phi^B_{pq}, u) &=&
382 * \sum_{i=0}^{nq_0}\sum_{j=0}^{nq_1}
383 * \phi^A_p(\eta_{0,i})\phi^B_{pq}(\eta_{1,j}) w^0_i w^1_j
384 * u(\xi_{0,i} \xi_{1,j}) \\
385 * & = & \sum_{i=0}^{nq_0} \phi^A_p(\eta_{0,i})
386 * \sum_{j=0}^{nq_1} \phi^B_{pq}(\eta_{1,j}) \tilde{u}_{i,j}
387 * \end{array}
388 * \f$
389 *
390 * where
391 *
392 * \f$ \tilde{u}_{i,j} = w^0_i w^1_j u(\xi_{0,i},\xi_{1,j}) \f$
393 *
394 * which can be implemented as
395 *
396 * \f$ f_{pj} = \sum_{i=0}^{nq_0} \phi^A_p(\eta_{0,i})
397 * \tilde{u}_{i,j}
398 * \rightarrow {\bf B_1 U} \f$
399 * \f$ I_{pq} = \sum_{j=0}^{nq_1} \phi^B_{pq}(\eta_{1,j}) f_{pj}
400 * \rightarrow {\bf B_2[p*skip] f[skip]} \f$
401 *
402 * \b Recall: \f$ \eta_{1} = \frac{2(1+\xi_1)}{(1-\xi_2)}-1, \,
403 * \eta_2 = \xi_2\f$
404 *
405 * \b Note: For the orthgonality of this expansion to be realised the
406 * 'q' ordering must run fastest in contrast to the Quad and Hex
407 * ordering where 'p' index runs fastest to be consistent with the
408 * quadrature ordering.
409 *
410 * In the triangular space the i (i.e. \f$\eta_1\f$ direction)
411 * ordering still runs fastest by convention.
412 */
418
420 const Array<OneD, const NekDouble> &inarray,
421 Array<OneD, NekDouble> &outarray, bool multiplybyweights)
422{
423 int nquad0 = m_base[0]->GetNumPoints();
424 int nquad1 = m_base[1]->GetNumPoints();
425 int order0 = m_base[0]->GetNumModes();
426
427 if (multiplybyweights)
428 {
429 Array<OneD, NekDouble> tmp(nquad0 * nquad1 + nquad1 * order0);
430 Array<OneD, NekDouble> wsp(tmp + nquad0 * nquad1);
431
432 // multiply by integration constants
433 MultiplyByQuadratureMetric(inarray, tmp);
435 m_base[1]->GetBdata(), tmp, outarray, wsp);
436 }
437 else
438 {
439 Array<OneD, NekDouble> wsp(nquad1 * order0);
441 m_base[1]->GetBdata(), inarray, outarray,
442 wsp);
443 }
444}
445
447 const Array<OneD, const NekDouble> &base0,
448 const Array<OneD, const NekDouble> &base1,
449 const Array<OneD, const NekDouble> &inarray,
451 [[maybe_unused]] bool doCheckCollDir0,
452 [[maybe_unused]] bool doCheckCollDir1)
453{
454 int i;
455 int mode;
456 int nquad0 = m_base[0]->GetNumPoints();
457 int nquad1 = m_base[1]->GetNumPoints();
458 int nmodes0 = m_base[0]->GetNumModes();
459 int nmodes1 = m_base[1]->GetNumModes();
460
461 ASSERTL1(wsp.size() >= nquad1 * nmodes0,
462 "Workspace size is not sufficient");
463
464 Blas::Dgemm('T', 'N', nquad1, nmodes0, nquad0, 1.0, inarray.data(), nquad0,
465 base0.data(), nquad0, 0.0, wsp.data(), nquad1);
466
467 // Inner product with respect to 'b' direction
468 for (mode = i = 0; i < nmodes0; ++i)
469 {
470 Blas::Dgemv('T', nquad1, nmodes1 - i, 1.0, base1.data() + mode * nquad1,
471 nquad1, wsp.data() + i * nquad1, 1, 0.0,
472 outarray.data() + mode, 1);
473 mode += nmodes1 - i;
474 }
475
476 // fix for modified basis by splitting top vertex mode
478 {
479 outarray[1] += Blas::Ddot(nquad1, base1.data() + nquad1, 1,
480 wsp.data() + nquad1, 1);
481 }
482}
483
485 const int dir, const Array<OneD, const NekDouble> &inarray,
486 Array<OneD, NekDouble> &outarray)
487{
488 StdTriExp::v_IProductWRTDerivBase_SumFac(dir, inarray, outarray);
489}
490
492 const int dir, const Array<OneD, const NekDouble> &inarray,
493 Array<OneD, NekDouble> &outarray)
494{
495 int i;
496 int nquad0 = m_base[0]->GetNumPoints();
497 int nquad1 = m_base[1]->GetNumPoints();
498 int nqtot = nquad0 * nquad1;
499 int nmodes0 = m_base[0]->GetNumModes();
500 int wspsize = max(max(nqtot, m_ncoeffs), nquad1 * nmodes0);
501
502 Array<OneD, NekDouble> gfac0(2 * wspsize);
503 Array<OneD, NekDouble> tmp0(gfac0 + wspsize);
504
505 const Array<OneD, const NekDouble> &z1 = m_base[1]->GetZ();
506
507 // set up geometric factor: 2/(1-z1)
508 for (i = 0; i < nquad1; ++i)
509 {
510 gfac0[i] = 2.0 / (1 - z1[i]);
511 }
512
513 for (i = 0; i < nquad1; ++i)
514 {
515 Vmath::Smul(nquad0, gfac0[i], &inarray[0] + i * nquad0, 1,
516 &tmp0[0] + i * nquad0, 1);
517 }
518
519 MultiplyByQuadratureMetric(tmp0, tmp0);
520
521 switch (dir)
522 {
523 case 0:
524 {
525 IProductWRTBase_SumFacKernel(m_base[0]->GetDbdata(),
526 m_base[1]->GetBdata(), tmp0, outarray,
527 gfac0);
528 break;
529 }
530 case 1:
531 {
533 const Array<OneD, const NekDouble> &z0 = m_base[0]->GetZ();
534
535 for (i = 0; i < nquad0; ++i)
536 {
537 gfac0[i] = 0.5 * (1 + z0[i]);
538 }
539
540 for (i = 0; i < nquad1; ++i)
541 {
542 Vmath::Vmul(nquad0, &gfac0[0], 1, &tmp0[0] + i * nquad0, 1,
543 &tmp0[0] + i * nquad0, 1);
544 }
545
546 IProductWRTBase_SumFacKernel(m_base[0]->GetDbdata(),
547 m_base[1]->GetBdata(), tmp0, tmp3,
548 gfac0);
549
550 MultiplyByQuadratureMetric(inarray, tmp0);
552 m_base[1]->GetDbdata(), tmp0, outarray,
553 gfac0);
554 Vmath::Vadd(m_ncoeffs, &tmp3[0], 1, &outarray[0], 1, &outarray[0],
555 1);
556 break;
557 }
558 default:
559 {
560 ASSERTL1(false, "input dir is out of range");
561 break;
562 }
563 }
564}
565
566//---------------------------------------
567// Evaluation functions
568//---------------------------------------
569
572{
573 NekDouble d1 = 1. - xi[1];
574 if (fabs(d1) < NekConstants::kNekZeroTol)
575 {
576 if (d1 >= 0.)
577 {
579 }
580 else
581 {
583 }
584 }
585 eta[0] = 2. * (1. + xi[0]) / d1 - 1.0;
586 eta[1] = xi[1];
587}
588
591{
592 xi[0] = (1.0 + eta[0]) * (1.0 - eta[1]) * 0.5 - 1.0;
593 xi[1] = eta[1];
594}
595
596void StdTriExp::v_FillMode(const int mode, Array<OneD, NekDouble> &outarray)
597{
598 int i, m;
599 int nquad0 = m_base[0]->GetNumPoints();
600 int nquad1 = m_base[1]->GetNumPoints();
601 int order0 = m_base[0]->GetNumModes();
602 int order1 = m_base[1]->GetNumModes();
603 int mode0 = 0;
604 Array<OneD, const NekDouble> base0 = m_base[0]->GetBdata();
605 Array<OneD, const NekDouble> base1 = m_base[1]->GetBdata();
606
607 ASSERTL2(mode <= m_ncoeffs, "calling argument mode is larger than "
608 "total expansion order");
609
610 m = order1;
611 for (i = 0; i < order0; ++i, m += order1 - i)
612 {
613 if (m > mode)
614 {
615 mode0 = i;
616 break;
617 }
618 }
619
620 // deal with top vertex mode in modified basis
621 if (mode == 1 && m_base[0]->GetBasisType() == LibUtilities::eModified_A)
622 {
623 Vmath::Fill(nquad0 * nquad1, 1.0, outarray, 1);
624 }
625 else
626 {
627 for (i = 0; i < nquad1; ++i)
628 {
629 Vmath::Vcopy(nquad0, (NekDouble *)(base0.data() + mode0 * nquad0),
630 1, &outarray[0] + i * nquad0, 1);
631 }
632 }
633
634 for (i = 0; i < nquad0; ++i)
635 {
636 Vmath::Vmul(nquad1, (NekDouble *)(base1.data() + mode * nquad1), 1,
637 &outarray[0] + i, nquad0, &outarray[0] + i, nquad0);
638 }
639}
640
642 const Array<OneD, const NekDouble> &coords, int mode)
643{
645 LocCoordToLocCollapsed(coords, coll);
646
647 // From mode we need to determine mode0 and mode1 in the (p,q)
648 // direction. mode1 can be directly inferred from mode.
649 const int nm1 = m_base[1]->GetNumModes();
650 const double c = 1 + 2 * nm1;
651 const int mode0 = floor(0.5 * (c - sqrt(c * c - 8 * mode)));
652
653 if (mode == 1 && m_base[0]->GetBasisType() == LibUtilities::eModified_A)
654 {
655 // Account for collapsed vertex.
656 return StdExpansion::BaryEvaluateBasis<1>(coll[1], 1);
657 }
658 else
659 {
660 return StdExpansion::BaryEvaluateBasis<0>(coll[0], mode0) *
661 StdExpansion::BaryEvaluateBasis<1>(coll[1], mode);
662 }
663}
664
666 const Array<OneD, NekDouble> &coord,
667 const Array<OneD, const NekDouble> &inarray,
668 std::array<NekDouble, 3> &firstOrderDerivs)
669{
670 // Collapse coordinates
671 Array<OneD, NekDouble> coll(2, 0.0);
672 LocCoordToLocCollapsed(coord, coll);
673
674 // If near singularity do the old interpolation matrix method
675 if ((1 - coll[1]) < 1e-5)
676 {
677 int totPoints = GetTotPoints();
678 Array<OneD, NekDouble> EphysDeriv0(totPoints), EphysDeriv1(totPoints);
679 PhysDeriv(inarray, EphysDeriv0, EphysDeriv1);
680
682 I[0] = GetBase()[0]->GetI(coll);
683 I[1] = GetBase()[1]->GetI(coll + 1);
684
685 firstOrderDerivs[0] = PhysEvaluate(I, EphysDeriv0);
686 firstOrderDerivs[1] = PhysEvaluate(I, EphysDeriv1);
687 return PhysEvaluate(I, inarray);
688 }
689
690 // set up geometric factor: 2.0/(1.0-z1)
691 NekDouble fac0 = 2 / (1 - coll[1]);
692
693 NekDouble val = BaryTensorDeriv(coll, inarray, firstOrderDerivs);
694
695 // Copy d0 into temp for d1
696 NekDouble temp;
697 temp = firstOrderDerivs[0];
698
699 // Multiply by geometric factor
700 firstOrderDerivs[0] = firstOrderDerivs[0] * fac0;
701
702 // set up geometric factor: (1+z0)/(1-z1)
703 NekDouble fac1 = fac0 * (coll[0] + 1) / 2;
704
705 // Multiply out_d0 by geometric factor and add to out_d1
706 firstOrderDerivs[1] += fac1 * temp;
707
708 return val;
709}
710
712{
713 return 3;
714}
715
717{
718 return 3;
719}
720
725
727{
729 "BasisType is not a boundary interior form");
731 "BasisType is not a boundary interior form");
732
733 return 3 + (GetBasisNumModes(0) - 2) + 2 * (GetBasisNumModes(1) - 2);
734}
735
737{
739 "BasisType is not a boundary interior form");
741 "BasisType is not a boundary interior form");
742
743 return GetBasisNumModes(0) + 2 * GetBasisNumModes(1);
744}
745
746int StdTriExp::v_GetTraceNcoeffs(const int i) const
747{
748 ASSERTL2(i >= 0 && i <= 2, "edge id is out of range");
749
750 if (i == 0)
751 {
752 return GetBasisNumModes(0);
753 }
754 else
755 {
756 return GetBasisNumModes(1);
757 }
758}
759
761{
762 ASSERTL2(i >= 0 && i <= 2, "edge id is out of range");
763
764 if (i == 0)
765 {
766 return GetBasisNumModes(0) - 2;
767 }
768 else
769 {
770 return GetBasisNumModes(1) - 2;
771 }
772}
773
774int StdTriExp::v_GetTraceNumPoints(const int i) const
775{
776 ASSERTL2((i >= 0) && (i <= 2), "edge id is out of range");
777
778 if (i == 0)
779 {
780 return GetNumPoints(0);
781 }
782 else
783 {
784 return GetNumPoints(1);
785 }
786}
787
789 const std::vector<unsigned int> &nummodes, int &modes_offset)
790{
792 nummodes[modes_offset], nummodes[modes_offset + 1]);
793 modes_offset += 2;
794
795 return nmodes;
796}
797
799 Array<OneD, NekDouble> &coords_1,
800 [[maybe_unused]] Array<OneD, NekDouble> &coords_2)
801{
802 Array<OneD, const NekDouble> z0 = m_base[0]->GetZ();
803 Array<OneD, const NekDouble> z1 = m_base[1]->GetZ();
804 int nq0 = GetNumPoints(0);
805 int nq1 = GetNumPoints(1);
806 int i, j;
807
808 for (i = 0; i < nq1; ++i)
809 {
810 for (j = 0; j < nq0; ++j)
811 {
812 coords_0[i * nq0 + j] = (1 + z0[j]) * (1 - z1[i]) / 2.0 - 1.0;
813 }
814 Vmath::Fill(nq0, z1[i], &coords_1[0] + i * nq0, 1);
815 }
816}
817
819{
820 return m_base[0]->GetBasisType() == LibUtilities::eModified_A &&
821 m_base[1]->GetBasisType() == LibUtilities::eModified_B;
822}
823
825 const int i, [[maybe_unused]] const int j,
826 [[maybe_unused]] bool UseGLL) const
827{
828 ASSERTL2(i >= 0 && i <= 2, "edge id is out of range");
829
830 // Get basiskey (0 or 1) according to edge id i
831 int dir = (i != 0);
832
833 switch (m_base[dir]->GetBasisType())
834 {
837 {
838 switch (m_base[dir]->GetPointsType())
839 {
842 {
843 return m_base[dir]->GetBasisKey();
844 }
845 break;
846 default:
847 {
849 "Unexpected points distribution " +
851 [m_base[dir]->GetPointsType()] +
852 " in StdTriExp::v_GetTraceBasisKey");
853 }
854 }
855 }
856 break;
858 {
859 switch (m_base[dir]->GetPointsType())
860 {
863 {
865 m_base[dir]->GetNumModes(),
866 m_base[dir]->GetPointsKey());
867 }
868 break;
870 {
872 m_base[dir]
873 ->GetBasisKey()
874 .GetPointsKey()
875 .GetNumPoints() +
876 1,
879 m_base[dir]->GetNumModes(),
880 pkey);
881 }
882 break;
883 case LibUtilities::eGaussRadauMAlpha1Beta0:
884 {
886 m_base[dir]
887 ->GetBasisKey()
888 .GetPointsKey()
889 .GetNumPoints() +
890 1,
893 m_base[dir]->GetNumModes(),
894 pkey);
895 }
896 break;
897 // Currently this does not increase the points by
898 // 1 since when using this quadrature we are
899 // presuming it is already been increased by one
900 // when comopared to
901 // GaussRadauMAlpha1Beta0. Currently used in the
902 // GJP option
903 //
904 // Note have put down it back to numpoints +1 to
905 // test for use on tri faces and GJP.
907 {
909 m_base[dir]
910 ->GetBasisKey()
911 .GetPointsKey()
912 .GetNumPoints() +
913 1,
916 m_base[dir]->GetNumModes(),
917 pkey);
918 }
919 break;
921 {
923 m_base[dir]
924 ->GetBasisKey()
925 .GetPointsKey()
926 .GetNumPoints() +
927 1,
930 m_base[dir]->GetNumModes(),
931 pkey);
932 }
933 break;
934 default:
935 {
937 "Unexpected points distribution " +
939 [m_base[dir]->GetPointsType()] +
940 " in StdTriExp::v_GetTraceBasisKey");
941 }
942 }
943 }
944 break;
946 {
947 switch (m_base[dir]->GetPointsType())
948 {
951 {
953 m_base[dir]->GetNumModes(),
954 m_base[dir]->GetPointsKey());
955 }
956 break;
957 default:
958 {
960 "Unexpected points distribution " +
962 [m_base[dir]->GetPointsType()] +
963 " in StdTriExp::v_GetTraceBasisKey");
964 }
965 }
966 }
967 break;
969 {
970 switch (m_base[dir]->GetPointsType())
971 {
974 {
976 m_base[dir]->GetNumModes(),
977 m_base[dir]->GetPointsKey());
978 }
979 break;
981 {
983 m_base[dir]
984 ->GetBasisKey()
985 .GetPointsKey()
986 .GetNumPoints() +
987 1,
990 m_base[dir]->GetNumModes(),
991 pkey);
992 }
993 break;
994 case LibUtilities::eGaussRadauMAlpha1Beta0:
995 {
997 m_base[dir]
998 ->GetBasisKey()
999 .GetPointsKey()
1000 .GetNumPoints() +
1001 1,
1004 m_base[dir]->GetNumModes(),
1005 pkey);
1006 }
1007 break;
1008 default:
1009 {
1011 "Unexpected points distribution " +
1013 [m_base[dir]->GetPointsType()] +
1014 " in StdTriExp::v_GetTraceBasisKey");
1015 }
1016 }
1017 }
1018 break;
1019 default:
1020 {
1022 "Information not available to set edge key");
1023 }
1024 }
1026}
1027
1028//--------------------------
1029// Mappings
1030//--------------------------
1031
1032int StdTriExp::v_GetVertexMap(const int localVertexId, bool useCoeffPacking)
1033{
1036 "Mapping not defined for this type of basis");
1037
1038 int localDOF = 0;
1039 if (useCoeffPacking == true)
1040 {
1041 switch (localVertexId)
1042 {
1043 case 0:
1044 {
1045 localDOF = 0;
1046 break;
1047 }
1048 case 1:
1049 {
1050 localDOF = 1;
1051 break;
1052 }
1053 case 2:
1054 {
1055 localDOF = m_base[1]->GetNumModes();
1056 break;
1057 }
1058 default:
1059 {
1060 ASSERTL0(false, "eid must be between 0 and 2");
1061 break;
1062 }
1063 }
1064 }
1065 else // follow book format for vertex indexing.
1066 {
1067 switch (localVertexId)
1068 {
1069 case 0:
1070 {
1071 localDOF = 0;
1072 break;
1073 }
1074 case 1:
1075 {
1076 localDOF = m_base[1]->GetNumModes();
1077 break;
1078 }
1079 case 2:
1080 {
1081 localDOF = 1;
1082 break;
1083 }
1084 default:
1085 {
1086 ASSERTL0(false, "eid must be between 0 and 2");
1087 break;
1088 }
1089 }
1090 }
1091
1092 return localDOF;
1093}
1094
1096{
1099 "Expansion not of a proper type");
1100
1101 int i, j;
1102 int cnt = 0;
1103 int nummodes0, nummodes1;
1104 int startvalue;
1105 if (outarray.size() != GetNcoeffs() - NumBndryCoeffs())
1106 {
1108 }
1109
1110 nummodes0 = m_base[0]->GetNumModes();
1111 nummodes1 = m_base[1]->GetNumModes();
1112
1113 startvalue = 2 * nummodes1;
1114
1115 for (i = 0; i < nummodes0 - 2; i++)
1116 {
1117 for (j = 0; j < nummodes1 - 3 - i; j++)
1118 {
1119 outarray[cnt++] = startvalue + j;
1120 }
1121 startvalue += nummodes1 - 2 - i;
1122 }
1123}
1124
1126{
1129 "Expansion not of expected type");
1130 int i;
1131 int cnt;
1132 int nummodes0, nummodes1;
1133 int value;
1134
1135 if (outarray.size() != NumBndryCoeffs())
1136 {
1138 }
1139
1140 nummodes0 = m_base[0]->GetNumModes();
1141 nummodes1 = m_base[1]->GetNumModes();
1142
1143 value = 2 * nummodes1 - 1;
1144 for (i = 0; i < value; i++)
1145 {
1146 outarray[i] = i;
1147 }
1148 cnt = value;
1149
1150 for (i = 0; i < nummodes0 - 2; i++)
1151 {
1152 outarray[cnt++] = value;
1153 value += nummodes1 - 2 - i;
1154 }
1155}
1156
1157void StdTriExp::v_GetTraceCoeffMap(const unsigned int eid,
1158 Array<OneD, unsigned int> &maparray)
1159{
1160
1163 "Mapping not defined for this type of basis");
1164
1165 ASSERTL1(eid < 3, "eid must be between 0 and 2");
1166
1167 int i;
1168 int order0 = m_base[0]->GetNumModes();
1169 int order1 = m_base[1]->GetNumModes();
1170 int numModes = (eid == 0) ? order0 : order1;
1171
1172 if (maparray.size() != numModes)
1173 {
1174 maparray = Array<OneD, unsigned int>(numModes);
1175 }
1176
1177 switch (eid)
1178 {
1179 case 0:
1180 {
1181 int cnt = 0;
1182 for (i = 0; i < numModes; cnt += order1 - i, ++i)
1183 {
1184 maparray[i] = cnt;
1185 }
1186 break;
1187 }
1188 case 1:
1189 {
1190 maparray[0] = order1;
1191 maparray[1] = 1;
1192 for (i = 2; i < numModes; i++)
1193 {
1194 maparray[i] = order1 - 1 + i;
1195 }
1196 break;
1197 }
1198 case 2:
1199 {
1200 for (i = 0; i < numModes; i++)
1201 {
1202 maparray[i] = i;
1203 }
1204 break;
1205 }
1206 default:
1207 ASSERTL0(false, "eid must be between 0 and 2");
1208 break;
1209 }
1210}
1211
1213 const int eid, Array<OneD, unsigned int> &maparray,
1214 Array<OneD, int> &signarray, const Orientation edgeOrient)
1215{
1218 "Mapping not defined for this type of basis");
1219 int i;
1220 const int nummodes1 = m_base[1]->GetNumModes();
1221 const int nEdgeIntCoeffs = GetTraceNcoeffs(eid) - 2;
1222
1223 if (maparray.size() != nEdgeIntCoeffs)
1224 {
1225 maparray = Array<OneD, unsigned int>(nEdgeIntCoeffs);
1226 }
1227
1228 if (signarray.size() != nEdgeIntCoeffs)
1229 {
1230 signarray = Array<OneD, int>(nEdgeIntCoeffs, 1);
1231 }
1232 else
1233 {
1234 fill(signarray.data(), signarray.data() + nEdgeIntCoeffs, 1);
1235 }
1236
1237 switch (eid)
1238 {
1239 case 0:
1240 {
1241 int cnt = 2 * nummodes1 - 1;
1242 for (i = 0; i < nEdgeIntCoeffs; cnt += nummodes1 - 2 - i, ++i)
1243 {
1244 maparray[i] = cnt;
1245 }
1246 break;
1247 }
1248 case 1:
1249 {
1250 for (i = 0; i < nEdgeIntCoeffs; i++)
1251 {
1252 maparray[i] = nummodes1 + 1 + i;
1253 }
1254 break;
1255 }
1256 case 2:
1257 {
1258 for (i = 0; i < nEdgeIntCoeffs; i++)
1259 {
1260 maparray[i] = 2 + i;
1261 }
1262 break;
1263 }
1264 default:
1265 {
1266 ASSERTL0(false, "eid must be between 0 and 2");
1267 break;
1268 }
1269 }
1270
1271 if (edgeOrient == eBackwards)
1272 {
1273 for (i = 1; i < nEdgeIntCoeffs; i += 2)
1274 {
1275 signarray[i] = -1;
1276 }
1277 }
1278}
1279
1280//---------------------------------------
1281// Wrapper functions
1282//---------------------------------------
1283
1285{
1286
1287 MatrixType mtype = mkey.GetMatrixType();
1288
1289 DNekMatSharedPtr Mat;
1290
1291 switch (mtype)
1292 {
1294 {
1295 int nq0, nq1, nq;
1296
1297 nq0 = m_base[0]->GetNumPoints();
1298 nq1 = m_base[1]->GetNumPoints();
1299
1300 // take definition from key
1302 {
1303 nq = (int)mkey.GetConstFactor(eFactorConst);
1304 }
1305 else
1306 {
1307 nq = max(nq0, nq1);
1308 }
1309
1312 Array<OneD, NekDouble> coll(2);
1314 Array<OneD, NekDouble> tmp(nq0);
1315
1316 Mat = MemoryManager<DNekMat>::AllocateSharedPtr(neq, nq0 * nq1);
1317 int cnt = 0;
1318
1319 for (int i = 0; i < nq; ++i)
1320 {
1321 for (int j = 0; j < nq - i; ++j, ++cnt)
1322 {
1323 coords[cnt] = Array<OneD, NekDouble>(2);
1324 coords[cnt][0] = -1.0 + 2 * j / (NekDouble)(nq - 1);
1325 coords[cnt][1] = -1.0 + 2 * i / (NekDouble)(nq - 1);
1326 }
1327 }
1328
1329 for (int i = 0; i < neq; ++i)
1330 {
1331 LocCoordToLocCollapsed(coords[i], coll);
1332
1333 I[0] = m_base[0]->GetI(coll);
1334 I[1] = m_base[1]->GetI(coll + 1);
1335
1336 // interpolate first coordinate direction
1337 for (int j = 0; j < nq1; ++j)
1338 {
1339 NekDouble fac = (I[1]->GetPtr())[j];
1340 Vmath::Smul(nq0, fac, I[0]->GetPtr(), 1, tmp, 1);
1341
1342 Vmath::Vcopy(nq0, &tmp[0], 1,
1343 Mat->GetRawPtr() + j * nq0 * neq + i, neq);
1344 }
1345 }
1346 break;
1347 }
1348 default:
1349 {
1351 break;
1352 }
1353 }
1354
1355 return Mat;
1356}
1357
1359{
1360 return v_GenMatrix(mkey);
1361}
1362
1363//---------------------------------------
1364// Operator evaluation functions
1365//---------------------------------------
1366
1368 Array<OneD, NekDouble> &outarray,
1369 const StdMatrixKey &mkey)
1370{
1371 StdExpansion::MassMatrixOp_MatFree(inarray, outarray, mkey);
1372}
1373
1375 Array<OneD, NekDouble> &outarray,
1376 const StdMatrixKey &mkey)
1377{
1378 StdTriExp::v_LaplacianMatrixOp_MatFree(inarray, outarray, mkey);
1379}
1380
1381void StdTriExp::v_LaplacianMatrixOp(const int k1, const int k2,
1382 const Array<OneD, const NekDouble> &inarray,
1383 Array<OneD, NekDouble> &outarray,
1384 const StdMatrixKey &mkey)
1385{
1386 StdExpansion::LaplacianMatrixOp_MatFree(k1, k2, inarray, outarray, mkey);
1387}
1388
1390 const Array<OneD, const NekDouble> &inarray,
1391 Array<OneD, NekDouble> &outarray,
1392 const StdMatrixKey &mkey)
1393{
1394 StdExpansion::WeakDerivMatrixOp_MatFree(i, inarray, outarray, mkey);
1395}
1396
1398 Array<OneD, NekDouble> &outarray,
1399 const StdMatrixKey &mkey)
1400{
1401 StdTriExp::v_HelmholtzMatrixOp_MatFree(inarray, outarray, mkey);
1402}
1403
1405 const StdMatrixKey &mkey)
1406{
1407 int qa = m_base[0]->GetNumPoints();
1408 int qb = m_base[1]->GetNumPoints();
1409 int nmodes_a = m_base[0]->GetNumModes();
1410 int nmodes_b = m_base[1]->GetNumModes();
1411
1412 // Declare orthogonal basis.
1415
1418 StdTriExp OrthoExp(Ba, Bb);
1419
1420 Array<OneD, NekDouble> orthocoeffs(OrthoExp.GetNcoeffs());
1421
1422 // project onto physical space.
1423 OrthoExp.FwdTrans(array, orthocoeffs);
1424
1425 if (mkey.ConstFactorExists(
1426 eFactorSVVPowerKerDiffCoeff)) // Rodrigo's power kern
1427 {
1429 NekDouble SvvDiffCoeff =
1432
1433 int cnt = 0;
1434 for (int j = 0; j < nmodes_a; ++j)
1435 {
1436 for (int k = 0; k < nmodes_b - j; ++k, ++cnt)
1437 {
1438 NekDouble fac = std::max(
1439 pow((1.0 * j) / (nmodes_a - 1), cutoff * nmodes_a),
1440 pow((1.0 * k) / (nmodes_b - 1), cutoff * nmodes_b));
1441
1442 orthocoeffs[cnt] *= (SvvDiffCoeff * fac);
1443 }
1444 }
1445 }
1446 else if (mkey.ConstFactorExists(
1447 eFactorSVVDGKerDiffCoeff)) // Rodrigo/mansoor's DG kernel
1448 {
1451 int max_ab = max(nmodes_a - kSVVDGFiltermodesmin,
1452 nmodes_b - kSVVDGFiltermodesmin);
1453 max_ab = max(max_ab, 0);
1454 max_ab = min(max_ab, kSVVDGFiltermodesmax - kSVVDGFiltermodesmin);
1455
1456 int cnt = 0;
1457 for (int j = 0; j < nmodes_a; ++j)
1458 {
1459 for (int k = 0; k < nmodes_b - j; ++k, ++cnt)
1460 {
1461 int maxjk = max(j, k);
1462 maxjk = min(maxjk, kSVVDGFiltermodesmax - 1);
1463
1464 orthocoeffs[cnt] *= SvvDiffCoeff * kSVVDGFilter[max_ab][maxjk];
1465 }
1466 }
1467 }
1468 else
1469 {
1470 NekDouble SvvDiffCoeff = mkey.GetConstFactor(eFactorSVVDiffCoeff);
1471
1472 int cutoff = (int)(mkey.GetConstFactor(eFactorSVVCutoffRatio) *
1473 min(nmodes_a, nmodes_b));
1474
1475 NekDouble epsilon = 1.0;
1476 int nmodes = min(nmodes_a, nmodes_b);
1477
1478 int cnt = 0;
1479
1480 // apply SVV filter (JEL)
1481 for (int j = 0; j < nmodes_a; ++j)
1482 {
1483 for (int k = 0; k < nmodes_b - j; ++k)
1484 {
1485 if (j + k >= cutoff)
1486 {
1487 orthocoeffs[cnt] *=
1488 (SvvDiffCoeff *
1489 exp(-(j + k - nmodes) * (j + k - nmodes) /
1490 ((NekDouble)((j + k - cutoff + epsilon) *
1491 (j + k - cutoff + epsilon)))));
1492 }
1493 else
1494 {
1495 orthocoeffs[cnt] *= 0.0;
1496 }
1497 cnt++;
1498 }
1499 }
1500 }
1501
1502 // backward transform to physical space
1503 OrthoExp.BwdTrans(orthocoeffs, array);
1504}
1505
1507 const Array<OneD, const NekDouble> &inarray,
1508 Array<OneD, NekDouble> &outarray)
1509{
1510 int n_coeffs = inarray.size();
1511 int nquad0 = m_base[0]->GetNumPoints();
1512 int nquad1 = m_base[1]->GetNumPoints();
1513 Array<OneD, NekDouble> coeff(n_coeffs);
1514 Array<OneD, NekDouble> coeff_tmp(n_coeffs, 0.0);
1517 int nqtot = nquad0 * nquad1;
1518 Array<OneD, NekDouble> phys_tmp(nqtot, 0.0);
1519
1520 int nmodes0 = m_base[0]->GetNumModes();
1521 int nmodes1 = m_base[1]->GetNumModes();
1522 int numMin2 = nmodes0;
1523 int i;
1524
1525 const LibUtilities::PointsKey Pkey0(nmodes0,
1527 const LibUtilities::PointsKey Pkey1(nmodes1,
1529
1530 LibUtilities::BasisKey b0(m_base[0]->GetBasisType(), nmodes0, Pkey0);
1531 LibUtilities::BasisKey b1(m_base[1]->GetBasisType(), nmodes1, Pkey1);
1532
1533 LibUtilities::BasisKey bortho0(LibUtilities::eOrtho_A, nmodes0, Pkey0);
1534 LibUtilities::BasisKey bortho1(LibUtilities::eOrtho_B, nmodes1, Pkey1);
1535
1536 StdRegions::StdTriExpSharedPtr m_OrthoTriExp;
1538
1541 bortho0, bortho1);
1542
1543 m_TriExp->BwdTrans(inarray, phys_tmp);
1544 m_OrthoTriExp->FwdTrans(phys_tmp, coeff);
1545
1546 for (i = 0; i < n_coeffs; i++)
1547 {
1548 if (i == numMin)
1549 {
1550 coeff[i] = 0.0;
1551 numMin += numMin2 - 1;
1552 numMin2 -= 1.0;
1553 }
1554 }
1555
1556 m_OrthoTriExp->BwdTrans(coeff, phys_tmp);
1557 m_TriExp->FwdTrans(phys_tmp, outarray);
1558}
1559
1560//---------------------------------------
1561// Private helper functions
1562//---------------------------------------
1563
1565 const Array<OneD, const NekDouble> &inarray,
1566 Array<OneD, NekDouble> &outarray)
1567{
1568 int i;
1569 int nquad0 = m_base[0]->GetNumPoints();
1570 int nquad1 = m_base[1]->GetNumPoints();
1571
1572 const Array<OneD, const NekDouble> &w0 = m_base[0]->GetW();
1573 const Array<OneD, const NekDouble> &w1 = m_base[1]->GetW();
1574 const Array<OneD, const NekDouble> &z1 = m_base[1]->GetZ();
1575
1576 // multiply by integration constants
1577 for (i = 0; i < nquad1; ++i)
1578 {
1579 Vmath::Vmul(nquad0, inarray.data() + i * nquad0, 1, w0.data(), 1,
1580 outarray.data() + i * nquad0, 1);
1581 }
1582
1583 switch (m_base[1]->GetPointsType())
1584 {
1585 // (1,0) Jacobi Inner product
1586 case LibUtilities::eGaussRadauMAlpha1Beta0:
1587 for (i = 0; i < nquad1; ++i)
1588 {
1589 Blas::Dscal(nquad0, 0.5 * w1[i], outarray.data() + i * nquad0,
1590 1);
1591 }
1592 break;
1593 // Legendre inner product
1594 default:
1595 for (i = 0; i < nquad1; ++i)
1596 {
1597 Blas::Dscal(nquad0, 0.5 * (1 - z1[i]) * w1[i],
1598 outarray.data() + i * nquad0, 1);
1599 }
1600 break;
1601 }
1602}
1603
1605 Array<OneD, int> &conn, [[maybe_unused]] bool standard)
1606{
1607 int np1 = m_base[0]->GetNumPoints();
1608 int np2 = m_base[1]->GetNumPoints();
1609 int np = max(np1, np2);
1610
1611 conn = Array<OneD, int>(3 * (np - 1) * (np - 1));
1612
1613 int row = 0;
1614 int rowp1 = 0;
1615 int cnt = 0;
1616 for (int i = 0; i < np - 1; ++i)
1617 {
1618 rowp1 += np - i;
1619 for (int j = 0; j < np - i - 2; ++j)
1620 {
1621 conn[cnt++] = row + j;
1622 conn[cnt++] = row + j + 1;
1623 conn[cnt++] = rowp1 + j;
1624
1625 conn[cnt++] = rowp1 + j + 1;
1626 conn[cnt++] = rowp1 + j;
1627 conn[cnt++] = row + j + 1;
1628 }
1629
1630 conn[cnt++] = row + np - i - 2;
1631 conn[cnt++] = row + np - i - 1;
1632 conn[cnt++] = rowp1 + np - i - 2;
1633
1634 row += np - i;
1635 }
1636}
1637} // namespace Nektar::StdRegions
#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 ASSERTL2(condition, msg)
Assert Level 2 – Debugging which is used FULLDEBUG compilation mode. This level assert is designed to...
#define sign(a, b)
return the sign(b)*a
Definition Polylib.cpp:47
Describes the specification for a Basis.
Definition Basis.h:45
int GetNumModes() const
Returns the order of the basis.
Definition Basis.h:74
Defines a specification for a set of points.
Definition Points.h:50
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
void PhysTensorDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray_d0, Array< OneD, NekDouble > &outarray_d1)
Calculate the 2D derivative in the local tensor/collapsed coordinate at the physical points.
NekDouble BaryTensorDeriv(const Array< OneD, NekDouble > &coord, const Array< OneD, const NekDouble > &inarray, std::array< NekDouble, 3 > &firstOrderDerivs)
NekDouble Integral(const Array< OneD, const NekDouble > &inarray, const Array< OneD, const NekDouble > &w0, const Array< OneD, const NekDouble > &w1)
void BwdTrans_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0=true, bool doCheckCollDir1=true)
void IProductWRTBase_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0=true, bool doCheckCollDir1=true)
The base class for all shapes.
virtual void v_LaplacianMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
int GetNcoeffs(void) const
This function returns the total number of coefficients used in the expansion.
int GetTotPoints() const
This function returns the total number of quadrature points used in the element.
void WeakDerivMatrixOp_MatFree(const int i, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
LibUtilities::BasisType GetBasisType(const int dir) const
This function returns the type of basis used in the dir direction.
DNekMatSharedPtr GetStdMatrix(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 MassMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
virtual void v_HelmholtzMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
const Array< OneD, const LibUtilities::BasisSharedPtr > & GetBase() const
This function gets the shared point to basis.
DNekMatSharedPtr CreateGeneralMatrix(const StdMatrixKey &mkey)
this function generates the mass matrix
void LaplacianMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
NekDouble PhysEvaluate(const Array< OneD, const NekDouble > &coords, const Array< OneD, const NekDouble > &physvals)
This function evaluates the expansion at a single (arbitrary) point of the domain.
void GetTraceToElementMap(const int tid, Array< OneD, unsigned int > &maparray, Array< OneD, int > &signarray, Orientation traceOrient=eForwards, int P=-1, int Q=-1)
LibUtilities::ShapeType DetShapeType() const
This function returns the shape of the expansion domain.
void BwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function performs the Backward transformation from coefficient space to physical space.
int GetTraceNcoeffs(const int i) const
This function returns the number of expansion coefficients belonging to the i-th trace.
LibUtilities::PointsType GetPointsType(const int dir) const
This function returns the type of quadrature points used in the dir direction.
void FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function performs the Forward transformation from physical space to coefficient space.
LibUtilities::NekManager< StdMatrixKey, DNekBlkMat, StdMatrixKey::opLess > m_stdStaticCondMatrixManager
int GetNumPoints(const int dir) const
This function returns the number of quadrature points in the dir direction.
void MultiplyByQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
int GetBasisNumModes(const int dir) const
This function returns the number of expansion modes in the dir direction.
void PhysDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d0, Array< OneD, NekDouble > &out_d1=NullNekDouble1DArray, Array< OneD, NekDouble > &out_d2=NullNekDouble1DArray)
Array< OneD, LibUtilities::BasisSharedPtr > m_base
void MassMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
MatrixType GetMatrixType() const
NekDouble GetConstFactor(const ConstFactorType &factor) const
bool ConstFactorExists(const ConstFactorType &factor) const
void v_WeakDerivMatrixOp(const int i, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey) override
LibUtilities::ShapeType v_DetShapeType() const final
int v_GetTraceNumPoints(const int i) const override
void v_BwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
Backward tranform for triangular elements.
void v_IProductWRTDerivBase(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
void v_LocCollapsedToLocCoord(const Array< OneD, const NekDouble > &eta, Array< OneD, NekDouble > &xi) override
void v_GetCoords(Array< OneD, NekDouble > &coords_x, Array< OneD, NekDouble > &coords_y, Array< OneD, NekDouble > &coords_z) override
int v_CalcNumberOfCoefficients(const std::vector< unsigned int > &nummodes, int &modes_offset) override
const LibUtilities::BasisKey v_GetTraceBasisKey(const int i, const int j, bool UseGLL=false) const override
void v_GetSimplexEquiSpacedConnectivity(Array< OneD, int > &conn, bool standard=true) override
void v_MassMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey) override
void v_GetBoundaryMap(Array< OneD, unsigned int > &outarray) override
int v_GetNtraces() const final
void v_StdPhysDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d0, Array< OneD, NekDouble > &out_d1, Array< OneD, NekDouble > &out_d2=NullNekDouble1DArray) override
void v_GetTraceInteriorToElementMap(const int eid, Array< OneD, unsigned int > &maparray, Array< OneD, int > &signarray, const Orientation edgeOrient=eForwards) override
int v_GetVertexMap(int localVertexId, bool useCoeffPacking=false) override
DNekMatSharedPtr v_CreateStdMatrix(const StdMatrixKey &mkey) override
void v_BwdTrans_SumFac(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
DNekMatSharedPtr v_GenMatrix(const StdMatrixKey &mkey) override
void v_IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
Calculate the inner product of inarray with respect to the basis B=base0[p]*base1[pq] and put into ou...
int v_GetTraceNcoeffs(const int i) const override
void v_PhysDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d0, Array< OneD, NekDouble > &out_d1, Array< OneD, NekDouble > &out_d2=NullNekDouble1DArray) override
Calculate the derivative of the physical points.
void v_GetTraceCoeffMap(const unsigned int traceid, Array< OneD, unsigned int > &maparray) override
void v_BwdTrans_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0, bool doCheckCollDir1) override
bool v_IsBoundaryInteriorExpansion() const override
void v_FillMode(const int mode, Array< OneD, NekDouble > &outarray) override
void v_ReduceOrderCoeffs(int numMin, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
void v_FwdTransBndConstrained(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
void v_IProductWRTDerivBase_SumFac(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
int v_GetTraceIntNcoeffs(const int i) const override
int v_NumDGBndryCoeffs() const override
void v_LocCoordToLocCollapsed(const Array< OneD, const NekDouble > &xi, Array< OneD, NekDouble > &eta) override
NekDouble v_PhysEvaluateBasis(const Array< OneD, const NekDouble > &coords, int mode) final
void v_HelmholtzMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey) override
NekDouble v_Integral(const Array< OneD, const NekDouble > &inarray) override
Integrates the specified function over the domain.
Definition StdTriExp.cpp:58
NekDouble v_PhysEvalFirstDeriv(const Array< OneD, NekDouble > &coord, const Array< OneD, const NekDouble > &inarray, std::array< NekDouble, 3 > &firstOrderDerivs) override
void v_FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
Transform a given function from physical quadrature space to coefficient space.
void v_GetInteriorMap(Array< OneD, unsigned int > &outarray) override
int v_GetNverts() const final
void v_LaplacianMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey) override
void v_SVVLaplacianFilter(Array< OneD, NekDouble > &array, const StdMatrixKey &mkey) override
void v_MultiplyByStdQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
int v_NumBndryCoeffs() const override
void v_IProductWRTBase_SumFac(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool multiplybyweights=true) override
void v_IProductWRTBase_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0, bool doCheckCollDir1) override
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 void Dscal(const int &n, const double &alpha, double *x, const int &incx)
BLAS level 1: x = alpha x.
Definition Blas.hpp:149
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
static void Daxpy(const int &n, const double &alpha, const double *x, const int &incx, const double *y, const int &incy)
BLAS level 1: y = alpha x plus y.
Definition Blas.hpp:135
int getNumberOfCoefficients(int Na, int Nb)
static const BasisKey NullBasisKey(eNoBasisType, 0, NullPointsKey)
Defines a null basis with no type or points.
const std::string kPointsTypeStr[]
@ 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
@ ePolyEvenlySpaced
1D Evenly-spaced points using Lagrange polynomial
Definition PointsType.h:73
@ eModified_B
Principle Modified Functions .
Definition BasisType.h:49
@ eOrtho_A
Principle Orthogonal Functions .
Definition BasisType.h:42
@ eGLL_Lagrange
Lagrange for SEM basis .
Definition BasisType.h:56
@ eOrtho_B
Principle Orthogonal Functions .
Definition BasisType.h:44
@ eModified_A
Principle Modified Functions .
Definition BasisType.h:48
static const NekDouble kNekZeroTol
const int kSVVDGFiltermodesmin
const int kSVVDGFiltermodesmax
const NekDouble kSVVDGFilter[9][11]
std::shared_ptr< StdTriExp > StdTriExpSharedPtr
Definition StdTriExp.h:215
std::shared_ptr< StdSegExp > StdSegExpSharedPtr
Definition StdSegExp.h:214
static Array< OneD, NekDouble > NullNekDouble1DArray
std::shared_ptr< DNekMat > DNekMatSharedPtr
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition Vmath.hpp:72
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition Vmath.hpp:366
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 Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition Vmath.hpp:100
void Sdiv(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha/x.
Definition Vmath.hpp:154
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition Vmath.hpp:54
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add vector y = alpha + x.
Definition Vmath.hpp:194
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition Vmath.hpp:825
void Vsub(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Subtract vector z = x-y.
Definition Vmath.hpp:220
STL namespace.
scalarT< T > max(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:305
scalarT< T > min(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:300
scalarT< T > sqrt(scalarT< T > in)
Definition scalar.hpp:290