source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp @ 1958

Last change on this file since 1958 was 1956, checked in by ymipsl, 4 years ago

Xios coupling

  • fix problem when sending grid mask from client to server
  • remove methods about grid compression, which will be managed in other ways

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: 64.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
[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     
[1787]95      distributed |= (1 == CContext::getCurrent()->intraCommSize_);
[1158]96      return distributed;
[594]97   }
[1622]98   CATCH
[594]99
[676]100   /*!
[1956]101    * Compute if the axis can be ouput in a compressed way.
102    * In this case the workflow view on server side must be the same
103    * than the full view for all context rank. The result is stored on
104    * internal isCompressible_ attribute.
[676]105    */
[1956]106   void CAxis::computeIsCompressible(void)
[1622]107   TRY
[676]108   {
[1956]109     // mesh is compressible contains some masked or indexed value, ie if full view is different of workflow view.
110     // But now assume that the size of the 2 view must be equal for everybody. True on server side
111     int isSameView = getLocalView(CElementView::FULL)->getSize() ==  getLocalView(CElementView::WORKFLOW)->getSize();
112     MPI_Allreduce(MPI_IN_PLACE, &isSameView, 1, MPI_INT, MPI_LAND, CContext::getCurrent()->getIntraComm()) ;
113     if (isSameView) isCompressible_ = false ;
114     else isCompressible_ = true ;
115     isCompressibleComputed_=true ;
[676]116   }
[1622]117   CATCH
[676]118
[219]119   void CAxis::addRelFile(const StdString & filename)
[1622]120   TRY
[219]121   {
122      this->relFiles.insert(filename);
123   }
[1622]124   CATCH_DUMP_ATTR
[219]125
[676]126   void CAxis::addRelFileCompressed(const StdString& filename)
[1622]127   TRY
[676]128   {
129      this->relFilesCompressed.insert(filename);
130   }
[1622]131   CATCH_DUMP_ATTR
[676]132
[219]133   //----------------------------------------------------------------
134
[676]135   /*!
136     Returns the number of indexes written by each server.
137     \return the number of indexes written by each server
138   */
[1639]139   int CAxis::getNumberWrittenIndexes(MPI_Comm writtenCom)
[1622]140   TRY
[676]141   {
[1249]142     int writtenSize;
[1639]143     MPI_Comm_size(writtenCom, &writtenSize);
[1249]144     return numberWrittenIndexes_[writtenSize];
[676]145   }
[1622]146   CATCH_DUMP_ATTR
[676]147
148   /*!
149     Returns the total number of indexes written by the servers.
150     \return the total number of indexes written by the servers
151   */
[1639]152   int CAxis::getTotalNumberWrittenIndexes(MPI_Comm writtenCom)
[1622]153   TRY
[676]154   {
[1249]155     int writtenSize;
[1639]156     MPI_Comm_size(writtenCom, &writtenSize);
[1249]157     return totalNumberWrittenIndexes_[writtenSize];
[676]158   }
[1622]159   CATCH_DUMP_ATTR
[676]160
161   /*!
162     Returns the offset of indexes written by each server.
163     \return the offset of indexes written by each server
164   */
[1639]165   int CAxis::getOffsetWrittenIndexes(MPI_Comm writtenCom)
[1622]166   TRY
[676]167   {
[1249]168     int writtenSize;
[1639]169     MPI_Comm_size(writtenCom, &writtenSize);
[1249]170     return offsetWrittenIndexes_[writtenSize];
[676]171   }
[1622]172   CATCH_DUMP_ATTR
[676]173
[1639]174   CArray<int, 1>& CAxis::getCompressedIndexToWriteOnServer(MPI_Comm writtenCom)
[1622]175   TRY
[1249]176   {
177     int writtenSize;
[1639]178     MPI_Comm_size(writtenCom, &writtenSize);
[1249]179     return compressedIndexToWriteOnServer[writtenSize];
180   }
[1622]181   CATCH_DUMP_ATTR
182
[676]183   //----------------------------------------------------------------
184
[731]185   /*!
186    * Compute the minimum buffer size required to send the attributes to the server(s).
187    *
188    * \return A map associating the server rank with its minimum buffer size.
189    */
[1371]190   std::map<int, StdSize> CAxis::getAttributesBufferSize(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
191                                                         CServerDistributionDescription::ServerDistributionType distType)
[1622]192   TRY
[731]193   {
194
[1330]195     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client);
[731]196
[1371]197//     bool isNonDistributed = (n_glo == n);
198     bool isDistributed = (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
199                                 || (index.numElements() != n_glo);
[731]200
201     if (client->isServerLeader())
202     {
203       // size estimation for sendServerAttribut
204       size_t size = 6 * sizeof(size_t);
205       // size estimation for sendNonDistributedValue
[1371]206       if (!isDistributed)
207       {
208//         size = std::max(size, CArray<double,1>::size(n_glo) + (isCompressible_ ? CArray<int,1>::size(n_glo) : 0));
209         size += CArray<int,1>::size(n_glo);
210         size += CArray<int,1>::size(n_glo);
211         size += CArray<bool,1>::size(n_glo);
212         size += CArray<double,1>::size(n_glo);
213         if (hasBounds)
214           size += CArray<double,2>::size(2*n_glo);
215         if (hasLabel)
216          size += CArray<StdString,1>::size(n_glo);
217       }
[731]218       size += CEventClient::headerSize + getId().size() + sizeof(size_t);
219
220       const std::list<int>& ranks = client->getRanksServerLeader();
221       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
222       {
223         if (size > attributesSizes[*itRank])
224           attributesSizes[*itRank] = size;
225       }
[1371]226       const std::list<int>& ranksNonLeaders = client->getRanksServerNotLeader();
227       for (std::list<int>::const_iterator itRank = ranksNonLeaders.begin(), itRankEnd = ranksNonLeaders.end(); itRank != itRankEnd; ++itRank)
228       {
229         if (size > attributesSizes[*itRank])
230           attributesSizes[*itRank] = size;
231       }
232
[731]233     }
234
[1371]235     if (isDistributed)
[731]236     {
237       // size estimation for sendDistributedValue
[1542]238       std::unordered_map<int, vector<size_t> >::const_iterator it, ite = indSrv_[client->serverSize].end();
[1337]239       for (it = indSrv_[client->serverSize].begin(); it != ite; ++it)
[731]240       {
[1371]241         size_t size = 6 * sizeof(size_t);
242         size += CArray<int,1>::size(it->second.size());
243         size += CArray<int,1>::size(it->second.size());
244         size += CArray<bool,1>::size(it->second.size());
245         size += CArray<double,1>::size(it->second.size());
[1235]246         if (hasBounds)
[1371]247           size += CArray<double,2>::size(2 * it->second.size());
[1158]248         if (hasLabel)
[1371]249           size += CArray<StdString,1>::size(it->second.size());
[731]250
[1371]251         size += CEventClient::headerSize + getId().size() + sizeof(size_t);
[731]252         if (size > attributesSizes[it->first])
253           attributesSizes[it->first] = size;
254       }
255     }
256     return attributesSizes;
257   }
[1622]258   CATCH_DUMP_ATTR
[731]259
260   //----------------------------------------------------------------
261
[219]262   StdString CAxis::GetName(void)   { return (StdString("axis")); }
263   StdString CAxis::GetDefName(void){ return (CAxis::GetName()); }
264   ENodeType CAxis::GetType(void)   { return (eAxis); }
265
266   //----------------------------------------------------------------
267
[622]268   CAxis* CAxis::createAxis()
[1622]269   TRY
[622]270   {
271     CAxis* axis = CAxisGroup::get("axis_definition")->createChild();
272     return axis;
273   }
[1622]274   CATCH
[622]275
[1144]276   /*!
277     Check common attributes of an axis.
278     This check should be done in the very beginning of work flow
279   */
[219]280   void CAxis::checkAttributes(void)
[1622]281   TRY
[219]282   {
[1869]283     if (checkAttributes_done_) return ;
284
[1637]285     CContext* context=CContext::getCurrent();
286
287     if (this->n_glo.isEmpty())
[679]288        ERROR("CAxis::checkAttributes(void)",
289              << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
290              << "The axis is wrongly defined, attribute 'n_glo' must be specified");
[666]291      StdSize size = this->n_glo.getValue();
[540]292
[970]293      if (!this->index.isEmpty())
[551]294      {
[970]295        if (n.isEmpty()) n = index.numElements();
296
297        // It's not so correct but if begin is not the first value of index
298        // then data on the local axis has user-defined distribution. In this case, begin has no meaning.
299        if (begin.isEmpty()) begin = index(0);         
[551]300      }
[970]301      else 
302      {
303        if (!this->begin.isEmpty())
304        {
305          if (begin < 0 || begin > size - 1)
306            ERROR("CAxis::checkAttributes(void)",
307                  << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
308                  << "The axis is wrongly defined, attribute 'begin' (" << begin.getValue() << ") must be non-negative and smaller than size-1 (" << size - 1 << ").");
309        }
310        else this->begin.setValue(0);
[551]311
[970]312        if (!this->n.isEmpty())
313        {
314          if (n < 0 || n > size)
315            ERROR("CAxis::checkAttributes(void)",
316                  << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
317                  << "The axis is wrongly defined, attribute 'n' (" << n.getValue() << ") must be non-negative and smaller than size (" << size << ").");
318        }
319        else this->n.setValue(size);
320
321        {
322          index.resize(n);
323          for (int i = 0; i < n; ++i) index(i) = i+begin;
324        }
[551]325      }
[624]326
[816]327      if (!this->value.isEmpty())
328      {
[1869]329        StdSize true_size = value.numElements();
330        if (this->n.getValue() != true_size)
331          ERROR("CAxis::checkAttributes(void)",
332              << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
333              << "The axis is wrongly defined, attribute 'value' has a different size (" << true_size
334              << ") than the one defined by the \'size\' attribute (" << n.getValue() << ").");
[816]335        this->hasValue = true;
336      }
[219]337
[1158]338      this->checkBounds();
[1869]339      this->checkMask();
340      this->checkData();
341      this->checkLabel();
[1918]342      initializeLocalElement() ;
343      addFullView() ;
344      addWorkflowView() ;
345      addModelView() ;
346
[1869]347      checkAttributes_done_ = true ;
[219]348   }
[1622]349   CATCH_DUMP_ATTR
[219]350
[1918]351
352
[1144]353   /*!
[1637]354      Check the validity of data, fill in values if any, and apply mask.
[1144]355   */
[551]356   void CAxis::checkData()
[1622]357   TRY
[551]358   {
359      if (data_begin.isEmpty()) data_begin.setValue(0);
[679]360
361      if (data_n.isEmpty())
[551]362      {
[679]363        data_n.setValue(n);
364      }
365      else if (data_n.getValue() < 0)
366      {
[551]367        ERROR("CAxis::checkData(void)",
[679]368              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
369              << "The data size should be strictly positive ('data_n' = " << data_n.getValue() << ").");
[551]370      }
371
372      if (data_index.isEmpty())
373      {
[679]374        data_index.resize(data_n);
[1637]375        for (int i = 0; i < data_n; ++i)
376        {
377          if ((i+data_begin) >= 0 && (i+data_begin<n))
378          {
379            if (mask(i+data_begin))
380              data_index(i) = i+data_begin;
381            else
382              data_index(i) = -1;
383          }
384          else
385            data_index(i) = -1;
386        }
[551]387      }
[1637]388      else
389      {
390        if (data_index.numElements() != data_n)
391        {
392          ERROR("CAxis::checkData(void)",
393                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
394                << "The size of data_index = "<< data_index.numElements() << "is not equal to the data size data_n = " << data_n.getValue() << ").");
395        }
396        for (int i = 0; i < data_n; ++i)
397        {
[1872]398           if (data_index(i) >= 0 && data_index(i)<n)
399             if (!mask(data_index(i))) data_index(i) = -1;
[1637]400        }
401      }
402
[551]403   }
[1622]404   CATCH_DUMP_ATTR
[551]405
[1215]406    size_t CAxis::getGlobalWrittenSize(void)
407    {
[1559]408      return n_glo ;
[1215]409    }
410
[1144]411   /*!
412     Check validity of mask info and fill in values if any.
413   */
[551]414   void CAxis::checkMask()
[1622]415   TRY
[551]416   {
417      if (!mask.isEmpty())
418      {
[1637]419        if (mask.extent(0) != n)
420        {
421          ERROR("CAxis::checkMask(void)",
422              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
423              << "The mask does not have the same size as the local domain." << std::endl
424              << "Local size is " << n.getValue() << "." << std::endl
425              << "Mask size is " << mask.extent(0) << ".");
426        }
[551]427      }
[1637]428      else
429      {
430        mask.resize(n);
431        mask = true;
[551]432      }
433   }
[1622]434   CATCH_DUMP_ATTR
[551]435
[1144]436   /*!
437     Check validity of bounds info and fill in values if any.
438   */
439   void CAxis::checkBounds()
[1622]440   TRY
[1144]441   {
442     if (!bounds.isEmpty())
443     {
444       if (bounds.extent(0) != 2 || bounds.extent(1) != n)
445         ERROR("CAxis::checkAttributes(void)",
446               << "The bounds array of the axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] must be of dimension 2 x axis size." << std::endl
447               << "Axis size is " << n.getValue() << "." << std::endl
448               << "Bounds size is "<< bounds.extent(0) << " x " << bounds.extent(1) << ".");
[1235]449       hasBounds = true;
[1144]450     }
[1235]451     else hasBounds = false;
[1144]452   }
[1622]453   CATCH_DUMP_ATTR
[633]454
[1158]455  void CAxis::checkLabel()
[1622]456  TRY
[1158]457  {
458    if (!label.isEmpty())
459    {
460      if (label.extent(0) != n)
461        ERROR("CAxis::checkLabel(void)",
462              << "The label array of the axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] must be of dimension of axis size." << std::endl
463              << "Axis size is " << n.getValue() << "." << std::endl
464              << "label size is "<< label.extent(0)<<  " .");
465      hasLabel = true;
466    }
467    else hasLabel = false;
468  }
[1622]469  CATCH_DUMP_ATTR
[1202]470
[1956]471 
[1235]472  /*!
473    Dispatch event from the lower communication layer then process event according to its type
474  */
475  bool CAxis::dispatchEvent(CEventServer& event)
[1622]476  TRY
[1235]477  {
478     if (SuperClass::dispatchEvent(event)) return true;
479     else
480     {
481       switch(event.type)
482       {
483          case EVENT_ID_DISTRIBUTION_ATTRIBUTE :
484            recvDistributionAttribute(event);
[633]485            return true;
486            break;
[1235]487         case EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES:
488           recvNonDistributedAttributes(event);
489           return true;
490           break;
491         case EVENT_ID_DISTRIBUTED_ATTRIBUTES:
[1930]492           recvDistributedAttributes_old(event);
493           return true;
494           break;
495         case EVENT_ID_AXIS_DISTRIBUTION:
496           recvAxisDistribution(event);
497           return true;
498           break;
499         case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE:
[1235]500           recvDistributedAttributes(event);
501           return true;
502           break;
503          default :
504            ERROR("bool CAxis::dispatchEvent(CEventServer& event)",
505                   << "Unknown Event");
506          return false;
507        }
508     }
509  }
[1622]510  CATCH
[567]511
[1144]512   /*!
513     Check attributes on client side (This name is still adequate???)
514   */
[742]515   void CAxis::checkAttributesOnClient()
[1622]516   TRY
[567]517   {
518     if (this->areClientAttributesChecked_) return;
[595]519
[1421]520     CContext* context=CContext::getCurrent();
[1853]521     if (context->getServiceType()==CServicesManager::CLIENT) this->checkAttributes();
[567]522
523     this->areClientAttributesChecked_ = true;
524   }
[1622]525   CATCH_DUMP_ATTR
[567]526
[1144]527   /*
[1235]528     The (spatial) transformation sometimes can change attributes of an axis (e.g zoom can change mask or generate can change whole attributes)
529     Therefore, we should recheck them.
[1144]530   */
[1869]531   // ym : obsolete to be removed
[927]532   void CAxis::checkAttributesOnClientAfterTransformation(const std::vector<int>& globalDim, int orderPositionInGrid,
533                                                          CServerDistributionDescription::ServerDistributionType distType)
[1622]534   TRY
[927]535   {
536     CContext* context=CContext::getCurrent() ;
537
538     if (this->isClientAfterTransformationChecked) return;
[1853]539     if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER)
[1235]540     {       
[1869]541       /* suppressed because of interface changed
[1258]542       if (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
543         computeConnectedClients(globalDim, orderPositionInGrid, distType);
544       else if (index.numElements() != n_glo) computeConnectedClients(globalDim, orderPositionInGrid,  CServerDistributionDescription::ROOT_DISTRIBUTION);
[1869]545       */
[927]546     }
547
548     this->isClientAfterTransformationChecked = true;
549   }
[1622]550   CATCH_DUMP_ATTR
[927]551
[1235]552   /*
553     Send all checked attributes to server? (We dont have notion of server any more so client==server)
554     \param [in] globalDim global dimension of grid containing this axis
555     \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2)
556     \param [in] distType distribution type of the server. For now, we only have band distribution.
557
558   */
[1870]559   //ym obsolete : to be removed
[567]560   void CAxis::sendCheckedAttributes(const std::vector<int>& globalDim, int orderPositionInGrid,
561                                     CServerDistributionDescription::ServerDistributionType distType)
[1622]562   TRY
[567]563   {
[742]564     if (!this->areClientAttributesChecked_) checkAttributesOnClient();
[927]565     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation(globalDim, orderPositionInGrid, distType);
[595]566     CContext* context = CContext::getCurrent();
[567]567
568     if (this->isChecked) return;
[1870]569     if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) /*sendAttributes(globalDim, orderPositionInGrid, distType)*/;   
[567]570
571     this->isChecked = true;
572   }
[1622]573   CATCH_DUMP_ATTR
[567]574
[1870]575 
576   void CAxis::sendAxisToFileServer(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid)
577   {
578     if (sendAxisToFileServer_done_.count(client)!=0) return ;
579     else sendAxisToFileServer_done_.insert(client) ;
580     
581     StdString axisDefRoot("axis_definition");
582     CAxisGroup* axisPtr = CAxisGroup::get(axisDefRoot);
583     axisPtr->sendCreateChild(this->getId(),client);
584     this->sendAllAttributesToServer(client)  ; 
585     this->sendAttributes(client, globalDim, orderPositionInGrid, CServerDistributionDescription::BAND_DISTRIBUTION) ;
586   }
587
[1875]588   void CAxis::sendAxisToCouplerOut(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid, const string& fieldId, int posInGrid)
589   {
590     if (sendAxisToFileServer_done_.count(client)!=0) return ;
591     else sendAxisToFileServer_done_.insert(client) ;
592     
593     string axisId="_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ;
594
595     if (!axis_ref.isEmpty())
596    {
597      auto axis_ref_tmp=axis_ref.getValue() ;
598      axis_ref.reset() ; // remove the reference, find an other way to do that more cleanly
599      this->sendAllAttributesToServer(client, axisId)  ; 
600      axis_ref = axis_ref_tmp ;
601    }
602    else this->sendAllAttributesToServer(client, axisId)  ; 
603 
604    this->sendAttributes(client, globalDim, orderPositionInGrid, CServerDistributionDescription::BAND_DISTRIBUTION, axisId) ;
605   }
606
607  void CAxis::makeAliasForCoupling(const string& fieldId, int posInGrid)
608  {
609    const string axisId = "_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ;
610    this->createAlias(axisId) ;
611  }
612
[1144]613  /*!
614    Send attributes from one client to other clients
615    \param[in] globalDim global dimension of grid which contains this axis
616    \param[in] order
617  */
[1870]618  void CAxis::sendAttributes(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
[1875]619                             CServerDistributionDescription::ServerDistributionType distType, const string& axisId)
[1622]620  TRY
[633]621  {
[1875]622     sendDistributionAttribute(client, globalDim, orderPositionInGrid, distType, axisId);
[1235]623
624     // if (index.numElements() == n_glo.getValue())
625     if ((orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
626         || (index.numElements() != n_glo))
[1099]627     {
[1930]628       sendDistributedAttributes_old(client, axisId);       
[1099]629     }
[1235]630     else
631     {
[1875]632       sendNonDistributedAttributes(client, axisId);   
[1235]633     }     
[633]634  }
[1622]635  CATCH_DUMP_ATTR
[633]636
[1235]637  /*
638    Compute the connection between group of clients (or clients/servers).
639    (E.g: Suppose we have 2 group of clients in two model: A (client role) connect to B (server role),
640    this function calculate number of clients B connect to one client of A)
641     \param [in] globalDim global dimension of grid containing this axis
642     \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2)
643     \param [in] distType distribution type of the server. For now, we only have band distribution.
644  */
[1869]645  void CAxis::computeConnectedClients(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid)
[1622]646  TRY
[633]647  {
[1869]648    if (computeConnectedClients_done_.count(client)!=0) return ;
649    else computeConnectedClients_done_.insert(client) ;
650
[633]651    CContext* context = CContext::getCurrent();
[1869]652    CServerDistributionDescription::ServerDistributionType distType ;
653    int defaultDistributedPos = CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), CServerDistributionDescription::BAND_DISTRIBUTION) ;
654   
655    if (orderPositionInGrid == defaultDistributedPos) distType =  CServerDistributionDescription::BAND_DISTRIBUTION ;
656    else if (index.numElements() != n_glo) distType =  CServerDistributionDescription::ROOT_DISTRIBUTION ;
657    else return ;
[1099]658
[1869]659    int nbServer = client->serverSize;
660    int range, clientSize = client->clientSize;
661    int rank = client->clientRank;
[1236]662
[1869]663    if (listNbServer_.count(nbServer) == 0)
[667]664    {
[1869]665      listNbServer_.insert(nbServer) ;
[667]666
[1869]667      if (connectedServerRank_.find(nbServer) != connectedServerRank_.end())
[1346]668      {
[1869]669        nbSenders.erase(nbServer);
670        connectedServerRank_.erase(nbServer);
671      }
[1784]672
[1869]673      size_t ni = this->n.getValue();
674      size_t ibegin = this->begin.getValue();
675      size_t nbIndex = index.numElements();
[1099]676
[1869]677      // First of all, we should compute the mapping of the global index and local index of the current client
678      if (globalLocalIndexMap_.empty())
679      {
680        for (size_t idx = 0; idx < nbIndex; ++idx)
[1235]681        {
[1869]682          globalLocalIndexMap_[index(idx)] = idx;
[1235]683        }
[1869]684      }
[1235]685
[1869]686      // Calculate the compressed index if any
687      //        std::set<int> writtenInd;
688      //        if (isCompressible_)
689      //        {
690      //          for (int idx = 0; idx < data_index.numElements(); ++idx)
691      //          {
692      //            int ind = CDistributionClient::getAxisIndex(data_index(idx), data_begin, ni);
693      //
694      //            if (ind >= 0 && ind < ni && mask(ind))
695      //            {
696      //              ind += ibegin;
697      //              writtenInd.insert(ind);
698      //            }
699      //          }
700      //        }
[1099]701
[1869]702      // Compute the global index of the current client (process) hold
703      std::vector<int> nGlobAxis(1);
704      nGlobAxis[0] = n_glo.getValue();
[1235]705
[1869]706      size_t globalSizeIndex = 1, indexBegin, indexEnd;
707      for (int i = 0; i < nGlobAxis.size(); ++i) globalSizeIndex *= nGlobAxis[i];
708      indexBegin = 0;
709      if (globalSizeIndex <= clientSize)
710      {
711        indexBegin = rank%globalSizeIndex;
712        indexEnd = indexBegin;
713      }
714      else
715      {
716        for (int i = 0; i < clientSize; ++i)
[906]717        {
[1869]718          range = globalSizeIndex / clientSize;
719          if (i < (globalSizeIndex%clientSize)) ++range;
720          if (i == client->clientRank) break;
721          indexBegin += range;
[906]722        }
[1869]723        indexEnd = indexBegin + range - 1;
724      }
[815]725
[1869]726      CArray<size_t,1> globalIndex(index.numElements());
727      for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
728        globalIndex(idx) = index(idx);
[1235]729
[1869]730      // Describe the distribution of server side
[1258]731
[1869]732      CServerDistributionDescription serverDescription(nGlobAxis, nbServer, distType);
733   
734      std::vector<int> serverZeroIndex;
735      serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0);
[1235]736
[1869]737      std::list<int> serverZeroIndexLeader;
738      std::list<int> serverZeroIndexNotLeader; 
739      CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader);
740      for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
741        *it = serverZeroIndex[*it];
[1235]742
[1869]743      // Find out the connection between client and server side
744      CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm);
745      clientServerMap->computeServerIndexMapping(globalIndex, nbServer);
746      CClientServerMapping::GlobalIndexMap& globalIndexAxisOnServer = clientServerMap->getGlobalIndexOnServer();     
[1235]747
[1869]748      indSrv_[nbServer].swap(globalIndexAxisOnServer);
[1235]749
[1869]750      if (distType==CServerDistributionDescription::ROOT_DISTRIBUTION)
751      {
752        for(int i=1; i<nbServer; ++i) indSrv_[nbServer].insert(pair<int, vector<size_t> >(i,indSrv_[nbServer][0]) ) ;
753        serverZeroIndexLeader.clear() ;
754      }
755       
756      CClientServerMapping::GlobalIndexMap::const_iterator it  = indSrv_[nbServer].begin(),
757                                                           ite = indSrv_[nbServer].end();
[1025]758
[1869]759      for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first);
[1258]760
[1869]761      for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
762        connectedServerRank_[nbServer].push_back(*it);
[1235]763
[1869]764       // Even if a client has no index, it must connect to at least one server and
765       // send an "empty" data to this server
766       if (connectedServerRank_[nbServer].empty())
767        connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize);
[1235]768
[1869]769      nbSenders[nbServer] = CClientServerMapping::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]);
[1235]770
[1869]771      delete clientServerMap;
[633]772    }
773  }
[1622]774  CATCH_DUMP_ATTR
[633]775
[1235]776  /*
777    Compute the index of data to write into file
778    (Different from the previous version, this version of XIOS allows data be written into file (classical role),
779    or transfered to another clients)
780  */
781  void CAxis::computeWrittenIndex()
[1622]782  TRY
[1235]783  { 
784    if (computedWrittenIndex_) return;
785    computedWrittenIndex_ = true;
[633]786
[1235]787    CContext* context=CContext::getCurrent();     
[1129]788
[1235]789    // We describe the distribution of client (server) on which data are written
790    std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1);
[1561]791    nBegin[0]       = begin;
[1559]792    nSize[0]        = n;
[1235]793    nBeginGlobal[0] = 0; 
794    nGlob[0]        = n_glo;
[1853]795    CDistributionServer srvDist(context->intraCommSize_, nBegin, nSize, nBeginGlobal, nGlob); 
[1235]796    const CArray<size_t,1>& writtenGlobalIndex  = srvDist.getGlobalIndex();
[1129]797
[1235]798    // Because all written data are local on a client,
799    // we need to compute the local index on the server from its corresponding global index
800    size_t nbWritten = 0, indGlo;     
[1542]801    std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
[1235]802                                                        ite = globalLocalIndexMap_.end(), it;         
803    CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
804                                     itSrve = writtenGlobalIndex.end(), itSrv; 
[1143]805
[1559]806    localIndexToWriteOnServer.resize(writtenGlobalIndex.numElements());
807    nbWritten = 0;
808    for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
[1235]809    {
[1559]810      indGlo = *itSrv;
811      if (ite != globalLocalIndexMap_.find(indGlo))
[1129]812      {
[1559]813        localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[indGlo];
[1235]814      }
[1637]815      else
816      {
817        localIndexToWriteOnServer(nbWritten) = -1;
818      }
819      ++nbWritten;
[1235]820    }
[1637]821
[1249]822  }
[1622]823  CATCH_DUMP_ATTR
[1249]824
[1639]825  void CAxis::computeWrittenCompressedIndex(MPI_Comm writtenComm)
[1622]826  TRY
[1249]827  {
828    int writtenCommSize;
[1639]829    MPI_Comm_size(writtenComm, &writtenCommSize);
[1249]830    if (compressedIndexToWriteOnServer.find(writtenCommSize) != compressedIndexToWriteOnServer.end())
831      return;
832
[1235]833    if (isCompressible())
834    {
[1249]835      size_t nbWritten = 0, indGlo;
836      CContext* context=CContext::getCurrent();     
[1853]837 
[1249]838      // We describe the distribution of client (server) on which data are written
839      std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1);
[1559]840      nBegin[0]       = 0;
841      nSize[0]        = n;
[1249]842      nBeginGlobal[0] = 0; 
843      nGlob[0]        = n_glo;
[1853]844      CDistributionServer srvDist(context->intraCommSize_, nBegin, nSize, nBeginGlobal, nGlob); 
[1249]845      const CArray<size_t,1>& writtenGlobalIndex  = srvDist.getGlobalIndex();
[1542]846      std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
[1249]847                                                          ite = globalLocalIndexMap_.end(), it;   
848
849      CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
850                                       itSrve = writtenGlobalIndex.end(), itSrv;
[1542]851      std::unordered_map<size_t,size_t> localGlobalIndexMap;
[1235]852      for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
[1143]853      {
[1235]854        indGlo = *itSrv;
855        if (ite != globalLocalIndexMap_.find(indGlo))
[1143]856        {
[1235]857          localGlobalIndexMap[localIndexToWriteOnServer(nbWritten)] = indGlo;
858          ++nbWritten;
859        }                 
860      }
[1637]861//
862//      nbWritten = 0;
863//      for (int idx = 0; idx < data_index.numElements(); ++idx)
864//      {
865//        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
866//        {
867//          ++nbWritten;
868//        }
869//      }
870//
871//      compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten);
872//      nbWritten = 0;
873//      for (int idx = 0; idx < data_index.numElements(); ++idx)
874//      {
875//        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
876//        {
877//          compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)];
878//          ++nbWritten;
879//        }
880//      }
[1143]881
[1235]882      nbWritten = 0;
883      for (int idx = 0; idx < data_index.numElements(); ++idx)
884      {
885        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
[1143]886        {
[1235]887          ++nbWritten;
[1143]888        }
[1235]889      }
[1143]890
[1249]891      compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten);
[1235]892      nbWritten = 0;
893      for (int idx = 0; idx < data_index.numElements(); ++idx)
894      {
895        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
[1143]896        {
[1249]897          compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)];
[1235]898          ++nbWritten;
[1143]899        }
[1235]900      }
[1143]901
[1249]902      numberWrittenIndexes_[writtenCommSize] = nbWritten;
[1761]903
904      bool distributed_glo, distributed=isDistributed() ;
905      MPI_Allreduce(&distributed,&distributed_glo, 1, MPI_INT, MPI_LOR, writtenComm) ;
906      if (distributed_glo)
[1235]907      {
908             
[1639]909        MPI_Allreduce(&numberWrittenIndexes_[writtenCommSize], &totalNumberWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
910        MPI_Scan(&numberWrittenIndexes_[writtenCommSize], &offsetWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
[1249]911        offsetWrittenIndexes_[writtenCommSize] -= numberWrittenIndexes_[writtenCommSize];
[1143]912      }
[1235]913      else
[1249]914        totalNumberWrittenIndexes_[writtenCommSize] = numberWrittenIndexes_[writtenCommSize];
[1235]915    }
916  }
[1622]917  CATCH_DUMP_ATTR
[1143]918
[1235]919  /*!
920    Send distribution information from a group of client (client role) to another group of client (server role)
921    The distribution of a group of client (server role) is imposed by the group of client (client role)
922    \param [in] globalDim global dimension of grid containing this axis
923    \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2)
924    \param [in] distType distribution type of the server. For now, we only have band distribution.
925  */
[1870]926  void CAxis::sendDistributionAttribute(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
[1875]927                                        CServerDistributionDescription::ServerDistributionType distType, const string& axisId)
[1622]928  TRY
[1099]929  {
[1875]930    string serverAxisId = axisId.empty() ? this->getId() : axisId ; 
[1870]931    int nbServer = client->serverSize;
[1099]932
[1870]933    CServerDistributionDescription serverDescription(globalDim, nbServer);
934    serverDescription.computeServerDistribution();
[1099]935
[1870]936    std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
937    std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
[1099]938
[1870]939    CEventClient event(getType(),EVENT_ID_DISTRIBUTION_ATTRIBUTE);
940    if (client->isServerLeader())
941    {
942      std::list<CMessage> msgs;
943
944      const std::list<int>& ranks = client->getRanksServerLeader();
945      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
[1099]946      {
[1870]947        // Use const int to ensure CMessage holds a copy of the value instead of just a reference
948        const int begin = serverIndexBegin[*itRank][orderPositionInGrid];
949        const int ni    = serverDimensionSizes[*itRank][orderPositionInGrid];
[1099]950
[1870]951        msgs.push_back(CMessage());
952        CMessage& msg = msgs.back();
[1875]953        msg << serverAxisId;
[1870]954        msg << ni << begin;
955        msg << isCompressible_;                   
[1099]956
[1870]957        event.push(*itRank,1,msg);
[1099]958      }
[1870]959      client->sendEvent(event);
[1099]960    }
[1870]961    else client->sendEvent(event);
[1099]962  }
[1622]963  CATCH_DUMP_ATTR
[1099]964
[1235]965  /*
966    Receive distribution attribute from another client
967    \param [in] event event containing data of these attributes
968  */
969  void CAxis::recvDistributionAttribute(CEventServer& event)
[1622]970  TRY
[1235]971  {
972    CBufferIn* buffer = event.subEvents.begin()->buffer;
973    string axisId;
974    *buffer >> axisId;
975    get(axisId)->recvDistributionAttribute(*buffer);
976  }
[1622]977  CATCH
[1235]978
979  /*
980    Receive distribution attribute from another client
981    \param [in] buffer buffer containing data of these attributes
982  */
983  void CAxis::recvDistributionAttribute(CBufferIn& buffer)
[1622]984  TRY
[1235]985  {
[1566]986    int ni_srv, begin_srv;
987    buffer >> ni_srv >> begin_srv;
[1235]988    buffer >> isCompressible_;           
989
990    // Set up new local size of axis on the receiving clients
991    n.setValue(ni_srv);
992    begin.setValue(begin_srv);
993  }
[1622]994  CATCH_DUMP_ATTR
[1235]995
996  /*
997    Send attributes of axis from a group of client to other group of clients/servers
998    on supposing that these attributes are not distributed among the sending group
999    In the future, if new attributes are added, they should also be processed in this function
1000  */
[1875]1001  void CAxis::sendNonDistributedAttributes(CContextClient* client, const string& axisId)
[1622]1002  TRY
[1025]1003  {
[1875]1004    string serverAxisId = axisId.empty() ? this->getId() : axisId ; 
1005
[1870]1006    CEventClient event(getType(), EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES);
1007    size_t nbIndex = index.numElements();
1008    size_t nbDataIndex = 0;
[1099]1009
[1870]1010    for (int idx = 0; idx < data_index.numElements(); ++idx)
1011    {
1012      int ind = data_index(idx);
1013      if (ind >= 0 && ind < nbIndex) ++nbDataIndex;
1014    }
[633]1015
[1870]1016    CArray<int,1> dataIndex(nbDataIndex);
1017    nbDataIndex = 0;
1018    for (int idx = 0; idx < data_index.numElements(); ++idx)
1019    {
1020      int ind = data_index(idx);
1021      if (ind >= 0 && ind < nbIndex)
[676]1022      {
[1870]1023        dataIndex(nbDataIndex) = ind;
1024        ++nbDataIndex;
[1027]1025      }
[1870]1026    }
[676]1027
[1870]1028    if (client->isServerLeader())
1029    {
1030      std::list<CMessage> msgs;
[633]1031
[1870]1032      const std::list<int>& ranks = client->getRanksServerLeader();
1033      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
[633]1034      {
[1870]1035        msgs.push_back(CMessage());
1036        CMessage& msg = msgs.back();
[1875]1037        msg << serverAxisId;
[1870]1038        msg << index.getValue() << dataIndex << mask.getValue();
1039        msg << hasValue;
1040        if (hasValue) msg << value.getValue();
1041        msg << hasBounds;
1042        if (hasBounds) msg << bounds.getValue();
1043        msg << hasLabel;
1044        if (hasLabel) msg << label.getValue();
[1025]1045
[1870]1046        event.push(*itRank, 1, msg);
[633]1047      }
[1870]1048      client->sendEvent(event);
[633]1049    }
[1870]1050    else client->sendEvent(event);
[633]1051  }
[1622]1052  CATCH_DUMP_ATTR
[633]1053
[1235]1054  /*
1055    Receive the non-distributed attributes from another group of clients
1056    \param [in] event event containing data of these attributes
1057  */
[1025]1058  void CAxis::recvNonDistributedAttributes(CEventServer& event)
[1622]1059  TRY
[633]1060  {
[1025]1061    list<CEventServer::SSubEvent>::iterator it;
1062    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1063    {
1064      CBufferIn* buffer = it->buffer;
1065      string axisId;
1066      *buffer >> axisId;
1067      get(axisId)->recvNonDistributedAttributes(it->rank, *buffer);
1068    }
1069  }
[1622]1070  CATCH
[1025]1071
[1235]1072  /*
1073    Receive the non-distributed attributes from another group of clients
1074    \param [in] rank rank of the sender
1075    \param [in] buffer buffer containing data sent from the sender
1076  */
[1025]1077  void CAxis::recvNonDistributedAttributes(int rank, CBufferIn& buffer)
[1622]1078  TRY
[1025]1079  { 
[1559]1080    CArray<int,1> tmp_index, tmp_data_index;
[1025]1081    CArray<bool,1> tmp_mask;
1082    CArray<double,1> tmp_val;
1083    CArray<double,2> tmp_bnds;
[1235]1084    CArray<string,1> tmp_label;
[1025]1085
1086    buffer >> tmp_index;
1087    index.reference(tmp_index);
1088    buffer >> tmp_data_index;
1089    data_index.reference(tmp_data_index);
1090    buffer >> tmp_mask;
1091    mask.reference(tmp_mask);
[1129]1092
[1025]1093    buffer >> hasValue;
1094    if (hasValue)
1095    {
1096      buffer >> tmp_val;
1097      value.reference(tmp_val);
1098    }
1099
[1235]1100    buffer >> hasBounds;
1101    if (hasBounds)
[1025]1102    {
1103      buffer >> tmp_bnds;
1104      bounds.reference(tmp_bnds);
1105    }
1106
[1235]1107    buffer >> hasLabel;
1108    if (hasLabel)
1109    {
1110      buffer >> tmp_label;
1111      label.reference(tmp_label);
1112    }
1113
1114    // Some value should be reset here
[1129]1115    data_begin.setValue(0);
[1871]1116    data_n.setValue(data_index.numElements());
[1129]1117    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
[1416]1118//    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[idx] = index(idx);
1119    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[index(idx)] = idx;
[1025]1120  }
[1622]1121  CATCH_DUMP_ATTR
[1025]1122
[1235]1123  /*
[1637]1124    Send axis attributes from a group of clients to another group of clients/servers
1125    supposing that these attributes are distributed among the clients of the sending group
1126    In future, if new attributes are added, they should also be processed in this function
[1235]1127  */
[1930]1128  void CAxis::sendDistributedAttributes_old(CContextClient* client, const string& axisId)
[1622]1129  TRY
[1025]1130  {
[1875]1131    string serverAxisId = axisId.empty() ? this->getId() : axisId ; 
1132   
[1637]1133    int ind, idx;
[1870]1134    int nbServer = client->serverSize;
[1345]1135
[1870]1136    CEventClient eventData(getType(), EVENT_ID_DISTRIBUTED_ATTRIBUTES);
1137
1138    list<CMessage> listData;
1139    list<CArray<int,1> > list_indi, list_dataInd;
1140    list<CArray<double,1> > list_val;
1141    list<CArray<double,2> > list_bounds;
1142    list<CArray<string,1> > list_label;
1143
1144    // Cut off the ghost points
1145    int nbIndex = index.numElements();
1146    CArray<int,1> dataIndex(nbIndex);
1147    dataIndex = -1;
1148    for (idx = 0; idx < data_index.numElements(); ++idx)
[1025]1149    {
[1870]1150      if (0 <= data_index(idx) && data_index(idx) < nbIndex)
1151        dataIndex(data_index(idx)) = 1;
1152    }
[1025]1153
[1870]1154    std::unordered_map<int, std::vector<size_t> >::const_iterator it, iteMap;
1155    iteMap = indSrv_[nbServer].end();
1156    for (int k = 0; k < connectedServerRank_[nbServer].size(); ++k)
1157    {
1158      int nbData = 0, nbDataCount = 0;
1159      int rank = connectedServerRank_[nbServer][k];
1160      it = indSrv_[nbServer].find(rank);
1161      if (iteMap != it)
1162        nbData = it->second.size();
[633]1163
[1870]1164      list_indi.push_back(CArray<int,1>(nbData));
1165      list_dataInd.push_back(CArray<int,1>(nbData));
[633]1166
[1870]1167      if (hasValue)
1168        list_val.push_back(CArray<double,1>(nbData));
[633]1169
[1870]1170      if (hasBounds)       
1171        list_bounds.push_back(CArray<double,2>(2,nbData));
1172
1173      if (hasLabel)
1174        list_label.push_back(CArray<string,1>(nbData));
1175
1176      CArray<int,1>& indi = list_indi.back();
1177      CArray<int,1>& dataIndi = list_dataInd.back();
1178      dataIndi = -1;
1179
1180      for (int n = 0; n < nbData; ++n)
[633]1181      {
[1870]1182        idx = static_cast<int>(it->second[n]);
1183        indi(n) = idx;
[633]1184
[1870]1185        ind = globalLocalIndexMap_[idx];
1186        dataIndi(n) = dataIndex(ind);
[1025]1187
1188        if (hasValue)
[1870]1189        {
1190          CArray<double,1>& val = list_val.back();
1191          val(n) = value(ind);
1192        }
[1027]1193
[1870]1194        if (hasBounds)
1195        {
1196          CArray<double,2>& boundsVal = list_bounds.back();
1197          boundsVal(0, n) = bounds(0,ind);
1198          boundsVal(1, n) = bounds(1,ind);
1199        }
[1025]1200
[1235]1201        if (hasLabel)
[633]1202        {
[1870]1203          CArray<string,1>& labelVal = list_label.back();
1204          labelVal(n) = label(ind); 
[633]1205        }
[1870]1206      }
[1027]1207
[1870]1208      listData.push_back(CMessage());
[1875]1209      listData.back() << serverAxisId
[1870]1210                      << list_indi.back() << list_dataInd.back();
[1099]1211
[1870]1212      listData.back() << hasValue;
1213      if (hasValue)
1214        listData.back() << list_val.back();
[1099]1215
[1870]1216      listData.back() << hasBounds;
1217      if (hasBounds)
1218        listData.back() << list_bounds.back();
[1027]1219
[1870]1220      listData.back() << hasLabel;
1221      if (hasLabel)
1222        listData.back() << list_label.back();
[1235]1223
[1870]1224      eventData.push(rank, nbSenders[nbServer][rank], listData.back());
1225    }
[633]1226
[1870]1227    client->sendEvent(eventData);
[633]1228  }
[1622]1229  CATCH_DUMP_ATTR
[633]1230
[1235]1231  /*
1232    Receive the distributed attributes from another group of clients
1233    \param [in] event event containing data of these attributes
1234  */
[1930]1235  void CAxis::recvDistributedAttributes_old(CEventServer& event)
[1622]1236  TRY
[633]1237  {
[1025]1238    string axisId;
1239    vector<int> ranks;
1240    vector<CBufferIn*> buffers;
[676]1241
[633]1242    list<CEventServer::SSubEvent>::iterator it;
1243    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1244    {
[1025]1245      ranks.push_back(it->rank);
[633]1246      CBufferIn* buffer = it->buffer;
[676]1247      *buffer >> axisId;
[1025]1248      buffers.push_back(buffer);
[633]1249    }
[1930]1250    get(axisId)->recvDistributedAttributes_old(ranks, buffers);
[633]1251  }
[1622]1252  CATCH
[633]1253
[1235]1254  /*
1255    Receive the non-distributed attributes from another group of clients
1256    \param [in] ranks rank of the sender
1257    \param [in] buffers buffer containing data sent from the sender
1258  */
[1930]1259  void CAxis::recvDistributedAttributes_old(vector<int>& ranks, vector<CBufferIn*> buffers)
[1622]1260  TRY
[633]1261  {
[1235]1262    int nbReceived = ranks.size(), idx, ind, gloInd, locInd;
[1559]1263    vector<CArray<int,1> > vec_indi(nbReceived), vec_dataInd(nbReceived);
[1025]1264    vector<CArray<double,1> > vec_val(nbReceived);
1265    vector<CArray<double,2> > vec_bounds(nbReceived);
[1235]1266    vector<CArray<string,1> > vec_label(nbReceived);
[1025]1267   
[1235]1268    for (idx = 0; idx < nbReceived; ++idx)
[1025]1269    {     
1270      CBufferIn& buffer = *buffers[idx];
1271      buffer >> vec_indi[idx];
[1099]1272      buffer >> vec_dataInd[idx];     
[676]1273
[1025]1274      buffer >> hasValue;
1275      if (hasValue)
1276        buffer >> vec_val[idx];
[1099]1277
[1235]1278      buffer >> hasBounds;
1279      if (hasBounds)
[1025]1280        buffer >> vec_bounds[idx];
[1235]1281
1282      buffer >> hasLabel;
1283      if (hasLabel)
1284        buffer >> vec_label[idx]; 
[676]1285    }
[633]1286
[1235]1287    // Estimate size of index array
1288    int nbIndexGlob = 0;
1289    for (idx = 0; idx < nbReceived; ++idx)
[633]1290    {
[1235]1291      nbIndexGlob += vec_indi[idx].numElements();
[633]1292    }
[1129]1293
[1235]1294    // Recompute global index
1295    // Take account of the overlapped index
1296    index.resize(nbIndexGlob);
[1129]1297    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
[1235]1298    nbIndexGlob = 0;
[1566]1299    int nbIndLoc = 0;
[1235]1300    for (idx = 0; idx < nbReceived; ++idx)
1301    {
1302      CArray<int,1>& tmp = vec_indi[idx];
1303      for (ind = 0; ind < tmp.numElements(); ++ind)
1304      {
1305         gloInd = tmp(ind);
[1566]1306         nbIndLoc = (gloInd % n_glo)-begin;
[1235]1307         if (0 == globalLocalIndexMap_.count(gloInd))
1308         {
[1637]1309           index(nbIndexGlob) = gloInd % n_glo;
1310           globalLocalIndexMap_[gloInd] = nbIndexGlob;
[1235]1311           ++nbIndexGlob;
1312         } 
1313      } 
1314    }
1315
1316    // Resize index to its real size
[1301]1317    if (nbIndexGlob==0) index.resize(nbIndexGlob) ;
1318    else index.resizeAndPreserve(nbIndexGlob);
[1235]1319
1320    int nbData = nbIndexGlob;
1321    CArray<int,1> nonCompressedData(nbData);
1322    nonCompressedData = -1;   
[1637]1323    // Mask is incorporated into data_index and is not sent/received anymore
[1872]1324    mask.reset();
[1025]1325    if (hasValue)
1326      value.resize(nbData);
[1235]1327    if (hasBounds)
[1025]1328      bounds.resize(2,nbData);
[1235]1329    if (hasLabel)
1330      label.resize(nbData);
[633]1331
[1025]1332    nbData = 0;
[1235]1333    for (idx = 0; idx < nbReceived; ++idx)
[633]1334    {
[1025]1335      CArray<int,1>& indi = vec_indi[idx];
1336      CArray<int,1>& dataIndi = vec_dataInd[idx];
1337      int nb = indi.numElements();
1338      for (int n = 0; n < nb; ++n)
[1235]1339      { 
1340        locInd = globalLocalIndexMap_[size_t(indi(n))];
1341
1342        nonCompressedData(locInd) = (-1 == nonCompressedData(locInd)) ? dataIndi(n) : nonCompressedData(locInd);
1343
[1025]1344        if (hasValue)
[1235]1345          value(locInd) = vec_val[idx](n);
1346
1347        if (hasBounds)
[1025]1348        {
[1235]1349          bounds(0,locInd) = vec_bounds[idx](0,n);
1350          bounds(1,locInd) = vec_bounds[idx](1,n);
[1025]1351        }
[1235]1352
1353        if (hasLabel)
1354          label(locInd) = vec_label[idx](n);
[633]1355      }
1356    }
[1235]1357   
[1637]1358    int nbCompressedData = 0;
[1235]1359    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
[1025]1360    {
[1235]1361      if (0 <= nonCompressedData(idx))
[1637]1362        ++nbCompressedData;
[1025]1363    }
[676]1364
[1025]1365    data_index.resize(nbCompressedData);
1366    nbCompressedData = 0;
[1235]1367    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
[633]1368    {
[1235]1369      if (0 <= nonCompressedData(idx))
[1025]1370      {
[1235]1371        data_index(nbCompressedData) = idx % n;
[1637]1372        ++nbCompressedData;
[1025]1373      }
[633]1374    }
[1235]1375
[1129]1376    data_begin.setValue(0);
[1637]1377    data_n.setValue(data_index.numElements());
[633]1378  }
[1622]1379  CATCH_DUMP_ATTR
[633]1380
[1158]1381  /*!
1382    Compare two axis objects.
1383    They are equal if only if they have identical attributes as well as their values.
1384    Moreover, they must have the same transformations.
1385  \param [in] axis Compared axis
1386  \return result of the comparison
1387  */
1388  bool CAxis::isEqual(CAxis* obj)
[1622]1389  TRY
[1158]1390  {
1391    vector<StdString> excludedAttr;
1392    excludedAttr.push_back("axis_ref");
[987]1393
[1158]1394    bool objEqual = SuperClass::isEqual(obj, excludedAttr);   
1395    if (!objEqual) return objEqual;
1396
1397    TransMapTypes thisTrans = this->getAllTransformations();
1398    TransMapTypes objTrans  = obj->getAllTransformations();
1399
1400    TransMapTypes::const_iterator it, itb, ite;
1401    std::vector<ETranformationType> thisTransType, objTransType;
1402    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
1403      thisTransType.push_back(it->first);
1404    for (it = objTrans.begin(); it != objTrans.end(); ++it)
1405      objTransType.push_back(it->first);
1406
1407    if (thisTransType.size() != objTransType.size()) return false;
1408    for (int idx = 0; idx < thisTransType.size(); ++idx)
1409      objEqual &= (thisTransType[idx] == objTransType[idx]);
1410
1411    return objEqual;
1412  }
[1622]1413  CATCH_DUMP_ATTR
[1158]1414
[1235]1415  /*
1416    Add transformation into axis. This function only servers for Fortran interface
1417    \param [in] transType transformation type
1418    \param [in] id identifier of the transformation object
1419  */
[836]1420  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
[1622]1421  TRY
[836]1422  {
1423    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
1424    return transformationMap_.back().second;
1425  }
[1622]1426  CATCH_DUMP_ATTR
[836]1427
[1235]1428  /*
1429    Check whether an axis has (spatial) transformation
1430  */
[619]1431  bool CAxis::hasTransformation()
[1622]1432  TRY
[619]1433  {
[621]1434    return (!transformationMap_.empty());
[619]1435  }
[1622]1436  CATCH_DUMP_ATTR
[619]1437
[1235]1438  /*
1439    Set transformation
1440    \param [in] axisTrans transformation to set
1441  */
[621]1442  void CAxis::setTransformations(const TransMapTypes& axisTrans)
[1622]1443  TRY
[619]1444  {
[621]1445    transformationMap_ = axisTrans;
[619]1446  }
[1622]1447  CATCH_DUMP_ATTR
[619]1448
[1235]1449  /*
1450    Return all transformation held by the axis
1451    \return transformation the axis has
1452  */
[621]1453  CAxis::TransMapTypes CAxis::getAllTransformations(void)
[1622]1454  TRY
[620]1455  {
[621]1456    return transformationMap_;
1457  }
[1622]1458  CATCH_DUMP_ATTR
[620]1459
[1235]1460  /*
1461    Duplicate transformation of another axis
1462    \param [in] src axis whose transformations are copied
1463  */
[823]1464  void CAxis::duplicateTransformation(CAxis* src)
[1622]1465  TRY
[823]1466  {
1467    if (src->hasTransformation())
1468    {
1469      this->setTransformations(src->getAllTransformations());
1470    }
1471  }
[1622]1472  CATCH_DUMP_ATTR
[823]1473
[747]1474  /*!
1475   * Go through the hierarchy to find the axis from which the transformations must be inherited
1476   */
[619]1477  void CAxis::solveInheritanceTransformation()
[1622]1478  TRY
[619]1479  {
[747]1480    if (hasTransformation() || !hasDirectAxisReference())
1481      return;
[619]1482
[747]1483    CAxis* axis = this;
[619]1484    std::vector<CAxis*> refAxis;
[747]1485    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
[619]1486    {
[747]1487      refAxis.push_back(axis);
1488      axis = axis->getDirectAxisReference();
[619]1489    }
1490
[747]1491    if (axis->hasTransformation())
1492      for (size_t i = 0; i < refAxis.size(); ++i)
1493        refAxis[i]->setTransformations(axis->getAllTransformations());
[619]1494  }
[1622]1495  CATCH_DUMP_ATTR
[619]1496
[1345]1497  void CAxis::setContextClient(CContextClient* contextClient)
[1622]1498  TRY
[1345]1499  {
[1353]1500    if (clientsSet.find(contextClient)==clientsSet.end())
1501    {
1502      clients.push_back(contextClient) ;
1503      clientsSet.insert(contextClient);
1504    }
[1622]1505  }
1506  CATCH_DUMP_ATTR
[1345]1507
[619]1508  void CAxis::parse(xml::CXMLNode & node)
[1622]1509  TRY
[619]1510  {
1511    SuperClass::parse(node);
1512
1513    if (node.goToChildElement())
1514    {
[836]1515      StdString nodeElementName;
[619]1516      do
1517      {
[784]1518        StdString nodeId("");
1519        if (node.getAttributes().end() != node.getAttributes().find("id"))
1520        { nodeId = node.getAttributes()["id"]; }
1521
[836]1522        nodeElementName = node.getElementName();
1523        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
1524        it = transformationMapList_.find(nodeElementName);
1525        if (ite != it)
1526        {
1527          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second,
1528                                                                                                               nodeId,
1529                                                                                                               &node)));
[786]1530        }
[968]1531        else
1532        {
1533          ERROR("void CAxis::parse(xml::CXMLNode & node)",
1534                << "The transformation " << nodeElementName << " has not been supported yet.");
1535        }
[619]1536      } while (node.goToNextElement()) ;
1537      node.goToParentElement();
1538    }
1539  }
[1622]1540  CATCH_DUMP_ATTR
[619]1541
[1930]1542
1543   //////////////////////////////////////////////////////////////////////////////////////
1544   //  this part is related to distribution, element definition, views and connectors  //
1545   //////////////////////////////////////////////////////////////////////////////////////
1546
1547   void CAxis::initializeLocalElement(void)
1548   {
1549      // after checkAttribute index of size n
1550      int rank = CContext::getCurrent()->getIntraCommRank() ;
1551     
1552      CArray<size_t,1> ind(n) ;
1553      for (int i=0;i<n;i++) ind(i)=index(i) ;
1554
1555      localElement_ = new CLocalElement(rank, n_glo, ind) ;
1556   }
1557
1558   void CAxis::addFullView(void)
1559   {
1560      CArray<int,1> index(n) ;
1561      for(int i=0; i<n ; i++) index(i)=i ;
1562      localElement_ -> addView(CElementView::FULL, index) ;
1563   }
1564
1565   void CAxis::addWorkflowView(void)
1566   {
1567     // mask + data are included into data_index
1568     int nk=data_index.numElements() ;
1569     int nMask=0 ;
1570     for(int k=0;k<nk;k++) if (data_index(k)>=0 && data_index(k)<n) nMask++ ;
1571     
1572     CArray<int,1> index(nMask) ;
1573     nMask=0 ;
1574     for(int k=0;k<nk;k++) 
1575       if (data_index(k)>=0 && data_index(k)<n) 
1576       {
1577         index(nMask) = data_index(k) ;
1578         nMask++ ;
1579       }
1580     localElement_ -> addView(CElementView::WORKFLOW, index) ;
1581   }
1582
1583   void CAxis::addModelView(void)
1584   {
1585     // information for model view is stored in data_index
1586     localElement_->addView(CElementView::MODEL, data_index) ;
1587   }
1588
1589   void CAxis::computeModelToWorkflowConnector(void)
1590   { 
1591     CLocalView* srcView=getLocalView(CElementView::MODEL) ;
1592     CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ;
1593     modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 
1594     modelToWorkflowConnector_->computeConnector() ;
1595   }
1596
1597
1598   void CAxis::computeRemoteElement(CContextClient* client, EDistributionType type)
1599  {
1600    CContext* context = CContext::getCurrent();
1601    map<int, CArray<size_t,1>> globalIndex ;
1602
1603    if (type==EDistributionType::BANDS) // Bands distribution to send to file server
1604    {
1605      int nbServer = client->serverSize;
1606      int nbClient = client->clientSize ;
1607      int rankClient = client->clientRank ;
1608      int size = nbServer / nbClient ;
1609      int start ;
1610      if (nbServer%nbClient > rankClient)
1611      {
1612       start = (size+1) * rankClient ;
1613       size++ ;
1614      }
1615      else start = size*rankClient + nbServer%nbClient ;
1616     
1617      for(int i=0; i<size; i++)
1618      { 
1619        int rank=start+i ; 
1620        size_t indSize = n_glo/nbServer ;
1621        size_t indStart ;
1622        if (n_glo % nbServer > rank)
1623        {
1624          indStart = (indSize+1) * rank ;
1625          indSize++ ;
1626        }
1627        else indStart = indSize*rank + n_glo%nbServer ;
1628       
1629        auto& globalInd =  globalIndex[rank] ;
1630        globalInd.resize(indSize) ;
1631        for(size_t n = 0 ; n<indSize; n++) globalInd(n)=indStart+n ;
1632      }
1633    }
1634    else if (type==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain
1635    {
1636      int nbServer = client->serverSize;
1637      size_t nglo=n_glo ;
1638      CArray<size_t,1> indGlo(nglo) ;
1639      for(size_t i=0;i<nglo;i++) indGlo(i) = i ;
[1939]1640      for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()); 
[1930]1641    }
1642    remoteElement_[client] = new CDistributedElement(n_glo, globalIndex) ;
1643    remoteElement_[client]->addFullView() ;
1644  }
1645 
[1956]1646  void CAxis::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, 
1647                                 CScattererConnector* &scattererConnector, const string& axisId)
[1930]1648  {
1649    string serverAxisId = axisId.empty() ? this->getId() : axisId ;
1650    CContext* context = CContext::getCurrent();
1651
1652    this->sendAllAttributesToServer(client, serverAxisId)  ;
1653
1654    CDistributedElement scatteredElement(n_glo,globalIndex) ;
1655    scatteredElement.addFullView() ;
[1956]1656    scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 
1657                                                 context->getIntraComm(), client->getRemoteSize()) ;
1658    scattererConnector->computeConnector() ;
[1930]1659   
1660    // phase 0
1661    // send remote element to construct the full view on server, ie without hole
1662    CEventClient event0(getType(), EVENT_ID_AXIS_DISTRIBUTION);
1663    CMessage message0 ;
1664    message0<<serverAxisId<<0 ; 
1665    remoteElement_[client]->sendToServer(client,event0,message0) ; 
1666   
1667    // phase 1
1668    // send the full view of element to construct the connector which connect distributed data coming from client to the full local view
1669    CEventClient event1(getType(), EVENT_ID_AXIS_DISTRIBUTION);
1670    CMessage message1 ;
1671    message1<<serverAxisId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 
[1956]1672    scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
[1930]1673
[1956]1674    sendDistributedAttributes(client, *scattererConnector, axisId) ;
[1930]1675 
1676    // phase 2 send the mask : data index + mask2D
1677    CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize());
1678    CArray<bool,1> maskOut ;
1679    CLocalConnector workflowToFull(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ;
1680    workflowToFull.computeConnector() ;
1681    maskIn=true ;
1682    workflowToFull.transfer(maskIn,maskOut,false) ;
1683
1684    // phase 3 : prepare grid scatterer connector to send data from client to server
1685    map<int,CArray<size_t,1>> workflowGlobalIndex ;
1686    map<int,CArray<bool,1>> maskOut2 ; 
[1956]1687    scattererConnector->transfer(maskOut, maskOut2) ;
[1930]1688    scatteredElement.addView(CElementView::WORKFLOW, maskOut2) ;
1689    scatteredElement.getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ;
1690    // create new workflow view for scattered element
1691    CDistributedElement clientToServerElement(scatteredElement.getGlobalSize(), workflowGlobalIndex) ;
1692    clientToServerElement.addFullView() ;
1693    CEventClient event2(getType(), EVENT_ID_AXIS_DISTRIBUTION);
1694    CMessage message2 ;
1695    message2<<serverAxisId<<2 ; 
1696    clientToServerElement.sendToServer(client, event2, message2) ; 
[1943]1697    clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL), 
1698                                                              context->getIntraComm(), client->getRemoteSize()) ;
[1930]1699    clientToServerConnector_[client]->computeConnector() ;
1700
[1934]1701    clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
1702    clientFromServerConnector_[client]->computeConnector() ;
[1930]1703
1704
1705  }
1706
1707  void CAxis::recvAxisDistribution(CEventServer& event)
1708  TRY
1709  {
1710    string axisId;
1711    int phasis ;
1712    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> phasis ;
1713    get(axisId)->receivedAxisDistribution(event, phasis);
1714  }
1715  CATCH
1716
1717
1718  void CAxis::receivedAxisDistribution(CEventServer& event, int phasis)
1719  TRY
1720  {
1721    CContext* context = CContext::getCurrent();
1722    if (phasis==0) // receive the remote element to construct the full view
1723    {
1724      localElement_ = new  CLocalElement(context->getIntraCommRank(),event) ;
1725      localElement_->addFullView() ;
1726      // construct the local dimension and indexes
1727      auto& globalIndex=localElement_->getGlobalIndex() ;
1728      int nk=globalIndex.numElements() ;
1729      int minK=n_glo,maxK=-1 ;
1730      int nGlo=n_glo ;
1731      int indGlo ;
1732      for(int k=0;k<nk;k++)
1733      {
1734        indGlo=globalIndex(k) ;
1735        if (indGlo<minK) minK=indGlo ;
1736        if (indGlo>maxK) maxK=indGlo ;
1737      } 
1738      if (maxK>=minK) { begin=minK ; n=maxK-minK+1 ; }
1739      else {begin=0; n=0 ;}
1740
1741    }
1742    else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server
1743    {
1744      CContext* context = CContext::getCurrent();
1745      CDistributedElement* elementFrom = new  CDistributedElement(event) ;
1746      elementFrom->addFullView() ;
1747      gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
1748      gathererConnector_->computeConnector() ; 
1749    }
1750    else if (phasis==2)
1751    {
[1956]1752//      delete gathererConnector_ ;
[1930]1753      elementFrom_ = new  CDistributedElement(event) ;
1754      elementFrom_->addFullView() ;
[1956]1755//      gathererConnector_ =  new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
1756//      gathererConnector_ -> computeConnector() ;
[1930]1757    }
[1943]1758 
[1930]1759  }
1760  CATCH
1761
[1943]1762  void CAxis::setServerMask(CArray<bool,1>& serverMask, CContextClient* client)
1763  TRY
1764  {
1765    CContext* context = CContext::getCurrent();
1766    localElement_->addView(CElementView::WORKFLOW, serverMask) ;
1767    mask.reference(serverMask.copy()) ;
1768 
1769    serverFromClientConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ;
1770    serverFromClientConnector_->computeConnector() ;
1771     
1772    serverToClientConnector_ = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL),
1773                                                         context->getIntraComm(), client->getRemoteSize()) ;
1774    serverToClientConnector_->computeConnector() ;
1775  }
1776  CATCH_DUMP_ATTR
1777
[1930]1778  void CAxis::sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& axisId)
1779  {
1780    string serverAxisId = axisId.empty() ? this->getId() : axisId ;
1781    CContext* context = CContext::getCurrent();
1782
1783    if (hasValue)
1784    {
1785      { // send level value
1786        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
1787        CMessage message ;
1788        message<<serverAxisId<<string("value") ; 
1789        scattererConnector.transfer(value, client, event,message) ;
1790      }
1791    }
1792
1793    if (hasBounds)
1794    {
1795      { // send bounds level value
1796        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
1797        CMessage message ;
1798        message<<serverAxisId<<string("bounds") ; 
1799        scattererConnector.transfer(2, bounds, client, event,message) ;
1800      }
1801    }
1802
1803    if (hasLabel)
1804    {
1805      { // send label
[1950]1806        // need to transform array of string (no fixed size for string) into array of array of char
1807        // to use connector to transfer
1808        // the strings must have fixed size which the maximum lenght over the string label. 
1809        int maxSize=0 ;
1810        for(int i=0; i<label.numElements();i++) 
1811          if (maxSize < label(i).size()) maxSize=label(i).size() ;
1812        MPI_Allreduce(MPI_IN_PLACE, &maxSize,1,MPI_INT,MPI_MAX, context->getIntraComm()) ;
1813        maxSize=maxSize+1 ;
1814        CArray<char,2> charArray(maxSize,label.numElements()) ;
1815        for(int j=0; j<label.numElements();j++) 
1816        {
1817          const char* str = label(j).c_str() ;
1818          int strSize=label(j).size()+1 ;
1819          for(int i=0; i<strSize; i++) charArray(i,j) = str[i] ;
1820        }
[1930]1821        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
1822        CMessage message ;
[1950]1823        message<<serverAxisId<<string("label")<<maxSize ;
1824        scattererConnector.transfer(maxSize, charArray, client, event,message) ;
[1930]1825      }
1826    }
1827  }
1828
1829  void CAxis::recvDistributedAttributes(CEventServer& event)
1830  TRY
1831  {
1832    string axisId;
1833    string type ;
1834    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> type ;
1835    get(axisId)->recvDistributedAttributes(event, type);
1836  }
1837  CATCH
1838
1839  void CAxis::recvDistributedAttributes(CEventServer& event, const string& type)
1840  TRY
1841  {
1842    if (type=="value") 
1843    {
1844      gathererConnector_->transfer(event, value, 0.); 
1845    }
1846    else if (type=="bounds")
1847    {
1848      CArray<double,1> value ;
1849      gathererConnector_->transfer(event, 2, value, 0.); 
1850      bounds.resize(2,n) ;
[1950]1851      if (bounds.numElements() > 0 ) bounds=CArray<double,2>(value.dataFirst(),shape(2,n),neverDeleteData) ; 
[1930]1852    }
1853    else if (type=="label")
1854    {
[1950]1855      int maxSize ;
1856      for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> maxSize ;
1857      CArray<char,1> value ;
1858      gathererConnector_->transfer(event, maxSize, value, '\0'); 
1859      CArray<char,2> charArray(maxSize,n) ;
1860      label.resize(n) ;
1861      if (n>0)
1862      {
1863        charArray=CArray<char,2>(value.dataFirst(),shape(maxSize,n),neverDeleteData) ;
1864        for(int j=0;j<n;j++)
1865        {
1866          int strSize ;
1867          for(int i=0;i<maxSize;i++) 
1868            if (charArray(i,j)=='\0') { strSize=i ; break; }
1869          string str(strSize,'\0') ;
1870          for(int i=0;i<strSize;i++) str[i]=charArray(i,j) ; 
1871          label(j)=str ;
1872        }
1873      } 
[1930]1874    }
1875  }
1876  CATCH
1877
[620]1878  DEFINE_REF_FUNC(Axis,axis)
[619]1879
[219]1880   ///---------------------------------------------------------------
1881
[335]1882} // namespace xios
Note: See TracBrowser for help on using the repository browser.