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

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

Temporary modification of auto-generate domain. This should be changed to a better solution

+) Divide a rectangular domain into parts being equal to number of procs

Test
+) On local with 2 procs, mode server and attached.
+) test_remap passes and result is correct

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