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

Last change on this file since 1672 was 1672, checked in by ymipsl, 5 years ago

Fix problem of distribution.
The isDistributed() method for domain and is local to all process, so some deadlock can occur.
YM

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 49.1 KB
RevLine 
[219]1#include "axis.hpp"
2
[352]3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6#include "message.hpp"
7#include "type.hpp"
[567]8#include "context.hpp"
9#include "context_client.hpp"
[676]10#include "context_server.hpp"
[591]11#include "xios_spl.hpp"
[633]12#include "server_distribution_description.hpp"
13#include "client_server_mapping_distributed.hpp"
[676]14#include "distribution_client.hpp"
[219]15
[335]16namespace xios {
[540]17
[1421]18   /// ////////////////////// Definitions ////////////////////// ///
[219]19
20   CAxis::CAxis(void)
21      : CObjectTemplate<CAxis>()
[771]22      , CAxisAttributes(), isChecked(false), relFiles(), areClientAttributesChecked_(false)
[927]23      , isClientAfterTransformationChecked(false)
[1235]24      , hasBounds(false), isCompressible_(false)
[1249]25      , numberWrittenIndexes_(), totalNumberWrittenIndexes_(), offsetWrittenIndexes_()
[1202]26      , transformationMap_(), hasValue(false), hasLabel(false)
[1129]27      , computedWrittenIndex_(false)
[1345]28          , clients()
[621]29   {
30   }
[219]31
32   CAxis::CAxis(const StdString & id)
33      : CObjectTemplate<CAxis>(id)
[771]34      , CAxisAttributes(), isChecked(false), relFiles(), areClientAttributesChecked_(false)
[927]35      , isClientAfterTransformationChecked(false)
[1235]36      , hasBounds(false), isCompressible_(false)
[1249]37      , numberWrittenIndexes_(), totalNumberWrittenIndexes_(), offsetWrittenIndexes_()
[1202]38      , transformationMap_(), hasValue(false), hasLabel(false)
[1129]39      , computedWrittenIndex_(false)
[1345]40          , clients()
[621]41   {
42   }
[219]43
44   CAxis::~CAxis(void)
45   { /* Ne rien faire de plus */ }
46
[836]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)
[1622]50   TRY
[836]51   {
52     m["zoom_axis"] = TRANS_ZOOM_AXIS;
53     m["interpolate_axis"] = TRANS_INTERPOLATE_AXIS;
[1558]54     m["extract_axis"] = TRANS_EXTRACT_AXIS;
[836]55     m["inverse_axis"] = TRANS_INVERSE_AXIS;
[895]56     m["reduce_domain"] = TRANS_REDUCE_DOMAIN_TO_AXIS;
[1301]57     m["reduce_axis"] = TRANS_REDUCE_AXIS_TO_AXIS;
[895]58     m["extract_domain"] = TRANS_EXTRACT_DOMAIN_TO_AXIS;
[1275]59     m["temporal_splitting"] = TRANS_TEMPORAL_SPLITTING;
[1314]60     m["duplicate_scalar"] = TRANS_DUPLICATE_SCALAR_TO_AXIS;
61
[836]62   }
[1622]63   CATCH
[836]64
[219]65   ///---------------------------------------------------------------
[1158]66
67   const std::set<StdString> & CAxis::getRelFiles(void) const
[1622]68   TRY
[1158]69   {
70      return (this->relFiles);
71   }
[1622]72   CATCH
[1158]73
[219]74   bool CAxis::IsWritten(const StdString & filename) const
[1622]75   TRY
[219]76   {
77      return (this->relFiles.find(filename) != this->relFiles.end());
78   }
[1622]79   CATCH
[219]80
[676]81   bool CAxis::isWrittenCompressed(const StdString& filename) const
[1622]82   TRY
[676]83   {
84      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
85   }
[1622]86   CATCH
[676]87
[594]88   bool CAxis::isDistributed(void) const
[1622]89   TRY
[594]90   {
[1158]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));
[1622]93      // A condition to make sure that if there is only one client, axis
[1158]94      // should be considered to be distributed. This should be a temporary solution     
95      distributed |= (1 == CContext::getCurrent()->client->clientSize);
96      return distributed;
[594]97   }
[1622]98   CATCH
[594]99
[676]100   /*!
101    * Test whether the data defined on the axis can be outputted in a compressed way.
[742]102    *
[676]103    * \return true if and only if a mask was defined for this axis
104    */
105   bool CAxis::isCompressible(void) const
[1622]106   TRY
[676]107   {
108      return isCompressible_;
109   }
[1622]110   CATCH
[676]111
[219]112   void CAxis::addRelFile(const StdString & filename)
[1622]113   TRY
[219]114   {
115      this->relFiles.insert(filename);
116   }
[1622]117   CATCH_DUMP_ATTR
[219]118
[676]119   void CAxis::addRelFileCompressed(const StdString& filename)
[1622]120   TRY
[676]121   {
122      this->relFilesCompressed.insert(filename);
123   }
[1622]124   CATCH_DUMP_ATTR
[676]125
[219]126   //----------------------------------------------------------------
127
[676]128   /*!
129     Returns the number of indexes written by each server.
130     \return the number of indexes written by each server
131   */
[1639]132   int CAxis::getNumberWrittenIndexes(MPI_Comm writtenCom)
[1622]133   TRY
[676]134   {
[1249]135     int writtenSize;
[1639]136     MPI_Comm_size(writtenCom, &writtenSize);
[1249]137     return numberWrittenIndexes_[writtenSize];
[676]138   }
[1622]139   CATCH_DUMP_ATTR
[676]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   */
[1639]145   int CAxis::getTotalNumberWrittenIndexes(MPI_Comm writtenCom)
[1622]146   TRY
[676]147   {
[1249]148     int writtenSize;
[1639]149     MPI_Comm_size(writtenCom, &writtenSize);
[1249]150     return totalNumberWrittenIndexes_[writtenSize];
[676]151   }
[1622]152   CATCH_DUMP_ATTR
[676]153
154   /*!
155     Returns the offset of indexes written by each server.
156     \return the offset of indexes written by each server
157   */
[1639]158   int CAxis::getOffsetWrittenIndexes(MPI_Comm writtenCom)
[1622]159   TRY
[676]160   {
[1249]161     int writtenSize;
[1639]162     MPI_Comm_size(writtenCom, &writtenSize);
[1249]163     return offsetWrittenIndexes_[writtenSize];
[676]164   }
[1622]165   CATCH_DUMP_ATTR
[676]166
[1639]167   CArray<int, 1>& CAxis::getCompressedIndexToWriteOnServer(MPI_Comm writtenCom)
[1622]168   TRY
[1249]169   {
170     int writtenSize;
[1639]171     MPI_Comm_size(writtenCom, &writtenSize);
[1249]172     return compressedIndexToWriteOnServer[writtenSize];
173   }
[1622]174   CATCH_DUMP_ATTR
175
[676]176   //----------------------------------------------------------------
177
[731]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    */
[1371]183   std::map<int, StdSize> CAxis::getAttributesBufferSize(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
184                                                         CServerDistributionDescription::ServerDistributionType distType)
[1622]185   TRY
[731]186   {
187
[1330]188     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client);
[731]189
[1371]190//     bool isNonDistributed = (n_glo == n);
191     bool isDistributed = (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
192                                 || (index.numElements() != n_glo);
[731]193
194     if (client->isServerLeader())
195     {
196       // size estimation for sendServerAttribut
197       size_t size = 6 * sizeof(size_t);
198       // size estimation for sendNonDistributedValue
[1371]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       }
[731]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       }
[1371]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
[731]226     }
227
[1371]228     if (isDistributed)
[731]229     {
230       // size estimation for sendDistributedValue
[1542]231       std::unordered_map<int, vector<size_t> >::const_iterator it, ite = indSrv_[client->serverSize].end();
[1337]232       for (it = indSrv_[client->serverSize].begin(); it != ite; ++it)
[731]233       {
[1371]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());
[1235]239         if (hasBounds)
[1371]240           size += CArray<double,2>::size(2 * it->second.size());
[1158]241         if (hasLabel)
[1371]242           size += CArray<StdString,1>::size(it->second.size());
[731]243
[1371]244         size += CEventClient::headerSize + getId().size() + sizeof(size_t);
[731]245         if (size > attributesSizes[it->first])
246           attributesSizes[it->first] = size;
247       }
248     }
249     return attributesSizes;
250   }
[1622]251   CATCH_DUMP_ATTR
[731]252
253   //----------------------------------------------------------------
254
[219]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
[622]261   CAxis* CAxis::createAxis()
[1622]262   TRY
[622]263   {
264     CAxis* axis = CAxisGroup::get("axis_definition")->createChild();
265     return axis;
266   }
[1622]267   CATCH
[622]268
[1144]269   /*!
270     Check common attributes of an axis.
271     This check should be done in the very beginning of work flow
272   */
[219]273   void CAxis::checkAttributes(void)
[1622]274   TRY
[219]275   {
[1637]276     CContext* context=CContext::getCurrent();
277
278     if (this->n_glo.isEmpty())
[679]279        ERROR("CAxis::checkAttributes(void)",
280              << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
281              << "The axis is wrongly defined, attribute 'n_glo' must be specified");
[666]282      StdSize size = this->n_glo.getValue();
[540]283
[970]284      if (!this->index.isEmpty())
[551]285      {
[970]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);         
[551]291      }
[970]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);
[551]302
[970]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        }
[551]316      }
[624]317
[816]318      if (!this->value.isEmpty())
319      {
[1637]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        }
[816]330        this->hasValue = true;
331      }
[219]332
[1158]333      this->checkBounds();
[1421]334
335      if (context->hasClient)
336      {
[1637]337        this->checkMask();
[1421]338        this->checkData();
339        this->checkLabel();
340      }
[219]341   }
[1622]342   CATCH_DUMP_ATTR
[219]343
[1144]344   /*!
[1637]345      Check the validity of data, fill in values if any, and apply mask.
[1144]346   */
[551]347   void CAxis::checkData()
[1622]348   TRY
[551]349   {
350      if (data_begin.isEmpty()) data_begin.setValue(0);
[679]351
352      if (data_n.isEmpty())
[551]353      {
[679]354        data_n.setValue(n);
355      }
356      else if (data_n.getValue() < 0)
357      {
[551]358        ERROR("CAxis::checkData(void)",
[679]359              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
360              << "The data size should be strictly positive ('data_n' = " << data_n.getValue() << ").");
[551]361      }
362
363      if (data_index.isEmpty())
364      {
[679]365        data_index.resize(data_n);
[1637]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        }
[551]378      }
[1637]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
[551]394   }
[1622]395   CATCH_DUMP_ATTR
[551]396
[1215]397    size_t CAxis::getGlobalWrittenSize(void)
398    {
[1559]399      return n_glo ;
[1215]400    }
401
[1144]402   /*!
403     Check validity of mask info and fill in values if any.
404   */
[551]405   void CAxis::checkMask()
[1622]406   TRY
[551]407   {
408      if (!mask.isEmpty())
409      {
[1637]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        }
[551]418      }
[1637]419      else
420      {
421        mask.resize(n);
422        mask = true;
[551]423      }
424   }
[1622]425   CATCH_DUMP_ATTR
[551]426
[1144]427   /*!
428     Check validity of bounds info and fill in values if any.
429   */
430   void CAxis::checkBounds()
[1622]431   TRY
[1144]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) << ".");
[1235]440       hasBounds = true;
[1144]441     }
[1235]442     else hasBounds = false;
[1144]443   }
[1622]444   CATCH_DUMP_ATTR
[633]445
[1158]446  void CAxis::checkLabel()
[1622]447  TRY
[1158]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  }
[1622]460  CATCH_DUMP_ATTR
[1202]461
[1235]462  /*!
463    Check whether we can do compressed output
464  */
[1158]465  void CAxis::checkEligibilityForCompressedOutput()
[1622]466  TRY
[1158]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  }
[1622]471  CATCH_DUMP_ATTR
[633]472
[1235]473  /*!
474    Dispatch event from the lower communication layer then process event according to its type
475  */
476  bool CAxis::dispatchEvent(CEventServer& event)
[1622]477  TRY
[1235]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);
[633]486            return true;
487            break;
[1235]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  }
[1622]503  CATCH
[567]504
[1144]505   /*!
506     Check attributes on client side (This name is still adequate???)
507   */
[742]508   void CAxis::checkAttributesOnClient()
[1622]509   TRY
[567]510   {
511     if (this->areClientAttributesChecked_) return;
[595]512
[1421]513     CContext* context=CContext::getCurrent();
514     if (context->hasClient && !context->hasServer) this->checkAttributes();
[567]515
516     this->areClientAttributesChecked_ = true;
517   }
[1622]518   CATCH_DUMP_ATTR
[567]519
[1144]520   /*
[1235]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.
[1144]523   */
[927]524   void CAxis::checkAttributesOnClientAfterTransformation(const std::vector<int>& globalDim, int orderPositionInGrid,
525                                                          CServerDistributionDescription::ServerDistributionType distType)
[1622]526   TRY
[927]527   {
528     CContext* context=CContext::getCurrent() ;
529
530     if (this->isClientAfterTransformationChecked) return;
531     if (context->hasClient)
[1235]532     {       
[1258]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);
[927]536     }
537
538     this->isClientAfterTransformationChecked = true;
539   }
[1622]540   CATCH_DUMP_ATTR
[927]541
[1235]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   */
[567]549   void CAxis::sendCheckedAttributes(const std::vector<int>& globalDim, int orderPositionInGrid,
550                                     CServerDistributionDescription::ServerDistributionType distType)
[1622]551   TRY
[567]552   {
[742]553     if (!this->areClientAttributesChecked_) checkAttributesOnClient();
[927]554     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation(globalDim, orderPositionInGrid, distType);
[595]555     CContext* context = CContext::getCurrent();
[567]556
557     if (this->isChecked) return;
[1099]558     if (context->hasClient) sendAttributes(globalDim, orderPositionInGrid, distType);   
[567]559
560     this->isChecked = true;
561   }
[1622]562   CATCH_DUMP_ATTR
[567]563
[1144]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  */
[1099]569  void CAxis::sendAttributes(const std::vector<int>& globalDim, int orderPositionInGrid,
570                             CServerDistributionDescription::ServerDistributionType distType)
[1622]571  TRY
[633]572  {
[1235]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))
[1099]578     {
[1129]579       sendDistributedAttributes();       
[1099]580     }
[1235]581     else
582     {
583       sendNonDistributedAttributes();   
584     }     
[633]585  }
[1622]586  CATCH_DUMP_ATTR
[633]587
[1235]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,
[815]597                                     CServerDistributionDescription::ServerDistributionType distType)
[1622]598  TRY
[633]599  {
600    CContext* context = CContext::getCurrent();
[1099]601
[1030]602    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
[1236]603
604    connectedServerRank_.clear();
605    nbSenders.clear();
606
[1054]607    for (int p = 0; p < nbSrvPools; ++p)
[667]608    {
[1054]609      CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[p] : context->client;
[1027]610      int nbServer = client->serverSize;
611      int range, clientSize = client->clientSize;
612      int rank = client->clientRank;
[667]613
[1346]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();
[1099]619
[1346]620        // First of all, we should compute the mapping of the global index and local index of the current client
621        if (globalLocalIndexMap_.empty())
[1235]622        {
[1346]623          for (size_t idx = 0; idx < nbIndex; ++idx)
624          {
625            globalLocalIndexMap_[index(idx)] = idx;
626          }
[1235]627        }
628
[1346]629        // Calculate the compressed index if any
[1637]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//        }
[1099]644
[1346]645        // Compute the global index of the current client (process) hold
646        std::vector<int> nGlobAxis(1);
647        nGlobAxis[0] = n_glo.getValue();
[1235]648
[1346]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)
[906]653        {
[1346]654          indexBegin = rank%globalSizeIndex;
655          indexEnd = indexBegin;
[906]656        }
[1346]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        }
[815]668
[1346]669        CArray<size_t,1> globalIndex(index.numElements());
670        for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
671          globalIndex(idx) = index(idx);
[1235]672
[1346]673        // Describe the distribution of server side
[1258]674
[1346]675        CServerDistributionDescription serverDescription(nGlobAxis, nbServer, distType);
[1258]676     
[1346]677        std::vector<int> serverZeroIndex;
[1542]678        serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0);
[1235]679
[1346]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];
[1235]685
[1346]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();     
[1235]690
[1346]691        indSrv_[nbServer].swap(globalIndexAxisOnServer);
[1235]692
[1346]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        }
[1258]698         
[1346]699        CClientServerMapping::GlobalIndexMap::const_iterator it  = indSrv_[nbServer].begin(),
700                                                             ite = indSrv_[nbServer].end();
[1025]701
[1346]702        for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first);
[1258]703
[1346]704        for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
705          connectedServerRank_[nbServer].push_back(*it);
[1235]706
[1346]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);
[1235]711
[1637]712        nbSenders[nbServer] = CClientServerMapping::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]);
[1235]713
[1346]714        delete clientServerMap;
715      }
[633]716    }
717  }
[1622]718  CATCH_DUMP_ATTR
[633]719
[1235]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()
[1622]726  TRY
[1235]727  { 
728    if (computedWrittenIndex_) return;
729    computedWrittenIndex_ = true;
[633]730
[1235]731    CContext* context=CContext::getCurrent();     
732    CContextServer* server = context->server; 
[1129]733
[1235]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);
[1561]736    nBegin[0]       = begin;
[1559]737    nSize[0]        = n;
[1235]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();
[1129]742
[1235]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;     
[1542]746    std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
[1235]747                                                        ite = globalLocalIndexMap_.end(), it;         
748    CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
749                                     itSrve = writtenGlobalIndex.end(), itSrv; 
[1143]750
[1559]751    localIndexToWriteOnServer.resize(writtenGlobalIndex.numElements());
752    nbWritten = 0;
753    for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
[1235]754    {
[1559]755      indGlo = *itSrv;
756      if (ite != globalLocalIndexMap_.find(indGlo))
[1129]757      {
[1559]758        localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[indGlo];
[1235]759      }
[1637]760      else
761      {
762        localIndexToWriteOnServer(nbWritten) = -1;
763      }
764      ++nbWritten;
[1235]765    }
[1637]766
[1249]767  }
[1622]768  CATCH_DUMP_ATTR
[1249]769
[1639]770  void CAxis::computeWrittenCompressedIndex(MPI_Comm writtenComm)
[1622]771  TRY
[1249]772  {
773    int writtenCommSize;
[1639]774    MPI_Comm_size(writtenComm, &writtenCommSize);
[1249]775    if (compressedIndexToWriteOnServer.find(writtenCommSize) != compressedIndexToWriteOnServer.end())
776      return;
777
[1235]778    if (isCompressible())
779    {
[1249]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);
[1559]786      nBegin[0]       = 0;
787      nSize[0]        = n;
[1249]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();
[1542]792      std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
[1249]793                                                          ite = globalLocalIndexMap_.end(), it;   
794
795      CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
796                                       itSrve = writtenGlobalIndex.end(), itSrv;
[1542]797      std::unordered_map<size_t,size_t> localGlobalIndexMap;
[1235]798      for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
[1143]799      {
[1235]800        indGlo = *itSrv;
801        if (ite != globalLocalIndexMap_.find(indGlo))
[1143]802        {
[1235]803          localGlobalIndexMap[localIndexToWriteOnServer(nbWritten)] = indGlo;
804          ++nbWritten;
805        }                 
806      }
[1637]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//      }
[1143]827
[1235]828      nbWritten = 0;
829      for (int idx = 0; idx < data_index.numElements(); ++idx)
830      {
831        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
[1143]832        {
[1235]833          ++nbWritten;
[1143]834        }
[1235]835      }
[1143]836
[1249]837      compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten);
[1235]838      nbWritten = 0;
839      for (int idx = 0; idx < data_index.numElements(); ++idx)
840      {
841        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
[1143]842        {
[1249]843          compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)];
[1235]844          ++nbWritten;
[1143]845        }
[1235]846      }
[1143]847
[1249]848      numberWrittenIndexes_[writtenCommSize] = nbWritten;
[1672]849
850      bool distributed_glo, distributed=isDistributed() ;
851      MPI_Allreduce(&distributed,&distributed_glo, 1, MPI_INT, MPI_LOR, writtenComm) ;
852      if (distributed_glo)
[1235]853      {
854             
[1639]855        MPI_Allreduce(&numberWrittenIndexes_[writtenCommSize], &totalNumberWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
856        MPI_Scan(&numberWrittenIndexes_[writtenCommSize], &offsetWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
[1249]857        offsetWrittenIndexes_[writtenCommSize] -= numberWrittenIndexes_[writtenCommSize];
[1143]858      }
[1235]859      else
[1249]860        totalNumberWrittenIndexes_[writtenCommSize] = numberWrittenIndexes_[writtenCommSize];
[1235]861    }
862  }
[1622]863  CATCH_DUMP_ATTR
[1143]864
[1235]865  /*!
866    Send distribution information from a group of client (client role) to another group of client (server role)
867    The distribution of a group of client (server role) is imposed by the group of client (client role)
868    \param [in] globalDim global dimension of grid containing this axis
869    \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2)
870    \param [in] distType distribution type of the server. For now, we only have band distribution.
871  */
[1099]872  void CAxis::sendDistributionAttribute(const std::vector<int>& globalDim, int orderPositionInGrid,
873                                        CServerDistributionDescription::ServerDistributionType distType)
[1622]874  TRY
[1099]875  {
[1353]876    std::list<CContextClient*>::iterator it;
[1345]877    for (it=clients.begin(); it!=clients.end(); ++it)
[1099]878    {
[1345]879      CContextClient* client = *it;
880      int nbServer = client->serverSize;
[1099]881
882      CServerDistributionDescription serverDescription(globalDim, nbServer);
883      serverDescription.computeServerDistribution();
884
885      std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
886      std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
887
888      CEventClient event(getType(),EVENT_ID_DISTRIBUTION_ATTRIBUTE);
[1345]889      if (client->isServerLeader())
[1099]890      {
891        std::list<CMessage> msgs;
892
[1345]893        const std::list<int>& ranks = client->getRanksServerLeader();
[1099]894        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
895        {
896          // Use const int to ensure CMessage holds a copy of the value instead of just a reference
897          const int begin = serverIndexBegin[*itRank][orderPositionInGrid];
898          const int ni    = serverDimensionSizes[*itRank][orderPositionInGrid];
899
900          msgs.push_back(CMessage());
901          CMessage& msg = msgs.back();
902          msg << this->getId();
[1566]903          msg << ni << begin;
[1235]904          msg << isCompressible_;                   
[1099]905
906          event.push(*itRank,1,msg);
907        }
[1345]908        client->sendEvent(event);
[1099]909      }
[1345]910      else client->sendEvent(event);
[1099]911    }
912  }
[1622]913  CATCH_DUMP_ATTR
[1099]914
[1235]915  /*
916    Receive distribution attribute from another client
917    \param [in] event event containing data of these attributes
918  */
919  void CAxis::recvDistributionAttribute(CEventServer& event)
[1622]920  TRY
[1235]921  {
922    CBufferIn* buffer = event.subEvents.begin()->buffer;
923    string axisId;
924    *buffer >> axisId;
925    get(axisId)->recvDistributionAttribute(*buffer);
926  }
[1622]927  CATCH
[1235]928
929  /*
930    Receive distribution attribute from another client
931    \param [in] buffer buffer containing data of these attributes
932  */
933  void CAxis::recvDistributionAttribute(CBufferIn& buffer)
[1622]934  TRY
[1235]935  {
[1566]936    int ni_srv, begin_srv;
937    buffer >> ni_srv >> begin_srv;
[1235]938    buffer >> isCompressible_;           
939
940    // Set up new local size of axis on the receiving clients
941    n.setValue(ni_srv);
942    begin.setValue(begin_srv);
943  }
[1622]944  CATCH_DUMP_ATTR
[1235]945
946  /*
947    Send attributes of axis from a group of client to other group of clients/servers
948    on supposing that these attributes are not distributed among the sending group
949    In the future, if new attributes are added, they should also be processed in this function
950  */
[1025]951  void CAxis::sendNonDistributedAttributes()
[1622]952  TRY
[1025]953  {
[1353]954    std::list<CContextClient*>::iterator it;
[1345]955    for (it=clients.begin(); it!=clients.end(); ++it)
956        {
957          CContextClient* client = *it;
[1099]958
[1027]959      CEventClient event(getType(), EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES);
960      size_t nbIndex = index.numElements();
961      size_t nbDataIndex = 0;
[633]962
[1027]963      for (int idx = 0; idx < data_index.numElements(); ++idx)
[676]964      {
[1027]965        int ind = data_index(idx);
966        if (ind >= 0 && ind < nbIndex) ++nbDataIndex;
967      }
[676]968
[1027]969      CArray<int,1> dataIndex(nbDataIndex);
970      nbDataIndex = 0;
971      for (int idx = 0; idx < data_index.numElements(); ++idx)
972      {
973        int ind = data_index(idx);
974        if (ind >= 0 && ind < nbIndex)
975        {
976          dataIndex(nbDataIndex) = ind;
977          ++nbDataIndex;
978        }
979      }
[633]980
[1027]981      if (client->isServerLeader())
[633]982      {
[1027]983        std::list<CMessage> msgs;
[1025]984
[1027]985        const std::list<int>& ranks = client->getRanksServerLeader();
986        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
987        {
988          msgs.push_back(CMessage());
989          CMessage& msg = msgs.back();
990          msg << this->getId();
[1129]991          msg << index.getValue() << dataIndex << mask.getValue();
[1027]992          msg << hasValue;
993          if (hasValue) msg << value.getValue();
[1235]994          msg << hasBounds;
995          if (hasBounds) msg << bounds.getValue();
996          msg << hasLabel;
997          if (hasLabel) msg << label.getValue();
[1027]998
999          event.push(*itRank, 1, msg);
1000        }
1001        client->sendEvent(event);
[633]1002      }
[1027]1003      else client->sendEvent(event);
[633]1004    }
1005  }
[1622]1006  CATCH_DUMP_ATTR
[633]1007
[1235]1008  /*
1009    Receive the non-distributed attributes from another group of clients
1010    \param [in] event event containing data of these attributes
1011  */
[1025]1012  void CAxis::recvNonDistributedAttributes(CEventServer& event)
[1622]1013  TRY
[633]1014  {
[1025]1015    list<CEventServer::SSubEvent>::iterator it;
1016    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1017    {
1018      CBufferIn* buffer = it->buffer;
1019      string axisId;
1020      *buffer >> axisId;
1021      get(axisId)->recvNonDistributedAttributes(it->rank, *buffer);
1022    }
1023  }
[1622]1024  CATCH
[1025]1025
[1235]1026  /*
1027    Receive the non-distributed attributes from another group of clients
1028    \param [in] rank rank of the sender
1029    \param [in] buffer buffer containing data sent from the sender
1030  */
[1025]1031  void CAxis::recvNonDistributedAttributes(int rank, CBufferIn& buffer)
[1622]1032  TRY
[1025]1033  { 
[1559]1034    CArray<int,1> tmp_index, tmp_data_index;
[1025]1035    CArray<bool,1> tmp_mask;
1036    CArray<double,1> tmp_val;
1037    CArray<double,2> tmp_bnds;
[1235]1038    CArray<string,1> tmp_label;
[1025]1039
1040    buffer >> tmp_index;
1041    index.reference(tmp_index);
1042    buffer >> tmp_data_index;
1043    data_index.reference(tmp_data_index);
1044    buffer >> tmp_mask;
1045    mask.reference(tmp_mask);
[1129]1046
[1025]1047    buffer >> hasValue;
1048    if (hasValue)
1049    {
1050      buffer >> tmp_val;
1051      value.reference(tmp_val);
1052    }
1053
[1235]1054    buffer >> hasBounds;
1055    if (hasBounds)
[1025]1056    {
1057      buffer >> tmp_bnds;
1058      bounds.reference(tmp_bnds);
1059    }
1060
[1235]1061    buffer >> hasLabel;
1062    if (hasLabel)
1063    {
1064      buffer >> tmp_label;
1065      label.reference(tmp_label);
1066    }
1067
1068    // Some value should be reset here
[1129]1069    data_begin.setValue(0);
1070    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
[1416]1071//    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[idx] = index(idx);
1072    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[index(idx)] = idx;
[1025]1073  }
[1622]1074  CATCH_DUMP_ATTR
[1025]1075
[1235]1076  /*
[1637]1077    Send axis attributes from a group of clients to another group of clients/servers
1078    supposing that these attributes are distributed among the clients of the sending group
1079    In future, if new attributes are added, they should also be processed in this function
[1235]1080  */
[1025]1081  void CAxis::sendDistributedAttributes(void)
[1622]1082  TRY
[1025]1083  {
[1637]1084    int ind, idx;
[1353]1085    std::list<CContextClient*>::iterator it;
[1345]1086
1087    for (it=clients.begin(); it!=clients.end(); ++it)
[1025]1088    {
[1345]1089      CContextClient* client = *it;
[1337]1090      int nbServer = client->serverSize;
[1025]1091
[1027]1092      CEventClient eventData(getType(), EVENT_ID_DISTRIBUTED_ATTRIBUTES);
[633]1093
[1027]1094      list<CMessage> listData;
[1559]1095      list<CArray<int,1> > list_indi, list_dataInd;
[1027]1096      list<CArray<double,1> > list_val;
1097      list<CArray<double,2> > list_bounds;
[1235]1098      list<CArray<string,1> > list_label;
[633]1099
[1637]1100      // Cut off the ghost points
[1027]1101      int nbIndex = index.numElements();
1102      CArray<int,1> dataIndex(nbIndex);
1103      dataIndex = -1;
[1235]1104      for (idx = 0; idx < data_index.numElements(); ++idx)
[633]1105      {
[1235]1106        if (0 <= data_index(idx) && data_index(idx) < nbIndex)
[1637]1107          dataIndex(data_index(idx)) = 1;
[633]1108      }
1109
[1542]1110      std::unordered_map<int, std::vector<size_t> >::const_iterator it, iteMap;
[1337]1111      iteMap = indSrv_[nbServer].end();
1112      for (int k = 0; k < connectedServerRank_[nbServer].size(); ++k)
[633]1113      {
[1637]1114        int nbData = 0, nbDataCount = 0;
[1337]1115        int rank = connectedServerRank_[nbServer][k];
1116        it = indSrv_[nbServer].find(rank);
[1027]1117        if (iteMap != it)
1118          nbData = it->second.size();
[633]1119
[1027]1120        list_indi.push_back(CArray<int,1>(nbData));
[1637]1121        list_dataInd.push_back(CArray<int,1>(nbData));
[1025]1122
1123        if (hasValue)
[1027]1124          list_val.push_back(CArray<double,1>(nbData));
1125
[1235]1126        if (hasBounds)       
[1027]1127          list_bounds.push_back(CArray<double,2>(2,nbData));
[1025]1128
[1235]1129        if (hasLabel)
1130          list_label.push_back(CArray<string,1>(nbData));
1131
[1027]1132        CArray<int,1>& indi = list_indi.back();
[1637]1133        CArray<int,1>& dataIndi = list_dataInd.back();
1134        dataIndi = -1;
[1027]1135
[1637]1136        for (int n = 0; n < nbData; ++n)
[633]1137        {
[1027]1138          idx = static_cast<int>(it->second[n]);
1139          indi(n) = idx;
1140
1141          ind = globalLocalIndexMap_[idx];
1142          dataIndi(n) = dataIndex(ind);
1143
1144          if (hasValue)
1145          {
1146            CArray<double,1>& val = list_val.back();
1147            val(n) = value(ind);
1148          }
1149
[1235]1150          if (hasBounds)
[1027]1151          {
1152            CArray<double,2>& boundsVal = list_bounds.back();
[1351]1153            boundsVal(0, n) = bounds(0,ind);
1154            boundsVal(1, n) = bounds(1,ind);
[1027]1155          }
[1235]1156
1157          if (hasLabel)
1158          {
1159            CArray<string,1>& labelVal = list_label.back();
1160            labelVal(n) = label(ind); 
1161          }
[633]1162        }
[1027]1163
1164        listData.push_back(CMessage());
1165        listData.back() << this->getId()
[1637]1166                        << list_indi.back() << list_dataInd.back();
[1099]1167
1168        listData.back() << hasValue;
[1027]1169        if (hasValue)
1170          listData.back() << list_val.back();
[1099]1171
[1235]1172        listData.back() << hasBounds;
1173        if (hasBounds)
[1027]1174          listData.back() << list_bounds.back();
1175
[1235]1176        listData.back() << hasLabel;
1177        if (hasLabel)
1178          listData.back() << list_label.back();
1179
[1337]1180        eventData.push(rank, nbSenders[nbServer][rank], listData.back());
[633]1181      }
1182
[1027]1183      client->sendEvent(eventData);
[633]1184    }
1185  }
[1622]1186  CATCH_DUMP_ATTR
[633]1187
[1235]1188  /*
1189    Receive the distributed attributes from another group of clients
1190    \param [in] event event containing data of these attributes
1191  */
[1025]1192  void CAxis::recvDistributedAttributes(CEventServer& event)
[1622]1193  TRY
[633]1194  {
[1025]1195    string axisId;
1196    vector<int> ranks;
1197    vector<CBufferIn*> buffers;
[676]1198
[633]1199    list<CEventServer::SSubEvent>::iterator it;
1200    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1201    {
[1025]1202      ranks.push_back(it->rank);
[633]1203      CBufferIn* buffer = it->buffer;
[676]1204      *buffer >> axisId;
[1025]1205      buffers.push_back(buffer);
[633]1206    }
[1025]1207    get(axisId)->recvDistributedAttributes(ranks, buffers);
[633]1208  }
[1622]1209  CATCH
[633]1210
[1235]1211  /*
1212    Receive the non-distributed attributes from another group of clients
1213    \param [in] ranks rank of the sender
1214    \param [in] buffers buffer containing data sent from the sender
1215  */
[1025]1216  void CAxis::recvDistributedAttributes(vector<int>& ranks, vector<CBufferIn*> buffers)
[1622]1217  TRY
[633]1218  {
[1235]1219    int nbReceived = ranks.size(), idx, ind, gloInd, locInd;
[1559]1220    vector<CArray<int,1> > vec_indi(nbReceived), vec_dataInd(nbReceived);
[1025]1221    vector<CArray<double,1> > vec_val(nbReceived);
1222    vector<CArray<double,2> > vec_bounds(nbReceived);
[1235]1223    vector<CArray<string,1> > vec_label(nbReceived);
[1025]1224   
[1235]1225    for (idx = 0; idx < nbReceived; ++idx)
[1025]1226    {     
1227      CBufferIn& buffer = *buffers[idx];
1228      buffer >> vec_indi[idx];
[1099]1229      buffer >> vec_dataInd[idx];     
[676]1230
[1025]1231      buffer >> hasValue;
1232      if (hasValue)
1233        buffer >> vec_val[idx];
[1099]1234
[1235]1235      buffer >> hasBounds;
1236      if (hasBounds)
[1025]1237        buffer >> vec_bounds[idx];
[1235]1238
1239      buffer >> hasLabel;
1240      if (hasLabel)
1241        buffer >> vec_label[idx]; 
[676]1242    }
[633]1243
[1235]1244    // Estimate size of index array
1245    int nbIndexGlob = 0;
1246    for (idx = 0; idx < nbReceived; ++idx)
[633]1247    {
[1235]1248      nbIndexGlob += vec_indi[idx].numElements();
[633]1249    }
[1129]1250
[1235]1251    // Recompute global index
1252    // Take account of the overlapped index
1253    index.resize(nbIndexGlob);
[1129]1254    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
[1235]1255    nbIndexGlob = 0;
[1566]1256    int nbIndLoc = 0;
[1235]1257    for (idx = 0; idx < nbReceived; ++idx)
1258    {
1259      CArray<int,1>& tmp = vec_indi[idx];
1260      for (ind = 0; ind < tmp.numElements(); ++ind)
1261      {
1262         gloInd = tmp(ind);
[1566]1263         nbIndLoc = (gloInd % n_glo)-begin;
[1235]1264         if (0 == globalLocalIndexMap_.count(gloInd))
1265         {
[1637]1266           index(nbIndexGlob) = gloInd % n_glo;
1267           globalLocalIndexMap_[gloInd] = nbIndexGlob;
[1235]1268           ++nbIndexGlob;
1269         } 
1270      } 
1271    }
1272
1273    // Resize index to its real size
[1301]1274    if (nbIndexGlob==0) index.resize(nbIndexGlob) ;
1275    else index.resizeAndPreserve(nbIndexGlob);
[1235]1276
1277    int nbData = nbIndexGlob;
1278    CArray<int,1> nonCompressedData(nbData);
1279    nonCompressedData = -1;   
[1637]1280    // Mask is incorporated into data_index and is not sent/received anymore
1281    mask.resize(0);
[1025]1282    if (hasValue)
1283      value.resize(nbData);
[1235]1284    if (hasBounds)
[1025]1285      bounds.resize(2,nbData);
[1235]1286    if (hasLabel)
1287      label.resize(nbData);
[633]1288
[1025]1289    nbData = 0;
[1235]1290    for (idx = 0; idx < nbReceived; ++idx)
[633]1291    {
[1025]1292      CArray<int,1>& indi = vec_indi[idx];
1293      CArray<int,1>& dataIndi = vec_dataInd[idx];
1294      int nb = indi.numElements();
1295      for (int n = 0; n < nb; ++n)
[1235]1296      { 
1297        locInd = globalLocalIndexMap_[size_t(indi(n))];
1298
1299        nonCompressedData(locInd) = (-1 == nonCompressedData(locInd)) ? dataIndi(n) : nonCompressedData(locInd);
1300
[1025]1301        if (hasValue)
[1235]1302          value(locInd) = vec_val[idx](n);
1303
1304        if (hasBounds)
[1025]1305        {
[1235]1306          bounds(0,locInd) = vec_bounds[idx](0,n);
1307          bounds(1,locInd) = vec_bounds[idx](1,n);
[1025]1308        }
[1235]1309
1310        if (hasLabel)
1311          label(locInd) = vec_label[idx](n);
[633]1312      }
1313    }
[1235]1314   
[1637]1315    int nbCompressedData = 0;
[1235]1316    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
[1025]1317    {
[1235]1318      if (0 <= nonCompressedData(idx))
[1637]1319        ++nbCompressedData;
[1025]1320    }
[676]1321
[1025]1322    data_index.resize(nbCompressedData);
1323    nbCompressedData = 0;
[1235]1324    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
[633]1325    {
[1235]1326      if (0 <= nonCompressedData(idx))
[1025]1327      {
[1235]1328        data_index(nbCompressedData) = idx % n;
[1637]1329        ++nbCompressedData;
[1025]1330      }
[633]1331    }
[1235]1332
[1129]1333    data_begin.setValue(0);
[1637]1334    data_n.setValue(data_index.numElements());
[633]1335  }
[1622]1336  CATCH_DUMP_ATTR
[633]1337
[1158]1338  /*!
1339    Compare two axis objects.
1340    They are equal if only if they have identical attributes as well as their values.
1341    Moreover, they must have the same transformations.
1342  \param [in] axis Compared axis
1343  \return result of the comparison
1344  */
1345  bool CAxis::isEqual(CAxis* obj)
[1622]1346  TRY
[1158]1347  {
1348    vector<StdString> excludedAttr;
1349    excludedAttr.push_back("axis_ref");
[987]1350
[1158]1351    bool objEqual = SuperClass::isEqual(obj, excludedAttr);   
1352    if (!objEqual) return objEqual;
1353
1354    TransMapTypes thisTrans = this->getAllTransformations();
1355    TransMapTypes objTrans  = obj->getAllTransformations();
1356
1357    TransMapTypes::const_iterator it, itb, ite;
1358    std::vector<ETranformationType> thisTransType, objTransType;
1359    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
1360      thisTransType.push_back(it->first);
1361    for (it = objTrans.begin(); it != objTrans.end(); ++it)
1362      objTransType.push_back(it->first);
1363
1364    if (thisTransType.size() != objTransType.size()) return false;
1365    for (int idx = 0; idx < thisTransType.size(); ++idx)
1366      objEqual &= (thisTransType[idx] == objTransType[idx]);
1367
1368    return objEqual;
1369  }
[1622]1370  CATCH_DUMP_ATTR
[1158]1371
[1235]1372  /*
1373    Add transformation into axis. This function only servers for Fortran interface
1374    \param [in] transType transformation type
1375    \param [in] id identifier of the transformation object
1376  */
[836]1377  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
[1622]1378  TRY
[836]1379  {
1380    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
1381    return transformationMap_.back().second;
1382  }
[1622]1383  CATCH_DUMP_ATTR
[836]1384
[1235]1385  /*
1386    Check whether an axis has (spatial) transformation
1387  */
[619]1388  bool CAxis::hasTransformation()
[1622]1389  TRY
[619]1390  {
[621]1391    return (!transformationMap_.empty());
[619]1392  }
[1622]1393  CATCH_DUMP_ATTR
[619]1394
[1235]1395  /*
1396    Set transformation
1397    \param [in] axisTrans transformation to set
1398  */
[621]1399  void CAxis::setTransformations(const TransMapTypes& axisTrans)
[1622]1400  TRY
[619]1401  {
[621]1402    transformationMap_ = axisTrans;
[619]1403  }
[1622]1404  CATCH_DUMP_ATTR
[619]1405
[1235]1406  /*
1407    Return all transformation held by the axis
1408    \return transformation the axis has
1409  */
[621]1410  CAxis::TransMapTypes CAxis::getAllTransformations(void)
[1622]1411  TRY
[620]1412  {
[621]1413    return transformationMap_;
1414  }
[1622]1415  CATCH_DUMP_ATTR
[620]1416
[1235]1417  /*
1418    Duplicate transformation of another axis
1419    \param [in] src axis whose transformations are copied
1420  */
[823]1421  void CAxis::duplicateTransformation(CAxis* src)
[1622]1422  TRY
[823]1423  {
1424    if (src->hasTransformation())
1425    {
1426      this->setTransformations(src->getAllTransformations());
1427    }
1428  }
[1622]1429  CATCH_DUMP_ATTR
[823]1430
[747]1431  /*!
1432   * Go through the hierarchy to find the axis from which the transformations must be inherited
1433   */
[619]1434  void CAxis::solveInheritanceTransformation()
[1622]1435  TRY
[619]1436  {
[747]1437    if (hasTransformation() || !hasDirectAxisReference())
1438      return;
[619]1439
[747]1440    CAxis* axis = this;
[619]1441    std::vector<CAxis*> refAxis;
[747]1442    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
[619]1443    {
[747]1444      refAxis.push_back(axis);
1445      axis = axis->getDirectAxisReference();
[619]1446    }
1447
[747]1448    if (axis->hasTransformation())
1449      for (size_t i = 0; i < refAxis.size(); ++i)
1450        refAxis[i]->setTransformations(axis->getAllTransformations());
[619]1451  }
[1622]1452  CATCH_DUMP_ATTR
[619]1453
[1345]1454  void CAxis::setContextClient(CContextClient* contextClient)
[1622]1455  TRY
[1345]1456  {
[1353]1457    if (clientsSet.find(contextClient)==clientsSet.end())
1458    {
1459      clients.push_back(contextClient) ;
1460      clientsSet.insert(contextClient);
1461    }
[1622]1462  }
1463  CATCH_DUMP_ATTR
[1345]1464
[619]1465  void CAxis::parse(xml::CXMLNode & node)
[1622]1466  TRY
[619]1467  {
1468    SuperClass::parse(node);
1469
1470    if (node.goToChildElement())
1471    {
[836]1472      StdString nodeElementName;
[619]1473      do
1474      {
[784]1475        StdString nodeId("");
1476        if (node.getAttributes().end() != node.getAttributes().find("id"))
1477        { nodeId = node.getAttributes()["id"]; }
1478
[836]1479        nodeElementName = node.getElementName();
1480        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
1481        it = transformationMapList_.find(nodeElementName);
1482        if (ite != it)
1483        {
1484          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second,
1485                                                                                                               nodeId,
1486                                                                                                               &node)));
[786]1487        }
[968]1488        else
1489        {
1490          ERROR("void CAxis::parse(xml::CXMLNode & node)",
1491                << "The transformation " << nodeElementName << " has not been supported yet.");
1492        }
[619]1493      } while (node.goToNextElement()) ;
1494      node.goToParentElement();
1495    }
1496  }
[1622]1497  CATCH_DUMP_ATTR
[619]1498
[620]1499  DEFINE_REF_FUNC(Axis,axis)
[619]1500
[219]1501   ///---------------------------------------------------------------
1502
[335]1503} // namespace xios
Note: See TracBrowser for help on using the repository browser.