Nektar++
Expansion1D.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File Expansion1D.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: File for Expansion1D routines
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <boost/core/ignore_unused.hpp>
36 
39 
40 using namespace std;
41 
42 namespace Nektar
43 {
44  namespace LocalRegions
45  {
46  void Expansion1D::v_NegateVertexNormal(const int vertex)
47  {
48  m_negatedNormals[vertex] = true;
49  for (int i = 0; i < GetCoordim(); ++i)
50  {
51  Vmath::Neg(m_vertexNormals[vertex][i].num_elements(),
52  m_vertexNormals[vertex][i], 1);
53  }
54  }
55 
56  bool Expansion1D::v_VertexNormalNegated(const int vertex)
57  {
58  return m_negatedNormals[vertex];
59  }
60 
61  DNekMatSharedPtr Expansion1D::v_GenMatrix(const StdRegions::StdMatrixKey &mkey)
62  {
63  DNekMatSharedPtr returnval;
64 
65  switch(mkey.GetMatrixType())
66  {
68  {
69  ASSERTL1(IsBoundaryInteriorExpansion(),
70  "HybridDGHelmholtz matrix not set up "
71  "for non boundary-interior expansions");
72  int i;
75  int ncoeffs = GetNcoeffs();
76 
77  int coordim = GetCoordim();
78 
79  DNekScalMat &invMass = *GetLocMatrix(StdRegions::eInvMass);
83  DNekMat LocMat(ncoeffs,ncoeffs);
84 
85  returnval = MemoryManager<DNekMat>::AllocateSharedPtr(ncoeffs,ncoeffs);
86  DNekMat &Mat = *returnval;
87 
88  Vmath::Zero(ncoeffs*ncoeffs,Mat.GetPtr(),1);
89 
90  for(i=0; i < coordim; ++i)
91  {
92  DNekScalMat &Dmat = *GetLocMatrix(DerivType[i]);
93 
94  Mat = Mat + Dmat*invMass*Transpose(Dmat);
95  }
96 
97  // Add end Mass Matrix Contribution
98  DNekScalMat &Mass = *GetLocMatrix(StdRegions::eMass);
99  Mat = Mat + lambdaval*Mass;
100 
102  GetBoundaryMap(bmap);
103 
104  // Add tau*F_e using elemental mass matrices
105  for(i = 0; i < 2; ++i)
106  {
107  Mat(bmap[i],bmap[i]) = Mat(bmap[i],bmap[i]) + tau;
108  }
109  }
110  break;
112  {
113  int j,k;
114  int nbndry = NumDGBndryCoeffs();
115  int ncoeffs = GetNcoeffs();
119 
120  Array<OneD,NekDouble> lambda(nbndry);
121  DNekVec Lambda(nbndry,lambda,eWrapper);
122  Array<OneD,NekDouble> ulam(ncoeffs);
123  DNekVec Ulam(ncoeffs,ulam,eWrapper);
124  Array<OneD,NekDouble> f(ncoeffs);
125  DNekVec F(ncoeffs,f,eWrapper);
126 
127  // declare matrix space
128  returnval = MemoryManager<DNekMat>::AllocateSharedPtr(ncoeffs,nbndry);
129  DNekMat &Umat = *returnval;
130 
131  // Helmholtz matrix
132  DNekScalMat &invHmat = *GetLocMatrix(StdRegions::eInvHybridDGHelmholtz, factors);
133 
134  // for each degree of freedom of the lambda space
135  // calculate Umat entry
136  // Generate Lambda to U_lambda matrix
137  for(j = 0; j < nbndry; ++j)
138  {
139  Vmath::Zero(nbndry,&lambda[0],1);
140  Vmath::Zero(ncoeffs,&f[0],1);
141  lambda[j] = 1.0;
142 
143  AddHDGHelmholtzTraceTerms(factors[StdRegions::eFactorTau],lambda,f);
144 
145  Ulam = invHmat*F; // generate Ulam from lambda
146 
147  // fill column of matrix
148  for(k = 0; k < ncoeffs; ++k)
149  {
150  Umat(k,j) = Ulam[k];
151  }
152  }
153  }
154  break;
158  {
159  int j = 0;
160  int k = 0;
161  int dir = 0;
162  int nbndry = NumDGBndryCoeffs();
163  int ncoeffs = GetNcoeffs();
164 
165  Array<OneD,NekDouble> lambda(nbndry);
166  DNekVec Lambda(nbndry,lambda,eWrapper);
167 
168  Array<OneD,NekDouble> ulam(ncoeffs);
169  DNekVec Ulam(ncoeffs,ulam,eWrapper);
170  Array<OneD,NekDouble> f(ncoeffs);
171  DNekVec F(ncoeffs,f,eWrapper);
175 
176  // declare matrix space
177  returnval = MemoryManager<DNekMat>::AllocateSharedPtr(ncoeffs,nbndry);
178  DNekMat &Qmat = *returnval;
179 
180  // Lambda to U matrix
181  DNekScalMat &lamToU = *GetLocMatrix(StdRegions::eHybridDGLamToU, factors);
182 
183  // Inverse mass matrix
184  DNekScalMat &invMass = *GetLocMatrix(StdRegions::eInvMass);
185 
186  //Weak Derivative matrix
188  switch(mkey.GetMatrixType())
189  {
191  dir = 0;
192  Dmat = GetLocMatrix(StdRegions::eWeakDeriv0);
193  break;
195  dir = 1;
196  Dmat = GetLocMatrix(StdRegions::eWeakDeriv1);
197  break;
199  dir = 2;
200  Dmat = GetLocMatrix(StdRegions::eWeakDeriv2);
201  break;
202  default:
203  ASSERTL0(false,"Direction not known");
204  break;
205  }
206 
207  // for each degree of freedom of the lambda space
208  // calculate Qmat entry
209  // Generate Lambda to Q_lambda matrix
210  for(j = 0; j < nbndry; ++j)
211  {
212  Vmath::Zero(nbndry,&lambda[0],1);
213  lambda[j] = 1.0;
214 
215  // for lambda[j] = 1 this is the solution to ulam
216  for(k = 0; k < ncoeffs; ++k)
217  {
218  Ulam[k] = lamToU(k,j);
219  }
220 
221 
222  // -D^T ulam
223  Vmath::Neg(ncoeffs,&ulam[0],1);
224  F = Transpose(*Dmat)*Ulam;
225 
226  // + \tilde{G} \lambda
227  AddNormTraceInt(dir,lambda,f);
228 
229  // multiply by inverse mass matrix
230  Ulam = invMass*F;
231 
232  // fill column of matrix (Qmat is in column major format)
233  Vmath::Vcopy(ncoeffs,&ulam[0],1,&(Qmat.GetPtr())[0]+j*ncoeffs,1);
234  }
235  }
236  break;
238  {
239  int j;
240  int nbndry = NumBndryCoeffs();
241 
245 
247  Array<OneD, NekDouble> lam(2);
248  GetBoundaryMap(bmap);
249 
250  // declare matrix space
251  returnval = MemoryManager<DNekMat>::AllocateSharedPtr(nbndry, nbndry);
252  DNekMat &BndMat = *returnval;
253 
254  // Matrix to map Lambda to U
255  DNekScalMat &LamToU = *GetLocMatrix(StdRegions::eHybridDGLamToU, factors);
256 
257  // Matrix to map Lambda to Q
258  DNekScalMat &LamToQ = *GetLocMatrix(StdRegions::eHybridDGLamToQ0, factors);
259 
260  lam[0] = 1.0; lam[1] = 0.0;
261  for(j = 0; j < nbndry; ++j)
262  {
263  BndMat(0,j) = -LamToQ(bmap[0],j) - factors[StdRegions::eFactorTau]*(LamToU(bmap[0],j) - lam[j]);
264  }
265 
266  lam[0] = 0.0; lam[1] = 1.0;
267  for(j = 0; j < nbndry; ++j)
268  {
269  BndMat(1,j) = LamToQ(bmap[1],j) - factors[StdRegions::eFactorTau]*(LamToU(bmap[1],j) - lam[j]);
270  }
271  }
272  break;
273  default:
274  ASSERTL0(false,"This matrix type cannot be generated from this class");
275  break;
276  }
277 
278  return returnval;
279  }
280 
281  void Expansion1D::AddNormTraceInt(const int dir,
283  Array<OneD,NekDouble> &outarray)
284  {
285  boost::ignore_unused(dir);
286 
287  int k;
288  int nbndry = NumBndryCoeffs();
289  int nquad = GetNumPoints(0);
290  const Array<OneD, const NekDouble> &Basis = GetBasis(0)->GetBdata();
292 
293  GetBoundaryMap(vmap);
294 
295  // add G \lambda term (can assume G is diagonal since one
296  // of the basis is zero at boundary otherwise)
297  for(k = 0; k < nbndry; ++k)
298  {
299  outarray[vmap[k]] += (Basis[(vmap[k]+1)*nquad-1]*Basis[(vmap[k]+1)*nquad-1] - Basis[vmap[k]*nquad]*Basis[vmap[k]*nquad])*inarray[vmap[k]];
300  }
301  }
302 
303  void Expansion1D::AddHDGHelmholtzTraceTerms(const NekDouble tau,
304  const Array<OneD,const NekDouble> &inarray, Array<OneD,NekDouble> &outarray)
305  {
306  int i,n;
307  int nbndry = NumBndryCoeffs();
308  int nquad = GetNumPoints(0);
309  int ncoeffs = GetNcoeffs();
310  int coordim = GetCoordim();
312 
313  ASSERTL0(&inarray[0] != &outarray[0],"Input and output arrays use the same memory");
314 
315 
316  const Array<OneD, const NekDouble> &Basis = GetBasis(0)->GetBdata();
317  DNekScalMat &invMass = *GetLocMatrix(StdRegions::eInvMass);
318 
319  GetBoundaryMap(vmap);
320 
321  // Add F = \tau <phi_i,phi_j> (note phi_i is zero if phi_j is non-zero)
322  for(i = 0; i < nbndry; ++i)
323  {
324  outarray[vmap[i]] += tau*Basis[(vmap[i]+1)*nquad-1]*Basis[(vmap[i]+1)*nquad-1]*inarray[vmap[i]];
325  outarray[vmap[i]] += tau*Basis[vmap[i]*nquad]*Basis[vmap[i]*nquad]*inarray[vmap[i]];
326  }
327 
328 
329  //===============================================================
330  // Add -\sum_i D_i^T M^{-1} G_i + E_i M^{-1} G_i =
331  // \sum_i D_i M^{-1} G_i term
332 
336  Array<OneD, NekDouble> tmpcoeff(ncoeffs,0.0);
337  DNekVec Coeffs (ncoeffs,outarray,eWrapper);
338  DNekVec Tmpcoeff(ncoeffs,tmpcoeff,eWrapper);
339 
340  for(n = 0; n < coordim; ++n)
341  {
342  // evaluate M^{-1} G
343  for(i = 0; i < ncoeffs; ++i)
344  {
345  // lower boundary (negative normal)
346  tmpcoeff[i] -= invMass(i,vmap[0])*Basis[vmap[0]*nquad]*Basis[vmap[0]*nquad]*inarray[vmap[0]];
347 
348  // upper boundary (positive normal)
349  tmpcoeff[i] += invMass(i,vmap[1])*Basis[(vmap[1]+1)*nquad-1]*Basis[(vmap[1]+1)*nquad-1]*inarray[vmap[1]];
350 
351  }
352 
353  DNekScalMat &Dmat = *GetLocMatrix(DerivType[n]);
354  Coeffs = Coeffs + Dmat*Tmpcoeff;
355  }
356  }
357 
358  void Expansion1D::v_AddRobinMassMatrix(const int vert, const Array<OneD, const NekDouble > &primCoeffs, DNekMatSharedPtr &inoutmat)
359  {
360  ASSERTL0(IsBoundaryInteriorExpansion(),"Robin boundary conditions are only implemented for boundary-interior expanisons");
361  ASSERTL1(inoutmat->GetRows() == inoutmat->GetColumns(),
362  "Assuming that input matrix was square");
363 
364  // Get local Element mapping for vertex point
365  int map = GetVertexMap(vert);
366 
367  // Now need to identify a map which takes the local edge
368  // mass matrix to the matrix stored in inoutmat;
369  // This can currently be deduced from the size of the matrix
370  // - if inoutmat.m_rows() == v_NCoeffs() it is a full
371  // matrix system
372  // - if inoutmat.m_rows() == v_NumBndCoeffs() it is a
373  // boundary CG system
374 
375  int rows = inoutmat->GetRows();
376 
377  if (rows == GetNcoeffs())
378  {
379  // no need to do anything
380  }
381  else if(rows == NumBndryCoeffs()) // same as NumDGBndryCoeffs()
382  {
383  int i;
385  GetBoundaryMap(bmap);
386 
387  for(i = 0; i < 2; ++i)
388  {
389  if(map == bmap[i])
390  {
391  map = i;
392  break;
393  }
394  }
395  ASSERTL1(i != 2,"Did not find number in map");
396  }
397 
398  // assumes end points have unit magnitude
399  (*inoutmat)(map,map) += primCoeffs[0];
400 
401  }
402 
403  /**
404  * Given an edge and vector of element coefficients:
405  * - maps those elemental coefficients corresponding to the edge into
406  * an edge-vector.
407  * - resets the element coefficients
408  * - multiplies the edge vector by the edge mass matrix
409  * - maps the edge coefficients back onto the elemental coefficients
410  */
411  void Expansion1D::v_AddRobinEdgeContribution(const int vert, const Array<OneD, const NekDouble > &primCoeffs, Array<OneD, NekDouble> &coeffs)
412  {
413  ASSERTL1(IsBoundaryInteriorExpansion(),
414  "Not set up for non boundary-interior expansions");
415 
416  int map = GetVertexMap(vert);
417  Vmath::Zero(GetNcoeffs(), coeffs, 1);
418  coeffs[map] = primCoeffs[0];
419  }
420 
421  NekDouble Expansion1D::v_VectorFlux(
422  const Array<OneD, Array<OneD, NekDouble> > &vec)
423  {
425  &normals = GetLeftAdjacentElementExp()->
426  GetEdgeNormal(GetLeftAdjacentElementEdge());
427 
428  int nq = m_base[0]->GetNumPoints();
430  Vmath::Vmul (nq, &vec[0][0], 1, &normals[0][0], 1, &Fn[0], 1);
431  Vmath::Vvtvp(nq, &vec[1][0], 1, &normals[1][0], 1, &Fn[0], 1, &Fn[0], 1);
432 
433  return Integral(Fn);
434  }
435  } //end of namespace
436 } //end of namespace
437 
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
Represents a basis of a given type.
Definition: Basis.h:211
std::shared_ptr< DNekScalMat > DNekScalMatSharedPtr
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
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
STL namespace.
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:294
std::shared_ptr< DNekMat > DNekMatSharedPtr
Definition: NekTypeDefs.hpp:69
MatrixType GetMatrixType() const
Definition: StdMatrixKey.h:81
const Array< OneD, const NekDouble > & GetBdata() const
Return basis definition array m_bdata.
Definition: Basis.h:313
NekMatrix< InnerMatrixType, BlockMatrixTag > Transpose(NekMatrix< InnerMatrixType, BlockMatrixTag > &rhs)
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:399
double NekDouble
NekDouble GetConstFactor(const ConstFactorType &factor) const
Definition: StdMatrixKey.h:121
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:376
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
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