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

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

XIOS coupling branch
Some updates.

First coupling test is beginning to work...

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