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

Last change on this file since 899 was 899, checked in by ymipsl, 5 years ago

Fix remaping for ni_glo=1 or nj_glo=1

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