Nektar++
VelocityCorrectionScheme.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: VelocityCorrectionScheme.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: Velocity Correction Scheme for the Incompressible
32// Navier Stokes equations
33//
34///////////////////////////////////////////////////////////////////////////////
35
43
44#include <boost/algorithm/string.hpp>
45
46namespace Nektar
47{
48
49using namespace MultiRegions;
50
53 "VelocityCorrectionScheme", VelocityCorrectionScheme::create);
54
57 "SolverType", "VelocityCorrectionScheme", eVelocityCorrectionScheme);
58
59/**
60 * Constructor. Creates ...
61 *
62 * \param
63 * \param
64 */
68 : UnsteadySystem(pSession, pGraph), IncNavierStokes(pSession, pGraph),
69 m_varCoeffLap(StdRegions::NullVarCoeffMap)
70{
71}
72
74{
75 int n;
76
78 m_explicitDiffusion = false;
79
80 // Set m_pressure to point to last field of m_fields;
81 if (boost::iequals(m_session->GetVariable(m_fields.size() - 1), "p"))
82 {
83 m_nConvectiveFields = m_fields.size() - 1;
85 }
86 else
87 {
88 ASSERTL0(false, "Need to set up pressure field definition");
89 }
90
91 // Determine diffusion coefficients for each field
93 for (n = 0; n < m_nConvectiveFields; ++n)
94 {
95 std::string varName = m_session->GetVariable(n);
96 if (m_session->DefinesFunction("DiffusionCoefficient", varName))
97 {
99 m_session->GetFunction("DiffusionCoefficient", varName);
100 m_diffCoeff[n] = ffunc->Evaluate();
101 }
102 }
103
104 // Integrate only the convective fields
105 for (n = 0; n < m_nConvectiveFields; ++n)
106 {
107 m_intVariables.push_back(n);
108 }
109
111 SetUpSVV();
112
113 // check to see if it is explicity turned off
114 m_session->MatchSolverInfo("GJPStabilisation", "False",
116
117 // if GJPStabilisation set to False bool will be true and
118 // if not false so negate/revese bool
120
121 m_session->MatchSolverInfo("GJPNormalVelocity", "True", m_useGJPNormalVel,
122 false);
123
125 {
126 ASSERTL0(boost::iequals(m_session->GetSolverInfo("GJPStabilisation"),
127 "Explicit"),
128 "Can only specify GJPNormalVelocity with"
129 " GJPStabilisation set to Explicit currently");
130 }
131
132 m_session->LoadParameter("GJPJumpScale", m_GJPJumpScale, 1.0);
133
134 m_session->MatchSolverInfo("SmoothAdvection", "True", m_SmoothAdvection,
135 false);
136
137 // set explicit time-intregration class operators
140
141 // set implicit time-intregration class operators
144
145 // Set up bits for flowrate.
146 m_session->LoadParameter("Flowrate", m_flowrate, 0.0);
147 m_session->LoadParameter("IO_FlowSteps", m_flowrateSteps, 0);
148}
149
151{
152 // creation of the extrapolation object
155 {
156 std::string vExtrapolation = v_GetExtrapolateStr();
157 if (m_session->DefinesSolverInfo("Extrapolation"))
158 {
159 vExtrapolation = v_GetSubSteppingExtrapolateStr(
160 m_session->GetSolverInfo("Extrapolation"));
161 }
163 vExtrapolation, m_session, m_fields, m_pressure, m_velocity,
165
166 m_extrapolation->SetForcing(m_forcing);
167 m_extrapolation->SubSteppingTimeIntegration(m_intScheme);
168 m_extrapolation->GenerateBndElmtExpansion();
169 m_extrapolation->GenerateHOPBCMap(m_session);
173 }
174}
175
176/**
177 * @brief Set up the Stokes solution used to impose constant flowrate
178 * through a boundary.
179 *
180 * This routine solves a Stokes equation using a unit forcing direction,
181 * specified by the user to be in the desired flow direction. This field can
182 * then be used to correct the end of each timestep to impose a constant
183 * volumetric flow rate through a user-defined boundary.
184 *
185 * There are three modes of operation:
186 *
187 * - Standard two-dimensional or three-dimensional simulations (e.g. pipes
188 * or channels)
189 * - 3DH1D simulations where the forcing is not in the homogeneous
190 * direction (e.g. channel flow, where the y-direction of the 2D mesh
191 * is perpendicular to the wall);
192 * - 3DH1D simulations where the forcing is in the homogeneous direction
193 * (e.g. pipe flow in the z-direction).
194 *
195 * In the first two cases, the user should define:
196 * - the `Flowrate` parameter, which dictates the volumetric flux through
197 * the reference area
198 * - tag a boundary region with the `Flowrate` user-defined type to define
199 * the reference area
200 * - define a `FlowrateForce` function with components `ForceX`, `ForceY`
201 * and `ForceZ` that defines a unit forcing in the appropriate direction.
202 *
203 * In the latter case, the user should define only the `Flowrate`; the
204 * reference area is taken to be the homogeneous plane and the force is
205 * assumed to be the unit z-vector \f$ \hat{e}_z \f$.
206 *
207 * This routine solves a single timestep of the Stokes problem
208 * (premultiplied by the backwards difference coefficient):
209 *
210 * \f[ \frac{\partial\mathbf{u}}{\partial t} = -\nabla p +
211 * \nu\nabla^2\mathbf{u} + \mathbf{f} \f]
212 *
213 * with a zero initial condition to obtain a field \f$ \mathbf{u}_s \f$. The
214 * flowrate is then corrected at each timestep \f$ n \f$ by adding the
215 * correction \f$ \alpha\mathbf{u}_s \f$ where
216 *
217 * \f[ \alpha = \frac{\overline{Q} - Q(\mathbf{u^n})}{Q(\mathbf{u}_s)} \f]
218 *
219 * where \f$ Q(\cdot)\f$ is the volumetric flux through the appropriate
220 * surface or line, which is implemented in
221 * VelocityCorrectionScheme::MeasureFlowrate. For more details, see chapter
222 * 3.2 of the thesis of D. Moxey (University of Warwick, 2011).
223 */
225{
226 m_flowrateBndID = -1;
227 m_flowrateArea = 0.0;
228
230 m_fields[0]->GetBndConditions();
231
232 std::string forces[] = {"X", "Y", "Z"};
233 Array<OneD, NekDouble> flowrateForce(m_spacedim, 0.0);
234
235 // Set up flowrate forces.
236 bool defined = true;
237 for (int i = 0; i < m_spacedim; ++i)
238 {
239 std::string varName = std::string("Force") + forces[i];
240 defined = m_session->DefinesFunction("FlowrateForce", varName);
241
242 if (!defined && m_HomogeneousType == eHomogeneous1D)
243 {
244 break;
245 }
246
247 ASSERTL0(defined,
248 "A 'FlowrateForce' function must defined with components "
249 "[ForceX, ...] to define direction of flowrate forcing");
250
252 m_session->GetFunction("FlowrateForce", varName);
253 flowrateForce[i] = ffunc->Evaluate();
254 }
255
256 // Define flag for case with homogeneous expansion and forcing not in the
257 // z-direction
258 m_homd1DFlowinPlane = false;
259 if (defined && m_HomogeneousType == eHomogeneous1D)
260 {
261 m_homd1DFlowinPlane = true;
262 }
263
264 // For 3DH1D simulations, if force isn't defined then assume in
265 // z-direction.
266 if (!defined)
267 {
268 flowrateForce[2] = 1.0;
269 }
270
271 // Find the boundary condition that is tagged as the flowrate boundary.
272 for (size_t i = 0; i < bcs.size(); ++i)
273 {
274 if (boost::iequals(bcs[i]->GetUserDefined(), "Flowrate"))
275 {
276 m_flowrateBndID = i;
277 break;
278 }
279 }
280
281 int tmpBr = m_flowrateBndID;
282 m_comm->AllReduce(tmpBr, LibUtilities::ReduceMax);
284 "One boundary region must be marked using the 'Flowrate' "
285 "user-defined type to monitor the volumetric flowrate.");
286
287 // Extract an appropriate expansion list to represents the boundary.
288 if (m_flowrateBndID >= 0)
289 {
290 // For a boundary, extract the boundary itself.
291 m_flowrateBnd = m_fields[0]->GetBndCondExpansions()[m_flowrateBndID];
292 }
294 {
295 // For 3DH1D simulations with no force specified, find the mean
296 // (0th) plane.
297 Array<OneD, unsigned int> zIDs = m_fields[0]->GetZIDs();
298 int tmpId = -1;
299
300 for (size_t i = 0; i < zIDs.size(); ++i)
301 {
302 if (zIDs[i] == 0)
303 {
304 tmpId = i;
305 break;
306 }
307 }
308
309 ASSERTL1(tmpId <= 0, "Should be either at location 0 or -1 if not "
310 "found");
311
312 if (tmpId != -1)
313 {
314 m_flowrateBnd = m_fields[0]->GetPlane(tmpId);
315 }
316 }
317
318 // At this point, some processors may not have m_flowrateBnd
319 // set if they don't contain the appropriate boundary. To
320 // calculate the area, we integrate 1.0 over the boundary
321 // (which has been set up with the appropriate subcommunicator
322 // to avoid deadlock), and then communicate this to the other
323 // processors with an AllReduce.
324 if (m_flowrateBnd)
325 {
326 Array<OneD, NekDouble> inArea(m_flowrateBnd->GetNpoints(), 1.0);
327 m_flowrateArea = m_flowrateBnd->Integral(inArea);
328 }
330
331 // In homogeneous case with forcing not aligned to the z-direction,
332 // redefine m_flowrateBnd so it is a 1D expansion
335 {
336 // For 3DH1D simulations with no force specified, find the mean
337 // (0th) plane.
338 Array<OneD, unsigned int> zIDs = m_fields[0]->GetZIDs();
339 m_planeID = -1;
340
341 for (size_t i = 0; i < zIDs.size(); ++i)
342 {
343 if (zIDs[i] == 0)
344 {
345 m_planeID = i;
346 break;
347 }
348 }
349
350 ASSERTL1(m_planeID <= 0, "Should be either at location 0 or -1 "
351 "if not found");
352
353 if (m_planeID != -1)
354 {
356 m_fields[0]->GetBndCondExpansions()[m_flowrateBndID]->GetPlane(
357 m_planeID);
358 }
359 }
360
361 // Set up some storage for the Stokes solution (to be stored in
362 // m_flowrateStokes) and its initial condition (inTmp), which holds the
363 // unit forcing.
364 int nqTot = m_fields[0]->GetNpoints();
367
368 for (int i = 0; i < m_spacedim; ++i)
369 {
370 inTmp[i] = Array<OneD, NekDouble>(nqTot, flowrateForce[i] * aii_dt);
372
374 {
375 Array<OneD, NekDouble> inTmp2(nqTot);
376 m_fields[i]->HomogeneousFwdTrans(nqTot, inTmp[i], inTmp2);
377 m_fields[i]->SetWaveSpace(true);
378 inTmp[i] = inTmp2;
379 }
380
381 Vmath::Zero(m_fields[i]->GetNcoeffs(), m_fields[i]->UpdateCoeffs(), 1);
382 }
383
384 // Create temporary extrapolation object to avoid issues with
385 // m_extrapolation for HOPBCs using higher order timestepping schemes.
386 // Zero pressure BCs in Neumann boundaries that may have been
387 // set in the advection step.
389 m_pressure->GetBndConditions();
391 m_pressure->GetBndCondExpansions();
392 for (size_t n = 0; n < PBndConds.size(); ++n)
393 {
394 if (PBndConds[n]->GetBoundaryConditionType() ==
396 {
397 Vmath::Zero(PBndExp[n]->GetNcoeffs(), PBndExp[n]->UpdateCoeffs(),
398 1);
399 }
400 }
401
402 // Finally, calculate the solution and the flux of the Stokes
403 // solution. We set m_greenFlux to maximum numeric limit, which signals
404 // to SolveUnsteadyStokesSystem that we don't need to apply a flowrate
405 // force.
406 m_greenFlux = std::numeric_limits<NekDouble>::max();
407 m_flowrateAiidt = aii_dt;
408
409 // Save the number of convective field in case it is not set
410 // to spacedim. Only need velocity components for stokes forcing
411 int SaveNConvectiveFields = m_nConvectiveFields;
413 SolveUnsteadyStokesSystem(inTmp, m_flowrateStokes, 0.0, aii_dt);
414 m_nConvectiveFields = SaveNConvectiveFields;
416
417 // If the user specified IO_FlowSteps, open a handle to store output.
418 if (m_comm->GetRank() == 0 && m_flowrateSteps &&
419 !m_flowrateStream.is_open())
420 {
421 std::string filename = m_session->GetSessionName();
422 filename += ".prs";
423 m_flowrateStream.open(filename.c_str());
424 m_flowrateStream.setf(std::ios::scientific, std::ios::floatfield);
425 m_flowrateStream << "# step time dP" << std::endl
426 << "# -------------------------------------------"
427 << std::endl;
428 }
429
430 // Replace pressure BCs with those evaluated from advection step
431 m_extrapolation->CopyPressureHBCsToPbndExp();
432}
433
434/**
435 * @brief Measure the volumetric flow rate through the volumetric flow rate
436 * reference surface.
437 *
438 * This routine computes the volumetric flow rate
439 *
440 * \f[
441 * Q(\mathbf{u}) = \frac{1}{\mu(R)} \int_R \mathbf{u} \cdot d\mathbf{s}
442 * \f]
443 *
444 * through the boundary region \f$ R \f$.
445 */
447 const Array<OneD, Array<OneD, NekDouble>> &inarray)
448{
449 NekDouble flowrate = 0.0;
450
451 if (m_flowrateBnd && m_flowrateBndID >= 0)
452 {
453 // If we're an actual boundary, calculate the vector flux through
454 // the boundary.
456
458 {
459 // General case
460 for (int i = 0; i < m_spacedim; ++i)
461 {
462 m_fields[i]->ExtractPhysToBnd(m_flowrateBndID, inarray[i],
463 boundary[i]);
464 }
465 flowrate = m_flowrateBnd->VectorFlux(boundary);
466 }
467 else if (m_planeID == 0)
468 {
469 // Homogeneous with forcing in plane. Calculate flux only on
470 // the meanmode - calculateFlux necessary for hybrid
471 // parallelisation.
472 for (int i = 0; i < m_spacedim; ++i)
473 {
474 m_fields[i]->GetPlane(m_planeID)->ExtractPhysToBnd(
475 m_flowrateBndID, inarray[i], boundary[i]);
476 }
477
478 // the flowrate is calculated on the mean mode so it needs to be
479 // multiplied by LZ to be consistent with the general case.
480 flowrate = m_flowrateBnd->VectorFlux(boundary) *
481 m_session->GetParameter("LZ");
482 }
483 }
485 {
486 // 3DH1D case with no Flowrate boundary defined: compute flux
487 // through the zero-th (mean) plane.
488 flowrate = m_flowrateBnd->Integral(inarray[2]);
489 }
490
491 // Communication to obtain the total flowrate
493 {
494 m_comm->GetColumnComm()->AllReduce(flowrate, LibUtilities::ReduceSum);
495 }
496 else
497 {
498 m_comm->GetSpaceComm()->AllReduce(flowrate, LibUtilities::ReduceSum);
499 }
500 return flowrate / m_flowrateArea;
501}
502
504{
505 if (m_flowrateSteps > 0)
506 {
507 if (m_comm->GetRank() == 0 && (step + 1) % m_flowrateSteps == 0)
508 {
509 m_flowrateStream << std::setw(8) << step << std::setw(16) << m_time
510 << std::setw(16) << m_alpha << std::endl;
511 }
512 }
513
515}
516
517/**
518 *
519 */
521{
523 SolverUtils::AddSummaryItem(s, "Splitting Scheme",
524 "Velocity correction (strong press. form)");
525
526 if (m_extrapolation->GetSubStepName().size())
527 {
528 SolverUtils::AddSummaryItem(s, "Substepping",
529 m_extrapolation->GetSubStepName());
530 }
531
532 std::string dealias = m_homogen_dealiasing ? "Homogeneous1D" : "";
534 {
535 dealias += (dealias == "" ? "" : " + ") + std::string("spectral/hp");
536 }
537 if (dealias != "")
538 {
539 SolverUtils::AddSummaryItem(s, "Dealiasing", dealias);
540 }
541
542 std::string smoothing = m_useSpecVanVisc ? "spectral/hp" : "";
543 if (smoothing != "")
544 {
546 {
548 s, "Smoothing-SpecHP",
549 "SVV (" + smoothing + " Exp Kernel(cut-off = " +
550 boost::lexical_cast<std::string>(m_sVVCutoffRatio) +
551 ", diff coeff = " +
552 boost::lexical_cast<std::string>(m_sVVDiffCoeff) + "))");
553 }
554 else
555 {
557 {
559 s, "Smoothing-SpecHP",
560 "SVV (" + smoothing + " Power Kernel (Power ratio =" +
561 boost::lexical_cast<std::string>(m_sVVCutoffRatio) +
562 ", diff coeff = " +
563 boost::lexical_cast<std::string>(m_sVVDiffCoeff) +
564 "*Uh/p))");
565 }
566 else
567 {
569 s, "Smoothing-SpecHP",
570 "SVV (" + smoothing + " DG Kernel (diff coeff = " +
571 boost::lexical_cast<std::string>(m_sVVDiffCoeff) +
572 "*Uh/p))");
573 }
574 }
575 }
576
578 {
580 s, "Smoothing-Homo1D",
581 "SVV (Homogeneous1D - Exp Kernel(cut-off = " +
582 boost::lexical_cast<std::string>(m_sVVCutoffRatioHomo1D) +
583 ", diff coeff = " +
584 boost::lexical_cast<std::string>(m_sVVDiffCoeffHomo1D) + "))");
585 }
586
588 {
590 s, "GJP Stab. Impl. ",
591 m_session->GetSolverInfo("GJPStabilisation"));
592 SolverUtils::AddSummaryItem(s, "GJP Stab. JumpScale", m_GJPJumpScale);
593
594 if (boost::iequals(m_session->GetSolverInfo("GJPStabilisation"),
595 "Explicit"))
596 {
598 s, "GJP Normal Velocity",
599 m_session->GetSolverInfo("GJPNormalVelocity"));
600 }
601 }
602}
603
604/**
605 *
606 */
607void VelocityCorrectionScheme::v_DoInitialise(bool dumpInitialConditions)
608{
610
611 for (int i = 0; i < m_nConvectiveFields; ++i)
612 {
614 }
615
616 m_flowrateAiidt = 0.0;
617
618 AdvectionSystem::v_DoInitialise(dumpInitialConditions);
619
620 // Set up Field Meta Data for output files
621 m_fieldMetaDataMap["Kinvis"] = boost::lexical_cast<std::string>(m_kinvis);
622 m_fieldMetaDataMap["TimeStep"] =
623 boost::lexical_cast<std::string>(m_timestep);
624
625 // set boundary conditions here so that any normal component
626 // correction are imposed before they are imposed on initial
627 // field below
629 std::map<std::string, NekDouble> params;
630 params["Time"] = m_time;
631 for (size_t i = 0; i < m_strFrameData.size(); ++i)
632 {
633 if (std::fabs(m_movingFrameData[i + 21]) != 0.)
634 {
635 params[m_strFrameData[i]] = m_movingFrameData[i + 21];
636 }
637 }
640 m_IncNavierStokesBCs->Update(fields, Adv, params);
641
642 // Ensure the initial conditions have correct BCs
643 for (size_t i = 0; i < m_fields.size(); ++i)
644 {
645 m_fields[i]->ImposeDirichletConditions(m_fields[i]->UpdateCoeffs());
646 m_fields[i]->LocalToGlobal();
647 m_fields[i]->GlobalToLocal();
648 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),
649 m_fields[i]->UpdatePhys());
650 }
651}
652
653/**
654 *
655 */
657{
658 size_t nfields = m_fields.size() - 1;
659 for (size_t k = 0; k < nfields; ++k)
660 {
661 // Backward Transformation in physical space for time evolution
662 m_fields[k]->BwdTrans(m_fields[k]->GetCoeffs(),
663 m_fields[k]->UpdatePhys());
664 }
665}
666
667/**
668 *
669 */
671{
672
673 size_t nfields = m_fields.size() - 1;
674 for (size_t k = 0; k < nfields; ++k)
675 {
676 // Forward Transformation in physical space for time evolution
677 m_fields[k]->FwdTransLocalElmt(m_fields[k]->GetPhys(),
678 m_fields[k]->UpdateCoeffs());
679 }
680}
681
682/**
683 *
684 */
686{
687 int vVar = m_session->GetVariables().size();
688 Array<OneD, bool> vChecks(vVar, false);
689 vChecks[vVar - 1] = true;
690 return vChecks;
691}
692
693/**
694 *
695 */
697{
698 return m_session->GetVariables().size() - 1;
699}
700
701/**
702 * Explicit part of the method - Advection, Forcing + HOPBCs
703 */
705 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
706 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
707{
709 timer.Start();
710 EvaluateAdvectionTerms(inarray, outarray, time);
711 timer.Stop();
712 timer.AccumulateRegion("Advection Terms");
713
714 // Smooth advection
716 {
717 for (int i = 0; i < m_nConvectiveFields; ++i)
718 {
719 m_pressure->SmoothField(outarray[i]);
720 }
721 }
722
723 // Add forcing terms
724 for (auto &x : m_forcing)
725 {
726 x->Apply(m_fields, inarray, outarray, time);
727 }
728
729 // Calculate High-Order pressure boundary conditions
730 timer.Start();
731 std::map<std::string, NekDouble> params;
732 params["Kinvis"] = m_kinvis;
733 params["Time"] = time + m_timestep;
734 for (size_t i = 0; i < m_strFrameData.size(); ++i)
735 {
736 if (std::fabs(m_movingFrameData[i + 21]) != 0.)
737 {
738 params[m_strFrameData[i]] = m_movingFrameData[i + 21];
739 }
740 }
741 m_extrapolation->EvaluatePressureBCs(inarray, outarray, m_kinvis);
742 m_IncNavierStokesBCs->Update(inarray, outarray, params);
743 timer.Stop();
744 timer.AccumulateRegion("Pressure BCs");
745}
746
747/**
748 * Implicit part of the method - Poisson + nConv*Helmholtz
749 */
751 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
753 [[maybe_unused]] const NekDouble time, const NekDouble aii_Dt)
754{
755 // Set up flowrate if we're starting for the first time or the value of
756 // aii_Dt has changed.
757 if (m_flowrate > 0.0 && (aii_Dt != m_flowrateAiidt))
758 {
759 SetupFlowrate(aii_Dt);
760 }
761
762 size_t physTot = m_fields[0]->GetTotPoints();
763
764 // Substep the pressure boundary condition if using substepping
765 m_extrapolation->SubStepSetPressureBCs(inarray, aii_Dt, m_kinvis);
766
767 // Set up forcing term for pressure Poisson equation
769 timer.Start();
770 SetUpPressureForcing(inarray, m_F, aii_Dt);
771 timer.Stop();
772 timer.AccumulateRegion("Pressure Forcing");
773
774 // Solve Pressure System
775 timer.Start();
776 SolvePressure(m_F[0]);
777 timer.Stop();
778 timer.AccumulateRegion("Pressure Solve");
779
780 // Set up forcing term for Helmholtz problems
781 timer.Start();
782 SetUpViscousForcing(inarray, m_F, aii_Dt);
783 timer.Stop();
784 timer.AccumulateRegion("Viscous Forcing");
785
786 // Solve velocity system
787 timer.Start();
788 SolveViscous(m_F, inarray, outarray, aii_Dt);
789 timer.Stop();
790 timer.AccumulateRegion("Viscous Solve");
791
792 // Apply flowrate correction
793 if (m_flowrate > 0.0 &&
794 m_greenFlux != std::numeric_limits<NekDouble>::max())
795 {
796 NekDouble currentFlux = MeasureFlowrate(outarray);
797 m_alpha = (m_flowrate - currentFlux) / m_greenFlux;
798
799 for (int i = 0; i < m_spacedim; ++i)
800 {
801 Vmath::Svtvp(physTot, m_alpha, m_flowrateStokes[i], 1, outarray[i],
802 1, outarray[i], 1);
803 // Enusre coeff space is updated for next time step
804 m_fields[i]->FwdTransLocalElmt(outarray[i],
805 m_fields[i]->UpdateCoeffs());
806 // Impsoe symmetry of flow on coeff space (good to enfore
807 // periodicity).
808 m_fields[i]->LocalToGlobal();
809 m_fields[i]->GlobalToLocal();
810 }
811 }
812}
813
814/**
815 * Forcing term for Poisson solver solver
816 */
818 const Array<OneD, const Array<OneD, NekDouble>> &fields,
820{
821 size_t i;
822 size_t physTot = m_fields[0]->GetTotPoints();
823 size_t nvel = m_velocity.size();
824
825 m_fields[0]->PhysDeriv(eX, fields[0], Forcing[0]);
826
827 for (i = 1; i < nvel; ++i)
828 {
829 // Use Forcing[1] as storage since it is not needed for the pressure
830 m_fields[i]->PhysDeriv(DirCartesianMap[i], fields[i], Forcing[1]);
831 Vmath::Vadd(physTot, Forcing[1], 1, Forcing[0], 1, Forcing[0], 1);
832 }
833
834 Vmath::Smul(physTot, 1.0 / aii_Dt, Forcing[0], 1, Forcing[0], 1);
835}
836
837/**
838 * Forcing term for Helmholtz solver
839 */
841 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
843{
844 NekDouble aii_dtinv = 1.0 / aii_Dt;
845 size_t phystot = m_fields[0]->GetTotPoints();
846
847 // Grad p
848 m_pressure->BwdTrans(m_pressure->GetCoeffs(), m_pressure->UpdatePhys());
849
850 int nvel = m_velocity.size();
851 if (nvel == 2)
852 {
853 m_pressure->PhysDeriv(m_pressure->GetPhys(), Forcing[m_velocity[0]],
854 Forcing[m_velocity[1]]);
855 }
856 else
857 {
858 m_pressure->PhysDeriv(m_pressure->GetPhys(), Forcing[m_velocity[0]],
860 }
861
862 // zero convective fields.
863 for (int i = nvel; i < m_nConvectiveFields; ++i)
864 {
865 Vmath::Zero(phystot, Forcing[i], 1);
866 }
867
868 // Subtract inarray/(aii_dt) and divide by kinvis. Kinvis will
869 // need to be updated for the convected fields.
870 for (int i = 0; i < m_nConvectiveFields; ++i)
871 {
872 Blas::Daxpy(phystot, -aii_dtinv, inarray[i], 1, Forcing[i], 1);
873 Blas::Dscal(phystot, 1.0 / m_diffCoeff[i], &(Forcing[i])[0], 1);
874 }
875}
876
877/**
878 * Solve pressure system
879 */
882{
884 // Setup coefficient for equation
886
887 // Solver Pressure Poisson Equation
888 m_pressure->HelmSolve(Forcing, m_pressure->UpdateCoeffs(), factors);
889
890 // Add presure to outflow bc if using convective like BCs
891 m_extrapolation->AddPressureToOutflowBCs(m_kinvis);
892}
893
894/**
895 * Solve velocity system
896 */
899 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
900 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble aii_Dt)
901{
905
906 AppendSVVFactors(factors, varFactorsMap);
907 ComputeGJPNormalVelocity(inarray, varCoeffMap);
908
909 // Solve Helmholtz system and put in Physical space
910 for (int i = 0; i < m_nConvectiveFields; ++i)
911 {
912 // Add diffusion coefficient to GJP matrix operator (Implicit part)
914 {
916 }
917
918 // Setup coefficients for equation
919 factors[StdRegions::eFactorLambda] = 1.0 / aii_Dt / m_diffCoeff[i];
920 m_fields[i]->HelmSolve(Forcing[i], m_fields[i]->UpdateCoeffs(), factors,
921 varCoeffMap, varFactorsMap);
922 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(), outarray[i]);
923 }
924}
925
927{
928
929 m_session->MatchSolverInfo("SpectralVanishingViscosity", "PowerKernel",
930 m_useSpecVanVisc, false);
931
933 {
935 }
936 else
937 {
939
940 m_session->MatchSolverInfo("SpectralVanishingViscositySpectralHP",
941 "PowerKernel", m_useSpecVanVisc, false);
942 }
943
945 {
946 m_IsSVVPowerKernel = true;
947 }
948 else
949 {
950 m_session->MatchSolverInfo("SpectralVanishingViscosity", "DGKernel",
951 m_useSpecVanVisc, false);
953 {
955 }
956 else
957 {
958 m_session->MatchSolverInfo("SpectralVanishingViscositySpectralHP",
959 "DGKernel", m_useSpecVanVisc, false);
960 }
961
963 {
964 m_IsSVVPowerKernel = false;
965 }
966 }
967
968 // set up varcoeff kernel if PowerKernel or DG is specified
970 {
973 if (m_session->DefinesFunction("SVVVelocityMagnitude"))
974 {
975 if (m_comm->GetRank() == 0)
976 {
977 std::cout << "Seting up SVV velocity from "
978 "SVVVelocityMagnitude section in session file"
979 << std::endl;
980 }
981 size_t nvel = m_velocity.size();
982 size_t phystot = m_fields[0]->GetTotPoints();
983 SVVVelFields = Array<OneD, Array<OneD, NekDouble>>(nvel);
984 std::vector<std::string> vars;
985 for (size_t i = 0; i < nvel; ++i)
986 {
987 SVVVelFields[i] = Array<OneD, NekDouble>(phystot);
988 vars.push_back(m_session->GetVariable(m_velocity[i]));
989 }
990
991 // Load up files into m_fields;
992 GetFunction("SVVVelocityMagnitude")->Evaluate(vars, SVVVelFields);
993 }
994
996 SVVVarDiffCoeff(1.0, m_svvVarDiffCoeff, SVVVelFields);
997 m_session->LoadParameter("SVVDiffCoeff", m_sVVDiffCoeff, 1.0);
998 }
999 else
1000 {
1002 m_session->LoadParameter("SVVDiffCoeff", m_sVVDiffCoeff, 0.1);
1003 }
1004
1005 // Load parameters for Spectral Vanishing Viscosity
1006 if (m_useSpecVanVisc == false)
1007 {
1008 m_session->MatchSolverInfo("SpectralVanishingViscosity", "True",
1009 m_useSpecVanVisc, false);
1010 if (m_useSpecVanVisc == false)
1011 {
1012 m_session->MatchSolverInfo("SpectralVanishingViscosity",
1013 "ExpKernel", m_useSpecVanVisc, false);
1014 }
1016
1017 if (m_useSpecVanVisc == false)
1018 {
1019 m_session->MatchSolverInfo("SpectralVanishingViscositySpectralHP",
1020 "True", m_useSpecVanVisc, false);
1021 if (m_useSpecVanVisc == false)
1022 {
1023 m_session->MatchSolverInfo(
1024 "SpectralVanishingViscositySpectralHP", "ExpKernel",
1025 m_useSpecVanVisc, false);
1026 }
1027 }
1028 }
1029
1030 // Case of only Homo1D kernel
1031 if (m_session->DefinesSolverInfo("SpectralVanishingViscosityHomo1D"))
1032 {
1033 m_session->MatchSolverInfo("SpectralVanishingViscosityHomo1D", "True",
1034 m_useHomo1DSpecVanVisc, false);
1035 if (m_useHomo1DSpecVanVisc == false)
1036 {
1037 m_session->MatchSolverInfo("SpectralVanishingViscosityHomo1D",
1038 "ExpKernel", m_useHomo1DSpecVanVisc,
1039 false);
1040 }
1041 }
1042
1043 m_session->LoadParameter("SVVCutoffRatio", m_sVVCutoffRatio, 0.75);
1044 m_session->LoadParameter("SVVCutoffRatioHomo1D", m_sVVCutoffRatioHomo1D,
1046 m_session->LoadParameter("SVVDiffCoeffHomo1D", m_sVVDiffCoeffHomo1D,
1048
1050 {
1051 ASSERTL0(
1053 "Expect to have three velocity fields with homogenous expansion");
1054
1056 {
1058 planes = m_fields[0]->GetZIDs();
1059
1060 size_t num_planes = planes.size();
1061 Array<OneD, NekDouble> SVV(num_planes, 0.0);
1062 NekDouble fac;
1063 size_t kmodes = m_fields[0]->GetHomogeneousBasis()->GetNumModes();
1064 size_t pstart;
1065
1066 pstart = m_sVVCutoffRatioHomo1D * kmodes;
1067
1068 for (size_t n = 0; n < num_planes; ++n)
1069 {
1070 if (planes[n] > pstart)
1071 {
1072 fac = (NekDouble)((planes[n] - kmodes) *
1073 (planes[n] - kmodes)) /
1074 ((NekDouble)((planes[n] - pstart) *
1075 (planes[n] - pstart)));
1076 SVV[n] = m_sVVDiffCoeffHomo1D * exp(-fac) / m_kinvis;
1077 }
1078 }
1079
1080 for (size_t i = 0; i < m_velocity.size(); ++i)
1081 {
1082 m_fields[m_velocity[i]]->SetHomo1DSpecVanVisc(SVV);
1083 }
1084 }
1085 }
1086}
1087
1089 const NekDouble velmag, Array<OneD, NekDouble> &diffcoeff,
1090 const Array<OneD, Array<OneD, NekDouble>> &vel)
1091{
1092 size_t phystot = m_fields[0]->GetTotPoints();
1093 size_t nel = m_fields[0]->GetNumElmts();
1094 size_t nvel, cnt;
1095
1097
1098 Vmath::Fill(nel, velmag, diffcoeff, 1);
1099
1100 if (vel != NullNekDoubleArrayOfArray)
1101 {
1102 Array<OneD, NekDouble> Velmag(phystot);
1103 nvel = vel.size();
1104 // calculate magnitude of v
1105 Vmath::Vmul(phystot, vel[0], 1, vel[0], 1, Velmag, 1);
1106 for (size_t n = 1; n < nvel; ++n)
1107 {
1108 Vmath::Vvtvp(phystot, vel[n], 1, vel[n], 1, Velmag, 1, Velmag, 1);
1109 }
1110 Vmath::Vsqrt(phystot, Velmag, 1, Velmag, 1);
1111
1112 cnt = 0;
1114 // calculate mean value of vel mag.
1115 for (size_t i = 0; i < nel; ++i)
1116 {
1117 size_t nq = m_fields[0]->GetExp(i)->GetTotPoints();
1118 tmp = Velmag + cnt;
1119 diffcoeff[i] = m_fields[0]->GetExp(i)->Integral(tmp);
1120 Vmath::Fill(nq, 1.0, tmp, 1);
1121 NekDouble area = m_fields[0]->GetExp(i)->Integral(tmp);
1122 diffcoeff[i] = diffcoeff[i] / area;
1123 cnt += nq;
1124 }
1125 }
1126 else
1127 {
1128 nvel = m_expdim;
1129 }
1130
1131 for (size_t e = 0; e < nel; e++)
1132 {
1133 LocalRegions::ExpansionSharedPtr exp = m_fields[0]->GetExp(e);
1134 NekDouble h = 0;
1135
1136 // Find maximum length of edge.
1137 size_t nEdge = exp->GetGeom()->GetNumEdges();
1138 for (size_t i = 0; i < nEdge; ++i)
1139 {
1140 h = std::max(h, exp->GetGeom()->GetEdge(i)->GetVertex(0)->dist(
1141 *(exp->GetGeom()->GetEdge(i)->GetVertex(1))));
1142 }
1143
1144 int p = 0;
1145 for (int i = 0; i < m_expdim; ++i)
1146 {
1147 p = std::max(p, exp->GetBasisNumModes(i) - 1);
1148 }
1149
1150 diffcoeff[e] *= h / p;
1151 }
1152}
1153
1156 MultiRegions::VarFactorsMap &varFactorsMap)
1157{
1158
1159 if (m_useSpecVanVisc)
1160 {
1164 {
1166 {
1169 }
1170 else
1171 {
1174 }
1175 }
1176 }
1177}
1178
1179/*
1180 * Calculate Normal velocity on Trace (boundary of elements)
1181 * for GJP stabilisation.
1182 * We only use this for explicit stabilisation. The Semi-Implicit
1183 * operator uses a constant u_{norm} = 1.0
1184 */
1186 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
1187 StdRegions::VarCoeffMap &varcoeffs)
1188{
1190 {
1192 std::dynamic_pointer_cast<MultiRegions::ContField>(m_fields[0]);
1193
1195 cfield->GetGJPForcing();
1196
1197 int nTracePts = GJPData->GetNumTracePts();
1198 Array<OneD, NekDouble> unorm(nTracePts, 1.0);
1199 Array<OneD, NekDouble> Fwd(nTracePts), Bwd(nTracePts);
1201 GJPData->GetTraceNormals();
1202
1203 m_fields[0]->GetFwdBwdTracePhys(inarray[0], Fwd, Bwd, true, true);
1204 Vmath::Vmul(nTracePts, Fwd, 1, traceNormals[0], 1, unorm, 1);
1205
1206 // Evaluate u.n on trace
1207 for (int f = 1; f < m_fields[0]->GetCoordim(0); ++f)
1208 {
1209 m_fields[0]->GetFwdBwdTracePhys(inarray[f], Fwd, Bwd, true, true);
1210 Vmath::Vvtvp(nTracePts, Fwd, 1, traceNormals[f], 1, unorm, 1, unorm,
1211 1);
1212 }
1213 Vmath::Vabs(nTracePts, unorm, 1, unorm, 1);
1214 varcoeffs[StdRegions::eVarCoeffGJPNormVel] = unorm;
1215 }
1216}
1217} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:242
This class is the base class for Navier Stokes problems.
void SetBoundaryConditions(NekDouble time)
time dependent boundary conditions updating
MultiRegions::ExpListSharedPtr m_pressure
Pointer to field holding pressure field.
NekDouble m_kinvis
Kinematic viscosity.
bool m_SmoothAdvection
bool to identify if advection term smoothing is requested
IncBoundaryConditionsSharedPtr m_IncNavierStokesBCs
void v_InitObject(bool DeclareField=true) override
Initialisation object for EquationSystem.
ExtrapolateSharedPtr m_extrapolation
Array< OneD, int > m_velocity
int which identifies which components of m_fields contains the velocity (u,v,w);
EquationType m_equationType
equation type;
int m_nConvectiveFields
Number of fields to be convected;.
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
Forcing terms.
void EvaluateAdvectionTerms(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
static std::string RegisterEnumValue(std::string pEnum, std::string pString, int pEnumValue)
Registers an enumeration value.
void DefineOdeRhs(FuncPointerT func, ObjectPointerT obj)
void DefineImplicitSolve(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.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
SOLVER_UTILS_EXPORT bool v_PostIntegrate(int step) override
int m_spacedim
Spatial dimension (>= expansion dim).
int m_expdim
Expansion dimension.
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.
std::vector< std::string > m_strFrameData
variable name in m_movingFrameData
SOLVER_UTILS_EXPORT int GetNcoeffs()
bool m_specHP_dealiasing
Flag to determine if dealisising is usde for the Spectral/hp element discretisation.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
enum HomogeneousType m_HomogeneousType
bool m_homogen_dealiasing
Flag to determine if dealiasing is used for homogeneous simulations.
SOLVER_UTILS_EXPORT int GetTotPoints()
LibUtilities::FieldMetaDataMap m_fieldMetaDataMap
Map to identify relevant solver info to dump in output fields.
Array< OneD, NekDouble > m_movingFrameData
Moving reference frame status in the inertial frame X, Y, Z, Theta_x, Theta_y, Theta_z,...
SOLVER_UTILS_EXPORT SessionFunctionSharedPtr GetFunction(std::string name, const MultiRegions::ExpListSharedPtr &field=MultiRegions::NullExpListSharedPtr, bool cache=false)
Get a SessionFunction by name.
Defines a forcing term to be explicitly applied.
Definition: Forcing.h:71
Base class for unsteady solvers.
LibUtilities::TimeIntegrationSchemeOperators m_ode
The time integration scheme operators to use.
SOLVER_UTILS_EXPORT void v_DoInitialise(bool dumpInitialConditions=true) override
Sets up initial conditions.
LibUtilities::TimeIntegrationSchemeSharedPtr m_intScheme
Wrapper to the time integration scheme.
bool m_explicitDiffusion
Indicates if explicit or implicit treatment of diffusion is used.
SOLVER_UTILS_EXPORT void v_GenerateSummary(SummaryList &s) override
Print a summary of time stepping parameters.
NekDouble m_greenFlux
Flux of the Stokes function solution.
virtual std::string v_GetExtrapolateStr(void)
MultiRegions::ExpListSharedPtr m_flowrateBnd
Flowrate reference surface.
Array< OneD, NekDouble > m_svvVarDiffCoeff
Array of coefficient if power kernel is used in SVV.
void v_TransCoeffToPhys(void) override
Virtual function for transformation to physical space.
NekDouble MeasureFlowrate(const Array< OneD, Array< OneD, NekDouble > > &inarray)
Measure the volumetric flow rate through the volumetric flow rate reference surface.
NekDouble m_sVVDiffCoeffHomo1D
Diffusion coefficient of SVV modes in homogeneous 1D Direction.
void v_TransPhysToCoeff(void) override
Virtual function for transformation to coefficient space.
NekDouble m_flowrate
Desired volumetric flowrate.
bool m_IsSVVPowerKernel
Identifier for Power Kernel otherwise DG kernel.
static SolverUtils::EquationSystemSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Creates an instance of this class.
NekDouble m_sVVCutoffRatio
cutt off ratio from which to start decayhing modes
NekDouble m_sVVDiffCoeff
Diffusion coefficient of SVV modes.
void v_GenerateSummary(SolverUtils::SummaryList &s) override
Print a summary of time stepping parameters.
void EvaluateAdvection_SetPressureBCs(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
Array< OneD, Array< OneD, NekDouble > > m_flowrateStokes
Stokes solution used to impose flowrate.
void SolveUnsteadyStokesSystem(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time, const NekDouble a_iixDt)
NekDouble m_alpha
Current flowrate correction.
bool m_useGJPStabilisation
bool to identify if GJP semi-implicit is active.
virtual void v_SolvePressure(const Array< OneD, NekDouble > &Forcing)
VelocityCorrectionScheme(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Array< OneD, Array< OneD, NekDouble > > m_F
void SetUpViscousForcing(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &Forcing, const NekDouble aii_Dt)
virtual void v_SolveUnsteadyStokesSystem(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time, const NekDouble a_iixDt)
void SetupFlowrate(NekDouble aii_dt)
Set up the Stokes solution used to impose constant flowrate through a boundary.
void SetUpPressureForcing(const Array< OneD, const Array< OneD, NekDouble > > &fields, Array< OneD, Array< OneD, NekDouble > > &Forcing, const NekDouble aii_Dt)
void SolveViscous(const Array< OneD, const Array< OneD, NekDouble > > &Forcing, const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble aii_Dt)
virtual void v_SetUpPressureForcing(const Array< OneD, const Array< OneD, NekDouble > > &fields, Array< OneD, Array< OneD, NekDouble > > &Forcing, const NekDouble aii_Dt)
bool m_useSpecVanVisc
bool to identify if spectral vanishing viscosity is active.
Array< OneD, NekDouble > m_diffCoeff
Diffusion coefficients (will be kinvis for velocities)
int m_flowrateSteps
Interval at which to record flowrate data.
void SVVVarDiffCoeff(const NekDouble velmag, Array< OneD, NekDouble > &diffcoeff, const Array< OneD, Array< OneD, NekDouble > > &vel=NullNekDoubleArrayOfArray)
virtual void v_SolveViscous(const Array< OneD, const Array< OneD, NekDouble > > &Forcing, const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble aii_Dt)
NekDouble m_flowrateArea
Area of the boundary through which we are measuring the flowrate.
std::ofstream m_flowrateStream
Output stream to record flowrate.
virtual void v_SetUpViscousForcing(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &Forcing, const NekDouble aii_Dt)
virtual void v_EvaluateAdvection_SetPressureBCs(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
static std::string className
Name of class.
void v_InitObject(bool DeclareField=true) override
Initialisation object for EquationSystem.
void AppendSVVFactors(StdRegions::ConstFactorMap &factors, MultiRegions::VarFactorsMap &varFactorsMap)
NekDouble m_flowrateAiidt
Value of aii_dt used to compute Stokes flowrate solution.
void SolvePressure(const Array< OneD, NekDouble > &Forcing)
void v_DoInitialise(bool dumpInitialConditions=true) override
Sets up initial conditions.
int m_planeID
Plane ID for cases with homogeneous expansion.
bool m_useHomo1DSpecVanVisc
bool to identify if spectral vanishing viscosity is active.
bool m_useGJPNormalVel
bool to identify if GJP normal Velocity should be applied in explicit approach
Array< OneD, bool > v_GetSystemSingularChecks() override
int m_flowrateBndID
Boundary ID of the flowrate reference surface.
virtual std::string v_GetSubSteppingExtrapolateStr(const std::string &instr)
void ComputeGJPNormalVelocity(const Array< OneD, const Array< OneD, NekDouble > > &inarray, StdRegions::VarCoeffMap &varcoeffs)
static void Dscal(const int &n, const double &alpha, double *x, const int &incx)
BLAS level 1: x = alpha x.
Definition: Blas.hpp:149
static void Daxpy(const int &n, const double &alpha, const double *x, const int &incx, const double *y, const int &incy)
BLAS level 1: y = alpha x plus y.
Definition: Blas.hpp:135
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< Equation > EquationSharedPtr
Definition: Equation.h:125
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:66
MultiRegions::Direction const DirCartesianMap[]
Definition: ExpList.h:87
static VarFactorsMap NullVarFactorsMap
std::map< StdRegions::ConstFactorType, Array< OneD, NekDouble > > VarFactorsMap
std::shared_ptr< GJPStabilisation > GJPStabilisationSharedPtr
std::shared_ptr< ContField > ContFieldSharedPtr
Definition: ContField.h:268
std::vector< std::pair< std::string, std::string > > SummaryList
Definition: Misc.h:46
EquationSystemFactory & GetEquationSystemFactory()
void AddSummaryItem(SummaryList &l, const std::string &name, const std::string &value)
Adds a summary item to the summary info list.
Definition: Misc.cpp:47
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:174
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:430
static VarCoeffMap NullVarCoeffMap
Definition: StdRegions.hpp:376
std::map< StdRegions::VarCoeffType, VarCoeffEntry > VarCoeffMap
Definition: StdRegions.hpp:375
StdRegions::ConstFactorMap factors
@ eUnsteadyStokes
@ eUnsteadyNavierStokes
@ eVelocityCorrectionScheme
static Array< OneD, Array< OneD, NekDouble > > NullNekDoubleArrayOfArray
ExtrapolateFactory & GetExtrapolateFactory()
Definition: Extrapolate.cpp:47
static Array< OneD, NekDouble > NullNekDouble1DArray
double NekDouble
void Vsqrt(int n, const T *x, const int incx, T *y, const int incy)
sqrt y = sqrt(x)
Definition: Vmath.hpp:340
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 Vabs(int n, const T *x, const int incx, T *y, const int incy)
vabs: y = |x|
Definition: Vmath.hpp:352
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
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 Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.hpp:54