src/Region/RegionLayout.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 REGION_LAYOUT_H
00012 #define REGION_LAYOUT_H
00013 
00014 /***************************************************************************
00015  * RegionLayout stores a partitioned set of NDRegion objects, to represent
00016  * the parallel layout of an encompassing NDRegion.  It also contains
00017  * functions to find the subsets of the NDRegion partitions which intersect
00018  * or touch a given NDRegion.  It is similar to FieldLayout, with the
00019  * following changes:
00020  * 1. It uses NDRegion instead of NDIndex, so it is templated on the position
00021  *    data type (although it can be constructed with an NDIndex and a Mesh
00022  *    as well);
00023  * 2. It does not contain any consideration for guard cells;
00024  * 3. It can store not only the partitioned domain, but periodic copies of
00025  *    the partitioned domain for use by particle periodic boundary conditions
00026  * 4. It also keeps a list of FieldLayoutUser's, so that it can notify them
00027  *    when the internal FieldLayout here is reparitioned or otherwise changed.
00028  *
00029  * If this is constructed with a FieldLayout, it stores a pointer to it
00030  * so that if we must repartition the copy of the FieldLayout that
00031  * is stored here, we will end up repartitioning all the registered Fields.
00032  ***************************************************************************/
00033 
00034 // include files
00035 #include "Region/Rnode.h"
00036 #include "Index/NDIndex.h"
00037 #include "DomainMap/DomainMap.h"
00038 #include "FieldLayout/FieldLayoutUser.h"
00039 #include "Utility/Unique.h"
00040 #include "Utility/UserList.h"
00041 #include "Utility/vmap.h"
00042 
00043 #ifdef IPPL_USE_STANDARD_HEADERS
00044 #include <iostream>
00045 using namespace std;
00046 #else
00047 #include <iostream.h>
00048 #endif
00049 
00050 
00051 // forward declarations
00052 template <unsigned Dim> class FieldLayout;
00053 template <unsigned Dim, class T> class UniformCartesian;
00054 template <class T, unsigned Dim, class MeshType> class RegionLayout;
00055 template <class T, unsigned Dim, class MeshType>
00056 ostream& operator<<(ostream&, const RegionLayout<T,Dim,MeshType>&);
00057 
00058 
00059 // the RegionLayout class definition
00060 template < class T, unsigned Dim, class MeshType=UniformCartesian<Dim,T> >
00061 class RegionLayout : public FieldLayoutUser, private UserList {
00062 
00063 public:
00064   // Typedefs for containers.
00065   typedef vmap<Unique::type, Rnode<T,Dim> *> ac_id_vnodes;
00066   typedef DomainMap<NDRegion<T,Dim>, Rnode<T,Dim> *,
00067                     TouchesRegion<T,Dim>,
00068                     ContainsRegion<T,Dim>,
00069                     SplitRegion<T,Dim> > ac_domain_vnodes;
00070 
00071   // Typedefs for iterators.
00072   typedef typename ac_id_vnodes::iterator                    iterator_iv;
00073   typedef typename ac_id_vnodes::const_iterator              const_iterator_iv;
00074   typedef typename ac_domain_vnodes::iterator                iterator_dv;
00075   typedef typename ac_domain_vnodes::const_iterator          const_iterator_dv;
00076   typedef typename ac_domain_vnodes::touch_iterator          touch_iterator_dv;
00077   typedef pair<touch_iterator_dv,touch_iterator_dv> touch_range_dv;
00078 
00079 public:
00080   // Default constructor.  To make this class actually work, the user
00081   // will have to later call 'changeDomain' to set the proper Domain
00082   // and get a new partitioning.
00083   RegionLayout();
00084 
00085   // Copy constructor.
00086   RegionLayout(const RegionLayout<T,Dim,MeshType>&);
00087 
00088   // Constructors which partition the given ND, 1D, 2D, or 3D PRegions
00089   RegionLayout(const NDRegion<T,Dim>& domain, MeshType& mesh, int vnodes=-1);
00090   RegionLayout(const PRegion<T>& i1, MeshType& mesh, int vnodes=-1);
00091   RegionLayout(const PRegion<T>& i1, const PRegion<T>& i2, MeshType& mesh,
00092                int vnodes=-1);
00093   RegionLayout(const PRegion<T>& i1, const PRegion<T>& i2,
00094                const PRegion<T>& i3, MeshType& mesh, int vnodes=-1);
00095 
00096   // Constructor which takes a FieldLayout, and stores a ref to it
00097   // This will assume a MeshType with unit spacing and that the domain of
00098   // the MeshType is one larger in each dimension than the domain of the 
00099   // FieldLayout (i.e., the FieldLayout index space refers to cell-centered
00100   // Field quantities).
00101   RegionLayout(FieldLayout<Dim>&);
00102 
00103   // Constructor which takes a FieldLayout and a MeshType
00104   // This one compares the domain of the FieldLayout and the domain of
00105   // the MeshType to determine the centering of the index space.
00106   RegionLayout(FieldLayout<Dim>&, MeshType&);
00107 
00108   // Constructor which takes an NDIndex and converts it to a RegionLayout.
00109   // These assume a MeshType with unit spacing and that the domain of
00110   // the MeshType is one larger in each dimension than the given domain 
00111   // (i.e., the index space refers to cell-centered Field quantities).
00112   RegionLayout(const NDIndex<Dim>& domain, int vnodes=-1);
00113   RegionLayout(const Index& i1,int vnodes=-1);
00114   RegionLayout(const Index& i1,const Index& i2,int vnodes=-1);
00115   RegionLayout(const Index& i1,const Index& i2,const Index& i3,int vnodes=-1);
00116 
00117   // Constructors which take NDIndex and MeshType and convert to RegionLayout.
00118   // These compare the given domain and the domain of
00119   // the MeshType to determine the centering of the index space.
00120   RegionLayout(const NDIndex<Dim>& domain, MeshType& mesh, int vnodes=-1);
00121   RegionLayout(const Index& i1, MeshType& mesh, int vnodes=-1);
00122   RegionLayout(const Index& i1, const Index& i2,MeshType& mesh,int vnodes=-1);
00123   RegionLayout(const Index& i1, const Index& i2, const Index& i3,
00124                MeshType& mesh, int vnodes=-1);
00125 
00126   // Destructor.
00127   virtual ~RegionLayout();
00128 
00129   //
00130   // accessor member functions
00131   //
00132 
00133   // Has the domain been initialized and partitioned yet?
00134   bool initialized() const { return (FLayout != 0); }
00135 
00136   // Return the encompassing domain.
00137   const NDRegion<T,Dim>& getDomain() const { return Domain; }
00138 
00139   // Return the underlying FieldLayout.  This is not const, since we may
00140   // want to make Field's out of it (and have those Field's temporarily
00141   // register themselves with this FieldLayout).  We do supply a const
00142   // version, however.
00143   FieldLayout<Dim>& getFieldLayout() { return *FLayout; }
00144   const FieldLayout<Dim>& getFieldLayout() const { return *FLayout; }
00145 
00146   // get the mesh
00147   MeshType& getMesh() { return *theMesh; }
00148   const MeshType& getMesh() const { return *theMesh; }
00149 
00150   // Accessors for the locals domains by Id.
00151   typename ac_id_vnodes::size_type size_iv() const { return Local_ac.size(); }
00152   iterator_iv begin_iv()             { return Local_ac.begin(); }
00153   iterator_iv end_iv()               { return Local_ac.end(); }
00154   const_iterator_iv begin_iv() const { return Local_ac.begin(); }
00155   const_iterator_iv end_iv() const   { return Local_ac.end(); }
00156 
00157   // Accessors for the remote vnodes themselves.
00158   typename ac_domain_vnodes::size_type size_rdv() const {
00159     return  (Remote_ac != 0 ? Remote_ac->size() : 0);
00160   }
00161   iterator_dv begin_rdv()                { return Remote_ac->begin(); }
00162   iterator_dv end_rdv()                  { return Remote_ac->end(); }
00163   const_iterator_dv begin_rdv() const    { return Remote_ac->begin(); }
00164   const_iterator_dv end_rdv() const      { return Remote_ac->end(); }
00165   touch_range_dv touch_range_rdv(const NDRegion<T,Dim>& domain) {
00166     return Remote_ac->touch_range(domain);
00167   }
00168 
00169   //
00170   // operator/action methods
00171   //
00172 
00173   // Repartition the region, using the given layout as the new global
00174   // domain.  This is essentially the same as what occurs during construction,
00175   // but may be done any time after construction.
00176   void changeDomain(FieldLayout<Dim>&);
00177   void changeDomain(const NDIndex<Dim>&, int vnodes=-1);
00178   void changeDomain(const NDRegion<T,Dim>&, int vnodes=-1);
00179 
00180   // Repartition the region, from a list of NDIndex objects which
00181   // represent our local domain.  This assumes two things:
00182   //   1. We are repartitioning the same global domain, just in a different
00183   //      way.  Thus, the encompassing NDRegion 'Domain' does not change.
00184   //   2. The NDIndex objects cover a domain which corresponds to our
00185   //      internal FieldLayout domain.  This may or may not directly
00186   //      overlap with the NDRegion domain.  The basic point is that with
00187   //      these NDIndex objects, we can replace the FieldLayout directly,
00188   //      and then regenerate our RegionLayout (Rnode) data.
00189   void RepartitionLayout(NDIndex<Dim>*, NDIndex<Dim>*);
00190   void RepartitionLayout(NDIndex<Dim>& domain) {
00191     RepartitionLayout(&domain, (&domain) + 1);
00192   }
00193 
00194   // convert a given NDIndex into an NDRegion ... if this object was
00195   // constructed from a FieldLayout, this does nothing, but if we have
00196   // our own internal FieldLayout, we must convert from the [0,N-1] index
00197   // space to our own continuous NDRegion space.
00198   NDRegion<T,Dim> convert_index(const NDIndex<Dim>&) const;
00199 
00200   // perform the inverse of convert_index: convert a given NDRegion (with
00201   // coordinates in the 'region' space) into an NDIndex (with values in
00202   // the [0,N-1] 'index' space).  This will truncate values when converting
00203   // from continuous to integer data.
00204   NDIndex<Dim> convert_region(const NDRegion<T,Dim>&) const;
00205 
00206 #ifdef IPPL_USE_MEMBER_TEMPLATES
00207   //mwerks  template < unsigned D >
00208   //mwerks  NDRegion<T,Dim> convert_index(const NDIndex<D>&) const;
00209   template < unsigned D >
00210   NDRegion<T,Dim>
00211   convert_index(const NDIndex<D>& ni) const {
00212     NDRegion<T,Dim> new_pregion; // Needed in TAU_TYPE_STRING
00213     TAU_TYPE_STRING(taustr, CT(new_pregion) + " ("  + CT(ni) + " )");
00214     TAU_PROFILE("RegionLayout::convert_index()", taustr, TAU_REGION);
00215 
00216     PInsist(D==Dim,"Dimension of input NDIndex does not match RegionLayout!!");
00217     return new_pregion;
00218   }
00219 
00220   //mwerks  template < unsigned D >
00221   //mwerks  NDIndex<Dim> convert_region(const NDRegion<T,D>&) const;
00222   template < unsigned D >
00223   NDIndex<Dim>
00224   convert_region(const NDRegion<T,D>& nr) const {
00225     NDIndex<Dim> index;
00226     TAU_TYPE_STRING(taustr, CT(index) + " ("  + CT(nr) + " )");
00227     TAU_PROFILE("RegionLayout::convert_region()", taustr, TAU_REGION);
00228 
00229     PInsist(D==Dim,"Dimension of input NDRegion does not match RegionLayout!!");
00230     return index;
00231   }
00232 #endif
00233 
00234   // Compare RegionLayouts to see if they represent the same domain.
00235   bool operator==(const RegionLayout<T,Dim,MeshType>& x) {
00236     return Domain == x.Domain;
00237   }
00238 
00239   //
00240   // virtual functions for FieldLayoutUser's (and other UserList users)
00241   //
00242 
00243   // Repartition onto a new layout
00244   virtual void Repartition(UserList *);
00245 
00246   // Tell this object that an object is being deleted
00247   virtual void notifyUserOfDelete(UserList *);
00248 
00249   //
00250   // UserList operations, so that users of this RegionLayout can be
00251   // kept and notified of changes to the RegionLayout.  We use
00252   // FieldLayoutUser as the class which must check in here for
00253   // convenience, since FieldLayoutUser defines a virtual function
00254   // 'Repartition' which we'll need to call for the users when this
00255   // RegionLayout changes via repartitioning of itself or of it's
00256   // internal FieldLayout.
00257   //
00258 
00259   // Return our ID, as generated by UserList.
00260   UserList::ID_t get_Id() const { return getUserListID(); }
00261 
00262   // Tell this object that a FieldLayoutUser is using it.
00263   // This is different than the checkinUser from UserList, since we need
00264   // a FieldLayoutUser to be stored that has a Repartition virtual function.
00265   void checkin(FieldLayoutUser& f) { checkinUser(f); }
00266 
00267   // Tell this object that a FieldLayoutUser is no longer using it.
00268   // This is different than the checkoutUser from UserList,
00269   // for symmetry with checkin.  Both of these make sure this object
00270   // only allows FieldLayoutUser's to check in.
00271   void checkout(FieldLayoutUser& f) { checkoutUser(f); }
00272 
00273 private:
00274   // The local and the remote subdomains which comprise the total domain
00275   ac_id_vnodes     Local_ac;
00276   ac_domain_vnodes *Remote_ac;
00277 
00278   // The total domain, i.e. the bounding box for the spatial region
00279   NDRegion<T,Dim>  Domain;
00280 
00281   // A FieldLayout which is used to represent a grid over our spatial area
00282   FieldLayout<Dim> *FLayout;
00283   bool             WeOwnFieldLayout;
00284 
00285   // A MeshType which is used to represent a grid over our spatial area
00286   MeshType *theMesh;
00287   bool WeOwnMesh;
00288 
00289   // The number of vertices in the mesh
00290   NDIndex<Dim> MeshVertices;
00291 
00292   // Offset from 'normal' Index space to 'Mesh' Index space
00293   int IndexOffset[Dim];
00294 
00295   // Offset needed between centering of Index space and Mesh points
00296   bool CenterOffset[Dim];
00297 
00298   // The routine which actually sets things up.
00299   void setup(const NDRegion<T,Dim>&, int);
00300 
00301   // Scan through the given FieldLayout and construct Rnodes based on
00302   // the FieldLayout and NDRegion.  Put them into out local
00303   // and remote Rnode containers.
00304   void make_rnodes(const NDRegion<T,Dim>&, FieldLayout<Dim>&);
00305 
00306   // Delete the Rnodes in out local and remote lists ... actually,
00307   // just returns them back to the static pool.
00308   void delete_rnodes();
00309 
00310   // Store a layout object pointer, and note if we own it or not.
00311   // Delete our current FLayout, and set it to NULL; we may have to
00312   // check out from the layout
00313   void store_flayout(FieldLayout<Dim>*, bool WeOwn);
00314   void delete_flayout();
00315 
00316   // Store a mesh object pointer, and note if we own it or not.
00317   // Delete our current MeshType, and set it to NULL; we may have to
00318   // check out from the mesh
00319   void store_mesh(MeshType*, bool WeOwn);
00320   void delete_mesh();
00321 
00322   // Calculate the boundary region of the given mesh, and the number of
00323   // vertices
00324 #if defined(__MWERKS__)
00325 #if __MWERKS__ < 0x2300
00326   const NDRegion<T,Dim> getMeshDomain(MeshType *);
00327 #else
00328   NDRegion<T,Dim> getMeshDomain(MeshType *);
00329 #endif
00330 #else
00331   // Is this really a C++ error here, or just something mwerksCW4 doesn't grok?
00332   NDRegion<T,Dim> getMeshDomain(MeshType *);
00333 #endif // __MWERKS__
00334   NDIndex<Dim>    getMeshVertices(MeshType *);
00335 
00336   //
00337   // Rnode pool - a static pool of unused Rnode's, used to cut down on new's
00338   //
00339 
00340   class RnodePool : public vector<Rnode<T,Dim> *> {
00341   public:
00342     // the constructor and destructor ... the destructor will clean up
00343     // the storage for allocated Rnode's when the program exits
00344     RnodePool() { }
00345     ~RnodePool() {
00346       while (this->size() > 0) {
00347         delete this->back();
00348         this->pop_back();
00349       }
00350     }
00351 
00352     // create a new Rnode, or get one from storage.
00353     Rnode<T,Dim>* create_rnode(const NDRegion<T,Dim>& nr, int node) {
00354       if (this->empty()) {
00355         return new Rnode<T,Dim>(nr, node);
00356       }
00357       else {
00358         Rnode<T,Dim>* rnode = this->back();
00359         this->pop_back();
00360         *rnode = Rnode<T,Dim>(nr, node);
00361         return rnode;
00362       }
00363     }
00364 
00365     // one more version of create, also specifying an offset
00366     Rnode<T,Dim>* create_rnode(const NDRegion<T,Dim>& nr,
00367                                const Vektor<T,Dim>& v,
00368                                int node) {
00369       if (this->empty()) {
00370         return new Rnode<T,Dim>(nr, v, node);
00371       }
00372       else {
00373         Rnode<T,Dim>* rnode = this->back();
00374         this->pop_back();
00375         *rnode = Rnode<T,Dim>(nr, v, node);
00376         return rnode;
00377       }
00378     }
00379   };
00380 
00381   // a static pool of Rnodes
00382   static RnodePool StaticRnodePool;
00383 
00384 };
00385 
00386 #include "Region/RegionLayout.cpp"
00387 
00388 #endif // REGION_LAYOUT_H
00389 
00390 /***************************************************************************
00391  * $RCSfile: RegionLayout.h,v $   $Author: adelmann $
00392  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:32 $
00393  * IPPL_VERSION_ID: $Id: RegionLayout.h,v 1.1.1.1 2003/01/23 07:40:32 adelmann Exp $ 
00394  ***************************************************************************/

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