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

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

Further simplifications on sending data/grid indexes.

(1) Domain/axis mask is not sent anymore. It has been incorporated into data index.

(2) Creating a map that holds grid mask only in case if grid mask is defined.

Still to fix: a hole in a domain or axis.

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