Nektar++
IncNavierStokes.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: IncNavierStokes.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: Incompressible Navier Stokes class definition built on
32// ADRBase class
33//
34///////////////////////////////////////////////////////////////////////////////
35
36#include <boost/algorithm/string.hpp>
37#include <iomanip>
38
45
49#include <algorithm>
50#include <fstream>
51#include <iostream>
52#include <sstream>
53
56#include <tinyxml.h>
57
58using namespace std;
59
60namespace Nektar
61{
62
63std::string IncNavierStokes::eqTypeLookupIds[6] = {
69 "EqType", "SteadyNavierStokes", eSteadyNavierStokes),
71 "EqType", "SteadyLinearisedNS", eSteadyLinearisedNS),
73 "EqType", "UnsteadyNavierStokes", eUnsteadyNavierStokes),
74 LibUtilities::SessionReader::RegisterEnumValue("EqType", "UnsteadyStokes",
76
77/**
78 * Constructor. Creates ...
79 *
80 * \param
81 * \param
82 */
86 : UnsteadySystem(pSession, pGraph), AdvectionSystem(pSession, pGraph),
87 m_SmoothAdvection(false)
88{
89}
90
91void IncNavierStokes::v_InitObject(bool DeclareField)
92{
94
95 int i, j;
96 int numfields = m_fields.size();
97 std::string velids[] = {"u", "v", "w"};
98
99 // Set up Velocity field to point to the first m_expdim of m_fields;
101
102 for (i = 0; i < m_spacedim; ++i)
103 {
104 for (j = 0; j < numfields; ++j)
105 {
106 std::string var = m_boundaryConditions->GetVariable(j);
107 if (boost::iequals(velids[i], var))
108 {
109 m_velocity[i] = j;
110 break;
111 }
112
113 ASSERTL0(j != numfields, "Failed to find field: " + var);
114 }
115 }
116
117 // Set up equation type enum using kEquationTypeStr
118 for (i = 0; i < (int)eEquationTypeSize; ++i)
119 {
120 bool match;
121 m_session->MatchSolverInfo("EQTYPE", kEquationTypeStr[i], match, false);
122 if (match)
123 {
125 break;
126 }
127 }
128 ASSERTL0(i != eEquationTypeSize, "EQTYPE not found in SOLVERINFO section");
129
130 m_session->LoadParameter("Kinvis", m_kinvis);
131
132 // Default advection type per solver
133 std::string vConvectiveType;
134 switch (m_equationType)
135 {
136 case eUnsteadyStokes:
138 vConvectiveType = "NoAdvection";
139 break;
142 vConvectiveType = "Convective";
143 break;
145 vConvectiveType = "Linearised";
146 break;
147 default:
148 break;
149 }
150
151 // Check if advection type overridden
152 if (m_session->DefinesTag("AdvectiveType") &&
155 {
156 vConvectiveType = m_session->GetTag("AdvectiveType");
157 }
158
159 // Initialise advection
161 vConvectiveType, vConvectiveType);
162 m_advObject->InitObject(m_session, m_fields);
163
164 // Set up arrays for moving reference frame
165 // Note: this must be done before the forcing
166 m_movingFrameProjMat = bnu::identity_matrix<NekDouble>(3, 3);
167 if (DefinedForcing("MovingReferenceFrame"))
168 {
172 }
174
175 // Forcing terms
176 m_forcing = SolverUtils::Forcing::Load(m_session, shared_from_this(),
178
179 // check to see if any Robin boundary conditions and if so set
180 // up m_field to boundary condition maps;
184
185 for (size_t i = 0; i < m_fields.size(); ++i)
186 {
187 bool Set = false;
188
191 int radpts = 0;
192
193 BndConds = m_fields[i]->GetBndConditions();
194 BndExp = m_fields[i]->GetBndCondExpansions();
195 for (size_t n = 0; n < BndConds.size(); ++n)
196 {
197 if (boost::iequals(BndConds[n]->GetUserDefined(), "Radiation"))
198 {
199 ASSERTL0(
200 BndConds[n]->GetBoundaryConditionType() ==
202 "Radiation boundary condition must be of type Robin <R>");
203
204 if (Set == false)
205 {
206 m_fields[i]->GetBoundaryToElmtMap(m_fieldsBCToElmtID[i],
208 Set = true;
209 }
210 radpts += BndExp[n]->GetTotPoints();
211 }
212 if (boost::iequals(BndConds[n]->GetUserDefined(),
213 "ZeroNormalComponent"))
214 {
215 ASSERTL0(BndConds[n]->GetBoundaryConditionType() ==
217 "Zero Normal Component boundary condition option must "
218 "be of type Dirichlet <D>");
219
220 if (Set == false)
221 {
222 m_fields[i]->GetBoundaryToElmtMap(m_fieldsBCToElmtID[i],
224 Set = true;
225 }
226 }
227 }
228
230
231 radpts = 0; // reset to use as a counter
232
233 for (size_t n = 0; n < BndConds.size(); ++n)
234 {
235 if (boost::iequals(BndConds[n]->GetUserDefined(), "Radiation"))
236 {
237
238 int npoints = BndExp[n]->GetNpoints();
239 Array<OneD, NekDouble> x0(npoints, 0.0);
240 Array<OneD, NekDouble> x1(npoints, 0.0);
241 Array<OneD, NekDouble> x2(npoints, 0.0);
242 Array<OneD, NekDouble> tmpArray;
243
244 BndExp[n]->GetCoords(x0, x1, x2);
245
247 std::static_pointer_cast<
249 ->m_robinPrimitiveCoeff;
250
251 coeff.Evaluate(x0, x1, x2, m_time,
252 tmpArray = m_fieldsRadiationFactor[i] + radpts);
253 // Vmath::Neg(npoints,tmpArray = m_fieldsRadiationFactor[i]+
254 // radpts,1);
255 radpts += npoints;
256 }
257 }
258 }
259
260 // Set up maping for womersley BC - and load variables
261 for (size_t i = 0; i < m_fields.size(); ++i)
262 {
263 for (size_t n = 0; n < m_fields[i]->GetBndConditions().size(); ++n)
264 {
265 if (boost::istarts_with(
266 m_fields[i]->GetBndConditions()[n]->GetUserDefined(),
267 "Womersley"))
268 {
269 // assumes that boundary condition is applied in normal
270 // direction and is decomposed for each direction. There could
271 // be a unique file for each direction
272 m_womersleyParams[i][n] =
274 m_spacedim);
275 // Read in fourier coeffs and precompute coefficients
277 i, n, m_fields[i]->GetBndConditions()[n]->GetUserDefined());
278
279 m_fields[i]->GetBoundaryToElmtMap(m_fieldsBCToElmtID[i],
281 }
282 }
283 }
284
285 // Set up Field Meta Data for output files
286 m_fieldMetaDataMap["Kinvis"] = boost::lexical_cast<std::string>(m_kinvis);
287 m_fieldMetaDataMap["TimeStep"] =
288 boost::lexical_cast<std::string>(m_timestep);
289}
290
291/**
292 * Destructor
293 */
295{
296}
297
298/**
299 * Evaluation -N(V) for all fields except pressure using m_velocity
300 */
302 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
303 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
304{
305 size_t VelDim = m_velocity.size();
307
308 size_t npoints = m_fields[0]->GetNpoints();
309 for (size_t i = 0; i < VelDim; ++i)
310 {
311 velocity[i] = Array<OneD, NekDouble>(npoints);
312 Vmath::Vcopy(npoints, inarray[m_velocity[i]], 1, velocity[i], 1);
313 }
314 for (auto &x : m_forcing)
315 {
316 x->PreApply(m_fields, velocity, velocity, time);
317 }
318
320 outarray, time);
321}
322
323/**
324 * Time dependent boundary conditions updating
325 */
327{
328 size_t i, n;
329 std::string varName;
330 size_t nvariables = m_fields.size();
331
332 for (i = 0; i < nvariables; ++i)
333 {
334 for (n = 0; n < m_fields[i]->GetBndConditions().size(); ++n)
335 {
336 if (m_fields[i]->GetBndConditions()[n]->IsTimeDependent())
337 {
338 varName = m_session->GetVariable(i);
339 m_fields[i]->EvaluateBoundaryConditions(time, varName);
340 }
341 else if (boost::istarts_with(
342 m_fields[i]->GetBndConditions()[n]->GetUserDefined(),
343 "Womersley"))
344 {
346 }
347 }
348
349 // Set Radiation conditions if required
351 }
352
353 // Enforcing the boundary conditions (Inlet and wall) for the
354 // Moving reference frame
357}
358
359/**
360 * Probably should be pushed back into ContField?
361 */
363{
364 size_t i, n;
365
368
369 BndConds = m_fields[fieldid]->GetBndConditions();
370 BndExp = m_fields[fieldid]->GetBndCondExpansions();
371
374
375 size_t cnt;
376 size_t elmtid, nq, offset, boundary;
377 Array<OneD, NekDouble> Bvals, U;
378 size_t cnt1 = 0;
379
380 for (cnt = n = 0; n < BndConds.size(); ++n)
381 {
382 std::string type = BndConds[n]->GetUserDefined();
383
384 if ((BndConds[n]->GetBoundaryConditionType() ==
386 (boost::iequals(type, "Radiation")))
387 {
388 size_t nExp = BndExp[n]->GetExpSize();
389 for (i = 0; i < nExp; ++i, cnt++)
390 {
391 elmtid = m_fieldsBCToElmtID[m_velocity[fieldid]][cnt];
392 elmt = m_fields[fieldid]->GetExp(elmtid);
393 offset = m_fields[fieldid]->GetPhys_Offset(elmtid);
394
395 U = m_fields[fieldid]->UpdatePhys() + offset;
396 Bc = BndExp[n]->GetExp(i);
397
398 boundary = m_fieldsBCToTraceID[fieldid][cnt];
399
400 // Get edge values and put into ubc
401 nq = Bc->GetTotPoints();
403 elmt->GetTracePhysVals(boundary, Bc, U, ubc);
404
405 Vmath::Vmul(nq,
407 [fieldid][cnt1 + BndExp[n]->GetPhys_Offset(i)],
408 1, &ubc[0], 1, &ubc[0], 1);
409
410 Bvals =
411 BndExp[n]->UpdateCoeffs() + BndExp[n]->GetCoeff_Offset(i);
412
413 Bc->IProductWRTBase(ubc, Bvals);
414 }
415 cnt1 += BndExp[n]->GetTotPoints();
416 }
417 else
418 {
419 cnt += BndExp[n]->GetExpSize();
420 }
421 }
422}
423
425{
426 // use static trip since cannot use UserDefinedTag for zero
427 // velocity and have time dependent conditions
428 static bool Setup = false;
429
430 if (Setup == true)
431 {
432 return;
433 }
434 Setup = true;
435
436 size_t i, n;
437
439 BndConds(m_spacedim);
441
442 for (int i = 0; i < m_spacedim; ++i)
443 {
444 BndConds[i] = m_fields[m_velocity[i]]->GetBndConditions();
445 BndExp[i] = m_fields[m_velocity[i]]->GetBndCondExpansions();
446 }
447
449
450 size_t cnt;
451 size_t elmtid, nq, boundary;
452
454 Array<OneD, NekDouble> Bphys, Bcoeffs;
455
456 size_t fldid = m_velocity[0];
457
458 for (cnt = n = 0; n < BndConds[0].size(); ++n)
459 {
460 if ((BndConds[0][n]->GetBoundaryConditionType() ==
462 (boost::iequals(BndConds[0][n]->GetUserDefined(),
463 "ZeroNormalComponent")))
464 {
465 size_t nExp = BndExp[0][n]->GetExpSize();
466 for (i = 0; i < nExp; ++i, cnt++)
467 {
468 elmtid = m_fieldsBCToElmtID[fldid][cnt];
469 elmt = m_fields[0]->GetExp(elmtid);
470 boundary = m_fieldsBCToTraceID[fldid][cnt];
471
472 normals = elmt->GetTraceNormal(boundary);
473
474 nq = BndExp[0][n]->GetExp(i)->GetTotPoints();
475 Array<OneD, NekDouble> normvel(nq, 0.0);
476
477 for (int k = 0; k < m_spacedim; ++k)
478 {
479 Bphys = BndExp[k][n]->UpdatePhys() +
480 BndExp[k][n]->GetPhys_Offset(i);
481 Bc = BndExp[k][n]->GetExp(i);
482 Vmath::Vvtvp(nq, normals[k], 1, Bphys, 1, normvel, 1,
483 normvel, 1);
484 }
485
486 // negate normvel for next step
487 Vmath::Neg(nq, normvel, 1);
488
489 for (int k = 0; k < m_spacedim; ++k)
490 {
491 Bphys = BndExp[k][n]->UpdatePhys() +
492 BndExp[k][n]->GetPhys_Offset(i);
493 Bcoeffs = BndExp[k][n]->UpdateCoeffs() +
494 BndExp[k][n]->GetCoeff_Offset(i);
495 Bc = BndExp[k][n]->GetExp(i);
496 Vmath::Vvtvp(nq, normvel, 1, normals[k], 1, Bphys, 1, Bphys,
497 1);
498 Bc->FwdTransBndConstrained(Bphys, Bcoeffs);
499 }
500 }
501 }
502 else
503 {
504 cnt += BndExp[0][n]->GetExpSize();
505 }
506 }
507}
508
509/**
510 * Womersley boundary condition defintion
511 */
512void IncNavierStokes::SetWomersleyBoundary(const int fldid, const int bndid)
513{
514 ASSERTL1(m_womersleyParams.count(bndid) == 1,
515 "Womersley parameters for this boundary have not been set up");
516
517 WomersleyParamsSharedPtr WomParam = m_womersleyParams[fldid][bndid];
518 NekComplexDouble zvel;
519 size_t i, j, k;
520
521 size_t M_coeffs = WomParam->m_wom_vel.size();
522
523 NekDouble T = WomParam->m_period;
524 NekDouble axis_normal = WomParam->m_axisnormal[fldid];
525
526 // Womersley Number
527 NekComplexDouble omega_c(2.0 * M_PI / T, 0.0);
528 NekComplexDouble k_c(0.0, 0.0);
529 NekComplexDouble m_time_c(m_time, 0.0);
530 NekComplexDouble zi(0.0, 1.0);
531 NekComplexDouble i_pow_3q2(-1.0 / sqrt(2.0), 1.0 / sqrt(2.0));
532
534 BndCondExp = m_fields[fldid]->GetBndCondExpansions()[bndid];
535
537 size_t cnt = 0;
538 size_t nfq;
540 size_t exp_npts = BndCondExp->GetExpSize();
541 Array<OneD, NekDouble> wbc(exp_npts, 0.0);
542
544
545 // preallocate the exponent
546 for (k = 1; k < M_coeffs; k++)
547 {
548 k_c = NekComplexDouble((NekDouble)k, 0.0);
549 zt[k] = std::exp(zi * omega_c * k_c * m_time_c);
550 }
551
552 // Loop over each element in an expansion
553 for (i = 0; i < exp_npts; ++i, cnt++)
554 {
555 // Get Boundary and trace expansion
556 bc = BndCondExp->GetExp(i);
557 nfq = bc->GetTotPoints();
558 Array<OneD, NekDouble> wbc(nfq, 0.0);
559
560 // Compute womersley solution
561 for (j = 0; j < nfq; j++)
562 {
563 wbc[j] = WomParam->m_poiseuille[i][j];
564 for (k = 1; k < M_coeffs; k++)
565 {
566 zvel = WomParam->m_zvel[i][j][k] * zt[k];
567 wbc[j] = wbc[j] + zvel.real();
568 }
569 }
570
571 // Multiply w by normal to get u,v,w component of velocity
572 Vmath::Smul(nfq, axis_normal, wbc, 1, wbc, 1);
573 // get the offset
574 Bvals = BndCondExp->UpdateCoeffs() + BndCondExp->GetCoeff_Offset(i);
575
576 // Push back to Coeff space
577 bc->FwdTrans(wbc, Bvals);
578 }
579}
580
581void IncNavierStokes::SetUpWomersley(const int fldid, const int bndid,
582 std::string womStr)
583{
584 std::string::size_type indxBeg = womStr.find_first_of(':') + 1;
585 string filename = womStr.substr(indxBeg, string::npos);
586
587 TiXmlDocument doc(filename);
588
589 bool loadOkay = doc.LoadFile();
590 ASSERTL0(loadOkay,
591 (std::string("Failed to load file: ") + filename).c_str());
592
593 TiXmlHandle docHandle(&doc);
594
595 int err; /// Error value returned by TinyXML.
596
597 TiXmlElement *nektar = doc.FirstChildElement("NEKTAR");
598 ASSERTL0(nektar, "Unable to find NEKTAR tag in file.");
599
600 TiXmlElement *wombc = nektar->FirstChildElement("WOMERSLEYBC");
601 ASSERTL0(wombc, "Unable to find WOMERSLEYBC tag in file.");
602
603 // read womersley parameters
604 TiXmlElement *womparam = wombc->FirstChildElement("WOMPARAMS");
605 ASSERTL0(womparam, "Unable to find WOMPARAMS tag in file.");
606
607 // Input coefficients
608 TiXmlElement *params = womparam->FirstChildElement("W");
609 map<std::string, std::string> Wparams;
610
611 // read parameter list
612 while (params)
613 {
614
615 std::string propstr;
616 propstr = params->Attribute("PROPERTY");
617
618 ASSERTL0(!propstr.empty(),
619 "Failed to read PROPERTY value Womersley BC Parameter");
620
621 std::string valstr;
622 valstr = params->Attribute("VALUE");
623
624 ASSERTL0(!valstr.empty(),
625 "Failed to read VALUE value Womersley BC Parameter");
626
627 std::transform(propstr.begin(), propstr.end(), propstr.begin(),
628 ::toupper);
629 Wparams[propstr] = valstr;
630
631 params = params->NextSiblingElement("W");
632 }
633 bool parseGood;
634
635 // Read parameters
636
637 ASSERTL0(
638 Wparams.count("RADIUS") == 1,
639 "Failed to find Radius parameter in Womersley boundary conditions");
640 std::vector<NekDouble> rad;
641 ParseUtils::GenerateVector(Wparams["RADIUS"], rad);
642 m_womersleyParams[fldid][bndid]->m_radius = rad[0];
643
644 ASSERTL0(
645 Wparams.count("PERIOD") == 1,
646 "Failed to find period parameter in Womersley boundary conditions");
647 std::vector<NekDouble> period;
648 parseGood = ParseUtils::GenerateVector(Wparams["PERIOD"], period);
649 m_womersleyParams[fldid][bndid]->m_period = period[0];
650
651 ASSERTL0(
652 Wparams.count("AXISNORMAL") == 1,
653 "Failed to find axisnormal parameter in Womersley boundary conditions");
654 std::vector<NekDouble> anorm;
655 parseGood = ParseUtils::GenerateVector(Wparams["AXISNORMAL"], anorm);
656 m_womersleyParams[fldid][bndid]->m_axisnormal[0] = anorm[0];
657 m_womersleyParams[fldid][bndid]->m_axisnormal[1] = anorm[1];
658 m_womersleyParams[fldid][bndid]->m_axisnormal[2] = anorm[2];
659
660 ASSERTL0(
661 Wparams.count("AXISPOINT") == 1,
662 "Failed to find axispoint parameter in Womersley boundary conditions");
663 std::vector<NekDouble> apt;
664 parseGood = ParseUtils::GenerateVector(Wparams["AXISPOINT"], apt);
665 m_womersleyParams[fldid][bndid]->m_axispoint[0] = apt[0];
666 m_womersleyParams[fldid][bndid]->m_axispoint[1] = apt[1];
667 m_womersleyParams[fldid][bndid]->m_axispoint[2] = apt[2];
668
669 // Read Temporal Fourier Coefficients.
670
671 // Find the FourierCoeff tag
672 TiXmlElement *coeff = wombc->FirstChildElement("FOURIERCOEFFS");
673
674 // Input coefficients
675 TiXmlElement *fval = coeff->FirstChildElement("F");
676
677 int indx;
678
679 while (fval)
680 {
681 TiXmlAttribute *fvalAttr = fval->FirstAttribute();
682 std::string attrName(fvalAttr->Name());
683
684 ASSERTL0(attrName == "ID",
685 (std::string("Unknown attribute name: ") + attrName).c_str());
686
687 err = fvalAttr->QueryIntValue(&indx);
688 ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID.");
689
690 std::string coeffStr = fval->FirstChild()->ToText()->ValueStr();
691 vector<NekDouble> coeffvals;
692
693 parseGood = ParseUtils::GenerateVector(coeffStr, coeffvals);
694 ASSERTL0(
695 parseGood,
696 (std::string("Problem reading value of fourier coefficient, ID=") +
697 boost::lexical_cast<string>(indx))
698 .c_str());
699 ASSERTL1(
700 coeffvals.size() == 2,
701 (std::string(
702 "Have not read two entries of Fourier coefficicent from ID=" +
703 boost::lexical_cast<string>(indx))
704 .c_str()));
705
706 m_womersleyParams[fldid][bndid]->m_wom_vel.push_back(
707 NekComplexDouble(coeffvals[0], coeffvals[1]));
708
709 fval = fval->NextSiblingElement("F");
710 }
711
712 // starting point of precalculation
713 size_t i, j, k;
714 // M fourier coefficients
715 size_t M_coeffs = m_womersleyParams[fldid][bndid]->m_wom_vel.size();
716 NekDouble R = m_womersleyParams[fldid][bndid]->m_radius;
717 NekDouble T = m_womersleyParams[fldid][bndid]->m_period;
718 Array<OneD, NekDouble> x0 = m_womersleyParams[fldid][bndid]->m_axispoint;
719
721 // Womersley Number
722 NekComplexDouble omega_c(2.0 * M_PI / T, 0.0);
723 NekComplexDouble alpha_c(R * sqrt(omega_c.real() / m_kinvis), 0.0);
724 NekComplexDouble z1(1.0, 0.0);
725 NekComplexDouble i_pow_3q2(-1.0 / sqrt(2.0), 1.0 / sqrt(2.0));
726
728 BndCondExp = m_fields[fldid]->GetBndCondExpansions()[bndid];
729
731 size_t cnt = 0;
732 size_t nfq;
734
735 size_t exp_npts = BndCondExp->GetExpSize();
736 Array<OneD, NekDouble> wbc(exp_npts, 0.0);
737
738 // allocate time indepedent variables
739 m_womersleyParams[fldid][bndid]->m_poiseuille =
741 m_womersleyParams[fldid][bndid]->m_zvel =
743 // could use M_coeffs - 1 but need to avoid complicating things
744 Array<OneD, NekComplexDouble> zJ0(M_coeffs);
745 Array<OneD, NekComplexDouble> lamda_n(M_coeffs);
746 Array<OneD, NekComplexDouble> k_c(M_coeffs);
747 NekComplexDouble zJ0r;
748
749 for (k = 1; k < M_coeffs; k++)
750 {
751 k_c[k] = NekComplexDouble((NekDouble)k, 0.0);
752 lamda_n[k] = i_pow_3q2 * alpha_c * sqrt(k_c[k]);
753 zJ0[k] = Polylib::ImagBesselComp(0, lamda_n[k]);
754 }
755
756 // Loop over each element in an expansion
757 for (i = 0; i < exp_npts; ++i, cnt++)
758 {
759 // Get Boundary and trace expansion
760 bc = BndCondExp->GetExp(i);
761 nfq = bc->GetTotPoints();
762
763 Array<OneD, NekDouble> x(nfq, 0.0);
764 Array<OneD, NekDouble> y(nfq, 0.0);
765 Array<OneD, NekDouble> z(nfq, 0.0);
766 bc->GetCoords(x, y, z);
767
768 m_womersleyParams[fldid][bndid]->m_poiseuille[i] =
770 m_womersleyParams[fldid][bndid]->m_zvel[i] =
772
773 // Compute coefficients
774 for (j = 0; j < nfq; j++)
775 {
776 rqR = NekComplexDouble(sqrt((x[j] - x0[0]) * (x[j] - x0[0]) +
777 (y[j] - x0[1]) * (y[j] - x0[1]) +
778 (z[j] - x0[2]) * (z[j] - x0[2])) /
779 R,
780 0.0);
781
782 // Compute Poiseulle Flow
783 m_womersleyParams[fldid][bndid]->m_poiseuille[i][j] =
784 m_womersleyParams[fldid][bndid]->m_wom_vel[0].real() *
785 (1. - rqR.real() * rqR.real());
786
787 m_womersleyParams[fldid][bndid]->m_zvel[i][j] =
789
790 // compute the velocity information
791 for (k = 1; k < M_coeffs; k++)
792 {
793 zJ0r = Polylib::ImagBesselComp(0, rqR * lamda_n[k]);
794 m_womersleyParams[fldid][bndid]->m_zvel[i][j][k] =
795 m_womersleyParams[fldid][bndid]->m_wom_vel[k] *
796 (z1 - (zJ0r / zJ0[k]));
797 }
798 }
799 }
800}
801
802/**
803 * Set boundary conditions for moving frame of reference
804 */
806{
807 SetMRFWallBCs(time);
808 SetMRFDomainVelBCs(time);
809}
810
811/**
812 * Set Wall boundary conditions for moving frame of reference
813 */
814void IncNavierStokes::SetMRFWallBCs([[maybe_unused]] const NekDouble &time)
815{
816 // for the wall we need to calculate:
817 // [V_wall]_xyz = [V_frame]_xyz + [Omega X r]_xyz
818 // Note all vectors must be in moving frame coordinates xyz
819 // not in inertial frame XYZ
820
822 BndConds(m_spacedim + 1);
824 1);
825
826 for (int i = 0; i < m_spacedim; ++i)
827 {
828 BndConds[i] = m_fields[m_velocity[i]]->GetBndConditions();
829 BndExp[i] = m_fields[m_velocity[i]]->GetBndCondExpansions();
830 }
831 BndConds[m_spacedim] = m_fields[m_fields.size() - 1]->GetBndConditions();
832 BndExp[m_spacedim] = m_fields[m_fields.size() - 1]->GetBndCondExpansions();
833
834 int npoints;
835 Array<OneD, NekDouble> Bphys, Bcoeffs;
836
837 // loop over the boundary regions
838 for (size_t n = 0; n < BndExp[0].size(); ++n)
839 {
840 std::set<int> MRFwall;
841 for (size_t k = 0; k < BndConds.size(); ++k)
842 {
843 if (BndConds[k][n]->GetBoundaryConditionType() ==
845 (boost::iequals(BndConds[k][n]->GetUserDefined(),
846 "MovingFrameWall")))
847 {
848 MRFwall.insert(k);
849 }
850 }
851 if (MRFwall.empty())
852 {
853 continue;
854 }
855 npoints = BndExp[0][n]->GetNpoints();
856 //
857 // define arrays to calculate the prescribed velocities and modifed
858 // ones
862 for (size_t k = 0; k < m_velocity.size(); ++k)
863 {
864 velocities[k] = Array<OneD, NekDouble>(npoints, 0.0);
865 acceleration[k] = Array<OneD, NekDouble>(npoints, 0.0);
866 }
867 Array<OneD, NekDouble> tmp(npoints, 0.0);
868 for (size_t k = 0; k < 3; ++k)
869 {
870 coords[k] = Array<OneD, NekDouble>(npoints, 0.0);
871 }
872 BndExp[0][n]->GetCoords(coords[0], coords[1], coords[2]);
873
874 // move the centre to the location of pivot
875 for (int i = 0; i < m_spacedim; ++i)
876 {
877 Vmath::Sadd(npoints, -m_pivotPoint[i], coords[i], 1, coords[i], 1);
878 }
879 /////////////////////////////////////
880 // Note that both Omega and the absolute velocities have been
881 // expressed in the moving reference frame unit vectors
882 // therefore the result is in moving ref frame and no furhter
883 // transformaton is required
884 //
885 // compute Omega X r = vx ex + vy ey + vz ez
886 // Note OmegaX : movingFrameVelsxyz[3]
887 // Note OmegaY : movingFrameVelsxyz[4]
888 // Note OmegaZ : movingFrameVelsxyz[5]
889 //
890 // vx = OmegaY*z-OmegaZ*y
891 Vmath::Smul(npoints, -1 * m_movingFrameVelsxyz[5], coords[1], 1,
892 velocities[0], 1);
893 // vy = OmegaZ*x-OmegaX*z
894 Vmath::Smul(npoints, m_movingFrameVelsxyz[5], coords[0], 1,
895 velocities[1], 1);
896 if (m_spacedim == 3)
897 {
898 // add the OmegaY*z to vx
899 Vmath::Svtvp(npoints, m_movingFrameVelsxyz[4], coords[2], 1,
900 velocities[0], 1, velocities[0], 1);
901 // add the -OmegaX*z to vy
902 Vmath::Svtvp(npoints, -1 * m_movingFrameVelsxyz[3], coords[2], 1,
903 velocities[1], 1, velocities[1], 1);
904
905 // vz = OmegaX*y-OmegaY*x
906 Vmath::Svtsvtp(npoints, m_movingFrameVelsxyz[3], coords[1], 1,
907 -1.0 * m_movingFrameVelsxyz[4], coords[0], 1,
908 velocities[2], 1);
909 }
910
911 // add the translation velocity
912 for (int k = 0; k < m_spacedim; ++k)
913 {
914 Vmath::Sadd(npoints, m_movingFrameVelsxyz[k], velocities[k], 1,
915 velocities[k], 1);
916 }
917
918 // set up pressure condition
919 Vmath::Svtsvtp(npoints,
921 coords[0], 1, m_movingFrameVelsxyz[11], coords[1], 1,
922 acceleration[0], 1);
923 Vmath::Svtsvtp(npoints,
925 coords[1], 1, -m_movingFrameVelsxyz[11], coords[0], 1,
926 acceleration[1], 1);
927 for (int k = 0; k < m_spacedim; ++k)
928 {
929 Vmath::Sadd(npoints, -m_movingFrameVelsxyz[6 + k], acceleration[k],
930 1, acceleration[k], 1);
931 }
932
933 // update the boundary values
934 for (auto k : MRFwall)
935 {
936 if (k < m_spacedim)
937 {
938 Vmath::Vcopy(npoints, velocities[k], 1,
939 BndExp[k][n]->UpdatePhys(), 1);
940 if (m_fields[k]->GetExpType() == MultiRegions::e3DH1D)
941 {
942 BndExp[k][n]->SetWaveSpace(false);
943 }
944 BndExp[k][n]->FwdTransBndConstrained(
945 BndExp[k][n]->GetPhys(), BndExp[k][n]->UpdateCoeffs());
946 }
947 else
948 {
949 BndExp[k][n]->NormVectorIProductWRTBase(
950 acceleration, BndExp[k][n]->UpdateCoeffs());
951 }
952 }
953 }
954}
955
956/**
957 * Set inlet boundary conditions for moving frame of reference
958 */
960{
961 // The inlet conditions for the velocities given in the session xml file
962 // however, those are in the inertial reference coordinate XYZ and
963 // needed to be converted to the moving reference coordinate xyz
964
965 // define arrays to calculate the prescribed velocities and modifed ones
969
971 BndConds(m_spacedim);
973
974 for (int i = 0; i < m_spacedim; ++i)
975 {
976 BndConds[i] = m_fields[m_velocity[i]]->GetBndConditions();
977 BndExp[i] = m_fields[m_velocity[i]]->GetBndCondExpansions();
978 }
979
980 int npoints;
981 Array<OneD, NekDouble> Bphys, Bcoeffs;
982
983 // loop over the boundary regions
984 for (size_t n = 0; n < BndExp[0].size(); ++n)
985 {
986 std::set<int> MRFBnd;
987 for (int k = 0; k < m_spacedim; ++k)
988 {
989 if (BndConds[k][n]->GetBoundaryConditionType() ==
991 (boost::iequals(BndConds[k][n]->GetUserDefined(),
992 "MovingFrameDomainVel")))
993 {
994 MRFBnd.insert(k);
995 }
996 }
997 if (MRFBnd.size() == 0)
998 {
999 continue;
1000 }
1001 npoints = BndExp[0][n]->GetNpoints();
1002 for (size_t k = 0; k < m_velocity.size(); ++k)
1003 {
1004 definedVels[k] = Array<OneD, NekDouble>(npoints, 0.0);
1005 velocities[k] = Array<OneD, NekDouble>(npoints, 0.0);
1006 }
1007 Array<OneD, NekDouble> tmp(npoints, 0.0);
1008 for (size_t k = 0; k < 3; ++k)
1009 {
1010 coords[k] = Array<OneD, NekDouble>(npoints, 0.0);
1011 }
1012 BndExp[0][n]->GetCoords(coords[0], coords[1], coords[2]);
1013
1014 // loop over the velocity fields and compute the boundary
1015 // condition
1016 for (size_t k = 0; k < m_velocity.size(); ++k)
1017 {
1018 LibUtilities::Equation condition =
1019 std::static_pointer_cast<
1021 ->m_dirichletCondition;
1022 // Evaluate
1023 condition.Evaluate(coords[0], coords[1], coords[2], time,
1024 definedVels[k]);
1025 }
1026
1027 // We have all velocity components
1028 // transform them to the moving refernce frame
1029 for (int l = 0; l < m_spacedim; ++l)
1030 {
1031 for (int m = 0; m < m_spacedim; ++m)
1032 {
1033 Vmath::Svtvp(npoints, m_movingFrameProjMat(l, m),
1034 definedVels[m], 1, velocities[l], 1, velocities[l],
1035 1);
1036 }
1037 }
1038
1039 // update the boundary values
1040 for (auto k : MRFBnd)
1041 {
1042 Vmath::Vcopy(npoints, velocities[k], 1, BndExp[k][n]->UpdatePhys(),
1043 1);
1044 if (m_fields[k]->GetExpType() == MultiRegions::e3DH1D)
1045 {
1046 BndExp[k][n]->SetWaveSpace(false);
1047 }
1048 BndExp[k][n]->FwdTransBndConstrained(BndExp[k][n]->GetPhys(),
1049 BndExp[k][n]->UpdateCoeffs());
1050 }
1051 }
1052}
1053
1054/**
1055 * Add an additional forcing term programmatically.
1056 */
1058{
1059 m_forcing.push_back(pForce);
1060}
1061
1062/**
1063 *
1064 */
1066 [[maybe_unused]] const NekDouble SpeedSoundFactor)
1067{
1068 size_t nvel = m_velocity.size();
1069 size_t nelmt = m_fields[0]->GetExpSize();
1070
1071 Array<OneD, NekDouble> stdVelocity(nelmt, 0.0);
1073
1074 if (m_HomogeneousType == eHomogeneous1D) // just do check on 2D info
1075 {
1076 velfields = Array<OneD, Array<OneD, NekDouble>>(2);
1077
1078 for (size_t i = 0; i < 2; ++i)
1079 {
1080 velfields[i] = m_fields[m_velocity[i]]->UpdatePhys();
1081 }
1082 }
1083 else
1084 {
1085 velfields = Array<OneD, Array<OneD, NekDouble>>(nvel);
1086
1087 for (size_t i = 0; i < nvel; ++i)
1088 {
1089 velfields[i] = m_fields[m_velocity[i]]->UpdatePhys();
1090 }
1091 }
1092
1093 stdVelocity = m_extrapolation->GetMaxStdVelocity(velfields);
1094
1095 return stdVelocity;
1096}
1097
1098/**
1099 *
1100 */
1102 const Array<OneD, const Array<OneD, NekDouble>> &physfield,
1104{
1105 if (physfield.size())
1106 {
1107 pressure = physfield[physfield.size() - 1];
1108 }
1109}
1110
1111/**
1112 *
1113 */
1115 const Array<OneD, const Array<OneD, NekDouble>> &physfield,
1116 Array<OneD, NekDouble> &density)
1117{
1118 int nPts = physfield[0].size();
1119 Vmath::Fill(nPts, 1.0, density, 1);
1120}
1121
1122/**
1123 *
1124 */
1126 const Array<OneD, const Array<OneD, NekDouble>> &physfield,
1128{
1129 for (int i = 0; i < m_spacedim; ++i)
1130 {
1131 velocity[i] = physfield[i];
1132 }
1133}
1134
1135/**
1136 * Function to set the moving frame velocities calucated in the forcing
1137 * this gives access to the moving reference forcing to set the velocities
1138 * to be later used in enforcing the boundary condition in IncNavierStokes
1139 * class
1140 */
1142 const Array<OneD, NekDouble> &vFrameVels)
1143{
1144 ASSERTL0(vFrameVels.size() == m_movingFrameVelsxyz.size(),
1145 "Arrays have different dimensions, cannot set moving frame "
1146 "velocities");
1147 Vmath::Vcopy(vFrameVels.size(), vFrameVels, 1, m_movingFrameVelsxyz, 1);
1148}
1149
1151 Array<OneD, NekDouble> &vFrameVels)
1152{
1153 ASSERTL0(vFrameVels.size() == m_movingFrameVelsxyz.size(),
1154 "Arrays have different dimensions, cannot get moving frame "
1155 "velocities");
1156 size_t size = m_movingFrameVelsxyz.size();
1157 Vmath::Vcopy(size, m_movingFrameVelsxyz, 1, vFrameVels, 1);
1158}
1159
1160/**
1161 * Function to set the rotation matrix computed in the forcing
1162 * this gives access to the moving reference forcing to set the Projection
1163 * matrix to be used later in IncNavierStokes calss for enforcing the
1164 * boundary conditions
1165 */
1167 const bnu::matrix<NekDouble> &vProjMat)
1168{
1169 ASSERTL0(vProjMat.size1() == m_movingFrameProjMat.size1(),
1170 "Matrices have different numbers of rows, cannot Set the "
1171 "moving frame projection matrix");
1172 ASSERTL0(vProjMat.size2() == m_movingFrameProjMat.size2(),
1173 "Matrices have different numbers of columns, cannot Set the "
1174 "moving frame projection matrix");
1175 for (size_t i = 0; i < vProjMat.size1(); ++i)
1176 {
1177 for (size_t j = 0; j < vProjMat.size2(); ++j)
1178 {
1179 m_movingFrameProjMat(i, j) = vProjMat(i, j);
1180 }
1181 }
1182}
1183
1185 bnu::matrix<NekDouble> &vProjMat)
1186{
1187 ASSERTL0(vProjMat.size1() == m_movingFrameProjMat.size1(),
1188 "Matrices have different numbers of rows, cannot Get the "
1189 "moving frame projection matrix");
1190 ASSERTL0(vProjMat.size2() == m_movingFrameProjMat.size2(),
1191 "Matrices have different numbers of columns, cannot Get the "
1192 "moving frame projection matrix");
1193
1194 for (size_t i = 0; i < vProjMat.size1(); ++i)
1195 {
1196 for (size_t j = 0; j < vProjMat.size2(); ++j)
1197 {
1198 vProjMat(i, j) = m_movingFrameProjMat(i, j);
1199 }
1200 }
1201}
1202
1203/**
1204 * Function to set the angles between the moving frame of reference and
1205 * stationary inertial reference frame
1206 **/
1208 const Array<OneD, NekDouble> &vFrameDisp)
1209{
1210 ASSERTL0(
1211 vFrameDisp.size() == m_movingFrameData.size(),
1212 "Arrays have different size, cannot set moving frame displacement");
1213 for (size_t i = 0; i < vFrameDisp.size(); ++i)
1214 {
1215 m_movingFrameData[i] = vFrameDisp[i];
1216 }
1217}
1218
1219/**
1220 * Function to get the angles between the moving frame of reference and
1221 * stationary inertial reference frame
1222 **/
1224{
1225 ASSERTL0(
1226 vFrameDisp.size() == m_movingFrameData.size(),
1227 "Arrays have different size, cannot get moving frame displacement");
1228 for (size_t i = 0; i < m_movingFrameData.size(); ++i)
1229 {
1230 vFrameDisp[i] = m_movingFrameData[i];
1231 }
1232}
1233
1235{
1236 Vmath::Vcopy(6, forces, 1, m_aeroForces, 1);
1237}
1238
1240{
1241 Vmath::Vcopy(6, m_aeroForces, 1, forces, 1);
1242}
1243
1244/**
1245 * Function to check the type of forcing
1246 **/
1247bool IncNavierStokes::DefinedForcing(const std::string &sForce)
1248{
1249 vector<std::string> vForceList;
1250 bool hasForce{false};
1251
1252 if (!m_session->DefinesElement("Nektar/Forcing"))
1253 {
1254 return hasForce;
1255 }
1256
1257 TiXmlElement *vForcing = m_session->GetElement("Nektar/Forcing");
1258 if (vForcing)
1259 {
1260 TiXmlElement *vForce = vForcing->FirstChildElement("FORCE");
1261 while (vForce)
1262 {
1263 string vType = vForce->Attribute("TYPE");
1264
1265 vForceList.push_back(vType);
1266 vForce = vForce->NextSiblingElement("FORCE");
1267 }
1268 }
1269
1270 for (auto &f : vForceList)
1271 {
1272 if (boost::iequals(f, sForce))
1273 {
1274 hasForce = true;
1275 }
1276 }
1277
1278 return hasForce;
1279}
1280
1281/**
1282 * Perform the extrapolation.
1283 */
1285{
1286 m_extrapolation->SubStepSaveFields(step);
1287 m_extrapolation->SubStepAdvance(step, m_time);
1289 return false;
1290}
1291
1292} // 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
Array< OneD, Array< OneD, int > > m_fieldsBCToTraceID
Mapping from BCs to Elmt Edge IDs.
Array< OneD, NekDouble > m_pivotPoint
Array< OneD, NekDouble > v_GetMaxStdVelocity(const NekDouble SpeedSoundFactor) override
std::map< int, std::map< int, WomersleyParamsSharedPtr > > m_womersleyParams
Womersley parameters if required.
void v_SetAeroForce(Array< OneD, NekDouble > forces) override
virtual int v_GetForceDimension()=0
void SetWomersleyBoundary(const int fldid, const int bndid)
Set Womersley Profile if specified.
void v_GetMovingFrameVelocities(Array< OneD, NekDouble > &vFrameVels) override
void v_GetAeroForce(Array< OneD, NekDouble > forces) override
void SetZeroNormalVelocity()
Set Normal Velocity Component to Zero.
void v_GetMovingFrameDisp(Array< OneD, NekDouble > &vFrameDisp) override
MultiRegions::ExpListSharedPtr v_GetPressure() override
Array< OneD, NekDouble > m_aeroForces
void SetBoundaryConditions(NekDouble time)
time dependent boundary conditions updating
void SetMRFDomainVelBCs(const NekDouble &time)
NekDouble m_kinvis
Kinematic viscosity.
void v_GetDensity(const Array< OneD, const Array< OneD, NekDouble > > &physfield, Array< OneD, NekDouble > &density) override
void SetRadiationBoundaryForcing(int fieldid)
Set Radiation forcing term.
Array< OneD, Array< OneD, NekDouble > > m_fieldsRadiationFactor
RHS Factor for Radiation Condition.
bool DefinedForcing(const std::string &sForce)
void SetMRFWallBCs(const NekDouble &time)
void v_SetMovingFrameVelocities(const Array< OneD, NekDouble > &vFrameVels) override
bool v_PreIntegrate(int step) override
void SetUpWomersley(const int fldid, const int bndid, std::string womstr)
Set Up Womersley details.
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);
static std::string eqTypeLookupIds[]
void v_GetMovingFrameProjectionMat(bnu::matrix< NekDouble > &vProjMat) override
Array< OneD, Array< OneD, int > > m_fieldsBCToElmtID
Mapping from BCs to Elmt IDs.
void v_GetVelocity(const Array< OneD, const Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, NekDouble > > &velocity) override
EquationType m_equationType
equation type;
void v_SetMovingFrameProjectionMat(const bnu::matrix< NekDouble > &vProjMat) override
int m_nConvectiveFields
Number of fields to be convected;.
void AddForcing(const SolverUtils::ForcingSharedPtr &pForce)
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
Forcing terms.
void v_SetMovingFrameDisp(const Array< OneD, NekDouble > &vFrameDisp) override
void EvaluateAdvectionTerms(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
void SetMovingReferenceFrameBCs(const NekDouble &time)
Set the moving reference frame boundary conditions.
IncNavierStokes(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Constructor.
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:143
static std::string RegisterEnumValue(std::string pEnum, std::string pString, int pEnumValue)
Registers an enumeration value.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
static bool GenerateVector(const std::string &str, std::vector< T > &out)
Takes a comma-separated string and converts it to entries in a vector.
Definition: ParseUtils.cpp:130
A base class for PDEs which include an advection component.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
SOLVER_UTILS_EXPORT void v_InitObject(bool DeclareField=true) override
Initialisation object for EquationSystem.
int m_spacedim
Spatial dimension (>= expansion dim).
boost::numeric::ublas::matrix< NekDouble > m_movingFrameProjMat
Projection matrix for transformation between inertial and moving.
NekDouble m_timestep
Time step size.
NekDouble m_time
Current time of simulation.
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
Array< OneD, NekDouble > m_movingFrameVelsxyz
Moving frame of reference velocities (u, v, w, omega_x, omega_y, omega_z, a_x, a_y,...
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
enum HomogeneousType m_HomogeneousType
SOLVER_UTILS_EXPORT int GetPhys_Offset(int n)
LibUtilities::FieldMetaDataMap m_fieldMetaDataMap
Map to identify relevant solver info to dump in output fields.
SpatialDomains::BoundaryConditionsSharedPtr m_boundaryConditions
Pointer to boundary conditions object.
Array< OneD, NekDouble > m_movingFrameData
Moving frame of reference angles with respect to the.
static SOLVER_UTILS_EXPORT std::vector< ForcingSharedPtr > Load(const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const unsigned int &pNumForcingFields=0)
Definition: Forcing.cpp:118
Base class for unsteady solvers.
static NekDouble rad(NekDouble x, NekDouble y)
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:66
const std::vector< NekDouble > velocity
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
AdvectionFactory & GetAdvectionFactory()
Gets the factory for initialising advection objects.
Definition: Advection.cpp:43
SOLVER_UTILS_EXPORT typedef std::shared_ptr< Forcing > ForcingSharedPtr
A shared pointer to an EquationSystem object.
Definition: Forcing.h:53
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:174
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
std::vector< double > z(NPUPPER)
std::complex< double > NekComplexDouble
@ eSteadyNavierStokes
@ eUnsteadyStokes
@ eUnsteadyNavierStokes
@ eSteadyLinearisedNS
@ eUnsteadyLinearisedNS
@ eEquationTypeSize
std::shared_ptr< WomersleyParams > WomersleyParamsSharedPtr
const std::string kEquationTypeStr[]
double NekDouble
std::complex< Nektar::NekDouble > ImagBesselComp(int n, std::complex< Nektar::NekDouble > y)
Calcualte the bessel function of the first kind with complex double input y. Taken from Numerical Rec...
Definition: Polylib.cpp:1559
void Svtsvtp(int n, const T alpha, const T *x, int incx, const T beta, const T *y, int incy, T *z, int incz)
Svtsvtp (scalar times vector plus scalar times vector):
Definition: Vmath.hpp:473
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.hpp:72
void Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Svtvp (scalar times vector plus vector): z = alpha*x + y.
Definition: Vmath.hpp:396
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.hpp:292
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 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 Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.hpp:54
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add vector y = alpha + x.
Definition: Vmath.hpp:194
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.hpp:825
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294