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

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

Big update on on going work related to data distribution and transfer between clients and servers.

  • move all related file into distribution directorie
  • implement the concept of data "View"
  • implement the concept of "connector" which make the data transfer between 2 differents "Views"

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