source: XIOS/branchs/xios-2.0/src/node/domain.cpp @ 1627

Last change on this file since 1627 was 1487, checked in by oabramkina, 6 years ago

Trunk: minor modifications for reading UGRID.

Using attribute nvertex defined by a user and not deduced from metadata of a file being read.
Taking into account the fact that the bounds attribute is not required by UGRID.

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