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

Last change on this file since 1301 was 1298, checked in by ymipsl, 7 years ago

Bug fix for generic transformation. By default redondant source points are now correctly eliminated from transformation.

YM

File size: 30.1 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    if (!computedProcSrcNonTransformedElement_)
258    {
259      for (idx = 0; idx < globalElementIndexOnProc_.size(); ++idx)
260      {
261        if (idx != elementPositionInGrid)
262        {
263          boost::unordered_map<int,std::vector<size_t> >::iterator itb = globalElementIndexOnProc_[idx].begin(), it,
264                                                                   ite = globalElementIndexOnProc_[idx].end();
265          for (it = itb; it != ite; ++it) procOfNonTransformedElements_.insert(it->first);
266          if (procOfNonTransformedElements_.size() == nbClient)
267            break;
268        }
269      }
270    }
271   
272    // Processes contain the source index of transformed element
273    std::set<int> procOfTransformedElement; 
274    CClientClientDHTInt::Index2VectorInfoTypeMap::iterator itIdxb = globalIndexOfTransformedElementOnProc.begin(),
275                                                           itIdxe = globalIndexOfTransformedElementOnProc.end(), itIdx;
276    for (itIdx = itIdxb; itIdx != itIdxe; ++itIdx)
277    {
278      std::vector<int>& tmp = itIdx->second;
279      for (int i = 0; i < tmp.size(); ++i)
280        procOfTransformedElement.insert(tmp[i]);
281      if (tmp.size() == nbClient)
282        break;
283    }                                                           
284   
285    std::set<int>& commonProc = (procOfTransformedElement.size() < procOfNonTransformedElements_.size()) ? procOfTransformedElement
286                              : (!procOfNonTransformedElements_.empty() ? procOfNonTransformedElements_ : procOfTransformedElement);
287   
288    std::vector<int> procContainSrcElementIdx(commonProc.size());
289    int count = 0;
290    for (std::set<int>::iterator it = commonProc.begin(); it != commonProc.end(); ++it)
291      procContainSrcElementIdx[count++] = *it;
292
293    procContainSrcElementIdx_.swap(procContainSrcElementIdx);   
294
295        // For the first time, surely we calculate proc containing non transformed elements
296    if (!computedProcSrcNonTransformedElement_)
297      computedProcSrcNonTransformedElement_ = true;
298  }
299 
300  for (size_t idxTrans = 0; idxTrans < transformationMapping_.size(); ++idxTrans)
301  {
302    TransformationIndexMap::const_iterator itbTransMap = transformationMapping_[idxTrans].begin(), itTransMap,
303                                           iteTransMap = transformationMapping_[idxTrans].end();
304    TransformationWeightMap::const_iterator itbTransWeight = transformationWeight_[idxTrans].begin(), itTransWeight;
305    SrcToDstMap src2DstMap;
306    src2DstMap.rehash(std::ceil(transformationMapping_[idxTrans].size()/src2DstMap.max_load_factor()));
307
308    // Build mapping between global source element index and global destination element index.
309    boost::unordered_map<int,std::vector<size_t> >().swap(globalElementIndexOnProc_[elementPositionInGrid]);
310    std::set<int> tmpCounter;
311    itTransWeight = itbTransWeight;
312    for (itTransMap = itbTransMap; itTransMap != iteTransMap; ++itTransMap, ++itTransWeight)
313    {
314      const std::vector<int>& srcIndex = itTransMap->second;
315      const std::vector<double>& weight = itTransWeight->second;
316      for (idx = 0; idx < srcIndex.size(); ++idx)
317      {
318        src2DstMap[srcIndex[idx]].push_back(make_pair(itTransMap->first, weight[idx]));
319        if (0 == tmpCounter.count(srcIndex[idx]))
320        {         
321          tmpCounter.insert(srcIndex[idx]);
322
323           std::vector<int>& srcProc = globalIndexOfTransformedElementOnProc[srcIndex[idx]];
324           for (int j = 0; j < srcProc.size(); ++j)
325              globalElementIndexOnProc_[elementPositionInGrid][srcProc[j]].push_back(srcIndex[idx]);
326/*         
327          for (int j = 0; j < procContainSrcElementIdx_.size(); ++j)
328            globalElementIndexOnProc_[elementPositionInGrid][procContainSrcElementIdx_[j]].push_back(srcIndex[idx]);*/
329        }
330      }
331    }
332 
333    if (!isTransPosEmpty)
334    {
335      for (idx = 0; idx < globalElementIndexOnProc_.size(); ++idx)
336      {
337        if (idx != elementPositionInGrid)
338        {
339          boost::unordered_map<int,std::vector<size_t> >::iterator itb = globalElementIndexOnProc_[idx].begin(), it,
340                                                                   ite = globalElementIndexOnProc_[idx].end();
341          for (it = itb; it != ite; ++it) it->second[0] = transPos(idxTrans);
342        }
343      }
344    }
345
346    // Ok, now compute global index of grid source and ones of grid destination
347    computeGlobalGridIndexMapping(elementPositionInGrid,
348                                  procContainSrcElementIdx_, //srcRank,
349                                  src2DstMap,
350                                  gridSrc,
351                                  gridDst,
352                                  globalElementIndexOnProc_,
353                                  globaIndexWeightFromSrcToDst);
354  } 
355 }
356
357/*!
358  Compute mapping of global index of grid source and grid destination
359  \param [in] elementPositionInGrid position of element in grid. E.x: grid composed of domain and axis, domain has position 0 and axis 1.
360  \param [in] srcRank rank of client from which we demand global index of element source
361  \param [in] src2DstMap mapping of global index of element source and global index of element destination
362  \param [in] gridSrc Grid source
363  \param [in] gridDst Grid destination
364  \param [in] globalElementIndexOnProc Global index of element source on different client rank
365  \param [out] globaIndexWeightFromSrcToDst Mapping of global index of grid source and grid destination
366*/
367void CGenericAlgorithmTransformation::computeGlobalGridIndexMapping(int elementPositionInGrid,
368                                                                   const std::vector<int>& srcRank,
369                                                                   boost::unordered_map<int, std::vector<std::pair<int,double> > >& src2DstMap,
370                                                                   CGrid* gridSrc,
371                                                                   CGrid* gridDst,
372                                                                   std::vector<boost::unordered_map<int,std::vector<size_t> > >& globalElementIndexOnProc,
373                                                                   SourceDestinationIndexMap& globaIndexWeightFromSrcToDst)
374{
375  SourceDestinationIndexMap globaIndexWeightFromSrcToDst_tmp ;
376 
377  CContext* context = CContext::getCurrent();
378  CContextClient* client=context->client;
379  int clientRank = client->clientRank;
380 
381  std::vector<CDomain*> domainListSrcP = gridSrc->getDomains();
382  std::vector<CAxis*> axisListSrcP = gridSrc->getAxis();
383  std::vector<CScalar*> scalarListSrcP = gridSrc->getScalars();
384  CArray<int,1> axisDomainSrcOrder = gridSrc->axis_domain_order;
385
386  size_t nbElement = axisDomainSrcOrder.numElements();
387  std::vector<size_t> nGlobSrc(nbElement);
388  size_t globalSrcSize = 1;
389  int domainIndex = 0, axisIndex = 0, scalarIndex = 0;
390  for (int idx = 0; idx < nbElement; ++idx)
391  {
392    nGlobSrc[idx] = globalSrcSize;
393    int elementDimension = axisDomainSrcOrder(idx);
394
395    // If this is a domain
396    if (2 == elementDimension)
397    {
398      globalSrcSize *= domainListSrcP[domainIndex]->nj_glo.getValue() * domainListSrcP[domainIndex]->ni_glo.getValue();
399      ++domainIndex;
400    }
401    else if (1 == elementDimension) // So it's an axis
402    {
403      globalSrcSize *= axisListSrcP[axisIndex]->n_glo.getValue();
404      ++axisIndex;
405    }
406    else
407    {
408      globalSrcSize *= 1;
409      ++scalarIndex;
410    }
411  }
412
413  std::vector<CDomain*> domainListDestP = gridDst->getDomains();
414  std::vector<CAxis*> axisListDestP = gridDst->getAxis();
415  std::vector<CScalar*> scalarListDestP = gridDst->getScalars();
416  CArray<int,1> axisDomainDstOrder = gridDst->axis_domain_order;
417
418  std::vector<size_t> nGlobDst(nbElement);
419  size_t globalDstSize = 1;
420  domainIndex = axisIndex = scalarIndex = 0;
421  set<size_t>  globalSrcStoreIndex ;
422 
423  for (int idx = 0; idx < nbElement; ++idx)
424  {
425    nGlobDst[idx] = globalDstSize;
426    int elementDimension = axisDomainDstOrder(idx);
427
428    // If this is a domain
429    if (2 == elementDimension)
430    {
431      globalDstSize *= domainListDestP[domainIndex]->nj_glo.getValue() * domainListDestP[domainIndex]->ni_glo.getValue();
432      ++domainIndex;
433    }
434    else if (1 == elementDimension) // So it's an axis
435    {
436      globalDstSize *= axisListDestP[axisIndex]->n_glo.getValue();
437      ++axisIndex;
438    }
439    else
440    {
441      globalDstSize *= 1;
442      ++scalarIndex;
443    }
444  }
445
446  std::map< std::pair<size_t,size_t>, int > rankMap ;
447  std::map< std::pair<size_t,size_t>, int >:: iterator rankMapIt ;
448 
449  for (int i = 0; i < srcRank.size(); ++i)
450  {
451    size_t ssize = 1;
452    int rankSrc = srcRank[i];
453    for (int idx = 0; idx < nbElement; ++idx)
454    {
455      ssize *= (globalElementIndexOnProc[idx][rankSrc]).size();
456    }
457
458    std::vector<int> idxLoop(nbElement,0);
459    std::vector<int> currentIndexSrc(nbElement, 0);
460    std::vector<int> currentIndexDst(nbElement, 0);
461    int innnerLoopSize = (globalElementIndexOnProc[0])[rankSrc].size();
462    size_t idx = 0;
463    while (idx < ssize)
464    {
465      for (int ind = 0; ind < nbElement; ++ind)
466      {
467        if (idxLoop[ind] == (globalElementIndexOnProc[ind])[rankSrc].size())
468        {
469          idxLoop[ind] = 0;
470          ++idxLoop[ind+1];
471        }
472
473        currentIndexDst[ind] = currentIndexSrc[ind] = (globalElementIndexOnProc[ind])[rankSrc][idxLoop[ind]];
474      }
475
476      for (int ind = 0; ind < innnerLoopSize; ++ind)
477      {
478        currentIndexDst[0] = currentIndexSrc[0] = (globalElementIndexOnProc[0])[rankSrc][ind];
479        int globalElementDstIndexSize = 0;
480        if (1 == src2DstMap.count(currentIndexSrc[elementPositionInGrid]))
481        {
482          globalElementDstIndexSize = src2DstMap[currentIndexSrc[elementPositionInGrid]].size();
483        }
484
485        std::vector<size_t> globalDstVecIndex(globalElementDstIndexSize,0);
486        size_t globalSrcIndex = 0;
487        for (int idxElement = 0; idxElement < nbElement; ++idxElement)
488        {
489          if (idxElement == elementPositionInGrid)
490          {
491            for (int k = 0; k < globalElementDstIndexSize; ++k)
492            {
493              globalDstVecIndex[k] += src2DstMap[currentIndexSrc[elementPositionInGrid]][k].first * nGlobDst[idxElement];
494            }
495          }
496          else
497          {
498            for (int k = 0; k < globalElementDstIndexSize; ++k)
499            {
500              globalDstVecIndex[k] += currentIndexDst[idxElement] * nGlobDst[idxElement];
501            }
502          }
503          globalSrcIndex += currentIndexSrc[idxElement] * nGlobSrc[idxElement];
504        }
505
506        for (int k = 0; k < globalElementDstIndexSize; ++k)
507        {
508         
509          globaIndexWeightFromSrcToDst_tmp[rankSrc][globalSrcIndex].push_back(make_pair(globalDstVecIndex[k],src2DstMap[currentIndexSrc[elementPositionInGrid]][k].second ));
510          rankMapIt=rankMap.find(make_pair(globalSrcIndex,globalDstVecIndex[k])) ;
511          if (rankMapIt==rankMap.end()) rankMap[make_pair(globalSrcIndex,globalDstVecIndex[k])] = rankSrc ;
512          else if (rankSrc==clientRank) rankMapIt->second = rankSrc ;
513        }
514        ++idxLoop[0];
515      }
516      idx += innnerLoopSize;
517    }
518  }
519
520  // eliminate redondant global src point owned by differrent processes.
521  // Avoid as possible to tranfer data from an other process if the src point is also owned by current process
522      int rankSrc ;
523      size_t globalSrcIndex ;
524      size_t globalDstIndex ;
525      double weight ;
526 
527      SourceDestinationIndexMap::iterator rankIt,rankIte ;
528      boost::unordered_map<size_t, std::vector<std::pair<size_t,double> > >::iterator globalSrcIndexIt, globalSrcIndexIte ;
529      std::vector<std::pair<size_t,double> >::iterator vectIt,vectIte ;
530   
531      rankIt=globaIndexWeightFromSrcToDst_tmp.begin() ; rankIte=globaIndexWeightFromSrcToDst_tmp.end() ;
532      for(;rankIt!=rankIte;++rankIt)
533      {
534        rankSrc = rankIt->first ;
535        globalSrcIndexIt = rankIt->second.begin() ; globalSrcIndexIte = rankIt->second.end() ;
536        for(;globalSrcIndexIt!=globalSrcIndexIte;++globalSrcIndexIt)
537        { 
538          globalSrcIndex = globalSrcIndexIt->first ;
539          vectIt = globalSrcIndexIt->second.begin() ; vectIte = globalSrcIndexIt->second.end() ;
540          for(vectIt; vectIt!=vectIte; vectIt++)
541          {
542            globalDstIndex = vectIt->first ;
543            weight = vectIt->second ;
544            if (eliminateRedondantSrc_)
545            {
546              if (rankMap[make_pair(globalSrcIndex,globalDstIndex)] == rankSrc) 
547                globaIndexWeightFromSrcToDst[rankSrc][globalSrcIndex].push_back(make_pair(globalDstIndex,weight)) ;
548            }
549            else globaIndexWeightFromSrcToDst[rankSrc][globalSrcIndex].push_back(make_pair(globalDstIndex,weight)) ;
550         }
551       }
552     }
553
554}
555
556/*!
557  Find out proc and global index of axis source which axis destination is on demande
558  \param[in] scalar Scalar destination
559  \param[in] scalar Scalar source
560  \param[in] destGlobalIndexPositionInGrid Relative position of axis corresponds to other element of grid.
561  \param[out] globalScalarIndexOnProc Global index of axis source on different procs
562*/
563void CGenericAlgorithmTransformation::computeExchangeScalarIndex(CScalar* scalarDst,
564                                                                 CScalar* scalarSrc,
565                                                                 CArray<size_t,1>& destGlobalIndexPositionInGrid,
566                                                                 boost::unordered_map<int,std::vector<size_t> >& globalScalarIndexOnProc)
567{
568  CContext* context = CContext::getCurrent();
569  CContextClient* client=context->client;
570  int clientRank = client->clientRank;
571  int clientSize = client->clientSize;
572
573  globalScalarIndexOnProc.rehash(std::ceil(clientSize/globalScalarIndexOnProc.max_load_factor()));
574  for (int idx = 0; idx < clientSize; ++idx)
575  {
576    globalScalarIndexOnProc[idx].push_back(0);
577  }
578}
579
580/*!
581  Find out proc and global index of axis source which axis destination is on demande
582  \param[in] axisDst Axis destination
583  \param[in] axisSrc Axis source
584  \param[in] destGlobalIndexPositionInGrid Relative position of axis corresponds to other element of grid.
585  \param[out] globalAxisIndexOnProc Global index of axis source on different procs
586*/
587void CGenericAlgorithmTransformation::computeExchangeAxisIndex(CAxis* axisDst,
588                                                               CAxis* axisSrc,
589                                                               CArray<size_t,1>& destGlobalIndexPositionInGrid,
590                                                               boost::unordered_map<int,std::vector<size_t> >& globalAxisIndexOnProc)
591{
592  CContext* context = CContext::getCurrent();
593  CContextClient* client=context->client;
594  int clientRank = client->clientRank;
595  int clientSize = client->clientSize;
596
597  size_t globalIndex;
598  int nIndexSize = axisSrc->index.numElements();
599  CClientClientDHTInt::Index2VectorInfoTypeMap globalIndex2ProcRank;
600  globalIndex2ProcRank.rehash(std::ceil(nIndexSize/globalIndex2ProcRank.max_load_factor()));
601  for (int idx = 0; idx < nIndexSize; ++idx)
602  {
603    globalIndex = axisSrc->index(idx);
604    globalIndex2ProcRank[globalIndex].push_back(clientRank);
605  }
606
607  CClientClientDHTInt dhtIndexProcRank(globalIndex2ProcRank, client->intraComm);
608  CArray<size_t,1> globalAxisIndex(axisDst->index.numElements());
609  for (int idx = 0; idx < globalAxisIndex.numElements(); ++idx)
610  {
611    globalAxisIndex(idx) = axisDst->index(idx);
612  }
613  dhtIndexProcRank.computeIndexInfoMapping(globalAxisIndex);
614
615  std::vector<int> countIndex(clientSize,0);
616  const CClientClientDHTInt::Index2VectorInfoTypeMap& computedGlobalIndexOnProc = dhtIndexProcRank.getInfoIndexMap();
617  CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = computedGlobalIndexOnProc.begin(), it,
618                                                               ite = computedGlobalIndexOnProc.end();
619  for (it = itb; it != ite; ++it)
620  {
621    const std::vector<int>& procList = it->second;
622    for (int idx = 0; idx < procList.size(); ++idx) ++countIndex[procList[idx]];
623  }
624
625  globalAxisIndexOnProc.rehash(std::ceil(clientSize/globalAxisIndexOnProc.max_load_factor()));
626  for (int idx = 0; idx < clientSize; ++idx)
627  {
628    if (0 != countIndex[idx])
629    {
630      globalAxisIndexOnProc[idx].resize(countIndex[idx]);
631      countIndex[idx] = 0;
632    }
633  }
634
635  for (it = itb; it != ite; ++it)
636  {
637    const std::vector<int>& procList = it->second;
638    for (int idx = 0; idx < procList.size(); ++idx)
639    {
640      globalAxisIndexOnProc[procList[idx]][countIndex[procList[idx]]] = it->first;
641      ++countIndex[procList[idx]];
642    }
643  }
644}
645
646/*!
647  Find out proc and global index of domain source which domain destination is on demande
648  \param[in] domainDst Domain destination
649  \param[in] domainSrc Domain source
650  \param[in] destGlobalIndexPositionInGrid Relative position of domain corresponds to other element of grid.
651  \param[out] globalDomainIndexOnProc Global index of domain source on different procs
652*/
653void CGenericAlgorithmTransformation::computeExchangeDomainIndex(CDomain* domainDst,
654                                                                 CDomain* domainSrc,
655                                                                 CArray<size_t,1>& destGlobalIndexPositionInGrid,
656                                                                 boost::unordered_map<int,std::vector<size_t> >& globalDomainIndexOnProc)
657{
658  CContext* context = CContext::getCurrent();
659  CContextClient* client=context->client;
660  int clientRank = client->clientRank;
661  int clientSize = client->clientSize;
662
663  int niGlobSrc = domainSrc->ni_glo.getValue();
664  size_t globalIndex;
665  int i_ind, j_ind;
666  int nIndexSize = (destGlobalIndexPositionInGrid.isEmpty()) ? domainSrc->i_index.numElements()
667                                                             : destGlobalIndexPositionInGrid.numElements();
668  CClientClientDHTInt::Index2VectorInfoTypeMap globalIndex2ProcRank;
669  globalIndex2ProcRank.rehash(std::ceil(nIndexSize/globalIndex2ProcRank.max_load_factor()));
670  if (destGlobalIndexPositionInGrid.isEmpty())
671  {
672    for (int idx = 0; idx < nIndexSize; ++idx)
673    {
674      i_ind=domainSrc->i_index(idx) ;
675      j_ind=domainSrc->j_index(idx) ;
676
677      globalIndex = i_ind + j_ind * niGlobSrc;
678      globalIndex2ProcRank[globalIndex].resize(1);
679      globalIndex2ProcRank[globalIndex][0] = clientRank;
680    }
681  }
682  else
683  {
684    for (int idx = 0; idx < nIndexSize; ++idx)
685    {
686      globalIndex2ProcRank[destGlobalIndexPositionInGrid(idx)].push_back(clientRank);
687    }
688  }
689
690  CArray<size_t,1> globalDomainIndex;
691  if (destGlobalIndexPositionInGrid.isEmpty())
692  {
693    int niGlobDst = domainDst->ni_glo.getValue();
694    globalDomainIndex.resize(domainDst->i_index.numElements());
695    nIndexSize = domainDst->i_index.numElements();
696
697    for (int idx = 0; idx < nIndexSize; ++idx)
698    {
699      i_ind=domainDst->i_index(idx) ;
700      j_ind=domainDst->j_index(idx) ;
701
702      globalDomainIndex(idx) = i_ind + j_ind * niGlobDst;
703    }
704  }
705  else
706  {
707    globalDomainIndex.reference(destGlobalIndexPositionInGrid);
708  }
709
710  CClientClientDHTInt dhtIndexProcRank(globalIndex2ProcRank, client->intraComm);
711  dhtIndexProcRank.computeIndexInfoMapping(globalDomainIndex);
712
713  std::vector<int> countIndex(clientSize,0);
714  const CClientClientDHTInt::Index2VectorInfoTypeMap& computedGlobalIndexOnProc = dhtIndexProcRank.getInfoIndexMap();
715  CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = computedGlobalIndexOnProc.begin(), it,
716                                                               ite = computedGlobalIndexOnProc.end();
717  for (it = itb; it != ite; ++it)
718  {
719    const std::vector<int>& procList = it->second;
720    for (int idx = 0; idx < procList.size(); ++idx) ++countIndex[procList[idx]];
721  }
722
723  globalDomainIndexOnProc.rehash(std::ceil(clientSize/globalDomainIndexOnProc.max_load_factor()));
724  for (int idx = 0; idx < clientSize; ++idx)
725  {
726    if (0 != countIndex[idx])
727    {
728      globalDomainIndexOnProc[idx].resize(countIndex[idx]);
729      countIndex[idx] = 0;
730    }
731  }
732
733  for (it = itb; it != ite; ++it)
734  {
735    const std::vector<int>& procList = it->second;
736    for (int idx = 0; idx < procList.size(); ++idx)
737    {
738      globalDomainIndexOnProc[procList[idx]][countIndex[procList[idx]]] = it->first;
739      ++countIndex[procList[idx]];
740    }
741  }
742}
743
744/*!
745  Compute index mapping between element source and element destination with an auxiliary inputs which determine
746position of each mapped index in global index of grid destination.
747  \param [in] dataAuxInputs auxiliary inputs
748*/
749void CGenericAlgorithmTransformation::computeIndexSourceMapping(const std::vector<CArray<double,1>* >& dataAuxInputs)
750{
751  computeIndexSourceMapping_(dataAuxInputs);
752}
753
754std::vector<StdString> CGenericAlgorithmTransformation::getIdAuxInputs()
755{
756  return idAuxInputs_;
757}
758
759CGenericAlgorithmTransformation::AlgoTransType CGenericAlgorithmTransformation::type()
760{
761  return type_;
762}
763
764}
Note: See TracBrowser for help on using the repository browser.