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

Last change on this file since 747 was 747, checked in by rlacroix, 8 years ago

Fix the inherited name for axis/domains with reference in some cases.

Correctly account for transformations and non default ids.

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