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

Last change on this file since 1984 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
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  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
460 
461  /*!
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)
469  TRY
470  {
471    vector<StdString> excludedAttr;
472    excludedAttr.push_back("axis_ref");
473
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  }
493  CATCH_DUMP_ATTR
494
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  */
500  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
501  TRY
502  {
503    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
504    return transformationMap_.back().second;
505  }
506  CATCH_DUMP_ATTR
507
508  /*
509    Check whether an axis has (spatial) transformation
510  */
511  bool CAxis::hasTransformation()
512  TRY
513  {
514    return (!transformationMap_.empty());
515  }
516  CATCH_DUMP_ATTR
517
518  /*
519    Set transformation
520    \param [in] axisTrans transformation to set
521  */
522  void CAxis::setTransformations(const TransMapTypes& axisTrans)
523  TRY
524  {
525    transformationMap_ = axisTrans;
526  }
527  CATCH_DUMP_ATTR
528
529  /*
530    Return all transformation held by the axis
531    \return transformation the axis has
532  */
533  CAxis::TransMapTypes CAxis::getAllTransformations(void)
534  TRY
535  {
536    return transformationMap_;
537  }
538  CATCH_DUMP_ATTR
539
540  /*
541    Duplicate transformation of another axis
542    \param [in] src axis whose transformations are copied
543  */
544  void CAxis::duplicateTransformation(CAxis* src)
545  TRY
546  {
547    if (src->hasTransformation())
548    {
549      this->setTransformations(src->getAllTransformations());
550    }
551  }
552  CATCH_DUMP_ATTR
553
554  /*!
555   * Go through the hierarchy to find the axis from which the transformations must be inherited
556   */
557  void CAxis::solveInheritanceTransformation_old()
558  TRY
559  {
560    if (hasTransformation() || !hasDirectAxisReference())
561      return;
562
563    CAxis* axis = this;
564    std::vector<CAxis*> refAxis;
565    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
566    {
567      refAxis.push_back(axis);
568      axis = axis->getDirectAxisReference();
569    }
570
571    if (axis->hasTransformation())
572      for (size_t i = 0; i < refAxis.size(); ++i)
573        refAxis[i]->setTransformations(axis->getAllTransformations());
574  }
575  CATCH_DUMP_ATTR
576
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
614  void CAxis::setContextClient(CContextClient* contextClient)
615  TRY
616  {
617    if (clientsSet.find(contextClient)==clientsSet.end())
618    {
619      clients.push_back(contextClient) ;
620      clientsSet.insert(contextClient);
621    }
622  }
623  CATCH_DUMP_ATTR
624
625  void CAxis::parse(xml::CXMLNode & node)
626  TRY
627  {
628    SuperClass::parse(node);
629
630    if (node.goToChildElement())
631    {
632      StdString nodeElementName;
633      do
634      {
635        StdString nodeId("");
636        if (node.getAttributes().end() != node.getAttributes().find("id"))
637        { nodeId = node.getAttributes()["id"]; }
638
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)));
647        }
648        else
649        {
650          ERROR("void CAxis::parse(xml::CXMLNode & node)",
651                << "The transformation " << nodeElementName << " has not been supported yet.");
652        }
653      } while (node.goToNextElement()) ;
654      node.goToParentElement();
655    }
656  }
657  CATCH_DUMP_ATTR
658
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 ;
757      for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()); 
758    }
759    remoteElement_[client] = new CDistributedElement(n_glo, globalIndex) ;
760    remoteElement_[client]->addFullView() ;
761  }
762 
763  void CAxis::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, 
764                                 CScattererConnector* &scattererConnector, const string& axisId)
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() ;
773    scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 
774                                                 context->getIntraComm(), client->getRemoteSize()) ;
775    scattererConnector->computeConnector() ;
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() ; 
789    scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
790
791    sendDistributedAttributes(client, *scattererConnector, axisId) ;
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 ; 
804    scattererConnector->transfer(maskOut, maskOut2) ;
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) ; 
814    clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL), 
815                                                              context->getIntraComm(), client->getRemoteSize()) ;
816    clientToServerConnector_[client]->computeConnector() ;
817
818    clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
819    clientFromServerConnector_[client]->computeConnector() ;
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    {
869//      delete gathererConnector_ ;
870      elementFrom_ = new  CDistributedElement(event) ;
871      elementFrom_->addFullView() ;
872//      gathererConnector_ =  new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
873//      gathererConnector_ -> computeConnector() ;
874    }
875 
876  }
877  CATCH
878
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
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
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        }
938        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
939        CMessage message ;
940        message<<serverAxisId<<string("label")<<maxSize ;
941        scattererConnector.transfer(maxSize, charArray, client, event,message) ;
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) ;
968      if (bounds.numElements() > 0 ) bounds=CArray<double,2>(value.dataFirst(),shape(2,n),neverDeleteData) ; 
969    }
970    else if (type=="label")
971    {
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      } 
991    }
992  }
993  CATCH
994
995  DEFINE_REF_FUNC(Axis,axis)
996
997   ///---------------------------------------------------------------
998
999} // namespace xios
Note: See TracBrowser for help on using the repository browser.