source: XIOS/dev/dev_olga/src/transformation/grid_transformation.cpp @ 1130

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

Correcting various bugs relating to transformation

+) Fix the order of transformation selection
+) Correct domain transformation selection
+) Reorganize test_remap

Test
+) On Curie
+) All tests pass

  • Property svn:executable set to *
File size: 28.9 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 "grid_transformation_factory_impl.hpp"
11#include "algo_types.hpp"
12#include "context.hpp"
13#include "context_client.hpp"
14#include "distribution_client.hpp"
15#include "mpi_tag.hpp"
16#include "grid.hpp"
17#include <boost/unordered_map.hpp>
18
19namespace xios {
20CGridTransformation::CGridTransformation(CGrid* destination, CGrid* source)
21 : CGridTransformationSelector(destination, source),
22  tmpGridDestination_(destination), originalGridSource_(source),
23  tempGridSrcs_(), tempGridDests_(),
24  dynamicalTransformation_(false), timeStamp_()
25{
26}
27
28CGridTransformation::~CGridTransformation()
29{
30}
31
32/*!
33  Select algorithm of a scalar corresponding to its transformation type and its position in each element
34  \param [in] elementPositionInGrid position of element in grid. e.g: a grid has 1 domain and 1 axis, then position of domain is 0 and position of axis is 1
35  \param [in] transType transformation type, for now we have
36  \param [in] transformationOrder position of the transformation in an element (an element can have several transformation)
37*/
38void CGridTransformation::selectScalarAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder)
39{
40  std::vector<CScalar*> scaListDestP = gridDestination_->getScalars();
41  int scalarDstIndex =  elementPositionInGridDst2ScalarPosition_[elementPositionInGrid];
42  CScalar::TransMapTypes trans = scaListDestP[scalarDstIndex]->getAllTransformations();
43  CScalar::TransMapTypes::const_iterator it = trans.begin();
44
45  for (int i = 0; i < transformationOrder; ++i, ++it) {}  // Find the correct transformation
46  CGenericAlgorithmTransformation* algo = 0;
47  algo = CGridTransformationFactory<CScalar>::createTransformation(transType,
48                                                                  gridDestination_,
49                                                                  gridSource_,
50                                                                  it->second,
51                                                                  elementPositionInGrid,
52                                                                  elementPositionInGridSrc2ScalarPosition_,
53                                                                  elementPositionInGridSrc2AxisPosition_,
54                                                                  elementPositionInGridSrc2DomainPosition_,
55                                                                  elementPositionInGridDst2ScalarPosition_,
56                                                                  elementPositionInGridDst2AxisPosition_,
57                                                                  elementPositionInGridDst2DomainPosition_);
58  algoTransformation_.push_back(algo);
59}
60
61/*!
62  Select algorithm of an axis corresponding to its transformation type and its position in each element
63  \param [in] elementPositionInGrid position of element in grid. e.g: a grid has 1 domain and 1 axis, then position of domain is 0 and position of axis is 1
64  \param [in] transType transformation type, for now we have zoom_axis, inverse_axis, interpolate_axis
65  \param [in] transformationOrder position of the transformation in an element (an element can have several transformation)
66*/
67void CGridTransformation::selectAxisAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder)
68{
69  std::vector<CAxis*> axisListDestP = gridDestination_->getAxis();
70  int axisDstIndex =  elementPositionInGridDst2AxisPosition_[elementPositionInGrid];
71  CAxis::TransMapTypes trans = axisListDestP[axisDstIndex]->getAllTransformations();
72  CAxis::TransMapTypes::const_iterator it = trans.begin();
73  for (int i = 0; i < transformationOrder; ++i, ++it) {}  // Find the correct transformation
74
75  CGenericAlgorithmTransformation* algo = 0;
76  algo = CGridTransformationFactory<CAxis>::createTransformation(transType,
77                                                                 gridDestination_,
78                                                                 gridSource_,
79                                                                 it->second,
80                                                                 elementPositionInGrid,
81                                                                 elementPositionInGridSrc2ScalarPosition_,
82                                                                 elementPositionInGridSrc2AxisPosition_,
83                                                                 elementPositionInGridSrc2DomainPosition_,
84                                                                 elementPositionInGridDst2ScalarPosition_,
85                                                                 elementPositionInGridDst2AxisPosition_,
86                                                                 elementPositionInGridDst2DomainPosition_);
87  algoTransformation_.push_back(algo);
88}
89
90/*!
91  Select algorithm of a domain corresponding to its transformation type and its position in each element
92  \param [in] elementPositionInGrid position of element in grid. e.g: a grid has 1 domain and 1 axis, then position of domain is 0 and position of axis is 1
93  \param [in] transType transformation type, for now we have zoom_domain, interpolate_domain
94  \param [in] transformationOrder position of the transformation in an element (an element can have several transformation)
95*/
96void CGridTransformation::selectDomainAlgo(int elementPositionInGrid, ETranformationType transType, int transformationOrder)
97{
98  std::vector<CDomain*> domainListDestP = gridDestination_->getDomains();
99  int domainIndex =  elementPositionInGridDst2DomainPosition_[elementPositionInGrid];
100  CDomain::TransMapTypes trans = domainListDestP[domainIndex]->getAllTransformations();
101  CDomain::TransMapTypes::const_iterator it = trans.begin();
102  for (int i = 0; i < transformationOrder; ++i, ++it) {}  // Find the correct transformation 
103
104  CGenericAlgorithmTransformation* algo = 0;
105  algo = CGridTransformationFactory<CDomain>::createTransformation(transType,
106                                                                   gridDestination_,
107                                                                   gridSource_,
108                                                                   it->second,
109                                                                   elementPositionInGrid,
110                                                                   elementPositionInGridSrc2ScalarPosition_,
111                                                                   elementPositionInGridSrc2AxisPosition_,
112                                                                   elementPositionInGridSrc2DomainPosition_,
113                                                                   elementPositionInGridDst2ScalarPosition_,
114                                                                   elementPositionInGridDst2AxisPosition_,
115                                                                   elementPositionInGridDst2DomainPosition_);
116  algoTransformation_.push_back(algo);
117}
118
119/*!
120  Find position of element in a grid as well as its type (domain, axis, scalar) and position in its own element list
121  \return element position: map<int,<int,int> > corresponds to <element position in grid, <element type, element position in element list> >
122*/
123std::map<int,std::pair<int,int> > CGridTransformation::getElementPosition(CGrid* grid)
124{
125  std::vector<CScalar*> scalarListP = grid->getScalars(); 
126  std::vector<CAxis*> axisListP = grid->getAxis();
127  std::vector<CDomain*> domListP = grid->getDomains(); 
128  CArray<int,1> axisDomainOrder = grid->axis_domain_order;
129  int scalarIndex = 0, axisIndex = 0, domainIndex = 0;
130  int nbElement = axisDomainOrder.numElements(), elementDim;
131  std::map<int,std::pair<int,int> > elementPosition;
132  for (int idx = 0; idx < nbElement; ++idx)
133  {
134    elementDim = axisDomainOrder(idx);
135    switch (elementDim)
136    {
137      case 2:
138        elementPosition[idx] = std::make_pair(elementDim, domainIndex);
139        ++domainIndex;
140        break;
141      case 1:
142        elementPosition[idx] = std::make_pair(elementDim, axisIndex);
143        ++axisIndex;
144        break;
145      case 0:
146        elementPosition[idx] = std::make_pair(elementDim, scalarIndex);
147        ++scalarIndex;
148        break;
149      default:
150        break;       
151    }
152  }
153
154  return elementPosition; 
155}
156
157/*!
158  If there are more than one transformation, a new temporary grid will be created and it will play the role of grid destination.
159This new created one keeps a pointer to the real transformed element of grid destination and generate new copies of other elements from grid source.
160  \param [in] elementPositionInGrid position of element in grid
161  \param [in] transType transformation type
162*/
163void CGridTransformation::setUpGridDestination(int elementPositionInGrid, ETranformationType transType)
164{
165  if (isSpecialTransformation(transType)) return;
166
167  if (!tempGridDests_.empty() && (getNbAlgo() == tempGridDests_.size()))
168  {
169    tempGridDests_.resize(0);
170  }
171
172  if (1 == getNbAlgo()) 
173  {
174    tmpGridDestination_ = gridDestination_;
175    return;
176  }
177
178  std::vector<CScalar*> scalarListDestP = gridDestination_->getScalars();
179  std::vector<CScalar*> scalarListSrcP = gridSource_->getScalars(), scalarDst;
180
181  std::vector<CAxis*> axisListDestP = gridDestination_->getAxis();
182  std::vector<CAxis*> axisListSrcP = gridSource_->getAxis(), axisDst;
183
184  std::vector<CDomain*> domListDestP = gridDestination_->getDomains();
185  std::vector<CDomain*> domListSrcP = gridSource_->getDomains(), domainDst;
186
187  CArray<int,1> axisDomainOrderSrc = gridSource_->axis_domain_order;
188  CArray<int,1> axisDomainOrderDst = gridDestination_->axis_domain_order;
189
190  std::map<int,std::pair<int,int> > elementPositionSrc = getElementPosition(gridSource_);
191  std::map<int,std::pair<int,int> > elementPositionDst = getElementPosition(gridDestination_);
192
193  CArray<int,1> elementOrder(axisDomainOrderDst.numElements());
194  for (int idx = 0; idx < axisDomainOrderDst.numElements(); ++idx)
195  {
196    if (elementPositionInGrid == idx)
197    {
198      int dimElementDst = elementPositionDst[idx].first;
199      int elementIndex  = elementPositionDst[idx].second;
200      switch (dimElementDst) 
201      {
202        case 2:
203          domainDst.push_back(domListDestP[elementIndex]);
204          break;
205        case 1:
206          axisDst.push_back(axisListDestP[elementIndex]);
207          break;
208        case 0:
209          scalarDst.push_back(scalarListDestP[elementIndex]);
210          break;
211        default:
212          break;
213      }
214      elementOrder(idx) = dimElementDst;
215    }
216    else
217    {     
218      int dimElementSrc = elementPositionSrc[idx].first;
219      int elementIndex  = elementPositionSrc[idx].second;
220      switch (dimElementSrc)
221      {
222        case 2:
223          domainDst.push_back(domListSrcP[elementIndex]);
224          break;
225        case 1:
226          axisDst.push_back(axisListSrcP[elementIndex]);
227          break;
228        case 0:
229          scalarDst.push_back(scalarListSrcP[elementIndex]);
230          break;
231        default:
232          break;
233      }
234      elementOrder(idx) = dimElementSrc;
235    }
236  }
237
238  tmpGridDestination_ = CGrid::createGrid(domainDst, axisDst, scalarDst, elementOrder);
239  tmpGridDestination_->computeGridGlobalDimension(domainDst, axisDst, scalarDst, elementOrder);
240  tempGridDests_.push_back(tmpGridDestination_);
241}
242
243/*!
244  Assign the current grid destination to the grid source in the new transformation.
245The current grid destination plays the role of grid source in next transformation (if any).
246Only element on which the transformation is performed is modified
247  \param [in] elementPositionInGrid position of element in grid
248  \param [in] transType transformation type
249*/
250void CGridTransformation::setUpGridSource(int elementPositionInGrid)
251{
252  if (!tempGridSrcs_.empty() && (getNbAlgo()-1) == tempGridSrcs_.size())
253  {
254    tempGridSrcs_.resize(0);
255  }
256
257  std::vector<CScalar*> scalarListDestP = tmpGridDestination_->getScalars();
258  std::vector<CScalar*> scalarListSrcP = gridSource_->getScalars(), scalarSrc;
259
260  std::vector<CAxis*> axisListDestP = tmpGridDestination_->getAxis();
261  std::vector<CAxis*> axisListSrcP = gridSource_->getAxis(), axisSrc;
262
263  std::vector<CDomain*> domListDestP = tmpGridDestination_->getDomains();
264  std::vector<CDomain*> domListSrcP = gridSource_->getDomains(), domainSrc;
265
266  CArray<int,1> axisDomainOrderSrc = gridSource_->axis_domain_order;
267  CArray<int,1> axisDomainOrderDst = tmpGridDestination_->axis_domain_order;
268
269  std::map<int,std::pair<int,int> > elementPositionSrc = getElementPosition(gridSource_);
270  std::map<int,std::pair<int,int> > elementPositionDst = getElementPosition(tmpGridDestination_);
271
272  for (int idx = 0; idx < axisDomainOrderDst.numElements(); ++idx)
273  {   
274    if (elementPositionInGrid == idx)
275    {
276      int dimElementDst = elementPositionDst[idx].first;
277      int elementIndex  = elementPositionDst[idx].second;
278      if (2 == dimElementDst)
279      {
280        CDomain* domain = CDomain::createDomain();
281        domain->domain_ref.setValue(domListDestP[elementIndex]->getId());
282        domain->solveRefInheritance(true);
283        domain->checkAttributesOnClient();
284        domainSrc.push_back(domain);
285      }
286      else if (1 == dimElementDst)
287      {
288        CAxis* axis = CAxis::createAxis();
289        axis->axis_ref.setValue(axisListDestP[elementIndex]->getId());
290        axis->solveRefInheritance(true);
291        axis->checkAttributesOnClient();
292        axisSrc.push_back(axis); 
293      }
294      else
295      {
296        CScalar* scalar = CScalar::createScalar();
297        scalar->scalar_ref.setValue(scalarListDestP[elementIndex]->getId());
298        scalar->solveRefInheritance(true);
299        scalar->checkAttributesOnClient();
300        scalarSrc.push_back(scalar);
301      }
302    }
303    else
304    {     
305      int dimElementDst = elementPositionDst[idx].first;
306      int elementIndex  = elementPositionDst[idx].second;
307      switch (dimElementDst)
308      {
309        case 2:
310          domainSrc.push_back(domListDestP[elementIndex]);
311          break;
312        case 1:
313          axisSrc.push_back(axisListDestP[elementIndex]);
314          break;
315        case 0:
316          scalarSrc.push_back(scalarListDestP[elementIndex]);
317          break;
318        default:
319          break;
320      }
321    }
322  }
323
324  gridSource_ = CGrid::createGrid(domainSrc, axisSrc, scalarSrc, tmpGridDestination_->axis_domain_order);
325  gridSource_->computeGridGlobalDimension(domainSrc, axisSrc, scalarSrc, tmpGridDestination_->axis_domain_order);
326
327  tempGridSrcs_.push_back(gridSource_);
328}
329
330/*!
331  Perform all transformations
332  For each transformation, there are some things to do:
333  -) Chose the correct algorithm by transformation type and position of element
334  -) Calculate the mapping of global index between the current grid source and grid destination
335  -) Calculate the mapping of global index between current grid DESTINATION and grid SOURCE
336  -) Make current grid destination become grid source in the next transformation
337*/
338void CGridTransformation::computeAll(const std::vector<CArray<double,1>* >& dataAuxInputs, Time timeStamp)
339{
340  if (nbNormalAlgos_ < 1) return;
341  if (!auxInputs_.empty() && !dynamicalTransformation_) { dynamicalTransformation_ = true; return; }
342  if (dynamicalTransformation_)
343  {
344    if (timeStamp_.insert(timeStamp).second)   //Reset map
345    {
346      std::list<SendingIndexGridSourceMap>().swap(localIndexToSendFromGridSource_);
347      std::list<RecvIndexGridDestinationMap>().swap(localIndexToReceiveOnGridDest_);
348      std::list<size_t>().swap(nbLocalIndexOnGridDest_);
349      std::list<std::vector<bool> >().swap(localMaskOnGridDest_);
350    }
351    else
352      return;
353  }
354
355  CContext* context = CContext::getCurrent();
356  CContextClient* client = context->client;
357
358  ListAlgoType::const_iterator itb = listAlgos_.begin(),
359                               ite = listAlgos_.end(), it;
360
361  CGenericAlgorithmTransformation* algo = 0;
362  int nbAgloTransformation = 0; // Only count for executed transformation. Generate domain is a special one, not executed in the list
363  for (it = itb; it != ite; ++it)
364  {
365    int elementPositionInGrid = it->first;
366    ETranformationType transType = (it->second).first;
367    int transformationOrder = (it->second).second.first;
368    int algoType = ((it->second).second.second); //algoTypes_[std::distance(itb, it)];
369    SourceDestinationIndexMap globaIndexWeightFromSrcToDst;
370   
371
372    // Create a temporary grid destination which contains transformed element of grid destination and
373    // non-transformed elements to grid source
374    setUpGridDestination(elementPositionInGrid, transType);
375
376    // First of all, select an algorithm
377    if (!dynamicalTransformation_ || (algoTransformation_.size() < listAlgos_.size()))
378    {
379      selectAlgo(elementPositionInGrid, transType, transformationOrder, algoType);
380      algo = algoTransformation_.back();
381    }
382    else
383      algo = algoTransformation_[std::distance(itb, it)];
384
385    if ((0 != algo) &&
386        ((CGenericAlgorithmTransformation::ELEMENT_NO_MODIFICATION_WITH_DATA == algo->type()) ||
387        (CGenericAlgorithmTransformation::ELEMENT_MODIFICATION_WITH_DATA == algo->type()))) // Only registered transformation can be executed
388    {
389      algo->computeIndexSourceMapping(dataAuxInputs);
390
391      // ComputeTransformation of global index of each element
392      int elementPosition = it->first;
393      algo->computeGlobalSourceIndex(elementPosition,
394                                     gridSource_,
395                                     tmpGridDestination_,
396                                     globaIndexWeightFromSrcToDst);
397
398      // Compute transformation of global indexes among grids
399      computeTransformationMapping(globaIndexWeightFromSrcToDst);
400
401      if (1 < nbNormalAlgos_)
402      {
403        // Now grid destination becomes grid source in a new transformation
404        if (nbAgloTransformation != (nbNormalAlgos_-1)) setUpGridSource(elementPositionInGrid);
405      }
406      ++nbAgloTransformation;
407    }
408  }
409}
410
411/*!
412  Compute exchange index between grid source and grid destination
413  \param [in] globalIndexWeightFromDestToSource global index mapping between grid destination and grid source
414*/
415void CGridTransformation::computeTransformationMapping(const SourceDestinationIndexMap& globaIndexWeightFromSrcToDst)
416{
417  CContext* context = CContext::getCurrent();
418  CContextClient* client = context->client;
419  int nbClient = client->clientSize;
420  int clientRank = client->clientRank;
421
422  // Recalculate the distribution of grid destination
423  CDistributionClient distributionClientDest(client->clientRank, tmpGridDestination_);
424  CDistributionClient::GlobalLocalDataMap& globalLocalIndexGridDestSendToServer = distributionClientDest.getGlobalLocalDataSendToServer();
425
426  // Update number of local index on each transformation
427  size_t nbLocalIndex = globalLocalIndexGridDestSendToServer.size();
428  nbLocalIndexOnGridDest_.push_back(nbLocalIndex);
429  localMaskOnGridDest_.push_back(std::vector<bool>());
430  std::vector<bool>& tmpMask = localMaskOnGridDest_.back();
431  tmpMask.resize(nbLocalIndex,false);
432
433  // Find out number of index sent from grid source and number of index received on grid destination
434  SourceDestinationIndexMap::const_iterator itbIndex = globaIndexWeightFromSrcToDst.begin(),
435                                            iteIndex = globaIndexWeightFromSrcToDst.end(), itIndex;
436  typedef boost::unordered_map<size_t, std::vector<std::pair<size_t,double> > > SendIndexMap;
437  std::map<int,int> sendRankSizeMap,recvRankSizeMap;
438  int connectedClient = globaIndexWeightFromSrcToDst.size();
439  int* recvCount=new int[nbClient];
440  int* displ=new int[nbClient];
441  int* sendRankBuff=new int[connectedClient];
442  int* sendSizeBuff=new int[connectedClient];
443  int n = 0;
444  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex, ++n)
445  {
446    sendRankBuff[n] = itIndex->first;
447    const SendIndexMap& sendIndexMap = itIndex->second;
448    SendIndexMap::const_iterator itbSend = sendIndexMap.begin(), iteSend = sendIndexMap.end(), itSend;
449    int sendSize = 0;
450    for (itSend = itbSend; itSend != iteSend; ++itSend)
451    {
452      sendSize += itSend->second.size();
453    }
454    sendSizeBuff[n] = sendSize;
455    sendRankSizeMap[itIndex->first] = sendSize;
456  }
457  MPI_Allgather(&connectedClient,1,MPI_INT,recvCount,1,MPI_INT,client->intraComm);
458
459  displ[0]=0 ;
460  for(int n=1;n<nbClient;n++) displ[n]=displ[n-1]+recvCount[n-1];
461  int recvSize=displ[nbClient-1]+recvCount[nbClient-1];
462  int* recvRankBuff=new int[recvSize];
463  int* recvSizeBuff=new int[recvSize];
464  MPI_Allgatherv(sendRankBuff,connectedClient,MPI_INT,recvRankBuff,recvCount,displ,MPI_INT,client->intraComm);
465  MPI_Allgatherv(sendSizeBuff,connectedClient,MPI_INT,recvSizeBuff,recvCount,displ,MPI_INT,client->intraComm);
466  for (int i = 0; i < nbClient; ++i)
467  {
468    int currentPos = displ[i];
469    for (int j = 0; j < recvCount[i]; ++j)
470      if (recvRankBuff[currentPos+j] == clientRank)
471      {
472        recvRankSizeMap[i] = recvSizeBuff[currentPos+j];
473      }
474  }
475
476  // Sending global index of grid source to corresponding process as well as the corresponding mask
477  std::vector<MPI_Request> requests;
478  std::vector<MPI_Status> status;
479  boost::unordered_map<int, unsigned char* > recvMaskDst;
480  boost::unordered_map<int, unsigned long* > recvGlobalIndexSrc;
481  for (std::map<int,int>::const_iterator itRecv = recvRankSizeMap.begin(); itRecv != recvRankSizeMap.end(); ++itRecv)
482  {
483    int recvRank = itRecv->first;
484    int recvSize = itRecv->second;
485    recvMaskDst[recvRank] = new unsigned char [recvSize];
486    recvGlobalIndexSrc[recvRank] = new unsigned long [recvSize];
487
488    requests.push_back(MPI_Request());
489    MPI_Irecv(recvGlobalIndexSrc[recvRank], recvSize, MPI_UNSIGNED_LONG, recvRank, 46, client->intraComm, &requests.back());
490    requests.push_back(MPI_Request());
491    MPI_Irecv(recvMaskDst[recvRank], recvSize, MPI_UNSIGNED_CHAR, recvRank, 47, client->intraComm, &requests.back());
492  }
493
494  boost::unordered_map<int, CArray<size_t,1> > globalIndexDst;
495  boost::unordered_map<int, CArray<double,1> > weightDst;
496  boost::unordered_map<int, unsigned char* > sendMaskDst;
497  boost::unordered_map<int, unsigned long* > sendGlobalIndexSrc;
498  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex)
499  {
500    int sendRank = itIndex->first;
501    int sendSize = sendRankSizeMap[sendRank];
502    const SendIndexMap& sendIndexMap = itIndex->second;
503    SendIndexMap::const_iterator itbSend = sendIndexMap.begin(), iteSend = sendIndexMap.end(), itSend;
504    globalIndexDst[sendRank].resize(sendSize);
505    weightDst[sendRank].resize(sendSize);
506    sendMaskDst[sendRank] = new unsigned char [sendSize];
507    sendGlobalIndexSrc[sendRank] = new unsigned long [sendSize];
508    int countIndex = 0;
509    for (itSend = itbSend; itSend != iteSend; ++itSend)
510    {
511      const std::vector<std::pair<size_t,double> >& dstWeight = itSend->second;
512      for (int idx = 0; idx < dstWeight.size(); ++idx)
513      {
514        globalIndexDst[sendRank](countIndex) = dstWeight[idx].first;
515        weightDst[sendRank](countIndex) = dstWeight[idx].second;
516        if (0 < globalLocalIndexGridDestSendToServer.count(dstWeight[idx].first))
517          sendMaskDst[sendRank][countIndex] = 1;
518        else
519          sendMaskDst[sendRank][countIndex] = 0;
520        sendGlobalIndexSrc[sendRank][countIndex] = itSend->first;
521        ++countIndex;
522      }
523    }
524
525    // Send global index source and mask
526    requests.push_back(MPI_Request());
527    MPI_Isend(sendGlobalIndexSrc[sendRank], sendSize, MPI_UNSIGNED_LONG, sendRank, 46, client->intraComm, &requests.back());
528    requests.push_back(MPI_Request());
529    MPI_Isend(sendMaskDst[sendRank], sendSize, MPI_UNSIGNED_CHAR, sendRank, 47, client->intraComm, &requests.back());
530  }
531
532  status.resize(requests.size());
533  MPI_Waitall(requests.size(), &requests[0], &status[0]);
534
535  // Okie, now use the mask to identify which index source we need to send, then also signal the destination which masked index we will return
536  std::vector<MPI_Request>().swap(requests);
537  std::vector<MPI_Status>().swap(status);
538  // Okie, on destination side, we will wait for information of masked index of source
539  for (std::map<int,int>::const_iterator itSend = sendRankSizeMap.begin(); itSend != sendRankSizeMap.end(); ++itSend)
540  {
541    int recvRank = itSend->first;
542    int recvSize = itSend->second;
543
544    requests.push_back(MPI_Request());
545    MPI_Irecv(sendMaskDst[recvRank], recvSize, MPI_UNSIGNED_CHAR, recvRank, 48, client->intraComm, &requests.back());
546  }
547
548  // Ok, now we fill in local index of grid source (we even count for masked index)
549  CDistributionClient distributionClientSrc(client->clientRank, gridSource_);
550  CDistributionClient::GlobalLocalDataMap& globalLocalIndexGridSrcSendToServer = distributionClientSrc.getGlobalLocalDataSendToServer();
551  localIndexToSendFromGridSource_.push_back(SendingIndexGridSourceMap());
552  SendingIndexGridSourceMap& tmpSend = localIndexToSendFromGridSource_.back();
553  for (std::map<int,int>::const_iterator itRecv = recvRankSizeMap.begin(); itRecv != recvRankSizeMap.end(); ++itRecv)
554  {
555    int recvRank = itRecv->first;
556    int recvSize = itRecv->second;
557    unsigned char* recvMask = recvMaskDst[recvRank];
558    unsigned long* recvIndexSrc = recvGlobalIndexSrc[recvRank];
559    int realSendSize = 0;
560    for (int idx = 0; idx < recvSize; ++idx)
561    {
562      if (0 != (*(recvMask+idx))) // OKie, now we have a demand from non-masked index destination
563        if (0 < globalLocalIndexGridSrcSendToServer.count(*(recvIndexSrc+idx))) // check whether index source is masked
564         ++realSendSize;
565        else // inform the destination that this index is masked
566         *(recvMask+idx) = 0;
567    }
568
569    tmpSend[recvRank].resize(realSendSize);
570    realSendSize = 0;
571    for (int idx = 0; idx < recvSize; ++idx)
572    {
573      if (0 != (*(recvMask+idx))) // OKie, now we have a demand from non-masked index destination
574      {
575        tmpSend[recvRank](realSendSize) = globalLocalIndexGridSrcSendToServer[*(recvIndexSrc+idx)];
576         ++realSendSize;
577      }
578    }
579
580    // Okie, now inform the destination which source index are masked
581    requests.push_back(MPI_Request());
582    MPI_Isend(recvMaskDst[recvRank], recvSize, MPI_UNSIGNED_CHAR, recvRank, 48, client->intraComm, &requests.back());
583  }
584  status.resize(requests.size());
585  MPI_Waitall(requests.size(), &requests[0], &status[0]);
586
587  // Cool, now we can fill in local index of grid destination (counted for masked index)
588  localIndexToReceiveOnGridDest_.push_back(RecvIndexGridDestinationMap());
589  RecvIndexGridDestinationMap& recvTmp = localIndexToReceiveOnGridDest_.back();
590  for (std::map<int,int>::const_iterator itSend = sendRankSizeMap.begin(); itSend != sendRankSizeMap.end(); ++itSend)
591  {
592    int recvRank = itSend->first;
593    int recvSize = itSend->second;
594    unsigned char* recvMask = sendMaskDst[recvRank];
595
596    CArray<size_t,1>& recvIndexDst = globalIndexDst[recvRank];
597    CArray<double,1>& recvWeightDst = weightDst[recvRank];
598    int realRecvSize = 0;
599    for (int idx = 0; idx < recvSize; ++idx)
600    {
601      if (0 != *(recvMask+idx)) // OKie, now we have a non-masked index destination
602         ++realRecvSize;
603    }
604
605    int localIndexDst;
606    recvTmp[recvRank].resize(realRecvSize);
607    realRecvSize = 0;
608    for (int idx = 0; idx < recvSize; ++idx)
609    {
610      if (0 != *(recvMask+idx)) // OKie, now we have a demand from non-masked index destination
611      {
612        recvTmp[recvRank][realRecvSize].first = globalLocalIndexGridDestSendToServer[recvIndexDst(idx)];
613        recvTmp[recvRank][realRecvSize].second = recvWeightDst(idx);
614        tmpMask[globalLocalIndexGridDestSendToServer[recvIndexDst(idx)]] = true;
615         ++realRecvSize;
616      }
617    }
618  }
619
620  delete [] recvCount;
621  delete [] displ;
622  delete [] sendRankBuff;
623  delete [] recvRankBuff;
624  delete [] sendSizeBuff;
625  delete [] recvSizeBuff;
626
627  boost::unordered_map<int, unsigned char* >::const_iterator itChar;
628  for (itChar = sendMaskDst.begin(); itChar != sendMaskDst.end(); ++itChar)
629    delete [] itChar->second;
630  for (itChar = recvMaskDst.begin(); itChar != recvMaskDst.end(); ++itChar)
631    delete [] itChar->second;
632  boost::unordered_map<int, unsigned long* >::const_iterator itLong;
633  for (itLong = sendGlobalIndexSrc.begin(); itLong != sendGlobalIndexSrc.end(); ++itLong)
634    delete [] itLong->second;
635  for (itLong = recvGlobalIndexSrc.begin(); itLong != recvGlobalIndexSrc.end(); ++itLong)
636    delete [] itLong->second;
637
638}
639
640/*!
641  Local index of data which need sending from the grid source
642  \return local index of data
643*/
644const std::list<CGridTransformation::SendingIndexGridSourceMap>& CGridTransformation::getLocalIndexToSendFromGridSource() const
645{
646  return localIndexToSendFromGridSource_;
647}
648
649/*!
650  Local index of data which will be received on the grid destination
651  \return local index of data
652*/
653const std::list<CGridTransformation::RecvIndexGridDestinationMap>& CGridTransformation::getLocalIndexToReceiveOnGridDest() const
654{
655  return localIndexToReceiveOnGridDest_;
656}
657
658/*!
659 Number of index will be received on the grid destination
660  \return number of index of data
661*/
662const std::list<size_t>& CGridTransformation::getNbLocalIndexToReceiveOnGridDest() const
663{
664  return nbLocalIndexOnGridDest_;
665}
666
667/*!
668  Local mask of data which will be received on the grid destination
669  \return local mask of data
670*/
671const std::list<std::vector<bool> >& CGridTransformation::getLocalMaskIndexOnGridDest() const
672{
673  return localMaskOnGridDest_;
674}
675
676}
Note: See TracBrowser for help on using the repository browser.