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

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

First implementation of hierarchical distributed hashed table

+) Implement dht for int with index of type size_t

Test
+) Local
+) Work correctly

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