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

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

Merging working version of coupler

+) Add some changes of domain and axis: Retransfer the atttributes in a generic ways for each level of client (or server)
+) Remove some spoiled files from the previous commits

Test
+) No test

  • 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: 93.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    for (int i = 0; i < nbSrvPools; ++i)
1446    {
1447       CContextClient* contextClientTmp = (context->hasServer) ? context->clientPrimServer[i]
1448                                                                         : context->client;   
1449      int nbServer = contextClientTmp->serverSize;
1450    std::vector<int> nGlobDomain(2);
1451    nGlobDomain[0] = this->ni_glo;
1452    nGlobDomain[1] = this->nj_glo;
1453
1454    CServerDistributionDescription serverDescription(nGlobDomain, nbServer);
1455      if (isUnstructed_) serverDescription.computeServerDistribution(false, 0);
1456      else serverDescription.computeServerDistribution(false, 1);
1457
1458      std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
1459      std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
1460
1461      CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT);
1462      if (contextClientTmp->isServerLeader())
1463      {
1464        std::list<CMessage> msgs;
1465
1466        const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1467        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1468        {
1469          // Use const int to ensure CMessage holds a copy of the value instead of just a reference
1470          const int ibegin_srv = serverIndexBegin[*itRank][0];
1471          const int jbegin_srv = serverIndexBegin[*itRank][1];
1472          const int ni_srv = serverDimensionSizes[*itRank][0];
1473          const int nj_srv = serverDimensionSizes[*itRank][1];
1474
1475          msgs.push_back(CMessage());
1476          CMessage& msg = msgs.back();
1477          msg << this->getId() ;
1478        msg << ni_srv << ibegin_srv << nj_srv << jbegin_srv;       
1479          msg << isCompressible_;
1480
1481          event.push(*itRank,1,msg);
1482        }
1483        contextClientTmp->sendEvent(event);
1484      }
1485      else contextClientTmp->sendEvent(event);
1486    }
1487  }
1488
1489  // void CDomain::computeConnectedClients(const std::vector<int>& globalDim, int orderPositionInGrid,
1490  //                                     CServerDistributionDescription::ServerDistributionType distType)
1491  /*!
1492     Compute the connection of a client to other clients to determine which clients to send attributes to
1493  */
1494  void CDomain::computeConnectedClients()
1495  {
1496    CContext* context=CContext::getCurrent() ;
1497    CContextClient* client = (0 != context->clientPrimServer) ? context->clientPrimServer : context->client;
1498    int nbServer=client->serverSize;
1499    int rank = client->clientRank;
1500    bool doComputeGlobalIndexServer = true;
1501
1502    int i,j,i_ind,j_ind, nbIndex, nbIndexZoom;
1503    int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1 ;
1504    int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1 ;
1505
1506    // Precompute number of index
1507    int globalIndexCountZoom = 0;
1508    nbIndex = i_index.numElements();
1509    // for (i = 0; i < nbIndex; ++i)
1510    // {
1511    //   i_ind=i_index(i);
1512    //   j_ind=j_index(i);
1513
1514    //   if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1515    //   {
1516    //     ++globalIndexCountZoom;
1517    //   }
1518    // }
1519
1520    // int globalIndexWrittenCount = 0;
1521    // if (isCompressible_)
1522    // {
1523    //   for (i = 0; i < data_i_index.numElements(); ++i)
1524    //   {
1525    //     i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1526    //                                                 data_ibegin, data_jbegin, data_dim, ni,
1527    //                                                 j_ind);
1528    //     if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1529    //     {
1530    //       i_ind += ibegin;
1531    //       j_ind += jbegin;
1532    //       if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1533    //         ++globalIndexWrittenCount;
1534    //     }
1535    //   }
1536    // }
1537
1538    // Fill in index
1539   
1540    CArray<size_t,1> localIndexDomainZoom(globalIndexCountZoom);
1541    CArray<size_t,1> globalIndexDomain(nbIndex);
1542    size_t globalIndex;
1543    int globalIndexCount = 0;
1544   
1545
1546    for (i = 0; i < nbIndex; ++i)
1547    {
1548      i_ind=i_index(i);
1549      j_ind=j_index(i);
1550      globalIndex = i_ind + j_ind * ni_glo;
1551      globalIndexDomain(globalIndexCount) = globalIndex;
1552      globalLocalIndexMap_[globalIndex] = i;
1553      ++globalIndexCount;
1554    }
1555
1556    nbIndexZoom = zoom_i_index.numElements();
1557    CArray<size_t,1> globalIndexDomainZoom(nbIndexZoom);
1558    globalIndexCountZoom = 0;
1559    for (i = 0; i < nbIndexZoom; ++i)
1560    {
1561      i_ind=zoom_i_index(i);
1562      j_ind=zoom_j_index(i);
1563      globalIndex = i_ind + j_ind * ni_glo;
1564      globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
1565
1566      ++globalIndexCountZoom;
1567      // if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1568      // {
1569      //   globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
1570      //   localIndexDomainZoom(globalIndexCountZoom) = i;
1571      //   ++globalIndexCountZoom;
1572      // }
1573    }
1574
1575    // CArray<int,1> globalIndexWrittenDomain(globalIndexWrittenCount);
1576    // if (isCompressible_)
1577    // {
1578    //   globalIndexWrittenCount = 0;
1579    //   for (i = 0; i < data_i_index.numElements(); ++i)
1580    //   {
1581    //     i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1582    //                                                 data_ibegin, data_jbegin, data_dim, ni,
1583    //                                                 j_ind);
1584    //     if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1585    //     {
1586    //       i_ind += ibegin;
1587    //       j_ind += jbegin;
1588    //       if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1589    //       {
1590    //         globalIndexWrittenDomain(globalIndexWrittenCount) = i_ind + j_ind * ni_glo;
1591    //         ++globalIndexWrittenCount;
1592    //       }
1593    //     }
1594    //   }
1595    // }
1596
1597    size_t globalSizeIndex = 1, indexBegin, indexEnd;
1598    int range, clientSize = client->clientSize;
1599    std::vector<int> nGlobDomain(2);
1600    nGlobDomain[0] = this->ni_glo;
1601    nGlobDomain[1] = this->nj_glo;
1602    for (int i = 0; i < nGlobDomain.size(); ++i) globalSizeIndex *= nGlobDomain[i];
1603    indexBegin = 0;
1604    if (globalSizeIndex <= clientSize)
1605    {
1606      indexBegin = rank%globalSizeIndex;
1607      indexEnd = indexBegin;
1608    }
1609    else
1610    {
1611      for (int i = 0; i < clientSize; ++i)
1612      {
1613        range = globalSizeIndex / clientSize;
1614        if (i < (globalSizeIndex%clientSize)) ++range;
1615        if (i == client->clientRank) break;
1616        indexBegin += range;
1617      }
1618      indexEnd = indexBegin + range - 1;
1619    }
1620
1621    CServerDistributionDescription serverDescription(nGlobDomain, nbServer);
1622    if (isUnstructed_) serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t,size_t>(indexBegin, indexEnd), 0);
1623    else serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t,size_t>(indexBegin, indexEnd), 1);
1624
1625    CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(),
1626                                                                                client->intraComm);
1627    clientServerMap->computeServerIndexMapping(globalIndexDomain);
1628    CClientServerMapping::GlobalIndexMap& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer();
1629
1630    CClientServerMapping::GlobalIndexMap::const_iterator it  = globalIndexDomainOnServer.begin(),
1631                                                         ite = globalIndexDomainOnServer.end();
1632    // typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
1633    // std::vector<int>::iterator itVec;
1634   
1635    // indSrv_.clear();
1636    // indWrittenSrv_.clear();
1637    // for (; it != ite; ++it)
1638    // {
1639    //   int rank = it->first;
1640    //   int indexSize = it->second.size();
1641    //   std::vector<int> permutIndex(indexSize);
1642    //   XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
1643    //   XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(it->second, permutIndex);
1644    //   BinarySearch binSearch(it->second);
1645    //   int nb = globalIndexDomainZoom.numElements();
1646    //   for (int i = 0; i < nb; ++i)
1647    //   {
1648    //     if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexDomainZoom(i), itVec))
1649    //     {
1650    //       indSrv_[rank].push_back(localIndexDomainZoom(i));
1651    //     }
1652    //   }
1653    //   for (int i = 0; i < globalIndexWrittenDomain.numElements(); ++i)
1654    //   {
1655    //     if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexWrittenDomain(i), itVec))
1656    //     {
1657    //       indWrittenSrv_[rank].push_back(globalIndexWrittenDomain(i));
1658    //     }
1659    //   }
1660    // }
1661
1662    connectedServerRank_.clear();
1663    for (it = globalIndexDomainOnServer.begin(); it != ite; ++it) {
1664      connectedServerRank_.push_back(it->first);
1665    }
1666
1667    indSrv_.swap(globalIndexDomainOnServer);
1668    nbConnectedClients_ = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
1669
1670    clientServerMap->computeServerIndexMapping(globalIndexDomainZoom);
1671    CClientServerMapping::GlobalIndexMap& globalIndexDomainZoomOnServer = clientServerMap->getGlobalIndexOnServer();
1672    indZoomSrv_.swap(globalIndexDomainZoomOnServer);
1673    std::vector<int> connectedServerZoomRank(indZoomSrv_.size());
1674    for (it = indZoomSrv_.begin(); it != indZoomSrv_.end(); ++it)
1675      connectedServerZoomRank.push_back(it->first);
1676    nbConnectedClientsZoom_ = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerZoomRank);       
1677
1678    delete clientServerMap;
1679  }
1680
1681  const boost::unordered_map<int, vector<size_t> >& CDomain::getIndexServer() const
1682  {
1683    return indSrv_;
1684  }
1685
1686  /*!
1687    Send all attributes from client to connected clients
1688    The attributes will be rebuilt on receiving side
1689  */
1690  void CDomain::sendAttributes()
1691  {
1692    sendIndex();
1693    sendDistributionAttributes();
1694    sendMask();
1695    sendLonLat();
1696    sendArea();   
1697    sendDataIndex();
1698  }
1699
1700  /*!
1701    Send global index and zoom index from client to connected client(s)
1702    zoom index can be smaller than global index
1703  */
1704  void CDomain::sendIndex()
1705  {
1706    int ns, n, i, j, ind, nv, idx;
1707    CContext* context = CContext::getCurrent();
1708    CContextClient* client = (0 != context->clientPrimServer) ? context->clientPrimServer : context->client;
1709
1710    CEventClient eventIndex(getType(), EVENT_ID_INDEX);
1711
1712    list<CMessage> list_msgsIndex;
1713    list<CArray<int,1> > list_indZoom, list_writtenInd, list_indGlob;
1714
1715    boost::unordered_map<int, vector<size_t> >::const_iterator itIndex, iteIndex, itZoom, iteZoom;
1716    iteIndex = indSrv_.end(); iteZoom = indZoomSrv_.end();
1717    for (int k = 0; k < connectedServerRank_.size(); ++k)
1718    {
1719      int nbIndGlob = 0;
1720      int rank = connectedServerRank_[k];
1721      itIndex = indSrv_.find(rank);
1722      if (iteIndex != itIndex)
1723        nbIndGlob = itIndex->second.size();
1724      int nbIndZoom = 0;
1725      itZoom = indZoomSrv_.find(rank);
1726      if (iteZoom != itZoom)
1727        nbIndZoom = itZoom->second.size(); 
1728
1729      list_indGlob.push_back(CArray<int,1>(nbIndGlob));
1730      list_indZoom.push_back(CArray<int,1>(nbIndZoom));
1731
1732      CArray<int,1>& indZoom = list_indZoom.back();
1733      CArray<int,1>& indGlob = list_indGlob.back();     
1734      for (n = 0; n < nbIndGlob; ++n)
1735      {
1736        indGlob(n) = static_cast<int>(itIndex->second[n]);       
1737      }
1738
1739      for (n = 0; n < nbIndZoom; ++n)
1740      {
1741        indZoom(n) = static_cast<int>(itZoom->second[n]);       
1742      }
1743
1744      list_msgsIndex.push_back(CMessage());
1745      list_msgsIndex.back() << this->getId() << (int)type; // enum ne fonctionne pour les message => ToFix
1746      list_msgsIndex.back() << isCurvilinear;
1747      list_msgsIndex.back() << list_indGlob.back() << list_indZoom.back(); //list_indi.back() << list_indj.back();
1748
1749      // if (isCompressible_)
1750      // {
1751      //   std::vector<int>& writtenIndSrc = indWrittenSrv_[rank];
1752      //   list_writtenInd.push_back(CArray<int,1>(writtenIndSrc.size()));
1753      //   CArray<int,1>& writtenInd = list_writtenInd.back();
1754
1755      //   for (n = 0; n < writtenInd.numElements(); ++n)
1756      //     writtenInd(n) = writtenIndSrc[n];
1757
1758      //   list_msgsIndex.back() << writtenInd;
1759      // }
1760
1761      eventIndex.push(rank, nbConnectedClients_[rank], list_msgsIndex.back());
1762    }
1763
1764    client->sendEvent(eventIndex);
1765  }
1766
1767  /*!
1768    Send mask index from client to connected(s)
1769  */
1770  void CDomain::sendMask()
1771  {
1772    int ns, n, i, j, ind, nv, idx;
1773    CContext* context = CContext::getCurrent();
1774    CContextClient* client = (0 != context->clientPrimServer) ? context->clientPrimServer : context->client;
1775
1776    // send area for each connected server
1777    CEventClient eventMask(getType(), EVENT_ID_MASK);
1778
1779    list<CMessage> list_msgsMask;
1780    list<CArray<bool,1> > list_mask;
1781
1782    boost::unordered_map<int, vector<size_t> >::const_iterator it, iteMap;
1783    iteMap = indSrv_.end();
1784    for (int k = 0; k < connectedServerRank_.size(); ++k)
1785    {
1786      int nbData = 0;
1787      int rank = connectedServerRank_[k];
1788      it = indSrv_.find(rank);
1789      if (iteMap != it)
1790        nbData = it->second.size();
1791      list_mask.push_back(CArray<bool,1>(nbData));
1792
1793      const std::vector<size_t>& temp = it->second;
1794      for (n = 0; n < nbData; ++n)
1795      {
1796        idx = static_cast<int>(it->second[n]);
1797        list_mask.back()(n) = mask_1d(globalLocalIndexMap_[idx]);         
1798      }
1799
1800      list_msgsMask.push_back(CMessage());
1801      list_msgsMask.back() << this->getId() << list_mask.back();
1802      eventMask.push(rank, nbConnectedClients_[rank], list_msgsMask.back());
1803    }
1804    client->sendEvent(eventMask);
1805  }
1806
1807  /*!
1808    Send area from client to connected client(s)
1809  */
1810  void CDomain::sendArea()
1811  {
1812    if (!hasArea) return;
1813
1814    int ns, n, i, j, ind, nv, idx;
1815    CContext* context = CContext::getCurrent();
1816    CContextClient* client = (0 != context->clientPrimServer) ? context->clientPrimServer : context->client;
1817
1818    // send area for each connected server
1819    CEventClient eventArea(getType(), EVENT_ID_AREA);
1820
1821    list<CMessage> list_msgsArea;
1822    list<CArray<double,1> > list_area;
1823
1824    boost::unordered_map<int, vector<size_t> >::const_iterator it, iteMap;
1825    iteMap = indSrv_.end();
1826    for (int k = 0; k < connectedServerRank_.size(); ++k)
1827    {
1828      int nbData = 0;
1829      int rank = connectedServerRank_[k];
1830      it = indSrv_.find(rank);
1831      if (iteMap != it)
1832        nbData = it->second.size();
1833      list_area.push_back(CArray<double,1>(nbData));
1834
1835      const std::vector<size_t>& temp = it->second;
1836      for (n = 0; n < nbData; ++n)
1837      {
1838        idx = static_cast<int>(it->second[n]);
1839        list_area.back()(n) = areavalue(globalLocalIndexMap_[idx]); 
1840      }
1841
1842      list_msgsArea.push_back(CMessage());
1843      list_msgsArea.back() << this->getId() << hasArea;
1844      list_msgsArea.back() << list_area.back();
1845      eventArea.push(rank, nbConnectedClients_[rank], list_msgsArea.back());
1846    }
1847    client->sendEvent(eventArea);
1848  }
1849
1850  /*!
1851    Send longitude and latitude from client to servers
1852    Each client send long and lat information to corresponding connected server(s).
1853    Because longitude and latitude are optional, this function only called if latitude and longitude exist
1854  */
1855  void CDomain::sendLonLat()
1856  {
1857    if (!hasLonLat) return;
1858
1859    int ns, n, i, j, ind, nv, idx;
1860    CContext* context = CContext::getCurrent();
1861    CContextClient* client = (0 != context->clientPrimServer) ? context->clientPrimServer : context->client;
1862
1863    // send lon lat for each connected server
1864    CEventClient eventLon(getType(), EVENT_ID_LON);
1865    CEventClient eventLat(getType(), EVENT_ID_LAT);
1866
1867    list<CMessage> list_msgsLon, list_msgsLat;
1868    list<CArray<double,1> > list_lon, list_lat;
1869    list<CArray<double,2> > list_boundslon, list_boundslat;
1870
1871    boost::unordered_map<int, vector<size_t> >::const_iterator it, iteMap;
1872    iteMap = indSrv_.end();
1873    for (int k = 0; k < connectedServerRank_.size(); ++k)
1874    {
1875      int nbData = 0;
1876      int rank = connectedServerRank_[k];
1877      it = indSrv_.find(rank);
1878      if (iteMap != it)
1879        nbData = it->second.size();
1880
1881      list_lon.push_back(CArray<double,1>(nbData));
1882      list_lat.push_back(CArray<double,1>(nbData));
1883
1884      if (hasBounds)
1885      {
1886        list_boundslon.push_back(CArray<double,2>(nvertex, nbData));
1887        list_boundslat.push_back(CArray<double,2>(nvertex, nbData));
1888      }
1889
1890      CArray<double,1>& lon = list_lon.back();
1891      CArray<double,1>& lat = list_lat.back();
1892      const std::vector<size_t>& temp = it->second;
1893      for (n = 0; n < nbData; ++n)
1894      {
1895        idx = static_cast<int>(it->second[n]);
1896        int localInd = globalLocalIndexMap_[idx];
1897        lon(n) = lonvalue(localInd);
1898        lat(n) = latvalue(localInd);
1899
1900        if (hasBounds)
1901        {
1902          CArray<double,2>& boundslon = list_boundslon.back();
1903          CArray<double,2>& boundslat = list_boundslat.back();
1904
1905          for (nv = 0; nv < nvertex; ++nv)
1906          {
1907            boundslon(nv, n) = bounds_lonvalue(nv, localInd);
1908            boundslat(nv, n) = bounds_latvalue(nv, localInd);
1909          }
1910        }
1911      }
1912
1913      list_msgsLon.push_back(CMessage());
1914      list_msgsLat.push_back(CMessage());
1915
1916      list_msgsLon.back() << this->getId() << hasLonLat << list_lon.back() << hasBounds;
1917      list_msgsLat.back() << this->getId() << hasLonLat << list_lat.back() << hasBounds;
1918
1919      if (hasBounds)
1920      {
1921        list_msgsLon.back() << list_boundslon.back();
1922        list_msgsLat.back() << list_boundslat.back();
1923      }
1924
1925      eventLon.push(rank, nbConnectedClients_[rank], list_msgsLon.back());
1926      eventLat.push(rank, nbConnectedClients_[rank], list_msgsLat.back());
1927    }
1928
1929    client->sendEvent(eventLon);
1930    client->sendEvent(eventLat);
1931  }
1932
1933  /*!
1934    Send data index to corresponding connected clients.
1935    Data index can be compressed however, we always send decompressed data index
1936    and they will be compressed on receiving.
1937  */
1938  void CDomain::sendDataIndex()
1939  {
1940    int ns, n, i, j, ind, nv, idx;
1941    CContext* context = CContext::getCurrent();
1942    CContextClient* client = (0 != context->clientPrimServer) ? context->clientPrimServer : context->client;
1943
1944    // send area for each connected server
1945    CEventClient eventDataIndex(getType(), EVENT_ID_DATA_INDEX);
1946
1947    list<CMessage> list_msgsDataIndex;
1948    list<CArray<int,1> > list_data_i_index, list_data_j_index;
1949
1950    int nbIndex = i_index.numElements();
1951    CArray<int,1> dataIIndex(nbIndex), dataJIndex(nbIndex);
1952    dataIIndex = -1; dataJIndex = -1, ind = 0;
1953    for (idx = 0; idx < data_i_index.numElements(); ++idx)
1954    {
1955      if ((0 <= data_i_index(idx)) && (data_i_index(idx) < ni) && (ind < nbIndex))
1956      {
1957        dataIIndex(ind) = data_i_index(idx);
1958        dataJIndex(ind) = data_j_index(idx);
1959        ++ind;
1960      }
1961    }
1962
1963    boost::unordered_map<int, vector<size_t> >::const_iterator it, iteMap;
1964    iteMap = indSrv_.end();
1965    for (int k = 0; k < connectedServerRank_.size(); ++k)
1966    {
1967      int nbData = 0;
1968      int rank = connectedServerRank_[k];
1969      it = indSrv_.find(rank);
1970      if (iteMap != it)
1971        nbData = it->second.size();
1972      list_data_i_index.push_back(CArray<int,1>(nbData));
1973      list_data_j_index.push_back(CArray<int,1>(nbData));
1974
1975      const std::vector<size_t>& temp = it->second;
1976      for (n = 0; n < nbData; ++n)
1977      {
1978        idx = static_cast<int>(it->second[n]);
1979        i = globalLocalIndexMap_[idx];
1980        list_data_i_index.back()(n) = dataIIndex(i);
1981        list_data_j_index.back()(n) = dataJIndex(i);         
1982      }
1983
1984      list_msgsDataIndex.push_back(CMessage());
1985      list_msgsDataIndex.back() << this->getId();
1986      list_msgsDataIndex.back() << list_data_i_index.back() << list_data_j_index.back();
1987      eventDataIndex.push(rank, nbConnectedClients_[rank], list_msgsDataIndex.back());
1988    }
1989    client->sendEvent(eventDataIndex);
1990  }
1991 
1992  bool CDomain::dispatchEvent(CEventServer& event)
1993  {
1994    if (SuperClass::dispatchEvent(event)) return true;
1995    else
1996    {
1997      switch(event.type)
1998      {
1999        case EVENT_ID_SERVER_ATTRIBUT:
2000          recvDistributionAttributes(event);
2001          return true;
2002          break;
2003        case EVENT_ID_INDEX:
2004          recvIndex(event);
2005          return true;
2006          break;
2007        case EVENT_ID_MASK:
2008          recvMask(event);
2009          return true;
2010          break;
2011        case EVENT_ID_LON:
2012          recvLon(event);
2013          return true;
2014          break;
2015        case EVENT_ID_LAT:
2016          recvLat(event);
2017          return true;
2018          break;
2019        case EVENT_ID_AREA:
2020          recvArea(event);
2021          return true;
2022          break; 
2023        case EVENT_ID_DATA_INDEX:
2024          recvDataIndex(event);
2025          return true;
2026          break;
2027        default:
2028          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
2029                << "Unknown Event");
2030          return false;
2031       }
2032    }
2033  }
2034
2035  /*!
2036    Receive attributes event from clients(s)
2037    \param[in] event event contain info about rank and associated attributes
2038  */
2039  void CDomain::recvDistributionAttributes(CEventServer& event)
2040  {
2041    CBufferIn* buffer=event.subEvents.begin()->buffer;
2042    string domainId ;
2043    *buffer>>domainId ;
2044    get(domainId)->recvDistributionAttributes(*buffer) ;
2045  }
2046
2047  /*!
2048    Receive attributes from client(s): zoom info and begin and n of each server
2049    \param[in] rank rank of client source
2050    \param[in] buffer message containing attributes info
2051  */
2052  void CDomain::recvDistributionAttributes(CBufferIn& buffer)
2053  {
2054    int ni_tmp, ibegin_tmp, nj_tmp, jbegin_tmp;
2055    buffer >> ni_tmp >> ibegin_tmp >> nj_tmp >> jbegin_tmp           
2056           >> isCompressible_;
2057    ni.setValue(ni_tmp);
2058    ibegin.setValue(ibegin_tmp);
2059    nj.setValue(nj_tmp);
2060    jbegin.setValue(jbegin_tmp);
2061  }
2062
2063  /*!
2064    Receive index event from clients(s)
2065    \param[in] event event contain info about rank and associated index
2066  */
2067  void CDomain::recvIndex(CEventServer& event)
2068  {
2069    string domainId;
2070    std::map<int, CBufferIn*> rankBuffers;
2071
2072    list<CEventServer::SSubEvent>::iterator it;
2073    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2074    {     
2075      CBufferIn* buffer = it->buffer;
2076      *buffer >> domainId;
2077      rankBuffers[it->rank] = buffer;       
2078    }
2079    get(domainId)->recvIndex(rankBuffers);
2080
2081    // if (domain->isCompressible_)
2082    // {
2083    //   std::sort(domain->indexesToWrite.begin(), domain->indexesToWrite.end());
2084
2085    //   CContextServer* server = CContext::getCurrent()->server;
2086    //   domain->numberWrittenIndexes_ = domain->indexesToWrite.size();
2087    //   MPI_Allreduce(&domain->numberWrittenIndexes_, &domain->totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
2088    //   MPI_Scan(&domain->numberWrittenIndexes_, &domain->offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
2089    //   domain->offsetWrittenIndexes_ -= domain->numberWrittenIndexes_;
2090    // }
2091  }
2092
2093  /*!
2094    Receive index information from client(s)
2095    \param[in] rankBuffers rank of sending client and the corresponding receive buffer 
2096  */
2097  void CDomain::recvIndex(std::map<int, CBufferIn*>& rankBuffers)
2098  {
2099    int nbReceived = rankBuffers.size(), i, ind, index, type_int;
2100    recvClientRanks_.resize(nbReceived);
2101    vector<CArray<int,1> > recvZoomInd(nbReceived);
2102
2103    std::map<int, CBufferIn*>::iterator it = rankBuffers.begin(), ite = rankBuffers.end();
2104    ind = 0;
2105    for (ind = 0; it != ite; ++it, ++ind)
2106    {       
2107       recvClientRanks_[ind] = it->first;
2108       CBufferIn& buffer = *(it->second);
2109       buffer >> type_int >> isCurvilinear >> indGlob_[it->first] >> recvZoomInd[ind]; //recvIndGlob[ind];
2110       type.setValue((type_attr::t_enum)type_int); // probleme des type enum avec les buffers : ToFix
2111    }
2112    int nbIndGlob = 0;
2113    for (i = 0; i < nbReceived; ++i)
2114    {
2115      nbIndGlob += indGlob_[recvClientRanks_[i]].numElements();
2116    }
2117   
2118    i_index.resize(nbIndGlob);
2119    j_index.resize(nbIndGlob);
2120
2121    nbIndGlob = 0;
2122    for (i = 0; i < nbReceived; ++i)
2123    {
2124      CArray<int,1>& tmp = indGlob_[recvClientRanks_[i]];
2125      for (ind = 0; ind < tmp.numElements(); ++ind)
2126      {
2127         index = tmp(ind);
2128         i_index(nbIndGlob) = index / ni_glo;
2129         j_index(nbIndGlob) = index % ni_glo;
2130         ++nbIndGlob;
2131      } 
2132    }
2133
2134    int nbZoomInd = 0;
2135    for (i = 0; i < nbReceived; ++i)
2136    {
2137      nbZoomInd += recvZoomInd[i].numElements();
2138    }
2139
2140    zoom_i_index.resize(nbZoomInd);
2141    zoom_j_index.resize(nbZoomInd);
2142   
2143    nbZoomInd = 0;
2144    for (i = 0; i < nbReceived; ++i)
2145    {
2146      CArray<int,1>& tmp = recvZoomInd[i];
2147      for (ind = 0; ind < tmp.numElements(); ++ind)
2148      {
2149         index = tmp(ind);
2150         zoom_i_index(nbZoomInd) = index / ni_glo;
2151         zoom_j_index(nbZoomInd) = index % ni_glo;
2152         ++nbZoomInd;
2153      } 
2154    }   
2155
2156    {
2157      CContextServer* server = CContext::getCurrent()->server;
2158      count_write_index_.resize(2);
2159      start_write_index_.resize(2);
2160      local_write_size_.resize(2);
2161      global_write_size_.resize(2);
2162      if ((this->type) == CDomain::type_attr::unstructured)
2163      {
2164        count_write_index_[0] = zoom_i_index.numElements();
2165        count_write_index_[1] = 0;
2166      }
2167      else
2168      {
2169        int ni_zoom = zoom_i_index.numElements(), idx, nbIZoom = 0, nbJZoom = 0;
2170        for (idx =0; idx < ni_zoom; ++idx)
2171        {
2172           if ((ibegin <= zoom_i_index(idx)) && (zoom_i_index(idx) < ibegin+ni) && (nbIZoom < ni))
2173            ++nbIZoom;
2174           if ((jbegin <= zoom_j_index(idx)) && (zoom_j_index(idx) < jbegin+nj) && (nbJZoom < nj))
2175            ++nbJZoom;
2176        }
2177        count_write_index_[0] = nbIZoom;
2178        count_write_index_[1] = nbJZoom;
2179      }
2180           
2181      MPI_Scan(&count_write_index_[0], &start_write_index_[0], 2, MPI_INT, MPI_SUM, server->intraComm);     
2182      start_write_index_[0] = 0; 
2183      start_write_index_[1] -= count_write_index_[1];
2184      local_write_size_[0] = count_write_index_[0];
2185      local_write_size_[1] = count_write_index_[1];
2186      MPI_Allreduce(&count_write_index_[0], &global_write_size_[0], 2, MPI_INT, MPI_SUM, server->intraComm);
2187      global_write_size_[0] = count_write_index_[0];
2188      global_write_size_[1] = (global_write_size_[1] > nj_glo) ? nj_glo : global_write_size_[1];
2189         
2190    }
2191
2192    // int type_int;
2193    // buffer >> type_int >> isCurvilinear >> indiSrv[rank] >> indjSrv[rank];
2194    // type.setValue((type_attr::t_enum)type_int); // probleme des type enum avec les buffers : ToFix
2195
2196    // if (isCompressible_)
2197    // {
2198    //   CArray<int, 1> writtenIndexes;
2199    //   buffer >> writtenIndexes;
2200    //   indexesToWrite.reserve(indexesToWrite.size() + writtenIndexes.numElements());
2201    //   for (int i = 0; i < writtenIndexes.numElements(); ++i)
2202    //     indexesToWrite.push_back(writtenIndexes(i));
2203    // }
2204  }
2205
2206  /*!
2207    Receive area event from clients(s)
2208    \param[in] event event contain info about rank and associated area
2209  */
2210  void CDomain::recvMask(CEventServer& event)
2211  {
2212    string domainId;
2213    std::map<int, CBufferIn*> rankBuffers;
2214
2215    list<CEventServer::SSubEvent>::iterator it;
2216    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2217    {     
2218      CBufferIn* buffer = it->buffer;
2219      *buffer >> domainId;
2220      rankBuffers[it->rank] = buffer;     
2221    }
2222    get(domainId)->recvMask(rankBuffers);
2223  }
2224
2225
2226  /*!
2227    Receive mask information from client(s)
2228    \param[in] rankBuffers rank of sending client and the corresponding receive buffer 
2229  */
2230  void CDomain::recvMask(std::map<int, CBufferIn*>& rankBuffers)
2231  {
2232    int nbReceived = rankBuffers.size(), i, ind, index;
2233    if (nbReceived != recvClientRanks_.size())
2234      ERROR("void CDomain::recvArea(std::map<int, CBufferIn*>& rankBuffers)",
2235           << "The number of sending clients is not correct."
2236           << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived);
2237
2238    vector<CArray<bool,1> > recvMaskValue(nbReceived);     
2239    for (i = 0; i < recvClientRanks_.size(); ++i)
2240    {
2241      int rank = recvClientRanks_[i];
2242      CBufferIn& buffer = *(rankBuffers[rank]);     
2243      buffer >> recvMaskValue[i];
2244    }
2245
2246    int nbMaskInd = 0;
2247    for (i = 0; i < nbReceived; ++i)
2248    {
2249      nbMaskInd += recvMaskValue[i].numElements();
2250    }
2251 
2252    mask_1d.resize(nbMaskInd);
2253    nbMaskInd = 0;
2254    for (i = 0; i < nbReceived; ++i)
2255    {
2256      CArray<bool,1>& tmp = recvMaskValue[i];
2257      for (ind = 0; ind < tmp.numElements(); ++ind)
2258      {
2259        mask_1d(nbMaskInd) = tmp(ind);     
2260        ++nbMaskInd;
2261      }
2262    }   
2263  }
2264
2265  /*!
2266    Receive longitude event from clients(s)
2267    \param[in] event event contain info about rank and associated longitude
2268  */
2269  void CDomain::recvLon(CEventServer& event)
2270  {
2271    string domainId;
2272    std::map<int, CBufferIn*> rankBuffers;
2273
2274    list<CEventServer::SSubEvent>::iterator it;
2275    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2276    {     
2277      CBufferIn* buffer = it->buffer;
2278      *buffer >> domainId;
2279      rankBuffers[it->rank] = buffer;       
2280    }
2281    get(domainId)->recvLon(rankBuffers);
2282  }
2283
2284  /*!
2285    Receive longitude information from client(s)
2286    \param[in] rankBuffers rank of sending client and the corresponding receive buffer 
2287  */
2288  void CDomain::recvLon(std::map<int, CBufferIn*>& rankBuffers)
2289  {
2290    int nbReceived = rankBuffers.size(), i, ind, index;
2291    if (nbReceived != recvClientRanks_.size())
2292      ERROR("void CDomain::recvLon(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<double,1> > recvLonValue(nbReceived);
2297    vector<CArray<double,2> > recvBoundsLonValue(nbReceived);   
2298    for (i = 0; i < recvClientRanks_.size(); ++i)
2299    {
2300      int rank = recvClientRanks_[i];
2301      CBufferIn& buffer = *(rankBuffers[rank]);
2302      buffer >> hasLonLat;
2303      buffer >> recvLonValue[i];
2304      buffer >> hasBounds;
2305      if (hasBounds)
2306        buffer >> recvBoundsLonValue[i];
2307    }
2308
2309    int nbLonInd = 0;
2310    for (i = 0; i < nbReceived; ++i)
2311    {
2312      nbLonInd += recvLonValue[i].numElements();
2313    }
2314
2315    lonvalue.resize(nbLonInd);
2316    if (hasBounds)
2317    {
2318      bounds_lonvalue.resize(nvertex, nbLonInd);
2319    }
2320
2321    nbLonInd = 0;
2322    for (i = 0; i < nbReceived; ++i)
2323    {
2324      CArray<double,1>& tmp = recvLonValue[i];
2325      for (ind = 0; ind < tmp.numElements(); ++ind)
2326      {
2327         lonvalue(nbLonInd) = tmp(ind);
2328         if (hasBounds)
2329         {
2330          CArray<double,2>& tmpBnds = recvBoundsLonValue[i];
2331          for (int nv = 0; nv < nvertex; ++nv)
2332            bounds_lonvalue(nv, nbLonInd) = tmpBnds(nv, ind);
2333         }       
2334         ++nbLonInd;
2335      }
2336    }
2337  }
2338
2339  /*!
2340    Receive latitude event from clients(s)
2341    \param[in] event event contain info about rank and associated latitude
2342  */
2343  void CDomain::recvLat(CEventServer& event)
2344  {
2345    string domainId;
2346    std::map<int, CBufferIn*> rankBuffers;
2347
2348    list<CEventServer::SSubEvent>::iterator it;
2349    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2350    {     
2351      CBufferIn* buffer = it->buffer;
2352      *buffer >> domainId;
2353      rankBuffers[it->rank] = buffer;   
2354    }
2355    get(domainId)->recvLat(rankBuffers);
2356  }
2357
2358  /*!
2359    Receive latitude information from client(s)
2360    \param[in] rankBuffers rank of sending client and the corresponding receive buffer 
2361  */
2362  void CDomain::recvLat(std::map<int, CBufferIn*>& rankBuffers)
2363  {
2364    int nbReceived = rankBuffers.size(), i, ind, index;
2365    if (nbReceived != recvClientRanks_.size())
2366      ERROR("void CDomain::recvLat(std::map<int, CBufferIn*>& rankBuffers)",
2367           << "The number of sending clients is not correct."
2368           << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived);
2369
2370    vector<CArray<double,1> > recvLatValue(nbReceived);
2371    vector<CArray<double,2> > recvBoundsLatValue(nbReceived);   
2372    for (i = 0; i < recvClientRanks_.size(); ++i)
2373    {
2374      int rank = recvClientRanks_[i];
2375      CBufferIn& buffer = *(rankBuffers[rank]);
2376      buffer >> hasLonLat;
2377      buffer >> recvLatValue[i];
2378      buffer >> hasBounds;
2379      if (hasBounds)
2380        buffer >> recvBoundsLatValue[i];
2381    }
2382
2383    int nbLatInd = 0;
2384    for (i = 0; i < nbReceived; ++i)
2385    {
2386      nbLatInd += recvLatValue[i].numElements();
2387    }
2388
2389    latvalue.resize(nbLatInd);
2390    if (hasBounds)
2391    {
2392      bounds_latvalue.resize(nvertex, nbLatInd);
2393    }
2394   
2395    nbLatInd = 0;
2396    for (i = 0; i < nbReceived; ++i)
2397    {
2398      CArray<double,1>& tmp = recvLatValue[i];
2399      for (ind = 0; ind < tmp.numElements(); ++ind)
2400      {         
2401         latvalue(nbLatInd) = tmp(ind);
2402         if (hasBounds)
2403         {
2404          CArray<double,2>& tmpBnds = recvBoundsLatValue[i];
2405          for (int nv = 0; nv < nvertex; ++nv)
2406            bounds_latvalue(nv, nbLatInd) = tmpBnds(nv, ind);
2407         }       
2408         ++nbLatInd;
2409      }
2410    }
2411  }
2412
2413  /*!
2414    Receive area event from clients(s)
2415    \param[in] event event contain info about rank and associated area
2416  */
2417  void CDomain::recvArea(CEventServer& event)
2418  {
2419    string domainId;
2420    std::map<int, CBufferIn*> rankBuffers;
2421
2422    list<CEventServer::SSubEvent>::iterator it;
2423    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2424    {     
2425      CBufferIn* buffer = it->buffer;
2426      *buffer >> domainId;
2427      rankBuffers[it->rank] = buffer;     
2428    }
2429    get(domainId)->recvArea(rankBuffers);
2430  }
2431
2432
2433  /*!
2434    Receive area information from client(s)
2435    \param[in] rankBuffers rank of sending client and the corresponding receive buffer     
2436  */
2437  void CDomain::recvArea(std::map<int, CBufferIn*>& rankBuffers)
2438  {
2439    int nbReceived = rankBuffers.size(), i, ind, index;
2440    if (nbReceived != recvClientRanks_.size())
2441      ERROR("void CDomain::recvArea(std::map<int, CBufferIn*>& rankBuffers)",
2442           << "The number of sending clients is not correct."
2443           << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived);
2444
2445    vector<CArray<double,1> > recvAreaValue(nbReceived);     
2446    for (i = 0; i < recvClientRanks_.size(); ++i)
2447    {
2448      int rank = recvClientRanks_[i];
2449      CBufferIn& buffer = *(rankBuffers[rank]);     
2450      buffer >> hasArea;
2451      if (hasArea)
2452        buffer >> recvAreaValue[i];
2453    }
2454
2455    int nbAreaInd = 0;
2456    for (i = 0; i < nbReceived; ++i)
2457    {
2458      if (hasArea)
2459        nbAreaInd += recvAreaValue[i].numElements();
2460    }
2461 
2462    areavalue.resize(nbAreaInd);
2463    nbAreaInd = 0;
2464    if (hasArea)
2465    {
2466      for (i = 0; i < nbReceived; ++i)
2467      {
2468        CArray<double,1>& tmp = recvAreaValue[i];
2469        for (ind = 0; ind < tmp.numElements(); ++ind)
2470        {
2471          area(nbAreaInd) = tmp(ind);     
2472          ++nbAreaInd;
2473        }
2474      }
2475    }
2476  }
2477
2478  /*!
2479    Receive data index event from clients(s)
2480    \param[in] event event contain info about rank and associated index
2481  */
2482  void CDomain::recvDataIndex(CEventServer& event)
2483  {
2484    string domainId;
2485    std::map<int, CBufferIn*> rankBuffers;
2486
2487    list<CEventServer::SSubEvent>::iterator it;
2488    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2489    {     
2490      CBufferIn* buffer = it->buffer;
2491      *buffer >> domainId;
2492      rankBuffers[it->rank] = buffer;       
2493    }
2494    get(domainId)->recvDataIndex(rankBuffers);
2495
2496    // if (domain->isCompressible_)
2497    // {
2498    //   std::sort(domain->indexesToWrite.begin(), domain->indexesToWrite.end());
2499
2500    //   CContextServer* server = CContext::getCurrent()->server;
2501    //   domain->numberWrittenIndexes_ = domain->indexesToWrite.size();
2502    //   MPI_Allreduce(&domain->numberWrittenIndexes_, &domain->totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
2503    //   MPI_Scan(&domain->numberWrittenIndexes_, &domain->offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
2504    //   domain->offsetWrittenIndexes_ -= domain->numberWrittenIndexes_;
2505    // }
2506  }
2507
2508  /*!
2509    Receive data index information from client(s)
2510    A client receives data index from different clients to rebuild its own data index.
2511    Because the data index is local, to rebuild data index of received client, we should use global index along with.
2512    \param[in] rankBuffers rank of sending client and the corresponding receive buffer     
2513  */
2514  void CDomain::recvDataIndex(std::map<int, CBufferIn*>& rankBuffers)
2515  {
2516    int nbReceived = rankBuffers.size(), i, ind, index, indexI, type_int;   
2517    if (nbReceived != recvClientRanks_.size())
2518      ERROR("void CDomain::recvLat(std::map<int, CBufferIn*>& rankBuffers)",
2519           << "The number of sending clients is not correct."
2520           << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived);
2521
2522    vector<CArray<int,1> > recvDataIIndex(nbReceived),recvDataJIndex(nbReceived);     
2523    for (i = 0; i < recvClientRanks_.size(); ++i)
2524    {
2525      int rank = recvClientRanks_[i];
2526      CBufferIn& buffer = *(rankBuffers[rank]);
2527      buffer >> recvDataIIndex[i];
2528      buffer >> recvDataJIndex[i];
2529    }
2530   
2531    int nbCompressedData = 0; 
2532    for (i = 0; i < nbReceived; ++i)
2533    {
2534      CArray<int,1>& tmp = recvDataIIndex[i];
2535      for (ind = 0; ind < tmp.numElements(); ++ind)
2536      {
2537         index = tmp(ind);
2538         if (0 <= index)
2539           ++nbCompressedData;
2540      }       
2541    }
2542
2543    data_i_index.resize(nbCompressedData);
2544    data_j_index.resize(nbCompressedData);
2545
2546    nbCompressedData = 0;
2547    for (i = 0; i < nbReceived; ++i)
2548    {
2549      CArray<int,1>& tmpI = recvDataIIndex[i];     
2550      CArray<int,1>& tmpIndex = indGlob_[recvClientRanks_[i]];
2551      for (ind = 0; ind < tmpI.numElements(); ++ind)
2552      {
2553         indexI = tmpI(ind);
2554         index  = tmpIndex(ind);
2555         if (0 <= indexI)
2556         {
2557          data_i_index(nbCompressedData) = index % ni_glo - ibegin;
2558          data_j_index(nbCompressedData) = index / ni_glo - jbegin;
2559          ++nbCompressedData;
2560         }         
2561      } 
2562    }
2563  }
2564
2565  CTransformation<CDomain>* CDomain::addTransformation(ETranformationType transType, const StdString& id)
2566  {
2567    transformationMap_.push_back(std::make_pair(transType, CTransformation<CDomain>::createTransformation(transType,id)));
2568    return transformationMap_.back().second;
2569  }
2570
2571  /*!
2572    Check whether a domain has transformation
2573    \return true if domain has transformation
2574  */
2575  bool CDomain::hasTransformation()
2576  {
2577    return (!transformationMap_.empty());
2578  }
2579
2580  /*!
2581    Set transformation for current domain. It's the method to move transformation in hierarchy
2582    \param [in] domTrans transformation on domain
2583  */
2584  void CDomain::setTransformations(const TransMapTypes& domTrans)
2585  {
2586    transformationMap_ = domTrans;
2587  }
2588
2589  /*!
2590    Get all transformation current domain has
2591    \return all transformation
2592  */
2593  CDomain::TransMapTypes CDomain::getAllTransformations(void)
2594  {
2595    return transformationMap_;
2596  }
2597
2598  void CDomain::duplicateTransformation(CDomain* src)
2599  {
2600    if (src->hasTransformation())
2601    {
2602      this->setTransformations(src->getAllTransformations());
2603    }
2604  }
2605
2606  /*!
2607   * Go through the hierarchy to find the domain from which the transformations must be inherited
2608   */
2609  void CDomain::solveInheritanceTransformation()
2610  {
2611    if (hasTransformation() || !hasDirectDomainReference())
2612      return;
2613
2614    CDomain* domain = this;
2615    std::vector<CDomain*> refDomains;
2616    while (!domain->hasTransformation() && domain->hasDirectDomainReference())
2617    {
2618      refDomains.push_back(domain);
2619      domain = domain->getDirectDomainReference();
2620    }
2621
2622    if (domain->hasTransformation())
2623      for (size_t i = 0; i < refDomains.size(); ++i)
2624        refDomains[i]->setTransformations(domain->getAllTransformations());
2625  }
2626
2627  /*!
2628    Parse children nodes of a domain in xml file.
2629    Whenver there is a new transformation, its type and name should be added into this function
2630    \param node child node to process
2631  */
2632  void CDomain::parse(xml::CXMLNode & node)
2633  {
2634    SuperClass::parse(node);
2635
2636    if (node.goToChildElement())
2637    {
2638      StdString nodeElementName;
2639      do
2640      {
2641        StdString nodeId("");
2642        if (node.getAttributes().end() != node.getAttributes().find("id"))
2643        { nodeId = node.getAttributes()["id"]; }
2644
2645        nodeElementName = node.getElementName();
2646        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
2647        it = transformationMapList_.find(nodeElementName);
2648        if (ite != it)
2649        {
2650          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CDomain>::createTransformation(it->second,
2651                                                                                                                nodeId,
2652                                                                                                                &node)));
2653        }
2654        else
2655        {
2656          ERROR("void CDomain::parse(xml::CXMLNode & node)",
2657                << "The transformation " << nodeElementName << " has not been supported yet.");
2658        }
2659      } while (node.goToNextElement()) ;
2660      node.goToParentElement();
2661    }
2662  }
2663   //----------------------------------------------------------------
2664
2665   DEFINE_REF_FUNC(Domain,domain)
2666
2667   ///---------------------------------------------------------------
2668
2669} // namespace xios
Note: See TracBrowser for help on using the repository browser.