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