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 
58 using namespace std;
59 
60 namespace Nektar
61 {
62 
63 std::string IncNavierStokes::eqTypeLookupIds[6] = {
64  LibUtilities::SessionReader::RegisterEnumValue("EqType", "SteadyStokes",
66  LibUtilities::SessionReader::RegisterEnumValue("EqType", "SteadyOseen",
67  eSteadyOseen),
68  LibUtilities::SessionReader::RegisterEnumValue(
69  "EqType", "SteadyNavierStokes", eSteadyNavierStokes),
70  LibUtilities::SessionReader::RegisterEnumValue(
71  "EqType", "SteadyLinearisedNS", eSteadyLinearisedNS),
72  LibUtilities::SessionReader::RegisterEnumValue(
73  "EqType", "UnsteadyNavierStokes", eUnsteadyNavierStokes),
74  LibUtilities::SessionReader::RegisterEnumValue("EqType", "UnsteadyStokes",
76 
77 /**
78  * Constructor. Creates ...
79  *
80  * \param
81  * \param
82  */
83 IncNavierStokes::IncNavierStokes(
86  : UnsteadySystem(pSession, pGraph), AdvectionSystem(pSession, pGraph),
87  m_SmoothAdvection(false)
88 {
89 }
90 
91 void IncNavierStokes::v_InitObject(bool DeclareField)
92 {
93  AdvectionSystem::v_InitObject(DeclareField);
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:
137  case eSteadyLinearisedNS:
138  vConvectiveType = "NoAdvection";
139  break;
141  case eSteadyNavierStokes:
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  {
173  }
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 
246  LibUtilities::Equation coeff =
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  // Check if we have moving reference frame boundary conditions,if so, all
286  // velocity vectors at those boundaries should be Drichlet and have a same
287  // tag loop over the boundaries
288  for (size_t n = 0; n < m_fields[0]->GetBndConditions().size(); ++n)
289  {
290  // loop over the velocities
291  for (size_t i = 0; i < m_velocity.size(); ++i)
292  {
293  if (boost::iequals(
294  m_fields[i]->GetBndConditions()[n]->GetUserDefined(),
295  "MovingFrameWall"))
296  {
297  // all velocities must have the same userdefined tag and all
298  // must be Dirichlet
299  for (size_t j = 0; j < m_velocity.size(); ++j)
300  {
301  ASSERTL0(m_fields[j]
302  ->GetBndConditions()[n]
303  ->GetBoundaryConditionType() ==
305  "All velocities with userdefined tag: "
306  "\"MovingFrameWall\" must be Dirichlet boundary "
307  "condition");
308  ASSERTL0(boost::iequals(m_fields[j]
309  ->GetBndConditions()[n]
310  ->GetUserDefined(),
311  "MovingFrameWall"),
312  "If any of the velocity components at a "
313  "boundary is defined as \"MovingFrameWall\", "
314  "the rest of velocity components are also "
315  "must be defined as \"MovingFrameWall\" ");
316  }
317  }
318 
319  if (boost::iequals(
320  m_fields[i]->GetBndConditions()[n]->GetUserDefined(),
321  "MovingFrameDomainVel"))
322  {
323  // all velocities must have the same userdefined tag and all
324  // must be Dirichlet
325  for (size_t j = 0; j < m_velocity.size(); ++j)
326  {
327  ASSERTL0(
328  m_fields[j]
329  ->GetBndConditions()[n]
330  ->GetBoundaryConditionType() ==
332  "All velocities with userdefined tag: "
333  "\"MovingFrameDomainVel\" must be Dirichlet boundary "
334  "condition");
335  ASSERTL0(boost::iequals(m_fields[j]
336  ->GetBndConditions()[n]
337  ->GetUserDefined(),
338  "MovingFrameDomainVel"),
339  "If any of the velocity components at a "
340  "boundary is defined as \"MovingFrameDomainVel\", "
341  "the rest of velocity components are also "
342  "must be defined as \"MovingFrameDomainVel\" ");
343  }
344  }
345  }
346  }
347 
348  // Set up Field Meta Data for output files
349  m_fieldMetaDataMap["Kinvis"] = boost::lexical_cast<std::string>(m_kinvis);
350  m_fieldMetaDataMap["TimeStep"] =
351  boost::lexical_cast<std::string>(m_timestep);
352 
353  // Check to see if the metadata for moving reference frame is defined
354  if (DefinedForcing("MovingReferenceFrame"))
355  {
357  {
358  std::vector<std::string> vSuffix = {"_x", "_y", "_z"};
359  for (size_t i = 0; i < 3; ++i)
360  {
361  NekDouble dTheta{0};
362  std::string sTheta = "Theta" + vSuffix[i];
363  auto it = m_fieldMetaDataMap.find(sTheta);
364  if (it != m_fieldMetaDataMap.end())
365  {
366  dTheta = boost::lexical_cast<NekDouble>(it->second);
367  m_movingFrameTheta[i] = dTheta;
368  }
369  else
370  {
371  m_fieldMetaDataMap[sTheta] =
372  boost::lexical_cast<std::string>(m_movingFrameTheta[i]);
373  }
374  }
375  }
376  else
377  {
378  std::vector<std::string> vSuffix = {"_x", "_y", "_z"};
379  for (size_t i = 0; i < 3; ++i)
380  {
381  std::string sTheta = "Theta" + vSuffix[i];
382  m_fieldMetaDataMap[sTheta] =
383  boost::lexical_cast<std::string>(m_movingFrameTheta[i]);
384  }
385  }
386  }
387 }
388 
389 /**
390  * Destructor
391  */
393 {
394 }
395 
396 /**
397  * Evaluation -N(V) for all fields except pressure using m_velocity
398  */
400  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
401  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
402 {
403  size_t VelDim = m_velocity.size();
404  Array<OneD, Array<OneD, NekDouble>> velocity(VelDim);
405 
406  size_t npoints = m_fields[0]->GetNpoints();
407  for (size_t i = 0; i < VelDim; ++i)
408  {
409  velocity[i] = Array<OneD, NekDouble>(npoints);
410  Vmath::Vcopy(npoints, inarray[m_velocity[i]], 1, velocity[i], 1);
411  }
412  for (auto &x : m_forcing)
413  {
414  x->PreApply(m_fields, velocity, velocity, time);
415  }
416 
417  m_advObject->Advect(m_nConvectiveFields, m_fields, velocity, inarray,
418  outarray, time);
419 }
420 
421 /**
422  * Time dependent boundary conditions updating
423  */
425 {
426  size_t i, n;
427  std::string varName;
428  size_t nvariables = m_fields.size();
429 
430  for (i = 0; i < nvariables; ++i)
431  {
432  for (n = 0; n < m_fields[i]->GetBndConditions().size(); ++n)
433  {
434  if (m_fields[i]->GetBndConditions()[n]->IsTimeDependent())
435  {
436  varName = m_session->GetVariable(i);
437  m_fields[i]->EvaluateBoundaryConditions(time, varName);
438  }
439  else if (boost::istarts_with(
440  m_fields[i]->GetBndConditions()[n]->GetUserDefined(),
441  "Womersley"))
442  {
443  SetWomersleyBoundary(i, n);
444  }
445  }
446 
447  // Set Radiation conditions if required
449  }
450 
451  // Enforcing the boundary conditions (Inlet and wall) for the
452  // Moving reference frame
455 }
456 
457 /**
458  * Probably should be pushed back into ContField?
459  */
461 {
462  size_t i, n;
463 
466 
467  BndConds = m_fields[fieldid]->GetBndConditions();
468  BndExp = m_fields[fieldid]->GetBndCondExpansions();
469 
472 
473  size_t cnt;
474  size_t elmtid, nq, offset, boundary;
475  Array<OneD, NekDouble> Bvals, U;
476  size_t cnt1 = 0;
477 
478  for (cnt = n = 0; n < BndConds.size(); ++n)
479  {
480  std::string type = BndConds[n]->GetUserDefined();
481 
482  if ((BndConds[n]->GetBoundaryConditionType() ==
484  (boost::iequals(type, "Radiation")))
485  {
486  size_t nExp = BndExp[n]->GetExpSize();
487  for (i = 0; i < nExp; ++i, cnt++)
488  {
489  elmtid = m_fieldsBCToElmtID[m_velocity[fieldid]][cnt];
490  elmt = m_fields[fieldid]->GetExp(elmtid);
491  offset = m_fields[fieldid]->GetPhys_Offset(elmtid);
492 
493  U = m_fields[fieldid]->UpdatePhys() + offset;
494  Bc = BndExp[n]->GetExp(i);
495 
496  boundary = m_fieldsBCToTraceID[fieldid][cnt];
497 
498  // Get edge values and put into ubc
499  nq = Bc->GetTotPoints();
500  Array<OneD, NekDouble> ubc(nq);
501  elmt->GetTracePhysVals(boundary, Bc, U, ubc);
502 
503  Vmath::Vmul(nq,
505  [fieldid][cnt1 + BndExp[n]->GetPhys_Offset(i)],
506  1, &ubc[0], 1, &ubc[0], 1);
507 
508  Bvals =
509  BndExp[n]->UpdateCoeffs() + BndExp[n]->GetCoeff_Offset(i);
510 
511  Bc->IProductWRTBase(ubc, Bvals);
512  }
513  cnt1 += BndExp[n]->GetTotPoints();
514  }
515  else
516  {
517  cnt += BndExp[n]->GetExpSize();
518  }
519  }
520 }
521 
523 {
524  // use static trip since cannot use UserDefinedTag for zero
525  // velocity and have time dependent conditions
526  static bool Setup = false;
527 
528  if (Setup == true)
529  {
530  return;
531  }
532  Setup = true;
533 
534  size_t i, n;
535 
537  BndConds(m_spacedim);
539 
540  for (int i = 0; i < m_spacedim; ++i)
541  {
542  BndConds[i] = m_fields[m_velocity[i]]->GetBndConditions();
543  BndExp[i] = m_fields[m_velocity[i]]->GetBndCondExpansions();
544  }
545 
547 
548  size_t cnt;
549  size_t elmtid, nq, boundary;
550 
552  Array<OneD, NekDouble> Bphys, Bcoeffs;
553 
554  size_t fldid = m_velocity[0];
555 
556  for (cnt = n = 0; n < BndConds[0].size(); ++n)
557  {
558  if ((BndConds[0][n]->GetBoundaryConditionType() ==
560  (boost::iequals(BndConds[0][n]->GetUserDefined(),
561  "ZeroNormalComponent")))
562  {
563  size_t nExp = BndExp[0][n]->GetExpSize();
564  for (i = 0; i < nExp; ++i, cnt++)
565  {
566  elmtid = m_fieldsBCToElmtID[fldid][cnt];
567  elmt = m_fields[0]->GetExp(elmtid);
568  boundary = m_fieldsBCToTraceID[fldid][cnt];
569 
570  normals = elmt->GetTraceNormal(boundary);
571 
572  nq = BndExp[0][n]->GetExp(i)->GetTotPoints();
573  Array<OneD, NekDouble> normvel(nq, 0.0);
574 
575  for (int k = 0; k < m_spacedim; ++k)
576  {
577  Bphys = BndExp[k][n]->UpdatePhys() +
578  BndExp[k][n]->GetPhys_Offset(i);
579  Bc = BndExp[k][n]->GetExp(i);
580  Vmath::Vvtvp(nq, normals[k], 1, Bphys, 1, normvel, 1,
581  normvel, 1);
582  }
583 
584  // negate normvel for next step
585  Vmath::Neg(nq, normvel, 1);
586 
587  for (int k = 0; k < m_spacedim; ++k)
588  {
589  Bphys = BndExp[k][n]->UpdatePhys() +
590  BndExp[k][n]->GetPhys_Offset(i);
591  Bcoeffs = BndExp[k][n]->UpdateCoeffs() +
592  BndExp[k][n]->GetCoeff_Offset(i);
593  Bc = BndExp[k][n]->GetExp(i);
594  Vmath::Vvtvp(nq, normvel, 1, normals[k], 1, Bphys, 1, Bphys,
595  1);
596  Bc->FwdTransBndConstrained(Bphys, Bcoeffs);
597  }
598  }
599  }
600  else
601  {
602  cnt += BndExp[0][n]->GetExpSize();
603  }
604  }
605 }
606 
607 /**
608  * Womersley boundary condition defintion
609  */
610 void IncNavierStokes::SetWomersleyBoundary(const int fldid, const int bndid)
611 {
612  ASSERTL1(m_womersleyParams.count(bndid) == 1,
613  "Womersley parameters for this boundary have not been set up");
614 
615  WomersleyParamsSharedPtr WomParam = m_womersleyParams[fldid][bndid];
616  NekComplexDouble zvel;
617  size_t i, j, k;
618 
619  size_t M_coeffs = WomParam->m_wom_vel.size();
620 
621  NekDouble T = WomParam->m_period;
622  NekDouble axis_normal = WomParam->m_axisnormal[fldid];
623 
624  // Womersley Number
625  NekComplexDouble omega_c(2.0 * M_PI / T, 0.0);
626  NekComplexDouble k_c(0.0, 0.0);
627  NekComplexDouble m_time_c(m_time, 0.0);
628  NekComplexDouble zi(0.0, 1.0);
629  NekComplexDouble i_pow_3q2(-1.0 / sqrt(2.0), 1.0 / sqrt(2.0));
630 
632  BndCondExp = m_fields[fldid]->GetBndCondExpansions()[bndid];
633 
635  size_t cnt = 0;
636  size_t nfq;
638  size_t exp_npts = BndCondExp->GetExpSize();
639  Array<OneD, NekDouble> wbc(exp_npts, 0.0);
640 
641  Array<OneD, NekComplexDouble> zt(M_coeffs);
642 
643  // preallocate the exponent
644  for (k = 1; k < M_coeffs; k++)
645  {
646  k_c = NekComplexDouble((NekDouble)k, 0.0);
647  zt[k] = std::exp(zi * omega_c * k_c * m_time_c);
648  }
649 
650  // Loop over each element in an expansion
651  for (i = 0; i < exp_npts; ++i, cnt++)
652  {
653  // Get Boundary and trace expansion
654  bc = BndCondExp->GetExp(i);
655  nfq = bc->GetTotPoints();
656  Array<OneD, NekDouble> wbc(nfq, 0.0);
657 
658  // Compute womersley solution
659  for (j = 0; j < nfq; j++)
660  {
661  wbc[j] = WomParam->m_poiseuille[i][j];
662  for (k = 1; k < M_coeffs; k++)
663  {
664  zvel = WomParam->m_zvel[i][j][k] * zt[k];
665  wbc[j] = wbc[j] + zvel.real();
666  }
667  }
668 
669  // Multiply w by normal to get u,v,w component of velocity
670  Vmath::Smul(nfq, axis_normal, wbc, 1, wbc, 1);
671  // get the offset
672  Bvals = BndCondExp->UpdateCoeffs() + BndCondExp->GetCoeff_Offset(i);
673 
674  // Push back to Coeff space
675  bc->FwdTrans(wbc, Bvals);
676  }
677 }
678 
679 void IncNavierStokes::SetUpWomersley(const int fldid, const int bndid,
680  std::string womStr)
681 {
682  std::string::size_type indxBeg = womStr.find_first_of(':') + 1;
683  string filename = womStr.substr(indxBeg, string::npos);
684 
685  TiXmlDocument doc(filename);
686 
687  bool loadOkay = doc.LoadFile();
688  ASSERTL0(loadOkay,
689  (std::string("Failed to load file: ") + filename).c_str());
690 
691  TiXmlHandle docHandle(&doc);
692 
693  int err; /// Error value returned by TinyXML.
694 
695  TiXmlElement *nektar = doc.FirstChildElement("NEKTAR");
696  ASSERTL0(nektar, "Unable to find NEKTAR tag in file.");
697 
698  TiXmlElement *wombc = nektar->FirstChildElement("WOMERSLEYBC");
699  ASSERTL0(wombc, "Unable to find WOMERSLEYBC tag in file.");
700 
701  // read womersley parameters
702  TiXmlElement *womparam = wombc->FirstChildElement("WOMPARAMS");
703  ASSERTL0(womparam, "Unable to find WOMPARAMS tag in file.");
704 
705  // Input coefficients
706  TiXmlElement *params = womparam->FirstChildElement("W");
707  map<std::string, std::string> Wparams;
708 
709  // read parameter list
710  while (params)
711  {
712 
713  std::string propstr;
714  propstr = params->Attribute("PROPERTY");
715 
716  ASSERTL0(!propstr.empty(),
717  "Failed to read PROPERTY value Womersley BC Parameter");
718 
719  std::string valstr;
720  valstr = params->Attribute("VALUE");
721 
722  ASSERTL0(!valstr.empty(),
723  "Failed to read VALUE value Womersley BC Parameter");
724 
725  std::transform(propstr.begin(), propstr.end(), propstr.begin(),
726  ::toupper);
727  Wparams[propstr] = valstr;
728 
729  params = params->NextSiblingElement("W");
730  }
731  bool parseGood;
732 
733  // Read parameters
734 
735  ASSERTL0(
736  Wparams.count("RADIUS") == 1,
737  "Failed to find Radius parameter in Womersley boundary conditions");
738  std::vector<NekDouble> rad;
739  ParseUtils::GenerateVector(Wparams["RADIUS"], rad);
740  m_womersleyParams[fldid][bndid]->m_radius = rad[0];
741 
742  ASSERTL0(
743  Wparams.count("PERIOD") == 1,
744  "Failed to find period parameter in Womersley boundary conditions");
745  std::vector<NekDouble> period;
746  parseGood = ParseUtils::GenerateVector(Wparams["PERIOD"], period);
747  m_womersleyParams[fldid][bndid]->m_period = period[0];
748 
749  ASSERTL0(
750  Wparams.count("AXISNORMAL") == 1,
751  "Failed to find axisnormal parameter in Womersley boundary conditions");
752  std::vector<NekDouble> anorm;
753  parseGood = ParseUtils::GenerateVector(Wparams["AXISNORMAL"], anorm);
754  m_womersleyParams[fldid][bndid]->m_axisnormal[0] = anorm[0];
755  m_womersleyParams[fldid][bndid]->m_axisnormal[1] = anorm[1];
756  m_womersleyParams[fldid][bndid]->m_axisnormal[2] = anorm[2];
757 
758  ASSERTL0(
759  Wparams.count("AXISPOINT") == 1,
760  "Failed to find axispoint parameter in Womersley boundary conditions");
761  std::vector<NekDouble> apt;
762  parseGood = ParseUtils::GenerateVector(Wparams["AXISPOINT"], apt);
763  m_womersleyParams[fldid][bndid]->m_axispoint[0] = apt[0];
764  m_womersleyParams[fldid][bndid]->m_axispoint[1] = apt[1];
765  m_womersleyParams[fldid][bndid]->m_axispoint[2] = apt[2];
766 
767  // Read Temporal Fourier Coefficients.
768 
769  // Find the FourierCoeff tag
770  TiXmlElement *coeff = wombc->FirstChildElement("FOURIERCOEFFS");
771 
772  // Input coefficients
773  TiXmlElement *fval = coeff->FirstChildElement("F");
774 
775  int indx;
776  int nextFourierCoeff = -1;
777 
778  while (fval)
779  {
780  nextFourierCoeff++;
781 
782  TiXmlAttribute *fvalAttr = fval->FirstAttribute();
783  std::string attrName(fvalAttr->Name());
784 
785  ASSERTL0(attrName == "ID",
786  (std::string("Unknown attribute name: ") + attrName).c_str());
787 
788  err = fvalAttr->QueryIntValue(&indx);
789  ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID.");
790 
791  std::string coeffStr = fval->FirstChild()->ToText()->ValueStr();
792  vector<NekDouble> coeffvals;
793 
794  parseGood = ParseUtils::GenerateVector(coeffStr, coeffvals);
795  ASSERTL0(
796  parseGood,
797  (std::string("Problem reading value of fourier coefficient, ID=") +
798  boost::lexical_cast<string>(indx))
799  .c_str());
800  ASSERTL1(
801  coeffvals.size() == 2,
802  (std::string(
803  "Have not read two entries of Fourier coefficicent from ID=" +
804  boost::lexical_cast<string>(indx))
805  .c_str()));
806 
807  m_womersleyParams[fldid][bndid]->m_wom_vel.push_back(
808  NekComplexDouble(coeffvals[0], coeffvals[1]));
809 
810  fval = fval->NextSiblingElement("F");
811  }
812 
813  // starting point of precalculation
814  size_t i, j, k;
815  // M fourier coefficients
816  size_t M_coeffs = m_womersleyParams[fldid][bndid]->m_wom_vel.size();
817  NekDouble R = m_womersleyParams[fldid][bndid]->m_radius;
818  NekDouble T = m_womersleyParams[fldid][bndid]->m_period;
819  Array<OneD, NekDouble> x0 = m_womersleyParams[fldid][bndid]->m_axispoint;
820 
821  NekComplexDouble rqR;
822  // Womersley Number
823  NekComplexDouble omega_c(2.0 * M_PI / T, 0.0);
824  NekComplexDouble alpha_c(R * sqrt(omega_c.real() / m_kinvis), 0.0);
825  NekComplexDouble z1(1.0, 0.0);
826  NekComplexDouble i_pow_3q2(-1.0 / sqrt(2.0), 1.0 / sqrt(2.0));
827 
829  BndCondExp = m_fields[fldid]->GetBndCondExpansions()[bndid];
830 
832  size_t cnt = 0;
833  size_t nfq;
835 
836  size_t exp_npts = BndCondExp->GetExpSize();
837  Array<OneD, NekDouble> wbc(exp_npts, 0.0);
838 
839  // allocate time indepedent variables
840  m_womersleyParams[fldid][bndid]->m_poiseuille =
842  m_womersleyParams[fldid][bndid]->m_zvel =
844  // could use M_coeffs - 1 but need to avoid complicating things
845  Array<OneD, NekComplexDouble> zJ0(M_coeffs);
846  Array<OneD, NekComplexDouble> lamda_n(M_coeffs);
847  Array<OneD, NekComplexDouble> k_c(M_coeffs);
848  NekComplexDouble zJ0r;
849 
850  for (k = 1; k < M_coeffs; k++)
851  {
852  k_c[k] = NekComplexDouble((NekDouble)k, 0.0);
853  lamda_n[k] = i_pow_3q2 * alpha_c * sqrt(k_c[k]);
854  zJ0[k] = Polylib::ImagBesselComp(0, lamda_n[k]);
855  }
856 
857  // Loop over each element in an expansion
858  for (i = 0; i < exp_npts; ++i, cnt++)
859  {
860  // Get Boundary and trace expansion
861  bc = BndCondExp->GetExp(i);
862  nfq = bc->GetTotPoints();
863 
864  Array<OneD, NekDouble> x(nfq, 0.0);
865  Array<OneD, NekDouble> y(nfq, 0.0);
866  Array<OneD, NekDouble> z(nfq, 0.0);
867  bc->GetCoords(x, y, z);
868 
869  m_womersleyParams[fldid][bndid]->m_poiseuille[i] =
871  m_womersleyParams[fldid][bndid]->m_zvel[i] =
873 
874  // Compute coefficients
875  for (j = 0; j < nfq; j++)
876  {
877  rqR = NekComplexDouble(sqrt((x[j] - x0[0]) * (x[j] - x0[0]) +
878  (y[j] - x0[1]) * (y[j] - x0[1]) +
879  (z[j] - x0[2]) * (z[j] - x0[2])) /
880  R,
881  0.0);
882 
883  // Compute Poiseulle Flow
884  m_womersleyParams[fldid][bndid]->m_poiseuille[i][j] =
885  m_womersleyParams[fldid][bndid]->m_wom_vel[0].real() *
886  (1. - rqR.real() * rqR.real());
887 
888  m_womersleyParams[fldid][bndid]->m_zvel[i][j] =
890 
891  // compute the velocity information
892  for (k = 1; k < M_coeffs; k++)
893  {
894  zJ0r = Polylib::ImagBesselComp(0, rqR * lamda_n[k]);
895  m_womersleyParams[fldid][bndid]->m_zvel[i][j][k] =
896  m_womersleyParams[fldid][bndid]->m_wom_vel[k] *
897  (z1 - (zJ0r / zJ0[k]));
898  }
899  }
900  }
901 }
902 
903 /**
904  * Set boundary conditions for moving frame of reference
905  */
907 {
908  SetMRFWallBCs(time);
909  SetMRFDomainVelBCs(time);
910 }
911 
912 /**
913  * Set Wall boundary conditions for moving frame of reference
914  */
916 {
917  boost::ignore_unused(time);
918 
919  // for the wall we need to calculate:
920  // [V_wall]_xyz = [V_frame]_xyz + [Omega X r]_xyz
921  // Note all vectors must be in moving frame coordinates xyz
922  // not in inertial frame XYZ
923 
925  BndConds(m_spacedim);
927 
928  for (int i = 0; i < m_spacedim; ++i)
929  {
930  BndConds[i] = m_fields[m_velocity[i]]->GetBndConditions();
931  BndExp[i] = m_fields[m_velocity[i]]->GetBndCondExpansions();
932  }
933 
934  int npoints;
935  Array<OneD, NekDouble> Bphys, Bcoeffs;
936 
937  // loop over the boundary regions
938  for (size_t n = 0; n < BndExp[0].size(); ++n)
939  {
940  if (BndConds[0][n]->GetBoundaryConditionType() ==
942  (boost::iequals(BndConds[0][n]->GetUserDefined(),
943  "MovingFrameWall")))
944  {
945  npoints = BndExp[0][n]->GetNpoints();
946  //
947  // define arrays to calculate the prescribed velocities and modifed
948  // ones
952  for (size_t k = 0; k < m_velocity.size(); ++k)
953  {
954  velocities[k] = Array<OneD, NekDouble>(npoints, 0.0);
955  unitArray[k] = Array<OneD, NekDouble>(npoints, 1.0);
956  }
957  Array<OneD, NekDouble> tmp(npoints, 0.0);
958  for (size_t k = 0; k < 3; ++k)
959  {
960  coords[k] = Array<OneD, NekDouble>(npoints, 0.0);
961  }
962  BndExp[0][n]->GetCoords(coords[0], coords[1], coords[2]);
963 
964  // move the centre to the location of pivot
965  for (int i = 0; i < m_spacedim; ++i)
966  {
967  Vmath::Sadd(npoints, -m_pivotPoint[i], coords[i], 1, coords[i],
968  1);
969  }
970  /////////////////////////////////////
971  // Note that both Omega and the absolute velocities have been
972  // expressed in the moving reference frame unit vectors
973  // therefore the result is in moving ref frame and no furhter
974  // transformaton is required
975  //
976  // compute Omega X r = vx ex + vy ey + vz ez
977  // Note OmegaX : movingFrameVelsxyz[3]
978  // Note OmegaY : movingFrameVelsxyz[4]
979  // Note OmegaZ : movingFrameVelsxyz[5]
980  //
981  // vx = OmegaY*z-OmegaZ*y
982  Vmath::Smul(npoints, -1 * m_movingFrameVelsxyz[5], coords[1], 1,
983  velocities[0], 1);
984  // vy = OmegaZ*x-OmegaX*z
985  Vmath::Smul(npoints, m_movingFrameVelsxyz[5], coords[0], 1,
986  velocities[1], 1);
987  if (m_spacedim == 3)
988  {
989  // add the OmegaY*z to vx
990  Vmath::Svtvp(npoints, m_movingFrameVelsxyz[4], coords[2], 1,
991  velocities[0], 1, velocities[0], 1);
992  // add the -OmegaX*z to vy
993  Vmath::Svtvp(npoints, -1 * m_movingFrameVelsxyz[3], coords[2],
994  1, velocities[1], 1, velocities[1], 1);
995 
996  // vz = OmegaX*y-OmegaY*x
997  Vmath::Svtsvtp(npoints, m_movingFrameVelsxyz[3], coords[1], 1,
998  -1.0 * m_movingFrameVelsxyz[4], coords[0], 1,
999  velocities[2], 1);
1000  }
1001 
1002  // add the translation velocity
1003  for (int k = 0; k < m_spacedim; ++k)
1004  {
1005  Vmath::Sadd(npoints, m_movingFrameVelsxyz[k], velocities[k], 1,
1006  velocities[k], 1);
1007  }
1008 
1009  // update the boundary values
1010  for (int k = 0; k < m_spacedim; ++k)
1011  {
1012  Vmath::Vmul(npoints, unitArray[k], 1, velocities[k], 1,
1013  BndExp[k][n]->UpdatePhys(), 1);
1014  }
1015  // update the coefficients
1016  for (int k = 0; k < m_spacedim; ++k)
1017  {
1018  if (m_fields[k]->GetExpType() == MultiRegions::e3DH1D)
1019  {
1020  BndExp[k][n]->SetWaveSpace(false);
1021  }
1022  BndExp[k][n]->FwdTransBndConstrained(
1023  BndExp[k][n]->GetPhys(), BndExp[k][n]->UpdateCoeffs());
1024  }
1025  }
1026  }
1027 }
1028 
1029 /**
1030  * Set inlet boundary conditions for moving frame of reference
1031  */
1033 {
1034  // The inlet conditions for the velocities given in the session xml file
1035  // however, those are in the inertial reference coordinate XYZ and
1036  // needed to be converted to the moving reference coordinate xyz
1037 
1038  // define arrays to calculate the prescribed velocities and modifed ones
1039  Array<OneD, Array<OneD, NekDouble>> definedVels(m_velocity.size());
1040  Array<OneD, Array<OneD, NekDouble>> velocities(m_velocity.size());
1043 
1045  BndConds(m_spacedim);
1047 
1048  for (int i = 0; i < m_spacedim; ++i)
1049  {
1050  BndConds[i] = m_fields[m_velocity[i]]->GetBndConditions();
1051  BndExp[i] = m_fields[m_velocity[i]]->GetBndCondExpansions();
1052  }
1053 
1054  int npoints;
1055  Array<OneD, NekDouble> Bphys, Bcoeffs;
1056 
1057  // loop over the boundary regions
1058  for (size_t n = 0; n < BndExp[0].size(); ++n)
1059  {
1060  if (BndConds[0][n]->GetBoundaryConditionType() ==
1062  (boost::iequals(BndConds[0][n]->GetUserDefined(),
1063  "MovingFrameDomainVel")))
1064  {
1065  npoints = BndExp[0][n]->GetNpoints();
1066  for (size_t k = 0; k < m_velocity.size(); ++k)
1067  {
1068  definedVels[k] = Array<OneD, NekDouble>(npoints, 0.0);
1069  velocities[k] = Array<OneD, NekDouble>(npoints, 0.0);
1070  unitArray[k] = Array<OneD, NekDouble>(npoints, 1.0);
1071  }
1072  Array<OneD, NekDouble> tmp(npoints, 0.0);
1073  for (size_t k = 0; k < 3; ++k)
1074  {
1075  coords[k] = Array<OneD, NekDouble>(npoints, 0.0);
1076  }
1077  BndExp[0][n]->GetCoords(coords[0], coords[1], coords[2]);
1078 
1079  // loop over the velocity fields and compute the boundary
1080  // condition
1081  for (size_t k = 0; k < m_velocity.size(); ++k)
1082  {
1083  LibUtilities::Equation condition =
1084  std::static_pointer_cast<
1086  BndConds[k][n])
1087  ->m_dirichletCondition;
1088  // Evaluate
1089  condition.Evaluate(coords[0], coords[1], coords[2], time,
1090  definedVels[k]);
1091  }
1092 
1093  // We have all velocity components
1094  // transform them to the moving refernce frame
1095  for (int l = 0; l < m_spacedim; ++l)
1096  {
1097  Array<OneD, NekDouble> tmp0(npoints, 0.0);
1098  Array<OneD, NekDouble> tmp1(npoints, 0.0);
1099  Array<OneD, NekDouble> tmp2(npoints, 0.0);
1100  for (int m = 0; m < m_spacedim; ++m)
1101  {
1102  Vmath::Svtvp(npoints, m_movingFrameProjMat(l, m),
1103  tmp0 = definedVels[m], 1, tmp1 = velocities[l],
1104  1, tmp2 = velocities[l], 1);
1105  }
1106  }
1107 
1108  // update the boundary values
1109  for (int k = 0; k < m_spacedim; ++k)
1110  {
1111  Vmath::Vmul(npoints, unitArray[k], 1, velocities[k], 1,
1112  BndExp[k][n]->UpdatePhys(), 1);
1113  }
1114  // update the coefficients
1115  for (int k = 0; k < m_spacedim; ++k)
1116  {
1117  if (m_fields[k]->GetExpType() == MultiRegions::e3DH1D)
1118  {
1119  BndExp[k][n]->SetWaveSpace(false);
1120  }
1121  BndExp[k][n]->FwdTransBndConstrained(
1122  BndExp[k][n]->GetPhys(), BndExp[k][n]->UpdateCoeffs());
1123  }
1124  }
1125  }
1126 }
1127 
1128 /**
1129  * Add an additional forcing term programmatically.
1130  */
1132 {
1133  m_forcing.push_back(pForce);
1134 }
1135 
1136 /**
1137  *
1138  */
1140  const NekDouble SpeedSoundFactor)
1141 {
1142  boost::ignore_unused(SpeedSoundFactor);
1143  size_t nvel = m_velocity.size();
1144  size_t nelmt = m_fields[0]->GetExpSize();
1145 
1146  Array<OneD, NekDouble> stdVelocity(nelmt, 0.0);
1148 
1149  if (m_HomogeneousType == eHomogeneous1D) // just do check on 2D info
1150  {
1151  velfields = Array<OneD, Array<OneD, NekDouble>>(2);
1152 
1153  for (size_t i = 0; i < 2; ++i)
1154  {
1155  velfields[i] = m_fields[m_velocity[i]]->UpdatePhys();
1156  }
1157  }
1158  else
1159  {
1160  velfields = Array<OneD, Array<OneD, NekDouble>>(nvel);
1161 
1162  for (size_t i = 0; i < nvel; ++i)
1163  {
1164  velfields[i] = m_fields[m_velocity[i]]->UpdatePhys();
1165  }
1166  }
1167 
1168  stdVelocity = m_extrapolation->GetMaxStdVelocity(velfields);
1169 
1170  return stdVelocity;
1171 }
1172 
1173 /**
1174  *
1175  */
1177  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
1179 {
1180  pressure = physfield[m_nConvectiveFields];
1181 }
1182 
1183 /**
1184  *
1185  */
1187  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
1188  Array<OneD, NekDouble> &density)
1189 {
1190  int nPts = physfield[0].size();
1191  Vmath::Fill(nPts, 1.0, density, 1);
1192 }
1193 
1194 /**
1195  *
1196  */
1198  const Array<OneD, const Array<OneD, NekDouble>> &physfield,
1199  Array<OneD, Array<OneD, NekDouble>> &velocity)
1200 {
1201  for (int i = 0; i < m_spacedim; ++i)
1202  {
1203  velocity[i] = physfield[i];
1204  }
1205 }
1206 
1207 /**
1208  * Function to set the moving frame velocities calucated in the forcing
1209  * this gives access to the moving reference forcing to set the velocities
1210  * to be later used in enforcing the boundary condition in IncNavierStokes
1211  * class
1212  */
1214  const Array<OneD, NekDouble> &vFrameVels)
1215 {
1216  ASSERTL0(vFrameVels.size() == m_movingFrameVelsxyz.size(),
1217  "Arrays have different dimensions, cannot set moving frame "
1218  "velocities");
1219  Vmath::Vcopy(vFrameVels.size(), vFrameVels, 1, m_movingFrameVelsxyz, 1);
1220 }
1221 
1223  Array<OneD, NekDouble> &vFrameVels)
1224 {
1225  ASSERTL0(vFrameVels.size() == m_movingFrameVelsxyz.size(),
1226  "Arrays have different dimensions, cannot get moving frame "
1227  "velocities");
1228  size_t size = m_movingFrameVelsxyz.size();
1229  Vmath::Vcopy(size, m_movingFrameVelsxyz, 1, vFrameVels, 1);
1230 }
1231 
1232 /**
1233  * Function to set the rotation matrix computed in the forcing
1234  * this gives access to the moving reference forcing to set the Projection
1235  * matrix to be used later in IncNavierStokes calss for enforcing the
1236  * boundary conditions
1237  */
1239  const bnu::matrix<NekDouble> &vProjMat)
1240 {
1241  ASSERTL0(vProjMat.size1() == m_movingFrameProjMat.size1(),
1242  "Matrices have different numbers of rows, cannot Set the "
1243  "moving frame projection matrix");
1244  ASSERTL0(vProjMat.size2() == m_movingFrameProjMat.size2(),
1245  "Matrices have different numbers of columns, cannot Set the "
1246  "moving frame projection matrix");
1247  for (size_t i = 0; i < vProjMat.size1(); ++i)
1248  {
1249  for (size_t j = 0; j < vProjMat.size2(); ++j)
1250  {
1251  m_movingFrameProjMat(i, j) = vProjMat(i, j);
1252  }
1253  }
1254 }
1255 
1257  bnu::matrix<NekDouble> &vProjMat)
1258 {
1259  ASSERTL0(vProjMat.size1() == m_movingFrameProjMat.size1(),
1260  "Matrices have different numbers of rows, cannot Get the "
1261  "moving frame projection matrix");
1262  ASSERTL0(vProjMat.size2() == m_movingFrameProjMat.size2(),
1263  "Matrices have different numbers of columns, cannot Get the "
1264  "moving frame projection matrix");
1265 
1266  for (size_t i = 0; i < vProjMat.size1(); ++i)
1267  {
1268  for (size_t j = 0; j < vProjMat.size2(); ++j)
1269  {
1270  vProjMat(i, j) = m_movingFrameProjMat(i, j);
1271  }
1272  }
1273 }
1274 
1275 /**
1276  * Function to set the angles between the moving frame of reference and
1277  * stationary inertial reference frame
1278  **/
1280  const Array<OneD, NekDouble> &vFrameTheta)
1281 {
1282  ASSERTL0(vFrameTheta.size() == m_movingFrameTheta.size(),
1283  "Arrays have different size, cannot set moving frame angles");
1284  for (size_t i = 0; i < vFrameTheta.size(); ++i)
1285  {
1286  m_movingFrameTheta[i] = vFrameTheta[i];
1287  }
1288 }
1289 
1290 /**
1291  * Function to get the angles between the moving frame of reference and
1292  * stationary inertial reference frame
1293  **/
1295  Array<OneD, NekDouble> &vFrameTheta)
1296 {
1297  ASSERTL0(vFrameTheta.size() == m_movingFrameTheta.size(),
1298  "Arrays have different size, cannot get moving frame angles");
1299  for (size_t i = 0; i < m_movingFrameTheta.size(); ++i)
1300  {
1301  vFrameTheta[i] = m_movingFrameTheta[i];
1302  }
1303 }
1304 
1305 /**
1306  * Function to check the type of forcing
1307  **/
1308 bool IncNavierStokes::DefinedForcing(const std::string &sForce)
1309 {
1310  vector<std::string> vForceList;
1311  bool hasForce{false};
1312 
1313  if (!m_session->DefinesElement("Nektar/Forcing"))
1314  {
1315  return hasForce;
1316  }
1317 
1318  TiXmlElement *vForcing = m_session->GetElement("Nektar/Forcing");
1319  if (vForcing)
1320  {
1321  TiXmlElement *vForce = vForcing->FirstChildElement("FORCE");
1322  while (vForce)
1323  {
1324  string vType = vForce->Attribute("TYPE");
1325 
1326  vForceList.push_back(vType);
1327  vForce = vForce->NextSiblingElement("FORCE");
1328  }
1329  }
1330 
1331  for (auto &f : vForceList)
1332  {
1333  if (boost::iequals(f, sForce))
1334  {
1335  hasForce = true;
1336  }
1337  }
1338 
1339  return hasForce;
1340 }
1341 
1342 /**
1343  * Get the pivot point for moving reference
1344  **/
1346 {
1347  std::string sMRFForcingType = "MovingReferenceFrame";
1348 
1349  // only if we use moving reference frame formulation
1350  if (!DefinedForcing(sMRFForcingType))
1351  {
1352  return;
1353  }
1354 
1355  TiXmlElement *vForcing = m_session->GetElement("Nektar/Forcing");
1356  if (vForcing)
1357  {
1358  TiXmlElement *vForce = vForcing->FirstChildElement("FORCE");
1359  while (vForce)
1360  {
1361  string vType = vForce->Attribute("TYPE");
1362 
1363  // if it is moving reference frame
1364  if (boost::iequals(vType, sMRFForcingType))
1365  {
1366  TiXmlElement *pivotElmt =
1367  vForce->FirstChildElement("PivotPoint");
1368 
1369  // if not defined, zero would be the default
1370  if (pivotElmt)
1371  {
1372  std::stringstream pivotPointStream;
1373  std::string pivotPointStr = pivotElmt->GetText();
1374  pivotPointStream.str(pivotPointStr);
1375 
1376  for (int j = 0; j < m_spacedim; ++j)
1377  {
1378  pivotPointStream >> pivotPointStr;
1379  if (!pivotPointStr.empty())
1380  {
1382  m_session->GetInterpreter(), pivotPointStr);
1383  vPivotPoint[j] = equ.Evaluate();
1384  }
1385  }
1386  }
1387 
1388  break;
1389  }
1390  }
1391  }
1392 }
1393 
1394 /**
1395  * Perform the extrapolation.
1396  */
1398 {
1399  m_extrapolation->SubStepSaveFields(step);
1400  m_extrapolation->SubStepAdvance(step, m_time);
1402  return false;
1403 }
1404 
1405 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
Array< OneD, Array< OneD, int > > m_fieldsBCToTraceID
Mapping from BCs to Elmt Edge IDs.
Array< OneD, NekDouble > m_pivotPoint
virtual Array< OneD, NekDouble > v_GetMaxStdVelocity(const NekDouble SpeedSoundFactor) override
std::map< int, std::map< int, WomersleyParamsSharedPtr > > m_womersleyParams
Womersley parameters if required.
virtual MultiRegions::ExpListSharedPtr v_GetPressure() override
virtual int v_GetForceDimension()=0
void SetWomersleyBoundary(const int fldid, const int bndid)
Set Womersley Profile if specified.
virtual void v_GetMovingFrameVelocities(Array< OneD, NekDouble > &vFrameVels) override
void SetZeroNormalVelocity()
Set Normal Velocity Component to Zero.
void SetBoundaryConditions(NekDouble time)
time dependent boundary conditions updating
void SetMRFDomainVelBCs(const NekDouble &time)
virtual void v_GetDensity(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, NekDouble > &density) override
NekDouble m_kinvis
Kinematic viscosity.
virtual void v_GetMovingFrameAngles(Array< OneD, NekDouble > &vFrameTheta) 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)
virtual void v_SetMovingFrameVelocities(const Array< OneD, NekDouble > &vFrameVels) override
void GetPivotPoint(Array< OneD, NekDouble > &vPivotPoint)
virtual bool v_PreIntegrate(int step) override
void SetUpWomersley(const int fldid, const int bndid, std::string womstr)
Set Up Womersley details.
virtual void v_InitObject(bool DeclareField=true) override
Init object for UnsteadySystem class.
ExtrapolateSharedPtr m_extrapolation
Array< OneD, int > m_velocity
int which identifies which components of m_fields contains the velocity (u,v,w);
virtual void v_SetMovingFrameAngles(const Array< OneD, NekDouble > &vFrameTheta) override
virtual void v_GetMovingFrameProjectionMat(bnu::matrix< NekDouble > &vProjMat) override
void EvaluateAdvectionTerms(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble time)
Array< OneD, Array< OneD, int > > m_fieldsBCToElmtID
Mapping from BCs to Elmt IDs.
EquationType m_equationType
equation type;
virtual 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.
virtual void v_GetVelocity(const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, Array< OneD, NekDouble >> &velocity) override
void SetMovingReferenceFrameBCs(const NekDouble &time)
Set the moving reference frame boundary conditions.
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
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:131
A base class for PDEs which include an advection component.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
virtual SOLVER_UTILS_EXPORT void v_InitObject(bool DeclareField=true) override
Init object for UnsteadySystem class.
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.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
enum HomogeneousType m_HomogeneousType
SOLVER_UTILS_EXPORT int GetPhys_Offset(int n)
Array< OneD, NekDouble > m_movingFrameTheta
Moving frame of reference angles with respect to the.
LibUtilities::FieldMetaDataMap m_fieldMetaDataMap
Map to identify relevant solver info to dump in output fields.
SpatialDomains::BoundaryConditionsSharedPtr m_boundaryConditions
Pointer to boundary conditions object.
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:120
Base class for unsteady solvers.
static NekDouble rad(NekDouble x, NekDouble y)
std::shared_ptr< SessionReader > SessionReaderSharedPtr
static FieldMetaDataMap NullFieldMetaDataMap
Definition: FieldIO.h:53
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:68
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
AdvectionFactory & GetAdvectionFactory()
Gets the factory for initialising advection objects.
Definition: Advection.cpp:47
SOLVER_UTILS_EXPORT typedef std::shared_ptr< Forcing > ForcingSharedPtr
A shared pointer to an EquationSystem object.
Definition: Forcing.h:52
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:172
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
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:1837
void Svtsvtp(int n, const T alpha, const T *x, int incx, const T beta, const T *y, int incy, T *z, int incz)
svtvvtp (scalar times vector plus scalar times vector):
Definition: Vmath.cpp:751
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.cpp:209
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.cpp:622
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:518
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.cpp:574
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.cpp:248
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:45
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add scalar y = alpha + x.
Definition: Vmath.cpp:384
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1255
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294