src/FieldLayout/FieldLayout.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 "FieldLayout/FieldLayout.h"
00028 #include "FieldLayout/VRB.h"
00029 #include "Message/Communicate.h"
00030 #include "Message/Message.h"
00031 #include "Utility/DiscMeta.h"
00032 #include "Utility/IpplInfo.h"
00033 #include "Utility/IpplStats.h"
00034 #include "Utility/PAssert.h"
00035 #include "Profile/Profiler.h"
00036 
00037 #include <stdlib.h>
00038 
00039 
00041 // Default constructor, which should only be used if you are going to
00042 // call 'initialize' soon after (before using in any context)
00043 template<unsigned Dim>
00044 FieldLayout<Dim>::FieldLayout() {
00045   TAU_TYPE_STRING(taustr, "void ()");
00046   TAU_PROFILE("FieldLayout::FieldLayout()", taustr, TAU_LAYOUT);
00047 
00048   // we have one more FieldLayout, indicate this
00049   //INCIPPLSTAT(incFieldLayouts);
00050 
00051   // just initialize basic things
00052   vnodesPerDirection_m = 0;
00053 
00054   // for this kind of construction, we just take it that the user is
00055   // requesting all parallel axes
00056   for (int dl=0; dl < Dim; ++dl) RequestedLayout[dl] = PARALLEL;
00057 }
00058 
00059 
00061 // Constructor which reads in FieldLayout data from a file.  If the
00062 // file contains data for an equal number of nodes as we are running on,
00063 // then that vnode -> pnode mapping will be used.  If the file does not
00064 // contain info for the same number of pnodes, the vnodes will be
00065 // distributed in some other manner.
00066 template<unsigned Dim>
00067 FieldLayout<Dim>::FieldLayout(const char *filename) {
00068   TAU_TYPE_STRING(taustr, "void (const char *)");
00069   TAU_PROFILE("FieldLayout::FieldLayout()", taustr, TAU_LAYOUT);
00070 
00071   // we have one more FieldLayout, indicate this
00072   //INCIPPLSTAT(incFieldLayouts);
00073 
00074   // try to initialize ourselves, by reading the info from the file.
00075   vnodesPerDirection_m = 0;
00076 
00077   // for this kind of construction, we just take it that the user is
00078   // requesting all parallel axes
00079   for (int dl=0; dl < Dim; ++dl) RequestedLayout[dl] = PARALLEL;
00080 
00081   // read in data from file
00082   read(filename);
00083 }
00084 
00085 
00087 // Destructor: Everything deletes itself automatically ... the base
00088 // class destructors inform all the FieldLayoutUser's we're going away.
00089 template<unsigned Dim>
00090 FieldLayout<Dim>::~FieldLayout() {
00091   if (vnodesPerDirection_m != 0)
00092     delete [] vnodesPerDirection_m;
00093 }
00094 
00095 
00097 
00098 // Initialization functions, only to be called by the user of FieldLayout
00099 // objects when the FieldLayout was created using the default constructor;
00100 // otherwise these are only called internally by the various non-default
00101 // FieldLayout constructors:
00102 
00103 //-----------------------------------------------------------------------------
00104 // These specify only a total number of vnodes, allowing the constructor
00105 // complete control on how to do the vnode partitioning of the index space:
00106 
00107 template<unsigned Dim>
00108 void
00109 FieldLayout<Dim>::initialize(const NDIndex<Dim>& domain,
00110                              e_dim_tag *p, int vnodes) {
00111   TAU_TYPE_STRING(taustr, "void (" + CT(domain) + ", e_dim_tag*, int)");
00112   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00113   setup(domain, p, vnodes);
00114 }
00115 
00116 
00117 template<unsigned Dim>
00118 void
00119 FieldLayout<Dim>::initialize(const Index& i1, e_dim_tag p1, int vnodes) {
00120   TAU_TYPE_STRING(taustr, "void (Index, e_dim_tag, int)");
00121   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00122 
00123   PInsist(Dim==1,
00124           "Number of arguments does not match dimension of FieldLayout!!");
00125   NDIndex<Dim> ndi(i1);
00126   setup(ndi,&p1,vnodes);
00127 }
00128 
00129 template<unsigned Dim>
00130 void
00131 FieldLayout<Dim>::initialize(const Index& i1, const Index& i2,
00132                              e_dim_tag p1, e_dim_tag p2, int vnodes) {
00133   TAU_TYPE_STRING(taustr, "void (Index, Index, e_dim_tag, e_dim_tag, int)");
00134   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00135 
00136   PInsist(Dim==2,
00137           "Number of arguments does not match dimension of FieldLayout!!");
00138   e_dim_tag par[Dim];
00139   par[0] = p1;
00140   par[1] = p2;
00141   NDIndex<Dim> ndi;
00142   ndi[0] = i1;
00143   ndi[1] = i2;
00144   setup(ndi,par,vnodes);
00145 }
00146 template<unsigned Dim>
00147 void
00148 FieldLayout<Dim>::initialize(const Index& i1, const Index& i2, const Index& i3,
00149                              e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00150                              int vnodes) {
00151   TAU_TYPE_STRING(taustr, string("void (Index, Index, Index,") +
00152                   string(" e_dim_tag, e_dim_tag, e_dim_tag, int)"));
00153   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00154 
00155   PInsist(Dim==3,
00156           "Number of arguments does not match dimension of FieldLayout!!");
00157   e_dim_tag par[Dim];
00158   par[0] = p1;
00159   par[1] = p2;
00160   par[2] = p3;
00161   NDIndex<Dim> ndi;
00162   ndi[0] = i1;
00163   ndi[1] = i2;
00164   ndi[2] = i3;
00165   setup(ndi,par,vnodes);
00166 }
00167 template<unsigned Dim>
00168 void
00169 FieldLayout<Dim>::initialize(const Index& i1, const Index& i2, const Index& i3,
00170                              const Index& i4,
00171                              e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00172                              e_dim_tag p4,
00173                              int vnodes) {
00174   TAU_TYPE_STRING(taustr, string("void (Index, Index, Index, Index,") +
00175                   string(" e_dim_tag, e_dim_tag, e_dim_tag, e_dim_tag, int)"));
00176   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00177 
00178   PInsist(Dim==4,
00179           "Number of arguments does not match dimension of FieldLayout!!");
00180   e_dim_tag par[Dim];
00181   par[0] = p1;
00182   par[1] = p2;
00183   par[2] = p3;
00184   par[3] = p4;
00185   NDIndex<Dim> ndi;
00186   ndi[0] = i1;
00187   ndi[1] = i2;
00188   ndi[2] = i3;
00189   ndi[3] = i4;
00190   setup(ndi,par,vnodes);
00191 }
00192 template<unsigned Dim>
00193 void
00194 FieldLayout<Dim>::initialize(const Index& i1, const Index& i2, const Index& i3,
00195                              const Index& i4, const Index& i5,
00196                              e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00197                              e_dim_tag p4, e_dim_tag p5,
00198                              int vnodes) {
00199   TAU_TYPE_STRING(taustr, string("void (Index, Index, Index, Index, Index,") +
00200                   string(" e_dim_tag, e_dim_tag, e_dim_tag, e_dim_tag,") +
00201                   string(" e_dim_tag, int)"));
00202   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00203 
00204   PInsist(Dim==5,
00205           "Number of arguments does not match dimension of FieldLayout!!");
00206   e_dim_tag par[Dim];
00207   par[0] = p1;
00208   par[1] = p2;
00209   par[2] = p3;
00210   par[3] = p4;
00211   par[4] = p5;
00212   NDIndex<Dim> ndi;
00213   ndi[0] = i1;
00214   ndi[1] = i2;
00215   ndi[2] = i3;
00216   ndi[3] = i4;
00217   ndi[4] = i5;
00218   setup(ndi,par,vnodes);
00219 }
00220 template<unsigned Dim>
00221 void
00222 FieldLayout<Dim>::initialize(const Index& i1, const Index& i2, const Index& i3,
00223                              const Index& i4, const Index& i5, const Index& i6,
00224                              e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00225                              e_dim_tag p4, e_dim_tag p5, e_dim_tag p6,
00226                              int vnodes) {
00227   TAU_TYPE_STRING(taustr, string("void (Index, Index, Index, Index, Index,") +
00228                   string(" Index, e_dim_tag, e_dim_tag, e_dim_tag,") +
00229                   string(" e_dim_tag, e_dim_tag, e_dim_tag, int)"));
00230   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00231 
00232   PInsist(Dim==6,
00233           "Number of arguments does not match dimension of FieldLayout!!");
00234   e_dim_tag par[Dim];
00235   par[0] = p1;
00236   par[1] = p2;
00237   par[2] = p3;
00238   par[3] = p4;
00239   par[4] = p5;
00240   par[5] = p6;
00241   NDIndex<Dim> ndi;
00242   ndi[0] = i1;
00243   ndi[1] = i2;
00244   ndi[2] = i3;
00245   ndi[3] = i4;
00246   ndi[4] = i5;
00247   ndi[5] = i6;
00248   setup(ndi,par,vnodes);
00249 }
00250 //-----------------------------------------------------------------------------
00251 
00252 //-----------------------------------------------------------------------------
00253 // These specify both the total number of vnodes and the numbers of vnodes
00254 // along each dimension for the partitioning of the index space. Obviously
00255 // this restricts the number of vnodes to be a product of the numbers along
00256 // each dimension (the constructor implementation checks this):
00257 
00258 template<unsigned Dim>
00259 void
00260 FieldLayout<Dim>::initialize(const NDIndex<Dim>& domain,
00261                              e_dim_tag *p, unsigned* vnodesPerDirection,
00262                              bool recurse, int vnodes) {
00263   TAU_TYPE_STRING(taustr, "void (" + CT(domain) +
00264                   ", e_dim_tag*, unsigned*, bool, int)");
00265   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00266 
00267   // Default to correct total vnodes:
00268   unsigned vnodesProduct = 1;
00269   for (int d=0; d<Dim; d++) vnodesProduct *= vnodesPerDirection[d];
00270   if (vnodes == -1) vnodes = vnodesProduct;
00271   // Verify than total vnodes is product of per-dimension vnode counts:
00272   if (vnodes != vnodesProduct) {
00273     ERRORMSG("FieldLayout constructor: "
00274             << "(vnodes != vnodesPerDirection[0]*vnodesPerDirection[1]*"
00275             << "...*vnodesPerDirection[" << Dim-1 << "])"
00276             << " ; vnodesPerDirection[0]*vnodesPerDirection[1]*"
00277             << "...*vnodesPerDirection[" << Dim-1 << "] = " 
00278             << vnodesProduct << " ; vnodes = " << vnodes << endl);
00279   }
00280   setup(domain, p, vnodesPerDirection,recurse,vnodes);
00281 }
00282 
00283 template<unsigned Dim>
00284 void
00285 FieldLayout<Dim>::initialize(const Index& i1, e_dim_tag p1, 
00286                              unsigned vnodes1, bool recurse, int vnodes) {
00287   TAU_TYPE_STRING(taustr, "void (Index, e_dim_tag, unsigned, bool, int)");
00288   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00289 
00290   PInsist(Dim==1,
00291           "Number of arguments does not match dimension of FieldLayout!!");
00292   NDIndex<Dim> ndi(i1);
00293   setup(ndi,&p1,&vnodes1,recurse,vnodes);
00294 }
00295 
00296 template<unsigned Dim>
00297 void
00298 FieldLayout<Dim>::initialize(const Index& i1, const Index& i2,
00299                              e_dim_tag p1, e_dim_tag p2, 
00300                              unsigned vnodes1, unsigned vnodes2, 
00301                              bool recurse, int vnodes) {
00302   TAU_TYPE_STRING(taustr, string("void (Index, Index, e_dim_tag, e_dim_tag,") +
00303                   string(" unsigned, unsigned, bool, int)"));
00304   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00305 
00306   PInsist(Dim==2,
00307           "Number of arguments does not match dimension of FieldLayout!!");
00308   e_dim_tag par[Dim];
00309   par[0] = p1;
00310   par[1] = p2;
00311   NDIndex<Dim> ndi;
00312   ndi[0] = i1;
00313   ndi[1] = i2;
00314   unsigned vnodesPerDirection[Dim];
00315   vnodesPerDirection[0] = vnodes1;
00316   vnodesPerDirection[1] = vnodes2;
00317   setup(ndi,par,vnodesPerDirection,recurse,vnodes);
00318 }
00319 template<unsigned Dim>
00320 void
00321 FieldLayout<Dim>::initialize(const Index& i1, const Index& i2, const Index& i3,
00322                              e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00323                              unsigned vnodes1, unsigned vnodes2, 
00324                              unsigned vnodes3, 
00325                              bool recurse, int vnodes) {
00326   TAU_TYPE_STRING(taustr, string("void (Index, Index, Index, e_dim_tag,") +
00327                   string(" e_dim_tag, e_dim_tag, unsigned, unsigned,") +
00328                   string(" unsigned, bool, int)"));
00329   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00330 
00331   PInsist(Dim==3,
00332           "Number of arguments does not match dimension of FieldLayout!!");
00333   e_dim_tag par[Dim];
00334   par[0] = p1;
00335   par[1] = p2;
00336   par[2] = p3;
00337   NDIndex<Dim> ndi;
00338   ndi[0] = i1;
00339   ndi[1] = i2;
00340   ndi[2] = i3;
00341   unsigned vnodesPerDirection[Dim];
00342   vnodesPerDirection[0] = vnodes1;
00343   vnodesPerDirection[1] = vnodes2;
00344   vnodesPerDirection[2] = vnodes3;
00345   setup(ndi,par,vnodesPerDirection,recurse,vnodes);
00346 }
00347 template<unsigned Dim>
00348 void
00349 FieldLayout<Dim>::initialize(const Index& i1, const Index& i2, const Index& i3,
00350                              const Index& i4,
00351                              e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00352                              e_dim_tag p4,
00353                              unsigned vnodes1, unsigned vnodes2, 
00354                              unsigned vnodes3, unsigned vnodes4, 
00355                              bool recurse, int vnodes) {
00356   TAU_TYPE_STRING(taustr, string("void (Index, Index, Index, Index,") +
00357                   string(" e_dim_tag, e_dim_tag, e_dim_tag, e_dim_tag,") +
00358                   string(" unsigned, unsigned, unsigned, unsigned, bool,") +
00359                   string(" int)"));
00360   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00361 
00362   PInsist(Dim==4,
00363           "Number of arguments does not match dimension of FieldLayout!!");
00364   e_dim_tag par[Dim];
00365   par[0] = p1;
00366   par[1] = p2;
00367   par[2] = p3;
00368   par[3] = p4;
00369   NDIndex<Dim> ndi;
00370   ndi[0] = i1;
00371   ndi[1] = i2;
00372   ndi[2] = i3;
00373   ndi[3] = i4;
00374   unsigned vnodesPerDirection[Dim];
00375   vnodesPerDirection[0] = vnodes1;
00376   vnodesPerDirection[1] = vnodes2;
00377   vnodesPerDirection[2] = vnodes3;
00378   vnodesPerDirection[3] = vnodes4;
00379   setup(ndi,par,vnodesPerDirection,recurse,vnodes);
00380 }
00381 template<unsigned Dim>
00382 void
00383 FieldLayout<Dim>::initialize(const Index& i1, const Index& i2, const Index& i3,
00384                              const Index& i4, const Index& i5,
00385                              e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00386                              e_dim_tag p4, e_dim_tag p5,
00387                              unsigned vnodes1, unsigned vnodes2, 
00388                              unsigned vnodes3, unsigned vnodes4, 
00389                              unsigned vnodes5, 
00390                              bool recurse, int vnodes) {
00391   TAU_TYPE_STRING(taustr, string("void (Index, Index, Index, Index, Index,") +
00392                   string(" e_dim_tag, e_dim_tag, e_dim_tag, e_dim_tag,") +
00393                   string(" e_dim_tag, unsigned, unsigned, unsigned,") +
00394                   string(" unsigned, unsigned, bool, int)"));
00395   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00396 
00397   PInsist(Dim==5,
00398           "Number of arguments does not match dimension of FieldLayout!!");
00399   e_dim_tag par[Dim];
00400   par[0] = p1;
00401   par[1] = p2;
00402   par[2] = p3;
00403   par[3] = p4;
00404   par[4] = p5;
00405   NDIndex<Dim> ndi;
00406   ndi[0] = i1;
00407   ndi[1] = i2;
00408   ndi[2] = i3;
00409   ndi[3] = i4;
00410   ndi[4] = i5;
00411   unsigned vnodesPerDirection[Dim];
00412   vnodesPerDirection[0] = vnodes1;
00413   vnodesPerDirection[1] = vnodes2;
00414   vnodesPerDirection[2] = vnodes3;
00415   vnodesPerDirection[3] = vnodes4;
00416   vnodesPerDirection[4] = vnodes5;
00417   setup(ndi,par,vnodesPerDirection,recurse,vnodes);
00418 }
00419 template<unsigned Dim>
00420 void
00421 FieldLayout<Dim>::initialize(const Index& i1, const Index& i2, const Index& i3,
00422                              const Index& i4, const Index& i5, const Index& i6,
00423                              e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00424                              e_dim_tag p4, e_dim_tag p5, e_dim_tag p6,
00425                              unsigned vnodes1, unsigned vnodes2, 
00426                              unsigned vnodes3, unsigned vnodes4, 
00427                              unsigned vnodes5, unsigned vnodes6, 
00428                              bool recurse, int vnodes) {
00429   TAU_TYPE_STRING(taustr, string("void (Index, Index, Index, Index, Index,") +
00430                   string(" Index, e_dim_tag, e_dim_tag, e_dim_tag,") +
00431                   string(" e_dim_tag, e_dim_tag, e_dim_tag, unsigned,") +
00432                   string(" unsigned, unsigned, unsigned, unsigned,") +
00433                   string(" unsigned, bool, int)"));
00434   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00435 
00436   PInsist(Dim==6,
00437           "Number of arguments does not match dimension of FieldLayout!!");
00438   e_dim_tag par[Dim];
00439   par[0] = p1;
00440   par[1] = p2;
00441   par[2] = p3;
00442   par[3] = p4;
00443   par[4] = p5;
00444   par[5] = p6;
00445   NDIndex<Dim> ndi;
00446   ndi[0] = i1;
00447   ndi[1] = i2;
00448   ndi[2] = i3;
00449   ndi[3] = i4;
00450   ndi[4] = i5;
00451   ndi[5] = i6;
00452   unsigned vnodesPerDirection[Dim];
00453   vnodesPerDirection[0] = vnodes1;
00454   vnodesPerDirection[1] = vnodes2;
00455   vnodesPerDirection[2] = vnodes3;
00456   vnodesPerDirection[3] = vnodes4;
00457   vnodesPerDirection[4] = vnodes5;
00458   vnodesPerDirection[5] = vnodes6;
00459   setup(ndi,par,vnodesPerDirection,recurse,vnodes);
00460 }
00461 //-----------------------------------------------------------------------------
00462 
00463 
00464 //-----------------------------------------------------------------------------
00465 // A version of initialize that takes the total domain, and iterators
00466 // over the subdomains the user wants along with iterators over the
00467 // node assignments.  No communication is done
00468 // so these lists must match on all nodes.  A bit of error checking
00469 // is done for overlapping blocks and illegal nodes, but not exhaustive
00470 // error checking.
00471 
00472 template<unsigned Dim>
00473 void
00474 FieldLayout<Dim>::initialize(const NDIndex<Dim> &domain,
00475                              const NDIndex<Dim> *dombegin,
00476                              const NDIndex<Dim> *domend,
00477                              const int *nbegin, const int *nend)
00478 {
00479   TAU_TYPE_STRING(taustr, string("void (NDIndex, NDIndex *, NDIndex *,") +
00480                   string(" int *, int *)"));
00481   TAU_PROFILE("FieldLayout::initialize()", taustr, TAU_LAYOUT);
00482 
00483   // Loop variables
00484   int i, j, d;
00485 
00486   // Save the total domain.
00487   Domain = domain;
00488 
00489   // Find the number of vnodes requested
00490   int vnodes = (nend - nbegin);
00491   PInsist(vnodes > 0,
00492           "A user-specified FieldLayout must have at least one vnode.");
00493   PInsist(vnodes == (domend - dombegin),
00494           "A user-specified FieldLayout must have equal length node and domain lists");
00495 
00496   // Since we don't know any differently, indicate the requested
00497   // layout is all parallel
00498   for (d = 0; d < Dim; ++d)
00499     RequestedLayout[d] = PARALLEL;
00500 
00501   // This is not a grid-like layout, so set the pointer for this to 0
00502   vnodesPerDirection_m = 0;
00503 
00504   // Create the empty remote vnode list
00505   ac_domain_vnodes *remote_ac = new ac_domain_vnodes(domain);
00506   typedef typename ac_gc_domain_vnodes::value_type vntype;
00507   Remotes_ac.insert( vntype(gc0(), remote_ac) );
00508 
00509   // Loop through the vnodes, and add them to our local or remote lists.
00510   // Do a sanity check on the vnodes, making sure each one does not
00511   // intersect any other.  Also, add up the size of each vnode, if it
00512   // does not equal the size of the total domain, there are holes
00513   // and it is an error.
00514   int coverage = 0;
00515   for (i = 0; i < vnodes; ++i) {
00516     // Compare to other vnodes
00517     for (j = (i+1); j < vnodes; ++j) {
00518       PInsist(! (dombegin[i].touches(dombegin[j])),
00519               "A user-specified FieldLayout cannot have overlapping domains.");
00520     }
00521 
00522     // Make sure the processor ID is OK
00523     PInsist(nbegin[i] >= 0 && nbegin[i] < Ippl::getNodes(),
00524             "A user-specified FieldLayout must have legal node assignments.");
00525 
00526     // Add in the volume of this domain
00527     coverage += dombegin[i].size();
00528 
00529     // Create a Vnode for this domain
00530     Vnode<Dim> *vnode = new Vnode<Dim>(dombegin[i], nbegin[i], i);
00531     typedef typename ac_id_vnodes::value_type v1;
00532     typedef typename ac_domain_vnodes::value_type v2;
00533     bool nosplit = (dombegin[i].size() < 2);
00534 
00535     // Based on the assigned node, add to our local or remote lists
00536     if (nbegin[i] == Ippl::myNode())
00537       Local_ac.insert(v1(Unique::get(), vnode));
00538     else
00539       remote_ac->insert(v2(dombegin[i], vnode), nosplit);
00540   }
00541 
00542   // Check the coverage, make sure it is complete
00543   PInsist(coverage == domain.size(),
00544           "A user-specified FieldLayout must completely cover the domain.");
00545 
00546   // At the end, calculate the widthds of all the vnodes
00547   calcWidths();
00548 }
00549 
00550 
00552 
00553 //
00554 // Now, the meat of the construction.
00555 //
00556 
00557 //-----------------------------------------------------------------------------
00558 //This setup() specifies only a total number of vnodes, taking complete control
00559 //on how to do the vnode partitioning of the index space:
00560 
00561 template<unsigned Dim>
00562 void
00563 FieldLayout<Dim>::setup(const NDIndex<Dim>& domain,
00564                         e_dim_tag *userflags, int vnodes)
00565 {
00566   TAU_TYPE_STRING(taustr, "void (" + CT(domain) + ", e_dim_tag, int)");
00567   TAU_PROFILE("FieldLayout::setup()", taustr, TAU_LAYOUT);
00568   // we have one more FieldLayout, indicate this
00569   //INCIPPLSTAT(incFieldLayouts);
00570 
00571   // Find the number processors.
00572   int nprocs = Ippl::getNodes();
00573   int myproc = Ippl::myNode();
00574 
00575   // If the user didn't specify the number of vnodes, make it equal nprocs
00576   if (vnodes <= 0) vnodes = nprocs;
00577 
00578   Inform dbgmsg("FieldLayout::setup", INFORM_ALL_NODES);
00579   // dbgmsg << "*** Domain=" << domain << ", nprocs=" << nprocs;
00580   // dbgmsg << ", myproc=" << myproc << ", vnodes=" << vnodes << endl;
00581 
00582   // If the user did not specify parallel/serial flags then make all parallel.
00583   int parallel_count = 0, flagdim = 0;
00584   long totparelems = 1;
00585   for (flagdim=0; flagdim < Dim; ++flagdim) {
00586     if (userflags == 0)
00587       RequestedLayout[flagdim] = PARALLEL;
00588     else
00589       RequestedLayout[flagdim] = userflags[flagdim];
00590     if (RequestedLayout[flagdim] == PARALLEL) {
00591       parallel_count++;
00592       totparelems *= domain[flagdim].length();
00593     }
00594   }
00595 
00596   // Make sure at least one of the parallel/serial flags is parallel
00597   PInsist(parallel_count>0,"At least one dimension of a FieldLayout must be PARALLEL!");
00598 
00599   // Check to see if we have too few elements to partition.  If so, reduced
00600   // the number of vnodes (if necessary) to just the number of elements along
00601   // parallel dims.
00602   if (totparelems < vnodes) {
00603     //dbgmsg << "Total parallel lengths = " << totparelems << "; reducing ";
00604     //dbgmsg << "vnodes from " << vnodes << " to " << totparelems << endl;
00605     vnodes = totparelems;
00606   }
00607 
00608   e_dim_tag *flags = RequestedLayout;
00609 
00610   // Recursively split the domain until we have generated all the domains.
00611   Domain = domain;
00612   NDIndex<Dim> *domains_c = new NDIndex<Dim>[vnodes];
00613   NDIndex<Dim> *copy_c    = new NDIndex<Dim>[vnodes];
00614   NDIndex<Dim> leftDomain ;
00615 
00616   // Start with the whole domain.
00617   domains_c[0] = domain;
00618   int v;
00619   int d=0;
00620 
00621   int v1,v2,rm,vtot,vl,vr,dd;
00622   double a,lmax,len;
00623   vnodesPerDirection_m = 0;
00624   for (v=vnodes,rm=0;v>1;v/=2) { rm += (v % 2); }
00625   if (rm == 0) {
00626 
00627     // vnodes is a power of 2
00628 
00629     // For power-of-two vnodes, allocate storage for vnodesPerDirection_m:
00630     //don't--tjw    vnodesPerDirection_m = new unsigned[Dim];
00631     // Fill in 1 for starters; remains 1 for serial directions:
00632     //don't--tjw    for (int d2=0; d2<Dim; d2++) vnodesPerDirection_m[d2] = 1;
00633 
00634     for (v=1; v<vnodes; v*=2) {
00635       // Go to the next parallel dimension.
00636       while(flags[d] != PARALLEL) if(++d == Dim) d = 0;
00637 
00638       // Split all the current vnodes.
00639       int i,j;
00640       for (i=0, j=0; i<v; ++i, j+=2)
00641         // Split to the left and to the right, saving both.
00642         domains_c[i].split( copy_c[j] , copy_c[j+1] , d );
00643       // Copy back.
00644       copy(copy_c,copy_c+v*2, domains_c);
00645 
00646       //don't--tjw      vnodesPerDirection_m[d] *= 2; // Update to reflect split
00647 
00648       // On to the next dimension.
00649       if (++d == Dim) d = 0;
00650     }
00651 
00652   } else {
00653 
00654     vtot = 1; // count the number of vnodes to make sure that it worked
00655     // vnodes is not a power of 2 so we need to do some fancy splitting
00656     // sorry... this would be much cleaner with recursion
00657     /*
00658       The way this works is to recursively split on the longest dimension.
00659       Suppose you request 11 vnodes.  It will split the longest dimension
00660       in the ratio 5:6 and put the new domains in node 0 and node 5.  Then
00661       it splits the longest dimension of the 0 domain and puts the results
00662       in node 0 and node 2 and then splits the longest dimension of node 5
00663       and puts the results in node 5 and node 8. etc.
00664       The logic is kind of bizarre, but it works.
00665     */
00666     for (v=1; v<2*vnodes; ++v) {
00667       // kind of reverse the bits of v
00668       for (v2=v,v1=1;v2>1;v2/=2) { v1 = 2*v1+(v2%2); }
00669       vl = 0; vr = vnodes;
00670       while (v1>1) {
00671         if ((v1%2)==1) {
00672           vl=vl+(vr-vl)/2;
00673         } else {
00674           vr=vl+(vr-vl)/2;
00675         }
00676         v1/=2;
00677       }
00678       v2=vl+(vr-vl)/2;
00679 
00680       if (v2>vl) {
00681         a = v2-vl;
00682         a /= vr-vl;
00683         vr=v2;
00684         leftDomain=domains_c[vl];
00685         lmax=0;
00686         d=-1;
00687         for (dd=0;dd<Dim;++dd) {
00688           if ( flags[dd] == PARALLEL ) {
00689             if ((len = leftDomain[dd].length()) > lmax) {
00690               lmax = len;
00691               d = dd;
00692             }
00693           }
00694         }
00695         domains_c[vl].split( domains_c[vl] , domains_c[vr] , d , a);
00696         ++vtot;
00697       }
00698     }
00699     v=vtot;
00700   }
00701 
00702   // Make sure we had a power of two number of vnodes.
00703   PAssert( v == vnodes );
00704 
00705   // Now make the vnodes, using the domains just generated.
00706   // Some of them we store in the local list, others in the remote.
00707   ac_domain_vnodes *remote_ac = new ac_domain_vnodes( domain );
00708   typedef typename ac_gc_domain_vnodes::value_type vtype;
00709   Remotes_ac.insert( vtype(gc0(),remote_ac) );
00710   for (v=0; v<vnodes; ++v)
00711     {
00712       int p = (v*nprocs)/vnodes;
00713       bool nosplit = (domains_c[v].size() < 2);
00714 
00715       // Add v arg to Vnode constructor 3/19/98 --tjw:
00716       Vnode<Dim> *vnode = new Vnode<Dim>(domains_c[v], p, v);
00717       typedef typename ac_id_vnodes::value_type v1;
00718       typedef typename ac_domain_vnodes::value_type v2;
00719       if ( p==myproc )
00720         Local_ac.insert(v1(Unique::get(),vnode));
00721       else
00722         remote_ac->insert(v2(domains_c[v], vnode), nosplit);
00723     }
00724 
00725   // Delete the memory we allocated.
00726   delete [] domains_c;
00727   delete [] copy_c;
00728 
00729   // Calculate the widths of all the vnodes
00730   calcWidths();
00731 }
00732 
00733 //-----------------------------------------------------------------------------
00734 
00735 //-----------------------------------------------------------------------------
00736 //
00737 // This setup() specifies both the total number of vnodes and the numbers of
00738 // vnodes along each dimension for the partitioning of the index space, where
00739 // the user wants this extra control over the partitioning of the index
00740 // space. Obviously this restricts the number of vnodes to be a product of the
00741 // numbers along each dimension (the constructor implementation checks this).
00742 //
00743 // The last argument is a bool for the algorithm to use for assigning
00744 // vnodes to processors.
00745 // If it is false, hand the vnodes to the processors in a very simple
00746 // but probably inefficient manner.
00747 // If it is true, use a binary recursive algorithm. This will usually be 
00748 // more efficient because it will generate less communication, but
00749 // it will sometimes fail, particularly near the case of one vnode per
00750 // processor.
00751 //
00752 //-----------------------------------------------------------------------------
00753 
00754 template<unsigned Dim>
00755 void
00756 FieldLayout<Dim>::setup(const NDIndex<Dim>& domain,
00757                         e_dim_tag *userflags, unsigned* vnodesPerDirection,
00758                         bool recurse, int vnodes)
00759 {
00760   TAU_TYPE_STRING(taustr, "void (" + CT(domain) + 
00761                   ", e_dim_tag, unsigned, int)");
00762   TAU_PROFILE("FieldLayout::setup()", taustr, TAU_LAYOUT);
00763 
00764   // Find the number processors.
00765   int nprocs = Ippl::getNodes();
00766   int myproc = Ippl::myNode();
00767 
00768   // The number of vnodes must have been specified or computed by now:
00769   if (vnodes <= 0) ERRORMSG("FieldLayout::setup(): vnodes <= 0 "
00770                             << "for a vnodes-per-direction product "
00771                             << "specification; not allowed." << endl);
00772 
00773   // Loop indices:
00774   int v, d, vl, d2;
00775 
00776   int parallel_count = 0, flagdim = 0;
00777   for (flagdim=0; flagdim < Dim; ++flagdim) {
00778     if (userflags == 0)
00779       RequestedLayout[flagdim] = PARALLEL;
00780     else
00781       RequestedLayout[flagdim] = userflags[flagdim];
00782 
00783     // keep track of the number of parallel dimensions; we need at least one
00784     parallel_count += (RequestedLayout[flagdim] == PARALLEL);
00785 
00786     // make sure any SERIAL dimensions request only one vnode along them:
00787     if (RequestedLayout[flagdim] == SERIAL) {
00788       bool chk = vnodesPerDirection[flagdim] == 1;
00789       PInsist(chk,"SERIAL layout specified, yet vnodesPerDirection is not 1!");
00790     }
00791   }
00792   
00793   // Make sure at least one of the parallel/serial flags is parallel
00794   PInsist(parallel_count>0,"At least one dimension of a FieldLayout must be PARALLEL!");
00795 
00796   // Allocate and store vnodesPerDirection_m data-member array:
00797   vnodesPerDirection_m = new unsigned[Dim];
00798   for (d=0; d<Dim; d++) vnodesPerDirection_m[d] = vnodesPerDirection[d];
00799 
00800   // The domain of this FieldLayout object under construction:
00801   Domain = domain;
00802 
00803   // Set up a container of NDIndex's to store the index ranges for all vnodes:
00804   NDIndex<Dim> *domains_c = new NDIndex<Dim>[vnodes];
00805 
00806   // Divide the numbers of elements by the numbers of vnodes (along each
00807   // dimension). All vnodes will have at least this many elements. Some will
00808   // have one extra element:
00809   unsigned elementsPerVnode[Dim];
00810   unsigned nLargerVnodes[Dim];
00811   for (d=0; d<Dim; d++) {
00812     elementsPerVnode[d] = domain[d].length()/vnodesPerDirection[d];
00813     nLargerVnodes[d] = domain[d].length() % vnodesPerDirection[d];
00814   }
00815 
00816   // Set up the base, bound, and stride for the index range of all
00817   // vnodes. Organize by "vnode level." For this kind of partitioning we have a
00818   // the equivalent of a Dim-dimensional array of vnodes, with the number of
00819   // elements in dimension d being vnodesPerDirection[d]. By "vnode level" we
00820   // mean the index along a dimension in the "vnode array" of a given vnode. We
00821   // can store the vnode-index bases and bounds 2D arrays of arrays; we only
00822   // need a 1D array to store the vnode strides because they are the same
00823   // everywhere (and the same as the global strides for each dimension):
00824   int stride[Dim];
00825   for (d=0; d<Dim; d++) stride[d] = domain[d].stride();
00826   int* base[Dim];
00827   int* bound[Dim];
00828   for (d=0; d<Dim; d++) {
00829     base[d] = new int[vnodesPerDirection[d]];
00830     bound[d] = new int[vnodesPerDirection[d]];
00831   }
00832   int length;
00833   for (d=0; d<Dim; d++) {
00834     // Start things off for the zeroth vnode level using the global index base:
00835     length = elementsPerVnode[d];
00836     if (nLargerVnodes[d] > 0) length += 1;
00837     base[d][0] = domain[d].first();
00838     bound[d][0] = base[d][0] + (length-1)*stride[d];
00839     // Now go through all the other vnode levels
00840     for (vl=1; vl < vnodesPerDirection[d]; vl++) {
00841       base[d][vl] = bound[d][vl-1] + stride[d];
00842       length = elementsPerVnode[d];
00843       if (vl < nLargerVnodes[d]) length += 1;
00844       bound[d][vl] = base[d][vl] +(length-1)*stride[d];
00845     }
00846   }
00847 
00848   // Now actually initialize the values in the container of NDIndex's which
00849   // represent each vnode's subdomain:
00850   for (v=0; v<vnodes; v++) {
00851     for (d=0; d<Dim; d++) {
00852       // Compute this vnode's level in this direction:
00853       unsigned denom = 1;
00854       for (d2=0; d2<d; d2++) denom *= vnodesPerDirection[d2];
00855       int vnodeLevel = (v/denom) % vnodesPerDirection[d];
00856       // Now use the precomputed base, bound values to set the Index values:
00857       domains_c[v][d] = Index(base[d][vnodeLevel],bound[d][vnodeLevel],
00858                               stride[d]);
00859       denom = 1; // for debugging
00860     }
00861   }
00862 
00863   // Now find what processor each vnode will end up on.
00864   // This is done with a recursive bisection algorithm.
00865   // This produces fairly squarish blocks -- and therefore
00866   // less communication at the expense of each processor getting 
00867   // a less balanced load.
00868   int *vnodeProcs = new int[vnodes];
00869   int *sizes = new int[Dim];
00870   for (v=0; v<Dim; ++v)
00871     sizes[v] = vnodesPerDirection[v];
00872 
00873   // If we have been instructed to use recursive bisection, do that.
00874   // if not, deal them out in a simple manner.
00875   if ( recurse )
00876     vnodeRecursiveBisection(Dim,sizes,nprocs,vnodeProcs);
00877   else
00878     for ( v=0; v<vnodes; ++v )
00879       vnodeProcs[v] = (v*nprocs)/vnodes;
00880 
00881 
00882   // Now make the vnodes, using the domains just generated.
00883   // Some of them we store in the local list, others in the remote.
00884   ac_domain_vnodes *remote_ac = new ac_domain_vnodes( domain );
00885   typedef typename ac_gc_domain_vnodes::value_type v1;
00886   Remotes_ac.insert(v1(gc0(),remote_ac) );
00887   for (v=0; v<vnodes; ++v) {
00888     int p = vnodeProcs[v];
00889     // Add v arg to Vnode constructor 3/19/98 --tjw:
00890     Vnode<Dim> *vnode = new Vnode<Dim>(domains_c[v], p, v);
00891     typedef typename ac_id_vnodes::value_type v2;
00892     if ( p==myproc )
00893       Local_ac.insert(v2(Unique::get(),vnode) );
00894     else
00895       // For domains of extent 1 in all directions, must call
00896       // DomainMap::insert() with the noSplit flag set to true, to avoid an
00897       // assertion failure in Index::split. Also do this for domains of
00898       // extent ZERO. These are not supposed to happen in IPPL, but when the
00899       // do when something like BinaryRepartition creates them, accomodating
00900       // them here will prevent subsequent code hangs or other errors and allow
00901       // recovery such as rejection of the result of BinaryRepartition (discard
00902       // the FieldLayout with zero-size domains and go on with the original
00903       // layout unchanged). (tjw)
00904       //      if (domains_c[v].size() == 1) {
00905       if (domains_c[v].size() <= 1) {
00906         typedef typename ac_domain_vnodes::value_type v1;
00907         remote_ac->insert(v1(domains_c[v], vnode), true);
00908       } else {
00909         typedef typename ac_domain_vnodes::value_type v1;
00910         remote_ac->insert(v1(domains_c[v], vnode), false);
00911       }
00912   }
00913 
00914   // Delete the memory we allocated.
00915   delete [] domains_c;
00916   delete [] vnodeProcs;
00917   delete [] sizes;
00918   for (d=0; d<Dim; d++) {
00919     delete [] base[d];
00920     delete [] bound[d];
00921   }
00922 
00923   // Calculate the widths of all the vnodes
00924   calcWidths();
00925 }
00926 //-----------------------------------------------------------------------------
00927 
00928 
00929 //-----------------------------------------------------------------------------
00930 // Return number of vnodes along a direction.
00931 template<unsigned Dim>
00932 unsigned FieldLayout<Dim>::
00933 getVnodesPerDirection(unsigned dir) {
00934   
00935   // If not set, then not appropriate to be calling this function. Example:
00936   // now-power-of-two-constructed FieldLayout which did *not* specify numbers
00937   // of vnodes along each direction:
00938   PAssert(vnodesPerDirection_m != 0);
00939 
00940   return(vnodesPerDirection_m[dir]);
00941 }
00942 //-----------------------------------------------------------------------------
00943 
00944 
00945 //---------------------------------------------------------------------
00946 
00947 template<unsigned Dim>
00948 void FieldLayout<Dim>::new_gc_layout(const GuardCellSizes<Dim>& gc)
00949 {
00950   TAU_TYPE_STRING(taustr, "void (" + CT(gc) + " )");
00951   TAU_PROFILE("FieldLayout::new_gc_layout()", taustr, TAU_LAYOUT);
00952 
00953   // Build the guarded domain.
00954   NDIndex<Dim> guarded_domain( AddGuardCells(Domain,gc) );
00955   // Build a container for vnodes in that domain.
00956   ac_domain_vnodes *gr = new ac_domain_vnodes(guarded_domain);
00957   // Record pointer to that container using gc as the key.
00958   typedef typename ac_gc_domain_vnodes::value_type v1;
00959   Remotes_ac.insert(v1(gc,gr) );
00960   // Get the container of vnodes stored w/o guard cells.
00961   ac_domain_vnodes &v0 = *Remotes_ac[ gc0() ];
00962   // Loop over all the remote vnodes.
00963   for (iterator_dv v_i = v0.begin(); v_i != v0.end(); ++v_i)
00964     {
00965       // Build the domain for this vnode with gc guard cells.
00966       NDIndex<Dim> domain(AddGuardCells((*v_i).first,gc));
00967       // Record pointer to this vnode with these guard cells.
00968       typedef typename ac_domain_vnodes::value_type v2;
00969       gr->insert(v2(domain,(*v_i).second) );
00970     }
00971 }
00972 
00973 //----------------------------------------------------------------------
00974 template<unsigned Dim>
00975 FieldLayout<Dim>::FieldLayout(const NDIndex<Dim>& domain,
00976                               const NDIndex<Dim>* idx_begin,
00977                               const NDIndex<Dim>* idx_end)
00978   : Domain(domain)
00979 {
00980   TAU_TYPE_STRING(taustr, "void (" + CT(domain) + ", " + CT(idx_begin) 
00981     + CT(idx_end) + " )");
00982   TAU_PROFILE("FieldLayout::FieldLayout()", taustr, TAU_LAYOUT);
00983 
00984   // we have one more FieldLayout, indicate this
00985   //INCIPPLSTAT(incFieldLayouts);
00986 
00987   // for this kind of construction, we just take it that the user is
00988   // requesting all parallel axes
00989   for (int dl=0; dl < Dim; ++dl) RequestedLayout[dl] = PARALLEL;
00990 
00991   // Build Vnodes for each of the local domains.
00992   vnodesPerDirection_m = 0;
00993   int mynode = Ippl::Comm->myNode();
00994   for (const NDIndex<Dim>* p=idx_begin; p!=idx_end; ++p)
00995     {
00996       typedef typename ac_id_vnodes::value_type v1;
00997       Local_ac.insert(v1(Unique::get(), new Vnode<Dim>(*p,mynode)));
00998     }
00999 
01000   // Everybody broadcasts their new local domains to everybody.
01001   // Build a message with the local domains and the id's for them.
01002   Message* bcast_mess = new Message;
01003   int count = idx_end - idx_begin;
01004   bcast_mess->put(count);
01005   // ::putMessage(*bcast_mess,idx_begin,idx_end);
01006   const NDIndex<Dim>* indxmsg = idx_begin;
01007   while (indxmsg != idx_end)
01008     (indxmsg++)->putMessage(*bcast_mess);
01009   // Send it to everybody except yourself, and record the number sent.
01010   int tag = Ippl::Comm->next_tag( F_REPARTITION_BCAST_TAG , F_TAG_CYCLE );
01011   int node_count = Ippl::Comm->broadcast_others(bcast_mess,tag);
01012   // Create the container for the remote vnodes.
01013   ac_domain_vnodes *remote_ac = new ac_domain_vnodes( Domain );
01014   typedef typename ac_gc_domain_vnodes::value_type v1;
01015   Remotes_ac.insert(v1(gc0(),remote_ac) );
01016 
01017   // Loop until we receive a message from each other node.
01018   while ((--node_count)>=0)
01019     {
01020       // Receive a broadcast message from any node.
01021       int other_node = COMM_ANY_NODE; 
01022       Message *recv_mess = Ippl::Comm->receive_block(other_node,tag);
01023       PAssert(recv_mess != 0);
01024       // Extract the number of vnodes coming in.
01025       int count;
01026       recv_mess->get(count);
01027       // Now get the domains for the vnodes from the message.
01028       NDIndex<Dim> p;
01029       while (count-- > 0) {
01030         p.getMessage(*recv_mess);
01031         Vnode<Dim> *vnode = new Vnode<Dim>(p, other_node);
01032         // For domains of extent 1 in all directions, must call
01033         // DomainMap::insert() with the noSplit flag set to true, to avoid an
01034         // assertion failure in Index::split. Also do this for domains of
01035         // extent ZERO. These are not supposed to happen in IPPL, but when the
01036         // do when something like BinaryRepartition creates them, accomodating
01037         // them here will prevent subsequent code hangs or other errors and
01038         // allow recovery such as rejection of the result of BinaryRepartition
01039         // (discard the FieldLayout with zero-size domains and go on with the
01040         // original layout unchanged). (tjw)
01041         //      if (p.size() == 1) {
01042         if (p.size() <= 1) {
01043           typedef typename ac_domain_vnodes::value_type v1;
01044           remote_ac->insert(v1(p, vnode), true);
01045         } else {
01046           typedef typename ac_domain_vnodes::value_type v1;
01047           remote_ac->insert(v1(p, vnode), false);
01048         }
01049       }
01050     }
01051 
01052   // Calculate the widths of all the vnodes
01053   calcWidths();
01054 }
01055 
01056 
01057 //----------------------------------------------------------------------
01058 // This differs from the previous ctor in that it allows preservation of
01059 // global Vnode integer ID numbers associated with the input Vnodes. --tjw
01060 template<unsigned Dim>
01061 FieldLayout<Dim>::FieldLayout(const NDIndex<Dim>& domain,
01062                               const Vnode<Dim>* idx_begin,
01063                               const Vnode<Dim>* idx_end)
01064   : Domain(domain)
01065 {
01066   TAU_TYPE_STRING(taustr, "void (" + CT(domain) + ", " + CT(idx_begin) 
01067     + CT(idx_end) + " )");
01068   TAU_PROFILE("FieldLayout::FieldLayout()", taustr, TAU_LAYOUT);
01069 
01070   // we have one more FieldLayout, indicate this
01071   //INCIPPLSTAT(incFieldLayouts);
01072 
01073   // for this kind of construction, we just take it that the user is
01074   // requesting all parallel axes
01075   for (int dl=0; dl < Dim; ++dl) RequestedLayout[dl] = PARALLEL;
01076 
01077   // Build Vnodes for each of the local domains.
01078   vnodesPerDirection_m = 0;
01079   int mynode = Ippl::Comm->myNode();
01080   for (const Vnode<Dim>* p=idx_begin; p!=idx_end; ++p) {
01081     typedef typename ac_id_vnodes::value_type v1;
01082     Local_ac.insert(v1(Unique::get(),
01083                new Vnode<Dim>((*p).getDomain(),mynode,(*p).getVnode())));
01084   }
01085 
01086   // Everybody broadcasts their new local domains to everybody.
01087   // Build a message with the local domains and the id's for them.
01088   Message* bcast_mess = new Message;
01089   int count = idx_end - idx_begin;
01090   bcast_mess->put(count);
01091   // ::putMessage(*bcast_mess,idx_begin,idx_end);
01092   const Vnode<Dim>* indxmsg = idx_begin;
01093   while (indxmsg != idx_end)
01094     (indxmsg++)->putMessage(*bcast_mess);
01095   // Send it to everybody except yourself, and record the number sent.
01096   int tag = Ippl::Comm->next_tag( F_REPARTITION_BCAST_TAG , F_TAG_CYCLE );
01097   int node_count = Ippl::Comm->broadcast_others(bcast_mess,tag);
01098   // Create the container for the remote vnodes.
01099   ac_domain_vnodes *remote_ac = new ac_domain_vnodes( Domain );
01100   typedef typename ac_gc_domain_vnodes::value_type v1;
01101   Remotes_ac.insert(v1(gc0(),remote_ac) );
01102 
01103   // Loop until we receive a message from each other node.
01104   while ((--node_count)>=0)
01105     {
01106       // Receive a broadcast message from any node.
01107       int other_node = COMM_ANY_NODE; 
01108       Message *recv_mess = Ippl::Comm->receive_block(other_node,tag);
01109       PAssert(recv_mess != 0);
01110       // Extract the number of vnodes coming in.
01111       int count;
01112       recv_mess->get(count);
01113       // Now get the domains for the vnodes from the message.
01114       Vnode<Dim> p;
01115       while (count-- > 0) {
01116         p.getMessage(*recv_mess);
01117         Vnode<Dim> *vnode = 
01118           new Vnode<Dim>(p.getDomain(), other_node, p.getVnode());
01119         // For domains of extent 1 in all directions, must call
01120         // DomainMap::insert() with the noSplit flag set to true, to avoid an
01121         // assertion failure in Index::split. Also do this for domains of
01122         // extent ZERO. These are not supposed to happen in IPPL, but when the
01123         // do when something like BinaryRepartition creates them, accomodating
01124         // them here will prevent subsequent code hangs or other errors and
01125         // allow recovery such as rejection of the result of BinaryRepartition
01126         // (discard the FieldLayout with zero-size domains and go on with the
01127         // original layout unchanged). (tjw)
01128         //      if (p.getDomain().size() == 1) {
01129         if (p.getDomain().size() <= 1) {
01130           typedef typename ac_domain_vnodes::value_type v1;
01131           remote_ac->insert(v1(p.getDomain(), vnode), true);
01132         } else {
01133           typedef typename ac_domain_vnodes::value_type v1;
01134           remote_ac->insert(v1(p.getDomain(), vnode), false);
01135         }
01136       }
01137     }
01138 
01139   // Calculate the widths of all the vnodes
01140   calcWidths();
01141 }
01142 
01143 
01144 //----------------------------------------------------------------------
01145 //
01146 // Completely repartition this FieldLayout and all of the Fields 
01147 // defined on it.
01148 //
01149 template<unsigned Dim>
01150 void
01151 FieldLayout<Dim>::Repartition(const NDIndex<Dim>* idxBegin,
01152                               const NDIndex<Dim>* idxEnd)
01153 {
01154   TAU_TYPE_STRING(taustr, "void (" + CT(idxBegin) + ", " + CT(idxEnd) + " )");
01155   TAU_PROFILE("FieldLayout::Repartition()", taustr, TAU_LAYOUT);
01156 
01157   // Build a temporary FieldLayout to declare the temporary arrays.
01158   FieldLayout<Dim> tempLayout(Domain,idxBegin,idxEnd);
01159 
01160   // (TJW) Copy the vnodesPerDirection information:
01161   if (vnodesPerDirection_m != 0) {
01162     tempLayout.vnodesPerDirection_m = new unsigned[Dim];
01163     for (int d=0; d<Dim; d++) {
01164       tempLayout.vnodesPerDirection_m[d] = vnodesPerDirection_m[d];
01165     }
01166   }
01167 
01168   // Repartition each field.
01169   iterator_if p, endp=end_if();
01170   for (p=begin_if(); p!=endp; ++p) {
01171     FieldLayoutUser *user = (FieldLayoutUser *)((*p).second);
01172     user->Repartition(&tempLayout);
01173   }
01174 
01175   // Copy back the layout information.
01176   Local_ac = tempLayout.Local_ac;
01177   Remotes_ac = tempLayout.Remotes_ac;
01178 
01179   // Calculate the widths of all the vnodes
01180   calcWidths();
01181 
01182   //INCIPPLSTAT(incRepartitions);
01183 }
01184 
01185 
01186 //----------------------------------------------------------------------
01187 //
01188 // Completely repartition this FieldLayout and all of the Fields 
01189 // defined on it.
01190 // This differs from the previous ctor in that it allows preservation of
01191 // global Vnode integer ID numbers associated with the input Vnodes. --tjw
01192 //
01193 template<unsigned Dim>
01194 void
01195 FieldLayout<Dim>::Repartition(const Vnode<Dim>* idxBegin, 
01196                               const Vnode<Dim>* idxEnd)
01197 {
01198   TAU_TYPE_STRING(taustr, "void (" + CT(idxBegin) + ", " + CT(idxEnd) + " )");
01199   TAU_PROFILE("FieldLayout::Repartition()", taustr, TAU_LAYOUT);
01200 
01201   // Build a temporary FieldLayout to declare the temporary arrays.
01202   FieldLayout<Dim> tempLayout(Domain,idxBegin,idxEnd);
01203 
01204   // (TJW) Copy the vnodesPerDirection information:
01205   if (vnodesPerDirection_m != 0) {
01206     tempLayout.vnodesPerDirection_m = new unsigned[Dim];
01207     for (int d=0; d<Dim; d++) {
01208       tempLayout.vnodesPerDirection_m[d] = vnodesPerDirection_m[d];
01209     }
01210   }
01211 
01212   // Repartition each field.
01213   iterator_if p, endp=end_if();
01214   for (p=begin_if(); p!=endp; ++p) {
01215     FieldLayoutUser *user = (FieldLayoutUser *)((*p).second);
01216     user->Repartition(&tempLayout);
01217   }
01218 
01219   // Copy back the layout information.
01220   Local_ac = tempLayout.Local_ac;
01221   Remotes_ac = tempLayout.Remotes_ac;
01222 
01223   // Calculate the widths of all the vnodes
01224   calcWidths();
01225 }
01226 
01227 
01228 //----------------------------------------------------------------------
01229 //
01230 // Write out a FieldLayout data to a file.  The file is in ascii format,
01231 // with keyword=value.  Return success.
01232 template<unsigned Dim>
01233 bool FieldLayout<Dim>::write(const char *filename) {
01234   TAU_TYPE_STRING(taustr, "bool (const char *)");
01235   TAU_PROFILE("FieldLayout::write()", taustr, TAU_LAYOUT);
01236 
01237   int d;
01238 
01239   // only do the read on node 0
01240   if (Ippl::myNode() == 0) {
01241     // create the file, make sure the creation is OK
01242     FILE *f = fopen(filename, "w");
01243     if (f == 0) {
01244       ERRORMSG("Could not create FieldLayout data file '" << filename);
01245       ERRORMSG("'." << endl);
01246       return false;
01247     }
01248 
01249     // write out FieldLayout information
01250     fprintf(f, "dim    = %d\n", Dim);
01251     fprintf(f, "vnodes = %d\n", numVnodes());
01252     fprintf(f, "pnodes = %d\n", Ippl::getNodes());
01253 
01254     fprintf(f, "domain =");
01255     for (d=0; d < Dim; ++d)
01256       fprintf(f, "  %d %d %d",
01257               Domain[d].first(), Domain[d].last(), Domain[d].stride());
01258     fprintf(f, "\n");
01259 
01260     if (vnodesPerDirection_m != 0) {
01261       fprintf(f, "vnodesperdir =");
01262       for (d=0; d < Dim; ++d)
01263         fprintf(f, " %d", vnodesPerDirection_m[d]);
01264       fprintf(f, "\n");
01265     }
01266 
01267     for (iterator_iv localv = begin_iv(); localv != end_iv(); ++localv) {
01268       Vnode<Dim> *vn = (*localv).second.get();
01269       fprintf(f, "block  = %d %d", vn->getVnode(), vn->getNode());
01270       for (d=0; d < Dim; ++d)
01271         fprintf(f, "  %d %d %d", vn->getDomain()[d].first(),
01272                 vn->getDomain()[d].last(), vn->getDomain()[d].stride());
01273       fprintf(f, "\n");
01274     }
01275 
01276     for (iterator_dv remotev = begin_rdv(); remotev != end_rdv(); ++remotev) {
01277       Vnode<Dim> *vn = (*remotev).second;
01278       fprintf(f, "block  = %d %d", vn->getVnode(), vn->getNode());
01279       for (d=0; d < Dim; ++d)
01280         fprintf(f, "  %d %d %d", vn->getDomain()[d].first(),
01281                 vn->getDomain()[d].last(), vn->getDomain()[d].stride());
01282       fprintf(f, "\n");
01283     }
01284 
01285     fclose(f);
01286   }
01287 
01288   return true;
01289 }
01290 
01291 
01292 //----------------------------------------------------------------------
01293 //
01294 // Read in FieldLayout data from a file.  If the
01295 // file contains data for an equal number of nodes as we are running on,
01296 // then that vnode -> pnode mapping will be used.  If the file does not
01297 // contain info for the same number of pnodes, the vnodes will be
01298 // distributed in some other manner.
01299 // Note that if this FieldLayout is initially empty (e.g., it has no
01300 // local or remote vnodes), the domain will be changed to that in the
01301 // file.  But if we already have some vnodes, we can only repartition
01302 // if the domain matches that in the file, or if we do not have any
01303 // users.  If an error occurs, return
01304 // false and leave our own layout unchanged.
01305 template<unsigned Dim>
01306 bool FieldLayout<Dim>::read(const char *filename) {
01307   TAU_TYPE_STRING(taustr, "bool (const char *)");
01308   TAU_PROFILE("FieldLayout::read()", taustr, TAU_LAYOUT);
01309 
01310   // generate a tag to use for communication
01311   int tag = Ippl::Comm->next_tag(F_LAYOUT_IO_TAG, F_TAG_CYCLE);
01312 
01313   // storage for data read from file
01314   NDIndex<Dim> fdomain;
01315   Vnode<Dim> *vnlist = 0;
01316   unsigned *vnodesPerDir = 0;
01317   int fdim = 0;
01318   int fvnodes = 0;
01319   int fpnodes = 0;
01320   int vnodesread = 0;
01321   int ok = 1;
01322 
01323   // only do the read on node 0
01324   if (Ippl::myNode() == 0) {
01325     // read the file, make sure the read is OK
01326     DiscMeta f(filename);
01327 
01328     // make sure it is OK
01329     DiscMeta::iterator metaline = f.begin();
01330     for ( ; ok == 1 && metaline != f.end(); ++metaline) {
01331       // get number of tokens and list of tokens in the line
01332       int numtokens  = (*metaline).second.first;
01333       string *tokens = (*metaline).second.second;
01334 
01335       // check first word
01336       if (tokens[0] == "dim") {
01337         if (fdim != 0) {
01338           ERRORMSG("Repeated 'dim' line in FieldLayout data file '");
01339           ERRORMSG(filename << "'." << endl);
01340           ok = 0;
01341         }
01342         fdim = atoi(tokens[1].c_str());
01343         if (fdim != Dim) {
01344           ERRORMSG("Mismatched dimension in FieldLayout data file '");
01345           ERRORMSG(filename << "'." << endl);
01346           ok = 0;
01347         }
01348       } else if (tokens[0] == "vnodes") {
01349         if (fvnodes != 0 || vnlist != 0) {
01350           ERRORMSG("Repeated 'vnodes' line in FieldLayout data file '");
01351           ERRORMSG(filename << "'." << endl);
01352           ok = 0;
01353         }
01354         fvnodes = atoi(tokens[1].c_str());
01355         if (fvnodes < 1) {
01356           ERRORMSG("Incorrect 'vnodes' line in FieldLayout data file '");
01357           ERRORMSG(filename << "'." << endl);
01358           ok = 0;
01359         } else {
01360           vnlist = new Vnode<Dim>[fvnodes];
01361         }
01362       } else if (tokens[0] == "pnodes") {
01363         if (fpnodes != 0) {
01364           ERRORMSG("Repeated 'pnodes' line in FieldLayout data file '");
01365           ERRORMSG(filename << "'." << endl);
01366           ok = 0;
01367         }
01368         fpnodes = atoi(tokens[1].c_str());
01369         if (fpnodes < 1) {
01370           ERRORMSG("Incorrect 'pnodes' line in FieldLayout data file '");
01371           ERRORMSG(filename << "'." << endl);
01372           ok = 0;
01373         }
01374       } else if (tokens[0] == "vnodesperdir") {
01375         if (vnodesPerDir != 0) {
01376           ERRORMSG("Repeated 'vnodesperdir' line in FieldLayout data file '");
01377           ERRORMSG(filename << "'." << endl);
01378           ok = 0;
01379         }
01380         if (numtokens - 1 != Dim) {
01381           ERRORMSG("Incorrect 'vnodesperdir' line in FieldLayout data file '");
01382           ERRORMSG(filename << "'." << endl);
01383           ok = 0;
01384         }
01385         vnodesPerDir = new unsigned[Dim];
01386         for (int d=0; d < Dim; ++d) {
01387           vnodesPerDir[d] = atoi(tokens[d+1].c_str());
01388           if (vnodesPerDir[d] < 1) {
01389             ERRORMSG("Illegal vnode per direction value for dim=" << d);
01390             ERRORMSG(" in FieldLayout data file '" << filename << "'."<<endl);
01391             ok = 0;
01392           }
01393         }
01394       } else if (tokens[0] == "domain") {
01395         // make sure we have (first,last,stride) for all dims
01396         if ((numtokens-1) % 3 != 0 || (numtokens-1) / 3 != Dim) {
01397           ERRORMSG("Incorrect 'domain' line in FieldLayout data file '");
01398           ERRORMSG(filename << "'." << endl);
01399           ok = 0;
01400         }
01401         for (int d=0, dindx=1; d < Dim; ++d) {
01402           fdomain[d] = Index(atoi(tokens[dindx].c_str()),
01403                              atoi(tokens[dindx + 1].c_str()),
01404                              atoi(tokens[dindx + 2].c_str()));
01405           dindx += 3;
01406         }
01407       } else if (tokens[0] == "block") {
01408         // this is vnode information; it should be of the form
01409         // vnode# pnode# (domain, with 3 numbers/dimension)
01410         // So, the number of tokens should be a multipple of three
01411         if (numtokens % 3 != 0 || numtokens / 3 != (Dim+1)) {
01412           ERRORMSG("Incorrect 'block' line in FieldLayout data file '");
01413           ERRORMSG(filename << "'." << endl);
01414           ok = 0;
01415         } else if (vnlist == 0) {
01416           ERRORMSG("In FieldLayout data file '" << filename << ": You must ");
01417           ERRORMSG("give the number vnodes before any block lines." << endl);
01418           ok = 0;
01419         } else {
01420           int vnum = atoi(tokens[1].c_str());
01421           int pnum = atoi(tokens[2].c_str());
01422           if (pnum < 0 || pnum >= fpnodes) {
01423             ERRORMSG("Illegal pnode number in 'block' line ");
01424             ERRORMSG("of file '" << filename << "'." << endl);
01425             ok = 0;
01426           }
01427           NDIndex<Dim> vdom;
01428           for (int d=0, dindx=3; d < Dim; ++d) {
01429             vdom[d] = Index(atoi(tokens[dindx].c_str()),
01430                             atoi(tokens[dindx + 1].c_str()),
01431                             atoi(tokens[dindx + 2].c_str()));
01432             dindx += 3;
01433           }
01434 
01435           // construct a new vnode from this info, and store it at the
01436           // index given by the vnum value
01437           vnlist[vnodesread++] = Vnode<Dim>(vdom, pnum, vnum);
01438         }
01439       } else {
01440         ERRORMSG("Unrecognized '" << tokens[0] << "' line in FieldLayout ");
01441         ERRORMSG(" data file '" << filename << "'." << endl);
01442         ok = 0;
01443       }
01444     }
01445 
01446     // do some final sanity checks
01447     if (ok != 0 && (fvnodes < 1 || fdim != Dim || vnodesread != fvnodes)) {
01448       ERRORMSG("Inconsistent FieldLayout data in file '" << filename);
01449       ERRORMSG("'." << endl);
01450       ok = 0;
01451     }
01452 
01453     // if we have users, we cannot change the global domain any
01454     if ( ok != 0 && getNumUsers() > 0 && !(fdomain == Domain) ) {
01455       ERRORMSG("You cannot change the global domain of a FieldLayout which");
01456       ERRORMSG(" has users." << endl);
01457       ok = 0;
01458     }
01459 
01460     // Send out new layout info to other nodes
01461     if (Ippl::getNodes() > 1) {
01462       Message *msg = new Message;
01463       msg->put(ok);
01464       if (ok != 0) {
01465         msg->put(fvnodes);
01466         msg->put(fpnodes);
01467         msg->put(fdomain);
01468         int vnpdok = (vnodesPerDir != 0 ? 1 : 0);
01469         msg->put(vnpdok);
01470         if (vnpdok != 0)
01471           msg->put(vnodesPerDir, vnodesPerDir + Dim);
01472         for (int v=0; v < fvnodes; ++v) {
01473           msg->put(vnlist[v]);
01474         }
01475       }
01476 
01477       Ippl::Comm->broadcast_others(msg, tag);
01478     }
01479   } else {
01480     // on the client nodes, get the info from node 0 and store it
01481     // first receive the message
01482     int node = 0;
01483     Message *msg = Ippl::Comm->receive_block(node, tag);
01484     PAssert(msg);
01485 
01486     // then get data out of the message
01487     msg->get(ok);
01488     if (ok != 0) {
01489       msg->get(fvnodes);
01490       msg->get(fpnodes);
01491       msg->get(fdomain);
01492       int vnpdok;
01493       msg->get(vnpdok);
01494       if (vnpdok != 0) {
01495         vnodesPerDir = new unsigned[Dim];
01496         msg->get_iter(vnodesPerDir);
01497       }
01498       if ((vnodesread = fvnodes) > 0) {
01499         vnlist = new Vnode<Dim>[fvnodes];
01500         for (int v=0; v < fvnodes; ++v) {
01501           Vnode<Dim> vn;
01502           msg->get(vn);
01503           vnlist[v] = vn;
01504         }
01505       }
01506     }
01507 
01508     // done with the message, we can delete it
01509     delete msg;
01510   }
01511 
01512   // now, on all nodes, figure out which vnodes are ours, and which are
01513   // local.  But if an error occurred during reading, we just exit
01514   // without changing anything.
01515   if (ok != 1 || fvnodes < 1) {
01516     if (vnodesPerDir != 0)
01517       delete [] vnodesPerDir;
01518     if (vnlist != 0)
01519       delete [] vnlist;
01520     return false;
01521   }
01522 
01523   // save the new domain
01524   Domain = fdomain;
01525 
01526   // for each vnode, figure out which physical node it belongs on, and
01527   // sort those vnodes to the top of the list.
01528   int localvnodes = 0;
01529   for (int v=0; v < fvnodes; ++v) {
01530     int node = vnlist[v].getNode() % Ippl::getNodes();
01531     if (node == Ippl::myNode()) {
01532       if (v > localvnodes) {
01533         // move this vnode to the top
01534         Vnode<Dim> tempv(vnlist[localvnodes]);
01535         vnlist[localvnodes] = vnlist[v];
01536         vnlist[v] = tempv;
01537       }
01538       localvnodes++;
01539     }
01540   }
01541 
01542   // save the info on how many vnodes we have per direction
01543   if (vnodesPerDirection_m != 0)
01544     delete [] vnodesPerDirection_m;
01545   vnodesPerDirection_m = vnodesPerDir;
01546 
01547   // Repartition the system using our list of local vnodes
01548   Repartition(vnlist, vnlist + localvnodes);
01549  
01550   // success!
01551   delete [] vnlist;
01552   return true;
01553 }
01554 
01555 
01556 //----------------------------------------------------------------------
01557 //
01558 // calculate the minimum vnode sizes in each dimension
01559 template<unsigned Dim>
01560 void FieldLayout<Dim>::calcWidths() {
01561   unsigned int d;
01562 
01563   // initialize widths first
01564   for (d=0; d < Dim; ++d)
01565     MinWidth[d] = getDomain()[d].length();
01566   
01567   // look for minimum width in local vnodes
01568   for  (const_iterator_iv v_i = begin_iv() ; v_i != end_iv(); ++v_i) {
01569     const NDIndex<Dim> &dom = (*v_i).second->getDomain();
01570     for (d=0; d < Dim; ++d) {
01571       if (dom[d].length() < MinWidth[d])
01572         MinWidth[d] = dom[d].length();
01573     }
01574   }
01575 
01576   // look for minimum width in remove vnodes
01577   ac_domain_vnodes *v_ac = Remotes_ac[ gc0() ].get();
01578   for (iterator_dv dv_i = v_ac->begin(); dv_i != v_ac->end(); ++ dv_i) {
01579     const NDIndex<Dim> &dom = (*dv_i).first;
01580     for (d=0; d < Dim; ++d) {
01581       if (dom[d].length() < MinWidth[d])
01582         MinWidth[d] = dom[d].length();
01583     }
01584   }
01585 
01586   //Inform dbgmsg("calcWidths", INFORM_ALL_NODES);
01587   //dbgmsg << "Calculated minimum widths for layout " << *this << endl;
01588   //for (d=0; d < Dim; ++d) {
01589   //  dbgmsg << " ==> MinWidth[" << d << "] = " << MinWidth[d];
01590   //  dbgmsg << " ... " << (getDistribution(d)==SERIAL?"serial":"parallel");
01591   //  dbgmsg << endl;
01592   //}
01593 }
01594 
01595 
01596 //----------------------------------------------------------------------
01597 //
01598 // Tell the FieldLayout that a FieldLayoutUser is using it
01599 template<unsigned Dim>
01600 void
01601 FieldLayout<Dim>::checkin(FieldLayoutUser& f,
01602                           const GuardCellSizes<Dim>& gc)
01603 {
01604   TAU_TYPE_STRING(taustr, "void (FieldLayoutUser, " + CT(gc) + " )");
01605   TAU_PROFILE("FieldLayout::checkin()", taustr, TAU_LAYOUT);
01606 
01607   checkinUser(f);
01608   iterator_gdv guarded = Remotes_ac.find(gc);
01609   if ( guarded == Remotes_ac.end() )
01610     new_gc_layout(gc);
01611 }
01612 
01613 //----------------------------------------------------------------------
01614 //
01615 // Tell the FieldLayout that a Field is no longer using it.
01616 template<unsigned Dim>
01617 void
01618 FieldLayout<Dim>::checkout(FieldLayoutUser& f)
01619 {
01620   TAU_PROFILE("FieldLayout::checkout()", "void (FieldLayoutUser)", TAU_LAYOUT);
01621 
01622   checkoutUser(f);
01623 }
01624 
01625 template<unsigned Dim>
01626 NDIndex<Dim> FieldLayout<Dim>::getLocalNDIndex()
01627 {
01628 
01629   NDIndex<Dim> theId;
01630   for (iterator_iv localv = begin_iv(); localv != end_iv(); ++localv) {
01631     Vnode<Dim> *vn = (*localv).second.get();
01632     if(vn->getNode() == Ippl::myNode())
01633       theId = vn->getDomain();
01634   }
01635   return theId;
01636 }
01637 
01638 
01639 //---------------------------------------------------------------------
01640 // output
01641 //---------------------------------------------------------------------
01642 template<unsigned Dim>
01643 void FieldLayout<Dim>::write(ostream& out) const
01644 {
01645   TAU_PROFILE("FieldLayout::write()", "void (ostream)", TAU_LAYOUT);
01646 
01647   int icount;
01648 
01649   // the whole domain, and the number of users
01650   out << "Domain = " << Domain << "\n";
01651   out << "FieldLayoutUsers = " << size_if() << "\n";
01652 
01653   // If applicable, vnodes per direction (tjw):
01654   if (vnodesPerDirection_m != 0) {
01655     out << "vnodesPerDirection_m[] =";
01656     for (int d=0; d<Dim; d++)
01657       out << " " << vnodesPerDirection_m[d];
01658     out << endl;
01659   }
01660 
01661   // iterate over the local vnodes and print them out.
01662   out << "Total number of vnodes = " << numVnodes() << endl;
01663   out << "Local Vnodes = " << Local_ac.size() << "\n";
01664   icount = 0;
01665   //tjw can now do operator<<() with whole Vnode objects
01666   //tjw  for(const_iterator_iv v_i = begin_iv() ; v_i != end_iv(); ++v_i)
01667   //tjw    out << " vnode " << icount++ <<" : "<< (*v_i).second->getDomain() << "\n";
01668   for(const_iterator_iv v_i = begin_iv() ; v_i != end_iv(); ++v_i)
01669     out << " vnode " << icount++ << ": " << *((*v_i).second) << endl;
01670 
01671   // iterate over the remote vnodes and print them out.
01672   ac_domain_vnodes *v_ac = Remotes_ac[ gc0() ].get();
01673   out << "Remote Vnodes = " << v_ac->size() << "\n";
01674   icount = 0;
01675   for (iterator_dv dv_i = v_ac->begin(); dv_i != v_ac->end(); ++ dv_i)
01676     out << " vnode " << icount++ << " : " << *((*dv_i).second) << endl;
01677 }
01678 
01679 
01680 /***************************************************************************
01681  * $RCSfile: FieldLayout.cpp,v $   $Author: adelmann $
01682  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:27 $
01683  * IPPL_VERSION_ID: $Id: FieldLayout.cpp,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $ 
01684  ***************************************************************************/

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