Nektar++
ForcingMovingReferenceFrame.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: ForcingMovingReferenceFrame.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: Solving the absolute flow in a moving body frame,
32 // by adding (U0 + Omega X (x - x0)) . grad u - Omega X u
33 // as the body force.
34 // U0 is the translational velocity of the body frame.
35 // Omega is the angular velocity.
36 // x0 is the rotation pivot in the body frame.
37 // All vectors use the basis of the body frame.
38 // Translational motion is allowed for all dimensions.
39 // Rotation is not allowed for 1D, 2DH1D, 3DH2D.
40 // Rotation in z direction is allowed for 2D and 3DH1D.
41 // Rotation in 3 directions are allowed for 3D.
42 ///////////////////////////////////////////////////////////////////////////////
43 
44 #include <boost/core/ignore_unused.hpp>
45 
47 #include <MultiRegions/ExpList.h>
50 
51 using namespace std;
52 
53 namespace Nektar
54 {
55 namespace SolverUtils
56 {
57 
58 std::string ForcingMovingReferenceFrame::classNameBody =
60  "MovingReferenceFrame", ForcingMovingReferenceFrame::create,
61  "Moving Frame");
62 
63 /**
64  * @brief
65  * @param pSession
66  * @param pEquation
67  */
68 ForcingMovingReferenceFrame::ForcingMovingReferenceFrame(
70  const std::weak_ptr<EquationSystem> &pEquation)
71  : Forcing(pSession, pEquation)
72 {
73 }
74 
75 /**
76  * @brief Initialise the forcing module
77  * @param pFields
78  * @param pNumForcingFields
79  * @param pForce
80  */
83  const unsigned int &pNumForcingFields, const TiXmlElement *pForce)
84 {
85  boost::ignore_unused(pNumForcingFields);
86  m_session->MatchSolverInfo("Homogeneous", "1D", m_isH1d, false);
87  m_session->MatchSolverInfo("Homogeneous", "2D", m_isH2d, false);
88  bool singleMode, halfMode;
89  m_session->MatchSolverInfo("ModeType", "SingleMode", singleMode, false);
90  m_session->MatchSolverInfo("ModeType", "HalfMode", halfMode, false);
91  if (singleMode || halfMode)
92  {
93  m_isH1d = false;
94  }
95 
96  int npoints = pFields[0]->GetNpoints();
97  int expdim = m_isH2d ? 1 : pFields[0]->GetGraph()->GetMeshDimension();
98  m_spacedim = expdim + (m_isH1d ? 1 : 0) + (m_isH2d ? 2 : 0);
100 
101  m_hasPlane0 = true;
102  if (m_isH1d)
103  {
104  m_hasPlane0 = pFields[0]->GetZIDs()[0] == 0;
105  }
106 
107  // linear velocities
108  const TiXmlElement *funcNameElmt;
109 
110  funcNameElmt = pForce->FirstChildElement("LinearVelocity");
111  ASSERTL0(funcNameElmt, "Requires LinearVelocity tag specifying function "
112  "name which prescribes velocity of the moving "
113  "frame.");
114 
115  m_velFuncName = funcNameElmt->GetText();
116  ASSERTL0(m_session->DefinesFunction(m_velFuncName),
117  "Function '" + m_velFuncName + "' is not defined in the session.");
118 
119  // angular velocities
120  // Initiate the rotation to false, will be updated later if rotation defined
121  m_hasRotation = false;
122  funcNameElmt = pForce->FirstChildElement("AngularVelocity");
123  if (funcNameElmt)
124  {
125  m_omegaFuncName = funcNameElmt->GetText();
126  ASSERTL0(m_session->DefinesFunction(m_omegaFuncName),
127  "Function '" + m_omegaFuncName +
128  "' is not defined in the session.");
129  m_hasRotation = true;
130  }
131 
132  // initiate the linear velocity values in both local and inertial frames
133  for (int i = 0; i < 3; ++i)
134  {
135  m_velXYZ[i] = 0.;
136  m_velxyz[i] = 0.;
137  }
138 
139  // initiate the angular velocity values in both local and inertial frames
140  for (int i = 0; i < 3; ++i)
141  {
142  m_omegaXYZ[i] = 0;
143  m_omegaxyz[i] = 0;
144  }
145 
146  // initiate the available frame velocities all to false
147  // this will be updated after reading the frame velocities and checking
148  // for the rotation
149  for (int i = 0; i < 3; ++i)
150  {
151  m_hasVel[i] = false;
152  m_hasOmega[i] = false;
153  }
154 
155  // initiate the rotation angle to zero
156  // m_theta = {theta_X, theta_Y, theta_Z}
158 
159  // initialize theta from the metadata of restart file or zero
160  CheckForRestartTheta(pFields, m_theta);
161 
162  // Initialize theta with the data from NS class
163  // This ensure correct moving coordinate orientation with respect to the
164  // stationary inertial frame when we restart the simulation
165  auto equ = m_equ.lock();
166  ASSERTL0(equ, "Weak pointer to the equation system is expired");
167  auto FluidEq = std::dynamic_pointer_cast<FluidInterface>(equ);
168  // Set the angles
169  FluidEq->SetMovingFrameAngles(m_theta);
170 
171  // initiate the rotation matrix to zero,
172  // Note that the rotation matrix is assumed for the rotation around z axis
173  // TODO: Generalize this for the 3D case with possiblity of rotation around
174  // each of axis. Probabley we only can support rotation around one axis. In
175  // that case the generalization means the user can provide Omega for one of
176  // x, y or z axis. Not sure how complicated to consider a general axis of
177  // rotation
178  //
179  // Note that these rotation matrices should be extrinsic rotations
180  m_ProjMatX = bn::ublas::zero_matrix<NekDouble>(3, 3);
181  m_ProjMatY = bn::ublas::zero_matrix<NekDouble>(3, 3);
182  m_ProjMatZ = bn::ublas::zero_matrix<NekDouble>(3, 3);
183  // populate the rotation matrix R(z)
184  {
185  NekDouble sn, cs;
186  sn = sin(m_theta[2]);
187  cs = cos(m_theta[2]);
188 
189  m_ProjMatZ(0, 0) = cs;
190  m_ProjMatZ(0, 1) = sn;
191  m_ProjMatZ(1, 0) = -1. * sn;
192  m_ProjMatZ(1, 1) = cs;
193  m_ProjMatZ(2, 2) = 1.0;
194  }
195 
196  // frame linear velocity
197  for (int i = 0; i < m_spacedim; ++i)
198  {
199  std::string s_FieldStr = m_session->GetVariable(i);
200 
201  if (m_session->DefinesFunction(m_velFuncName, s_FieldStr))
202  {
203  m_velFunction[i] =
204  m_session->GetFunction(m_velFuncName, s_FieldStr);
205  m_hasVel[i] = true;
206  }
207  }
208  if (expdim == 1)
209  {
210  return;
211  }
212 
213  // initialize the poivot coordinate with a default at origin
215  if (m_hasRotation)
216  {
217  // frame angular velocity
218  std::vector<std::string> angularVar = {"Omega_x", "Omega_y", "Omega_z"};
219  for (int i = 0; i < 3; ++i)
220  {
221  std::string s_FieldStr = angularVar[i];
222  if (m_session->DefinesFunction(m_omegaFuncName, s_FieldStr))
223  {
224  // m_hasRotation = true;
225  m_omegaFunction[i] =
226  m_session->GetFunction(m_omegaFuncName, s_FieldStr);
227  m_hasOmega[i] = true;
228  // m_hasVel[m_spacedim+i]=true;
229  }
230  }
231 
232  // for now only support Omega_z
233  // TODO: add the support for general rotation
234  for (int i = 0; i < 2; ++i)
235  {
236  ASSERTL0(!m_hasOmega[i], "Currently only Omega_z is supported");
237  }
238 
239  // Reading the pivot point coordinate for rotation
240  const TiXmlElement *pivotElmt = pForce->FirstChildElement("PivotPoint");
241  // if not defined, zero would be the default
242  if (pivotElmt)
243  {
244  std::stringstream pivotPointStream;
245  std::string pivotPointStr = pivotElmt->GetText();
246  pivotPointStream.str(pivotPointStr);
247 
248  for (int j = 0; j < m_spacedim; ++j)
249  {
250  pivotPointStream >> pivotPointStr;
251  if (!pivotPointStr.empty())
252  {
253  LibUtilities::Equation equ(m_session->GetInterpreter(),
254  pivotPointStr);
255  m_pivotPoint[j] = equ.Evaluate();
256  }
257  }
258  }
259 
261  for (int j = 0; j < m_spacedim; ++j)
262  {
263  m_coords[j] = Array<OneD, NekDouble>(npoints);
264  }
265  pFields[0]->GetCoords(m_coords[0], m_coords[1], m_coords[2]);
266  // move the origin to the pivot point
267  for (int i = 0; i < m_spacedim; ++i)
268  {
269  Vmath::Sadd(npoints, -m_pivotPoint[i], m_coords[i], 1, m_coords[i],
270  1);
271  }
272 
273  // account for the effect of rotation
274  // Omega_X results in having v and w even if not defined by user
275  // Omega_Y results in having u and w even if not defined by user
276  // Omega_Z results in having u and v even if not defined by user
277  //
278  for (int i = 0; i < 3; ++i)
279  {
280  int j = (i + 1) % 3;
281  int k = (i + 2) % 3;
282 
283  if (m_hasOmega[i])
284  {
285  m_hasVel[j] = true;
286  m_hasVel[k] = true;
287  }
288  }
289  }
290 }
291 
292 /**
293  * @brief Updates the forcing array with the current required forcing.
294  * @param pFields
295  * @param time
296  */
298 {
299  // compute the velociites whos functions are provided in inertial frame
300  for (auto it : m_velFunction)
301  {
302  m_velXYZ[it.first] = it.second->Evaluate(0., 0., 0., time);
303  }
304  for (auto it : m_omegaFunction)
305  {
306  m_omegaXYZ[it.first] = it.second->Evaluate(0., 0., 0., time);
307  }
308  // include the effect of rotation
309  if (m_hasRotation)
310  {
311  UpdateTheta(time);
312 
313  // transform the translation velocities to the moving frame
314  bn::ublas::vector<NekDouble> v0 = bn::ublas::zero_vector<NekDouble>(3);
315  bn::ublas::vector<NekDouble> v1 = bn::ublas::zero_vector<NekDouble>(3);
316  for (int i = 0; i < m_spacedim; ++i)
317  {
318  v0(i) = m_velXYZ[i];
319  }
320  v1 = bn::ublas::prec_prod(m_ProjMatZ, v0);
321  for (int i = 0; i < 3; ++i)
322  {
323  m_velxyz[i] = v1(i);
324  }
325 
326  // transform the angular velocities to moving frame
327  v0 = bn::ublas::zero_vector<NekDouble>(3);
328  v1 = bn::ublas::zero_vector<NekDouble>(3);
329  for (auto it : m_omegaXYZ)
330  {
331  v0(it.first) = it.second;
332  }
333  v1 = bn::ublas::prec_prod(m_ProjMatZ, v0);
334  for (int i = 0; i < 3; ++i)
335  {
336  m_omegaxyz[i] = v1(i);
337  }
338  }
339  else
340  {
341  // for translation only,
342  for (int i = 0; i < m_spacedim; ++i)
343  {
344  m_velxyz[i] = m_velXYZ[i];
345  }
346  }
347 
348  // set the velocities and rotation matrix for enforcement of boundary
349  // conditions in the Incompressible Naveri-Stokes
350  Array<OneD, NekDouble> vel(6, 0.0);
351  // save the linear and angular velocities to be used in enforcing bc
352  for (int i = 0; i < 3; ++i)
353  {
354  vel[i] = m_velxyz[i];
355  vel[i + 3] = m_omegaxyz[i];
356  }
357 
358  auto equ = m_equ.lock();
359  ASSERTL0(equ, "Weak pointer to the equation system is expired");
360  auto FluidEq = std::dynamic_pointer_cast<FluidInterface>(equ);
361  // update the frame velocities
362  FluidEq->SetMovingFrameVelocities(vel);
363  // update the projection matrix
364  FluidEq->SetMovingFrameProjectionMat(m_ProjMatZ);
365  // update the frame angle (with respect to the inertial frame)
366  // this angle is used to update the meta data,
367  // on the other hand, for boundary conditions the projection matrix is used
368  FluidEq->SetMovingFrameAngles(m_theta);
369 }
370 
372 {
373 
374  NekDouble dt = m_session->GetParameter("TimeStep");
375  NekDouble t1 = time + dt;
376  std::map<int, NekDouble> Omega;
377 
378  // Calculate angular velocities at dt
379  // TODO: Generalize to the case with a general 3D rotation support
380  for (int i = 0; i < 3; ++i)
381  {
382  if (m_hasOmega[i])
383  {
384  Omega[i] = 0.5 * (m_omegaXYZ[i] +
385  m_omegaFunction[i]->Evaluate(0., 0., 0., t1));
386  }
387  }
388 
389  // Using the Omega_z
390  m_theta[2] += (Omega[2] * dt);
391 
392  // update the rotation matrix
393  {
394  NekDouble sn, cs;
395  sn = sin(m_theta[2]);
396  cs = cos(m_theta[2]);
397 
398  m_ProjMatZ(0, 0) = cs;
399  m_ProjMatZ(0, 1) = sn;
400  m_ProjMatZ(1, 0) = -sn;
401  m_ProjMatZ(1, 1) = cs;
402  m_ProjMatZ(2, 2) = 1.0;
403  }
404 }
405 
406 /**
407  * @brief Adds the body force, -Omega X u.
408  * @param fields
409  * @param inarray
410  * @param outarray
411  * @param time
412  */
415  const Array<OneD, Array<OneD, NekDouble>> &inarray,
416  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble &time)
417 {
418  boost::ignore_unused(time);
419  // If there is no rotation, body force is zero,
420  // nothing needs to be done here.
421  if (!m_hasRotation)
422  {
423  return;
424  }
425  // frame velocities are already updated in pre_Apply
426  int npoints = fields[0]->GetNpoints();
427  boost::ignore_unused(npoints);
428  addRotation(npoints, outarray, -1., inarray, outarray);
429 }
430 
431 /**
432  * @brief outarray = inarray0 + angVelScale Omega x inarray1
433  */
435  int nPnts, // number of points
436  const Array<OneD, Array<OneD, NekDouble>> &inarray0, NekDouble angVelScale,
437  const Array<OneD, Array<OneD, NekDouble>> &inarray1,
438  Array<OneD, Array<OneD, NekDouble>> &outarray)
439 {
440  ASSERTL0(&inarray1 != &outarray, "inarray1 and outarray "
441  "should not be the same.");
442 
443  // TODO: In case of having support for all three components of Omega,
444  // they should be transformed into the rotating frame first!
445 
446  // In case that the inarray0 and outarry are different, to avoid using
447  // un-initialized array, copy the array first
448  if (&inarray0 != &outarray)
449  {
450  ASSERTL0(inarray0.size() == outarray.size(),
451  "inarray0 and outarray must have same dimentions");
452  for (int i = 0; i < inarray0.size(); ++i)
453  {
454  Vmath::Vcopy(nPnts, inarray0[i], 1, outarray[i], 1);
455  }
456  }
457 
458  if (m_spacedim >= 2 && m_hasOmega[2])
459  {
460  NekDouble cp = m_omegaxyz[2] * angVelScale;
461  NekDouble cm = -1. * cp;
462 
463  Vmath::Svtvp(nPnts, cm, inarray1[1], 1, outarray[0], 1, outarray[0], 1);
464  Vmath::Svtvp(nPnts, cp, inarray1[0], 1, outarray[1], 1, outarray[1], 1);
465  }
466 
467  if (m_spacedim == 3 && m_hasOmega[0])
468  {
469  NekDouble cp = m_omegaxyz[0] * angVelScale;
470  NekDouble cm = -1. * cp;
471 
472  Vmath::Svtvp(nPnts, cp, inarray1[1], 1, outarray[2], 1, outarray[2], 1);
473  Vmath::Svtvp(nPnts, cm, inarray1[2], 1, outarray[1], 1, outarray[1], 1);
474  }
475 
476  if (m_spacedim == 3 && m_hasOmega[1])
477  {
478  NekDouble cp = m_omegaxyz[1] * angVelScale;
479  NekDouble cm = -1. * cp;
480 
481  Vmath::Svtvp(nPnts, cp, inarray1[2], 1, outarray[0], 1, outarray[0], 1);
482  Vmath::Svtvp(nPnts, cm, inarray1[0], 1, outarray[2], 1, outarray[2], 1);
483  }
484 }
485 
488  const Array<OneD, Array<OneD, NekDouble>> &inarray,
489  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble &time)
490 {
491  Update(time);
492  int npoints = fields[0]->GetNpoints();
493  if (m_isH2d && fields[0]->GetWaveSpace())
494  {
495  for (int i = 0; i < m_spacedim; ++i)
496  {
497  if (m_hasVel[i])
498  {
499  Array<OneD, NekDouble> tmpphys(npoints, -m_velxyz[i]);
500  Array<OneD, NekDouble> tmpcoef(npoints);
501  fields[0]->HomogeneousFwdTrans(npoints, tmpphys, tmpcoef);
502  Vmath::Vadd(npoints, tmpcoef, 1, inarray[i], 1, outarray[i], 1);
503  }
504  else if (&inarray != &outarray)
505  {
506  Vmath::Vcopy(npoints, inarray[i], 1, outarray[i], 1);
507  }
508  }
509  }
510  else
511  {
512  int npoints0 = npoints;
513  if (m_isH1d && fields[0]->GetWaveSpace())
514  {
515  npoints0 = m_hasPlane0 ? fields[0]->GetPlane(0)->GetNpoints() : 0;
516  }
517  for (int i = 0; i < m_spacedim; ++i)
518  {
519  if (m_hasVel[i])
520  {
521  Vmath::Sadd(npoints0, -m_velxyz[i], inarray[i], 1, outarray[i],
522  1);
523  if (&inarray != &outarray && npoints != npoints0)
524  {
525  Array<OneD, NekDouble> tmp = outarray[i] + npoints0;
526  Vmath::Vcopy(npoints - npoints0, inarray[i] + npoints0, 1,
527  tmp, 1);
528  }
529  }
530  else if (&inarray != &outarray)
531  {
532  Vmath::Vcopy(npoints, inarray[i], 1, outarray[i], 1);
533  }
534  }
535  if (m_hasRotation)
536  {
537  addRotation(npoints0, outarray, -1., m_coords, outarray);
538  }
539  }
540 }
541 
544  Array<OneD, NekDouble> &theta)
545 {
546  std::map<std::string, std::string> fieldMetaDataMap;
547 
548  // initialize theta to zero
549  for (auto &t : theta)
550  {
551  t = 0.0;
552  }
553 
554  if (m_session->DefinesFunction("InitialConditions"))
555  {
556  for (int i = 0; i < pFields.size(); ++i)
557  {
559 
560  vType = m_session->GetFunctionType("InitialConditions",
561  m_session->GetVariable(i));
562 
563  if (vType == LibUtilities::eFunctionTypeFile)
564  {
565  std::string filename = m_session->GetFunctionFilename(
566  "InitialConditions", m_session->GetVariable(i));
567 
568  fs::path pfilename(filename);
569 
570  // redefine path for parallel file which is in directory
571  if (fs::is_directory(pfilename))
572  {
573  fs::path metafile("Info.xml");
574  fs::path fullpath = pfilename / metafile;
575  filename = LibUtilities::PortablePath(fullpath);
576  }
579  fld->ImportFieldMetaData(filename, fieldMetaDataMap);
580 
581  // check to see if theta is defined
582  if (fieldMetaDataMap != LibUtilities::NullFieldMetaDataMap)
583  {
584  std::vector<std::string> vSuffix = {"_x", "_y", "_z"};
585 
586  for (int j = 0; j < 3; ++j)
587  {
588  std::string sTheta = "Theta" + vSuffix[j];
589  auto iter = fieldMetaDataMap.find(sTheta);
590  if (iter != fieldMetaDataMap.end())
591  {
592  theta[j] =
593  boost::lexical_cast<NekDouble>(iter->second);
594  }
595  }
596 
597  break;
598  }
599 
600  break;
601  }
602  }
603  }
604 }
605 
606 } // namespace SolverUtils
607 } // namespace Nektar
const NekDouble Omega
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
static std::shared_ptr< FieldIO > CreateForFile(const LibUtilities::SessionReaderSharedPtr session, const std::string &filename)
Construct a FieldIO object for a given input filename.
Definition: FieldIO.cpp:226
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
Defines a forcing term to be explicitly applied.
Definition: Forcing.h:73
int m_NumVariable
Number of variables.
Definition: Forcing.h:122
const std::weak_ptr< EquationSystem > m_equ
Weak pointer to equation system using this forcing.
Definition: Forcing.h:118
LibUtilities::SessionReaderSharedPtr m_session
Session reader.
Definition: Forcing.h:116
virtual SOLVER_UTILS_EXPORT void v_PreApply(const Array< OneD, MultiRegions::ExpListSharedPtr > &fields, const Array< OneD, Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble &time) override
void addRotation(int npoints, const Array< OneD, Array< OneD, NekDouble >> &inarray0, NekDouble angVelScale, const Array< OneD, Array< OneD, NekDouble >> &inarray1, Array< OneD, Array< OneD, NekDouble >> &outarray)
outarray = inarray0 + angVelScale Omega x inarray1
std::map< int, LibUtilities::EquationSharedPtr > m_omegaFunction
void CheckForRestartTheta(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, Array< OneD, NekDouble > &theta)
virtual SOLVER_UTILS_EXPORT void v_Apply(const Array< OneD, MultiRegions::ExpListSharedPtr > &fields, const Array< OneD, Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble &time) override
Adds the body force, -Omega X u.
virtual SOLVER_UTILS_EXPORT void v_InitObject(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const unsigned int &pNumForcingFields, const TiXmlElement *pForce) override
Initialise the forcing module.
std::map< int, LibUtilities::EquationSharedPtr > m_velFunction
void Update(const NekDouble &time)
Updates the forcing array with the current required forcing.
std::shared_ptr< FieldIO > FieldIOSharedPtr
Definition: FieldIO.h:327
std::string PortablePath(const boost::filesystem::path &path)
create portable path on different platforms for boost::filesystem path
Definition: FileSystem.cpp:45
std::shared_ptr< SessionReader > SessionReaderSharedPtr
static FieldMetaDataMap NullFieldMetaDataMap
Definition: FieldIO.h:53
ForcingFactory & GetForcingFactory()
Declaration of the forcing factory singleton.
Definition: Forcing.cpp:44
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
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 Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition: Vmath.cpp:359
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