00001 00007 #include "TreeNode.h" 00008 #include "parUtils.h" 00009 00010 #ifdef __DEBUG__ 00011 #ifndef __DEBUG_OCT__ 00012 #define __DEBUG_OCT__ 00013 #endif 00014 #endif 00015 00016 namespace ot { 00017 00018 //Basic idea: Any octant with all possible neighbours inside blocks are 00019 //considered to be stable. This works on the assumption that the blocks are 00020 //internally balanced and inter-block boundaries are also balanced. So if all 00021 //possible neighbours of an octant are inside these blocks, then its entire 00022 //insulation layer is stable. Although, initially developed for checking 00023 //unstable inter-processor boundaries only,this idea is also applicable to 00024 //test stable remote octants in computing sendNodes for stage 2 communication 00025 //for balancing. 00026 //Assumptions: Blocks are sorted and unique and linear, nodes is sorted and unique and linear. 00027 //Every element in nodes is a decendant of or equal to some block. 00028 //Blocks are complete i.e. there are no gaps in the morton-space covered by 00029 //the blocks. 00030 //Some Blocks may be empty. 00031 00032 #define PICK_IPBB_SET_TN_VALUE res.push_back(nodes[nodeCnt]); 00033 00034 #define PICK_IPBB_SET_UI_VALUE res.push_back(nodeCnt); 00035 00036 #define PICK_INTER_PROCESSOR_BOUNDARY_BLOCK(SetValueLine) {\ 00037 res.clear();\ 00038 unsigned int dim = firstBlock.getDim();\ 00039 unsigned int maxDepth = firstBlock.getMaxDepth();\ 00040 ot::TreeNode root(dim, maxDepth);\ 00041 for(unsigned int nodeCnt = 0; nodeCnt < nodes.size(); nodeCnt++) {\ 00042 unsigned int myMinX = nodes[nodeCnt].minX();\ 00043 unsigned int myMinY = nodes[nodeCnt].minY();\ 00044 unsigned int myMinZ = nodes[nodeCnt].minZ();\ 00045 unsigned int myMaxX = nodes[nodeCnt].maxX();\ 00046 unsigned int myMaxY = nodes[nodeCnt].maxY();\ 00047 unsigned int myMaxZ = nodes[nodeCnt].maxZ();\ 00048 unsigned int myLen = (myMaxX - myMinX);\ 00049 unsigned int myLevel = nodes[nodeCnt].getLevel();\ 00050 unsigned int negX = ((myMinX > 0) ? (myMinX - myLen) : myMinX);\ 00051 unsigned int negY = ((myMinY > 0) ? (myMinY - myLen) : myMinY);\ 00052 unsigned int negZ = ((myMinZ > 0) ? (myMinZ - myLen) : myMinZ);\ 00053 unsigned int posX = ((myMaxX < (1u << maxDepth)) ? (myMaxX + myLen -1) : (myMaxX-1));\ 00054 unsigned int posY = ((myMaxY < (1u << maxDepth)) ? (myMaxY + myLen -1) : (myMaxY-1));\ 00055 unsigned int posZ = ((myMaxZ < (1u << maxDepth)) ? (myMaxZ + myLen -1) : (myMaxZ-1));\ 00056 ot::TreeNode negCorner(negX, negY, negZ, myLevel, dim, maxDepth);\ 00057 ot::TreeNode posCorner(posX, posY, posZ, maxDepth, dim, maxDepth);\ 00058 bool add = true;\ 00059 if( (negCorner >= firstBlock) && (posCorner <= lastBlock.getDLD()) ) {\ 00060 add = false;\ 00061 }\ 00062 if (add) {\ 00063 SetValueLine\ 00064 }\ 00065 }\ 00066 return 1;\ 00067 } 00068 00069 //New Implementation 00070 00071 int pickInterProcessorBoundaryNodes(const std::vector<ot::TreeNode> & nodes, 00072 std::vector<unsigned int> & res, const ot::TreeNode & firstBlock, 00073 const ot::TreeNode & lastBlock) { 00074 PROF_PICK_BND_BEGIN 00075 00076 PICK_INTER_PROCESSOR_BOUNDARY_BLOCK(PICK_IPBB_SET_UI_VALUE) 00077 00078 PROF_PICK_BND_END 00079 } 00080 00081 int pickInterProcessorBoundaryNodes(const std::vector<ot::TreeNode> & nodes, 00082 std::vector<ot::TreeNode> & res, const ot::TreeNode & firstBlock, 00083 const ot::TreeNode & lastBlock) { 00084 PROF_PICK_BND_BEGIN 00085 00086 PICK_INTER_PROCESSOR_BOUNDARY_BLOCK(PICK_IPBB_SET_TN_VALUE) 00087 00088 PROF_PICK_BND_END 00089 } 00090 00091 00092 /* 00093 #define PICK_INTER_PROCESSOR_BOUNDARY_BLOCK(SetValueLine) {\ 00094 TreeNode root(dim,maxDepth);\ 00095 res.clear();\ 00096 unsigned int nodeCnt = 0;\ 00097 unsigned int blkCnt = 0;\ 00098 while ( ( blkCnt < blocks.size() ) && ( nodeCnt < nodes.size() ) ) {\ 00099 if ( blocks[blkCnt] <= nodes[nodeCnt] ) {\ 00100 *//*Check if Ancestor*//* \ 00101 if ( blocks[blkCnt].isAncestor(nodes[nodeCnt]) ) {\ 00102 *//*Check if this node touches the internal boundary of the block.*//* \ 00103 unsigned int myMinX = nodes[nodeCnt].minX();\ 00104 unsigned int myMinY = nodes[nodeCnt].minY();\ 00105 unsigned int myMinZ = nodes[nodeCnt].minZ();\ 00106 unsigned int myMaxX = nodes[nodeCnt].maxX();\ 00107 unsigned int myMaxY = nodes[nodeCnt].maxY();\ 00108 unsigned int myMaxZ = nodes[nodeCnt].maxZ();\ 00109 unsigned int bMinX = blocks[blkCnt].minX();\ 00110 unsigned int bMinY = blocks[blkCnt].minY();\ 00111 unsigned int bMinZ = blocks[blkCnt].minZ();\ 00112 unsigned int bMaxX = blocks[blkCnt].maxX();\ 00113 unsigned int bMaxY = blocks[blkCnt].maxY();\ 00114 unsigned int bMaxZ = blocks[blkCnt].maxZ();\ 00115 if ( (myMinX == bMinX) || (myMinY == bMinY) || (myMinZ == bMinZ) ||\ 00116 (myMaxX == bMaxX) || (myMaxY == bMaxY) || (myMaxZ == bMaxZ) ) {\ 00117 *//*node touches the boundary of this block from the inside*//* \ 00118 std::vector<TreeNode> nh = nodes[nodeCnt].getAllNeighbours();\ 00119 par::makeVectorUnique<ot::TreeNode>(nh, false);\ 00120 unsigned int st = 0;\ 00121 if (nh[0] == root) {\ 00122 st = 1;\ 00123 }\ 00124 bool add = true;\ 00125 *//*An indirect and cheap way to assert existence*//* \ 00126 *//*of an ancestor is to*//* \ 00127 *//*compare nh with the span of the domain owned by this processor 00128 *//* \ 00129 *//*Note the second condition. You must compare the DLDs on both 00130 sides.*//*\ 00131 *//* Just comparing reducedNh with last block or last block's DLD is 00132 not enough*//*\ 00133 *//* This is because, the last block could be a decendant of 00134 reducedNh*//*\ 00135 if(st < nh.size()) {\ 00136 if( (nh[st] >= blocks[0]) &&\ 00137 ((nh[nh.size()-1].getDLD())\ 00138 <= (blocks[blocks.size()-1].getDLD())) ) {\ 00139 add = false;\ 00140 }\ 00141 } else {\ 00142 add = false;\ 00143 }\ 00144 if (add) {\ 00145 SetValueLine\ 00146 }\ 00147 }\ 00148 *//*There could be more nodes that are decendants of the same 00149 block.*//* \ 00150 nodeCnt++;\ 00151 } else if ( blocks[blkCnt] == nodes[nodeCnt] ) {\ 00152 std::vector<TreeNode> nh = nodes[nodeCnt].getAllNeighbours();\ 00153 par::makeVectorUnique<TreeNode>(nh,false);\ 00154 unsigned int st = 0;\ 00155 if (nh[0] == root) {\ 00156 st = 1;\ 00157 }\ 00158 bool add = true;\ 00159 *//*An indirect and cheap way to assert existence*//* \ 00160 *//*of an ancestor is to*//* \ 00161 *//*compare nh with the span of the domain owned by this processor *//* \ 00162 if(st < nh.size()) {\ 00163 if( (nh[st] >= blocks[0]) &&\ 00164 ((nh[nh.size()-1].getDLD())\ 00165 <= (blocks[blocks.size()-1].getDLD())) ) {\ 00166 add = false;\ 00167 }\ 00168 } else {\ 00169 add = false;\ 00170 }\ 00171 if (add) {\ 00172 SetValueLine\ 00173 }\ 00174 blkCnt++;\ 00175 } else {\ 00176 *//*Neither Ancestor nor equal.*//* \ 00177 blkCnt++;\ 00178 }\ 00179 } else {\ 00180 *//*Block can't be an Ancestor of the node.*//* \ 00181 nodeCnt++;\ 00182 }\ 00183 }\ 00184 return 1;\ 00185 } 00186 */ 00187 00188 /* 00189 //Old Implementation 00190 int pickInterProcessorBoundaryNodes(const std::vector<ot::TreeNode> & blocks, 00191 const std::vector<ot::TreeNode> &nodes, 00192 std::vector<unsigned int >& res, 00193 unsigned int dim, unsigned int maxDepth) { 00194 PICK_INTER_PROCESSOR_BOUNDARY_BLOCK(PICK_IPBB_SET_UI_VALUE) 00195 } // end pickboundary 00196 00197 int pickInterProcessorBoundaryNodes(const std::vector<ot::TreeNode> & blocks, 00198 const std::vector<ot::TreeNode> &nodes, 00199 std::vector<ot::TreeNode>& res, 00200 unsigned int dim, unsigned int maxDepth) { 00201 PICK_INTER_PROCESSOR_BOUNDARY_BLOCK(PICK_IPBB_SET_TN_VALUE) 00202 } // end pickboundary 00203 */ 00204 00205 #undef PICK_IPBB_SET_TN_VALUE 00206 #undef PICK_IPBB_SET_UI_VALUE 00207 #undef PICK_INTER_PROCESSOR_BOUNDARY_BLOCK 00208 00209 00210 // Oldest Implementation ... 00211 /* 00212 int pickInterProcessorBoundaryNodes(const std::vector<ot::TreeNode> & blocks, const std::vector<ot::TreeNode> &nodes, std::vector<ot::TreeNode>& res, unsigned int dim, unsigned int maxDepth){ 00213 TreeNode root(dim,maxDepth); 00214 unsigned int resLen=0; 00215 res.resize(nodes.size()); 00216 for(unsigned int i=0;i<nodes.size();i++) { 00217 //A node is considered stable only if it is stable in all directions. 00218 std::vector<TreeNode> nh = nodes[i].getAllNeighbours(); 00219 bool add=false; 00220 for(unsigned int k=0;k<nh.size();k++) { 00221 if(nh[k]==root){ 00222 //Stable from this direction 00223 continue; 00224 } 00225 bool foundAnc = false; 00226 for(unsigned int j=0;j<blocks.size();j++) { 00227 if((blocks[j] == nh[k]) || (blocks[j].isAncestor(nh[k]))){ 00228 foundAnc=true; 00229 break; 00230 } 00231 }//end for j 00232 if(!foundAnc) { 00233 //Unstable from this direction 00234 add=true; 00235 break; 00236 } 00237 }//end for k 00238 if(add){ 00239 res[resLen] = nodes[i]; 00240 resLen++; 00241 } 00242 }//end for i 00243 res.resize(resLen); 00244 return 1; 00245 }//end function 00246 */ 00247 00248 }//end namespace 00249 00250 00251