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

Last change on this file since 2130 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
Line 
1#include "axis.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6#include "message.hpp"
7#include "type.hpp"
8#include "context.hpp"
9#include "context_client.hpp"
10#include "context_server.hpp"
11#include "xios_spl.hpp"
12#include "server_distribution_description.hpp"
13#include "client_server_mapping_distributed.hpp"
14#include "distribution_client.hpp"
15
16namespace xios {
17
18   /// ////////////////////// Definitions ////////////////////// ///
19
20   CAxis::CAxis(void)
21      : CObjectTemplate<CAxis>()
22      , CAxisAttributes(), isChecked(false), relFiles()
23      , hasBounds(false), isCompressible_(false)
24      , transformationMap_(), hasValue(false), hasLabel(false)
25      , clients()
26   {
27   }
28
29   CAxis::CAxis(const StdString & id)
30      : CObjectTemplate<CAxis>(id)
31      , CAxisAttributes(), isChecked(false), relFiles()
32      , hasBounds(false), isCompressible_(false)
33      , transformationMap_(), hasValue(false), hasLabel(false)
34      , clients()
35   {
36   }
37
38   CAxis::~CAxis(void)
39   { /* Ne rien faire de plus */ }
40
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)
44   TRY
45   {
46     m["zoom_axis"] = TRANS_ZOOM_AXIS;
47     m["interpolate_axis"] = TRANS_INTERPOLATE_AXIS;
48     m["extract_axis"] = TRANS_EXTRACT_AXIS;
49     m["inverse_axis"] = TRANS_INVERSE_AXIS;
50     m["reduce_domain"] = TRANS_REDUCE_DOMAIN_TO_AXIS;
51     m["reduce_axis"] = TRANS_REDUCE_AXIS_TO_AXIS;
52     m["extract_domain"] = TRANS_EXTRACT_DOMAIN_TO_AXIS;
53     m["temporal_splitting"] = TRANS_TEMPORAL_SPLITTING;
54     m["duplicate_scalar"] = TRANS_DUPLICATE_SCALAR_TO_AXIS;
55
56   }
57   CATCH
58
59   ///---------------------------------------------------------------
60
61   const std::set<StdString> & CAxis::getRelFiles(void) const
62   TRY
63   {
64      return (this->relFiles);
65   }
66   CATCH
67
68   bool CAxis::IsWritten(const StdString & filename) const
69   TRY
70   {
71      return (this->relFiles.find(filename) != this->relFiles.end());
72   }
73   CATCH
74
75   bool CAxis::isWrittenCompressed(const StdString& filename) const
76   TRY
77   {
78      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
79   }
80   CATCH
81
82   bool CAxis::isDistributed(void) const
83   TRY
84   {
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));
87      // A condition to make sure that if there is only one client, axis
88      // should be considered to be distributed. This should be a temporary solution     
89      distributed |= (1 == CContext::getCurrent()->intraCommSize_);
90      return distributed;
91   }
92   CATCH
93
94   /*!
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.
99    */
100   void CAxis::computeIsCompressible(void)
101   TRY
102   {
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 ;
110   }
111   CATCH
112
113   void CAxis::addRelFile(const StdString & filename)
114   TRY
115   {
116      this->relFiles.insert(filename);
117   }
118   CATCH_DUMP_ATTR
119
120   void CAxis::addRelFileCompressed(const StdString& filename)
121   TRY
122   {
123      this->relFilesCompressed.insert(filename);
124   }
125   CATCH_DUMP_ATTR
126
127    //----------------------------------------------------------------
128
129   /*!
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    */
134   std::map<int, StdSize> CAxis::getAttributesBufferSize(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid,
135                                                         CServerDistributionDescription::ServerDistributionType distType)
136   TRY
137   {
138
139     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client);
140
141//     bool isNonDistributed = (n_glo == n);
142     bool isDistributed = (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType))
143                                 || (index.numElements() != n_glo);
144
145     if (client->isServerLeader())
146     {
147       // size estimation for sendServerAttribut
148       size_t size = 6 * sizeof(size_t);
149       // size estimation for sendNonDistributedValue
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       }
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       }
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
177     }
178
179     if (isDistributed)
180     {
181       // size estimation for sendDistributedValue
182       std::unordered_map<int, vector<size_t> >::const_iterator it, ite = indSrv_[client->serverSize].end();
183       for (it = indSrv_[client->serverSize].begin(); it != ite; ++it)
184       {
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());
190         if (hasBounds)
191           size += CArray<double,2>::size(2 * it->second.size());
192         if (hasLabel)
193           size += CArray<StdString,1>::size(it->second.size());
194
195         size += CEventClient::headerSize + getId().size() + sizeof(size_t);
196         if (size > attributesSizes[it->first])
197           attributesSizes[it->first] = size;
198       }
199     }
200     return attributesSizes;
201   }
202   CATCH_DUMP_ATTR
203
204   //----------------------------------------------------------------
205
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
212   CAxis* CAxis::createAxis()
213   TRY
214   {
215     CAxis* axis = CAxisGroup::get("axis_definition")->createChild();
216     return axis;
217   }
218   CATCH
219
220   /*!
221     Check common attributes of an axis.
222     This check should be done in the very beginning of work flow
223   */
224   void CAxis::checkAttributes(void)
225   TRY
226   {
227     if (checkAttributes_done_) return ;
228
229     CContext* context=CContext::getCurrent();
230
231     if (this->n_glo.isEmpty())
232        ERROR("CAxis::checkAttributes(void)",
233              << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
234              << "The axis is wrongly defined, attribute 'n_glo' must be specified");
235      StdSize size = this->n_glo.getValue();
236
237      if (!this->index.isEmpty())
238      {
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);         
244      }
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);
255
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        }
269      }
270
271      if (!this->value.isEmpty())
272      {
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() << ").");
279        this->hasValue = true;
280      }
281
282      this->checkBounds();
283      this->checkMask();
284      this->checkData();
285      this->checkLabel();
286      initializeLocalElement() ;
287      addFullView() ;
288      addWorkflowView() ;
289      addModelView() ;
290
291      checkAttributes_done_ = true ;
292   }
293   CATCH_DUMP_ATTR
294
295
296
297   /*!
298      Check the validity of data, fill in values if any, and apply mask.
299   */
300   void CAxis::checkData()
301   TRY
302   {
303      if (data_begin.isEmpty()) data_begin.setValue(0);
304
305      if (data_n.isEmpty())
306      {
307        data_n.setValue(n);
308      }
309      else if (data_n.getValue() < 0)
310      {
311        ERROR("CAxis::checkData(void)",
312              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
313              << "The data size should be strictly positive ('data_n' = " << data_n.getValue() << ").");
314      }
315
316      if (data_index.isEmpty())
317      {
318        data_index.resize(data_n);
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        }
331      }
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        {
342           if (data_index(i) >= 0 && data_index(i)<n)
343             if (!mask(data_index(i))) data_index(i) = -1;
344        }
345      }
346
347   }
348   CATCH_DUMP_ATTR
349
350    size_t CAxis::getGlobalWrittenSize(void)
351    {
352      return n_glo ;
353    }
354
355   /*!
356     Check validity of mask info and fill in values if any.
357   */
358   void CAxis::checkMask()
359   TRY
360   {
361      if (!mask.isEmpty())
362      {
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        }
371      }
372      else
373      {
374        mask.resize(n);
375        mask = true;
376      }
377   }
378   CATCH_DUMP_ATTR
379
380   /*!
381     Check validity of bounds info and fill in values if any.
382   */
383   void CAxis::checkBounds()
384   TRY
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) << ".");
393       hasBounds = true;
394     }
395     else hasBounds = false;
396   }
397   CATCH_DUMP_ATTR
398
399  void CAxis::checkLabel()
400  TRY
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  }
413  CATCH_DUMP_ATTR
414
415 
416  /*!
417    Dispatch event from the lower communication layer then process event according to its type
418  */
419  bool CAxis::dispatchEvent(CEventServer& event)
420  TRY
421  {
422     if (SuperClass::dispatchEvent(event)) return true;
423     else
424     {
425       switch(event.type)
426       {
427         case EVENT_ID_AXIS_DISTRIBUTION:
428           recvAxisDistribution(event);
429           return true;
430           break;
431         case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE:
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  }
442  CATCH
443
444   /* to remove later when reimplementing coupling */
445   void CAxis::sendAxisToCouplerOut(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid, const string& fieldId, int posInGrid)
446   {
447     if (sendAxisToCouplerOut_done_.count(client)!=0) return ;
448     else sendAxisToCouplerOut_done_.insert(client) ;
449     
450     string axisId="_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ;
451
452    }
453
454  string CAxis::getCouplingAlias(const string& fieldId, int posInGrid)
455  {
456    return "_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ;
457  }
458
459  void CAxis::makeAliasForCoupling(const string& fieldId, int posInGrid)
460  {
461    const string axisId = getCouplingAlias(fieldId,posInGrid)  ;
462    this->createAlias(axisId) ;
463  }
464
465 
466  /*!
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)
474  TRY
475  {
476    vector<StdString> excludedAttr;
477    excludedAttr.push_back("axis_ref");
478
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  }
498  CATCH_DUMP_ATTR
499
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  */
505  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
506  TRY
507  {
508    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
509    return transformationMap_.back().second;
510  }
511  CATCH_DUMP_ATTR
512
513  /*
514    Check whether an axis has (spatial) transformation
515  */
516  bool CAxis::hasTransformation()
517  TRY
518  {
519    return (!transformationMap_.empty());
520  }
521  CATCH_DUMP_ATTR
522
523  /*
524    Set transformation
525    \param [in] axisTrans transformation to set
526  */
527  void CAxis::setTransformations(const TransMapTypes& axisTrans)
528  TRY
529  {
530    transformationMap_ = axisTrans;
531  }
532  CATCH_DUMP_ATTR
533
534  /*
535    Return all transformation held by the axis
536    \return transformation the axis has
537  */
538  CAxis::TransMapTypes CAxis::getAllTransformations(void)
539  TRY
540  {
541    return transformationMap_;
542  }
543  CATCH_DUMP_ATTR
544
545  /*
546    Duplicate transformation of another axis
547    \param [in] src axis whose transformations are copied
548  */
549  void CAxis::duplicateTransformation(CAxis* src)
550  TRY
551  {
552    if (src->hasTransformation())
553    {
554      this->setTransformations(src->getAllTransformations());
555    }
556  }
557  CATCH_DUMP_ATTR
558
559  /*!
560   * Go through the hierarchy to find the axis from which the transformations must be inherited
561   */
562  void CAxis::solveInheritanceTransformation_old()
563  TRY
564  {
565    if (hasTransformation() || !hasDirectAxisReference())
566      return;
567
568    CAxis* axis = this;
569    std::vector<CAxis*> refAxis;
570    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
571    {
572      refAxis.push_back(axis);
573      axis = axis->getDirectAxisReference();
574    }
575
576    if (axis->hasTransformation())
577      for (size_t i = 0; i < refAxis.size(); ++i)
578        refAxis[i]->setTransformations(axis->getAllTransformations());
579  }
580  CATCH_DUMP_ATTR
581
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
619  void CAxis::setContextClient(CContextClient* contextClient)
620  TRY
621  {
622    if (clientsSet.find(contextClient)==clientsSet.end())
623    {
624      clients.push_back(contextClient) ;
625      clientsSet.insert(contextClient);
626    }
627  }
628  CATCH_DUMP_ATTR
629
630  void CAxis::parse(xml::CXMLNode & node)
631  TRY
632  {
633    SuperClass::parse(node);
634
635    if (node.goToChildElement())
636    {
637      StdString nodeElementName;
638      do
639      {
640        StdString nodeId("");
641        if (node.getAttributes().end() != node.getAttributes().find("id"))
642        { nodeId = node.getAttributes()["id"]; }
643
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)));
652        }
653        else
654        {
655          ERROR("void CAxis::parse(xml::CXMLNode & node)",
656                << "The transformation " << nodeElementName << " has not been supported yet.");
657        }
658      } while (node.goToNextElement()) ;
659      node.goToParentElement();
660    }
661  }
662  CATCH_DUMP_ATTR
663
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 ;
762      for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()); 
763    }
764    remoteElement_[client] = new CDistributedElement(n_glo, globalIndex) ;
765    remoteElement_[client]->addFullView() ;
766  }
767 
768  void CAxis::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, 
769                                 CScattererConnector* &scattererConnector, const string& axisId)
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() ;
778    scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 
779                                                 context->getIntraComm(), client->getRemoteSize()) ;
780    scattererConnector->computeConnector() ;
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() ; 
794    scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
795
796    sendDistributedAttributes(client, *scattererConnector, axisId) ;
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 ; 
809    scattererConnector->transfer(maskOut, maskOut2) ;
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) ; 
819    clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL), 
820                                                              context->getIntraComm(), client->getRemoteSize()) ;
821    clientToServerConnector_[client]->computeConnector() ;
822
823    clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
824    clientFromServerConnector_[client]->computeConnector() ;
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    {
874//      delete gathererConnector_ ;
875      elementFrom_ = new  CDistributedElement(event) ;
876      elementFrom_->addFullView() ;
877//      gathererConnector_ =  new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
878//      gathererConnector_ -> computeConnector() ;
879    }
880 
881  }
882  CATCH
883
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
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
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        }
943        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
944        CMessage message ;
945        message<<serverAxisId<<string("label")<<maxSize ;
946        scattererConnector.transfer(maxSize, charArray, client, event,message) ;
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) ;
973      if (bounds.numElements() > 0 ) bounds=CArray<double,2>(value.dataFirst(),shape(2,n),neverDeleteData) ; 
974    }
975    else if (type=="label")
976    {
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      } 
996    }
997  }
998  CATCH
999
1000  DEFINE_REF_FUNC(Axis,axis)
1001
1002   ///---------------------------------------------------------------
1003
1004} // namespace xios
Note: See TracBrowser for help on using the repository browser.