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

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

Exposing transformation to Fortran interface

+) Export zoom and axis transformation to Fortran interface

Test
+) On Curie
+) All work

File size: 9.7 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#include "client_client_dht_template.hpp"
16#include "dht_data_types.hpp"
17#include "mpi_tag.hpp"
18
19namespace xios {
20
21CTransformationMapping::CTransformationMapping(CGrid* destination, CGrid* source)
22  : gridSource_(source), gridDestination_(destination)
23{
24  CContext* context = CContext::getCurrent();
25  CContextClient* client=context->client;
26  int clientRank = client->clientRank;
27
28  CDistributionClient distributionClientSrc(client->clientRank, gridSource_);
29  const CDistributionClient::GlobalLocalDataMap& globalLocalIndexGridSrc = distributionClientSrc.getGlobalLocalDataSendToServer();
30  CDistributionClient::GlobalLocalDataMap::const_iterator itIndex = globalLocalIndexGridSrc.begin(), iteIndex = globalLocalIndexGridSrc.end();
31
32  // Mapping of global index and pair containing rank and local index
33  CClientClientDHTPairIntInt::Index2InfoTypeMap globalIndexOfServer;
34  PairIntInt pairIntInt;
35  for (; itIndex != iteIndex; ++itIndex)
36  {
37    pairIntInt.first  = clientRank;
38    pairIntInt.second = itIndex->second;
39    globalIndexOfServer[itIndex->first] = pairIntInt;
40  }
41
42  gridIndexClientClientMapping_ = new CClientClientDHTPairIntInt(globalIndexOfServer,
43                                                                 client->intraComm);
44}
45
46CTransformationMapping::CTransformationMapping(CAxis* destination, CAxis* source)
47  : gridSource_(0), gridDestination_(0)
48{
49  CContext* context = CContext::getCurrent();
50  CContextClient* client=context->client;
51  int clientRank = client->clientRank;
52
53  int niSrc     = source->n.getValue();
54  int ibeginSrc = source->begin.getValue();
55
56  CClientClientDHTPairIntInt::Index2InfoTypeMap globalIndexOfAxisSource;
57  PairIntInt pii;
58  for (int idx = 0; idx < niSrc; ++idx)
59  {
60    pii.first  = clientRank;
61    pii.second = idx;
62    globalIndexOfAxisSource[idx+ibeginSrc] = pii; //std::make_pair(clientRank,idx);
63  }
64
65  gridIndexClientClientMapping_ = new CClientClientDHTPairIntInt(globalIndexOfAxisSource,
66                                                                 client->intraComm);
67}
68
69CTransformationMapping::~CTransformationMapping()
70{
71  if (0 != gridIndexClientClientMapping_) delete gridIndexClientClientMapping_;
72}
73
74/*!
75  Suppose that we have transformations between two grids, which are represented in form of mapping between global indexes of these two grids,
76this function tries to find out which clients a client needs to send and receive these global indexes to accomplish the transformations.
77  The grid destination is the grid whose global indexes demande global indexes from the other grid
78  Grid destination and grid source are also distributed among clients but in different manners.
79  \param [in] globaIndexWeightFromDestToSource mapping representing the transformations
80*/
81void CTransformationMapping::computeTransformationMapping(const DestinationIndexMap& globaIndexWeightFromDestToSource)
82{
83  CContext* context = CContext::getCurrent();
84  CContextClient* client=context->client;
85
86  DestinationIndexMap::const_iterator itbMap = globaIndexWeightFromDestToSource.begin(), itMap,
87                                      iteMap = globaIndexWeightFromDestToSource.end();
88
89  // Not only one index on grid destination can demande two indexes from grid source
90  // but an index on grid source has to be sent to two indexes of grid destination
91  DestinationIndexMap globalIndexMapFromSrcToDest;
92  boost::unordered_map<size_t, int> nbGlobalIndexMapFromSrcToDest;
93  std::vector<std::pair<int, std::pair<size_t,double> > >::const_iterator itbVecPair, itVecPair, iteVecPair;
94  for (itMap = itbMap; itMap != iteMap; ++itMap)
95  {
96    itbVecPair = (itMap->second).begin();
97    iteVecPair = (itMap->second).end();
98    for (itVecPair = itbVecPair; itVecPair != iteVecPair; ++itVecPair)
99    {
100      ++nbGlobalIndexMapFromSrcToDest[(itVecPair->second).first];
101    }
102  }
103
104  for (boost::unordered_map<size_t, int>::const_iterator it = nbGlobalIndexMapFromSrcToDest.begin();
105                                                         it != nbGlobalIndexMapFromSrcToDest.end(); ++it)
106  {
107    globalIndexMapFromSrcToDest[it->first].reserve(it->second);
108  }
109
110  for (itMap = itbMap; itMap != iteMap; ++itMap)
111  {
112    itbVecPair = (itMap->second).begin();
113    iteVecPair = (itMap->second).end();
114    for (itVecPair = itbVecPair; itVecPair != iteVecPair; ++itVecPair)
115    {
116      globalIndexMapFromSrcToDest[(itVecPair->second).first].push_back(std::make_pair(itVecPair->first, std::make_pair(itMap->first, (itVecPair->second).second)));
117    }
118  }
119
120  // All global indexes of a client on grid destination
121  CArray<size_t,1> globalIndexMap(globalIndexMapFromSrcToDest.size());
122  DestinationIndexMap::const_iterator itbMapBoost = globalIndexMapFromSrcToDest.begin(), itMapBoost;
123  DestinationIndexMap::const_iterator iteMapBoost = globalIndexMapFromSrcToDest.end();
124  int idx = 0;
125  for (itMapBoost = itbMapBoost; itMapBoost != iteMapBoost; ++itMapBoost)
126  {
127    globalIndexMap(idx) = itMapBoost->first;
128    ++idx;
129  }
130
131  // Find out on which clients the necessary indexes of grid source are.
132  gridIndexClientClientMapping_->computeIndexInfoMapping(globalIndexMap);
133  const CClientClientDHTPairIntInt::Index2InfoTypeMap& globalIndexSentFromGridSource = gridIndexClientClientMapping_->getInfoIndexMap();
134  CClientClientDHTPairIntInt::Index2InfoTypeMap::const_iterator itbMapSrc = globalIndexSentFromGridSource.begin(), itMapSrc,
135                                                                iteMapSrc = globalIndexSentFromGridSource.end();
136  std::vector<size_t>::const_iterator itbVec, itVec, iteVec;
137    // Inform client about the destination to which it needs to send global indexes
138  int nbClient = client->clientSize;
139  std::vector<int> sendNbClientBuff(nbClient,0);
140  std::vector<int> recvNbClientBuff(nbClient,0);
141  std::vector<int> sendIndexBuff(nbClient,0);
142  std::vector<int> recvIndexBuff(nbClient,0);
143  boost::unordered_map<int,std::vector<size_t> > sendIndexMap;
144  for (itMapSrc = itbMapSrc; itMapSrc != iteMapSrc; ++itMapSrc)
145  {
146    int sourceRank = (itMapSrc->second).first;
147    (globalIndexReceivedOnGridDestMapping_[sourceRank]).push_back(globalIndexMapFromSrcToDest[itMapSrc->first]);
148    sendIndexMap[sourceRank].push_back((itMapSrc->second).second);
149    sendIndexMap[sourceRank].push_back(itMapSrc->first);
150    sendNbClientBuff[sourceRank] = 1;
151    ++sendIndexBuff[sourceRank];
152  }
153
154  MPI_Allreduce(&sendNbClientBuff[0], &recvNbClientBuff[0], nbClient, MPI_INT, MPI_SUM, client->intraComm);
155  int numClientToReceive = recvNbClientBuff[client->clientRank];
156
157  // Then specify the size of receiving buffer, because we use synch send/receive so only necessary to know maximum size
158  MPI_Allreduce(&sendIndexBuff[0], &recvIndexBuff[0], nbClient, MPI_INT, MPI_MAX, client->intraComm);
159  int buffSize = 2*recvIndexBuff[client->clientRank]; // we send global as well as local index
160  unsigned long* recvBuffGlobalIndex;
161  if (0 != buffSize) recvBuffGlobalIndex = new unsigned long [buffSize];
162
163  std::map<int, MPI_Request> requests;
164
165  // Inform all "source clients" about index that they need to send
166  boost::unordered_map<int,std::vector<size_t> >::const_iterator itSendIndex = sendIndexMap.begin(),
167                                                                 iteSendIndex= sendIndexMap.end();
168  for (; itSendIndex != iteSendIndex; ++itSendIndex)
169  {
170    unsigned long* sendPtr = const_cast<unsigned long*>(&(itSendIndex->second)[0]);
171    MPI_Isend(sendPtr,
172              (itSendIndex->second).size(),
173              MPI_UNSIGNED_LONG,
174              (itSendIndex->first),
175              MPI_TRANSFORMATION_MAPPING_INDEX,
176              client->intraComm,
177              &requests[(itSendIndex->first)]);
178  }
179
180  // Now all the "source clients" try listening messages from other "destination clients"
181  int numClientReceived = 0;  // number of client to which data has been already sent
182  int countBuff;
183  while (numClientReceived < numClientToReceive)
184  {
185    MPI_Status status;
186    MPI_Recv(recvBuffGlobalIndex,
187             buffSize,
188             MPI_UNSIGNED_LONG,
189             MPI_ANY_SOURCE,
190             MPI_TRANSFORMATION_MAPPING_INDEX,
191             client->intraComm,
192             &status);
193
194    MPI_Get_count(&status, MPI_UNSIGNED_LONG, &countBuff);
195    int clientDestRank = status.MPI_SOURCE;
196    for (int idx = 0; idx < countBuff; idx += 2)
197    {
198      globalIndexSendToGridDestMapping_[clientDestRank].push_back(std::make_pair<int,size_t>(recvBuffGlobalIndex[idx], recvBuffGlobalIndex[idx+1]));
199    }
200    ++numClientReceived;
201  }
202
203  std::map<int, MPI_Request>::iterator itRequest;
204  for (itRequest = requests.begin(); itRequest != requests.end(); ++itRequest)
205    MPI_Wait(&itRequest->second, MPI_STATUS_IGNORE);
206
207  if (0 != buffSize) delete [] recvBuffGlobalIndex;
208}
209
210/*!
211  Return (grid) global index on grid destination. This mapping contains the rank of client source (that sends info to grid destination)
212and the corresponding global index to write on grid destination.
213  \return global index mapping to receive on grid destination
214*/
215const CTransformationMapping::ReceivedIndexMap& CTransformationMapping::getGlobalIndexReceivedOnGridDestMapping() const
216{
217  return globalIndexReceivedOnGridDestMapping_;
218}
219
220/*!
221  Return (grid) global index on grid source. This mapping contains the rank of client destination (which receives transformation info) and
222the corresponding global index to send
223  \return global index mapping to send on grid source
224*/
225const CTransformationMapping::SentIndexMap& CTransformationMapping::getGlobalIndexSendToGridDestMapping() const
226{
227  return globalIndexSendToGridDestMapping_;
228}
229
230}
Note: See TracBrowser for help on using the repository browser.