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

Last change on this file since 1870 was 1870, checked in by ymipsl, 4 years ago

Some update on XIOS_COUPLING branch...

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   //ym obsolete : to be removed
549   void CAxis::sendCheckedAttributes(const std::vector<int>& globalDim, int orderPositionInGrid,
550                                     CServerDistributionDescription::ServerDistributionType distType)
551   TRY
552   {
553     if (!this->areClientAttributesChecked_) checkAttributesOnClient();
554     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation(globalDim, orderPositionInGrid, distType);
555     CContext* context = CContext::getCurrent();
556
557     if (this->isChecked) return;
558     if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) /*sendAttributes(globalDim, orderPositionInGrid, distType)*/;   
559
560     this->isChecked = true;
561   }
562   CATCH_DUMP_ATTR
563
564 
565   void CAxis::sendAxisToFileServer(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid)
566   {
567     if (sendAxisToFileServer_done_.count(client)!=0) return ;
568     else sendAxisToFileServer_done_.insert(client) ;
569     
570     StdString axisDefRoot("axis_definition");
571     CAxisGroup* axisPtr = CAxisGroup::get(axisDefRoot);
572     axisPtr->sendCreateChild(this->getId(),client);
573     this->sendAllAttributesToServer(client)  ; 
574     this->sendAttributes(client, globalDim, orderPositionInGrid, CServerDistributionDescription::BAND_DISTRIBUTION) ;
575   }
576
577  /*!
578    Send attributes from one client to other clients
579    \param[in] globalDim global dimension of grid which contains this axis
580    \param[in] order
581  */
582  void CAxis::sendAttributes(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
583                             CServerDistributionDescription::ServerDistributionType distType)
584  TRY
585  {
586     sendDistributionAttribute(client, globalDim, orderPositionInGrid, distType);
587
588     // if (index.numElements() == n_glo.getValue())
589     if ((orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
590         || (index.numElements() != n_glo))
591     {
592       sendDistributedAttributes(client);       
593     }
594     else
595     {
596       sendNonDistributedAttributes(client);   
597     }     
598  }
599  CATCH_DUMP_ATTR
600
601  /*
602    Compute the connection between group of clients (or clients/servers).
603    (E.g: Suppose we have 2 group of clients in two model: A (client role) connect to B (server role),
604    this function calculate number of clients B connect to one client of A)
605     \param [in] globalDim global dimension of grid containing this axis
606     \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2)
607     \param [in] distType distribution type of the server. For now, we only have band distribution.
608  */
609  void CAxis::computeConnectedClients(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid)
610  TRY
611  {
612    if (computeConnectedClients_done_.count(client)!=0) return ;
613    else computeConnectedClients_done_.insert(client) ;
614
615    CContext* context = CContext::getCurrent();
616    CServerDistributionDescription::ServerDistributionType distType ;
617    int defaultDistributedPos = CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), CServerDistributionDescription::BAND_DISTRIBUTION) ;
618   
619    if (orderPositionInGrid == defaultDistributedPos) distType =  CServerDistributionDescription::BAND_DISTRIBUTION ;
620    else if (index.numElements() != n_glo) distType =  CServerDistributionDescription::ROOT_DISTRIBUTION ;
621    else return ;
622
623    int nbServer = client->serverSize;
624    int range, clientSize = client->clientSize;
625    int rank = client->clientRank;
626
627    if (listNbServer_.count(nbServer) == 0)
628    {
629      listNbServer_.insert(nbServer) ;
630
631      if (connectedServerRank_.find(nbServer) != connectedServerRank_.end())
632      {
633        nbSenders.erase(nbServer);
634        connectedServerRank_.erase(nbServer);
635      }
636
637      size_t ni = this->n.getValue();
638      size_t ibegin = this->begin.getValue();
639      size_t nbIndex = index.numElements();
640
641      // First of all, we should compute the mapping of the global index and local index of the current client
642      if (globalLocalIndexMap_.empty())
643      {
644        for (size_t idx = 0; idx < nbIndex; ++idx)
645        {
646          globalLocalIndexMap_[index(idx)] = idx;
647        }
648      }
649
650      // Calculate the compressed index if any
651      //        std::set<int> writtenInd;
652      //        if (isCompressible_)
653      //        {
654      //          for (int idx = 0; idx < data_index.numElements(); ++idx)
655      //          {
656      //            int ind = CDistributionClient::getAxisIndex(data_index(idx), data_begin, ni);
657      //
658      //            if (ind >= 0 && ind < ni && mask(ind))
659      //            {
660      //              ind += ibegin;
661      //              writtenInd.insert(ind);
662      //            }
663      //          }
664      //        }
665
666      // Compute the global index of the current client (process) hold
667      std::vector<int> nGlobAxis(1);
668      nGlobAxis[0] = n_glo.getValue();
669
670      size_t globalSizeIndex = 1, indexBegin, indexEnd;
671      for (int i = 0; i < nGlobAxis.size(); ++i) globalSizeIndex *= nGlobAxis[i];
672      indexBegin = 0;
673      if (globalSizeIndex <= clientSize)
674      {
675        indexBegin = rank%globalSizeIndex;
676        indexEnd = indexBegin;
677      }
678      else
679      {
680        for (int i = 0; i < clientSize; ++i)
681        {
682          range = globalSizeIndex / clientSize;
683          if (i < (globalSizeIndex%clientSize)) ++range;
684          if (i == client->clientRank) break;
685          indexBegin += range;
686        }
687        indexEnd = indexBegin + range - 1;
688      }
689
690      CArray<size_t,1> globalIndex(index.numElements());
691      for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
692        globalIndex(idx) = index(idx);
693
694      // Describe the distribution of server side
695
696      CServerDistributionDescription serverDescription(nGlobAxis, nbServer, distType);
697   
698      std::vector<int> serverZeroIndex;
699      serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0);
700
701      std::list<int> serverZeroIndexLeader;
702      std::list<int> serverZeroIndexNotLeader; 
703      CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader);
704      for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
705        *it = serverZeroIndex[*it];
706
707      // Find out the connection between client and server side
708      CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm);
709      clientServerMap->computeServerIndexMapping(globalIndex, nbServer);
710      CClientServerMapping::GlobalIndexMap& globalIndexAxisOnServer = clientServerMap->getGlobalIndexOnServer();     
711
712      indSrv_[nbServer].swap(globalIndexAxisOnServer);
713
714      if (distType==CServerDistributionDescription::ROOT_DISTRIBUTION)
715      {
716        for(int i=1; i<nbServer; ++i) indSrv_[nbServer].insert(pair<int, vector<size_t> >(i,indSrv_[nbServer][0]) ) ;
717        serverZeroIndexLeader.clear() ;
718      }
719       
720      CClientServerMapping::GlobalIndexMap::const_iterator it  = indSrv_[nbServer].begin(),
721                                                           ite = indSrv_[nbServer].end();
722
723      for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first);
724
725      for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
726        connectedServerRank_[nbServer].push_back(*it);
727
728       // Even if a client has no index, it must connect to at least one server and
729       // send an "empty" data to this server
730       if (connectedServerRank_[nbServer].empty())
731        connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize);
732
733      nbSenders[nbServer] = CClientServerMapping::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]);
734
735      delete clientServerMap;
736    }
737  }
738  CATCH_DUMP_ATTR
739
740  /*
741    Compute the index of data to write into file
742    (Different from the previous version, this version of XIOS allows data be written into file (classical role),
743    or transfered to another clients)
744  */
745  void CAxis::computeWrittenIndex()
746  TRY
747  { 
748    if (computedWrittenIndex_) return;
749    computedWrittenIndex_ = true;
750
751    CContext* context=CContext::getCurrent();     
752
753    // We describe the distribution of client (server) on which data are written
754    std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1);
755    nBegin[0]       = begin;
756    nSize[0]        = n;
757    nBeginGlobal[0] = 0; 
758    nGlob[0]        = n_glo;
759    CDistributionServer srvDist(context->intraCommSize_, nBegin, nSize, nBeginGlobal, nGlob); 
760    const CArray<size_t,1>& writtenGlobalIndex  = srvDist.getGlobalIndex();
761
762    // Because all written data are local on a client,
763    // we need to compute the local index on the server from its corresponding global index
764    size_t nbWritten = 0, indGlo;     
765    std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
766                                                        ite = globalLocalIndexMap_.end(), it;         
767    CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
768                                     itSrve = writtenGlobalIndex.end(), itSrv; 
769
770    localIndexToWriteOnServer.resize(writtenGlobalIndex.numElements());
771    nbWritten = 0;
772    for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
773    {
774      indGlo = *itSrv;
775      if (ite != globalLocalIndexMap_.find(indGlo))
776      {
777        localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[indGlo];
778      }
779      else
780      {
781        localIndexToWriteOnServer(nbWritten) = -1;
782      }
783      ++nbWritten;
784    }
785
786  }
787  CATCH_DUMP_ATTR
788
789  void CAxis::computeWrittenCompressedIndex(MPI_Comm writtenComm)
790  TRY
791  {
792    int writtenCommSize;
793    MPI_Comm_size(writtenComm, &writtenCommSize);
794    if (compressedIndexToWriteOnServer.find(writtenCommSize) != compressedIndexToWriteOnServer.end())
795      return;
796
797    if (isCompressible())
798    {
799      size_t nbWritten = 0, indGlo;
800      CContext* context=CContext::getCurrent();     
801 
802      // We describe the distribution of client (server) on which data are written
803      std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1);
804      nBegin[0]       = 0;
805      nSize[0]        = n;
806      nBeginGlobal[0] = 0; 
807      nGlob[0]        = n_glo;
808      CDistributionServer srvDist(context->intraCommSize_, nBegin, nSize, nBeginGlobal, nGlob); 
809      const CArray<size_t,1>& writtenGlobalIndex  = srvDist.getGlobalIndex();
810      std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
811                                                          ite = globalLocalIndexMap_.end(), it;   
812
813      CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
814                                       itSrve = writtenGlobalIndex.end(), itSrv;
815      std::unordered_map<size_t,size_t> localGlobalIndexMap;
816      for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
817      {
818        indGlo = *itSrv;
819        if (ite != globalLocalIndexMap_.find(indGlo))
820        {
821          localGlobalIndexMap[localIndexToWriteOnServer(nbWritten)] = indGlo;
822          ++nbWritten;
823        }                 
824      }
825//
826//      nbWritten = 0;
827//      for (int idx = 0; idx < data_index.numElements(); ++idx)
828//      {
829//        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
830//        {
831//          ++nbWritten;
832//        }
833//      }
834//
835//      compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten);
836//      nbWritten = 0;
837//      for (int idx = 0; idx < data_index.numElements(); ++idx)
838//      {
839//        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
840//        {
841//          compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)];
842//          ++nbWritten;
843//        }
844//      }
845
846      nbWritten = 0;
847      for (int idx = 0; idx < data_index.numElements(); ++idx)
848      {
849        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
850        {
851          ++nbWritten;
852        }
853      }
854
855      compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten);
856      nbWritten = 0;
857      for (int idx = 0; idx < data_index.numElements(); ++idx)
858      {
859        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
860        {
861          compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)];
862          ++nbWritten;
863        }
864      }
865
866      numberWrittenIndexes_[writtenCommSize] = nbWritten;
867
868      bool distributed_glo, distributed=isDistributed() ;
869      MPI_Allreduce(&distributed,&distributed_glo, 1, MPI_INT, MPI_LOR, writtenComm) ;
870      if (distributed_glo)
871      {
872             
873        MPI_Allreduce(&numberWrittenIndexes_[writtenCommSize], &totalNumberWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
874        MPI_Scan(&numberWrittenIndexes_[writtenCommSize], &offsetWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
875        offsetWrittenIndexes_[writtenCommSize] -= numberWrittenIndexes_[writtenCommSize];
876      }
877      else
878        totalNumberWrittenIndexes_[writtenCommSize] = numberWrittenIndexes_[writtenCommSize];
879    }
880  }
881  CATCH_DUMP_ATTR
882
883  /*!
884    Send distribution information from a group of client (client role) to another group of client (server role)
885    The distribution of a group of client (server role) is imposed by the group of client (client role)
886    \param [in] globalDim global dimension of grid containing this axis
887    \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2)
888    \param [in] distType distribution type of the server. For now, we only have band distribution.
889  */
890  void CAxis::sendDistributionAttribute(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
891                                        CServerDistributionDescription::ServerDistributionType distType)
892  TRY
893  {
894    int nbServer = client->serverSize;
895
896    CServerDistributionDescription serverDescription(globalDim, nbServer);
897    serverDescription.computeServerDistribution();
898
899    std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
900    std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
901
902    CEventClient event(getType(),EVENT_ID_DISTRIBUTION_ATTRIBUTE);
903    if (client->isServerLeader())
904    {
905      std::list<CMessage> msgs;
906
907      const std::list<int>& ranks = client->getRanksServerLeader();
908      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
909      {
910        // Use const int to ensure CMessage holds a copy of the value instead of just a reference
911        const int begin = serverIndexBegin[*itRank][orderPositionInGrid];
912        const int ni    = serverDimensionSizes[*itRank][orderPositionInGrid];
913
914        msgs.push_back(CMessage());
915        CMessage& msg = msgs.back();
916        msg << this->getId();
917        msg << ni << begin;
918        msg << isCompressible_;                   
919
920        event.push(*itRank,1,msg);
921      }
922      client->sendEvent(event);
923    }
924    else client->sendEvent(event);
925  }
926  CATCH_DUMP_ATTR
927
928  /*
929    Receive distribution attribute from another client
930    \param [in] event event containing data of these attributes
931  */
932  void CAxis::recvDistributionAttribute(CEventServer& event)
933  TRY
934  {
935    CBufferIn* buffer = event.subEvents.begin()->buffer;
936    string axisId;
937    *buffer >> axisId;
938    get(axisId)->recvDistributionAttribute(*buffer);
939  }
940  CATCH
941
942  /*
943    Receive distribution attribute from another client
944    \param [in] buffer buffer containing data of these attributes
945  */
946  void CAxis::recvDistributionAttribute(CBufferIn& buffer)
947  TRY
948  {
949    int ni_srv, begin_srv;
950    buffer >> ni_srv >> begin_srv;
951    buffer >> isCompressible_;           
952
953    // Set up new local size of axis on the receiving clients
954    n.setValue(ni_srv);
955    begin.setValue(begin_srv);
956  }
957  CATCH_DUMP_ATTR
958
959  /*
960    Send attributes of axis from a group of client to other group of clients/servers
961    on supposing that these attributes are not distributed among the sending group
962    In the future, if new attributes are added, they should also be processed in this function
963  */
964  void CAxis::sendNonDistributedAttributes(CContextClient* client)
965  TRY
966  {
967    CEventClient event(getType(), EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES);
968    size_t nbIndex = index.numElements();
969    size_t nbDataIndex = 0;
970
971    for (int idx = 0; idx < data_index.numElements(); ++idx)
972    {
973      int ind = data_index(idx);
974      if (ind >= 0 && ind < nbIndex) ++nbDataIndex;
975    }
976
977    CArray<int,1> dataIndex(nbDataIndex);
978    nbDataIndex = 0;
979    for (int idx = 0; idx < data_index.numElements(); ++idx)
980    {
981      int ind = data_index(idx);
982      if (ind >= 0 && ind < nbIndex)
983      {
984        dataIndex(nbDataIndex) = ind;
985        ++nbDataIndex;
986      }
987    }
988
989    if (client->isServerLeader())
990    {
991      std::list<CMessage> msgs;
992
993      const std::list<int>& ranks = client->getRanksServerLeader();
994      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
995      {
996        msgs.push_back(CMessage());
997        CMessage& msg = msgs.back();
998        msg << this->getId();
999        msg << index.getValue() << dataIndex << mask.getValue();
1000        msg << hasValue;
1001        if (hasValue) msg << value.getValue();
1002        msg << hasBounds;
1003        if (hasBounds) msg << bounds.getValue();
1004        msg << hasLabel;
1005        if (hasLabel) msg << label.getValue();
1006
1007        event.push(*itRank, 1, msg);
1008      }
1009      client->sendEvent(event);
1010    }
1011    else client->sendEvent(event);
1012  }
1013  CATCH_DUMP_ATTR
1014
1015  /*
1016    Receive the non-distributed attributes from another group of clients
1017    \param [in] event event containing data of these attributes
1018  */
1019  void CAxis::recvNonDistributedAttributes(CEventServer& event)
1020  TRY
1021  {
1022    list<CEventServer::SSubEvent>::iterator it;
1023    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1024    {
1025      CBufferIn* buffer = it->buffer;
1026      string axisId;
1027      *buffer >> axisId;
1028      get(axisId)->recvNonDistributedAttributes(it->rank, *buffer);
1029    }
1030  }
1031  CATCH
1032
1033  /*
1034    Receive the non-distributed attributes from another group of clients
1035    \param [in] rank rank of the sender
1036    \param [in] buffer buffer containing data sent from the sender
1037  */
1038  void CAxis::recvNonDistributedAttributes(int rank, CBufferIn& buffer)
1039  TRY
1040  { 
1041    CArray<int,1> tmp_index, tmp_data_index;
1042    CArray<bool,1> tmp_mask;
1043    CArray<double,1> tmp_val;
1044    CArray<double,2> tmp_bnds;
1045    CArray<string,1> tmp_label;
1046
1047    buffer >> tmp_index;
1048    index.reference(tmp_index);
1049    buffer >> tmp_data_index;
1050    data_index.reference(tmp_data_index);
1051    buffer >> tmp_mask;
1052    mask.reference(tmp_mask);
1053
1054    buffer >> hasValue;
1055    if (hasValue)
1056    {
1057      buffer >> tmp_val;
1058      value.reference(tmp_val);
1059    }
1060
1061    buffer >> hasBounds;
1062    if (hasBounds)
1063    {
1064      buffer >> tmp_bnds;
1065      bounds.reference(tmp_bnds);
1066    }
1067
1068    buffer >> hasLabel;
1069    if (hasLabel)
1070    {
1071      buffer >> tmp_label;
1072      label.reference(tmp_label);
1073    }
1074
1075    // Some value should be reset here
1076    data_begin.setValue(0);
1077    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
1078//    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[idx] = index(idx);
1079    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[index(idx)] = idx;
1080  }
1081  CATCH_DUMP_ATTR
1082
1083  /*
1084    Send axis attributes from a group of clients to another group of clients/servers
1085    supposing that these attributes are distributed among the clients of the sending group
1086    In future, if new attributes are added, they should also be processed in this function
1087  */
1088  void CAxis::sendDistributedAttributes(CContextClient* client)
1089  TRY
1090  {
1091    int ind, idx;
1092    int nbServer = client->serverSize;
1093
1094    CEventClient eventData(getType(), EVENT_ID_DISTRIBUTED_ATTRIBUTES);
1095
1096    list<CMessage> listData;
1097    list<CArray<int,1> > list_indi, list_dataInd;
1098    list<CArray<double,1> > list_val;
1099    list<CArray<double,2> > list_bounds;
1100    list<CArray<string,1> > list_label;
1101
1102    // Cut off the ghost points
1103    int nbIndex = index.numElements();
1104    CArray<int,1> dataIndex(nbIndex);
1105    dataIndex = -1;
1106    for (idx = 0; idx < data_index.numElements(); ++idx)
1107    {
1108      if (0 <= data_index(idx) && data_index(idx) < nbIndex)
1109        dataIndex(data_index(idx)) = 1;
1110    }
1111
1112    std::unordered_map<int, std::vector<size_t> >::const_iterator it, iteMap;
1113    iteMap = indSrv_[nbServer].end();
1114    for (int k = 0; k < connectedServerRank_[nbServer].size(); ++k)
1115    {
1116      int nbData = 0, nbDataCount = 0;
1117      int rank = connectedServerRank_[nbServer][k];
1118      it = indSrv_[nbServer].find(rank);
1119      if (iteMap != it)
1120        nbData = it->second.size();
1121
1122      list_indi.push_back(CArray<int,1>(nbData));
1123      list_dataInd.push_back(CArray<int,1>(nbData));
1124
1125      if (hasValue)
1126        list_val.push_back(CArray<double,1>(nbData));
1127
1128      if (hasBounds)       
1129        list_bounds.push_back(CArray<double,2>(2,nbData));
1130
1131      if (hasLabel)
1132        list_label.push_back(CArray<string,1>(nbData));
1133
1134      CArray<int,1>& indi = list_indi.back();
1135      CArray<int,1>& dataIndi = list_dataInd.back();
1136      dataIndi = -1;
1137
1138      for (int n = 0; n < nbData; ++n)
1139      {
1140        idx = static_cast<int>(it->second[n]);
1141        indi(n) = idx;
1142
1143        ind = globalLocalIndexMap_[idx];
1144        dataIndi(n) = dataIndex(ind);
1145
1146        if (hasValue)
1147        {
1148          CArray<double,1>& val = list_val.back();
1149          val(n) = value(ind);
1150        }
1151
1152        if (hasBounds)
1153        {
1154          CArray<double,2>& boundsVal = list_bounds.back();
1155          boundsVal(0, n) = bounds(0,ind);
1156          boundsVal(1, n) = bounds(1,ind);
1157        }
1158
1159        if (hasLabel)
1160        {
1161          CArray<string,1>& labelVal = list_label.back();
1162          labelVal(n) = label(ind); 
1163        }
1164      }
1165
1166      listData.push_back(CMessage());
1167      listData.back() << this->getId()
1168                      << list_indi.back() << list_dataInd.back();
1169
1170      listData.back() << hasValue;
1171      if (hasValue)
1172        listData.back() << list_val.back();
1173
1174      listData.back() << hasBounds;
1175      if (hasBounds)
1176        listData.back() << list_bounds.back();
1177
1178      listData.back() << hasLabel;
1179      if (hasLabel)
1180        listData.back() << list_label.back();
1181
1182      eventData.push(rank, nbSenders[nbServer][rank], listData.back());
1183    }
1184
1185    client->sendEvent(eventData);
1186  }
1187  CATCH_DUMP_ATTR
1188
1189  /*
1190    Receive the distributed attributes from another group of clients
1191    \param [in] event event containing data of these attributes
1192  */
1193  void CAxis::recvDistributedAttributes(CEventServer& event)
1194  TRY
1195  {
1196    string axisId;
1197    vector<int> ranks;
1198    vector<CBufferIn*> buffers;
1199
1200    list<CEventServer::SSubEvent>::iterator it;
1201    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1202    {
1203      ranks.push_back(it->rank);
1204      CBufferIn* buffer = it->buffer;
1205      *buffer >> axisId;
1206      buffers.push_back(buffer);
1207    }
1208    get(axisId)->recvDistributedAttributes(ranks, buffers);
1209  }
1210  CATCH
1211
1212  /*
1213    Receive the non-distributed attributes from another group of clients
1214    \param [in] ranks rank of the sender
1215    \param [in] buffers buffer containing data sent from the sender
1216  */
1217  void CAxis::recvDistributedAttributes(vector<int>& ranks, vector<CBufferIn*> buffers)
1218  TRY
1219  {
1220    int nbReceived = ranks.size(), idx, ind, gloInd, locInd;
1221    vector<CArray<int,1> > vec_indi(nbReceived), vec_dataInd(nbReceived);
1222    vector<CArray<double,1> > vec_val(nbReceived);
1223    vector<CArray<double,2> > vec_bounds(nbReceived);
1224    vector<CArray<string,1> > vec_label(nbReceived);
1225   
1226    for (idx = 0; idx < nbReceived; ++idx)
1227    {     
1228      CBufferIn& buffer = *buffers[idx];
1229      buffer >> vec_indi[idx];
1230      buffer >> vec_dataInd[idx];     
1231
1232      buffer >> hasValue;
1233      if (hasValue)
1234        buffer >> vec_val[idx];
1235
1236      buffer >> hasBounds;
1237      if (hasBounds)
1238        buffer >> vec_bounds[idx];
1239
1240      buffer >> hasLabel;
1241      if (hasLabel)
1242        buffer >> vec_label[idx]; 
1243    }
1244
1245    // Estimate size of index array
1246    int nbIndexGlob = 0;
1247    for (idx = 0; idx < nbReceived; ++idx)
1248    {
1249      nbIndexGlob += vec_indi[idx].numElements();
1250    }
1251
1252    // Recompute global index
1253    // Take account of the overlapped index
1254    index.resize(nbIndexGlob);
1255    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
1256    nbIndexGlob = 0;
1257    int nbIndLoc = 0;
1258    for (idx = 0; idx < nbReceived; ++idx)
1259    {
1260      CArray<int,1>& tmp = vec_indi[idx];
1261      for (ind = 0; ind < tmp.numElements(); ++ind)
1262      {
1263         gloInd = tmp(ind);
1264         nbIndLoc = (gloInd % n_glo)-begin;
1265         if (0 == globalLocalIndexMap_.count(gloInd))
1266         {
1267           index(nbIndexGlob) = gloInd % n_glo;
1268           globalLocalIndexMap_[gloInd] = nbIndexGlob;
1269           ++nbIndexGlob;
1270         } 
1271      } 
1272    }
1273
1274    // Resize index to its real size
1275    if (nbIndexGlob==0) index.resize(nbIndexGlob) ;
1276    else index.resizeAndPreserve(nbIndexGlob);
1277
1278    int nbData = nbIndexGlob;
1279    CArray<int,1> nonCompressedData(nbData);
1280    nonCompressedData = -1;   
1281    // Mask is incorporated into data_index and is not sent/received anymore
1282    mask.resize(0);
1283    if (hasValue)
1284      value.resize(nbData);
1285    if (hasBounds)
1286      bounds.resize(2,nbData);
1287    if (hasLabel)
1288      label.resize(nbData);
1289
1290    nbData = 0;
1291    for (idx = 0; idx < nbReceived; ++idx)
1292    {
1293      CArray<int,1>& indi = vec_indi[idx];
1294      CArray<int,1>& dataIndi = vec_dataInd[idx];
1295      int nb = indi.numElements();
1296      for (int n = 0; n < nb; ++n)
1297      { 
1298        locInd = globalLocalIndexMap_[size_t(indi(n))];
1299
1300        nonCompressedData(locInd) = (-1 == nonCompressedData(locInd)) ? dataIndi(n) : nonCompressedData(locInd);
1301
1302        if (hasValue)
1303          value(locInd) = vec_val[idx](n);
1304
1305        if (hasBounds)
1306        {
1307          bounds(0,locInd) = vec_bounds[idx](0,n);
1308          bounds(1,locInd) = vec_bounds[idx](1,n);
1309        }
1310
1311        if (hasLabel)
1312          label(locInd) = vec_label[idx](n);
1313      }
1314    }
1315   
1316    int nbCompressedData = 0;
1317    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1318    {
1319      if (0 <= nonCompressedData(idx))
1320        ++nbCompressedData;
1321    }
1322
1323    data_index.resize(nbCompressedData);
1324    nbCompressedData = 0;
1325    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1326    {
1327      if (0 <= nonCompressedData(idx))
1328      {
1329        data_index(nbCompressedData) = idx % n;
1330        ++nbCompressedData;
1331      }
1332    }
1333
1334    data_begin.setValue(0);
1335    data_n.setValue(data_index.numElements());
1336  }
1337  CATCH_DUMP_ATTR
1338
1339  /*!
1340    Compare two axis objects.
1341    They are equal if only if they have identical attributes as well as their values.
1342    Moreover, they must have the same transformations.
1343  \param [in] axis Compared axis
1344  \return result of the comparison
1345  */
1346  bool CAxis::isEqual(CAxis* obj)
1347  TRY
1348  {
1349    vector<StdString> excludedAttr;
1350    excludedAttr.push_back("axis_ref");
1351
1352    bool objEqual = SuperClass::isEqual(obj, excludedAttr);   
1353    if (!objEqual) return objEqual;
1354
1355    TransMapTypes thisTrans = this->getAllTransformations();
1356    TransMapTypes objTrans  = obj->getAllTransformations();
1357
1358    TransMapTypes::const_iterator it, itb, ite;
1359    std::vector<ETranformationType> thisTransType, objTransType;
1360    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
1361      thisTransType.push_back(it->first);
1362    for (it = objTrans.begin(); it != objTrans.end(); ++it)
1363      objTransType.push_back(it->first);
1364
1365    if (thisTransType.size() != objTransType.size()) return false;
1366    for (int idx = 0; idx < thisTransType.size(); ++idx)
1367      objEqual &= (thisTransType[idx] == objTransType[idx]);
1368
1369    return objEqual;
1370  }
1371  CATCH_DUMP_ATTR
1372
1373  /*
1374    Add transformation into axis. This function only servers for Fortran interface
1375    \param [in] transType transformation type
1376    \param [in] id identifier of the transformation object
1377  */
1378  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
1379  TRY
1380  {
1381    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
1382    return transformationMap_.back().second;
1383  }
1384  CATCH_DUMP_ATTR
1385
1386  /*
1387    Check whether an axis has (spatial) transformation
1388  */
1389  bool CAxis::hasTransformation()
1390  TRY
1391  {
1392    return (!transformationMap_.empty());
1393  }
1394  CATCH_DUMP_ATTR
1395
1396  /*
1397    Set transformation
1398    \param [in] axisTrans transformation to set
1399  */
1400  void CAxis::setTransformations(const TransMapTypes& axisTrans)
1401  TRY
1402  {
1403    transformationMap_ = axisTrans;
1404  }
1405  CATCH_DUMP_ATTR
1406
1407  /*
1408    Return all transformation held by the axis
1409    \return transformation the axis has
1410  */
1411  CAxis::TransMapTypes CAxis::getAllTransformations(void)
1412  TRY
1413  {
1414    return transformationMap_;
1415  }
1416  CATCH_DUMP_ATTR
1417
1418  /*
1419    Duplicate transformation of another axis
1420    \param [in] src axis whose transformations are copied
1421  */
1422  void CAxis::duplicateTransformation(CAxis* src)
1423  TRY
1424  {
1425    if (src->hasTransformation())
1426    {
1427      this->setTransformations(src->getAllTransformations());
1428    }
1429  }
1430  CATCH_DUMP_ATTR
1431
1432/*!
1433  \brief Check if a axis is completed
1434  Before make any axis processing, we must be sure that all axis informations have
1435  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
1436  other context (coupling). So all direct reference of the axis (axis_ref) must be also completed
1437  \return true if axis and axis reference are completed
1438  */
1439  bool CAxis::checkIfCompleted(void)
1440  {
1441    if (hasDirectAxisReference()) if (!getDirectAxisReference()->checkIfCompleted()) return false;
1442    return isCompleted_ ;
1443  }
1444
1445  /*!
1446  \brief Set a axis as completed
1447   When all information about a axis have been received, the axis is tagged as completed and is
1448   suitable for processing
1449  */
1450  void CAxis::setCompleted(void)
1451  {
1452    if (hasDirectAxisReference()) getDirectAxisReference()->setCompleted() ;
1453    isCompleted_=true ;
1454  }
1455
1456  /*!
1457  \brief Set a axis as uncompleted
1458   When informations about a axis are expected from a grid reading from file or coupling, the axis is
1459   tagged as uncompleted and is not suitable for processing
1460  */
1461  void CAxis::setUncompleted(void)
1462  {
1463    if (hasDirectAxisReference()) getDirectAxisReference()->setUncompleted() ;
1464    isCompleted_=false ;
1465  }
1466
1467
1468
1469  /*!
1470   * Go through the hierarchy to find the axis from which the transformations must be inherited
1471   */
1472  void CAxis::solveInheritanceTransformation()
1473  TRY
1474  {
1475    if (hasTransformation() || !hasDirectAxisReference())
1476      return;
1477
1478    CAxis* axis = this;
1479    std::vector<CAxis*> refAxis;
1480    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
1481    {
1482      refAxis.push_back(axis);
1483      axis = axis->getDirectAxisReference();
1484    }
1485
1486    if (axis->hasTransformation())
1487      for (size_t i = 0; i < refAxis.size(); ++i)
1488        refAxis[i]->setTransformations(axis->getAllTransformations());
1489  }
1490  CATCH_DUMP_ATTR
1491
1492  void CAxis::setContextClient(CContextClient* contextClient)
1493  TRY
1494  {
1495    if (clientsSet.find(contextClient)==clientsSet.end())
1496    {
1497      clients.push_back(contextClient) ;
1498      clientsSet.insert(contextClient);
1499    }
1500  }
1501  CATCH_DUMP_ATTR
1502
1503  void CAxis::parse(xml::CXMLNode & node)
1504  TRY
1505  {
1506    SuperClass::parse(node);
1507
1508    if (node.goToChildElement())
1509    {
1510      StdString nodeElementName;
1511      do
1512      {
1513        StdString nodeId("");
1514        if (node.getAttributes().end() != node.getAttributes().find("id"))
1515        { nodeId = node.getAttributes()["id"]; }
1516
1517        nodeElementName = node.getElementName();
1518        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
1519        it = transformationMapList_.find(nodeElementName);
1520        if (ite != it)
1521        {
1522          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second,
1523                                                                                                               nodeId,
1524                                                                                                               &node)));
1525        }
1526        else
1527        {
1528          ERROR("void CAxis::parse(xml::CXMLNode & node)",
1529                << "The transformation " << nodeElementName << " has not been supported yet.");
1530        }
1531      } while (node.goToNextElement()) ;
1532      node.goToParentElement();
1533    }
1534  }
1535  CATCH_DUMP_ATTR
1536
1537  DEFINE_REF_FUNC(Axis,axis)
1538
1539   ///---------------------------------------------------------------
1540
1541} // namespace xios
Note: See TracBrowser for help on using the repository browser.