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