source: XIOS/trunk/src/filter/transformation_mapping.cpp @ 623

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

Implementing transformation algorithm: zoom axis (local commit)

+) Implement zoom axis: zoomed points are points not masked
+) Correct some minor bugs

Test
+) Ok with normal cases: zoom in the last of transformation list
+) There is still a bug in case of zoom then inverse

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