Nektar++
NavierStokesCFE.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File NavierStokesCFE.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: Navier Stokes equations in conservative variables
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
36 
37 using namespace std;
38 
39 namespace Nektar
40 {
41  string NavierStokesCFE::className =
43  "NavierStokesCFE", NavierStokesCFE::create,
44  "NavierStokes equations in conservative variables.");
45 
46  NavierStokesCFE::NavierStokesCFE(
49  : UnsteadySystem(pSession, pGraph),
50  CompressibleFlowSystem(pSession, pGraph)
51  {
52  }
53 
55  {
56 
57  }
58 
59  /**
60  * @brief Initialization object for CompressibleFlowSystem class.
61  */
63  {
65 
66  // Get gas constant from session file and compute Cp
67  NekDouble gasConstant;
68  m_session->LoadParameter ("GasConstant", gasConstant, 287.058);
69  m_Cp = m_gamma / (m_gamma - 1.0) * gasConstant;
70 
71  // Viscosity
72  int nPts = m_fields[0]->GetNpoints();
73  m_session->LoadSolverInfo("ViscosityType", m_ViscosityType, "Constant");
74  m_session->LoadParameter ("mu", m_muRef, 1.78e-05);
76 
77  // Thermal conductivity or Prandtl
78  if( m_session->DefinesParameter("thermalConductivity"))
79  {
80  ASSERTL0( !m_session->DefinesParameter("Pr"),
81  "Cannot define both Pr and thermalConductivity.");
82 
83  m_session->LoadParameter ("thermalConductivity",
86  }
87  else
88  {
89  m_session->LoadParameter ("Pr", m_Prandtl, 0.72);
91  }
94 
95  string diffName;
96  m_session->LoadSolverInfo("DiffusionType", diffName, "LDGNS");
97 
99  .CreateInstance(diffName, diffName);
100 
102  {
103  m_diffusion->SetFluxVectorNS(
105  this);
106  }
107  else
108  {
109  m_diffusion->SetFluxVectorNS(&NavierStokesCFE::
110  v_GetViscousFluxVector, this);
111  }
112 
113  // Set up penalty term for LDGNS
114  m_diffusion->SetFluxPenaltyNS(&NavierStokesCFE::
115  v_GetFluxPenalty, this);
116 
117  // Concluding initialisation of diffusion operator
118  m_diffusion->InitObject (m_session, m_fields);
119  }
120 
122  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
123  Array<OneD, Array<OneD, NekDouble> > &outarray,
124  const Array<OneD, Array<OneD, NekDouble> > &pFwd,
125  const Array<OneD, Array<OneD, NekDouble> > &pBwd)
126  {
127  int i;
128  int nvariables = inarray.num_elements();
129  int npoints = GetNpoints();
130  int nTracePts = GetTraceTotPoints();
131 
132  Array<OneD, Array<OneD, NekDouble> > outarrayDiff(nvariables);
133 
134  Array<OneD, Array<OneD, NekDouble> > inarrayDiff(nvariables-1);
135  Array<OneD, Array<OneD, NekDouble> > inFwd(nvariables-1);
136  Array<OneD, Array<OneD, NekDouble> > inBwd(nvariables-1);
137 
138  for (i = 0; i < nvariables; ++i)
139  {
140  outarrayDiff[i] = Array<OneD, NekDouble>(npoints);
141  }
142 
143  for (i = 0; i < nvariables-1; ++i)
144  {
145  inarrayDiff[i] = Array<OneD, NekDouble>(npoints);
146  inFwd[i] = Array<OneD, NekDouble>(nTracePts);
147  inBwd[i] = Array<OneD, NekDouble>(nTracePts);
148  }
149 
150  // Extract pressure
151  // (use inarrayDiff[0] as a temporary storage for the pressure)
152  m_varConv->GetPressure(inarray, inarrayDiff[0]);
153 
154  // Extract temperature
155  m_varConv->GetTemperature(inarray, inarrayDiff[nvariables-2]);
156 
157  // Extract velocities
158  m_varConv->GetVelocityVector(inarray, inarrayDiff);
159 
160  // Repeat calculation for trace space
161  if (pFwd == NullNekDoubleArrayofArray ||
163  {
166  }
167  else
168  {
169  m_varConv->GetPressure(pFwd, inFwd[0]);
170  m_varConv->GetPressure(pBwd, inBwd[0]);
171 
172  m_varConv->GetTemperature(pFwd, inFwd[nvariables-2]);
173  m_varConv->GetTemperature(pBwd, inBwd[nvariables-2]);
174 
175  m_varConv->GetVelocityVector(pFwd, inFwd);
176  m_varConv->GetVelocityVector(pBwd, inBwd);
177  }
178 
179  // Diffusion term in physical rhs form
180  m_diffusion->Diffuse(nvariables, m_fields, inarrayDiff, outarrayDiff,
181  inFwd, inBwd);
182 
183  for (i = 0; i < nvariables; ++i)
184  {
185  Vmath::Vadd(npoints,
186  outarrayDiff[i], 1,
187  outarray[i], 1,
188  outarray[i], 1);
189  }
190  }
191 
192  /**
193  * @brief Return the flux vector for the LDG diffusion problem.
194  * \todo Complete the viscous flux vector
195  */
197  const Array<OneD, Array<OneD, NekDouble> > &physfield,
198  Array<OneD, Array<OneD, Array<OneD, NekDouble> > > &derivativesO1,
199  Array<OneD, Array<OneD, Array<OneD, NekDouble> > > &viscousTensor)
200  {
201  // Auxiliary variables
202  int nScalar = physfield.num_elements();
203  int nPts = physfield[0].num_elements();
204  Array<OneD, NekDouble > divVel (nPts, 0.0);
205 
206  // Stokes hypothesis
207  const NekDouble lambda = -2.0/3.0;
208 
209  // Update viscosity and thermal conductivity
210  GetViscosityAndThermalCondFromTemp(physfield[nScalar-1], m_mu,
212 
213  // Velocity divergence
214  for (int j = 0; j < m_spacedim; ++j)
215  {
216  Vmath::Vadd(nPts, divVel, 1, derivativesO1[j][j], 1,
217  divVel, 1);
218  }
219 
220  // Velocity divergence scaled by lambda * mu
221  Vmath::Smul(nPts, lambda, divVel, 1, divVel, 1);
222  Vmath::Vmul(nPts, m_mu, 1, divVel, 1, divVel, 1);
223 
224  // Viscous flux vector for the rho equation = 0
225  for (int i = 0; i < m_spacedim; ++i)
226  {
227  Vmath::Zero(nPts, viscousTensor[i][0], 1);
228  }
229 
230  // Viscous stress tensor (for the momentum equations)
231  for (int i = 0; i < m_spacedim; ++i)
232  {
233  for (int j = i; j < m_spacedim; ++j)
234  {
235  Vmath::Vadd(nPts, derivativesO1[i][j], 1,
236  derivativesO1[j][i], 1,
237  viscousTensor[i][j+1], 1);
238 
239  Vmath::Vmul(nPts, m_mu, 1,
240  viscousTensor[i][j+1], 1,
241  viscousTensor[i][j+1], 1);
242 
243  if (i == j)
244  {
245  // Add divergence term to diagonal
246  Vmath::Vadd(nPts, viscousTensor[i][j+1], 1,
247  divVel, 1,
248  viscousTensor[i][j+1], 1);
249  }
250  else
251  {
252  // Copy to make symmetric
253  Vmath::Vcopy(nPts, viscousTensor[i][j+1], 1,
254  viscousTensor[j][i+1], 1);
255  }
256  }
257  }
258 
259  // Terms for the energy equation
260  for (int i = 0; i < m_spacedim; ++i)
261  {
262  Vmath::Zero(nPts, viscousTensor[i][m_spacedim+1], 1);
263  // u_j * tau_ij
264  for (int j = 0; j < m_spacedim; ++j)
265  {
266  Vmath::Vvtvp(nPts, physfield[j], 1,
267  viscousTensor[i][j+1], 1,
268  viscousTensor[i][m_spacedim+1], 1,
269  viscousTensor[i][m_spacedim+1], 1);
270  }
271  // Add k*T_i
273  derivativesO1[i][m_spacedim], 1,
274  viscousTensor[i][m_spacedim+1], 1,
275  viscousTensor[i][m_spacedim+1], 1);
276  }
277  }
278 
279  /**
280  * @brief Return the flux vector for the LDG diffusion problem.
281  * \todo Complete the viscous flux vector
282  */
284  const Array<OneD, Array<OneD, NekDouble> > &physfield,
285  Array<OneD, Array<OneD, Array<OneD, NekDouble> > > &derivativesO1,
286  Array<OneD, Array<OneD, Array<OneD, NekDouble> > > &viscousTensor)
287  {
288  // Factor to rescale 1d points in dealiasing.
289  NekDouble OneDptscale = 2;
290  // Get number of points to dealias a cubic non-linearity
291  int nScalar = physfield.num_elements();
292  int nPts = m_fields[0]->Get1DScaledTotPoints(OneDptscale);
293  int nPts_orig = physfield[0].num_elements();
294 
295  // Auxiliary variables
296  Array<OneD, NekDouble > divVel (nPts, 0.0);
297 
298  // Stokes hypothesis
299  const NekDouble lambda = -2.0/3.0;
300 
301  // Update viscosity and thermal conductivity
302  GetViscosityAndThermalCondFromTemp(physfield[nScalar-1], m_mu,
304 
305  // Interpolate inputs and initialise interpolated output
308  deriv_interp(m_spacedim);
310  out_interp(m_spacedim);
311  for (int i = 0; i < m_spacedim; ++i)
312  {
313  // Interpolate velocity
314  vel_interp[i] = Array<OneD, NekDouble> (nPts);
315  m_fields[0]->PhysInterp1DScaled(
316  OneDptscale, physfield[i], vel_interp[i]);
317 
318  // Interpolate derivatives
319  deriv_interp[i] = Array<OneD,Array<OneD,NekDouble> > (m_spacedim+1);
320  for (int j = 0; j < m_spacedim+1; ++j)
321  {
322  deriv_interp[i][j] = Array<OneD, NekDouble> (nPts);
323  m_fields[0]->PhysInterp1DScaled(
324  OneDptscale, derivativesO1[i][j], deriv_interp[i][j]);
325  }
326 
327  // Output (start from j=1 since flux is zero for rho)
328  out_interp[i] = Array<OneD,Array<OneD,NekDouble> > (m_spacedim+2);
329  for (int j = 1; j < m_spacedim+2; ++j)
330  {
331  out_interp[i][j] = Array<OneD, NekDouble> (nPts);
332  }
333  }
334 
335  // Velocity divergence
336  for (int j = 0; j < m_spacedim; ++j)
337  {
338  Vmath::Vadd(nPts, divVel, 1, deriv_interp[j][j], 1,
339  divVel, 1);
340  }
341 
342  // Velocity divergence scaled by lambda * mu
343  Vmath::Smul(nPts, lambda, divVel, 1, divVel, 1);
344  Vmath::Vmul(nPts, m_mu, 1, divVel, 1, divVel, 1);
345 
346  // Viscous flux vector for the rho equation = 0 (no need to dealias)
347  for (int i = 0; i < m_spacedim; ++i)
348  {
349  Vmath::Zero(nPts_orig, viscousTensor[i][0], 1);
350  }
351 
352  // Viscous stress tensor (for the momentum equations)
353  for (int i = 0; i < m_spacedim; ++i)
354  {
355  for (int j = i; j < m_spacedim; ++j)
356  {
357  Vmath::Vadd(nPts, deriv_interp[i][j], 1,
358  deriv_interp[j][i], 1,
359  out_interp[i][j+1], 1);
360 
361  Vmath::Vmul(nPts, m_mu, 1,
362  out_interp[i][j+1], 1,
363  out_interp[i][j+1], 1);
364 
365  if (i == j)
366  {
367  // Add divergence term to diagonal
368  Vmath::Vadd(nPts, out_interp[i][j+1], 1,
369  divVel, 1,
370  out_interp[i][j+1], 1);
371  }
372  else
373  {
374  // Make symmetric
375  out_interp[j][i+1] = out_interp[i][j+1];
376  }
377  }
378  }
379 
380  // Terms for the energy equation
381  for (int i = 0; i < m_spacedim; ++i)
382  {
383  Vmath::Zero(nPts, out_interp[i][m_spacedim+1], 1);
384  // u_j * tau_ij
385  for (int j = 0; j < m_spacedim; ++j)
386  {
387  Vmath::Vvtvp(nPts, vel_interp[j], 1,
388  out_interp[i][j+1], 1,
389  out_interp[i][m_spacedim+1], 1,
390  out_interp[i][m_spacedim+1], 1);
391  }
392  // Add k*T_i
394  deriv_interp[i][m_spacedim], 1,
395  out_interp[i][m_spacedim+1], 1,
396  out_interp[i][m_spacedim+1], 1);
397  }
398 
399  // Project to original space
400  for (int i = 0; i < m_spacedim; ++i)
401  {
402  for (int j = 1; j < m_spacedim+2; ++j)
403  {
404  m_fields[0]->PhysGalerkinProjection1DScaled(
405  OneDptscale,
406  out_interp[i][j],
407  viscousTensor[i][j]);
408  }
409  }
410  }
411 
412  /**
413  * @brief Return the penalty vector for the LDGNS diffusion problem.
414  */
416  const Array<OneD, Array<OneD, NekDouble> > &uFwd,
417  const Array<OneD, Array<OneD, NekDouble> > &uBwd,
418  Array<OneD, Array<OneD, NekDouble> > &penaltyCoeff)
419  {
420  unsigned int nTracePts = uFwd[0].num_elements();
421 
422  // Compute average temperature
423  unsigned int nVariables = uFwd.num_elements();
424  Array<OneD, NekDouble> tAve{nTracePts, 0.0};
425  Vmath::Svtsvtp(nTracePts, 0.5, uFwd[nVariables-1], 1,
426  0.5, uBwd[nVariables-1], 1, tAve, 1);
427 
428  // Get average viscosity and thermal conductivity
429  Array<OneD, NekDouble> muAve{nTracePts, 0.0};
430  Array<OneD, NekDouble> tcAve{nTracePts, 0.0};
431 
432  GetViscosityAndThermalCondFromTemp(tAve, muAve, tcAve);
433 
434  // Compute penalty term
435  for (int i = 0; i < nVariables; ++i)
436  {
437  // Get jump of u variables
438  Vmath::Vsub(nTracePts, uFwd[i], 1, uBwd[i], 1, penaltyCoeff[i], 1);
439  // Multiply by variable coefficient = {coeff} ( u^+ - u^- )
440  if ( i < nVariables-1 )
441  {
442  Vmath::Vmul(nTracePts, muAve, 1, penaltyCoeff[i], 1,
443  penaltyCoeff[i], 1);
444  }
445  else
446  {
447  Vmath::Vmul(nTracePts, tcAve, 1, penaltyCoeff[i], 1,
448  penaltyCoeff[i], 1);
449  }
450  }
451  }
452 
453 
454  /**
455  * @brief Update viscosity
456  * todo: add artificial viscosity here
457  */
459  const Array<OneD, NekDouble> &temperature,
461  Array<OneD, NekDouble> &thermalCond)
462  {
463  int nPts = temperature.num_elements();
464 
465  // Variable viscosity through the Sutherland's law
466  if (m_ViscosityType == "Variable")
467  {
468  m_varConv->GetDynamicViscosity(temperature, mu);
469  }
470  else
471  {
472  Vmath::Fill(nPts, m_muRef, mu, 1);
473  }
474  NekDouble tRa = m_Cp / m_Prandtl;
475  Vmath::Smul(nPts, tRa, mu, 1, thermalCond, 1);
476 
477  }
478 
479 }
virtual void v_InitObject()
Initialization object for CompressibleFlowSystem class.
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:163
virtual void v_InitObject()
Initialization object for CompressibleFlowSystem class.
Array< OneD, NekDouble > m_thermalConductivity
NekDouble m_thermalConductivityRef
VariableConverterSharedPtr m_varConv
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:45
DiffusionFactory & GetDiffusionFactory()
Definition: Diffusion.cpp:41
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.
bool m_specHP_dealiasing
Flag to determine if dealisising is usde for the Spectral/hp element discretisation.
virtual void v_GetFluxPenalty(const Array< OneD, Array< OneD, NekDouble > > &uFwd, const Array< OneD, Array< OneD, NekDouble > > &uBwd, Array< OneD, Array< OneD, NekDouble > > &penaltyCoeff)
Return the penalty vector for the LDGNS diffusion problem.
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*y.
Definition: Vmath.cpp:216
Base class for unsteady solvers.
int m_spacedim
Spatial dimension (>= expansion dim).
double NekDouble
EquationSystemFactory & GetEquationSystemFactory()
void Vsub(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Subtract vector z = x-y.
Definition: Vmath.cpp:346
SolverUtils::DiffusionSharedPtr m_diffusion
SOLVER_UTILS_EXPORT int GetTraceTotPoints()
void GetViscosityAndThermalCondFromTemp(const Array< OneD, NekDouble > &temperature, Array< OneD, NekDouble > &mu, Array< OneD, NekDouble > &thermalCond)
Update viscosity todo: add artificial viscosity here.
virtual void v_GetViscousFluxVector(const Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &derivatives, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &viscousTensor)
Return the flux vector for the LDG diffusion problem.
SOLVER_UTILS_EXPORT int GetNpoints()
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
virtual void v_GetViscousFluxVectorDeAlias(const Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &derivatives, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &viscousTensor)
Return the flux vector for the LDG diffusion problem.
Array< OneD, NekDouble > m_mu
void Svtsvtp(int n, const T alpha, const T *x, int incx, const T beta, const T *y, int incy, T *z, int incz)
vvtvvtp (scalar times vector plus scalar times vector):
Definition: Vmath.cpp:594
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:199
virtual void v_DoDiffusion(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const Array< OneD, Array< OneD, NekDouble > > &pFwd, const Array< OneD, Array< OneD, NekDouble > > &pBwd)
static Array< OneD, Array< OneD, NekDouble > > NullNekDoubleArrayofArray
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:376
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
std::shared_ptr< SessionReader > SessionReaderSharedPtr
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition: Vmath.cpp:302
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