source: XIOS/dev/dev_trunk_graph/src/transformation/axis_algorithm/axis_algorithm_inverse.cpp @ 2030

Last change on this file since 2030 was 2030, checked in by yushan, 6 months ago

Graph intermediate commit to a tmp branch.

  • Property svn:executable set to *
File size: 11.4 KB
Line 
1/*!
2   \file axis_algorithm_inverse.hpp
3   \author Ha NGUYEN
4   \since 14 May 2015
5   \date 29 June 2015
6
7   \brief Algorithm for inversing an axis..
8 */
9#include "axis_algorithm_inverse.hpp"
10#include "context.hpp"
11#include "context_client.hpp"
12#include "axis.hpp"
13#include "grid.hpp"
14#include "grid_transformation_factory_impl.hpp"
15#include "inverse_axis.hpp"
16#include "client_client_dht_template.hpp"
17
18namespace xios {
19
20CGenericAlgorithmTransformation* CAxisAlgorithmInverse::create(bool isSource, CGrid* gridDst, CGrid* gridSrc,
21                                                               CTransformation<CAxis>* transformation,
22                                                               int elementPositionInGrid,
23                                                               std::map<int, int>& elementPositionInGridSrc2ScalarPosition,
24                                                               std::map<int, int>& elementPositionInGridSrc2AxisPosition,
25                                                               std::map<int, int>& elementPositionInGridSrc2DomainPosition,
26                                                               std::map<int, int>& elementPositionInGridDst2ScalarPosition,
27                                                               std::map<int, int>& elementPositionInGridDst2AxisPosition,
28                                                               std::map<int, int>& elementPositionInGridDst2DomainPosition)
29TRY
30{
31  std::vector<CAxis*> axisListDestP = gridDst->getAxis();
32  std::vector<CAxis*> axisListSrcP  = gridSrc->getAxis();
33
34  CInverseAxis* inverseAxis = dynamic_cast<CInverseAxis*> (transformation);
35  int axisDstIndex = elementPositionInGridDst2AxisPosition[elementPositionInGrid];
36  int axisSrcIndex = elementPositionInGridSrc2AxisPosition[elementPositionInGrid];
37
38  return (new CAxisAlgorithmInverse(isSource, axisListDestP[axisDstIndex], axisListSrcP[axisSrcIndex], inverseAxis));
39}
40CATCH
41
42bool CAxisAlgorithmInverse::dummyRegistered_ = CAxisAlgorithmInverse::registerTrans();
43bool CAxisAlgorithmInverse::registerTrans()
44TRY
45{
46  return CGridTransformationFactory<CAxis>::registerTransformation(TRANS_INVERSE_AXIS, create);
47}
48CATCH
49
50CAxisAlgorithmInverse::CAxisAlgorithmInverse(bool isSource, CAxis* axisDestination, CAxis* axisSource, CInverseAxis* inverseAxis)
51 : CAlgorithmTransformationTransfer(isSource), axisDest_(axisDestination), axisSrc_(axisSource)
52TRY
53{
54  if (axisDestination->n_glo.getValue() != axisSource->n_glo.getValue())
55  {
56    ERROR("CAxisAlgorithmInverse::CAxisAlgorithmInverse(CAxis* axisDestination, CAxis* axisSource)",
57           << "Two axis have different global size"
58           << "Size of axis source " <<axisSource->getId() << " is " << axisSource->n_glo.getValue()  << std::endl
59           << "Size of axis destination " <<axisDestination->getId() << " is " << axisDestination->n_glo.getValue());
60  }
61
62  auto& transMap = this->transformationMapping_;
63
64  int globalIndexSize = axisSource->index.numElements();
65  for (int idx = 0; idx < globalIndexSize; ++idx)
66  {
67    //transMap[axisDestination->index(idx)] = globalIndexSize-axisDestination->index(idx)-1;
68    transMap[axisSource->index(idx)] = globalIndexSize-axisSource->index(idx)-1;
69  }
70
71  int niSrc   = axisSrc_->n.getValue();
72  int sizeSrc = axisSrc_->n_glo.getValue();
73  if (niSrc != sizeSrc) updateAxisValue();
74  else
75  {
76    for (int idx = 0; idx < sizeSrc; ++idx)
77    {
78      axisDest_->value(idx) = axisSrc_->value(sizeSrc-idx-1);
79    }
80  }
81
82  axisDestination->checkAttributes() ;
83  this->computeAlgorithm(axisSource->getLocalView(CElementView::WORKFLOW), axisDestination->getLocalView(CElementView::WORKFLOW)) ;
84
85}
86CATCH
87
88
89/*!
90  Update value on axis after inversing
91  After an axis is inversed, not only the data on it must be inversed but also the value
92*/
93void CAxisAlgorithmInverse::updateAxisValue()
94TRY
95{
96  CContext* context = CContext::getCurrent();
97  int clientRank = context->intraCommRank_;
98  int nbClient = context->intraCommSize_;
99
100  int niSrc     = axisSrc_->n.getValue();
101  int ibeginSrc = axisSrc_->begin.getValue();
102  int nSrc = axisSrc_->index.numElements();
103
104  CClientClientDHTInt::Index2VectorInfoTypeMap globalIndex2ProcRank;
105  for (int idx = 0; idx < nSrc; ++idx)
106  {
107    if ((axisSrc_->mask)(idx))
108    {
109      globalIndex2ProcRank[(axisSrc_->index)(idx)].resize(1);
110      globalIndex2ProcRank[(axisSrc_->index)(idx)][0] = clientRank;
111    }
112  }
113
114  typedef std::unordered_map<size_t, std::vector<double> > GlobalIndexMapFromSrcToDest;
115  GlobalIndexMapFromSrcToDest globalIndexMapFromSrcToDest;
116  auto& transMap = this->transformationMapping_;
117  CArray<size_t,1> globalSrcIndex(transMap.size());
118  int localIndex = 0;
119  for (auto it = transMap.begin(); it != transMap.end(); ++it)
120  {
121    size_t srcIndex = it->second;
122    globalIndexMapFromSrcToDest[srcIndex].resize(1);
123    globalIndexMapFromSrcToDest[srcIndex][0] = it->first;
124    globalSrcIndex(localIndex) = srcIndex;
125    ++localIndex;
126  }
127
128  CClientClientDHTInt dhtIndexProcRank(globalIndex2ProcRank, context->intraComm_);
129  dhtIndexProcRank.computeIndexInfoMapping(globalSrcIndex);
130  CClientClientDHTInt::Index2VectorInfoTypeMap& computedGlobalIndexOnProc = dhtIndexProcRank.getInfoIndexMap();
131  std::unordered_map<int, std::vector<size_t> > globalSrcIndexSendToProc;
132  for (int idx = 0; idx < localIndex; ++idx)
133  {
134    size_t tmpIndex = globalSrcIndex(idx);
135    if (1 == computedGlobalIndexOnProc.count(tmpIndex))
136    {
137      std::vector<int>& tmpVec = computedGlobalIndexOnProc[tmpIndex];
138      globalSrcIndexSendToProc[tmpVec[0]].push_back(tmpIndex);
139    }
140  }
141
142  std::unordered_map<int, std::vector<size_t> >::const_iterator itbIndex = globalSrcIndexSendToProc.begin(), itIndex,
143                                                                  iteIndex = globalSrcIndexSendToProc.end();
144  std::map<int,int> sendRankSizeMap,recvRankSizeMap;
145  int connectedClient = globalSrcIndexSendToProc.size();
146  int* recvCount=new int[nbClient];
147  int* displ=new int[nbClient];
148  int* sendRankBuff=new int[connectedClient];
149  int* sendSizeBuff=new int[connectedClient];
150  int n = 0;
151  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex, ++n)
152  {
153    sendRankBuff[n] = itIndex->first;
154    int sendSize = itIndex->second.size();
155    sendSizeBuff[n] = sendSize;
156    sendRankSizeMap[itIndex->first] = sendSize;
157  }
158  MPI_Allgather(&connectedClient,1,MPI_INT,recvCount,1,MPI_INT,context->intraComm_);
159
160  displ[0]=0 ;
161  for(int n=1;n<nbClient;n++) displ[n]=displ[n-1]+recvCount[n-1];
162  int recvSize=displ[nbClient-1]+recvCount[nbClient-1];
163  int* recvRankBuff=new int[recvSize];
164  int* recvSizeBuff=new int[recvSize];
165  MPI_Allgatherv(sendRankBuff,connectedClient,MPI_INT,recvRankBuff,recvCount,displ,MPI_INT,context->intraComm_);
166  MPI_Allgatherv(sendSizeBuff,connectedClient,MPI_INT,recvSizeBuff,recvCount,displ,MPI_INT,context->intraComm_);
167  for (int i = 0; i < nbClient; ++i)
168  {
169    int currentPos = displ[i];
170    for (int j = 0; j < recvCount[i]; ++j)
171      if (recvRankBuff[currentPos+j] == clientRank)
172      {
173        recvRankSizeMap[i] = recvSizeBuff[currentPos+j];
174      }
175  }
176
177  // Sending global index of grid source to corresponding process as well as the corresponding mask
178  std::vector<MPI_Request> requests;
179  std::vector<MPI_Status> status;
180  std::unordered_map<int, unsigned long* > recvGlobalIndexSrc;
181  std::unordered_map<int, double* > sendValueToDest;
182  for (std::map<int,int>::const_iterator itRecv = recvRankSizeMap.begin(); itRecv != recvRankSizeMap.end(); ++itRecv)
183  {
184    int recvRank = itRecv->first;
185    int recvSize = itRecv->second;
186    recvGlobalIndexSrc[recvRank] = new unsigned long [recvSize];
187    sendValueToDest[recvRank] = new double [recvSize];
188
189    requests.push_back(MPI_Request());
190    MPI_Irecv(recvGlobalIndexSrc[recvRank], recvSize, MPI_UNSIGNED_LONG, recvRank, 46, context->intraComm_, &requests.back());
191  }
192
193  std::unordered_map<int, unsigned long* > sendGlobalIndexSrc;
194  std::unordered_map<int, double* > recvValueFromSrc;
195  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex)
196  {
197    int sendRank = itIndex->first;
198    int sendSize = sendRankSizeMap[sendRank];
199    const std::vector<size_t>& sendIndexMap = itIndex->second;
200    std::vector<size_t>::const_iterator itbSend = sendIndexMap.begin(), iteSend = sendIndexMap.end(), itSend;
201    sendGlobalIndexSrc[sendRank] = new unsigned long [sendSize];
202    recvValueFromSrc[sendRank] = new double [sendSize];
203    int countIndex = 0;
204    for (itSend = itbSend; itSend != iteSend; ++itSend)
205    {
206      sendGlobalIndexSrc[sendRank][countIndex] = *itSend;
207      ++countIndex;
208    }
209
210    // Send global index source and mask
211    requests.push_back(MPI_Request());
212    MPI_Isend(sendGlobalIndexSrc[sendRank], sendSize, MPI_UNSIGNED_LONG, sendRank, 46, context->intraComm_, &requests.back());
213  }
214
215  status.resize(requests.size());
216  MPI_Waitall(requests.size(), &requests[0], &status[0]);
217
218
219  std::vector<MPI_Request>().swap(requests);
220  std::vector<MPI_Status>().swap(status);
221
222  // Okie, on destination side, we will wait for information of masked index of source
223  for (std::map<int,int>::const_iterator itSend = sendRankSizeMap.begin(); itSend != sendRankSizeMap.end(); ++itSend)
224  {
225    int recvRank = itSend->first;
226    int recvSize = itSend->second;
227
228    requests.push_back(MPI_Request());
229    MPI_Irecv(recvValueFromSrc[recvRank], recvSize, MPI_DOUBLE, recvRank, 48, context->intraComm_, &requests.back());
230  }
231
232  for (std::map<int,int>::const_iterator itRecv = recvRankSizeMap.begin(); itRecv != recvRankSizeMap.end(); ++itRecv)
233  {
234    int recvRank = itRecv->first;
235    int recvSize = itRecv->second;
236    double* sendValue = sendValueToDest[recvRank];
237    unsigned long* recvIndexSrc = recvGlobalIndexSrc[recvRank];
238    int realSendSize = 0;
239    for (int idx = 0; idx < recvSize; ++idx)
240    {
241      size_t globalIndex = *(recvIndexSrc+idx);
242      int localIndex = globalIndex - ibeginSrc;
243      *(sendValue + idx) = axisSrc_->value(localIndex);
244    }
245    // Okie, now inform the destination which source index are masked
246    requests.push_back(MPI_Request());
247    MPI_Isend(sendValueToDest[recvRank], recvSize, MPI_DOUBLE, recvRank, 48, context->intraComm_, &requests.back());
248  }
249  status.resize(requests.size());
250  MPI_Waitall(requests.size(), &requests[0], &status[0]);
251
252
253  size_t nGloAxisDest = axisDest_->n_glo.getValue() - 1;
254  for (std::map<int,int>::const_iterator itSend = sendRankSizeMap.begin(); itSend != sendRankSizeMap.end(); ++itSend)
255  {
256    int recvRank = itSend->first;
257    int recvSize = itSend->second;
258
259    double* recvValue = recvValueFromSrc[recvRank];
260    unsigned long* recvIndex = sendGlobalIndexSrc[recvRank];
261    for (int idx = 0; idx < recvSize; ++idx)
262    {
263      size_t globalIndex = *(recvIndex+idx);
264      int localIndex = ((nGloAxisDest-globalIndex) - axisDest_->begin);
265      axisDest_->value(localIndex) = *(recvValue + idx);
266    }
267  }
268
269  delete [] recvCount;
270  delete [] displ;
271  delete [] sendRankBuff;
272  delete [] recvRankBuff;
273  delete [] sendSizeBuff;
274  delete [] recvSizeBuff;
275
276  std::unordered_map<int, double* >::const_iterator itChar;
277  for (itChar = sendValueToDest.begin(); itChar != sendValueToDest.end(); ++itChar)
278    delete [] itChar->second;
279  for (itChar = recvValueFromSrc.begin(); itChar != recvValueFromSrc.end(); ++itChar)
280    delete [] itChar->second;
281  std::unordered_map<int, unsigned long* >::const_iterator itLong;
282  for (itLong = sendGlobalIndexSrc.begin(); itLong != sendGlobalIndexSrc.end(); ++itLong)
283    delete [] itLong->second;
284  for (itLong = recvGlobalIndexSrc.begin(); itLong != recvGlobalIndexSrc.end(); ++itLong)
285    delete [] itLong->second;
286}
287CATCH
288
289}
Note: See TracBrowser for help on using the repository browser.