source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp @ 1869

Last change on this file since 1869 was 1869, checked in by ymipsl, 18 months ago

Some update...

YM

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