source: XIOS/dev/dev_trunk_omp/src/node/axis.cpp @ 1646

Last change on this file since 1646 was 1646, checked in by yushan, 5 years ago

branch merged with trunk @1645. arch file (ep&mpi) added for ADA

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