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

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

Big cleaning on XIOS coupling branch
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: 32.3 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()
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::setContextClient(CContextClient* contextClient)
578  TRY
579  {
580    if (clientsSet.find(contextClient)==clientsSet.end())
581    {
582      clients.push_back(contextClient) ;
583      clientsSet.insert(contextClient);
584    }
585  }
586  CATCH_DUMP_ATTR
587
588  void CAxis::parse(xml::CXMLNode & node)
589  TRY
590  {
591    SuperClass::parse(node);
592
593    if (node.goToChildElement())
594    {
595      StdString nodeElementName;
596      do
597      {
598        StdString nodeId("");
599        if (node.getAttributes().end() != node.getAttributes().find("id"))
600        { nodeId = node.getAttributes()["id"]; }
601
602        nodeElementName = node.getElementName();
603        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
604        it = transformationMapList_.find(nodeElementName);
605        if (ite != it)
606        {
607          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second,
608                                                                                                               nodeId,
609                                                                                                               &node)));
610        }
611        else
612        {
613          ERROR("void CAxis::parse(xml::CXMLNode & node)",
614                << "The transformation " << nodeElementName << " has not been supported yet.");
615        }
616      } while (node.goToNextElement()) ;
617      node.goToParentElement();
618    }
619  }
620  CATCH_DUMP_ATTR
621
622
623   //////////////////////////////////////////////////////////////////////////////////////
624   //  this part is related to distribution, element definition, views and connectors  //
625   //////////////////////////////////////////////////////////////////////////////////////
626
627   void CAxis::initializeLocalElement(void)
628   {
629      // after checkAttribute index of size n
630      int rank = CContext::getCurrent()->getIntraCommRank() ;
631     
632      CArray<size_t,1> ind(n) ;
633      for (int i=0;i<n;i++) ind(i)=index(i) ;
634
635      localElement_ = new CLocalElement(rank, n_glo, ind) ;
636   }
637
638   void CAxis::addFullView(void)
639   {
640      CArray<int,1> index(n) ;
641      for(int i=0; i<n ; i++) index(i)=i ;
642      localElement_ -> addView(CElementView::FULL, index) ;
643   }
644
645   void CAxis::addWorkflowView(void)
646   {
647     // mask + data are included into data_index
648     int nk=data_index.numElements() ;
649     int nMask=0 ;
650     for(int k=0;k<nk;k++) if (data_index(k)>=0 && data_index(k)<n) nMask++ ;
651     
652     CArray<int,1> index(nMask) ;
653     nMask=0 ;
654     for(int k=0;k<nk;k++) 
655       if (data_index(k)>=0 && data_index(k)<n) 
656       {
657         index(nMask) = data_index(k) ;
658         nMask++ ;
659       }
660     localElement_ -> addView(CElementView::WORKFLOW, index) ;
661   }
662
663   void CAxis::addModelView(void)
664   {
665     // information for model view is stored in data_index
666     localElement_->addView(CElementView::MODEL, data_index) ;
667   }
668
669   void CAxis::computeModelToWorkflowConnector(void)
670   { 
671     CLocalView* srcView=getLocalView(CElementView::MODEL) ;
672     CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ;
673     modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 
674     modelToWorkflowConnector_->computeConnector() ;
675   }
676
677
678   void CAxis::computeRemoteElement(CContextClient* client, EDistributionType type)
679  {
680    CContext* context = CContext::getCurrent();
681    map<int, CArray<size_t,1>> globalIndex ;
682
683    if (type==EDistributionType::BANDS) // Bands distribution to send to file server
684    {
685      int nbServer = client->serverSize;
686      int nbClient = client->clientSize ;
687      int rankClient = client->clientRank ;
688      int size = nbServer / nbClient ;
689      int start ;
690      if (nbServer%nbClient > rankClient)
691      {
692       start = (size+1) * rankClient ;
693       size++ ;
694      }
695      else start = size*rankClient + nbServer%nbClient ;
696     
697      for(int i=0; i<size; i++)
698      { 
699        int rank=start+i ; 
700        size_t indSize = n_glo/nbServer ;
701        size_t indStart ;
702        if (n_glo % nbServer > rank)
703        {
704          indStart = (indSize+1) * rank ;
705          indSize++ ;
706        }
707        else indStart = indSize*rank + n_glo%nbServer ;
708       
709        auto& globalInd =  globalIndex[rank] ;
710        globalInd.resize(indSize) ;
711        for(size_t n = 0 ; n<indSize; n++) globalInd(n)=indStart+n ;
712      }
713    }
714    else if (type==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain
715    {
716      int nbServer = client->serverSize;
717      size_t nglo=n_glo ;
718      CArray<size_t,1> indGlo(nglo) ;
719      for(size_t i=0;i<nglo;i++) indGlo(i) = i ;
720      for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()); 
721    }
722    remoteElement_[client] = new CDistributedElement(n_glo, globalIndex) ;
723    remoteElement_[client]->addFullView() ;
724  }
725 
726  void CAxis::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, 
727                                 CScattererConnector* &scattererConnector, const string& axisId)
728  {
729    string serverAxisId = axisId.empty() ? this->getId() : axisId ;
730    CContext* context = CContext::getCurrent();
731
732    this->sendAllAttributesToServer(client, serverAxisId)  ;
733
734    CDistributedElement scatteredElement(n_glo,globalIndex) ;
735    scatteredElement.addFullView() ;
736    scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 
737                                                 context->getIntraComm(), client->getRemoteSize()) ;
738    scattererConnector->computeConnector() ;
739   
740    // phase 0
741    // send remote element to construct the full view on server, ie without hole
742    CEventClient event0(getType(), EVENT_ID_AXIS_DISTRIBUTION);
743    CMessage message0 ;
744    message0<<serverAxisId<<0 ; 
745    remoteElement_[client]->sendToServer(client,event0,message0) ; 
746   
747    // phase 1
748    // send the full view of element to construct the connector which connect distributed data coming from client to the full local view
749    CEventClient event1(getType(), EVENT_ID_AXIS_DISTRIBUTION);
750    CMessage message1 ;
751    message1<<serverAxisId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 
752    scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
753
754    sendDistributedAttributes(client, *scattererConnector, axisId) ;
755 
756    // phase 2 send the mask : data index + mask2D
757    CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize());
758    CArray<bool,1> maskOut ;
759    CLocalConnector workflowToFull(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ;
760    workflowToFull.computeConnector() ;
761    maskIn=true ;
762    workflowToFull.transfer(maskIn,maskOut,false) ;
763
764    // phase 3 : prepare grid scatterer connector to send data from client to server
765    map<int,CArray<size_t,1>> workflowGlobalIndex ;
766    map<int,CArray<bool,1>> maskOut2 ; 
767    scattererConnector->transfer(maskOut, maskOut2) ;
768    scatteredElement.addView(CElementView::WORKFLOW, maskOut2) ;
769    scatteredElement.getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ;
770    // create new workflow view for scattered element
771    CDistributedElement clientToServerElement(scatteredElement.getGlobalSize(), workflowGlobalIndex) ;
772    clientToServerElement.addFullView() ;
773    CEventClient event2(getType(), EVENT_ID_AXIS_DISTRIBUTION);
774    CMessage message2 ;
775    message2<<serverAxisId<<2 ; 
776    clientToServerElement.sendToServer(client, event2, message2) ; 
777    clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL), 
778                                                              context->getIntraComm(), client->getRemoteSize()) ;
779    clientToServerConnector_[client]->computeConnector() ;
780
781    clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
782    clientFromServerConnector_[client]->computeConnector() ;
783
784
785  }
786
787  void CAxis::recvAxisDistribution(CEventServer& event)
788  TRY
789  {
790    string axisId;
791    int phasis ;
792    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> phasis ;
793    get(axisId)->receivedAxisDistribution(event, phasis);
794  }
795  CATCH
796
797
798  void CAxis::receivedAxisDistribution(CEventServer& event, int phasis)
799  TRY
800  {
801    CContext* context = CContext::getCurrent();
802    if (phasis==0) // receive the remote element to construct the full view
803    {
804      localElement_ = new  CLocalElement(context->getIntraCommRank(),event) ;
805      localElement_->addFullView() ;
806      // construct the local dimension and indexes
807      auto& globalIndex=localElement_->getGlobalIndex() ;
808      int nk=globalIndex.numElements() ;
809      int minK=n_glo,maxK=-1 ;
810      int nGlo=n_glo ;
811      int indGlo ;
812      for(int k=0;k<nk;k++)
813      {
814        indGlo=globalIndex(k) ;
815        if (indGlo<minK) minK=indGlo ;
816        if (indGlo>maxK) maxK=indGlo ;
817      } 
818      if (maxK>=minK) { begin=minK ; n=maxK-minK+1 ; }
819      else {begin=0; n=0 ;}
820
821    }
822    else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server
823    {
824      CContext* context = CContext::getCurrent();
825      CDistributedElement* elementFrom = new  CDistributedElement(event) ;
826      elementFrom->addFullView() ;
827      gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
828      gathererConnector_->computeConnector() ; 
829    }
830    else if (phasis==2)
831    {
832//      delete gathererConnector_ ;
833      elementFrom_ = new  CDistributedElement(event) ;
834      elementFrom_->addFullView() ;
835//      gathererConnector_ =  new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
836//      gathererConnector_ -> computeConnector() ;
837    }
838 
839  }
840  CATCH
841
842  void CAxis::setServerMask(CArray<bool,1>& serverMask, CContextClient* client)
843  TRY
844  {
845    CContext* context = CContext::getCurrent();
846    localElement_->addView(CElementView::WORKFLOW, serverMask) ;
847    mask.reference(serverMask.copy()) ;
848 
849    serverFromClientConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ;
850    serverFromClientConnector_->computeConnector() ;
851     
852    serverToClientConnector_ = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL),
853                                                         context->getIntraComm(), client->getRemoteSize()) ;
854    serverToClientConnector_->computeConnector() ;
855  }
856  CATCH_DUMP_ATTR
857
858  void CAxis::sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& axisId)
859  {
860    string serverAxisId = axisId.empty() ? this->getId() : axisId ;
861    CContext* context = CContext::getCurrent();
862
863    if (hasValue)
864    {
865      { // send level value
866        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
867        CMessage message ;
868        message<<serverAxisId<<string("value") ; 
869        scattererConnector.transfer(value, client, event,message) ;
870      }
871    }
872
873    if (hasBounds)
874    {
875      { // send bounds level value
876        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
877        CMessage message ;
878        message<<serverAxisId<<string("bounds") ; 
879        scattererConnector.transfer(2, bounds, client, event,message) ;
880      }
881    }
882
883    if (hasLabel)
884    {
885      { // send label
886        // need to transform array of string (no fixed size for string) into array of array of char
887        // to use connector to transfer
888        // the strings must have fixed size which the maximum lenght over the string label. 
889        int maxSize=0 ;
890        for(int i=0; i<label.numElements();i++) 
891          if (maxSize < label(i).size()) maxSize=label(i).size() ;
892        MPI_Allreduce(MPI_IN_PLACE, &maxSize,1,MPI_INT,MPI_MAX, context->getIntraComm()) ;
893        maxSize=maxSize+1 ;
894        CArray<char,2> charArray(maxSize,label.numElements()) ;
895        for(int j=0; j<label.numElements();j++) 
896        {
897          const char* str = label(j).c_str() ;
898          int strSize=label(j).size()+1 ;
899          for(int i=0; i<strSize; i++) charArray(i,j) = str[i] ;
900        }
901        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
902        CMessage message ;
903        message<<serverAxisId<<string("label")<<maxSize ;
904        scattererConnector.transfer(maxSize, charArray, client, event,message) ;
905      }
906    }
907  }
908
909  void CAxis::recvDistributedAttributes(CEventServer& event)
910  TRY
911  {
912    string axisId;
913    string type ;
914    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> type ;
915    get(axisId)->recvDistributedAttributes(event, type);
916  }
917  CATCH
918
919  void CAxis::recvDistributedAttributes(CEventServer& event, const string& type)
920  TRY
921  {
922    if (type=="value") 
923    {
924      gathererConnector_->transfer(event, value, 0.); 
925    }
926    else if (type=="bounds")
927    {
928      CArray<double,1> value ;
929      gathererConnector_->transfer(event, 2, value, 0.); 
930      bounds.resize(2,n) ;
931      if (bounds.numElements() > 0 ) bounds=CArray<double,2>(value.dataFirst(),shape(2,n),neverDeleteData) ; 
932    }
933    else if (type=="label")
934    {
935      int maxSize ;
936      for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> maxSize ;
937      CArray<char,1> value ;
938      gathererConnector_->transfer(event, maxSize, value, '\0'); 
939      CArray<char,2> charArray(maxSize,n) ;
940      label.resize(n) ;
941      if (n>0)
942      {
943        charArray=CArray<char,2>(value.dataFirst(),shape(maxSize,n),neverDeleteData) ;
944        for(int j=0;j<n;j++)
945        {
946          int strSize ;
947          for(int i=0;i<maxSize;i++) 
948            if (charArray(i,j)=='\0') { strSize=i ; break; }
949          string str(strSize,'\0') ;
950          for(int i=0;i<strSize;i++) str[i]=charArray(i,j) ; 
951          label(j)=str ;
952        }
953      } 
954    }
955  }
956  CATCH
957
958  DEFINE_REF_FUNC(Axis,axis)
959
960   ///---------------------------------------------------------------
961
962} // namespace xios
Note: See TracBrowser for help on using the repository browser.