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

Last change on this file since 1262 was 1262, checked in by ymipsl, 7 years ago

backport of rev.1259 in trunk.

YM

  • 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.0 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     }
1373     else
1374     {
1375       hasBounds = false;
1376       nvertex = 0;
1377     }
1378   }
1379
1380   void CDomain::checkArea(void)
1381   {
1382     hasArea = !area.isEmpty();
1383     if (hasArea)
1384     {
1385       if (area.extent(0) != ni || area.extent(1) != nj)
1386       {
1387         ERROR("CDomain::checkArea(void)",
1388               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1389               << "The area does not have the same size as the local domain." << std::endl
1390               << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1391               << "Area size is " << area.extent(0) << " x " << area.extent(1) << ".");
1392       }
1393     }
1394   }
1395
1396   void CDomain::checkLonLat()
1397   {
1398     hasLonLat = (!latvalue_1d.isEmpty() && !lonvalue_1d.isEmpty()) ||
1399                 (!latvalue_2d.isEmpty() && !lonvalue_2d.isEmpty());
1400     if (hasLonLat)
1401     {
1402       if (!lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
1403         ERROR("CDomain::checkLonLat()",
1404               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1405               << "Only one longitude attribute can be used but both 'lonvalue_1d' and 'lonvalue_2d' are defined." << std::endl
1406               << "Define only one longitude attribute: 'lonvalue_1d' or 'lonvalue_2d'.");
1407
1408       if (!lonvalue_1d.isEmpty() && lonvalue_2d.isEmpty())
1409       {
1410         if ((type_attr::rectilinear != type) && (lonvalue_1d.numElements() != i_index.numElements()))
1411           ERROR("CDomain::checkLonLat()",
1412                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1413                 << "'lonvalue_1d' does not have the same size as the local domain." << std::endl
1414                 << "Local size is " << i_index.numElements() << "." << std::endl
1415                 << "'lonvalue_1d' size is " << lonvalue_1d.numElements() << ".");
1416       }
1417
1418       if (lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
1419       {
1420         if (lonvalue_2d.extent(0) != ni || lonvalue_2d.extent(1) != nj)
1421           ERROR("CDomain::checkLonLat()",
1422                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1423                 << "'lonvalue_2d' does not have the same size as the local domain." << std::endl
1424                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1425                 << "'lonvalue_2d' size is " << lonvalue_2d.extent(0) << " x " << lonvalue_2d.extent(1) << ".");
1426       }
1427
1428       if (!latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
1429         ERROR("CDomain::checkLonLat()",
1430               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1431               << "Only one latitude attribute can be used but both 'latvalue_1d' and 'latvalue_2d' are defined." << std::endl
1432               << "Define only one latitude attribute: 'latvalue_1d' or 'latvalue_2d'.");
1433
1434       if (!latvalue_1d.isEmpty() && latvalue_2d.isEmpty())
1435       {
1436         if ((type_attr::rectilinear != type) && (latvalue_1d.numElements() != i_index.numElements()))
1437           ERROR("CDomain::checkLonLat()",
1438                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1439                 << "'latvalue_1d' does not have the same size as the local domain." << std::endl
1440                 << "Local size is " << i_index.numElements() << "." << std::endl
1441                 << "'latvalue_1d' size is " << latvalue_1d.numElements() << ".");
1442       }
1443
1444       if (latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
1445       {
1446         if (latvalue_2d.extent(0) != ni || latvalue_2d.extent(1) != nj)
1447           ERROR("CDomain::checkLonLat()",
1448                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1449                 << "'latvalue_2d' does not have the same size as the local domain." << std::endl
1450                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1451                 << "'latvalue_2d' size is " << latvalue_2d.extent(0) << " x " << latvalue_2d.extent(1) << ".");
1452       }
1453     }
1454   }
1455
1456   void CDomain::checkAttributesOnClientAfterTransformation()
1457   {
1458     CContext* context=CContext::getCurrent() ;
1459
1460     if (this->isClientAfterTransformationChecked) return;
1461     if (context->hasClient)
1462     {
1463       this->checkMask();
1464       if (hasLonLat || hasArea || isCompressible_) this->computeConnectedServer();
1465       if (hasLonLat) this->completeLonLatClient();
1466     }
1467
1468     this->isClientAfterTransformationChecked = true;
1469   }
1470
1471   //----------------------------------------------------------------
1472   // Divide function checkAttributes into 2 seperate ones
1473   // This function only checks all attributes of current domain
1474   void CDomain::checkAttributesOnClient()
1475   {
1476     if (this->isClientChecked) return;
1477     CContext* context=CContext::getCurrent();
1478
1479      this->checkDomain();
1480      this->checkBounds();
1481      this->checkArea();
1482      this->checkLonLat();
1483
1484      if (context->hasClient)
1485      { // CÃŽté client uniquement
1486         this->checkMask();
1487         this->checkDomainData();
1488         this->checkCompression();
1489         this->computeLocalMask() ;
1490      }
1491      else
1492      { // CÃŽté serveur uniquement
1493      }
1494
1495      this->isClientChecked = true;
1496   }
1497
1498   // Send all checked attributes to server
1499   void CDomain::sendCheckedAttributes()
1500   {
1501     if (!this->isClientChecked) checkAttributesOnClient();
1502     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation();
1503     CContext* context=CContext::getCurrent() ;
1504
1505     if (this->isChecked) return;
1506     if (context->hasClient)
1507     {
1508       sendServerAttribut();
1509       if (hasLonLat || hasArea || isCompressible_) sendLonLatArea();
1510     }
1511     this->isChecked = true;
1512   }
1513
1514   void CDomain::checkAttributes(void)
1515   {
1516      if (this->isChecked) return;
1517      CContext* context=CContext::getCurrent() ;
1518
1519      this->checkDomain();
1520      this->checkLonLat();
1521      this->checkBounds();
1522      this->checkArea();
1523
1524      if (context->hasClient)
1525      { // CÃŽté client uniquement
1526         this->checkMask();
1527         this->checkDomainData();
1528         this->checkCompression();
1529         this->computeLocalMask() ;
1530
1531      }
1532      else
1533      { // CÃŽté serveur uniquement
1534      }
1535
1536      if (context->hasClient)
1537      {
1538        this->computeConnectedServer();
1539        this->completeLonLatClient();
1540        this->sendServerAttribut();
1541        this->sendLonLatArea();
1542      }
1543
1544      this->isChecked = true;
1545   }
1546
1547  void CDomain::sendServerAttribut(void)
1548  {
1549    CContext* context = CContext::getCurrent();
1550    CContextClient* client = context->client;
1551    int nbServer = client->serverSize;
1552
1553    CServerDistributionDescription serverDescription(getNbGlob(), nbServer);
1554    if (isUnstructed_) serverDescription.computeServerDistribution(false, 0);
1555    else serverDescription.computeServerDistribution(false, 1);
1556
1557    std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
1558    std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
1559
1560    CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT);
1561    if (client->isServerLeader())
1562    {
1563      std::list<CMessage> msgs;
1564
1565      const std::list<int>& ranks = client->getRanksServerLeader();
1566      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1567      {
1568        // Use const int to ensure CMessage holds a copy of the value instead of just a reference
1569        const int ibegin_srv = serverIndexBegin[*itRank][0];
1570        const int jbegin_srv = serverIndexBegin[*itRank][1];
1571        const int ni_srv = serverDimensionSizes[*itRank][0];
1572        const int nj_srv = serverDimensionSizes[*itRank][1];
1573        const int iend_srv = ibegin_srv + ni_srv - 1;
1574        const int jend_srv = jbegin_srv + nj_srv - 1;
1575
1576        msgs.push_back(CMessage());
1577        CMessage& msg = msgs.back();
1578        msg << this->getId() ;
1579        msg << ni_srv << ibegin_srv << iend_srv << nj_srv << jbegin_srv << jend_srv;
1580        msg << global_zoom_ni.getValue() << global_zoom_ibegin.getValue() << global_zoom_nj.getValue() << global_zoom_jbegin.getValue();
1581        msg << isCompressible_;
1582
1583        event.push(*itRank,1,msg);
1584      }
1585      client->sendEvent(event);
1586    }
1587    else client->sendEvent(event);
1588  }
1589
1590  std::vector<int> CDomain::getNbGlob()
1591  {
1592     std::vector<int> nbGlob(2);
1593     nbGlob[0] = ni_glo.getValue();
1594     nbGlob[1] = nj_glo.getValue();
1595
1596     return nbGlob;
1597  }
1598
1599  void CDomain::computeConnectedServer(void)
1600  {
1601    CContext* context=CContext::getCurrent() ;
1602    CContextClient* client=context->client ;
1603    int nbServer=client->serverSize;
1604    int rank = client->clientRank;
1605    bool doComputeGlobalIndexServer = true;
1606
1607    int i,j,i_ind,j_ind, nbIndex;
1608    int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1 ;
1609    int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1 ;
1610
1611    // Precompute number of index
1612    int globalIndexCountZoom = 0;
1613    nbIndex = i_index.numElements();
1614    for (i = 0; i < nbIndex; ++i)
1615    {
1616      i_ind=i_index(i);
1617      j_ind=j_index(i);
1618
1619      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1620      {
1621        ++globalIndexCountZoom;
1622      }
1623    }
1624
1625    int globalIndexWrittenCount = 0;
1626    if (isCompressible_)
1627    {
1628      for (i = 0; i < data_i_index.numElements(); ++i)
1629      {
1630        i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1631                                                    data_ibegin, data_jbegin, data_dim, ni,
1632                                                    j_ind);
1633        if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1634        {
1635          i_ind += ibegin;
1636          j_ind += jbegin;
1637          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1638            ++globalIndexWrittenCount;
1639        }
1640      }
1641    }
1642
1643    // Fill in index
1644    CArray<size_t,1> globalIndexDomainZoom(globalIndexCountZoom);
1645    CArray<size_t,1> localIndexDomainZoom(globalIndexCountZoom);
1646    CArray<size_t,1> globalIndexDomain(nbIndex);
1647    size_t globalIndex;
1648    int globalIndexCount = 0;
1649    globalIndexCountZoom = 0;
1650
1651    for (i = 0; i < nbIndex; ++i)
1652    {
1653      i_ind=i_index(i);
1654      j_ind=j_index(i);
1655      globalIndex = i_ind + j_ind * ni_glo;
1656      globalIndexDomain(globalIndexCount) = globalIndex;
1657      ++globalIndexCount;
1658      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1659      {
1660        globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
1661        localIndexDomainZoom(globalIndexCountZoom) = i;
1662        ++globalIndexCountZoom;
1663      }
1664    }
1665
1666    CArray<int,1> globalIndexWrittenDomain(globalIndexWrittenCount);
1667    if (isCompressible_)
1668    {
1669      globalIndexWrittenCount = 0;
1670      for (i = 0; i < data_i_index.numElements(); ++i)
1671      {
1672        i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1673                                                    data_ibegin, data_jbegin, data_dim, ni,
1674                                                    j_ind);
1675        if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1676        {
1677          i_ind += ibegin;
1678          j_ind += jbegin;
1679          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1680          {
1681            globalIndexWrittenDomain(globalIndexWrittenCount) = i_ind + j_ind * ni_glo;
1682            ++globalIndexWrittenCount;
1683          }
1684        }
1685      }
1686    }
1687
1688    size_t globalSizeIndex = 1, indexBegin, indexEnd;
1689    int range, clientSize = client->clientSize;
1690    for (int i = 0; i < getNbGlob().size(); ++i) globalSizeIndex *= getNbGlob()[i];
1691    indexBegin = 0;
1692    if (globalSizeIndex <= clientSize)
1693    {
1694      indexBegin = rank%globalSizeIndex;
1695      indexEnd = indexBegin;
1696    }
1697    else
1698    {
1699      for (int i = 0; i < clientSize; ++i)
1700      {
1701        range = globalSizeIndex / clientSize;
1702        if (i < (globalSizeIndex%clientSize)) ++range;
1703        if (i == client->clientRank) break;
1704        indexBegin += range;
1705      }
1706      indexEnd = indexBegin + range - 1;
1707    }
1708
1709    CServerDistributionDescription serverDescription(getNbGlob(), nbServer);
1710    if (isUnstructed_) serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t,size_t>(indexBegin, indexEnd), 0);
1711    else serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t,size_t>(indexBegin, indexEnd), 1);
1712
1713    CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(),
1714                                                                                client->intraComm);
1715    clientServerMap->computeServerIndexMapping(globalIndexDomain);
1716    const CClientServerMapping::GlobalIndexMap& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer();
1717
1718    CClientServerMapping::GlobalIndexMap::const_iterator it  = globalIndexDomainOnServer.begin(),
1719                                                         ite = globalIndexDomainOnServer.end();
1720    typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
1721    std::vector<int>::iterator itVec;
1722
1723    indSrv_.clear();
1724    indWrittenSrv_.clear();
1725    for (; it != ite; ++it)
1726    {
1727      int rank = it->first;
1728      int indexSize = it->second.size();
1729      std::vector<int> permutIndex(indexSize);
1730      XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
1731      XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(it->second, permutIndex);
1732      BinarySearch binSearch(it->second);
1733      int nb = globalIndexDomainZoom.numElements();
1734      for (int i = 0; i < nb; ++i)
1735      {
1736        if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexDomainZoom(i), itVec))
1737        {
1738          indSrv_[rank].push_back(localIndexDomainZoom(i));
1739        }
1740      }
1741      for (int i = 0; i < globalIndexWrittenDomain.numElements(); ++i)
1742      {
1743        if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexWrittenDomain(i), itVec))
1744        {
1745          indWrittenSrv_[rank].push_back(globalIndexWrittenDomain(i));
1746        }
1747      }
1748    }
1749
1750    connectedServerRank_.clear();
1751    for (it = globalIndexDomainOnServer.begin(); it != ite; ++it) {
1752      connectedServerRank_.push_back(it->first);
1753    }
1754
1755    nbConnectedClients_ = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
1756
1757    delete clientServerMap;
1758  }
1759
1760  const std::map<int, vector<size_t> >& CDomain::getIndexServer() const
1761  {
1762    return indSrv_;
1763  }
1764
1765  /*!
1766    Send index from client to server(s)
1767  */
1768  void CDomain::sendIndex()
1769  {
1770    int ns, n, i, j, ind, nv, idx;
1771    CContext* context = CContext::getCurrent();
1772    CContextClient* client=context->client;
1773
1774    CEventClient eventIndex(getType(), EVENT_ID_INDEX);
1775
1776    list<CMessage> list_msgsIndex;
1777    list<CArray<int,1> > list_indi, list_indj, list_writtenInd;
1778
1779    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1780    iteMap = indSrv_.end();
1781    for (int k = 0; k < connectedServerRank_.size(); ++k)
1782    {
1783      int nbData = 0;
1784      int rank = connectedServerRank_[k];
1785      it = indSrv_.find(rank);
1786      if (iteMap != it)
1787        nbData = it->second.size();
1788
1789      list_indi.push_back(CArray<int,1>(nbData));
1790      list_indj.push_back(CArray<int,1>(nbData));
1791
1792      CArray<int,1>& indi = list_indi.back();
1793      CArray<int,1>& indj = list_indj.back();
1794      const std::vector<size_t>& temp = it->second;
1795      for (n = 0; n < nbData; ++n)
1796      {
1797        idx = static_cast<int>(it->second[n]);
1798        indi(n) = i_index(idx);
1799        indj(n) = j_index(idx);
1800      }
1801
1802      list_msgsIndex.push_back(CMessage());
1803
1804      list_msgsIndex.back() << this->getId() << (int)type; // enum ne fonctionne pour les message => ToFix
1805      list_msgsIndex.back() << isCurvilinear;
1806      list_msgsIndex.back() << list_indi.back() << list_indj.back();
1807
1808      if (isCompressible_)
1809      {
1810        std::vector<int>& writtenIndSrc = indWrittenSrv_[rank];
1811        list_writtenInd.push_back(CArray<int,1>(writtenIndSrc.size()));
1812        CArray<int,1>& writtenInd = list_writtenInd.back();
1813
1814        for (n = 0; n < writtenInd.numElements(); ++n)
1815          writtenInd(n) = writtenIndSrc[n];
1816
1817        list_msgsIndex.back() << writtenInd;
1818      }
1819
1820      eventIndex.push(rank, nbConnectedClients_[rank], list_msgsIndex.back());
1821    }
1822
1823    client->sendEvent(eventIndex);
1824  }
1825
1826  /*!
1827    Send area from client to server(s)
1828  */
1829  void CDomain::sendArea()
1830  {
1831    if (!hasArea) return;
1832
1833    int ns, n, i, j, ind, nv, idx;
1834    CContext* context = CContext::getCurrent();
1835    CContextClient* client=context->client;
1836
1837    // send area for each connected server
1838    CEventClient eventArea(getType(), EVENT_ID_AREA);
1839
1840    list<CMessage> list_msgsArea;
1841    list<CArray<double,1> > list_area;
1842
1843    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1844    iteMap = indSrv_.end();
1845    for (int k = 0; k < connectedServerRank_.size(); ++k)
1846    {
1847      int nbData = 0;
1848      int rank = connectedServerRank_[k];
1849      it = indSrv_.find(rank);
1850      if (iteMap != it)
1851        nbData = it->second.size();
1852      list_area.push_back(CArray<double,1>(nbData));
1853
1854      const std::vector<size_t>& temp = it->second;
1855      for (n = 0; n < nbData; ++n)
1856      {
1857        idx = static_cast<int>(it->second[n]);
1858        i = i_index(idx);
1859        j = j_index(idx);
1860        if (hasArea)
1861          list_area.back()(n) = area(i - ibegin, j - jbegin);
1862      }
1863
1864      list_msgsArea.push_back(CMessage());
1865      list_msgsArea.back() << this->getId() << list_area.back();
1866      eventArea.push(rank, nbConnectedClients_[rank], list_msgsArea.back());
1867    }
1868    client->sendEvent(eventArea);
1869  }
1870
1871  /*!
1872    Send longitude and latitude from client to servers
1873    Each client send long and lat information to corresponding connected server(s).
1874    Because longitude and latitude are optional, this function only called if latitude and longitude exist
1875  */
1876  void CDomain::sendLonLat()
1877  {
1878    if (!hasLonLat) return;
1879
1880    int ns, n, i, j, ind, nv, idx;
1881    CContext* context = CContext::getCurrent();
1882    CContextClient* client=context->client;
1883
1884    // send lon lat for each connected server
1885    CEventClient eventLon(getType(), EVENT_ID_LON);
1886    CEventClient eventLat(getType(), EVENT_ID_LAT);
1887
1888    list<CMessage> list_msgsLon, list_msgsLat;
1889    list<CArray<double,1> > list_lon, list_lat;
1890    list<CArray<double,2> > list_boundslon, list_boundslat;
1891
1892    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1893    iteMap = indSrv_.end();
1894    for (int k = 0; k < connectedServerRank_.size(); ++k)
1895    {
1896      int nbData = 0;
1897      int rank = connectedServerRank_[k];
1898      it = indSrv_.find(rank);
1899      if (iteMap != it)
1900        nbData = it->second.size();
1901
1902      list_lon.push_back(CArray<double,1>(nbData));
1903      list_lat.push_back(CArray<double,1>(nbData));
1904
1905      if (hasBounds)
1906      {
1907        list_boundslon.push_back(CArray<double,2>(nvertex, nbData));
1908        list_boundslat.push_back(CArray<double,2>(nvertex, nbData));
1909      }
1910
1911      CArray<double,1>& lon = list_lon.back();
1912      CArray<double,1>& lat = list_lat.back();
1913      const std::vector<size_t>& temp = it->second;
1914      for (n = 0; n < nbData; ++n)
1915      {
1916        idx = static_cast<int>(it->second[n]);
1917        lon(n) = lonvalue_client(idx);
1918        lat(n) = latvalue_client(idx);
1919
1920        if (hasBounds)
1921        {
1922          CArray<double,2>& boundslon = list_boundslon.back();
1923          CArray<double,2>& boundslat = list_boundslat.back();
1924
1925          for (nv = 0; nv < nvertex; ++nv)
1926          {
1927            boundslon(nv, n) = bounds_lon_client(nv, idx);
1928            boundslat(nv, n) = bounds_lat_client(nv, idx);
1929          }
1930        }
1931      }
1932
1933      list_msgsLon.push_back(CMessage());
1934      list_msgsLat.push_back(CMessage());
1935
1936      list_msgsLon.back() << this->getId() << list_lon.back();
1937      list_msgsLat.back() << this->getId() << list_lat.back();
1938
1939      if (hasBounds)
1940      {
1941        list_msgsLon.back() << list_boundslon.back();
1942        list_msgsLat.back() << list_boundslat.back();
1943      }
1944
1945      eventLon.push(rank, nbConnectedClients_[rank], list_msgsLon.back());
1946      eventLat.push(rank, nbConnectedClients_[rank], list_msgsLat.back());
1947    }
1948
1949    client->sendEvent(eventLon);
1950    client->sendEvent(eventLat);
1951  }
1952
1953  /*!
1954    Send some optional information to server(s)
1955    In the future, this function can be extended with more optional information to send
1956  */
1957  void CDomain::sendLonLatArea(void)
1958  {
1959    sendIndex();
1960    sendLonLat();
1961    sendArea();
1962  }
1963
1964  bool CDomain::dispatchEvent(CEventServer& event)
1965  {
1966    if (SuperClass::dispatchEvent(event)) return true;
1967    else
1968    {
1969      switch(event.type)
1970      {
1971        case EVENT_ID_SERVER_ATTRIBUT:
1972          recvServerAttribut(event);
1973          return true;
1974          break;
1975        case EVENT_ID_INDEX:
1976          recvIndex(event);
1977          return true;
1978          break;
1979        case EVENT_ID_LON:
1980          recvLon(event);
1981          return true;
1982          break;
1983        case EVENT_ID_LAT:
1984          recvLat(event);
1985          return true;
1986          break;
1987        case EVENT_ID_AREA:
1988          recvArea(event);
1989          return true;
1990          break;
1991        default:
1992          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1993                << "Unknown Event");
1994          return false;
1995       }
1996    }
1997  }
1998
1999  /*!
2000    Receive attributes event from clients(s)
2001    \param[in] event event contain info about rank and associated attributes
2002  */
2003  void CDomain::recvServerAttribut(CEventServer& event)
2004  {
2005    CBufferIn* buffer=event.subEvents.begin()->buffer;
2006    string domainId ;
2007    *buffer>>domainId ;
2008    get(domainId)->recvServerAttribut(*buffer) ;
2009  }
2010
2011  /*!
2012    Receive attributes from client(s): zoom info and begin and n of each server
2013    \param[in] rank rank of client source
2014    \param[in] buffer message containing attributes info
2015  */
2016  void CDomain::recvServerAttribut(CBufferIn& buffer)
2017  {
2018    int global_zoom_ni_tmp, global_zoom_ibegin_tmp, global_zoom_nj_tmp, global_zoom_jbegin_tmp;
2019    buffer >> ni_srv >> ibegin_srv >> iend_srv >> nj_srv >> jbegin_srv >> jend_srv
2020           >> global_zoom_ni_tmp >> global_zoom_ibegin_tmp >> global_zoom_nj_tmp >> global_zoom_jbegin_tmp
2021           >> isCompressible_;
2022
2023    global_zoom_ni.setValue(global_zoom_ni_tmp);
2024    global_zoom_ibegin.setValue(global_zoom_ibegin_tmp);
2025    global_zoom_nj.setValue(global_zoom_nj_tmp);
2026    global_zoom_jbegin.setValue(global_zoom_jbegin_tmp);
2027
2028    int zoom_iend = global_zoom_ibegin + global_zoom_ni - 1;
2029    int zoom_jend = global_zoom_jbegin + global_zoom_nj - 1;
2030
2031    zoom_ibegin_srv = global_zoom_ibegin > ibegin_srv ? global_zoom_ibegin : ibegin_srv ;
2032    zoom_iend_srv = zoom_iend < iend_srv ? zoom_iend : iend_srv ;
2033    zoom_ni_srv=zoom_iend_srv-zoom_ibegin_srv+1 ;
2034
2035    zoom_jbegin_srv = global_zoom_jbegin > jbegin_srv ? global_zoom_jbegin : jbegin_srv ;
2036    zoom_jend_srv = zoom_jend < jend_srv ? zoom_jend : jend_srv ;
2037    zoom_nj_srv=zoom_jend_srv-zoom_jbegin_srv+1 ;
2038
2039    if (zoom_ni_srv<=0 || zoom_nj_srv<=0)
2040    {
2041      zoom_ibegin_srv=0 ; zoom_iend_srv=0 ; zoom_ni_srv=0 ;
2042      zoom_jbegin_srv=0 ; zoom_jend_srv=0 ; zoom_nj_srv=0 ;
2043    }
2044    lonvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
2045    lonvalue_srv = 0. ;
2046    latvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
2047    latvalue_srv = 0. ;
2048    if (hasBounds)
2049    {
2050      bounds_lon_srv.resize(nvertex,zoom_ni_srv*zoom_nj_srv) ;
2051      bounds_lon_srv = 0. ;
2052      bounds_lat_srv.resize(nvertex,zoom_ni_srv*zoom_nj_srv) ;
2053      bounds_lat_srv = 0. ;
2054    }
2055
2056    if (hasArea)
2057    {
2058      area_srv.resize(zoom_ni_srv * zoom_nj_srv);
2059      area_srv = 0.;
2060    }
2061
2062  }
2063
2064  /*!
2065    Receive index event from clients(s)
2066    \param[in] event event contain info about rank and associated index
2067  */
2068  void CDomain::recvIndex(CEventServer& event)
2069  {
2070    CDomain* domain;
2071
2072    list<CEventServer::SSubEvent>::iterator it;
2073    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2074    {
2075      CBufferIn* buffer = it->buffer;
2076      string domainId;
2077      *buffer >> domainId;
2078      domain = get(domainId);
2079      domain->recvIndex(it->rank, *buffer);
2080    }
2081
2082    if (domain->isCompressible_)
2083    {
2084      std::sort(domain->indexesToWrite.begin(), domain->indexesToWrite.end());
2085
2086      CContextServer* server = CContext::getCurrent()->server;
2087      domain->numberWrittenIndexes_ = domain->indexesToWrite.size();
2088      MPI_Allreduce(&domain->numberWrittenIndexes_, &domain->totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
2089      MPI_Scan(&domain->numberWrittenIndexes_, &domain->offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
2090      domain->offsetWrittenIndexes_ -= domain->numberWrittenIndexes_;
2091    }
2092  }
2093
2094  /*!
2095    Receive index information from client(s)
2096    \param[in] rank rank of client source
2097    \param[in] buffer message containing index info
2098  */
2099  void CDomain::recvIndex(int rank, CBufferIn& buffer)
2100  {
2101    int type_int;
2102    buffer >> type_int >> isCurvilinear >> indiSrv[rank] >> indjSrv[rank];
2103    type.setValue((type_attr::t_enum)type_int); // probleme des type enum avec les buffers : ToFix
2104
2105    if (isCompressible_)
2106    {
2107      CArray<int, 1> writtenIndexes;
2108      buffer >> writtenIndexes;
2109      indexesToWrite.reserve(indexesToWrite.size() + writtenIndexes.numElements());
2110      for (int i = 0; i < writtenIndexes.numElements(); ++i)
2111        indexesToWrite.push_back(writtenIndexes(i));
2112    }
2113  }
2114
2115  /*!
2116    Receive longitude event from clients(s)
2117    \param[in] event event contain info about rank and associated longitude
2118  */
2119  void CDomain::recvLon(CEventServer& event)
2120  {
2121    list<CEventServer::SSubEvent>::iterator it;
2122    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2123    {
2124      CBufferIn* buffer = it->buffer;
2125      string domainId;
2126      *buffer >> domainId;
2127      get(domainId)->recvLon(it->rank, *buffer);
2128    }
2129  }
2130
2131  /*!
2132    Receive longitude information from client(s)
2133    \param[in] rank rank of client source
2134    \param[in] buffer message containing longitude info
2135  */
2136  void CDomain::recvLon(int rank, CBufferIn& buffer)
2137  {
2138    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
2139    CArray<double,1> lon;
2140    CArray<double,2> boundslon;
2141
2142    buffer >> lon;
2143
2144    if (hasBounds) buffer >> boundslon;
2145
2146    int i, j, ind_srv;
2147    for (int ind = 0; ind < indi.numElements(); ind++)
2148    {
2149      i = indi(ind); j = indj(ind);
2150      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
2151      lonvalue_srv(ind_srv) = lon(ind);
2152      if (hasBounds)
2153      {
2154        for (int nv = 0; nv < nvertex; ++nv)
2155          bounds_lon_srv(nv, ind_srv) = boundslon(nv, ind);
2156      }
2157    }
2158  }
2159
2160  /*!
2161    Receive latitude event from clients(s)
2162    \param[in] event event contain info about rank and associated latitude
2163  */
2164  void CDomain::recvLat(CEventServer& event)
2165  {
2166    list<CEventServer::SSubEvent>::iterator it;
2167    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2168    {
2169      CBufferIn* buffer = it->buffer;
2170      string domainId;
2171      *buffer >> domainId;
2172      get(domainId)->recvLat(it->rank, *buffer);
2173    }
2174  }
2175
2176  /*!
2177    Receive latitude information from client(s)
2178    \param[in] rank rank of client source
2179    \param[in] buffer message containing latitude info
2180  */
2181  void CDomain::recvLat(int rank, CBufferIn& buffer)
2182  {
2183    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
2184    CArray<double,1> lat;
2185    CArray<double,2> boundslat;
2186
2187    buffer >> lat;
2188    if (hasBounds) buffer >> boundslat;
2189
2190    int i, j, ind_srv;
2191    for (int ind = 0; ind < indi.numElements(); ind++)
2192    {
2193      i = indi(ind); j = indj(ind);
2194      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
2195      latvalue_srv(ind_srv) = lat(ind);
2196      if (hasBounds)
2197      {
2198        for (int nv = 0; nv < nvertex; nv++)
2199          bounds_lat_srv(nv, ind_srv) = boundslat(nv, ind);
2200      }
2201    }
2202  }
2203
2204  /*!
2205    Receive area event from clients(s)
2206    \param[in] event event contain info about rank and associated area
2207  */
2208  void CDomain::recvArea(CEventServer& event)
2209  {
2210    list<CEventServer::SSubEvent>::iterator it;
2211    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
2212    {
2213      CBufferIn* buffer = it->buffer;
2214      string domainId;
2215      *buffer >> domainId;
2216      get(domainId)->recvArea(it->rank, *buffer);
2217    }
2218  }
2219
2220  /*!
2221    Receive area information from client(s)
2222    \param[in] rank rank of client source
2223    \param[in] buffer message containing area info
2224  */
2225  void CDomain::recvArea(int rank, CBufferIn& buffer)
2226  {
2227    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
2228    CArray<double,1> clientArea;
2229
2230    buffer >> clientArea;
2231
2232    int i, j, ind_srv;
2233    for (int ind = 0; ind < indi.numElements(); ind++)
2234    {
2235      i = indi(ind); j = indj(ind);
2236      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
2237      area_srv(ind_srv) = clientArea(ind);
2238    }
2239  }
2240
2241  /*!
2242    Compare two domain objects.
2243    They are equal if only if they have identical attributes as well as their values.
2244    Moreover, they must have the same transformations.
2245  \param [in] domain Compared domain
2246  \return result of the comparison
2247  */
2248  bool CDomain::isEqual(CDomain* obj)
2249  {
2250    vector<StdString> excludedAttr;
2251    excludedAttr.push_back("domain_ref");
2252    bool objEqual = SuperClass::isEqual(obj, excludedAttr);
2253    if (!objEqual) return objEqual;
2254
2255    TransMapTypes thisTrans = this->getAllTransformations();
2256    TransMapTypes objTrans  = obj->getAllTransformations();
2257
2258    TransMapTypes::const_iterator it, itb, ite;
2259    std::vector<ETranformationType> thisTransType, objTransType;
2260    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
2261      thisTransType.push_back(it->first);
2262    for (it = objTrans.begin(); it != objTrans.end(); ++it)
2263      objTransType.push_back(it->first);
2264
2265    if (thisTransType.size() != objTransType.size()) return false;
2266    for (int idx = 0; idx < thisTransType.size(); ++idx)
2267      objEqual &= (thisTransType[idx] == objTransType[idx]);
2268
2269    return objEqual;
2270  }
2271
2272  CTransformation<CDomain>* CDomain::addTransformation(ETranformationType transType, const StdString& id)
2273  {
2274    transformationMap_.push_back(std::make_pair(transType, CTransformation<CDomain>::createTransformation(transType,id)));
2275    return transformationMap_.back().second;
2276  }
2277
2278  /*!
2279    Check whether a domain has transformation
2280    \return true if domain has transformation
2281  */
2282  bool CDomain::hasTransformation()
2283  {
2284    return (!transformationMap_.empty());
2285  }
2286
2287  /*!
2288    Set transformation for current domain. It's the method to move transformation in hierarchy
2289    \param [in] domTrans transformation on domain
2290  */
2291  void CDomain::setTransformations(const TransMapTypes& domTrans)
2292  {
2293    transformationMap_ = domTrans;
2294  }
2295
2296  /*!
2297    Get all transformation current domain has
2298    \return all transformation
2299  */
2300  CDomain::TransMapTypes CDomain::getAllTransformations(void)
2301  {
2302    return transformationMap_;
2303  }
2304
2305  void CDomain::duplicateTransformation(CDomain* src)
2306  {
2307    if (src->hasTransformation())
2308    {
2309      this->setTransformations(src->getAllTransformations());
2310    }
2311  }
2312
2313  /*!
2314   * Go through the hierarchy to find the domain from which the transformations must be inherited
2315   */
2316  void CDomain::solveInheritanceTransformation()
2317  {
2318    if (hasTransformation() || !hasDirectDomainReference())
2319      return;
2320
2321    CDomain* domain = this;
2322    std::vector<CDomain*> refDomains;
2323    while (!domain->hasTransformation() && domain->hasDirectDomainReference())
2324    {
2325      refDomains.push_back(domain);
2326      domain = domain->getDirectDomainReference();
2327    }
2328
2329    if (domain->hasTransformation())
2330      for (size_t i = 0; i < refDomains.size(); ++i)
2331        refDomains[i]->setTransformations(domain->getAllTransformations());
2332  }
2333
2334  /*!
2335    Parse children nodes of a domain in xml file.
2336    Whenver there is a new transformation, its type and name should be added into this function
2337    \param node child node to process
2338  */
2339  void CDomain::parse(xml::CXMLNode & node)
2340  {
2341    SuperClass::parse(node);
2342
2343    if (node.goToChildElement())
2344    {
2345      StdString nodeElementName;
2346      do
2347      {
2348        StdString nodeId("");
2349        if (node.getAttributes().end() != node.getAttributes().find("id"))
2350        { nodeId = node.getAttributes()["id"]; }
2351
2352        nodeElementName = node.getElementName();
2353        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
2354        it = transformationMapList_.find(nodeElementName);
2355        if (ite != it)
2356        {
2357          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CDomain>::createTransformation(it->second,
2358                                                                                                                nodeId,
2359                                                                                                                &node)));
2360        }
2361        else
2362        {
2363          ERROR("void CDomain::parse(xml::CXMLNode & node)",
2364                << "The transformation " << nodeElementName << " has not been supported yet.");
2365        }
2366      } while (node.goToNextElement()) ;
2367      node.goToParentElement();
2368    }
2369  }
2370   //----------------------------------------------------------------
2371
2372   DEFINE_REF_FUNC(Domain,domain)
2373
2374   ///---------------------------------------------------------------
2375
2376} // namespace xios
Note: See TracBrowser for help on using the repository browser.