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