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

Last change on this file since 631 was 631, checked in by mhnguyen, 9 years ago

Implementing zooming on a domain

+) Add algorithm to do zooming on a domain
+) Remove some redundant codes

Test
+) On Curie
+) test_complete and test_client are correct

File size: 27.7 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 int currentBuffPosition = 0;
475 for (itSend = itbSend; itSend != iteSend; ++itSend)
476 {
477   int destRank = itSend->first;
478   const std::vector<size_t>& globalIndexOfCurrentGridSourceToSend = itSend->second;
479   int countSize = globalIndexOfCurrentGridSourceToSend.size();
480   for (int idx = 0; idx < (countSize); ++idx)
481   {
482     itArr = std::find(itbArr, iteArr, globalIndexOfCurrentGridSourceToSend[idx]);
483     if (iteArr != itArr)
484     {
485       int index = std::distance(itbArr, itArr);
486       sendBuff[idx+currentBuffPosition] = (*globalIndexOfOriginalGridSource_)(index);
487     }
488   }
489   currentSendBuff = sendBuff + currentBuffPosition;
490   MPI_Send(currentSendBuff, countSize, MPI_UNSIGNED_LONG, destRank, 14, client->intraComm);
491   currentBuffPosition += countSize;
492 }
493
494 // Receiving global index of grid source sending from current grid source
495 std::map<int,std::vector<std::vector<std::pair<size_t,double> > > >::const_iterator itbRecv = globalIndexToReceive.begin(), itRecv,
496                                                                                     iteRecv = globalIndexToReceive.end();
497 int recvBuffSize = 0;
498 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv) recvBuffSize += (itRecv->second).size();
499
500 unsigned long* recvBuff, *currentRecvBuff;
501 if (0 != recvBuffSize) recvBuff = new unsigned long [recvBuffSize];
502 for (StdSize idx = 0; idx < recvBuffSize; ++idx) recvBuff[idx] = NumTraits<Scalar>::sfmax();
503
504 int currentRecvBuffPosition = 0;
505 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
506 {
507   MPI_Status status;
508   int srcRank = itRecv->first;
509   int countSize = (itRecv->second).size();
510   currentRecvBuff = recvBuff + currentRecvBuffPosition;
511   MPI_Recv(currentRecvBuff, countSize, MPI_UNSIGNED_LONG, srcRank, 14, client->intraComm, &status);
512   currentRecvBuffPosition += countSize;
513 }
514
515 int nbCurrentGridSource = 0;
516 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
517 {
518   int ssize = (itRecv->second).size();
519   for (int idx = 0; idx < ssize; ++idx)
520   {
521     nbCurrentGridSource += (itRecv->second)[idx].size();
522   }
523 }
524
525 if (globalIndexOfCurrentGridSource_->numElements()  != nbCurrentGridSource)
526 {
527   delete globalIndexOfCurrentGridSource_;
528   globalIndexOfCurrentGridSource_ = new CArray<size_t,1>(nbCurrentGridSource);
529   delete globalIndexOfOriginalGridSource_;
530   globalIndexOfOriginalGridSource_ = new CArray<size_t,1>(nbCurrentGridSource);
531   delete weightOfGlobalIndexOfOriginalGridSource_;
532   weightOfGlobalIndexOfOriginalGridSource_ = new CArray<double,1>(nbCurrentGridSource);
533 }
534
535 int k = 0;
536 currentRecvBuff = recvBuff;
537 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
538 {
539   int countSize = (itRecv->second).size();
540   for (int idx = 0; idx < countSize; ++idx, ++currentRecvBuff)
541   {
542     int ssize = (itRecv->second)[idx].size();
543     for (int i = 0; i < ssize; ++i)
544     {
545       (*globalIndexOfCurrentGridSource_)(k) = ((itRecv->second)[idx][i]).first;
546       (*weightOfGlobalIndexOfOriginalGridSource_)(k) = ((itRecv->second)[idx][i]).second;
547       (*globalIndexOfOriginalGridSource_)(k) = *currentRecvBuff;
548       ++k;
549     }
550   }
551 }
552
553 if (0 != sendBuffSize) delete [] sendBuff;
554 if (0 != recvBuffSize) delete [] recvBuff;
555}
556
557/*!
558  Compute transformation mapping between grid source and grid destination
559  The transformation between grid source and grid destination is represented in form of mapping between global index
560of two grids. Then local index mapping between data on each grid will be found out thanks to these global indexes
561*/
562void CGridTransformation::computeFinalTransformationMapping()
563{
564  CContext* context = CContext::getCurrent();
565  CContextClient* client=context->client;
566
567  CTransformationMapping transformationMap(gridDestination_, originalGridSource_);
568
569  std::map<size_t, std::vector<std::pair<size_t,double> > > globaIndexWeightFromDestToSource;
570  int nb = globalIndexOfCurrentGridSource_->numElements();
571  const size_t sfmax = NumTraits<unsigned long>::sfmax();
572  for (int idx = 0; idx < nb; ++idx)
573  {
574    if (sfmax != (*globalIndexOfOriginalGridSource_)(idx))
575      globaIndexWeightFromDestToSource[(*globalIndexOfCurrentGridSource_)(idx)].push_back(make_pair((*globalIndexOfOriginalGridSource_)(idx),(*weightOfGlobalIndexOfOriginalGridSource_)(idx))) ;
576  }
577
578  // Then compute transformation mapping among clients
579  transformationMap.computeTransformationMapping(globaIndexWeightFromDestToSource);
580
581  const std::map<int,std::vector<std::vector<std::pair<size_t,double> > > >& globalIndexToReceive = transformationMap.getGlobalIndexReceivedOnGridDestMapping();
582  const std::map<int,std::vector<size_t> >& globalIndexToSend = transformationMap.getGlobalIndexSendToGridDestMapping();
583
584  CDistributionClient distributionClientDest(client->clientRank, gridDestination_);
585  CDistributionClient distributionClientSrc(client->clientRank, originalGridSource_);
586
587  const CArray<int, 1>& localIndexOnClientDest = distributionClientDest.getLocalDataIndexSendToServer();
588  const CArray<size_t,1>& globalIndexOnClientDest = distributionClientDest.getGlobalDataIndexSendToServer();
589
590  const CArray<int, 1>& localIndexOnClientSrc = distributionClientSrc.getLocalDataIndexOnClient();
591  const CArray<size_t,1>& globalIndexOnClientSrc = distributionClientSrc.getGlobalDataIndexSendToServer();
592
593  std::vector<size_t>::const_iterator itbVec, itVec, iteVec;
594  CArray<size_t, 1>::const_iterator itbArr, itArr, iteArr;
595
596  std::map<int,std::vector<std::vector<std::pair<size_t,double> > > >::const_iterator itbMapRecv, itMapRecv, iteMapRecv;
597
598  // Find out local index on grid destination (received)
599  itbMapRecv = globalIndexToReceive.begin();
600  iteMapRecv = globalIndexToReceive.end();
601  itbArr = globalIndexOnClientDest.begin();
602  iteArr = globalIndexOnClientDest.end();
603  for (itMapRecv = itbMapRecv; itMapRecv != iteMapRecv; ++itMapRecv)
604  {
605    int sourceRank = itMapRecv->first;
606    int numGlobalIndex = (itMapRecv->second).size();
607    for (int i = 0; i < numGlobalIndex; ++i)
608    {
609      int vecSize = ((itMapRecv->second)[i]).size();
610      std::vector<std::pair<int,double> > tmpVec;
611      for (int idx = 0; idx < vecSize; ++idx)
612      {
613        size_t globalIndex = (itMapRecv->second)[i][idx].first;
614        double weight = (itMapRecv->second)[i][idx].second;
615        itArr = std::find(itbArr, iteArr, globalIndex);
616        if (iteArr != itArr)
617        {
618          int localIdx = std::distance(itbArr, itArr);
619          tmpVec.push_back(make_pair(localIdx, weight));
620        }
621      }
622      localIndexToReceiveOnGridDest_[sourceRank].push_back(tmpVec);
623    }
624  }
625
626  // Find out local index on grid source (to send)
627  std::map<int,std::vector<size_t> >::const_iterator itbMap, itMap, iteMap;
628  itbMap = globalIndexToSend.begin();
629  iteMap = globalIndexToSend.end();
630  itbArr = globalIndexOnClientSrc.begin();
631  iteArr = globalIndexOnClientSrc.end();
632  for (itMap = itbMap; itMap != iteMap; ++itMap)
633  {
634    CArray<int,1>* ptr = new CArray<int,1>((itMap->second).size());
635    localIndexToSendFromGridSource_[itMap->first] = ptr;
636    int destRank = itMap->first;
637    int vecSize = (itMap->second).size();
638    for (int idx = 0; idx < vecSize; ++idx)
639    {
640      itArr = std::find(itbArr, iteArr, (itMap->second)[idx]);
641      if (iteArr != itArr)
642      {
643        int localIdx = std::distance(itbArr, itArr);
644        (*localIndexToSendFromGridSource_[destRank])(idx) = (localIdx);
645      }
646    }
647  }
648}
649
650/*!
651  Local index of data which need sending from the grid source
652  \return local index of data
653*/
654const std::map<int, CArray<int,1>* >& CGridTransformation::getLocalIndexToSendFromGridSource() const
655{
656  return localIndexToSendFromGridSource_;
657}
658
659/*!
660  Local index of data which will be received on the grid destination
661  \return local index of data
662*/
663const std::map<int,std::vector<std::vector<std::pair<int,double> > > >& CGridTransformation::getLocalIndexToReceiveOnGridDest() const
664{
665  return localIndexToReceiveOnGridDest_;
666}
667
668}
Note: See TracBrowser for help on using the repository browser.