Main Page   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    / /__/ _ \/ _ \/  V \/ _ \/ _ \
00004    \___/_//_/\___/_/_/_/_.__/\___/
00005 */
00006 // CHOMBO Copyright (c) 2000-2004, The Regents of the University of
00007 // California, through Lawrence Berkeley National Laboratory (subject to
00008 // receipt of any required approvals from U.S. Dept. of Energy).  All
00009 // rights reserved.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are met:
00013 //
00014 // (1) Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 // (2) Redistributions in binary form must reproduce the above copyright
00017 // notice, this list of conditions and the following disclaimer in the
00018 // documentation and/or other materials provided with the distribution.
00019 // (3) Neither the name of Lawrence Berkeley National Laboratory, U.S.
00020 // Dept. of Energy nor the names of its contributors may be used to endorse
00021 // or promote products derived from this software without specific prior
00022 // written permission.
00023 //
00024 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00026 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00027 // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00028 // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00029 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00030 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00031 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00032 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00033 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00034 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035 //
00036 // You are under no obligation whatsoever to provide any bug fixes,
00037 // patches, or upgrades to the features, functionality or performance of
00038 // the source code ("Enhancements") to anyone; however, if you choose to
00039 // make your Enhancements available either publicly, or directly to
00040 // Lawrence Berkeley National Laboratory, without imposing a separate
00041 // written license agreement for such Enhancements, then you hereby grant
00042 // the following license: a non-exclusive, royalty-free perpetual license
00043 // to install, use, modify, prepare derivative works, incorporate into
00044 // other computer software, distribute, and sublicense such Enhancements or
00045 // derivative works thereof, in binary and source code form.
00046 //
00047 // TRADEMARKS. Product and company names mentioned herein may be the
00048 // trademarks of their respective owners.  Any rights not expressly granted
00049 // herein are reserved.
00050 //
00051 
00052 #ifndef _BINFABIMPLEM_H_
00053 #define _BINFABIMPLEM_H_
00054 
00055 #include <cmath>
00056 
00057 #include "BoxIterator.H"
00058 #include "parstream.H"
00059 
00060 //
00061 // Implementation.=====================================
00062 //
00063 
00064 template <class T>
00065 BinFab<T>::BinFab()
00066   : BaseFab<List<T> >(),
00067     //[NOTE: dont use RealVect::Zero because of unreliable order of static initializations. <dbs>]
00068     m_origin(D_DECL(0,0,0)),
00069     m_mesh_spacing(D_DECL(0,0,0))
00070 {
00071 }
00072 
00073 template <class T>
00074 BinFab<T>::BinFab(const Box&           a_domain,
00075                   const RealVect&      a_meshSpacing,
00076                   const RealVect&      a_origin)
00077 {
00078   define(a_domain, a_meshSpacing, a_origin);
00079 }
00080 
00081 template <class T>
00082 BinFab<T>::BinFab(const BinFab<T>& a_binfab)
00083 {
00084   define(a_binfab.m_domain, a_binfab.m_mesh_spacing, a_binfab.m_origin);
00085   BaseFab<List<T> >::copy(a_binfab);
00086 }
00087 
00088 template <class T>
00089 BinFab<T>::~BinFab()
00090 {
00091   this->undefine();
00092 }
00093 
00094 template <class T>
00095 void BinFab<T>::define(const Box&           a_domain,
00096                        const RealVect&      a_meshSpacing,
00097                        const RealVect&      a_origin)
00098 {
00099   // BaseFab vars
00100   this->m_domain = a_domain;
00101   this->m_nvar = 1;
00102   this->m_numpts = this->m_domain.numPts();
00103   BaseFab<List<T> >::define();
00104   // BinFab vars
00105   m_mesh_spacing = a_meshSpacing;
00106   m_origin = a_origin;
00107 }
00108 
00109 // set the mesh spacing
00110 //[NOTE: this is a vector even though Chombo doesn't support isotropic grids yet.]
00111 template <class T>
00112 void BinFab<T>::meshSpacing(const RealVect & a_meshSpacing)
00113 {
00114   m_mesh_spacing = a_meshSpacing;
00115 }
00116 
00117 // retrieve a copy of the mesh spacing
00118 template <class T>
00119 RealVect BinFab<T>::meshSpacing() const
00120 {
00121   return m_mesh_spacing;
00122 }
00123 
00124 // set the coordinate origin;
00125 // i.e. the physical location of the lower corner of cell IntVect::Zero
00126 template <class T>
00127 void BinFab<T>::origin(const RealVect& a_origin)
00128 {
00129   m_origin = a_origin;
00130 }
00131 
00132 // retrieve a copy of the coordinate origin
00133 template <class T>
00134 RealVect BinFab<T>::origin() const
00135 {
00136   return m_origin;
00137 }
00138 
00140 
00142 template <class T>
00143 void BinFab<T>::addItem(const T& a_item)
00144 {
00145   int comp = 0;
00146   IntVect binLoc = locateBin(a_item);
00147   if (this->m_domain.contains(binLoc))
00148   {
00149     this->operator()(binLoc,comp).append(a_item);
00150   }
00151 }
00152 
00154 template <class T>
00155 void BinFab<T>::addItem(const T& a_item, const IntVect& a_binLoc)
00156 {
00157   int comp = 0;
00158   if (this->m_domain.contains(a_binLoc))
00159   {
00160     this->operator()(a_binLoc,comp).append(a_item);
00161   }
00162 }
00163 
00165 template <class T>
00166 void BinFab<T>::addItems(const List<T>& a_List)
00167 {
00168   if (a_List.isNotEmpty())
00169   {
00170     // loop through items in List, and add to appropriate locations
00171     ListIterator<T> lit(a_List);
00172     int comp = 0;
00173     IntVect binLoc;
00174 
00175     for (lit.rewind(); lit; ++lit)
00176     {
00177       const T& thisItem =  a_List[lit];
00178       binLoc = locateBin(thisItem);
00179 
00180       if (this->m_domain.contains(binLoc))
00181       {
00182         this->operator()(binLoc,comp).append(thisItem);
00183       }
00184     }
00185   }
00186 }
00187 
00189 
00191 //  [NOTE: this is mostly the same as the previous version, except for the inner loop]
00192 template <class T>
00193 void BinFab<T>::addItemsDestructive(List<T>& a_List)
00194 {
00195   if (a_List.isNotEmpty())
00196   {
00197     // loop through items in List, add to appropriate bins,
00198     // and remove from List
00199     ListIterator<T> lit(a_List);
00200     int comp = 0;
00201     IntVect binLoc;
00202 
00203     for (lit.rewind(); lit; )
00204     {
00205       const T& thisItem =  a_List[lit];
00206       binLoc = locateBin(thisItem);
00207       if (this->m_domain.contains(binLoc)) //[NOTE: BaseFab domain, not problem domain]
00208       {
00209         //this->operator()(binLoc,comp).append(thisItem);
00210         //a_List.remove(lit);
00211         this->operator()(binLoc,comp).transfer(lit);
00212       }
00213       else
00214       {
00215         // removing a list element has the side-effect of moving the
00216         // iterator forward, so only increment explicitly if not removed
00217         ++lit ;
00218       }
00219     }
00220   }
00221 }
00222 
00224 // [NOTE: this is mostly the same as the previous version, except for the inner loop]
00225 template <class T>
00226 void BinFab<T>::addItemsDestructive(List<T>& a_List, const Box& a_valid ,bool a_in)
00227 {
00228   assert( a_valid.cellCentered() );
00229   if (a_List.isNotEmpty())
00230   {
00231     // loop through items in List, add to appropriate bins,
00232     // and remove from List
00233     ListIterator<T> lit(a_List);
00234     int comp = 0;
00235     IntVect binLoc;
00236 
00237         for (lit.rewind(); lit; )
00238       {
00239         const T& thisItem =  a_List[lit];
00240         binLoc = locateBin(thisItem);
00241         if (this->m_domain.contains(binLoc)) //[NOTE: BaseFab domain, not problem domain]
00242           {
00243 
00244             // If the a_in flag is true, then delete the particle from the
00245             // List if it is in the valid Box; if the a_in flag is false,
00246             // delete the particle if it is NOT in the Box.
00247             // Transfering a list element has the side-effect of moving the
00248             // iterator forward, so explicitly increment the iterator only
00249             // if the particle was not transfered.  Wish C++ have a nice XOR function.
00250             if( a_valid.contains(binLoc) )
00251               {
00252                 if( a_in )
00253                   {
00254                     //this->operator()(binLoc,comp).append(thisItem);
00255                     //a_List.remove(lit);
00256                     this->operator()(binLoc,comp).transfer(lit);
00257                   }
00258                 else
00259                   {
00260                     this->operator()(binLoc,comp).append(thisItem);
00261                     ++lit ;
00262                   }
00263               }
00264             else
00265               {
00266                 if( a_in )
00267                   {
00268                     this->operator()(binLoc,comp).append(thisItem);
00269                     ++lit;
00270                   }
00271                 else
00272                   {
00273                     //this->operator()(binLoc,comp).append(thisItem);
00274                     //a_List.remove(lit);
00275                     this->operator()(binLoc,comp).transfer(lit);
00276                   }
00277               }
00278 
00279           }
00280         else
00281           {
00282             // not added, so just increment the iterator
00283             ++lit ;
00284           }
00285       }
00286   }
00287 }
00288 
00290 
00291 // Look at every item in the BinFab and move to a different cell
00292 // if it is in the wrong one.  Useful after computing new physical
00293 // locations of particles, e.g. moving in time.
00294 template <class T>
00295 void BinFab<T>::reBin()
00296 {
00297   // loop through each bin and determine if each binItem is
00298   // in the correct bin.
00299   BoxIterator bit(this->m_domain);
00300   int comp = 0;
00301   IntVect binLoc;
00302 //  int lost = 0;
00303 
00304   for (BoxIterator bit(this->m_domain); bit.ok(); ++bit)
00305     {
00306       const IntVect thisIV = bit();
00307       List<T>& thisList = this->operator()(thisIV,comp);
00308 
00309       if (thisList.isNotEmpty())
00310         {
00311           // now index through the List and figure out which bin each
00312           // particle should be in
00313           for (ListIterator<T> thisLit(thisList); thisLit;)
00314             {
00315               T& thisItem = thisList[thisLit];
00316               binLoc = locateBin(thisItem);
00317 
00318               if (binLoc != thisIV)
00319                 {
00320                   // binItem needs to be moved.
00321                   // note that if binItem moves outside of domain, it is lost
00322                   if (this->m_domain.contains(binLoc))
00323                     {
00324                       // this->operator()(binLoc,comp).append(thisItem);
00325                       // thisList.remove(thisLit);
00326                       this->operator()(binLoc,comp).transfer(thisLit);
00327                     }
00328                   else
00329                     {
00330 //                    ++lost ;
00331                       thisList.remove(thisLit);
00332                     }
00333                 }
00334               else
00335                 {
00336                   // if this list element is not moved, increment the iterator
00337                   ++thisLit;
00338                 }
00339             } // end loop over items in this List of binItems
00340         } // end if this list has items
00341     } // end loop over bins
00342 //  return lost;
00343 }
00344 
00345 // Sort all the items into the appropriate bins and return items that are in (or not in) the \p Box.
00346 // The returned items are appended to the list, so the caller should clear() first if apprpriate.
00347 // Same as reBin(void) except it keeps track of the lost items.
00348 //[NOTE: items that are moved forward in the box wil be looked at twice. <dbs>]
00349 template <class T>
00350 void BinFab<T>::reBin(List<T>& a_lost, const Box & a_valid, bool a_in)
00351 {
00352 //XXX What to do if a_valid is not contained in m_domain?? <dbs>
00353   int comp = 0;  //assume only one component
00354   IntVect binLoc;
00355   Box valid = a_valid.isEmpty() ? this->m_domain : a_valid ;
00356 
00357   // Loop through _all_ the bins in this BinFab, regardless of the valid Box
00358   for (BoxIterator bit(this->m_domain); bit.ok(); ++bit)
00359   {
00360     const IntVect thisIV = bit();
00361     List<T>& thisList = this->operator()(thisIV,comp);
00362     if (thisList.isNotEmpty())
00363     {
00364       // Compute the proper cell for each element in this list
00365       for (ListIterator<T> thisLit(thisList); thisLit;) //[NOTE: no auto-increment operation]
00366       {
00367         T& thisItem = thisList[thisLit];
00368         binLoc = locateBin(thisItem);
00369         if (binLoc != thisIV)
00370         {
00371           // move it or return it, as appropriate
00372           if (valid.contains(binLoc))
00373           { // new location is in the arg box
00374             if (a_in) a_lost.transfer(thisLit) ;//return it
00375             else      this->operator()(binLoc,comp).transfer(thisLit); //move it
00376           }
00377           else if (this->m_domain.contains(binLoc))
00378           { // new location not in the arg box but in the domain
00379             this->operator()(binLoc,comp).transfer(thisLit); //move it
00380           }
00381           else
00382           { // new location is not in the domain
00383             if (!a_in) a_lost.transfer(thisLit); //return it
00384             else  thisList.remove(thisLit); // and not in the box, so throw it away
00385           }
00386           //
00387         }
00388         else
00389         {
00390           // increment the iterator only if the item stays in place
00391           ++thisLit;
00392         }
00393       } // end loop over items in this List of binItems
00394     } // end if this list has items
00395   } // end loop over bins
00396 }
00397 
00399 
00400 // Move items from a_srcBox in the source BinFab to a_destBox in *this.
00401 // This is what ::copy() would do if it allowed a non-const source.
00402 //[NOTE: if the boxes are different, the items will end up in cells with
00403 //       different IntVects from the ones they started in. <dbs>]
00404 template <class T>
00405 void BinFab<T>::transfer(BinFab<T>&  a_src,
00406                     const Box&  a_srcBox,
00407                     const Box&  a_destBox)
00408 {
00409   assert(a_src.box().contains(a_srcBox));
00410   assert(a_destBox.sameSize(a_srcBox));
00411   // Ignore components; BinFab assumes only one.
00412   const int comp = 0, ncomps = 1;
00413 //XXX stupid lack of operator==
00414 //XXX  assert( a_comps == Interval(0,0) );
00415   // loop through the cells in the intersection of the two boxes
00416   ForAllThisBNNXCBN(List<T>,a_destBox,comp,ncomps,a_src,a_srcBox,comp)
00417     {
00418       if(a_srcR.isNotEmpty())
00419       {
00420         // cast away const-ness that is assumed by the ForAll...
00421         List<T>& src = (List<T>&)a_srcR ;
00422 //XXX debug
00423 //XXX        pout() << "dbg: transfer: i=" << iR << " has " << a_srcR.length() << endl ;
00424         thisR.catenate(src);
00425       }
00426     } EndForTX
00427 }
00428 
00430 
00431 // Deletes all items from this BinFab and resets it to the undefined state.
00432 template <class T>
00433 void BinFab<T>::clear()
00434 {
00435   this->undefine();
00436   this->m_domain = Box();
00437   this->m_nvar = 0;
00438   this->m_numpts = 0;
00439   m_origin = RealVect::Zero;
00440   m_mesh_spacing = RealVect::Zero;
00441 }
00442 
00444 
00445 // Counts the number of items in the cells of a_box.
00446 template <class T>
00447 int BinFab<T>::numItems(const Box& a_box) const
00448 {
00449   // Ignore components; BinFab assumes only one.
00450   const int comp = 0 ;
00451   // default is an empty box, so use this BinFab's box instead
00452   // [NOTE: this leaves the caller no way to ask for an empty box;
00453   //       it must avoid calling this routine in that case. Sorry.]
00454   Box ibox = a_box;
00455   if (ibox.isEmpty())
00456   {
00457     ibox = this->box();
00458   }
00459   // Loop over all bins in the BinFab
00460   int totalSize = 0;
00461   for (BoxIterator bi(ibox); bi.ok(); ++bi)
00462   {
00463     totalSize += this->operator()(bi(),comp).length();
00464   }
00465 //XXX -- debug
00466 //XXX  pout() << "dbg: BinFab::numItems is " << totalSize << " for box " << ibox << endl ;
00467   return totalSize;
00468 }
00469 
00471 
00472 // Computes the linear size (in bytes) of the items in the cells of a_box.
00473 template <class T>
00474 int BinFab<T>::size(const Box& a_box, const Interval& a_comps) const
00475 {
00476   // Ignore components; BinFab assumes only one.
00477   const int ncomps = 1 ;
00478 //XXX stupid lack of operator==
00479 //XXX  assert( a_comps == Interval(0,0) );
00480   // Count the number of items in the specified Box.
00481   int totalSize = numItems(a_box);
00482   // Compute size as the number of items times the size of the items
00483   {
00484     // Compute the size of an item, assuming all are the same size.
00485     int sizeOfT;
00486     T tmp;
00487     sizeOfT = tmp.size();
00488     // totalSize has total number of items, so now compute total size
00489     totalSize *= sizeOfT;
00490   }
00491   // Will also need to include an integer for each list to specify how
00492   // many items are in each list.
00493   //[NOTE: Is this the right thing to do?  An alternate approach would be to
00494   //       simply unpack one List<T> for all the items and then call addItems()
00495   //       with that list.  But that probably will be slower. <dfmartin>]
00496   int numBins = a_box.numPts() * ncomps ;
00497   totalSize += numBins*sizeof(int);
00498   return totalSize;
00499 }
00500 
00502 
00503 // Linearizes the items in the cells of a_box into a_buf.
00504 template <class T>
00505 void BinFab<T>::linearOut(void* a_buf, const Box& a_box, const Interval& a_comps) const
00506 {
00507   // Ignore components; BinFab assumes only one.
00508   const int comp = 0 ;
00509 //XXX stupid lack of operator==
00510 //XXX  assert( a_comps == Interval(0,0) );
00511   // make a usable pointer to the buffer
00512   char* buf_ch = (char*)a_buf;
00513   // All we do in this function is loop over the Box
00514   // and call linearOut() on the List elements.
00515   for (BoxIterator bit(a_box); bit.ok(); ++bit)
00516   {
00517     const List<T>& thisList = this->operator()(bit(), comp);
00518     // write the number of list items first
00519     int *intBuffer = (int*)buf_ch;
00520     *intBuffer = thisList.length();
00521     buf_ch += sizeof(int);
00522     // now loop over the items in the list and write each one
00523     for (ListIterator<T> lit(thisList); lit.ok(); ++lit)
00524     {
00525       thisList[lit].linearOut(buf_ch);
00526       buf_ch += thisList[lit].size();
00527     }
00528   }
00529 }
00530 
00532 
00533 // Same as linearOut() except it clear()s the List after writing it.
00534 template <class T>
00535 void
00536 BinFab<T>::linearOutDestructive(void* a_buf, const Box& a_box, const Interval& a_comps)
00537 {
00538   const int comp = 0 ;
00539 //XXX stupid lack of operator==
00540 //XXX  assert( a_comps == Interval(0,0) );
00541   char* buf_ch = (char*)a_buf;
00542   for (BoxIterator bit(a_box); bit.ok(); ++bit)
00543   {
00544     List<T>& thisList = this->operator()(bit(), comp);
00545     int *intBuffer = (int*)buf_ch;
00546     *intBuffer = thisList.length();
00547     buf_ch += sizeof(int);
00548     for (ListIterator<T> lit(thisList); lit.ok(); ++lit)
00549     {
00550       thisList[lit].linearOut(buf_ch);
00551       buf_ch += thisList[lit].size();
00552     }
00553     thisList.clear();
00554   }
00555 }
00556 
00558 
00559 // Fills this BinFab from the linearization in a_buf of the cells in a_box.
00560 template <class T>
00561 void
00562 BinFab<T>::linearIn(void* a_buf, const Box& a_box, const Interval& a_comps)
00563 {
00564   // Should be just the inverse of linearOut().
00565   // Ignore components; BinFab assumes only one.
00566   const int comp = 0 ;
00567 //XXX stupid lack of operator==
00568 //XXX  assert( a_comps == Interval(0,0) );
00569   // make a usable pointer to the buffer
00570   char *buf_ch = (char*)a_buf;
00571   // All we do in this function is loop over the Box
00572   // and call linearOut() on the List elements.
00573   for (BoxIterator bit(a_box); bit.ok(); ++bit)
00574   {
00575     List<T>& thisList = this->operator()(bit(), comp);
00576     // clear the list to prevent accumulation of binItems
00577     thisList.clear();
00578 
00579     // first extract the length of the list
00580     int numItems = *((int*)buf_ch);
00581     buf_ch += sizeof(int);
00582     // loop over the list items and make the list
00583     for (int n=0; n<numItems; ++n)
00584     {
00585       T thisBinItem;
00586       thisBinItem.linearIn( buf_ch );
00587       thisList.append(thisBinItem);
00588       buf_ch += thisBinItem.size();
00589     }
00590   }
00591 }
00592 
00593 //X /*******************************************************************************
00594 //X This is an example that I want to keep here to remind that the loops over boxes
00595 //X should be unrolled through the BaseFabMacro.  <fm>
00596 //X *******************************************************************************
00597 //X template <class T>
00598 //X inline
00599 //X void
00600 //X BaseFab<T>::linearIn(void* buf, const Box& R, const Interval& comps)
00601 //X {
00602 //X   T* buffer = (T*)buf;
00603 //X   ForAllThisBNN(T,R,comps.begin(), comps.size())
00604 //X     {
00605 //X       thisR = *buffer;
00606 //X       ++buffer;
00607 //X     } EndFor;
00608 //X }
00609 //X */
00610 
00612 
00613 // Compute the IntVect of the cell containing a_binItem.
00614 template <class T>
00615 inline
00616 IntVect
00617 BinFab<T>::locateBin(const T& a_binItem) const
00618 {
00619   IntVect binLoc;
00620   RealVect thisPos = a_binItem.position();
00621   thisPos -= m_origin;
00622   thisPos /= m_mesh_spacing;
00623 
00624   for( int d=0 ; d<SpaceDim ; ++d )
00625   {
00626     binLoc[d] = (int)floor(thisPos[d]);
00627   }
00628   return binLoc;
00629 }
00630 
00631 #endif

Generated on Wed Jan 19 17:51:22 2005 for Chombo&INSwithParticles by doxygen1.2.16