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