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

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

Adding a new transformation: Reduce a domain to an axis

Test
+) On Curie
+) Tests pass and are correct

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