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

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

Modifying the interface of interpolation domain

+) Change node name from interpolate_from_file_domain to interpolate_domain and add some new atrributes
+) Add more tests into test_remap

Test
+) On Curie
+) test_remap works for direct weight calculation and reading weight calculation from file

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