Nektar++
StdPyrExp.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File StdPyrExp.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: pyramidic routines built upon StdExpansion3D
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <boost/core/ignore_unused.hpp>
36 
38 #include <StdRegions/StdPyrExp.h>
39 #include <iomanip>
40 
41 using namespace std;
42 
43 namespace Nektar
44 {
45 namespace StdRegions
46 {
47 StdPyrExp::StdPyrExp() // Deafult construct of standard expansion directly
48  // called.
49 {
50 }
51 
52 StdPyrExp::StdPyrExp(const LibUtilities::BasisKey &Ba,
53  const LibUtilities::BasisKey &Bb,
54  const LibUtilities::BasisKey &Bc)
55  : StdExpansion(LibUtilities::StdPyrData::getNumberOfCoefficients(
56  Ba.GetNumModes(), Bb.GetNumModes(), Bc.GetNumModes()),
57  3, Ba, Bb, Bc),
58  StdExpansion3D(LibUtilities::StdPyrData::getNumberOfCoefficients(
59  Ba.GetNumModes(), Bb.GetNumModes(), Bc.GetNumModes()),
60  Ba, Bb, Bc)
61 {
62 
63  ASSERTL0(Ba.GetNumModes() <= Bc.GetNumModes(),
64  "order in 'a' direction is higher "
65  "than order in 'c' direction");
66  ASSERTL0(Bb.GetNumModes() <= Bc.GetNumModes(),
67  "order in 'b' direction is higher "
68  "than order in 'c' direction");
71  "Expected basis type in 'c' direction to be ModifiedPyr_C or "
72  "OrthoPyr_C");
73 }
74 
76 {
77 }
78 
79 // Destructor
81 {
82 }
83 
84 //---------------------------------------
85 // Differentiation/integration Methods
86 //---------------------------------------
87 
88 /**
89  * \brief Calculate the derivative of the physical points
90  *
91  * The derivative is evaluated at the nodal physical points.
92  * Derivatives with respect to the local Cartesian coordinates.
93  *
94  * \f$\begin{Bmatrix} \frac {\partial} {\partial \xi_1} \\ \frac
95  * {\partial} {\partial \xi_2} \\ \frac {\partial} {\partial \xi_3}
96  * \end{Bmatrix} = \begin{Bmatrix} \frac 2 {(1-\eta_3)} \frac \partial
97  * {\partial \bar \eta_1} \\ \frac {\partial} {\partial \xi_2} \ \
98  * \frac {(1 + \bar \eta_1)} {(1 - \eta_3)} \frac \partial {\partial
99  * \bar \eta_1} + \frac {\partial} {\partial \eta_3} \end{Bmatrix}\f$
100  */
102  Array<OneD, NekDouble> &out_dxi1,
103  Array<OneD, NekDouble> &out_dxi2,
104  Array<OneD, NekDouble> &out_dxi3)
105 {
106  // PhysDerivative implementation based on Spen's book page 152.
107  int Qx = m_base[0]->GetNumPoints();
108  int Qy = m_base[1]->GetNumPoints();
109  int Qz = m_base[2]->GetNumPoints();
110 
111  Array<OneD, NekDouble> dEta_bar1(Qx * Qy * Qz, 0.0);
112  Array<OneD, NekDouble> dXi2(Qx * Qy * Qz, 0.0);
113  Array<OneD, NekDouble> dEta3(Qx * Qy * Qz, 0.0);
114  PhysTensorDeriv(u_physical, dEta_bar1, dXi2, dEta3);
115 
116  Array<OneD, const NekDouble> eta_x, eta_y, eta_z;
117  eta_x = m_base[0]->GetZ();
118  eta_y = m_base[1]->GetZ();
119  eta_z = m_base[2]->GetZ();
120 
121  int i, j, k, n;
122 
123  if (out_dxi1.size() > 0)
124  {
125  for (k = 0, n = 0; k < Qz; ++k)
126  {
127  NekDouble fac = 2.0 / (1.0 - eta_z[k]);
128  for (j = 0; j < Qy; ++j)
129  {
130  for (i = 0; i < Qx; ++i, ++n)
131  {
132  out_dxi1[n] = fac * dEta_bar1[n];
133  }
134  }
135  }
136  }
137 
138  if (out_dxi2.size() > 0)
139  {
140  for (k = 0, n = 0; k < Qz; ++k)
141  {
142  NekDouble fac = 2.0 / (1.0 - eta_z[k]);
143  for (j = 0; j < Qy; ++j)
144  {
145  for (i = 0; i < Qx; ++i, ++n)
146  {
147  out_dxi2[n] = fac * dXi2[n];
148  }
149  }
150  }
151  }
152 
153  if (out_dxi3.size() > 0)
154  {
155  for (k = 0, n = 0; k < Qz; ++k)
156  {
157  NekDouble fac = 1.0 / (1.0 - eta_z[k]);
158  for (j = 0; j < Qy; ++j)
159  {
160  NekDouble fac1 = (1.0 + eta_y[j]);
161  for (i = 0; i < Qx; ++i, ++n)
162  {
163  out_dxi3[n] = (1.0 + eta_x[i]) * fac * dEta_bar1[n] +
164  fac1 * fac * dXi2[n] + dEta3[n];
165  }
166  }
167  }
168  }
169 }
170 
171 void StdPyrExp::v_PhysDeriv(const int dir,
172  const Array<OneD, const NekDouble> &inarray,
173  Array<OneD, NekDouble> &outarray)
174 {
175  switch (dir)
176  {
177  case 0:
178  {
179  v_PhysDeriv(inarray, outarray, NullNekDouble1DArray,
181  break;
182  }
183 
184  case 1:
185  {
186  v_PhysDeriv(inarray, NullNekDouble1DArray, outarray,
188  break;
189  }
190 
191  case 2:
192  {
194  outarray);
195  break;
196  }
197 
198  default:
199  {
200  ASSERTL1(false, "input dir is out of range");
201  }
202  break;
203  }
204 }
205 
207  Array<OneD, NekDouble> &out_d0,
208  Array<OneD, NekDouble> &out_d1,
209  Array<OneD, NekDouble> &out_d2)
210 {
211  StdPyrExp::v_PhysDeriv(inarray, out_d0, out_d1, out_d2);
212 }
213 
214 void StdPyrExp::v_StdPhysDeriv(const int dir,
215  const Array<OneD, const NekDouble> &inarray,
216  Array<OneD, NekDouble> &outarray)
217 {
218  StdPyrExp::v_PhysDeriv(dir, inarray, outarray);
219 }
220 
221 //---------------------------------------
222 // Transforms
223 //---------------------------------------
224 
225 /**
226  * \brief Backward transformation is evaluated at the quadrature
227  * points.
228  *
229  * \f$ u^{\delta} (\xi_{1i}, \xi_{2j}, \xi_{3k}) = \sum_{m(pqr)} \hat
230  * u_{pqr} \phi_{pqr} (\xi_{1i}, \xi_{2j}, \xi_{3k})\f$
231  *
232  * Backward transformation is three dimensional tensorial expansion
233  *
234  * \f$ u (\xi_{1i}, \xi_{2j}, \xi_{3k}) = \sum_{p=0}^{Q_x} \psi_p^a
235  * (\xi_{1i}) \lbrace { \sum_{q=0}^{Q_y} \psi_{q}^a (\xi_{2j})
236  * \lbrace { \sum_{r=0}^{Q_z} \hat u_{pqr} \psi_{pqr}^c (\xi_{3k})
237  * \rbrace} \rbrace}. \f$
238  *
239  * And sumfactorizing step of the form is as:\ \ \f$ f_{pqr}
240  * (\xi_{3k}) = \sum_{r=0}^{Q_z} \hat u_{pqr} \psi_{pqr}^c
241  * (\xi_{3k}),\\ g_{p} (\xi_{2j}, \xi_{3k}) = \sum_{r=0}^{Q_y}
242  * \psi_{p}^a (\xi_{2j}) f_{pqr} (\xi_{3k}),\\ u(\xi_{1i}, \xi_{2j},
243  * \xi_{3k}) = \sum_{p=0}^{Q_x} \psi_{p}^a (\xi_{1i}) g_{p}
244  * (\xi_{2j}, \xi_{3k}). \f$
245  **/
247  Array<OneD, NekDouble> &outarray)
248 {
249  if (m_base[0]->Collocation() && m_base[1]->Collocation() &&
250  m_base[2]->Collocation())
251  {
253  m_base[2]->GetNumPoints(),
254  inarray, 1, outarray, 1);
255  }
256  else
257  {
258  StdPyrExp::v_BwdTrans_SumFac(inarray, outarray);
259  }
260 }
261 
262 /**
263  * Sum-factorisation implementation of the BwdTrans operation.
264  */
266  Array<OneD, NekDouble> &outarray)
267 {
268  int nquad0 = m_base[0]->GetNumPoints();
269  int nquad1 = m_base[1]->GetNumPoints();
270  int nquad2 = m_base[2]->GetNumPoints();
271  int order0 = m_base[0]->GetNumModes();
272  int order1 = m_base[1]->GetNumModes();
273 
274  Array<OneD, NekDouble> wsp(nquad2 * order0 * order1 +
275  nquad2 * nquad1 * nquad0);
276 
277  v_BwdTrans_SumFacKernel(m_base[0]->GetBdata(), m_base[1]->GetBdata(),
278  m_base[2]->GetBdata(), inarray, outarray, wsp, true,
279  true, true);
280 }
281 
283  const Array<OneD, const NekDouble> &base0,
284  const Array<OneD, const NekDouble> &base1,
285  const Array<OneD, const NekDouble> &base2,
286  const Array<OneD, const NekDouble> &inarray,
288  bool doCheckCollDir0, bool doCheckCollDir1, bool doCheckCollDir2)
289 {
290  boost::ignore_unused(doCheckCollDir0, doCheckCollDir1, doCheckCollDir2);
291 
292  int nquad0 = m_base[0]->GetNumPoints();
293  int nquad1 = m_base[1]->GetNumPoints();
294  int nquad2 = m_base[2]->GetNumPoints();
295 
296  int order0 = m_base[0]->GetNumModes();
297  int order1 = m_base[1]->GetNumModes();
298  int order2 = m_base[2]->GetNumModes();
299 
300  Array<OneD, NekDouble> tmp = wsp;
301  Array<OneD, NekDouble> tmp1 = tmp + nquad2 * order0 * order1;
302 
303  int i, j, mode, mode1, cnt;
304 
305  // Perform summation over '2' direction
306  mode = mode1 = cnt = 0;
307  for (i = 0; i < order0; ++i)
308  {
309  for (j = 0; j < order1; ++j, ++cnt)
310  {
311  int ijmax = max(i, j);
312  Blas::Dgemv('N', nquad2, order2 - ijmax, 1.0,
313  base2.get() + mode * nquad2, nquad2,
314  inarray.get() + mode1, 1, 0.0, tmp.get() + cnt * nquad2,
315  1);
316  mode += order2 - ijmax;
317  mode1 += order2 - ijmax;
318  }
319  // increment mode in case order1!=order2
320  for (j = order1; j < order2 - i; ++j)
321  {
322  int ijmax = max(i, j);
323  mode += order2 - ijmax;
324  }
325  }
326 
327  // fix for modified basis by adding split of top singular
328  // vertex mode - currently (1+c)/2 x (1-b)/2 x (1-a)/2
329  // component is evaluated
331  {
332 
333  // Not sure why we could not use basis as 1.0
334  // top singular vertex - (1+c)/2 x (1+b)/2 x (1-a)/2 component
335  Blas::Daxpy(nquad2, inarray[1], base2.get() + nquad2, 1,
336  &tmp[0] + nquad2, 1);
337 
338  // top singular vertex - (1+c)/2 x (1-b)/2 x (1+a)/2 component
339  Blas::Daxpy(nquad2, inarray[1], base2.get() + nquad2, 1,
340  &tmp[0] + order1 * nquad2, 1);
341 
342  // top singular vertex - (1+c)/2 x (1+b)/2 x (1+a)/2 component
343  Blas::Daxpy(nquad2, inarray[1], base2.get() + nquad2, 1,
344  &tmp[0] + order1 * nquad2 + nquad2, 1);
345  }
346 
347  // Perform summation over '1' direction
348  mode = 0;
349  for (i = 0; i < order0; ++i)
350  {
351  Blas::Dgemm('N', 'T', nquad1, nquad2, order1, 1.0, base1.get(), nquad1,
352  tmp.get() + mode * nquad2, nquad2, 0.0,
353  tmp1.get() + i * nquad1 * nquad2, nquad1);
354  mode += order1;
355  }
356 
357  // Perform summation over '0' direction
358  Blas::Dgemm('N', 'T', nquad0, nquad1 * nquad2, order0, 1.0, base0.get(),
359  nquad0, tmp1.get(), nquad1 * nquad2, 0.0, outarray.get(),
360  nquad0);
361 }
362 
363 /** \brief Forward transform from physical quadrature space
364  stored in \a inarray and evaluate the expansion coefficients and
365  store in \a outarray
366 
367  Inputs:\n
368 
369  - \a inarray: array of physical quadrature points to be transformed
370 
371  Outputs:\n
372 
373  - \a outarray: updated array of expansion coefficients.
374 
375 */
377  Array<OneD, NekDouble> &outarray)
378 {
379  v_IProductWRTBase(inarray, outarray);
380 
381  // get Mass matrix inverse
382  StdMatrixKey imasskey(eInvMass, DetShapeType(), *this);
383  DNekMatSharedPtr imatsys = GetStdMatrix(imasskey);
384 
385  // copy inarray in case inarray == outarray
386  DNekVec in(m_ncoeffs, outarray);
387  DNekVec out(m_ncoeffs, outarray, eWrapper);
388 
389  out = (*imatsys) * in;
390 }
391 
392 //---------------------------------------
393 // Inner product functions
394 //---------------------------------------
395 
396 /** \brief Inner product of \a inarray over region with respect to the
397  expansion basis m_base[0]->GetBdata(),m_base[1]->GetBdata(),
398  m_base[2]->GetBdata() and return in \a outarray
399 
400  Wrapper call to StdPyrExp::IProductWRTBase
401 
402  Input:\n
403 
404  - \a inarray: array of function evaluated at the physical collocation points
405 
406  Output:\n
407 
408  - \a outarray: array of inner product with respect to each basis over region
409 
410 */
412  Array<OneD, NekDouble> &outarray)
413 {
414  if (m_base[0]->Collocation() && m_base[1]->Collocation() &&
415  m_base[2]->Collocation())
416  {
417  v_MultiplyByStdQuadratureMetric(inarray, outarray);
418  }
419  else
420  {
421  StdPyrExp::v_IProductWRTBase_SumFac(inarray, outarray);
422  }
423 }
424 
426  const Array<OneD, const NekDouble> &inarray,
427  Array<OneD, NekDouble> &outarray, bool multiplybyweights)
428 {
429 
430  int nquad1 = m_base[1]->GetNumPoints();
431  int nquad2 = m_base[2]->GetNumPoints();
432  int order0 = m_base[0]->GetNumModes();
433  int order1 = m_base[1]->GetNumModes();
434 
435  Array<OneD, NekDouble> wsp(order0 * nquad2 * (nquad1 + order1));
436 
437  if (multiplybyweights)
438  {
439  Array<OneD, NekDouble> tmp(inarray.size());
440 
441  v_MultiplyByStdQuadratureMetric(inarray, tmp);
442 
444  m_base[0]->GetBdata(), m_base[1]->GetBdata(), m_base[2]->GetBdata(),
445  tmp, outarray, wsp, true, true, true);
446  }
447  else
448  {
450  m_base[0]->GetBdata(), m_base[1]->GetBdata(), m_base[2]->GetBdata(),
451  inarray, outarray, wsp, true, true, true);
452  }
453 }
454 
456  const Array<OneD, const NekDouble> &base0,
457  const Array<OneD, const NekDouble> &base1,
458  const Array<OneD, const NekDouble> &base2,
459  const Array<OneD, const NekDouble> &inarray,
461  bool doCheckCollDir0, bool doCheckCollDir1, bool doCheckCollDir2)
462 {
463  boost::ignore_unused(doCheckCollDir0, doCheckCollDir1, doCheckCollDir2);
464 
465  int nquad0 = m_base[0]->GetNumPoints();
466  int nquad1 = m_base[1]->GetNumPoints();
467  int nquad2 = m_base[2]->GetNumPoints();
468 
469  int order0 = m_base[0]->GetNumModes();
470  int order1 = m_base[1]->GetNumModes();
471  int order2 = m_base[2]->GetNumModes();
472 
473  ASSERTL1(wsp.size() >= nquad1 * nquad2 * order0 + nquad2 * order0 * order1,
474  "Insufficient workspace size");
475 
476  Array<OneD, NekDouble> tmp1 = wsp;
477  Array<OneD, NekDouble> tmp2 = wsp + nquad1 * nquad2 * order0;
478 
479  int i, j, mode, mode1, cnt;
480 
481  // Inner product with respect to the '0' direction
482  Blas::Dgemm('T', 'N', nquad1 * nquad2, order0, nquad0, 1.0, inarray.get(),
483  nquad0, base0.get(), nquad0, 0.0, tmp1.get(), nquad1 * nquad2);
484 
485  // Inner product with respect to the '1' direction
486  for (mode = i = 0; i < order0; ++i)
487  {
488  Blas::Dgemm('T', 'N', nquad2, order1, nquad1, 1.0,
489  tmp1.get() + i * nquad1 * nquad2, nquad1, base1.get(),
490  nquad1, 0.0, tmp2.get() + mode * nquad2, nquad2);
491  mode += order1;
492  }
493 
494  // Inner product with respect to the '2' direction
495  mode = mode1 = cnt = 0;
496  for (i = 0; i < order0; ++i)
497  {
498  for (j = 0; j < order1; ++j, ++cnt)
499  {
500  int ijmax = max(i, j);
501 
502  Blas::Dgemv('T', nquad2, order2 - ijmax, 1.0,
503  base2.get() + mode * nquad2, nquad2,
504  tmp2.get() + cnt * nquad2, 1, 0.0,
505  outarray.get() + mode1, 1);
506  mode += order2 - ijmax;
507  mode1 += order2 - ijmax;
508  }
509 
510  // increment mode in case order1!=order2
511  for (j = order1; j < order2; ++j)
512  {
513  int ijmax = max(i, j);
514  mode += order2 - ijmax;
515  }
516  }
517 
518  // fix for modified basis for top singular vertex component
519  // Already have evaluated (1+c)/2 (1-b)/2 (1-a)/2
521  {
522  // add in (1+c)/2 (1+b)/2 (1-a)/2 component
523  outarray[1] +=
524  Blas::Ddot(nquad2, base2.get() + nquad2, 1, &tmp2[nquad2], 1);
525 
526  // add in (1+c)/2 (1-b)/2 (1+a)/2 component
527  outarray[1] += Blas::Ddot(nquad2, base2.get() + nquad2, 1,
528  &tmp2[nquad2 * order1], 1);
529 
530  // add in (1+c)/2 (1+b)/2 (1+a)/2 component
531  outarray[1] += Blas::Ddot(nquad2, base2.get() + nquad2, 1,
532  &tmp2[nquad2 * order1 + nquad2], 1);
533  }
534 }
535 
537  const int dir, const Array<OneD, const NekDouble> &inarray,
538  Array<OneD, NekDouble> &outarray)
539 {
540  StdPyrExp::v_IProductWRTDerivBase_SumFac(dir, inarray, outarray);
541 }
542 
543 /**
544  * @param inarray Function evaluated at physical collocation
545  * points.
546  * @param outarray Inner product with respect to each basis
547  * function over the element.
548  */
550  const int dir, const Array<OneD, const NekDouble> &inarray,
551  Array<OneD, NekDouble> &outarray)
552 {
553  int i;
554  int nquad0 = m_base[0]->GetNumPoints();
555  int nquad1 = m_base[1]->GetNumPoints();
556  int nquad2 = m_base[2]->GetNumPoints();
557  int nqtot = nquad0 * nquad1 * nquad2;
558 
559  Array<OneD, NekDouble> gfac0(nquad0);
560  Array<OneD, NekDouble> gfac1(nquad1);
561  Array<OneD, NekDouble> gfac2(nquad2);
562  Array<OneD, NekDouble> tmp0(nqtot);
563 
564  int order0 = m_base[0]->GetNumModes();
565  int order1 = m_base[1]->GetNumModes();
566 
567  Array<OneD, NekDouble> wsp(nquad1 * nquad2 * order0 +
568  nquad2 * order0 * order1);
569 
570  const Array<OneD, const NekDouble> &z0 = m_base[0]->GetZ();
571  const Array<OneD, const NekDouble> &z1 = m_base[1]->GetZ();
572  const Array<OneD, const NekDouble> &z2 = m_base[2]->GetZ();
573 
574  // set up geometric factor: (1+z0)/2
575  for (i = 0; i < nquad0; ++i)
576  {
577  gfac0[i] = 0.5 * (1 + z0[i]);
578  }
579 
580  // set up geometric factor: (1+z1)/2
581  for (i = 0; i < nquad1; ++i)
582  {
583  gfac1[i] = 0.5 * (1 + z1[i]);
584  }
585 
586  // Set up geometric factor: 2/(1-z2)
587  for (i = 0; i < nquad2; ++i)
588  {
589  gfac2[i] = 2.0 / (1 - z2[i]);
590  }
591 
592  // Derivative in first/second direction is always scaled as follows
593  const int nq01 = nquad0 * nquad1;
594  for (i = 0; i < nquad2; ++i)
595  {
596  Vmath::Smul(nq01, gfac2[i], &inarray[0] + i * nq01, 1,
597  &tmp0[0] + i * nq01, 1);
598  }
599 
601 
602  switch (dir)
603  {
604  case 0:
605  {
607  m_base[0]->GetDbdata(), m_base[1]->GetBdata(),
608  m_base[2]->GetBdata(), tmp0, outarray, wsp, false, true, true);
609  break;
610  }
611  case 1:
612  {
614  m_base[0]->GetBdata(), m_base[1]->GetDbdata(),
615  m_base[2]->GetBdata(), tmp0, outarray, wsp, true, false, true);
616  break;
617  }
618  case 2:
619  {
622 
623  // Scale eta_1 derivative by gfac0
624  for (i = 0; i < nquad1 * nquad2; ++i)
625  {
626  Vmath::Vmul(nquad0, tmp0.get() + i * nquad0, 1, gfac0.get(), 1,
627  tmp0.get() + i * nquad0, 1);
628  }
630  m_base[0]->GetDbdata(), m_base[1]->GetBdata(),
631  m_base[2]->GetBdata(), tmp0, tmp3, wsp, false, true, true);
632 
633  // Scale eta_2 derivative by gfac1*gfac2
634  for (i = 0; i < nquad2; ++i)
635  {
636  Vmath::Smul(nq01, gfac2[i], &inarray[0] + i * nq01, 1,
637  &tmp0[0] + i * nq01, 1);
638  }
639  for (i = 0; i < nquad1 * nquad2; ++i)
640  {
641  Vmath::Smul(nquad0, gfac1[i % nquad1], &tmp0[0] + i * nquad0, 1,
642  &tmp0[0] + i * nquad0, 1);
643  }
644 
647  m_base[0]->GetBdata(), m_base[1]->GetDbdata(),
648  m_base[2]->GetBdata(), tmp0, tmp4, wsp, true, false, true);
649 
650  v_MultiplyByStdQuadratureMetric(inarray, tmp0);
652  m_base[0]->GetBdata(), m_base[1]->GetBdata(),
653  m_base[2]->GetDbdata(), tmp0, outarray, wsp, true, true, false);
654 
655  Vmath::Vadd(m_ncoeffs, &tmp3[0], 1, &outarray[0], 1, &outarray[0],
656  1);
657  Vmath::Vadd(m_ncoeffs, &tmp4[0], 1, &outarray[0], 1, &outarray[0],
658  1);
659  break;
660  }
661  default:
662  {
663  ASSERTL1(false, "input dir is out of range");
664  break;
665  }
666  }
667 }
668 
669 //---------------------------------------
670 // Evaluation functions
671 //---------------------------------------
672 
675 {
676  NekDouble d2 = 1.0 - xi[2];
677  if (fabs(d2) < NekConstants::kNekZeroTol)
678  {
679  if (d2 >= 0.)
680  {
682  }
683  else
684  {
686  }
687  }
688  eta[2] = xi[2]; // eta_z = xi_z
689  eta[1] = 2.0 * (1.0 + xi[1]) / d2 - 1.0;
690  eta[0] = 2.0 * (1.0 + xi[0]) / d2 - 1.0;
691 }
692 
695 {
696  xi[0] = (1.0 + eta[0]) * (1.0 - eta[2]) * 0.5 - 1.0;
697  xi[1] = (1.0 + eta[1]) * (1.0 - eta[2]) * 0.5 - 1.0;
698  xi[2] = eta[2];
699 }
700 
704 {
705  Array<OneD, const NekDouble> etaBar_x = m_base[0]->GetZ();
706  Array<OneD, const NekDouble> eta_y = m_base[1]->GetZ();
707  Array<OneD, const NekDouble> eta_z = m_base[2]->GetZ();
708  int Qx = GetNumPoints(0);
709  int Qy = GetNumPoints(1);
710  int Qz = GetNumPoints(2);
711 
712  // Convert collapsed coordinates into cartesian coordinates: eta --> xi
713  for (int k = 0; k < Qz; ++k)
714  {
715  for (int j = 0; j < Qy; ++j)
716  {
717  for (int i = 0; i < Qx; ++i)
718  {
719  int s = i + Qx * (j + Qy * k);
720 
721  xi_z[s] = eta_z[k];
722  xi_y[s] = (1.0 + eta_y[j]) * (1.0 - eta_z[k]) / 2.0 - 1.0;
723  xi_x[s] = (1.0 + etaBar_x[i]) * (1.0 - eta_z[k]) / 2.0 - 1.0;
724  }
725  }
726  }
727 }
728 
729 void StdPyrExp::v_FillMode(const int mode, Array<OneD, NekDouble> &outarray)
730 {
732  tmp[mode] = 1.0;
733  v_BwdTrans(tmp, outarray);
734 }
735 
736 void StdPyrExp::v_GetTraceNumModes(const int fid, int &numModes0,
737  int &numModes1, Orientation faceOrient)
738 {
739  int nummodes[3] = {m_base[0]->GetNumModes(), m_base[1]->GetNumModes(),
740  m_base[2]->GetNumModes()};
741  switch (fid)
742  {
743  // quad
744  case 0:
745  {
746  numModes0 = nummodes[0];
747  numModes1 = nummodes[1];
748  }
749  break;
750  case 1:
751  case 3:
752  {
753  numModes0 = nummodes[0];
754  numModes1 = nummodes[2];
755  }
756  break;
757  case 2:
758  case 4:
759  {
760  numModes0 = nummodes[1];
761  numModes1 = nummodes[2];
762  }
763  break;
764  }
765 
766  if (faceOrient >= 9)
767  {
768  std::swap(numModes0, numModes1);
769  }
770 }
771 
773  const Array<OneD, const NekDouble> &coords, int mode)
774 {
775  Array<OneD, NekDouble> coll(3);
776  LocCoordToLocCollapsed(coords, coll);
777 
778  const int nm0 = m_base[0]->GetNumModes();
779  const int nm1 = m_base[1]->GetNumModes();
780  const int nm2 = m_base[2]->GetNumModes();
781 
782  int mode0 = 0, mode1 = 0, mode2 = 0, cnt = 0;
783 
784  bool found = false;
785  for (mode0 = 0; mode0 < nm0; ++mode0)
786  {
787  for (mode1 = 0; mode1 < nm1; ++mode1)
788  {
789  int maxpq = max(mode0, mode1);
790  for (mode2 = 0; mode2 < nm2 - maxpq; ++mode2, ++cnt)
791  {
792  if (cnt == mode)
793  {
794  found = true;
795  break;
796  }
797  }
798 
799  if (found)
800  {
801  break;
802  }
803  }
804 
805  if (found)
806  {
807  break;
808  }
809 
810  for (int j = nm1; j < nm2; ++j)
811  {
812  int ijmax = max(mode0, j);
813  mode2 += nm2 - ijmax;
814  }
815  }
816 
817  if (mode == 1 && m_base[0]->GetBasisType() == LibUtilities::eModified_A)
818  {
819  return StdExpansion::BaryEvaluateBasis<2>(coll[2], 1);
820  }
821  else
822  {
823  return StdExpansion::BaryEvaluateBasis<0>(coll[0], mode0) *
824  StdExpansion::BaryEvaluateBasis<1>(coll[1], mode1) *
825  StdExpansion::BaryEvaluateBasis<2>(coll[2], mode2);
826  }
827 }
828 
829 //---------------------------------------
830 // Helper functions
831 //---------------------------------------
832 
834 {
835  return 5;
836 }
837 
839 {
840  return 8;
841 }
842 
844 {
845  return 5;
846 }
847 
849 {
850  return LibUtilities::ePyramid;
851 }
852 
854 {
857  "BasisType is not a boundary interior form");
860  "BasisType is not a boundary interior form");
863  "BasisType is not a boundary interior form");
864 
865  int P = m_base[0]->GetNumModes();
866  int Q = m_base[1]->GetNumModes();
867  int R = m_base[2]->GetNumModes();
868 
870 }
871 
873 {
876  "BasisType is not a boundary interior form");
879  "BasisType is not a boundary interior form");
882  "BasisType is not a boundary interior form");
883 
884  int P = m_base[0]->GetNumModes() - 1;
885  int Q = m_base[1]->GetNumModes() - 1;
886  int R = m_base[2]->GetNumModes() - 1;
887 
888  return (P + 1) * (Q + 1) // 1 rect. face on base
889  + 2 * (R + 1) + P * (1 + 2 * R - P) // 2 tri. (P,R) faces
890  + 2 * (R + 1) + Q * (1 + 2 * R - Q); // 2 tri. (Q,R) faces
891 }
892 
893 int StdPyrExp::v_GetTraceNcoeffs(const int i) const
894 {
895  ASSERTL2(i >= 0 && i <= 4, "face id is out of range");
896 
897  if (i == 0)
898  {
899  return GetBasisNumModes(0) * GetBasisNumModes(1);
900  }
901  else if (i == 1 || i == 3)
902  {
903  int P = GetBasisNumModes(0) - 1, Q = GetBasisNumModes(2) - 1;
904  return Q + 1 + (P * (1 + 2 * Q - P)) / 2;
905  }
906  else
907  {
908  int P = GetBasisNumModes(1) - 1, Q = GetBasisNumModes(2) - 1;
909  return Q + 1 + (P * (1 + 2 * Q - P)) / 2;
910  }
911 }
912 
913 int StdPyrExp::v_GetTraceIntNcoeffs(const int i) const
914 {
915  ASSERTL2(i >= 0 && i <= 4, "face id is out of range");
916 
917  int P = m_base[0]->GetNumModes() - 1;
918  int Q = m_base[1]->GetNumModes() - 1;
919  int R = m_base[2]->GetNumModes() - 1;
920 
921  if (i == 0)
922  {
923  return (P - 1) * (Q - 1);
924  }
925  else if (i == 1 || i == 3)
926  {
927  return (P - 1) * (2 * (R - 1) - (P - 1) - 1) / 2;
928  }
929  else
930  {
931  return (Q - 1) * (2 * (R - 1) - (Q - 1) - 1) / 2;
932  }
933 }
934 
935 int StdPyrExp::v_GetTraceNumPoints(const int i) const
936 {
937  ASSERTL2(i >= 0 && i <= 4, "face id is out of range");
938 
939  if (i == 0)
940  {
941  return m_base[0]->GetNumPoints() * m_base[1]->GetNumPoints();
942  }
943  else if (i == 1 || i == 3)
944  {
945  return m_base[0]->GetNumPoints() * m_base[2]->GetNumPoints();
946  }
947  else
948  {
949  return m_base[1]->GetNumPoints() * m_base[2]->GetNumPoints();
950  }
951 }
952 
953 int StdPyrExp::v_GetEdgeNcoeffs(const int i) const
954 {
955  ASSERTL2(i >= 0 && i <= 7, "edge id is out of range");
956 
957  if (i == 0 || i == 2)
958  {
959  return GetBasisNumModes(0);
960  }
961  else if (i == 1 || i == 3)
962  {
963  return GetBasisNumModes(1);
964  }
965  else
966  {
967  return GetBasisNumModes(2);
968  }
969 }
970 
972  const int k) const
973 {
974  ASSERTL2(i >= 0 && i <= 4, "face id is out of range");
975  ASSERTL2(k >= 0 && k <= 1, "basis key id is out of range");
976 
977  switch (i)
978  {
979  case 0:
980  {
982  m_base[k]->GetNumPoints(),
983  m_base[k]->GetNumModes());
984  }
985  case 1:
986  case 3:
987  {
988  return EvaluateTriFaceBasisKey(k, m_base[2 * k]->GetBasisType(),
989  m_base[2 * k]->GetNumPoints(),
990  m_base[2 * k]->GetNumModes());
991  }
992  case 2:
993  case 4:
994  {
995  return EvaluateTriFaceBasisKey(k, m_base[k + 1]->GetBasisType(),
996  m_base[k + 1]->GetNumPoints(),
997  m_base[k + 1]->GetNumModes());
998  }
999  }
1000 
1001  // Should never get here.
1003 }
1004 
1006  const std::vector<unsigned int> &nummodes, int &modes_offset)
1007 {
1009  nummodes[modes_offset], nummodes[modes_offset + 1],
1010  nummodes[modes_offset + 2]);
1011 
1012  modes_offset += 3;
1013  return nmodes;
1014 }
1015 
1016 int StdPyrExp::v_GetVertexMap(int vId, bool useCoeffPacking)
1017 {
1021  "Mapping not defined for this type of basis");
1022 
1023  int l = 0;
1024 
1025  if (useCoeffPacking == true) // follow packing of coefficients i.e q,r,p
1026  {
1027  switch (vId)
1028  {
1029  case 0:
1030  l = GetMode(0, 0, 0);
1031  break;
1032  case 1:
1033  l = GetMode(0, 0, 1);
1034  break;
1035  case 2:
1036  l = GetMode(0, 1, 0);
1037  break;
1038  case 3:
1039  l = GetMode(1, 0, 0);
1040  break;
1041  case 4:
1042  l = GetMode(1, 1, 0);
1043  break;
1044  default:
1045  ASSERTL0(false, "local vertex id must be between 0 and 4");
1046  }
1047  }
1048  else
1049  {
1050  switch (vId)
1051  {
1052  case 0:
1053  l = GetMode(0, 0, 0);
1054  break;
1055  case 1:
1056  l = GetMode(1, 0, 0);
1057  break;
1058  case 2:
1059  l = GetMode(1, 1, 0);
1060  break;
1061  case 3:
1062  l = GetMode(0, 1, 0);
1063  break;
1064  case 4:
1065  l = GetMode(0, 0, 1);
1066  break;
1067  default:
1068  ASSERTL0(false, "local vertex id must be between 0 and 4");
1069  }
1070  }
1071 
1072  return l;
1073 }
1074 
1076 {
1079  "BasisType is not a boundary interior form");
1082  "BasisType is not a boundary interior form");
1085  "BasisType is not a boundary interior form");
1086 
1087  int P = m_base[0]->GetNumModes() - 1, p;
1088  int Q = m_base[1]->GetNumModes() - 1, q;
1089  int R = m_base[2]->GetNumModes() - 1, r;
1090 
1091  int nIntCoeffs = m_ncoeffs - NumBndryCoeffs();
1092 
1093  if (outarray.size() != nIntCoeffs)
1094  {
1095  outarray = Array<OneD, unsigned int>(nIntCoeffs);
1096  }
1097 
1098  int idx = 0;
1099 
1100  // Loop over all interior modes.
1101  for (p = 2; p <= P; ++p)
1102  {
1103  for (q = 2; q <= Q; ++q)
1104  {
1105  int maxpq = max(p, q);
1106  for (r = 1; r <= R - maxpq; ++r)
1107  {
1108  outarray[idx++] = GetMode(p, q, r);
1109  }
1110  }
1111  }
1112 }
1113 
1115 {
1118  "BasisType is not a boundary interior form");
1121  "BasisType is not a boundary interior form");
1124  "BasisType is not a boundary interior form");
1125 
1126  int P = m_base[0]->GetNumModes() - 1, p;
1127  int Q = m_base[1]->GetNumModes() - 1, q;
1128  int R = m_base[2]->GetNumModes() - 1, r;
1129  int idx = 0;
1130 
1131  int nBnd = NumBndryCoeffs();
1132 
1133  if (maparray.size() != nBnd)
1134  {
1135  maparray = Array<OneD, unsigned int>(nBnd);
1136  }
1137 
1138  // Loop over all boundary modes (in ascending order).
1139  for (p = 0; p <= P; ++p)
1140  {
1141  // First two q-r planes are entirely boundary modes.
1142  if (p <= 1)
1143  {
1144  for (q = 0; q <= Q; ++q)
1145  {
1146  int maxpq = max(p, q);
1147  for (r = 0; r <= R - maxpq; ++r)
1148  {
1149  maparray[idx++] = GetMode(p, q, r);
1150  }
1151  }
1152  }
1153  else
1154  {
1155  // Remaining q-r planes contain boundary modes on the two
1156  // front and back sides and edges 0 2.
1157  for (q = 0; q <= Q; ++q)
1158  {
1159  if (q <= 1)
1160  {
1161  for (r = 0; r <= R - p; ++r)
1162  {
1163  maparray[idx++] = GetMode(p, q, r);
1164  }
1165  }
1166  else
1167  {
1168  maparray[idx++] = GetMode(p, q, 0);
1169  }
1170  }
1171  }
1172  }
1173 }
1174 
1175 void StdPyrExp::v_GetTraceCoeffMap(const unsigned int fid,
1176  Array<OneD, unsigned int> &maparray)
1177 {
1179  "Method only implemented if BasisType is identical"
1180  "in x and y directions");
1183  "Method only implemented for Modified_A BasisType"
1184  "(x and y direction) and ModifiedPyr_C BasisType (z "
1185  "direction)");
1186 
1187  int p, q, r, P = 0, Q = 0, idx = 0;
1188 
1189  int order0 = m_base[0]->GetNumModes();
1190  int order1 = m_base[1]->GetNumModes();
1191  int order2 = m_base[2]->GetNumModes();
1192 
1193  switch (fid)
1194  {
1195  case 0:
1196  P = order0;
1197  Q = order1;
1198  break;
1199  case 1:
1200  case 3:
1201  P = order0;
1202  Q = order2;
1203  break;
1204  case 2:
1205  case 4:
1206  P = order1;
1207  Q = order2;
1208  break;
1209  default:
1210  ASSERTL0(false, "fid must be between 0 and 4");
1211  }
1212 
1213  if (maparray.size() != P * Q)
1214  {
1215  maparray = Array<OneD, unsigned int>(P * Q);
1216  }
1217 
1218  // Set up ordering inside each 2D face. Also for triangular faces,
1219  // populate signarray.
1220  switch (fid)
1221  {
1222  case 0: // Bottom quad
1223 
1224  for (q = 0; q < Q; ++q)
1225  {
1226  for (p = 0; p < P; ++p)
1227  {
1228  maparray[q * P + p] = GetMode(p, q, 0);
1229  }
1230  }
1231  break;
1232 
1233  case 1: // Front triangle
1234  for (p = 0; p < P; ++p)
1235  {
1236  for (r = 0; r < Q - p; ++r)
1237  {
1238  maparray[idx++] = GetMode(p, 0, r);
1239  }
1240  }
1241  break;
1242 
1243  case 2: // Right triangle
1244  maparray[idx++] = GetMode(1, 0, 0);
1245  maparray[idx++] = GetMode(0, 0, 1);
1246  for (r = 1; r < Q - 1; ++r)
1247  {
1248  maparray[idx++] = GetMode(1, 0, r);
1249  }
1250 
1251  for (q = 1; q < P; ++q)
1252  {
1253  for (r = 0; r < Q - q; ++r)
1254  {
1255  maparray[idx++] = GetMode(1, q, r);
1256  }
1257  }
1258  break;
1259 
1260  case 3: // Rear triangle
1261  maparray[idx++] = GetMode(0, 1, 0);
1262  maparray[idx++] = GetMode(0, 0, 1);
1263  for (r = 1; r < Q - 1; ++r)
1264  {
1265  maparray[idx++] = GetMode(0, 1, r);
1266  }
1267 
1268  for (p = 1; p < P; ++p)
1269  {
1270  for (r = 0; r < Q - p; ++r)
1271  {
1272  maparray[idx++] = GetMode(p, 1, r);
1273  }
1274  }
1275  break;
1276 
1277  case 4: // Left triangle
1278  for (q = 0; q < P; ++q)
1279  {
1280  for (r = 0; r < Q - q; ++r)
1281  {
1282  maparray[idx++] = GetMode(0, q, r);
1283  }
1284  }
1285  break;
1286 
1287  default:
1288  ASSERTL0(false, "Face to element map unavailable.");
1289  }
1290 }
1291 
1292 void StdPyrExp::v_GetElmtTraceToTraceMap(const unsigned int fid,
1293  Array<OneD, unsigned int> &maparray,
1294  Array<OneD, int> &signarray,
1295  Orientation faceOrient, int P, int Q)
1296 {
1298  "Method only implemented if BasisType is identical"
1299  "in x and y directions");
1302  "Method only implemented for Modified_A BasisType"
1303  "(x and y direction) and ModifiedPyr_C BasisType (z "
1304  "direction)");
1305 
1306  int i, j, k, p, r, nFaceCoeffs;
1307  int nummodesA = 0, nummodesB = 0;
1308 
1309  int order0 = m_base[0]->GetNumModes();
1310  int order1 = m_base[1]->GetNumModes();
1311  int order2 = m_base[2]->GetNumModes();
1312 
1313  switch (fid)
1314  {
1315  case 0:
1316  nummodesA = order0;
1317  nummodesB = order1;
1318  break;
1319  case 1:
1320  case 3:
1321  nummodesA = order0;
1322  nummodesB = order2;
1323  break;
1324  case 2:
1325  case 4:
1326  nummodesA = order1;
1327  nummodesB = order2;
1328  break;
1329  default:
1330  ASSERTL0(false, "fid must be between 0 and 4");
1331  }
1332 
1333  if (P == -1)
1334  {
1335  P = nummodesA;
1336  Q = nummodesB;
1337  nFaceCoeffs = GetTraceNcoeffs(fid);
1338  }
1339  else if (fid > 0)
1340  {
1341  nFaceCoeffs = P * (2 * Q - P + 1) / 2;
1342  }
1343  else
1344  {
1345  nFaceCoeffs = P * Q;
1346  }
1347 
1348  // Allocate the map array and sign array; set sign array to ones (+)
1349  if (maparray.size() != nFaceCoeffs)
1350  {
1351  maparray = Array<OneD, unsigned int>(nFaceCoeffs);
1352  }
1353 
1354  if (signarray.size() != nFaceCoeffs)
1355  {
1356  signarray = Array<OneD, int>(nFaceCoeffs, 1);
1357  }
1358  else
1359  {
1360  fill(signarray.get(), signarray.get() + nFaceCoeffs, 1);
1361  }
1362 
1363  // triangular faces
1364  if (fid > 0)
1365  {
1366  // zero signmap and set maparray to zero if elemental
1367  // modes are not as large as face modesl
1368  int idx = 0;
1369  int cnt = 0;
1370  int minPA = min(nummodesA, P);
1371  int minQB = min(nummodesB, Q);
1372 
1373  for (j = 0; j < minPA; ++j)
1374  {
1375  // set maparray
1376  for (k = 0; k < minQB - j; ++k, ++cnt)
1377  {
1378  maparray[idx++] = cnt;
1379  }
1380 
1381  cnt += nummodesB - minQB;
1382 
1383  for (k = nummodesB - j; k < Q - j; ++k)
1384  {
1385  signarray[idx] = 0.0;
1386  maparray[idx++] = maparray[0];
1387  }
1388  }
1389 #if 0 // not required?
1390 
1391  for (j = minPA; j < nummodesA; ++j)
1392  {
1393  // set maparray
1394  for (k = 0; k < minQB-j; ++k, ++cnt)
1395  {
1396  maparray[idx++] = cnt;
1397  }
1398 
1399  cnt += nummodesB-minQB;
1400 
1401  for (k = nummodesB-j; k < Q-j; ++k)
1402  {
1403  signarray[idx] = 0.0;
1404  maparray[idx++] = maparray[0];
1405  }
1406  }
1407 #endif
1408  for (j = nummodesA; j < P; ++j)
1409  {
1410  for (k = 0; k < Q - j; ++k)
1411  {
1412  signarray[idx] = 0.0;
1413  maparray[idx++] = maparray[0];
1414  }
1415  }
1416 
1417  // Triangles only have one possible orientation (base
1418  // direction reversed); swap edge modes.
1419  if (faceOrient == eDir1BwdDir1_Dir2FwdDir2)
1420  {
1421  swap(maparray[0], maparray[Q]);
1422  for (i = 1; i < Q - 1; ++i)
1423  {
1424  swap(maparray[i + 1], maparray[Q + i]);
1425  }
1426 
1427  idx = 0;
1428  for (p = 0; p < P; ++p)
1429  {
1430  for (r = 0; r < Q - p; ++r, idx++)
1431  {
1432  if (p > 1)
1433  {
1434  signarray[idx] = p % 2 ? -1 : 1;
1435  }
1436  }
1437  }
1438  }
1439  }
1440  else
1441  {
1442 
1443  // Set up an array indexing for quads, since the ordering may need
1444  // to be transposed.
1445  Array<OneD, int> arrayindx(nFaceCoeffs, -1);
1446 
1447  for (i = 0; i < Q; i++)
1448  {
1449  for (j = 0; j < P; j++)
1450  {
1451  if (faceOrient < eDir1FwdDir2_Dir2FwdDir1)
1452  {
1453  arrayindx[i * P + j] = i * P + j;
1454  }
1455  else
1456  {
1457  arrayindx[i * P + j] = j * Q + i;
1458  }
1459  }
1460  }
1461 
1462  // zero signmap and set maparray to zero if elemental
1463  // modes are not as large as face modesl
1464  for (j = 0; j < P; ++j)
1465  {
1466  // set up default maparray
1467  for (k = 0; k < Q; k++)
1468  {
1469  maparray[arrayindx[j + k * P]] = j + k * nummodesA;
1470  }
1471 
1472  for (k = nummodesB; k < Q; ++k)
1473  {
1474  signarray[arrayindx[j + k * P]] = 0.0;
1475  maparray[arrayindx[j + k * P]] = maparray[0];
1476  }
1477  }
1478 
1479  for (j = nummodesA; j < P; ++j)
1480  {
1481  for (k = 0; k < Q; ++k)
1482  {
1483  signarray[arrayindx[j + k * P]] = 0.0;
1484  maparray[arrayindx[j + k * P]] = maparray[0];
1485  }
1486  }
1487 
1488  // The code below is exactly the same as that taken from
1489  // StdHexExp and reverses the 'b' and 'a' directions as
1490  // appropriate (1st and 2nd if statements respectively) in
1491  // quadrilateral faces.
1492  if (faceOrient == eDir1FwdDir1_Dir2BwdDir2 ||
1493  faceOrient == eDir1BwdDir1_Dir2BwdDir2 ||
1494  faceOrient == eDir1BwdDir2_Dir2FwdDir1 ||
1495  faceOrient == eDir1BwdDir2_Dir2BwdDir1)
1496  {
1497  if (faceOrient < eDir1FwdDir2_Dir2FwdDir1)
1498  {
1499  for (i = 3; i < Q; i += 2)
1500  {
1501  for (j = 0; j < P; j++)
1502  {
1503  signarray[arrayindx[i * P + j]] *= -1;
1504  }
1505  }
1506 
1507  for (i = 0; i < P; i++)
1508  {
1509  swap(maparray[i], maparray[i + P]);
1510  swap(signarray[i], signarray[i + P]);
1511  }
1512  }
1513  else
1514  {
1515  for (i = 0; i < Q; i++)
1516  {
1517  for (j = 3; j < P; j += 2)
1518  {
1519  signarray[arrayindx[i * P + j]] *= -1;
1520  }
1521  }
1522 
1523  for (i = 0; i < Q; i++)
1524  {
1525  swap(maparray[i], maparray[i + Q]);
1526  swap(signarray[i], signarray[i + Q]);
1527  }
1528  }
1529  }
1530 
1531  if (faceOrient == eDir1BwdDir1_Dir2FwdDir2 ||
1532  faceOrient == eDir1BwdDir1_Dir2BwdDir2 ||
1533  faceOrient == eDir1FwdDir2_Dir2BwdDir1 ||
1534  faceOrient == eDir1BwdDir2_Dir2BwdDir1)
1535  {
1536  if (faceOrient < eDir1FwdDir2_Dir2FwdDir1)
1537  {
1538  for (i = 0; i < Q; i++)
1539  {
1540  for (j = 3; j < P; j += 2)
1541  {
1542  signarray[arrayindx[i * P + j]] *= -1;
1543  }
1544  }
1545 
1546  for (i = 0; i < Q; i++)
1547  {
1548  swap(maparray[i * P], maparray[i * P + 1]);
1549  swap(signarray[i * P], signarray[i * P + 1]);
1550  }
1551  }
1552  else
1553  {
1554  for (i = 3; i < Q; i += 2)
1555  {
1556  for (j = 0; j < P; j++)
1557  {
1558  signarray[arrayindx[i * P + j]] *= -1;
1559  }
1560  }
1561 
1562  for (i = 0; i < P; i++)
1563  {
1564  swap(maparray[i * Q], maparray[i * Q + 1]);
1565  swap(signarray[i * Q], signarray[i * Q + 1]);
1566  }
1567  }
1568  }
1569  }
1570 }
1571 
1573  const int eid, Array<OneD, unsigned int> &maparray,
1574  Array<OneD, int> &signarray, const Orientation edgeOrient)
1575 {
1576  int i;
1577  bool signChange;
1578  const int P = m_base[0]->GetNumModes() - 1;
1579  const int Q = m_base[1]->GetNumModes() - 1;
1580  const int R = m_base[2]->GetNumModes() - 1;
1581  const int nEdgeIntCoeffs = v_GetEdgeNcoeffs(eid) - 2;
1582 
1583  if (maparray.size() != nEdgeIntCoeffs)
1584  {
1585  maparray = Array<OneD, unsigned int>(nEdgeIntCoeffs);
1586  }
1587 
1588  if (signarray.size() != nEdgeIntCoeffs)
1589  {
1590  signarray = Array<OneD, int>(nEdgeIntCoeffs, 1);
1591  }
1592  else
1593  {
1594  fill(signarray.get(), signarray.get() + nEdgeIntCoeffs, 1);
1595  }
1596 
1597  // If edge is oriented backwards, change sign of modes which have
1598  // degree 2n+1, n >= 1.
1599  signChange = edgeOrient == eBackwards;
1600 
1601  switch (eid)
1602  {
1603  case 0:
1604  for (i = 2; i <= P; ++i)
1605  {
1606  maparray[i - 2] = GetMode(i, 0, 0);
1607  }
1608  break;
1609 
1610  case 1:
1611  for (i = 2; i <= Q; ++i)
1612  {
1613  maparray[i - 2] = GetMode(1, i, 0);
1614  }
1615  break;
1616  case 2:
1617  for (i = 2; i <= P; ++i)
1618  {
1619  maparray[i - 2] = GetMode(i, 1, 0);
1620  }
1621  break;
1622 
1623  case 3:
1624  for (i = 2; i <= Q; ++i)
1625  {
1626  maparray[i - 2] = GetMode(0, i, 0);
1627  }
1628  break;
1629  case 4:
1630  for (i = 2; i <= R; ++i)
1631  {
1632  maparray[i - 2] = GetMode(0, 0, i);
1633  }
1634  break;
1635 
1636  case 5:
1637  for (i = 1; i <= R - 1; ++i)
1638  {
1639  maparray[i - 1] = GetMode(1, 0, i);
1640  }
1641  break;
1642  case 6:
1643  for (i = 1; i <= R - 1; ++i)
1644  {
1645  maparray[i - 1] = GetMode(1, 1, i);
1646  }
1647  break;
1648 
1649  case 7:
1650  for (i = 1; i <= R - 1; ++i)
1651  {
1652  maparray[i - 1] = GetMode(0, 1, i);
1653  }
1654  break;
1655  default:
1656  ASSERTL0(false, "Edge not defined.");
1657  break;
1658  }
1659 
1660  if (signChange)
1661  {
1662  for (i = 1; i < nEdgeIntCoeffs; i += 2)
1663  {
1664  signarray[i] = -1;
1665  }
1666  }
1667 }
1668 
1670  const int fid, Array<OneD, unsigned int> &maparray,
1671  Array<OneD, int> &signarray, const Orientation faceOrient)
1672 {
1673  const int P = m_base[0]->GetNumModes() - 1;
1674  const int Q = m_base[1]->GetNumModes() - 1;
1675  const int R = m_base[2]->GetNumModes() - 1;
1676  const int nFaceIntCoeffs = v_GetTraceIntNcoeffs(fid);
1677  int p, q, r, idx = 0;
1678  int nummodesA = 0;
1679  int nummodesB = 0;
1680  int i, j;
1681 
1682  if (maparray.size() != nFaceIntCoeffs)
1683  {
1684  maparray = Array<OneD, unsigned int>(nFaceIntCoeffs);
1685  }
1686 
1687  if (signarray.size() != nFaceIntCoeffs)
1688  {
1689  signarray = Array<OneD, int>(nFaceIntCoeffs, 1);
1690  }
1691  else
1692  {
1693  fill(signarray.get(), signarray.get() + nFaceIntCoeffs, 1);
1694  }
1695 
1696  // Set up an array indexing for quad faces, since the ordering may
1697  // need to be transposed depending on orientation.
1698  Array<OneD, int> arrayindx(nFaceIntCoeffs);
1699  if (fid == 0)
1700  {
1701  nummodesA = P - 1;
1702  nummodesB = Q - 1;
1703 
1704  for (i = 0; i < nummodesB; i++)
1705  {
1706  for (j = 0; j < nummodesA; j++)
1707  {
1708  if (faceOrient < 9)
1709  {
1710  arrayindx[i * nummodesA + j] = i * nummodesA + j;
1711  }
1712  else
1713  {
1714  arrayindx[i * nummodesA + j] = j * nummodesB + i;
1715  }
1716  }
1717  }
1718  }
1719 
1720  switch (fid)
1721  {
1722  case 0: // Bottom quad
1723  for (q = 2; q <= Q; ++q)
1724  {
1725  for (p = 2; p <= P; ++p)
1726  {
1727  maparray[arrayindx[(q - 2) * nummodesA + (p - 2)]] =
1728  GetMode(p, q, 0);
1729  }
1730  }
1731  break;
1732  case 1: // Front triangle
1733  for (p = 2; p <= P; ++p)
1734  {
1735  for (r = 1; r <= R - p; ++r)
1736  {
1737  if ((int)faceOrient == 7)
1738  {
1739  signarray[idx] = p % 2 ? -1 : 1;
1740  }
1741  maparray[idx++] = GetMode(p, 0, r);
1742  }
1743  }
1744  break;
1745  case 2: // Right triangle
1746  for (q = 2; q <= Q; ++q)
1747  {
1748  for (r = 1; r <= R - q; ++r)
1749  {
1750  if ((int)faceOrient == 7)
1751  {
1752  signarray[idx] = q % 2 ? -1 : 1;
1753  }
1754  maparray[idx++] = GetMode(1, q, r);
1755  }
1756  }
1757  break;
1758 
1759  case 3: // Rear triangle
1760  for (p = 2; p <= P; ++p)
1761  {
1762  for (r = 1; r <= R - p; ++r)
1763  {
1764  if ((int)faceOrient == 7)
1765  {
1766  signarray[idx] = p % 2 ? -1 : 1;
1767  }
1768  maparray[idx++] = GetMode(p, 1, r);
1769  }
1770  }
1771  break;
1772 
1773  case 4: // Left triangle
1774  for (q = 2; q <= Q; ++q)
1775  {
1776  for (r = 1; r <= R - q; ++r)
1777  {
1778  if ((int)faceOrient == 7)
1779  {
1780  signarray[idx] = q % 2 ? -1 : 1;
1781  }
1782  maparray[idx++] = GetMode(0, q, r);
1783  }
1784  }
1785  break;
1786  default:
1787  ASSERTL0(false, "Face interior map not available.");
1788  }
1789 
1790  // Triangular faces are processed in the above switch loop; for
1791  // remaining quad faces, set up orientation if necessary.
1792  if (fid > 0)
1793  {
1794  return;
1795  }
1796 
1797  if (faceOrient == 6 || faceOrient == 8 || faceOrient == 11 ||
1798  faceOrient == 12)
1799  {
1800  if (faceOrient < 9)
1801  {
1802  for (i = 1; i < nummodesB; i += 2)
1803  {
1804  for (j = 0; j < nummodesA; j++)
1805  {
1806  signarray[arrayindx[i * nummodesA + j]] *= -1;
1807  }
1808  }
1809  }
1810  else
1811  {
1812  for (i = 0; i < nummodesB; i++)
1813  {
1814  for (j = 1; j < nummodesA; j += 2)
1815  {
1816  signarray[arrayindx[i * nummodesA + j]] *= -1;
1817  }
1818  }
1819  }
1820  }
1821 
1822  if (faceOrient == 7 || faceOrient == 8 || faceOrient == 10 ||
1823  faceOrient == 12)
1824  {
1825  if (faceOrient < 9)
1826  {
1827  for (i = 0; i < nummodesB; i++)
1828  {
1829  for (j = 1; j < nummodesA; j += 2)
1830  {
1831  signarray[arrayindx[i * nummodesA + j]] *= -1;
1832  }
1833  }
1834  }
1835  else
1836  {
1837  for (i = 1; i < nummodesB; i += 2)
1838  {
1839  for (j = 0; j < nummodesA; j++)
1840  {
1841  signarray[arrayindx[i * nummodesA + j]] *= -1;
1842  }
1843  }
1844  }
1845  }
1846 }
1847 
1848 //---------------------------------------
1849 // Wrapper functions
1850 //---------------------------------------
1851 
1853 {
1854  return CreateGeneralMatrix(mkey);
1855 }
1856 
1858 {
1859  return v_GenMatrix(mkey);
1860 }
1861 
1862 /**
1863  * @brief Compute the mode number in the expansion for a
1864  * particular tensorial combination.
1865  *
1866  * Modes are numbered with the r index travelling fastest,
1867  * followed by q and then p, and each q-r plane is of size
1868  *
1869  * (R+1-p)*(Q+1) - l(l+1)/2 where l = max(0,Q-p)
1870  *
1871  * For example, when P=2, Q=3 and R=4 the indexing inside each
1872  * q-r plane (with r increasing upwards and q to the right)
1873  * is:
1874  *
1875  * p = 0: p = 1: p = 2:
1876  * ----------------------------------
1877  * 4
1878  * 3 8 17 21
1879  * 2 7 11 16 20 24 29 32 35
1880  * 1 6 10 13 15 19 23 26 28 31 34 37
1881  * 0 5 9 12 14 18 22 25 27 30 33 36
1882  *
1883  * Note that in this element, we must have that \f$ P,Q \leq
1884  * R\f$.
1885  */
1886 int StdPyrExp::GetMode(const int I, const int J, const int K)
1887 {
1888  const int Q = m_base[1]->GetNumModes() - 1;
1889  const int R = m_base[2]->GetNumModes() - 1;
1890 
1891  int i, l;
1892  int cnt = 0;
1893 
1894  // Traverse to q-r plane number I
1895  for (i = 0; i < I; ++i)
1896  {
1897  // Size of triangle part
1898  l = max(0, Q - i);
1899 
1900  // Size of rectangle part
1901  cnt += (R + 1 - i) * (Q + 1) - l * (l + 1) / 2;
1902  }
1903 
1904  // Traverse to q column J (Pretend this is a face of width J)
1905  l = max(0, J - 1 - I);
1906  cnt += (R + 1 - I) * J - l * (l + 1) / 2;
1907 
1908  // Traverse up stacks to K
1909  cnt += K;
1910 
1911  return cnt;
1912 }
1913 
1915  const Array<OneD, const NekDouble> &inarray,
1916  Array<OneD, NekDouble> &outarray)
1917 {
1918  int i, j;
1919 
1920  int nquad0 = m_base[0]->GetNumPoints();
1921  int nquad1 = m_base[1]->GetNumPoints();
1922  int nquad2 = m_base[2]->GetNumPoints();
1923 
1924  const Array<OneD, const NekDouble> &w0 = m_base[0]->GetW();
1925  const Array<OneD, const NekDouble> &w1 = m_base[1]->GetW();
1926  const Array<OneD, const NekDouble> &w2 = m_base[2]->GetW();
1927 
1928  const Array<OneD, const NekDouble> &z2 = m_base[2]->GetZ();
1929 
1930  // Multiply by integration constants in x-direction
1931  for (i = 0; i < nquad1 * nquad2; ++i)
1932  {
1933  Vmath::Vmul(nquad0, inarray.get() + i * nquad0, 1, w0.get(), 1,
1934  outarray.get() + i * nquad0, 1);
1935  }
1936 
1937  // Multiply by integration constants in y-direction
1938  for (j = 0; j < nquad2; ++j)
1939  {
1940  for (i = 0; i < nquad1; ++i)
1941  {
1942  Blas::Dscal(nquad0, w1[i],
1943  &outarray[0] + i * nquad0 + j * nquad0 * nquad1, 1);
1944  }
1945  }
1946 
1947  // Multiply by integration constants in z-direction; need to
1948  // incorporate factor [(1-eta_3)/2]^2 into weights, but only if
1949  // using GLL quadrature points.
1950  switch (m_base[2]->GetPointsType())
1951  {
1952  // (2,0) Jacobi inner product.
1953  case LibUtilities::eGaussRadauMAlpha2Beta0:
1954  for (i = 0; i < nquad2; ++i)
1955  {
1956  Blas::Dscal(nquad0 * nquad1, 0.25 * w2[i],
1957  &outarray[0] + i * nquad0 * nquad1, 1);
1958  }
1959  break;
1960 
1961  default:
1962  for (i = 0; i < nquad2; ++i)
1963  {
1964  Blas::Dscal(nquad0 * nquad1,
1965  0.25 * (1 - z2[i]) * (1 - z2[i]) * w2[i],
1966  &outarray[0] + i * nquad0 * nquad1, 1);
1967  }
1968  break;
1969  }
1970 }
1971 
1973  const StdMatrixKey &mkey)
1974 {
1975  // Generate an orthonogal expansion
1976  int qa = m_base[0]->GetNumPoints();
1977  int qb = m_base[1]->GetNumPoints();
1978  int qc = m_base[2]->GetNumPoints();
1979  int nmodes_a = m_base[0]->GetNumModes();
1980  int nmodes_b = m_base[1]->GetNumModes();
1981  int nmodes_c = m_base[2]->GetNumModes();
1982  // Declare orthogonal basis.
1986 
1990  StdPyrExp OrthoExp(Ba, Bb, Bc);
1991 
1992  Array<OneD, NekDouble> orthocoeffs(OrthoExp.GetNcoeffs());
1993  int i, j, k, cnt = 0;
1994 
1995  // project onto modal space.
1996  OrthoExp.FwdTrans(array, orthocoeffs);
1997 
1999  {
2000  // Rodrigo's power kernel
2002  NekDouble SvvDiffCoeff =
2005 
2006  for (int i = 0; i < nmodes_a; ++i)
2007  {
2008  for (int j = 0; j < nmodes_b; ++j)
2009  {
2010  int maxij = max(i, j);
2011  NekDouble fac1 = std::max(
2012  pow((1.0 * i) / (nmodes_a - 1), cutoff * nmodes_a),
2013  pow((1.0 * j) / (nmodes_b - 1), cutoff * nmodes_b));
2014 
2015  for (int k = 0; k < nmodes_c - maxij; ++k)
2016  {
2017  NekDouble fac =
2018  std::max(fac1, pow((1.0 * k) / (nmodes_c - 1),
2019  cutoff * nmodes_c));
2020 
2021  orthocoeffs[cnt] *= SvvDiffCoeff * fac;
2022  cnt++;
2023  }
2024  }
2025  }
2026  }
2027  else if (mkey.ConstFactorExists(
2028  eFactorSVVDGKerDiffCoeff)) // Rodrigo/Mansoor's DG Kernel
2029  {
2030  NekDouble SvvDiffCoeff = mkey.GetConstFactor(eFactorSVVDGKerDiffCoeff) *
2032 
2033  int max_abc = max(nmodes_a - kSVVDGFiltermodesmin,
2034  nmodes_b - kSVVDGFiltermodesmin);
2035  max_abc = max(max_abc, nmodes_c - kSVVDGFiltermodesmin);
2036  // clamp max_abc
2037  max_abc = max(max_abc, 0);
2038  max_abc = min(max_abc, kSVVDGFiltermodesmax - kSVVDGFiltermodesmin);
2039 
2040  for (int i = 0; i < nmodes_a; ++i)
2041  {
2042  for (int j = 0; j < nmodes_b; ++j)
2043  {
2044  int maxij = max(i, j);
2045 
2046  for (int k = 0; k < nmodes_c - maxij; ++k)
2047  {
2048  int maxijk = max(maxij, k);
2049  maxijk = min(maxijk, kSVVDGFiltermodesmax - 1);
2050 
2051  orthocoeffs[cnt] *=
2052  SvvDiffCoeff * kSVVDGFilter[max_abc][maxijk];
2053  cnt++;
2054  }
2055  }
2056  }
2057  }
2058  else
2059  {
2060  // SVV filter paramaters (how much added diffusion relative
2061  // to physical one and fraction of modes from which you
2062  // start applying this added diffusion)
2063  //
2064  NekDouble SvvDiffCoeff =
2066  NekDouble SVVCutOff =
2068 
2069  // Defining the cut of mode
2070  int cutoff_a = (int)(SVVCutOff * nmodes_a);
2071  int cutoff_b = (int)(SVVCutOff * nmodes_b);
2072  int cutoff_c = (int)(SVVCutOff * nmodes_c);
2073  // To avoid the fac[j] from blowing up
2074  NekDouble epsilon = 1;
2075 
2076  int nmodes = min(min(nmodes_a, nmodes_b), nmodes_c);
2077  NekDouble cutoff = min(min(cutoff_a, cutoff_b), cutoff_c);
2078 
2079  for (i = 0; i < nmodes_a; ++i) // P
2080  {
2081  for (j = 0; j < nmodes_b; ++j) // Q
2082  {
2083  int maxij = max(i, j);
2084  for (k = 0; k < nmodes_c - maxij; ++k) // R
2085  {
2086  if (j + k >= cutoff || i + k >= cutoff)
2087  {
2088  orthocoeffs[cnt] *=
2089  (SvvDiffCoeff *
2090  exp(-(i + k - nmodes) * (i + k - nmodes) /
2091  ((NekDouble)((i + k - cutoff + epsilon) *
2092  (i + k - cutoff + epsilon)))) *
2093  exp(-(j - nmodes) * (j - nmodes) /
2094  ((NekDouble)((j - cutoff + epsilon) *
2095  (j - cutoff + epsilon)))));
2096  }
2097  else
2098  {
2099  orthocoeffs[cnt] *= 0.0;
2100  }
2101  cnt++;
2102  }
2103  }
2104  }
2105  }
2106 
2107  // backward transform to physical space
2108  OrthoExp.BwdTrans(orthocoeffs, array);
2109 }
2110 
2112  const Array<OneD, const NekDouble> &inarray,
2113  Array<OneD, NekDouble> &outarray)
2114 {
2115  int nquad0 = m_base[0]->GetNumPoints();
2116  int nquad1 = m_base[1]->GetNumPoints();
2117  int nquad2 = m_base[2]->GetNumPoints();
2118  int nqtot = nquad0 * nquad1 * nquad2;
2119  int nmodes0 = m_base[0]->GetNumModes();
2120  int nmodes1 = m_base[1]->GetNumModes();
2121  int nmodes2 = m_base[2]->GetNumModes();
2122  int numMax = nmodes0;
2123 
2125  Array<OneD, NekDouble> coeff_tmp1(m_ncoeffs, 0.0);
2126  Array<OneD, NekDouble> phys_tmp(nqtot, 0.0);
2127  Array<OneD, NekDouble> tmp, tmp2, tmp3, tmp4;
2128 
2129  const LibUtilities::PointsKey Pkey0 = m_base[0]->GetPointsKey();
2130  const LibUtilities::PointsKey Pkey1 = m_base[1]->GetPointsKey();
2131  const LibUtilities::PointsKey Pkey2 = m_base[2]->GetPointsKey();
2132 
2133  LibUtilities::BasisKey bortho0(LibUtilities::eOrtho_A, nmodes0, Pkey0);
2134  LibUtilities::BasisKey bortho1(LibUtilities::eOrtho_A, nmodes1, Pkey1);
2135  LibUtilities::BasisKey bortho2(LibUtilities::eOrthoPyr_C, nmodes2, Pkey2);
2136 
2137  int cnt = 0;
2138  int u = 0;
2139  int i = 0;
2140  StdRegions::StdPyrExpSharedPtr OrthoPyrExp;
2141 
2143  bortho0, bortho1, bortho2);
2144 
2145  BwdTrans(inarray, phys_tmp);
2146  OrthoPyrExp->FwdTrans(phys_tmp, coeff);
2147 
2148  // filtering
2149  for (u = 0; u < numMin; ++u)
2150  {
2151  for (i = 0; i < numMin; ++i)
2152  {
2153 
2154  int maxui = max(u, i);
2155  Vmath::Vcopy(numMin - maxui, tmp = coeff + cnt, 1,
2156  tmp2 = coeff_tmp1 + cnt, 1);
2157  cnt += nmodes2 - maxui;
2158  }
2159 
2160  for (i = numMin; i < nmodes1; ++i)
2161  {
2162  int maxui = max(u, i);
2163  cnt += numMax - maxui;
2164  }
2165  }
2166 
2167  OrthoPyrExp->BwdTrans(coeff_tmp1, phys_tmp);
2168  StdPyrExp::FwdTrans(phys_tmp, outarray);
2169 }
2170 
2171 } // namespace StdRegions
2172 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
#define ASSERTL2(condition, msg)
Assert Level 2 – Debugging which is used FULLDEBUG compilation mode. This level assert is designed to...
Definition: ErrorUtil.hpp:272
Describes the specification for a Basis.
Definition: Basis.h:50
BasisType GetBasisType() const
Return type of expansion basis.
Definition: Basis.h:141
int GetNumModes() const
Returns the order of the basis.
Definition: Basis.h:83
Defines a specification for a set of points.
Definition: Points.h:59
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
void IProductWRTBase_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0, bool doCheckCollDir1, bool doCheckCollDir2)
void PhysTensorDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray_d1, Array< OneD, NekDouble > &outarray_d2, Array< OneD, NekDouble > &outarray_d3)
Calculate the 3D derivative in the local tensor/collapsed coordinate at the physical points.
The base class for all shapes.
Definition: StdExpansion.h:71
int GetNcoeffs(void) const
This function returns the total number of coefficients used in the expansion.
Definition: StdExpansion.h:130
LibUtilities::BasisType GetBasisType(const int dir) const
This function returns the type of basis used in the dir direction.
Definition: StdExpansion.h:163
DNekMatSharedPtr GetStdMatrix(const StdMatrixKey &mkey)
Definition: StdExpansion.h:611
void LocCoordToLocCollapsed(const Array< OneD, const NekDouble > &xi, Array< OneD, NekDouble > &eta)
Convert local cartesian coordinate xi into local collapsed coordinates eta.
Definition: StdExpansion.h:974
DNekMatSharedPtr CreateGeneralMatrix(const StdMatrixKey &mkey)
this function generates the mass matrix
LibUtilities::ShapeType DetShapeType() const
This function returns the shape of the expansion domain.
Definition: StdExpansion.h:375
void BwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function performs the Backward transformation from coefficient space to physical space.
Definition: StdExpansion.h:432
int GetTraceNcoeffs(const int i) const
This function returns the number of expansion coefficients belonging to the i-th trace.
Definition: StdExpansion.h:269
LibUtilities::PointsType GetPointsType(const int dir) const
This function returns the type of quadrature points used in the dir direction.
Definition: StdExpansion.h:213
void FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function performs the Forward transformation from physical space to coefficient space.
int GetNumPoints(const int dir) const
This function returns the number of quadrature points in the dir direction.
Definition: StdExpansion.h:226
int GetBasisNumModes(const int dir) const
This function returns the number of expansion modes in the dir direction.
Definition: StdExpansion.h:176
Array< OneD, LibUtilities::BasisSharedPtr > m_base
NekDouble GetConstFactor(const ConstFactorType &factor) const
Definition: StdMatrixKey.h:126
bool ConstFactorExists(const ConstFactorType &factor) const
Definition: StdMatrixKey.h:135
virtual void v_GetInteriorMap(Array< OneD, unsigned int > &outarray)
Definition: StdPyrExp.cpp:1075
void v_MultiplyByStdQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: StdPyrExp.cpp:1914
virtual void v_GetCoords(Array< OneD, NekDouble > &xi_x, Array< OneD, NekDouble > &xi_y, Array< OneD, NekDouble > &xi_z)
Definition: StdPyrExp.cpp:701
virtual void v_GetTraceNumModes(const int fid, int &numModes0, int &numModes1, Orientation faceOrient=eDir1FwdDir1_Dir2FwdDir2)
Definition: StdPyrExp.cpp:736
virtual void v_BwdTrans_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0, bool doCheckCollDir1, bool doCheckCollDir2)
Definition: StdPyrExp.cpp:282
virtual int v_GetTraceNumPoints(const int i) const
Definition: StdPyrExp.cpp:935
virtual void v_IProductWRTDerivBase_SumFac(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: StdPyrExp.cpp:549
NekDouble v_PhysEvaluateBasis(const Array< OneD, const NekDouble > &coords, int mode) final
Definition: StdPyrExp.cpp:772
virtual const LibUtilities::BasisKey v_GetTraceBasisKey(const int i, const int k) const
Definition: StdPyrExp.cpp:971
virtual void v_LocCoordToLocCollapsed(const Array< OneD, const NekDouble > &xi, Array< OneD, NekDouble > &eta)
Definition: StdPyrExp.cpp:673
virtual DNekMatSharedPtr v_GenMatrix(const StdMatrixKey &mkey)
Definition: StdPyrExp.cpp:1852
virtual void v_IProductWRTDerivBase(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: StdPyrExp.cpp:536
virtual int v_GetEdgeNcoeffs(const int i) const
Definition: StdPyrExp.cpp:953
virtual void v_BwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Backward transformation is evaluated at the quadrature points.
Definition: StdPyrExp.cpp:246
virtual void v_IProductWRTBase_SumFac(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool multiplybyweights=true)
Definition: StdPyrExp.cpp:425
virtual void v_StdPhysDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d0, Array< OneD, NekDouble > &out_d1, Array< OneD, NekDouble > &out_d2)
Definition: StdPyrExp.cpp:206
virtual int v_CalcNumberOfCoefficients(const std::vector< unsigned int > &nummodes, int &modes_offset)
Definition: StdPyrExp.cpp:1005
virtual int v_GetNverts() const
Definition: StdPyrExp.cpp:833
virtual void v_PhysDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &out_d0, Array< OneD, NekDouble > &out_d1, Array< OneD, NekDouble > &out_d2)
Calculate the derivative of the physical points.
Definition: StdPyrExp.cpp:101
virtual int v_GetTraceNcoeffs(const int i) const
Definition: StdPyrExp.cpp:893
virtual void v_GetBoundaryMap(Array< OneD, unsigned int > &outarray)
Definition: StdPyrExp.cpp:1114
virtual int v_NumDGBndryCoeffs() const
Definition: StdPyrExp.cpp:872
virtual LibUtilities::ShapeType v_DetShapeType() const
Definition: StdPyrExp.cpp:848
int GetMode(int I, int J, int K)
Compute the mode number in the expansion for a particular tensorial combination.
Definition: StdPyrExp.cpp:1886
virtual void v_IProductWRTBase_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0, bool doCheckCollDir1, bool doCheckCollDir2)
Definition: StdPyrExp.cpp:455
virtual int v_NumBndryCoeffs() const
Definition: StdPyrExp.cpp:853
virtual void v_FillMode(const int mode, Array< OneD, NekDouble > &outarray)
Definition: StdPyrExp.cpp:729
virtual int v_GetTraceIntNcoeffs(const int i) const
Definition: StdPyrExp.cpp:913
virtual DNekMatSharedPtr v_CreateStdMatrix(const StdMatrixKey &mkey)
Definition: StdPyrExp.cpp:1857
virtual void v_IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Inner product of inarray over region with respect to the expansion basis m_base[0]->GetBdata(),...
Definition: StdPyrExp.cpp:411
virtual void v_GetTraceCoeffMap(const unsigned int fid, Array< OneD, unsigned int > &maparray)
Definition: StdPyrExp.cpp:1175
virtual void v_ReduceOrderCoeffs(int numMin, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: StdPyrExp.cpp:2111
virtual void v_FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Forward transform from physical quadrature space stored in inarray and evaluate the expansion coeffic...
Definition: StdPyrExp.cpp:376
virtual void v_BwdTrans_SumFac(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: StdPyrExp.cpp:265
virtual int v_GetNedges() const
Definition: StdPyrExp.cpp:838
virtual void v_GetTraceInteriorToElementMap(const int tid, Array< OneD, unsigned int > &maparray, Array< OneD, int > &signarray, const Orientation traceOrient=eDir1FwdDir1_Dir2FwdDir2)
Definition: StdPyrExp.cpp:1669
virtual int v_GetVertexMap(int localVertexId, bool useCoeffPacking=false)
Definition: StdPyrExp.cpp:1016
virtual void v_GetEdgeInteriorToElementMap(const int tid, Array< OneD, unsigned int > &maparray, Array< OneD, int > &signarray, const Orientation traceOrient=eDir1FwdDir1_Dir2FwdDir2)
Definition: StdPyrExp.cpp:1572
virtual void v_GetElmtTraceToTraceMap(const unsigned int fid, Array< OneD, unsigned int > &maparray, Array< OneD, int > &signarray, Orientation faceOrient, int P, int Q)
Definition: StdPyrExp.cpp:1292
virtual void v_SVVLaplacianFilter(Array< OneD, NekDouble > &array, const StdMatrixKey &mkey)
Definition: StdPyrExp.cpp:1972
virtual int v_GetNtraces() const
Definition: StdPyrExp.cpp:843
virtual void v_LocCollapsedToLocCoord(const Array< OneD, const NekDouble > &eta, Array< OneD, NekDouble > &xi)
Definition: StdPyrExp.cpp:693
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 = A x where A[m x n].
Definition: Blas.hpp:246
static void Dscal(const int &n, const double &alpha, double *x, const int &incx)
BLAS level 1: x = alpha x.
Definition: Blas.hpp:168
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:182
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:368
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:154
int getNumberOfCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:235
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:262
static const BasisKey NullBasisKey(eNoBasisType, 0, NullPointsKey)
Defines a null basis with no type or points.
@ eOrtho_A
Principle Orthogonal Functions .
Definition: BasisType.h:44
@ eGLL_Lagrange
Lagrange for SEM basis .
Definition: BasisType.h:58
@ eModifiedPyr_C
Principle Modified Functions.
Definition: BasisType.h:55
@ eModified_A
Principle Modified Functions .
Definition: BasisType.h:50
@ eOrthoPyr_C
Principle Orthogonal Functions .
Definition: BasisType.h:53
static const NekDouble kNekZeroTol
LibUtilities::BasisKey EvaluateTriFaceBasisKey(const int facedir, const LibUtilities::BasisType faceDirBasisType, const int numpoints, const int nummodes)
const int kSVVDGFiltermodesmin
Definition: StdRegions.hpp:352
std::shared_ptr< StdPyrExp > StdPyrExpSharedPtr
Definition: StdPyrExp.h:248
const int kSVVDGFiltermodesmax
Definition: StdRegions.hpp:353
LibUtilities::BasisKey EvaluateQuadFaceBasisKey(const int facedir, const LibUtilities::BasisType faceDirBasisType, const int numpoints, const int nummodes)
const NekDouble kSVVDGFilter[9][11]
Definition: StdRegions.hpp:355
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
static Array< OneD, NekDouble > NullNekDouble1DArray
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:75
double NekDouble
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.cpp:209
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.cpp:359
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.cpp:248
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1255