source: XIOS/trunk/src/transformation/transformation_mapping.cpp @ 624

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

Final tests of zoom and inverse on axis

+) Modify test_client and test_complete to work with new grid definition
+) Correct some bugs causing memory leak
+) Clean abundant code
+) Add more comments to new files

Test
+) On Curie
+) test_client and test_complete pass with correct results

File size: 7.3 KB
Line 
1/*!
2   \file transformation_mapping.cpp
3   \author Ha NGUYEN
4   \since 14 May 2015
5   \date 18 June 2015
6
7   \brief Take charge of communication among clients to exchange transformed data.
8 */
9
10#include "transformation_mapping.hpp"
11#include <boost/unordered_map.hpp>
12#include "context.hpp"
13#include "context_client.hpp"
14#include "distribution_client.hpp"
15
16namespace xios {
17
18CTransformationMapping::CTransformationMapping(CGrid* destination, CGrid* source)
19  : gridSource_(source), gridDestination_(destination)
20{
21  CContext* context = CContext::getCurrent();
22  CContextClient* client=context->client;
23  int clientRank = client->clientRank;
24
25  CDistributionClient distributionClientSrc(client->clientRank, gridSource_);
26
27  const CArray<size_t,1>& globalIndexGridSrc = distributionClientSrc.getGlobalDataIndexSendToServer(); //gridSource_->getDistributionClient()->getGlobalDataIndexSendToServer();
28  boost::unordered_map<size_t,int> globalIndexOfServer;
29  int globalIndexSize = globalIndexGridSrc.numElements();
30  for (int idx = 0; idx < globalIndexSize; ++idx)
31  {
32    globalIndexOfServer[globalIndexGridSrc(idx)] = clientRank;
33  }
34
35  gridIndexClientClientMapping_ = new CClientServerMappingDistributed(globalIndexOfServer,
36                                                                      client->intraComm,
37                                                                      true);
38}
39
40CTransformationMapping::~CTransformationMapping()
41{
42  if (0 != gridIndexClientClientMapping_) delete gridIndexClientClientMapping_;
43}
44
45/*!
46  Suppose that we have transformations between two grids, which are represented in form of mapping between global indexes of these two grids,
47this function tries to find out which clients a client needs to send and receive these global indexes to accomplish the transformations.
48  The grid destination is the grid whose global indexes demande global indexes from the grid source
49  Grid destination and grid source are also distributed among clients but in different manners.
50  \param [in] globaIndexMapFromDestToSource mapping representing the transformations
51*/
52void CTransformationMapping::computeTransformationMapping(const std::map<size_t, std::set<size_t> >& globaIndexMapFromDestToSource)
53{
54  CContext* context = CContext::getCurrent();
55  CContextClient* client=context->client;
56
57  int numMappingPoints = 0;
58  std::map<size_t, std::set<size_t> >::const_iterator itbMap = globaIndexMapFromDestToSource.begin(), itMap,
59                                                      iteMap = globaIndexMapFromDestToSource.end();
60  for (itMap = itbMap; itMap != iteMap; ++itMap)
61  {
62    numMappingPoints += (itMap->second).size();
63  }
64
65  // All global indexes of a client on grid destination
66  CArray<size_t,1> globalIndexMap(numMappingPoints);
67  // Not only one index on grid destination can demande two indexes from grid source
68  // but an index on grid destination have to be sent to two indexes of grid destination
69  std::map<size_t, std::vector<size_t> > globalIndexMapFromSrcToDest;
70  std::set<size_t>::const_iterator itbSet, itSet, iteSet;
71  int idx = 0;
72  for (itMap = itbMap; itMap != iteMap; ++itMap)
73  {
74    itbSet = (itMap->second).begin();
75    iteSet = (itMap->second).end();
76    for (itSet = itbSet; itSet != iteSet; ++itSet)
77    {
78      globalIndexMap(idx) = *itSet;
79      globalIndexMapFromSrcToDest[*itSet].push_back(itMap->first);
80      ++idx;
81    }
82  }
83
84  // Find out on which clients the necessary indexes of grid source are.
85  gridIndexClientClientMapping_->computeServerIndexMapping(globalIndexMap);
86  const std::map<int, std::vector<size_t> >& globalIndexSentFromGridSource = gridIndexClientClientMapping_->getGlobalIndexOnServer();
87  std::map<int, std::vector<size_t> >::const_iterator itbMapSrc = globalIndexSentFromGridSource.begin(), itMapSrc,
88                                                      iteMapSrc = globalIndexSentFromGridSource.end();
89  std::vector<size_t>::const_iterator itbVec, itVec, iteVec;
90  for (itMapSrc = itbMapSrc; itMapSrc != iteMapSrc; ++itMapSrc)
91  {
92    int sourceRank = itMapSrc->first;
93    itbVec = (itMapSrc->second).begin();
94    iteVec = (itMapSrc->second).end();
95    for (itVec = itbVec; itVec != iteVec; ++itVec)
96    {
97       (globalIndexReceivedOnGridDestMapping_[sourceRank]).push_back(globalIndexMapFromSrcToDest[*itVec]);
98    }
99  }
100
101  // Inform client about the destination to which it needs to send global indexes
102  int nbClient = client->clientSize;
103  int* sendBuff = new int[nbClient];
104  int* recvBuff = new int[nbClient];
105  for (int i = 0; i < nbClient; ++i) sendBuff[i] = 0;
106
107  // First of all, inform the number of destination a client needs to send global index
108  for (itMapSrc = itbMapSrc; itMapSrc != iteMapSrc; ++itMapSrc) sendBuff[itMapSrc->first] = 1;
109  MPI_Allreduce(sendBuff, recvBuff, nbClient, MPI_INT, MPI_SUM, client->intraComm);
110  int numClientToReceive = recvBuff[client->clientRank];
111
112  // Then specify the size of receiving buffer, because we use synch send/receive so only necessary to know maximum size
113  for (itMapSrc = itbMapSrc; itMapSrc != iteMapSrc; ++itMapSrc) sendBuff[itMapSrc->first] = (itMapSrc->second).size();
114  MPI_Allreduce(sendBuff, recvBuff, nbClient, MPI_INT, MPI_MAX, client->intraComm);
115
116  int buffSize = recvBuff[client->clientRank];
117  unsigned long* recvBuffGlobalIndex;
118  if (0 != buffSize) recvBuffGlobalIndex = new unsigned long [buffSize];
119
120  // Inform all "source clients" about index that they need to send
121  for (itMapSrc = itbMapSrc; itMapSrc != iteMapSrc; ++itMapSrc)
122  {
123    MPI_Request request;
124    unsigned long* sendPtr = const_cast<unsigned long*>(&(itMapSrc->second)[0]);
125    MPI_Isend(sendPtr,
126              (itMapSrc->second).size(),
127              MPI_UNSIGNED_LONG,
128              itMapSrc->first,
129              11,
130              client->intraComm,
131              &request);
132  }
133
134  // Now all the "source clients" try listening messages from other "destination clients"
135  int numClientReceived = 0;  // number of client to which data has been already sent
136  int countBuff;
137  while (numClientReceived < numClientToReceive)
138  {
139    MPI_Status status;
140    MPI_Recv(recvBuffGlobalIndex,
141             buffSize,
142             MPI_UNSIGNED_LONG,
143             MPI_ANY_SOURCE,
144             11,
145             client->intraComm,
146             &status);
147
148    MPI_Get_count(&status, MPI_UNSIGNED_LONG, &countBuff);
149    int clientDestRank = status.MPI_SOURCE;
150    for (int idx = 0; idx < countBuff; ++idx)
151    {
152      globalIndexSendToGridDestMapping_[clientDestRank].push_back(recvBuffGlobalIndex[idx]);
153    }
154    ++numClientReceived;
155  }
156
157  delete [] sendBuff;
158  delete [] recvBuff;
159  if (0 != buffSize) delete [] recvBuffGlobalIndex;
160}
161
162/*!
163  Return (grid) global index on grid destination. This mapping contains the rank of client source (that sends info to grid destination)
164and the corresponding global index to write on grid destination.
165  \return global index mapping to receive on grid destination
166*/
167const std::map<int,std::vector<std::vector<size_t> > >& CTransformationMapping::getGlobalIndexReceivedOnGridDestMapping() const
168{
169  return globalIndexReceivedOnGridDestMapping_;
170}
171
172/*!
173  Return (grid) global index on grid source. This mapping contains the rank of client destination (which receives transformation info) and
174the corresponding global index to send
175  \return global index mapping to send on grid source
176*/
177const std::map<int,std::vector<size_t> >& CTransformationMapping::getGlobalIndexSendToGridDestMapping() const
178{
179  return globalIndexSendToGridDestMapping_;
180}
181
182}
Note: See TracBrowser for help on using the repository browser.