Nektar++
FilterMovingBody.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File FilterMovingBody.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: Output moving body forces during time-stepping.
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
41 #include <iomanip>
42 
43 using namespace std;
44 
45 namespace Nektar
46 {
47 
48 std::string FilterMovingBody::className =
50  "MovingBody", FilterMovingBody::create, "Moving Body Filter");
51 /**
52  *
53  */
54 FilterMovingBody::FilterMovingBody(
56  const std::weak_ptr<SolverUtils::EquationSystem> &pEquation,
57  const ParamMap &pParams)
58  : Filter(pSession, pEquation)
59 {
60  // OutputFile
61  auto it = pParams.find("OutputFile");
62  if (it == pParams.end())
63  {
64  m_outputFile_fce = pSession->GetSessionName();
65  m_outputFile_mot = pSession->GetSessionName();
66  }
67  else
68  {
69  ASSERTL0(it->second.length() > 0, "Missing parameter 'OutputFile'.");
70 
71  m_outputFile_fce = it->second;
72  m_outputFile_mot = it->second;
73  }
74  if (!(m_outputFile_fce.length() >= 4 &&
75  m_outputFile_fce.substr(m_outputFile_fce.length() - 4) == ".fce"))
76  {
77  m_outputFile_fce += ".fce";
78  }
79  if (!(m_outputFile_mot.length() >= 4 &&
80  m_outputFile_mot.substr(m_outputFile_mot.length() - 4) == ".mot"))
81  {
82  m_outputFile_mot += ".mot";
83  }
84 
85  // OutputFrequency
86  it = pParams.find("OutputFrequency");
87  if (it == pParams.end())
88  {
90  }
91  else
92  {
93  LibUtilities::Equation equ(m_session->GetInterpreter(), it->second);
94  m_outputFrequency = round(equ.Evaluate());
95  }
96 
97  pSession->MatchSolverInfo("Homogeneous", "1D", m_isHomogeneous1D, false);
98  ASSERTL0(m_isHomogeneous1D, "Moving Body implemented just for 3D "
99  "Homogeneous 1D discetisations.");
100 
101  // Boundary (to calculate the forces)
102  it = pParams.find("Boundary");
103  ASSERTL0(it != pParams.end(), "Missing parameter 'Boundary'.");
104  ASSERTL0(it->second.length() > 0, "Missing parameter 'Boundary'.");
105  m_BoundaryString = it->second;
106 }
107 
108 /**
109  *
110  */
112 {
113 }
114 
115 /**
116  *
117  */
120  const NekDouble &time)
121 {
122  m_index_f = 0;
123  m_index_m = 0;
125  // Parse the boundary regions into a list.
126  std::string::size_type FirstInd = m_BoundaryString.find_first_of('[') + 1;
127  std::string::size_type LastInd = m_BoundaryString.find_last_of(']') - 1;
128 
129  ASSERTL0(FirstInd <= LastInd,
130  (std::string("Error reading boundary region definition:") +
132  .c_str());
133 
134  std::string IndString =
135  m_BoundaryString.substr(FirstInd, LastInd - FirstInd + 1);
136 
137  bool parseGood =
139 
140  ASSERTL0(parseGood && !m_boundaryRegionsIdList.empty(),
141  (std::string("Unable to read boundary regions index "
142  "range for FilterAeroForces: ") +
143  IndString)
144  .c_str());
145 
146  // determine what boundary regions need to be considered
147  unsigned int numBoundaryRegions = pFields[0]->GetBndConditions().size();
148 
150  numBoundaryRegions, 0);
151 
152  SpatialDomains::BoundaryConditions bcs(m_session, pFields[0]->GetGraph());
153 
155  bcs.GetBoundaryRegions();
156 
157  int cnt = 0;
158  for (auto &it : bregions)
159  {
162  it.first) != m_boundaryRegionsIdList.end())
163  {
164  m_boundaryRegionIsInList[cnt] = 1;
165  }
166  ++cnt;
167  }
168 
169  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
170 
171  if (vComm->GetRank() == 0)
172  {
173  // Open output stream for cable forces
174  m_outputStream[0].open(m_outputFile_fce.c_str());
175  m_outputStream[0] << "#";
176  m_outputStream[0].width(7);
177  m_outputStream[0] << "Time";
178  m_outputStream[0].width(15);
179  m_outputStream[0] << "z";
180  m_outputStream[0].width(15);
181  m_outputStream[0] << "Fx (press)";
182  m_outputStream[0].width(15);
183  m_outputStream[0] << "Fx (visc)";
184  m_outputStream[0].width(15);
185  m_outputStream[0] << "Fx (tot)";
186  m_outputStream[0].width(15);
187  m_outputStream[0] << "Fy (press)";
188  m_outputStream[0].width(15);
189  m_outputStream[0] << "Fy (visc)";
190  m_outputStream[0].width(15);
191  m_outputStream[0] << "Fy (tot)";
192  m_outputStream[0] << endl;
193 
194  // Open output stream for cable motions
195  m_outputStream[1].open(m_outputFile_mot.c_str());
196  m_outputStream[1] << "#";
197  m_outputStream[1].width(7);
198  m_outputStream[1] << "Time";
199  m_outputStream[1].width(15);
200  m_outputStream[1] << "z";
201  m_outputStream[1].width(15);
202  m_outputStream[1] << "Disp_x";
203  m_outputStream[1].width(15);
204  m_outputStream[1] << "Vel_x";
205  m_outputStream[1].width(15);
206  m_outputStream[1] << "Acel_x";
207  m_outputStream[1].width(15);
208  m_outputStream[1] << "Disp_y";
209  m_outputStream[1].width(15);
210  m_outputStream[1] << "Vel_y";
211  m_outputStream[1].width(15);
212  m_outputStream[1] << "Acel_y";
213  m_outputStream[1] << endl;
214  }
215 }
216 
217 /**
218  *
219  */
221  const LibUtilities::SessionReaderSharedPtr &pSession,
223  Array<OneD, NekDouble> &Aeroforces, const NekDouble &time)
224 {
225  int n, cnt, elmtid, nq, offset, boundary;
226  int nt = pFields[0]->GetNpoints();
227  int dim = pFields.size() - 1;
228 
230  Array<OneD, int> BoundarytoElmtID;
231  Array<OneD, int> BoundarytoTraceID;
233 
238 
242 
246 
247  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
248  LibUtilities::CommSharedPtr vRowComm = vComm->GetRowComm();
249  LibUtilities::CommSharedPtr vColComm = vComm->GetColumnComm();
250  LibUtilities::CommSharedPtr vCColComm = vColComm->GetColumnComm();
251 
252  // set up storage space for forces on all the planes (z-positions)
253  // on each processors some of them will remain empty as we may
254  // have just few planes per processor
255  int Num_z_pos = pFields[0]->GetHomogeneousBasis()->GetNumModes();
256  Array<OneD, NekDouble> Fx(Num_z_pos, 0.0);
257  Array<OneD, NekDouble> Fxp(Num_z_pos, 0.0);
258  Array<OneD, NekDouble> Fxv(Num_z_pos, 0.0);
259  Array<OneD, NekDouble> Fy(Num_z_pos, 0.0);
260  Array<OneD, NekDouble> Fyp(Num_z_pos, 0.0);
261  Array<OneD, NekDouble> Fyv(Num_z_pos, 0.0);
262 
263  NekDouble rho = (pSession->DefinesParameter("rho"))
264  ? (pSession->GetParameter("rho"))
265  : 1;
266  NekDouble mu = rho * pSession->GetParameter("Kinvis");
267 
268  for (int i = 0; i < pFields.size(); ++i)
269  {
270  pFields[i]->SetWaveSpace(false);
271  pFields[i]->BwdTrans(pFields[i]->GetCoeffs(), pFields[i]->UpdatePhys());
272  pFields[i]->SetPhysState(true);
273  }
274 
275  // Get the number of local planes on the process and their IDs
276  // to properly locate the forces in the Fx, Fy etc. vectors.
278  ZIDs = pFields[0]->GetZIDs();
279  int local_planes = ZIDs.size();
280 
281  // Homogeneous 1D case Compute forces on all WALL boundaries
282  // This only has to be done on the zero (mean) Fourier mode.
283  for (int plane = 0; plane < local_planes; plane++)
284  {
285  pFields[0]->GetPlane(plane)->GetBoundaryToElmtMap(BoundarytoElmtID,
286  BoundarytoTraceID);
287  BndExp = pFields[0]->GetPlane(plane)->GetBndCondExpansions();
289 
290  // loop over the types of boundary conditions
291  for (cnt = n = 0; n < BndExp.size(); ++n)
292  {
293  if (m_boundaryRegionIsInList[n] == 1)
294  {
295  for (int i = 0; i < BndExp[n]->GetExpSize(); ++i, cnt++)
296  {
297  // find element of this expansion.
298  elmtid = BoundarytoElmtID[cnt];
299  elmt = pFields[0]->GetPlane(plane)->GetExp(elmtid);
300  nq = elmt->GetTotPoints();
301  offset =
302  pFields[0]->GetPlane(plane)->GetPhys_Offset(elmtid);
303 
304  // Initialise local arrays for the velocity
305  // gradients size of total number of quadrature
306  // points for each element (hence local).
307  for (int j = 0; j < dim; ++j)
308  {
309  gradU[j] = Array<OneD, NekDouble>(nq, 0.0);
310  gradV[j] = Array<OneD, NekDouble>(nq, 0.0);
311  gradW[j] = Array<OneD, NekDouble>(nq, 0.0);
312  }
313 
314  // identify boundary of element
315  boundary = BoundarytoTraceID[cnt];
316 
317  // Extract fields
318  U = pFields[0]->GetPlane(plane)->GetPhys() + offset;
319  V = pFields[1]->GetPlane(plane)->GetPhys() + offset;
320  P = pFields[3]->GetPlane(plane)->GetPhys() + offset;
321 
322  // compute the gradients
323  elmt->PhysDeriv(U, gradU[0], gradU[1]);
324  elmt->PhysDeriv(V, gradV[0], gradV[1]);
325 
326  // Get face 1D expansion from element expansion
327  bc = BndExp[n]->GetExp(i)->as<LocalRegions::Expansion1D>();
328 
329  // number of points on the boundary
330  int nbc = bc->GetTotPoints();
331 
332  // several vectors for computing the forces
333  Array<OneD, NekDouble> Pb(nbc, 0.0);
334 
335  for (int j = 0; j < dim; ++j)
336  {
337  fgradU[j] = Array<OneD, NekDouble>(nbc, 0.0);
338  fgradV[j] = Array<OneD, NekDouble>(nbc, 0.0);
339  }
340 
341  Array<OneD, NekDouble> drag_t(nbc, 0.0);
342  Array<OneD, NekDouble> lift_t(nbc, 0.0);
343  Array<OneD, NekDouble> drag_p(nbc, 0.0);
344  Array<OneD, NekDouble> lift_p(nbc, 0.0);
345  Array<OneD, NekDouble> temp(nbc, 0.0);
346  Array<OneD, NekDouble> temp2(nbc, 0.0);
347 
348  // identify boundary of element .
349  boundary = BoundarytoTraceID[cnt];
350 
351  // extraction of the pressure and wss on the
352  // boundary of the element
353  elmt->GetTracePhysVals(boundary, bc, P, Pb);
354 
355  for (int j = 0; j < dim; ++j)
356  {
357  elmt->GetTracePhysVals(boundary, bc, gradU[j],
358  fgradU[j]);
359  elmt->GetTracePhysVals(boundary, bc, gradV[j],
360  fgradV[j]);
361  }
362 
363  // normals of the element
364  const Array<OneD, Array<OneD, NekDouble>> &normals =
365  elmt->GetTraceNormal(boundary);
366 
367  //
368  // Compute viscous tractive forces on wall from
369  //
370  // t_i = - T_ij * n_j (minus sign for force
371  // exerted BY fluid ON wall),
372  //
373  // where
374  //
375  // T_ij = viscous stress tensor (here in Cartesian
376  // coords)
377  // dU_i dU_j
378  // = RHO * KINVIS * ( ---- + ---- ) .
379  // dx_j dx_i
380 
381  // a) DRAG TERMS
382  //-rho*kinvis*(2*du/dx*nx+(du/dy+dv/dx)*ny)
383 
384  Vmath::Vadd(nbc, fgradU[1], 1, fgradV[0], 1, drag_t, 1);
385  Vmath::Vmul(nbc, drag_t, 1, normals[1], 1, drag_t, 1);
386 
387  Vmath::Smul(nbc, 2.0, fgradU[0], 1, fgradU[0], 1);
388  Vmath::Vmul(nbc, fgradU[0], 1, normals[0], 1, temp2, 1);
389  Vmath::Smul(nbc, 0.5, fgradU[0], 1, fgradU[0], 1);
390 
391  Vmath::Vadd(nbc, temp2, 1, drag_t, 1, drag_t, 1);
392  Vmath::Smul(nbc, -mu, drag_t, 1, drag_t, 1);
393 
394  // zero temporary storage vector
395  Vmath::Zero(nbc, temp, 0.0);
396  Vmath::Zero(nbc, temp2, 0.0);
397 
398  // b) LIFT TERMS
399  //-rho*kinvis*(2*dv/dy*ny+(du/dy+dv/dx)*nx)
400 
401  Vmath::Vadd(nbc, fgradU[1], 1, fgradV[0], 1, lift_t, 1);
402  Vmath::Vmul(nbc, lift_t, 1, normals[0], 1, lift_t, 1);
403 
404  Vmath::Smul(nbc, 2.0, fgradV[1], 1, fgradV[1], 1);
405  Vmath::Vmul(nbc, fgradV[1], 1, normals[1], 1, temp2, 1);
406  Vmath::Smul(nbc, -0.5, fgradV[1], 1, fgradV[1], 1);
407 
408  Vmath::Vadd(nbc, temp2, 1, lift_t, 1, lift_t, 1);
409  Vmath::Smul(nbc, -mu, lift_t, 1, lift_t, 1);
410 
411  // Compute normal tractive forces on all WALL
412  // boundaries
413 
414  Vmath::Vvtvp(nbc, Pb, 1, normals[0], 1, drag_p, 1, drag_p,
415  1);
416  Vmath::Vvtvp(nbc, Pb, 1, normals[1], 1, lift_p, 1, lift_p,
417  1);
418 
419  // integration over the boundary
420  Fxv[ZIDs[plane]] += bc->Integral(drag_t);
421  Fyv[ZIDs[plane]] += bc->Integral(lift_t);
422 
423  Fxp[ZIDs[plane]] += bc->Integral(drag_p);
424  Fyp[ZIDs[plane]] += bc->Integral(lift_p);
425  }
426  }
427  else
428  {
429  cnt += BndExp[n]->GetExpSize();
430  }
431  }
432  }
433 
434  for (int i = 0; i < pFields.size(); ++i)
435  {
436  pFields[i]->SetWaveSpace(true);
437  pFields[i]->BwdTrans(pFields[i]->GetCoeffs(), pFields[i]->UpdatePhys());
438  pFields[i]->SetPhysState(false);
439  }
440 
441  // In case we are using an hybrid parallelisation we need
442  // to reduce the forces on the same plane coming from
443  // different mesh partitions.
444  // It is quite an expensive communication, therefore
445  // we check to make sure it is actually required.
446 
447  if (vComm->GetRowComm()->GetSize() > 0)
448  {
449  // NOTE 1: We can eventually sum the viscous and pressure
450  // component before doing the communication, thus
451  // reducing by a factor 2 the communication.
452  // NOTE 2: We may want to set up in the Comm class an AllReduce
453  // routine wich can handle arrays more efficiently
454  for (int plane = 0; plane < local_planes; plane++)
455  {
456  vRowComm->AllReduce(Fxp[ZIDs[plane]], LibUtilities::ReduceSum);
457  vRowComm->AllReduce(Fxv[ZIDs[plane]], LibUtilities::ReduceSum);
458  vRowComm->AllReduce(Fyp[ZIDs[plane]], LibUtilities::ReduceSum);
459  vRowComm->AllReduce(Fyv[ZIDs[plane]], LibUtilities::ReduceSum);
460  }
461  }
462 
463  // At this point on rank (0,n) of the Mesh partion communicator we have
464  // the total areo forces on the planes which are on the same column
465  // communicator. Since the planes are scattered on different processors
466  // some of the entries of the vector Fxp, Fxp etc. are still zero.
467  // Now we need to reduce the values on a single vector on rank (0,0) of the
468  // global communicator.
469  if (!pSession->DefinesSolverInfo("HomoStrip"))
470  {
471  if (vComm->GetRowComm()->GetRank() == 0)
472  {
473  for (int z = 0; z < Num_z_pos; z++)
474  {
475  vColComm->AllReduce(Fxp[z], LibUtilities::ReduceSum);
476  vColComm->AllReduce(Fxv[z], LibUtilities::ReduceSum);
477  vColComm->AllReduce(Fyp[z], LibUtilities::ReduceSum);
478  vColComm->AllReduce(Fyv[z], LibUtilities::ReduceSum);
479  }
480  }
481  }
482  else
483  {
484  if (vComm->GetRowComm()->GetRank() == 0)
485  {
486  for (int z = 0; z < Num_z_pos; z++)
487  {
488  vCColComm->AllReduce(Fxp[z], LibUtilities::ReduceSum);
489  vCColComm->AllReduce(Fxv[z], LibUtilities::ReduceSum);
490  vCColComm->AllReduce(Fyp[z], LibUtilities::ReduceSum);
491  vCColComm->AllReduce(Fyv[z], LibUtilities::ReduceSum);
492  }
493  }
494  }
495 
496  if (!pSession->DefinesSolverInfo("HomoStrip"))
497  {
498  // set the forces imparted on the cable's wall
499  for (int plane = 0; plane < local_planes; plane++)
500  {
501  Aeroforces[plane] = Fxp[ZIDs[plane]] + Fxv[ZIDs[plane]];
502  Aeroforces[plane + local_planes] =
503  Fyp[ZIDs[plane]] + Fyv[ZIDs[plane]];
504  }
505 
506  // Only output every m_outputFrequency.
507  if ((m_index_f++) % m_outputFrequency)
508  {
509  return;
510  }
511 
512  // At thi point in rank (0,0) we have the full vectors
513  // containing Fxp,Fxv,Fyp and Fyv where different positions
514  // in the vectors correspond to different planes.
515  // Here we write it to file. We do it just on one porcess
516 
517  Array<OneD, NekDouble> z_coords(Num_z_pos, 0.0);
519  pFields[0]->GetHomogeneousBasis()->GetZ();
520 
521  NekDouble LZ;
522  pSession->LoadParameter("LZ", LZ);
523  Vmath::Smul(Num_z_pos, LZ / 2.0, pts, 1, z_coords, 1);
524  Vmath::Sadd(Num_z_pos, LZ / 2.0, z_coords, 1, z_coords, 1);
525  if (vComm->GetRank() == 0)
526  {
527 
528  Vmath::Vadd(Num_z_pos, Fxp, 1, Fxv, 1, Fx, 1);
529  Vmath::Vadd(Num_z_pos, Fyp, 1, Fyv, 1, Fy, 1);
530 
531  for (int i = 0; i < Num_z_pos; i++)
532  {
533  m_outputStream[0].width(8);
534  m_outputStream[0] << setprecision(6) << time;
535 
536  m_outputStream[0].width(15);
537  m_outputStream[0] << setprecision(6) << z_coords[i];
538 
539  m_outputStream[0].width(15);
540  m_outputStream[0] << setprecision(8) << Fxp[i];
541  m_outputStream[0].width(15);
542  m_outputStream[0] << setprecision(8) << Fxv[i];
543  m_outputStream[0].width(15);
544  m_outputStream[0] << setprecision(8) << Fx[i];
545 
546  m_outputStream[0].width(15);
547  m_outputStream[0] << setprecision(8) << Fyp[i];
548  m_outputStream[0].width(15);
549  m_outputStream[0] << setprecision(8) << Fyv[i];
550  m_outputStream[0].width(15);
551  m_outputStream[0] << setprecision(8) << Fy[i];
552  m_outputStream[0] << endl;
553  }
554  }
555  }
556  else
557  {
558  // average the forces over local planes for each processor
559  Array<OneD, NekDouble> fces(6, 0.0);
560  for (int plane = 0; plane < local_planes; plane++)
561  {
562  fces[0] += Fxp[ZIDs[plane]] + Fxv[ZIDs[plane]];
563  fces[1] += Fyp[ZIDs[plane]] + Fyv[ZIDs[plane]];
564  fces[2] += Fxp[ZIDs[plane]];
565  fces[3] += Fyp[ZIDs[plane]];
566  fces[4] += Fxv[ZIDs[plane]];
567  fces[5] += Fyv[ZIDs[plane]];
568  }
569 
570  fces[0] = fces[0] / local_planes;
571  fces[1] = fces[1] / local_planes;
572  fces[2] = fces[2] / local_planes;
573  fces[3] = fces[3] / local_planes;
574  fces[4] = fces[4] / local_planes;
575  fces[5] = fces[5] / local_planes;
576 
577  // average the forces over communicators within each strip
578  vCColComm->AllReduce(fces[0], LibUtilities::ReduceSum);
579  vCColComm->AllReduce(fces[1], LibUtilities::ReduceSum);
580  vCColComm->AllReduce(fces[2], LibUtilities::ReduceSum);
581  vCColComm->AllReduce(fces[3], LibUtilities::ReduceSum);
582  vCColComm->AllReduce(fces[4], LibUtilities::ReduceSum);
583  vCColComm->AllReduce(fces[5], LibUtilities::ReduceSum);
584 
585  int npts = vComm->GetColumnComm()->GetColumnComm()->GetSize();
586 
587  fces[0] = fces[0] / npts;
588  fces[1] = fces[1] / npts;
589  fces[2] = fces[2] / npts;
590  fces[3] = fces[3] / npts;
591  fces[4] = fces[4] / npts;
592  fces[5] = fces[5] / npts;
593 
594  for (int plane = 0; plane < local_planes; plane++)
595  {
596  Aeroforces[plane] = fces[0];
597  Aeroforces[plane + local_planes] = fces[1];
598  }
599 
600  // Only output every m_outputFrequency.
602  {
603  return;
604  }
605 
606  int colrank = vColComm->GetRank();
607  int nstrips;
608 
609  NekDouble DistStrip;
610 
611  pSession->LoadParameter("Strip_Z", nstrips);
612  pSession->LoadParameter("DistStrip", DistStrip);
613 
614  Array<OneD, NekDouble> z_coords(nstrips);
615  for (int i = 0; i < nstrips; i++)
616  {
617  z_coords[i] = i * DistStrip;
618  }
619 
620  if (colrank == 0)
621  {
622  m_outputStream[0].width(8);
623  m_outputStream[0] << setprecision(6) << time;
624 
625  m_outputStream[0].width(15);
626  m_outputStream[0] << setprecision(6) << z_coords[0];
627 
628  m_outputStream[0].width(15);
629  m_outputStream[0] << setprecision(8) << fces[2];
630  m_outputStream[0].width(15);
631  m_outputStream[0] << setprecision(8) << fces[4];
632  m_outputStream[0].width(15);
633  m_outputStream[0] << setprecision(8) << fces[0];
634 
635  m_outputStream[0].width(15);
636  m_outputStream[0] << setprecision(8) << fces[3];
637  m_outputStream[0].width(15);
638  m_outputStream[0] << setprecision(8) << fces[5];
639  m_outputStream[0].width(15);
640  m_outputStream[0] << setprecision(8) << fces[1];
641  m_outputStream[0] << endl;
642 
643  for (int i = 1; i < nstrips; i++)
644  {
645  vColComm->Recv(i, fces);
646 
647  m_outputStream[0].width(8);
648  m_outputStream[0] << setprecision(6) << time;
649 
650  m_outputStream[0].width(15);
651  m_outputStream[0] << setprecision(6) << z_coords[i];
652 
653  m_outputStream[0].width(15);
654  m_outputStream[0] << setprecision(8) << fces[2];
655  m_outputStream[0].width(15);
656  m_outputStream[0] << setprecision(8) << fces[4];
657  m_outputStream[0].width(15);
658  m_outputStream[0] << setprecision(8) << fces[0];
659 
660  m_outputStream[0].width(15);
661  m_outputStream[0] << setprecision(8) << fces[3];
662  m_outputStream[0].width(15);
663  m_outputStream[0] << setprecision(8) << fces[5];
664  m_outputStream[0].width(15);
665  m_outputStream[0] << setprecision(8) << fces[1];
666  m_outputStream[0] << endl;
667  }
668  }
669  else
670  {
671  for (int i = 1; i < nstrips; i++)
672  {
673  if (colrank == i)
674  {
675  vColComm->Send(0, fces);
676  }
677  }
678  }
679  }
680 }
681 
682 /**
683  *
684  */
686  const LibUtilities::SessionReaderSharedPtr &pSession,
688  Array<OneD, NekDouble> &MotionVars, const NekDouble &time)
689 {
690  // Only output every m_outputFrequency.
691  if ((m_index_m++) % m_outputFrequency)
692  {
693  return;
694  }
695 
696  int npts;
697  // Length of the cable
698  NekDouble Length;
699 
700  if (!pSession->DefinesSolverInfo("HomoStrip"))
701  {
702  pSession->LoadParameter("LZ", Length);
703  npts = m_session->GetParameter("HomModesZ");
704  }
705  else
706  {
707  pSession->LoadParameter("LC", Length);
708  npts = m_session->GetParameter("HomStructModesZ");
709  }
710 
711  NekDouble z_coords;
712  for (int n = 0; n < npts; n++)
713  {
714  z_coords = Length / npts * n;
715  m_outputStream[1].width(8);
716  m_outputStream[1] << setprecision(6) << time;
717  m_outputStream[1].width(15);
718  m_outputStream[1] << setprecision(6) << z_coords;
719  m_outputStream[1].width(15);
720  m_outputStream[1] << setprecision(8) << MotionVars[n];
721  m_outputStream[1].width(15);
722  m_outputStream[1] << setprecision(8) << MotionVars[npts + n];
723  m_outputStream[1].width(15);
724  m_outputStream[1] << setprecision(8) << MotionVars[2 * npts + n];
725  m_outputStream[1].width(15);
726  m_outputStream[1] << setprecision(8) << MotionVars[3 * npts + n];
727  m_outputStream[1].width(15);
728  m_outputStream[1] << setprecision(8) << MotionVars[4 * npts + n];
729  m_outputStream[1].width(15);
730  m_outputStream[1] << setprecision(8) << MotionVars[5 * npts + n];
731  m_outputStream[1] << endl;
732  }
733 }
734 
735 /**
736  *
737  */
740  const NekDouble &time)
741 {
742  if (pFields[0]->GetComm()->GetRank() == 0)
743  {
744  m_outputStream[0].close();
745  m_outputStream[1].close();
746  }
747 }
748 
749 /**
750  *
751  */
753 {
754  return true;
755 }
756 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
virtual void v_Initialise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
virtual void v_Finalise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
void UpdateMotion(const LibUtilities::SessionReaderSharedPtr &pSession, const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, Array< OneD, NekDouble > &MotionVars, const NekDouble &time)
std::vector< unsigned int > m_boundaryRegionsIdList
ID's of boundary regions where we want the forces.
Array< OneD, std::ofstream > m_outputStream
std::vector< bool > m_boundaryRegionIsInList
Determines if a given Boundary Region is in m_boundaryRegionsIdList.
void UpdateForce(const LibUtilities::SessionReaderSharedPtr &pSession, const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, Array< OneD, NekDouble > &Aeroforces, const NekDouble &time)
NekDouble Evaluate() const
Definition: Equation.cpp:95
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
static bool GenerateSeqVector(const std::string &str, std::vector< unsigned int > &out)
Takes a comma-separated compressed string and converts it to entries in a vector.
Definition: ParseUtils.cpp:103
LibUtilities::SessionReaderSharedPtr m_session
Definition: Filter.h:85
std::map< std::string, std::string > ParamMap
Definition: Filter.h:67
const BoundaryRegionCollection & GetBoundaryRegions(void) const
Definition: Conditions.h:234
int GetTotPoints() const
This function returns the total number of quadrature points used in the element.
Definition: StdExpansion.h:140
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:54
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:68
FilterFactory & GetFilterFactory()
Definition: Filter.cpp:41
std::map< int, BoundaryRegionShPtr > BoundaryRegionCollection
Definition: Conditions.h:210
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:327
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
double NekDouble
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 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 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 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 Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:492
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:384