Chombo + EB  3.0
BoxLayout.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 
12 #ifndef _BOXLAYOUT_H_
13 #define _BOXLAYOUT_H_
14 
15 #include "Box.H"
16 #include "Vector.H"
17 #include "RefCountedPtr.H"
18 #include "DataIndex.H"
19 #include "SPMD.H"
20 #include "LoHiSide.H"
21 #include "ProblemDomain.H"
22 #include "NamespaceHeader.H"
23 
24 class DataIterator;
25 class TimedDataIterator;
26 class LayoutIterator;
27 
28 ///Base class to transform boxes in an existing layout
29 /**
30  If you want to do something esoteric to each box in a layout and preserve
31  its ordering and proc assignment, here is what you do.
32  Define your own transformation that inherits from this and here is
33  what the code will look like.
34 
35  class MyTransform: public BaseTransform
36  {
37  virtual Box operator()(const Box& a_inputBox)
38  {
39  ///do what you need to output the box you want given the input
40  }
41  };
42 
43  BoxLayout bl1; //fill this one with starting layout
44  BoxLayout bl2 = bl1;
45  MyTransform mytrans;
46  bl2.transform(mytrans);
47  */
49 {
50 public:
51  ///
52  virtual Box operator()(const Box& a_inputBox) = 0;
53 
54  ///apparently I have to declare this to make some compilers happy.
55  virtual ~BaseTransform()
56  {
57  ;
58  }
59 };
60 
61 struct Entry
62 {
64  :
65  m_procID(procID())
66  {}
67 
68  Entry(const Box& a_box)
69  :
70  box(a_box),
71  m_procID(procID())
72  {}
73 
74  Entry(const Box& a_box, const unsigned int a_index)
75  :
76  box(a_box),
77  m_procID(procID())
78  {}
79 
80  bool operator < (const Entry& rhs) const
81  {
82  return box < rhs.box;
83  }
84 
86  unsigned int m_procID;// not used in serial code.
87 };
88 
89 
90 ///A not-necessarily-disjoint collective of boxes.
91 /**
92  A BoxLayout is a collection of Box objects that are assigned
93  to process numbers. Each box is associated with only one
94  process. Processes are numbered from 0 to n-1 (for a job with
95  n processes).
96 
97  A BoxLayout can be either open or closed.
98 
99  Open BoxLayout:
100  - Created by null construction or deepCopy.
101  - Boxes may be added to it.
102  - Non-const operations may be performed on the boxes in it.
103 
104  Closed BoxLayout:
105  - Created by constructor with vectors of Boxes and processors given explicitly.
106  - Cannot be modified.
107  - Represented as sorted boxes.
108  - Many uses of BoxLayouts require a closed BoxLayout.
109 
110  <b>Ref-counting</b>
111 
112  BoxLayout is an explicitly ref-counted object.
113 
114  Assignment and copy are compiler-generated. They increment the refcount
115  on the contained data members. They perform shallow, ref-counted
116  operations.
117 
118  Refcounting is a process whereby multiple instantiations make
119  use of a single implementation of that object and keep a tally
120  of how many instantiations are sharing. Thus:
121  <PRE>
122 
123  BoxLayout b1(boxes, procIDs);
124 
125  b1 ----> refcount = 1
126  ----> m_boxes
127  ----> m_processors
128 
129  BoxLayout b2(b1)
130 
131  b1 ----> refcount = 2 <---- b2
132  ----> m_boxes <----
133  ----> m_processors <----
134 
135  BoxLayout b3;
136  b3 = b2;
137 
138  b1 ----> refcount = 3 <---- b2
139  ----> m_boxes <----
140  ----> m_processors <----
141  ^^^
142  |||
143  b3
144  </PRE>
145 */
147 {
148 public:
149 
150  /**
151  \name Constructors, destructors, assignments, defines
152  */
153  /*@{*/
154 
155  ///
156  /**
157  Construct BoxLayout with no boxes.
158  */
159  BoxLayout();
160 
161  ///
162  /** Construct from a Vector of Boxes and a Vector of
163  processor assignments. On exit, the BoxLayout will be closed.
164  */
165  BoxLayout(const Vector<Box>& a_boxes,
166  const Vector<int>& a_procIDs);
167 
168 
169  ///
170  void transform(BaseTransform& a_transform);
171 
172  ///
173  /**
174  Ref-counted destruction. Once the last reference to the
175  implementation of this class is destroyed, the data members
176  are cleaned up
177  */
178  virtual
179  ~BoxLayout();
180 
181  ///
182  /**
183  Ref-counted assignment.
184  */
185  BoxLayout& operator=(const BoxLayout& a_rhs);
186 
187  ///
188  /** Define this BoxLayout from a Vector of Boxes and a
189  Vector of processor assignments. Any pre-existing layout will
190  be lost (ref-count dropped by one). The processor assignment Vector
191  must be the same length
192  as the Box Vector. On exit, the BoxLayout will be closed.
193  */
194  virtual void
195  define(const Vector<Box>& a_boxes,
196  const Vector<int>& a_procIDs);
197 
198 
199 
200  /*@}*/
201 
202  /**
203  \name Accessors
204  */
205  /*@{*/
206 
207  ///
208  /** const accessor operator. See also get(const LayoutIndex&).
209  */
210  Box
211  operator[](const LayoutIndex& it) const;
212 
213 
214  ///
215  /** accessor operator. See also get(const LayoutIndex&).
216  */
217  Box
218  operator[](const LayoutIterator& it) const;
219 
220  ///
221  /** accessor operator. See also get(const LayoutIndex&).
222  */
223  Box
224  operator[](const DataIterator& it) const;
225 
226  ///
227  /** Get box indexed by <i>it</i>.
228 
229  As a consequence of the C++ compiler being free to choose which
230  version of operator[] when the object is technically non-const, we very
231  often get 'BoxLayout closed' errors.
232  This is a non-overloaded get method.
233  */
234  Box get(const LayoutIndex& it) const;
235 
236 
237  ///
238  /** Get box indexed by <i>it</i>. equivalent to get(it()), just does the extra() for you.
239  */
240  Box get(const DataIterator& it) const;
241 
242  ///
243  /** Get box indexed by <i>it</i>. equivalent to get(it()), just does the extra() for you.
244  */
245  Box get(const LayoutIterator& it) const;
246 
247  ///
248  /** Returns the processor to which this box has been assigned.
249  Not a user function, at least, not a new user function. It can
250  be used safely at anytime, closed or open. A person needing this
251  level of knowledge of the processor assignment should have non-trivial
252  needs, like writing your own load balancer or such.
253  Most user-level parallel
254 
255  */
256  unsigned int
257  procID(const LayoutIndex& a_index) const ;
258 
259  /// Checks whether this layout has the same boxes in the same order as a_layout.
260  /** Checks whether this layout has the same boxes in the same order as a_layout.
261  */
262  bool sameBoxes(const BoxLayout& a_layout) const;
263 
264  /// Returns the number of boxes assigned to a given procID.
265  /** Returns the number of boxes assigned to a given procID.
266  */
267  int numBoxes(const int procID) const;
268 
269 
270  /// Return number of cells in all boxes of entire box layout
271  long long numCells() const;
272 
273  /// Returns the total number of boxes in the BoxLayout.
274  /** Returns the total number of boxes in the BoxLayout.
275  */
276  unsigned int
277  size() const ;
278 
279  /** Not a user function. Used in I/O routine.
280  */
281  unsigned int index(const LayoutIndex& index) const;
282 
283  unsigned int lindex(const DataIndex& index) const;
284  /*@}*/
285 
286  /**
287  \name Checks
288  */
289  /*@{*/
290 
291  ///
292  /** Refcounted pointer check. Return <tt>true</tt> if these two objects
293  share the same implementation.
294  */
295  inline bool
296  operator==(const BoxLayout& rhs) const ;
297 
298  /**
299  RefCounted pointer compare. Need this to use DisjointBoxLayout as a Key in a std::map
300  */
301  inline bool operator<(const BoxLayout& rhs) const ;
302 
303  /**
304  current ref count for this object
305  */
306  int refCount() const
307  {
308  return m_boxes.refCount();
309  }
310  ///
311  /** Refcounted pointer check. Return <tt>true</tt> if these two objects
312  share the same implementation.
313  */
314  bool eq(const BoxLayout& rhs) const
315  {
316  return *this == rhs;
317  }
318 
319  /** Return <tt>true</tt> if close() has been called.
320  Closed BoxLayout is always sorted.
321  */
322  bool
323  isClosed() const;
324 
325  ///
326  /** Return <tt>true</tt> if sort() has been called.
327  */
328  bool
329  isSorted() const
330  {
331  return *m_sorted;
332  }
333 
334  /** not a user function
335  */
336  bool check(const LayoutIndex& index) const
337  { return index.m_layoutIntPtr == m_layout;}
338 
339 
340  ///
341  /**
342  returns 'true' if you can use the same LayoutIterator and DataIterator on these
343  two layouts and data holders built on top of these layouts
344  */
345  bool compatible(const BoxLayout& a_rhs) const
346  {
347  return m_layout == a_rhs.m_layout;
348  }
349 
350  /*@}*/
351 
352  /**
353  \name Modification functions
354  */
355  /*@{*/
356 
357  ///
358  /** Mark this BoxLayout as complete and unchangeable.
359  */
360  virtual void
361  close();
362 
363  // not for general consumption.
364  virtual void
365  closeNoSort();
366 
367 
368  ///
369  /** Actual deep copy operation. New object created with copied
370  data. This object disassociates itself with original implementation
371  safely. This object now is considered 'open' and can be non-const
372  modified. There is no assurance that the order in which this BoxLayout
373  is indexed corresponds to the indexing of <i>a_source</i>.
374 <PRE>
375  BoxLayout b1(boxes, procIDs);
376 
377  b1 ----> refcount = 1
378  ----> m_boxes
379  ----> m_processors
380 
381  BoxLayout b2(b1)
382 
383  b1 ----> refcount = 2 <---- b2
384  ----> m_boxes <----
385  ----> m_processors <----
386 
387  BoxLayout b3;
388  b3.deepCopy(b2);
389  b1 ----> refcount = 2 <---- b2 b3 ----> refcount = 1
390  ----> m_boxes <---- ----> m_boxes
391  ----> m_processors <---- ----> m_processors
392 </PRE>
393  */
394  virtual void
395  deepCopy(const BoxLayout& a_source);
396 
397  ///
398  /**
399  returns true iff:
400  - every Box in the BoxLayout can be coarsened by refRatio and return back
401  to the original Box when refined by refRatio.
402  - refRatio must be a positive non-zero integer.
403  */
404  bool coarsenable(int refRatio) const;
405 
406  ///
407  /**
408  Coarsen a BoxLayout:
409  - <i>output</i> must be open
410  - <i>input</i> must be closed
411  - <i>refinement</i> must be a positive non-zero integer
412  - <i>output</i> and <i>input</i> do not share an
413  implementation.
414 
415  <i>output</i> is first deepCopy'ed from <i>input</i>,
416  then coarsen(refinement) is called on each box of <i>output</i>.
417 
418  <i>output</i> returns from this function closed.
419 
420  LayoutIterators and DataIterators from <i>input</i> and <i>output</i>
421  can be used interchangeably.
422  */
423  friend void coarsen(BoxLayout& output,
424  const BoxLayout& input,
425  int refinement);
426 
427  ///
428  /**
429  if a_sd == side::lo, do growLo, else do grow hi with the other arguments.
430  */
431  void growSide(int idir, int length, Side::LoHiSide a_sd);
432 
433  ///
434  /**
435  Do surroundingNodes on each box.
436  */
437  void surroundingNodes();
438 
439  ///
440  /**
441  multiblock stuff.
442  */
443  void convertOldToNew(const IntVect& a_permutation,
444  const IntVect& a_sign,
445  const IntVect& a_translation);
446 
447  ///
448  /**
449  multiblock stuff.
450  */
451  void convertNewToOld(const IntVect& a_permutation,
452  const IntVect& a_sign,
453  const IntVect& a_translation);
454 
455  ///
456  /**
457  Do enclosedCells on each box.
458  */
459  void enclosedCells();
460 
461  ///
462  /**
463  coarsen each box by a_ref
464  */
465  void coarsen(int a_ref);
466 
467 
468  ///
469  /**
470  refine each box by a_ref
471  */
472  void refine(int a_ref);
473 
474 
475  ///
476  /**
477  grow each box by a_growth
478  */
479  void grow(int a_growth);
480 
481  ///
482  /**
483  grow each box by a_growth
484  */
485  void grow(IntVect a_growth);
486 
487  ///
488  /**
489  grow each box in a_dir by a_growth
490  */
491  void grow(int a_dir, int a_growth);
492 
493 
494  ///
495  /**
496  set each box to the appropriate adjCellSide call
497  if a_sd == side::lo, do adjCellLo, else do adjCellhi with the other arguments.
498  */
499  void adjCellSide(int a_dir, int a_len, Side::LoHiSide a_sd);
500 
501  ///
502  /**
503  intersect all boxes with incoming box
504  */
505  void operator&= (const Box& a_box);
506 
507  ///
508  /**
509  intersect all boxes with incoming box
510  */
511  void operator&= (const ProblemDomain& a_domain);
512 
513  ///
514  /**
515  Refine a BoxLayout:
516  - <i>output</i> must be open
517  - <i>input</i> must be closed
518  - <i>refinement</i> must be a positive non-zero integer
519  - <i>output</i> and <i>input</i> do not share an
520  implementation.
521 
522  <i>output</i> is first deepCopy'ed from <i>input</i>,
523  then refine(refinement) is called on each box of <i>output</i>.
524 
525  <i>output</i> returns from this function closed.
526 
527  LayoutIterators and DataIterators from <i>input</i> and <i>output</i>
528  can be used interchangeably.
529  */
530  friend void refine(BoxLayout& output,
531  const BoxLayout& input,
532  int refinement);
533 
534  ///
535  /** Assign a Box in the BoxLayout to a processor.
536  Requires the BoxLayout to be open.
537  */
538  void
539  setProcID(const LayoutIndex& a_index, unsigned int a_procID);
540 
541  //const or non-const operation ?.....I can think of usages either way...bvs
542  ///
543  /**
544  Sort the boxes of an open BoxLayout.
545  No change if the BoxLayout is closed.
546  */
547  void
548  sort();
549 
550 
551  /*@}*/
552 
553  /**
554  \name Iterators
555  */
556  /*@{*/
557 
558  ///Parallel iterator.
559  /** Parallel iterator.
560 
561  Returns DataIndex object that corresponds to boxes
562  on the local processor only. */
564  dataIterator() const;
565 
566  ///
568  timedDataIterator() const;
569 
570  ///Iterator that processes through ALL the boxes in a BoxLayout.
571  /** Iterator that processes through ALL the boxes in a BoxLayout.
572 
573  If BoxLayout is closed, then LayoutIterator will return
574  the Boxes in sorted order. */
576  layoutIterator() const;
577 
578  /*@}*/
579 
580  /**
581  \name I/O functions
582  */
583  /*@{*/
584 
585  ///
586  /**
587  Invokes cout<<*this; pretty-print dump of BoxLayout.
588  */
589  void
590  print() const;
591 
592  ///
593  /**
594  Invokes cout<<*this; pretty-print dump of BoxLayout.
595  */
596  void p() const
597  {
598  print();
599  }
600 
601  /*@}*/
602 
603  /* Return all the constituent boxes. */
604  Vector<Box> boxArray() const;
605 
606  /** Return the processor id numbers corresponding to the boxes as returned by
607  * this->boxArray().
608  */
609  Vector<int> procIDs() const;
610 
611  inline unsigned int indexI(const LayoutIndex&) const;
612 
613 protected:
614 
615  void buildDataIndex();
616  friend class LayoutIterator;
617  friend class DataIterator;
618 
625 
626 #ifdef CH_MPI
627  RefCountedPtr<Vector<DataIndex> > m_dataIndex;
628 #endif
629 
630  void checkDefine(const Vector<Box>& a_boxes, const Vector<int>& procIDs);
631 private:
632 
633 };
634 
635 void coarsen_bl(BoxLayout& output, const BoxLayout& input, int refinement);
636 
637 void refine_bl(BoxLayout& output, const BoxLayout& input, int refinement);
638 
639 
640 inline
641 void coarsen_bl(BoxLayout& output, const BoxLayout& input, int refinement)
642 {
643  coarsen(output, input, refinement);
644 }
645 
646 inline
647 void refine_bl(BoxLayout& output, const BoxLayout& input, int refinement)
648 {
649  refine(output, input, refinement);
650 }
651 
652 void mortonOrdering(Vector<Box>& a_boxes);
653 
654 //========================================================
655 
656 inline Box
657 BoxLayout::operator[](const LayoutIndex& a_layoutIndex) const
658 {
659  CH_assert(check(a_layoutIndex));// make sure this LayoutIndex came from my own iterator
660  return m_boxes->operator[](a_layoutIndex.m_index).box;
661 }
662 
663 
664 
665 inline bool
667 {
668  return m_boxes == rhs.m_boxes;
669 }
670 
671 inline bool
673 {
674  return m_boxes < rhs.m_boxes;
675 }
676 
677 // member functions
678 // ================
679 
680 inline Box
681 BoxLayout::get(const LayoutIndex& a_layoutIndex) const
682 {
683  CH_assert(check(a_layoutIndex)); // make sure this LayoutIndex came from my own iterator
684  return m_boxes->operator[](a_layoutIndex.m_index).box;
685 }
686 
687 
688 
689 inline unsigned int
690 BoxLayout::index(const LayoutIndex& a_layoutIndex) const
691 {
692  return a_layoutIndex.m_index;
693 }
694 
695 inline bool
697 {
698  return *m_closed;
699 }
700 
701 inline unsigned int
702 BoxLayout::procID(const LayoutIndex& a_layoutIndex) const
703 {
704  CH_assert(check(a_layoutIndex));
705  return m_boxes->operator[](a_layoutIndex.m_index).m_procID;
706 }
707 
708 
709 inline void
710 BoxLayout::setProcID(const LayoutIndex& a_layoutIndex, unsigned int a_procID)
711 {
712  CH_assert(check(a_layoutIndex));
713  m_boxes->operator[](a_layoutIndex.m_index).m_procID = a_procID;
714 }
715 
716 // global functions
717 // ================
718 
719 std::ostream& operator<<(std::ostream& os, const BoxLayout& a_layout);
720 
721 
722 #include "NamespaceFooter.H"
723 #endif
Base class to transform boxes in an existing layout.
Definition: BoxLayout.H:48
virtual void define(const Vector< Box > &a_boxes, const Vector< int > &a_procIDs)
void adjCellSide(int a_dir, int a_len, Side::LoHiSide a_sd)
TimedDataIterator timedDataIterator() const
A reference-counting handle class.
Definition: RefCountedPtr.H:66
Box operator[](const LayoutIndex &it) const
Definition: BoxLayout.H:657
bool isSorted() const
Definition: BoxLayout.H:329
#define CH_assert(cond)
Definition: CHArray.H:37
Box refine(const Box &b, const IntVect &refinement_ratio)
A class to facilitate interaction with physical boundary conditions.
Definition: ProblemDomain.H:130
RefCountedPtr< bool > m_closed
Definition: BoxLayout.H:621
bool operator==(const BoxLayout &rhs) const
Definition: BoxLayout.H:666
A not-necessarily-disjoint collective of boxes.
Definition: BoxLayout.H:146
Vector< int > procIDs() const
LayoutIterator layoutIterator() const
Iterator that processes through ALL the boxes in a BoxLayout.
Entry()
Definition: BoxLayout.H:63
void refine_bl(BoxLayout &output, const BoxLayout &input, int refinement)
Definition: BoxLayout.H:647
std::ostream & operator<<(std::ostream &os, const BoxLayout &a_layout)
Box box
Definition: BoxLayout.H:85
void convertNewToOld(const IntVect &a_permutation, const IntVect &a_sign, const IntVect &a_translation)
int refCount() const
Definition: RefCountedPtr.H:276
bool check(const LayoutIndex &index) const
Definition: BoxLayout.H:336
Definition: DataIterator.H:140
unsigned int size() const
Returns the total number of boxes in the BoxLayout.
void refine(int a_ref)
RefCountedPtr< Vector< LayoutIndex > > m_indicies
Definition: BoxLayout.H:624
An Iterator based on a BoxLayout object.
Definition: LayoutIterator.H:38
friend void coarsen(BoxLayout &output, const BoxLayout &input, int refinement)
RefCountedPtr< int > m_layout
Definition: BoxLayout.H:620
void operator&=(const Box &a_box)
Definition: EBInterface.H:45
void convertOldToNew(const IntVect &a_permutation, const IntVect &a_sign, const IntVect &a_translation)
void coarsen_bl(BoxLayout &output, const BoxLayout &input, int refinement)
Definition: BoxLayout.H:641
IndexTM< T, N > coarsen(const IndexTM< T, N > &a_p, T a_s)
Definition: IndexTMI.H:432
const int * m_layoutIntPtr
Definition: DataIndex.H:100
unsigned int indexI(const LayoutIndex &) const
virtual ~BaseTransform()
apparently I have to declare this to make some compilers happy.
Definition: BoxLayout.H:55
RefCountedPtr< bool > m_sorted
Definition: BoxLayout.H:622
virtual void close()
void sort()
void setProcID(const LayoutIndex &a_index, unsigned int a_procID)
Definition: BoxLayout.H:710
unsigned int index(const LayoutIndex &index) const
Definition: BoxLayout.H:690
Entry(const Box &a_box)
Definition: BoxLayout.H:68
void transform(BaseTransform &a_transform)
LoHiSide
Definition: LoHiSide.H:27
bool operator<(const BoxLayout &rhs) const
Definition: BoxLayout.H:672
bool operator<(const Entry &rhs) const
Definition: BoxLayout.H:80
void grow(int a_growth)
long long numCells() const
Return number of cells in all boxes of entire box layout.
bool isClosed() const
Definition: BoxLayout.H:696
Entry(const Box &a_box, const unsigned int a_index)
Definition: BoxLayout.H:74
RefCountedPtr< Vector< Entry > > m_boxes
Definition: BoxLayout.H:619
BoxLayout & operator=(const BoxLayout &a_rhs)
void buildDataIndex()
DataIterator dataIterator() const
Parallel iterator.
RefCountedPtr< DataIterator > m_dataIterator
Definition: BoxLayout.H:623
virtual void closeNoSort()
A Rectangular Domain on an Integer Lattice.
Definition: Box.H:465
virtual Box operator()(const Box &a_inputBox)=0
bool eq(const BoxLayout &rhs) const
Definition: BoxLayout.H:314
void checkDefine(const Vector< Box > &a_boxes, const Vector< int > &procIDs)
Definition: DataIndex.H:112
bool compatible(const BoxLayout &a_rhs) const
Definition: BoxLayout.H:345
void print() const
bool sameBoxes(const BoxLayout &a_layout) const
Checks whether this layout has the same boxes in the same order as a_layout.
unsigned int lindex(const DataIndex &index) const
An integer Vector in SpaceDim-dimensional space.
Definition: CHArray.H:42
unsigned int procID(const LayoutIndex &a_index) const
Definition: BoxLayout.H:702
bool coarsenable(int refRatio) const
virtual ~BoxLayout()
Vector< Box > boxArray() const
An index for LayoutIterator.
Definition: DataIndex.H:30
int refCount() const
Definition: BoxLayout.H:306
void mortonOrdering(Vector< Box > &a_boxes)
int m_index
Definition: DataIndex.H:98
virtual void deepCopy(const BoxLayout &a_source)
void surroundingNodes()
Box get(const LayoutIndex &it) const
Definition: BoxLayout.H:681
int procID()
local process ID
unsigned int m_procID
Definition: BoxLayout.H:86
void growSide(int idir, int length, Side::LoHiSide a_sd)
void enclosedCells()
int numBoxes(const int procID) const
Returns the number of boxes assigned to a given procID.
void p() const
Definition: BoxLayout.H:596
Definition: BoxLayout.H:61
Definition: TimedDataIterator.H:23