source: XIOS/dev/XIOS_DEV_CMIP6/src/transformation/generic_algorithm_transformation.cpp @ 1390

Last change on this file since 1390 was 1389, checked in by ymipsl, 6 years ago

Fix regression on vertical interpolation with pressure level.

YM

File size: 31.8 KB
Line 
1/*!
2   \file generic_algorithm_transformation.hpp
3   \author Ha NGUYEN
4   \since 14 May 2015
5   \date 21 Mars 2016
6
7   \brief Interface for all transformation algorithms.
8 */
9#include "generic_algorithm_transformation.hpp"
10#include "context.hpp"
11#include "context_client.hpp"
12#include "client_client_dht_template.hpp"
13#include "utils.hpp"
14#include "timer.hpp"
15
16namespace xios {
17
18CGenericAlgorithmTransformation::CGenericAlgorithmTransformation()
19 : transformationMapping_(), transformationWeight_(), transformationPosition_(),
20   idAuxInputs_(), type_(ELEMENT_NO_MODIFICATION_WITH_DATA), indexElementSrc_(),
21   computedProcSrcNonTransformedElement_(false), eliminateRedondantSrc_(true)
22{
23}
24
25void CGenericAlgorithmTransformation::updateData(CArray<double,1>& dataOut)
26{
27
28}
29
30void CGenericAlgorithmTransformation::apply(const std::vector<std::pair<int,double> >& localIndex,
31                                            const double* dataInput,
32                                            CArray<double,1>& dataOut,
33                                            std::vector<bool>& flagInitial,
34                                            bool ignoreMissingValue, bool firstPass  )
35{
36  int nbLocalIndex = localIndex.size();   
37  double defaultValue = std::numeric_limits<double>::quiet_NaN();
38  if (ignoreMissingValue)
39  {
40    for (int idx = 0; idx < nbLocalIndex; ++idx)
41    {
42      if (NumTraits<double>::isnan(*(dataInput + idx)))
43      {
44        flagInitial[localIndex[idx].first] = false;
45      }
46      else
47      {
48        dataOut(localIndex[idx].first) += *(dataInput + idx) * localIndex[idx].second;
49        flagInitial[localIndex[idx].first] = true; // Reset flag to indicate not all data source are nan
50      }
51    }
52
53    // If all data source are nan then data destination must be nan
54    for (int idx = 0; idx < nbLocalIndex; ++idx)
55    {
56      if (!flagInitial[localIndex[idx].first])
57        dataOut(localIndex[idx].first) = defaultValue;
58    }
59  }
60  else
61  {
62    for (int idx = 0; idx < nbLocalIndex; ++idx)
63    {
64      dataOut(localIndex[idx].first) += *(dataInput + idx) * localIndex[idx].second;
65    }
66  }
67}
68
69void CGenericAlgorithmTransformation::computePositionElements(CGrid* dst, CGrid* src)
70{
71  int idxScalar = 0, idxAxis = 0, idxDomain = 0;
72  CArray<int,1> axisDomainOrderDst = dst->axis_domain_order;
73  for (int i = 0; i < axisDomainOrderDst.numElements(); ++i)
74  {
75    int dimElement = axisDomainOrderDst(i);
76    if (2 == dimElement)
77    {
78      elementPositionInGridDst2DomainPosition_[i] = idxDomain;
79      ++idxDomain;
80    }
81    else if (1 == dimElement)
82    {
83      elementPositionInGridDst2AxisPosition_[i] = idxAxis;
84      ++idxAxis;
85    }
86    else
87    {
88      elementPositionInGridDst2ScalarPosition_[i] = idxScalar;
89      ++idxScalar;
90    }
91  }
92
93  idxScalar = idxAxis = idxDomain = 0;
94  CArray<int,1> axisDomainOrderSrc = src->axis_domain_order;
95  for (int i = 0; i < axisDomainOrderSrc.numElements(); ++i)
96  {
97    int dimElement = axisDomainOrderSrc(i);
98    if (2 == dimElement)
99    {
100      elementPositionInGridSrc2DomainPosition_[i] = idxDomain;
101      ++idxDomain;
102    }
103    else if (1 == dimElement)
104    {
105      elementPositionInGridSrc2AxisPosition_[i] = idxAxis;
106      ++idxAxis;
107    }
108    else
109    {
110      elementPositionInGridSrc2ScalarPosition_[i] = idxScalar;
111      ++idxScalar;
112    }
113  }
114}
115
116/*!
117  This function computes the global indexes of grid source, which the grid destination is in demand.
118  \param[in] elementPositionInGrid position of an element in a grid .E.g: if grid is composed of domain and axis (in order),
119                then position of axis in grid is 1 and domain is positioned at 0.
120  \param[in] gridSrc Grid source
121  \param[in] gridDst Grid destination
122  \param[in\out] globaIndexWeightFromSrcToDst mapping of each global index source and weight to index destination
123*/
124void CGenericAlgorithmTransformation::computeGlobalSourceIndex(int elementPositionInGrid,
125                                                               CGrid* gridSrc,
126                                                               CGrid* gridDst,
127                                                               SourceDestinationIndexMap& globaIndexWeightFromSrcToDst)
128 {
129  CContext* context = CContext::getCurrent();
130  CContextClient* client = context->client;
131  int nbClient = client->clientSize;
132
133  typedef boost::unordered_map<int, std::vector<std::pair<int,double> > > SrcToDstMap;
134  int idx;
135
136  // compute position of elements on grids
137  computePositionElements(gridDst, gridSrc);
138  std::vector<CScalar*> scalarListDestP = gridDst->getScalars();
139  std::vector<CAxis*> axisListDestP = gridDst->getAxis();
140  std::vector<CDomain*> domainListDestP = gridDst->getDomains();
141  CArray<int,1> axisDomainDstOrder = gridDst->axis_domain_order;
142  std::vector<CScalar*> scalarListSrcP  = gridSrc->getScalars();
143  std::vector<CAxis*> axisListSrcP = gridSrc->getAxis();
144  std::vector<CDomain*> domainListSrcP = gridSrc->getDomains();
145  CArray<int,1> axisDomainSrcOrder = gridSrc->axis_domain_order; 
146 
147  bool isTransPosEmpty = transformationPosition_.empty();
148  CArray<size_t,1> transPos;
149  if (!isTransPosEmpty) transPos.resize(transformationMapping_.size());
150  std::set<size_t> allIndexSrc; // All index of source, which can be scattered among processes, need for doing transformation
151 
152  for (size_t idxTrans = 0; idxTrans < transformationMapping_.size(); ++idxTrans)
153  {
154    TransformationIndexMap::const_iterator itbTransMap = transformationMapping_[idxTrans].begin(), itTransMap,
155                                           iteTransMap = transformationMapping_[idxTrans].end();
156    TransformationWeightMap::const_iterator itbTransWeight = transformationWeight_[idxTrans].begin(), itTransWeight;
157
158    // Build mapping between global source element index and global destination element index.
159    itTransWeight = itbTransWeight;
160    for (itTransMap = itbTransMap; itTransMap != iteTransMap; ++itTransMap, ++itTransWeight)
161    {
162      const std::vector<int>& srcIndex = itTransMap->second;
163      for (idx = 0; idx < srcIndex.size(); ++idx)
164        allIndexSrc.insert(srcIndex[idx]);
165    }
166
167    if (!isTransPosEmpty)
168    {
169      TransformationPositionMap::const_iterator itPosMap = transformationPosition_[idxTrans].begin();
170      transPos(idxTrans) = itPosMap->second[0];
171    }
172  }
173
174  size_t indexSrcSize = 0;
175  CArray<size_t,1> indexSrc(allIndexSrc.size());
176  for (std::set<size_t>::iterator it = allIndexSrc.begin(); it != allIndexSrc.end(); ++it, ++indexSrcSize)
177    indexSrc(indexSrcSize) = *it;
178
179  // Flag to indicate whether we will recompute distribution of source global index  on processes
180  bool computeGlobalIndexOnProc = false; 
181  if (indexElementSrc_.size() != allIndexSrc.size())
182    computeGlobalIndexOnProc = true; 
183  else
184  {
185    for (std::set<size_t>::iterator it = allIndexSrc.begin(); it != allIndexSrc.end(); ++it)
186      if (0 == indexElementSrc_.count(*it))
187      {
188        computeGlobalIndexOnProc = true;
189        break;       
190      }
191  }
192
193  if (computeGlobalIndexOnProc)
194    indexElementSrc_.swap(allIndexSrc);
195     
196  int sendValue = (computeGlobalIndexOnProc) ? 1 : 0;
197  int recvValue = 0;
198  MPI_Allreduce(&sendValue, &recvValue, 1, MPI_INT, MPI_SUM, client->intraComm);
199  computeGlobalIndexOnProc = (0 < recvValue);
200
201  CClientClientDHTInt::Index2VectorInfoTypeMap globalIndexOfTransformedElementOnProc;
202 
203  if (computeGlobalIndexOnProc || !computedProcSrcNonTransformedElement_)
204  {   
205    // Find out global index source of transformed element on corresponding process.   
206    if (globalElementIndexOnProc_.empty())
207      globalElementIndexOnProc_.resize(axisDomainDstOrder.numElements());
208   
209    for (idx = 0; idx < axisDomainDstOrder.numElements(); ++idx)
210    {
211      if (idx == elementPositionInGrid)
212        computeExchangeGlobalIndex(indexSrc, axisDomainSrcOrder(idx), globalIndexOfTransformedElementOnProc); //globalElementIndexOnProc[idx]);
213      if (!computedProcSrcNonTransformedElement_)
214      {
215        if (2 == axisDomainDstOrder(idx)) // It's domain
216        {
217          if (idx != elementPositionInGrid)
218            computeExchangeDomainIndex(domainListDestP[elementPositionInGridDst2DomainPosition_[idx]],
219                                       domainListSrcP[elementPositionInGridSrc2DomainPosition_[idx]],
220                                       transPos,
221                                       globalElementIndexOnProc_[idx]);     
222
223        }
224        else if (1 == axisDomainDstOrder(idx))//it's an axis
225        {
226          if (idx != elementPositionInGrid)
227            computeExchangeAxisIndex(axisListDestP[elementPositionInGridDst2AxisPosition_[idx]],
228                                     axisListSrcP[elementPositionInGridSrc2AxisPosition_[idx]],
229                                     transPos,
230                                     globalElementIndexOnProc_[idx]);
231        }
232        else //it's a scalar
233        {
234          if (idx != elementPositionInGrid)
235            computeExchangeScalarIndex(scalarListDestP[elementPositionInGridDst2ScalarPosition_[idx]],
236                                       scalarListSrcP[elementPositionInGridSrc2ScalarPosition_[idx]],
237                                       transPos,
238                                       globalElementIndexOnProc_[idx]);
239
240        }
241      }
242    }
243
244    if (!isTransPosEmpty && !computedProcSrcNonTransformedElement_)
245    {
246      for (idx = 0; idx < globalElementIndexOnProc_.size(); ++idx)
247      {
248        if (idx != elementPositionInGrid)
249        {
250          boost::unordered_map<int,std::vector<size_t> >::iterator itb = globalElementIndexOnProc_[idx].begin(), it,
251                                                                   ite = globalElementIndexOnProc_[idx].end();
252          for (it = itb; it != ite; ++it) it->second.resize(1);
253        }
254      }
255    }
256
257/*     
258    if (!computedProcSrcNonTransformedElement_)
259    {
260      for (idx = 0; idx < globalElementIndexOnProc_.size(); ++idx)
261      {
262        if (idx != elementPositionInGrid)
263        {
264          boost::unordered_map<int,std::vector<size_t> >::iterator itb = globalElementIndexOnProc_[idx].begin(), it,
265                                                                   ite = globalElementIndexOnProc_[idx].end();
266          for (it = itb; it != ite; ++it) procOfNonTransformedElements_.insert(it->first);
267          if (procOfNonTransformedElements_.size() == nbClient)
268            break;
269        }
270      }
271    }
272   
273    // Processes contain the source index of transformed element
274    std::set<int> procOfTransformedElement;
275    CClientClientDHTInt::Index2VectorInfoTypeMap::iterator itIdxb = globalIndexOfTransformedElementOnProc.begin(),
276                                                           itIdxe = globalIndexOfTransformedElementOnProc.end(), itIdx;
277    for (itIdx = itIdxb; itIdx != itIdxe; ++itIdx)
278    {
279      std::vector<int>& tmp = itIdx->second;
280      for (int i = 0; i < tmp.size(); ++i)
281        procOfTransformedElement.insert(tmp[i]);
282      if (tmp.size() == nbClient)
283        break;
284    }                                                           
285   
286    std::set<int>& commonProc = (procOfTransformedElement.size() < procOfNonTransformedElements_.size()) ? procOfTransformedElement
287                              : (!procOfNonTransformedElements_.empty() ? procOfNonTransformedElements_ : procOfTransformedElement);
288   
289    std::vector<int> procContainSrcElementIdx(commonProc.size());
290    int count = 0;
291    for (std::set<int>::iterator it = commonProc.begin(); it != commonProc.end(); ++it)
292      procContainSrcElementIdx[count++] = *it;
293
294    procContainSrcElementIdx_.swap(procContainSrcElementIdx);   
295*/
296    std::set<int> commonProc ;
297    if (procElementList_.empty()) procElementList_.resize(axisDomainDstOrder.numElements()) ;
298    for (idx = 0; idx < axisDomainDstOrder.numElements(); ++idx)
299    {
300      std::set<int>& procList=procElementList_[idx] ;
301      std::set<int> commonTmp ;
302      if (idx == elementPositionInGrid)
303      {
304          set<int> tmpSet ; 
305          procList.swap(tmpSet) ;
306          CClientClientDHTInt::Index2VectorInfoTypeMap::iterator itIdxb = globalIndexOfTransformedElementOnProc.begin(),
307                                                                 itIdxe = globalIndexOfTransformedElementOnProc.end(), itIdx;
308          for (itIdx = itIdxb; itIdx != itIdxe; ++itIdx)
309          {
310             std::vector<int>& tmp = itIdx->second;
311             for (int i = 0; i < tmp.size(); ++i) procList.insert(tmp[i]);
312             if (tmp.size() == nbClient)
313             break;
314          }
315      }
316      else
317      {
318        if (!computedProcSrcNonTransformedElement_)
319        {
320          set<int> tmpSet ; 
321          procList.swap(tmpSet) ;
322          boost::unordered_map<int,std::vector<size_t> >::iterator itb = globalElementIndexOnProc_[idx].begin(), it,
323                                                                   ite = globalElementIndexOnProc_[idx].end();
324          for (it = itb; it != ite; ++it)
325          {
326            procList.insert(it->first);
327            if (procList.size() == nbClient)  break;
328          }
329        }
330      }
331
332      if (idx==0) commonProc.swap(procList) ;
333      else
334      {
335        for (std::set<int>::iterator it = commonProc.begin(); it != commonProc.end(); ++it)
336          if (procList.count(*it)==1) commonTmp.insert(*it) ;
337        commonProc.swap(commonTmp) ;
338      }
339    }
340    std::vector<int> procContainSrcElementIdx(commonProc.size());
341    int count = 0;
342    for (std::set<int>::iterator it = commonProc.begin(); it != commonProc.end(); ++it) procContainSrcElementIdx[count++] = *it;
343    procContainSrcElementIdx_.swap(procContainSrcElementIdx);
344   
345        // For the first time, surely we calculate proc containing non transformed elements
346    if (!computedProcSrcNonTransformedElement_) computedProcSrcNonTransformedElement_ = true;
347  }
348 
349  for (size_t idxTrans = 0; idxTrans < transformationMapping_.size(); ++idxTrans)
350  {
351    TransformationIndexMap::const_iterator itbTransMap = transformationMapping_[idxTrans].begin(), itTransMap,
352                                           iteTransMap = transformationMapping_[idxTrans].end();
353    TransformationWeightMap::const_iterator itbTransWeight = transformationWeight_[idxTrans].begin(), itTransWeight;
354    SrcToDstMap src2DstMap;
355    src2DstMap.rehash(std::ceil(transformationMapping_[idxTrans].size()/src2DstMap.max_load_factor()));
356
357    // Build mapping between global source element index and global destination element index.
358    boost::unordered_map<int,std::vector<size_t> >().swap(globalElementIndexOnProc_[elementPositionInGrid]);
359    std::set<int> tmpCounter;
360    itTransWeight = itbTransWeight;
361    for (itTransMap = itbTransMap; itTransMap != iteTransMap; ++itTransMap, ++itTransWeight)
362    {
363      const std::vector<int>& srcIndex = itTransMap->second;
364      const std::vector<double>& weight = itTransWeight->second;
365      for (idx = 0; idx < srcIndex.size(); ++idx)
366      {
367        src2DstMap[srcIndex[idx]].push_back(make_pair(itTransMap->first, weight[idx]));
368        if (0 == tmpCounter.count(srcIndex[idx]))
369        {         
370          tmpCounter.insert(srcIndex[idx]);
371       
372          for (int j = 0; j < procContainSrcElementIdx_.size(); ++j)
373            globalElementIndexOnProc_[elementPositionInGrid][procContainSrcElementIdx_[j]].push_back(srcIndex[idx]);
374        }
375      }
376    }
377 
378    if (!isTransPosEmpty)
379    {
380      for (idx = 0; idx < globalElementIndexOnProc_.size(); ++idx)
381      {
382        if (idx != elementPositionInGrid)
383        {
384          boost::unordered_map<int,std::vector<size_t> >::iterator itb = globalElementIndexOnProc_[idx].begin(), it,
385                                                                   ite = globalElementIndexOnProc_[idx].end();
386          for (it = itb; it != ite; ++it) it->second[0] = transPos(idxTrans);
387        }
388      }
389    }
390
391    // Ok, now compute global index of grid source and ones of grid destination
392    computeGlobalGridIndexMapping(elementPositionInGrid,
393                                  procContainSrcElementIdx_, //srcRank,
394                                  src2DstMap,
395                                  gridSrc,
396                                  gridDst,
397                                  globalElementIndexOnProc_,
398                                  globaIndexWeightFromSrcToDst);
399  } 
400 }
401
402/*!
403  Compute mapping of global index of grid source and grid destination
404  \param [in] elementPositionInGrid position of element in grid. E.x: grid composed of domain and axis, domain has position 0 and axis 1.
405  \param [in] srcRank rank of client from which we demand global index of element source
406  \param [in] src2DstMap mapping of global index of element source and global index of element destination
407  \param [in] gridSrc Grid source
408  \param [in] gridDst Grid destination
409  \param [in] globalElementIndexOnProc Global index of element source on different client rank
410  \param [out] globaIndexWeightFromSrcToDst Mapping of global index of grid source and grid destination
411*/
412void CGenericAlgorithmTransformation::computeGlobalGridIndexMapping(int elementPositionInGrid,
413                                                                   const std::vector<int>& srcRank,
414                                                                   boost::unordered_map<int, std::vector<std::pair<int,double> > >& src2DstMap,
415                                                                   CGrid* gridSrc,
416                                                                   CGrid* gridDst,
417                                                                   std::vector<boost::unordered_map<int,std::vector<size_t> > >& globalElementIndexOnProc,
418                                                                   SourceDestinationIndexMap& globaIndexWeightFromSrcToDst)
419{
420  SourceDestinationIndexMap globaIndexWeightFromSrcToDst_tmp ;
421 
422  CContext* context = CContext::getCurrent();
423  CContextClient* client=context->client;
424  int clientRank = client->clientRank;
425 
426  std::vector<CDomain*> domainListSrcP = gridSrc->getDomains();
427  std::vector<CAxis*> axisListSrcP = gridSrc->getAxis();
428  std::vector<CScalar*> scalarListSrcP = gridSrc->getScalars();
429  CArray<int,1> axisDomainSrcOrder = gridSrc->axis_domain_order;
430
431  size_t nbElement = axisDomainSrcOrder.numElements();
432  std::vector<size_t> nGlobSrc(nbElement);
433  size_t globalSrcSize = 1;
434  int domainIndex = 0, axisIndex = 0, scalarIndex = 0;
435  for (int idx = 0; idx < nbElement; ++idx)
436  {
437    nGlobSrc[idx] = globalSrcSize;
438    int elementDimension = axisDomainSrcOrder(idx);
439
440    // If this is a domain
441    if (2 == elementDimension)
442    {
443      globalSrcSize *= domainListSrcP[domainIndex]->nj_glo.getValue() * domainListSrcP[domainIndex]->ni_glo.getValue();
444      ++domainIndex;
445    }
446    else if (1 == elementDimension) // So it's an axis
447    {
448      globalSrcSize *= axisListSrcP[axisIndex]->n_glo.getValue();
449      ++axisIndex;
450    }
451    else
452    {
453      globalSrcSize *= 1;
454      ++scalarIndex;
455    }
456  }
457
458  std::vector<CDomain*> domainListDestP = gridDst->getDomains();
459  std::vector<CAxis*> axisListDestP = gridDst->getAxis();
460  std::vector<CScalar*> scalarListDestP = gridDst->getScalars();
461  CArray<int,1> axisDomainDstOrder = gridDst->axis_domain_order;
462
463  std::vector<size_t> nGlobDst(nbElement);
464  size_t globalDstSize = 1;
465  domainIndex = axisIndex = scalarIndex = 0;
466  set<size_t>  globalSrcStoreIndex ;
467 
468  for (int idx = 0; idx < nbElement; ++idx)
469  {
470    nGlobDst[idx] = globalDstSize;
471    int elementDimension = axisDomainDstOrder(idx);
472
473    // If this is a domain
474    if (2 == elementDimension)
475    {
476      globalDstSize *= domainListDestP[domainIndex]->nj_glo.getValue() * domainListDestP[domainIndex]->ni_glo.getValue();
477      ++domainIndex;
478    }
479    else if (1 == elementDimension) // So it's an axis
480    {
481      globalDstSize *= axisListDestP[axisIndex]->n_glo.getValue();
482      ++axisIndex;
483    }
484    else
485    {
486      globalDstSize *= 1;
487      ++scalarIndex;
488    }
489  }
490
491  std::map< std::pair<size_t,size_t>, int > rankMap ;
492  std::map< std::pair<size_t,size_t>, int >:: iterator rankMapIt ;
493 
494  for (int i = 0; i < srcRank.size(); ++i)
495  {
496    size_t ssize = 1;
497    int rankSrc = srcRank[i];
498    for (int idx = 0; idx < nbElement; ++idx)
499    {
500      ssize *= (globalElementIndexOnProc[idx][rankSrc]).size();
501    }
502
503    std::vector<int> idxLoop(nbElement,0);
504    std::vector<int> currentIndexSrc(nbElement, 0);
505    std::vector<int> currentIndexDst(nbElement, 0);
506    int innnerLoopSize = (globalElementIndexOnProc[0])[rankSrc].size();
507    size_t idx = 0;
508    while (idx < ssize)
509    {
510      for (int ind = 0; ind < nbElement; ++ind)
511      {
512        if (idxLoop[ind] == (globalElementIndexOnProc[ind])[rankSrc].size())
513        {
514          idxLoop[ind] = 0;
515          ++idxLoop[ind+1];
516        }
517
518        currentIndexDst[ind] = currentIndexSrc[ind] = (globalElementIndexOnProc[ind])[rankSrc][idxLoop[ind]];
519      }
520
521      for (int ind = 0; ind < innnerLoopSize; ++ind)
522      {
523        currentIndexDst[0] = currentIndexSrc[0] = (globalElementIndexOnProc[0])[rankSrc][ind];
524        int globalElementDstIndexSize = 0;
525        if (1 == src2DstMap.count(currentIndexSrc[elementPositionInGrid]))
526        {
527          globalElementDstIndexSize = src2DstMap[currentIndexSrc[elementPositionInGrid]].size();
528        }
529
530        std::vector<size_t> globalDstVecIndex(globalElementDstIndexSize,0);
531        size_t globalSrcIndex = 0;
532        for (int idxElement = 0; idxElement < nbElement; ++idxElement)
533        {
534          if (idxElement == elementPositionInGrid)
535          {
536            for (int k = 0; k < globalElementDstIndexSize; ++k)
537            {
538              globalDstVecIndex[k] += src2DstMap[currentIndexSrc[elementPositionInGrid]][k].first * nGlobDst[idxElement];
539            }
540          }
541          else
542          {
543            for (int k = 0; k < globalElementDstIndexSize; ++k)
544            {
545              globalDstVecIndex[k] += currentIndexDst[idxElement] * nGlobDst[idxElement];
546            }
547          }
548          globalSrcIndex += currentIndexSrc[idxElement] * nGlobSrc[idxElement];
549        }
550
551        for (int k = 0; k < globalElementDstIndexSize; ++k)
552        {
553         
554          globaIndexWeightFromSrcToDst_tmp[rankSrc][globalSrcIndex].push_back(make_pair(globalDstVecIndex[k],src2DstMap[currentIndexSrc[elementPositionInGrid]][k].second ));
555          rankMapIt=rankMap.find(make_pair(globalSrcIndex,globalDstVecIndex[k])) ;
556          if (rankMapIt==rankMap.end()) rankMap[make_pair(globalSrcIndex,globalDstVecIndex[k])] = rankSrc ;
557          else if (rankSrc==clientRank) rankMapIt->second = rankSrc ;
558        }
559        ++idxLoop[0];
560      }
561      idx += innnerLoopSize;
562    }
563  }
564
565  // eliminate redondant global src point owned by differrent processes.
566  // Avoid as possible to tranfer data from an other process if the src point is also owned by current process
567      int rankSrc ;
568      size_t globalSrcIndex ;
569      size_t globalDstIndex ;
570      double weight ;
571 
572      SourceDestinationIndexMap::iterator rankIt,rankIte ;
573      boost::unordered_map<size_t, std::vector<std::pair<size_t,double> > >::iterator globalSrcIndexIt, globalSrcIndexIte ;
574      std::vector<std::pair<size_t,double> >::iterator vectIt,vectIte ;
575   
576      rankIt=globaIndexWeightFromSrcToDst_tmp.begin() ; rankIte=globaIndexWeightFromSrcToDst_tmp.end() ;
577      for(;rankIt!=rankIte;++rankIt)
578      {
579        rankSrc = rankIt->first ;
580        globalSrcIndexIt = rankIt->second.begin() ; globalSrcIndexIte = rankIt->second.end() ;
581        for(;globalSrcIndexIt!=globalSrcIndexIte;++globalSrcIndexIt)
582        { 
583          globalSrcIndex = globalSrcIndexIt->first ;
584          vectIt = globalSrcIndexIt->second.begin() ; vectIte = globalSrcIndexIt->second.end() ;
585          for(vectIt; vectIt!=vectIte; vectIt++)
586          {
587            globalDstIndex = vectIt->first ;
588            weight = vectIt->second ;
589            if (eliminateRedondantSrc_)
590            {
591              if (rankMap[make_pair(globalSrcIndex,globalDstIndex)] == rankSrc) 
592                globaIndexWeightFromSrcToDst[rankSrc][globalSrcIndex].push_back(make_pair(globalDstIndex,weight)) ;
593            }
594            else globaIndexWeightFromSrcToDst[rankSrc][globalSrcIndex].push_back(make_pair(globalDstIndex,weight)) ;
595         }
596       }
597     }
598
599}
600
601/*!
602  Find out proc and global index of axis source which axis destination is on demande
603  \param[in] scalar Scalar destination
604  \param[in] scalar Scalar source
605  \param[in] destGlobalIndexPositionInGrid Relative position of axis corresponds to other element of grid.
606  \param[out] globalScalarIndexOnProc Global index of axis source on different procs
607*/
608void CGenericAlgorithmTransformation::computeExchangeScalarIndex(CScalar* scalarDst,
609                                                                 CScalar* scalarSrc,
610                                                                 CArray<size_t,1>& destGlobalIndexPositionInGrid,
611                                                                 boost::unordered_map<int,std::vector<size_t> >& globalScalarIndexOnProc)
612{
613  CContext* context = CContext::getCurrent();
614  CContextClient* client=context->client;
615  int clientRank = client->clientRank;
616  int clientSize = client->clientSize;
617
618  globalScalarIndexOnProc.rehash(std::ceil(clientSize/globalScalarIndexOnProc.max_load_factor()));
619  for (int idx = 0; idx < clientSize; ++idx)
620  {
621    globalScalarIndexOnProc[idx].push_back(0);
622  }
623}
624
625/*!
626  Find out proc and global index of axis source which axis destination is on demande
627  \param[in] axisDst Axis destination
628  \param[in] axisSrc Axis source
629  \param[in] destGlobalIndexPositionInGrid Relative position of axis corresponds to other element of grid.
630  \param[out] globalAxisIndexOnProc Global index of axis source on different procs
631*/
632void CGenericAlgorithmTransformation::computeExchangeAxisIndex(CAxis* axisDst,
633                                                               CAxis* axisSrc,
634                                                               CArray<size_t,1>& destGlobalIndexPositionInGrid,
635                                                               boost::unordered_map<int,std::vector<size_t> >& globalAxisIndexOnProc)
636{
637  CContext* context = CContext::getCurrent();
638  CContextClient* client=context->client;
639  int clientRank = client->clientRank;
640  int clientSize = client->clientSize;
641
642  size_t globalIndex;
643  int nIndexSize = axisSrc->index.numElements();
644  CClientClientDHTInt::Index2VectorInfoTypeMap globalIndex2ProcRank;
645  globalIndex2ProcRank.rehash(std::ceil(nIndexSize/globalIndex2ProcRank.max_load_factor()));
646  for (int idx = 0; idx < nIndexSize; ++idx)
647  {
648    globalIndex = axisSrc->index(idx);
649    globalIndex2ProcRank[globalIndex].push_back(clientRank);
650  }
651
652  CClientClientDHTInt dhtIndexProcRank(globalIndex2ProcRank, client->intraComm);
653  CArray<size_t,1> globalAxisIndex(axisDst->index.numElements());
654  for (int idx = 0; idx < globalAxisIndex.numElements(); ++idx)
655  {
656    globalAxisIndex(idx) = axisDst->index(idx);
657  }
658  dhtIndexProcRank.computeIndexInfoMapping(globalAxisIndex);
659
660  std::vector<int> countIndex(clientSize,0);
661  const CClientClientDHTInt::Index2VectorInfoTypeMap& computedGlobalIndexOnProc = dhtIndexProcRank.getInfoIndexMap();
662  CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = computedGlobalIndexOnProc.begin(), it,
663                                                               ite = computedGlobalIndexOnProc.end();
664  for (it = itb; it != ite; ++it)
665  {
666    const std::vector<int>& procList = it->second;
667    for (int idx = 0; idx < procList.size(); ++idx) ++countIndex[procList[idx]];
668  }
669
670  globalAxisIndexOnProc.rehash(std::ceil(clientSize/globalAxisIndexOnProc.max_load_factor()));
671  for (int idx = 0; idx < clientSize; ++idx)
672  {
673    if (0 != countIndex[idx])
674    {
675      globalAxisIndexOnProc[idx].resize(countIndex[idx]);
676      countIndex[idx] = 0;
677    }
678  }
679
680  for (it = itb; it != ite; ++it)
681  {
682    const std::vector<int>& procList = it->second;
683    for (int idx = 0; idx < procList.size(); ++idx)
684    {
685      globalAxisIndexOnProc[procList[idx]][countIndex[procList[idx]]] = it->first;
686      ++countIndex[procList[idx]];
687    }
688  }
689}
690
691/*!
692  Find out proc and global index of domain source which domain destination is on demande
693  \param[in] domainDst Domain destination
694  \param[in] domainSrc Domain source
695  \param[in] destGlobalIndexPositionInGrid Relative position of domain corresponds to other element of grid.
696  \param[out] globalDomainIndexOnProc Global index of domain source on different procs
697*/
698void CGenericAlgorithmTransformation::computeExchangeDomainIndex(CDomain* domainDst,
699                                                                 CDomain* domainSrc,
700                                                                 CArray<size_t,1>& destGlobalIndexPositionInGrid,
701                                                                 boost::unordered_map<int,std::vector<size_t> >& globalDomainIndexOnProc)
702{
703  CContext* context = CContext::getCurrent();
704  CContextClient* client=context->client;
705  int clientRank = client->clientRank;
706  int clientSize = client->clientSize;
707
708  int niGlobSrc = domainSrc->ni_glo.getValue();
709  size_t globalIndex;
710  int i_ind, j_ind;
711  int nIndexSize = (destGlobalIndexPositionInGrid.isEmpty()) ? domainSrc->i_index.numElements()
712                                                             : destGlobalIndexPositionInGrid.numElements();
713  CClientClientDHTInt::Index2VectorInfoTypeMap globalIndex2ProcRank;
714  globalIndex2ProcRank.rehash(std::ceil(nIndexSize/globalIndex2ProcRank.max_load_factor()));
715  if (destGlobalIndexPositionInGrid.isEmpty())
716  {
717    for (int idx = 0; idx < nIndexSize; ++idx)
718    {
719      i_ind=domainSrc->i_index(idx) ;
720      j_ind=domainSrc->j_index(idx) ;
721
722      globalIndex = i_ind + j_ind * niGlobSrc;
723      globalIndex2ProcRank[globalIndex].resize(1);
724      globalIndex2ProcRank[globalIndex][0] = clientRank;
725    }
726  }
727  else
728  {
729    for (int idx = 0; idx < nIndexSize; ++idx)
730    {
731      globalIndex2ProcRank[destGlobalIndexPositionInGrid(idx)].push_back(clientRank);
732    }
733  }
734
735  CArray<size_t,1> globalDomainIndex;
736  if (destGlobalIndexPositionInGrid.isEmpty())
737  {
738    int niGlobDst = domainDst->ni_glo.getValue();
739    globalDomainIndex.resize(domainDst->i_index.numElements());
740    nIndexSize = domainDst->i_index.numElements();
741
742    for (int idx = 0; idx < nIndexSize; ++idx)
743    {
744      i_ind=domainDst->i_index(idx) ;
745      j_ind=domainDst->j_index(idx) ;
746
747      globalDomainIndex(idx) = i_ind + j_ind * niGlobDst;
748    }
749  }
750  else
751  {
752    globalDomainIndex.reference(destGlobalIndexPositionInGrid);
753  }
754
755  CClientClientDHTInt dhtIndexProcRank(globalIndex2ProcRank, client->intraComm);
756  dhtIndexProcRank.computeIndexInfoMapping(globalDomainIndex);
757
758  std::vector<int> countIndex(clientSize,0);
759  const CClientClientDHTInt::Index2VectorInfoTypeMap& computedGlobalIndexOnProc = dhtIndexProcRank.getInfoIndexMap();
760  CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = computedGlobalIndexOnProc.begin(), it,
761                                                               ite = computedGlobalIndexOnProc.end();
762  for (it = itb; it != ite; ++it)
763  {
764    const std::vector<int>& procList = it->second;
765    for (int idx = 0; idx < procList.size(); ++idx) ++countIndex[procList[idx]];
766  }
767
768  globalDomainIndexOnProc.rehash(std::ceil(clientSize/globalDomainIndexOnProc.max_load_factor()));
769  for (int idx = 0; idx < clientSize; ++idx)
770  {
771    if (0 != countIndex[idx])
772    {
773      globalDomainIndexOnProc[idx].resize(countIndex[idx]);
774      countIndex[idx] = 0;
775    }
776  }
777
778  for (it = itb; it != ite; ++it)
779  {
780    const std::vector<int>& procList = it->second;
781    for (int idx = 0; idx < procList.size(); ++idx)
782    {
783      globalDomainIndexOnProc[procList[idx]][countIndex[procList[idx]]] = it->first;
784      ++countIndex[procList[idx]];
785    }
786  }
787}
788
789/*!
790  Compute index mapping between element source and element destination with an auxiliary inputs which determine
791position of each mapped index in global index of grid destination.
792  \param [in] dataAuxInputs auxiliary inputs
793*/
794void CGenericAlgorithmTransformation::computeIndexSourceMapping(const std::vector<CArray<double,1>* >& dataAuxInputs)
795{
796  computeIndexSourceMapping_(dataAuxInputs);
797}
798
799std::vector<StdString> CGenericAlgorithmTransformation::getIdAuxInputs()
800{
801  return idAuxInputs_;
802}
803
804CGenericAlgorithmTransformation::AlgoTransType CGenericAlgorithmTransformation::type()
805{
806  return type_;
807}
808
809}
Note: See TracBrowser for help on using the repository browser.