parallel/RCB.cpp

00001 // -*- C++ -*-
00002 //
00003 //  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00004 //
00005 //                                   Fehmi Cirak
00006 //                        California Institute of Technology
00007 //                           (C) 2004 All Rights Reserved
00008 //
00009 //  <LicenseText>
00010 //
00011 //  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00012 //
00013 // EDITED BY MATT GALLOWAY FOR USE WITH DAPTA
00014 
00015 #include "DAPTA.hpp"
00016 
00017 #include <cmath>
00018 #include <vector>
00019 #include <algorithm>
00020 #include <functional>
00021 #include <cassert>
00022 #include <cstdlib>
00023 
00024 namespace DAPTA { // Define namespace DAPTA
00025 
00026 template <typename V>
00027 std::vector<int> RCBDecomposer<V>::decompose(unsigned numberOfPartitions, unsigned myNumber) {
00028    std::vector<int> myNodes;
00029 
00030     // head of the RCB tree
00031     RCBTree *head = new RCBTree(this->vertices.begin(), this->vertices.end(), 0);
00032         
00033     // maximum height of the RCB tree
00034     int maxLevel = (int)std::ceil(std::log((double)numberOfPartitions)/std::log(2.0));
00035 
00036     // RCB partitioning
00037     buildRCBTree(head, maxLevel);
00038 
00039     // assign the RCB nodes to the processors
00040     std::vector<PointIt> leafDataBegins, leafDataEnds;    
00041     leafDataBegins.reserve(numberOfPartitions*2);
00042     leafDataEnds.reserve(numberOfPartitions*2);
00043     collectLeafNodeData(head, leafDataBegins, leafDataEnds);
00044     
00045     std::vector<PointIt> collectProcBegins, collectProcEnds;
00046     collectProcBegins.reserve(leafDataBegins.size());
00047     collectProcEnds.reserve(leafDataEnds.size());
00048     
00049     // combine leafs so that there are as many subdomains as processors
00050     unsigned numLeafs = leafDataBegins.size();
00051     unsigned offSet=0;
00052     while (numLeafs!=numberOfPartitions) {
00053       collectProcBegins.push_back(leafDataBegins[offSet]);
00054       collectProcEnds.push_back(leafDataEnds[offSet+1]);
00055       offSet += 2;
00056       --numLeafs;
00057     }
00058     
00059     // just copy the remaining leafs
00060     for (unsigned j=offSet; j<leafDataBegins.size(); ++j) {
00061       collectProcBegins.push_back(leafDataBegins[j]);
00062       collectProcEnds.push_back(leafDataEnds[j]);
00063     }
00064     
00065     for (unsigned i=0; i<collectProcBegins.size(); ++i) {
00066       if (i!=myNumber) continue;
00067       for (PointIt it = collectProcBegins[i]; it!=collectProcEnds[i]; ++it) {
00068          myNodes.push_back((*it)->globalID);
00069       }
00070     }
00071 
00072     // delete the tree
00073     delete head;
00074    
00075    return myNodes;
00076 }
00077 
00078 // compute the longest axis
00079 template <typename V>
00080 int RCBDecomposer<V>::maxBoxInDimension(PointIt begin, PointIt end) {
00081    typename V::CoordType low[V::dimension];
00082    typename V::CoordType upper[V::dimension];
00083       
00084    assert(begin!=end);
00085    for (unsigned i=0; i<V::dimension; ++i) {
00086       low[i] = (*begin)->coords.at(i);
00087       upper[i] = low[i];
00088    }
00089    
00090    for (PointIt it=begin; it!=end; ++it) {
00091       for (unsigned i=0; i<V::dimension; ++i) {
00092          low[i] = std::min(low[i], (*it)->coords.at(i));
00093          upper[i] = std::max(upper[i], (*it)->coords.at(i));
00094       }
00095    }
00096    
00097    typename V::CoordType maxBox = upper[0]-low[0];
00098    unsigned maxDim = 0;
00099    for (unsigned i=1; i<V::dimension; ++i) {
00100       if ((upper[i]-low[i])>maxBox) {
00101          maxBox = upper[i]-low[i];
00102          maxDim = i;
00103       }
00104    }
00105    
00106    return maxDim;
00107 }
00108    
00109 // recursive partitioning function
00110 template <typename V>
00111 void RCBDecomposer<V>::buildRCBTree(RCBTree *tree, const int& maxLevel) {
00112    // compute the longest axis
00113    // todo: this computation can be done more efficiently
00114    int partAxis = maxBoxInDimension(tree->_dataBegin, tree->_dataEnd);
00115    
00116    // sort along the longest axis
00117    std::sort(tree->_dataBegin, tree->_dataEnd, VertexComparison<V>(partAxis));
00118    
00119    // create two new children and add to the tree
00120    int size = tree->_dataEnd-tree->_dataBegin;
00121    if (size<1) return;
00122    int middle = size/2;
00123    
00124    tree->_childL = new RCBTree(tree->_dataBegin, tree->_dataBegin+middle, 
00125                         tree->_level+1);
00126    tree->_childR = new RCBTree(tree->_dataBegin+middle, tree->_dataEnd, 
00127                         tree->_level+1);
00128    
00129    // recurse until maximum tree height is reached
00130    if (tree->_childL->_level<maxLevel) {
00131       buildRCBTree(tree->_childL, maxLevel);
00132       buildRCBTree(tree->_childR, maxLevel);
00133    }
00134       
00135    return;
00136 }
00137     
00138 // recursive leaf collecter
00139 template <typename V>
00140 void RCBDecomposer<V>::collectLeafNodeData(RCBTree *tree, std::vector<PointIt>& begins, 
00141                               std::vector<PointIt>& ends) {
00142    if (leaf(tree)) {
00143       assert(tree != NULL);
00144       begins.push_back(tree->_dataBegin);
00145       ends.push_back(tree->_dataEnd);
00146    } else {
00147       collectLeafNodeData(tree->_childL, begins, ends);     
00148       collectLeafNodeData(tree->_childR, begins, ends);     
00149    }
00150 }
00151 
00152 } // namespace DAPTA

Generated on Tue May 29 17:13:49 2007 for DAPTA by  doxygen 1.5.1