Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CompressibleFlowSystem.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File CompressibleFlowSystem.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 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Compressible flow system base class with auxiliary functions
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
37 #include <LocalRegions/TriExp.h>
38 #include <MultiRegions/ExpList.h>
39 
40 
41 using namespace std;
42 
43 namespace Nektar
44 {
45  CompressibleFlowSystem::CompressibleFlowSystem(
47  : UnsteadySystem(pSession)
48  {
49  }
50 
51  /**
52  * @brief Initialization object for CompressibleFlowSystem class.
53  */
55  {
57 
60 
61  ASSERTL0(m_session->DefinesSolverInfo("UPWINDTYPE"),
62  "No UPWINDTYPE defined in session.");
63 
64  // Do not forwards transform initial condition
65  m_homoInitialFwd = false;
66 
67  // Set up locations of velocity vector.
70  for (int i = 0; i < m_spacedim; ++i)
71  {
72  m_vecLocs[0][i] = 1 + i;
73  }
74 
75  // Loading parameters from session file
77 
78  // Setting up advection and diffusion operators
79  InitAdvection();
80 
81  // Create artificial diffusion
82  if (m_shockCaptureType != "Off")
83  {
86  m_session,
87  m_fields,
88  m_spacedim);
89  }
90 
91  // Forcing terms for the sponge region
93  m_fields.num_elements());
94 
95  // User-defined boundary conditions
96  int cnt = 0;
97  for (int n = 0; n < m_fields[0]->GetBndConditions().num_elements(); ++n)
98  {
99  std::string type =
100  m_fields[0]->GetBndConditions()[n]->GetUserDefined();
101  if(!type.empty())
102  {
103  m_bndConds.push_back(GetCFSBndCondFactory().CreateInstance(
104  type,
105  m_session,
106  m_fields,
108  m_spacedim,
109  n,
110  cnt));
111  }
112  cnt += m_fields[0]->GetBndCondExpansions()[n]->GetExpSize();
113  }
114 
116  {
119  }
120  else
121  {
122  ASSERTL0(false, "Implicit CFS not set up.");
123  }
124  }
125 
126  /**
127  * @brief Destructor for CompressibleFlowSystem class.
128  */
130  {
131 
132  }
133 
134  /**
135  * @brief Load CFS parameters from the session file
136  */
138  {
139  NekDouble velInf, gasConstant;
140 
141  // Get gamma parameter from session file.
142  m_session->LoadParameter("Gamma", m_gamma, 1.4);
143 
144  // Get gas constant from session file and compute Cp
145  m_session->LoadParameter ("GasConstant", gasConstant, 287.058);
146  m_Cp = m_gamma / (m_gamma - 1.0) * gasConstant;
147 
148  // Get pInf parameter from session file.
149  m_session->LoadParameter("pInf", m_pInf, 101325);
150 
151  // Get rhoInf parameter from session file.
152  m_session->LoadParameter("rhoInf", m_rhoInf, 1.225);
153 
154  // Get uInf parameter from session file.
155  m_session->LoadParameter("uInf", velInf, 0.1);
156 
157  m_UInf = velInf*velInf;
158 
159  // Get vInf parameter from session file.
160  if (m_spacedim == 2 || m_spacedim == 3)
161  {
162  m_session->LoadParameter("vInf", velInf, 0.0);
163  m_UInf += velInf*velInf;
164  }
165 
166  // Get wInf parameter from session file.
167  if (m_spacedim == 3)
168  {
169  m_session->LoadParameter("wInf", velInf, 0.0);
170  m_UInf += velInf*velInf;
171  }
172  m_UInf = sqrt(m_UInf);
173 
174  // Viscosity
175  m_session->LoadSolverInfo("ViscosityType", m_ViscosityType, "Constant");
176  m_session->LoadParameter ("mu", m_mu, 1.78e-05);
177 
178  // Thermal conductivity or Prandtl
179  if( m_session->DefinesParameter("thermalConductivity"))
180  {
181  ASSERTL0( !m_session->DefinesParameter("Pr"),
182  "Cannot define both Pr and thermalConductivity.");
183 
184  m_session->LoadParameter ("thermalConductivity",
187  }
188  else
189  {
190  m_session->LoadParameter ("Pr",
191  m_Prandtl, 0.72);
193  }
194 
195  // Steady state tolerance
196  m_session->LoadParameter("SteadyStateTol", m_steadyStateTol, 0.0);
197 
198  // Shock capture
199  m_session->LoadSolverInfo("ShockCaptureType",
200  m_shockCaptureType, "Off");
201  }
202 
203  /**
204  * @brief Create advection and diffusion objects for CFS
205  */
207  {
208  // Check if projection type is correct
210  "Unsupported projection type.");
211 
212  string advName, riemName;
213  m_session->LoadSolverInfo("AdvectionType", advName, "WeakDG");
214 
216  .CreateInstance(advName, advName);
217 
219  {
220  m_advection->SetFluxVector(&CompressibleFlowSystem::
221  GetFluxVectorDeAlias, this);
222  }
223  else
224  {
225  m_advection->SetFluxVector (&CompressibleFlowSystem::
226  GetFluxVector, this);
227  }
228 
229  // Setting up Riemann solver for advection operator
230  m_session->LoadSolverInfo("UpwindType", riemName, "Average");
231 
233  riemannSolver = SolverUtils::GetRiemannSolverFactory()
234  .CreateInstance(riemName);
235 
236  // Setting up parameters for advection operator Riemann solver
237  riemannSolver->SetParam (
238  "gamma", &CompressibleFlowSystem::GetGamma, this);
239  riemannSolver->SetAuxVec(
240  "vecLocs", &CompressibleFlowSystem::GetVecLocs, this);
241  riemannSolver->SetVector(
243 
244  // Concluding initialisation of advection / diffusion operators
245  m_advection->SetRiemannSolver (riemannSolver);
246  m_advection->InitObject (m_session, m_fields);
247  }
248 
249  /**
250  * @brief Compute the right-hand side.
251  */
253  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
254  Array<OneD, Array<OneD, NekDouble> > &outarray,
255  const NekDouble time)
256  {
257  int i;
258  int nvariables = inarray.num_elements();
259  int npoints = GetNpoints();
260  int nTracePts = GetTraceTotPoints();
261 
262  // Store forwards/backwards space along trace space
263  Array<OneD, Array<OneD, NekDouble> > Fwd (nvariables);
264  Array<OneD, Array<OneD, NekDouble> > Bwd (nvariables);
265 
267  {
270  }
271  else
272  {
273  for(i = 0; i < nvariables; ++i)
274  {
275  Fwd[i] = Array<OneD, NekDouble>(nTracePts, 0.0);
276  Bwd[i] = Array<OneD, NekDouble>(nTracePts, 0.0);
277  m_fields[i]->GetFwdBwdTracePhys(inarray[i], Fwd[i], Bwd[i]);
278  }
279  }
280 
281  // Calculate advection
282  DoAdvection(inarray, outarray, time, Fwd, Bwd);
283 
284  // Negate results
285  for (i = 0; i < nvariables; ++i)
286  {
287  Vmath::Neg(npoints, outarray[i], 1);
288  }
289 
290  // Add diffusion terms
291  DoDiffusion(inarray, outarray, Fwd, Bwd);
292 
293  // Add forcing terms
294  std::vector<SolverUtils::ForcingSharedPtr>::const_iterator x;
295  for (x = m_forcing.begin(); x != m_forcing.end(); ++x)
296  {
297  (*x)->Apply(m_fields, inarray, outarray, time);
298  }
299  }
300 
301  /**
302  * @brief Compute the projection and call the method for imposing the
303  * boundary conditions in case of discontinuous projection.
304  */
306  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
307  Array<OneD, Array<OneD, NekDouble> > &outarray,
308  const NekDouble time)
309  {
310  int i;
311  int nvariables = inarray.num_elements();
312 
313  switch(m_projectionType)
314  {
316  {
317  // Just copy over array
318  int npoints = GetNpoints();
319 
320  for(i = 0; i < nvariables; ++i)
321  {
322  Vmath::Vcopy(npoints, inarray[i], 1, outarray[i], 1);
323  }
324  SetBoundaryConditions(outarray, time);
325  break;
326  }
329  {
330  ASSERTL0(false, "No Continuous Galerkin for full compressible "
331  "Navier-Stokes equations");
332  break;
333  }
334  default:
335  ASSERTL0(false, "Unknown projection scheme");
336  break;
337  }
338  }
339 
340  /**
341  * @brief Compute the advection terms for the right-hand side
342  */
344  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
345  Array<OneD, Array<OneD, NekDouble> > &outarray,
346  const NekDouble time,
347  const Array<OneD, Array<OneD, NekDouble> > &pFwd,
348  const Array<OneD, Array<OneD, NekDouble> > &pBwd)
349  {
350  int nvariables = inarray.num_elements();
352 
353  m_advection->Advect(nvariables, m_fields, advVel, inarray,
354  outarray, time, pFwd, pBwd);
355  }
356 
357  /**
358  * @brief Add the diffusions terms to the right-hand side
359  */
361  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
362  Array<OneD, Array<OneD, NekDouble> > &outarray,
363  const Array<OneD, Array<OneD, NekDouble> > &pFwd,
364  const Array<OneD, Array<OneD, NekDouble> > &pBwd)
365  {
366  v_DoDiffusion(inarray, outarray, pFwd, pBwd);
367 
368  if (m_shockCaptureType != "Off")
369  {
370  m_artificialDiffusion->DoArtificialDiffusion(inarray, outarray);
371  }
372  }
373 
375  Array<OneD, Array<OneD, NekDouble> > &physarray,
376  NekDouble time)
377  {
378  int nTracePts = GetTraceTotPoints();
379  int nvariables = physarray.num_elements();
380 
381  Array<OneD, Array<OneD, NekDouble> > Fwd(nvariables);
382  for (int i = 0; i < nvariables; ++i)
383  {
384  Fwd[i] = Array<OneD, NekDouble>(nTracePts);
385  m_fields[i]->ExtractTracePhys(physarray[i], Fwd[i]);
386  }
387 
388  if (m_bndConds.size())
389  {
390  // Loop over user-defined boundary conditions
392  for (x = m_bndConds.begin(); x != m_bndConds.end(); ++x)
393  {
394  (*x)->Apply(Fwd, physarray, time);
395  }
396  }
397  }
398 
399  /**
400  * @brief Return the flux vector for the compressible Euler equations.
401  *
402  * @param physfield Fields.
403  * @param flux Resulting flux.
404  */
406  const Array<OneD, Array<OneD, NekDouble> > &physfield,
408  {
409  int i, j;
410  int nq = physfield[0].num_elements();
411  int nVariables = m_fields.num_elements();
412 
413  Array<OneD, NekDouble> pressure(nq);
415 
416  // Flux vector for the rho equation
417  for (i = 0; i < m_spacedim; ++i)
418  {
419  velocity[i] = Array<OneD, NekDouble>(nq);
420  Vmath::Vcopy(nq, physfield[i+1], 1, flux[0][i], 1);
421  }
422 
423  m_varConv->GetVelocityVector(physfield, velocity);
424  m_varConv->GetPressure(physfield, velocity, pressure);
425 
426  // Flux vector for the velocity fields
427  for (i = 0; i < m_spacedim; ++i)
428  {
429  for (j = 0; j < m_spacedim; ++j)
430  {
431  Vmath::Vmul(nq, velocity[j], 1, physfield[i+1], 1,
432  flux[i+1][j], 1);
433  }
434 
435  // Add pressure to appropriate field
436  Vmath::Vadd(nq, flux[i+1][i], 1, pressure, 1, flux[i+1][i], 1);
437  }
438 
439  // Flux vector for energy.
440  Vmath::Vadd(nq, physfield[m_spacedim+1], 1, pressure, 1,
441  pressure, 1);
442 
443  for (j = 0; j < m_spacedim; ++j)
444  {
445  Vmath::Vmul(nq, velocity[j], 1, pressure, 1,
446  flux[m_spacedim+1][j], 1);
447  }
448 
449  // For the smooth viscosity model
450  if (nVariables == m_spacedim+3)
451  {
452  // Add a zero row for the advective fluxes
453  for (j = 0; j < m_spacedim; ++j)
454  {
455  Vmath::Zero(nq, flux[m_spacedim+2][j], 1);
456  }
457  }
458  }
459 
460  /**
461  * @brief Return the flux vector for the compressible Euler equations
462  * by using the de-aliasing technique.
463  *
464  * @param physfield Fields.
465  * @param flux Resulting flux.
466  */
468  const Array<OneD, Array<OneD, NekDouble> > &physfield,
470  {
471  int i, j;
472  int nq = physfield[0].num_elements();
473  int nVariables = m_fields.num_elements();
474 
475  // Factor to rescale 1d points in dealiasing
476  NekDouble OneDptscale = 2;
477  nq = m_fields[0]->Get1DScaledTotPoints(OneDptscale);
478 
479  Array<OneD, NekDouble> pressure(nq);
481 
482  Array<OneD, Array<OneD, NekDouble> > physfield_interp(nVariables);
484  nVariables);
485 
486  for (i = 0; i < nVariables; ++ i)
487  {
488  physfield_interp[i] = Array<OneD, NekDouble>(nq);
490  m_fields[0]->PhysInterp1DScaled(
491  OneDptscale, physfield[i], physfield_interp[i]);
492 
493  for (j = 0; j < m_spacedim; ++j)
494  {
495  flux_interp[i][j] = Array<OneD, NekDouble>(nq);
496  }
497  }
498 
499  // Flux vector for the rho equation
500  for (i = 0; i < m_spacedim; ++i)
501  {
502  velocity[i] = Array<OneD, NekDouble>(nq);
503 
504  // Galerkin project solution back to original space
505  m_fields[0]->PhysGalerkinProjection1DScaled(
506  OneDptscale, physfield_interp[i+1], flux[0][i]);
507  }
508 
509  m_varConv->GetVelocityVector(physfield_interp, velocity);
510  m_varConv->GetPressure (physfield_interp, velocity, pressure);
511 
512  // Evaluation of flux vector for the velocity fields
513  for (i = 0; i < m_spacedim; ++i)
514  {
515  for (j = 0; j < m_spacedim; ++j)
516  {
517  Vmath::Vmul(nq, velocity[j], 1, physfield_interp[i+1], 1,
518  flux_interp[i+1][j], 1);
519  }
520 
521  // Add pressure to appropriate field
522  Vmath::Vadd(nq, flux_interp[i+1][i], 1, pressure,1,
523  flux_interp[i+1][i], 1);
524  }
525 
526  // Galerkin project solution back to origianl space
527  for (i = 0; i < m_spacedim; ++i)
528  {
529  for (j = 0; j < m_spacedim; ++j)
530  {
531  m_fields[0]->PhysGalerkinProjection1DScaled(
532  OneDptscale, flux_interp[i+1][j], flux[i+1][j]);
533  }
534  }
535 
536  // Evaluation of flux vector for energy
537  Vmath::Vadd(nq, physfield_interp[m_spacedim+1], 1, pressure, 1,
538  pressure, 1);
539 
540  for (j = 0; j < m_spacedim; ++j)
541  {
542  Vmath::Vmul(nq, velocity[j], 1, pressure, 1,
543  flux_interp[m_spacedim+1][j], 1);
544 
545  // Galerkin project solution back to origianl space
546  m_fields[0]->PhysGalerkinProjection1DScaled(
547  OneDptscale,
548  flux_interp[m_spacedim+1][j],
549  flux[m_spacedim+1][j]);
550  }
551  }
552 
553  /**
554  * @brief Perform post-integration checks, presently just to check steady
555  * state behaviour.
556  */
558  {
559  if (m_steadyStateTol > 0.0)
560  {
561  bool doOutput = step % m_infosteps == 0;
562  if (CalcSteadyState(doOutput))
563  {
564  if (m_comm->GetRank() == 0)
565  {
566  cout << "Reached Steady State to tolerance "
567  << m_steadyStateTol << endl;
568  }
569  return true;
570  }
571  }
572  return false;
573  }
574 
575  /**
576  * @brief Calculate whether the system has reached a steady state by
577  * observing residuals to a user-defined tolerance.
578  */
580  {
581  const int nPoints = GetTotPoints();
582  const int nFields = m_fields.num_elements();
583 
584  // Holds L2 errors.
585  Array<OneD, NekDouble> L2 (nFields);
586  Array<OneD, NekDouble> residual(nFields);
587 
588  for (int i = 0; i < nFields; ++i)
589  {
590  Array<OneD, NekDouble> diff(nPoints);
591 
592  Vmath::Vsub(nPoints, m_fields[i]->GetPhys(), 1, m_un[i], 1, diff, 1);
593  Vmath::Vmul(nPoints, diff, 1, diff, 1, diff, 1);
594  residual[i] = Vmath::Vsum(nPoints, diff, 1);
595  }
596 
597  m_comm->AllReduce(residual, LibUtilities::ReduceSum);
598 
599  // L2 error
600  L2[0] = sqrt(residual[0]) / m_rhoInf;
601 
602  for (int i = 1; i < nFields-1; ++i)
603  {
604  L2[i] = sqrt(residual[i]) / m_UInf / m_rhoInf;
605  }
606 
607  NekDouble Einf = m_pInf / (m_gamma-1.0) + 0.5 * m_rhoInf * m_UInf;
608  L2[nFields-1] = sqrt(residual[nFields-1]) / Einf;
609 
610  if (m_comm->GetRank() == 0 && output)
611  {
612  // Output time
613  m_errFile << setprecision(8) << setw(17) << scientific << m_time;
614 
615  // Output residuals
616  for (int i = 0; i < nFields; ++i)
617  {
618  m_errFile << setprecision(11) << setw(22) << scientific
619  << L2[i];
620  }
621 
622  m_errFile << endl;
623  }
624 
625  // Calculate maximum L2 error
626  NekDouble maxL2 = Vmath::Vmax(nFields, L2, 1);
627 
628  if (m_session->DefinesCmdLineArgument("verbose") &&
629  m_comm->GetRank() == 0 && output)
630  {
631  cout << "-- Maximum L^2 residual: " << maxL2 << endl;
632  }
633 
634  if (maxL2 <= m_steadyStateTol)
635  {
636  return true;
637  }
638 
639  for (int i = 0; i < m_fields.num_elements(); ++i)
640  {
641  Vmath::Vcopy(nPoints, m_fields[i]->GetPhys(), 1, m_un[i], 1);
642  }
643 
644  return false;
645  }
646 
647  /**
648  * @brief Calculate the maximum timestep subject to CFL restrictions.
649  */
651  const Array<OneD, const Array<OneD, NekDouble> > &inarray)
652  {
653  int n;
654  int nElements = m_fields[0]->GetExpSize();
655  const Array<OneD, int> ExpOrder = GetNumExpModesPerExp();
656 
657  Array<OneD, NekDouble> tstep (nElements, 0.0);
658  Array<OneD, NekDouble> stdVelocity(nElements);
659 
660  // Get standard velocity to compute the time-step limit
661  GetStdVelocity(inarray, stdVelocity);
662 
663  // Factors to compute the time-step limit
664  NekDouble minLength = 0.0;
666  NekDouble cLambda = 0.2; // Spencer book-317
667 
668  // Loop over elements to compute the time-step limit for each element
669  for(n = 0; n < nElements; ++n)
670  {
671  int npoints = m_fields[0]->GetExp(n)->GetTotPoints();
672  Array<OneD, NekDouble> one2D(npoints, 1.0);
673  NekDouble Area = m_fields[0]->GetExp(n)->Integral(one2D);
674 
675  minLength = sqrt(Area);
676  if (m_fields[0]->GetExp(n)->as<LocalRegions::TriExp>())
677  {
678  minLength *= 2.0;
679  }
680 
681  tstep[n] = m_cflSafetyFactor * alpha * minLength
682  / (stdVelocity[n] * cLambda
683  * (ExpOrder[n] - 1) * (ExpOrder[n] - 1));
684  }
685 
686  // Get the minimum time-step limit and return the time-step
687  NekDouble TimeStep = Vmath::Vmin(nElements, tstep, 1);
688  m_comm->AllReduce(TimeStep, LibUtilities::ReduceMin);
689  return TimeStep;
690  }
691 
692  /**
693  * @brief Set up logic for residual calculation.
694  */
696  NekDouble initialtime,
697  bool dumpInitialConditions,
698  const int domain)
699  {
700  EquationSystem::v_SetInitialConditions(initialtime, false);
701 
702  // insert white noise in initial condition
703  NekDouble Noise;
704  int phystot = m_fields[0]->GetTotPoints();
705  Array<OneD, NekDouble> noise(phystot);
706 
707  m_session->LoadParameter("Noise", Noise,0.0);
708  int m_nConvectiveFields = m_fields.num_elements();
709 
710  if (Noise > 0.0)
711  {
712  int seed = - m_comm->GetRank()*m_nConvectiveFields;
713  for (int i = 0; i < m_nConvectiveFields; i++)
714  {
715  Vmath::FillWhiteNoise(phystot, Noise, noise, 1,
716  seed);
717  --seed;
718  Vmath::Vadd(phystot, m_fields[i]->GetPhys(), 1,
719  noise, 1, m_fields[i]->UpdatePhys(), 1);
720  m_fields[i]->FwdTrans_IterPerExp(m_fields[i]->GetPhys(),
721  m_fields[i]->UpdateCoeffs());
722  }
723  }
724 
726 
727  if (dumpInitialConditions)
728  {
729  // Dump initial conditions to file
731  }
732  }
733 
735  {
736  if (m_session->DefinesParameter("SteadyStateTol"))
737  {
738  const int nPoints = m_fields[0]->GetTotPoints();
740  m_fields.num_elements());
741 
742  for (int i = 0; i < m_fields.num_elements(); ++i)
743  {
744  m_un[i] = Array<OneD, NekDouble>(nPoints);
745  Vmath::Vcopy(nPoints, m_fields[i]->GetPhys(), 1, m_un[i], 1);
746  }
747 
748  if (m_comm->GetRank() == 0)
749  {
750  std::string fName = m_session->GetSessionName() +
751  std::string(".res");
752  m_errFile.open(fName.c_str());
753  m_errFile << "# "
754  << setw(15) << left << "Time"
755  << setw(22) << left << "rho";
756 
757  std::string velFields[3] = {"u", "v", "w"};
758 
759  for (int i = 0; i < m_fields.num_elements()-2; ++i)
760  {
761  m_errFile << setw(22) << "rho"+velFields[i];
762  }
763 
764  m_errFile << setw(22) << left << "E" << endl;
765  }
766  }
767  }
768 
769 
770  /**
771  * @brief Compute the advection velocity in the standard space
772  * for each element of the expansion.
773  *
774  * @param inarray Momentum field.
775  * @param stdV Standard velocity field.
776  */
778  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
780  {
781  int nTotQuadPoints = GetTotPoints();
782  int n_element = m_fields[0]->GetExpSize();
783  int nBCEdgePts = 0;
784 
785  // Getting the velocity vector on the 2D normal space
788  Array<OneD, NekDouble> pressure (nTotQuadPoints);
789  Array<OneD, NekDouble> soundspeed (nTotQuadPoints);
791 
792  // Zero output array
793  Vmath::Zero(stdV.num_elements(), stdV, 1);
794 
795  for (int i = 0; i < m_spacedim; ++i)
796  {
797  velocity [i] = Array<OneD, NekDouble>(nTotQuadPoints);
798  stdVelocity[i] = Array<OneD, NekDouble>(nTotQuadPoints, 0.0);
799  }
800 
801  m_varConv->GetVelocityVector(inarray, velocity);
802  m_varConv->GetPressure (inarray, velocity, pressure);
803  m_varConv->GetSoundSpeed (inarray, pressure, soundspeed);
804 
805  for(int el = 0; el < n_element; ++el)
806  {
807  ptsKeys = m_fields[0]->GetExp(el)->GetPointsKeys();
808 
809  // Possible bug: not multiply by jacobian??
810  const SpatialDomains::GeomFactorsSharedPtr metricInfo =
811  m_fields[0]->GetExp(el)->GetGeom()->GetMetricInfo();
812  const Array<TwoD, const NekDouble> &gmat =
813  m_fields[0]->GetExp(el)->GetGeom()->GetMetricInfo()
814  ->GetDerivFactors(ptsKeys);
815 
816  int nq = m_fields[0]->GetExp(el)->GetTotPoints();
817 
818  if(metricInfo->GetGtype() == SpatialDomains::eDeformed)
819  {
820  // d xi/ dx = gmat = 1/J * d x/d xi
821  for (int i = 0; i < m_spacedim; ++i)
822  {
823  Vmath::Vmul(nq, gmat[i], 1, velocity[0], 1,
824  stdVelocity[i], 1);
825  for (int j = 1; j < m_spacedim; ++j)
826  {
827  Vmath::Vvtvp(nq, gmat[m_spacedim*j+i], 1, velocity[j],
828  1, stdVelocity[i], 1, stdVelocity[i], 1);
829  }
830  }
831  }
832  else
833  {
834  for (int i = 0; i < m_spacedim; ++i)
835  {
836  Vmath::Smul(nq, gmat[i][0], velocity[0], 1,
837  stdVelocity[i], 1);
838  for (int j = 1; j < m_spacedim; ++j)
839  {
840  Vmath::Svtvp(nq, gmat[m_spacedim*j+i][0], velocity[j],
841  1, stdVelocity[i], 1, stdVelocity[i], 1);
842  }
843  }
844  }
845 
846  for (int i = 0; i < nq; ++i)
847  {
848  NekDouble pntVelocity = 0.0;
849  for (int j = 0; j < m_spacedim; ++j)
850  {
851  pntVelocity += stdVelocity[j][i]*stdVelocity[j][i];
852  }
853  pntVelocity = sqrt(pntVelocity) + soundspeed[nBCEdgePts];
854  if (pntVelocity > stdV[el])
855  {
856  stdV[el] = pntVelocity;
857  }
858  nBCEdgePts++;
859  }
860  }
861  }
862 
863  /**
864  * @brief Set the denominator to compute the time step when a cfl
865  * control is employed. This function is no longer used but is still
866  * here for being utilised in the future.
867  *
868  * @param n Order of expansion element by element.
869  */
871  {
872  ASSERTL0(n <= 20, "Illegal modes dimension for CFL calculation "
873  "(P has to be less then 20)");
874 
875  NekDouble CFLDG[21] = { 2.0000, 6.0000, 11.8424, 19.1569,
876  27.8419, 37.8247, 49.0518, 61.4815,
877  75.0797, 89.8181, 105.6700, 122.6200,
878  140.6400, 159.7300, 179.8500, 201.0100,
879  223.1800, 246.3600, 270.5300, 295.6900,
880  321.8300}; //CFLDG 1D [0-20]
881  NekDouble CFL = 0.0;
882 
884  {
885  CFL = CFLDG[n];
886  }
887  else
888  {
889  ASSERTL0(false, "Continuous Galerkin stability coefficients "
890  "not introduced yet.");
891  }
892 
893  return CFL;
894  }
895 
896  /**
897  * @brief Compute the vector of denominators to compute the time step
898  * when a cfl control is employed. This function is no longer used but
899  * is still here for being utilised in the future.
900  *
901  * @param ExpOrder Order of expansion element by element.
902  */
904  const Array<OneD,int> &ExpOrder)
905  {
906  int i;
907  Array<OneD,NekDouble> returnval(m_fields[0]->GetExpSize(), 0.0);
908  for (i =0; i<m_fields[0]->GetExpSize(); i++)
909  {
910  returnval[i] = GetStabilityLimit(ExpOrder[i]);
911  }
912  return returnval;
913  }
914 
916  std::vector<Array<OneD, NekDouble> > &fieldcoeffs,
917  std::vector<std::string> &variables)
918  {
919  bool extraFields;
920  m_session->MatchSolverInfo("OutputExtraFields","True",
921  extraFields, true);
922  if (extraFields)
923  {
924  const int nPhys = m_fields[0]->GetNpoints();
925  const int nCoeffs = m_fields[0]->GetNcoeffs();
926  Array<OneD, Array<OneD, NekDouble> > tmp(m_fields.num_elements());
927 
928  for (int i = 0; i < m_fields.num_elements(); ++i)
929  {
930  tmp[i] = m_fields[i]->GetPhys();
931  }
932 
933  Array<OneD, NekDouble> pressure(nPhys), soundspeed(nPhys), mach(nPhys);
934  Array<OneD, NekDouble> sensor(nPhys), SensorKappa(nPhys);
935 
936  m_varConv->GetPressure (tmp, pressure);
937  m_varConv->GetSoundSpeed(tmp, pressure, soundspeed);
938  m_varConv->GetMach (tmp, soundspeed, mach);
939  m_varConv->GetSensor (m_fields[0], tmp, sensor, SensorKappa);
940 
941  Array<OneD, NekDouble> pFwd(nCoeffs), sFwd(nCoeffs), mFwd(nCoeffs);
942  Array<OneD, NekDouble> sensFwd(nCoeffs);
943 
944  m_fields[0]->FwdTrans_IterPerExp(pressure, pFwd);
945  m_fields[0]->FwdTrans_IterPerExp(soundspeed, sFwd);
946  m_fields[0]->FwdTrans_IterPerExp(mach, mFwd);
947  m_fields[0]->FwdTrans_IterPerExp(sensor, sensFwd);
948 
949  variables.push_back ("p");
950  variables.push_back ("a");
951  variables.push_back ("Mach");
952  variables.push_back ("Sensor");
953  fieldcoeffs.push_back(pFwd);
954  fieldcoeffs.push_back(sFwd);
955  fieldcoeffs.push_back(mFwd);
956  fieldcoeffs.push_back(sensFwd);
957 
959  {
960  // reuse pressure
961  m_artificialDiffusion->GetArtificialViscosity(tmp, pressure);
962  m_fields[0]->FwdTrans_IterPerExp(pressure, pFwd);
963 
964  variables.push_back ("ArtificialVisc");
965  fieldcoeffs.push_back(pFwd);
966  }
967  }
968  }
969 }
void 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)
Add the diffusions terms to the right-hand side.
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:198
virtual void v_InitObject()
Initialization object for CompressibleFlowSystem class.
std::vector< PointsKey > PointsKeyVector
Definition: Points.h:242
virtual ~CompressibleFlowSystem()
Destructor for CompressibleFlowSystem class.
bool m_homoInitialFwd
Flag to determine if simulation should start in homogeneous forward transformed state.
tBaseSharedPtr CreateInstance(tKey idKey BOOST_PP_COMMA_IF(MAX_PARAM) BOOST_PP_ENUM_BINARY_PARAMS(MAX_PARAM, tParam, x))
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:162
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
NekDouble m_time
Current time of simulation.
void GetStdVelocity(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, NekDouble > &stdV)
Compute the advection velocity in the standard space for each element of the expansion.
T Vmax(int n, const T *x, const int incx)
Return the maximum element in x – called vmax to avoid conflict with max.
Definition: Vmath.cpp:779
LibUtilities::TimeIntegrationSchemeOperators m_ode
The time integration scheme operators to use.
VariableConverterSharedPtr m_varConv
T Vmin(int n, const T *x, const int incx)
Return the minimum element in x - called vmin to avoid conflict with min.
Definition: Vmath.cpp:871
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)
SOLVER_UTILS_EXPORT const Array< OneD, int > GetNumExpModesPerExp()
NekDouble GetStabilityLimit(int n)
Function to calculate the stability limit for DG/CG.
SOLVER_UTILS_EXPORT void Checkpoint_Output(const int n)
Write checkpoint file of m_fields.
virtual void v_ExtraFldOutput(std::vector< Array< OneD, NekDouble > > &fieldcoeffs, std::vector< std::string > &variables)
void Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
svtvp (scalar times vector plus vector): z = alpha*x + y
Definition: Vmath.cpp:485
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:442
enum MultiRegions::ProjectionType m_projectionType
Type of projection; e.g continuous or discontinuous.
STL namespace.
bool m_specHP_dealiasing
Flag to determine if dealisising is usde for the Spectral/hp element discretisation.
static SOLVER_UTILS_EXPORT std::vector< ForcingSharedPtr > Load(const LibUtilities::SessionReaderSharedPtr &pSession, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const unsigned int &pNumForcingFields=0)
Definition: Forcing.cpp:86
Array< OneD, Array< OneD, NekDouble > > m_vecLocs
Array< OneD, Array< OneD, NekDouble > > m_un
SOLVER_UTILS_EXPORT NekDouble MaxTimeStepEstimator()
Get the maximum timestep estimator for cfl control.
boost::shared_ptr< RiemannSolver > RiemannSolverSharedPtr
A shared pointer to an EquationSystem object.
boost::shared_ptr< SessionReader > SessionReaderSharedPtr
Definition: MeshPartition.h:51
virtual NekDouble v_GetTimeStep(const Array< OneD, const Array< OneD, NekDouble > > &inarray)
Calculate the maximum timestep subject to CFL restrictions.
void DoOdeRhs(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
Compute the right-hand side.
LibUtilities::CommSharedPtr m_comm
Communicator.
void DoOdeProjection(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
Compute the projection and call the method for imposing the boundary conditions in case of discontinu...
SOLVER_UTILS_EXPORT int GetTotPoints()
Array< OneD, Array< OneD, NekDouble > > m_traceNormals
Array holding trace normals for DG simulations in the forwards direction.
void DefineProjection(FuncPointerT func, ObjectPointerT obj)
CFSBndCondFactory & GetCFSBndCondFactory()
Declaration of the boundary condition factory singleton.
Definition: CFSBndCond.cpp:42
const Array< OneD, const Array< OneD, NekDouble > > & GetVecLocs()
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:213
bool m_explicitAdvection
Indicates if explicit or implicit treatment of advection is used.
void DefineOdeRhs(FuncPointerT func, ObjectPointerT obj)
void GetFluxVectorDeAlias(const Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &flux)
Return the flux vector for the compressible Euler equations by using the de-aliasing technique...
Base class for unsteady solvers.
RiemannSolverFactory & GetRiemannSolverFactory()
Array< OneD, NekDouble > GetStabilityLimitVector(const Array< OneD, int > &ExpOrder)
Function to calculate the stability limit for DG/CG (a vector of them).
int m_spacedim
Spatial dimension (>= expansion dim).
void SetBoundaryConditions(Array< OneD, Array< OneD, NekDouble > > &physarray, NekDouble time)
void InitialiseParameters()
Load CFS parameters from the session file.
AdvectionFactory & GetAdvectionFactory()
Gets the factory for initialising advection objects.
Definition: Advection.cpp:46
ArtificialDiffusionFactory & GetArtificialDiffusionFactory()
Declaration of the artificial diffusion factory singleton.
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:396
double NekDouble
virtual SOLVER_UTILS_EXPORT void v_SetInitialConditions(NekDouble initialtime=0.0, bool dumpInitialConditions=true, const int domain=0)
virtual SOLVER_UTILS_EXPORT void v_InitObject()
Init object for UnsteadySystem class.
virtual void v_SetInitialConditions(NekDouble initialtime=0.0, bool dumpInitialConditions=true, const int domain=0)
Set up logic for residual calculation.
NekDouble m_cflSafetyFactor
CFL safety factor (comprise between 0 to 1).
virtual bool v_PostIntegrate(int step)
Perform post-integration checks, presently just to check steady state behaviour.
bool CalcSteadyState(bool output)
Calculate whether the system has reached a steady state by observing residuals to a user-defined tole...
void DoAdvection(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time, const Array< OneD, Array< OneD, NekDouble > > &pFwd, const Array< OneD, Array< OneD, NekDouble > > &pBwd)
Compute the advection terms for the right-hand side.
SolverUtils::AdvectionSharedPtr m_advection
void InitAdvection()
Create advection and diffusion objects for CFS.
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:343
SOLVER_UTILS_EXPORT int GetTraceTotPoints()
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
SOLVER_UTILS_EXPORT int GetNpoints()
const Array< OneD, const Array< OneD, NekDouble > > & GetNormals()
boost::shared_ptr< GeomFactors > GeomFactorsSharedPtr
Pointer to a GeomFactors object.
Definition: GeomFactors.h:62
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
SOLVER_UTILS_EXPORT int GetExpSize()
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
ArtificialDiffusionSharedPtr m_artificialDiffusion
void FillWhiteNoise(int n, const T eps, T *x, const int incx, int outseed)
Fills a vector with white noise.
Definition: Vmath.cpp:138
int m_infosteps
Number of time steps between outputting status information.
static Array< OneD, Array< OneD, NekDouble > > NullNekDoubleArrayofArray
void GetFluxVector(const Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &flux)
Return the flux vector for the compressible Euler equations.
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition: Vmath.cpp:737
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:373
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1061
Geometry is curved or has non-constant factors.
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
std::vector< CFSBndCondSharedPtr > m_bndConds
enum HomogeneousType m_HomogeneousType
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:299
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:183