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

Last change on this file since 1960 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
Line 
1#include "axis.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6#include "message.hpp"
7#include "type.hpp"
8#include "context.hpp"
9#include "context_client.hpp"
10#include "context_server.hpp"
11#include "xios_spl.hpp"
12#include "server_distribution_description.hpp"
13#include "client_server_mapping_distributed.hpp"
14#include "distribution_client.hpp"
15
16namespace xios {
17
18   /// ////////////////////// Definitions ////////////////////// ///
19
20   CAxis::CAxis(void)
21      : CObjectTemplate<CAxis>()
22      , CAxisAttributes(), isChecked(false), relFiles(), areClientAttributesChecked_(false)
23      , isClientAfterTransformationChecked(false)
24      , hasBounds(false), isCompressible_(false)
25      , numberWrittenIndexes_(), totalNumberWrittenIndexes_(), offsetWrittenIndexes_()
26      , transformationMap_(), hasValue(false), hasLabel(false)
27      , computedWrittenIndex_(false)
28          , clients()
29   {
30   }
31
32   CAxis::CAxis(const StdString & id)
33      : CObjectTemplate<CAxis>(id)
34      , CAxisAttributes(), isChecked(false), relFiles(), areClientAttributesChecked_(false)
35      , isClientAfterTransformationChecked(false)
36      , hasBounds(false), isCompressible_(false)
37      , numberWrittenIndexes_(), totalNumberWrittenIndexes_(), offsetWrittenIndexes_()
38      , transformationMap_(), hasValue(false), hasLabel(false)
39      , computedWrittenIndex_(false)
40          , clients()
41   {
42   }
43
44   CAxis::~CAxis(void)
45   { /* Ne rien faire de plus */ }
46
47   std::map<StdString, ETranformationType> CAxis::transformationMapList_ = std::map<StdString, ETranformationType>();
48   bool CAxis::dummyTransformationMapList_ = CAxis::initializeTransformationMap(CAxis::transformationMapList_);
49   bool CAxis::initializeTransformationMap(std::map<StdString, ETranformationType>& m)
50   TRY
51   {
52     m["zoom_axis"] = TRANS_ZOOM_AXIS;
53     m["interpolate_axis"] = TRANS_INTERPOLATE_AXIS;
54     m["extract_axis"] = TRANS_EXTRACT_AXIS;
55     m["inverse_axis"] = TRANS_INVERSE_AXIS;
56     m["reduce_domain"] = TRANS_REDUCE_DOMAIN_TO_AXIS;
57     m["reduce_axis"] = TRANS_REDUCE_AXIS_TO_AXIS;
58     m["extract_domain"] = TRANS_EXTRACT_DOMAIN_TO_AXIS;
59     m["temporal_splitting"] = TRANS_TEMPORAL_SPLITTING;
60     m["duplicate_scalar"] = TRANS_DUPLICATE_SCALAR_TO_AXIS;
61
62   }
63   CATCH
64
65   ///---------------------------------------------------------------
66
67   const std::set<StdString> & CAxis::getRelFiles(void) const
68   TRY
69   {
70      return (this->relFiles);
71   }
72   CATCH
73
74   bool CAxis::IsWritten(const StdString & filename) const
75   TRY
76   {
77      return (this->relFiles.find(filename) != this->relFiles.end());
78   }
79   CATCH
80
81   bool CAxis::isWrittenCompressed(const StdString& filename) const
82   TRY
83   {
84      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
85   }
86   CATCH
87
88   bool CAxis::isDistributed(void) const
89   TRY
90   {
91      bool distributed = (!this->begin.isEmpty() && !this->n.isEmpty() && (this->begin + this->n < this->n_glo)) ||
92             (!this->n.isEmpty() && (this->n != this->n_glo));
93      // A condition to make sure that if there is only one client, axis
94      // should be considered to be distributed. This should be a temporary solution     
95      distributed |= (1 == CContext::getCurrent()->intraCommSize_);
96      return distributed;
97   }
98   CATCH
99
100   /*!
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.
105    */
106   void CAxis::computeIsCompressible(void)
107   TRY
108   {
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 ;
116   }
117   CATCH
118
119   void CAxis::addRelFile(const StdString & filename)
120   TRY
121   {
122      this->relFiles.insert(filename);
123   }
124   CATCH_DUMP_ATTR
125
126   void CAxis::addRelFileCompressed(const StdString& filename)
127   TRY
128   {
129      this->relFilesCompressed.insert(filename);
130   }
131   CATCH_DUMP_ATTR
132
133   //----------------------------------------------------------------
134
135   /*!
136     Returns the number of indexes written by each server.
137     \return the number of indexes written by each server
138   */
139   int CAxis::getNumberWrittenIndexes(MPI_Comm writtenCom)
140   TRY
141   {
142     int writtenSize;
143     MPI_Comm_size(writtenCom, &writtenSize);
144     return numberWrittenIndexes_[writtenSize];
145   }
146   CATCH_DUMP_ATTR
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   */
152   int CAxis::getTotalNumberWrittenIndexes(MPI_Comm writtenCom)
153   TRY
154   {
155     int writtenSize;
156     MPI_Comm_size(writtenCom, &writtenSize);
157     return totalNumberWrittenIndexes_[writtenSize];
158   }
159   CATCH_DUMP_ATTR
160
161   /*!
162     Returns the offset of indexes written by each server.
163     \return the offset of indexes written by each server
164   */
165   int CAxis::getOffsetWrittenIndexes(MPI_Comm writtenCom)
166   TRY
167   {
168     int writtenSize;
169     MPI_Comm_size(writtenCom, &writtenSize);
170     return offsetWrittenIndexes_[writtenSize];
171   }
172   CATCH_DUMP_ATTR
173
174   CArray<int, 1>& CAxis::getCompressedIndexToWriteOnServer(MPI_Comm writtenCom)
175   TRY
176   {
177     int writtenSize;
178     MPI_Comm_size(writtenCom, &writtenSize);
179     return compressedIndexToWriteOnServer[writtenSize];
180   }
181   CATCH_DUMP_ATTR
182
183   //----------------------------------------------------------------
184
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    */
190   std::map<int, StdSize> CAxis::getAttributesBufferSize(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
191                                                         CServerDistributionDescription::ServerDistributionType distType)
192   TRY
193   {
194
195     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client);
196
197//     bool isNonDistributed = (n_glo == n);
198     bool isDistributed = (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
199                                 || (index.numElements() != n_glo);
200
201     if (client->isServerLeader())
202     {
203       // size estimation for sendServerAttribut
204       size_t size = 6 * sizeof(size_t);
205       // size estimation for sendNonDistributedValue
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       }
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       }
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
233     }
234
235     if (isDistributed)
236     {
237       // size estimation for sendDistributedValue
238       std::unordered_map<int, vector<size_t> >::const_iterator it, ite = indSrv_[client->serverSize].end();
239       for (it = indSrv_[client->serverSize].begin(); it != ite; ++it)
240       {
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());
246         if (hasBounds)
247           size += CArray<double,2>::size(2 * it->second.size());
248         if (hasLabel)
249           size += CArray<StdString,1>::size(it->second.size());
250
251         size += CEventClient::headerSize + getId().size() + sizeof(size_t);
252         if (size > attributesSizes[it->first])
253           attributesSizes[it->first] = size;
254       }
255     }
256     return attributesSizes;
257   }
258   CATCH_DUMP_ATTR
259
260   //----------------------------------------------------------------
261
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
268   CAxis* CAxis::createAxis()
269   TRY
270   {
271     CAxis* axis = CAxisGroup::get("axis_definition")->createChild();
272     return axis;
273   }
274   CATCH
275
276   /*!
277     Check common attributes of an axis.
278     This check should be done in the very beginning of work flow
279   */
280   void CAxis::checkAttributes(void)
281   TRY
282   {
283     if (checkAttributes_done_) return ;
284
285     CContext* context=CContext::getCurrent();
286
287     if (this->n_glo.isEmpty())
288        ERROR("CAxis::checkAttributes(void)",
289              << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
290              << "The axis is wrongly defined, attribute 'n_glo' must be specified");
291      StdSize size = this->n_glo.getValue();
292
293      if (!this->index.isEmpty())
294      {
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);         
300      }
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);
311
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        }
325      }
326
327      if (!this->value.isEmpty())
328      {
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() << ").");
335        this->hasValue = true;
336      }
337
338      this->checkBounds();
339      this->checkMask();
340      this->checkData();
341      this->checkLabel();
342      initializeLocalElement() ;
343      addFullView() ;
344      addWorkflowView() ;
345      addModelView() ;
346
347      checkAttributes_done_ = true ;
348   }
349   CATCH_DUMP_ATTR
350
351
352
353   /*!
354      Check the validity of data, fill in values if any, and apply mask.
355   */
356   void CAxis::checkData()
357   TRY
358   {
359      if (data_begin.isEmpty()) data_begin.setValue(0);
360
361      if (data_n.isEmpty())
362      {
363        data_n.setValue(n);
364      }
365      else if (data_n.getValue() < 0)
366      {
367        ERROR("CAxis::checkData(void)",
368              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
369              << "The data size should be strictly positive ('data_n' = " << data_n.getValue() << ").");
370      }
371
372      if (data_index.isEmpty())
373      {
374        data_index.resize(data_n);
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        }
387      }
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        {
398           if (data_index(i) >= 0 && data_index(i)<n)
399             if (!mask(data_index(i))) data_index(i) = -1;
400        }
401      }
402
403   }
404   CATCH_DUMP_ATTR
405
406    size_t CAxis::getGlobalWrittenSize(void)
407    {
408      return n_glo ;
409    }
410
411   /*!
412     Check validity of mask info and fill in values if any.
413   */
414   void CAxis::checkMask()
415   TRY
416   {
417      if (!mask.isEmpty())
418      {
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        }
427      }
428      else
429      {
430        mask.resize(n);
431        mask = true;
432      }
433   }
434   CATCH_DUMP_ATTR
435
436   /*!
437     Check validity of bounds info and fill in values if any.
438   */
439   void CAxis::checkBounds()
440   TRY
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) << ".");
449       hasBounds = true;
450     }
451     else hasBounds = false;
452   }
453   CATCH_DUMP_ATTR
454
455  void CAxis::checkLabel()
456  TRY
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  }
469  CATCH_DUMP_ATTR
470
471 
472  /*!
473    Dispatch event from the lower communication layer then process event according to its type
474  */
475  bool CAxis::dispatchEvent(CEventServer& event)
476  TRY
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);
485            return true;
486            break;
487         case EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES:
488           recvNonDistributedAttributes(event);
489           return true;
490           break;
491         case EVENT_ID_DISTRIBUTED_ATTRIBUTES:
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:
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  }
510  CATCH
511
512   /*!
513     Check attributes on client side (This name is still adequate???)
514   */
515   void CAxis::checkAttributesOnClient()
516   TRY
517   {
518     if (this->areClientAttributesChecked_) return;
519
520     CContext* context=CContext::getCurrent();
521     if (context->getServiceType()==CServicesManager::CLIENT) this->checkAttributes();
522
523     this->areClientAttributesChecked_ = true;
524   }
525   CATCH_DUMP_ATTR
526
527   /*
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.
530   */
531   // ym : obsolete to be removed
532   void CAxis::checkAttributesOnClientAfterTransformation(const std::vector<int>& globalDim, int orderPositionInGrid,
533                                                          CServerDistributionDescription::ServerDistributionType distType)
534   TRY
535   {
536     CContext* context=CContext::getCurrent() ;
537
538     if (this->isClientAfterTransformationChecked) return;
539     if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER)
540     {       
541       /* suppressed because of interface changed
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);
545       */
546     }
547
548     this->isClientAfterTransformationChecked = true;
549   }
550   CATCH_DUMP_ATTR
551
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   */
559   //ym obsolete : to be removed
560   void CAxis::sendCheckedAttributes(const std::vector<int>& globalDim, int orderPositionInGrid,
561                                     CServerDistributionDescription::ServerDistributionType distType)
562   TRY
563   {
564     if (!this->areClientAttributesChecked_) checkAttributesOnClient();
565     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation(globalDim, orderPositionInGrid, distType);
566     CContext* context = CContext::getCurrent();
567
568     if (this->isChecked) return;
569     if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) /*sendAttributes(globalDim, orderPositionInGrid, distType)*/;   
570
571     this->isChecked = true;
572   }
573   CATCH_DUMP_ATTR
574
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
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
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  */
618  void CAxis::sendAttributes(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
619                             CServerDistributionDescription::ServerDistributionType distType, const string& axisId)
620  TRY
621  {
622     sendDistributionAttribute(client, globalDim, orderPositionInGrid, distType, axisId);
623
624     // if (index.numElements() == n_glo.getValue())
625     if ((orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
626         || (index.numElements() != n_glo))
627     {
628       sendDistributedAttributes_old(client, axisId);       
629     }
630     else
631     {
632       sendNonDistributedAttributes(client, axisId);   
633     }     
634  }
635  CATCH_DUMP_ATTR
636
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  */
645  void CAxis::computeConnectedClients(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid)
646  TRY
647  {
648    if (computeConnectedClients_done_.count(client)!=0) return ;
649    else computeConnectedClients_done_.insert(client) ;
650
651    CContext* context = CContext::getCurrent();
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 ;
658
659    int nbServer = client->serverSize;
660    int range, clientSize = client->clientSize;
661    int rank = client->clientRank;
662
663    if (listNbServer_.count(nbServer) == 0)
664    {
665      listNbServer_.insert(nbServer) ;
666
667      if (connectedServerRank_.find(nbServer) != connectedServerRank_.end())
668      {
669        nbSenders.erase(nbServer);
670        connectedServerRank_.erase(nbServer);
671      }
672
673      size_t ni = this->n.getValue();
674      size_t ibegin = this->begin.getValue();
675      size_t nbIndex = index.numElements();
676
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)
681        {
682          globalLocalIndexMap_[index(idx)] = idx;
683        }
684      }
685
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      //        }
701
702      // Compute the global index of the current client (process) hold
703      std::vector<int> nGlobAxis(1);
704      nGlobAxis[0] = n_glo.getValue();
705
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)
717        {
718          range = globalSizeIndex / clientSize;
719          if (i < (globalSizeIndex%clientSize)) ++range;
720          if (i == client->clientRank) break;
721          indexBegin += range;
722        }
723        indexEnd = indexBegin + range - 1;
724      }
725
726      CArray<size_t,1> globalIndex(index.numElements());
727      for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
728        globalIndex(idx) = index(idx);
729
730      // Describe the distribution of server side
731
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);
736
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];
742
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();     
747
748      indSrv_[nbServer].swap(globalIndexAxisOnServer);
749
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();
758
759      for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first);
760
761      for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
762        connectedServerRank_[nbServer].push_back(*it);
763
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);
768
769      nbSenders[nbServer] = CClientServerMapping::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]);
770
771      delete clientServerMap;
772    }
773  }
774  CATCH_DUMP_ATTR
775
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()
782  TRY
783  { 
784    if (computedWrittenIndex_) return;
785    computedWrittenIndex_ = true;
786
787    CContext* context=CContext::getCurrent();     
788
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);
791    nBegin[0]       = begin;
792    nSize[0]        = n;
793    nBeginGlobal[0] = 0; 
794    nGlob[0]        = n_glo;
795    CDistributionServer srvDist(context->intraCommSize_, nBegin, nSize, nBeginGlobal, nGlob); 
796    const CArray<size_t,1>& writtenGlobalIndex  = srvDist.getGlobalIndex();
797
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;     
801    std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
802                                                        ite = globalLocalIndexMap_.end(), it;         
803    CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
804                                     itSrve = writtenGlobalIndex.end(), itSrv; 
805
806    localIndexToWriteOnServer.resize(writtenGlobalIndex.numElements());
807    nbWritten = 0;
808    for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
809    {
810      indGlo = *itSrv;
811      if (ite != globalLocalIndexMap_.find(indGlo))
812      {
813        localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[indGlo];
814      }
815      else
816      {
817        localIndexToWriteOnServer(nbWritten) = -1;
818      }
819      ++nbWritten;
820    }
821
822  }
823  CATCH_DUMP_ATTR
824
825  void CAxis::computeWrittenCompressedIndex(MPI_Comm writtenComm)
826  TRY
827  {
828    int writtenCommSize;
829    MPI_Comm_size(writtenComm, &writtenCommSize);
830    if (compressedIndexToWriteOnServer.find(writtenCommSize) != compressedIndexToWriteOnServer.end())
831      return;
832
833    if (isCompressible())
834    {
835      size_t nbWritten = 0, indGlo;
836      CContext* context=CContext::getCurrent();     
837 
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);
840      nBegin[0]       = 0;
841      nSize[0]        = n;
842      nBeginGlobal[0] = 0; 
843      nGlob[0]        = n_glo;
844      CDistributionServer srvDist(context->intraCommSize_, nBegin, nSize, nBeginGlobal, nGlob); 
845      const CArray<size_t,1>& writtenGlobalIndex  = srvDist.getGlobalIndex();
846      std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
847                                                          ite = globalLocalIndexMap_.end(), it;   
848
849      CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
850                                       itSrve = writtenGlobalIndex.end(), itSrv;
851      std::unordered_map<size_t,size_t> localGlobalIndexMap;
852      for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
853      {
854        indGlo = *itSrv;
855        if (ite != globalLocalIndexMap_.find(indGlo))
856        {
857          localGlobalIndexMap[localIndexToWriteOnServer(nbWritten)] = indGlo;
858          ++nbWritten;
859        }                 
860      }
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//      }
881
882      nbWritten = 0;
883      for (int idx = 0; idx < data_index.numElements(); ++idx)
884      {
885        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
886        {
887          ++nbWritten;
888        }
889      }
890
891      compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten);
892      nbWritten = 0;
893      for (int idx = 0; idx < data_index.numElements(); ++idx)
894      {
895        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
896        {
897          compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)];
898          ++nbWritten;
899        }
900      }
901
902      numberWrittenIndexes_[writtenCommSize] = nbWritten;
903
904      bool distributed_glo, distributed=isDistributed() ;
905      MPI_Allreduce(&distributed,&distributed_glo, 1, MPI_INT, MPI_LOR, writtenComm) ;
906      if (distributed_glo)
907      {
908             
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);
911        offsetWrittenIndexes_[writtenCommSize] -= numberWrittenIndexes_[writtenCommSize];
912      }
913      else
914        totalNumberWrittenIndexes_[writtenCommSize] = numberWrittenIndexes_[writtenCommSize];
915    }
916  }
917  CATCH_DUMP_ATTR
918
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  */
926  void CAxis::sendDistributionAttribute(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
927                                        CServerDistributionDescription::ServerDistributionType distType, const string& axisId)
928  TRY
929  {
930    string serverAxisId = axisId.empty() ? this->getId() : axisId ; 
931    int nbServer = client->serverSize;
932
933    CServerDistributionDescription serverDescription(globalDim, nbServer);
934    serverDescription.computeServerDistribution();
935
936    std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
937    std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
938
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)
946      {
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];
950
951        msgs.push_back(CMessage());
952        CMessage& msg = msgs.back();
953        msg << serverAxisId;
954        msg << ni << begin;
955        msg << isCompressible_;                   
956
957        event.push(*itRank,1,msg);
958      }
959      client->sendEvent(event);
960    }
961    else client->sendEvent(event);
962  }
963  CATCH_DUMP_ATTR
964
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)
970  TRY
971  {
972    CBufferIn* buffer = event.subEvents.begin()->buffer;
973    string axisId;
974    *buffer >> axisId;
975    get(axisId)->recvDistributionAttribute(*buffer);
976  }
977  CATCH
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)
984  TRY
985  {
986    int ni_srv, begin_srv;
987    buffer >> ni_srv >> begin_srv;
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  }
994  CATCH_DUMP_ATTR
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  */
1001  void CAxis::sendNonDistributedAttributes(CContextClient* client, const string& axisId)
1002  TRY
1003  {
1004    string serverAxisId = axisId.empty() ? this->getId() : axisId ; 
1005
1006    CEventClient event(getType(), EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES);
1007    size_t nbIndex = index.numElements();
1008    size_t nbDataIndex = 0;
1009
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    }
1015
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)
1022      {
1023        dataIndex(nbDataIndex) = ind;
1024        ++nbDataIndex;
1025      }
1026    }
1027
1028    if (client->isServerLeader())
1029    {
1030      std::list<CMessage> msgs;
1031
1032      const std::list<int>& ranks = client->getRanksServerLeader();
1033      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1034      {
1035        msgs.push_back(CMessage());
1036        CMessage& msg = msgs.back();
1037        msg << serverAxisId;
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();
1045
1046        event.push(*itRank, 1, msg);
1047      }
1048      client->sendEvent(event);
1049    }
1050    else client->sendEvent(event);
1051  }
1052  CATCH_DUMP_ATTR
1053
1054  /*
1055    Receive the non-distributed attributes from another group of clients
1056    \param [in] event event containing data of these attributes
1057  */
1058  void CAxis::recvNonDistributedAttributes(CEventServer& event)
1059  TRY
1060  {
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  }
1070  CATCH
1071
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  */
1077  void CAxis::recvNonDistributedAttributes(int rank, CBufferIn& buffer)
1078  TRY
1079  { 
1080    CArray<int,1> tmp_index, tmp_data_index;
1081    CArray<bool,1> tmp_mask;
1082    CArray<double,1> tmp_val;
1083    CArray<double,2> tmp_bnds;
1084    CArray<string,1> tmp_label;
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);
1092
1093    buffer >> hasValue;
1094    if (hasValue)
1095    {
1096      buffer >> tmp_val;
1097      value.reference(tmp_val);
1098    }
1099
1100    buffer >> hasBounds;
1101    if (hasBounds)
1102    {
1103      buffer >> tmp_bnds;
1104      bounds.reference(tmp_bnds);
1105    }
1106
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
1115    data_begin.setValue(0);
1116    data_n.setValue(data_index.numElements());
1117    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
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;
1120  }
1121  CATCH_DUMP_ATTR
1122
1123  /*
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
1127  */
1128  void CAxis::sendDistributedAttributes_old(CContextClient* client, const string& axisId)
1129  TRY
1130  {
1131    string serverAxisId = axisId.empty() ? this->getId() : axisId ; 
1132   
1133    int ind, idx;
1134    int nbServer = client->serverSize;
1135
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)
1149    {
1150      if (0 <= data_index(idx) && data_index(idx) < nbIndex)
1151        dataIndex(data_index(idx)) = 1;
1152    }
1153
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();
1163
1164      list_indi.push_back(CArray<int,1>(nbData));
1165      list_dataInd.push_back(CArray<int,1>(nbData));
1166
1167      if (hasValue)
1168        list_val.push_back(CArray<double,1>(nbData));
1169
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)
1181      {
1182        idx = static_cast<int>(it->second[n]);
1183        indi(n) = idx;
1184
1185        ind = globalLocalIndexMap_[idx];
1186        dataIndi(n) = dataIndex(ind);
1187
1188        if (hasValue)
1189        {
1190          CArray<double,1>& val = list_val.back();
1191          val(n) = value(ind);
1192        }
1193
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        }
1200
1201        if (hasLabel)
1202        {
1203          CArray<string,1>& labelVal = list_label.back();
1204          labelVal(n) = label(ind); 
1205        }
1206      }
1207
1208      listData.push_back(CMessage());
1209      listData.back() << serverAxisId
1210                      << list_indi.back() << list_dataInd.back();
1211
1212      listData.back() << hasValue;
1213      if (hasValue)
1214        listData.back() << list_val.back();
1215
1216      listData.back() << hasBounds;
1217      if (hasBounds)
1218        listData.back() << list_bounds.back();
1219
1220      listData.back() << hasLabel;
1221      if (hasLabel)
1222        listData.back() << list_label.back();
1223
1224      eventData.push(rank, nbSenders[nbServer][rank], listData.back());
1225    }
1226
1227    client->sendEvent(eventData);
1228  }
1229  CATCH_DUMP_ATTR
1230
1231  /*
1232    Receive the distributed attributes from another group of clients
1233    \param [in] event event containing data of these attributes
1234  */
1235  void CAxis::recvDistributedAttributes_old(CEventServer& event)
1236  TRY
1237  {
1238    string axisId;
1239    vector<int> ranks;
1240    vector<CBufferIn*> buffers;
1241
1242    list<CEventServer::SSubEvent>::iterator it;
1243    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1244    {
1245      ranks.push_back(it->rank);
1246      CBufferIn* buffer = it->buffer;
1247      *buffer >> axisId;
1248      buffers.push_back(buffer);
1249    }
1250    get(axisId)->recvDistributedAttributes_old(ranks, buffers);
1251  }
1252  CATCH
1253
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  */
1259  void CAxis::recvDistributedAttributes_old(vector<int>& ranks, vector<CBufferIn*> buffers)
1260  TRY
1261  {
1262    int nbReceived = ranks.size(), idx, ind, gloInd, locInd;
1263    vector<CArray<int,1> > vec_indi(nbReceived), vec_dataInd(nbReceived);
1264    vector<CArray<double,1> > vec_val(nbReceived);
1265    vector<CArray<double,2> > vec_bounds(nbReceived);
1266    vector<CArray<string,1> > vec_label(nbReceived);
1267   
1268    for (idx = 0; idx < nbReceived; ++idx)
1269    {     
1270      CBufferIn& buffer = *buffers[idx];
1271      buffer >> vec_indi[idx];
1272      buffer >> vec_dataInd[idx];     
1273
1274      buffer >> hasValue;
1275      if (hasValue)
1276        buffer >> vec_val[idx];
1277
1278      buffer >> hasBounds;
1279      if (hasBounds)
1280        buffer >> vec_bounds[idx];
1281
1282      buffer >> hasLabel;
1283      if (hasLabel)
1284        buffer >> vec_label[idx]; 
1285    }
1286
1287    // Estimate size of index array
1288    int nbIndexGlob = 0;
1289    for (idx = 0; idx < nbReceived; ++idx)
1290    {
1291      nbIndexGlob += vec_indi[idx].numElements();
1292    }
1293
1294    // Recompute global index
1295    // Take account of the overlapped index
1296    index.resize(nbIndexGlob);
1297    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
1298    nbIndexGlob = 0;
1299    int nbIndLoc = 0;
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);
1306         nbIndLoc = (gloInd % n_glo)-begin;
1307         if (0 == globalLocalIndexMap_.count(gloInd))
1308         {
1309           index(nbIndexGlob) = gloInd % n_glo;
1310           globalLocalIndexMap_[gloInd] = nbIndexGlob;
1311           ++nbIndexGlob;
1312         } 
1313      } 
1314    }
1315
1316    // Resize index to its real size
1317    if (nbIndexGlob==0) index.resize(nbIndexGlob) ;
1318    else index.resizeAndPreserve(nbIndexGlob);
1319
1320    int nbData = nbIndexGlob;
1321    CArray<int,1> nonCompressedData(nbData);
1322    nonCompressedData = -1;   
1323    // Mask is incorporated into data_index and is not sent/received anymore
1324    mask.reset();
1325    if (hasValue)
1326      value.resize(nbData);
1327    if (hasBounds)
1328      bounds.resize(2,nbData);
1329    if (hasLabel)
1330      label.resize(nbData);
1331
1332    nbData = 0;
1333    for (idx = 0; idx < nbReceived; ++idx)
1334    {
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)
1339      { 
1340        locInd = globalLocalIndexMap_[size_t(indi(n))];
1341
1342        nonCompressedData(locInd) = (-1 == nonCompressedData(locInd)) ? dataIndi(n) : nonCompressedData(locInd);
1343
1344        if (hasValue)
1345          value(locInd) = vec_val[idx](n);
1346
1347        if (hasBounds)
1348        {
1349          bounds(0,locInd) = vec_bounds[idx](0,n);
1350          bounds(1,locInd) = vec_bounds[idx](1,n);
1351        }
1352
1353        if (hasLabel)
1354          label(locInd) = vec_label[idx](n);
1355      }
1356    }
1357   
1358    int nbCompressedData = 0;
1359    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1360    {
1361      if (0 <= nonCompressedData(idx))
1362        ++nbCompressedData;
1363    }
1364
1365    data_index.resize(nbCompressedData);
1366    nbCompressedData = 0;
1367    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1368    {
1369      if (0 <= nonCompressedData(idx))
1370      {
1371        data_index(nbCompressedData) = idx % n;
1372        ++nbCompressedData;
1373      }
1374    }
1375
1376    data_begin.setValue(0);
1377    data_n.setValue(data_index.numElements());
1378  }
1379  CATCH_DUMP_ATTR
1380
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)
1389  TRY
1390  {
1391    vector<StdString> excludedAttr;
1392    excludedAttr.push_back("axis_ref");
1393
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  }
1413  CATCH_DUMP_ATTR
1414
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  */
1420  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
1421  TRY
1422  {
1423    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
1424    return transformationMap_.back().second;
1425  }
1426  CATCH_DUMP_ATTR
1427
1428  /*
1429    Check whether an axis has (spatial) transformation
1430  */
1431  bool CAxis::hasTransformation()
1432  TRY
1433  {
1434    return (!transformationMap_.empty());
1435  }
1436  CATCH_DUMP_ATTR
1437
1438  /*
1439    Set transformation
1440    \param [in] axisTrans transformation to set
1441  */
1442  void CAxis::setTransformations(const TransMapTypes& axisTrans)
1443  TRY
1444  {
1445    transformationMap_ = axisTrans;
1446  }
1447  CATCH_DUMP_ATTR
1448
1449  /*
1450    Return all transformation held by the axis
1451    \return transformation the axis has
1452  */
1453  CAxis::TransMapTypes CAxis::getAllTransformations(void)
1454  TRY
1455  {
1456    return transformationMap_;
1457  }
1458  CATCH_DUMP_ATTR
1459
1460  /*
1461    Duplicate transformation of another axis
1462    \param [in] src axis whose transformations are copied
1463  */
1464  void CAxis::duplicateTransformation(CAxis* src)
1465  TRY
1466  {
1467    if (src->hasTransformation())
1468    {
1469      this->setTransformations(src->getAllTransformations());
1470    }
1471  }
1472  CATCH_DUMP_ATTR
1473
1474  /*!
1475   * Go through the hierarchy to find the axis from which the transformations must be inherited
1476   */
1477  void CAxis::solveInheritanceTransformation()
1478  TRY
1479  {
1480    if (hasTransformation() || !hasDirectAxisReference())
1481      return;
1482
1483    CAxis* axis = this;
1484    std::vector<CAxis*> refAxis;
1485    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
1486    {
1487      refAxis.push_back(axis);
1488      axis = axis->getDirectAxisReference();
1489    }
1490
1491    if (axis->hasTransformation())
1492      for (size_t i = 0; i < refAxis.size(); ++i)
1493        refAxis[i]->setTransformations(axis->getAllTransformations());
1494  }
1495  CATCH_DUMP_ATTR
1496
1497  void CAxis::setContextClient(CContextClient* contextClient)
1498  TRY
1499  {
1500    if (clientsSet.find(contextClient)==clientsSet.end())
1501    {
1502      clients.push_back(contextClient) ;
1503      clientsSet.insert(contextClient);
1504    }
1505  }
1506  CATCH_DUMP_ATTR
1507
1508  void CAxis::parse(xml::CXMLNode & node)
1509  TRY
1510  {
1511    SuperClass::parse(node);
1512
1513    if (node.goToChildElement())
1514    {
1515      StdString nodeElementName;
1516      do
1517      {
1518        StdString nodeId("");
1519        if (node.getAttributes().end() != node.getAttributes().find("id"))
1520        { nodeId = node.getAttributes()["id"]; }
1521
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)));
1530        }
1531        else
1532        {
1533          ERROR("void CAxis::parse(xml::CXMLNode & node)",
1534                << "The transformation " << nodeElementName << " has not been supported yet.");
1535        }
1536      } while (node.goToNextElement()) ;
1537      node.goToParentElement();
1538    }
1539  }
1540  CATCH_DUMP_ATTR
1541
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 ;
1640      for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()); 
1641    }
1642    remoteElement_[client] = new CDistributedElement(n_glo, globalIndex) ;
1643    remoteElement_[client]->addFullView() ;
1644  }
1645 
1646  void CAxis::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, 
1647                                 CScattererConnector* &scattererConnector, const string& axisId)
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() ;
1656    scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 
1657                                                 context->getIntraComm(), client->getRemoteSize()) ;
1658    scattererConnector->computeConnector() ;
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() ; 
1672    scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
1673
1674    sendDistributedAttributes(client, *scattererConnector, axisId) ;
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 ; 
1687    scattererConnector->transfer(maskOut, maskOut2) ;
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) ; 
1697    clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL), 
1698                                                              context->getIntraComm(), client->getRemoteSize()) ;
1699    clientToServerConnector_[client]->computeConnector() ;
1700
1701    clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
1702    clientFromServerConnector_[client]->computeConnector() ;
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    {
1752//      delete gathererConnector_ ;
1753      elementFrom_ = new  CDistributedElement(event) ;
1754      elementFrom_->addFullView() ;
1755//      gathererConnector_ =  new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
1756//      gathererConnector_ -> computeConnector() ;
1757    }
1758 
1759  }
1760  CATCH
1761
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
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
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        }
1821        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
1822        CMessage message ;
1823        message<<serverAxisId<<string("label")<<maxSize ;
1824        scattererConnector.transfer(maxSize, charArray, client, event,message) ;
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) ;
1851      if (bounds.numElements() > 0 ) bounds=CArray<double,2>(value.dataFirst(),shape(2,n),neverDeleteData) ; 
1852    }
1853    else if (type=="label")
1854    {
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      } 
1874    }
1875  }
1876  CATCH
1877
1878  DEFINE_REF_FUNC(Axis,axis)
1879
1880   ///---------------------------------------------------------------
1881
1882} // namespace xios
Note: See TracBrowser for help on using the repository browser.