Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

BinFabImplem.H

Go to the documentation of this file.
00001 /*   _______              __
00002     / ___/ /  ___  __ _  / /  ___
00003    / /__/ _ \/ _ \/  ' \/ _ \/ _ \
00004    \___/_//_/\___/_/_/_/_.__/\___/
00005 */
00006 //
00007 // This software is copyright (C) by the Lawrence Berkeley
00008 // National Laboratory.  Permission is granted to reproduce
00009 // this software for non-commercial purposes provided that
00010 // this notice is left intact.
00011 //
00012 // It is acknowledged that the U.S. Government has rights to
00013 // this software under Contract DE-AC03-765F00098 between
00014 // the U.S.  Department of Energy and the University of
00015 // California.
00016 //
00017 // This software is provided as a professional and academic
00018 // contribution for joint exchange. Thus it is experimental,
00019 // is provided ``as is'', with no warranties of any kind
00020 // whatsoever, no support, no promise of updates, or printed
00021 // documentation. By using this software, you acknowledge
00022 // that the Lawrence Berkeley National Laboratory and
00023 // Regents of the University of California shall have no
00024 // liability with respect to the infringement of other
00025 // copyrights by any part of this software.
00026 //
00027 
00028 #ifndef _BINFABIMPLEM_H_
00029 #define _BINFABIMPLEM_H_
00030 
00031 #include "BoxIterator.H"
00032 #include "List.H"
00033 
00034 //
00035 // Implementation.=====================================
00036 //
00037 
00038 template <class T>
00039 BinFab<T>::BinFab()
00040   : BaseFab<List<T> >(),
00041     m_origin(D_DECL(1.0e8, 1.0e8, 1.0e8)),
00042     m_mesh_spacing(D_DECL(0,0,0))
00043 {
00044 }
00045 
00046 template <class T>
00047 BinFab<T>::BinFab(const Box&           a_domain,
00048                   const RealVect&      a_mesh_spacing,
00049                   const RealVect&      a_origin,
00050                   const ProblemDomain& a_probdomain)
00051 {
00052   define(a_domain, a_mesh_spacing, a_origin, a_probdomain);
00053 }
00054 
00055 template <class T>
00056 BinFab<T>::BinFab(const BinFab& a_binfab)
00057 {
00058   define(a_binfab.domain, a_binfab.m_mesh_spacing, a_binfab.m_origin,
00059          a_binfab.m_probdomain);
00060 
00061   copy(a_binfab);
00062 }
00063 
00064 template <class T>
00065 BinFab<T>::~BinFab()
00066 {
00067   this->undefine();
00068 }
00069 
00070 template <class T>
00071 void BinFab<T>::define(const Box&           a_domain,
00072                        const RealVect&      a_mesh_spacing,
00073                        const RealVect&      a_origin,
00074                        const ProblemDomain& a_probdomain)
00075 {
00076   this->domain = a_domain;
00077   this->nvar = 1;
00078   this->numpts = this->domain.numPts();
00079 
00080   BaseFab<List<T> >::define();
00081 
00082   m_mesh_spacing = a_mesh_spacing;
00083   m_origin = a_origin;
00084   m_probdomain = a_probdomain;
00085 }
00086 
00087 template <class T>
00088 void BinFab<T>::reBin()
00089 {
00090   // loop through each bin and determine if each binItem is
00091   // in the correct bin.
00092   BoxIterator bit(this->domain);
00093   int comp = 0;
00094 
00095   for (bit.begin(); bit.ok(); ++bit)
00096     {
00097       const IntVect thisIV = bit();
00098       List<T>& thisList = this->operator()(thisIV,comp);
00099 
00100       if (thisList.length() > 0)
00101         {
00102           // now index through the List and figure out which bin this
00103           // particle should be in
00104           ListIterator<T> thisLit(thisList);
00105           IntVect binLoc;
00106 
00107           for (thisLit.rewind(); thisLit; ++thisLit)
00108             {
00109               T& thisItem = thisList[thisLit];
00110               binLoc = locateBin(thisItem);
00111 
00112               if (binLoc != thisIV)
00113                 {
00114                   // binItem needs to be moved.
00115                   // note that if binItem moves outside of domain, it is lost
00116                   if (this->domain.contains(binLoc))
00117                     this->operator()(binLoc,comp).append(thisItem);
00118 #ifndef NDEBUG
00119                   else
00120                     cerr << "warning: BinFab::reBin() lost an item at " << binLoc << endl;
00121 #endif
00122                   thisList.remove(thisLit);
00123                 }
00124             } // end loop over items in this List of binItems
00125         } // end if this list has items
00126     } // end loop over bins
00127 }
00128 
00130 template <class T>
00131 void BinFab<T>::addItem(const T& a_item)
00132 {
00133     int comp = 0;
00134     IntVect binLoc = locateBin(a_item);
00135 
00136     if (this->domain.contains(binLoc))
00137       {
00138         this->operator()(binLoc,comp).append(a_item);
00139       }
00140 }
00141 
00143 template <class T>
00144 void
00145 BinFab<T>::addItems(const List<T>& a_List)
00146 {
00147   if (a_List.length() > 0)
00148     {
00149       // loop through items in List, and add to appropriate locations
00150       ListIterator<T> lit(a_List);
00151       int comp = 0;
00152       IntVect binLoc;
00153 
00154       for (lit.rewind(); lit; ++lit)
00155         {
00156           const T& thisItem =  a_List[lit];
00157           binLoc = locateBin(thisItem);
00158 
00159           if (this->domain.contains(binLoc))
00160           {
00161             this->operator()(binLoc,comp).append(thisItem);
00162           }
00163         }
00164     }
00165 }
00166 
00168 //  [NOTE: this is mostly the same as the previous version, except for the inner loop]
00169 template <class T>
00170 void
00171 BinFab<T>::addItemsDestructive(List<T>& a_List)
00172 {
00173  if (a_List.length() > 0)
00174     {
00175       // loop through items in List, add to appropriate bins,
00176       // and remove from List
00177       ListIterator<T> lit(a_List);
00178       int comp = 0;
00179       IntVect binLoc;
00180 
00181       for (lit.rewind(); lit; )
00182         {
00183           const T& thisItem =  a_List[lit];
00184           binLoc = locateBin(thisItem);
00185 
00186           if (this->domain.contains(binLoc))  //[NOTE: BaseFab domain, not problem domain]
00187             {
00188               this->operator()(binLoc,comp).append(thisItem);
00189               a_List.remove(lit);
00190             }
00191           else
00192             {
00193               // removing a list element has the side-effect of moving the
00194               // iterator forward, so only increment explicitly if not removed
00195               ++lit;
00196             }
00197         }
00198     }
00199 }
00200 
00202 
00205 //  [NOTE: this is mostly the same as the previous version, except for the inner loop]
00206 template <class T>
00207 void
00208 BinFab<T>::addItemsDestructive(List<T>& a_List ,const Box& a_valid ,bool a_in)
00209 {
00210   assert( a_valid.cellCentered() );
00211   if (a_List.length() > 0) 
00212     {
00213       // loop through items in List, add to appropriate bins, 
00214       // and remove from List
00215       ListIterator<T> lit(a_List);
00216       int comp = 0;
00217       IntVect binLoc;
00218 
00219       for (lit.rewind(); lit; )
00220         {
00221           const T& thisItem =  a_List[lit];
00222           binLoc = locateBin(thisItem);
00223           if (this->domain.contains(binLoc))  //[NOTE: BaseFab domain, not problem domain]
00224             {
00225               this->operator()(binLoc,comp).append(thisItem);
00226               // If the a_in flag is true, then delete the particle from the
00227               // List if it is in the valid Box; if the a_in flag is false,
00228               // delete the particle if it is NOT in the Box.
00229               // Removing a list element has the side-effect of moving the
00230               // iterator forward, so explicitly increment the iterator only
00231               // if the particle was not removed.
00232               if( a_valid.contains(binLoc) )
00233                 {
00234                   if( a_in ) a_List.remove(lit);
00235                   else     ++lit ;
00236                 }
00237               else
00238                 {
00239                   if( a_in ) ++lit;
00240                   else     a_List.remove(lit);
00241                 }
00242             }
00243           else
00244             {
00245               // not added or removed, so increment the iterator
00246               ++lit;
00247             }
00248         }
00249     }  
00250 }
00251 
00252 template <class T>
00253 void BinFab<T>::clear()
00254 {
00255   this->undefine();
00256 
00257   this->domain = Box();
00258   this->nvar = 0;
00259   this->numpts = 0;
00260   m_origin = RealVect(D_DECL(1.0e8, 1.0e8, 1.0e8));
00261   m_mesh_spacing = RealVect(D_DECL(1.0e8, 1.0e8, 1.0e8));
00262 }
00263 
00264 template <class T>
00265 int BinFab<T>::numItems(const Box& a_box, const Interval& a_comps) const
00266 {
00267   int totalSize = 0;
00268 
00269   // default is an empty box, so use this BinFab's box instead
00270   // [NOTE: this leaves the caller no way to ask for an empty box;
00271   //       it must avoid calling this routine in that case. Sorry.]
00272   Box ibox = a_box;
00273   if (ibox.isEmpty())
00274     {
00275       ibox = this->box();
00276     }
00277 
00278   // default is an empty interval, so use all comps
00279   //[NOTE: see above NOTE]
00280   Interval comps = a_comps;
00281   if (comps.size() == 0)
00282     {
00283       comps = this->interval();
00284     }
00285 
00286   // iterate over all bins and components in the BinFab
00287   // [NOTE: making the "c" loop be inner would have better cache
00288   //       efficiency for large #s of comps, but would take more
00289   //       instructions and that will dominate for small ncomps.
00290   for (int c = comps.begin(); c <= comps.end(); ++c)
00291     {
00292       for (BoxIterator bi(ibox); bi.ok(); ++bi)
00293         {
00294           totalSize += this->operator()(bi(),c).length();
00295         }
00296     }
00297 
00298   return totalSize;
00299 }
00300 
00301 // this is just to prevent hiding of the BaseFab version
00302 template <class T> 
00303 const int*
00304 BinFab<T>::size() const
00305 {
00306   return BaseFab<List<T> >::size();
00307 }
00308   
00309 
00310 template <class T>
00311 int
00312 BinFab<T>::size(const Box& box, const Interval& comps) const
00313 {
00314   int totalSize = 0;
00315 
00316   // First extract the size of the binItem.
00317   // Assumes all the items are the same size.
00318   int sizeOfT ;
00319   {
00320     T tmp ;
00321     sizeOfT = tmp.size() ;
00322   }
00323 
00324   // Count the number of items in the fab
00325   BoxIterator bit(box);
00326   for (int comp=comps.begin(); comp<=comps.end(); ++comp)
00327     {
00328       for (bit.begin(); bit.ok(); ++bit)
00329         {
00330           const List<T>& thisList = this->operator()(bit(), comp);
00331           totalSize += thisList.length();
00332         }
00333     }
00334 
00335   // totalSize now has total number of binItems.  now compute total size
00336   totalSize *= sizeOfT;
00337 
00338   // will also need to add an integer for each list to determine how
00339   // many binItems are in each list. (is this the right thing to do?)
00340   // alternate approach would be to simply unpack a List<T> on the other
00341   // end and then do an addItems call with that list.  that will probably
00342   // be slower, though.
00343   int numBins = box.numPts() * comps.size();
00344   totalSize += numBins * sizeof(int);
00345 
00346   return totalSize;
00347 }
00348 
00349 template <class T>
00350 void BinFab<T>::linearOut(void* buf, const Box& R, const Interval& comps) const
00351 {
00352   char* buf_ch = (char*)buf;
00353   // all we do in this function is loop over the box (and components),
00354   // and call linearOut on the individual items...
00355   BoxIterator bit(R);
00356   for (int comp=comps.begin(); comp<= comps.end(); ++comp)
00357     {
00358       for (bit.begin(); bit.ok(); ++bit)
00359         {
00360           const List<T>& thisList = this->operator()(bit(), comp);
00361           int *intBuffer = (int*)buf_ch;
00362 
00363           *intBuffer = thisList.length();
00364           buf_ch += sizeof(int);
00365 
00366           // now loop over the items in the list.
00367           ListIterator<T> lit(thisList);
00368           for (lit.rewind(); lit; ++lit)
00369             {
00370               thisList[lit].linearOut(buf_ch);
00371               buf_ch += thisList[lit].size();
00372             }
00373         }
00374     }
00375 }
00376 
00377 template <class T>
00378 void BinFab<T>::linearIn(void* buf, const Box& R, const Interval& comps)
00379 {
00380   // should be just the inverse of linearOut
00381   char *buf_ch = (char*)buf;
00382 
00383   BoxIterator bit(R);
00384   for (int comp = comps.begin(); comp <= comps.end(); ++comp)
00385     {
00386       for (bit.begin(); bit.ok(); ++bit)
00387         {
00388           List<T>& thisList = this->operator()(bit(), comp);
00389 
00390           // need to clear this list to prevent accumulation of binItems
00391           thisList.clear();
00392 
00393           int numItems = *((int*)buf_ch);
00394 
00395           buf_ch += sizeof(int);
00396 
00397           if (numItems > 100000)
00398             {
00399               pout() << " [error: numItems=" << numItems << "] ";
00400               numItems = 1;
00401             }
00402 
00403           for (int n = 0; n < numItems; ++n)
00404             {
00405               T thisBinItem;
00406 
00407               thisBinItem.linearIn( buf_ch );
00408               thisList.append(thisBinItem);
00409               buf_ch += thisBinItem.size();
00410             }
00411         }
00412     }
00413 }
00414 
00415 template <class T>
00416 IntVect BinFab<T>::locateBin(const T& a_binItem) const
00417 {
00418   IntVect binLoc;
00419   RealVect thisPos = a_binItem.position();
00420 
00421   thisPos -= m_origin;
00422   thisPos /= m_mesh_spacing;
00423 
00424   for (int d=0; d<SpaceDim; ++d)
00425     {
00426       // handle periodic domain
00427       if (m_probdomain.isPeriodic(d))
00428         {
00429           binLoc[d] = (int)floor(thisPos[d]) % m_probdomain.domainBox().size(d);
00430         }
00431       else
00432         {
00433           binLoc[d] = (int) floor(thisPos[d]);
00434           // need to shift by one if negative
00435           if (thisPos[d] < 0) --binLoc[d];
00436         }
00437     }
00438 
00439   return binLoc;
00440 }
00441 
00442 #endif

Generated on Fri Jul 2 17:53:41 2004 for Chombo by doxygen 1.3.2