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

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

Adding new transformation: Compute_connectivity_domain

Test
+) On Curie
+) Test passes

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