source: XIOS3/trunk/src/node/axis.cpp @ 2507

Last change on this file since 2507 was 2507, checked in by ymipsl, 13 months ago

Merging XIOS3_ATTACHED branch into XIOS3 trunk.

YM

  • 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: 43.5 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
[2203]16#include <algorithm>
17#include <regex>
18
[335]19namespace xios {
[540]20
[1421]21   /// ////////////////////// Definitions ////////////////////// ///
[219]22
23   CAxis::CAxis(void)
24      : CObjectTemplate<CAxis>()
[1975]25      , CAxisAttributes(), isChecked(false), relFiles()
[2507]26      , hasBounds_(false), isCompressible_(false)
27      , transformationMap_()
[1975]28      , clients()
[621]29   {
30   }
[219]31
32   CAxis::CAxis(const StdString & id)
33      : CObjectTemplate<CAxis>(id)
[1975]34      , CAxisAttributes(), isChecked(false), relFiles()
[2507]35      , hasBounds_(false), isCompressible_(false)
36      , transformationMap_()
[1975]37      , clients()
[621]38   {
39   }
[219]40
41   CAxis::~CAxis(void)
42   { /* Ne rien faire de plus */ }
43
[836]44   std::map<StdString, ETranformationType> CAxis::transformationMapList_ = std::map<StdString, ETranformationType>();
45   bool CAxis::dummyTransformationMapList_ = CAxis::initializeTransformationMap(CAxis::transformationMapList_);
46   bool CAxis::initializeTransformationMap(std::map<StdString, ETranformationType>& m)
[1622]47   TRY
[836]48   {
[2339]49     m["zoom_axis"] = TRANS_EXTRACT_AXIS;
[836]50     m["interpolate_axis"] = TRANS_INTERPOLATE_AXIS;
[1558]51     m["extract_axis"] = TRANS_EXTRACT_AXIS;
[836]52     m["inverse_axis"] = TRANS_INVERSE_AXIS;
[895]53     m["reduce_domain"] = TRANS_REDUCE_DOMAIN_TO_AXIS;
[1301]54     m["reduce_axis"] = TRANS_REDUCE_AXIS_TO_AXIS;
[895]55     m["extract_domain"] = TRANS_EXTRACT_DOMAIN_TO_AXIS;
[1275]56     m["temporal_splitting"] = TRANS_TEMPORAL_SPLITTING;
[1314]57     m["duplicate_scalar"] = TRANS_DUPLICATE_SCALAR_TO_AXIS;
[2507]58     m["redistribute_axis"] = TRANS_REDISTRIBUTE_AXIS;
59
[2196]60     return true;
[836]61   }
[1622]62   CATCH
[2274]63   
64   void CAxis::releaseStaticAllocation(void)
65   {
66     transformationMapList_.clear() ;
67     CTransformation<CAxis>::unregisterAllTransformations() ;
68     CGridTransformationFactory<CAxis>::unregisterAllTransformations() ;
69   }
[836]70
[219]71   ///---------------------------------------------------------------
[1158]72
73   const std::set<StdString> & CAxis::getRelFiles(void) const
[1622]74   TRY
[1158]75   {
76      return (this->relFiles);
77   }
[1622]78   CATCH
[1158]79
[219]80   bool CAxis::IsWritten(const StdString & filename) const
[1622]81   TRY
[219]82   {
83      return (this->relFiles.find(filename) != this->relFiles.end());
84   }
[1622]85   CATCH
[219]86
[676]87   bool CAxis::isWrittenCompressed(const StdString& filename) const
[1622]88   TRY
[676]89   {
90      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
91   }
[1622]92   CATCH
[676]93
[594]94   bool CAxis::isDistributed(void) const
[1622]95   TRY
[594]96   {
[1158]97      bool distributed = (!this->begin.isEmpty() && !this->n.isEmpty() && (this->begin + this->n < this->n_glo)) ||
98             (!this->n.isEmpty() && (this->n != this->n_glo));
[1622]99      // A condition to make sure that if there is only one client, axis
[1158]100      // should be considered to be distributed. This should be a temporary solution     
[1787]101      distributed |= (1 == CContext::getCurrent()->intraCommSize_);
[1158]102      return distributed;
[594]103   }
[1622]104   CATCH
[594]105
[676]106   /*!
[1956]107    * Compute if the axis can be ouput in a compressed way.
108    * In this case the workflow view on server side must be the same
109    * than the full view for all context rank. The result is stored on
110    * internal isCompressible_ attribute.
[676]111    */
[1956]112   void CAxis::computeIsCompressible(void)
[1622]113   TRY
[676]114   {
[1956]115     // mesh is compressible contains some masked or indexed value, ie if full view is different of workflow view.
116     // But now assume that the size of the 2 view must be equal for everybody. True on server side
117     int isSameView = getLocalView(CElementView::FULL)->getSize() ==  getLocalView(CElementView::WORKFLOW)->getSize();
118     MPI_Allreduce(MPI_IN_PLACE, &isSameView, 1, MPI_INT, MPI_LAND, CContext::getCurrent()->getIntraComm()) ;
119     if (isSameView) isCompressible_ = false ;
120     else isCompressible_ = true ;
121     isCompressibleComputed_=true ;
[676]122   }
[1622]123   CATCH
[676]124
[219]125   void CAxis::addRelFile(const StdString & filename)
[1622]126   TRY
[219]127   {
128      this->relFiles.insert(filename);
129   }
[1622]130   CATCH_DUMP_ATTR
[219]131
[676]132   void CAxis::addRelFileCompressed(const StdString& filename)
[1622]133   TRY
[676]134   {
135      this->relFilesCompressed.insert(filename);
136   }
[1622]137   CATCH_DUMP_ATTR
[676]138
[1975]139    //----------------------------------------------------------------
[219]140
[676]141   /*!
[731]142    * Compute the minimum buffer size required to send the attributes to the server(s).
143    *
144    * \return A map associating the server rank with its minimum buffer size.
145    */
[1371]146   std::map<int, StdSize> CAxis::getAttributesBufferSize(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
147                                                         CServerDistributionDescription::ServerDistributionType distType)
[1622]148   TRY
[731]149   {
150
[1330]151     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client);
[731]152
[1371]153//     bool isNonDistributed = (n_glo == n);
154     bool isDistributed = (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
155                                 || (index.numElements() != n_glo);
[731]156
157     if (client->isServerLeader())
158     {
159       // size estimation for sendServerAttribut
160       size_t size = 6 * sizeof(size_t);
161       // size estimation for sendNonDistributedValue
[1371]162       if (!isDistributed)
163       {
164//         size = std::max(size, CArray<double,1>::size(n_glo) + (isCompressible_ ? CArray<int,1>::size(n_glo) : 0));
165         size += CArray<int,1>::size(n_glo);
166         size += CArray<int,1>::size(n_glo);
167         size += CArray<bool,1>::size(n_glo);
168         size += CArray<double,1>::size(n_glo);
[2507]169         if (hasBounds_)
[1371]170           size += CArray<double,2>::size(2*n_glo);
[2507]171         if (hasLabel_)
[1371]172          size += CArray<StdString,1>::size(n_glo);
173       }
[731]174       size += CEventClient::headerSize + getId().size() + sizeof(size_t);
175
176       const std::list<int>& ranks = client->getRanksServerLeader();
177       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
178       {
179         if (size > attributesSizes[*itRank])
180           attributesSizes[*itRank] = size;
181       }
[1371]182       const std::list<int>& ranksNonLeaders = client->getRanksServerNotLeader();
183       for (std::list<int>::const_iterator itRank = ranksNonLeaders.begin(), itRankEnd = ranksNonLeaders.end(); itRank != itRankEnd; ++itRank)
184       {
185         if (size > attributesSizes[*itRank])
186           attributesSizes[*itRank] = size;
187       }
188
[731]189     }
190
[1371]191     if (isDistributed)
[731]192     {
193       // size estimation for sendDistributedValue
[2343]194       std::unordered_map<int, vector<size_t> >::const_iterator it, ite = indSrv_[client->getRemoteSize()].end();
195       for (it = indSrv_[client->getRemoteSize()].begin(); it != ite; ++it)
[731]196       {
[1371]197         size_t size = 6 * sizeof(size_t);
198         size += CArray<int,1>::size(it->second.size());
199         size += CArray<int,1>::size(it->second.size());
200         size += CArray<bool,1>::size(it->second.size());
201         size += CArray<double,1>::size(it->second.size());
[2507]202         if (hasBounds_)
[1371]203           size += CArray<double,2>::size(2 * it->second.size());
[2507]204         if (hasLabel_)
[1371]205           size += CArray<StdString,1>::size(it->second.size());
[731]206
[1371]207         size += CEventClient::headerSize + getId().size() + sizeof(size_t);
[731]208         if (size > attributesSizes[it->first])
209           attributesSizes[it->first] = size;
210       }
211     }
212     return attributesSizes;
213   }
[1622]214   CATCH_DUMP_ATTR
[731]215
216   //----------------------------------------------------------------
217
[219]218   StdString CAxis::GetName(void)   { return (StdString("axis")); }
219   StdString CAxis::GetDefName(void){ return (CAxis::GetName()); }
220   ENodeType CAxis::GetType(void)   { return (eAxis); }
221
222   //----------------------------------------------------------------
223
[622]224   CAxis* CAxis::createAxis()
[1622]225   TRY
[622]226   {
227     CAxis* axis = CAxisGroup::get("axis_definition")->createChild();
228     return axis;
229   }
[1622]230   CATCH
[622]231
[2206]232   CAxis* CAxis::get(const string& id, bool noError)
[2203]233   {
234     const regex r("::");
235     smatch m;
236     if (regex_search(id, m, r))
237     {
238        if (m.size()!=1) ERROR("CAxis* CAxis::get(string& id)", <<" id = "<<id<< "  -> bad format id, separator :: append more than one time");
239        string fieldId=m.prefix() ;
240        if (fieldId.empty()) ERROR("CAxis* CAxis::get(string& id)", <<" id = "<<id<< "  -> bad format id, field name is empty");
241        string suffix=m.suffix() ;
[2206]242        if (!CField::has(fieldId)) 
243          if (noError)  return nullptr ;
244          else ERROR("CAxis* CAxis::get(string& id, bool noError)", <<" id = "<<id<< "  -> field Id : < "<<fieldId<<" > doesn't exist");
[2203]245        CField* field=CField::get(fieldId) ;
[2206]246        return field->getAssociatedAxis(suffix, noError) ;
[2203]247     }
[2206]248     {
249       if (noError) if(!CObjectFactory::HasObject<CAxis>(id)) return nullptr ;
250       return CObjectFactory::GetObject<CAxis>(id).get();
251     }
[2203]252   }
[2206]253   
254   bool CAxis::has(const string& id)
255   {
256     if (CAxis::get(id,true)==nullptr) return false ;
257     else return true ;
258   }
259   
260   CField* CAxis::getFieldFromId(const string& id)
261   {
262     const regex r("::");
263     smatch m;
264     if (regex_search(id, m, r))
265     {
266        if (m.size()!=1) ERROR("CField* CAxis::getFieldFromId(const string& id)", <<" id = "<<id<< "  -> bad format id, separator :: append more than one time");
267        string fieldId=m.prefix() ;
268        if (fieldId.empty()) ERROR("CField* CAxis::getFieldFromId(const string& id)", <<" id = "<<id<< "  -> bad format id, field name is empty");
269        string suffix=m.suffix() ;
270        CField* field=CField::get(fieldId) ;
271        return field ;
272     }
273     else return nullptr;
274   }
[2203]275
[1144]276   /*!
277     Check common attributes of an axis.
278     This check should be done in the very beginning of work flow
279   */
[2291]280   
[219]281   void CAxis::checkAttributes(void)
[2291]282   {
283      if (checkAttributes_done_) return ;
284      checkGeometricAttributes(true) ;
285      initializeLocalElement() ;
286      addFullView() ;
287      addWorkflowView() ;
288      addModelView() ;
289
290      checkAttributes_done_ = true ;
291   }
292   
293   void CAxis::resetGeometricAttributes(void)
294   {
295     n_glo.reset();
296     index.reset();
297     n.reset();
298     begin.reset();
299     mask.reset();
300     data_index.reset();
301     data_n.reset();
302     data_begin.reset();
303     value.reset();
304     bounds.reset();
305     label.reset() ;
306   }
307
[2388]308   size_t CAxis::computeAttributesHash( MPI_Comm comm )
[2386]309   {
310     // Compute the hash of distributed attributs (value ...)
311     int globalSize = this->n_glo.getValue();
312     CArray<size_t,1> globalIndex; // No redundancy globalIndex will be computed with the connector
313     shared_ptr<CGridTransformConnector> gridTransformConnector;
314     // Compute a without redundancy element FULL view to enable a consistent hash computation (and a distributed globalIndex)
315     this->getLocalView(CElementView::FULL)->createWithoutRedundancyFullViewConnector( globalSize, comm, gridTransformConnector, globalIndex );
316     int localSize = globalIndex.numElements();
317
318     CArray<double,1> distributedValue ;
319     gridTransformConnector->transfer(this->value, distributedValue );
320       
[2388]321     size_t localHash = 0;
[2386]322     for (int iloc=0; iloc<localSize ; iloc++ ) localHash+=globalIndex(iloc)*distributedValue(iloc);
[2388]323     size_t distributedHash = 0;
324     MPI_Allreduce( &localHash, &distributedHash, 1, MPI_UNSIGNED_LONG, MPI_SUM, comm  );
[2386]325
326     // Compute the hash of global attributs (unit, prec ...)
327     vector<StdString> excludedAttr;
328     //excludedAttr.push_back("name");
329     // internal attributs
330     excludedAttr.insert(excludedAttr.end(), { "index", "data_n", "data_begin", "data_index"  });
331     excludedAttr.insert(excludedAttr.end(), { "begin", "n" });     
332     excludedAttr.push_back("axis_ref");
333     // in distributed
334     excludedAttr.push_back("value");
335     // should be considered in distributed
336     excludedAttr.push_back("bounds");
337     excludedAttr.push_back("label");
338     excludedAttr.push_back("mask"); // ???
339
[2388]340     size_t globalHash = this->computeGlobalAttributesHash( excludedAttr );
[2386]341
342     return distributedHash + globalHash;
343   }
[2389]344 
345   void CAxis::renameAttributesBeforeWriting(CAxis* writtenAxis)
346   {
347     if (writtenAxis!=NULL)
348     {
349       this->name = writtenAxis->getAxisOutputName();
350       // + label if necessary, other attributs concerned ?
351     }
352     else
353     {
354       this->name =  this->getId();
355       // + label if necessary, other attributs concerned ?
356     }
357   }
358 
[2291]359   void CAxis::setGeometricAttributes(const CAxis& axisSrc)
360   {
361     resetGeometricAttributes() ;
362     n_glo=axisSrc.n_glo;
363     if (!axisSrc.index.isEmpty())
364     {
365       index.resize(axisSrc.index.shape()) ;
366       index=axisSrc.index;
367     }
368
369     n=axisSrc.n;
370     begin=axisSrc.begin;
371     if (!axisSrc.mask.isEmpty())
372     {
373       mask.resize(axisSrc.mask.shape()) ;
374       mask=axisSrc.mask;
375     }
376     if (!axisSrc.data_index.isEmpty())
377     {
378       data_index.resize(axisSrc.data_index.shape()) ;
379       data_index=axisSrc.data_index;
380     }
381     data_n=axisSrc.data_n;
382     data_begin=axisSrc.data_begin;
383     if (!axisSrc.value.isEmpty())
384     {
385       value.resize(axisSrc.value.shape()) ;
386       value=axisSrc.value;
387     }
388     
389     if (!axisSrc.bounds.isEmpty())
390     {
391       bounds.resize(axisSrc.bounds.shape()) ;
392       bounds=axisSrc.bounds;
393     }
394     if (!axisSrc.label.isEmpty())
395     {
396       label.resize(axisSrc.label.shape()) ;
397       label=axisSrc.label;
398     }
399
400   }
401   
402   bool CAxis::checkGeometricAttributes(bool generateError)
[1622]403   TRY
[219]404   {
[1637]405     CContext* context=CContext::getCurrent();
406
407     if (this->n_glo.isEmpty())
[2291]408        if (generateError) ERROR("CAxis::checkAttributes(void)",
409                                << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
410                                << "The axis is wrongly defined, attribute 'n_glo' must be specified")
411        else return false ; 
[666]412      StdSize size = this->n_glo.getValue();
[540]413
[970]414      if (!this->index.isEmpty())
[551]415      {
[970]416        if (n.isEmpty()) n = index.numElements();
417
418        // It's not so correct but if begin is not the first value of index
419        // then data on the local axis has user-defined distribution. In this case, begin has no meaning.
420        if (begin.isEmpty()) begin = index(0);         
[551]421      }
[970]422      else 
423      {
424        if (!this->begin.isEmpty())
425        {
426          if (begin < 0 || begin > size - 1)
[2291]427             if (generateError) ERROR("CAxis::checkAttributes(void)",
428                                      << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
429                                      << "The axis is wrongly defined, attribute 'begin' (" 
430                                      << begin.getValue() << ") must be non-negative and smaller than size-1 (" << size - 1 << ").")
431              else return false ; 
[970]432        }
433        else this->begin.setValue(0);
[551]434
[970]435        if (!this->n.isEmpty())
436        {
437          if (n < 0 || n > size)
[2291]438            if (generateError) ERROR("CAxis::checkAttributes(void)",
439                                      << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
440                                      << "The axis is wrongly defined, attribute 'n' (" << n.getValue() << ") must be non-negative and smaller than size (" 
441                                      << size << ").")
442            else return false ; 
[970]443        }
444        else this->n.setValue(size);
445
446        {
447          index.resize(n);
448          for (int i = 0; i < n; ++i) index(i) = i+begin;
449        }
[551]450      }
[624]451
[816]452      if (!this->value.isEmpty())
453      {
[1869]454        StdSize true_size = value.numElements();
455        if (this->n.getValue() != true_size)
[2291]456          if (generateError) ERROR("CAxis::checkAttributes(void)",
457                                   << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
458                                   << "The axis is wrongly defined, attribute 'value' has a different size (" << true_size
459                                   << ") than the one defined by the \'size\' attribute (" << n.getValue() << ").")
460          else return false ; 
[2507]461        this->hasValue_ = true;
[816]462      }
[219]463
[2291]464      if (!this->checkBounds(generateError)) return false;
465      if (!this->checkMask(generateError))   return false;
466      if (!this->checkData(generateError))   return false;
467      if (!this->checkLabel(generateError))  return false;
468     
469      return true ;
[219]470   }
[1622]471   CATCH_DUMP_ATTR
[219]472
[1918]473
[1144]474   /*!
[1637]475      Check the validity of data, fill in values if any, and apply mask.
[1144]476   */
[2291]477   bool CAxis::checkData(bool generateError)
[1622]478   TRY
[551]479   {
480      if (data_begin.isEmpty()) data_begin.setValue(0);
[679]481
482      if (data_n.isEmpty())
[551]483      {
[679]484        data_n.setValue(n);
485      }
486      else if (data_n.getValue() < 0)
487      {
[2291]488        if (generateError) ERROR("CAxis::checkData(void)",
489                              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
490                              << "The data size should be strictly positive ('data_n' = " << data_n.getValue() << ").")
491        else return false ;
[551]492      }
493
494      if (data_index.isEmpty())
495      {
[679]496        data_index.resize(data_n);
[1637]497        for (int i = 0; i < data_n; ++i)
498        {
499          if ((i+data_begin) >= 0 && (i+data_begin<n))
500          {
501            if (mask(i+data_begin))
502              data_index(i) = i+data_begin;
503            else
504              data_index(i) = -1;
505          }
506          else
507            data_index(i) = -1;
508        }
[551]509      }
[1637]510      else
511      {
512        if (data_index.numElements() != data_n)
513        {
[2291]514          if (generateError) ERROR("CAxis::checkData(void)",
515                               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
516                               << "The size of data_index = "<< data_index.numElements() << "is not equal to the data size data_n = " 
517                               << data_n.getValue() << ").")
518          else return false ;
[1637]519        }
520        for (int i = 0; i < data_n; ++i)
521        {
[1872]522           if (data_index(i) >= 0 && data_index(i)<n)
523             if (!mask(data_index(i))) data_index(i) = -1;
[1637]524        }
525      }
[2291]526      return true ;
[551]527   }
[1622]528   CATCH_DUMP_ATTR
[551]529
[2291]530/*!
531   Check validity of mask info and fill in values if any.
532  */
533   bool CAxis::checkMask(bool generateError)
[1622]534   TRY
[551]535   {
536      if (!mask.isEmpty())
537      {
[1637]538        if (mask.extent(0) != n)
539        {
[2291]540          if (generateError) ERROR("CAxis::checkMask(void)",
541                                  << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
542                                  << "The mask does not have the same size as the local domain." << std::endl
543                                  << "Local size is " << n.getValue() << "." << std::endl
544                                  << "Mask size is " << mask.extent(0) << ".")
545          else return false ;
[1637]546        }
[551]547      }
[1637]548      else
549      {
550        mask.resize(n);
551        mask = true;
[551]552      }
[2291]553      return true ;
[551]554   }
[1622]555   CATCH_DUMP_ATTR
[551]556
[1144]557   /*!
558     Check validity of bounds info and fill in values if any.
559   */
[2291]560   bool CAxis::checkBounds(bool generateError)
[1622]561   TRY
[1144]562   {
563     if (!bounds.isEmpty())
564     {
565       if (bounds.extent(0) != 2 || bounds.extent(1) != n)
[2291]566         if (generateError) ERROR("CAxis::checkAttributes(void)",
567                               << "The bounds array of the axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] must be of dimension 2 x axis size." << std::endl
568                               << "Axis size is " << n.getValue() << "." << std::endl
569                               << "Bounds size is "<< bounds.extent(0) << " x " << bounds.extent(1) << ".")
570         else return false ;
[2507]571       hasBounds_ = true;
[1144]572     }
[2507]573     else hasBounds_ = false;
[2291]574     return true ;
[1144]575   }
[1622]576   CATCH_DUMP_ATTR
[633]577
[2291]578  bool CAxis::checkLabel(bool generateError)
[1622]579  TRY
[1158]580  {
581    if (!label.isEmpty())
582    {
583      if (label.extent(0) != n)
[2291]584        if (generateError) ERROR("CAxis::checkLabel(void)",
585                              << "The label array of the axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] must be of dimension of axis size." << std::endl
586                              << "Axis size is " << n.getValue() << "." << std::endl
587                              << "label size is "<< label.extent(0)<<  " .")
588        else return false ;
[2507]589      hasLabel_ = true;
[1158]590    }
[2507]591    else hasLabel_ = false;
[2291]592    return true ;
[1158]593  }
[1622]594  CATCH_DUMP_ATTR
[1202]595
[2291]596
597  size_t CAxis::getGlobalWrittenSize(void)
598  {
599    return n_glo ;
600  }
601
602   
603
[1956]604 
[1235]605  /*!
606    Dispatch event from the lower communication layer then process event according to its type
607  */
608  bool CAxis::dispatchEvent(CEventServer& event)
[1622]609  TRY
[1235]610  {
611     if (SuperClass::dispatchEvent(event)) return true;
612     else
613     {
614       switch(event.type)
615       {
[1930]616         case EVENT_ID_AXIS_DISTRIBUTION:
617           recvAxisDistribution(event);
618           return true;
619           break;
620         case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE:
[1235]621           recvDistributedAttributes(event);
622           return true;
623           break;
624          default :
625            ERROR("bool CAxis::dispatchEvent(CEventServer& event)",
626                   << "Unknown Event");
627          return false;
628        }
629     }
630  }
[1622]631  CATCH
[567]632
[1975]633   /* to remove later when reimplementing coupling */
[1875]634   void CAxis::sendAxisToCouplerOut(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid, const string& fieldId, int posInGrid)
635   {
[1975]636     if (sendAxisToCouplerOut_done_.count(client)!=0) return ;
637     else sendAxisToCouplerOut_done_.insert(client) ;
[1875]638     
639     string axisId="_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ;
640
641    }
642
[2022]643  string CAxis::getCouplingAlias(const string& fieldId, int posInGrid)
644  {
645    return "_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ;
646  }
647
[1875]648  void CAxis::makeAliasForCoupling(const string& fieldId, int posInGrid)
649  {
[2022]650    const string axisId = getCouplingAlias(fieldId,posInGrid)  ;
[1875]651    this->createAlias(axisId) ;
652  }
653
[1975]654 
[1144]655  /*!
[1158]656    Compare two axis objects.
657    They are equal if only if they have identical attributes as well as their values.
658    Moreover, they must have the same transformations.
659  \param [in] axis Compared axis
660  \return result of the comparison
661  */
662  bool CAxis::isEqual(CAxis* obj)
[1622]663  TRY
[1158]664  {
665    vector<StdString> excludedAttr;
666    excludedAttr.push_back("axis_ref");
[987]667
[1158]668    bool objEqual = SuperClass::isEqual(obj, excludedAttr);   
669    if (!objEqual) return objEqual;
670
671    TransMapTypes thisTrans = this->getAllTransformations();
672    TransMapTypes objTrans  = obj->getAllTransformations();
673
674    TransMapTypes::const_iterator it, itb, ite;
675    std::vector<ETranformationType> thisTransType, objTransType;
676    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
677      thisTransType.push_back(it->first);
678    for (it = objTrans.begin(); it != objTrans.end(); ++it)
679      objTransType.push_back(it->first);
680
681    if (thisTransType.size() != objTransType.size()) return false;
682    for (int idx = 0; idx < thisTransType.size(); ++idx)
683      objEqual &= (thisTransType[idx] == objTransType[idx]);
684
685    return objEqual;
686  }
[1622]687  CATCH_DUMP_ATTR
[1158]688
[1235]689  /*
690    Add transformation into axis. This function only servers for Fortran interface
691    \param [in] transType transformation type
692    \param [in] id identifier of the transformation object
693  */
[836]694  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
[1622]695  TRY
[836]696  {
697    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
698    return transformationMap_.back().second;
699  }
[1622]700  CATCH_DUMP_ATTR
[836]701
[1235]702  /*
703    Check whether an axis has (spatial) transformation
704  */
[619]705  bool CAxis::hasTransformation()
[1622]706  TRY
[619]707  {
[621]708    return (!transformationMap_.empty());
[619]709  }
[1622]710  CATCH_DUMP_ATTR
[619]711
[1235]712  /*
713    Set transformation
714    \param [in] axisTrans transformation to set
715  */
[621]716  void CAxis::setTransformations(const TransMapTypes& axisTrans)
[1622]717  TRY
[619]718  {
[621]719    transformationMap_ = axisTrans;
[619]720  }
[1622]721  CATCH_DUMP_ATTR
[619]722
[1235]723  /*
724    Return all transformation held by the axis
725    \return transformation the axis has
726  */
[621]727  CAxis::TransMapTypes CAxis::getAllTransformations(void)
[1622]728  TRY
[620]729  {
[621]730    return transformationMap_;
731  }
[1622]732  CATCH_DUMP_ATTR
[620]733
[1235]734  /*
735    Duplicate transformation of another axis
736    \param [in] src axis whose transformations are copied
737  */
[823]738  void CAxis::duplicateTransformation(CAxis* src)
[1622]739  TRY
[823]740  {
741    if (src->hasTransformation())
742    {
743      this->setTransformations(src->getAllTransformations());
744    }
745  }
[1622]746  CATCH_DUMP_ATTR
[823]747
[747]748  /*!
749   * Go through the hierarchy to find the axis from which the transformations must be inherited
750   */
[1984]751  void CAxis::solveInheritanceTransformation_old()
[1622]752  TRY
[619]753  {
[747]754    if (hasTransformation() || !hasDirectAxisReference())
755      return;
[619]756
[747]757    CAxis* axis = this;
[619]758    std::vector<CAxis*> refAxis;
[747]759    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
[619]760    {
[747]761      refAxis.push_back(axis);
762      axis = axis->getDirectAxisReference();
[619]763    }
764
[747]765    if (axis->hasTransformation())
766      for (size_t i = 0; i < refAxis.size(); ++i)
767        refAxis[i]->setTransformations(axis->getAllTransformations());
[619]768  }
[1622]769  CATCH_DUMP_ATTR
[619]770
[1984]771  void CAxis::solveInheritanceTransformation()
772  TRY
773  {
774    if (solveInheritanceTransformation_done_) return;
775    else solveInheritanceTransformation_done_=true ;
776
777    CAxis* axis = this;
778    std::list<CAxis*> refAxis;
779    bool out=false ;
780    vector<StdString> excludedAttr;
781    excludedAttr.push_back("axis_ref");
782   
783    refAxis.push_front(axis) ;
784    while (axis->hasDirectAxisReference() && !out)
785    {
786      CAxis* lastAxis=axis ;
787      axis = axis->getDirectAxisReference();
788      axis->solveRefInheritance() ;
789      if (!axis->SuperClass::isEqual(lastAxis,excludedAttr)) out=true ;
790      refAxis.push_front(axis) ;
791    }
792
793    CTransformationPaths::TPath path ;
794    auto& pathList = std::get<2>(path) ;
795    std::get<0>(path) = EElement::AXIS ;
796    std::get<1>(path) = refAxis.front()->getId() ;
797    for (auto& axis : refAxis)
798    {
799      CAxis::TransMapTypes transformations = axis->getAllTransformations();
800      for(auto& transformation : transformations) pathList.push_back({transformation.second->getTransformationType(), 
801                                                                      transformation.second->getId()}) ;
802    }
803    transformationPaths_.addPath(path) ;
804
805  }
806  CATCH_DUMP_ATTR
807
[2206]808  bool CAxis::activateFieldWorkflow(CGarbageCollector& gc)
809  TRY
810  {
811    if (!axis_ref.isEmpty())
812    {
813      CField* field=getFieldFromId(axis_ref) ;
814      if (field!=nullptr)
815      {
816        bool ret = field->buildWorkflowGraph(gc) ;
817        if (!ret) return false ; // cannot build workflow graph at this state
818      }
819      else 
820      {
821        CAxis* axis = get(axis_ref) ;
822        bool ret = axis->activateFieldWorkflow(gc) ;
823        if (!ret) return false ; // cannot build workflow graph at this state
824        axis_ref=axis->getId() ; // replace domain_ref by solved reference
825      }
826    }
827    activateFieldWorkflow_done_=true ;
828    return true ;
829  }
830  CATCH_DUMP_ATTR
831
832
[1345]833  void CAxis::setContextClient(CContextClient* contextClient)
[1622]834  TRY
[1345]835  {
[1353]836    if (clientsSet.find(contextClient)==clientsSet.end())
837    {
838      clients.push_back(contextClient) ;
839      clientsSet.insert(contextClient);
840    }
[1622]841  }
842  CATCH_DUMP_ATTR
[1345]843
[619]844  void CAxis::parse(xml::CXMLNode & node)
[1622]845  TRY
[619]846  {
847    SuperClass::parse(node);
848
849    if (node.goToChildElement())
850    {
[836]851      StdString nodeElementName;
[619]852      do
853      {
[784]854        StdString nodeId("");
855        if (node.getAttributes().end() != node.getAttributes().find("id"))
856        { nodeId = node.getAttributes()["id"]; }
857
[836]858        nodeElementName = node.getElementName();
859        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
860        it = transformationMapList_.find(nodeElementName);
861        if (ite != it)
862        {
[2339]863          if (it->first == "zoom_axis")
864          {
865            info(0) << "WARNING : " << it->first << " is deprecated, replaced by extract_axis." << endl;
866          }
[836]867          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second,
868                                                                                                               nodeId,
869                                                                                                               &node)));
[786]870        }
[968]871        else
872        {
873          ERROR("void CAxis::parse(xml::CXMLNode & node)",
874                << "The transformation " << nodeElementName << " has not been supported yet.");
875        }
[619]876      } while (node.goToNextElement()) ;
877      node.goToParentElement();
878    }
879  }
[1622]880  CATCH_DUMP_ATTR
[619]881
[1930]882
883   //////////////////////////////////////////////////////////////////////////////////////
884   //  this part is related to distribution, element definition, views and connectors  //
885   //////////////////////////////////////////////////////////////////////////////////////
886
887   void CAxis::initializeLocalElement(void)
888   {
889      // after checkAttribute index of size n
890      int rank = CContext::getCurrent()->getIntraCommRank() ;
891     
892      CArray<size_t,1> ind(n) ;
893      for (int i=0;i<n;i++) ind(i)=index(i) ;
894
[2267]895      localElement_ = make_shared<CLocalElement>(rank, n_glo, ind) ;
[1930]896   }
897
898   void CAxis::addFullView(void)
899   {
900      CArray<int,1> index(n) ;
901      for(int i=0; i<n ; i++) index(i)=i ;
902      localElement_ -> addView(CElementView::FULL, index) ;
903   }
904
905   void CAxis::addWorkflowView(void)
906   {
907     // mask + data are included into data_index
908     int nk=data_index.numElements() ;
909     int nMask=0 ;
910     for(int k=0;k<nk;k++) if (data_index(k)>=0 && data_index(k)<n) nMask++ ;
911     
912     CArray<int,1> index(nMask) ;
913     nMask=0 ;
914     for(int k=0;k<nk;k++) 
915       if (data_index(k)>=0 && data_index(k)<n) 
916       {
917         index(nMask) = data_index(k) ;
918         nMask++ ;
919       }
920     localElement_ -> addView(CElementView::WORKFLOW, index) ;
921   }
922
923   void CAxis::addModelView(void)
924   {
925     // information for model view is stored in data_index
926     localElement_->addView(CElementView::MODEL, data_index) ;
927   }
928
929   void CAxis::computeModelToWorkflowConnector(void)
930   { 
[2267]931     shared_ptr<CLocalView> srcView=getLocalView(CElementView::MODEL) ;
932     shared_ptr<CLocalView> dstView=getLocalView(CElementView::WORKFLOW) ;
933     modelToWorkflowConnector_ = make_shared<CLocalConnector>(srcView, dstView); 
[1930]934     modelToWorkflowConnector_->computeConnector() ;
935   }
936
937
938   void CAxis::computeRemoteElement(CContextClient* client, EDistributionType type)
939  {
940    CContext* context = CContext::getCurrent();
941    map<int, CArray<size_t,1>> globalIndex ;
942
943    if (type==EDistributionType::BANDS) // Bands distribution to send to file server
944    {
[2343]945      int nbServer = client->getRemoteSize();
946      int nbClient = client->getIntraCommSize() ;
947      int rankClient = client->getIntraCommRank() ;
[1930]948      int size = nbServer / nbClient ;
949      int start ;
950      if (nbServer%nbClient > rankClient)
951      {
952       start = (size+1) * rankClient ;
953       size++ ;
954      }
955      else start = size*rankClient + nbServer%nbClient ;
956     
957      for(int i=0; i<size; i++)
958      { 
959        int rank=start+i ; 
960        size_t indSize = n_glo/nbServer ;
961        size_t indStart ;
962        if (n_glo % nbServer > rank)
963        {
964          indStart = (indSize+1) * rank ;
965          indSize++ ;
966        }
967        else indStart = indSize*rank + n_glo%nbServer ;
968       
969        auto& globalInd =  globalIndex[rank] ;
970        globalInd.resize(indSize) ;
971        for(size_t n = 0 ; n<indSize; n++) globalInd(n)=indStart+n ;
972      }
973    }
974    else if (type==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain
975    {
[2343]976      int nbServer = client->getRemoteSize();
[1930]977      size_t nglo=n_glo ;
978      CArray<size_t,1> indGlo(nglo) ;
979      for(size_t i=0;i<nglo;i++) indGlo(i) = i ;
[1939]980      for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()); 
[1930]981    }
[2267]982    remoteElement_[client] = make_shared<CDistributedElement>(n_glo, globalIndex) ;
[1930]983    remoteElement_[client]->addFullView() ;
984  }
985 
[2397]986  void CAxis::distributeToServer(CContextClient* client, bool inOut, std::map<int, CArray<size_t,1>>& globalIndexOut, std::map<int, CArray<size_t,1>>& globalIndexIn, 
[2267]987                                 shared_ptr<CScattererConnector> &scattererConnector, const string& axisId)
[1930]988  {
989    string serverAxisId = axisId.empty() ? this->getId() : axisId ;
990    CContext* context = CContext::getCurrent();
991
992    this->sendAllAttributesToServer(client, serverAxisId)  ;
993
[2304]994    auto scatteredElement = make_shared<CDistributedElement>(n_glo,globalIndexOut) ;
[2267]995    scatteredElement->addFullView() ;
996    scattererConnector = make_shared<CScattererConnector>(localElement_->getView(CElementView::FULL), scatteredElement->getView(CElementView::FULL), 
997                                                          context->getIntraComm(), client->getRemoteSize()) ;
[1956]998    scattererConnector->computeConnector() ;
[1930]999   
1000    // phase 0
1001    // send remote element to construct the full view on server, ie without hole
1002    CEventClient event0(getType(), EVENT_ID_AXIS_DISTRIBUTION);
1003    CMessage message0 ;
1004    message0<<serverAxisId<<0 ; 
1005    remoteElement_[client]->sendToServer(client,event0,message0) ; 
1006   
1007    // phase 1
1008    // send the full view of element to construct the connector which connect distributed data coming from client to the full local view
1009    CEventClient event1(getType(), EVENT_ID_AXIS_DISTRIBUTION);
1010    CMessage message1 ;
1011    message1<<serverAxisId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 
[1956]1012    scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
[1930]1013
[2267]1014    sendDistributedAttributes(client, scattererConnector, axisId) ;
[1930]1015 
1016    // phase 2 send the mask : data index + mask2D
[2304]1017    {
1018      CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize());
1019      CArray<bool,1> maskOut ;
1020      auto workflowToFull = make_shared<CLocalConnector>(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ;
1021      workflowToFull->computeConnector() ;
1022      maskIn=true ;
1023      workflowToFull->transfer(maskIn,maskOut,false) ;
[1930]1024
[2304]1025      //  prepare grid scatterer connector to send data from client to server
1026      map<int,CArray<size_t,1>> workflowGlobalIndex ;
1027      map<int,CArray<bool,1>> maskOut2 ; 
1028      scattererConnector->transfer(maskOut, maskOut2) ;
1029      scatteredElement->addView(CElementView::WORKFLOW, maskOut2) ;
1030      scatteredElement->getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ;
1031      // create new workflow view for scattered element
1032      auto clientToServerElement = make_shared<CDistributedElement>(scatteredElement->getGlobalSize(), workflowGlobalIndex) ;
1033      clientToServerElement->addFullView() ;
1034      CEventClient event2(getType(), EVENT_ID_AXIS_DISTRIBUTION);
1035      CMessage message2 ;
1036      message2<<serverAxisId<<2 ; 
1037      clientToServerElement->sendToServer(client, event2, message2) ; 
1038      clientToServerConnector_[client] = make_shared<CScattererConnector>(localElement_->getView(CElementView::WORKFLOW), clientToServerElement->getView(CElementView::FULL), 
[2267]1039                                                                        context->getIntraComm(), client->getRemoteSize()) ;
[2304]1040      clientToServerConnector_[client]->computeConnector() ;
1041    }
[1930]1042
[2304]1043    ////////////
1044    // phase 3 : compute connector to receive from server
1045    ////////////
[2397]1046    if (inOut)
[2304]1047    {
1048      auto scatteredElement = make_shared<CDistributedElement>(n_glo, globalIndexIn) ;
1049      scatteredElement->addFullView() ;
1050      auto scattererConnector = make_shared<CScattererConnector>(localElement_->getView(CElementView::FULL), scatteredElement->getView(CElementView::FULL), 
1051                                                                 context->getIntraComm(), client->getRemoteSize()) ;
1052      scattererConnector->computeConnector() ;
1053      CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize());
1054      CArray<bool,1> maskOut ;
1055      auto workflowToFull = make_shared<CLocalConnector>(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ;
1056      workflowToFull->computeConnector() ;
1057      maskIn=true ;
1058      workflowToFull->transfer(maskIn,maskOut,false) ;
[1930]1059
[2304]1060      map<int,CArray<size_t,1>> workflowGlobalIndex ;
1061      map<int,CArray<bool,1>> maskOut2 ; 
1062      scattererConnector->transfer(maskOut, maskOut2, false) ;
1063      scatteredElement->addView(CElementView::WORKFLOW, maskOut2) ;
1064      scatteredElement->getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ;
1065      auto clientToServerElement = make_shared<CDistributedElement>(scatteredElement->getGlobalSize(), workflowGlobalIndex) ;
1066      clientToServerElement->addFullView() ;
1067      CEventClient event3(getType(), EVENT_ID_AXIS_DISTRIBUTION);
1068      CMessage message3 ;
1069      message3<<serverAxisId<<3 ; 
1070      clientToServerElement->sendToServer(client, event3, message3) ; 
[1930]1071
[2304]1072      clientFromServerConnector_[client] = make_shared<CGathererConnector>(clientToServerElement->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
1073      clientFromServerConnector_[client]->computeConnector() ;     
1074    }
1075
1076//    clientFromServerConnector_[client] = make_shared<CGathererConnector>(clientToServerElement->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
1077//    clientFromServerConnector_[client]->computeConnector() ;
1078
1079
[1930]1080  }
1081
1082  void CAxis::recvAxisDistribution(CEventServer& event)
1083  TRY
1084  {
1085    string axisId;
1086    int phasis ;
1087    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> phasis ;
1088    get(axisId)->receivedAxisDistribution(event, phasis);
1089  }
1090  CATCH
1091
1092
1093  void CAxis::receivedAxisDistribution(CEventServer& event, int phasis)
1094  TRY
1095  {
1096    CContext* context = CContext::getCurrent();
1097    if (phasis==0) // receive the remote element to construct the full view
1098    {
[2267]1099      localElement_ = make_shared<CLocalElement>(context->getIntraCommRank(),event) ;
[1930]1100      localElement_->addFullView() ;
1101      // construct the local dimension and indexes
1102      auto& globalIndex=localElement_->getGlobalIndex() ;
1103      int nk=globalIndex.numElements() ;
1104      int minK=n_glo,maxK=-1 ;
1105      int nGlo=n_glo ;
1106      int indGlo ;
1107      for(int k=0;k<nk;k++)
1108      {
1109        indGlo=globalIndex(k) ;
1110        if (indGlo<minK) minK=indGlo ;
1111        if (indGlo>maxK) maxK=indGlo ;
1112      } 
1113      if (maxK>=minK) { begin=minK ; n=maxK-minK+1 ; }
1114      else {begin=0; n=0 ;}
1115
1116    }
1117    else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server
1118    {
1119      CContext* context = CContext::getCurrent();
[2267]1120      shared_ptr<CDistributedElement> elementFrom = make_shared<CDistributedElement>(event) ;
[1930]1121      elementFrom->addFullView() ;
[2267]1122      gathererConnector_ = make_shared<CGathererConnector>(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
[1930]1123      gathererConnector_->computeConnector() ; 
1124    }
1125    else if (phasis==2)
1126    {
[1956]1127//      delete gathererConnector_ ;
[2267]1128      elementFrom_ = make_shared<CDistributedElement>(event) ;
[1930]1129      elementFrom_->addFullView() ;
[2267]1130//      gathererConnector_ =  make_shared<CGathererConnector>(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
[1956]1131//      gathererConnector_ -> computeConnector() ;
[1930]1132    }
[2397]1133    else if (phasis==3) // only for server -> client
[2304]1134    {
1135      elementTo_ = make_shared<CDistributedElement>(event) ;
1136      elementTo_->addFullView() ;
1137    }
[1930]1138  }
1139  CATCH
1140
[1943]1141  void CAxis::setServerMask(CArray<bool,1>& serverMask, CContextClient* client)
1142  TRY
1143  {
1144    CContext* context = CContext::getCurrent();
1145    localElement_->addView(CElementView::WORKFLOW, serverMask) ;
1146    mask.reference(serverMask.copy()) ;
1147 
[2267]1148    serverFromClientConnector_ = make_shared<CGathererConnector>(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ;
[1943]1149    serverFromClientConnector_->computeConnector() ;
[2397]1150    elementFrom_.reset() ;
1151
1152    if (elementTo_)
1153    {
1154      serverToClientConnector_ = make_shared<CScattererConnector>(localElement_->getView(CElementView::WORKFLOW), elementTo_->getView(CElementView::FULL),
[2267]1155                                                                context->getIntraComm(), client->getRemoteSize()) ;
[2397]1156      serverToClientConnector_->computeConnector() ;
1157      elementTo_.reset() ;
1158    }
[1943]1159  }
1160  CATCH_DUMP_ATTR
1161
[2267]1162  void CAxis::sendDistributedAttributes(CContextClient* client, shared_ptr<CScattererConnector> scattererConnector, const string& axisId)
[1930]1163  {
1164    string serverAxisId = axisId.empty() ? this->getId() : axisId ;
1165    CContext* context = CContext::getCurrent();
1166
[2507]1167    if (hasValue_)
[1930]1168    {
1169      { // send level value
1170        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
1171        CMessage message ;
1172        message<<serverAxisId<<string("value") ; 
[2267]1173        scattererConnector->transfer(value, client, event,message) ;
[1930]1174      }
1175    }
1176
[2507]1177    if (hasBounds_)
[1930]1178    {
1179      { // send bounds level value
1180        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
1181        CMessage message ;
1182        message<<serverAxisId<<string("bounds") ; 
[2267]1183        scattererConnector->transfer(2, bounds, client, event,message) ;
[1930]1184      }
1185    }
1186
[2507]1187    if (hasLabel_)
[1930]1188    {
1189      { // send label
[1950]1190        // need to transform array of string (no fixed size for string) into array of array of char
1191        // to use connector to transfer
1192        // the strings must have fixed size which the maximum lenght over the string label. 
1193        int maxSize=0 ;
1194        for(int i=0; i<label.numElements();i++) 
1195          if (maxSize < label(i).size()) maxSize=label(i).size() ;
1196        MPI_Allreduce(MPI_IN_PLACE, &maxSize,1,MPI_INT,MPI_MAX, context->getIntraComm()) ;
1197        maxSize=maxSize+1 ;
1198        CArray<char,2> charArray(maxSize,label.numElements()) ;
1199        for(int j=0; j<label.numElements();j++) 
1200        {
1201          const char* str = label(j).c_str() ;
1202          int strSize=label(j).size()+1 ;
1203          for(int i=0; i<strSize; i++) charArray(i,j) = str[i] ;
1204        }
[1930]1205        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
1206        CMessage message ;
[1950]1207        message<<serverAxisId<<string("label")<<maxSize ;
[2267]1208        scattererConnector->transfer(maxSize, charArray, client, event,message) ;
[1930]1209      }
1210    }
1211  }
1212
1213  void CAxis::recvDistributedAttributes(CEventServer& event)
1214  TRY
1215  {
1216    string axisId;
1217    string type ;
1218    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> type ;
1219    get(axisId)->recvDistributedAttributes(event, type);
1220  }
1221  CATCH
1222
1223  void CAxis::recvDistributedAttributes(CEventServer& event, const string& type)
1224  TRY
1225  {
1226    if (type=="value") 
1227    {
1228      gathererConnector_->transfer(event, value, 0.); 
1229    }
1230    else if (type=="bounds")
1231    {
1232      CArray<double,1> value ;
1233      gathererConnector_->transfer(event, 2, value, 0.); 
1234      bounds.resize(2,n) ;
[1950]1235      if (bounds.numElements() > 0 ) bounds=CArray<double,2>(value.dataFirst(),shape(2,n),neverDeleteData) ; 
[1930]1236    }
1237    else if (type=="label")
1238    {
[1950]1239      int maxSize ;
1240      for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> maxSize ;
1241      CArray<char,1> value ;
1242      gathererConnector_->transfer(event, maxSize, value, '\0'); 
1243      CArray<char,2> charArray(maxSize,n) ;
1244      label.resize(n) ;
1245      if (n>0)
1246      {
1247        charArray=CArray<char,2>(value.dataFirst(),shape(maxSize,n),neverDeleteData) ;
1248        for(int j=0;j<n;j++)
1249        {
1250          int strSize ;
1251          for(int i=0;i<maxSize;i++) 
1252            if (charArray(i,j)=='\0') { strSize=i ; break; }
1253          string str(strSize,'\0') ;
1254          for(int i=0;i<strSize;i++) str[i]=charArray(i,j) ; 
1255          label(j)=str ;
1256        }
1257      } 
[1930]1258    }
1259  }
1260  CATCH
1261
[620]1262  DEFINE_REF_FUNC(Axis,axis)
[619]1263
[219]1264   ///---------------------------------------------------------------
1265
[335]1266} // namespace xios
Note: See TracBrowser for help on using the repository browser.