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

Last change on this file since 775 was 775, checked in by mhnguyen, 8 years ago

Implementing the reading of attributes of an axis from a file

+) 3d grid can be read directly from a file
+) Clean some redundant codes
+) Add new attribute declaration that allows to output only desired attributes

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