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 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Output moving body forces during time-stepping.
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
37 #include <iomanip>
42 
43 namespace Nektar
44 {
45 
47  RegisterCreatorFunction("MovingBody",
49  "Moving Body Filter");
50 /**
51  *
52  */
55  const ParamMap &pParams)
56  : Filter(pSession),
57  m_session(pSession)
58 {
59  ParamMap::const_iterator it;
60 
61  // OutputFile
62  it = pParams.find("OutputFile");
63  if (it == pParams.end())
64  {
65  m_outputFile_fce = pSession->GetSessionName();
66  m_outputFile_mot = pSession->GetSessionName();
67  }
68  else
69  {
70  ASSERTL0(it->second.length() > 0, "Missing parameter 'OutputFile'.");
71 
72  m_outputFile_fce = it->second;
73  m_outputFile_mot = it->second;
74  }
75  if (!(m_outputFile_fce.length() >= 4 &&
76  m_outputFile_fce.substr(m_outputFile_fce.length() - 4) == ".fce"))
77  {
78  m_outputFile_fce += ".fce";
79  }
80  if (!(m_outputFile_mot.length() >= 4 &&
81  m_outputFile_mot.substr(m_outputFile_mot.length() - 4) == ".mot"))
82  {
83  m_outputFile_mot += ".mot";
84  }
85 
86  // OutputFrequency
87  it = pParams.find("OutputFrequency");
88  if (it == pParams.end())
89  {
91  }
92  else
93  {
94  LibUtilities::Equation equ(m_session, it->second);
95  m_outputFrequency = floor(equ.Evaluate());
96  }
97 
98  pSession->MatchSolverInfo("Homogeneous", "1D", m_isHomogeneous1D, false);
99  ASSERTL0(m_isHomogeneous1D, "Moving Body implemented just for 3D "
100  "Homogeneous 1D discetisations.");
101 
102  // Boundary (to calculate the forces)
103  it = pParams.find("Boundary");
104  ASSERTL0(it != pParams.end(), "Missing parameter 'Boundary'.");
105  ASSERTL0(it->second.length() > 0, "Missing parameter 'Boundary'.");
106  m_BoundaryString = it->second;
107 }
108 
109 
110 /**
111  *
112  */
114 {
115 
116 }
117 
118 
119 /**
120  *
121  */
124  const NekDouble &time)
125 {
126  m_index = 0;
128  // Parse the boundary regions into a list.
129  std::string::size_type FirstInd = m_BoundaryString.find_first_of('[') + 1;
130  std::string::size_type LastInd = m_BoundaryString.find_last_of(']') - 1;
131 
132  ASSERTL0(FirstInd <= LastInd,
133  (std::string("Error reading boundary region definition:") +
134  m_BoundaryString).c_str());
135 
136  std::string IndString = m_BoundaryString.substr(FirstInd,
137  LastInd - FirstInd + 1);
138 
139  bool parseGood = ParseUtils::GenerateSeqVector(IndString.c_str(),
141 
142  ASSERTL0(parseGood && !m_boundaryRegionsIdList.empty(),
143  (std::string("Unable to read boundary regions index "
144  "range for FilterAeroForces: ") + IndString).c_str());
145 
146  // determine what boundary regions need to be considered
147  int cnt;
148 
149  unsigned int numBoundaryRegions
150  = pFields[0]->GetBndConditions().num_elements();
151 
153  numBoundaryRegions, 0);
154 
155  SpatialDomains::BoundaryConditions bcs(m_session,pFields[0]->GetGraph());
156 
158  = bcs.GetBoundaryRegions();
159 
160  SpatialDomains::BoundaryRegionCollection::const_iterator it;
161 
162  for (cnt = 0, it = bregions.begin(); it != bregions.end();
163  ++it, cnt++)
164  {
165  if ( std::find(m_boundaryRegionsIdList.begin(),
166  m_boundaryRegionsIdList.end(), it->first) !=
168  {
169  m_boundaryRegionIsInList[cnt] = 1;
170  }
171  }
172 
173  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
174 
175  if (vComm->GetRank() == 0)
176  {
177  // Open output stream for cable forces
178  m_outputStream[0].open(m_outputFile_fce.c_str());
179  m_outputStream[0] << "#";
180  m_outputStream[0].width(7);
181  m_outputStream[0] << "Time";
182  m_outputStream[0].width(25);
183  m_outputStream[0] << "z";
184  m_outputStream[0].width(25);
185  m_outputStream[0] << "Fx (press)";
186  m_outputStream[0].width(25);
187  m_outputStream[0] << "Fx (visc)";
188  m_outputStream[0].width(25);
189  m_outputStream[0] << "Fx (tot)";
190  m_outputStream[0].width(25);
191  m_outputStream[0] << "Fy (press)";
192  m_outputStream[0].width(25);
193  m_outputStream[0] << "Fy (visc)";
194  m_outputStream[0].width(25);
195  m_outputStream[0] << "Fy (tot)";
196  m_outputStream[0] << endl;
197 
198  // Open output stream for cable motions
199  m_outputStream[1].open(m_outputFile_mot.c_str());
200  m_outputStream[1] << "#";
201  m_outputStream[1].width(7);
202  m_outputStream[1] << "Time";
203  m_outputStream[1].width(25);
204  m_outputStream[1] << "z";
205  m_outputStream[1].width(25);
206  m_outputStream[1] << "Disp_x";
207  m_outputStream[1].width(25);
208  m_outputStream[1] << "Vel_x";
209  m_outputStream[1].width(25);
210  m_outputStream[1] << "Acel_x";
211  m_outputStream[1].width(25);
212  m_outputStream[1] << "Disp_y";
213  m_outputStream[1].width(25);
214  m_outputStream[1] << "Vel_y";
215  m_outputStream[1].width(25);
216  m_outputStream[1] << "Acel_y";
217  m_outputStream[1] << endl;
218  }
219 }
220 
221 
222 /**
223  *
224  */
226  const LibUtilities::SessionReaderSharedPtr &pSession,
228  Array<OneD, NekDouble> &Aeroforces,
229  const NekDouble &time)
230 {
231  int n, cnt, elmtid, nq, offset, boundary;
232  int nt = pFields[0]->GetNpoints();
233  int dim = pFields.num_elements()-1;
234 
236  Array<OneD, int> BoundarytoElmtID;
237  Array<OneD, int> BoundarytoTraceID;
239 
244 
248 
252 
253  LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
254  LibUtilities::CommSharedPtr vRowComm = vComm->GetRowComm();
255  LibUtilities::CommSharedPtr vColComm = vComm->GetColumnComm();
256  LibUtilities::CommSharedPtr vCColComm = vColComm->GetColumnComm();
257 
258  // set up storage space for forces on all the planes (z-positions)
259  // on each processors some of them will remain empty as we may
260  // have just few planes per processor
261  int Num_z_pos = pFields[0]->GetHomogeneousBasis()->GetNumModes();
262  Array<OneD, NekDouble> Fx(Num_z_pos,0.0);
263  Array<OneD, NekDouble> Fxp(Num_z_pos,0.0);
264  Array<OneD, NekDouble> Fxv(Num_z_pos,0.0);
265  Array<OneD, NekDouble> Fy(Num_z_pos,0.0);
266  Array<OneD, NekDouble> Fyp(Num_z_pos,0.0);
267  Array<OneD, NekDouble> Fyv(Num_z_pos,0.0);
268 
269 
270  NekDouble rho = (pSession->DefinesParameter("rho"))
271  ? (pSession->GetParameter("rho"))
272  : 1;
273  NekDouble mu = rho*pSession->GetParameter("Kinvis");
274 
275  for(int i = 0; i < pFields.num_elements(); ++i)
276  {
277  pFields[i]->SetWaveSpace(false);
278  pFields[i]->BwdTrans(pFields[i]->GetCoeffs(),
279  pFields[i]->UpdatePhys());
280  pFields[i]->SetPhysState(true);
281  }
282 
283  // Get the number of local planes on the process and their IDs
284  // to properly locate the forces in the Fx, Fy etc. vectors.
286  ZIDs = pFields[0]->GetZIDs();
287  int local_planes = ZIDs.num_elements();
288 
289  // Homogeneous 1D case Compute forces on all WALL boundaries
290  // This only has to be done on the zero (mean) Fourier mode.
291  for(int plane = 0 ; plane < local_planes; plane++)
292  {
293  pFields[0]->GetPlane(plane)->GetBoundaryToElmtMap(BoundarytoElmtID,
294  BoundarytoTraceID);
295  BndExp = pFields[0]->GetPlane(plane)->GetBndCondExpansions();
297 
298  // loop over the types of boundary conditions
299  for(cnt = n = 0; n < BndExp.num_elements(); ++n)
300  {
301  if(m_boundaryRegionIsInList[n] == 1)
302  {
303  for(int i = 0; i < BndExp[n]->GetExpSize(); ++i, cnt++)
304  {
305  // find element of this expansion.
306  elmtid = BoundarytoElmtID[cnt];
307  elmt = pFields[0]->GetPlane(plane)->GetExp(elmtid);
308  nq = elmt->GetTotPoints();
309  offset = pFields[0]->GetPlane(plane)
310  ->GetPhys_Offset(elmtid);
311 
312  // Initialise local arrays for the velocity
313  // gradients size of total number of quadrature
314  // points for each element (hence local).
315  for(int j = 0; j < dim; ++j)
316  {
317  gradU[j] = Array<OneD, NekDouble>(nq,0.0);
318  gradV[j] = Array<OneD, NekDouble>(nq,0.0);
319  gradW[j] = Array<OneD, NekDouble>(nq,0.0);
320  }
321 
322  // identify boundary of element
323  boundary = BoundarytoTraceID[cnt];
324 
325  // Extract fields
326  U = pFields[0]->GetPlane(plane)->GetPhys() + offset;
327  V = pFields[1]->GetPlane(plane)->GetPhys() + offset;
328  P = pFields[3]->GetPlane(plane)->GetPhys() + offset;
329 
330  // compute the gradients
331  elmt->PhysDeriv(U,gradU[0],gradU[1]);
332  elmt->PhysDeriv(V,gradV[0],gradV[1]);
333 
334  // Get face 1D expansion from element expansion
335  bc = BndExp[n]->GetExp(i)->as<LocalRegions::Expansion1D>();
336 
337  // number of points on the boundary
338  int nbc = bc->GetTotPoints();
339 
340  // several vectors for computing the forces
341  Array<OneD, NekDouble> Pb(nbc,0.0);
342 
343  for(int j = 0; j < dim; ++j)
344  {
345  fgradU[j] = Array<OneD, NekDouble>(nbc,0.0);
346  fgradV[j] = Array<OneD, NekDouble>(nbc,0.0);
347  }
348 
349  Array<OneD, NekDouble> drag_t(nbc,0.0);
350  Array<OneD, NekDouble> lift_t(nbc,0.0);
351  Array<OneD, NekDouble> drag_p(nbc,0.0);
352  Array<OneD, NekDouble> lift_p(nbc,0.0);
353  Array<OneD, NekDouble> temp(nbc,0.0);
354  Array<OneD, NekDouble> temp2(nbc,0.0);
355 
356  // identify boundary of element .
357  boundary = BoundarytoTraceID[cnt];
358 
359  // extraction of the pressure and wss on the
360  // boundary of the element
361  elmt->GetEdgePhysVals(boundary,bc,P,Pb);
362 
363  for(int j = 0; j < dim; ++j)
364  {
365  elmt->GetEdgePhysVals(boundary,bc,gradU[j],fgradU[j]);
366  elmt->GetEdgePhysVals(boundary,bc,gradV[j],fgradV[j]);
367  }
368 
369  //normals of the element
370  const Array<OneD, Array<OneD, NekDouble> > &normals
371  = elmt->GetEdgeNormal(boundary);
372 
373  //
374  // Compute viscous tractive forces on wall from
375  //
376  // t_i = - T_ij * n_j (minus sign for force
377  // exerted BY fluid ON wall),
378  //
379  // where
380  //
381  // T_ij = viscous stress tensor (here in Cartesian
382  // coords)
383  // dU_i dU_j
384  // = RHO * KINVIS * ( ---- + ---- ) .
385  // dx_j dx_i
386 
387  //a) DRAG TERMS
388  //-rho*kinvis*(2*du/dx*nx+(du/dy+dv/dx)*ny)
389 
390  Vmath::Vadd(nbc, fgradU[1], 1, fgradV[0], 1, drag_t, 1);
391  Vmath::Vmul(nbc, drag_t, 1, normals[1], 1, drag_t, 1);
392 
393  Vmath::Smul(nbc, 2.0, fgradU[0], 1, fgradU[0], 1);
394  Vmath::Vmul(nbc, fgradU[0], 1, normals[0], 1, temp2, 1);
395  Vmath::Smul(nbc, 0.5, fgradU[0], 1, fgradU[0], 1);
396 
397  Vmath::Vadd(nbc, temp2, 1, drag_t, 1, drag_t, 1);
398  Vmath::Smul(nbc, -mu, drag_t, 1, drag_t, 1);
399 
400  //zero temporary storage vector
401  Vmath::Zero(nbc, temp, 0.0);
402  Vmath::Zero(nbc, temp2, 0.0);
403 
404 
405  //b) LIFT TERMS
406  //-rho*kinvis*(2*dv/dy*ny+(du/dy+dv/dx)*nx)
407 
408  Vmath::Vadd(nbc, fgradU[1], 1, fgradV[0], 1, lift_t, 1);
409  Vmath::Vmul(nbc, lift_t, 1, normals[0], 1, lift_t, 1);
410 
411  Vmath::Smul(nbc, 2.0, fgradV[1], 1, fgradV[1], 1);
412  Vmath::Vmul(nbc, fgradV[1], 1, normals[1], 1, temp2, 1);
413  Vmath::Smul(nbc, -0.5, fgradV[1], 1, fgradV[1], 1);
414 
415 
416  Vmath::Vadd(nbc, temp2, 1, lift_t, 1, lift_t, 1);
417  Vmath::Smul(nbc, -mu, lift_t, 1, lift_t, 1);
418 
419  // Compute normal tractive forces on all WALL
420  // boundaries
421 
422  Vmath::Vvtvp(nbc, Pb, 1, normals[0], 1, drag_p, 1,
423  drag_p, 1);
424  Vmath::Vvtvp(nbc, Pb, 1, normals[1], 1, lift_p, 1,
425  lift_p, 1);
426 
427  //integration over the boundary
428  Fxv[ZIDs[plane]] += bc->Integral(drag_t);
429  Fyv[ZIDs[plane]] += bc->Integral(lift_t);
430 
431  Fxp[ZIDs[plane]] += bc->Integral(drag_p);
432  Fyp[ZIDs[plane]] += bc->Integral(lift_p);
433  }
434  }
435  else
436  {
437  cnt += BndExp[n]->GetExpSize();
438  }
439  }
440  }
441 
442  for(int i = 0; i < pFields.num_elements(); ++i)
443  {
444  pFields[i]->SetWaveSpace(true);
445  pFields[i]->BwdTrans(pFields[i]->GetCoeffs(),
446  pFields[i]->UpdatePhys());
447  pFields[i]->SetPhysState(false);
448  }
449 
450  // In case we are using an hybrid parallelisation we need
451  // to reduce the forces on the same plane coming from
452  // different mesh partitions.
453  // It is quite an expensive communication, therefore
454  // we check to make sure it is actually required.
455 
456  if(vComm->GetRowComm()->GetSize() > 0)
457  {
458  // NOTE 1: We can eventually sum the viscous and pressure
459  // component before doing the communication, thus
460  // reducing by a factor 2 the communication.
461  // NOTE 2: We may want to set up in the Comm class an AllReduce
462  // routine wich can handle arrays more efficiently
463  for(int plane = 0 ; plane < local_planes; plane++)
464  {
465  vRowComm->AllReduce(Fxp[ZIDs[plane]], LibUtilities::ReduceSum);
466  vRowComm->AllReduce(Fxv[ZIDs[plane]], LibUtilities::ReduceSum);
467  vRowComm->AllReduce(Fyp[ZIDs[plane]], LibUtilities::ReduceSum);
468  vRowComm->AllReduce(Fyv[ZIDs[plane]], LibUtilities::ReduceSum);
469  }
470  }
471 
472  // At this point on rank (0,n) of the Mesh partion communicator we have
473  // the total areo forces on the planes which are on the same column
474  // communicator. Since the planes are scattered on different processors
475  // some of the entries of the vector Fxp, Fxp etc. are still zero.
476  // Now we need to reduce the values on a single vector on rank (0,0) of the
477  // global communicator.
478  if(!pSession->DefinesSolverInfo("HomoStrip"))
479  {
480  if(vComm->GetRowComm()->GetRank() == 0)
481  {
482  for(int z = 0 ; z < Num_z_pos; z++)
483  {
484  vColComm->AllReduce(Fxp[z], LibUtilities::ReduceSum);
485  vColComm->AllReduce(Fxv[z], LibUtilities::ReduceSum);
486  vColComm->AllReduce(Fyp[z], LibUtilities::ReduceSum);
487  vColComm->AllReduce(Fyv[z], LibUtilities::ReduceSum);
488  }
489  }
490  }
491  else
492  {
493  if(vComm->GetRowComm()->GetRank() == 0)
494  {
495  for(int z = 0 ; z < Num_z_pos; z++)
496  {
497  vCColComm->AllReduce(Fxp[z], LibUtilities::ReduceSum);
498  vCColComm->AllReduce(Fxv[z], LibUtilities::ReduceSum);
499  vCColComm->AllReduce(Fyp[z], LibUtilities::ReduceSum);
500  vCColComm->AllReduce(Fyv[z], LibUtilities::ReduceSum);
501  }
502  }
503  }
504 
505  if(!pSession->DefinesSolverInfo("HomoStrip"))
506  {
507  //set the forces imparted on the cable's wall
508  for(int plane = 0 ; plane < local_planes; plane++)
509  {
510  Aeroforces[plane] = Fxp[ZIDs[plane]]
511  + Fxv[ZIDs[plane]];
512  Aeroforces[plane + local_planes] = Fyp[ZIDs[plane]]
513  + Fyv[ZIDs[plane]];
514  }
515 
516  // Only output every m_outputFrequency.
517  if ((m_index++) % m_outputFrequency)
518  {
519  return;
520  }
521 
522  // At thi point in rank (0,0) we have the full vectors
523  // containing Fxp,Fxv,Fyp and Fyv where different positions
524  // in the vectors correspond to different planes.
525  // Here we write it to file. We do it just on one porcess
526 
527  Array<OneD, NekDouble> z_coords(Num_z_pos,0.0);
529  = pFields[0]->GetHomogeneousBasis()->GetZ();
530 
531  NekDouble LZ;
532  pSession->LoadParameter("LZ", LZ);
533  Vmath::Smul(Num_z_pos,LZ/2.0,pts,1,z_coords,1);
534  Vmath::Sadd(Num_z_pos,LZ/2.0,z_coords,1,z_coords,1);
535  if (vComm->GetRank() == 0)
536  {
537 
538  Vmath::Vadd(Num_z_pos,Fxp,1,Fxv,1,Fx,1);
539  Vmath::Vadd(Num_z_pos,Fyp,1,Fyv,1,Fy,1);
540 
541  for(int i = 0 ; i < Num_z_pos; i++)
542  {
543  m_outputStream[0].width(8);
544  m_outputStream[0] << setprecision(6) << time;
545 
546  m_outputStream[0].width(25);
547  m_outputStream[0] << setprecision(6) << z_coords[i];
548 
549  m_outputStream[0].width(25);
550  m_outputStream[0] << setprecision(8) << Fxp[i];
551  m_outputStream[0].width(25);
552  m_outputStream[0] << setprecision(8) << Fxv[i];
553  m_outputStream[0].width(25);
554  m_outputStream[0] << setprecision(8) << Fx[i];
555 
556  m_outputStream[0].width(25);
557  m_outputStream[0] << setprecision(8) << Fyp[i];
558  m_outputStream[0].width(25);
559  m_outputStream[0] << setprecision(8) << Fyv[i];
560  m_outputStream[0].width(25);
561  m_outputStream[0] << setprecision(8) << Fy[i];
562  m_outputStream[0] << endl;
563  }
564  }
565  }
566  else
567  {
568  // average the forces over local planes for each processor
569  Array<OneD, NekDouble> fces(6,0.0);
570  for(int plane = 0 ; plane < local_planes; plane++)
571  {
572  fces[0] += Fxp[ZIDs[plane]] + Fxv[ZIDs[plane]];
573  fces[1] += Fyp[ZIDs[plane]] + Fyv[ZIDs[plane]];
574  fces[2] += Fxp[ZIDs[plane]] ;
575  fces[3] += Fyp[ZIDs[plane]] ;
576  fces[4] += Fxv[ZIDs[plane]] ;
577  fces[5] += Fyv[ZIDs[plane]] ;
578  }
579 
580  fces[0] = fces[0]/local_planes;
581  fces[1] = fces[1]/local_planes;
582  fces[2] = fces[2]/local_planes;
583  fces[3] = fces[3]/local_planes;
584  fces[4] = fces[4]/local_planes;
585  fces[5] = fces[5]/local_planes;
586 
587  // average the forces over communicators within each strip
588  vCColComm->AllReduce(fces[0], LibUtilities::ReduceSum);
589  vCColComm->AllReduce(fces[1], LibUtilities::ReduceSum);
590  vCColComm->AllReduce(fces[2], LibUtilities::ReduceSum);
591  vCColComm->AllReduce(fces[3], LibUtilities::ReduceSum);
592  vCColComm->AllReduce(fces[4], LibUtilities::ReduceSum);
593  vCColComm->AllReduce(fces[5], LibUtilities::ReduceSum);
594 
595  int npts = vComm->GetColumnComm()->GetColumnComm()->GetSize();
596 
597  fces[0] = fces[0]/npts;
598  fces[1] = fces[1]/npts;
599  fces[2] = fces[2]/npts;
600  fces[3] = fces[3]/npts;
601  fces[4] = fces[4]/npts;
602  fces[5] = fces[5]/npts;
603 
604  for(int plane = 0 ; plane < local_planes; plane++)
605  {
606  Aeroforces[plane] = fces[0];
607  Aeroforces[plane+local_planes] = fces[1];
608  }
609 
610  // Only output every m_outputFrequency.
611  if ((m_index) % m_outputFrequency)
612  {
613  return;
614  }
615 
616  int colrank = vColComm->GetRank();
617  int nstrips;
618 
619  NekDouble DistStrip;
620 
621  pSession->LoadParameter("Strip_Z", nstrips);
622  pSession->LoadParameter("DistStrip", DistStrip);
623 
624  Array<OneD, NekDouble> z_coords(nstrips);
625  for(int i = 0; i < nstrips; i++)
626  {
627  z_coords[i] = i * DistStrip;
628  }
629 
630  if(colrank == 0)
631  {
632  m_outputStream[0].width(8);
633  m_outputStream[0] << setprecision(6) << time;
634 
635  m_outputStream[0].width(25);
636  m_outputStream[0] << setprecision(6) << z_coords[0];
637 
638  m_outputStream[0].width(25);
639  m_outputStream[0] << setprecision(8) << fces[2];
640  m_outputStream[0].width(25);
641  m_outputStream[0] << setprecision(8) << fces[4];
642  m_outputStream[0].width(25);
643  m_outputStream[0] << setprecision(8) << fces[0];
644 
645  m_outputStream[0].width(25);
646  m_outputStream[0] << setprecision(8) << fces[3];
647  m_outputStream[0].width(25);
648  m_outputStream[0] << setprecision(8) << fces[5];
649  m_outputStream[0].width(25);
650  m_outputStream[0] << setprecision(8) << fces[1];
651  m_outputStream[0] << endl;
652 
653  for(int i = 1; i < nstrips; i++)
654  {
655  vColComm->Recv(i, fces);
656 
657  m_outputStream[0].width(8);
658  m_outputStream[0] << setprecision(6) << time;
659 
660  m_outputStream[0].width(25);
661  m_outputStream[0] << setprecision(6) << z_coords[i];
662 
663  m_outputStream[0].width(25);
664  m_outputStream[0] << setprecision(8) << fces[2];
665  m_outputStream[0].width(25);
666  m_outputStream[0] << setprecision(8) << fces[4];
667  m_outputStream[0].width(25);
668  m_outputStream[0] << setprecision(8) << fces[0];
669 
670  m_outputStream[0].width(25);
671  m_outputStream[0] << setprecision(8) << fces[3];
672  m_outputStream[0].width(25);
673  m_outputStream[0] << setprecision(8) << fces[5];
674  m_outputStream[0].width(25);
675  m_outputStream[0] << setprecision(8) << fces[1];
676  m_outputStream[0] << endl;
677  }
678  }
679  else
680  {
681  for(int i = 1; i < nstrips; i++)
682  {
683  if(colrank == i)
684  {
685  vColComm->Send(0, fces);
686  }
687  }
688  }
689  }
690 }
691 
692 
693 /**
694  *
695  */
697  const LibUtilities::SessionReaderSharedPtr &pSession,
699  Array<OneD, NekDouble> &MotionVars,
700  const NekDouble &time)
701 {
702  // Only output every m_outputFrequency.
703  if ((m_index++) % m_outputFrequency)
704  {
705  return;
706  }
707 
708  // Get the number of local planes on the process and their IDs
709  // to properly locate the forces in the Fx, Fy etc. vectors.
711  ZIDs = pFields[0]->GetZIDs();
712  int local_planes = ZIDs.num_elements();
713 
715  = pFields[0]->GetComm()->GetColumnComm();
716 
717  //
718  if(!pSession->DefinesSolverInfo("HomoStrip"))
719  {
720  int Num_z_pos = pFields[0]->GetHomogeneousBasis()->GetNumModes();
721  Array<OneD, NekDouble> z_coords(Num_z_pos,0.0);
723  = pFields[0]->GetHomogeneousBasis()->GetZ();
724 
725  NekDouble LZ;
726  pSession->LoadParameter("LZ", LZ);
727  Vmath::Smul(Num_z_pos,LZ/2.0,pts,1,z_coords,1);
728  Vmath::Sadd(Num_z_pos,LZ/2.0,z_coords,1,z_coords,1);
729 
730  //get and output moving body variables
731  int nStrVars = 3;
732  Array<OneD, Array<OneD, NekDouble> > Motion_x(nStrVars);
733  Array<OneD, Array<OneD, NekDouble> > Motion_y(nStrVars);
734 
735  for(int i = 0; i < nStrVars; i++)
736  {
737  Motion_x[i] = Array<OneD, NekDouble>(local_planes,0.0);
738  Motion_y[i] = Array<OneD, NekDouble>(local_planes,0.0);
739  }
740 
741  for(int plane = 0; plane < local_planes; plane++)
742  {
743  for (int var = 0; var < nStrVars; var++)
744  {
745  int xoffset = var*local_planes+plane;
746  int yoffset = nStrVars*local_planes+xoffset;
747  Motion_x[var][plane] = MotionVars[xoffset];
748  Motion_y[var][plane] = MotionVars[yoffset];
749  }
750  }
751 
752  Array <OneD, NekDouble> CableAccelX;
753  Array <OneD, NekDouble> CableVelocX;
754  Array <OneD, NekDouble> CableDisplX;
755  Array <OneD, NekDouble> CableAccelY;
756  Array <OneD, NekDouble> CableVelocY;
757  Array <OneD, NekDouble> CableDisplY;
758 
759  int npoints = Motion_x[0].num_elements();
760  CableAccelX = Array <OneD, NekDouble>(npoints);
761  CableVelocX = Array <OneD, NekDouble>(npoints);
762  CableDisplX = Array <OneD, NekDouble>(npoints);
763  CableAccelY = Array <OneD, NekDouble>(npoints);
764  CableVelocY = Array <OneD, NekDouble>(npoints);
765  CableDisplY = Array <OneD, NekDouble>(npoints);
766 
767  Vmath::Vcopy(npoints, Motion_x[0], 1, CableDisplX, 1);
768  Vmath::Vcopy(npoints, Motion_x[1], 1, CableVelocX, 1);
769  Vmath::Vcopy(npoints, Motion_x[2], 1, CableAccelX, 1);
770  Vmath::Vcopy(npoints, Motion_y[0], 1, CableDisplY, 1);
771  Vmath::Vcopy(npoints, Motion_y[1], 1, CableVelocY, 1);
772  Vmath::Vcopy(npoints, Motion_y[2], 1, CableAccelY, 1);
773 
774  int colrank = vColComm->GetRank();
775  int nproc = vColComm->GetSize();
776  // Send to root process.
777  if (colrank == 0)
778  {
779  for (int j = 0; j <Motion_x[0].num_elements(); j++)
780  {
781  m_outputStream[1].width(8);
782  m_outputStream[1] << setprecision(6) << time;
783  m_outputStream[1].width(25);
784  m_outputStream[1] << setprecision(6) << z_coords[j];
785  m_outputStream[1].width(25);
786  m_outputStream[1] << setprecision(8) << CableDisplX[j];
787  m_outputStream[1].width(25);
788  m_outputStream[1] << setprecision(8) << CableVelocX[j];
789  m_outputStream[1].width(25);
790  m_outputStream[1] << setprecision(8) << CableAccelX[j];
791  m_outputStream[1].width(25);
792  m_outputStream[1] << setprecision(8) << CableDisplY[j];
793  m_outputStream[1].width(25);
794  m_outputStream[1] << setprecision(8) << CableVelocY[j];
795  m_outputStream[1].width(25);
796  m_outputStream[1] << setprecision(8) << CableAccelY[j];
797  m_outputStream[1] << endl;
798  }
799 
800  for (int i = 1; i < nproc; ++i)
801  {
802  vColComm->Recv(i, CableAccelX);
803  vColComm->Recv(i, CableVelocX);
804  vColComm->Recv(i, CableDisplX);
805  vColComm->Recv(i, CableAccelY);
806  vColComm->Recv(i, CableVelocY);
807  vColComm->Recv(i, CableDisplY);
808 
809 
810  for (int j = 0; j < Motion_x[0].num_elements(); ++j)
811  {
812  int n = Num_z_pos/nproc * i + j;
813  m_outputStream[1].width(8);
814  m_outputStream[1] << setprecision(6) << time;
815  m_outputStream[1].width(25);
816  m_outputStream[1] << setprecision(6) << z_coords[n];
817  m_outputStream[1].width(25);
818  m_outputStream[1] << setprecision(8) << CableDisplX[j];
819  m_outputStream[1].width(25);
820  m_outputStream[1] << setprecision(8) << CableVelocX[j];
821  m_outputStream[1].width(25);
822  m_outputStream[1] << setprecision(8) << CableAccelX[j];
823  m_outputStream[1].width(25);
824  m_outputStream[1] << setprecision(8) << CableDisplY[j];
825  m_outputStream[1].width(25);
826  m_outputStream[1] << setprecision(8) << CableVelocY[j];
827  m_outputStream[1].width(25);
828  m_outputStream[1] << setprecision(8) << CableAccelY[j];
829  m_outputStream[1] << endl;
830  }
831  }
832  }
833  else
834  {
835  vColComm->Send(0, CableAccelX);
836  vColComm->Send(0, CableVelocX);
837  vColComm->Send(0, CableDisplX);
838  vColComm->Send(0, CableAccelY);
839  vColComm->Send(0, CableVelocY);
840  vColComm->Send(0, CableDisplY);
841  }
842  }
843  else
844  {
845  int colrank = vColComm->GetRank();
846  int nstrips;
847 
848  NekDouble DistStrip;
849 
850  pSession->LoadParameter("Strip_Z", nstrips);
851  pSession->LoadParameter("DistStrip", DistStrip);
852 
853  Array<OneD, NekDouble> z_coords(nstrips);
854  for(int i = 0; i < nstrips; i++)
855  {
856  z_coords[i] = i * DistStrip;
857  }
858 
859  //get and output moving body variables
860  int nStrVars = 3;
861  Array<OneD, Array<OneD, NekDouble> > Motion_x(nStrVars);
862  Array<OneD, Array<OneD, NekDouble> > Motion_y(nStrVars);
863 
864  for(int i = 0; i < nStrVars; i++)
865  {
866  Motion_x[i] = Array<OneD, NekDouble>(local_planes,0.0);
867  Motion_y[i] = Array<OneD, NekDouble>(local_planes,0.0);
868  }
869 
870  for(int plane = 0; plane < local_planes; plane++)
871  {
872  for (int var = 0; var < nStrVars; var++)
873  {
874  int xoffset = plane*nStrVars+var;
875  int yoffset = nStrVars*local_planes+xoffset;
876  Motion_x[var][plane] = MotionVars[xoffset];
877  Motion_y[var][plane] = MotionVars[yoffset];
878  }
879  }
880 
881  Array <OneD, NekDouble> CableMotions(6);
882 
883  for(int var = 0; var <nStrVars; var++)
884  {
885  CableMotions[var] = Motion_x[var][0];
886  CableMotions[3+var] = Motion_y[var][0];
887  }
888  // Send to root process.
889  if (colrank == 0)
890  {
891  m_outputStream[1].width(8);
892  m_outputStream[1] << setprecision(6) << time;
893  m_outputStream[1].width(25);
894  m_outputStream[1] << setprecision(6) << z_coords[0];
895  for(int var = 0; var < 2*nStrVars; var++)
896  {
897  m_outputStream[1].width(25);
898  m_outputStream[1] << setprecision(8) << CableMotions[var];
899  }
900  m_outputStream[1] << endl;
901 
902  for (int i = 1; i < nstrips; ++i)
903  {
904  vColComm->Recv(i, CableMotions);
905 
906  m_outputStream[1].width(8);
907  m_outputStream[1] << setprecision(6) << time;
908  m_outputStream[1].width(25);
909  m_outputStream[1] << setprecision(6) << z_coords[i];
910  for(int var = 0; var < 2*nStrVars; var++)
911  {
912  m_outputStream[1].width(25);
913  m_outputStream[1] << setprecision(8) << CableMotions[var];
914  }
915  m_outputStream[1] << endl;
916  }
917  }
918  else
919  {
920  for(int i = 1; i < nstrips; i++)
921  {
922  if(colrank == i)
923  {
924  vColComm->Send(0, CableMotions);
925  }
926  }
927  }
928  }
929 }
930 
931 
932 /**
933  *
934  */
937  const NekDouble &time)
938 {
939  if (pFields[0]->GetComm()->GetRank() == 0)
940  {
941  m_outputStream[0].close();
942  m_outputStream[1].close();
943  }
944 }
945 
946 
947 /**
948  *
949  */
951 {
952  return true;
953 }
954 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:161
Array< OneD, std::ofstream > m_outputStream
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:428
LibUtilities::SessionReaderSharedPtr m_session
boost::shared_ptr< SessionReader > SessionReaderSharedPtr
Definition: MeshPartition.h:50
static bool GenerateSeqVector(const char *const str, std::vector< unsigned int > &vec)
Definition: ParseUtils.hpp:78
static SolverUtils::FilterSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const ParamMap &pParams)
Creates an instance of this class.
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)
int GetTotPoints() const
This function returns the total number of quadrature points used in the element.
Definition: StdExpansion.h:141
static std::string className
virtual void v_Initialise(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
boost::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:53
vector< unsigned int > m_boundaryRegionsIdList
ID's of boundary regions where we want the forces.
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:199
NekDouble Evaluate() const
Definition: Equation.h:102
std::map< int, BoundaryRegionShPtr > BoundaryRegionCollection
Definition: Conditions.h:204
static std::string npts
Definition: InputFld.cpp:43
double NekDouble
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:301
std::map< std::string, std::string > ParamMap
Definition: Filter.h:67
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)
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:312
FilterFactory & GetFilterFactory()
Definition: Filter.cpp:42
const BoundaryRegionCollection & GetBoundaryRegions(void) const
Definition: Conditions.h:225
FilterMovingBody(const LibUtilities::SessionReaderSharedPtr &pSession, const ParamMap &pParams)
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:359
boost::shared_ptr< StdExpansion > StdExpansionSharedPtr
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1038
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:285
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:169