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

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

Implement direct transformation with domain_ref and axis_ref

+) Add a new case in which transformations among fields can be done via domain_ref and axis_ref (not only grid_ref)
+) Fix a minor bug relating to baseFieldReference

Test
+) On Curie
+) all standard tests (client, complete) pass
+) test_remap pass and the results are correct

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