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

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

Integrating remap library into XIOS

+) Change name of some files of remap library to be compatible with XIOS
+) Implement function to fill in automatically boundary longitude and latitude

Test
+) On Curie
+) test_remap correct

File size: 28.3 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_from_file.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  CInterpolateFromFileDomain* interpFileDomain = 0;
279  CGenericAlgorithmTransformation* algo = 0;
280  switch (transType)
281  {
282    case TRANS_INTERPOLATE_DOMAIN_FROM_FILE:
283      interpFileDomain = dynamic_cast<CInterpolateFromFileDomain*> (it->second);
284      algo = new CDomainAlgorithmInterpolateFromFile(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_FROM_FILE:
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//       int index = std::distance(itbArr, itArr);
497       sendBuff[idx+currentBuffPosition] = globalIndexOfOriginalGridSource_[*itIndex]; //[index];
498     }
499   }
500   currentSendBuff = sendBuff + currentBuffPosition;
501   MPI_Isend(currentSendBuff, countSize, MPI_UNSIGNED_LONG, destRank, 14, client->intraComm, &requests[destRank]);
502   currentBuffPosition += countSize;
503 }
504
505 // Receiving global index of grid source sending from current grid source
506 std::map<int,std::vector<std::vector<std::pair<size_t,double> > > >::const_iterator itbRecv = globalIndexToReceive.begin(), itRecv,
507                                                                                     iteRecv = globalIndexToReceive.end();
508 int recvBuffSize = 0;
509 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv) recvBuffSize += (itRecv->second).size();
510
511 unsigned long* recvBuff, *currentRecvBuff;
512 if (0 != recvBuffSize) recvBuff = new unsigned long [recvBuffSize];
513 for (StdSize idx = 0; idx < recvBuffSize; ++idx) recvBuff[idx] = NumTraits<Scalar>::sfmax();
514
515 int currentRecvBuffPosition = 0;
516 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
517 {
518   MPI_Status status;
519   int srcRank = itRecv->first;
520   int countSize = (itRecv->second).size();
521   currentRecvBuff = recvBuff + currentRecvBuffPosition;
522   MPI_Recv(currentRecvBuff, countSize, MPI_UNSIGNED_LONG, srcRank, 14, client->intraComm, &status);
523   currentRecvBuffPosition += countSize;
524 }
525
526 int nbCurrentGridSource = 0;
527 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
528 {
529   int ssize = (itRecv->second).size();
530   for (int idx = 0; idx < ssize; ++idx)
531   {
532     nbCurrentGridSource += (itRecv->second)[idx].size();
533   }
534 }
535
536 if (globalIndexOfCurrentGridSource_.size() != nbCurrentGridSource)
537 {
538   globalIndexOfCurrentGridSource_.resize(nbCurrentGridSource);
539   globalIndexOfOriginalGridSource_.resize(nbCurrentGridSource);
540   weightOfGlobalIndexOfOriginalGridSource_.resize(nbCurrentGridSource);
541 }
542
543 int k = 0;
544 currentRecvBuff = recvBuff;
545 for (itRecv = itbRecv; itRecv != iteRecv; ++itRecv)
546 {
547   int countSize = (itRecv->second).size();
548   for (int idx = 0; idx < countSize; ++idx, ++currentRecvBuff)
549   {
550     int ssize = (itRecv->second)[idx].size();
551     for (int i = 0; i < ssize; ++i)
552     {
553       globalIndexOfCurrentGridSource_[k] = ((itRecv->second)[idx][i]).first;
554       weightOfGlobalIndexOfOriginalGridSource_(k) = ((itRecv->second)[idx][i]).second;
555       globalIndexOfOriginalGridSource_[k] = *currentRecvBuff;
556       ++k;
557     }
558   }
559 }
560
561 std::map<int, MPI_Request>::iterator itRequest;
562 for (itRequest = requests.begin(); itRequest != requests.end(); ++itRequest)
563   MPI_Wait(&itRequest->second, MPI_STATUS_IGNORE);
564
565 if (0 != sendBuffSize) delete [] sendBuff;
566 if (0 != recvBuffSize) delete [] recvBuff;
567}
568
569/*!
570  Compute transformation mapping between grid source and grid destination
571  The transformation between grid source and grid destination is represented in form of mapping between global index
572of two grids. Then local index mapping between data on each grid will be found out thanks to these global indexes
573*/
574void CGridTransformation::computeFinalTransformationMapping()
575{
576  CContext* context = CContext::getCurrent();
577  CContextClient* client = context->client;
578
579  CTransformationMapping transformationMap(gridDestination_, originalGridSource_);
580
581  std::map<size_t, std::vector<std::pair<size_t,double> > > globaIndexWeightFromDestToSource;
582  int nb = globalIndexOfCurrentGridSource_.size();
583  const size_t sfmax = NumTraits<unsigned long>::sfmax();
584  for (int idx = 0; idx < nb; ++idx)
585  {
586    if (sfmax != globalIndexOfOriginalGridSource_[idx])
587      globaIndexWeightFromDestToSource[globalIndexOfCurrentGridSource_[idx]].push_back(make_pair(globalIndexOfOriginalGridSource_[idx], weightOfGlobalIndexOfOriginalGridSource_(idx))) ;
588  }
589
590  // Then compute transformation mapping among clients
591  transformationMap.computeTransformationMapping(globaIndexWeightFromDestToSource);
592
593  const std::map<int,std::vector<std::vector<std::pair<size_t,double> > > >& globalIndexToReceive = transformationMap.getGlobalIndexReceivedOnGridDestMapping();
594  const std::map<int,std::vector<size_t> >& globalIndexToSend = transformationMap.getGlobalIndexSendToGridDestMapping();
595
596  CDistributionClient distributionClientDest(client->clientRank, gridDestination_);
597  CDistributionClient distributionClientSrc(client->clientRank, originalGridSource_);
598
599  const std::vector<size_t>& globalIndexOnClientDest = distributionClientDest.getGlobalDataIndexSendToServer();
600  const std::vector<size_t>& globalIndexOnClientSrc = distributionClientSrc.getGlobalDataIndexSendToServer();
601
602  std::vector<size_t>::const_iterator itbArr, itArr, iteArr;
603  std::vector<int>::const_iterator itIndex, itbIndex, iteIndex;
604  std::map<int,std::vector<std::vector<std::pair<size_t,double> > > >::const_iterator itbMapRecv, itMapRecv, iteMapRecv;
605
606  std::vector<int> permutIndex;
607  typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
608
609  // Find out local index on grid destination (received)
610  XIOSAlgorithms::fillInIndex(globalIndexOnClientDest.size(), permutIndex);
611  XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(globalIndexOnClientDest, permutIndex);
612  itbIndex = permutIndex.begin();
613  iteIndex = permutIndex.end();
614  BinarySearch searchClientDest(globalIndexOnClientDest);
615  itbMapRecv = globalIndexToReceive.begin();
616  iteMapRecv = globalIndexToReceive.end();
617  for (itMapRecv = itbMapRecv; itMapRecv != iteMapRecv; ++itMapRecv)
618  {
619    int sourceRank = itMapRecv->first;
620    int numGlobalIndex = (itMapRecv->second).size();
621    for (int i = 0; i < numGlobalIndex; ++i)
622    {
623      int vecSize = ((itMapRecv->second)[i]).size();
624      std::vector<std::pair<int,double> > tmpVec;
625      for (int idx = 0; idx < vecSize; ++idx)
626      {
627        size_t globalIndex = (itMapRecv->second)[i][idx].first;
628        double weight = (itMapRecv->second)[i][idx].second;
629        if (searchClientDest.search(itbIndex, iteIndex, globalIndex, itIndex))
630        {
631          tmpVec.push_back(make_pair(*itIndex, weight));
632        }
633      }
634      localIndexToReceiveOnGridDest_[sourceRank].push_back(tmpVec);
635    }
636  }
637
638  // Find out local index on grid source (to send)
639  std::map<int,std::vector<size_t> >::const_iterator itbMap, itMap, iteMap;
640  XIOSAlgorithms::fillInIndex(globalIndexOnClientSrc.size(), permutIndex);
641  XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(globalIndexOnClientSrc, permutIndex);
642  itbIndex = permutIndex.begin();
643  iteIndex = permutIndex.end();
644  BinarySearch searchClientSrc(globalIndexOnClientSrc);
645  itbMap = globalIndexToSend.begin();
646  iteMap = globalIndexToSend.end();
647  for (itMap = itbMap; itMap != iteMap; ++itMap)
648  {
649    int destRank = itMap->first;
650    int vecSize = itMap->second.size();
651    localIndexToSendFromGridSource_[destRank].resize(vecSize);
652    for (int idx = 0; idx < vecSize; ++idx)
653    {
654      if (searchClientSrc.search(itbIndex, iteIndex, itMap->second[idx], itIndex))
655      {
656        localIndexToSendFromGridSource_[destRank](idx) = *itIndex;
657      }
658    }
659  }
660}
661
662/*!
663  Local index of data which need sending from the grid source
664  \return local index of data
665*/
666const std::map<int, CArray<int,1> >& CGridTransformation::getLocalIndexToSendFromGridSource() const
667{
668  return localIndexToSendFromGridSource_;
669}
670
671/*!
672  Local index of data which will be received on the grid destination
673  \return local index of data
674*/
675const std::map<int,std::vector<std::vector<std::pair<int,double> > > >& CGridTransformation::getLocalIndexToReceiveOnGridDest() const
676{
677  return localIndexToReceiveOnGridDest_;
678}
679
680}
Note: See TracBrowser for help on using the repository browser.