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 <iomanip>
37 #include <boost/algorithm/string.hpp>
38 
45 
49 #include <algorithm>
50 #include <iostream>
51 #include <fstream>
52 #include <sstream>
53 
54 #include <tinyxml.h>
56 
57 using namespace std;
58 
59 namespace Nektar
60 {
61 
62  /**
63  * Constructor. Creates ...
64  *
65  * \param
66  * \param
67  */
68  IncNavierStokes::IncNavierStokes(
71  UnsteadySystem(pSession, pGraph),
72  AdvectionSystem(pSession, pGraph),
73  m_SmoothAdvection(false)
74  {
75  }
76 
78  {
80 
81  int i,j;
82  int numfields = m_fields.num_elements();
83  std::string velids[] = {"u","v","w"};
84 
85  // Set up Velocity field to point to the first m_expdim of m_fields;
87 
88  for(i = 0; i < m_spacedim; ++i)
89  {
90  for(j = 0; j < numfields; ++j)
91  {
92  std::string var = m_boundaryConditions->GetVariable(j);
93  if(boost::iequals(velids[i], var))
94  {
95  m_velocity[i] = j;
96  break;
97  }
98 
99  ASSERTL0(j != numfields, "Failed to find field: " + var);
100  }
101  }
102 
103  // Set up equation type enum using kEquationTypeStr
104  for(i = 0; i < (int) eEquationTypeSize; ++i)
105  {
106  bool match;
107  m_session->MatchSolverInfo("EQTYPE",
108  kEquationTypeStr[i],match,false);
109  if(match)
110  {
112  break;
113  }
114  }
116  "EQTYPE not found in SOLVERINFO section");
117 
118  // This probably should to into specific implementations
119  // Equation specific Setups
120  switch(m_equationType)
121  {
122  case eSteadyStokes:
123  case eSteadyOseen:
124  case eSteadyNavierStokes:
125  case eSteadyLinearisedNS:
127  case eUnsteadyStokes:
128  break;
129  case eNoEquationType:
130  default:
131  ASSERTL0(false,"Unknown or undefined equation type");
132  }
133 
134  m_session->LoadParameter("Kinvis", m_kinvis);
135 
136  // Default advection type per solver
137  std::string vConvectiveType;
138  switch(m_equationType)
139  {
140  case eUnsteadyStokes:
141  case eSteadyLinearisedNS:
142  vConvectiveType = "NoAdvection";
143  break;
145  case eSteadyNavierStokes:
146  vConvectiveType = "Convective";
147  break;
149  vConvectiveType = "Linearised";
150  break;
151  default:
152  break;
153  }
154 
155  // Check if advection type overridden
156  if (m_session->DefinesTag("AdvectiveType") &&
159  {
160  vConvectiveType = m_session->GetTag("AdvectiveType");
161  }
162 
163  // Initialise advection
165  vConvectiveType, vConvectiveType);
166  m_advObject->InitObject( m_session, m_fields);
167 
168  // Forcing terms
169  m_forcing = SolverUtils::Forcing::Load(m_session, shared_from_this(),
171 
172  // check to see if any Robin boundary conditions and if so set
173  // up m_field to boundary condition maps;
178 
179  for (i = 0; i < m_fields.num_elements(); ++i)
180  {
181  bool Set = false;
182 
185  int radpts = 0;
186 
187  BndConds = m_fields[i]->GetBndConditions();
188  BndExp = m_fields[i]->GetBndCondExpansions();
189  for(int n = 0; n < BndConds.num_elements(); ++n)
190  {
191  if(boost::iequals(BndConds[n]->GetUserDefined(),"Radiation"))
192  {
193  ASSERTL0(BndConds[n]->GetBoundaryConditionType() ==
195  "Radiation boundary condition must be of type Robin <R>");
196 
197  if(Set == false)
198  {
199  m_fields[i]->GetBoundaryToElmtMap(
200  m_fieldsBCToElmtID[i],m_fieldsBCToTraceID[i]);
201  Set = true;
202  }
203  radpts += BndExp[n]->GetTotPoints();
204  }
205  if(boost::iequals(BndConds[n]->GetUserDefined(),
206  "ZeroNormalComponent"))
207  {
208  ASSERTL0(BndConds[n]->GetBoundaryConditionType() ==
210  "Zero Normal Component boundary condition option must be of type Dirichlet <D>");
211 
212  if(Set == false)
213  {
214  m_fields[i]->GetBoundaryToElmtMap(
215  m_fieldsBCToElmtID[i],m_fieldsBCToTraceID[i]);
216  Set = true;
217  }
218  }
219  }
220 
221  m_fieldsRadiationFactor[i] = Array<OneD, NekDouble>(radpts);
222 
223  radpts = 0; // reset to use as a counter
224 
225  for(int n = 0; n < BndConds.num_elements(); ++n)
226  {
227  if(boost::iequals(BndConds[n]->GetUserDefined(),"Radiation"))
228  {
229 
230  int npoints = BndExp[n]->GetNpoints();
231  Array<OneD, NekDouble> x0(npoints,0.0);
232  Array<OneD, NekDouble> x1(npoints,0.0);
233  Array<OneD, NekDouble> x2(npoints,0.0);
234  Array<OneD, NekDouble> tmpArray;
235 
236  BndExp[n]->GetCoords(x0,x1,x2);
237 
238  LibUtilities::Equation coeff =
239  std::static_pointer_cast<
241  >(BndConds[n])->m_robinPrimitiveCoeff;
242 
243  coeff.Evaluate(x0,x1,x2,m_time,
244  tmpArray = m_fieldsRadiationFactor[i]+ radpts);
245  //Vmath::Neg(npoints,tmpArray = m_fieldsRadiationFactor[i]+ radpts,1);
246  radpts += npoints;
247  }
248  }
249  }
250 
251  // Set up maping for womersley BC - and load variables
252  for (int i = 0; i < m_fields.num_elements(); ++i)
253  {
254  for(int n = 0; n < m_fields[i]->GetBndConditions().num_elements(); ++n)
255  {
256  if(boost::istarts_with(m_fields[i]->GetBndConditions()[n]->GetUserDefined(),"Womersley"))
257  {
258  // assumes that boundary condition is applied in normal direction
259  // and is decomposed for each direction. There could be a
260  // unique file for each direction
262  // Read in fourier coeffs and precompute coefficients
263  SetUpWomersley(i, n,
264  m_fields[i]->GetBndConditions()[n]->GetUserDefined());
265 
266  m_fields[i]->GetBoundaryToElmtMap(m_fieldsBCToElmtID[i],m_fieldsBCToTraceID[i]);
267 
268  }
269  }
270  }
271 
272  // Set up Field Meta Data for output files
273  m_fieldMetaDataMap["Kinvis"] = boost::lexical_cast<std::string>(m_kinvis);
274  m_fieldMetaDataMap["TimeStep"] = boost::lexical_cast<std::string>(m_timestep);
275  }
276 
277  /**
278  * Destructor
279  */
281  {
282  }
283 
284  /**
285  * Evaluation -N(V) for all fields except pressure using m_velocity
286  */
288  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
289  Array<OneD, Array<OneD, NekDouble> > &outarray)
290  {
291  int i;
292  int VelDim = m_velocity.num_elements();
293  Array<OneD, Array<OneD, NekDouble> > velocity(VelDim);
294 
295  for(i = 0; i < VelDim; ++i)
296  {
297  velocity[i] = inarray[m_velocity[i]];
298  }
299 
301  velocity, inarray, outarray, m_time);
302  }
303 
304  /**
305  * Time dependent boundary conditions updating
306  */
308  {
309  int i, n;
310  std::string varName;
311  int nvariables = m_fields.num_elements();
312 
313  for (i = 0; i < nvariables; ++i)
314  {
315  for(n = 0; n < m_fields[i]->GetBndConditions().num_elements(); ++n)
316  {
317  if(m_fields[i]->GetBndConditions()[n]->IsTimeDependent())
318  {
319  varName = m_session->GetVariable(i);
320  m_fields[i]->EvaluateBoundaryConditions(time, varName);
321  }
322  else if(boost::istarts_with(
323  m_fields[i]->GetBndConditions()[n]->GetUserDefined(),
324  "Womersley"))
325  {
327  }
328  }
329 
330  // Set Radiation conditions if required
332  }
333 
335  }
336 
337  /**
338  * Probably should be pushed back into ContField?
339  */
341  {
342  int i,n;
343 
346 
347  BndConds = m_fields[fieldid]->GetBndConditions();
348  BndExp = m_fields[fieldid]->GetBndCondExpansions();
349 
352 
353  int cnt;
354  int elmtid,nq,offset, boundary;
355  Array<OneD, NekDouble> Bvals, U;
356  int cnt1 = 0;
357 
358  for(cnt = n = 0; n < BndConds.num_elements(); ++n)
359  {
360  std::string type = BndConds[n]->GetUserDefined();
361 
362  if((BndConds[n]->GetBoundaryConditionType() ==
364  (boost::iequals(type,"Radiation")))
365  {
366  for(i = 0; i < BndExp[n]->GetExpSize(); ++i,cnt++)
367  {
368  elmtid = m_fieldsBCToElmtID[m_velocity[fieldid]][cnt];
369  elmt = m_fields[fieldid]->GetExp(elmtid);
370  offset = m_fields[fieldid]->GetPhys_Offset(elmtid);
371 
372  U = m_fields[fieldid]->UpdatePhys() + offset;
373  Bc = BndExp[n]->GetExp(i);
374 
375  boundary = m_fieldsBCToTraceID[fieldid][cnt];
376 
377  // Get edge values and put into ubc
378  nq = Bc->GetTotPoints();
379  Array<OneD, NekDouble> ubc(nq);
380  elmt->GetTracePhysVals(boundary,Bc,U,ubc);
381 
382  Vmath::Vmul(nq,&m_fieldsRadiationFactor[fieldid][cnt1 +
383  BndExp[n]->GetPhys_Offset(i)],1,
384  &ubc[0],1,&ubc[0],1);
385 
386  Bvals = BndExp[n]->UpdateCoeffs()+BndExp[n]->
387  GetCoeff_Offset(i);
388 
389  Bc->IProductWRTBase(ubc,Bvals);
390  }
391  cnt1 += BndExp[n]->GetTotPoints();
392  }
393  else
394  {
395  cnt += BndExp[n]->GetExpSize();
396  }
397  }
398  }
399 
400 
402  {
403  // use static trip since cannot use UserDefinedTag for zero
404  // velocity and have time dependent conditions
405  static bool Setup = false;
406 
407  if(Setup == true)
408  {
409  return;
410  }
411  Setup = true;
412 
413  int i,n;
414 
416  BndConds(m_spacedim);
418  BndExp(m_spacedim);
419 
420 
421  for(i = 0; i < m_spacedim; ++i)
422  {
423  BndConds[i] = m_fields[m_velocity[i]]->GetBndConditions();
424  BndExp[i] = m_fields[m_velocity[i]]->GetBndCondExpansions();
425  }
426 
428 
429  int cnt;
430  int elmtid,nq, boundary;
431 
433  Array<OneD, NekDouble> Bphys,Bcoeffs;
434 
435  int fldid = m_velocity[0];
436 
437  for(cnt = n = 0; n < BndConds[0].num_elements(); ++n)
438  {
439  if((BndConds[0][n]->GetBoundaryConditionType() ==
441  (boost::iequals(BndConds[0][n]->GetUserDefined(),
442  "ZeroNormalComponent")))
443  {
444  for(i = 0; i < BndExp[0][n]->GetExpSize(); ++i,cnt++)
445  {
446  elmtid = m_fieldsBCToElmtID[fldid][cnt];
447  elmt = m_fields[0]->GetExp(elmtid);
448  boundary = m_fieldsBCToTraceID[fldid][cnt];
449 
450  normals = elmt->GetSurfaceNormal(boundary);
451 
452  nq = BndExp[0][n]->GetExp(i)->GetTotPoints();
453  Array<OneD, NekDouble> normvel(nq,0.0);
454 
455  for(int k = 0; k < m_spacedim; ++k)
456  {
457  Bphys = BndExp[k][n]->UpdatePhys()+
458  BndExp[k][n]->GetPhys_Offset(i);
459  Bc = BndExp[k][n]->GetExp(i);
460  Vmath::Vvtvp(nq,normals[k],1,Bphys,1,normvel,1,
461  normvel,1);
462  }
463 
464  // negate normvel for next step
465  Vmath::Neg(nq,normvel,1);
466 
467  for(int k = 0; k < m_spacedim; ++k)
468  {
469  Bphys = BndExp[k][n]->UpdatePhys()+
470  BndExp[k][n]->GetPhys_Offset(i);
471  Bcoeffs = BndExp[k][n]->UpdateCoeffs()+
472  BndExp[k][n]->GetCoeff_Offset(i);
473  Bc = BndExp[k][n]->GetExp(i);
474  Vmath::Vvtvp(nq,normvel,1,normals[k],1,Bphys,1,
475  Bphys,1);
476  Bc->FwdTrans_BndConstrained(Bphys,Bcoeffs);
477  }
478  }
479  }
480  else
481  {
482  cnt += BndExp[0][n]->GetExpSize();
483  }
484  }
485  }
486 
487 
488  /**
489  * Womersley boundary condition defintion
490  */
491  void IncNavierStokes::SetWomersleyBoundary(const int fldid, const int bndid)
492  {
493  ASSERTL1(m_womersleyParams.count(bndid) == 1,
494  "Womersley parameters for this boundary have not been set up");
495 
496  WomersleyParamsSharedPtr WomParam = m_womersleyParams[fldid][bndid];
497  NekComplexDouble zvel;
498  int i,j,k;
499 
500  int M_coeffs = WomParam->m_wom_vel.size();
501 
502  NekDouble T = WomParam->m_period;
503  NekDouble axis_normal = WomParam->m_axisnormal[fldid];
504 
505  // Womersley Number
506  NekComplexDouble omega_c (2.0*M_PI/T, 0.0);
507  NekComplexDouble k_c (0.0, 0.0);
508  NekComplexDouble m_time_c (m_time, 0.0);
509  NekComplexDouble zi (0.0,1.0);
510  NekComplexDouble i_pow_3q2 (-1.0/sqrt(2.0),1.0/sqrt(2.0));
511 
513  BndCondExp = m_fields[fldid]->GetBndCondExpansions()[bndid];
514 
516  int cnt=0;
517  int nfq;
519  int exp_npts = BndCondExp->GetExpSize();
520  Array<OneD, NekDouble> wbc(exp_npts,0.0);
521 
522  Array<OneD, NekComplexDouble> zt(M_coeffs);
523 
524  // preallocate the exponent
525  for (k=1; k < M_coeffs; k++)
526  {
527  k_c = NekComplexDouble((NekDouble) k, 0.0);
528  zt[k] = std::exp(zi * omega_c * k_c * m_time_c);
529  }
530 
531  // Loop over each element in an expansion
532  for(i = 0; i < exp_npts; ++i,cnt++)
533  {
534  // Get Boundary and trace expansion
535  bc = BndCondExp->GetExp(i);
536  nfq = bc->GetTotPoints();
537  Array<OneD, NekDouble> wbc(nfq,0.0);
538 
539  // Compute womersley solution
540  for (j=0; j < nfq; j++)
541  {
542  wbc[j] = WomParam->m_poiseuille[i][j];
543  for (k=1; k < M_coeffs; k++)
544  {
545  zvel = WomParam->m_zvel[i][j][k] * zt[k];
546  wbc[j] = wbc[j] + zvel.real();
547  }
548  }
549 
550  // Multiply w by normal to get u,v,w component of velocity
551  Vmath::Smul(nfq,axis_normal,wbc,1,wbc,1);
552  // get the offset
553  Bvals = BndCondExp->UpdateCoeffs()+
554  BndCondExp->GetCoeff_Offset(i);
555 
556  // Push back to Coeff space
557  bc->FwdTrans(wbc,Bvals);
558  }
559  }
560 
561 
562  void IncNavierStokes::SetUpWomersley(const int fldid, const int bndid, std::string womStr)
563  {
564  std::string::size_type indxBeg = womStr.find_first_of(':') + 1;
565  string filename = womStr.substr(indxBeg,string::npos);
566 
567  TiXmlDocument doc(filename);
568 
569  bool loadOkay = doc.LoadFile();
570  ASSERTL0(loadOkay,(std::string("Failed to load file: ") +
571  filename).c_str());
572 
573  TiXmlHandle docHandle(&doc);
574 
575  int err; /// Error value returned by TinyXML.
576 
577  TiXmlElement *nektar = doc.FirstChildElement("NEKTAR");
578  ASSERTL0(nektar, "Unable to find NEKTAR tag in file.");
579 
580  TiXmlElement *wombc = nektar->FirstChildElement("WOMERSLEYBC");
581  ASSERTL0(wombc, "Unable to find WOMERSLEYBC tag in file.");
582 
583  // read womersley parameters
584  TiXmlElement *womparam = wombc->FirstChildElement("WOMPARAMS");
585  ASSERTL0(womparam, "Unable to find WOMPARAMS tag in file.");
586 
587  // Input coefficients
588  TiXmlElement *params = womparam->FirstChildElement("W");
589  map<std::string,std::string> Wparams;
590 
591  // read parameter list
592  while (params)
593  {
594 
595  std::string propstr;
596  propstr = params->Attribute("PROPERTY");
597 
598  ASSERTL0(!propstr.empty(),
599  "Failed to read PROPERTY value Womersley BC Parameter");
600 
601 
602  std::string valstr;
603  valstr = params->Attribute("VALUE");
604 
605  ASSERTL0(!valstr.empty(),
606  "Failed to read VALUE value Womersley BC Parameter");
607 
608  std::transform(propstr.begin(),propstr.end(),propstr.begin(),
609  ::toupper);
610  Wparams[propstr] = valstr;
611 
612  params = params->NextSiblingElement("W");
613  }
614  bool parseGood;
615 
616  // Read parameters
617 
618  ASSERTL0(Wparams.count("RADIUS") == 1,
619  "Failed to find Radius parameter in Womersley boundary conditions");
620  std::vector<NekDouble> rad;
621  ParseUtils::GenerateVector(Wparams["RADIUS"],rad);
622  m_womersleyParams[fldid][bndid]->m_radius = rad[0];
623 
624  ASSERTL0(Wparams.count("PERIOD") == 1,
625  "Failed to find period parameter in Womersley boundary conditions");
626  std::vector<NekDouble> period;
627  parseGood = ParseUtils::GenerateVector(Wparams["PERIOD"],period);
628  m_womersleyParams[fldid][bndid]->m_period = period[0];
629 
630 
631  ASSERTL0(Wparams.count("AXISNORMAL") == 1,
632  "Failed to find axisnormal parameter in Womersley boundary conditions");
633  std::vector<NekDouble> anorm;
634  parseGood = ParseUtils::GenerateVector(Wparams["AXISNORMAL"],anorm);
635  m_womersleyParams[fldid][bndid]->m_axisnormal[0] = anorm[0];
636  m_womersleyParams[fldid][bndid]->m_axisnormal[1] = anorm[1];
637  m_womersleyParams[fldid][bndid]->m_axisnormal[2] = anorm[2];
638 
639 
640  ASSERTL0(Wparams.count("AXISPOINT") == 1,
641  "Failed to find axispoint parameter in Womersley boundary conditions");
642  std::vector<NekDouble> apt;
643  parseGood = ParseUtils::GenerateVector(Wparams["AXISPOINT"],apt);
644  m_womersleyParams[fldid][bndid]->m_axispoint[0] = apt[0];
645  m_womersleyParams[fldid][bndid]->m_axispoint[1] = apt[1];
646  m_womersleyParams[fldid][bndid]->m_axispoint[2] = apt[2];
647 
648  // Read Temporal Fourier Coefficients.
649 
650  // Find the FourierCoeff tag
651  TiXmlElement *coeff = wombc->FirstChildElement("FOURIERCOEFFS");
652 
653  // Input coefficients
654  TiXmlElement *fval = coeff->FirstChildElement("F");
655 
656  int indx;
657  int nextFourierCoeff = -1;
658 
659  while (fval)
660  {
661  nextFourierCoeff++;
662 
663  TiXmlAttribute *fvalAttr = fval->FirstAttribute();
664  std::string attrName(fvalAttr->Name());
665 
666  ASSERTL0(attrName == "ID",
667  (std::string("Unknown attribute name: ") + attrName).c_str());
668 
669  err = fvalAttr->QueryIntValue(&indx);
670  ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID.");
671 
672  std::string coeffStr = fval->FirstChild()->ToText()->ValueStr();
673  vector<NekDouble> coeffvals;
674 
675  parseGood = ParseUtils::GenerateVector(coeffStr, coeffvals);
676  ASSERTL0(parseGood,
677  (std::string("Problem reading value of fourier coefficient, ID=") +
678  boost::lexical_cast<string>(indx)).c_str());
679  ASSERTL1(coeffvals.size() == 2,
680  (std::string("Have not read two entries of Fourier coefficicent from ID="+
681  boost::lexical_cast<string>(indx)).c_str()));
682 
683  m_womersleyParams[fldid][bndid]->m_wom_vel.push_back(NekComplexDouble (coeffvals[0], coeffvals[1]));
684 
685  fval = fval->NextSiblingElement("F");
686  }
687 
688  // starting point of precalculation
689  int i,j,k;
690  // M fourier coefficients
691  int M_coeffs = m_womersleyParams[fldid][bndid]->m_wom_vel.size();
692  NekDouble R = m_womersleyParams[fldid][bndid]->m_radius;
693  NekDouble T = m_womersleyParams[fldid][bndid]->m_period;
694  Array<OneD, NekDouble > x0 = m_womersleyParams[fldid][bndid]->m_axispoint;
695 
696  NekComplexDouble rqR;
697  // Womersley Number
698  NekComplexDouble omega_c (2.0*M_PI/T, 0.0);
699  NekComplexDouble alpha_c (R*sqrt(omega_c.real()/m_kinvis), 0.0);
700  NekComplexDouble z1 (1.0,0.0);
701  NekComplexDouble i_pow_3q2 (-1.0/sqrt(2.0),1.0/sqrt(2.0));
702 
704  BndCondExp = m_fields[fldid]->GetBndCondExpansions()[bndid];
705 
707  int cnt = 0;
708  int nfq;
710 
711  int exp_npts = BndCondExp->GetExpSize();
712  Array<OneD, NekDouble> wbc(exp_npts,0.0);
713 
714  // allocate time indepedent variables
715  m_womersleyParams[fldid][bndid]->m_poiseuille = Array<OneD, Array<OneD, NekDouble> > (exp_npts);
716  m_womersleyParams[fldid][bndid]->m_zvel = Array<OneD, Array<OneD, Array<OneD, NekComplexDouble> > > (exp_npts);
717  // could use M_coeffs - 1 but need to avoid complicating things
718  Array<OneD, NekComplexDouble> zJ0(M_coeffs);
719  Array<OneD, NekComplexDouble> lamda_n(M_coeffs);
720  Array<OneD, NekComplexDouble> k_c(M_coeffs);
721  NekComplexDouble zJ0r;
722 
723  for (k=1; k < M_coeffs; k++)
724  {
725  k_c[k] = NekComplexDouble((NekDouble) k, 0.0);
726  lamda_n[k] = i_pow_3q2 * alpha_c * sqrt(k_c[k]);
727  zJ0[k] = Polylib::ImagBesselComp(0,lamda_n[k]);
728  }
729 
730  // Loop over each element in an expansion
731  for(i = 0; i < exp_npts; ++i,cnt++)
732  {
733  // Get Boundary and trace expansion
734  bc = BndCondExp->GetExp(i);
735  nfq = bc->GetTotPoints();
736 
737  Array<OneD, NekDouble> x(nfq,0.0);
738  Array<OneD, NekDouble> y(nfq,0.0);
739  Array<OneD, NekDouble> z(nfq,0.0);
740  bc->GetCoords(x,y,z);
741 
742  m_womersleyParams[fldid][bndid]->m_poiseuille[i] =
744  m_womersleyParams[fldid][bndid]->m_zvel[i] =
746 
747  // Compute coefficients
748  for (j=0; j < nfq; j++)
749  {
750  rqR = NekComplexDouble (sqrt((x[j]-x0[0])*(x[j]-x0[0]) +
751  (y[j]-x0[1])*(y[j]-x0[1]) +
752  (z[j]-x0[2])*(z[j]-x0[2]))/R, 0.0);
753 
754  // Compute Poiseulle Flow
755  m_womersleyParams[fldid][bndid]->m_poiseuille[i][j] =
756  m_womersleyParams[fldid][bndid]->m_wom_vel[0].real() *
757  (1. - rqR.real()*rqR.real());
758 
759 
760  m_womersleyParams[fldid][bndid]->m_zvel[i][j] =
762 
763  // compute the velocity information
764  for (k=1; k < M_coeffs; k++)
765  {
766  zJ0r = Polylib::ImagBesselComp(0,rqR * lamda_n[k]);
767  m_womersleyParams[fldid][bndid]->m_zvel[i][j][k] =
768  m_womersleyParams[fldid][bndid]->m_wom_vel[k] *
769  (z1 - (zJ0r / zJ0[k]));
770  }
771  }
772  }
773  }
774 
775  /**
776  * Add an additional forcing term programmatically.
777  */
779  const SolverUtils::ForcingSharedPtr& pForce)
780  {
781  m_forcing.push_back(pForce);
782  }
783 
784  /**
785  *
786  */
788  {
789  int nvel = m_velocity.num_elements();
790  int nelmt = m_fields[0]->GetExpSize();
791 
792  Array<OneD, NekDouble> stdVelocity(nelmt, 0.0);
794 
795  if(m_HomogeneousType == eHomogeneous1D) // just do check on 2D info
796  {
797  velfields = Array<OneD, Array<OneD, NekDouble> >(2);
798 
799  for(int i = 0; i < 2; ++i)
800  {
801  velfields[i] = m_fields[m_velocity[i]]->UpdatePhys();
802  }
803  }
804  else
805  {
806  velfields = Array<OneD, Array<OneD, NekDouble> >(nvel);
807 
808  for(int i = 0; i < nvel; ++i)
809  {
810  velfields[i] = m_fields[m_velocity[i]]->UpdatePhys();
811  }
812  }
813 
814  stdVelocity = m_extrapolation->GetMaxStdVelocity(velfields);
815 
816  return stdVelocity;
817  }
818 
819  /**
820  *
821  */
823  const Array<OneD, const Array<OneD, NekDouble> > &physfield,
825  {
826  pressure = physfield[m_nConvectiveFields];
827  }
828 
829  /**
830  *
831  */
833  const Array<OneD, const Array<OneD, NekDouble> > &physfield,
834  Array<OneD, NekDouble> &density)
835  {
836  int nPts = physfield[0].num_elements();
837  Vmath::Fill(nPts, 1.0, density, 1);
838  }
839 
840  /**
841  *
842  */
844  const Array<OneD, const Array<OneD, NekDouble> > &physfield,
845  Array<OneD, Array<OneD, NekDouble> > &velocity)
846  {
847  for(int i = 0; i < m_spacedim; ++i)
848  {
849  velocity[i] = physfield[i];
850  }
851  }
852 
853  /**
854  * Perform the extrapolation.
855  */
857  {
858  m_extrapolation->SubStepSaveFields(step);
859  m_extrapolation->SubStepAdvance(m_intSoln,step,m_time);
861  return false;
862  }
863 
864 } //end of namespace
865 
EquationType m_equationType
equation type;
void SetZeroNormalVelocity()
Set Normal Velocity Component to Zero.
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
SOLVER_UTILS_EXPORT typedef std::shared_ptr< Forcing > ForcingSharedPtr
A shared pointer to an EquationSystem object.
Definition: Forcing.h:52
std::complex< double > NekComplexDouble
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:163
void SetBoundaryConditions(NekDouble time)
time dependent boundary conditions updating
Array< OneD, Array< OneD, int > > m_fieldsBCToTraceID
Mapping from BCs to Elmt Edge IDs.
std::map< int, std::map< int, WomersleyParamsSharedPtr > > m_womersleyParams
Womersley parameters if required.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
virtual bool v_PreIntegrate(int step)
NekDouble m_time
Current time of simulation.
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
void SetRadiationBoundaryForcing(int fieldid)
Set Radiation forcing term.
NekDouble m_kinvis
Kinematic viscosity.
NekDouble m_timestep
Time step size.
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:45
Array< OneD, int > m_velocity
int which identifies which components of m_fields contains the velocity (u,v,w);
ExtrapolateSharedPtr m_extrapolation
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:445
STL namespace.
virtual void GetDensity(const Array< OneD, const Array< OneD, NekDouble > > &physfield, Array< OneD, NekDouble > &density)
Extract array with density from physfield.
void EvaluateAdvectionTerms(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray)
int m_nConvectiveFields
Number of fields to be convected;.
SOLVER_UTILS_EXPORT int GetCoeff_Offset(int n)
void SetUpWomersley(const int fldid, const int bndid, std::string womstr)
Set Up Womersley details.
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
Array< OneD, Array< OneD, NekDouble > > m_fieldsRadiationFactor
RHS Factor for Radiation Condition.
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*y.
Definition: Vmath.cpp:216
virtual Array< OneD, NekDouble > v_GetMaxStdVelocity()
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:85
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
Forcing terms.
Base class for unsteady solvers.
SpatialDomains::BoundaryConditionsSharedPtr m_boundaryConditions
Pointer to boundary conditions object.
int m_spacedim
Spatial dimension (>= expansion dim).
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
LibUtilities::FieldMetaDataMap m_fieldMetaDataMap
Map to identify relevant solver info to dump in output fields.
AdvectionFactory & GetAdvectionFactory()
Gets the factory for initialising advection objects.
Definition: Advection.cpp:47
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:399
NekDouble Evaluate() const
Definition: Equation.cpp:95
double NekDouble
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:135
Array< OneD, int > & GetVelocity(void)
SOLVER_UTILS_EXPORT int GetPhys_Offset(int n)
static NekDouble rad(NekDouble x, NekDouble y)
Definition: Interpreter.cpp:86
void AddForcing(const SolverUtils::ForcingSharedPtr &pForce)
Array< OneD, Array< OneD, int > > m_fieldsBCToElmtID
Mapping from BCs to Elmt IDs.
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
SOLVER_UTILS_EXPORT MultiRegions::ExpListSharedPtr GetPressure()
Get pressure field if available.
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:1565
const std::string kEquationTypeStr[]
void SetWomersleyBoundary(const int fldid, const int bndid)
Set Womersley Profile if specified.
virtual SOLVER_UTILS_EXPORT void v_InitObject()
Init object for UnsteadySystem class.
A base class for PDEs which include an advection component.
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
std::shared_ptr< WomersleyParams > WomersleyParamsSharedPtr
LibUtilities::TimeIntegrationSolutionSharedPtr m_intSoln
virtual void v_InitObject()
Init object for UnsteadySystem class.
std::shared_ptr< SessionReader > SessionReaderSharedPtr
virtual int v_GetForceDimension()=0
enum HomogeneousType m_HomogeneousType
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:186