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

Last change on this file since 808 was 808, checked in by ymipsl, 7 years ago

Fix problem using rectilinear grid from file, or self-generated

  • Defining boundaries at poles was incorrect

YM

  • 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.2 KB
Line 
1#include "domain.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6
7#include "xios_spl.hpp"
8#include "event_client.hpp"
9#include "event_server.hpp"
10#include "buffer_in.hpp"
11#include "message.hpp"
12#include "type.hpp"
13#include "context.hpp"
14#include "context_client.hpp"
15#include "context_server.hpp"
16#include "array_new.hpp"
17#include "distribution_client.hpp"
18#include "server_distribution_description.hpp"
19#include "client_server_mapping_distributed.hpp"
20#include "zoom_domain.hpp"
21#include "interpolate_domain.hpp"
22#include "generate_rectilinear_domain.hpp"
23
24#include <algorithm>
25
26namespace xios {
27
28   /// ////////////////////// Définitions ////////////////////// ///
29
30   CDomain::CDomain(void)
31      : CObjectTemplate<CDomain>(), CDomainAttributes()
32      , isChecked(false), relFiles(), isClientChecked(false), nbConnectedClients_(), indSrv_(), connectedServerRank_()
33      , hasBounds(false), hasArea(false), isDistributed_(false), nGlobDomain_(), isCompressible_(false), isUnstructed_(false)
34      , global_zoom_ni(0), global_zoom_ibegin(0), global_zoom_nj(0), global_zoom_jbegin(0)
35      , isClientAfterTransformationChecked(false), hasLonLat(false)
36      , lonvalue_client(), latvalue_client(), bounds_lon_client(), bounds_lat_client()
37      , 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      , 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   const std::set<StdString> & CDomain::getRelFiles(void) const
63   {
64      return (this->relFiles);
65   }
66
67   //----------------------------------------------------------------
68
69   const std::vector<int>& CDomain::getIndexesToWrite(void) const
70   {
71     return indexesToWrite;
72   }
73
74   /*!
75     Returns the number of indexes written by each server.
76     \return the number of indexes written by each server
77   */
78   int CDomain::getNumberWrittenIndexes() const
79   {
80     return numberWrittenIndexes_;
81   }
82
83   /*!
84     Returns the total number of indexes written by the servers.
85     \return the total number of indexes written by the servers
86   */
87   int CDomain::getTotalNumberWrittenIndexes() const
88   {
89     return totalNumberWrittenIndexes_;
90   }
91
92   /*!
93     Returns the offset of indexes written by each server.
94     \return the offset of indexes written by each server
95   */
96   int CDomain::getOffsetWrittenIndexes() const
97   {
98     return offsetWrittenIndexes_;
99   }
100
101   //----------------------------------------------------------------
102
103   /*!
104    * Compute the minimum buffer size required to send the attributes to the server(s).
105    *
106    * \return A map associating the server rank with its minimum buffer size.
107    */
108   std::map<int, StdSize> CDomain::getAttributesBufferSize()
109   {
110     CContextClient* client = CContext::getCurrent()->client;
111
112     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes();
113
114     if (client->isServerLeader())
115     {
116       // size estimation for sendServerAttribut
117       size_t size = 11 * sizeof(size_t);
118
119       const std::list<int>& ranks = client->getRanksServerLeader();
120       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
121       {
122         if (size > attributesSizes[*itRank])
123           attributesSizes[*itRank] = size;
124       }
125     }
126
127     std::map<int, std::vector<size_t> >::const_iterator itIndexEnd = indSrv_.end();
128     std::map<int, std::vector<int> >::const_iterator itWrittenIndexEnd = indWrittenSrv_.end();
129     for (size_t k = 0; k < connectedServerRank_.size(); ++k)
130     {
131       int rank = connectedServerRank_[k];
132       std::map<int, std::vector<size_t> >::const_iterator it = indSrv_.find(rank);
133       size_t idxCount = (it != itIndexEnd) ? it->second.size() : 0;
134
135       // size estimation for sendIndex (and sendArea which is always smaller or equal)
136       size_t sizeIndexEvent = 2 * sizeof(size_t) + 2 * CArray<int,1>::size(idxCount);
137       if (isCompressible_)
138       {
139         std::map<int, std::vector<int> >::const_iterator itWritten = indWrittenSrv_.find(rank);
140         size_t writtenIdxCount = (itWritten != itWrittenIndexEnd) ? itWritten->second.size() : 0;
141         sizeIndexEvent += CArray<int,1>::size(writtenIdxCount);
142       }
143
144       // size estimation for sendLonLat
145       size_t sizeLonLatEvent = CArray<double,1>::size(idxCount);
146       if (hasBounds)
147         sizeLonLatEvent += CArray<double,2>::size(nvertex * idxCount);
148
149       size_t size = CEventClient::headerSize + getId().size() + sizeof(size_t) + std::max(sizeIndexEvent, sizeLonLatEvent);
150       if (size > attributesSizes[rank])
151         attributesSizes[rank] = size;
152     }
153
154     return attributesSizes;
155   }
156
157   //----------------------------------------------------------------
158
159   bool CDomain::isEmpty(void) const
160   {
161      return ((this->zoom_ni_srv == 0) ||
162              (this->zoom_nj_srv == 0));
163   }
164
165   //----------------------------------------------------------------
166
167   bool CDomain::IsWritten(const StdString & filename) const
168   {
169      return (this->relFiles.find(filename) != this->relFiles.end());
170   }
171
172   bool CDomain::isWrittenCompressed(const StdString& filename) const
173   {
174      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
175   }
176
177   //----------------------------------------------------------------
178
179   bool CDomain::isDistributed(void) const
180   {
181      return isDistributed_;
182   }
183
184   //----------------------------------------------------------------
185
186   /*!
187    * Test whether the data defined on the domain can be outputted in a compressed way.
188    *
189    * \return true if and only if a mask was defined for this domain
190    */
191   bool CDomain::isCompressible(void) const
192   {
193      return isCompressible_;
194   }
195
196   //----------------------------------------------------------------
197
198   void CDomain::addRelFile(const StdString & filename)
199   {
200      this->relFiles.insert(filename);
201   }
202
203   void CDomain::addRelFileCompressed(const StdString& filename)
204   {
205      this->relFilesCompressed.insert(filename);
206   }
207
208
209   StdString CDomain::GetName(void)   { return (StdString("domain")); }
210   StdString CDomain::GetDefName(void){ return (CDomain::GetName()); }
211   ENodeType CDomain::GetType(void)   { return (eDomain); }
212
213   //----------------------------------------------------------------
214
215   /*!
216     Redistribute RECTILINEAR domain with a number of local domains.
217   All attributes ni,nj,ibegin,jbegin (if defined) will be rewritten
218   The optional attributes lonvalue, latvalue will be added. Because this function only serves (for now)
219   for interpolation from unstructured domain to rectilinear one, range of latvalue is 0-360 and lonvalue is -90 - +90
220    \param [in] nbLocalDomain number of local domain on the domain destination
221   */
222   void CDomain::redistribute(int nbLocalDomain)
223   {
224     if (this->isRedistributed_) return;
225
226     this->isRedistributed_ = true;
227     CContext* context = CContext::getCurrent();
228     CContextClient* client = context->client;
229     int rankClient = client->clientRank;
230     int rankOnDomain = rankClient%nbLocalDomain;
231
232     if (ni_glo.isEmpty() || ni_glo <= 0 )
233     {
234        ERROR("CDomain::redistribute(int nbLocalDomain)",
235           << "[ Id = " << this->getId() << " ] "
236           << "The global domain is badly defined,"
237           << " check the \'ni_glo\'  value !")
238     }
239
240     if (nj_glo.isEmpty() || nj_glo <= 0 )
241     {
242        ERROR("CDomain::redistribute(int nbLocalDomain)",
243           << "[ Id = " << this->getId() << " ] "
244           << "The global domain is badly defined,"
245           << " check the \'nj_glo\'  value !")
246     }
247
248     if ((type_attr::rectilinear == type)  || (type_attr::curvilinear == type))
249     {
250        int globalDomainSize = ni_glo * nj_glo;
251        if (globalDomainSize <= nbLocalDomain)
252        {
253          for (int idx = 0; idx < nbLocalDomain; ++idx)
254          {
255            if (rankOnDomain < globalDomainSize)
256            {
257              int iIdx = rankOnDomain % ni_glo;
258              int jIdx = rankOnDomain / ni_glo;
259              ibegin.setValue(iIdx); jbegin.setValue(jIdx);
260              ni.setValue(1); nj.setValue(1);
261            }
262            else
263            {
264              ibegin.setValue(0); jbegin.setValue(0);
265              ni.setValue(0); nj.setValue(0);
266            }
267          }
268        }
269        else
270        {
271          float njGlo = nj_glo.getValue();
272          float niGlo = ni_glo.getValue();
273          int nbProcOnX, nbProcOnY, range;
274
275          // Compute (approximately) number of segment on x and y axis
276          float yOverXRatio = njGlo/niGlo;
277
278          nbProcOnX = std::ceil(std::sqrt(nbLocalDomain/yOverXRatio));
279          nbProcOnY = std::ceil(((float)nbLocalDomain)/nbProcOnX);
280
281          // Simple distribution: Sweep from top to bottom, left to right
282          // Calculate local begin on x
283          std::vector<int> ibeginVec(nbProcOnX,0), jbeginVec(nbProcOnY,0);
284          std::vector<int> niVec(nbProcOnX), njVec(nbProcOnY);
285          for (int i = 1; i < nbProcOnX; ++i)
286          {
287            range = ni_glo / nbProcOnX;
288            if (i < (ni_glo%nbProcOnX)) ++range;
289            niVec[i-1] = range;
290            ibeginVec[i] = ibeginVec[i-1] + niVec[i-1];
291          }
292          niVec[nbProcOnX-1] = ni_glo - ibeginVec[nbProcOnX-1];
293
294          // Calculate local begin on y
295          for (int j = 1; j < nbProcOnY; ++j)
296          {
297            range = nj_glo / nbProcOnY;
298            if (j < (nj_glo%nbProcOnY)) ++range;
299            njVec[j-1] = range;
300            jbeginVec[j] = jbeginVec[j-1] + njVec[j-1];
301          }
302          njVec[nbProcOnY-1] = nj_glo - jbeginVec[nbProcOnY-1];
303
304          // Now assign value to ni, ibegin, nj, jbegin
305          int iIdx = rankOnDomain % nbProcOnX;
306          int jIdx = rankOnDomain / nbProcOnX;
307
308          if (rankOnDomain != (nbLocalDomain-1))
309          {
310            ibegin.setValue(ibeginVec[iIdx]);
311            jbegin.setValue(jbeginVec[jIdx]);
312            nj.setValue(njVec[jIdx]);
313            ni.setValue(niVec[iIdx]);
314          }
315          else // just merge all the remaining rectangle into the last one
316          {
317            ibegin.setValue(ibeginVec[iIdx]);
318            jbegin.setValue(jbeginVec[jIdx]);
319            nj.setValue(njVec[jIdx]);
320            ni.setValue(ni_glo - ibeginVec[iIdx]);
321          }
322        }
323
324        // Now fill other attributes
325        if (type_attr::rectilinear == type) fillInRectilinearLonLat();
326     }
327     else  // unstructured domain
328     {
329       if (this->i_index.isEmpty())
330       {
331          int globalDomainSize = ni_glo * nj_glo;
332          if (globalDomainSize <= nbLocalDomain)
333          {
334            for (int idx = 0; idx < nbLocalDomain; ++idx)
335            {
336              if (rankOnDomain < globalDomainSize)
337              {
338                int iIdx = rankOnDomain % ni_glo;
339                int jIdx = rankOnDomain / ni_glo;
340                ibegin.setValue(iIdx); jbegin.setValue(jIdx);
341                ni.setValue(1); nj.setValue(1);
342              }
343              else
344              {
345                ibegin.setValue(0); jbegin.setValue(0);
346                ni.setValue(0); nj.setValue(0);
347              }
348            }
349          }
350          else
351          {
352            float njGlo = nj_glo.getValue();
353            float niGlo = ni_glo.getValue();
354            std::vector<int> ibeginVec(nbLocalDomain,0);
355            std::vector<int> niVec(nbLocalDomain);
356            for (int i = 1; i < nbLocalDomain; ++i)
357            {
358              int range = ni_glo / nbLocalDomain;
359              if (i < (ni_glo%nbLocalDomain)) ++range;
360              niVec[i-1] = range;
361              ibeginVec[i] = ibeginVec[i-1] + niVec[i-1];
362            }
363            niVec[nbLocalDomain-1] = ni_glo - ibeginVec[nbLocalDomain-1];
364
365            int iIdx = rankOnDomain % nbLocalDomain;
366            ibegin.setValue(ibeginVec[iIdx]);
367            jbegin.setValue(0);
368            ni.setValue(niVec[iIdx]);
369            nj.setValue(1);
370          }
371        }
372        else
373        {
374          ibegin.setValue(this->i_index(0));
375          jbegin.setValue(0);
376          ni.setValue(this->i_index.numElements());
377          nj.setValue(1);
378        }
379     }
380
381     checkDomain();
382   }
383
384   /*!
385     Fill in the values for lonvalue_1d and latvalue_1d of rectilinear domain
386     Range of longitude value from 0 - 360
387     Range of latitude value from -90 - +90
388   */
389   void CDomain::fillInRectilinearLonLat()
390   {
391     if (!lonvalue_rectilinear_read_from_file.isEmpty())
392     {
393       lonvalue_1d.resize(ni);
394       for (int idx = 0; idx < ni; ++idx)
395         lonvalue_1d(idx) = lonvalue_rectilinear_read_from_file(idx+ibegin);
396       lon_start.setValue(lonvalue_rectilinear_read_from_file(0));
397       lon_end.setValue(lonvalue_rectilinear_read_from_file(ni_glo-1));
398     }
399     else
400     {
401       if (!lonvalue_2d.isEmpty()) lonvalue_2d.free();
402       lonvalue_1d.resize(ni);
403       double lonRange = lon_end - lon_start;
404       double lonStep = (1 == ni_glo.getValue()) ? lonRange : lonRange/double(ni_glo.getValue()-1);
405
406        // Assign lon value
407       for (int i = 0; i < ni; ++i)
408       {
409         if (0 == (ibegin + i))
410         {
411           lonvalue_1d(i) = lon_start;
412         }
413         else if (ni_glo == (ibegin + i + 1))
414         {
415           lonvalue_1d(i) = lon_end;
416         }
417         else
418         {
419           lonvalue_1d(i) = (ibegin + i) * lonStep  + lon_start;
420         }
421       }
422     }
423
424
425     if (!latvalue_rectilinear_read_from_file.isEmpty())
426     {
427       latvalue_1d.resize(nj);
428       for (int idx = 0; idx < nj; ++idx)
429         latvalue_1d(idx) = latvalue_rectilinear_read_from_file(idx+jbegin);
430       lat_start.setValue(latvalue_rectilinear_read_from_file(0));
431       lat_end.setValue(latvalue_rectilinear_read_from_file(nj_glo-1));
432     }
433     else
434     {
435       if (!latvalue_2d.isEmpty()) latvalue_1d.free();
436       latvalue_1d.resize(nj);
437
438       double latRange = lat_end - lat_start;
439       double latStep = (1 == nj_glo.getValue()) ? latRange : latRange/double(nj_glo.getValue()-1);
440
441       for (int j = 0; j < nj; ++j)
442       {
443         if (0 == (jbegin + j))
444         {
445            latvalue_1d(j) = lat_start;
446         }
447         else if (nj_glo == (jbegin + j + 1))
448         {
449            latvalue_1d(j) = lat_end;
450         }
451         else
452         {
453           latvalue_1d(j) =  (jbegin + j) * latStep + lat_start;
454         }
455       }
456     }
457   }
458
459   void CDomain::fillInRectilinearBoundLonLat(CArray<double,2>& boundsLon, CArray<double,2>& boundsLat,
460                                              bool isNorthPole, bool isSouthPole)
461   {
462     int i,j,k;
463     const int nvertexValue = 4;
464     boundsLon.resize(nvertexValue,ni*nj);
465
466     if (!lonvalue_rectilinear_read_from_file.isEmpty())
467     {
468       double lonStepStart = lonvalue_rectilinear_read_from_file(1)-lonvalue_rectilinear_read_from_file(0);
469       bounds_lon_start.setValue(lonvalue_rectilinear_read_from_file(0) - lonStepStart/2);
470       double lonStepEnd = (lonvalue_rectilinear_read_from_file(ni_glo-1)-lonvalue_rectilinear_read_from_file(ni_glo-2));
471       bounds_lon_end.setValue(lonvalue_rectilinear_read_from_file(ni_glo-1) + lonStepEnd/2);
472       double errorBoundsLon = std::abs(360-std::abs(bounds_lon_end-bounds_lon_start));
473       if (errorBoundsLon > NumTraits<double>::epsilon()) bounds_lon_end.setValue(bounds_lon_start+360);
474       for(j=0;j<nj;++j)
475         for(i=0;i<ni;++i)
476         {
477           k=j*ni+i;
478           boundsLon(0,k) = boundsLon(1,k) = (0 == (ibegin + i)) ? bounds_lon_start
479                                                                 : (lonvalue_rectilinear_read_from_file(ibegin + i)+lonvalue_rectilinear_read_from_file(ibegin + i-1))/2;
480           boundsLon(2,k) = boundsLon(3,k) = ((ibegin + i + 1) == ni_glo) ? bounds_lon_end
481                                                                          : (lonvalue_rectilinear_read_from_file(ibegin + i + 1)+lonvalue_rectilinear_read_from_file(ibegin + i))/2;
482         }
483     }
484     else
485     {
486       double boundsLonRange = bounds_lon_end - bounds_lon_start;
487       double lonStep = boundsLonRange/double(ni_glo.getValue());
488       for(j=0;j<nj;++j)
489         for(i=0;i<ni;++i)
490         {
491           k=j*ni+i;
492           boundsLon(0,k) = boundsLon(1,k) = (0 != (ibegin + i)) ? (ibegin + i) * lonStep + bounds_lon_start
493                                                                 : bounds_lon_start;
494           boundsLon(2,k) = boundsLon(3,k) = ((ibegin + i + 1) != ni_glo) ? (ibegin + i +1) * lonStep + bounds_lon_start
495                                                                          : bounds_lon_end;
496         }
497     }
498
499     boundsLat.resize(nvertexValue,nj*ni);
500     if (!latvalue_rectilinear_read_from_file.isEmpty())
501     {
502       double latStepStart = latvalue_rectilinear_read_from_file(1)-latvalue_rectilinear_read_from_file(0);
503       if (isNorthPole) bounds_lat_start.setValue(latvalue_rectilinear_read_from_file(0) );
504       else bounds_lat_start.setValue(latvalue_rectilinear_read_from_file(0)-latStepStart/2 );
505
506
507       double latStepEnd = (latvalue_rectilinear_read_from_file(nj_glo-1)-latvalue_rectilinear_read_from_file(nj_glo-2));
508       if (isSouthPole) bounds_lat_end.setValue(latvalue_rectilinear_read_from_file(nj_glo-1));
509       else bounds_lat_end.setValue(latvalue_rectilinear_read_from_file(nj_glo-1)+latStepEnd/2);
510       
511       if (bounds_lat_start > 90.-1e-3) bounds_lat_start=90 ;
512       if (bounds_lat_start < -90.+1e-3) bounds_lat_start=-90 ;
513       if (bounds_lat_end > 90.-1e-3) bounds_lat_end=90 ;
514       if (bounds_lat_end < -90.+1e-3) bounds_lat_end=-90 ;
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
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
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  /*!
1928    Parse children nodes of a domain in xml file.
1929    Whenver there is a new transformation, its type and name should be added into this function
1930    \param node child node to process
1931  */
1932  void CDomain::parse(xml::CXMLNode & node)
1933  {
1934    SuperClass::parse(node);
1935
1936    if (node.goToChildElement())
1937    {
1938      StdString zoomDomainDefRoot("zoom_domain_definition");
1939      StdString zoom("zoom_domain");
1940      StdString interpDomainDefRoot("interpolate_domain_definition");
1941      StdString interpFromFile("interpolate_domain");
1942      StdString generateRectilinearDefRoot("generate_rectilinear_domain_definition");
1943      StdString generateRectilinear("generate_rectilinear_domain");
1944      do
1945      {
1946        StdString nodeId("");
1947        if (node.getAttributes().end() != node.getAttributes().find("id"))
1948        { nodeId = node.getAttributes()["id"]; }
1949
1950        if (node.getElementName() == zoom) {
1951          CZoomDomain* tmp = (CZoomDomainGroup::get(zoomDomainDefRoot))->createChild(nodeId);
1952          tmp->parse(node);
1953          transformationMap_.push_back(std::make_pair(TRANS_ZOOM_DOMAIN,tmp));
1954        }
1955        else if (node.getElementName() == interpFromFile)
1956        {
1957          CInterpolateDomain* tmp = (CInterpolateDomainGroup::get(interpDomainDefRoot))->createChild(nodeId);
1958          tmp->parse(node);
1959          transformationMap_.push_back(std::make_pair(TRANS_INTERPOLATE_DOMAIN,tmp));
1960        }
1961        else if (node.getElementName() == generateRectilinear)
1962        {
1963          CGenerateRectilinearDomain* tmp = (CGenerateRectilinearDomainGroup::get(generateRectilinearDefRoot))->createChild(nodeId);
1964          tmp->parse(node);
1965          transformationMap_.push_back(std::make_pair(TRANS_GENERATE_RECTILINEAR_DOMAIN,tmp));
1966        }
1967      } while (node.goToNextElement()) ;
1968      node.goToParentElement();
1969    }
1970  }
1971   //----------------------------------------------------------------
1972
1973   DEFINE_REF_FUNC(Domain,domain)
1974
1975   ///---------------------------------------------------------------
1976
1977} // namespace xios
Note: See TracBrowser for help on using the repository browser.