source: XIOS/dev/dev_olga/src/node/domain.cpp @ 1099

Last change on this file since 1099 was 1099, checked in by mhnguyen, 5 years ago

Updating 2-level server

+) Make some changes in the way data rebuilt on each level of server
+) Make some changes in the order of functions call during close context to make sure that each server receives the global indexes before calculating index to send to next level
+) Modify some functions to make sure data sent to the correct server pool

Test
+) On Curie
+) Only test_client

  • 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: 103.4 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), isCompressible_(false), isUnstructed_(false)
34      , isClientAfterTransformationChecked(false), hasLonLat(false)
35      , isRedistributed_(false), hasPole(false), doZoomByIndex_(false)
36      , lonvalue(), latvalue(), bounds_lonvalue(), bounds_latvalue()
37      , globalLocalIndexMap_()
38   {
39   }
40
41   CDomain::CDomain(const StdString & id)
42      : CObjectTemplate<CDomain>(id), CDomainAttributes()
43      , isChecked(false), relFiles(), isClientChecked(false), nbConnectedClients_(), indSrv_(), connectedServerRank_()
44      , hasBounds(false), hasArea(false), isDistributed_(false), isCompressible_(false), isUnstructed_(false)
45      , isClientAfterTransformationChecked(false), hasLonLat(false)
46      , isRedistributed_(false), hasPole(false), doZoomByIndex_(false)
47      , lonvalue(), latvalue(), bounds_lonvalue(), bounds_latvalue()
48      , globalLocalIndexMap_()
49   {
50         }
51
52   CDomain::~CDomain(void)
53   {
54   }
55
56   ///---------------------------------------------------------------
57
58   void CDomain::assignMesh(const StdString meshName, const int nvertex)
59   {
60     mesh = CMesh::getMesh(meshName, nvertex);
61   }
62
63   CDomain* CDomain::createDomain()
64   {
65     CDomain* domain = CDomainGroup::get("domain_definition")->createChild();
66     return domain;
67   }
68
69   std::map<StdString, ETranformationType> CDomain::transformationMapList_ = std::map<StdString, ETranformationType>();
70   bool CDomain::_dummyTransformationMapList = CDomain::initializeTransformationMap(CDomain::transformationMapList_);
71
72   bool CDomain::initializeTransformationMap(std::map<StdString, ETranformationType>& m)
73   {
74     m["zoom_domain"] = TRANS_ZOOM_DOMAIN;
75     m["interpolate_domain"] = TRANS_INTERPOLATE_DOMAIN;
76     m["generate_rectilinear_domain"] = TRANS_GENERATE_RECTILINEAR_DOMAIN;
77     m["compute_connectivity_domain"] = TRANS_COMPUTE_CONNECTIVITY_DOMAIN;
78     m["expand_domain"] = TRANS_EXPAND_DOMAIN;
79   }
80
81   const std::set<StdString> & CDomain::getRelFiles(void) const
82   {
83      return (this->relFiles);
84   }
85
86
87   const std::vector<int>& CDomain::getIndexesToWrite(void) const
88   {
89     return indexesToWrite;
90   }
91
92   /*!
93     Returns the number of indexes written by each server.
94     \return the number of indexes written by each server
95   */
96   int CDomain::getNumberWrittenIndexes() const
97   {
98     return numberWrittenIndexes_;
99   }
100
101   /*!
102     Returns the total number of indexes written by the servers.
103     \return the total number of indexes written by the servers
104   */
105   int CDomain::getTotalNumberWrittenIndexes() const
106   {
107     return totalNumberWrittenIndexes_;
108   }
109
110   /*!
111     Returns the offset of indexes written by each server.
112     \return the offset of indexes written by each server
113   */
114   int CDomain::getOffsetWrittenIndexes() const
115   {
116     return offsetWrittenIndexes_;
117   }
118
119   /*!
120     Returns the start of indexes written by each server.
121     \return the start of indexes written by each server
122   */
123   const std::vector<int>& CDomain::getStartWriteIndex() const
124   {
125     return start_write_index_;
126   }
127
128   /*!
129     Returns the count of indexes written by each server.
130     \return the count of indexes written by each server
131   */
132   const std::vector<int>& CDomain::getCountWriteIndex() const
133   {
134     return count_write_index_;
135   }
136
137   /*!
138     Returns the local data written by each server.     
139   */
140   const std::vector<int>& CDomain::getLocalWriteSize() const
141   {
142     return local_write_size_;
143   }
144
145   /*!
146     Returns the global data written by all server.     
147   */
148   const std::vector<int>& CDomain::getGlobalWriteSize() const
149   {
150     return global_write_size_;
151   }
152
153   //----------------------------------------------------------------
154
155   /*!
156    * Compute the minimum buffer size required to send the attributes to the server(s).
157    *
158    * \return A map associating the server rank with its minimum buffer size.
159    */
160   std::map<int, StdSize> CDomain::getAttributesBufferSize()
161   {
162     CContext* context = CContext::getCurrent();
163     // For now the assumption is that secondary server pools consist of the same number of procs.
164     // CHANGE the line below if the assumption changes.
165     CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[0] : context->client;
166
167     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes();
168
169     if (client->isServerLeader())
170     {
171       // size estimation for sendDistributionAttribut
172       size_t size = 11 * sizeof(size_t);
173
174       const std::list<int>& ranks = client->getRanksServerLeader();
175       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
176       {
177         if (size > attributesSizes[*itRank])
178           attributesSizes[*itRank] = size;
179       }
180     }
181
182     boost::unordered_map<int, vector<size_t> >::const_iterator itIndexEnd = indSrv_.end();
183     std::map<int, std::vector<int> >::const_iterator itWrittenIndexEnd = indWrittenSrv_.end();
184     for (size_t k = 0; k < connectedServerRank_.size(); ++k)
185     {
186       int rank = connectedServerRank_[k];
187       boost::unordered_map<int, std::vector<size_t> >::const_iterator it = indSrv_.find(rank);
188       size_t idxCount = (it != itIndexEnd) ? it->second.size() : 0;
189
190       // size estimation for sendIndex (and sendArea which is always smaller or equal)
191       size_t sizeIndexEvent = 2 * sizeof(size_t) + 2 * CArray<int,1>::size(idxCount);
192       if (isCompressible_)
193       {
194         std::map<int, std::vector<int> >::const_iterator itWritten = indWrittenSrv_.find(rank);
195         size_t writtenIdxCount = (itWritten != itWrittenIndexEnd) ? itWritten->second.size() : 0;
196         sizeIndexEvent += CArray<int,1>::size(writtenIdxCount);
197       }
198
199       // size estimation for sendLonLat
200       size_t sizeLonLatEvent = CArray<double,1>::size(idxCount);
201       if (hasBounds)
202         sizeLonLatEvent += CArray<double,2>::size(nvertex * idxCount);
203
204       size_t size = CEventClient::headerSize + getId().size() + sizeof(size_t) + std::max(sizeIndexEvent, sizeLonLatEvent);
205       if (size > attributesSizes[rank])
206         attributesSizes[rank] = size;
207     }
208
209     return attributesSizes;
210   }
211
212   //----------------------------------------------------------------
213
214   bool CDomain::isEmpty(void) const
215   {
216      return ((this->zoom_i_index.isEmpty()) || (0 == this->zoom_i_index.numElements()));
217      // return ((this->zoom_ni_srv == 0) ||
218      //         (this->zoom_nj_srv == 0));
219   }
220
221   //----------------------------------------------------------------
222
223   bool CDomain::IsWritten(const StdString & filename) const
224   {
225      return (this->relFiles.find(filename) != this->relFiles.end());
226   }
227
228   bool CDomain::isWrittenCompressed(const StdString& filename) const
229   {
230      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
231   }
232
233   //----------------------------------------------------------------
234
235   bool CDomain::isDistributed(void) const
236   {
237      return isDistributed_;
238   }
239
240   //----------------------------------------------------------------
241
242   /*!
243    * Test whether the data defined on the domain can be outputted in a compressed way.
244    *
245    * \return true if and only if a mask was defined for this domain
246    */
247   bool CDomain::isCompressible(void) const
248   {
249      return isCompressible_;
250   }
251
252   void CDomain::addRelFile(const StdString & filename)
253   {
254      this->relFiles.insert(filename);
255   }
256
257   void CDomain::addRelFileCompressed(const StdString& filename)
258   {
259      this->relFilesCompressed.insert(filename);
260   }
261
262   StdString CDomain::GetName(void)   { return (StdString("domain")); }
263   StdString CDomain::GetDefName(void){ return (CDomain::GetName()); }
264   ENodeType CDomain::GetType(void)   { return (eDomain); }
265
266   //----------------------------------------------------------------
267
268   /*!
269     Redistribute RECTILINEAR domain with a number of local domains.
270   All attributes ni,nj,ibegin,jbegin (if defined) will be rewritten
271   The optional attributes lonvalue, latvalue will be added. Because this function only serves (for now)
272   for interpolation from unstructured domain to rectilinear one, range of latvalue is 0-360 and lonvalue is -90 - +90
273    \param [in] nbLocalDomain number of local domain on the domain destination
274   */
275   void CDomain::redistribute(int nbLocalDomain)
276   {
277     if (this->isRedistributed_) return;
278
279     this->isRedistributed_ = true;
280     CContext* context = CContext::getCurrent();
281     // For now the assumption is that secondary server pools consist of the same number of procs.
282     // CHANGE the line below if the assumption changes.
283     CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[0] : context->client;
284     int rankClient = client->clientRank;
285     int rankOnDomain = rankClient%nbLocalDomain;
286
287     if (ni_glo.isEmpty() || ni_glo <= 0 )
288     {
289        ERROR("CDomain::redistribute(int nbLocalDomain)",
290           << "[ Id = " << this->getId() << " ] "
291           << "The global domain is badly defined,"
292           << " check the \'ni_glo\'  value !")
293     }
294
295     if (nj_glo.isEmpty() || nj_glo <= 0 )
296     {
297        ERROR("CDomain::redistribute(int nbLocalDomain)",
298           << "[ Id = " << this->getId() << " ] "
299           << "The global domain is badly defined,"
300           << " check the \'nj_glo\'  value !")
301     }
302
303     if ((type_attr::rectilinear == type)  || (type_attr::curvilinear == type))
304     {
305        int globalDomainSize = ni_glo * nj_glo;
306        if (globalDomainSize <= nbLocalDomain)
307        {
308          for (int idx = 0; idx < nbLocalDomain; ++idx)
309          {
310            if (rankOnDomain < globalDomainSize)
311            {
312              int iIdx = rankOnDomain % ni_glo;
313              int jIdx = rankOnDomain / ni_glo;
314              ibegin.setValue(iIdx); jbegin.setValue(jIdx);
315              ni.setValue(1); nj.setValue(1);
316            }
317            else
318            {
319              ibegin.setValue(0); jbegin.setValue(0);
320              ni.setValue(0); nj.setValue(0);
321            }
322          }
323        }
324        else
325        {
326          float njGlo = nj_glo.getValue();
327          float niGlo = ni_glo.getValue();
328          int nbProcOnX, nbProcOnY, range;
329
330          // Compute (approximately) number of segment on x and y axis
331          float yOverXRatio = njGlo/niGlo;
332
333          nbProcOnX = std::ceil(std::sqrt(nbLocalDomain/yOverXRatio));
334          nbProcOnY = std::ceil(((float)nbLocalDomain)/nbProcOnX);
335
336          // Simple distribution: Sweep from top to bottom, left to right
337          // Calculate local begin on x
338          std::vector<int> ibeginVec(nbProcOnX,0), jbeginVec(nbProcOnY,0);
339          std::vector<int> niVec(nbProcOnX), njVec(nbProcOnY);
340          for (int i = 1; i < nbProcOnX; ++i)
341          {
342            range = ni_glo / nbProcOnX;
343            if (i < (ni_glo%nbProcOnX)) ++range;
344            niVec[i-1] = range;
345            ibeginVec[i] = ibeginVec[i-1] + niVec[i-1];
346          }
347          niVec[nbProcOnX-1] = ni_glo - ibeginVec[nbProcOnX-1];
348
349          // Calculate local begin on y
350          for (int j = 1; j < nbProcOnY; ++j)
351          {
352            range = nj_glo / nbProcOnY;
353            if (j < (nj_glo%nbProcOnY)) ++range;
354            njVec[j-1] = range;
355            jbeginVec[j] = jbeginVec[j-1] + njVec[j-1];
356          }
357          njVec[nbProcOnY-1] = nj_glo - jbeginVec[nbProcOnY-1];
358
359          // Now assign value to ni, ibegin, nj, jbegin
360          int iIdx = rankOnDomain % nbProcOnX;
361          int jIdx = rankOnDomain / nbProcOnX;
362
363          if (rankOnDomain != (nbLocalDomain-1))
364          {
365            ibegin.setValue(ibeginVec[iIdx]);
366            jbegin.setValue(jbeginVec[jIdx]);
367            nj.setValue(njVec[jIdx]);
368            ni.setValue(niVec[iIdx]);
369          }
370          else // just merge all the remaining rectangle into the last one
371          {
372            ibegin.setValue(ibeginVec[iIdx]);
373            jbegin.setValue(jbeginVec[jIdx]);
374            nj.setValue(njVec[jIdx]);
375            ni.setValue(ni_glo - ibeginVec[iIdx]);
376          }
377        }
378
379        // Now fill other attributes
380        if (type_attr::rectilinear == type) fillInRectilinearLonLat();
381     }
382     else  // unstructured domain
383     {
384       if (this->i_index.isEmpty())
385       {
386          int globalDomainSize = ni_glo * nj_glo;
387          if (globalDomainSize <= nbLocalDomain)
388          {
389            for (int idx = 0; idx < nbLocalDomain; ++idx)
390            {
391              if (rankOnDomain < globalDomainSize)
392              {
393                int iIdx = rankOnDomain % ni_glo;
394                int jIdx = rankOnDomain / ni_glo;
395                ibegin.setValue(iIdx); jbegin.setValue(jIdx);
396                ni.setValue(1); nj.setValue(1);
397              }
398              else
399              {
400                ibegin.setValue(0); jbegin.setValue(0);
401                ni.setValue(0); nj.setValue(0);
402              }
403            }
404          }
405          else
406          {
407            float njGlo = nj_glo.getValue();
408            float niGlo = ni_glo.getValue();
409            std::vector<int> ibeginVec(nbLocalDomain,0);
410            std::vector<int> niVec(nbLocalDomain);
411            for (int i = 1; i < nbLocalDomain; ++i)
412            {
413              int range = ni_glo / nbLocalDomain;
414              if (i < (ni_glo%nbLocalDomain)) ++range;
415              niVec[i-1] = range;
416              ibeginVec[i] = ibeginVec[i-1] + niVec[i-1];
417            }
418            niVec[nbLocalDomain-1] = ni_glo - ibeginVec[nbLocalDomain-1];
419
420            int iIdx = rankOnDomain % nbLocalDomain;
421            ibegin.setValue(ibeginVec[iIdx]);
422            jbegin.setValue(0);
423            ni.setValue(niVec[iIdx]);
424            nj.setValue(1);
425          }
426        }
427        else
428        {
429          ibegin.setValue(this->i_index(0));
430          jbegin.setValue(0);
431          ni.setValue(this->i_index.numElements());
432          nj.setValue(1);
433        }
434     }
435
436     checkDomain();
437   }
438
439   /*!
440     Fill in the values for lonvalue_1d and latvalue_1d of rectilinear domain
441     Range of longitude value from 0 - 360
442     Range of latitude value from -90 - +90
443   */
444   void CDomain::fillInRectilinearLonLat()
445   {
446     if (!lonvalue_rectilinear_read_from_file.isEmpty())
447     {
448       lonvalue_1d.resize(ni);
449       for (int idx = 0; idx < ni; ++idx)
450         lonvalue_1d(idx) = lonvalue_rectilinear_read_from_file(idx+ibegin);
451       lon_start.setValue(lonvalue_rectilinear_read_from_file(0));
452       lon_end.setValue(lonvalue_rectilinear_read_from_file(ni_glo-1));
453     }
454     else
455     {
456       if (!lonvalue_2d.isEmpty()) lonvalue_2d.free();
457       lonvalue_1d.resize(ni);
458       double lonRange = lon_end - lon_start;
459       double lonStep = (1 == ni_glo.getValue()) ? lonRange : lonRange/double(ni_glo.getValue()-1);
460
461        // Assign lon value
462       for (int i = 0; i < ni; ++i)
463       {
464         if (0 == (ibegin + i))
465         {
466           lonvalue_1d(i) = lon_start;
467         }
468         else if (ni_glo == (ibegin + i + 1))
469         {
470           lonvalue_1d(i) = lon_end;
471         }
472         else
473         {
474           lonvalue_1d(i) = (ibegin + i) * lonStep  + lon_start;
475         }
476       }
477     }
478
479
480     if (!latvalue_rectilinear_read_from_file.isEmpty())
481     {
482       latvalue_1d.resize(nj);
483       for (int idx = 0; idx < nj; ++idx)
484         latvalue_1d(idx) = latvalue_rectilinear_read_from_file(idx+jbegin);
485       lat_start.setValue(latvalue_rectilinear_read_from_file(0));
486       lat_end.setValue(latvalue_rectilinear_read_from_file(nj_glo-1));
487     }
488     else
489     {
490       if (!latvalue_2d.isEmpty()) latvalue_1d.free();
491       latvalue_1d.resize(nj);
492
493       double latRange = lat_end - lat_start;
494       double latStep = (1 == nj_glo.getValue()) ? latRange : latRange/double(nj_glo.getValue()-1);
495
496       for (int j = 0; j < nj; ++j)
497       {
498         if (0 == (jbegin + j))
499         {
500            latvalue_1d(j) = lat_start;
501         }
502         else if (nj_glo == (jbegin + j + 1))
503         {
504            latvalue_1d(j) = lat_end;
505         }
506         else
507         {
508           latvalue_1d(j) =  (jbegin + j) * latStep + lat_start;
509         }
510       }
511     }
512   }
513
514
515
516   void CDomain::AllgatherRectilinearLonLat(CArray<double,1>& lon, CArray<double,1>& lat, CArray<double,1>& lon_g, CArray<double,1>& lat_g)
517   {
518          CContext* context = CContext::getCurrent();
519    // For now the assumption is that secondary server pools consist of the same number of procs.
520    // CHANGE the line below if the assumption changes.
521    CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[0] : context->client;
522          lon_g.resize(ni_glo) ;
523          lat_g.resize(nj_glo) ;
524
525
526          int* ibegin_g = new int[client->clientSize] ;
527          int* jbegin_g = new int[client->clientSize] ;
528          int* ni_g = new int[client->clientSize] ;
529          int* nj_g = new int[client->clientSize] ;
530          int v ;
531          v=ibegin ;
532          MPI_Allgather(&v,1,MPI_INT,ibegin_g,1,MPI_INT,client->intraComm) ;
533          v=jbegin ;
534          MPI_Allgather(&v,1,MPI_INT,jbegin_g,1,MPI_INT,client->intraComm) ;
535          v=ni ;
536          MPI_Allgather(&v,1,MPI_INT,ni_g,1,MPI_INT,client->intraComm) ;
537          v=nj ;
538          MPI_Allgather(&v,1,MPI_INT,nj_g,1,MPI_INT,client->intraComm) ;
539
540          MPI_Allgatherv(lon.dataFirst(),ni,MPI_DOUBLE,lon_g.dataFirst(),ni_g, ibegin_g,MPI_DOUBLE,client->intraComm) ;
541          MPI_Allgatherv(lat.dataFirst(),nj,MPI_DOUBLE,lat_g.dataFirst(),nj_g, jbegin_g,MPI_DOUBLE,client->intraComm) ;
542
543      delete[] ibegin_g ;
544      delete[] jbegin_g ;
545      delete[] ni_g ;
546      delete[] nj_g ;
547   }
548
549   void CDomain::fillInRectilinearBoundLonLat(CArray<double,1>& lon, CArray<double,1>& lat,
550                                              CArray<double,2>& boundsLon, CArray<double,2>& boundsLat)
551   {
552     int i,j,k;
553
554     const int nvertexValue = 4;
555     boundsLon.resize(nvertexValue,ni*nj);
556
557     if (ni_glo>1)
558     {
559       double lonStepStart = lon(1)-lon(0);
560       bounds_lon_start=lon(0) - lonStepStart/2;
561       double lonStepEnd = lon(ni_glo-1)-lon(ni_glo-2);
562       bounds_lon_end=lon(ni_glo-1) + lonStepEnd/2;
563       double errorBoundsLon = std::abs(360-std::abs(bounds_lon_end-bounds_lon_start));
564
565       // if errorBoundsLon is reasonably small (0.1 x cell size) consider it as closed in longitude
566       if (errorBoundsLon < std::abs(lonStepStart)*1e-1 || errorBoundsLon < std::abs(lonStepEnd)*1e-1 )
567       {
568         bounds_lon_start= (lon(0) + lon(ni_glo-1)-360)/2 ;
569         bounds_lon_end= (lon(0) +360 + lon(ni_glo-1))/2 ;
570       }
571     }
572     else
573     {
574       if (bounds_lon_start.isEmpty()) bounds_lon_start=-180. ;
575       if (bounds_lon_end.isEmpty()) bounds_lon_end=180.-1e-8 ;
576     }
577
578     for(j=0;j<nj;++j)
579       for(i=0;i<ni;++i)
580       {
581         k=j*ni+i;
582         boundsLon(0,k) = boundsLon(1,k) = (0 == (ibegin + i)) ? bounds_lon_start
583                                                               : (lon(ibegin + i)+lon(ibegin + i-1))/2;
584         boundsLon(2,k) = boundsLon(3,k) = ((ibegin + i + 1) == ni_glo) ? bounds_lon_end
585                                                                        : (lon(ibegin + i + 1)+lon(ibegin + i))/2;
586       }
587
588
589    boundsLat.resize(nvertexValue,nj*ni);
590    bool isNorthPole=false ;
591    bool isSouthPole=false ;
592    if (std::abs(90 - std::abs(lat(0))) < NumTraits<double>::epsilon()) isNorthPole = true;
593    if (std::abs(90 - std::abs(lat(nj_glo-1))) < NumTraits<double>::epsilon()) isSouthPole = true;
594
595    // lat boundaries beyond pole the assimilate it to pole
596    // lat boundarie is relativelly close to pole (0.1 x cell size) assimilate it to pole
597    if (nj_glo>1)
598    {
599      double latStepStart = lat(1)-lat(0);
600      if (isNorthPole) bounds_lat_start=lat(0);
601      else
602      {
603        bounds_lat_start=lat(0)-latStepStart/2;
604        if (bounds_lat_start >= 90 ) bounds_lat_start=90 ;
605        else if (bounds_lat_start <= -90 ) bounds_lat_start=-90 ;
606        else if (bounds_lat_start <= 90 && bounds_lat_start >= lat(0))
607        {
608          if ( std::abs(90-bounds_lat_start) <= 0.1*std::abs(latStepStart)) bounds_lat_start=90 ;
609        }
610        else if (bounds_lat_start >= -90 && bounds_lat_start <= lat(0))
611        {
612          if ( std::abs(-90 - bounds_lat_start) <= 0.1*std::abs(latStepStart)) bounds_lat_start=-90 ;
613        }
614      }
615
616      double latStepEnd = lat(nj_glo-1)-lat(nj_glo-2);
617      if (isSouthPole) bounds_lat_end=lat(nj_glo-1);
618      else
619      {
620        bounds_lat_end=lat(nj_glo-1)+latStepEnd/2;
621
622        if (bounds_lat_end >= 90 ) bounds_lat_end=90 ;
623        else if (bounds_lat_end <= -90 ) bounds_lat_end=-90 ;
624        else if (bounds_lat_end <= 90 && bounds_lat_end >= lat(nj_glo-1))
625        {
626          if ( std::abs(90-bounds_lat_end) <= 0.1*std::abs(latStepEnd)) bounds_lat_end=90 ;
627        }
628        else if (bounds_lat_end >= -90 && bounds_lat_end <= lat(nj_glo-1))
629        {
630          if ( std::abs(-90 - bounds_lat_end) <= 0.1*std::abs(latStepEnd)) bounds_lat_end=-90 ;
631        }
632      }
633    }
634    else
635    {
636      if (bounds_lat_start.isEmpty()) bounds_lon_start=-90. ;
637      if (bounds_lat_end.isEmpty()) bounds_lat_end=90 ;
638    }
639
640    for(j=0;j<nj;++j)
641      for(i=0;i<ni;++i)
642      {
643        k=j*ni+i;
644        boundsLat(1,k) = boundsLat(2,k) = (0 == (jbegin + j)) ? bounds_lat_start
645                                                              : (lat(jbegin + j)+lat(jbegin + j-1))/2;
646        boundsLat(0,k) = boundsLat(3,k) = ((jbegin + j +1) == nj_glo) ? bounds_lat_end
647                                                                      : (lat(jbegin + j + 1)+lat(jbegin + j))/2;
648      }
649   }
650
651   void CDomain::checkDomain(void)
652   {
653     if (type.isEmpty())
654     {
655       ERROR("CDomain::checkDomain(void)",
656             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
657             << "The domain type is mandatory, "
658             << "please define the 'type' attribute.")
659     }
660
661     if (type == type_attr::gaussian) 
662     {
663           hasPole=true ;
664             type.setValue(type_attr::unstructured) ;
665           }
666           else if (type == type_attr::rectilinear) hasPole=true ;
667         
668     if (type == type_attr::unstructured)
669     {
670        if (ni_glo.isEmpty())
671        {
672          ERROR("CDomain::checkDomain(void)",
673                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
674                << "The global domain is badly defined, "
675                << "the mandatory 'ni_glo' attribute is missing.")
676        }
677        else if (ni_glo <= 0)
678        {
679          ERROR("CDomain::checkDomain(void)",
680                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
681                << "The global domain is badly defined, "
682                << "'ni_glo' attribute should be strictly positive so 'ni_glo = " << ni_glo.getValue() << "' is invalid.")
683        }
684        isUnstructed_ = true;
685        nj_glo = 1;
686        nj = 1;
687        jbegin = 0;
688        if (!i_index.isEmpty()) ni = i_index.numElements();
689        j_index.resize(ni);
690        for(int i=0;i<ni;++i) j_index(i)=0;
691
692        if (!area.isEmpty())
693          area.transposeSelf(1, 0);
694     }
695
696     if (ni_glo.isEmpty())
697     {
698       ERROR("CDomain::checkDomain(void)",
699             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
700             << "The global domain is badly defined, "
701             << "the mandatory 'ni_glo' attribute is missing.")
702     }
703     else if (ni_glo <= 0)
704     {
705       ERROR("CDomain::checkDomain(void)",
706             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
707             << "The global domain is badly defined, "
708             << "'ni_glo' attribute should be strictly positive so 'ni_glo = " << ni_glo.getValue() << "' is invalid.")
709     }
710
711     if (nj_glo.isEmpty())
712     {
713       ERROR("CDomain::checkDomain(void)",
714             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
715             << "The global domain is badly defined, "
716             << "the mandatory 'nj_glo' attribute is missing.")
717     }
718     else if (nj_glo <= 0)
719     {
720       ERROR("CDomain::checkDomain(void)",
721             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
722             << "The global domain is badly defined, "
723             << "'nj_glo' attribute should be strictly positive so 'nj_glo = " << nj_glo.getValue() << "' is invalid.")
724     }
725
726     checkLocalIDomain();
727     checkLocalJDomain();
728
729     if (i_index.isEmpty())
730     {
731       i_index.resize(ni*nj);
732       for (int j = 0; j < nj; ++j)
733         for (int i = 0; i < ni; ++i) i_index(i+j*ni) = i+ibegin;
734     }
735
736     if (j_index.isEmpty())
737     {
738       j_index.resize(ni*nj);
739       for (int j = 0; j < nj; ++j)
740         for (int i = 0; i < ni; ++i) j_index(i+j*ni) = j+jbegin;
741     }     
742     checkZoom();
743
744     isDistributed_ = !((!ni.isEmpty() && (ni == ni_glo) && !nj.isEmpty() && (nj == nj_glo)) ||
745                        (!i_index.isEmpty() && i_index.numElements() == ni_glo*nj_glo));
746   }
747
748   // Check global zoom of a domain
749   // If there is no zoom defined for the domain, zoom will have value of global doamin
750   void CDomain::checkZoom(void)
751   {
752     if (global_zoom_ibegin.isEmpty())
753      global_zoom_ibegin.setValue(0);
754     if (global_zoom_ni.isEmpty())
755      global_zoom_ni.setValue(ni_glo);
756     if (global_zoom_jbegin.isEmpty())
757      global_zoom_jbegin.setValue(0);
758     if (global_zoom_nj.isEmpty())
759      global_zoom_nj.setValue(nj_glo);
760    if (zoom_i_index.isEmpty()) zoom_i_index.setValue(i_index.getValue());
761    if (zoom_j_index.isEmpty()) zoom_j_index.setValue(j_index.getValue());
762    if (zoom_ibegin.isEmpty()) zoom_ibegin.setValue(ibegin);
763    if (zoom_ni.isEmpty()) zoom_ni.setValue(ni);
764    if (zoom_jbegin.isEmpty()) zoom_jbegin.setValue(jbegin);
765    if (zoom_nj.isEmpty()) zoom_nj.setValue(nj);
766   }
767
768   //----------------------------------------------------------------
769
770   // Check validity of local domain on using the combination of 3 parameters: ibegin, ni and i_index
771   void CDomain::checkLocalIDomain(void)
772   {
773      // If ibegin and ni are provided then we use them to check the validity of local domain
774      if (i_index.isEmpty() && !ibegin.isEmpty() && !ni.isEmpty())
775      {
776        if ((ni.getValue() < 0 || ibegin.getValue() < 0) || ((ibegin.getValue() + ni.getValue()) > ni_glo.getValue()))
777        {
778          ERROR("CDomain::checkLocalIDomain(void)",
779                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
780                << "The local domain is wrongly defined,"
781                << " check the attributes 'ni_glo' (" << ni_glo.getValue() << "), 'ni' (" << ni.getValue() << ") and 'ibegin' (" << ibegin.getValue() << ")");
782        }
783      }
784
785      // i_index has higher priority than ibegin and ni
786      if (!i_index.isEmpty())
787      {
788        int minIIndex = (0 < i_index.numElements()) ? i_index(0) : 0;
789        if (ni.isEmpty()) 
790        {         
791         // No information about ni
792          int minIndex = ni_glo - 1;
793          int maxIndex = 0;
794          for (int idx = 0; idx < i_index.numElements(); ++idx)
795          {
796            if (i_index(idx) < minIndex) minIndex = i_index(idx);
797            if (i_index(idx) > maxIndex) maxIndex = i_index(idx);
798          }
799          ni = maxIndex - minIndex + 1; 
800          minIIndex = minIIndex;         
801        }
802
803        // It's not so correct but if ibegin is not the first value of i_index
804        // then data on local domain has user-defined distribution. In this case, ibegin, ni have no meaning.
805        if (ibegin.isEmpty()) ibegin = minIIndex;
806      }
807      else if (ibegin.isEmpty() && ni.isEmpty())
808      {
809        ibegin = 0;
810        ni = ni_glo;
811      }
812      else if ((!ibegin.isEmpty() && ni.isEmpty()) || (ibegin.isEmpty() && !ni.isEmpty()))
813      {
814        ERROR("CDomain::checkLocalIDomain(void)",
815              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
816              << "The local domain is wrongly defined," << endl
817              << "i_index is empty and either 'ni' or 'ibegin' is not defined. " 
818              << "If 'ni' and 'ibegin' are used to define a domain, both of them must not be empty.");
819      }
820       
821
822      if ((ni.getValue() < 0 || ibegin.getValue() < 0))
823      {
824        ERROR("CDomain::checkLocalIDomain(void)",
825              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
826              << "The local domain is wrongly defined,"
827              << " check the attributes 'ni_glo' (" << ni_glo.getValue() << "), 'ni' (" << ni.getValue() << ") and 'ibegin' (" << ibegin.getValue() << ")");
828      }
829   }
830
831   // Check validity of local domain on using the combination of 3 parameters: jbegin, nj and j_index
832   void CDomain::checkLocalJDomain(void)
833   {
834    // If jbegin and nj are provided then we use them to check the validity of local domain
835     if (j_index.isEmpty() && !jbegin.isEmpty() && !nj.isEmpty())
836     {
837       if ((nj.getValue() < 0 || jbegin.getValue() < 0) || (jbegin.getValue() + nj.getValue()) > nj_glo.getValue())
838       {
839         ERROR("CDomain::checkLocalJDomain(void)",
840                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
841                << "The local domain is wrongly defined,"
842                << " check the attributes 'nj_glo' (" << nj_glo.getValue() << "), 'nj' (" << nj.getValue() << ") and 'jbegin' (" << jbegin.getValue() << ")");
843       }
844     }
845
846     if (!j_index.isEmpty())
847     {
848        int minJIndex = (0 < j_index.numElements()) ? j_index(0) : 0;
849        if (nj.isEmpty()) 
850        {
851          // No information about nj
852          int minIndex = nj_glo - 1;
853          int maxIndex = 0;
854          for (int idx = 0; idx < j_index.numElements(); ++idx)
855          {
856            if (j_index(idx) < minIndex) minIndex = j_index(idx);
857            if (j_index(idx) > maxIndex) maxIndex = j_index(idx);
858          }
859          nj = maxIndex - minIndex + 1;
860          minJIndex = minIndex; 
861        } 
862        // It's the same as checkLocalIDomain. It's not so correct but if jbegin is not the first value of j_index
863        // then data on local domain has user-defined distribution. In this case, jbegin has no meaning.
864       if (jbegin.isEmpty()) jbegin = minJIndex;       
865     }
866     else if (jbegin.isEmpty() && nj.isEmpty())
867     {
868       jbegin = 0;
869       nj = nj_glo;
870     }     
871
872
873     if ((nj.getValue() < 0 || jbegin.getValue() < 0))
874     {
875       ERROR("CDomain::checkLocalJDomain(void)",
876              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
877              << "The local domain is wrongly defined,"
878              << " check the attributes 'nj_glo' (" << nj_glo.getValue() << "), 'nj' (" << nj.getValue() << ") and 'jbegin' (" << jbegin.getValue() << ")");
879     }
880   }
881
882   //----------------------------------------------------------------
883
884   void CDomain::checkMask(void)
885   {
886      if (!mask_1d.isEmpty() && !mask_2d.isEmpty())
887        ERROR("CDomain::checkMask(void)",
888              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
889              << "Both mask_1d and mask_2d are defined but only one can be used at the same time." << std::endl
890              << "Please define only one mask: 'mask_1d' or 'mask_2d'.");
891
892      if (!mask_1d.isEmpty() && mask_2d.isEmpty())
893      {
894        if (mask_1d.numElements() != i_index.numElements())
895          ERROR("CDomain::checkMask(void)",
896                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
897                << "'mask_1d' does not have the same size as the local domain." << std::endl
898                << "Local size is " << i_index.numElements() << "." << std::endl
899                << "Mask size is " << mask_1d.numElements() << ".");
900      }
901
902      if (mask_1d.isEmpty() && !mask_2d.isEmpty())
903      {
904        if (mask_2d.extent(0) != ni || mask_2d.extent(1) != nj)
905          ERROR("CDomain::checkMask(void)",
906                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
907                << "The mask does not have the same size as the local domain." << std::endl
908                << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
909                << "Mask size is " << mask_2d.extent(0) << " x " << mask_2d.extent(1) << ".");
910      }
911
912      if (!mask_2d.isEmpty())
913      {
914        mask_1d.resize(mask_2d.extent(0) * mask_2d.extent(1));
915        for (int j = 0; j < nj; ++j)
916          for (int i = 0; i < ni; ++i) mask_1d(i+j*ni) = mask_2d(i,j);
917        mask_2d.reset();
918      }
919      else if (mask_1d.isEmpty())
920      {
921        mask_1d.resize(i_index.numElements());
922        for (int i = 0; i < i_index.numElements(); ++i) mask_1d(i) = true;
923      }
924   }
925
926   //----------------------------------------------------------------
927
928   void CDomain::checkDomainData(void)
929   {
930      if (data_dim.isEmpty())
931      {
932        data_dim.setValue(1);
933      }
934      else if (!(data_dim.getValue() == 1 || data_dim.getValue() == 2))
935      {
936        ERROR("CDomain::checkDomainData(void)",
937              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
938              << "The data dimension is invalid, 'data_dim' must be 1 or 2 not << " << data_dim.getValue() << ".");
939      }
940
941      if (data_ibegin.isEmpty())
942         data_ibegin.setValue(0);
943      if (data_jbegin.isEmpty())
944         data_jbegin.setValue(0);
945
946      if (data_ni.isEmpty())
947      {
948        data_ni.setValue((data_dim == 1) ? (ni.getValue() * nj.getValue()) : ni.getValue());
949      }
950      else if (data_ni.getValue() < 0)
951      {
952        ERROR("CDomain::checkDomainData(void)",
953              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
954              << "The data size cannot be negative ('data_ni' = " << data_ni.getValue() << ").");
955      }
956
957      if (data_nj.isEmpty())
958      {
959        data_nj.setValue((data_dim.getValue() == 1) ? (ni.getValue() * nj.getValue()) : nj.getValue());
960      }
961      else if (data_nj.getValue() < 0)
962      {
963        ERROR("CDomain::checkDomainData(void)",
964              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
965              << "The data size cannot be negative ('data_nj' = " << data_nj.getValue() << ").");
966      }
967   }
968
969   //----------------------------------------------------------------
970
971   void CDomain::checkCompression(void)
972   {
973      if (!data_i_index.isEmpty())
974      {
975        if (!data_j_index.isEmpty() &&
976            data_j_index.numElements() != data_i_index.numElements())
977        {
978           ERROR("CDomain::checkCompression(void)",
979                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
980                 << "'data_i_index' and 'data_j_index' arrays must have the same size." << std::endl
981                 << "'data_i_index' size = " << data_i_index.numElements() << std::endl
982                 << "'data_j_index' size = " << data_j_index.numElements());
983        }
984
985        if (2 == data_dim)
986        {
987          if (data_j_index.isEmpty())
988          {
989             ERROR("CDomain::checkCompression(void)",
990                   << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
991                   << "'data_j_index' must be defined when 'data_i_index' is set and 'data_dim' is 2.");
992          }
993        }
994        else // (1 == data_dim)
995        {
996          if (data_j_index.isEmpty())
997          {
998            data_j_index.resize(data_ni);
999            for (int j = 0; j < data_ni; ++j) data_j_index(j) = 0;
1000          }
1001        }
1002      }
1003      else
1004      {
1005        if (data_dim == 2 && !data_j_index.isEmpty())
1006          ERROR("CDomain::checkCompression(void)",
1007                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1008                << "'data_i_index' must be defined when 'data_j_index' is set and 'data_dim' is 2.");
1009
1010        if (1 == data_dim)
1011        {
1012          data_i_index.resize(data_ni);
1013          data_j_index.resize(data_ni);
1014
1015          for (int i = 0; i < data_ni; ++i)
1016          {
1017            data_i_index(i) = i;
1018            data_j_index(i) = 0;
1019          }
1020        }
1021        else // (data_dim == 2)
1022        {
1023          const int dsize = data_ni * data_nj;
1024          data_i_index.resize(dsize);
1025          data_j_index.resize(dsize);
1026
1027          for(int count = 0, j = 0; j < data_nj; ++j)
1028          {
1029            for(int i = 0; i < data_ni; ++i, ++count)
1030            {
1031              data_i_index(count) = i;
1032              data_j_index(count) = j;
1033            }
1034          }
1035        }
1036      }
1037   }
1038
1039   //----------------------------------------------------------------
1040   void CDomain::computeLocalMask(void)
1041   {
1042     localMask.resize(ni*nj) ;
1043     localMask=false ;
1044     size_t zoom_ibegin= global_zoom_ibegin ;
1045     size_t zoom_iend= global_zoom_ibegin+global_zoom_ni-1 ;
1046     size_t zoom_jbegin= global_zoom_jbegin ;
1047     size_t zoom_jend= global_zoom_jbegin+global_zoom_nj-1 ;
1048
1049
1050     size_t dn=data_i_index.numElements() ;
1051     int i,j ;
1052     size_t k,ind ;
1053
1054     for(k=0;k<dn;k++)
1055     {
1056       if (data_dim==2)
1057       {
1058          i=data_i_index(k)+data_ibegin ;
1059          j=data_j_index(k)+data_jbegin ;
1060       }
1061       else
1062       {
1063          i=(data_i_index(k)+data_ibegin)%ni ;
1064          j=(data_i_index(k)+data_ibegin)/ni ;
1065       }
1066
1067       if (i>=0 && i<ni && j>=0 && j<nj)
1068         if (i+ibegin>=zoom_ibegin && i+ibegin<=zoom_iend && j+jbegin>=zoom_jbegin && j+jbegin<=zoom_jend)
1069         {
1070           ind=i+ni*j ;
1071           localMask(ind)=mask_1d(ind) ;
1072         }
1073     }
1074   }
1075
1076   void CDomain::checkEligibilityForCompressedOutput(void)
1077   {
1078     // We don't check if the mask or the indexes are valid here, just if they have been defined at this point.
1079     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !data_i_index.isEmpty();
1080   }
1081
1082   //----------------------------------------------------------------
1083
1084   void CDomain::completeLonLatClient(void)
1085   {
1086     bool lonlatValueExisted = (0 != lonvalue.numElements()) || (0 != latvalue.numElements());
1087     if (!lonvalue_2d.isEmpty() && !lonlatValueExisted)
1088     {
1089       lonvalue.resize(ni * nj);
1090       latvalue.resize(ni * nj);
1091       if (hasBounds)
1092       {
1093         bounds_lonvalue.resize(nvertex, ni * nj);
1094         bounds_latvalue.resize(nvertex, ni * nj);
1095       }
1096
1097       for (int j = 0; j < nj; ++j)
1098       {
1099         for (int i = 0; i < ni; ++i)
1100         {
1101           int k = j * ni + i;
1102
1103           lonvalue(k) = lonvalue_2d(i,j);
1104           latvalue(k) = latvalue_2d(i,j);
1105
1106           if (hasBounds)
1107           {
1108             for (int n = 0; n < nvertex; ++n)
1109             {
1110               bounds_lonvalue(n,k) = bounds_lon_2d(n,i,j);
1111               bounds_latvalue(n,k) = bounds_lat_2d(n,i,j);
1112             }
1113           }
1114         }
1115       }
1116     }
1117     else if (!lonvalue_1d.isEmpty()  && !lonlatValueExisted)
1118     {
1119       if (type_attr::rectilinear == type)
1120       {
1121         if (ni == lonvalue_1d.numElements() && nj == latvalue_1d.numElements())
1122         {
1123           lonvalue.resize(ni * nj);
1124           latvalue.resize(ni * nj);
1125           if (hasBounds)
1126           {
1127             bounds_lonvalue.resize(nvertex, ni * nj);
1128             bounds_latvalue.resize(nvertex, ni * nj);
1129           }
1130
1131           for (int j = 0; j < nj; ++j)
1132           {
1133             for (int i = 0; i < ni; ++i)
1134             {
1135               int k = j * ni + i;
1136
1137               lonvalue(k) = lonvalue_1d(i);
1138               latvalue(k) = latvalue_1d(j);
1139
1140               if (hasBounds)
1141               {
1142                 for (int n = 0; n < nvertex; ++n)
1143                 {
1144                   bounds_lonvalue(n,k) = bounds_lon_1d(n,i);
1145                   bounds_latvalue(n,k) = bounds_lat_1d(n,j);
1146                 }
1147               }
1148             }
1149           }
1150         }
1151         else if (i_index.numElements() == lonvalue_1d.numElements() && j_index.numElements() == latvalue_1d.numElements()  && !lonlatValueExisted)
1152         {
1153           lonvalue.reference(lonvalue_1d);
1154           latvalue.reference(latvalue_1d);
1155            if (hasBounds)
1156           {
1157             bounds_lonvalue.reference(bounds_lon_1d);
1158             bounds_latvalue.reference(bounds_lat_1d);
1159           }
1160         }
1161         else
1162           ERROR("CDomain::completeLonClient(void)",
1163                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1164                 << "'lonvalue_1d' and 'latvalue_1d' does not have the same size as the local domain." << std::endl
1165                 << "'lonvalue_1d' size is " << lonvalue_1d.numElements() 
1166                 << " and 'latvalue_1d' size is " << latvalue_1d.numElements() << std::endl
1167                 << " They should be correspondingly " << ni.getValue() << " and "  << nj.getValue() << " or " << std::endl
1168                 << i_index.numElements() << " and "  << j_index.numElements() << ".");
1169       }
1170       else if (type == type_attr::curvilinear || type == type_attr::unstructured  && !lonlatValueExisted)
1171       {
1172         lonvalue.reference(lonvalue_1d);
1173         latvalue.reference(latvalue_1d);
1174         if (hasBounds)
1175         {
1176           bounds_lonvalue.reference(bounds_lon_1d);
1177           bounds_latvalue.reference(bounds_lat_1d);
1178         }
1179       }
1180     }
1181   }
1182
1183   void CDomain::checkBounds(void)
1184   {
1185     bool hasBoundValues = (0 != bounds_lonvalue.numElements()) || (0 != bounds_latvalue.numElements());
1186     if (!nvertex.isEmpty() && nvertex > 0 && !hasBoundValues)
1187     {
1188       if (!bounds_lon_1d.isEmpty() && !bounds_lon_2d.isEmpty())
1189         ERROR("CDomain::checkBounds(void)",
1190               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1191               << "Only one longitude boundary attribute can be used but both 'bounds_lon_1d' and 'bounds_lon_2d' are defined." << std::endl
1192               << "Define only one longitude boundary attribute: 'bounds_lon_1d' or 'bounds_lon_2d'.");
1193
1194       if (!bounds_lat_1d.isEmpty() && !bounds_lat_2d.isEmpty())
1195         ERROR("CDomain::checkBounds(void)",
1196               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1197               << "Only one latitude boundary attribute can be used but both 'bounds_lat_1d' and 'bounds_lat_2d' are defined." << std::endl
1198               << "Define only one latitude boundary attribute: 'bounds_lat_1d' or 'bounds_lat_2d'.");
1199
1200       if ((!bounds_lon_1d.isEmpty() && bounds_lat_1d.isEmpty()) || (bounds_lon_1d.isEmpty() && !bounds_lat_1d.isEmpty()))
1201       {
1202         ERROR("CDomain::checkBounds(void)",
1203               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1204               << "Only 'bounds_lon_1d' or 'bounds_lat_1d' is defined." << std::endl
1205               << "Please define either both attributes or none.");
1206       }
1207
1208       if ((!bounds_lon_2d.isEmpty() && bounds_lat_2d.isEmpty()) || (bounds_lon_2d.isEmpty() && !bounds_lat_2d.isEmpty()))
1209       {
1210         ERROR("CDomain::checkBounds(void)",
1211               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1212               << "Only 'bounds_lon_2d' or 'bounds_lat_2d' is defined." << std::endl
1213               << "Please define either both attributes or none.");
1214       }
1215
1216       if (!bounds_lon_1d.isEmpty() && nvertex.getValue() != bounds_lon_1d.extent(0))
1217         ERROR("CDomain::checkBounds(void)",
1218               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1219               << "'bounds_lon_1d' dimension is not compatible with 'nvertex'." << std::endl
1220               << "'bounds_lon_1d' dimension is " << bounds_lon_1d.extent(1)
1221               << " but nvertex is " << nvertex.getValue() << ".");
1222
1223       if (!bounds_lon_2d.isEmpty() && nvertex.getValue() != bounds_lon_2d.extent(0))
1224         ERROR("CDomain::checkBounds(void)",
1225               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1226               << "'bounds_lon_2d' dimension is not compatible with 'nvertex'." << std::endl
1227               << "'bounds_lon_2d' dimension is " << bounds_lon_2d.extent(2)
1228               << " but nvertex is " << nvertex.getValue() << ".");
1229
1230       if (!bounds_lon_1d.isEmpty() && lonvalue_1d.isEmpty())
1231         ERROR("CDomain::checkBounds(void)",
1232               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1233               << "Since 'bounds_lon_1d' is defined, 'lonvalue_1d' must be defined too." << std::endl);
1234
1235       if (!bounds_lon_2d.isEmpty() && lonvalue_2d.isEmpty())
1236         ERROR("CDomain::checkBounds(void)",
1237               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1238               << "Since 'bounds_lon_2d' is defined, 'lonvalue_2d' must be defined too." << std::endl);
1239
1240       if (!bounds_lat_1d.isEmpty() && nvertex.getValue() != bounds_lat_1d.extent(0))
1241         ERROR("CDomain::checkBounds(void)",
1242               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1243               << "'bounds_lat_1d' dimension is not compatible with 'nvertex'." << std::endl
1244               << "'bounds_lat_1d' dimension is " << bounds_lat_1d.extent(1)
1245               << " but nvertex is " << nvertex.getValue() << ".");
1246
1247       if (!bounds_lat_2d.isEmpty() && nvertex.getValue() != bounds_lat_2d.extent(0))
1248         ERROR("CDomain::checkBounds(void)",
1249               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1250               << "'bounds_lat_2d' dimension is not compatible with 'nvertex'." << std::endl
1251               << "'bounds_lat_2d' dimension is " << bounds_lat_2d.extent(2)
1252               << " but nvertex is " << nvertex.getValue() << ".");
1253
1254       if (!bounds_lat_1d.isEmpty() && latvalue_1d.isEmpty())
1255         ERROR("CDomain::checkBounds(void)",
1256               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1257               << "Since 'bounds_lat_1d' is defined, 'latvalue_1d' must be defined too." << std::endl);
1258
1259       if (!bounds_lat_2d.isEmpty() && latvalue_2d.isEmpty())
1260         ERROR("CDomain::checkBounds(void)",
1261               << "Since 'bounds_lat_2d' is defined, 'latvalue_2d' must be defined too." << std::endl);
1262
1263       hasBounds = true;
1264     }
1265     else
1266     {
1267       hasBounds = false;
1268       nvertex = 0;
1269     }
1270   }
1271
1272   void CDomain::checkArea(void)
1273   {
1274     bool hasAreaValue = (0 != areavalue.numElements());
1275     hasArea = !area.isEmpty() || !areavalue.isEmpty();
1276     if (hasArea)
1277     {
1278       if (area.extent(0) != ni || area.extent(1) != nj)
1279       {
1280         ERROR("CDomain::checkArea(void)",
1281               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1282               << "The area does not have the same size as the local domain." << std::endl
1283               << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1284               << "Area size is " << area.extent(0) << " x " << area.extent(1) << ".");
1285       }
1286       if (areavalue.isEmpty())
1287       {
1288          areavalue.resize(ni*nj);
1289         for (int j = 0; j < nj; ++j)
1290         {
1291           for (int i = 0; i < ni; ++i)
1292           {
1293             int k = j * ni + i;
1294             areavalue(k) = area(i,j);
1295           }
1296         }
1297       }
1298     }
1299   }
1300
1301   void CDomain::checkLonLat()
1302   {
1303     hasLonLat = (!latvalue_1d.isEmpty() && !lonvalue_1d.isEmpty()) ||
1304                 (!latvalue_2d.isEmpty() && !lonvalue_2d.isEmpty());
1305     bool hasLonLatValue = (0 != lonvalue.numElements()) || (0 != latvalue.numElements());
1306     if (hasLonLat && !hasLonLatValue)
1307     {
1308       if (!lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
1309         ERROR("CDomain::checkLonLat()",
1310               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1311               << "Only one longitude attribute can be used but both 'lonvalue_1d' and 'lonvalue_2d' are defined." << std::endl
1312               << "Define only one longitude attribute: 'lonvalue_1d' or 'lonvalue_2d'.");
1313
1314       if (!lonvalue_1d.isEmpty() && lonvalue_2d.isEmpty())
1315       {
1316         if ((type_attr::rectilinear != type) && (lonvalue_1d.numElements() != i_index.numElements()))
1317           ERROR("CDomain::checkLonLat()",
1318                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1319                 << "'lonvalue_1d' does not have the same size as the local domain." << std::endl
1320                 << "Local size is " << i_index.numElements() << "." << std::endl
1321                 << "'lonvalue_1d' size is " << lonvalue_1d.numElements() << ".");
1322       }
1323
1324       if (lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
1325       {
1326         if (lonvalue_2d.extent(0) != ni || lonvalue_2d.extent(1) != nj)
1327           ERROR("CDomain::checkLonLat()",
1328                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1329                 << "'lonvalue_2d' does not have the same size as the local domain." << std::endl
1330                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1331                 << "'lonvalue_2d' size is " << lonvalue_2d.extent(0) << " x " << lonvalue_2d.extent(1) << ".");
1332       }
1333
1334       if (!latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
1335         ERROR("CDomain::checkLonLat()",
1336               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1337               << "Only one latitude attribute can be used but both 'latvalue_1d' and 'latvalue_2d' are defined." << std::endl
1338               << "Define only one latitude attribute: 'latvalue_1d' or 'latvalue_2d'.");
1339
1340       if (!latvalue_1d.isEmpty() && latvalue_2d.isEmpty())
1341       {
1342         if ((type_attr::rectilinear != type) && (latvalue_1d.numElements() != i_index.numElements()))
1343           ERROR("CDomain::checkLonLat()",
1344                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1345                 << "'latvalue_1d' does not have the same size as the local domain." << std::endl
1346                 << "Local size is " << i_index.numElements() << "." << std::endl
1347                 << "'latvalue_1d' size is " << latvalue_1d.numElements() << ".");
1348       }
1349
1350       if (latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
1351       {
1352         if (latvalue_2d.extent(0) != ni || latvalue_2d.extent(1) != nj)
1353           ERROR("CDomain::checkLonLat()",
1354                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1355                 << "'latvalue_2d' does not have the same size as the local domain." << std::endl
1356                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1357                 << "'latvalue_2d' size is " << latvalue_2d.extent(0) << " x " << latvalue_2d.extent(1) << ".");
1358       }
1359     }
1360   }
1361
1362   void CDomain::checkAttributesOnClientAfterTransformation()
1363   {
1364     CContext* context=CContext::getCurrent() ;
1365
1366     if (this->isClientAfterTransformationChecked) return;
1367     if (context->hasClient)
1368     {
1369       // this->checkMask();
1370      this->computeConnectedClients();
1371       // if (hasLonLat || hasArea || isCompressible_) this->computeConnectedClients();
1372       if (hasLonLat)
1373         if (!context->hasServer)
1374           this->completeLonLatClient();
1375     }
1376
1377     this->isClientAfterTransformationChecked = true;
1378   }
1379
1380   //----------------------------------------------------------------
1381   // Divide function checkAttributes into 2 seperate ones
1382   // This function only checks all attributes of current domain
1383   void CDomain::checkAttributesOnClient()
1384   {
1385     if (this->isClientChecked) return;
1386     CContext* context=CContext::getCurrent();
1387
1388      if (context->hasClient && !context->hasServer)
1389      {
1390        this->checkDomain();
1391        this->checkBounds();
1392        this->checkArea();
1393        this->checkLonLat();
1394      }
1395
1396      if (context->hasClient && !context->hasServer)
1397      { // CÃŽté client uniquement
1398         this->checkMask();
1399         this->checkDomainData();
1400         this->checkCompression();
1401         this->computeLocalMask() ;
1402      }
1403      else
1404      { // CÃŽté serveur uniquement
1405      }
1406
1407      this->isClientChecked = true;
1408   }
1409
1410   // Send all checked attributes to server
1411   void CDomain::sendCheckedAttributes()
1412   {
1413     if (!this->isClientChecked) checkAttributesOnClient();
1414     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation();
1415     CContext* context=CContext::getCurrent() ;
1416
1417     if (this->isChecked) return;
1418     if (context->hasClient)
1419     {
1420//       this->completeLonLatClient();
1421       sendAttributes();
1422     }
1423     this->isChecked = true;
1424   }
1425
1426   void CDomain::checkAttributes(void)
1427   {
1428      if (this->isChecked) return;
1429      CContext* context=CContext::getCurrent() ;
1430
1431      this->checkDomain();
1432      this->checkLonLat();
1433      this->checkBounds();
1434      this->checkArea();
1435
1436      if (context->hasClient)
1437      { // CÃŽté client uniquement
1438         this->checkMask();
1439         this->checkDomainData();
1440         this->checkCompression();
1441         this->computeLocalMask() ;
1442
1443      }
1444      else
1445      { // CÃŽté serveur uniquement
1446      }
1447
1448      if (context->hasClient)
1449      {
1450        this->computeConnectedClients();
1451        this->completeLonLatClient();
1452      }
1453
1454      this->isChecked = true;
1455   }
1456
1457
1458  // void CDomain::computeConnectedClients(const std::vector<int>& globalDim, int orderPositionInGrid,
1459  //                                     CServerDistributionDescription::ServerDistributionType distType)
1460  /*!
1461     Compute the connection of a client to other clients to determine which clients to send attributes to
1462  */
1463  void CDomain::computeConnectedClients()
1464  {
1465    CContext* context=CContext::getCurrent() ;
1466
1467    // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
1468    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
1469    for (int p = 0; p < nbSrvPools; ++p)
1470    {
1471      CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[p] : context->client;
1472      int nbServer = client->serverSize;
1473      int rank     = client->clientRank;
1474      bool doComputeGlobalIndexServer = true;
1475
1476      int i,j,i_ind,j_ind, nbIndex, nbIndexZoom;
1477      int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1;
1478      int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1;
1479
1480      // Precompute number of index
1481      int globalIndexCountZoom = 0;
1482      nbIndex = i_index.numElements();
1483
1484      if (doZoomByIndex_) 
1485      {
1486        globalIndexCountZoom = zoom_i_index.numElements();
1487      }
1488      else 
1489      {
1490        for (i = 0; i < nbIndex; ++i)
1491        {
1492          i_ind=i_index(i);
1493          j_ind=j_index(i);
1494
1495          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1496          {
1497            ++globalIndexCountZoom;
1498          }
1499        }
1500      }
1501
1502      // for (i = 0; i < nbIndex; ++i)
1503      // {
1504      //   i_ind=i_index(i);
1505      //   j_ind=j_index(i);
1506
1507      //   if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1508      //   {
1509      //     ++globalIndexCountZoom;
1510      //   }
1511      // }
1512
1513      // int globalIndexWrittenCount = 0;
1514      // if (isCompressible_)
1515      // {
1516      //   for (i = 0; i < data_i_index.numElements(); ++i)
1517      //   {
1518      //     i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1519      //                                                 data_ibegin, data_jbegin, data_dim, ni,
1520      //                                                 j_ind);
1521      //     if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1522      //     {
1523      //       i_ind += ibegin;
1524      //       j_ind += jbegin;
1525      //       if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1526      //         ++globalIndexWrittenCount;
1527      //     }
1528      //   }
1529      // }
1530
1531      // Fill in index
1532
1533      CArray<size_t,1> globalIndexDomainZoom(globalIndexCountZoom);
1534      CArray<size_t,1> localIndexDomainZoom(globalIndexCountZoom);
1535      CArray<size_t,1> globalIndexDomain(nbIndex);
1536      size_t globalIndex;
1537      int globalIndexCount = 0;
1538
1539      for (i = 0; i < nbIndex; ++i)
1540      {
1541        i_ind=i_index(i);
1542        j_ind=j_index(i);
1543        globalIndex = i_ind + j_ind * ni_glo;
1544        globalIndexDomain(i) = globalIndex;               
1545      }
1546
1547      if (globalLocalIndexMap_.empty())
1548      {
1549        for (i = 0; i < nbIndex; ++i)
1550          globalLocalIndexMap_[globalIndexDomain(i)] = i;
1551
1552      }
1553
1554      globalIndexCountZoom = 0;
1555      if (doZoomByIndex_) 
1556      {
1557        int nbIndexZoom = zoom_i_index.numElements();       
1558       
1559        for (i = 0; i < nbIndexZoom; ++i)
1560        {
1561          i_ind=zoom_i_index(i);
1562          j_ind=zoom_j_index(i);
1563          globalIndex = i_ind + j_ind * ni_glo;
1564          globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
1565          ++globalIndexCountZoom;
1566          // if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1567          // {
1568          //   globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
1569          //   localIndexDomainZoom(globalIndexCountZoom) = i;
1570          //   ++globalIndexCountZoom;
1571          // }
1572        }
1573      }
1574      else 
1575      {
1576          int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1;
1577          int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1;
1578          for (i = 0; i < nbIndex; ++i)
1579          {
1580            i_ind=i_index(i);
1581            j_ind=j_index(i);
1582            globalIndex = i_ind + j_ind * ni_glo;
1583            if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1584            {
1585              globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
1586              ++globalIndexCountZoom;
1587            }
1588          }
1589
1590          int iend = ibegin + ni -1;
1591          int jend = jbegin + nj -1;
1592          zoom_ibegin = global_zoom_ibegin > ibegin ? global_zoom_ibegin : ibegin;
1593          int zoom_iend   = global_zoom_iend < iend ? zoom_iend : iend ;
1594          zoom_ni     = zoom_iend-zoom_ibegin+1 ;
1595
1596          zoom_jbegin = global_zoom_jbegin > jbegin ? global_zoom_jbegin : jbegin ;
1597          int zoom_jend   = global_zoom_jend < jend ? zoom_jend : jend;
1598          zoom_nj     = zoom_jend-zoom_jbegin+1;
1599      }
1600
1601
1602      // CArray<int,1> globalIndexWrittenDomain(globalIndexWrittenCount);
1603      // if (isCompressible_)
1604      // {
1605      //   globalIndexWrittenCount = 0;
1606      //   for (i = 0; i < data_i_index.numElements(); ++i)
1607      //   {
1608      //     i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1609      //                                                 data_ibegin, data_jbegin, data_dim, ni,
1610      //                                                 j_ind);
1611      //     if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1612      //     {
1613      //       i_ind += ibegin;
1614      //       j_ind += jbegin;
1615      //       if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1616      //       {
1617      //         globalIndexWrittenDomain(globalIndexWrittenCount) = i_ind + j_ind * ni_glo;
1618      //         ++globalIndexWrittenCount;
1619      //       }
1620      //     }
1621      //   }
1622      // }
1623
1624      size_t globalSizeIndex = 1, indexBegin, indexEnd;
1625      int range, clientSize = client->clientSize;
1626      std::vector<int> nGlobDomain(2);
1627      nGlobDomain[0] = this->ni_glo;
1628      nGlobDomain[1] = this->nj_glo;
1629      for (int i = 0; i < nGlobDomain.size(); ++i) globalSizeIndex *= nGlobDomain[i];
1630      indexBegin = 0;
1631      if (globalSizeIndex <= clientSize)
1632      {
1633        indexBegin = rank%globalSizeIndex;
1634        indexEnd = indexBegin;
1635      }
1636      else
1637      {
1638        for (int i = 0; i < clientSize; ++i)
1639        {
1640          range = globalSizeIndex / clientSize;
1641          if (i < (globalSizeIndex%clientSize)) ++range;
1642          if (i == client->clientRank) break;
1643          indexBegin += range;
1644        }
1645        indexEnd = indexBegin + range - 1;
1646      }
1647
1648      CServerDistributionDescription serverDescription(nGlobDomain, nbServer);
1649      if (isUnstructed_) serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t,size_t>(indexBegin, indexEnd), 0);
1650      else serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t,size_t>(indexBegin, indexEnd), 1);
1651
1652      CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(),
1653                                                                                  client->intraComm);
1654      clientServerMap->computeServerIndexMapping(globalIndexDomain);
1655      CClientServerMapping::GlobalIndexMap& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer();
1656
1657      CClientServerMapping::GlobalIndexMap::const_iterator it  = globalIndexDomainOnServer.begin(),
1658                                                           ite = globalIndexDomainOnServer.end();
1659      // typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
1660      // std::vector<int>::iterator itVec;
1661
1662      // indSrv_.clear();
1663      // indWrittenSrv_.clear();
1664      // for (; it != ite; ++it)
1665      // {
1666      //   int rank = it->first;
1667      //   int indexSize = it->second.size();
1668      //   std::vector<int> permutIndex(indexSize);
1669      //   XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
1670      //   XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(it->second, permutIndex);
1671      //   BinarySearch binSearch(it->second);
1672      //   int nb = globalIndexDomainZoom.numElements();
1673      //   for (int i = 0; i < nb; ++i)
1674      //   {
1675      //     if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexDomainZoom(i), itVec))
1676      //     {
1677      //       indSrv_[rank].push_back(localIndexDomainZoom(i));
1678      //     }
1679      //   }
1680      //   for (int i = 0; i < globalIndexWrittenDomain.numElements(); ++i)
1681      //   {
1682      //     if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexWrittenDomain(i), itVec))
1683      //     {
1684      //       indWrittenSrv_[rank].push_back(globalIndexWrittenDomain(i));
1685      //     }
1686      //   }
1687      // }
1688
1689      connectedServerRank_.clear();
1690      for (it = globalIndexDomainOnServer.begin(); it != ite; ++it) {
1691        connectedServerRank_.push_back(it->first);
1692        // std::vector<size_t> vec = it->second;
1693        // std::sort(vec.begin(), vec.end());
1694        // indSrv_[it->first] = vec;
1695      }
1696
1697      indSrv_.swap(globalIndexDomainOnServer);
1698      nbConnectedClients_ = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
1699
1700      clientServerMap->computeServerIndexMapping(globalIndexDomainZoom);
1701      CClientServerMapping::GlobalIndexMap& globalIndexDomainZoomOnServer = clientServerMap->getGlobalIndexOnServer();
1702//      indZoomSrv_.swap(globalIndexDomainZoomOnServer);
1703      std::vector<int> connectedServerZoomRank; //(indZoomSrv_.size());
1704//      for (it = indZoomSrv_.begin(); it != indZoomSrv_.end(); ++it)
1705//        connectedServerZoomRank.push_back(it->first);
1706      for (it = globalIndexDomainZoomOnServer.begin(); it != globalIndexDomainZoomOnServer.end(); ++it)
1707      {
1708        connectedServerZoomRank.push_back(it->first);
1709        std::vector<size_t> vec = it->second;
1710        std::sort(vec.begin(), vec.end());
1711        indZoomSrv_[it->first] = vec;
1712      }
1713      nbConnectedClientsZoom_ = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerZoomRank);
1714
1715      delete clientServerMap;
1716    }
1717  }
1718
1719  const boost::unordered_map<int, vector<size_t> >& CDomain::getIndexServer() const
1720  {
1721    return indSrv_;
1722  }
1723
1724  /*!
1725    Send all attributes from client to connected clients
1726    The attributes will be rebuilt on receiving side
1727  */
1728  void CDomain::sendAttributes()
1729  {
1730    sendDistributionAttributes();
1731    sendIndex();
1732    sendIndex();   
1733    sendMask();
1734    sendLonLat();
1735    sendArea();   
1736    sendDataIndex();
1737  }
1738
1739  /*!
1740    Send global index and zoom index from client to connected client(s)
1741    zoom index can be smaller than global index
1742  */
1743  void CDomain::sendIndex()
1744  {
1745    int ns, n, i, j, ind, nv, idx;
1746    CContext* context = CContext::getCurrent();
1747
1748    // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
1749    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
1750    for (int p = 0; p < nbSrvPools; ++p)
1751    {
1752      CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[p] : context->client;
1753
1754      CEventClient eventIndex(getType(), EVENT_ID_INDEX);
1755
1756      list<CMessage> list_msgsIndex;
1757      list<CArray<int,1> > list_indZoom, list_writtenInd, list_indGlob;
1758
1759      boost::unordered_map<int, vector<size_t> >::const_iterator itIndex, iteIndex, itZoom, iteZoom;
1760      iteIndex = indSrv_.end(); iteZoom = indZoomSrv_.end();
1761      for (int k = 0; k < connectedServerRank_.size(); ++k)
1762      {
1763        int nbIndGlob = 0;
1764        int rank = connectedServerRank_[k];
1765        itIndex = indSrv_.find(rank);
1766        if (iteIndex != itIndex)
1767          nbIndGlob = itIndex->second.size();
1768        int nbIndZoom = 0;
1769        itZoom = indZoomSrv_.find(rank);
1770        if (iteZoom != itZoom)
1771          nbIndZoom = itZoom->second.size();
1772
1773        list_indGlob.push_back(CArray<int,1>(nbIndGlob));
1774        list_indZoom.push_back(CArray<int,1>(nbIndZoom));
1775
1776        CArray<int,1>& indZoom = list_indZoom.back();
1777        CArray<int,1>& indGlob = list_indGlob.back();
1778        for (n = 0; n < nbIndGlob; ++n)
1779        {
1780          indGlob(n) = static_cast<int>(itIndex->second[n]);
1781        }
1782
1783        for (n = 0; n < nbIndZoom; ++n)
1784        {
1785          indZoom(n) = static_cast<int>(itZoom->second[n]);
1786        }
1787
1788        list_msgsIndex.push_back(CMessage());
1789        list_msgsIndex.back() << this->getId() << (int)type; // enum ne fonctionne pour les message => ToFix
1790        list_msgsIndex.back() << isCurvilinear;
1791        list_msgsIndex.back() << list_indGlob.back() << list_indZoom.back() << doZoomByIndex_; //list_indi.back() << list_indj.back();
1792        if (!doZoomByIndex_) 
1793        {
1794          //list_msgsIndex.back() << zoom_ni.getValue() << zoom_ibegin.getValue() << zoom_nj.getValue() << zoom_jbegin.getValue();
1795        }
1796       
1797        // if (isCompressible_)
1798        // {
1799        //   std::vector<int>& writtenIndSrc = indWrittenSrv_[rank];
1800        //   list_writtenInd.push_back(CArray<int,1>(writtenIndSrc.size()));
1801        //   CArray<int,1>& writtenInd = list_writtenInd.back();
1802
1803        //   for (n = 0; n < writtenInd.numElements(); ++n)
1804        //     writtenInd(n) = writtenIndSrc[n];
1805
1806        //   list_msgsIndex.back() << writtenInd;
1807        // }
1808
1809        eventIndex.push(rank, nbConnectedClients_[rank], list_msgsIndex.back());
1810      }
1811
1812      client->sendEvent(eventIndex);
1813    }
1814  }
1815
1816  /*!
1817    Send distribution from client to other clients
1818    Because a client in a level knows correctly the grid distribution of client on the next level
1819    it calculates this distribution then sends it to the corresponding clients on the next level
1820  */
1821  void CDomain::sendDistributionAttributes(void)
1822  {
1823    CContext* context = CContext::getCurrent();
1824     // Use correct context client to send message
1825    // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
1826    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
1827    for (int i = 0; i < nbSrvPools; ++i)
1828    {
1829      CContextClient* contextClientTmp = (context->hasServer) ? context->clientPrimServer[i]
1830                                                                         : context->client;   
1831      int nbServer = contextClientTmp->serverSize;
1832      std::vector<int> nGlobDomain(2);
1833      nGlobDomain[0] = this->ni_glo;
1834      nGlobDomain[1] = this->nj_glo;
1835
1836      CServerDistributionDescription serverDescription(nGlobDomain, nbServer);
1837      if (isUnstructed_) serverDescription.computeServerDistribution(false, 0);
1838      else serverDescription.computeServerDistribution(false, 1);
1839
1840      std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
1841      std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
1842
1843      CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT);
1844      if (contextClientTmp->isServerLeader())
1845      {
1846        std::list<CMessage> msgs;
1847
1848        const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1849        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1850        {
1851          // Use const int to ensure CMessage holds a copy of the value instead of just a reference
1852          const int ibegin_srv = serverIndexBegin[*itRank][0];
1853          const int jbegin_srv = serverIndexBegin[*itRank][1];
1854          const int ni_srv = serverDimensionSizes[*itRank][0];
1855          const int nj_srv = serverDimensionSizes[*itRank][1];
1856
1857          msgs.push_back(CMessage());
1858          CMessage& msg = msgs.back();
1859          msg << this->getId() ;
1860          msg << ni_srv << ibegin_srv << nj_srv << jbegin_srv;
1861          msg << global_zoom_ni.getValue() << global_zoom_ibegin.getValue() << global_zoom_nj.getValue() << global_zoom_jbegin.getValue();       
1862          msg << isCompressible_;
1863
1864          event.push(*itRank,1,msg);
1865        }
1866        contextClientTmp->sendEvent(event);
1867      }
1868      else contextClientTmp->sendEvent(event);
1869    }
1870  }
1871
1872  /*!
1873    Send mask index from client to connected(s)
1874  */
1875  void CDomain::sendMask()
1876  {
1877    int ns, n, i, j, ind, nv, idx;
1878    CContext* context = CContext::getCurrent();
1879
1880    // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
1881    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
1882    for (int p = 0; p < nbSrvPools; ++p)
1883    {
1884      CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[p] : context->client;
1885
1886      // send area for each connected server
1887      CEventClient eventMask(getType(), EVENT_ID_MASK);
1888
1889      list<CMessage> list_msgsMask;
1890      list<CArray<bool,1> > list_mask;
1891
1892      boost::unordered_map<int, vector<size_t> >::const_iterator it, iteMap;
1893      iteMap = indSrv_.end();
1894      for (int k = 0; k < connectedServerRank_.size(); ++k)
1895      {
1896        int nbData = 0;
1897        int rank = connectedServerRank_[k];
1898        it = indSrv_.find(rank);
1899        if (iteMap != it)
1900          nbData = it->second.size();
1901        list_mask.push_back(CArray<bool,1>(nbData));
1902
1903        const std::vector<size_t>& temp = it->second;
1904        for (n = 0; n < nbData; ++n)
1905        {
1906          idx = static_cast<int>(it->second[n]);
1907          list_mask.back()(n) = mask_1d(globalLocalIndexMap_[idx]);
1908        }
1909
1910        list_msgsMask.push_back(CMessage());
1911        list_msgsMask.back() << this->getId() << list_mask.back();
1912        eventMask.push(rank, nbConnectedClients_[rank], list_msgsMask.back());
1913      }
1914      client->sendEvent(eventMask);
1915    }
1916  }
1917
1918  /*!
1919    Send area from client to connected client(s)
1920  */
1921  void CDomain::sendArea()
1922  {
1923    if (!hasArea) return;
1924
1925    int ns, n, i, j, ind, nv, idx;
1926    CContext* context = CContext::getCurrent();
1927
1928    // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
1929    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
1930    for (int p = 0; p < nbSrvPools; ++p)
1931    {
1932      CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[p] : context->client;
1933
1934      // send area for each connected server
1935      CEventClient eventArea(getType(), EVENT_ID_AREA);
1936
1937      list<CMessage> list_msgsArea;
1938      list<CArray<double,1> > list_area;
1939
1940      boost::unordered_map<int, vector<size_t> >::const_iterator it, iteMap;
1941      iteMap = indSrv_.end();
1942      for (int k = 0; k < connectedServerRank_.size(); ++k)
1943      {
1944        int nbData = 0;
1945        int rank = connectedServerRank_[k];
1946        it = indSrv_.find(rank);
1947        if (iteMap != it)
1948          nbData = it->second.size();
1949        list_area.push_back(CArray<double,1>(nbData));
1950
1951        const std::vector<size_t>& temp = it->second;
1952        for (n = 0; n < nbData; ++n)
1953        {
1954          idx = static_cast<int>(it->second[n]);
1955          list_area.back()(n) = areavalue(globalLocalIndexMap_[idx]);
1956        }
1957
1958        list_msgsArea.push_back(CMessage());
1959        list_msgsArea.back() << this->getId() << hasArea;
1960        list_msgsArea.back() << list_area.back();
1961        eventArea.push(rank, nbConnectedClients_[rank], list_msgsArea.back());
1962      }
1963      client->sendEvent(eventArea);
1964    }
1965  }
1966
1967  /*!
1968    Send longitude and latitude from client to servers
1969    Each client send long and lat information to corresponding connected server(s).
1970    Because longitude and latitude are optional, this function only called if latitude and longitude exist
1971  */
1972  void CDomain::sendLonLat()
1973  {
1974    if (!hasLonLat) return;
1975
1976    int ns, n, i, j, ind, nv, idx;
1977    CContext* context = CContext::getCurrent();
1978
1979    // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
1980    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
1981    for (int p = 0; p < nbSrvPools; ++p)
1982    {
1983      CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[p] : context->client;
1984
1985      // send lon lat for each connected server
1986      CEventClient eventLon(getType(), EVENT_ID_LON);
1987      CEventClient eventLat(getType(), EVENT_ID_LAT);
1988
1989      list<CMessage> list_msgsLon, list_msgsLat;
1990      list<CArray<double,1> > list_lon, list_lat;
1991      list<CArray<double,2> > list_boundslon, list_boundslat;
1992
1993      boost::unordered_map<int, vector<size_t> >::const_iterator it, iteMap;
1994      iteMap = indSrv_.end();
1995      for (int k = 0; k < connectedServerRank_.size(); ++k)
1996      {
1997        int nbData = 0;
1998        int rank = connectedServerRank_[k];
1999        it = indSrv_.find(rank);
2000        if (iteMap != it)
2001          nbData = it->second.size();
2002
2003        list_lon.push_back(CArray<double,1>(nbData));
2004        list_lat.push_back(CArray<double,1>(nbData));
2005
2006        if (hasBounds)
2007        {
2008          list_boundslon.push_back(CArray<double,2>(nvertex, nbData));
2009          list_boundslat.push_back(CArray<double,2>(nvertex, nbData));
2010        }
2011
2012        CArray<double,1>& lon = list_lon.back();
2013        CArray<double,1>& lat = list_lat.back();
2014        const std::vector<size_t>& temp = it->second;
2015        for (n = 0; n < nbData; ++n)
2016        {
2017          idx = static_cast<int>(it->second[n]);
2018          int localInd = globalLocalIndexMap_[idx];
2019          lon(n) = lonvalue(localInd);
2020          lat(n) = latvalue(localInd);
2021
2022          if (hasBounds)
2023          {
2024            CArray<double,2>& boundslon = list_boundslon.back();
2025            CArray<double,2>& boundslat = list_boundslat.back();
2026
2027            for (nv = 0; nv < nvertex; ++nv)
2028            {
2029              boundslon(nv, n) = bounds_lonvalue(nv, localInd);
2030              boundslat(nv, n) = bounds_latvalue(nv, localInd);
2031            }
2032          }
2033        }
2034
2035        list_msgsLon.push_back(CMessage());
2036        list_msgsLat.push_back(CMessage());
2037
2038        list_msgsLon.back() << this->getId() << hasLonLat << list_lon.back() << hasBounds;
2039        list_msgsLat.back() << this->getId() << hasLonLat << list_lat.back() << hasBounds;
2040
2041        if (hasBounds)
2042        {
2043          list_msgsLon.back() << list_boundslon.back();
2044          list_msgsLat.back() << list_boundslat.back();
2045        }
2046
2047        eventLon.push(rank, nbConnectedClients_[rank], list_msgsLon.back());
2048        eventLat.push(rank, nbConnectedClients_[rank], list_msgsLat.back());
2049      }
2050      client->sendEvent(eventLon);
2051      client->sendEvent(eventLat);
2052    }
2053  }
2054
2055  /*!
2056    Send data index to corresponding connected clients.
2057    Data index can be compressed however, we always send decompressed data index
2058    and they will be compressed on receiving.
2059  */
2060  void CDomain::sendDataIndex()
2061  {
2062    int ns, n, i, j, ind, nv, idx;
2063    CContext* context = CContext::getCurrent();
2064
2065    // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
2066    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
2067    for (int p = 0; p < nbSrvPools; ++p)
2068    {
2069      CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[p] : context->client;
2070
2071      // send area for each connected server
2072      CEventClient eventDataIndex(getType(), EVENT_ID_DATA_INDEX);
2073
2074      list<CMessage> list_msgsDataIndex;
2075      list<CArray<int,1> > list_data_i_index, list_data_j_index;
2076
2077      int nbIndex = i_index.numElements();
2078      CArray<int,1> dataIIndex(nbIndex), dataJIndex(nbIndex);
2079      dataIIndex = -1; dataJIndex = -1, ind = 0;
2080      for (idx = 0; idx < data_i_index.numElements(); ++idx)
2081      {
2082        if ((0 <= data_i_index(idx)) && (data_i_index(idx) < ni) && (ind < nbIndex))
2083        {
2084          dataIIndex(ind) = data_i_index(idx);
2085          dataJIndex(ind) = data_j_index(idx);
2086          ++ind;
2087        }
2088      }
2089
2090      boost::unordered_map<int, vector<size_t> >::const_iterator it, iteMap;
2091      iteMap = indSrv_.end();
2092      for (int k = 0; k < connectedServerRank_.size(); ++k)
2093      {
2094        int nbData = 0;
2095        int rank = connectedServerRank_[k];
2096        it = indSrv_.find(rank);
2097        if (iteMap != it)
2098          nbData = it->second.size();
2099        list_data_i_index.push_back(CArray<int,1>(nbData));
2100        list_data_j_index.push_back(CArray<int,1>(nbData));
2101
2102        const std::vector<size_t>& temp = it->second;
2103        for (n = 0; n < nbData; ++n)
2104        {
2105          idx = static_cast<int>(it->second[n]);
2106          i = globalLocalIndexMap_[idx];
2107          list_data_i_index.back()(n) = dataIIndex(i);
2108          list_data_j_index.back()(n) = dataJIndex(i);
2109        }
2110
2111        list_msgsDataIndex.push_back(CMessage());
2112        list_msgsDataIndex.back() << this->getId();
2113        list_msgsDataIndex.back() << list_data_i_index.back() << list_data_j_index.back();
2114        eventDataIndex.push(rank, nbConnectedClients_[rank], list_msgsDataIndex.back());
2115      }
2116      client->sendEvent(eventDataIndex);
2117    }
2118  }
2119 
2120  bool CDomain::dispatchEvent(CEventServer& event)
2121  {
2122    if (SuperClass::dispatchEvent(event)) return true;
2123    else
2124    {
2125      switch(event.type)
2126      {
2127        case EVENT_ID_SERVER_ATTRIBUT:
2128          recvDistributionAttributes(event);
2129          return true;
2130          break;
2131        case EVENT_ID_INDEX:
2132          recvIndex(event);
2133          return true;
2134          break;
2135        case EVENT_ID_MASK:
2136          recvMask(event);
2137          return true;
2138          break;
2139        case EVENT_ID_LON:
2140          recvLon(event);
2141          return true;
2142          break;
2143        case EVENT_ID_LAT:
2144          recvLat(event);
2145          return true;
2146          break;
2147        case EVENT_ID_AREA:
2148          recvArea(event);
2149          return true;
2150          break; 
2151        case EVENT_ID_DATA_INDEX:
2152          recvDataIndex(event);
2153          return true;
2154          break;
2155        default:
2156          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
2157                << "Unknown Event");
2158          return false;
2159       }
2160    }
2161  }
2162
2163  /*!
2164    Receive index event from clients(s)
2165    \param[in] event event contain info about rank and associated index
2166  */
2167  void CDomain::recvIndex(CEventServer& event)
2168  {
2169    string domainId;
2170    std::map<int, CBufferIn*> rankBuffers;
2171
2172    list<CEventServer::SSubEvent>::iterator it;
2173    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2174    {     
2175      CBufferIn* buffer = it->buffer;
2176      *buffer >> domainId;
2177      rankBuffers[it->rank] = buffer;       
2178    }
2179    get(domainId)->recvIndex(rankBuffers);
2180
2181    // if (domain->isCompressible_)
2182    // {
2183    //   std::sort(domain->indexesToWrite.begin(), domain->indexesToWrite.end());
2184
2185    //   CContextServer* server = CContext::getCurrent()->server;
2186    //   domain->numberWrittenIndexes_ = domain->indexesToWrite.size();
2187    //   MPI_Allreduce(&domain->numberWrittenIndexes_, &domain->totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
2188    //   MPI_Scan(&domain->numberWrittenIndexes_, &domain->offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
2189    //   domain->offsetWrittenIndexes_ -= domain->numberWrittenIndexes_;
2190    // }
2191  }
2192
2193  /*!
2194    Receive index information from client(s)
2195    \param[in] rankBuffers rank of sending client and the corresponding receive buffer 
2196  */
2197  void CDomain::recvIndex(std::map<int, CBufferIn*>& rankBuffers)
2198  {
2199    int nbReceived = rankBuffers.size(), i, ind, index, type_int;
2200    recvClientRanks_.resize(nbReceived);
2201    vector<CArray<int,1> > recvZoomInd(nbReceived);
2202    int ni_zoom_tmp, ibegin_zoom_tmp, nj_zoom_tmp, jbegin_zoom_tmp;
2203
2204    std::map<int, CBufferIn*>::iterator it = rankBuffers.begin(), ite = rankBuffers.end();
2205    ind = 0;
2206    for (ind = 0; it != ite; ++it, ++ind)
2207    {       
2208       recvClientRanks_[ind] = it->first;
2209       CBufferIn& buffer = *(it->second);
2210       buffer >> type_int >> isCurvilinear >> indGlob_[it->first] >> recvZoomInd[ind] >> doZoomByIndex_; 
2211       if (!doZoomByIndex_)
2212       {
2213        //buffer >> ni_zoom_tmp >> ibegin_zoom_tmp >> nj_zoom_tmp >> jbegin_zoom_tmp;
2214       }
2215       type.setValue((type_attr::t_enum)type_int); // probleme des type enum avec les buffers : ToFix
2216    }
2217    int nbIndGlob = 0;
2218    for (i = 0; i < nbReceived; ++i)
2219    {
2220      nbIndGlob += indGlob_[recvClientRanks_[i]].numElements();
2221    }
2222   
2223    i_index.resize(nbIndGlob);
2224    j_index.resize(nbIndGlob);
2225
2226    nbIndGlob = 0;
2227    for (i = 0; i < nbReceived; ++i)
2228    {
2229      CArray<int,1>& tmp = indGlob_[recvClientRanks_[i]];
2230      for (ind = 0; ind < tmp.numElements(); ++ind)
2231      {
2232         index = tmp(ind);
2233         i_index(nbIndGlob) = index % ni_glo;
2234         j_index(nbIndGlob) = index / ni_glo;
2235         ++nbIndGlob;
2236      } 
2237    }
2238
2239    int nbZoomInd = 0;
2240    for (i = 0; i < nbReceived; ++i)
2241    {
2242      nbZoomInd += recvZoomInd[i].numElements();
2243    }
2244
2245    if (doZoomByIndex_)
2246    {
2247      zoom_i_index.resize(nbZoomInd);
2248      zoom_j_index.resize(nbZoomInd);
2249     
2250      nbZoomInd = 0;
2251      for (i = 0; i < nbReceived; ++i)
2252      {
2253        CArray<int,1>& tmp = recvZoomInd[i];
2254        for (ind = 0; ind < tmp.numElements(); ++ind)
2255        {
2256           index = tmp(ind);
2257           zoom_i_index(nbZoomInd) = index % ni_glo;
2258           zoom_j_index(nbZoomInd) = index / ni_glo;
2259           ++nbZoomInd;
2260        } 
2261      }     
2262    }
2263    else 
2264    {
2265      // zoom_ni.setValue(ni_zoom_tmp);
2266      // zoom_ibegin.setValue(ibegin_zoom_tmp);
2267      // zoom_nj.setValue(nj_zoom_tmp);
2268      // zoom_jbegin.setValue(jbegin_zoom_tmp);
2269      // int nbZoom = ni_zoom_tmp * nj_zoom_tmp;
2270      // zoom_i_index.resize(nbZoom);
2271      // zoom_j_index.resize(nbZoom);
2272      // nbZoom = 0;
2273      // for (int j = 0; j < nj_zoom_tmp; ++j)
2274      //   for (int i = 0; i < ni_zoom_tmp; ++i)
2275      //   {
2276      //     zoom_i_index(nbZoom) = ibegin_zoom_tmp + i;
2277      //     zoom_j_index(nbZoom) = jbegin_zoom_tmp + j;
2278      //     ++nbZoom;
2279      //   }
2280    }
2281
2282    globalLocalIndexMap_.rehash(std::ceil(nbIndGlob/globalLocalIndexMap_.max_load_factor()));
2283    nbIndGlob = 0;
2284    for (int j = 0; j < nj; ++j) 
2285      for (int i = 0; i < ni; ++i)
2286      {
2287        globalLocalIndexMap_[(i + ibegin) + (j + jbegin) * ni_glo] = nbIndGlob;
2288        ++nbIndGlob;
2289      }
2290
2291
2292   
2293    // {
2294    //   CContextServer* server = CContext::getCurrent()->server;
2295    //   count_write_index_.resize(2);
2296    //   start_write_index_.resize(2);
2297    //   local_write_size_.resize(2);
2298    //   global_write_size_.resize(2);
2299    //   if ((this->type) == CDomain::type_attr::unstructured)
2300    //   {
2301    //     count_write_index_[0] = zoom_i_index.numElements();
2302    //     count_write_index_[1] = 0;
2303    //   }
2304    //   else
2305    //   {
2306    //     int ni_zoom = zoom_i_index.numElements(), idx, nbIZoom = 0, nbJZoom = 0;
2307    //     for (idx =0; idx < ni_zoom; ++idx)
2308    //     {
2309    //        if ((ibegin <= zoom_i_index(idx)) && (zoom_i_index(idx) < ibegin+ni) && (nbIZoom < ni))
2310    //         ++nbIZoom;
2311    //        if ((jbegin <= zoom_j_index(idx)) && (zoom_j_index(idx) < jbegin+nj) && (nbJZoom < nj))
2312    //         ++nbJZoom;
2313    //     }
2314    //     count_write_index_[0] = nbIZoom;
2315    //     count_write_index_[1] = nbJZoom;
2316
2317    //     // Reoder the zoom_index
2318    //     for (int j = 0; j < nbJZoom; ++j)
2319    //       for (int i = 0; i < nbIZoom; ++i)
2320    //       {
2321    //         idx = nbIZoom * j + i;
2322    //         if (idx < ni_zoom)
2323    //         {
2324    //           zoom_i_index(idx) = ibegin + i;
2325    //           zoom_j_index(idx) = jbegin + j;
2326    //         }
2327    //       } 
2328
2329    //     // Reorder the global index
2330    //     for (int j = 0; j < nj; ++j)
2331    //       for (int i = 0; i < ni; ++i)
2332    //       {
2333    //         idx = ni * j + i;
2334    //         if (idx < nbIndGlob)
2335    //         {
2336    //           i_index(idx) = ibegin + i;
2337    //           j_index(idx) = jbegin + j;
2338    //         }
2339    //       }         
2340    //   }
2341
2342           
2343    //   MPI_Scan(&count_write_index_[0], &start_write_index_[0], 2, MPI_INT, MPI_SUM, server->intraComm);     
2344    //   start_write_index_[0] = 0;
2345    //   start_write_index_[1] -= count_write_index_[1];
2346    //   local_write_size_[0] = count_write_index_[0];
2347    //   local_write_size_[1] = count_write_index_[1];
2348    //   MPI_Allreduce(&count_write_index_[0], &global_write_size_[0], 2, MPI_INT, MPI_SUM, server->intraComm);
2349    //   global_write_size_[0] = count_write_index_[0];
2350    //   global_write_size_[1] = (global_write_size_[1] > nj_glo) ? nj_glo : global_write_size_[1];
2351         
2352
2353    // }
2354
2355    // int type_int;
2356    // buffer >> type_int >> isCurvilinear >> indiSrv[rank] >> indjSrv[rank];
2357    // type.setValue((type_attr::t_enum)type_int); // probleme des type enum avec les buffers : ToFix
2358
2359    // if (isCompressible_)
2360    // {
2361    //   CArray<int, 1> writtenIndexes;
2362    //   buffer >> writtenIndexes;
2363    //   indexesToWrite.reserve(indexesToWrite.size() + writtenIndexes.numElements());
2364    //   for (int i = 0; i < writtenIndexes.numElements(); ++i)
2365    //     indexesToWrite.push_back(writtenIndexes(i));
2366    // }
2367  }
2368
2369  /*!
2370    Receive attributes event from clients(s)
2371    \param[in] event event contain info about rank and associated attributes
2372  */
2373  void CDomain::recvDistributionAttributes(CEventServer& event)
2374  {
2375    CBufferIn* buffer=event.subEvents.begin()->buffer;
2376    string domainId ;
2377    *buffer>>domainId ;
2378    get(domainId)->recvDistributionAttributes(*buffer);
2379  }
2380
2381  /*!
2382    Receive attributes from client(s): zoom info and begin and n of each server
2383    \param[in] rank rank of client source
2384    \param[in] buffer message containing attributes info
2385  */
2386  void CDomain::recvDistributionAttributes(CBufferIn& buffer)
2387  {
2388    int ni_tmp, ibegin_tmp, nj_tmp, jbegin_tmp;
2389    int global_zoom_ni_tmp, global_zoom_ibegin_tmp, global_zoom_nj_tmp, global_zoom_jbegin_tmp;
2390    buffer >> ni_tmp >> ibegin_tmp >> nj_tmp >> jbegin_tmp
2391           >> global_zoom_ni_tmp >> global_zoom_ibegin_tmp >> global_zoom_nj_tmp >> global_zoom_jbegin_tmp           
2392           >> isCompressible_;
2393    ni.setValue(ni_tmp);
2394    ibegin.setValue(ibegin_tmp);
2395    nj.setValue(nj_tmp);
2396    jbegin.setValue(jbegin_tmp);
2397
2398    global_zoom_ni.setValue(global_zoom_ni_tmp);
2399    global_zoom_ibegin.setValue(global_zoom_ibegin_tmp);
2400    global_zoom_nj.setValue(global_zoom_nj_tmp);
2401    global_zoom_jbegin.setValue(global_zoom_jbegin_tmp);
2402
2403    int iend = ibegin + ni  - 1;
2404    int jend = jbegin + nj  - 1;
2405    int zoom_iend_glob = global_zoom_ibegin + global_zoom_ni - 1;
2406    int zoom_jend_glob = global_zoom_jbegin + global_zoom_nj - 1;
2407
2408    zoom_ibegin.setValue(global_zoom_ibegin > ibegin ? global_zoom_ibegin : ibegin);
2409    int zoom_iend = zoom_iend_glob < iend ? zoom_iend_glob : iend ;
2410    zoom_ni.setValue(zoom_iend-zoom_ibegin+1);
2411
2412    zoom_jbegin.setValue(global_zoom_jbegin > jbegin ? global_zoom_jbegin : jbegin);
2413    int zoom_jend = zoom_jend_glob < jend ? zoom_jend_glob : jend ;
2414    zoom_nj.setValue(zoom_jend-zoom_jbegin+1);
2415
2416    if (zoom_ni<=0 || zoom_nj<=0)
2417    {
2418      zoom_ibegin=0 ; zoom_iend=0 ; zoom_ni=0 ;
2419      zoom_jbegin=0 ; zoom_jend=0 ; zoom_nj=0 ;
2420    }
2421
2422  }
2423
2424  /*!
2425    Receive area event from clients(s)
2426    \param[in] event event contain info about rank and associated area
2427  */
2428  void CDomain::recvMask(CEventServer& event)
2429  {
2430    string domainId;
2431    std::map<int, CBufferIn*> rankBuffers;
2432
2433    list<CEventServer::SSubEvent>::iterator it;
2434    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2435    {     
2436      CBufferIn* buffer = it->buffer;
2437      *buffer >> domainId;
2438      rankBuffers[it->rank] = buffer;     
2439    }
2440    get(domainId)->recvMask(rankBuffers);
2441  }
2442
2443
2444  /*!
2445    Receive mask information from client(s)
2446    \param[in] rankBuffers rank of sending client and the corresponding receive buffer 
2447  */
2448  void CDomain::recvMask(std::map<int, CBufferIn*>& rankBuffers)
2449  {
2450    int nbReceived = rankBuffers.size(), i, ind, index;
2451    if (nbReceived != recvClientRanks_.size())
2452      ERROR("void CDomain::recvArea(std::map<int, CBufferIn*>& rankBuffers)",
2453           << "The number of sending clients is not correct."
2454           << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived);
2455
2456    vector<CArray<bool,1> > recvMaskValue(nbReceived);     
2457    for (i = 0; i < recvClientRanks_.size(); ++i)
2458    {
2459      int rank = recvClientRanks_[i];
2460      CBufferIn& buffer = *(rankBuffers[rank]);     
2461      buffer >> recvMaskValue[i];
2462    }
2463
2464    int nbMaskInd = 0;
2465    for (i = 0; i < nbReceived; ++i)
2466    {
2467      nbMaskInd += recvMaskValue[i].numElements();
2468    }
2469 
2470    mask_1d.resize(nbMaskInd);
2471    nbMaskInd = 0;
2472    for (i = 0; i < nbReceived; ++i)
2473    {
2474      CArray<bool,1>& tmp = recvMaskValue[i];
2475      for (ind = 0; ind < tmp.numElements(); ++ind)
2476      {
2477        mask_1d(nbMaskInd) = tmp(ind);     
2478        ++nbMaskInd;
2479      }
2480    }   
2481  }
2482
2483  /*!
2484    Receive longitude event from clients(s)
2485    \param[in] event event contain info about rank and associated longitude
2486  */
2487  void CDomain::recvLon(CEventServer& event)
2488  {
2489    string domainId;
2490    std::map<int, CBufferIn*> rankBuffers;
2491
2492    list<CEventServer::SSubEvent>::iterator it;
2493    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2494    {     
2495      CBufferIn* buffer = it->buffer;
2496      *buffer >> domainId;
2497      rankBuffers[it->rank] = buffer;       
2498    }
2499    get(domainId)->recvLon(rankBuffers);
2500  }
2501
2502  /*!
2503    Receive longitude information from client(s)
2504    \param[in] rankBuffers rank of sending client and the corresponding receive buffer 
2505  */
2506  void CDomain::recvLon(std::map<int, CBufferIn*>& rankBuffers)
2507  {
2508    int nbReceived = rankBuffers.size(), i, ind, index, iindex, jindex;
2509    if (nbReceived != recvClientRanks_.size())
2510      ERROR("void CDomain::recvLon(std::map<int, CBufferIn*>& rankBuffers)",
2511           << "The number of sending clients is not correct."
2512           << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived);
2513
2514    vector<CArray<double,1> > recvLonValue(nbReceived);
2515    vector<CArray<double,2> > recvBoundsLonValue(nbReceived);   
2516    for (i = 0; i < recvClientRanks_.size(); ++i)
2517    {
2518      int rank = recvClientRanks_[i];
2519      CBufferIn& buffer = *(rankBuffers[rank]);
2520      buffer >> hasLonLat;
2521      buffer >> recvLonValue[i];
2522      buffer >> hasBounds;
2523      if (hasBounds)
2524        buffer >> recvBoundsLonValue[i];
2525    }
2526
2527    lonvalue.resize(zoom_ni*zoom_nj);
2528    lonvalue = 0;
2529
2530    if (hasBounds)
2531    {
2532      bounds_lonvalue.resize(nvertex,zoom_ni*zoom_nj);
2533      bounds_lonvalue = 0.;
2534    }
2535   
2536    for (i = 0; i < nbReceived; ++i)
2537    {
2538      int rank = recvClientRanks_[i];
2539      CArray<int,1> &indi = indGlob_[rank], &indj = indGlob_[rank];     
2540      for (ind = 0; ind < indi.numElements(); ++ind)
2541      {
2542         iindex = indi(ind) % ni_glo; jindex = indj(ind) / ni_glo;
2543         index = (iindex - zoom_ibegin) + (jindex - zoom_jbegin) * zoom_ni;
2544         lonvalue(index) = recvLonValue[i](ind);
2545         if (hasBounds)
2546         {         
2547          for (int nv = 0; nv < nvertex; ++nv)
2548            bounds_lonvalue(nv, index) = recvBoundsLonValue[i](nv, ind);
2549         }         
2550      }
2551    }
2552  }
2553
2554  /*!
2555    Receive latitude event from clients(s)
2556    \param[in] event event contain info about rank and associated latitude
2557  */
2558  void CDomain::recvLat(CEventServer& event)
2559  {
2560    string domainId;
2561    std::map<int, CBufferIn*> rankBuffers;
2562
2563    list<CEventServer::SSubEvent>::iterator it;
2564    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2565    {     
2566      CBufferIn* buffer = it->buffer;
2567      *buffer >> domainId;
2568      rankBuffers[it->rank] = buffer;   
2569    }
2570    get(domainId)->recvLat(rankBuffers);
2571  }
2572
2573  /*!
2574    Receive latitude information from client(s)
2575    \param[in] rankBuffers rank of sending client and the corresponding receive buffer 
2576  */
2577  void CDomain::recvLat(std::map<int, CBufferIn*>& rankBuffers)
2578  {
2579    int nbReceived = rankBuffers.size(), i, ind, index, iindex, jindex;
2580    if (nbReceived != recvClientRanks_.size())
2581      ERROR("void CDomain::recvLat(std::map<int, CBufferIn*>& rankBuffers)",
2582           << "The number of sending clients is not correct."
2583           << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived);
2584
2585    vector<CArray<double,1> > recvLatValue(nbReceived);
2586    vector<CArray<double,2> > recvBoundsLatValue(nbReceived);   
2587    for (i = 0; i < recvClientRanks_.size(); ++i)
2588    {
2589      int rank = recvClientRanks_[i];
2590      CBufferIn& buffer = *(rankBuffers[rank]);
2591      buffer >> hasLonLat;
2592      buffer >> recvLatValue[i];
2593      buffer >> hasBounds;
2594      if (hasBounds)
2595        buffer >> recvBoundsLatValue[i];
2596    }
2597
2598    latvalue.resize(zoom_ni*zoom_nj);
2599    latvalue = 0;
2600
2601    if (hasBounds)
2602    {
2603      bounds_latvalue.resize(nvertex,zoom_ni*zoom_nj);
2604      bounds_latvalue = 0. ;
2605    }
2606   
2607    for (i = 0; i < nbReceived; ++i)
2608    {
2609      int rank = recvClientRanks_[i];
2610      CArray<int,1> &indi = indGlob_[rank], &indj = indGlob_[rank];
2611      CArray<double,1>& lat = recvLatValue[i];
2612      for (ind = 0; ind < indi.numElements(); ++ind)
2613      {
2614         iindex = indi(ind) % ni_glo; jindex = indj(ind) / ni_glo;
2615         index = (iindex - zoom_ibegin) + (jindex - zoom_jbegin) * zoom_ni;
2616         latvalue(index) = lat(ind);
2617         if (hasBounds)
2618         {
2619          CArray<double,2>& boundslat = recvBoundsLatValue[i];
2620          for (int nv = 0; nv < nvertex; ++nv)
2621            bounds_latvalue(nv, index) = boundslat(nv, ind);
2622         }         
2623      }
2624    }
2625  }
2626
2627  /*!
2628    Receive area event from clients(s)
2629    \param[in] event event contain info about rank and associated area
2630  */
2631  void CDomain::recvArea(CEventServer& event)
2632  {
2633    string domainId;
2634    std::map<int, CBufferIn*> rankBuffers;
2635
2636    list<CEventServer::SSubEvent>::iterator it;
2637    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2638    {     
2639      CBufferIn* buffer = it->buffer;
2640      *buffer >> domainId;
2641      rankBuffers[it->rank] = buffer;     
2642    }
2643    get(domainId)->recvArea(rankBuffers);
2644  }
2645
2646
2647  /*!
2648    Receive area information from client(s)
2649    \param[in] rankBuffers rank of sending client and the corresponding receive buffer     
2650  */
2651  void CDomain::recvArea(std::map<int, CBufferIn*>& rankBuffers)
2652  {
2653    int nbReceived = rankBuffers.size(), i, ind, index;
2654    if (nbReceived != recvClientRanks_.size())
2655      ERROR("void CDomain::recvArea(std::map<int, CBufferIn*>& rankBuffers)",
2656           << "The number of sending clients is not correct."
2657           << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived);
2658
2659    vector<CArray<double,1> > recvAreaValue(nbReceived);     
2660    for (i = 0; i < recvClientRanks_.size(); ++i)
2661    {
2662      int rank = recvClientRanks_[i];
2663      CBufferIn& buffer = *(rankBuffers[rank]);     
2664      buffer >> hasArea;
2665      if (hasArea)
2666        buffer >> recvAreaValue[i];
2667    }
2668
2669    int nbAreaInd = 0;
2670    for (i = 0; i < nbReceived; ++i)
2671    {
2672      if (hasArea)
2673        nbAreaInd += recvAreaValue[i].numElements();
2674    }
2675 
2676    areavalue.resize(nbAreaInd);
2677    nbAreaInd = 0;
2678    if (hasArea)
2679    {
2680      for (i = 0; i < nbReceived; ++i)
2681      {
2682        CArray<double,1>& tmp = recvAreaValue[i];
2683        for (ind = 0; ind < tmp.numElements(); ++ind)
2684        {
2685          area(nbAreaInd) = tmp(ind);     
2686          ++nbAreaInd;
2687        }
2688      }
2689    }
2690  }
2691
2692  /*!
2693    Receive data index event from clients(s)
2694    \param[in] event event contain info about rank and associated index
2695  */
2696  void CDomain::recvDataIndex(CEventServer& event)
2697  {
2698    string domainId;
2699    std::map<int, CBufferIn*> rankBuffers;
2700
2701    list<CEventServer::SSubEvent>::iterator it;
2702    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2703    {     
2704      CBufferIn* buffer = it->buffer;
2705      *buffer >> domainId;
2706      rankBuffers[it->rank] = buffer;       
2707    }
2708    get(domainId)->recvDataIndex(rankBuffers);
2709
2710    // if (domain->isCompressible_)
2711    // {
2712    //   std::sort(domain->indexesToWrite.begin(), domain->indexesToWrite.end());
2713
2714    //   CContextServer* server = CContext::getCurrent()->server;
2715    //   domain->numberWrittenIndexes_ = domain->indexesToWrite.size();
2716    //   MPI_Allreduce(&domain->numberWrittenIndexes_, &domain->totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
2717    //   MPI_Scan(&domain->numberWrittenIndexes_, &domain->offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
2718    //   domain->offsetWrittenIndexes_ -= domain->numberWrittenIndexes_;
2719    // }
2720  }
2721
2722  /*!
2723    Receive data index information from client(s)
2724    A client receives data index from different clients to rebuild its own data index.
2725    Because the data index is local, to rebuild data index of received client, we should use global index along with.
2726    \param[in] rankBuffers rank of sending client and the corresponding receive buffer     
2727  */
2728  void CDomain::recvDataIndex(std::map<int, CBufferIn*>& rankBuffers)
2729  {
2730    int nbReceived = rankBuffers.size(), i, ind, index, indexI, type_int;   
2731    if (nbReceived != recvClientRanks_.size())
2732      ERROR("void CDomain::recvLat(std::map<int, CBufferIn*>& rankBuffers)",
2733           << "The number of sending clients is not correct."
2734           << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived);
2735
2736    vector<CArray<int,1> > recvDataIIndex(nbReceived),recvDataJIndex(nbReceived);     
2737    for (i = 0; i < recvClientRanks_.size(); ++i)
2738    {
2739      int rank = recvClientRanks_[i];
2740      CBufferIn& buffer = *(rankBuffers[rank]);
2741      buffer >> recvDataIIndex[i];
2742      buffer >> recvDataJIndex[i];
2743    }
2744   
2745    int nbCompressedData = 0; 
2746    for (i = 0; i < nbReceived; ++i)
2747    {
2748      CArray<int,1>& tmp = recvDataIIndex[i];
2749      for (ind = 0; ind < tmp.numElements(); ++ind)
2750      {
2751         index = tmp(ind);
2752         if (0 <= index)
2753           ++nbCompressedData;
2754      }       
2755    }
2756
2757    data_i_index.resize(nbCompressedData);
2758    data_j_index.resize(nbCompressedData);
2759
2760    nbCompressedData = 0;
2761    for (i = 0; i < nbReceived; ++i)
2762    {
2763      CArray<int,1>& tmpI = recvDataIIndex[i];     
2764      CArray<int,1>& tmpIndex = indGlob_[recvClientRanks_[i]];
2765      for (ind = 0; ind < tmpI.numElements(); ++ind)
2766      {
2767         indexI = tmpI(ind);
2768         index  = tmpIndex(ind);
2769         if (0 <= indexI)
2770         {
2771          data_i_index(nbCompressedData) = index % ni_glo - ibegin;
2772          data_j_index(nbCompressedData) = index / ni_glo - jbegin;
2773          ++nbCompressedData;
2774         }         
2775      } 
2776    }
2777  }
2778
2779  CTransformation<CDomain>* CDomain::addTransformation(ETranformationType transType, const StdString& id)
2780  {
2781    transformationMap_.push_back(std::make_pair(transType, CTransformation<CDomain>::createTransformation(transType,id)));
2782    return transformationMap_.back().second;
2783  }
2784
2785  /*!
2786    Check whether a domain has transformation
2787    \return true if domain has transformation
2788  */
2789  bool CDomain::hasTransformation()
2790  {
2791    return (!transformationMap_.empty());
2792  }
2793
2794  /*!
2795    Set transformation for current domain. It's the method to move transformation in hierarchy
2796    \param [in] domTrans transformation on domain
2797  */
2798  void CDomain::setTransformations(const TransMapTypes& domTrans)
2799  {
2800    transformationMap_ = domTrans;
2801  }
2802
2803  /*!
2804    Get all transformation current domain has
2805    \return all transformation
2806  */
2807  CDomain::TransMapTypes CDomain::getAllTransformations(void)
2808  {
2809    return transformationMap_;
2810  }
2811
2812  void CDomain::duplicateTransformation(CDomain* src)
2813  {
2814    if (src->hasTransformation())
2815    {
2816      this->setTransformations(src->getAllTransformations());
2817    }
2818  }
2819
2820  /*!
2821   * Go through the hierarchy to find the domain from which the transformations must be inherited
2822   */
2823  void CDomain::solveInheritanceTransformation()
2824  {
2825    if (hasTransformation() || !hasDirectDomainReference())
2826      return;
2827
2828    CDomain* domain = this;
2829    std::vector<CDomain*> refDomains;
2830    while (!domain->hasTransformation() && domain->hasDirectDomainReference())
2831    {
2832      refDomains.push_back(domain);
2833      domain = domain->getDirectDomainReference();
2834    }
2835
2836    if (domain->hasTransformation())
2837      for (size_t i = 0; i < refDomains.size(); ++i)
2838        refDomains[i]->setTransformations(domain->getAllTransformations());
2839  }
2840
2841  /*!
2842    Parse children nodes of a domain in xml file.
2843    Whenver there is a new transformation, its type and name should be added into this function
2844    \param node child node to process
2845  */
2846  void CDomain::parse(xml::CXMLNode & node)
2847  {
2848    SuperClass::parse(node);
2849
2850    if (node.goToChildElement())
2851    {
2852      StdString nodeElementName;
2853      do
2854      {
2855        StdString nodeId("");
2856        if (node.getAttributes().end() != node.getAttributes().find("id"))
2857        { nodeId = node.getAttributes()["id"]; }
2858
2859        nodeElementName = node.getElementName();
2860        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
2861        it = transformationMapList_.find(nodeElementName);
2862        if (ite != it)
2863        {
2864          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CDomain>::createTransformation(it->second,
2865                                                                                                                nodeId,
2866                                                                                                                &node)));
2867        }
2868        else
2869        {
2870          ERROR("void CDomain::parse(xml::CXMLNode & node)",
2871                << "The transformation " << nodeElementName << " has not been supported yet.");
2872        }
2873      } while (node.goToNextElement()) ;
2874      node.goToParentElement();
2875    }
2876  }
2877   //----------------------------------------------------------------
2878
2879   DEFINE_REF_FUNC(Domain,domain)
2880
2881   ///---------------------------------------------------------------
2882
2883} // namespace xios
Note: See TracBrowser for help on using the repository browser.