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

Last change on this file since 801 was 795, checked in by mhnguyen, 9 years ago

Fixng a minor bug

+) Remove function that shadows the one of ancestor class

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