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

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

Adding attribute reading of unstructured grid

+) Fix a minor bug relating to unstructured grid detection
+) Add attribute reading for unstructured domain

Test
+) On Curie
+) test_remap passes

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