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

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

Taking care of cases when a process doesn't possess a grid (its domain or axe size is zero).

Tested with CMIP6 toy models and IPSL model.

To do: remove grid mask from transformations.

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