Nektar++
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
VariableConverter.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File VariableConverter.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: Auxiliary functions to convert variables in
32 // the compressible flow system
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 #include <iomanip>
36 #include <iostream>
37 
39 
40 using namespace std;
41 
42 namespace Nektar
43 {
44 VariableConverter::VariableConverter(
45  const LibUtilities::SessionReaderSharedPtr &pSession, const int spaceDim)
46  : m_session(pSession), m_spacedim(spaceDim)
47 {
48  // Create equation of state object
49  std::string eosType;
50  m_session->LoadSolverInfo("EquationOfState", eosType, "IdealGas");
52 
53  // Parameters for dynamic viscosity
54  m_session->LoadParameter("pInf", m_pInf, 101325);
55  m_session->LoadParameter("rhoInf", m_rhoInf, 1.225);
56  m_session->LoadParameter("GasConstant", m_gasConstant, 287.058);
57  m_session->LoadParameter("mu", m_mu, 1.78e-05);
59 
60  // Parameters for sensor
61  m_session->LoadParameter("Skappa", m_Skappa, -1.0);
62  m_session->LoadParameter("Kappa", m_Kappa, 0.25);
63 
64 
65 }
66 
67 /**
68  * @brief Destructor for VariableConverter class.
69  */
71 {
72 }
73 
74 /**
75  * @brief Compute the dynamic energy
76  * \f$ e = rho*V^2/2 \f$.
77  */
79  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
80  Array<OneD, NekDouble> &energy)
81 {
82  size_t nPts = physfield[m_spacedim + 1].size();
83  Vmath::Zero(nPts, energy, 1);
84 
85  // tmp = (rho * u_i)^2
86  for (int i = 0; i < m_spacedim; ++i)
87  {
88  Vmath::Vvtvp(nPts, physfield[i + 1], 1, physfield[i + 1], 1, energy, 1,
89  energy, 1);
90  }
91  // Divide by rho and multiply by 0.5 --> tmp = 0.5 * rho * u^2
92  Vmath::Vdiv(nPts, energy, 1, physfield[0], 1, energy, 1);
93  Vmath::Smul(nPts, 0.5, energy, 1, energy, 1);
94 }
95 
96 /**
97  * @brief Compute the specific internal energy
98  * \f$ e = (E - rho*V^2/2)/rho \f$.
99  */
101  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
102  Array<OneD, NekDouble> &energy)
103 {
104  int nPts = physfield[0].size();
105  Array<OneD, NekDouble> tmp(nPts);
106 
107  GetDynamicEnergy(physfield, tmp);
108 
109  // Calculate rhoe = E - rho*V^2/2
110  Vmath::Vsub(nPts, physfield[m_spacedim + 1], 1, tmp, 1, energy, 1);
111  // Divide by rho
112  Vmath::Vdiv(nPts, energy, 1, physfield[0], 1, energy, 1);
113 }
114 
115 /**
116  * @brief Compute the specific enthalpy \f$ h = e + p/rho \f$.
117  */
119  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
120  Array<OneD, NekDouble> &enthalpy)
121 {
122  int nPts = physfield[0].size();
123  Array<OneD, NekDouble> energy(nPts, 0.0);
124  Array<OneD, NekDouble> pressure(nPts, 0.0);
125 
126  GetInternalEnergy(physfield, energy);
127  GetPressure(physfield, pressure);
128 
129  // Calculate p/rho
130  Vmath::Vdiv(nPts, pressure, 1, physfield[0], 1, enthalpy, 1);
131  // Calculate h = e + p/rho
132  Vmath::Vadd(nPts, energy, 1, enthalpy, 1, enthalpy, 1);
133 }
134 
135 /**
136  * @brief Compute the velocity field \f$ \mathbf{v} \f$ given the momentum
137  * \f$ \rho\mathbf{v} \f$.
138  *
139  * @param physfield Momentum field.
140  * @param velocity Velocity field.
141  */
143  const Array<OneD, Array<OneD, NekDouble>> &physfield,
144  Array<OneD, Array<OneD, NekDouble>> &velocity)
145 {
146  const int nPts = physfield[0].size();
147 
148  for (int i = 0; i < m_spacedim; ++i)
149  {
150  Vmath::Vdiv(nPts, physfield[1 + i], 1, physfield[0], 1, velocity[i], 1);
151  }
152 }
153 
154 /**
155  * @brief Compute the mach number \f$ M = \| \mathbf{v} \|^2 / c \f$.
156  *
157  * @param physfield Input physical field.
158  * @param soundfield The speed of sound corresponding to physfield.
159  * @param mach The resulting mach number \f$ M \f$.
160  */
162  Array<OneD, NekDouble> &soundspeed,
164 {
165  const int nPts = physfield[0].size();
166 
167  Vmath::Vmul(nPts, physfield[1], 1, physfield[1], 1, mach, 1);
168 
169  for (int i = 1; i < m_spacedim; ++i)
170  {
171  Vmath::Vvtvp(nPts, physfield[1 + i], 1, physfield[1 + i], 1, mach, 1,
172  mach, 1);
173  }
174 
175  Vmath::Vdiv(nPts, mach, 1, physfield[0], 1, mach, 1);
176  Vmath::Vdiv(nPts, mach, 1, physfield[0], 1, mach, 1);
177  Vmath::Vsqrt(nPts, mach, 1, mach, 1);
178 
179  Vmath::Vdiv(nPts, mach, 1, soundspeed, 1, mach, 1);
180 }
181 
182 /**
183  * @brief Compute the dynamic viscosity using the Sutherland's law
184  * \f$ \mu = \mu_star * (T / T_star)^3/2 * (1 + C) / (T / T_star + C) \f$,
185  * where: \mu_star = 1.7894 * 10^-5 Kg / (m * s)
186  * T_star = 288.15 K
187  * C = 110. / 288.15
188  *
189  * WARNING, if this routine is modified the same must be done in the
190  * FieldConvert utility ProcessWSS.cpp (this class should be restructured).
191  *
192  * @param temperature Input temperature field.
193  * @param mu The resulting dynamic viscosity.
194  */
197 {
198  const int nPts = temperature.size();
199 
200  for (int i = 0; i < nPts; ++i)
201  {
202  mu[i] = GetDynamicViscosity(temperature[i]);
203  }
204 }
205 
206 /**
207  * @brief Compute the dynamic viscosity using the Sutherland's law
208  * \f$ \mu = \mu_star * (T / T_star)^3/2 * (T_star + 110) / (T + 110) \f$,
209  * where: \mu_star = 1.7894 * 10^-5 Kg / (m * s)
210  * T_star = 288.15 K
211  *
212  * @param physfield Input physical field.
213  * @param mu The resulting dynamic viscosity.
214  */
216  const Array<OneD, const NekDouble> &temperature,
218  Array<OneD, NekDouble> &DmuDT)
219 {
220  const int nPts = temperature.size();
221  NekDouble tmp = 0.0;
222 
223  for (int i = 0; i < nPts; ++i)
224  {
225  tmp = 0.5* (temperature[i]+3.0*110.0)/
226  (temperature[i]*(temperature[i]+110.0));
227  DmuDT[i] = mu[i]*tmp;
228  }
229 }
230 
232  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
234 {
235  const int nPts = physfield[0].size();
236 
237  // Getting the velocity vector on the 2D normal space
239 
240  Vmath::Zero(Vtot.size(), Vtot, 1);
241 
242  for (int i = 0; i < m_spacedim; ++i)
243  {
244  velocity[i] = Array<OneD, NekDouble>(nPts);
245  }
246 
247  GetVelocityVector(physfield, velocity);
248 
249  for (int i = 0; i < m_spacedim; ++i)
250  {
251  Vmath::Vvtvp(nPts, velocity[i], 1, velocity[i], 1, Vtot, 1, Vtot, 1);
252  }
253 
254  Vmath::Vsqrt(nPts, Vtot, 1, Vtot, 1);
255 }
256 
258  const MultiRegions::ExpListSharedPtr &field,
259  const Array<OneD, const Array<OneD, NekDouble>> &physarray,
260  Array<OneD, NekDouble> &Sensor, Array<OneD, NekDouble> &SensorKappa,
261  int offset)
262 {
263  NekDouble Skappa;
264  NekDouble order;
266  Array<OneD, int> expOrderElement = field->EvalBasisNumModesMaxPerExp();
267 
268  for (int e = 0; e < field->GetExpSize(); e++)
269  {
270  int numModesElement = expOrderElement[e];
271  int nElmtPoints = field->GetExp(e)->GetTotPoints();
272  int physOffset = field->GetPhys_Offset(e);
273  int nElmtCoeffs = field->GetExp(e)->GetNcoeffs();
274  int numCutOff = numModesElement - offset;
275 
276  if (numModesElement <= offset)
277  {
278  Vmath::Fill(nElmtPoints, 0.0,
279  tmp = Sensor + physOffset, 1);
280  Vmath::Fill(nElmtPoints, 0.0,
281  tmp = SensorKappa + physOffset, 1);
282  continue;
283  }
284 
285  // create vector to save the solution points per element at P = p;
286  Array<OneD, NekDouble> elmtPhys(nElmtPoints,
287  tmp = physarray[0] + physOffset);
288  // Compute coefficients
289  Array<OneD, NekDouble> elmtCoeffs(nElmtCoeffs, 0.0);
290  field->GetExp(e)->FwdTrans(elmtPhys, elmtCoeffs);
291 
292  // ReduceOrderCoeffs reduces the polynomial order of the solution
293  // that is represented by the coeffs given as an inarray. This is
294  // done by projecting the higher order solution onto the orthogonal
295  // basis and padding the higher order coefficients with zeros.
296  Array<OneD, NekDouble> reducedElmtCoeffs(nElmtCoeffs, 0.0);
297  field->GetExp(e)->ReduceOrderCoeffs(numCutOff, elmtCoeffs,
298  reducedElmtCoeffs);
299 
300  Array<OneD, NekDouble> reducedElmtPhys(nElmtPoints, 0.0);
301  field->GetExp(e)->BwdTrans(reducedElmtCoeffs, reducedElmtPhys);
302 
303  NekDouble numerator = 0.0;
304  NekDouble denominator = 0.0;
305 
306  // Determining the norm of the numerator of the Sensor
307  Array<OneD, NekDouble> difference(nElmtPoints, 0.0);
308  Vmath::Vsub(nElmtPoints, elmtPhys, 1, reducedElmtPhys, 1, difference,
309  1);
310 
311  numerator = Vmath::Dot(nElmtPoints, difference, difference);
312  denominator = Vmath::Dot(nElmtPoints, elmtPhys, elmtPhys);
313 
314  NekDouble elmtSensor = sqrt(numerator / denominator);
315  elmtSensor = log10(max(elmtSensor, NekConstants::kNekSqrtTol));
316 
317  Vmath::Fill(nElmtPoints, elmtSensor, tmp = Sensor + physOffset, 1);
318 
319  // Compute reference value for sensor
320  order = max(numModesElement-1, 1);
321  if (order > 0 )
322  {
323  Skappa = m_Skappa - 4.25 * log10(static_cast<NekDouble>(order));
324  }
325  else
326  {
327  Skappa = 0.0;
328  }
329 
330  // Compute artificial viscosity
331  NekDouble elmtSensorKappa;
332  if (elmtSensor < (Skappa-m_Kappa))
333  {
334  elmtSensorKappa = 0;
335  }
336  else if (elmtSensor > (Skappa + m_Kappa))
337  {
338  elmtSensorKappa = 1.0;
339  }
340  else
341  {
342  elmtSensorKappa = 0.5 *
343  (1 + sin(M_PI * (elmtSensor - Skappa) / (2 * m_Kappa)));
344  }
345  Vmath::Fill(nElmtPoints, elmtSensorKappa,
346  tmp = SensorKappa + physOffset, 1);
347  }
348 }
349 
350 /**
351  * @brief Calculate the pressure using the equation of state.
352  *
353  * @param physfield Input momentum.
354  * @param pressure Computed pressure field.
355  */
357  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
359 {
360  int nPts = physfield[0].size();
361 
362  Array<OneD, NekDouble> energy(nPts);
363  GetInternalEnergy(physfield, energy);
364 
365  for (int i = 0; i < nPts; ++i)
366  {
367  pressure[i] = m_eos->GetPressure(physfield[0][i], energy[i]);
368  }
369 }
370 
371 /**
372  * @brief Compute the temperature using the equation of state.
373  *
374  * @param physfield Input physical field.
375  * @param temperature The resulting temperature \f$ T \f$.
376  */
378  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
379  Array<OneD, NekDouble> &temperature)
380 {
381  int nPts = physfield[0].size();
382 
383  Array<OneD, NekDouble> energy(nPts);
384  GetInternalEnergy(physfield, energy);
385 
386  for (int i = 0; i < nPts; ++i)
387  {
388  temperature[i] = m_eos->GetTemperature(physfield[0][i], energy[i]);
389  }
390 }
391 
392 /**
393  * @brief Compute the sound speed using the equation of state.
394  *
395  * @param physfield Input physical field
396  * @param soundspeed The resulting sound speed \f$ c \f$.
397  */
399  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
400  Array<OneD, NekDouble> &soundspeed)
401 {
402  int nPts = physfield[0].size();
403 
404  Array<OneD, NekDouble> energy(nPts);
405  GetInternalEnergy(physfield, energy);
406 
407  for (int i = 0; i < nPts; ++i)
408  {
409  soundspeed[i] = m_eos->GetSoundSpeed(physfield[0][i], energy[i]);
410  }
411 }
412 
413 /**
414  * @brief Compute the entropy using the equation of state.
415  *
416  * @param physfield Input physical field
417  * @param soundspeed The resulting sound speed \f$ c \f$.
418  */
420  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
421  Array<OneD, NekDouble> &entropy)
422 {
423  int nPts = physfield[0].size();
424 
425  Array<OneD, NekDouble> energy(nPts);
426  GetInternalEnergy(physfield, energy);
427 
428  for (int i = 0; i < nPts; ++i)
429  {
430  entropy[i] = m_eos->GetEntropy(physfield[0][i], energy[i]);
431  }
432 }
433 
434 /**
435  * @brief Compute \f$ e(rho,p) \f$ using the equation of state.
436  *
437  * @param rho Input density
438  * @param pressure Input pressure
439  * @param energy The resulting internal energy.
440  */
443  Array<OneD, NekDouble> &energy)
444 {
445  int nPts = rho.size();
446 
447  for (int i = 0; i < nPts; ++i)
448  {
449  energy[i] = m_eos->GetEFromRhoP(rho[i], pressure[i]);
450  }
451 }
452 
453 /**
454  * @brief Compute \f$ rho(p,T) \f$ using the equation of state.
455  *
456  * @param pressure Input pressure
457  * @param temperature Input temperature
458  * @param rho The resulting density
459  */
461  const Array<OneD, NekDouble> &temperature,
463 {
464  int nPts = pressure.size();
465 
466  for (int i = 0; i < nPts; ++i)
467  {
468  rho[i] = m_eos->GetRhoFromPT(pressure[i], temperature[i]);
469  }
470 }
471 
472 }
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:145
EquationOfStateSharedPtr m_eos
void GetDynamicEnergy(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &energy)
Compute the dynamic energy .
void GetRhoFromPT(const Array< OneD, NekDouble > &pressure, const Array< OneD, NekDouble > &temperature, Array< OneD, NekDouble > &rho)
Compute using the equation of state.
void GetTemperature(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &temperature)
Compute the temperature using the equation of state.
void GetDmuDT(const Array< OneD, const NekDouble > &temperature, const Array< OneD, const NekDouble > &mu, Array< OneD, NekDouble > &DmuDT)
Compute the dynamic viscosity using the Sutherland's law , where: \mu_star = 1.7894 * 10^-5 Kg / (m *...
void GetEnthalpy(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &enthalpy)
Compute the specific enthalpy .
void GetEFromRhoP(const Array< OneD, NekDouble > &rho, const Array< OneD, NekDouble > &pressure, Array< OneD, NekDouble > &energy)
Compute using the equation of state.
LibUtilities::SessionReaderSharedPtr m_session
void GetPressure(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &pressure)
Calculate the pressure using the equation of state.
void GetSoundSpeed(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &soundspeed)
Compute the sound speed using the equation of state.
void GetAbsoluteVelocity(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &Vtot)
void GetEntropy(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &entropy)
Compute the entropy using the equation of state.
void GetVelocityVector(const Array< OneD, Array< OneD, NekDouble >> &physfield, Array< OneD, Array< OneD, NekDouble >> &velocity)
Compute the velocity field given the momentum .
void GetMach(Array< OneD, Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &soundspeed, Array< OneD, NekDouble > &mach)
Compute the mach number .
void GetSensor(const MultiRegions::ExpListSharedPtr &field, const Array< OneD, const Array< OneD, NekDouble >> &physarray, Array< OneD, NekDouble > &Sensor, Array< OneD, NekDouble > &SensorKappa, int offset=1)
~VariableConverter()
Destructor for VariableConverter class.
void GetInternalEnergy(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &energy)
Compute the specific internal energy .
void GetDynamicViscosity(const Array< OneD, const NekDouble > &temperature, Array< OneD, NekDouble > &mu)
Compute the dynamic viscosity using the Sutherland's law , where: \mu_star = 1.7894 * 10^-5 Kg / (m *...
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
static const NekDouble kNekSqrtTol
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
EquationOfStateFactory & GetEquationOfStateFactory()
Declaration of the equation of state factory singleton.
double NekDouble
void Vsqrt(int n, const T *x, const int incx, T *y, const int incy)
sqrt y = sqrt(x)
Definition: Vmath.cpp:475
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 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
T Dot(int n, const T *w, const T *x)
vvtvp (vector times vector times vector): z = w*x*y
Definition: Vmath.cpp:1038
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:322
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition: Vmath.cpp:225
void Vdiv(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:257
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:436
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:45
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:372
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:267