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

Last change on this file since 1030 was 1030, checked in by oabramkina, 7 years ago

dev: intermediate commit.

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