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

Last change on this file since 731 was 731, checked in by rlacroix, 9 years ago

Correctly estimate the needed buffer sizes.

The attributes were not considered which could lead to incorrect estimations.

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