Chombo + EB  3.2
Copier.H
Go to the documentation of this file.
1 #ifdef CH_LANG_CC
2 /*
3  * _______ __
4  * / ___/ / ___ __ _ / / ___
5  * / /__/ _ \/ _ \/ V \/ _ \/ _ \
6  * \___/_//_/\___/_/_/_/_.__/\___/
7  * Please refer to Copyright.txt, in Chombo's root directory.
8  */
9 #endif
10 
11 #ifndef _COPIER_H_
12 #define _COPIER_H_
13 
14 #include "DisjointBoxLayout.H"
15 #include "Pool.H"
16 #include "Vector.H"
17 #include "ProblemDomain.H"
18 #include <unordered_map>
19 #include <cstdint>
20 #include "NamespaceHeader.H"
21 
22 
23 typedef std::unordered_map<uint64_t, LayoutIndex> LMap;
24 
25 
26 class CopyIterator;
27 
28 // These classes are public because I can't find a nice
29 // way to make a class a friend of all the instantiations
30 // of a template class. These classes are not part of
31 // the public interface for the Array API.
32 //
33 // Later, if MotionItem shows up in the profiler, we
34 // can start using a pool allocation scheme and placement new
35 
37 {
38 public:
42  int procID;
43  // this constructor will probably eventually go away
44  MotionItem(const DataIndex& a_from,
45  const DataIndex& a_to,
46  const Box& a_region);
47  MotionItem(const DataIndex& a_from,
48  const DataIndex& a_to,
49  const Box& a_fromRegion,
50  const Box& a_toRegion);
51  void reverse();
52 
53  bool operator==(const MotionItem& rhs)
54  { return fromIndex == rhs.fromIndex && toIndex == rhs.toIndex &&
55  fromRegion == rhs.fromRegion && toRegion == rhs.toRegion &&
56  procID == rhs.procID;}
57 };
58 
60 {
61 public:
62 
63  ///null constructor, copy constructor and operator= can be compiler defined.
64  CopierBuffer():m_ncomps(0), m_sendbuffer(NULL), m_sendcapacity(0),
65  m_recbuffer(NULL), m_reccapacity(0)
66  {}
67 
68  ///
69  virtual ~CopierBuffer();
70 
71  void clear();
72 
73  bool isDefined(int ncomps) const
74  { return ncomps == m_ncomps;}
75 
76  mutable int m_ncomps;
77 
78  mutable void* m_sendbuffer; // pointer member OK here,
79  // since LevelData<T> has no copy
80  mutable size_t m_sendcapacity;
81  mutable void* m_recbuffer; // pointer member OK here,
82  // since LevelData<T> has no copy
83  mutable size_t m_reccapacity;
84 
85 #ifndef DOXYGEN
86 
87  struct bufEntry
88  {
89  void* bufPtr; // pointer into contiguous m_buffer
90  size_t size;
91  const MotionItem* item;
92  unsigned int procID;
93  bool operator < (const bufEntry& rhs) const
94  {
95  if (procID == rhs.procID)
96  {
97  const Box& left = item->toRegion;
98  const Box& right= rhs.item->toRegion;
99  if (left.smallEnd() == right.smallEnd())
100  {
101  return left.bigEnd().lexLT(right.bigEnd());
102  }
103  else
104  {
105  return item->toRegion < rhs.item->toRegion;
106  }
107  }
108  //else
109  return procID < rhs.procID;
110  }
111  };
112 
113 #endif
114  mutable std::vector<bufEntry> m_fromMe;
115  mutable std::vector<bufEntry> m_toMe;
116  mutable std::vector<std::vector<bufEntry> > m_toMeUnpack;
117 
118 
119 protected:
120 
121 };
122 
123 /// A strange but true thing to make copying from one boxlayoutdata to another fast
124 /**
125  class to handle the organization of data from a LevelData to a BoxLayoutData
126  defined over the same index space. The idea behind this object
127  is twofold:
128  A) there is a significant amount of information that can be
129  computed once and reused from one copy to the next for
130  a LevelData and BoxLayoutData that have unchanging BoxLayouts
131  underneath them. In these cases, LevelData::copyTo methods
132  has an optional argument. That way, in cases where the operation
133  is only performed a single time, we do not waste our time building
134  optimizing data, etc.
135  B) when we interface with KeLP, this class maps quite well
136  with the existing KeLP API (class MotionPlan).
137 
138  pains have been taken to not have this class be templated. Thus
139  it does not actually perform the copying itself (which would require
140  knowledge of the template class type). It provides an iterator
141  interface to MotionItems that specify the required work. LevelData
142  provides the copyTo methods.
143 */
144 
145 class Copier
146 {
147 public:
148 
149  ///null constructor, copy constructor and operator= can be compiler defined.
150  Copier():m_isDefined(false)
151  {}
152 
153  Copier(const Copier& a_rhs);
154 
155  ///
156  Copier(const DisjointBoxLayout& a_level,
157  const BoxLayout& a_dest,
158  bool a_exchange = false,
159  IntVect a_shift = IntVect::Zero);
160 
161  /// this constructor contains support for periodic BC's
162  Copier(const DisjointBoxLayout& a_level,
163  const BoxLayout& a_dest,
164  const ProblemDomain& a_domain,
165  bool a_exchange = false,
166  IntVect a_shift = IntVect::Zero);
167 
168  /// Copier to copy data into the valid and invalid regions of a_dest from a_level
169  Copier(const DisjointBoxLayout& a_level,
170  const BoxLayout& a_dest,
171  const IntVect& a_destGhost,
172  bool a_exchange = false,
173  IntVect a_shift = IntVect::Zero);
174 
175  /// Copier to copy data into the valid and invalid regions of a_dest from a_level with support for periodic BCs
176  Copier(const DisjointBoxLayout& a_level,
177  const BoxLayout& a_dest,
178  const ProblemDomain& a_domain,
179  const IntVect& a_destGhost,
180  bool a_exchange = false,
181  IntVect a_shift = IntVect::Zero);
182 
183  ///
184  virtual ~Copier();
185 
186  ///
187  virtual void define(const DisjointBoxLayout& a_level,
188  const BoxLayout& a_dest,
189  bool a_exchange = false,
190  IntVect a_shift = IntVect::Zero);
191 
192  /// contains support for periodic BCs
193  virtual void define(const DisjointBoxLayout& a_level,
194  const BoxLayout& a_dest,
195  const ProblemDomain& a_domain,
196  bool a_exchange = false,
197  IntVect a_shift = IntVect::Zero);
198 
199  ///
200  virtual void define(const DisjointBoxLayout& a_level,
201  const BoxLayout& a_dest,
202  const IntVect& a_destGhost,
203  bool a_exchange = false,
204  IntVect a_shift = IntVect::Zero);
205 
206  /// contains support for periodic BCs
207  virtual void define(const BoxLayout& a_level,
208  const BoxLayout& a_dest,
209  const ProblemDomain& a_domain,
210  const IntVect& a_destGhost,
211  bool a_exchange = false,
212  IntVect a_shift = IntVect::Zero);
213 
214  /// alternative version of define for exchange copiers that uses new optimized neighborIterator
215  virtual void exchangeDefine(const DisjointBoxLayout& a_grids,
216  const IntVect& a_ghost,
217  bool a_includeSelf=false);
218 
219  void defineFixedBoxSize(const DisjointBoxLayout& a_src,
220  const LMap& a_lmap,
221  const IntVect& a_ghost,
222  const ProblemDomain& a_domain,
223  bool a_includeSelf=false,
224  bool a_reverse=false);
225 
226  void defineFixedBoxSize(const DisjointBoxLayout& a_src,
227  const LMap& a_lmapSrc,
228  const IntVect& a_refRatioSrc,
229  const DisjointBoxLayout& a_dst,
230  const LMap& a_lmapDst,
231  const IntVect& a_refRatioDst,
232  const IntVect& a_ghost,
233  const ProblemDomain& a_domain,
234  bool a_reverse = false);
235 
236  void defineFixedSizeNodesCollect(const DisjointBoxLayout& a_layout,
237  const LMap& a_lmap,
238  const IntVect& a_ghostSrc,
239  const IntVect& a_ghostDst,
240  const ProblemDomain& a_domain);
241 
242  void defineFixedSizeNodesCollect(const DisjointBoxLayout& a_src,
243  const LMap& a_lmapSrc,
244  const IntVect& a_refRatioSrc,
245  const IntVect& a_ghostSrc,
246  const DisjointBoxLayout& a_dst,
247  const LMap& a_lmapDst,
248  const IntVect& a_refRatioDst,
249  const IntVect& a_ghostDst,
250  const ProblemDomain& a_domain);
251 
252  /// performs the computation necessary for moving from ghost+valid cells to all valid cells in a_dest
253  /** instead of copying from the valid of a_src to the valid+ghost of a_dest,
254  this routine defines a Copier that moves data from the ghost+valid region
255  of a_src to a_dest. This is used by LevelFluxRegister.
256  */
257  void ghostDefine(const DisjointBoxLayout& a_src,
258  const DisjointBoxLayout& a_dest,
259  const ProblemDomain& a_domain,
260  const IntVect& a_srcGhost);
261 
262  /// performs the computation necessary for moving from ghost+valid cells to all valid+ghost cells in a_dest
263  /** instead of copying from the valid of a_src to the valid+ghost of a_dest,
264  this routine defines a Copier that moves data from the ghost+valid region
265  of a_src to valid+ghost a_dest. This is used by BlockBaseRegister. Note that this does not handle
266  periodic matchings here. That is handled by different code in the MappedMultiBlock libraries.
267  Sending in a null-constructed ProblemDomain just results in a computation that ignores domain boundaries.
268  */
269  void ghostDefine(const DisjointBoxLayout& a_src,
270  const DisjointBoxLayout& a_dest,
271  const ProblemDomain& a_domain,
272  const IntVect& a_srcGhost,
273  const IntVect& a_destGhost);
274 
275  ///
276  virtual void clear();
277 
278  ///
279  /**
280  The assignment operator.
281 
282  */
283  Copier& operator= (const Copier& b);
284 
285  ///
286  /**
287  reverse the communication of this Copier.
288  */
289  void reverse();
290 
291  ///
292  /**
293  Under the right algorithmic circumstances, a user might know that they no not
294  need corner cells filled in exchanges, what they really need are just sufficient
295  ghost cells in each CH_SPACEDIM direction for each valid cell. This operation
296  eliminates copy operations that do not contribute to such cells. Under reasonable
297  3D configurations this can eliminate more than half the copy operations.
298  */
299  void trimEdges(const DisjointBoxLayout& a_exchangedLayout, const IntVect& ghost);
300 
301  ///
302  /*
303  OK, if you *really* know what you are doing (!) you can coarsen a Copier in place of
304  building a new Copier on a coarsened DisjointBoxLayout. The trick is when you do have
305  ghost cells and working out on paper for yourself that the coarsening is valid. One
306  common configuration is an exchange Copier with *one* ghost cell. A particular
307  case where coarsen will do the *wrong* thing is an exchange Copier with more than one
308  ghost cell.
309  **/
310  void coarsen(int a_refRatio);
311 
312  ///
313  /* check equality of two Copiers. Full check of every MotionItem
314  */
315  bool operator==(const Copier& rhs) const;
316 
317  int print() const;
318 
319  bool bufferAllocated() const;
320  void setBufferAllocated(bool arg) const;
321 
322  int numLocalCellsToCopy() const;
323  int numFromCellsToCopy() const;
324  int numToCellsToCopy() const;
325 
326  bool isDefined() const
327  { return m_isDefined;}
328 
330 
331  std::vector<IndexTM<int,2> > m_range;
332 protected:
333 
334  friend class CopyIterator;
335 
336 
340 
341  friend void dumpmemoryatexit();
343  mutable bool buffersAllocated;
344 
345  // keep a refcounted reference around for debugging purposes, we can
346  // decide afterwards if we want to eliminate it.
349 
351 
352  void trimMotion(const DisjointBoxLayout& a_exchangedLayout, const IntVect& a_ghost,
353  const Vector<MotionItem*>& a_oldItems, Vector<MotionItem*>& a_newItems);
354 
355  void sort();
356 
357  // sneaky end-around to problem of getting physDomains in derived classes
358  const ProblemDomain& getPhysDomain(const DisjointBoxLayout& a_level) const;
359 };
360 
361 std::ostream& operator<<(std::ostream& os, const Copier& copier);
362 
363 //===========================================================================
364 // end of public interface for Copier.
365 //===========================================================================
366 
367 inline MotionItem::MotionItem(const DataIndex& a_from,
368  const DataIndex& a_to,
369  const Box& a_region)
370  :fromIndex(a_from), toIndex(a_to), fromRegion(a_region),
371  toRegion(a_region), procID(-1)
372 {
373 }
374 
375 inline MotionItem::MotionItem(const DataIndex& a_from,
376  const DataIndex& a_to,
377  const Box& a_fromRegion,
378  const Box& a_toRegion)
379  :fromIndex(a_from), toIndex(a_to), fromRegion(a_fromRegion),
380  toRegion(a_toRegion), procID(-1)
381 {
382 }
383 
384 inline
386 {
387  Box tmp(fromRegion);
389  toRegion=tmp;
390  DataIndex tmpIndex(fromIndex);
391  fromIndex = toIndex;
392  toIndex = tmpIndex;
393 }
394 
396 {
397 public:
399  {
402  TO
403  };
404 
405  inline CopyIterator(const Copier& a_copier, local_from_to);
406 
407  inline const MotionItem& operator()() const;
408 
409  inline const MotionItem& operator[](size_t index) const;
410 
411  inline void operator++();
412 
413  inline bool ok() const;
414 
415  inline void reset();
416 
417  inline size_t size(){ return m_motionplanPtr->size();}
418 
419 private:
421  unsigned int m_current;
422 };
423 
424 //====== inlined functions====================================
425 
426 inline CopyIterator::CopyIterator(const Copier& a_copier, local_from_to type)
427  :m_current(0)
428 {
429  switch(type)
430  {
431  case LOCAL:
432  m_motionplanPtr = &(a_copier.m_localMotionPlan);
433  break;
434  case FROM:
435  m_motionplanPtr = &(a_copier.m_fromMotionPlan);
436  break;
437  case TO:
438  m_motionplanPtr = &(a_copier.m_toMotionPlan);
439  break;
440  default:
441  MayDay::Error("illegal local_from_to option for CopyIterator");
442  }
443 }
444 
446 {
447  CH_assert(m_current < m_motionplanPtr->size());
448  return *(m_motionplanPtr->operator[](m_current));
449 }
450 
451 inline const MotionItem& CopyIterator::operator[](size_t a_index) const
452 {
453  CH_assert(a_index < m_motionplanPtr->size());
454  return *(m_motionplanPtr->operator[](a_index));
455 }
456 
458 {
459  ++m_current;
460 }
461 
462 inline bool CopyIterator::ok() const
463 {
464  return m_current < m_motionplanPtr->size();
465 }
466 
467 inline void CopyIterator::reset()
468 {
469  m_current = 0;
470 }
471 
472 #include "NamespaceFooter.H"
473 #endif
bool isDefined(int ncomps) const
Definition: Copier.H:73
std::vector< IndexTM< int, 2 > > m_range
Definition: Copier.H:331
bool isDefined() const
Definition: Copier.H:326
void reset()
Definition: Copier.H:467
#define CH_assert(cond)
Definition: CHArray.H:37
A class to facilitate interaction with physical boundary conditions.
Definition: ProblemDomain.H:141
CopierBuffer m_buffers
Definition: Copier.H:329
Vector< MotionItem * > m_fromMotionPlan
Definition: Copier.H:338
int m_ncomps
Definition: Copier.H:76
std::unordered_map< uint64_t, LayoutIndex > LMap
Definition: Copier.H:23
A not-necessarily-disjoint collective of boxes.
Definition: BoxLayout.H:145
one dimensional dynamic array
Definition: Vector.H:53
A strange but true thing to make copying from one boxlayoutdata to another fast.
Definition: Copier.H:145
std::ostream & operator<<(std::ostream &os, const Copier &copier)
const MotionItem & operator[](size_t index) const
Definition: Copier.H:451
std::vector< std::vector< bufEntry > > m_toMeUnpack
Definition: Copier.H:116
std::vector< bufEntry > m_fromMe
Definition: Copier.H:114
DisjointBoxLayout m_originPlan
Definition: Copier.H:347
Definition: Copier.H:401
bool m_isDefined
Definition: Copier.H:350
Definition: Copier.H:59
size_t m_sendcapacity
Definition: Copier.H:80
size_t size()
Definition: Copier.H:417
void reverse()
Definition: Copier.H:385
static Pool s_motionItemPool
Definition: Copier.H:342
Definition: Copier.H:402
Definition: Copier.H:36
int procID
Definition: Copier.H:42
IndexTM< T, N > coarsen(const IndexTM< T, N > &a_p, T a_s)
Definition: IndexTMI.H:430
DataIndex toIndex
Definition: Copier.H:39
const IntVect & bigEnd() const
Definition: Box.H:1768
BoxLayout m_dest
Definition: Copier.H:348
Vector< MotionItem * > m_toMotionPlan
Definition: Copier.H:339
size_t m_reccapacity
Definition: Copier.H:83
void * m_recbuffer
Definition: Copier.H:81
MotionItem(const DataIndex &a_from, const DataIndex &a_to, const Box &a_region)
Definition: Copier.H:367
void * m_sendbuffer
Definition: Copier.H:78
const IntVect & smallEnd() const
{ Accessors}
Definition: Box.H:1754
bool operator<(const FaceIndex &f1, const FaceIndex &f2)
Definition: FaceIndex.H:212
Pool is a class to optimize memory allocation.
Definition: Pool.H:63
bool buffersAllocated
Definition: Copier.H:343
A BoxLayout that has a concept of disjointedness.
Definition: DisjointBoxLayout.H:30
CopierBuffer()
null constructor, copy constructor and operator= can be compiler defined.
Definition: Copier.H:64
Vector< MotionItem * > m_localMotionPlan
Definition: Copier.H:337
size_t size() const
Definition: Vector.H:192
Box toRegion
Definition: Copier.H:41
static void Error(const char *const a_msg=m_nullString, int m_exitCode=CH_DEFAULT_ERROR_CODE)
Print out message to cerr and exit with the specified exit code.
unsigned int m_current
Definition: Copier.H:421
void operator++()
Definition: Copier.H:457
static const IntVect Zero
Definition: IntVect.H:654
A Rectangular Domain on an Integer Lattice.
Definition: Box.H:465
void dumpmemoryatexit()
Definition: DataIndex.H:112
Copier()
null constructor, copy constructor and operator= can be compiler defined.
Definition: Copier.H:150
const MotionItem & operator()() const
Definition: Copier.H:445
local_from_to
Definition: Copier.H:398
An integer Vector in SpaceDim-dimensional space.
Definition: CHArray.H:42
Definition: Copier.H:400
bool ok() const
Definition: Copier.H:462
const Vector< MotionItem * > * m_motionplanPtr
Definition: Copier.H:420
DataIndex fromIndex
Definition: Copier.H:39
bool operator==(const MotionItem &rhs)
Definition: Copier.H:53
Box fromRegion
Definition: Copier.H:40
CopyIterator(const Copier &a_copier, local_from_to)
Definition: Copier.H:426
std::vector< bufEntry > m_toMe
Definition: Copier.H:115
Definition: Copier.H:395
bool lexLT(const IntVect &s) const
Definition: IntVect.H:898