00001
00002 #include "mpi.h"
00003 #include "petsc.h"
00004 #include "sys.h"
00005 #include "octUtils.h"
00006 #include "TreeNode.h"
00007 #include "parUtils.h"
00008 #include "testUtils.h"
00009 #include <cstring>
00010 #include "externVars.h"
00011 #include "dendro.h"
00012
00013
00014 #ifdef MPI_WTIME_IS_GLOBAL
00015 #undef MPI_WTIME_IS_GLOBAL
00016 #endif
00017
00018 int main(int argc, char ** argv ) {
00019 int size, rank;
00020 double startTime, endTime, minTime;
00021 unsigned int incInt = 1;
00022 bool incCorner = 1;
00023 unsigned int numPts;
00024 unsigned int writePOut = 0;
00025 unsigned int writeBOut = 0;
00026 unsigned int readPtsFile = 0;
00027 unsigned int readOctFile =0;
00028 unsigned int runOpt =2;
00029 char Kstr[20];
00030 char inpFileName[50],p2nOut[50],n2oOut[50],balOut[50],coarseOut[50];
00031 double gSize[3];
00032
00033 PetscInitialize(&argc,&argv,"options",NULL);
00034 ot::RegisterEvents();
00035
00036 #ifdef PETSC_USE_LOG
00037 int stages[4];
00038 PetscLogStageRegister(&stages[0],"Prepare Input.");
00039 PetscLogStageRegister(&stages[1],"P2O");
00040 PetscLogStageRegister(&stages[2],"N2O");
00041 PetscLogStageRegister(&stages[3],"Bal");
00042 #endif
00043
00044 MPI_Comm_size(MPI_COMM_WORLD,&size);
00045 MPI_Comm_rank(MPI_COMM_WORLD,&rank);
00046 if(argc < 3) {
00047 std::cerr << "Usage: " << argv[0] << " inpfile complx incInt[1] runOpt[2]"<<
00048 "readPtsFile[0] readOctFile[0] maxDepth[30] writePOut[0] writeBOut[0]"<<
00049 " dim[3] maxNumPtsPerOctant[1] incCorner[0] " << std::endl;
00050 return -1;
00051 }
00052 unsigned int maxNumPts= 1;
00053 int complx = atoi(argv[2]);
00054 unsigned int dim=3;
00055 unsigned int maxDepth=30;
00056 if(argc > 3) {
00057 incInt = atoi(argv[3]);
00058 }
00059 if(argc > 4) {
00060 runOpt = atoi(argv[4]);
00061 }
00062 if(argc > 5) {
00063 readPtsFile = atoi(argv[5]);
00064 }
00065 if(argc > 6) {
00066 readOctFile = atoi(argv[6]);
00067 }
00068 if(argc > 7) {
00069 maxDepth = atoi(argv[7]);
00070 }
00071 if(argc > 8) {
00072 writePOut = atoi(argv[8]);
00073 }
00074 if(argc > 9) {
00075 writeBOut = atoi(argv[9]);
00076 }
00077 if(argc > 10) {
00078 dim = atoi(argv[10]);
00079 }
00080 if(argc > 11) {
00081 maxNumPts = atoi(argv[11]);
00082 }
00083 if(argc > 12) { incCorner = (bool)(atoi(argv[12]));}
00084
00085 strcpy(inpFileName, argv[1]);
00086 strcpy(balOut,inpFileName);
00087 ot::int2str(rank,Kstr);
00088 strcat(balOut,Kstr);
00089 strcat(balOut,"_\0");
00090 ot::int2str(size,Kstr);
00091 strcat(balOut,Kstr);
00092 strcpy(n2oOut,balOut);
00093 strcpy(p2nOut,balOut);
00094 strcpy(coarseOut,balOut);
00095 strcat(balOut,"_Bal.ot\0");
00096 strcat(coarseOut,"_Coarse.ot\0");
00097 strcat(n2oOut,"_Con.ot\0");
00098 strcat(p2nOut,".pts\0");
00099 strcat(inpFileName,".inp\0");
00100 std::vector<ot::TreeNode> nodes;
00101 std::vector<double> pts;
00102 unsigned int ptsLen;
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 #ifdef PETSC_USE_LOG
00113 PetscLogStagePush(stages[0]);
00114 #endif
00115 if(runOpt == 1 || runOpt == 2) {
00116 if(readPtsFile) {
00117 if(!rank){
00118 std::cout << " reading "<<p2nOut<<std::endl;
00119 }
00120 ot::readPtsFromFile(p2nOut, pts);
00121 if(!rank){
00122 std::cout << " finished reading "<<p2nOut<<std::endl;
00123 }
00124 ptsLen = pts.size();
00125 std::vector<ot::TreeNode> tmpNodes;
00126 for(unsigned int i = 0; i < ptsLen; i+= 3) {
00127 if( (pts[i] > 0.0) &&
00128 (pts[i+1] > 0.0)
00129 && (pts[i+2] > 0.0) &&
00130 ( (static_cast<unsigned int>(pts[i]*(static_cast<double>(1u<<maxDepth)))) < (1u<<maxDepth)) &&
00131 ( (static_cast<unsigned int>(pts[i+1]*(static_cast<double>(1u<<maxDepth)))) < (1u<<maxDepth)) &&
00132 ( (static_cast<unsigned int>(pts[i+2]*(static_cast<double>(1u<<maxDepth)))) < (1u<<maxDepth)) ) {
00133 tmpNodes.push_back( ot::TreeNode(
00134 static_cast<unsigned int>(pts[i]*static_cast<double>(1u<<maxDepth)),
00135 static_cast<unsigned int>(pts[i+1]*static_cast<double>(1u<<maxDepth)),
00136 static_cast<unsigned int>(pts[i+2]*static_cast<double>(1u<<maxDepth)),
00137 maxDepth,dim,maxDepth) );
00138 }
00139 }
00140 pts.clear();
00141
00142 par::removeDuplicates<ot::TreeNode>(tmpNodes,false,MPI_COMM_WORLD);
00143
00144 nodes = tmpNodes;
00145 tmpNodes.clear();
00146 par::partitionW<ot::TreeNode>(nodes, NULL,MPI_COMM_WORLD);
00147
00148 DendroIntL locSz, totalSz;
00149 locSz = nodes.size();
00150
00151 par::Mpi_Reduce<DendroIntL>(&locSz, &totalSz, 1, MPI_SUM, 0, MPI_COMM_WORLD);
00152
00153 if(rank==0) {
00154 std::cout<<"rank= "<<rank<<" size= " << size << " total pts= " << totalSz<<std::endl;
00155 }
00156
00157 pts.resize(3*(nodes.size()));
00158 ptsLen = (3*(nodes.size()));
00159 for(unsigned int i = 0; i < nodes.size(); i++) {
00160 pts[3*i] = (((double)(nodes[i].getX())) + 0.5)/((double)(1u << maxDepth));
00161 pts[(3*i)+1] = (((double)(nodes[i].getY())) +0.5)/((double)(1u << maxDepth));
00162 pts[(3*i)+2] = (((double)(nodes[i].getZ())) +0.5)/((double)(1u << maxDepth));
00163 }
00164 nodes.clear();
00165 }
00166 gSize[0] = 1.;
00167 gSize[1] = 1.;
00168 gSize[2] = 1.;
00169 #ifdef PETSC_USE_LOG
00170 PetscLogStagePop();
00171 #endif
00172 MPI_Barrier(MPI_COMM_WORLD);
00173 #ifdef PETSC_USE_LOG
00174 PetscLogStagePush(stages[1]);
00175 #endif
00176 startTime = MPI_Wtime();
00177 ot::points2Octree(pts, gSize, nodes, dim, maxDepth, maxNumPts, MPI_COMM_WORLD);
00178 endTime = MPI_Wtime();
00179 #ifdef PETSC_USE_LOG
00180 PetscLogStagePop();
00181 #endif
00182 double locTime, totalTime, minTime;
00183 locTime = endTime - startTime;
00184 par::Mpi_Reduce<double>(&locTime, &totalTime, 1, MPI_MAX, 0, MPI_COMM_WORLD);
00185 par::Mpi_Reduce<double>(&locTime, &minTime, 1, MPI_MIN, 0, MPI_COMM_WORLD);
00186 if(!rank){
00187 std::cout <<"P2n Time: "<<totalTime << " " << "secs imbalance: "<< totalTime/minTime << std::endl;
00188 }
00189 pts.clear();
00190 }
00191
00192 if(runOpt == 0 || runOpt == 2) {
00193 if(readOctFile) {
00194 ot::readNodesFromFile(n2oOut,nodes);
00195 }
00196 std::vector<ot::TreeNode > linOct;
00197 #ifdef PETSC_USE_LOG
00198 PetscLogStagePush(stages[2]);
00199 #endif
00200 DendroIntL inputNodes = nodes.size();
00201 DendroIntL totInp;
00202 par::Mpi_Reduce<DendroIntL>(&inputNodes, &totInp, 1, MPI_SUM, 0, MPI_COMM_WORLD);
00203 if(!rank) {
00204 std::cout << "Nodes after p2o: "<< totInp << std::endl;
00205 }
00206 ot::completeOctree(nodes, linOct, dim, maxDepth, false, false, false, MPI_COMM_WORLD);
00207 #ifdef PETSC_USE_LOG
00208 PetscLogStagePop();
00209 #endif
00210
00211 assert(!linOct.empty());
00212 if(writeBOut) {
00213 ot::writeNodesToFile(n2oOut,linOct);
00214 }
00215 inputNodes = linOct.size();
00216 nodes.clear();
00217 std::vector<ot::TreeNode > balOct;
00218
00219 par::Mpi_Reduce<DendroIntL>(&inputNodes, &totInp, 1, MPI_SUM, 0, MPI_COMM_WORLD);
00220 if(!rank) {
00221 std::cout << "Nodes before balancing: "<< totInp << std::endl;
00222 }
00223
00224 MPI_Barrier(MPI_COMM_WORLD);
00225 #ifdef PETSC_USE_LOG
00226 PetscLogStagePush(stages[3]);
00227 #endif
00228 startTime = MPI_Wtime();
00229
00230 ot::balanceOctree (linOct, balOct, dim, maxDepth, incCorner, MPI_COMM_WORLD, NULL, NULL);
00231 endTime = MPI_Wtime();
00232 MPI_Barrier(MPI_COMM_WORLD);
00233 if(!rank) {
00234 std::cout << "balancing time: "<< (endTime-startTime) << std::endl;
00235 }
00236
00237 #ifdef PETSC_USE_LOG
00238 PetscLogStagePop();
00239 #endif
00240 assert(!balOct.empty());
00241 if(writeBOut) {
00242 ot::writeNodesToFile(balOut,balOct);
00243 }
00244
00245 DendroIntL locBalNodes = balOct.size();
00246 DendroIntL totBal, totBalC, totBalSc;
00247 double balTime, totTime;
00248 balTime = endTime - startTime;
00249 par::Mpi_Reduce<DendroIntL>(&locBalNodes, &totBal, 1, MPI_SUM, 0, MPI_COMM_WORLD);
00250 if(!rank) {
00251 std::cout << "Nodes after balancing: "<< totBal << std::endl;
00252 }
00253
00254 std::vector<ot::TreeNode> allBal;
00255 std::vector<ot::TreeNode> allBalC;
00256 std::vector<ot::TreeNode> cBalP1;
00257 std::vector<ot::TreeNode> coarserOct;
00258 std::vector<ot::TreeNode> simpleCoarserOct;
00259
00260 MPI_Barrier(MPI_COMM_WORLD);
00261 startTime = MPI_Wtime();
00262 ot::coarsenOctree(balOct, coarserOct, dim, maxDepth, MPI_COMM_WORLD, false, NULL, NULL);
00263 endTime = MPI_Wtime();
00264 MPI_Barrier(MPI_COMM_WORLD);
00265 if(writeBOut) {
00266 ot::writeNodesToFile(coarseOut,coarserOct);
00267 }
00268 if(!rank) {
00269 std::cout << "coarsening time: "<< (endTime-startTime) << std::endl;
00270 }
00271
00272 MPI_Barrier(MPI_COMM_WORLD);
00273 startTime = MPI_Wtime();
00274 ot::simpleCoarsen(balOct, simpleCoarserOct, MPI_COMM_WORLD);
00275 endTime = MPI_Wtime();
00276 MPI_Barrier(MPI_COMM_WORLD);
00277 if(!rank) {
00278 std::cout << " simple coarsening time: "<< (endTime-startTime) << std::endl;
00279 }
00280
00281 DendroIntL locBalC = coarserOct.size();
00282 DendroIntL locBalSc = simpleCoarserOct.size();
00283 par::Mpi_Reduce<DendroIntL>(&locBalC, &totBalC, 1, MPI_SUM, 0, MPI_COMM_WORLD);
00284 par::Mpi_Reduce<DendroIntL>(&locBalSc, &totBalSc, 1, MPI_SUM, 0, MPI_COMM_WORLD);
00285
00286 if(!rank) {
00287 std::cout << "Nodes after Coarsening: "<< totBalC << std::endl;
00288 std::cout << "Nodes after simple Coarsening: "<< totBalSc << std::endl;
00289 }
00290
00291 assert(simpleCoarserOct == coarserOct);
00292 simpleCoarserOct.clear();
00293
00294 if(!rank) {
00295 std::cout<<"coarsening and simpleCoarsening match."<<std::endl;
00296 }
00297
00298 if(rank) {
00299 allBal.resize(0);
00300 allBalC.resize(0);
00301 }else {
00302 allBal.resize(totBal);
00303 allBalC.resize(totBalC);
00304 }
00305
00306 MPI_Barrier(MPI_COMM_WORLD);
00307 startTime = MPI_Wtime();
00308 par::scatterValues<ot::TreeNode>(balOct, allBal, allBal.size(), MPI_COMM_WORLD);
00309 endTime = MPI_Wtime();
00310 MPI_Barrier(MPI_COMM_WORLD);
00311 if(!rank) {
00312 std::cout << "scatter-1 time: "<< (endTime-startTime) << std::endl;
00313 }
00314
00315 MPI_Barrier(MPI_COMM_WORLD);
00316 startTime = MPI_Wtime();
00317 par::scatterValues<ot::TreeNode>(coarserOct, allBalC, allBalC.size(), MPI_COMM_WORLD);
00318 endTime = MPI_Wtime();
00319 MPI_Barrier(MPI_COMM_WORLD);
00320 if(!rank) {
00321 std::cout << "scatter-2 time: "<< (endTime-startTime) << std::endl;
00322 }
00323
00324 MPI_Comm zeroOnlyComm;
00325 if(size > 1) {
00326 par::splitComm2way(rank, &zeroOnlyComm, MPI_COMM_WORLD);
00327 }
00328
00329 if(!rank) {
00330 bool failed;
00331 failed = seq::test::isUniqueAndSorted<ot::TreeNode>(allBal);
00332 assert(failed);
00333 std::cout<<"Fine is unique and sorted."<<std::endl;
00334
00335 failed = ot::test::isLinear(allBal);
00336 assert(failed);
00337 std::cout<<"Fine is linear."<<std::endl;
00338
00339 failed = ot::test::isComplete(allBal);
00340 assert(failed);
00341 std::cout<<"Fine is complete."<<std::endl;
00342
00343 failed = ot::test::isBalanced(dim,maxDepth,
00344 "failedCheck_2_1_",allBal, incCorner,1);
00345 assert(failed);
00346 std::cout<<"Fine is balanced."<<std::endl;
00347
00348
00349 failed = seq::test::isUniqueAndSorted<ot::TreeNode>(allBalC);
00350 assert(failed);
00351 std::cout<<"Coarse is unique and sorted."<<std::endl;
00352
00353 failed = ot::test::isLinear(allBalC);
00354 assert(failed);
00355 std::cout<<"Coarse is linear."<<std::endl;
00356
00357 failed = ot::test::isComplete(allBalC);
00358 assert(failed);
00359 std::cout<<"Coarse is complete."<<std::endl;
00360
00361 failed = ot::test::isBalanced(dim,maxDepth,
00362 "failedCheck_4_1_",allBalC, incCorner,2);
00363 assert(failed);
00364 std::cout<<"Coarse is balanced."<<std::endl;
00365
00366 if(size > 1) {
00367 ot::coarsenOctree(allBal, cBalP1, dim, maxDepth, zeroOnlyComm, false, NULL, NULL);
00368 assert(cBalP1 == allBalC);
00369 std::cout<<"Coarsening in parallel is the same as coarsening on 1 processor."<<std::endl;
00370 }
00371 }
00372
00373 allBal.clear();
00374 allBalC.clear();
00375
00376 par::Mpi_Reduce<double>(&balTime, &totTime, 1, MPI_MAX, 0, MPI_COMM_WORLD);
00377 par::Mpi_Reduce<double>(&balTime, &minTime, 1, MPI_MIN, 0, MPI_COMM_WORLD);
00378
00379 if(!rank) {
00380 std::cout << "bal Time: "<<totTime << " " << "secs imbalance: "<< totTime/minTime << std::endl;
00381 }
00382 linOct.clear();
00383 balOct.clear();
00384 }
00385
00386 PetscFinalize();
00387
00388 }
00389