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 "Particle/ParticleBalancer.h" 00028 #include "Particle/ParticleBase.h" 00029 #include "Particle/ParticleSpatialLayout.h" 00030 #include "Particle/ParticleUniformLayout.h" 00031 #include "Particle/ParticleAttrib.h" 00032 #include "Particle/IntNGP.h" 00033 #include "Region/RegionLayout.h" 00034 #include "Index/NDIndex.h" 00035 #include "FieldLayout/FieldLayout.h" 00036 #include "FieldLayout/BinaryBalancer.h" 00037 #include "Utility/IpplInfo.h" 00038 #include "Profile/Profiler.h" 00039 00040 00042 // calculate a new RegionLayout for a given ParticleBase, and distribute the 00043 // new RegionLayout to all the nodes. This uses a Field BinaryBalancer. 00044 template < class T, unsigned Dim, class Mesh> 00045 void 00046 BinaryRepartition(ParticleBase<ParticleSpatialLayout<T,Dim,Mesh> >& PB) { 00047 TAU_TYPE_STRING(taustr, "void (" + CT(PB) + " )"); 00048 TAU_PROFILE("BinaryRepartition()", taustr, TAU_PARTICLE); 00049 00050 static IntNGP interp; // to scatter particle density 00051 00052 //Inform dbgmsg("Particle BinaryRepartition", INFORM_ALL_NODES); 00053 //dbgmsg << "Performing particle load balancing, for "; 00054 //dbgmsg << PB.getTotalNum() << " particles ..." << endl; 00055 00056 // get the internal FieldLayout from the Particle object's internal 00057 // RegionLayout. From this, we make a new Field (we do not need a 00058 RegionLayout<T,Dim,Mesh>& RL = PB.getLayout().getLayout(); 00059 if ( ! RL.initialized()) { 00060 ERRORMSG("Cannot repartition particles: uninitialized layout." << endl); 00061 return; 00062 } 00063 FieldLayout<Dim>& FL = RL.getFieldLayout(); 00064 Mesh& mesh = RL.getMesh(); 00065 00066 // NDIndex which describes the entire domain ... if a particle is 00067 // outside this region, we are in trouble! 00068 const NDIndex<Dim>& TotalDomain = FL.getDomain(); 00069 00070 // for all the particles, do the following: 00071 // 1. get the position, and invert to the 'FieldLayout' index space 00072 // 2. increment the field at the position near this index position 00073 NDIndex<Dim> indx; 00074 00075 // By default, we do the number density computation and repartition of 00076 // index space on a cell-centered Field. If FieldLayout is vertex-centered, 00077 // we'll need to make some adjustments here. 00078 bool CenterOffset[Dim]; 00079 int CenteringTotal = 0; 00080 unsigned int d; 00081 for (d=0; d<Dim; ++d) { 00082 CenterOffset[d] = (TotalDomain[d].length() < mesh.gridSizes[d]); 00083 CenteringTotal += CenterOffset[d]; 00084 } 00085 00086 if (CenteringTotal == Dim) { // allCell centering 00087 Field<double,Dim,Mesh,Cell> BF(mesh,FL,GuardCellSizes<Dim>(1)); 00088 00089 // Now do a number density scatter on this Field 00090 // Afterwards, the Field will be deleted, and will checkout of the 00091 // FieldLayout. This is desired so that when we repartition the 00092 // FieldLayout, we do not waste time redistributing the Field's data. 00093 BF = 0.0; 00094 scatter(BF,PB.R,interp); 00095 00096 // calculate a new repartitioning of the field, and use this to repartition 00097 // the FieldLayout used inside the Particle object 00098 indx = CalcBinaryRepartition(FL, BF); 00099 } 00100 else if (CenteringTotal == 0) { // allVert centering 00101 Field<double,Dim,Mesh,Vert> BF(mesh,FL,GuardCellSizes<Dim>(1)); 00102 00103 // Now do a number density scatter on this Field 00104 // Afterwards, the Field will be deleted, and will checkout of the 00105 // FieldLayout. This is desired so that when we repartition the 00106 // FieldLayout, we do not waste time redistributing the Field's data. 00107 BF = 0.0; 00108 scatter(BF,PB.R,interp); 00109 00110 // calculate a new repartitioning of the field, and use this to repartition 00111 // the FieldLayout used inside the Particle object 00112 indx = CalcBinaryRepartition(FL, BF); 00113 } 00114 else { 00115 ERRORMSG("Not implemented for face- and edge-centered Fields!!" << endl); 00116 Ippl::abort(); 00117 } 00118 00119 // now, we can repartition the FieldLayout within the RegionLayout 00120 RL.RepartitionLayout(indx); 00121 PB.update(); 00122 } 00123 00124 00125 // the same, but taking a uniform layout (this will not actually do anything) 00126 template<class T, unsigned Dim> 00127 void 00128 BinaryRepartition(ParticleBase<ParticleUniformLayout<T,Dim> >&) { 00129 // for a uniform layout, this repartition method does nothing, so just 00130 // exit 00131 return; 00132 } 00133 00134 00135 /*************************************************************************** 00136 * $RCSfile: ParticleBalancer.cpp,v $ $Author: adelmann $ 00137 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:28 $ 00138 * IPPL_VERSION_ID: $Id: ParticleBalancer.cpp,v 1.1.1.1 2003/01/23 07:40:28 adelmann Exp $ 00139 ***************************************************************************/ 00140 00141