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

Last change on this file since 815 was 815, checked in by mhnguyen, 6 years ago

Fixing the bug in ticket 72

+) The distributed axis on client side send info to correct corresponding server
+) Improve serverdistributiondescription class to make it more flexible
+) Create new test_basic_2D only for test cases of 2-d grid

Test
+) On Curie
+) All tests pass

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