src/FieldLayout/ConejoBalancer_inst.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/ConejoBalancer.h"
00028 #include "FieldLayout/MultiBalancer.h"
00029 #include "Utility/IpplInfo.h"
00030 
00032 //
00033 // PUBLIC FUNCTIONS
00034 //
00036 
00037 //
00038 // The constructor for ConejoBalancer.
00039 // Record the number of processors in the system.
00040 //
00041 
00042 ConejoBalancer::ConejoBalancer()
00043 :
00044   // Initialize the pointer to the balancer to zero
00045   // because we can't construct it yet.
00046   m_balancer(0), 
00047   // Initialize the number of vnodes to -1 because we don't know that yet.
00048   m_localVnodes(-1),
00049   m_totalVnodes(-1),
00050   // Record the number of processors.
00051   m_procs( IpplInfo::getNodes() ),
00052   // Record which processor is mine.
00053   m_myProc( IpplInfo::myNode() )
00054 {
00055   // Record the number of vnodes on each processor.
00056   // Start the value out with -1 so we know if it has been set or not.
00057   m_vnodeCounts.resize(m_procs);
00058   for (int i=0; i<m_procs; ++i)
00059     m_vnodeCounts[i] = -1;
00060 }
00061 
00063 
00064 //
00065 // The destructor for ConejoBalancer.
00066 // Just delete the balancer.
00067 //
00068 
00069 ConejoBalancer::~ConejoBalancer()
00070 {
00071   delete m_balancer;
00072 }
00073 
00075 //
00076 // PRIVATE FUNCTIONS
00077 //
00079 
00080 //
00081 // ConejoBalancer::sendWeights
00082 //
00083 // INPUTS:
00084 // vnodeWeights: A vector<double> of weights for vnodes on this proc.
00085 // tag: an integer tag for the message.
00086 //
00087 // OUTPUTS:
00088 // Message is sent.
00089 //
00090 
00091 void
00092 ConejoBalancer::sendWeights(vector<double>& vnodeWeights, int tag)
00093 {
00094   // Build a message to be sent.
00095   Message *msg = new Message();
00096 
00097   // Add data to the message.
00098   // First the number of elements, then the elements themselves.
00099   msg->put(vnodeWeights.size());
00100   putMessage(*msg, vnodeWeights.begin(), vnodeWeights.end());
00101 
00102   // Send the message.
00103   Ippl::Comm->send(msg, 0, tag);
00104 }
00105 
00107 
00108 //
00109 // ConejoBalancer::receiveWeights
00110 //
00111 // INPUTS:
00112 // vnodeWeights: A vector<double>. Initially has the data from this
00113 //               processor. Used as a place to put incoming data.
00114 // tag: an integer tag for the messages.
00115 //
00116 // OUTPUTS:
00117 // Updated state of the ConejoBalancer with the data from 
00118 // the other processors.
00119 //
00120 
00121 void
00122 ConejoBalancer::receiveWeights(vector<double>& vnodeWeights, int tag)
00123 {
00124   // Tell the MultiBalancer that it is about to get a new material.
00125   m_balancer->newMaterial();
00126 
00127   // Receive messages from all the other processors.
00128   for ( int proc=0; proc < m_procs ; ++proc )
00129     {
00130       // Receive a message from the next proc.
00131       Message *msg = Ippl::Comm->receive_block(proc,tag);
00132 
00133       // Get the number of vnodes.
00134       long int count;
00135       msg->get(count);
00136       
00137       // Record the number of vnodes on that proc.
00138       recordVnodeCount(count,proc);
00139 
00140       // Allocate space for the incoming data.
00141       vnodeWeights.resize( count );
00142 
00143       // Unpack it.
00144       getMessage_iter(*msg, vnodeWeights.begin() );
00145 
00146       // Record it by extracting a double* from the vnodeWeights iterator.
00147       double *p = &*(vnodeWeights.begin());
00148       m_balancer->appendWeights(p,p+vnodeWeights.size());
00149 
00150       // Delete the message.
00151       delete msg;
00152     }
00153 }
00154 
00156 
00157 //
00158 // Tell the ConejoBalancer the number of vnodes it is dealing with.
00159 //
00160 // INPUT:
00161 //    localVnodes:  The number of vnodes on this processor.
00162 //    totalVnodes:  The total number of vnodes on all the processors.
00163 //
00164 // OUTPUT:
00165 //    Updated state of the ConejoBalancer.
00166 //    The number of vnodes is recorded.
00167 //    The MultiBalancer is initialized.
00168 //
00169 
00170 void
00171 ConejoBalancer::setupVnodes(int localVnodes, int remoteVnodes)
00172 {
00173   // The first time through we need to record the sizes, 
00174   // and build the balancer
00175   if ( m_balancer == 0 )
00176     {
00177       // Record the sizes.
00178       m_localVnodes = localVnodes;
00179       m_totalVnodes = localVnodes + remoteVnodes;
00180 
00181       // If we are processor zero, build the balancer object.
00182       if ( m_myProc == 0 )
00183         m_balancer = new MultiBalancer(m_procs,m_totalVnodes);
00184     }
00185   // If it isn't the first time, make sure this BareField
00186   // is consistent with the previous.
00187   else
00188     {
00189       PAssert(m_localVnodes == localVnodes);
00190       PAssert(m_totalVnodes == localVnodes + remoteVnodes);
00191       PAssert( (m_balancer!=0) == (m_myProc==0 ) );
00192     }
00193 }
00194 
00196 
00197 //
00198 // Tell the ConejoBalancer the number of vnodes on a given processor.
00199 //
00200 // INPUT:
00201 //   count: an integer for the number of vnodes
00202 //   proc:  an integer of the processor
00203 //
00204 // OUTPUT:
00205 //   Updated state of the ConejoBalancer.
00206 //   The first time it is called it records the count.
00207 //   After that, it checks to make sure the counts agree.
00208 //
00209 
00210 void 
00211 ConejoBalancer::recordVnodeCount(int count, int proc)
00212 {
00213   // Make sure this processor number makes sense.
00214   PAssert( proc >= 0 );
00215 
00216   // Check to see if this is the first time it is being called.
00217   if ( m_vnodeCounts[proc] < 0 )
00218     {
00219       // First time, record the count.
00220       m_vnodeCounts[proc] = count;
00221     }
00222   // Not the first time.
00223   else
00224     {
00225       // Make sure this count agrees with record.
00226       PAssert( m_vnodeCounts[proc] == count );
00227     }
00228 }
00229 
00231 
00232 //
00233 // ConejoBalancer::broadcastVnodesToSend
00234 //
00235 // Scan through the data in the MultiBalancer and figure out
00236 // which processors will be sending vnodes to where.
00237 // Broadcast that information to the processors that will
00238 // be sending.
00239 //
00240 // INPUT:
00241 //   tag: an integer message tag.
00242 //
00243 // OUTPUT:
00244 //   Messages sent.
00245 //
00246 
00247 void 
00248 ConejoBalancer::broadcastVnodesToSend(int tag)
00249 {
00250   // Get a pointer to the destination processors for each vnode.
00251   MultiBalancer::iterator vp = m_balancer->begin();
00252 
00253   // Loop over the source processors, sending data to each.
00254   for ( int sourceProc = 0; sourceProc < m_procs; ++sourceProc )
00255     {
00256       // Cache the number of vnodes on this processor.
00257       long int c = m_vnodeCounts[sourceProc];
00258 
00259       // Build the message.
00260       Message *msg = new Message;
00261       msg->put(c);
00262       putMessage(*msg, vp, vp + c);
00263 
00264       // Send the message.
00265       Ippl::Comm->send(msg,sourceProc,tag);
00266 
00267       // Increment the pointer to the destination processors.
00268       vp += c;
00269     }
00270 }
00271 
00273 
00274 //
00275 // ConejoBalancer::receiveVnodesToSend
00276 //
00277 // Every processor receives from processor zero the destinations
00278 // for its vnodes.
00279 //
00280 // INPUT:
00281 //   tag: an integer message tag.
00282 //
00283 // OUTPUT:
00284 //   vnodeDestinations: A vector<int>& to hold the destinations for 
00285 //                      all the vnodes on this proc.
00286 //
00287 
00288 void 
00289 ConejoBalancer::receiveVnodesToSend(vector<int>& vnodeDestinations, int tag)
00290 {
00291   // Receive the message from proc 0.
00292   int proc_zero = 0;
00293   Message *msg = Ippl::Comm->receive_block(proc_zero,tag);
00294 
00295   // Get the number of vnodes coming in.
00296   long int s;
00297   msg->get(s);
00298 
00299   // Extract the vnode destinations.
00300   vnodeDestinations.resize(s);
00301   getMessage_iter(*msg, vnodeDestinations.begin() );
00302 
00303   // Delete the message.
00304   delete msg;
00305 }
00306 
00307 /***************************************************************************
00308  * $RCSfile: ConejoBalancer_inst.cpp,v $   $Author: adelmann $
00309  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:27 $
00310  * IPPL_VERSION_ID: $Id: ConejoBalancer_inst.cpp,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $ 
00311  ***************************************************************************/

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