Nektar++
QuadExp.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File QuadExp.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: Expansion for quadrilateral elements.
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <boost/core/ignore_unused.hpp>
36 
42 #include <LocalRegions/QuadExp.h>
43 #include <LocalRegions/SegExp.h>
44 
45 using namespace std;
46 
47 namespace Nektar
48 {
49 namespace LocalRegions
50 {
51 QuadExp::QuadExp(const LibUtilities::BasisKey &Ba,
52  const LibUtilities::BasisKey &Bb,
54  : StdExpansion(Ba.GetNumModes() * Bb.GetNumModes(), 2, Ba, Bb),
55  StdExpansion2D(Ba.GetNumModes() * Bb.GetNumModes(), Ba, Bb),
56  StdQuadExp(Ba, Bb), Expansion(geom), Expansion2D(geom),
57  m_matrixManager(
58  std::bind(&Expansion2D::CreateMatrix, this, std::placeholders::_1),
59  std::string("QuadExpMatrix")),
60  m_staticCondMatrixManager(std::bind(&Expansion::CreateStaticCondMatrix,
61  this, std::placeholders::_1),
62  std::string("QuadExpStaticCondMatrix"))
63 {
64 }
65 
67  : StdExpansion(T), StdExpansion2D(T), StdQuadExp(T), Expansion(T),
68  Expansion2D(T), m_matrixManager(T.m_matrixManager),
69  m_staticCondMatrixManager(T.m_staticCondMatrixManager)
70 {
71 }
72 
74 {
75 }
76 
78 {
79  int nquad0 = m_base[0]->GetNumPoints();
80  int nquad1 = m_base[1]->GetNumPoints();
82  NekDouble ival;
83  Array<OneD, NekDouble> tmp(nquad0 * nquad1);
84 
85  // multiply inarray with Jacobian
86  if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
87  {
88  Vmath::Vmul(nquad0 * nquad1, jac, 1, inarray, 1, tmp, 1);
89  }
90  else
91  {
92  Vmath::Smul(nquad0 * nquad1, jac[0], inarray, 1, tmp, 1);
93  }
94 
95  // call StdQuadExp version;
96  ival = StdQuadExp::v_Integral(tmp);
97  return ival;
98 }
99 
101  Array<OneD, NekDouble> &out_d0,
102  Array<OneD, NekDouble> &out_d1,
103  Array<OneD, NekDouble> &out_d2)
104 {
105  int nquad0 = m_base[0]->GetNumPoints();
106  int nquad1 = m_base[1]->GetNumPoints();
107  int nqtot = nquad0 * nquad1;
108  const Array<TwoD, const NekDouble> &df =
109  m_metricinfo->GetDerivFactors(GetPointsKeys());
110  Array<OneD, NekDouble> diff0(2 * nqtot);
111  Array<OneD, NekDouble> diff1(diff0 + nqtot);
112 
113  StdQuadExp::v_PhysDeriv(inarray, diff0, diff1);
114 
115  if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
116  {
117  if (out_d0.size())
118  {
119  Vmath::Vmul(nqtot, df[0], 1, diff0, 1, out_d0, 1);
120  Vmath::Vvtvp(nqtot, df[1], 1, diff1, 1, out_d0, 1, out_d0, 1);
121  }
122 
123  if (out_d1.size())
124  {
125  Vmath::Vmul(nqtot, df[2], 1, diff0, 1, out_d1, 1);
126  Vmath::Vvtvp(nqtot, df[3], 1, diff1, 1, out_d1, 1, out_d1, 1);
127  }
128 
129  if (out_d2.size())
130  {
131  Vmath::Vmul(nqtot, df[4], 1, diff0, 1, out_d2, 1);
132  Vmath::Vvtvp(nqtot, df[5], 1, diff1, 1, out_d2, 1, out_d2, 1);
133  }
134  }
135  else // regular geometry
136  {
137  if (out_d0.size())
138  {
139  Vmath::Smul(nqtot, df[0][0], diff0, 1, out_d0, 1);
140  Blas::Daxpy(nqtot, df[1][0], diff1, 1, out_d0, 1);
141  }
142 
143  if (out_d1.size())
144  {
145  Vmath::Smul(nqtot, df[2][0], diff0, 1, out_d1, 1);
146  Blas::Daxpy(nqtot, df[3][0], diff1, 1, out_d1, 1);
147  }
148 
149  if (out_d2.size())
150  {
151  Vmath::Smul(nqtot, df[4][0], diff0, 1, out_d2, 1);
152  Blas::Daxpy(nqtot, df[5][0], diff1, 1, out_d2, 1);
153  }
154  }
155 }
156 
157 void QuadExp::v_PhysDeriv(const int dir,
158  const Array<OneD, const NekDouble> &inarray,
159  Array<OneD, NekDouble> &outarray)
160 {
161  switch (dir)
162  {
163  case 0:
164  {
165  v_PhysDeriv(inarray, outarray, NullNekDouble1DArray,
167  }
168  break;
169  case 1:
170  {
171  v_PhysDeriv(inarray, NullNekDouble1DArray, outarray,
173  }
174  break;
175  case 2:
176  {
178  outarray);
179  }
180  break;
181  default:
182  {
183  ASSERTL1(false, "input dir is out of range");
184  }
185  break;
186  }
187 }
188 
190  const Array<OneD, const NekDouble> &inarray,
192 {
193  int nquad0 = m_base[0]->GetNumPoints();
194  int nquad1 = m_base[1]->GetNumPoints();
195  int nqtot = nquad0 * nquad1;
196 
197  const Array<TwoD, const NekDouble> &df =
198  m_metricinfo->GetDerivFactors(GetPointsKeys());
199 
200  Array<OneD, NekDouble> diff0(2 * nqtot);
201  Array<OneD, NekDouble> diff1(diff0 + nqtot);
202 
203  StdQuadExp::v_PhysDeriv(inarray, diff0, diff1);
204 
205  if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
206  {
208 
209  // d/dx_v^s = v_x*ds/dx + v_y*ds/dy + v_z*dx/dz
210  for (int i = 0; i < 2; ++i)
211  {
212  tangmat[i] = Array<OneD, NekDouble>(nqtot, 0.0);
213  for (int k = 0; k < (m_geom->GetCoordim()); ++k)
214  {
215  Vmath::Vvtvp(nqtot, &df[2 * k + i][0], 1, &direction[k * nqtot],
216  1, &tangmat[i][0], 1, &tangmat[i][0], 1);
217  }
218  }
219 
220  /// D_v = d/dx_v^s + d/dx_v^r
221  if (out.size())
222  {
223  Vmath::Vmul(nqtot, &tangmat[0][0], 1, &diff0[0], 1, &out[0], 1);
224  Vmath::Vvtvp(nqtot, &tangmat[1][0], 1, &diff1[0], 1, &out[0], 1,
225  &out[0], 1);
226  }
227  }
228  else
229  {
231  "Wrong route");
232  }
233 }
234 
236  Array<OneD, NekDouble> &outarray)
237 {
238  if ((m_base[0]->Collocation()) && (m_base[1]->Collocation()))
239  {
240  Vmath::Vcopy(m_ncoeffs, inarray, 1, outarray, 1);
241  }
242  else
243  {
244  IProductWRTBase(inarray, outarray);
245 
246  // get Mass matrix inverse
247  MatrixKey masskey(StdRegions::eInvMass, DetShapeType(), *this);
248  DNekScalMatSharedPtr matsys = m_matrixManager[masskey];
249 
250  // copy inarray in case inarray == outarray
251  NekVector<NekDouble> in(m_ncoeffs, outarray, eCopy);
252  NekVector<NekDouble> out(m_ncoeffs, outarray, eWrapper);
253 
254  out = (*matsys) * in;
255  }
256 }
257 
259  const Array<OneD, const NekDouble> &inarray,
260  Array<OneD, NekDouble> &outarray)
261 {
262  if ((m_base[0]->Collocation()) && (m_base[1]->Collocation()))
263  {
264  Vmath::Vcopy(m_ncoeffs, inarray, 1, outarray, 1);
265  }
266  else
267  {
268  int i, j;
269  int npoints[2] = {m_base[0]->GetNumPoints(), m_base[1]->GetNumPoints()};
270  int nmodes[2] = {m_base[0]->GetNumModes(), m_base[1]->GetNumModes()};
271 
272  fill(outarray.get(), outarray.get() + m_ncoeffs, 0.0);
273 
274  if (nmodes[0] == 1 && nmodes[1] == 1)
275  {
276  outarray[0] = inarray[0];
277  return;
278  }
279 
280  Array<OneD, NekDouble> physEdge[4];
281  Array<OneD, NekDouble> coeffEdge[4];
282  StdRegions::Orientation orient[4];
283  for (i = 0; i < 4; i++)
284  {
285  physEdge[i] = Array<OneD, NekDouble>(npoints[i % 2]);
286  coeffEdge[i] = Array<OneD, NekDouble>(nmodes[i % 2]);
287  orient[i] = GetTraceOrient(i);
288  }
289 
290  for (i = 0; i < npoints[0]; i++)
291  {
292  physEdge[0][i] = inarray[i];
293  physEdge[2][i] = inarray[npoints[0] * (npoints[1] - 1) + i];
294  }
295 
296  for (i = 0; i < npoints[1]; i++)
297  {
298  physEdge[1][i] = inarray[npoints[0] - 1 + i * npoints[0]];
299  physEdge[3][i] = inarray[i * npoints[0]];
300  }
301 
302  for (i = 0; i < 4; i++)
303  {
304  if (orient[i] == StdRegions::eBackwards)
305  {
306  reverse((physEdge[i]).get(),
307  (physEdge[i]).get() + npoints[i % 2]);
308  }
309  }
310 
311  SegExpSharedPtr segexp[4];
312  for (i = 0; i < 4; i++)
313  {
315  m_base[i % 2]->GetBasisKey(), GetGeom2D()->GetEdge(i));
316  }
317 
318  Array<OneD, unsigned int> mapArray;
319  Array<OneD, int> signArray;
320  NekDouble sign;
321 
322  for (i = 0; i < 4; i++)
323  {
324  segexp[i % 2]->FwdTransBndConstrained(physEdge[i], coeffEdge[i]);
325 
326  GetTraceToElementMap(i, mapArray, signArray, orient[i]);
327  for (j = 0; j < nmodes[i % 2]; j++)
328  {
329  sign = (NekDouble)signArray[j];
330  outarray[mapArray[j]] = sign * coeffEdge[i][j];
331  }
332  }
333 
334  int nBoundaryDofs = NumBndryCoeffs();
335  int nInteriorDofs = m_ncoeffs - nBoundaryDofs;
336 
337  if (nInteriorDofs > 0)
338  {
341 
343  DetShapeType(), *this);
344  MassMatrixOp(outarray, tmp0, stdmasskey);
345  IProductWRTBase(inarray, tmp1);
346 
347  Vmath::Vsub(m_ncoeffs, tmp1, 1, tmp0, 1, tmp1, 1);
348 
349  // get Mass matrix inverse (only of interior DOF)
350  // use block (1,1) of the static condensed system
351  // note: this block alreay contains the inverse matrix
352  MatrixKey masskey(StdRegions::eMass, DetShapeType(), *this);
353  DNekScalMatSharedPtr matsys =
354  (m_staticCondMatrixManager[masskey])->GetBlock(1, 1);
355 
356  Array<OneD, NekDouble> rhs(nInteriorDofs);
357  Array<OneD, NekDouble> result(nInteriorDofs);
358 
359  GetInteriorMap(mapArray);
360 
361  for (i = 0; i < nInteriorDofs; i++)
362  {
363  rhs[i] = tmp1[mapArray[i]];
364  }
365 
366  Blas::Dgemv('N', nInteriorDofs, nInteriorDofs, matsys->Scale(),
367  &((matsys->GetOwnedMatrix())->GetPtr())[0],
368  nInteriorDofs, rhs.get(), 1, 0.0, result.get(), 1);
369 
370  for (i = 0; i < nInteriorDofs; i++)
371  {
372  outarray[mapArray[i]] = result[i];
373  }
374  }
375  }
376 }
377 
379  Array<OneD, NekDouble> &outarray)
380 {
381  if (m_base[0]->Collocation() && m_base[1]->Collocation())
382  {
383  MultiplyByQuadratureMetric(inarray, outarray);
384  }
385  else
386  {
387  IProductWRTBase_SumFac(inarray, outarray);
388  }
389 }
390 
392  const int dir, const Array<OneD, const NekDouble> &inarray,
393  Array<OneD, NekDouble> &outarray)
394 {
395  IProductWRTDerivBase_SumFac(dir, inarray, outarray);
396 }
397 
399  const Array<OneD, const NekDouble> &inarray,
400  Array<OneD, NekDouble> &outarray, bool multiplybyweights)
401 {
402  int nquad0 = m_base[0]->GetNumPoints();
403  int nquad1 = m_base[1]->GetNumPoints();
404  int order0 = m_base[0]->GetNumModes();
405 
406  if (multiplybyweights)
407  {
408  Array<OneD, NekDouble> tmp(nquad0 * nquad1 + nquad1 * order0);
409  Array<OneD, NekDouble> wsp(tmp + nquad0 * nquad1);
410 
411  MultiplyByQuadratureMetric(inarray, tmp);
412  StdQuadExp::IProductWRTBase_SumFacKernel(m_base[0]->GetBdata(),
413  m_base[1]->GetBdata(), tmp,
414  outarray, wsp, true, true);
415  }
416  else
417  {
418  Array<OneD, NekDouble> wsp(nquad1 * order0);
419 
420  StdQuadExp::IProductWRTBase_SumFacKernel(m_base[0]->GetBdata(),
421  m_base[1]->GetBdata(), inarray,
422  outarray, wsp, true, true);
423  }
424 }
425 
427  const Array<OneD, const NekDouble> &inarray,
428  Array<OneD, NekDouble> &outarray)
429 {
430  int nq = GetTotPoints();
431  MatrixKey iprodmatkey(StdRegions::eIProductWRTBase, DetShapeType(), *this);
432  DNekScalMatSharedPtr iprodmat = m_matrixManager[iprodmatkey];
433 
434  Blas::Dgemv('N', m_ncoeffs, nq, iprodmat->Scale(),
435  (iprodmat->GetOwnedMatrix())->GetPtr().get(), m_ncoeffs,
436  inarray.get(), 1, 0.0, outarray.get(), 1);
437 }
438 
440  const int dir, const Array<OneD, const NekDouble> &inarray,
441  Array<OneD, NekDouble> &outarray)
442 {
443  ASSERTL1((dir == 0) || (dir == 1) || (dir == 2), "Invalid direction.");
444  ASSERTL1((dir == 2) ? (m_geom->GetCoordim() == 3) : true,
445  "Invalid direction.");
446 
447  int nquad0 = m_base[0]->GetNumPoints();
448  int nquad1 = m_base[1]->GetNumPoints();
449  int nqtot = nquad0 * nquad1;
450  int nmodes0 = m_base[0]->GetNumModes();
451 
452  Array<OneD, NekDouble> tmp1(2 * nqtot + m_ncoeffs + nmodes0 * nquad1);
453  Array<OneD, NekDouble> tmp2(tmp1 + nqtot);
454  Array<OneD, NekDouble> tmp3(tmp1 + 2 * nqtot);
455  Array<OneD, NekDouble> tmp4(tmp1 + 2 * nqtot + m_ncoeffs);
456 
458  tmp2D[0] = tmp1;
459  tmp2D[1] = tmp2;
460 
461  QuadExp::v_AlignVectorToCollapsedDir(dir, inarray, tmp2D);
462 
463  MultiplyByQuadratureMetric(tmp1, tmp1);
464  MultiplyByQuadratureMetric(tmp2, tmp2);
465 
466  IProductWRTBase_SumFacKernel(m_base[0]->GetDbdata(), m_base[1]->GetBdata(),
467  tmp1, tmp3, tmp4, false, true);
468  IProductWRTBase_SumFacKernel(m_base[0]->GetBdata(), m_base[1]->GetDbdata(),
469  tmp2, outarray, tmp4, true, false);
470  Vmath::Vadd(m_ncoeffs, tmp3, 1, outarray, 1, outarray, 1);
471 }
472 
474  const int dir, const Array<OneD, const NekDouble> &inarray,
475  Array<OneD, Array<OneD, NekDouble>> &outarray)
476 {
477  ASSERTL1((dir == 0) || (dir == 1) || (dir == 2), "Invalid direction.");
478  ASSERTL1((dir == 2) ? (m_geom->GetCoordim() == 3) : true,
479  "Invalid direction.");
480 
481  int nquad0 = m_base[0]->GetNumPoints();
482  int nquad1 = m_base[1]->GetNumPoints();
483  int nqtot = nquad0 * nquad1;
484  int nmodes0 = m_base[0]->GetNumModes();
485 
486  const Array<TwoD, const NekDouble> &df =
487  m_metricinfo->GetDerivFactors(GetPointsKeys());
488 
489  Array<OneD, NekDouble> tmp1 = outarray[0];
490  Array<OneD, NekDouble> tmp2 = outarray[1];
492  Array<OneD, NekDouble> tmp4(nmodes0 * nquad1);
493 
494  if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
495  {
496  Vmath::Vmul(nqtot, &df[2 * dir][0], 1, inarray.get(), 1, tmp1.get(), 1);
497  Vmath::Vmul(nqtot, &df[2 * dir + 1][0], 1, inarray.get(), 1, tmp2.get(),
498  1);
499  }
500  else
501  {
502  Vmath::Smul(nqtot, df[2 * dir][0], inarray.get(), 1, tmp1.get(), 1);
503  Vmath::Smul(nqtot, df[2 * dir + 1][0], inarray.get(), 1, tmp2.get(), 1);
504  }
505 }
506 
508  const int dir, const Array<OneD, const NekDouble> &inarray,
509  Array<OneD, NekDouble> &outarray)
510 {
511  int nq = GetTotPoints();
513 
514  switch (dir)
515  {
516  case 0:
517  {
519  }
520  break;
521  case 1:
522  {
524  }
525  break;
526  case 2:
527  {
529  }
530  break;
531  default:
532  {
533  ASSERTL1(false, "input dir is out of range");
534  }
535  break;
536  }
537 
538  MatrixKey iprodmatkey(mtype, DetShapeType(), *this);
539  DNekScalMatSharedPtr iprodmat = m_matrixManager[iprodmatkey];
540 
541  Blas::Dgemv('N', m_ncoeffs, nq, iprodmat->Scale(),
542  (iprodmat->GetOwnedMatrix())->GetPtr().get(), m_ncoeffs,
543  inarray.get(), 1, 0.0, outarray.get(), 1);
544 }
545 
550 {
551  int nq = m_base[0]->GetNumPoints() * m_base[1]->GetNumPoints();
552  Array<OneD, NekDouble> Fn(nq);
553 
555  GetLeftAdjacentElementExp()->GetTraceNormal(
557 
558  if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
559  {
560  Vmath::Vvtvvtp(nq, &normals[0][0], 1, &Fx[0], 1, &normals[1][0], 1,
561  &Fy[0], 1, &Fn[0], 1);
562  Vmath::Vvtvp(nq, &normals[2][0], 1, &Fz[0], 1, &Fn[0], 1, &Fn[0], 1);
563  }
564  else
565  {
566  Vmath::Svtsvtp(nq, normals[0][0], &Fx[0], 1, normals[1][0], &Fy[0], 1,
567  &Fn[0], 1);
568  Vmath::Svtvp(nq, normals[2][0], &Fz[0], 1, &Fn[0], 1, &Fn[0], 1);
569  }
570 
571  IProductWRTBase(Fn, outarray);
572 }
573 
575  const Array<OneD, const Array<OneD, NekDouble>> &Fvec,
576  Array<OneD, NekDouble> &outarray)
577 {
578  NormVectorIProductWRTBase(Fvec[0], Fvec[1], Fvec[2], outarray);
579 }
580 
582 {
584  m_base[0]->GetBasisKey(), m_base[1]->GetBasisKey());
585 }
586 
588 {
590  m_base[0]->GetPointsKey());
592  m_base[1]->GetPointsKey());
593 
595  bkey1);
596 }
597 
599  Array<OneD, NekDouble> &coords_1,
600  Array<OneD, NekDouble> &coords_2)
601 {
602  Expansion::v_GetCoords(coords_0, coords_1, coords_2);
603 }
604 
606  Array<OneD, NekDouble> &coords)
607 {
608  int i;
609 
610  ASSERTL1(Lcoords[0] >= -1.0 && Lcoords[1] <= 1.0 && Lcoords[1] >= -1.0 &&
611  Lcoords[1] <= 1.0,
612  "Local coordinates are not in region [-1,1]");
613 
614  m_geom->FillGeom();
615  for (i = 0; i < m_geom->GetCoordim(); ++i)
616  {
617  coords[i] = m_geom->GetCoord(i, Lcoords);
618  }
619 }
620 
621 /**
622  * Given the local cartesian coordinate \a Lcoord evaluate the
623  * value of physvals at this point by calling through to the
624  * StdExpansion method
625  */
627  const Array<OneD, const NekDouble> &Lcoord,
628  const Array<OneD, const NekDouble> &physvals)
629 {
630  // Evaluate point in local (eta) coordinates.
631  return StdQuadExp::v_PhysEvaluate(Lcoord, physvals);
632 }
633 
635  const Array<OneD, const NekDouble> &physvals)
636 {
638 
639  ASSERTL0(m_geom, "m_geom not defined");
640  m_geom->GetLocCoords(coord, Lcoord);
641 
642  return StdQuadExp::v_PhysEvaluate(Lcoord, physvals);
643 }
644 
645 // Get edge values from the 2D Phys space along an edge
646 // following a counter clockwise edge convention for definition
647 // of edgedir, Note that point distribution is given by QuadExp.
648 void QuadExp::v_GetEdgePhysVals(const int edge,
649  const Array<OneD, const NekDouble> &inarray,
650  Array<OneD, NekDouble> &outarray)
651 {
652  int nquad0 = m_base[0]->GetNumPoints();
653  int nquad1 = m_base[1]->GetNumPoints();
654 
655  StdRegions::Orientation edgedir = GetTraceOrient(edge);
656  switch (edge)
657  {
658  case 0:
659  if (edgedir == StdRegions::eForwards)
660  {
661  Vmath::Vcopy(nquad0, &(inarray[0]), 1, &(outarray[0]), 1);
662  }
663  else
664  {
665  Vmath::Vcopy(nquad0, &(inarray[0]) + (nquad0 - 1), -1,
666  &(outarray[0]), 1);
667  }
668  break;
669  case 1:
670  if (edgedir == StdRegions::eForwards)
671  {
672  Vmath::Vcopy(nquad1, &(inarray[0]) + (nquad0 - 1), nquad0,
673  &(outarray[0]), 1);
674  }
675  else
676  {
677  Vmath::Vcopy(nquad1, &(inarray[0]) + (nquad0 * nquad1 - 1),
678  -nquad0, &(outarray[0]), 1);
679  }
680  break;
681  case 2:
682  if (edgedir == StdRegions::eForwards)
683  {
684  Vmath::Vcopy(nquad0, &(inarray[0]) + (nquad0 * nquad1 - 1), -1,
685  &(outarray[0]), 1);
686  }
687  else
688  {
689  Vmath::Vcopy(nquad0, &(inarray[0]) + nquad0 * (nquad1 - 1), 1,
690  &(outarray[0]), 1);
691  }
692  break;
693  case 3:
694  if (edgedir == StdRegions::eForwards)
695  {
696  Vmath::Vcopy(nquad1, &(inarray[0]) + nquad0 * (nquad1 - 1),
697  -nquad0, &(outarray[0]), 1);
698  }
699  else
700  {
701  Vmath::Vcopy(nquad1, &(inarray[0]), nquad0, &(outarray[0]), 1);
702  }
703  break;
704  default:
705  ASSERTL0(false, "edge value (< 3) is out of range");
706  break;
707  }
708 }
709 
711  const int edge, const StdRegions::StdExpansionSharedPtr &EdgeExp,
712  const Array<OneD, const NekDouble> &inarray,
714 {
715  int nquad0 = m_base[0]->GetNumPoints();
716  int nquad1 = m_base[1]->GetNumPoints();
717 
718  // Implementation for all the basis except Gauss points
721  {
722  switch (edge)
723  {
724  case 0:
725  Vmath::Vcopy(nquad0, &(inarray[0]), 1, &(outarray[0]), 1);
726  break;
727  case 1:
728  Vmath::Vcopy(nquad1, &(inarray[0]) + (nquad0 - 1), nquad0,
729  &(outarray[0]), 1);
730  break;
731  case 2:
732  Vmath::Vcopy(nquad0, &(inarray[0]) + nquad0 * (nquad1 - 1), 1,
733  &(outarray[0]), 1);
734  break;
735  case 3:
736  Vmath::Vcopy(nquad1, &(inarray[0]), nquad0, &(outarray[0]), 1);
737  break;
738  default:
739  ASSERTL0(false, "edge value (< 3) is out of range");
740  break;
741  }
742  }
743  else
744  {
745  QuadExp::v_GetEdgeInterpVals(edge, inarray, outarray);
746  }
747 
748  // Interpolate if required
749  if (m_base[edge % 2]->GetPointsKey() !=
750  EdgeExp->GetBasis(0)->GetPointsKey())
751  {
752  Array<OneD, NekDouble> outtmp(max(nquad0, nquad1));
753 
754  outtmp = outarray;
755 
756  LibUtilities::Interp1D(m_base[edge % 2]->GetPointsKey(), outtmp,
757  EdgeExp->GetBasis(0)->GetPointsKey(), outarray);
758  }
759 
760  if (orient == StdRegions::eNoOrientation)
761  {
762  orient = GetTraceOrient(edge);
763  }
764  // Reverse data if necessary
765  if (orient == StdRegions::eBackwards)
766  {
767  Vmath::Reverse(EdgeExp->GetNumPoints(0), &outarray[0], 1, &outarray[0],
768  1);
769  }
770 }
771 
772 void QuadExp::v_GetEdgeInterpVals(const int edge,
773  const Array<OneD, const NekDouble> &inarray,
774  Array<OneD, NekDouble> &outarray)
775 {
776  int i;
777  int nq0 = m_base[0]->GetNumPoints();
778  int nq1 = m_base[1]->GetNumPoints();
779 
781  factors[StdRegions::eFactorGaussEdge] = edge;
782 
784  *this, factors);
785 
786  DNekScalMatSharedPtr mat_gauss = m_matrixManager[key];
787 
788  switch (edge)
789  {
790  case 0:
791  {
792  for (i = 0; i < nq0; i++)
793  {
794  outarray[i] =
795  Blas::Ddot(nq1, mat_gauss->GetOwnedMatrix()->GetPtr().get(),
796  1, &inarray[i], nq0);
797  }
798  break;
799  }
800  case 1:
801  {
802  for (i = 0; i < nq1; i++)
803  {
804  outarray[i] =
805  Blas::Ddot(nq0, mat_gauss->GetOwnedMatrix()->GetPtr().get(),
806  1, &inarray[i * nq0], 1);
807  }
808  break;
809  }
810  case 2:
811  {
812  for (i = 0; i < nq0; i++)
813  {
814  outarray[i] =
815  Blas::Ddot(nq1, mat_gauss->GetOwnedMatrix()->GetPtr().get(),
816  1, &inarray[i], nq0);
817  }
818  break;
819  }
820  case 3:
821  {
822  for (i = 0; i < nq1; i++)
823  {
824  outarray[i] =
825  Blas::Ddot(nq0, mat_gauss->GetOwnedMatrix()->GetPtr().get(),
826  1, &inarray[i * nq0], 1);
827  }
828  break;
829  }
830  default:
831  ASSERTL0(false, "edge value (< 3) is out of range");
832  break;
833  }
834 }
835 
836 void QuadExp::v_GetTracePhysMap(const int edge, Array<OneD, int> &outarray)
837 {
838  int nquad0 = m_base[0]->GetNumPoints();
839  int nquad1 = m_base[1]->GetNumPoints();
840 
841  // Get points in Cartesian orientation
842  switch (edge)
843  {
844  case 0:
845  outarray = Array<OneD, int>(nquad0);
846  for (int i = 0; i < nquad0; ++i)
847  {
848  outarray[i] = i;
849  }
850  break;
851  case 1:
852  outarray = Array<OneD, int>(nquad1);
853  for (int i = 0; i < nquad1; ++i)
854  {
855  outarray[i] = (nquad0 - 1) + i * nquad0;
856  }
857  break;
858  case 2:
859  outarray = Array<OneD, int>(nquad0);
860  for (int i = 0; i < nquad0; ++i)
861  {
862  outarray[i] = i + nquad0 * (nquad1 - 1);
863  }
864  break;
865  case 3:
866  outarray = Array<OneD, int>(nquad1);
867  for (int i = 0; i < nquad1; ++i)
868  {
869  outarray[i] = i * nquad0;
870  }
871  break;
872  default:
873  ASSERTL0(false, "edge value (< 3) is out of range");
874  break;
875  }
876 }
877 
878 void QuadExp::v_GetTraceQFactors(const int edge,
879  Array<OneD, NekDouble> &outarray)
880 {
881  int i;
882  int nquad0 = m_base[0]->GetNumPoints();
883  int nquad1 = m_base[1]->GetNumPoints();
884 
886  const Array<OneD, const NekDouble> &jac = m_metricinfo->GetJac(ptsKeys);
887  const Array<TwoD, const NekDouble> &df =
888  m_metricinfo->GetDerivFactors(ptsKeys);
889 
890  Array<OneD, NekDouble> j(max(nquad0, nquad1), 0.0);
891  Array<OneD, NekDouble> g0(max(nquad0, nquad1), 0.0);
892  Array<OneD, NekDouble> g1(max(nquad0, nquad1), 0.0);
893  Array<OneD, NekDouble> g2(max(nquad0, nquad1), 0.0);
894  Array<OneD, NekDouble> g3(max(nquad0, nquad1), 0.0);
895 
896  if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
897  {
898  // Implementation for all the basis except Gauss points
901  {
902  switch (edge)
903  {
904  case 0:
905  Vmath::Vcopy(nquad0, &(df[1][0]), 1, &(g1[0]), 1);
906  Vmath::Vcopy(nquad0, &(df[3][0]), 1, &(g3[0]), 1);
907  Vmath::Vcopy(nquad0, &(jac[0]), 1, &(j[0]), 1);
908 
909  for (i = 0; i < nquad0; ++i)
910  {
911  outarray[i] =
912  j[i] * sqrt(g1[i] * g1[i] + g3[i] * g3[i]);
913  }
914  break;
915  case 1:
916  Vmath::Vcopy(nquad1, &(df[0][0]) + (nquad0 - 1), nquad0,
917  &(g0[0]), 1);
918 
919  Vmath::Vcopy(nquad1, &(df[2][0]) + (nquad0 - 1), nquad0,
920  &(g2[0]), 1);
921 
922  Vmath::Vcopy(nquad1, &(jac[0]) + (nquad0 - 1), nquad0,
923  &(j[0]), 1);
924 
925  for (i = 0; i < nquad1; ++i)
926  {
927  outarray[i] =
928  j[i] * sqrt(g0[i] * g0[i] + g2[i] * g2[i]);
929  }
930  break;
931  case 2:
932 
933  Vmath::Vcopy(nquad0, &(df[1][0]) + (nquad0 * (nquad1 - 1)),
934  1, &(g1[0]), 1);
935 
936  Vmath::Vcopy(nquad0, &(df[3][0]) + (nquad0 * (nquad1 - 1)),
937  1, &(g3[0]), 1);
938 
939  Vmath::Vcopy(nquad0, &(jac[0]) + (nquad0 * (nquad1 - 1)), 1,
940  &(j[0]), 1);
941 
942  for (i = 0; i < nquad0; ++i)
943  {
944  outarray[i] =
945  j[i] * sqrt(g1[i] * g1[i] + g3[i] * g3[i]);
946  }
947  break;
948  case 3:
949 
950  Vmath::Vcopy(nquad1, &(df[0][0]), nquad0, &(g0[0]), 1);
951  Vmath::Vcopy(nquad1, &(df[2][0]), nquad0, &(g2[0]), 1);
952  Vmath::Vcopy(nquad1, &(jac[0]), nquad0, &(j[0]), 1);
953 
954  for (i = 0; i < nquad1; ++i)
955  {
956  outarray[i] =
957  j[i] * sqrt(g0[i] * g0[i] + g2[i] * g2[i]);
958  }
959  break;
960  default:
961  ASSERTL0(false, "edge value (< 3) is out of range");
962  break;
963  }
964  }
965  else
966  {
967  int nqtot = nquad0 * nquad1;
968  Array<OneD, NekDouble> tmp_gmat0(nqtot, 0.0);
969  Array<OneD, NekDouble> tmp_gmat1(nqtot, 0.0);
970  Array<OneD, NekDouble> tmp_gmat2(nqtot, 0.0);
971  Array<OneD, NekDouble> tmp_gmat3(nqtot, 0.0);
972  Array<OneD, NekDouble> g0_edge(max(nquad0, nquad1), 0.0);
973  Array<OneD, NekDouble> g1_edge(max(nquad0, nquad1), 0.0);
974  Array<OneD, NekDouble> g2_edge(max(nquad0, nquad1), 0.0);
975  Array<OneD, NekDouble> g3_edge(max(nquad0, nquad1), 0.0);
976  Array<OneD, NekDouble> jac_edge(max(nquad0, nquad1), 0.0);
977 
978  switch (edge)
979  {
980  case 0:
981  Vmath::Vmul(nqtot, &(df[1][0]), 1, &jac[0], 1,
982  &(tmp_gmat1[0]), 1);
983  Vmath::Vmul(nqtot, &(df[3][0]), 1, &jac[0], 1,
984  &(tmp_gmat3[0]), 1);
985  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat1, g1_edge);
986  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat3, g3_edge);
987 
988  for (i = 0; i < nquad0; ++i)
989  {
990  outarray[i] = sqrt(g1_edge[i] * g1_edge[i] +
991  g3_edge[i] * g3_edge[i]);
992  }
993  break;
994 
995  case 1:
996  Vmath::Vmul(nqtot, &(df[0][0]), 1, &jac[0], 1,
997  &(tmp_gmat0[0]), 1);
998  Vmath::Vmul(nqtot, &(df[2][0]), 1, &jac[0], 1,
999  &(tmp_gmat2[0]), 1);
1000  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat0, g0_edge);
1001  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat2, g2_edge);
1002 
1003  for (i = 0; i < nquad1; ++i)
1004  {
1005  outarray[i] = sqrt(g0_edge[i] * g0_edge[i] +
1006  g2_edge[i] * g2_edge[i]);
1007  }
1008 
1009  break;
1010  case 2:
1011 
1012  Vmath::Vmul(nqtot, &(df[1][0]), 1, &jac[0], 1,
1013  &(tmp_gmat1[0]), 1);
1014  Vmath::Vmul(nqtot, &(df[3][0]), 1, &jac[0], 1,
1015  &(tmp_gmat3[0]), 1);
1016  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat1, g1_edge);
1017  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat3, g3_edge);
1018 
1019  for (i = 0; i < nquad0; ++i)
1020  {
1021  outarray[i] = sqrt(g1_edge[i] * g1_edge[i] +
1022  g3_edge[i] * g3_edge[i]);
1023  }
1024 
1025  Vmath::Reverse(nquad0, &outarray[0], 1, &outarray[0], 1);
1026 
1027  break;
1028  case 3:
1029  Vmath::Vmul(nqtot, &(df[0][0]), 1, &jac[0], 1,
1030  &(tmp_gmat0[0]), 1);
1031  Vmath::Vmul(nqtot, &(df[2][0]), 1, &jac[0], 1,
1032  &(tmp_gmat2[0]), 1);
1033  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat0, g0_edge);
1034  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat2, g2_edge);
1035 
1036  for (i = 0; i < nquad1; ++i)
1037  {
1038  outarray[i] = sqrt(g0_edge[i] * g0_edge[i] +
1039  g2_edge[i] * g2_edge[i]);
1040  }
1041 
1042  Vmath::Reverse(nquad1, &outarray[0], 1, &outarray[0], 1);
1043 
1044  break;
1045  default:
1046  ASSERTL0(false, "edge value (< 3) is out of range");
1047  break;
1048  }
1049  }
1050  }
1051  else
1052  {
1053 
1054  switch (edge)
1055  {
1056  case 0:
1057 
1058  for (i = 0; i < nquad0; ++i)
1059  {
1060  outarray[i] = jac[0] * sqrt(df[1][0] * df[1][0] +
1061  df[3][0] * df[3][0]);
1062  }
1063  break;
1064  case 1:
1065  for (i = 0; i < nquad1; ++i)
1066  {
1067  outarray[i] = jac[0] * sqrt(df[0][0] * df[0][0] +
1068  df[2][0] * df[2][0]);
1069  }
1070  break;
1071  case 2:
1072  for (i = 0; i < nquad0; ++i)
1073  {
1074  outarray[i] = jac[0] * sqrt(df[1][0] * df[1][0] +
1075  df[3][0] * df[3][0]);
1076  }
1077  break;
1078  case 3:
1079  for (i = 0; i < nquad1; ++i)
1080  {
1081  outarray[i] = jac[0] * sqrt(df[0][0] * df[0][0] +
1082  df[2][0] * df[2][0]);
1083  }
1084  break;
1085  default:
1086  ASSERTL0(false, "edge value (< 3) is out of range");
1087  break;
1088  }
1089  }
1090 }
1091 
1092 void QuadExp::v_ComputeTraceNormal(const int edge)
1093 {
1094  int i;
1095  const SpatialDomains::GeomFactorsSharedPtr &geomFactors =
1096  GetGeom()->GetMetricInfo();
1097  SpatialDomains::GeomType type = geomFactors->GetGtype();
1098 
1100  for (i = 0; i < ptsKeys.size(); ++i)
1101  {
1102  // Need at least 2 points for computing normals
1103  if (ptsKeys[i].GetNumPoints() == 1)
1104  {
1105  LibUtilities::PointsKey pKey(2, ptsKeys[i].GetPointsType());
1106  ptsKeys[i] = pKey;
1107  }
1108  }
1109 
1110  const Array<TwoD, const NekDouble> &df =
1111  geomFactors->GetDerivFactors(ptsKeys);
1112  const Array<OneD, const NekDouble> &jac = geomFactors->GetJac(ptsKeys);
1113  int nqe;
1114  if (edge == 0 || edge == 2)
1115  {
1116  nqe = m_base[0]->GetNumPoints();
1117  }
1118  else
1119  {
1120  nqe = m_base[1]->GetNumPoints();
1121  }
1122  int vCoordDim = GetCoordim();
1123 
1126  for (i = 0; i < vCoordDim; ++i)
1127  {
1128  normal[i] = Array<OneD, NekDouble>(nqe);
1129  }
1130 
1131  size_t nqb = nqe;
1132  size_t nbnd = edge;
1135 
1136  // Regular geometry case
1137  if ((type == SpatialDomains::eRegular) ||
1139  {
1140  NekDouble fac;
1141  // Set up normals
1142  switch (edge)
1143  {
1144  case 0:
1145  for (i = 0; i < vCoordDim; ++i)
1146  {
1147  Vmath::Fill(nqe, -df[2 * i + 1][0], normal[i], 1);
1148  }
1149  break;
1150  case 1:
1151  for (i = 0; i < vCoordDim; ++i)
1152  {
1153  Vmath::Fill(nqe, df[2 * i][0], normal[i], 1);
1154  }
1155  break;
1156  case 2:
1157  for (i = 0; i < vCoordDim; ++i)
1158  {
1159  Vmath::Fill(nqe, df[2 * i + 1][0], normal[i], 1);
1160  }
1161  break;
1162  case 3:
1163  for (i = 0; i < vCoordDim; ++i)
1164  {
1165  Vmath::Fill(nqe, -df[2 * i][0], normal[i], 1);
1166  }
1167  break;
1168  default:
1169  ASSERTL0(false, "edge is out of range (edge < 4)");
1170  }
1171 
1172  // normalise
1173  fac = 0.0;
1174  for (i = 0; i < vCoordDim; ++i)
1175  {
1176  fac += normal[i][0] * normal[i][0];
1177  }
1178  fac = 1.0 / sqrt(fac);
1179 
1180  Vmath::Fill(nqb, fac, length, 1);
1181 
1182  for (i = 0; i < vCoordDim; ++i)
1183  {
1184  Vmath::Smul(nqe, fac, normal[i], 1, normal[i], 1);
1185  }
1186  }
1187  else // Set up deformed normals
1188  {
1189  int j;
1190 
1191  int nquad0 = ptsKeys[0].GetNumPoints();
1192  int nquad1 = ptsKeys[1].GetNumPoints();
1193 
1194  LibUtilities::PointsKey from_key;
1195 
1196  Array<OneD, NekDouble> normals(vCoordDim * max(nquad0, nquad1), 0.0);
1197  Array<OneD, NekDouble> edgejac(vCoordDim * max(nquad0, nquad1), 0.0);
1198 
1199  // Extract Jacobian along edges and recover local
1200  // derivates (dx/dr) for polynomial interpolation by
1201  // multiplying m_gmat by jacobian
1202 
1203  // Implementation for all the basis except Gauss points
1206  {
1207  switch (edge)
1208  {
1209  case 0:
1210  for (j = 0; j < nquad0; ++j)
1211  {
1212  edgejac[j] = jac[j];
1213  for (i = 0; i < vCoordDim; ++i)
1214  {
1215  normals[i * nquad0 + j] =
1216  -df[2 * i + 1][j] * edgejac[j];
1217  }
1218  }
1219  from_key = ptsKeys[0];
1220  break;
1221  case 1:
1222  for (j = 0; j < nquad1; ++j)
1223  {
1224  edgejac[j] = jac[nquad0 * j + nquad0 - 1];
1225  for (i = 0; i < vCoordDim; ++i)
1226  {
1227  normals[i * nquad1 + j] =
1228  df[2 * i][nquad0 * j + nquad0 - 1] * edgejac[j];
1229  }
1230  }
1231  from_key = ptsKeys[1];
1232  break;
1233  case 2:
1234  for (j = 0; j < nquad0; ++j)
1235  {
1236  edgejac[j] = jac[nquad0 * (nquad1 - 1) + j];
1237  for (i = 0; i < vCoordDim; ++i)
1238  {
1239  normals[i * nquad0 + j] =
1240  (df[2 * i + 1][nquad0 * (nquad1 - 1) + j]) *
1241  edgejac[j];
1242  }
1243  }
1244  from_key = ptsKeys[0];
1245  break;
1246  case 3:
1247  for (j = 0; j < nquad1; ++j)
1248  {
1249  edgejac[j] = jac[nquad0 * j];
1250  for (i = 0; i < vCoordDim; ++i)
1251  {
1252  normals[i * nquad1 + j] =
1253  -df[2 * i][nquad0 * j] * edgejac[j];
1254  }
1255  }
1256  from_key = ptsKeys[1];
1257  break;
1258  default:
1259  ASSERTL0(false, "edge is out of range (edge < 3)");
1260  }
1261  }
1262  else
1263  {
1264  int nqtot = nquad0 * nquad1;
1265  Array<OneD, NekDouble> tmp_gmat(nqtot, 0.0);
1266  Array<OneD, NekDouble> tmp_gmat_edge(nqe, 0.0);
1267 
1268  switch (edge)
1269  {
1270  case 0:
1271  for (j = 0; j < nquad0; ++j)
1272  {
1273  for (i = 0; i < vCoordDim; ++i)
1274  {
1275  Vmath::Vmul(nqtot, &(df[2 * i + 1][0]), 1, &jac[0],
1276  1, &(tmp_gmat[0]), 1);
1277  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat,
1278  tmp_gmat_edge);
1279  normals[i * nquad0 + j] = -tmp_gmat_edge[j];
1280  }
1281  }
1282  from_key = ptsKeys[0];
1283  break;
1284  case 1:
1285  for (j = 0; j < nquad1; ++j)
1286  {
1287  for (i = 0; i < vCoordDim; ++i)
1288  {
1289  Vmath::Vmul(nqtot, &(df[2 * i][0]), 1, &jac[0], 1,
1290  &(tmp_gmat[0]), 1);
1291  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat,
1292  tmp_gmat_edge);
1293  normals[i * nquad1 + j] = tmp_gmat_edge[j];
1294  }
1295  }
1296  from_key = ptsKeys[1];
1297  break;
1298  case 2:
1299  for (j = 0; j < nquad0; ++j)
1300  {
1301  for (i = 0; i < vCoordDim; ++i)
1302  {
1303  Vmath::Vmul(nqtot, &(df[2 * i + 1][0]), 1, &jac[0],
1304  1, &(tmp_gmat[0]), 1);
1305  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat,
1306  tmp_gmat_edge);
1307  normals[i * nquad0 + j] = tmp_gmat_edge[j];
1308  }
1309  }
1310  from_key = ptsKeys[0];
1311  break;
1312  case 3:
1313  for (j = 0; j < nquad1; ++j)
1314  {
1315  for (i = 0; i < vCoordDim; ++i)
1316  {
1317  Vmath::Vmul(nqtot, &(df[2 * i][0]), 1, &jac[0], 1,
1318  &(tmp_gmat[0]), 1);
1319  QuadExp::v_GetEdgeInterpVals(edge, tmp_gmat,
1320  tmp_gmat_edge);
1321  normals[i * nquad1 + j] = -tmp_gmat_edge[j];
1322  }
1323  }
1324  from_key = ptsKeys[1];
1325  break;
1326  default:
1327  ASSERTL0(false, "edge is out of range (edge < 3)");
1328  }
1329  }
1330 
1331  int nq = from_key.GetNumPoints();
1332  Array<OneD, NekDouble> work(nqe, 0.0);
1333 
1334  // interpolate Jacobian and invert
1335  LibUtilities::Interp1D(from_key, jac, m_base[0]->GetPointsKey(), work);
1336  Vmath::Sdiv(nqe, 1.0, &work[0], 1, &work[0], 1);
1337 
1338  // interpolate
1339  for (i = 0; i < GetCoordim(); ++i)
1340  {
1341  LibUtilities::Interp1D(from_key, &normals[i * nq],
1342  m_base[0]->GetPointsKey(), &normal[i][0]);
1343  Vmath::Vmul(nqe, work, 1, normal[i], 1, normal[i], 1);
1344  }
1345 
1346  // normalise normal vectors
1347  Vmath::Zero(nqe, work, 1);
1348  for (i = 0; i < GetCoordim(); ++i)
1349  {
1350  Vmath::Vvtvp(nqe, normal[i], 1, normal[i], 1, work, 1, work, 1);
1351  }
1352 
1353  Vmath::Vsqrt(nqe, work, 1, work, 1);
1354  Vmath::Sdiv(nqe, 1.0, work, 1, work, 1);
1355 
1356  Vmath::Vcopy(nqb, work, 1, length, 1);
1357 
1358  for (i = 0; i < GetCoordim(); ++i)
1359  {
1360  Vmath::Vmul(nqe, normal[i], 1, work, 1, normal[i], 1);
1361  }
1362  }
1363  if (GetGeom()->GetEorient(edge) == StdRegions::eBackwards)
1364  {
1365  for (i = 0; i < vCoordDim; ++i)
1366  {
1367  if (geomFactors->GetGtype() == SpatialDomains::eDeformed)
1368  {
1369  Vmath::Reverse(nqe, normal[i], 1, normal[i], 1);
1370  }
1371  }
1372  }
1373 }
1374 
1376 {
1377  return m_metricinfo;
1378 }
1379 
1381 {
1382  return m_geom->GetCoordim();
1383 }
1384 
1386  const NekDouble *data, const std::vector<unsigned int> &nummodes,
1387  int mode_offset, NekDouble *coeffs,
1388  std::vector<LibUtilities::BasisType> &fromType)
1389 {
1390  int data_order0 = nummodes[mode_offset];
1391  int fillorder0 = std::min(m_base[0]->GetNumModes(), data_order0);
1392 
1393  int data_order1 = nummodes[mode_offset + 1];
1394  int order1 = m_base[1]->GetNumModes();
1395  int fillorder1 = min(order1, data_order1);
1396 
1397  // Check if same basis
1398  if (fromType[0] != m_base[0]->GetBasisType() ||
1399  fromType[1] != m_base[1]->GetBasisType())
1400  {
1401  // Construct a quad with the appropriate basis type at our
1402  // quadrature points, and one more to do a forwards
1403  // transform. We can then copy the output to coeffs.
1404  StdRegions::StdQuadExp tmpQuad(
1405  LibUtilities::BasisKey(fromType[0], data_order0,
1406  m_base[0]->GetPointsKey()),
1407  LibUtilities::BasisKey(fromType[1], data_order1,
1408  m_base[1]->GetPointsKey()));
1409  StdRegions::StdQuadExp tmpQuad2(m_base[0]->GetBasisKey(),
1410  m_base[1]->GetBasisKey());
1411 
1412  Array<OneD, const NekDouble> tmpData(tmpQuad.GetNcoeffs(), data);
1413  Array<OneD, NekDouble> tmpBwd(tmpQuad2.GetTotPoints());
1414  Array<OneD, NekDouble> tmpOut(tmpQuad2.GetNcoeffs());
1415 
1416  tmpQuad.BwdTrans(tmpData, tmpBwd);
1417  tmpQuad2.FwdTrans(tmpBwd, tmpOut);
1418  Vmath::Vcopy(tmpOut.size(), &tmpOut[0], 1, coeffs, 1);
1419 
1420  return;
1421  }
1422 
1423  switch (m_base[0]->GetBasisType())
1424  {
1426  {
1427  int i;
1428  int cnt = 0;
1429  int cnt1 = 0;
1430 
1432  "Extraction routine not set up for this basis");
1433 
1434  Vmath::Zero(m_ncoeffs, coeffs, 1);
1435  for (i = 0; i < fillorder0; ++i)
1436  {
1437  Vmath::Vcopy(fillorder1, data + cnt, 1, coeffs + cnt1, 1);
1438  cnt += data_order1;
1439  cnt1 += order1;
1440  }
1441  }
1442  break;
1444  {
1445  LibUtilities::PointsKey p0(nummodes[0],
1447  LibUtilities::PointsKey p1(nummodes[1],
1449  LibUtilities::PointsKey t0(m_base[0]->GetNumModes(),
1451  LibUtilities::PointsKey t1(m_base[1]->GetNumModes(),
1453  LibUtilities::Interp2D(p0, p1, data, t0, t1, coeffs);
1454  }
1455  break;
1457  {
1458  // Assume that input is also Gll_Lagrange but no way to check;
1459  LibUtilities::PointsKey p0(nummodes[0],
1461  LibUtilities::PointsKey p1(nummodes[1],
1463  LibUtilities::PointsKey t0(m_base[0]->GetNumModes(),
1465  LibUtilities::PointsKey t1(m_base[1]->GetNumModes(),
1467  LibUtilities::Interp2D(p0, p1, data, t0, t1, coeffs);
1468  }
1469  break;
1470  default:
1471  ASSERTL0(false, "basis is either not set up or not hierarchicial");
1472  }
1473 }
1474 
1476 {
1477  return m_geom->GetEorient(edge);
1478 }
1479 
1481 {
1482  ASSERTL1(dir >= 0 && dir <= 1, "input dir is out of range");
1483  return m_base[dir];
1484 }
1485 
1486 int QuadExp::v_GetNumPoints(const int dir) const
1487 {
1488  return GetNumPoints(dir);
1489 }
1490 
1492 {
1493  DNekMatSharedPtr returnval;
1494  switch (mkey.GetMatrixType())
1495  {
1503  returnval = Expansion2D::v_GenMatrix(mkey);
1504  break;
1505  default:
1506  returnval = StdQuadExp::v_GenMatrix(mkey);
1507  }
1508  return returnval;
1509 }
1510 
1512  const StdRegions::StdMatrixKey &mkey)
1513 {
1514  LibUtilities::BasisKey bkey0 = m_base[0]->GetBasisKey();
1515  LibUtilities::BasisKey bkey1 = m_base[1]->GetBasisKey();
1518  return tmp->GetStdMatrix(mkey);
1519 }
1520 
1522 {
1523  return m_matrixManager[mkey];
1524 }
1525 
1527 {
1528  return m_staticCondMatrixManager[mkey];
1529 }
1530 
1532 {
1533  m_staticCondMatrixManager.DeleteObject(mkey);
1534 }
1535 
1537  Array<OneD, NekDouble> &outarray,
1538  const StdRegions::StdMatrixKey &mkey)
1539 {
1540  StdExpansion::MassMatrixOp_MatFree(inarray, outarray, mkey);
1541 }
1542 
1544  Array<OneD, NekDouble> &outarray,
1545  const StdRegions::StdMatrixKey &mkey)
1546 {
1547  QuadExp::LaplacianMatrixOp_MatFree(inarray, outarray, mkey);
1548 }
1549 
1550 void QuadExp::v_LaplacianMatrixOp(const int k1, const int k2,
1551  const Array<OneD, const NekDouble> &inarray,
1552  Array<OneD, NekDouble> &outarray,
1553  const StdRegions::StdMatrixKey &mkey)
1554 {
1555  StdExpansion::LaplacianMatrixOp_MatFree(k1, k2, inarray, outarray, mkey);
1556 }
1557 
1559  const Array<OneD, const NekDouble> &inarray,
1560  Array<OneD, NekDouble> &outarray,
1561  const StdRegions::StdMatrixKey &mkey)
1562 {
1563  StdExpansion::WeakDerivMatrixOp_MatFree(i, inarray, outarray, mkey);
1564 }
1565 
1567  const Array<OneD, const NekDouble> &inarray,
1568  Array<OneD, NekDouble> &outarray, const StdRegions::StdMatrixKey &mkey)
1569 {
1570  StdExpansion::WeakDirectionalDerivMatrixOp_MatFree(inarray, outarray, mkey);
1571 }
1572 
1574  const Array<OneD, const NekDouble> &inarray,
1575  Array<OneD, NekDouble> &outarray, const StdRegions::StdMatrixKey &mkey)
1576 {
1577  StdExpansion::MassLevelCurvatureMatrixOp_MatFree(inarray, outarray, mkey);
1578 }
1579 
1581  Array<OneD, NekDouble> &outarray,
1582  const StdRegions::StdMatrixKey &mkey)
1583 {
1584  QuadExp::HelmholtzMatrixOp_MatFree(inarray, outarray, mkey);
1585 }
1586 
1588  const Array<OneD, const NekDouble> &inarray,
1589  Array<OneD, NekDouble> &outarray, const StdRegions::StdMatrixKey &mkey)
1590 {
1591  MatrixKey newkey(mkey);
1592  DNekScalMatSharedPtr mat = GetLocMatrix(newkey);
1593 
1594  if (inarray.get() == outarray.get())
1595  {
1597  Vmath::Vcopy(m_ncoeffs, inarray.get(), 1, tmp.get(), 1);
1598 
1599  Blas::Dgemv('N', m_ncoeffs, m_ncoeffs, mat->Scale(),
1600  (mat->GetOwnedMatrix())->GetPtr().get(), m_ncoeffs,
1601  tmp.get(), 1, 0.0, outarray.get(), 1);
1602  }
1603  else
1604  {
1605  Blas::Dgemv('N', m_ncoeffs, m_ncoeffs, mat->Scale(),
1606  (mat->GetOwnedMatrix())->GetPtr().get(), m_ncoeffs,
1607  inarray.get(), 1, 0.0, outarray.get(), 1);
1608  }
1609 }
1610 
1612  const Array<OneD, const NekDouble> &inarray,
1613  Array<OneD, NekDouble> &outarray)
1614 {
1615  int n_coeffs = inarray.size();
1616 
1617  Array<OneD, NekDouble> coeff(n_coeffs);
1618  Array<OneD, NekDouble> coeff_tmp(n_coeffs, 0.0);
1619  Array<OneD, NekDouble> tmp, tmp2;
1620 
1621  int nmodes0 = m_base[0]->GetNumModes();
1622  int nmodes1 = m_base[1]->GetNumModes();
1623  int numMax = nmodes0;
1624 
1625  Vmath::Vcopy(n_coeffs, inarray, 1, coeff_tmp, 1);
1626 
1627  const LibUtilities::PointsKey Pkey0(nmodes0,
1629  const LibUtilities::PointsKey Pkey1(nmodes1,
1631  LibUtilities::BasisKey b0(m_base[0]->GetBasisType(), nmodes0, Pkey0);
1632  LibUtilities::BasisKey b1(m_base[1]->GetBasisType(), nmodes1, Pkey1);
1633  LibUtilities::BasisKey bortho0(LibUtilities::eOrtho_A, nmodes0, Pkey0);
1634  LibUtilities::BasisKey bortho1(LibUtilities::eOrtho_A, nmodes1, Pkey1);
1635 
1636  LibUtilities::InterpCoeff2D(b0, b1, coeff_tmp, bortho0, bortho1, coeff);
1637 
1638  Vmath::Zero(n_coeffs, coeff_tmp, 1);
1639 
1640  int cnt = 0;
1641  for (int i = 0; i < numMin + 1; ++i)
1642  {
1643  Vmath::Vcopy(numMin, tmp = coeff + cnt, 1, tmp2 = coeff_tmp + cnt, 1);
1644 
1645  cnt = i * numMax;
1646  }
1647 
1648  LibUtilities::InterpCoeff2D(bortho0, bortho1, coeff_tmp, b0, b1, outarray);
1649 }
1650 
1652  const Array<OneD, const NekDouble> &inarray,
1654 {
1655  if (m_metrics.count(eMetricLaplacian00) == 0)
1656  {
1658  }
1659 
1660  int nquad0 = m_base[0]->GetNumPoints();
1661  int nquad1 = m_base[1]->GetNumPoints();
1662  int nqtot = nquad0 * nquad1;
1663  int nmodes0 = m_base[0]->GetNumModes();
1664  int nmodes1 = m_base[1]->GetNumModes();
1665  int wspsize =
1666  max(max(max(nqtot, m_ncoeffs), nquad1 * nmodes0), nquad0 * nmodes1);
1667 
1668  ASSERTL1(wsp.size() >= 3 * wspsize, "Workspace is of insufficient size.");
1669 
1670  const Array<OneD, const NekDouble> &base0 = m_base[0]->GetBdata();
1671  const Array<OneD, const NekDouble> &base1 = m_base[1]->GetBdata();
1672  const Array<OneD, const NekDouble> &dbase0 = m_base[0]->GetDbdata();
1673  const Array<OneD, const NekDouble> &dbase1 = m_base[1]->GetDbdata();
1674  const Array<OneD, const NekDouble> &metric00 =
1676  const Array<OneD, const NekDouble> &metric01 =
1678  const Array<OneD, const NekDouble> &metric11 =
1680 
1681  // Allocate temporary storage
1682  Array<OneD, NekDouble> wsp0(wsp);
1683  Array<OneD, NekDouble> wsp1(wsp + wspsize);
1684  Array<OneD, NekDouble> wsp2(wsp + 2 * wspsize);
1685 
1686  StdExpansion2D::PhysTensorDeriv(inarray, wsp1, wsp2);
1687 
1688  // wsp0 = k = g0 * wsp1 + g1 * wsp2 = g0 * du_dxi1 + g1 * du_dxi2
1689  // wsp2 = l = g1 * wsp1 + g2 * wsp2 = g0 * du_dxi1 + g1 * du_dxi2
1690  // where g0, g1 and g2 are the metric terms set up in the GeomFactors class
1691  // especially for this purpose
1692  Vmath::Vvtvvtp(nqtot, &metric00[0], 1, &wsp1[0], 1, &metric01[0], 1,
1693  &wsp2[0], 1, &wsp0[0], 1);
1694  Vmath::Vvtvvtp(nqtot, &metric01[0], 1, &wsp1[0], 1, &metric11[0], 1,
1695  &wsp2[0], 1, &wsp2[0], 1);
1696 
1697  // outarray = m = (D_xi1 * B)^T * k
1698  // wsp1 = n = (D_xi2 * B)^T * l
1699  IProductWRTBase_SumFacKernel(dbase0, base1, wsp0, outarray, wsp1, false,
1700  true);
1701  IProductWRTBase_SumFacKernel(base0, dbase1, wsp2, wsp1, wsp0, true, false);
1702 
1703  // outarray = outarray + wsp1
1704  // = L * u_hat
1705  Vmath::Vadd(m_ncoeffs, wsp1.get(), 1, outarray.get(), 1, outarray.get(), 1);
1706 }
1707 
1709 {
1710  if (m_metrics.count(eMetricQuadrature) == 0)
1711  {
1713  }
1714 
1715  const SpatialDomains::GeomType type = m_metricinfo->GetGtype();
1716  const unsigned int nqtot = GetTotPoints();
1717  const unsigned int dim = 2;
1718  const MetricType m[3][3] = {
1722 
1723  const Array<TwoD, const NekDouble> gmat =
1724  m_metricinfo->GetGmat(GetPointsKeys());
1725  for (unsigned int i = 0; i < dim; ++i)
1726  {
1727  for (unsigned int j = i; j < dim; ++j)
1728  {
1729  m_metrics[m[i][j]] = Array<OneD, NekDouble>(nqtot);
1730  if (type == SpatialDomains::eDeformed)
1731  {
1732  Vmath::Vcopy(nqtot, &gmat[i * dim + j][0], 1,
1733  &m_metrics[m[i][j]][0], 1);
1734  }
1735  else
1736  {
1737  Vmath::Fill(nqtot, gmat[i * dim + j][0], &m_metrics[m[i][j]][0],
1738  1);
1739  }
1740  MultiplyByQuadratureMetric(m_metrics[m[i][j]], m_metrics[m[i][j]]);
1741  }
1742  }
1743 }
1744 
1746  const StdRegions::StdMatrixKey &mkey)
1747 {
1748  int nq = GetTotPoints();
1749 
1750  // Calculate sqrt of the Jacobian
1752  Array<OneD, NekDouble> sqrt_jac(nq);
1753  if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
1754  {
1755  Vmath::Vsqrt(nq, jac, 1, sqrt_jac, 1);
1756  }
1757  else
1758  {
1759  Vmath::Fill(nq, sqrt(jac[0]), sqrt_jac, 1);
1760  }
1761 
1762  // Multiply array by sqrt(Jac)
1763  Vmath::Vmul(nq, sqrt_jac, 1, array, 1, array, 1);
1764 
1765  // Apply std region filter
1766  StdQuadExp::v_SVVLaplacianFilter(array, mkey);
1767 
1768  // Divide by sqrt(Jac)
1769  Vmath::Vdiv(nq, array, 1, sqrt_jac, 1, array, 1);
1770 }
1771 
1772 /** @brief: This method gets all of the factors which are
1773  required as part of the Gradient Jump Penalty (GJP)
1774  stabilisation and involves the product of the normal and
1775  geometric factors along the element trace.
1776 */
1778  Array<OneD, Array<OneD, NekDouble>> &d0factors,
1779  Array<OneD, Array<OneD, NekDouble>> &d1factors,
1780  Array<OneD, Array<OneD, NekDouble>> &d2factors)
1781 {
1782  boost::ignore_unused(d2factors); // for 3D shapes
1783  int nquad0 = GetNumPoints(0);
1784  int nquad1 = GetNumPoints(1);
1785 
1786  const Array<TwoD, const NekDouble> &df =
1787  m_metricinfo->GetDerivFactors(GetPointsKeys());
1788 
1789  if (d0factors.size() != 4)
1790  {
1791  d0factors = Array<OneD, Array<OneD, NekDouble>>(4);
1792  d1factors = Array<OneD, Array<OneD, NekDouble>>(4);
1793  }
1794 
1795  if (d0factors[0].size() != nquad0)
1796  {
1797  d0factors[0] = Array<OneD, NekDouble>(nquad0);
1798  d0factors[2] = Array<OneD, NekDouble>(nquad0);
1799  d1factors[0] = Array<OneD, NekDouble>(nquad0);
1800  d1factors[2] = Array<OneD, NekDouble>(nquad0);
1801  }
1802 
1803  if (d0factors[1].size() != nquad1)
1804  {
1805  d0factors[1] = Array<OneD, NekDouble>(nquad1);
1806  d0factors[3] = Array<OneD, NekDouble>(nquad1);
1807  d1factors[1] = Array<OneD, NekDouble>(nquad1);
1808  d1factors[3] = Array<OneD, NekDouble>(nquad1);
1809  }
1810 
1811  // Outwards normals
1812  const Array<OneD, const Array<OneD, NekDouble>> &normal_0 =
1813  GetTraceNormal(0);
1814  const Array<OneD, const Array<OneD, NekDouble>> &normal_1 =
1815  GetTraceNormal(1);
1816  const Array<OneD, const Array<OneD, NekDouble>> &normal_2 =
1817  GetTraceNormal(2);
1818  const Array<OneD, const Array<OneD, NekDouble>> &normal_3 =
1819  GetTraceNormal(3);
1820 
1821  int ncoords = normal_0.size();
1822 
1823  if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
1824  {
1825  // needs checking for 3D coords
1826 
1827  // factors 0 and 2
1828  for (int i = 0; i < nquad0; ++i)
1829  {
1830  d0factors[0][i] = df[0][i] * normal_0[0][i];
1831  d0factors[2][i] = df[0][nquad0 * (nquad1 - 1) + i] * normal_2[0][i];
1832 
1833  d1factors[0][i] = df[1][i] * normal_0[0][i];
1834  d1factors[2][i] = df[1][nquad0 * (nquad1 - 1) + i] * normal_2[0][i];
1835  }
1836 
1837  for (int n = 1; n < ncoords; ++n)
1838  {
1839  // d xi_1/dy n_y
1840  // needs checking for 3D coords
1841  for (int i = 0; i < nquad0; ++i)
1842  {
1843  d0factors[0][i] += df[2 * n][i] * normal_0[n][i];
1844  d0factors[2][i] +=
1845  df[2 * n][nquad0 * (nquad1 - 1) + i] * normal_2[n][i];
1846 
1847  d1factors[0][i] += df[2 * n + 1][i] * normal_0[n][i];
1848  d1factors[2][i] +=
1849  df[2 * n + 1][nquad0 * (nquad1 - 1) + i] * normal_2[n][i];
1850  }
1851  }
1852 
1853  // faces 1 and 3
1854  for (int i = 0; i < nquad1; ++i)
1855  {
1856  d0factors[1][i] = df[0][(i + 1) * nquad0 - 1] * normal_1[0][i];
1857  d0factors[3][i] = df[0][i * nquad0] * normal_3[0][i];
1858 
1859  d1factors[1][i] = df[1][(i + 1) * nquad0 - 1] * normal_1[0][i];
1860  d1factors[3][i] = df[1][i * nquad0] * normal_3[0][i];
1861  }
1862 
1863  for (int n = 1; n < ncoords; ++n)
1864  {
1865  for (int i = 0; i < nquad1; ++i)
1866  {
1867  d0factors[1][i] +=
1868  df[2 * n][(i + 1) * nquad0 - 1] * normal_1[n][i];
1869  d0factors[3][i] += df[2 * n][i * nquad0] * normal_3[n][i];
1870 
1871  d1factors[1][i] +=
1872  df[2 * n + 1][(i + 1) * nquad0 - 1] * normal_1[n][i];
1873  d1factors[3][i] += df[2 * n + 1][i * nquad0] * normal_3[n][i];
1874  }
1875  }
1876  }
1877  else
1878  {
1879  // d xi_2/dx n_x
1880  for (int i = 0; i < nquad0; ++i)
1881  {
1882  d1factors[0][i] = df[1][0] * normal_0[0][i];
1883  d1factors[2][i] = df[1][0] * normal_2[0][i];
1884  }
1885 
1886  // d xi_1/dx n_x
1887  for (int i = 0; i < nquad1; ++i)
1888  {
1889  d0factors[1][i] = df[0][0] * normal_1[0][i];
1890  d0factors[3][i] = df[0][0] * normal_3[0][i];
1891  }
1892 
1893  for (int n = 1; n < ncoords; ++n)
1894  {
1895  // d xi_2/dy n_y
1896  // needs checking for 3D coords
1897  for (int i = 0; i < nquad0; ++i)
1898  {
1899  d1factors[0][i] += df[2 * n + 1][0] * normal_0[n][i];
1900  d1factors[2][i] += df[2 * n + 1][0] * normal_2[n][i];
1901  }
1902 
1903  // d xi_1/dy n_y
1904  // needs checking for 3D coords
1905  for (int i = 0; i < nquad1; ++i)
1906  {
1907  d0factors[1][i] += df[2 * n][0] * normal_1[n][i];
1908  d0factors[3][i] += df[2 * n][0] * normal_3[n][i];
1909  }
1910  }
1911 
1912  // d1factors
1913  // d xi_1/dx n_x
1914  for (int i = 0; i < nquad0; ++i)
1915  {
1916  d0factors[0][i] = df[0][0] * normal_0[0][i];
1917  d0factors[2][i] = df[0][0] * normal_2[0][i];
1918  }
1919 
1920  // d xi_2/dx n_x
1921  for (int i = 0; i < nquad1; ++i)
1922  {
1923  d1factors[1][i] = df[1][0] * normal_1[0][i];
1924  d1factors[3][i] = df[1][0] * normal_3[0][i];
1925  }
1926 
1927  for (int n = 1; n < ncoords; ++n)
1928  {
1929  // d xi_1/dy n_y
1930  // needs checking for 3D coords
1931  for (int i = 0; i < nquad0; ++i)
1932  {
1933  d0factors[0][i] += df[2 * n][0] * normal_0[n][i];
1934  d0factors[2][i] += df[2 * n][0] * normal_2[n][i];
1935  }
1936 
1937  // d xi_2/dy n_y
1938  // needs checking for 3D coords
1939  for (int i = 0; i < nquad1; ++i)
1940  {
1941  d1factors[1][i] += df[2 * n + 1][0] * normal_1[n][i];
1942  d1factors[3][i] += df[2 * n + 1][0] * normal_3[n][i];
1943  }
1944  }
1945  }
1946 }
1947 } // namespace LocalRegions
1948 } // 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 sign(a, b)
return the sign(b)*a
Definition: Polylib.cpp:15
Describes the specification for a Basis.
Definition: Basis.h:50
Defines a specification for a set of points.
Definition: Points.h:59
unsigned int GetNumPoints() const
Definition: Points.h:104
virtual DNekMatSharedPtr v_GenMatrix(const StdRegions::StdMatrixKey &mkey)
SpatialDomains::Geometry2DSharedPtr GetGeom2D() const
Definition: Expansion2D.h:180
std::map< int, NormalVector > m_traceNormals
Definition: Expansion.h:275
std::map< int, Array< OneD, NekDouble > > m_elmtBndNormDirElmtLen
the element length in each element boundary(Vertex, edge or face) normal direction calculated based o...
Definition: Expansion.h:285
SpatialDomains::GeometrySharedPtr GetGeom() const
Definition: Expansion.cpp:166
SpatialDomains::GeometrySharedPtr m_geom
Definition: Expansion.h:272
ExpansionSharedPtr GetLeftAdjacentElementExp() const
Definition: Expansion.h:433
int GetLeftAdjacentElementTrace() const
Definition: Expansion.h:446
SpatialDomains::GeomFactorsSharedPtr m_metricinfo
Definition: Expansion.h:273
virtual void v_GetCoords(Array< OneD, NekDouble > &coords_1, Array< OneD, NekDouble > &coords_2, Array< OneD, NekDouble > &coords_3)
Definition: Expansion.cpp:524
StdRegions::Orientation GetTraceOrient(int trace)
Definition: Expansion.h:167
DNekScalMatSharedPtr GetLocMatrix(const LocalRegions::MatrixKey &mkey)
Definition: Expansion.cpp:88
const NormalVector & GetTraceNormal(const int id)
Definition: Expansion.cpp:250
virtual NekDouble v_PhysEvaluate(const Array< OneD, const NekDouble > &coord, const Array< OneD, const NekDouble > &physvals)
This function evaluates the expansion at a single (arbitrary) point of the domain.
Definition: QuadExp.cpp:634
virtual DNekScalMatSharedPtr v_GetLocMatrix(const MatrixKey &mkey)
Definition: QuadExp.cpp:1521
virtual const SpatialDomains::GeomFactorsSharedPtr & v_GetMetricInfo() const
Definition: QuadExp.cpp:1375
virtual void v_FwdTransBndConstrained(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: QuadExp.cpp:258
virtual void v_AlignVectorToCollapsedDir(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray)
Definition: QuadExp.cpp:473
virtual void v_ComputeTraceNormal(const int edge)
Definition: QuadExp.cpp:1092
virtual void v_PhysDirectionalDeriv(const Array< OneD, const NekDouble > &inarray, const Array< OneD, const NekDouble > &direction, Array< OneD, NekDouble > &out)
Physical derivative along a direction vector.
Definition: QuadExp.cpp:189
virtual void v_IProductWRTDerivBase_MatOp(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: QuadExp.cpp:507
virtual void v_SVVLaplacianFilter(Array< OneD, NekDouble > &array, const StdRegions::StdMatrixKey &mkey)
Definition: QuadExp.cpp:1745
virtual DNekMatSharedPtr v_CreateStdMatrix(const StdRegions::StdMatrixKey &mkey)
Definition: QuadExp.cpp:1511
virtual void v_WeakDerivMatrixOp(const int i, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
Definition: QuadExp.cpp:1558
virtual void v_ReduceOrderCoeffs(int numMin, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: QuadExp.cpp:1611
virtual void v_MassMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
Definition: QuadExp.cpp:1536
virtual void v_LaplacianMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
Definition: QuadExp.cpp:1543
virtual void v_IProductWRTBase_MatOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: QuadExp.cpp:426
virtual void v_IProductWRTBase(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Calculate the inner product of inarray with respect to the basis B=base0*base1 and put into outarray.
Definition: QuadExp.cpp:378
virtual NekDouble v_StdPhysEvaluate(const Array< OneD, const NekDouble > &Lcoord, const Array< OneD, const NekDouble > &physvals)
Definition: QuadExp.cpp:626
virtual void v_HelmholtzMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
Definition: QuadExp.cpp:1580
virtual void v_IProductWRTDerivBase_SumFac(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: QuadExp.cpp:439
virtual DNekMatSharedPtr v_GenMatrix(const StdRegions::StdMatrixKey &mkey)
Definition: QuadExp.cpp:1491
virtual StdRegions::Orientation v_GetTraceOrient(int edge)
Definition: QuadExp.cpp:1475
virtual void v_GetTracePhysMap(const int edge, Array< OneD, int > &outarray)
Definition: QuadExp.cpp:836
virtual void v_NormalTraceDerivFactors(Array< OneD, Array< OneD, NekDouble >> &factors, Array< OneD, Array< OneD, NekDouble >> &d0factors, Array< OneD, Array< OneD, NekDouble >> &d1factors)
: This method gets all of the factors which are required as part of the Gradient Jump Penalty (GJP) s...
Definition: QuadExp.cpp:1777
virtual void v_GetEdgePhysVals(const int edge, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: QuadExp.cpp:648
virtual void v_GetCoord(const Array< OneD, const NekDouble > &Lcoords, Array< OneD, NekDouble > &coords)
Definition: QuadExp.cpp:605
LibUtilities::NekManager< MatrixKey, DNekScalMat, MatrixKey::opLess > m_matrixManager
Definition: QuadExp.h:249
virtual void v_ComputeLaplacianMetric()
Definition: QuadExp.cpp:1708
virtual DNekScalBlkMatSharedPtr v_GetLocStaticCondMatrix(const MatrixKey &mkey)
Definition: QuadExp.cpp:1526
virtual void v_GetCoords(Array< OneD, NekDouble > &coords_1, Array< OneD, NekDouble > &coords_2, Array< OneD, NekDouble > &coords_3)
Definition: QuadExp.cpp:598
LibUtilities::NekManager< MatrixKey, DNekScalBlkMat, MatrixKey::opLess > m_staticCondMatrixManager
Definition: QuadExp.h:251
virtual void v_NormVectorIProductWRTBase(const Array< OneD, const NekDouble > &Fx, const Array< OneD, const NekDouble > &Fy, const Array< OneD, const NekDouble > &Fz, Array< OneD, NekDouble > &outarray)
Definition: QuadExp.cpp:546
virtual void v_GetTracePhysVals(const int edge, const StdRegions::StdExpansionSharedPtr &EdgeExp, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, StdRegions::Orientation orient)
Definition: QuadExp.cpp:710
virtual void v_MassLevelCurvatureMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
Definition: QuadExp.cpp:1573
void v_DropLocStaticCondMatrix(const MatrixKey &mkey)
Definition: QuadExp.cpp:1531
virtual void v_GeneralMatrixOp_MatOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
Definition: QuadExp.cpp:1587
virtual void v_WeakDirectionalDerivMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
Definition: QuadExp.cpp:1566
virtual void v_GetTraceQFactors(const int edge, Array< OneD, NekDouble > &outarray)
Definition: QuadExp.cpp:878
virtual void v_LaplacianMatrixOp_MatFree_Kernel(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp)
Definition: QuadExp.cpp:1651
virtual const LibUtilities::BasisSharedPtr & v_GetBasis(int dir) const
Definition: QuadExp.cpp:1480
virtual StdRegions::StdExpansionSharedPtr v_GetStdExp(void) const
Definition: QuadExp.cpp:581
virtual void v_ExtractDataToCoeffs(const NekDouble *data, const std::vector< unsigned int > &nummodes, const int mode_offset, NekDouble *coeffs, std::vector< LibUtilities::BasisType > &fromType)
Definition: QuadExp.cpp:1385
virtual StdRegions::StdExpansionSharedPtr v_GetLinStdExp(void) const
Definition: QuadExp.cpp:587
virtual void v_FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Transform a given function from physical quadrature space to coefficient space.
Definition: QuadExp.cpp:235
virtual int v_GetNumPoints(const int dir) const
Definition: QuadExp.cpp:1486
virtual void v_IProductWRTBase_SumFac(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool multiplybyweights=true)
Definition: QuadExp.cpp:398
virtual void v_GetEdgeInterpVals(const int edge, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: QuadExp.cpp:772
virtual NekDouble v_Integral(const Array< OneD, const NekDouble > &inarray)
Integrates the specified function over the domain.
Definition: QuadExp.cpp:77
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=NullNekDouble1DArray)
Calculate the derivative of the physical points.
Definition: QuadExp.cpp:100
virtual void v_IProductWRTDerivBase(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: QuadExp.cpp:391
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 > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0=true, bool doCheckCollDir1=true)
int GetNcoeffs(void) const
This function returns the total number of coefficients used in the expansion.
Definition: StdExpansion.h:130
int GetTotPoints() const
This function returns the total number of quadrature points used in the element.
Definition: StdExpansion.h:140
LibUtilities::BasisType GetBasisType(const int dir) const
This function returns the type of basis used in the dir direction.
Definition: StdExpansion.h:163
void HelmholtzMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
const LibUtilities::PointsKeyVector GetPointsKeys() const
void MassMatrixOp(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
Definition: StdExpansion.h:760
void IProductWRTDerivBase_SumFac(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
void NormVectorIProductWRTBase(const Array< OneD, const NekDouble > &Fx, Array< OneD, NekDouble > &outarray)
Definition: StdExpansion.h:621
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...
Definition: StdExpansion.h:536
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)
Definition: StdExpansion.h:692
LibUtilities::ShapeType DetShapeType() const
This function returns the shape of the expansion domain.
Definition: StdExpansion.h:375
void GetInteriorMap(Array< OneD, unsigned int > &outarray)
Definition: StdExpansion.h:682
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
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
void IProductWRTBase_SumFac(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool multiplybyweights=true)
void MultiplyByQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: StdExpansion.h:731
Array< OneD, LibUtilities::BasisSharedPtr > m_base
MatrixType GetMatrixType() const
Definition: StdMatrixKey.h:85
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 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 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
std::shared_ptr< Basis > BasisSharedPtr
void Interp1D(const BasisKey &fbasis0, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, Array< OneD, NekDouble > &to)
this function interpolates a 1D function evaluated at the quadrature points of the basis fbasis0 to ...
Definition: Interp.cpp:52
void InterpCoeff2D(const BasisKey &fbasis0, const BasisKey &fbasis1, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, Array< OneD, NekDouble > &to)
Definition: InterpCoeff.cpp:71
void Interp2D(const BasisKey &fbasis0, const BasisKey &fbasis1, const Array< OneD, const NekDouble > &from, const BasisKey &tbasis0, const BasisKey &tbasis1, Array< OneD, NekDouble > &to)
this function interpolates a 2D function evaluated at the quadrature points of the 2D basis,...
Definition: Interp.cpp:106
std::vector< PointsKey > PointsKeyVector
Definition: Points.h:250
@ eGaussLobattoLegendre
1D Gauss-Lobatto-Legendre quadrature points
Definition: PointsType.h:53
@ eGaussGaussLegendre
1D Gauss-Gauss-Legendre quadrature points
Definition: PointsType.h:48
@ eGauss_Lagrange
Lagrange Polynomials using the Gauss points.
Definition: BasisType.h:59
@ eOrtho_A
Principle Orthogonal Functions .
Definition: BasisType.h:44
@ eGLL_Lagrange
Lagrange for SEM basis .
Definition: BasisType.h:58
@ eModified_A
Principle Modified Functions .
Definition: BasisType.h:50
std::shared_ptr< SegExp > SegExpSharedPtr
Definition: SegExp.h:255
std::shared_ptr< GeomFactors > GeomFactorsSharedPtr
Pointer to a GeomFactors object.
Definition: GeomFactors.h:62
GeomType
Indicates the type of element geometry.
@ eRegular
Geometry is straight-sided with constant geometric factors.
@ eMovingRegular
Currently unused.
@ eDeformed
Geometry is curved or has non-constant factors.
std::shared_ptr< Geometry2D > Geometry2DSharedPtr
Definition: Geometry.h:65
std::shared_ptr< StdQuadExp > StdQuadExpSharedPtr
Definition: StdQuadExp.h:234
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:282
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
Definition: NekTypeDefs.hpp:79
static Array< OneD, NekDouble > NullNekDouble1DArray
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:75
double NekDouble
void Vsqrt(int n, const T *x, const int incx, T *y, const int incy)
sqrt y = sqrt(x)
Definition: Vmath.cpp:534
void Svtsvtp(int n, const T alpha, const T *x, int incx, const T beta, const T *y, int incy, T *z, int incz)
vvtvvtp (scalar times vector plus scalar times vector):
Definition: Vmath.cpp:751
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 Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
svtvp (scalar times vector plus vector): z = alpha*x + y
Definition: Vmath.cpp:622
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition: Vmath.cpp:574
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 Sdiv(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha/y.
Definition: Vmath.cpp:324
void Vdiv(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:284
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:492
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:45
void Reverse(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1286
void Vvtvvtp(int n, const T *v, int incv, const T *w, int incw, const T *x, int incx, const T *y, int incy, T *z, int incz)
vvtvvtp (vector times vector plus vector times vector):
Definition: Vmath.cpp:692
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1255
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.cpp:419
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:291