source: XIOS/dev/branch_openmp/src/node/domain.cpp @ 1338

Last change on this file since 1338 was 1334, checked in by yushan, 6 years ago

omp_dev

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