src/FieldLayout/FieldLayout.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 FIELD_LAYOUT_H
00012 #define FIELD_LAYOUT_H
00013 
00014 // FieldLayout describes how a given index space (represented by an NDIndex
00015 // object) is partitioned into vnodes.  It performs the initial partitioning,
00016 // and stores a list of local and remote vnodes. The user may request that a
00017 // particular dimension not be partitioned by flagging that axis as 'SERIAL'
00018 // (instead of 'PARALLEL').
00019 
00020 // For a power-of-two number of vnodes, using the basic constructor, the
00021 // partitioning is done using a recursive bisection method which makes cuts
00022 // along whole hyperplanes in the global index space. For non-power-of-two
00023 // vnodes with the basic constructor, the cuts do not necessarily go all the
00024 // way across all the elements in all directions. There is also a constructor
00025 // with extra arguments specifying the numbers of vnodes along each direction;
00026 // this one makes the specified number of cuts to divide up the given
00027 // directions. This last constructor obviously only works for numbers of vnodes
00028 // expressible as products of N numbers (in ND), though 1 is an allowable
00029 // number so it really allows any number of vnodes.
00030 
00031 // include files
00032 #include "FieldLayout/FieldLayoutUser.h"
00033 #include "FieldLayout/Vnode.h"
00034 #include "DomainMap/DomainMap.h"
00035 #include "Index/NDIndex.h"
00036 #include "Field/GuardCellSizes.h"
00037 #include "Utility/IpplInfo.h"
00038 #include "Utility/UserList.h"
00039 #include "Utility/vmap.h"
00040 #include "Utility/Unique.h"
00041 #include "Utility/my_auto_ptr.h"
00042 #include "Utility/RefCounted.h"
00043 
00044 // #include "source/grid/brick.h"
00045 
00046 
00047 #ifdef IPPL_USE_STANDARD_HEADERS
00048 #include <iostream>
00049 using namespace std;
00050 #else
00051 #include <iostream.h>
00052 #endif
00053 
00054 // forward declarations
00055 template <unsigned Dim> class FieldLayout;
00056 template <unsigned Dim>
00057 ostream& operator<<(ostream&, const FieldLayout<Dim>&);
00058 
00059 // enumeration used to select serial or parallel axes
00060 enum e_dim_tag { SERIAL=0, PARALLEL=1 } ;
00061 
00062 
00063 // class definition ... inheritance is private, so that we hide the
00064 // UserList checkin routines and instead replace them with our own
00065 template<unsigned Dim>
00066 class FieldLayout : private UserList
00067 {
00068 
00069 public:
00070   // Typedefs for containers.
00071   typedef vmap<Unique::type,my_auto_ptr<Vnode<Dim> > > ac_id_vnodes;
00072   typedef DomainMap<NDIndex<Dim>,RefCountedP< Vnode<Dim> >,
00073                     Touches<Dim>,Contains<Dim>,Split<Dim> > ac_domain_vnodes;
00074   typedef vmap<GuardCellSizes<Dim>,my_auto_ptr<ac_domain_vnodes> >
00075           ac_gc_domain_vnodes;
00076 
00077   // Typedefs for iterators.
00078   typedef typename ac_id_vnodes::iterator           iterator_iv;
00079   typedef typename ac_id_vnodes::const_iterator     const_iterator_iv;
00080   typedef typename ac_domain_vnodes::iterator       iterator_dv;
00081   typedef typename ac_domain_vnodes::touch_iterator touch_iterator_dv;
00082   typedef pair<touch_iterator_dv,touch_iterator_dv> touch_range_dv;
00083   typedef typename ac_gc_domain_vnodes::iterator    iterator_gdv;
00084   typedef iterator_user                             iterator_if;
00085   typedef size_type_user                            size_type_if;
00086 
00087 private:
00088   // utility to return a zero-guard cell structure.
00089   static GuardCellSizes<Dim> gc0() { return GuardCellSizes<Dim>(0U); }
00090 
00091 public:
00092   //
00093   // constructors and destructors
00094   //
00095 
00096   // Default constructor, which should only be used if you are going to
00097   // call 'initialize' soon after (before using in any context)
00098   FieldLayout();
00099 
00100   // Constructor which reads in FieldLayout data from a file.  If the
00101   // file contains data for an equal number of nodes as we are running on,
00102   // then that vnode -> pnode mapping will be used.  If the file does not
00103   // contain info for the same number of pnodes, the vnodes will be
00104   // distributed in some other manner.
00105   FieldLayout(const char *filename);
00106 
00107   // Constructors for 1 ... 6 dimensions
00108   // These specify only a total number of vnodes, allowing the constructor
00109   // complete control on how to do the vnode partitioning of the index space:
00110   FieldLayout(const Index& i1,
00111               e_dim_tag p1=PARALLEL, int vnodes=-1);
00112   FieldLayout(const Index& i1, const Index& i2,
00113               e_dim_tag p1=PARALLEL, e_dim_tag p2=PARALLEL, int vnodes=-1);
00114   FieldLayout(const Index& i1, const Index& i2, const Index& i3,
00115               e_dim_tag p1=PARALLEL, e_dim_tag p2=PARALLEL,
00116               e_dim_tag p3=PARALLEL, int vnodes=-1);
00117   FieldLayout(const Index& i1, const Index& i2, const Index& i3,
00118               const Index& i4,
00119               e_dim_tag p1=PARALLEL, e_dim_tag p2=PARALLEL,
00120               e_dim_tag p3=PARALLEL, e_dim_tag p4=PARALLEL,
00121               int vnodes=-1);
00122   FieldLayout(const Index& i1, const Index& i2, const Index& i3,
00123               const Index& i4, const Index& i5,
00124               e_dim_tag p1=PARALLEL, e_dim_tag p2=PARALLEL,
00125               e_dim_tag p3=PARALLEL, e_dim_tag p4=PARALLEL,
00126               e_dim_tag p5=PARALLEL,
00127               int vnodes=-1);
00128   FieldLayout(const Index& i1, const Index& i2, const Index& i3,
00129               const Index& i4, const Index& i5, const Index& i6,
00130               e_dim_tag p1=PARALLEL, e_dim_tag p2=PARALLEL,
00131               e_dim_tag p3=PARALLEL, e_dim_tag p4=PARALLEL,
00132               e_dim_tag p5=PARALLEL, e_dim_tag p6=PARALLEL,
00133               int vnodes=-1);
00134 
00135   // These specify both the total number of vnodes and the numbers of vnodes
00136   // along each dimension for the partitioning of the index space. Obviously
00137   // this restricts the number of vnodes to be a product of the numbers along
00138   // each dimension (the constructor implementation checks this):
00139   FieldLayout(const Index& i1,
00140               e_dim_tag p1,
00141               unsigned vnodes1,
00142               bool recurse=false,
00143               int vnodes=-1);
00144   FieldLayout(const Index& i1, const Index& i2,
00145               e_dim_tag p1, e_dim_tag p2,
00146               unsigned vnodes1, unsigned vnodes2,
00147               bool recurse=false,int vnodes=-1);
00148   FieldLayout(const Index& i1, const Index& i2, const Index& i3,
00149               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00150               unsigned vnodes1, unsigned vnodes2, unsigned vnodes3,
00151               bool recurse=false, int vnodes=-1);
00152   FieldLayout(const Index& i1, const Index& i2, const Index& i3,
00153               const Index& i4,
00154               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3, 
00155               e_dim_tag p4,
00156               unsigned vnodes1, unsigned vnodes2, unsigned vnodes3,
00157               unsigned vnodes4,
00158               bool recurse=false, int vnodes=-1);
00159   FieldLayout(const Index& i1, const Index& i2, const Index& i3,
00160               const Index& i4, const Index& i5,
00161               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3, 
00162               e_dim_tag p4, e_dim_tag p5,
00163               unsigned vnodes1, unsigned vnodes2, unsigned vnodes3,
00164               unsigned vnodes4, unsigned vnodes5,
00165               bool recurse=false, int vnodes=-1);
00166   FieldLayout(const Index& i1, const Index& i2, const Index& i3,
00167               const Index& i4, const Index& i5, const Index& i6,
00168               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3, 
00169               e_dim_tag p4, e_dim_tag p5, e_dim_tag p6,
00170               unsigned vnodes1, unsigned vnodes2, unsigned vnodes3,
00171               unsigned vnodes4, unsigned vnodes5, unsigned vnodes6,
00172               bool recurse=false, int vnodes=-1);
00173 
00174   // Next we have one for arbitrary dimension.
00175   // This one specifies only a total number of vnodes, allowing the constructor
00176   // complete control on how to do the vnode partitioning of the index space:
00177   FieldLayout(const NDIndex<Dim>& domain, e_dim_tag *p=0, int vnodes=-1) {
00178     initialize(domain,p,vnodes);
00179   }
00180 
00181   // This one specifies both the total number of vnodes and the numbers of
00182   // vnodes along each dimension for the partitioning of the index
00183   // space. Obviously this restricts the number of vnodes to be a product of
00184   // the numbers along each dimension (the constructor implementation checks
00185   // this):
00186   //
00187   // The last argument is a bool for the algorithm to use for assigning vnodes
00188   // to processors.  If it is false, hand the vnodes to the processors in a
00189   // very simple but probably inefficient manner.  If it is true, use a binary
00190   // recursive algorithm. This will usually be more efficient because it will
00191   // generate less communication, but it will sometimes fail, particularly
00192   // near the case of one vnode per processor. Because this can fail, it is
00193   // not the default. This algorithm should only be used when you have 4 or
00194   // more vnodes per processor.
00195 
00196   FieldLayout(const NDIndex<Dim>& domain, e_dim_tag *p, 
00197               unsigned* vnodesPerDirection, 
00198               bool recurse=false, int vnodes=-1 ) {
00199     initialize(domain,p,vnodesPerDirection,recurse,vnodes);
00200   }
00201 
00202   // Build a FieldLayout given the whole domain and
00203   // begin and end iterators for the set of domains for the local Vnodes.
00204   // It does a collective computation to find the remote Vnodes.
00205   FieldLayout(const NDIndex<Dim>& Domain,
00206               const NDIndex<Dim>* begin, const NDIndex<Dim>* end);
00207 
00208   // Build a FieldLayout given the whole domain and
00209   // begin and end iterators for the set of Vnodes for the local Vnodes.
00210   // It does a collective computation to find the remote Vnodes.
00211   // This differs from the previous ctor in that it allows preservation of
00212   // global Vnode integer ID numbers associated with the input Vnodes. --tjw
00213   FieldLayout(const NDIndex<Dim>& Domain,
00214               const Vnode<Dim>* begin, const Vnode<Dim>* end);
00215 
00216   // Constructor that takes a whole domain, and a pair of iterators over
00217   // a list of NDIndex's and nodes so that the user specifies the entire
00218   // decomposition.  No communication is done
00219   // so these lists must match on all nodes.  A bit of error checking
00220   // is done for overlapping blocks and illegal nodes, but not exhaustive
00221   // error checking.
00222   FieldLayout(const NDIndex<Dim>& Domain,
00223               const NDIndex<Dim>* dombegin, const NDIndex<Dim>* domend,
00224               const int *nbegin, const int *nend);
00225 
00226   // Destructor: Everything deletes itself automatically ... the base
00227   // class destructors inform all the FieldLayoutUser's we're going away.
00228   virtual ~FieldLayout();
00229 
00230   // Initialization functions, only to be called by the user of FieldLayout
00231   // objects when the FieldLayout was created using the default constructor;
00232   // otherwise these are only called internally by the various non-default
00233   // FieldLayout constructors:
00234 
00235   // These specify only a total number of vnodes, allowing the constructor
00236   // complete control on how to do the vnode partitioning of the index space:
00237   void initialize(const Index& i1,
00238                   e_dim_tag p1=PARALLEL, int vnodes=-1);
00239   void initialize(const Index& i1, const Index& i2,
00240                   e_dim_tag p1=PARALLEL, e_dim_tag p2=PARALLEL, int vnodes=-1);
00241   void initialize(const Index& i1, const Index& i2, const Index& i3,
00242                   e_dim_tag p1=PARALLEL, e_dim_tag p2=PARALLEL,
00243                   e_dim_tag p3=PARALLEL, int vnodes=-1);
00244   void initialize(const Index& i1, const Index& i2, const Index& i3,
00245                   const Index& i4,
00246                   e_dim_tag p1=PARALLEL, e_dim_tag p2=PARALLEL,
00247                   e_dim_tag p3=PARALLEL, e_dim_tag p4=PARALLEL,
00248                   int vnodes=-1);
00249   void initialize(const Index& i1, const Index& i2, const Index& i3,
00250                   const Index& i4, const Index& i5,
00251                   e_dim_tag p1=PARALLEL, e_dim_tag p2=PARALLEL,
00252                   e_dim_tag p3=PARALLEL, e_dim_tag p4=PARALLEL,
00253                   e_dim_tag p5=PARALLEL,
00254                   int vnodes=-1);
00255   void initialize(const Index& i1, const Index& i2, const Index& i3,
00256                   const Index& i4, const Index& i5, const Index& i6,
00257                   e_dim_tag p1=PARALLEL, e_dim_tag p2=PARALLEL,
00258                   e_dim_tag p3=PARALLEL, e_dim_tag p4=PARALLEL,
00259                   e_dim_tag p5=PARALLEL, e_dim_tag p6=PARALLEL,
00260                   int vnodes=-1);
00261   void initialize(const NDIndex<Dim>& domain, e_dim_tag *p=0, int vnodes=-1);
00262 
00263   // These specify both the total number of vnodes and the numbers of vnodes
00264   // along each dimension for the partitioning of the index space. Obviously
00265   // this restricts the number of vnodes to be a product of the numbers along
00266   // each dimension (the constructor implementation checks this):
00267   void initialize(const Index& i1,
00268                   e_dim_tag p1, 
00269                   unsigned vnodes1, 
00270                   bool recurse=false, int vnodes=-1);
00271   void initialize(const Index& i1, const Index& i2,
00272                   e_dim_tag p1, e_dim_tag p2, 
00273                   unsigned vnodes1, unsigned vnodes2,
00274                   bool recurse=false, int vnodes=-1);
00275   void initialize(const Index& i1, const Index& i2, const Index& i3,
00276                   e_dim_tag p1, e_dim_tag p2, e_dim_tag p3, 
00277                   unsigned vnodes1, unsigned vnodes2, unsigned vnodes3,
00278                   bool recurse=false, int vnodes=-1);
00279   void initialize(const Index& i1, const Index& i2, const Index& i3,
00280                   const Index& i4,
00281                   e_dim_tag p1, e_dim_tag p2, e_dim_tag p3, 
00282                   e_dim_tag p4,
00283                   unsigned vnodes1, unsigned vnodes2, unsigned vnodes3,
00284                   unsigned vnodes4,
00285                   bool recurse=false, int vnodes=-1);
00286   void initialize(const Index& i1, const Index& i2, const Index& i3,
00287                   const Index& i4, const Index& i5,
00288                   e_dim_tag p1, e_dim_tag p2, e_dim_tag p3, 
00289                   e_dim_tag p4, e_dim_tag p5,
00290                   unsigned vnodes1, unsigned vnodes2, unsigned vnodes3,
00291                   unsigned vnodes4, unsigned vnodes5,
00292                   bool recurse=false, int vnodes=-1);
00293   void initialize(const Index& i1, const Index& i2, const Index& i3,
00294                   const Index& i4, const Index& i5, const Index& i6,
00295                   e_dim_tag p1, e_dim_tag p2, e_dim_tag p3, 
00296                   e_dim_tag p4, e_dim_tag p5, e_dim_tag p6,
00297                   unsigned vnodes1, unsigned vnodes2, unsigned vnodes3,
00298                   unsigned vnodes4, unsigned vnodes5, unsigned vnodes6,
00299                   bool recurse=false, int vnodes=-1);
00300   void initialize(const NDIndex<Dim>& domain, e_dim_tag *p, 
00301                   unsigned* vnodesPerDirection, 
00302                   bool recurse=false, int vnodes=-1);
00303 
00304   // Initialize that takes a whole domain, and a pair of iterators over
00305   // a list of NDIndex's and nodes so that the user specifies the entire
00306   // decomposition.  No communication is done
00307   // so these lists must match on all nodes.  A bit of error checking
00308   // is done for overlapping blocks and illegal nodes, but not exhaustive
00309   // error checking.
00310   void initialize(const NDIndex<Dim>& Domain,
00311                   const NDIndex<Dim>* dombegin, const NDIndex<Dim>* domend,
00312                   const int *nbegin, const int *nend);
00313 
00314   //
00315   // FieldLayout operations and information
00316   //
00317 
00318   // Let the user set the local vnodes.
00319   // this does everything necessary to realign all the fields
00320   // associated with this FieldLayout!
00321   // It inputs begin and end iterators for the local vnodes.
00322   void Repartition(const NDIndex<Dim>*, const NDIndex<Dim>*);
00323   void Repartition(const NDIndex<Dim>& domain) { Repartition(&domain,(&domain)+1); }
00324 
00325   // This differs from the previous prototype in that it allows preservation of
00326   // global Vnode integer ID numbers associated with the input Vnodes. --tjw
00327   void Repartition(const Vnode<Dim>*, const Vnode<Dim>*);
00328 
00329   // Return the domain.
00330   const NDIndex<Dim>& getDomain() const { return Domain; }
00331 
00332 //tjw   // Compare FieldLayouts to see if they represent the same domain.
00333 //tjw   bool operator==(const FieldLayout<Dim>& x) const {
00334 //tjw     return Domain == x.Domain;
00335 //tjw   }
00336 
00337   // Compare FieldLayouts to see if they represent the same domain; if
00338   // dimensionalities are different, the NDIndex operator==() will return
00339   // false:
00340   template <unsigned Dim2>
00341   bool operator==(const FieldLayout<Dim2>& x) const {
00342     return Domain == x.getDomain();
00343   }
00344 
00345   // Read information from the given file on how to repartition the data.
00346   // This works just like it does when constructing a FieldLayout from a
00347   // file, in fact this routine is called by the FieldLayout(const char *)
00348   // constructor.  Only node 0 will actually read the file.  Return success.
00349   bool read(const char *filename);
00350 
00351   // Write out info about this layout to the given file.  Only node 0 will
00352   // actually write a file.  Return success.
00353   bool write(const char *filename);
00354 
00355   //
00356   // local vnode, remote vnode, touch range, and FieldLayoutUser iterators
00357   //
00358   int numVnodes(void) const {
00359     return (size_iv() + size_rdv());
00360   }
00361 
00362   // Accessors for the locals by Id.
00363   typename ac_id_vnodes::size_type size_iv() const;
00364   iterator_iv                      begin_iv();
00365   iterator_iv                      end_iv();
00366   const_iterator_iv                begin_iv() const;
00367   const_iterator_iv                end_iv() const;
00368 
00369   // Accessors for the remote vnode containers.
00370   typename ac_gc_domain_vnodes::size_type size_rgdv() const;
00371   iterator_gdv                            begin_rgdv();
00372   iterator_gdv                            end_rgdv();
00373 
00374   // Accessors for the remote vnodes themselves.
00375   typename ac_domain_vnodes::size_type 
00376     size_rdv(const GuardCellSizes<Dim>& gc = gc0()) const;
00377   iterator_dv begin_rdv(const GuardCellSizes<Dim>& gc = gc0());
00378   iterator_dv end_rdv(const GuardCellSizes<Dim>& gc = gc0());
00379   touch_range_dv touch_range_rdv(const NDIndex<Dim>& domain,
00380                                  const GuardCellSizes<Dim>& gc = gc0()) const; 
00381 
00382   // Accessors for the users accessing this FieldLayout
00383   size_type_if      size_if() const { return getNumUsers(); }
00384   iterator_if       begin_if() { return begin_user(); }
00385   iterator_if       end_if() { return end_user(); }
00386 
00387   //
00388   // Query for information about the vnode sizes
00389   //
00390 
00391   // check if the vnode sizes are OK, to match the given GuardCellSizes
00392   bool fitsGuardCells(const GuardCellSizes<Dim>& gc) const {
00393     for (unsigned int d=0; d < Dim; ++d)
00394       if (MinWidth[d] < gc.left(d) || MinWidth[d] < gc.right(d))
00395         return false;
00396     return true;
00397   }
00398 
00399   // for the requested dimension, report if the distribution is
00400   // SERIAL or PARALLEL
00401   e_dim_tag getDistribution(unsigned int d) const {
00402     e_dim_tag retval = PARALLEL;
00403     if (MinWidth[d] == Domain[d].length())
00404       retval = SERIAL;
00405     return retval;
00406   }
00407 
00408   // for the requested dimension, report if the distribution was requested to
00409   // be SERIAL or PARALLEL
00410   e_dim_tag getRequestedDistribution(unsigned int d) const {
00411     return RequestedLayout[d];
00412   }
00413 
00414   // When stored, return number of vnodes along a direction:
00415   unsigned getVnodesPerDirection(unsigned dir);
00416 
00417   //
00418   // UserList operations
00419   //
00420 
00421   // Return our ID, as generated by UserList.
00422   UserList::ID_t get_Id() const { return getUserListID(); }
00423 
00424   // Tell the FieldLayout that a FieldLayoutUser has been declared on it.
00425   // This is different than the checkinUser from UserList,
00426   // since we have the GuardCellSizes argument.
00427   void checkin(FieldLayoutUser& f, const GuardCellSizes<Dim>& gc = gc0());
00428 
00429   // Tell the FieldLayout that a FieldLayoutUser is no longer using it.
00430   // This is different than the checkoutUser from UserList,
00431   // for symmetry with checkin
00432   void checkout(FieldLayoutUser& f);
00433 
00434   NDIndex<Dim> getLocalNDIndex();
00435 
00436   //
00437   // I/O
00438   //
00439 
00440   // Print it out.
00441   void write(ostream&) const;
00442 
00443 private:
00444   // Container definitions.
00445   ac_id_vnodes        Local_ac;
00446   ac_gc_domain_vnodes Remotes_ac;
00447 
00448   // Record the domain.
00449   NDIndex<Dim> Domain;
00450 
00451   // The minimum width of vnodes in each dimension, and the type of
00452   // layout that the user requested (this might not be the case anymore).
00453   unsigned int MinWidth[Dim];
00454   e_dim_tag RequestedLayout[Dim];
00455 
00456   // Store the numbers of vnodes along each direction, when appropriate
00457   // constructors were called; otherwise leave pointer unset for assertion
00458   // checks.
00459   unsigned* vnodesPerDirection_m;
00460 
00461   // calculate the minimum vnode sizes in each dimension
00462   void calcWidths();
00463 
00464   // utility to return a zero-guard cell structure.
00465   void new_gc_layout(const GuardCellSizes<Dim>&);
00466 
00467   // The routine which actually sets things up.
00468   void setup(const NDIndex<Dim>&, e_dim_tag *, int);
00469   void setup(const NDIndex<Dim>&, e_dim_tag *, unsigned*, bool, int);
00470 };
00471 
00472 
00474 
00475 // Definitions for the specialized constructors.
00476 // Just turn it into a call to the general ctor.
00477 
00478 //-----------------------------------------------------------------------------
00479 // These specify only a total number of vnodes, allowing the constructor
00480 // complete control on how to do the vnode partitioning of the index space:
00481 
00482 template<unsigned Dim>
00483 inline
00484 FieldLayout<Dim>::FieldLayout(const Index& i1, e_dim_tag p1, int vnodes)
00485 {
00486   initialize(i1, p1, vnodes);
00487 }
00488 
00489 template<unsigned Dim>
00490 inline
00491 FieldLayout<Dim>::FieldLayout(const Index& i1,const Index& i2,
00492                               e_dim_tag p1, e_dim_tag p2, int vnodes)
00493 {
00494   initialize(i1, i2, p1, p2, vnodes);
00495 }
00496 
00497 template<unsigned Dim>
00498 inline
00499 FieldLayout<Dim>::FieldLayout(const Index& i1, const Index& i2, 
00500                               const Index& i3,
00501                               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00502                               int vnodes)
00503 {
00504   initialize(i1, i2, i3, p1, p2, p3, vnodes);
00505 }
00506 
00507 template<unsigned Dim>
00508 inline
00509 FieldLayout<Dim>::FieldLayout(const Index& i1, const Index& i2, 
00510                               const Index& i3, const Index& i4,
00511                               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00512                               e_dim_tag p4,
00513                               int vnodes)
00514 {
00515   initialize(i1, i2, i3, i4, p1, p2, p3, p4, vnodes);
00516 }
00517 
00518 template<unsigned Dim>
00519 inline
00520 FieldLayout<Dim>::FieldLayout(const Index& i1, const Index& i2, 
00521                               const Index& i3, const Index& i4, 
00522                               const Index& i5,
00523                               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00524                               e_dim_tag p4, e_dim_tag p5,
00525                               int vnodes)
00526 {
00527   initialize(i1, i2, i3, i4, i5, p1, p2, p3, p4, p5, vnodes);
00528 }
00529 
00530 template<unsigned Dim>
00531 inline
00532 FieldLayout<Dim>::FieldLayout(const Index& i1, const Index& i2, 
00533                               const Index& i3, const Index& i4, 
00534                               const Index& i5, const Index& i6,
00535                               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00536                               e_dim_tag p4, e_dim_tag p5, e_dim_tag p6,
00537                               int vnodes)
00538 {
00539   initialize(i1, i2, i3, i4, i5, i6, p1, p2, p3, p4, p5, p6, vnodes);
00540 }
00541 //-----------------------------------------------------------------------------
00542 
00543 //-----------------------------------------------------------------------------
00544 // These specify both the total number of vnodes and the numbers of vnodes
00545 // along each dimension for the partitioning of the index space. Obviously
00546 // this restricts the number of vnodes to be a product of the numbers along
00547 // each dimension (the constructor implementation checks this):
00548 
00549 template<unsigned Dim>
00550 inline
00551 FieldLayout<Dim>::FieldLayout(const Index& i1, 
00552                               e_dim_tag p1, 
00553                               unsigned vnodes1,
00554                               bool recurse, int vnodes)
00555 {
00556   // Default to correct total vnodes:
00557   if (vnodes == -1) vnodes = vnodes1;
00558   // Verify than total vnodes is product of per-dimension vnode counts:
00559   if (vnodes != vnodes1) {
00560     ERRORMSG("FieldLayout constructor: "
00561             << "(vnodes1 != vnodes)"
00562             << " ; vnodes1 = " << vnodes1 
00563             << " ; vnodes = " << vnodes << endl);
00564   }
00565   initialize(i1, p1, vnodes1, recurse,vnodes);
00566 }
00567 
00568 template<unsigned Dim>
00569 inline
00570 FieldLayout<Dim>::FieldLayout(const Index& i1,const Index& i2,
00571                               e_dim_tag p1, e_dim_tag p2, 
00572                               unsigned vnodes1, unsigned vnodes2,
00573                               bool recurse, int vnodes)
00574 {
00575   // Default to correct total vnodes:
00576   if (vnodes == -1) vnodes = vnodes1*vnodes2;
00577   // Verify than total vnodes is product of per-dimension vnode counts:
00578   if (vnodes != vnodes1*vnodes2) {
00579     ERRORMSG("FieldLayout constructor: "
00580             << "(vnodes != vnodes1*vnodes2)"
00581             << " ; vnodes1 = " << vnodes1 << " ; vnodes2 = " << vnodes2 
00582             << " ; vnodes = " << vnodes << endl);
00583   }
00584   initialize(i1, i2, p1, p2, vnodes1, vnodes2, recurse, vnodes);
00585 }
00586 
00587 template<unsigned Dim>
00588 inline
00589 FieldLayout<Dim>::FieldLayout(const Index& i1, const Index& i2, 
00590                               const Index& i3,
00591                               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00592                               unsigned vnodes1, unsigned vnodes2, 
00593                               unsigned vnodes3,
00594                               bool recurse, int vnodes)
00595 {
00596   // Default to correct total vnodes:
00597   if (vnodes == -1) vnodes = vnodes1*vnodes2*vnodes3;
00598   // Verify than total vnodes is product of per-dimension vnode counts:
00599   if (vnodes != vnodes1*vnodes2*vnodes3) {
00600     ERRORMSG("FieldLayout constructor: "
00601             << "(vnodes != vnodes1*vnodes2*vnodes3)"
00602             << " ; vnodes1 = " << vnodes1 << " ; vnodes2 = " << vnodes2 
00603             << " ; vnodes3 = " << vnodes3 
00604             << " ; vnodes = " << vnodes << endl);
00605   }
00606   initialize(i1, i2, i3, p1, p2, p3, vnodes1, vnodes2, vnodes3, recurse, vnodes);
00607 }
00608 
00609 template<unsigned Dim>
00610 inline
00611 FieldLayout<Dim>::FieldLayout(const Index& i1, const Index& i2, 
00612                               const Index& i3, const Index& i4,
00613                               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00614                               e_dim_tag p4,
00615                               unsigned vnodes1, unsigned vnodes2, 
00616                               unsigned vnodes3, unsigned vnodes4,
00617                               bool recurse, int vnodes)
00618 {
00619   // Default to correct total vnodes:
00620   if (vnodes == -1) vnodes = vnodes1*vnodes2*vnodes3*vnodes4;
00621   // Verify than total vnodes is product of per-dimension vnode counts:
00622   if (vnodes != vnodes1*vnodes2*vnodes3*vnodes4) {
00623     ERRORMSG("FieldLayout constructor: "
00624             << "(vnodes != vnodes1*vnodes2*vnodes3*vnodes4)"
00625             << " ; vnodes1 = " << vnodes1 << " ; vnodes2 = " << vnodes2 
00626             << " ; vnodes3 = " << vnodes3 << " ; vnodes4 = " << vnodes4 
00627             << " ; vnodes = " << vnodes << endl);
00628   }
00629   initialize(i1, i2, i3, i4, p1, p2, p3, p4, 
00630              vnodes1, vnodes2, vnodes3, recurse, vnodes);
00631 }
00632 
00633 template<unsigned Dim>
00634 inline
00635 FieldLayout<Dim>::FieldLayout(const Index& i1, const Index& i2, 
00636                               const Index& i3, const Index& i4, 
00637                               const Index& i5,
00638                               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00639                               e_dim_tag p4, e_dim_tag p5,
00640                               unsigned vnodes1, unsigned vnodes2, 
00641                               unsigned vnodes3, unsigned vnodes4,
00642                               unsigned vnodes5,
00643                               bool recurse, int vnodes)
00644 {
00645   // Default to correct total vnodes:
00646   if (vnodes == -1) vnodes = vnodes1*vnodes2*vnodes3*vnodes4*vnodes5;
00647   // Verify than total vnodes is product of per-dimension vnode counts:
00648   if (vnodes != vnodes1*vnodes2*vnodes3*vnodes4*vnodes5) {
00649     ERRORMSG("FieldLayout constructor: "
00650             << "(vnodes != vnodes1*vnodes2*vnodes3*vnodes4*vnodes5)"
00651             << " ; vnodes1 = " << vnodes1 << " ; vnodes2 = " << vnodes2 
00652             << " ; vnodes3 = " << vnodes3 << " ; vnodes4 = " << vnodes4 
00653             << " ; vnodes5 = " << vnodes5 
00654             << " ; vnodes = " << vnodes << endl);
00655   }
00656   initialize(i1, i2, i3, i4, i5, p1, p2, p3, p4, p5, 
00657              vnodes1, vnodes2, vnodes3, vnodes4, vnodes5, recurse, vnodes);
00658 }
00659 
00660 template<unsigned Dim>
00661 inline
00662 FieldLayout<Dim>::FieldLayout(const Index& i1, const Index& i2, 
00663                               const Index& i3, const Index& i4, 
00664                               const Index& i5, const Index& i6,
00665                               e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00666                               e_dim_tag p4, e_dim_tag p5, e_dim_tag p6,
00667                               unsigned vnodes1, unsigned vnodes2, 
00668                               unsigned vnodes3, unsigned vnodes4,
00669                               unsigned vnodes5, unsigned vnodes6,
00670                               bool recurse, int vnodes)
00671 {
00672   // Default to correct total vnodes:
00673   if (vnodes == -1) vnodes = vnodes1*vnodes2*vnodes3*vnodes4*vnodes5*vnodes6;
00674   // Verify than total vnodes is product of per-dimension vnode counts:
00675   if (vnodes != vnodes1*vnodes2*vnodes3*vnodes4*vnodes5*vnodes6) {
00676     ERRORMSG("FieldLayout constructor: "
00677             << "(vnodes != vnodes1*vnodes2*vnodes3*vnodes4*vnodes5*vnodes6)"
00678             << " ; vnodes1 = " << vnodes1 << " ; vnodes2 = " << vnodes2 
00679             << " ; vnodes3 = " << vnodes3 << " ; vnodes4 = " << vnodes4 
00680             << " ; vnodes5 = " << vnodes5 << " ; vnodes6 = " << vnodes6 
00681             << " ; vnodes = " << vnodes << endl);
00682   }
00683   initialize(i1, i2, i3, i4, i5, i6, p1, p2, p3, p4, p5, p6, 
00684              vnodes1, vnodes2, vnodes3, vnodes4, vnodes5, vnodes6, recurse, vnodes);
00685 }
00686 
00687 template<unsigned Dim>
00688 inline
00689 FieldLayout<Dim>::FieldLayout(const NDIndex<Dim> &Domain,
00690                               const NDIndex<Dim> *dombegin,
00691                               const NDIndex<Dim> *domend,
00692                               const int *nbegin,
00693                               const int *nend)
00694 {
00695   initialize(Domain, dombegin, domend, nbegin, nend);
00696 }
00697 
00698 //-----------------------------------------------------------------------------
00699 
00700 
00702 
00703 // Accessor definitions.
00704 
00705 template<unsigned Dim>
00706 inline typename FieldLayout<Dim>::ac_id_vnodes::size_type 
00707 FieldLayout<Dim>::size_iv() const
00708 {
00709   return Local_ac.size();
00710 }
00711 
00712 template<unsigned Dim>
00713 inline typename FieldLayout<Dim>::iterator_iv
00714 FieldLayout<Dim>::begin_iv()
00715 {
00716   return Local_ac.begin();
00717 }
00718 
00719 template<unsigned Dim>
00720 inline typename FieldLayout<Dim>::iterator_iv
00721 FieldLayout<Dim>::end_iv()
00722 {
00723   return Local_ac.end();
00724 }
00725 
00726 template<unsigned Dim>
00727 inline typename FieldLayout<Dim>::const_iterator_iv
00728 FieldLayout<Dim>::begin_iv() const
00729 {
00730   return Local_ac.begin();
00731 }
00732 
00733 template<unsigned Dim>
00734 inline typename FieldLayout<Dim>::const_iterator_iv
00735 FieldLayout<Dim>::end_iv() const
00736 {
00737   return Local_ac.end();
00738 }
00739 
00740 template<unsigned Dim>
00741 inline typename FieldLayout<Dim>::ac_gc_domain_vnodes::size_type
00742 FieldLayout<Dim>::size_rgdv() const
00743 {
00744   return Remotes_ac.size();
00745 }
00746 
00747 template<unsigned Dim>
00748 inline typename FieldLayout<Dim>::iterator_gdv
00749 FieldLayout<Dim>::begin_rgdv()
00750 {
00751   return Remotes_ac.begin();
00752 }
00753 
00754 template<unsigned Dim>
00755 inline typename FieldLayout<Dim>::iterator_gdv
00756 FieldLayout<Dim>::end_rgdv()
00757 {
00758   return Remotes_ac.end();
00759 }
00760 
00761 template<unsigned Dim>
00762 inline typename FieldLayout<Dim>::ac_domain_vnodes::size_type
00763 FieldLayout<Dim>::size_rdv(const GuardCellSizes<Dim>& gc) const
00764 {
00765   return Remotes_ac[gc]->size();
00766 }
00767 
00768 template<unsigned Dim>
00769 inline typename FieldLayout<Dim>::iterator_dv
00770 FieldLayout<Dim>::begin_rdv(const GuardCellSizes<Dim>& gc)
00771 {
00772   return Remotes_ac[gc]->begin();
00773 }
00774 
00775 template<unsigned Dim>
00776 inline typename FieldLayout<Dim>::iterator_dv
00777 FieldLayout<Dim>::end_rdv(const GuardCellSizes<Dim>& gc)
00778 {
00779   return Remotes_ac[gc]->end();
00780 }
00781 
00782 template<unsigned Dim>
00783 inline 
00784 typename FieldLayout<Dim>::touch_range_dv
00785 FieldLayout<Dim>::touch_range_rdv(const NDIndex<Dim>& domain,
00786                                   const GuardCellSizes<Dim>& gc) const
00787 {
00788   return Remotes_ac[gc]->touch_range(domain);
00789 }
00790 
00791 
00792 // I/O
00793 
00794 template<unsigned Dim>
00795 inline
00796 ostream& operator<<(ostream& out, const FieldLayout<Dim>& f) {
00797   TAU_TYPE_STRING(taustr, "ostream (ostream, " + CT(f) + " )");
00798   TAU_PROFILE("operator<<()", taustr, TAU_LAYOUT | TAU_IO);
00799 
00800   f.write(out);
00801   return out;
00802 }
00803 
00804 
00805 #include "FieldLayout/FieldLayout.cpp"
00806 
00807 #endif // FIELD_LAYOUT_H
00808 
00809 /***************************************************************************
00810  * $RCSfile: FieldLayout.h,v $   $Author: adelmann $
00811  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:27 $
00812  * IPPL_VERSION_ID: $Id: FieldLayout.h,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $ 
00813  ***************************************************************************/

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