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
36
39
40using namespace std;
41
42namespace Nektar
43{
47 : UnsteadySystem(pSession, pGraph), AdvectionSystem(pSession, pGraph)
48{
49}
50
51/**
52 * @brief Initialization object for CompressibleFlowSystem class.
53 */
55{
56 AdvectionSystem::v_InitObject(DeclareFields);
57
58 for (size_t i = 0; i < m_fields.size(); i++)
59 {
60 // Use BwdTrans to make sure initial condition is in solution space
61 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),
62 m_fields[i]->UpdatePhys());
63 }
64
67
68 ASSERTL0(m_session->DefinesSolverInfo("UPWINDTYPE"),
69 "No UPWINDTYPE defined in session.");
70
71 // Do not forwards transform initial condition
72 m_homoInitialFwd = false;
73
74 // Set up locations of velocity vector.
77 for (int i = 0; i < m_spacedim; ++i)
78 {
79 m_vecLocs[0][i] = 1 + i;
80 }
81
82 // Loading parameters from session file
84
85 // Setting up advection and diffusion operators
87
88 // Create artificial diffusion with laplacian operator
89 if (m_shockCaptureType == "NonSmooth")
90 {
93 }
94
95 // Forcing terms for the sponge region
97 m_fields, m_fields.size());
98
99 // User-defined boundary conditions
100 size_t cnt = 0;
101 for (size_t n = 0; n < (size_t)m_fields[0]->GetBndConditions().size(); ++n)
102 {
103 std::string type = m_fields[0]->GetBndConditions()[n]->GetUserDefined();
104
105 if (m_fields[0]->GetBndConditions()[n]->GetBoundaryConditionType() ==
107 {
108 continue;
109 }
110
111 if (!type.empty())
112 {
115 m_spacedim, n, cnt));
116 }
117 cnt += m_fields[0]->GetBndCondExpansions()[n]->GetExpSize();
118 }
119
122
124}
125
126/**
127 * @brief Load CFS parameters from the session file
128 */
130{
131 // Get gamma parameter from session file.
132 m_session->LoadParameter("Gamma", m_gamma, 1.4);
133
134 // Shock capture
135 m_session->LoadSolverInfo("ShockCaptureType", m_shockCaptureType, "Off");
136
137 // Check if the shock capture type is supported
138 std::string err_msg = "Warning, ShockCaptureType = " + m_shockCaptureType +
139 " is not supported by this solver";
141
142 // Load parameters for exponential filtering
143 m_session->MatchSolverInfo("ExponentialFiltering", "True", m_useFiltering,
144 false);
145 if (m_useFiltering)
146 {
147 m_session->LoadParameter("FilterAlpha", m_filterAlpha, 36);
148 m_session->LoadParameter("FilterExponent", m_filterExponent, 16);
149 m_session->LoadParameter("FilterCutoff", m_filterCutoff, 0);
150 }
151
152 // Load CFL for local time-stepping (for steady state)
153 m_session->MatchSolverInfo("LocalTimeStep", "True", m_useLocalTimeStep,
154 false);
156 {
158 "Local time stepping requires CFL parameter.");
159 }
160}
161
162/**
163 * @brief Create advection and diffusion objects for CFS
164 */
166{
167 // Check if projection type is correct
169 "Unsupported projection type.");
170
171 string advName, riemName;
172 m_session->LoadSolverInfo("AdvectionType", advName, "WeakDG");
173
176
178 {
179 m_advObject->SetFluxVector(
181 }
182 else
183 {
185 this);
186 }
187
188 // Setting up Riemann solver for advection operator
189 m_session->LoadSolverInfo("UpwindType", riemName, "Average");
190
193 riemName, m_session);
194
195 // Tell Riemann Solver if doing ALE and provide trace grid velocity
196 riemannSolver->SetALEFlag(m_ALESolver);
197 riemannSolver->SetVector("vgt", &ALEHelper::GetGridVelocityTrace, this);
198
199 // Setting up parameters for advection operator Riemann solver
200 riemannSolver->SetParam("gamma", &CompressibleFlowSystem::GetGamma, this);
201 riemannSolver->SetAuxVec("vecLocs", &CompressibleFlowSystem::GetVecLocs,
202 this);
203 riemannSolver->SetVector("N", &CompressibleFlowSystem::GetNormals, this);
204
205 // Concluding initialisation of advection / diffusion operators
206 m_advObject->SetRiemannSolver(riemannSolver);
207 m_advObject->InitObject(m_session, m_fields);
208}
209
210/**
211 * @brief Compute the right-hand side.
212 */
214 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
215 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
216{
218
219 size_t nvariables = inarray.size();
220 size_t nTracePts = GetTraceTotPoints();
221
222 // This converts our Mu in coefficient space to u in physical space for ALE
223 Array<OneD, Array<OneD, NekDouble>> tmpIn(nvariables);
224 if (m_ALESolver)
225 {
227 }
228 else
229 {
230 tmpIn = inarray;
231 }
232
233 m_bndEvaluateTime = time;
234
235 // Store forwards/backwards space along trace space
236 Array<OneD, Array<OneD, NekDouble>> Fwd(nvariables);
237 Array<OneD, Array<OneD, NekDouble>> Bwd(nvariables);
238
240 {
243 }
244 else
245 {
246 for (size_t i = 0; i < nvariables; ++i)
247 {
248 Fwd[i] = Array<OneD, NekDouble>(nTracePts, 0.0);
249 Bwd[i] = Array<OneD, NekDouble>(nTracePts, 0.0);
250 m_fields[i]->GetFwdBwdTracePhys(tmpIn[i], Fwd[i], Bwd[i]);
251 }
252 }
253
254 // Calculate advection
255 timer.Start();
256 DoAdvection(tmpIn, outarray, time, Fwd, Bwd);
257 timer.Stop();
258 timer.AccumulateRegion("DoAdvection");
259
260 // Negate results
261 for (size_t i = 0; i < nvariables; ++i)
262 {
263 Vmath::Neg(outarray[i].size(), outarray[i], 1);
264 }
265
266 // Add diffusion terms
267 timer.Start();
268 DoDiffusion(tmpIn, outarray, Fwd, Bwd);
269 timer.Stop();
270 timer.AccumulateRegion("DoDiffusion");
271
272 // Add forcing terms
273 for (auto &x : m_forcing)
274 {
275 x->Apply(m_fields, tmpIn, outarray, time);
276 }
277
279 {
280 size_t nElements = m_fields[0]->GetExpSize();
281 int nq, offset;
282 NekDouble fac;
284
285 Array<OneD, NekDouble> tstep(nElements, 0.0);
286 GetElmtTimeStep(tmpIn, tstep);
287
288 // Loop over elements
289 for (size_t n = 0; n < nElements; ++n)
290 {
291 nq = m_fields[0]->GetExp(n)->GetTotPoints();
292 offset = m_fields[0]->GetPhys_Offset(n);
293 fac = tstep[n] / m_timestep;
294 for (size_t i = 0; i < nvariables; ++i)
295 {
296 Vmath::Smul(nq, fac, outarray[i] + offset, 1,
297 tmp = outarray[i] + offset, 1);
298 }
299 }
300 }
301}
302
303/**
304 * @brief Compute the projection and call the method for imposing the
305 * boundary conditions in case of discontinuous projection.
306 */
308 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
309 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
310{
311 size_t nvariables = inarray.size();
312
313 // Perform ALE movement
314 if (m_ALESolver)
315 {
317 }
318
319 switch (m_projectionType)
320 {
322 {
323 // Just copy over array
324 for (size_t i = 0; i < nvariables; ++i)
325 {
326 Vmath::Vcopy(inarray[i].size(), inarray[i], 1, outarray[i], 1);
327
328 if (m_useFiltering)
329 {
330 m_fields[i]->ExponentialFilter(outarray[i], m_filterAlpha,
333 }
334 }
335 SetBoundaryConditions(outarray, time);
336 break;
337 }
340 {
341 NEKERROR(ErrorUtil::efatal, "No Continuous Galerkin for full "
342 "compressible Navier-Stokes equations");
343 break;
344 }
345 default:
346 NEKERROR(ErrorUtil::efatal, "Unknown projection scheme");
347 break;
348 }
349}
350
351/**
352 * @brief Compute the advection terms for the right-hand side
353 */
355 const Array<OneD, Array<OneD, NekDouble>> &inarray,
356 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time,
357 const Array<OneD, Array<OneD, NekDouble>> &pFwd,
358 const Array<OneD, Array<OneD, NekDouble>> &pBwd)
359{
360 int nvariables = inarray.size();
362
363 if (m_ALESolver)
364 {
365 auto advWeakDGObject =
366 std::dynamic_pointer_cast<SolverUtils::AdvectionWeakDG>(
368 advWeakDGObject->AdvectCoeffs(nvariables, m_fields, advVel, inarray,
369 outarray, time, pFwd, pBwd);
370 }
371 else
372 {
373 m_advObject->Advect(nvariables, m_fields, advVel, inarray, outarray,
374 time, pFwd, pBwd);
375 }
376}
377
378/**
379 * @brief Add the diffusions terms to the right-hand side
380 */
382 const Array<OneD, Array<OneD, NekDouble>> &inarray,
384 const Array<OneD, Array<OneD, NekDouble>> &pFwd,
385 const Array<OneD, Array<OneD, NekDouble>> &pBwd)
386{
387 v_DoDiffusion(inarray, outarray, pFwd, pBwd);
388}
389
391 Array<OneD, Array<OneD, NekDouble>> &physarray, NekDouble time)
392{
393 size_t nTracePts = GetTraceTotPoints();
394 size_t nvariables = physarray.size();
395
396 // This converts our Mu in coefficient space to u in physical space for ALE
397 Array<OneD, Array<OneD, NekDouble>> tmpIn(nvariables);
398
400 {
401 ALEHelper::ALEDoElmtInvMassBwdTrans(physarray, tmpIn);
402 }
403 else
404 {
405 tmpIn = physarray;
406 }
407
408 Array<OneD, Array<OneD, NekDouble>> Fwd(nvariables);
409 for (size_t i = 0; i < nvariables; ++i)
410 {
411 Fwd[i] = Array<OneD, NekDouble>(nTracePts);
412 m_fields[i]->ExtractTracePhys(tmpIn[i], Fwd[i]);
413 }
414
415 if (!m_bndConds.empty())
416 {
417 // Loop over user-defined boundary conditions
418 for (auto &x : m_bndConds)
419 {
420 x->Apply(Fwd, tmpIn, time);
421 }
422 }
423}
424/**
425 * @brief Set up a weight on physical boundaries for boundary condition
426 * applications
427 */
429{
430 if (m_bndConds.size())
431 {
432 // Loop over user-defined boundary conditions
433 for (auto &x : m_bndConds)
434 {
435 x->ApplyBwdWeight();
436 }
437 }
438}
439
440/**
441 * @brief Return the flux vector for the compressible Euler equations.
442 *
443 * @param physfield Fields.
444 * @param flux Resulting flux.
445 */
447 const Array<OneD, const Array<OneD, NekDouble>> &physfield,
449{
450 size_t nVariables = physfield.size();
451 size_t nPts = physfield[0].size();
452
453 constexpr unsigned short maxVel = 3;
454 constexpr unsigned short maxFld = 5;
455
456 // hardcoding done for performance reasons
457 ASSERTL1(nVariables <= maxFld, "GetFluxVector, hard coded max fields");
458
459 for (size_t p = 0; p < nPts; ++p)
460 {
461 // local storage
462 std::array<NekDouble, maxFld> fieldTmp;
463 std::array<NekDouble, maxVel> velocity;
464
465 // rearrenge and load data
466 for (size_t f = 0; f < nVariables; ++f)
467 {
468 fieldTmp[f] = physfield[f][p]; // load
469 }
470
471 // 1 / rho
472 NekDouble oneOrho = 1.0 / fieldTmp[0];
473
474 for (size_t d = 0; d < m_spacedim; ++d)
475 {
476 // Flux vector for the rho equation
477 flux[0][d][p] = fieldTmp[d + 1]; // store
478 // compute velocity
479 velocity[d] = fieldTmp[d + 1] * oneOrho;
480 }
481
482 NekDouble pressure = m_varConv->GetPressure(fieldTmp.data());
483 NekDouble ePlusP = fieldTmp[m_spacedim + 1] + pressure;
484 for (size_t f = 0; f < m_spacedim; ++f)
485 {
486 // Flux vector for the velocity fields
487 for (size_t d = 0; d < m_spacedim; ++d)
488 {
489 flux[f + 1][d][p] = velocity[d] * fieldTmp[f + 1]; // store
490 }
491
492 // Add pressure to appropriate field
493 flux[f + 1][f][p] += pressure;
494
495 // Flux vector for energy
496 flux[m_spacedim + 1][f][p] = ePlusP * velocity[f]; // store
497 }
498 }
499
500 // @TODO : for each row (3 columns) negative grid velocity component (d * d
501 // + 2 (4 rows)) rho, rhou, rhov, rhow, E,
502 // @TODO : top row is flux for rho etc... each row subtract v_g * conserved
503 // variable for that row... For grid velocity subtract v_g * conserved
504 // variable
505 if (m_ALESolver)
506 {
507 for (int i = 0; i < m_spacedim + 2; ++i)
508 {
509 for (int j = 0; j < m_spacedim; ++j)
510 {
511 for (int k = 0; k < nPts; ++k)
512 {
513 flux[i][j][k] -= physfield[i][k] * m_gridVelocity[j][k];
514 }
515 }
516 }
517 }
518}
519
520/**
521 * @brief Return the flux vector for the compressible Euler equations
522 * by using the de-aliasing technique.
523 *
524 * @param physfield Fields.
525 * @param flux Resulting flux.
526 */
528 const Array<OneD, const Array<OneD, NekDouble>> &physfield,
530{
531 int i, j;
532 size_t nq = physfield[0].size();
533 size_t nVariables = m_fields.size();
534
535 // Factor to rescale 1d points in dealiasing
536 NekDouble OneDptscale = 2;
537 nq = m_fields[0]->Get1DScaledTotPoints(OneDptscale);
538
541
542 Array<OneD, Array<OneD, NekDouble>> physfield_interp(nVariables);
543 TensorOfArray3D<NekDouble> flux_interp(nVariables);
544
545 for (size_t i = 0; i < nVariables; ++i)
546 {
547 physfield_interp[i] = Array<OneD, NekDouble>(nq);
549 m_fields[0]->PhysInterp1DScaled(OneDptscale, physfield[i],
550 physfield_interp[i]);
551
552 for (j = 0; j < m_spacedim; ++j)
553 {
554 flux_interp[i][j] = Array<OneD, NekDouble>(nq);
555 }
556 }
557
558 // Flux vector for the rho equation
559 for (i = 0; i < m_spacedim; ++i)
560 {
561 velocity[i] = Array<OneD, NekDouble>(nq);
562
563 // Galerkin project solution back to original space
564 m_fields[0]->PhysGalerkinProjection1DScaled(
565 OneDptscale, physfield_interp[i + 1], flux[0][i]);
566 }
567
568 m_varConv->GetVelocityVector(physfield_interp, velocity);
569 m_varConv->GetPressure(physfield_interp, pressure);
570
571 // Evaluation of flux vector for the velocity fields
572 for (i = 0; i < m_spacedim; ++i)
573 {
574 for (j = 0; j < m_spacedim; ++j)
575 {
576 Vmath::Vmul(nq, velocity[j], 1, physfield_interp[i + 1], 1,
577 flux_interp[i + 1][j], 1);
578 }
579
580 // Add pressure to appropriate field
581 Vmath::Vadd(nq, flux_interp[i + 1][i], 1, pressure, 1,
582 flux_interp[i + 1][i], 1);
583 }
584
585 // Galerkin project solution back to original space
586 for (i = 0; i < m_spacedim; ++i)
587 {
588 for (j = 0; j < m_spacedim; ++j)
589 {
590 m_fields[0]->PhysGalerkinProjection1DScaled(
591 OneDptscale, flux_interp[i + 1][j], flux[i + 1][j]);
592 }
593 }
594
595 // Evaluation of flux vector for energy
596 Vmath::Vadd(nq, physfield_interp[m_spacedim + 1], 1, pressure, 1, pressure,
597 1);
598
599 for (j = 0; j < m_spacedim; ++j)
600 {
601 Vmath::Vmul(nq, velocity[j], 1, pressure, 1,
602 flux_interp[m_spacedim + 1][j], 1);
603
604 // Galerkin project solution back to original space
605 m_fields[0]->PhysGalerkinProjection1DScaled(
606 OneDptscale, flux_interp[m_spacedim + 1][j],
607 flux[m_spacedim + 1][j]);
608 }
609}
610
611/**
612 * @brief Calculate the maximum timestep on each element
613 * subject to CFL restrictions.
614 */
616 [[maybe_unused]] const Array<OneD, const Array<OneD, NekDouble>> &inarray,
618{
619 size_t nElements = m_fields[0]->GetExpSize();
620
621 // Change value of m_timestep (in case it is set to zero)
622 NekDouble tmp = m_timestep;
623 m_timestep = 1.0;
624
625 Array<OneD, NekDouble> cfl(nElements);
626 cfl = GetElmtCFLVals();
627
628 // Factors to compute the time-step limit
630
631 // Loop over elements to compute the time-step limit for each element
632 for (size_t n = 0; n < nElements; ++n)
633 {
634 tstep[n] = m_cflSafetyFactor * alpha / cfl[n];
635 }
636
637 // Restore value of m_timestep
638 m_timestep = tmp;
639}
640
641/**
642 * @brief Calculate the maximum timestep subject to CFL restrictions.
643 */
645 const Array<OneD, const Array<OneD, NekDouble>> &inarray)
646{
647 int nElements = m_fields[0]->GetExpSize();
648 Array<OneD, NekDouble> tstep(nElements, 0.0);
649
650 GetElmtTimeStep(inarray, tstep);
651
652 // Get the minimum time-step limit and return the time-step
653 NekDouble TimeStep = Vmath::Vmin(nElements, tstep, 1);
654 m_comm->GetSpaceComm()->AllReduce(TimeStep, LibUtilities::ReduceMin);
655
656 return TimeStep;
657}
658
660{
662 if (m_session->DefinesSolverInfo("ICTYPE"))
663 {
664 if (boost::iequals(m_session->GetSolverInfo("ICTYPE"),
665 "IsentropicVortex"))
666 {
667 SolverUtils::AddSummaryItem(s, "Problem Type", "IsentropicVortex");
668 }
669 else if (boost::iequals(m_session->GetSolverInfo("ICTYPE"),
670 "RinglebFlow"))
671 {
672 SolverUtils::AddSummaryItem(s, "Problem Type", "RinglebFlow");
673 }
674 else
675 {
676 NEKERROR(ErrorUtil::efatal, "unknow initial condition");
677 }
678 }
679}
680
681/**
682 * @brief Set up logic for residual calculation.
683 */
685 NekDouble initialtime, bool dumpInitialConditions,
686 [[maybe_unused]] const int domain)
687{
688 if (m_session->DefinesSolverInfo("ICTYPE") &&
689 boost::iequals(m_session->GetSolverInfo("ICTYPE"), "IsentropicVortex"))
690 {
691 // Forward transform to fill the coefficient space
692 for (int i = 0; i < m_fields.size(); ++i)
693 {
694 EvaluateIsentropicVortex(i, m_fields[i]->UpdatePhys(), initialtime);
695 m_fields[i]->SetPhysState(true);
696 m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
697 m_fields[i]->UpdateCoeffs());
698 }
699 }
700 else
701 {
702 EquationSystem::v_SetInitialConditions(initialtime, false);
703 m_nchk--; // Note: m_nchk has been incremented in EquationSystem.
704
705 // insert white noise in initial condition
706 NekDouble Noise;
707 int phystot = m_fields[0]->GetTotPoints();
708 Array<OneD, NekDouble> noise(phystot);
709
710 m_session->LoadParameter("Noise", Noise, 0.0);
711 int m_nConvectiveFields = m_fields.size();
712
713 if (Noise > 0.0)
714 {
715 int seed = -m_comm->GetSpaceComm()->GetRank() * m_nConvectiveFields;
716 for (int i = 0; i < m_nConvectiveFields; i++)
717 {
718 Vmath::FillWhiteNoise(phystot, Noise, noise, 1, seed);
719 --seed;
720 Vmath::Vadd(phystot, m_fields[i]->GetPhys(), 1, noise, 1,
721 m_fields[i]->UpdatePhys(), 1);
722 m_fields[i]->FwdTransLocalElmt(m_fields[i]->GetPhys(),
723 m_fields[i]->UpdateCoeffs());
724 }
725 }
726 }
727
728 if (dumpInitialConditions && m_nchk == 0 && m_checksteps &&
729 !m_comm->IsParallelInTime())
730 {
732 }
733 else if (dumpInitialConditions && m_nchk == 0 && m_comm->IsParallelInTime())
734 {
735 std::string newdir = m_sessionName + ".pit";
736 if (!fs::is_directory(newdir))
737 {
738 fs::create_directory(newdir);
739 }
740 if (m_comm->GetTimeComm()->GetRank() == 0)
741 {
742 WriteFld(newdir + "/" + m_sessionName + "_0.fld");
743 }
744 }
745 m_nchk++;
746}
747
749 unsigned int field, Array<OneD, NekDouble> &outfield, const NekDouble time)
750{
751
752 if (!m_session->DefinesFunction("ExactSolution") &&
753 m_session->DefinesSolverInfo("ICTYPE"))
754 {
755 if (boost::iequals(m_session->GetSolverInfo("ICTYPE"),
756 "IsentropicVortex"))
757 {
758 EvaluateIsentropicVortex(field, outfield, time);
759 }
760 else if (boost::iequals(m_session->GetSolverInfo("ICTYPE"),
761 "RinglebFlow"))
762 {
763 GetExactRinglebFlow(field, outfield);
764 }
765 }
766 else
767 {
769 }
770}
771
772/**
773 * @brief Compute the advection velocity in the standard space
774 * for each element of the expansion.
775 */
777 const NekDouble SpeedSoundFactor)
778{
779 size_t nTotQuadPoints = GetTotPoints();
780 size_t n_element = m_fields[0]->GetExpSize();
781 size_t expdim = m_fields[0]->GetGraph()->GetMeshDimension();
782 size_t nfields = m_fields.size();
783 int offset;
785
786 Array<OneD, Array<OneD, NekDouble>> physfields(nfields);
787 for (size_t i = 0; i < nfields; ++i)
788 {
789 physfields[i] = m_fields[i]->GetPhys();
790 }
791
792 Array<OneD, NekDouble> stdV(n_element, 0.0);
793
794 // Getting the velocity vector on the 2D normal space
798 Array<OneD, NekDouble> soundspeed(nTotQuadPoints);
800
801 for (int i = 0; i < m_spacedim; ++i)
802 {
803 velocity[i] = Array<OneD, NekDouble>(nTotQuadPoints);
804 stdVelocity[i] = Array<OneD, NekDouble>(nTotQuadPoints, 0.0);
805 stdSoundSpeed[i] = Array<OneD, NekDouble>(nTotQuadPoints, 0.0);
806 }
807
808 m_varConv->GetVelocityVector(physfields, velocity);
809 m_varConv->GetSoundSpeed(physfields, soundspeed);
810
811 // Subtract Ug from the velocity for the ALE formulation
812 for (size_t i = 0; i < m_spacedim; ++i)
813 {
814 Vmath::Vsub(nTotQuadPoints, velocity[i], 1, m_gridVelocity[i], 1,
815 velocity[i], 1);
816 }
817
818 for (int el = 0; el < n_element; ++el)
819 {
820 ptsKeys = m_fields[0]->GetExp(el)->GetPointsKeys();
821 offset = m_fields[0]->GetPhys_Offset(el);
822 int nq = m_fields[0]->GetExp(el)->GetTotPoints();
823
824 const SpatialDomains::GeomFactorsSharedPtr metricInfo =
825 m_fields[0]->GetExp(el)->GetGeom()->GetMetricInfo();
826 const Array<TwoD, const NekDouble> &gmat =
827 m_fields[0]
828 ->GetExp(el)
829 ->GetGeom()
830 ->GetMetricInfo()
831 ->GetDerivFactors(ptsKeys);
832
833 // Convert to standard element
834 // consider soundspeed in all directions
835 // (this might overestimate the cfl)
836 if (metricInfo->GetGtype() == SpatialDomains::eDeformed)
837 {
838 // d xi/ dx = gmat = 1/J * d x/d xi
839 for (size_t i = 0; i < expdim; ++i)
840 {
841 Vmath::Vmul(nq, gmat[i], 1, velocity[0] + offset, 1,
842 tmp = stdVelocity[i] + offset, 1);
843 Vmath::Vmul(nq, gmat[i], 1, soundspeed + offset, 1,
844 tmp = stdSoundSpeed[i] + offset, 1);
845 for (size_t j = 1; j < expdim; ++j)
846 {
847 Vmath::Vvtvp(nq, gmat[expdim * j + i], 1,
848 velocity[j] + offset, 1,
849 stdVelocity[i] + offset, 1,
850 tmp = stdVelocity[i] + offset, 1);
851 Vmath::Vvtvp(nq, gmat[expdim * j + i], 1,
852 soundspeed + offset, 1,
853 stdSoundSpeed[i] + offset, 1,
854 tmp = stdSoundSpeed[i] + offset, 1);
855 }
856 }
857 }
858 else
859 {
860 for (size_t i = 0; i < expdim; ++i)
861 {
862 Vmath::Smul(nq, gmat[i][0], velocity[0] + offset, 1,
863 tmp = stdVelocity[i] + offset, 1);
864 Vmath::Smul(nq, gmat[i][0], soundspeed + offset, 1,
865 tmp = stdSoundSpeed[i] + offset, 1);
866 for (size_t j = 1; j < expdim; ++j)
867 {
868 Vmath::Svtvp(nq, gmat[expdim * j + i][0],
869 velocity[j] + offset, 1,
870 stdVelocity[i] + offset, 1,
871 tmp = stdVelocity[i] + offset, 1);
872 Vmath::Svtvp(nq, gmat[expdim * j + i][0],
873 soundspeed + offset, 1,
874 stdSoundSpeed[i] + offset, 1,
875 tmp = stdSoundSpeed[i] + offset, 1);
876 }
877 }
878 }
879
880 NekDouble vel;
881 for (size_t i = 0; i < nq; ++i)
882 {
883 NekDouble pntVelocity = 0.0;
884 for (size_t j = 0; j < expdim; ++j)
885 {
886 // Add sound speed
887 vel = std::abs(stdVelocity[j][offset + i]) +
888 SpeedSoundFactor * std::abs(stdSoundSpeed[j][offset + i]);
889 pntVelocity += vel * vel;
890 }
891 pntVelocity = sqrt(pntVelocity);
892 if (pntVelocity > stdV[el])
893 {
894 stdV[el] = pntVelocity;
895 }
896 }
897 }
898
899 return stdV;
900}
901
902/**
903 * @brief Set the denominator to compute the time step when a cfl
904 * control is employed. This function is no longer used but is still
905 * here for being utilised in the future.
906 *
907 * @param n Order of expansion element by element.
908 */
910{
911 ASSERTL0(n <= 20, "Illegal modes dimension for CFL calculation "
912 "(P has to be less then 20)");
913
914 NekDouble CFLDG[21] = {2.0000, 6.0000, 11.8424, 19.1569, 27.8419,
915 37.8247, 49.0518, 61.4815, 75.0797, 89.8181,
916 105.6700, 122.6200, 140.6400, 159.7300, 179.8500,
917 201.0100, 223.1800, 246.3600, 270.5300, 295.6900,
918 321.8300}; // CFLDG 1D [0-20]
919 NekDouble CFL = 0.0;
920
922 {
923 CFL = CFLDG[n];
924 }
925 else
926 {
927 NEKERROR(ErrorUtil::efatal, "Continuous Galerkin stability "
928 "coefficients not introduced yet.");
929 }
930
931 return CFL;
932}
933
934/**
935 * @brief Compute the vector of denominators to compute the time step
936 * when a cfl control is employed. This function is no longer used but
937 * is still here for being utilised in the future.
938 *
939 * @param ExpOrder Order of expansion element by element.
940 */
942 const Array<OneD, int> &ExpOrder)
943{
944 int i;
945 Array<OneD, NekDouble> returnval(m_fields[0]->GetExpSize(), 0.0);
946 for (i = 0; i < m_fields[0]->GetExpSize(); i++)
947 {
948 returnval[i] = GetStabilityLimit(ExpOrder[i]);
949 }
950 return returnval;
951}
952
954 std::vector<Array<OneD, NekDouble>> &fieldcoeffs,
955 std::vector<std::string> &variables)
956{
957 bool extraFields;
958 m_session->MatchSolverInfo("OutputExtraFields", "True", extraFields, true);
959 if (extraFields)
960 {
961 const int nPhys = m_fields[0]->GetNpoints();
962 const int nCoeffs = m_fields[0]->GetNcoeffs();
964
965 for (int i = 0; i < m_fields.size(); ++i)
966 {
967 tmp[i] = m_fields[i]->GetPhys();
968 }
969
972 for (int i = 0; i < m_spacedim; ++i)
973 {
974 velocity[i] = Array<OneD, NekDouble>(nPhys);
975 velFwd[i] = Array<OneD, NekDouble>(nCoeffs);
976 }
977
978 Array<OneD, NekDouble> pressure(nPhys), temperature(nPhys);
979 Array<OneD, NekDouble> entropy(nPhys);
980 Array<OneD, NekDouble> soundspeed(nPhys), mach(nPhys);
981 Array<OneD, NekDouble> sensor(nPhys), SensorKappa(nPhys);
982
983 m_varConv->GetVelocityVector(tmp, velocity);
984 m_varConv->GetPressure(tmp, pressure);
985 m_varConv->GetTemperature(tmp, temperature);
986 m_varConv->GetEntropy(tmp, entropy);
987 m_varConv->GetSoundSpeed(tmp, soundspeed);
988 m_varConv->GetMach(tmp, soundspeed, mach);
989
990 int sensorOffset;
991 m_session->LoadParameter("SensorOffset", sensorOffset, 1);
992 m_varConv->GetSensor(m_fields[0], tmp, sensor, SensorKappa,
993 sensorOffset);
994
995 Array<OneD, NekDouble> pFwd(nCoeffs), TFwd(nCoeffs);
996 Array<OneD, NekDouble> sFwd(nCoeffs);
997 Array<OneD, NekDouble> aFwd(nCoeffs), mFwd(nCoeffs);
998 Array<OneD, NekDouble> sensFwd(nCoeffs);
999
1000 string velNames[3] = {"u", "v", "w"};
1001 for (int i = 0; i < m_spacedim; ++i)
1002 {
1003 m_fields[0]->FwdTransLocalElmt(velocity[i], velFwd[i]);
1004 variables.push_back(velNames[i]);
1005 fieldcoeffs.push_back(velFwd[i]);
1006 }
1007
1008 m_fields[0]->FwdTransLocalElmt(pressure, pFwd);
1009 m_fields[0]->FwdTransLocalElmt(temperature, TFwd);
1010 m_fields[0]->FwdTransLocalElmt(entropy, sFwd);
1011 m_fields[0]->FwdTransLocalElmt(soundspeed, aFwd);
1012 m_fields[0]->FwdTransLocalElmt(mach, mFwd);
1013 m_fields[0]->FwdTransLocalElmt(sensor, sensFwd);
1014
1015 variables.push_back("p");
1016 variables.push_back("T");
1017 variables.push_back("s");
1018 variables.push_back("a");
1019 variables.push_back("Mach");
1020 variables.push_back("Sensor");
1021 fieldcoeffs.push_back(pFwd);
1022 fieldcoeffs.push_back(TFwd);
1023 fieldcoeffs.push_back(sFwd);
1024 fieldcoeffs.push_back(aFwd);
1025 fieldcoeffs.push_back(mFwd);
1026 fieldcoeffs.push_back(sensFwd);
1027
1029 {
1030 // reuse pressure
1031 Array<OneD, NekDouble> sensorFwd(nCoeffs);
1032 m_artificialDiffusion->GetArtificialViscosity(tmp, pressure);
1033 m_fields[0]->FwdTransLocalElmt(pressure, sensorFwd);
1034
1035 variables.push_back("ArtificialVisc");
1036 fieldcoeffs.push_back(sensorFwd);
1037 }
1038
1039 if (m_ALESolver)
1040 {
1041 ExtraFldOutputGridVelocity(fieldcoeffs, variables);
1042 }
1043 }
1044}
1045
1046/**
1047 *
1048 */
1050 const Array<OneD, const Array<OneD, NekDouble>> &physfield,
1052{
1053 m_varConv->GetPressure(physfield, pressure);
1054}
1055
1056/**
1057 *
1058 */
1060 const Array<OneD, const Array<OneD, NekDouble>> &physfield,
1061 Array<OneD, NekDouble> &density)
1062{
1063 density = physfield[0];
1064}
1065
1066/**
1067 *
1068 */
1070 const Array<OneD, const Array<OneD, NekDouble>> &physfield,
1071 Array<OneD, Array<OneD, NekDouble>> &velocity)
1072{
1073 m_varConv->GetVelocityVector(physfield, velocity);
1074}
1075
1078{
1079 const size_t nPoints = GetTotPoints();
1080 const size_t nFields = m_fields.size();
1082 Array<OneD, Array<OneD, NekDouble>> inarray(nFields);
1083 for (size_t i = 0; i < nFields; ++i)
1084 {
1085 rhs[i] = Array<OneD, NekDouble>(nPoints, 0.0);
1086 inarray[i] = m_fields[i]->UpdatePhys();
1087 }
1088
1089 DoOdeRhs(inarray, rhs, m_time);
1090
1091 // Holds L2 errors.
1093 Array<OneD, NekDouble> RHSL2(nFields);
1094 Array<OneD, NekDouble> residual(nFields);
1095
1096 for (size_t i = 0; i < nFields; ++i)
1097 {
1098 tmp = rhs[i];
1099
1100 Vmath::Vmul(nPoints, tmp, 1, tmp, 1, tmp, 1);
1101 residual[i] = Vmath::Vsum(nPoints, tmp, 1);
1102 }
1103
1104 m_comm->GetSpaceComm()->AllReduce(residual, LibUtilities::ReduceSum);
1105
1106 NekDouble onPoints = 1.0 / NekDouble(nPoints);
1107 for (size_t i = 0; i < nFields; ++i)
1108 {
1109 L2[i] = sqrt(residual[i] * onPoints);
1110 }
1111}
1112
1113/**
1114 *
1115 */
1117 unsigned int field, Array<OneD, NekDouble> &outfield, NekDouble time,
1118 const int o)
1119{
1120 NekDouble beta, u0, v0, x0, y0;
1121
1122 int nTotQuadPoints = GetTotPoints();
1123 Array<OneD, NekDouble> x(nTotQuadPoints);
1124 Array<OneD, NekDouble> y(nTotQuadPoints);
1125 Array<OneD, NekDouble> z(nTotQuadPoints);
1127
1128 m_fields[0]->GetCoords(x, y, z);
1129
1130 for (int i = 0; i < m_spacedim + 2; ++i)
1131 {
1132 u[i] = Array<OneD, NekDouble>(nTotQuadPoints);
1133 }
1134 m_session->LoadParameter("IsentropicBeta", beta, 5.0);
1135 m_session->LoadParameter("IsentropicU0", u0, 1.0);
1136 m_session->LoadParameter("IsentropicV0", v0, 0.5);
1137 m_session->LoadParameter("IsentropicX0", x0, 5.0);
1138 m_session->LoadParameter("IsentropicY0", y0, 0.0);
1139
1140 // Flow parameters
1141 NekDouble r, xbar, ybar, tmp;
1142 NekDouble fac = 1.0 / (16.0 * m_gamma * M_PI * M_PI);
1143
1144 // In 3D zero rhow field.
1145 if (m_spacedim == 3)
1146 {
1147 Vmath::Zero(nTotQuadPoints, &u[3][o], 1);
1148 }
1149
1150 // Fill storage
1151 for (int i = 0; i < nTotQuadPoints; ++i)
1152 {
1153 xbar = x[i] - u0 * time - x0;
1154 ybar = y[i] - v0 * time - y0;
1155 r = sqrt(xbar * xbar + ybar * ybar);
1156 tmp = beta * exp(1 - r * r);
1157 u[0][i + o] =
1158 pow(1.0 - (m_gamma - 1.0) * tmp * tmp * fac, 1.0 / (m_gamma - 1.0));
1159 u[1][i + o] = u[0][i + o] * (u0 - tmp * ybar / (2 * M_PI));
1160 u[2][i + o] = u[0][i + o] * (v0 + tmp * xbar / (2 * M_PI));
1161 u[m_spacedim + 1][i + o] =
1162 pow(u[0][i + o], m_gamma) / (m_gamma - 1.0) +
1163 0.5 * (u[1][i + o] * u[1][i + o] + u[2][i + o] * u[2][i + o]) /
1164 u[0][i + o];
1165 }
1166 Vmath::Vcopy(nTotQuadPoints, u[field].get(), 1, outfield.get(), 1);
1167}
1168
1169/**
1170 * @brief Compute the exact solution for the Ringleb flow problem.
1171 */
1173 int field, Array<OneD, NekDouble> &outarray)
1174{
1175 int nTotQuadPoints = GetTotPoints();
1176
1177 Array<OneD, NekDouble> rho(nTotQuadPoints, 100.0);
1178 Array<OneD, NekDouble> rhou(nTotQuadPoints);
1179 Array<OneD, NekDouble> rhov(nTotQuadPoints);
1180 Array<OneD, NekDouble> E(nTotQuadPoints);
1181 Array<OneD, NekDouble> x(nTotQuadPoints);
1182 Array<OneD, NekDouble> y(nTotQuadPoints);
1183 Array<OneD, NekDouble> z(nTotQuadPoints);
1184
1185 m_fields[0]->GetCoords(x, y, z);
1186
1187 // Flow parameters
1188 NekDouble c, k, phi, r, J, VV, pp, sint, P, ss;
1189 NekDouble J11, J12, J21, J22, det;
1190 NekDouble Fx, Fy;
1191 NekDouble xi, yi;
1192 NekDouble dV;
1193 NekDouble dtheta;
1194 NekDouble par1;
1195 NekDouble theta = M_PI / 4.0;
1196 NekDouble kExt = 0.7;
1197 NekDouble V = kExt * sin(theta);
1198 NekDouble toll = 1.0e-8;
1199 NekDouble errV = 1.0;
1200 NekDouble errTheta = 1.0;
1201 NekDouble gamma = m_gamma;
1202 NekDouble gamma_1_2 = (gamma - 1.0) / 2.0;
1203
1204 for (int i = 0; i < nTotQuadPoints; ++i)
1205 {
1206 while ((abs(errV) > toll) || (abs(errTheta) > toll))
1207 {
1208 VV = V * V;
1209 sint = sin(theta);
1210 c = sqrt(1.0 - gamma_1_2 * VV);
1211 k = V / sint;
1212 phi = 1.0 / k;
1213 pp = phi * phi;
1214 J = 1.0 / c + 1.0 / (3.0 * c * c * c) +
1215 1.0 / (5.0 * c * c * c * c * c) -
1216 0.5 * log((1.0 + c) / (1.0 - c));
1217
1218 r = pow(c, 1.0 / gamma_1_2);
1219 xi = 1.0 / (2.0 * r) * (1.0 / VV - 2.0 * pp) + J / 2.0;
1220 yi = phi / (r * V) * sqrt(1.0 - VV * pp);
1221 par1 = 25.0 - 5.0 * VV;
1222 ss = sint * sint;
1223
1224 Fx = xi - x[i];
1225 Fy = yi - y[i];
1226
1227 J11 =
1228 39062.5 / pow(par1, 3.5) * (1.0 / VV - 2.0 / VV * ss) * V +
1229 1562.5 / pow(par1, 2.5) *
1230 (-2.0 / (VV * V) + 4.0 / (VV * V) * ss) +
1231 12.5 / pow(par1, 1.5) * V + 312.5 / pow(par1, 2.5) * V +
1232 7812.5 / pow(par1, 3.5) * V -
1233 0.25 *
1234 (-1.0 / pow(par1, 0.5) * V / (1.0 - 0.2 * pow(par1, 0.5)) -
1235 (1.0 + 0.2 * pow(par1, 0.5)) /
1236 pow((1.0 - 0.2 * pow(par1, 0.5)), 2.0) /
1237 pow(par1, 0.5) * V) /
1238 (1.0 + 0.2 * pow(par1, 0.5)) * (1.0 - 0.2 * pow(par1, 0.5));
1239
1240 J12 = -6250.0 / pow(par1, 2.5) / VV * sint * cos(theta);
1241 J21 = -6250.0 / (VV * V) * sint / pow(par1, 2.5) *
1242 pow((1.0 - ss), 0.5) +
1243 78125.0 / V * sint / pow(par1, 3.5) * pow((1.0 - ss), 0.5);
1244
1245 // the matrix is singular when theta = pi/2
1246 if (abs(y[i]) < toll && abs(cos(theta)) < toll)
1247 {
1248 J22 = -39062.5 / pow(par1, 3.5) / V +
1249 3125 / pow(par1, 2.5) / (VV * V) +
1250 12.5 / pow(par1, 1.5) * V + 312.5 / pow(par1, 2.5) * V +
1251 7812.5 / pow(par1, 3.5) * V -
1252 0.25 *
1253 (-1.0 / pow(par1, 0.5) * V /
1254 (1.0 - 0.2 * pow(par1, 0.5)) -
1255 (1.0 + 0.2 * pow(par1, 0.5)) /
1256 pow((1.0 - 0.2 * pow(par1, 0.5)), 2.0) /
1257 pow(par1, 0.5) * V) /
1258 (1.0 + 0.2 * pow(par1, 0.5)) *
1259 (1.0 - 0.2 * pow(par1, 0.5));
1260
1261 // dV = -dV/dx * Fx
1262 dV = -1.0 / J22 * Fx;
1263 dtheta = 0.0;
1264 theta = M_PI / 2.0;
1265 }
1266 else
1267 {
1268 J22 = 3125.0 / VV * cos(theta) / pow(par1, 2.5) *
1269 pow((1.0 - ss), 0.5) -
1270 3125.0 / VV * ss / pow(par1, 2.5) / pow((1.0 - ss), 0.5) *
1271 cos(theta);
1272
1273 det = -1.0 / (J11 * J22 - J12 * J21);
1274
1275 // [dV dtheta]' = -[invJ]*[Fx Fy]'
1276 dV = det * (J22 * Fx - J12 * Fy);
1277 dtheta = det * (-J21 * Fx + J11 * Fy);
1278 }
1279
1280 V = V + dV;
1281 theta = theta + dtheta;
1282
1283 errV = abs(dV);
1284 errTheta = abs(dtheta);
1285 }
1286
1287 c = sqrt(1.0 - gamma_1_2 * VV);
1288 r = pow(c, 1.0 / gamma_1_2);
1289
1290 rho[i] = r;
1291 rhou[i] = rho[i] * V * cos(theta);
1292 rhov[i] = rho[i] * V * sin(theta);
1293 P = (c * c) * rho[i] / gamma;
1294 E[i] = P / (gamma - 1.0) +
1295 0.5 * (rhou[i] * rhou[i] / rho[i] + rhov[i] * rhov[i] / rho[i]);
1296
1297 // Resetting the guess value
1298 errV = 1.0;
1299 errTheta = 1.0;
1300 theta = M_PI / 4.0;
1301 V = kExt * sin(theta);
1302 }
1303
1304 switch (field)
1305 {
1306 case 0:
1307 outarray = rho;
1308 break;
1309 case 1:
1310 outarray = rhou;
1311 break;
1312 case 2:
1313 outarray = rhov;
1314 break;
1315 case 3:
1316 outarray = E;
1317 break;
1318 default:
1319 ASSERTL0(false, "Error in variable number!");
1320 break;
1321 }
1322}
1323
1325 int spaceDim, Array<OneD, MultiRegions::ExpListSharedPtr> &fields)
1326{
1327 m_spaceDim = spaceDim;
1328 m_fieldsALE = fields;
1329
1330 // Initialise grid velocities as 0s
1333 for (int i = 0; i < spaceDim; ++i)
1334 {
1335 m_gridVelocity[i] =
1336 Array<OneD, NekDouble>(fields[0]->GetTotPoints(), 0.0);
1338 Array<OneD, NekDouble>(fields[0]->GetTrace()->GetTotPoints(), 0.0);
1339 }
1340
1341 ALEHelper::InitObject(spaceDim, fields);
1342}
1343
1344} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:202
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:242
void GetFluxVector(const Array< OneD, const Array< OneD, NekDouble > > &physfield, TensorOfArray3D< NekDouble > &flux)
Return the flux vector for the compressible Euler equations.
CompressibleFlowSystem(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
void v_ALEInitObject(int spaceDim, Array< OneD, MultiRegions::ExpListSharedPtr > &fields) override
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.
void SetBoundaryConditions(Array< OneD, Array< OneD, NekDouble > > &physarray, NekDouble time)
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 bool v_SupportsShockCaptType(const std::string type) const =0
MultiRegions::ExpListSharedPtr v_GetPressure() override
Array< OneD, NekDouble > GetStabilityLimitVector(const Array< OneD, int > &ExpOrder)
Function to calculate the stability limit for DG/CG (a vector of them).
void InitAdvection()
Create advection and diffusion objects for CFS.
NekDouble v_GetTimeStep(const Array< OneD, const Array< OneD, NekDouble > > &inarray) override
Calculate the maximum timestep subject to CFL restrictions.
const Array< OneD, const Array< OneD, NekDouble > > & GetNormals()
void v_GenerateSummary(SolverUtils::SummaryList &s) override
Print a summary of time stepping parameters.
virtual void v_DoDiffusion(const Array< OneD, Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const Array< OneD, Array< OneD, NekDouble > > &pFwd, const Array< OneD, Array< OneD, NekDouble > > &pBwd)=0
void v_SetInitialConditions(NekDouble initialtime=0.0, bool dumpInitialConditions=true, const int domain=0) override
Set up logic for residual calculation.
void GetExactRinglebFlow(int field, Array< OneD, NekDouble > &outarray)
Ringleb Flow Test Case.
void v_InitObject(bool DeclareFields=true) override
Initialization object for CompressibleFlowSystem class.
void v_GetDensity(const Array< OneD, const Array< OneD, NekDouble > > &physfield, Array< OneD, NekDouble > &density) override
void EvaluateIsentropicVortex(unsigned int field, Array< OneD, NekDouble > &outfield, NekDouble time, const int o=0)
Isentropic Vortex Test Case.
NekDouble GetStabilityLimit(int n)
Function to calculate the stability limit for DG/CG.
void GetFluxVectorDeAlias(const Array< OneD, const Array< OneD, NekDouble > > &physfield, TensorOfArray3D< NekDouble > &flux)
Return the flux vector for the compressible Euler equations by using the de-aliasing technique.
std::vector< CFSBndCondSharedPtr > m_bndConds
Array< OneD, Array< OneD, NekDouble > > m_vecLocs
void v_ExtraFldOutput(std::vector< Array< OneD, NekDouble > > &fieldcoeffs, std::vector< std::string > &variables) override
VariableConverterSharedPtr m_varConv
const Array< OneD, const Array< OneD, NekDouble > > & GetVecLocs()
void SetBoundaryConditionsBwdWeight()
Set up a weight on physical boundaries for boundary condition applications.
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
ArtificialDiffusionSharedPtr m_artificialDiffusion
Array< OneD, NekDouble > v_GetMaxStdVelocity(const NekDouble SpeedSoundFactor) override
Compute the advection velocity in the standard space for each element of the expansion.
void DoAdvection(const Array< OneD, 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 InitialiseParameters()
Load CFS parameters from the session file.
void DoDiffusion(const Array< OneD, 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.
void DoOdeRhs(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
Compute the right-hand side.
void v_SteadyStateResidual(int step, Array< OneD, NekDouble > &L2) override
void v_EvaluateExactSolution(unsigned int field, Array< OneD, NekDouble > &outfield, const NekDouble time=0.0) override
void v_GetVelocity(const Array< OneD, const Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, NekDouble > > &velocity) override
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
void DefineProjection(FuncPointerT func, ObjectPointerT obj)
void DefineOdeRhs(FuncPointerT func, ObjectPointerT obj)
void AccumulateRegion(std::string, int iolevel=0)
Accumulate elapsed time for a region.
Definition: Timer.cpp:70
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
Array< OneD, MultiRegions::ExpListSharedPtr > m_fieldsALE
Definition: ALEHelper.h:89
SOLVER_UTILS_EXPORT void InitObject(int spaceDim, Array< OneD, MultiRegions::ExpListSharedPtr > &fields)
Definition: ALEHelper.cpp:48
Array< OneD, Array< OneD, NekDouble > > m_gridVelocityTrace
Definition: ALEHelper.h:91
SOLVER_UTILS_EXPORT void ALEDoElmtInvMassBwdTrans(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray)
Definition: ALEHelper.cpp:149
SOLVER_UTILS_EXPORT void ExtraFldOutputGridVelocity(std::vector< Array< OneD, NekDouble > > &fieldcoeffs, std::vector< std::string > &variables)
Definition: ALEHelper.cpp:392
SOLVER_UTILS_EXPORT void MoveMesh(const NekDouble &time, Array< OneD, Array< OneD, NekDouble > > &traceNormals)
Definition: ALEHelper.cpp:169
SOLVER_UTILS_EXPORT const Array< OneD, const Array< OneD, NekDouble > > & GetGridVelocityTrace()
Definition: ALEHelper.cpp:290
Array< OneD, Array< OneD, NekDouble > > m_gridVelocity
Definition: ALEHelper.h:90
A base class for PDEs which include an advection component.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
SOLVER_UTILS_EXPORT Array< OneD, NekDouble > GetElmtCFLVals(const bool FlagAcousticCFL=true)
SOLVER_UTILS_EXPORT void v_InitObject(bool DeclareField=true) override
Initialisation object for EquationSystem.
int m_spacedim
Spatial dimension (>= expansion dim).
virtual SOLVER_UTILS_EXPORT void v_SetInitialConditions(NekDouble initialtime=0.0, bool dumpInitialConditions=true, const int domain=0)
SpatialDomains::MeshGraphSharedPtr m_graph
Pointer to graph defining mesh.
LibUtilities::CommSharedPtr m_comm
Communicator.
NekDouble m_timestep
Time step size.
NekDouble m_time
Current time of simulation.
SOLVER_UTILS_EXPORT int GetTraceTotPoints()
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
SOLVER_UTILS_EXPORT void Checkpoint_Output(const int n)
Write checkpoint file of m_fields.
virtual SOLVER_UTILS_EXPORT void v_EvaluateExactSolution(unsigned int field, Array< OneD, NekDouble > &outfield, const NekDouble time)
SOLVER_UTILS_EXPORT void WriteFld(const std::string &outname)
Write field data to the given filename.
SOLVER_UTILS_EXPORT int GetExpSize()
std::string m_sessionName
Name of the session.
bool m_specHP_dealiasing
Flag to determine if dealisising is usde for the Spectral/hp element discretisation.
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.
enum HomogeneousType m_HomogeneousType
int m_nchk
Number of checkpoints written so far.
enum MultiRegions::ProjectionType m_projectionType
Type of projection; e.g continuous or discontinuous.
int m_checksteps
Number of steps between checkpoints.
SOLVER_UTILS_EXPORT int GetTotPoints()
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:118
Base class for unsteady solvers.
LibUtilities::TimeIntegrationSchemeOperators m_ode
The time integration scheme operators to use.
NekDouble m_cflSafetyFactor
CFL safety factor (comprise between 0 to 1).
SOLVER_UTILS_EXPORT NekDouble MaxTimeStepEstimator()
Get the maximum timestep estimator for cfl control.
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.
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::vector< PointsKey > PointsKeyVector
Definition: Points.h:231
@ beta
Gauss Radau pinned at x=-1,.
Definition: PointsType.h:59
@ P
Monomial polynomials .
Definition: BasisType.h:62
std::shared_ptr< RiemannSolver > RiemannSolverSharedPtr
A shared pointer to an EquationSystem object.
AdvectionFactory & GetAdvectionFactory()
Gets the factory for initialising advection objects.
Definition: Advection.cpp:43
std::vector< std::pair< std::string, std::string > > SummaryList
Definition: Misc.h:46
void AddSummaryItem(SummaryList &l, const std::string &name, const std::string &value)
Adds a summary item to the summary info list.
Definition: Misc.cpp:47
RiemannSolverFactory & GetRiemannSolverFactory()
std::shared_ptr< GeomFactors > GeomFactorsSharedPtr
Pointer to a GeomFactors object.
Definition: GeomFactors.h:60
@ eDeformed
Geometry is curved or has non-constant factors.
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:174
std::vector< double > z(NPUPPER)
std::vector< double > d(NPUPPER *NPUPPER)
CFSBndCondFactory & GetCFSBndCondFactory()
Declaration of the boundary condition factory singleton.
Definition: CFSBndCond.cpp:41
static Array< OneD, Array< OneD, NekDouble > > NullNekDoubleArrayOfArray
ArtificialDiffusionFactory & GetArtificialDiffusionFactory()
Declaration of the artificial diffusion factory singleton.
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.hpp:72
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.hpp:396
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.hpp:292
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.hpp:725
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.hpp:366
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition: Vmath.hpp:608
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.hpp:180
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.hpp:100
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.hpp:273
void FillWhiteNoise(int n, const T eps, T *x, const int incx, int outseed)
Fills a vector with white noise.
Definition: Vmath.cpp:154
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.hpp:825
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.hpp:220
STL namespace.
scalarT< T > abs(scalarT< T > in)
Definition: scalar.hpp:298
scalarT< T > log(scalarT< T > in)
Definition: scalar.hpp:303
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294