source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp @ 1930

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

Big update on on going work related to data distribution and transfer between clients and servers.
Revisite of the source and store filter using "connectors".

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: 111.6 KB
Line 
1
2#include "grid.hpp"
3
4#include "attribute_template.hpp"
5#include "object_template.hpp"
6#include "group_template.hpp"
7#include "message.hpp"
8#include <iostream>
9#include "xios_spl.hpp"
10#include "type.hpp"
11#include "context.hpp"
12#include "context_client.hpp"
13#include "context_server.hpp"
14#include "array_new.hpp"
15#include "server_distribution_description.hpp"
16#include "client_server_mapping_distributed.hpp"
17#include "distribution_client.hpp"
18#include "grid_transformation.hpp"
19#include "grid_generate.hpp"
20#include "server.hpp"
21#include "distribution_type.hpp"
22#include "grid_remote_connector.hpp"
23#include "grid_elements.hpp"
24#include "grid_local_view.hpp"
25
26
27namespace xios {
28
29   /// ////////////////////// Dfinitions ////////////////////// ///
30
31   CGrid::CGrid(void)
32      : CObjectTemplate<CGrid>(), CGridAttributes()
33      , isChecked(false), isDomainAxisChecked(false)
34      , vDomainGroup_(), domList_(), isDomListSet(false)
35      , vAxisGroup_(), axisList_(), isAxisListSet(false)
36      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
37      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
38      , numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
39      , connectedDataSize_(), connectedServerRank_(), connectedServerRankRead_(), connectedDataSizeRead_()
40            , isCompressible_(false)
41      , transformations_(0), isTransformed_(false)
42      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
43      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
44      , computedWrittenIndex_(false)
45      , clients()
46   {
47     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
48     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
49     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
50   }
51
52   CGrid::CGrid(const StdString& id)
53      : CObjectTemplate<CGrid>(id), CGridAttributes()
54      , isChecked(false), isDomainAxisChecked(false)
55      , vDomainGroup_(), domList_(), isDomListSet(false)
56      , vAxisGroup_(), axisList_(), isAxisListSet(false)
57      , vScalarGroup_(), scalarList_(), isScalarListSet(false)
58      , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0)
59      , numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
60      , connectedDataSize_(), connectedServerRank_(), connectedServerRankRead_(), connectedDataSizeRead_()
61            , isCompressible_(false)
62      , transformations_(0), isTransformed_(false)
63      , axisPositionInGrid_(), hasDomainAxisBaseRef_(false)
64      , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_()
65      , computedWrittenIndex_(false)
66      , clients()
67   {
68     setVirtualDomainGroup(CDomainGroup::create(getId() + "_virtual_domain_group"));
69     setVirtualAxisGroup(CAxisGroup::create(getId() + "_virtual_axis_group"));
70     setVirtualScalarGroup(CScalarGroup::create(getId() + "_virtual_scalar_group"));
71   }
72
73   CGrid::~CGrid(void)
74   {
75    if (0 != clientDistribution_) delete clientDistribution_;
76    if (0 != serverDistribution_) delete serverDistribution_;
77    if (0 != clientServerMap_) delete clientServerMap_;
78    if (0 != transformations_) delete transformations_;
79   }
80
81   ///---------------------------------------------------------------
82
83   StdString CGrid::GetName(void)    { return StdString("grid"); }
84   StdString CGrid::GetDefName(void) { return CGrid::GetName(); }
85   ENodeType CGrid::GetType(void)    { return eGrid; }
86
87
88  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
90  /////////              MEMBER FUNCTION RELATED TO GRID CONSTRUCTION by ELEMNTS AND MANAGEMENT                      /////
91  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
92  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93
94
95   CGrid* CGrid::createGrid(CDomain* domain)
96   TRY
97   {
98     std::vector<CDomain*> vecDom(1, domain);
99     std::vector<CAxis*> vecAxis;
100     return createGrid(vecDom, vecAxis);
101   }
102   CATCH
103
104   CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis)
105   TRY
106  {
107      std::vector<CDomain*> vecDom(1, domain);
108      std::vector<CAxis*> vecAxis(1, axis);
109
110      return createGrid(vecDom, vecAxis);
111   }
112   CATCH
113
114   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
115                            const CArray<int,1>& axisDomainOrder)
116   TRY
117   {
118     std::vector<CScalar*> vecScalar;
119     return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder);
120   }
121   CATCH
122
123   CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
124                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
125   TRY
126   {
127     return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder);
128   }
129   CATCH
130
131   CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
132                            const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
133   TRY
134   {
135      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
136        ERROR("CGrid* CGrid::createGrid(...)",
137              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
138              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
139
140      CGrid* grid = CGridGroup::get("grid_definition")->createChild(id);
141      grid->setDomainList(domains);
142      grid->setAxisList(axis);
143      grid->setScalarList(scalars);
144
145      // By default, domains are always the first elements of a grid
146      if (0 == axisDomainOrder.numElements())
147      {
148        int size = domains.size() + axis.size() + scalars.size();
149        int nb = 0;
150        grid->axis_domain_order.resize(size);
151        for (int i = 0; i < size; ++i)
152        {
153          if (i < domains.size()) {
154            grid->axis_domain_order(i) = 2;
155
156          }
157          else if ((scalars.size() < (size-nb)) < size) {
158            grid->axis_domain_order(i) = 1;
159          }
160          else
161            grid->axis_domain_order(i) = 0;
162          ++nb;
163        }
164      }
165      else
166      {
167        grid->axis_domain_order.resize(axisDomainOrder.numElements());
168        grid->axis_domain_order = axisDomainOrder;
169      }
170
171 //     grid->solveElementsRefInheritance(true);
172
173      return grid;
174   }
175   CATCH
176
177   //----------------------------------------------------------------
178
179   //! Change virtual field group to a new one
180   void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup)
181   TRY
182   {
183      this->vDomainGroup_ = newVDomainGroup;
184   }
185   CATCH_DUMP_ATTR
186
187   //! Change virtual variable group to new one
188   void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup)
189   TRY
190   {
191      this->vAxisGroup_ = newVAxisGroup;
192   }
193   CATCH_DUMP_ATTR
194
195   //! Change virtual variable group to new one
196   void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup)
197   TRY
198   {
199      this->vScalarGroup_ = newVScalarGroup;
200   }
201   CATCH_DUMP_ATTR
202
203   //----------------------------------------------------------------
204
205   CDomainGroup* CGrid::getVirtualDomainGroup() const
206   TRY
207   {
208     return this->vDomainGroup_;
209   }
210   CATCH
211
212   CAxisGroup* CGrid::getVirtualAxisGroup() const
213   TRY
214   {
215     return this->vAxisGroup_;
216   }
217   CATCH
218
219   CScalarGroup* CGrid::getVirtualScalarGroup() const
220   TRY
221   {
222     return this->vScalarGroup_;
223   }
224   CATCH
225
226  ///---------------------------------------------------------------
227
228   CDomain* CGrid::addDomain(const std::string& id)
229   TRY
230   {
231     order_.push_back(2);
232     axis_domain_order.resize(order_.size());
233     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
234     return vDomainGroup_->createChild(id);
235   }
236   CATCH_DUMP_ATTR
237
238   CAxis* CGrid::addAxis(const std::string& id)
239   TRY
240   {
241     order_.push_back(1);
242     axis_domain_order.resize(order_.size());
243     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
244     return vAxisGroup_->createChild(id);
245   }
246   CATCH_DUMP_ATTR
247
248   CScalar* CGrid::addScalar(const std::string& id)
249   TRY
250   {
251     order_.push_back(0);
252     axis_domain_order.resize(order_.size());
253     for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx];
254     return vScalarGroup_->createChild(id);
255   }
256   CATCH_DUMP_ATTR
257
258
259
260
261  /*!
262  \brief Get the list of domain pointers
263  \return list of domain pointers
264  */
265  std::vector<CDomain*> CGrid::getDomains()
266  TRY
267  {
268    std::vector<CDomain*> domList;
269    if (!domList_.empty())
270    {
271      for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i]));
272    }
273    return domList;
274  }
275  CATCH_DUMP_ATTR
276
277  /*!
278  \brief Get the list of  axis pointers
279  \return list of axis pointers
280  */
281  std::vector<CAxis*> CGrid::getAxis()
282  TRY
283  {
284    std::vector<CAxis*> aList;
285    if (!axisList_.empty())
286      for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i]));
287
288    return aList;
289  }
290  CATCH_DUMP_ATTR
291
292  /*!
293  \brief Get the list of  axis pointers
294  \return list of axis pointers
295  */
296  std::vector<CScalar*> CGrid::getScalars()
297  TRY
298  {
299    std::vector<CScalar*> sList;
300    if (!scalarList_.empty())
301      for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i]));
302
303    return sList;
304  }
305  CATCH_DUMP_ATTR
306
307  /*!
308  \brief Get domain pointer with index
309  \return domain pointer
310  */
311  CDomain* CGrid::getDomain(int domainIndex)
312  TRY
313  {
314    std::vector<CDomain*> domainListP = this->getDomains();
315    if (domainListP.empty())
316    {
317      ERROR("CGrid::getDomain(int domainIndex)",
318            << "No domain associated to this grid. " << std::endl
319            << "Grid id = " << this->getId());
320    }
321
322    if (domainIndex >= domainListP.size() || (domainIndex < 0))
323      ERROR("CGrid::getDomain(int domainIndex)",
324            << "Domain with the index doesn't exist " << std::endl
325            << "Grid id = " << this->getId() << std::endl
326            << "Grid has only " << domainListP.size() << " domain but domain index required is " << domainIndex << std::endl);
327
328    return domainListP[domainIndex];
329  }
330  CATCH_DUMP_ATTR
331
332  /*!
333  \brief Get the axis pointer with index
334  \return axis pointer
335  */
336  CAxis* CGrid::getAxis(int axisIndex)
337  TRY
338  {
339    std::vector<CAxis*> axisListP = this->getAxis();
340    if (axisListP.empty())
341    {
342      ERROR("CGrid::getDomain(int axisIndex)",
343            << "No axis associated to this grid. " << std::endl
344            << "Grid id = " << this->getId());
345    }
346
347    if (axisIndex >= axisListP.size() || (axisIndex < 0))
348      ERROR("CGrid::getDomain(int axisIndex)",
349            << "Domain with the index doesn't exist " << std::endl
350            << "Grid id = " << this->getId() << std::endl
351            << "Grid has only " << axisListP.size() << " axis but axis index required is " << axisIndex << std::endl);
352
353    return axisListP[axisIndex];
354  }
355  CATCH_DUMP_ATTR
356
357  /*!
358  \brief Get the a scalar pointer
359  \return scalar pointer
360  */
361  CScalar* CGrid::getScalar(int scalarIndex)
362  TRY
363  {
364    std::vector<CScalar*> scalarListP = this->getScalars();
365    if (scalarListP.empty())
366    {
367      ERROR("CGrid::getScalar(int scalarIndex)",
368            << "No scalar associated to this grid. " << std::endl
369            << "Grid id = " << this->getId());
370    }
371
372    if (scalarIndex >= scalarListP.size() || (scalarIndex < 0))
373      ERROR("CGrid::getScalar(int scalarIndex)",
374            << "Scalar with the index doesn't exist " << std::endl
375            << "Grid id = " << this->getId() << std::endl
376            << "Grid has only " << scalarListP.size() << " scalar but scalar index required is " << scalarIndex << std::endl);
377
378    return scalarListP[scalarIndex];
379  }
380  CATCH_DUMP_ATTR
381
382  /*!
383  \brief Set domain(s) of a grid from a list
384  \param[in] domains list of domains
385  */
386  void CGrid::setDomainList(const std::vector<CDomain*> domains)
387  TRY
388  {
389    if (isDomListSet) return;
390    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
391    if (!domains.empty() && domList.empty())
392    {
393      for (int i = 0; i < domains.size(); ++i)
394        this->getVirtualDomainGroup()->addChild(domains[i]);
395      domList = this->getVirtualDomainGroup()->getAllChildren();
396    }
397
398    if (!domList.empty())
399    {
400      int sizeDom = domList.size();
401      domList_.resize(sizeDom);
402      for (int i = 0; i < sizeDom; ++i)
403      {
404        domList_[i] = domList[i]->getId();
405      }
406      isDomListSet = true;
407    }
408  }
409  CATCH_DUMP_ATTR
410
411  /*!
412  \brief Set axis(s) of a grid from a list
413  \param[in] axis list of axis
414  */
415  void CGrid::setAxisList(const std::vector<CAxis*> axis)
416  TRY
417  {
418    if (isAxisListSet) return;
419    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
420    if (!axis.empty() && aList.empty())
421    {
422      for (int i = 0; i < axis.size(); ++i)
423        this->getVirtualAxisGroup()->addChild(axis[i]);
424      aList = this->getVirtualAxisGroup()->getAllChildren();
425    }
426
427    if (!aList.empty())
428    {
429      int sizeAxis = aList.size();
430      axisList_.resize(sizeAxis);
431      for (int i = 0; i < sizeAxis; ++i)
432      {
433        axisList_[i] = aList[i]->getId();
434      }
435      isAxisListSet = true;
436    }
437  }
438  CATCH_DUMP_ATTR
439
440  /*!
441  \brief Set scalar(s) of a grid from a list
442  \param[in] scalars list of scalars
443  */
444  void CGrid::setScalarList(const std::vector<CScalar*> scalars)
445  TRY
446  {
447    if (isScalarListSet) return;
448    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
449    if (!scalars.empty() && sList.empty())
450    {
451      for (int i = 0; i < scalars.size(); ++i)
452        this->getVirtualScalarGroup()->addChild(scalars[i]);
453      sList = this->getVirtualScalarGroup()->getAllChildren();
454    }
455
456    if (!sList.empty())
457    {
458      int sizeScalar = sList.size();
459      scalarList_.resize(sizeScalar);
460      for (int i = 0; i < sizeScalar; ++i)
461      {
462        scalarList_[i] = sList[i]->getId();
463      }
464      isScalarListSet = true;
465    }
466  }
467  CATCH_DUMP_ATTR
468
469  /*!
470  \brief Get list of id of domains
471  \return id list of domains
472  */
473  std::vector<StdString> CGrid::getDomainList()
474  TRY
475  {
476    setDomainList();
477    return domList_;
478  }
479  CATCH
480
481  /*!
482  \brief Get list of id of axis
483  \return id list of axis
484  */
485  std::vector<StdString> CGrid::getAxisList()
486  TRY
487  {
488    setAxisList();
489    return axisList_;
490  }
491  CATCH
492
493  /*!
494  \brief Get list of id of scalar
495  \return id list of scalar
496  */
497  std::vector<StdString> CGrid::getScalarList()
498  TRY
499  {
500    setScalarList();
501    return scalarList_;
502  }
503  CATCH
504
505
506  void CGrid::computeElements(void)
507  {
508    const auto& domains = getDomains() ;
509    const auto& axis = getAxis() ;
510    const auto& scalars = getScalars() ;
511    int idxDomain = 0, idxAxis=0 , idxScalar=0 ; 
512 
513    for(auto type : order_)
514    {
515      if      (type == 0) { elements_.push_back({scalars[idxScalar], TYPE_SCALAR, scalars[idxScalar], nullptr, nullptr } ) ; idxScalar++;}
516      else if (type == 1) { elements_.push_back({axis[idxAxis], TYPE_AXIS, nullptr, axis[idxAxis], nullptr}) ; idxAxis++;}
517      else if (type == 2) { elements_.push_back({domains[idxDomain], TYPE_DOMAIN, nullptr, nullptr, domains[idxDomain] }) ; idxDomain++;}       
518    }
519    elementsComputed_ = true ;
520  }
521 
522 
523 /*!
524    Parse a grid, for now, it contains only domain, axis and scalar
525  */
526  void CGrid::parse(xml::CXMLNode& node)
527  TRY
528  {
529    SuperClass::parse(node);
530
531    if (node.goToChildElement())
532    {
533      StdString domainName("domain");
534      StdString axisName("axis");
535      StdString scalarName("scalar");
536      do
537      {
538        if (node.getElementName() == domainName) {
539          order_.push_back(2);
540          this->getVirtualDomainGroup()->parseChild(node);
541        }
542        if (node.getElementName() == axisName) {
543          order_.push_back(1);
544          this->getVirtualAxisGroup()->parseChild(node);
545        }
546        if (node.getElementName() == scalarName) {
547          order_.push_back(0);
548          this->getVirtualScalarGroup()->parseChild(node);
549        }
550      } while (node.goToNextElement());
551      node.goToParentElement();
552    }
553
554    if (!order_.empty())
555    {
556      int sizeOrd = order_.size();
557      axis_domain_order.resize(sizeOrd);
558      for (int i = 0; i < sizeOrd; ++i)
559      {
560        axis_domain_order(i) = order_[i];
561      }
562    }
563
564    setDomainList();
565    setAxisList();
566    setScalarList();
567   }
568   CATCH_DUMP_ATTR
569
570
571  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
572  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
573  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
574  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
575
576
577
578   StdSize CGrid::getDimension(void)
579   TRY
580   {
581      return getGlobalDimension().size();
582   }
583   CATCH_DUMP_ATTR
584
585   //---------------------------------------------------------------
586
587   StdSize CGrid::getDataSize(void) 
588   TRY
589   {
590     StdSize retvalue = 1;
591     if (!isScalarGrid())
592     {
593       std::vector<int> dataNindex = getClientDistribution()->getDataNIndex();
594       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];       
595     }
596     return retvalue;
597   }
598   CATCH
599   
600   /*!
601    * Get the local data grid size, ie the size of the compressed grid (inside the workflow)
602    * \return The size od the compressed grid
603    */
604    StdSize  CGrid::getLocalDataSize(void) { return getClientDistribution()->getLocalDataSize();}
605
606
607   /*!
608    * Compute the minimum buffer size required to send the attributes to the server(s).
609    *
610    * \return A map associating the server rank with its minimum buffer size.
611    * TODO: Refactor code
612    */
613   std::map<int, StdSize> CGrid::getAttributesBufferSize(CContextClient* client, bool bufferForWriting)
614   TRY
615   {
616     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client);
617
618     // The grid indexes require a similar size as the actual data
619     std::map<int, StdSize> dataSizes = getDataBufferSize(client, "", bufferForWriting);
620     std::map<int, StdSize>::iterator it, itE = dataSizes.end();
621     for (it = dataSizes.begin(); it != itE; ++it)
622     {
623       it->second += 2 * sizeof(bool);
624       if (it->second > attributesSizes[it->first])
625         attributesSizes[it->first] = it->second;
626     }
627     
628     // Account for the axis attributes
629     std::vector<CAxis*> axisList = getAxis();
630     for (size_t i = 0; i < axisList.size(); ++i)
631     {
632       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize(client, getGlobalDimension(),getAxisPositionInGrid()[i]);
633       for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it)
634       {
635         it->second += 2 * sizeof(bool);
636         if (it->second > attributesSizes[it->first])
637           attributesSizes[it->first] = it->second;
638       }
639     }
640
641     // Account for the domain attributes
642     std::vector<CDomain*> domList = getDomains();
643     for (size_t i = 0; i < domList.size(); ++i)
644     {
645       std::map<int, StdSize> domAttBuffSize = domList[i]->getAttributesBufferSize(client);
646       for (it = domAttBuffSize.begin(), itE = domAttBuffSize.end(); it != itE; ++it)
647       {
648         it->second += 2 * sizeof(bool);
649         if (it->second > attributesSizes[it->first])
650           attributesSizes[it->first] = it->second;
651       }
652     }
653
654     return attributesSizes;
655  }
656   CATCH_DUMP_ATTR
657
658   /*!
659    * Compute the minimum buffer size required to send the data.
660    * \param client contextClient used to determine the size of connected receivers
661    * \param id the id used to tag the data
662    * \param bufferForWriting flag indicating if a buffer is used to send data for writing
663    * \return A map associating the sender rank with its minimum buffer size.
664    */
665   std::map<int, StdSize> CGrid::getDataBufferSize(CContextClient* client, const std::string& id /*= ""*/, bool bufferForWriting /*= "false"*/)
666   TRY
667   {     
668     // The record index is sometimes sent along with the data but we always
669     // include it in the size calculation for the sake of simplicity
670     const size_t extraSize = CEventClient::headerSize + (id.empty() ? getId() : id).size() 
671                                                       + 2 * sizeof(size_t) 
672                                                       + sizeof(size_t);
673
674     std::map<int, StdSize> dataSizes;
675     int receiverSize = client->serverSize;
676     std::map<int,size_t>& dataSizeMap = bufferForWriting ? connectedDataSize_[receiverSize]: connectedDataSizeRead_;
677     std::vector<int>& connectedServerRanks = bufferForWriting ? connectedServerRank_[receiverSize] : connectedServerRankRead_;
678
679     std::map<int, size_t>::const_iterator itEnd = dataSizeMap.end();
680     for (size_t k = 0; k < connectedServerRanks.size(); ++k)
681     {
682       int rank = connectedServerRanks[k];
683       std::map<int, size_t>::const_iterator it = dataSizeMap.find(rank);
684       size_t count = (it != itEnd) ? it->second : 0;
685
686       dataSizes.insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
687     }
688
689     return dataSizes;
690   }
691   CATCH_DUMP_ATTR
692
693   size_t CGrid::getGlobalWrittenSize(void)
694   TRY
695   {
696         std::vector<CDomain*> domainP = this->getDomains();
697     std::vector<CAxis*> axisP = this->getAxis();
698     
699     size_t globalGridSize=1 ;
700     for (std::vector<CDomain*>::iterator it=domainP.begin(); it!=domainP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
701     for (std::vector<CAxis*>::iterator it=axisP.begin(); it!=axisP.end();++it) globalGridSize*=(*it)->getGlobalWrittenSize() ;
702     return globalGridSize ;
703   }
704   CATCH_DUMP_ATTR
705   
706
707   void CGrid::computeAxisPositionInGrid(void)
708   {
709     axisPositionInGrid_.resize(0);
710     int idx = 0;
711     for (int i = 0; i < axis_domain_order.numElements(); ++i)
712     {
713       int elementDimension = axis_domain_order(i);
714       if (1 == elementDimension)
715       {
716         axisPositionInGrid_.push_back(idx);
717         ++idx;
718       }
719       else if (2 == elementDimension) idx += 2;
720     }
721   }
722
723   void CGrid::checkAttributesAfterTransformation()
724   TRY
725   {
726      setAxisList();
727      std::vector<CAxis*> axisListP = this->getAxis();
728      for (int i = 0; i < axisListP.size(); ++i)
729        axisListP[i]->checkAttributesOnClientAfterTransformation(getGlobalDimension(), getAxisPositionInGrid()[i]);
730   
731      setDomainList();
732      std::vector<CDomain*> domListP = this->getDomains();
733      if (!domListP.empty())
734      {
735        for (int i = 0; i < domListP.size(); ++i)
736        {
737          domListP[i]->checkAttributesOnClientAfterTransformation();
738        }
739      }
740   }
741   CATCH_DUMP_ATTR
742
743   //---------------------------------------------------------------
744
745   /*!
746    * Test whether the data defined on the grid can be outputted in a compressed way.
747    *
748    * \return true if and only if a mask was defined for this grid
749    */
750   bool CGrid::isCompressible(void) const
751   TRY
752   {
753      return isCompressible_;
754   }
755   CATCH
756
757   //---------------------------------------------------------------
758
759   void CGrid::addRelFileCompressed(const StdString& filename)
760   TRY
761   {
762      this->relFilesCompressed.insert(filename);
763   }
764   CATCH_DUMP_ATTR
765
766   bool CGrid::isWrittenCompressed(const StdString& filename) const
767   TRY
768   {
769      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
770   }
771   CATCH
772
773   //---------------------------------------------------------------
774   /*
775     Find all reference of grid's components and inherite attributes if necessary
776   */
777   void CGrid::solveDomainAxisRef(bool areAttributesChecked)
778   TRY
779   {
780     if (this->isDomainAxisChecked) return;
781
782     this->solveScalarRef(areAttributesChecked);
783     this->solveAxisRef(areAttributesChecked);
784     this->solveDomainRef(areAttributesChecked);     
785     this->isDomainAxisChecked = areAttributesChecked;
786   }
787   CATCH_DUMP_ATTR
788
789   /*
790     Go up hierachy reference and fill in the base reference with attributes of the children
791     This function should be only used after reading component's attributes from file
792   */
793   void CGrid::solveDomainAxisBaseRef()
794   TRY
795   {
796     if (this->hasDomainAxisBaseRef_) return;
797     // Account for the scalar attributes
798     std::vector<CScalar*> scalarList = getScalars();
799     for (size_t i = 0; i < scalarList.size(); ++i)
800     {
801       scalarList[i]->setAttributesReference();
802     }
803
804     // Account for the axis attributes
805     std::vector<CAxis*> axisList = getAxis();
806     for (size_t i = 0; i < axisList.size(); ++i)
807     {
808       axisList[i]->setAttributesReference();
809     }
810
811     // Account for the domain attributes
812     std::vector<CDomain*> domList = getDomains();
813     for (size_t i = 0; i < domList.size(); ++i)
814     {
815       domList[i]->setAttributesReference();
816     }
817
818     this->hasDomainAxisBaseRef_ = true;
819   }
820   CATCH_DUMP_ATTR
821
822   void CGrid::checkEligibilityForCompressedOutput()
823   TRY
824   {
825     // We don't check if the mask is valid here, just if a mask has been defined at this point.
826     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty();
827   }
828   CATCH_DUMP_ATTR
829
830   //ym obsolete -> to be removed later
831   void CGrid::checkMaskIndex(bool doSendingIndex)
832   TRY
833   {
834     CContext* context = CContext::getCurrent();
835     if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER)     
836     {
837       if (this->isChecked && doSendingIndex && !isIndexSent) 
838       { 
839         if (isScalarGrid())  /*sendIndexScalarGrid()*/;
840         else  /*sendIndex()*/;
841         this->isIndexSent = true; 
842       }
843     }
844
845     if (this->isChecked) return;
846     this->checkAttributesAfterTransformation();
847
848     // TODO: Transfer grid attributes
849     //if (!context->hasClient && context->hasServer) this->createMask();
850     this->computeIndex();
851
852     if (!(this->hasTransform() && !this->isTransformed()))
853      this->isChecked = true;
854
855     if (!(this->hasTransform() && (!this->isGenerated())))
856      this->isChecked = true;
857   }
858   CATCH_DUMP_ATTR
859
860
861   bool CGrid::hasMask() const
862   TRY
863   {
864     return (!mask_1d.isEmpty() || !mask_2d.isEmpty() || !mask_3d.isEmpty() ||
865             !mask_4d.isEmpty() || !mask_5d.isEmpty() || !mask_6d.isEmpty() || !mask_7d.isEmpty());
866   }
867   CATCH
868
869   
870   CArray<bool,1>& CGrid::getMask(void)
871   {
872     
873      if (mask_.isEmpty())
874      { 
875        if (!mask_0d.isEmpty()) mask_.reference(CArray<bool,1>(mask_0d.dataFirst(),shape(mask_0d.numElements()), neverDeleteData)) ;
876        if (!mask_1d.isEmpty()) mask_.reference(CArray<bool,1>(mask_1d.dataFirst(),shape(mask_1d.numElements()), neverDeleteData)) ;
877        if (!mask_2d.isEmpty()) mask_.reference(CArray<bool,1>(mask_2d.dataFirst(),shape(mask_2d.numElements()), neverDeleteData)) ;
878        if (!mask_3d.isEmpty()) mask_.reference(CArray<bool,1>(mask_3d.dataFirst(),shape(mask_3d.numElements()), neverDeleteData)) ;
879        if (!mask_4d.isEmpty()) mask_.reference(CArray<bool,1>(mask_4d.dataFirst(),shape(mask_4d.numElements()), neverDeleteData)) ;
880        if (!mask_5d.isEmpty()) mask_.reference(CArray<bool,1>(mask_5d.dataFirst(),shape(mask_5d.numElements()), neverDeleteData)) ;
881        if (!mask_6d.isEmpty()) mask_.reference(CArray<bool,1>(mask_6d.dataFirst(),shape(mask_6d.numElements()), neverDeleteData)) ;
882        if (!mask_7d.isEmpty()) mask_.reference(CArray<bool,1>(mask_7d.dataFirst(),shape(mask_7d.numElements()), neverDeleteData)) ;
883      }
884      return mask_ ;
885   }
886   /*
887     Create mask of grid from mask of its components
888   */
889   void CGrid::createMask(void)
890   TRY
891   {
892      using namespace std;
893      std::vector<CDomain*> domainP = this->getDomains();
894      std::vector<CAxis*> axisP = this->getAxis();
895      int dim = domainP.size() * 2 + axisP.size();
896
897      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
898      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->domainMask);
899      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
900      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
901
902      switch (dim) {
903        case 1:
904          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order, true);
905          break;
906        case 2:
907          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order, true);
908          break;
909        case 3:
910          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order, true);
911          break;
912        case 4:
913          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order, true);
914          break;
915        case 5:
916          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order, true);
917          break;
918        case 6:
919          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order, true);
920          break;
921        case 7:
922          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order, true);
923          break;
924        default:
925          break;
926      }
927   }
928   CATCH_DUMP_ATTR
929
930   /*
931     Check validity of grid's mask by using the masks of its components
932   */
933   void CGrid::checkMask(void)
934   TRY
935   {
936      using namespace std;
937      std::vector<CDomain*> domainP = this->getDomains();
938      std::vector<CAxis*> axisP = this->getAxis();
939      int dim = domainP.size() * 2 + axisP.size();
940
941      std::vector<CArray<bool,1>* > domainMasks(domainP.size());
942      for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->domainMask);
943      std::vector<CArray<bool,1>* > axisMasks(axisP.size());
944      for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask);
945
946      switch (dim) {
947        case 1:
948          checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order);
949          break;
950        case 2:
951          checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order);
952          break;
953        case 3:
954          checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order);
955          break;
956        case 4:
957          checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order);
958          break;
959        case 5:
960          checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order);
961          break;
962        case 6:
963          checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order);
964          break;
965        case 7:
966          checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order);
967          break;
968        default:
969          break;
970      }
971   }
972   CATCH_DUMP_ATTR
973
974   /*
975     Modify value of mask in a certain index
976     This function can be used to correct the mask of grid after being constructed with createMask
977     \param [in] indexToModify
978     \param [in] modifyValue
979   */
980   void CGrid::modifyMask(const CArray<int,1>& indexToModify, bool modifyValue)
981   TRY
982   {
983      using namespace std;
984      std::vector<CDomain*> domainP = this->getDomains();
985      std::vector<CAxis*> axisP = this->getAxis();
986      int dim = domainP.size() * 2 + axisP.size();
987
988      switch (dim) {
989        case 0:
990          modifyGridMask(mask_0d, indexToModify, modifyValue);
991          break;
992        case 1:
993          modifyGridMask(mask_1d, indexToModify, modifyValue);
994          break;
995        case 2:
996          modifyGridMask(mask_2d, indexToModify, modifyValue);
997          break;
998        case 3:
999          modifyGridMask(mask_3d, indexToModify, modifyValue);
1000          break;
1001        case 4:
1002          modifyGridMask(mask_4d, indexToModify, modifyValue);
1003          break;
1004        case 5:
1005          modifyGridMask(mask_5d, indexToModify, modifyValue);
1006          break;
1007        case 6:
1008          modifyGridMask(mask_6d, indexToModify, modifyValue);
1009          break;
1010        case 7:
1011          modifyGridMask(mask_7d, indexToModify, modifyValue);
1012          break;
1013        default:
1014          break;
1015      }
1016   }
1017   CATCH_DUMP_ATTR
1018
1019   /*
1020     Change the mask size. This function is used on reconstructing mask in server side
1021     \param [in] newDimensionSize
1022     \param [in] newValue
1023   */
1024   void CGrid::modifyMaskSize(const std::vector<int>& newDimensionSize, bool newValue)
1025   TRY
1026   {     
1027      std::vector<CDomain*> domainP = this->getDomains();
1028      std::vector<CAxis*> axisP = this->getAxis();           
1029      int dim = domainP.size() * 2 + axisP.size();
1030
1031      switch (dim) {
1032        case 0:
1033          modifyGridMaskSize(mask_0d, newDimensionSize, newValue);
1034          break;
1035        case 1:
1036          modifyGridMaskSize(mask_1d, newDimensionSize, newValue);
1037          break;
1038        case 2:
1039          modifyGridMaskSize(mask_2d, newDimensionSize, newValue);
1040          break;
1041        case 3:
1042          modifyGridMaskSize(mask_3d, newDimensionSize, newValue);
1043          break;
1044        case 4:
1045          modifyGridMaskSize(mask_4d, newDimensionSize, newValue);
1046          break;
1047        case 5:
1048          modifyGridMaskSize(mask_5d, newDimensionSize, newValue);
1049          break;
1050        case 6:
1051          modifyGridMaskSize(mask_6d, newDimensionSize, newValue);
1052          break;
1053        case 7:
1054          modifyGridMaskSize(mask_7d, newDimensionSize, newValue);
1055          break;
1056        default:
1057          break;
1058      }
1059   }
1060   CATCH_DUMP_ATTR
1061
1062   //---------------------------------------------------------------
1063
1064   void CGrid::solveDomainRef(bool sendAtt)
1065   TRY
1066   {
1067      setDomainList();
1068      std::vector<CDomain*> domListP = this->getDomains();
1069      if (!domListP.empty())
1070      {
1071        for (int i = 0; i < domListP.size(); ++i)
1072        {
1073          if (sendAtt) domListP[i]->sendCheckedAttributes();
1074          else domListP[i]->checkAttributesOnClient();
1075        }
1076      }
1077   }
1078   CATCH_DUMP_ATTR
1079
1080   //---------------------------------------------------------------
1081
1082   void CGrid::solveAxisRef(bool sendAtt)
1083   TRY
1084   {
1085      setAxisList();
1086      std::vector<CAxis*> axisListP = this->getAxis();
1087      if (!axisListP.empty())
1088      {
1089        for (int i = 0; i < axisListP.size(); ++i)
1090        {
1091          if (sendAtt)
1092            axisListP[i]->sendCheckedAttributes(getGlobalDimension(),getAxisPositionInGrid()[i]);
1093          else
1094            axisListP[i]->checkAttributesOnClient();
1095        }
1096      }
1097   }
1098   CATCH_DUMP_ATTR
1099
1100   //---------------------------------------------------------------
1101
1102   void CGrid::solveScalarRef(bool sendAtt)
1103   TRY
1104   {
1105      setScalarList();
1106      std::vector<CScalar*> scalarListP = this->getScalars();
1107      if (!scalarListP.empty())
1108      {
1109        for (int i = 0; i < scalarListP.size(); ++i)
1110        {
1111          /*Nothing to do for now */
1112//          if (sendAtt) scalarListP[i]->sendCheckedAttributes();
1113//          else scalarListP[i]->checkAttributesOnClient();
1114        }
1115      }
1116   }
1117   CATCH_DUMP_ATTR
1118
1119   /*!
1120      Compute the index to for write data into a file
1121   */
1122   void CGrid::computeWrittenIndex()
1123   TRY
1124   {     
1125      if (computedWrittenIndex_) return;
1126      computedWrittenIndex_ = true;
1127
1128      if (isScalarGrid())
1129      {
1130        size_t nbWritten = 1;
1131        int writtenIndex = 0;
1132
1133        localIndexToWriteOnClient_.resize(nbWritten); 
1134        localIndexToWriteOnServer_.resize(nbWritten);
1135        localIndexToWriteOnServer_(0) = writtenIndex;
1136        localIndexToWriteOnClient_(0) = writtenIndex;
1137       
1138        return;
1139      }
1140
1141      size_t nbWritten = 0, indGlo;
1142      CDistributionClient::GlobalLocalDataMap& globalDataIndex = getClientDistribution()->getGlobalDataIndexOnClient();
1143      CDistributionClient::GlobalLocalDataMap::const_iterator itb = globalDataIndex.begin(),
1144                                                              ite = globalDataIndex.end(), it;   
1145      const CDistributionServer::GlobalLocalMap& globalLocalIndex = serverDistribution_->getGlobalLocalIndex();                                                             
1146      CDistributionServer::GlobalLocalMap::const_iterator itSrvb = globalLocalIndex.begin(),
1147                                                          itSrve = globalLocalIndex.end(), itSrv;
1148      for (it = itb; it != ite; ++it)
1149      {
1150        indGlo = it->first;
1151        if (globalLocalIndex.end() != globalLocalIndex.find(indGlo)) ++nbWritten;               
1152      }
1153
1154      localIndexToWriteOnClient_.resize(nbWritten); 
1155      localIndexToWriteOnServer_.resize(nbWritten);
1156     
1157      {
1158        numberWrittenIndexes_ = nbWritten;
1159        if (isDataDistributed())
1160        {
1161          CContext* context = CContext::getCurrent();     
1162          MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, context->intraComm_);
1163          MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, context->intraComm_);
1164          offsetWrittenIndexes_ -= numberWrittenIndexes_;
1165        }
1166        else
1167          totalNumberWrittenIndexes_ = numberWrittenIndexes_;
1168      }
1169
1170      nbWritten = 0; 
1171      for (it = itb; it != ite; ++it)
1172      {
1173        indGlo = it->first;
1174        itSrv = globalLocalIndex.find(indGlo);
1175        if (itSrve != itSrv)
1176        {
1177          localIndexToWriteOnServer_(nbWritten) = itSrv->second;
1178          localIndexToWriteOnClient_(nbWritten) = it->second;
1179          ++nbWritten;               
1180        } 
1181      }
1182   }
1183   CATCH_DUMP_ATTR
1184
1185   
1186
1187   /*!
1188     Compute the global index of grid to send to server as well as the connected server of the current client.
1189     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know
1190     their global index. We can have a map of global index of grid and local index that each client holds
1191     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s)
1192     of the current client.
1193   */
1194   void CGrid::computeGridIndexToFileServer(CContextClient* client)
1195   {
1196     if (isScalarGrid()) computeConnectedClientsScalarGrid(client);
1197     else computeConnectedClients(client);
1198   
1199     // compute indices for client/server transfer for domain
1200     for (const auto& domainId : domList_) CDomain::get(domainId)->computeConnectedClients(client);
1201   
1202   
1203     // compute indices for client/server transfer for axis
1204     std::vector<CAxis*> axisList = this->getAxis();
1205     for(int i=0 ; i<axisList.size(); i++) axisList[i] -> computeConnectedClients(client, getGlobalDimension(),getAxisPositionInGrid()[i]) ;
1206   }
1207   //---------------------------------------------------------------
1208
1209   
1210   void CGrid::computeClientDistribution(void)
1211   {
1212     if (computeClientDistribution_done_) return ;
1213     else computeClientDistribution_done_ = true ;
1214
1215     CContext* context = CContext::getCurrent();
1216     int rank = context-> getIntraCommRank();
1217     clientDistribution_ = new CDistributionClient(rank, this);
1218   }
1219
1220   void CGrid::computeStoreIndex_client(void)
1221   {
1222     if (computeStoreIndex_client_done_) return ;
1223     else computeStoreIndex_client_done_ = true ;
1224     if (isScalarGrid())
1225     {
1226       storeIndex_client_.resize(1);
1227       storeIndex_client_(0) = 0;
1228     }
1229     else
1230     {
1231       CDistributionClient* clientDistribution = getClientDistribution() ;
1232       const std::vector<int>& localDataIndex = clientDistribution->getLocalDataIndexOnClient() ;
1233       int nbStoreIndex = localDataIndex.size() ;
1234       storeIndex_client_.resize(nbStoreIndex);
1235       for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client_(idx) = localDataIndex[idx];
1236     }
1237   }
1238
1239   void CGrid::computeStoreMask_client(void)
1240   {
1241     if (computeStoreMask_client_done_) return ;
1242     else computeStoreMask_client_done_ = true ;
1243     if (isScalarGrid())
1244     {
1245       storeMask_client_.resize(1);
1246       storeMask_client_(0) = true;
1247     }
1248     else
1249     {
1250       CDistributionClient* clientDistribution = getClientDistribution() ;
1251       const std::vector<bool>& localMaskIndex = clientDistribution->getLocalMaskIndexOnClient() ;
1252       int nbMaskIndex = localMaskIndex.size() ;
1253       storeMask_client_.resize(nbMaskIndex);
1254       for (int idx = 0; idx < nbMaskIndex; ++idx) storeMask_client_(idx) = localMaskIndex[idx];
1255     }
1256   }
1257
1258
1259  void CGrid::computeOutLocalIndexStoreOnClient(void)
1260  {
1261    if (computeOutLocalIndexStoreOnClient_done_) return ;
1262    else computeOutLocalIndexStoreOnClient_done_=true ;
1263
1264    if (isScalarGrid())
1265    {
1266        auto& outGlobalIndexFromClient  = getOutGlobalIndexFromClient();
1267        auto itb = outGlobalIndexFromClient.begin(), ite = outGlobalIndexFromClient.end() ;
1268        for (auto it = itb; it != ite; ++it)
1269        {
1270          int rank = it->first;
1271          CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
1272          outLocalIndexStoreOnClient_.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
1273          CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient_[rank];
1274          if (1 != globalIndex.numElements())
1275            ERROR("void CGrid::computeClientIndexScalarGrid()",
1276              << "Something wrong happened. "
1277              << "Number of received global index on scalar grid should equal to 1" 
1278              << "Number of received global index " << globalIndex.numElements() << ".");
1279
1280          localIndex(0) = globalIndex(0);
1281        }
1282    }
1283    else
1284    {
1285      CDistributionClient::GlobalLocalDataMap& globalDataIndex = getClientDistribution()->getGlobalDataIndexOnClient();
1286      CDistributionClient::GlobalLocalDataMap::const_iterator itGloe = globalDataIndex.end();
1287      auto& outGlobalIndexFromClient  = getOutGlobalIndexFromClient();
1288      auto itb = outGlobalIndexFromClient.begin(), ite = outGlobalIndexFromClient.end() ;
1289   
1290      for (auto it = itb; it != ite; ++it)
1291      {
1292         int rank = it->first;
1293         CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
1294         outLocalIndexStoreOnClient_.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
1295         CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient_[rank];
1296         size_t nbIndex = 0;
1297
1298        // Keep this code for this moment but it should be removed (or moved to DEBUG) to improve performance
1299        for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
1300          if (itGloe != globalDataIndex.find(globalIndex(idx))) ++nbIndex;
1301
1302        if (nbIndex != localIndex.numElements())
1303             ERROR("void CGrid::computeClientIndex()",
1304                 << "Number of local index on client is different from number of received global index"
1305                 << "Rank of sent client " << rank <<"."
1306                 << "Number of local index " << nbIndex << ". "
1307                 << "Number of received global index " << localIndex.numElements() << ".");
1308
1309        nbIndex = 0;
1310        for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
1311          if (itGloe != globalDataIndex.find(globalIndex(idx)))
1312            localIndex(idx) = globalDataIndex[globalIndex(idx)];
1313      }
1314    }
1315  }
1316
1317  bool CGrid::isDataDistributed(void) 
1318  { 
1319    return getClientDistribution()->isDataDistributed() ;
1320  }
1321
1322   /*!
1323     Compute connected receivers and indexes to be sent to these receivers.
1324   */
1325   void CGrid::computeConnectedClients(CContextClient* client)
1326   TRY
1327   {
1328     if (computeConnectedClients_done_.count(client)!=0) return ;
1329     else  computeConnectedClients_done_.insert(client) ;
1330
1331     CContext* context = CContext::getCurrent();
1332     
1333     set<int> listReceiverSize ;
1334     int receiverSize = client->serverSize;
1335     
1336     if (listReceiverSize.find(receiverSize)==listReceiverSize.end())
1337     {
1338       listReceiverSize.insert(receiverSize) ;
1339       if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end())
1340       {
1341          // delete corresponding map in case of recompute, probably because a grid could has been modifiedd
1342          // by a transformation
1343          connectedServerRank_.erase(receiverSize);
1344          connectedDataSize_.erase(receiverSize);
1345          globalIndexOnServer_.erase(receiverSize);
1346          nbSenders_.erase(receiverSize);
1347       }
1348
1349       if (!doGridHaveDataDistributed(client))
1350       {
1351          if (client->isServerLeader())
1352          {
1353            size_t ssize = getClientDistribution()->getLocalDataIndexOnClient().size();
1354            const std::list<int>& ranks = client->getRanksServerLeader();
1355            for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1356            {
1357              connectedServerRank_[receiverSize].push_back(*itRank);
1358              connectedDataSize_[receiverSize][*itRank] = ssize;
1359            }
1360          }
1361          return;
1362       }
1363
1364       // Compute mapping between client and server
1365       std::vector<std::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
1366       CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize);
1367       std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
1368                                                                                                    client->clientRank,
1369                                                                                                    client->clientSize,
1370                                                                                                    axis_domain_order,
1371                                                                                                    getDistributedDimension());
1372
1373       // Even if servers have no index, they must received something from client
1374       // We only use several client to send "empty" message to these servers
1375       std::list<int> serverZeroIndexLeader;
1376       std::list<int> serverZeroIndexNotLeader;
1377       CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader);
1378       for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
1379         *it = serverZeroIndex[*it];
1380
1381       if (globalIndexOnServer_.find(receiverSize) == globalIndexOnServer_.end())
1382         computeIndexByElement(indexServerOnElement, client, globalIndexOnServer_[receiverSize]);
1383
1384       const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = getClientDistribution()->getGlobalLocalDataSendToServer();
1385       CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
1386       CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
1387       itbGlobalMap = globalIndexOnServer_[receiverSize].begin();
1388       iteGlobalMap = globalIndexOnServer_[receiverSize].end();
1389
1390       for (itGlobalMap  = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap)
1391       {
1392         int serverRank = itGlobalMap->first;
1393         int indexSize = itGlobalMap->second.size();
1394         const std::vector<size_t>& indexVec = itGlobalMap->second;
1395         for (int idx = 0; idx < indexSize; ++idx)
1396         {
1397            itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
1398            if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
1399            {
1400              if (connectedDataSize_[receiverSize].end() == connectedDataSize_[receiverSize].find(serverRank))
1401                connectedDataSize_[receiverSize][serverRank] = 1;
1402              else
1403                ++connectedDataSize_[receiverSize][serverRank];
1404            }
1405         }
1406       }
1407
1408       // Connected servers which really have index
1409       for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) 
1410         connectedServerRank_[receiverSize].push_back(itGlobalMap->first);
1411     
1412       // Connected servers which have no index at all
1413       for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
1414         connectedServerRank_[receiverSize].push_back(*it);
1415
1416       // Even if a client has no index, it must connect to at least one server and
1417       // send an "empty" data to this server
1418       if (connectedServerRank_[receiverSize].empty())
1419         connectedServerRank_[receiverSize].push_back(client->clientRank % client->serverSize);
1420 
1421       // Now check if all servers have data to receive. If not, master client will send empty data.
1422       // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive.
1423       std::vector<int> counts (client->clientSize);
1424       std::vector<int> displs (client->clientSize);
1425       displs[0] = 0;
1426       int localCount = connectedServerRank_[receiverSize].size() ;
1427       MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ;
1428       for (int i = 0; i < client->clientSize-1; ++i) displs[i+1] = displs[i] + counts[i];
1429       std::vector<int> allConnectedServers(displs[client->clientSize-1]+counts[client->clientSize-1]);
1430       MPI_Gatherv(&(connectedServerRank_[receiverSize])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm);
1431
1432       if ((allConnectedServers.size() != receiverSize) && (client->clientRank == 0))
1433       {
1434         std::vector<bool> isSrvConnected (receiverSize, false);
1435         for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true;
1436         for (int i = 0; i < receiverSize; ++i) if (!isSrvConnected[i]) connectedServerRank_[receiverSize].push_back(i);
1437       }
1438
1439       nbSenders_[receiverSize] = CClientServerMapping::computeConnectedClients(receiverSize, client->clientSize, client->intraComm, connectedServerRank_[receiverSize]);
1440     }
1441   }
1442   CATCH_DUMP_ATTR
1443
1444   /*!
1445     Compute the global index of grid to send to server as well as the connected server of the current client.
1446     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know
1447     their global index. We can have a map of global index of grid and local index that each client holds
1448     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s)
1449     of the current client.
1450   */
1451   // ym obsolete : to be removed....
1452   void CGrid::computeIndex(void)
1453   TRY
1454   {
1455    // old interface
1456     CContext* context = CContext::getCurrent();
1457     if (isScalarGrid())
1458     {
1459       //computeClientIndexScalarGrid();
1460       if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER)
1461       {
1462         // ym computeConnectedClientsScalarGrid();
1463       }
1464     }
1465     else
1466     {
1467       //computeClientIndex();
1468       if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER)
1469       {
1470         //computeConnectedClients();
1471       }
1472     }
1473//ym     if (CServer::serverLevel==2)
1474     if (context->getServiceType()==CServicesManager::OUT_SERVER)
1475     {
1476       computeWrittenIndex() ;
1477       if (serverDistribution_!=0) serverDistribution_->partialClear() ;
1478       if (clientDistribution_!=0) clientDistribution_->partialClear() ;
1479       outGlobalIndexFromClient_.clear() ;
1480     }
1481   }
1482   CATCH_DUMP_ATTR
1483
1484   /*!
1485      Compute the global of (client) grid to send to server with the global index of each element of grid
1486      Each element of grid has its own global index associated to a groups of server. We only search for the global index of each element whose
1487      server is the same, then calculate the global index of grid. This way can reduce so much the time for executing DHT, which only needs to run
1488      on each element whose size is much smaller than one of whole grid.
1489      \param [in] indexServerOnElement global index of each element and the rank of server associated with these index
1490      \param [in] client contextClient
1491      \param [out] globalIndexOnServer global index of grid and its corresponding rank of server.
1492   */
1493   void CGrid::computeIndexByElement(const std::vector<std::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
1494                                     const CContextClient* client,
1495                                     CClientServerMapping::GlobalIndexMap& globalIndexOnServer)
1496   TRY
1497   {
1498     int serverSize = client->serverSize;
1499
1500     std::vector<CDomain*> domList = getDomains();
1501     std::vector<CAxis*> axisList = getAxis();
1502
1503     // Some pre-calculations of global index on each element of current grid.
1504     int nbElement = axis_domain_order.numElements();
1505     std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
1506     int domainIdx = 0, axisIdx = 0, scalarIdx = 0;
1507     std::vector<size_t> elementNGlobal(nbElement);
1508     elementNGlobal[0] = 1;
1509     size_t globalSize = 1;
1510     for (int idx = 0; idx < nbElement; ++idx)
1511     {
1512       elementNGlobal[idx] = globalSize;
1513       size_t elementSize;
1514       size_t elementGlobalSize = 1;
1515       if (2 == axis_domain_order(idx)) // This is domain
1516       {
1517         elementSize = domList[domainIdx]->i_index.numElements();
1518         globalIndexElement[idx].resize(elementSize);
1519         for (int jdx = 0; jdx < elementSize; ++jdx)
1520         {
1521           globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
1522         }
1523         elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
1524         ++domainIdx;
1525       }
1526       else if (1 == axis_domain_order(idx))  // This is axis
1527       {
1528         elementSize = axisList[axisIdx]->index.numElements();
1529         globalIndexElement[idx].resize(elementSize);
1530         for (int jdx = 0; jdx < elementSize; ++jdx)
1531         {
1532           globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
1533         }
1534         elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
1535         ++axisIdx;
1536       }
1537       else  // Of course, this is scalar
1538       {
1539         globalIndexElement[idx].resize(1);
1540         globalIndexElement[idx](0) = 0;
1541         elementGlobalSize = 1;
1542       }
1543       globalSize *= elementGlobalSize;
1544     }
1545
1546     std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
1547     std::vector<std::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
1548     CArray<int,1> nbIndexOnServer(serverSize); // Number of distributed global index held by each client for each server
1549     // Number of temporary distributed global index held by each client for each server
1550     // We have this variable for the case of non-distributed element (often axis) to check the duplicate server rank
1551     CArray<int,1> nbIndexOnServerTmp(serverSize);
1552     for (int idx = 0; idx < nbElement; ++idx)
1553     {
1554       nbIndexOnServer = 0;
1555       const std::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
1556       const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
1557       CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
1558       clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
1559       const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
1560       CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
1561                                                                    ite = globalIndexElementOnServerMap.end(), it;
1562       for (it = itb; it != ite; ++it)
1563       {
1564         const std::vector<int>& tmp = it->second;
1565         nbIndexOnServerTmp = 0;
1566         for (int i = 0; i < tmp.size(); ++i)
1567         {
1568           if (0 == nbIndexOnServerTmp(tmp[i])) ++nbIndexOnServerTmp(tmp[i]);
1569         }
1570         nbIndexOnServer += nbIndexOnServerTmp;
1571       }
1572
1573       for (int i = 0; i < serverSize; ++i)
1574       {
1575         if (0 != nbIndexOnServer(i))
1576         {
1577           globalElementIndexOnServer[idx][i].resize(nbIndexOnServer(i));
1578           elementOnServer[idx][i] = true;
1579         }
1580       }
1581
1582     nbIndexOnServer = 0;
1583     for (size_t j = 0; j < globalIndexElementOnServerMap.size(); ++j)
1584     {
1585       it = globalIndexElementOnServerMap.find(globalIndexElementOnClient(j));
1586       if (it != ite)
1587       {
1588         const std::vector<int>& tmp = it->second;
1589         nbIndexOnServerTmp = 0;
1590         for (int i = 0; i < tmp.size(); ++i)
1591         {
1592           if (0 == nbIndexOnServerTmp(tmp[i]))
1593           {
1594             globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer(tmp[i])] = it->first;
1595             ++nbIndexOnServerTmp(tmp[i]);
1596           }
1597         }
1598         nbIndexOnServer += nbIndexOnServerTmp;
1599       }
1600     }
1601   }
1602
1603    // Determine server which contain global source index
1604    std::vector<bool> intersectedProc(serverSize, true);
1605    for (int idx = 0; idx < nbElement; ++idx)
1606    {
1607      std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
1608                     intersectedProc.begin(), intersectedProc.begin(),
1609                     std::logical_and<bool>());
1610    }
1611
1612    std::vector<int> srcRank;
1613    for (int idx = 0; idx < serverSize; ++idx)
1614    {
1615      if (intersectedProc[idx]) srcRank.push_back(idx);
1616    }
1617
1618    // Compute the global index of grid from global index of each element.
1619    for (int i = 0; i < srcRank.size(); ++i)
1620    {
1621      size_t ssize = 1;
1622      int rankSrc = srcRank[i];
1623      std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
1624      std::vector<size_t> currentIndex(nbElement,0);
1625      for (int idx = 0; idx < nbElement; ++idx)
1626      {
1627        ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
1628        globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
1629      }
1630      globalIndexOnServer[rankSrc].resize(ssize);
1631
1632      std::vector<int> idxLoop(nbElement,0);
1633      int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
1634      size_t idx = 0;
1635      while (idx < ssize)
1636      {
1637        for (int ind = 0; ind < nbElement; ++ind)
1638        {
1639          if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
1640          {
1641            idxLoop[ind] = 0;
1642            ++idxLoop[ind+1];
1643          }
1644
1645          currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
1646        }
1647
1648        for (int ind = 0; ind < innnerLoopSize; ++ind)
1649        {
1650          currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
1651          size_t globalSrcIndex = 0;
1652          for (int idxElement = 0; idxElement < nbElement; ++idxElement)
1653          {
1654            globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
1655          }
1656          globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
1657          ++idx;
1658          ++idxLoop[0];
1659        }
1660      }
1661    }
1662   }
1663   CATCH_DUMP_ATTR
1664//----------------------------------------------------------------
1665
1666
1667
1668   CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc)
1669   TRY
1670   {
1671     std::vector<CDomain*> domainSrcTmp = gridSrc->getDomains(), domainSrc;
1672     std::vector<CAxis*> axisSrcTmp = gridSrc->getAxis(), axisSrc;
1673     std::vector<CScalar*> scalarSrcTmp = gridSrc->getScalars(), scalarSrc;
1674
1675     for (int idx = 0; idx < domainSrcTmp.size(); ++idx)
1676     {
1677       CDomain* domain = CDomain::createDomain();
1678       domain->duplicateAttributes(domainSrcTmp[idx]);
1679       domain->duplicateTransformation(domainSrcTmp[idx]);
1680       domain->solveRefInheritance(true);
1681       domain->solveInheritanceTransformation();
1682       domainSrc.push_back(domain);
1683     }
1684
1685     for (int idx = 0; idx < axisSrcTmp.size(); ++idx)
1686     {
1687       CAxis* axis = CAxis::createAxis();
1688       axis->duplicateAttributes(axisSrcTmp[idx]);
1689       axis->duplicateTransformation(axisSrcTmp[idx]);
1690       axis->solveRefInheritance(true);
1691       axis->solveInheritanceTransformation();
1692       axisSrc.push_back(axis);
1693     }
1694
1695     for (int idx = 0; idx < scalarSrcTmp.size(); ++idx)
1696     {
1697       CScalar* scalar = CScalar::createScalar();
1698       scalar->duplicateAttributes(scalarSrcTmp[idx]);
1699       scalar->duplicateTransformation(scalarSrcTmp[idx]);
1700       scalar->solveRefInheritance(true);
1701       scalar->solveInheritanceTransformation();
1702       scalarSrc.push_back(scalar);
1703     }
1704
1705      CGrid* grid = CGrid::createGrid(idNewGrid, domainSrc, axisSrc, scalarSrc, gridSrc->axis_domain_order);
1706
1707      return grid;
1708   }
1709   CATCH
1710
1711   StdString CGrid::generateId(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis,
1712                               const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder)
1713   TRY
1714   {
1715      if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size()))
1716        ERROR("CGrid* CGrid::generateId(...)",
1717              << "The size of axisDomainOrder (" << axisDomainOrder.numElements()
1718              << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<").");
1719
1720      std::ostringstream id;
1721
1722      if (domains.empty() && axis.empty() && !scalars.empty())
1723        id << "__scalar_";
1724
1725      if (0 != (domains.size() + axis.size() + scalars.size()))
1726      {
1727        id << "__grid";
1728
1729        if (0 == axisDomainOrder.numElements())
1730        {
1731          for (size_t i = 0; i < domains.size(); ++i) id << "_" << domains[i]->getId();
1732          for (size_t i = 0; i < axis.size(); ++i) id << "_" << axis[i]->getId();
1733          for (size_t i = 0; i < scalars.size(); ++i) id << "_" << scalars[i]->getId();
1734        }
1735        else
1736        {
1737          size_t iDomain = 0, iAxis = 0, iScalar = 0;
1738          for (size_t i = 0; i < axisDomainOrder.numElements(); ++i)
1739          {
1740            if (2 == axisDomainOrder(i))
1741              id << "_" << domains[iDomain++]->getId();
1742            else if (1 == axisDomainOrder(i))
1743              id << "_" << axis[iAxis++]->getId();
1744            else
1745              id << "_" << scalars[iScalar++]->getId();
1746          }
1747        }
1748
1749        id << "__";
1750      }
1751
1752      return id.str();
1753   }
1754   CATCH
1755
1756   StdString CGrid::generateId(const CGrid* gridSrc, const CGrid* gridDest)
1757   TRY
1758   {
1759     StdString idSrc  = gridSrc->getId();
1760     StdString idDest = gridDest->getId();
1761
1762     std::ostringstream id;
1763     id << idSrc << "__" << idDest;
1764
1765     return id.str();
1766   }
1767   CATCH
1768
1769
1770   //----------------------------------------------------------------
1771
1772   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) 
1773   TRY
1774   {
1775      auto& storeIndex_client = getStoreIndex_client() ;
1776      const StdSize size = storeIndex_client.numElements();
1777
1778      stored.resize(size);
1779      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
1780   }
1781   CATCH
1782
1783   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) 
1784   TRY
1785   {
1786      auto& storeIndex_client=getStoreIndex_client() ;
1787      const StdSize size = storeIndex_client.numElements();
1788
1789      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i);
1790   }
1791   CATCH
1792
1793   void CGrid::maskField_arr(const double* const data, CArray<double, 1>& stored) 
1794   {
1795      auto& storeIndex_client=getStoreIndex_client() ;
1796      auto& storeMask_client=getStoreMask_client() ;
1797       
1798      const StdSize size = storeIndex_client.numElements();
1799      stored.resize(size);
1800      const double nanValue = std::numeric_limits<double>::quiet_NaN();
1801
1802      if (storeMask_client.numElements() != 0)
1803        for(StdSize i = 0; i < size; i++) stored(i) = (storeMask_client(i)) ? data[storeIndex_client(i)] : nanValue;
1804      else
1805        for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)];
1806   }
1807
1808   void CGrid::uncompressField_arr(const double* const data, CArray<double, 1>& out) 
1809   TRY
1810   {
1811      const std::vector<int>& localMaskedDataIndex = getClientDistribution()->getLocalMaskedDataIndexOnClient();
1812      const int size = localMaskedDataIndex.size();
1813      for(int i = 0; i < size; ++i) out(localMaskedDataIndex[i]) = data[i];
1814   }
1815   CATCH
1816
1817 
1818  void CGrid::computeConnectedClientsScalarGrid(CContextClient* client)
1819  TRY
1820  {
1821    if (computeConnectedClientsScalarGrid_done_.count(client)!=0) return ;
1822
1823    CContext* context = CContext::getCurrent();
1824     
1825    set<int> listReceiverSize ;
1826
1827    int receiverSize = client->serverSize;
1828     
1829    if (listReceiverSize.find(receiverSize)==listReceiverSize.end())
1830    {
1831      listReceiverSize.insert(receiverSize) ;
1832      if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end())
1833      {
1834         // delete corresponding map in case of recompute, probably because a grid could has been modifiedd
1835         // by a transformation
1836        connectedServerRank_.erase(receiverSize);
1837        connectedDataSize_.erase(receiverSize);
1838        globalIndexOnServer_.erase(receiverSize);
1839        nbSenders_.erase(receiverSize);
1840      }
1841
1842      if (client->isServerLeader())
1843      {
1844        const std::list<int>& ranks = client->getRanksServerLeader();
1845        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1846        {
1847          int rank = *itRank;
1848          int nb = 1;
1849          connectedServerRank_[receiverSize].push_back(rank);
1850          connectedDataSize_[receiverSize][rank] = nb;
1851          nbSenders_[receiverSize][rank] = nb;
1852        }
1853      }
1854      else
1855      {
1856        const std::list<int>& ranks = client->getRanksServerNotLeader();
1857        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1858        {
1859          int rank = *itRank;
1860          int nb = 1;
1861          connectedServerRank_[receiverSize].push_back(rank);
1862          connectedDataSize_[receiverSize][rank] = nb;
1863          nbSenders_[receiverSize][rank] = nb;
1864        }
1865      }
1866    }
1867   
1868    computeConnectedClientsScalarGrid_done_.insert(client) ;
1869  }
1870  CATCH_DUMP_ATTR
1871
1872  void CGrid::sendIndexScalarGrid(CContextClient* client, const string& gridId)
1873  TRY
1874  {
1875    if (sendIndexScalarGrid_done_.count(client)!=0) return ;
1876    else sendIndexScalarGrid_done_.insert(client) ;
1877
1878    CContext* context = CContext::getCurrent();
1879   
1880    string serverGridId = gridId.empty() ? serverGridId=this->getId() : serverGridId=gridId ;
1881
1882    int receiverSize = client->serverSize;
1883
1884    CEventClient event(getType(), EVENT_ID_INDEX);
1885    list<CMessage> listMsg;
1886    list<CArray<size_t,1> > listOutIndex;
1887
1888    if (client->isServerLeader())
1889    {
1890      const std::list<int>& ranks = client->getRanksServerLeader();
1891      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1892      {
1893        int rank = *itRank;
1894        int nb = 1;
1895        storeIndex_toSrv_[client].insert(std::make_pair(rank, CArray<int,1>(nb)));
1896        listOutIndex.push_back(CArray<size_t,1>(nb));
1897
1898        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv_[client][rank];
1899        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
1900
1901        for (int k = 0; k < nb; ++k)
1902        {
1903          outGlobalIndexOnServer(k) = 0;
1904          outLocalIndexToServer(k)  = 0;
1905        }
1906
1907        if (context->getServiceType()==CServicesManager::CLIENT)  // -> what about for coupling probably unusefull to be check
1908          storeIndex_fromSrv_.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1909
1910        listMsg.push_back(CMessage());
1911        listMsg.back() << serverGridId << isCompressible_ << listOutIndex.back();
1912
1913        event.push(rank, 1, listMsg.back());
1914      }
1915      client->sendEvent(event);
1916    }
1917    else
1918    {
1919      const std::list<int>& ranks = client->getRanksServerNotLeader();
1920      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1921      {
1922        int rank = *itRank;
1923        int nb = 1;         
1924        CArray<int, 1> outLocalIndexToServer(nb);
1925        for (int k = 0; k < nb; ++k)
1926        {
1927          outLocalIndexToServer(k)  = 0;
1928        }
1929
1930        if (context->getServiceType()==CServicesManager::CLIENT)
1931          storeIndex_fromSrv_.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
1932      }
1933      client->sendEvent(event);
1934    }
1935  }
1936  CATCH_DUMP_ATTR
1937
1938  void CGrid::sendIndex(CContextClient* client, const string& gridId)
1939  TRY
1940  {
1941    if (sendIndex_done_.count(client)!=0) return ;
1942    else sendIndex_done_.insert(client) ;
1943    CContext* context = CContext::getCurrent();
1944    string serverGridId = gridId.empty() ? this->getId() : gridId ;
1945
1946
1947
1948    int receiverSize = client->serverSize;
1949
1950    CEventClient event(getType(), EVENT_ID_INDEX);
1951    int rank;
1952    list<CMessage> listMsg;
1953    list<CArray<size_t,1> > listOutIndex;
1954    const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = getClientDistribution()->getGlobalLocalDataSendToServer();
1955    CDistributionClient::GlobalLocalDataMap::const_iterator itbIndex = globalLocalIndexSendToServer.begin(), itIndex,
1956                                                            iteIndex = globalLocalIndexSendToServer.end();
1957    itIndex = itbIndex;                                                             
1958
1959    if (!doGridHaveDataDistributed(client))
1960    {
1961      if (client->isServerLeader())
1962      {
1963        int indexSize = globalLocalIndexSendToServer.size();
1964        CArray<size_t,1> outGlobalIndexOnServer(indexSize);
1965        CArray<int,1> outLocalIndexToServer(indexSize);
1966        for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1967        {
1968          outGlobalIndexOnServer(idx) = itIndex->first;
1969          outLocalIndexToServer(idx) = itIndex->second;
1970        }
1971
1972        const std::list<int>& ranks = client->getRanksServerLeader();
1973        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1974        {
1975          storeIndex_toSrv_[client].insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1976          if (context->getServiceType()==CServicesManager::CLIENT)  // -> what about for coupling probably unusefull to be check
1977            storeIndex_fromSrv_.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
1978         
1979          listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer));
1980
1981          listMsg.push_back(CMessage());
1982          listMsg.back() << serverGridId << isCompressible_ << listOutIndex.back();
1983
1984          event.push(*itRank, 1, listMsg.back());
1985        }
1986        client->sendEvent(event);
1987      }
1988      else
1989      {
1990         int indexSize = globalLocalIndexSendToServer.size();
1991         CArray<int,1> outLocalIndexToServer(indexSize);
1992         for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx)
1993         {
1994           outLocalIndexToServer(idx) = itIndex->second;
1995         }
1996
1997         const std::list<int>& ranks = client->getRanksServerNotLeader();
1998         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1999         {
2000           storeIndex_fromSrv_.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer)));
2001         }
2002         client->sendEvent(event);
2003       }
2004    }
2005    else
2006    {
2007      CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itGlobalMap;
2008      itGlobalMap = globalIndexOnServer_[receiverSize].begin();
2009      iteGlobalMap = globalIndexOnServer_[receiverSize].end();
2010
2011      std::map<int,std::vector<int> >localIndexTmp;
2012      std::map<int,std::vector<size_t> > globalIndexTmp;
2013      for (; itGlobalMap != iteGlobalMap; ++itGlobalMap)
2014      {
2015        int serverRank = itGlobalMap->first;
2016        int indexSize = itGlobalMap->second.size();
2017        const std::vector<size_t>& indexVec = itGlobalMap->second;
2018        for (int idx = 0; idx < indexSize; ++idx)
2019        {
2020          itIndex = globalLocalIndexSendToServer.find(indexVec[idx]);
2021          if (iteIndex != itIndex)
2022          {
2023            globalIndexTmp[serverRank].push_back(itIndex->first);
2024            localIndexTmp[serverRank].push_back(itIndex->second);
2025          }
2026        }
2027      }
2028
2029      for (int ns = 0; ns < connectedServerRank_[receiverSize].size(); ++ns)
2030      {
2031        rank = connectedServerRank_[receiverSize][ns];
2032        int nb = 0;
2033        if (globalIndexTmp.end() != globalIndexTmp.find(rank))
2034          nb = globalIndexTmp[rank].size();
2035
2036        storeIndex_toSrv_[client].insert(make_pair(rank, CArray<int,1>(nb)));
2037        listOutIndex.push_back(CArray<size_t,1>(nb));
2038
2039        CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv_[client][rank];
2040        CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back();
2041
2042        for (int k = 0; k < nb; ++k)
2043        {
2044          outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k);
2045          outLocalIndexToServer(k)  = localIndexTmp[rank].at(k);
2046        }
2047
2048        storeIndex_fromSrv_.insert(make_pair(rank, CArray<int,1>(outLocalIndexToServer)));
2049        listMsg.push_back(CMessage());
2050        listMsg.back() << serverGridId  << isCompressible_ << listOutIndex.back();
2051
2052        event.push(rank, nbSenders_[receiverSize][rank], listMsg.back());
2053      }
2054      client->sendEvent(event);
2055    }
2056  }
2057  CATCH_DUMP_ATTR
2058
2059  void CGrid::recvIndex(CEventServer& event)
2060  TRY
2061  {
2062    string gridId;
2063    vector<int> ranks;
2064    vector<CBufferIn*> buffers;
2065
2066    list<CEventServer::SSubEvent>::iterator it;
2067    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2068    {
2069      ranks.push_back(it->rank);
2070      CBufferIn* buffer = it->buffer;
2071      *buffer >> gridId;
2072      buffers.push_back(buffer);
2073    }
2074    get(gridId)->recvIndex(ranks, buffers, event.getContextServer());
2075  }
2076  CATCH
2077
2078  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers, CContextServer* server)
2079  TRY
2080  {
2081    CContextClient* client = server->getAssociatedClient();
2082    connectedServerRankRead_ = ranks;
2083    for (int n = 0; n < ranks.size(); n++)
2084    {
2085      int rank = ranks[n];
2086      CBufferIn& buffer = *buffers[n];
2087      buffer >>  isCompressible_; // probably to be removed later
2088      CArray<size_t,1> outIndex;
2089      buffer >> outIndex;
2090      outGlobalIndexFromClient_.insert(std::make_pair(rank, outIndex));
2091      connectedDataSizeRead_[rank] = outIndex.numElements();
2092    }
2093    // ym : displaced to avoid collective call at message reception
2094/*
2095    nbReadSenders_[client] = CClientServerMappingDistributed::computeConnectedClients(client->serverSize, client->clientSize,
2096                                                                                     client->intraComm, ranks);
2097*/
2098  }
2099  CATCH_DUMP_ATTR
2100 
2101 
2102  /*!
2103   * Compute the number of connected client for a given contextClient and insert it in the nbReadSenders map.
2104   * /param[in] client : the given contextClient
2105   */
2106  void CGrid::computeNbReadSenders(CContextClient* client) 
2107  TRY
2108 
2109  { 
2110    nbReadSenders_[client] = CClientServerMappingDistributed::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRankRead_);
2111  }
2112  CATCH_DUMP_ATTR
2113 
2114  void CGrid::computeServerDistribution(void)
2115  TRY
2116  {
2117    if (computeServerDistribution_done_) return ;
2118    else computeServerDistribution_done_=true ;
2119
2120    CContext* context = CContext::getCurrent();
2121     
2122    int idx = 0, numElement = axis_domain_order.numElements();
2123    int ssize = numElement;
2124    std::vector<int> indexMap(numElement);
2125    for (int i = 0; i < numElement; ++i)
2126    {
2127      indexMap[i] = idx;
2128      if (2 == axis_domain_order(i))
2129      {
2130        ++ssize;
2131        idx += 2;
2132      }
2133      else
2134        ++idx;
2135    }
2136
2137    for (int n = 0; n < connectedServerRankRead_.size(); n++)
2138    {
2139      int rank = connectedServerRankRead_[n];
2140      size_t dataSize = 0;
2141
2142      if (0 == serverDistribution_)
2143      {
2144        int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
2145        std::vector<CDomain*> domainList = getDomains();
2146        std::vector<CAxis*> axisList = getAxis();
2147        std::vector<int> nBegin(ssize), nSize(ssize), nGlob(ssize), nBeginGlobal(ssize), nGlobElement(numElement);
2148        std::vector<CArray<int,1> > globalIndex(numElement);
2149        for (int i = 0; i < numElement; ++i)
2150        {
2151          nGlobElement[i] = globalSize;
2152          if (2 == axis_domain_order(i)) //domain
2153          {
2154            nBegin[indexMap[i]] = domainList[domainId]->ibegin;
2155            nSize[indexMap[i]]  = domainList[domainId]->ni;
2156            nBeginGlobal[indexMap[i]] = 0;
2157            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
2158
2159            nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
2160            nSize[indexMap[i] + 1] = domainList[domainId]->nj;
2161            nBeginGlobal[indexMap[i] + 1] = 0;
2162            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
2163
2164            {
2165              int count = 0;
2166              globalIndex[i].resize(nSize[indexMap[i]]*nSize[indexMap[i]+1]);
2167              for (int jdx = 0; jdx < nSize[indexMap[i]+1]; ++jdx)
2168                for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
2169                {
2170                  globalIndex[i](count) = (nBegin[indexMap[i]] + idx) + (nBegin[indexMap[i]+1] + jdx) * nGlob[indexMap[i]];
2171                  ++count;
2172                }
2173            }
2174
2175            ++domainId;
2176          }
2177          else if (1 == axis_domain_order(i)) // axis
2178          {
2179            nBegin[indexMap[i]] = axisList[axisId]->begin;
2180            nSize[indexMap[i]]  = axisList[axisId]->n;
2181            nBeginGlobal[indexMap[i]] = 0;
2182            nGlob[indexMap[i]] = axisList[axisId]->n_glo;     
2183            globalIndex[i].resize(nSize[indexMap[i]]);
2184            for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
2185              globalIndex[i](idx) = nBegin[indexMap[i]] + idx;
2186
2187            ++axisId;
2188          }
2189          else // scalar
2190          { 
2191            nBegin[indexMap[i]] = 0;
2192            nSize[indexMap[i]]  = 1;
2193            nBeginGlobal[indexMap[i]] = 0;
2194            nGlob[indexMap[i]] = 1;
2195            globalIndex[i].resize(1);
2196            globalIndex[i](0) = 0;
2197            ++scalarId;
2198          }
2199        }
2200        dataSize = 1;
2201
2202        for (int i = 0; i < nSize.size(); ++i)
2203        dataSize *= nSize[i];
2204        serverDistribution_ = new CDistributionServer(context->intraCommRank_, 
2205                                                      globalIndex, axis_domain_order,
2206                                                      nBegin, nSize, nBeginGlobal, nGlob);
2207      }
2208    }
2209  }
2210  CATCH_DUMP_ATTR
2211
2212
2213
2214
2215
2216
2217/* old interface => transform into compute receivedIndex
2218  void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers, CContextServer* server)
2219  TRY
2220  {
2221    CContext* context = CContext::getCurrent();
2222    connectedServerRankRead_ = ranks;
2223
2224    nbReadSenders_.clear();
2225    CContextClient* client = server->getAssociatedClient();   
2226     
2227    int idx = 0, numElement = axis_domain_order.numElements();
2228    int ssize = numElement;
2229    std::vector<int> indexMap(numElement);
2230    for (int i = 0; i < numElement; ++i)
2231    {
2232      indexMap[i] = idx;
2233      if (2 == axis_domain_order(i))
2234      {
2235        ++ssize;
2236        idx += 2;
2237      }
2238      else
2239        ++idx;
2240    }
2241
2242    for (int n = 0; n < ranks.size(); n++)
2243    {
2244      int rank = ranks[n];
2245      CBufferIn& buffer = *buffers[n];
2246
2247      buffer >>  isCompressible_;
2248      size_t dataSize = 0;
2249
2250      if (0 == serverDistribution_)
2251      {
2252        int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
2253        std::vector<CDomain*> domainList = getDomains();
2254        std::vector<CAxis*> axisList = getAxis();
2255        std::vector<int> nBegin(ssize), nSize(ssize), nGlob(ssize), nBeginGlobal(ssize), nGlobElement(numElement);
2256        std::vector<CArray<int,1> > globalIndex(numElement);
2257        for (int i = 0; i < numElement; ++i)
2258        {
2259          nGlobElement[i] = globalSize;
2260          if (2 == axis_domain_order(i)) //domain
2261          {
2262            nBegin[indexMap[i]] = domainList[domainId]->ibegin;
2263            nSize[indexMap[i]]  = domainList[domainId]->ni;
2264            nBeginGlobal[indexMap[i]] = 0;
2265            nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
2266
2267            nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
2268            nSize[indexMap[i] + 1] = domainList[domainId]->nj;
2269            nBeginGlobal[indexMap[i] + 1] = 0;
2270            nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
2271
2272            {
2273              int count = 0;
2274              globalIndex[i].resize(nSize[indexMap[i]]*nSize[indexMap[i]+1]);
2275              for (int jdx = 0; jdx < nSize[indexMap[i]+1]; ++jdx)
2276                for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
2277                {
2278                  globalIndex[i](count) = (nBegin[indexMap[i]] + idx) + (nBegin[indexMap[i]+1] + jdx) * nGlob[indexMap[i]];
2279                  ++count;
2280                }
2281            }
2282
2283            ++domainId;
2284          }
2285          else if (1 == axis_domain_order(i)) // axis
2286          {
2287            nBegin[indexMap[i]] = axisList[axisId]->begin;
2288            nSize[indexMap[i]]  = axisList[axisId]->n;
2289            nBeginGlobal[indexMap[i]] = 0;
2290            nGlob[indexMap[i]] = axisList[axisId]->n_glo;     
2291            globalIndex[i].resize(nSize[indexMap[i]]);
2292            for (int idx = 0; idx < nSize[indexMap[i]]; ++idx)
2293              globalIndex[i](idx) = nBegin[indexMap[i]] + idx;
2294
2295            ++axisId;
2296          }
2297          else // scalar
2298          {
2299            nBegin[indexMap[i]] = 0;
2300            nSize[indexMap[i]]  = 1;
2301            nBeginGlobal[indexMap[i]] = 0;
2302            nGlob[indexMap[i]] = 1;
2303            globalIndex[i].resize(1);
2304            globalIndex[i](0) = 0;
2305            ++scalarId;
2306          }
2307        }
2308        dataSize = 1;
2309
2310        for (int i = 0; i < nSize.size(); ++i)
2311        dataSize *= nSize[i];
2312        serverDistribution_ = new CDistributionServer(context->intraCommRank_,
2313                                                      globalIndex, axis_domain_order,
2314                                                      nBegin, nSize, nBeginGlobal, nGlob);
2315      }
2316
2317      CArray<size_t,1> outIndex;
2318      buffer >> outIndex;
2319      outGlobalIndexFromClient_.insert(std::make_pair(rank, outIndex));
2320      connectedDataSizeRead_[rank] = outIndex.numElements();
2321
2322      if (doGridHaveDataDistributed(client))
2323      {}
2324      else
2325      {
2326        // THE PROBLEM HERE IS THAT DATA CAN BE NONDISTRIBUTED ON CLIENT AND DISTRIBUTED ON SERVER
2327        // BELOW IS THE TEMPORARY FIX only for a single type of element (domain, asix, scalar)
2328        dataSize = serverDistribution_->getGridSize();
2329      }
2330      writtenDataSize_ += dataSize;
2331    }
2332
2333
2334    // Compute mask of the current grid
2335    {
2336      int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1;
2337      std::vector<CDomain*> domainList = getDomains();
2338      std::vector<CAxis*> axisList = getAxis();
2339      int dimSize = 2 * domainList.size() + axisList.size();
2340      std::vector<int> nBegin(dimSize), nSize(dimSize), nGlob(dimSize), nBeginGlobal(dimSize);       
2341      for (int i = 0; i < numElement; ++i)
2342      {         
2343        if (2 == axis_domain_order(i)) //domain
2344        {
2345          nBegin[indexMap[i]] = domainList[domainId]->ibegin;
2346          nSize[indexMap[i]]  = domainList[domainId]->ni;
2347          nBeginGlobal[indexMap[i]] = 0;             
2348          nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
2349
2350          nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin;
2351          nSize[indexMap[i] + 1] = domainList[domainId]->nj;
2352          nBeginGlobal[indexMap[i] + 1] = 0;             
2353          nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
2354          ++domainId;
2355        }
2356        else if (1 == axis_domain_order(i)) // axis
2357        {
2358          nBegin[indexMap[i]] = axisList[axisId]->begin;
2359          nSize[indexMap[i]]  = axisList[axisId]->n;
2360          nBeginGlobal[indexMap[i]] = 0;             
2361          nGlob[indexMap[i]] = axisList[axisId]->n_glo;             
2362          ++axisId;
2363        }
2364        else // scalar
2365        { 
2366        }
2367      }
2368     
2369      if (nSize.empty()) // Scalar grid
2370      {
2371        nBegin.push_back(0);
2372        nSize.push_back(1);
2373        nBeginGlobal.push_back(0);             
2374        nGlob.push_back(1); 
2375      }
2376    }
2377
2378    if (isScalarGrid()) return;
2379
2380    nbReadSenders_[client] = CClientServerMappingDistributed::computeConnectedClients(client->serverSize, client->clientSize,
2381                                                                                      client->intraComm, ranks);
2382
2383  }
2384  CATCH_DUMP_ATTR
2385*/
2386
2387
2388  /*
2389     Compute on the fly the global dimension of a grid with its elements
2390     \param[in/out] globalDim global dimension of grid
2391     \param[in] domains list of its domains
2392     \param[in] axiss list of its axis
2393     \param[in] scalars list of its scalars
2394     \param[in] axisDomainOrder the order of element in a grid (e.g: scalar then axis)
2395     \return The dimension of which we do distribution (often for server)
2396  */
2397  int CGrid::computeGridGlobalDimension(std::vector<int>& globalDim,
2398                                        const std::vector<CDomain*> domains,
2399                                        const std::vector<CAxis*> axis,
2400                                        const std::vector<CScalar*> scalars,
2401                                        const CArray<int,1>& axisDomainOrder)
2402  TRY
2403 {
2404 //   globalDim.resize(domains.size()*2+axis.size()+scalars.size());
2405    globalDim.resize(domains.size()*2+axis.size());
2406    int positionDimensionDistributed = 1;
2407    int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0;
2408    for (int i = 0; i < axisDomainOrder.numElements(); ++i)
2409    {
2410      if (2 == axisDomainOrder(i))
2411      {
2412        if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured))
2413        {
2414          positionDimensionDistributed = idx;
2415        }
2416        else
2417        {
2418          positionDimensionDistributed = idx +1;
2419        }
2420
2421        globalDim[idx]   = domains[idxDomain]->ni_glo.getValue();
2422        globalDim[idx+1] = domains[idxDomain]->nj_glo.getValue();
2423
2424        ++idxDomain;
2425        idx += 2;
2426      }
2427      else if (1 == axisDomainOrder(i))
2428      {
2429        globalDim[idx] = axis[idxAxis]->n_glo.getValue();
2430        ++idxAxis;
2431        ++idx;
2432      }
2433      else
2434      {
2435//        globalDim[idx] = 1;
2436        ++idxScalar;
2437//        ++idx;
2438      }
2439    }
2440
2441    return positionDimensionDistributed;
2442  }
2443  CATCH_DUMP_ATTR
2444
2445  // Retrieve the global dimension of grid
2446  std::vector<int> CGrid::getGlobalDimension()
2447  TRY
2448  {
2449    std::vector<int> globalDim;
2450    computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);
2451
2452    return globalDim;
2453  }
2454  CATCH_DUMP_ATTR
2455
2456  // Retrieve dimension on which we do distribution (Very often, it should be 2nd dimension)
2457  int CGrid::getDistributedDimension()
2458  TRY
2459  {
2460    std::vector<int> globalDim;
2461    return computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order);   
2462  }
2463  CATCH_DUMP_ATTR
2464
2465  bool CGrid::isScalarGrid() const
2466  TRY
2467  {
2468    return (axisList_.empty() && domList_.empty());
2469  }
2470  CATCH
2471
2472  /*!
2473    Verify whether one server need to write data
2474    There are some cases on which one server has nodata to write. For example, when we
2475    just only want to zoom on a domain.
2476  */
2477  bool CGrid::doGridHaveDataToWrite()
2478  TRY
2479  {
2480     return (0 != getGridLocalElements()->getView(CElementView::FULL)->getSize());
2481  }
2482  CATCH_DUMP_ATTR
2483
2484  /*!
2485    Return size of data which is written on each server
2486    Whatever dimension of a grid, data which are written on server must be presented as
2487    an one dimension array.
2488    \return size of data written on server
2489  */
2490  size_t CGrid::getWrittenDataSize() 
2491  TRY
2492  {
2493    return getGridLocalElements()->getView(CElementView::FULL)->getSize() ;
2494  }
2495  CATCH
2496
2497  /*!
2498    Returns the number of indexes written by each server.
2499    \return the number of indexes written by each server
2500  */
2501  int CGrid::getNumberWrittenIndexes() const
2502  TRY
2503  {
2504    return numberWrittenIndexes_;
2505  }
2506  CATCH
2507
2508  /*!
2509    Returns the total number of indexes written by the servers.
2510    \return the total number of indexes written by the servers
2511  */
2512  int CGrid::getTotalNumberWrittenIndexes() const
2513  TRY
2514  {
2515    return totalNumberWrittenIndexes_;
2516  }
2517  CATCH
2518
2519  /*!
2520    Returns the offset of indexes written by each server.
2521    \return the offset of indexes written by each server
2522  */
2523  int CGrid::getOffsetWrittenIndexes() const
2524  TRY
2525  {
2526    return offsetWrittenIndexes_;
2527  }
2528  CATCH
2529
2530 
2531  CDistributionClient* CGrid::getClientDistribution()
2532  TRY
2533  {
2534    if (!computeClientDistribution_done_) computeClientDistribution() ;
2535    return clientDistribution_;
2536  }
2537  CATCH_DUMP_ATTR
2538
2539  bool CGrid::doGridHaveDataDistributed(CContextClient* client)
2540  TRY
2541  {
2542    // This function is now useless because it will return false only if server and client size are equal to 1
2543    // to be seriously check in future
2544
2545    if (isScalarGrid()) return false;
2546    else if (0 != client)
2547    {
2548      return  (isDataDistributed() ||  (1 != client->clientSize) || (1 != client->serverSize));
2549    }
2550    else
2551      return isDataDistributed();   
2552  }
2553  CATCH_DUMP_ATTR
2554
2555   /*!
2556   \brief Dispatch event received from client
2557      Whenever a message is received in buffer of server, it will be processed depending on
2558   its event type. A new event type should be added in the switch list to make sure
2559   it processed on server side.
2560   \param [in] event: Received message
2561   */
2562  bool CGrid::dispatchEvent(CEventServer& event)
2563  TRY
2564  {
2565
2566    if (SuperClass::dispatchEvent(event)) return true;
2567    else
2568    {
2569      switch(event.type)
2570      {
2571        case EVENT_ID_INDEX :
2572          recvIndex(event);
2573          return true;
2574          break;
2575
2576         case EVENT_ID_ADD_DOMAIN :
2577           recvAddDomain(event);
2578           return true;
2579           break;
2580
2581         case EVENT_ID_ADD_AXIS :
2582           recvAddAxis(event);
2583           return true;
2584           break;
2585
2586         case EVENT_ID_ADD_SCALAR :
2587           recvAddScalar(event);
2588           return true;
2589           break;
2590        default :
2591          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
2592                << "Unknown Event");
2593          return false;
2594      }
2595    }
2596  }
2597  CATCH
2598
2599 
2600
2601  void CGrid::sendGridToFileServer(CContextClient* client)
2602  {
2603    if (sendGridToFileServer_done_.count(client)!=0) return ;
2604    else sendGridToFileServer_done_.insert(client) ;
2605
2606    StdString gridDefRoot("grid_definition");
2607    CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
2608    gridPtr->sendCreateChild(this->getId(),client);
2609    this->sendAllAttributesToServer(client);
2610    //if (isScalarGrid())  sendIndexScalarGrid(client);
2611    //else  sendIndex(client);
2612    //this->sendAllDomains(client);
2613    //this->sendAllAxis(client);
2614    //this->sendAllScalars(client);
2615
2616    distributeGridToFileServer(client) ;
2617  }
2618
2619
2620  void CGrid::distributeGridToFileServer(CContextClient* client)
2621  {
2622    CContext* context = CContext::getCurrent();
2623    // simple Distribution for now
2624    // distribute over the fisrt element except if it is a scalar
2625    auto& elements = getElements() ;
2626    int posDistributed = 0 ;
2627    for(auto& element : elements)
2628    {
2629      if (element.type==TYPE_DOMAIN) break ;
2630      else if (element.type==TYPE_AXIS) break ;
2631      else if (element.type==TYPE_SCALAR) posDistributed++ ;
2632    }
2633   
2634    vector<CLocalView*> localViews ;
2635    vector<CDistributedView*> remoteViews ;
2636
2637    for(int i=0 ; i<elements.size() ; i++)
2638    {
2639      if (elements[i].type==TYPE_DOMAIN) 
2640      { 
2641         CDomain* domain = (CDomain*) elements[i].ptr ;
2642         domain->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2643         remoteViews.push_back(domain->getRemoteElement(client)->getView(CElementView::FULL)) ;
2644         localViews.push_back(domain->getLocalView(CElementView::FULL)) ;
2645      }
2646      else if (elements[i].type==TYPE_AXIS)
2647      {
2648        CAxis* axis = (CAxis*) elements[i].ptr ;
2649        axis->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2650        remoteViews.push_back(axis->getRemoteElement(client)->getView(CElementView::FULL)) ;
2651        localViews.push_back(axis->getLocalView(CElementView::FULL)) ;
2652      }
2653      else if (elements[i].type==TYPE_SCALAR)
2654      {
2655        CScalar* scalar = (CScalar*) elements[i].ptr ;
2656        scalar->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2657        remoteViews.push_back(scalar->getRemoteElement(client)->getView(CElementView::FULL)) ;
2658        localViews.push_back(scalar->getLocalView(CElementView::FULL)) ;
2659      }
2660    }
2661    CGridRemoteConnector gridRemoteConnector(localViews, remoteViews, context->getIntraComm()) ;
2662    gridRemoteConnector.computeConnector() ;
2663   
2664    vector<CScattererConnector*> clientToServerConnectors ;
2665    for(int i=0 ; i<elements.size() ; i++)
2666    {
2667      if (elements[i].type==TYPE_DOMAIN) 
2668      { 
2669         CDomain* domain = (CDomain*) elements[i].ptr ;
2670         sendAddDomain(domain->getId(),client) ;
2671         domain->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2672         clientToServerConnectors.push_back(domain->getClientToServerConnector(client)) ;
2673      }
2674      else if (elements[i].type==TYPE_AXIS)
2675      {
2676        CAxis* axis = (CAxis*) elements[i].ptr ;
2677        sendAddAxis(axis->getId(),client) ;
2678        axis->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2679        clientToServerConnectors.push_back(axis->getClientToServerConnector(client)) ;
2680      }
2681      else if (elements[i].type==TYPE_SCALAR)
2682      {
2683        CScalar* scalar = (CScalar*) elements[i].ptr ;
2684        sendAddScalar(scalar->getId(),client) ;
2685        scalar->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2686        clientToServerConnectors.push_back(scalar->getClientToServerConnector(client)) ;
2687      }
2688    }
2689   
2690    // compute the grid clientToServerConnector to send flux from client to servers
2691    clientToServerConnector_[client] = new CGridScattererConnector(clientToServerConnectors) ;
2692
2693  }
2694
2695
2696  void CGrid::sendGridToCouplerOut(CContextClient* client, const string& fieldId)
2697  {
2698    if (sendGridToCouplerOut_done_.count(client)!=0) return ;
2699    else sendGridToCouplerOut_done_.insert(client) ;
2700 
2701    CContext* context = CContext::getCurrent();
2702    // simple Distribution for now
2703    // distribute over the fisrt element except if it is a scalar
2704    auto& elements = getElements() ;
2705    int posDistributed = 0 ;
2706    for(auto& element : elements)
2707    {
2708      if (element.type==TYPE_DOMAIN) break ;
2709      else if (element.type==TYPE_AXIS) break ;
2710      else if (element.type==TYPE_SCALAR) posDistributed++ ;
2711    }
2712   
2713    vector<CLocalView*> localViews ;
2714    vector<CDistributedView*> remoteViews ;
2715
2716    for(int i=0 ; i<elements.size() ; i++)
2717    {
2718      if (elements[i].type==TYPE_DOMAIN) 
2719      { 
2720         CDomain* domain = (CDomain*) elements[i].ptr ;
2721         domain->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2722         remoteViews.push_back(domain->getRemoteElement(client)->getView(CElementView::FULL)) ;
2723         localViews.push_back(domain->getLocalView(CElementView::FULL)) ;
2724      }
2725      else if (elements[i].type==TYPE_AXIS)
2726      {
2727        CAxis* axis = (CAxis*) elements[i].ptr ;
2728        axis->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2729        remoteViews.push_back(axis->getRemoteElement(client)->getView(CElementView::FULL)) ;
2730        localViews.push_back(axis->getLocalView(CElementView::FULL)) ;
2731      }
2732      else if (elements[i].type==TYPE_SCALAR)
2733      {
2734        CScalar* scalar = (CScalar*) elements[i].ptr ;
2735        scalar->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ;
2736        remoteViews.push_back(scalar->getRemoteElement(client)->getView(CElementView::FULL)) ;
2737        localViews.push_back(scalar->getLocalView(CElementView::FULL)) ;
2738      }
2739    }
2740    CGridRemoteConnector gridRemoteConnector(localViews, remoteViews, context->getIntraComm()) ;
2741    gridRemoteConnector.computeConnector() ;
2742   
2743    vector<CScattererConnector*> clientToClientConnectors ;
2744    for(int i=0 ; i<elements.size() ; i++)
2745    {
2746      if (elements[i].type==TYPE_DOMAIN) 
2747      { 
2748         CDomain* domain = (CDomain*) elements[i].ptr ;
2749         sendAddDomain(domain->getId(),client) ;
2750         domain->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2751         clientToClientConnectors.push_back(domain->getClientToServerConnector(client)) ;
2752      }
2753      else if (elements[i].type==TYPE_AXIS)
2754      {
2755        CAxis* axis = (CAxis*) elements[i].ptr ;
2756        sendAddAxis(axis->getId(),client) ;
2757        axis->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2758        clientToClientConnectors.push_back(axis->getClientToServerConnector(client)) ;
2759      }
2760      else if (elements[i].type==TYPE_SCALAR)
2761      {
2762        CScalar* scalar = (CScalar*) elements[i].ptr ;
2763        sendAddScalar(scalar->getId(),client) ;
2764        scalar->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ;
2765        clientToClientConnectors.push_back(scalar->getClientToServerConnector(client)) ;
2766      }
2767    }
2768   
2769    // compute the grid clientToServerConnector to send flux from client to servers
2770    clientToClientConnector_[client] = new CGridScattererConnector(clientToClientConnectors) ;
2771  }
2772
2773  void CGrid::makeAliasForCoupling(const string& fieldId)
2774  {
2775    string gridId="_grid_of_"+fieldId ;
2776    createAlias(gridId) ;
2777   
2778    const auto& domVect = getDomains() ;
2779    for (int pos=0; pos<domVect.size();pos++) domVect[pos]->makeAliasForCoupling(fieldId, pos);
2780
2781    const auto& axisVect=getAxis() ;
2782    for (int pos=0; pos<axisVect.size();pos++) axisVect[pos]->makeAliasForCoupling(fieldId, pos);
2783
2784    const auto& scalVect=getScalars() ;
2785    for (int pos=0; pos<scalVect.size();pos++) scalVect[pos]->makeAliasForCoupling(fieldId, pos);
2786  }
2787
2788   /*!
2789   \brief Send a message to create a domain on server side
2790   \param[in] id String identity of domain that will be created on server
2791   */
2792   void CGrid::sendAddDomain(const string& id, CContextClient* contextClient)
2793   TRY
2794  {
2795      sendAddItem(id, (int)EVENT_ID_ADD_DOMAIN, contextClient);
2796   }
2797   CATCH_DUMP_ATTR
2798
2799   /*!
2800   \brief Send a message to create an axis on server side
2801   \param[in] id String identity of axis that will be created on server
2802   */
2803   void CGrid::sendAddAxis(const string& id, CContextClient* contextClient)
2804   TRY
2805   {
2806      sendAddItem(id, (int)EVENT_ID_ADD_AXIS, contextClient);
2807   }
2808   CATCH_DUMP_ATTR
2809
2810   /*!
2811   \brief Send a message to create a scalar on server side
2812   \param[in] id String identity of scalar that will be created on server
2813   */
2814   void CGrid::sendAddScalar(const string& id, CContextClient* contextClient)
2815   TRY
2816   {
2817      sendAddItem(id, (int)EVENT_ID_ADD_SCALAR, contextClient);
2818   }
2819   CATCH_DUMP_ATTR
2820
2821   /*!
2822   \brief Receive a message annoucing the creation of a domain on server side
2823   \param[in] event Received event
2824   */
2825   void CGrid::recvAddDomain(CEventServer& event)
2826   TRY
2827   {
2828
2829      CBufferIn* buffer = event.subEvents.begin()->buffer;
2830      string id;
2831      *buffer >> id;
2832      get(id)->recvAddDomain(*buffer);
2833   }
2834   CATCH
2835
2836   /*!
2837   \brief Receive a message annoucing the creation of a domain on server side
2838   \param[in] buffer Buffer containing message
2839   */
2840   void CGrid::recvAddDomain(CBufferIn& buffer)
2841   TRY
2842   {
2843      string id;
2844      buffer >> id;
2845      addDomain(id);
2846   }
2847   CATCH_DUMP_ATTR
2848
2849   /*!
2850   \brief Receive a message annoucing the creation of an axis on server side
2851   \param[in] event Received event
2852   */
2853   void CGrid::recvAddAxis(CEventServer& event)
2854   TRY
2855   {
2856
2857      CBufferIn* buffer = event.subEvents.begin()->buffer;
2858      string id;
2859      *buffer >> id;
2860      get(id)->recvAddAxis(*buffer);
2861   }
2862   CATCH
2863
2864   /*!
2865   \brief Receive a message annoucing the creation of an axis on server side
2866   \param[in] buffer Buffer containing message
2867   */
2868   void CGrid::recvAddAxis(CBufferIn& buffer)
2869   TRY
2870   {
2871      string id;
2872      buffer >> id;
2873      addAxis(id);
2874   }
2875   CATCH_DUMP_ATTR
2876
2877   /*!
2878   \brief Receive a message annoucing the creation of an scalar on server side
2879   \param[in] event Received event
2880   */
2881   void CGrid::recvAddScalar(CEventServer& event)
2882   TRY
2883   {
2884
2885      CBufferIn* buffer = event.subEvents.begin()->buffer;
2886      string id;
2887      *buffer >> id;
2888      get(id)->recvAddScalar(*buffer);
2889   }
2890   CATCH
2891
2892   /*!
2893   \brief Receive a message annoucing the creation of an scalar on server side
2894   \param[in] buffer Buffer containing message
2895   */
2896   void CGrid::recvAddScalar(CBufferIn& buffer)
2897   TRY
2898   {
2899      string id;
2900      buffer >> id;
2901      addScalar(id);
2902   }
2903   CATCH_DUMP_ATTR
2904
2905  /*!
2906  \brief Check if all elements of the grid are complete
2907  Before make any grid processing, we must be sure that all grid information elements have
2908  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
2909  other context (coupling)
2910  */
2911  bool CGrid::isCompleted(void)
2912  {
2913    setDomainList();
2914    for (auto domainId : domList_) if (!CDomain::get(domainId)->isCompleted()) return false ;
2915    setAxisList() ;
2916    for (auto axisId : axisList_) if (!CAxis::get(axisId)->isCompleted()) return false ;
2917    setScalarList() ;
2918    for (auto scalarId : scalarList_) if (!CScalar::get(scalarId)->isCompleted()) return false ;
2919    return true ;
2920  }
2921
2922  /*!
2923  \brief impose that all elements of the grid are complete
2924  Before make any grid processing, we must be sure that all grid information elements have
2925  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
2926  other context (coupling)
2927  */
2928  void CGrid::setCompleted(void)
2929  {
2930    setDomainList();
2931    for (auto domainId : domList_) CDomain::get(domainId)->setCompleted() ;
2932    setAxisList() ;
2933    for (auto axisId : axisList_) CAxis::get(axisId)->setCompleted() ;
2934    setScalarList() ;
2935    for (auto scalarId : scalarList_) CScalar::get(scalarId)->setCompleted() ;
2936  }
2937
2938/*!
2939  \brief impose that all elements of the grid are incomplete
2940  Before make any grid processing, we must be sure that all grid information elements have
2941  been sent, for exemple when reading a grid in a file or when grid elements are sent by an
2942  other context (coupling)
2943  */
2944  void CGrid::unsetCompleted(void)
2945  {
2946    setDomainList();
2947    for (auto domainId : domList_) CDomain::get(domainId)->unsetCompleted() ;
2948    setAxisList() ;
2949    for (auto axisId : axisList_) CAxis::get(axisId)->unsetCompleted() ;
2950    setScalarList() ;
2951    for (auto scalarId : scalarList_) CScalar::get(scalarId)->unsetCompleted() ;
2952  }
2953
2954  /*!
2955  \brief Solve domain and axis references
2956  As field, domain and axis can refer to other domains or axis. In order to inherit correctly
2957  all attributes from their parents, they should be processed with this function
2958  \param[in] apply inherit all attributes of parents (true)
2959  */
2960  void CGrid::solveElementsRefInheritance(bool apply)
2961  TRY
2962  {
2963    setDomainList();
2964    for (auto domainId : domList_)
2965    {
2966      CDomain* pDom = CDomain::get(domainId);
2967      pDom->solveRefInheritance(apply);
2968      pDom->solveInheritanceTransformation();
2969    }
2970
2971    setAxisList();
2972    for (auto axisId : axisList_)
2973    {
2974      CAxis* pAxis = CAxis::get(axisId);
2975      pAxis->solveRefInheritance(apply);
2976      pAxis->solveInheritanceTransformation();
2977    }
2978
2979    setScalarList();
2980    for (auto scalarId : scalarList_)
2981    {
2982      CScalar* pScalar = CScalar::get(scalarId);
2983      pScalar->solveRefInheritance(apply);
2984      pScalar->solveInheritanceTransformation();
2985    }
2986  }
2987  CATCH_DUMP_ATTR
2988
2989 /*!
2990  \brief check attributes of all elements of the grid
2991  */
2992  void CGrid::checkElementsAttributes(void)
2993  TRY
2994  {
2995    setDomainList();
2996    for (auto domainId : domList_) CDomain::get(domainId)->checkAttributes();
2997
2998    setAxisList();
2999    for (auto axisId : axisList_) CAxis::get(axisId)->checkAttributes();
3000   
3001    setScalarList();
3002    for (auto scalarId : scalarList_) CScalar::get(scalarId)->checkAttributes();
3003  }
3004  CATCH_DUMP_ATTR
3005
3006  bool CGrid::isTransformed()
3007  TRY
3008  {
3009    return isTransformed_;
3010  }
3011  CATCH_DUMP_ATTR
3012
3013  void CGrid::setTransformed()
3014  TRY
3015  {
3016    isTransformed_ = true;
3017  }
3018  CATCH_DUMP_ATTR
3019
3020  CGridTransformation* CGrid::getTransformations()
3021  TRY
3022  {
3023    return transformations_;
3024  }
3025  CATCH_DUMP_ATTR
3026
3027  void CGrid::addTransGridSource(CGrid* gridSrc)
3028  TRY
3029  {
3030    if (gridSrc_.end() == gridSrc_.find(gridSrc))
3031      gridSrc_.insert(make_pair(gridSrc,make_pair(false,"")));
3032  }
3033  CATCH_DUMP_ATTR
3034
3035  std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource()
3036  TRY
3037  {
3038    return gridSrc_;
3039  }
3040  CATCH_DUMP_ATTR
3041
3042  /*!
3043     Complete all the necessary (and lacking) attributes of a grid
3044     This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation
3045  */
3046  void CGrid::completeGrid(CGrid* transformGridSrc)
3047  TRY
3048  {
3049    if (nullptr != transformGridSrc)
3050    {
3051      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
3052      {
3053        ERROR("CGrid::completeGrid(CGrid* transformGridSrc)",
3054             << "Two grids have different number of elements. " << std::endl
3055             << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
3056             << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
3057      }
3058    }
3059
3060    if (isGenerated()) return;
3061    setGenerated();
3062
3063    CGridGenerate gridGenerate(this, transformGridSrc);
3064    gridGenerate.completeGrid();
3065  }
3066  CATCH_DUMP_ATTR
3067
3068  bool CGrid::isGenerated()
3069  TRY
3070  {
3071    return isGenerated_;
3072  }
3073  CATCH
3074
3075  void CGrid::setGenerated()
3076  TRY
3077  {
3078    isGenerated_ = true;
3079  }
3080  CATCH_DUMP_ATTR
3081
3082  void CGrid::transformGrid(CGrid* transformGridSrc)
3083  TRY
3084  {
3085    if (!transformGridSrc)
3086      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
3087            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
3088
3089    if (isTransformed()) return;
3090    setTransformed();
3091    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
3092    {
3093      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
3094           << "Two grids have different number of elements. " << std::endl
3095           << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
3096           << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
3097    }
3098    else
3099    {
3100    }
3101
3102    transformations_ = new CGridTransformation(this, transformGridSrc);
3103    transformations_->computeAll();
3104    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
3105
3106    // Ok, now need to compute index of grid source
3107    transformGridSrc->checkMaskIndex(false);
3108  }
3109  CATCH_DUMP_ATTR
3110
3111
3112
3113
3114  void CGrid::prepareTransformGrid(CGrid* transformGridSrc)
3115  TRY
3116  {
3117    if (prepareTransformGrid_done_) return ;
3118
3119    if (!transformGridSrc)
3120      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
3121            << "Impossible to transform grid '" << getId() << "', the source grid is null.");
3122
3123    if (isTransformed()) return;
3124    setTransformed();
3125    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements())
3126    {
3127      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)",
3128           << "Two grids have different number of elements. " << std::endl
3129           << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl
3130           << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements());
3131    }
3132    else
3133    {
3134    }
3135
3136    transformations_ = new CGridTransformation(this, transformGridSrc);
3137    if (0 < transformations_->getNbAlgo()) hasTransform_ = true;
3138
3139    prepareTransformGrid_done_ = true; 
3140  }
3141  CATCH_DUMP_ATTR
3142
3143
3144  void CGrid::makeTransformGrid(void)
3145  TRY
3146  {
3147    if (makeTransformGrid_done_) return ;
3148    transformations_->computeAll();
3149
3150    makeTransformGrid_done_ = true ; 
3151  }
3152  CATCH_DUMP_ATTR
3153
3154
3155  vector<std::string> CGrid::getAuxInputTransformGrid(void)
3156  TRY
3157  {
3158    if (transformations_ != nullptr) return transformations_->getAuxInputs() ;
3159  }
3160  CATCH_DUMP_ATTR
3161
3162
3163
3164
3165
3166
3167
3168  bool CGrid::hasTransform()
3169  TRY
3170  {
3171    if (hasTransform_) return hasTransform_;
3172
3173    std::vector<CDomain*> domList = getDomains();
3174    std::vector<CAxis*> axisList = getAxis();
3175    std::vector<CScalar*> scalarList = getScalars();
3176
3177    for (int idx = 0; idx < domList.size(); ++idx) hasTransform_ |= domList[idx]->hasTransformation();
3178    for (int idx = 0; idx < axisList.size(); ++idx) hasTransform_ |= axisList[idx]->hasTransformation();
3179    for (int idx = 0; idx < scalarList.size(); ++idx) hasTransform_ |= scalarList[idx]->hasTransformation();
3180
3181    return hasTransform_;
3182  }
3183  CATCH_DUMP_ATTR
3184
3185
3186
3187  /*!
3188    Send all attributes of domains from client to server
3189  */
3190  void CGrid::sendAllDomains(CContextClient* contextClient)
3191  TRY
3192  {
3193    std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren();
3194    for (auto domain : domList)
3195    {
3196      sendAddDomain(domain->getId(),contextClient);
3197      domain->sendDomainToFileServer(contextClient);
3198    }
3199  }
3200  CATCH_DUMP_ATTR
3201
3202  /*!
3203    Send all attributes of axis from client to server
3204  */
3205  void CGrid::sendAllAxis(CContextClient* contextClient)
3206  TRY
3207  {
3208    std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren();
3209    for (int i=0; i<aList.size() ; ++i)
3210    {
3211      sendAddAxis(aList[i]->getId(),contextClient);
3212      aList[i]->sendAxisToFileServer(contextClient, getGlobalDimension(), getAxisPositionInGrid()[i]);
3213    }
3214  }
3215  CATCH_DUMP_ATTR
3216
3217  /*!
3218    Send all attributes of scalars from client to server
3219  */
3220  void CGrid::sendAllScalars(CContextClient* contextClient)
3221  TRY
3222  {
3223    std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren();
3224    for (auto scalar : sList)
3225    {
3226      sendAddScalar(scalar->getId(),contextClient);
3227      scalar->sendScalarToFileServer(contextClient);
3228    }
3229  }
3230  CATCH_DUMP_ATTR
3231
3232  void CGrid::setContextClient(CContextClient* contextClient)
3233  TRY
3234  {
3235    if (clientsSet.find(contextClient)==clientsSet.end())
3236    {
3237      clients.push_back(contextClient) ;
3238      clientsSet.insert(contextClient);
3239    }
3240    for (auto domain : getDomains()) domain->setContextClient(contextClient);
3241    for (auto axis : getAxis()) axis->setContextClient(contextClient);
3242    for (auto scalar : getScalars()) scalar->setContextClient(contextClient);
3243   
3244  }
3245  CATCH_DUMP_ATTR
3246
3247 
3248  void CGrid::computeGridLocalElements()
3249  {
3250    std::vector<CDomain*> domainList = this->getDomains();
3251    std::vector<CAxis*> axisList = this->getAxis();
3252    auto domain=domainList.begin() ;
3253    auto axis=axisList.begin() ;
3254    vector<CLocalElement*> elements;
3255    for(auto order : order_)
3256    {
3257      if (order==2) 
3258      {
3259        elements.push_back((*domain)->getLocalElement());
3260        domain++ ;
3261      }
3262      else if (order==1)
3263      {
3264        elements.push_back((*axis)->getLocalElement());
3265        axis++ ;
3266      }
3267      else if (order==0)
3268      { 
3269      }
3270    }
3271    if (hasMask()) 
3272    {
3273      vector<bool> mask(getMask().getVector()) ;
3274      gridLocalElements_ = new CGridLocalElements(elements, mask) ; 
3275    }
3276    else gridLocalElements_ = new CGridLocalElements(elements) ; 
3277  }
3278
3279  void CGrid::computeModelToWorkflowConnector(void)
3280  {
3281    modelToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::MODEL,CElementView::WORKFLOW) ;
3282  }
3283
3284  void CGrid::computeWorkflowToFullConnector(void)
3285  {
3286    workflowToFullConnector_ = getGridLocalElements()->getConnector(CElementView::WORKFLOW,CElementView::FULL) ;
3287  }
3288
3289  void CGrid::computeWorkflowToModelConnector(void)
3290  {
3291    workflowToModelConnector_ = getGridLocalElements()->getConnector(CElementView::WORKFLOW,CElementView::MODEL) ;
3292  }
3293
3294  void CGrid::computeFullToWorkflowConnector(void)
3295  {
3296    fullToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::FULL,CElementView::WORKFLOW) ;
3297  }
3298
3299  void CGrid::computeServerFromClientConnector(void)
3300  {
3301    vector<CGathererConnector*> connectors ;
3302    for(auto& element : getElements())
3303    {
3304      if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerFromClientConnector()) ;
3305      else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerFromClientConnector()) ; 
3306      else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerFromClientConnector()) ; 
3307    }
3308    serverFromClientConnector_ = new CGridGathererConnector(connectors) ;
3309  }
3310
3311  void CGrid::computeClientFromClientConnector(void)
3312  {
3313    vector<CGathererConnector*> connectors ;
3314    for(auto& element : getElements())
3315    {
3316      if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerFromClientConnector()) ;
3317      else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerFromClientConnector()) ; 
3318      else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerFromClientConnector()) ; 
3319    }
3320    clientFromClientConnector_ = new CGridGathererConnector(connectors) ;
3321  }
3322} // namespace xios
Note: See TracBrowser for help on using the repository browser.