Changeset 1328 for XIOS/dev/branch_openmp/extern/remap/src/mapper.cpp
- Timestamp:
- 11/15/17 12:14:34 (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
XIOS/dev/branch_openmp/extern/remap/src/mapper.cpp
r1220 r1328 12 12 13 13 #include "mapper.hpp" 14 using namespace ep_lib; 14 15 15 16 namespace sphereRemap { 16 17 extern CRemapGrid srcGrid;18 #pragma omp threadprivate(srcGrid)19 20 extern CRemapGrid tgtGrid;21 #pragma omp threadprivate(tgtGrid)22 23 17 24 18 /* A subdivition of an array into N sub-arays … … 72 66 void Mapper::setTargetMesh(const double* boundsLon, const double* boundsLat, int nVertex, int nbCells, const double* pole, const long int* globalId) 73 67 { 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 68 tgtGrid.pole = Coord(pole[0], pole[1], pole[2]); 69 70 int mpiRank, mpiSize; 71 MPI_Comm_rank(communicator, &mpiRank); 72 MPI_Comm_size(communicator, &mpiSize); 73 74 targetElements.reserve(nbCells); 75 targetMesh.reserve(nbCells); 76 77 targetGlobalId.resize(nbCells) ; 78 if (globalId==NULL) 79 { 80 long int offset ; 81 long int nb=nbCells ; 82 MPI_Scan(&nb,&offset,1,MPI_LONG,MPI_SUM,communicator) ; 83 offset=offset-nb ; 84 for(int i=0;i<nbCells;i++) targetGlobalId[i]=offset+i ; 85 } 86 else targetGlobalId.assign(globalId,globalId+nbCells); 87 88 for (int i = 0; i < nbCells; i++) 89 { 90 int offs = i*nVertex; 91 Elt elt(boundsLon + offs, boundsLat + offs, nVertex); 92 targetElements.push_back(elt); 93 targetMesh.push_back(Node(elt.x, cptRadius(elt), &sourceElements.back())); 94 cptEltGeom(targetElements[i], Coord(pole[0], pole[1], pole[2])); 95 } 102 96 103 97 … … 106 100 void Mapper::setSourceValue(const double* val) 107 101 { 108 109 102 int size=sourceElements.size() ; 103 for(int i=0;i<size;++i) sourceElements[i].val=val[i] ; 110 104 } 111 105 112 106 void Mapper::getTargetValue(double* val) 113 107 { 114 115 108 int size=targetElements.size() ; 109 for(int i=0;i<size;++i) val[i]=targetElements[i].val ; 116 110 } 117 111 118 112 vector<double> Mapper::computeWeights(int interpOrder, bool renormalize, bool quantity) 119 113 { 120 vector<double> timings; 121 int mpiSize, mpiRank; 122 MPI_Comm_size(communicator, &mpiSize); 123 MPI_Comm_rank(communicator, &mpiRank); 124 125 this->buildSSTree(sourceMesh, targetMesh); 126 127 if (mpiRank == 0 && verbose) cout << "Computing intersections ..." << endl; 128 double tic = cputime(); 129 computeIntersection(&targetElements[0], targetElements.size()); 130 timings.push_back(cputime() - tic); 131 132 tic = cputime(); 133 if (interpOrder == 2) { 134 if (mpiRank == 0 && verbose) cout << "Computing grads ..." << endl; 135 buildMeshTopology(); 136 computeGrads(); 137 } 138 timings.push_back(cputime() - tic); 139 140 /* Prepare computation of weights */ 141 /* compute number of intersections which for the first order case 142 corresponds to the number of edges in the remap matrix */ 143 int nIntersections = 0; 144 for (int j = 0; j < targetElements.size(); j++) 145 { 146 Elt &elt = targetElements[j]; 147 for (list<Polyg*>::iterator it = elt.is.begin(); it != elt.is.end(); it++) 148 nIntersections++; 149 } 150 /* overallocate for NMAX neighbours for each elements */ 151 remapMatrix = new double[nIntersections*NMAX]; 152 srcAddress = new int[nIntersections*NMAX]; 153 srcRank = new int[nIntersections*NMAX]; 154 dstAddress = new int[nIntersections*NMAX]; 155 sourceWeightId =new long[nIntersections*NMAX]; 156 targetWeightId =new long[nIntersections*NMAX]; 157 158 159 if (mpiRank == 0 && verbose) cout << "Remapping..." << endl; 160 tic = cputime(); 161 nWeights = remap(&targetElements[0], targetElements.size(), interpOrder, renormalize, quantity); 162 timings.push_back(cputime() - tic); 163 164 for (int i = 0; i < targetElements.size(); i++) targetElements[i].delete_intersections(); 165 166 return timings; 114 vector<double> timings; 115 int mpiSize, mpiRank; 116 MPI_Comm_size(communicator, &mpiSize); 117 MPI_Comm_rank(communicator, &mpiRank); 118 119 120 this->buildSSTree(sourceMesh, targetMesh); 121 122 if (mpiRank == 0 && verbose) cout << "Computing intersections ..." << endl; 123 double tic = cputime(); 124 computeIntersection(&targetElements[0], targetElements.size()); 125 timings.push_back(cputime() - tic); 126 127 tic = cputime(); 128 if (interpOrder == 2) { 129 if (mpiRank == 0 && verbose) cout << "Computing grads ..." << endl; 130 buildMeshTopology(); 131 computeGrads(); 132 } 133 timings.push_back(cputime() - tic); 134 135 /* Prepare computation of weights */ 136 /* compute number of intersections which for the first order case 137 corresponds to the number of edges in the remap matrix */ 138 int nIntersections = 0; 139 for (int j = 0; j < targetElements.size(); j++) 140 { 141 Elt &elt = targetElements[j]; 142 for (list<Polyg*>::iterator it = elt.is.begin(); it != elt.is.end(); it++) 143 nIntersections++; 144 } 145 /* overallocate for NMAX neighbours for each elements */ 146 remapMatrix = new double[nIntersections*NMAX]; 147 srcAddress = new int[nIntersections*NMAX]; 148 srcRank = new int[nIntersections*NMAX]; 149 dstAddress = new int[nIntersections*NMAX]; 150 sourceWeightId =new long[nIntersections*NMAX]; 151 targetWeightId =new long[nIntersections*NMAX]; 152 153 154 if (mpiRank == 0 && verbose) cout << "Remapping..." << endl; 155 tic = cputime(); 156 nWeights = remap(&targetElements[0], targetElements.size(), interpOrder, renormalize, quantity); 157 timings.push_back(cputime() - tic); 158 159 for (int i = 0; i < targetElements.size(); i++) targetElements[i].delete_intersections(); 160 161 return timings; 167 162 } 168 163 169 164 /** 170 @param elements are cells of the target grid that are distributed over CPUs171 indepentently of the distribution of the SS-tree.172 @param nbElements is the size of the elements array.173 @param order is the order of interpolaton (must be 1 or 2).174 165 @param elements are cells of the target grid that are distributed over CPUs 166 indepentently of the distribution of the SS-tree. 167 @param nbElements is the size of the elements array. 168 @param order is the order of interpolaton (must be 1 or 2). 169 */ 175 170 int Mapper::remap(Elt *elements, int nbElements, int order, bool renormalize, bool quantity) 176 171 { 177 int mpiSize, mpiRank; 178 MPI_Comm_size(communicator, &mpiSize); 179 MPI_Comm_rank(communicator, &mpiRank); 180 181 /* create list of intersections (super mesh elements) for each rank */ 182 multimap<int, Polyg *> *elementList = new multimap<int, Polyg *>[mpiSize]; 183 for (int j = 0; j < nbElements; j++) 184 { 185 Elt& e = elements[j]; 186 for (list<Polyg *>::iterator it = e.is.begin(); it != e.is.end(); it++) 187 elementList[(*it)->id.rank].insert(pair<int, Polyg *>((*it)->id.ind, *it)); 188 } 189 190 int *nbSendElement = new int[mpiSize]; 191 int **sendElement = new int*[mpiSize]; /* indices of elements required from other rank */ 192 double **recvValue = new double*[mpiSize]; 193 double **recvArea = new double*[mpiSize]; 194 Coord **recvGrad = new Coord*[mpiSize]; 195 GloId **recvNeighIds = new GloId*[mpiSize]; /* ids of the of the source neighbours which also contribute through gradient */ 196 for (int rank = 0; rank < mpiSize; rank++) 197 { 198 /* get size for allocation */ 199 int last = -1; /* compares unequal to any index */ 200 int index = -1; /* increased to starting index 0 in first iteration */ 201 for (multimap<int, Polyg *>::iterator it = elementList[rank].begin(); it != elementList[rank].end(); ++it) 202 { 203 if (last != it->first) 204 index++; 205 (it->second)->id.ind = index; 206 last = it->first; 207 } 208 nbSendElement[rank] = index + 1; 209 210 /* if size is non-zero allocate and collect indices of elements on other ranks that we intersect */ 211 if (nbSendElement[rank] > 0) 212 { 213 sendElement[rank] = new int[nbSendElement[rank]]; 214 recvValue[rank] = new double[nbSendElement[rank]]; 215 recvArea[rank] = new double[nbSendElement[rank]]; 216 if (order == 2) 217 { 218 recvNeighIds[rank] = new GloId[nbSendElement[rank]*(NMAX+1)]; 219 recvGrad[rank] = new Coord[nbSendElement[rank]*(NMAX+1)]; 220 } 221 else 222 recvNeighIds[rank] = new GloId[nbSendElement[rank]]; 223 224 last = -1; 225 index = -1; 226 for (multimap<int, Polyg *>::iterator it = elementList[rank].begin(); it != elementList[rank].end(); ++it) 227 { 228 if (last != it->first) 229 index++; 230 sendElement[rank][index] = it->first; 231 last = it->first; 232 } 233 } 234 } 235 236 /* communicate sizes of source elements to be sent (index lists and later values and gradients) */ 237 int *nbRecvElement = new int[mpiSize]; 238 MPI_Alltoall(nbSendElement, 1, MPI_INT, nbRecvElement, 1, MPI_INT, communicator); 239 240 /* communicate indices of source elements on other ranks whoes value and gradient we need (since intersection) */ 241 int nbSendRequest = 0; 242 int nbRecvRequest = 0; 243 int **recvElement = new int*[mpiSize]; 244 double **sendValue = new double*[mpiSize]; 245 double **sendArea = new double*[mpiSize]; 246 Coord **sendGrad = new Coord*[mpiSize]; 247 GloId **sendNeighIds = new GloId*[mpiSize]; 248 MPI_Request *sendRequest = new MPI_Request[4*mpiSize]; 249 MPI_Request *recvRequest = new MPI_Request[4*mpiSize]; 250 for (int rank = 0; rank < mpiSize; rank++) 251 { 252 if (nbSendElement[rank] > 0) 253 { 254 MPI_Issend(sendElement[rank], nbSendElement[rank], MPI_INT, rank, 0, communicator, &sendRequest[nbSendRequest]); 255 nbSendRequest++; 256 } 257 258 if (nbRecvElement[rank] > 0) 259 { 260 recvElement[rank] = new int[nbRecvElement[rank]]; 261 sendValue[rank] = new double[nbRecvElement[rank]]; 262 sendArea[rank] = new double[nbRecvElement[rank]]; 263 if (order == 2) 264 { 265 sendNeighIds[rank] = new GloId[nbRecvElement[rank]*(NMAX+1)]; 266 sendGrad[rank] = new Coord[nbRecvElement[rank]*(NMAX+1)]; 267 } 268 else 269 { 270 sendNeighIds[rank] = new GloId[nbRecvElement[rank]]; 271 } 272 MPI_Irecv(recvElement[rank], nbRecvElement[rank], MPI_INT, rank, 0, communicator, &recvRequest[nbRecvRequest]); 273 nbRecvRequest++; 274 } 275 } 276 277 MPI_Status *status = new MPI_Status[4*mpiSize]; 278 279 MPI_Waitall(nbSendRequest, sendRequest, status); 280 MPI_Waitall(nbRecvRequest, recvRequest, status); 281 282 /* for all indices that have been received from requesting ranks: pack values and gradients, then send */ 283 nbSendRequest = 0; 284 nbRecvRequest = 0; 285 for (int rank = 0; rank < mpiSize; rank++) 286 { 287 if (nbRecvElement[rank] > 0) 288 { 289 int jj = 0; // jj == j if no weight writing 290 for (int j = 0; j < nbRecvElement[rank]; j++) 291 { 292 sendValue[rank][j] = sstree.localElements[recvElement[rank][j]].val; 293 sendArea[rank][j] = sstree.localElements[recvElement[rank][j]].area; 294 if (order == 2) 295 { 296 sendGrad[rank][jj] = sstree.localElements[recvElement[rank][j]].grad; 297 sendNeighIds[rank][jj] = sstree.localElements[recvElement[rank][j]].src_id; 298 jj++; 299 for (int i = 0; i < NMAX; i++) 300 { 301 sendGrad[rank][jj] = sstree.localElements[recvElement[rank][j]].gradNeigh[i]; 302 sendNeighIds[rank][jj] = sstree.localElements[recvElement[rank][j]].neighId[i]; 303 jj++; 304 } 305 } 306 else 307 sendNeighIds[rank][j] = sstree.localElements[recvElement[rank][j]].src_id; 308 } 309 MPI_Issend(sendValue[rank], nbRecvElement[rank], MPI_DOUBLE, rank, 0, communicator, &sendRequest[nbSendRequest]); 310 nbSendRequest++; 311 MPI_Issend(sendArea[rank], nbRecvElement[rank], MPI_DOUBLE, rank, 1, communicator, &sendRequest[nbSendRequest]); 312 nbSendRequest++; 313 if (order == 2) 314 { 315 MPI_Issend(sendGrad[rank], 3*nbRecvElement[rank]*(NMAX+1), 316 MPI_DOUBLE, rank, 2, communicator, &sendRequest[nbSendRequest]); 317 nbSendRequest++; 318 MPI_Issend(sendNeighIds[rank], 4*nbRecvElement[rank]*(NMAX+1), MPI_INT, rank, 3, communicator, &sendRequest[nbSendRequest]); 319 //ym --> attention taille GloId 320 nbSendRequest++; 321 } 322 else 323 { 324 MPI_Issend(sendNeighIds[rank], 4*nbRecvElement[rank], MPI_INT, rank, 4, communicator, &sendRequest[nbSendRequest]); 325 //ym --> attention taille GloId 326 nbSendRequest++; 327 } 328 } 329 if (nbSendElement[rank] > 0) 330 { 331 MPI_Irecv(recvValue[rank], nbSendElement[rank], MPI_DOUBLE, rank, 0, communicator, &recvRequest[nbRecvRequest]); 332 nbRecvRequest++; 333 MPI_Irecv(recvArea[rank], nbSendElement[rank], MPI_DOUBLE, rank, 1, communicator, &recvRequest[nbRecvRequest]); 334 nbRecvRequest++; 335 if (order == 2) 336 { 337 MPI_Irecv(recvGrad[rank], 3*nbSendElement[rank]*(NMAX+1), 338 MPI_DOUBLE, rank, 2, communicator, &recvRequest[nbRecvRequest]); 339 nbRecvRequest++; 340 MPI_Irecv(recvNeighIds[rank], 4*nbSendElement[rank]*(NMAX+1), MPI_INT, rank, 3, communicator, &recvRequest[nbRecvRequest]); 341 //ym --> attention taille GloId 342 nbRecvRequest++; 343 } 344 else 345 { 346 MPI_Irecv(recvNeighIds[rank], 4*nbSendElement[rank], MPI_INT, rank, 4, communicator, &recvRequest[nbRecvRequest]); 347 //ym --> attention taille GloId 348 nbRecvRequest++; 349 } 350 } 351 } 352 353 MPI_Waitall(nbRecvRequest, recvRequest, status); 354 MPI_Waitall(nbSendRequest, sendRequest, status); 355 356 357 358 /* now that all values and gradients are available use them to computed interpolated values on target 359 and also to compute weights */ 360 int i = 0; 361 for (int j = 0; j < nbElements; j++) 362 { 363 Elt& e = elements[j]; 364 365 /* since for the 2nd order case source grid elements can contribute to a destination grid element over several "paths" 366 (step1: gradient is computed using neighbours on same grid, step2: intersection uses several elements on other grid) 367 accumulate them so that there is only one final weight between two elements */ 368 map<GloId,double> wgt_map; 369 370 /* for destination element `e` loop over all intersetions/the corresponding source elements */ 371 for (list<Polyg *>::iterator it = e.is.begin(); it != e.is.end(); it++) 372 { 373 /* it is the intersection element, so it->x and it->area are barycentre and area of intersection element (super mesh) 374 but it->id is id of the source element that it intersects */ 375 int n1 = (*it)->id.ind; 376 int rank = (*it)->id.rank; 377 double fk = recvValue[rank][n1]; 378 double srcArea = recvArea[rank][n1]; 379 double w = (*it)->area; 380 if (quantity) w/=srcArea ; 381 382 /* first order: src value times weight (weight = supermesh area), later divide by target area */ 383 int kk = (order == 2) ? n1 * (NMAX + 1) : n1; 384 GloId neighID = recvNeighIds[rank][kk]; 385 wgt_map[neighID] += w; 386 387 if (order == 2) 388 { 389 for (int k = 0; k < NMAX+1; k++) 390 { 391 int kk = n1 * (NMAX + 1) + k; 392 GloId neighID = recvNeighIds[rank][kk]; 393 if (neighID.ind != -1) wgt_map[neighID] += w * scalarprod(recvGrad[rank][kk], (*it)->x); 394 } 395 396 } 397 } 398 399 double renorm=0; 400 if (renormalize) 401 for (map<GloId,double>::iterator it = wgt_map.begin(); it != wgt_map.end(); it++) renorm+=it->second / e.area; 402 else renorm=1. ; 403 404 for (map<GloId,double>::iterator it = wgt_map.begin(); it != wgt_map.end(); it++) 405 { 406 if (quantity) this->remapMatrix[i] = (it->second ) / renorm; 407 else this->remapMatrix[i] = (it->second / e.area) / renorm; 408 this->srcAddress[i] = it->first.ind; 409 this->srcRank[i] = it->first.rank; 410 this->dstAddress[i] = j; 411 this->sourceWeightId[i]= it->first.globalId ; 412 this->targetWeightId[i]= targetGlobalId[j] ; 413 i++; 414 } 415 } 416 417 /* free all memory allocated in this function */ 418 for (int rank = 0; rank < mpiSize; rank++) 419 { 420 if (nbSendElement[rank] > 0) 421 { 422 delete[] sendElement[rank]; 423 delete[] recvValue[rank]; 424 delete[] recvArea[rank]; 425 if (order == 2) 426 { 427 delete[] recvGrad[rank]; 428 } 429 delete[] recvNeighIds[rank]; 430 } 431 if (nbRecvElement[rank] > 0) 432 { 433 delete[] recvElement[rank]; 434 delete[] sendValue[rank]; 435 delete[] sendArea[rank]; 436 if (order == 2) 437 delete[] sendGrad[rank]; 438 delete[] sendNeighIds[rank]; 439 } 440 } 441 delete[] status; 442 delete[] sendRequest; 443 delete[] recvRequest; 444 delete[] elementList; 445 delete[] nbSendElement; 446 delete[] nbRecvElement; 447 delete[] sendElement; 448 delete[] recvElement; 449 delete[] sendValue; 450 delete[] recvValue; 451 delete[] sendGrad; 452 delete[] recvGrad; 453 delete[] sendNeighIds; 454 delete[] recvNeighIds; 455 456 return i; 172 int mpiSize, mpiRank; 173 MPI_Comm_size(communicator, &mpiSize); 174 MPI_Comm_rank(communicator, &mpiRank); 175 176 /* create list of intersections (super mesh elements) for each rank */ 177 multimap<int, Polyg *> *elementList = new multimap<int, Polyg *>[mpiSize]; 178 for (int j = 0; j < nbElements; j++) 179 { 180 Elt& e = elements[j]; 181 for (list<Polyg *>::iterator it = e.is.begin(); it != e.is.end(); it++) 182 elementList[(*it)->id.rank].insert(pair<int, Polyg *>((*it)->id.ind, *it)); 183 } 184 185 int *nbSendElement = new int[mpiSize]; 186 int **sendElement = new int*[mpiSize]; /* indices of elements required from other rank */ 187 double **recvValue = new double*[mpiSize]; 188 double **recvArea = new double*[mpiSize]; 189 Coord **recvGrad = new Coord*[mpiSize]; 190 GloId **recvNeighIds = new GloId*[mpiSize]; /* ids of the of the source neighbours which also contribute through gradient */ 191 for (int rank = 0; rank < mpiSize; rank++) 192 { 193 /* get size for allocation */ 194 int last = -1; /* compares unequal to any index */ 195 int index = -1; /* increased to starting index 0 in first iteration */ 196 for (multimap<int, Polyg *>::iterator it = elementList[rank].begin(); it != elementList[rank].end(); ++it) 197 { 198 if (last != it->first) 199 index++; 200 (it->second)->id.ind = index; 201 last = it->first; 202 } 203 nbSendElement[rank] = index + 1; 204 205 /* if size is non-zero allocate and collect indices of elements on other ranks that we intersect */ 206 if (nbSendElement[rank] > 0) 207 { 208 sendElement[rank] = new int[nbSendElement[rank]]; 209 recvValue[rank] = new double[nbSendElement[rank]]; 210 recvArea[rank] = new double[nbSendElement[rank]]; 211 if (order == 2) 212 { 213 recvNeighIds[rank] = new GloId[nbSendElement[rank]*(NMAX+1)]; 214 recvGrad[rank] = new Coord[nbSendElement[rank]*(NMAX+1)]; 215 } 216 else 217 recvNeighIds[rank] = new GloId[nbSendElement[rank]]; 218 219 last = -1; 220 index = -1; 221 for (multimap<int, Polyg *>::iterator it = elementList[rank].begin(); it != elementList[rank].end(); ++it) 222 { 223 if (last != it->first) 224 index++; 225 sendElement[rank][index] = it->first; 226 last = it->first; 227 } 228 } 229 } 230 231 /* communicate sizes of source elements to be sent (index lists and later values and gradients) */ 232 int *nbRecvElement = new int[mpiSize]; 233 MPI_Alltoall(nbSendElement, 1, MPI_INT, nbRecvElement, 1, MPI_INT, communicator); 234 235 /* communicate indices of source elements on other ranks whoes value and gradient we need (since intersection) */ 236 int nbSendRequest = 0; 237 int nbRecvRequest = 0; 238 int **recvElement = new int*[mpiSize]; 239 double **sendValue = new double*[mpiSize]; 240 double **sendArea = new double*[mpiSize]; 241 Coord **sendGrad = new Coord*[mpiSize]; 242 GloId **sendNeighIds = new GloId*[mpiSize]; 243 MPI_Request *sendRequest = new MPI_Request[4*mpiSize]; 244 MPI_Request *recvRequest = new MPI_Request[4*mpiSize]; 245 for (int rank = 0; rank < mpiSize; rank++) 246 { 247 if (nbSendElement[rank] > 0) 248 { 249 MPI_Issend(sendElement[rank], nbSendElement[rank], MPI_INT, rank, 0, communicator, &sendRequest[nbSendRequest]); 250 nbSendRequest++; 251 } 252 253 if (nbRecvElement[rank] > 0) 254 { 255 recvElement[rank] = new int[nbRecvElement[rank]]; 256 sendValue[rank] = new double[nbRecvElement[rank]]; 257 sendArea[rank] = new double[nbRecvElement[rank]]; 258 if (order == 2) 259 { 260 sendNeighIds[rank] = new GloId[nbRecvElement[rank]*(NMAX+1)]; 261 sendGrad[rank] = new Coord[nbRecvElement[rank]*(NMAX+1)]; 262 } 263 else 264 { 265 sendNeighIds[rank] = new GloId[nbRecvElement[rank]]; 266 } 267 MPI_Irecv(recvElement[rank], nbRecvElement[rank], MPI_INT, rank, 0, communicator, &recvRequest[nbRecvRequest]); 268 nbRecvRequest++; 269 } 270 } 271 272 MPI_Status *status = new MPI_Status[4*mpiSize]; 273 274 MPI_Waitall(nbSendRequest, sendRequest, status); 275 MPI_Waitall(nbRecvRequest, recvRequest, status); 276 277 /* for all indices that have been received from requesting ranks: pack values and gradients, then send */ 278 nbSendRequest = 0; 279 nbRecvRequest = 0; 280 for (int rank = 0; rank < mpiSize; rank++) 281 { 282 if (nbRecvElement[rank] > 0) 283 { 284 int jj = 0; // jj == j if no weight writing 285 for (int j = 0; j < nbRecvElement[rank]; j++) 286 { 287 sendValue[rank][j] = sstree.localElements[recvElement[rank][j]].val; 288 sendArea[rank][j] = sstree.localElements[recvElement[rank][j]].area; 289 if (order == 2) 290 { 291 sendGrad[rank][jj] = sstree.localElements[recvElement[rank][j]].grad; 292 sendNeighIds[rank][jj] = sstree.localElements[recvElement[rank][j]].src_id; 293 jj++; 294 for (int i = 0; i < NMAX; i++) 295 { 296 sendGrad[rank][jj] = sstree.localElements[recvElement[rank][j]].gradNeigh[i]; 297 sendNeighIds[rank][jj] = sstree.localElements[recvElement[rank][j]].neighId[i]; 298 jj++; 299 } 300 } 301 else 302 sendNeighIds[rank][j] = sstree.localElements[recvElement[rank][j]].src_id; 303 } 304 MPI_Issend(sendValue[rank], nbRecvElement[rank], MPI_DOUBLE, rank, 0, communicator, &sendRequest[nbSendRequest]); 305 nbSendRequest++; 306 MPI_Issend(sendArea[rank], nbRecvElement[rank], MPI_DOUBLE, rank, 0, communicator, &sendRequest[nbSendRequest]); 307 nbSendRequest++; 308 if (order == 2) 309 { 310 MPI_Issend(sendGrad[rank], 3*nbRecvElement[rank]*(NMAX+1), 311 MPI_DOUBLE, rank, 0, communicator, &sendRequest[nbSendRequest]); 312 nbSendRequest++; 313 MPI_Issend(sendNeighIds[rank], 4*nbRecvElement[rank]*(NMAX+1), MPI_INT, rank, 0, communicator, &sendRequest[nbSendRequest]); 314 //ym --> attention taille GloId 315 nbSendRequest++; 316 } 317 else 318 { 319 MPI_Issend(sendNeighIds[rank], 4*nbRecvElement[rank], MPI_INT, rank, 0, communicator, &sendRequest[nbSendRequest]); 320 //ym --> attention taille GloId 321 nbSendRequest++; 322 } 323 } 324 if (nbSendElement[rank] > 0) 325 { 326 MPI_Irecv(recvValue[rank], nbSendElement[rank], MPI_DOUBLE, rank, 0, communicator, &recvRequest[nbRecvRequest]); 327 nbRecvRequest++; 328 MPI_Irecv(recvArea[rank], nbSendElement[rank], MPI_DOUBLE, rank, 0, communicator, &recvRequest[nbRecvRequest]); 329 nbRecvRequest++; 330 if (order == 2) 331 { 332 MPI_Irecv(recvGrad[rank], 3*nbSendElement[rank]*(NMAX+1), 333 MPI_DOUBLE, rank, 0, communicator, &recvRequest[nbRecvRequest]); 334 nbRecvRequest++; 335 MPI_Irecv(recvNeighIds[rank], 4*nbSendElement[rank]*(NMAX+1), MPI_INT, rank, 0, communicator, &recvRequest[nbRecvRequest]); 336 //ym --> attention taille GloId 337 nbRecvRequest++; 338 } 339 else 340 { 341 MPI_Irecv(recvNeighIds[rank], 4*nbSendElement[rank], MPI_INT, rank, 0, communicator, &recvRequest[nbRecvRequest]); 342 //ym --> attention taille GloId 343 nbRecvRequest++; 344 } 345 } 346 } 347 348 MPI_Waitall(nbSendRequest, sendRequest, status); 349 MPI_Waitall(nbRecvRequest, recvRequest, status); 350 351 352 /* now that all values and gradients are available use them to computed interpolated values on target 353 and also to compute weights */ 354 int i = 0; 355 for (int j = 0; j < nbElements; j++) 356 { 357 Elt& e = elements[j]; 358 359 /* since for the 2nd order case source grid elements can contribute to a destination grid element over several "paths" 360 (step1: gradient is computed using neighbours on same grid, step2: intersection uses several elements on other grid) 361 accumulate them so that there is only one final weight between two elements */ 362 map<GloId,double> wgt_map; 363 364 /* for destination element `e` loop over all intersetions/the corresponding source elements */ 365 for (list<Polyg *>::iterator it = e.is.begin(); it != e.is.end(); it++) 366 { 367 /* it is the intersection element, so it->x and it->area are barycentre and area of intersection element (super mesh) 368 but it->id is id of the source element that it intersects */ 369 int n1 = (*it)->id.ind; 370 int rank = (*it)->id.rank; 371 double fk = recvValue[rank][n1]; 372 double srcArea = recvArea[rank][n1]; 373 double w = (*it)->area; 374 if (quantity) w/=srcArea ; 375 376 /* first order: src value times weight (weight = supermesh area), later divide by target area */ 377 int kk = (order == 2) ? n1 * (NMAX + 1) : n1; 378 GloId neighID = recvNeighIds[rank][kk]; 379 wgt_map[neighID] += w; 380 381 if (order == 2) 382 { 383 for (int k = 0; k < NMAX+1; k++) 384 { 385 int kk = n1 * (NMAX + 1) + k; 386 GloId neighID = recvNeighIds[rank][kk]; 387 if (neighID.ind != -1) wgt_map[neighID] += w * scalarprod(recvGrad[rank][kk], (*it)->x); 388 } 389 390 } 391 } 392 393 double renorm=0; 394 if (renormalize) 395 for (map<GloId,double>::iterator it = wgt_map.begin(); it != wgt_map.end(); it++) renorm+=it->second / e.area; 396 else renorm=1. ; 397 398 for (map<GloId,double>::iterator it = wgt_map.begin(); it != wgt_map.end(); it++) 399 { 400 if (quantity) this->remapMatrix[i] = (it->second ) / renorm; 401 else this->remapMatrix[i] = (it->second / e.area) / renorm; 402 this->srcAddress[i] = it->first.ind; 403 this->srcRank[i] = it->first.rank; 404 this->dstAddress[i] = j; 405 this->sourceWeightId[i]= it->first.globalId ; 406 this->targetWeightId[i]= targetGlobalId[j] ; 407 i++; 408 } 409 } 410 411 /* free all memory allocated in this function */ 412 for (int rank = 0; rank < mpiSize; rank++) 413 { 414 if (nbSendElement[rank] > 0) 415 { 416 delete[] sendElement[rank]; 417 delete[] recvValue[rank]; 418 delete[] recvArea[rank]; 419 if (order == 2) 420 { 421 delete[] recvGrad[rank]; 422 } 423 delete[] recvNeighIds[rank]; 424 } 425 if (nbRecvElement[rank] > 0) 426 { 427 delete[] recvElement[rank]; 428 delete[] sendValue[rank]; 429 delete[] sendArea[rank]; 430 if (order == 2) 431 delete[] sendGrad[rank]; 432 delete[] sendNeighIds[rank]; 433 } 434 } 435 delete[] status; 436 delete[] sendRequest; 437 delete[] recvRequest; 438 delete[] elementList; 439 delete[] nbSendElement; 440 delete[] nbRecvElement; 441 delete[] sendElement; 442 delete[] recvElement; 443 delete[] sendValue; 444 delete[] recvValue; 445 delete[] sendGrad; 446 delete[] recvGrad; 447 delete[] sendNeighIds; 448 delete[] recvNeighIds; 449 return i; 457 450 } 458 451 459 452 void Mapper::computeGrads() 460 453 { 461 462 463 464 465 466 467 468 469 470 454 /* array of pointers to collect local elements and elements received from other cpu */ 455 vector<Elt*> globalElements(sstree.nbLocalElements + nbNeighbourElements); 456 int index = 0; 457 for (int i = 0; i < sstree.nbLocalElements; i++, index++) 458 globalElements[index] = &(sstree.localElements[i]); 459 for (int i = 0; i < nbNeighbourElements; i++, index++) 460 globalElements[index] = &neighbourElements[i]; 461 462 update_baryc(sstree.localElements, sstree.nbLocalElements); 463 computeGradients(&globalElements[0], sstree.nbLocalElements); 471 464 } 472 465 473 466 /** for each element of the source grid, finds all the neighbouring elements that share an edge 474 (filling array neighbourElements). This is used later to compute gradients */467 (filling array neighbourElements). This is used later to compute gradients */ 475 468 void Mapper::buildMeshTopology() 476 469 { 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 intersector of a local node */673 674 675 676 use the SS-tree to find all elements (including neighbourElements)677 who are potential neighbours because their circles intersect,678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 whoes circles intersect with the circle around `elt` (the SS intersectors)693 and check if they are neighbours in the sense that the two elements share an edge.694 If they do, save this information for elt */695 696 697 698 699 700 701 470 int mpiSize, mpiRank; 471 MPI_Comm_size(communicator, &mpiSize); 472 MPI_Comm_rank(communicator, &mpiRank); 473 474 vector<Node> *routingList = new vector<Node>[mpiSize]; 475 vector<vector<int> > routes(sstree.localTree.leafs.size()); 476 477 sstree.routeIntersections(routes, sstree.localTree.leafs); 478 479 for (int i = 0; i < routes.size(); ++i) 480 for (int k = 0; k < routes[i].size(); ++k) 481 routingList[routes[i][k]].push_back(sstree.localTree.leafs[i]); 482 routingList[mpiRank].clear(); 483 484 485 CMPIRouting mpiRoute(communicator); 486 mpiRoute.init(routes); 487 int nRecv = mpiRoute.getTotalSourceElement(); 488 489 int *nbSendNode = new int[mpiSize]; 490 int *nbRecvNode = new int[mpiSize]; 491 int *sendMessageSize = new int[mpiSize]; 492 int *recvMessageSize = new int[mpiSize]; 493 494 for (int rank = 0; rank < mpiSize; rank++) 495 { 496 nbSendNode[rank] = routingList[rank].size(); 497 sendMessageSize[rank] = 0; 498 for (size_t j = 0; j < routingList[rank].size(); j++) 499 { 500 Elt *elt = (Elt *) (routingList[rank][j].data); 501 sendMessageSize[rank] += packedPolygonSize(*elt); 502 } 503 } 504 505 MPI_Alltoall(nbSendNode, 1, MPI_INT, nbRecvNode, 1, MPI_INT, communicator); 506 MPI_Alltoall(sendMessageSize, 1, MPI_INT, recvMessageSize, 1, MPI_INT, communicator); 507 508 char **sendBuffer = new char*[mpiSize]; 509 char **recvBuffer = new char*[mpiSize]; 510 int *pos = new int[mpiSize]; 511 512 for (int rank = 0; rank < mpiSize; rank++) 513 { 514 if (nbSendNode[rank] > 0) sendBuffer[rank] = new char[sendMessageSize[rank]]; 515 if (nbRecvNode[rank] > 0) recvBuffer[rank] = new char[recvMessageSize[rank]]; 516 } 517 518 for (int rank = 0; rank < mpiSize; rank++) 519 { 520 pos[rank] = 0; 521 for (size_t j = 0; j < routingList[rank].size(); j++) 522 { 523 Elt *elt = (Elt *) (routingList[rank][j].data); 524 packPolygon(*elt, sendBuffer[rank], pos[rank]); 525 } 526 } 527 delete [] routingList; 528 529 530 int nbSendRequest = 0; 531 int nbRecvRequest = 0; 532 MPI_Request *sendRequest = new MPI_Request[mpiSize]; 533 MPI_Request *recvRequest = new MPI_Request[mpiSize]; 534 MPI_Status *status = new MPI_Status[mpiSize]; 535 536 for (int rank = 0; rank < mpiSize; rank++) 537 { 538 if (nbSendNode[rank] > 0) 539 { 540 MPI_Issend(sendBuffer[rank], sendMessageSize[rank], MPI_CHAR, rank, 0, communicator, &sendRequest[nbSendRequest]); 541 nbSendRequest++; 542 } 543 if (nbRecvNode[rank] > 0) 544 { 545 MPI_Irecv(recvBuffer[rank], recvMessageSize[rank], MPI_CHAR, rank, 0, communicator, &recvRequest[nbRecvRequest]); 546 nbRecvRequest++; 547 } 548 } 549 550 MPI_Waitall(nbRecvRequest, recvRequest, status); 551 MPI_Waitall(nbSendRequest, sendRequest, status); 552 553 for (int rank = 0; rank < mpiSize; rank++) 554 if (nbSendNode[rank] > 0) delete [] sendBuffer[rank]; 555 delete [] sendBuffer; 556 557 char **sendBuffer2 = new char*[mpiSize]; 558 char **recvBuffer2 = new char*[mpiSize]; 559 560 for (int rank = 0; rank < mpiSize; rank++) 561 { 562 nbSendNode[rank] = 0; 563 sendMessageSize[rank] = 0; 564 565 if (nbRecvNode[rank] > 0) 566 { 567 set<NodePtr> neighbourList; 568 pos[rank] = 0; 569 for (int j = 0; j < nbRecvNode[rank]; j++) 570 { 571 Elt elt; 572 unpackPolygon(elt, recvBuffer[rank], pos[rank]); 573 Node node(elt.x, cptRadius(elt), &elt); 574 findNeighbour(sstree.localTree.root, &node, neighbourList); 575 } 576 nbSendNode[rank] = neighbourList.size(); 577 for (set<NodePtr>::iterator it = neighbourList.begin(); it != neighbourList.end(); it++) 578 { 579 Elt *elt = (Elt *) ((*it)->data); 580 sendMessageSize[rank] += packedPolygonSize(*elt); 581 } 582 583 sendBuffer2[rank] = new char[sendMessageSize[rank]]; 584 pos[rank] = 0; 585 586 for (set<NodePtr>::iterator it = neighbourList.begin(); it != neighbourList.end(); it++) 587 { 588 Elt *elt = (Elt *) ((*it)->data); 589 packPolygon(*elt, sendBuffer2[rank], pos[rank]); 590 } 591 } 592 } 593 for (int rank = 0; rank < mpiSize; rank++) 594 if (nbRecvNode[rank] > 0) delete [] recvBuffer[rank]; 595 delete [] recvBuffer; 596 597 598 MPI_Barrier(communicator); 599 MPI_Alltoall(nbSendNode, 1, MPI_INT, nbRecvNode, 1, MPI_INT, communicator); 600 MPI_Alltoall(sendMessageSize, 1, MPI_INT, recvMessageSize, 1, MPI_INT, communicator); 601 602 for (int rank = 0; rank < mpiSize; rank++) 603 if (nbRecvNode[rank] > 0) recvBuffer2[rank] = new char[recvMessageSize[rank]]; 604 605 nbSendRequest = 0; 606 nbRecvRequest = 0; 607 608 for (int rank = 0; rank < mpiSize; rank++) 609 { 610 if (nbSendNode[rank] > 0) 611 { 612 MPI_Issend(sendBuffer2[rank], sendMessageSize[rank], MPI_CHAR, rank, 0, communicator, &sendRequest[nbSendRequest]); 613 nbSendRequest++; 614 } 615 if (nbRecvNode[rank] > 0) 616 { 617 MPI_Irecv(recvBuffer2[rank], recvMessageSize[rank], MPI_CHAR, rank, 0, communicator, &recvRequest[nbRecvRequest]); 618 nbRecvRequest++; 619 } 620 } 621 622 MPI_Waitall(nbRecvRequest, recvRequest, status); 623 MPI_Waitall(nbSendRequest, sendRequest, status); 624 625 int nbNeighbourNodes = 0; 626 for (int rank = 0; rank < mpiSize; rank++) 627 nbNeighbourNodes += nbRecvNode[rank]; 628 629 neighbourElements = new Elt[nbNeighbourNodes]; 630 nbNeighbourElements = nbNeighbourNodes; 631 632 int index = 0; 633 for (int rank = 0; rank < mpiSize; rank++) 634 { 635 pos[rank] = 0; 636 for (int j = 0; j < nbRecvNode[rank]; j++) 637 { 638 unpackPolygon(neighbourElements[index], recvBuffer2[rank], pos[rank]); 639 neighbourElements[index].id.ind = sstree.localTree.leafs.size() + index; 640 index++; 641 } 642 } 643 for (int rank = 0; rank < mpiSize; rank++) 644 { 645 if (nbRecvNode[rank] > 0) delete [] recvBuffer2[rank]; 646 if (nbSendNode[rank] > 0) delete [] sendBuffer2[rank]; 647 } 648 delete [] recvBuffer2; 649 delete [] sendBuffer2; 650 delete [] sendMessageSize; 651 delete [] recvMessageSize; 652 delete [] nbSendNode; 653 delete [] nbRecvNode; 654 delete [] sendRequest; 655 delete [] recvRequest; 656 delete [] status; 657 delete [] pos; 658 659 /* re-compute on received elements to avoid having to send this information */ 660 neighbourNodes.resize(nbNeighbourNodes); 661 setCirclesAndLinks(neighbourElements, neighbourNodes); 662 cptAllEltsGeom(neighbourElements, nbNeighbourNodes, srcGrid.pole); 663 664 /* the local SS tree must include nodes from other cpus if they are potential 665 intersector of a local node */ 666 sstree.localTree.insertNodes(neighbourNodes); 667 668 /* for every local element, 669 use the SS-tree to find all elements (including neighbourElements) 670 who are potential neighbours because their circles intersect, 671 then check all canditates for common edges to build up connectivity information 672 */ 673 for (int j = 0; j < sstree.localTree.leafs.size(); j++) 674 { 675 Node& node = sstree.localTree.leafs[j]; 676 677 /* find all leafs whoes circles that intersect node's circle and save into node->intersectors */ 678 node.search(sstree.localTree.root); 679 680 Elt *elt = (Elt *)(node.data); 681 682 for (int i = 0; i < elt->n; i++) elt->neighbour[i] = NOT_FOUND; 683 684 /* for element `elt` loop through all nodes in the SS-tree 685 whoes circles intersect with the circle around `elt` (the SS intersectors) 686 and check if they are neighbours in the sense that the two elements share an edge. 687 If they do, save this information for elt */ 688 for (list<NodePtr>::iterator it = (node.intersectors).begin(); it != (node.intersectors).end(); ++it) 689 { 690 Elt *elt2 = (Elt *)((*it)->data); 691 set_neighbour(*elt, *elt2); 692 } 693 694 } 702 695 } 703 696 … … 705 698 void Mapper::computeIntersection(Elt *elements, int nbElements) 706 699 { 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 //intersect_ym(&recvElt[j], elt2);834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 700 int mpiSize, mpiRank; 701 MPI_Comm_size(communicator, &mpiSize); 702 MPI_Comm_rank(communicator, &mpiRank); 703 704 MPI_Barrier(communicator); 705 706 vector<Node> *routingList = new vector<Node>[mpiSize]; 707 708 vector<Node> routeNodes; routeNodes.reserve(nbElements); 709 for (int j = 0; j < nbElements; j++) 710 { 711 elements[j].id.ind = j; 712 elements[j].id.rank = mpiRank; 713 routeNodes.push_back(Node(elements[j].x, cptRadius(elements[j]), &elements[j])); 714 } 715 716 vector<vector<int> > routes(routeNodes.size()); 717 sstree.routeIntersections(routes, routeNodes); 718 for (int i = 0; i < routes.size(); ++i) 719 for (int k = 0; k < routes[i].size(); ++k) 720 routingList[routes[i][k]].push_back(routeNodes[i]); 721 722 if (verbose >= 2) 723 { 724 cout << " --> rank " << mpiRank << " nbElements " << nbElements << " : "; 725 for (int rank = 0; rank < mpiSize; rank++) 726 cout << routingList[rank].size() << " "; 727 cout << endl; 728 } 729 MPI_Barrier(communicator); 730 731 int *nbSendNode = new int[mpiSize]; 732 int *nbRecvNode = new int[mpiSize]; 733 int *sentMessageSize = new int[mpiSize]; 734 int *recvMessageSize = new int[mpiSize]; 735 736 for (int rank = 0; rank < mpiSize; rank++) 737 { 738 nbSendNode[rank] = routingList[rank].size(); 739 sentMessageSize[rank] = 0; 740 for (size_t j = 0; j < routingList[rank].size(); j++) 741 { 742 Elt *elt = (Elt *) (routingList[rank][j].data); 743 sentMessageSize[rank] += packedPolygonSize(*elt); 744 } 745 } 746 747 MPI_Alltoall(nbSendNode, 1, MPI_INT, nbRecvNode, 1, MPI_INT, communicator); 748 MPI_Alltoall(sentMessageSize, 1, MPI_INT, recvMessageSize, 1, MPI_INT, communicator); 749 750 int total = 0; 751 752 for (int rank = 0; rank < mpiSize; rank++) 753 { 754 total = total + nbRecvNode[rank]; 755 } 756 757 if (verbose >= 2) cout << "---> rank " << mpiRank << " : compute intersection : total received nodes " << total << endl; 758 char **sendBuffer = new char*[mpiSize]; 759 char **recvBuffer = new char*[mpiSize]; 760 int *pos = new int[mpiSize]; 761 762 for (int rank = 0; rank < mpiSize; rank++) 763 { 764 if (nbSendNode[rank] > 0) sendBuffer[rank] = new char[sentMessageSize[rank]]; 765 if (nbRecvNode[rank] > 0) recvBuffer[rank] = new char[recvMessageSize[rank]]; 766 } 767 768 for (int rank = 0; rank < mpiSize; rank++) 769 { 770 pos[rank] = 0; 771 for (size_t j = 0; j < routingList[rank].size(); j++) 772 { 773 Elt* elt = (Elt *) (routingList[rank][j].data); 774 packPolygon(*elt, sendBuffer[rank], pos[rank]); 775 } 776 } 777 delete [] routingList; 778 779 int nbSendRequest = 0; 780 int nbRecvRequest = 0; 781 MPI_Request *sendRequest = new MPI_Request[mpiSize]; 782 MPI_Request *recvRequest = new MPI_Request[mpiSize]; 783 MPI_Status *status = new MPI_Status[mpiSize]; 784 785 for (int rank = 0; rank < mpiSize; rank++) 786 { 787 if (nbSendNode[rank] > 0) 788 { 789 MPI_Issend(sendBuffer[rank], sentMessageSize[rank], MPI_CHAR, rank, 0, communicator, &sendRequest[nbSendRequest]); 790 nbSendRequest++; 791 } 792 if (nbRecvNode[rank] > 0) 793 { 794 MPI_Irecv(recvBuffer[rank], recvMessageSize[rank], MPI_CHAR, rank, 0, communicator, &recvRequest[nbRecvRequest]); 795 nbRecvRequest++; 796 } 797 } 798 799 MPI_Waitall(nbRecvRequest, recvRequest, status); 800 MPI_Waitall(nbSendRequest, sendRequest, status); 801 802 char **sendBuffer2 = new char*[mpiSize]; 803 char **recvBuffer2 = new char*[mpiSize]; 804 805 double tic = cputime(); 806 for (int rank = 0; rank < mpiSize; rank++) 807 { 808 sentMessageSize[rank] = 0; 809 810 if (nbRecvNode[rank] > 0) 811 { 812 Elt *recvElt = new Elt[nbRecvNode[rank]]; 813 pos[rank] = 0; 814 for (int j = 0; j < nbRecvNode[rank]; j++) 815 { 816 unpackPolygon(recvElt[j], recvBuffer[rank], pos[rank]); 817 cptEltGeom(recvElt[j], tgtGrid.pole); 818 Node recvNode(recvElt[j].x, cptRadius(recvElt[j]), &recvElt[j]); 819 recvNode.search(sstree.localTree.root); 820 /* for a node holding an element of the target, loop throught candidates for intersecting source */ 821 for (list<NodePtr>::iterator it = (recvNode.intersectors).begin(); it != (recvNode.intersectors).end(); ++it) 822 { 823 Elt *elt2 = (Elt *) ((*it)->data); 824 /* recvElt is target, elt2 is source */ 825 // intersect(&recvElt[j], elt2); 826 intersect_ym(&recvElt[j], elt2); 827 } 828 if (recvElt[j].is.size() > 0) sentMessageSize[rank] += packIntersectionSize(recvElt[j]); 829 830 // here recvNode goes out of scope 831 } 832 833 if (sentMessageSize[rank] > 0) 834 { 835 sentMessageSize[rank] += sizeof(int); 836 sendBuffer2[rank] = new char[sentMessageSize[rank]]; 837 *((int *) sendBuffer2[rank]) = 0; 838 pos[rank] = sizeof(int); 839 for (int j = 0; j < nbRecvNode[rank]; j++) 840 { 841 packIntersection(recvElt[j], sendBuffer2[rank], pos[rank]); 842 //FIXME should be deleted: recvElt[j].delete_intersections(); // intersection areas have been packed to buffer and won't be used any more 843 } 844 } 845 delete [] recvElt; 846 } 847 } 848 delete [] pos; 849 850 for (int rank = 0; rank < mpiSize; rank++) 851 { 852 if (nbSendNode[rank] > 0) delete [] sendBuffer[rank]; 853 if (nbRecvNode[rank] > 0) delete [] recvBuffer[rank]; 854 nbSendNode[rank] = 0; 855 } 856 857 if (verbose >= 2) cout << "Rank " << mpiRank << " Compute (internal) intersection " << cputime() - tic << " s" << endl; 858 MPI_Alltoall(sentMessageSize, 1, MPI_INT, recvMessageSize, 1, MPI_INT, communicator); 859 860 for (int rank = 0; rank < mpiSize; rank++) 861 if (recvMessageSize[rank] > 0) 862 recvBuffer2[rank] = new char[recvMessageSize[rank]]; 863 864 nbSendRequest = 0; 865 nbRecvRequest = 0; 866 867 for (int rank = 0; rank < mpiSize; rank++) 868 { 869 if (sentMessageSize[rank] > 0) 870 { 871 MPI_Issend(sendBuffer2[rank], sentMessageSize[rank], MPI_CHAR, rank, 0, communicator, &sendRequest[nbSendRequest]); 872 nbSendRequest++; 873 } 874 if (recvMessageSize[rank] > 0) 875 { 876 MPI_Irecv(recvBuffer2[rank], recvMessageSize[rank], MPI_CHAR, rank, 0, communicator, &recvRequest[nbRecvRequest]); 877 nbRecvRequest++; 878 } 879 } 880 881 MPI_Waitall(nbRecvRequest, recvRequest, status); 882 MPI_Waitall(nbSendRequest, sendRequest, status); 883 884 delete [] sendRequest; 885 delete [] recvRequest; 886 delete [] status; 887 for (int rank = 0; rank < mpiSize; rank++) 888 { 889 if (nbRecvNode[rank] > 0) 890 { 891 if (sentMessageSize[rank] > 0) 892 delete [] sendBuffer2[rank]; 893 } 894 895 if (recvMessageSize[rank] > 0) 896 { 897 unpackIntersection(elements, recvBuffer2[rank]); 898 delete [] recvBuffer2[rank]; 899 } 900 } 901 delete [] sendBuffer2; 902 delete [] recvBuffer2; 903 delete [] sendBuffer; 904 delete [] recvBuffer; 905 906 delete [] nbSendNode; 907 delete [] nbRecvNode; 908 delete [] sentMessageSize; 909 delete [] recvMessageSize; 917 910 } 918 911 919 912 Mapper::~Mapper() 920 913 { 921 922 923 924 925 926 } 927 928 } 914 delete [] remapMatrix; 915 delete [] srcAddress; 916 delete [] srcRank; 917 delete [] dstAddress; 918 if (neighbourElements) delete [] neighbourElements; 919 } 920 921 }
Note: See TracChangeset
for help on using the changeset viewer.