src/FieldLayout/VnodeMultiBalancer.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 //-----------------------------------------------------------------------------
00027 // Description:
00028 // Vnode-granularity load balancer, based on input container of bool weight
00029 // BareFields
00030 //-----------------------------------------------------------------------------
00031 
00032 // include files
00033 #include "FieldLayout/VnodeMultiBalancer.h"
00034 #include "FieldLayout/BinaryBalancer.h"
00035 #include "FieldLayout/FieldLayout.h"
00036 #include "Field/BareField.h"
00037 #include "Profile/Profiler.h"
00038 
00040 // Implementation of VnodeMultiRepartition().
00041 // 
00042 // Internally, it constructs a Field<...,double,....> having one element for
00043 // each vnode along each direction in the input FieldLayout, called vf. It
00044 // assigns a weight of 1.0 to each element equal to the total number of unique
00045 // Field's having any true elements in each vnode for all the Field's in the
00046 // input container (STL vector) of boolean weight Fields. If any vnode is
00047 // compressed to false, the corresponding vf element value is left unchanged;
00048 // if a vnode is uncompressed, this means that there is at least one true
00049 // element in it, and the vf element value is incremented by one; if a vnode is
00050 // compressed to true, this means all elements are true and the vf element is
00051 // also incremented by 1.  Then, it invokes BinaryBalancer on this small Field
00052 // of weights, vf, to partition it elementwise among the processors, one
00053 // element per PE. Finally, it maps this back to the input FieldLayout (used by
00054 // the input Fields of weights), and repartitions the input FieldLayout's
00055 // vnodes in a corresponding way among the PE's.
00057 
00058 
00059 template<unsigned Dim>
00060 void VnodeMultiRepartition(FieldLayout<Dim>& layout, 
00061                            vector<BareField<bool,Dim>* >& weights) {
00062   
00063   TAU_TYPE_STRING(taustr, " (" + CT(layout) + ", "+ CT(weights) + " )");
00064   TAU_PROFILE("VnodeMultiRepartition()", taustr, TAU_LAYOUT);
00065 
00066   int npe = Ippl::Comm->getNodes(); // Total number of PE's (pnodes)
00067   if (npe == 1) return; // Not much hope of balancing on 1 node, eh?
00068 
00069   // Get numbers of vnodes per direction (vnode "array" extents) and total
00070   // number of vnodes:
00071   unsigned vpd[Dim];
00072   int vnodes = 1;
00073   for (int d=0; d<Dim; d++) {
00074     vpd[d] = layout.getVnodesPerDirection(d);
00075     vnodes *= vpd[d];
00076   }
00077 
00078   // Construct the Field sized as vpd[d] elements along each dimension d:
00079   NDIndex<Dim> vfndi;
00080   for (int d=0; d<Dim; d++) vfndi[d] = Index(vpd[d]);
00081   // SERIAL/PARALLEL specification must match input FieldLayout layout:
00082   e_dim_tag edt[Dim];
00083   for (int d=0; d<Dim; d++) edt[d] = layout.getDistribution(d);
00084   // Because "true" for recurse parameter selected here, this algorithm will
00085   // run faster the first time through if the input "layout" was also
00086   // constructed with recurse=true. Should be correct even if not, though, and
00087   // subsequent re-calls of VnodeMultiRepartition() should go faster in either
00088   // case:
00089   FieldLayout<Dim> l(vfndi, edt, vpd, true, vnodes);
00090   BareField<double,Dim> vf(l);
00091   vf = 0.0;
00092 
00093   
00094   // Loop through the PE's owned LField's (<==> Vnode's) in each boolean Field
00095   // of weights. Check each for compression, and increment the value the value
00096   // in an array of double's with one element for each vnode; increment by 1 if
00097   // compressed to true or uncompressed; if compressed to false don't
00098   // increment:
00099   int* anyTrueElements = new int[vnodes];
00100   for (int v=0; v < vnodes; v++) anyTrueElements[v] = 0;
00101   
00102   // Iterate through the BareFields in the container:
00103   typename vector<BareField<bool,Dim>* >::iterator bfi;
00104   for (bfi = weights.begin(); bfi != weights.end(); ++bfi) {
00105     BareField<bool,Dim>& weight = *(*bfi);
00106     typename BareField<bool,Dim>::iterator_if weightItr;
00107     // Go through the LFields in the BareField:
00108     for (weightItr = weight.begin_if();
00109          weightItr != weight.end_if(); 
00110          ++weightItr) {
00111       if ((*weightItr).second->IsCompressed()) {
00112         if ((*weightItr).second->getCompressedData()) {
00113           anyTrueElements[(*weightItr).second->getVnode()] += 1;
00114         }
00115       } else {
00116         anyTrueElements[(*weightItr).second->getVnode()] += 1;
00117       }
00118     }
00119   }
00120 
00121 
00122   // Now broadcast so that every PE has complete copy of "anyTrueElements"
00123   // array: Send to PE 0, which combines all, then broadcasts back:
00124   int pe = Ippl::Comm->myNode();   // My processor ID
00125   Message *msg;
00126   int partialTag  = Ippl::Comm->next_tag(VNMB_PARTIAL_TAG, VNMB_TAG_CYCLE);
00127   int completeTag = Ippl::Comm->next_tag(VNMB_COMPLETE_TAG, VNMB_TAG_CYCLE);
00128   if (pe == 0) {
00129     // Receive partially-filled arrays from other PE's:
00130     int* anyTrueElementsPartial = new int[vnodes];
00131     int notReceived = npe - 1;
00132     while (notReceived > 0) {
00133       int otherPE = COMM_ANY_NODE;
00134       int tag = partialTag;
00135       Message* msg2 = Ippl::Comm->receive_block(otherPE, tag);
00136       msg2->get(anyTrueElementsPartial);
00137       delete msg2;
00138       // Put values into anyTrueElements:
00139       for (int v=0; v < vnodes; v++) {
00140         // Any nonzero element in anyTrueElementsPartial *must* correspond to a
00141         // zero element in current status of anyTrueElements on PE 0; check for
00142         // otherwise and give error message if otherwise:
00143         if ((anyTrueElements[v] != 0) && (anyTrueElementsPartial[v] != 0)) {
00144           ERRORMSG("VnodeMultiRepartition(): anyTrueElements[" << v << "] = "
00145                    << anyTrueElements[v] << " and anyTrueElementsPartial[" 
00146                    << v << "] = " << anyTrueElementsPartial[v] 
00147                    << " ; inconsistent!" << endl);
00148         }
00149         anyTrueElements[v] += anyTrueElementsPartial[v];
00150       }
00151       notReceived--;
00152     }
00153     msg = new Message();
00154     msg->put(anyTrueElements, anyTrueElements + vnodes);
00155     // Broadcast fully-filled array to other PE's:
00156     Ippl::Comm->broadcast_others(msg, completeTag);
00157     delete [] anyTrueElementsPartial;
00158   } else {
00159     // Send my partially-filled array to PE 0:
00160     msg = new Message();
00161     msg->put(anyTrueElements, anyTrueElements + vnodes);
00162     Ippl::Comm->send(msg, 0, partialTag);
00163     // Receive fully-filled array from PE 0:
00164     int pe0 = 0;
00165     msg = Ippl::Comm->receive_block(pe0, completeTag);
00166     msg->get(anyTrueElements);
00167   }
00168 
00169   // Loop through the PE's owned LField's (<==> Vnode's) in vf:
00170   typename BareField<double,Dim>::iterator_if vfItr;
00171   for (vfItr = vf.begin_if(); vfItr != vf.end_if(); ++vfItr) {
00172     
00173     // Global integer index of this vnode:
00174     int vnode = (*vfItr).second->getVnode();
00175 
00176     // Assign the integer value from anyTrueElements to the corresponding
00177     // single element in vf's corresponding vnode: The use of the special
00178     // LField::Compress(double val) function is a trick; we know that the vf
00179     // Field can be compressed (and probably always is); using this function
00180     // assigns the CompressedData value directly, or else compresses the LField
00181     // and sets CompressedData to the requested value if for some reason it
00182     // wasn't already compressed:
00183     (*vfItr).second->Compress(anyTrueElements[vnode]);
00184 
00185   }
00186 
00187 
00188   // Now invoke BinaryBalancer on the small Field vf:
00189   BinaryRepartition(l, vf);
00190 
00191   // Try this more rational alternative to handling zero-length vnodes:
00192 
00193   // Find and record all zero-length vnodes in l; each PE can check for this
00194   // independently, since all have domain size info for both local and remote
00195   // vnodes:
00196   int nZeroSizeVnodes = 0;
00197   // Locals:
00198   typename FieldLayout<Dim>::iterator_iv lLocals;
00199   for (lLocals = l.begin_iv(); lLocals != l.end_iv(); ++lLocals) {
00200     if ((*lLocals).second->getDomain().size() == 0) {nZeroSizeVnodes += 1;}
00201   }
00202   // Remotes:
00203   typename FieldLayout<Dim>::iterator_dv lRemotes;
00204   for (lRemotes = l.begin_rdv(); lRemotes != l.end_rdv(); ++lRemotes) {
00205     if ((*lRemotes).second->getDomain().size() == 0) {nZeroSizeVnodes += 1;}
00206   }
00207 
00208   // For now, punt on handling this and just return without changing the input
00209   // FieldLayout at all; report this as an error. The stuff ifdef'd by "GROSS"
00210   // below is partially-completed (and partially-compiling) kludge to try and
00211   // make BinaryRepartition do something in this case by tweaking the vf Field
00212   // values with random numbers.
00213   if (nZeroSizeVnodes != 0) {
00214     WARNMSG("VnodeMultiRepartition() was not able to get a successful "
00215             << "rebalance. So, it is leaving the FieldLayout vnode "
00216             << "PE-partioning the way it was whenyou called it. Sorry about "
00217             << "that; there just aren't enough noncompressed vnodes to go "
00218             << "around for this many PEs---at least not enough located in a "
00219             << "way that the underlying BinaryBalancer algorithm can deal "
00220             << "with." << endl);
00221     // Cleanup:
00222     delete [] anyTrueElements;
00223     return;
00224   }
00225 
00226 #ifdef GROSS
00227   // Moved this gross stuff to the bottom of the file; hoist it back in here
00228   // later if needed. Of course, this module will not compile when GROSS is
00229   // defined until you do this hoisting, and fix remaining compile errors in
00230   // the gross stuff.
00231 #endif // GROSS
00232 
00233 
00234   // This has changed the FieldLayout l so that it no longer has the same
00235   // number of vnodes as layout; it has one vnode per pnode.
00236 
00237   // Now must go through each *element* of vf, find which PE owns it now, map
00238   // the element index back to a vnode-array (and then global vnode ID) index
00239   // in layout, and reassign ownership of layout's corresponding vnode to that
00240   // same PE.
00241 
00242   int* peOwner = new int[vnodes];
00243   // Mask value -1 needed for inter-PE-exchange of array values below:
00244   for (int v=0; v < vnodes; v++) peOwner[v] = -1;
00245 
00246   // Loop through the elements of the Field vf. We know there is one per vnode
00247   // in the Field vf:
00248 
00249   // Outer loop over PE's owned Lfields in vf; vfItr constructed already:
00250   for (vfItr = vf.begin_if(); vfItr != vf.end_if(); ++vfItr) {
00251 
00252     // Inner loop over elements in LField:
00253     typename LField<double,Dim>::iterator lfi;
00254     for (lfi = (*vfItr).second->begin(); 
00255          lfi != (*vfItr).second->end(); ++lfi) {
00256       // Global integer index values of the Field element this refers to:
00257       int vfIndex[Dim];
00258       // To compute this from result of Lfield::iterator::GetOffset(), must
00259       // have the global-index-space base index values of this LField's
00260       // subdomain so you can add it on:
00261       int lfBase[Dim];
00262       for (int d=0; d<Dim; d++) {
00263         lfBase[d] = (*vfItr).second->getOwned()[d].first();
00264       }
00265       for (int d=0; d<Dim; d++) vfIndex[d] = lfi.GetOffset(d) + lfBase[d];
00266       // Global integer index of this vnode:
00267       int vnode = vfIndex[0];
00268       int multipplier = 1;
00269       for (int d=1; d<Dim; d++) {
00270         multipplier *= vpd[d-1];
00271         vnode += vfIndex[d]*multipplier;
00272       }
00273       if (vnode >= vnodes) {
00274         ERRORMSG("VnodeMultiRepartition(): vnode = " << vnode
00275                  << " but vnodes is only " << vnodes << " ; inconsistent!"
00276                  << endl);
00277         PInsist(vnode < vnodes, 
00278                 "VnodeMultiRepartition: exit because of vnode value error.");
00279       }
00280 
00281       // Record PE ownership. This is SPMD code here. The PE that calculated
00282       // the value of vnode is the one that owns it, so assign ownership to
00283       // it's PE ID number:
00284       peOwner[vnode] = pe;
00285     }
00286   }
00287 
00288 
00289   // Now broadcast so that every PE has complete copy of "peOwner" array:
00290   partialTag  = Ippl::Comm->next_tag(VNMB_PARTIAL_TAG, VNMB_TAG_CYCLE);
00291   completeTag = Ippl::Comm->next_tag(VNMB_COMPLETE_TAG, VNMB_TAG_CYCLE);
00292   Message* msg4;
00293   if (pe == 0) {
00294     // Receive partially-filled arrays from other PE's:
00295     int* peOwnerPartial = new int[vnodes];
00296     int notReceived = npe - 1;
00297     while (notReceived > 0) {
00298       int otherPE = COMM_ANY_NODE;
00299       int tag = partialTag;
00300       Message* msg2 = Ippl::Comm->receive_block(otherPE, tag);
00301       msg2->getmsg((void *)peOwnerPartial);
00302       delete msg2;
00303       // Put values into peOwner:
00304       for (int v=0; v < vnodes; v++) {
00305         if (peOwnerPartial[v] != -1) {
00306           // Any non-minus-one element in peOwnerPartial *must* correspond to a
00307           // minus-one element in current status of peOwner on PE 0; check for
00308           // otherwise and give error message if otherwise:
00309           if (peOwner[v] != -1) {
00310             ERRORMSG("VnodeMultiRepartition(): peOwner[" << v << "] = "
00311                      << peOwner[v] << " and peOwnerPartial[" 
00312                      << v << "] = " << peOwnerPartial[v] 
00313                      << " ; inconsistent!" << endl);
00314           }
00315           peOwner[v] = peOwnerPartial[v];
00316         }
00317       }
00318       notReceived--;
00319     }
00320     msg4 = new Message();
00321     msg4->put(peOwner, peOwner + vnodes);
00322     // Broadcast fully-filled array to other PE's:
00323     Ippl::Comm->broadcast_others(msg4, completeTag);
00324     delete [] peOwnerPartial;
00325   } else {
00326     // Send my partially-filled array to PE 0:
00327     msg4 = new Message();
00328     msg4->put(peOwner, peOwner + vnodes);
00329     Ippl::Comm->send(msg4, 0, partialTag);
00330     // Receive fully-filled array from PE 0:
00331     int pe0 = 0;
00332     msg4 = Ippl::Comm->receive_block(pe0, completeTag);
00333     msg4->get(peOwner);
00334   }
00335   delete msg4;
00336 
00337 
00338   // Now repartition layout to have the same PE ownership as l; must construct
00339   // an array of NDIndex's before FieldLayout::Repartition can be invoked:
00340   
00341   // Find out how many vnodes I (PE) own:
00342   int nVnodesIOwn = 0;
00343   for (int v=0; v < vnodes; v++) if (peOwner[v] == pe) ++nVnodesIOwn;
00344 
00345   // Array of Vnodes that I own:
00346   Vnode<Dim>* domains = new Vnode<Dim>[nVnodesIOwn];
00347 
00348   // Get the values of the domains from the original layout:
00349 
00350   // The ones I owned in the original layout (locals):
00351   typename FieldLayout<Dim>::iterator_iv oldLocals;
00352   int domain = 0; // counter
00353   for (oldLocals = layout.begin_iv(); oldLocals != layout.end_iv(); 
00354        ++oldLocals) {
00355     // Global integer index of this vnode:
00356     int vnode = (*oldLocals).second->getVnode();
00357     if (peOwner[vnode] == pe) {
00358       domains[domain] = 
00359         Vnode<Dim>((*oldLocals).second->getDomain(), pe, vnode);
00360       ++domain;
00361     }
00362   }
00363 
00364   // The ones I didn't own in the original layout (remotes):
00365   typename FieldLayout<Dim>::iterator_dv oldRemotes;
00366   for (oldRemotes = layout.begin_rdv(); oldRemotes != layout.end_rdv(); 
00367        ++oldRemotes) {
00368     // Global integer index of this vnode:
00369     int vnode = (*oldRemotes).second->getVnode();
00370     if (peOwner[vnode] == pe) {
00371       domains[domain] = 
00372         Vnode<Dim>((*oldRemotes).second->getDomain(), pe, vnode);
00373       ++domain;
00374     }
00375   }
00376 
00377 
00378   // Finally, call FieldLayout::Repartition() to repartition layout:
00379   layout.Repartition(domains, domains + nVnodesIOwn);
00380 
00381 
00382   // Cleanup:
00383   delete [] anyTrueElements;
00384   delete [] peOwner;
00385   delete [] domains;
00386 
00387   return;
00388 }
00389 
00390 #ifdef GROSS
00391   // See comments above in first "GROSS" block about putting this stuff back up there.
00392 
00393   // If none are zero, go on from here. If any are zero, have to go back and
00394   // find them, and find suitable nonzero ones to divide to get one nonzero one
00395   // for each PE that owns a zero-size one:
00396   FieldLayout<Dim> l2(vfndi, edt, vpd, true, vnodes); // Outside if block for scoping.
00397   if (nZeroSizeVnodes != 0) {
00398     // Reconstruct a replacement vf Field, add a random epsilon fudge factor to
00399     // it, and see if the repartitioner works; if not, *don't* repartition and
00400     // just return (load balance attempt fails, so leave load as it was):
00401 
00402     // The replacement vf Field:
00403     //outside if block; see above    FieldLayout<Dim> l2(vfndi, edt, vpd, true, vnodes);
00404     BareField<double,Dim> vf2(l2);
00405     vf2 = 0.0;
00406 
00407     // -----------------------------------------------------------------------------------
00408     // Duplicate the original assignment of the vf Field:
00409 
00410     // Loop through the PE's owned LField's (<==> Vnode's) in each boolean Field
00411     // of weights. Check each for compression, and increment the value the value
00412     // in an array of double's with one element for each vnode; increment by 1 if
00413     // compressed to true or uncompressed; if compressed to false don't
00414     // increment:
00415     for (int v=0; v < vnodes; v++) anyTrueElements[v] = 0;
00416   
00417     // Iterate through the BareFields in the container:
00418     vector<BareField<bool,Dim>* >::iterator bfi2;
00419     for (bfi2 = weights.begin(); bfi2 != weights.end(); ++bfi2) {
00420       BareField<bool,Dim>& weight2 = *(*bfi2);
00421       BareField<bool,Dim>::iterator_if weight2Itr;
00422       // Go through the LFields in the BareField:
00423       for (weight2Itr = weight2.begin_if();
00424            weight2Itr != weight2.end_if(); 
00425            ++weight2Itr) {
00426         if ((*weight2Itr).second->IsCompressed()) {
00427           if ((*weight2Itr).second->getCompressedData()) {
00428             anyTrueElements[(*weight2Itr).second->getVnode()] += 1;
00429           }
00430         } else {
00431           anyTrueElements[(*weight2Itr).second->getVnode()] += 1;
00432         }
00433       }
00434     }
00435     // -----------------------------------------------------------------------------------
00436 
00437     // Now add the epsilon tweak:
00438     double normfact = sum(Abs(vf2));
00439     normfact = normfact/vfndi.size();
00440     double epsilon = 1.0/normfact;
00441     vf2 += epsilon*IpplRandom;
00442 
00443     // ***********************************************************************
00444     // Once again go through the code up to the attempted BinaryRepartition():
00445     // This should maybe a function....
00446 
00447     // Now broadcast so that every PE has complete copy of "anyTrueElements"
00448     // array: Send to PE 0, which combines all, then broadcasts back:
00449     partialTag  = Ippl::Comm->next_tag(VNMB_PARTIAL_TAG, VNMB_TAG_CYCLE);
00450     completeTag = Ippl::Comm->next_tag(VNMB_COMPLETE_TAG, VNMB_TAG_CYCLE);
00451     Message *msg3;
00452     if (pe == 0) {
00453       // Receive partially-filled arrays from other PE's:
00454       int* anyTrueElementsPartial = new int[vnodes];
00455       int notReceived = npe - 1;
00456       while (notReceived > 0) {
00457         int otherPE = COMM_ANY_NODE;
00458         int tag = partialTag;
00459         Message* msg2 = Ippl::Comm->receive_block(otherPE, tag);
00460         msg2->get(anyTrueElementsPartial);
00461         delete msg2;
00462         // Put values into anyTrueElements:
00463         for (int v=0; v < vnodes; v++) {
00464           // Any nonzero element in anyTrueElementsPartial *must* correspond to a
00465           // zero element in current status of anyTrueElements on PE 0; check for
00466           // otherwise and give error message if otherwise:
00467           if ((anyTrueElements[v] != 0) && (anyTrueElementsPartial[v] != 0)) {
00468             ERRORMSG("VnodeMultiRepartition(): anyTrueElements[" << v << "] = "
00469                      << anyTrueElements[v] << " and anyTrueElementsPartial[" 
00470                      << v << "] = " << anyTrueElementsPartial[v] 
00471                      << " ; inconsistent!" << endl);
00472           }
00473           anyTrueElements[v] += anyTrueElementsPartial[v];
00474         }
00475         notReceived--;
00476       }
00477       msg3 = new Message();
00478       msg3->put(anyTrueElements, anyTrueElements + vnodes);
00479       // Broadcast fully-filled array to other PE's:
00480       Ippl::Comm->broadcast_others(msg3, completeTag);
00481       delete [] anyTrueElementsPartial;
00482     } else {
00483       // Send my partially-filled array to PE 0:
00484       msg3 = new Message();
00485       msg3->put(anyTrueElements, anyTrueElements + vnodes);
00486       Ippl::Comm->send(msg3, 0, partialTag);
00487       // Receive fully-filled array from PE 0:
00488       int pe0 = 0;
00489       msg3 = Ippl::Comm->receive_block(pe0, completeTag);
00490       msg3->get(anyTrueElements);
00491     }
00492     delete msg3;
00493 
00494     // Loop through the PE's owned LField's (<==> Vnode's) in vf2:
00495     BareField<double,Dim>::iterator_if vf2Itr;
00496     for (vf2Itr = vf2.begin_if(); vf2Itr != vf2.end_if(); ++vf2Itr) {
00497     
00498       // Global integer index of this vnode:
00499       int vnode = (*vf2Itr).second->getVnode();
00500 
00501       // Assign the integer value from anyTrueElements to the corresponding
00502       // single element in vf2's corresponding vnode: The use of the special
00503       // LField::Compress(double val) function is a trick; we know that the vf2
00504       // Field can be compressed (and probably always is); using this function
00505       // assigns the CompressedData value directly, or else compresses the LField
00506       // and sets CompressedData to the requested value if for some reason it
00507       // wasn't already compressed:
00508       (*vf2Itr).second->Compress(anyTrueElements[vnode]);
00509 
00510     }
00511 
00512     // Now invoke BinaryBalancer on the small Field vf2:
00513     BinaryRepartition(l2, vf2);
00514 
00515     // ***********************************************************************
00516 
00517     // Check once again for boo-boos (zero-length vnodes); if found, abandon balance:
00518     // Find and record all zero-length vnodes in l; each PE can check for this
00519     // independently, since all have domain size info for both local and remote
00520     // vnodes:
00521     int nZeroSizeVnodes2 = 0;
00522     // Locals:
00523     FieldLayout<Dim>::iterator_iv l2Locals;
00524     for (l2Locals = l2.begin_iv(); l2Locals != l2.end_iv(); ++l2Locals) {
00525       if ((*l2Locals).second->getDomain().size() == 0) {nZeroSizeVnodes2 += 1;}
00526     }
00527     // Remotes:
00528     FieldLayout<Dim>::iterator_dv l2Remotes;
00529     for (l2Remotes = l2.begin_rdv(); l2Remotes != l2.end_rdv(); ++l2Remotes) {
00530       if ((*l2Remotes).second->getDomain().size() == 0) {nZeroSizeVnodes2 += 1;}
00531     }
00532     // If none are zero, go on from here. If any are zero, have to go back and
00533     // find them, and find suitable nonzero ones to divide to get one nonzero one
00534     // for each PE that owns a zero-size one:
00535     if (nZeroSizeVnodes2 != 0) {
00536       WARNMSG("VnodeMultiRepartition(): even on a desperate 2nd attempt by adding in some"
00537               << "random nonzero vnodes, was not able to get a successful rebalance. So, "
00538               << "leaving the FieldLayout partioning the way it was when you called"
00539               << " VnodeMultiRepartition(). Sorry about that." << endl);
00540       return;
00541     } else {
00542       // Success! (Of some sort....); repartition vf and assign it to vf2. Do
00543       // this by setting l equal to l2 and doing l.Repartition():
00544       l = l2;
00545       l2.Repartition
00546       vf = vf2;
00547     }
00548   }
00549 #endif // GROSS
00550 
00551 /***************************************************************************
00552  * $RCSfile: VnodeMultiBalancer.cpp,v $   $Author: adelmann $
00553  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:27 $
00554  * IPPL_VERSION_ID: $Id: VnodeMultiBalancer.cpp,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $ 
00555  ***************************************************************************/

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