source: XIOS/trunk/src/node/axis.cpp @ 1638

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

dev on ADA

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