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
46using namespace std;
47
48namespace Nektar
49{
50using namespace MultiRegions;
51
54 "VelocityCorrectionScheme", VelocityCorrectionScheme::create);
55
58 "SolverType", "VelocityCorrectionScheme", eVelocityCorrectionScheme);
59
60/**
61 * Constructor. Creates ...
62 *
63 * \param
64 * \param
65 */
69 : UnsteadySystem(pSession, pGraph), IncNavierStokes(pSession, pGraph),
70 m_varCoeffLap(StdRegions::NullVarCoeffMap)
71{
72}
73
75{
76 int n;
77
79 m_explicitDiffusion = false;
80
81 // Set m_pressure to point to last field of m_fields;
82 if (boost::iequals(m_session->GetVariable(m_fields.size() - 1), "p"))
83 {
84 m_nConvectiveFields = m_fields.size() - 1;
86 }
87 else
88 {
89 ASSERTL0(false, "Need to set up pressure field definition");
90 }
91
92 // Determine diffusion coefficients for each field
94 for (n = 0; n < m_nConvectiveFields; ++n)
95 {
96 std::string varName = m_session->GetVariable(n);
97 if (m_session->DefinesFunction("DiffusionCoefficient", varName))
98 {
100 m_session->GetFunction("DiffusionCoefficient", varName);
101 m_diffCoeff[n] = ffunc->Evaluate();
102 }
103 }
104
105 // Integrate only the convective fields
106 for (n = 0; n < m_nConvectiveFields; ++n)
107 {
108 m_intVariables.push_back(n);
109 }
110
112 SetUpSVV();
113
114 // check to see if it is explicity turned off
115 m_session->MatchSolverInfo("GJPStabilisation", "False",
117
118 // if GJPStabilisation set to False bool will be true and
119 // if not false so negate/revese bool
121
122 m_session->MatchSolverInfo("GJPNormalVelocity", "True", m_useGJPNormalVel,
123 false);
124
126 {
127 ASSERTL0(boost::iequals(m_session->GetSolverInfo("GJPStabilisation"),
128 "Explicit"),
129 "Can only specify GJPNormalVelocity with"
130 " GJPStabilisation set to Explicit currently");
131 }
132
133 m_session->LoadParameter("GJPJumpScale", m_GJPJumpScale, 1.0);
134
135 m_session->MatchSolverInfo("SmoothAdvection", "True", m_SmoothAdvection,
136 false);
137
138 // set explicit time-intregration class operators
141
142 // set implicit time-intregration class operators
145
146 // Set up bits for flowrate.
147 m_session->LoadParameter("Flowrate", m_flowrate, 0.0);
148 m_session->LoadParameter("IO_FlowSteps", m_flowrateSteps, 0);
149}
150
152{
153 // creation of the extrapolation object
156 {
157 std::string vExtrapolation = v_GetExtrapolateStr();
158 if (m_session->DefinesSolverInfo("Extrapolation"))
159 {
160 vExtrapolation = v_GetSubSteppingExtrapolateStr(
161 m_session->GetSolverInfo("Extrapolation"));
162 }
164 vExtrapolation, m_session, m_fields, m_pressure, m_velocity,
166
167 m_extrapolation->SetForcing(m_forcing);
168 m_extrapolation->SubSteppingTimeIntegration(m_intScheme);
169 m_extrapolation->GenerateBndElmtExpansion();
170 m_extrapolation->GenerateHOPBCMap(m_session);
174 }
175}
176
177/**
178 * @brief Set up the Stokes solution used to impose constant flowrate
179 * through a boundary.
180 *
181 * This routine solves a Stokes equation using a unit forcing direction,
182 * specified by the user to be in the desired flow direction. This field can
183 * then be used to correct the end of each timestep to impose a constant
184 * volumetric flow rate through a user-defined boundary.
185 *
186 * There are three modes of operation:
187 *
188 * - Standard two-dimensional or three-dimensional simulations (e.g. pipes
189 * or channels)
190 * - 3DH1D simulations where the forcing is not in the homogeneous
191 * direction (e.g. channel flow, where the y-direction of the 2D mesh
192 * is perpendicular to the wall);
193 * - 3DH1D simulations where the forcing is in the homogeneous direction
194 * (e.g. pipe flow in the z-direction).
195 *
196 * In the first two cases, the user should define:
197 * - the `Flowrate` parameter, which dictates the volumetric flux through
198 * the reference area
199 * - tag a boundary region with the `Flowrate` user-defined type to define
200 * the reference area
201 * - define a `FlowrateForce` function with components `ForceX`, `ForceY`
202 * and `ForceZ` that defines a unit forcing in the appropriate direction.
203 *
204 * In the latter case, the user should define only the `Flowrate`; the
205 * reference area is taken to be the homogeneous plane and the force is
206 * assumed to be the unit z-vector \f$ \hat{e}_z \f$.
207 *
208 * This routine solves a single timestep of the Stokes problem
209 * (premultiplied by the backwards difference coefficient):
210 *
211 * \f[ \frac{\partial\mathbf{u}}{\partial t} = -\nabla p +
212 * \nu\nabla^2\mathbf{u} + \mathbf{f} \f]
213 *
214 * with a zero initial condition to obtain a field \f$ \mathbf{u}_s \f$. The
215 * flowrate is then corrected at each timestep \f$ n \f$ by adding the
216 * correction \f$ \alpha\mathbf{u}_s \f$ where
217 *
218 * \f[ \alpha = \frac{\overline{Q} - Q(\mathbf{u^n})}{Q(\mathbf{u}_s)} \f]
219 *
220 * where \f$ Q(\cdot)\f$ is the volumetric flux through the appropriate
221 * surface or line, which is implemented in
222 * VelocityCorrectionScheme::MeasureFlowrate. For more details, see chapter
223 * 3.2 of the thesis of D. Moxey (University of Warwick, 2011).
224 */
226{
227 m_flowrateBndID = -1;
228 m_flowrateArea = 0.0;
229
231 m_fields[0]->GetBndConditions();
232
233 std::string forces[] = {"X", "Y", "Z"};
234 Array<OneD, NekDouble> flowrateForce(m_spacedim, 0.0);
235
236 // Set up flowrate forces.
237 bool defined = true;
238 for (int i = 0; i < m_spacedim; ++i)
239 {
240 std::string varName = std::string("Force") + forces[i];
241 defined = m_session->DefinesFunction("FlowrateForce", varName);
242
243 if (!defined && m_HomogeneousType == eHomogeneous1D)
244 {
245 break;
246 }
247
248 ASSERTL0(defined,
249 "A 'FlowrateForce' function must defined with components "
250 "[ForceX, ...] to define direction of flowrate forcing");
251
253 m_session->GetFunction("FlowrateForce", varName);
254 flowrateForce[i] = ffunc->Evaluate();
255 }
256
257 // Define flag for case with homogeneous expansion and forcing not in the
258 // z-direction
259 m_homd1DFlowinPlane = false;
260 if (defined && m_HomogeneousType == eHomogeneous1D)
261 {
262 m_homd1DFlowinPlane = true;
263 }
264
265 // For 3DH1D simulations, if force isn't defined then assume in
266 // z-direction.
267 if (!defined)
268 {
269 flowrateForce[2] = 1.0;
270 }
271
272 // Find the boundary condition that is tagged as the flowrate boundary.
273 for (size_t i = 0; i < bcs.size(); ++i)
274 {
275 if (boost::iequals(bcs[i]->GetUserDefined(), "Flowrate"))
276 {
277 m_flowrateBndID = i;
278 break;
279 }
280 }
281
282 int tmpBr = m_flowrateBndID;
283 m_comm->AllReduce(tmpBr, LibUtilities::ReduceMax);
285 "One boundary region must be marked using the 'Flowrate' "
286 "user-defined type to monitor the volumetric flowrate.");
287
288 // Extract an appropriate expansion list to represents the boundary.
289 if (m_flowrateBndID >= 0)
290 {
291 // For a boundary, extract the boundary itself.
292 m_flowrateBnd = m_fields[0]->GetBndCondExpansions()[m_flowrateBndID];
293 }
295 {
296 // For 3DH1D simulations with no force specified, find the mean
297 // (0th) plane.
298 Array<OneD, unsigned int> zIDs = m_fields[0]->GetZIDs();
299 int tmpId = -1;
300
301 for (size_t i = 0; i < zIDs.size(); ++i)
302 {
303 if (zIDs[i] == 0)
304 {
305 tmpId = i;
306 break;
307 }
308 }
309
310 ASSERTL1(tmpId <= 0, "Should be either at location 0 or -1 if not "
311 "found");
312
313 if (tmpId != -1)
314 {
315 m_flowrateBnd = m_fields[0]->GetPlane(tmpId);
316 }
317 }
318
319 // At this point, some processors may not have m_flowrateBnd
320 // set if they don't contain the appropriate boundary. To
321 // calculate the area, we integrate 1.0 over the boundary
322 // (which has been set up with the appropriate subcommunicator
323 // to avoid deadlock), and then communicate this to the other
324 // processors with an AllReduce.
325 if (m_flowrateBnd)
326 {
327 Array<OneD, NekDouble> inArea(m_flowrateBnd->GetNpoints(), 1.0);
328 m_flowrateArea = m_flowrateBnd->Integral(inArea);
329 }
331
332 // In homogeneous case with forcing not aligned to the z-direction,
333 // redefine m_flowrateBnd so it is a 1D expansion
336 {
337 // For 3DH1D simulations with no force specified, find the mean
338 // (0th) plane.
339 Array<OneD, unsigned int> zIDs = m_fields[0]->GetZIDs();
340 m_planeID = -1;
341
342 for (size_t i = 0; i < zIDs.size(); ++i)
343 {
344 if (zIDs[i] == 0)
345 {
346 m_planeID = i;
347 break;
348 }
349 }
350
351 ASSERTL1(m_planeID <= 0, "Should be either at location 0 or -1 "
352 "if not found");
353
354 if (m_planeID != -1)
355 {
357 m_fields[0]->GetBndCondExpansions()[m_flowrateBndID]->GetPlane(
358 m_planeID);
359 }
360 }
361
362 // Set up some storage for the Stokes solution (to be stored in
363 // m_flowrateStokes) and its initial condition (inTmp), which holds the
364 // unit forcing.
365 int nqTot = m_fields[0]->GetNpoints();
368
369 for (int i = 0; i < m_spacedim; ++i)
370 {
371 inTmp[i] = Array<OneD, NekDouble>(nqTot, flowrateForce[i] * aii_dt);
373
375 {
376 Array<OneD, NekDouble> inTmp2(nqTot);
377 m_fields[i]->HomogeneousFwdTrans(nqTot, inTmp[i], inTmp2);
378 m_fields[i]->SetWaveSpace(true);
379 inTmp[i] = inTmp2;
380 }
381
382 Vmath::Zero(m_fields[i]->GetNcoeffs(), m_fields[i]->UpdateCoeffs(), 1);
383 }
384
385 // Create temporary extrapolation object to avoid issues with
386 // m_extrapolation for HOPBCs using higher order timestepping schemes.
387 // Zero pressure BCs in Neumann boundaries that may have been
388 // set in the advection step.
390 m_pressure->GetBndConditions();
392 m_pressure->GetBndCondExpansions();
393 for (size_t n = 0; n < PBndConds.size(); ++n)
394 {
395 if (PBndConds[n]->GetBoundaryConditionType() ==
397 {
398 Vmath::Zero(PBndExp[n]->GetNcoeffs(), PBndExp[n]->UpdateCoeffs(),
399 1);
400 }
401 }
402
403 // Finally, calculate the solution and the flux of the Stokes
404 // solution. We set m_greenFlux to maximum numeric limit, which signals
405 // to SolveUnsteadyStokesSystem that we don't need to apply a flowrate
406 // force.
407 m_greenFlux = numeric_limits<NekDouble>::max();
408 m_flowrateAiidt = aii_dt;
409
410 // Save the number of convective field in case it is not set
411 // to spacedim. Only need velocity components for stokes forcing
412 int SaveNConvectiveFields = m_nConvectiveFields;
414 SolveUnsteadyStokesSystem(inTmp, m_flowrateStokes, 0.0, aii_dt);
415 m_nConvectiveFields = SaveNConvectiveFields;
417
418 // If the user specified IO_FlowSteps, open a handle to store output.
419 if (m_comm->GetRank() == 0 && m_flowrateSteps &&
420 !m_flowrateStream.is_open())
421 {
422 std::string filename = m_session->GetSessionName();
423 filename += ".prs";
424 m_flowrateStream.open(filename.c_str());
425 m_flowrateStream.setf(ios::scientific, ios::floatfield);
426 m_flowrateStream << "# step time dP" << endl
427 << "# -------------------------------------------"
428 << endl;
429 }
430
431 // Replace pressure BCs with those evaluated from advection step
432 m_extrapolation->CopyPressureHBCsToPbndExp();
433}
434
435/**
436 * @brief Measure the volumetric flow rate through the volumetric flow rate
437 * reference surface.
438 *
439 * This routine computes the volumetric flow rate
440 *
441 * \f[
442 * Q(\mathbf{u}) = \frac{1}{\mu(R)} \int_R \mathbf{u} \cdot d\mathbf{s}
443 * \f]
444 *
445 * through the boundary region \f$ R \f$.
446 */
448 const Array<OneD, Array<OneD, NekDouble>> &inarray)
449{
450 NekDouble flowrate = 0.0;
451
452 if (m_flowrateBnd && m_flowrateBndID >= 0)
453 {
454 // If we're an actual boundary, calculate the vector flux through
455 // the boundary.
457
459 {
460 // General case
461 for (int i = 0; i < m_spacedim; ++i)
462 {
463 m_fields[i]->ExtractPhysToBnd(m_flowrateBndID, inarray[i],
464 boundary[i]);
465 }
466 flowrate = m_flowrateBnd->VectorFlux(boundary);
467 }
468 else if (m_planeID == 0)
469 {
470 // Homogeneous with forcing in plane. Calculate flux only on
471 // the meanmode - calculateFlux necessary for hybrid
472 // parallelisation.
473 for (int i = 0; i < m_spacedim; ++i)
474 {
475 m_fields[i]->GetPlane(m_planeID)->ExtractPhysToBnd(
476 m_flowrateBndID, inarray[i], boundary[i]);
477 }
478
479 // the flowrate is calculated on the mean mode so it needs to be
480 // multiplied by LZ to be consistent with the general case.
481 flowrate = m_flowrateBnd->VectorFlux(boundary) *
482 m_session->GetParameter("LZ");
483 }
484 }
486 {
487 // 3DH1D case with no Flowrate boundary defined: compute flux
488 // through the zero-th (mean) plane.
489 flowrate = m_flowrateBnd->Integral(inarray[2]);
490 }
491
492 // Communication to obtain the total flowrate
494 {
495 m_comm->GetColumnComm()->AllReduce(flowrate, LibUtilities::ReduceSum);
496 }
497 else
498 {
499 m_comm->GetSpaceComm()->AllReduce(flowrate, LibUtilities::ReduceSum);
500 }
501 return flowrate / m_flowrateArea;
502}
503
505{
506 if (m_flowrateSteps > 0)
507 {
508 if (m_comm->GetRank() == 0 && (step + 1) % m_flowrateSteps == 0)
509 {
510 m_flowrateStream << setw(8) << step << setw(16) << m_time
511 << setw(16) << m_alpha << endl;
512 }
513 }
514
516}
517
518/**
519 * Destructor
520 */
522{
523}
524
525/**
526 *
527 */
529{
531 SolverUtils::AddSummaryItem(s, "Splitting Scheme",
532 "Velocity correction (strong press. form)");
533
534 if (m_extrapolation->GetSubStepName().size())
535 {
536 SolverUtils::AddSummaryItem(s, "Substepping",
537 m_extrapolation->GetSubStepName());
538 }
539
540 string dealias = m_homogen_dealiasing ? "Homogeneous1D" : "";
542 {
543 dealias += (dealias == "" ? "" : " + ") + string("spectral/hp");
544 }
545 if (dealias != "")
546 {
547 SolverUtils::AddSummaryItem(s, "Dealiasing", dealias);
548 }
549
550 string smoothing = m_useSpecVanVisc ? "spectral/hp" : "";
551 if (smoothing != "")
552 {
554 {
556 s, "Smoothing-SpecHP",
557 "SVV (" + smoothing + " Exp Kernel(cut-off = " +
558 boost::lexical_cast<string>(m_sVVCutoffRatio) +
559 ", diff coeff = " +
560 boost::lexical_cast<string>(m_sVVDiffCoeff) + "))");
561 }
562 else
563 {
565 {
567 s, "Smoothing-SpecHP",
568 "SVV (" + smoothing + " Power Kernel (Power ratio =" +
569 boost::lexical_cast<string>(m_sVVCutoffRatio) +
570 ", diff coeff = " +
571 boost::lexical_cast<string>(m_sVVDiffCoeff) +
572 "*Uh/p))");
573 }
574 else
575 {
577 s, "Smoothing-SpecHP",
578 "SVV (" + smoothing + " DG Kernel (diff coeff = " +
579 boost::lexical_cast<string>(m_sVVDiffCoeff) +
580 "*Uh/p))");
581 }
582 }
583 }
584
586 {
588 s, "Smoothing-Homo1D",
589 "SVV (Homogeneous1D - Exp Kernel(cut-off = " +
590 boost::lexical_cast<string>(m_sVVCutoffRatioHomo1D) +
591 ", diff coeff = " +
592 boost::lexical_cast<string>(m_sVVDiffCoeffHomo1D) + "))");
593 }
594
596 {
598 s, "GJP Stab. Impl. ",
599 m_session->GetSolverInfo("GJPStabilisation"));
600 SolverUtils::AddSummaryItem(s, "GJP Stab. JumpScale", m_GJPJumpScale);
601
602 if (boost::iequals(m_session->GetSolverInfo("GJPStabilisation"),
603 "Explicit"))
604 {
606 s, "GJP Normal Velocity",
607 m_session->GetSolverInfo("GJPNormalVelocity"));
608 }
609 }
610}
611
612/**
613 *
614 */
615void VelocityCorrectionScheme::v_DoInitialise(bool dumpInitialConditions)
616{
618
619 for (int i = 0; i < m_nConvectiveFields; ++i)
620 {
622 }
623
624 m_flowrateAiidt = 0.0;
625
626 AdvectionSystem::v_DoInitialise(dumpInitialConditions);
627
628 // Set up Field Meta Data for output files
629 m_fieldMetaDataMap["Kinvis"] = boost::lexical_cast<std::string>(m_kinvis);
630 m_fieldMetaDataMap["TimeStep"] =
631 boost::lexical_cast<std::string>(m_timestep);
632
633 // set boundary conditions here so that any normal component
634 // correction are imposed before they are imposed on initial
635 // field below
637 std::map<std::string, NekDouble> params;
638 params["Time"] = m_time;
639 for (size_t i = 0; i < m_strFrameData.size(); ++i)
640 {
641 if (std::fabs(m_movingFrameData[i + 21]) != 0.)
642 {
643 params[m_strFrameData[i]] = m_movingFrameData[i + 21];
644 }
645 }
648 m_IncNavierStokesBCs->Update(fields, Adv, params);
649
650 // Ensure the initial conditions have correct BCs
651 for (size_t i = 0; i < m_fields.size(); ++i)
652 {
653 m_fields[i]->ImposeDirichletConditions(m_fields[i]->UpdateCoeffs());
654 m_fields[i]->LocalToGlobal();
655 m_fields[i]->GlobalToLocal();
656 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),
657 m_fields[i]->UpdatePhys());
658 }
659}
660
661/**
662 *
663 */
665{
666 size_t nfields = m_fields.size() - 1;
667 for (size_t k = 0; k < nfields; ++k)
668 {
669 // Backward Transformation in physical space for time evolution
670 m_fields[k]->BwdTrans(m_fields[k]->GetCoeffs(),
671 m_fields[k]->UpdatePhys());
672 }
673}
674
675/**
676 *
677 */
679{
680
681 size_t nfields = m_fields.size() - 1;
682 for (size_t k = 0; k < nfields; ++k)
683 {
684 // Forward Transformation in physical space for time evolution
685 m_fields[k]->FwdTransLocalElmt(m_fields[k]->GetPhys(),
686 m_fields[k]->UpdateCoeffs());
687 }
688}
689
690/**
691 *
692 */
694{
695 int vVar = m_session->GetVariables().size();
696 Array<OneD, bool> vChecks(vVar, false);
697 vChecks[vVar - 1] = true;
698 return vChecks;
699}
700
701/**
702 *
703 */
705{
706 return m_session->GetVariables().size() - 1;
707}
708
709/**
710 * Explicit part of the method - Advection, Forcing + HOPBCs
711 */
713 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
714 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
715{
717 timer.Start();
718 EvaluateAdvectionTerms(inarray, outarray, time);
719 timer.Stop();
720 timer.AccumulateRegion("Advection Terms");
721
722 // Smooth advection
724 {
725 for (int i = 0; i < m_nConvectiveFields; ++i)
726 {
727 m_pressure->SmoothField(outarray[i]);
728 }
729 }
730
731 // Add forcing terms
732 for (auto &x : m_forcing)
733 {
734 x->Apply(m_fields, inarray, outarray, time);
735 }
736
737 // Calculate High-Order pressure boundary conditions
738 timer.Start();
739 std::map<std::string, NekDouble> params;
740 params["Kinvis"] = m_kinvis;
741 params["Time"] = time + m_timestep;
742 for (size_t i = 0; i < m_strFrameData.size(); ++i)
743 {
744 if (std::fabs(m_movingFrameData[i + 21]) != 0.)
745 {
746 params[m_strFrameData[i]] = m_movingFrameData[i + 21];
747 }
748 }
749 m_extrapolation->EvaluatePressureBCs(inarray, outarray, m_kinvis);
750 m_IncNavierStokesBCs->Update(inarray, outarray, params);
751 timer.Stop();
752 timer.AccumulateRegion("Pressure BCs");
753}
754
755/**
756 * Implicit part of the method - Poisson + nConv*Helmholtz
757 */
759 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
761 [[maybe_unused]] const NekDouble time, const NekDouble aii_Dt)
762{
763 // Set up flowrate if we're starting for the first time or the value of
764 // aii_Dt has changed.
765 if (m_flowrate > 0.0 && (aii_Dt != m_flowrateAiidt))
766 {
767 SetupFlowrate(aii_Dt);
768 }
769
770 size_t physTot = m_fields[0]->GetTotPoints();
771
772 // Substep the pressure boundary condition if using substepping
773 m_extrapolation->SubStepSetPressureBCs(inarray, aii_Dt, m_kinvis);
774
775 // Set up forcing term for pressure Poisson equation
777 timer.Start();
778 SetUpPressureForcing(inarray, m_F, aii_Dt);
779 timer.Stop();
780 timer.AccumulateRegion("Pressure Forcing");
781
782 // Solve Pressure System
783 timer.Start();
784 SolvePressure(m_F[0]);
785 timer.Stop();
786 timer.AccumulateRegion("Pressure Solve");
787
788 // Set up forcing term for Helmholtz problems
789 timer.Start();
790 SetUpViscousForcing(inarray, m_F, aii_Dt);
791 timer.Stop();
792 timer.AccumulateRegion("Viscous Forcing");
793
794 // Solve velocity system
795 timer.Start();
796 SolveViscous(m_F, inarray, outarray, aii_Dt);
797 timer.Stop();
798 timer.AccumulateRegion("Viscous Solve");
799
800 // Apply flowrate correction
801 if (m_flowrate > 0.0 && m_greenFlux != numeric_limits<NekDouble>::max())
802 {
803 NekDouble currentFlux = MeasureFlowrate(outarray);
804 m_alpha = (m_flowrate - currentFlux) / m_greenFlux;
805
806 for (int i = 0; i < m_spacedim; ++i)
807 {
808 Vmath::Svtvp(physTot, m_alpha, m_flowrateStokes[i], 1, outarray[i],
809 1, outarray[i], 1);
810 // Enusre coeff space is updated for next time step
811 m_fields[i]->FwdTransLocalElmt(outarray[i],
812 m_fields[i]->UpdateCoeffs());
813 // Impsoe symmetry of flow on coeff space (good to enfore
814 // periodicity).
815 m_fields[i]->LocalToGlobal();
816 m_fields[i]->GlobalToLocal();
817 }
818 }
819}
820
821/**
822 * Forcing term for Poisson solver solver
823 */
825 const Array<OneD, const Array<OneD, NekDouble>> &fields,
827{
828 size_t i;
829 size_t physTot = m_fields[0]->GetTotPoints();
830 size_t nvel = m_velocity.size();
831
832 m_fields[0]->PhysDeriv(eX, fields[0], Forcing[0]);
833
834 for (i = 1; i < nvel; ++i)
835 {
836 // Use Forcing[1] as storage since it is not needed for the pressure
837 m_fields[i]->PhysDeriv(DirCartesianMap[i], fields[i], Forcing[1]);
838 Vmath::Vadd(physTot, Forcing[1], 1, Forcing[0], 1, Forcing[0], 1);
839 }
840
841 Vmath::Smul(physTot, 1.0 / aii_Dt, Forcing[0], 1, Forcing[0], 1);
842}
843
844/**
845 * Forcing term for Helmholtz solver
846 */
848 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
850{
851 NekDouble aii_dtinv = 1.0 / aii_Dt;
852 size_t phystot = m_fields[0]->GetTotPoints();
853
854 // Grad p
855 m_pressure->BwdTrans(m_pressure->GetCoeffs(), m_pressure->UpdatePhys());
856
857 int nvel = m_velocity.size();
858 if (nvel == 2)
859 {
860 m_pressure->PhysDeriv(m_pressure->GetPhys(), Forcing[m_velocity[0]],
861 Forcing[m_velocity[1]]);
862 }
863 else
864 {
865 m_pressure->PhysDeriv(m_pressure->GetPhys(), Forcing[m_velocity[0]],
867 }
868
869 // zero convective fields.
870 for (int i = nvel; i < m_nConvectiveFields; ++i)
871 {
872 Vmath::Zero(phystot, Forcing[i], 1);
873 }
874
875 // Subtract inarray/(aii_dt) and divide by kinvis. Kinvis will
876 // need to be updated for the convected fields.
877 for (int i = 0; i < m_nConvectiveFields; ++i)
878 {
879 Blas::Daxpy(phystot, -aii_dtinv, inarray[i], 1, Forcing[i], 1);
880 Blas::Dscal(phystot, 1.0 / m_diffCoeff[i], &(Forcing[i])[0], 1);
881 }
882}
883
884/**
885 * Solve pressure system
886 */
889{
891 // Setup coefficient for equation
893
894 // Solver Pressure Poisson Equation
895 m_pressure->HelmSolve(Forcing, m_pressure->UpdateCoeffs(), factors);
896
897 // Add presure to outflow bc if using convective like BCs
898 m_extrapolation->AddPressureToOutflowBCs(m_kinvis);
899}
900
901/**
902 * Solve velocity system
903 */
906 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
907 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble aii_Dt)
908{
912
913 AppendSVVFactors(factors, varFactorsMap);
914 ComputeGJPNormalVelocity(inarray, varCoeffMap);
915
916 // Solve Helmholtz system and put in Physical space
917 for (int i = 0; i < m_nConvectiveFields; ++i)
918 {
919 // Add diffusion coefficient to GJP matrix operator (Implicit part)
921 {
923 }
924
925 // Setup coefficients for equation
926 factors[StdRegions::eFactorLambda] = 1.0 / aii_Dt / m_diffCoeff[i];
927 m_fields[i]->HelmSolve(Forcing[i], m_fields[i]->UpdateCoeffs(), factors,
928 varCoeffMap, varFactorsMap);
929 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(), outarray[i]);
930 }
931}
932
934{
935
936 m_session->MatchSolverInfo("SpectralVanishingViscosity", "PowerKernel",
937 m_useSpecVanVisc, false);
938
940 {
942 }
943 else
944 {
946
947 m_session->MatchSolverInfo("SpectralVanishingViscositySpectralHP",
948 "PowerKernel", m_useSpecVanVisc, false);
949 }
950
952 {
953 m_IsSVVPowerKernel = true;
954 }
955 else
956 {
957 m_session->MatchSolverInfo("SpectralVanishingViscosity", "DGKernel",
958 m_useSpecVanVisc, false);
960 {
962 }
963 else
964 {
965 m_session->MatchSolverInfo("SpectralVanishingViscositySpectralHP",
966 "DGKernel", m_useSpecVanVisc, false);
967 }
968
970 {
971 m_IsSVVPowerKernel = false;
972 }
973 }
974
975 // set up varcoeff kernel if PowerKernel or DG is specified
977 {
980 if (m_session->DefinesFunction("SVVVelocityMagnitude"))
981 {
982 if (m_comm->GetRank() == 0)
983 {
984 cout << "Seting up SVV velocity from "
985 "SVVVelocityMagnitude section in session file"
986 << endl;
987 }
988 size_t nvel = m_velocity.size();
989 size_t phystot = m_fields[0]->GetTotPoints();
990 SVVVelFields = Array<OneD, Array<OneD, NekDouble>>(nvel);
991 vector<string> vars;
992 for (size_t i = 0; i < nvel; ++i)
993 {
994 SVVVelFields[i] = Array<OneD, NekDouble>(phystot);
995 vars.push_back(m_session->GetVariable(m_velocity[i]));
996 }
997
998 // Load up files into m_fields;
999 GetFunction("SVVVelocityMagnitude")->Evaluate(vars, SVVVelFields);
1000 }
1001
1003 SVVVarDiffCoeff(1.0, m_svvVarDiffCoeff, SVVVelFields);
1004 m_session->LoadParameter("SVVDiffCoeff", m_sVVDiffCoeff, 1.0);
1005 }
1006 else
1007 {
1009 m_session->LoadParameter("SVVDiffCoeff", m_sVVDiffCoeff, 0.1);
1010 }
1011
1012 // Load parameters for Spectral Vanishing Viscosity
1013 if (m_useSpecVanVisc == false)
1014 {
1015 m_session->MatchSolverInfo("SpectralVanishingViscosity", "True",
1016 m_useSpecVanVisc, false);
1017 if (m_useSpecVanVisc == false)
1018 {
1019 m_session->MatchSolverInfo("SpectralVanishingViscosity",
1020 "ExpKernel", m_useSpecVanVisc, false);
1021 }
1023
1024 if (m_useSpecVanVisc == false)
1025 {
1026 m_session->MatchSolverInfo("SpectralVanishingViscositySpectralHP",
1027 "True", m_useSpecVanVisc, false);
1028 if (m_useSpecVanVisc == false)
1029 {
1030 m_session->MatchSolverInfo(
1031 "SpectralVanishingViscositySpectralHP", "ExpKernel",
1032 m_useSpecVanVisc, false);
1033 }
1034 }
1035 }
1036
1037 // Case of only Homo1D kernel
1038 if (m_session->DefinesSolverInfo("SpectralVanishingViscosityHomo1D"))
1039 {
1040 m_session->MatchSolverInfo("SpectralVanishingViscosityHomo1D", "True",
1041 m_useHomo1DSpecVanVisc, false);
1042 if (m_useHomo1DSpecVanVisc == false)
1043 {
1044 m_session->MatchSolverInfo("SpectralVanishingViscosityHomo1D",
1045 "ExpKernel", m_useHomo1DSpecVanVisc,
1046 false);
1047 }
1048 }
1049
1050 m_session->LoadParameter("SVVCutoffRatio", m_sVVCutoffRatio, 0.75);
1051 m_session->LoadParameter("SVVCutoffRatioHomo1D", m_sVVCutoffRatioHomo1D,
1053 m_session->LoadParameter("SVVDiffCoeffHomo1D", m_sVVDiffCoeffHomo1D,
1055
1057 {
1058 ASSERTL0(
1060 "Expect to have three velocity fields with homogenous expansion");
1061
1063 {
1065 planes = m_fields[0]->GetZIDs();
1066
1067 size_t num_planes = planes.size();
1068 Array<OneD, NekDouble> SVV(num_planes, 0.0);
1069 NekDouble fac;
1070 size_t kmodes = m_fields[0]->GetHomogeneousBasis()->GetNumModes();
1071 size_t pstart;
1072
1073 pstart = m_sVVCutoffRatioHomo1D * kmodes;
1074
1075 for (size_t n = 0; n < num_planes; ++n)
1076 {
1077 if (planes[n] > pstart)
1078 {
1079 fac = (NekDouble)((planes[n] - kmodes) *
1080 (planes[n] - kmodes)) /
1081 ((NekDouble)((planes[n] - pstart) *
1082 (planes[n] - pstart)));
1083 SVV[n] = m_sVVDiffCoeffHomo1D * exp(-fac) / m_kinvis;
1084 }
1085 }
1086
1087 for (size_t i = 0; i < m_velocity.size(); ++i)
1088 {
1089 m_fields[m_velocity[i]]->SetHomo1DSpecVanVisc(SVV);
1090 }
1091 }
1092 }
1093}
1094
1096 const NekDouble velmag, Array<OneD, NekDouble> &diffcoeff,
1097 const Array<OneD, Array<OneD, NekDouble>> &vel)
1098{
1099 size_t phystot = m_fields[0]->GetTotPoints();
1100 size_t nel = m_fields[0]->GetNumElmts();
1101 size_t nvel, cnt;
1102
1104
1105 Vmath::Fill(nel, velmag, diffcoeff, 1);
1106
1107 if (vel != NullNekDoubleArrayOfArray)
1108 {
1109 Array<OneD, NekDouble> Velmag(phystot);
1110 nvel = vel.size();
1111 // calculate magnitude of v
1112 Vmath::Vmul(phystot, vel[0], 1, vel[0], 1, Velmag, 1);
1113 for (size_t n = 1; n < nvel; ++n)
1114 {
1115 Vmath::Vvtvp(phystot, vel[n], 1, vel[n], 1, Velmag, 1, Velmag, 1);
1116 }
1117 Vmath::Vsqrt(phystot, Velmag, 1, Velmag, 1);
1118
1119 cnt = 0;
1121 // calculate mean value of vel mag.
1122 for (size_t i = 0; i < nel; ++i)
1123 {
1124 size_t nq = m_fields[0]->GetExp(i)->GetTotPoints();
1125 tmp = Velmag + cnt;
1126 diffcoeff[i] = m_fields[0]->GetExp(i)->Integral(tmp);
1127 Vmath::Fill(nq, 1.0, tmp, 1);
1128 NekDouble area = m_fields[0]->GetExp(i)->Integral(tmp);
1129 diffcoeff[i] = diffcoeff[i] / area;
1130 cnt += nq;
1131 }
1132 }
1133 else
1134 {
1135 nvel = m_expdim;
1136 }
1137
1138 for (size_t e = 0; e < nel; e++)
1139 {
1140 LocalRegions::ExpansionSharedPtr exp = m_fields[0]->GetExp(e);
1141 NekDouble h = 0;
1142
1143 // Find maximum length of edge.
1144 size_t nEdge = exp->GetGeom()->GetNumEdges();
1145 for (size_t i = 0; i < nEdge; ++i)
1146 {
1147 h = max(h, exp->GetGeom()->GetEdge(i)->GetVertex(0)->dist(
1148 *(exp->GetGeom()->GetEdge(i)->GetVertex(1))));
1149 }
1150
1151 int p = 0;
1152 for (int i = 0; i < m_expdim; ++i)
1153 {
1154 p = max(p, exp->GetBasisNumModes(i) - 1);
1155 }
1156
1157 diffcoeff[e] *= h / p;
1158 }
1159}
1160
1163 MultiRegions::VarFactorsMap &varFactorsMap)
1164{
1165
1166 if (m_useSpecVanVisc)
1167 {
1171 {
1173 {
1176 }
1177 else
1178 {
1181 }
1182 }
1183 }
1184}
1185
1186/*
1187 * Calculate Normal velocity on Trace (boundary of elements)
1188 * for GJP stabilisation.
1189 * We only use this for explicit stabilisation. The Semi-Implicit
1190 * operator uses a constant u_{norm} = 1.0
1191 */
1193 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
1194 StdRegions::VarCoeffMap &varcoeffs)
1195{
1197 {
1199 std::dynamic_pointer_cast<MultiRegions::ContField>(m_fields[0]);
1200
1202 cfield->GetGJPForcing();
1203
1204 int nTracePts = GJPData->GetNumTracePts();
1205 Array<OneD, NekDouble> unorm(nTracePts, 1.0);
1206 Array<OneD, NekDouble> Fwd(nTracePts), Bwd(nTracePts);
1208 GJPData->GetTraceNormals();
1209
1210 m_fields[0]->GetFwdBwdTracePhys(inarray[0], Fwd, Bwd, true, true);
1211 Vmath::Vmul(nTracePts, Fwd, 1, traceNormals[0], 1, unorm, 1);
1212
1213 // Evaluate u.n on trace
1214 for (int f = 1; f < m_fields[0]->GetCoordim(0); ++f)
1215 {
1216 m_fields[0]->GetFwdBwdTracePhys(inarray[f], Fwd, Bwd, true, true);
1217 Vmath::Vvtvp(nTracePts, Fwd, 1, traceNormals[f], 1, unorm, 1, unorm,
1218 1);
1219 }
1220 Vmath::Vabs(nTracePts, unorm, 1, unorm, 1);
1221 varcoeffs[StdRegions::eVarCoeffGJPNormVel] = unorm;
1222 }
1223}
1224} // 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
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 GetNcoeffs()
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.
SOLVER_UTILS_EXPORT int GetTotPoints()
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.
static std::string className
Name of class.
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)
Constructor.
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)
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:48
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
STL namespace.