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

Last change on this file since 762 was 762, checked in by rlacroix, 9 years ago

Domain: Fix some error messages to reference the correct function.

  • 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: 66.2 KB
Line 
1#include "domain.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6
7#include "xios_spl.hpp"
8#include "event_client.hpp"
9#include "event_server.hpp"
10#include "buffer_in.hpp"
11#include "message.hpp"
12#include "type.hpp"
13#include "context.hpp"
14#include "context_client.hpp"
15#include "context_server.hpp"
16#include "array_new.hpp"
17#include "distribution_client.hpp"
18#include "server_distribution_description.hpp"
19#include "client_server_mapping_distributed.hpp"
20#include "zoom_domain.hpp"
21#include "interpolate_domain.hpp"
22#include "generate_rectilinear_domain.hpp"
23
24#include <algorithm>
25
26namespace xios {
27
28   /// ////////////////////// Définitions ////////////////////// ///
29
30   CDomain::CDomain(void)
31      : CObjectTemplate<CDomain>(), CDomainAttributes()
32      , isChecked(false), relFiles(), isClientChecked(false), nbConnectedClients_(), indSrv_(), connectedServerRank_()
33      , hasBounds(false), hasArea(false), isDistributed_(false), nGlobDomain_(), isCompressible_(false), isUnstructed_(false)
34      , global_zoom_ni(0), global_zoom_ibegin(0), global_zoom_nj(0), global_zoom_jbegin(0)
35      , isClientAfterTransformationChecked(false), hasLonLat(false)
36      , lonvalue_client(), latvalue_client(), bounds_lon_client(), bounds_lat_client()
37      , srcObject_(0), isRedistributed_(false)
38   { /* Ne rien faire de plus */ }
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), nGlobDomain_(), isCompressible_(false), isUnstructed_(false)
44      , global_zoom_ni(0), global_zoom_ibegin(0), global_zoom_nj(0), global_zoom_jbegin(0)
45      , isClientAfterTransformationChecked(false), hasLonLat(false)
46      , lonvalue_client(), latvalue_client(), bounds_lon_client(), bounds_lat_client()
47      , srcObject_(0), isRedistributed_(false)
48   { /* Ne rien faire de plus */ }
49
50   CDomain::~CDomain(void)
51   {
52   }
53
54   ///---------------------------------------------------------------
55
56   CDomain* CDomain::createDomain()
57   {
58     CDomain* domain = CDomainGroup::get("domain_definition")->createChild();
59     return domain;
60   }
61
62   void CDomain::duplicateAttributes(CDomain* domain)
63   {
64     domain->setAttributes(this);
65   }
66
67   const std::set<StdString> & CDomain::getRelFiles(void) const
68   {
69      return (this->relFiles);
70   }
71
72   //----------------------------------------------------------------
73
74   const std::vector<int>& CDomain::getIndexesToWrite(void) const
75   {
76     return indexesToWrite;
77   }
78
79   /*!
80     Returns the number of indexes written by each server.
81     \return the number of indexes written by each server
82   */
83   int CDomain::getNumberWrittenIndexes() const
84   {
85     return numberWrittenIndexes_;
86   }
87
88   /*!
89     Returns the total number of indexes written by the servers.
90     \return the total number of indexes written by the servers
91   */
92   int CDomain::getTotalNumberWrittenIndexes() const
93   {
94     return totalNumberWrittenIndexes_;
95   }
96
97   /*!
98     Returns the offset of indexes written by each server.
99     \return the offset of indexes written by each server
100   */
101   int CDomain::getOffsetWrittenIndexes() const
102   {
103     return offsetWrittenIndexes_;
104   }
105
106   //----------------------------------------------------------------
107
108   /*!
109    * Compute the minimum buffer size required to send the attributes to the server(s).
110    *
111    * \return A map associating the server rank with its minimum buffer size.
112    */
113   std::map<int, StdSize> CDomain::getAttributesBufferSize()
114   {
115     CContextClient* client = CContext::getCurrent()->client;
116
117     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes();
118
119     if (client->isServerLeader())
120     {
121       // size estimation for sendServerAttribut
122       size_t size = 11 * sizeof(size_t);
123
124       const std::list<int>& ranks = client->getRanksServerLeader();
125       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
126       {
127         if (size > attributesSizes[*itRank])
128           attributesSizes[*itRank] = size;
129       }
130     }
131
132     std::map<int, std::vector<size_t> >::const_iterator it, ite = indSrv_.end();
133     for (it = indSrv_.begin(); it != ite; ++it)
134     {
135       // size estimation for sendIndex (and sendArea which is always smaller or equal)
136       size_t sizeIndexEvent = 2 * sizeof(size_t) + 2 * CArray<int,1>::size(it->second.size());
137       if (isCompressible_)
138         sizeIndexEvent += CArray<int,1>::size(indWrittenSrv_[it->first].size());
139
140       // size estimation for sendLonLat
141       size_t sizeLonLatEvent = CArray<double,1>::size(it->second.size());
142       if (hasBounds)
143         sizeLonLatEvent += CArray<double,2>::size(nvertex * it->second.size());
144
145       size_t size = CEventClient::headerSize + getId().size() + sizeof(size_t) + std::max(sizeIndexEvent, sizeLonLatEvent);
146       if (size > attributesSizes[it->first])
147         attributesSizes[it->first] = size;
148     }
149
150     return attributesSizes;
151   }
152
153   //----------------------------------------------------------------
154
155   bool CDomain::isEmpty(void) const
156   {
157      return ((this->zoom_ni_srv == 0) ||
158              (this->zoom_nj_srv == 0));
159   }
160
161   //----------------------------------------------------------------
162
163   bool CDomain::IsWritten(const StdString & filename) const
164   {
165      return (this->relFiles.find(filename) != this->relFiles.end());
166   }
167
168   bool CDomain::isWrittenCompressed(const StdString& filename) const
169   {
170      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
171   }
172
173   //----------------------------------------------------------------
174
175   bool CDomain::isDistributed(void) const
176   {
177      return isDistributed_;
178   }
179
180   //----------------------------------------------------------------
181
182   /*!
183    * Test whether the data defined on the domain can be outputted in a compressed way.
184    *
185    * \return true if and only if a mask was defined for this domain
186    */
187   bool CDomain::isCompressible(void) const
188   {
189      return isCompressible_;
190   }
191
192   //----------------------------------------------------------------
193
194   void CDomain::addRelFile(const StdString & filename)
195   {
196      this->relFiles.insert(filename);
197   }
198
199   void CDomain::addRelFileCompressed(const StdString& filename)
200   {
201      this->relFilesCompressed.insert(filename);
202   }
203
204
205   StdString CDomain::GetName(void)   { return (StdString("domain")); }
206   StdString CDomain::GetDefName(void){ return (CDomain::GetName()); }
207   ENodeType CDomain::GetType(void)   { return (eDomain); }
208
209   //----------------------------------------------------------------
210
211   /*!
212     Redistribute RECTILINEAR domain with a number of local domains.
213   All attributes ni,nj,ibegin,jbegin (if defined) will be rewritten
214   The optional attributes lonvalue, latvalue will be added. Because this function only serves (for now)
215   for interpolation from unstructured domain to rectilinear one, range of latvalue is 0-360 and lonvalue is -90 - +90
216    \param [in] nbLocalDomain number of local domain on the domain destination
217   */
218   void CDomain::redistribute(int nbLocalDomain)
219   {
220     if (this->isRedistributed_) return;
221     if (type_attr::rectilinear == type)
222     {
223        this->isRedistributed_ = true;
224
225        CContext* context = CContext::getCurrent();
226        CContextClient* client = context->client;
227        int rankClient = client->clientRank;
228        int rankOnDomain = rankClient%nbLocalDomain;
229
230        if (ni_glo.isEmpty() || ni_glo <= 0 )
231        {
232           ERROR("CDomain::redistribute(int nbLocalDomain)",
233              << "[ Id = " << this->getId() << " ] "
234              << "The global domain is badly defined,"
235              << " check the \'ni_glo\'  value !")
236        }
237
238        if (nj_glo.isEmpty() || nj_glo <= 0 )
239        {
240           ERROR("CDomain::redistribute(int nbLocalDomain)",
241              << "[ Id = " << this->getId() << " ] "
242              << "The global domain is badly defined,"
243              << " check the \'nj_glo\'  value !")
244        }
245
246        int globalDomainSize = ni_glo * nj_glo;
247        if (globalDomainSize <= nbLocalDomain)
248        {
249          for (int idx = 0; idx < nbLocalDomain; ++idx)
250          {
251            if (rankOnDomain < globalDomainSize)
252            {
253              int iIdx = rankOnDomain % ni_glo;
254              int jIdx = rankOnDomain / ni_glo;
255              ibegin.setValue(iIdx); jbegin.setValue(jIdx);
256              ni.setValue(1); nj.setValue(1);
257            }
258            else
259            {
260              ibegin.setValue(0); jbegin.setValue(0);
261              ni.setValue(0); nj.setValue(0);
262            }
263          }
264        }
265        else
266        {
267          float njGlo = nj_glo.getValue();
268          float niGlo = ni_glo.getValue();
269          int nbProcOnX, nbProcOnY, range;
270
271          // Compute (approximately) number of segment on x and y axis
272          float yOverXRatio = njGlo/niGlo;
273
274          nbProcOnX = std::ceil(std::sqrt(nbLocalDomain/yOverXRatio));
275          nbProcOnY = std::ceil(((float)nbLocalDomain)/nbProcOnX);
276
277          // Simple distribution: Sweep from top to bottom, left to right
278          // Calculate local begin on x
279          std::vector<int> ibeginVec(nbProcOnX,0), jbeginVec(nbProcOnY,0);
280          std::vector<int> niVec(nbProcOnX), njVec(nbProcOnY);
281          for (int i = 1; i < nbProcOnX; ++i)
282          {
283            range = ni_glo / nbProcOnX;
284            if (i < (ni_glo%nbProcOnX)) ++range;
285            niVec[i-1] = range;
286            ibeginVec[i] = ibeginVec[i-1] + niVec[i-1];
287          }
288          niVec[nbProcOnX-1] = ni_glo - ibeginVec[nbProcOnX-1];
289
290          // Calculate local begin on y
291          for (int j = 1; j < nbProcOnY; ++j)
292          {
293            range = nj_glo / nbProcOnY;
294            if (j < (nj_glo%nbProcOnY)) ++range;
295            njVec[j-1] = range;
296            jbeginVec[j] = jbeginVec[j-1] + njVec[j-1];
297          }
298          njVec[nbProcOnY-1] = nj_glo - jbeginVec[nbProcOnY-1];
299
300          // Now assign value to ni, ibegin, nj, jbegin
301          int iIdx = rankOnDomain % nbProcOnX;
302          int jIdx = rankOnDomain / nbProcOnX;
303
304          if (rankOnDomain != (nbLocalDomain-1))
305          {
306            ibegin.setValue(ibeginVec[iIdx]);
307            jbegin.setValue(jbeginVec[jIdx]);
308            nj.setValue(njVec[jIdx]);
309            ni.setValue(niVec[iIdx]);
310          }
311          else // just merge all the remaining rectangle into the last one
312          {
313            ibegin.setValue(ibeginVec[iIdx]);
314            jbegin.setValue(jbeginVec[jIdx]);
315            nj.setValue(njVec[jIdx]);
316            ni.setValue(ni_glo - ibeginVec[iIdx]);
317          }
318        }
319
320        // Now fill other attributes
321        fillInRectilinearLonLat();
322     }
323   }
324
325   /*!
326     Fill in the values for lonvalue_1d and latvalue_1d of rectilinear domain
327     Range of longitude value from 0 - 360
328     Range of latitude value from -90 - +90
329   */
330   void CDomain::fillInRectilinearLonLat()
331   {
332     if (!lonvalue_2d.isEmpty()) lonvalue_2d.free();
333     if (!latvalue_2d.isEmpty()) latvalue_1d.free();
334     lonvalue_1d.resize(ni);
335     latvalue_1d.resize(nj);
336
337     double lonRange = lon_end - lon_start;
338     double latRange = lat_end - lat_start;
339
340     double lonStep = (1 == ni_glo.getValue()) ? lonRange : lonRange/double(ni_glo.getValue()-1);
341     double latStep = (1 == nj_glo.getValue()) ? latRange : latRange/double(nj_glo.getValue()-1);
342
343     // Assign lon value
344     for (int i = 0; i < ni; ++i)
345     {
346       if (0 == (ibegin + i))
347       {
348         lonvalue_1d(i) = lon_start;
349       }
350       else if (ni_glo == (ibegin + i + 1))
351       {
352         lonvalue_1d(i) = lon_end;
353       }
354       else
355       {
356         lonvalue_1d(i) = (ibegin + i) * lonStep  + lon_start;
357       }
358     }
359
360     for (int j = 0; j < nj; ++j)
361     {
362       if (0 == (jbegin + j))
363       {
364          latvalue_1d(j) = lat_start;
365       }
366       else if (nj_glo == (jbegin + j + 1))
367       {
368          latvalue_1d(j) = lat_end;
369       }
370       else
371       {
372         latvalue_1d(j) =  (jbegin + j) * latStep + lat_start;
373       }
374     }
375   }
376
377   void CDomain::fillInRectilinearBoundLonLat(CArray<double,2>& boundsLon, CArray<double,2>& boundsLat,
378                                              bool isNorthPole, bool isSouthPole)
379   {
380     int i,j,k;
381     const int nvertexValue = 4;
382
383     double boundsLonRange = bounds_lon_end - bounds_lon_start;
384     double boundsLatRange = bounds_lat_end - bounds_lat_start;
385
386     boundsLon.resize(nvertexValue,ni*nj);
387     boundsLat.resize(nvertexValue,nj*ni);
388
389     double lonStep = boundsLonRange/double(ni_glo.getValue());
390     double latStep = boundsLatRange/double(nj_glo.getValue());
391
392     for(j=0;j<nj;++j)
393       for(i=0;i<ni;++i)
394       {
395         k=j*ni+i;
396         boundsLon(0,k) = boundsLon(1,k) = (0 != (ibegin + i)) ? (ibegin + i) * lonStep + bounds_lon_start
397                                                               : bounds_lon_start;
398         boundsLon(2,k) = boundsLon(3,k) = ((ibegin + i + 1) != ni_glo) ? (ibegin + i +1) * lonStep + bounds_lon_start
399                                                                        : bounds_lon_end;
400       }
401
402     double bounds_lat_start_pole = bounds_lat_start;
403     double bounds_lat_end_pole   = bounds_lat_end;
404     if (isNorthPole) bounds_lat_start_pole = lat_start;
405     if (isSouthPole) bounds_lat_end_pole   = lat_end;
406
407     for(j=0;j<nj;++j)
408       for(i=0;i<ni;++i)
409       {
410         k=j*ni+i;
411         boundsLat(1,k) = boundsLat(2,k) = (0 != (jbegin + j)) ? (jbegin + j) * latStep + bounds_lat_start
412                                                               : bounds_lat_start_pole;
413         boundsLat(0,k) = boundsLat(3,k) = ((jbegin + j +1) != nj_glo) ? (jbegin + j +1) * latStep + bounds_lat_start
414                                                               : bounds_lat_end_pole;
415       }
416   }
417
418   /*!
419     Temporary function to verify whether a rectilinear domain is created automatically.
420   The domain is distributed into number of parts which are equal to number of clients (intracomm)
421   */
422   void CDomain::checkGenerate()
423   {
424     TransMapTypes trans = this->getAllTransformations();
425     TransMapTypes::const_iterator it = trans.begin(), ite = trans.end();
426     int transOrder = 0;
427     for (; it != ite; ++it, ++transOrder)
428     {
429       ETranformationType transType = it->first;
430       if ((TRANS_GENERATE_RECTILINEAR_DOMAIN == transType) && (0 == transOrder))
431       {
432         CContext* context = CContext::getCurrent();
433         CContextClient* client = context->client;
434         int nbClient;
435         MPI_Comm_size(client->intraComm,&nbClient);
436         it->second->checkValid(this);
437         this->redistribute(nbClient);
438         break;
439       }
440     }
441   }
442
443
444   void CDomain::checkDomain(void)
445   {
446     if (type.isEmpty())
447     {
448       ERROR("CDomain::checkDomain(void)",
449             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
450             << "The domain type is mandatory, "
451             << "please define the 'type' attribute.")
452     }
453
454     if (type == type_attr::unstructured)
455     {
456        if (ni_glo.isEmpty())
457        {
458          ERROR("CDomain::checkDomain(void)",
459                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
460                << "The global domain is badly defined, "
461                << "the mandatory 'ni_glo' attribute is missing.")
462        }
463        else if (ni_glo <= 0)
464        {
465          ERROR("CDomain::checkDomain(void)",
466                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
467                << "The global domain is badly defined, "
468                << "'ni_glo' attribute should be strictly positive so 'ni_glo = " << ni_glo.getValue() << "' is invalid.")
469        }
470        isUnstructed_ = true;
471        nj_glo = 1;
472        nj = 1;
473        jbegin = 0;
474        if (ni.isEmpty()) ni = i_index.numElements();
475        j_index.resize(ni);
476        for(int i=0;i<ni;++i) j_index(i)=0;
477
478        if (!area.isEmpty())
479          area.transposeSelf(1, 0);
480     }
481
482     if (ni_glo.isEmpty())
483     {
484       ERROR("CDomain::checkDomain(void)",
485             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
486             << "The global domain is badly defined, "
487             << "the mandatory 'ni_glo' attribute is missing.")
488     }
489     else if (ni_glo <= 0)
490     {
491       ERROR("CDomain::checkDomain(void)",
492             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
493             << "The global domain is badly defined, "
494             << "'ni_glo' attribute should be strictly positive so 'ni_glo = " << ni_glo.getValue() << "' is invalid.")
495     }
496
497     if (nj_glo.isEmpty())
498     {
499       ERROR("CDomain::checkDomain(void)",
500             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
501             << "The global domain is badly defined, "
502             << "the mandatory 'nj_glo' attribute is missing.")
503     }
504     else if (nj_glo <= 0)
505     {
506       ERROR("CDomain::checkDomain(void)",
507             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
508             << "The global domain is badly defined, "
509             << "'nj_glo' attribute should be strictly positive so 'nj_glo = " << nj_glo.getValue() << "' is invalid.")
510     }
511
512     isDistributed_ = !ibegin.isEmpty() || !ni.isEmpty() || !jbegin.isEmpty() || !nj.isEmpty();
513
514     checkLocalIDomain();
515     checkLocalJDomain();
516
517     if (i_index.isEmpty())
518     {
519       i_index.resize(ni*nj);
520       for (int j = 0; j < nj; ++j)
521         for (int i = 0; i < ni; ++i) i_index(i+j*ni) = i+ibegin;
522     }
523
524     if (j_index.isEmpty())
525     {
526       j_index.resize(ni*nj);
527       for (int j = 0; j < nj; ++j)
528         for (int i = 0; i < ni; ++i) j_index(i+j*ni) = j+jbegin;
529     }
530     computeNGlobDomain();
531
532     if (0 == global_zoom_ni) global_zoom_ni = ni_glo;
533     if (0 == global_zoom_nj) global_zoom_nj = nj_glo;
534   }
535
536   //----------------------------------------------------------------
537
538   void CDomain::checkLocalIDomain(void)
539   {
540      if (ibegin.isEmpty() && ni.isEmpty())
541      {
542        ibegin = 0;
543        ni = ni_glo;
544      }
545      else if (!i_index.isEmpty())
546      {
547        if (ibegin.isEmpty()) ibegin = i_index(0);
548      }
549
550      if (ni.getValue() < 0 || ibegin.getValue() < 0 ||
551         (ibegin.getValue() + ni.getValue()) > ni_glo.getValue())
552      {
553        ERROR("CDomain::checkLocalIDomain(void)",
554              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
555              << "The local domain is wrongly defined,"
556              << " check the attributes 'ni_glo' (" << ni_glo.getValue() << "), 'ni' (" << ni.getValue() << ") and 'ibegin' (" << ibegin.getValue() << ")");
557      }
558   }
559
560   void CDomain::checkLocalJDomain(void)
561   {
562     if (jbegin.isEmpty() && nj.isEmpty())
563     {
564       jbegin = 0;
565       nj = nj_glo;
566     }
567     else if (!j_index.isEmpty())
568     {
569       if (jbegin.isEmpty()) jbegin = j_index(0);
570     }
571
572      if (nj.getValue() < 0 || jbegin.getValue() < 0 ||
573         (jbegin.getValue() + nj.getValue()) > nj_glo.getValue())
574      {
575        ERROR("CDomain::checkLocalJDomain(void)",
576              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
577              << "The local domain is wrongly defined,"
578              << " check the attributes 'nj_glo' (" << nj_glo.getValue() << "), 'nj' (" << nj.getValue() << ") and 'jbegin' (" << jbegin.getValue() << ")");
579      }
580   }
581
582   //----------------------------------------------------------------
583
584   void CDomain::checkMask(void)
585   {
586      if (!mask_1d.isEmpty() && !mask_2d.isEmpty())
587        ERROR("CDomain::checkMask(void)",
588              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
589              << "Both mask_1d and mask_2d are defined but only one can be used at the same time." << std::endl
590              << "Please define only one mask: 'mask_1d' or 'mask_2d'.");
591
592      if (!mask_1d.isEmpty() && mask_2d.isEmpty())
593      {
594        if (mask_1d.numElements() != i_index.numElements())
595          ERROR("CDomain::checkMask(void)",
596                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
597                << "'mask_1d' does not have the same size as the local domain." << std::endl
598                << "Local size is " << i_index.numElements() << "." << std::endl
599                << "Mask size is " << mask_1d.numElements() << ".");
600      }
601
602      if (mask_1d.isEmpty() && !mask_2d.isEmpty())
603      {
604        if (mask_2d.extent(0) != ni || mask_2d.extent(1) != nj)
605          ERROR("CDomain::checkMask(void)",
606                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
607                << "The mask does not have the same size as the local domain." << std::endl
608                << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
609                << "Mask size is " << mask_2d.extent(0) << " x " << mask_2d.extent(1) << ".");
610      }
611
612      if (!mask_2d.isEmpty())
613      {
614        mask_1d.resize(mask_2d.extent(0) * mask_2d.extent(1));
615        for (int j = 0; j < nj; ++j)
616          for (int i = 0; i < ni; ++i) mask_1d(i+j*ni) = mask_2d(i,j);
617        mask_2d.free();
618      }
619      else if (mask_1d.isEmpty())
620      {
621        mask_1d.resize(i_index.numElements());
622        for (int i = 0; i < i_index.numElements(); ++i) mask_1d(i) = true;
623      }
624   }
625
626   //----------------------------------------------------------------
627
628   void CDomain::checkDomainData(void)
629   {
630      if (data_dim.isEmpty())
631      {
632        data_dim.setValue(1);
633      }
634      else if (!(data_dim.getValue() == 1 || data_dim.getValue() == 2))
635      {
636        ERROR("CDomain::checkDomainData(void)",
637              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
638              << "The data dimension is invalid, 'data_dim' must be 1 or 2 not << " << data_dim.getValue() << ".");
639      }
640
641      if (data_ibegin.isEmpty())
642         data_ibegin.setValue(0);
643      if (data_jbegin.isEmpty())
644         data_jbegin.setValue(0);
645
646      if (data_ni.isEmpty())
647      {
648        data_ni.setValue((data_dim == 1) ? (ni.getValue() * nj.getValue()) : ni.getValue());
649      }
650      else if (data_ni.getValue() < 0)
651      {
652        ERROR("CDomain::checkDomainData(void)",
653              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
654              << "The data size cannot be negative ('data_ni' = " << data_ni.getValue() << ").");
655      }
656
657      if (data_nj.isEmpty())
658      {
659        data_nj.setValue((data_dim.getValue() == 1) ? (ni.getValue() * nj.getValue()) : nj.getValue());
660      }
661      else if (data_nj.getValue() < 0)
662      {
663        ERROR("CDomain::checkDomainData(void)",
664              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
665              << "The data size cannot be negative ('data_nj' = " << data_nj.getValue() << ").");
666      }
667   }
668
669   //----------------------------------------------------------------
670
671   void CDomain::checkCompression(void)
672   {
673      if (!data_i_index.isEmpty())
674      {
675        if (!data_j_index.isEmpty() &&
676            data_j_index.numElements() != data_i_index.numElements())
677        {
678           ERROR("CDomain::checkCompression(void)",
679                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
680                 << "'data_i_index' and 'data_j_index' arrays must have the same size." << std::endl
681                 << "'data_i_index' size = " << data_i_index.numElements() << std::endl
682                 << "'data_j_index' size = " << data_j_index.numElements());
683        }
684
685        if (2 == data_dim)
686        {
687          if (data_j_index.isEmpty())
688          {
689             ERROR("CDomain::checkCompression(void)",
690                   << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
691                   << "'data_j_index' must be defined when 'data_i_index' is set and 'data_dim' is 2.");
692          }
693        }
694        else // (1 == data_dim)
695        {
696          if (data_j_index.isEmpty())
697          {
698            data_j_index.resize(data_ni);
699            for (int j = 0; j < data_ni; ++j) data_j_index(j) = 0;
700          }
701        }
702      }
703      else
704      {
705        if (data_dim == 2 && !data_j_index.isEmpty())
706          ERROR("CDomain::checkCompression(void)",
707                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
708                << "'data_i_index' must be defined when 'data_j_index' is set and 'data_dim' is 2.");
709
710        if (1 == data_dim)
711        {
712          data_i_index.resize(data_ni);
713          data_j_index.resize(data_ni);
714
715          for (int i = 0; i < data_ni; ++i)
716          {
717            data_i_index(i) = i;
718            data_j_index(i) = 0;
719          }
720        }
721        else // (data_dim == 2)
722        {
723          const int dsize = data_ni * data_nj;
724          data_i_index.resize(dsize);
725          data_j_index.resize(dsize);
726
727          for(int count = 0, j = 0; j < data_nj; ++j)
728          {
729            for(int i = 0; i < data_ni; ++i, ++count)
730            {
731              data_i_index(count) = i;
732              data_j_index(count) = j;
733            }
734          }
735        }
736      }
737   }
738
739   //----------------------------------------------------------------
740
741   void CDomain::checkEligibilityForCompressedOutput(void)
742   {
743     // We don't check if the mask or the indexes are valid here, just if they have been defined at this point.
744     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !data_i_index.isEmpty();
745   }
746
747   //----------------------------------------------------------------
748
749   void CDomain::completeLonLatClient(void)
750   {
751     if (!lonvalue_2d.isEmpty())
752     {
753       lonvalue_client.resize(ni * nj);
754       latvalue_client.resize(ni * nj);
755       if (hasBounds)
756       {
757         bounds_lon_client.resize(nvertex, ni * nj);
758         bounds_lat_client.resize(nvertex, ni * nj);
759       }
760
761       for (int j = 0; j < nj; ++j)
762       {
763         for (int i = 0; i < ni; ++i)
764         {
765           int k = j * ni + i;
766
767           lonvalue_client(k) = lonvalue_2d(i,j);
768           latvalue_client(k) = latvalue_2d(i,j);
769
770           if (hasBounds)
771           {
772             for (int n = 0; n < nvertex; ++n)
773             {
774               bounds_lon_client(n,k) = bounds_lon_2d(n,i,j);
775               bounds_lat_client(n,k) = bounds_lat_2d(n,i,j);
776             }
777           }
778         }
779       }
780     }
781     else if (!lonvalue_1d.isEmpty())
782     {
783       if (type_attr::rectilinear == type)
784       {
785         if (ni == lonvalue_1d.numElements() && nj == latvalue_1d.numElements())
786         {
787           lonvalue_client.resize(ni * nj);
788           latvalue_client.resize(ni * nj);
789           if (hasBounds)
790           {
791             bounds_lon_client.resize(nvertex, ni * nj);
792             bounds_lat_client.resize(nvertex, ni * nj);
793           }
794
795           for (int j = 0; j < nj; ++j)
796           {
797             for (int i = 0; i < ni; ++i)
798             {
799               int k = j * ni + i;
800
801               lonvalue_client(k) = lonvalue_1d(i);
802               latvalue_client(k) = latvalue_1d(j);
803
804               if (hasBounds)
805               {
806                 for (int n = 0; n < nvertex; ++n)
807                 {
808                   bounds_lon_client(n,k) = bounds_lon_1d(n,i);
809                   bounds_lat_client(n,k) = bounds_lat_1d(n,j);
810                 }
811               }
812             }
813           }
814         }
815         else
816           ERROR("CDomain::completeLonClient(void)",
817                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
818                 << "'lonvalue_1d' and 'latvalue_1d' does not have the same size as the local domain." << std::endl
819                 << "'lonvalue_1d' size is " << lonvalue_1d.numElements() << " but it should be " << ni.getValue() << '.' << std::endl
820                 << "'latvalue_1d' size is " << latvalue_1d.numElements() << " but it should be " << nj.getValue() << '.');
821       }
822       else if (type == type_attr::curvilinear || type == type_attr::unstructured)
823       {
824         lonvalue_client.reference(lonvalue_1d);
825         latvalue_client.reference(latvalue_1d);
826         if (hasBounds)
827         {
828           bounds_lon_client.reference(bounds_lon_1d);
829           bounds_lat_client.reference(bounds_lat_1d);
830         }
831       }
832     }
833   }
834
835   void CDomain::checkBounds(void)
836   {
837     if (!nvertex.isEmpty() && nvertex > 0)
838     {
839       if (!bounds_lon_1d.isEmpty() && !bounds_lon_2d.isEmpty())
840         ERROR("CDomain::checkBounds(void)",
841               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
842               << "Only one longitude boundary attribute can be used but both 'bounds_lon_1d' and 'bounds_lon_2d' are defined." << std::endl
843               << "Define only one longitude boundary attribute: 'bounds_lon_1d' or 'bounds_lon_2d'.");
844
845       if (!bounds_lat_1d.isEmpty() && !bounds_lat_2d.isEmpty())
846         ERROR("CDomain::checkBounds(void)",
847               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
848               << "Only one latitude boundary attribute can be used but both 'bounds_lat_1d' and 'bounds_lat_2d' are defined." << std::endl
849               << "Define only one latitude boundary attribute: 'bounds_lat_1d' or 'bounds_lat_2d'.");
850
851       if ((!bounds_lon_1d.isEmpty() && bounds_lat_1d.isEmpty()) || (bounds_lon_1d.isEmpty() && !bounds_lat_1d.isEmpty()))
852       {
853         ERROR("CDomain::checkBounds(void)",
854               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
855               << "Only 'bounds_lon_1d' or 'bounds_lat_1d' is defined." << std::endl
856               << "Please define either both attributes or none.");
857       }
858
859       if ((!bounds_lon_2d.isEmpty() && bounds_lat_2d.isEmpty()) || (bounds_lon_2d.isEmpty() && !bounds_lat_2d.isEmpty()))
860       {
861         ERROR("CDomain::checkBounds(void)",
862               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
863               << "Only 'bounds_lon_2d' or 'bounds_lat_2d' is defined." << std::endl
864               << "Please define either both attributes or none.");
865       }
866
867       if (!bounds_lon_1d.isEmpty() && nvertex.getValue() != bounds_lon_1d.extent(0))
868         ERROR("CDomain::checkBounds(void)",
869               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
870               << "'bounds_lon_1d' dimension is not compatible with 'nvertex'." << std::endl
871               << "'bounds_lon_1d' dimension is " << bounds_lon_1d.extent(1)
872               << " but nvertex is " << nvertex.getValue() << ".");
873
874       if (!bounds_lon_2d.isEmpty() && nvertex.getValue() != bounds_lon_2d.extent(0))
875         ERROR("CDomain::checkBounds(void)",
876               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
877               << "'bounds_lon_2d' dimension is not compatible with 'nvertex'." << std::endl
878               << "'bounds_lon_2d' dimension is " << bounds_lon_2d.extent(2)
879               << " but nvertex is " << nvertex.getValue() << ".");
880
881       if (!bounds_lon_1d.isEmpty() && lonvalue_1d.isEmpty())
882         ERROR("CDomain::checkBounds(void)",
883               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
884               << "Since 'bounds_lon_1d' is defined, 'lonvalue_1d' must be defined too." << std::endl);
885
886       if (!bounds_lon_2d.isEmpty() && lonvalue_2d.isEmpty())
887         ERROR("CDomain::checkBounds(void)",
888               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
889               << "Since 'bounds_lon_2d' is defined, 'lonvalue_2d' must be defined too." << std::endl);
890
891       if (!bounds_lat_1d.isEmpty() && nvertex.getValue() != bounds_lat_1d.extent(0))
892         ERROR("CDomain::checkBounds(void)",
893               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
894               << "'bounds_lat_1d' dimension is not compatible with 'nvertex'." << std::endl
895               << "'bounds_lat_1d' dimension is " << bounds_lat_1d.extent(1)
896               << " but nvertex is " << nvertex.getValue() << ".");
897
898       if (!bounds_lat_2d.isEmpty() && nvertex.getValue() != bounds_lat_2d.extent(0))
899         ERROR("CDomain::checkBounds(void)",
900               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
901               << "'bounds_lat_2d' dimension is not compatible with 'nvertex'." << std::endl
902               << "'bounds_lat_2d' dimension is " << bounds_lat_2d.extent(2)
903               << " but nvertex is " << nvertex.getValue() << ".");
904
905       if (!bounds_lat_1d.isEmpty() && latvalue_1d.isEmpty())
906         ERROR("CDomain::checkBounds(void)",
907               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
908               << "Since 'bounds_lat_1d' is defined, 'latvalue_1d' must be defined too." << std::endl);
909
910       if (!bounds_lat_2d.isEmpty() && latvalue_2d.isEmpty())
911         ERROR("CDomain::checkBounds(void)",
912               << "Since 'bounds_lat_2d' is defined, 'latvalue_2d' must be defined too." << std::endl);
913
914       hasBounds = true;
915     }
916     else
917     {
918       hasBounds = false;
919       nvertex = 0;
920     }
921   }
922
923   void CDomain::checkArea(void)
924   {
925     hasArea = !area.isEmpty();
926     if (hasArea)
927     {
928       if (area.extent(0) != ni || area.extent(1) != nj)
929       {
930         ERROR("CDomain::checkArea(void)",
931               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
932               << "The area does not have the same size as the local domain." << std::endl
933               << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
934               << "Area size is " << area.extent(0) << " x " << area.extent(1) << ".");
935       }
936     }
937   }
938
939   void CDomain::checkLonLat()
940   {
941     hasLonLat = (!latvalue_1d.isEmpty() && !lonvalue_1d.isEmpty()) ||
942                 (!latvalue_2d.isEmpty() && !lonvalue_2d.isEmpty());
943     if (hasLonLat)
944     {
945       if (!lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
946         ERROR("CDomain::checkLonLat()",
947               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
948               << "Only one longitude attribute can be used but both 'lonvalue_1d' and 'lonvalue_2d' are defined." << std::endl
949               << "Define only one longitude attribute: 'lonvalue_1d' or 'lonvalue_2d'.");
950
951       if (!lonvalue_1d.isEmpty() && lonvalue_2d.isEmpty())
952       {
953         if ((type_attr::rectilinear != type) && (lonvalue_1d.numElements() != i_index.numElements()))
954           ERROR("CDomain::checkLonLat()",
955                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
956                 << "'lonvalue_1d' does not have the same size as the local domain." << std::endl
957                 << "Local size is " << i_index.numElements() << "." << std::endl
958                 << "'lonvalue_1d' size is " << lonvalue_1d.numElements() << ".");
959       }
960
961       if (lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
962       {
963         if (lonvalue_2d.extent(0) != ni || lonvalue_2d.extent(1) != nj)
964           ERROR("CDomain::checkLonLat()",
965                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
966                 << "'lonvalue_2d' does not have the same size as the local domain." << std::endl
967                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
968                 << "'lonvalue_2d' size is " << lonvalue_2d.extent(0) << " x " << lonvalue_2d.extent(1) << ".");
969       }
970
971       if (!latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
972         ERROR("CDomain::checkLonLat()",
973               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
974               << "Only one latitude attribute can be used but both 'latvalue_1d' and 'latvalue_2d' are defined." << std::endl
975               << "Define only one latitude attribute: 'latvalue_1d' or 'latvalue_2d'.");
976
977       if (!latvalue_1d.isEmpty() && latvalue_2d.isEmpty())
978       {
979         if ((type_attr::rectilinear != type) && (latvalue_1d.numElements() != i_index.numElements()))
980           ERROR("CDomain::checkLonLat()",
981                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
982                 << "'latvalue_1d' does not have the same size as the local domain." << std::endl
983                 << "Local size is " << i_index.numElements() << "." << std::endl
984                 << "'latvalue_1d' size is " << latvalue_1d.numElements() << ".");
985       }
986
987       if (latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
988       {
989         if (latvalue_2d.extent(0) != ni || latvalue_2d.extent(1) != nj)
990           ERROR("CDomain::checkLonLat()",
991                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
992                 << "'latvalue_2d' does not have the same size as the local domain." << std::endl
993                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
994                 << "'latvalue_2d' size is " << latvalue_2d.extent(0) << " x " << latvalue_2d.extent(1) << ".");
995       }
996     }
997   }
998
999   void CDomain::checkAttributesOnClientAfterTransformation()
1000   {
1001     CContext* context=CContext::getCurrent() ;
1002
1003     if (this->isClientAfterTransformationChecked) return;
1004     if (context->hasClient)
1005     {
1006       this->checkMask();
1007       if (hasLonLat || hasArea || isCompressible_) this->computeConnectedServer();
1008       if (hasLonLat) this->completeLonLatClient();
1009     }
1010
1011     this->isClientAfterTransformationChecked = true;
1012   }
1013
1014   //----------------------------------------------------------------
1015   // Divide function checkAttributes into 2 seperate ones
1016   // This function only checks all attributes of current domain
1017   void CDomain::checkAttributesOnClient()
1018   {
1019     if (this->isClientChecked) return;
1020     CContext* context=CContext::getCurrent();
1021
1022      this->checkGenerate();
1023      this->checkDomain();
1024      this->checkBounds();
1025      this->checkArea();
1026      this->checkLonLat();
1027
1028      if (context->hasClient)
1029      { // CÃŽté client uniquement
1030         this->checkMask();
1031         this->checkDomainData();
1032         this->checkCompression();
1033      }
1034      else
1035      { // CÃŽté serveur uniquement
1036      }
1037
1038      this->isClientChecked = true;
1039   }
1040
1041   // Send all checked attributes to server
1042   void CDomain::sendCheckedAttributes()
1043   {
1044     if (!this->isClientChecked) checkAttributesOnClient();
1045     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation();
1046     CContext* context=CContext::getCurrent() ;
1047
1048     if (this->isChecked) return;
1049     if (context->hasClient)
1050     {
1051       sendServerAttribut();
1052       if (hasLonLat || hasArea || isCompressible_) sendLonLatArea();
1053     }
1054     this->isChecked = true;
1055   }
1056
1057   void CDomain::checkAttributes(void)
1058   {
1059      if (this->isChecked) return;
1060      CContext* context=CContext::getCurrent() ;
1061
1062      this->checkDomain();
1063      this->checkLonLat();
1064      this->checkBounds();
1065      this->checkArea();
1066
1067      if (context->hasClient)
1068      { // CÃŽté client uniquement
1069         this->checkMask();
1070         this->checkDomainData();
1071         this->checkCompression();
1072
1073      }
1074      else
1075      { // CÃŽté serveur uniquement
1076      }
1077
1078      if (context->hasClient)
1079      {
1080        this->computeConnectedServer();
1081        this->completeLonLatClient();
1082        this->sendServerAttribut();
1083        this->sendLonLatArea();
1084      }
1085
1086      this->isChecked = true;
1087   }
1088
1089  void CDomain::sendServerAttribut(void)
1090  {
1091    CServerDistributionDescription serverDescription(nGlobDomain_);
1092
1093    CContext* context = CContext::getCurrent();
1094    CContextClient* client = context->client;
1095    int nbServer = client->serverSize;
1096
1097    if (isUnstructed_) serverDescription.computeServerDistribution(nbServer,0);
1098    else serverDescription.computeServerDistribution(nbServer,1);
1099
1100    std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
1101    std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
1102
1103    CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT);
1104    if (client->isServerLeader())
1105    {
1106      std::list<CMessage> msgs;
1107
1108      const std::list<int>& ranks = client->getRanksServerLeader();
1109      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1110      {
1111        // Use const int to ensure CMessage holds a copy of the value instead of just a reference
1112        const int ibegin_srv = serverIndexBegin[*itRank][0];
1113        const int jbegin_srv = serverIndexBegin[*itRank][1];
1114        const int ni_srv = serverDimensionSizes[*itRank][0];
1115        const int nj_srv = serverDimensionSizes[*itRank][1];
1116        const int iend_srv = ibegin_srv + ni_srv - 1;
1117        const int jend_srv = jbegin_srv + nj_srv - 1;
1118
1119        msgs.push_back(CMessage());
1120        CMessage& msg = msgs.back();
1121        msg << this->getId() ;
1122        msg << ni_srv << ibegin_srv << iend_srv << nj_srv << jbegin_srv << jend_srv;
1123        msg << global_zoom_ni << global_zoom_ibegin << global_zoom_nj << global_zoom_jbegin;
1124        msg << isCompressible_;
1125
1126        event.push(*itRank,1,msg);
1127      }
1128      client->sendEvent(event);
1129    }
1130    else client->sendEvent(event);
1131  }
1132
1133  void CDomain::computeNGlobDomain()
1134  {
1135    nGlobDomain_.resize(2);
1136    nGlobDomain_[0] = ni_glo.getValue();
1137    nGlobDomain_[1] = nj_glo.getValue();
1138  }
1139
1140  void CDomain::computeConnectedServer(void)
1141  {
1142    CContext* context=CContext::getCurrent() ;
1143    CContextClient* client=context->client ;
1144    int nbServer=client->serverSize;
1145    bool doComputeGlobalIndexServer = true;
1146
1147    int i,j,i_ind,j_ind, nbIndex;
1148    int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1 ;
1149    int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1 ;
1150
1151    // Precompute number of index
1152    int globalIndexCountZoom = 0;
1153    nbIndex = i_index.numElements();
1154    for (i = 0; i < nbIndex; ++i)
1155    {
1156      i_ind=i_index(i);
1157      j_ind=j_index(i);
1158
1159      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1160      {
1161        ++globalIndexCountZoom;
1162      }
1163    }
1164
1165    int globalIndexWrittenCount = 0;
1166    if (isCompressible_)
1167    {
1168      for (i = 0; i < data_i_index.numElements(); ++i)
1169      {
1170        i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1171                                                    data_ibegin, data_jbegin, data_dim, ni,
1172                                                    j_ind);
1173        if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1174        {
1175          i_ind += ibegin;
1176          j_ind += jbegin;
1177          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1178            ++globalIndexWrittenCount;
1179        }
1180      }
1181    }
1182
1183    // Fill in index
1184    CArray<size_t,1> globalIndexDomainZoom(globalIndexCountZoom);
1185    CArray<size_t,1> localIndexDomainZoom(globalIndexCountZoom);
1186    CArray<size_t,1> globalIndexDomain(nbIndex);
1187    size_t globalIndex;
1188    int globalIndexCount = 0;
1189    globalIndexCountZoom = 0;
1190
1191    for (i = 0; i < nbIndex; ++i)
1192    {
1193      i_ind=i_index(i);
1194      j_ind=j_index(i);
1195      globalIndex = i_ind + j_ind * ni_glo;
1196      globalIndexDomain(globalIndexCount) = globalIndex;
1197      ++globalIndexCount;
1198      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1199      {
1200        globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
1201        localIndexDomainZoom(globalIndexCountZoom) = i;
1202        ++globalIndexCountZoom;
1203      }
1204    }
1205
1206    CArray<int,1> globalIndexWrittenDomain(globalIndexWrittenCount);
1207    if (isCompressible_)
1208    {
1209      globalIndexWrittenCount = 0;
1210      for (i = 0; i < data_i_index.numElements(); ++i)
1211      {
1212        i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1213                                                    data_ibegin, data_jbegin, data_dim, ni,
1214                                                    j_ind);
1215        if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1216        {
1217          i_ind += ibegin;
1218          j_ind += jbegin;
1219          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1220          {
1221            globalIndexWrittenDomain(globalIndexWrittenCount) = i_ind + j_ind * ni_glo;
1222            ++globalIndexWrittenCount;
1223          }
1224        }
1225      }
1226    }
1227
1228    size_t globalSizeIndex = 1, indexBegin, indexEnd;
1229    int range, clientSize = client->clientSize;
1230    for (int i = 0; i < nGlobDomain_.size(); ++i) globalSizeIndex *= nGlobDomain_[i];
1231    indexBegin = 0;
1232    for (int i = 0; i < clientSize; ++i)
1233    {
1234      range = globalSizeIndex / clientSize;
1235      if (i < (globalSizeIndex%clientSize)) ++range;
1236      if (i == client->clientRank) break;
1237      indexBegin += range;
1238    }
1239    indexEnd = indexBegin + range - 1;
1240
1241    CServerDistributionDescription serverDescription(nGlobDomain_);
1242    if (isUnstructed_) serverDescription.computeServerGlobalIndexInRange(nbServer, std::make_pair<size_t,size_t>(indexBegin, indexEnd), 0);
1243    else serverDescription.computeServerGlobalIndexInRange(nbServer, std::make_pair<size_t,size_t>(indexBegin, indexEnd), 1);
1244
1245    CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(),
1246                                                                                client->intraComm);
1247    clientServerMap->computeServerIndexMapping(globalIndexDomain);
1248    const std::map<int, std::vector<size_t> >& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer();
1249
1250    std::map<int, std::vector<size_t> >::const_iterator it = globalIndexDomainOnServer.begin(),
1251                                                       ite = globalIndexDomainOnServer.end();
1252    typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
1253    std::vector<int>::iterator itVec;
1254
1255    indSrv_.clear();
1256    indWrittenSrv_.clear();
1257    for (; it != ite; ++it)
1258    {
1259      int rank = it->first;
1260      int indexSize = it->second.size();
1261      std::vector<int> permutIndex(indexSize);
1262      XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
1263      XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(it->second, permutIndex);
1264      BinarySearch binSearch(it->second);
1265      int nb = globalIndexDomainZoom.numElements();
1266      for (int i = 0; i < nb; ++i)
1267      {
1268        if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexDomainZoom(i), itVec))
1269        {
1270          indSrv_[rank].push_back(localIndexDomainZoom(i));
1271        }
1272      }
1273      for (int i = 0; i < globalIndexWrittenDomain.numElements(); ++i)
1274      {
1275        if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexWrittenDomain(i), itVec))
1276        {
1277          indWrittenSrv_[rank].push_back(globalIndexWrittenDomain(i));
1278        }
1279      }
1280    }
1281
1282    connectedServerRank_.clear();
1283    for (it = globalIndexDomainOnServer.begin(); it != ite; ++it) {
1284      connectedServerRank_.push_back(it->first);
1285    }
1286
1287    if (!indSrv_.empty())
1288    {
1289      connectedServerRank_.clear();
1290      for (it = indSrv_.begin(); it != indSrv_.end(); ++it)
1291        connectedServerRank_.push_back(it->first);
1292    }
1293    nbConnectedClients_ = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
1294
1295    delete clientServerMap;
1296  }
1297
1298  const std::map<int, vector<size_t> >& CDomain::getIndexServer() const
1299  {
1300    return indSrv_;
1301  }
1302
1303  /*!
1304    Send index from client to server(s)
1305  */
1306  void CDomain::sendIndex()
1307  {
1308    int ns, n, i, j, ind, nv, idx;
1309    CContext* context = CContext::getCurrent();
1310    CContextClient* client=context->client;
1311
1312    CEventClient eventIndex(getType(), EVENT_ID_INDEX);
1313
1314    list<CMessage> list_msgsIndex;
1315    list<CArray<int,1> > list_indi, list_indj, list_writtenInd;
1316
1317    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1318    iteMap = indSrv_.end();
1319    for (int k = 0; k < connectedServerRank_.size(); ++k)
1320    {
1321      int nbData = 0;
1322      int rank = connectedServerRank_[k];
1323      it = indSrv_.find(rank);
1324      if (iteMap != it)
1325        nbData = it->second.size();
1326
1327      list_indi.push_back(CArray<int,1>(nbData));
1328      list_indj.push_back(CArray<int,1>(nbData));
1329
1330      CArray<int,1>& indi = list_indi.back();
1331      CArray<int,1>& indj = list_indj.back();
1332      const std::vector<size_t>& temp = it->second;
1333      for (n = 0; n < nbData; ++n)
1334      {
1335        idx = static_cast<int>(it->second[n]);
1336        indi(n) = i_index(idx);
1337        indj(n) = j_index(idx);
1338      }
1339
1340      list_msgsIndex.push_back(CMessage());
1341
1342      list_msgsIndex.back() << this->getId() << (int)type; // enum ne fonctionne pour les message => ToFix
1343      list_msgsIndex.back() << isCurvilinear;
1344      list_msgsIndex.back() << list_indi.back() << list_indj.back();
1345
1346      if (isCompressible_)
1347      {
1348        std::vector<int>& writtenIndSrc = indWrittenSrv_[rank];
1349        list_writtenInd.push_back(CArray<int,1>(writtenIndSrc.size()));
1350        CArray<int,1>& writtenInd = list_writtenInd.back();
1351
1352        for (n = 0; n < writtenInd.numElements(); ++n)
1353          writtenInd(n) = writtenIndSrc[n];
1354
1355        list_msgsIndex.back() << writtenInd;
1356      }
1357
1358      eventIndex.push(rank, nbConnectedClients_[rank], list_msgsIndex.back());
1359    }
1360
1361    client->sendEvent(eventIndex);
1362  }
1363
1364  /*!
1365    Send area from client to server(s)
1366  */
1367  void CDomain::sendArea()
1368  {
1369    if (!hasArea) return;
1370
1371    int ns, n, i, j, ind, nv, idx;
1372    CContext* context = CContext::getCurrent();
1373    CContextClient* client=context->client;
1374
1375    // send area for each connected server
1376    CEventClient eventArea(getType(), EVENT_ID_AREA);
1377
1378    list<CMessage> list_msgsArea;
1379    list<CArray<double,1> > list_area;
1380
1381    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1382    iteMap = indSrv_.end();
1383    for (int k = 0; k < connectedServerRank_.size(); ++k)
1384    {
1385      int nbData = 0;
1386      int rank = connectedServerRank_[k];
1387      it = indSrv_.find(rank);
1388      if (iteMap != it)
1389        nbData = it->second.size();
1390      list_area.push_back(CArray<double,1>(nbData));
1391
1392      const std::vector<size_t>& temp = it->second;
1393      for (n = 0; n < nbData; ++n)
1394      {
1395        idx = static_cast<int>(it->second[n]);
1396        i = i_index(idx);
1397        j = j_index(idx);
1398        if (hasArea)
1399          list_area.back()(n) = area(i - ibegin, j - jbegin);
1400      }
1401
1402      list_msgsArea.push_back(CMessage());
1403      list_msgsArea.back() << this->getId() << list_area.back();
1404      eventArea.push(rank, nbConnectedClients_[rank], list_msgsArea.back());
1405    }
1406    client->sendEvent(eventArea);
1407  }
1408
1409  /*!
1410    Send longitude and latitude from client to servers
1411    Each client send long and lat information to corresponding connected server(s).
1412    Because longitude and latitude are optional, this function only called if latitude and longitude exist
1413  */
1414  void CDomain::sendLonLat()
1415  {
1416    if (!hasLonLat) return;
1417
1418    int ns, n, i, j, ind, nv, idx;
1419    CContext* context = CContext::getCurrent();
1420    CContextClient* client=context->client;
1421
1422    // send lon lat for each connected server
1423    CEventClient eventLon(getType(), EVENT_ID_LON);
1424    CEventClient eventLat(getType(), EVENT_ID_LAT);
1425
1426    list<CMessage> list_msgsLon, list_msgsLat;
1427    list<CArray<double,1> > list_lon, list_lat;
1428    list<CArray<double,2> > list_boundslon, list_boundslat;
1429
1430    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1431    iteMap = indSrv_.end();
1432    for (int k = 0; k < connectedServerRank_.size(); ++k)
1433    {
1434      int nbData = 0;
1435      int rank = connectedServerRank_[k];
1436      it = indSrv_.find(rank);
1437      if (iteMap != it)
1438        nbData = it->second.size();
1439
1440      list_lon.push_back(CArray<double,1>(nbData));
1441      list_lat.push_back(CArray<double,1>(nbData));
1442
1443      if (hasBounds)
1444      {
1445        list_boundslon.push_back(CArray<double,2>(nvertex, nbData));
1446        list_boundslat.push_back(CArray<double,2>(nvertex, nbData));
1447      }
1448
1449      CArray<double,1>& lon = list_lon.back();
1450      CArray<double,1>& lat = list_lat.back();
1451      const std::vector<size_t>& temp = it->second;
1452      for (n = 0; n < nbData; ++n)
1453      {
1454        idx = static_cast<int>(it->second[n]);
1455        lon(n) = lonvalue_client(idx);
1456        lat(n) = latvalue_client(idx);
1457
1458        if (hasBounds)
1459        {
1460          CArray<double,2>& boundslon = list_boundslon.back();
1461          CArray<double,2>& boundslat = list_boundslat.back();
1462
1463          for (nv = 0; nv < nvertex; ++nv)
1464          {
1465            boundslon(nv, n) = bounds_lon_client(nv, idx);
1466            boundslat(nv, n) = bounds_lat_client(nv, idx);
1467          }
1468        }
1469      }
1470
1471      list_msgsLon.push_back(CMessage());
1472      list_msgsLat.push_back(CMessage());
1473
1474      list_msgsLon.back() << this->getId() << list_lon.back();
1475      list_msgsLat.back() << this->getId() << list_lat.back();
1476
1477      if (hasBounds)
1478      {
1479        list_msgsLon.back() << list_boundslon.back();
1480        list_msgsLat.back() << list_boundslat.back();
1481      }
1482
1483      eventLon.push(rank, nbConnectedClients_[rank], list_msgsLon.back());
1484      eventLat.push(rank, nbConnectedClients_[rank], list_msgsLat.back());
1485    }
1486
1487    client->sendEvent(eventLon);
1488    client->sendEvent(eventLat);
1489  }
1490
1491  /*!
1492    Send some optional information to server(s)
1493    In the future, this function can be extended with more optional information to send
1494  */
1495  void CDomain::sendLonLatArea(void)
1496  {
1497    sendIndex();
1498    sendLonLat();
1499    sendArea();
1500  }
1501
1502  bool CDomain::dispatchEvent(CEventServer& event)
1503  {
1504    if (SuperClass::dispatchEvent(event)) return true;
1505    else
1506    {
1507      switch(event.type)
1508      {
1509        case EVENT_ID_SERVER_ATTRIBUT:
1510          recvServerAttribut(event);
1511          return true;
1512          break;
1513        case EVENT_ID_INDEX:
1514          recvIndex(event);
1515          return true;
1516          break;
1517        case EVENT_ID_LON:
1518          recvLon(event);
1519          return true;
1520          break;
1521        case EVENT_ID_LAT:
1522          recvLat(event);
1523          return true;
1524          break;
1525        case EVENT_ID_AREA:
1526          recvArea(event);
1527          return true;
1528          break;
1529        default:
1530          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
1531                << "Unknown Event");
1532          return false;
1533       }
1534    }
1535  }
1536
1537  /*!
1538    Receive attributes event from clients(s)
1539    \param[in] event event contain info about rank and associated attributes
1540  */
1541  void CDomain::recvServerAttribut(CEventServer& event)
1542  {
1543    CBufferIn* buffer=event.subEvents.begin()->buffer;
1544    string domainId ;
1545    *buffer>>domainId ;
1546    get(domainId)->recvServerAttribut(*buffer) ;
1547  }
1548
1549  /*!
1550    Receive attributes from client(s): zoom info and begin and n of each server
1551    \param[in] rank rank of client source
1552    \param[in] buffer message containing attributes info
1553  */
1554  void CDomain::recvServerAttribut(CBufferIn& buffer)
1555  {
1556    buffer >> ni_srv >> ibegin_srv >> iend_srv >> nj_srv >> jbegin_srv >> jend_srv
1557           >> global_zoom_ni >> global_zoom_ibegin >> global_zoom_nj >> global_zoom_jbegin
1558           >> isCompressible_;
1559
1560    int zoom_iend = global_zoom_ibegin + global_zoom_ni - 1;
1561    int zoom_jend = global_zoom_jbegin + global_zoom_nj - 1;
1562
1563    zoom_ibegin_srv = global_zoom_ibegin > ibegin_srv ? global_zoom_ibegin : ibegin_srv ;
1564    zoom_iend_srv = zoom_iend < iend_srv ? zoom_iend : iend_srv ;
1565    zoom_ni_srv=zoom_iend_srv-zoom_ibegin_srv+1 ;
1566
1567    zoom_jbegin_srv = global_zoom_jbegin > jbegin_srv ? global_zoom_jbegin : jbegin_srv ;
1568    zoom_jend_srv = zoom_jend < jend_srv ? zoom_jend : jend_srv ;
1569    zoom_nj_srv=zoom_jend_srv-zoom_jbegin_srv+1 ;
1570
1571    if (zoom_ni_srv<=0 || zoom_nj_srv<=0)
1572    {
1573      zoom_ibegin_srv=0 ; zoom_iend_srv=0 ; zoom_ni_srv=0 ;
1574      zoom_jbegin_srv=0 ; zoom_jend_srv=0 ; zoom_nj_srv=0 ;
1575    }
1576    lonvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
1577    lonvalue_srv = 0. ;
1578    latvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
1579    latvalue_srv = 0. ;
1580    if (hasBounds)
1581    {
1582      bounds_lon_srv.resize(nvertex,zoom_ni_srv*zoom_nj_srv) ;
1583      bounds_lon_srv = 0. ;
1584      bounds_lat_srv.resize(nvertex,zoom_ni_srv*zoom_nj_srv) ;
1585      bounds_lat_srv = 0. ;
1586    }
1587
1588    if (hasArea)
1589      area_srv.resize(zoom_ni_srv * zoom_nj_srv);
1590  }
1591
1592  /*!
1593    Receive index event from clients(s)
1594    \param[in] event event contain info about rank and associated index
1595  */
1596  void CDomain::recvIndex(CEventServer& event)
1597  {
1598    CDomain* domain;
1599
1600    list<CEventServer::SSubEvent>::iterator it;
1601    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1602    {
1603      CBufferIn* buffer = it->buffer;
1604      string domainId;
1605      *buffer >> domainId;
1606      domain = get(domainId);
1607      domain->recvIndex(it->rank, *buffer);
1608    }
1609
1610    if (domain->isCompressible_)
1611    {
1612      std::sort(domain->indexesToWrite.begin(), domain->indexesToWrite.end());
1613
1614      CContextServer* server = CContext::getCurrent()->server;
1615      domain->numberWrittenIndexes_ = domain->indexesToWrite.size();
1616      MPI_Allreduce(&domain->numberWrittenIndexes_, &domain->totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1617      MPI_Scan(&domain->numberWrittenIndexes_, &domain->offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1618      domain->offsetWrittenIndexes_ -= domain->numberWrittenIndexes_;
1619    }
1620  }
1621
1622  /*!
1623    Receive index information from client(s)
1624    \param[in] rank rank of client source
1625    \param[in] buffer message containing index info
1626  */
1627  void CDomain::recvIndex(int rank, CBufferIn& buffer)
1628  {
1629    int type_int;
1630    buffer >> type_int >> isCurvilinear >> indiSrv[rank] >> indjSrv[rank];
1631    type.setValue((type_attr::t_enum)type_int); // probleme des type enum avec les buffers : ToFix
1632
1633    if (isCompressible_)
1634    {
1635      CArray<int, 1> writtenIndexes;
1636      buffer >> writtenIndexes;
1637      indexesToWrite.reserve(indexesToWrite.size() + writtenIndexes.numElements());
1638      for (int i = 0; i < writtenIndexes.numElements(); ++i)
1639        indexesToWrite.push_back(writtenIndexes(i));
1640    }
1641  }
1642
1643  /*!
1644    Receive longitude event from clients(s)
1645    \param[in] event event contain info about rank and associated longitude
1646  */
1647  void CDomain::recvLon(CEventServer& event)
1648  {
1649    list<CEventServer::SSubEvent>::iterator it;
1650    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1651    {
1652      CBufferIn* buffer = it->buffer;
1653      string domainId;
1654      *buffer >> domainId;
1655      get(domainId)->recvLon(it->rank, *buffer);
1656    }
1657  }
1658
1659  /*!
1660    Receive longitude information from client(s)
1661    \param[in] rank rank of client source
1662    \param[in] buffer message containing longitude info
1663  */
1664  void CDomain::recvLon(int rank, CBufferIn& buffer)
1665  {
1666    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1667    CArray<double,1> lon;
1668    CArray<double,2> boundslon;
1669
1670    buffer >> lon;
1671    if (hasBounds) buffer >> boundslon;
1672
1673    int i, j, ind_srv;
1674    for (int ind = 0; ind < indi.numElements(); ind++)
1675    {
1676      i = indi(ind); j = indj(ind);
1677      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1678      lonvalue_srv(ind_srv) = lon(ind);
1679      if (hasBounds)
1680      {
1681        for (int nv = 0; nv < nvertex; ++nv)
1682          bounds_lon_srv(nv, ind_srv) = boundslon(nv, ind);
1683      }
1684    }
1685  }
1686
1687  /*!
1688    Receive latitude event from clients(s)
1689    \param[in] event event contain info about rank and associated latitude
1690  */
1691  void CDomain::recvLat(CEventServer& event)
1692  {
1693    list<CEventServer::SSubEvent>::iterator it;
1694    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1695    {
1696      CBufferIn* buffer = it->buffer;
1697      string domainId;
1698      *buffer >> domainId;
1699      get(domainId)->recvLat(it->rank, *buffer);
1700    }
1701  }
1702
1703  /*!
1704    Receive latitude information from client(s)
1705    \param[in] rank rank of client source
1706    \param[in] buffer message containing latitude info
1707  */
1708  void CDomain::recvLat(int rank, CBufferIn& buffer)
1709  {
1710    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1711    CArray<double,1> lat;
1712    CArray<double,2> boundslat;
1713
1714    buffer >> lat;
1715    if (hasBounds) buffer >> boundslat;
1716
1717    int i, j, ind_srv;
1718    for (int ind = 0; ind < indi.numElements(); ind++)
1719    {
1720      i = indi(ind); j = indj(ind);
1721      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1722      latvalue_srv(ind_srv) = lat(ind);
1723      if (hasBounds)
1724      {
1725        for (int nv = 0; nv < nvertex; nv++)
1726          bounds_lat_srv(nv, ind_srv) = boundslat(nv, ind);
1727      }
1728    }
1729  }
1730
1731  /*!
1732    Receive area event from clients(s)
1733    \param[in] event event contain info about rank and associated area
1734  */
1735  void CDomain::recvArea(CEventServer& event)
1736  {
1737    list<CEventServer::SSubEvent>::iterator it;
1738    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1739    {
1740      CBufferIn* buffer = it->buffer;
1741      string domainId;
1742      *buffer >> domainId;
1743      get(domainId)->recvArea(it->rank, *buffer);
1744    }
1745  }
1746
1747  /*!
1748    Receive area information from client(s)
1749    \param[in] rank rank of client source
1750    \param[in] buffer message containing area info
1751  */
1752  void CDomain::recvArea(int rank, CBufferIn& buffer)
1753  {
1754    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1755    CArray<double,1> clientArea;
1756
1757    buffer >> clientArea;
1758
1759    int i, j, ind_srv;
1760    for (int ind = 0; ind < indi.numElements(); ind++)
1761    {
1762      i = indi(ind); j = indj(ind);
1763      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1764      area_srv(ind_srv) = clientArea(ind);
1765    }
1766  }
1767
1768  /*!
1769    Check whether a domain has transformation
1770    \return true if domain has transformation
1771  */
1772  bool CDomain::hasTransformation()
1773  {
1774    return (!transformationMap_.empty());
1775  }
1776
1777  /*!
1778    Set transformation for current domain. It's the method to move transformation in hierarchy
1779    \param [in] domTrans transformation on domain
1780  */
1781  void CDomain::setTransformations(const TransMapTypes& domTrans)
1782  {
1783    transformationMap_ = domTrans;
1784  }
1785
1786  /*!
1787    Get all transformation current domain has
1788    \return all transformation
1789  */
1790  CDomain::TransMapTypes CDomain::getAllTransformations(void)
1791  {
1792    return transformationMap_;
1793  }
1794
1795  /*!
1796    Check the validity of all transformations applied on domain
1797  This functions is called AFTER all inherited attributes are solved
1798  */
1799  void CDomain::checkTransformations()
1800  {
1801    TransMapTypes::const_iterator itb = transformationMap_.begin(), it,
1802                                  ite = transformationMap_.end();
1803    for (it = itb; it != ite; ++it)
1804    {
1805      (it->second)->checkValid(this);
1806    }
1807  }
1808
1809  /*!
1810   * Go through the hierarchy to find the domain from which the transformations must be inherited
1811   */
1812  void CDomain::solveInheritanceTransformation()
1813  {
1814    if (hasTransformation() || !hasDirectDomainReference())
1815      return;
1816
1817    CDomain* domain = this;
1818    std::vector<CDomain*> refDomains;
1819    while (!domain->hasTransformation() && domain->hasDirectDomainReference())
1820    {
1821      refDomains.push_back(domain);
1822      domain = domain->getDirectDomainReference();
1823    }
1824
1825    if (domain->hasTransformation())
1826      for (size_t i = 0; i < refDomains.size(); ++i)
1827        refDomains[i]->setTransformations(domain->getAllTransformations());
1828
1829    // Try to inherit the id of the referenced object as the domain name
1830    // when no name was been defined and a defaut id is used.
1831    if (name.isEmpty())
1832    {
1833      static const std::string defId("__domain_undef_id_");
1834      const std::string& id = getId();
1835      if (id.size() > defId.size() && id.compare(0, defId.size(), defId) == 0)
1836        name = domain->getId();
1837    }
1838  }
1839
1840  void CDomain::solveSrcInheritance()
1841  {
1842    if (!domain_src.isEmpty())
1843    {
1844       if (!CDomain::has(this->domain_src.getValue()))                                   \
1845          ERROR("CDomain::solveSrcInheritance()",                                \
1846             << "[ src_name = " << this->domain_src.getValue() << "]"                 \
1847             << " invalid domain name !");
1848
1849       srcObject_ = CDomain::get(this->domain_src.getValue());
1850    }
1851  }
1852
1853  CDomain* CDomain::getDomainSrc()
1854  {
1855    return srcObject_;
1856  }
1857
1858  /*!
1859    Parse children nodes of a domain in xml file.
1860    Whenver there is a new transformation, its type and name should be added into this function
1861    \param node child node to process
1862  */
1863  void CDomain::parse(xml::CXMLNode & node)
1864  {
1865    SuperClass::parse(node);
1866
1867    if (node.goToChildElement())
1868    {
1869      StdString zoomDomainDefRoot("zoom_domain_definition");
1870      StdString zoom("zoom_domain");
1871      StdString interpDomainDefRoot("interpolate_domain_definition");
1872      StdString interpFromFile("interpolate_domain");
1873      StdString generateRectilinearDefRoot("generate_rectilinear_domain_definition");
1874      StdString generateRectilinear("generate_rectilinear_domain");
1875      do
1876      {
1877        if (node.getElementName() == zoom) {
1878          CZoomDomain* tmp = (CZoomDomainGroup::get(zoomDomainDefRoot))->createChild();
1879          tmp->parse(node);
1880          transformationMap_.push_back(std::make_pair(TRANS_ZOOM_DOMAIN,tmp));
1881        }
1882        else if (node.getElementName() == interpFromFile)
1883        {
1884          CInterpolateDomain* tmp = (CInterpolateDomainGroup::get(interpDomainDefRoot))->createChild();
1885          tmp->parse(node);
1886          transformationMap_.push_back(std::make_pair(TRANS_INTERPOLATE_DOMAIN,tmp));
1887        }
1888        else if (node.getElementName() == generateRectilinear)
1889        {
1890          CGenerateRectilinearDomain* tmp = (CGenerateRectilinearDomainGroup::get(generateRectilinearDefRoot))->createChild();
1891          tmp->parse(node);
1892          transformationMap_.push_back(std::make_pair(TRANS_GENERATE_RECTILINEAR_DOMAIN,tmp));
1893        }
1894      } while (node.goToNextElement()) ;
1895      node.goToParentElement();
1896    }
1897  }
1898   //----------------------------------------------------------------
1899
1900   DEFINE_REF_FUNC(Domain,domain)
1901
1902   ///---------------------------------------------------------------
1903
1904} // namespace xios
Note: See TracBrowser for help on using the repository browser.