src/Field/LField.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 LFIELD_H
00012 #define LFIELD_H
00013 
00014 // include files
00015 #include "Utility/Pooled.h"
00016 #include "Field/CompressedBrickIterator.h"
00017 
00018 #ifdef IPPL_USE_STANDARD_HEADERS
00019 #include <iostream>
00020 using namespace std;
00021 #else
00022 #include <iostream.h>
00023 #endif
00024 
00025 // forward declarations
00026 template <class T, unsigned Dim> class LField;
00027 template <class T, unsigned Dim>
00028 ostream& operator<<(ostream&, const LField<T,Dim>&);
00029 
00030 // Template metaprogram to calculate Dim**N. Used to
00031 // reserve space in the overlap cache below.
00032 
00033 template <int Dim>
00034 struct ToTheDim
00035 {
00036   inline static int calc(int n)
00037   {
00038     return ToTheDim<Dim-1>::calc(n) * n;
00039   }
00040 };
00041 
00042 template<>
00043 struct ToTheDim<1>
00044 {
00045   inline static int calc(int n)
00046   {
00047     return n;
00048   }
00049 };
00050 
00051 
00053 
00054 // This stores the local data for a Field.
00055 template<class T, unsigned Dim>
00056 class LField : public Pooled< LField<T,Dim> >
00057 {
00058 
00059 public: 
00060   // An iterator for the contents of this LField.
00061   typedef CompressedBrickIterator<T,Dim> iterator;
00062 
00063   // The type of domain stored here
00064   typedef NDIndex<Dim> Domain_t;
00065 
00066   //
00067   // Constructors and destructor
00068   //
00069 
00070   // Ctors for an LField.  Arguments:
00071   //     owned = domain of "owned" region of LField (without guards)
00072   //     allocated = domain of "allocated" region, which includes guards
00073   //     vnode = global vnode ID number (see below)
00074   LField(const NDIndex<Dim>& owned,
00075          const NDIndex<Dim>& allocated,
00076          int vnode = -1);
00077 
00078   // Copy constructor.
00079   LField(const LField<T,Dim>&);
00080 
00081   // Destructor: just free the memory, if it's there.
00082 
00083   ~LField();
00084 
00085   //
00086   // General information accessors
00087   //
00088 
00089   // Return information about the LField.
00090   int size(unsigned d) const { return Owned[d].length(); }
00091   const NDIndex<Dim>& getAllocated()   const { return Allocated; }
00092   const NDIndex<Dim>& getOwned()       const { return Owned; }
00093   T*    getP() { return P; }
00094 
00095   // Return global vnode ID number (between 0 and nvnodes - 1)
00096   int getVnode() const { return vnode_m; }
00097 
00098   //
00099   // iterator interface
00100   //
00101 
00102   // Return begin/end iterators for the LField data
00103   const iterator&     begin()          const { return Begin; }
00104   const iterator&     end()            const { return End; }
00105 
00106   // get an iterator over a subrange.
00107   iterator begin(const NDIndex<Dim>& domain);
00108 
00109   // Get an iterator over a subrange, when we might want to try to
00110   // compress the data in the subrange without affecting the rest of
00111   // the LField data.
00112   // The LField iterator here must be told about a specific
00113   // location into which to store a compressed value, since this
00114   // iterator is used only to create a message.  Since the intersect
00115   // region may not be the whole LField, we cannot use the LField's
00116   // storage, we need to provide our own (otherwise, when compressing
00117   // the Field, we'll write the compressed value for ALL current
00118   // iterators on the LField which use the LField's compression
00119   // storage).
00120   iterator begin(const NDIndex<Dim>& domain, T&);
00121 
00122   //
00123   // Compression handling.
00124   //
00125 
00126   // Let the user ask if we are already compressed.
00127   inline bool IsCompressed() const
00128   {
00129     return P==0;
00130   }
00131 
00132   // Let the user tell us to try to compress.
00133   // Return quickly if we already are compressed.
00134   // If the argument is true, then only examine the owned domain to determine
00135   // if all the values are the same.
00136   bool TryCompress(bool baseOnPhysicalCells = false);
00137 
00138   // Look through the data and figure out if it can be compressed.
00139   inline bool CanCompress() const
00140   {
00141     if (!IsCompressed())
00142       return CanCompress(*Begin);
00143     return true;
00144   }
00145 
00146   // Look through the data and figure out if it can be compressed
00147   // to the given value.  Return true if it can be compressed down to the
00148   // given value.  If this returns false, then the data is currently not
00149   // compressed and contains different values.
00150   bool CanCompress(T x) const;
00151 
00152   // Force a compress.  Delete the memory and make Begin compressed.
00153   // First is a version that uses the first value.
00154   inline void Compress()
00155   {
00156     if (!IsCompressed())
00157       Compress(*P);
00158   }
00159 
00160   // Here is version that lets the user specify a new value.
00161   void Compress(const T &val);
00162 
00163   // Let the user tell us to uncompress.
00164   // Return quickly if we are already uncompressed.
00165   inline void Uncompress(bool fill_domain = true)
00166   {
00167     if (IsCompressed())
00168       ReallyUncompress(fill_domain);
00169   }
00170 
00171   // Return a reference to the compressed data for debugging.
00172   T &getCompressedData()             { return CompressedData; }
00173   const T &getCompressedData() const { return CompressedData; }
00174 
00175   //
00176   // Overlap cache interface
00177   //
00178 
00179   bool OverlapCacheInitialized() { return overlapCacheInited; }
00180 
00181   void AddToOverlapCache(LField<T, Dim> *newCacheItem)
00182     {
00183       if (overlap.size() == 0) 
00184         overlap.reserve(ToTheDim<Dim>::calc(3)-1);
00185       overlap.push_back(newCacheItem);
00186       overlapCacheInited = true;
00187     }
00188 
00189   typedef typename vector< LField<T, Dim> *>::iterator OverlapIterator;
00190 
00191   OverlapIterator BeginOverlap() { return overlap.begin(); }
00192   OverlapIterator EndOverlap() { return overlap.end(); }
00193 
00194   //
00195   // Swap the pointers between two LFields.
00196   //
00197 
00198   void swapData( LField<T,Dim>& a );
00199 
00200   //
00201   // I/O
00202   //
00203 
00204   // print an LField out
00205   void write(ostream&) const;
00206 
00207 private:
00208   // Global vnode ID number for the associated Vnode (useful with more recent
00209   // FieldLayouts which store a logical "array" of vnodes; user specifies
00210   // numbers of vnodes along each direction). Classes or user codes that use
00211   // LField are responsible for setting and managing the values of this index;
00212   // if unset, it has the value -1. Generally, this parameter value is set on
00213   // construction of the vnode:
00214 
00215   int vnode_m;
00216 
00217   // The actual pointer to the LField data.
00218 
00219   T*             P;
00220 
00221   // What domain in the data is owned by this LField.
00222 
00223   NDIndex<Dim>   Owned;
00224 
00225   // How total domain is actually allocated for thie LField (including guards)
00226 
00227   NDIndex<Dim>   Allocated;
00228 
00229   // An iterator pointing to the first element in the owned domain.
00230 
00231   iterator       Begin;
00232 
00233   // An iterator pointing one past the last element in the owned domain.
00234 
00235   iterator       End;
00236 
00237   // If compressed, put the data here.  If not compressed, this is not used.
00238 
00239   T              CompressedData;
00240 
00241   // The overlap cache, an whether it has been initialized.
00242 
00243   vector< LField<T, Dim> * > overlap;
00244   bool overlapCacheInited;
00245 
00246   // The index of the element to start comparing to the first element
00247   // in a "CanCompress" check.  This is generally set to the index of the
00248   // first element that failed a compression check last time.  There are
00249   // two versions, one for when we're checking using the entire allocated
00250   // domain, and another when we're checking using just the owned domain.
00251 
00252   mutable int allocCompressIndex;
00253   mutable int ownedCompressIndex;
00254 
00255   // A counter for an offset that is used to keep data from always aligning
00256   // at the same point in a memory page.
00257 
00258   long offsetBlocks;
00259 
00260   // Private methods used to implement compression
00261 
00262   bool CanCompressBasedOnPhysicalCells() const;
00263   void ReallyUncompress(bool fill_domain);
00264   void CompressBasedOnPhysicalCells();
00265 
00266   // Actualy allocate storage for the LField data, doing any special
00267   // memory tricks needed for performance.  Sets P pointer to new memory.
00268 
00269   void allocateStorage(int newsize);
00270 
00271   // Actually free the storage used in the LField, if any.  Resets P to zero.
00272 
00273   void deallocateStorage();
00274 
00275   // Disable default constructor and operator=
00276 
00277   LField();
00278   const LField<T,Dim> &operator=(const LField<T,Dim> &);
00279 };
00280 
00281 
00282 template<class T, unsigned Dim>
00283 inline
00284 ostream& operator<<(ostream& out, const LField<T,Dim>& a)
00285 {
00286   TAU_TYPE_STRING(taustr, "ostream (ostream, " + CT(a) + " )" );
00287   TAU_PROFILE("operator<<()", taustr, TAU_FIELD | TAU_IO);
00288   a.write(out);
00289   return out;
00290 }
00291 
00293 
00294 #include "Field/LField.cpp"
00295 
00296 #endif // LFIELD_H
00297 
00298 /***************************************************************************
00299  * $RCSfile: LField.h,v $   $Author: adelmann $
00300  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:26 $
00301  * IPPL_VERSION_ID: $Id: LField.h,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $ 
00302  ***************************************************************************/

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