source: XIOS/trunk/src/node/domain.cpp @ 943

Last change on this file since 943 was 942, checked in by mhnguyen, 8 years ago

Modifying some checking conditions of domain to be loosen

+) Loosen the check with unstructured domain

Test
+) On Curie
+) Work

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