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

Last change on this file since 691 was 691, checked in by mhnguyen, 6 years ago

Correcting minor bugs after merging

Test
+) On Curie
+) All tests pass

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