Nektar++
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 // 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: Compressible flow system base class with auxiliary functions
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <boost/core/ignore_unused.hpp>
36 
38 
39 using namespace std;
40 
41 namespace Nektar
42 {
43  CompressibleFlowSystem::CompressibleFlowSystem(
46  : UnsteadySystem(pSession, pGraph),
47  AdvectionSystem(pSession, pGraph)
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
92  m_forcing = SolverUtils::Forcing::Load(m_session, shared_from_this(),
93  m_fields, 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 
102  if (m_fields[0]->GetBndConditions()[n]->GetBoundaryConditionType()
104  {
105  continue;
106  }
107 
108  if(!type.empty())
109  {
110  m_bndConds.push_back(GetCFSBndCondFactory().CreateInstance(
111  type,
112  m_session,
113  m_fields,
115  m_spacedim,
116  n,
117  cnt));
118  }
119  cnt += m_fields[0]->GetBndCondExpansions()[n]->GetExpSize();
120  }
121 
123  {
126  }
127  else
128  {
129  ASSERTL0(false, "Implicit CFS not set up.");
130  }
131  }
132 
133  /**
134  * @brief Destructor for CompressibleFlowSystem class.
135  */
137  {
138 
139  }
140 
141  /**
142  * @brief Load CFS parameters from the session file
143  */
145  {
146  // Get gamma parameter from session file.
147  m_session->LoadParameter("Gamma", m_gamma, 1.4);
148 
149  // Shock capture
150  m_session->LoadSolverInfo("ShockCaptureType",
151  m_shockCaptureType, "Off");
152 
153  // Load parameters for exponential filtering
154  m_session->MatchSolverInfo("ExponentialFiltering","True",
155  m_useFiltering, false);
156  if(m_useFiltering)
157  {
158  m_session->LoadParameter ("FilterAlpha", m_filterAlpha, 36);
159  m_session->LoadParameter ("FilterExponent", m_filterExponent, 16);
160  m_session->LoadParameter ("FilterCutoff", m_filterCutoff, 0);
161  }
162 
163  // Load CFL for local time-stepping (for steady state)
164  m_session->MatchSolverInfo("LocalTimeStep","True",
165  m_useLocalTimeStep, false);
167  {
169  "Local time stepping requires CFL parameter.");
170  }
171  }
172 
173  /**
174  * @brief Create advection and diffusion objects for CFS
175  */
177  {
178  // Check if projection type is correct
180  "Unsupported projection type.");
181 
182  string advName, riemName;
183  m_session->LoadSolverInfo("AdvectionType", advName, "WeakDG");
184 
186  .CreateInstance(advName, advName);
187 
189  {
190  m_advObject->SetFluxVector(&CompressibleFlowSystem::
191  GetFluxVectorDeAlias, this);
192  }
193  else
194  {
195  m_advObject->SetFluxVector (&CompressibleFlowSystem::
196  GetFluxVector, this);
197  }
198 
199  // Setting up Riemann solver for advection operator
200  m_session->LoadSolverInfo("UpwindType", riemName, "Average");
201 
203  riemannSolver = SolverUtils::GetRiemannSolverFactory()
204  .CreateInstance(riemName, m_session);
205 
206  // Setting up parameters for advection operator Riemann solver
207  riemannSolver->SetParam (
208  "gamma", &CompressibleFlowSystem::GetGamma, this);
209  riemannSolver->SetAuxVec(
210  "vecLocs", &CompressibleFlowSystem::GetVecLocs, this);
211  riemannSolver->SetVector(
213 
214  // Concluding initialisation of advection / diffusion operators
215  m_advObject->SetRiemannSolver (riemannSolver);
216  m_advObject->InitObject (m_session, m_fields);
217  }
218 
219  /**
220  * @brief Compute the right-hand side.
221  */
223  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
224  Array<OneD, Array<OneD, NekDouble> > &outarray,
225  const NekDouble time)
226  {
227  int i;
228  int nvariables = inarray.num_elements();
229  int npoints = GetNpoints();
230  int nTracePts = GetTraceTotPoints();
231 
232  // Store forwards/backwards space along trace space
233  Array<OneD, Array<OneD, NekDouble> > Fwd (nvariables);
234  Array<OneD, Array<OneD, NekDouble> > Bwd (nvariables);
235 
237  {
240  }
241  else
242  {
243  for(i = 0; i < nvariables; ++i)
244  {
245  Fwd[i] = Array<OneD, NekDouble>(nTracePts, 0.0);
246  Bwd[i] = Array<OneD, NekDouble>(nTracePts, 0.0);
247  m_fields[i]->GetFwdBwdTracePhys(inarray[i], Fwd[i], Bwd[i]);
248  }
249  }
250 
251  // Calculate advection
252  DoAdvection(inarray, outarray, time, Fwd, Bwd);
253 
254  // Negate results
255  for (i = 0; i < nvariables; ++i)
256  {
257  Vmath::Neg(npoints, outarray[i], 1);
258  }
259 
260  // Add diffusion terms
261  DoDiffusion(inarray, outarray, Fwd, Bwd);
262 
263  // Add forcing terms
264  for (auto &x : m_forcing)
265  {
266  x->Apply(m_fields, inarray, outarray, time);
267  }
268 
269  if (m_useLocalTimeStep)
270  {
271  int nElements = m_fields[0]->GetExpSize();
272  int nq, offset;
273  NekDouble fac;
275 
276  Array<OneD, NekDouble> tstep (nElements, 0.0);
277  GetElmtTimeStep(inarray, tstep);
278 
279  // Loop over elements
280  for(int n = 0; n < nElements; ++n)
281  {
282  nq = m_fields[0]->GetExp(n)->GetTotPoints();
283  offset = m_fields[0]->GetPhys_Offset(n);
284  fac = tstep[n] / m_timestep;
285  for(i = 0; i < nvariables; ++i)
286  {
287  Vmath::Smul(nq, fac, outarray[i] + offset, 1,
288  tmp = outarray[i] + offset, 1);
289  }
290  }
291  }
292  }
293 
294  /**
295  * @brief Compute the projection and call the method for imposing the
296  * boundary conditions in case of discontinuous projection.
297  */
299  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
300  Array<OneD, Array<OneD, NekDouble> > &outarray,
301  const NekDouble time)
302  {
303  int i;
304  int nvariables = inarray.num_elements();
305 
306  switch(m_projectionType)
307  {
309  {
310  // Just copy over array
311  int npoints = GetNpoints();
312 
313  for(i = 0; i < nvariables; ++i)
314  {
315  Vmath::Vcopy(npoints, inarray[i], 1, outarray[i], 1);
316  if(m_useFiltering)
317  {
318  m_fields[i]->ExponentialFilter(outarray[i],
320  }
321  }
322  SetBoundaryConditions(outarray, time);
323  break;
324  }
327  {
328  ASSERTL0(false, "No Continuous Galerkin for full compressible "
329  "Navier-Stokes equations");
330  break;
331  }
332  default:
333  ASSERTL0(false, "Unknown projection scheme");
334  break;
335  }
336  }
337 
338  /**
339  * @brief Compute the advection terms for the right-hand side
340  */
342  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
343  Array<OneD, Array<OneD, NekDouble> > &outarray,
344  const NekDouble time,
345  const Array<OneD, Array<OneD, NekDouble> > &pFwd,
346  const Array<OneD, Array<OneD, NekDouble> > &pBwd)
347  {
348  int nvariables = inarray.num_elements();
350 
351  m_advObject->Advect(nvariables, m_fields, advVel, inarray,
352  outarray, time, pFwd, pBwd);
353  }
354 
355  /**
356  * @brief Add the diffusions terms to the right-hand side
357  */
359  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
360  Array<OneD, Array<OneD, NekDouble> > &outarray,
361  const Array<OneD, Array<OneD, NekDouble> > &pFwd,
362  const Array<OneD, Array<OneD, NekDouble> > &pBwd)
363  {
364  v_DoDiffusion(inarray, outarray, pFwd, pBwd);
365 
366  if (m_shockCaptureType != "Off")
367  {
368  // Get min h/p
369  m_artificialDiffusion->SetElmtHP(GetElmtMinHP());
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
391  for (auto &x : m_bndConds)
392  {
393  x->Apply(Fwd, physarray, time);
394  }
395  }
396  }
397 
398  /**
399  * @brief Return the flux vector for the compressible Euler equations.
400  *
401  * @param physfield Fields.
402  * @param flux Resulting flux.
403  */
405  const Array<OneD, Array<OneD, NekDouble> > &physfield,
407  {
408  int i, j;
409  int nq = physfield[0].num_elements();
410  int nVariables = m_fields.num_elements();
411 
414 
415  // Flux vector for the rho equation
416  for (i = 0; i < m_spacedim; ++i)
417  {
418  velocity[i] = Array<OneD, NekDouble>(nq);
419  Vmath::Vcopy(nq, physfield[i+1], 1, flux[0][i], 1);
420  }
421 
422  m_varConv->GetVelocityVector(physfield, velocity);
423  m_varConv->GetPressure(physfield, pressure);
424 
425  // Flux vector for the velocity fields
426  for (i = 0; i < m_spacedim; ++i)
427  {
428  for (j = 0; j < m_spacedim; ++j)
429  {
430  Vmath::Vmul(nq, velocity[j], 1, physfield[i+1], 1,
431  flux[i+1][j], 1);
432  }
433 
434  // Add pressure to appropriate field
435  Vmath::Vadd(nq, flux[i+1][i], 1, pressure, 1, flux[i+1][i], 1);
436  }
437 
438  // Flux vector for energy.
439  Vmath::Vadd(nq, physfield[m_spacedim+1], 1, pressure, 1,
440  pressure, 1);
441 
442  for (j = 0; j < m_spacedim; ++j)
443  {
444  Vmath::Vmul(nq, velocity[j], 1, pressure, 1,
445  flux[m_spacedim+1][j], 1);
446  }
447 
448  // For the smooth viscosity model
449  if (nVariables == m_spacedim+3)
450  {
451  // Add a zero row for the advective fluxes
452  for (j = 0; j < m_spacedim; ++j)
453  {
454  Vmath::Zero(nq, flux[m_spacedim+2][j], 1);
455  }
456  }
457  }
458 
459  /**
460  * @brief Return the flux vector for the compressible Euler equations
461  * by using the de-aliasing technique.
462  *
463  * @param physfield Fields.
464  * @param flux Resulting flux.
465  */
467  const Array<OneD, Array<OneD, NekDouble> > &physfield,
469  {
470  int i, j;
471  int nq = physfield[0].num_elements();
472  int nVariables = m_fields.num_elements();
473 
474  // Factor to rescale 1d points in dealiasing
475  NekDouble OneDptscale = 2;
476  nq = m_fields[0]->Get1DScaledTotPoints(OneDptscale);
477 
480 
481  Array<OneD, Array<OneD, NekDouble> > physfield_interp(nVariables);
483  nVariables);
484 
485  for (i = 0; i < nVariables; ++ i)
486  {
487  physfield_interp[i] = Array<OneD, NekDouble>(nq);
489  m_fields[0]->PhysInterp1DScaled(
490  OneDptscale, physfield[i], physfield_interp[i]);
491 
492  for (j = 0; j < m_spacedim; ++j)
493  {
494  flux_interp[i][j] = Array<OneD, NekDouble>(nq);
495  }
496  }
497 
498  // Flux vector for the rho equation
499  for (i = 0; i < m_spacedim; ++i)
500  {
501  velocity[i] = Array<OneD, NekDouble>(nq);
502 
503  // Galerkin project solution back to original space
504  m_fields[0]->PhysGalerkinProjection1DScaled(
505  OneDptscale, physfield_interp[i+1], flux[0][i]);
506  }
507 
508  m_varConv->GetVelocityVector(physfield_interp, velocity);
509  m_varConv->GetPressure (physfield_interp, pressure);
510 
511  // Evaluation of flux vector for the velocity fields
512  for (i = 0; i < m_spacedim; ++i)
513  {
514  for (j = 0; j < m_spacedim; ++j)
515  {
516  Vmath::Vmul(nq, velocity[j], 1, physfield_interp[i+1], 1,
517  flux_interp[i+1][j], 1);
518  }
519 
520  // Add pressure to appropriate field
521  Vmath::Vadd(nq, flux_interp[i+1][i], 1, pressure,1,
522  flux_interp[i+1][i], 1);
523  }
524 
525  // Galerkin project solution back to original space
526  for (i = 0; i < m_spacedim; ++i)
527  {
528  for (j = 0; j < m_spacedim; ++j)
529  {
530  m_fields[0]->PhysGalerkinProjection1DScaled(
531  OneDptscale, flux_interp[i+1][j], flux[i+1][j]);
532  }
533  }
534 
535  // Evaluation of flux vector for energy
536  Vmath::Vadd(nq, physfield_interp[m_spacedim+1], 1, pressure, 1,
537  pressure, 1);
538 
539  for (j = 0; j < m_spacedim; ++j)
540  {
541  Vmath::Vmul(nq, velocity[j], 1, pressure, 1,
542  flux_interp[m_spacedim+1][j], 1);
543 
544  // Galerkin project solution back to original space
545  m_fields[0]->PhysGalerkinProjection1DScaled(
546  OneDptscale,
547  flux_interp[m_spacedim+1][j],
548  flux[m_spacedim+1][j]);
549  }
550  }
551 
552  /**
553  * @brief Calculate the maximum timestep on each element
554  * subject to CFL restrictions.
555  */
557  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
558  Array<OneD, NekDouble> &tstep)
559  {
560  boost::ignore_unused(inarray);
561 
562  int n;
563  int nElements = m_fields[0]->GetExpSize();
564 
565  // Change value of m_timestep (in case it is set to zero)
566  NekDouble tmp = m_timestep;
567  m_timestep = 1.0;
568 
569  Array<OneD, NekDouble> cfl(nElements);
570  cfl = GetElmtCFLVals();
571 
572  // Factors to compute the time-step limit
574 
575  // Loop over elements to compute the time-step limit for each element
576  for(n = 0; n < nElements; ++n)
577  {
578  tstep[n] = m_cflSafetyFactor * alpha / cfl[n];
579  }
580 
581  // Restore value of m_timestep
582  m_timestep = tmp;
583  }
584 
585  /**
586  * @brief Calculate the maximum timestep subject to CFL restrictions.
587  */
589  const Array<OneD, const Array<OneD, NekDouble> > &inarray)
590  {
591  int nElements = m_fields[0]->GetExpSize();
592  Array<OneD, NekDouble> tstep (nElements, 0.0);
593 
594  GetElmtTimeStep(inarray, tstep);
595 
596  // Get the minimum time-step limit and return the time-step
597  NekDouble TimeStep = Vmath::Vmin(nElements, tstep, 1);
598  m_comm->AllReduce(TimeStep, LibUtilities::ReduceMin);
599  return TimeStep;
600  }
601 
602  /**
603  * @brief Set up logic for residual calculation.
604  */
606  NekDouble initialtime,
607  bool dumpInitialConditions,
608  const int domain)
609  {
610  boost::ignore_unused(domain);
611 
612  EquationSystem::v_SetInitialConditions(initialtime, false);
613 
614  // insert white noise in initial condition
615  NekDouble Noise;
616  int phystot = m_fields[0]->GetTotPoints();
617  Array<OneD, NekDouble> noise(phystot);
618 
619  m_session->LoadParameter("Noise", Noise,0.0);
620  int m_nConvectiveFields = m_fields.num_elements();
621 
622  if (Noise > 0.0)
623  {
624  int seed = - m_comm->GetRank()*m_nConvectiveFields;
625  for (int i = 0; i < m_nConvectiveFields; i++)
626  {
627  Vmath::FillWhiteNoise(phystot, Noise, noise, 1,
628  seed);
629  --seed;
630  Vmath::Vadd(phystot, m_fields[i]->GetPhys(), 1,
631  noise, 1, m_fields[i]->UpdatePhys(), 1);
632  m_fields[i]->FwdTrans_IterPerExp(m_fields[i]->GetPhys(),
633  m_fields[i]->UpdateCoeffs());
634  }
635  }
636 
637  if (dumpInitialConditions && m_checksteps)
638  {
640  m_nchk++;
641  }
642  }
643 
644  /**
645  * @brief Compute the advection velocity in the standard space
646  * for each element of the expansion.
647  */
649  {
650  int nTotQuadPoints = GetTotPoints();
651  int n_element = m_fields[0]->GetExpSize();
652  int expdim = m_fields[0]->GetGraph()->GetMeshDimension();
653  int nfields = m_fields.num_elements();
654  int offset;
656 
657  Array<OneD, Array<OneD, NekDouble> > physfields(nfields);
658  for (int i = 0; i < nfields; ++i)
659  {
660  physfields[i] = m_fields[i]->GetPhys();
661  }
662 
663  Array<OneD, NekDouble> stdV(n_element, 0.0);
664 
665  // Getting the velocity vector on the 2D normal space
669  Array<OneD, NekDouble> soundspeed (nTotQuadPoints);
671 
672  for (int i = 0; i < m_spacedim; ++i)
673  {
674  velocity [i] = Array<OneD, NekDouble>(nTotQuadPoints);
675  stdVelocity[i] = Array<OneD, NekDouble>(nTotQuadPoints, 0.0);
676  stdSoundSpeed[i] = Array<OneD, NekDouble>(nTotQuadPoints, 0.0);
677  }
678 
679  m_varConv->GetVelocityVector(physfields, velocity);
680  m_varConv->GetSoundSpeed (physfields, soundspeed);
681 
682  for(int el = 0; el < n_element; ++el)
683  {
684  ptsKeys = m_fields[0]->GetExp(el)->GetPointsKeys();
685  offset = m_fields[0]->GetPhys_Offset(el);
686  int nq = m_fields[0]->GetExp(el)->GetTotPoints();
687 
688  const SpatialDomains::GeomFactorsSharedPtr metricInfo =
689  m_fields[0]->GetExp(el)->GetGeom()->GetMetricInfo();
690  const Array<TwoD, const NekDouble> &gmat =
691  m_fields[0]->GetExp(el)->GetGeom()->GetMetricInfo()
692  ->GetDerivFactors(ptsKeys);
693 
694  // Convert to standard element
695  // consider soundspeed in all directions
696  // (this might overestimate the cfl)
697  if(metricInfo->GetGtype() == SpatialDomains::eDeformed)
698  {
699  // d xi/ dx = gmat = 1/J * d x/d xi
700  for (int i = 0; i < expdim; ++i)
701  {
702  Vmath::Vmul(nq, gmat[i], 1,
703  velocity[0] + offset, 1,
704  tmp = stdVelocity[i] + offset, 1);
705  Vmath::Vmul(nq, gmat[i], 1,
706  soundspeed + offset, 1,
707  tmp = stdSoundSpeed[i] + offset, 1);
708  for (int j = 1; j < expdim; ++j)
709  {
710  Vmath::Vvtvp(nq, gmat[expdim*j+i], 1,
711  velocity[j] + offset, 1,
712  stdVelocity[i] + offset, 1,
713  tmp = stdVelocity[i] + offset, 1);
714  Vmath::Vvtvp(nq, gmat[expdim*j+i], 1,
715  soundspeed + offset, 1,
716  stdSoundSpeed[i] + offset, 1,
717  tmp = stdSoundSpeed[i] + offset, 1);
718  }
719  }
720  }
721  else
722  {
723  for (int i = 0; i < expdim; ++i)
724  {
725  Vmath::Smul(nq, gmat[i][0],
726  velocity[0] + offset, 1,
727  tmp = stdVelocity[i] + offset, 1);
728  Vmath::Smul(nq, gmat[i][0],
729  soundspeed + offset, 1,
730  tmp = stdSoundSpeed[i] + offset, 1);
731  for (int j = 1; j < expdim; ++j)
732  {
733  Vmath::Svtvp(nq, gmat[expdim*j+i][0],
734  velocity[j] + offset, 1,
735  stdVelocity[i] + offset, 1,
736  tmp = stdVelocity[i] + offset, 1);
737  Vmath::Svtvp(nq, gmat[expdim*j+i][0],
738  soundspeed + offset, 1,
739  stdSoundSpeed[i] + offset, 1,
740  tmp = stdSoundSpeed[i] + offset, 1);
741  }
742  }
743  }
744 
745  NekDouble vel;
746  for (int i = 0; i < nq; ++i)
747  {
748  NekDouble pntVelocity = 0.0;
749  for (int j = 0; j < expdim; ++j)
750  {
751  // Add sound speed
752  vel = std::abs(stdVelocity[j][offset + i]) +
753  std::abs(stdSoundSpeed[j][offset + i]);
754  pntVelocity += vel * vel;
755  }
756  pntVelocity = sqrt(pntVelocity);
757  if (pntVelocity > stdV[el])
758  {
759  stdV[el] = pntVelocity;
760  }
761  }
762  }
763 
764  return stdV;
765  }
766 
767  /**
768  * @brief Set the denominator to compute the time step when a cfl
769  * control is employed. This function is no longer used but is still
770  * here for being utilised in the future.
771  *
772  * @param n Order of expansion element by element.
773  */
775  {
776  ASSERTL0(n <= 20, "Illegal modes dimension for CFL calculation "
777  "(P has to be less then 20)");
778 
779  NekDouble CFLDG[21] = { 2.0000, 6.0000, 11.8424, 19.1569,
780  27.8419, 37.8247, 49.0518, 61.4815,
781  75.0797, 89.8181, 105.6700, 122.6200,
782  140.6400, 159.7300, 179.8500, 201.0100,
783  223.1800, 246.3600, 270.5300, 295.6900,
784  321.8300}; //CFLDG 1D [0-20]
785  NekDouble CFL = 0.0;
786 
788  {
789  CFL = CFLDG[n];
790  }
791  else
792  {
793  ASSERTL0(false, "Continuous Galerkin stability coefficients "
794  "not introduced yet.");
795  }
796 
797  return CFL;
798  }
799 
800  /**
801  * @brief Compute the vector of denominators to compute the time step
802  * when a cfl control is employed. This function is no longer used but
803  * is still here for being utilised in the future.
804  *
805  * @param ExpOrder Order of expansion element by element.
806  */
808  const Array<OneD,int> &ExpOrder)
809  {
810  int i;
811  Array<OneD,NekDouble> returnval(m_fields[0]->GetExpSize(), 0.0);
812  for (i =0; i<m_fields[0]->GetExpSize(); i++)
813  {
814  returnval[i] = GetStabilityLimit(ExpOrder[i]);
815  }
816  return returnval;
817  }
818 
820  std::vector<Array<OneD, NekDouble> > &fieldcoeffs,
821  std::vector<std::string> &variables)
822  {
823  bool extraFields;
824  m_session->MatchSolverInfo("OutputExtraFields","True",
825  extraFields, true);
826  if (extraFields)
827  {
828  const int nPhys = m_fields[0]->GetNpoints();
829  const int nCoeffs = m_fields[0]->GetNcoeffs();
830  Array<OneD, Array<OneD, NekDouble> > tmp(m_fields.num_elements());
831 
832  for (int i = 0; i < m_fields.num_elements(); ++i)
833  {
834  tmp[i] = m_fields[i]->GetPhys();
835  }
836 
839  for (int i = 0; i < m_spacedim; ++i)
840  {
841  velocity[i] = Array<OneD, NekDouble> (nPhys);
842  velFwd[i] = Array<OneD, NekDouble> (nCoeffs);
843  }
844 
845  Array<OneD, NekDouble> pressure(nPhys), temperature(nPhys);
846  Array<OneD, NekDouble> entropy(nPhys);
847  Array<OneD, NekDouble> soundspeed(nPhys), mach(nPhys);
848  Array<OneD, NekDouble> sensor(nPhys), SensorKappa(nPhys);
849 
850  m_varConv->GetVelocityVector(tmp, velocity);
851  m_varConv->GetPressure (tmp, pressure);
852  m_varConv->GetTemperature(tmp, temperature);
853  m_varConv->GetEntropy (tmp, entropy);
854  m_varConv->GetSoundSpeed(tmp, soundspeed);
855  m_varConv->GetMach (tmp, soundspeed, mach);
856 
857  int sensorOffset;
858  m_session->LoadParameter ("SensorOffset", sensorOffset, 1);
859  m_varConv->GetSensor (m_fields[0], tmp, sensor, SensorKappa,
860  sensorOffset);
861 
862  Array<OneD, NekDouble> pFwd(nCoeffs), TFwd(nCoeffs);
863  Array<OneD, NekDouble> sFwd(nCoeffs);
864  Array<OneD, NekDouble> aFwd(nCoeffs), mFwd(nCoeffs);
865  Array<OneD, NekDouble> sensFwd(nCoeffs);
866 
867  string velNames[3] = {"u", "v", "w"};
868  for (int i = 0; i < m_spacedim; ++i)
869  {
870  m_fields[0]->FwdTrans_IterPerExp(velocity[i], velFwd[i]);
871  variables.push_back(velNames[i]);
872  fieldcoeffs.push_back(velFwd[i]);
873  }
874 
875  m_fields[0]->FwdTrans_IterPerExp(pressure, pFwd);
876  m_fields[0]->FwdTrans_IterPerExp(temperature,TFwd);
877  m_fields[0]->FwdTrans_IterPerExp(entropy, sFwd);
878  m_fields[0]->FwdTrans_IterPerExp(soundspeed, aFwd);
879  m_fields[0]->FwdTrans_IterPerExp(mach, mFwd);
880  m_fields[0]->FwdTrans_IterPerExp(sensor, sensFwd);
881 
882  variables.push_back ("p");
883  variables.push_back ("T");
884  variables.push_back ("s");
885  variables.push_back ("a");
886  variables.push_back ("Mach");
887  variables.push_back ("Sensor");
888  fieldcoeffs.push_back(pFwd);
889  fieldcoeffs.push_back(TFwd);
890  fieldcoeffs.push_back(sFwd);
891  fieldcoeffs.push_back(aFwd);
892  fieldcoeffs.push_back(mFwd);
893  fieldcoeffs.push_back(sensFwd);
894 
896  {
897  // Get min h/p
898  m_artificialDiffusion->SetElmtHP(GetElmtMinHP());
899  // reuse pressure
900  Array<OneD, NekDouble> sensorFwd(nCoeffs);
901  m_artificialDiffusion->GetArtificialViscosity(tmp, pressure);
902  m_fields[0]->FwdTrans_IterPerExp(pressure, sensorFwd);
903 
904  variables.push_back ("ArtificialVisc");
905  fieldcoeffs.push_back(sensorFwd);
906  }
907  }
908  }
909 
910  /**
911  *
912  */
914  const Array<OneD, const Array<OneD, NekDouble> > &physfield,
916  {
917  m_varConv->GetPressure(physfield, pressure);
918  }
919 
920  /**
921  *
922  */
924  const Array<OneD, const Array<OneD, NekDouble> > &physfield,
925  Array<OneD, NekDouble> &density)
926  {
927  density = physfield[0];
928  }
929 
930  /**
931  *
932  */
934  const Array<OneD, const Array<OneD, NekDouble> > &physfield,
935  Array<OneD, Array<OneD, NekDouble> > &velocity)
936  {
937  m_varConv->GetVelocityVector(physfield, velocity);
938  }
939 
940 /**
941  * @brief Compute an estimate of minimum h/p
942  * for each element of the expansion.
943  */
945 {
946  int nElements = m_fields[0]->GetExpSize();
947  Array<OneD, NekDouble> hOverP(nElements, 1.0);
948 
949  // Determine h/p scaling
950  Array<OneD, int> pOrderElmt = m_fields[0]->EvalBasisNumModesMaxPerExp();
951  for (int e = 0; e < nElements; e++)
952  {
953  NekDouble h = 1.0e+10;
954  switch(m_expdim)
955  {
956  case 3:
957  {
959  exp3D = m_fields[0]->GetExp(e)->as<LocalRegions::Expansion3D>();
960  for(int i = 0; i < exp3D->GetNedges(); ++i)
961  {
962  h = min(h, exp3D->GetGeom3D()->GetEdge(i)->GetVertex(0)->
963  dist(*(exp3D->GetGeom3D()->GetEdge(i)->GetVertex(1))));
964  }
965  break;
966  }
967 
968  case 2:
969  {
971  exp2D = m_fields[0]->GetExp(e)->as<LocalRegions::Expansion2D>();
972  for(int i = 0; i < exp2D->GetNedges(); ++i)
973  {
974  h = min(h, exp2D->GetGeom2D()->GetEdge(i)->GetVertex(0)->
975  dist(*(exp2D->GetGeom2D()->GetEdge(i)->GetVertex(1))));
976  }
977  break;
978  }
979  case 1:
980  {
982  exp1D = m_fields[0]->GetExp(e)->as<LocalRegions::Expansion1D>();
983 
984  h = min(h, exp1D->GetGeom1D()->GetVertex(0)->
985  dist(*(exp1D->GetGeom1D()->GetVertex(1))));
986 
987  break;
988  }
989  default:
990  {
991  ASSERTL0(false,"Dimension out of bound.")
992  }
993  }
994 
995  // Determine h/p scaling
996  hOverP[e] = h/max(pOrderElmt[e]-1,1);
997 
998  }
999  return hOverP;
1000 }
1001 }
SOLVER_UTILS_EXPORT Array< OneD, NekDouble > GetElmtCFLVals(void)
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:216
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:163
virtual void v_InitObject()
Initialization object for CompressibleFlowSystem class.
std::vector< PointsKey > PointsKeyVector
Definition: Points.h:246
virtual ~CompressibleFlowSystem()
Destructor for CompressibleFlowSystem class.
bool m_homoInitialFwd
Flag to determine if simulation should start in homogeneous forward transformed state.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
LibUtilities::TimeIntegrationSchemeOperators m_ode
The time integration scheme operators to use.
std::shared_ptr< GeomFactors > GeomFactorsSharedPtr
Pointer to a GeomFactors object.
Definition: GeomFactors.h:62
NekDouble m_timestep
Time step size.
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:874
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)
int m_expdim
Expansion dimension.
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:488
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
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.
Array< OneD, Array< OneD, NekDouble > > m_vecLocs
SOLVER_UTILS_EXPORT NekDouble MaxTimeStepEstimator()
Get the maximum timestep estimator for cfl control.
int m_nchk
Number of checkpoints written so far.
void GetElmtTimeStep(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, NekDouble > &tstep)
Calculate the maximum timestep on each element subject to CFL restrictions.
int m_checksteps
Number of steps between checkpoints.
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...
virtual void GetDensity(const Array< OneD, const Array< OneD, NekDouble > > &physfield, Array< OneD, NekDouble > &density)
Extract array with density from physfield.
SOLVER_UTILS_EXPORT int GetTotPoints()
virtual void GetVelocity(const Array< OneD, const Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, NekDouble > > &velocity)
Extract array with velocity from physfield.
Array< OneD, Array< OneD, NekDouble > > m_traceNormals
Array holding trace normals for DG simulations in the forwards direction.
void DefineProjection(FuncPointerT func, ObjectPointerT obj)
std::shared_ptr< RiemannSolver > RiemannSolverSharedPtr
A shared pointer to an EquationSystem object.
std::shared_ptr< Expansion3D > Expansion3DSharedPtr
Definition: Expansion2D.h:49
CFSBndCondFactory & GetCFSBndCondFactory()
Declaration of the boundary condition factory singleton.
Definition: CFSBndCond.cpp:41
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
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:216
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...
virtual Array< OneD, NekDouble > v_GetMaxStdVelocity()
Compute the advection velocity in the standard space for each element of the expansion.
SpatialDomains::Geometry1DSharedPtr GetGeom1D() const
Definition: Expansion1D.h:173
static SOLVER_UTILS_EXPORT std::vector< ForcingSharedPtr > Load(const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const unsigned int &pNumForcingFields=0)
Definition: Forcing.cpp:85
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).
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
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:47
ArtificialDiffusionFactory & GetArtificialDiffusionFactory()
Declaration of the artificial diffusion factory singleton.
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:399
double NekDouble
virtual SOLVER_UTILS_EXPORT void v_SetInitialConditions(NekDouble initialtime=0.0, bool dumpInitialConditions=true, const int domain=0)
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).
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.
void InitAdvection()
Create advection and diffusion objects for CFS.
SOLVER_UTILS_EXPORT int GetTraceTotPoints()
SOLVER_UTILS_EXPORT int GetNpoints()
const Array< OneD, const Array< OneD, NekDouble > > & GetNormals()
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
SOLVER_UTILS_EXPORT int GetExpSize()
std::shared_ptr< Expansion2D > Expansion2DSharedPtr
Definition: Expansion1D.h:47
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:139
SOLVER_UTILS_EXPORT MultiRegions::ExpListSharedPtr GetPressure()
Get pressure field if available.
Array< OneD, NekDouble > GetElmtMinHP(void)
Function to get estimate of min h/p factor per element.
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.
virtual SOLVER_UTILS_EXPORT void v_InitObject()
Init object for UnsteadySystem class.
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:376
A base class for PDEs which include an advection component.
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
Geometry is curved or has non-constant factors.
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
std::shared_ptr< Expansion1D > Expansion1DSharedPtr
Definition: Expansion1D.h:51
std::vector< CFSBndCondSharedPtr > m_bndConds
std::shared_ptr< SessionReader > SessionReaderSharedPtr
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: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