Nektar++
Transposition.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: Transposition.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: Data manager for homogeneous transpositions
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <boost/core/ignore_unused.hpp>
36 
38 
39 #include <LibUtilities/BasicUtils/ErrorUtil.hpp> // for ASSERTL0, etc
40 #include <LibUtilities/BasicUtils/SharedArray.hpp> // for Array
41 #include <LibUtilities/BasicUtils/Vmath.hpp> // for Vcopy
42 #include <LibUtilities/Foundations/Basis.h> // for BasisKey
44 
45 namespace Nektar
46 {
47 namespace LibUtilities
48 {
49 /**
50  * Constructor for 1D transform.
51  */
55 {
56  m_hcomm = hcomm1;
58 
63 
64  m_num_homogeneous_points[0] = HomoBasis0.GetNumPoints();
65  m_num_homogeneous_coeffs[0] = HomoBasis0.GetNumModes();
66  m_num_processes[0] = m_hcomm->GetSize();
68  m_rank_id = m_hcomm->GetRank();
69 
70  //================================================================
71  // TODO: Need to be generalised for 1D, 2D and 3D
74 
75  for (int i = 0; i < m_num_points_per_proc[0]; i++)
76  {
78  }
79 
80  int global_rank_id = hcomm0->GetColumnComm()->GetRank();
81  int NumStrips = hcomm0->GetColumnComm()->GetSize() / m_hcomm->GetSize();
82  m_strip_ID = 0;
83 
84  if (NumStrips > 1)
85  {
86  m_strip_ID = (NumStrips > global_rank_id)
87  ? global_rank_id
88  : (global_rank_id - NumStrips);
89  }
90 
91  if (HomoBasis0.GetBasisType() == LibUtilities::eFourier)
92  {
93  for (int i = 0; i < m_num_points_per_proc[0]; i++)
94  {
95  m_K[i] = m_planes_IDs[i] / 2;
96  }
97  }
98 
100  {
101  m_K[0] = 1;
102  m_K[1] = 1;
103  }
104 
105  if (HomoBasis0.GetBasisType() == LibUtilities::eFourierHalfModeRe ||
107  {
108  m_K[0] = 1;
109  }
110  //================================================================
111 }
112 
113 /**
114  * Constructor for 2D transform.
115  */
117  const LibUtilities::BasisKey &HomoBasis1,
119 {
120  m_hcomm = hcomm;
122 
127 
128  m_num_homogeneous_points[0] = HomoBasis0.GetNumPoints();
129  m_num_homogeneous_coeffs[0] = HomoBasis0.GetNumModes();
130  m_num_homogeneous_points[1] = HomoBasis1.GetNumPoints();
131  m_num_homogeneous_coeffs[1] = HomoBasis1.GetNumModes();
132 
133  m_num_processes[0] = m_hcomm->GetRowComm()->GetSize();
134  m_num_processes[1] = m_hcomm->GetColumnComm()->GetSize();
135 
138 
139  //================================================================
140  // TODO: Need set up for 2D lines IDs and Ks if Fourier
141  //================================================================
142 }
143 
144 /**
145  * Constructor for 3D transform.
146  */
148  const LibUtilities::BasisKey &HomoBasis1,
149  const LibUtilities::BasisKey &HomoBasis2,
151 {
152  boost::ignore_unused(HomoBasis0, HomoBasis1, HomoBasis2);
153 
154  m_hcomm = hcomm;
156 
161 
162  //================================================================
163  // TODO: Need set up for 3D
164  ASSERTL0(false, "Transposition is not set up for 3D.");
165  //================================================================
166 }
167 
168 /**
169  * Destructor
170  */
172 {
173 }
174 
175 //====================================================================
176 // TODO: Need to generalise the following methods for 1D, 2D and 3D
177 unsigned int Transposition::GetK(int i)
178 {
179  return m_K[i];
180 }
181 
183 {
184  return m_K;
185 }
186 
187 unsigned int Transposition::GetPlaneID(int i)
188 {
189  return m_planes_IDs[i];
190 }
191 
193 {
194  return m_planes_IDs;
195 }
196 
197 unsigned int Transposition::GetStripID(void)
198 {
199  return m_strip_ID;
200 }
201 
202 /**
203  * Main method: General transposition, the dir parameters define if
204  * 1D,2D,3D and which transposition is required at the same time
205  */
206 void Transposition::Transpose(const int npts,
207  const Array<OneD, const NekDouble> &inarray,
208  Array<OneD, NekDouble> &outarray, bool UseNumMode,
209  TranspositionDir dir)
210 {
211  switch (dir)
212  {
213  case eXYtoZ:
214  {
215  TransposeXYtoZ(npts, inarray, outarray, UseNumMode);
216  }
217  break;
218  case eZtoXY:
219  {
220  TransposeZtoXY(npts, inarray, outarray, UseNumMode);
221  }
222  break;
223  case eXtoYZ:
224  {
225  TransposeXtoYZ(npts, inarray, outarray, UseNumMode);
226  }
227  break;
228  case eYZtoX:
229  {
230  TransposeYZtoX(npts, inarray, outarray, UseNumMode);
231  }
232  break;
233  case eYZtoZY:
234  {
235  TransposeYZtoZY(npts, inarray, outarray, UseNumMode);
236  }
237  break;
238  case eZYtoYZ:
239  {
240  TransposeZYtoYZ(npts, inarray, outarray, UseNumMode);
241  }
242  break;
243  case eXtoY:
244  {
245  ASSERTL0(false, "Transposition not implemented yet.");
246  }
247  break;
248  case eYtoZ:
249  {
250  ASSERTL0(false, "Transposition not implemented yet.");
251  }
252  break;
253  case eZtoX:
254  {
255  ASSERTL0(false, "Transposition not implemented yet.");
256  }
257  break;
258  default:
259  {
260  ASSERTL0(false, "Transposition type does not exist.");
261  }
262  }
263 }
264 
265 /**
266  * Homogeneous 1D transposition from SEM to Homogeneous ordering.
267  */
268 void Transposition::TransposeXYtoZ(const int npts,
269  const Array<OneD, const NekDouble> &inarray,
270  Array<OneD, NekDouble> &outarray,
271  bool UseNumMode)
272 {
273  if (m_num_processes[0] > 1)
274  {
275  // Paramerers set up
276  int i, packed_len;
277  int copy_len = 0;
278  int index = 0;
279  int cnt = 0;
280 
281  int num_dofs = npts;
282  int num_points_per_plane = num_dofs / m_num_points_per_proc[0];
283  int num_pencil_per_proc =
284  (num_points_per_plane / m_num_processes[0]) +
285  (num_points_per_plane % m_num_processes[0] > 0);
286 
289 
290  for (i = 0; i < m_num_processes[0]; i++)
291  {
292  m_SizeMap[i] = num_pencil_per_proc * m_num_points_per_proc[0];
293  m_OffsetMap[i] = i * num_pencil_per_proc * m_num_points_per_proc[0];
294  }
295 
296  Array<OneD, NekDouble> tmp_outarray(
297  num_pencil_per_proc * m_num_homogeneous_points[0], 0.0);
298 
299  if (UseNumMode)
300  {
301  packed_len = m_num_homogeneous_coeffs[0];
302  }
303  else
304  {
305  packed_len = m_num_homogeneous_points[0];
306  }
307 
308  // Start Transposition
309  while (index < num_points_per_plane)
310  {
311  copy_len = num_pencil_per_proc < (num_points_per_plane - index)
312  ? num_pencil_per_proc
313  : (num_points_per_plane - index);
314 
315  for (i = 0; i < m_num_points_per_proc[0]; i++)
316  {
317  Vmath::Vcopy(copy_len,
318  &(inarray[index + (i * num_points_per_plane)]), 1,
319  &(outarray[cnt]), 1);
320 
321  cnt += num_pencil_per_proc;
322  }
323 
324  index += copy_len;
325  }
326 
327  m_hcomm->AlltoAllv(outarray, m_SizeMap, m_OffsetMap, tmp_outarray,
329 
330  for (i = 0; i < packed_len; ++i)
331  {
332  Vmath::Vcopy(num_pencil_per_proc,
333  &(tmp_outarray[i * num_pencil_per_proc]), 1,
334  &(outarray[i]), packed_len);
335  }
336  // End Transposition
337  }
338 
339  // Serial case implementation (more efficient then MPI 1 processor
340  // implemenation)
341  else
342  {
343  int i, pts_per_plane;
344  int n = npts;
345  int packed_len;
346 
347  pts_per_plane = n / m_num_points_per_proc[0];
348 
349  if (UseNumMode)
350  {
351  packed_len = m_num_homogeneous_coeffs[0];
352  }
353  else
354  {
355  packed_len = m_num_homogeneous_points[0];
356  }
357 
358  ASSERTL1(&inarray[0] != &outarray[0],
359  "Inarray and outarray cannot be the same");
360 
361  for (i = 0; i < packed_len; ++i)
362  {
363  Vmath::Vcopy(pts_per_plane, &(inarray[i * pts_per_plane]), 1,
364  &(outarray[i]), packed_len);
365  }
366  }
367 }
368 
369 /**
370  * Homogeneous 1D transposition from Homogeneous to SEM ordering.
371  */
372 void Transposition::TransposeZtoXY(const int npts,
373  const Array<OneD, const NekDouble> &inarray,
374  Array<OneD, NekDouble> &outarray,
375  bool UseNumMode)
376 {
377  if (m_num_processes[0] > 1)
378  {
379  // Paramerers set up
380  int i, packed_len;
381  int copy_len = 0;
382  int index = 0;
383  int cnt = 0;
384 
385  int num_dofs = npts; // outarray.size();
386  int num_points_per_plane = num_dofs / m_num_points_per_proc[0];
387  int num_pencil_per_proc =
388  (num_points_per_plane / m_num_processes[0]) +
389  (num_points_per_plane % m_num_processes[0] > 0);
390 
393 
394  for (i = 0; i < m_num_processes[0]; i++)
395  {
396  m_SizeMap[i] = num_pencil_per_proc * m_num_points_per_proc[0];
397  m_OffsetMap[i] = i * num_pencil_per_proc * m_num_points_per_proc[0];
398  }
399 
400  Array<OneD, NekDouble> tmp_inarray(
401  num_pencil_per_proc * m_num_homogeneous_points[0], 0.0);
402  Array<OneD, NekDouble> tmp_outarray(
403  num_pencil_per_proc * m_num_homogeneous_points[0], 0.0);
404 
405  if (UseNumMode)
406  {
407  packed_len = m_num_homogeneous_coeffs[0];
408  }
409  else
410  {
411  packed_len = m_num_homogeneous_points[0];
412  }
413 
414  // Start Transposition
415  for (i = 0; i < packed_len; ++i)
416  {
417  Vmath::Vcopy(num_pencil_per_proc, &(inarray[i]), packed_len,
418  &(tmp_inarray[i * num_pencil_per_proc]), 1);
419  }
420 
421  m_hcomm->AlltoAllv(tmp_inarray, m_SizeMap, m_OffsetMap, tmp_outarray,
423 
424  while (index < num_points_per_plane)
425  {
426  copy_len = num_pencil_per_proc < (num_points_per_plane - index)
427  ? num_pencil_per_proc
428  : (num_points_per_plane - index);
429 
430  for (i = 0; i < m_num_points_per_proc[0]; i++)
431  {
432  Vmath::Vcopy(copy_len, &(tmp_outarray[cnt]), 1,
433  &(outarray[index + (i * num_points_per_plane)]),
434  1);
435 
436  cnt += num_pencil_per_proc;
437  }
438 
439  index += copy_len;
440  }
441  // End Transposition
442  }
443 
444  // Serial case implementation (more efficient then MPI 1 processor
445  // implemenation)
446  else
447  {
448  int i, pts_per_plane;
449  int n = npts;
450  int packed_len;
451 
452  // use length of inarray to determine data storage type
453  // (i.e.modal or physical).
454  pts_per_plane = n / m_num_points_per_proc[0];
455 
456  if (UseNumMode)
457  {
458  packed_len = m_num_homogeneous_coeffs[0];
459  }
460  else
461  {
462  packed_len = m_num_homogeneous_points[0];
463  }
464 
465  ASSERTL1(&inarray[0] != &outarray[0],
466  "Inarray and outarray cannot be the same");
467 
468  for (i = 0; i < packed_len; ++i)
469  {
470  Vmath::Vcopy(pts_per_plane, &(inarray[i]), packed_len,
471  &(outarray[i * pts_per_plane]), 1);
472  }
473  }
474 }
475 
476 /**
477  * Homogeneous 2D transposition from SEM to Homogeneous(YZ) ordering.
478  */
479 void Transposition::TransposeXtoYZ(const int npts,
480  const Array<OneD, const NekDouble> &inarray,
481  Array<OneD, NekDouble> &outarray,
482  bool UseNumMode)
483 {
484  if (m_num_processes[0] > 1 || m_num_processes[1] > 1)
485  {
486  ASSERTL0(false, "Parallel transposition not implemented yet for "
487  "3D-Homo-2D approach.");
488  }
489  else
490  {
491  int i, pts_per_line;
492  int n = npts;
493  int packed_len;
494 
495  pts_per_line =
497 
498  if (UseNumMode)
499  {
500  packed_len =
502  }
503  else
504  {
505  packed_len =
507  }
508 
509  ASSERTL1(&inarray[0] != &outarray[0],
510  "Inarray and outarray cannot be the same");
511 
512  for (i = 0; i < packed_len; ++i)
513  {
514  Vmath::Vcopy(pts_per_line, &(inarray[i * pts_per_line]), 1,
515  &(outarray[i]), packed_len);
516  }
517  }
518 }
519 
520 /**
521  * Homogeneous 2D transposition from Homogeneous (YZ) ordering to SEM.
522  */
523 void Transposition::TransposeYZtoX(const int npts,
524  const Array<OneD, const NekDouble> &inarray,
525  Array<OneD, NekDouble> &outarray,
526  bool UseNumMode)
527 {
528  if (m_num_processes[0] > 1 || m_num_processes[1] > 1)
529  {
530  ASSERTL0(false, "Parallel transposition not implemented yet for "
531  "3D-Homo-2D approach.");
532  }
533  else
534  {
535  int i, pts_per_line;
536  int n = npts;
537  int packed_len;
538 
539  pts_per_line =
541 
542  if (UseNumMode)
543  {
544  packed_len =
546  }
547  else
548  {
549  packed_len =
551  }
552 
553  ASSERTL1(&inarray[0] != &outarray[0],
554  "Inarray and outarray cannot be the same");
555 
556  for (i = 0; i < packed_len; ++i)
557  {
558  Vmath::Vcopy(pts_per_line, &(inarray[i]), packed_len,
559  &(outarray[i * pts_per_line]), 1);
560  }
561  }
562 }
563 
564 /**
565  * Homogeneous 2D transposition from Y ordering to Z.
566  */
567 void Transposition::TransposeYZtoZY(const int npts,
568  const Array<OneD, const NekDouble> &inarray,
569  Array<OneD, NekDouble> &outarray,
570  bool UseNumMode)
571 {
572  boost::ignore_unused(UseNumMode);
573 
574  if (m_num_processes[0] > 1 || m_num_processes[1] > 1)
575  {
576  ASSERTL0(false, "Parallel transposition not implemented yet for "
577  "3D-Homo-2D approach.");
578  }
579  else
580  {
582  int s = npts;
583 
584  int pts_per_line = s / n;
585 
586  int packed_len = pts_per_line * m_num_homogeneous_points[1];
587 
588  for (int i = 0; i < m_num_homogeneous_points[0]; ++i)
589  {
590  Vmath::Vcopy(packed_len, &(inarray[i]), m_num_homogeneous_points[0],
591  &(outarray[i * packed_len]), 1);
592  }
593  }
594 }
595 
596 /**
597  * Homogeneous 2D transposition from Z ordering to Y.
598  */
599 void Transposition::TransposeZYtoYZ(const int npts,
600  const Array<OneD, const NekDouble> &inarray,
601  Array<OneD, NekDouble> &outarray,
602  bool UseNumMode)
603 {
604  boost::ignore_unused(UseNumMode);
605 
606  if (m_num_processes[0] > 1 || m_num_processes[1] > 1)
607  {
608  ASSERTL0(false, "Parallel transposition not implemented yet for "
609  "3D-Homo-2D approach.");
610  }
611  else
612  {
614  int s = npts;
615 
616  int pts_per_line = s / n;
617 
618  int packed_len = pts_per_line * m_num_homogeneous_points[1];
619 
620  for (int i = 0; i < packed_len; ++i)
621  {
622  Vmath::Vcopy(m_num_homogeneous_points[0], &(inarray[i]), packed_len,
623  &(outarray[i * m_num_homogeneous_points[0]]), 1);
624  }
625  }
626 }
627 
628 // TODO: Impelement 2D and 3D transposition routines
629 } // namespace LibUtilities
630 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
Describes the specification for a Basis.
Definition: Basis.h:50
int GetNumPoints() const
Return points order at which basis is defined.
Definition: Basis.h:130
BasisType GetBasisType() const
Return type of expansion basis.
Definition: Basis.h:141
int GetNumModes() const
Returns the order of the basis.
Definition: Basis.h:83
void TransposeYZtoZY(const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool UseNumMode=false)
Array< OneD, unsigned int > GetKs(void)
unsigned int m_strip_ID
IDs of the strips on the processes.
Array< OneD, int > m_num_homogeneous_coeffs
Total number of homogeneous coefficients.
Array< OneD, unsigned int > GetPlanesIDs(void)
void TransposeYZtoX(const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool UseNumMode=false)
Array< OneD, int > m_OffsetMap
MPI_Alltoallv offset map of send/recv buffer in global vector.
void Transpose(const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool UseNumMode=false, TranspositionDir dir=eNoTrans)
Transposition(const LibUtilities::BasisKey &HomoBasis0, LibUtilities::CommSharedPtr hcomm0, LibUtilities::CommSharedPtr hcomm1)
void TransposeXtoYZ(const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool UseNumMode=false)
Array< OneD, int > m_num_points_per_proc
Number of homogeneous points on each processor per direction.
Array< OneD, int > m_SizeMap
MPI_Alltoallv map containing size of send/recv buffer.
Array< OneD, int > m_num_homogeneous_points
Total homogeneous points per direction.
Array< OneD, unsigned int > m_K
Fourier wave numbers associated with the planes.
Array< OneD, unsigned int > m_planes_IDs
IDs of the planes on the processes.
void TransposeZtoXY(const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool UseNumMode=false)
void TransposeXYtoZ(const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool UseNumMode=false)
void TransposeZYtoYZ(const int npts, const Array< OneD, const NekDouble > &inarray, Array< OneD, NekDouble > &outarray, bool UseNumMode=false)
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:54
@ eFourierSingleMode
Fourier ModifiedExpansion with just the first mode .
Definition: BasisType.h:66
@ eFourierHalfModeIm
Fourier Modified expansions with just the imaginary part of the first mode .
Definition: BasisType.h:70
@ eFourierHalfModeRe
Fourier Modified expansions with just the real part of the first mode .
Definition: BasisType.h:68
@ eFourier
Fourier Expansion .
Definition: BasisType.h:57
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1255