Nektar++
UnsteadyAdvectionDiffusion.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: UnsteadyAdvectionDiffusion.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: Unsteady advection-diffusion solve routines
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <iostream>
36 
37 #include <boost/core/ignore_unused.hpp>
38 
41 
42 namespace Nektar
43 {
44 using namespace LibUtilities;
45 
48  "UnsteadyAdvectionDiffusion", UnsteadyAdvectionDiffusion::create);
49 
53  : UnsteadySystem(pSession, pGraph), AdvectionSystem(pSession, pGraph)
54 {
55  m_planeNumber = 0;
56 }
57 
58 /**
59  * @brief Initialisation object for the unsteady linear advection
60  * diffusion equation.
61  */
63 {
64  AdvectionSystem::v_InitObject(DeclareFields);
65 
66  m_session->LoadParameter("wavefreq", m_waveFreq, 0.0);
67  m_session->LoadParameter("epsilon", m_epsilon, 1.0);
68 
69  // turn on substepping
70  m_session->MatchSolverInfo("Extrapolation", "SubStepping",
71  m_subSteppingScheme, false);
72 
73  // Define Velocity fields
75  std::vector<std::string> vel;
76  vel.push_back("Vx");
77  vel.push_back("Vy");
78  vel.push_back("Vz");
79  vel.resize(m_spacedim);
80 
81  GetFunction("AdvectionVelocity")->Evaluate(vel, m_velocity);
82 
83  m_session->MatchSolverInfo("SpectralVanishingViscosity", "True",
84  m_useSpecVanVisc, false);
85 
86  // check to see if it is explicity turned off
87  m_session->MatchSolverInfo("GJPStabilisation", "False",
88  m_useGJPStabilisation, true);
89 
90  // if GJPStabilisation set to False bool will be true and
91  // if not false so negate/revese bool
93 
94  m_session->LoadParameter("GJPJumpScale", m_GJPJumpScale, 1.0);
95 
96  if (m_useSpecVanVisc)
97  {
98  m_session->LoadParameter("SVVCutoffRatio", m_sVVCutoffRatio, 0.75);
99  m_session->LoadParameter("SVVDiffCoeff", m_sVVDiffCoeff, 0.1);
100  }
101 
102  // Type of advection and diffusion classes to be used
103  switch (m_projectionType)
104  {
105  // Discontinuous field
107  {
108  // Do not forwards transform initial condition
109  m_homoInitialFwd = false;
110 
111  // Advection term
112  std::string advName;
113  std::string riemName;
114  m_session->LoadSolverInfo("AdvectionType", advName, "WeakDG");
116  advName, advName);
117  m_advObject->SetFluxVector(
119  m_session->LoadSolverInfo("UpwindType", riemName, "Upwind");
122  riemName, m_session);
123  m_riemannSolver->SetScalar(
125  m_advObject->SetRiemannSolver(m_riemannSolver);
126  m_advObject->InitObject(m_session, m_fields);
127 
128  // Diffusion term
130  {
131  std::string diffName;
132  m_session->LoadSolverInfo("DiffusionType", diffName, "LDG");
134  diffName, diffName);
135  m_diffusion->SetFluxVector(
137  m_diffusion->InitObject(m_session, m_fields);
138  }
139 
140  ASSERTL0(m_subSteppingScheme == false,
141  "SubSteppingScheme is not set up for DG projection");
142  break;
143  }
144  // Continuous field
147  {
148  // Advection term
149  std::string advName;
150  m_session->LoadSolverInfo("AdvectionType", advName,
151  "NonConservative");
153  advName, advName);
154  m_advObject->SetFluxVector(
156 
157  if (advName.compare("WeakDG") == 0)
158  {
159  std::string riemName;
160  m_session->LoadSolverInfo("UpwindType", riemName, "Upwind");
163  riemName, m_session);
164  m_riemannSolver->SetScalar(
166  m_advObject->SetRiemannSolver(m_riemannSolver);
167  m_advObject->InitObject(m_session, m_fields);
168  }
169 
170  // In case of Galerkin explicit diffusion gives an error
172  {
173  ASSERTL0(false, "Explicit Galerkin diffusion not set up.");
174  }
175  // In case of Galerkin implicit diffusion: do nothing
176  break;
177  }
178  default:
179  {
180  ASSERTL0(false, "Unsupported projection type.");
181  break;
182  }
183  }
184 
185  // Forcing terms
186  m_forcing = SolverUtils::Forcing::Load(m_session, shared_from_this(),
187  m_fields, m_fields.size());
188 
190  this);
193 
194  if (m_subSteppingScheme) // Substepping
195  {
197  "Projection must be set to Mixed_CG_Discontinuous for "
198  "substepping");
200  }
201 }
202 
203 /**
204  * @brief Unsteady linear advection diffusion equation destructor.
205  */
207 {
208 }
209 
210 /**
211  * @brief Get the normal velocity for the unsteady linear advection
212  * diffusion equation.
213  */
215 {
216  return GetNormalVel(m_velocity);
217 }
218 
220  const Array<OneD, const Array<OneD, NekDouble>> &velfield)
221 {
222  // Number of trace (interface) points
223  int i;
224  int nTracePts = GetTraceNpoints();
225 
226  // Auxiliary variable to compute the normal velocity
227  Array<OneD, NekDouble> tmp(nTracePts);
228  m_traceVn = Array<OneD, NekDouble>(nTracePts, 0.0);
229 
230  // Reset the normal velocity
231  Vmath::Zero(nTracePts, m_traceVn, 1);
232 
233  for (i = 0; i < velfield.size(); ++i)
234  {
235  m_fields[0]->ExtractTracePhys(velfield[i], tmp);
236 
237  Vmath::Vvtvp(nTracePts, m_traceNormals[i], 1, tmp, 1, m_traceVn, 1,
238  m_traceVn, 1);
239  }
240 
241  return m_traceVn;
242 }
243 
244 /**
245  * @brief Compute the right-hand side for the unsteady linear advection
246  * diffusion problem.
247  *
248  * @param inarray Given fields.
249  * @param outarray Calculated solution.
250  * @param time Time.
251  */
253  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
254  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
255 {
256  // Number of fields (variables of the problem)
257  int nVariables = inarray.size();
258 
259  // Number of solution points
260  int nSolutionPts = GetNpoints();
261 
262  // RHS computation using the new advection base class
263  m_advObject->Advect(nVariables, m_fields, m_velocity, inarray, outarray,
264  time);
265 
266  // Negate the RHS
267  for (int i = 0; i < nVariables; ++i)
268  {
269  Vmath::Neg(nSolutionPts, outarray[i], 1);
270  }
271 
273  {
274  Array<OneD, Array<OneD, NekDouble>> outarrayDiff(nVariables);
275  for (int i = 0; i < nVariables; ++i)
276  {
277  outarrayDiff[i] = Array<OneD, NekDouble>(nSolutionPts, 0.0);
278  }
279 
280  m_diffusion->Diffuse(nVariables, m_fields, inarray, outarrayDiff);
281 
282  for (int i = 0; i < nVariables; ++i)
283  {
284  Vmath::Vadd(nSolutionPts, &outarrayDiff[i][0], 1, &outarray[i][0],
285  1, &outarray[i][0], 1);
286  }
287  }
288 
289  // Add forcing terms
290  for (auto &x : m_forcing)
291  {
292  // set up non-linear terms
293  x->Apply(m_fields, inarray, outarray, time);
294  }
295 }
296 
297 /**
298  * @brief Compute the projection for the unsteady advection
299  * diffusion problem.
300  *
301  * @param inarray Given fields.
302  * @param outarray Calculated solution.
303  * @param time Time.
304  */
306  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
307  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
308 {
309  int i;
310  int nvariables = inarray.size();
311  SetBoundaryConditions(time);
312  switch (m_projectionType)
313  {
315  {
316  // Just copy over array
317  int npoints = GetNpoints();
318 
319  for (i = 0; i < nvariables; ++i)
320  {
321  Vmath::Vcopy(npoints, inarray[i], 1, outarray[i], 1);
322  }
323  break;
324  }
327  {
329 
330  for (i = 0; i < nvariables; ++i)
331  {
332  m_fields[i]->FwdTrans(inarray[i], coeffs);
333  m_fields[i]->BwdTrans(coeffs, outarray[i]);
334  }
335  break;
336  }
337  default:
338  {
339  ASSERTL0(false, "Unknown projection scheme");
340  break;
341  }
342  }
343 }
344 
345 /* @brief Compute the diffusion term implicitly.
346  *
347  * @param inarray Given fields.
348  * @param outarray Calculated solution.
349  * @param time Time.
350  * @param lambda Diffusion coefficient.
351  */
353  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
354  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time,
355  const NekDouble lambda)
356 {
357  int nvariables = inarray.size();
358  int nq = m_fields[0]->GetNpoints();
359 
361  factors[StdRegions::eFactorLambda] = 1.0 / lambda / m_epsilon;
362 
363  // Add factor is GJP turned on
365  {
367  }
368 
369  if (m_useSpecVanVisc)
370  {
373  }
375  {
376  factors[StdRegions::eFactorTau] = 1.0;
377  }
378 
379  Array<OneD, Array<OneD, NekDouble>> F(nvariables);
380  for (int n = 0; n < nvariables; ++n)
381  {
382  F[n] = Array<OneD, NekDouble>(nq);
383  }
384 
385  // We solve ( \nabla^2 - HHlambda ) Y[i] = rhs [i]
386  // inarray = input: \hat{rhs} -> output: \hat{Y}
387  // outarray = output: nabla^2 \hat{Y}
388  // where \hat = modal coeffs
389  for (int i = 0; i < nvariables; ++i)
390  {
391  // Multiply 1.0/timestep/lambda
392  Vmath::Smul(nq, -factors[StdRegions::eFactorLambda], inarray[i], 1,
393  F[i], 1);
394  }
395 
396  // Setting boundary conditions
397  SetBoundaryConditions(time);
398 
399  for (int i = 0; i < nvariables; ++i)
400  {
401  // Solve a system of equations with Helmholtz solver
402  m_fields[i]->HelmSolve(F[i], m_fields[i]->UpdateCoeffs(), factors);
403 
404  m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(), outarray[i]);
405  }
406 }
407 
408 /**
409  * @brief Return the flux vector for the advection part.
410  *
411  * @param physfield Fields.
412  * @param flux Resulting flux.
413  */
415  const Array<OneD, Array<OneD, NekDouble>> &physfield,
417 {
418  ASSERTL1(flux[0].size() == m_velocity.size(),
419  "Dimension of flux array and velocity array do not match");
420 
421  const int nq = m_fields[0]->GetNpoints();
422 
423  for (int i = 0; i < flux.size(); ++i)
424  {
425  for (int j = 0; j < flux[0].size(); ++j)
426  {
427  Vmath::Vmul(nq, physfield[i], 1, m_velocity[j], 1, flux[i][j], 1);
428  }
429  }
430 }
431 
432 /**
433  * @brief Return the flux vector for the diffusion part.
434  *
435  * @param i Equation number.
436  * @param j Spatial direction.
437  * @param physfield Fields.
438  * @param derivatives First order derivatives.
439  * @param flux Resulting flux.
440  */
442  const Array<OneD, Array<OneD, NekDouble>> &inarray,
443  const Array<OneD, Array<OneD, Array<OneD, NekDouble>>> &qfield,
444  Array<OneD, Array<OneD, Array<OneD, NekDouble>>> &viscousTensor)
445 {
446  boost::ignore_unused(inarray);
447 
448  unsigned int nDim = qfield.size();
449  unsigned int nConvectiveFields = qfield[0].size();
450  unsigned int nPts = qfield[0][0].size();
451  for (unsigned int j = 0; j < nDim; ++j)
452  {
453  for (unsigned int i = 0; i < nConvectiveFields; ++i)
454  {
455  Vmath::Smul(nPts, m_epsilon, qfield[j][i], 1, viscousTensor[j][i],
456  1);
457  }
458  }
459 }
460 
462 {
465  {
467  s, "GJP Stab. Impl. ",
468  m_session->GetSolverInfo("GJPStabilisation"));
469  SolverUtils::AddSummaryItem(s, "GJP Stab. JumpScale", m_GJPJumpScale);
470  }
471 }
472 
473 /**
474  * Perform the extrapolation.
475  */
477 {
479  {
480  SubStepAdvance(step, m_time);
481  }
482 
483  return false;
484 }
485 
486 /**
487  *
488  */
490 {
491  int n;
492  int nsubsteps;
493 
494  NekDouble dt;
495 
496  Array<OneD, Array<OneD, NekDouble>> fields, velfields;
497 
498  static int ncalls = 1;
499  int nint = std::min(ncalls++, m_intSteps);
500 
502 
503  LibUtilities::CommSharedPtr comm = m_session->GetComm();
504 
505  // Get the proper time step with CFL control
506  dt = GetSubstepTimeStep();
507 
508  nsubsteps = (m_timestep > dt) ? ((int)(m_timestep / dt) + 1) : 1;
509  nsubsteps = std::max(m_minsubsteps, nsubsteps);
510 
511  dt = m_timestep / nsubsteps;
512 
513  if (m_infosteps && !((nstep + 1) % m_infosteps) && comm->GetRank() == 0)
514  {
515  std::cout << "Sub-integrating using " << nsubsteps
516  << " steps over Dt = " << m_timestep
517  << " (SubStep CFL=" << m_cflSafetyFactor << ")" << std::endl;
518  }
519 
520  const TripleArray &solutionVector = m_intScheme->GetSolutionVector();
521 
522  for (int m = 0; m < nint; ++m)
523  {
524  // We need to update the fields held by the m_intScheme
525  fields = solutionVector[m];
526 
527  // Initialise NS solver which is set up to use a GLM method
528  // with calls to EvaluateAdvection_SetPressureBCs and
529  // SolveUnsteadyStokesSystem
530  m_subStepIntegrationScheme->InitializeScheme(dt, fields, time,
532 
533  for (n = 0; n < nsubsteps; ++n)
534  {
535  fields = m_subStepIntegrationScheme->TimeIntegrate(
536  n, dt, m_subStepIntegrationOps);
537  }
538 
539  // Reset time integrated solution in m_intScheme
540  m_intScheme->SetSolutionVector(m, fields);
541  }
542 }
543 
544 /**
545  *
546  */
548 {
549  int n_element = m_fields[0]->GetExpSize();
550 
551  const Array<OneD, int> ExpOrder = m_fields[0]->EvalBasisNumModesMaxPerExp();
552  Array<OneD, int> ExpOrderList(n_element, ExpOrder);
553 
554  const NekDouble cLambda = 0.2; // Spencer book pag. 317
555 
556  Array<OneD, NekDouble> tstep(n_element, 0.0);
557  Array<OneD, NekDouble> stdVelocity(n_element, 0.0);
558 
559  stdVelocity = GetMaxStdVelocity(m_velocity);
560 
561  for (int el = 0; el < n_element; ++el)
562  {
563  tstep[el] =
564  m_cflSafetyFactor / (stdVelocity[el] * cLambda *
565  (ExpOrder[el] - 1) * (ExpOrder[el] - 1));
566  }
567 
568  NekDouble TimeStep = Vmath::Vmin(n_element, tstep, 1);
569  m_session->GetComm()->AllReduce(TimeStep, LibUtilities::ReduceMin);
570 
571  return TimeStep;
572 }
573 
575  const LibUtilities::TimeIntegrationSchemeSharedPtr &IntegrationScheme)
576 {
577  // Set to 1 for first step and it will then be increased in
578  // time advance routines
579  unsigned int order = IntegrationScheme->GetOrder();
580 
581  // Set to 1 for first step and it will then be increased in
582  // time advance routines
583  if ((IntegrationScheme->GetName() == "Euler" &&
584  IntegrationScheme->GetVariant() == "Backward") ||
585  (IntegrationScheme->GetName() == "BDFImplicit" &&
586  (order == 1 || order == 2)))
587  {
588  // Note RK first order SSP is just Forward Euler.
591  "RungeKutta", "SSP", order, std::vector<NekDouble>());
592  }
593  else
594  {
596  "Integration method not suitable: "
597  "Options include BackwardEuler or BDFImplicitOrder1");
598  }
599 
600  m_intSteps = IntegrationScheme->GetNumIntegrationPhases();
601 
602  // set explicit time-integration class operators
607 }
608 
609 /**
610  * Explicit Advection terms used by SubStepAdvance time integration
611  */
613  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
614  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
615 {
616  int i;
617  int nVariables = inarray.size();
618 
619  /// Get the number of coefficients
620  int ncoeffs = m_fields[0]->GetNcoeffs();
621 
622  /// Define an auxiliary variable to compute the RHS
623  Array<OneD, Array<OneD, NekDouble>> WeakAdv(nVariables);
624  WeakAdv[0] = Array<OneD, NekDouble>(ncoeffs * nVariables);
625  for (i = 1; i < nVariables; ++i)
626  {
627  WeakAdv[i] = WeakAdv[i - 1] + ncoeffs;
628  }
629 
630  // Currently assume velocity field is time independent and does not
631  // therefore need extrapolating. RHS computation using the advection base
632  // class
633  m_advObject->Advect(nVariables, m_fields, m_velocity, inarray, outarray,
634  time);
635 
636  for (i = 0; i < nVariables; ++i)
637  {
638  m_fields[i]->IProductWRTBase(outarray[i], WeakAdv[i]);
639  // negation requried due to sign of DoAdvection term to be consistent
640  Vmath::Neg(ncoeffs, WeakAdv[i], 1);
641  }
642 
643  AddAdvectionPenaltyFlux(m_velocity, inarray, WeakAdv);
644 
645  /// Operations to compute the RHS
646  for (i = 0; i < nVariables; ++i)
647  {
648  // Negate the RHS
649  Vmath::Neg(ncoeffs, WeakAdv[i], 1);
650 
651  /// Multiply the flux by the inverse of the mass matrix
652  m_fields[i]->MultiplyByElmtInvMass(WeakAdv[i], WeakAdv[i]);
653 
654  /// Store in outarray the physical values of the RHS
655  m_fields[i]->BwdTrans(WeakAdv[i], outarray[i]);
656  }
657 }
658 
659 /**
660  * Projection used by SubStepAdvance time integration
661  */
663  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
664  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
665 {
666  boost::ignore_unused(time);
667 
668  ASSERTL1(inarray.size() == outarray.size(),
669  "Inarray and outarray of different sizes ");
670 
671  for (int i = 0; i < inarray.size(); ++i)
672  {
673  Vmath::Vcopy(inarray[i].size(), inarray[i], 1, outarray[i], 1);
674  }
675 }
676 
678  const Array<OneD, const Array<OneD, NekDouble>> &velfield,
679  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
680  Array<OneD, Array<OneD, NekDouble>> &Outarray)
681 {
682  ASSERTL1(physfield.size() == Outarray.size(),
683  "Physfield and outarray are of different dimensions");
684 
685  int i;
686 
687  /// Number of trace points
688  int nTracePts = m_fields[0]->GetTrace()->GetNpoints();
689 
690  /// Forward state array
691  Array<OneD, NekDouble> Fwd(3 * nTracePts);
692 
693  /// Backward state array
694  Array<OneD, NekDouble> Bwd = Fwd + nTracePts;
695 
696  /// upwind numerical flux state array
697  Array<OneD, NekDouble> numflux = Bwd + nTracePts;
698 
699  /// Normal velocity array
700  Array<OneD, NekDouble> Vn = GetNormalVel(velfield);
701 
702  for (i = 0; i < physfield.size(); ++i)
703  {
704  /// Extract forwards/backwards trace spaces
705  /// Note: Needs to have correct i value to get boundary conditions
706  m_fields[i]->GetFwdBwdTracePhys(physfield[i], Fwd, Bwd);
707 
708  /// Upwind between elements
709  m_fields[0]->GetTrace()->Upwind(Vn, Fwd, Bwd, numflux);
710 
711  /// Construct difference between numflux and Fwd,Bwd
712  Vmath::Vsub(nTracePts, numflux, 1, Fwd, 1, Fwd, 1);
713  Vmath::Vsub(nTracePts, numflux, 1, Bwd, 1, Bwd, 1);
714 
715  /// Calculate the numerical fluxes multipling Fwd, Bwd and
716  /// numflux by the normal advection velocity
717  Vmath::Vmul(nTracePts, Fwd, 1, Vn, 1, Fwd, 1);
718  Vmath::Vmul(nTracePts, Bwd, 1, Vn, 1, Bwd, 1);
719 
720  m_fields[0]->AddFwdBwdTraceIntegral(Fwd, Bwd, Outarray[i]);
721  }
722 }
723 
725  const Array<OneD, Array<OneD, NekDouble>> inarray)
726 {
727 
728  int n_points_0 = m_fields[0]->GetExp(0)->GetTotPoints();
729  int n_element = m_fields[0]->GetExpSize();
730  int nvel = inarray.size();
731  int cnt;
732 
733  ASSERTL0(nvel >= 2, "Method not implemented for 1D");
734 
735  NekDouble pntVelocity;
736 
737  // Getting the standard velocity vector on the 2D normal space
738  Array<OneD, Array<OneD, NekDouble>> stdVelocity(nvel);
739  Array<OneD, NekDouble> maxV(n_element, 0.0);
741 
742  for (int i = 0; i < nvel; ++i)
743  {
744  stdVelocity[i] = Array<OneD, NekDouble>(n_points_0);
745  }
746 
747  if (nvel == 2)
748  {
749  cnt = 0.0;
750  for (int el = 0; el < n_element; ++el)
751  {
752  int n_points = m_fields[0]->GetExp(el)->GetTotPoints();
753  ptsKeys = m_fields[0]->GetExp(el)->GetPointsKeys();
754 
755  // reset local space if necessary
756  if (n_points != n_points_0)
757  {
758  for (int j = 0; j < nvel; ++j)
759  {
760  stdVelocity[j] = Array<OneD, NekDouble>(n_points);
761  }
762  n_points_0 = n_points;
763  }
764 
766  ->GetExp(el)
767  ->GetGeom()
768  ->GetMetricInfo()
769  ->GetDerivFactors(ptsKeys);
770 
771  if (m_fields[0]
772  ->GetExp(el)
773  ->GetGeom()
774  ->GetMetricInfo()
775  ->GetGtype() == SpatialDomains::eDeformed)
776  {
777  for (int i = 0; i < n_points; i++)
778  {
779  stdVelocity[0][i] = gmat[0][i] * inarray[0][i + cnt] +
780  gmat[2][i] * inarray[1][i + cnt];
781 
782  stdVelocity[1][i] = gmat[1][i] * inarray[0][i + cnt] +
783  gmat[3][i] * inarray[1][i + cnt];
784  }
785  }
786  else
787  {
788  for (int i = 0; i < n_points; i++)
789  {
790  stdVelocity[0][i] = gmat[0][0] * inarray[0][i + cnt] +
791  gmat[2][0] * inarray[1][i + cnt];
792 
793  stdVelocity[1][i] = gmat[1][0] * inarray[0][i + cnt] +
794  gmat[3][0] * inarray[1][i + cnt];
795  }
796  }
797 
798  cnt += n_points;
799 
800  for (int i = 0; i < n_points; i++)
801  {
802  pntVelocity = stdVelocity[0][i] * stdVelocity[0][i] +
803  stdVelocity[1][i] * stdVelocity[1][i];
804 
805  if (pntVelocity > maxV[el])
806  {
807  maxV[el] = pntVelocity;
808  }
809  }
810  maxV[el] = sqrt(maxV[el]);
811  }
812  }
813  else
814  {
815  cnt = 0;
816  for (int el = 0; el < n_element; ++el)
817  {
818 
819  int n_points = m_fields[0]->GetExp(el)->GetTotPoints();
820  ptsKeys = m_fields[0]->GetExp(el)->GetPointsKeys();
821 
822  // reset local space if necessary
823  if (n_points != n_points_0)
824  {
825  for (int j = 0; j < nvel; ++j)
826  {
827  stdVelocity[j] = Array<OneD, NekDouble>(n_points);
828  }
829  n_points_0 = n_points;
830  }
831 
833  ->GetExp(el)
834  ->GetGeom()
835  ->GetMetricInfo()
836  ->GetDerivFactors(ptsKeys);
837 
838  if (m_fields[0]
839  ->GetExp(el)
840  ->GetGeom()
841  ->GetMetricInfo()
842  ->GetGtype() == SpatialDomains::eDeformed)
843  {
844  for (int i = 0; i < n_points; i++)
845  {
846  stdVelocity[0][i] = gmat[0][i] * inarray[0][i + cnt] +
847  gmat[3][i] * inarray[1][i + cnt] +
848  gmat[6][i] * inarray[2][i + cnt];
849 
850  stdVelocity[1][i] = gmat[1][i] * inarray[0][i + cnt] +
851  gmat[4][i] * inarray[1][i + cnt] +
852  gmat[7][i] * inarray[2][i + cnt];
853 
854  stdVelocity[2][i] = gmat[2][i] * inarray[0][i + cnt] +
855  gmat[5][i] * inarray[1][i + cnt] +
856  gmat[8][i] * inarray[2][i + cnt];
857  }
858  }
859  else
860  {
861  for (int i = 0; i < n_points; i++)
862  {
863  stdVelocity[0][i] = gmat[0][0] * inarray[0][i + cnt] +
864  gmat[3][0] * inarray[1][i + cnt] +
865  gmat[6][0] * inarray[2][i + cnt];
866 
867  stdVelocity[1][i] = gmat[1][0] * inarray[0][i + cnt] +
868  gmat[4][0] * inarray[1][i + cnt] +
869  gmat[7][0] * inarray[2][i + cnt];
870 
871  stdVelocity[2][i] = gmat[2][0] * inarray[0][i + cnt] +
872  gmat[5][0] * inarray[1][i + cnt] +
873  gmat[8][0] * inarray[2][i + cnt];
874  }
875  }
876 
877  cnt += n_points;
878 
879  for (int i = 0; i < n_points; i++)
880  {
881  pntVelocity = stdVelocity[0][i] * stdVelocity[0][i] +
882  stdVelocity[1][i] * stdVelocity[1][i] +
883  stdVelocity[2][i] * stdVelocity[2][i];
884 
885  if (pntVelocity > maxV[el])
886  {
887  maxV[el] = pntVelocity;
888  }
889  }
890 
891  maxV[el] = sqrt(maxV[el]);
892  // cout << maxV[el]*maxV[el] << endl;
893  }
894  }
895 
896  return maxV;
897 }
898 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
void DefineProjection(FuncPointerT func, ObjectPointerT obj)
void DefineOdeRhs(FuncPointerT func, ObjectPointerT obj)
void DefineImplicitSolve(FuncPointerT func, ObjectPointerT obj)
A base class for PDEs which include an advection component.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
virtual SOLVER_UTILS_EXPORT void v_InitObject(bool DeclareField=true) override
Init object for UnsteadySystem class.
int m_spacedim
Spatial dimension (>= expansion dim).
SOLVER_UTILS_EXPORT int GetTraceNpoints()
NekDouble m_timestep
Time step size.
NekDouble m_time
Current time of simulation.
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
SOLVER_UTILS_EXPORT int GetExpSize()
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
Array< OneD, Array< OneD, NekDouble > > m_traceNormals
Array holding trace normals for DG simulations in the forwards direction.
SOLVER_UTILS_EXPORT int GetNpoints()
SOLVER_UTILS_EXPORT int GetNcoeffs()
enum MultiRegions::ProjectionType m_projectionType
Type of projection; e.g continuous or discontinuous.
SOLVER_UTILS_EXPORT void SetBoundaryConditions(NekDouble time)
Evaluates the boundary conditions at the given time.
SOLVER_UTILS_EXPORT SessionFunctionSharedPtr GetFunction(std::string name, const MultiRegions::ExpListSharedPtr &field=MultiRegions::NullExpListSharedPtr, bool cache=false)
Get a SessionFunction by name.
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:120
Base class for unsteady solvers.
LibUtilities::TimeIntegrationSchemeOperators m_ode
The time integration scheme operators to use.
LibUtilities::TimeIntegrationSchemeSharedPtr m_intScheme
Wrapper to the time integration scheme.
bool m_explicitDiffusion
Indicates if explicit or implicit treatment of diffusion is used.
virtual SOLVER_UTILS_EXPORT void v_GenerateSummary(SummaryList &s) override
Print a summary of time stepping parameters.
bool m_homoInitialFwd
Flag to determine if simulation should start in homogeneous forward transformed state.
void GetFluxVectorAdv(const Array< OneD, Array< OneD, NekDouble >> &physfield, Array< OneD, Array< OneD, Array< OneD, NekDouble >>> &flux)
Evaluate the flux at each solution point for the advection part.
UnsteadyAdvectionDiffusion(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Session reader.
void DoOdeRhs(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble time)
Compute the RHS.
SolverUtils::DiffusionSharedPtr m_diffusion
Array< OneD, NekDouble > & GetNormalVelocity()
Get the normal velocity based on m_velocity.
void AddAdvectionPenaltyFlux(const Array< OneD, const Array< OneD, NekDouble >> &velfield, const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, Array< OneD, NekDouble >> &Outarray)
virtual bool v_PreIntegrate(int step) override
PreIntegration step for substepping.
void SubStepAdvection(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble time)
virtual void v_InitObject(bool DeclareFields=true) override
Initialise the object.
Array< OneD, Array< OneD, NekDouble > > m_velocity
void DoImplicitSolve(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, NekDouble time, NekDouble lambda)
Solve implicitly the diffusion term.
void SetUpSubSteppingTimeIntegration(const LibUtilities::TimeIntegrationSchemeSharedPtr &IntegrationScheme)
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
Forcing terms.
void DoOdeProjection(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble time)
Perform the projection.
Array< OneD, NekDouble > GetMaxStdVelocity(const Array< OneD, Array< OneD, NekDouble >> inarray)
static SolverUtils::EquationSystemSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Creates an instance of this class.
void SubStepAdvance(int nstep, NekDouble time)
void GetFluxVectorDiff(const Array< OneD, Array< OneD, NekDouble >> &inarray, const Array< OneD, Array< OneD, Array< OneD, NekDouble >>> &qfield, Array< OneD, Array< OneD, Array< OneD, NekDouble >>> &viscousTensor)
Evaluate the flux at each solution point for the diffusion part.
static std::string className
Name of class.
SolverUtils::RiemannSolverSharedPtr m_riemannSolver
virtual void v_GenerateSummary(SolverUtils::SummaryList &s) override
Print Summary.
LibUtilities::TimeIntegrationSchemeSharedPtr m_subStepIntegrationScheme
Array< OneD, NekDouble > & GetNormalVel(const Array< OneD, const Array< OneD, NekDouble >> &velfield)
Get the normal velocity based on input velfield.
void SubStepProjection(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble time)
LibUtilities::TimeIntegrationSchemeOperators m_subStepIntegrationOps
TimeIntegrationSchemeFactory & GetTimeIntegrationSchemeFactory()
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::vector< PointsKey > PointsKeyVector
Definition: Points.h:250
std::shared_ptr< TimeIntegrationScheme > TimeIntegrationSchemeSharedPtr
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:54
AdvectionFactory & GetAdvectionFactory()
Gets the factory for initialising advection objects.
Definition: Advection.cpp:47
std::vector< std::pair< std::string, std::string > > SummaryList
Definition: Misc.h:48
DiffusionFactory & GetDiffusionFactory()
Definition: Diffusion.cpp:41
EquationSystemFactory & GetEquationSystemFactory()
void AddSummaryItem(SummaryList &l, const std::string &name, const std::string &value)
Adds a summary item to the summary info list.
Definition: Misc.cpp:49
RiemannSolverFactory & GetRiemannSolverFactory()
@ eDeformed
Geometry is curved or has non-constant factors.
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:172
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:399
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.cpp:209
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:518
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:1050
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition: Vmath.cpp:574
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:359
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:248
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:492
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1255
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:419
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294