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