source: XIOS/dev/branch_yushan_merged/src/node/domain.cpp @ 1138

Last change on this file since 1138 was 1138, checked in by yushan, 7 years ago

test_remap back to work. No thread for now

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