source: XIOS/trunk/src/node/axis.cpp @ 1672

Last change on this file since 1672 was 1672, checked in by ymipsl, 5 years ago

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