src/Field/BareField.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_H
00012 #define BARE_FIELD_H
00013 
00014 /***************************************************************************
00015  *
00016  * This is the user visible BareField of type T.
00017  * It doesn't even really do expression evaluation; that is
00018  * handled with the templates in Expressions.h
00019  *
00020  ***************************************************************************/
00021 
00022 // include files
00023 #include "Field/LField.h"
00024 #include "Field/IndexedBareField.h"
00025 #include "Field/GuardCellSizes.h"
00026 #include "Field/FieldLoc.h"
00027 #include "Field/BareFieldIterator.h"
00028 #include "FieldLayout/FieldLayout.h"
00029 #include "FieldLayout/FieldLayoutUser.h"
00030 #include "PETE/IpplExpressions.h"
00031 #include "Index/SIndex.h"
00032 #include "SubField/SubBareField.h"
00033 #include "Utility/IpplInfo.h"
00034 #include "Utility/PAssert.h"
00035 #include "Utility/Unique.h"
00036 #include "Utility/my_auto_ptr.h"
00037 #include "Utility/vmap.h"
00038 
00039 #ifdef IPPL_USE_STANDARD_HEADERS
00040 #include <iostream>
00041 using namespace std;
00042 #else
00043 #include <iostream.h>
00044 #endif
00045 
00046 #include <stdlib.h>
00047 
00048 // forward declarations
00049 class Index;
00050 template<unsigned Dim> class NDIndex;
00051 template<unsigned Dim> class FieldLayout;
00052 template<class T, unsigned Dim> class LField;
00053 template<class T, unsigned Dim> class BareField;
00054 template<class T, unsigned Dim>
00055 ostream& operator<<(ostream&, const BareField<T,Dim>&);
00056 
00057 // class definition
00058 template<class T,  unsigned Dim>
00059 class BareField : public FieldLayoutUser,
00060                   public PETE_Expr< BareField<T,Dim> >
00061 {
00062 
00063 public: 
00064   // Some externally visible typedefs and enums
00065   typedef T T_t;
00066   typedef FieldLayout<Dim> Layout_t;
00067   typedef LField<T,Dim> LField_t;
00068   enum { Dim_u = Dim };
00069 
00070 public:
00071   // A default constructor, which should be used only if the user calls the
00072   // 'initialize' function before doing anything else.  There are no special
00073   // checks in the rest of the BareField methods to check that the field has
00074   // been properly initialized.
00075   BareField();
00076 
00077   // Copy ctor.  Deep copy.
00078   BareField(const BareField<T,Dim>&);
00079 
00080   // Create a new BareField with a given layout and optional guard cells.
00081   BareField(Layout_t &);
00082   BareField(Layout_t &, const GuardCellSizes<Dim>&);
00083 
00084   // Destroy the BareField.
00085   ~BareField();
00086 
00087   // Initialize the field, if it was constructed from the default constructor.
00088   // This should NOT be called if the field was constructed by providing
00089   // a FieldLayout.
00090   void initialize(Layout_t &);
00091   void initialize(Layout_t &, const GuardCellSizes<Dim>&);
00092 
00093   // Some typedefs to make access to the maps a bit simpler.
00094   typedef vmap< typename Unique::type, my_auto_ptr< LField<T,Dim> > > 
00095     ac_id_larray;
00096   typedef typename ac_id_larray::iterator iterator_if;
00097   typedef typename ac_id_larray::const_iterator const_iterator_if;
00098   typedef typename LField<T,Dim>::iterator LFI;
00099 
00100   // An iterator over the elements of the BareField.
00101   typedef BareFieldIterator<T,Dim> iterator;
00102 
00103   // Let the user iterate over the larrays.
00104   iterator_if begin_if() { return Locals_ac.begin(); }
00105   iterator_if end_if()   { return Locals_ac.end(); }
00106   const_iterator_if begin_if() const { return Locals_ac.begin(); }
00107   const_iterator_if end_if()   const { return Locals_ac.end(); }
00108   typename ac_id_larray::size_type size_if() const { return Locals_ac.size(); }
00109 
00110   // If you make any modifications using an iterator, you must call this.
00111   virtual void fillGuardCells(bool reallyFill = true) const;
00112 
00113   // For use before scatters into guard cells
00114   void setGuardCells(const T&) const;
00115 
00116   // For use after scatters into guard cells
00117   void accumGuardCells();
00118 
00119   // Dirty flag maintenance.
00120   bool isDirty() const { return dirty_m; }
00121   void setDirtyFlag() { if (IpplInfo::deferGuardCellFills) dirty_m = true; }
00122   void clearDirtyFlag() { dirty_m = false; }
00123 
00124   // If the dirty flag is not set, fill guard cells; otherwise,
00125   // don't fill guard cells, but do call boundary conditions.
00126   void fillGuardCellsIfNotDirty() const
00127   {
00128     if (!isDirty())
00129       fillGuardCells();
00130     else
00131       fillGuardCells(false);
00132   }
00133 
00134   // Access to the layout.
00135   Layout_t &getLayout() const
00136   {
00137     PAssert(Layout != 0);
00138     return *Layout;
00139   }
00140 
00141   // When we apply a bracket it converts the type
00142   // to IndexedBareField so that we can check at compile time
00143   // that we have the right number of indexes and brackets.
00144   IndexedBareField<T,Dim,1>   operator[](const Index& idx);
00145   IndexedBareField<T,Dim,1>   operator[](int i);
00146   IndexedBareField<T,Dim,Dim> operator[](const NDIndex<Dim>& nidx);
00147   SubBareField<T,Dim,SIndex<Dim> >  operator[](const SIndex<Dim>&);
00148 
00149   // Boundary condition handling.
00150   const GuardCellSizes<Dim>& getGC() const { return Gc; }
00151   const GuardCellSizes<Dim>& getGuardCellSizes() const { return Gc; }
00152   unsigned leftGuard(unsigned d) const   { return getGC().left(d); }
00153   unsigned rightGuard(unsigned d) const  { return getGC().right(d); }
00154 
00155   const Index& getIndex(unsigned d) const {return getLayout().getDomain()[d];}
00156   const NDIndex<Dim>& getDomain() const { return getLayout().getDomain(); }
00157 
00158   // Assignment from a constant.
00159   const BareField<T,Dim>& operator=(T x)
00160   {
00161     assign(*this,x);
00162     return *this;
00163   }
00164 
00165   // Assign another array.
00166   const BareField<T,Dim>&
00167   operator=(const BareField<T,Dim>& x)
00168   {
00169     assign(*this,x);
00170     return *this;
00171   }
00172 
00173   template<class X>
00174   const BareField<T,Dim>&
00175   operator=(const BareField<X,Dim>& x)
00176   {
00177     assign(*this,x);
00178     return *this;
00179   }
00180 
00181   // If we have member templates available, assign a generic expression.
00182   template<class B>
00183   const BareField<T,Dim>&
00184   operator=(const PETE_Expr<B>& x)
00185   {
00186     assign(*this,x);
00187     return *this;
00188   }
00189 
00190   //
00191   // Methods to deal with compression
00192   //
00193 
00194   // Tell whether BareField may be compressed or not
00195   bool compressible() const
00196   {
00197     return compressible_m;
00198   }
00199 
00200   // Report what fraction of the elements are compressed.
00201   // Completely compressed is 1.0, completely uncompressed is 0.0.
00202   double CompressedFraction() const;
00203 
00204   // Tell a BareField to compress/uncompress itself.
00205 
00206   void Compress() const;
00207   void Uncompress() const;
00208 
00209   // dictate whether BareField may be compressed or not.  This will set
00210   // a flag, and set the state to be consistent with the flag.
00211   void setCompression(bool compress)
00212   {
00213     if (!Ippl::noFieldCompression) {
00214       compressible_m = compress;
00215       if (compress)
00216         Compress();
00217       else
00218         Uncompress();
00219     }
00220   }
00221 
00222   //
00223   // virtual functions for FieldLayoutUser's (and other UserList users)
00224   //
00225 
00226   // Repartition onto a new layout
00227   virtual void Repartition(UserList *);
00228 
00229   // Tell this object that an object is being deleted
00230   virtual void notifyUserOfDelete(UserList *);
00231 
00232   //
00233   // Scalar code interface
00234   //
00235 
00236   // Let the user iterate over each element.  Return a begin iterator
00237   // for the whole BareField.
00238   iterator begin() const
00239   {
00240     return iterator(const_cast<BareField<T,Dim> &>(*this));
00241   }
00242 
00243   // Let the user iterate over each element.  Return an end iterator
00244   // for the whole BareField.
00245   iterator end() const
00246   {
00247     return iterator();
00248   }
00249 
00250   // Let the user iterate over each element, but specify where they should
00251   // start (other than the beginning).  We don't need an end, since this just
00252   // affect where we start, not how we traverse the data.
00253   iterator beginLoc(const FieldLoc<Dim> &loc) const
00254   {
00255     return iterator(loc, const_cast<BareField<T,Dim> &>(*this));
00256   }
00257 
00258   // Prepare this BareField for some future scalar code use where the
00259   // BareField may be modified by BareFieldIterators.  This means
00260   // to make sure that the field is properly uncompressed and guard cells
00261   // are filled.  The
00262   // one argument allows the user to explicitly avoid filling guard
00263   // cells if they do not need this.
00264   // If tryfill is true, this routine must be called in SPMD-fashion.  If
00265   // it is false, it can be called on a per-node basis.
00266   void prepareForScalarCode(bool tryfill = true)
00267   {
00268     // Turn off compression for now
00269     setCompression(false);
00270 
00271     // Fill the guard cells if they are dirty
00272     if (tryfill && isDirty())
00273       fillGuardCells(true);
00274 
00275     // Increment the counter for scalar code starts
00276     INCIPPLSTAT(incBeginScalarCodes);
00277   }
00278 
00279   // Finish up after a scalar code section.  This means go back to
00280   // a compressed state if possible, and, if the user says so, indicate
00281   // that things have been modified so the dirty flag must be set.
00282   // If modified is true, this routine must be called in SPMD-fashion.  If
00283   // it is false, it can be called on a per-node basis.
00284   void finishScalarCode(bool modified = true)
00285   {
00286     // If the user says the field has been modified, either we have
00287     // to set the dirty flag or go and actually fill GC's (if we are not
00288     // deferring GC fills, we need to update things now).  So, we try to
00289     // set the dirty flag; if it gets set, then fillGuardCellsIfNotDirty
00290     // will just leave it set, if it does not get set, then that routine
00291     // will go and actually do a GC fill.
00292     if (modified)
00293       {
00294         setDirtyFlag();
00295         fillGuardCellsIfNotDirty();
00296       }
00297 
00298     // Turn compression back on, and try to compress if possible
00299     setCompression(true);
00300 
00301     // Increment the counter for scalar code stops
00302     INCIPPLSTAT(incEndScalarCodes);
00303   }
00304 
00305   //
00306   // Single-element access
00307   //
00308 
00309   // Get a ref to a single element of the Field; if it is not local to our
00310   // processor, print an error and exit.  This allows the user to provide
00311   // different index values on each node, instead of using the same element
00312   // and broadcasting to all nodes.
00313   T& localElement(const NDIndex<Dim>&) const;
00314 
00315   // get a single value and return it in the given storage.  Whichever
00316   // node owns the value must broadcast it to the other nodes.
00317   void getsingle(const NDIndex<Dim>&, T&) const;
00318 
00319   //
00320   // I/O routines for a BareField
00321   // 
00322 
00323   void write(ostream&);
00324   void write(char*) const;
00325   void writeb(char*) const;
00326 
00327   //
00328   // PETE interface.
00329   //
00330 
00331   enum { IsExpr = 0 };
00332   typedef iterator PETE_Expr_t;
00333   iterator MakeExpression() const { return begin(); }
00334 
00335 protected:
00336   // The container of local arrays.
00337   ac_id_larray Locals_ac;
00338 
00339 private:
00340   friend class BareFieldIterator<T,Dim>;
00341 
00342   // Setup allocates all the LFields.  The various ctors call this.
00343   void setup();
00344 
00345   // How the local arrays are laid out.
00346   Layout_t *Layout;
00347 
00348   // The specification of how many guard cells this array needs.
00349   GuardCellSizes<Dim> Gc;
00350 
00351   // A version of get_single that uses a slower but more
00352   // robust method.  The externally visible get_single
00353   // calls this when it determines it needs it.
00354   void getsingle_bc(const NDIndex<Dim>&, T&) const;
00355 
00356   // Dirty flag. Tells whether or not we need to fill guard cells.
00357   bool dirty_m;
00358 
00359   // compression flags
00360   bool compressible_m;          // are we allowed to compress this BareField?
00361 };
00362 
00364 
00365 //
00366 // Construct a BareField from nothing ... default case.
00367 //
00368 
00369 template< class T, unsigned Dim >
00370 inline
00371 BareField<T,Dim>::
00372 BareField()
00373 : Layout(0),                     // No layout yet.
00374   Gc( GuardCellSizes<Dim>(0U) ), // No guard cells.
00375   compressible_m(!Ippl::noFieldCompression)
00376 {
00377 }
00378 
00379 
00380 //
00381 // Construct a BareField from a FieldLayout.
00382 //
00383 
00384 template< class T, unsigned Dim >
00385 inline
00386 BareField<T,Dim>::
00387 BareField(Layout_t & l)
00388 : Layout(&l),                    // Just record the layout.
00389   Gc( GuardCellSizes<Dim>(0U) ), // No guard cells.
00390   compressible_m(!Ippl::noFieldCompression)
00391 {
00392   setup();                      // Do the common setup chores.
00393 }
00394 
00395 
00396 //
00397 // Construct a BareField from a FieldLayout and guard cell sizes.
00398 //
00399 
00400 template< class T, unsigned Dim >
00401 inline
00402 BareField<T,Dim>::
00403 BareField(Layout_t & l, const GuardCellSizes<Dim>& g)
00404 : Layout(&l),                   // Just record the layout.
00405   Gc(g),                        // Just record guard cells.
00406   compressible_m(!Ippl::noFieldCompression)
00407 {
00408   setup();                      // Do the common setup chores.
00409 }
00410 
00411 
00413 
00414 template< class T, unsigned Dim >
00415 inline IndexedBareField<T,Dim,1> 
00416 BareField<T,Dim>::operator[](const Index& idx)
00417 {
00418   return IndexedBareField<T,Dim,1>(*this,idx);
00419 }
00420 
00421 template< class T, unsigned Dim >
00422 inline IndexedBareField<T,Dim,1>
00423 BareField<T,Dim>::operator[](int i) 
00424 {
00425   return IndexedBareField<T,Dim,1>(*this,i);
00426 }
00427 
00428 template< class T, unsigned Dim >
00429 inline IndexedBareField<T,Dim,Dim> 
00430 BareField<T,Dim>::operator[](const NDIndex<Dim>& nidx)
00431 {
00432   return IndexedBareField<T,Dim,Dim>(*this,nidx);
00433 }
00434 
00435 template< class T, unsigned Dim >
00436 inline SubBareField<T,Dim,SIndex<Dim> >
00437 BareField<T,Dim>::operator[](const SIndex<Dim>& s)
00438 {
00439   return SubBareField<T,Dim,SIndex<Dim> >(*this, s);
00440 }
00441 
00442 template< class T, unsigned Dim >
00443 inline
00444 ostream& operator<<(ostream& out, const BareField<T,Dim>& a)
00445 {
00446   TAU_TYPE_STRING(taustr, "ostream (ostream, " + CT(a) + " )" );
00447   TAU_PROFILE("operator<<()", taustr, TAU_FIELD | TAU_IO);
00448 
00449   BareField<T,Dim>& nca = const_cast<BareField<T,Dim>&>(a);
00450   nca.write(out);
00451   return out;
00452 }
00453 
00454 
00456 
00457 #include "Field/BareField.cpp"
00458 
00459 #endif // BARE_FIELD_H
00460 
00461 /***************************************************************************
00462  * $RCSfile: BareField.h,v $   $Author: adelmann $
00463  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:26 $
00464  * IPPL_VERSION_ID: $Id: BareField.h,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $ 
00465  ***************************************************************************/

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