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

Last change on this file since 1871 was 1871, 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.7 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    data_n.setValue(data_index.numElements());
1078    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
1079//    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[idx] = index(idx);
1080    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[index(idx)] = idx;
1081  }
1082  CATCH_DUMP_ATTR
1083
1084  /*
1085    Send axis attributes from a group of clients to another group of clients/servers
1086    supposing that these attributes are distributed among the clients of the sending group
1087    In future, if new attributes are added, they should also be processed in this function
1088  */
1089  void CAxis::sendDistributedAttributes(CContextClient* client)
1090  TRY
1091  {
1092    int ind, idx;
1093    int nbServer = client->serverSize;
1094
1095    CEventClient eventData(getType(), EVENT_ID_DISTRIBUTED_ATTRIBUTES);
1096
1097    list<CMessage> listData;
1098    list<CArray<int,1> > list_indi, list_dataInd;
1099    list<CArray<double,1> > list_val;
1100    list<CArray<double,2> > list_bounds;
1101    list<CArray<string,1> > list_label;
1102
1103    // Cut off the ghost points
1104    int nbIndex = index.numElements();
1105    CArray<int,1> dataIndex(nbIndex);
1106    dataIndex = -1;
1107    for (idx = 0; idx < data_index.numElements(); ++idx)
1108    {
1109      if (0 <= data_index(idx) && data_index(idx) < nbIndex)
1110        dataIndex(data_index(idx)) = 1;
1111    }
1112
1113    std::unordered_map<int, std::vector<size_t> >::const_iterator it, iteMap;
1114    iteMap = indSrv_[nbServer].end();
1115    for (int k = 0; k < connectedServerRank_[nbServer].size(); ++k)
1116    {
1117      int nbData = 0, nbDataCount = 0;
1118      int rank = connectedServerRank_[nbServer][k];
1119      it = indSrv_[nbServer].find(rank);
1120      if (iteMap != it)
1121        nbData = it->second.size();
1122
1123      list_indi.push_back(CArray<int,1>(nbData));
1124      list_dataInd.push_back(CArray<int,1>(nbData));
1125
1126      if (hasValue)
1127        list_val.push_back(CArray<double,1>(nbData));
1128
1129      if (hasBounds)       
1130        list_bounds.push_back(CArray<double,2>(2,nbData));
1131
1132      if (hasLabel)
1133        list_label.push_back(CArray<string,1>(nbData));
1134
1135      CArray<int,1>& indi = list_indi.back();
1136      CArray<int,1>& dataIndi = list_dataInd.back();
1137      dataIndi = -1;
1138
1139      for (int n = 0; n < nbData; ++n)
1140      {
1141        idx = static_cast<int>(it->second[n]);
1142        indi(n) = idx;
1143
1144        ind = globalLocalIndexMap_[idx];
1145        dataIndi(n) = dataIndex(ind);
1146
1147        if (hasValue)
1148        {
1149          CArray<double,1>& val = list_val.back();
1150          val(n) = value(ind);
1151        }
1152
1153        if (hasBounds)
1154        {
1155          CArray<double,2>& boundsVal = list_bounds.back();
1156          boundsVal(0, n) = bounds(0,ind);
1157          boundsVal(1, n) = bounds(1,ind);
1158        }
1159
1160        if (hasLabel)
1161        {
1162          CArray<string,1>& labelVal = list_label.back();
1163          labelVal(n) = label(ind); 
1164        }
1165      }
1166
1167      listData.push_back(CMessage());
1168      listData.back() << this->getId()
1169                      << list_indi.back() << list_dataInd.back();
1170
1171      listData.back() << hasValue;
1172      if (hasValue)
1173        listData.back() << list_val.back();
1174
1175      listData.back() << hasBounds;
1176      if (hasBounds)
1177        listData.back() << list_bounds.back();
1178
1179      listData.back() << hasLabel;
1180      if (hasLabel)
1181        listData.back() << list_label.back();
1182
1183      eventData.push(rank, nbSenders[nbServer][rank], listData.back());
1184    }
1185
1186    client->sendEvent(eventData);
1187  }
1188  CATCH_DUMP_ATTR
1189
1190  /*
1191    Receive the distributed attributes from another group of clients
1192    \param [in] event event containing data of these attributes
1193  */
1194  void CAxis::recvDistributedAttributes(CEventServer& event)
1195  TRY
1196  {
1197    string axisId;
1198    vector<int> ranks;
1199    vector<CBufferIn*> buffers;
1200
1201    list<CEventServer::SSubEvent>::iterator it;
1202    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1203    {
1204      ranks.push_back(it->rank);
1205      CBufferIn* buffer = it->buffer;
1206      *buffer >> axisId;
1207      buffers.push_back(buffer);
1208    }
1209    get(axisId)->recvDistributedAttributes(ranks, buffers);
1210  }
1211  CATCH
1212
1213  /*
1214    Receive the non-distributed attributes from another group of clients
1215    \param [in] ranks rank of the sender
1216    \param [in] buffers buffer containing data sent from the sender
1217  */
1218  void CAxis::recvDistributedAttributes(vector<int>& ranks, vector<CBufferIn*> buffers)
1219  TRY
1220  {
1221    int nbReceived = ranks.size(), idx, ind, gloInd, locInd;
1222    vector<CArray<int,1> > vec_indi(nbReceived), vec_dataInd(nbReceived);
1223    vector<CArray<double,1> > vec_val(nbReceived);
1224    vector<CArray<double,2> > vec_bounds(nbReceived);
1225    vector<CArray<string,1> > vec_label(nbReceived);
1226   
1227    for (idx = 0; idx < nbReceived; ++idx)
1228    {     
1229      CBufferIn& buffer = *buffers[idx];
1230      buffer >> vec_indi[idx];
1231      buffer >> vec_dataInd[idx];     
1232
1233      buffer >> hasValue;
1234      if (hasValue)
1235        buffer >> vec_val[idx];
1236
1237      buffer >> hasBounds;
1238      if (hasBounds)
1239        buffer >> vec_bounds[idx];
1240
1241      buffer >> hasLabel;
1242      if (hasLabel)
1243        buffer >> vec_label[idx]; 
1244    }
1245
1246    // Estimate size of index array
1247    int nbIndexGlob = 0;
1248    for (idx = 0; idx < nbReceived; ++idx)
1249    {
1250      nbIndexGlob += vec_indi[idx].numElements();
1251    }
1252
1253    // Recompute global index
1254    // Take account of the overlapped index
1255    index.resize(nbIndexGlob);
1256    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
1257    nbIndexGlob = 0;
1258    int nbIndLoc = 0;
1259    for (idx = 0; idx < nbReceived; ++idx)
1260    {
1261      CArray<int,1>& tmp = vec_indi[idx];
1262      for (ind = 0; ind < tmp.numElements(); ++ind)
1263      {
1264         gloInd = tmp(ind);
1265         nbIndLoc = (gloInd % n_glo)-begin;
1266         if (0 == globalLocalIndexMap_.count(gloInd))
1267         {
1268           index(nbIndexGlob) = gloInd % n_glo;
1269           globalLocalIndexMap_[gloInd] = nbIndexGlob;
1270           ++nbIndexGlob;
1271         } 
1272      } 
1273    }
1274
1275    // Resize index to its real size
1276    if (nbIndexGlob==0) index.resize(nbIndexGlob) ;
1277    else index.resizeAndPreserve(nbIndexGlob);
1278
1279    int nbData = nbIndexGlob;
1280    CArray<int,1> nonCompressedData(nbData);
1281    nonCompressedData = -1;   
1282    // Mask is incorporated into data_index and is not sent/received anymore
1283    mask.resize(0);
1284    if (hasValue)
1285      value.resize(nbData);
1286    if (hasBounds)
1287      bounds.resize(2,nbData);
1288    if (hasLabel)
1289      label.resize(nbData);
1290
1291    nbData = 0;
1292    for (idx = 0; idx < nbReceived; ++idx)
1293    {
1294      CArray<int,1>& indi = vec_indi[idx];
1295      CArray<int,1>& dataIndi = vec_dataInd[idx];
1296      int nb = indi.numElements();
1297      for (int n = 0; n < nb; ++n)
1298      { 
1299        locInd = globalLocalIndexMap_[size_t(indi(n))];
1300
1301        nonCompressedData(locInd) = (-1 == nonCompressedData(locInd)) ? dataIndi(n) : nonCompressedData(locInd);
1302
1303        if (hasValue)
1304          value(locInd) = vec_val[idx](n);
1305
1306        if (hasBounds)
1307        {
1308          bounds(0,locInd) = vec_bounds[idx](0,n);
1309          bounds(1,locInd) = vec_bounds[idx](1,n);
1310        }
1311
1312        if (hasLabel)
1313          label(locInd) = vec_label[idx](n);
1314      }
1315    }
1316   
1317    int nbCompressedData = 0;
1318    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1319    {
1320      if (0 <= nonCompressedData(idx))
1321        ++nbCompressedData;
1322    }
1323
1324    data_index.resize(nbCompressedData);
1325    nbCompressedData = 0;
1326    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1327    {
1328      if (0 <= nonCompressedData(idx))
1329      {
1330        data_index(nbCompressedData) = idx % n;
1331        ++nbCompressedData;
1332      }
1333    }
1334
1335    data_begin.setValue(0);
1336    data_n.setValue(data_index.numElements());
1337  }
1338  CATCH_DUMP_ATTR
1339
1340  /*!
1341    Compare two axis objects.
1342    They are equal if only if they have identical attributes as well as their values.
1343    Moreover, they must have the same transformations.
1344  \param [in] axis Compared axis
1345  \return result of the comparison
1346  */
1347  bool CAxis::isEqual(CAxis* obj)
1348  TRY
1349  {
1350    vector<StdString> excludedAttr;
1351    excludedAttr.push_back("axis_ref");
1352
1353    bool objEqual = SuperClass::isEqual(obj, excludedAttr);   
1354    if (!objEqual) return objEqual;
1355
1356    TransMapTypes thisTrans = this->getAllTransformations();
1357    TransMapTypes objTrans  = obj->getAllTransformations();
1358
1359    TransMapTypes::const_iterator it, itb, ite;
1360    std::vector<ETranformationType> thisTransType, objTransType;
1361    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
1362      thisTransType.push_back(it->first);
1363    for (it = objTrans.begin(); it != objTrans.end(); ++it)
1364      objTransType.push_back(it->first);
1365
1366    if (thisTransType.size() != objTransType.size()) return false;
1367    for (int idx = 0; idx < thisTransType.size(); ++idx)
1368      objEqual &= (thisTransType[idx] == objTransType[idx]);
1369
1370    return objEqual;
1371  }
1372  CATCH_DUMP_ATTR
1373
1374  /*
1375    Add transformation into axis. This function only servers for Fortran interface
1376    \param [in] transType transformation type
1377    \param [in] id identifier of the transformation object
1378  */
1379  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
1380  TRY
1381  {
1382    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
1383    return transformationMap_.back().second;
1384  }
1385  CATCH_DUMP_ATTR
1386
1387  /*
1388    Check whether an axis has (spatial) transformation
1389  */
1390  bool CAxis::hasTransformation()
1391  TRY
1392  {
1393    return (!transformationMap_.empty());
1394  }
1395  CATCH_DUMP_ATTR
1396
1397  /*
1398    Set transformation
1399    \param [in] axisTrans transformation to set
1400  */
1401  void CAxis::setTransformations(const TransMapTypes& axisTrans)
1402  TRY
1403  {
1404    transformationMap_ = axisTrans;
1405  }
1406  CATCH_DUMP_ATTR
1407
1408  /*
1409    Return all transformation held by the axis
1410    \return transformation the axis has
1411  */
1412  CAxis::TransMapTypes CAxis::getAllTransformations(void)
1413  TRY
1414  {
1415    return transformationMap_;
1416  }
1417  CATCH_DUMP_ATTR
1418
1419  /*
1420    Duplicate transformation of another axis
1421    \param [in] src axis whose transformations are copied
1422  */
1423  void CAxis::duplicateTransformation(CAxis* src)
1424  TRY
1425  {
1426    if (src->hasTransformation())
1427    {
1428      this->setTransformations(src->getAllTransformations());
1429    }
1430  }
1431  CATCH_DUMP_ATTR
1432
1433/*!
1434  \brief Check if a axis is completed
1435  Before make any axis processing, we must be sure that all axis informations have
1436  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
1437  other context (coupling). So all direct reference of the axis (axis_ref) must be also completed
1438  \return true if axis and axis reference are completed
1439  */
1440  bool CAxis::checkIfCompleted(void)
1441  {
1442    if (hasDirectAxisReference()) if (!getDirectAxisReference()->checkIfCompleted()) return false;
1443    return isCompleted_ ;
1444  }
1445
1446  /*!
1447  \brief Set a axis as completed
1448   When all information about a axis have been received, the axis is tagged as completed and is
1449   suitable for processing
1450  */
1451  void CAxis::setCompleted(void)
1452  {
1453    if (hasDirectAxisReference()) getDirectAxisReference()->setCompleted() ;
1454    isCompleted_=true ;
1455  }
1456
1457  /*!
1458  \brief Set a axis as uncompleted
1459   When informations about a axis are expected from a grid reading from file or coupling, the axis is
1460   tagged as uncompleted and is not suitable for processing
1461  */
1462  void CAxis::setUncompleted(void)
1463  {
1464    if (hasDirectAxisReference()) getDirectAxisReference()->setUncompleted() ;
1465    isCompleted_=false ;
1466  }
1467
1468
1469
1470  /*!
1471   * Go through the hierarchy to find the axis from which the transformations must be inherited
1472   */
1473  void CAxis::solveInheritanceTransformation()
1474  TRY
1475  {
1476    if (hasTransformation() || !hasDirectAxisReference())
1477      return;
1478
1479    CAxis* axis = this;
1480    std::vector<CAxis*> refAxis;
1481    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
1482    {
1483      refAxis.push_back(axis);
1484      axis = axis->getDirectAxisReference();
1485    }
1486
1487    if (axis->hasTransformation())
1488      for (size_t i = 0; i < refAxis.size(); ++i)
1489        refAxis[i]->setTransformations(axis->getAllTransformations());
1490  }
1491  CATCH_DUMP_ATTR
1492
1493  void CAxis::setContextClient(CContextClient* contextClient)
1494  TRY
1495  {
1496    if (clientsSet.find(contextClient)==clientsSet.end())
1497    {
1498      clients.push_back(contextClient) ;
1499      clientsSet.insert(contextClient);
1500    }
1501  }
1502  CATCH_DUMP_ATTR
1503
1504  void CAxis::parse(xml::CXMLNode & node)
1505  TRY
1506  {
1507    SuperClass::parse(node);
1508
1509    if (node.goToChildElement())
1510    {
1511      StdString nodeElementName;
1512      do
1513      {
1514        StdString nodeId("");
1515        if (node.getAttributes().end() != node.getAttributes().find("id"))
1516        { nodeId = node.getAttributes()["id"]; }
1517
1518        nodeElementName = node.getElementName();
1519        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
1520        it = transformationMapList_.find(nodeElementName);
1521        if (ite != it)
1522        {
1523          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second,
1524                                                                                                               nodeId,
1525                                                                                                               &node)));
1526        }
1527        else
1528        {
1529          ERROR("void CAxis::parse(xml::CXMLNode & node)",
1530                << "The transformation " << nodeElementName << " has not been supported yet.");
1531        }
1532      } while (node.goToNextElement()) ;
1533      node.goToParentElement();
1534    }
1535  }
1536  CATCH_DUMP_ATTR
1537
1538  DEFINE_REF_FUNC(Axis,axis)
1539
1540   ///---------------------------------------------------------------
1541
1542} // namespace xios
Note: See TracBrowser for help on using the repository browser.