src/Field/IndexedBareField.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 INDEXED_BARE_FIELD_H
00012 #define INDEXED_BARE_FIELD_H
00013 
00014 // Include files
00015 #include "Field/FieldLoc.h"
00016 #include "Utility/PAssert.h"
00017 #include "PETE/IpplExpressions.h"
00018 
00019 #ifdef IPPL_USE_STANDARD_HEADERS
00020 #include <iostream>
00021 using namespace std;
00022 #else
00023 #include <iostream.h>
00024 #endif
00025 
00026 #include "Field/BareFieldIterator.h"
00027 
00028 
00029 
00030 // forward declarations
00031 class Index;
00032 template<unsigned Dim> class NDIndex;
00033 template<class T, unsigned Dim> class LField;
00034 template<class T, unsigned Dim> class BareField;
00035 template<class T, unsigned Dim, unsigned Brackets> class IndexedBareField;
00036 template<class T, unsigned Dim, unsigned Brackets>
00037 ostream& operator<<(ostream&, const IndexedBareField<T,Dim,Brackets>&);
00038 
00039 
00040 //
00041 // Because of a limitation in the template mechanism on SGI
00042 // we need a tag class to get it to match the Dim parameter
00043 // in the IndexedBareField.
00044 //
00045 template<unsigned D> class DimTag {};
00046 
00047 //----------------------------------------------------------------------
00048 
00049 template<class T, unsigned Dim>
00050 class IndexedBareFieldIterator : public BareField<T,Dim>::iterator
00051 {
00052 public:
00053   enum { Dim_u = Dim };
00054   typedef T return_type;
00055 
00056   // Null ctor for arrays of these things.
00057   IndexedBareFieldIterator()
00058     {
00059     }
00060 
00061   // Construct with a BareField and an NDIndex.
00062   // Point to the beginning of the BareField & record the index.
00063   IndexedBareFieldIterator(BareField<T,Dim>& df, const NDIndex<Dim> &idx)
00064     : BareField<T,Dim>::iterator(df), I(idx)
00065     {
00066       // make sure we're at the start of the PROPER LField (not necessarily
00067       // the first)
00068       beginLField(); 
00069     }
00070 
00071   // Destructor
00072   ~IndexedBareFieldIterator()
00073     {
00074     }
00075 
00076   // Return the subdomain we are indexing into here
00077   const NDIndex<Dim>& getDomain() const
00078     {
00079       return I;
00080     }
00081 
00082   // Some other accsssor functions:
00083   const BareField<T,Dim>& getBareField() const { return *(this->MyBareField); }
00084   BareField<T,Dim>& getBareField()       { return *(this->MyBareField); }
00085 
00086   // Fills the guard cells if necessary.
00087   template<unsigned D1, class T1>
00088   void FillGCIfNecessary(const BareField<T1,D1> &lhs) const
00089   {
00090     // If the dirty flag is set, we need to decide whether we need
00091     // to fill the guard cells. A safe way to do this is to pass
00092     // the domain of the lhs and our domain to 'isStencil', which
00093     // will check to see if the domains are offset, indicating a
00094     // stencil. This doesn't necessarily mean that we *must* fill
00095     // (as in the case where the stencil is fully contained in an
00096     // LField), but filling is the safe thing to do short of a more
00097     // detailed analysis.
00098 
00099     if (this->GetBareField().isDirty())
00100       {
00101         if ( isStencil(lhs.getDomain(), getDomain()) ||
00102              !(lhs.getLayout() == getBareField().getLayout()) )
00103           {
00104             BareField<T,Dim> &bf = 
00105               const_cast<BareField<T,Dim>&>(this->GetBareField());
00106             bf.fillGuardCells();
00107           }
00108       }
00109   }
00110 
00111 
00112   // The LHS tells this guy about a given local domain.
00113   //MWERKS: Moved this member template function definition into here.
00114   //MWERKS template<unsigned int D1>
00115   //MWERKS bool plugBase(const NDIndex<D1>& i);
00116   template<unsigned int D2>
00117   bool
00118   plugBase(const NDIndex<D2>& i)
00119   {
00120     TAU_TYPE_STRING(taustr, "bool (" + CT(*this) + ", " + CT(i) + ", DimTag<D1> )" );
00121     TAU_PROFILE("plugBase()", taustr, TAU_FIELD);
00122     
00123     //  Inform msg("plugBase", INFORM_ALL_NODES);
00124     
00125     // Substitute the index expression from the lhs into this one.
00126     NDIndex<Dim> plugged ( I.plugBase(i) );
00127 
00128     // Try to find a single local array that has all of the rhs.
00129     // Loop over all the local arrays.
00130     typedef typename BareField<T,Dim>::iterator_if BFI;
00131     BFI e = BareFieldIterator<T,Dim>::MyBareField->end_if();
00132     for (BFI lf_i = BareFieldIterator<T,Dim>::MyBareField->begin_if(); lf_i !=  e ;  ++lf_i) {
00133       if ( (*lf_i).second->getAllocated().contains( plugged ) ) {
00134         // Found it.  Make this one current and go.
00135         BareFieldIterator<T,Dim>::CurrentLField = lf_i;
00136         (CompressedBrickIterator<T,Dim>&)(*this) = (*lf_i).second->begin(plugged);
00137         return true;
00138       }
00139     }
00140     // Didn't find it.
00141     return false;
00142   }
00143 
00144   // From a given FieldLoc, set where we're pointing.  Since an
00145   // IndexedBareField iterates over only a subset, we must make sure the
00146   // requested point is within the subset domain.
00147   void SetCurrentLocation(const FieldLoc<Dim>& loc)
00148     {
00149       BareField<T,Dim>::SetCurrentLocation(loc);
00150       if (!this->done()) {
00151         FieldLoc<Dim> checkloc;
00152         GetCurrentLocation(checkloc);
00153         PAssert(I.contains(checkloc.getDomain()));
00154       }
00155     }
00156 
00157   // Increment this iterator.
00158   IndexedBareFieldIterator<T,Dim>& operator++()
00159     {
00160       CompressedBrickIterator<T,Dim>::operator++();
00161       if (*this == (*BareFieldIterator<T,Dim>::CurrentLField).second->end())
00162         general_increment();
00163       return *this;
00164     }
00165 
00166   // Set ourselves up to point to the first item in the current LField
00167   // that we'll be accessing.  Since we're iterating over a subset of
00168   // the domain, we might need to skip over some LFields first.
00169   void beginLField()
00170     {
00171       // get a pointer to the current LField, and ourselves cast as a
00172       // compressed brick iterator.
00173       CompressedBrickIterator<T,Dim> *c=(CompressedBrickIterator<T,Dim>*)this;
00174 
00175       // advance to the first LField that intersects our subdomain
00176       while (!this->done() && ! I.touches((*BareFieldIterator<T,Dim>::CurrentLField).second->getOwned()))
00177         this->nextLField();
00178 
00179       // now that we're at a new LField with some points, set the pointer
00180       // to the first item we'll need.  Set ourselves equal to a
00181       // compressed brick iterator that iterates over the subdomain formed
00182       // from the intersection of the total indexed subdomain and the
00183       // current LField's owned domain.
00184       if (!this->done())
00185         *c = (*BareFieldIterator<T,Dim>::CurrentLField).second->begin(
00186            I.intersect((*BareFieldIterator<T,Dim>::CurrentLField).second->getOwned()));
00187       else
00188         BareFieldIterator<T,Dim>::LFIndex = (-1);
00189     }
00190 
00191 protected:
00192   // User supplied offsets.
00193   NDIndex<Dim> I;                           
00194 
00195   // Increment and go on to the next LField if necessary.
00196   void general_increment()
00197     {
00198       this->nextLField();
00199       beginLField();
00200     }
00201 }; 
00202 
00203 //----------------------------------------------------------------------
00204 
00205 template < class T, unsigned Dim, unsigned Brackets >
00206 class IndexedBareField : public PETE_Expr< IndexedBareField<T,Dim,Brackets> >
00207 {
00208 
00209   friend class IndexedBareField<T,Dim,Brackets-1>;
00210   friend class BareField<T,Dim>;
00211 
00212 public:
00213 
00214   typedef T T_t;
00215   enum { Dim_u = Dim };
00216   typedef IndexedBareFieldIterator<T,Dim> iterator;
00217 
00218   IndexedBareField<T,Dim,Brackets+1> operator[](const Index& idx)
00219   {
00220     CTAssert(Brackets<Dim);
00221     return IndexedBareField<T,Dim,Brackets+1> (A,Indexes,idx);
00222   }
00223 
00224   IndexedBareField<T,Dim,Brackets+1> operator[](int i)
00225   {
00226     CTAssert(Brackets<Dim);
00227     return IndexedBareField<T,Dim,Brackets+1> (A,Indexes,Index(i,i));
00228   }
00229   // Also allow using a single NDIndex instead of N Index objects:
00230   IndexedBareField<T,Dim,Brackets+1> operator[](const NDIndex<Dim>& ndidx)
00231   {
00232     CTAssert(Brackets<Dim);
00233     return IndexedBareField<T,Dim,Brackets+1> (A,Indexes,ndidx);
00234   }
00235 
00236   void operator=(T x)
00237   {
00238     typedef PETE_Scalar<T> S;
00239     assign(*this,x);
00240   }
00241 
00242   IndexedBareField<T,Dim,Brackets>&
00243   operator=(const IndexedBareField<T,Dim,Brackets>& x)
00244   {
00245     CTAssert(Dim==Brackets);
00246     assign(*this,x);
00247     return *this;
00248   }
00249 
00250   template<class X, unsigned Dim1, unsigned Brackets1>
00251   IndexedBareField<T,Dim,Brackets>&
00252   operator=(const IndexedBareField<X,Dim1,Brackets1>& x)
00253   {
00254     CTAssert(Dim1==Brackets1);
00255     assign(*this,x);
00256     return *this;
00257   }
00258 
00259   IndexedBareField<T,Dim,Brackets>&
00260   operator=(const Index& x)
00261   {
00262     assign(*this,x);
00263     return *this;
00264   }
00265 
00266   template<class B>
00267   IndexedBareField<T,Dim,Brackets>&
00268   operator=(const PETE_Expr<B>& x)
00269   {
00270     assign(*this,x);
00271     return *this;
00272   }
00273 
00274   const NDIndex<Dim>& getDomain() const { return Indexes; }
00275         BareField<T,Dim>& getBareField()       { return A; }
00276   const BareField<T,Dim>& getBareField() const { return A; }
00277 
00278   // Pass operator() down to each element of type T.
00279   // Could also build versions with 2 or more arguments...
00280   // Without member templates we are restricted to passing an integer down.
00281   PETE_TUTree< OpParens<int>, iterator >
00282   operator()(int arg)
00283   {
00284     CTAssert(Dim==Brackets);
00285     typedef PETE_TUTree< OpParens<int> , iterator > Elem_t;
00286     return Elem_t(arg,begin());
00287   }
00288   PETE_TUTree< OpParens< pair<int,int> >, iterator >
00289   operator()(int a1, int a2)
00290   {
00291     CTAssert(Dim==Brackets);
00292     typedef PETE_TUTree< OpParens< pair<int,int> > , iterator > Elem_t;
00293     return Elem_t(pair<int,int>(a1,a2),begin());
00294   }
00295 
00296   // Return a single value.
00297   // operator T() { T r; getsingle(r); return r; }
00298   //T get() { T r ; getsingle(r); return r; }
00299   T get();
00300 
00301   // Return the beginning and end iterators for this class.
00302   iterator begin() const { return iterator( A, Indexes ); }
00303   iterator end() const   { return iterator(); }
00304 
00305   // Print out the values for this object to the given output stream.
00306   void write(ostream&);
00307 
00308   // PETE interface
00309   enum { IsExpr = 0 };
00310   typedef iterator PETE_Expr_t;
00311   iterator MakeExpression() const { return begin(); }
00312 
00313 protected: 
00314   BareField<T,Dim> &A;
00315   NDIndex<Brackets> Indexes;
00316 
00317   // Make the constructors private so that only BareField and IndexedBareField
00318   // can construct them.
00319   IndexedBareField(BareField<T,Dim> &a, const Index& idx)
00320     : A(a), Indexes(idx) {}
00321   IndexedBareField(BareField<T,Dim> &a, int i)
00322     : A(a), Indexes(Index(i,i)) {}
00323   IndexedBareField(BareField<T,Dim> &a,const NDIndex<Brackets-1>& idx, const Index& i)
00324     : A(a), Indexes(idx,i) {}
00325 
00326   // Also allow using a single NDIndex instead of N Index objects:
00327   IndexedBareField(BareField<T,Dim> &a, const NDIndex<Dim>& ndidx)
00328     : A(a), Indexes(ndidx) {}
00329 
00330   // read a single value from the array.
00331   void getsingle(T&);
00332 };
00333 
00334 
00335 template < class T, unsigned Dim, unsigned Brackets >
00336 inline
00337 ostream& operator<<(ostream& out, const IndexedBareField<T,Dim,Brackets>& i) {
00338   TAU_TYPE_STRING(taustr, "ostream (ostream, " + CT(i) + " )" );
00339   TAU_PROFILE("operator<<()", taustr, TAU_FIELD | TAU_IO);
00340   IndexedBareField<T,Dim,Brackets>& nci =
00341     const_cast<IndexedBareField<T,Dim,Brackets>&>(i);
00342   nci.write(out);
00343   return out;
00344 }
00345 
00347 
00348 #include "Field/IndexedBareField.cpp"
00349 
00350 #endif // INDEXED_BARE_FIELD_H
00351 
00352 /***************************************************************************
00353  * $RCSfile: IndexedBareField.h,v $   $Author: adelmann $
00354  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:26 $
00355  * IPPL_VERSION_ID: $Id: IndexedBareField.h,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $ 
00356  ***************************************************************************/

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