source: XIOS/branchs/xios-2.5/src/node/axis.cpp @ 1566

Last change on this file since 1566 was 1566, checked in by oabramkina, 6 years ago

Bugfix for masked distributed axis.

Previously mask wasn't working at all, an exception was thrown.

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