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
RevLine 
[219]1#include "domain.hpp"
2
[352]3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
[219]6
[591]7#include "xios_spl.hpp"
[300]8#include "event_client.hpp"
9#include "event_server.hpp"
10#include "buffer_in.hpp"
[352]11#include "message.hpp"
12#include "type.hpp"
13#include "context.hpp"
14#include "context_client.hpp"
[676]15#include "context_server.hpp"
[369]16#include "array_new.hpp"
[676]17#include "distribution_client.hpp"
[553]18#include "server_distribution_description.hpp"
[569]19#include "client_server_mapping_distributed.hpp"
[631]20#include "zoom_domain.hpp"
[657]21#include "interpolate_from_file_domain.hpp"
[274]22
[676]23#include <algorithm>
24
[335]25namespace xios {
[509]26
[219]27   /// ////////////////////// Définitions ////////////////////// ///
28
29   CDomain::CDomain(void)
30      : CObjectTemplate<CDomain>(), CDomainAttributes()
[584]31      , isChecked(false), relFiles(), isClientChecked(false), nbConnectedClients_(), indSrv_(), connectedServerRank_()
[676]32      , hasBounds(false), hasArea(false), isDistributed_(false), nGlobDomain_(), isCompressible_(false), isUnstructed_(false)
[664]33      , global_zoom_ni(0), global_zoom_ibegin(0), global_zoom_nj(0), global_zoom_jbegin(0)
[665]34      , isClientAfterTransformationChecked(false), hasLonLat(false)
[664]35      , lonvalue_client(), latvalue_client(), bounds_lon_client(), bounds_lat_client()
[219]36   { /* Ne rien faire de plus */ }
37
38   CDomain::CDomain(const StdString & id)
39      : CObjectTemplate<CDomain>(id), CDomainAttributes()
[584]40      , isChecked(false), relFiles(), isClientChecked(false), nbConnectedClients_(), indSrv_(), connectedServerRank_()
[676]41      , hasBounds(false), hasArea(false), isDistributed_(false), nGlobDomain_(), isCompressible_(false), isUnstructed_(false)
[664]42      , global_zoom_ni(0), global_zoom_ibegin(0), global_zoom_nj(0), global_zoom_jbegin(0)
[665]43      , isClientAfterTransformationChecked(false), hasLonLat(false)
[664]44      , lonvalue_client(), latvalue_client(), bounds_lon_client(), bounds_lat_client()
[635]45   { /* Ne rien faire de plus */ }
[219]46
47   CDomain::~CDomain(void)
[509]48   {
[219]49   }
50
51   ///---------------------------------------------------------------
52
[622]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
[219]64   const std::set<StdString> & CDomain::getRelFiles(void) const
65   {
[509]66      return (this->relFiles);
[219]67   }
68
69   //----------------------------------------------------------------
[676]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
[219]105   bool CDomain::isEmpty(void) const
106   {
[509]107      return ((this->zoom_ni_srv == 0) ||
[300]108              (this->zoom_nj_srv == 0));
[219]109   }
110
111   //----------------------------------------------------------------
[676]112
[219]113   bool CDomain::IsWritten(const StdString & filename) const
114   {
115      return (this->relFiles.find(filename) != this->relFiles.end());
116   }
117
[676]118   bool CDomain::isWrittenCompressed(const StdString& filename) const
119   {
120      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
121   }
122
[219]123   //----------------------------------------------------------------
[676]124
[594]125   bool CDomain::isDistributed(void) const
126   {
127      return isDistributed_;
128   }
129
130   //----------------------------------------------------------------
[676]131
132   /*!
133    * Test whether the data defined on the domain can be outputted in a compressed way.
[679]134    *
[676]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
[219]144   void CDomain::addRelFile(const StdString & filename)
145   {
146      this->relFiles.insert(filename);
147   }
148
[676]149   void CDomain::addRelFileCompressed(const StdString& filename)
150   {
151      this->relFilesCompressed.insert(filename);
152   }
[219]153
[676]154
[219]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
[467]161   void CDomain::checkDomain(void)
[219]162   {
[664]163     if (type.isEmpty())
164     {
165       ERROR("CDomain::checkDomain(void)",
[679]166             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
167             << "The domain type is mandatory, "
168             << "please define the 'type' attribute.")
[664]169     }
[467]170
[679]171     if (type == type_attr::unstructured)
[664]172     {
[679]173        if (ni_glo.isEmpty())
[664]174        {
[679]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.")
[664]179        }
[679]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        }
[664]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;
[611]194
[664]195        if (!area.isEmpty())
196          area.transposeSelf(1, 0);
197     }
[679]198
199     if (ni_glo.isEmpty())
[664]200     {
[679]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.")
[664]205     }
[679]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     }
[509]213
[679]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
[664]229     isDistributed_ = !ibegin.isEmpty() || !ni.isEmpty() || !jbegin.isEmpty() || !nj.isEmpty();
[509]230
[664]231     checkLocalIDomain();
232     checkLocalJDomain();
[509]233
[664]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     }
[594]240
[664]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();
[663]248
[664]249     if (0 == global_zoom_ni) global_zoom_ni = ni_glo;
250     if (0 == global_zoom_nj) global_zoom_nj = nj_glo;
[219]251   }
252
253   //----------------------------------------------------------------
254
255   void CDomain::checkLocalIDomain(void)
256   {
[657]257      if (ibegin.isEmpty() && ni.isEmpty())
[219]258      {
[594]259        ibegin = 0;
260        ni = ni_glo;
261      }
[657]262      else if (!i_index.isEmpty())
[219]263      {
[667]264        if (ibegin.isEmpty()) ibegin = i_index(0);
[219]265      }
266
[657]267      if (ni.getValue() < 0 || ibegin.getValue() < 0 ||
268         (ibegin.getValue() + ni.getValue()) > ni_glo.getValue())
[594]269      {
270        ERROR("CDomain::checkLocalIDomain(void)",
[679]271              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
[594]272              << "The local domain is wrongly defined,"
[679]273              << " check the attributes 'ni_glo' (" << ni_glo.getValue() << "), 'ni' (" << ni.getValue() << ") and 'ibegin' (" << ibegin.getValue() << ")");
[594]274      }
[219]275   }
276
277   void CDomain::checkLocalJDomain(void)
278   {
[657]279     if (jbegin.isEmpty() && nj.isEmpty())
280     {
281       jbegin = 0;
282       nj = nj_glo;
283     }
284     else if (!j_index.isEmpty())
285     {
[667]286       if (jbegin.isEmpty()) jbegin = j_index(0);
[657]287     }
[219]288
[657]289      if (nj.getValue() < 0 || jbegin.getValue() < 0 ||
290         (jbegin.getValue() + nj.getValue()) > nj_glo.getValue())
[594]291      {
292        ERROR("CDomain::checkLocalJDomain(void)",
[679]293              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
[594]294              << "The local domain is wrongly defined,"
[679]295              << " check the attributes 'nj_glo' (" << nj_glo.getValue() << "), 'nj' (" << nj.getValue() << ") and 'jbegin' (" << jbegin.getValue() << ")");
[594]296      }
[219]297   }
298
299   //----------------------------------------------------------------
[679]300
[219]301   void CDomain::checkMask(void)
302   {
[664]303      if (!mask_1d.isEmpty() && !mask_2d.isEmpty())
[657]304        ERROR("CDomain::checkMask(void)",
[679]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'.");
[657]308
[664]309      if (!mask_1d.isEmpty() && mask_2d.isEmpty())
[219]310      {
[664]311        if (mask_1d.numElements() != i_index.numElements())
[657]312          ERROR("CDomain::checkMask(void)",
[679]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() << ".");
[657]317      }
[509]318
[664]319      if (mask_1d.isEmpty() && !mask_2d.isEmpty())
[657]320      {
[679]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) << ".");
[657]327      }
[509]328
[664]329      if (!mask_2d.isEmpty())
[657]330      {
[664]331        mask_1d.resize(mask_2d.extent(0) * mask_2d.extent(1));
[657]332        for (int j = 0; j < nj; ++j)
[664]333          for (int i = 0; i < ni; ++i) mask_1d(i+j*ni) = mask_2d(i,j);
[675]334        mask_2d.free();
[657]335      }
[675]336      else if (mask_1d.isEmpty())
[657]337      {
[664]338        mask_1d.resize(i_index.numElements());
339        for (int i = 0; i < i_index.numElements(); ++i) mask_1d(i) = true;
[657]340      }
[219]341   }
342
[676]343   //----------------------------------------------------------------
[219]344
345   void CDomain::checkDomainData(void)
[509]346   {
[679]347      if (data_dim.isEmpty())
[219]348      {
[679]349        data_dim.setValue(1);
[219]350      }
[679]351      else if (!(data_dim.getValue() == 1 || data_dim.getValue() == 2))
[219]352      {
[679]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() << ".");
[219]356      }
357
358      if (data_ibegin.isEmpty())
[679]359         data_ibegin.setValue(0);
[660]360      if (data_jbegin.isEmpty())
[679]361         data_jbegin.setValue(0);
[219]362
[679]363      if (data_ni.isEmpty())
[219]364      {
[679]365        data_ni.setValue((data_dim == 1) ? (ni.getValue() * nj.getValue()) : ni.getValue());
[219]366      }
[679]367      else if (data_ni.getValue() < 0)
[219]368      {
[679]369        ERROR("CDomain::checkDomainData(void)",
370              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
371              << "The data size cannot be negative ('data_ni' = " << data_ni.getValue() << ").");
[219]372      }
373
[679]374      if (data_nj.isEmpty())
[219]375      {
[679]376        data_nj.setValue((data_dim.getValue() == 1) ? (ni.getValue() * nj.getValue()) : nj.getValue());
[219]377      }
[679]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      }
[219]384   }
385
386   //----------------------------------------------------------------
[679]387
[219]388   void CDomain::checkCompression(void)
389   {
390      if (!data_i_index.isEmpty())
391      {
[664]392        if (!data_j_index.isEmpty() &&
[678]393            data_j_index.numElements() != data_i_index.numElements())
[664]394        {
[679]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());
[664]400        }
401
[679]402        if (2 == data_dim)
403        {
[664]404          if (data_j_index.isEmpty())
[660]405          {
[679]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.");
[660]409          }
[679]410        }
411        else // (1 == data_dim)
412        {
[664]413          if (data_j_index.isEmpty())
414          {
[679]415            data_j_index.resize(data_ni);
416            for (int j = 0; j < data_ni; ++j) data_j_index(j) = 0;
[664]417          }
[679]418        }
[219]419      }
420      else
421      {
[679]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.");
[219]426
[679]427        if (1 == data_dim)
428        {
429          data_i_index.resize(data_ni);
430          data_j_index.resize(data_ni);
[666]431
[679]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);
[509]443
[679]444          for(int count = 0, j = 0; j < data_nj; ++j)
445          {
446            for(int i = 0; i < data_ni; ++i, ++count)
[219]447            {
[679]448              data_i_index(count) = i;
449              data_j_index(count) = j;
[219]450            }
[679]451          }
452        }
[219]453      }
454   }
455
[666]456   //----------------------------------------------------------------
[676]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
[666]466   void CDomain::completeLonLatClient(void)
[219]467   {
[664]468     int i,j,k ;
[679]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);
[509]473
[664]474     if (!lonvalue_2d.isEmpty())
475     {
476        for (j = 0; j < nj; ++j)
477          for (i = 0; i < ni; ++i)
[384]478          {
[679]479            lonvalue_temp(i + j * ni) = lonvalue_2d(i,j);
480            latvalue_temp(i + j * ni) = latvalue_2d(i,j);
[449]481            if (hasBounds)
482            {
[679]483              k = j * ni + i;
484              for (int n = 0; n < nvertex; ++n)
[666]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              }
[449]489            }
[384]490          }
[664]491     }
[509]492
[664]493     if (!lonvalue_1d.isEmpty())
494     {
495       if (type_attr::rectilinear == type)
496       {
[679]497         if (ni == lonvalue_1d.numElements() && nj == latvalue_1d.numElements())
[664]498         {
[679]499           for (j = 0; j < nj; ++j)
500             for (i = 0; i < ni; ++i)
[664]501             {
[679]502               k = j * ni + i;
[664]503               lonvalue_temp(k) = lonvalue_1d(i);
[666]504               latvalue_temp(k) = latvalue_1d(j);
[664]505               if (hasBounds)
506               {
[679]507                 for (int n = 0; n < nvertex; ++n)
[666]508                 {
509                   bounds_lon_temp(n,k) = bounds_lon_1d(n,i);
510                   bounds_lat_temp(n,k) = bounds_lat_1d(n,j);
511                 }
[664]512               }
513             }
514          }
515          else
516            ERROR("CDomain::completeLonClient(void)",
[679]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() << '.');
[664]521       }
[679]522       else if (type == type_attr::curvilinear || type == type_attr::unstructured)
[664]523       {
[679]524         lonvalue_temp = lonvalue_1d;
525         latvalue_temp = latvalue_1d;
[664]526         if (hasBounds)
527         {
[679]528           bounds_lon_temp = bounds_lon_1d;
529           bounds_lat_temp = bounds_lat_1d;
[664]530         }
531       }
532     }
[266]533
[666]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;
[664]537
[666]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);
[509]544
[666]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    }
[584]550
[666]551      // Make sure that this attribute is non-empty for every client.
552     if (0 != globalIndexCountZoom)
[664]553     {
[666]554       lonvalue_client.resize(globalIndexCountZoom);
555       latvalue_client.resize(globalIndexCountZoom);
556       if (hasBounds)
[664]557       {
[666]558         bounds_lon_client.resize(nvertex,globalIndexCountZoom);
559         bounds_lat_client.resize(nvertex,globalIndexCountZoom);
[664]560       }
561     }
562
[666]563     int nCountZoom = 0;
564     for (i = 0; i < nbIndex; ++i)
[664]565     {
[666]566       i_ind=i_index(i);
567       j_ind=j_index(i);
[664]568
[666]569       if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
[664]570       {
[666]571         lonvalue_client(nCountZoom) = lonvalue_temp(i);
572         latvalue_client(nCountZoom) = latvalue_temp(i);
[664]573         if (hasBounds)
574         {
[666]575           for (int n = 0; n < nvertex; ++n)
[664]576           {
[666]577             bounds_lon_client(n,nCountZoom) = bounds_lon_temp(n,i);
578             bounds_lat_client(n,nCountZoom) = bounds_lat_temp(n,i);
[664]579           }
580         }
[666]581         ++nCountZoom;
[664]582       }
583     }
584   }
585
[449]586   void CDomain::checkBounds(void)
587   {
[679]588     if (!nvertex.isEmpty() && nvertex > 0)
[449]589     {
[664]590       if (!bounds_lon_1d.isEmpty() && !bounds_lon_2d.isEmpty())
591         ERROR("CDomain::checkBounds(void)",
[679]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'.");
[664]595
596       if (!bounds_lat_1d.isEmpty() && !bounds_lat_2d.isEmpty())
597         ERROR("CDomain::checkBounds(void)",
[679]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'.");
[664]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)",
[679]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.");
[664]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)",
[679]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.");
[664]616       }
617
[679]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() << ".");
[664]624
[679]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() << ".");
[664]631
632       if (!bounds_lon_1d.isEmpty() && lonvalue_1d.isEmpty())
[679]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);
[664]636
637       if (!bounds_lon_2d.isEmpty() && lonvalue_2d.isEmpty())
[679]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);
[664]641
[679]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() << ".");
[664]648
[679]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() << ".");
[664]655
656       if (!bounds_lat_1d.isEmpty() && latvalue_1d.isEmpty())
[679]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);
[664]660
661       if (!bounds_lat_2d.isEmpty() && latvalue_2d.isEmpty())
[679]662         ERROR("CDomain::checkBounds(void)",
663               << "Since 'bounds_lat_2d' is defined, 'latvalue_2d' must be defined too." << std::endl);
664
665       hasBounds = true;
[449]666     }
[509]667     else
[449]668     {
[679]669       hasBounds = false;
670       nvertex = 0;
[449]671     }
672   }
[509]673
[611]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       {
[679]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) << ".");
[611]686       }
687     }
688   }
689
[665]690   void CDomain::checkLonLat()
691   {
692     hasLonLat = (!latvalue_1d.isEmpty() && !lonvalue_1d.isEmpty()) ||
693                 (!latvalue_2d.isEmpty() && !lonvalue_2d.isEmpty());
[666]694     if (hasLonLat)
695     {
696       if (!lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
697         ERROR("CDomain::completeLonLatClient(void)",
[679]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'.");
[666]701
702       if (!lonvalue_1d.isEmpty() && lonvalue_2d.isEmpty())
703       {
704         if (lonvalue_1d.numElements() != i_index.numElements())
705           ERROR("CDomain::completeLonLatClient(void)",
[679]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() << ".");
[666]710       }
711
712       if (lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
713       {
[679]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) << ".");
[666]720       }
721
722       if (!latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
723         ERROR("CDomain::completeLonLatClient(void)",
[679]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'.");
[666]727
728       if (!latvalue_1d.isEmpty() && latvalue_2d.isEmpty())
729       {
730         if (latvalue_1d.numElements() != i_index.numElements())
731           ERROR("CDomain::completeLonLatClient(void)",
[679]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() << ".");
[666]736       }
737
738       if (latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
739       {
[679]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) << ".");
[666]746       }
747     }
[665]748   }
749
[657]750   void CDomain::checkAttributesOnClientAfterTransformation()
751   {
752     CContext* context=CContext::getCurrent() ;
753
754     if (this->isClientAfterTransformationChecked) return;
755     if (context->hasClient)
756     {
757       this->checkMask();
[665]758       if (hasLonLat || hasArea) this->computeConnectedServer();
759       if (hasLonLat) this->completeLonLatClient();
[657]760     }
761
762     this->isClientAfterTransformationChecked = true;
763   }
764
[219]765   //----------------------------------------------------------------
[667]766   // Divide function checkAttributes into 2 seperate ones
[509]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();
[219]772
[509]773      this->checkDomain();
774      this->checkBounds();
[611]775      this->checkArea();
[665]776      this->checkLonLat();
[509]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();
[657]795     if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation();
[509]796     CContext* context=CContext::getCurrent() ;
797
798     if (this->isChecked) return;
799     if (context->hasClient)
800     {
[665]801       sendServerAttribut();
802       if (hasLonLat || hasArea) sendLonLatArea();
[509]803     }
804     this->isChecked = true;
805   }
806
[219]807   void CDomain::checkAttributes(void)
808   {
809      if (this->isChecked) return;
[347]810      CContext* context=CContext::getCurrent() ;
[219]811
[467]812      this->checkDomain();
[665]813      this->checkLonLat();
[449]814      this->checkBounds();
[611]815      this->checkArea();
[509]816
[300]817      if (context->hasClient)
[219]818      { // CÃŽté client uniquement
819         this->checkMask();
820         this->checkDomainData();
821         this->checkCompression();
[666]822
[219]823      }
824      else
825      { // CÃŽté serveur uniquement
826      }
[509]827
[300]828      if (context->hasClient)
829      {
[666]830        this->computeConnectedServer();
831        this->completeLonLatClient();
832        this->sendServerAttribut();
833        this->sendLonLatArea();
[300]834      }
[509]835
[219]836      this->isChecked = true;
837   }
[509]838
[300]839  void CDomain::sendServerAttribut(void)
840  {
[657]841    CServerDistributionDescription serverDescription(nGlobDomain_);
[553]842
[595]843    CContext* context = CContext::getCurrent();
844    CContextClient* client = context->client;
845    int nbServer = client->serverSize;
[509]846
[657]847    if (isUnstructed_) serverDescription.computeServerDistribution(nbServer,0);
848    else serverDescription.computeServerDistribution(nbServer,1);
849
[595]850    std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
851    std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
[509]852
[595]853    CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT);
854    if (client->isServerLeader())
855    {
856      std::list<CMessage> msgs;
[509]857
[595]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;
[509]868
[595]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;
[631]873        msg << global_zoom_ni << global_zoom_ibegin << global_zoom_nj << global_zoom_jbegin;
[676]874        msg << isCompressible_;
[595]875
876        event.push(*itRank,1,msg);
877      }
878      client->sendEvent(event);
879    }
880    else client->sendEvent(event);
[300]881  }
[467]882
[657]883  void CDomain::computeNGlobDomain()
884  {
885    nGlobDomain_.resize(2);
886    nGlobDomain_[0] = ni_glo.getValue();
887    nGlobDomain_[1] = nj_glo.getValue();
888  }
889
[300]890  void CDomain::computeConnectedServer(void)
891  {
[553]892    CContext* context=CContext::getCurrent() ;
[300]893    CContextClient* client=context->client ;
[553]894    int nbServer=client->serverSize;
895    bool doComputeGlobalIndexServer = true;
[449]896
[657]897    int i,j,i_ind,j_ind, nbIndex;
[666]898    int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1 ;
899    int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1 ;
[509]900
[553]901    // Precompute number of index
[584]902    int globalIndexCountZoom = 0;
[657]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
[666]909      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
[467]910      {
[657]911        ++globalIndexCountZoom;
[467]912      }
[657]913    }
[467]914
[676]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
[553]933    // Fill in index
[584]934    CArray<size_t,1> globalIndexDomainZoom(globalIndexCountZoom);
[657]935    CArray<size_t,1> localIndexDomainZoom(globalIndexCountZoom);
936    CArray<size_t,1> globalIndexDomain(nbIndex);
[553]937    size_t globalIndex;
[584]938    int globalIndexCount = 0;
939    globalIndexCountZoom = 0;
[467]940
[657]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;
[666]948      if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
[467]949      {
[657]950        globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
951        localIndexDomainZoom(globalIndexCountZoom) = i;
952        ++globalIndexCountZoom;
[300]953      }
[657]954    }
[509]955
[676]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    }
[569]977
[676]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
[657]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
[569]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();
[584]999
1000    std::map<int, std::vector<size_t> >::const_iterator it = globalIndexDomainOnServer.begin(),
1001                                                       ite = globalIndexDomainOnServer.end();
[668]1002    typedef XIOSBinarySearchWithIndex<size_t> BinarySearch;
1003    std::vector<int>::iterator itVec;
1004
[584]1005    indSrv_.clear();
[676]1006    indWrittenSrv_.clear();
[584]1007    for (; it != ite; ++it)
1008    {
1009      int rank = it->first;
[668]1010      int indexSize = it->second.size();
1011      std::vector<int> permutIndex(indexSize);
1012      XIOSAlgorithms::fillInIndex(indexSize, permutIndex);
[671]1013      XIOSAlgorithms::sortWithIndex<size_t, CVectorStorage>(it->second, permutIndex);
[668]1014      BinarySearch binSearch(it->second);
[584]1015      int nb = globalIndexDomainZoom.numElements();
1016      for (int i = 0; i < nb; ++i)
1017      {
[668]1018        if (binSearch.search(permutIndex.begin(), permutIndex.end(), globalIndexDomainZoom(i), itVec))
[584]1019        {
[657]1020          indSrv_[rank].push_back(localIndexDomainZoom(i));
[584]1021        }
1022      }
[676]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      }
[553]1030    }
[569]1031
[584]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
[569]1045    delete clientServerMap;
[300]1046  }
[467]1047
[657]1048  const std::map<int, vector<size_t> >& CDomain::getIndexServer() const
1049  {
1050    return indSrv_;
1051  }
1052
[667]1053  /*!
1054    Send index from client to server(s)
1055  */
[665]1056  void CDomain::sendIndex()
[300]1057  {
[610]1058    int ns, n, i, j, ind, nv, idx;
1059    CContext* context = CContext::getCurrent();
1060    CContextClient* client=context->client;
1061
[665]1062    CEventClient eventIndex(getType(), EVENT_ID_INDEX);
1063
1064    list<CMessage> list_msgsIndex;
[676]1065    list<CArray<int,1> > list_indi, list_indj, list_writtenInd;
[665]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
[676]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
[665]1108      eventIndex.push(rank, nbConnectedClients_[rank], list_msgsIndex.back());
1109    }
1110
1111    client->sendEvent(eventIndex);
1112  }
1113
[667]1114  /*!
1115    Send area from client to server(s)
1116  */
[665]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
[667]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  */
[665]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
[300]1172    // send lon lat for each connected server
[610]1173    CEventClient eventLon(getType(), EVENT_ID_LON);
1174    CEventClient eventLat(getType(), EVENT_ID_LAT);
[509]1175
[665]1176    list<CMessage> list_msgsLon, list_msgsLat;
[610]1177    list<CArray<double,1> > list_lon, list_lat;
1178    list<CArray<double,2> > list_boundslon, list_boundslat;
[518]1179
[610]1180    std::map<int, std::vector<size_t> >::const_iterator it, iteMap;
[553]1181    iteMap = indSrv_.end();
[584]1182    for (int k = 0; k < connectedServerRank_.size(); ++k)
[300]1183    {
[584]1184      int nbData = 0;
1185      int rank = connectedServerRank_[k];
1186      it = indSrv_.find(rank);
1187      if (iteMap != it)
[610]1188        nbData = it->second.size();
[584]1189
[610]1190      list_lon.push_back(CArray<double,1>(nbData));
1191      list_lat.push_back(CArray<double,1>(nbData));
[509]1192
[610]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();
[657]1201      const std::vector<size_t>& temp = it->second;
[553]1202      for (n = 0; n < nbData; ++n)
[467]1203      {
[610]1204        idx = static_cast<int>(it->second[n]);
[666]1205        lon(n) = lonvalue_client(idx);
1206        lat(n) = latvalue_client(idx);
[509]1207
[467]1208        if (hasBounds)
[300]1209        {
[610]1210          CArray<double,2>& boundslon = list_boundslon.back();
1211          CArray<double,2>& boundslat = list_boundslat.back();
1212
[666]1213          for (nv = 0; nv < nvertex; ++nv)
[449]1214          {
[666]1215            boundslon(nv, n) = bounds_lon_client(nv, idx);
1216            boundslat(nv, n) = bounds_lat_client(nv, idx);
[449]1217          }
[300]1218        }
[467]1219      }
[509]1220
[610]1221      list_msgsLon.push_back(CMessage());
1222      list_msgsLat.push_back(CMessage());
[518]1223
[610]1224      list_msgsLon.back() << this->getId() << list_lon.back();
1225      list_msgsLat.back() << this->getId() << list_lat.back();
1226
[518]1227      if (hasBounds)
1228      {
[610]1229        list_msgsLon.back() << list_boundslon.back();
1230        list_msgsLat.back() << list_boundslat.back();
[518]1231      }
[584]1232
[610]1233      eventLon.push(rank, nbConnectedClients_[rank], list_msgsLon.back());
1234      eventLat.push(rank, nbConnectedClients_[rank], list_msgsLat.back());
[300]1235    }
1236
[610]1237    client->sendEvent(eventLon);
1238    client->sendEvent(eventLat);
[300]1239  }
[509]1240
[667]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  */
[665]1245  void CDomain::sendLonLatArea(void)
1246  {
1247    sendIndex();
1248    sendLonLat();
1249    sendArea();
1250  }
1251
[300]1252  bool CDomain::dispatchEvent(CEventServer& event)
[610]1253  {
1254    if (SuperClass::dispatchEvent(event)) return true;
1255    else
1256    {
1257      switch(event.type)
[300]1258      {
[610]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;
[611]1275        case EVENT_ID_AREA:
1276          recvArea(event);
1277          return true;
1278          break;
[610]1279        default:
1280          ERROR("bool CContext::dispatchEvent(CEventServer& event)",
1281                << "Unknown Event");
1282          return false;
1283       }
1284    }
1285  }
[509]1286
[667]1287  /*!
1288    Receive attributes event from clients(s)
1289    \param[in] event event contain info about rank and associated attributes
1290  */
[300]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  }
[509]1298
[667]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  */
[300]1304  void CDomain::recvServerAttribut(CBufferIn& buffer)
1305  {
[631]1306    buffer >> ni_srv >> ibegin_srv >> iend_srv >> nj_srv >> jbegin_srv >> jend_srv
[676]1307           >> global_zoom_ni >> global_zoom_ibegin >> global_zoom_nj >> global_zoom_jbegin
1308           >> isCompressible_;
[300]1309
[631]1310    int zoom_iend = global_zoom_ibegin + global_zoom_ni - 1;
1311    int zoom_jend = global_zoom_jbegin + global_zoom_nj - 1;
[509]1312
[631]1313    zoom_ibegin_srv = global_zoom_ibegin > ibegin_srv ? global_zoom_ibegin : ibegin_srv ;
[300]1314    zoom_iend_srv = zoom_iend < iend_srv ? zoom_iend : iend_srv ;
1315    zoom_ni_srv=zoom_iend_srv-zoom_ibegin_srv+1 ;
[509]1316
[631]1317    zoom_jbegin_srv = global_zoom_jbegin > jbegin_srv ? global_zoom_jbegin : jbegin_srv ;
[300]1318    zoom_jend_srv = zoom_jend < jend_srv ? zoom_jend : jend_srv ;
1319    zoom_nj_srv=zoom_jend_srv-zoom_jbegin_srv+1 ;
1320
[509]1321    if (zoom_ni_srv<=0 || zoom_nj_srv<=0)
[300]1322    {
[551]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 ;
[300]1325    }
[369]1326    lonvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
[456]1327    lonvalue_srv = 0. ;
[369]1328    latvalue_srv.resize(zoom_ni_srv*zoom_nj_srv) ;
[456]1329    latvalue_srv = 0. ;
[509]1330    if (hasBounds)
[456]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    }
[611]1337
1338    if (hasArea)
1339      area_srv.resize(zoom_ni_srv * zoom_nj_srv);
[300]1340  }
[509]1341
[667]1342  /*!
1343    Receive index event from clients(s)
1344    \param[in] event event contain info about rank and associated index
1345  */
[610]1346  void CDomain::recvIndex(CEventServer& event)
1347  {
[676]1348    CDomain* domain;
1349
[610]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;
[676]1356      domain = get(domainId);
1357      domain->recvIndex(it->rank, *buffer);
[610]1358    }
[676]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    }
[610]1370  }
1371
[667]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  */
[610]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
[676]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    }
[610]1391  }
1392
[667]1393  /*!
1394    Receive longitude event from clients(s)
1395    \param[in] event event contain info about rank and associated longitude
1396  */
[518]1397  void CDomain::recvLon(CEventServer& event)
[300]1398  {
[610]1399    list<CEventServer::SSubEvent>::iterator it;
1400    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
[300]1401    {
[610]1402      CBufferIn* buffer = it->buffer;
1403      string domainId;
1404      *buffer >> domainId;
1405      get(domainId)->recvLon(it->rank, *buffer);
[300]1406    }
1407  }
[509]1408
[667]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  */
[610]1414  void CDomain::recvLon(int rank, CBufferIn& buffer)
[300]1415  {
[610]1416    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1417    CArray<double,1> lon;
1418    CArray<double,2> boundslon;
[518]1419
[610]1420    buffer >> lon;
1421    if (hasBounds) buffer >> boundslon;
[518]1422
[610]1423    int i, j, ind_srv;
1424    for (int ind = 0; ind < indi.numElements(); ind++)
[518]1425    {
[610]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);
[518]1429      if (hasBounds)
1430      {
[666]1431        for (int nv = 0; nv < nvertex; ++nv)
[610]1432          bounds_lon_srv(nv, ind_srv) = boundslon(nv, ind);
[518]1433      }
1434    }
1435  }
1436
[667]1437  /*!
1438    Receive latitude event from clients(s)
1439    \param[in] event event contain info about rank and associated latitude
1440  */
[518]1441  void CDomain::recvLat(CEventServer& event)
1442  {
[610]1443    list<CEventServer::SSubEvent>::iterator it;
1444    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
[518]1445    {
[610]1446      CBufferIn* buffer = it->buffer;
1447      string domainId;
1448      *buffer >> domainId;
1449      get(domainId)->recvLat(it->rank, *buffer);
[518]1450    }
1451  }
1452
[667]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  */
[610]1458  void CDomain::recvLat(int rank, CBufferIn& buffer)
[518]1459  {
[610]1460    CArray<int,1> &indi = indiSrv[rank], &indj = indjSrv[rank];
1461    CArray<double,1> lat;
1462    CArray<double,2> boundslat;
[509]1463
[610]1464    buffer >> lat;
1465    if (hasBounds) buffer >> boundslat;
1466
1467    int i, j, ind_srv;
1468    for (int ind = 0; ind < indi.numElements(); ind++)
[300]1469    {
[610]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);
[509]1473      if (hasBounds)
[449]1474      {
[610]1475        for (int nv = 0; nv < nvertex; nv++)
1476          bounds_lat_srv(nv, ind_srv) = boundslat(nv, ind);
[449]1477      }
[300]1478    }
1479  }
[553]1480
[667]1481  /*!
1482    Receive area event from clients(s)
1483    \param[in] event event contain info about rank and associated area
1484  */
[611]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
[667]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  */
[611]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
[667]1518  /*!
1519    Check whether a domain has transformation
1520    \return true if domain has transformation
1521  */
[631]1522  bool CDomain::hasTransformation()
1523  {
1524    return (!transformationMap_.empty());
1525  }
1526
[667]1527  /*!
1528    Set transformation for current domain. It's the method to move transformation in hierarchy
1529    \param [in] domTrans transformation on domain
1530  */
[631]1531  void CDomain::setTransformations(const TransMapTypes& domTrans)
1532  {
1533    transformationMap_ = domTrans;
1534  }
1535
[667]1536  /*!
1537    Get all transformation current domain has
1538    \return all transformation
1539  */
[631]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
[667]1559  /*!
1560    A current domain will go up the hierarchy to find out the domain from which it has transformation
1561  */
[631]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
[667]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  */
[631]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");
[657]1595      StdString interpFromFileDomainDefRoot("interpolate_from_file_domain_definition");
1596      StdString interpFromFile("interpolate_from_file_domain");
[631]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        }
[657]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        }
[631]1610      } while (node.goToNextElement()) ;
1611      node.goToParentElement();
1612    }
1613  }
[219]1614   //----------------------------------------------------------------
[509]1615
[540]1616   DEFINE_REF_FUNC(Domain,domain)
[509]1617
[219]1618   ///---------------------------------------------------------------
1619
[335]1620} // namespace xios
Note: See TracBrowser for help on using the repository browser.