Nektar++
PyrExp.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File PyrExp.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: PyrExp routines
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <LocalRegions/PyrExp.h>
37 
38 using namespace std;
39 
40 namespace Nektar
41 {
42  namespace LocalRegions
43  {
44 
45  PyrExp::PyrExp(const LibUtilities::BasisKey &Ba,
46  const LibUtilities::BasisKey &Bb,
47  const LibUtilities::BasisKey &Bc,
49  StdExpansion (LibUtilities::StdPyrData::getNumberOfCoefficients(
50  Ba.GetNumModes(),
51  Bb.GetNumModes(),
52  Bc.GetNumModes()),
53  3, Ba, Bb, Bc),
54  StdExpansion3D(LibUtilities::StdPyrData::getNumberOfCoefficients(
55  Ba.GetNumModes(),
56  Bb.GetNumModes(),
57  Bc.GetNumModes()),
58  Ba, Bb, Bc),
59  StdPyrExp (Ba,Bb,Bc),
60  Expansion (geom),
61  Expansion3D (geom),
62  m_matrixManager(
63  std::bind(&PyrExp::CreateMatrix, this, std::placeholders::_1),
64  std::string("PyrExpMatrix")),
65  m_staticCondMatrixManager(
66  std::bind(&PyrExp::CreateStaticCondMatrix, this, std::placeholders::_1),
67  std::string("PyrExpStaticCondMatrix"))
68  {
69  }
70 
72  StdExpansion (T),
73  StdExpansion3D(T),
74  StdPyrExp (T),
75  Expansion (T),
76  Expansion3D (T),
79  {
80  }
81 
83  {
84  }
85 
86 
87  //----------------------------
88  // Integration Methods
89  //----------------------------
90 
91  /**
92  * \brief Integrate the physical point list \a inarray over pyramidic
93  * region and return the value.
94  *
95  * Inputs:\n
96  *
97  * - \a inarray: definition of function to be returned at quadrature
98  * point of expansion.
99  *
100  * Outputs:\n
101  *
102  * - returns \f$\int^1_{-1}\int^1_{-1}\int^1_{-1} u(\bar \eta_1,
103  * \eta_2, \eta_3) J[i,j,k] d \bar \eta_1 d \eta_2 d \eta_3\f$ \n \f$=
104  * \sum_{i=0}^{Q_1 - 1} \sum_{j=0}^{Q_2 - 1} \sum_{k=0}^{Q_3 - 1}
105  * u(\bar \eta_{1i}^{0,0}, \eta_{2j}^{0,0},\eta_{3k}^{2,0})w_{i}^{0,0}
106  * w_{j}^{0,0} \hat w_{k}^{2,0} \f$ \n where \f$inarray[i,j, k] =
107  * u(\bar \eta_{1i},\eta_{2j}, \eta_{3k}) \f$, \n \f$\hat w_{k}^{2,0}
108  * = \frac {w^{2,0}} {2} \f$ \n and \f$ J[i,j,k] \f$ is the Jacobian
109  * evaluated at the quadrature point.
110  */
112  {
113  int nquad0 = m_base[0]->GetNumPoints();
114  int nquad1 = m_base[1]->GetNumPoints();
115  int nquad2 = m_base[2]->GetNumPoints();
117  Array<OneD, NekDouble> tmp(nquad0*nquad1*nquad2);
118 
119  // multiply inarray with Jacobian
120  if(m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
121  {
122  Vmath::Vmul(nquad0*nquad1*nquad2,&jac[0],1,(NekDouble*)&inarray[0],1, &tmp[0],1);
123  }
124  else
125  {
126  Vmath::Smul(nquad0*nquad1*nquad2,(NekDouble) jac[0], (NekDouble*)&inarray[0],1,&tmp[0],1);
127  }
128 
129  // call StdPyrExp version;
130  return StdPyrExp::v_Integral(tmp);
131  }
132 
133 
134  //----------------------------
135  // Differentiation Methods
136  //----------------------------
137 
139  Array<OneD, NekDouble>& out_d0,
140  Array<OneD, NekDouble>& out_d1,
141  Array<OneD, NekDouble>& out_d2)
142  {
143  int nquad0 = m_base[0]->GetNumPoints();
144  int nquad1 = m_base[1]->GetNumPoints();
145  int nquad2 = m_base[2]->GetNumPoints();
147  m_metricinfo->GetDerivFactors(GetPointsKeys());
148  Array<OneD,NekDouble> diff0(nquad0*nquad1*nquad2);
149  Array<OneD,NekDouble> diff1(nquad0*nquad1*nquad2);
150  Array<OneD,NekDouble> diff2(nquad0*nquad1*nquad2);
151 
152  StdPyrExp::v_PhysDeriv(inarray, diff0, diff1, diff2);
153 
154  if(m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
155  {
156  if(out_d0.num_elements())
157  {
158  Vmath::Vmul (nquad0*nquad1*nquad2,&gmat[0][0],1,&diff0[0],1, &out_d0[0], 1);
159  Vmath::Vvtvp (nquad0*nquad1*nquad2,&gmat[1][0],1,&diff1[0],1, &out_d0[0], 1,&out_d0[0],1);
160  Vmath::Vvtvp (nquad0*nquad1*nquad2,&gmat[2][0],1,&diff2[0],1, &out_d0[0], 1,&out_d0[0],1);
161  }
162 
163  if(out_d1.num_elements())
164  {
165  Vmath::Vmul (nquad0*nquad1*nquad2,&gmat[3][0],1,&diff0[0],1, &out_d1[0], 1);
166  Vmath::Vvtvp (nquad0*nquad1*nquad2,&gmat[4][0],1,&diff1[0],1, &out_d1[0], 1,&out_d1[0],1);
167  Vmath::Vvtvp (nquad0*nquad1*nquad2,&gmat[5][0],1,&diff2[0],1, &out_d1[0], 1,&out_d1[0],1);
168  }
169 
170  if(out_d2.num_elements())
171  {
172  Vmath::Vmul (nquad0*nquad1*nquad2,&gmat[6][0],1,&diff0[0],1, &out_d2[0], 1);
173  Vmath::Vvtvp (nquad0*nquad1*nquad2,&gmat[7][0],1,&diff1[0],1, &out_d2[0], 1, &out_d2[0],1);
174  Vmath::Vvtvp (nquad0*nquad1*nquad2,&gmat[8][0],1,&diff2[0],1, &out_d2[0], 1, &out_d2[0],1);
175  }
176  }
177  else // regular geometry
178  {
179  if(out_d0.num_elements())
180  {
181  Vmath::Smul (nquad0*nquad1*nquad2,gmat[0][0],&diff0[0],1, &out_d0[0], 1);
182  Blas::Daxpy (nquad0*nquad1*nquad2,gmat[1][0],&diff1[0],1, &out_d0[0], 1);
183  Blas::Daxpy (nquad0*nquad1*nquad2,gmat[2][0],&diff2[0],1, &out_d0[0], 1);
184  }
185 
186  if(out_d1.num_elements())
187  {
188  Vmath::Smul (nquad0*nquad1*nquad2,gmat[3][0],&diff0[0],1, &out_d1[0], 1);
189  Blas::Daxpy (nquad0*nquad1*nquad2,gmat[4][0],&diff1[0],1, &out_d1[0], 1);
190  Blas::Daxpy (nquad0*nquad1*nquad2,gmat[5][0],&diff2[0],1, &out_d1[0], 1);
191  }
192 
193  if(out_d2.num_elements())
194  {
195  Vmath::Smul (nquad0*nquad1*nquad2,gmat[6][0],&diff0[0],1, &out_d2[0], 1);
196  Blas::Daxpy (nquad0*nquad1*nquad2,gmat[7][0],&diff1[0],1, &out_d2[0], 1);
197  Blas::Daxpy (nquad0*nquad1*nquad2,gmat[8][0],&diff2[0],1, &out_d2[0], 1);
198  }
199  }
200  }
201 
202 
203  //---------------------------------------
204  // Transforms
205  //---------------------------------------
206 
207  /**
208  * \brief Forward transform from physical quadrature space stored in
209  * \a inarray and evaluate the expansion coefficients and store in \a
210  * (this)->m_coeffs
211  *
212  * Inputs:\n
213  *
214  * - \a inarray: array of physical quadrature points to be transformed
215  *
216  * Outputs:\n
217  *
218  * - (this)->_coeffs: updated array of expansion coefficients.
219  */
221  Array<OneD, NekDouble>& outarray)
222  {
223  if(m_base[0]->Collocation() &&
224  m_base[1]->Collocation() &&
225  m_base[2]->Collocation())
226  {
227  Vmath::Vcopy(GetNcoeffs(),&inarray[0],1,&outarray[0],1);
228  }
229  else
230  {
231  v_IProductWRTBase(inarray,outarray);
232 
233  // get Mass matrix inverse
235  DetShapeType(),*this);
236  DNekScalMatSharedPtr matsys = m_matrixManager[masskey];
237 
238  // copy inarray in case inarray == outarray
239  DNekVec in (m_ncoeffs,outarray);
240  DNekVec out(m_ncoeffs,outarray,eWrapper);
241 
242  out = (*matsys)*in;
243  }
244  }
245 
246 
247  //---------------------------------------
248  // Inner product functions
249  //---------------------------------------
250 
251  /**
252  * \brief Calculate the inner product of inarray with respect to the
253  * basis B=base0*base1*base2 and put into outarray:
254  *
255  * \f$ \begin{array}{rcl} I_{pqr} = (\phi_{pqr}, u)_{\delta} & = &
256  * \sum_{i=0}^{nq_0} \sum_{j=0}^{nq_1} \sum_{k=0}^{nq_2} \psi_{p}^{a}
257  * (\bar \eta_{1i}) \psi_{q}^{a} (\eta_{2j}) \psi_{pqr}^{c}
258  * (\eta_{3k}) w_i w_j w_k u(\bar \eta_{1,i} \eta_{2,j} \eta_{3,k})
259  * J_{i,j,k}\\ & = & \sum_{i=0}^{nq_0} \psi_p^a(\bar \eta_{1,i})
260  * \sum_{j=0}^{nq_1} \psi_{q}^a(\eta_{2,j}) \sum_{k=0}^{nq_2}
261  * \psi_{pqr}^c u(\bar \eta_{1i},\eta_{2j},\eta_{3k}) J_{i,j,k}
262  * \end{array} \f$ \n
263  *
264  * where
265  *
266  * \f$\phi_{pqr} (\xi_1 , \xi_2 , \xi_3) = \psi_p^a (\bar \eta_1)
267  * \psi_{q}^a (\eta_2) \psi_{pqr}^c (\eta_3) \f$ \n
268  *
269  * which can be implemented as \n \f$f_{pqr} (\xi_{3k}) =
270  * \sum_{k=0}^{nq_3} \psi_{pqr}^c u(\bar
271  * \eta_{1i},\eta_{2j},\eta_{3k}) J_{i,j,k} = {\bf B_3 U} \f$ \n \f$
272  * g_{pq} (\xi_{3k}) = \sum_{j=0}^{nq_1} \psi_{q}^a (\xi_{2j}) f_{pqr}
273  * (\xi_{3k}) = {\bf B_2 F} \f$ \n \f$ (\phi_{pqr}, u)_{\delta} =
274  * \sum_{k=0}^{nq_0} \psi_{p}^a (\xi_{3k}) g_{pq} (\xi_{3k}) = {\bf
275  * B_1 G} \f$
276  */
277 
279  const Array<OneD, const NekDouble>& inarray,
280  Array<OneD, NekDouble>& outarray)
281  {
282  v_IProductWRTBase_SumFac(inarray, outarray);
283  }
284 
286  const Array<OneD, const NekDouble>& inarray,
287  Array<OneD, NekDouble>& outarray,
288  bool multiplybyweights)
289  {
290  const int nquad0 = m_base[0]->GetNumPoints();
291  const int nquad1 = m_base[1]->GetNumPoints();
292  const int nquad2 = m_base[2]->GetNumPoints();
293  const int order0 = m_base[0]->GetNumModes();
294  const int order1 = m_base[1]->GetNumModes();
295 
296  Array<OneD, NekDouble> wsp(order0*nquad2*(nquad1+order1));
297 
298  if(multiplybyweights)
299  {
300  Array<OneD, NekDouble> tmp(nquad0*nquad1*nquad2);
301 
302  MultiplyByQuadratureMetric(inarray, tmp);
303 
304  IProductWRTBase_SumFacKernel(m_base[0]->GetBdata(),
305  m_base[1]->GetBdata(),
306  m_base[2]->GetBdata(),
307  tmp,outarray,wsp,
308  true,true,true);
309  }
310  else
311  {
312  IProductWRTBase_SumFacKernel(m_base[0]->GetBdata(),
313  m_base[1]->GetBdata(),
314  m_base[2]->GetBdata(),
315  inarray,outarray,wsp,
316  true,true,true);
317  }
318  }
319 
320 
321  /**
322  * @brief Calculates the inner product \f$ I_{pqr} = (u,
323  * \partial_{x_i} \phi_{pqr}) \f$.
324  *
325  * The derivative of the basis functions is performed using the chain
326  * rule in order to incorporate the geometric factors. Assuming that
327  * the basis functions are a tensor product
328  * \f$\phi_{pqr}(\eta_1,\eta_2,\eta_3) =
329  * \phi_1(\eta_1)\phi_2(\eta_2)\phi_3(\eta_3)\f$, this yields the
330  * result
331  *
332  * \f[
333  * I_{pqr} = \sum_{j=1}^3 \left(u, \frac{\partial u}{\partial \eta_j}
334  * \frac{\partial \eta_j}{\partial x_i}\right)
335  * \f]
336  *
337  * In the pyramid element, we must also incorporate a second set
338  * of geometric factors which incorporate the collapsed co-ordinate
339  * system, so that
340  *
341  * \f[ \frac{\partial\eta_j}{\partial x_i} = \sum_{k=1}^3
342  * \frac{\partial\eta_j}{\partial\xi_k}\frac{\partial\xi_k}{\partial
343  * x_i} \f]
344  *
345  * These derivatives can be found on p152 of Sherwin & Karniadakis.
346  *
347  * @param dir Direction in which to take the derivative.
348  * @param inarray The function \f$ u \f$.
349  * @param outarray Value of the inner product.
350  */
352  const int dir,
353  const Array<OneD, const NekDouble> &inarray,
354  Array<OneD, NekDouble> &outarray)
355  {
356  v_IProductWRTDerivBase_SumFac(dir, inarray, outarray);
357  }
358 
360  const int dir,
361  const Array<OneD, const NekDouble> &inarray,
362  Array<OneD, NekDouble> &outarray)
363  {
364  const int nquad0 = m_base[0]->GetNumPoints();
365  const int nquad1 = m_base[1]->GetNumPoints();
366  const int nquad2 = m_base[2]->GetNumPoints();
367  const int order0 = m_base[0]->GetNumModes ();
368  const int order1 = m_base[1]->GetNumModes ();
369  const int nqtot = nquad0*nquad1*nquad2;
370  int i;
371 
372  const Array<OneD, const NekDouble> &z0 = m_base[0]->GetZ();
373  const Array<OneD, const NekDouble> &z1 = m_base[1]->GetZ();
374  const Array<OneD, const NekDouble> &z2 = m_base[2]->GetZ();
375 
376  Array<OneD, NekDouble> gfac0(nquad0 );
377  Array<OneD, NekDouble> gfac1(nquad1 );
378  Array<OneD, NekDouble> gfac2(nquad2 );
379  Array<OneD, NekDouble> tmp1 (nqtot );
380  Array<OneD, NekDouble> tmp2 (nqtot );
381  Array<OneD, NekDouble> tmp3 (nqtot );
382  Array<OneD, NekDouble> tmp4 (nqtot );
383  Array<OneD, NekDouble> tmp5 (nqtot );
385  Array<OneD, NekDouble> wsp (std::max(nqtot,order0*nquad2*(nquad1+order1)));
386 
387  const Array<TwoD, const NekDouble>& df =
388  m_metricinfo->GetDerivFactors(GetPointsKeys());
389 
390  MultiplyByQuadratureMetric(inarray, tmp1);
391 
392  if(m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
393  {
394  Vmath::Vmul(nqtot,&df[3*dir][0], 1,tmp1.get(),1,tmp2.get(),1);
395  Vmath::Vmul(nqtot,&df[3*dir+1][0],1,tmp1.get(),1,tmp3.get(),1);
396  Vmath::Vmul(nqtot,&df[3*dir+2][0],1,tmp1.get(),1,tmp4.get(),1);
397  }
398  else
399  {
400  Vmath::Smul(nqtot, df[3*dir][0], tmp1.get(),1,tmp2.get(), 1);
401  Vmath::Smul(nqtot, df[3*dir+1][0],tmp1.get(),1,tmp3.get(), 1);
402  Vmath::Smul(nqtot, df[3*dir+2][0],tmp1.get(),1,tmp4.get(), 1);
403  }
404 
405  // set up geometric factor: (1+z0)/2
406  for (i = 0; i < nquad0; ++i)
407  {
408  gfac0[i] = 0.5*(1+z0[i]);
409  }
410 
411  // set up geometric factor: (1+z1)/2
412  for(i = 0; i < nquad1; ++i)
413  {
414  gfac1[i] = 0.5*(1+z1[i]);
415  }
416 
417  // Set up geometric factor: 2/(1-z2)
418  for (i = 0; i < nquad2; ++i)
419  {
420  gfac2[i] = 2.0/(1-z2[i]);
421  }
422 
423  const int nq01 = nquad0*nquad1;
424 
425  for (i = 0; i < nquad2; ++i)
426  {
427  Vmath::Smul(nq01,gfac2[i],&tmp2[0]+i*nq01,1,&tmp2[0]+i*nq01,1); // 2/(1-z2) for d/dxi_0
428  Vmath::Smul(nq01,gfac2[i],&tmp3[0]+i*nq01,1,&tmp3[0]+i*nq01,1); // 2/(1-z2) for d/dxi_1
429  Vmath::Smul(nq01,gfac2[i],&tmp4[0]+i*nq01,1,&tmp5[0]+i*nq01,1); // 2/(1-z2) for d/dxi_2
430  }
431 
432  // (1+z0)/(1-z2) for d/d eta_0
433  for(i = 0; i < nquad1*nquad2; ++i)
434  {
435  Vmath::Vmul(nquad0,&gfac0[0],1,
436  &tmp5[0]+i*nquad0,1,
437  &wsp[0]+i*nquad0,1);
438  }
439 
440  Vmath::Vadd(nqtot, &tmp2[0], 1, &wsp[0], 1, &tmp2[0], 1);
441 
442  // (1+z1)/(1-z2) for d/d eta_1
443  for(i = 0; i < nquad1*nquad2; ++i)
444  {
445  Vmath::Smul(nquad0,gfac1[i%nquad1],
446  &tmp5[0]+i*nquad0,1,
447  &tmp5[0]+i*nquad0,1);
448  }
449  Vmath::Vadd(nqtot, &tmp3[0], 1, &tmp5[0], 1, &tmp3[0], 1);
450 
451 
452  IProductWRTBase_SumFacKernel(m_base[0]->GetDbdata(),
453  m_base[1]->GetBdata (),
454  m_base[2]->GetBdata (),
455  tmp2,outarray,wsp,
456  false,true,true);
457 
458  IProductWRTBase_SumFacKernel(m_base[0]->GetBdata (),
459  m_base[1]->GetDbdata(),
460  m_base[2]->GetBdata (),
461  tmp3,tmp6,wsp,
462  true,false,true);
463 
464  Vmath::Vadd(m_ncoeffs, tmp6, 1, outarray, 1, outarray, 1);
465 
466  IProductWRTBase_SumFacKernel(m_base[0]->GetBdata (),
467  m_base[1]->GetBdata (),
468  m_base[2]->GetDbdata(),
469  tmp4,tmp6,wsp,
470  true,true,false);
471 
472  Vmath::Vadd(m_ncoeffs, tmp6, 1, outarray, 1, outarray, 1);
473  }
474 
475 
476  //---------------------------------------
477  // Evaluation functions
478  //---------------------------------------
479 
481  {
483  ::AllocateSharedPtr(m_base[0]->GetBasisKey(),
484  m_base[1]->GetBasisKey(),
485  m_base[2]->GetBasisKey());
486  }
487 
489  {
491  2, m_base[0]->GetPointsKey());
493  2, m_base[1]->GetPointsKey());
495  2, m_base[2]->GetPointsKey());
496 
498  ::AllocateSharedPtr( bkey0, bkey1, bkey2);
499  }
500 
501  /*
502  * @brief Get the coordinates #coords at the local coordinates
503  * #Lcoords
504  */
506  Array<OneD, NekDouble>& coords)
507  {
508  int i;
509 
510  ASSERTL1(Lcoords[0] <= -1.0 && Lcoords[0] >= 1.0 &&
511  Lcoords[1] <= -1.0 && Lcoords[1] >= 1.0 &&
512  Lcoords[2] <= -1.0 && Lcoords[2] >= 1.0,
513  "Local coordinates are not in region [-1,1]");
514 
515  // m_geom->FillGeom(); // TODO: implement FillGeom()
516 
517  for(i = 0; i < m_geom->GetCoordim(); ++i)
518  {
519  coords[i] = m_geom->GetCoord(i,Lcoords);
520  }
521  }
522 
524  Array<OneD, NekDouble> &coords_1,
525  Array<OneD, NekDouble> &coords_2,
526  Array<OneD, NekDouble> &coords_3)
527  {
528  Expansion::v_GetCoords(coords_1, coords_2, coords_3);
529  }
530 
531 
533  const NekDouble *data,
534  const std::vector<unsigned int > &nummodes,
535  const int mode_offset,
536  NekDouble * coeffs,
537  std::vector<LibUtilities::BasisType> &fromType)
538  {
539  int data_order0 = nummodes[mode_offset];
540  int fillorder0 = min(m_base[0]->GetNumModes(),data_order0);
541  int data_order1 = nummodes[mode_offset+1];
542  int order1 = m_base[1]->GetNumModes();
543  int fillorder1 = min(order1,data_order1);
544  int data_order2 = nummodes[mode_offset+2];
545  int order2 = m_base[2]->GetNumModes();
546  int fillorder2 = min(order2,data_order2);
547 
548  // Check if not same order or basis and if not make temp
549  // element to read in data
550  if (fromType[0] != m_base[0]->GetBasisType() ||
551  fromType[1] != m_base[1]->GetBasisType() ||
552  fromType[2] != m_base[2]->GetBasisType() ||
553  data_order0 != fillorder0 ||
554  data_order1 != fillorder1 ||
555  data_order2 != fillorder2)
556  {
557  // Construct a pyr with the appropriate basis type at our
558  // quadrature points, and one more to do a forwards
559  // transform. We can then copy the output to coeffs.
560  StdRegions::StdPyrExp tmpPyr(
562  fromType[0], data_order0, m_base[0]->GetPointsKey()),
564  fromType[1], data_order1, m_base[1]->GetPointsKey()),
566  fromType[2], data_order2, m_base[2]->GetPointsKey()));
567 
568  StdRegions::StdPyrExp tmpPyr2(m_base[0]->GetBasisKey(),
569  m_base[1]->GetBasisKey(),
570  m_base[2]->GetBasisKey());
571 
572  Array<OneD, const NekDouble> tmpData(tmpPyr.GetNcoeffs(), data);
573  Array<OneD, NekDouble> tmpBwd(tmpPyr2.GetTotPoints());
574  Array<OneD, NekDouble> tmpOut(tmpPyr2.GetNcoeffs());
575 
576  tmpPyr.BwdTrans(tmpData, tmpBwd);
577  tmpPyr2.FwdTrans(tmpBwd, tmpOut);
578  Vmath::Vcopy(tmpOut.num_elements(), &tmpOut[0], 1, coeffs, 1);
579 
580  }
581  else
582  {
583  Vmath::Vcopy(m_ncoeffs,&data[0],1,coeffs,1);
584  }
585  }
586 
587  /**
588  * Given the local cartesian coordinate \a Lcoord evaluate the
589  * value of physvals at this point by calling through to the
590  * StdExpansion method
591  */
593  const Array<OneD, const NekDouble> &Lcoord,
594  const Array<OneD, const NekDouble> &physvals)
595  {
596  // Evaluate point in local coordinates.
597  return StdPyrExp::v_PhysEvaluate(Lcoord,physvals);
598  }
599 
601  const Array<OneD, const NekDouble>& physvals)
602  {
603  Array<OneD,NekDouble> Lcoord(3);
604 
605  ASSERTL0(m_geom,"m_geom not defined");
606 
607  //TODO: check GetLocCoords()
608  m_geom->GetLocCoords(coord, Lcoord);
609 
610  return StdPyrExp::v_PhysEvaluate(Lcoord, physvals);
611  }
612 
613 
614  //---------------------------------------
615  // Helper functions
616  //---------------------------------------
617 
619  {
620  return m_geom->GetCoordim();
621  }
622 
623  void PyrExp::v_GetFacePhysMap(const int face,
624  Array<OneD, int> &outarray)
625  {
626  int nquad0 = m_base[0]->GetNumPoints();
627  int nquad1 = m_base[1]->GetNumPoints();
628  int nquad2 = m_base[2]->GetNumPoints();
629 
630  int nq0 = 0;
631  int nq1 = 0;
632 
633  switch(face)
634  {
635  case 0:
636  nq0 = nquad0;
637  nq1 = nquad1;
638  if(outarray.num_elements()!=nq0*nq1)
639  {
640  outarray = Array<OneD, int>(nq0*nq1);
641  }
642 
643  //Directions A and B positive
644  for(int i = 0; i < nquad0*nquad1; ++i)
645  {
646  outarray[i] = i;
647  }
648 
649  break;
650  case 1:
651  nq0 = nquad0;
652  nq1 = nquad2;
653  if(outarray.num_elements()!=nq0*nq1)
654  {
655  outarray = Array<OneD, int>(nq0*nq1);
656  }
657 
658  //Direction A and B positive
659  for (int k=0; k<nquad2; k++)
660  {
661  for(int i = 0; i < nquad0; ++i)
662  {
663  outarray[k*nquad0+i] = (nquad0*nquad1*k)+i;
664  }
665  }
666 
667  break;
668  case 2:
669  nq0 = nquad1;
670  nq1 = nquad2;
671  if(outarray.num_elements()!=nq0*nq1)
672  {
673  outarray = Array<OneD, int>(nq0*nq1);
674  }
675 
676  //Directions A and B positive
677  for(int j = 0; j < nquad1*nquad2; ++j)
678  {
679  outarray[j] = nquad0-1 + j*nquad0;
680 
681  }
682  break;
683  case 3:
684 
685  nq0 = nquad0;
686  nq1 = nquad2;
687  if(outarray.num_elements()!=nq0*nq1)
688  {
689  outarray = Array<OneD, int>(nq0*nq1);
690  }
691 
692  //Direction A and B positive
693  for (int k=0; k<nquad2; k++)
694  {
695  for(int i = 0; i < nquad0; ++i)
696  {
697  outarray[k*nquad0+i] = nquad0*(nquad1-1) + (nquad0*nquad1*k)+i;
698  }
699  }
700  break;
701  case 4:
702  nq0 = nquad1;
703  nq1 = nquad2;
704 
705  if(outarray.num_elements()!=nq0*nq1)
706  {
707  outarray = Array<OneD, int>(nq0*nq1);
708  }
709 
710  //Directions A and B positive
711  for(int j = 0; j < nquad1*nquad2; ++j)
712  {
713  outarray[j] = j*nquad0;
714 
715  }
716  break;
717  default:
718  ASSERTL0(false,"face value (> 4) is out of range");
719  break;
720  }
721  }
722 
723  void PyrExp::v_ComputeFaceNormal(const int face)
724  {
725  const SpatialDomains::GeomFactorsSharedPtr &geomFactors =
726  GetGeom()->GetMetricInfo();
727 
729  for(int i = 0; i < ptsKeys.size(); ++i)
730  {
731  // Need at least 2 points for computing normals
732  if (ptsKeys[i].GetNumPoints() == 1)
733  {
734  LibUtilities::PointsKey pKey(2, ptsKeys[i].GetPointsType());
735  ptsKeys[i] = pKey;
736  }
737  }
738 
739  SpatialDomains::GeomType type = geomFactors->GetGtype();
740  const Array<TwoD, const NekDouble> &df = geomFactors->GetDerivFactors(ptsKeys);
741  const Array<OneD, const NekDouble> &jac = geomFactors->GetJac(ptsKeys);
742 
743  LibUtilities::BasisKey tobasis0 = DetFaceBasisKey(face,0);
744  LibUtilities::BasisKey tobasis1 = DetFaceBasisKey(face,1);
745 
746  // Number of quadrature points in face expansion.
747  int nq_face = tobasis0.GetNumPoints()*tobasis1.GetNumPoints();
748 
749  int vCoordDim = GetCoordim();
750  int i;
751 
754  for (i = 0; i < vCoordDim; ++i)
755  {
756  normal[i] = Array<OneD, NekDouble>(nq_face);
757  }
758 
759  // Regular geometry case
760  if (type == SpatialDomains::eRegular ||
762  {
763  NekDouble fac;
764  // Set up normals
765  switch(face)
766  {
767  case 0:
768  {
769  for(i = 0; i < vCoordDim; ++i)
770  {
771  normal[i][0] = -df[3*i+2][0];
772  }
773  break;
774  }
775  case 1:
776  {
777  for(i = 0; i < vCoordDim; ++i)
778  {
779  normal[i][0] = -df[3*i+1][0];
780  }
781  break;
782  }
783  case 2:
784  {
785  for(i = 0; i < vCoordDim; ++i)
786  {
787  normal[i][0] = df[3*i][0]+df[3*i+2][0];
788  }
789  break;
790  }
791  case 3:
792  {
793  for(i = 0; i < vCoordDim; ++i)
794  {
795  normal[i][0] = df[3*i+1][0]+df[3*i+2][0];
796  }
797  break;
798  }
799  case 4:
800  {
801  for(i = 0; i < vCoordDim; ++i)
802  {
803  normal[i][0] = -df[3*i][0];
804  }
805  break;
806  }
807  default:
808  ASSERTL0(false,"face is out of range (face < 4)");
809  }
810 
811  // Normalise resulting vector.
812  fac = 0.0;
813  for(i = 0; i < vCoordDim; ++i)
814  {
815  fac += normal[i][0]*normal[i][0];
816  }
817  fac = 1.0/sqrt(fac);
818  for (i = 0; i < vCoordDim; ++i)
819  {
820  Vmath::Fill(nq_face,fac*normal[i][0],normal[i],1);
821  }
822  }
823  else
824  {
825  // Set up deformed normals.
826  int j, k;
827 
828  int nq0 = ptsKeys[0].GetNumPoints();
829  int nq1 = ptsKeys[1].GetNumPoints();
830  int nq2 = ptsKeys[2].GetNumPoints();
831  int nq01 = nq0*nq1;
832  int nqtot;
833 
834  // Determine number of quadrature points on the face.
835  if (face == 0)
836  {
837  nqtot = nq0*nq1;
838  }
839  else if (face == 1 || face == 3)
840  {
841  nqtot = nq0*nq2;
842  }
843  else
844  {
845  nqtot = nq1*nq2;
846  }
847 
848  LibUtilities::PointsKey points0;
849  LibUtilities::PointsKey points1;
850 
851  Array<OneD, NekDouble> faceJac(nqtot);
852  Array<OneD, NekDouble> normals(vCoordDim*nqtot,0.0);
853 
854  // Extract Jacobian along face and recover local derivatives
855  // (dx/dr) for polynomial interpolation by multiplying m_gmat by
856  // jacobian
857  switch(face)
858  {
859  case 0:
860  {
861  for(j = 0; j < nq01; ++j)
862  {
863  normals[j] = -df[2][j]*jac[j];
864  normals[nqtot+j] = -df[5][j]*jac[j];
865  normals[2*nqtot+j] = -df[8][j]*jac[j];
866  faceJac[j] = jac[j];
867  }
868 
869  points0 = ptsKeys[0];
870  points1 = ptsKeys[1];
871  break;
872  }
873 
874  case 1:
875  {
876  for (j = 0; j < nq0; ++j)
877  {
878  for(k = 0; k < nq2; ++k)
879  {
880  int tmp = j+nq01*k;
881  normals[j+k*nq0] =
882  -df[1][tmp]*jac[tmp];
883  normals[nqtot+j+k*nq0] =
884  -df[4][tmp]*jac[tmp];
885  normals[2*nqtot+j+k*nq0] =
886  -df[7][tmp]*jac[tmp];
887  faceJac[j+k*nq0] = jac[tmp];
888  }
889  }
890 
891  points0 = ptsKeys[0];
892  points1 = ptsKeys[2];
893  break;
894  }
895 
896  case 2:
897  {
898  for (j = 0; j < nq1; ++j)
899  {
900  for(k = 0; k < nq2; ++k)
901  {
902  int tmp = nq0-1+nq0*j+nq01*k;
903  normals[j+k*nq1] =
904  (df[0][tmp]+df[2][tmp])*jac[tmp];
905  normals[nqtot+j+k*nq1] =
906  (df[3][tmp]+df[5][tmp])*jac[tmp];
907  normals[2*nqtot+j+k*nq1] =
908  (df[6][tmp]+df[8][tmp])*jac[tmp];
909  faceJac[j+k*nq1] = jac[tmp];
910  }
911  }
912 
913  points0 = ptsKeys[1];
914  points1 = ptsKeys[2];
915  break;
916  }
917 
918  case 3:
919  {
920  for (j = 0; j < nq0; ++j)
921  {
922  for(k = 0; k < nq2; ++k)
923  {
924  int tmp = nq0*(nq1-1) + j + nq01*k;
925  normals[j+k*nq0] =
926  (df[1][tmp]+df[2][tmp])*jac[tmp];
927  normals[nqtot+j+k*nq0] =
928  (df[4][tmp]+df[5][tmp])*jac[tmp];
929  normals[2*nqtot+j+k*nq0] =
930  (df[7][tmp]+df[8][tmp])*jac[tmp];
931  faceJac[j+k*nq0] = jac[tmp];
932  }
933  }
934 
935  points0 = ptsKeys[0];
936  points1 = ptsKeys[2];
937  break;
938  }
939 
940  case 4:
941  {
942  for (j = 0; j < nq1; ++j)
943  {
944  for(k = 0; k < nq2; ++k)
945  {
946  int tmp = j*nq0+nq01*k;
947  normals[j+k*nq1] =
948  -df[0][tmp]*jac[tmp];
949  normals[nqtot+j+k*nq1] =
950  -df[3][tmp]*jac[tmp];
951  normals[2*nqtot+j+k*nq1] =
952  -df[6][tmp]*jac[tmp];
953  faceJac[j+k*nq1] = jac[tmp];
954  }
955  }
956 
957  points0 = ptsKeys[1];
958  points1 = ptsKeys[2];
959  break;
960  }
961 
962  default:
963  ASSERTL0(false,"face is out of range (face < 4)");
964  }
965 
966  Array<OneD, NekDouble> work (nq_face, 0.0);
967  // Interpolate Jacobian and invert
968  LibUtilities::Interp2D(points0, points1, faceJac,
969  tobasis0.GetPointsKey(),
970  tobasis1.GetPointsKey(),
971  work);
972  Vmath::Sdiv(nq_face, 1.0, &work[0], 1, &work[0], 1);
973 
974  // Interpolate normal and multiply by inverse Jacobian.
975  for(i = 0; i < vCoordDim; ++i)
976  {
977  LibUtilities::Interp2D(points0, points1,
978  &normals[i*nqtot],
979  tobasis0.GetPointsKey(),
980  tobasis1.GetPointsKey(),
981  &normal[i][0]);
982  Vmath::Vmul(nq_face,work,1,normal[i],1,normal[i],1);
983  }
984 
985  // Normalise to obtain unit normals.
986  Vmath::Zero(nq_face,work,1);
987  for(i = 0; i < GetCoordim(); ++i)
988  {
989  Vmath::Vvtvp(nq_face,normal[i],1,normal[i],1,work,1,work,1);
990  }
991 
992  Vmath::Vsqrt(nq_face,work,1,work,1);
993  Vmath::Sdiv (nq_face,1.0,work,1,work,1);
994 
995  for(i = 0; i < GetCoordim(); ++i)
996  {
997  Vmath::Vmul(nq_face,normal[i],1,work,1,normal[i],1);
998  }
999  }
1000  }
1001 
1003  Array<OneD, NekDouble> &array,
1004  const StdRegions::StdMatrixKey &mkey)
1005  {
1006  int nq = GetTotPoints();
1007 
1008  // Calculate sqrt of the Jacobian
1010  m_metricinfo->GetJac(GetPointsKeys());
1011  Array<OneD, NekDouble> sqrt_jac(nq);
1012  if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
1013  {
1014  Vmath::Vsqrt(nq,jac,1,sqrt_jac,1);
1015  }
1016  else
1017  {
1018  Vmath::Fill(nq,sqrt(jac[0]),sqrt_jac,1);
1019  }
1020 
1021  // Multiply array by sqrt(Jac)
1022  Vmath::Vmul(nq,sqrt_jac,1,array,1,array,1);
1023 
1024  // Apply std region filter
1025  StdPyrExp::v_SVVLaplacianFilter( array, mkey);
1026 
1027  // Divide by sqrt(Jac)
1028  Vmath::Vdiv(nq,array,1,sqrt_jac,1,array,1);
1029  }
1030 
1031 
1032  //---------------------------------------
1033  // Matrix creation functions
1034  //---------------------------------------
1035 
1037  {
1038  DNekMatSharedPtr returnval;
1039 
1040  switch(mkey.GetMatrixType())
1041  {
1048  returnval = Expansion3D::v_GenMatrix(mkey);
1049  break;
1050  default:
1051  returnval = StdPyrExp::v_GenMatrix(mkey);
1052  }
1053 
1054  return returnval;
1055  }
1056 
1058  {
1059  LibUtilities::BasisKey bkey0 = m_base[0]->GetBasisKey();
1060  LibUtilities::BasisKey bkey1 = m_base[1]->GetBasisKey();
1061  LibUtilities::BasisKey bkey2 = m_base[2]->GetBasisKey();
1063  MemoryManager<StdPyrExp>::AllocateSharedPtr(bkey0, bkey1, bkey2);
1064 
1065  return tmp->GetStdMatrix(mkey);
1066  }
1067 
1069  {
1070  return m_matrixManager[mkey];
1071  }
1072 
1074  {
1075  return m_staticCondMatrixManager[mkey];
1076  }
1077 
1079  {
1080  m_staticCondMatrixManager.DeleteObject(mkey);
1081  }
1082 
1084  {
1085  DNekScalMatSharedPtr returnval;
1087 
1088  ASSERTL2(m_metricinfo->GetGtype() != SpatialDomains::eNoGeomType,"Geometric information is not set up");
1089 
1090  switch(mkey.GetMatrixType())
1091  {
1092  case StdRegions::eMass:
1093  {
1094  if(m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
1095  {
1096  NekDouble one = 1.0;
1097  DNekMatSharedPtr mat = GenMatrix(mkey);
1098  returnval = MemoryManager<DNekScalMat>::AllocateSharedPtr(one,mat);
1099  }
1100  else
1101  {
1102  NekDouble jac = (m_metricinfo->GetJac(ptsKeys))[0];
1103  DNekMatSharedPtr mat = GetStdMatrix(mkey);
1104  returnval = MemoryManager<DNekScalMat>::AllocateSharedPtr(jac,mat);
1105  }
1106  }
1107  break;
1108  case StdRegions::eInvMass:
1109  {
1110  if(m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
1111  {
1112  NekDouble one = 1.0;
1114  *this);
1115  DNekMatSharedPtr mat = GenMatrix(masskey);
1116  mat->Invert();
1117  returnval = MemoryManager<DNekScalMat>::AllocateSharedPtr(one,mat);
1118  }
1119  else
1120  {
1121  NekDouble fac = 1.0/(m_metricinfo->GetJac(ptsKeys))[0];
1122  DNekMatSharedPtr mat = GetStdMatrix(mkey);
1123  returnval = MemoryManager<DNekScalMat>::AllocateSharedPtr(fac,mat);
1124  }
1125  }
1126  break;
1128  {
1129  if (m_metricinfo->GetGtype() == SpatialDomains::eDeformed ||
1130  mkey.GetNVarCoeff() > 0 ||
1131  mkey.ConstFactorExists(
1133  {
1134  NekDouble one = 1.0;
1135  DNekMatSharedPtr mat = GenMatrix(mkey);
1136 
1137  returnval = MemoryManager<DNekScalMat>::AllocateSharedPtr(one,mat);
1138  }
1139  else
1140  {
1142  mkey.GetShapeType(), *this);
1144  mkey.GetShapeType(), *this);
1146  mkey.GetShapeType(), *this);
1148  mkey.GetShapeType(), *this);
1150  mkey.GetShapeType(), *this);
1152  mkey.GetShapeType(), *this);
1153 
1154  DNekMat &lap00 = *GetStdMatrix(lap00key);
1155  DNekMat &lap01 = *GetStdMatrix(lap01key);
1156  DNekMat &lap02 = *GetStdMatrix(lap02key);
1157  DNekMat &lap11 = *GetStdMatrix(lap11key);
1158  DNekMat &lap12 = *GetStdMatrix(lap12key);
1159  DNekMat &lap22 = *GetStdMatrix(lap22key);
1160 
1161  NekDouble jac = (m_metricinfo->GetJac(ptsKeys))[0];
1163  m_metricinfo->GetGmat(ptsKeys);
1164 
1165  int rows = lap00.GetRows();
1166  int cols = lap00.GetColumns();
1167 
1169  ::AllocateSharedPtr(rows,cols);
1170 
1171  (*lap) = gmat[0][0]*lap00
1172  + gmat[4][0]*lap11
1173  + gmat[8][0]*lap22
1174  + gmat[3][0]*(lap01 + Transpose(lap01))
1175  + gmat[6][0]*(lap02 + Transpose(lap02))
1176  + gmat[7][0]*(lap12 + Transpose(lap12));
1177 
1178  returnval = MemoryManager<DNekScalMat>
1179  ::AllocateSharedPtr(jac, lap);
1180  }
1181  }
1182  break;
1184  {
1186  MatrixKey masskey(StdRegions::eMass, mkey.GetShapeType(), *this);
1187  DNekScalMat &MassMat = *(this->m_matrixManager[masskey]);
1188  MatrixKey lapkey(StdRegions::eLaplacian, mkey.GetShapeType(), *this, mkey.GetConstFactors(), mkey.GetVarCoeffs());
1189  DNekScalMat &LapMat = *(this->m_matrixManager[lapkey]);
1190 
1191  int rows = LapMat.GetRows();
1192  int cols = LapMat.GetColumns();
1193 
1195 
1196  (*helm) = LapMat + factor*MassMat;
1197 
1198  returnval = MemoryManager<DNekScalMat>::AllocateSharedPtr(1.0, helm);
1199  }
1200  break;
1202  {
1203  NekDouble one = 1.0;
1204  MatrixKey helmkey(StdRegions::eHelmholtz, mkey.GetShapeType(), *this, mkey.GetConstFactors(), mkey.GetVarCoeffs());
1205  DNekScalBlkMatSharedPtr helmStatCond = GetLocStaticCondMatrix(helmkey);
1206  DNekScalMatSharedPtr A =helmStatCond->GetBlock(0,0);
1208 
1210  }
1211  break;
1213  {
1214  NekDouble one = 1.0;
1215  MatrixKey masskey(StdRegions::eMass, mkey.GetShapeType(), *this);
1216  DNekScalBlkMatSharedPtr massStatCond = GetLocStaticCondMatrix(masskey);
1217  DNekScalMatSharedPtr A =massStatCond->GetBlock(0,0);
1219 
1221  }
1222  break;
1223  default:
1224  NEKERROR(ErrorUtil::efatal, "Matrix creation not defined");
1225  break;
1226  }
1227 
1228  return returnval;
1229  }
1230 
1232  {
1233  DNekScalBlkMatSharedPtr returnval;
1234 
1235  ASSERTL2(m_metricinfo->GetGtype() != SpatialDomains::eNoGeomType,"Geometric information is not set up");
1236 
1237  // set up block matrix system
1238  unsigned int nbdry = NumBndryCoeffs();
1239  unsigned int nint = (unsigned int)(m_ncoeffs - nbdry);
1240  unsigned int exp_size[] = {nbdry, nint};
1241  unsigned int nblks = 2;
1242  returnval = MemoryManager<DNekScalBlkMat>::AllocateSharedPtr(nblks, nblks, exp_size, exp_size); //Really need a constructor which takes Arrays
1243  NekDouble factor = 1.0;
1244 
1245  switch(mkey.GetMatrixType())
1246  {
1247  case StdRegions::eLaplacian:
1248  case StdRegions::eHelmholtz: // special case since Helmholtz not defined in StdRegions
1249 
1250  // use Deformed case for both regular and deformed geometries
1251  factor = 1.0;
1252  goto UseLocRegionsMatrix;
1253  break;
1254  default:
1255  if(m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
1256  {
1257  factor = 1.0;
1258  goto UseLocRegionsMatrix;
1259  }
1260  else
1261  {
1262  DNekScalMatSharedPtr mat = GetLocMatrix(mkey);
1263  factor = mat->Scale();
1264  goto UseStdRegionsMatrix;
1265  }
1266  break;
1267  UseStdRegionsMatrix:
1268  {
1269  NekDouble invfactor = 1.0/factor;
1270  NekDouble one = 1.0;
1272  DNekScalMatSharedPtr Atmp;
1273  DNekMatSharedPtr Asubmat;
1274 
1275  //TODO: check below
1276  returnval->SetBlock(0,0,Atmp = MemoryManager<DNekScalMat>::AllocateSharedPtr(factor,Asubmat = mat->GetBlock(0,0)));
1277  returnval->SetBlock(0,1,Atmp = MemoryManager<DNekScalMat>::AllocateSharedPtr(one,Asubmat = mat->GetBlock(0,1)));
1278  returnval->SetBlock(1,0,Atmp = MemoryManager<DNekScalMat>::AllocateSharedPtr(factor,Asubmat = mat->GetBlock(1,0)));
1279  returnval->SetBlock(1,1,Atmp = MemoryManager<DNekScalMat>::AllocateSharedPtr(invfactor,Asubmat = mat->GetBlock(1,1)));
1280  }
1281  break;
1282  UseLocRegionsMatrix:
1283  {
1284  int i,j;
1285  NekDouble invfactor = 1.0/factor;
1286  NekDouble one = 1.0;
1287  DNekScalMat &mat = *GetLocMatrix(mkey);
1292 
1293  Array<OneD,unsigned int> bmap(nbdry);
1294  Array<OneD,unsigned int> imap(nint);
1295  GetBoundaryMap(bmap);
1296  GetInteriorMap(imap);
1297 
1298  for(i = 0; i < nbdry; ++i)
1299  {
1300  for(j = 0; j < nbdry; ++j)
1301  {
1302  (*A)(i,j) = mat(bmap[i],bmap[j]);
1303  }
1304 
1305  for(j = 0; j < nint; ++j)
1306  {
1307  (*B)(i,j) = mat(bmap[i],imap[j]);
1308  }
1309  }
1310 
1311  for(i = 0; i < nint; ++i)
1312  {
1313  for(j = 0; j < nbdry; ++j)
1314  {
1315  (*C)(i,j) = mat(imap[i],bmap[j]);
1316  }
1317 
1318  for(j = 0; j < nint; ++j)
1319  {
1320  (*D)(i,j) = mat(imap[i],imap[j]);
1321  }
1322  }
1323 
1324  // Calculate static condensed system
1325  if(nint)
1326  {
1327  D->Invert();
1328  (*B) = (*B)*(*D);
1329  (*A) = (*A) - (*B)*(*C);
1330  }
1331 
1332  DNekScalMatSharedPtr Atmp;
1333 
1334  returnval->SetBlock(0,0,Atmp = MemoryManager<DNekScalMat>::AllocateSharedPtr(factor,A));
1335  returnval->SetBlock(0,1,Atmp = MemoryManager<DNekScalMat>::AllocateSharedPtr(one,B));
1336  returnval->SetBlock(1,0,Atmp = MemoryManager<DNekScalMat>::AllocateSharedPtr(factor,C));
1337  returnval->SetBlock(1,1,Atmp = MemoryManager<DNekScalMat>::AllocateSharedPtr(invfactor,D));
1338  }
1339  }
1340  return returnval;
1341  }
1342 
1344  {
1345  if (m_metrics.count(eMetricQuadrature) == 0)
1346  {
1348  }
1349 
1350  int i, j;
1351  const unsigned int nqtot = GetTotPoints();
1352  const unsigned int dim = 3;
1353  const MetricType m[3][3] = {
1357  };
1358 
1359  for (unsigned int i = 0; i < dim; ++i)
1360  {
1361  for (unsigned int j = i; j < dim; ++j)
1362  {
1363  m_metrics[m[i][j]] = Array<OneD, NekDouble>(nqtot);
1364  }
1365  }
1366 
1367  // Define shorthand synonyms for m_metrics storage
1368  Array<OneD,NekDouble> g0 (m_metrics[m[0][0]]);
1369  Array<OneD,NekDouble> g1 (m_metrics[m[1][1]]);
1370  Array<OneD,NekDouble> g2 (m_metrics[m[2][2]]);
1371  Array<OneD,NekDouble> g3 (m_metrics[m[0][1]]);
1372  Array<OneD,NekDouble> g4 (m_metrics[m[0][2]]);
1373  Array<OneD,NekDouble> g5 (m_metrics[m[1][2]]);
1374 
1375  // Allocate temporary storage
1376  Array<OneD,NekDouble> alloc(9*nqtot,0.0);
1377  Array<OneD,NekDouble> h0 (nqtot, alloc);
1378  Array<OneD,NekDouble> h1 (nqtot, alloc+ 1*nqtot);
1379  Array<OneD,NekDouble> h2 (nqtot, alloc+ 2*nqtot);
1380  Array<OneD,NekDouble> wsp1 (nqtot, alloc+ 3*nqtot);
1381  Array<OneD,NekDouble> wsp2 (nqtot, alloc+ 4*nqtot);
1382  Array<OneD,NekDouble> wsp3 (nqtot, alloc+ 5*nqtot);
1383  Array<OneD,NekDouble> wsp4 (nqtot, alloc+ 6*nqtot);
1384  Array<OneD,NekDouble> wsp5 (nqtot, alloc+ 7*nqtot);
1385  Array<OneD,NekDouble> wsp6 (nqtot, alloc+ 8*nqtot);
1386 
1387  const Array<TwoD, const NekDouble>& df =
1388  m_metricinfo->GetDerivFactors(GetPointsKeys());
1389  const Array<OneD, const NekDouble>& z0 = m_base[0]->GetZ();
1390  const Array<OneD, const NekDouble>& z1 = m_base[1]->GetZ();
1391  const Array<OneD, const NekDouble>& z2 = m_base[2]->GetZ();
1392  const unsigned int nquad0 = m_base[0]->GetNumPoints();
1393  const unsigned int nquad1 = m_base[1]->GetNumPoints();
1394  const unsigned int nquad2 = m_base[2]->GetNumPoints();
1395 
1396  // Populate collapsed coordinate arrays h0, h1 and h2.
1397  for(j = 0; j < nquad2; ++j)
1398  {
1399  for(i = 0; i < nquad1; ++i)
1400  {
1401  Vmath::Fill(nquad0, 2.0/(1.0-z2[j]), &h0[0]+i*nquad0 + j*nquad0*nquad1,1);
1402  Vmath::Fill(nquad0, 1.0/(1.0-z2[j]), &h1[0]+i*nquad0 + j*nquad0*nquad1,1);
1403  Vmath::Fill(nquad0, (1.0+z1[i])/(1.0-z2[j]), &h2[0]+i*nquad0 + j*nquad0*nquad1,1);
1404  }
1405  }
1406  for(i = 0; i < nquad0; i++)
1407  {
1408  Blas::Dscal(nquad1*nquad2, 1+z0[i], &h1[0]+i, nquad0);
1409  }
1410 
1411  // Step 3. Construct combined metric terms for physical space to
1412  // collapsed coordinate system.
1413  // Order of construction optimised to minimise temporary storage
1414  if(m_metricinfo->GetGtype() == SpatialDomains::eDeformed)
1415  {
1416  // f_{1k}
1417  Vmath::Vvtvvtp(nqtot, &df[0][0], 1, &h0[0], 1, &df[2][0], 1, &h1[0], 1, &wsp1[0], 1);
1418  Vmath::Vvtvvtp(nqtot, &df[3][0], 1, &h0[0], 1, &df[5][0], 1, &h1[0], 1, &wsp2[0], 1);
1419  Vmath::Vvtvvtp(nqtot, &df[6][0], 1, &h0[0], 1, &df[8][0], 1, &h1[0], 1, &wsp3[0], 1);
1420 
1421  // g0
1422  Vmath::Vvtvvtp(nqtot, &wsp1[0], 1, &wsp1[0], 1, &wsp2[0], 1, &wsp2[0], 1, &g0[0], 1);
1423  Vmath::Vvtvp (nqtot, &wsp3[0], 1, &wsp3[0], 1, &g0[0], 1, &g0[0], 1);
1424 
1425  // g4
1426  Vmath::Vvtvvtp(nqtot, &df[2][0], 1, &wsp1[0], 1, &df[5][0], 1, &wsp2[0], 1, &g4[0], 1);
1427  Vmath::Vvtvp (nqtot, &df[8][0], 1, &wsp3[0], 1, &g4[0], 1, &g4[0], 1);
1428 
1429  // f_{2k}
1430  Vmath::Vvtvvtp(nqtot, &df[1][0], 1, &h0[0], 1, &df[2][0], 1, &h2[0], 1, &wsp4[0], 1);
1431  Vmath::Vvtvvtp(nqtot, &df[4][0], 1, &h0[0], 1, &df[5][0], 1, &h2[0], 1, &wsp5[0], 1);
1432  Vmath::Vvtvvtp(nqtot, &df[7][0], 1, &h0[0], 1, &df[8][0], 1, &h2[0], 1, &wsp6[0], 1);
1433 
1434  // g1
1435  Vmath::Vvtvvtp(nqtot, &wsp4[0], 1, &wsp4[0], 1, &wsp5[0], 1, &wsp5[0], 1, &g1[0], 1);
1436  Vmath::Vvtvp (nqtot, &wsp6[0], 1, &wsp6[0], 1, &g1[0], 1, &g1[0], 1);
1437 
1438  // g3
1439  Vmath::Vvtvvtp(nqtot, &wsp1[0], 1, &wsp4[0], 1, &wsp2[0], 1, &wsp5[0], 1, &g3[0], 1);
1440  Vmath::Vvtvp (nqtot, &wsp3[0], 1, &wsp6[0], 1, &g3[0], 1, &g3[0], 1);
1441 
1442  // g5
1443  Vmath::Vvtvvtp(nqtot, &df[2][0], 1, &wsp4[0], 1, &df[5][0], 1, &wsp5[0], 1, &g5[0], 1);
1444  Vmath::Vvtvp (nqtot, &df[8][0], 1, &wsp6[0], 1, &g5[0], 1, &g5[0], 1);
1445 
1446  // g2
1447  Vmath::Vvtvvtp(nqtot, &df[2][0], 1, &df[2][0], 1, &df[5][0], 1, &df[5][0], 1, &g2[0], 1);
1448  Vmath::Vvtvp (nqtot, &df[8][0], 1, &df[8][0], 1, &g2[0], 1, &g2[0], 1);
1449  }
1450  else
1451  {
1452  // f_{1k}
1453  Vmath::Svtsvtp(nqtot, df[0][0], &h0[0], 1, df[2][0], &h1[0], 1, &wsp1[0], 1);
1454  Vmath::Svtsvtp(nqtot, df[3][0], &h0[0], 1, df[5][0], &h1[0], 1, &wsp2[0], 1);
1455  Vmath::Svtsvtp(nqtot, df[6][0], &h0[0], 1, df[8][0], &h1[0], 1, &wsp3[0], 1);
1456 
1457  // g0
1458  Vmath::Vvtvvtp(nqtot, &wsp1[0], 1, &wsp1[0], 1, &wsp2[0], 1, &wsp2[0], 1, &g0[0], 1);
1459  Vmath::Vvtvp (nqtot, &wsp3[0], 1, &wsp3[0], 1, &g0[0], 1, &g0[0], 1);
1460 
1461  // g4
1462  Vmath::Svtsvtp(nqtot, df[2][0], &wsp1[0], 1, df[5][0], &wsp2[0], 1, &g4[0], 1);
1463  Vmath::Svtvp (nqtot, df[8][0], &wsp3[0], 1, &g4[0], 1, &g4[0], 1);
1464 
1465  // f_{2k}
1466  Vmath::Svtsvtp(nqtot, df[1][0], &h0[0], 1, df[2][0], &h2[0], 1, &wsp4[0], 1);
1467  Vmath::Svtsvtp(nqtot, df[4][0], &h0[0], 1, df[5][0], &h2[0], 1, &wsp5[0], 1);
1468  Vmath::Svtsvtp(nqtot, df[7][0], &h0[0], 1, df[8][0], &h2[0], 1, &wsp6[0], 1);
1469 
1470  // g1
1471  Vmath::Vvtvvtp(nqtot, &wsp4[0], 1, &wsp4[0], 1, &wsp5[0], 1, &wsp5[0], 1, &g1[0], 1);
1472  Vmath::Vvtvp (nqtot, &wsp6[0], 1, &wsp6[0], 1, &g1[0], 1, &g1[0], 1);
1473 
1474  // g3
1475  Vmath::Vvtvvtp(nqtot, &wsp1[0], 1, &wsp4[0], 1, &wsp2[0], 1, &wsp5[0], 1, &g3[0], 1);
1476  Vmath::Vvtvp (nqtot, &wsp3[0], 1, &wsp6[0], 1, &g3[0], 1, &g3[0], 1);
1477 
1478  // g5
1479  Vmath::Svtsvtp(nqtot, df[2][0], &wsp4[0], 1, df[5][0], &wsp5[0], 1, &g5[0], 1);
1480  Vmath::Svtvp (nqtot, df[8][0], &wsp6[0], 1, &g5[0], 1, &g5[0], 1);
1481 
1482  // g2
1483  Vmath::Fill(nqtot, df[2][0]*df[2][0] + df[5][0]*df[5][0] + df[8][0]*df[8][0], &g2[0], 1);
1484  }
1485 
1486  for (unsigned int i = 0; i < dim; ++i)
1487  {
1488  for (unsigned int j = i; j < dim; ++j)
1489  {
1491  m_metrics[m[i][j]]);
1492 
1493  }
1494  }
1495  }
1496 
1498  const Array<OneD, const NekDouble> &inarray,
1499  Array<OneD, NekDouble> &outarray,
1501  {
1502  // This implementation is only valid when there are no coefficients
1503  // associated to the Laplacian operator
1504  if (m_metrics.count(eMetricLaplacian00) == 0)
1505  {
1507  }
1508 
1509  int nquad0 = m_base[0]->GetNumPoints();
1510  int nquad1 = m_base[1]->GetNumPoints();
1511  int nq2 = m_base[2]->GetNumPoints();
1512  int nqtot = nquad0*nquad1*nq2;
1513 
1514  ASSERTL1(wsp.num_elements() >= 6*nqtot,
1515  "Insufficient workspace size.");
1516  ASSERTL1(m_ncoeffs <= nqtot,
1517  "Workspace not set up for ncoeffs > nqtot");
1518 
1519  const Array<OneD, const NekDouble>& base0 = m_base[0]->GetBdata();
1520  const Array<OneD, const NekDouble>& base1 = m_base[1]->GetBdata();
1521  const Array<OneD, const NekDouble>& base2 = m_base[2]->GetBdata();
1522  const Array<OneD, const NekDouble>& dbase0 = m_base[0]->GetDbdata();
1523  const Array<OneD, const NekDouble>& dbase1 = m_base[1]->GetDbdata();
1524  const Array<OneD, const NekDouble>& dbase2 = m_base[2]->GetDbdata();
1531 
1532  // Allocate temporary storage
1533  Array<OneD,NekDouble> wsp0 (2*nqtot, wsp);
1534  Array<OneD,NekDouble> wsp1 ( nqtot, wsp+1*nqtot);
1535  Array<OneD,NekDouble> wsp2 ( nqtot, wsp+2*nqtot);
1536  Array<OneD,NekDouble> wsp3 ( nqtot, wsp+3*nqtot);
1537  Array<OneD,NekDouble> wsp4 ( nqtot, wsp+4*nqtot);
1538  Array<OneD,NekDouble> wsp5 ( nqtot, wsp+5*nqtot);
1539 
1540  // LAPLACIAN MATRIX OPERATION
1541  // wsp1 = du_dxi1 = D_xi1 * inarray = D_xi1 * u
1542  // wsp2 = du_dxi2 = D_xi2 * inarray = D_xi2 * u
1543  // wsp2 = du_dxi3 = D_xi3 * inarray = D_xi3 * u
1544  StdExpansion3D::PhysTensorDeriv(inarray,wsp0,wsp1,wsp2);
1545 
1546  // wsp0 = k = g0 * wsp1 + g1 * wsp2 = g0 * du_dxi1 + g1 * du_dxi2
1547  // wsp2 = l = g1 * wsp1 + g2 * wsp2 = g0 * du_dxi1 + g1 * du_dxi2
1548  // where g0, g1 and g2 are the metric terms set up in the GeomFactors class
1549  // especially for this purpose
1550  Vmath::Vvtvvtp(nqtot,&metric00[0],1,&wsp0[0],1,&metric01[0],1,&wsp1[0],1,&wsp3[0],1);
1551  Vmath::Vvtvp (nqtot,&metric02[0],1,&wsp2[0],1,&wsp3[0],1,&wsp3[0],1);
1552  Vmath::Vvtvvtp(nqtot,&metric01[0],1,&wsp0[0],1,&metric11[0],1,&wsp1[0],1,&wsp4[0],1);
1553  Vmath::Vvtvp (nqtot,&metric12[0],1,&wsp2[0],1,&wsp4[0],1,&wsp4[0],1);
1554  Vmath::Vvtvvtp(nqtot,&metric02[0],1,&wsp0[0],1,&metric12[0],1,&wsp1[0],1,&wsp5[0],1);
1555  Vmath::Vvtvp (nqtot,&metric22[0],1,&wsp2[0],1,&wsp5[0],1,&wsp5[0],1);
1556 
1557  // outarray = m = (D_xi1 * B)^T * k
1558  // wsp1 = n = (D_xi2 * B)^T * l
1559  IProductWRTBase_SumFacKernel(dbase0,base1,base2,wsp3,outarray,wsp0,false,true,true);
1560  IProductWRTBase_SumFacKernel(base0,dbase1,base2,wsp4,wsp2, wsp0,true,false,true);
1561  Vmath::Vadd(m_ncoeffs,wsp2.get(),1,outarray.get(),1,outarray.get(),1);
1562  IProductWRTBase_SumFacKernel(base0,base1,dbase2,wsp5,wsp2, wsp0,true,true,false);
1563  Vmath::Vadd(m_ncoeffs,wsp2.get(),1,outarray.get(),1,outarray.get(),1);
1564  }
1565  }//end of namespace
1566 }//end of namespace
int GetNumPoints() const
Return points order at which basis is defined.
Definition: Basis.h:133
const VarCoeffMap & GetVarCoeffs() const
Definition: StdMatrixKey.h:161
DNekMatSharedPtr GenMatrix(const StdMatrixKey &mkey)
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
DNekScalBlkMatSharedPtr CreateStaticCondMatrix(const MatrixKey &mkey)
Definition: PyrExp.cpp:1231
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mod...
Definition: ErrorUtil.hpp:209
std::vector< PointsKey > PointsKeyVector
Definition: Points.h:246
void v_ComputeFaceNormal(const int face)
Definition: PyrExp.cpp:723
LibUtilities::NekManager< MatrixKey, DNekScalBlkMat, MatrixKey::opLess > m_staticCondMatrixManager
Definition: PyrExp.h:183
LibUtilities::ShapeType DetShapeType() const
This function returns the shape of the expansion domain.
Definition: StdExpansion.h:469
virtual void v_ComputeLaplacianMetric()
Definition: PyrExp.cpp:1343
int GetNumPoints(const int dir) const
This function returns the number of quadrature points in the dir direction.
Definition: StdExpansion.h:228
void Vsqrt(int n, const T *x, const int incx, T *y, const int incy)
sqrt y = sqrt(x)
Definition: Vmath.cpp:411
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
virtual StdRegions::StdExpansionSharedPtr v_GetLinStdExp(void) const
Definition: PyrExp.cpp:488
void MultiplyByQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: StdExpansion.h:945
SpatialDomains::GeometrySharedPtr GetGeom() const
Definition: Expansion.cpp:167
DNekScalMatSharedPtr CreateMatrix(const MatrixKey &mkey)
Definition: PyrExp.cpp:1083
virtual void v_GetFacePhysMap(const int face, Array< OneD, int > &outarray)
Definition: PyrExp.cpp:623
std::shared_ptr< GeomFactors > GeomFactorsSharedPtr
Pointer to a GeomFactors object.
Definition: GeomFactors.h:62
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
std::shared_ptr< DNekScalBlkMat > DNekScalBlkMatSharedPtr
Definition: NekTypeDefs.hpp:73
virtual DNekMatSharedPtr v_CreateStdMatrix(const StdRegions::StdMatrixKey &mkey)
Definition: PyrExp.cpp:1057
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*base2 and put into out...
Definition: PyrExp.cpp:278
void v_IProductWRTDerivBase(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Calculates the inner product .
Definition: PyrExp.cpp:351
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:45
virtual DNekMatSharedPtr v_GenMatrix(const StdRegions::StdMatrixKey &mkey)
Definition: PyrExp.cpp:1036
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:488
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:445
SpatialDomains::GeomFactorsSharedPtr m_metricinfo
Definition: Expansion.h:128
virtual int v_GetCoordim()
Definition: PyrExp.cpp:618
STL namespace.
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:274
virtual void v_IProductWRTBase_SumFac(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool multiplybyweights=true)
Definition: PyrExp.cpp:285
DNekMatSharedPtr BuildVertexMatrix(const DNekScalMatSharedPtr &r_bnd)
Definition: Expansion.cpp:98
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
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:244
SpatialDomains::GeometrySharedPtr m_geom
Definition: Expansion.h:127
virtual void v_LaplacianMatrixOp_MatFree_Kernel(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp)
Definition: PyrExp.cpp:1497
MatrixType GetMatrixType() const
Definition: StdMatrixKey.h:81
DNekScalBlkMatSharedPtr GetLocStaticCondMatrix(const LocalRegions::MatrixKey &mkey)
Definition: StdExpansion.h:761
PointsKey GetPointsKey() const
Return distribution of points.
Definition: Basis.h:150
std::shared_ptr< DNekBlkMat > DNekBlkMatSharedPtr
Definition: NekTypeDefs.hpp:71
virtual void v_GetCoord(const Array< OneD, const NekDouble > &Lcoords, Array< OneD, NekDouble > &coords)
Definition: PyrExp.cpp:505
DNekMatSharedPtr GetStdMatrix(const StdMatrixKey &mkey)
Definition: StdExpansion.h:714
virtual NekDouble v_Integral(const Array< OneD, const NekDouble > &inarray)
Integrate the physical point list inarray over pyramidic region and return the value.
Definition: PyrExp.cpp:111
virtual StdRegions::StdExpansionSharedPtr v_GetStdExp(void) const
Definition: PyrExp.cpp:480
const LibUtilities::PointsKeyVector GetPointsKeys() const
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:115
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
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: PyrExp.cpp:220
DNekBlkMatSharedPtr GetStdStaticCondMatrix(const StdMatrixKey &mkey)
Definition: StdExpansion.h:719
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)
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: PyrExp.cpp:532
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*y.
Definition: Vmath.cpp:216
virtual void v_GetCoords(Array< OneD, NekDouble > &coords_1, Array< OneD, NekDouble > &coords_2, Array< OneD, NekDouble > &coords_3)
Definition: Expansion.cpp:231
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
void GetInteriorMap(Array< OneD, unsigned int > &outarray)
Definition: StdExpansion.h:817
NekMatrix< InnerMatrixType, BlockMatrixTag > Transpose(NekMatrix< InnerMatrixType, BlockMatrixTag > &rhs)
Defines a specification for a set of points.
Definition: Points.h:59
double NekDouble
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: PyrExp.cpp:138
std::map< int, NormalVector > m_faceNormals
NekDouble GetConstFactor(const ConstFactorType &factor) const
Definition: StdMatrixKey.h:121
void v_IProductWRTDerivBase_SumFac(const int dir, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: PyrExp.cpp:359
int GetNcoeffs(void) const
This function returns the total number of coefficients used in the expansion.
Definition: StdExpansion.h:130
void v_DropLocStaticCondMatrix(const MatrixKey &mkey)
Definition: PyrExp.cpp:1078
std::shared_ptr< PyrGeom > PyrGeomSharedPtr
Definition: PyrGeom.h:80
NekDouble v_StdPhysEvaluate(const Array< OneD, const NekDouble > &Lcoord, const Array< OneD, const NekDouble > &physvals)
Definition: PyrExp.cpp:592
DNekScalMatSharedPtr GetLocMatrix(const LocalRegions::MatrixKey &mkey)
Definition: Expansion.cpp:85
static void Dscal(const int &n, const double &alpha, double *x, const int &incx)
BLAS level 1: x = alpha x.
Definition: Blas.hpp:125
const ConstFactorMap & GetConstFactors() const
Definition: StdMatrixKey.h:135
LibUtilities::PointsType GetPointsType(const int dir) const
This function returns the type of quadrature points used in the dir direction.
Definition: StdExpansion.h:215
virtual DNekMatSharedPtr v_GenMatrix(const StdRegions::StdMatrixKey &mkey)
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:540
bool ConstFactorExists(const ConstFactorType &factor) const
Definition: StdMatrixKey.h:130
#define ASSERTL2(condition, msg)
Assert Level 2 – Debugging which is used FULLDEBUG compilation mode. This level assert is designed t...
Definition: ErrorUtil.hpp:274
Geometry is straight-sided with constant geometric factors.
LibUtilities::BasisType GetBasisType(const int dir) const
This function returns the type of basis used in the dir direction.
Definition: StdExpansion.h:164
const LibUtilities::BasisKey DetFaceBasisKey(const int i, const int k) const
Definition: StdExpansion.h:323
virtual void v_SVVLaplacianFilter(Array< OneD, NekDouble > &array, const StdRegions::StdMatrixKey &mkey)
Definition: PyrExp.cpp:1002
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:530
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:594
virtual DNekScalMatSharedPtr v_GetLocMatrix(const MatrixKey &mkey)
Definition: PyrExp.cpp:1068
StdExpansion()
Default Constructor.
int GetTotPoints() const
This function returns the total number of quadrature points used in the element.
Definition: StdExpansion.h:140
GeomType
Indicates the type of element geometry.
virtual DNekScalBlkMatSharedPtr v_GetLocStaticCondMatrix(const MatrixKey &mkey)
Definition: PyrExp.cpp:1073
virtual void v_GetCoords(Array< OneD, NekDouble > &coords_1, Array< OneD, NekDouble > &coords_2, Array< OneD, NekDouble > &coords_3)
Definition: PyrExp.cpp:523
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:376
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: PyrExp.cpp:600
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
Array< OneD, LibUtilities::BasisSharedPtr > m_base
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:110
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
Geometry is curved or has non-constant factors.
LibUtilities::ShapeType GetShapeType() const
Definition: StdMatrixKey.h:86
void GetBoundaryMap(Array< OneD, unsigned int > &outarray)
Definition: StdExpansion.h:812
LibUtilities::NekManager< MatrixKey, DNekScalMat, MatrixKey::opLess > m_matrixManager
Definition: PyrExp.h:182
Describes the specification for a Basis.
Definition: Basis.h:49
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:302
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:186
std::shared_ptr< StdPyrExp > StdPyrExpSharedPtr
Definition: StdPyrExp.h:270
PyrExp(const LibUtilities::BasisKey &Ba, const LibUtilities::BasisKey &Bb, const LibUtilities::BasisKey &Bc, const SpatialDomains::PyrGeomSharedPtr &geom)
Constructor using BasisKey class for quadrature points and order definition.
Definition: PyrExp.cpp:45
void FwdTrans(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
This function performs the Forward transformation from physical space to coefficient space...