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

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

Add more attributes to generate_rectilinear_domain

+) Longitude and latitude of an auto-generated domain can be specified by its boundaries whose values are determined by range

Test
+) On Curie
+) test_remap passes

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