source: XIOS/dev/dev_olga/src/node/axis.cpp @ 1577

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

Adding a check on the client side if all servers have data to receive. If servers have no data to receive the master process will send empty data to such servers. This ensures that all servers participate in collective calls.

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