00001 #ifdef CH_LANG_CC 00002 /* 00003 * _______ __ 00004 * / ___/ / ___ __ _ / / ___ 00005 * / /__/ _ \/ _ \/ V \/ _ \/ _ \ 00006 * \___/_//_/\___/_/_/_/_.__/\___/ 00007 * Please refer to Copyright.txt, in Chombo's root directory. 00008 */ 00009 #endif 00010 00011 #ifndef _BASEFAB_H_ 00012 #define _BASEFAB_H_ 00013 00014 #include <cstdlib> 00015 #include "SPACE.H" 00016 #include <string> 00017 #include <typeinfo> 00018 #include <cmath> 00019 00020 #include "Box.H" 00021 #include "Arena.H" 00022 #include "Interval.H" 00023 #include "REAL.H" 00024 #include "NamespaceHeader.H" 00025 00026 struct SliceSpec; 00027 00028 /** A Fortran Array-like Container 00029 00030 BaseFab emulates the Fortran array concept. 00031 Useful operations can be performed upon 00032 BaseFab's in C++, and they provide a convenient interface to 00033 Fortran when it is necessary to retreat into that language. 00034 00035 `BaseFab' is a template class. Through use of the 00036 template, a `BaseFab' may be based upon any class. So far at least, 00037 most applications have been based upon simple types like `integer's, 00038 `real's, or `doubleprecision's. Most applications do not use BaseFab's 00039 directly, but utilize specialized classes derived from BaseFab. 00040 00041 It will be easier to use a `BaseFab' if you understand the following 00042 concepts. `BaseFab' objects depend on the dimensionality of space 00043 (indirectly through the DOMAIN `Box' member). It is 00044 typical to define the macro `CH_SPACEDIM' to be 1, 2, or 3 to indicate 00045 the dimension of space. See the discussion of class `Box' for more 00046 information. A `BaseFab' contains a `Box' DOMAIN, which indicates the 00047 integer indexing space over which the array is defined. A `BaseFab' 00048 also has NVAR components. By components, we mean that for each 00049 point in the rectangular indexing space, there are NVAR values 00050 associated with that point. A Fortran array corresponding to a 00051 `BaseFab' would have (CH_SPACEDIM+1) dimensions. 00052 00053 By design, the array layout in a `BaseFab' mirrors that of a 00054 Fortran array. The first index (x direction for example) varies 00055 most rapidly, the next index (y direction), if any, varies next 00056 fastest. The component index varies last, after all the spatial 00057 indices. 00058 00059 It is sometimes convenient to be able to treat a sub-array within an 00060 existing `BaseFab' as a `BaseFab' in its own right. This is often 00061 referred to as 'aliasing' the `BaseFab'. Note that when aliasing is 00062 used, the BaseFab's domain will not, in general, be the same as the 00063 parent BaseFab's domain, nor will the number of components. 00064 BaseFab is a dimension dependent class, so CH_SPACEDIM must be 00065 defined as either 1, 2, or 3 when compiling. 00066 00067 This is NOT a polymorphic class. 00068 00069 It does NOT provide a copy constructor or assignment operator. 00070 00071 T MUST have a default constructor and an assignment operator. 00072 */ 00073 00074 extern Real BaseFabRealSetVal; 00075 00076 template <class T> class BaseFab 00077 { 00078 public: 00079 /// {\bf constructors, destructor and defines} 00080 00081 ///for AggStencil and its minions 00082 virtual long offset(const IntVect& a_iv, const int& a_ivar) const 00083 { 00084 CH_assert(a_ivar >= 0); 00085 CH_assert(a_ivar < m_nvar); 00086 CH_assert(!(m_dptr == 0)); 00087 CH_assert(m_domain.contains(a_iv)); 00088 00089 IntVect ivDiff = a_iv - m_domain.smallEnd(); 00090 IntVect ivSize = m_domain.size(); 00091 long offset = ivDiff[0]; 00092 00093 #if CH_SPACEDIM > 1 00094 offset += ivDiff[1]*ivSize[0] ; 00095 #endif 00096 #if CH_SPACEDIM > 2 00097 offset += ivDiff[2]*ivSize[0]*ivSize[1]; 00098 #endif 00099 #if CH_SPACEDIM > 3 00100 offset += ivDiff[3]*ivSize[0]*ivSize[1]*ivSize[2]; 00101 #endif 00102 #if CH_SPACEDIM > 4 00103 offset += ivDiff[4]*ivSize[0]*ivSize[1]*ivSize[2]*ivSize[3]; 00104 #endif 00105 #if CH_SPACEDIM > 5 00106 offset += ivDiff[5]*ivSize[0]*ivSize[1]*ivSize[2]*ivSize[3]*ivSize[4]; 00107 #endif 00108 offset += m_numpts * a_ivar; 00109 00110 return offset; 00111 } 00112 00113 /** 00114 Constructs an invalid `BaseFab'. The domain is invalid, the 00115 number of components is zero, and no actual array memory is 00116 allocated. An invalid `BaseFab' must be resize()d 00117 (see `BaseFab::resize') before use. 00118 */ 00119 BaseFab (); 00120 00121 /// 00122 /** 00123 Constructs a BaseFab with desired domain and number of components. 00124 */ 00125 BaseFab(const Box& a_bx, 00126 int a_n, 00127 T* a_alias = NULL); 00128 00129 /** 00130 Constructs an 'aliased' BaseFab of the requested interval of the 00131 argument BaseFab. This BaseFab does not allocate any memory, but 00132 sets its data pointer into the memory pointed to by the argument 00133 BaseFab. It is the users responsiblity to ensure this aliased 00134 BaseFab is not used after the original BaseFab has deleted its data ptr 00135 (resize, define(..) called, or destruction, etc.). 00136 00137 This aliased BaseFab will also generate side effects (modifying the values 00138 of data in one will modify the other's data). 00139 00140 This aliased BaseFab will have a_comps.size() components, starting at zero. 00141 */ 00142 BaseFab(const Interval& a_comps, 00143 BaseFab<T>& a_original); 00144 00145 /// move constructor 00146 BaseFab(BaseFab<T>&& a_in) noexcept; 00147 /// 00148 /** 00149 The destructor deletes the array memory. Unless this was an aliased 00150 BaseFab. 00151 */ 00152 virtual ~BaseFab(); 00153 00154 /** 00155 This function resizes a `BaseFab' so it covers the `Box' a_b with a_n 00156 components. If a_alias is not NULL the memory it points to is used 00157 (without checking size); otherwise the existing data is lost and the 00158 new data is uninitialized. 00159 */ 00160 void resize(const Box& a_b, 00161 int a_n = 1, 00162 T* a_alias=NULL); 00163 00164 /** 00165 Make BaseFab with desired domain and number of components. Existing 00166 data is lost. Data is in uninialized state. 00167 */ 00168 virtual void define(const Box& a_box, 00169 int a_comps, 00170 T* a_alias = NULL) 00171 { 00172 resize(a_box, a_comps, a_alias); 00173 } 00174 00175 /** 00176 alias define. no memory allocated. this BaseFab sets its data ptr 00177 directly in the a_original BaseFab data. 00178 */ 00179 virtual void define(const Interval& a_comps, 00180 BaseFab<T>& a_original); 00181 00182 /** 00183 The function returns the `BaseFab' to the invalid state. (See 00184 comments for constructors above.) The memory is freed. 00185 */ 00186 void clear(); 00187 00188 /// {\bf accessors} 00189 00190 /// 00191 /** 00192 Returns the number of components. 00193 */ 00194 int nComp() const; 00195 00196 /// 00197 /** 00198 Returns the domain (box) where the array is defined. 00199 */ 00200 const Box& box() const; 00201 00202 /** 00203 Returns an IntVect giving the length 00204 of the domain in each direction. 00205 */ 00206 IntVect size() const; 00207 00208 /** 00209 Returns the lower corner of the domain. See class `Box' for analogue. 00210 */ 00211 const IntVect& smallEnd() const; 00212 00213 /** 00214 Returns the upper corner of the domain. See class `Box' for analogue. 00215 */ 00216 const IntVect& bigEnd() const; 00217 00218 /// 00219 /** 00220 Returns an Interval for the entire range on components. 00221 */ 00222 Interval interval() const 00223 { 00224 return Interval(0, m_nvar-1); 00225 } 00226 00227 /// move assignment 00228 inline BaseFab<T>& operator= (BaseFab<T>&&) noexcept; 00229 /** 00230 Returns a modifiable lvalue reference to the Nth component value defined 00231 at position p in the domain. This operator may be inefficient if the 00232 C++ compiler is unable to optimize the C++ code. 00233 */ 00234 T& operator () (const IntVect& a_p, 00235 int a_N); 00236 00237 T& operator () (const IntVect& a_p); 00238 00239 /** 00240 Returns a conatant reference to the Nth component value defined at 00241 position p in the domain. This operator may be inefficient if the C++ 00242 compiler is unable to optimize the C++ code. 00243 */ 00244 const T& operator () (const IntVect& p, 00245 int N) const; 00246 00247 const T& operator () (const IntVect& p) const; 00248 00249 /** 00250 This function puts numcomp component values, starting at component N, 00251 from position pos in the domain into array data, that must be allocated 00252 by the user. 00253 */ 00254 void getVal(T* a_data, 00255 const IntVect& a_pos, 00256 int a_N, 00257 int a_numcomp) const; 00258 00259 /** 00260 This function puts all component values, starting at component 0, 00261 from position pos in the domain into array data, that must be allocated 00262 by the user. 00263 */ 00264 void getVal(T* a_data, 00265 const IntVect& a_pos) const; 00266 00267 ///{\bf Fortran interface functions} 00268 00269 /** 00270 Returns the lower corner of the domain. Instead of returning them in 00271 the form of IntVects, as in smallEnd and bigEnd, it returns the values 00272 as a pointer to an array of constant integers. This is useful when 00273 interfacing to Fortran subroutines. It should not be used in any other 00274 context!!! 00275 */ 00276 const int* loVect() const; 00277 00278 /** 00279 Returns the upper corner of the domain. Instead of returning them in 00280 the form of IntVects, as in smallEnd and bigEnd, it returns the values 00281 as a pointer to an array of constant integers. This is useful when 00282 interfacing to Fortran subroutines. It should not be used in any other 00283 context!!! 00284 */ 00285 const int* hiVect() const; 00286 00287 /** 00288 Returns a pointer to an integer that contains the number of components 00289 in the BaseFab. This is useful when interfacing to Fortran subroutines. 00290 It should not be used in any other context!!! 00291 */ 00292 const int* nCompPtr() const; 00293 00294 /** 00295 Returns a pointer to an object of type T that is the value of the a_nth 00296 component associated with the cell at the low end of the domain. This 00297 is commonly used to get a pointer to data in the array which is then 00298 handed off to a Fortran subroutine. It should not be used in any other 00299 context!!! Remember that data is stored in Fortran array order, with 00300 the component index coming last. In other words, `dataPtr' returns a 00301 pointer to all the a_nth components. 00302 */ 00303 T* dataPtr(int a_n = 0); 00304 00305 /** 00306 Returns a constant pointer to an object of type T that is the value of 00307 the a_nth component associated with the cell at the low end of the domain. 00308 This is commonly used to get a pointer to data in the array which is 00309 then handed off to a Fortran subroutine. It should not be used in any 00310 other context!!! Remember that data is stored in Fortran array order, 00311 with the component index coming last. In other words, `dataPtr' returns 00312 a pointer to all the a_nth components. 00313 */ 00314 const T* dataPtr(int a_n = 0) const; 00315 00316 ///{\bf comparison functions} 00317 00318 /** 00319 Returns true if the domain of a_fab is totally contained within the domain 00320 of this `BaseFab'. 00321 */ 00322 bool contains(const BaseFab<T>& a_fab) const; 00323 00324 /** 00325 Returns true if a_bx is totally contained within the domain of this 00326 `BaseFab'. 00327 */ 00328 bool contains(const Box& a_bx) const; 00329 00330 ///{\bf data modification functions} 00331 00332 /** 00333 The setVal functions set subregions in the `BaseFab' to a constant value. 00334 This most general form specifies the subbox, the starting component 00335 number, and the number of components to be set. 00336 */ 00337 void setVal(T a_x, 00338 const Box& a_bx, 00339 int a_nstart, 00340 int a_numcomp); 00341 00342 /// 00343 /** 00344 Modifies this BaseFab so that all values of a component, a_n, in the 00345 specified Box, a_bx, are set to the given value, a_x. 00346 */ 00347 void setVal(T a_x, 00348 const Box& a_bx, 00349 int a_n); 00350 00351 /// 00352 /** 00353 Modifies this BaseFab so that all values of a component, a_n, are set to 00354 the given value, a_x. 00355 */ 00356 void setVal(T a_x, 00357 int a_n); 00358 00359 /// 00360 /** 00361 Modifies this BaseFab so that all values of all components are set to 00362 the given value, a_x. 00363 */ 00364 void setVal(T a_x); 00365 00366 /** 00367 Modifies this BaseFab by copying the contents of the argument BaseFab 00368 into it. This, the most general form of copy, specifies the contents 00369 of any sub-box a_srcbox in `BaseFab' a_src may be copied into a (possibly 00370 different) a_destbox in the destination `BaseFab'. Note that although 00371 the a_srcbox and the a_destbox may be disjoint, they must be the same size 00372 and shape. If the sizes differ, the copy is undefined and a runtime 00373 error results. This copy function is the only one of the copy 00374 functions to allow a copy between differing boxes. The user also 00375 specifies how many components are copied, starting at component 00376 a_srccomp in a_src and stored starting at component a_destcomp. The 00377 results are UNDEFINED if the a_src and dest BaseFabs are the same and 00378 the a_srcbox and a_destbox overlap. 00379 00380 */ 00381 BaseFab<T>& copy(const BaseFab<T>& a_src, 00382 const Box& a_srcbox, 00383 int a_srccomp, 00384 const Box& a_destbox, 00385 int a_destcomp, 00386 int a_numcomp); 00387 00388 /** 00389 Modifies this BaseFab by copying the contents of the argument BaseFab 00390 into it. A copy within the intersecting region of the domains of the 00391 two BaseFabs is performed. The user specifies how many components are 00392 copied, starting at component a_srccomp in a_src and stored starting at 00393 component a_destcomp. 00394 */ 00395 BaseFab<T>& copy(const BaseFab<T>& a_src, 00396 int a_srccomp, 00397 int a_destcomp, 00398 int a_numcomp = 1); 00399 00400 /** 00401 Modifies this BaseFab by copying the contents of the argument BaseFab 00402 into it. A copy within the intersecting region of the domains of the 00403 two BaseFabs and the specified Box a_destbox is performed. All 00404 components are copied. 00405 */ 00406 BaseFab<T>& copy(const BaseFab<T>& a_src, 00407 const Box& a_destbox); 00408 00409 /** 00410 Modifies this BaseFab by copying the contents of the argument BaseFab 00411 into it. A copy within the intersecting region of the domains of the 00412 two BaseFabs is performed. All components are copied. 00413 */ 00414 BaseFab<T>& copy(const BaseFab<T>& a_src); 00415 00416 /// 00417 /** 00418 Copy from a subsection of one box into another. Assumes the boxes are 00419 both in the same index space, and that box R is completely contained 00420 in both the source and destination boxes. 00421 */ 00422 void copy(const Box& a_RegionFrom, 00423 const Interval& a_Cdest, 00424 const Box& a_RegionTo, 00425 const BaseFab<T>& a_src, 00426 const Interval& a_Csrc); 00427 00428 /// {\bf domain modification functions} 00429 00430 /// 00431 /** 00432 Modifies the domain of this BaseFab by shifting. Equivalent to 00433 fab.shift(0,a_v[0]).shift(1,a_v[1])... There is no effect upon 00434 the array memory. 00435 */ 00436 BaseFab<T>& shift(const IntVect& a_v); 00437 00438 /// 00439 /** 00440 Modifies the domain of this BaseFab by shifting it a_ncells 00441 indexing positions in coordinate direction a_idir. Directions are 00442 zero-based. It is an error if not 0 <= a_idir < SpaceDim. There is 00443 no effect upon the array memory. 00444 */ 00445 BaseFab<T>& shift(int a_idir, 00446 int a_ncells); 00447 00448 /// 00449 /** 00450 Modifies the domain of this BaseFab by shifting by "half" indices, 00451 thereby converting the Box from type CELL to NODE or vice-versa. 00452 fab.shiftHalf(0,1) shifts the domain to the right by 1/2 cells. 00453 fab.shiftHalf(1,-3) shifts the domain in the -j direction by 3/2 cells. 00454 NOTE: If a_numHalfs is EVEN the shift is a_numHalfs/2 full zones 00455 and hence will not change the type. This is: fab.shiftHalf(1,4) == 00456 fab.shift(1,2). Directions are zero-based. It is an error if not 0 00457 <= a_dir < SpaceDim. There is no effect upon the array memory. 00458 */ 00459 BaseFab<T>& shiftHalf(int a_dir, 00460 int a_numHalfs); 00461 00462 /// 00463 /** 00464 Modifies the domain of this BaseFab by shifting by half indices. 00465 Equivalent to fab.shiftHalf(0,a_v[0]).shiftHalf(1,a_v[1]) ... 00466 There is no effect upon the array memory. 00467 */ 00468 BaseFab<T>& shiftHalf(const IntVect& a_v); 00469 00470 ///{\bf linearization functions} 00471 00472 /// 00473 /** 00474 Returns the size, in number of bytes, of a flat linear 00475 representation of the data in this object in the area defined 00476 by the input Box a_box and the component Interval a_comps. The size 00477 does not include the size of a_box and a_comps. 00478 */ 00479 virtual size_t size(const Box& a_box, 00480 const Interval& a_comps) const; 00481 00482 /// 00483 /** 00484 Write a linear representation of the internal data. Assumes that 00485 sufficient memory for the buffer has already been allocated by the 00486 caller. 00487 */ 00488 virtual void linearOut(void* a_buf, 00489 const Box& a_R, 00490 const Interval& a_comps) const; 00491 00492 /// Same as linearOut, but returns the current location in the buffer 00493 virtual void* linearOut2(void* a_buf, 00494 const Box& a_R, 00495 const Interval& a_comps) const; 00496 00497 /// 00498 virtual void linearIn(void* a_buf, 00499 const Box& a_R, 00500 const Interval& a_comps); 00501 00502 /// same as linearIn, but returns the current location in the buffer 00503 virtual void* linearIn2(void* a_buf, 00504 const Box& a_R, 00505 const Interval& a_comps); 00506 00507 /// These functions are required for broadcast & gather. 00508 00509 void linearOut(void* a_buf) const; 00510 /// 00511 void linearIn(const void* const a_buf); 00512 /// 00513 int linearSize(void) const; 00514 00515 /// 00516 static int preAllocatable() 00517 { 00518 return 0; // static preAllocatable 00519 } 00520 00521 /** 00522 Turns a_slice into a BaseFab that's the same as *this except that it's just 00523 one cell thick in the a_sliceSpec.direction-th direction, and its 00524 coordinate in that direction is a_sliceSpec.position. 00525 00526 If a_sliceSpec.position is outside the range of *this, that's a fatal error. 00527 */ 00528 void degenerate(BaseFab<T>& a_slice, const SliceSpec& a_sliceSpec) const; 00529 00530 /// 00531 bool isAliased() const; 00532 00533 ///regression test 00534 static int test(); 00535 00536 ///regression test 00537 static int testBoxAndComp(); 00538 protected: 00539 // 00540 // Allocates memory for the `BaseFab<T>'. 00541 // 00542 void define(); 00543 00544 // 00545 // Deallocates memory for the `BaseFab<T>'. 00546 // 00547 void undefine(); 00548 00549 static std::string name(); 00550 00551 // 00552 // The function called by BaseFab copy operations. 00553 // 00554 virtual void performCopy(const BaseFab<T>& a_src, 00555 const Box& a_srcbox, 00556 int a_srccomp, 00557 const Box& a_destbox, 00558 int a_destcomp, 00559 int a_numcomp); 00560 00561 // 00562 // This function is called by the `BaseFab' setVal operations. 00563 // 00564 void performSetVal(T a_x, 00565 const Box& a_bx, 00566 int a_nstart, 00567 int a_numcomp); 00568 00569 // 00570 // template class static data member. not sure if this will 00571 // work with all compilers. It has been in the draft standard 00572 // for some time 00573 // 00574 static Arena* s_Arena; 00575 00576 Box m_domain; // My index space. 00577 int m_nvar; // Number components. 00578 long m_numpts; // Cached number of points in FAB. 00579 long m_truesize; // m_nvar * m_numpts that was allocated on heap 00580 // (only if m_aliased == false). 00581 T* __restrict m_dptr; // The data pointer. 00582 bool m_aliased; // The BaseFab is not allocated memory, but is an alias. bvs 00583 00584 private: 00585 // 00586 // These functions are made private to prevent use of the default 00587 // functions provided by the C++ compiler. 00588 // 00589 BaseFab<T>& operator= (const BaseFab<T>&); 00590 BaseFab (const BaseFab<T>&); 00591 }; 00592 00593 #include "NamespaceFooter.H" 00594 00595 #include "BaseFabImplem.H" 00596 00597 #endif