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

Last change on this file since 734 was 734, checked in by mhnguyen, 9 years ago

Correcting a bug concerning the range of longitude and latitude of auto-generated domain

+) Modify range of auto-generated longitude and latitude
+) Update test_remap

Test
+) On Curie
+) auto-generating domain source and domain dest
+) result is correct

  • 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.8 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(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   {
379     int i,j,k;
380     const int nvertexValue = 4;
381
382     double boundsLonRange = bounds_lon_end - bounds_lon_start;
383     double boundsLatRange = bounds_lat_end - bounds_lat_start;
384
385     boundsLon.resize(nvertexValue,ni*nj);
386     boundsLat.resize(nvertexValue,nj*ni);
387
388     double lonStep = boundsLonRange/double(ni_glo.getValue());
389     double latStep = boundsLatRange/double(nj_glo.getValue());
390
391     for(j=0;j<nj;++j)
392       for(i=0;i<ni;++i)
393       {
394         k=j*ni+i;
395         boundsLon(0,k) = boundsLon(1,k) = (0 != (ibegin + i)) ? (ibegin + i) * lonStep + bounds_lon_start
396                                                               : bounds_lon_start;
397         boundsLon(2,k) = boundsLon(3,k) = ((ibegin + i + 1) != ni_glo) ? (ibegin + i +1) * lonStep + bounds_lon_start
398                                                                        : bounds_lon_end;
399
400         boundsLat(1,k) = boundsLat(2,k) = (0 != (jbegin + j)) ? (jbegin + j) * latStep + bounds_lat_start
401                                                               : bounds_lat_start;
402         boundsLat(0,k) = boundsLat(3,k) = ((jbegin + j +1) != nj_glo) ? (jbegin + j +1) * latStep + bounds_lat_start
403                                                               : bounds_lat_end;
404       }
405   }
406
407   /*!
408     Temporary function to verify whether a rectilinear domain is created automatically.
409   The domain is distributed into number of parts which are equal to number of clients (intracomm)
410   */
411   void CDomain::checkGenerate()
412   {
413     TransMapTypes trans = this->getAllTransformations();
414     TransMapTypes::const_iterator it = trans.begin(), ite = trans.end();
415     int transOrder = 0;
416     for (; it != ite; ++it, ++transOrder)
417     {
418       ETranformationType transType = it->first;
419       if ((TRANS_GENERATE_RECTILINEAR_DOMAIN == transType) && (0 == transOrder))
420       {
421         CContext* context = CContext::getCurrent();
422         CContextClient* client = context->client;
423         int nbClient;
424         MPI_Comm_size(client->intraComm,&nbClient);
425         it->second->checkValid(this);
426         this->redistribute(nbClient);
427         break;
428       }
429     }
430   }
431
432
433   void CDomain::checkDomain(void)
434   {
435     if (type.isEmpty())
436     {
437       ERROR("CDomain::checkDomain(void)",
438             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
439             << "The domain type is mandatory, "
440             << "please define the 'type' attribute.")
441     }
442
443     if (type == type_attr::unstructured)
444     {
445        if (ni_glo.isEmpty())
446        {
447          ERROR("CDomain::checkDomain(void)",
448                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
449                << "The global domain is badly defined, "
450                << "the mandatory 'ni_glo' attribute is missing.")
451        }
452        else if (ni_glo <= 0)
453        {
454          ERROR("CDomain::checkDomain(void)",
455                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
456                << "The global domain is badly defined, "
457                << "'ni_glo' attribute should be strictly positive so 'ni_glo = " << ni_glo.getValue() << "' is invalid.")
458        }
459        isUnstructed_ = true;
460        nj_glo = 1;
461        nj = 1;
462        jbegin = 0;
463        if (ni.isEmpty()) ni = i_index.numElements();
464        j_index.resize(ni);
465        for(int i=0;i<ni;++i) j_index(i)=0;
466
467        if (!area.isEmpty())
468          area.transposeSelf(1, 0);
469     }
470
471     if (ni_glo.isEmpty())
472     {
473       ERROR("CDomain::checkDomain(void)",
474             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
475             << "The global domain is badly defined, "
476             << "the mandatory 'ni_glo' attribute is missing.")
477     }
478     else if (ni_glo <= 0)
479     {
480       ERROR("CDomain::checkDomain(void)",
481             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
482             << "The global domain is badly defined, "
483             << "'ni_glo' attribute should be strictly positive so 'ni_glo = " << ni_glo.getValue() << "' is invalid.")
484     }
485
486     if (nj_glo.isEmpty())
487     {
488       ERROR("CDomain::checkDomain(void)",
489             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
490             << "The global domain is badly defined, "
491             << "the mandatory 'nj_glo' attribute is missing.")
492     }
493     else if (nj_glo <= 0)
494     {
495       ERROR("CDomain::checkDomain(void)",
496             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
497             << "The global domain is badly defined, "
498             << "'nj_glo' attribute should be strictly positive so 'nj_glo = " << nj_glo.getValue() << "' is invalid.")
499     }
500
501     isDistributed_ = !ibegin.isEmpty() || !ni.isEmpty() || !jbegin.isEmpty() || !nj.isEmpty();
502
503     checkLocalIDomain();
504     checkLocalJDomain();
505
506     if (i_index.isEmpty())
507     {
508       i_index.resize(ni*nj);
509       for (int j = 0; j < nj; ++j)
510         for (int i = 0; i < ni; ++i) i_index(i+j*ni) = i+ibegin;
511     }
512
513     if (j_index.isEmpty())
514     {
515       j_index.resize(ni*nj);
516       for (int j = 0; j < nj; ++j)
517         for (int i = 0; i < ni; ++i) j_index(i+j*ni) = j+jbegin;
518     }
519     computeNGlobDomain();
520
521     if (0 == global_zoom_ni) global_zoom_ni = ni_glo;
522     if (0 == global_zoom_nj) global_zoom_nj = nj_glo;
523   }
524
525   //----------------------------------------------------------------
526
527   void CDomain::checkLocalIDomain(void)
528   {
529      if (ibegin.isEmpty() && ni.isEmpty())
530      {
531        ibegin = 0;
532        ni = ni_glo;
533      }
534      else if (!i_index.isEmpty())
535      {
536        if (ibegin.isEmpty()) ibegin = i_index(0);
537      }
538
539      if (ni.getValue() < 0 || ibegin.getValue() < 0 ||
540         (ibegin.getValue() + ni.getValue()) > ni_glo.getValue())
541      {
542        ERROR("CDomain::checkLocalIDomain(void)",
543              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
544              << "The local domain is wrongly defined,"
545              << " check the attributes 'ni_glo' (" << ni_glo.getValue() << "), 'ni' (" << ni.getValue() << ") and 'ibegin' (" << ibegin.getValue() << ")");
546      }
547   }
548
549   void CDomain::checkLocalJDomain(void)
550   {
551     if (jbegin.isEmpty() && nj.isEmpty())
552     {
553       jbegin = 0;
554       nj = nj_glo;
555     }
556     else if (!j_index.isEmpty())
557     {
558       if (jbegin.isEmpty()) jbegin = j_index(0);
559     }
560
561      if (nj.getValue() < 0 || jbegin.getValue() < 0 ||
562         (jbegin.getValue() + nj.getValue()) > nj_glo.getValue())
563      {
564        ERROR("CDomain::checkLocalJDomain(void)",
565              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
566              << "The local domain is wrongly defined,"
567              << " check the attributes 'nj_glo' (" << nj_glo.getValue() << "), 'nj' (" << nj.getValue() << ") and 'jbegin' (" << jbegin.getValue() << ")");
568      }
569   }
570
571   //----------------------------------------------------------------
572
573   void CDomain::checkMask(void)
574   {
575      if (!mask_1d.isEmpty() && !mask_2d.isEmpty())
576        ERROR("CDomain::checkMask(void)",
577              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
578              << "Both mask_1d and mask_2d are defined but only one can be used at the same time." << std::endl
579              << "Please define only one mask: 'mask_1d' or 'mask_2d'.");
580
581      if (!mask_1d.isEmpty() && mask_2d.isEmpty())
582      {
583        if (mask_1d.numElements() != i_index.numElements())
584          ERROR("CDomain::checkMask(void)",
585                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
586                << "'mask_1d' does not have the same size as the local domain." << std::endl
587                << "Local size is " << i_index.numElements() << "." << std::endl
588                << "Mask size is " << mask_1d.numElements() << ".");
589      }
590
591      if (mask_1d.isEmpty() && !mask_2d.isEmpty())
592      {
593        if (mask_2d.extent(0) != ni || mask_2d.extent(1) != nj)
594          ERROR("CDomain::checkMask(void)",
595                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
596                << "The mask does not have the same size as the local domain." << std::endl
597                << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
598                << "Mask size is " << mask_2d.extent(0) << " x " << mask_2d.extent(1) << ".");
599      }
600
601      if (!mask_2d.isEmpty())
602      {
603        mask_1d.resize(mask_2d.extent(0) * mask_2d.extent(1));
604        for (int j = 0; j < nj; ++j)
605          for (int i = 0; i < ni; ++i) mask_1d(i+j*ni) = mask_2d(i,j);
606        mask_2d.free();
607      }
608      else if (mask_1d.isEmpty())
609      {
610        mask_1d.resize(i_index.numElements());
611        for (int i = 0; i < i_index.numElements(); ++i) mask_1d(i) = true;
612      }
613   }
614
615   //----------------------------------------------------------------
616
617   void CDomain::checkDomainData(void)
618   {
619      if (data_dim.isEmpty())
620      {
621        data_dim.setValue(1);
622      }
623      else if (!(data_dim.getValue() == 1 || data_dim.getValue() == 2))
624      {
625        ERROR("CDomain::checkDomainData(void)",
626              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
627              << "The data dimension is invalid, 'data_dim' must be 1 or 2 not << " << data_dim.getValue() << ".");
628      }
629
630      if (data_ibegin.isEmpty())
631         data_ibegin.setValue(0);
632      if (data_jbegin.isEmpty())
633         data_jbegin.setValue(0);
634
635      if (data_ni.isEmpty())
636      {
637        data_ni.setValue((data_dim == 1) ? (ni.getValue() * nj.getValue()) : ni.getValue());
638      }
639      else if (data_ni.getValue() < 0)
640      {
641        ERROR("CDomain::checkDomainData(void)",
642              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
643              << "The data size cannot be negative ('data_ni' = " << data_ni.getValue() << ").");
644      }
645
646      if (data_nj.isEmpty())
647      {
648        data_nj.setValue((data_dim.getValue() == 1) ? (ni.getValue() * nj.getValue()) : nj.getValue());
649      }
650      else if (data_nj.getValue() < 0)
651      {
652        ERROR("CDomain::checkDomainData(void)",
653              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
654              << "The data size cannot be negative ('data_nj' = " << data_nj.getValue() << ").");
655      }
656   }
657
658   //----------------------------------------------------------------
659
660   void CDomain::checkCompression(void)
661   {
662      if (!data_i_index.isEmpty())
663      {
664        if (!data_j_index.isEmpty() &&
665            data_j_index.numElements() != data_i_index.numElements())
666        {
667           ERROR("CDomain::checkCompression(void)",
668                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
669                 << "'data_i_index' and 'data_j_index' arrays must have the same size." << std::endl
670                 << "'data_i_index' size = " << data_i_index.numElements() << std::endl
671                 << "'data_j_index' size = " << data_j_index.numElements());
672        }
673
674        if (2 == data_dim)
675        {
676          if (data_j_index.isEmpty())
677          {
678             ERROR("CDomain::checkCompression(void)",
679                   << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
680                   << "'data_j_index' must be defined when 'data_i_index' is set and 'data_dim' is 2.");
681          }
682        }
683        else // (1 == data_dim)
684        {
685          if (data_j_index.isEmpty())
686          {
687            data_j_index.resize(data_ni);
688            for (int j = 0; j < data_ni; ++j) data_j_index(j) = 0;
689          }
690        }
691      }
692      else
693      {
694        if (data_dim == 2 && !data_j_index.isEmpty())
695          ERROR("CDomain::checkCompression(void)",
696                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
697                << "'data_i_index' must be defined when 'data_j_index' is set and 'data_dim' is 2.");
698
699        if (1 == data_dim)
700        {
701          data_i_index.resize(data_ni);
702          data_j_index.resize(data_ni);
703
704          for (int i = 0; i < data_ni; ++i)
705          {
706            data_i_index(i) = i;
707            data_j_index(i) = 0;
708          }
709        }
710        else // (data_dim == 2)
711        {
712          const int dsize = data_ni * data_nj;
713          data_i_index.resize(dsize);
714          data_j_index.resize(dsize);
715
716          for(int count = 0, j = 0; j < data_nj; ++j)
717          {
718            for(int i = 0; i < data_ni; ++i, ++count)
719            {
720              data_i_index(count) = i;
721              data_j_index(count) = j;
722            }
723          }
724        }
725      }
726   }
727
728   //----------------------------------------------------------------
729
730   void CDomain::checkEligibilityForCompressedOutput(void)
731   {
732     // We don't check if the mask or the indexes are valid here, just if they have been defined at this point.
733     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !data_i_index.isEmpty();
734   }
735
736   //----------------------------------------------------------------
737
738   void CDomain::completeLonLatClient(void)
739   {
740     int i,j,k ;
741     CArray<double,1> lonvalue_temp(ni * nj);
742     CArray<double,2> bounds_lon_temp(nvertex, ni * nj);
743     CArray<double,1> latvalue_temp(ni * nj);
744     CArray<double,2> bounds_lat_temp(nvertex, ni * nj);
745
746     if (!lonvalue_2d.isEmpty())
747     {
748        for (j = 0; j < nj; ++j)
749          for (i = 0; i < ni; ++i)
750          {
751            lonvalue_temp(i + j * ni) = lonvalue_2d(i,j);
752            latvalue_temp(i + j * ni) = latvalue_2d(i,j);
753            if (hasBounds)
754            {
755              k = j * ni + i;
756              for (int n = 0; n < nvertex; ++n)
757              {
758                bounds_lon_temp(n,k) = bounds_lon_2d(n,i,j);
759                bounds_lat_temp(n,k) = bounds_lat_2d(n,i,j);
760              }
761            }
762          }
763        lonvalue_1d.free();
764     }
765
766     if (!lonvalue_1d.isEmpty())
767     {
768       if (type_attr::rectilinear == type)
769       {
770         if (ni == lonvalue_1d.numElements() && nj == latvalue_1d.numElements())
771         {
772           for (j = 0; j < nj; ++j)
773             for (i = 0; i < ni; ++i)
774             {
775               k = j * ni + i;
776               lonvalue_temp(k) = lonvalue_1d(i);
777               latvalue_temp(k) = latvalue_1d(j);
778               if (hasBounds)
779               {
780                 for (int n = 0; n < nvertex; ++n)
781                 {
782                   bounds_lon_temp(n,k) = bounds_lon_1d(n,i);
783                   bounds_lat_temp(n,k) = bounds_lat_1d(n,j);
784                 }
785               }
786             }
787          }
788          else
789            ERROR("CDomain::completeLonClient(void)",
790                  << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
791                  << "'lonvalue_1d' and 'latvalue_1d' does not have the same size as the local domain." << std::endl
792                  << "'lonvalue_1d' size is " << lonvalue_1d.numElements() << " but it should be " << ni.getValue() << '.' << std::endl
793                  << "'latvalue_1d' size is " << latvalue_1d.numElements() << " but it should be " << nj.getValue() << '.');
794       }
795       else if (type == type_attr::curvilinear || type == type_attr::unstructured)
796       {
797         lonvalue_temp = lonvalue_1d;
798         latvalue_temp = latvalue_1d;
799         if (hasBounds)
800         {
801           bounds_lon_temp = bounds_lon_1d;
802           bounds_lat_temp = bounds_lat_1d;
803         }
804       }
805       lonvalue_2d.free();
806     }
807
808    int i_ind,j_ind;
809    int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1;
810    int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1;
811
812    int globalIndexCountZoom = 0;
813    int nbIndex = i_index.numElements();
814    for (i = 0; i < nbIndex; ++i)
815    {
816      i_ind=i_index(i);
817      j_ind=j_index(i);
818
819      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
820      {
821        ++globalIndexCountZoom;
822      }
823    }
824
825      // Make sure that this attribute is non-empty for every client.
826     if (0 != globalIndexCountZoom)
827     {
828       lonvalue_client.resize(globalIndexCountZoom);
829       latvalue_client.resize(globalIndexCountZoom);
830       if (hasBounds)
831       {
832         bounds_lon_client.resize(nvertex,globalIndexCountZoom);
833         bounds_lat_client.resize(nvertex,globalIndexCountZoom);
834       }
835     }
836
837     int nCountZoom = 0;
838     for (i = 0; i < nbIndex; ++i)
839     {
840       i_ind=i_index(i);
841       j_ind=j_index(i);
842
843       if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
844       {
845         lonvalue_client(nCountZoom) = lonvalue_temp(i);
846         latvalue_client(nCountZoom) = latvalue_temp(i);
847         if (hasBounds)
848         {
849           for (int n = 0; n < nvertex; ++n)
850           {
851             bounds_lon_client(n,nCountZoom) = bounds_lon_temp(n,i);
852             bounds_lat_client(n,nCountZoom) = bounds_lat_temp(n,i);
853           }
854         }
855         ++nCountZoom;
856       }
857     }
858   }
859
860   void CDomain::checkBounds(void)
861   {
862     if (!nvertex.isEmpty() && nvertex > 0)
863     {
864       if (!bounds_lon_1d.isEmpty() && !bounds_lon_2d.isEmpty())
865         ERROR("CDomain::checkBounds(void)",
866               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
867               << "Only one longitude boundary attribute can be used but both 'bounds_lon_1d' and 'bounds_lon_2d' are defined." << std::endl
868               << "Define only one longitude boundary attribute: 'bounds_lon_1d' or 'bounds_lon_2d'.");
869
870       if (!bounds_lat_1d.isEmpty() && !bounds_lat_2d.isEmpty())
871         ERROR("CDomain::checkBounds(void)",
872               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
873               << "Only one latitude boundary attribute can be used but both 'bounds_lat_1d' and 'bounds_lat_2d' are defined." << std::endl
874               << "Define only one latitude boundary attribute: 'bounds_lat_1d' or 'bounds_lat_2d'.");
875
876       if ((!bounds_lon_1d.isEmpty() && bounds_lat_1d.isEmpty()) || (bounds_lon_1d.isEmpty() && !bounds_lat_1d.isEmpty()))
877       {
878         ERROR("CDomain::checkBounds(void)",
879               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
880               << "Only 'bounds_lon_1d' or 'bounds_lat_1d' is defined." << std::endl
881               << "Please define either both attributes or none.");
882       }
883
884       if ((!bounds_lon_2d.isEmpty() && bounds_lat_2d.isEmpty()) || (bounds_lon_2d.isEmpty() && !bounds_lat_2d.isEmpty()))
885       {
886         ERROR("CDomain::checkBounds(void)",
887               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
888               << "Only 'bounds_lon_2d' or 'bounds_lat_2d' is defined." << std::endl
889               << "Please define either both attributes or none.");
890       }
891
892       if (!bounds_lon_1d.isEmpty() && nvertex.getValue() != bounds_lon_1d.extent(0))
893         ERROR("CDomain::checkBounds(void)",
894               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
895               << "'bounds_lon_1d' dimension is not compatible with 'nvertex'." << std::endl
896               << "'bounds_lon_1d' dimension is " << bounds_lon_1d.extent(1)
897               << " but nvertex is " << nvertex.getValue() << ".");
898
899       if (!bounds_lon_2d.isEmpty() && nvertex.getValue() != bounds_lon_2d.extent(0))
900         ERROR("CDomain::checkBounds(void)",
901               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
902               << "'bounds_lon_2d' dimension is not compatible with 'nvertex'." << std::endl
903               << "'bounds_lon_2d' dimension is " << bounds_lon_2d.extent(2)
904               << " but nvertex is " << nvertex.getValue() << ".");
905
906       if (!bounds_lon_1d.isEmpty() && lonvalue_1d.isEmpty())
907         ERROR("CDomain::checkBounds(void)",
908               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
909               << "Since 'bounds_lon_1d' is defined, 'lonvalue_1d' must be defined too." << std::endl);
910
911       if (!bounds_lon_2d.isEmpty() && lonvalue_2d.isEmpty())
912         ERROR("CDomain::checkBounds(void)",
913               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
914               << "Since 'bounds_lon_2d' is defined, 'lonvalue_2d' must be defined too." << std::endl);
915
916       if (!bounds_lat_1d.isEmpty() && nvertex.getValue() != bounds_lat_1d.extent(0))
917         ERROR("CDomain::checkBounds(void)",
918               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
919               << "'bounds_lat_1d' dimension is not compatible with 'nvertex'." << std::endl
920               << "'bounds_lat_1d' dimension is " << bounds_lat_1d.extent(1)
921               << " but nvertex is " << nvertex.getValue() << ".");
922
923       if (!bounds_lat_2d.isEmpty() && nvertex.getValue() != bounds_lat_2d.extent(0))
924         ERROR("CDomain::checkBounds(void)",
925               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
926               << "'bounds_lat_2d' dimension is not compatible with 'nvertex'." << std::endl
927               << "'bounds_lat_2d' dimension is " << bounds_lat_2d.extent(2)
928               << " but nvertex is " << nvertex.getValue() << ".");
929
930       if (!bounds_lat_1d.isEmpty() && latvalue_1d.isEmpty())
931         ERROR("CDomain::checkBounds(void)",
932               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
933               << "Since 'bounds_lat_1d' is defined, 'latvalue_1d' must be defined too." << std::endl);
934
935       if (!bounds_lat_2d.isEmpty() && latvalue_2d.isEmpty())
936         ERROR("CDomain::checkBounds(void)",
937               << "Since 'bounds_lat_2d' is defined, 'latvalue_2d' must be defined too." << std::endl);
938
939       hasBounds = true;
940     }
941     else
942     {
943       hasBounds = false;
944       nvertex = 0;
945     }
946   }
947
948   void CDomain::checkArea(void)
949   {
950     hasArea = !area.isEmpty();
951     if (hasArea)
952     {
953       if (area.extent(0) != ni || area.extent(1) != nj)
954       {
955         ERROR("CDomain::checkArea(void)",
956               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
957               << "The area does not have the same size as the local domain." << std::endl
958               << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
959               << "Area size is " << area.extent(0) << " x " << area.extent(1) << ".");
960       }
961     }
962   }
963
964   void CDomain::checkLonLat()
965   {
966     hasLonLat = (!latvalue_1d.isEmpty() && !lonvalue_1d.isEmpty()) ||
967                 (!latvalue_2d.isEmpty() && !lonvalue_2d.isEmpty());
968     if (hasLonLat)
969     {
970       if (!lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
971         ERROR("CDomain::completeLonLatClient(void)",
972               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
973               << "Only one longitude attribute can be used but both 'lonvalue_1d' and 'lonvalue_2d' are defined." << std::endl
974               << "Define only one longitude attribute: 'lonvalue_1d' or 'lonvalue_2d'.");
975
976       if (!lonvalue_1d.isEmpty() && lonvalue_2d.isEmpty())
977       {
978         if ((type_attr::rectilinear != type) && (lonvalue_1d.numElements() != i_index.numElements()))
979           ERROR("CDomain::completeLonLatClient(void)",
980                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
981                 << "'lonvalue_1d' does not have the same size as the local domain." << std::endl
982                 << "Local size is " << i_index.numElements() << "." << std::endl
983                 << "'lonvalue_1d' size is " << lonvalue_1d.numElements() << ".");
984       }
985
986       if (lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
987       {
988         if (lonvalue_2d.extent(0) != ni || lonvalue_2d.extent(1) != nj)
989           ERROR("CDomain::completeLonLatClient(void)",
990                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
991                 << "'lonvalue_2d' does not have the same size as the local domain." << std::endl
992                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
993                 << "'lonvalue_2d' size is " << lonvalue_2d.extent(0) << " x " << lonvalue_2d.extent(1) << ".");
994       }
995
996       if (!latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
997         ERROR("CDomain::completeLonLatClient(void)",
998               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
999               << "Only one latitude attribute can be used but both 'latvalue_1d' and 'latvalue_2d' are defined." << std::endl
1000               << "Define only one latitude attribute: 'latvalue_1d' or 'latvalue_2d'.");
1001
1002       if (!latvalue_1d.isEmpty() && latvalue_2d.isEmpty())
1003       {
1004         if ((type_attr::rectilinear != type) && (latvalue_1d.numElements() != i_index.numElements()))
1005           ERROR("CDomain::completeLonLatClient(void)",
1006                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1007                 << "'latvalue_1d' does not have the same size as the local domain." << std::endl
1008                 << "Local size is " << i_index.numElements() << "." << std::endl
1009                 << "'latvalue_1d' size is " << latvalue_1d.numElements() << ".");
1010       }
1011
1012       if (latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
1013       {
1014         if (latvalue_2d.extent(0) != ni || latvalue_2d.extent(1) != nj)
1015           ERROR("CDomain::completeLonLatClient(void)",
1016                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1017                 << "'latvalue_2d' does not have the same size as the local domain." << std::endl
1018                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1019                 << "'latvalue_2d' size is " << latvalue_2d.extent(0) << " x " << latvalue_2d.extent(1) << ".");
1020       }
1021     }
1022   }
1023
1024   void CDomain::checkAttributesOnClientAfterTransformation()
1025   {
1026     CContext* context=CContext::getCurrent() ;
1027
1028     if (this->isClientAfterTransformationChecked) return;
1029     if (context->hasClient)
1030     {
1031       this->checkMask();
1032       if (hasLonLat || hasArea) this->computeConnectedServer();
1033       if (hasLonLat) this->completeLonLatClient();
1034     }
1035
1036     this->isClientAfterTransformationChecked = true;
1037   }
1038
1039   //----------------------------------------------------------------
1040   // Divide function checkAttributes into 2 seperate ones
1041   // This function only checks all attributes of current domain
1042   void CDomain::checkAttributesOnClient()
1043   {
1044     if (this->isClientChecked) return;
1045     CContext* context=CContext::getCurrent();
1046
1047      this->checkGenerate();
1048      this->checkDomain();
1049      this->checkBounds();
1050      this->checkArea();
1051      this->checkLonLat();
1052
1053      if (context->hasClient)
1054      { // CÃŽté client uniquement
1055         this->checkMask();
1056         this->checkDomainData();
1057         this->checkCompression();
1058      }
1059      else
1060      { // CÃŽté serveur uniquement
1061      }
1062
1063      this->isClientChecked = true;
1064   }
1065
1066   // Send all checked attributes to server
1067   void CDomain::sendCheckedAttributes()
1068   {
1069     if (!this->isClientChecked) checkAttributesOnClient();
1070     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation();
1071     CContext* context=CContext::getCurrent() ;
1072
1073     if (this->isChecked) return;
1074     if (context->hasClient)
1075     {
1076       sendServerAttribut();
1077       if (hasLonLat || hasArea) sendLonLatArea();
1078     }
1079     this->isChecked = true;
1080   }
1081
1082   void CDomain::checkAttributes(void)
1083   {
1084      if (this->isChecked) return;
1085      CContext* context=CContext::getCurrent() ;
1086
1087      this->checkDomain();
1088      this->checkLonLat();
1089      this->checkBounds();
1090      this->checkArea();
1091
1092      if (context->hasClient)
1093      { // CÃŽté client uniquement
1094         this->checkMask();
1095         this->checkDomainData();
1096         this->checkCompression();
1097
1098      }
1099      else
1100      { // CÃŽté serveur uniquement
1101      }
1102
1103      if (context->hasClient)
1104      {
1105        this->computeConnectedServer();
1106        this->completeLonLatClient();
1107        this->sendServerAttribut();
1108        this->sendLonLatArea();
1109      }
1110
1111      this->isChecked = true;
1112   }
1113
1114  void CDomain::sendServerAttribut(void)
1115  {
1116    CServerDistributionDescription serverDescription(nGlobDomain_);
1117
1118    CContext* context = CContext::getCurrent();
1119    CContextClient* client = context->client;
1120    int nbServer = client->serverSize;
1121
1122    if (isUnstructed_) serverDescription.computeServerDistribution(nbServer,0);
1123    else serverDescription.computeServerDistribution(nbServer,1);
1124
1125    std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
1126    std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
1127
1128    CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT);
1129    if (client->isServerLeader())
1130    {
1131      std::list<CMessage> msgs;
1132
1133      const std::list<int>& ranks = client->getRanksServerLeader();
1134      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1135      {
1136        // Use const int to ensure CMessage holds a copy of the value instead of just a reference
1137        const int ibegin_srv = serverIndexBegin[*itRank][0];
1138        const int jbegin_srv = serverIndexBegin[*itRank][1];
1139        const int ni_srv = serverDimensionSizes[*itRank][0];
1140        const int nj_srv = serverDimensionSizes[*itRank][1];
1141        const int iend_srv = ibegin_srv + ni_srv - 1;
1142        const int jend_srv = jbegin_srv + nj_srv - 1;
1143
1144        msgs.push_back(CMessage());
1145        CMessage& msg = msgs.back();
1146        msg << this->getId() ;
1147        msg << ni_srv << ibegin_srv << iend_srv << nj_srv << jbegin_srv << jend_srv;
1148        msg << global_zoom_ni << global_zoom_ibegin << global_zoom_nj << global_zoom_jbegin;
1149        msg << isCompressible_;
1150
1151        event.push(*itRank,1,msg);
1152      }
1153      client->sendEvent(event);
1154    }
1155    else client->sendEvent(event);
1156  }
1157
1158  void CDomain::computeNGlobDomain()
1159  {
1160    nGlobDomain_.resize(2);
1161    nGlobDomain_[0] = ni_glo.getValue();
1162    nGlobDomain_[1] = nj_glo.getValue();
1163  }
1164
1165  void CDomain::computeConnectedServer(void)
1166  {
1167    CContext* context=CContext::getCurrent() ;
1168    CContextClient* client=context->client ;
1169    int nbServer=client->serverSize;
1170    bool doComputeGlobalIndexServer = true;
1171
1172    int i,j,i_ind,j_ind, nbIndex;
1173    int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1 ;
1174    int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1 ;
1175
1176    // Precompute number of index
1177    int globalIndexCountZoom = 0;
1178    nbIndex = i_index.numElements();
1179    for (i = 0; i < nbIndex; ++i)
1180    {
1181      i_ind=i_index(i);
1182      j_ind=j_index(i);
1183
1184      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1185      {
1186        ++globalIndexCountZoom;
1187      }
1188    }
1189
1190    int globalIndexWrittenCount = 0;
1191    if (isCompressible_)
1192    {
1193      for (i = 0; i < data_i_index.numElements(); ++i)
1194      {
1195        i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1196                                                    data_ibegin, data_jbegin, data_dim, ni,
1197                                                    j_ind);
1198        if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1199        {
1200          i_ind += ibegin;
1201          j_ind += jbegin;
1202          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1203            ++globalIndexWrittenCount;
1204        }
1205      }
1206    }
1207
1208    // Fill in index
1209    CArray<size_t,1> globalIndexDomainZoom(globalIndexCountZoom);
1210    CArray<size_t,1> localIndexDomainZoom(globalIndexCountZoom);
1211    CArray<size_t,1> globalIndexDomain(nbIndex);
1212    size_t globalIndex;
1213    int globalIndexCount = 0;
1214    globalIndexCountZoom = 0;
1215
1216    for (i = 0; i < nbIndex; ++i)
1217    {
1218      i_ind=i_index(i);
1219      j_ind=j_index(i);
1220      globalIndex = i_ind + j_ind * ni_glo;
1221      globalIndexDomain(globalIndexCount) = globalIndex;
1222      ++globalIndexCount;
1223      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1224      {
1225        globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
1226        localIndexDomainZoom(globalIndexCountZoom) = i;
1227        ++globalIndexCountZoom;
1228      }
1229    }
1230
1231    CArray<int,1> globalIndexWrittenDomain(globalIndexWrittenCount);
1232    if (isCompressible_)
1233    {
1234      globalIndexWrittenCount = 0;
1235      for (i = 0; i < data_i_index.numElements(); ++i)
1236      {
1237        i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
1238                                                    data_ibegin, data_jbegin, data_dim, ni,
1239                                                    j_ind);
1240        if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
1241        {
1242          i_ind += ibegin;
1243          j_ind += jbegin;
1244          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
1245          {
1246            globalIndexWrittenDomain(globalIndexWrittenCount) = i_ind + j_ind * ni_glo;
1247            ++globalIndexWrittenCount;
1248          }
1249        }
1250      }
1251    }
1252
1253    size_t globalSizeIndex = 1, indexBegin, indexEnd;
1254    int range, clientSize = client->clientSize;
1255    for (int i = 0; i < nGlobDomain_.size(); ++i) globalSizeIndex *= nGlobDomain_[i];
1256    indexBegin = 0;
1257    for (int i = 0; i < clientSize; ++i)
1258    {
1259      range = globalSizeIndex / clientSize;
1260      if (i < (globalSizeIndex%clientSize)) ++range;
1261      if (i == client->clientRank) break;
1262      indexBegin += range;
1263    }
1264    indexEnd = indexBegin + range - 1;
1265
1266    CServerDistributionDescription serverDescription(nGlobDomain_);
1267    if (isUnstructed_) serverDescription.computeServerGlobalIndexInRange(nbServer, std::make_pair<size_t,size_t>(indexBegin, indexEnd), 0);
1268    else serverDescription.computeServerGlobalIndexInRange(nbServer, std::make_pair<size_t,size_t>(indexBegin, indexEnd), 1);
1269
1270    CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(),
1271                                                                                client->intraComm);
1272    clientServerMap->computeServerIndexMapping(globalIndexDomain);
1273    const std::map<int, std::vector<size_t> >& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer();
1274
1275    std::map<int, std::vector<size_t> >::const_iterator it = globalIndexDomainOnServer.begin(),
1276                                                       ite = globalIndexDomainOnServer.end();
1277    typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
1278    std::vector<int>::iterator itVec;
1279
1280    indSrv_.clear();
1281    indWrittenSrv_.clear();
1282    for (; it != ite; ++it)
1283    {
1284      int rank = it->first;
1285      int indexSize = it->second.size();
1286      std::vector<int> permutIndex(indexSize);
1287      XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
1288      XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(it->second, permutIndex);
1289      BinarySearch binSearch(it->second);
1290      int nb = globalIndexDomainZoom.numElements();
1291      for (int i = 0; i < nb; ++i)
1292      {
1293        if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexDomainZoom(i), itVec))
1294        {
1295          indSrv_[rank].push_back(localIndexDomainZoom(i));
1296        }
1297      }
1298      for (int i = 0; i < globalIndexWrittenDomain.numElements(); ++i)
1299      {
1300        if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexWrittenDomain(i), itVec))
1301        {
1302          indWrittenSrv_[rank].push_back(globalIndexWrittenDomain(i));
1303        }
1304      }
1305    }
1306
1307    connectedServerRank_.clear();
1308    for (it = globalIndexDomainOnServer.begin(); it != ite; ++it) {
1309      connectedServerRank_.push_back(it->first);
1310    }
1311
1312    if (!indSrv_.empty())
1313    {
1314      connectedServerRank_.clear();
1315      for (it = indSrv_.begin(); it != indSrv_.end(); ++it)
1316        connectedServerRank_.push_back(it->first);
1317    }
1318    nbConnectedClients_ = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
1319
1320    delete clientServerMap;
1321  }
1322
1323  const std::map<int, vector<size_t> >& CDomain::getIndexServer() const
1324  {
1325    return indSrv_;
1326  }
1327
1328  /*!
1329    Send index from client to server(s)
1330  */
1331  void CDomain::sendIndex()
1332  {
1333    int ns, n, i, j, ind, nv, idx;
1334    CContext* context = CContext::getCurrent();
1335    CContextClient* client=context->client;
1336
1337    CEventClient eventIndex(getType(), EVENT_ID_INDEX);
1338
1339    list<CMessage> list_msgsIndex;
1340    list<CArray<int,1> > list_indi, list_indj, list_writtenInd;
1341
1342    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1343    iteMap = indSrv_.end();
1344    for (int k = 0; k < connectedServerRank_.size(); ++k)
1345    {
1346      int nbData = 0;
1347      int rank = connectedServerRank_[k];
1348      it = indSrv_.find(rank);
1349      if (iteMap != it)
1350        nbData = it->second.size();
1351
1352      list_indi.push_back(CArray<int,1>(nbData));
1353      list_indj.push_back(CArray<int,1>(nbData));
1354
1355      CArray<int,1>& indi = list_indi.back();
1356      CArray<int,1>& indj = list_indj.back();
1357      const std::vector<size_t>& temp = it->second;
1358      for (n = 0; n < nbData; ++n)
1359      {
1360        idx = static_cast<int>(it->second[n]);
1361        indi(n) = i_index(idx);
1362        indj(n) = j_index(idx);
1363      }
1364
1365      list_msgsIndex.push_back(CMessage());
1366
1367      list_msgsIndex.back() << this->getId() << (int)type; // enum ne fonctionne pour les message => ToFix
1368      list_msgsIndex.back() << isCurvilinear;
1369      list_msgsIndex.back() << list_indi.back() << list_indj.back();
1370
1371      if (isCompressible_)
1372      {
1373        std::vector<int>& writtenIndSrc = indWrittenSrv_[rank];
1374        list_writtenInd.push_back(CArray<int,1>(writtenIndSrc.size()));
1375        CArray<int,1>& writtenInd = list_writtenInd.back();
1376
1377        for (n = 0; n < writtenInd.numElements(); ++n)
1378          writtenInd(n) = writtenIndSrc[n];
1379
1380        list_msgsIndex.back() << writtenInd;
1381      }
1382
1383      eventIndex.push(rank, nbConnectedClients_[rank], list_msgsIndex.back());
1384    }
1385
1386    client->sendEvent(eventIndex);
1387  }
1388
1389  /*!
1390    Send area from client to server(s)
1391  */
1392  void CDomain::sendArea()
1393  {
1394    if (!hasArea) return;
1395
1396    int ns, n, i, j, ind, nv, idx;
1397    CContext* context = CContext::getCurrent();
1398    CContextClient* client=context->client;
1399
1400    // send area for each connected server
1401    CEventClient eventArea(getType(), EVENT_ID_AREA);
1402
1403    list<CMessage> list_msgsArea;
1404    list<CArray<double,1> > list_area;
1405
1406    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1407    iteMap = indSrv_.end();
1408    for (int k = 0; k < connectedServerRank_.size(); ++k)
1409    {
1410      int nbData = 0;
1411      int rank = connectedServerRank_[k];
1412      it = indSrv_.find(rank);
1413      if (iteMap != it)
1414        nbData = it->second.size();
1415      list_area.push_back(CArray<double,1>(nbData));
1416
1417      const std::vector<size_t>& temp = it->second;
1418      for (n = 0; n < nbData; ++n)
1419      {
1420        idx = static_cast<int>(it->second[n]);
1421        i = i_index(idx);
1422        j = j_index(idx);
1423        if (hasArea)
1424          list_area.back()(n) = area(i - ibegin, j - jbegin);
1425      }
1426
1427      list_msgsArea.push_back(CMessage());
1428      list_msgsArea.back() << this->getId() << list_area.back();
1429      eventArea.push(rank, nbConnectedClients_[rank], list_msgsArea.back());
1430    }
1431    client->sendEvent(eventArea);
1432  }
1433
1434  /*!
1435    Send longitude and latitude from client to servers
1436    Each client send long and lat information to corresponding connected server(s).
1437    Because longitude and latitude are optional, this function only called if latitude and longitude exist
1438  */
1439  void CDomain::sendLonLat()
1440  {
1441    if (!hasLonLat) return;
1442
1443    int ns, n, i, j, ind, nv, idx;
1444    CContext* context = CContext::getCurrent();
1445    CContextClient* client=context->client;
1446
1447    // send lon lat for each connected server
1448    CEventClient eventLon(getType(), EVENT_ID_LON);
1449    CEventClient eventLat(getType(), EVENT_ID_LAT);
1450
1451    list<CMessage> list_msgsLon, list_msgsLat;
1452    list<CArray<double,1> > list_lon, list_lat;
1453    list<CArray<double,2> > list_boundslon, list_boundslat;
1454
1455    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1456    iteMap = indSrv_.end();
1457    for (int k = 0; k < connectedServerRank_.size(); ++k)
1458    {
1459      int nbData = 0;
1460      int rank = connectedServerRank_[k];
1461      it = indSrv_.find(rank);
1462      if (iteMap != it)
1463        nbData = it->second.size();
1464
1465      list_lon.push_back(CArray<double,1>(nbData));
1466      list_lat.push_back(CArray<double,1>(nbData));
1467
1468      if (hasBounds)
1469      {
1470        list_boundslon.push_back(CArray<double,2>(nvertex, nbData));
1471        list_boundslat.push_back(CArray<double,2>(nvertex, nbData));
1472      }
1473
1474      CArray<double,1>& lon = list_lon.back();
1475      CArray<double,1>& lat = list_lat.back();
1476      const std::vector<size_t>& temp = it->second;
1477      for (n = 0; n < nbData; ++n)
1478      {
1479        idx = static_cast<int>(it->second[n]);
1480        lon(n) = lonvalue_client(idx);
1481        lat(n) = latvalue_client(idx);
1482
1483        if (hasBounds)
1484        {
1485          CArray<double,2>& boundslon = list_boundslon.back();
1486          CArray<double,2>& boundslat = list_boundslat.back();
1487
1488          for (nv = 0; nv < nvertex; ++nv)
1489          {
1490            boundslon(nv, n) = bounds_lon_client(nv, idx);
1491            boundslat(nv, n) = bounds_lat_client(nv, idx);
1492          }
1493        }
1494      }
1495
1496      list_msgsLon.push_back(CMessage());
1497      list_msgsLat.push_back(CMessage());
1498
1499      list_msgsLon.back() << this->getId() << list_lon.back();
1500      list_msgsLat.back() << this->getId() << list_lat.back();
1501
1502      if (hasBounds)
1503      {
1504        list_msgsLon.back() << list_boundslon.back();
1505        list_msgsLat.back() << list_boundslat.back();
1506      }
1507
1508      eventLon.push(rank, nbConnectedClients_[rank], list_msgsLon.back());
1509      eventLat.push(rank, nbConnectedClients_[rank], list_msgsLat.back());
1510    }
1511
1512    client->sendEvent(eventLon);
1513    client->sendEvent(eventLat);
1514  }
1515
1516  /*!
1517    Send some optional information to server(s)
1518    In the future, this function can be extended with more optional information to send
1519  */
1520  void CDomain::sendLonLatArea(void)
1521  {
1522    sendIndex();
1523    sendLonLat();
1524    sendArea();
1525  }
1526
1527  bool CDomain::dispatchEvent(CEventServer& event)
1528  {
1529    if (SuperClass::dispatchEvent(event)) return true;
1530    else
1531    {
1532      switch(event.type)
1533      {
1534        case EVENT_ID_SERVER_ATTRIBUT:
1535          recvServerAttribut(event);
1536          return true;
1537          break;
1538        case EVENT_ID_INDEX:
1539          recvIndex(event);
1540          return true;
1541          break;
1542        case EVENT_ID_LON:
1543          recvLon(event);
1544          return true;
1545          break;
1546        case EVENT_ID_LAT:
1547          recvLat(event);
1548          return true;
1549          break;
1550        case EVENT_ID_AREA:
1551          recvArea(event);
1552          return true;
1553          break;
1554        default:
1555          ERROR("bool CContext::dispatchEvent(CEventServer& event)",
1556                << "Unknown Event");
1557          return false;
1558       }
1559    }
1560  }
1561
1562  /*!
1563    Receive attributes event from clients(s)
1564    \param[in] event event contain info about rank and associated attributes
1565  */
1566  void CDomain::recvServerAttribut(CEventServer& event)
1567  {
1568    CBufferIn* buffer=event.subEvents.begin()->buffer;
1569    string domainId ;
1570    *buffer>>domainId ;
1571    get(domainId)->recvServerAttribut(*buffer) ;
1572  }
1573
1574  /*!
1575    Receive attributes from client(s): zoom info and begin and n of each server
1576    \param[in] rank rank of client source
1577    \param[in] buffer message containing attributes info
1578  */
1579  void CDomain::recvServerAttribut(CBufferIn& buffer)
1580  {
1581    buffer >> ni_srv >> ibegin_srv >> iend_srv >> nj_srv >> jbegin_srv >> jend_srv
1582           >> global_zoom_ni >> global_zoom_ibegin >> global_zoom_nj >> global_zoom_jbegin
1583           >> isCompressible_;
1584
1585    int zoom_iend = global_zoom_ibegin + global_zoom_ni - 1;
1586    int zoom_jend = global_zoom_jbegin + global_zoom_nj - 1;
1587
1588    zoom_ibegin_srv = global_zoom_ibegin > ibegin_srv ? global_zoom_ibegin : ibegin_srv ;
1589    zoom_iend_srv = zoom_iend < iend_srv ? zoom_iend : iend_srv ;
1590    zoom_ni_srv=zoom_iend_srv-zoom_ibegin_srv+1 ;
1591
1592    zoom_jbegin_srv = global_zoom_jbegin > jbegin_srv ? global_zoom_jbegin : jbegin_srv ;
1593    zoom_jend_srv = zoom_jend < jend_srv ? zoom_jend : jend_srv ;
1594    zoom_nj_srv=zoom_jend_srv-zoom_jbegin_srv+1 ;
1595
1596    if (zoom_ni_srv<=0 || zoom_nj_srv<=0)
1597    {
1598      zoom_ibegin_srv=0 ; zoom_iend_srv=0 ; zoom_ni_srv=0 ;
1599      zoom_jbegin_srv=0 ; zoom_jend_srv=0 ; zoom_nj_srv=0 ;
1600    }
1601    lonvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
1602    lonvalue_srv = 0. ;
1603    latvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
1604    latvalue_srv = 0. ;
1605    if (hasBounds)
1606    {
1607      bounds_lon_srv.resize(nvertex,zoom_ni_srv*zoom_nj_srv) ;
1608      bounds_lon_srv = 0. ;
1609      bounds_lat_srv.resize(nvertex,zoom_ni_srv*zoom_nj_srv) ;
1610      bounds_lat_srv = 0. ;
1611    }
1612
1613    if (hasArea)
1614      area_srv.resize(zoom_ni_srv * zoom_nj_srv);
1615  }
1616
1617  /*!
1618    Receive index event from clients(s)
1619    \param[in] event event contain info about rank and associated index
1620  */
1621  void CDomain::recvIndex(CEventServer& event)
1622  {
1623    CDomain* domain;
1624
1625    list<CEventServer::SSubEvent>::iterator it;
1626    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1627    {
1628      CBufferIn* buffer = it->buffer;
1629      string domainId;
1630      *buffer >> domainId;
1631      domain = get(domainId);
1632      domain->recvIndex(it->rank, *buffer);
1633    }
1634
1635    if (domain->isCompressible_)
1636    {
1637      std::sort(domain->indexesToWrite.begin(), domain->indexesToWrite.end());
1638
1639      CContextServer* server = CContext::getCurrent()->server;
1640      domain->numberWrittenIndexes_ = domain->indexesToWrite.size();
1641      MPI_Allreduce(&domain->numberWrittenIndexes_, &domain->totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1642      MPI_Scan(&domain->numberWrittenIndexes_, &domain->offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1643      domain->offsetWrittenIndexes_ -= domain->numberWrittenIndexes_;
1644    }
1645  }
1646
1647  /*!
1648    Receive index information from client(s)
1649    \param[in] rank rank of client source
1650    \param[in] buffer message containing index info
1651  */
1652  void CDomain::recvIndex(int rank, CBufferIn& buffer)
1653  {
1654    int type_int;
1655    buffer >> type_int >> isCurvilinear >> indiSrv[rank] >> indjSrv[rank];
1656    type.setValue((type_attr::t_enum)type_int); // probleme des type enum avec les buffers : ToFix
1657
1658    if (isCompressible_)
1659    {
1660      CArray<int, 1> writtenIndexes;
1661      buffer >> writtenIndexes;
1662      indexesToWrite.reserve(indexesToWrite.size() + writtenIndexes.numElements());
1663      for (int i = 0; i < writtenIndexes.numElements(); ++i)
1664        indexesToWrite.push_back(writtenIndexes(i));
1665    }
1666  }
1667
1668  /*!
1669    Receive longitude event from clients(s)
1670    \param[in] event event contain info about rank and associated longitude
1671  */
1672  void CDomain::recvLon(CEventServer& event)
1673  {
1674    list<CEventServer::SSubEvent>::iterator it;
1675    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1676    {
1677      CBufferIn* buffer = it->buffer;
1678      string domainId;
1679      *buffer >> domainId;
1680      get(domainId)->recvLon(it->rank, *buffer);
1681    }
1682  }
1683
1684  /*!
1685    Receive longitude information from client(s)
1686    \param[in] rank rank of client source
1687    \param[in] buffer message containing longitude info
1688  */
1689  void CDomain::recvLon(int rank, CBufferIn& buffer)
1690  {
1691    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1692    CArray<double,1> lon;
1693    CArray<double,2> boundslon;
1694
1695    buffer >> lon;
1696    if (hasBounds) buffer >> boundslon;
1697
1698    int i, j, ind_srv;
1699    for (int ind = 0; ind < indi.numElements(); ind++)
1700    {
1701      i = indi(ind); j = indj(ind);
1702      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1703      lonvalue_srv(ind_srv) = lon(ind);
1704      if (hasBounds)
1705      {
1706        for (int nv = 0; nv < nvertex; ++nv)
1707          bounds_lon_srv(nv, ind_srv) = boundslon(nv, ind);
1708      }
1709    }
1710  }
1711
1712  /*!
1713    Receive latitude event from clients(s)
1714    \param[in] event event contain info about rank and associated latitude
1715  */
1716  void CDomain::recvLat(CEventServer& event)
1717  {
1718    list<CEventServer::SSubEvent>::iterator it;
1719    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1720    {
1721      CBufferIn* buffer = it->buffer;
1722      string domainId;
1723      *buffer >> domainId;
1724      get(domainId)->recvLat(it->rank, *buffer);
1725    }
1726  }
1727
1728  /*!
1729    Receive latitude information from client(s)
1730    \param[in] rank rank of client source
1731    \param[in] buffer message containing latitude info
1732  */
1733  void CDomain::recvLat(int rank, CBufferIn& buffer)
1734  {
1735    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1736    CArray<double,1> lat;
1737    CArray<double,2> boundslat;
1738
1739    buffer >> lat;
1740    if (hasBounds) buffer >> boundslat;
1741
1742    int i, j, ind_srv;
1743    for (int ind = 0; ind < indi.numElements(); ind++)
1744    {
1745      i = indi(ind); j = indj(ind);
1746      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1747      latvalue_srv(ind_srv) = lat(ind);
1748      if (hasBounds)
1749      {
1750        for (int nv = 0; nv < nvertex; nv++)
1751          bounds_lat_srv(nv, ind_srv) = boundslat(nv, ind);
1752      }
1753    }
1754  }
1755
1756  /*!
1757    Receive area event from clients(s)
1758    \param[in] event event contain info about rank and associated area
1759  */
1760  void CDomain::recvArea(CEventServer& event)
1761  {
1762    list<CEventServer::SSubEvent>::iterator it;
1763    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1764    {
1765      CBufferIn* buffer = it->buffer;
1766      string domainId;
1767      *buffer >> domainId;
1768      get(domainId)->recvArea(it->rank, *buffer);
1769    }
1770  }
1771
1772  /*!
1773    Receive area information from client(s)
1774    \param[in] rank rank of client source
1775    \param[in] buffer message containing area info
1776  */
1777  void CDomain::recvArea(int rank, CBufferIn& buffer)
1778  {
1779    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1780    CArray<double,1> clientArea;
1781
1782    buffer >> clientArea;
1783
1784    int i, j, ind_srv;
1785    for (int ind = 0; ind < indi.numElements(); ind++)
1786    {
1787      i = indi(ind); j = indj(ind);
1788      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1789      area_srv(ind_srv) = clientArea(ind);
1790    }
1791  }
1792
1793  /*!
1794    Check whether a domain has transformation
1795    \return true if domain has transformation
1796  */
1797  bool CDomain::hasTransformation()
1798  {
1799    return (!transformationMap_.empty());
1800  }
1801
1802  /*!
1803    Set transformation for current domain. It's the method to move transformation in hierarchy
1804    \param [in] domTrans transformation on domain
1805  */
1806  void CDomain::setTransformations(const TransMapTypes& domTrans)
1807  {
1808    transformationMap_ = domTrans;
1809  }
1810
1811  /*!
1812    Get all transformation current domain has
1813    \return all transformation
1814  */
1815  CDomain::TransMapTypes CDomain::getAllTransformations(void)
1816  {
1817    return transformationMap_;
1818  }
1819
1820  /*!
1821    Check the validity of all transformations applied on domain
1822  This functions is called AFTER all inherited attributes are solved
1823  */
1824  void CDomain::checkTransformations()
1825  {
1826    TransMapTypes::const_iterator itb = transformationMap_.begin(), it,
1827                                  ite = transformationMap_.end();
1828    for (it = itb; it != ite; ++it)
1829    {
1830      (it->second)->checkValid(this);
1831    }
1832  }
1833
1834  /*!
1835    A current domain will go up the hierarchy to find out the domain from which it has transformation
1836  */
1837  void CDomain::solveInheritanceTransformation()
1838  {
1839    if (this->hasTransformation()) return;
1840
1841    std::vector<CDomain*> refDomain;
1842    CDomain* refer_sptr;
1843    CDomain* refer_ptr = this;
1844    while (refer_ptr->hasDirectDomainReference())
1845    {
1846      refDomain.push_back(refer_ptr);
1847      refer_sptr = refer_ptr->getDirectDomainReference();
1848      refer_ptr  = refer_sptr;
1849      if (refer_ptr->hasTransformation()) break;
1850    }
1851
1852    if (refer_ptr->hasTransformation())
1853      for (int idx = 0; idx < refDomain.size(); ++idx)
1854        refDomain[idx]->setTransformations(refer_ptr->getAllTransformations());
1855  }
1856
1857  void CDomain::solveSrcInheritance()
1858  {
1859    if (!domain_src.isEmpty())
1860    {
1861       if (!CDomain::has(this->domain_src.getValue()))                                   \
1862          ERROR("CDomain::solveSrcInheritance()",                                \
1863             << "[ src_name = " << this->domain_src.getValue() << "]"                 \
1864             << " invalid domain name !");
1865
1866       srcObject_ = CDomain::get(this->domain_src.getValue());
1867    }
1868  }
1869
1870  CDomain* CDomain::getDomainSrc()
1871  {
1872    return srcObject_;
1873  }
1874
1875  /*!
1876    Parse children nodes of a domain in xml file.
1877    Whenver there is a new transformation, its type and name should be added into this function
1878    \param node child node to process
1879  */
1880  void CDomain::parse(xml::CXMLNode & node)
1881  {
1882    SuperClass::parse(node);
1883
1884    if (node.goToChildElement())
1885    {
1886      StdString zoomDomainDefRoot("zoom_domain_definition");
1887      StdString zoom("zoom_domain");
1888      StdString interpDomainDefRoot("interpolate_domain_definition");
1889      StdString interpFromFile("interpolate_domain");
1890      StdString generateRectilinearDefRoot("generate_rectilinear_domain_definition");
1891      StdString generateRectilinear("generate_rectilinear_domain");
1892      do
1893      {
1894        if (node.getElementName() == zoom) {
1895          CZoomDomain* tmp = (CZoomDomainGroup::get(zoomDomainDefRoot))->createChild();
1896          tmp->parse(node);
1897          transformationMap_.push_back(std::make_pair(TRANS_ZOOM_DOMAIN,tmp));
1898        }
1899        else if (node.getElementName() == interpFromFile)
1900        {
1901          CInterpolateDomain* tmp = (CInterpolateDomainGroup::get(interpDomainDefRoot))->createChild();
1902          tmp->parse(node);
1903          transformationMap_.push_back(std::make_pair(TRANS_INTERPOLATE_DOMAIN,tmp));
1904        }
1905        else if (node.getElementName() == generateRectilinear)
1906        {
1907          CGenerateRectilinearDomain* tmp = (CGenerateRectilinearDomainGroup::get(generateRectilinearDefRoot))->createChild();
1908          tmp->parse(node);
1909          transformationMap_.push_back(std::make_pair(TRANS_GENERATE_RECTILINEAR_DOMAIN,tmp));
1910        }
1911      } while (node.goToNextElement()) ;
1912      node.goToParentElement();
1913    }
1914  }
1915   //----------------------------------------------------------------
1916
1917   DEFINE_REF_FUNC(Domain,domain)
1918
1919   ///---------------------------------------------------------------
1920
1921} // namespace xios
Note: See TracBrowser for help on using the repository browser.