source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp @ 2002

Last change on this file since 2002 was 1984, checked in by ymipsl, 4 years ago

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