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>
49 
50 using namespace std;
51 
52 namespace Nektar
53 {
54 namespace SolverUtils
55 {
56 
57 std::string ForcingMovingReferenceFrame::classNameBody = GetForcingFactory().
58  RegisterCreatorFunction("MovingReferenceFrame",
59  ForcingMovingReferenceFrame::create,
60  "Moving Frame");
61 std::string ForcingMovingReferenceFrame::classNameField = GetForcingFactory().
62  RegisterCreatorFunction("Field",
63  ForcingMovingReferenceFrame::create,
64  "Field Forcing");
65 
66 /**
67  * @brief
68  * @param pSession
69  * @param pEquation
70  */
71 ForcingMovingReferenceFrame::ForcingMovingReferenceFrame(
73  const std::weak_ptr<EquationSystem> &pEquation)
74  : Forcing(pSession, pEquation)
75 {
76 }
77 
78 
79 /**
80  * @brief Initialise the forcing module
81  * @param pFields
82  * @param pNumForcingFields
83  * @param pForce
84  */
87  const unsigned int &pNumForcingFields,
88  const TiXmlElement *pForce)
89 {
90  boost::ignore_unused(pNumForcingFields);
91  m_session->MatchSolverInfo("Homogeneous", "1D", m_isH1d, false);
92  m_session->MatchSolverInfo("Homogeneous", "2D", m_isH2d, false);
93  bool singleMode, halfMode;
94  m_session->MatchSolverInfo("ModeType", "SingleMode", singleMode, false);
95  m_session->MatchSolverInfo("ModeType", "HalfMode", halfMode, false);
96  if (singleMode || halfMode)
97  {
98  m_isH1d = false;
99  }
100 
101  int npoints = pFields[0]->GetNpoints();
102  int expdim = m_isH2d ? 1 : pFields[0]->GetGraph()
103  ->GetMeshDimension();
104  m_spacedim = expdim + (m_isH1d ? 1 : 0) + (m_isH2d ? 2 : 0);
106 
107  m_hasPlane0 = true;
108  if (m_isH1d)
109  {
110  m_hasPlane0 = pFields[0]->GetZIDs()[0] == 0;
111  }
112 
113  const TiXmlElement *funcNameElmt = pForce->FirstChildElement(
114  "FRAMEVELOCITY");
115  ASSERTL0(funcNameElmt, "Requires FRAMEVELOCITY tag specifying function "
116  "name which prescribes velocity of the moving "
117  "frame.");
118 
119  m_funcName = funcNameElmt->GetText();
120  ASSERTL0(m_session->DefinesFunction(m_funcName),
121  "Function '" + m_funcName + "' not defined.");
122 
123  for (int i = 0; i < 6; ++i)
124  {
125  m_frameVelocity[i] = 0.;
126  }
127 
128  m_hasRotation = false;
129  //frame linear velocity
130  for (int i = 0; i < m_spacedim; ++i)
131  {
132  std::string s_FieldStr = m_session->GetVariable(i);
133 
134  if (m_session->DefinesFunction(m_funcName, s_FieldStr))
135  {
137  GetFunction(m_funcName, s_FieldStr);
138  }
139  }
140 
141  if (expdim==1)
142  {
143  return;
144  }
145  //frame angular velocity
146  std::vector<std::string> angularVar = {"Omega_x", "Omega_y", "Omega_z"};
147  for (int i = (expdim==2 ? 2 : 0); i < 3; ++i)
148  {
149  std::string s_FieldStr = angularVar[i];
150 
151  if (m_session->DefinesFunction(m_funcName, s_FieldStr))
152  {
153  m_hasRotation = true;
155  GetFunction(m_funcName, s_FieldStr);
156  }
157  }
158  if (m_hasRotation)
159  {
161  for(int j=0; j<m_spacedim; ++j)
162  {
163  m_coords[j] = Array<OneD, NekDouble>(npoints);
164  }
165  for(int j=m_spacedim; j<3; ++j)
166  {
168  }
169  pFields[0]->GetCoords(m_coords[0], m_coords[1], m_coords[2]);
170  std::vector<std::string> pivotVar = {"x0", "y0", "z0"};
171  for (int i = 0; i < m_spacedim; ++i)
172  {
173  std::string s_FieldStr = pivotVar[i];
174 
175  if (m_session->DefinesFunction(m_funcName, s_FieldStr))
176  {
177  NekDouble x0 = m_session->GetFunction(m_funcName,
178  s_FieldStr)->Evaluate();
179  Vmath::Sadd(npoints, -x0, m_coords[i], 1, m_coords[i], 1);
180  }
181  }
182  }
183 }
184 
185 /**
186  * @brief Updates the forcing array with the current required forcing.
187  * @param pFields
188  * @param time
189  */
191 {
192  for (auto it : m_frameFunction)
193  {
194  m_frameVelocity[it.first] = it.second->Evaluate(0., 0., 0., time);
195  }
196 }
197 
198 /**
199  * @brief Adds the body force, -Omega X u.
200  * @param fields
201  * @param inarray
202  * @param outarray
203  * @param time
204  */
207  const Array<OneD, Array<OneD, NekDouble> > &inarray,
208  Array<OneD, Array<OneD, NekDouble> > &outarray,
209  const NekDouble &time)
210 {
211  // If there is no rotation, body force is zero,
212  // nothing needs to be done here.
213  if (!m_hasRotation)
214  {
215  return;
216  }
217  Update(time);
218  int npoints = fields[0]->GetNpoints();
219  addRotation(npoints, outarray, -1., inarray, outarray);
220 }
221 
222 /**
223  * @brief outarray = inarray0 + angVelScale Omega x inarray1
224  */
226  int npoints,
227  const Array<OneD, Array<OneD, NekDouble> > &inarray0,
228  NekDouble angVelScale,
229  const Array<OneD, Array<OneD, NekDouble> > &inarray1,
230  Array<OneD, Array<OneD, NekDouble> > &outarray)
231 {
232  ASSERTL0(&inarray1!=&outarray, "inarray1 and outarray "
233  "should have different addresses.");
234 
235  if ((m_spacedim>=2 && &inarray0 != &outarray) ||
236  (m_spacedim>=2 && m_frameFunction.count(m_spacedim+2)) )
237  {
238  Vmath::Svtvp(npoints,
239  -m_frameVelocity[m_spacedim+2]*angVelScale,
240  inarray1[1], 1,
241  inarray0[0], 1,
242  outarray[0], 1);
243  Vmath::Svtvp(npoints,
244  +m_frameVelocity[m_spacedim+2]*angVelScale,
245  inarray1[0], 1,
246  inarray0[1], 1,
247  outarray[1], 1);
248  }
249 
250  if ((m_spacedim==3 && &inarray0 != &outarray) ||
251  (m_spacedim==3 && m_frameFunction.count(m_spacedim+0)) )
252  {
253  Vmath::Svtvp(npoints,
254  +m_frameVelocity[m_spacedim+0]*angVelScale,
255  inarray1[1], 1,
256  inarray0[2], 1,
257  outarray[2], 1);
258  }
259 
260  if (m_spacedim==3 && m_frameFunction.count(m_spacedim+0))
261  {
262  Vmath::Svtvp(npoints,
263  -m_frameVelocity[m_spacedim+0]*angVelScale,
264  inarray1[2], 1,
265  outarray[1], 1,
266  outarray[1], 1);
267  }
268 
269  if (m_spacedim==3 && m_frameFunction.count(m_spacedim+1))
270  {
271  Vmath::Svtvp(npoints,
272  +m_frameVelocity[m_spacedim+1]*angVelScale,
273  inarray1[2], 1,
274  outarray[0], 1,
275  outarray[0], 1);
276  Vmath::Svtvp(npoints,
277  -m_frameVelocity[m_spacedim+1]*angVelScale,
278  inarray1[0], 1,
279  outarray[2], 1,
280  outarray[2], 1);
281  }
282 }
283 
286  const Array<OneD, Array<OneD, NekDouble> > &inarray,
287  Array<OneD, Array<OneD, NekDouble> > &outarray,
288  const NekDouble &time)
289 {
290  Update(time);
291  int npoints = fields[0]->GetNpoints();
292  if (m_isH2d && fields[0]->GetWaveSpace())
293  {
294  for (int i=0; i<m_spacedim; ++i)
295  {
296  if (m_frameFunction.count(i))
297  {
298  Array<OneD, NekDouble> tmpphys(npoints, -m_frameVelocity[i]);
299  Array<OneD, NekDouble> tmpcoef(npoints);
300  fields[0]->HomogeneousFwdTrans(tmpphys, tmpcoef);
301  Vmath::Vadd(npoints, tmpcoef, 1, inarray[i], 1, outarray[i], 1);
302  }
303  else if (&inarray != &outarray)
304  {
305  Vmath::Vcopy(npoints, inarray[i], 1, outarray[i], 1);
306  }
307  }
308  }
309  else
310  {
311  int npoints0 = npoints;
312  if (m_isH1d && fields[0]->GetWaveSpace())
313  {
314  npoints0 = m_hasPlane0 ? fields[0]->GetPlane(0)->GetNpoints() : 0;
315  }
316  for (int i=0; i<m_spacedim; ++i)
317  {
318  if (m_frameFunction.count(i))
319  {
320  Vmath::Sadd(npoints0, -m_frameVelocity[i], inarray[i], 1, outarray[i], 1);
321  if (&inarray != &outarray && npoints != npoints0)
322  {
323  Array<OneD, NekDouble> tmp = outarray[i]+npoints0;
324  Vmath::Vcopy(npoints - npoints0, inarray[i] + npoints0, 1, tmp, 1);
325  }
326  }
327  else if (&inarray != &outarray)
328  {
329  Vmath::Vcopy(npoints, inarray[i], 1, outarray[i], 1);
330  }
331  }
332  if (m_hasRotation)
333  {
334  addRotation(npoints0, outarray, -1., m_coords, outarray);
335  }
336  }
337 }
338 
339 }
340 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
Defines a forcing term to be explicitly applied.
Definition: Forcing.h:73
int m_NumVariable
Number of variables.
Definition: Forcing.h:124
SOLVER_UTILS_EXPORT SessionFunctionSharedPtr GetFunction(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const LibUtilities::SessionReaderSharedPtr &pSession, std::string pName, bool pCache=false)
Get a SessionFunction by name.
Definition: Forcing.cpp:202
LibUtilities::SessionReaderSharedPtr m_session
Session reader.
Definition: Forcing.h:118
virtual SOLVER_UTILS_EXPORT void v_InitObject(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const unsigned int &pNumForcingFields, const TiXmlElement *pForce)
Initialise the forcing module.
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
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)
Adds the body force, -Omega X u.
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)
std::map< int, LibUtilities::EquationSharedPtr > m_frameFunction
void Update(const NekDouble &time)
Updates the forcing array with the current required forcing.
Array< OneD, Array< OneD, NekDouble > > m_coords
std::shared_ptr< SessionReader > SessionReaderSharedPtr
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:1
static Array< OneD, NekDouble > NullNekDouble1DArray
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:565
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:322
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add vector y = alpha - x.
Definition: Vmath.cpp:341
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1199