source: XIOS/dev/branch_openmp/src/node/axis.cpp @ 1545

Last change on this file since 1545 was 1545, checked in by yushan, 6 years ago

branch_openmp merged with trunk r1544

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