Nektar++
NavierStokesAdvection.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File NavierStokesAdvection.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: Evaluation of the Navier Stokes advective term
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
37 
38 using namespace std;
39 
40 namespace Nektar
41 {
42 
43  std::string NavierStokesAdvection::navierStokesAdvectionTypeLookupIds[2] = {
44  LibUtilities::SessionReader::RegisterEnumValue("SPECTRALHPDEALIASING",
45  "True", 0),
46  LibUtilities::SessionReader::RegisterEnumValue("SPECTRALHPDEALIASING",
47  "False", 1)};
48 
49  string NavierStokesAdvection::className = SolverUtils::GetAdvectionFactory().RegisterCreatorFunction("Convective", NavierStokesAdvection::create);
50  string NavierStokesAdvection::className2 = SolverUtils::GetAdvectionFactory().RegisterCreatorFunction("NonConservative", NavierStokesAdvection::create);
51 
52  /**
53  * Constructor. Creates ...
54  *
55  * \param
56  * \param
57  */
58 
59  NavierStokesAdvection::NavierStokesAdvection():
60  Advection()
61 
62  {
63 
64  }
65 
67  {
68  }
69 
70 
74  {
75  m_homogen_dealiasing = pSession->DefinesSolverInfo("dealiasing");
76 
77  pSession->MatchSolverInfo("SPECTRALHPDEALIASING","True",m_specHP_dealiasing,false);
78  pSession->MatchSolverInfo("ModeType","SingleMode",m_SingleMode,false);
79  pSession->MatchSolverInfo("ModeType","HalfMode",m_HalfMode,false);
80 
81  Advection::v_InitObject(pSession, pFields);
82  }
83 
84 
86  const int nConvectiveFields,
88  const Array<OneD, Array<OneD, NekDouble> > &advVel,
89  const Array<OneD, Array<OneD, NekDouble> > &inarray,
90  Array<OneD, Array<OneD, NekDouble> > &outarray,
91  const NekDouble &time,
92  const Array<OneD, Array<OneD, NekDouble> > &pFwd,
93  const Array<OneD, Array<OneD, NekDouble> > &pBwd)
94  {
95  int nqtot = fields[0]->GetTotPoints();
96  ASSERTL1(nConvectiveFields == inarray.size(),"Number of convective fields and Inarray are not compatible");
97 
98  // use dimension of Velocity vector to dictate dimension of operation
99  int ndim = advVel.size();
100  Array<OneD, Array<OneD, NekDouble> > AdvVel (advVel.size());
101 
102  Array<OneD, Array<OneD, NekDouble> > velocity(ndim);
103 
104 LibUtilities::Timer timer;
105 
106  for(int i = 0; i < ndim; ++i)
107  {
108  if(fields[i]->GetWaveSpace() && !m_SingleMode && !m_HalfMode &&
110  {
111  velocity[i] = Array<OneD, NekDouble>(nqtot,0.0);
112  fields[i]->HomogeneousBwdTrans(advVel[i],velocity[i]);
113  }
114  else
115  {
116  velocity[i] = advVel[i];
117  }
118  }
119 
120  int nPointsTot = fields[0]->GetNpoints();
121  Array<OneD, NekDouble> grad0,grad1,grad2,wkSp;
122 
123  NekDouble OneDptscale = 1.5; // factor to rescale 1d points in dealiasing
124 
126  {
127  // Get number of points to dealias a quadratic non-linearity
128  nPointsTot = fields[0]->Get1DScaledTotPoints(OneDptscale);
129 
130  }
131 
132  // interpolate Advection velocity
133  if(m_specHP_dealiasing) // interpolate advection field to higher space.
134  {
135  for(int i = 0; i < ndim; ++i)
136  {
137  AdvVel[i] = Array<OneD, NekDouble> (nPointsTot);
138  // interpolate infield to 3/2 dimension
139 timer.Start();
140  fields[0]->PhysInterp1DScaled(OneDptscale,velocity[i],AdvVel[i]);
141 timer.Stop();
142 timer.AccumulateRegion("Interp1DScaled");
143  }
144  }
145  else
146  {
147  for(int i = 0; i < ndim; ++i)
148  {
149  AdvVel[i] = velocity[i];
150  }
151  }
152 
153  wkSp = Array<OneD, NekDouble> (nPointsTot);
154 
155  // Evaluate V\cdot Grad(u)
156  switch(ndim)
157  {
158  case 1:
159  grad0 = Array<OneD, NekDouble> (fields[0]->GetNpoints());
160  for(int n = 0; n < nConvectiveFields; ++n)
161  {
162  fields[0]->PhysDeriv(inarray[n],grad0);
163  if(m_specHP_dealiasing) // interpolate gradient field
164  {
165  Array<OneD, NekDouble> Outarray(nPointsTot);
166  fields[0]->PhysInterp1DScaled(OneDptscale,grad0,wkSp);
167  Vmath::Vmul (nPointsTot,wkSp,1,AdvVel[0],1,Outarray,1);
168  // Galerkin project solution back to origianl spac
169 timer.Start();
170  fields[0]->PhysGalerkinProjection1DScaled(OneDptscale,Outarray,outarray[n]);
171 timer.Stop();
172 timer.AccumulateRegion("GalerinProject");
173  }
174  else
175  {
176  Vmath::Vmul(nPointsTot,grad0,1,AdvVel[0],1,outarray[n],1);
177  }
178  }
179  break;
180  case 2:
181  grad0 = Array<OneD, NekDouble> (fields[0]->GetNpoints());
182  grad1 = Array<OneD, NekDouble> (fields[0]->GetNpoints());
183  for(int n = 0; n < nConvectiveFields; ++n)
184  {
185  fields[0]->PhysDeriv(inarray[n],grad0,grad1);
186 
187  if(m_specHP_dealiasing) // interpolate gradient field
188  {
189  Array<OneD, NekDouble> Outarray(nPointsTot);
190  fields[0]->PhysInterp1DScaled(OneDptscale,grad0,wkSp);
191  Vmath::Vmul (nPointsTot,wkSp,1,AdvVel[0],1,Outarray,1);
192 timer.Start();
193  fields[0]->PhysInterp1DScaled(OneDptscale,grad1,wkSp);
194 timer.Stop();
195 timer.AccumulateRegion("Interp1DScaled");
196  Vmath::Vvtvp(nPointsTot,wkSp,1,AdvVel[1],1,Outarray,1,Outarray,1);
197  // Galerkin project solution back to original space
198 timer.Start();
199  fields[0]->PhysGalerkinProjection1DScaled(OneDptscale,Outarray,outarray[n]);
200 timer.Stop();
201 timer.AccumulateRegion("GalerinProject");
202  }
203  else
204  {
205  Vmath::Vmul (nPointsTot,grad0,1,AdvVel[0],1,outarray[n],1);
206  Vmath::Vvtvp(nPointsTot,grad1,1,AdvVel[1],1,outarray[n],1,outarray[n],1);
207  }
208  }
209  break;
210  case 3:
211  if(m_homogen_dealiasing == true && m_specHP_dealiasing == true)
212  {
214  Array<OneD, Array<OneD, NekDouble> > gradScaled (ndim*nConvectiveFields);
215  Array<OneD, Array<OneD, NekDouble> > Outarray (nConvectiveFields);
216  for (int i = 0; i < ndim; i++)
217  {
218  grad[i] = Array<OneD, NekDouble>(fields[0]->GetNpoints());
219  }
220  for (int i = 0; i < ndim*nConvectiveFields; i++)
221  {
222  gradScaled[i] = Array<OneD, NekDouble>(nPointsTot);
223  }
224  for (int i = 0; i < nConvectiveFields; i++)
225  {
226  Outarray[i] = Array<OneD, NekDouble>(nPointsTot);
227  }
228 
229  for (int n = 0; n < nConvectiveFields; n++)
230  {
231  fields[0]->PhysDeriv(inarray[n],grad[0],grad[1],grad[2]);
232  for (int i = 0; i < ndim; i++)
233  {
234 timer.Start();
235  fields[0]->PhysInterp1DScaled(OneDptscale,grad[i],
236  gradScaled[n*ndim+i]);
237 timer.Stop();
238 timer.AccumulateRegion("Interp1DScaled");
239  }
240  }
241 
242  fields[0]->DealiasedDotProd(AdvVel,gradScaled,Outarray);
243 
244 timer.Start();
245  for (int n = 0; n < nConvectiveFields; n++)
246  {
247  fields[0]->PhysGalerkinProjection1DScaled(OneDptscale,
248  Outarray[n],outarray[n]);
249  }
250 timer.Stop();
251 timer.AccumulateRegion("GalerinProject");
252  }
253  else if(m_homogen_dealiasing == true && m_specHP_dealiasing == false)
254  {
255  Array<OneD, Array<OneD, NekDouble> > grad (ndim*nConvectiveFields);
256  Array<OneD, Array<OneD, NekDouble> > Outarray (nConvectiveFields);
257  for (int i = 0; i < ndim*nConvectiveFields; i++)
258  {
259  grad[i] = Array<OneD, NekDouble>(nPointsTot);
260  }
261  for (int i = 0; i < nConvectiveFields; i++)
262  {
263  Outarray[i] = Array<OneD, NekDouble>(nPointsTot);
264  }
265 
266  for (int n = 0; n < nConvectiveFields; n++)
267  {
268  fields[0]->PhysDeriv(inarray[n],grad[n*ndim+0],
269  grad[n*ndim+1],
270  grad[n*ndim+2]);
271  }
272 
273  fields[0]->DealiasedDotProd(AdvVel,grad,outarray);
274  }
275  else
276  {
277  grad0 = Array<OneD, NekDouble> (fields[0]->GetNpoints());
278  grad1 = Array<OneD, NekDouble> (fields[0]->GetNpoints());
279  grad2 = Array<OneD, NekDouble> (fields[0]->GetNpoints());
280  Array<OneD, NekDouble> tmp = grad2;
281  for(int n = 0; n < nConvectiveFields; ++n)
282  {
283  if (fields[0]->GetWaveSpace() == true &&
284  fields[0]->GetExpType() == MultiRegions::e3DH1D)
285  {
286  fields[0]->HomogeneousBwdTrans(inarray[n],tmp);
287  fields[0]->PhysDeriv(tmp,grad0,grad1);
288  // Take d/dz derivative using wave space field
289  fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[2],
290  inarray[n],
291  outarray[n]);
292  fields[0]->HomogeneousBwdTrans(outarray[n],grad2);
293  }
294  else if (fields[0]->GetWaveSpace() == true &&
295  fields[0]->GetExpType() == MultiRegions::e3DH2D)
296  {
297  fields[0]->HomogeneousBwdTrans(inarray[n],tmp);
298  fields[0]->PhysDeriv(tmp,grad0);
299  // Take d/dy derivative using wave space field
300  fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[1],inarray[n],
301  outarray[n]);
302  fields[0]->HomogeneousBwdTrans(outarray[n],grad1);
303  // Take d/dz derivative using wave space field
304  fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[2],inarray[n],
305  outarray[n]);
306  fields[0]->HomogeneousBwdTrans(outarray[n],grad2);
307  }
308  else
309  {
310  fields[0]->PhysDeriv(inarray[n],grad0,grad1,grad2);
311  }
312  if(m_specHP_dealiasing) //interpolate spectral/hp gradient field
313  {
314  Array<OneD, NekDouble> Outarray(nPointsTot);
315 timer.Start();
316  fields[0]->PhysInterp1DScaled(OneDptscale,grad0,wkSp);
317 timer.Stop();
318 timer.AccumulateRegion("Interp1DScaled");
319  Vmath::Vmul(nPointsTot,wkSp,1,AdvVel[0],1,Outarray,1);
320 
321 timer.Start();
322  fields[0]->PhysInterp1DScaled(OneDptscale,grad1,wkSp);
323 timer.Stop();
324 timer.AccumulateRegion("Interp1DScaled");
325  Vmath::Vvtvp(nPointsTot,wkSp,1,AdvVel[1],1,Outarray,1,
326  Outarray,1);
327 
328 timer.Start();
329  fields[0]->PhysInterp1DScaled(OneDptscale,grad2,wkSp);
330 timer.Stop();
331 timer.AccumulateRegion("Interp1DScaled");
332  Vmath::Vvtvp(nPointsTot,wkSp,1,AdvVel[2],1,Outarray,1,
333  Outarray,1);
334 timer.Start();
335  fields[0]->PhysGalerkinProjection1DScaled(OneDptscale,
336  Outarray,outarray[n]);
337 timer.Stop();
338 timer.AccumulateRegion("GalerinProject");
339  }
340  else
341  {
342  Vmath::Vmul(nPointsTot,grad0,1,AdvVel[0],1,outarray[n],1);
343  Vmath::Vvtvp(nPointsTot,grad1,1,AdvVel[1],1,outarray[n],1,
344  outarray[n],1);
345  Vmath::Vvtvp(nPointsTot,grad2,1,AdvVel[2],1,outarray[n],1,
346  outarray[n],1);
347  }
348 
349  if(fields[0]->GetWaveSpace() == true)
350  {
351  fields[0]->HomogeneousFwdTrans(outarray[n],outarray[n]);
352  }
353  }
354  }
355  break;
356  default:
357  ASSERTL0(false,"dimension unknown");
358  }
359 
360  for(int n = 0; n < nConvectiveFields; ++n)
361  {
362  Vmath::Neg(nqtot,outarray[n],1);
363  }
364 
365  }
366 
367 } //end of namespace
368 
#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
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:200
void AccumulateRegion(std::string, int iolevel=0)
Accumulate elapsed time for a region.
Definition: Timer.cpp:67
virtual void v_InitObject(LibUtilities::SessionReaderSharedPtr pSession, Array< OneD, MultiRegions::ExpListSharedPtr > pFields)
Initialises the advection object.
virtual void v_Advect(const int nConvectiveFields, const Array< OneD, MultiRegions::ExpListSharedPtr > &fields, const Array< OneD, Array< OneD, NekDouble > > &advVel, const Array< OneD, Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble &time, const Array< OneD, Array< OneD, NekDouble > > &pFwd=NullNekDoubleArrayOfArray, const Array< OneD, Array< OneD, NekDouble > > &pBwd=NullNekDoubleArrayOfArray)
Advects a vector field.
An abstract base class encapsulating the concept of advection of a vector field.
Definition: Advection.h:73
virtual SOLVER_UTILS_EXPORT void v_InitObject(LibUtilities::SessionReaderSharedPtr pSession, Array< OneD, MultiRegions::ExpListSharedPtr > pFields)
Initialises the advection object.
Definition: Advection.cpp:366
std::shared_ptr< SessionReader > SessionReaderSharedPtr
MultiRegions::Direction const DirCartesianMap[]
Definition: ExpList.h:90
AdvectionFactory & GetAdvectionFactory()
Gets the factory for initialising advection objects.
Definition: Advection.cpp:47
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
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