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

Last change on this file since 1900 was 1900, checked in by yushan, 4 years ago

xios-2.5 : minormodif for Jean-Zay after system maintenance to RH8 and complr update frr om 8 à to 8.3.1. To be checked

  • 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.7 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     return true ;
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(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//    nbWritten = 0;
708//    for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
709//    {
710//      indGlo = *itSrv;
711//      if (ite != globalLocalIndexMap_.find(indGlo))
712//      {
713//        localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[indGlo];
714//      }
715//      else
716//      {
717//        localIndexToWriteOnServer(nbWritten) = -1;
718//      }
719//      ++nbWritten;
720//    }
721
722      localIndexToWriteOnServer.resize(writtenGlobalIndex.numElements());
723//      localIndexToWriteOnServer.resize(nbWritten);
724
725      nbWritten = 0;
726      for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
727      {
728        indGlo = *itSrv;
729        if (ite != globalLocalIndexMap_.find(indGlo))
730        {
731          localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[indGlo];
732          ++nbWritten;
733        }                 
734      }
735    }
736    else
737    {
738      nbWritten = 0;
739      boost::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
740                                                          ite = globalLocalIndexMap_.end(), it;
741      for (int i = 0; i < zoom_index.numElements(); ++i)
742      {
743         if (ite != globalLocalIndexMap_.find(zoom_index(i)))
744          ++nbWritten;
745      }
746
747      localIndexToWriteOnServer.resize(nbWritten);
748
749      nbWritten = 0;
750      for (int i = 0; i < zoom_index.numElements(); ++i)
751      {
752         if (ite != globalLocalIndexMap_.find(zoom_index(i)))
753         {
754           localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[zoom_index(i)];
755           ++nbWritten;
756         }
757      }
758    }
759
760    // if (isCompressible())
761    // {
762    //   nbWritten = 0;
763    //   boost::unordered_map<size_t,size_t> localGlobalIndexMap;
764    //   for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
765    //   {
766    //     indGlo = *itSrv;
767    //     if (ite != globalLocalIndexMap_.find(indGlo))
768    //     {
769    //       localGlobalIndexMap[localIndexToWriteOnServer(nbWritten)] = indGlo;
770    //       ++nbWritten;
771    //     }                 
772    //   }
773
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    //       ++nbWritten;
780    //     }
781    //   }
782
783    //   compressedIndexToWriteOnServer.resize(nbWritten);
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    //       compressedIndexToWriteOnServer(nbWritten) = localGlobalIndexMap[data_index(idx)];
790    //       ++nbWritten;
791    //     }
792    //   }
793
794    //   numberWrittenIndexes_ = nbWritten;
795    //   if (isDistributed())
796    //   {
797             
798    //     MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
799    //     MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
800    //     offsetWrittenIndexes_ -= numberWrittenIndexes_;
801    //   }
802    //   else
803    //     totalNumberWrittenIndexes_ = numberWrittenIndexes_;
804    // }
805  }
806
807  void CAxis::computeWrittenCompressedIndex(MPI_Comm writtenComm)
808  {
809    int writtenCommSize;
810    MPI_Comm_size(writtenComm, &writtenCommSize);
811    if (compressedIndexToWriteOnServer.find(writtenCommSize) != compressedIndexToWriteOnServer.end())
812      return;
813
814    if (isCompressible())
815    {
816      size_t nbWritten = 0, indGlo;
817      CContext* context=CContext::getCurrent();     
818      CContextServer* server = context->server; 
819
820      // We describe the distribution of client (server) on which data are written
821      std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1);
822      nBegin[0]       = zoom_begin;
823      nSize[0]        = zoom_n;   
824      nBeginGlobal[0] = 0; 
825      nGlob[0]        = n_glo;
826      CDistributionServer srvDist(server->intraCommSize, nBegin, nSize, nBeginGlobal, nGlob); 
827      const CArray<size_t,1>& writtenGlobalIndex  = srvDist.getGlobalIndex();
828      boost::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),
829                                                          ite = globalLocalIndexMap_.end(), it;   
830
831      CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),
832                                       itSrve = writtenGlobalIndex.end(), itSrv;
833      boost::unordered_map<size_t,size_t> localGlobalIndexMap;
834      for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)
835      {
836        indGlo = *itSrv;
837        if (ite != globalLocalIndexMap_.find(indGlo))
838        {
839          localGlobalIndexMap[localIndexToWriteOnServer(nbWritten)] = indGlo;
840          ++nbWritten;
841        }                 
842      }
843
844      nbWritten = 0;
845      for (int idx = 0; idx < data_index.numElements(); ++idx)
846      {
847        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
848        {
849          ++nbWritten;
850        }
851      }
852
853      compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten);
854      nbWritten = 0;
855      for (int idx = 0; idx < data_index.numElements(); ++idx)
856      {
857        if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx)))
858        {
859          compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)];
860          ++nbWritten;
861        }
862      }
863
864      numberWrittenIndexes_[writtenCommSize] = nbWritten;
865      if (isDistributed())
866      {
867             
868        MPI_Allreduce(&numberWrittenIndexes_[writtenCommSize], &totalNumberWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
869        MPI_Scan(&numberWrittenIndexes_[writtenCommSize], &offsetWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);
870        offsetWrittenIndexes_[writtenCommSize] -= numberWrittenIndexes_[writtenCommSize];
871      }
872      else
873        totalNumberWrittenIndexes_[writtenCommSize] = numberWrittenIndexes_[writtenCommSize];
874    }
875  }
876
877  /*!
878    Send distribution information from a group of client (client role) to another group of client (server role)
879    The distribution of a group of client (server role) is imposed by the group of client (client role)
880    \param [in] globalDim global dimension of grid containing this axis
881    \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2)
882    \param [in] distType distribution type of the server. For now, we only have band distribution.
883  */
884  void CAxis::sendDistributionAttribute(const std::vector<int>& globalDim, int orderPositionInGrid,
885                                        CServerDistributionDescription::ServerDistributionType distType)
886  {
887    std::list<CContextClient*>::iterator it;
888    for (it=clients.begin(); it!=clients.end(); ++it)
889    {
890      CContextClient* client = *it;
891      int nbServer = client->serverSize;
892
893      CServerDistributionDescription serverDescription(globalDim, nbServer);
894      serverDescription.computeServerDistribution();
895
896      std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
897      std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
898
899      CEventClient event(getType(),EVENT_ID_DISTRIBUTION_ATTRIBUTE);
900      if (client->isServerLeader())
901      {
902        std::list<CMessage> msgs;
903
904        const std::list<int>& ranks = client->getRanksServerLeader();
905        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
906        {
907          // Use const int to ensure CMessage holds a copy of the value instead of just a reference
908          const int begin = serverIndexBegin[*itRank][orderPositionInGrid];
909          const int ni    = serverDimensionSizes[*itRank][orderPositionInGrid];
910          const int end   = begin + ni - 1;         
911
912          msgs.push_back(CMessage());
913          CMessage& msg = msgs.back();
914          msg << this->getId();
915          msg << ni << begin << end;         
916          msg << isCompressible_;                   
917
918          event.push(*itRank,1,msg);
919        }
920        client->sendEvent(event);
921      }
922      else client->sendEvent(event);
923    }
924  }
925
926  /*
927    Receive distribution attribute from another client
928    \param [in] event event containing data of these attributes
929  */
930  void CAxis::recvDistributionAttribute(CEventServer& event)
931  {
932    CBufferIn* buffer = event.subEvents.begin()->buffer;
933    string axisId;
934    *buffer >> axisId;
935    get(axisId)->recvDistributionAttribute(*buffer);
936  }
937
938  /*
939    Receive distribution attribute from another client
940    \param [in] buffer buffer containing data of these attributes
941  */
942  void CAxis::recvDistributionAttribute(CBufferIn& buffer)
943  {
944    int ni_srv, begin_srv, end_srv;
945    int global_zoom_end, zoom_end;
946    bool zoomIndex = zoomByIndex();
947   
948    std::vector<int> zoom_index_tmp;
949    std::vector<int>::iterator itZoomBegin, itZoomEnd, itZoom;
950
951    buffer >> ni_srv >> begin_srv >> end_srv;   
952    buffer >> isCompressible_;           
953
954    // Set up new local size of axis on the receiving clients
955    n.setValue(ni_srv);
956    begin.setValue(begin_srv);
957
958    // If we have zoom by index then process it
959    if (zoomIndex)
960    {
961      zoom_index_tmp.resize(global_zoom_index.numElements());
962      std::copy(global_zoom_index.begin(), global_zoom_index.end(), zoom_index_tmp.begin());
963      std::sort(zoom_index_tmp.begin(), zoom_index_tmp.end());
964      itZoomBegin = std::lower_bound(zoom_index_tmp.begin(), zoom_index_tmp.end(), begin_srv);
965      itZoomEnd   = std::upper_bound(zoom_index_tmp.begin(), zoom_index_tmp.end(), end_srv);     
966      int sz = std::distance(itZoomBegin, itZoomEnd);
967      zoom_index.resize(sz);
968      itZoom = itZoomBegin;
969      for (int i = 0; i < sz; ++i, ++itZoom)
970      {
971        zoom_index(i) = *(itZoom);
972      }
973    }
974
975    global_zoom_begin = zoomIndex ? 0 : global_zoom_begin ;
976    global_zoom_n     = zoomIndex ? zoom_index_tmp.size() : global_zoom_n;
977    global_zoom_end   = global_zoom_begin + global_zoom_n - 1;
978
979    zoom_begin = zoomIndex ? std::distance(zoom_index_tmp.begin(), itZoomBegin)
980                           : global_zoom_begin > begin_srv ? global_zoom_begin : begin_srv ;
981    zoom_end   = zoomIndex ? std::distance(zoom_index_tmp.begin(), itZoomEnd) - 1 
982                           : global_zoom_end < end_srv ? global_zoom_end : end_srv ;
983    zoom_n     = zoom_end - zoom_begin + 1;
984
985    if (zoom_n<=0)
986    {
987      zoom_n = 0; zoom_begin=global_zoom_begin; //0; zoom_begin = 0;
988    }
989
990    if (n_glo == n)
991    {
992      zoom_begin = zoomIndex ? std::distance(itZoomBegin, zoom_index_tmp.begin())
993                             : global_zoom_begin;     
994      zoom_n     = zoomIndex ? zoom_index_tmp.size() : global_zoom_n;
995    }
996  }
997
998  /*
999    Send attributes of axis from a group of client to other group of clients/servers
1000    on supposing that these attributes are not distributed among the sending group
1001    In the future, if new attributes are added, they should also be processed in this function
1002  */
1003  void CAxis::sendNonDistributedAttributes()
1004  {
1005    std::list<CContextClient*>::iterator it;
1006    for (it=clients.begin(); it!=clients.end(); ++it)
1007        {
1008          CContextClient* client = *it;
1009
1010      CEventClient event(getType(), EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES);
1011      size_t nbIndex = index.numElements();
1012      size_t nbDataIndex = 0;
1013
1014      for (int idx = 0; idx < data_index.numElements(); ++idx)
1015      {
1016        int ind = data_index(idx);
1017        if (ind >= 0 && ind < nbIndex) ++nbDataIndex;
1018      }
1019
1020      CArray<int,1> dataIndex(nbDataIndex);
1021      nbDataIndex = 0;
1022      for (int idx = 0; idx < data_index.numElements(); ++idx)
1023      {
1024        int ind = data_index(idx);
1025        if (ind >= 0 && ind < nbIndex)
1026        {
1027          dataIndex(nbDataIndex) = ind;
1028          ++nbDataIndex;
1029        }
1030      }
1031
1032      if (client->isServerLeader())
1033      {
1034        std::list<CMessage> msgs;
1035
1036        const std::list<int>& ranks = client->getRanksServerLeader();
1037        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1038        {
1039          msgs.push_back(CMessage());
1040          CMessage& msg = msgs.back();
1041          msg << this->getId();
1042          msg << index.getValue() << dataIndex << mask.getValue();
1043          msg << hasValue;
1044          if (hasValue) msg << value.getValue();
1045          msg << hasBounds;
1046          if (hasBounds) msg << bounds.getValue();
1047          msg << hasLabel;
1048          if (hasLabel) msg << label.getValue();
1049
1050          event.push(*itRank, 1, msg);
1051        }
1052        client->sendEvent(event);
1053      }
1054      else client->sendEvent(event);
1055    }
1056  }
1057
1058  /*
1059    Receive the non-distributed attributes from another group of clients
1060    \param [in] event event containing data of these attributes
1061  */
1062  void CAxis::recvNonDistributedAttributes(CEventServer& event)
1063  {
1064    list<CEventServer::SSubEvent>::iterator it;
1065    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1066    {
1067      CBufferIn* buffer = it->buffer;
1068      string axisId;
1069      *buffer >> axisId;
1070      get(axisId)->recvNonDistributedAttributes(it->rank, *buffer);
1071    }
1072  }
1073
1074  /*
1075    Receive the non-distributed attributes from another group of clients
1076    \param [in] rank rank of the sender
1077    \param [in] buffer buffer containing data sent from the sender
1078  */
1079  void CAxis::recvNonDistributedAttributes(int rank, CBufferIn& buffer)
1080  { 
1081    CArray<int,1> tmp_index, tmp_data_index, tmp_zoom_index;
1082    CArray<bool,1> tmp_mask;
1083    CArray<double,1> tmp_val;
1084    CArray<double,2> tmp_bnds;
1085    CArray<string,1> tmp_label;
1086
1087    buffer >> tmp_index;
1088    index.reference(tmp_index);
1089    buffer >> tmp_data_index;
1090    data_index.reference(tmp_data_index);
1091    buffer >> tmp_mask;
1092    mask.reference(tmp_mask);
1093
1094    buffer >> hasValue;
1095    if (hasValue)
1096    {
1097      buffer >> tmp_val;
1098      value.reference(tmp_val);
1099    }
1100
1101    buffer >> hasBounds;
1102    if (hasBounds)
1103    {
1104      buffer >> tmp_bnds;
1105      bounds.reference(tmp_bnds);
1106    }
1107
1108    buffer >> hasLabel;
1109    if (hasLabel)
1110    {
1111      buffer >> tmp_label;
1112      label.reference(tmp_label);
1113    }
1114
1115    // Some value should be reset here
1116    data_begin.setValue(0);
1117    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
1118//    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[idx] = index(idx);
1119    for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[index(idx)] = idx;
1120  }
1121
1122  /*
1123    Send attributes of axis from a group of client to other group of clients/servers
1124    on supposing that these attributes are distributed among the clients of the sending group
1125    In the future, if new attributes are added, they should also be processed in this function
1126  */
1127  void CAxis::sendDistributedAttributes(void)
1128  {
1129    int ns, n, i, j, ind, nv, idx;
1130    std::list<CContextClient*>::iterator it;
1131
1132    for (it=clients.begin(); it!=clients.end(); ++it)
1133    {
1134      CContextClient* client = *it;
1135      int nbServer = client->serverSize;
1136
1137      CEventClient eventData(getType(), EVENT_ID_DISTRIBUTED_ATTRIBUTES);
1138
1139      list<CMessage> listData;
1140      list<CArray<int,1> > list_indi, list_dataInd, list_zoomInd;
1141      list<CArray<bool,1> > list_mask;
1142      list<CArray<double,1> > list_val;
1143      list<CArray<double,2> > list_bounds;
1144      list<CArray<string,1> > list_label;
1145
1146      int nbIndex = index.numElements();
1147      CArray<int,1> dataIndex(nbIndex);
1148      dataIndex = -1;
1149      for (idx = 0; idx < data_index.numElements(); ++idx)
1150      {
1151        if (0 <= data_index(idx) && data_index(idx) < nbIndex)
1152          dataIndex(idx) = 1;
1153      }
1154
1155      boost::unordered_map<int, std::vector<size_t> >::const_iterator it, iteMap;
1156      iteMap = indSrv_[nbServer].end();
1157      for (int k = 0; k < connectedServerRank_[nbServer].size(); ++k)
1158      {
1159        int nbData = 0;
1160        int rank = connectedServerRank_[nbServer][k];
1161        it = indSrv_[nbServer].find(rank);
1162        if (iteMap != it)
1163          nbData = it->second.size();
1164
1165        list_indi.push_back(CArray<int,1>(nbData));
1166        list_dataInd.push_back(CArray<int,1>(nbData));       
1167        list_mask.push_back(CArray<bool,1>(nbData));
1168
1169        if (hasValue)
1170          list_val.push_back(CArray<double,1>(nbData));
1171
1172        if (hasBounds)       
1173          list_bounds.push_back(CArray<double,2>(2,nbData));
1174
1175        if (hasLabel)
1176          list_label.push_back(CArray<string,1>(nbData));
1177
1178        CArray<int,1>& indi = list_indi.back();
1179        CArray<int,1>& dataIndi = list_dataInd.back();       
1180        CArray<bool,1>& maskIndi = list_mask.back();
1181
1182        for (n = 0; n < nbData; ++n)
1183        {
1184          idx = static_cast<int>(it->second[n]);
1185          indi(n) = idx;
1186
1187          ind = globalLocalIndexMap_[idx];
1188          dataIndi(n) = dataIndex(ind);
1189          maskIndi(n) = mask(ind);
1190
1191          if (hasValue)
1192          {
1193            CArray<double,1>& val = list_val.back();
1194            val(n) = value(ind);
1195          }
1196
1197          if (hasBounds)
1198          {
1199            CArray<double,2>& boundsVal = list_bounds.back();
1200            boundsVal(0, n) = bounds(0,ind);
1201            boundsVal(1, n) = bounds(1,ind);
1202          }
1203
1204          if (hasLabel)
1205          {
1206            CArray<string,1>& labelVal = list_label.back();
1207            labelVal(n) = label(ind); 
1208          }
1209        }
1210
1211        listData.push_back(CMessage());
1212        listData.back() << this->getId()
1213                        << list_indi.back() << list_dataInd.back() << list_mask.back();
1214
1215        listData.back() << hasValue;
1216        if (hasValue)
1217          listData.back() << list_val.back();
1218
1219        listData.back() << hasBounds;
1220        if (hasBounds)
1221          listData.back() << list_bounds.back();
1222
1223        listData.back() << hasLabel;
1224        if (hasLabel)
1225          listData.back() << list_label.back();
1226
1227        eventData.push(rank, nbSenders[nbServer][rank], listData.back());
1228      }
1229
1230      client->sendEvent(eventData);
1231    }
1232  }
1233
1234  /*
1235    Receive the distributed attributes from another group of clients
1236    \param [in] event event containing data of these attributes
1237  */
1238  void CAxis::recvDistributedAttributes(CEventServer& event)
1239  {
1240    string axisId;
1241    vector<int> ranks;
1242    vector<CBufferIn*> buffers;
1243
1244    list<CEventServer::SSubEvent>::iterator it;
1245    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1246    {
1247      ranks.push_back(it->rank);
1248      CBufferIn* buffer = it->buffer;
1249      *buffer >> axisId;
1250      buffers.push_back(buffer);
1251    }
1252    get(axisId)->recvDistributedAttributes(ranks, buffers);
1253  }
1254
1255  /*
1256    Receive the non-distributed attributes from another group of clients
1257    \param [in] ranks rank of the sender
1258    \param [in] buffers buffer containing data sent from the sender
1259  */
1260  void CAxis::recvDistributedAttributes(vector<int>& ranks, vector<CBufferIn*> buffers)
1261  {
1262    int nbReceived = ranks.size(), idx, ind, gloInd, locInd;
1263    vector<CArray<int,1> > vec_indi(nbReceived), vec_dataInd(nbReceived), vec_zoomInd(nbReceived);   
1264    vector<CArray<bool,1> > vec_mask(nbReceived);
1265    vector<CArray<double,1> > vec_val(nbReceived);
1266    vector<CArray<double,2> > vec_bounds(nbReceived);
1267    vector<CArray<string,1> > vec_label(nbReceived);
1268   
1269    for (idx = 0; idx < nbReceived; ++idx)
1270    {     
1271      CBufferIn& buffer = *buffers[idx];
1272      buffer >> vec_indi[idx];
1273      buffer >> vec_dataInd[idx];     
1274      buffer >> vec_mask[idx];
1275
1276      buffer >> hasValue;
1277      if (hasValue)
1278        buffer >> vec_val[idx];
1279
1280      buffer >> hasBounds;
1281      if (hasBounds)
1282        buffer >> vec_bounds[idx];
1283
1284      buffer >> hasLabel;
1285      if (hasLabel)
1286        buffer >> vec_label[idx]; 
1287    }
1288
1289    // Estimate size of index array
1290    int nbIndexGlob = 0;
1291    for (idx = 0; idx < nbReceived; ++idx)
1292    {
1293      nbIndexGlob += vec_indi[idx].numElements();
1294    }
1295
1296    // Recompute global index
1297    // Take account of the overlapped index
1298    index.resize(nbIndexGlob);
1299    globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor()));
1300    nbIndexGlob = 0;
1301    int nbIndLoc = 0;
1302    for (idx = 0; idx < nbReceived; ++idx)
1303    {
1304      CArray<int,1>& tmp = vec_indi[idx];
1305      for (ind = 0; ind < tmp.numElements(); ++ind)
1306      {
1307         gloInd = tmp(ind);
1308         nbIndLoc = (gloInd % n_glo) - begin;
1309         if (0 == globalLocalIndexMap_.count(gloInd))
1310         {
1311           index(nbIndexGlob) = gloInd % n_glo;
1312           globalLocalIndexMap_[gloInd] = nbIndexGlob;
1313//           index(nbIndLoc) = gloInd % n_glo;
1314//           globalLocalIndexMap_[gloInd] = nbIndLoc; 
1315           ++nbIndexGlob;
1316         } 
1317      } 
1318    }
1319
1320    // Resize index to its real size
1321    if (nbIndexGlob==0) index.resize(nbIndexGlob) ;
1322    else index.resizeAndPreserve(nbIndexGlob);
1323
1324    int nbData = nbIndexGlob;
1325    CArray<int,1> nonCompressedData(nbData);
1326    nonCompressedData = -1;   
1327    mask.resize(nbData);
1328    if (hasValue)
1329      value.resize(nbData);
1330    if (hasBounds)
1331      bounds.resize(2,nbData);
1332    if (hasLabel)
1333      label.resize(nbData);
1334
1335    nbData = 0;
1336    for (idx = 0; idx < nbReceived; ++idx)
1337    {
1338      CArray<int,1>& indi = vec_indi[idx];
1339      CArray<int,1>& dataIndi = vec_dataInd[idx];
1340      CArray<bool,1>& maskIndi = vec_mask[idx];
1341      int nb = indi.numElements();
1342      for (int n = 0; n < nb; ++n)
1343      { 
1344        locInd = globalLocalIndexMap_[size_t(indi(n))];
1345
1346        nonCompressedData(locInd) = (-1 == nonCompressedData(locInd)) ? dataIndi(n) : nonCompressedData(locInd);
1347
1348        if (!mask(locInd)) // Only rewrite mask if it's not true
1349          mask(locInd) = maskIndi(n);
1350       
1351        if (hasValue)
1352          value(locInd) = vec_val[idx](n);
1353
1354        if (hasBounds)
1355        {
1356          bounds(0,locInd) = vec_bounds[idx](0,n);
1357          bounds(1,locInd) = vec_bounds[idx](1,n);
1358        }
1359
1360        if (hasLabel)
1361          label(locInd) = vec_label[idx](n);
1362      }
1363    }
1364   
1365    int nbCompressedData = 0;
1366    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1367    {
1368      if (0 <= nonCompressedData(idx))
1369        ++nbCompressedData;
1370    }
1371
1372    data_index.resize(nbCompressedData);
1373    nbCompressedData = 0;
1374    for (idx = 0; idx < nonCompressedData.numElements(); ++idx)
1375    {
1376      if (0 <= nonCompressedData(idx))
1377      {
1378        data_index(nbCompressedData) = idx % n;
1379        ++nbCompressedData;
1380      }
1381    }
1382
1383    data_begin.setValue(0);
1384  }
1385
1386
1387  /*!
1388    Compare two axis objects.
1389    They are equal if only if they have identical attributes as well as their values.
1390    Moreover, they must have the same transformations.
1391  \param [in] axis Compared axis
1392  \return result of the comparison
1393  */
1394  bool CAxis::isEqual(CAxis* obj)
1395  {
1396    vector<StdString> excludedAttr;
1397    excludedAttr.push_back("axis_ref");
1398
1399    bool objEqual = SuperClass::isEqual(obj, excludedAttr);   
1400    if (!objEqual) return objEqual;
1401
1402    TransMapTypes thisTrans = this->getAllTransformations();
1403    TransMapTypes objTrans  = obj->getAllTransformations();
1404
1405    TransMapTypes::const_iterator it, itb, ite;
1406    std::vector<ETranformationType> thisTransType, objTransType;
1407    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
1408      thisTransType.push_back(it->first);
1409    for (it = objTrans.begin(); it != objTrans.end(); ++it)
1410      objTransType.push_back(it->first);
1411
1412    if (thisTransType.size() != objTransType.size()) return false;
1413    for (int idx = 0; idx < thisTransType.size(); ++idx)
1414      objEqual &= (thisTransType[idx] == objTransType[idx]);
1415
1416    return objEqual;
1417  }
1418
1419  /*
1420    Add transformation into axis. This function only servers for Fortran interface
1421    \param [in] transType transformation type
1422    \param [in] id identifier of the transformation object
1423  */
1424  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
1425  {
1426    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
1427    return transformationMap_.back().second;
1428  }
1429
1430  /*
1431    Check whether an axis has (spatial) transformation
1432  */
1433  bool CAxis::hasTransformation()
1434  {
1435    return (!transformationMap_.empty());
1436  }
1437
1438  /*
1439    Set transformation
1440    \param [in] axisTrans transformation to set
1441  */
1442  void CAxis::setTransformations(const TransMapTypes& axisTrans)
1443  {
1444    transformationMap_ = axisTrans;
1445  }
1446
1447  /*
1448    Return all transformation held by the axis
1449    \return transformation the axis has
1450  */
1451  CAxis::TransMapTypes CAxis::getAllTransformations(void)
1452  {
1453    return transformationMap_;
1454  }
1455
1456  /*
1457    Duplicate transformation of another axis
1458    \param [in] src axis whose transformations are copied
1459  */
1460  void CAxis::duplicateTransformation(CAxis* src)
1461  {
1462    if (src->hasTransformation())
1463    {
1464      this->setTransformations(src->getAllTransformations());
1465    }
1466  }
1467
1468  /*!
1469   * Go through the hierarchy to find the axis from which the transformations must be inherited
1470   */
1471  void CAxis::solveInheritanceTransformation()
1472  {
1473    if (hasTransformation() || !hasDirectAxisReference())
1474      return;
1475
1476    CAxis* axis = this;
1477    std::vector<CAxis*> refAxis;
1478    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
1479    {
1480      refAxis.push_back(axis);
1481      axis = axis->getDirectAxisReference();
1482    }
1483
1484    if (axis->hasTransformation())
1485      for (size_t i = 0; i < refAxis.size(); ++i)
1486        refAxis[i]->setTransformations(axis->getAllTransformations());
1487  }
1488
1489  void CAxis::setContextClient(CContextClient* contextClient)
1490  {
1491    if (clientsSet.find(contextClient)==clientsSet.end())
1492    {
1493      clients.push_back(contextClient) ;
1494      clientsSet.insert(contextClient);
1495    }
1496  }
1497
1498  void CAxis::parse(xml::CXMLNode & node)
1499  {
1500    SuperClass::parse(node);
1501
1502    if (node.goToChildElement())
1503    {
1504      StdString nodeElementName;
1505      do
1506      {
1507        StdString nodeId("");
1508        if (node.getAttributes().end() != node.getAttributes().find("id"))
1509        { nodeId = node.getAttributes()["id"]; }
1510
1511        nodeElementName = node.getElementName();
1512        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
1513        it = transformationMapList_.find(nodeElementName);
1514        if (ite != it)
1515        {
1516          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second,
1517                                                                                                               nodeId,
1518                                                                                                               &node)));
1519        }
1520        else
1521        {
1522          ERROR("void CAxis::parse(xml::CXMLNode & node)",
1523                << "The transformation " << nodeElementName << " has not been supported yet.");
1524        }
1525      } while (node.goToNextElement()) ;
1526      node.goToParentElement();
1527    }
1528  }
1529
1530  DEFINE_REF_FUNC(Axis,axis)
1531
1532   ///---------------------------------------------------------------
1533
1534} // namespace xios
Note: See TracBrowser for help on using the repository browser.