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

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

Add support for indexed output.

If the new field attribute "indexed_output" is set to true and a mask is defined (either at grid, domain or axis level), the indexed data will be outputed instead of the full data with missing values.

See http://cfconventions.org/Data/cf-conventions/cf-conventions-1.5/build/cf-conventions.html#compression-by-gathering for more information.

  • 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: 50.3 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_from_file_domain.hpp"
22
23#include <algorithm>
24
25namespace xios {
26
27   /// ////////////////////// Définitions ////////////////////// ///
28
29   CDomain::CDomain(void)
30      : CObjectTemplate<CDomain>(), CDomainAttributes()
31      , isChecked(false), relFiles(), isClientChecked(false), nbConnectedClients_(), indSrv_(), connectedServerRank_()
32      , hasBounds(false), hasArea(false), isDistributed_(false), nGlobDomain_(), isCompressible_(false), isUnstructed_(false)
33      , global_zoom_ni(0), global_zoom_ibegin(0), global_zoom_nj(0), global_zoom_jbegin(0)
34      , isClientAfterTransformationChecked(false), hasLonLat(false)
35      , lonvalue_client(), latvalue_client(), bounds_lon_client(), bounds_lat_client()
36   { /* Ne rien faire de plus */ }
37
38   CDomain::CDomain(const StdString & id)
39      : CObjectTemplate<CDomain>(id), CDomainAttributes()
40      , isChecked(false), relFiles(), isClientChecked(false), nbConnectedClients_(), indSrv_(), connectedServerRank_()
41      , hasBounds(false), hasArea(false), isDistributed_(false), nGlobDomain_(), isCompressible_(false), isUnstructed_(false)
42      , global_zoom_ni(0), global_zoom_ibegin(0), global_zoom_nj(0), global_zoom_jbegin(0)
43      , isClientAfterTransformationChecked(false), hasLonLat(false)
44      , lonvalue_client(), latvalue_client(), bounds_lon_client(), bounds_lat_client()
45   { /* Ne rien faire de plus */ }
46
47   CDomain::~CDomain(void)
48   {
49   }
50
51   ///---------------------------------------------------------------
52
53   CDomain* CDomain::createDomain()
54   {
55     CDomain* domain = CDomainGroup::get("domain_definition")->createChild();
56     return domain;
57   }
58
59   void CDomain::duplicateAttributes(CDomain* domain)
60   {
61     domain->setAttributes(this);
62   }
63
64   const std::set<StdString> & CDomain::getRelFiles(void) const
65   {
66      return (this->relFiles);
67   }
68
69   //----------------------------------------------------------------
70
71   const std::vector<int>& CDomain::getIndexesToWrite(void) const
72   {
73     return indexesToWrite;
74   }
75
76   /*!
77     Returns the number of indexes written by each server.
78     \return the number of indexes written by each server
79   */
80   int CDomain::getNumberWrittenIndexes() const
81   {
82     return numberWrittenIndexes_;
83   }
84
85   /*!
86     Returns the total number of indexes written by the servers.
87     \return the total number of indexes written by the servers
88   */
89   int CDomain::getTotalNumberWrittenIndexes() const
90   {
91     return totalNumberWrittenIndexes_;
92   }
93
94   /*!
95     Returns the offset of indexes written by each server.
96     \return the offset of indexes written by each server
97   */
98   int CDomain::getOffsetWrittenIndexes() const
99   {
100     return offsetWrittenIndexes_;
101   }
102
103   //----------------------------------------------------------------
104
105   bool CDomain::isEmpty(void) const
106   {
107      return ((this->zoom_ni_srv == 0) ||
108              (this->zoom_nj_srv == 0));
109   }
110
111   //----------------------------------------------------------------
112
113   bool CDomain::IsWritten(const StdString & filename) const
114   {
115      return (this->relFiles.find(filename) != this->relFiles.end());
116   }
117
118   bool CDomain::isWrittenCompressed(const StdString& filename) const
119   {
120      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
121   }
122
123   //----------------------------------------------------------------
124
125   bool CDomain::isDistributed(void) const
126   {
127      return isDistributed_;
128   }
129
130   //----------------------------------------------------------------
131
132   /*!
133    * Test whether the data defined on the domain can be outputted in a compressed way.
134    *
135    * \return true if and only if a mask was defined for this domain
136    */
137   bool CDomain::isCompressible(void) const
138   {
139      return isCompressible_;
140   }
141
142   //----------------------------------------------------------------
143
144   void CDomain::addRelFile(const StdString & filename)
145   {
146      this->relFiles.insert(filename);
147   }
148
149   void CDomain::addRelFileCompressed(const StdString& filename)
150   {
151      this->relFilesCompressed.insert(filename);
152   }
153
154
155   StdString CDomain::GetName(void)   { return (StdString("domain")); }
156   StdString CDomain::GetDefName(void){ return (CDomain::GetName()); }
157   ENodeType CDomain::GetType(void)   { return (eDomain); }
158
159   //----------------------------------------------------------------
160
161   void CDomain::checkDomain(void)
162   {
163     if (type.isEmpty())
164     {
165       ERROR("CDomain::checkDomain(void)",
166             << "[ Id = " << this->getId() << " ] "
167             << "The domain type is not defined,"
168             << " check the 'type'  value !")
169     }
170
171     if (type==type_attr::unstructured)
172     {
173        if (ni_glo.isEmpty() || ni_glo <= 0 )
174        {
175           ERROR("CDomain::checkAttributes(void)",
176              << "[ Id = " << this->getId() << " ] "
177              << "The global domain is badly defined,"
178              << " check the \'ni_glo\'  value !")
179        }
180        isUnstructed_ = true;
181        nj_glo = 1;
182        nj = 1;
183        jbegin = 0;
184        if (ni.isEmpty()) ni = i_index.numElements();
185        j_index.resize(ni);
186        for(int i=0;i<ni;++i) j_index(i)=0;
187
188        if (!area.isEmpty())
189          area.transposeSelf(1, 0);
190     }
191     else if ((ni_glo.isEmpty() || ni_glo.getValue() <= 0 ) ||
192         (nj_glo.isEmpty() || nj_glo.getValue() <= 0 ))
193     {
194        ERROR("CDomain::checkAttributes(void)",
195              << "[ Id = " << this->getId() << " ] "
196              << "The global domain is badly defined,"
197              << " check the \'ni_glo\' et \'nj_glo\' values !")
198     }
199
200     isDistributed_ = !ibegin.isEmpty() || !ni.isEmpty() || !jbegin.isEmpty() || !nj.isEmpty();
201
202     checkLocalIDomain();
203     checkLocalJDomain();
204
205     if (i_index.isEmpty())
206     {
207       i_index.resize(ni*nj);
208       for (int j = 0; j < nj; ++j)
209         for (int i = 0; i < ni; ++i) i_index(i+j*ni) = i+ibegin;
210     }
211
212     if (j_index.isEmpty())
213     {
214       j_index.resize(ni*nj);
215       for (int j = 0; j < nj; ++j)
216         for (int i = 0; i < ni; ++i) j_index(i+j*ni) = j+jbegin;
217     }
218     computeNGlobDomain();
219
220     if (0 == global_zoom_ni) global_zoom_ni = ni_glo;
221     if (0 == global_zoom_nj) global_zoom_nj = nj_glo;
222   }
223
224   //----------------------------------------------------------------
225
226   void CDomain::checkLocalIDomain(void)
227   {
228      if (ibegin.isEmpty() && ni.isEmpty())
229      {
230        ibegin = 0;
231        ni = ni_glo;
232      }
233      else if (!i_index.isEmpty())
234      {
235        if (ibegin.isEmpty()) ibegin = i_index(0);
236      }
237
238      if (ni.getValue() < 0 || ibegin.getValue() < 0 ||
239         (ibegin.getValue() + ni.getValue()) > ni_glo.getValue())
240      {
241        ERROR("CDomain::checkLocalIDomain(void)",
242              << "[ Id = " << this->getId() << " ] "
243              << "The local domain is wrongly defined,"
244              << " check the attributes 'ni_glo', 'ni' and 'ibegin'");
245      }
246   }
247
248   //----------------------------------------------------------------
249   void CDomain::checkLocalJDomain(void)
250   {
251     if (jbegin.isEmpty() && nj.isEmpty())
252     {
253       jbegin = 0;
254       nj = nj_glo;
255     }
256     else if (!j_index.isEmpty())
257     {
258       if (jbegin.isEmpty()) jbegin = j_index(0);
259     }
260
261      if (nj.getValue() < 0 || jbegin.getValue() < 0 ||
262         (jbegin.getValue() + nj.getValue()) > nj_glo.getValue())
263      {
264        ERROR("CDomain::checkLocalJDomain(void)",
265              << "[ Id = " << this->getId() << " ] "
266              << "The local domain is wrongly defined,"
267              << " check the attributes 'nj_glo', 'nj' and 'jbegin'");
268      }
269   }
270
271   //----------------------------------------------------------------
272   void CDomain::checkMask(void)
273   {
274      if (!mask_1d.isEmpty() && !mask_2d.isEmpty())
275        ERROR("CDomain::checkMask(void)",
276             <<"Only one mask is used but both mask_1d and mask_2d are defined! "<<endl
277             <<"Define only one mask: mask_1d or mask_2d ");
278
279      if (!mask_1d.isEmpty() && mask_2d.isEmpty())
280      {
281        if (mask_1d.numElements() != i_index.numElements())
282          ERROR("CDomain::checkMask(void)",
283                <<"the mask_1d has not the same size as the local domain"<<endl
284                <<"Local size is "<<i_index.numElements()<<endl
285                <<"Mask size is "<<mask_1d.numElements());
286      }
287
288      if (mask_1d.isEmpty() && !mask_2d.isEmpty())
289      {
290         if ((mask_2d.extent(0) != ni) ||
291             (mask_2d.extent(1) != nj))
292            ERROR("CDomain::checkMask(void)",
293                  <<"the mask has not the same size as the local domain"<<endl
294                  <<"Local size is "<<ni<<"x"<<nj<<endl
295                  <<"Mask size is "<<mask_2d.extent(0)<<"x"<<mask_2d.extent(1));
296      }
297
298      if (!mask_2d.isEmpty())
299      {
300        mask_1d.resize(mask_2d.extent(0) * mask_2d.extent(1));
301        for (int j = 0; j < nj; ++j)
302          for (int i = 0; i < ni; ++i) mask_1d(i+j*ni) = mask_2d(i,j);
303        mask_2d.free();
304      }
305      else if (mask_1d.isEmpty())
306      {
307        mask_1d.resize(i_index.numElements());
308        for (int i = 0; i < i_index.numElements(); ++i) mask_1d(i) = true;
309      }
310   }
311
312   //----------------------------------------------------------------
313
314   void CDomain::checkDomainData(void)
315   {
316      if (!data_dim.isEmpty() &&
317         !(data_dim.getValue() == 1 || data_dim.getValue() == 2))
318      {
319         ERROR("CDomain::checkAttributes(void)",
320               << "Data dimension incompatible (must be 1 or 2) !") ;
321      }
322      else if (data_dim.isEmpty())
323      {
324        data_dim.setValue(1);
325      }
326
327      if (data_ibegin.isEmpty())
328         data_ibegin.setValue(0) ;
329      if (data_jbegin.isEmpty())
330         data_jbegin.setValue(0) ;
331
332      if (!data_ni.isEmpty() && (data_ni.getValue() <= 0))
333      {
334         ERROR("CDomain::checkAttributes(void)",
335               << "Data dimension is negative (data_ni).") ;
336      }
337      else if (data_ni.isEmpty())
338      {
339         data_ni.setValue((data_dim.getValue() == 1)
340                           ? (ni.getValue() * nj.getValue())
341                           : ni.getValue());
342      }
343
344      if (!data_nj.isEmpty() && (data_nj.getValue() <= 0) )
345      {
346         ERROR("CDomain::checkAttributes(void)",
347               << "Data dimension is negative (data_nj).") ;
348      }
349
350      if (data_nj.isEmpty())
351         data_nj.setValue((data_dim.getValue() == 1)
352                   ? (ni.getValue() * nj.getValue())
353                   : nj.getValue());
354
355   }
356
357   //----------------------------------------------------------------
358   void CDomain::checkCompression(void)
359   {
360      if (!data_i_index.isEmpty())
361      {
362        if (!data_j_index.isEmpty() &&
363           (data_j_index.numElements() != data_i_index.numElements()))
364        {
365           ERROR("CDomain::checkAttributes(void)",
366                 <<"Dimension data_j_index incompatible with data_i_index.") ;
367        }
368
369       if (2 == data_dim.getValue())
370       {
371          if (data_j_index.isEmpty())
372          {
373             ERROR("CDomain::checkAttributes(void)",
374                   <<"data_j_index must be defined !") ;
375          }
376       }
377       else // (1 == data_dim.getValue())
378       {
379          if (data_j_index.isEmpty())
380          {
381            const int dni = data_ni.getValue();
382            data_j_index.resize(dni);
383            for (int j = 0; j < dni; ++j) data_j_index(j) = 0;
384          }
385       }
386      }
387      else
388      {
389         if ((data_dim.getValue() == 2) && (!data_j_index.isEmpty()))
390            ERROR("CDomain::checkAttributes(void)", << "data_i_index undefined") ;
391
392         if (1 == data_dim.getValue())
393         {
394            const int dni = data_ni.getValue();
395            data_i_index.resize(dni) ;
396            data_j_index.resize(dni) ;
397
398            for (int i = 0; i < dni; ++i)
399            {
400              data_i_index(i) = i;
401              data_j_index(i) = 0;
402            }
403         }
404         else   // (data_dim == 2)
405         {
406            const int dni = data_ni.getValue() * data_nj.getValue();
407            data_i_index.resize(dni) ;
408            data_j_index.resize(dni) ;
409
410            for(int count = 0, j = 0; j  < data_nj.getValue(); ++j)
411            {
412               for(int i = 0; i < data_ni.getValue(); ++i, ++count)
413               {
414                  data_i_index(count) = i;
415                  data_j_index(count) = j;
416               }
417            }
418         }
419      }
420   }
421
422   //----------------------------------------------------------------
423
424   void CDomain::checkEligibilityForCompressedOutput(void)
425   {
426     // We don't check if the mask or the indexes are valid here, just if they have been defined at this point.
427     isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !data_i_index.isEmpty();
428   }
429
430   //----------------------------------------------------------------
431
432   void CDomain::completeLonLatClient(void)
433   {
434     int i,j,k ;
435     CArray<double,1> lonvalue_temp(ni*nj) ;
436     CArray<double,2> bounds_lon_temp(nvertex,ni*nj);
437     CArray<double,1> latvalue_temp(ni*nj) ;
438     CArray<double,2> bounds_lat_temp(nvertex,ni*nj);
439
440     if (!lonvalue_2d.isEmpty())
441     {
442        for (j = 0; j < nj; ++j)
443          for (i = 0; i < ni; ++i)
444          {
445            lonvalue_temp(i+j*ni) = lonvalue_2d(i,j);
446            latvalue_temp(i+j*ni) = latvalue_2d(i,j);
447            if (hasBounds)
448            {
449              k=j*ni+i;
450              for(int n=0;n<nvertex;++n)
451              {
452                bounds_lon_temp(n,k) = bounds_lon_2d(n,i,j);
453                bounds_lat_temp(n,k) = bounds_lat_2d(n,i,j);
454              }
455            }
456          }
457     }
458
459     if (!lonvalue_1d.isEmpty())
460     {
461       if (type_attr::rectilinear == type)
462       {
463         if ((ni == lonvalue_1d.numElements()) && (nj == latvalue_1d.numElements()))
464         {
465           for(j=0;j<nj;++j)
466             for(i=0;i<ni;++i)
467             {
468               k=j*ni+i;
469               lonvalue_temp(k) = lonvalue_1d(i);
470               latvalue_temp(k) = latvalue_1d(j);
471               if (hasBounds)
472               {
473                 for(int n=0;n<nvertex;++n)
474                 {
475                   bounds_lon_temp(n,k) = bounds_lon_1d(n,i);
476                   bounds_lat_temp(n,k) = bounds_lat_1d(n,j);
477                 }
478               }
479             }
480          }
481          else
482            ERROR("CDomain::completeLonClient(void)",
483                 <<"lonvalue_1d and latvalue_1d has not the same size as the local domain"<<endl
484                 <<"Local size is "<<ni<<"x " << nj<< endl
485                 <<"lonvalue_1d size is "<<lonvalue_1d.numElements()
486                 <<"latvalue_1d size is "<<latvalue_1d.numElements());
487       }
488       else if (type==type_attr::curvilinear || type==type_attr::unstructured)
489       {
490         lonvalue_temp=lonvalue_1d;
491         latvalue_temp=latvalue_1d;
492         if (hasBounds)
493         {
494           bounds_lon_temp=bounds_lon_1d;
495           bounds_lat_temp=bounds_lat_1d;
496         }
497       }
498     }
499
500    int i_ind,j_ind;
501    int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1;
502    int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1;
503
504    int globalIndexCountZoom = 0;
505    int nbIndex = i_index.numElements();
506    for (i = 0; i < nbIndex; ++i)
507    {
508      i_ind=i_index(i);
509      j_ind=j_index(i);
510
511      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
512      {
513        ++globalIndexCountZoom;
514      }
515    }
516
517      // Make sure that this attribute is non-empty for every client.
518     if (0 != globalIndexCountZoom)
519     {
520       lonvalue_client.resize(globalIndexCountZoom);
521       latvalue_client.resize(globalIndexCountZoom);
522       if (hasBounds)
523       {
524         bounds_lon_client.resize(nvertex,globalIndexCountZoom);
525         bounds_lat_client.resize(nvertex,globalIndexCountZoom);
526       }
527     }
528
529     int nCountZoom = 0;
530     for (i = 0; i < nbIndex; ++i)
531     {
532       i_ind=i_index(i);
533       j_ind=j_index(i);
534
535       if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
536       {
537         lonvalue_client(nCountZoom) = lonvalue_temp(i);
538         latvalue_client(nCountZoom) = latvalue_temp(i);
539         if (hasBounds)
540         {
541           for (int n = 0; n < nvertex; ++n)
542           {
543             bounds_lon_client(n,nCountZoom) = bounds_lon_temp(n,i);
544             bounds_lat_client(n,nCountZoom) = bounds_lat_temp(n,i);
545           }
546         }
547         ++nCountZoom;
548       }
549     }
550   }
551
552   void CDomain::checkBounds(void)
553   {
554     if (!nvertex.isEmpty() && (0 != nvertex.getValue()))
555     {
556       if (!bounds_lon_1d.isEmpty() && !bounds_lon_2d.isEmpty())
557         ERROR("CDomain::checkBounds(void)",
558              <<"Only one longitude boundary value can be used but both bounds_lon_1d and bounds_lon_2d are defined! "<<endl
559              <<"Define only one longitude boundary value: lonvalue_1d or bounds_lon_2d ");
560
561       if (!bounds_lat_1d.isEmpty() && !bounds_lat_2d.isEmpty())
562         ERROR("CDomain::checkBounds(void)",
563              <<"Only one latitude boundary value can be used but both bounds_lat_1d and bounds_lat_2d are defined! "<<endl
564              <<"Define only one latitude boundary value: bounds_lat_1d or bounds_lat_2d ");
565
566       if ((!bounds_lon_1d.isEmpty() && bounds_lat_1d.isEmpty()) || (bounds_lon_1d.isEmpty() && !bounds_lat_1d.isEmpty()))
567       {
568         ERROR("CDomain::checkBounds(void)",
569           <<"Only bounds_lon_1d or bounds_lat_1d is defined "<<endl
570           <<"Both must be defined ");
571       }
572
573       if ((!bounds_lon_2d.isEmpty() && bounds_lat_2d.isEmpty()) || (bounds_lon_2d.isEmpty() && !bounds_lat_2d.isEmpty()))
574       {
575         ERROR("CDomain::checkBounds(void)",
576           <<"Only bounds_lon_2d or bounds_lat_2d is defined "<<endl
577           <<"Both must be defined ");
578       }
579
580       if (!bounds_lon_1d.isEmpty() && (nvertex.getValue() != bounds_lon_1d.extent(0)))
581          ERROR("CDomain::checkBounds(void)",
582                <<"Only bounds_lon_1d and nvertex are not compatible"<<endl
583                <<"bounds_lon_1d dimension is " << bounds_lon_1d.extent(1)
584                <<"but nvertex is " << nvertex.getValue());
585
586       if (!bounds_lon_2d.isEmpty() && (nvertex.getValue() != bounds_lon_2d.extent(0)))
587          ERROR("CDomain::checkBounds(void)",
588                <<"Only bounds_lon_2d and nvertex are not compatible"<<endl
589                <<"bounds_lon_2d dimension is " << bounds_lon_1d.extent(2)
590                <<"but nvertex is " << nvertex.getValue());
591
592       if (!bounds_lon_1d.isEmpty() && lonvalue_1d.isEmpty())
593           ERROR("CDomain::checkBounds(void)",
594                <<"Both bounds_lon_1d and lonvalue_1d must be defined"<<endl);
595
596       if (!bounds_lon_2d.isEmpty() && lonvalue_2d.isEmpty())
597           ERROR("CDomain::checkBounds(void)",
598                <<"Both bounds_lon_1d and lonvalue_1d must be defined"<<endl);
599
600       if (!bounds_lat_1d.isEmpty() && (nvertex.getValue() != bounds_lat_1d.extent(0)))
601          ERROR("CDomain::checkBounds(void)",
602                <<"Only bounds_lat_1d and nvertex are not compatible"<<endl
603                <<"bounds_lat_1d dimension is " << bounds_lat_1d.extent(1)
604                <<"but nvertex is " << nvertex.getValue());
605
606       if (!bounds_lat_2d.isEmpty() && (nvertex.getValue() != bounds_lat_2d.extent(0)))
607          ERROR("CDomain::checkBounds(void)",
608                <<"Only bounds_lat_2d and nvertex are not compatible"<<endl
609                <<"bounds_lat_2d dimension is " << bounds_lat_1d.extent(2)
610                <<"but nvertex is " << nvertex.getValue());
611
612       if (!bounds_lat_1d.isEmpty() && latvalue_1d.isEmpty())
613           ERROR("CDomain::checkBounds(void)",
614                <<"Both bounds_lat_1d and latvalue_1d must be defined"<<endl);
615
616       if (!bounds_lat_2d.isEmpty() && latvalue_2d.isEmpty())
617           ERROR("CDomain::checkBounds(void)",
618                <<"Both bounds_lat_1d and latvalue_1d must be defined"<<endl);
619       hasBounds=true ;
620     }
621     else
622     {
623       hasBounds=false;
624       nvertex=0 ;
625     }
626   }
627
628   void CDomain::checkArea(void)
629   {
630     hasArea = !area.isEmpty();
631     if (hasArea)
632     {
633       if (area.extent(0) != ni || area.extent(1) != nj)
634       {
635         ERROR("void CDomain::checkArea(void)",
636               "The area attribute must be of size ni x nj.");
637       }
638     }
639   }
640
641   void CDomain::checkLonLat()
642   {
643     hasLonLat = (!latvalue_1d.isEmpty() && !lonvalue_1d.isEmpty()) ||
644                 (!latvalue_2d.isEmpty() && !lonvalue_2d.isEmpty());
645     if (hasLonLat)
646     {
647       if (!lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
648         ERROR("CDomain::completeLonLatClient(void)",
649              <<"Only one longitude value can be used but both lonvalue_1d and lonvalue_2d are defined! "<<endl
650              <<"Define only one longitude value: lonvalue_1d or lonvalue_2d ");
651
652       if (!lonvalue_1d.isEmpty() && lonvalue_2d.isEmpty())
653       {
654         if (lonvalue_1d.numElements() != i_index.numElements())
655           ERROR("CDomain::completeLonLatClient(void)",
656                 <<"lonvalue_1d has not the same size as the local domain"<<endl
657                 <<"Local size is "<<i_index.numElements()<<endl
658                 <<"lonvalue_1d size is "<<lonvalue_1d.numElements());
659       }
660
661       if (lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
662       {
663          if ((lonvalue_2d.extent(0) != ni) ||
664              (lonvalue_2d.extent(1) != nj))
665             ERROR("CDomain::completeLonLatClient(void)",
666                   <<"the lonvalue has not the same size as the local domain"<<endl
667                   <<"Local size is "<<ni<<"x"<<nj<<endl
668                   <<"Lonvalue size is "<<lonvalue_2d.extent(0)<<"x"<<lonvalue_2d.extent(1));
669       }
670
671       if (!latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
672         ERROR("CDomain::completeLonLatClient(void)",
673              <<"Only one longitude value can be used but both latvalue_1d and latvalue_2d are defined! "<<endl
674              <<"Define only one longitude value: latvalue_1d or latvalue_2d ");
675
676       if (!latvalue_1d.isEmpty() && latvalue_2d.isEmpty())
677       {
678         if (latvalue_1d.numElements() != i_index.numElements())
679           ERROR("CDomain::completeLonLatClient(void)",
680                 <<"the latvalue_1d has not the same size as the local domain"<<endl
681                 <<"Local size is "<<i_index.numElements()<<endl
682                 <<"Mask size is "<<latvalue_1d.numElements());
683       }
684
685       if (latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
686       {
687          if ((latvalue_2d.extent(0) != ni) ||
688              (latvalue_2d.extent(1) != nj))
689             ERROR("CDomain::completeLonLatClient(void)",
690                   <<"the mask has not the same size as the local domain"<<endl
691                   <<"Local size is "<<ni<<"x"<<nj<<endl
692                   <<"Mask size is "<<latvalue_2d.extent(0)<<"x"<<latvalue_2d.extent(1));
693       }
694     }
695   }
696
697   void CDomain::checkAttributesOnClientAfterTransformation()
698   {
699     CContext* context=CContext::getCurrent() ;
700
701     if (this->isClientAfterTransformationChecked) return;
702     if (context->hasClient)
703     {
704       this->checkMask();
705       if (hasLonLat || hasArea) this->computeConnectedServer();
706       if (hasLonLat) this->completeLonLatClient();
707     }
708
709     this->isClientAfterTransformationChecked = true;
710   }
711
712   //----------------------------------------------------------------
713   // Divide function checkAttributes into 2 seperate ones
714   // This function only checks all attributes of current domain
715   void CDomain::checkAttributesOnClient()
716   {
717     if (this->isClientChecked) return;
718     CContext* context=CContext::getCurrent();
719
720      this->checkDomain();
721      this->checkBounds();
722      this->checkArea();
723      this->checkLonLat();
724
725      if (context->hasClient)
726      { // CÃŽté client uniquement
727         this->checkMask();
728         this->checkDomainData();
729         this->checkCompression();
730      }
731      else
732      { // CÃŽté serveur uniquement
733      }
734
735      this->isClientChecked = true;
736   }
737
738   // Send all checked attributes to server
739   void CDomain::sendCheckedAttributes()
740   {
741     if (!this->isClientChecked) checkAttributesOnClient();
742     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation();
743     CContext* context=CContext::getCurrent() ;
744
745     if (this->isChecked) return;
746     if (context->hasClient)
747     {
748       sendServerAttribut();
749       if (hasLonLat || hasArea) sendLonLatArea();
750     }
751     this->isChecked = true;
752   }
753
754   void CDomain::checkAttributes(void)
755   {
756      if (this->isChecked) return;
757      CContext* context=CContext::getCurrent() ;
758
759      this->checkDomain();
760      this->checkLonLat();
761      this->checkBounds();
762      this->checkArea();
763
764      if (context->hasClient)
765      { // CÃŽté client uniquement
766         this->checkMask();
767         this->checkDomainData();
768         this->checkCompression();
769
770      }
771      else
772      { // CÃŽté serveur uniquement
773      }
774
775      if (context->hasClient)
776      {
777        this->computeConnectedServer();
778        this->completeLonLatClient();
779        this->sendServerAttribut();
780        this->sendLonLatArea();
781      }
782
783      this->isChecked = true;
784   }
785
786  void CDomain::sendServerAttribut(void)
787  {
788    CServerDistributionDescription serverDescription(nGlobDomain_);
789
790    CContext* context = CContext::getCurrent();
791    CContextClient* client = context->client;
792    int nbServer = client->serverSize;
793
794    if (isUnstructed_) serverDescription.computeServerDistribution(nbServer,0);
795    else serverDescription.computeServerDistribution(nbServer,1);
796
797    std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
798    std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
799
800    CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT);
801    if (client->isServerLeader())
802    {
803      std::list<CMessage> msgs;
804
805      const std::list<int>& ranks = client->getRanksServerLeader();
806      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
807      {
808        // Use const int to ensure CMessage holds a copy of the value instead of just a reference
809        const int ibegin_srv = serverIndexBegin[*itRank][0];
810        const int jbegin_srv = serverIndexBegin[*itRank][1];
811        const int ni_srv = serverDimensionSizes[*itRank][0];
812        const int nj_srv = serverDimensionSizes[*itRank][1];
813        const int iend_srv = ibegin_srv + ni_srv - 1;
814        const int jend_srv = jbegin_srv + nj_srv - 1;
815
816        msgs.push_back(CMessage());
817        CMessage& msg = msgs.back();
818        msg << this->getId() ;
819        msg << ni_srv << ibegin_srv << iend_srv << nj_srv << jbegin_srv << jend_srv;
820        msg << global_zoom_ni << global_zoom_ibegin << global_zoom_nj << global_zoom_jbegin;
821        msg << isCompressible_;
822
823        event.push(*itRank,1,msg);
824      }
825      client->sendEvent(event);
826    }
827    else client->sendEvent(event);
828  }
829
830  void CDomain::computeNGlobDomain()
831  {
832    nGlobDomain_.resize(2);
833    nGlobDomain_[0] = ni_glo.getValue();
834    nGlobDomain_[1] = nj_glo.getValue();
835  }
836
837  void CDomain::computeConnectedServer(void)
838  {
839    CContext* context=CContext::getCurrent() ;
840    CContextClient* client=context->client ;
841    int nbServer=client->serverSize;
842    bool doComputeGlobalIndexServer = true;
843
844    int i,j,i_ind,j_ind, nbIndex;
845    int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1 ;
846    int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1 ;
847
848    // Precompute number of index
849    int globalIndexCountZoom = 0;
850    nbIndex = i_index.numElements();
851    for (i = 0; i < nbIndex; ++i)
852    {
853      i_ind=i_index(i);
854      j_ind=j_index(i);
855
856      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
857      {
858        ++globalIndexCountZoom;
859      }
860    }
861
862    int globalIndexWrittenCount = 0;
863    if (isCompressible_)
864    {
865      for (i = 0; i < data_i_index.numElements(); ++i)
866      {
867        i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
868                                                    data_ibegin, data_jbegin, data_dim, ni,
869                                                    j_ind);
870        if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
871        {
872          i_ind += ibegin;
873          j_ind += jbegin;
874          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
875            ++globalIndexWrittenCount;
876        }
877      }
878    }
879
880    // Fill in index
881    CArray<size_t,1> globalIndexDomainZoom(globalIndexCountZoom);
882    CArray<size_t,1> localIndexDomainZoom(globalIndexCountZoom);
883    CArray<size_t,1> globalIndexDomain(nbIndex);
884    size_t globalIndex;
885    int globalIndexCount = 0;
886    globalIndexCountZoom = 0;
887
888    for (i = 0; i < nbIndex; ++i)
889    {
890      i_ind=i_index(i);
891      j_ind=j_index(i);
892      globalIndex = i_ind + j_ind * ni_glo;
893      globalIndexDomain(globalIndexCount) = globalIndex;
894      ++globalIndexCount;
895      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
896      {
897        globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
898        localIndexDomainZoom(globalIndexCountZoom) = i;
899        ++globalIndexCountZoom;
900      }
901    }
902
903    CArray<int,1> globalIndexWrittenDomain(globalIndexWrittenCount);
904    if (isCompressible_)
905    {
906      globalIndexWrittenCount = 0;
907      for (i = 0; i < data_i_index.numElements(); ++i)
908      {
909        i_ind = CDistributionClient::getDomainIndex(data_i_index(i), data_j_index(i),
910                                                    data_ibegin, data_jbegin, data_dim, ni,
911                                                    j_ind);
912        if (i_ind >= 0 && i_ind < ni && j_ind >= 0 && j_ind < nj && mask_1d(i_ind + j_ind * ni))
913        {
914          i_ind += ibegin;
915          j_ind += jbegin;
916          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
917          {
918            globalIndexWrittenDomain(globalIndexWrittenCount) = i_ind + j_ind * ni_glo;
919            ++globalIndexWrittenCount;
920          }
921        }
922      }
923    }
924
925    size_t globalSizeIndex = 1, indexBegin, indexEnd;
926    int range, clientSize = client->clientSize;
927    for (int i = 0; i < nGlobDomain_.size(); ++i) globalSizeIndex *= nGlobDomain_[i];
928    indexBegin = 0;
929    for (int i = 0; i < clientSize; ++i)
930    {
931      range = globalSizeIndex / clientSize;
932      if (i < (globalSizeIndex%clientSize)) ++range;
933      if (i == client->clientRank) break;
934      indexBegin += range;
935    }
936    indexEnd = indexBegin + range - 1;
937
938    CServerDistributionDescription serverDescription(nGlobDomain_);
939    if (isUnstructed_) serverDescription.computeServerGlobalIndexInRange(nbServer, std::make_pair<size_t,size_t>(indexBegin, indexEnd), 0);
940    else serverDescription.computeServerGlobalIndexInRange(nbServer, std::make_pair<size_t,size_t>(indexBegin, indexEnd), 1);
941
942    CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(),
943                                                                                client->intraComm);
944    clientServerMap->computeServerIndexMapping(globalIndexDomain);
945    const std::map<int, std::vector<size_t> >& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer();
946
947    std::map<int, std::vector<size_t> >::const_iterator it = globalIndexDomainOnServer.begin(),
948                                                       ite = globalIndexDomainOnServer.end();
949    typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
950    std::vector<int>::iterator itVec;
951
952    indSrv_.clear();
953    indWrittenSrv_.clear();
954    for (; it != ite; ++it)
955    {
956      int rank = it->first;
957      int indexSize = it->second.size();
958      std::vector<int> permutIndex(indexSize);
959      XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
960      XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(it->second, permutIndex);
961      BinarySearch binSearch(it->second);
962      int nb = globalIndexDomainZoom.numElements();
963      for (int i = 0; i < nb; ++i)
964      {
965        if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexDomainZoom(i), itVec))
966        {
967          indSrv_[rank].push_back(localIndexDomainZoom(i));
968        }
969      }
970      for (int i = 0; i < globalIndexWrittenDomain.numElements(); ++i)
971      {
972        if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexWrittenDomain(i), itVec))
973        {
974          indWrittenSrv_[rank].push_back(globalIndexWrittenDomain(i));
975        }
976      }
977    }
978
979    connectedServerRank_.clear();
980    for (it = globalIndexDomainOnServer.begin(); it != ite; ++it) {
981      connectedServerRank_.push_back(it->first);
982    }
983
984    if (!indSrv_.empty())
985    {
986      connectedServerRank_.clear();
987      for (it = indSrv_.begin(); it != indSrv_.end(); ++it)
988        connectedServerRank_.push_back(it->first);
989    }
990    nbConnectedClients_ = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
991
992    delete clientServerMap;
993  }
994
995  const std::map<int, vector<size_t> >& CDomain::getIndexServer() const
996  {
997    return indSrv_;
998  }
999
1000  /*!
1001    Send index from client to server(s)
1002  */
1003  void CDomain::sendIndex()
1004  {
1005    int ns, n, i, j, ind, nv, idx;
1006    CContext* context = CContext::getCurrent();
1007    CContextClient* client=context->client;
1008
1009    CEventClient eventIndex(getType(), EVENT_ID_INDEX);
1010
1011    list<CMessage> list_msgsIndex;
1012    list<CArray<int,1> > list_indi, list_indj, list_writtenInd;
1013
1014    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1015    iteMap = indSrv_.end();
1016    for (int k = 0; k < connectedServerRank_.size(); ++k)
1017    {
1018      int nbData = 0;
1019      int rank = connectedServerRank_[k];
1020      it = indSrv_.find(rank);
1021      if (iteMap != it)
1022        nbData = it->second.size();
1023
1024      list_indi.push_back(CArray<int,1>(nbData));
1025      list_indj.push_back(CArray<int,1>(nbData));
1026
1027      CArray<int,1>& indi = list_indi.back();
1028      CArray<int,1>& indj = list_indj.back();
1029      const std::vector<size_t>& temp = it->second;
1030      for (n = 0; n < nbData; ++n)
1031      {
1032        idx = static_cast<int>(it->second[n]);
1033        indi(n) = i_index(idx);
1034        indj(n) = j_index(idx);
1035      }
1036
1037      list_msgsIndex.push_back(CMessage());
1038
1039      list_msgsIndex.back() << this->getId() << (int)type; // enum ne fonctionne pour les message => ToFix
1040      list_msgsIndex.back() << isCurvilinear;
1041      list_msgsIndex.back() << list_indi.back() << list_indj.back();
1042
1043      if (isCompressible_)
1044      {
1045        std::vector<int>& writtenIndSrc = indWrittenSrv_[rank];
1046        list_writtenInd.push_back(CArray<int,1>(writtenIndSrc.size()));
1047        CArray<int,1>& writtenInd = list_writtenInd.back();
1048
1049        for (n = 0; n < writtenInd.numElements(); ++n)
1050          writtenInd(n) = writtenIndSrc[n];
1051
1052        list_msgsIndex.back() << writtenInd;
1053      }
1054
1055      eventIndex.push(rank, nbConnectedClients_[rank], list_msgsIndex.back());
1056    }
1057
1058    client->sendEvent(eventIndex);
1059  }
1060
1061  /*!
1062    Send area from client to server(s)
1063  */
1064  void CDomain::sendArea()
1065  {
1066    if (!hasArea) return;
1067
1068    int ns, n, i, j, ind, nv, idx;
1069    CContext* context = CContext::getCurrent();
1070    CContextClient* client=context->client;
1071
1072    // send area for each connected server
1073    CEventClient eventArea(getType(), EVENT_ID_AREA);
1074
1075    list<CMessage> list_msgsArea;
1076    list<CArray<double,1> > list_area;
1077
1078    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1079    iteMap = indSrv_.end();
1080    for (int k = 0; k < connectedServerRank_.size(); ++k)
1081    {
1082      int nbData = 0;
1083      int rank = connectedServerRank_[k];
1084      it = indSrv_.find(rank);
1085      if (iteMap != it)
1086        nbData = it->second.size();
1087      list_area.push_back(CArray<double,1>(nbData));
1088
1089      const std::vector<size_t>& temp = it->second;
1090      for (n = 0; n < nbData; ++n)
1091      {
1092        idx = static_cast<int>(it->second[n]);
1093        i = i_index(idx);
1094        j = j_index(idx);
1095        if (hasArea)
1096          list_area.back()(n) = area(i - ibegin, j - jbegin);
1097      }
1098
1099      list_msgsArea.push_back(CMessage());
1100      list_msgsArea.back() << this->getId() << list_area.back();
1101      eventArea.push(rank, nbConnectedClients_[rank], list_msgsArea.back());
1102    }
1103    client->sendEvent(eventArea);
1104  }
1105
1106  /*!
1107    Send longitude and latitude from client to servers
1108    Each client send long and lat information to corresponding connected server(s).
1109    Because longitude and latitude are optional, this function only called if latitude and longitude exist
1110  */
1111  void CDomain::sendLonLat()
1112  {
1113    if (!hasLonLat) return;
1114
1115    int ns, n, i, j, ind, nv, idx;
1116    CContext* context = CContext::getCurrent();
1117    CContextClient* client=context->client;
1118
1119    // send lon lat for each connected server
1120    CEventClient eventLon(getType(), EVENT_ID_LON);
1121    CEventClient eventLat(getType(), EVENT_ID_LAT);
1122
1123    list<CMessage> list_msgsLon, list_msgsLat;
1124    list<CArray<double,1> > list_lon, list_lat;
1125    list<CArray<double,2> > list_boundslon, list_boundslat;
1126
1127    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
1128    iteMap = indSrv_.end();
1129    for (int k = 0; k < connectedServerRank_.size(); ++k)
1130    {
1131      int nbData = 0;
1132      int rank = connectedServerRank_[k];
1133      it = indSrv_.find(rank);
1134      if (iteMap != it)
1135        nbData = it->second.size();
1136
1137      list_lon.push_back(CArray<double,1>(nbData));
1138      list_lat.push_back(CArray<double,1>(nbData));
1139
1140      if (hasBounds)
1141      {
1142        list_boundslon.push_back(CArray<double,2>(nvertex, nbData));
1143        list_boundslat.push_back(CArray<double,2>(nvertex, nbData));
1144      }
1145
1146      CArray<double,1>& lon = list_lon.back();
1147      CArray<double,1>& lat = list_lat.back();
1148      const std::vector<size_t>& temp = it->second;
1149      for (n = 0; n < nbData; ++n)
1150      {
1151        idx = static_cast<int>(it->second[n]);
1152        lon(n) = lonvalue_client(idx);
1153        lat(n) = latvalue_client(idx);
1154
1155        if (hasBounds)
1156        {
1157          CArray<double,2>& boundslon = list_boundslon.back();
1158          CArray<double,2>& boundslat = list_boundslat.back();
1159
1160          for (nv = 0; nv < nvertex; ++nv)
1161          {
1162            boundslon(nv, n) = bounds_lon_client(nv, idx);
1163            boundslat(nv, n) = bounds_lat_client(nv, idx);
1164          }
1165        }
1166      }
1167
1168      list_msgsLon.push_back(CMessage());
1169      list_msgsLat.push_back(CMessage());
1170
1171      list_msgsLon.back() << this->getId() << list_lon.back();
1172      list_msgsLat.back() << this->getId() << list_lat.back();
1173
1174      if (hasBounds)
1175      {
1176        list_msgsLon.back() << list_boundslon.back();
1177        list_msgsLat.back() << list_boundslat.back();
1178      }
1179
1180      eventLon.push(rank, nbConnectedClients_[rank], list_msgsLon.back());
1181      eventLat.push(rank, nbConnectedClients_[rank], list_msgsLat.back());
1182    }
1183
1184    client->sendEvent(eventLon);
1185    client->sendEvent(eventLat);
1186  }
1187
1188  /*!
1189    Send some optional information to server(s)
1190    In the future, this function can be extended with more optional information to send
1191  */
1192  void CDomain::sendLonLatArea(void)
1193  {
1194    sendIndex();
1195    sendLonLat();
1196    sendArea();
1197  }
1198
1199  bool CDomain::dispatchEvent(CEventServer& event)
1200  {
1201    if (SuperClass::dispatchEvent(event)) return true;
1202    else
1203    {
1204      switch(event.type)
1205      {
1206        case EVENT_ID_SERVER_ATTRIBUT:
1207          recvServerAttribut(event);
1208          return true;
1209          break;
1210        case EVENT_ID_INDEX:
1211          recvIndex(event);
1212          return true;
1213          break;
1214        case EVENT_ID_LON:
1215          recvLon(event);
1216          return true;
1217          break;
1218        case EVENT_ID_LAT:
1219          recvLat(event);
1220          return true;
1221          break;
1222        case EVENT_ID_AREA:
1223          recvArea(event);
1224          return true;
1225          break;
1226        default:
1227          ERROR("bool CContext::dispatchEvent(CEventServer& event)",
1228                << "Unknown Event");
1229          return false;
1230       }
1231    }
1232  }
1233
1234  /*!
1235    Receive attributes event from clients(s)
1236    \param[in] event event contain info about rank and associated attributes
1237  */
1238  void CDomain::recvServerAttribut(CEventServer& event)
1239  {
1240    CBufferIn* buffer=event.subEvents.begin()->buffer;
1241    string domainId ;
1242    *buffer>>domainId ;
1243    get(domainId)->recvServerAttribut(*buffer) ;
1244  }
1245
1246  /*!
1247    Receive attributes from client(s): zoom info and begin and n of each server
1248    \param[in] rank rank of client source
1249    \param[in] buffer message containing attributes info
1250  */
1251  void CDomain::recvServerAttribut(CBufferIn& buffer)
1252  {
1253    buffer >> ni_srv >> ibegin_srv >> iend_srv >> nj_srv >> jbegin_srv >> jend_srv
1254           >> global_zoom_ni >> global_zoom_ibegin >> global_zoom_nj >> global_zoom_jbegin
1255           >> isCompressible_;
1256
1257    int zoom_iend = global_zoom_ibegin + global_zoom_ni - 1;
1258    int zoom_jend = global_zoom_jbegin + global_zoom_nj - 1;
1259
1260    zoom_ibegin_srv = global_zoom_ibegin > ibegin_srv ? global_zoom_ibegin : ibegin_srv ;
1261    zoom_iend_srv = zoom_iend < iend_srv ? zoom_iend : iend_srv ;
1262    zoom_ni_srv=zoom_iend_srv-zoom_ibegin_srv+1 ;
1263
1264    zoom_jbegin_srv = global_zoom_jbegin > jbegin_srv ? global_zoom_jbegin : jbegin_srv ;
1265    zoom_jend_srv = zoom_jend < jend_srv ? zoom_jend : jend_srv ;
1266    zoom_nj_srv=zoom_jend_srv-zoom_jbegin_srv+1 ;
1267
1268    if (zoom_ni_srv<=0 || zoom_nj_srv<=0)
1269    {
1270      zoom_ibegin_srv=0 ; zoom_iend_srv=0 ; zoom_ni_srv=0 ;
1271      zoom_jbegin_srv=0 ; zoom_jend_srv=0 ; zoom_nj_srv=0 ;
1272    }
1273    lonvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
1274    lonvalue_srv = 0. ;
1275    latvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
1276    latvalue_srv = 0. ;
1277    if (hasBounds)
1278    {
1279      bounds_lon_srv.resize(nvertex,zoom_ni_srv*zoom_nj_srv) ;
1280      bounds_lon_srv = 0. ;
1281      bounds_lat_srv.resize(nvertex,zoom_ni_srv*zoom_nj_srv) ;
1282      bounds_lat_srv = 0. ;
1283    }
1284
1285    if (hasArea)
1286      area_srv.resize(zoom_ni_srv * zoom_nj_srv);
1287  }
1288
1289  /*!
1290    Receive index event from clients(s)
1291    \param[in] event event contain info about rank and associated index
1292  */
1293  void CDomain::recvIndex(CEventServer& event)
1294  {
1295    CDomain* domain;
1296
1297    list<CEventServer::SSubEvent>::iterator it;
1298    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1299    {
1300      CBufferIn* buffer = it->buffer;
1301      string domainId;
1302      *buffer >> domainId;
1303      domain = get(domainId);
1304      domain->recvIndex(it->rank, *buffer);
1305    }
1306
1307    if (domain->isCompressible_)
1308    {
1309      std::sort(domain->indexesToWrite.begin(), domain->indexesToWrite.end());
1310
1311      CContextServer* server = CContext::getCurrent()->server;
1312      domain->numberWrittenIndexes_ = domain->indexesToWrite.size();
1313      MPI_Allreduce(&domain->numberWrittenIndexes_, &domain->totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1314      MPI_Scan(&domain->numberWrittenIndexes_, &domain->offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm);
1315      domain->offsetWrittenIndexes_ -= domain->numberWrittenIndexes_;
1316    }
1317  }
1318
1319  /*!
1320    Receive index information from client(s)
1321    \param[in] rank rank of client source
1322    \param[in] buffer message containing index info
1323  */
1324  void CDomain::recvIndex(int rank, CBufferIn& buffer)
1325  {
1326    int type_int;
1327    buffer >> type_int >> isCurvilinear >> indiSrv[rank] >> indjSrv[rank];
1328    type.setValue((type_attr::t_enum)type_int); // probleme des type enum avec les buffers : ToFix
1329
1330    if (isCompressible_)
1331    {
1332      CArray<int, 1> writtenIndexes;
1333      buffer >> writtenIndexes;
1334      indexesToWrite.reserve(indexesToWrite.size() + writtenIndexes.numElements());
1335      for (int i = 0; i < writtenIndexes.numElements(); ++i)
1336        indexesToWrite.push_back(writtenIndexes(i));
1337    }
1338  }
1339
1340  /*!
1341    Receive longitude event from clients(s)
1342    \param[in] event event contain info about rank and associated longitude
1343  */
1344  void CDomain::recvLon(CEventServer& event)
1345  {
1346    list<CEventServer::SSubEvent>::iterator it;
1347    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1348    {
1349      CBufferIn* buffer = it->buffer;
1350      string domainId;
1351      *buffer >> domainId;
1352      get(domainId)->recvLon(it->rank, *buffer);
1353    }
1354  }
1355
1356  /*!
1357    Receive longitude information from client(s)
1358    \param[in] rank rank of client source
1359    \param[in] buffer message containing longitude info
1360  */
1361  void CDomain::recvLon(int rank, CBufferIn& buffer)
1362  {
1363    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1364    CArray<double,1> lon;
1365    CArray<double,2> boundslon;
1366
1367    buffer >> lon;
1368    if (hasBounds) buffer >> boundslon;
1369
1370    int i, j, ind_srv;
1371    for (int ind = 0; ind < indi.numElements(); ind++)
1372    {
1373      i = indi(ind); j = indj(ind);
1374      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1375      lonvalue_srv(ind_srv) = lon(ind);
1376      if (hasBounds)
1377      {
1378        for (int nv = 0; nv < nvertex; ++nv)
1379          bounds_lon_srv(nv, ind_srv) = boundslon(nv, ind);
1380      }
1381    }
1382  }
1383
1384  /*!
1385    Receive latitude event from clients(s)
1386    \param[in] event event contain info about rank and associated latitude
1387  */
1388  void CDomain::recvLat(CEventServer& event)
1389  {
1390    list<CEventServer::SSubEvent>::iterator it;
1391    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1392    {
1393      CBufferIn* buffer = it->buffer;
1394      string domainId;
1395      *buffer >> domainId;
1396      get(domainId)->recvLat(it->rank, *buffer);
1397    }
1398  }
1399
1400  /*!
1401    Receive latitude information from client(s)
1402    \param[in] rank rank of client source
1403    \param[in] buffer message containing latitude info
1404  */
1405  void CDomain::recvLat(int rank, CBufferIn& buffer)
1406  {
1407    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1408    CArray<double,1> lat;
1409    CArray<double,2> boundslat;
1410
1411    buffer >> lat;
1412    if (hasBounds) buffer >> boundslat;
1413
1414    int i, j, ind_srv;
1415    for (int ind = 0; ind < indi.numElements(); ind++)
1416    {
1417      i = indi(ind); j = indj(ind);
1418      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1419      latvalue_srv(ind_srv) = lat(ind);
1420      if (hasBounds)
1421      {
1422        for (int nv = 0; nv < nvertex; nv++)
1423          bounds_lat_srv(nv, ind_srv) = boundslat(nv, ind);
1424      }
1425    }
1426  }
1427
1428  /*!
1429    Receive area event from clients(s)
1430    \param[in] event event contain info about rank and associated area
1431  */
1432  void CDomain::recvArea(CEventServer& event)
1433  {
1434    list<CEventServer::SSubEvent>::iterator it;
1435    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
1436    {
1437      CBufferIn* buffer = it->buffer;
1438      string domainId;
1439      *buffer >> domainId;
1440      get(domainId)->recvArea(it->rank, *buffer);
1441    }
1442  }
1443
1444  /*!
1445    Receive area information from client(s)
1446    \param[in] rank rank of client source
1447    \param[in] buffer message containing area info
1448  */
1449  void CDomain::recvArea(int rank, CBufferIn& buffer)
1450  {
1451    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1452    CArray<double,1> clientArea;
1453
1454    buffer >> clientArea;
1455
1456    int i, j, ind_srv;
1457    for (int ind = 0; ind < indi.numElements(); ind++)
1458    {
1459      i = indi(ind); j = indj(ind);
1460      ind_srv = (i - zoom_ibegin_srv) + (j - zoom_jbegin_srv) * zoom_ni_srv;
1461      area_srv(ind_srv) = clientArea(ind);
1462    }
1463  }
1464
1465  /*!
1466    Check whether a domain has transformation
1467    \return true if domain has transformation
1468  */
1469  bool CDomain::hasTransformation()
1470  {
1471    return (!transformationMap_.empty());
1472  }
1473
1474  /*!
1475    Set transformation for current domain. It's the method to move transformation in hierarchy
1476    \param [in] domTrans transformation on domain
1477  */
1478  void CDomain::setTransformations(const TransMapTypes& domTrans)
1479  {
1480    transformationMap_ = domTrans;
1481  }
1482
1483  /*!
1484    Get all transformation current domain has
1485    \return all transformation
1486  */
1487  CDomain::TransMapTypes CDomain::getAllTransformations(void)
1488  {
1489    return transformationMap_;
1490  }
1491
1492  /*!
1493    Check the validity of all transformations applied on domain
1494  This functions is called AFTER all inherited attributes are solved
1495  */
1496  void CDomain::checkTransformations()
1497  {
1498    TransMapTypes::const_iterator itb = transformationMap_.begin(), it,
1499                                  ite = transformationMap_.end();
1500    for (it = itb; it != ite; ++it)
1501    {
1502      (it->second)->checkValid(this);
1503    }
1504  }
1505
1506  /*!
1507    A current domain will go up the hierarchy to find out the domain from which it has transformation
1508  */
1509  void CDomain::solveInheritanceTransformation()
1510  {
1511    if (this->hasTransformation()) return;
1512
1513    std::vector<CDomain*> refDomain;
1514    CDomain* refer_sptr;
1515    CDomain* refer_ptr = this;
1516    while (refer_ptr->hasDirectDomainReference())
1517    {
1518      refDomain.push_back(refer_ptr);
1519      refer_sptr = refer_ptr->getDirectDomainReference();
1520      refer_ptr  = refer_sptr;
1521      if (refer_ptr->hasTransformation()) break;
1522    }
1523
1524    if (refer_ptr->hasTransformation())
1525      for (int idx = 0; idx < refDomain.size(); ++idx)
1526        refDomain[idx]->setTransformations(refer_ptr->getAllTransformations());
1527  }
1528
1529  /*!
1530    Parse children nodes of a domain in xml file.
1531    Whenver there is a new transformation, its type and name should be added into this function
1532    \param node child node to process
1533  */
1534  void CDomain::parse(xml::CXMLNode & node)
1535  {
1536    SuperClass::parse(node);
1537
1538    if (node.goToChildElement())
1539    {
1540      StdString zoomDomainDefRoot("zoom_domain_definition");
1541      StdString zoom("zoom_domain");
1542      StdString interpFromFileDomainDefRoot("interpolate_from_file_domain_definition");
1543      StdString interpFromFile("interpolate_from_file_domain");
1544      do
1545      {
1546        if (node.getElementName() == zoom) {
1547          CZoomDomain* tmp = (CZoomDomainGroup::get(zoomDomainDefRoot))->createChild();
1548          tmp->parse(node);
1549          transformationMap_.push_back(std::make_pair(TRANS_ZOOM_DOMAIN,tmp));
1550        }
1551        else if (node.getElementName() == interpFromFile)
1552        {
1553          CInterpolateFromFileDomain* tmp = (CInterpolateFromFileDomainGroup::get(interpFromFileDomainDefRoot))->createChild();
1554          tmp->parse(node);
1555          transformationMap_.push_back(std::make_pair(TRANS_INTERPOLATE_DOMAIN_FROM_FILE,tmp));
1556        }
1557      } while (node.goToNextElement()) ;
1558      node.goToParentElement();
1559    }
1560  }
1561   //----------------------------------------------------------------
1562
1563   DEFINE_REF_FUNC(Domain,domain)
1564
1565   ///---------------------------------------------------------------
1566
1567} // namespace xios
Note: See TracBrowser for help on using the repository browser.