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