source: XIOS/dev/dev_trunk_omp/src/node/axis.cpp @ 1678

Last change on this file since 1678 was 1678, checked in by yushan, 5 years ago

MARK: Dynamic workflow graph developement. Branch up to date with trunk @1676. Generic testcase not yet tested

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