source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp @ 1853

Last change on this file since 1853 was 1853, checked in by ymipsl, 4 years ago

Coupling branch : replace hasServer and hasClient combination by the name of correct service : CLIENT, GATHERER or OUT_SERVER.

YM

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