source: XIOS/dev/dev_olga/src/node/axis.cpp @ 1612

Last change on this file since 1612 was 1612, checked in by oabramkina, 5 years ago

Dev: adding exception handling.

To activate it, compilation flag -DXIOS_EXCEPTION should be added.

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