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

Last change on this file since 1144 was 1144, checked in by mhnguyen, 7 years ago

Cleaning up some redundant codes

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