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

Last change on this file since 2203 was 2203, checked in by ymipsl, 5 months ago

New functionnality : domain, axis and scalar can now be retrieve with new syntax id :
ex. for domain :

id="domainId" : old syntax, working as before
id="fieldId::domainId" : get the domain related to "domainId" associated to the field "fieldId", work if only 1 domain related to domainId is associated to the field.
id="fieldId::domainId[n]" : get the nth domain related to "domainId" associated to the field "fieldId"
id="fieldId::" : get the domain associated the the field "fieldId, work if grid associated to th field is composed with exactly 1 domain (and possibly other components axis or scalars)
id="fieldId::[n] : get the nth domain composing the grid associated to the field

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