distributionMap.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Class
25  Foam::distributionMap
26 
27 Description
28  Class containing processor-to-processor mapping information.
29 
30  We store mapping from the bits-to-send to the complete starting list
31  (subXXXMap) and from the received bits to their location in the new
32  list (constructXXXMap).
33 
34  Schedule is a list of processor pairs (one send, one receive. One of
35  them will be myself) which forms a scheduled (i.e. non-buffered) exchange.
36  See distribute on how to use it.
37  Note2: number of items sent on one processor have to equal the number
38  of items received on the other processor.
39 
40  To aid constructing these maps there are the constructors from global
41  numbering, either with or without transforms.
42 
43  - without transforms:
44  Constructors using compact numbering: layout is
45  - all my own elements first (whether used or not)
46  - followed by used-only remote elements sorted by remote processor.
47  So e.g 4 procs and on proc 1 the compact
48  table will first have all globalIndex.localSize() elements from proc1
49  followed by used-only elements of proc0, proc2, proc3.
50  The constructed distributionMap sends the local elements from and
51  receives the remote elements into their compact position.
52  compactMap[proci] is the position of elements from proci in the compact
53  map. compactMap[myProcNo()] is empty since trivial addressing.
54 
55  It rewrites the input global indices into indices into the constructed
56  data.
57 
58 
59  - with transforms:
60  This requires the precalculated set of possible transforms
61  (globalIndexAndTransform). These are given as permutations (+, -, or none)
62  of up to 3 independent transforms.
63  The layout of the data is
64  - all my own elements first (whether used or not)
65  - followed by used-only remote elements sorted by remote processor.
66  - followed by - for each transformation index - the set of local or
67  remote elements with that transformation.
68  The inputs for the constructor are
69  - the set of untransformed local or remote indices in globalIndex
70  numbering. These get rewritten to be indices into the layout of the data.
71  - the set of transformed local or remote indices in globalIndexAndTransform
72  encoding. These are labelPairs.
73 
74  Any distribute with transforms is now done as:
75  1. exchange data with other processors and receive these into the
76  slots for that processor
77  2. for all transformations transform a subset of the data according
78  to transformElements_[transformI] and store this starting from
79  transformStart_[transformI]
80 
81  In the same way a reverse distribute will
82  1. apply the inverse transform to the data starting at
83  transformStart_[transformI] and copy the result back into the
84  transformElements_[transformI]. These might be local or remote slots.
85  2. the data in the remote slots will now be sent back to the correct
86  location in the originating processor.
87 
88  E.g. a map to handle
89  - mesh points on a mesh with
90  - 1 cyclic so 3 permutations (+,-,none) will have layout
91  - on e.g. processor 1 out of 2:
92 
93  +------+ <- transformStart[2]
94  | |
95  | | <- transform2 applied to data in local or remote slots
96  | |
97  +------+ <- transformStart[1]
98  | |
99  | | <- transform1 applied to data in local or remote slots
100  | |
101  +------+ <- transformStart[1]
102  | |
103  | | <- transform0 applied to data in local or remote slots
104  | |
105  +------+ <- transformStart[0]
106  | |
107  | | <- data from proc2
108  | |
109  +------+
110  | |
111  | | <- data from proc0
112  | |
113  +------+ <- mesh.nPoints()
114  | |
115  | |
116  | |
117  +------+ 0
118 
119  When constructing from components optionally a 'flip' on
120  the maps can be specified. This will interpret the map
121  values as index+flip, similar to e.g. faceProcAddressing. The flip
122  will only be applied to fieldTypes (scalar, vector, .. triad)
123 
124 SourceFiles
125  distributionMap.C
126  distributionMapTemplates.C
127 
128 \*---------------------------------------------------------------------------*/
129 
130 #ifndef distributionMap_H
131 #define distributionMap_H
132 
133 #include "distributionMapBase.H"
134 #include "transformer.H"
135 #include "coupledPolyPatch.H"
136 #include "EdgeMap.H"
137 
138 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
139 
140 namespace Foam
141 {
142 
143 class globalIndexAndTransform;
144 
145 
146 // Forward declaration of friend functions and operators
147 
148 class distributionMap;
149 
150 Istream& operator>>(Istream&, distributionMap&);
151 Ostream& operator<<(Ostream&, const distributionMap&);
152 
153 
154 /*---------------------------------------------------------------------------*\
155  Class distributionMap Declaration
156 \*---------------------------------------------------------------------------*/
157 
158 class distributionMap
159 :
160  public distributionMapBase
161 {
162  // Private Data
163 
164  //- For every globalIndexAndTransform::transformPermutations
165  // gives the elements that need to be transformed
166  labelListList transformElements_;
167 
168  //- Destination in constructMap for transformed elements
169  labelList transformStart_;
170 
171 
172  // Private Member Functions
173 
174  //- Helper function: copy transformElements without transformation
175  template<class T>
176  void applyDummyTransforms(List<T>& field) const;
177 
178  template<class T, class TransformOp>
179  void applyTransforms
180  (
181  const globalIndexAndTransform& globalTransforms,
182  List<T>& field,
183  const TransformOp& top
184  ) const;
185 
186  //- Helper function: copy transformElements without transformation
187  template<class T>
188  void applyDummyInverseTransforms(List<T>& field) const;
189 
190  template<class T, class TransformOp>
191  void applyInverseTransforms
192  (
193  const globalIndexAndTransform& globalTransforms,
194  List<T>& field,
195  const TransformOp& top
196  ) const;
197 
198 
199 public:
200 
201  // Public classes
202 
203  //- Default transformation behaviour
204  class transform
205  {
206  public:
207 
208  template<class Type>
209  void operator()
210  (
211  const transformer& vt,
212  const bool forward,
213  List<Type>& fld
214  ) const
215  {
216  if (forward)
217  {
218  vt.transformList(fld);
219  }
220  else
221  {
222  vt.invTransformList(fld);
223  }
224  }
225 
226  template<class Type>
227  void operator()
228  (
229  const transformer& vt,
230  const bool forward,
231  List<List<Type>>& flds
232  ) const
233  {
234  forAll(flds, i)
235  {
236  operator()(vt, forward, flds[i]);
237  }
238  }
239 
240  //- Transform patch-based field
241  template<class Type>
242  void operator()(const coupledPolyPatch& cpp, UList<Type>& fld) const
243  {
244  if (cpp.transform().transforms())
245  {
246  cpp.transform().transformList(fld);
247  }
248  }
249 
250  //- Transform sparse field
251  template<class Type, template<class> class Container>
252  void operator()(const coupledPolyPatch& cpp, Container<Type>& map)
253  const
254  {
255  if (cpp.transform().transforms())
256  {
257  cpp.transform().transformList(map);
258  }
259  }
260  };
261 
262  //- Default transformation behaviour for position
263  class transformPosition
264  {
265  public:
266 
267  void operator()
268  (
269  const transformer& vt,
270  const bool forward,
272  ) const
273  {
274  pointField pfld(move(fld));
275  if (forward)
276  {
277  fld = vt.transformPosition(pfld);
278  }
279  else
280  {
281  fld = vt.invTransformPosition(pfld);
282  }
283  }
284 
285  void operator()
286  (
287  const transformer& vt,
288  const bool forward,
289  List<List<point>>& flds
290  ) const
291  {
292  forAll(flds, i)
293  {
294  operator()(vt, forward, flds[i]);
295  }
296  }
297 
298  //- Transform patch-based field
299  void operator()(const coupledPolyPatch& cpp, pointField& fld) const
300  {
302  }
303 
304  template<template<class> class Container>
305  void operator()(const coupledPolyPatch& cpp, Container<point>& map)
306  const
307  {
308  Field<point> fld(map.size());
309 
310  label i = 0;
311  forAllConstIter(typename Container<point>, map, iter)
312  {
313  fld[i++] = iter();
314  }
315 
317 
318  i = 0;
319  forAllIter(typename Container<point>, map, iter)
320  {
321  iter() = fld[i++];
322  }
323  }
324  };
325 
326 
327  // Declare name of the class and its debug switch
328  ClassName("distributionMap");
329 
330 
331  // Constructors
332 
333  //- Construct null
334  distributionMap();
335 
336  //- Construct from components
338  (
339  const label constructSize,
342  const bool subHasFlip = false,
343  const bool constructHasFlip = false
344  );
345 
346  //- Construct from components
348  (
349  const label constructSize,
354  const bool subHasFlip = false,
355  const bool constructHasFlip = false
356  );
357 
358  //- Construct from reverse addressing: per data item the send
359  // processor and the receive processor. (note: data is not stored
360  // sorted per processor so cannot use printLayout).
362  (
363  const labelList& sendProcs,
364  const labelList& recvProcs
365  );
366 
367  //- Construct from list of (possibly) remote elements in globalIndex
368  // numbering (or -1). Determines compact numbering (see above) and
369  // distribute map to get data into this ordering and renumbers the
370  // elements to be in compact numbering.
372  (
373  const globalIndex&,
374  labelList& elements,
375  List<Map<label>>& compactMap,
376  const int tag = Pstream::msgType()
377  );
378 
379  //- Special variant that works with the info sorted into bins
380  // according to local indices. E.g. think cellCells where
381  // cellCells[localCelli] is a list of global cells
383  (
384  const globalIndex&,
385  labelListList& cellCells,
386  List<Map<label>>& compactMap,
387  const int tag = Pstream::msgType()
388  );
389 
390  //- Construct from list of (possibly remote) untransformed elements
391  // in globalIndex numbering (or -1) and (possibly remote)
392  // transformded elements in globalIndexAndTransform numbering.
393  // Determines compact numbering (see above) and
394  // distribute map to get data into this ordering and renumbers the
395  // elements to be in compact numbering.
397  (
398  const globalIndex&,
399  labelList& untransformedElements,
401  const labelPairList& transformedElements,
402  labelList& transformedIndices,
403  List<Map<label>>& compactMap,
404  const int tag = Pstream::msgType()
405  );
406 
407  //- As above but with ListLists.
409  (
410  const globalIndex&,
411  labelListList& cellCells,
413  const List<labelPairList>& transformedElements,
414  labelListList& transformedIndices,
415  List<Map<label>>& compactMap,
416  const int tag = Pstream::msgType()
417  );
418 
419  //- Copy constructor
421 
422  //- Move constructor
424 
425  //- Construct from Istream
427 
428  //- Clone
430 
431 
432  //- Destructor
433  virtual ~distributionMap()
434  {}
435 
436 
437  // Member Functions
438 
439  // Access
440 
441  //- For every globalIndexAndTransform::transformPermutations
442  // gives the elements that need to be transformed
443  const labelListList& transformElements() const
444  {
445  return transformElements_;
446  }
447 
448  //- Destination in constructMap for transformed elements
449  const labelList& transformStart() const
450  {
451  return transformStart_;
452  }
453 
454  //- Find transform from transformElements
455  label whichTransform(const label index) const;
456 
457 
458  // Other
459 
460  //- Transfer the contents of the argument and annul the argument.
461  void transfer(distributionMap&);
462 
463  //- Distribute data using default commsType.
464  template<class T>
465  void distribute
466  (
467  List<T>& fld,
468  const bool dummyTransform = true,
469  const int tag = UPstream::msgType()
470  ) const;
471 
472  //- Distribute data using default commsType.
473  template<class T, class negateOp>
474  void distribute
475  (
476  List<T>& fld,
477  const negateOp& negOp,
478  const bool dummyTransform = true,
479  const int tag = UPstream::msgType()
480  ) const;
481 
482  //- Distribute data using default commsType.
483  template<class T>
484  void distribute
485  (
487  const bool dummyTransform = true,
488  const int tag = UPstream::msgType()
489  ) const;
490 
491  //- Reverse distribute data using default commsType.
492  template<class T>
493  void reverseDistribute
494  (
495  const label constructSize,
496  List<T>&,
497  const bool dummyTransform = true,
498  const int tag = UPstream::msgType()
499  ) const;
500 
501  //- Reverse distribute data using default commsType.
502  // Since constructSize might be larger than supplied size supply
503  // a nullValue
504  template<class T>
505  void reverseDistribute
506  (
507  const label constructSize,
508  const T& nullValue,
509  List<T>& fld,
510  const bool dummyTransform = true,
511  const int tag = UPstream::msgType()
512  ) const;
513 
514  //- Distribute with transforms
515  template<class T, class TransformOp>
516  void distribute
517  (
519  List<T>& fld,
520  const TransformOp& top,
521  const int tag = UPstream::msgType()
522  ) const;
523 
524  //- Reverse distribute with transforms
525  template<class T, class TransformOp>
526  void reverseDistribute
527  (
529  const label constructSize,
530  List<T>& fld,
531  const TransformOp& top,
532  const int tag = UPstream::msgType()
533  ) const;
534 
535  //- Reverse distribute with transforms
536  template<class T, class TransformOp>
537  void reverseDistribute
538  (
540  const label constructSize,
541  const T& nullValue,
542  List<T>& fld,
543  const TransformOp& top,
544  const int tag = UPstream::msgType()
545  ) const;
546 
547  //- Debug: print layout. Can only be used on maps with sorted
548  // storage (local data first, then non-local data)
549  void printLayout(Ostream& os) const;
550 
551 
552  // Member Operators
553 
554  void operator=(const distributionMap&);
555 
556 
557  // IOstream Operators
558 
559  //- Read dictionary from Istream
561 
562  //- Write dictionary to Ostream
563  friend Ostream& operator<<(Ostream&, const distributionMap&);
564 };
565 
566 
567 // Template specialisation for primitives that do not need transform
568 template<>
569 void distributionMap::transform::operator()
570 (
571  const transformer&,
572  const bool,
573  List<label>&
574 ) const;
575 template<>
576 void distributionMap::transform::operator()
577 (
578  const coupledPolyPatch&,
579  UList<label>&
580 ) const;
581 template<>
582 void distributionMap::transform::operator()
583 (
584  const coupledPolyPatch&,
585  Map<label>&
586 ) const;
587 template<>
588 void distributionMap::transform::operator()
589 (
590  const coupledPolyPatch&,
592 ) const;
593 
594 template<>
595 void distributionMap::transform::operator()
596 (
597  const coupledPolyPatch&,
599 ) const;
600 template<>
601 void distributionMap::transform::operator()
602 (
603  const transformer&,
604  const bool,
605  List<scalar>&
606 ) const;
607 template<>
608 void distributionMap::transform::operator()
609 (
610  const coupledPolyPatch&,
611  Map<scalar>&
612 ) const;
613 template<>
614 void distributionMap::transform::operator()
615 (
616  const coupledPolyPatch&,
618 ) const;
619 
620 template<>
621 void distributionMap::transform::operator()
622 (
623  const coupledPolyPatch& cpp,
625 ) const;
626 template<>
627 void distributionMap::transform::operator()
628 (
629  const transformer&,
630  const bool,
631  List<bool>&
632 ) const;
633 template<>
634 void distributionMap::transform::operator()
635 (
636  const coupledPolyPatch&,
637  Map<bool>&
638 ) const;
639 template<>
640 void distributionMap::transform::operator()
641 (
642  const coupledPolyPatch&,
644 ) const;
645 
646 
647 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
648 
649 } // End namespace Foam
650 
651 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
652 
653 #ifdef NoRepository
654  #include "distributionMapTemplates.C"
655 #endif
656 
657 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
658 
659 #endif
660 
661 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:459
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:78
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:476
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
virtual const transformer & transform() const =0
Return transformation between the coupled patches.
Class containing processor-to-processor mapping information.
bool subHasFlip() const
Does subMap include a sign.
const labelListList & constructMap() const
From subsetted data to new reconstructed data.
const labelListList & subMap() const
From subsetted data back to original data.
bool constructHasFlip() const
Does constructMap include a sign.
label constructSize() const
Constructed data size.
Default transformation behaviour for position.
void operator()(const transformer &vt, const bool forward, List< point > &fld) const
Default transformation behaviour.
void operator()(const transformer &vt, const bool forward, List< Type > &fld) const
Class containing processor-to-processor mapping information.
virtual ~distributionMap()
Destructor.
label whichTransform(const label index) const
Find transform from transformElements.
const labelListList & transformElements() const
For every globalIndexAndTransform::transformPermutations.
friend Ostream & operator<<(Ostream &, const distributionMap &)
Write dictionary to Ostream.
void printLayout(Ostream &os) const
Debug: print layout. Can only be used on maps with sorted.
void transfer(distributionMap &)
Transfer the contents of the argument and annul the argument.
autoPtr< distributionMap > clone() const
Clone.
ClassName("distributionMap")
const labelList & transformStart() const
Destination in constructMap for transformed elements.
void distribute(List< T > &fld, const bool dummyTransform=true, const int tag=UPstream::msgType()) const
Distribute data using default commsType.
friend Istream & operator>>(Istream &, distributionMap &)
Read dictionary from Istream.
void operator=(const distributionMap &)
distributionMap()
Construct null.
void reverseDistribute(const label constructSize, List< T > &, const bool dummyTransform=true, const int tag=UPstream::msgType()) const
Reverse distribute data using default commsType.
Determination and storage of the possible independent transforms introduced by coupledPolyPatches,...
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:64
Vector-tensor class used to perform translations, rotations and scaling operations in 3D space.
Definition: transformer.H:84
void transformList(Container< Type > &) const
Transform the given container.
bool transforms() const
Return true if the transformer transforms a type.
Definition: transformerI.H:133
vector transformPosition(const vector &v) const
Transform the given position.
Definition: transformerI.H:153
gmvFile<< "tracers "<< particles.size()<< nl;{ pointField positions(particles.size());label particlei=0;forAllConstIter(Cloud< passiveParticle >, particles, iter) { positions[particlei++]=iter().position(mesh);} for(i=0;i< pTraits< point >::nComponents;i++) { forAll(positions, particlei) { gmvFile<< component(positions[particlei], i)<< ' ';} gmvFile<< nl;}}forAll(lagrangianScalarNames, i){ const word &name=lagrangianScalarNames[i];IOField< scalar > fld(IOobject(name, runTime.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Namespace for OpenFOAM.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Istream & operator>>(Istream &, directionInfo &)
Ostream & operator<<(Ostream &, const ensightPart &)
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)