src/Field/AssignGeneralIBF.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 
00027 //
00028 // This file contains the version of assign() that work with 
00029 // general IndexedBareField = IndexedBareField expressions.  It will perform
00030 // general communication to exchange data if the LHS and RHS layouts
00031 // do not match.  It will also handle assignments between sliced fields,
00032 // permuted indices, etc.
00033 //
00035 
00036 // include files
00037 #include "Field/Assign.h"
00038 #include "Field/AssignDefs.h"
00039 #include "Field/BareField.h"
00040 #include "Field/BrickExpression.h"
00041 #include "Field/IndexedBareField.h"
00042 #include "Field/LField.h"
00043 #include "Message/Communicate.h"
00044 #include "Message/Message.h"
00045 #include "Utility/PAssert.h"
00046 #include "Utility/IpplInfo.h"
00047 #include "Utility/IpplStats.h"
00048 #include "Profile/Profiler.h"
00049 #include "PETE/IpplExpressions.h"
00050 
00051 #ifdef IPPL_STDSTL
00052 #include <map>
00053 #include <vector>
00054 #include <functional>
00055 #include <utility>
00056 using namespace std;
00057 #else
00058 #include <map.h>
00059 #include <vector.h>
00060 #include <function.h>
00061 #include <multimap.h>
00062 #endif
00063 
00064 #ifdef IPPL_USE_STANDARD_HEADERS
00065 #include <iostream>
00066 #include <typeinfo>
00067 using namespace std;
00068 #else
00069 #include <iostream.h>
00070 #include <typeinfo.h>
00071 #endif
00072 
00073 
00075 //
00076 // Send out messages needed to do an IBF = IBF assignment.
00077 //
00079 
00080 template<class T1, class T2, unsigned D1, unsigned D2>
00081 inline void
00082 IndexedSend(IndexedBareField<T1,D1,D1>& ilhs,
00083             IndexedBareField<T2,D2,D2>& irhs,
00084             int tag)
00085 {
00086   TAU_TYPE_STRING(taustr, "void (" + CT(ilhs) + ", " + CT(irhs) + ", int)" );
00087   TAU_PROFILE("IndexedSend()", taustr, TAU_FIELD);
00088 
00089   // debugging output macros.  these are only enabled if DEBUG_ASSIGN is
00090   // defined.
00091   ASSIGNMSG(Inform msg("IndexedSend", INFORM_ALL_NODES));
00092   ASSIGNMSG(msg << "Sending out messages for IBF[" << ilhs.getDomain());
00093   ASSIGNMSG(msg << "] = IBF[" << irhs.getDomain() << "] ..." << endl);
00094 
00095   // Get the BareField for the left and right hand sides.
00096   BareField<T1,D1> &lhs = ilhs.getBareField();
00097   BareField<T2,D2> &rhs = irhs.getBareField();
00098   typename BareField<T2,D2>::iterator_if rf_i, rf_e = rhs.end_if();
00099   T2 compressed_value;
00100 
00101   // set up messages to be sent
00102   int nprocs = Ippl::getNodes();
00103   Message** mess = new Message*[nprocs];
00104   int iproc;
00105   for (iproc=0; iproc<nprocs; ++iproc) 
00106     mess[iproc] = 0;
00107 
00108   // Loop over all the local nodes of the right hand side and
00109   // send data to the remote ones they overlap on the left hand side.
00110   for (rf_i = rhs.begin_if(); rf_i != rf_e; ++rf_i) {
00111     // Cache some information about this local array.
00112     LField<T2,D2> &rf = *((*rf_i).second);
00113     const NDIndex<D2>& ro = rf.getOwned();
00114 
00115     // Is this local field in the given right hand side domain?
00116     if ( ro.touches( irhs.getDomain() ) ) {
00117       // They touch, find the intersection.
00118       NDIndex<D2> rt = irhs.getDomain().intersect( ro );
00119 
00120       // Find the lhs domain where this is going to go.
00121       NDIndex<D1> lt = ilhs.getDomain().plugBase( rt );
00122 
00123       // Loop over the remote parts of lhs to find where to send stuff.
00124       typename FieldLayout<D1>::touch_range_dv
00125         range(lhs.getLayout().touch_range_rdv(lt,lhs.getGuardCellSizes()));
00126       typename FieldLayout<D1>::touch_iterator_dv remote_i;
00127       for (remote_i = range.first; remote_i != range.second; ++remote_i) {
00128         // Find the intersection.
00129         NDIndex<D1> left_intersect = lt.intersect( (*remote_i).first );
00130 
00131         // Find out who owns this remote domain
00132         int rnode = (*remote_i).second->getNode();
00133 
00134         // Forward substitute to get the domain in the rhs.
00135         NDIndex<D2> right_intersect =
00136           irhs.getDomain().plugBase(left_intersect);
00137 
00138         // Build the iterator for the data.
00139         typename LField<T2,D2>::iterator rhs_i =
00140           rf.begin(right_intersect, compressed_value);
00141 
00142         ASSIGNMSG(msg << "Sending IndexedField data from domain ");
00143         ASSIGNMSG(msg << right_intersect << " to domain " << left_intersect);
00144         ASSIGNMSG(msg << endl);
00145 
00146         // Permute the loop order so that they agree.
00147         CompressedBrickIterator<T2,D1> prhs_i =
00148           rhs_i.permute(right_intersect,left_intersect);
00149 
00150         // Try to compress it.
00151         prhs_i.TryCompress();
00152 
00153         // put data into proper message
00154         if (!mess[rnode]) mess[rnode] = new Message;
00155         PAssert(mess[rnode]);
00156         left_intersect.putMessage(*mess[rnode]);
00157         prhs_i.putMessage(*mess[rnode]);
00158       }  // loop over touching remote nodes
00159     }
00160   }  // loop over LFields
00161 
00162   // send all the messages
00163   for (iproc=0; iproc<nprocs; ++iproc) {
00164     if (mess[iproc])
00165       Ippl::Comm->send(mess[iproc],iproc,tag);
00166   }
00167 
00168   delete [] mess;
00169   return;
00170 }
00171 
00172 
00174 //
00175 // Calculate what messages we expect to receiving during an IBF = IBF assign.
00176 //
00178 
00179 template<class T1, class T2, unsigned D1, unsigned D2, class Container>
00180 inline void
00181 CalcIndexedReceive(IndexedBareField<T1,D1,D1>& ilhs,
00182                    IndexedBareField<T2,D2,D2>& irhs,
00183                    Container& recv_ac, int& msgnum)
00184 {
00185   TAU_TYPE_STRING(taustr, "void (" + CT(ilhs) + ", " + CT(irhs) + ", " +
00186                   CT(recv_ac) + " )" );
00187   TAU_PROFILE("CalcIndexedReceive()", taustr, TAU_FIELD);
00188 
00189   // debugging output macros.  these are only enabled if DEBUG_ASSIGN is
00190   // defined.
00191   ASSIGNMSG(Inform msg("CalcIndexedReceive", INFORM_ALL_NODES));
00192   ASSIGNMSG(msg << "Computing receive messages for IBF[" << ilhs.getDomain());
00193   ASSIGNMSG(msg << "] = IBF[" << irhs.getDomain() << "] ..." << endl);
00194 
00195   // Get the BareField for the left and right hand sides.
00196   BareField<T1,D1> &lhs = ilhs.getBareField();
00197   BareField<T2,D2> &rhs = irhs.getBareField();
00198   typename BareField<T1,D1>::iterator_if lf_i, lf_e = lhs.end_if();
00199 
00200   int nprocs = Ippl::getNodes();
00201   bool* recvmsg = new bool[nprocs];
00202   int iproc;
00203   for (iproc=0; iproc<nprocs; ++iproc)
00204     recvmsg[iproc] = false;
00205 
00206   // Loop over the locals.
00207   for (lf_i = lhs.begin_if(); lf_i != lf_e; ++lf_i) {
00208     // Cache some information about this LField.
00209     LField<T1,D1> &lf = *((*lf_i).second);
00210     const NDIndex<D1>& la = lf.getAllocated();
00211     // Is this local field in the domain in question.
00212     if ( la.touches( ilhs.getDomain() ) ) {
00213       // They touch.  Find the intersection.
00214       NDIndex<D1> lt = ilhs.getDomain().intersect( la );
00215       // Find the rhs domain this is coming from.
00216       NDIndex<D2> rt = irhs.getDomain().plugBase( lt );
00217       // Find the remote ones that that touch this.
00218       typename FieldLayout<D2>::touch_range_dv
00219         range( rhs.getLayout().touch_range_rdv(rt) );
00220       // Loop over them.
00221       typename FieldLayout<D2>::touch_iterator_dv rv_i;
00222       for (rv_i = range.first; rv_i != range.second; ++rv_i) {
00223         // Save the intersection and the LField it is for.
00224         NDIndex<D2> ri = rt.intersect((*rv_i).first);
00225         NDIndex<D1> li = ilhs.getDomain().plugBase( ri );
00226 
00227         ASSIGNMSG(msg << "Expecting IndexedField data from domain " << ri);
00228         ASSIGNMSG(msg << " for domain " << li << endl);
00229 
00230         typedef typename Container::value_type value_type;
00231         recv_ac.insert(value_type(li,&lf));
00232         // note who will be sending this data
00233         int rnode = (*rv_i).second->getNode();
00234         recvmsg[rnode] = true;
00235       }  // loop over remote nodes
00236     }
00237   }  // loop over LFields
00238 
00239   msgnum = 0;
00240   for (iproc=0; iproc<nprocs; ++iproc)
00241     if (recvmsg[iproc]) ++msgnum;
00242   delete [] recvmsg;
00243   return;
00244 }
00245 
00246 
00248 //
00249 // Assign between just the local blocks for an IBF = IBF assign.
00250 //
00252 
00253 template<class T1, class T2, unsigned D1, unsigned D2, class Op>
00254 inline void
00255 IndexedLocalAssign(IndexedBareField<T1,D1,D1>& ilhs,
00256                    IndexedBareField<T2,D2,D2>& irhs,
00257                    Op& op)
00258 {
00259   TAU_TYPE_STRING(taustr, "void (" + CT(ilhs) + ", " + CT(irhs) + ", " +
00260                   CT(op) + " )" );
00261   TAU_PROFILE("IndexedLocalAssign()", taustr, TAU_FIELD);
00262 
00263   // debugging output macros.  these are only enabled if DEBUG_ASSIGN is
00264   // defined.
00265   ASSIGNMSG(Inform msg("IndexedLocalAssign-IBF", INFORM_ALL_NODES));
00266   ASSIGNMSG(msg << "Computing general local assignment to IBF[");
00267   ASSIGNMSG(msg << ilhs.getDomain() << "] = IBF[");
00268   ASSIGNMSG(msg << irhs.getDomain() << "] ..." << endl);
00269 
00270   // Get the BareField for the left and right hand sides.
00271   BareField<T1,D1> &lhs = ilhs.getBareField();
00272   BareField<T2,D2> &rhs = irhs.getBareField();
00273 
00274   // Loop over all the local Fields of the lhs and all the local
00275   // fields in the rhs.
00276   // This is an N*N operation, but the expectation is that there won't
00277   // be TOO many Vnodes on a given processor.
00278   for (typename BareField<T1,D1>::iterator_if lf_i=lhs.begin_if();
00279        lf_i!=lhs.end_if(); ++lf_i)
00280     {
00281       // Cache some information about this LField.
00282       LField<T1,D1> &lf = *(*lf_i).second;
00283       const NDIndex<D1>& lo = lf.getOwned();
00284       const NDIndex<D1>& la = lf.getAllocated();
00285 
00286       // See if it touches the given domain.
00287       if ( lo.touches( ilhs.getDomain() ) )
00288         {
00289           ASSIGNMSG(msg << "----------------" << endl);
00290           ASSIGNMSG(msg << "Assigning to local LField with owned = " << lo);
00291           ASSIGNMSG(msg << endl);
00292 
00293           // Get the intersection.
00294           NDIndex<D1> lt = ilhs.getDomain().intersect( lo );
00295           ASSIGNMSG(msg << "Intersection lhs domain = " << lt << endl);
00296 
00297           // Transform into right hand side space.
00298           NDIndex<D2> rp = irhs.getDomain().plugBase( lt );
00299           ASSIGNMSG(msg << "Plugbase domain = " << rp << endl);
00300 
00301           // Loop over all the local lfields on the right.
00302           for (typename BareField<T2,D2>::iterator_if rf_i = rhs.begin_if();
00303                rf_i != rhs.end_if(); ++rf_i)
00304             {
00305               // Cache the domain for this local field.
00306               LField<T2,D2> &rf = *(*rf_i).second;
00307               const NDIndex<D2>& ra = rf.getAllocated();
00308               const NDIndex<D2>& ro = rf.getOwned();
00309 
00310               // Two cases:
00311               // 1. rhs allocated contains lhs owned
00312               //    Then this is a stencil and we should fill from allocated.
00313               //    Assume that nobody else will fill the owned spot.
00314               // 2. rhs allocated does not contain lhs owned.
00315               //    Then this is general communication and we
00316               //    should only fill from rhs owned.
00317               // I can construct cases for which this gives wrong answers
00318               // on += type operations.  We'll be able to fix this much much
00319               // easier with one sided communication.
00320 
00321               // If this local field touches the domain, we have work to do.
00322               // ra has unit stride so end-point "contains" is OK.
00323               const NDIndex<D2> &rd = ( ra.contains(rp) ? ra : ro );
00324               if ( rd.touches( rp ) )
00325                 {
00326                   // Get the intersection.  We'll copy out of this.
00327                   NDIndex<D2> rhsDomain = rp.intersect(rd);
00328 
00329                   // Transform that back.  We'll copy into this.
00330                   NDIndex<D1> lhsDomain = lt.plugBase(rhsDomain);
00331 
00332                   ASSIGNMSG(msg << "Found touching rhs field: assigning ");
00333                   ASSIGNMSG(msg << lhsDomain << " = " << rhsDomain << endl);
00334 
00335                   // Can we compress the left?
00336                   bool c1 = rf.IsCompressed();
00337 
00338                   // Not clear that lhs is unit stride, so call
00339                   // containsAllPoints...
00340                   bool c2 = lhsDomain.containsAllPoints(la);
00341                   bool c3 = OperatorTraits<Op>::IsAssign;
00342                   bool c4 = lf.IsCompressed();
00343                   ASSIGNMSG(msg << "Checking for possible compressed-assign:");
00344                   ASSIGNMSG(msg << "\n  rf.IsCompressed = " << c1);
00345                   ASSIGNMSG(msg << "\n  lhs.contains(allocatd) = " << c2);
00346                   ASSIGNMSG(msg << "\n  lf.IsCompressed = " << c4);
00347                   ASSIGNMSG(msg << "\n  Doing assignment = " << c3);
00348                   ASSIGNMSG(msg << "\n      Result = " << (c1&&c2&&(c3||c4)));
00349                   ASSIGNMSG(msg << endl);
00350                   if ( lhs.compressible() && c1 && c2 && ( c3 || c4 ) )
00351                     {
00352                       ASSIGNMSG(msg << "Can do compressed assign from rhs ");
00353                       ASSIGNMSG(msg << "to lhs." << endl);
00354 
00355                       // We can compress the left!
00356                       lf.Compress();
00357 
00358                       // Set the constant value.
00359                       PETE_apply(op, *lf.begin() , *rf.begin() );
00360                       ASSIGNMSG(msg << "After compress, " << *lf.begin());
00361                       ASSIGNMSG(msg << " = ");
00362                       ASSIGNMSG(msg << *rf.begin() << endl);
00363                     }
00364                   else
00365                     {
00366                       // Can't leave the left compressed.
00367                       // Only fill in the data if you have to.
00368                       bool c2 = lhsDomain.containsAllPoints(lo);
00369                       bool c3 = OperatorTraits<Op>::IsAssign;
00370                       bool filldom = ((!c2) || (!c3));
00371                       ASSIGNMSG(msg << "Must uncompress, filldom = ");
00372                       ASSIGNMSG(msg << filldom << endl);
00373                       lf.Uncompress(filldom);
00374 
00375                       // Types for the assignment.
00376                       typedef typename LField<T1,D1>::iterator LFI;
00377                       typedef typename LField<T2,D1>::iterator RFI;
00378                       typedef BrickExpression<D1,LFI,RFI,Op> Expr;
00379 
00380                       // Build iterators for the left and right hand sides.
00381                       RFI rhs_i =
00382                         rf.begin(rhsDomain).permute(rhsDomain,lhsDomain) ;
00383                       LFI lhs_i =
00384                         lf.begin(lhsDomain) ;
00385 
00386                       // And do the assignment.
00387                       ASSIGNMSG(msg << "Doing full loop assignment." << endl);
00388                       Expr(lhs_i,rhs_i,op).apply();
00389                     }
00390                 }
00391             }
00392         }
00393     }
00394 }
00395 
00396 
00398 //
00399 // Receive in needed messages and assign them to our storage
00400 // for an IBF = IBF assign.
00401 //
00403 
00404 template<class T1, class T2, unsigned D1, unsigned D2,
00405          class Op, class Container>
00406 inline void
00407 IndexedReceive(IndexedBareField<T1,D1,D1>& ilhs,
00408                IndexedBareField<T2,D2,D2>& irhs,
00409                Op& op,
00410                Container& recv_ac, int msgnum,
00411                int tag)
00412 {
00413   TAU_TYPE_STRING(taustr, "void (" + CT(ilhs) + ", " + CT(irhs) + ", " +
00414                   CT(op) + ", " + CT(recv_ac) + ", int )" );
00415   TAU_PROFILE("IndexedReceive()", taustr, TAU_FIELD);
00416 
00417   // debugging output macros.  these are only enabled if DEBUG_ASSIGN is
00418   // defined.
00419   ASSIGNMSG(Inform msg("IndexedReceive", INFORM_ALL_NODES));
00420   ASSIGNMSG(msg << "Receiving messages for IBF[" << ilhs.getDomain());
00421   ASSIGNMSG(msg << "] = IBF[" << irhs.getDomain() << "] ..." << endl);
00422 
00423   // Get the BareField for the left hand side.
00424   BareField<T1,D1> &lhs = ilhs.getBareField();
00425 
00426   // Build iterators within local fields on the left and right hand side.
00427   typedef typename LField<T1,D1>::iterator LFI;
00428   typedef CompressedBrickIterator<T2,D1> RFI;
00429 
00430   // The type for the expression.
00431   typedef BrickExpression<D1,LFI,RFI,Op> Expr;
00432 
00433   // Loop until we've received all the messages.
00434   while (msgnum>0) {
00435     // Receive the next message.
00436     int any_node = COMM_ANY_NODE;
00437     Message *mess = Ippl::Comm->receive_block(any_node,tag);
00438     PAssert(mess != 0);
00439     --msgnum;
00440     // determine the number of domains being sent
00441     int ndoms = mess->size() / (D1 + 3);
00442     for (int idom=0; idom<ndoms; ++idom) {
00443       // extract the next domain from the message
00444       NDIndex<D1> domain;
00445       domain.getMessage(*mess);
00446       // Extract the rhs iterator from it.
00447       T2 compressed_data;
00448       RFI rhs_i(compressed_data);
00449       rhs_i.getMessage(*mess);
00450 
00451       ASSIGNMSG(msg << "Received IndexedField data for domain " << domain);
00452       ASSIGNMSG(msg << endl);
00453 
00454       // Find the LField it is destined for.
00455       typename Container::iterator hit = recv_ac.find( domain );
00456       PAssert( hit != recv_ac.end() );
00457       LField<T1,D1> &lf = *(*hit).second;
00458 
00459       // Can we compress the left?
00460       bool c1 = rhs_i.IsCompressed();
00461       bool c2 = domain.containsAllPoints( lf.getAllocated() );
00462       bool c3 = OperatorTraits<Op>::IsAssign;
00463       bool c4 = lf.IsCompressed();
00464       if ( lhs.compressible() && c1 && c2 && ( c3 || c4 ) ) {
00465         // We can compress the left!
00466         lf.Compress();
00467         // Set the constant value.
00468         PETE_apply(op, *lf.begin() , *rhs_i);
00469       }
00470       else {
00471         // Can't leave the left compressed.
00472         // Only fill in the data if you have to.
00473         bool c2 = domain.containsAllPoints(lf.getOwned());
00474         bool c3 = OperatorTraits<Op>::IsAssign;
00475         lf.Uncompress( !(c2&&c3) );
00476         // Build iterators for the left and right hand sides.
00477         LFI lhs_i = lf.begin(domain);
00478         // And do the assignment.
00479         Expr(lhs_i,rhs_i,op).apply();
00480       }
00481 
00482       // Take that entry out of the receive list.
00483       recv_ac.erase( hit );
00484     }
00485     delete mess;
00486   }  // loop over messages to receive
00487   return;
00488 }
00489 
00490 
00492 //
00493 // A simple utility struct used to do touching calculations between
00494 // domains of different dimensions.  They only can possibly touch
00495 // if their dimensions are the same.
00496 //
00498 
00499 template<unsigned int D1, unsigned int D2>
00500 struct AssignTouches
00501 {
00502   static bool apply(const NDIndex<D1>&, const NDIndex<D2>&)
00503   {
00504     return false;
00505   }
00506 };
00507 
00508 template<unsigned int D1>
00509 struct AssignTouches< D1, D1 >
00510 {
00511   static bool apply(const NDIndex<D1>& x,const NDIndex<D1>& y)
00512   {
00513     return x.touches(y);
00514   }
00515 };
00516 
00517 
00519 //
00520 // Assign one IndexedBareField to another.  This works even if the two
00521 // are on different layouts and are different dimensionalities.
00522 //
00524 
00525 template<class T1, unsigned D1, class RHS, class Op>
00526 void
00527 assign(IndexedBareField<T1,D1,D1> lhs,
00528        RHS rhsp,
00529        Op op, ExprTag<false>)
00530 {
00531   // profiling macros
00532   // here, 'Op' is not used to form the type string, so the timings here
00533   // will be the sum of all different operators 'Op' used in the code.
00534   TAU_TYPE_STRING(p1, "void (" + CT(lhs) + ", " + CT(rhsp) + ", " + CT(op) 
00535     + ", ExprTag<false> )" );
00536   TAU_PROFILE("assign()", p1.data(), TAU_ASSIGN | TAU_FIELD);
00537   TAU_PROFILE_TIMER(sendtimer,   " assign[IndexedBareField]-send",
00538                     p1.data(), TAU_ASSIGN);
00539   TAU_PROFILE_TIMER(findtimer,   " assign[IndexedBareField]-findreceive", 
00540                     p1.data(),TAU_ASSIGN);
00541   TAU_PROFILE_TIMER(localstimer, " assign[IndexedBareField]-locals",
00542                     p1.data(), TAU_ASSIGN);
00543   TAU_PROFILE_TIMER(rectimer,    " assign[IndexedBareField]-recieve",
00544                     p1.data(), TAU_ASSIGN);
00545   TAU_PROFILE_TIMER(filltimer,   " assign[IndexedBareField]-fill",
00546                     p1.data(), TAU_ASSIGN);
00547 
00548   typedef typename RHS::PETE_Return_t T2;
00549   enum { D2=RHS::Dim_u };
00550   IndexedBareField<T2,D2,D2> rhs ( rhsp.getBareField()[ rhsp.getDomain() ] );
00551 
00552   // Make sure we aren't assigning into overlapping domains in the same array.
00553   // First test to see if they are the same array.
00554   if ( lhs.getBareField().get_Id() == rhs.getBareField().get_Id() )
00555     {
00556       // Now check to see if the domains overlap.
00557       if ( AssignTouches<D1,D2>::apply(lhs.getDomain(),rhs.getDomain()))
00558         {
00559           // They overlap.  Scream and die.
00560           ERRORMSG("Overlapping domains in indexed assignment!"<<endl);
00561           PAssert(0);
00562         }
00563     }
00564   
00565   // Get a unique tag for the messages here.
00566   int tag = Ippl::Comm->next_tag( F_GEN_ASSIGN_TAG , F_TAG_CYCLE );
00567 
00568   // Fill guard cells if necessary.
00569 
00570   for_each(rhs.begin(), FillGCIfNecessary(lhs.getBareField()), 
00571      PETE_NullCombiner());
00572 
00573   // ----------------------------------------
00574   // Send all the data from the right hand side
00575   // the the parts of the left hand side that need them.
00576   if (Ippl::getNodes() > 1) {
00577     TAU_PROFILE_START(sendtimer);
00578     IndexedSend(lhs,rhs,tag);
00579     TAU_PROFILE_STOP(sendtimer);
00580   }
00581 
00582   // ----------------------------------------
00583   // Build a map of the messages we expect to receive.
00584   multimap< NDIndex<D1> , LField<T1,D1>* , less< NDIndex<D1> > >  recv_ac;
00585   int msgnum;
00586   if (Ippl::getNodes() > 1) {
00587     TAU_PROFILE_START(findtimer);
00588     CalcIndexedReceive(lhs,rhs,recv_ac,msgnum);
00589     TAU_PROFILE_STOP(findtimer);
00590   }
00591 
00592   // ----------------------------------------
00593   // Handle the local fills.
00594   TAU_PROFILE_START(localstimer);
00595   IndexedLocalAssign(lhs,rhs,op);
00596   TAU_PROFILE_STOP(localstimer);
00597 
00598   // ----------------------------------------
00599   // Receive all the messages.
00600   if (Ippl::getNodes() > 1) {
00601     TAU_PROFILE_START(rectimer);
00602     IndexedReceive(lhs,rhs,op,recv_ac,msgnum,tag);
00603     TAU_PROFILE_STOP(rectimer);
00604   }
00605 
00606   lhs.getBareField().setDirtyFlag();
00607 
00608   // Update the guard cells.
00609   TAU_PROFILE_START(filltimer);
00610   lhs.getBareField().fillGuardCellsIfNotDirty();
00611   TAU_PROFILE_STOP(filltimer);
00612 
00613   // Compress the LHS.
00614   lhs.getBareField().Compress();
00615 
00616   //INCIPPLSTAT(incExpressions);
00617   //INCIPPLSTAT(incIBFEqualsIBF);
00618 }
00619 
00620 /***************************************************************************
00621  * $RCSfile: AssignGeneralIBF.cpp,v $   $Author: adelmann $
00622  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:26 $
00623  * IPPL_VERSION_ID: $Id: AssignGeneralIBF.cpp,v 1.1.1.1 2003/01/23 07:40:26 adelmann Exp $ 
00624  ***************************************************************************/

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