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

Last change on this file since 1297 was 1274, checked in by ymipsl, 7 years ago

Improvement for spatial transformations : when axis or domain overlapping in source grid, transformation eliminate redondant global point, and choose if possible, point owned by current process.

YM

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