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

Last change on this file since 2297 was 1964, checked in by yushan, 4 years ago

trunk : Mask was not correctly applied on data when data_index is used

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