source: XIOS/dev/branch_openmp/src/node/axis.cpp @ 1460

Last change on this file since 1460 was 1460, checked in by yushan, 6 years ago

branch_openmp merged with XIOS_DEV_CMIP6@1459

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 51.6 KB
Line 
1#include "axis.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6#include "message.hpp"
7#include "type.hpp"
8#include "context.hpp"
9#include "context_client.hpp"
10#include "context_server.hpp"
11#include "xios_spl.hpp"
12#include "server_distribution_description.hpp"
13#include "client_server_mapping_distributed.hpp"
14#include "distribution_client.hpp"
15
16using namespace ep_lib;
17
18namespace xios {
19
20   /// ////////////////////// Definitions ////////////////////// ///
21
22   CAxis::CAxis(void)
23      : CObjectTemplate<CAxis>()
24      , CAxisAttributes(), isChecked(false), relFiles()
25      , areClientAttributesChecked_(false)
26      , isClientAfterTransformationChecked(false)
27      , hasBounds(false), isCompressible_(false)
28      , numberWrittenIndexes_(), totalNumberWrittenIndexes_(), offsetWrittenIndexes_()
29      , transformationMap_()
30      , hasValue(false), hasLabel(false)
31      , computedWrittenIndex_(false)
32      , clients()
33   {
34   }
35
36   CAxis::CAxis(const StdString & id)
37      : CObjectTemplate<CAxis>(id)
38      , CAxisAttributes(), isChecked(false), relFiles()
39      , areClientAttributesChecked_(false)
40      , isClientAfterTransformationChecked(false)
41      , hasBounds(false), isCompressible_(false)
42      , numberWrittenIndexes_(), totalNumberWrittenIndexes_(), offsetWrittenIndexes_()
43      , transformationMap_()
44      , hasValue(false), hasLabel(false)
45      , computedWrittenIndex_(false)
46      , clients()
47   {
48   }
49
50   CAxis::~CAxis(void)
51   { /* Ne rien faire de plus */ }
52
53   std::map<StdString, ETranformationType> *CAxis::transformationMapList_ptr = 0;
54
55   bool CAxis::initializeTransformationMap(std::map<StdString, ETranformationType>& m)
56   {
57     m["zoom_axis"] = TRANS_ZOOM_AXIS;
58     m["interpolate_axis"] = TRANS_INTERPOLATE_AXIS;
59     m["inverse_axis"] = TRANS_INVERSE_AXIS;
60     m["reduce_domain"] = TRANS_REDUCE_DOMAIN_TO_AXIS;
61     m["reduce_axis"] = TRANS_REDUCE_AXIS_TO_AXIS;
62     m["extract_domain"] = TRANS_EXTRACT_DOMAIN_TO_AXIS;
63     m["temporal_splitting"] = TRANS_TEMPORAL_SPLITTING;
64     m["duplicate_scalar"] = TRANS_DUPLICATE_SCALAR_TO_AXIS;
65   }
66
67   bool CAxis::initializeTransformationMap()
68   {
69     if(CAxis::transformationMapList_ptr == 0) CAxis::transformationMapList_ptr = new std::map<StdString, ETranformationType>();
70     (*CAxis::transformationMapList_ptr)["zoom_axis"]        = TRANS_ZOOM_AXIS;
71     (*CAxis::transformationMapList_ptr)["interpolate_axis"] = TRANS_INTERPOLATE_AXIS;
72     (*CAxis::transformationMapList_ptr)["inverse_axis"]     = TRANS_INVERSE_AXIS;
73     (*CAxis::transformationMapList_ptr)["reduce_domain"]    = TRANS_REDUCE_DOMAIN_TO_AXIS;
74     (*CAxis::transformationMapList_ptr)["extract_domain"]   = TRANS_EXTRACT_DOMAIN_TO_AXIS;
75     (*CAxis::transformationMapList_ptr)["reduce_axis"]      = TRANS_REDUCE_AXIS_TO_AXIS;
76     (*CAxis::transformationMapList_ptr)["temporal_splitting"] = TRANS_TEMPORAL_SPLITTING;
77     (*CAxis::transformationMapList_ptr)["duplicate_scalar"] = TRANS_DUPLICATE_SCALAR_TO_AXIS;
78   }
79
80   ///---------------------------------------------------------------
81
82   const std::set<StdString> & CAxis::getRelFiles(void) const
83   {
84      return (this->relFiles);
85   }
86
87   bool CAxis::IsWritten(const StdString & filename) const
88   {
89      return (this->relFiles.find(filename) != this->relFiles.end());
90   }
91
92   bool CAxis::isWrittenCompressed(const StdString& filename) const
93   {
94      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
95   }
96
97   bool CAxis::isDistributed(void) const
98   {
99      bool distributed = (!this->begin.isEmpty() && !this->n.isEmpty() && (this->begin + this->n < this->n_glo)) ||
100             (!this->n.isEmpty() && (this->n != this->n_glo));
101      // A same stupid condition to make sure that if there is only one client, axis
102      // should be considered to be distributed. This should be a temporary solution     
103      distributed |= (1 == CContext::getCurrent()->client->clientSize);
104      return distributed;
105   }
106
107   /*!
108    * Test whether the data defined on the axis can be outputted in a compressed way.
109    *
110    * \return true if and only if a mask was defined for this axis
111    */
112   bool CAxis::isCompressible(void) const
113   {
114      return isCompressible_;
115   }
116
117   void CAxis::addRelFile(const StdString & filename)
118   {
119      this->relFiles.insert(filename);
120   }
121
122   void CAxis::addRelFileCompressed(const StdString& filename)
123   {
124      this->relFilesCompressed.insert(filename);
125   }
126
127   //----------------------------------------------------------------
128
129   /*!
130     Returns the number of indexes written by each server.
131     \return the number of indexes written by each server
132   */
133   int CAxis::getNumberWrittenIndexes(ep_lib::MPI_Comm writtenCom)
134   {
135     int writtenSize;
136     ep_lib::MPI_Comm_size(writtenCom, &writtenSize);
137     return numberWrittenIndexes_[writtenSize];
138   }
139
140   /*!
141     Returns the total number of indexes written by the servers.
142     \return the total number of indexes written by the servers
143   */
144   int CAxis::getTotalNumberWrittenIndexes(ep_lib::MPI_Comm writtenCom)
145   {
146     int writtenSize;
147     ep_lib::MPI_Comm_size(writtenCom, &writtenSize);
148     return totalNumberWrittenIndexes_[writtenSize];
149   }
150
151   /*!
152     Returns the offset of indexes written by each server.
153     \return the offset of indexes written by each server
154   */
155   int CAxis::getOffsetWrittenIndexes(ep_lib::MPI_Comm writtenCom)
156   {
157     int writtenSize;
158     ep_lib::MPI_Comm_size(writtenCom, &writtenSize);
159     return offsetWrittenIndexes_[writtenSize];
160   }
161
162   CArray<int, 1>& CAxis::getCompressedIndexToWriteOnServer(ep_lib::MPI_Comm writtenCom)
163   {
164     int writtenSize;
165     ep_lib::MPI_Comm_size(writtenCom, &writtenSize);
166     return compressedIndexToWriteOnServer[writtenSize];
167   }
168
169   //----------------------------------------------------------------
170
171      /*!
172    * Compute the minimum buffer size required to send the attributes to the server(s).
173    *
174    * \return A map associating the server rank with its minimum buffer size.
175    */
176   std::map<int, StdSize> CAxis::getAttributesBufferSize(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
177                                                         CServerDistributionDescription::ServerDistributionType distType)
178   {
179
180     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client);
181
182//     bool isNonDistributed = (n_glo == n);
183     bool isDistributed = (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
184                         || (index.numElements() != n_glo);
185
186     if (client->isServerLeader())
187     {
188       // size estimation for sendServerAttribut
189       size_t size = 6 * sizeof(size_t);
190       // size estimation for sendNonDistributedValue
191       if (!isDistributed)
192       {
193//         size = std::max(size, CArray<double,1>::size(n_glo) + (isCompressible_ ? CArray<int,1>::size(n_glo) : 0));
194         size += CArray<int,1>::size(n_glo);
195         size += CArray<int,1>::size(n_glo);
196         size += CArray<bool,1>::size(n_glo);
197         size += CArray<double,1>::size(n_glo);
198         if (hasBounds)
199           size += CArray<double,2>::size(2*n_glo);
200         if (hasLabel)
201          size += CArray<StdString,1>::size(n_glo);
202       }
203       size += CEventClient::headerSize + getId().size() + sizeof(size_t);
204
205       const std::list<int>& ranks = client->getRanksServerLeader();
206       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
207       {
208         if (size > attributesSizes[*itRank])
209           attributesSizes[*itRank] = size;
210       }
211       const std::list<int>& ranksNonLeaders = client->getRanksServerNotLeader();
212       for (std::list<int>::const_iterator itRank = ranksNonLeaders.begin(), itRankEnd = ranksNonLeaders.end(); itRank != itRankEnd; ++itRank)
213       {
214         if (size > attributesSizes[*itRank])
215           attributesSizes[*itRank] = size;
216       }
217
218     }
219
220     if (isDistributed)
221     {
222       // size estimation for sendDistributedValue
223       boost::unordered_map<int, vector<size_t> >::const_iterator it, ite = indSrv_[client->serverSize].end();
224       for (it = indSrv_[client->serverSize].begin(); it != ite; ++it)
225       {
226         size_t size = 6 * sizeof(size_t);
227         size += CArray<int,1>::size(it->second.size());
228         size += CArray<int,1>::size(it->second.size());
229         size += CArray<bool,1>::size(it->second.size());
230         size += CArray<double,1>::size(it->second.size());
231         if (hasBounds)
232           size += CArray<double,2>::size(2 * it->second.size());
233         if (hasLabel)
234           size += CArray<StdString,1>::size(it->second.size());
235
236         size += CEventClient::headerSize + getId().size() + sizeof(size_t);
237         if (size > attributesSizes[it->first])
238           attributesSizes[it->first] = size;
239       }
240     }
241
242     return attributesSizes;
243   }
244
245   //----------------------------------------------------------------
246
247   StdString CAxis::GetName(void)   { return (StdString("axis")); }
248   StdString CAxis::GetDefName(void){ return (CAxis::GetName()); }
249   ENodeType CAxis::GetType(void)   { return (eAxis); }
250
251   //----------------------------------------------------------------
252
253   CAxis* CAxis::createAxis()
254   {
255     CAxis* axis = CAxisGroup::get("axis_definition")->createChild();
256     return axis;
257   }
258
259   /*!
260     Check common attributes of an axis.
261     This check should be done in the very beginning of work flow
262   */
263   void CAxis::checkAttributes(void)
264   {
265      if (this->n_glo.isEmpty())
266        ERROR("CAxis::checkAttributes(void)",
267              << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
268              << "The axis is wrongly defined, attribute 'n_glo' must be specified");
269      StdSize size = this->n_glo.getValue();
270
271      if (!this->index.isEmpty())
272      {
273        if (n.isEmpty()) n = index.numElements();
274
275        // It's not so correct but if begin is not the first value of index
276        // then data on the local axis has user-defined distribution. In this case, begin has no meaning.
277        if (begin.isEmpty()) begin = index(0);         
278      }
279      else 
280      {
281        if (!this->begin.isEmpty())
282        {
283          if (begin < 0 || begin > size - 1)
284            ERROR("CAxis::checkAttributes(void)",
285                  << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
286                  << "The axis is wrongly defined, attribute 'begin' (" << begin.getValue() << ") must be non-negative and smaller than size-1 (" << size - 1 << ").");
287        }
288        else this->begin.setValue(0);
289
290        if (!this->n.isEmpty())
291        {
292          if (n < 0 || n > size)
293            ERROR("CAxis::checkAttributes(void)",
294                  << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
295                  << "The axis is wrongly defined, attribute 'n' (" << n.getValue() << ") must be non-negative and smaller than size (" << size << ").");
296        }
297        else this->n.setValue(size);
298
299        {
300          index.resize(n);
301          for (int i = 0; i < n; ++i) index(i) = i+begin;
302        }
303      }
304
305      // Remove this check because it doen't make sense in case of a hole or overlapping axes
306      if (!this->value.isEmpty())
307      {
308//        StdSize true_size = value.numElements();
309//        if (this->n.getValue() != true_size)
310//          ERROR("CAxis::checkAttributes(void)",
311//                << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
312//                << "The axis is wrongly defined, attribute 'value' has a different size (" << true_size << ") than the one defined by the \'size\' attribute (" << n.getValue() << ").");
313        this->hasValue = true;
314      }
315
316      this->checkBounds();
317
318      CContext* context=CContext::getCurrent();
319      if (context->hasClient)
320      {
321        this->checkData();
322        this->checkZoom();
323        this->checkMask();
324        this->checkLabel();
325      }
326   }
327
328   /*!
329      Check the validity of data and fill in values if any.
330   */
331   void CAxis::checkData()
332   {
333      if (data_begin.isEmpty()) data_begin.setValue(0);
334
335      if (data_n.isEmpty())
336      {
337        data_n.setValue(n);
338      }
339      else if (data_n.getValue() < 0)
340      {
341        ERROR("CAxis::checkData(void)",
342              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
343              << "The data size should be strictly positive ('data_n' = " << data_n.getValue() << ").");
344      }
345
346      if (data_index.isEmpty())
347      {
348        data_index.resize(data_n);
349        for (int i = 0; i < data_n; ++i) data_index(i) = i;
350      }
351   }
352
353   /*!
354     Check validity of zoom info and fill in values if any.
355   */
356   void CAxis::checkZoom(void)
357   {
358     if (global_zoom_begin.isEmpty()) global_zoom_begin.setValue(0);
359     if (global_zoom_n.isEmpty()) global_zoom_n.setValue(n_glo.getValue());
360     if (zoom_index.isEmpty())
361     {
362       zoom_index.setValue(index.getValue());
363     }
364     if (zoom_n.isEmpty()) zoom_n.setValue(n);
365     if (zoom_begin.isEmpty()) zoom_begin.setValue(begin);
366   }
367
368    size_t CAxis::getGlobalWrittenSize(void)
369    {
370      if (zoomByIndex()) return  global_zoom_index.numElements();
371      else return global_zoom_n ;
372    }
373
374   /*!
375     Check validity of mask info and fill in values if any.
376   */
377   void CAxis::checkMask()
378   {
379      if (!mask.isEmpty())
380      {
381         if (mask.extent(0) != n)
382           ERROR("CAxis::checkMask(void)",
383                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
384                 << "The mask does not have the same size as the local domain." << std::endl
385                 << "Local size is " << n.getValue() << "." << std::endl
386                 << "Mask size is " << mask.extent(0) << ".");
387      }
388      else // (mask.isEmpty())
389      { // If no mask was defined, we create a default one without any masked point.
390         mask.resize(n);
391         for (int i = 0; i < n; ++i)
392         {
393           mask(i) = true;
394         }
395      }
396   }
397
398   /*!
399     Check validity of bounds info and fill in values if any.
400   */
401   void CAxis::checkBounds()
402   {
403     if (!bounds.isEmpty())
404     {
405       if (bounds.extent(0) != 2 || bounds.extent(1) != n)
406         ERROR("CAxis::checkAttributes(void)",
407               << "The bounds array of the axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] must be of dimension 2 x axis size." << std::endl
408               << "Axis size is " << n.getValue() << "." << std::endl
409               << "Bounds size is "<< bounds.extent(0) << " x " << bounds.extent(1) << ".");
410       hasBounds = true;
411     }
412     else hasBounds = false;
413   }
414
415  void CAxis::checkLabel()
416  {
417    if (!label.isEmpty())
418    {
419      if (label.extent(0) != n)
420        ERROR("CAxis::checkLabel(void)",
421              << "The label array of the axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] must be of dimension of axis size." << std::endl
422              << "Axis size is " << n.getValue() << "." << std::endl
423              << "label size is "<< label.extent(0)<<  " .");
424      hasLabel = true;
425    }
426    else hasLabel = false;
427  }
428
429  /*!
430    Check whether we can do compressed output
431  */
432  void CAxis::checkEligibilityForCompressedOutput()
433  {
434    // We don't check if the mask is valid here, just if a mask has been defined at this point.
435    isCompressible_ = !mask.isEmpty();
436  }
437
438  /*
439    Check whether we do zooming by indexing
440    return true if do zooming by index
441  */
442  bool CAxis::zoomByIndex()
443  {
444    return (!global_zoom_index.isEmpty() && (0 != global_zoom_index.numElements()));
445  }
446
447  /*!
448    Dispatch event from the lower communication layer then process event according to its type
449  */
450  bool CAxis::dispatchEvent(CEventServer& event)
451  {
452     if (SuperClass::dispatchEvent(event)) return true;
453     else
454     {
455       switch(event.type)
456       {
457          case EVENT_ID_DISTRIBUTION_ATTRIBUTE :
458            recvDistributionAttribute(event);
459            return true;
460            break;
461         case EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES:
462           recvNonDistributedAttributes(event);
463           return true;
464           break;
465         case EVENT_ID_DISTRIBUTED_ATTRIBUTES:
466           recvDistributedAttributes(event);
467           return true;
468           break;
469          default :
470            ERROR("bool CAxis::dispatchEvent(CEventServer& event)",
471                   << "Unknown Event");
472          return false;
473        }
474     }
475  }
476 
477  /*!
478     Check attributes on client side (This name is still adequate???)
479   */
480   void CAxis::checkAttributesOnClient()
481   {
482     if (this->areClientAttributesChecked_) return;
483
484     CContext* context=CContext::getCurrent();
485     if (context->hasClient && !context->hasServer) this->checkAttributes();
486
487     this->areClientAttributesChecked_ = true;
488   }
489
490   /*
491     The (spatial) transformation sometimes can change attributes of an axis (e.g zoom can change mask or generate can change whole attributes)
492     Therefore, we should recheck them.
493   */
494   void CAxis::checkAttributesOnClientAfterTransformation(const std::vector<int>& globalDim, int orderPositionInGrid,
495                                                          CServerDistributionDescription::ServerDistributionType distType)
496   {
497     CContext* context=CContext::getCurrent() ;
498
499     if (this->isClientAfterTransformationChecked) return;
500     if (context->hasClient)
501     {       
502       if (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
503         computeConnectedClients(globalDim, orderPositionInGrid, distType);
504       else if (index.numElements() != n_glo) computeConnectedClients(globalDim, orderPositionInGrid,  CServerDistributionDescription::ROOT_DISTRIBUTION);
505     }
506
507     this->isClientAfterTransformationChecked = true;
508   }
509
510   /*
511     Send all checked attributes to server? (We dont have notion of server any more so client==server)
512     \param [in] globalDim global dimension of grid containing this axis
513     \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2)
514     \param [in] distType distribution type of the server. For now, we only have band distribution.
515
516   */
517   void CAxis::sendCheckedAttributes(const std::vector<int>& globalDim, int orderPositionInGrid,
518                                     CServerDistributionDescription::ServerDistributionType distType)
519   {
520     if (!this->areClientAttributesChecked_) checkAttributesOnClient();
521     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation(globalDim, orderPositionInGrid, distType);
522     CContext* context = CContext::getCurrent();
523
524     if (this->isChecked) return;
525     if (context->hasClient) sendAttributes(globalDim, orderPositionInGrid, distType);   
526
527     this->isChecked = true;
528   }
529
530   /*!
531    Send attributes from one client to other clients
532    \param[in] globalDim global dimension of grid which contains this axis
533    \param[in] order
534  */
535  void CAxis::sendAttributes(const std::vector<int>& globalDim, int orderPositionInGrid,
536                             CServerDistributionDescription::ServerDistributionType distType)
537  {
538     sendDistributionAttribute(globalDim, orderPositionInGrid, distType);
539
540     // if (index.numElements() == n_glo.getValue())
541     if ((orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
542         || (index.numElements() != n_glo))
543     {
544       sendDistributedAttributes();       
545     }
546     else
547     {
548       sendNonDistributedAttributes();   
549     }     
550  }
551
552  /*
553    Compute the connection between group of clients (or clients/servers).
554    (E.g: Suppose we have 2 group of clients in two model: A (client role) connect to B (server role),
555    this function calculate number of clients B connect to one client of A)
556     \param [in] globalDim global dimension of grid containing this axis
557     \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2)
558     \param [in] distType distribution type of the server. For now, we only have band distribution.
559  */
560  void CAxis::computeConnectedClients(const std::vector<int>& globalDim, int orderPositionInGrid,
561                                     CServerDistributionDescription::ServerDistributionType distType)
562  {
563    CContext* context = CContext::getCurrent();
564
565    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
566
567    connectedServerRank_.clear();
568    nbSenders.clear();
569
570    for (int p = 0; p < nbSrvPools; ++p)
571    {
572      CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[p] : context->client;
573      int nbServer = client->serverSize;
574      int range, clientSize = client->clientSize;
575      int rank = client->clientRank;
576
577      if (connectedServerRank_.find(nbServer) == connectedServerRank_.end())
578      {
579        size_t ni = this->n.getValue();
580        size_t ibegin = this->begin.getValue();
581        size_t global_zoom_end = global_zoom_begin+global_zoom_n-1;
582        size_t nZoomCount = 0;
583        size_t nbIndex = index.numElements();
584
585        // First of all, we should compute the mapping of the global index and local index of the current client
586        if (globalLocalIndexMap_.empty())
587        {
588          for (size_t idx = 0; idx < nbIndex; ++idx)
589          {
590            globalLocalIndexMap_[index(idx)] = idx;
591          }
592        }
593
594        // Calculate the compressed index if any
595        std::set<int> writtenInd;
596        if (isCompressible_)
597        {
598          for (int idx = 0; idx < data_index.numElements(); ++idx)
599          {
600            int ind = CDistributionClient::getAxisIndex(data_index(idx), data_begin, ni);
601
602            if (ind >= 0 && ind < ni && mask(ind))
603            {
604              ind += ibegin;
605              if (ind >= global_zoom_begin && ind <= global_zoom_end)
606                writtenInd.insert(ind);
607            }
608          }
609        }
610
611        // Compute the global index of the current client (process) hold
612        std::vector<int> nGlobAxis(1);
613        nGlobAxis[0] = n_glo.getValue();
614
615        size_t globalSizeIndex = 1, indexBegin, indexEnd;
616        for (int i = 0; i < nGlobAxis.size(); ++i) globalSizeIndex *= nGlobAxis[i];
617        indexBegin = 0;
618        if (globalSizeIndex <= clientSize)
619        {
620          indexBegin = rank%globalSizeIndex;
621          indexEnd = indexBegin;
622        }
623        else
624        {
625          for (int i = 0; i < clientSize; ++i)
626          {
627            range = globalSizeIndex / clientSize;
628            if (i < (globalSizeIndex%clientSize)) ++range;
629            if (i == client->clientRank) break;
630            indexBegin += range;
631          }
632          indexEnd = indexBegin + range - 1;
633        }
634
635        CArray<size_t,1> globalIndex(index.numElements());
636        for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
637          globalIndex(idx) = index(idx);
638
639        // Describe the distribution of server side
640
641        CServerDistributionDescription serverDescription(nGlobAxis, nbServer, distType);
642
643        std::vector<int> serverZeroIndex;
644        serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t,size_t>(indexBegin, indexEnd), 0);     
645
646        std::list<int> serverZeroIndexLeader;
647        std::list<int> serverZeroIndexNotLeader; 
648        CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader);
649
650        for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
651          *it = serverZeroIndex[*it];
652
653        // Find out the connection between client and server side
654        CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm);
655        clientServerMap->computeServerIndexMapping(globalIndex, nbServer);
656        CClientServerMapping::GlobalIndexMap& globalIndexAxisOnServer = clientServerMap->getGlobalIndexOnServer();     
657
658        indSrv_[nbServer].swap(globalIndexAxisOnServer);
659
660        if (distType==CServerDistributionDescription::ROOT_DISTRIBUTION)
661        {
662          for(int i=1; i<nbServer; ++i) 
663          {
664            indSrv_[nbServer].insert(pair<int, vector<size_t> >(i,indSrv_[nbServer][0]) ) ;
665          }
666
667          serverZeroIndexLeader.clear() ;
668        }
669
670        CClientServerMapping::GlobalIndexMap::const_iterator it  = indSrv_[nbServer].begin(),
671                                                             ite = indSrv_[nbServer].end();
672
673        for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first);
674
675        for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
676          connectedServerRank_[nbServer].push_back(*it);
677
678         // Even if a client has no index, it must connect to at least one server and
679         // send an "empty" data to this server
680         if (connectedServerRank_[nbServer].empty())
681          connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize);
682
683         nbSenders[nbServer] = CClientServerMapping::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]);
684
685        delete clientServerMap;
686      }
687    }
688  }
689
690  /*
691    Compute the index of data to write into file
692    (Different from the previous version, this version of XIOS allows data be written into file (classical role),
693    or transfered to another clients)
694  */
695  void CAxis::computeWrittenIndex()
696  { 
697    if (computedWrittenIndex_) return;
698    computedWrittenIndex_ = true;
699
700    CContext* context=CContext::getCurrent();     
701    CContextServer* server = context->server; 
702
703    // We describe the distribution of client (server) on which data are written
704    std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1);
705    nBegin[0]       = zoom_begin;
706    nSize[0]        = zoom_n;   
707    nBeginGlobal[0] = 0; 
708    nGlob[0]        = n_glo;
709    CDistributionServer srvDist(server->intraCommSize, nBegin, nSize, nBeginGlobal, nGlob); 
710    const CArray<size_t,1>& writtenGlobalIndex  = srvDist.getGlobalIndex();
711
712    // Because all written data are local on a client,
713    // we need to compute the local index on the server from its corresponding global index
714    size_t nbWritten = 0, indGlo;     
715    boost::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
716                                                        ite = globalLocalIndexMap_.end(), it;         
717    CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
718                                     itSrve = writtenGlobalIndex.end(), itSrv; 
719    if (!zoomByIndex())
720    {   
721      for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
722      {
723        indGlo = *itSrv;
724        if (ite != globalLocalIndexMap_.find(indGlo))
725        {         
726          ++nbWritten;
727        }                 
728      }
729
730      localIndexToWriteOnServer.resize(writtenGlobalIndex.numElements());
731//      localIndexToWriteOnServer.resize(nbWritten);
732
733      nbWritten = 0;
734      for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
735      {
736        indGlo = *itSrv;
737        if (ite != globalLocalIndexMap_.find(indGlo))
738        {
739          localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[indGlo];
740          ++nbWritten;
741        }                 
742      }
743    }
744    else
745    {
746      nbWritten = 0;
747      boost::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
748                                                          ite = globalLocalIndexMap_.end(), it;
749      for (int i = 0; i < zoom_index.numElements(); ++i)
750      {
751         if (ite != globalLocalIndexMap_.find(zoom_index(i)))
752          ++nbWritten;
753      }
754
755      localIndexToWriteOnServer.resize(nbWritten);
756
757      nbWritten = 0;
758      for (int i = 0; i < zoom_index.numElements(); ++i)
759      {
760         if (ite != globalLocalIndexMap_.find(zoom_index(i)))
761         {
762           localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[zoom_index(i)];
763           ++nbWritten;
764         }
765      }
766    }
767
768  }
769
770  void CAxis::computeWrittenCompressedIndex(ep_lib::MPI_Comm writtenComm)
771  {
772    int writtenCommSize;
773    ep_lib::MPI_Comm_size(writtenComm, &writtenCommSize);
774    if (compressedIndexToWriteOnServer.find(writtenCommSize) != compressedIndexToWriteOnServer.end())
775      return;
776
777    if (isCompressible())
778    {
779      size_t nbWritten = 0, indGlo;
780      CContext* context=CContext::getCurrent();     
781      CContextServer* server = context->server; 
782
783      // We describe the distribution of client (server) on which data are written
784      std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1);
785      nBegin[0]       = zoom_begin;
786      nSize[0]        = zoom_n;   
787      nBeginGlobal[0] = 0; 
788      nGlob[0]        = n_glo;
789      CDistributionServer srvDist(server->intraCommSize, nBegin, nSize, nBeginGlobal, nGlob); 
790      const CArray<size_t,1>& writtenGlobalIndex  = srvDist.getGlobalIndex();
791      boost::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
792                                                          ite = globalLocalIndexMap_.end(), it;   
793
794      CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
795                                       itSrve = writtenGlobalIndex.end(), itSrv;
796      boost::unordered_map<size_t,size_t> localGlobalIndexMap;
797      for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
798      {
799        indGlo = *itSrv;
800        if (ite != globalLocalIndexMap_.find(indGlo))
801        {
802          localGlobalIndexMap[localIndexToWriteOnServer(nbWritten)] = indGlo;
803          ++nbWritten;
804        }                 
805      }
806
807      nbWritten = 0;
808      for (int idx = 0; idx < data_index.numElements(); ++idx)
809      {
810        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
811        {
812          ++nbWritten;
813        }
814      }
815
816      compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten);
817      nbWritten = 0;
818      for (int idx = 0; idx < data_index.numElements(); ++idx)
819      {
820        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
821        {
822          compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)];
823          ++nbWritten;
824        }
825      }
826
827      numberWrittenIndexes_[writtenCommSize] = nbWritten;
828      if (isDistributed())
829      {
830             
831        ep_lib::MPI_Allreduce(&numberWrittenIndexes_[writtenCommSize], &totalNumberWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
832        ep_lib::MPI_Scan(&numberWrittenIndexes_[writtenCommSize], &offsetWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
833        offsetWrittenIndexes_[writtenCommSize] -= numberWrittenIndexes_[writtenCommSize];
834      }
835      else
836        totalNumberWrittenIndexes_[writtenCommSize] = numberWrittenIndexes_[writtenCommSize];
837    }
838  }
839
840  /*!
841    Send distribution information from a group of client (client role) to another group of client (server role)
842    The distribution of a group of client (server role) is imposed by the group of client (client role)
843    \param [in] globalDim global dimension of grid containing this axis
844    \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2)
845    \param [in] distType distribution type of the server. For now, we only have band distribution.
846  */
847  void CAxis::sendDistributionAttribute(const std::vector<int>& globalDim, int orderPositionInGrid,
848                                        CServerDistributionDescription::ServerDistributionType distType)
849  {
850    std::list<CContextClient*>::iterator it;
851    for (it=clients.begin(); it!=clients.end(); ++it)
852    {
853      CContextClient* client = *it;
854      int nbServer = client->serverSize;
855
856      CServerDistributionDescription serverDescription(globalDim, nbServer);
857      serverDescription.computeServerDistribution();
858
859      std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
860      std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
861
862      CEventClient event(getType(),EVENT_ID_DISTRIBUTION_ATTRIBUTE);
863      if (client->isServerLeader())
864      {
865        std::list<CMessage> msgs;
866
867        const std::list<int>& ranks = client->getRanksServerLeader();
868        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
869        {
870          // Use const int to ensure CMessage holds a copy of the value instead of just a reference
871          const int begin = serverIndexBegin[*itRank][orderPositionInGrid];
872          const int ni    = serverDimensionSizes[*itRank][orderPositionInGrid];
873          const int end   = begin + ni - 1;         
874
875          msgs.push_back(CMessage());
876          CMessage& msg = msgs.back();
877          msg << this->getId();
878          msg << ni << begin << end;         
879          msg << isCompressible_;                   
880
881          event.push(*itRank,1,msg);
882        }
883        client->sendEvent(event);
884      }
885      else client->sendEvent(event);
886    }
887  }
888
889  /*
890    Receive distribution attribute from another client
891    \param [in] event event containing data of these attributes
892  */
893  void CAxis::recvDistributionAttribute(CEventServer& event)
894  {
895    CBufferIn* buffer = event.subEvents.begin()->buffer;
896    string axisId;
897    *buffer >> axisId;
898    get(axisId)->recvDistributionAttribute(*buffer);
899  }
900
901  /*
902    Receive distribution attribute from another client
903    \param [in] buffer buffer containing data of these attributes
904  */
905  void CAxis::recvDistributionAttribute(CBufferIn& buffer)
906  {
907    int ni_srv, begin_srv, end_srv;
908    int global_zoom_end, zoom_end;
909    bool zoomIndex = zoomByIndex();
910   
911    std::vector<int> zoom_index_tmp;
912    std::vector<int>::iterator itZoomBegin, itZoomEnd, itZoom;
913
914    buffer >> ni_srv >> begin_srv >> end_srv;   
915    buffer >> isCompressible_;           
916
917    // Set up new local size of axis on the receiving clients
918    n.setValue(ni_srv);
919    begin.setValue(begin_srv);
920
921    // If we have zoom by index then process it
922    if (zoomIndex)
923    {
924      zoom_index_tmp.resize(global_zoom_index.numElements());
925      std::copy(global_zoom_index.begin(), global_zoom_index.end(), zoom_index_tmp.begin());
926      std::sort(zoom_index_tmp.begin(), zoom_index_tmp.end());
927      itZoomBegin = std::lower_bound(zoom_index_tmp.begin(), zoom_index_tmp.end(), begin_srv);
928      itZoomEnd   = std::upper_bound(zoom_index_tmp.begin(), zoom_index_tmp.end(), end_srv);     
929      int sz = std::distance(itZoomBegin, itZoomEnd);
930      zoom_index.resize(sz);
931      itZoom = itZoomBegin;
932      for (int i = 0; i < sz; ++i, ++itZoom)
933      {
934        zoom_index(i) = *(itZoom);
935      }
936    }
937
938    global_zoom_begin = zoomIndex ? 0 : global_zoom_begin ;
939    global_zoom_n     = zoomIndex ? zoom_index_tmp.size() : global_zoom_n;
940    global_zoom_end   = global_zoom_begin + global_zoom_n - 1;
941
942    zoom_begin = zoomIndex ? std::distance(zoom_index_tmp.begin(), itZoomBegin)
943                           : global_zoom_begin > begin_srv ? global_zoom_begin : begin_srv ;
944    zoom_end   = zoomIndex ? std::distance(zoom_index_tmp.begin(), itZoomEnd) - 1 
945                           : global_zoom_end < end_srv ? global_zoom_end : end_srv ;
946    zoom_n     = zoom_end - zoom_begin + 1;
947
948    if (zoom_n<=0)
949    {
950      zoom_n = 0; zoom_begin=global_zoom_begin; //0; zoom_begin = 0;
951    }
952
953    if (n_glo == n)
954    {
955      zoom_begin = zoomIndex ? std::distance(itZoomBegin, zoom_index_tmp.begin())
956                             : global_zoom_begin;     
957      zoom_n     = zoomIndex ? zoom_index_tmp.size() : global_zoom_n;
958    }
959  }
960
961  /*
962    Send attributes of axis from a group of client to other group of clients/servers
963    on supposing that these attributes are not distributed among the sending group
964    In the future, if new attributes are added, they should also be processed in this function
965  */
966  void CAxis::sendNonDistributedAttributes()
967  {
968    std::list<CContextClient*>::iterator it;
969    for (it=clients.begin(); it!=clients.end(); ++it)
970  {
971    CContextClient* client = *it;
972
973      CEventClient event(getType(), EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES);
974      size_t nbIndex = index.numElements();
975      size_t nbDataIndex = 0;
976
977      for (int idx = 0; idx < data_index.numElements(); ++idx)
978      {
979        int ind = data_index(idx);
980        if (ind >= 0 && ind < nbIndex) ++nbDataIndex;
981      }
982
983      CArray<int,1> dataIndex(nbDataIndex);
984      nbDataIndex = 0;
985      for (int idx = 0; idx < data_index.numElements(); ++idx)
986      {
987        int ind = data_index(idx);
988        if (ind >= 0 && ind < nbIndex)
989        {
990          dataIndex(nbDataIndex) = ind;
991          ++nbDataIndex;
992        }
993      }
994
995      if (client->isServerLeader())
996      {
997        std::list<CMessage> msgs;
998
999        const std::list<int>& ranks = client->getRanksServerLeader();
1000        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1001        {
1002          msgs.push_back(CMessage());
1003          CMessage& msg = msgs.back();
1004          msg << this->getId();
1005          msg << index.getValue() << dataIndex << mask.getValue();
1006          msg << hasValue;
1007          if (hasValue) msg << value.getValue();
1008          msg << hasBounds;
1009          if (hasBounds) msg << bounds.getValue();
1010          msg << hasLabel;
1011          if (hasLabel) msg << label.getValue();
1012
1013          event.push(*itRank, 1, msg);
1014        }
1015        client->sendEvent(event);
1016      }
1017      else client->sendEvent(event);
1018    }
1019  }
1020
1021  /*
1022    Receive the non-distributed attributes from another group of clients
1023    \param [in] event event containing data of these attributes
1024  */
1025  void CAxis::recvNonDistributedAttributes(CEventServer& event)
1026  {
1027    list<CEventServer::SSubEvent>::iterator it;
1028    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1029    {
1030      CBufferIn* buffer = it->buffer;
1031      string axisId;
1032      *buffer >> axisId;
1033      get(axisId)->recvNonDistributedAttributes(it->rank, *buffer);
1034    }
1035  }
1036
1037  /*
1038    Receive the non-distributed attributes from another group of clients
1039    \param [in] rank rank of the sender
1040    \param [in] buffer buffer containing data sent from the sender
1041  */
1042  void CAxis::recvNonDistributedAttributes(int rank, CBufferIn& buffer)
1043  { 
1044    CArray<int,1> tmp_index, tmp_data_index, tmp_zoom_index;
1045    CArray<bool,1> tmp_mask;
1046    CArray<double,1> tmp_val;
1047    CArray<double,2> tmp_bnds;
1048    CArray<string,1> tmp_label;
1049
1050    buffer >> tmp_index;
1051    index.reference(tmp_index);
1052    buffer >> tmp_data_index;
1053    data_index.reference(tmp_data_index);
1054    buffer >> tmp_mask;
1055    mask.reference(tmp_mask);
1056
1057    buffer >> hasValue;
1058    if (hasValue)
1059    {
1060      buffer >> tmp_val;
1061      value.reference(tmp_val);
1062    }
1063
1064    buffer >> hasBounds;
1065    if (hasBounds)
1066    {
1067      buffer >> tmp_bnds;
1068      bounds.reference(tmp_bnds);
1069    }
1070
1071    buffer >> hasLabel;
1072    if (hasLabel)
1073    {
1074      buffer >> tmp_label;
1075      label.reference(tmp_label);
1076    }
1077
1078    // Some value should be reset here
1079    data_begin.setValue(0);
1080    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
1081//    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[idx] = index(idx);
1082    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[index(idx)] = idx;
1083  }
1084
1085/*
1086    Send attributes of axis from a group of client to other group of clients/servers
1087    on supposing that these attributes are distributed among the clients of the sending group
1088    In the future, if new attributes are added, they should also be processed in this function
1089  */
1090  void CAxis::sendDistributedAttributes(void)
1091  {
1092    int ns, n, i, j, ind, nv, idx;
1093    std::list<CContextClient*>::iterator it;
1094
1095    for (it=clients.begin(); it!=clients.end(); ++it)
1096    {
1097      CContextClient* client = *it;
1098      int nbServer = client->serverSize;
1099
1100      CEventClient eventData(getType(), EVENT_ID_DISTRIBUTED_ATTRIBUTES);
1101
1102      list<CMessage> listData;
1103      list<CArray<int,1> > list_indi, list_dataInd, list_zoomInd;
1104      list<CArray<bool,1> > list_mask;
1105      list<CArray<double,1> > list_val;
1106      list<CArray<double,2> > list_bounds;
1107      list<CArray<string,1> > list_label;
1108
1109      int nbIndex = index.numElements();
1110      CArray<int,1> dataIndex(nbIndex);
1111      dataIndex = -1;
1112      for (idx = 0; idx < data_index.numElements(); ++idx)
1113      {
1114        if (0 <= data_index(idx) && data_index(idx) < nbIndex)
1115          dataIndex(idx) = 1;
1116      }
1117
1118      boost::unordered_map<int, std::vector<size_t> >::const_iterator it, iteMap;
1119      iteMap = indSrv_[nbServer].end();
1120      for (int k = 0; k < connectedServerRank_[nbServer].size(); ++k)
1121      {
1122        int nbData = 0;
1123        int rank = connectedServerRank_[nbServer][k];
1124        it = indSrv_[nbServer].find(rank);
1125        if (iteMap != it)
1126          nbData = it->second.size();
1127
1128        list_indi.push_back(CArray<int,1>(nbData));
1129        list_dataInd.push_back(CArray<int,1>(nbData));       
1130        list_mask.push_back(CArray<bool,1>(nbData));
1131
1132        if (hasValue)
1133          list_val.push_back(CArray<double,1>(nbData));
1134
1135        if (hasBounds)       
1136          list_bounds.push_back(CArray<double,2>(2,nbData));
1137
1138        if (hasLabel)
1139          list_label.push_back(CArray<string,1>(nbData));
1140
1141        CArray<int,1>& indi = list_indi.back();
1142        CArray<int,1>& dataIndi = list_dataInd.back();       
1143        CArray<bool,1>& maskIndi = list_mask.back();
1144
1145        for (n = 0; n < nbData; ++n)
1146        {
1147          idx = static_cast<int>(it->second[n]);
1148          indi(n) = idx;
1149
1150          ind = globalLocalIndexMap_[idx];
1151          dataIndi(n) = dataIndex(ind);
1152          maskIndi(n) = mask(ind);
1153
1154          if (hasValue)
1155          {
1156            CArray<double,1>& val = list_val.back();
1157            val(n) = value(ind);
1158          }
1159
1160          if (hasBounds)
1161          {
1162            CArray<double,2>& boundsVal = list_bounds.back();
1163            boundsVal(0, n) = bounds(0,ind);
1164            boundsVal(1, n) = bounds(1,ind);
1165          }
1166
1167          if (hasLabel)
1168          {
1169            CArray<string,1>& labelVal = list_label.back();
1170            labelVal(n) = label(ind); 
1171          }
1172        }
1173
1174        listData.push_back(CMessage());
1175        listData.back() << this->getId()
1176                        << list_indi.back() << list_dataInd.back() << list_mask.back();
1177
1178        listData.back() << hasValue;
1179        if (hasValue)
1180          listData.back() << list_val.back();
1181
1182        listData.back() << hasBounds;
1183        if (hasBounds)
1184          listData.back() << list_bounds.back();
1185
1186        listData.back() << hasLabel;
1187        if (hasLabel)
1188          listData.back() << list_label.back();
1189
1190        eventData.push(rank, nbSenders[nbServer][rank], listData.back());
1191      }
1192
1193      client->sendEvent(eventData);
1194    }
1195  }
1196
1197  /*
1198    Receive the distributed attributes from another group of clients
1199    \param [in] event event containing data of these attributes
1200  */
1201  void CAxis::recvDistributedAttributes(CEventServer& event)
1202  {
1203    string axisId;
1204    vector<int> ranks;
1205    vector<CBufferIn*> buffers;
1206
1207    list<CEventServer::SSubEvent>::iterator it;
1208    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1209    {
1210      ranks.push_back(it->rank);
1211      CBufferIn* buffer = it->buffer;
1212      *buffer >> axisId;
1213      buffers.push_back(buffer);
1214    }
1215    get(axisId)->recvDistributedAttributes(ranks, buffers);
1216  }
1217
1218  /*
1219    Receive the non-distributed attributes from another group of clients
1220    \param [in] ranks rank of the sender
1221    \param [in] buffers buffer containing data sent from the sender
1222  */
1223  void CAxis::recvDistributedAttributes(vector<int>& ranks, vector<CBufferIn*> buffers)
1224  {
1225    int nbReceived = ranks.size(), idx, ind, gloInd, locInd;
1226    vector<CArray<int,1> > vec_indi(nbReceived), vec_dataInd(nbReceived), vec_zoomInd(nbReceived);   
1227    vector<CArray<bool,1> > vec_mask(nbReceived);
1228    vector<CArray<double,1> > vec_val(nbReceived);
1229    vector<CArray<double,2> > vec_bounds(nbReceived);
1230    vector<CArray<string,1> > vec_label(nbReceived);
1231   
1232    for (idx = 0; idx < nbReceived; ++idx)
1233    {     
1234      CBufferIn& buffer = *buffers[idx];
1235      buffer >> vec_indi[idx];
1236      buffer >> vec_dataInd[idx];     
1237      buffer >> vec_mask[idx];
1238
1239      buffer >> hasValue;
1240      if (hasValue)
1241        buffer >> vec_val[idx];
1242
1243      buffer >> hasBounds;
1244      if (hasBounds)
1245        buffer >> vec_bounds[idx];
1246
1247      buffer >> hasLabel;
1248      if (hasLabel)
1249        buffer >> vec_label[idx]; 
1250    }
1251
1252    // Estimate size of index array
1253    int nbIndexGlob = 0;
1254    for (idx = 0; idx < nbReceived; ++idx)
1255    {
1256      nbIndexGlob += vec_indi[idx].numElements();
1257    }
1258
1259    // Recompute global index
1260    // Take account of the overlapped index
1261    index.resize(nbIndexGlob);
1262    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
1263    nbIndexGlob = 0;
1264    for (idx = 0; idx < nbReceived; ++idx)
1265    {
1266      CArray<int,1>& tmp = vec_indi[idx];
1267      for (ind = 0; ind < tmp.numElements(); ++ind)
1268      {
1269         gloInd = tmp(ind);
1270         if (0 == globalLocalIndexMap_.count(gloInd))
1271         {
1272           index(nbIndexGlob) = gloInd % n_glo;           
1273           globalLocalIndexMap_[gloInd] = nbIndexGlob; 
1274           ++nbIndexGlob;
1275         } 
1276      } 
1277    }
1278
1279    // Resize index to its real size
1280    if (nbIndexGlob==0) index.resize(nbIndexGlob) ;
1281    else index.resizeAndPreserve(nbIndexGlob);
1282
1283    int nbData = nbIndexGlob;
1284    CArray<int,1> nonCompressedData(nbData);
1285    nonCompressedData = -1;   
1286    mask.resize(nbData);
1287    if (hasValue)
1288      value.resize(nbData);
1289    if (hasBounds)
1290      bounds.resize(2,nbData);
1291    if (hasLabel)
1292      label.resize(nbData);
1293
1294    nbData = 0;
1295    for (idx = 0; idx < nbReceived; ++idx)
1296    {
1297      CArray<int,1>& indi = vec_indi[idx];
1298      CArray<int,1>& dataIndi = vec_dataInd[idx];
1299      CArray<bool,1>& maskIndi = vec_mask[idx];
1300      int nb = indi.numElements();
1301      for (int n = 0; n < nb; ++n)
1302      { 
1303        locInd = globalLocalIndexMap_[size_t(indi(n))];
1304
1305        nonCompressedData(locInd) = (-1 == nonCompressedData(locInd)) ? dataIndi(n) : nonCompressedData(locInd);
1306
1307        if (!mask(locInd)) // Only rewrite mask if it's not true
1308          mask(locInd) = maskIndi(n);
1309       
1310        if (hasValue)
1311          value(locInd) = vec_val[idx](n);
1312
1313        if (hasBounds)
1314        {
1315          bounds(0,locInd) = vec_bounds[idx](0,n);
1316          bounds(1,locInd) = vec_bounds[idx](1,n);
1317        }
1318
1319        if (hasLabel)
1320          label(locInd) = vec_label[idx](n);
1321      }
1322    }
1323   
1324    int nbCompressedData = 0; 
1325    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1326    {
1327      if (0 <= nonCompressedData(idx))
1328        ++nbCompressedData;       
1329    }
1330
1331    data_index.resize(nbCompressedData);
1332    nbCompressedData = 0;
1333    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1334    {
1335      if (0 <= nonCompressedData(idx))
1336      {
1337        data_index(nbCompressedData) = idx % n;
1338        ++nbCompressedData;       
1339      }
1340    }
1341
1342    data_begin.setValue(0);
1343  }
1344
1345  /*!
1346    Compare two axis objects.
1347    They are equal if only if they have identical attributes as well as their values.
1348    Moreover, they must have the same transformations.
1349  \param [in] axis Compared axis
1350  \return result of the comparison
1351  */
1352  bool CAxis::isEqual(CAxis* obj)
1353  {
1354    vector<StdString> excludedAttr;
1355    excludedAttr.push_back("axis_ref");
1356
1357    bool objEqual = SuperClass::isEqual(obj, excludedAttr);   
1358    if (!objEqual) return objEqual;
1359
1360    TransMapTypes thisTrans = this->getAllTransformations();
1361    TransMapTypes objTrans  = obj->getAllTransformations();
1362
1363    TransMapTypes::const_iterator it, itb, ite;
1364    std::vector<ETranformationType> thisTransType, objTransType;
1365    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
1366      thisTransType.push_back(it->first);
1367    for (it = objTrans.begin(); it != objTrans.end(); ++it)
1368      objTransType.push_back(it->first);
1369
1370    if (thisTransType.size() != objTransType.size()) return false;
1371    for (int idx = 0; idx < thisTransType.size(); ++idx)
1372      objEqual &= (thisTransType[idx] == objTransType[idx]);
1373
1374    return objEqual;
1375  }
1376
1377  /*
1378    Add transformation into axis. This function only servers for Fortran interface
1379    \param [in] transType transformation type
1380    \param [in] id identifier of the transformation object
1381  */
1382  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
1383  {
1384    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
1385    return transformationMap_.back().second;
1386  }
1387
1388  /*
1389    Check whether an axis has (spatial) transformation
1390  */
1391  bool CAxis::hasTransformation()
1392  {
1393    return (!transformationMap_.empty());
1394  }
1395
1396  /*
1397    Set transformation
1398    \param [in] axisTrans transformation to set
1399  */
1400  void CAxis::setTransformations(const TransMapTypes& axisTrans)
1401  {
1402    transformationMap_ = axisTrans;
1403  }
1404
1405  /*
1406    Return all transformation held by the axis
1407    \return transformation the axis has
1408  */
1409  CAxis::TransMapTypes CAxis::getAllTransformations(void)
1410  {
1411    return transformationMap_;
1412  }
1413
1414  /*
1415    Duplicate transformation of another axis
1416    \param [in] src axis whose transformations are copied
1417  */
1418  void CAxis::duplicateTransformation(CAxis* src)
1419  {
1420    if (src->hasTransformation())
1421    {
1422      this->setTransformations(src->getAllTransformations());
1423    }
1424  }
1425
1426  /*!
1427   * Go through the hierarchy to find the axis from which the transformations must be inherited
1428   */
1429  void CAxis::solveInheritanceTransformation()
1430  {
1431    if (hasTransformation() || !hasDirectAxisReference())
1432      return;
1433
1434    CAxis* axis = this;
1435    std::vector<CAxis*> refAxis;
1436    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
1437    {
1438      refAxis.push_back(axis);
1439      axis = axis->getDirectAxisReference();
1440    }
1441
1442    if (axis->hasTransformation())
1443      for (size_t i = 0; i < refAxis.size(); ++i)
1444        refAxis[i]->setTransformations(axis->getAllTransformations());
1445  }
1446
1447  void CAxis::setContextClient(CContextClient* contextClient)
1448  {
1449    if (clientsSet.find(contextClient)==clientsSet.end())
1450    {
1451      clients.push_back(contextClient) ;
1452      clientsSet.insert(contextClient);
1453    }
1454}
1455
1456  void CAxis::parse(xml::CXMLNode & node)
1457  {
1458    SuperClass::parse(node);
1459
1460    if (node.goToChildElement())
1461    {
1462      StdString nodeElementName;
1463      do
1464      {
1465        StdString nodeId("");
1466        if (node.getAttributes().end() != node.getAttributes().find("id"))
1467        { nodeId = node.getAttributes()["id"]; }
1468
1469        nodeElementName = node.getElementName();
1470
1471        if(transformationMapList_ptr == 0) initializeTransformationMap();
1472        std::map<StdString, ETranformationType>::const_iterator ite = (*CAxis::transformationMapList_ptr).end(), it;
1473        it = (*CAxis::transformationMapList_ptr).find(nodeElementName);
1474        if (ite != it)
1475        {
1476          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second,
1477                                                                                                               nodeId,
1478                                                                                                               &node)));
1479        }
1480        else
1481        {
1482          ERROR("void CAxis::parse(xml::CXMLNode & node)",
1483                << "The transformation " << nodeElementName << " has not been supported yet.");
1484        }
1485      } while (node.goToNextElement()) ;
1486      node.goToParentElement();
1487    }
1488  }
1489
1490  DEFINE_REF_FUNC(Axis,axis)
1491
1492   ///---------------------------------------------------------------
1493
1494} // namespace xios
Note: See TracBrowser for help on using the repository browser.