source: XIOS/trunk/src/transformation/grid_transformation.cpp @ 634

Last change on this file since 634 was 634, checked in by rlacroix, 9 years ago

Transformations: Fix some errors in MPI communications

  • Some communications could have caused deadlocks.
  • Some communications were not properly checked for completion.
File size: 28.0 KB
Line 
1/*!
2   \file grid_transformation.cpp
3   \author Ha NGUYEN
4   \since 14 May 2015
5   \date 02 Jul 2015
6
7   \brief Interface for all transformations.
8 */
9#include "grid_transformation.hpp"
10#include "axis_algorithm_inverse.hpp"
11#include "axis_algorithm_zoom.hpp"
12#include "axis_algorithm_interpolate.hpp"
13#include "domain_algorithm_zoom.hpp"
14#include "context.hpp"
15#include "context_client.hpp"
16#include "transformation_mapping.hpp"
17#include "axis_algorithm_transformation.hpp"
18
19namespace xios {
20CGridTransformation::CGridTransformation(CGrid* destination, CGrid* source)
21: gridSource_(source), gridDestination_(destination), originalGridSource_(source),
22  globalIndexOfCurrentGridSource_(0), globalIndexOfOriginalGridSource_(0), weightOfGlobalIndexOfOriginalGridSource_(0), algoTypes_()
23{
24  //Verify the compatibity between two grids
25  int numElement = gridDestination_->axis_domain_order.numElements();
26  if (numElement != gridSource_->axis_domain_order.numElements())
27    ERROR("CGridTransformation::CGridTransformation(CGrid* destination, CGrid* source)",
28       << "Two grids have different number of elements"
29       << "Number of elements of grid source " <<gridSource_->getId() << " is " << gridSource_->axis_domain_order.numElements()  << std::endl
30       << "Number of elements of grid destination " <<gridDestination_->getId() << " is " << numElement);
31
32  for (int i = 0; i < numElement; ++i)
33  {
34    if (gridDestination_->axis_domain_order(i) != gridSource_->axis_domain_order(i))
35      ERROR("CGridTransformation::CGridTransformation(CGrid* destination, CGrid* source)",
36         << "Transformed grid and its grid source have incompatible elements"
37         << "Grid source " <<gridSource_->getId() << std::endl
38         << "Grid destination " <<gridDestination_->getId());
39  }
40
41  std::vector<CAxis*> axisSrcTmp = gridSource_->getAxis(), axisSrc;
42  std::vector<CDomain*> domainSrcTmp = gridSource_->getDomains(), domainSrc;
43  for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
44  {
45    CAxis* axis = CAxis::createAxis();
46    axis->setAttributes(axisSrcTmp[idx]);
47    axisSrc.push_back(axis);
48  }
49
50  for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
51  {
52    CDomain* domain = CDomain::createDomain();
53    domain->setAttributes(domainSrcTmp[idx]);
54    domainSrc.push_back(domain);
55  }
56
57  gridSource_ = CGrid::createGrid(domainSrc, axisSrc, gridDestination_->axis_domain_order);
58  gridSourceDimensionSize_ = gridSource_->getGlobalDimension();
59  gridDestinationDimensionSize_ = gridDestination_->getGlobalDimension();
60
61  initializeMappingOfOriginalGridSource();
62  initializeAlgorithms();
63}
64
65/*!
66  Initialize the mapping between the first grid source and the original one
67  In a series of transformation, for each step, there is a need to "create" a new grid that plays a role of "temporary" source.
68Because at the end of the series, we need to know about the index mapping between the final grid destination and original grid source,
69for each transformation, we need to make sure that the current "temporary source" maps its global index correctly to the original one.
70*/
71void CGridTransformation::initializeMappingOfOriginalGridSource()
72{
73  CContext* context = CContext::getCurrent();
74  CContextClient* client=context->client;
75
76  CDistributionClient distribution(client->clientRank, originalGridSource_);
77  const CArray<size_t,1>& globalIndexGridDestSendToServer = distribution.getGlobalDataIndexSendToServer();
78
79  globalIndexOfCurrentGridSource_   = new CArray<size_t,1>(globalIndexGridDestSendToServer.numElements());
80  globalIndexOfOriginalGridSource_  = new CArray<size_t,1>(globalIndexGridDestSendToServer.numElements());
81  weightOfGlobalIndexOfOriginalGridSource_  = new CArray<double,1>(globalIndexGridDestSendToServer.numElements());
82  *globalIndexOfCurrentGridSource_  = globalIndexGridDestSendToServer;
83  *globalIndexOfOriginalGridSource_ = globalIndexGridDestSendToServer;
84  *weightOfGlobalIndexOfOriginalGridSource_ = 1.0;
85}
86
87CGridTransformation::~CGridTransformation()
88{
89  std::list<CGenericAlgorithmTransformation*>::const_iterator itb = algoTransformation_.begin(), it,
90                                                              ite = algoTransformation_.end();
91  for (it = itb; it != ite; ++it) delete (*it);
92
93  std::map<int, CArray<int,1>* >::const_iterator itMap, iteMap;
94  itMap = localIndexToSendFromGridSource_.begin();
95  iteMap = localIndexToSendFromGridSource_.end();
96  for (; itMap != iteMap; ++itMap) delete (itMap->second);
97
98  if (0 != globalIndexOfCurrentGridSource_) delete globalIndexOfCurrentGridSource_;
99  if (0 != globalIndexOfOriginalGridSource_) delete globalIndexOfOriginalGridSource_;
100  if (0 != weightOfGlobalIndexOfOriginalGridSource_) delete weightOfGlobalIndexOfOriginalGridSource_;
101}
102
103/*!
104  Initialize the algorithms (transformations)
105*/
106void CGridTransformation::initializeAlgorithms()
107{
108  std::vector<int> axisPositionInGrid;
109  std::vector<int> domPositionInGrid;
110  std::vector<CAxis*> axisListDestP = gridDestination_->getAxis();
111  std::vector<CDomain*> domListDestP = gridDestination_->getDomains();
112
113  int idx = 0;
114  for (int i = 0; i < gridDestination_->axis_domain_order.numElements(); ++i)
115  {
116    if (false == (gridDestination_->axis_domain_order)(i))
117    {
118      axisPositionInGrid.push_back(idx);
119      ++idx;
120    }
121    else
122    {
123      ++idx;
124      domPositionInGrid.push_back(idx);
125      ++idx;
126    }
127  }
128
129  for (int i = 0; i < axisListDestP.size(); ++i)
130  {
131    elementPosition2AxisPositionInGrid_[axisPositionInGrid[i]] = i;
132  }
133
134  for (int i = 0; i < domListDestP.size(); ++i)
135  {
136    elementPosition2DomainPositionInGrid_[domPositionInGrid[i]] = i;
137  }
138
139  idx = 0;
140  for (int i = 0; i < gridDestination_->axis_domain_order.numElements(); ++i)
141  {
142    if (false == (gridDestination_->axis_domain_order)(i))
143    {
144      initializeAxisAlgorithms(idx);
145      ++idx;
146    }
147    else
148    {
149      ++idx;
150      initializeDomainAlgorithms(idx);
151      ++idx;
152    }
153  }
154}
155
156
157
158/*!
159  Initialize the algorithms corresponding to transformation info contained in each axis.
160If an axis has transformations, these transformations will be represented in form of vector of CTransformation pointers
161In general, each axis can have several transformations performed on itself. However, should they be done seperately or combinely (of course in order)?
162For now, one approach is to do these combinely but maybe this needs changing.
163\param [in] axisPositionInGrid position of an axis in grid. (for example: a grid with one domain and one axis, position of domain is 1, position of axis is 2)
164*/
165void CGridTransformation::initializeAxisAlgorithms(int axisPositionInGrid)
166{
167  std::vector<CAxis*> axisListDestP = gridDestination_->getAxis();
168  if (!axisListDestP.empty())
169  {
170    if (axisListDestP[elementPosition2AxisPositionInGrid_[axisPositionInGrid]]->hasTransformation())
171    {
172      CAxis::TransMapTypes trans = axisListDestP[elementPosition2AxisPositionInGrid_[axisPositionInGrid]]->getAllTransformations();
173      CAxis::TransMapTypes::const_iterator itb = trans.begin(), it,
174                                           ite = trans.end();
175      int transformationOrder = 0;
176      for (it = itb; it != ite; ++it)
177      {
178        listAlgos_.push_back(std::make_pair(axisPositionInGrid, std::make_pair(it->first, transformationOrder)));
179        algoTypes_.push_back(false);
180        ++transformationOrder;
181      }
182    }
183  }
184}
185
186/*!
187  Initialize the algorithms corresponding to transformation info contained in each domain.
188If a domain has transformations, they will be represented in form of vector of CTransformation pointers
189In general, each domain can have several transformations performed on itself.
190\param [in] domPositionInGrid position of a domain in grid. (for example: a grid with one domain and one axis, position of domain is 1, position of axis is 2)
191*/
192void CGridTransformation::initializeDomainAlgorithms(int domPositionInGrid)
193{
194  std::vector<CDomain*> domListDestP = gridDestination_->getDomains();
195  if (!domListDestP.empty())
196  {
197    if (domListDestP[elementPosition2DomainPositionInGrid_[domPositionInGrid]]->hasTransformation())
198    {
199      CDomain::TransMapTypes trans = domListDestP[elementPosition2DomainPositionInGrid_[domPositionInGrid]]->getAllTransformations();
200      CDomain::TransMapTypes::const_iterator itb = trans.begin(), it,
201                                             ite = trans.end();
202      int transformationOrder = 0;
203      for (it = itb; it != ite; ++it)
204      {
205        listAlgos_.push_back(std::make_pair(domPositionInGrid, std::make_pair(it->first, transformationOrder)));
206        algoTypes_.push_back(true);
207        ++transformationOrder;
208      }
209    }
210  }
211
212}
213
214/*!
215  Select algorithm correspoding to its transformation type and its position in each element
216  \param [in] elementPositionInGrid position of element in grid. e.g: a grid has 1 domain and 1 axis, then position of domain is 1 (because it contains 2 basic elements)
217                                             and position of axis is 2
218  \param [in] transType transformation type, for now we have Zoom_axis, inverse_axis
219  \param [in] transformationOrder position of the transformation in an element (an element can have several transformation)
220  \param [in] isDomainAlgo flag to specify type of algorithm (for domain or axis)
221*/
222void CGridTransformation::selectAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder, bool isDomainAlgo)
223{
224   if (isDomainAlgo) selectDomainAlgo(elementPositionInGrid, transType, transformationOrder);
225   else selectAxisAlgo(elementPositionInGrid, transType, transformationOrder);
226}
227
228/*!
229  Select algorithm of an axis correspoding to its transformation type and its position in each element
230  \param [in] elementPositionInGrid position of element in grid. e.g: a grid has 1 domain and 1 axis, then position of domain is 1 (because it contains 2 basic elements)
231                                             and position of axis is 2
232  \param [in] transType transformation type, for now we have Zoom_axis, inverse_axis
233  \param [in] transformationOrder position of the transformation in an element (an element can have several transformation)
234*/
235void CGridTransformation::selectAxisAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder)
236{
237  std::vector<CAxis*> axisListDestP = gridDestination_->getAxis();
238  std::vector<CAxis*> axisListSrcP = gridSource_->getAxis();
239
240  int axisIndex =  elementPosition2AxisPositionInGrid_[elementPositionInGrid];
241  CAxis::TransMapTypes trans = axisListDestP[axisIndex]->getAllTransformations();
242  CAxis::TransMapTypes::const_iterator it = trans.begin();
243
244  for (int i = 0; i < transformationOrder; ++i, ++it) {}  // Find the correct transformation
245
246  CZoomAxis* zoomAxis = 0;
247  CInterpolateAxis* interpAxis = 0;
248  CGenericAlgorithmTransformation* algo = 0;
249  switch (transType)
250  {
251    case TRANS_INTERPOLATE_AXIS:
252      interpAxis = dynamic_cast<CInterpolateAxis*> (it->second);
253      algo = new CAxisAlgorithmInterpolate(axisListDestP[axisIndex], axisListSrcP[axisIndex], interpAxis);
254      break;
255    case TRANS_ZOOM_AXIS:
256      zoomAxis = dynamic_cast<CZoomAxis*> (it->second);
257      algo = new CAxisAlgorithmZoom(axisListDestP[axisIndex], axisListSrcP[axisIndex], zoomAxis);
258      break;
259    case TRANS_INVERSE_AXIS:
260      algo = new CAxisAlgorithmInverse(axisListDestP[axisIndex], axisListSrcP[axisIndex]);
261      break;
262    default:
263      break;
264  }
265  algoTransformation_.push_back(algo);
266
267}
268
269/*!
270  Select algorithm of a domain correspoding to its transformation type and its position in each element
271  \param [in] elementPositionInGrid position of element in grid. e.g: a grid has 1 domain and 1 axis, then position of domain is 1 (because it contains 2 basic elements)
272                                             and position of axis is 2
273  \param [in] transType transformation type, for now we have Zoom_axis, inverse_axis
274  \param [in] transformationOrder position of the transformation in an element (an element can have several transformation)
275*/
276void CGridTransformation::selectDomainAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder)
277{
278  std::vector<CDomain*> domainListDestP = gridDestination_->getDomains();
279  std::vector<CDomain*> domainListSrcP = gridSource_->getDomains();
280
281  int domainIndex =  elementPosition2DomainPositionInGrid_[elementPositionInGrid];
282  CDomain::TransMapTypes trans = domainListDestP[domainIndex]->getAllTransformations();
283  CDomain::TransMapTypes::const_iterator it = trans.begin();
284
285  for (int i = 0; i < transformationOrder; ++i, ++it) {}  // Find the correct transformation
286
287  CZoomDomain* zoomDomain = 0;
288  CGenericAlgorithmTransformation* algo = 0;
289  switch (transType)
290  {
291    case TRANS_ZOOM_DOMAIN:
292      zoomDomain = dynamic_cast<CZoomDomain*> (it->second);
293      algo = new CDomainAlgorithmZoom(domainListDestP[domainIndex], domainListSrcP[domainIndex], zoomDomain);
294      break;
295    default:
296      break;
297  }
298  algoTransformation_.push_back(algo);
299}
300
301/*!
302  Assign the current grid destination to the grid source in the new transformation.
303The current grid destination plays the role of grid source in next transformation (if any).
304Only element on which the transformation is performed is modified
305  \param [in] elementPositionInGrid position of element in grid
306  \param [in] transType transformation type
307*/
308void CGridTransformation::setUpGrid(int elementPositionInGrid, ETranformationType transType)
309{
310  std::vector<CAxis*> axisListDestP = gridDestination_->getAxis();
311  std::vector<CAxis*> axisListSrcP = gridSource_->getAxis();
312
313  std::vector<CDomain*> domListDestP = gridDestination_->getDomains();
314  std::vector<CDomain*> domListSrcP = gridSource_->getDomains();
315
316  int axisIndex, domainIndex;
317  switch (transType)
318  {
319    case TRANS_ZOOM_DOMAIN:
320      domainIndex = elementPosition2DomainPositionInGrid_[elementPositionInGrid];
321      domListSrcP[domainIndex]->duplicateAttributes(domListDestP[domainIndex]);
322      break;
323
324    case TRANS_INTERPOLATE_AXIS:
325    case TRANS_ZOOM_AXIS:
326    case TRANS_INVERSE_AXIS:
327      axisIndex =  elementPosition2AxisPositionInGrid_[elementPositionInGrid];
328      axisListSrcP[axisIndex]->duplicateAttributes(axisListDestP[axisIndex]);
329      break;
330    default:
331      break;
332  }
333}
334
335/*!
336  Perform all transformations
337  For each transformation, there are some things to do:
338  -) Chose the correct algorithm by transformation type and position of element
339  -) Calculate the mapping of global index between the current grid source and grid destination
340  -) Calculate the mapping of global index between current grid DESTINATION and ORIGINAL grid SOURCE
341  -) Make current grid destination become grid source in the next transformation
342*/
343void CGridTransformation::computeAll()
344{
345  CContext* context = CContext::getCurrent();
346  CContextClient* client=context->client;
347
348  ListAlgoType::const_iterator itb = listAlgos_.begin(),
349                               ite = listAlgos_.end(), it;
350  CGenericAlgorithmTransformation* algo = 0;
351
352  for (it = itb; it != ite; ++it)
353  {
354    int elementPositionInGrid = it->first;
355    ETranformationType transType = (it->second).first;
356    int transformationOrder = (it->second).second;
357    std::map<size_t, std::vector<std::pair<size_t,double> > > globaIndexWeightFromDestToSource;
358
359    // First of all, select an algorithm
360    selectAlgo(elementPositionInGrid, transType, transformationOrder, algoTypes_[std::distance(itb, it)]);
361    algo = algoTransformation_.back();
362
363    // Recalculate the distribution of grid destination
364    CDistributionClient distributionClientDest(client->clientRank, gridDestination_);
365    const CArray<size_t,1>& globalIndexGridDestSendToServer = distributionClientDest.getGlobalDataIndexSendToServer();
366
367    // ComputeTransformation of global index of each element
368    std::vector<int> gridDestinationDimensionSize = gridDestination_->getGlobalDimension();
369    std::vector<int> gridSrcDimensionSize = gridSource_->getGlobalDimension();
370    int elementPosition = it->first;
371    algo->computeGlobalSourceIndex(elementPosition,
372                                   gridDestinationDimensionSize,
373                                   gridSrcDimensionSize,
374                                   globalIndexGridDestSendToServer,
375                                   globaIndexWeightFromDestToSource);
376
377    // Compute transformation of global indexes among grids
378    computeTransformationFromOriginalGridSource(globaIndexWeightFromDestToSource);
379
380    // Now grid destination becomes grid source in a new transformation
381    setUpGrid(elementPositionInGrid, transType);
382  }
383
384  updateFinalGridDestination();
385  computeFinalTransformationMapping();
386}
387
388
389/*!
390  After applying the algorithms, there are some informations on grid destination needing change, for now, there are:
391   +) mask
392*/
393void CGridTransformation::updateFinalGridDestination()
394{
395  CContext* context = CContext::getCurrent();
396  CContextClient* client=context->client;
397
398  //First of all, retrieve info of local mask of grid destination
399  CDistributionClient distributionClientDest(client->clientRank, gridDestination_);
400  const CArray<int, 1>& localMaskIndexOnClientDest = distributionClientDest.getLocalMaskIndexOnClient();
401  const CArray<size_t,1>& globalIndexOnClientDest = distributionClientDest.getGlobalDataIndexSendToServer();
402
403  CArray<size_t, 1>::const_iterator itbArr, itArr, iteArr;
404  itbArr = globalIndexOnClientDest.begin();
405  iteArr = globalIndexOnClientDest.end();
406
407  // Then find out which index became invalid (become masked after being applied the algorithms, or demande some masked points from grid source)
408  int num = globalIndexOfOriginalGridSource_->numElements();
409  const size_t sfmax = NumTraits<unsigned long>::sfmax();
410  int maskIndexNum = 0;
411  for (int idx = 0; idx < num; ++idx)
412  {
413    if (sfmax == (*globalIndexOfOriginalGridSource_)(idx))
414    {
415      size_t maskedGlobalIndex = (*globalIndexOfCurrentGridSource_)(idx);
416      itArr = std::find(itbArr, iteArr, maskedGlobalIndex);
417      if (iteArr != itArr) ++maskIndexNum;
418    }
419  }
420
421  CArray<int,1>* maskIndexToModify = new CArray<int,1>(maskIndexNum);
422  maskIndexNum = 0;
423  for (int idx = 0; idx < num; ++idx)
424  {
425    if (sfmax == (*globalIndexOfOriginalGridSource_)(idx))
426    {
427      size_t maskedGlobalIndex = (*globalIndexOfCurrentGridSource_)(idx);
428      itArr = std::find(itbArr, iteArr, maskedGlobalIndex);
429      if (iteArr != itArr)
430      {
431        int localIdx = std::distance(itbArr, itArr);
432        (*maskIndexToModify)(maskIndexNum) = (localMaskIndexOnClientDest)(localIdx);
433        ++maskIndexNum;
434      }
435    }
436  }
437
438  gridDestination_->modifyMask(*maskIndexToModify);
439
440  delete maskIndexToModify;
441}
442
443/*!
444  A transformation from a grid source to grid destination often passes several intermediate grids, which play a role of
445temporary grid source and/or grid destination. This function makes sure that global index of original grid source are mapped correctly to
446the final grid destination
447*/
448void CGridTransformation::computeTransformationFromOriginalGridSource(const std::map<size_t, std::vector<std::pair<size_t,double> > >& globaIndexMapFromDestToSource)
449{
450  CContext* context = CContext::getCurrent();
451  CContextClient* client=context->client;
452
453  CTransformationMapping transformationMap(gridDestination_, gridSource_);
454
455    // Then compute transformation mapping among clients
456  transformationMap.computeTransformationMapping(globaIndexMapFromDestToSource);
457
458  const std::map<int,std::vector<std::vector<std::pair<size_t,double> > > >& globalIndexToReceive = transformationMap.getGlobalIndexReceivedOnGridDestMapping();
459  const std::map<int,std::vector<size_t> >& globalIndexToSend = transformationMap.getGlobalIndexSendToGridDestMapping();
460
461 // Sending global index of original grid source
462  std::map<int,std::vector<size_t> >::const_iterator itbSend = globalIndexToSend.begin(), itSend,
463                                                     iteSend = globalIndexToSend.end();
464  CArray<size_t,1>::const_iterator itbArr = globalIndexOfCurrentGridSource_->begin(), itArr,
465                                   iteArr = globalIndexOfCurrentGridSource_->end();
466 int sendBuffSize = 0;
467 for (itSend = itbSend; itSend != iteSend; ++itSend) sendBuffSize += (itSend->second).size();
468
469 typedef unsigned long Scalar;
470 unsigned long* sendBuff, *currentSendBuff;
471 if (0 != sendBuffSize) sendBuff = new unsigned long [sendBuffSize];
472 for (StdSize idx = 0; idx < sendBuffSize; ++idx) sendBuff[idx] = NumTraits<Scalar>::sfmax();
473
474 std::map<int, MPI_Request> requests;
475
476 int currentBuffPosition = 0;
477 for (itSend = itbSend; itSend != iteSend; ++itSend)
478 {
479   int destRank = itSend->first;
480   const std::vector<size_t>& globalIndexOfCurrentGridSourceToSend = itSend->second;
481   int countSize = globalIndexOfCurrentGridSourceToSend.size();
482   for (int idx = 0; idx < (countSize); ++idx)
483   {
484     itArr = std::find(itbArr, iteArr, globalIndexOfCurrentGridSourceToSend[idx]);
485     if (iteArr != itArr)
486     {
487       int index = std::distance(itbArr, itArr);
488       sendBuff[idx+currentBuffPosition] = (*globalIndexOfOriginalGridSource_)(index);
489     }
490   }
491   currentSendBuff = sendBuff + currentBuffPosition;
492   MPI_Isend(currentSendBuff, countSize, MPI_UNSIGNED_LONG, destRank, 14, client->intraComm, &requests[destRank]);
493   currentBuffPosition += countSize;
494 }
495
496 // Receiving global index of grid source sending from current grid source
497 std::map<int,std::vector<std::vector<std::pair<size_t,double> > > >::const_iterator itbRecv = globalIndexToReceive.begin(), itRecv,
498                                                                                     iteRecv = globalIndexToReceive.end();
499 int recvBuffSize = 0;
500 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv) recvBuffSize += (itRecv->second).size();
501
502 unsigned long* recvBuff, *currentRecvBuff;
503 if (0 != recvBuffSize) recvBuff = new unsigned long [recvBuffSize];
504 for (StdSize idx = 0; idx < recvBuffSize; ++idx) recvBuff[idx] = NumTraits<Scalar>::sfmax();
505
506 int currentRecvBuffPosition = 0;
507 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
508 {
509   MPI_Status status;
510   int srcRank = itRecv->first;
511   int countSize = (itRecv->second).size();
512   currentRecvBuff = recvBuff + currentRecvBuffPosition;
513   MPI_Recv(currentRecvBuff, countSize, MPI_UNSIGNED_LONG, srcRank, 14, client->intraComm, &status);
514   currentRecvBuffPosition += countSize;
515 }
516
517 int nbCurrentGridSource = 0;
518 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
519 {
520   int ssize = (itRecv->second).size();
521   for (int idx = 0; idx < ssize; ++idx)
522   {
523     nbCurrentGridSource += (itRecv->second)[idx].size();
524   }
525 }
526
527 if (globalIndexOfCurrentGridSource_->numElements()  != nbCurrentGridSource)
528 {
529   delete globalIndexOfCurrentGridSource_;
530   globalIndexOfCurrentGridSource_ = new CArray<size_t,1>(nbCurrentGridSource);
531   delete globalIndexOfOriginalGridSource_;
532   globalIndexOfOriginalGridSource_ = new CArray<size_t,1>(nbCurrentGridSource);
533   delete weightOfGlobalIndexOfOriginalGridSource_;
534   weightOfGlobalIndexOfOriginalGridSource_ = new CArray<double,1>(nbCurrentGridSource);
535 }
536
537 int k = 0;
538 currentRecvBuff = recvBuff;
539 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
540 {
541   int countSize = (itRecv->second).size();
542   for (int idx = 0; idx < countSize; ++idx, ++currentRecvBuff)
543   {
544     int ssize = (itRecv->second)[idx].size();
545     for (int i = 0; i < ssize; ++i)
546     {
547       (*globalIndexOfCurrentGridSource_)(k) = ((itRecv->second)[idx][i]).first;
548       (*weightOfGlobalIndexOfOriginalGridSource_)(k) = ((itRecv->second)[idx][i]).second;
549       (*globalIndexOfOriginalGridSource_)(k) = *currentRecvBuff;
550       ++k;
551     }
552   }
553 }
554
555 std::map<int, MPI_Request>::iterator itRequest;
556 for (itRequest = requests.begin(); itRequest != requests.end(); ++itRequest)
557   MPI_Wait(&itRequest->second, MPI_STATUS_IGNORE);
558
559 if (0 != sendBuffSize) delete [] sendBuff;
560 if (0 != recvBuffSize) delete [] recvBuff;
561}
562
563/*!
564  Compute transformation mapping between grid source and grid destination
565  The transformation between grid source and grid destination is represented in form of mapping between global index
566of two grids. Then local index mapping between data on each grid will be found out thanks to these global indexes
567*/
568void CGridTransformation::computeFinalTransformationMapping()
569{
570  CContext* context = CContext::getCurrent();
571  CContextClient* client=context->client;
572
573  CTransformationMapping transformationMap(gridDestination_, originalGridSource_);
574
575  std::map<size_t, std::vector<std::pair<size_t,double> > > globaIndexWeightFromDestToSource;
576  int nb = globalIndexOfCurrentGridSource_->numElements();
577  const size_t sfmax = NumTraits<unsigned long>::sfmax();
578  for (int idx = 0; idx < nb; ++idx)
579  {
580    if (sfmax != (*globalIndexOfOriginalGridSource_)(idx))
581      globaIndexWeightFromDestToSource[(*globalIndexOfCurrentGridSource_)(idx)].push_back(make_pair((*globalIndexOfOriginalGridSource_)(idx),(*weightOfGlobalIndexOfOriginalGridSource_)(idx))) ;
582  }
583
584  // Then compute transformation mapping among clients
585  transformationMap.computeTransformationMapping(globaIndexWeightFromDestToSource);
586
587  const std::map<int,std::vector<std::vector<std::pair<size_t,double> > > >& globalIndexToReceive = transformationMap.getGlobalIndexReceivedOnGridDestMapping();
588  const std::map<int,std::vector<size_t> >& globalIndexToSend = transformationMap.getGlobalIndexSendToGridDestMapping();
589
590  CDistributionClient distributionClientDest(client->clientRank, gridDestination_);
591  CDistributionClient distributionClientSrc(client->clientRank, originalGridSource_);
592
593  const CArray<int, 1>& localIndexOnClientDest = distributionClientDest.getLocalDataIndexSendToServer();
594  const CArray<size_t,1>& globalIndexOnClientDest = distributionClientDest.getGlobalDataIndexSendToServer();
595
596  const CArray<int, 1>& localIndexOnClientSrc = distributionClientSrc.getLocalDataIndexOnClient();
597  const CArray<size_t,1>& globalIndexOnClientSrc = distributionClientSrc.getGlobalDataIndexSendToServer();
598
599  std::vector<size_t>::const_iterator itbVec, itVec, iteVec;
600  CArray<size_t, 1>::const_iterator itbArr, itArr, iteArr;
601
602  std::map<int,std::vector<std::vector<std::pair<size_t,double> > > >::const_iterator itbMapRecv, itMapRecv, iteMapRecv;
603
604  // Find out local index on grid destination (received)
605  itbMapRecv = globalIndexToReceive.begin();
606  iteMapRecv = globalIndexToReceive.end();
607  itbArr = globalIndexOnClientDest.begin();
608  iteArr = globalIndexOnClientDest.end();
609  for (itMapRecv = itbMapRecv; itMapRecv != iteMapRecv; ++itMapRecv)
610  {
611    int sourceRank = itMapRecv->first;
612    int numGlobalIndex = (itMapRecv->second).size();
613    for (int i = 0; i < numGlobalIndex; ++i)
614    {
615      int vecSize = ((itMapRecv->second)[i]).size();
616      std::vector<std::pair<int,double> > tmpVec;
617      for (int idx = 0; idx < vecSize; ++idx)
618      {
619        size_t globalIndex = (itMapRecv->second)[i][idx].first;
620        double weight = (itMapRecv->second)[i][idx].second;
621        itArr = std::find(itbArr, iteArr, globalIndex);
622        if (iteArr != itArr)
623        {
624          int localIdx = std::distance(itbArr, itArr);
625          tmpVec.push_back(make_pair(localIdx, weight));
626        }
627      }
628      localIndexToReceiveOnGridDest_[sourceRank].push_back(tmpVec);
629    }
630  }
631
632  // Find out local index on grid source (to send)
633  std::map<int,std::vector<size_t> >::const_iterator itbMap, itMap, iteMap;
634  itbMap = globalIndexToSend.begin();
635  iteMap = globalIndexToSend.end();
636  itbArr = globalIndexOnClientSrc.begin();
637  iteArr = globalIndexOnClientSrc.end();
638  for (itMap = itbMap; itMap != iteMap; ++itMap)
639  {
640    CArray<int,1>* ptr = new CArray<int,1>((itMap->second).size());
641    localIndexToSendFromGridSource_[itMap->first] = ptr;
642    int destRank = itMap->first;
643    int vecSize = (itMap->second).size();
644    for (int idx = 0; idx < vecSize; ++idx)
645    {
646      itArr = std::find(itbArr, iteArr, (itMap->second)[idx]);
647      if (iteArr != itArr)
648      {
649        int localIdx = std::distance(itbArr, itArr);
650        (*localIndexToSendFromGridSource_[destRank])(idx) = (localIdx);
651      }
652    }
653  }
654}
655
656/*!
657  Local index of data which need sending from the grid source
658  \return local index of data
659*/
660const std::map<int, CArray<int,1>* >& CGridTransformation::getLocalIndexToSendFromGridSource() const
661{
662  return localIndexToSendFromGridSource_;
663}
664
665/*!
666  Local index of data which will be received on the grid destination
667  \return local index of data
668*/
669const std::map<int,std::vector<std::vector<std::pair<int,double> > > >& CGridTransformation::getLocalIndexToReceiveOnGridDest() const
670{
671  return localIndexToReceiveOnGridDest_;
672}
673
674}
Note: See TracBrowser for help on using the repository browser.