src/Field/BareFieldIterator.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  *
00007  * Visit http://people.web.psi.ch/adelmann/ for more details
00008  *
00009  ***************************************************************************/
00010 
00011 #ifndef BARE_FIELD_ITERATOR_H
00012 #define BARE_FIELD_ITERATOR_H
00013 
00014 /***************************************************************************
00015  *
00016  * A iterator class used for BareField.  This will store a ref to a
00017  * BareField and keep track of a position within it's LField's.  Note that
00018  * this is not the most efficient way to loop through the elements of
00019  * a BareField, it is more efficient to do an explicit loop over LField's
00020  * and then loop over each LField separately (this avoids continual if-tests
00021  * in the increment operator checking to see if you are at the end of an
00022  * LField).
00023  *
00024  ***************************************************************************/
00025 
00026 // include files
00027 #include "Index/NDIndex.h"
00028 #include "Field/LField.h"
00029 #include "Field/FieldLoc.h"
00030 #include "Field/CompressedBrickIterator.h"
00031 #include "Field/BrickIterator.h"
00032 #include "Utility/IpplInfo.h"
00033 #include "Utility/PAssert.h"
00034 
00035 // forward declarations
00036 template<class T, unsigned Dim> class BareField;
00037 
00038 // An iterator over all the elements of a BareField.
00039 template<class T, unsigned Dim>
00040 class BareFieldIterator
00041   : public CompressedBrickIterator<T,Dim>
00042 {
00043 public:
00044   // Typedef for the type of data iterated over by this iterator
00045   typedef T return_type;
00046 
00047   // Default constructor
00048   BareFieldIterator()
00049     : CompressedBrickIterator<T,Dim>(dummy_compressed_data),
00050       LFIndex(-1),
00051       MyBareField(0)
00052   {
00053     // Increment the statistic on how many iterators were created.
00054     //INCIPPLSTAT(incDefaultBareFieldIterators);
00055   }
00056 
00057   // Construct with a BareField, and a flag indicating if the field
00058   // is constant.  If it is constant, we do not try to decompress.
00059   BareFieldIterator(BareField<T,Dim> &df)
00060     : CompressedBrickIterator<T,Dim>(dummy_compressed_data),
00061       LFIndex(0),
00062       CurrentLField(df.begin_if()),
00063       MyBareField(&df)
00064   {
00065     // set iterator at first element
00066     beginLField();
00067 
00068     // Increment the statistic on how many iterators were created.
00069     //INCIPPLSTAT(incBareFieldIterators);
00070   }
00071 
00072   // Construct with a BareField and a FieldLoc pointing to some relative
00073   // location in the Field, perhaps in a different LField than the
00074   // first one.  If it is constant, we do not try to decompress.
00075   BareFieldIterator(const FieldLoc<Dim> &loc, BareField<T,Dim> &df)
00076     : CompressedBrickIterator<T,Dim>(dummy_compressed_data),
00077       LFIndex(0),
00078       CurrentLField(df.begin_if()),
00079       MyBareField(&df)
00080   {
00081     // set iterator location to loc
00082     SetCurrentLocation(loc);
00083 
00084     // Increment the statistic on how many iterators were created.
00085     //INCIPPLSTAT(incBareFieldIterators);
00086   }
00087 
00088   // Copy constructor.
00089   BareFieldIterator(const BareFieldIterator<T,Dim> &iter)
00090     : CompressedBrickIterator<T,Dim>(iter),
00091       LFIndex(iter.LFIndex),
00092       CurrentLField(iter.CurrentLField),
00093       MyBareField(iter.MyBareField)
00094   {
00095     // Increment the statistic on how many iterators were created.
00096     //INCIPPLSTAT(incBareFieldIterators);
00097   }
00098 
00099   // Destructor
00100   ~BareFieldIterator() 
00101   {
00102   }
00103 
00104   // Assignment operator
00105   const BareFieldIterator<T,Dim> &
00106   operator=(const BareFieldIterator<T,Dim> &rhs)
00107   {
00108     // if they are the same, just return
00109     if (this == &rhs)
00110       return *this;
00111 
00112     // invoke base class operator=
00113     *(dynamic_cast<CompressedBrickIterator<T,Dim>*>(this)) = rhs;
00114 
00115     // copy data members
00116     LFIndex = rhs.LFIndex;
00117     CurrentLField = rhs.CurrentLField;
00118     MyBareField = rhs.MyBareField;
00119 
00120     return *this;
00121   }
00122 
00123   // Reset where we are pointing
00124   void SetCurrentLocation(const FieldLoc<Dim> &loc)
00125   {
00126     // Whoops!  This assumes our iterator is pointing to the first LField!
00127     // We need to make sure this is true.
00128     PAssert(MyBareField != NULL);
00129     CurrentLField = MyBareField->begin_if();
00130     LFIndex = 0;
00131 
00132     // Now advance to the requested LField, indicated by getIndex, which
00133     // returns the relative index of the LField we want to interate over.
00134     int curr = loc.getIndex();
00135     while (!done() && curr-- > 0)
00136       nextLField();
00137 
00138     if (!done()) {
00139       // find the relative offset in this LField
00140       const NDIndex<Dim>& domain = (*CurrentLField).second->getOwned();
00141       int offloc[Dim];
00142       for (unsigned int d=0; d < Dim; ++d)
00143         offloc[d] = (loc[d] - domain[d].first()) / domain[d].stride();
00144 
00145       // set the position in the current LField
00146       beginLField();
00147       moveBy(offloc);
00148     } else {
00149       IpplInfo::abort("Inconsistent FieldLoc in SetCurrentLocation.");
00150     }
00151   }
00152   
00153   // Set the given FieldLoc to the current position of this iterator.
00154   void GetCurrentLocation(FieldLoc<Dim> &loc) const
00155   {
00156     const NDIndex<Dim>& domain = (*CurrentLField).second->getOwned();
00157     for (unsigned d=0; d<Dim; ++d)
00158       loc[d] = this->GetOffset(d)*domain[d].stride() + domain[d].first();
00159     loc.setIndex(LFIndex);
00160   }
00161 
00162   // Just return the relative offset within the current LField
00163   void GetCurrentLocation(int *loc) const
00164   {
00165     const NDIndex<Dim>& domain = (*CurrentLField).second->getOwned();
00166     for (unsigned d=0; d<Dim; ++d)
00167       loc[d] = this->GetOffset(d)*domain[d].stride() + domain[d].first();
00168   }
00169 
00170   // Increment the iterator
00171   BareFieldIterator<T,Dim>& operator++()
00172   {
00173     CompressedBrickIterator<T,Dim>::operator++();
00174     if ( *this == (*CurrentLField).second->end() ) 
00175       general_increment();
00176     return *this;
00177   }
00178 
00179   // Dereference the iterator, and return a ref to the data
00180   T& operator*() const
00181   {
00182     PAssert(MyBareField != NULL);
00183     // We fill guard cells before using iterator
00184     //      PAssert(MyBareField->isDirty() ? !isInGC() : true);
00185     return CompressedBrickIterator<T,Dim>::operator*();
00186   }
00187 
00188   // Move on to the LField
00189   void nextLField()
00190   {
00191     ++CurrentLField; ++LFIndex;
00192   }
00193 
00194   // Check if we are at the end of the total iteration space
00195   bool done() const
00196   {
00197     PAssert(MyBareField != NULL);
00198     return CurrentLField == MyBareField->end_if();
00199   }
00200 
00201   // Check if we are done with iteration over just the specified dimension
00202   bool done(unsigned d) const 
00203   { 
00204     return CompressedBrickIterator<T,Dim>::done(d); 
00205   }
00206 
00207   // Set ourselves up to point to the beginning of the first LField
00208   void beginLField()
00209   {
00210     if (!done())
00211       *(CompressedBrickIterator<T,Dim>*)this = 
00212         (*CurrentLField).second->begin();
00213     else
00214       LFIndex = (-1);
00215   }
00216 
00217   // Report true if the data being iterated over is currently compressed
00218   bool IsCompressed() const
00219   {
00220     bool is_compressed = CompressedBrickIterator<T,Dim>::IsCompressed();
00221     PAssert((*CurrentLField).second->IsCompressed() == is_compressed);
00222     return is_compressed;
00223   }
00224 
00225   // Report true if the data being iterated over can be compressed
00226   bool CanCompress() const
00227   {
00228     PAssert(MyBareField != NULL);
00229     if (!MyBareField->compressible()) return false;
00230     return (*CurrentLField).second->CanCompress();
00231   }
00232 
00233   // Go and compress the current LField
00234   void Compress()
00235   {
00236     (*CurrentLField).second->Compress();
00237   }
00238 
00239   // Go and compress the current LField to the given value
00240   void Compress(T val)
00241   {
00242     (*CurrentLField).second->Compress(val);
00243   }
00244 
00245   // Try to compress the current LField
00246   bool TryCompress()
00247   {
00248     return (*CurrentLField).second->TryCompress();
00249   }
00250 
00251   // Return a reference to the BareField we're iterating over
00252   BareField<T,Dim> &GetBareField()
00253   {
00254     PAssert(MyBareField != NULL);
00255     return *MyBareField;
00256   }
00257 
00258   // Same, just for const BareField's
00259   const BareField<T,Dim> &GetBareField() const
00260   {
00261     PAssert(MyBareField != NULL);
00262     return *MyBareField;
00263   }
00264 
00265   //
00266   // Scalar code interface
00267   //
00268 
00269   // Prepare this BareField for some future scalar code use where the
00270   // BareField may be modified by BareFieldIterators.  This means
00271   // to make sure that the field is properly uncompressed and guard cells
00272   // are filled.  The
00273   // one argument allows the user to explicitly avoid filling guard
00274   // cells if they do not need this.
00275   // If tryfill is true, this routine must be called in SPMD-fashion.  If
00276   // it is false, it can be called on a per-node basis.
00277   void prepareForScalarCode(bool tryfill = true)
00278   {
00279     PAssert(MyBareField != NULL);
00280     MyBareField->prepareForScalarCode(tryfill);
00281   }
00282 
00283   // Finish up after a scalar code section.  This means go back to
00284   // a compressed state if possible, and, if the user says so, indicate
00285   // that things have been modified so the dirty flag must be set.
00286   // If modified is true, this routine must be called in SPMD-fashion.  If
00287   // it is false, it can be called on a per-node basis.
00288   void finishScalarCode(bool modified = true)
00289   {
00290     PAssert(MyBareField != NULL);
00291     MyBareField->finishScalarCode(modified);
00292   }
00293 
00294 protected:
00295   // The current LField we're iterating within right now
00296   typename BareField<T,Dim>::iterator_if CurrentLField;
00297 
00298   // The BareField we're iterating over
00299   BareField<T,Dim>* MyBareField;
00300 
00301   // Storage for some compressed value if needed.
00302   T dummy_compressed_data;
00303 
00304   // The index of our current LField, from 0 ... # LField's - 1
00305   int LFIndex;
00306 
00307   // Increment and go on to the next LField if necessary.
00308   // Put this here because the SGI compiler doesn't
00309   // recognize it out of line.
00310   void general_increment()
00311   {
00312     nextLField();
00313     beginLField();
00314   }
00315 
00316   // Check to see if our current iteration position is inside the owned
00317   // domain of the current LField.
00318   bool isInGC() const
00319   {
00320     // Get the owned domain for our current LField
00321     const NDIndex<Dim> &owned = (*CurrentLField).second->getOwned();
00322 
00323     // Check to see if our current position is within this owned domain
00324     for (unsigned d=0; d<Dim; ++d)
00325       {
00326         unsigned locd = this->GetOffset(d)*owned[d].stride() + owned[d].first();
00327         if (!owned[d].contains(Index(locd,locd)))
00328           return true;
00329       }
00330 
00331     // If we're here, we must not be in the owned domain.
00332     return false;
00333   }
00334 };
00335 
00336 
00337 #endif // BARE_FIELD_ITERATOR_H
00338 
00339 /***************************************************************************
00340  * $RCSfile: BareFieldIterator.h,v $   $Author: adelmann $
00341  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:26 $
00342  * IPPL_VERSION_ID: $Id: BareFieldIterator.h,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $ 
00343  ***************************************************************************/

Generated on Mon Jan 16 13:23:43 2006 for IPPL by  doxygen 1.4.6