source: XIOS/dev/XIOS_DEV_CMIP6/src/node/axis.cpp @ 1248

Last change on this file since 1248 was 1236, checked in by mhnguyen, 7 years ago

Making some changes to allow pools with different number of server

+) Associate context client to each grid distribution (This should be changed in the future)
+) Correct some buffer size estimation
+) Clean some redundant code and add comments

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