src/Region/RegionLayout.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  * This program was prepared by PSI. 
00007  * All rights in the program are reserved by PSI.
00008  * Neither PSI nor the author(s)
00009  * makes any warranty, express or implied, or assumes any liability or
00010  * responsibility for the use of this software
00011  *
00012  * Visit http://www.acl.lanl.gov/POOMS for more details
00013  *
00014  ***************************************************************************/
00015 
00016 // -*- C++ -*-
00017 /***************************************************************************
00018  *
00019  * The IPPL Framework
00020  * 
00021  *
00022  * Visit http://people.web.psi.ch/adelmann/ for more details
00023  *
00024  ***************************************************************************/
00025 
00026 // include files
00027 #include "Region/RegionLayout.h"
00028 #include "Region/Rnode.h"
00029 #include "Index/NDIndex.h"
00030 #include "Field/GuardCellSizes.h"
00031 #include "FieldLayout/FieldLayout.h"
00032 #include "Utility/PAssert.h"
00033 #include "Utility/IpplInfo.h"
00034 #include "Profile/Profiler.h"
00035 
00036 // static RegionLayout members
00037 template < class T, unsigned Dim, class MeshType >
00038 typename RegionLayout<T,Dim,MeshType>::RnodePool
00039   RegionLayout<T,Dim,MeshType>::StaticRnodePool;
00040 
00041 
00043 // default constructor
00044 template < class T, unsigned Dim, class MeshType >
00045 RegionLayout<T,Dim,MeshType>::RegionLayout() {
00046   TAU_TYPE_STRING(taustr, CT(*this) + " void ()");
00047   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00048 
00049   for (unsigned d=0; d < Dim; ++d) {
00050     IndexOffset[d] = 0;
00051     CenterOffset[d] = 0;
00052   }
00053 
00054   Remote_ac = 0;
00055   //  store_mesh(0, true);
00056   //  store_flayout(0, true);
00057   // Initialize the data members directly,
00058   // to avoid problems with non-zero default values of pointers
00059   theMesh = 0;
00060   WeOwnMesh = true;
00061   FLayout = 0;
00062   WeOwnFieldLayout = true;
00063 }
00064 
00066 // copy constructor
00067 template < class T, unsigned Dim, class MeshType >
00068 RegionLayout<T,Dim,MeshType>::RegionLayout(const RegionLayout<T,Dim,MeshType>& r) {
00069   TAU_TYPE_STRING(taustr, "void (" + CT(r) + ")");
00070   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00071 
00072   for (unsigned d=0; d < Dim; ++d) {
00073     IndexOffset[d] = r.IndexOffset[d];
00074     CenterOffset[d] = r.CenterOffset[d];
00075   }
00076 
00077   FLayout = 0;
00078   theMesh = 0;
00079   Remote_ac = 0;
00080   
00081   if (r.WeOwnMesh) {
00082     // make local copy of mesh
00083     store_mesh(new MeshType(*(r.theMesh)), true);
00084   } else {
00085     // just copy the pointer
00086     store_mesh(r.theMesh, false);
00087   }
00088 
00089   if (r.WeOwnFieldLayout)
00090     changeDomain(r.Domain, r.size_iv() + r.size_rdv());
00091   else
00092     changeDomain(*((FieldLayout<Dim> *)(r.FLayout)));
00093 }
00094 
00095 
00097 // destructor
00098 template < class T, unsigned Dim, class MeshType >
00099 RegionLayout<T,Dim,MeshType>::~RegionLayout() {
00100   TAU_TYPE_STRING(taustr, CT(*this) + " void ()");
00101   TAU_PROFILE("RegionLayout::~RegionLayout()", taustr, TAU_REGION);
00102  
00103   // delete all our existing rnodes
00104   delete_rnodes();
00105 
00106   // delete the FieldLayout
00107   delete_flayout();
00108 
00109   // delete the mesh
00110   delete_mesh();
00111 }
00112 
00113 
00115 // constructor for an N-Dimensional PRegion
00116 template < class T, unsigned Dim, class MeshType >
00117 RegionLayout<T,Dim,MeshType>::RegionLayout(const NDRegion<T,Dim>& domain,
00118                                            MeshType& mesh, int vnodes) {
00119   TAU_TYPE_STRING(taustr, "void (" + CT(domain) + ", " + CT(mesh) + ", int)");
00120   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00121 
00122   FLayout = 0;
00123   theMesh = 0;
00124   Remote_ac = 0;
00125   store_mesh(&mesh, false);
00126   changeDomain(domain, vnodes);
00127 }
00128 
00130 // constructor for just a 1-D PRegion
00131 template < class T, unsigned Dim, class MeshType >
00132 RegionLayout<T,Dim,MeshType>::RegionLayout(const PRegion<T>& i1,
00133                                            MeshType& mesh, int vnodes) {
00134   TAU_TYPE_STRING(taustr, "void (" + CT(i1) + ", " + CT(mesh) + ", int)");
00135   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00136 
00137   PInsist(Dim==1,
00138     "Number of PRegion arguments does not match RegionLayout dimension!!");
00139   FLayout = 0;
00140   theMesh = 0;
00141   Remote_ac = 0;
00142   store_mesh(&mesh, false);
00143   NDRegion<T,Dim> dom;
00144   dom[0] = i1;
00145   changeDomain(dom, vnodes);
00146 }
00147 
00149 // constructor for just a 2-D PRegion
00150 template < class T, unsigned Dim, class MeshType >
00151 RegionLayout<T,Dim,MeshType>::RegionLayout(const PRegion<T>& i1,
00152                                            const PRegion<T>& i2,
00153                                            MeshType& mesh,
00154                                            int vnodes) {
00155   TAU_TYPE_STRING(taustr, "void (" + CT(i1) + ", " + CT(i2) + ", " 
00156     + CT(mesh) + ", int)");
00157   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00158 
00159   PInsist(Dim==2,
00160     "Number of PRegion arguments does not match RegionLayout dimension!!");
00161   FLayout = 0;
00162   theMesh = 0;
00163   Remote_ac = 0;
00164   store_mesh(&mesh, false);
00165   NDRegion<T,Dim> dom;
00166   dom[0] = i1;
00167   dom[1] = i2;
00168   changeDomain(dom, vnodes);
00169 }
00170 
00172 // constructor for just a 3-D PRegion
00173 template < class T, unsigned Dim, class MeshType >
00174 RegionLayout<T,Dim,MeshType>::RegionLayout(const PRegion<T>& i1,
00175                                            const PRegion<T>& i2,
00176                                            const PRegion<T>& i3,
00177                                            MeshType& mesh,
00178                                            int vnodes) {
00179   TAU_TYPE_STRING(taustr, "void (" + CT(i1) + ", " + CT(i2) + ", " 
00180     + CT(i3) + ", " + CT(mesh) + ", int)");
00181   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00182 
00183   PInsist(Dim==3,
00184     "Number of PRegion arguments does not match RegionLayout dimension!!");
00185   FLayout = 0;
00186   theMesh = 0;
00187   Remote_ac = 0;
00188   store_mesh(&mesh, false);
00189   NDRegion<T,Dim> dom;
00190   dom[0] = i1;
00191   dom[1] = i2;
00192   dom[2] = i3;
00193   changeDomain(dom, vnodes);
00194 }
00195 
00196 
00197 
00199 // constructor for an N-Dimensional PRegion, given an NDIndex
00200 template < class T, unsigned Dim, class MeshType >
00201 RegionLayout<T,Dim,MeshType>::RegionLayout(const NDIndex<Dim>& domain,
00202                                            int vnodes) {
00203   TAU_TYPE_STRING(taustr, "void (" + CT(domain) + ", int)");
00204   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00205 
00206   // build mesh on this domain, with each axis extended by one
00207   NDIndex<Dim> extended;
00208   for (int i=0; i<Dim; i++)
00209     extended[i] = Index(domain[i].first(), domain[i].last()+1,
00210                         domain[i].stride());
00211   FLayout = 0;
00212   theMesh = 0;
00213   Remote_ac = 0;
00214   store_mesh(new MeshType(extended), true);
00215   changeDomain(domain, vnodes);
00216 }
00217 
00219 // constructor for just a 1-D PRegion, given an Index
00220 template < class T, unsigned Dim, class MeshType >
00221 RegionLayout<T,Dim,MeshType>::RegionLayout(const Index& i1, int vnodes) {
00222   TAU_TYPE_STRING(taustr, "void (" + CT(i1) + ", int)");
00223   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00224  
00225   PInsist(Dim==1,
00226     "Number of Index arguments does not match RegionLayout dimension!!");
00227   // build mesh on this Index, extended by one
00228   Index extended(i1.first(), i1.last()+1, i1.stride());
00229   FLayout = 0;
00230   theMesh = 0;
00231   Remote_ac = 0;
00232   store_mesh(new MeshType(extended), true);
00233   NDIndex<Dim> dom;
00234   dom[0] = i1;
00235   changeDomain(dom, vnodes);
00236 }
00237 
00239 // constructor for just a 2-D PRegion, given two Index objecs
00240 template < class T, unsigned Dim, class MeshType >
00241 RegionLayout<T,Dim,MeshType>::RegionLayout(const Index& i1, const Index& i2,
00242                                        int vnodes) {
00243   TAU_TYPE_STRING(taustr, "void (" + CT(i1) + ", " + CT(i2) + ", int)"); 
00244   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00245 
00246   PInsist(Dim==2,
00247     "Number of Index arguments does not match RegionLayout dimension!!");
00248   // build mesh on domain extended by one on each axis
00249   Index ex1(i1.first(), i1.last()+1, i1.stride());
00250   Index ex2(i2.first(), i2.last()+1, i2.stride());
00251   FLayout = 0;
00252   theMesh = 0;
00253   Remote_ac = 0;
00254   store_mesh(new MeshType(ex1, ex2), true);
00255   NDIndex<Dim> dom;
00256   dom[0] = i1;
00257   dom[1] = i2;
00258   changeDomain(dom, vnodes);
00259 }
00260 
00262 // constructor for just a 3-D PRegion, given three Index objecs
00263 template < class T, unsigned Dim, class MeshType >
00264 RegionLayout<T,Dim,MeshType>::RegionLayout(const Index& i1, const Index& i2,
00265                                        const Index& i3, int vnodes) {
00266   TAU_TYPE_STRING(taustr, "void (" + CT(i1) + ", " + CT(i2) + ", "
00267     + CT(i3) + ", int)");
00268   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00269 
00270   PInsist(Dim==3,
00271     "Number of Index arguments does not match RegionLayout dimension!!");
00272   // build mesh on domain extended by one on each axis
00273   Index ex1(i1.first(), i1.last()+1, i1.stride());
00274   Index ex2(i2.first(), i2.last()+1, i2.stride());
00275   Index ex3(i3.first(), i3.last()+1, i3.stride());
00276   FLayout = 0;
00277   theMesh = 0;
00278   Remote_ac = 0;
00279   store_mesh(new MeshType(ex1, ex2, ex3), true);
00280   NDIndex<Dim> dom;
00281   dom[0] = i1;
00282   dom[1] = i2;
00283   dom[2] = i3;
00284   changeDomain(dom, vnodes);
00285 }
00286 
00287 
00288 
00290 // constructor for an N-Dimensional PRegion, given an NDIndex and Mesh
00291 template < class T, unsigned Dim, class MeshType >
00292 RegionLayout<T,Dim,MeshType>::RegionLayout(const NDIndex<Dim>& domain,
00293                                            MeshType& mesh,
00294                                            int vnodes) {
00295   TAU_TYPE_STRING(taustr, "void (" + CT(domain) + ", " + CT(mesh) + ", int)");
00296   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00297 
00298   FLayout = 0;
00299   theMesh = 0;
00300   Remote_ac = 0;
00301   store_mesh(&mesh, false);
00302   changeDomain(domain, vnodes);
00303 }
00304 
00306 // constructor for just a 1-D PRegion, given an Index and Mesh
00307 template < class T, unsigned Dim, class MeshType >
00308 RegionLayout<T,Dim,MeshType>::RegionLayout(const Index& i1,
00309                                            MeshType& mesh,
00310                                            int vnodes) {
00311   TAU_TYPE_STRING(taustr, "void (" + CT(i1) + ", " + CT(mesh) + ", int)");
00312   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00313 
00314   PInsist(Dim==1,
00315     "Number of Index arguments does not match RegionLayout dimension!!");
00316   FLayout = 0;
00317   theMesh = 0;
00318   Remote_ac = 0;
00319   store_mesh(&mesh, false);
00320   NDIndex<Dim> dom;
00321   dom[0] = i1;
00322   changeDomain(dom, vnodes);
00323 }
00324 
00326 // constructor for just a 2-D PRegion, given two Index objecs and a Mesh
00327 template < class T, unsigned Dim, class MeshType >
00328 RegionLayout<T,Dim,MeshType>::RegionLayout(const Index& i1,
00329                                            const Index& i2,
00330                                            MeshType& mesh,
00331                                            int vnodes) {
00332   TAU_TYPE_STRING(taustr, "void (" + CT(i1) + ", " + CT(i2) + ", " 
00333     + CT(mesh) + ", int)");
00334   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00335 
00336   PInsist(Dim==2,
00337     "Number of Index arguments does not match RegionLayout dimension!!");
00338   FLayout = 0;
00339   theMesh = 0;
00340   Remote_ac = 0;
00341   store_mesh(&mesh, false);
00342   NDIndex<Dim> dom;
00343   dom[0] = i1;
00344   dom[1] = i2;
00345   changeDomain(dom, vnodes);
00346 }
00347 
00349 // constructor for just a 3-D PRegion, given three Index objecs and a Mesh
00350 template < class T, unsigned Dim, class MeshType >
00351 RegionLayout<T,Dim,MeshType>::RegionLayout(const Index& i1,
00352                                            const Index& i2,
00353                                            const Index& i3,
00354                                            MeshType& mesh,
00355                                            int vnodes) {
00356   TAU_TYPE_STRING(taustr, "void (" + CT(i1) + ", " + CT(i2) + ", " 
00357     + CT(i3) + ", " + CT(mesh) + ", int)");
00358   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00359 
00360   PInsist(Dim==3,
00361     "Number of Index arguments does not match RegionLayout dimension!!");
00362   FLayout = 0;
00363   theMesh = 0;
00364   Remote_ac = 0;
00365   store_mesh(&mesh, false);
00366   NDIndex<Dim> dom;
00367   dom[0] = i1;
00368   dom[1] = i2;
00369   dom[2] = i3;
00370   changeDomain(dom, vnodes);
00371 }
00372 
00373 
00375 // Constructor which takes a FieldLayout, and uses it for our layout
00376 template < class T, unsigned Dim, class MeshType >
00377 RegionLayout<T,Dim,MeshType>::RegionLayout(FieldLayout<Dim>& fl) {
00378   TAU_TYPE_STRING(taustr, "void (" + CT(fl) + " )" );
00379   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00380 
00381   // build mesh on domain extended by one along each axis
00382   NDIndex<Dim> domain = fl.getDomain();
00383   NDIndex<Dim> extended;
00384   for (int i=0; i<Dim; i++)
00385     extended[i] = Index(domain[i].first(), domain[i].last()+1,
00386                         domain[i].stride());
00387   FLayout = 0;
00388   theMesh = 0;
00389   Remote_ac = 0;
00390   store_mesh(new MeshType(extended), true);
00391   changeDomain(fl);
00392 }
00393 
00394 
00396 // Constructor which takes a FieldLayout and a Mesh
00397 template < class T, unsigned Dim, class MeshType >
00398 RegionLayout<T,Dim,MeshType>::RegionLayout(FieldLayout<Dim>& fl,
00399                                            MeshType& mesh) {
00400   TAU_TYPE_STRING(taustr, "void (" + CT(fl) + ", " + CT(mesh)  + " )" );
00401   TAU_PROFILE("RegionLayout::RegionLayout()", taustr, TAU_REGION);
00402 
00403   FLayout = 0;
00404   theMesh = 0;
00405   Remote_ac = 0;
00406   store_mesh(&mesh, false);
00407   changeDomain(fl);
00408 }
00409 
00410 
00412 // Reconstruct this RegionLayout from the given domain.  This clears
00413 // out the existing data, and generates a new partitioning.
00414 template < class T, unsigned Dim, class MeshType >
00415 void RegionLayout<T,Dim,MeshType>::changeDomain(const NDIndex<Dim>& domain,
00416                                                 int vnodes) {
00417   TAU_TYPE_STRING(taustr, "void (" + CT(domain) + ", int)");
00418   TAU_PROFILE("RegionLayout::changeDomain()", taustr, TAU_REGION);
00419 
00420   unsigned int d;                       // loop variable
00421 
00422   // delete our existing FieldLayout
00423   delete_flayout();
00424 
00425   // create a mesh, if necessary
00426   if (theMesh == 0) {
00427     NDIndex<Dim> ex;
00428     for (d=0; d < Dim; ++d)
00429       ex[d] = Index(domain[d].first(),domain[d].last()+1,domain[d].stride());
00430     store_mesh(new MeshType(ex), true);
00431   }
00432 
00433   // set our index space offset
00434   for (d=0; d < Dim; ++d) {
00435     IndexOffset[d] = domain[d].first();
00436     CenterOffset[d] = (MeshVertices[d].length() > domain[d].length());
00437   }
00438 
00439   // build the FieldLayout from this NDIndex ... note that
00440   // we're making our own FieldLayout here.  Creating this FieldLayout
00441   // results in a distribution of vnodes, which we will use for our rnodes.
00442   store_flayout(new FieldLayout<Dim>(domain, 0, vnodes), true);
00443 
00444   // save the region, and note that our domain matches the FieldLayout's,
00445   // so that there is no offset
00446   Domain = convert_index(FLayout->getDomain());
00447 
00448   // from the FieldLayout and Domain, build our internal representation
00449   make_rnodes(Domain, *FLayout);
00450   return;
00451 }
00452 
00453 
00455 // Reconstruct this RegionLayout from the given domain.  This clears
00456 // out the existing data, and generates a new partitioning.
00457 template < class T, unsigned Dim, class MeshType >
00458 void RegionLayout<T,Dim,MeshType>::changeDomain(const NDRegion<T,Dim>& domain,
00459                                                 int vnodes) {
00460   TAU_TYPE_STRING(taustr, "void (" + CT(domain) + ", int)");
00461   TAU_PROFILE("RegionLayout::changeDomain()", taustr, TAU_REGION);
00462 
00463   unsigned int d;                       // loop variable
00464 
00465   // delete our existing FieldLayout
00466   delete_flayout();
00467 
00468   // create a mesh, if necessary
00469   // right now, we assume that the current mesh is adequate, but 
00470   // we might have to pass a new one in or create one.
00471   PAssert(theMesh != 0);
00472 
00473   // set our index space and centering offsets
00474   for (d=0; d < Dim; ++d) {
00475     IndexOffset[d] = 0;
00476     CenterOffset[d] = true;  // make the internal FieldLayout cell-centered
00477   }
00478 
00479   // make an NDIndex based on the NDRegion & mesh
00480   NDIndex<Dim> area = convert_region(domain);
00481 
00482   // build the FieldLayout from this NDIndex ... note that
00483   // we're making our own FieldLayout here.  Creating this FieldLayout
00484   // results in a distribution of vnodes, which we will use for our rnodes.
00485   store_flayout(new FieldLayout<Dim>(area, 0, vnodes), true);
00486 
00487   // save the region, and note that our domain is offset from the FieldLayout's
00488   Domain = domain;
00489 
00490   // from the FieldLayout, build our internal representation
00491   make_rnodes(Domain, *FLayout);
00492   return;
00493 }
00494 
00495 
00497 // Reconstruct this RegionLayout from the given FieldLayout.  This
00498 // we just use the FieldLayout as-is, instead of making a new one.
00499 template < class T, unsigned Dim, class MeshType >
00500 void RegionLayout<T,Dim,MeshType>::changeDomain(FieldLayout<Dim>& fl) {
00501   TAU_TYPE_STRING(taustr, "void (" + CT(fl) + " )");
00502   TAU_PROFILE("RegionLayout::changeDomain()", taustr, TAU_REGION);
00503 
00504   unsigned int d;                       // loop variable
00505 
00506   // delete our existing FieldLayout
00507   delete_flayout();
00508 
00509   // create a mesh, if necessary
00510   if (theMesh == 0) {
00511     NDIndex<Dim> ex;
00512     const NDIndex<Dim>& domain(fl.getDomain());
00513     for (d=0; d < Dim; ++d)
00514       ex[d] = Index(domain[d].first(),domain[d].last()+1,domain[d].stride());
00515     store_mesh(new MeshType(ex), true);
00516   }
00517 
00518   // set our index space offset
00519   for (d=0; d < Dim; ++d) {
00520     IndexOffset[d] = fl.getDomain()[d].first();
00521     CenterOffset[d] = (theMesh->gridSizes[d] > fl.getDomain()[d].length());
00522   }
00523 
00524   // save this new layout, and set up our data structures
00525   Domain = convert_index(fl.getDomain());
00526   store_flayout(&fl, false);
00527   make_rnodes(Domain, *FLayout);
00528   return;
00529 }
00530 
00531 
00533 // convert a given NDIndex into an NDRegion ... if this object was
00534 // constructed from a FieldLayout, this does nothing, but if we are maintaining
00535 // our own internal FieldLayout, we must convert from the [0,N-1] index
00536 // space to our own continuous NDRegion space.
00537 // NOTE: THIS ASSUMES THAT REGION'S HAVE first() < last() !!
00538 template < class T, unsigned Dim, class MeshType >
00539 NDRegion<T,Dim>
00540 RegionLayout<T,Dim,MeshType>::convert_index(const NDIndex<Dim>& ni) const {
00541 
00542   NDRegion<T,Dim> new_pregion; // Needed in TAU_TYPE_STRING
00543 
00544   TAU_TYPE_STRING(taustr, CT(new_pregion) + " ("  + CT(ni) + " )");
00545   TAU_PROFILE("RegionLayout::convert_index()", taustr, TAU_REGION);
00546 
00547   int d;
00548 
00549   // find first and last points in NDIndex and get coordinates from mesh
00550   NDIndex<Dim> FirstPoint, LastPoint;
00551   for (d=0; d<Dim; d++) {
00552     int first = ni[d].first() - IndexOffset[d];
00553     int last  = ni[d].last()  - IndexOffset[d] + CenterOffset[d];
00554     FirstPoint[d] = Index(first, first);
00555     LastPoint[d] = Index(last, last);
00556   }
00557 
00558   // convert to mesh space
00559   Vektor<T,Dim> FirstCoord = theMesh->getVertexPosition(FirstPoint);
00560   Vektor<T,Dim> LastCoord = theMesh->getVertexPosition(LastPoint);
00561   for (d=0; d<Dim; d++) {
00562     if (!CenterOffset[d]) { // vertex centering, so offset region endpoints
00563       if ( !(FirstPoint[d] == Index(0,0)) ) {
00564         FirstPoint[d] = FirstPoint[d] - 1;
00565         FirstCoord = theMesh->getVertexPosition(FirstPoint);
00566         FirstCoord(d) = FirstCoord(d) +
00567                         0.5 * theMesh->getDeltaVertex(FirstPoint)(d);
00568       }
00569       int final = theMesh->gridSizes[d]-1; 
00570       if ( !(LastPoint[d] == Index(final,final)) )
00571         LastCoord(d) = LastCoord(d) +
00572                        0.5 * theMesh->getDeltaVertex(LastPoint)(d);
00573     }
00574 
00575     new_pregion[d] = PRegion<T>(FirstCoord(d), LastCoord(d));
00576   }
00577 
00578   return new_pregion;
00579 }
00580 
00581 
00583 // perform the inverse of convert_index: convert a given NDRegion (with
00584 // coordinates in the 'region' space) into an NDIndex (with values in
00585 // the [0,N-1] 'index' space).  This will truncate values when converting
00586 // from continuous to integer data.
00587 template < class T, unsigned Dim, class MeshType >
00588 NDIndex<Dim>
00589 RegionLayout<T,Dim,MeshType>::convert_region(const NDRegion<T,Dim>& nr) const {
00590   NDIndex<Dim> index;
00591   TAU_TYPE_STRING(taustr, CT(index) + " ("  + CT(nr) + " )");
00592   TAU_PROFILE("RegionLayout::convert_region()", taustr, TAU_REGION);
00593 
00594   unsigned d;
00595 
00596   // find mesh points corresponding to endpoints of region
00597   Vektor<T,Dim> FirstCoord, LastCoord;
00598   for (d=0; d<Dim; d++) {
00599     FirstCoord(d) = nr[d].first();
00600     LastCoord(d) = nr[d].last();
00601   }
00602   NDIndex<Dim> FirstPoint = theMesh->getNearestVertex(FirstCoord);
00603   NDIndex<Dim> LastPoint = theMesh->getNearestVertex(LastCoord);
00604   for (d=0; d<Dim; d++) {
00605     if (!CenterOffset[d]) { // vertex centering
00606       if (theMesh->getVertexPosition(FirstPoint)(d) < FirstCoord(d))
00607         FirstPoint[d] = FirstPoint[d] + 1;
00608       if (theMesh->getVertexPosition(LastPoint)(d) > LastCoord(d))
00609         LastPoint[d] = LastPoint[d] - 1;
00610     }
00611     index[d] = Index(FirstPoint[d].first() + IndexOffset[d],
00612                      LastPoint[d].first() + IndexOffset[d] - CenterOffset[d]);
00613   }
00614 
00615   return index;
00616 }
00617 
00618 #ifdef IPPL_USE_MEMBER_TEMPLATES
00619 
00620 //mwerks Moved into class definition (.h file).
00621 
00622 #endif
00623 
00625 // Scan through the internal FieldLayout and construct Rnodes based on
00626 // the current FieldLayout and PRegion.  Put them into out local
00627 // and remote Rnode containers.
00628 template < class T, unsigned Dim, class MeshType >
00629 void
00630 RegionLayout<T,Dim,MeshType>::make_rnodes(const NDRegion<T,Dim>& dom,
00631                                           FieldLayout<Dim>& FL) {
00632   TAU_TYPE_STRING(taustr, "void (" + CT(dom) + ", " + CT(FL) + " )");
00633   TAU_PROFILE("RegionLayout::make_rnodes()", taustr, TAU_REGION);
00634 
00635   //Inform dbgmsg("RegionLayout::make_rnodes");
00636   //dbgmsg << "Creating new rnodes based on FieldLayout = " << FL << endl;
00637 
00638   // delete the existing rnodes
00639   delete_rnodes();
00640 
00641   // for each local vnode in the FieldLayout, make a corresponding NDRegion
00642   // and put it in a local Rnode
00643   typedef typename ac_id_vnodes::value_type lrnode_t;
00644   typename FieldLayout<Dim>::iterator_iv lociter = FL.begin_iv();
00645   typename FieldLayout<Dim>::iterator_iv endloc  = FL.end_iv();
00646   for ( ; lociter != endloc; ++lociter) {
00647     Rnode<T,Dim> *rnode =
00648       StaticRnodePool.create_rnode(
00649                    convert_index((*((*lociter).second)).getDomain()),
00650                    (*((*lociter).second)).getNode());
00651 
00652     //dbgmsg << "  Created local rnode = " << rnode->getDomain();
00653     //dbgmsg << " from vnode = " << (*((*lociter).second)).getDomain() <<endl;
00654     
00655     Local_ac.insert( lrnode_t(Unique::get(), rnode) );
00656   }
00657 
00658   // similarly, for each remote vnode in the FieldLayout, make an Rnode
00659   Remote_ac = new ac_domain_vnodes(dom);
00660   typedef typename ac_domain_vnodes::value_type rrnode_t;
00661   typename FieldLayout<Dim>::iterator_dv remiter = FL.begin_rdv();
00662   typename FieldLayout<Dim>::iterator_dv endrem  = FL.end_rdv();
00663   for ( ; remiter != endrem; ++remiter) {
00664     Rnode<T,Dim> *rnode =
00665       StaticRnodePool.create_rnode(
00666                    convert_index((*((*remiter).second)).getDomain()),
00667                    (*((*remiter).second)).getNode());
00668 
00669     //dbgmsg << "  Created remote rnode = " << rnode->getDomain();
00670     //dbgmsg << " from vnode = " << (*((*remiter).second)).getDomain() <<endl;
00671     
00672     Remote_ac->insert( rrnode_t(rnode->getDomain(), rnode) );
00673   }
00674 
00675   // Since the rnodes changed, repartition each object using this
00676   // RegionLayout.  We have made sure only FieldLayoutUser's can
00677   // check in with us, so we know that all user's can be cast to
00678   // FieldLayoutUser.
00679   for (iterator_user p = begin_user(); p != end_user(); ++p) {
00680 #ifndef IPPL_KAI
00681     FieldLayoutUser *user = dynamic_cast<FieldLayoutUser *>((*p).second);
00682 #else
00683     // minor hack to work around RTTI bug in KCC 3.2; use C-style cast
00684     FieldLayoutUser *user = (FieldLayoutUser *) (*p).second;
00685 #endif
00686     user->Repartition(this);
00687   }
00688 }
00689 
00690 
00692 // Delete the Rnodes in the given local and remote lists ... actually,
00693 // just returns them back to the static pool.  Note that this DOES NOT
00694 // remove the elements from the lists.
00695 template < class T, unsigned Dim, class MeshType >
00696 void RegionLayout<T,Dim,MeshType>::delete_rnodes() {
00697   TAU_TYPE_STRING(taustr, "void ()");
00698   TAU_PROFILE("RegionLayout::delete_rnodes()", taustr, TAU_REGION);
00699 
00700   // delete local rnodes
00701   typename ac_id_vnodes::iterator lociter = Local_ac.begin();
00702   typename ac_id_vnodes::iterator endloc  = Local_ac.end();
00703   for ( ; lociter != endloc; ++lociter)
00704     StaticRnodePool.push_back((*lociter).second);
00705   Local_ac.erase(Local_ac.begin(), Local_ac.end());
00706 
00707   // delete remote rnodes
00708   if (Remote_ac != 0) {
00709     typename ac_domain_vnodes::iterator remiter = Remote_ac->begin();
00710     typename ac_domain_vnodes::iterator endrem  = Remote_ac->end();
00711     for ( ; remiter != endrem; ++remiter)
00712       StaticRnodePool.push_back((*remiter).second);
00713     delete Remote_ac;
00714     Remote_ac = 0;
00715   }
00716 }
00717 
00718 
00720 // Store a FieldLayout pointer, and note if we own it or not.
00721 template < class T, unsigned Dim, class MeshType >
00722 void RegionLayout<T,Dim,MeshType>::store_flayout(FieldLayout<Dim>* f,
00723                                                  bool WeOwn) {
00724   TAU_TYPE_STRING(taustr, "void (" + CT(f) + ", bool)");
00725   TAU_PROFILE("RegionLayout::store_flayout()", taustr, TAU_REGION);
00726 
00727   // get rid of the existing layout, if necessary
00728   delete_flayout();
00729 
00730   // save the pointer, and whether we own it.  Also, check in to the
00731   // layout
00732   FLayout = f;
00733   WeOwnFieldLayout = WeOwn;
00734   if (FLayout != 0)
00735     FLayout->checkin(*this);
00736 }
00737 
00738 
00740 // Delete our current FLayout, and set it to NULL; we may have to
00741 // check out from the layout
00742 template < class T, unsigned Dim, class MeshType >
00743 void RegionLayout<T,Dim,MeshType>::delete_flayout() {
00744   TAU_PROFILE("RegionLayout::delete_flayout()", "void ()", TAU_REGION);
00745   if (FLayout != 0) {
00746     FLayout->checkout(*this);
00747     if (WeOwnFieldLayout)
00748       delete FLayout;
00749     FLayout = 0;
00750   }
00751 }
00752 
00753 
00755 // Store a Mesh pointer, and note if we own it or not.
00756 template < class T, unsigned Dim, class MeshType >
00757 void RegionLayout<T,Dim,MeshType>::store_mesh(MeshType* m, bool WeOwn) {
00758   TAU_TYPE_STRING(taustr, "void (" + CT(m) + ", bool)"); 
00759   TAU_PROFILE("RegionLayout::store_mesh()", taustr, TAU_REGION);
00760 
00761   // get rid of the existing mesh, if necessary
00762   delete_mesh();
00763 
00764   // save the pointer, and whether we own it.  Also, check in to the
00765   // layout
00766   theMesh = m;
00767   WeOwnMesh = WeOwn;
00768   if (theMesh != 0) {
00769     theMesh->checkin(*this);
00770     for (int d=0; d < Dim; ++d)
00771       MeshVertices[d] = Index(theMesh->gridSizes[d]);
00772   }
00773 }
00774 
00775 
00777 // Delete our current MeshType, and set it to NULL; we may have to
00778 // check out from the mesh
00779 template < class T, unsigned Dim, class MeshType >
00780 void RegionLayout<T,Dim,MeshType>::delete_mesh() {
00781   TAU_PROFILE("RegionLayout::delete_mesh()", "void ()", TAU_REGION);
00782   
00783   if (theMesh != 0) {
00784     theMesh->checkout(*this);
00785     if (WeOwnMesh)
00786       delete theMesh;
00787     theMesh = 0;
00788   }
00789 }
00790 
00791 
00793 // calculate the boundary region of the given mesh object
00794 template < class T, unsigned Dim, class MeshType >
00795 NDRegion<T,Dim> RegionLayout<T,Dim,MeshType>::getMeshDomain(MeshType *m) {
00796   NDRegion<T,Dim> retDomain;
00797 
00798   TAU_TYPE_STRING(taustr, CT(retDomain) + " (" + CT(m) + " )");
00799   TAU_PROFILE("RegionLayout::getMeshDomain()", taustr, TAU_REGION);
00800 
00801   typename MeshType::MeshVektor_t morigin  = m->get_origin();
00802   NDIndex<Dim> meshCells;
00803   int d;
00804   for (d=0; d < Dim; ++d)
00805     meshCells[d] = Index(MeshVertices[d].first(),MeshVertices[d].last()-1);
00806   typename MeshType::MeshVektor_t msize    = m->getDeltaVertex(meshCells);
00807   for (d=0; d < Dim; ++d)
00808     retDomain[d] = PRegion<T>(morigin[d], morigin[d] + msize[d]);
00809   return retDomain;
00810 }
00811 
00812 
00814 // calculate the number of vertices in the given mesh
00815 template < class T, unsigned Dim, class MeshType >
00816 NDIndex<Dim> RegionLayout<T,Dim,MeshType>::getMeshVertices(MeshType *m) {
00817   NDIndex<Dim> mvertices;
00818 
00819   TAU_TYPE_STRING(taustr, CT(mvertices) + " (" + CT(m) + " )" );
00820   TAU_PROFILE("RegionLayout::getMeshVertices()", taustr, TAU_REGION);
00821 
00822   for (int d=0; d < Dim; ++d)
00823     mvertices[d] = Index(m->gridSizes[d]);
00824   return mvertices;
00825 }
00826 
00827 
00829 // output
00830 template < class T, unsigned Dim, class MeshType >
00831 ostream& operator<<(ostream& out, const RegionLayout<T,Dim,MeshType>& f) {
00832   TAU_TYPE_STRING(taustr, "ostream ( ostream, " + CT(f) + " )");
00833   TAU_PROFILE("operator<<()", taustr, TAU_REGION | TAU_IO);
00834  
00835   int icount;
00836 
00837   // the whole domain
00838   out << "Total Domain = " << f.getDomain() << "\n";
00839 
00840   // iterate over the local vnodes and print them out.
00841   out << "Local Rnodes = " << f.size_iv() << "\n";
00842   typename RegionLayout<T,Dim,MeshType>::const_iterator_iv v_i = f.begin_iv();
00843   typename RegionLayout<T,Dim,MeshType>::const_iterator_iv v_e = f.end_iv();
00844   for(icount=0 ; v_i != v_e; ++v_i, ++icount)
00845     out << " rnode " << icount << " : " << (*v_i).second->getDomain() << "\n";
00846 
00847   // iterate over the remote vnodes and print them out.
00848   out << "Remote Rnodes = " << f.size_rdv() << "\n";
00849   if (f.size_rdv() > 0) {
00850     typename RegionLayout<T,Dim,MeshType>::const_iterator_dv dv_i = f.begin_rdv();
00851     typename RegionLayout<T,Dim,MeshType>::const_iterator_dv dv_e = f.end_rdv();
00852     for (icount=0 ; dv_i != dv_e; ++dv_i, ++icount)
00853       out << " rnode " << icount << " : " << (*dv_i).first << "\n";
00854   }
00855 
00856   // print out our internal FieldLayout
00857   out << "Internal FieldLayout = " << f.getFieldLayout();
00858 
00859   return out;
00860 }
00861 
00862 
00864 // Repartition the region, from a list of NDIndex objects which
00865 // represent our local domain.  This assumes two things:
00866 //   1. We are repartitioning the same global domain, just in a different
00867 //      way.  Thus, the encompassing NDRegion 'Domain' does not change.
00868 //   2. The NDIndex objects cover a domain which corresponds to our
00869 //      internal FieldLayout domain.  This may or may not directly
00870 //      overlap with the NDRegion domain.  The basic point is that with
00871 //      these NDIndex objects, we can replace the FieldLayout directly,
00872 //      and then regenerate our RegionLayout (Rnode) data.
00873 template < class T, unsigned Dim, class MeshType >
00874 void RegionLayout<T,Dim,MeshType>::RepartitionLayout(NDIndex<Dim>* ni,
00875                                                      NDIndex<Dim>* nf) {
00876   TAU_TYPE_STRING(taustr, "void (" + CT(ni) + ", " + CT(nf) + " )");
00877   TAU_PROFILE("RegionLayout::RepartitionLayout()", taustr, TAU_REGION);
00878 
00879   // repartition the FieldLayout, using the given list of local vnodes.  This
00880   // call will result in a distribution of the data to all the nodes.  Also,
00881   // as part of the Repartition process the FieldLayout will tell us to
00882   // recreate out rnodes by calling RegionLayout::Repartition.
00883   if (FLayout != 0)
00884     FLayout->Repartition(ni, nf);
00885 }
00886 
00887 
00889 // Repartition onto a new layout, if the layout changes ... this is a
00890 // virtual function called by a UserList, as opposed to the RepartitionLayout
00891 // function used by the particle load balancing mechanism.
00892 template < class T, unsigned Dim, class MeshType >
00893 void RegionLayout<T,Dim,MeshType>::Repartition(UserList* userlist) {
00894   TAU_TYPE_STRING(taustr, "void (" + CT(userlist) + " )");
00895   TAU_PROFILE("RegionLayout::Repartition()", taustr, TAU_REGION);
00896 
00897   if (theMesh != 0 && userlist->getUserListID() == theMesh->get_Id()) {
00898     // perform actions to restructure our data due to a change in the
00899     // mesh
00900 
00901     //Inform dbgmsg("RegionLayout::Repartition");
00902     //dbgmsg << "Repartitioning RegionLayout due to mesh change ..." << endl;
00903 
00904     // have the number of mesh points changed?
00905     NDIndex<Dim> mvertices(getMeshVertices(theMesh));
00906     if (!(mvertices == MeshVertices)) {
00907       // yes they have ... we must reconstruct everything, including
00908       // our FieldLayout.
00909       MeshVertices = mvertices;
00910       if (WeOwnFieldLayout)
00911         changeDomain(getMeshDomain(theMesh), size_iv() + size_rdv());
00912       else
00913         changeDomain(*FLayout);
00914     } else {
00915       // since we have the same number of vertices, the layout has not
00916       // changed, only the size of the rnodes and the total domain.
00917       Domain = getMeshDomain(theMesh);
00918       make_rnodes(Domain, *FLayout);
00919     }
00920 
00921   } else {
00922 
00923     //Inform dbgmsg("RegionLayout::Repartition");
00924     //dbgmsg << "Repartitioning RegionLayout due to layout change ..." << endl;
00925 
00926     // Must be a FieldLayout change instead, so,
00927     // create new rnodes based on the vnodes in this layout.  Since this
00928     // is called by the FieldLayout we are using, there is no need to
00929     // change our FLayout pointer.
00930     FieldLayout<Dim>* newLayout = (FieldLayout<Dim>*)( userlist );
00931     make_rnodes(Domain, *newLayout);
00932   }
00933 }
00934 
00935 
00937 // Tell the subclass that the FieldLayoutBase is being deleted, so
00938 // don't use it anymore
00939 template < class T, unsigned Dim, class MeshType >
00940 void RegionLayout<T,Dim,MeshType>::notifyUserOfDelete(UserList* userlist) {
00941   TAU_TYPE_STRING(taustr, "void (" + CT(userlist) + " )");
00942   TAU_PROFILE("RegionLayout::notifyUserOfDelete()", taustr, TAU_REGION);
00943 
00944   if (FLayout != 0 && FLayout->get_Id() == userlist->getUserListID()) {
00945     // set our FieldLayout pointer to null, if it matches the given userlist.
00946     // This may render this RegionLayout instance useless,
00947     // so this should be followed only by a call to the destructor of
00948     // RegionLayout.
00949     FLayout = 0;
00950 
00951   } else if (theMesh != 0 && userlist->getUserListID() == theMesh->get_Id()) {
00952     // set our mesh pointer to null, if it matches the given userlist.
00953     // This may render this RegionLayout instance useless,
00954     // so this should be followed only by a call to the destructor of
00955     // RegionLayout.
00956     theMesh = 0;
00957 
00958   } else {
00959     // for now, print a warning ... but in general, this is OK and this
00960     // warning should be removed
00961     WARNMSG("RegionLayout: notified of unknown UserList being deleted.");
00962   }
00963 }
00964 
00965 
00966 /***************************************************************************
00967  * $RCSfile: RegionLayout.cpp,v $   $Author: adelmann $
00968  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:32 $
00969  * IPPL_VERSION_ID: $Id: RegionLayout.cpp,v 1.1.1.1 2003/01/23 07:40:32 adelmann Exp $ 
00970  ***************************************************************************/

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