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

Last change on this file since 823 was 823, checked in by mhnguyen, 8 years ago

Implementing grid destination clone in case of two grid source

+) Clone attributes of grid destination as well as its transformation
+) Clean some redundant codes

Test
+) All tests pass

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