Chombo + EB  3.2
BaseFab.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 _BASEFAB_H_
12 #define _BASEFAB_H_
13 
14 #include <cstdlib>
15 #include "SPACE.H"
16 #include <string>
17 #include <typeinfo>
18 #include <cmath>
19 
20 #include "Box.H"
21 #include "Arena.H"
22 #include "Interval.H"
23 #include "REAL.H"
24 #include "NamespaceHeader.H"
25 
26 struct SliceSpec;
27 
28 /** A Fortran Array-like Container
29 
30  BaseFab emulates the Fortran array concept.
31  Useful operations can be performed upon
32  BaseFab's in C++, and they provide a convenient interface to
33  Fortran when it is necessary to retreat into that language.
34 
35  `BaseFab' is a template class. Through use of the
36  template, a `BaseFab' may be based upon any class. So far at least,
37  most applications have been based upon simple types like `integer's,
38  `real's, or `doubleprecision's. Most applications do not use BaseFab's
39  directly, but utilize specialized classes derived from BaseFab.
40 
41  It will be easier to use a `BaseFab' if you understand the following
42  concepts. `BaseFab' objects depend on the dimensionality of space
43  (indirectly through the DOMAIN `Box' member). It is
44  typical to define the macro `CH_SPACEDIM' to be 1, 2, or 3 to indicate
45  the dimension of space. See the discussion of class `Box' for more
46  information. A `BaseFab' contains a `Box' DOMAIN, which indicates the
47  integer indexing space over which the array is defined. A `BaseFab'
48  also has NVAR components. By components, we mean that for each
49  point in the rectangular indexing space, there are NVAR values
50  associated with that point. A Fortran array corresponding to a
51  `BaseFab' would have (CH_SPACEDIM+1) dimensions.
52 
53  By design, the array layout in a `BaseFab' mirrors that of a
54  Fortran array. The first index (x direction for example) varies
55  most rapidly, the next index (y direction), if any, varies next
56  fastest. The component index varies last, after all the spatial
57  indices.
58 
59  It is sometimes convenient to be able to treat a sub-array within an
60  existing `BaseFab' as a `BaseFab' in its own right. This is often
61  referred to as 'aliasing' the `BaseFab'. Note that when aliasing is
62  used, the BaseFab's domain will not, in general, be the same as the
63  parent BaseFab's domain, nor will the number of components.
64  BaseFab is a dimension dependent class, so CH_SPACEDIM must be
65  defined as either 1, 2, or 3 when compiling.
66 
67  This is NOT a polymorphic class.
68 
69  It does NOT provide a copy constructor or assignment operator.
70 
71  T MUST have a default constructor and an assignment operator.
72 */
73 
74 extern Real BaseFabRealSetVal;
75 
76 template <class T> class BaseFab
77 {
78 public:
79  /// {\bf constructors, destructor and defines}
80 
81  ///for AggStencil and its minions
82  virtual long offset(const IntVect& a_iv, const int& a_ivar) const
83  {
84  CH_assert(a_ivar >= 0);
85  CH_assert(a_ivar < m_nvar);
86  CH_assert(!(m_dptr == 0));
88 
89  IntVect ivDiff = a_iv - m_domain.smallEnd();
90  IntVect ivSize = m_domain.size();
91  long offset = ivDiff[0];
92 
93 #if CH_SPACEDIM > 1
94  offset += ivDiff[1]*ivSize[0] ;
95 #endif
96 #if CH_SPACEDIM > 2
97  offset += ivDiff[2]*ivSize[0]*ivSize[1];
98 #endif
99 #if CH_SPACEDIM > 3
100  offset += ivDiff[3]*ivSize[0]*ivSize[1]*ivSize[2];
101 #endif
102 #if CH_SPACEDIM > 4
103  offset += ivDiff[4]*ivSize[0]*ivSize[1]*ivSize[2]*ivSize[3];
104 #endif
105 #if CH_SPACEDIM > 5
106  offset += ivDiff[5]*ivSize[0]*ivSize[1]*ivSize[2]*ivSize[3]*ivSize[4];
107 #endif
108  offset += m_numpts * a_ivar;
109 
110  return offset;
111  }
112 
113  /**
114  Constructs an invalid `BaseFab'. The domain is invalid, the
115  number of components is zero, and no actual array memory is
116  allocated. An invalid `BaseFab' must be resize()d
117  (see `BaseFab::resize') before use.
118  */
119  BaseFab ();
120 
121  ///
122  /**
123  Constructs a BaseFab with desired domain and number of components.
124  */
125  BaseFab(const Box& a_bx,
126  int a_n,
127  T* a_alias = NULL);
128 
129  /**
130  Constructs an 'aliased' BaseFab of the requested interval of the
131  argument BaseFab. This BaseFab does not allocate any memory, but
132  sets its data pointer into the memory pointed to by the argument
133  BaseFab. It is the users responsiblity to ensure this aliased
134  BaseFab is not used after the original BaseFab has deleted its data ptr
135  (resize, define(..) called, or destruction, etc.).
136 
137  This aliased BaseFab will also generate side effects (modifying the values
138  of data in one will modify the other's data).
139 
140  This aliased BaseFab will have a_comps.size() components, starting at zero.
141  */
142  BaseFab(const Interval& a_comps,
143  BaseFab<T>& a_original);
144 
145  /// move constructor
146  BaseFab(BaseFab<T>&& a_in) noexcept;
147  ///
148  /**
149  The destructor deletes the array memory. Unless this was an aliased
150  BaseFab.
151  */
152  virtual ~BaseFab();
153 
154  /**
155  This function resizes a `BaseFab' so it covers the `Box' a_b with a_n
156  components. If a_alias is not NULL the memory it points to is used
157  (without checking size); otherwise the existing data is lost and the
158  new data is uninitialized.
159  */
160  void resize(const Box& a_b,
161  int a_n = 1,
162  T* a_alias=NULL);
163 
164  /**
165  Make BaseFab with desired domain and number of components. Existing
166  data is lost. Data is in uninialized state.
167  */
168  virtual void define(const Box& a_box,
169  int a_comps,
170  T* a_alias = NULL)
171  {
172  resize(a_box, a_comps, a_alias);
173  }
174 
175  /**
176  alias define. no memory allocated. this BaseFab sets its data ptr
177  directly in the a_original BaseFab data.
178  */
179  virtual void define(const Interval& a_comps,
180  BaseFab<T>& a_original);
181 
182  /**
183  The function returns the `BaseFab' to the invalid state. (See
184  comments for constructors above.) The memory is freed.
185  */
186  void clear();
187 
188  /// {\bf accessors}
189 
190  ///
191  /**
192  Returns the number of components.
193  */
194  int nComp() const;
195 
196  ///
197  /**
198  Returns the domain (box) where the array is defined.
199  */
200  const Box& box() const;
201 
202  /**
203  Returns an IntVect giving the length
204  of the domain in each direction.
205  */
206  IntVect size() const;
207 
208  /**
209  Returns the lower corner of the domain. See class `Box' for analogue.
210  */
211  const IntVect& smallEnd() const;
212 
213  /**
214  Returns the upper corner of the domain. See class `Box' for analogue.
215  */
216  const IntVect& bigEnd() const;
217 
218  ///
219  /**
220  Returns an Interval for the entire range on components.
221  */
223  {
224  return Interval(0, m_nvar-1);
225  }
226 
227  /// move assignment
228  inline BaseFab<T>& operator= (BaseFab<T>&&) noexcept;
229  /**
230  Returns a modifiable lvalue reference to the Nth component value defined
231  at position p in the domain. This operator may be inefficient if the
232  C++ compiler is unable to optimize the C++ code.
233  */
234  T& operator () (const IntVect& a_p,
235  int a_N);
236 
237  T& operator () (const IntVect& a_p);
238 
239  /**
240  Returns a conatant reference to the Nth component value defined at
241  position p in the domain. This operator may be inefficient if the C++
242  compiler is unable to optimize the C++ code.
243  */
244  const T& operator () (const IntVect& p,
245  int N) const;
246 
247  const T& operator () (const IntVect& p) const;
248 
249  /**
250  This function puts numcomp component values, starting at component N,
251  from position pos in the domain into array data, that must be allocated
252  by the user.
253  */
254  void getVal(T* a_data,
255  const IntVect& a_pos,
256  int a_N,
257  int a_numcomp) const;
258 
259  /**
260  This function puts all component values, starting at component 0,
261  from position pos in the domain into array data, that must be allocated
262  by the user.
263  */
264  void getVal(T* a_data,
265  const IntVect& a_pos) const;
266 
267  ///{\bf Fortran interface functions}
268 
269  /**
270  Returns the lower corner of the domain. Instead of returning them in
271  the form of IntVects, as in smallEnd and bigEnd, it returns the values
272  as a pointer to an array of constant integers. This is useful when
273  interfacing to Fortran subroutines. It should not be used in any other
274  context!!!
275  */
276  const int* loVect() const;
277 
278  /**
279  Returns the upper corner of the domain. Instead of returning them in
280  the form of IntVects, as in smallEnd and bigEnd, it returns the values
281  as a pointer to an array of constant integers. This is useful when
282  interfacing to Fortran subroutines. It should not be used in any other
283  context!!!
284  */
285  const int* hiVect() const;
286 
287  /**
288  Returns a pointer to an integer that contains the number of components
289  in the BaseFab. This is useful when interfacing to Fortran subroutines.
290  It should not be used in any other context!!!
291  */
292  const int* nCompPtr() const;
293 
294  /**
295  Returns a pointer to an object of type T that is the value of the a_nth
296  component associated with the cell at the low end of the domain. This
297  is commonly used to get a pointer to data in the array which is then
298  handed off to a Fortran subroutine. It should not be used in any other
299  context!!! Remember that data is stored in Fortran array order, with
300  the component index coming last. In other words, `dataPtr' returns a
301  pointer to all the a_nth components.
302  */
303  T* dataPtr(int a_n = 0);
304 
305  /**
306  Returns a constant pointer to an object of type T that is the value of
307  the a_nth component associated with the cell at the low end of the domain.
308  This is commonly used to get a pointer to data in the array which is
309  then handed off to a Fortran subroutine. It should not be used in any
310  other context!!! Remember that data is stored in Fortran array order,
311  with the component index coming last. In other words, `dataPtr' returns
312  a pointer to all the a_nth components.
313  */
314  const T* dataPtr(int a_n = 0) const;
315 
316  ///{\bf comparison functions}
317 
318  /**
319  Returns true if the domain of a_fab is totally contained within the domain
320  of this `BaseFab'.
321  */
322  bool contains(const BaseFab<T>& a_fab) const;
323 
324  /**
325  Returns true if a_bx is totally contained within the domain of this
326  `BaseFab'.
327  */
328  bool contains(const Box& a_bx) const;
329 
330  ///{\bf data modification functions}
331 
332  /**
333  The setVal functions set subregions in the `BaseFab' to a constant value.
334  This most general form specifies the subbox, the starting component
335  number, and the number of components to be set.
336  */
337  void setVal(T a_x,
338  const Box& a_bx,
339  int a_nstart,
340  int a_numcomp);
341 
342  ///
343  /**
344  Modifies this BaseFab so that all values of a component, a_n, in the
345  specified Box, a_bx, are set to the given value, a_x.
346  */
347  void setVal(T a_x,
348  const Box& a_bx,
349  int a_n);
350 
351  ///
352  /**
353  Modifies this BaseFab so that all values of a component, a_n, are set to
354  the given value, a_x.
355  */
356  void setVal(T a_x,
357  int a_n);
358 
359  ///
360  /**
361  Modifies this BaseFab so that all values of all components are set to
362  the given value, a_x.
363  */
364  void setVal(T a_x);
365 
366  /**
367  Modifies this BaseFab by copying the contents of the argument BaseFab
368  into it. This, the most general form of copy, specifies the contents
369  of any sub-box a_srcbox in `BaseFab' a_src may be copied into a (possibly
370  different) a_destbox in the destination `BaseFab'. Note that although
371  the a_srcbox and the a_destbox may be disjoint, they must be the same size
372  and shape. If the sizes differ, the copy is undefined and a runtime
373  error results. This copy function is the only one of the copy
374  functions to allow a copy between differing boxes. The user also
375  specifies how many components are copied, starting at component
376  a_srccomp in a_src and stored starting at component a_destcomp. The
377  results are UNDEFINED if the a_src and dest BaseFabs are the same and
378  the a_srcbox and a_destbox overlap.
379 
380  */
381  BaseFab<T>& copy(const BaseFab<T>& a_src,
382  const Box& a_srcbox,
383  int a_srccomp,
384  const Box& a_destbox,
385  int a_destcomp,
386  int a_numcomp);
387 
388  /**
389  Modifies this BaseFab by copying the contents of the argument BaseFab
390  into it. A copy within the intersecting region of the domains of the
391  two BaseFabs is performed. The user specifies how many components are
392  copied, starting at component a_srccomp in a_src and stored starting at
393  component a_destcomp.
394  */
395  BaseFab<T>& copy(const BaseFab<T>& a_src,
396  int a_srccomp,
397  int a_destcomp,
398  int a_numcomp = 1);
399 
400  /**
401  Modifies this BaseFab by copying the contents of the argument BaseFab
402  into it. A copy within the intersecting region of the domains of the
403  two BaseFabs and the specified Box a_destbox is performed. All
404  components are copied.
405  */
406  BaseFab<T>& copy(const BaseFab<T>& a_src,
407  const Box& a_destbox);
408 
409  /**
410  Modifies this BaseFab by copying the contents of the argument BaseFab
411  into it. A copy within the intersecting region of the domains of the
412  two BaseFabs is performed. All components are copied.
413  */
414  BaseFab<T>& copy(const BaseFab<T>& a_src);
415 
416  ///
417  /**
418  Copy from a subsection of one box into another. Assumes the boxes are
419  both in the same index space, and that box R is completely contained
420  in both the source and destination boxes.
421  */
422  void copy(const Box& a_RegionFrom,
423  const Interval& a_Cdest,
424  const Box& a_RegionTo,
425  const BaseFab<T>& a_src,
426  const Interval& a_Csrc);
427 
428  /// {\bf domain modification functions}
429 
430  ///
431  /**
432  Modifies the domain of this BaseFab by shifting. Equivalent to
433  fab.shift(0,a_v[0]).shift(1,a_v[1])... There is no effect upon
434  the array memory.
435  */
436  BaseFab<T>& shift(const IntVect& a_v);
437 
438  ///
439  /**
440  Modifies the domain of this BaseFab by shifting it a_ncells
441  indexing positions in coordinate direction a_idir. Directions are
442  zero-based. It is an error if not 0 <= a_idir < SpaceDim. There is
443  no effect upon the array memory.
444  */
445  BaseFab<T>& shift(int a_idir,
446  int a_ncells);
447 
448  ///
449  /**
450  Modifies the domain of this BaseFab by shifting by "half" indices,
451  thereby converting the Box from type CELL to NODE or vice-versa.
452  fab.shiftHalf(0,1) shifts the domain to the right by 1/2 cells.
453  fab.shiftHalf(1,-3) shifts the domain in the -j direction by 3/2 cells.
454  NOTE: If a_numHalfs is EVEN the shift is a_numHalfs/2 full zones
455  and hence will not change the type. This is: fab.shiftHalf(1,4) ==
456  fab.shift(1,2). Directions are zero-based. It is an error if not 0
457  <= a_dir < SpaceDim. There is no effect upon the array memory.
458  */
459  BaseFab<T>& shiftHalf(int a_dir,
460  int a_numHalfs);
461 
462  ///
463  /**
464  Modifies the domain of this BaseFab by shifting by half indices.
465  Equivalent to fab.shiftHalf(0,a_v[0]).shiftHalf(1,a_v[1]) ...
466  There is no effect upon the array memory.
467  */
468  BaseFab<T>& shiftHalf(const IntVect& a_v);
469 
470  ///{\bf linearization functions}
471 
472  ///
473  /**
474  Returns the size, in number of bytes, of a flat linear
475  representation of the data in this object in the area defined
476  by the input Box a_box and the component Interval a_comps. The size
477  does not include the size of a_box and a_comps.
478  */
479  virtual size_t size(const Box& a_box,
480  const Interval& a_comps) const;
481 
482  ///
483  /**
484  Write a linear representation of the internal data. Assumes that
485  sufficient memory for the buffer has already been allocated by the
486  caller.
487  */
488  virtual void linearOut(void* a_buf,
489  const Box& a_R,
490  const Interval& a_comps) const;
491 
492  /// Same as linearOut, but returns the current location in the buffer
493  virtual void* linearOut2(void* a_buf,
494  const Box& a_R,
495  const Interval& a_comps) const;
496 
497  ///
498  virtual void linearIn(void* a_buf,
499  const Box& a_R,
500  const Interval& a_comps);
501 
502  /// same as linearIn, but returns the current location in the buffer
503  virtual void* linearIn2(void* a_buf,
504  const Box& a_R,
505  const Interval& a_comps);
506 
507  /// These functions are required for broadcast & gather.
508 
509  void linearOut(void* a_buf) const;
510  ///
511  void linearIn(const void* const a_buf);
512  ///
513  int linearSize(void) const;
514 
515  ///
516  static int preAllocatable()
517  {
518  return 0; // static preAllocatable
519  }
520 
521  /**
522  Turns a_slice into a BaseFab that's the same as *this except that it's just
523  one cell thick in the a_sliceSpec.direction-th direction, and its
524  coordinate in that direction is a_sliceSpec.position.
525 
526  If a_sliceSpec.position is outside the range of *this, that's a fatal error.
527  */
528  void degenerate(BaseFab<T>& a_slice, const SliceSpec& a_sliceSpec) const;
529 
530  ///
531  bool isAliased() const;
532 
533  ///regression test
534  static int test();
535 
536  ///regression test
537  static int testBoxAndComp();
538 protected:
539  //
540  // Allocates memory for the `BaseFab<T>'.
541  //
542  void define();
543 
544  //
545  // Deallocates memory for the `BaseFab<T>'.
546  //
547  void undefine();
548 
549  static std::string name();
550 
551  //
552  // The function called by BaseFab copy operations.
553  //
554  virtual void performCopy(const BaseFab<T>& a_src,
555  const Box& a_srcbox,
556  int a_srccomp,
557  const Box& a_destbox,
558  int a_destcomp,
559  int a_numcomp);
560 
561  //
562  // This function is called by the `BaseFab' setVal operations.
563  //
564  void performSetVal(T a_x,
565  const Box& a_bx,
566  int a_nstart,
567  int a_numcomp);
568 
569  //
570  // template class static data member. not sure if this will
571  // work with all compilers. It has been in the draft standard
572  // for some time
573  //
574  static Arena* s_Arena;
575 
576  Box m_domain; // My index space.
577  int m_nvar; // Number components.
578  long m_numpts; // Cached number of points in FAB.
579  long m_truesize; // m_nvar * m_numpts that was allocated on heap
580  // (only if m_aliased == false).
581  T* __restrict m_dptr; // The data pointer.
582  bool m_aliased; // The BaseFab is not allocated memory, but is an alias. bvs
583 
584 private:
585  //
586  // These functions are made private to prevent use of the default
587  // functions provided by the C++ compiler.
588  //
590  BaseFab (const BaseFab<T>&);
591 };
592 
593 #include "NamespaceFooter.H"
594 
595 #include "BaseFabImplem.H"
596 
597 #endif
int linearSize(void) const
Definition: BaseFabImplem.H:606
void clear()
Definition: BaseFabImplem.H:210
virtual long offset(const IntVect &a_iv, const int &a_ivar) const
{ constructors, destructor and defines}
Definition: BaseFab.H:82
const int * loVect() const
{ Fortran interface functions}
Definition: BaseFabImplem.H:311
static Arena * s_Arena
Definition: BaseFab.H:574
#define CH_assert(cond)
Definition: CHArray.H:37
void setVal(T a_x, const Box &a_bx, int a_nstart, int a_numcomp)
{ data modification functions}
Definition: BaseFabImplem.H:354
bool contains(const BaseFab< T > &a_fab) const
{ comparison functions}
Definition: BaseFabImplem.H:344
BaseFab< T > & shift(const IntVect &a_v)
{ domain modification functions}
Definition: BaseFabImplem.H:471
virtual void linearIn(void *a_buf, const Box &a_R, const Interval &a_comps)
Definition: BaseFabImplem.H:527
Definition: SliceSpec.H:41
IntVect size() const
size functions
Definition: Box.H:1803
static std::string name()
Definition: BaseFabImplem.H:702
Box m_domain
Definition: BaseFab.H:576
int m_nvar
Definition: BaseFab.H:577
virtual void linearOut(void *a_buf, const Box &a_R, const Interval &a_comps) const
Definition: BaseFabImplem.H:507
BaseFab< T > & operator=(BaseFab< T > &&) noexcept
move assignment
Definition: BaseFabImplem.H:97
BaseFab()
Definition: BaseFabImplem.H:108
const IntVect & smallEnd() const
Definition: BaseFabImplem.H:236
int nComp() const
{ accessors}
Definition: BaseFabImplem.H:219
static int preAllocatable()
Definition: BaseFab.H:516
BaseFab< T > & shiftHalf(int a_dir, int a_numHalfs)
Definition: BaseFabImplem.H:486
bool isAliased() const
Definition: BaseFabImplem.H:756
Structure for passing component ranges in code.
Definition: Interval.H:23
Interval interval() const
Definition: BaseFab.H:222
A Virtual Base Class for Dynamic Memory Managemen.
Definition: Arena.H:40
double Real
Definition: REAL.H:33
void define()
Definition: BaseFabImplem.H:611
virtual void performCopy(const BaseFab< T > &a_src, const Box &a_srcbox, int a_srccomp, const Box &a_destbox, int a_destcomp, int a_numcomp)
Definition: BaseFabImplem.H:710
BaseFab< T > & copy(const BaseFab< T > &a_src, const Box &a_srcbox, int a_srccomp, const Box &a_destbox, int a_destcomp, int a_numcomp)
Definition: BaseFabImplem.H:381
const int * hiVect() const
Definition: BaseFabImplem.H:316
Definition: BaseFab.H:76
T * dataPtr(int a_n=0)
Definition: BaseFabImplem.H:328
virtual void * linearOut2(void *a_buf, const Box &a_R, const Interval &a_comps) const
Same as linearOut, but returns the current location in the buffer.
Definition: BaseFabImplem.H:513
T *__restrict m_dptr
Definition: BaseFab.H:581
Real BaseFabRealSetVal
A Rectangular Domain on an Integer Lattice.
Definition: Box.H:465
bool m_aliased
Definition: BaseFab.H:582
long m_truesize
Definition: BaseFab.H:579
bool contains(const IntVect &p) const
Definition: Box.H:1871
const int * nCompPtr() const
Definition: BaseFabImplem.H:321
An integer Vector in SpaceDim-dimensional space.
Definition: CHArray.H:42
void getVal(T *a_data, const IntVect &a_pos, int a_N, int a_numcomp) const
Definition: BaseFabImplem.H:288
void const char const int const int * N
Definition: Lapack.H:83
void resize(const Box &a_b, int a_n=1, T *a_alias=NULL)
Definition: BaseFabImplem.H:158
void undefine()
Definition: BaseFabImplem.H:667
static int testBoxAndComp()
regression test
Definition: BaseFabImplem.H:39
void performSetVal(T a_x, const Box &a_bx, int a_nstart, int a_numcomp)
Definition: BaseFabImplem.H:729
static int test()
regression test
Definition: BaseFabImplem.H:77
virtual void * linearIn2(void *a_buf, const Box &a_R, const Interval &a_comps)
same as linearIn, but returns the current location in the buffer
Definition: BaseFabImplem.H:535
const IntVect & smallEnd() const
{ Accessors}
Definition: Box.H:1754
IntVect size() const
Definition: BaseFabImplem.H:231
void degenerate(BaseFab< T > &a_slice, const SliceSpec &a_sliceSpec) const
Definition: BaseFabImplem.H:762
long m_numpts
Definition: BaseFab.H:578
const IntVect & bigEnd() const
Definition: BaseFabImplem.H:241
const Box & box() const
Definition: BaseFabImplem.H:226