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

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

dev_omp

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