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

Last change on this file since 2274 was 2274, checked in by ymipsl, 3 years ago

Tracking memory leak : release memory statically alocated

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: 36.5 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   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->serverSize].end();
193       for (it = indSrv_[client->serverSize].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   void CAxis::checkAttributes(void)
279   TRY
280   {
281     if (checkAttributes_done_) return ;
282
283     CContext* context=CContext::getCurrent();
284
285     if (this->n_glo.isEmpty())
286        ERROR("CAxis::checkAttributes(void)",
287              << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
288              << "The axis is wrongly defined, attribute 'n_glo' must be specified");
289      StdSize size = this->n_glo.getValue();
290
291      if (!this->index.isEmpty())
292      {
293        if (n.isEmpty()) n = index.numElements();
294
295        // It's not so correct but if begin is not the first value of index
296        // then data on the local axis has user-defined distribution. In this case, begin has no meaning.
297        if (begin.isEmpty()) begin = index(0);         
298      }
299      else 
300      {
301        if (!this->begin.isEmpty())
302        {
303          if (begin < 0 || begin > size - 1)
304            ERROR("CAxis::checkAttributes(void)",
305                  << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
306                  << "The axis is wrongly defined, attribute 'begin' (" << begin.getValue() << ") must be non-negative and smaller than size-1 (" << size - 1 << ").");
307        }
308        else this->begin.setValue(0);
309
310        if (!this->n.isEmpty())
311        {
312          if (n < 0 || n > size)
313            ERROR("CAxis::checkAttributes(void)",
314                  << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
315                  << "The axis is wrongly defined, attribute 'n' (" << n.getValue() << ") must be non-negative and smaller than size (" << size << ").");
316        }
317        else this->n.setValue(size);
318
319        {
320          index.resize(n);
321          for (int i = 0; i < n; ++i) index(i) = i+begin;
322        }
323      }
324
325      if (!this->value.isEmpty())
326      {
327        StdSize true_size = value.numElements();
328        if (this->n.getValue() != true_size)
329          ERROR("CAxis::checkAttributes(void)",
330              << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] "
331              << "The axis is wrongly defined, attribute 'value' has a different size (" << true_size
332              << ") than the one defined by the \'size\' attribute (" << n.getValue() << ").");
333        this->hasValue = true;
334      }
335
336      this->checkBounds();
337      this->checkMask();
338      this->checkData();
339      this->checkLabel();
340      initializeLocalElement() ;
341      addFullView() ;
342      addWorkflowView() ;
343      addModelView() ;
344
345      checkAttributes_done_ = true ;
346   }
347   CATCH_DUMP_ATTR
348
349
350
351   /*!
352      Check the validity of data, fill in values if any, and apply mask.
353   */
354   void CAxis::checkData()
355   TRY
356   {
357      if (data_begin.isEmpty()) data_begin.setValue(0);
358
359      if (data_n.isEmpty())
360      {
361        data_n.setValue(n);
362      }
363      else if (data_n.getValue() < 0)
364      {
365        ERROR("CAxis::checkData(void)",
366              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
367              << "The data size should be strictly positive ('data_n' = " << data_n.getValue() << ").");
368      }
369
370      if (data_index.isEmpty())
371      {
372        data_index.resize(data_n);
373        for (int i = 0; i < data_n; ++i)
374        {
375          if ((i+data_begin) >= 0 && (i+data_begin<n))
376          {
377            if (mask(i+data_begin))
378              data_index(i) = i+data_begin;
379            else
380              data_index(i) = -1;
381          }
382          else
383            data_index(i) = -1;
384        }
385      }
386      else
387      {
388        if (data_index.numElements() != data_n)
389        {
390          ERROR("CAxis::checkData(void)",
391                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
392                << "The size of data_index = "<< data_index.numElements() << "is not equal to the data size data_n = " << data_n.getValue() << ").");
393        }
394        for (int i = 0; i < data_n; ++i)
395        {
396           if (data_index(i) >= 0 && data_index(i)<n)
397             if (!mask(data_index(i))) data_index(i) = -1;
398        }
399      }
400
401   }
402   CATCH_DUMP_ATTR
403
404    size_t CAxis::getGlobalWrittenSize(void)
405    {
406      return n_glo ;
407    }
408
409   /*!
410     Check validity of mask info and fill in values if any.
411   */
412   void CAxis::checkMask()
413   TRY
414   {
415      if (!mask.isEmpty())
416      {
417        if (mask.extent(0) != n)
418        {
419          ERROR("CAxis::checkMask(void)",
420              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
421              << "The mask does not have the same size as the local domain." << std::endl
422              << "Local size is " << n.getValue() << "." << std::endl
423              << "Mask size is " << mask.extent(0) << ".");
424        }
425      }
426      else
427      {
428        mask.resize(n);
429        mask = true;
430      }
431   }
432   CATCH_DUMP_ATTR
433
434   /*!
435     Check validity of bounds info and fill in values if any.
436   */
437   void CAxis::checkBounds()
438   TRY
439   {
440     if (!bounds.isEmpty())
441     {
442       if (bounds.extent(0) != 2 || bounds.extent(1) != n)
443         ERROR("CAxis::checkAttributes(void)",
444               << "The bounds array of the axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] must be of dimension 2 x axis size." << std::endl
445               << "Axis size is " << n.getValue() << "." << std::endl
446               << "Bounds size is "<< bounds.extent(0) << " x " << bounds.extent(1) << ".");
447       hasBounds = true;
448     }
449     else hasBounds = false;
450   }
451   CATCH_DUMP_ATTR
452
453  void CAxis::checkLabel()
454  TRY
455  {
456    if (!label.isEmpty())
457    {
458      if (label.extent(0) != n)
459        ERROR("CAxis::checkLabel(void)",
460              << "The label array of the axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] must be of dimension of axis size." << std::endl
461              << "Axis size is " << n.getValue() << "." << std::endl
462              << "label size is "<< label.extent(0)<<  " .");
463      hasLabel = true;
464    }
465    else hasLabel = false;
466  }
467  CATCH_DUMP_ATTR
468
469 
470  /*!
471    Dispatch event from the lower communication layer then process event according to its type
472  */
473  bool CAxis::dispatchEvent(CEventServer& event)
474  TRY
475  {
476     if (SuperClass::dispatchEvent(event)) return true;
477     else
478     {
479       switch(event.type)
480       {
481         case EVENT_ID_AXIS_DISTRIBUTION:
482           recvAxisDistribution(event);
483           return true;
484           break;
485         case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE:
486           recvDistributedAttributes(event);
487           return true;
488           break;
489          default :
490            ERROR("bool CAxis::dispatchEvent(CEventServer& event)",
491                   << "Unknown Event");
492          return false;
493        }
494     }
495  }
496  CATCH
497
498   /* to remove later when reimplementing coupling */
499   void CAxis::sendAxisToCouplerOut(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid, const string& fieldId, int posInGrid)
500   {
501     if (sendAxisToCouplerOut_done_.count(client)!=0) return ;
502     else sendAxisToCouplerOut_done_.insert(client) ;
503     
504     string axisId="_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ;
505
506    }
507
508  string CAxis::getCouplingAlias(const string& fieldId, int posInGrid)
509  {
510    return "_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ;
511  }
512
513  void CAxis::makeAliasForCoupling(const string& fieldId, int posInGrid)
514  {
515    const string axisId = getCouplingAlias(fieldId,posInGrid)  ;
516    this->createAlias(axisId) ;
517  }
518
519 
520  /*!
521    Compare two axis objects.
522    They are equal if only if they have identical attributes as well as their values.
523    Moreover, they must have the same transformations.
524  \param [in] axis Compared axis
525  \return result of the comparison
526  */
527  bool CAxis::isEqual(CAxis* obj)
528  TRY
529  {
530    vector<StdString> excludedAttr;
531    excludedAttr.push_back("axis_ref");
532
533    bool objEqual = SuperClass::isEqual(obj, excludedAttr);   
534    if (!objEqual) return objEqual;
535
536    TransMapTypes thisTrans = this->getAllTransformations();
537    TransMapTypes objTrans  = obj->getAllTransformations();
538
539    TransMapTypes::const_iterator it, itb, ite;
540    std::vector<ETranformationType> thisTransType, objTransType;
541    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
542      thisTransType.push_back(it->first);
543    for (it = objTrans.begin(); it != objTrans.end(); ++it)
544      objTransType.push_back(it->first);
545
546    if (thisTransType.size() != objTransType.size()) return false;
547    for (int idx = 0; idx < thisTransType.size(); ++idx)
548      objEqual &= (thisTransType[idx] == objTransType[idx]);
549
550    return objEqual;
551  }
552  CATCH_DUMP_ATTR
553
554  /*
555    Add transformation into axis. This function only servers for Fortran interface
556    \param [in] transType transformation type
557    \param [in] id identifier of the transformation object
558  */
559  CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
560  TRY
561  {
562    transformationMap_.push_back(std::make_pair(transType, CTransformation<CAxis>::createTransformation(transType,id)));
563    return transformationMap_.back().second;
564  }
565  CATCH_DUMP_ATTR
566
567  /*
568    Check whether an axis has (spatial) transformation
569  */
570  bool CAxis::hasTransformation()
571  TRY
572  {
573    return (!transformationMap_.empty());
574  }
575  CATCH_DUMP_ATTR
576
577  /*
578    Set transformation
579    \param [in] axisTrans transformation to set
580  */
581  void CAxis::setTransformations(const TransMapTypes& axisTrans)
582  TRY
583  {
584    transformationMap_ = axisTrans;
585  }
586  CATCH_DUMP_ATTR
587
588  /*
589    Return all transformation held by the axis
590    \return transformation the axis has
591  */
592  CAxis::TransMapTypes CAxis::getAllTransformations(void)
593  TRY
594  {
595    return transformationMap_;
596  }
597  CATCH_DUMP_ATTR
598
599  /*
600    Duplicate transformation of another axis
601    \param [in] src axis whose transformations are copied
602  */
603  void CAxis::duplicateTransformation(CAxis* src)
604  TRY
605  {
606    if (src->hasTransformation())
607    {
608      this->setTransformations(src->getAllTransformations());
609    }
610  }
611  CATCH_DUMP_ATTR
612
613  /*!
614   * Go through the hierarchy to find the axis from which the transformations must be inherited
615   */
616  void CAxis::solveInheritanceTransformation_old()
617  TRY
618  {
619    if (hasTransformation() || !hasDirectAxisReference())
620      return;
621
622    CAxis* axis = this;
623    std::vector<CAxis*> refAxis;
624    while (!axis->hasTransformation() && axis->hasDirectAxisReference())
625    {
626      refAxis.push_back(axis);
627      axis = axis->getDirectAxisReference();
628    }
629
630    if (axis->hasTransformation())
631      for (size_t i = 0; i < refAxis.size(); ++i)
632        refAxis[i]->setTransformations(axis->getAllTransformations());
633  }
634  CATCH_DUMP_ATTR
635
636  void CAxis::solveInheritanceTransformation()
637  TRY
638  {
639    if (solveInheritanceTransformation_done_) return;
640    else solveInheritanceTransformation_done_=true ;
641
642    CAxis* axis = this;
643    std::list<CAxis*> refAxis;
644    bool out=false ;
645    vector<StdString> excludedAttr;
646    excludedAttr.push_back("axis_ref");
647   
648    refAxis.push_front(axis) ;
649    while (axis->hasDirectAxisReference() && !out)
650    {
651      CAxis* lastAxis=axis ;
652      axis = axis->getDirectAxisReference();
653      axis->solveRefInheritance() ;
654      if (!axis->SuperClass::isEqual(lastAxis,excludedAttr)) out=true ;
655      refAxis.push_front(axis) ;
656    }
657
658    CTransformationPaths::TPath path ;
659    auto& pathList = std::get<2>(path) ;
660    std::get<0>(path) = EElement::AXIS ;
661    std::get<1>(path) = refAxis.front()->getId() ;
662    for (auto& axis : refAxis)
663    {
664      CAxis::TransMapTypes transformations = axis->getAllTransformations();
665      for(auto& transformation : transformations) pathList.push_back({transformation.second->getTransformationType(), 
666                                                                      transformation.second->getId()}) ;
667    }
668    transformationPaths_.addPath(path) ;
669
670  }
671  CATCH_DUMP_ATTR
672
673  bool CAxis::activateFieldWorkflow(CGarbageCollector& gc)
674  TRY
675  {
676    if (!axis_ref.isEmpty())
677    {
678      CField* field=getFieldFromId(axis_ref) ;
679      if (field!=nullptr)
680      {
681        bool ret = field->buildWorkflowGraph(gc) ;
682        if (!ret) return false ; // cannot build workflow graph at this state
683      }
684      else 
685      {
686        CAxis* axis = get(axis_ref) ;
687        bool ret = axis->activateFieldWorkflow(gc) ;
688        if (!ret) return false ; // cannot build workflow graph at this state
689        axis_ref=axis->getId() ; // replace domain_ref by solved reference
690      }
691    }
692    activateFieldWorkflow_done_=true ;
693    return true ;
694  }
695  CATCH_DUMP_ATTR
696
697
698  void CAxis::setContextClient(CContextClient* contextClient)
699  TRY
700  {
701    if (clientsSet.find(contextClient)==clientsSet.end())
702    {
703      clients.push_back(contextClient) ;
704      clientsSet.insert(contextClient);
705    }
706  }
707  CATCH_DUMP_ATTR
708
709  void CAxis::parse(xml::CXMLNode & node)
710  TRY
711  {
712    SuperClass::parse(node);
713
714    if (node.goToChildElement())
715    {
716      StdString nodeElementName;
717      do
718      {
719        StdString nodeId("");
720        if (node.getAttributes().end() != node.getAttributes().find("id"))
721        { nodeId = node.getAttributes()["id"]; }
722
723        nodeElementName = node.getElementName();
724        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
725        it = transformationMapList_.find(nodeElementName);
726        if (ite != it)
727        {
728          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CAxis>::createTransformation(it->second,
729                                                                                                               nodeId,
730                                                                                                               &node)));
731        }
732        else
733        {
734          ERROR("void CAxis::parse(xml::CXMLNode & node)",
735                << "The transformation " << nodeElementName << " has not been supported yet.");
736        }
737      } while (node.goToNextElement()) ;
738      node.goToParentElement();
739    }
740  }
741  CATCH_DUMP_ATTR
742
743
744   //////////////////////////////////////////////////////////////////////////////////////
745   //  this part is related to distribution, element definition, views and connectors  //
746   //////////////////////////////////////////////////////////////////////////////////////
747
748   void CAxis::initializeLocalElement(void)
749   {
750      // after checkAttribute index of size n
751      int rank = CContext::getCurrent()->getIntraCommRank() ;
752     
753      CArray<size_t,1> ind(n) ;
754      for (int i=0;i<n;i++) ind(i)=index(i) ;
755
756      localElement_ = make_shared<CLocalElement>(rank, n_glo, ind) ;
757   }
758
759   void CAxis::addFullView(void)
760   {
761      CArray<int,1> index(n) ;
762      for(int i=0; i<n ; i++) index(i)=i ;
763      localElement_ -> addView(CElementView::FULL, index) ;
764   }
765
766   void CAxis::addWorkflowView(void)
767   {
768     // mask + data are included into data_index
769     int nk=data_index.numElements() ;
770     int nMask=0 ;
771     for(int k=0;k<nk;k++) if (data_index(k)>=0 && data_index(k)<n) nMask++ ;
772     
773     CArray<int,1> index(nMask) ;
774     nMask=0 ;
775     for(int k=0;k<nk;k++) 
776       if (data_index(k)>=0 && data_index(k)<n) 
777       {
778         index(nMask) = data_index(k) ;
779         nMask++ ;
780       }
781     localElement_ -> addView(CElementView::WORKFLOW, index) ;
782   }
783
784   void CAxis::addModelView(void)
785   {
786     // information for model view is stored in data_index
787     localElement_->addView(CElementView::MODEL, data_index) ;
788   }
789
790   void CAxis::computeModelToWorkflowConnector(void)
791   { 
792     shared_ptr<CLocalView> srcView=getLocalView(CElementView::MODEL) ;
793     shared_ptr<CLocalView> dstView=getLocalView(CElementView::WORKFLOW) ;
794     modelToWorkflowConnector_ = make_shared<CLocalConnector>(srcView, dstView); 
795     modelToWorkflowConnector_->computeConnector() ;
796   }
797
798
799   void CAxis::computeRemoteElement(CContextClient* client, EDistributionType type)
800  {
801    CContext* context = CContext::getCurrent();
802    map<int, CArray<size_t,1>> globalIndex ;
803
804    if (type==EDistributionType::BANDS) // Bands distribution to send to file server
805    {
806      int nbServer = client->serverSize;
807      int nbClient = client->clientSize ;
808      int rankClient = client->clientRank ;
809      int size = nbServer / nbClient ;
810      int start ;
811      if (nbServer%nbClient > rankClient)
812      {
813       start = (size+1) * rankClient ;
814       size++ ;
815      }
816      else start = size*rankClient + nbServer%nbClient ;
817     
818      for(int i=0; i<size; i++)
819      { 
820        int rank=start+i ; 
821        size_t indSize = n_glo/nbServer ;
822        size_t indStart ;
823        if (n_glo % nbServer > rank)
824        {
825          indStart = (indSize+1) * rank ;
826          indSize++ ;
827        }
828        else indStart = indSize*rank + n_glo%nbServer ;
829       
830        auto& globalInd =  globalIndex[rank] ;
831        globalInd.resize(indSize) ;
832        for(size_t n = 0 ; n<indSize; n++) globalInd(n)=indStart+n ;
833      }
834    }
835    else if (type==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain
836    {
837      int nbServer = client->serverSize;
838      size_t nglo=n_glo ;
839      CArray<size_t,1> indGlo(nglo) ;
840      for(size_t i=0;i<nglo;i++) indGlo(i) = i ;
841      for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()); 
842    }
843    remoteElement_[client] = make_shared<CDistributedElement>(n_glo, globalIndex) ;
844    remoteElement_[client]->addFullView() ;
845  }
846 
847  void CAxis::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, 
848                                 shared_ptr<CScattererConnector> &scattererConnector, const string& axisId)
849  {
850    string serverAxisId = axisId.empty() ? this->getId() : axisId ;
851    CContext* context = CContext::getCurrent();
852
853    this->sendAllAttributesToServer(client, serverAxisId)  ;
854
855    auto scatteredElement = make_shared<CDistributedElement>(n_glo,globalIndex) ;
856    scatteredElement->addFullView() ;
857    scattererConnector = make_shared<CScattererConnector>(localElement_->getView(CElementView::FULL), scatteredElement->getView(CElementView::FULL), 
858                                                          context->getIntraComm(), client->getRemoteSize()) ;
859    scattererConnector->computeConnector() ;
860   
861    // phase 0
862    // send remote element to construct the full view on server, ie without hole
863    CEventClient event0(getType(), EVENT_ID_AXIS_DISTRIBUTION);
864    CMessage message0 ;
865    message0<<serverAxisId<<0 ; 
866    remoteElement_[client]->sendToServer(client,event0,message0) ; 
867   
868    // phase 1
869    // send the full view of element to construct the connector which connect distributed data coming from client to the full local view
870    CEventClient event1(getType(), EVENT_ID_AXIS_DISTRIBUTION);
871    CMessage message1 ;
872    message1<<serverAxisId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 
873    scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
874
875    sendDistributedAttributes(client, scattererConnector, axisId) ;
876 
877    // phase 2 send the mask : data index + mask2D
878    CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize());
879    CArray<bool,1> maskOut ;
880    auto workflowToFull = make_shared<CLocalConnector>(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ;
881    workflowToFull->computeConnector() ;
882    maskIn=true ;
883    workflowToFull->transfer(maskIn,maskOut,false) ;
884
885    // phase 3 : prepare grid scatterer connector to send data from client to server
886    map<int,CArray<size_t,1>> workflowGlobalIndex ;
887    map<int,CArray<bool,1>> maskOut2 ; 
888    scattererConnector->transfer(maskOut, maskOut2) ;
889    scatteredElement->addView(CElementView::WORKFLOW, maskOut2) ;
890    scatteredElement->getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ;
891    // create new workflow view for scattered element
892    auto clientToServerElement = make_shared<CDistributedElement>(scatteredElement->getGlobalSize(), workflowGlobalIndex) ;
893    clientToServerElement->addFullView() ;
894    CEventClient event2(getType(), EVENT_ID_AXIS_DISTRIBUTION);
895    CMessage message2 ;
896    message2<<serverAxisId<<2 ; 
897    clientToServerElement->sendToServer(client, event2, message2) ; 
898    clientToServerConnector_[client] = make_shared<CScattererConnector>(localElement_->getView(CElementView::WORKFLOW), clientToServerElement->getView(CElementView::FULL), 
899                                                                        context->getIntraComm(), client->getRemoteSize()) ;
900    clientToServerConnector_[client]->computeConnector() ;
901
902    clientFromServerConnector_[client] = make_shared<CGathererConnector>(clientToServerElement->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
903    clientFromServerConnector_[client]->computeConnector() ;
904
905
906  }
907
908  void CAxis::recvAxisDistribution(CEventServer& event)
909  TRY
910  {
911    string axisId;
912    int phasis ;
913    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> phasis ;
914    get(axisId)->receivedAxisDistribution(event, phasis);
915  }
916  CATCH
917
918
919  void CAxis::receivedAxisDistribution(CEventServer& event, int phasis)
920  TRY
921  {
922    CContext* context = CContext::getCurrent();
923    if (phasis==0) // receive the remote element to construct the full view
924    {
925      localElement_ = make_shared<CLocalElement>(context->getIntraCommRank(),event) ;
926      localElement_->addFullView() ;
927      // construct the local dimension and indexes
928      auto& globalIndex=localElement_->getGlobalIndex() ;
929      int nk=globalIndex.numElements() ;
930      int minK=n_glo,maxK=-1 ;
931      int nGlo=n_glo ;
932      int indGlo ;
933      for(int k=0;k<nk;k++)
934      {
935        indGlo=globalIndex(k) ;
936        if (indGlo<minK) minK=indGlo ;
937        if (indGlo>maxK) maxK=indGlo ;
938      } 
939      if (maxK>=minK) { begin=minK ; n=maxK-minK+1 ; }
940      else {begin=0; n=0 ;}
941
942    }
943    else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server
944    {
945      CContext* context = CContext::getCurrent();
946      shared_ptr<CDistributedElement> elementFrom = make_shared<CDistributedElement>(event) ;
947      elementFrom->addFullView() ;
948      gathererConnector_ = make_shared<CGathererConnector>(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
949      gathererConnector_->computeConnector() ; 
950    }
951    else if (phasis==2)
952    {
953//      delete gathererConnector_ ;
954      elementFrom_ = make_shared<CDistributedElement>(event) ;
955      elementFrom_->addFullView() ;
956//      gathererConnector_ =  make_shared<CGathererConnector>(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
957//      gathererConnector_ -> computeConnector() ;
958    }
959 
960  }
961  CATCH
962
963  void CAxis::setServerMask(CArray<bool,1>& serverMask, CContextClient* client)
964  TRY
965  {
966    CContext* context = CContext::getCurrent();
967    localElement_->addView(CElementView::WORKFLOW, serverMask) ;
968    mask.reference(serverMask.copy()) ;
969 
970    serverFromClientConnector_ = make_shared<CGathererConnector>(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ;
971    serverFromClientConnector_->computeConnector() ;
972     
973    serverToClientConnector_ = make_shared<CScattererConnector>(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL),
974                                                                context->getIntraComm(), client->getRemoteSize()) ;
975    serverToClientConnector_->computeConnector() ;
976  }
977  CATCH_DUMP_ATTR
978
979  void CAxis::sendDistributedAttributes(CContextClient* client, shared_ptr<CScattererConnector> scattererConnector, const string& axisId)
980  {
981    string serverAxisId = axisId.empty() ? this->getId() : axisId ;
982    CContext* context = CContext::getCurrent();
983
984    if (hasValue)
985    {
986      { // send level value
987        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
988        CMessage message ;
989        message<<serverAxisId<<string("value") ; 
990        scattererConnector->transfer(value, client, event,message) ;
991      }
992    }
993
994    if (hasBounds)
995    {
996      { // send bounds level value
997        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
998        CMessage message ;
999        message<<serverAxisId<<string("bounds") ; 
1000        scattererConnector->transfer(2, bounds, client, event,message) ;
1001      }
1002    }
1003
1004    if (hasLabel)
1005    {
1006      { // send label
1007        // need to transform array of string (no fixed size for string) into array of array of char
1008        // to use connector to transfer
1009        // the strings must have fixed size which the maximum lenght over the string label. 
1010        int maxSize=0 ;
1011        for(int i=0; i<label.numElements();i++) 
1012          if (maxSize < label(i).size()) maxSize=label(i).size() ;
1013        MPI_Allreduce(MPI_IN_PLACE, &maxSize,1,MPI_INT,MPI_MAX, context->getIntraComm()) ;
1014        maxSize=maxSize+1 ;
1015        CArray<char,2> charArray(maxSize,label.numElements()) ;
1016        for(int j=0; j<label.numElements();j++) 
1017        {
1018          const char* str = label(j).c_str() ;
1019          int strSize=label(j).size()+1 ;
1020          for(int i=0; i<strSize; i++) charArray(i,j) = str[i] ;
1021        }
1022        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
1023        CMessage message ;
1024        message<<serverAxisId<<string("label")<<maxSize ;
1025        scattererConnector->transfer(maxSize, charArray, client, event,message) ;
1026      }
1027    }
1028  }
1029
1030  void CAxis::recvDistributedAttributes(CEventServer& event)
1031  TRY
1032  {
1033    string axisId;
1034    string type ;
1035    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> type ;
1036    get(axisId)->recvDistributedAttributes(event, type);
1037  }
1038  CATCH
1039
1040  void CAxis::recvDistributedAttributes(CEventServer& event, const string& type)
1041  TRY
1042  {
1043    if (type=="value") 
1044    {
1045      gathererConnector_->transfer(event, value, 0.); 
1046    }
1047    else if (type=="bounds")
1048    {
1049      CArray<double,1> value ;
1050      gathererConnector_->transfer(event, 2, value, 0.); 
1051      bounds.resize(2,n) ;
1052      if (bounds.numElements() > 0 ) bounds=CArray<double,2>(value.dataFirst(),shape(2,n),neverDeleteData) ; 
1053    }
1054    else if (type=="label")
1055    {
1056      int maxSize ;
1057      for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> maxSize ;
1058      CArray<char,1> value ;
1059      gathererConnector_->transfer(event, maxSize, value, '\0'); 
1060      CArray<char,2> charArray(maxSize,n) ;
1061      label.resize(n) ;
1062      if (n>0)
1063      {
1064        charArray=CArray<char,2>(value.dataFirst(),shape(maxSize,n),neverDeleteData) ;
1065        for(int j=0;j<n;j++)
1066        {
1067          int strSize ;
1068          for(int i=0;i<maxSize;i++) 
1069            if (charArray(i,j)=='\0') { strSize=i ; break; }
1070          string str(strSize,'\0') ;
1071          for(int i=0;i<strSize;i++) str[i]=charArray(i,j) ; 
1072          label(j)=str ;
1073        }
1074      } 
1075    }
1076  }
1077  CATCH
1078
1079  DEFINE_REF_FUNC(Axis,axis)
1080
1081   ///---------------------------------------------------------------
1082
1083} // namespace xios
Note: See TracBrowser for help on using the repository browser.