Nektar++
StdExpansion3D.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File StdExpansion3D.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: Daughter of StdExpansion. This class contains routine
32 // which are common to 3D expansion. Typically this inolves physiocal
33 // space operations.
34 //
35 ///////////////////////////////////////////////////////////////////////////////
36 
37 #include <boost/core/ignore_unused.hpp>
38 
40 
41 #ifdef max
42 #undef max
43 #endif
44 
45 namespace Nektar
46 {
47  namespace StdRegions
48  {
50  {
51  }
52 
54  const LibUtilities::BasisKey &Ba,
55  const LibUtilities::BasisKey &Bb,
56  const LibUtilities::BasisKey &Bc) :
57  StdExpansion(numcoeffs,3,Ba,Bb,Bc)
58  {
59  }
60 
62  StdExpansion(T)
63  {
64  }
65 
67  {
68  }
70  const Array<OneD, const NekDouble> &inarray,
71  Array<OneD, NekDouble> &out_dx,
72  Array<OneD, NekDouble> &out_dy,
73  Array<OneD, NekDouble> &out_dz)
74  {
75  const int nquad0 = m_base[0]->GetNumPoints();
76  const int nquad1 = m_base[1]->GetNumPoints();
77  const int nquad2 = m_base[2]->GetNumPoints();
78 
79  Array<OneD, NekDouble> wsp(nquad0*nquad1*nquad2);
80 
81  // copy inarray to wsp in case inarray is used as outarray
82  Vmath::Vcopy(nquad0*nquad1*nquad2, &inarray[0], 1, &wsp[0], 1);
83 
84  if (out_dx.num_elements() > 0)
85  {
86  NekDouble *D0 = &((m_base[0]->GetD())->GetPtr())[0];
87 
88  Blas::Dgemm('N','N', nquad0,nquad1*nquad2,nquad0,1.0,
89  D0,nquad0,&wsp[0],nquad0,0.0,&out_dx[0],nquad0);
90  }
91 
92  if (out_dy.num_elements() > 0)
93  {
94  NekDouble *D1 = &((m_base[1]->GetD())->GetPtr())[0];
95  for (int j = 0; j < nquad2; ++j)
96  {
97  Blas::Dgemm('N', 'T', nquad0, nquad1, nquad1,
98  1.0, &wsp[j*nquad0*nquad1], nquad0,
99  D1, nquad1,
100  0.0, &out_dy[j*nquad0*nquad1], nquad0);
101  }
102  }
103 
104  if (out_dz.num_elements() > 0)
105  {
106  NekDouble *D2 = &((m_base[2]->GetD())->GetPtr())[0];
107 
108  Blas::Dgemm('N','T',nquad0*nquad1,nquad2,nquad2,1.0,
109  &wsp[0],nquad0*nquad1,D2,nquad2,0.0,&out_dz[0],
110  nquad0*nquad1);
111  }
112  }
113 
115  const Array<OneD, const NekDouble>& base0,
116  const Array<OneD, const NekDouble>& base1,
117  const Array<OneD, const NekDouble>& base2,
118  const Array<OneD, const NekDouble>& inarray,
119  Array<OneD, NekDouble>& outarray,
121  bool doCheckCollDir0,
122  bool doCheckCollDir1,
123  bool doCheckCollDir2)
124  {
125  v_BwdTrans_SumFacKernel(base0, base1, base2, inarray, outarray, wsp, doCheckCollDir0, doCheckCollDir1, doCheckCollDir2);
126  }
127 
129  const Array<OneD, const NekDouble>& base0,
130  const Array<OneD, const NekDouble>& base1,
131  const Array<OneD, const NekDouble>& base2,
132  const Array<OneD, const NekDouble>& inarray,
133  Array<OneD, NekDouble> &outarray,
135  bool doCheckCollDir0,
136  bool doCheckCollDir1,
137  bool doCheckCollDir2)
138  {
139  v_IProductWRTBase_SumFacKernel(base0, base1, base2, inarray, outarray, wsp, doCheckCollDir0, doCheckCollDir1, doCheckCollDir2);
140  }
141 
143  const Array<OneD, const NekDouble> &coords,
144  const Array<OneD, const NekDouble> &physvals)
145  {
148 
149  WARNINGL2(coords[0] >= -1 - NekConstants::kNekZeroTol,"coord[0] < -1");
150  WARNINGL2(coords[0] <= 1 + NekConstants::kNekZeroTol,"coord[0] > 1");
151  WARNINGL2(coords[1] >= -1 - NekConstants::kNekZeroTol,"coord[1] < -1");
152  WARNINGL2(coords[1] <= 1 + NekConstants::kNekZeroTol,"coord[1] > 1");
153  WARNINGL2(coords[2] >= -1 - NekConstants::kNekZeroTol,"coord[2] < -1");
154  WARNINGL2(coords[2] <= 1 + NekConstants::kNekZeroTol,"coord[2] > 1");
155 
156  // Obtain local collapsed corodinate from
157  // cartesian coordinate.
158  LocCoordToLocCollapsed(coords,eta);
159 
160  // Get Lagrange interpolants.
161  I[0] = m_base[0]->GetI(eta);
162  I[1] = m_base[1]->GetI(eta+1);
163  I[2] = m_base[2]->GetI(eta+2);
164 
165  return v_PhysEvaluate(I,physvals);
166  }
167 
170  const Array<OneD, const NekDouble> &physvals)
171  {
172  NekDouble value;
173 
174  int Qx = m_base[0]->GetNumPoints();
175  int Qy = m_base[1]->GetNumPoints();
176  int Qz = m_base[2]->GetNumPoints();
177 
178  Array<OneD, NekDouble> sumFactorization_qr = Array<OneD, NekDouble>(Qy*Qz);
179  Array<OneD, NekDouble> sumFactorization_r = Array<OneD, NekDouble>(Qz);
180 
181  // Lagrangian interpolation matrix
182  NekDouble *interpolatingNodes = 0;
183 
184  // Interpolate first coordinate direction
185  interpolatingNodes = &I[0]->GetPtr()[0];
186 
187  Blas::Dgemv('T',Qx,Qy*Qz,1.0,&physvals[0],Qx,&interpolatingNodes[0], 1, 0.0, &sumFactorization_qr[0], 1);
188 
189  // Interpolate in second coordinate direction
190  interpolatingNodes = &I[1]->GetPtr()[0];
191 
192  Blas::Dgemv('T',Qy,Qz,1.0,&sumFactorization_qr[0],Qy,&interpolatingNodes[0],1,0.0,&sumFactorization_r[0], 1);
193 
194  // Interpolate in third coordinate direction
195  interpolatingNodes = &I[2]->GetPtr()[0];
196  value = Blas::Ddot(Qz, interpolatingNodes, 1, &sumFactorization_r[0], 1);
197 
198  return value;
199  }
200 
201 
202  /**
203  * @param inarray Input coefficients.
204  * @param output Output coefficients.
205  * @param mkey Matrix key
206  */
208  const Array<OneD, const NekDouble> &inarray,
209  Array<OneD,NekDouble> &outarray,
210  const StdRegions::StdMatrixKey &mkey)
211  {
212  if ( mkey.GetNVarCoeff() == 0 &&
214  {
215  // This implementation is only valid when there are no
216  // coefficients associated to the Laplacian operator
217  int nqtot = GetTotPoints();
218 
219  const Array<OneD, const NekDouble>& base0 = m_base[0]->GetBdata();
220  const Array<OneD, const NekDouble>& base1 = m_base[1]->GetBdata();
221  const Array<OneD, const NekDouble>& base2 = m_base[2]->GetBdata();
222 
223  // Allocate temporary storage
224  Array<OneD,NekDouble> wsp0(7*nqtot);
225  Array<OneD,NekDouble> wsp1(wsp0+nqtot);
226 
227  if(!(m_base[0]->Collocation() && m_base[1]->Collocation() &&
228  m_base[2]->Collocation()))
229  {
230  // LAPLACIAN MATRIX OPERATION
231  // wsp0 = u = B * u_hat
232  // wsp1 = du_dxi1 = D_xi1 * wsp0 = D_xi1 * u
233  // wsp2 = du_dxi2 = D_xi2 * wsp0 = D_xi2 * u
234  BwdTrans_SumFacKernel(base0,base1,base2,inarray,wsp0,wsp1,true,true,true);
235  LaplacianMatrixOp_MatFree_Kernel(wsp0,outarray,wsp1);
236  }
237  else
238  {
239  LaplacianMatrixOp_MatFree_Kernel(inarray,outarray,wsp1);
240  }
241  }
242  else
243  {
245  }
246  }
247 
248 
250  const Array<OneD, const NekDouble> &inarray,
251  Array<OneD,NekDouble> &outarray,
252  const StdRegions::StdMatrixKey &mkey)
253  {
254  if(mkey.GetNVarCoeff() == 0)
255  {
256  using std::max;
257 
258  int nquad0 = m_base[0]->GetNumPoints();
259  int nquad1 = m_base[1]->GetNumPoints();
260  int nquad2 = m_base[2]->GetNumPoints();
261  int nmodes0 = m_base[0]->GetNumModes();
262  int nmodes1 = m_base[1]->GetNumModes();
263  int nmodes2 = m_base[2]->GetNumModes();
264  int wspsize = max(nquad0*nmodes2*(nmodes1+nquad1),
265  nquad0*nquad1*(nquad2+nmodes0)+
266  nmodes0*nmodes1*nquad2);
267 
269 
270  const Array<OneD, const NekDouble>& base0 = m_base[0]->GetBdata ();
271  const Array<OneD, const NekDouble>& base1 = m_base[1]->GetBdata ();
272  const Array<OneD, const NekDouble>& base2 = m_base[2]->GetBdata ();
273  Array<OneD,NekDouble> wsp0(8*wspsize);
274  Array<OneD,NekDouble> wsp1(wsp0+1*wspsize);
275  Array<OneD,NekDouble> wsp2(wsp0+2*wspsize);
276 
277  if(!(m_base[0]->Collocation() && m_base[1]->Collocation() &&
278  m_base[2]->Collocation()))
279  {
280  // MASS MATRIX OPERATION
281  // The following is being calculated:
282  // wsp0 = B * u_hat = u
283  // wsp1 = W * wsp0
284  // outarray = B^T * wsp1 = B^T * W * B * u_hat = M * u_hat
285  BwdTrans_SumFacKernel (base0,base1,base2,inarray,
286  wsp0,wsp2,true,true,true);
287  MultiplyByQuadratureMetric (wsp0,wsp1);
288  IProductWRTBase_SumFacKernel (base0,base1,base2,wsp1,
289  outarray,wsp2,true,true,true);
290  LaplacianMatrixOp_MatFree_Kernel(wsp0,wsp1,wsp2);
291  }
292  else
293  {
294  // specialised implementation for the classical spectral
295  // element method
296  MultiplyByQuadratureMetric (inarray,outarray);
297  LaplacianMatrixOp_MatFree_Kernel(inarray,wsp1,wsp2);
298  }
299 
300  // outarray = lambda * outarray + wsp1
301  // = (lambda * M + L ) * u_hat
302  Vmath::Svtvp(m_ncoeffs,lambda,&outarray[0],1,&wsp1[0],1,
303  &outarray[0],1);
304  }
305  else
306  {
308  }
309 
310  }
311 
313  const int id) const
314  {
315  return v_GetFaceNormal(id);
316  }
317 
318  const NormalVector & StdExpansion3D::v_GetFaceNormal(const int face) const
319  {
320  auto x = m_faceNormals.find(face);
321  ASSERTL0 (x != m_faceNormals.end(),
322  "face normal not computed.");
323  return x->second;
324  }
325 
327  const Array<OneD, const NekDouble>& inarray)
328  {
329  const int nqtot = GetTotPoints();
331  MultiplyByStdQuadratureMetric(inarray, tmp);
332  return Vmath::Vsum(nqtot, tmp, 1);
333  }
334 
335 
337  {
338  m_negatedNormals[face] = true;
339  for (int i = 0; i < GetCoordim(); ++i)
340  {
341  Vmath::Neg(m_faceNormals[face][i].num_elements(),
342  m_faceNormals[face][i], 1);
343  }
344  }
345 
347  {
348  return m_negatedNormals[face];
349  }
350 
352  const int facedir,
353  const LibUtilities::BasisType faceDirBasisType,
354  const int numpoints,
355  const int nummodes)
356  {
357  boost::ignore_unused(facedir);
358 
359  switch(faceDirBasisType)
360  {
362  {
363  const LibUtilities::PointsKey pkey(
365  return LibUtilities::BasisKey(
366  LibUtilities::eModified_A, nummodes, pkey);
367  }
370  {
371  const LibUtilities::PointsKey pkey(
373  return LibUtilities::BasisKey(
374  LibUtilities::eModified_A, nummodes, pkey);
375  }
377  {
378  const LibUtilities::PointsKey pkey(
380  return LibUtilities::BasisKey(
381  LibUtilities::eGLL_Lagrange, nummodes, pkey);
382  }
384  {
385  const LibUtilities::PointsKey pkey(
387  return LibUtilities::BasisKey(
388  LibUtilities::eOrtho_A, nummodes, pkey);
389  }
392  {
393  const LibUtilities::PointsKey pkey(
395  return LibUtilities::BasisKey(
396  LibUtilities::eOrtho_A, nummodes, pkey);
397  }
398  default:
399  {
400  ASSERTL0(false, "expansion type unknown");
401  break;
402  }
403  }
404 
405  // Keep things happy by returning a value.
407  }
408 
410  const int facedir,
411  const LibUtilities::BasisType faceDirBasisType,
412  const int numpoints,
413  const int nummodes)
414  {
415  switch(faceDirBasisType)
416  {
418  {
419  const LibUtilities::PointsKey pkey(
421  return LibUtilities::BasisKey(
422  LibUtilities::eModified_A, nummodes, pkey);
423  }
427  {
428  switch (facedir)
429  {
430  case 0:
431  {
432  const LibUtilities::PointsKey pkey(
433  numpoints+1,
435  return LibUtilities::BasisKey(
436  LibUtilities::eModified_A, nummodes, pkey);
437  }
438  case 1:
439  {
440 // const LibUtilities::PointsKey pkey(
441 // numpoints+1,
442 // LibUtilities::eGaussLobattoLegendre);
443  const LibUtilities::PointsKey pkey(
444  numpoints,
446  return LibUtilities::BasisKey(
447  LibUtilities::eModified_B, nummodes, pkey);
448  }
449  default:
450  {
451 
452  ASSERTL0(false,"invalid value to flag");
453  break;
454  }
455  }
456  break;
457  }
458 
460  {
461  switch (facedir)
462  {
463  case 0:
464  {
465  const LibUtilities::PointsKey pkey(
466  numpoints,
468  return LibUtilities::BasisKey(
469  LibUtilities::eOrtho_A, nummodes, pkey);
470  }
471  case 1:
472  {
473  const LibUtilities::PointsKey pkey(
474  numpoints,
476  return LibUtilities::BasisKey(
477  LibUtilities::eOrtho_B, nummodes, pkey);
478  }
479  default:
480  {
481  ASSERTL0(false,"invalid value to flag");
482  break;
483  }
484  }
485  break;
486  }
487 
492  {
493  switch (facedir)
494  {
495  case 0:
496  {
497  const LibUtilities::PointsKey pkey(
498  numpoints,
500  return LibUtilities::BasisKey(
501  LibUtilities::eOrtho_A, nummodes, pkey);
502  }
503  case 1:
504  {
505  const LibUtilities::PointsKey pkey(
506  numpoints,
508  return LibUtilities::BasisKey(
509  LibUtilities::eOrtho_B, nummodes, pkey);
510  }
511  default:
512  {
513  ASSERTL0(false,"invalid value to flag");
514  break;
515  }
516  }
517  break;
518  }
519  default:
520  {
521  ASSERTL0(false,"expansion type unknown");
522  break;
523  }
524  }
525 
526  // Keep things happy by returning a value.
528  }
529  }//end namespace
530 }//end namespace
void HelmholtzMatrixOp_MatFree_GenericImpl(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
void LaplacianMatrixOp_MatFree_GenericImpl(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
Principle Modified Functions .
Definition: BasisType.h:50
void BwdTrans_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0, bool doCheckCollDir1, bool doCheckCollDir2)
virtual void v_LaplacianMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
Principle Modified Functions .
Definition: BasisType.h:52
void MultiplyByQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: StdExpansion.h:945
const NormalVector & v_GetFaceNormal(const int face) const
void MultiplyByStdQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: StdExpansion.h:952
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
LibUtilities::BasisKey EvaluateTriFaceBasisKey(const int facedir, const LibUtilities::BasisType faceDirBasisType, const int numpoints, const int nummodes)
Principle Modified Functions .
Definition: BasisType.h:48
void LocCoordToLocCollapsed(const Array< OneD, const NekDouble > &xi, Array< OneD, NekDouble > &eta)
Convert local cartesian coordinate xi into local collapsed coordinates eta.
static void Dgemm(const char &transa, const char &transb, const int &m, const int &n, const int &k, const double &alpha, const double *a, const int &lda, const double *b, const int &ldb, const double &beta, double *c, const int &ldc)
BLAS level 3: Matrix-matrix multiply C = A x B where A[m x n], B[n x k], C[m x k].
Definition: Blas.hpp:213
virtual bool v_FaceNormalNegated(const int face)
virtual void v_BwdTrans_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0, bool doCheckCollDir1, bool doCheckCollDir2)=0
Gauss Radau pinned at x=-1, .
Definition: PointsType.h:58
const NormalVector & v_GetSurfaceNormal(const int id) const
Principle Orthogonal Functions .
Definition: BasisType.h:46
std::map< int, bool > m_negatedNormals
void PhysTensorDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray_d1, Array< OneD, NekDouble > &outarray_d2, Array< OneD, NekDouble > &outarray_d3)
Calculate the 3D derivative in the local tensor/collapsed coordinate at the physical points...
The base class for all shapes.
Definition: StdExpansion.h:68
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)
static const NekDouble kNekZeroTol
LibUtilities::BasisKey EvaluateQuadFaceBasisKey(const int facedir, const LibUtilities::BasisType faceDirBasisType, const int numpoints, const int nummodes)
Principle Modified Functions .
Definition: BasisType.h:49
virtual NekDouble v_Integral(const Array< OneD, const NekDouble > &inarray)
Integrates the specified function over the domain.
Principle Orthogonal Functions .
Definition: BasisType.h:47
Principle Orthogonal Functions .
Definition: BasisType.h:45
Defines a specification for a set of points.
Definition: Points.h:59
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:399
double NekDouble
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:168
void LaplacianMatrixOp_MatFree_Kernel(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp)
std::map< int, NormalVector > m_faceNormals
NekDouble GetConstFactor(const ConstFactorType &factor) const
Definition: StdMatrixKey.h:121
Principle Orthogonal Functions .
Definition: BasisType.h:51
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:140
virtual void v_NegateFaceNormal(const int face)
bool ConstFactorExists(const ConstFactorType &factor) const
Definition: StdMatrixKey.h:130
#define WARNINGL2(condition, msg)
Definition: ErrorUtil.hpp:275
virtual NekDouble v_PhysEvaluate(const Array< OneD, const NekDouble > &coords, const Array< OneD, const NekDouble > &physvals)
This function evaluates the expansion at a single (arbitrary) point of the domain.
static const BasisKey NullBasisKey(eNoBasisType, 0, NullPointsKey)
Defines a null basis with no type or points.
int GetTotPoints() const
This function returns the total number of quadrature points used in the element.
Definition: StdExpansion.h:140
Lagrange for SEM basis .
Definition: BasisType.h:54
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition: Vmath.cpp:740
virtual void v_HelmholtzMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
Array< OneD, LibUtilities::BasisSharedPtr > m_base
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
Describes the specification for a Basis.
Definition: Basis.h:49
1D Gauss-Lobatto-Legendre quadrature points
Definition: PointsType.h:51
virtual void v_IProductWRTBase_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &base2, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0, bool doCheckCollDir1, bool doCheckCollDir2)=0