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

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

More cleaning : replace contextClient rank and size by context rank and size.
Because for couling it will have more than one contextClient.

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.0 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->hasClient)
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->hasClient)
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->hasClient && !context->hasServer) 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->hasClient)
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->hasClient) 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    CContextServer* server = context->server; 
737
738    // We describe the distribution of client (server) on which data are written
739    std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1);
740    nBegin[0]       = begin;
741    nSize[0]        = n;
742    nBeginGlobal[0] = 0; 
743    nGlob[0]        = n_glo;
744    CDistributionServer srvDist(server->intraCommSize, nBegin, nSize, nBeginGlobal, nGlob); 
745    const CArray<size_t,1>& writtenGlobalIndex  = srvDist.getGlobalIndex();
746
747    // Because all written data are local on a client,
748    // we need to compute the local index on the server from its corresponding global index
749    size_t nbWritten = 0, indGlo;     
750    std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
751                                                        ite = globalLocalIndexMap_.end(), it;         
752    CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
753                                     itSrve = writtenGlobalIndex.end(), itSrv; 
754
755    localIndexToWriteOnServer.resize(writtenGlobalIndex.numElements());
756    nbWritten = 0;
757    for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
758    {
759      indGlo = *itSrv;
760      if (ite != globalLocalIndexMap_.find(indGlo))
761      {
762        localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[indGlo];
763      }
764      else
765      {
766        localIndexToWriteOnServer(nbWritten) = -1;
767      }
768      ++nbWritten;
769    }
770
771  }
772  CATCH_DUMP_ATTR
773
774  void CAxis::computeWrittenCompressedIndex(MPI_Comm writtenComm)
775  TRY
776  {
777    int writtenCommSize;
778    MPI_Comm_size(writtenComm, &writtenCommSize);
779    if (compressedIndexToWriteOnServer.find(writtenCommSize) != compressedIndexToWriteOnServer.end())
780      return;
781
782    if (isCompressible())
783    {
784      size_t nbWritten = 0, indGlo;
785      CContext* context=CContext::getCurrent();     
786      CContextServer* server = context->server; 
787
788      // We describe the distribution of client (server) on which data are written
789      std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1);
790      nBegin[0]       = 0;
791      nSize[0]        = n;
792      nBeginGlobal[0] = 0; 
793      nGlob[0]        = n_glo;
794      CDistributionServer srvDist(server->intraCommSize, nBegin, nSize, nBeginGlobal, nGlob); 
795      const CArray<size_t,1>& writtenGlobalIndex  = srvDist.getGlobalIndex();
796      std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
797                                                          ite = globalLocalIndexMap_.end(), it;   
798
799      CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
800                                       itSrve = writtenGlobalIndex.end(), itSrv;
801      std::unordered_map<size_t,size_t> localGlobalIndexMap;
802      for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
803      {
804        indGlo = *itSrv;
805        if (ite != globalLocalIndexMap_.find(indGlo))
806        {
807          localGlobalIndexMap[localIndexToWriteOnServer(nbWritten)] = indGlo;
808          ++nbWritten;
809        }                 
810      }
811//
812//      nbWritten = 0;
813//      for (int idx = 0; idx < data_index.numElements(); ++idx)
814//      {
815//        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
816//        {
817//          ++nbWritten;
818//        }
819//      }
820//
821//      compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten);
822//      nbWritten = 0;
823//      for (int idx = 0; idx < data_index.numElements(); ++idx)
824//      {
825//        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
826//        {
827//          compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)];
828//          ++nbWritten;
829//        }
830//      }
831
832      nbWritten = 0;
833      for (int idx = 0; idx < data_index.numElements(); ++idx)
834      {
835        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
836        {
837          ++nbWritten;
838        }
839      }
840
841      compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten);
842      nbWritten = 0;
843      for (int idx = 0; idx < data_index.numElements(); ++idx)
844      {
845        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
846        {
847          compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)];
848          ++nbWritten;
849        }
850      }
851
852      numberWrittenIndexes_[writtenCommSize] = nbWritten;
853
854      bool distributed_glo, distributed=isDistributed() ;
855      MPI_Allreduce(&distributed,&distributed_glo, 1, MPI_INT, MPI_LOR, writtenComm) ;
856      if (distributed_glo)
857      {
858             
859        MPI_Allreduce(&numberWrittenIndexes_[writtenCommSize], &totalNumberWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
860        MPI_Scan(&numberWrittenIndexes_[writtenCommSize], &offsetWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
861        offsetWrittenIndexes_[writtenCommSize] -= numberWrittenIndexes_[writtenCommSize];
862      }
863      else
864        totalNumberWrittenIndexes_[writtenCommSize] = numberWrittenIndexes_[writtenCommSize];
865    }
866  }
867  CATCH_DUMP_ATTR
868
869  /*!
870    Send distribution information from a group of client (client role) to another group of client (server role)
871    The distribution of a group of client (server role) is imposed by the group of client (client role)
872    \param [in] globalDim global dimension of grid containing this axis
873    \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2)
874    \param [in] distType distribution type of the server. For now, we only have band distribution.
875  */
876  void CAxis::sendDistributionAttribute(const std::vector<int>& globalDim, int orderPositionInGrid,
877                                        CServerDistributionDescription::ServerDistributionType distType)
878  TRY
879  {
880    std::list<CContextClient*>::iterator it;
881    for (it=clients.begin(); it!=clients.end(); ++it)
882    {
883      CContextClient* client = *it;
884      int nbServer = client->serverSize;
885
886      CServerDistributionDescription serverDescription(globalDim, nbServer);
887      serverDescription.computeServerDistribution();
888
889      std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
890      std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
891
892      CEventClient event(getType(),EVENT_ID_DISTRIBUTION_ATTRIBUTE);
893      if (client->isServerLeader())
894      {
895        std::list<CMessage> msgs;
896
897        const std::list<int>& ranks = client->getRanksServerLeader();
898        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
899        {
900          // Use const int to ensure CMessage holds a copy of the value instead of just a reference
901          const int begin = serverIndexBegin[*itRank][orderPositionInGrid];
902          const int ni    = serverDimensionSizes[*itRank][orderPositionInGrid];
903
904          msgs.push_back(CMessage());
905          CMessage& msg = msgs.back();
906          msg << this->getId();
907          msg << ni << begin;
908          msg << isCompressible_;                   
909
910          event.push(*itRank,1,msg);
911        }
912        client->sendEvent(event);
913      }
914      else client->sendEvent(event);
915    }
916  }
917  CATCH_DUMP_ATTR
918
919  /*
920    Receive distribution attribute from another client
921    \param [in] event event containing data of these attributes
922  */
923  void CAxis::recvDistributionAttribute(CEventServer& event)
924  TRY
925  {
926    CBufferIn* buffer = event.subEvents.begin()->buffer;
927    string axisId;
928    *buffer >> axisId;
929    get(axisId)->recvDistributionAttribute(*buffer);
930  }
931  CATCH
932
933  /*
934    Receive distribution attribute from another client
935    \param [in] buffer buffer containing data of these attributes
936  */
937  void CAxis::recvDistributionAttribute(CBufferIn& buffer)
938  TRY
939  {
940    int ni_srv, begin_srv;
941    buffer >> ni_srv >> begin_srv;
942    buffer >> isCompressible_;           
943
944    // Set up new local size of axis on the receiving clients
945    n.setValue(ni_srv);
946    begin.setValue(begin_srv);
947  }
948  CATCH_DUMP_ATTR
949
950  /*
951    Send attributes of axis from a group of client to other group of clients/servers
952    on supposing that these attributes are not distributed among the sending group
953    In the future, if new attributes are added, they should also be processed in this function
954  */
955  void CAxis::sendNonDistributedAttributes()
956  TRY
957  {
958    std::list<CContextClient*>::iterator it;
959    for (it=clients.begin(); it!=clients.end(); ++it)
960        {
961          CContextClient* client = *it;
962
963      CEventClient event(getType(), EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES);
964      size_t nbIndex = index.numElements();
965      size_t nbDataIndex = 0;
966
967      for (int idx = 0; idx < data_index.numElements(); ++idx)
968      {
969        int ind = data_index(idx);
970        if (ind >= 0 && ind < nbIndex) ++nbDataIndex;
971      }
972
973      CArray<int,1> dataIndex(nbDataIndex);
974      nbDataIndex = 0;
975      for (int idx = 0; idx < data_index.numElements(); ++idx)
976      {
977        int ind = data_index(idx);
978        if (ind >= 0 && ind < nbIndex)
979        {
980          dataIndex(nbDataIndex) = ind;
981          ++nbDataIndex;
982        }
983      }
984
985      if (client->isServerLeader())
986      {
987        std::list<CMessage> msgs;
988
989        const std::list<int>& ranks = client->getRanksServerLeader();
990        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
991        {
992          msgs.push_back(CMessage());
993          CMessage& msg = msgs.back();
994          msg << this->getId();
995          msg << index.getValue() << dataIndex << mask.getValue();
996          msg << hasValue;
997          if (hasValue) msg << value.getValue();
998          msg << hasBounds;
999          if (hasBounds) msg << bounds.getValue();
1000          msg << hasLabel;
1001          if (hasLabel) msg << label.getValue();
1002
1003          event.push(*itRank, 1, msg);
1004        }
1005        client->sendEvent(event);
1006      }
1007      else client->sendEvent(event);
1008    }
1009  }
1010  CATCH_DUMP_ATTR
1011
1012  /*
1013    Receive the non-distributed attributes from another group of clients
1014    \param [in] event event containing data of these attributes
1015  */
1016  void CAxis::recvNonDistributedAttributes(CEventServer& event)
1017  TRY
1018  {
1019    list<CEventServer::SSubEvent>::iterator it;
1020    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1021    {
1022      CBufferIn* buffer = it->buffer;
1023      string axisId;
1024      *buffer >> axisId;
1025      get(axisId)->recvNonDistributedAttributes(it->rank, *buffer);
1026    }
1027  }
1028  CATCH
1029
1030  /*
1031    Receive the non-distributed attributes from another group of clients
1032    \param [in] rank rank of the sender
1033    \param [in] buffer buffer containing data sent from the sender
1034  */
1035  void CAxis::recvNonDistributedAttributes(int rank, CBufferIn& buffer)
1036  TRY
1037  { 
1038    CArray<int,1> tmp_index, tmp_data_index;
1039    CArray<bool,1> tmp_mask;
1040    CArray<double,1> tmp_val;
1041    CArray<double,2> tmp_bnds;
1042    CArray<string,1> tmp_label;
1043
1044    buffer >> tmp_index;
1045    index.reference(tmp_index);
1046    buffer >> tmp_data_index;
1047    data_index.reference(tmp_data_index);
1048    buffer >> tmp_mask;
1049    mask.reference(tmp_mask);
1050
1051    buffer >> hasValue;
1052    if (hasValue)
1053    {
1054      buffer >> tmp_val;
1055      value.reference(tmp_val);
1056    }
1057
1058    buffer >> hasBounds;
1059    if (hasBounds)
1060    {
1061      buffer >> tmp_bnds;
1062      bounds.reference(tmp_bnds);
1063    }
1064
1065    buffer >> hasLabel;
1066    if (hasLabel)
1067    {
1068      buffer >> tmp_label;
1069      label.reference(tmp_label);
1070    }
1071
1072    // Some value should be reset here
1073    data_begin.setValue(0);
1074    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
1075//    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[idx] = index(idx);
1076    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[index(idx)] = idx;
1077  }
1078  CATCH_DUMP_ATTR
1079
1080  /*
1081    Send axis attributes from a group of clients to another group of clients/servers
1082    supposing that these attributes are distributed among the clients of the sending group
1083    In future, if new attributes are added, they should also be processed in this function
1084  */
1085  void CAxis::sendDistributedAttributes(void)
1086  TRY
1087  {
1088    int ind, idx;
1089    std::list<CContextClient*>::iterator it;
1090
1091    for (it=clients.begin(); it!=clients.end(); ++it)
1092    {
1093      CContextClient* client = *it;
1094      int nbServer = client->serverSize;
1095
1096      CEventClient eventData(getType(), EVENT_ID_DISTRIBUTED_ATTRIBUTES);
1097
1098      list<CMessage> listData;
1099      list<CArray<int,1> > list_indi, list_dataInd;
1100      list<CArray<double,1> > list_val;
1101      list<CArray<double,2> > list_bounds;
1102      list<CArray<string,1> > list_label;
1103
1104      // Cut off the ghost points
1105      int nbIndex = index.numElements();
1106      CArray<int,1> dataIndex(nbIndex);
1107      dataIndex = -1;
1108      for (idx = 0; idx < data_index.numElements(); ++idx)
1109      {
1110        if (0 <= data_index(idx) && data_index(idx) < nbIndex)
1111          dataIndex(data_index(idx)) = 1;
1112      }
1113
1114      std::unordered_map<int, std::vector<size_t> >::const_iterator it, iteMap;
1115      iteMap = indSrv_[nbServer].end();
1116      for (int k = 0; k < connectedServerRank_[nbServer].size(); ++k)
1117      {
1118        int nbData = 0, nbDataCount = 0;
1119        int rank = connectedServerRank_[nbServer][k];
1120        it = indSrv_[nbServer].find(rank);
1121        if (iteMap != it)
1122          nbData = it->second.size();
1123
1124        list_indi.push_back(CArray<int,1>(nbData));
1125        list_dataInd.push_back(CArray<int,1>(nbData));
1126
1127        if (hasValue)
1128          list_val.push_back(CArray<double,1>(nbData));
1129
1130        if (hasBounds)       
1131          list_bounds.push_back(CArray<double,2>(2,nbData));
1132
1133        if (hasLabel)
1134          list_label.push_back(CArray<string,1>(nbData));
1135
1136        CArray<int,1>& indi = list_indi.back();
1137        CArray<int,1>& dataIndi = list_dataInd.back();
1138        dataIndi = -1;
1139
1140        for (int n = 0; n < nbData; ++n)
1141        {
1142          idx = static_cast<int>(it->second[n]);
1143          indi(n) = idx;
1144
1145          ind = globalLocalIndexMap_[idx];
1146          dataIndi(n) = dataIndex(ind);
1147
1148          if (hasValue)
1149          {
1150            CArray<double,1>& val = list_val.back();
1151            val(n) = value(ind);
1152          }
1153
1154          if (hasBounds)
1155          {
1156            CArray<double,2>& boundsVal = list_bounds.back();
1157            boundsVal(0, n) = bounds(0,ind);
1158            boundsVal(1, n) = bounds(1,ind);
1159          }
1160
1161          if (hasLabel)
1162          {
1163            CArray<string,1>& labelVal = list_label.back();
1164            labelVal(n) = label(ind); 
1165          }
1166        }
1167
1168        listData.push_back(CMessage());
1169        listData.back() << this->getId()
1170                        << list_indi.back() << list_dataInd.back();
1171
1172        listData.back() << hasValue;
1173        if (hasValue)
1174          listData.back() << list_val.back();
1175
1176        listData.back() << hasBounds;
1177        if (hasBounds)
1178          listData.back() << list_bounds.back();
1179
1180        listData.back() << hasLabel;
1181        if (hasLabel)
1182          listData.back() << list_label.back();
1183
1184        eventData.push(rank, nbSenders[nbServer][rank], listData.back());
1185      }
1186
1187      client->sendEvent(eventData);
1188    }
1189  }
1190  CATCH_DUMP_ATTR
1191
1192  /*
1193    Receive the distributed attributes from another group of clients
1194    \param [in] event event containing data of these attributes
1195  */
1196  void CAxis::recvDistributedAttributes(CEventServer& event)
1197  TRY
1198  {
1199    string axisId;
1200    vector<int> ranks;
1201    vector<CBufferIn*> buffers;
1202
1203    list<CEventServer::SSubEvent>::iterator it;
1204    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1205    {
1206      ranks.push_back(it->rank);
1207      CBufferIn* buffer = it->buffer;
1208      *buffer >> axisId;
1209      buffers.push_back(buffer);
1210    }
1211    get(axisId)->recvDistributedAttributes(ranks, buffers);
1212  }
1213  CATCH
1214
1215  /*
1216    Receive the non-distributed attributes from another group of clients
1217    \param [in] ranks rank of the sender
1218    \param [in] buffers buffer containing data sent from the sender
1219  */
1220  void CAxis::recvDistributedAttributes(vector<int>& ranks, vector<CBufferIn*> buffers)
1221  TRY
1222  {
1223    int nbReceived = ranks.size(), idx, ind, gloInd, locInd;
1224    vector<CArray<int,1> > vec_indi(nbReceived), vec_dataInd(nbReceived);
1225    vector<CArray<double,1> > vec_val(nbReceived);
1226    vector<CArray<double,2> > vec_bounds(nbReceived);
1227    vector<CArray<string,1> > vec_label(nbReceived);
1228   
1229    for (idx = 0; idx < nbReceived; ++idx)
1230    {     
1231      CBufferIn& buffer = *buffers[idx];
1232      buffer >> vec_indi[idx];
1233      buffer >> vec_dataInd[idx];     
1234
1235      buffer >> hasValue;
1236      if (hasValue)
1237        buffer >> vec_val[idx];
1238
1239      buffer >> hasBounds;
1240      if (hasBounds)
1241        buffer >> vec_bounds[idx];
1242
1243      buffer >> hasLabel;
1244      if (hasLabel)
1245        buffer >> vec_label[idx]; 
1246    }
1247
1248    // Estimate size of index array
1249    int nbIndexGlob = 0;
1250    for (idx = 0; idx < nbReceived; ++idx)
1251    {
1252      nbIndexGlob += vec_indi[idx].numElements();
1253    }
1254
1255    // Recompute global index
1256    // Take account of the overlapped index
1257    index.resize(nbIndexGlob);
1258    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
1259    nbIndexGlob = 0;
1260    int nbIndLoc = 0;
1261    for (idx = 0; idx < nbReceived; ++idx)
1262    {
1263      CArray<int,1>& tmp = vec_indi[idx];
1264      for (ind = 0; ind < tmp.numElements(); ++ind)
1265      {
1266         gloInd = tmp(ind);
1267         nbIndLoc = (gloInd % n_glo)-begin;
1268         if (0 == globalLocalIndexMap_.count(gloInd))
1269         {
1270           index(nbIndexGlob) = gloInd % n_glo;
1271           globalLocalIndexMap_[gloInd] = nbIndexGlob;
1272           ++nbIndexGlob;
1273         } 
1274      } 
1275    }
1276
1277    // Resize index to its real size
1278    if (nbIndexGlob==0) index.resize(nbIndexGlob) ;
1279    else index.resizeAndPreserve(nbIndexGlob);
1280
1281    int nbData = nbIndexGlob;
1282    CArray<int,1> nonCompressedData(nbData);
1283    nonCompressedData = -1;   
1284    // Mask is incorporated into data_index and is not sent/received anymore
1285    mask.resize(0);
1286    if (hasValue)
1287      value.resize(nbData);
1288    if (hasBounds)
1289      bounds.resize(2,nbData);
1290    if (hasLabel)
1291      label.resize(nbData);
1292
1293    nbData = 0;
1294    for (idx = 0; idx < nbReceived; ++idx)
1295    {
1296      CArray<int,1>& indi = vec_indi[idx];
1297      CArray<int,1>& dataIndi = vec_dataInd[idx];
1298      int nb = indi.numElements();
1299      for (int n = 0; n < nb; ++n)
1300      { 
1301        locInd = globalLocalIndexMap_[size_t(indi(n))];
1302
1303        nonCompressedData(locInd) = (-1 == nonCompressedData(locInd)) ? dataIndi(n) : nonCompressedData(locInd);
1304
1305        if (hasValue)
1306          value(locInd) = vec_val[idx](n);
1307
1308        if (hasBounds)
1309        {
1310          bounds(0,locInd) = vec_bounds[idx](0,n);
1311          bounds(1,locInd) = vec_bounds[idx](1,n);
1312        }
1313
1314        if (hasLabel)
1315          label(locInd) = vec_label[idx](n);
1316      }
1317    }
1318   
1319    int nbCompressedData = 0;
1320    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1321    {
1322      if (0 <= nonCompressedData(idx))
1323        ++nbCompressedData;
1324    }
1325
1326    data_index.resize(nbCompressedData);
1327    nbCompressedData = 0;
1328    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1329    {
1330      if (0 <= nonCompressedData(idx))
1331      {
1332        data_index(nbCompressedData) = idx % n;
1333        ++nbCompressedData;
1334      }
1335    }
1336
1337    data_begin.setValue(0);
1338    data_n.setValue(data_index.numElements());
1339  }
1340  CATCH_DUMP_ATTR
1341
1342  /*!
1343    Compare two axis objects.
1344    They are equal if only if they have identical attributes as well as their values.
1345    Moreover, they must have the same transformations.
1346  \param [in] axis Compared axis
1347  \return result of the comparison
1348  */
1349  bool CAxis::isEqual(CAxis* obj)
1350  TRY
1351  {
1352    vector<StdString> excludedAttr;
1353    excludedAttr.push_back("axis_ref");
1354
1355    bool objEqual = SuperClass::isEqual(obj, excludedAttr);   
1356    if (!objEqual) return objEqual;
1357
1358    TransMapTypes thisTrans = this->getAllTransformations();
1359    TransMapTypes objTrans  = obj->getAllTransformations();
1360
1361    TransMapTypes::const_iterator it, itb, ite;
1362    std::vector<ETranformationType> thisTransType, objTransType;
1363    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
1364      thisTransType.push_back(it->first);
1365    for (it = objTrans.begin(); it != objTrans.end(); ++it)
1366      objTransType.push_back(it->first);
1367
1368    if (thisTransType.size() != objTransType.size()) return false;
1369    for (int idx = 0; idx < thisTransType.size(); ++idx)
1370      objEqual &= (thisTransType[idx] == objTransType[idx]);
1371
1372    return objEqual;
1373  }
1374  CATCH_DUMP_ATTR
1375
1376  /*
1377    Add transformation into axis. This function only servers for Fortran interface
1378    \param [in] transType transformation type
1379    \param [in] id identifier of the transformation object
1380  */
1381  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
1382  TRY
1383  {
1384    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
1385    return transformationMap_.back().second;
1386  }
1387  CATCH_DUMP_ATTR
1388
1389  /*
1390    Check whether an axis has (spatial) transformation
1391  */
1392  bool CAxis::hasTransformation()
1393  TRY
1394  {
1395    return (!transformationMap_.empty());
1396  }
1397  CATCH_DUMP_ATTR
1398
1399  /*
1400    Set transformation
1401    \param [in] axisTrans transformation to set
1402  */
1403  void CAxis::setTransformations(const TransMapTypes& axisTrans)
1404  TRY
1405  {
1406    transformationMap_ = axisTrans;
1407  }
1408  CATCH_DUMP_ATTR
1409
1410  /*
1411    Return all transformation held by the axis
1412    \return transformation the axis has
1413  */
1414  CAxis::TransMapTypes CAxis::getAllTransformations(void)
1415  TRY
1416  {
1417    return transformationMap_;
1418  }
1419  CATCH_DUMP_ATTR
1420
1421  /*
1422    Duplicate transformation of another axis
1423    \param [in] src axis whose transformations are copied
1424  */
1425  void CAxis::duplicateTransformation(CAxis* src)
1426  TRY
1427  {
1428    if (src->hasTransformation())
1429    {
1430      this->setTransformations(src->getAllTransformations());
1431    }
1432  }
1433  CATCH_DUMP_ATTR
1434
1435  /*!
1436   * Go through the hierarchy to find the axis from which the transformations must be inherited
1437   */
1438  void CAxis::solveInheritanceTransformation()
1439  TRY
1440  {
1441    if (hasTransformation() || !hasDirectAxisReference())
1442      return;
1443
1444    CAxis* axis = this;
1445    std::vector<CAxis*> refAxis;
1446    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
1447    {
1448      refAxis.push_back(axis);
1449      axis = axis->getDirectAxisReference();
1450    }
1451
1452    if (axis->hasTransformation())
1453      for (size_t i = 0; i < refAxis.size(); ++i)
1454        refAxis[i]->setTransformations(axis->getAllTransformations());
1455  }
1456  CATCH_DUMP_ATTR
1457
1458  void CAxis::setContextClient(CContextClient* contextClient)
1459  TRY
1460  {
1461    if (clientsSet.find(contextClient)==clientsSet.end())
1462    {
1463      clients.push_back(contextClient) ;
1464      clientsSet.insert(contextClient);
1465    }
1466  }
1467  CATCH_DUMP_ATTR
1468
1469  void CAxis::parse(xml::CXMLNode & node)
1470  TRY
1471  {
1472    SuperClass::parse(node);
1473
1474    if (node.goToChildElement())
1475    {
1476      StdString nodeElementName;
1477      do
1478      {
1479        StdString nodeId("");
1480        if (node.getAttributes().end() != node.getAttributes().find("id"))
1481        { nodeId = node.getAttributes()["id"]; }
1482
1483        nodeElementName = node.getElementName();
1484        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
1485        it = transformationMapList_.find(nodeElementName);
1486        if (ite != it)
1487        {
1488          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second,
1489                                                                                                               nodeId,
1490                                                                                                               &node)));
1491        }
1492        else
1493        {
1494          ERROR("void CAxis::parse(xml::CXMLNode & node)",
1495                << "The transformation " << nodeElementName << " has not been supported yet.");
1496        }
1497      } while (node.goToNextElement()) ;
1498      node.goToParentElement();
1499    }
1500  }
1501  CATCH_DUMP_ATTR
1502
1503  DEFINE_REF_FUNC(Axis,axis)
1504
1505   ///---------------------------------------------------------------
1506
1507} // namespace xios
Note: See TracBrowser for help on using the repository browser.