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

Last change on this file since 2343 was 2343, checked in by ymipsl, 2 years ago
  • Implement new infrastructure for transfert protocol.
  • new purelly one sided protocol is now available, the previous protocol (legacy, mix send/recv and one sided) is still available. Other specific protocol could be implemented more easilly in future.
  • switch can be operate with "transport_protocol" variable in XIOS context :

ex:
<variable id="transport_protocol" type="string">one_sided</variable>

Available protocols are : one_sided, legacy or default. The default protocol is "legacy".

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