Nektar++
Loading...
Searching...
No Matches
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 "SemiImplicit"),
128 "Can not specify GJPNormalVelocity with"
129 " GJPStabilisation set to SemiImplicit");
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 m_session->LoadParameter("IO_FlowStepsPrecision", m_flowrateStepsPrecision,
149 6);
150}
151
153{
154 // creation of the extrapolation object
157 {
158 std::string vExtrapolation = v_GetExtrapolateStr();
159 if (m_session->DefinesSolverInfo("Extrapolation"))
160 {
161 vExtrapolation = v_GetSubSteppingExtrapolateStr(
162 m_session->GetSolverInfo("Extrapolation"));
163 }
165 vExtrapolation, m_session, m_fields, m_pressure, m_velocity,
167
168 m_extrapolation->SetForcing(m_forcing);
169 m_extrapolation->SubSteppingTimeIntegration(m_intScheme);
170 m_extrapolation->GenerateBndElmtExpansion();
171 m_extrapolation->GenerateHOPBCMap(m_session);
175 }
176}
177
178/**
179 * @brief Set up the Stokes solution used to impose constant flowrate
180 * through a boundary.
181 *
182 * This routine solves a Stokes equation using a unit forcing direction,
183 * specified by the user to be in the desired flow direction. This field can
184 * then be used to correct the end of each timestep to impose a constant
185 * volumetric flow rate through a user-defined boundary.
186 *
187 * There are three modes of operation:
188 *
189 * - Standard two-dimensional or three-dimensional simulations (e.g. pipes
190 * or channels)
191 * - 3DH1D simulations where the forcing is not in the homogeneous
192 * direction (e.g. channel flow, where the y-direction of the 2D mesh
193 * is perpendicular to the wall);
194 * - 3DH1D simulations where the forcing is in the homogeneous direction
195 * (e.g. pipe flow in the z-direction).
196 *
197 * In the first two cases, the user should define:
198 * - the `Flowrate` parameter, which dictates the volumetric flux through
199 * the reference area
200 * - tag a boundary region with the `Flowrate` user-defined type to define
201 * the reference area
202 * - define a `FlowrateForce` function with components `ForceX`, `ForceY`
203 * and `ForceZ` that defines a unit forcing in the appropriate direction.
204 *
205 * In the latter case, the user should define only the `Flowrate`; the
206 * reference area is taken to be the homogeneous plane and the force is
207 * assumed to be the unit z-vector \f$ \hat{e}_z \f$.
208 *
209 * This routine solves a single timestep of the Stokes problem
210 * (premultiplied by the backwards difference coefficient):
211 *
212 * \f[ \frac{\partial\mathbf{u}}{\partial t} = -\nabla p +
213 * \nu\nabla^2\mathbf{u} + \mathbf{f} \f]
214 *
215 * with a zero initial condition to obtain a field \f$ \mathbf{u}_s \f$. The
216 * flowrate is then corrected at each timestep \f$ n \f$ by adding the
217 * correction \f$ \alpha\mathbf{u}_s \f$ where
218 *
219 * \f[ \alpha = \frac{\overline{Q} - Q(\mathbf{u^n})}{Q(\mathbf{u}_s)} \f]
220 *
221 * where \f$ Q(\cdot)\f$ is the volumetric flux through the appropriate
222 * surface or line, which is implemented in
223 * VelocityCorrectionScheme::MeasureFlowrate. For more details, see chapter
224 * 3.2 of the thesis of D. Moxey (University of Warwick, 2011).
225 */
227{
228 m_flowrateBndID = -1;
229 m_flowrateArea = 0.0;
230
232 m_fields[0]->GetBndConditions();
233
234 std::string forces[] = {"X", "Y", "Z"};
235 Array<OneD, NekDouble> flowrateForce(m_spacedim, 0.0);
236
237 // Set up flowrate forces.
238 bool defined = true;
239 for (int i = 0; i < m_spacedim; ++i)
240 {
241 std::string varName = std::string("Force") + forces[i];
242 defined = m_session->DefinesFunction("FlowrateForce", varName);
243
244 if (!defined && m_HomogeneousType == eHomogeneous1D)
245 {
246 break;
247 }
248
249 ASSERTL0(defined,
250 "A 'FlowrateForce' function must defined with components "
251 "[ForceX, ...] to define direction of flowrate forcing");
252
254 m_session->GetFunction("FlowrateForce", varName);
255 flowrateForce[i] = ffunc->Evaluate();
256 }
257
258 // Define flag for case with homogeneous expansion and forcing not in the
259 // z-direction
260 m_homd1DFlowinPlane = false;
261 if (defined && m_HomogeneousType == eHomogeneous1D)
262 {
263 m_homd1DFlowinPlane = true;
264 }
265
266 // For 3DH1D simulations, if force isn't defined then assume in
267 // z-direction.
268 if (!defined)
269 {
270 flowrateForce[2] = 1.0;
271 }
272
273 // Find the boundary condition that is tagged as the flowrate boundary.
274 for (size_t i = 0; i < bcs.size(); ++i)
275 {
276 if (boost::iequals(bcs[i]->GetUserDefined(), "Flowrate"))
277 {
278 m_flowrateBndID = i;
279 break;
280 }
281 }
282
283 int tmpBr = m_flowrateBndID;
284 m_comm->AllReduce(tmpBr, LibUtilities::ReduceMax);
286 "One boundary region must be marked using the 'Flowrate' "
287 "user-defined type to monitor the volumetric flowrate.");
288
289 // Extract an appropriate expansion list to represents the boundary.
290 if (m_flowrateBndID >= 0)
291 {
292 // For a boundary, extract the boundary itself.
293 m_flowrateBnd = m_fields[0]->GetBndCondExpansions()[m_flowrateBndID];
294 }
296 {
297 // For 3DH1D simulations with no force specified, find the mean
298 // (0th) plane.
299 Array<OneD, unsigned int> zIDs = m_fields[0]->GetZIDs();
300 int tmpId = -1;
301
302 for (size_t i = 0; i < zIDs.size(); ++i)
303 {
304 if (zIDs[i] == 0)
305 {
306 tmpId = i;
307 break;
308 }
309 }
310
311 ASSERTL1(tmpId <= 0, "Should be either at location 0 or -1 if not "
312 "found");
313
314 if (tmpId != -1)
315 {
316 m_flowrateBnd = m_fields[0]->GetPlane(tmpId);
317 }
318 }
319
320 // At this point, some processors may not have m_flowrateBnd
321 // set if they don't contain the appropriate boundary. To
322 // calculate the area, we integrate 1.0 over the boundary
323 // (which has been set up with the appropriate subcommunicator
324 // to avoid deadlock), and then communicate this to the other
325 // processors with an AllReduce.
326 if (m_flowrateBnd)
327 {
328 Array<OneD, NekDouble> inArea(m_flowrateBnd->GetNpoints(), 1.0);
329 m_flowrateArea = m_flowrateBnd->Integral(inArea);
330 }
332
333 // In homogeneous case with forcing not aligned to the z-direction,
334 // redefine m_flowrateBnd so it is a 1D expansion
337 {
338 // For 3DH1D simulations with no force specified, find the mean
339 // (0th) plane.
340 Array<OneD, unsigned int> zIDs = m_fields[0]->GetZIDs();
341 m_planeID = -1;
342
343 for (size_t i = 0; i < zIDs.size(); ++i)
344 {
345 if (zIDs[i] == 0)
346 {
347 m_planeID = i;
348 break;
349 }
350 }
351
352 ASSERTL1(m_planeID <= 0, "Should be either at location 0 or -1 "
353 "if not found");
354
355 if (m_planeID != -1)
356 {
358 m_fields[0]->GetBndCondExpansions()[m_flowrateBndID]->GetPlane(
359 m_planeID);
360 }
361 }
362
363 // Set up some storage for the Stokes solution (to be stored in
364 // m_flowrateStokes) and its initial condition (inTmp), which holds the
365 // unit forcing.
366 int nqTot = m_fields[0]->GetNpoints();
369
370 for (int i = 0; i < m_spacedim; ++i)
371 {
372 inTmp[i] = Array<OneD, NekDouble>(nqTot, flowrateForce[i] * aii_dt);
374
376 {
377 Array<OneD, NekDouble> inTmp2(nqTot);
378 m_fields[i]->HomogeneousFwdTrans(nqTot, inTmp[i], inTmp2);
379 m_fields[i]->SetWaveSpace(true);
380 inTmp[i] = inTmp2;
381 }
382
383 Vmath::Zero(m_fields[i]->GetNcoeffs(), m_fields[i]->UpdateCoeffs(), 1);
384 }
385
386 // Create temporary extrapolation object to avoid issues with
387 // m_extrapolation for HOPBCs using higher order timestepping schemes.
388 // Zero pressure BCs in Neumann boundaries that may have been
389 // set in the advection step.
391 m_pressure->GetBndConditions();
393 m_pressure->GetBndCondExpansions();
394 for (size_t n = 0; n < PBndConds.size(); ++n)
395 {
396 if (PBndConds[n]->GetBoundaryConditionType() ==
398 {
399 Vmath::Zero(PBndExp[n]->GetNcoeffs(), PBndExp[n]->UpdateCoeffs(),
400 1);
401 }
402 }
403
404 // Finally, calculate the solution and the flux of the Stokes
405 // solution. We set m_greenFlux to maximum numeric limit, which signals
406 // to SolveUnsteadyStokesSystem that we don't need to apply a flowrate
407 // force.
408 m_greenFlux = std::numeric_limits<NekDouble>::max();
409 m_flowrateAiidt = aii_dt;
410
411 // Save the number of convective field in case it is not set
412 // to spacedim. Only need velocity components for stokes forcing
413 int SaveNConvectiveFields = m_nConvectiveFields;
415 // Save Dirichlet BCs and set to zero for Stokes solve
416 std::map<std::pair<int, int>, Array<OneD, NekDouble>> SaveDirBCs;
417 for (int i = 0; i < m_nConvectiveFields; ++i)
418 {
419 const Array<OneD, const ExpListSharedPtr> &BndCondExp =
420 m_fields[i]->GetBndCondExpansions();
421
422 for (int j = 0; j < BndCondExp.size(); ++j)
423 {
424 if (m_fields[i]
425 ->GetBndConditions()[j]
426 ->GetBoundaryConditionType() == SpatialDomains::eDirichlet)
427 {
428 Array<OneD, NekDouble> bndcoeffs =
429 m_fields[i]->UpdateBndCondExpansion(j)->UpdateCoeffs();
430 SaveDirBCs[std::make_pair(i, j)] =
431 Array<OneD, NekDouble>(bndcoeffs.size(), bndcoeffs.data());
432 Vmath::Zero(bndcoeffs.size(), bndcoeffs, 1);
433 }
434 }
435 }
436 SolveUnsteadyStokesSystem(inTmp, m_flowrateStokes, 0.0, aii_dt);
437 // Reset Dirichlet BCs
438 for (int i = 0; i < m_nConvectiveFields; ++i)
439 {
440 for (int j = 0; j < m_fields[i]->GetBndCondExpansions().size(); ++j)
441 {
442 if (m_fields[i]
443 ->GetBndConditions()[j]
444 ->GetBoundaryConditionType() == SpatialDomains::eDirichlet)
445 {
446 Array<OneD, NekDouble> bndcoeffs =
447 m_fields[i]->UpdateBndCondExpansion(j)->UpdateCoeffs();
448 Vmath::Vcopy(bndcoeffs.size(), SaveDirBCs[std::make_pair(i, j)],
449 1, bndcoeffs, 1);
450 }
451 }
452 }
453
454 m_nConvectiveFields = SaveNConvectiveFields;
456
457 // If the user specified IO_FlowSteps, open a handle to store output.
458 if (m_comm->GetRank() == 0 && m_flowrateSteps &&
459 !m_flowrateStream.is_open())
460 {
461 std::string filename = m_session->GetSessionName();
462 filename += ".prs";
463 m_flowrateStream.open(filename.c_str());
464 m_flowrateStream.setf(std::ios::scientific, std::ios::floatfield);
465 m_flowrateStream << "# step time dP" << std::endl
466 << "# -------------------------------------------"
467 << std::endl;
468 }
469
470 // Replace pressure BCs with those evaluated from advection step
471 m_extrapolation->CopyPressureHBCsToPbndExp();
472}
473
474/**
475 * @brief Measure the volumetric flow rate through the volumetric flow rate
476 * reference surface.
477 *
478 * This routine computes the volumetric flow rate
479 *
480 * \f[
481 * Q(\mathbf{u}) = \frac{1}{\mu(R)} \int_R \mathbf{u} \cdot d\mathbf{s}
482 * \f]
483 *
484 * through the boundary region \f$ R \f$.
485 */
487 const Array<OneD, Array<OneD, NekDouble>> &inarray)
488{
489 NekDouble flowrate = 0.0;
490
491 if (m_flowrateBnd && m_flowrateBndID >= 0)
492 {
493 // If we're an actual boundary, calculate the vector flux through
494 // the boundary.
496
498 {
499 // General case
500 for (int i = 0; i < m_spacedim; ++i)
501 {
502 m_fields[i]->ExtractPhysToBnd(m_flowrateBndID, inarray[i],
503 boundary[i]);
504 }
505 flowrate = m_flowrateBnd->VectorFlux(boundary);
506 }
507 else if (m_planeID == 0)
508 {
509 // Homogeneous with forcing in plane. Calculate flux only on
510 // the meanmode - calculateFlux necessary for hybrid
511 // parallelisation.
512 for (int i = 0; i < m_spacedim; ++i)
513 {
514 m_fields[i]->GetPlane(m_planeID)->ExtractPhysToBnd(
515 m_flowrateBndID, inarray[i], boundary[i]);
516 }
517
518 // the flowrate is calculated on the mean mode so it needs to be
519 // multiplied by LZ to be consistent with the general case.
520 flowrate = m_flowrateBnd->VectorFlux(boundary) *
521 m_session->GetParameter("LZ");
522 }
523 }
525 {
526 // 3DH1D case with no Flowrate boundary defined: compute flux
527 // through the zero-th (mean) plane.
528 flowrate = m_flowrateBnd->Integral(inarray[2]);
529 }
530
531 // Communication to obtain the total flowrate
533 {
534 m_comm->GetColumnComm()->AllReduce(flowrate, LibUtilities::ReduceSum);
535 }
536 else
537 {
538 m_comm->GetSpaceComm()->AllReduce(flowrate, LibUtilities::ReduceSum);
539 }
540 return flowrate / m_flowrateArea;
541}
542
544{
545 if (m_flowrateSteps > 0)
546 {
547 if (m_comm->GetRank() == 0 && (step + 1) % m_flowrateSteps == 0)
548 {
550 << std::setw(8) << step
551 << std::setw(m_flowrateStepsPrecision + 10) << m_time
552 << std::setw(m_flowrateStepsPrecision + 10) << std::fixed
553 << std::setprecision(m_flowrateStepsPrecision) << m_alpha
554 << std::endl;
555 }
556 }
557
559}
560
561/**
562 *
563 */
565{
566 AdvectionSystem::v_GenerateSummary(s);
567 SolverUtils::AddSummaryItem(s, "Splitting Scheme",
568 "Velocity correction (strong press. form)");
569
570 if (m_extrapolation->GetSubStepName().size())
571 {
572 SolverUtils::AddSummaryItem(s, "Substepping",
573 m_extrapolation->GetSubStepName());
574 }
575
576 std::string dealias = m_homogen_dealiasing ? "Homogeneous1D" : "";
578 {
579 dealias += (dealias == "" ? "" : " + ") + std::string("spectral/hp");
580 }
581 if (dealias != "")
582 {
583 SolverUtils::AddSummaryItem(s, "Dealiasing", dealias);
584 }
585
586 std::string smoothing = m_useSpecVanVisc ? "spectral/hp" : "";
587 if (smoothing != "")
588 {
590 {
592 s, "Smoothing-SpecHP",
593 "SVV (" + smoothing + " Exp Kernel(cut-off = " +
594 boost::lexical_cast<std::string>(m_sVVCutoffRatio) +
595 ", diff coeff = " +
596 boost::lexical_cast<std::string>(m_sVVDiffCoeff) + "))");
597 }
598 else
599 {
601 {
603 s, "Smoothing-SpecHP",
604 "SVV (" + smoothing + " Power Kernel (Power ratio =" +
605 boost::lexical_cast<std::string>(m_sVVCutoffRatio) +
606 ", diff coeff = " +
607 boost::lexical_cast<std::string>(m_sVVDiffCoeff) +
608 "*Uh/p))");
609 }
610 else
611 {
613 s, "Smoothing-SpecHP",
614 "SVV (" + smoothing + " DG Kernel (diff coeff = " +
615 boost::lexical_cast<std::string>(m_sVVDiffCoeff) +
616 "*Uh/p))");
617 }
618 }
619 }
620
622 {
624 s, "Smoothing-Homo1D",
625 "SVV (Homogeneous1D - Exp Kernel(cut-off = " +
626 boost::lexical_cast<std::string>(m_sVVCutoffRatioHomo1D) +
627 ", diff coeff = " +
628 boost::lexical_cast<std::string>(m_sVVDiffCoeffHomo1D) + "))");
629 }
630
632 {
634 s, "GJP Stab. Impl. ",
635 m_session->GetSolverInfo("GJPStabilisation"));
636 SolverUtils::AddSummaryItem(s, "GJP Stab. JumpScale", m_GJPJumpScale);
637
638 if (boost::iequals(m_session->GetSolverInfo("GJPStabilisation"),
639 "Explicit"))
640 {
642 s, "GJP Normal Velocity",
643 m_session->GetSolverInfo("GJPNormalVelocity"));
644 }
645 }
646}
647
648/**
649 *
650 */
651void VelocityCorrectionScheme::v_DoInitialise(bool dumpInitialConditions)
652{
654
655 for (int i = 0; i < m_nConvectiveFields; ++i)
656 {
658 }
659
660 m_flowrateAiidt = 0.0;
661
662 AdvectionSystem::v_DoInitialise(dumpInitialConditions);
663
664 // Set up Field Meta Data for output files
665 m_fieldMetaDataMap["Kinvis"] = boost::lexical_cast<std::string>(m_kinvis);
666 m_fieldMetaDataMap["TimeStep"] =
667 boost::lexical_cast<std::string>(m_timestep);
668
669 // set boundary conditions here so that any normal component
670 // correction are imposed before they are imposed on initial
671 // field below
673 std::map<std::string, NekDouble> params;
674 params["Time"] = m_time;
675 params["velocity"] = 1.;
679 m_IncNavierStokesBCs->Update(fields, Adv, params);
680
681 // Ensure the initial conditions have correct BCs
682 for (size_t i = 0; i < m_fields.size(); ++i)
683 {
684 m_fields[i]->ImposeDirichletConditions(m_fields[i]->UpdateCoeffs());
685 m_fields[i]->LocalToGlobal();
686 m_fields[i]->GlobalToLocal();
687 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),
688 m_fields[i]->UpdatePhys());
689 }
690
692 {
693 // initialise GJP in first field and copy to other convective fields
694 if (m_fields[0]->GetGJPData() == nullptr)
695 {
696 std::dynamic_pointer_cast<MultiRegions::ContField>(m_fields[0])
697 ->InitGJPData();
698 }
699 for (unsigned i = 1; i < m_nConvectiveFields; ++i)
700 {
701 std::dynamic_pointer_cast<MultiRegions::ContField>(m_fields[i])
702 ->SetGJPData(m_fields[0]->GetGJPData());
703 }
704 }
705}
706
707/**
708 *
709 */
711{
712 size_t nfields = m_fields.size() - 1;
713 for (size_t k = 0; k < nfields; ++k)
714 {
715 // Backward Transformation in physical space for time evolution
716 m_fields[k]->BwdTrans(m_fields[k]->GetCoeffs(),
717 m_fields[k]->UpdatePhys());
718 }
719}
720
721/**
722 *
723 */
725{
726
727 size_t nfields = m_fields.size() - 1;
728 for (size_t k = 0; k < nfields; ++k)
729 {
730 // Forward Transformation in physical space for time evolution
731 m_fields[k]->FwdTransLocalElmt(m_fields[k]->GetPhys(),
732 m_fields[k]->UpdateCoeffs());
733 }
734}
735
736/**
737 *
738 */
740{
741 int vVar = m_session->GetVariables().size();
742 Array<OneD, bool> vChecks(vVar, false);
743 vChecks[vVar - 1] = true;
744 return vChecks;
745}
746
747/**
748 *
749 */
751{
752 return m_session->GetVariables().size() - 1;
753}
754
755/**
756 * Explicit part of the method - Advection, Forcing + HOPBCs
757 */
759 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
760 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
761{
763 timer.Start();
764 EvaluateAdvectionTerms(inarray, outarray, time);
765 timer.Stop();
766 timer.AccumulateRegion("Advection Terms");
767
768 // Smooth advection
770 {
771 for (int i = 0; i < m_nConvectiveFields; ++i)
772 {
773 m_pressure->SmoothField(outarray[i]);
774 }
775 }
776
777 // Add forcing terms
778 for (auto &x : m_forcing)
779 {
780 x->Apply(m_fields, inarray, outarray, time);
781 }
782
783 // Calculate High-Order pressure boundary conditions
784 timer.Start();
785 std::map<std::string, NekDouble> params;
786 params["Kinvis"] = m_kinvis;
787 params["Time"] = time + m_timestep;
788 params["pressure"] = 1.;
790 m_extrapolation->EvaluatePressureBCs(inarray, outarray, m_kinvis);
791 m_IncNavierStokesBCs->Update(inarray, outarray, params);
792 timer.Stop();
793 timer.AccumulateRegion("Pressure BCs");
794}
795
796/**
797 * Implicit part of the method - Poisson + nConv*Helmholtz
798 */
800 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
802 [[maybe_unused]] const NekDouble time, const NekDouble aii_Dt)
803{
804 // Set up flowrate if we're starting for the first time or the value of
805 // aii_Dt has changed.
806 if (m_flowrate > 0.0 && (aii_Dt != m_flowrateAiidt))
807 {
808 SetupFlowrate(aii_Dt);
809 }
810
811 size_t physTot = m_fields[0]->GetTotPoints();
812
813 // Substep the pressure boundary condition if using substepping
814 m_extrapolation->SubStepSetPressureBCs(inarray, aii_Dt, m_kinvis);
815
816 // Set up forcing term for pressure Poisson equation
818 timer.Start();
819 SetUpPressureForcing(inarray, m_F, aii_Dt);
820 timer.Stop();
821 timer.AccumulateRegion("Pressure Forcing");
822
823 // Solve Pressure System
824 timer.Start();
825 SolvePressure(m_F[0]);
826 timer.Stop();
827 timer.AccumulateRegion("Pressure Solve");
828
829 // Set up forcing term for Helmholtz problems
830 timer.Start();
831 SolveSolid(time);
832 SetUpViscousForcing(inarray, m_F, aii_Dt);
833 timer.Stop();
834 timer.AccumulateRegion("Viscous Forcing");
835
836 // Solve velocity system
837 timer.Start();
838 SolveViscous(m_F, inarray, outarray, aii_Dt);
839 timer.Stop();
840 timer.AccumulateRegion("Viscous Solve");
841
842 // Apply flowrate correction
843 if (m_flowrate > 0.0 &&
844 m_greenFlux != std::numeric_limits<NekDouble>::max())
845 {
846 NekDouble currentFlux = MeasureFlowrate(outarray);
847 m_alpha = (m_flowrate - currentFlux) / m_greenFlux;
848
849 for (int i = 0; i < m_spacedim; ++i)
850 {
851 Vmath::Svtvp(physTot, m_alpha, m_flowrateStokes[i], 1, outarray[i],
852 1, outarray[i], 1);
853 // Enusre coeff space is updated for next time step
854 m_fields[i]->FwdTransLocalElmt(outarray[i],
855 m_fields[i]->UpdateCoeffs());
856 // Impsoe symmetry of flow on coeff space (good to enfore
857 // periodicity).
858 m_fields[i]->LocalToGlobal();
859 m_fields[i]->GlobalToLocal();
860 }
861 }
862}
863
868
870{
871 // update velocity boundary condition
874 std::map<std::string, NekDouble> params;
875 params["Time"] = time;
876 params["velocity"] = 1.;
878 m_IncNavierStokesBCs->Update(fields, Adv, params);
879}
880
881/**
882 * Forcing term for Poisson solver solver
883 */
885 const Array<OneD, const Array<OneD, NekDouble>> &fields,
887{
888 size_t i;
889 size_t physTot = m_fields[0]->GetTotPoints();
890 size_t nvel = m_velocity.size();
891
892 m_fields[0]->PhysDeriv(eX, fields[0], Forcing[0]);
893
894 for (i = 1; i < nvel; ++i)
895 {
896 // Use Forcing[1] as storage since it is not needed for the pressure
897 m_fields[i]->PhysDeriv(DirCartesianMap[i], fields[i], Forcing[1]);
898 Vmath::Vadd(physTot, Forcing[1], 1, Forcing[0], 1, Forcing[0], 1);
899 }
900
901 Vmath::Smul(physTot, 1.0 / aii_Dt, Forcing[0], 1, Forcing[0], 1);
902}
903
904/**
905 * Forcing term for Helmholtz solver
906 */
908 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
910{
911 NekDouble aii_dtinv = 1.0 / aii_Dt;
912 size_t phystot = m_fields[0]->GetTotPoints();
913
914 // Grad p
915 m_pressure->BwdTrans(m_pressure->GetCoeffs(), m_pressure->UpdatePhys());
916
917 int nvel = m_velocity.size();
918 if (nvel == 2)
919 {
920 m_pressure->PhysDeriv(m_pressure->GetPhys(), Forcing[m_velocity[0]],
921 Forcing[m_velocity[1]]);
922 }
923 else
924 {
925 m_pressure->PhysDeriv(m_pressure->GetPhys(), Forcing[m_velocity[0]],
927 }
928
929 // zero convective fields.
930 for (int i = nvel; i < m_nConvectiveFields; ++i)
931 {
932 Vmath::Zero(phystot, Forcing[i], 1);
933 }
934
935 // Subtract inarray/(aii_dt) and divide by kinvis. Kinvis will
936 // need to be updated for the convected fields.
937 for (int i = 0; i < m_nConvectiveFields; ++i)
938 {
939 Blas::Daxpy(phystot, -aii_dtinv, inarray[i], 1, Forcing[i], 1);
940 Blas::Dscal(phystot, 1.0 / m_diffCoeff[i], &(Forcing[i])[0], 1);
941 }
942}
943
944/**
945 * Solve pressure system
946 */
949{
951 // Setup coefficient for equation
952 factors[StdRegions::eFactorLambda] = 0.0;
953
954 // Solver Pressure Poisson Equation
955 m_pressure->HelmSolve(Forcing, m_pressure->UpdateCoeffs(), factors);
956
957 // Add presure to outflow bc if using convective like BCs
958 m_extrapolation->AddPressureToOutflowBCs(m_kinvis);
959}
960
961/**
962 * Solve velocity system
963 */
966 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
967 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble aii_Dt)
968{
972
973 AppendSVVFactors(factors, varFactorsMap);
974 ComputeGJPNormalVelocity(inarray, varCoeffMap);
975
976 // Solve Helmholtz system and put in Physical space
977 for (int i = 0; i < m_nConvectiveFields; ++i)
978 {
979 // Add diffusion coefficient to GJP matrix operator (Implicit part)
981 {
983 }
984
985 // Setup coefficients for equation
986 factors[StdRegions::eFactorLambda] = 1.0 / aii_Dt / m_diffCoeff[i];
987 m_fields[i]->HelmSolve(Forcing[i], m_fields[i]->UpdateCoeffs(), factors,
988 varCoeffMap, varFactorsMap);
989 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(), outarray[i]);
990 }
991}
992
994{
995
996 m_session->MatchSolverInfo("SpectralVanishingViscosity", "PowerKernel",
997 m_useSpecVanVisc, false);
998
1000 {
1002 }
1003 else
1004 {
1005 m_useHomo1DSpecVanVisc = false;
1006
1007 m_session->MatchSolverInfo("SpectralVanishingViscositySpectralHP",
1008 "PowerKernel", m_useSpecVanVisc, false);
1009 }
1010
1011 if (m_useSpecVanVisc)
1012 {
1013 m_IsSVVPowerKernel = true;
1014 }
1015 else
1016 {
1017 m_session->MatchSolverInfo("SpectralVanishingViscosity", "DGKernel",
1018 m_useSpecVanVisc, false);
1019 if (m_useSpecVanVisc)
1020 {
1022 }
1023 else
1024 {
1025 m_session->MatchSolverInfo("SpectralVanishingViscositySpectralHP",
1026 "DGKernel", m_useSpecVanVisc, false);
1027 }
1028
1029 if (m_useSpecVanVisc)
1030 {
1031 m_IsSVVPowerKernel = false;
1032 }
1033 }
1034
1035 // set up varcoeff kernel if PowerKernel or DG is specified
1036 if (m_useSpecVanVisc)
1037 {
1040 if (m_session->DefinesFunction("SVVVelocityMagnitude"))
1041 {
1042 if (m_comm->GetRank() == 0)
1043 {
1044 std::cout << "Seting up SVV velocity from "
1045 "SVVVelocityMagnitude section in session file"
1046 << std::endl;
1047 }
1048 size_t nvel = m_velocity.size();
1049 size_t phystot = m_fields[0]->GetTotPoints();
1050 SVVVelFields = Array<OneD, Array<OneD, NekDouble>>(nvel);
1051 std::vector<std::string> vars;
1052 for (size_t i = 0; i < nvel; ++i)
1053 {
1054 SVVVelFields[i] = Array<OneD, NekDouble>(phystot);
1055 vars.push_back(m_session->GetVariable(m_velocity[i]));
1056 }
1057
1058 // Load up files into m_fields;
1059 GetFunction("SVVVelocityMagnitude")->Evaluate(vars, SVVVelFields);
1060 }
1061
1063 SVVVarDiffCoeff(1.0, m_svvVarDiffCoeff, SVVVelFields);
1064 m_session->LoadParameter("SVVDiffCoeff", m_sVVDiffCoeff, 1.0);
1065 }
1066 else
1067 {
1069 m_session->LoadParameter("SVVDiffCoeff", m_sVVDiffCoeff, 0.1);
1070 }
1071
1072 // Load parameters for Spectral Vanishing Viscosity
1073 if (m_useSpecVanVisc == false)
1074 {
1075 m_session->MatchSolverInfo("SpectralVanishingViscosity", "True",
1076 m_useSpecVanVisc, false);
1077 if (m_useSpecVanVisc == false)
1078 {
1079 m_session->MatchSolverInfo("SpectralVanishingViscosity",
1080 "ExpKernel", m_useSpecVanVisc, false);
1081 }
1083
1084 if (m_useSpecVanVisc == false)
1085 {
1086 m_session->MatchSolverInfo("SpectralVanishingViscositySpectralHP",
1087 "True", m_useSpecVanVisc, false);
1088 if (m_useSpecVanVisc == false)
1089 {
1090 m_session->MatchSolverInfo(
1091 "SpectralVanishingViscositySpectralHP", "ExpKernel",
1092 m_useSpecVanVisc, false);
1093 }
1094 }
1095 }
1096
1097 // Case of only Homo1D kernel
1098 if (m_session->DefinesSolverInfo("SpectralVanishingViscosityHomo1D"))
1099 {
1100 m_session->MatchSolverInfo("SpectralVanishingViscosityHomo1D", "True",
1101 m_useHomo1DSpecVanVisc, false);
1102 if (m_useHomo1DSpecVanVisc == false)
1103 {
1104 m_session->MatchSolverInfo("SpectralVanishingViscosityHomo1D",
1105 "ExpKernel", m_useHomo1DSpecVanVisc,
1106 false);
1107 }
1108 }
1109
1110 m_session->LoadParameter("SVVCutoffRatio", m_sVVCutoffRatio, 0.75);
1111 m_session->LoadParameter("SVVCutoffRatioHomo1D", m_sVVCutoffRatioHomo1D,
1113 m_session->LoadParameter("SVVDiffCoeffHomo1D", m_sVVDiffCoeffHomo1D,
1115
1117 {
1118 ASSERTL0(
1120 "Expect to have three velocity fields with homogenous expansion");
1121
1123 {
1125 planes = m_fields[0]->GetZIDs();
1126
1127 size_t num_planes = planes.size();
1128 Array<OneD, NekDouble> SVV(num_planes, 0.0);
1129 NekDouble fac;
1130 size_t kmodes = m_fields[0]->GetHomogeneousBasis()->GetNumModes();
1131 size_t pstart;
1132
1133 pstart = m_sVVCutoffRatioHomo1D * kmodes;
1134
1135 for (size_t n = 0; n < num_planes; ++n)
1136 {
1137 if (planes[n] > pstart)
1138 {
1139 fac = (NekDouble)((planes[n] - kmodes) *
1140 (planes[n] - kmodes)) /
1141 ((NekDouble)((planes[n] - pstart) *
1142 (planes[n] - pstart)));
1143 SVV[n] = m_sVVDiffCoeffHomo1D * exp(-fac) / m_kinvis;
1144 }
1145 }
1146
1147 for (size_t i = 0; i < m_velocity.size(); ++i)
1148 {
1149 m_fields[m_velocity[i]]->SetHomo1DSpecVanVisc(SVV);
1150 }
1151 }
1152 }
1153}
1154
1156 const NekDouble velmag, Array<OneD, NekDouble> &diffcoeff,
1157 const Array<OneD, Array<OneD, NekDouble>> &vel)
1158{
1159 size_t phystot = m_fields[0]->GetTotPoints();
1160 size_t nel = m_fields[0]->GetNumElmts();
1161 size_t nvel, cnt;
1162
1164
1165 Vmath::Fill(nel, velmag, diffcoeff, 1);
1166
1167 if (vel != NullNekDoubleArrayOfArray)
1168 {
1169 Array<OneD, NekDouble> Velmag(phystot);
1170 nvel = vel.size();
1171 // calculate magnitude of v
1172 Vmath::Vmul(phystot, vel[0], 1, vel[0], 1, Velmag, 1);
1173 for (size_t n = 1; n < nvel; ++n)
1174 {
1175 Vmath::Vvtvp(phystot, vel[n], 1, vel[n], 1, Velmag, 1, Velmag, 1);
1176 }
1177 Vmath::Vsqrt(phystot, Velmag, 1, Velmag, 1);
1178
1179 cnt = 0;
1181 // calculate mean value of vel mag.
1182 for (size_t i = 0; i < nel; ++i)
1183 {
1184 size_t nq = m_fields[0]->GetExp(i)->GetTotPoints();
1185 tmp = Velmag + cnt;
1186 diffcoeff[i] = m_fields[0]->GetExp(i)->Integral(tmp);
1187 Vmath::Fill(nq, 1.0, tmp, 1);
1188 NekDouble area = m_fields[0]->GetExp(i)->Integral(tmp);
1189 diffcoeff[i] = diffcoeff[i] / area;
1190 cnt += nq;
1191 }
1192 }
1193 else
1194 {
1195 nvel = m_expdim;
1196 }
1197
1198 for (size_t e = 0; e < nel; e++)
1199 {
1200 LocalRegions::ExpansionSharedPtr exp = m_fields[0]->GetExp(e);
1201 NekDouble h = 0;
1202
1203 // Find maximum length of edge.
1204 size_t nEdge = exp->GetGeom()->GetNumEdges();
1205 for (size_t i = 0; i < nEdge; ++i)
1206 {
1207 h = std::max(h, exp->GetGeom()->GetEdge(i)->GetVertex(0)->dist(
1208 *(exp->GetGeom()->GetEdge(i)->GetVertex(1))));
1209 }
1210
1211 int p = 0;
1212 for (int i = 0; i < m_expdim; ++i)
1213 {
1214 p = std::max(p, exp->GetBasisNumModes(i) - 1);
1215 }
1216
1217 diffcoeff[e] *= h / p;
1218 }
1219}
1220
1223 StdRegions::VarFactorsMap &varFactorsMap)
1224{
1225
1226 if (m_useSpecVanVisc)
1227 {
1231 {
1233 {
1236 }
1237 else
1238 {
1241 }
1242 }
1243 }
1244}
1245
1246/*
1247 * Calculate Normal velocity on Trace (boundary of elements)
1248 * for GJP stabilisation.
1249 * We only use this for explicit stabilisation. The Semi-Implicit
1250 * operator uses a constant u_{norm} = 1.0
1251 */
1253 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
1254 StdRegions::VarCoeffMap &varcoeffs)
1255{
1257 {
1259 std::dynamic_pointer_cast<MultiRegions::ContField>(m_fields[0]);
1260
1261 cfield->InitGJPData();
1262
1263 MultiRegions::GJPStabilisationSharedPtr GJPData = cfield->GetGJPData();
1264
1265 int nTracePts = GJPData->GetNumTracePts();
1266 Array<OneD, NekDouble> unorm(nTracePts, 1.0);
1267 Array<OneD, NekDouble> Fwd(nTracePts), Bwd(nTracePts);
1269 GJPData->GetTraceNormals();
1270
1271 m_fields[0]->GetFwdBwdTracePhys(inarray[0], Fwd, Bwd, true, true);
1272 Vmath::Vmul(nTracePts, Fwd, 1, traceNormals[0], 1, unorm, 1);
1273
1274 // Evaluate u.n on trace
1275 for (int f = 1; f < m_fields[0]->GetCoordim(0); ++f)
1276 {
1277 m_fields[0]->GetFwdBwdTracePhys(inarray[f], Fwd, Bwd, true, true);
1278 Vmath::Vvtvp(nTracePts, Fwd, 1, traceNormals[f], 1, unorm, 1, unorm,
1279 1);
1280 }
1281 Vmath::Vabs(nTracePts, unorm, 1, unorm, 1);
1282 varcoeffs[StdRegions::eVarCoeffGJPNormVel] = unorm;
1283 }
1284}
1285
1287 const std::vector<std::string> &strFrameData,
1288 const Array<OneD, NekDouble> &movingFrameData,
1289 std::map<std::string, NekDouble> &params)
1290{
1291 for (size_t i = 0; i < strFrameData.size(); ++i)
1292 {
1293 if (std::fabs(movingFrameData[i]) != 0.0)
1294 {
1295 params[strFrameData[i]] = movingFrameData[i];
1296 }
1297 }
1298}
1299} // namespace Nektar
#define ASSERTL0(condition, msg)
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
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 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).
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.
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 body 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.
LibUtilities::TimeIntegrationSchemeSharedPtr m_intScheme
Wrapper to the time integration scheme.
bool m_explicitDiffusion
Indicates if explicit or implicit treatment of diffusion is used.
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)
int m_flowrateStepsPrecision
Decimal precision of flow rate (alpha)
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)
void AddMovingFrameDataToParams(const std::vector< std::string > &strFrameData, const Array< OneD, NekDouble > &movingFrameData, std::map< std::string, NekDouble > &params)
VelocityCorrectionScheme(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Array< OneD, Array< OneD, NekDouble > > m_F
void AppendSVVFactors(StdRegions::ConstFactorMap &factors, StdRegions::VarFactorsMap &varFactorsMap)
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_SolveSolid(NekDouble time)
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.
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:124
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:117
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< Equation > EquationSharedPtr
Definition Equation.h:131
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition Expansion.h:66
MultiRegions::Direction const DirCartesianMap[]
Definition ExpList.h:86
std::shared_ptr< GJPStabilisation > GJPStabilisationSharedPtr
std::shared_ptr< ContField > ContFieldSharedPtr
Definition ContField.h:295
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:224
std::map< StdRegions::ConstFactorType, Array< OneD, NekDouble > > VarFactorsMap
static VarFactorsMap NullVarFactorsMap
std::map< ConstFactorType, NekDouble > ConstFactorMap
static VarCoeffMap NullVarCoeffMap
std::map< StdRegions::VarCoeffType, VarCoeffEntry > VarCoeffMap
@ eUnsteadyNavierStokes
@ eVelocityCorrectionScheme
static Array< OneD, Array< OneD, NekDouble > > NullNekDoubleArrayOfArray
ExtrapolateFactory & GetExtrapolateFactory()
static Array< OneD, NekDouble > NullNekDouble1DArray
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
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition Vmath.hpp:825