Nektar++
StdExpansion2D.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File StdExpansion2D.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 2D expansion. Typically this inolves physiocal
33 // space operations.
34 //
35 ///////////////////////////////////////////////////////////////////////////////
36 
38 
39 #ifdef max
40 #undef max
41 #endif
42 
43 namespace Nektar
44 {
45  namespace StdRegions
46  {
47 
49  {
50  }
51 
53  const LibUtilities::BasisKey &Ba,
54  const LibUtilities::BasisKey &Bb):
55  StdExpansion(numcoeffs,2, Ba, Bb)
56  {
57  }
58 
60  StdExpansion(T)
61  {
62  }
63 
65  {
66  }
67 
68  //----------------------------
69  // Differentiation Methods
70  //----------------------------
72  Array<OneD, NekDouble> &outarray_d0,
73  Array<OneD, NekDouble> &outarray_d1)
74  {
75  int nquad0 = m_base[0]->GetNumPoints();
76  int nquad1 = m_base[1]->GetNumPoints();
77 
78  if (outarray_d0.size() > 0) // calculate du/dx_0
79  {
80  DNekMatSharedPtr D0 = m_base[0]->GetD();
81  if(inarray.data() == outarray_d0.data())
82  {
83  Array<OneD, NekDouble> wsp(nquad0 * nquad1);
84  Vmath::Vcopy(nquad0 * nquad1,inarray.get(),1,wsp.get(),1);
85  Blas::Dgemm('N', 'N', nquad0, nquad1, nquad0, 1.0,
86  &(D0->GetPtr())[0], nquad0, &wsp[0], nquad0, 0.0,
87  &outarray_d0[0], nquad0);
88  }
89  else
90  {
91  Blas::Dgemm('N', 'N', nquad0, nquad1, nquad0, 1.0,
92  &(D0->GetPtr())[0], nquad0, &inarray[0], nquad0, 0.0,
93  &outarray_d0[0], nquad0);
94  }
95  }
96 
97  if (outarray_d1.size() > 0) // calculate du/dx_1
98  {
99  DNekMatSharedPtr D1 = m_base[1]->GetD();
100  if(inarray.data() == outarray_d1.data())
101  {
102  Array<OneD, NekDouble> wsp(nquad0 * nquad1);
103  Vmath::Vcopy(nquad0 * nquad1,inarray.get(),1,wsp.get(),1);
104  Blas:: Dgemm('N', 'T', nquad0, nquad1, nquad1, 1.0, &wsp[0], nquad0,
105  &(D1->GetPtr())[0], nquad1, 0.0, &outarray_d1[0], nquad0);
106  }
107  else
108  {
109  Blas:: Dgemm('N', 'T', nquad0, nquad1, nquad1, 1.0, &inarray[0], nquad0,
110  &(D1->GetPtr())[0], nquad1, 0.0, &outarray_d1[0], nquad0);
111  }
112  }
113  }
114 
116  const Array<OneD, const NekDouble> &coords,
117  const Array<OneD, const NekDouble> &physvals)
118  {
119  ASSERTL2(coords[0] > -1 - NekConstants::kNekZeroTol,
120  "coord[0] < -1");
121  ASSERTL2(coords[0] < 1 + NekConstants::kNekZeroTol,
122  "coord[0] > 1");
123  ASSERTL2(coords[1] > -1 - NekConstants::kNekZeroTol,
124  "coord[1] < -1");
125  ASSERTL2(coords[1] < 1 + NekConstants::kNekZeroTol,
126  "coord[1] > 1");
127 
128  Array<OneD, NekDouble> coll(2);
129  LocCoordToLocCollapsed(coords,coll);
130 
131  const int nq0 = m_base[0]->GetNumPoints();
132  const int nq1 = m_base[1]->GetNumPoints();
133 
134  Array<OneD, NekDouble> wsp(nq1);
135  for (int i = 0; i < nq1; ++i)
136  {
137  wsp[i] = StdExpansion::BaryEvaluate<0>(
138  coll[0], &physvals[0] + i * nq0);
139  }
140 
141  return StdExpansion::BaryEvaluate<1>(coll[1], &wsp[0]);
142  }
143 
146  const Array<OneD, const NekDouble> &physvals)
147  {
148  NekDouble val;
149  int i;
150  int nq0 = m_base[0]->GetNumPoints();
151  int nq1 = m_base[1]->GetNumPoints();
152  Array<OneD, NekDouble> wsp1(nq1);
153 
154  // interpolate first coordinate direction
155  for (i = 0; i < nq1;++i)
156  {
157  wsp1[i] = Blas::Ddot(nq0, &(I[0]->GetPtr())[0], 1,
158  &physvals[i * nq0], 1);
159  }
160 
161  // interpolate in second coordinate direction
162  val = Blas::Ddot(nq1, I[1]->GetPtr(), 1, wsp1, 1);
163 
164  return val;
165  }
166 
167  //////////////////////////////
168  // Integration Methods
169  //////////////////////////////
170 
174  {
175  int i;
176  NekDouble Int = 0.0;
177  int nquad0 = m_base[0]->GetNumPoints();
178  int nquad1 = m_base[1]->GetNumPoints();
179  Array<OneD, NekDouble> tmp(nquad0 * nquad1);
180 
181  // multiply by integration constants
182  for (i = 0; i < nquad1; ++i)
183  {
184  Vmath::Vmul(nquad0, &inarray[0] + i*nquad0, 1, w0.get(),
185  1, &tmp[0] + i*nquad0, 1);
186  }
187 
188  for (i = 0; i < nquad0; ++i)
189  {
190  Vmath::Vmul(nquad1, &tmp[0]+ i, nquad0, w1.get(), 1,
191  &tmp[0] + i, nquad0);
192  }
193  Int = Vmath::Vsum(nquad0 * nquad1, tmp, 1);
194 
195  return Int;
196  }
197 
199  const Array<OneD, const NekDouble>& base0,
200  const Array<OneD, const NekDouble>& base1,
201  const Array<OneD, const NekDouble>& inarray,
202  Array<OneD, NekDouble> &outarray,
204  bool doCheckCollDir0,
205  bool doCheckCollDir1)
206  {
207  v_BwdTrans_SumFacKernel(base0, base1, inarray, outarray, wsp, doCheckCollDir0, doCheckCollDir1);
208  }
209 
211  const Array<OneD, const NekDouble>& base0,
212  const Array<OneD, const NekDouble>& base1,
213  const Array<OneD, const NekDouble>& inarray,
214  Array<OneD, NekDouble> &outarray,
216  bool doCheckCollDir0,
217  bool doCheckCollDir1)
218  {
219  v_IProductWRTBase_SumFacKernel(base0, base1, inarray, outarray, wsp, doCheckCollDir0, doCheckCollDir1);
220  }
221 
223  const int dir,
224  DNekMatSharedPtr &mat)
225  {
226  ASSERTL1((dir==0) || (dir==1),
227  "Invalid direction.");
228 
229  int nquad0 = m_base[0]->GetNumPoints();
230  int nquad1 = m_base[1]->GetNumPoints();
231  int nqtot = nquad0*nquad1;
232  int nmodes0 = m_base[0]->GetNumModes();
233 
234  Array<OneD, NekDouble> tmp1(2*nqtot+m_ncoeffs+nmodes0*nquad1,0.0);
235  Array<OneD, NekDouble> tmp3(tmp1 + 2*nqtot);
236  Array<OneD, NekDouble> tmp4(tmp1 + 2*nqtot+m_ncoeffs);
237 
238  switch(dir)
239  {
240  case 0:
241  for(int i=0; i<nqtot;i++)
242  {
243  tmp1[i] = 1.0;
245  m_base[0]->GetDbdata(), m_base[1]->GetBdata(),
246  tmp1, tmp3, tmp4, false, true);
247  tmp1[i] = 0.0;
248 
249  for(int j=0; j<m_ncoeffs;j++)
250  {
251  (*mat)(j,i) = tmp3[j];
252  }
253  }
254  break;
255  case 1:
256  for(int i=0; i<nqtot;i++)
257  {
258  tmp1[i] = 1.0;
260  m_base[0]->GetBdata() , m_base[1]->GetDbdata(),
261  tmp1, tmp3, tmp4, true, false);
262  tmp1[i] = 0.0;
263 
264  for(int j=0; j<m_ncoeffs;j++)
265  {
266  (*mat)(j,i) = tmp3[j];
267  }
268  }
269  break;
270  default:
271  NEKERROR(ErrorUtil::efatal, "Not a 2D expansion.");
272  break;
273  }
274  }
275 
277  const Array<OneD, const NekDouble> &inarray,
278  Array<OneD,NekDouble> &outarray,
279  const StdRegions::StdMatrixKey &mkey)
280  {
283  {
284  using std::max;
285 
286  // This implementation is only valid when there are no
287  // coefficients associated to the Laplacian operator
288  int nquad0 = m_base[0]->GetNumPoints();
289  int nquad1 = m_base[1]->GetNumPoints();
290  int nqtot = nquad0*nquad1;
291  int nmodes0 = m_base[0]->GetNumModes();
292  int nmodes1 = m_base[1]->GetNumModes();
293  int wspsize = max(max(max(nqtot,m_ncoeffs),nquad1*nmodes0),nquad0*nmodes1);
294 
295  const Array<OneD, const NekDouble>& base0 = m_base[0]->GetBdata();
296  const Array<OneD, const NekDouble>& base1 = m_base[1]->GetBdata();
297 
298  // Allocate temporary storage
299  Array<OneD,NekDouble> wsp0(4*wspsize); // size wspsize
300  Array<OneD,NekDouble> wsp1(wsp0+wspsize); // size 3*wspsize
301 
302  if(!(m_base[0]->Collocation() && m_base[1]->Collocation()))
303  {
304  // LAPLACIAN MATRIX OPERATION
305  // wsp0 = u = B * u_hat
306  // wsp1 = du_dxi1 = D_xi1 * wsp0 = D_xi1 * u
307  // wsp2 = du_dxi2 = D_xi2 * wsp0 = D_xi2 * u
308  BwdTrans_SumFacKernel(base0,base1,inarray,wsp0,wsp1,true,true);
309  LaplacianMatrixOp_MatFree_Kernel(wsp0, outarray, wsp1);
310  }
311  else
312  {
313  LaplacianMatrixOp_MatFree_Kernel(inarray, outarray, wsp1);
314  }
315  }
316  else
317  {
319  inarray,outarray,mkey);
320  }
321  }
322 
323 
324 
326  const Array<OneD, const NekDouble> &inarray,
327  Array<OneD,NekDouble> &outarray,
328  const StdRegions::StdMatrixKey &mkey)
329  {
332  {
333  using std::max;
334 
335  int nquad0 = m_base[0]->GetNumPoints();
336  int nquad1 = m_base[1]->GetNumPoints();
337  int nqtot = nquad0*nquad1;
338  int nmodes0 = m_base[0]->GetNumModes();
339  int nmodes1 = m_base[1]->GetNumModes();
340  int wspsize = max(max(max(nqtot,m_ncoeffs),nquad1*nmodes0),
341  nquad0*nmodes1);
342  NekDouble lambda =
344 
345  const Array<OneD, const NekDouble>& base0 = m_base[0]->GetBdata();
346  const Array<OneD, const NekDouble>& base1 = m_base[1]->GetBdata();
347 
348  // Allocate temporary storage
349  Array<OneD,NekDouble> wsp0(5*wspsize); // size wspsize
350  Array<OneD,NekDouble> wsp1(wsp0 + wspsize); // size wspsize
351  Array<OneD,NekDouble> wsp2(wsp0 + 2*wspsize);// size 3*wspsize
352 
353  if (!(m_base[0]->Collocation() && m_base[1]->Collocation()))
354  {
355  // MASS MATRIX OPERATION
356  // The following is being calculated:
357  // wsp0 = B * u_hat = u
358  // wsp1 = W * wsp0
359  // outarray = B^T * wsp1 = B^T * W * B * u_hat = M * u_hat
360  BwdTrans_SumFacKernel (base0, base1, inarray,
361  wsp0, wsp2,true,true);
362  MultiplyByQuadratureMetric (wsp0, wsp1);
363  IProductWRTBase_SumFacKernel(base0, base1, wsp1, outarray,
364  wsp2, true, true);
365 
366  LaplacianMatrixOp_MatFree_Kernel(wsp0, wsp1, wsp2);
367  }
368  else
369  {
370  MultiplyByQuadratureMetric(inarray,outarray);
371  LaplacianMatrixOp_MatFree_Kernel(inarray, wsp1, wsp2);
372  }
373 
374  // outarray = lambda * outarray + wsp1
375  // = (lambda * M + L ) * u_hat
376  Vmath::Svtvp(m_ncoeffs, lambda, &outarray[0], 1,
377  &wsp1[0], 1, &outarray[0], 1);
378  }
379  else
380  {
382  inarray,outarray,mkey);
383  }
384  }
385 
386  } //end namespace
387 } //end namespace
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:250
#define ASSERTL2(condition, msg)
Assert Level 2 – Debugging which is used FULLDEBUG compilation mode. This level assert is designed to...
Definition: ErrorUtil.hpp:274
Describes the specification for a Basis.
Definition: Basis.h:50
virtual void v_IProductWRTBase_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0, bool doCheckCollDir1)=0
void PhysTensorDeriv(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray_d0, Array< OneD, NekDouble > &outarray_d1)
Calculate the 2D derivative in the local tensor/collapsed coordinate at the physical points.
virtual void v_BwdTrans_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0, bool doCheckCollDir1)=0
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.
NekDouble Integral(const Array< OneD, const NekDouble > &inarray, const Array< OneD, const NekDouble > &w0, const Array< OneD, const NekDouble > &w1)
void BwdTrans_SumFacKernel(const Array< OneD, const NekDouble > &base0, const Array< OneD, const NekDouble > &base1, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp, bool doCheckCollDir0=true, bool doCheckCollDir1=true)
virtual void v_HelmholtzMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
virtual void v_LaplacianMatrixOp_MatFree(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdRegions::StdMatrixKey &mkey)
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)
virtual void v_GenStdMatBwdDeriv(const int dir, DNekMatSharedPtr &mat)
The base class for all shapes.
Definition: StdExpansion.h:63
void LaplacianMatrixOp_MatFree_GenericImpl(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
void LocCoordToLocCollapsed(const Array< OneD, const NekDouble > &xi, Array< OneD, NekDouble > &eta)
Convert local cartesian coordinate xi into local collapsed coordinates eta.
Definition: StdExpansion.h:982
void MultiplyByQuadratureMetric(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray)
Definition: StdExpansion.h:733
void HelmholtzMatrixOp_MatFree_GenericImpl(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, const StdMatrixKey &mkey)
Array< OneD, LibUtilities::BasisSharedPtr > m_base
void LaplacianMatrixOp_MatFree_Kernel(const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, Array< OneD, NekDouble > &wsp)
NekDouble GetConstFactor(const ConstFactorType &factor) const
Definition: StdMatrixKey.h:121
bool ConstFactorExists(const ConstFactorType &factor) const
Definition: StdMatrixKey.h:130
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:197
static void Dgemm(const char &transa, const char &transb, const int &m, const int &n, const int &k, const double &alpha, const double *a, const int &lda, const double *b, const int &ldb, const double &beta, double *c, const int &ldc)
BLAS level 3: Matrix-matrix multiply C = A x B where op(A)[m x k], op(B)[k x n], C[m x n] DGEMM perfo...
Definition: Blas.hpp:394
static const NekDouble kNekZeroTol
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
double NekDouble
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.cpp:192
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:565
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition: Vmath.cpp:846
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1199