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

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

Distributions and transformations: Avoid using heap allocations.

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