source: XIOS/trunk/src/transformation/domain_algorithm_interpolate.cpp @ 880

Last change on this file since 880 was 880, checked in by ymipsl, 8 years ago

Interpolation : solve issue with indexed mesh definition.

YM

File size: 23.9 KB
Line 
1/*!
2   \file domain_algorithm_interpolate_from_file.cpp
3   \author Ha NGUYEN
4   \since 09 Jul 2015
5   \date 15 Sep 2015
6
7   \brief Algorithm for interpolation on a domain.
8 */
9#include "domain_algorithm_interpolate.hpp"
10#include <boost/unordered_map.hpp>
11#include "context.hpp"
12#include "context_client.hpp"
13#include "distribution_client.hpp"
14#include "client_server_mapping_distributed.hpp"
15#include "netcdf.hpp"
16#include "mapper.hpp"
17#include "mpi_tag.hpp"
18
19namespace xios {
20
21CDomainAlgorithmInterpolate::CDomainAlgorithmInterpolate(CDomain* domainDestination, CDomain* domainSource, CInterpolateDomain* interpDomain)
22: CDomainAlgorithmTransformation(domainDestination, domainSource), interpDomain_(interpDomain)
23{
24  interpDomain_->checkValid(domainSource);
25}
26
27/*!
28  Compute remap with integrated remap calculation module
29*/
30void CDomainAlgorithmInterpolate::computeRemap()
31{
32  using namespace sphereRemap;
33
34  CContext* context = CContext::getCurrent();
35  CContextClient* client=context->client;
36  int clientRank = client->clientRank;
37  int i, j, k, idx;
38  std::vector<double> srcPole(3,0), dstPole(3,0);
39        int orderInterp = interpDomain_->order.getValue();
40  bool renormalize ;
41
42  if (interpDomain_->renormalize.isEmpty()) renormalize=true;
43  else renormalize = interpDomain_->renormalize;
44
45  const double poleValue = 90.0;
46  const int constNVertex = 4; // Value by default number of vertex for rectangular domain
47  int nVertexSrc, nVertexDest;
48  nVertexSrc = nVertexDest = constNVertex;
49
50  // First of all, try to retrieve the boundary values of domain source and domain destination
51  int localDomainSrcSize = domainSrc_->i_index.numElements();
52  int niSrc = domainSrc_->ni.getValue(), njSrc = domainSrc_->nj.getValue();
53  bool hasBoundSrc = domainSrc_->hasBounds;
54  if (hasBoundSrc) nVertexSrc = domainSrc_->nvertex.getValue();
55  CArray<double,2> boundsLonSrc(nVertexSrc,localDomainSrcSize);
56  CArray<double,2> boundsLatSrc(nVertexSrc,localDomainSrcSize);
57
58  if (CDomain::type_attr::rectilinear == domainSrc_->type) srcPole[2] = 1;
59  if (hasBoundSrc)  // Suppose that domain source is curvilinear or unstructured
60  {
61    if (!domainSrc_->bounds_lon_2d.isEmpty())
62    {
63      for (j = 0; j < njSrc; ++j)
64        for (i = 0; i < niSrc; ++i)
65        {
66          k=j*niSrc+i;
67          for(int n=0;n<nVertexSrc;++n)
68          {
69            boundsLonSrc(n,k) = domainSrc_->bounds_lon_2d(n,i,j);
70            boundsLatSrc(n,k) = domainSrc_->bounds_lat_2d(n,i,j);
71          }
72        }
73    }
74    else
75    {
76      boundsLonSrc = domainSrc_->bounds_lon_1d;
77      boundsLatSrc = domainSrc_->bounds_lat_1d;
78    }
79  }
80  else // if domain source is rectilinear, not do anything now
81  {
82    bool isNorthPole = false;
83    bool isSouthPole = false;
84    CArray<double,1> lon_g ;
85    CArray<double,1> lat_g ;
86
87    if (!domainSrc_->lonvalue_1d.isEmpty() && !domainSrc_->latvalue_1d.isEmpty())
88    {
89                domainSrc_->AllgatherRectilinearLonLat(domainSrc_->lonvalue_1d,domainSrc_->latvalue_1d, lon_g,lat_g) ;
90          }
91          else if (! domainSrc_->latvalue_rectilinear_read_from_file.isEmpty() && ! domainSrc_->lonvalue_rectilinear_read_from_file.isEmpty() )
92    {
93                lat_g=domainSrc_->latvalue_rectilinear_read_from_file ;
94                lon_g=domainSrc_->lonvalue_rectilinear_read_from_file ;
95          }
96          else if (!domainSrc_->lon_start.isEmpty() && !domainSrc_->lon_end.isEmpty() &&
97                 !domainSrc_->lat_start.isEmpty() && !domainSrc_->lat_end.isEmpty())
98          {
99            double step=(domainSrc_->lon_end-domainSrc_->lon_start)/domainSrc_->ni_glo ;
100            for(int i=0; i<domainSrc_->ni_glo; ++i) lon_g(i)=domainSrc_->lon_start+i*step ;
101            step=(domainSrc_->lat_end-domainSrc_->lat_start)/domainSrc_->nj_glo ;
102            for(int i=0; i<domainSrc_->ni_glo; ++i) lat_g(i)=domainSrc_->lat_start+i*step ;
103          }
104          else ERROR("void CDomainAlgorithmInterpolate::computeRemap()",<<"Cannot compute bounds for rectilinear domain") ;
105
106    nVertexSrc = constNVertex;
107    domainSrc_->fillInRectilinearBoundLonLat(lon_g,lat_g, boundsLonSrc, boundsLatSrc);
108  }
109
110  std::map<int,std::vector<std::pair<int,double> > > interpMapValueNorthPole;
111  std::map<int,std::vector<std::pair<int,double> > > interpMapValueSouthPole;
112
113  int localDomainDestSize = domainDest_->i_index.numElements();
114  int niDest = domainDest_->ni.getValue(), njDest = domainDest_->nj.getValue();
115  bool hasBoundDest = domainDest_->hasBounds;
116  if (hasBoundDest) nVertexDest = domainDest_->nvertex.getValue();
117  CArray<double,2> boundsLonDest(nVertexDest,localDomainDestSize);
118  CArray<double,2> boundsLatDest(nVertexDest,localDomainDestSize);
119
120  if (CDomain::type_attr::rectilinear == domainDest_->type) dstPole[2] = 1;
121  if (hasBoundDest)
122  {
123    if (!domainDest_->bounds_lon_2d.isEmpty())
124    {
125      for (j = 0; j < njDest; ++j)
126        for (i = 0; i < niDest; ++i)
127        {
128          k=j*niDest+i;
129          for(int n=0;n<nVertexDest;++n)
130          {
131            boundsLonDest(n,k) = domainDest_->bounds_lon_2d(n,i,j);
132            boundsLatDest(n,k) = domainDest_->bounds_lat_2d(n,i,j);
133          }
134        }
135    }
136    else
137    {
138      boundsLonDest = domainDest_->bounds_lon_1d;
139      boundsLatDest = domainDest_->bounds_lat_1d;
140    }
141  }
142  else
143  {
144    bool isNorthPole = false;
145    bool isSouthPole = false;
146    if (std::abs(poleValue - std::abs(domainDest_->lat_start)) < NumTraits<double>::epsilon()) isNorthPole = true;
147    if (std::abs(poleValue - std::abs(domainDest_->lat_end)) < NumTraits<double>::epsilon()) isSouthPole = true;
148
149    CArray<double,1> lon_g ;
150    CArray<double,1> lat_g ;
151
152    if (!domainDest_->lonvalue_1d.isEmpty() && !domainDest_->latvalue_1d.isEmpty())
153    {
154                domainDest_->AllgatherRectilinearLonLat(domainDest_->lonvalue_1d,domainDest_->latvalue_1d, lon_g,lat_g) ;
155        }
156        else if (! domainDest_->latvalue_rectilinear_read_from_file.isEmpty() && ! domainDest_->lonvalue_rectilinear_read_from_file.isEmpty() )
157    {
158                lat_g=domainDest_->latvalue_rectilinear_read_from_file ;
159                lon_g=domainDest_->lonvalue_rectilinear_read_from_file ;
160        }
161        else if (!domainDest_->lon_start.isEmpty() && !domainDest_->lon_end.isEmpty() &&
162                 !domainDest_->lat_start.isEmpty() && !domainDest_->lat_end.isEmpty())
163        {
164          double step=(domainDest_->lon_end-domainDest_->lon_start)/domainDest_->ni_glo ;
165          for(int i=0; i<domainDest_->ni_glo; ++i) lon_g(i)=domainDest_->lon_start+i*step ;
166          step=(domainDest_->lat_end-domainDest_->lat_start)/domainDest_->nj_glo ;
167          for(int i=0; i<domainDest_->ni_glo; ++i) lat_g(i)=domainDest_->lat_start+i*step ;
168        }
169        else ERROR("void CDomainAlgorithmInterpolate::computeRemap()",<<"Cannot compute bounds for rectilinear domain") ;
170    if (std::abs(poleValue - std::abs(lat_g(0))) < NumTraits<double>::epsilon()) isNorthPole = true;
171    if (std::abs(poleValue - std::abs(lat_g(domainDest_->nj_glo-1))) < NumTraits<double>::epsilon()) isSouthPole = true;
172
173
174
175
176    if (isNorthPole && (0 == domainDest_->jbegin.getValue()))
177    {
178      int ibegin = domainDest_->ibegin.getValue();
179      for (i = 0; i < niDest; ++i)
180      {
181        interpMapValueNorthPole[i+ibegin];
182      }
183    }
184
185    if (isSouthPole && (domainDest_->nj_glo.getValue() == (domainDest_->jbegin.getValue() + njDest)))
186    {
187      int ibegin = domainDest_->ibegin.getValue();
188      int njGlo = domainDest_->nj_glo.getValue();
189      int niGlo = domainDest_->ni_glo.getValue();
190      for (i = 0; i < niDest; ++i)
191      {
192        k = (njGlo - 1)*niGlo + i + ibegin;
193        interpMapValueSouthPole[k];
194      }
195    }
196
197    // Ok, fill in boundary values for rectangular domain
198    nVertexDest = constNVertex;
199    domainDest_->fillInRectilinearBoundLonLat(lon_g,lat_g, boundsLonDest, boundsLatDest);
200  }
201
202
203
204  // Ok, now use mapper to calculate
205  int nSrcLocal = domainSrc_->i_index.numElements();
206  int nDstLocal = domainDest_->i_index.numElements();
207  long int * globalSrc = new long int [nSrcLocal];
208  long int * globalDst = new long int [nDstLocal];
209
210  long int globalIndex;
211  int i_ind, j_ind;
212  for (int idx = 0; idx < nSrcLocal; ++idx)
213  {
214    i_ind=domainSrc_->i_index(idx) ;
215    j_ind=domainSrc_->j_index(idx) ;
216
217    globalIndex = i_ind + j_ind * domainSrc_->ni_glo;
218    globalSrc[idx] = globalIndex;
219  }
220
221  for (int idx = 0; idx < nDstLocal; ++idx)
222  {
223    i_ind=domainDest_->i_index(idx) ;
224    j_ind=domainDest_->j_index(idx) ;
225
226    globalIndex = i_ind + j_ind * domainDest_->ni_glo;
227    globalDst[idx] = globalIndex;
228  }
229
230
231  // Calculate weight index
232  Mapper mapper(client->intraComm);
233  mapper.setVerbosity(PROGRESS) ;
234
235
236  CArray<bool,1> localMask(nSrcLocal) ;
237  localMask=false ;
238  size_t ndata=domainSrc_->data_i_index.numElements() ;
239  for (int idx=0; idx < ndata; ++idx)
240  {
241    size_t ind = domainSrc_->data_j_index(idx)*domainSrc_->ni+domainSrc_->data_i_index(idx) ;
242    localMask(ind)=domainSrc_->mask_1d(ind) ;
243  }
244     
245     
246  // supress masked data for the source
247  int nSrcLocalUnmasked = 0 ;
248  for (int idx=0 ; idx < nSrcLocal; idx++) if (localMask(idx)) ++nSrcLocalUnmasked ;
249
250
251  CArray<double,2> boundsLonSrcUnmasked(nVertexSrc,nSrcLocalUnmasked);
252  CArray<double,2> boundsLatSrcUnmasked(nVertexSrc,nSrcLocalUnmasked);
253  long int * globalSrcUnmasked = new long int [nSrcLocalUnmasked];
254
255  nSrcLocalUnmasked=0 ;
256  for (int idx=0 ; idx < nSrcLocal; idx++)
257  {
258    if (localMask(idx))
259    {
260      for(int n=0;n<nVertexSrc;++n)
261      {
262        boundsLonSrcUnmasked(n,nSrcLocalUnmasked) = boundsLonSrc(n,idx) ;
263        boundsLatSrcUnmasked(n,nSrcLocalUnmasked) = boundsLatSrc(n,idx) ;
264      }
265      globalSrcUnmasked[nSrcLocalUnmasked]=globalSrc[idx] ;
266      ++nSrcLocalUnmasked ;
267    }
268  }
269
270  localMask.resize(nDstLocal) ;
271  localMask=false ;
272  ndata=domainDest_->data_i_index.numElements() ;
273  for (int idx=0; idx < ndata; ++idx)
274  {
275    size_t ind = domainDest_->data_j_index(idx)*domainDest_->ni+domainDest_->data_i_index(idx) ;
276    localMask(ind)=domainDest_->mask_1d(ind) ;
277  }
278     
279  int nDstLocalUnmasked = 0 ;
280  for (int idx=0 ; idx < nDstLocal; idx++) if (localMask(idx)) ++nDstLocalUnmasked ;
281
282  CArray<double,2> boundsLonDestUnmasked(nVertexDest,nDstLocalUnmasked);
283  CArray<double,2> boundsLatDestUnmasked(nVertexDest,nDstLocalUnmasked);
284  long int * globalDstUnmasked = new long int [nDstLocalUnmasked];
285
286  nDstLocalUnmasked=0 ;
287  for (int idx=0 ; idx < nDstLocal; idx++)
288  {
289    if (localMask(idx))
290    {
291      for(int n=0;n<nVertexDest;++n)
292      {
293        boundsLonDestUnmasked(n,nDstLocalUnmasked) = boundsLonDest(n,idx) ;
294        boundsLatDestUnmasked(n,nDstLocalUnmasked) = boundsLatDest(n,idx) ;
295      }
296      globalDstUnmasked[nDstLocalUnmasked]=globalDst[idx] ;
297      ++nDstLocalUnmasked ;
298    }
299  }
300
301  mapper.setSourceMesh(boundsLonSrcUnmasked.dataFirst(), boundsLatSrcUnmasked.dataFirst(), nVertexSrc, nSrcLocalUnmasked, &srcPole[0], globalSrcUnmasked);
302  mapper.setTargetMesh(boundsLonDestUnmasked.dataFirst(), boundsLatDestUnmasked.dataFirst(), nVertexDest, nDstLocalUnmasked, &dstPole[0], globalDstUnmasked);
303
304  std::vector<double> timings = mapper.computeWeights(orderInterp,renormalize);
305
306  std::map<int,std::vector<std::pair<int,double> > > interpMapValue;
307  std::map<int,std::vector<std::pair<int,double> > >::const_iterator iteNorthPole = interpMapValueNorthPole.end(),
308                                                                     iteSouthPole = interpMapValueSouthPole.end();
309  for (int idx = 0;  idx < mapper.nWeights; ++idx)
310  {
311    interpMapValue[mapper.targetWeightId[idx]].push_back(make_pair(mapper.sourceWeightId[idx],mapper.remapMatrix[idx]));
312    if (iteNorthPole != interpMapValueNorthPole.find(mapper.targetWeightId[idx]))
313    {
314      interpMapValueNorthPole[mapper.targetWeightId[idx]].push_back(make_pair(mapper.sourceWeightId[idx],mapper.remapMatrix[idx]));
315    }
316
317    if (iteSouthPole != interpMapValueSouthPole.find(mapper.targetWeightId[idx]))
318    {
319      interpMapValueSouthPole[mapper.targetWeightId[idx]].push_back(make_pair(mapper.sourceWeightId[idx],mapper.remapMatrix[idx]));
320    }
321  }
322  int niGloDst = domainDest_->ni_glo.getValue();
323  processPole(interpMapValueNorthPole, niGloDst);
324  processPole(interpMapValueSouthPole, niGloDst);
325
326  if (!interpMapValueNorthPole.empty())
327  {
328     std::map<int,std::vector<std::pair<int,double> > >::iterator itNorthPole = interpMapValueNorthPole.begin();
329     for (; itNorthPole != iteNorthPole; ++itNorthPole)
330     {
331       if (!(itNorthPole->second.empty()))
332        itNorthPole->second.swap(interpMapValue[itNorthPole->first]);
333     }
334  }
335
336  if (!interpMapValueSouthPole.empty())
337  {
338     std::map<int,std::vector<std::pair<int,double> > >::iterator itSouthPole = interpMapValueSouthPole.begin();
339     for (; itSouthPole != iteSouthPole; ++itSouthPole)
340     {
341       if (!(itSouthPole->second.empty()))
342        itSouthPole->second.swap(interpMapValue[itSouthPole->first]);
343     }
344  }
345
346  exchangeRemapInfo(interpMapValue);
347
348  delete [] globalSrc;
349  delete [] globalSrcUnmasked;
350  delete [] globalDst;
351  delete [] globalDstUnmasked;
352
353}
354
355void CDomainAlgorithmInterpolate::processPole(std::map<int,std::vector<std::pair<int,double> > >& interMapValuePole,
356                                              int nbGlobalPointOnPole)
357{
358  CContext* context = CContext::getCurrent();
359  CContextClient* client=context->client;
360
361  MPI_Comm poleComme(MPI_COMM_NULL);
362  MPI_Comm_split(client->intraComm, interMapValuePole.empty() ? MPI_UNDEFINED : 1, 0, &poleComme);
363  if (MPI_COMM_NULL != poleComme)
364  {
365    int nbClientPole;
366    MPI_Comm_size(poleComme, &nbClientPole);
367
368    std::map<int,std::vector<std::pair<int,double> > >::iterator itePole = interMapValuePole.end(), itPole,
369                                                                 itbPole = interMapValuePole.begin();
370
371    int nbWeight = 0;
372    for (itPole = itbPole; itPole != itePole; ++itPole)
373       nbWeight += itPole->second.size();
374
375    std::vector<int> recvCount(nbClientPole,0);
376    std::vector<int> displ(nbClientPole,0);
377    MPI_Allgather(&nbWeight,1,MPI_INT,&recvCount[0],1,MPI_INT,poleComme) ;
378
379    displ[0]=0;
380    for(int n=1;n<nbClientPole;++n) displ[n]=displ[n-1]+recvCount[n-1] ;
381    int recvSize=displ[nbClientPole-1]+recvCount[nbClientPole-1] ;
382
383    std::vector<int> sendSourceIndexBuff(nbWeight);
384    std::vector<double> sendSourceWeightBuff(nbWeight);
385    int k = 0;
386    for (itPole = itbPole; itPole != itePole; ++itPole)
387    {
388      for (int idx = 0; idx < itPole->second.size(); ++idx)
389      {
390        sendSourceIndexBuff[k] = (itPole->second)[idx].first;
391        sendSourceWeightBuff[k] = (itPole->second)[idx].second;
392        ++k;
393      }
394    }
395
396    std::vector<int> recvSourceIndexBuff(recvSize);
397    std::vector<double> recvSourceWeightBuff(recvSize);
398
399    // Gather all index and weight for pole
400    MPI_Allgatherv(&sendSourceIndexBuff[0],nbWeight,MPI_INT,&recvSourceIndexBuff[0],&recvCount[0],&displ[0],MPI_INT,poleComme);
401    MPI_Allgatherv(&sendSourceWeightBuff[0],nbWeight,MPI_DOUBLE,&recvSourceWeightBuff[0],&recvCount[0],&displ[0],MPI_DOUBLE,poleComme);
402
403    std::map<int,double> recvTemp;
404    for (int idx = 0; idx < recvSize; ++idx)
405    {
406      if (recvTemp.end() != recvTemp.find(recvSourceIndexBuff[idx]))
407        recvTemp[recvSourceIndexBuff[idx]] += recvSourceWeightBuff[idx]/nbGlobalPointOnPole;
408      else
409        recvTemp[recvSourceIndexBuff[idx]] = 0.0;
410    }
411
412    std::map<int,double>::const_iterator itRecvTemp, itbRecvTemp = recvTemp.begin(), iteRecvTemp = recvTemp.end();
413
414    for (itPole = itbPole; itPole != itePole; ++itPole)
415    {
416      itPole->second.clear();
417      for (itRecvTemp = itbRecvTemp; itRecvTemp != iteRecvTemp; ++itRecvTemp)
418          itPole->second.push_back(make_pair(itRecvTemp->first, itRecvTemp->second));
419    }
420  }
421
422}
423
424/*!
425  Compute the index mapping between domain on grid source and one on grid destination
426*/
427void CDomainAlgorithmInterpolate::computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs)
428{
429  if (!interpDomain_->file.isEmpty())
430    readRemapInfo();
431  else
432    computeRemap();
433}
434
435void CDomainAlgorithmInterpolate::readRemapInfo()
436{
437  CContext* context = CContext::getCurrent();
438  CContextClient* client=context->client;
439  int clientRank = client->clientRank;
440
441  std::string filename = interpDomain_->file.getValue();
442  std::map<int,std::vector<std::pair<int,double> > > interpMapValue;
443  readInterpolationInfo(filename, interpMapValue);
444
445  exchangeRemapInfo(interpMapValue);
446}
447
448
449/*!
450  Read remap information from file then distribute it among clients
451*/
452void CDomainAlgorithmInterpolate::exchangeRemapInfo(std::map<int,std::vector<std::pair<int,double> > >& interpMapValue)
453{
454  CContext* context = CContext::getCurrent();
455  CContextClient* client=context->client;
456  int clientRank = client->clientRank;
457
458  this->transformationMapping_.resize(1);
459  this->transformationWeight_.resize(1);
460
461  TransformationIndexMap& transMap = this->transformationMapping_[0];
462  TransformationWeightMap& transWeight = this->transformationWeight_[0];
463
464  boost::unordered_map<size_t,int> globalIndexOfDomainDest;
465  int ni = domainDest_->ni.getValue();
466  int nj = domainDest_->nj.getValue();
467  int ni_glo = domainDest_->ni_glo.getValue();
468  size_t globalIndex;
469  int nIndexSize = domainDest_->i_index.numElements(), i_ind, j_ind;
470  for (int idx = 0; idx < nIndexSize; ++idx)
471  {
472    i_ind=domainDest_->i_index(idx) ;
473    j_ind=domainDest_->j_index(idx) ;
474
475    globalIndex = i_ind + j_ind * ni_glo;
476    globalIndexOfDomainDest[globalIndex] = clientRank;
477  }
478
479  CClientServerMappingDistributed domainIndexClientClientMapping(globalIndexOfDomainDest,
480                                                                 client->intraComm,
481                                                                 true);
482  CArray<size_t,1> globalIndexInterp(interpMapValue.size());
483  std::map<int,std::vector<std::pair<int,double> > >::const_iterator itb = interpMapValue.begin(), it,
484                                                                     ite = interpMapValue.end();
485  size_t globalIndexCount = 0;
486  for (it = itb; it != ite; ++it)
487  {
488    globalIndexInterp(globalIndexCount) = it->first;
489    ++globalIndexCount;
490  }
491
492  domainIndexClientClientMapping.computeServerIndexMapping(globalIndexInterp);
493  const CClientServerMapping::GlobalIndexMap& globalIndexInterpSendToClient = domainIndexClientClientMapping.getGlobalIndexOnServer();
494
495  //Inform each client number of index they will receive
496  int nbClient = client->clientSize;
497  int* sendBuff = new int[nbClient];
498  int* recvBuff = new int[nbClient];
499  for (int i = 0; i < nbClient; ++i)
500  {
501    sendBuff[i] = 0;
502    recvBuff[i] = 0;
503  }
504  int sendBuffSize = 0;
505  CClientServerMapping::GlobalIndexMap::const_iterator itbMap = globalIndexInterpSendToClient.begin(), itMap,
506                                                       iteMap = globalIndexInterpSendToClient.end();
507  for (itMap = itbMap; itMap != iteMap; ++itMap)
508  {
509    const std::vector<size_t>& tmp = itMap->second;
510    int sizeIndex = 0, mapSize = (itMap->second).size();
511    for (int idx = 0; idx < mapSize; ++idx)
512    {
513//      sizeIndex += interpMapValue.at((itMap->second)[idx]).size();
514      sizeIndex += (interpMapValue[(int)(itMap->second)[idx]]).size();
515    }
516    sendBuff[itMap->first] = sizeIndex;
517    sendBuffSize += sizeIndex;
518  }
519
520
521  MPI_Allreduce(sendBuff, recvBuff, nbClient, MPI_INT, MPI_SUM, client->intraComm);
522
523  int* sendIndexDestBuff = new int [sendBuffSize];
524  int* sendIndexSrcBuff  = new int [sendBuffSize];
525  double* sendWeightBuff = new double [sendBuffSize];
526
527  std::vector<MPI_Request> sendRequest;
528
529  int sendOffSet = 0, l = 0;
530  for (itMap = itbMap; itMap != iteMap; ++itMap)
531  {
532    const std::vector<size_t>& indexToSend = itMap->second;
533    int mapSize = indexToSend.size();
534    int k = 0;
535    for (int idx = 0; idx < mapSize; ++idx)
536    {
537      std::vector<std::pair<int,double> >& interpMap = interpMapValue[(int)indexToSend[idx]]; //interpMapValue.at(indexToSend[idx]);
538      for (int i = 0; i < interpMap.size(); ++i)
539      {
540        sendIndexDestBuff[l] = indexToSend[idx];
541        sendIndexSrcBuff[l]  = interpMap[i].first;
542        sendWeightBuff[l]    = interpMap[i].second;
543        ++k;
544        ++l;
545      }
546    }
547
548    sendRequest.push_back(MPI_Request());
549    MPI_Isend(sendIndexDestBuff + sendOffSet,
550             k,
551             MPI_INT,
552             itMap->first,
553             MPI_DOMAIN_INTERPOLATION_DEST_INDEX,
554             client->intraComm,
555             &sendRequest.back());
556    sendRequest.push_back(MPI_Request());
557    MPI_Isend(sendIndexSrcBuff + sendOffSet,
558             k,
559             MPI_INT,
560             itMap->first,
561             MPI_DOMAIN_INTERPOLATION_SRC_INDEX,
562             client->intraComm,
563             &sendRequest.back());
564    sendRequest.push_back(MPI_Request());
565    MPI_Isend(sendWeightBuff + sendOffSet,
566             k,
567             MPI_DOUBLE,
568             itMap->first,
569             MPI_DOMAIN_INTERPOLATION_WEIGHT,
570             client->intraComm,
571             &sendRequest.back());
572    sendOffSet += k;
573  }
574
575  int recvBuffSize = recvBuff[clientRank];
576  int* recvIndexDestBuff = new int [recvBuffSize];
577  int* recvIndexSrcBuff  = new int [recvBuffSize];
578  double* recvWeightBuff = new double [recvBuffSize];
579  int receivedSize = 0;
580  int clientSrcRank;
581  while (receivedSize < recvBuffSize)
582  {
583    MPI_Status recvStatus;
584    MPI_Recv((recvIndexDestBuff + receivedSize),
585             recvBuffSize,
586             MPI_INT,
587             MPI_ANY_SOURCE,
588             MPI_DOMAIN_INTERPOLATION_DEST_INDEX,
589             client->intraComm,
590             &recvStatus);
591
592    int countBuff = 0;
593    MPI_Get_count(&recvStatus, MPI_INT, &countBuff);
594    clientSrcRank = recvStatus.MPI_SOURCE;
595
596    MPI_Recv((recvIndexSrcBuff + receivedSize),
597             recvBuffSize,
598             MPI_INT,
599             clientSrcRank,
600             MPI_DOMAIN_INTERPOLATION_SRC_INDEX,
601             client->intraComm,
602             &recvStatus);
603
604    MPI_Recv((recvWeightBuff + receivedSize),
605             recvBuffSize,
606             MPI_DOUBLE,
607             clientSrcRank,
608             MPI_DOMAIN_INTERPOLATION_WEIGHT,
609             client->intraComm,
610             &recvStatus);
611
612    for (int idx = 0; idx < countBuff; ++idx)
613    {
614      transMap[*(recvIndexDestBuff + receivedSize + idx)].push_back(*(recvIndexSrcBuff + receivedSize + idx));
615      transWeight[*(recvIndexDestBuff + receivedSize + idx)].push_back(*(recvWeightBuff + receivedSize + idx));
616    }
617    receivedSize += countBuff;
618  }
619
620  std::vector<MPI_Status> requestStatus(sendRequest.size());
621  MPI_Waitall(sendRequest.size(), &sendRequest[0], MPI_STATUS_IGNORE);
622
623  delete [] sendIndexDestBuff;
624  delete [] sendIndexSrcBuff;
625  delete [] sendWeightBuff;
626  delete [] recvIndexDestBuff;
627  delete [] recvIndexSrcBuff;
628  delete [] recvWeightBuff;
629  delete [] sendBuff;
630  delete [] recvBuff;
631}
632
633/*!
634  Read interpolation information from a file
635  \param [in] filename interpolation file
636  \param [in/out] interpMapValue Mapping between (global) index of domain on grid destination and
637         corresponding global index of domain and associated weight value on grid source
638*/
639void CDomainAlgorithmInterpolate::readInterpolationInfo(std::string& filename,
640                                                        std::map<int,std::vector<std::pair<int,double> > >& interpMapValue)
641{
642  int ncid ;
643  int weightDimId ;
644  size_t nbWeightGlo ;
645
646  CContext* context = CContext::getCurrent();
647  CContextClient* client=context->client;
648  int clientRank = client->clientRank;
649  int clientSize = client->clientSize;
650
651  nc_open(filename.c_str(),NC_NOWRITE, &ncid) ;
652  nc_inq_dimid(ncid,"n_weight",&weightDimId) ;
653  nc_inq_dimlen(ncid,weightDimId,&nbWeightGlo) ;
654
655  size_t nbWeight ;
656  size_t start ;
657  size_t div = nbWeightGlo/clientSize ;
658  size_t mod = nbWeightGlo%clientSize ;
659  if (clientRank < mod)
660  {
661    nbWeight=div+1 ;
662    start=clientRank*(div+1) ;
663  }
664  else
665  {
666    nbWeight=div ;
667    start= mod * (div+1) + (clientRank-mod) * div ;
668  }
669
670  double* weight=new double[nbWeight] ;
671  int weightId ;
672  nc_inq_varid (ncid, "weight", &weightId) ;
673  nc_get_vara_double(ncid, weightId, &start, &nbWeight, weight) ;
674
675  long* srcIndex=new long[nbWeight] ;
676  int srcIndexId ;
677  nc_inq_varid (ncid, "src_idx", &srcIndexId) ;
678  nc_get_vara_long(ncid, srcIndexId, &start, &nbWeight, srcIndex) ;
679
680  long* dstIndex=new long[nbWeight] ;
681  int dstIndexId ;
682  nc_inq_varid (ncid, "dst_idx", &dstIndexId) ;
683  nc_get_vara_long(ncid, dstIndexId, &start, &nbWeight, dstIndex) ;
684
685  for(size_t ind=0; ind<nbWeight;++ind)
686    interpMapValue[dstIndex[ind]-1].push_back(make_pair(srcIndex[ind]-1,weight[ind]));
687}
688
689}
Note: See TracBrowser for help on using the repository browser.