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

Last change on this file since 1129 was 1129, checked in by mhnguyen, 3 years ago

Updating two-level server.
Each client now can play the role of server: It can forward data to other clients or write data like a server.
Each client must combine all data received from other client(s) before forward them or write them on files

+) Correct some bugs of exchange data_index in domain and axis
+) Reorder some functions in context.cpp to make sure that all necessary attributes are available before computing index
+) Add the mapping index for client to write data.

Test
+) On Curie
+) test_client and test_complete
+) Mode:

  • Only one level: Correct
  • Two levels: Work if using ddt (bug)

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