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

Last change on this file since 2250 was 1964, checked in by yushan, 4 years ago

trunk : Mask was not correctly applied on data when data_index is used

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