Nektar++
Loading...
Searching...
No Matches
StdQuadExp.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: StdQuadExp.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: Quadrilateral routines built upon StdExpansion2D
32//
33///////////////////////////////////////////////////////////////////////////////
34
38
39using namespace std;
40
41namespace Nektar::StdRegions
42{
43
44/** \brief Constructor using BasisKey class for quadrature
45 * points and order definition
46 */
48 const LibUtilities::BasisKey &Bb)
49 : StdExpansion(Ba.GetNumModes() * Bb.GetNumModes(), 2, Ba, Bb),
50 StdExpansion2D(Ba.GetNumModes() * Bb.GetNumModes(), Ba, Bb)
51{
52}
53
54/////////////////////////
55// Integration Methods //
56/////////////////////////
57
59{
62
63 return StdExpansion2D::Integral(inarray, w0, w1);
64}
65
66/////////////////////////////
67// Differentiation Methods //
68/////////////////////////////
69
70/** \brief Calculate the derivative of the physical points
71 *
72 * For quadrilateral region can use the Tensor_Deriv function
73 * defined under StdExpansion.
74 */
75
79 [[maybe_unused]] Array<OneD, NekDouble> &out_d2)
80{
81 PhysTensorDeriv(inarray, out_d0, out_d1);
82}
83
84void StdQuadExp::v_PhysDeriv(const int dir,
85 const Array<OneD, const NekDouble> &inarray,
86 Array<OneD, NekDouble> &outarray)
87{
88 switch (dir)
89 {
90 case 0:
91 {
92 PhysTensorDeriv(inarray, outarray, NullNekDouble1DArray);
93 }
94 break;
95 case 1:
96 {
97 PhysTensorDeriv(inarray, NullNekDouble1DArray, outarray);
98 }
99 break;
100 default:
101 {
102 ASSERTL1(false, "input dir is out of range");
103 }
104 break;
105 }
106}
107
111 [[maybe_unused]] Array<OneD, NekDouble> &out_d2)
112{
113 StdQuadExp::v_PhysDeriv(inarray, out_d0, out_d1);
114}
115
116////////////////
117// Transforms //
118////////////////
119
121 Array<OneD, NekDouble> &outarray)
122{
123 if (m_base[0]->Collocation() && m_base[1]->Collocation())
124 {
126 inarray, 1, outarray, 1);
127 }
128 else
129 {
130 StdQuadExp::v_BwdTrans_SumFac(inarray, outarray);
131 }
132}
133
135 Array<OneD, NekDouble> &outarray)
136{
138 m_base[1]->GetNumModes());
139
140 BwdTrans_SumFacKernel(m_base[0]->GetBdata(), m_base[1]->GetBdata(), inarray,
141 outarray, wsp, true, true);
142}
143
144// The arguments doCheckCollDir0 and doCheckCollDir1 allow you to specify
145// whether to check if the basis has collocation properties (i.e. for the
146// classical spectral element basis, In this case the 1D 'B' matrix is equal to
147// the identity matrix which can be exploited to speed up the calculations).
148// However, as this routine also allows to pass the matrix 'DB' (derivative of
149// the basis), the collocation property cannot always be used. Therefor follow
150// this rule: if base0 == m_base[0]->GetBdata() --> set doCheckCollDir0 == true;
151// base1 == m_base[1]->GetBdata() --> set doCheckCollDir1 == true;
152// base0 == m_base[0]->GetDbdata() --> set doCheckCollDir0 == false;
153// base1 == m_base[1]->GetDbdata() --> set doCheckCollDir1 == false;
155 const Array<OneD, const NekDouble> &base0,
156 const Array<OneD, const NekDouble> &base1,
157 const Array<OneD, const NekDouble> &inarray,
159 bool doCheckCollDir0, bool doCheckCollDir1)
160{
161 int nquad0 = m_base[0]->GetNumPoints();
162 int nquad1 = m_base[1]->GetNumPoints();
163 int nmodes0 = m_base[0]->GetNumModes();
164 int nmodes1 = m_base[1]->GetNumModes();
165
166 bool colldir0 = doCheckCollDir0 ? (m_base[0]->Collocation()) : false;
167 bool colldir1 = doCheckCollDir1 ? (m_base[1]->Collocation()) : false;
168
169 if (colldir0 && colldir1)
170 {
171 Vmath::Vcopy(m_ncoeffs, inarray.data(), 1, outarray.data(), 1);
172 }
173 else if (colldir0)
174 {
175 Blas::Dgemm('N', 'T', nquad0, nquad1, nmodes1, 1.0, &inarray[0], nquad0,
176 base1.data(), nquad1, 0.0, &outarray[0], nquad0);
177 }
178 else if (colldir1)
179 {
180 Blas::Dgemm('N', 'N', nquad0, nmodes1, nmodes0, 1.0, base0.data(),
181 nquad0, &inarray[0], nmodes0, 0.0, &outarray[0], nquad0);
182 }
183 else
184 {
185 ASSERTL1(wsp.size() >= nquad0 * nmodes1,
186 "Workspace size is not sufficient");
187
188 // Those two calls correpsond to the operation
189 // out = B0*in*Transpose(B1);
190 Blas::Dgemm('N', 'N', nquad0, nmodes1, nmodes0, 1.0, base0.data(),
191 nquad0, &inarray[0], nmodes0, 0.0, &wsp[0], nquad0);
192 Blas::Dgemm('N', 'T', nquad0, nquad1, nmodes1, 1.0, &wsp[0], nquad0,
193 base1.data(), nquad1, 0.0, &outarray[0], nquad0);
194 }
195}
196
198 Array<OneD, NekDouble> &outarray)
199{
200 if ((m_base[0]->Collocation()) && (m_base[1]->Collocation()))
201 {
202 Vmath::Vcopy(m_ncoeffs, inarray, 1, outarray, 1);
203 }
204 else
205 {
206 StdQuadExp::v_IProductWRTBase(inarray, outarray);
207
208 // get Mass matrix inverse
209 StdMatrixKey masskey(eInvMass, DetShapeType(), *this);
210 DNekMatSharedPtr matsys = GetStdMatrix(masskey);
211
212 // copy inarray in case inarray == outarray
213 NekVector<NekDouble> in(m_ncoeffs, outarray, eCopy);
215
216 out = (*matsys) * in;
217 }
218}
219
221 const Array<OneD, const NekDouble> &inarray,
222 Array<OneD, NekDouble> &outarray)
223{
224 if ((m_base[0]->Collocation()) && (m_base[1]->Collocation()))
225 {
226 Vmath::Vcopy(m_ncoeffs, inarray, 1, outarray, 1);
227 }
228 else
229 {
230 int i, j;
231 int npoints[2] = {m_base[0]->GetNumPoints(), m_base[1]->GetNumPoints()};
232 int nmodes[2] = {m_base[0]->GetNumModes(), m_base[1]->GetNumModes()};
233
234 fill(outarray.data(), outarray.data() + m_ncoeffs, 0.0);
235
236 Array<OneD, NekDouble> physEdge[4];
237 Array<OneD, NekDouble> coeffEdge[4];
238 for (i = 0; i < 4; i++)
239 {
240 physEdge[i] = Array<OneD, NekDouble>(npoints[i % 2]);
241 coeffEdge[i] = Array<OneD, NekDouble>(nmodes[i % 2]);
242 }
243
244 for (i = 0; i < npoints[0]; i++)
245 {
246 physEdge[0][i] = inarray[i];
247 physEdge[2][i] = inarray[npoints[0] * npoints[1] - 1 - i];
248 }
249
250 for (i = 0; i < npoints[1]; i++)
251 {
252 physEdge[1][i] = inarray[npoints[0] - 1 + i * npoints[0]];
253 physEdge[3][i] =
254 inarray[(npoints[1] - 1) * npoints[0] - i * npoints[0]];
255 }
256
257 StdSegExpSharedPtr segexp[2] = {
259 m_base[0]->GetBasisKey()),
261 m_base[1]->GetBasisKey())};
262
264 Array<OneD, int> signArray;
266
267 for (i = 0; i < 4; i++)
268 {
269 segexp[i % 2]->FwdTransBndConstrained(physEdge[i], coeffEdge[i]);
270
271 GetTraceToElementMap(i, mapArray, signArray);
272 for (j = 0; j < nmodes[i % 2]; j++)
273 {
274 sign = (NekDouble)signArray[j];
275 outarray[mapArray[j]] = sign * coeffEdge[i][j];
276 }
277 }
278
281
282 StdMatrixKey masskey(eMass, DetShapeType(), *this);
283 MassMatrixOp(outarray, tmp0, masskey);
284 IProductWRTBase(inarray, tmp1);
285
286 Vmath::Vsub(m_ncoeffs, tmp1, 1, tmp0, 1, tmp1, 1);
287
288 // get Mass matrix inverse (only of interior DOF)
289 // use block (1,1) of the static condensed system
290 // note: this block alreay contains the inverse matrix
291 DNekMatSharedPtr matsys =
292 (m_stdStaticCondMatrixManager[masskey])->GetBlock(1, 1);
293
294 int nBoundaryDofs = NumBndryCoeffs();
295 int nInteriorDofs = m_ncoeffs - nBoundaryDofs;
296
297 Array<OneD, NekDouble> rhs(nInteriorDofs);
298 Array<OneD, NekDouble> result(nInteriorDofs);
299
300 GetInteriorMap(mapArray);
301
302 for (i = 0; i < nInteriorDofs; i++)
303 {
304 rhs[i] = tmp1[mapArray[i]];
305 }
306
307 Blas::Dgemv('N', nInteriorDofs, nInteriorDofs, 1.0,
308 &(matsys->GetPtr())[0], nInteriorDofs, rhs.data(), 1, 0.0,
309 result.data(), 1);
310
311 for (i = 0; i < nInteriorDofs; i++)
312 {
313 outarray[mapArray[i]] = result[i];
314 }
315 }
316}
317
318/////////////////////////////
319// Inner Product Functions //
320/////////////////////////////
321
322/** \brief Calculate the inner product of inarray with respect to
323 * the basis B=base0*base1 and put into outarray
324 *
325 * \f$
326 * \begin{array}{rcl}
327 * I_{pq} = (\phi_p \phi_q, u) & = & \sum_{i=0}^{nq_0}
328 * \sum_{j=0}^{nq_1}
329 * \phi_p(\xi_{0,i}) \phi_q(\xi_{1,j}) w^0_i w^1_j u(\xi_{0,i}
330 * \xi_{1,j}) \\
331 * & = & \sum_{i=0}^{nq_0} \phi_p(\xi_{0,i})
332 * \sum_{j=0}^{nq_1} \phi_q(\xi_{1,j}) \tilde{u}_{i,j}
333 * \end{array}
334 * \f$
335 *
336 * where
337 *
338 * \f$ \tilde{u}_{i,j} = w^0_i w^1_j u(\xi_{0,i},\xi_{1,j}) \f$
339 *
340 * which can be implemented as
341 *
342 * \f$ f_{qi} = \sum_{j=0}^{nq_1} \phi_q(\xi_{1,j})
343 * \tilde{u}_{i,j} = {\bf B_1 U} \f$
344 * \f$ I_{pq} = \sum_{i=0}^{nq_0} \phi_p(\xi_{0,i}) f_{qi} =
345 * {\bf B_0 F} \f$
346 */
348 Array<OneD, NekDouble> &outarray)
349{
350 if (m_base[0]->Collocation() && m_base[1]->Collocation())
351 {
352 MultiplyByQuadratureMetric(inarray, outarray);
353 }
354 else
355 {
356 StdQuadExp::v_IProductWRTBase_SumFac(inarray, outarray);
357 }
358}
359
361 const Array<OneD, const NekDouble> &inarray,
362 Array<OneD, NekDouble> &outarray, bool multiplybyweights)
363{
364 int nquad0 = m_base[0]->GetNumPoints();
365 int nquad1 = m_base[1]->GetNumPoints();
366 int order0 = m_base[0]->GetNumModes();
367
368 if (multiplybyweights)
369 {
370 Array<OneD, NekDouble> tmp(nquad0 * nquad1 + nquad1 * order0);
371 Array<OneD, NekDouble> wsp(tmp + nquad0 * nquad1);
372
373 // multiply by integration constants
374 MultiplyByQuadratureMetric(inarray, tmp);
376 m_base[1]->GetBdata(), tmp, outarray, wsp,
377 true, true);
378 }
379 else
380 {
381 Array<OneD, NekDouble> wsp(nquad1 * order0);
383 m_base[1]->GetBdata(), inarray, outarray,
384 wsp, true, true);
385 }
386}
387
389 const int dir, const Array<OneD, const NekDouble> &inarray,
390 Array<OneD, NekDouble> &outarray)
391{
392 v_IProductWRTDerivBase_SumFac(dir, inarray, outarray);
393}
394
396 const int dir, const Array<OneD, const NekDouble> &inarray,
397 Array<OneD, NekDouble> &outarray)
398{
399 ASSERTL0((dir == 0) || (dir == 1), "input dir is out of range");
400
401 int nquad0 = m_base[0]->GetNumPoints();
402 int nquad1 = m_base[1]->GetNumPoints();
403 int nqtot = nquad0 * nquad1;
404 int order0 = m_base[0]->GetNumModes();
405
406 Array<OneD, NekDouble> tmp(nqtot + nquad1 * order0);
407 Array<OneD, NekDouble> wsp(tmp + nqtot);
408
409 // multiply by integration constants
410 MultiplyByQuadratureMetric(inarray, tmp);
411
412 if (dir) // dir == 1
413 {
415 m_base[1]->GetDbdata(), tmp, outarray, wsp,
416 true, false);
417 }
418 else // dir == 0
419 {
420 IProductWRTBase_SumFacKernel(m_base[0]->GetDbdata(),
421 m_base[1]->GetBdata(), tmp, outarray, wsp,
422 false, true);
423 }
424}
425
426// the arguments doCheckCollDir0 and doCheckCollDir1 allow you to specify
427// whether to check if the basis has collocation properties (i.e. for the
428// classical spectral element basis, In this case the 1D 'B' matrix is equal to
429// the identity matrix which can be exploited to speed up the calculations).
430// However, as this routine also allows to pass the matrix 'DB' (derivative of
431// the basis), the collocation property cannot always be used. Therefor follow
432// this rule: if base0 == m_base[0]->GetBdata() --> set doCheckCollDir0 == true;
433// base1 == m_base[1]->GetBdata() --> set doCheckCollDir1 == true;
434// base0 == m_base[0]->GetDbdata() --> set doCheckCollDir0 == false;
435// base1 == m_base[1]->GetDbdata() --> set doCheckCollDir1 == false;
437 const Array<OneD, const NekDouble> &base0,
438 const Array<OneD, const NekDouble> &base1,
439 const Array<OneD, const NekDouble> &inarray,
441 bool doCheckCollDir0, bool doCheckCollDir1)
442{
443 int nquad0 = m_base[0]->GetNumPoints();
444 int nquad1 = m_base[1]->GetNumPoints();
445 int nmodes0 = m_base[0]->GetNumModes();
446 int nmodes1 = m_base[1]->GetNumModes();
447
448 bool colldir0 = doCheckCollDir0 ? (m_base[0]->Collocation()) : false;
449 bool colldir1 = doCheckCollDir1 ? (m_base[1]->Collocation()) : false;
450
451 if (colldir0 && colldir1)
452 {
453 Vmath::Vcopy(m_ncoeffs, inarray.data(), 1, outarray.data(), 1);
454 }
455 else if (colldir0)
456 {
457 Blas::Dgemm('N', 'N', nmodes0, nmodes1, nquad1, 1.0, inarray.data(),
458 nmodes0, base1.data(), nquad1, 0.0, outarray.data(),
459 nmodes0);
460 }
461 else if (colldir1)
462 {
463 Blas::Dgemm('T', 'N', nmodes0, nquad1, nquad0, 1.0, base0.data(),
464 nquad0, inarray.data(), nquad0, 0.0, outarray.data(),
465 nmodes0);
466 }
467 else
468 {
469 ASSERTL1(wsp.size() >= nquad1 * nmodes0,
470 "Workspace size is not sufficient");
471
472#if 1
473 Blas::Dgemm('T', 'N', nmodes0, nquad1, nquad0, 1.0, base0.data(),
474 nquad0, inarray.data(), nquad0, 0.0, wsp.data(), nmodes0);
475
476#else
477 for (int i = 0; i < nmodes0; ++i)
478 {
479 for (int j = 0; j < nquad1; ++j)
480 {
481 wsp[j * nmodes0 + i] =
482 Blas::Ddot(nquad0, base0.data() + i * nquad0, 1,
483 inarray.data() + j * nquad0, 1);
484 }
485 }
486#endif
487 Blas::Dgemm('N', 'N', nmodes0, nmodes1, nquad1, 1.0, wsp.data(),
488 nmodes0, base1.data(), nquad1, 0.0, outarray.data(),
489 nmodes0);
490 }
491}
492
493//////////////////////////
494// Evaluation functions //
495//////////////////////////
496
499{
500 eta[0] = xi[0];
501 eta[1] = xi[1];
502}
503
506{
507 xi[0] = eta[0];
508 xi[1] = eta[1];
509}
510
511/** \brief Fill outarray with mode \a mode of expansion
512 *
513 * Note for quadrilateral expansions _base[0] (i.e. p) modes run
514 * fastest
515 */
516
517void StdQuadExp::v_FillMode(const int mode, Array<OneD, NekDouble> &outarray)
518{
519 int i;
520 int nquad0 = m_base[0]->GetNumPoints();
521 int nquad1 = m_base[1]->GetNumPoints();
522 Array<OneD, const NekDouble> base0 = m_base[0]->GetBdata();
523 Array<OneD, const NekDouble> base1 = m_base[1]->GetBdata();
524 int btmp0 = m_base[0]->GetNumModes();
525 int mode0 = mode % btmp0;
526 int mode1 = mode / btmp0;
527
528 ASSERTL2(mode1 == (int)floor((1.0 * mode) / btmp0),
529 "Integer Truncation not Equiv to Floor");
530
531 ASSERTL2(m_ncoeffs > mode,
532 "calling argument mode is larger than total expansion order");
533
534 for (i = 0; i < nquad1; ++i)
535 {
536 Vmath::Vcopy(nquad0, (NekDouble *)(base0.data() + mode0 * nquad0), 1,
537 &outarray[0] + i * nquad0, 1);
538 }
539
540 for (i = 0; i < nquad0; ++i)
541 {
542 Vmath::Vmul(nquad1, (NekDouble *)(base1.data() + mode1 * nquad1), 1,
543 &outarray[0] + i, nquad0, &outarray[0] + i, nquad0);
544 }
545}
546
547//////////////////////
548// Helper functions //
549//////////////////////
550
552{
553 return 4;
554}
555
557{
558 return 4;
559}
560
561int StdQuadExp::v_GetTraceNcoeffs(const int i) const
562{
563 ASSERTL2((i >= 0) && (i <= 3), "edge id is out of range");
564
565 if ((i == 0) || (i == 2))
566 {
567 return GetBasisNumModes(0);
568 }
569 else
570 {
571 return GetBasisNumModes(1);
572 }
573}
574
576{
577 ASSERTL2((i >= 0) && (i <= 4), "edge id is out of range");
578 if ((i == 0) || (i == 2))
579 {
580 return GetBasisNumModes(0) - 2;
581 }
582 else
583 {
584 return GetBasisNumModes(1) - 2;
585 }
586}
587
589{
590 ASSERTL2((i >= 0) && (i <= 3), "edge id is out of range");
591
592 if ((i == 0) || (i == 2))
593 {
594 return GetNumPoints(0);
595 }
596 else
597 {
598 return GetNumPoints(1);
599 }
600}
601
603 const int i, [[maybe_unused]] const int j,
604 [[maybe_unused]] bool UseGLL) const
605{
606 ASSERTL2((i >= 0) && (i <= 3), "edge id is out of range");
607
608 if ((i == 0) || (i == 2))
609 {
610 switch (GetBasis(0)->GetBasisType())
611 {
613 {
615 GetBasis(0)->GetNumModes(),
616 GetBasis(0)->GetPointsKey());
617 }
618 break;
619 default:
620 {
621 return GetBasis(0)->GetBasisKey();
622 }
623 }
624 }
625 else
626 {
627 switch (GetBasis(1)->GetBasisType())
628 {
630 {
632 GetBasis(1)->GetNumModes(),
633 GetBasis(1)->GetPointsKey());
634 }
635 break;
636 default:
637 {
638 return GetBasis(1)->GetBasisKey();
639 }
640 }
641 }
642}
643
648
650{
654 "BasisType is not a boundary interior form");
658 "BasisType is not a boundary interior form");
659
660 return 4 + 2 * (GetBasisNumModes(0) - 2) + 2 * (GetBasisNumModes(1) - 2);
661}
662
664{
668 "BasisType is not a boundary interior form");
672 "BasisType is not a boundary interior form");
673
674 return 2 * GetBasisNumModes(0) + 2 * GetBasisNumModes(1);
675}
676
678 const std::vector<unsigned int> &nummodes, int &modes_offset)
679{
680 int nmodes = nummodes[modes_offset] * nummodes[modes_offset + 1];
681 modes_offset += 2;
682
683 return nmodes;
684}
685
687{
688 bool returnval = false;
689
692 {
695 {
696 returnval = true;
697 }
698 }
699
700 return returnval;
701}
702
704 Array<OneD, NekDouble> &coords_1,
705 [[maybe_unused]] Array<OneD, NekDouble> &coords_2)
706{
707 Array<OneD, const NekDouble> z0 = m_base[0]->GetZ();
708 Array<OneD, const NekDouble> z1 = m_base[1]->GetZ();
709 int nq0 = GetNumPoints(0);
710 int nq1 = GetNumPoints(1);
711 int i;
712
713 for (i = 0; i < nq1; ++i)
714 {
715 Blas::Dcopy(nq0, z0.data(), 1, &coords_0[0] + i * nq0, 1);
716 Vmath::Fill(nq0, z1[i], &coords_1[0] + i * nq0, 1);
717 }
718}
719
720/**
721 * @brief This function evaluates the basis function mode @p mode at a
722 * point @p coords of the domain.
723 *
724 * This function uses barycentric interpolation with the tensor
725 * product separation of the basis function to improve performance.
726 *
727 * @param coord The coordinate inside the standard region.
728 * @param mode The mode number to be evaluated.
729 *
730 * @return The value of the basis function @p mode at @p coords.
731 */
733 const Array<OneD, const NekDouble> &coords, int mode)
734{
735 ASSERTL2(coords[0] > -1 - NekConstants::kNekZeroTol, "coord[0] < -1");
736 ASSERTL2(coords[0] < 1 + NekConstants::kNekZeroTol, "coord[0] > 1");
737 ASSERTL2(coords[1] > -1 - NekConstants::kNekZeroTol, "coord[1] < -1");
738 ASSERTL2(coords[1] < 1 + NekConstants::kNekZeroTol, "coord[1] > 1");
739
740 const int nm0 = m_base[0]->GetNumModes();
741 const int nm1 = m_base[1]->GetNumModes();
742
743 return StdExpansion::BaryEvaluateBasis<0>(coords[0], mode % nm1) *
744 StdExpansion::BaryEvaluateBasis<1>(coords[1], mode / nm0);
745}
746
748 const Array<OneD, NekDouble> &coord,
749 const Array<OneD, const NekDouble> &inarray,
750 std::array<NekDouble, 3> &firstOrderDerivs)
751{
752 return BaryTensorDeriv(coord, inarray, firstOrderDerivs);
753}
754
755//////////////
756// Mappings //
757//////////////
758
760{
761 int i;
762 int cnt = 0;
763 int nummodes0, nummodes1;
764 int value1 = 0, value2 = 0;
765 if (outarray.size() != NumBndryCoeffs())
766 {
768 }
769
770 nummodes0 = m_base[0]->GetNumModes();
771 nummodes1 = m_base[1]->GetNumModes();
772
773 const LibUtilities::BasisType Btype0 = GetBasisType(0);
774 const LibUtilities::BasisType Btype1 = GetBasisType(1);
775
776 switch (Btype1)
777 {
780 value1 = nummodes0;
781 break;
783 value1 = 2 * nummodes0;
784 break;
785 default:
786 ASSERTL0(0, "Mapping array is not defined for this expansion");
787 break;
788 }
789
790 for (i = 0; i < value1; i++)
791 {
792 outarray[i] = i;
793 }
794 cnt = value1;
795
796 switch (Btype0)
797 {
800 value2 = value1 + nummodes0 - 1;
801 break;
803 value2 = value1 + 1;
804 break;
805 default:
806 ASSERTL0(0, "Mapping array is not defined for this expansion");
807 break;
808 }
809
810 for (i = 0; i < nummodes1 - 2; i++)
811 {
812 outarray[cnt++] = value1 + i * nummodes0;
813 outarray[cnt++] = value2 + i * nummodes0;
814 }
815
816 if (Btype1 == LibUtilities::eGLL_Lagrange ||
818 {
819 for (i = nummodes0 * (nummodes1 - 1); i < GetNcoeffs(); i++)
820 {
821 outarray[cnt++] = i;
822 }
823 }
824}
825
827{
828 int i, j;
829 int cnt = 0;
830 int nummodes0, nummodes1;
831 int startvalue = 0;
832 if (outarray.size() != GetNcoeffs() - NumBndryCoeffs())
833 {
835 }
836
837 nummodes0 = m_base[0]->GetNumModes();
838 nummodes1 = m_base[1]->GetNumModes();
839
840 const LibUtilities::BasisType Btype0 = GetBasisType(0);
841 const LibUtilities::BasisType Btype1 = GetBasisType(1);
842
843 switch (Btype1)
844 {
846 startvalue = nummodes0;
847 break;
849 startvalue = 2 * nummodes0;
850 break;
851 default:
852 ASSERTL0(0, "Mapping array is not defined for this expansion");
853 break;
854 }
855
856 switch (Btype0)
857 {
859 startvalue++;
860 break;
862 startvalue += 2;
863 break;
864 default:
865 ASSERTL0(0, "Mapping array is not defined for this expansion");
866 break;
867 }
868
869 for (i = 0; i < nummodes1 - 2; i++)
870 {
871 for (j = 0; j < nummodes0 - 2; j++)
872 {
873 outarray[cnt++] = startvalue + j;
874 }
875 startvalue += nummodes0;
876 }
877}
878
879int StdQuadExp::v_GetVertexMap(int localVertexId, bool useCoeffPacking)
880{
881 int localDOF = 0;
882
883 if (useCoeffPacking == true)
884 {
885 switch (localVertexId)
886 {
887 case 0:
888 {
889 localDOF = 0;
890 }
891 break;
892 case 1:
893 {
895 {
896 localDOF = m_base[0]->GetNumModes() - 1;
897 }
898 else
899 {
900 localDOF = 1;
901 }
902 }
903 break;
904 case 2:
905 {
907 {
908 localDOF = m_base[0]->GetNumModes() *
909 (m_base[1]->GetNumModes() - 1);
910 }
911 else
912 {
913 localDOF = m_base[0]->GetNumModes();
914 }
915 }
916 break;
917 case 3:
918 {
920 {
921 localDOF =
922 m_base[0]->GetNumModes() * m_base[1]->GetNumModes() - 1;
923 }
924 else
925 {
926 localDOF = m_base[0]->GetNumModes() + 1;
927 }
928 }
929 break;
930 default:
931 ASSERTL0(false, "eid must be between 0 and 3");
932 break;
933 }
934 }
935 else
936 {
937 switch (localVertexId)
938 {
939 case 0:
940 {
941 localDOF = 0;
942 }
943 break;
944 case 1:
945 {
947 {
948 localDOF = m_base[0]->GetNumModes() - 1;
949 }
950 else
951 {
952 localDOF = 1;
953 }
954 }
955 break;
956 case 2:
957 {
959 {
960 localDOF =
961 m_base[0]->GetNumModes() * m_base[1]->GetNumModes() - 1;
962 }
963 else
964 {
965 localDOF = m_base[0]->GetNumModes() + 1;
966 }
967 }
968 break;
969 case 3:
970 {
972 {
973 localDOF = m_base[0]->GetNumModes() *
974 (m_base[1]->GetNumModes() - 1);
975 }
976 else
977 {
978 localDOF = m_base[0]->GetNumModes();
979 }
980 }
981 break;
982 default:
983 ASSERTL0(false, "eid must be between 0 and 3");
984 break;
985 }
986 }
987 return localDOF;
988}
989
990/** \brief Get the map of the coefficient location to teh
991 * local trace coefficients
992 */
993
994void StdQuadExp::v_GetTraceCoeffMap(const unsigned int traceid,
996{
997 ASSERTL1(traceid < 4, "traceid must be between 0 and 3");
998
999 unsigned int i;
1000 unsigned int order0 = m_base[0]->GetNumModes();
1001 unsigned int order1 = m_base[1]->GetNumModes();
1002 unsigned int numModes = (traceid % 2) ? order1 : order0;
1003
1004 if (maparray.size() != numModes)
1005 {
1006 maparray = Array<OneD, unsigned int>(numModes);
1007 }
1008
1009 const LibUtilities::BasisType bType = GetBasisType(traceid % 2);
1010
1011 if (bType == LibUtilities::eModified_A)
1012 {
1013 switch (traceid)
1014 {
1015 case 0:
1016 {
1017 for (i = 0; i < numModes; i++)
1018 {
1019 maparray[i] = i;
1020 }
1021 }
1022 break;
1023 case 1:
1024 {
1025 for (i = 0; i < numModes; i++)
1026 {
1027 maparray[i] = i * order0 + 1;
1028 }
1029 }
1030 break;
1031 case 2:
1032 {
1033 for (i = 0; i < numModes; i++)
1034 {
1035 maparray[i] = order0 + i;
1036 }
1037 }
1038 break;
1039 case 3:
1040 {
1041 for (i = 0; i < numModes; i++)
1042 {
1043 maparray[i] = i * order0;
1044 }
1045 }
1046 break;
1047 default:
1048 break;
1049 }
1050 }
1051 else if (bType == LibUtilities::eGLL_Lagrange ||
1053 {
1054 switch (traceid)
1055 {
1056 case 0:
1057 {
1058 for (i = 0; i < numModes; i++)
1059 {
1060 maparray[i] = i;
1061 }
1062 }
1063 break;
1064 case 1:
1065 {
1066 for (i = 0; i < numModes; i++)
1067 {
1068 maparray[i] = (i + 1) * order0 - 1;
1069 }
1070 }
1071 break;
1072 case 2:
1073 {
1074 for (i = 0; i < numModes; i++)
1075 {
1076 maparray[i] = order0 * (order1 - 1) + i;
1077 }
1078 }
1079 break;
1080 case 3:
1081 {
1082 for (i = 0; i < numModes; i++)
1083 {
1084 maparray[i] = order0 * i;
1085 }
1086 }
1087 break;
1088 default:
1089 break;
1090 }
1091 }
1092 else
1093 {
1094 ASSERTL0(false, "Mapping not defined for this type of basis");
1095 }
1096}
1097
1099 const int eid, Array<OneD, unsigned int> &maparray,
1100 Array<OneD, int> &signarray, const Orientation edgeOrient)
1101{
1102 int i;
1103 const int nummodes0 = m_base[0]->GetNumModes();
1104 const int nummodes1 = m_base[1]->GetNumModes();
1105 const int nEdgeIntCoeffs = GetTraceNcoeffs(eid) - 2;
1106 const LibUtilities::BasisType bType = GetBasisType(eid % 2);
1107
1108 if (maparray.size() != nEdgeIntCoeffs)
1109 {
1110 maparray = Array<OneD, unsigned int>(nEdgeIntCoeffs);
1111 }
1112
1113 if (signarray.size() != nEdgeIntCoeffs)
1114 {
1115 signarray = Array<OneD, int>(nEdgeIntCoeffs, 1);
1116 }
1117 else
1118 {
1119 fill(signarray.data(), signarray.data() + nEdgeIntCoeffs, 1);
1120 }
1121
1122 if (bType == LibUtilities::eModified_A)
1123 {
1124 switch (eid)
1125 {
1126 case 0:
1127 {
1128 for (i = 0; i < nEdgeIntCoeffs; i++)
1129 {
1130 maparray[i] = i + 2;
1131 }
1132 }
1133 break;
1134 case 1:
1135 {
1136 for (i = 0; i < nEdgeIntCoeffs; i++)
1137 {
1138 maparray[i] = (i + 2) * nummodes0 + 1;
1139 }
1140 }
1141 break;
1142 case 2:
1143 {
1144 for (i = 0; i < nEdgeIntCoeffs; i++)
1145 {
1146 maparray[i] = nummodes0 + i + 2;
1147 }
1148 }
1149 break;
1150 case 3:
1151 {
1152 for (i = 0; i < nEdgeIntCoeffs; i++)
1153 {
1154 maparray[i] = (i + 2) * nummodes0;
1155 }
1156 }
1157 break;
1158 default:
1159 ASSERTL0(false, "eid must be between 0 and 3");
1160 break;
1161 }
1162
1163 if (edgeOrient == eBackwards)
1164 {
1165 for (i = 1; i < nEdgeIntCoeffs; i += 2)
1166 {
1167 signarray[i] = -1;
1168 }
1169 }
1170 }
1171 else if (bType == LibUtilities::eGLL_Lagrange)
1172 {
1173 switch (eid)
1174 {
1175 case 0:
1176 {
1177 for (i = 0; i < nEdgeIntCoeffs; i++)
1178 {
1179 maparray[i] = i + 1;
1180 }
1181 }
1182 break;
1183 case 1:
1184 {
1185 for (i = 0; i < nEdgeIntCoeffs; i++)
1186 {
1187 maparray[i] = (i + 2) * nummodes0 - 1;
1188 }
1189 }
1190 break;
1191 case 2:
1192 {
1193 for (i = 0; i < nEdgeIntCoeffs; i++)
1194 {
1195 maparray[i] = nummodes0 * (nummodes1 - 1) + i + 1;
1196 }
1197 }
1198 break;
1199 case 3:
1200 {
1201 for (i = 0; i < nEdgeIntCoeffs; i++)
1202 {
1203 maparray[i] = nummodes0 * (i + 1);
1204 }
1205 }
1206 break;
1207 default:
1208 ASSERTL0(false, "eid must be between 0 and 3");
1209 break;
1210 }
1211 if (edgeOrient == eBackwards)
1212 {
1213 reverse(maparray.data(), maparray.data() + nEdgeIntCoeffs);
1214 }
1215 }
1216 else
1217 {
1218 ASSERTL0(false, "Mapping not defined for this type of basis");
1219 }
1220}
1221
1222///////////////////////
1223// Wrapper Functions //
1224///////////////////////
1225
1227{
1228 int i, j;
1229 int order0 = GetBasisNumModes(0);
1230 int order1 = GetBasisNumModes(1);
1231 MatrixType mtype = mkey.GetMatrixType();
1232
1233 DNekMatSharedPtr Mat;
1234
1235 switch (mtype)
1236 {
1238 {
1239 int nq0 = m_base[0]->GetNumPoints();
1240 int nq1 = m_base[1]->GetNumPoints();
1241 int nq;
1242
1243 // take definition from key
1245 {
1246 nq = (int)mkey.GetConstFactor(eFactorConst);
1247 }
1248 else
1249 {
1250 nq = max(nq0, nq1);
1251 }
1252
1253 int neq =
1256 Array<OneD, NekDouble> coll(2);
1258 Array<OneD, NekDouble> tmp(nq0);
1259
1260 Mat = MemoryManager<DNekMat>::AllocateSharedPtr(neq, nq0 * nq1);
1261 int cnt = 0;
1262
1263 for (i = 0; i < nq; ++i)
1264 {
1265 for (j = 0; j < nq; ++j, ++cnt)
1266 {
1267 coords[cnt] = Array<OneD, NekDouble>(2);
1268 coords[cnt][0] = -1.0 + 2 * j / (NekDouble)(nq - 1);
1269 coords[cnt][1] = -1.0 + 2 * i / (NekDouble)(nq - 1);
1270 }
1271 }
1272
1273 for (i = 0; i < neq; ++i)
1274 {
1275 LocCoordToLocCollapsed(coords[i], coll);
1276
1277 I[0] = m_base[0]->GetI(coll);
1278 I[1] = m_base[1]->GetI(coll + 1);
1279
1280 // interpolate first coordinate direction
1281 for (j = 0; j < nq1; ++j)
1282 {
1283 NekDouble fac = (I[1]->GetPtr())[j];
1284 Vmath::Smul(nq0, fac, I[0]->GetPtr(), 1, tmp, 1);
1285
1286 Vmath::Vcopy(nq0, &tmp[0], 1,
1287 Mat->GetRawPtr() + j * nq0 * neq + i, neq);
1288 }
1289 }
1290 break;
1291 }
1292 case eMass:
1293 {
1295 // For Fourier basis set the imaginary component of mean mode
1296 // to have a unit diagonal component in mass matrix
1298 {
1299 for (i = 0; i < order1; ++i)
1300 {
1301 (*Mat)(order0 *i + 1, i * order0 + 1) = 1.0;
1302 }
1303 }
1304
1306 {
1307 for (i = 0; i < order0; ++i)
1308 {
1309 (*Mat)(order0 + i, order0 + i) = 1.0;
1310 }
1311 }
1312 break;
1313 }
1314 case eFwdTrans:
1315 {
1316 Mat =
1318 StdMatrixKey iprodkey(eIProductWRTBase, DetShapeType(), *this);
1319 DNekMat &Iprod = *GetStdMatrix(iprodkey);
1320 StdMatrixKey imasskey(eInvMass, DetShapeType(), *this);
1321 DNekMat &Imass = *GetStdMatrix(imasskey);
1322
1323 (*Mat) = Imass * Iprod;
1324 break;
1325 }
1326 case eGaussDG:
1327 {
1328 ConstFactorMap factors = mkey.GetConstFactors();
1329
1330 int edge = (int)factors[StdRegions::eFactorGaussEdge];
1331 int dir = (edge + 1) % 2;
1332 int nCoeffs = m_base[dir]->GetNumModes();
1333
1334 const LibUtilities::PointsKey BS_p(
1337 nCoeffs, BS_p);
1338
1339 Array<OneD, NekDouble> coords(1, 0.0);
1340 coords[0] = (edge == 0 || edge == 3) ? -1.0 : 1.0;
1341
1344 DNekMatSharedPtr m_Ix = basis->GetI(coords);
1345
1347 Vmath::Vcopy(nCoeffs, m_Ix->GetPtr(), 1, Mat->GetPtr(), 1);
1348 break;
1349 }
1350 default:
1351 {
1353 break;
1354 }
1355 }
1356
1357 return Mat;
1358}
1359
1361{
1362 return GenMatrix(mkey);
1363}
1364
1365///////////////////////////////////
1366// Operator evaluation functions //
1367///////////////////////////////////
1368
1370 const StdMatrixKey &mkey)
1371{
1372 // Generate an orthonogal expansion
1373 int qa = m_base[0]->GetNumPoints();
1374 int qb = m_base[1]->GetNumPoints();
1375 int nmodes_a = m_base[0]->GetNumModes();
1376 int nmodes_b = m_base[1]->GetNumModes();
1377 int nmodes = min(nmodes_a, nmodes_b);
1378 // Declare orthogonal basis.
1381
1384 StdQuadExp OrthoExp(Ba, Bb);
1385
1386 // SVV parameters loaded from the .xml case file
1387 Array<OneD, NekDouble> orthocoeffs(OrthoExp.GetNcoeffs());
1388
1389 // project onto modal space.
1390 OrthoExp.FwdTrans(array, orthocoeffs);
1391
1392 if (mkey.ConstFactorExists(
1393 eFactorSVVPowerKerDiffCoeff)) // Rodrigo's power kernel
1394 {
1396 NekDouble SvvDiffCoeff =
1399
1400 for (int j = 0; j < nmodes_a; ++j)
1401 {
1402 for (int k = 0; k < nmodes_b; ++k)
1403 {
1404 // linear space but makes high modes very negative
1405 NekDouble fac = std::max(
1406 pow((1.0 * j) / (nmodes_a - 1), cutoff * nmodes_a),
1407 pow((1.0 * k) / (nmodes_b - 1), cutoff * nmodes_b));
1408
1409 orthocoeffs[j * nmodes_b + k] *= SvvDiffCoeff * fac;
1410 }
1411 }
1412 }
1413 else if (mkey.ConstFactorExists(
1414 eFactorSVVDGKerDiffCoeff)) // Rodrigo/mansoor's DG kernel
1415 {
1418 int max_ab = max(nmodes_a - kSVVDGFiltermodesmin,
1419 nmodes_b - kSVVDGFiltermodesmin);
1420 max_ab = max(max_ab, 0);
1421 max_ab = min(max_ab, kSVVDGFiltermodesmax - kSVVDGFiltermodesmin);
1422
1423 for (int j = 0; j < nmodes_a; ++j)
1424 {
1425 for (int k = 0; k < nmodes_b; ++k)
1426 {
1427 int maxjk = max(j, k);
1428 maxjk = min(maxjk, kSVVDGFiltermodesmax - 1);
1429
1430 orthocoeffs[j * nmodes_b + k] *=
1431 SvvDiffCoeff * kSVVDGFilter[max_ab][maxjk];
1432 }
1433 }
1434 }
1435 else
1436 {
1437 NekDouble SvvDiffCoeff = mkey.GetConstFactor(eFactorSVVDiffCoeff);
1438 // Exponential Kernel implementation
1439 int cutoff = (int)(mkey.GetConstFactor(eFactorSVVCutoffRatio) *
1440 min(nmodes_a, nmodes_b));
1441
1442 //------"New" Version August 22nd '13--------------------
1443 for (int j = 0; j < nmodes_a; ++j)
1444 {
1445 for (int k = 0; k < nmodes_b; ++k)
1446 {
1447 if (j + k >= cutoff) // to filter out only the "high-modes"
1448 {
1449 orthocoeffs[j * nmodes_b + k] *=
1450 (SvvDiffCoeff *
1451 exp(-(j + k - nmodes) * (j + k - nmodes) /
1452 ((NekDouble)((j + k - cutoff + 1) *
1453 (j + k - cutoff + 1)))));
1454 }
1455 else
1456 {
1457 orthocoeffs[j * nmodes_b + k] *= 0.0;
1458 }
1459 }
1460 }
1461 }
1462
1463 // backward transform to physical space
1464 OrthoExp.BwdTrans(orthocoeffs, array);
1465}
1466
1468 const NekDouble alpha,
1469 const NekDouble exponent,
1470 const NekDouble cutoff)
1471{
1472 // Generate an orthogonal expansion
1473 int qa = m_base[0]->GetNumPoints();
1474 int qb = m_base[1]->GetNumPoints();
1475 int nmodesA = m_base[0]->GetNumModes();
1476 int nmodesB = m_base[1]->GetNumModes();
1477 int P = nmodesA - 1;
1478 int Q = nmodesB - 1;
1479
1480 // Declare orthogonal basis.
1483
1486 StdQuadExp OrthoExp(Ba, Bb);
1487
1488 // Cutoff
1489 int Pcut = cutoff * P;
1490 int Qcut = cutoff * Q;
1491
1492 // Project onto orthogonal space.
1493 Array<OneD, NekDouble> orthocoeffs(OrthoExp.GetNcoeffs());
1494 OrthoExp.FwdTrans(array, orthocoeffs);
1495
1496 //
1497 NekDouble fac, fac1, fac2;
1498 for (int i = 0; i < nmodesA; ++i)
1499 {
1500 for (int j = 0; j < nmodesB; ++j)
1501 {
1502 // to filter out only the "high-modes"
1503 if (i > Pcut || j > Qcut)
1504 {
1505 fac1 = (NekDouble)(i - Pcut) / ((NekDouble)(P - Pcut));
1506 fac2 = (NekDouble)(j - Qcut) / ((NekDouble)(Q - Qcut));
1507 fac = max(fac1, fac2);
1508 fac = pow(fac, exponent);
1509 orthocoeffs[i * nmodesB + j] *= exp(-alpha * fac);
1510 }
1511 }
1512 }
1513
1514 // backward transform to physical space
1515 OrthoExp.BwdTrans(orthocoeffs, array);
1516}
1517
1519 int numMin, const Array<OneD, const NekDouble> &inarray,
1520 Array<OneD, NekDouble> &outarray)
1521{
1522 int n_coeffs = inarray.size();
1523
1524 Array<OneD, NekDouble> coeff(n_coeffs);
1525 Array<OneD, NekDouble> coeff_tmp(n_coeffs, 0.0);
1528
1529 int nmodes0 = m_base[0]->GetNumModes();
1530 int nmodes1 = m_base[1]->GetNumModes();
1531 int numMax = nmodes0;
1532
1533 Vmath::Vcopy(n_coeffs, inarray, 1, coeff_tmp, 1);
1534
1535 const LibUtilities::PointsKey Pkey0(nmodes0,
1537 const LibUtilities::PointsKey Pkey1(nmodes1,
1539
1540 LibUtilities::BasisKey b0(m_base[0]->GetBasisType(), nmodes0, Pkey0);
1541 LibUtilities::BasisKey b1(m_base[1]->GetBasisType(), nmodes1, Pkey1);
1542
1543 LibUtilities::BasisKey bortho0(LibUtilities::eOrtho_A, nmodes0, Pkey0);
1544 LibUtilities::BasisKey bortho1(LibUtilities::eOrtho_A, nmodes1, Pkey1);
1545
1546 LibUtilities::InterpCoeff2D(b0, b1, coeff_tmp, bortho0, bortho1, coeff);
1547
1548 Vmath::Zero(n_coeffs, coeff_tmp, 1);
1549
1550 int cnt = 0;
1551 for (int i = 0; i < numMin + 1; ++i)
1552 {
1553 Vmath::Vcopy(numMin, tmp = coeff + cnt, 1, tmp2 = coeff_tmp + cnt, 1);
1554
1555 cnt = i * numMax;
1556 }
1557
1558 LibUtilities::InterpCoeff2D(bortho0, bortho1, coeff_tmp, b0, b1, outarray);
1559}
1560
1562 Array<OneD, NekDouble> &outarray,
1563 const StdMatrixKey &mkey)
1564{
1565 StdExpansion::MassMatrixOp_MatFree(inarray, outarray, mkey);
1566}
1567
1569 const Array<OneD, const NekDouble> &inarray,
1570 Array<OneD, NekDouble> &outarray, const StdMatrixKey &mkey)
1571{
1572 StdQuadExp::v_LaplacianMatrixOp_MatFree(inarray, outarray, mkey);
1573}
1574
1576 const int k1, const int k2, const Array<OneD, const NekDouble> &inarray,
1577 Array<OneD, NekDouble> &outarray, const StdMatrixKey &mkey)
1578{
1579 StdExpansion::LaplacianMatrixOp_MatFree(k1, k2, inarray, outarray, mkey);
1580}
1581
1583 const int i, const Array<OneD, const NekDouble> &inarray,
1584 Array<OneD, NekDouble> &outarray, const StdMatrixKey &mkey)
1585{
1586 StdExpansion::WeakDerivMatrixOp_MatFree(i, inarray, outarray, mkey);
1587}
1588
1590 const Array<OneD, const NekDouble> &inarray,
1591 Array<OneD, NekDouble> &outarray, const StdMatrixKey &mkey)
1592{
1593 StdQuadExp::v_HelmholtzMatrixOp_MatFree(inarray, outarray, mkey);
1594}
1595
1596// up to here
1598 const Array<OneD, const NekDouble> &inarray,
1599 Array<OneD, NekDouble> &outarray)
1600{
1601 int i;
1602 int nquad0 = m_base[0]->GetNumPoints();
1603 int nquad1 = m_base[1]->GetNumPoints();
1604
1605 const Array<OneD, const NekDouble> &w0 = m_base[0]->GetW();
1606 const Array<OneD, const NekDouble> &w1 = m_base[1]->GetW();
1607
1608 // multiply by integration constants
1609 for (i = 0; i < nquad1; ++i)
1610 {
1611 Vmath::Vmul(nquad0, inarray.data() + i * nquad0, 1, w0.data(), 1,
1612 outarray.data() + i * nquad0, 1);
1613 }
1614
1615 for (i = 0; i < nquad0; ++i)
1616 {
1617 Vmath::Vmul(nquad1, outarray.data() + i, nquad0, w1.data(), 1,
1618 outarray.data() + i, nquad0);
1619 }
1620}
1621
1623 Array<OneD, int> &conn, [[maybe_unused]] bool standard)
1624{
1625 int np1 = m_base[0]->GetNumPoints();
1626 int np2 = m_base[1]->GetNumPoints();
1627 int np = max(np1, np2);
1628
1629 conn = Array<OneD, int>(6 * (np - 1) * (np - 1));
1630
1631 int row = 0;
1632 int rowp1 = 0;
1633 int cnt = 0;
1634 for (int i = 0; i < np - 1; ++i)
1635 {
1636 rowp1 += np;
1637 for (int j = 0; j < np - 1; ++j)
1638 {
1639 conn[cnt++] = row + j;
1640 conn[cnt++] = row + j + 1;
1641 conn[cnt++] = rowp1 + j;
1642
1643 conn[cnt++] = rowp1 + j + 1;
1644 conn[cnt++] = rowp1 + j;
1645 conn[cnt++] = row + j + 1;
1646 }
1647 row += np;
1648 }
1649}
1650
1651} // namespace Nektar::StdRegions
#define ASSERTL0(condition, msg)
#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
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)
const LibUtilities::BasisSharedPtr & GetBasis(int dir) const
This function gets the shared point to basis in the dir direction.
int GetNcoeffs(void) const
This function returns the total number of coefficients used in the expansion.
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)
DNekMatSharedPtr CreateGeneralMatrix(const StdMatrixKey &mkey)
this function generates the mass matrix
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 LaplacianMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
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 GetInteriorMap(Array< OneD, unsigned int > &outarray)
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.
DNekMatSharedPtr GenMatrix(const StdMatrixKey &mkey)
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.
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
const ConstFactorMap & GetConstFactors() const
NekDouble GetConstFactor(const ConstFactorType &factor) const
bool ConstFactorExists(const ConstFactorType &factor) const
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_BwdTrans_SumFac(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
void v_ExponentialFilter(Array< OneD, NekDouble > &array, const NekDouble alpha, const NekDouble exponent, const NekDouble cutoff) 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
int v_NumDGBndryCoeffs() const final
void v_FwdTransBndConstrained(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
void v_LocCoordToLocCollapsed(const Array< OneD, const NekDouble > &xi, Array< OneD, NekDouble > &eta) override
int v_GetVertexMap(int localVertexId, bool useCoeffPacking=false) override
void v_IProductWRTDerivBase_SumFac(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
void v_MultiplyByStdQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
bool v_IsBoundaryInteriorExpansion() const override
int v_GetTraceNcoeffs(const int i) const final
void v_ReduceOrderCoeffs(int numMin, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
int v_GetTraceNumPoints(const int i) const final
void v_HelmholtzMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey) override
int v_NumBndryCoeffs() const final
void v_SVVLaplacianFilter(Array< OneD, NekDouble > &array, const StdMatrixKey &mkey) override
void v_GetCoords(Array< OneD, NekDouble > &coords_0, Array< OneD, NekDouble > &coords_1, Array< OneD, NekDouble > &coords_2) override
NekDouble v_PhysEvaluateBasis(const Array< OneD, const NekDouble > &coords, int mode) override
This function evaluates the basis function mode mode at a point coords of the domain.
int v_CalcNumberOfCoefficients(const std::vector< unsigned int > &nummodes, int &modes_offset) 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*base1 and put into outarray.
void v_GetInteriorMap(Array< OneD, unsigned int > &outarray) override
NekDouble v_Integral(const Array< OneD, const NekDouble > &inarray) override
Integrates the specified function over the domain.
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_BwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) override
void v_WeakDerivMatrixOp(const int i, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey) override
void v_LocCollapsedToLocCoord(const Array< OneD, const NekDouble > &eta, Array< OneD, NekDouble > &xi) override
NekDouble v_PhysEvalFirstDeriv(const Array< OneD, NekDouble > &coord, const Array< OneD, const NekDouble > &inarray, std::array< NekDouble, 3 > &firstOrderDerivs) override
void v_GetTraceCoeffMap(const unsigned int traceid, Array< OneD, unsigned int > &maparray) override
Get the map of the coefficient location to teh local trace coefficients.
const LibUtilities::BasisKey v_GetTraceBasisKey(const int i, const int j, bool UseGLL=false) const final
DNekMatSharedPtr v_CreateStdMatrix(const StdMatrixKey &mkey) 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_IProductWRTBase_SumFac(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool multiplybyweights=true) override
void v_IProductWRTDerivBase(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray) 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
void v_GetTraceInteriorToElementMap(const int eid, Array< OneD, unsigned int > &maparray, Array< OneD, int > &signarray, const Orientation edgeOrient=eForwards) 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_GetBoundaryMap(Array< OneD, unsigned int > &outarray) override
DNekMatSharedPtr v_GenMatrix(const StdMatrixKey &mkey) override
int v_GetTraceIntNcoeffs(const int i) const final
StdQuadExp(const LibUtilities::BasisKey &Ba, const LibUtilities::BasisKey &Bb)
Constructor using BasisKey class for quadrature points and order definition.
void v_LaplacianMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey) override
LibUtilities::ShapeType v_DetShapeType() const final
void v_FillMode(const int mode, Array< OneD, NekDouble > &array) override
Fill outarray with mode mode of expansion.
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 Dcopy(const int &n, const double *x, const int &incx, double *y, const int &incy)
BLAS level 1: Copy x to y.
Definition Blas.hpp:128
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
int getNumberOfCoefficients(int Na, int Nb)
BasisManagerT & BasisManager(void)
std::shared_ptr< Basis > BasisSharedPtr
void InterpCoeff2D(const BasisKey &fbasis0, const BasisKey &fbasis1, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, Array< OneD, NekDouble > &to)
@ eGaussLobattoLegendre
1D Gauss-Lobatto-Legendre quadrature points
Definition PointsType.h:51
@ eGaussGaussLegendre
1D Gauss-Gauss-Legendre quadrature points
Definition PointsType.h:46
@ P
Monomial polynomials .
Definition BasisType.h:62
@ eGauss_Lagrange
Lagrange Polynomials using the Gauss points.
Definition BasisType.h:57
@ eOrtho_A
Principle Orthogonal Functions .
Definition BasisType.h:42
@ eGLL_Lagrange
Lagrange for SEM basis .
Definition BasisType.h:56
@ eModified_A
Principle Modified Functions .
Definition BasisType.h:48
@ eFourier
Fourier Expansion .
Definition BasisType.h:55
static const NekDouble kNekZeroTol
const int kSVVDGFiltermodesmin
const int kSVVDGFiltermodesmax
const NekDouble kSVVDGFilter[9][11]
std::map< ConstFactorType, NekDouble > ConstFactorMap
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 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 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
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