source: XIOS/dev/dev_olga/src/node/axis.cpp @ 1568

Last change on this file since 1568 was 1568, checked in by oabramkina, 3 years ago

Grid mask is now applied in the source filter of clients: unmasked values are replaced by NaN. It is not reconstructed any more by servers.

This needs to be tested more rigorously before commiting to trunk.

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