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

Last change on this file since 2182 was 2022, checked in by ymipsl, 3 years ago

Reimplement coupling in the new infrastructure.
Tested for 2-way coupling toy model.

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.6 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
[2022]454  string CAxis::getCouplingAlias(const string& fieldId, int posInGrid)
455  {
456    return "_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ;
457  }
458
[1875]459  void CAxis::makeAliasForCoupling(const string& fieldId, int posInGrid)
460  {
[2022]461    const string axisId = getCouplingAlias(fieldId,posInGrid)  ;
[1875]462    this->createAlias(axisId) ;
463  }
464
[1975]465 
[1144]466  /*!
[1158]467    Compare two axis objects.
468    They are equal if only if they have identical attributes as well as their values.
469    Moreover, they must have the same transformations.
470  \param [in] axis Compared axis
471  \return result of the comparison
472  */
473  bool CAxis::isEqual(CAxis* obj)
[1622]474  TRY
[1158]475  {
476    vector<StdString> excludedAttr;
477    excludedAttr.push_back("axis_ref");
[987]478
[1158]479    bool objEqual = SuperClass::isEqual(obj, excludedAttr);   
480    if (!objEqual) return objEqual;
481
482    TransMapTypes thisTrans = this->getAllTransformations();
483    TransMapTypes objTrans  = obj->getAllTransformations();
484
485    TransMapTypes::const_iterator it, itb, ite;
486    std::vector<ETranformationType> thisTransType, objTransType;
487    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
488      thisTransType.push_back(it->first);
489    for (it = objTrans.begin(); it != objTrans.end(); ++it)
490      objTransType.push_back(it->first);
491
492    if (thisTransType.size() != objTransType.size()) return false;
493    for (int idx = 0; idx < thisTransType.size(); ++idx)
494      objEqual &= (thisTransType[idx] == objTransType[idx]);
495
496    return objEqual;
497  }
[1622]498  CATCH_DUMP_ATTR
[1158]499
[1235]500  /*
501    Add transformation into axis. This function only servers for Fortran interface
502    \param [in] transType transformation type
503    \param [in] id identifier of the transformation object
504  */
[836]505  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
[1622]506  TRY
[836]507  {
508    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
509    return transformationMap_.back().second;
510  }
[1622]511  CATCH_DUMP_ATTR
[836]512
[1235]513  /*
514    Check whether an axis has (spatial) transformation
515  */
[619]516  bool CAxis::hasTransformation()
[1622]517  TRY
[619]518  {
[621]519    return (!transformationMap_.empty());
[619]520  }
[1622]521  CATCH_DUMP_ATTR
[619]522
[1235]523  /*
524    Set transformation
525    \param [in] axisTrans transformation to set
526  */
[621]527  void CAxis::setTransformations(const TransMapTypes& axisTrans)
[1622]528  TRY
[619]529  {
[621]530    transformationMap_ = axisTrans;
[619]531  }
[1622]532  CATCH_DUMP_ATTR
[619]533
[1235]534  /*
535    Return all transformation held by the axis
536    \return transformation the axis has
537  */
[621]538  CAxis::TransMapTypes CAxis::getAllTransformations(void)
[1622]539  TRY
[620]540  {
[621]541    return transformationMap_;
542  }
[1622]543  CATCH_DUMP_ATTR
[620]544
[1235]545  /*
546    Duplicate transformation of another axis
547    \param [in] src axis whose transformations are copied
548  */
[823]549  void CAxis::duplicateTransformation(CAxis* src)
[1622]550  TRY
[823]551  {
552    if (src->hasTransformation())
553    {
554      this->setTransformations(src->getAllTransformations());
555    }
556  }
[1622]557  CATCH_DUMP_ATTR
[823]558
[747]559  /*!
560   * Go through the hierarchy to find the axis from which the transformations must be inherited
561   */
[1984]562  void CAxis::solveInheritanceTransformation_old()
[1622]563  TRY
[619]564  {
[747]565    if (hasTransformation() || !hasDirectAxisReference())
566      return;
[619]567
[747]568    CAxis* axis = this;
[619]569    std::vector<CAxis*> refAxis;
[747]570    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
[619]571    {
[747]572      refAxis.push_back(axis);
573      axis = axis->getDirectAxisReference();
[619]574    }
575
[747]576    if (axis->hasTransformation())
577      for (size_t i = 0; i < refAxis.size(); ++i)
578        refAxis[i]->setTransformations(axis->getAllTransformations());
[619]579  }
[1622]580  CATCH_DUMP_ATTR
[619]581
[1984]582  void CAxis::solveInheritanceTransformation()
583  TRY
584  {
585    if (solveInheritanceTransformation_done_) return;
586    else solveInheritanceTransformation_done_=true ;
587
588    CAxis* axis = this;
589    std::list<CAxis*> refAxis;
590    bool out=false ;
591    vector<StdString> excludedAttr;
592    excludedAttr.push_back("axis_ref");
593   
594    refAxis.push_front(axis) ;
595    while (axis->hasDirectAxisReference() && !out)
596    {
597      CAxis* lastAxis=axis ;
598      axis = axis->getDirectAxisReference();
599      axis->solveRefInheritance() ;
600      if (!axis->SuperClass::isEqual(lastAxis,excludedAttr)) out=true ;
601      refAxis.push_front(axis) ;
602    }
603
604    CTransformationPaths::TPath path ;
605    auto& pathList = std::get<2>(path) ;
606    std::get<0>(path) = EElement::AXIS ;
607    std::get<1>(path) = refAxis.front()->getId() ;
608    for (auto& axis : refAxis)
609    {
610      CAxis::TransMapTypes transformations = axis->getAllTransformations();
611      for(auto& transformation : transformations) pathList.push_back({transformation.second->getTransformationType(), 
612                                                                      transformation.second->getId()}) ;
613    }
614    transformationPaths_.addPath(path) ;
615
616  }
617  CATCH_DUMP_ATTR
618
[1345]619  void CAxis::setContextClient(CContextClient* contextClient)
[1622]620  TRY
[1345]621  {
[1353]622    if (clientsSet.find(contextClient)==clientsSet.end())
623    {
624      clients.push_back(contextClient) ;
625      clientsSet.insert(contextClient);
626    }
[1622]627  }
628  CATCH_DUMP_ATTR
[1345]629
[619]630  void CAxis::parse(xml::CXMLNode & node)
[1622]631  TRY
[619]632  {
633    SuperClass::parse(node);
634
635    if (node.goToChildElement())
636    {
[836]637      StdString nodeElementName;
[619]638      do
639      {
[784]640        StdString nodeId("");
641        if (node.getAttributes().end() != node.getAttributes().find("id"))
642        { nodeId = node.getAttributes()["id"]; }
643
[836]644        nodeElementName = node.getElementName();
645        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
646        it = transformationMapList_.find(nodeElementName);
647        if (ite != it)
648        {
649          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second,
650                                                                                                               nodeId,
651                                                                                                               &node)));
[786]652        }
[968]653        else
654        {
655          ERROR("void CAxis::parse(xml::CXMLNode & node)",
656                << "The transformation " << nodeElementName << " has not been supported yet.");
657        }
[619]658      } while (node.goToNextElement()) ;
659      node.goToParentElement();
660    }
661  }
[1622]662  CATCH_DUMP_ATTR
[619]663
[1930]664
665   //////////////////////////////////////////////////////////////////////////////////////
666   //  this part is related to distribution, element definition, views and connectors  //
667   //////////////////////////////////////////////////////////////////////////////////////
668
669   void CAxis::initializeLocalElement(void)
670   {
671      // after checkAttribute index of size n
672      int rank = CContext::getCurrent()->getIntraCommRank() ;
673     
674      CArray<size_t,1> ind(n) ;
675      for (int i=0;i<n;i++) ind(i)=index(i) ;
676
677      localElement_ = new CLocalElement(rank, n_glo, ind) ;
678   }
679
680   void CAxis::addFullView(void)
681   {
682      CArray<int,1> index(n) ;
683      for(int i=0; i<n ; i++) index(i)=i ;
684      localElement_ -> addView(CElementView::FULL, index) ;
685   }
686
687   void CAxis::addWorkflowView(void)
688   {
689     // mask + data are included into data_index
690     int nk=data_index.numElements() ;
691     int nMask=0 ;
692     for(int k=0;k<nk;k++) if (data_index(k)>=0 && data_index(k)<n) nMask++ ;
693     
694     CArray<int,1> index(nMask) ;
695     nMask=0 ;
696     for(int k=0;k<nk;k++) 
697       if (data_index(k)>=0 && data_index(k)<n) 
698       {
699         index(nMask) = data_index(k) ;
700         nMask++ ;
701       }
702     localElement_ -> addView(CElementView::WORKFLOW, index) ;
703   }
704
705   void CAxis::addModelView(void)
706   {
707     // information for model view is stored in data_index
708     localElement_->addView(CElementView::MODEL, data_index) ;
709   }
710
711   void CAxis::computeModelToWorkflowConnector(void)
712   { 
713     CLocalView* srcView=getLocalView(CElementView::MODEL) ;
714     CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ;
715     modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 
716     modelToWorkflowConnector_->computeConnector() ;
717   }
718
719
720   void CAxis::computeRemoteElement(CContextClient* client, EDistributionType type)
721  {
722    CContext* context = CContext::getCurrent();
723    map<int, CArray<size_t,1>> globalIndex ;
724
725    if (type==EDistributionType::BANDS) // Bands distribution to send to file server
726    {
727      int nbServer = client->serverSize;
728      int nbClient = client->clientSize ;
729      int rankClient = client->clientRank ;
730      int size = nbServer / nbClient ;
731      int start ;
732      if (nbServer%nbClient > rankClient)
733      {
734       start = (size+1) * rankClient ;
735       size++ ;
736      }
737      else start = size*rankClient + nbServer%nbClient ;
738     
739      for(int i=0; i<size; i++)
740      { 
741        int rank=start+i ; 
742        size_t indSize = n_glo/nbServer ;
743        size_t indStart ;
744        if (n_glo % nbServer > rank)
745        {
746          indStart = (indSize+1) * rank ;
747          indSize++ ;
748        }
749        else indStart = indSize*rank + n_glo%nbServer ;
750       
751        auto& globalInd =  globalIndex[rank] ;
752        globalInd.resize(indSize) ;
753        for(size_t n = 0 ; n<indSize; n++) globalInd(n)=indStart+n ;
754      }
755    }
756    else if (type==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain
757    {
758      int nbServer = client->serverSize;
759      size_t nglo=n_glo ;
760      CArray<size_t,1> indGlo(nglo) ;
761      for(size_t i=0;i<nglo;i++) indGlo(i) = i ;
[1939]762      for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()); 
[1930]763    }
764    remoteElement_[client] = new CDistributedElement(n_glo, globalIndex) ;
765    remoteElement_[client]->addFullView() ;
766  }
767 
[1956]768  void CAxis::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, 
769                                 CScattererConnector* &scattererConnector, const string& axisId)
[1930]770  {
771    string serverAxisId = axisId.empty() ? this->getId() : axisId ;
772    CContext* context = CContext::getCurrent();
773
774    this->sendAllAttributesToServer(client, serverAxisId)  ;
775
776    CDistributedElement scatteredElement(n_glo,globalIndex) ;
777    scatteredElement.addFullView() ;
[1956]778    scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 
779                                                 context->getIntraComm(), client->getRemoteSize()) ;
780    scattererConnector->computeConnector() ;
[1930]781   
782    // phase 0
783    // send remote element to construct the full view on server, ie without hole
784    CEventClient event0(getType(), EVENT_ID_AXIS_DISTRIBUTION);
785    CMessage message0 ;
786    message0<<serverAxisId<<0 ; 
787    remoteElement_[client]->sendToServer(client,event0,message0) ; 
788   
789    // phase 1
790    // send the full view of element to construct the connector which connect distributed data coming from client to the full local view
791    CEventClient event1(getType(), EVENT_ID_AXIS_DISTRIBUTION);
792    CMessage message1 ;
793    message1<<serverAxisId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 
[1956]794    scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
[1930]795
[1956]796    sendDistributedAttributes(client, *scattererConnector, axisId) ;
[1930]797 
798    // phase 2 send the mask : data index + mask2D
799    CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize());
800    CArray<bool,1> maskOut ;
801    CLocalConnector workflowToFull(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ;
802    workflowToFull.computeConnector() ;
803    maskIn=true ;
804    workflowToFull.transfer(maskIn,maskOut,false) ;
805
806    // phase 3 : prepare grid scatterer connector to send data from client to server
807    map<int,CArray<size_t,1>> workflowGlobalIndex ;
808    map<int,CArray<bool,1>> maskOut2 ; 
[1956]809    scattererConnector->transfer(maskOut, maskOut2) ;
[1930]810    scatteredElement.addView(CElementView::WORKFLOW, maskOut2) ;
811    scatteredElement.getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ;
812    // create new workflow view for scattered element
813    CDistributedElement clientToServerElement(scatteredElement.getGlobalSize(), workflowGlobalIndex) ;
814    clientToServerElement.addFullView() ;
815    CEventClient event2(getType(), EVENT_ID_AXIS_DISTRIBUTION);
816    CMessage message2 ;
817    message2<<serverAxisId<<2 ; 
818    clientToServerElement.sendToServer(client, event2, message2) ; 
[1943]819    clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL), 
820                                                              context->getIntraComm(), client->getRemoteSize()) ;
[1930]821    clientToServerConnector_[client]->computeConnector() ;
822
[1934]823    clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
824    clientFromServerConnector_[client]->computeConnector() ;
[1930]825
826
827  }
828
829  void CAxis::recvAxisDistribution(CEventServer& event)
830  TRY
831  {
832    string axisId;
833    int phasis ;
834    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> phasis ;
835    get(axisId)->receivedAxisDistribution(event, phasis);
836  }
837  CATCH
838
839
840  void CAxis::receivedAxisDistribution(CEventServer& event, int phasis)
841  TRY
842  {
843    CContext* context = CContext::getCurrent();
844    if (phasis==0) // receive the remote element to construct the full view
845    {
846      localElement_ = new  CLocalElement(context->getIntraCommRank(),event) ;
847      localElement_->addFullView() ;
848      // construct the local dimension and indexes
849      auto& globalIndex=localElement_->getGlobalIndex() ;
850      int nk=globalIndex.numElements() ;
851      int minK=n_glo,maxK=-1 ;
852      int nGlo=n_glo ;
853      int indGlo ;
854      for(int k=0;k<nk;k++)
855      {
856        indGlo=globalIndex(k) ;
857        if (indGlo<minK) minK=indGlo ;
858        if (indGlo>maxK) maxK=indGlo ;
859      } 
860      if (maxK>=minK) { begin=minK ; n=maxK-minK+1 ; }
861      else {begin=0; n=0 ;}
862
863    }
864    else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server
865    {
866      CContext* context = CContext::getCurrent();
867      CDistributedElement* elementFrom = new  CDistributedElement(event) ;
868      elementFrom->addFullView() ;
869      gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
870      gathererConnector_->computeConnector() ; 
871    }
872    else if (phasis==2)
873    {
[1956]874//      delete gathererConnector_ ;
[1930]875      elementFrom_ = new  CDistributedElement(event) ;
876      elementFrom_->addFullView() ;
[1956]877//      gathererConnector_ =  new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
878//      gathererConnector_ -> computeConnector() ;
[1930]879    }
[1943]880 
[1930]881  }
882  CATCH
883
[1943]884  void CAxis::setServerMask(CArray<bool,1>& serverMask, CContextClient* client)
885  TRY
886  {
887    CContext* context = CContext::getCurrent();
888    localElement_->addView(CElementView::WORKFLOW, serverMask) ;
889    mask.reference(serverMask.copy()) ;
890 
891    serverFromClientConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ;
892    serverFromClientConnector_->computeConnector() ;
893     
894    serverToClientConnector_ = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL),
895                                                         context->getIntraComm(), client->getRemoteSize()) ;
896    serverToClientConnector_->computeConnector() ;
897  }
898  CATCH_DUMP_ATTR
899
[1930]900  void CAxis::sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& axisId)
901  {
902    string serverAxisId = axisId.empty() ? this->getId() : axisId ;
903    CContext* context = CContext::getCurrent();
904
905    if (hasValue)
906    {
907      { // send level value
908        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
909        CMessage message ;
910        message<<serverAxisId<<string("value") ; 
911        scattererConnector.transfer(value, client, event,message) ;
912      }
913    }
914
915    if (hasBounds)
916    {
917      { // send bounds level value
918        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
919        CMessage message ;
920        message<<serverAxisId<<string("bounds") ; 
921        scattererConnector.transfer(2, bounds, client, event,message) ;
922      }
923    }
924
925    if (hasLabel)
926    {
927      { // send label
[1950]928        // need to transform array of string (no fixed size for string) into array of array of char
929        // to use connector to transfer
930        // the strings must have fixed size which the maximum lenght over the string label. 
931        int maxSize=0 ;
932        for(int i=0; i<label.numElements();i++) 
933          if (maxSize < label(i).size()) maxSize=label(i).size() ;
934        MPI_Allreduce(MPI_IN_PLACE, &maxSize,1,MPI_INT,MPI_MAX, context->getIntraComm()) ;
935        maxSize=maxSize+1 ;
936        CArray<char,2> charArray(maxSize,label.numElements()) ;
937        for(int j=0; j<label.numElements();j++) 
938        {
939          const char* str = label(j).c_str() ;
940          int strSize=label(j).size()+1 ;
941          for(int i=0; i<strSize; i++) charArray(i,j) = str[i] ;
942        }
[1930]943        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
944        CMessage message ;
[1950]945        message<<serverAxisId<<string("label")<<maxSize ;
946        scattererConnector.transfer(maxSize, charArray, client, event,message) ;
[1930]947      }
948    }
949  }
950
951  void CAxis::recvDistributedAttributes(CEventServer& event)
952  TRY
953  {
954    string axisId;
955    string type ;
956    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> type ;
957    get(axisId)->recvDistributedAttributes(event, type);
958  }
959  CATCH
960
961  void CAxis::recvDistributedAttributes(CEventServer& event, const string& type)
962  TRY
963  {
964    if (type=="value") 
965    {
966      gathererConnector_->transfer(event, value, 0.); 
967    }
968    else if (type=="bounds")
969    {
970      CArray<double,1> value ;
971      gathererConnector_->transfer(event, 2, value, 0.); 
972      bounds.resize(2,n) ;
[1950]973      if (bounds.numElements() > 0 ) bounds=CArray<double,2>(value.dataFirst(),shape(2,n),neverDeleteData) ; 
[1930]974    }
975    else if (type=="label")
976    {
[1950]977      int maxSize ;
978      for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> maxSize ;
979      CArray<char,1> value ;
980      gathererConnector_->transfer(event, maxSize, value, '\0'); 
981      CArray<char,2> charArray(maxSize,n) ;
982      label.resize(n) ;
983      if (n>0)
984      {
985        charArray=CArray<char,2>(value.dataFirst(),shape(maxSize,n),neverDeleteData) ;
986        for(int j=0;j<n;j++)
987        {
988          int strSize ;
989          for(int i=0;i<maxSize;i++) 
990            if (charArray(i,j)=='\0') { strSize=i ; break; }
991          string str(strSize,'\0') ;
992          for(int i=0;i<strSize;i++) str[i]=charArray(i,j) ; 
993          label(j)=str ;
994        }
995      } 
[1930]996    }
997  }
998  CATCH
999
[620]1000  DEFINE_REF_FUNC(Axis,axis)
[619]1001
[219]1002   ///---------------------------------------------------------------
1003
[335]1004} // namespace xios
Note: See TracBrowser for help on using the repository browser.