Ticket #95: domain_patch.cpp

File domain_patch.cpp, 72.0 KB (added by ssenesi, 8 years ago)

Modified,proposed, domain.cpp

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