source: XIOS/trunk/src/node/domain.cpp @ 764

Last change on this file since 764 was 764, checked in by rlacroix, 6 years ago

Fix the buffer size estimation to avoid requests for unexpected buffers.

  • 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: 66.5 KB
Line 
1#include "domain.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6
7#include "xios_spl.hpp"
8#include "event_client.hpp"
9#include "event_server.hpp"
10#include "buffer_in.hpp"
11#include "message.hpp"
12#include "type.hpp"
13#include "context.hpp"
14#include "context_client.hpp"
15#include "context_server.hpp"
16#include "array_new.hpp"
17#include "distribution_client.hpp"
18#include "server_distribution_description.hpp"
19#include "client_server_mapping_distributed.hpp"
20#include "zoom_domain.hpp"
21#include "interpolate_domain.hpp"
22#include "generate_rectilinear_domain.hpp"
23
24#include <algorithm>
25
26namespace xios {
27
28   /// ////////////////////// Définitions ////////////////////// ///
29
30   CDomain::CDomain(void)
31      : CObjectTemplate<CDomain>(), CDomainAttributes()
32      , isChecked(false), relFiles(), isClientChecked(false), nbConnectedClients_(), indSrv_(), connectedServerRank_()
33      , hasBounds(false), hasArea(false), isDistributed_(false), nGlobDomain_(), isCompressible_(false), isUnstructed_(false)
34      , global_zoom_ni(0), global_zoom_ibegin(0), global_zoom_nj(0), global_zoom_jbegin(0)
35      , isClientAfterTransformationChecked(false), hasLonLat(false)
36      , lonvalue_client(), latvalue_client(), bounds_lon_client(), bounds_lat_client()
37      , srcObject_(0), isRedistributed_(false)
38   { /* Ne rien faire de plus */ }
39
40   CDomain::CDomain(const StdString & id)
41      : CObjectTemplate<CDomain>(id), CDomainAttributes()
42      , isChecked(false), relFiles(), isClientChecked(false), nbConnectedClients_(), indSrv_(), connectedServerRank_()
43      , hasBounds(false), hasArea(false), isDistributed_(false), nGlobDomain_(), isCompressible_(false), isUnstructed_(false)
44      , global_zoom_ni(0), global_zoom_ibegin(0), global_zoom_nj(0), global_zoom_jbegin(0)
45      , isClientAfterTransformationChecked(false), hasLonLat(false)
46      , lonvalue_client(), latvalue_client(), bounds_lon_client(), bounds_lat_client()
47      , srcObject_(0), isRedistributed_(false)
48   { /* Ne rien faire de plus */ }
49
50   CDomain::~CDomain(void)
51   {
52   }
53
54   ///---------------------------------------------------------------
55
56   CDomain* CDomain::createDomain()
57   {
58     CDomain* domain = CDomainGroup::get("domain_definition")->createChild();
59     return domain;
60   }
61
62   void CDomain::duplicateAttributes(CDomain* domain)
63   {
64     domain->setAttributes(this);
65   }
66
67   const std::set<StdString> & CDomain::getRelFiles(void) const
68   {
69      return (this->relFiles);
70   }
71
72   //----------------------------------------------------------------
73
74   const std::vector<int>& CDomain::getIndexesToWrite(void) const
75   {
76     return indexesToWrite;
77   }
78
79   /*!
80     Returns the number of indexes written by each server.
81     \return the number of indexes written by each server
82   */
83   int CDomain::getNumberWrittenIndexes() const
84   {
85     return numberWrittenIndexes_;
86   }
87
88   /*!
89     Returns the total number of indexes written by the servers.
90     \return the total number of indexes written by the servers
91   */
92   int CDomain::getTotalNumberWrittenIndexes() const
93   {
94     return totalNumberWrittenIndexes_;
95   }
96
97   /*!
98     Returns the offset of indexes written by each server.
99     \return the offset of indexes written by each server
100   */
101   int CDomain::getOffsetWrittenIndexes() const
102   {
103     return offsetWrittenIndexes_;
104   }
105
106   //----------------------------------------------------------------
107
108   /*!
109    * Compute the minimum buffer size required to send the attributes to the server(s).
110    *
111    * \return A map associating the server rank with its minimum buffer size.
112    */
113   std::map<int, StdSize> CDomain::getAttributesBufferSize()
114   {
115     CContextClient* client = CContext::getCurrent()->client;
116
117     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes();
118
119     if (client->isServerLeader())
120     {
121       // size estimation for sendServerAttribut
122       size_t size = 11 * sizeof(size_t);
123
124       const std::list<int>& ranks = client->getRanksServerLeader();
125       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
126       {
127         if (size > attributesSizes[*itRank])
128           attributesSizes[*itRank] = size;
129       }
130     }
131
132     std::map<int, std::vector<size_t> >::const_iterator itIndexEnd = indSrv_.end();
133     std::map<int, std::vector<int> >::const_iterator itWrittenIndexEnd = indWrittenSrv_.end();
134     for (size_t k = 0; k < connectedServerRank_.size(); ++k)
135     {
136       int rank = connectedServerRank_[k];
137       std::map<int, std::vector<size_t> >::const_iterator it = indSrv_.find(rank);
138       size_t idxCount = (it != itIndexEnd) ? it->second.size() : 0;
139
140       // size estimation for sendIndex (and sendArea which is always smaller or equal)
141       size_t sizeIndexEvent = 2 * sizeof(size_t) + 2 * CArray<int,1>::size(idxCount);
142       if (isCompressible_)
143       {
144         std::map<int, std::vector<int> >::const_iterator itWritten = indWrittenSrv_.find(rank);
145         size_t writtenIdxCount = (itWritten != itWrittenIndexEnd) ? itWritten->second.size() : 0;
146         sizeIndexEvent += CArray<int,1>::size(writtenIdxCount);
147       }
148
149       // size estimation for sendLonLat
150       size_t sizeLonLatEvent = CArray<double,1>::size(idxCount);
151       if (hasBounds)
152         sizeLonLatEvent += CArray<double,2>::size(nvertex * idxCount);
153
154       size_t size = CEventClient::headerSize + getId().size() + sizeof(size_t) + std::max(sizeIndexEvent, sizeLonLatEvent);
155       if (size > attributesSizes[rank])
156         attributesSizes[rank] = size;
157     }
158
159     return attributesSizes;
160   }
161
162   //----------------------------------------------------------------
163
164   bool CDomain::isEmpty(void) const
165   {
166      return ((this->zoom_ni_srv == 0) ||
167              (this->zoom_nj_srv == 0));
168   }
169
170   //----------------------------------------------------------------
171
172   bool CDomain::IsWritten(const StdString & filename) const
173   {
174      return (this->relFiles.find(filename) != this->relFiles.end());
175   }
176
177   bool CDomain::isWrittenCompressed(const StdString& filename) const
178   {
179      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
180   }
181
182   //----------------------------------------------------------------
183
184   bool CDomain::isDistributed(void) const
185   {
186      return isDistributed_;
187   }
188
189   //----------------------------------------------------------------
190
191   /*!
192    * Test whether the data defined on the domain can be outputted in a compressed way.
193    *
194    * \return true if and only if a mask was defined for this domain
195    */
196   bool CDomain::isCompressible(void) const
197   {
198      return isCompressible_;
199   }
200
201   //----------------------------------------------------------------
202
203   void CDomain::addRelFile(const StdString & filename)
204   {
205      this->relFiles.insert(filename);
206   }
207
208   void CDomain::addRelFileCompressed(const StdString& filename)
209   {
210      this->relFilesCompressed.insert(filename);
211   }
212
213
214   StdString CDomain::GetName(void)   { return (StdString("domain")); }
215   StdString CDomain::GetDefName(void){ return (CDomain::GetName()); }
216   ENodeType CDomain::GetType(void)   { return (eDomain); }
217
218   //----------------------------------------------------------------
219
220   /*!
221     Redistribute RECTILINEAR domain with a number of local domains.
222   All attributes ni,nj,ibegin,jbegin (if defined) will be rewritten
223   The optional attributes lonvalue, latvalue will be added. Because this function only serves (for now)
224   for interpolation from unstructured domain to rectilinear one, range of latvalue is 0-360 and lonvalue is -90 - +90
225    \param [in] nbLocalDomain number of local domain on the domain destination
226   */
227   void CDomain::redistribute(int nbLocalDomain)
228   {
229     if (this->isRedistributed_) return;
230     if (type_attr::rectilinear == type)
231     {
232        this->isRedistributed_ = true;
233
234        CContext* context = CContext::getCurrent();
235        CContextClient* client = context->client;
236        int rankClient = client->clientRank;
237        int rankOnDomain = rankClient%nbLocalDomain;
238
239        if (ni_glo.isEmpty() || ni_glo <= 0 )
240        {
241           ERROR("CDomain::redistribute(int nbLocalDomain)",
242              << "[ Id = " << this->getId() << " ] "
243              << "The global domain is badly defined,"
244              << " check the \'ni_glo\'  value !")
245        }
246
247        if (nj_glo.isEmpty() || nj_glo <= 0 )
248        {
249           ERROR("CDomain::redistribute(int nbLocalDomain)",
250              << "[ Id = " << this->getId() << " ] "
251              << "The global domain is badly defined,"
252              << " check the \'nj_glo\'  value !")
253        }
254
255        int globalDomainSize = ni_glo * nj_glo;
256        if (globalDomainSize <= nbLocalDomain)
257        {
258          for (int idx = 0; idx < nbLocalDomain; ++idx)
259          {
260            if (rankOnDomain < globalDomainSize)
261            {
262              int iIdx = rankOnDomain % ni_glo;
263              int jIdx = rankOnDomain / ni_glo;
264              ibegin.setValue(iIdx); jbegin.setValue(jIdx);
265              ni.setValue(1); nj.setValue(1);
266            }
267            else
268            {
269              ibegin.setValue(0); jbegin.setValue(0);
270              ni.setValue(0); nj.setValue(0);
271            }
272          }
273        }
274        else
275        {
276          float njGlo = nj_glo.getValue();
277          float niGlo = ni_glo.getValue();
278          int nbProcOnX, nbProcOnY, range;
279
280          // Compute (approximately) number of segment on x and y axis
281          float yOverXRatio = njGlo/niGlo;
282
283          nbProcOnX = std::ceil(std::sqrt(nbLocalDomain/yOverXRatio));
284          nbProcOnY = std::ceil(((float)nbLocalDomain)/nbProcOnX);
285
286          // Simple distribution: Sweep from top to bottom, left to right
287          // Calculate local begin on x
288          std::vector<int> ibeginVec(nbProcOnX,0), jbeginVec(nbProcOnY,0);
289          std::vector<int> niVec(nbProcOnX), njVec(nbProcOnY);
290          for (int i = 1; i < nbProcOnX; ++i)
291          {
292            range = ni_glo / nbProcOnX;
293            if (i < (ni_glo%nbProcOnX)) ++range;
294            niVec[i-1] = range;
295            ibeginVec[i] = ibeginVec[i-1] + niVec[i-1];
296          }
297          niVec[nbProcOnX-1] = ni_glo - ibeginVec[nbProcOnX-1];
298
299          // Calculate local begin on y
300          for (int j = 1; j < nbProcOnY; ++j)
301          {
302            range = nj_glo / nbProcOnY;
303            if (j < (nj_glo%nbProcOnY)) ++range;
304            njVec[j-1] = range;
305            jbeginVec[j] = jbeginVec[j-1] + njVec[j-1];
306          }
307          njVec[nbProcOnY-1] = nj_glo - jbeginVec[nbProcOnY-1];
308
309          // Now assign value to ni, ibegin, nj, jbegin
310          int iIdx = rankOnDomain % nbProcOnX;
311          int jIdx = rankOnDomain / nbProcOnX;
312
313          if (rankOnDomain != (nbLocalDomain-1))
314          {
315            ibegin.setValue(ibeginVec[iIdx]);
316            jbegin.setValue(jbeginVec[jIdx]);
317            nj.setValue(njVec[jIdx]);
318            ni.setValue(niVec[iIdx]);
319          }
320          else // just merge all the remaining rectangle into the last one
321          {
322            ibegin.setValue(ibeginVec[iIdx]);
323            jbegin.setValue(jbeginVec[jIdx]);
324            nj.setValue(njVec[jIdx]);
325            ni.setValue(ni_glo - ibeginVec[iIdx]);
326          }
327        }
328
329        // Now fill other attributes
330        fillInRectilinearLonLat();
331     }
332   }
333
334   /*!
335     Fill in the values for lonvalue_1d and latvalue_1d of rectilinear domain
336     Range of longitude value from 0 - 360
337     Range of latitude value from -90 - +90
338   */
339   void CDomain::fillInRectilinearLonLat()
340   {
341     if (!lonvalue_2d.isEmpty()) lonvalue_2d.free();
342     if (!latvalue_2d.isEmpty()) latvalue_1d.free();
343     lonvalue_1d.resize(ni);
344     latvalue_1d.resize(nj);
345
346     double lonRange = lon_end - lon_start;
347     double latRange = lat_end - lat_start;
348
349     double lonStep = (1 == ni_glo.getValue()) ? lonRange : lonRange/double(ni_glo.getValue()-1);
350     double latStep = (1 == nj_glo.getValue()) ? latRange : latRange/double(nj_glo.getValue()-1);
351
352     // Assign lon value
353     for (int i = 0; i < ni; ++i)
354     {
355       if (0 == (ibegin + i))
356       {
357         lonvalue_1d(i) = lon_start;
358       }
359       else if (ni_glo == (ibegin + i + 1))
360       {
361         lonvalue_1d(i) = lon_end;
362       }
363       else
364       {
365         lonvalue_1d(i) = (ibegin + i) * lonStep  + lon_start;
366       }
367     }
368
369     for (int j = 0; j < nj; ++j)
370     {
371       if (0 == (jbegin + j))
372       {
373          latvalue_1d(j) = lat_start;
374       }
375       else if (nj_glo == (jbegin + j + 1))
376       {
377          latvalue_1d(j) = lat_end;
378       }
379       else
380       {
381         latvalue_1d(j) =  (jbegin + j) * latStep + lat_start;
382       }
383     }
384   }
385
386   void CDomain::fillInRectilinearBoundLonLat(CArray<double,2>& boundsLon, CArray<double,2>& boundsLat,
387                                              bool isNorthPole, bool isSouthPole)
388   {
389     int i,j,k;
390     const int nvertexValue = 4;
391
392     double boundsLonRange = bounds_lon_end - bounds_lon_start;
393     double boundsLatRange = bounds_lat_end - bounds_lat_start;
394
395     boundsLon.resize(nvertexValue,ni*nj);
396     boundsLat.resize(nvertexValue,nj*ni);
397
398     double lonStep = boundsLonRange/double(ni_glo.getValue());
399     double latStep = boundsLatRange/double(nj_glo.getValue());
400
401     for(j=0;j<nj;++j)
402       for(i=0;i<ni;++i)
403       {
404         k=j*ni+i;
405         boundsLon(0,k) = boundsLon(1,k) = (0 != (ibegin + i)) ? (ibegin + i) * lonStep + bounds_lon_start
406                                                               : bounds_lon_start;
407         boundsLon(2,k) = boundsLon(3,k) = ((ibegin + i + 1) != ni_glo) ? (ibegin + i +1) * lonStep + bounds_lon_start
408                                                                        : bounds_lon_end;
409       }
410
411     double bounds_lat_start_pole = bounds_lat_start;
412     double bounds_lat_end_pole   = bounds_lat_end;
413     if (isNorthPole) bounds_lat_start_pole = lat_start;
414     if (isSouthPole) bounds_lat_end_pole   = lat_end;
415
416     for(j=0;j<nj;++j)
417       for(i=0;i<ni;++i)
418       {
419         k=j*ni+i;
420         boundsLat(1,k) = boundsLat(2,k) = (0 != (jbegin + j)) ? (jbegin + j) * latStep + bounds_lat_start
421                                                               : bounds_lat_start_pole;
422         boundsLat(0,k) = boundsLat(3,k) = ((jbegin + j +1) != nj_glo) ? (jbegin + j +1) * latStep + bounds_lat_start
423                                                               : bounds_lat_end_pole;
424       }
425   }
426
427   /*!
428     Temporary function to verify whether a rectilinear domain is created automatically.
429   The domain is distributed into number of parts which are equal to number of clients (intracomm)
430   */
431   void CDomain::checkGenerate()
432   {
433     TransMapTypes trans = this->getAllTransformations();
434     TransMapTypes::const_iterator it = trans.begin(), ite = trans.end();
435     int transOrder = 0;
436     for (; it != ite; ++it, ++transOrder)
437     {
438       ETranformationType transType = it->first;
439       if ((TRANS_GENERATE_RECTILINEAR_DOMAIN == transType) && (0 == transOrder))
440       {
441         CContext* context = CContext::getCurrent();
442         CContextClient* client = context->client;
443         int nbClient;
444         MPI_Comm_size(client->intraComm,&nbClient);
445         it->second->checkValid(this);
446         this->redistribute(nbClient);
447         break;
448       }
449     }
450   }
451
452
453   void CDomain::checkDomain(void)
454   {
455     if (type.isEmpty())
456     {
457       ERROR("CDomain::checkDomain(void)",
458             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
459             << "The domain type is mandatory, "
460             << "please define the 'type' attribute.")
461     }
462
463     if (type == type_attr::unstructured)
464     {
465        if (ni_glo.isEmpty())
466        {
467          ERROR("CDomain::checkDomain(void)",
468                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
469                << "The global domain is badly defined, "
470                << "the mandatory 'ni_glo' attribute is missing.")
471        }
472        else if (ni_glo <= 0)
473        {
474          ERROR("CDomain::checkDomain(void)",
475                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
476                << "The global domain is badly defined, "
477                << "'ni_glo' attribute should be strictly positive so 'ni_glo = " << ni_glo.getValue() << "' is invalid.")
478        }
479        isUnstructed_ = true;
480        nj_glo = 1;
481        nj = 1;
482        jbegin = 0;
483        if (ni.isEmpty()) ni = i_index.numElements();
484        j_index.resize(ni);
485        for(int i=0;i<ni;++i) j_index(i)=0;
486
487        if (!area.isEmpty())
488          area.transposeSelf(1, 0);
489     }
490
491     if (ni_glo.isEmpty())
492     {
493       ERROR("CDomain::checkDomain(void)",
494             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
495             << "The global domain is badly defined, "
496             << "the mandatory 'ni_glo' attribute is missing.")
497     }
498     else if (ni_glo <= 0)
499     {
500       ERROR("CDomain::checkDomain(void)",
501             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
502             << "The global domain is badly defined, "
503             << "'ni_glo' attribute should be strictly positive so 'ni_glo = " << ni_glo.getValue() << "' is invalid.")
504     }
505
506     if (nj_glo.isEmpty())
507     {
508       ERROR("CDomain::checkDomain(void)",
509             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
510             << "The global domain is badly defined, "
511             << "the mandatory 'nj_glo' attribute is missing.")
512     }
513     else if (nj_glo <= 0)
514     {
515       ERROR("CDomain::checkDomain(void)",
516             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
517             << "The global domain is badly defined, "
518             << "'nj_glo' attribute should be strictly positive so 'nj_glo = " << nj_glo.getValue() << "' is invalid.")
519     }
520
521     isDistributed_ = !ibegin.isEmpty() || !ni.isEmpty() || !jbegin.isEmpty() || !nj.isEmpty();
522
523     checkLocalIDomain();
524     checkLocalJDomain();
525
526     if (i_index.isEmpty())
527     {
528       i_index.resize(ni*nj);
529       for (int j = 0; j < nj; ++j)
530         for (int i = 0; i < ni; ++i) i_index(i+j*ni) = i+ibegin;
531     }
532
533     if (j_index.isEmpty())
534     {
535       j_index.resize(ni*nj);
536       for (int j = 0; j < nj; ++j)
537         for (int i = 0; i < ni; ++i) j_index(i+j*ni) = j+jbegin;
538     }
539     computeNGlobDomain();
540
541     if (0 == global_zoom_ni) global_zoom_ni = ni_glo;
542     if (0 == global_zoom_nj) global_zoom_nj = nj_glo;
543   }
544
545   //----------------------------------------------------------------
546
547   void CDomain::checkLocalIDomain(void)
548   {
549      if (ibegin.isEmpty() && ni.isEmpty())
550      {
551        ibegin = 0;
552        ni = ni_glo;
553      }
554      else if (!i_index.isEmpty())
555      {
556        if (ibegin.isEmpty()) ibegin = i_index(0);
557      }
558
559      if (ni.getValue() < 0 || ibegin.getValue() < 0 ||
560         (ibegin.getValue() + ni.getValue()) > ni_glo.getValue())
561      {
562        ERROR("CDomain::checkLocalIDomain(void)",
563              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
564              << "The local domain is wrongly defined,"
565              << " check the attributes 'ni_glo' (" << ni_glo.getValue() << "), 'ni' (" << ni.getValue() << ") and 'ibegin' (" << ibegin.getValue() << ")");
566      }
567   }
568
569   void CDomain::checkLocalJDomain(void)
570   {
571     if (jbegin.isEmpty() && nj.isEmpty())
572     {
573       jbegin = 0;
574       nj = nj_glo;
575     }
576     else if (!j_index.isEmpty())
577     {
578       if (jbegin.isEmpty()) jbegin = j_index(0);
579     }
580
581      if (nj.getValue() < 0 || jbegin.getValue() < 0 ||
582         (jbegin.getValue() + nj.getValue()) > nj_glo.getValue())
583      {
584        ERROR("CDomain::checkLocalJDomain(void)",
585              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
586              << "The local domain is wrongly defined,"
587              << " check the attributes 'nj_glo' (" << nj_glo.getValue() << "), 'nj' (" << nj.getValue() << ") and 'jbegin' (" << jbegin.getValue() << ")");
588      }
589   }
590
591   //----------------------------------------------------------------
592
593   void CDomain::checkMask(void)
594   {
595      if (!mask_1d.isEmpty() && !mask_2d.isEmpty())
596        ERROR("CDomain::checkMask(void)",
597              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
598              << "Both mask_1d and mask_2d are defined but only one can be used at the same time." << std::endl
599              << "Please define only one mask: 'mask_1d' or 'mask_2d'.");
600
601      if (!mask_1d.isEmpty() && mask_2d.isEmpty())
602      {
603        if (mask_1d.numElements() != i_index.numElements())
604          ERROR("CDomain::checkMask(void)",
605                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
606                << "'mask_1d' does not have the same size as the local domain." << std::endl
607                << "Local size is " << i_index.numElements() << "." << std::endl
608                << "Mask size is " << mask_1d.numElements() << ".");
609      }
610
611      if (mask_1d.isEmpty() && !mask_2d.isEmpty())
612      {
613        if (mask_2d.extent(0) != ni || mask_2d.extent(1) != nj)
614          ERROR("CDomain::checkMask(void)",
615                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
616                << "The mask does not have the same size as the local domain." << std::endl
617                << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
618                << "Mask size is " << mask_2d.extent(0) << " x " << mask_2d.extent(1) << ".");
619      }
620
621      if (!mask_2d.isEmpty())
622      {
623        mask_1d.resize(mask_2d.extent(0) * mask_2d.extent(1));
624        for (int j = 0; j < nj; ++j)
625          for (int i = 0; i < ni; ++i) mask_1d(i+j*ni) = mask_2d(i,j);
626        mask_2d.free();
627      }
628      else if (mask_1d.isEmpty())
629      {
630        mask_1d.resize(i_index.numElements());
631        for (int i = 0; i < i_index.numElements(); ++i) mask_1d(i) = true;
632      }
633   }
634
635   //----------------------------------------------------------------
636
637   void CDomain::checkDomainData(void)
638   {
639      if (data_dim.isEmpty())
640      {
641        data_dim.setValue(1);
642      }
643      else if (!(data_dim.getValue() == 1 || data_dim.getValue() == 2))
644      {
645        ERROR("CDomain::checkDomainData(void)",
646              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
647              << "The data dimension is invalid, 'data_dim' must be 1 or 2 not << " << data_dim.getValue() << ".");
648      }
649
650      if (data_ibegin.isEmpty())
651         data_ibegin.setValue(0);
652      if (data_jbegin.isEmpty())
653         data_jbegin.setValue(0);
654
655      if (data_ni.isEmpty())
656      {
657        data_ni.setValue((data_dim == 1) ? (ni.getValue() * nj.getValue()) : ni.getValue());
658      }
659      else if (data_ni.getValue() < 0)
660      {
661        ERROR("CDomain::checkDomainData(void)",
662              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
663              << "The data size cannot be negative ('data_ni' = " << data_ni.getValue() << ").");
664      }
665
666      if (data_nj.isEmpty())
667      {
668        data_nj.setValue((data_dim.getValue() == 1) ? (ni.getValue() * nj.getValue()) : nj.getValue());
669      }
670      else if (data_nj.getValue() < 0)
671      {
672        ERROR("CDomain::checkDomainData(void)",
673              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
674              << "The data size cannot be negative ('data_nj' = " << data_nj.getValue() << ").");
675      }
676   }
677
678   //----------------------------------------------------------------
679
680   void CDomain::checkCompression(void)
681   {
682      if (!data_i_index.isEmpty())
683      {
684        if (!data_j_index.isEmpty() &&
685            data_j_index.numElements() != data_i_index.numElements())
686        {
687           ERROR("CDomain::checkCompression(void)",
688                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
689                 << "'data_i_index' and 'data_j_index' arrays must have the same size." << std::endl
690                 << "'data_i_index' size = " << data_i_index.numElements() << std::endl
691                 << "'data_j_index' size = " << data_j_index.numElements());
692        }
693
694        if (2 == data_dim)
695        {
696          if (data_j_index.isEmpty())
697          {
698             ERROR("CDomain::checkCompression(void)",
699                   << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
700                   << "'data_j_index' must be defined when 'data_i_index' is set and 'data_dim' is 2.");
701          }
702        }
703        else // (1 == data_dim)
704        {
705          if (data_j_index.isEmpty())
706          {
707            data_j_index.resize(data_ni);
708            for (int j = 0; j < data_ni; ++j) data_j_index(j) = 0;
709          }
710        }
711      }
712      else
713      {
714        if (data_dim == 2 && !data_j_index.isEmpty())
715          ERROR("CDomain::checkCompression(void)",
716                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
717                << "'data_i_index' must be defined when 'data_j_index' is set and 'data_dim' is 2.");
718
719        if (1 == data_dim)
720        {
721          data_i_index.resize(data_ni);
722          data_j_index.resize(data_ni);
723
724          for (int i = 0; i < data_ni; ++i)
725          {
726            data_i_index(i) = i;
727            data_j_index(i) = 0;
728          }
729        }
730        else // (data_dim == 2)
731        {
732          const int dsize = data_ni * data_nj;
733          data_i_index.resize(dsize);
734          data_j_index.resize(dsize);
735
736          for(int count = 0, j = 0; j < data_nj; ++j)
737          {
738            for(int i = 0; i < data_ni; ++i, ++count)
739            {
740              data_i_index(count) = i;
741              data_j_index(count) = j;
742            }
743          }
744        }
745      }
746   }
747
748   //----------------------------------------------------------------
749
750   void CDomain::checkEligibilityForCompressedOutput(void)
751   {
752     // We don't check if the mask or the indexes are valid here, just if they have been defined at this point.
753     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !data_i_index.isEmpty();
754   }
755
756   //----------------------------------------------------------------
757
758   void CDomain::completeLonLatClient(void)
759   {
760     if (!lonvalue_2d.isEmpty())
761     {
762       lonvalue_client.resize(ni * nj);
763       latvalue_client.resize(ni * nj);
764       if (hasBounds)
765       {
766         bounds_lon_client.resize(nvertex, ni * nj);
767         bounds_lat_client.resize(nvertex, ni * nj);
768       }
769
770       for (int j = 0; j < nj; ++j)
771       {
772         for (int i = 0; i < ni; ++i)
773         {
774           int k = j * ni + i;
775
776           lonvalue_client(k) = lonvalue_2d(i,j);
777           latvalue_client(k) = latvalue_2d(i,j);
778
779           if (hasBounds)
780           {
781             for (int n = 0; n < nvertex; ++n)
782             {
783               bounds_lon_client(n,k) = bounds_lon_2d(n,i,j);
784               bounds_lat_client(n,k) = bounds_lat_2d(n,i,j);
785             }
786           }
787         }
788       }
789     }
790     else if (!lonvalue_1d.isEmpty())
791     {
792       if (type_attr::rectilinear == type)
793       {
794         if (ni == lonvalue_1d.numElements() && nj == latvalue_1d.numElements())
795         {
796           lonvalue_client.resize(ni * nj);
797           latvalue_client.resize(ni * nj);
798           if (hasBounds)
799           {
800             bounds_lon_client.resize(nvertex, ni * nj);
801             bounds_lat_client.resize(nvertex, ni * nj);
802           }
803
804           for (int j = 0; j < nj; ++j)
805           {
806             for (int i = 0; i < ni; ++i)
807             {
808               int k = j * ni + i;
809
810               lonvalue_client(k) = lonvalue_1d(i);
811               latvalue_client(k) = latvalue_1d(j);
812
813               if (hasBounds)
814               {
815                 for (int n = 0; n < nvertex; ++n)
816                 {
817                   bounds_lon_client(n,k) = bounds_lon_1d(n,i);
818                   bounds_lat_client(n,k) = bounds_lat_1d(n,j);
819                 }
820               }
821             }
822           }
823         }
824         else
825           ERROR("CDomain::completeLonClient(void)",
826                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
827                 << "'lonvalue_1d' and 'latvalue_1d' does not have the same size as the local domain." << std::endl
828                 << "'lonvalue_1d' size is " << lonvalue_1d.numElements() << " but it should be " << ni.getValue() << '.' << std::endl
829                 << "'latvalue_1d' size is " << latvalue_1d.numElements() << " but it should be " << nj.getValue() << '.');
830       }
831       else if (type == type_attr::curvilinear || type == type_attr::unstructured)
832       {
833         lonvalue_client.reference(lonvalue_1d);
834         latvalue_client.reference(latvalue_1d);
835         if (hasBounds)
836         {
837           bounds_lon_client.reference(bounds_lon_1d);
838           bounds_lat_client.reference(bounds_lat_1d);
839         }
840       }
841     }
842   }
843
844   void CDomain::checkBounds(void)
845   {
846     if (!nvertex.isEmpty() && nvertex > 0)
847     {
848       if (!bounds_lon_1d.isEmpty() && !bounds_lon_2d.isEmpty())
849         ERROR("CDomain::checkBounds(void)",
850               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
851               << "Only one longitude boundary attribute can be used but both 'bounds_lon_1d' and 'bounds_lon_2d' are defined." << std::endl
852               << "Define only one longitude boundary attribute: 'bounds_lon_1d' or 'bounds_lon_2d'.");
853
854       if (!bounds_lat_1d.isEmpty() && !bounds_lat_2d.isEmpty())
855         ERROR("CDomain::checkBounds(void)",
856               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
857               << "Only one latitude boundary attribute can be used but both 'bounds_lat_1d' and 'bounds_lat_2d' are defined." << std::endl
858               << "Define only one latitude boundary attribute: 'bounds_lat_1d' or 'bounds_lat_2d'.");
859
860       if ((!bounds_lon_1d.isEmpty() && bounds_lat_1d.isEmpty()) || (bounds_lon_1d.isEmpty() && !bounds_lat_1d.isEmpty()))
861       {
862         ERROR("CDomain::checkBounds(void)",
863               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
864               << "Only 'bounds_lon_1d' or 'bounds_lat_1d' is defined." << std::endl
865               << "Please define either both attributes or none.");
866       }
867
868       if ((!bounds_lon_2d.isEmpty() && bounds_lat_2d.isEmpty()) || (bounds_lon_2d.isEmpty() && !bounds_lat_2d.isEmpty()))
869       {
870         ERROR("CDomain::checkBounds(void)",
871               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
872               << "Only 'bounds_lon_2d' or 'bounds_lat_2d' is defined." << std::endl
873               << "Please define either both attributes or none.");
874       }
875
876       if (!bounds_lon_1d.isEmpty() && nvertex.getValue() != bounds_lon_1d.extent(0))
877         ERROR("CDomain::checkBounds(void)",
878               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
879               << "'bounds_lon_1d' dimension is not compatible with 'nvertex'." << std::endl
880               << "'bounds_lon_1d' dimension is " << bounds_lon_1d.extent(1)
881               << " but nvertex is " << nvertex.getValue() << ".");
882
883       if (!bounds_lon_2d.isEmpty() && nvertex.getValue() != bounds_lon_2d.extent(0))
884         ERROR("CDomain::checkBounds(void)",
885               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
886               << "'bounds_lon_2d' dimension is not compatible with 'nvertex'." << std::endl
887               << "'bounds_lon_2d' dimension is " << bounds_lon_2d.extent(2)
888               << " but nvertex is " << nvertex.getValue() << ".");
889
890       if (!bounds_lon_1d.isEmpty() && lonvalue_1d.isEmpty())
891         ERROR("CDomain::checkBounds(void)",
892               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
893               << "Since 'bounds_lon_1d' is defined, 'lonvalue_1d' must be defined too." << std::endl);
894
895       if (!bounds_lon_2d.isEmpty() && lonvalue_2d.isEmpty())
896         ERROR("CDomain::checkBounds(void)",
897               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
898               << "Since 'bounds_lon_2d' is defined, 'lonvalue_2d' must be defined too." << std::endl);
899
900       if (!bounds_lat_1d.isEmpty() && nvertex.getValue() != bounds_lat_1d.extent(0))
901         ERROR("CDomain::checkBounds(void)",
902               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
903               << "'bounds_lat_1d' dimension is not compatible with 'nvertex'." << std::endl
904               << "'bounds_lat_1d' dimension is " << bounds_lat_1d.extent(1)
905               << " but nvertex is " << nvertex.getValue() << ".");
906
907       if (!bounds_lat_2d.isEmpty() && nvertex.getValue() != bounds_lat_2d.extent(0))
908         ERROR("CDomain::checkBounds(void)",
909               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
910               << "'bounds_lat_2d' dimension is not compatible with 'nvertex'." << std::endl
911               << "'bounds_lat_2d' dimension is " << bounds_lat_2d.extent(2)
912               << " but nvertex is " << nvertex.getValue() << ".");
913
914       if (!bounds_lat_1d.isEmpty() && latvalue_1d.isEmpty())
915         ERROR("CDomain::checkBounds(void)",
916               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
917               << "Since 'bounds_lat_1d' is defined, 'latvalue_1d' must be defined too." << std::endl);
918
919       if (!bounds_lat_2d.isEmpty() && latvalue_2d.isEmpty())
920         ERROR("CDomain::checkBounds(void)",
921               << "Since 'bounds_lat_2d' is defined, 'latvalue_2d' must be defined too." << std::endl);
922
923       hasBounds = true;
924     }
925     else
926     {
927       hasBounds = false;
928       nvertex = 0;
929     }
930   }
931
932   void CDomain::checkArea(void)
933   {
934     hasArea = !area.isEmpty();
935     if (hasArea)
936     {
937       if (area.extent(0) != ni || area.extent(1) != nj)
938       {
939         ERROR("CDomain::checkArea(void)",
940               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
941               << "The area does not have the same size as the local domain." << std::endl
942               << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
943               << "Area size is " << area.extent(0) << " x " << area.extent(1) << ".");
944       }
945     }
946   }
947
948   void CDomain::checkLonLat()
949   {
950     hasLonLat = (!latvalue_1d.isEmpty() && !lonvalue_1d.isEmpty()) ||
951                 (!latvalue_2d.isEmpty() && !lonvalue_2d.isEmpty());
952     if (hasLonLat)
953     {
954       if (!lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
955         ERROR("CDomain::checkLonLat()",
956               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
957               << "Only one longitude attribute can be used but both 'lonvalue_1d' and 'lonvalue_2d' are defined." << std::endl
958               << "Define only one longitude attribute: 'lonvalue_1d' or 'lonvalue_2d'.");
959
960       if (!lonvalue_1d.isEmpty() && lonvalue_2d.isEmpty())
961       {
962         if ((type_attr::rectilinear != type) && (lonvalue_1d.numElements() != i_index.numElements()))
963           ERROR("CDomain::checkLonLat()",
964                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
965                 << "'lonvalue_1d' does not have the same size as the local domain." << std::endl
966                 << "Local size is " << i_index.numElements() << "." << std::endl
967                 << "'lonvalue_1d' size is " << lonvalue_1d.numElements() << ".");
968       }
969
970       if (lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
971       {
972         if (lonvalue_2d.extent(0) != ni || lonvalue_2d.extent(1) != nj)
973           ERROR("CDomain::checkLonLat()",
974                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
975                 << "'lonvalue_2d' does not have the same size as the local domain." << std::endl
976                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
977                 << "'lonvalue_2d' size is " << lonvalue_2d.extent(0) << " x " << lonvalue_2d.extent(1) << ".");
978       }
979
980       if (!latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
981         ERROR("CDomain::checkLonLat()",
982               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
983               << "Only one latitude attribute can be used but both 'latvalue_1d' and 'latvalue_2d' are defined." << std::endl
984               << "Define only one latitude attribute: 'latvalue_1d' or 'latvalue_2d'.");
985
986       if (!latvalue_1d.isEmpty() && latvalue_2d.isEmpty())
987       {
988         if ((type_attr::rectilinear != type) && (latvalue_1d.numElements() != i_index.numElements()))
989           ERROR("CDomain::checkLonLat()",
990                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
991                 << "'latvalue_1d' does not have the same size as the local domain." << std::endl
992                 << "Local size is " << i_index.numElements() << "." << std::endl
993                 << "'latvalue_1d' size is " << latvalue_1d.numElements() << ".");
994       }
995
996       if (latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
997       {
998         if (latvalue_2d.extent(0) != ni || latvalue_2d.extent(1) != nj)
999           ERROR("CDomain::checkLonLat()",
1000                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1001                 << "'latvalue_2d' does not have the same size as the local domain." << std::endl
1002                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1003                 << "'latvalue_2d' size is " << latvalue_2d.extent(0) << " x " << latvalue_2d.extent(1) << ".");
1004       }
1005     }
1006   }
1007
1008   void CDomain::checkAttributesOnClientAfterTransformation()
1009   {
1010     CContext* context=CContext::getCurrent() ;
1011
1012     if (this->isClientAfterTransformationChecked) return;
1013     if (context->hasClient)
1014     {
1015       this->checkMask();
1016       if (hasLonLat || hasArea || isCompressible_) this->computeConnectedServer();
1017       if (hasLonLat) this->completeLonLatClient();
1018     }
1019
1020     this->isClientAfterTransformationChecked = true;
1021   }
1022
1023   //----------------------------------------------------------------
1024   // Divide function checkAttributes into 2 seperate ones
1025   // This function only checks all attributes of current domain
1026   void CDomain::checkAttributesOnClient()
1027   {
1028     if (this->isClientChecked) return;
1029     CContext* context=CContext::getCurrent();
1030
1031      this->checkGenerate();
1032      this->checkDomain();
1033      this->checkBounds();
1034      this->checkArea();
1035      this->checkLonLat();
1036
1037      if (context->hasClient)
1038      { // CÃŽté client uniquement
1039         this->checkMask();
1040         this->checkDomainData();
1041         this->checkCompression();
1042      }
1043      else
1044      { // CÃŽté serveur uniquement
1045      }
1046
1047      this->isClientChecked = true;
1048   }
1049
1050   // Send all checked attributes to server
1051   void CDomain::sendCheckedAttributes()
1052   {
1053     if (!this->isClientChecked) checkAttributesOnClient();
1054     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation();
1055     CContext* context=CContext::getCurrent() ;
1056
1057     if (this->isChecked) return;
1058     if (context->hasClient)
1059     {
1060       sendServerAttribut();
1061       if (hasLonLat || hasArea || isCompressible_) sendLonLatArea();
1062     }
1063     this->isChecked = true;
1064   }
1065
1066   void CDomain::checkAttributes(void)
1067   {
1068      if (this->isChecked) return;
1069      CContext* context=CContext::getCurrent() ;
1070
1071      this->checkDomain();
1072      this->checkLonLat();
1073      this->checkBounds();
1074      this->checkArea();
1075
1076      if (context->hasClient)
1077      { // CÃŽté client uniquement
1078         this->checkMask();
1079         this->checkDomainData();
1080         this->checkCompression();
1081
1082      }
1083      else
1084      { // CÃŽté serveur uniquement
1085      }
1086
1087      if (context->hasClient)
1088      {
1089        this->computeConnectedServer();
1090        this->completeLonLatClient();
1091        this->sendServerAttribut();
1092        this->sendLonLatArea();
1093      }
1094
1095      this->isChecked = true;
1096   }
1097
1098  void CDomain::sendServerAttribut(void)
1099  {
1100    CServerDistributionDescription serverDescription(nGlobDomain_);
1101
1102    CContext* context = CContext::getCurrent();
1103    CContextClient* client = context->client;
1104    int nbServer = client->serverSize;
1105
1106    if (isUnstructed_) serverDescription.computeServerDistribution(nbServer,0);
1107    else serverDescription.computeServerDistribution(nbServer,1);
1108
1109    std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
1110    std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
1111
1112    CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT);
1113    if (client->isServerLeader())
1114    {
1115      std::list<CMessage> msgs;
1116
1117      const std::list<int>& ranks = client->getRanksServerLeader();
1118      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1119      {
1120        // Use const int to ensure CMessage holds a copy of the value instead of just a reference
1121        const int ibegin_srv = serverIndexBegin[*itRank][0];
1122        const int jbegin_srv = serverIndexBegin[*itRank][1];
1123        const int ni_srv = serverDimensionSizes[*itRank][0];
1124        const int nj_srv = serverDimensionSizes[*itRank][1];
1125        const int iend_srv = ibegin_srv + ni_srv - 1;
1126        const int jend_srv = jbegin_srv + nj_srv - 1;
1127
1128        msgs.push_back(CMessage());
1129        CMessage& msg = msgs.back();
1130        msg << this->getId() ;
1131        msg << ni_srv << ibegin_srv << iend_srv << nj_srv << jbegin_srv << jend_srv;
1132        msg << global_zoom_ni << global_zoom_ibegin << global_zoom_nj << global_zoom_jbegin;
1133        msg << isCompressible_;
1134
1135        event.push(*itRank,1,msg);
1136      }
1137      client->sendEvent(event);
1138    }
1139    else client->sendEvent(event);
1140  }
1141
1142  void CDomain::computeNGlobDomain()
1143  {
1144    nGlobDomain_.resize(2);
1145    nGlobDomain_[0] = ni_glo.getValue();
1146    nGlobDomain_[1] = nj_glo.getValue();
1147  }
1148
1149  void CDomain::computeConnectedServer(void)
1150  {
1151    CContext* context=CContext::getCurrent() ;
1152    CContextClient* client=context->client ;
1153    int nbServer=client->serverSize;
1154    bool doComputeGlobalIndexServer = true;
1155
1156    int i,j,i_ind,j_ind, nbIndex;
1157    int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1 ;
1158    int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1 ;
1159
1160    // Precompute number of index
1161    int globalIndexCountZoom = 0;
1162    nbIndex = i_index.numElements();
1163    for (i = 0; i < nbIndex; ++i)
1164    {
1165      i_ind=i_index(i);
1166      j_ind=j_index(i);
1167
1168      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1169      {
1170        ++globalIndexCountZoom;
1171      }
1172    }
1173
1174    int globalIndexWrittenCount = 0;
1175    if (isCompressible_)
1176    {
1177      for (i = 0; i < data_i_index.numElements(); ++i)
1178      {
1179        i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1180                                                    data_ibegin, data_jbegin, data_dim, ni,
1181                                                    j_ind);
1182        if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1183        {
1184          i_ind += ibegin;
1185          j_ind += jbegin;
1186          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1187            ++globalIndexWrittenCount;
1188        }
1189      }
1190    }
1191
1192    // Fill in index
1193    CArray<size_t,1> globalIndexDomainZoom(globalIndexCountZoom);
1194    CArray<size_t,1> localIndexDomainZoom(globalIndexCountZoom);
1195    CArray<size_t,1> globalIndexDomain(nbIndex);
1196    size_t globalIndex;
1197    int globalIndexCount = 0;
1198    globalIndexCountZoom = 0;
1199
1200    for (i = 0; i < nbIndex; ++i)
1201    {
1202      i_ind=i_index(i);
1203      j_ind=j_index(i);
1204      globalIndex = i_ind + j_ind * ni_glo;
1205      globalIndexDomain(globalIndexCount) = globalIndex;
1206      ++globalIndexCount;
1207      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1208      {
1209        globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
1210        localIndexDomainZoom(globalIndexCountZoom) = i;
1211        ++globalIndexCountZoom;
1212      }
1213    }
1214
1215    CArray<int,1> globalIndexWrittenDomain(globalIndexWrittenCount);
1216    if (isCompressible_)
1217    {
1218      globalIndexWrittenCount = 0;
1219      for (i = 0; i < data_i_index.numElements(); ++i)
1220      {
1221        i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1222                                                    data_ibegin, data_jbegin, data_dim, ni,
1223                                                    j_ind);
1224        if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1225        {
1226          i_ind += ibegin;
1227          j_ind += jbegin;
1228          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1229          {
1230            globalIndexWrittenDomain(globalIndexWrittenCount) = i_ind + j_ind * ni_glo;
1231            ++globalIndexWrittenCount;
1232          }
1233        }
1234      }
1235    }
1236
1237    size_t globalSizeIndex = 1, indexBegin, indexEnd;
1238    int range, clientSize = client->clientSize;
1239    for (int i = 0; i < nGlobDomain_.size(); ++i) globalSizeIndex *= nGlobDomain_[i];
1240    indexBegin = 0;
1241    for (int i = 0; i < clientSize; ++i)
1242    {
1243      range = globalSizeIndex / clientSize;
1244      if (i < (globalSizeIndex%clientSize)) ++range;
1245      if (i == client->clientRank) break;
1246      indexBegin += range;
1247    }
1248    indexEnd = indexBegin + range - 1;
1249
1250    CServerDistributionDescription serverDescription(nGlobDomain_);
1251    if (isUnstructed_) serverDescription.computeServerGlobalIndexInRange(nbServer, std::make_pair<size_t,size_t>(indexBegin, indexEnd), 0);
1252    else serverDescription.computeServerGlobalIndexInRange(nbServer, std::make_pair<size_t,size_t>(indexBegin, indexEnd), 1);
1253
1254    CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(),
1255                                                                                client->intraComm);
1256    clientServerMap->computeServerIndexMapping(globalIndexDomain);
1257    const std::map<int, std::vector<size_t> >& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer();
1258
1259    std::map<int, std::vector<size_t> >::const_iterator it = globalIndexDomainOnServer.begin(),
1260                                                       ite = globalIndexDomainOnServer.end();
1261    typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
1262    std::vector<int>::iterator itVec;
1263
1264    indSrv_.clear();
1265    indWrittenSrv_.clear();
1266    for (; it != ite; ++it)
1267    {
1268      int rank = it->first;
1269      int indexSize = it->second.size();
1270      std::vector<int> permutIndex(indexSize);
1271      XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
1272      XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(it->second, permutIndex);
1273      BinarySearch binSearch(it->second);
1274      int nb = globalIndexDomainZoom.numElements();
1275      for (int i = 0; i < nb; ++i)
1276      {
1277        if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexDomainZoom(i), itVec))
1278        {
1279          indSrv_[rank].push_back(localIndexDomainZoom(i));
1280        }
1281      }
1282      for (int i = 0; i < globalIndexWrittenDomain.numElements(); ++i)
1283      {
1284        if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexWrittenDomain(i), itVec))
1285        {
1286          indWrittenSrv_[rank].push_back(globalIndexWrittenDomain(i));
1287        }
1288      }
1289    }
1290
1291    connectedServerRank_.clear();
1292    for (it = globalIndexDomainOnServer.begin(); it != ite; ++it) {
1293      connectedServerRank_.push_back(it->first);
1294    }
1295
1296    nbConnectedClients_ = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
1297
1298    delete clientServerMap;
1299  }
1300
1301  const std::map<int, vector<size_t> >& CDomain::getIndexServer() const
1302  {
1303    return indSrv_;
1304  }
1305
1306  /*!
1307    Send index from client to server(s)
1308  */
1309  void CDomain::sendIndex()
1310  {
1311    int ns, n, i, j, ind, nv, idx;
1312    CContext* context = CContext::getCurrent();
1313    CContextClient* client=context->client;
1314
1315    CEventClient eventIndex(getType(), EVENT_ID_INDEX);
1316
1317    list<CMessage> list_msgsIndex;
1318    list<CArray<int,1> > list_indi, list_indj, list_writtenInd;
1319
1320    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1321    iteMap = indSrv_.end();
1322    for (int k = 0; k < connectedServerRank_.size(); ++k)
1323    {
1324      int nbData = 0;
1325      int rank = connectedServerRank_[k];
1326      it = indSrv_.find(rank);
1327      if (iteMap != it)
1328        nbData = it->second.size();
1329
1330      list_indi.push_back(CArray<int,1>(nbData));
1331      list_indj.push_back(CArray<int,1>(nbData));
1332
1333      CArray<int,1>& indi = list_indi.back();
1334      CArray<int,1>& indj = list_indj.back();
1335      const std::vector<size_t>& temp = it->second;
1336      for (n = 0; n < nbData; ++n)
1337      {
1338        idx = static_cast<int>(it->second[n]);
1339        indi(n) = i_index(idx);
1340        indj(n) = j_index(idx);
1341      }
1342
1343      list_msgsIndex.push_back(CMessage());
1344
1345      list_msgsIndex.back() << this->getId() << (int)type; // enum ne fonctionne pour les message => ToFix
1346      list_msgsIndex.back() << isCurvilinear;
1347      list_msgsIndex.back() << list_indi.back() << list_indj.back();
1348
1349      if (isCompressible_)
1350      {
1351        std::vector<int>& writtenIndSrc = indWrittenSrv_[rank];
1352        list_writtenInd.push_back(CArray<int,1>(writtenIndSrc.size()));
1353        CArray<int,1>& writtenInd = list_writtenInd.back();
1354
1355        for (n = 0; n < writtenInd.numElements(); ++n)
1356          writtenInd(n) = writtenIndSrc[n];
1357
1358        list_msgsIndex.back() << writtenInd;
1359      }
1360
1361      eventIndex.push(rank, nbConnectedClients_[rank], list_msgsIndex.back());
1362    }
1363
1364    client->sendEvent(eventIndex);
1365  }
1366
1367  /*!
1368    Send area from client to server(s)
1369  */
1370  void CDomain::sendArea()
1371  {
1372    if (!hasArea) return;
1373
1374    int ns, n, i, j, ind, nv, idx;
1375    CContext* context = CContext::getCurrent();
1376    CContextClient* client=context->client;
1377
1378    // send area for each connected server
1379    CEventClient eventArea(getType(), EVENT_ID_AREA);
1380
1381    list<CMessage> list_msgsArea;
1382    list<CArray<double,1> > list_area;
1383
1384    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1385    iteMap = indSrv_.end();
1386    for (int k = 0; k < connectedServerRank_.size(); ++k)
1387    {
1388      int nbData = 0;
1389      int rank = connectedServerRank_[k];
1390      it = indSrv_.find(rank);
1391      if (iteMap != it)
1392        nbData = it->second.size();
1393      list_area.push_back(CArray<double,1>(nbData));
1394
1395      const std::vector<size_t>& temp = it->second;
1396      for (n = 0; n < nbData; ++n)
1397      {
1398        idx = static_cast<int>(it->second[n]);
1399        i = i_index(idx);
1400        j = j_index(idx);
1401        if (hasArea)
1402          list_area.back()(n) = area(i - ibegin, j - jbegin);
1403      }
1404
1405      list_msgsArea.push_back(CMessage());
1406      list_msgsArea.back() << this->getId() << list_area.back();
1407      eventArea.push(rank, nbConnectedClients_[rank], list_msgsArea.back());
1408    }
1409    client->sendEvent(eventArea);
1410  }
1411
1412  /*!
1413    Send longitude and latitude from client to servers
1414    Each client send long and lat information to corresponding connected server(s).
1415    Because longitude and latitude are optional, this function only called if latitude and longitude exist
1416  */
1417  void CDomain::sendLonLat()
1418  {
1419    if (!hasLonLat) return;
1420
1421    int ns, n, i, j, ind, nv, idx;
1422    CContext* context = CContext::getCurrent();
1423    CContextClient* client=context->client;
1424
1425    // send lon lat for each connected server
1426    CEventClient eventLon(getType(), EVENT_ID_LON);
1427    CEventClient eventLat(getType(), EVENT_ID_LAT);
1428
1429    list<CMessage> list_msgsLon, list_msgsLat;
1430    list<CArray<double,1> > list_lon, list_lat;
1431    list<CArray<double,2> > list_boundslon, list_boundslat;
1432
1433    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1434    iteMap = indSrv_.end();
1435    for (int k = 0; k < connectedServerRank_.size(); ++k)
1436    {
1437      int nbData = 0;
1438      int rank = connectedServerRank_[k];
1439      it = indSrv_.find(rank);
1440      if (iteMap != it)
1441        nbData = it->second.size();
1442
1443      list_lon.push_back(CArray<double,1>(nbData));
1444      list_lat.push_back(CArray<double,1>(nbData));
1445
1446      if (hasBounds)
1447      {
1448        list_boundslon.push_back(CArray<double,2>(nvertex, nbData));
1449        list_boundslat.push_back(CArray<double,2>(nvertex, nbData));
1450      }
1451
1452      CArray<double,1>& lon = list_lon.back();
1453      CArray<double,1>& lat = list_lat.back();
1454      const std::vector<size_t>& temp = it->second;
1455      for (n = 0; n < nbData; ++n)
1456      {
1457        idx = static_cast<int>(it->second[n]);
1458        lon(n) = lonvalue_client(idx);
1459        lat(n) = latvalue_client(idx);
1460
1461        if (hasBounds)
1462        {
1463          CArray<double,2>& boundslon = list_boundslon.back();
1464          CArray<double,2>& boundslat = list_boundslat.back();
1465
1466          for (nv = 0; nv < nvertex; ++nv)
1467          {
1468            boundslon(nv, n) = bounds_lon_client(nv, idx);
1469            boundslat(nv, n) = bounds_lat_client(nv, idx);
1470          }
1471        }
1472      }
1473
1474      list_msgsLon.push_back(CMessage());
1475      list_msgsLat.push_back(CMessage());
1476
1477      list_msgsLon.back() << this->getId() << list_lon.back();
1478      list_msgsLat.back() << this->getId() << list_lat.back();
1479
1480      if (hasBounds)
1481      {
1482        list_msgsLon.back() << list_boundslon.back();
1483        list_msgsLat.back() << list_boundslat.back();
1484      }
1485
1486      eventLon.push(rank, nbConnectedClients_[rank], list_msgsLon.back());
1487      eventLat.push(rank, nbConnectedClients_[rank], list_msgsLat.back());
1488    }
1489
1490    client->sendEvent(eventLon);
1491    client->sendEvent(eventLat);
1492  }
1493
1494  /*!
1495    Send some optional information to server(s)
1496    In the future, this function can be extended with more optional information to send
1497  */
1498  void CDomain::sendLonLatArea(void)
1499  {
1500    sendIndex();
1501    sendLonLat();
1502    sendArea();
1503  }
1504
1505  bool CDomain::dispatchEvent(CEventServer& event)
1506  {
1507    if (SuperClass::dispatchEvent(event)) return true;
1508    else
1509    {
1510      switch(event.type)
1511      {
1512        case EVENT_ID_SERVER_ATTRIBUT:
1513          recvServerAttribut(event);
1514          return true;
1515          break;
1516        case EVENT_ID_INDEX:
1517          recvIndex(event);
1518          return true;
1519          break;
1520        case EVENT_ID_LON:
1521          recvLon(event);
1522          return true;
1523          break;
1524        case EVENT_ID_LAT:
1525          recvLat(event);
1526          return true;
1527          break;
1528        case EVENT_ID_AREA:
1529          recvArea(event);
1530          return true;
1531          break;
1532        default:
1533          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1534                << "Unknown Event");
1535          return false;
1536       }
1537    }
1538  }
1539
1540  /*!
1541    Receive attributes event from clients(s)
1542    \param[in] event event contain info about rank and associated attributes
1543  */
1544  void CDomain::recvServerAttribut(CEventServer& event)
1545  {
1546    CBufferIn* buffer=event.subEvents.begin()->buffer;
1547    string domainId ;
1548    *buffer>>domainId ;
1549    get(domainId)->recvServerAttribut(*buffer) ;
1550  }
1551
1552  /*!
1553    Receive attributes from client(s): zoom info and begin and n of each server
1554    \param[in] rank rank of client source
1555    \param[in] buffer message containing attributes info
1556  */
1557  void CDomain::recvServerAttribut(CBufferIn& buffer)
1558  {
1559    buffer >> ni_srv >> ibegin_srv >> iend_srv >> nj_srv >> jbegin_srv >> jend_srv
1560           >> global_zoom_ni >> global_zoom_ibegin >> global_zoom_nj >> global_zoom_jbegin
1561           >> isCompressible_;
1562
1563    int zoom_iend = global_zoom_ibegin + global_zoom_ni - 1;
1564    int zoom_jend = global_zoom_jbegin + global_zoom_nj - 1;
1565
1566    zoom_ibegin_srv = global_zoom_ibegin > ibegin_srv ? global_zoom_ibegin : ibegin_srv ;
1567    zoom_iend_srv = zoom_iend < iend_srv ? zoom_iend : iend_srv ;
1568    zoom_ni_srv=zoom_iend_srv-zoom_ibegin_srv+1 ;
1569
1570    zoom_jbegin_srv = global_zoom_jbegin > jbegin_srv ? global_zoom_jbegin : jbegin_srv ;
1571    zoom_jend_srv = zoom_jend < jend_srv ? zoom_jend : jend_srv ;
1572    zoom_nj_srv=zoom_jend_srv-zoom_jbegin_srv+1 ;
1573
1574    if (zoom_ni_srv<=0 || zoom_nj_srv<=0)
1575    {
1576      zoom_ibegin_srv=0 ; zoom_iend_srv=0 ; zoom_ni_srv=0 ;
1577      zoom_jbegin_srv=0 ; zoom_jend_srv=0 ; zoom_nj_srv=0 ;
1578    }
1579    lonvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
1580    lonvalue_srv = 0. ;
1581    latvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
1582    latvalue_srv = 0. ;
1583    if (hasBounds)
1584    {
1585      bounds_lon_srv.resize(nvertex,zoom_ni_srv*zoom_nj_srv) ;
1586      bounds_lon_srv = 0. ;
1587      bounds_lat_srv.resize(nvertex,zoom_ni_srv*zoom_nj_srv) ;
1588      bounds_lat_srv = 0. ;
1589    }
1590
1591    if (hasArea)
1592      area_srv.resize(zoom_ni_srv * zoom_nj_srv);
1593  }
1594
1595  /*!
1596    Receive index event from clients(s)
1597    \param[in] event event contain info about rank and associated index
1598  */
1599  void CDomain::recvIndex(CEventServer& event)
1600  {
1601    CDomain* domain;
1602
1603    list<CEventServer::SSubEvent>::iterator it;
1604    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1605    {
1606      CBufferIn* buffer = it->buffer;
1607      string domainId;
1608      *buffer >> domainId;
1609      domain = get(domainId);
1610      domain->recvIndex(it->rank, *buffer);
1611    }
1612
1613    if (domain->isCompressible_)
1614    {
1615      std::sort(domain->indexesToWrite.begin(), domain->indexesToWrite.end());
1616
1617      CContextServer* server = CContext::getCurrent()->server;
1618      domain->numberWrittenIndexes_ = domain->indexesToWrite.size();
1619      MPI_Allreduce(&domain->numberWrittenIndexes_, &domain->totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1620      MPI_Scan(&domain->numberWrittenIndexes_, &domain->offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1621      domain->offsetWrittenIndexes_ -= domain->numberWrittenIndexes_;
1622    }
1623  }
1624
1625  /*!
1626    Receive index information from client(s)
1627    \param[in] rank rank of client source
1628    \param[in] buffer message containing index info
1629  */
1630  void CDomain::recvIndex(int rank, CBufferIn& buffer)
1631  {
1632    int type_int;
1633    buffer >> type_int >> isCurvilinear >> indiSrv[rank] >> indjSrv[rank];
1634    type.setValue((type_attr::t_enum)type_int); // probleme des type enum avec les buffers : ToFix
1635
1636    if (isCompressible_)
1637    {
1638      CArray<int, 1> writtenIndexes;
1639      buffer >> writtenIndexes;
1640      indexesToWrite.reserve(indexesToWrite.size() + writtenIndexes.numElements());
1641      for (int i = 0; i < writtenIndexes.numElements(); ++i)
1642        indexesToWrite.push_back(writtenIndexes(i));
1643    }
1644  }
1645
1646  /*!
1647    Receive longitude event from clients(s)
1648    \param[in] event event contain info about rank and associated longitude
1649  */
1650  void CDomain::recvLon(CEventServer& event)
1651  {
1652    list<CEventServer::SSubEvent>::iterator it;
1653    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1654    {
1655      CBufferIn* buffer = it->buffer;
1656      string domainId;
1657      *buffer >> domainId;
1658      get(domainId)->recvLon(it->rank, *buffer);
1659    }
1660  }
1661
1662  /*!
1663    Receive longitude information from client(s)
1664    \param[in] rank rank of client source
1665    \param[in] buffer message containing longitude info
1666  */
1667  void CDomain::recvLon(int rank, CBufferIn& buffer)
1668  {
1669    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1670    CArray<double,1> lon;
1671    CArray<double,2> boundslon;
1672
1673    buffer >> lon;
1674    if (hasBounds) buffer >> boundslon;
1675
1676    int i, j, ind_srv;
1677    for (int ind = 0; ind < indi.numElements(); ind++)
1678    {
1679      i = indi(ind); j = indj(ind);
1680      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1681      lonvalue_srv(ind_srv) = lon(ind);
1682      if (hasBounds)
1683      {
1684        for (int nv = 0; nv < nvertex; ++nv)
1685          bounds_lon_srv(nv, ind_srv) = boundslon(nv, ind);
1686      }
1687    }
1688  }
1689
1690  /*!
1691    Receive latitude event from clients(s)
1692    \param[in] event event contain info about rank and associated latitude
1693  */
1694  void CDomain::recvLat(CEventServer& event)
1695  {
1696    list<CEventServer::SSubEvent>::iterator it;
1697    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1698    {
1699      CBufferIn* buffer = it->buffer;
1700      string domainId;
1701      *buffer >> domainId;
1702      get(domainId)->recvLat(it->rank, *buffer);
1703    }
1704  }
1705
1706  /*!
1707    Receive latitude information from client(s)
1708    \param[in] rank rank of client source
1709    \param[in] buffer message containing latitude info
1710  */
1711  void CDomain::recvLat(int rank, CBufferIn& buffer)
1712  {
1713    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1714    CArray<double,1> lat;
1715    CArray<double,2> boundslat;
1716
1717    buffer >> lat;
1718    if (hasBounds) buffer >> boundslat;
1719
1720    int i, j, ind_srv;
1721    for (int ind = 0; ind < indi.numElements(); ind++)
1722    {
1723      i = indi(ind); j = indj(ind);
1724      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1725      latvalue_srv(ind_srv) = lat(ind);
1726      if (hasBounds)
1727      {
1728        for (int nv = 0; nv < nvertex; nv++)
1729          bounds_lat_srv(nv, ind_srv) = boundslat(nv, ind);
1730      }
1731    }
1732  }
1733
1734  /*!
1735    Receive area event from clients(s)
1736    \param[in] event event contain info about rank and associated area
1737  */
1738  void CDomain::recvArea(CEventServer& event)
1739  {
1740    list<CEventServer::SSubEvent>::iterator it;
1741    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1742    {
1743      CBufferIn* buffer = it->buffer;
1744      string domainId;
1745      *buffer >> domainId;
1746      get(domainId)->recvArea(it->rank, *buffer);
1747    }
1748  }
1749
1750  /*!
1751    Receive area information from client(s)
1752    \param[in] rank rank of client source
1753    \param[in] buffer message containing area info
1754  */
1755  void CDomain::recvArea(int rank, CBufferIn& buffer)
1756  {
1757    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1758    CArray<double,1> clientArea;
1759
1760    buffer >> clientArea;
1761
1762    int i, j, ind_srv;
1763    for (int ind = 0; ind < indi.numElements(); ind++)
1764    {
1765      i = indi(ind); j = indj(ind);
1766      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1767      area_srv(ind_srv) = clientArea(ind);
1768    }
1769  }
1770
1771  /*!
1772    Check whether a domain has transformation
1773    \return true if domain has transformation
1774  */
1775  bool CDomain::hasTransformation()
1776  {
1777    return (!transformationMap_.empty());
1778  }
1779
1780  /*!
1781    Set transformation for current domain. It's the method to move transformation in hierarchy
1782    \param [in] domTrans transformation on domain
1783  */
1784  void CDomain::setTransformations(const TransMapTypes& domTrans)
1785  {
1786    transformationMap_ = domTrans;
1787  }
1788
1789  /*!
1790    Get all transformation current domain has
1791    \return all transformation
1792  */
1793  CDomain::TransMapTypes CDomain::getAllTransformations(void)
1794  {
1795    return transformationMap_;
1796  }
1797
1798  /*!
1799    Check the validity of all transformations applied on domain
1800  This functions is called AFTER all inherited attributes are solved
1801  */
1802  void CDomain::checkTransformations()
1803  {
1804    TransMapTypes::const_iterator itb = transformationMap_.begin(), it,
1805                                  ite = transformationMap_.end();
1806    for (it = itb; it != ite; ++it)
1807    {
1808      (it->second)->checkValid(this);
1809    }
1810  }
1811
1812  /*!
1813   * Go through the hierarchy to find the domain from which the transformations must be inherited
1814   */
1815  void CDomain::solveInheritanceTransformation()
1816  {
1817    if (hasTransformation() || !hasDirectDomainReference())
1818      return;
1819
1820    CDomain* domain = this;
1821    std::vector<CDomain*> refDomains;
1822    while (!domain->hasTransformation() && domain->hasDirectDomainReference())
1823    {
1824      refDomains.push_back(domain);
1825      domain = domain->getDirectDomainReference();
1826    }
1827
1828    if (domain->hasTransformation())
1829      for (size_t i = 0; i < refDomains.size(); ++i)
1830        refDomains[i]->setTransformations(domain->getAllTransformations());
1831
1832    // Try to inherit the id of the referenced object as the domain name
1833    // when no name was been defined and a defaut id is used.
1834    if (name.isEmpty())
1835    {
1836      static const std::string defId("__domain_undef_id_");
1837      const std::string& id = getId();
1838      if (id.size() > defId.size() && id.compare(0, defId.size(), defId) == 0)
1839        name = domain->getId();
1840    }
1841  }
1842
1843  void CDomain::solveSrcInheritance()
1844  {
1845    if (!domain_src.isEmpty())
1846    {
1847       if (!CDomain::has(this->domain_src.getValue()))                                   \
1848          ERROR("CDomain::solveSrcInheritance()",                                \
1849             << "[ src_name = " << this->domain_src.getValue() << "]"                 \
1850             << " invalid domain name !");
1851
1852       srcObject_ = CDomain::get(this->domain_src.getValue());
1853    }
1854  }
1855
1856  CDomain* CDomain::getDomainSrc()
1857  {
1858    return srcObject_;
1859  }
1860
1861  /*!
1862    Parse children nodes of a domain in xml file.
1863    Whenver there is a new transformation, its type and name should be added into this function
1864    \param node child node to process
1865  */
1866  void CDomain::parse(xml::CXMLNode & node)
1867  {
1868    SuperClass::parse(node);
1869
1870    if (node.goToChildElement())
1871    {
1872      StdString zoomDomainDefRoot("zoom_domain_definition");
1873      StdString zoom("zoom_domain");
1874      StdString interpDomainDefRoot("interpolate_domain_definition");
1875      StdString interpFromFile("interpolate_domain");
1876      StdString generateRectilinearDefRoot("generate_rectilinear_domain_definition");
1877      StdString generateRectilinear("generate_rectilinear_domain");
1878      do
1879      {
1880        if (node.getElementName() == zoom) {
1881          CZoomDomain* tmp = (CZoomDomainGroup::get(zoomDomainDefRoot))->createChild();
1882          tmp->parse(node);
1883          transformationMap_.push_back(std::make_pair(TRANS_ZOOM_DOMAIN,tmp));
1884        }
1885        else if (node.getElementName() == interpFromFile)
1886        {
1887          CInterpolateDomain* tmp = (CInterpolateDomainGroup::get(interpDomainDefRoot))->createChild();
1888          tmp->parse(node);
1889          transformationMap_.push_back(std::make_pair(TRANS_INTERPOLATE_DOMAIN,tmp));
1890        }
1891        else if (node.getElementName() == generateRectilinear)
1892        {
1893          CGenerateRectilinearDomain* tmp = (CGenerateRectilinearDomainGroup::get(generateRectilinearDefRoot))->createChild();
1894          tmp->parse(node);
1895          transformationMap_.push_back(std::make_pair(TRANS_GENERATE_RECTILINEAR_DOMAIN,tmp));
1896        }
1897      } while (node.goToNextElement()) ;
1898      node.goToParentElement();
1899    }
1900  }
1901   //----------------------------------------------------------------
1902
1903   DEFINE_REF_FUNC(Domain,domain)
1904
1905   ///---------------------------------------------------------------
1906
1907} // namespace xios
Note: See TracBrowser for help on using the repository browser.