Chombo + EB  3.0
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 class 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  ///
146  /**
147  The destructor deletes the array memory. Unless this was an aliased
148  BaseFab.
149  */
150  virtual ~BaseFab();
151 
152  /**
153  This function resizes a `BaseFab' so it covers the `Box' a_b with a_n
154  components. If a_alias is not NULL the memory it points to is used
155  (without checking size); otherwise the existing data is lost and the
156  new data is uninitialized.
157  */
158  void resize(const Box& a_b,
159  int a_n = 1,
160  T* a_alias=NULL);
161 
162  /**
163  Make BaseFab with desired domain and number of components. Existing
164  data is lost. Data is in uninialized state.
165  */
166  virtual void define(const Box& a_box,
167  int a_comps,
168  T* a_alias = NULL)
169  {
170  resize(a_box, a_comps, a_alias);
171  }
172 
173  /**
174  alias define. no memory allocated. this BaseFab sets its data ptr
175  directly in the a_original BaseFab data.
176  */
177  virtual void define(const Interval& a_comps,
178  BaseFab<T>& a_original);
179 
180  /**
181  The function returns the `BaseFab' to the invalid state. (See
182  comments for constructors above.) The memory is freed.
183  */
184  void clear();
185 
186  /// {\bf accessors}
187 
188  ///
189  /**
190  Returns the number of components.
191  */
192  int nComp() const;
193 
194  ///
195  /**
196  Returns the domain (box) where the array is defined.
197  */
198  const Box& box() const;
199 
200  /**
201  Returns an IntVect giving the length
202  of the domain in each direction.
203  */
204  IntVect size() const;
205 
206  /**
207  Returns the lower corner of the domain. See class `Box' for analogue.
208  */
209  const IntVect& smallEnd() const;
210 
211  /**
212  Returns the upper corner of the domain. See class `Box' for analogue.
213  */
214  const IntVect& bigEnd() const;
215 
216  ///
217  /**
218  Returns an Interval for the entire range on components.
219  */
221  {
222  return Interval(0, m_nvar-1);
223  }
224 
225  /**
226  Returns a modifiable lvalue reference to the Nth component value defined
227  at position p in the domain. This operator may be inefficient if the
228  C++ compiler is unable to optimize the C++ code.
229  */
230  T& operator () (const IntVect& a_p,
231  int a_N);
232 
233  T& operator () (const IntVect& a_p);
234 
235  /**
236  Returns a conatant reference to the Nth component value defined at
237  position p in the domain. This operator may be inefficient if the C++
238  compiler is unable to optimize the C++ code.
239  */
240  const T& operator () (const IntVect& p,
241  int N) const;
242 
243  const T& operator () (const IntVect& p) const;
244 
245  /**
246  This function puts numcomp component values, starting at component N,
247  from position pos in the domain into array data, that must be allocated
248  by the user.
249  */
250  void getVal(T* a_data,
251  const IntVect& a_pos,
252  int a_N,
253  int a_numcomp) const;
254 
255  /**
256  This function puts all component values, starting at component 0,
257  from position pos in the domain into array data, that must be allocated
258  by the user.
259  */
260  void getVal(T* a_data,
261  const IntVect& a_pos) const;
262 
263  ///{\bf Fortran interface functions}
264 
265  /**
266  Returns the lower corner of the domain. Instead of returning them in
267  the form of IntVects, as in smallEnd and bigEnd, it returns the values
268  as a pointer to an array of constant integers. This is useful when
269  interfacing to Fortran subroutines. It should not be used in any other
270  context!!!
271  */
272  const int* loVect() const;
273 
274  /**
275  Returns the upper corner of the domain. Instead of returning them in
276  the form of IntVects, as in smallEnd and bigEnd, it returns the values
277  as a pointer to an array of constant integers. This is useful when
278  interfacing to Fortran subroutines. It should not be used in any other
279  context!!!
280  */
281  const int* hiVect() const;
282 
283  /**
284  Returns a pointer to an integer that contains the number of components
285  in the BaseFab. This is useful when interfacing to Fortran subroutines.
286  It should not be used in any other context!!!
287  */
288  const int* nCompPtr() const;
289 
290  /**
291  Returns a pointer to an object of type T that is the value of the a_nth
292  component associated with the cell at the low end of the domain. This
293  is commonly used to get a pointer to data in the array which is then
294  handed off to a Fortran subroutine. It should not be used in any other
295  context!!! Remember that data is stored in Fortran array order, with
296  the component index coming last. In other words, `dataPtr' returns a
297  pointer to all the a_nth components.
298  */
299  T* dataPtr(int a_n = 0);
300 
301  /**
302  Returns a constant pointer to an object of type T that is the value of
303  the a_nth component associated with the cell at the low end of the domain.
304  This is commonly used to get a pointer to data in the array which is
305  then handed off to a Fortran subroutine. It should not be used in any
306  other context!!! Remember that data is stored in Fortran array order,
307  with the component index coming last. In other words, `dataPtr' returns
308  a pointer to all the a_nth components.
309  */
310  const T* dataPtr(int a_n = 0) const;
311 
312  ///{\bf comparison functions}
313 
314  /**
315  Returns true if the domain of a_fab is totally contained within the domain
316  of this `BaseFab'.
317  */
318  bool contains(const BaseFab<T>& a_fab) const;
319 
320  /**
321  Returns true if a_bx is totally contained within the domain of this
322  `BaseFab'.
323  */
324  bool contains(const Box& a_bx) const;
325 
326  ///{\bf data modification functions}
327 
328  /**
329  The setVal functions set subregions in the `BaseFab' to a constant value.
330  This most general form specifies the subbox, the starting component
331  number, and the number of components to be set.
332  */
333  void setVal(T a_x,
334  const Box& a_bx,
335  int a_nstart,
336  int a_numcomp);
337 
338  ///
339  /**
340  Modifies this BaseFab so that all values of a component, a_n, in the
341  specified Box, a_bx, are set to the given value, a_x.
342  */
343  void setVal(T a_x,
344  const Box& a_bx,
345  int a_n);
346 
347  ///
348  /**
349  Modifies this BaseFab so that all values of a component, a_n, are set to
350  the given value, a_x.
351  */
352  void setVal(T a_x,
353  int a_n);
354 
355  ///
356  /**
357  Modifies this BaseFab so that all values of all components are set to
358  the given value, a_x.
359  */
360  void setVal(T a_x);
361 
362  /**
363  Modifies this BaseFab by copying the contents of the argument BaseFab
364  into it. This, the most general form of copy, specifies the contents
365  of any sub-box a_srcbox in `BaseFab' a_src may be copied into a (possibly
366  different) a_destbox in the destination `BaseFab'. Note that although
367  the a_srcbox and the a_destbox may be disjoint, they must be the same size
368  and shape. If the sizes differ, the copy is undefined and a runtime
369  error results. This copy function is the only one of the copy
370  functions to allow a copy between differing boxes. The user also
371  specifies how many components are copied, starting at component
372  a_srccomp in a_src and stored starting at component a_destcomp. The
373  results are UNDEFINED if the a_src and dest BaseFabs are the same and
374  the a_srcbox and a_destbox overlap.
375 
376  */
377  BaseFab<T>& copy(const BaseFab<T>& a_src,
378  const Box& a_srcbox,
379  int a_srccomp,
380  const Box& a_destbox,
381  int a_destcomp,
382  int a_numcomp);
383 
384  /**
385  Modifies this BaseFab by copying the contents of the argument BaseFab
386  into it. A copy within the intersecting region of the domains of the
387  two BaseFabs is performed. The user specifies how many components are
388  copied, starting at component a_srccomp in a_src and stored starting at
389  component a_destcomp.
390  */
391  BaseFab<T>& copy(const BaseFab<T>& a_src,
392  int a_srccomp,
393  int a_destcomp,
394  int a_numcomp = 1);
395 
396  /**
397  Modifies this BaseFab by copying the contents of the argument BaseFab
398  into it. A copy within the intersecting region of the domains of the
399  two BaseFabs and the specified Box a_destbox is performed. All
400  components are copied.
401  */
402  BaseFab<T>& copy(const BaseFab<T>& a_src,
403  const Box& a_destbox);
404 
405  /**
406  Modifies this BaseFab by copying the contents of the argument BaseFab
407  into it. A copy within the intersecting region of the domains of the
408  two BaseFabs is performed. All components are copied.
409  */
410  BaseFab<T>& copy(const BaseFab<T>& a_src);
411 
412  ///
413  /**
414  Copy from a subsection of one box into another. Assumes the boxes are
415  both in the same index space, and that box R is completely contained
416  in both the source and destination boxes.
417  */
418  void copy(const Box& a_RegionFrom,
419  const Interval& a_Cdest,
420  const Box& a_RegionTo,
421  const BaseFab<T>& a_src,
422  const Interval& a_Csrc);
423 
424  /// {\bf domain modification functions}
425 
426  ///
427  /**
428  Modifies the domain of this BaseFab by shifting. Equivalent to
429  fab.shift(0,a_v[0]).shift(1,a_v[1])... There is no effect upon
430  the array memory.
431  */
432  BaseFab<T>& shift(const IntVect& a_v);
433 
434  ///
435  /**
436  Modifies the domain of this BaseFab by shifting it a_ncells
437  indexing positions in coordinate direction a_idir. Directions are
438  zero-based. It is an error if not 0 <= a_idir < SpaceDim. There is
439  no effect upon the array memory.
440  */
441  BaseFab<T>& shift(int a_idir,
442  int a_ncells);
443 
444  ///
445  /**
446  Modifies the domain of this BaseFab by shifting by "half" indices,
447  thereby converting the Box from type CELL to NODE or vice-versa.
448  fab.shiftHalf(0,1) shifts the domain to the right by 1/2 cells.
449  fab.shiftHalf(1,-3) shifts the domain in the -j direction by 3/2 cells.
450  NOTE: If a_numHalfs is EVEN the shift is a_numHalfs/2 full zones
451  and hence will not change the type. This is: fab.shiftHalf(1,4) ==
452  fab.shift(1,2). Directions are zero-based. It is an error if not 0
453  <= a_dir < SpaceDim. There is no effect upon the array memory.
454  */
455  BaseFab<T>& shiftHalf(int a_dir,
456  int a_numHalfs);
457 
458  ///
459  /**
460  Modifies the domain of this BaseFab by shifting by half indices.
461  Equivalent to fab.shiftHalf(0,a_v[0]).shiftHalf(1,a_v[1]) ...
462  There is no effect upon the array memory.
463  */
464  BaseFab<T>& shiftHalf(const IntVect& a_v);
465 
466  ///{\bf linearization functions}
467 
468  ///
469  /**
470  Returns the size, in number of bytes, of a flat linear
471  representation of the data in this object in the area defined
472  by the input Box a_box and the component Interval a_comps. The size
473  does not include the size of a_box and a_comps.
474  */
475  virtual int size(const Box& a_box,
476  const Interval& a_comps) const;
477 
478  ///
479  /**
480  Write a linear representation of the internal data. Assumes that
481  sufficient memory for the buffer has already been allocated by the
482  caller.
483  */
484  virtual void linearOut(void* a_buf,
485  const Box& a_R,
486  const Interval& a_comps) const;
487 
488  /// Same as linearOut, but returns the current location in the buffer
489  virtual void* linearOut2(void* a_buf,
490  const Box& a_R,
491  const Interval& a_comps) const;
492 
493  ///
494  virtual void linearIn(void* a_buf,
495  const Box& a_R,
496  const Interval& a_comps);
497 
498  /// same as linearIn, but returns the current location in the buffer
499  virtual void* linearIn2(void* a_buf,
500  const Box& a_R,
501  const Interval& a_comps);
502 
503  ///
504  static int preAllocatable()
505  {
506  return 0; // static preAllocatable
507  }
508 
509  /**
510  Turns a_slice into a BaseFab that's the same as *this except that it's just
511  one cell thick in the a_sliceSpec.direction-th direction, and its
512  coordinate in that direction is a_sliceSpec.position.
513 
514  If a_sliceSpec.position is outside the range of *this, that's a fatal error.
515  */
516  void degenerate(BaseFab<T>& a_slice, const SliceSpec& a_sliceSpec) const;
517 
518 
519  ///
520  bool isAliased() const;
521 
522  ///regression test
523  static int test();
524 
525  ///regression test
526  static int testBoxAndComp();
527 protected:
528  //
529  // Allocates memory for the `BaseFab<T>'.
530  //
531  void define();
532 
533  //
534  // Deallocates memory for the `BaseFab<T>'.
535  //
536  void undefine();
537 
538  static std::string name();
539 
540  //
541  // The function called by BaseFab copy operations.
542  //
543  virtual void performCopy(const BaseFab<T>& a_src,
544  const Box& a_srcbox,
545  int a_srccomp,
546  const Box& a_destbox,
547  int a_destcomp,
548  int a_numcomp);
549 
550  //
551  // This function is called by the `BaseFab' setVal operations.
552  //
553  void performSetVal(T a_x,
554  const Box& a_bx,
555  int a_nstart,
556  int a_numcomp);
557 
558  //
559  // template class static data member. not sure if this will
560  // work with all compilers. It has been in the draft standard
561  // for some time
562  //
563  static Arena* s_Arena;
564 
565  Box m_domain; // My index space.
566  int m_nvar; // Number components.
567  long m_numpts; // Cached number of points in FAB.
568  long m_truesize; // m_nvar * m_numpts that was allocated on heap
569  // (only if m_aliased == false).
570  T* m_dptr; // The data pointer.
571  bool m_aliased; // The BaseFab is not allocated memory, but is an alias. bvs
572 
573 private:
574  //
575  // These functions are made private to prevent use of the default
576  // functions provided by the C++ compiler.
577  //
579  BaseFab (const BaseFab<T>&);
580 };
581 
582 #include "NamespaceFooter.H"
583 
584 #include "BaseFabImplem.H"
585 
586 #endif
void clear()
Definition: BaseFabImplem.H:186
BaseFab< T > & operator=(const BaseFab< T > &)
void degenerate(BaseFab< T > &a_slice, const SliceSpec &a_sliceSpec) const
Definition: BaseFabImplem.H:666
bool contains(const BaseFab< T > &a_fab) const
{ comparison functions}
Definition: BaseFabImplem.H:316
IntVect size() const
size functions
Definition: Box.H:1814
static Arena * s_Arena
Definition: BaseFab.H:563
#define CH_assert(cond)
Definition: CHArray.H:37
virtual void linearOut(void *a_buf, const Box &a_R, const Interval &a_comps) const
Definition: BaseFabImplem.H:479
void setVal(T a_x, const Box &a_bx, int a_nstart, int a_numcomp)
{ data modification functions}
Definition: BaseFabImplem.H:326
virtual ~BaseFab()
Definition: BaseFabImplem.H:130
BaseFab< T > & shift(const IntVect &a_v)
{ domain modification functions}
Definition: BaseFabImplem.H:443
virtual void linearIn(void *a_buf, const Box &a_R, const Interval &a_comps)
Definition: BaseFabImplem.H:500
Definition: SliceSpec.H:42
bool contains(const IntVect &p) const
Definition: Box.H:1888
static std::string name()
Definition: BaseFabImplem.H:606
Box m_domain
Definition: BaseFab.H:565
const IntVect & bigEnd() const
Definition: BaseFabImplem.H:217
int m_nvar
Definition: BaseFab.H:566
const Box & box() const
Definition: BaseFabImplem.H:202
const int * nCompPtr() const
Definition: BaseFabImplem.H:293
BaseFab()
Definition: BaseFabImplem.H:85
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:486
bool isAliased() const
Definition: BaseFabImplem.H:660
void getVal(T *a_data, const IntVect &a_pos, int a_N, int a_numcomp) const
Definition: BaseFabImplem.H:260
static int preAllocatable()
Definition: BaseFab.H:504
BaseFab< T > & shiftHalf(int a_dir, int a_numHalfs)
Definition: BaseFabImplem.H:458
Structure for passing component ranges in code.
Definition: Interval.H:23
T * m_dptr
Definition: BaseFab.H:570
const IntVect & smallEnd() const
{ Accessors}
Definition: Box.H:1765
virtual void define(const Box &a_box, int a_comps, T *a_alias=NULL)
Definition: BaseFab.H:166
A Virtual Base Class for Dynamic Memory Managemen.
Definition: Arena.H:40
double Real
Definition: REAL.H:33
void define()
Definition: BaseFabImplem.H:524
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:614
const int * hiVect() const
Definition: BaseFabImplem.H:288
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:353
Interval interval() const
Definition: BaseFab.H:220
virtual long offset(const IntVect &a_iv, const int &a_ivar) const
{ constructors, destructor and defines}
Definition: BaseFab.H:82
const IntVect & smallEnd() const
Definition: BaseFabImplem.H:212
Definition: BaseFab.H:76
T * dataPtr(int a_n=0)
Definition: BaseFabImplem.H:300
Real BaseFabRealSetVal
A Rectangular Domain on an Integer Lattice.
Definition: Box.H:465
bool m_aliased
Definition: BaseFab.H:571
long m_truesize
Definition: BaseFab.H:568
An integer Vector in SpaceDim-dimensional space.
Definition: CHArray.H:42
T & operator()(const IntVect &a_p, int a_N)
Definition: BaseFabImplem.H:222
const int * loVect() const
{ Fortran interface functions}
Definition: BaseFabImplem.H:283
int nComp() const
{ accessors}
Definition: BaseFabImplem.H:195
void resize(const Box &a_b, int a_n=1, T *a_alias=NULL)
Definition: BaseFabImplem.H:135
void undefine()
Definition: BaseFabImplem.H:572
static int testBoxAndComp()
regression test
Definition: BaseFabImplem.H:37
void performSetVal(T a_x, const Box &a_bx, int a_nstart, int a_numcomp)
Definition: BaseFabImplem.H:633
static int test()
regression test
Definition: BaseFabImplem.H:75
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:509
IntVect size() const
Definition: BaseFabImplem.H:207
long m_numpts
Definition: BaseFab.H:567