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

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

Improve the error messages for axis and domains.

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