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

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

Allowing each process to retrieve its own distribution with i_index

+) Read value and data from unstructured grid with provided i_index value

Test
+) On Curie
+) test_remap works

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