source: XIOS/dev/branch_openmp/extern/remap/src/mapper.cpp @ 1338

Last change on this file since 1338 was 1338, checked in by yushan, 6 years ago

dev_omp

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