source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp @ 1975

Last change on this file since 1975 was 1974, checked in by ymipsl, 4 years ago

Big cleaning on XIOS coupling branch
YM

  • 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: 83.0 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 "local_connector.hpp"
21#include "grid_local_connector.hpp"
22#include "remote_connector.hpp"
23#include "gatherer_connector.hpp"
24#include "scatterer_connector.hpp"
25#include "grid_scatterer_connector.hpp"
26#include "grid_gatherer_connector.hpp"
27
28
29
30
31#include <algorithm>
32
33namespace xios {
34
35   /// ////////////////////// Définitions ////////////////////// ///
36
37   CDomain::CDomain(void)
38      : CObjectTemplate<CDomain>(), CDomainAttributes()
39      , isChecked(false), relFiles(),  indSrv_(), connectedServerRank_()
40      , hasBounds(false), hasArea(false), isCompressible_(false), isUnstructed_(false)
41      , hasLonLat(false)
42      , isRedistributed_(false), hasPole(false)
43      , lonvalue(), latvalue(), bounds_lonvalue(), bounds_latvalue()
44      , clients(), hasLatInReadFile_(false), hasBoundsLatInReadFile_(false)
45      , hasLonInReadFile_(false), hasBoundsLonInReadFile_(false)
46   {
47   }
48
49   CDomain::CDomain(const StdString & id)
50      : CObjectTemplate<CDomain>(id), CDomainAttributes()
51      , isChecked(false), relFiles(), indSrv_(), connectedServerRank_() 
52      , hasBounds(false), hasArea(false), isCompressible_(false), isUnstructed_(false)
53      , hasLonLat(false)
54      , isRedistributed_(false), hasPole(false)
55      , lonvalue(), latvalue(), bounds_lonvalue(), bounds_latvalue()
56      , clients(), hasLatInReadFile_(false), hasBoundsLatInReadFile_(false)
57      , hasLonInReadFile_(false), hasBoundsLonInReadFile_(false)
58   {
59    }
60
61   CDomain::~CDomain(void)
62   {
63   }
64
65   ///---------------------------------------------------------------
66
67   void CDomain::assignMesh(const StdString meshName, const int nvertex)
68   TRY
69   {
70     mesh = CMesh::getMesh(meshName, nvertex);
71   }
72   CATCH_DUMP_ATTR
73
74   CDomain* CDomain::createDomain()
75   TRY
76   {
77     CDomain* domain = CDomainGroup::get("domain_definition")->createChild();
78     return domain;
79   }
80   CATCH
81
82   std::map<StdString, ETranformationType> CDomain::transformationMapList_ = std::map<StdString, ETranformationType>();
83   bool CDomain::_dummyTransformationMapList = CDomain::initializeTransformationMap(CDomain::transformationMapList_);
84
85   bool CDomain::initializeTransformationMap(std::map<StdString, ETranformationType>& m)
86   TRY
87   {
88     m["zoom_domain"] = TRANS_ZOOM_DOMAIN;
89     m["interpolate_domain"] = TRANS_INTERPOLATE_DOMAIN;
90     m["generate_rectilinear_domain"] = TRANS_GENERATE_RECTILINEAR_DOMAIN;
91     m["compute_connectivity_domain"] = TRANS_COMPUTE_CONNECTIVITY_DOMAIN;
92     m["expand_domain"] = TRANS_EXPAND_DOMAIN;
93     m["reorder_domain"] = TRANS_REORDER_DOMAIN;
94     m["extract_domain"] = TRANS_EXTRACT_DOMAIN;
95   }
96   CATCH
97
98   const std::set<StdString> & CDomain::getRelFiles(void) const
99   TRY
100   {
101      return (this->relFiles);
102   }
103   CATCH
104
105     //----------------------------------------------------------------
106
107   /*!
108    * Compute the minimum buffer size required to send the attributes to the server(s).
109    *
110    * \return A map associating the server rank with its minimum buffer size.
111    */
112   std::map<int, StdSize> CDomain::getAttributesBufferSize(CContextClient* client, bool bufferForWriting /*= false*/)
113   TRY
114   {
115
116     std::map<int, StdSize> attributesSizes = getMinimumBufferSizeForAttributes(client);
117
118     if (client->isServerLeader())
119     {
120       // size estimation for sendDistributionAttribut
121       size_t size = 11 * sizeof(size_t);
122
123       const std::list<int>& ranks = client->getRanksServerLeader();
124       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
125       {
126         if (size > attributesSizes[*itRank])
127           attributesSizes[*itRank] = size;
128       }
129     }
130
131     std::unordered_map<int, vector<size_t> >::const_iterator itIndexEnd = indSrv_[client->serverSize].end();
132     // std::map<int, std::vector<int> >::const_iterator itWrittenIndexEnd = indWrittenSrv_.end();
133     for (size_t k = 0; k < connectedServerRank_[client->serverSize].size(); ++k)
134     {
135       int rank = connectedServerRank_[client->serverSize][k];
136       std::unordered_map<int, std::vector<size_t> >::const_iterator it = indSrv_[client->serverSize].find(rank);
137       size_t idxCount = (it != itIndexEnd) ? it->second.size() : 0;
138
139       // size estimation for sendIndex (and sendArea which is always smaller or equal)
140       size_t sizeIndexEvent = 2 * sizeof(size_t) + 2 * CArray<int,1>::size(idxCount);
141
142       // size estimation for sendLonLat
143       size_t sizeLonLatEvent = CArray<double,1>::size(idxCount);
144       if (hasBounds)
145         sizeLonLatEvent += CArray<double,2>::size(nvertex * idxCount);
146
147       size_t size = CEventClient::headerSize + getId().size() + sizeof(size_t) + std::max(sizeIndexEvent, sizeLonLatEvent);
148       if (size > attributesSizes[rank])
149         attributesSizes[rank] = size;
150     }
151
152     return attributesSizes;
153   }
154   CATCH_DUMP_ATTR
155
156   //----------------------------------------------------------------
157
158   bool CDomain::isEmpty(void) const
159   TRY
160   {
161     return ((this->i_index.isEmpty()) || (0 == this->i_index.numElements()));
162   }
163   CATCH
164
165   //----------------------------------------------------------------
166
167   bool CDomain::IsWritten(const StdString & filename) const
168   TRY
169   {
170      return (this->relFiles.find(filename) != this->relFiles.end());
171   }
172   CATCH
173
174   bool CDomain::isWrittenCompressed(const StdString& filename) const
175   TRY
176   {
177      return (this->relFilesCompressed.find(filename) != this->relFilesCompressed.end());
178   }
179   CATCH
180
181   //----------------------------------------------------------------
182
183   bool CDomain::isDistributed(void) const
184   TRY
185   {
186      bool distributed =  !((!ni.isEmpty() && (ni == ni_glo) && !nj.isEmpty() && (nj == nj_glo)) ||
187              (!i_index.isEmpty() && i_index.numElements() == ni_glo*nj_glo));
188      bool distributed_glo ;
189      distributed |= (1 == CContext::getCurrent()->intraCommSize_);
190
191      return distributed;
192   }
193   CATCH
194
195   //----------------------------------------------------------------
196
197   /*!
198    * Compute if the domain can be ouput in a compressed way.
199    * In this case the workflow view on server side must be the same
200    * than the full view for all context rank. The result is stored on
201    * internal isCompressible_ attribute.
202    */
203   void CDomain::computeIsCompressible(void)
204   TRY
205   {
206     // mesh is compressible contains some masked or indexed value, ie if full view is different of workflow view.
207     // But now assume that the size of the 2 view must be equal for everybody. True on server side
208     int isSameView = getLocalView(CElementView::FULL)->getSize() ==  getLocalView(CElementView::WORKFLOW)->getSize();
209     MPI_Allreduce(MPI_IN_PLACE, &isSameView, 1, MPI_INT, MPI_LAND, CContext::getCurrent()->getIntraComm()) ;
210     if (isSameView) isCompressible_ = false ;
211     else isCompressible_ = true ;
212     isCompressibleComputed_=true ;
213   }
214   CATCH
215
216   void CDomain::addRelFile(const StdString & filename)
217   TRY
218   {
219      this->relFiles.insert(filename);
220   }
221   CATCH_DUMP_ATTR
222
223   void CDomain::addRelFileCompressed(const StdString& filename)
224   TRY
225   {
226      this->relFilesCompressed.insert(filename);
227   }
228   CATCH_DUMP_ATTR
229
230   StdString CDomain::GetName(void)   { return (StdString("domain")); }
231   StdString CDomain::GetDefName(void){ return (CDomain::GetName()); }
232   ENodeType CDomain::GetType(void)   { return (eDomain); }
233
234   //----------------------------------------------------------------
235
236   /*!
237      Verify if all distribution information of a domain are available
238      This checking verifies the definition of distribution attributes (ni, nj, ibegin, jbegin)
239   */
240   bool CDomain::distributionAttributesHaveValue() const
241   TRY
242   {
243      bool hasValues = true;
244
245      if (ni.isEmpty() && ibegin.isEmpty() && i_index.isEmpty())
246      {
247        hasValues = false;
248        return hasValues;
249      }
250
251      return hasValues;
252   }
253   CATCH
254
255   /*!
256     Redistribute RECTILINEAR or CURVILINEAR domain with a number of local domains.
257   All attributes ni,nj,ibegin,jbegin (if defined) will be rewritten
258   The optional attributes lonvalue, latvalue will be added. Because this function only serves (for now)
259   for interpolation from unstructured domain to rectilinear one, range of latvalue is 0-360 and lonvalue is -90 - +90
260    \param [in] nbLocalDomain number of local domain on the domain destination
261   */
262   void CDomain::redistribute(int nbLocalDomain)
263   TRY
264   {
265     if (this->isRedistributed_) return;
266
267     this->isRedistributed_ = true;
268     CContext* context = CContext::getCurrent();
269     // For now the assumption is that secondary server pools consist of the same number of procs.
270     // CHANGE the line below if the assumption changes.
271
272     int rankClient = context->intraCommRank_;
273     int rankOnDomain = rankClient%nbLocalDomain;
274
275     if (ni_glo.isEmpty() || ni_glo <= 0 )
276     {
277        ERROR("CDomain::redistribute(int nbLocalDomain)",
278           << "[ Id = " << this->getId() << " ] "
279           << "The global domain is badly defined,"
280           << " check the \'ni_glo\'  value !")
281     }
282
283     if (nj_glo.isEmpty() || nj_glo <= 0 )
284     {
285        ERROR("CDomain::redistribute(int nbLocalDomain)",
286           << "[ Id = " << this->getId() << " ] "
287           << "The global domain is badly defined,"
288           << " check the \'nj_glo\'  value !")
289     }
290
291     if ((type_attr::rectilinear == type)  || (type_attr::curvilinear == type))
292     {
293        int globalDomainSize = ni_glo * nj_glo;
294        if (globalDomainSize <= nbLocalDomain)
295        {
296          for (int idx = 0; idx < nbLocalDomain; ++idx)
297          {
298            if (rankOnDomain < globalDomainSize)
299            {
300              int iIdx = rankOnDomain % ni_glo;
301              int jIdx = rankOnDomain / ni_glo;
302              ibegin.setValue(iIdx); jbegin.setValue(jIdx);
303              ni.setValue(1); nj.setValue(1);
304            }
305            else
306            {
307              ibegin.setValue(0); jbegin.setValue(0);
308              ni.setValue(0); nj.setValue(0);
309            }
310          }
311        }
312        else
313        {
314          float njGlo = nj_glo.getValue();
315          float niGlo = ni_glo.getValue();
316          int nbProcOnX, nbProcOnY, range;
317
318          // Compute (approximately) number of segment on x and y axis
319          float yOverXRatio = njGlo/niGlo;
320
321          nbProcOnX = std::ceil(std::sqrt(nbLocalDomain/yOverXRatio));
322          nbProcOnY = std::ceil(((float)nbLocalDomain)/nbProcOnX);
323
324          // Simple distribution: Sweep from top to bottom, left to right
325          // Calculate local begin on x
326          std::vector<int> ibeginVec(nbProcOnX,0), jbeginVec(nbProcOnY,0);
327          std::vector<int> niVec(nbProcOnX), njVec(nbProcOnY);
328          for (int i = 1; i < nbProcOnX; ++i)
329          {
330            range = ni_glo / nbProcOnX;
331            if (i < (ni_glo%nbProcOnX)) ++range;
332            niVec[i-1] = range;
333            ibeginVec[i] = ibeginVec[i-1] + niVec[i-1];
334          }
335          niVec[nbProcOnX-1] = ni_glo - ibeginVec[nbProcOnX-1];
336
337          // Calculate local begin on y
338          for (int j = 1; j < nbProcOnY; ++j)
339          {
340            range = nj_glo / nbProcOnY;
341            if (j < (nj_glo%nbProcOnY)) ++range;
342            njVec[j-1] = range;
343            jbeginVec[j] = jbeginVec[j-1] + njVec[j-1];
344          }
345          njVec[nbProcOnY-1] = nj_glo - jbeginVec[nbProcOnY-1];
346
347          // Now assign value to ni, ibegin, nj, jbegin
348          int iIdx = rankOnDomain % nbProcOnX;
349          int jIdx = rankOnDomain / nbProcOnX;
350
351          if (rankOnDomain != (nbLocalDomain-1))
352          {
353            ibegin.setValue(ibeginVec[iIdx]);
354            jbegin.setValue(jbeginVec[jIdx]);
355            nj.setValue(njVec[jIdx]);
356            ni.setValue(niVec[iIdx]);
357          }
358          else // just merge all the remaining rectangle into the last one
359          {
360            ibegin.setValue(ibeginVec[iIdx]);
361            jbegin.setValue(jbeginVec[jIdx]);
362            nj.setValue(njVec[jIdx]);
363            ni.setValue(ni_glo - ibeginVec[iIdx]);
364          }
365        } 
366     }
367     else  // unstructured domain
368     {
369       if (this->i_index.isEmpty())
370       {
371          int globalDomainSize = ni_glo * nj_glo;
372          if (globalDomainSize <= nbLocalDomain)
373          {
374            for (int idx = 0; idx < nbLocalDomain; ++idx)
375            {
376              if (rankOnDomain < globalDomainSize)
377              {
378                int iIdx = rankOnDomain % ni_glo;
379                int jIdx = rankOnDomain / ni_glo;
380                ibegin.setValue(iIdx); jbegin.setValue(jIdx);
381                ni.setValue(1); nj.setValue(1);
382              }
383              else
384              {
385                ibegin.setValue(0); jbegin.setValue(0);
386                ni.setValue(0); nj.setValue(0);
387              }
388            }
389          }
390          else
391          {
392            float njGlo = nj_glo.getValue();
393            float niGlo = ni_glo.getValue();
394            std::vector<int> ibeginVec(nbLocalDomain,0);
395            std::vector<int> niVec(nbLocalDomain);
396            for (int i = 1; i < nbLocalDomain; ++i)
397            {
398              int range = ni_glo / nbLocalDomain;
399              if (i < (ni_glo%nbLocalDomain)) ++range;
400              niVec[i-1] = range;
401              ibeginVec[i] = ibeginVec[i-1] + niVec[i-1];
402            }
403            niVec[nbLocalDomain-1] = ni_glo - ibeginVec[nbLocalDomain-1];
404
405            int iIdx = rankOnDomain % nbLocalDomain;
406            ibegin.setValue(ibeginVec[iIdx]);
407            jbegin.setValue(0);
408            ni.setValue(niVec[iIdx]);
409            nj.setValue(1);
410          }
411
412          i_index.resize(ni);         
413          for(int idx = 0; idx < ni; ++idx) i_index(idx)=ibegin+idx;
414        }
415        else
416        {
417          ibegin.setValue(this->i_index(0));
418          jbegin.setValue(0);
419          ni.setValue(this->i_index.numElements());
420          nj.setValue(1);
421        }
422     }
423
424     checkDomain();
425   }
426   CATCH_DUMP_ATTR
427
428   /*!
429     Fill in longitude and latitude whose values are read from file
430   */
431   void CDomain::fillInLonLat()
432   TRY
433   {
434     switch (type)
435     {
436      case type_attr::rectilinear:
437        fillInRectilinearLonLat();
438        break;
439      case type_attr::curvilinear:
440        fillInCurvilinearLonLat();
441        break;
442      case type_attr::unstructured:
443        fillInUnstructuredLonLat();
444        break;
445
446      default:
447      break;
448     }
449     completeLonLatClient() ;
450   }
451   CATCH_DUMP_ATTR
452
453   /*!
454     Fill in the values for lonvalue_1d and latvalue_1d of rectilinear domain
455     Range of longitude value from 0 - 360
456     Range of latitude value from -90 - +90
457   */
458   void CDomain::fillInRectilinearLonLat()
459   TRY
460   {
461     if (!lonvalue_rectilinear_read_from_file.isEmpty() && lonvalue_2d.isEmpty() && lonvalue_1d.isEmpty())
462     {
463       lonvalue_1d.resize(ni);
464       for (int idx = 0; idx < ni; ++idx)
465         lonvalue_1d(idx) = lonvalue_rectilinear_read_from_file(idx+ibegin);
466       lon_start.setValue(lonvalue_rectilinear_read_from_file(0));
467       lon_end.setValue(lonvalue_rectilinear_read_from_file(ni_glo-1));
468     }
469     else if (!hasLonInReadFile_)
470     {
471       if (!lonvalue_2d.isEmpty()) lonvalue_2d.free();
472       lonvalue_1d.resize(ni);
473       double lonRange = lon_end - lon_start;
474       double lonStep = (1 == ni_glo.getValue()) ? lonRange : lonRange/double(ni_glo.getValue()-1);
475
476        // Assign lon value
477       for (int i = 0; i < ni; ++i)
478       {
479         if (0 == (ibegin + i))
480         {
481           lonvalue_1d(i) = lon_start;
482         }
483         else if (ni_glo == (ibegin + i + 1))
484         {
485           lonvalue_1d(i) = lon_end;
486         }
487         else
488         {
489           lonvalue_1d(i) = (ibegin + i) * lonStep  + lon_start;
490         }
491       }
492     }
493
494
495     if (!latvalue_rectilinear_read_from_file.isEmpty() && latvalue_2d.isEmpty() && latvalue_1d.isEmpty())
496     {
497       latvalue_1d.resize(nj);
498       for (int idx = 0; idx < nj; ++idx)
499         latvalue_1d(idx) = latvalue_rectilinear_read_from_file(idx+jbegin);
500       lat_start.setValue(latvalue_rectilinear_read_from_file(0));
501       lat_end.setValue(latvalue_rectilinear_read_from_file(nj_glo-1));
502     }
503     else if (!hasLatInReadFile_)
504     {
505       if (!latvalue_2d.isEmpty()) latvalue_1d.free();
506       latvalue_1d.resize(nj);
507
508       double latRange = lat_end - lat_start;
509       double latStep = (1 == nj_glo.getValue()) ? latRange : latRange/double(nj_glo.getValue()-1);
510
511       for (int j = 0; j < nj; ++j)
512       {
513         if (0 == (jbegin + j))
514         {
515            latvalue_1d(j) = lat_start;
516         }
517         else if (nj_glo == (jbegin + j + 1))
518         {
519            latvalue_1d(j) = lat_end;
520         }
521         else
522         {
523           latvalue_1d(j) =  (jbegin + j) * latStep + lat_start;
524         }
525       }
526     }
527   }
528   CATCH_DUMP_ATTR
529
530    /*
531      Fill in 2D longitude and latitude of curvilinear domain read from a file.
532      If there are already longitude and latitude defined by model. We just ignore read value.
533    */
534   void CDomain::fillInCurvilinearLonLat()
535   TRY
536   {
537     if (!lonvalue_curvilinear_read_from_file.isEmpty() && lonvalue_2d.isEmpty() && lonvalue_1d.isEmpty())
538     {
539       lonvalue_2d.resize(ni,nj);
540       for (int jdx = 0; jdx < nj; ++jdx)
541        for (int idx = 0; idx < ni; ++idx)
542         lonvalue_2d(idx,jdx) = lonvalue_curvilinear_read_from_file(idx, jdx);
543
544       lonvalue_curvilinear_read_from_file.free();
545     }
546
547     if (!latvalue_curvilinear_read_from_file.isEmpty() && latvalue_2d.isEmpty() && latvalue_1d.isEmpty())
548     {
549       latvalue_2d.resize(ni,nj);
550       for (int jdx = 0; jdx < nj; ++jdx)
551        for (int idx = 0; idx < ni; ++idx)
552           latvalue_2d(idx,jdx) = latvalue_curvilinear_read_from_file(idx, jdx);
553
554       latvalue_curvilinear_read_from_file.free();
555     }
556
557     if (!bounds_lonvalue_curvilinear_read_from_file.isEmpty() && bounds_lon_2d.isEmpty() && bounds_lon_1d.isEmpty())
558     {
559       bounds_lon_2d.resize(nvertex,ni,nj);
560       for (int jdx = 0; jdx < nj; ++jdx)
561        for (int idx = 0; idx < ni; ++idx)
562          for (int ndx = 0; ndx < nvertex; ++ndx)
563            bounds_lon_2d(ndx,idx,jdx) = bounds_lonvalue_curvilinear_read_from_file(ndx,idx, jdx);
564
565       bounds_lonvalue_curvilinear_read_from_file.free();
566     }
567
568     if (!bounds_latvalue_curvilinear_read_from_file.isEmpty() && bounds_lat_2d.isEmpty() && bounds_lat_1d.isEmpty())
569     {
570       bounds_lat_2d.resize(nvertex,ni,nj);
571       for (int jdx = 0; jdx < nj; ++jdx)
572        for (int idx = 0; idx < ni; ++idx)
573          for (int ndx = 0; ndx < nvertex; ++ndx)
574            bounds_lat_2d(ndx,idx,jdx) = bounds_latvalue_curvilinear_read_from_file(ndx,idx, jdx);
575
576       bounds_latvalue_curvilinear_read_from_file.free();
577     }
578   }
579   CATCH_DUMP_ATTR
580
581    /*
582      Fill in longitude and latitude of unstructured domain read from a file
583      If there are already longitude and latitude defined by model. We just igonore reading value.
584    */
585   void CDomain::fillInUnstructuredLonLat()
586   TRY
587   {
588     if (i_index.isEmpty())
589     {
590       i_index.resize(ni);
591       for(int idx = 0; idx < ni; ++idx) i_index(idx)=ibegin+idx;
592     }
593
594     if (!lonvalue_unstructured_read_from_file.isEmpty() && lonvalue_1d.isEmpty())
595     {
596        lonvalue_1d.resize(ni);
597        for (int idx = 0; idx < ni; ++idx)
598          lonvalue_1d(idx) = lonvalue_unstructured_read_from_file(idx);
599
600        // We dont need these values anymore, so just delete them
601        lonvalue_unstructured_read_from_file.free();
602     } 
603
604     if (!latvalue_unstructured_read_from_file.isEmpty() && latvalue_1d.isEmpty())
605     {
606        latvalue_1d.resize(ni);
607        for (int idx = 0; idx < ni; ++idx)
608          latvalue_1d(idx) =  latvalue_unstructured_read_from_file(idx);
609
610        // We dont need these values anymore, so just delete them
611        latvalue_unstructured_read_from_file.free();
612     }
613
614     if (!bounds_lonvalue_unstructured_read_from_file.isEmpty() && bounds_lon_1d.isEmpty())
615     {
616        int nbVertex = nvertex;
617        bounds_lon_1d.resize(nbVertex,ni);
618        for (int idx = 0; idx < ni; ++idx)
619          for (int jdx = 0; jdx < nbVertex; ++jdx)
620            bounds_lon_1d(jdx,idx) = bounds_lonvalue_unstructured_read_from_file(jdx, idx);
621
622        // We dont need these values anymore, so just delete them
623        bounds_lonvalue_unstructured_read_from_file.free();
624     }
625
626     if (!bounds_latvalue_unstructured_read_from_file.isEmpty() && bounds_lat_1d.isEmpty())
627     {
628        int nbVertex = nvertex;
629        bounds_lat_1d.resize(nbVertex,ni);
630        for (int idx = 0; idx < ni; ++idx)
631          for (int jdx = 0; jdx < nbVertex; ++jdx)
632            bounds_lat_1d(jdx,idx) = bounds_latvalue_unstructured_read_from_file(jdx, idx);
633
634        // We dont need these values anymore, so just delete them
635        bounds_latvalue_unstructured_read_from_file.free();
636     }
637   }
638   CATCH_DUMP_ATTR
639
640  /*
641    Get global longitude and latitude of rectilinear domain.
642  */
643   void CDomain::AllgatherRectilinearLonLat(CArray<double,1>& lon, CArray<double,1>& lat, CArray<double,1>& lon_g, CArray<double,1>& lat_g)
644   TRY
645   {
646     CContext* context = CContext::getCurrent();
647    // For now the assumption is that secondary server pools consist of the same number of procs.
648    // CHANGE the line below if the assumption changes.
649     int clientSize = context->intraCommSize_ ;
650     lon_g.resize(ni_glo) ;
651     lat_g.resize(nj_glo) ;
652
653
654     int* ibegin_g = new int[clientSize] ;
655     int* jbegin_g = new int[clientSize] ;
656     int* ni_g = new int[clientSize] ;
657     int* nj_g = new int[clientSize] ;
658     int v ;
659     v=ibegin ;
660     MPI_Allgather(&v,1,MPI_INT,ibegin_g,1,MPI_INT,context->intraComm_) ;
661     v=jbegin ;
662     MPI_Allgather(&v,1,MPI_INT,jbegin_g,1,MPI_INT,context->intraComm_) ;
663     v=ni ;
664     MPI_Allgather(&v,1,MPI_INT,ni_g,1,MPI_INT,context->intraComm_) ;
665     v=nj ;
666     MPI_Allgather(&v,1,MPI_INT,nj_g,1,MPI_INT,context->intraComm_) ;
667
668     MPI_Allgatherv(lon.dataFirst(),ni,MPI_DOUBLE,lon_g.dataFirst(),ni_g, ibegin_g,MPI_DOUBLE,context->intraComm_) ;
669     MPI_Allgatherv(lat.dataFirst(),nj,MPI_DOUBLE,lat_g.dataFirst(),nj_g, jbegin_g,MPI_DOUBLE,context->intraComm_) ;
670
671      delete[] ibegin_g ;
672      delete[] jbegin_g ;
673      delete[] ni_g ;
674      delete[] nj_g ;
675   }
676   CATCH_DUMP_ATTR
677
678   void CDomain::fillInRectilinearBoundLonLat(CArray<double,1>& lon, CArray<double,1>& lat,
679                                              CArray<double,2>& boundsLon, CArray<double,2>& boundsLat)
680   TRY
681  {
682     int i,j,k;
683
684     const int nvertexValue = 4;
685     boundsLon.resize(nvertexValue,ni*nj);
686
687     if (ni_glo>1)
688     {
689       double lonStepStart = lon(1)-lon(0);
690       bounds_lon_start=lon(0) - lonStepStart/2;
691       double lonStepEnd = lon(ni_glo-1)-lon(ni_glo-2);
692       bounds_lon_end=lon(ni_glo-1) + lonStepEnd/2;
693       double errorBoundsLon = std::abs(360-std::abs(bounds_lon_end-bounds_lon_start));
694
695       // if errorBoundsLon is reasonably small (0.1 x cell size) consider it as closed in longitude
696       if (errorBoundsLon < std::abs(lonStepStart)*1e-1 || errorBoundsLon < std::abs(lonStepEnd)*1e-1 )
697       {
698         bounds_lon_start= (lon(0) + lon(ni_glo-1)-360)/2 ;
699         bounds_lon_end= (lon(0) +360 + lon(ni_glo-1))/2 ;
700       }
701     }
702     else
703     {
704       if (bounds_lon_start.isEmpty()) bounds_lon_start=-180. ;
705       if (bounds_lon_end.isEmpty()) bounds_lon_end=180.-1e-8 ;
706     }
707
708     for(j=0;j<nj;++j)
709       for(i=0;i<ni;++i)
710       {
711         k=j*ni+i;
712         boundsLon(0,k) = boundsLon(1,k) = (0 == (ibegin + i)) ? bounds_lon_start
713                                                               : (lon(ibegin + i)+lon(ibegin + i-1))/2;
714         boundsLon(2,k) = boundsLon(3,k) = ((ibegin + i + 1) == ni_glo) ? bounds_lon_end
715                                                                        : (lon(ibegin + i + 1)+lon(ibegin + i))/2;
716       }
717
718
719    boundsLat.resize(nvertexValue,nj*ni);
720    bool isNorthPole=false ;
721    bool isSouthPole=false ;
722    if (std::abs(90 - std::abs(lat(0))) < NumTraits<double>::epsilon()) isNorthPole = true;
723    if (std::abs(90 - std::abs(lat(nj_glo-1))) < NumTraits<double>::epsilon()) isSouthPole = true;
724
725    // lat boundaries beyond pole the assimilate it to pole
726    // lat boundarie is relativelly close to pole (0.1 x cell size) assimilate it to pole
727    if (nj_glo>1)
728    {
729      double latStepStart = lat(1)-lat(0);
730      if (isNorthPole) bounds_lat_start=lat(0);
731      else
732      {
733        bounds_lat_start=lat(0)-latStepStart/2;
734        if (bounds_lat_start >= 90 ) bounds_lat_start=90 ;
735        else if (bounds_lat_start <= -90 ) bounds_lat_start=-90 ;
736        else if (bounds_lat_start <= 90 && bounds_lat_start >= lat(0))
737        {
738          if ( std::abs(90-bounds_lat_start) <= 0.1*std::abs(latStepStart)) bounds_lat_start=90 ;
739        }
740        else if (bounds_lat_start >= -90 && bounds_lat_start <= lat(0))
741        {
742          if ( std::abs(-90 - bounds_lat_start) <= 0.1*std::abs(latStepStart)) bounds_lat_start=-90 ;
743        }
744      }
745
746      double latStepEnd = lat(nj_glo-1)-lat(nj_glo-2);
747      if (isSouthPole) bounds_lat_end=lat(nj_glo-1);
748      else
749      {
750        bounds_lat_end=lat(nj_glo-1)+latStepEnd/2;
751
752        if (bounds_lat_end >= 90 ) bounds_lat_end=90 ;
753        else if (bounds_lat_end <= -90 ) bounds_lat_end=-90 ;
754        else if (bounds_lat_end <= 90 && bounds_lat_end >= lat(nj_glo-1))
755        {
756          if ( std::abs(90-bounds_lat_end) <= 0.1*std::abs(latStepEnd)) bounds_lat_end=90 ;
757        }
758        else if (bounds_lat_end >= -90 && bounds_lat_end <= lat(nj_glo-1))
759        {
760          if ( std::abs(-90 - bounds_lat_end) <= 0.1*std::abs(latStepEnd)) bounds_lat_end=-90 ;
761        }
762      }
763    }
764    else
765    {
766      if (bounds_lat_start.isEmpty()) bounds_lat_start=-90. ;
767      if (bounds_lat_end.isEmpty()) bounds_lat_end=90 ;
768    }
769
770    for(j=0;j<nj;++j)
771      for(i=0;i<ni;++i)
772      {
773        k=j*ni+i;
774        boundsLat(1,k) = boundsLat(2,k) = (0 == (jbegin + j)) ? bounds_lat_start
775                                                              : (lat(jbegin + j)+lat(jbegin + j-1))/2;
776        boundsLat(0,k) = boundsLat(3,k) = ((jbegin + j +1) == nj_glo) ? bounds_lat_end
777                                                                      : (lat(jbegin + j + 1)+lat(jbegin + j))/2;
778      }
779   }
780   CATCH_DUMP_ATTR
781
782   /*
783     General check of the domain to verify its mandatory attributes
784   */
785   void CDomain::checkDomain(void)
786   TRY
787   {
788     if (type.isEmpty())
789     {
790       ERROR("CDomain::checkDomain(void)",
791             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
792             << "The domain type is mandatory, "
793             << "please define the 'type' attribute.")
794     }
795
796     if (type == type_attr::gaussian) 
797     {
798        hasPole=true ;
799        type.setValue(type_attr::unstructured) ;
800      }
801      else if (type == type_attr::rectilinear) hasPole=true ;
802
803     if (type == type_attr::unstructured)
804     {
805        if (ni_glo.isEmpty())
806        {
807          ERROR("CDomain::checkDomain(void)",
808                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
809                << "The global domain is badly defined, "
810                << "the mandatory 'ni_glo' attribute is missing.")
811        }
812        else if (ni_glo <= 0)
813        {
814          ERROR("CDomain::checkDomain(void)",
815                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
816                << "The global domain is badly defined, "
817                << "'ni_glo' attribute should be strictly positive so 'ni_glo = " << ni_glo.getValue() << "' is invalid.")
818        }
819        isUnstructed_ = true;
820        nj_glo = 1;
821        nj = 1;
822        jbegin = 0;
823        if (!i_index.isEmpty()) ni = i_index.numElements();
824        j_index.resize(ni);
825        for(int i=0;i<ni;++i) j_index(i)=0;
826
827        if (!area.isEmpty())
828          area.transposeSelf(1, 0);
829     }
830
831     if (ni_glo.isEmpty())
832     {
833       ERROR("CDomain::checkDomain(void)",
834             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
835             << "The global domain is badly defined, "
836             << "the mandatory 'ni_glo' attribute is missing.")
837     }
838     else if (ni_glo <= 0)
839     {
840       ERROR("CDomain::checkDomain(void)",
841             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
842             << "The global domain is badly defined, "
843             << "'ni_glo' attribute should be strictly positive so 'ni_glo = " << ni_glo.getValue() << "' is invalid.")
844     }
845
846     if (nj_glo.isEmpty())
847     {
848       ERROR("CDomain::checkDomain(void)",
849             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
850             << "The global domain is badly defined, "
851             << "the mandatory 'nj_glo' attribute is missing.")
852     }
853     else if (nj_glo <= 0)
854     {
855       ERROR("CDomain::checkDomain(void)",
856             << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
857             << "The global domain is badly defined, "
858             << "'nj_glo' attribute should be strictly positive so 'nj_glo = " << nj_glo.getValue() << "' is invalid.")
859     }
860
861     checkLocalIDomain();
862     checkLocalJDomain();
863
864     if (i_index.isEmpty())
865     {
866       i_index.resize(ni*nj);
867       for (int j = 0; j < nj; ++j)
868         for (int i = 0; i < ni; ++i) i_index(i+j*ni) = i+ibegin;
869     }
870
871     if (j_index.isEmpty())
872     {
873       j_index.resize(ni*nj);
874       for (int j = 0; j < nj; ++j)
875         for (int i = 0; i < ni; ++i) j_index(i+j*ni) = j+jbegin;
876     }
877   }
878   CATCH_DUMP_ATTR
879
880   size_t CDomain::getGlobalWrittenSize(void)
881   {
882     return ni_glo*nj_glo ;
883   }
884   //----------------------------------------------------------------
885
886   // Check validity of local domain on using the combination of 3 parameters: ibegin, ni and i_index
887   void CDomain::checkLocalIDomain(void)
888   TRY
889   {
890      // If ibegin and ni are provided then we use them to check the validity of local domain
891      if (i_index.isEmpty() && !ibegin.isEmpty() && !ni.isEmpty())
892      {
893        if ((ni.getValue() < 0 || ibegin.getValue() < 0) || ((ibegin.getValue() + ni.getValue()) > ni_glo.getValue()))
894        {
895          ERROR("CDomain::checkLocalIDomain(void)",
896                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
897                << "The local domain is wrongly defined,"
898                << " check the attributes 'ni_glo' (" << ni_glo.getValue() << "), 'ni' (" << ni.getValue() << ") and 'ibegin' (" << ibegin.getValue() << ")");
899        }
900      }
901
902      // i_index has higher priority than ibegin and ni
903      if (!i_index.isEmpty())
904      {
905        int minIIndex = (0 < i_index.numElements()) ? i_index(0) : 0;
906        if (ni.isEmpty()) 
907        {         
908         // No information about ni
909          int minIndex = ni_glo - 1;
910          int maxIndex = 0;
911          for (int idx = 0; idx < i_index.numElements(); ++idx)
912          {
913            if (i_index(idx) < minIndex) minIndex = i_index(idx);
914            if (i_index(idx) > maxIndex) maxIndex = i_index(idx);
915          }
916          ni = maxIndex - minIndex + 1; 
917          minIIndex = minIIndex;         
918        }
919
920        // It's not so correct but if ibegin is not the first value of i_index
921        // then data on local domain has user-defined distribution. In this case, ibegin, ni have no meaning.
922        if (ibegin.isEmpty()) ibegin = minIIndex;
923      }
924      else if (ibegin.isEmpty() && ni.isEmpty())
925      {
926        ibegin = 0;
927        ni = ni_glo;
928      }
929      else if ((!ibegin.isEmpty() && ni.isEmpty()) || (ibegin.isEmpty() && !ni.isEmpty()))
930      {
931        ERROR("CDomain::checkLocalIDomain(void)",
932              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
933              << "The local domain is wrongly defined," << endl
934              << "i_index is empty and either 'ni' or 'ibegin' is not defined. " 
935              << "If 'ni' and 'ibegin' are used to define a domain, both of them must not be empty.");
936      }
937       
938
939      if ((ni.getValue() < 0 || ibegin.getValue() < 0))
940      {
941        ERROR("CDomain::checkLocalIDomain(void)",
942              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
943              << "The local domain is wrongly defined,"
944              << " check the attributes 'ni_glo' (" << ni_glo.getValue() << "), 'ni' (" << ni.getValue() << ") and 'ibegin' (" << ibegin.getValue() << ")");
945      }
946   }
947   CATCH_DUMP_ATTR
948
949   // Check validity of local domain on using the combination of 3 parameters: jbegin, nj and j_index
950   void CDomain::checkLocalJDomain(void)
951   TRY
952   {
953    // If jbegin and nj are provided then we use them to check the validity of local domain
954     if (j_index.isEmpty() && !jbegin.isEmpty() && !nj.isEmpty())
955     {
956       if ((nj.getValue() < 0 || jbegin.getValue() < 0) || (jbegin.getValue() + nj.getValue()) > nj_glo.getValue())
957       {
958         ERROR("CDomain::checkLocalJDomain(void)",
959                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
960                << "The local domain is wrongly defined,"
961                << " check the attributes 'nj_glo' (" << nj_glo.getValue() << "), 'nj' (" << nj.getValue() << ") and 'jbegin' (" << jbegin.getValue() << ")");
962       }
963     }
964
965     if (!j_index.isEmpty())
966     {
967        int minJIndex = (0 < j_index.numElements()) ? j_index(0) : 0;
968        if (nj.isEmpty()) 
969        {
970          // No information about nj
971          int minIndex = nj_glo - 1;
972          int maxIndex = 0;
973          for (int idx = 0; idx < j_index.numElements(); ++idx)
974          {
975            if (j_index(idx) < minIndex) minIndex = j_index(idx);
976            if (j_index(idx) > maxIndex) maxIndex = j_index(idx);
977          }
978          nj = maxIndex - minIndex + 1;
979          minJIndex = minIndex; 
980        } 
981        // It's the same as checkLocalIDomain. It's not so correct but if jbegin is not the first value of j_index
982        // then data on local domain has user-defined distribution. In this case, jbegin has no meaning.
983       if (jbegin.isEmpty()) jbegin = minJIndex;       
984     }
985     else if (jbegin.isEmpty() && nj.isEmpty())
986     {
987       jbegin = 0;
988       nj = nj_glo;
989     }     
990
991
992     if ((nj.getValue() < 0 || jbegin.getValue() < 0))
993     {
994       ERROR("CDomain::checkLocalJDomain(void)",
995              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
996              << "The local domain is wrongly defined,"
997              << " check the attributes 'nj_glo' (" << nj_glo.getValue() << "), 'nj' (" << nj.getValue() << ") and 'jbegin' (" << jbegin.getValue() << ")");
998     }
999   }
1000   CATCH_DUMP_ATTR
1001
1002   //----------------------------------------------------------------
1003
1004   void CDomain::checkMask(void)
1005   TRY
1006   {
1007      if (!mask_1d.isEmpty() && !mask_2d.isEmpty())
1008        ERROR("CDomain::checkMask(void)",
1009              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1010              << "Both mask_1d and mask_2d are defined but only one can be used at the same time." << std::endl
1011              << "Please define only one mask: 'mask_1d' or 'mask_2d'.");
1012
1013      if (!mask_1d.isEmpty() && mask_2d.isEmpty())
1014      {
1015        if (mask_1d.numElements() != i_index.numElements())
1016          ERROR("CDomain::checkMask(void)",
1017                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1018                << "'mask_1d' does not have the same size as the local domain." << std::endl
1019                << "Local size is " << i_index.numElements() << "." << std::endl
1020                << "Mask size is " << mask_1d.numElements() << ".");
1021      }
1022
1023      if (mask_1d.isEmpty() && !mask_2d.isEmpty())
1024      {
1025        if (mask_2d.extent(0) != ni || mask_2d.extent(1) != nj)
1026          ERROR("CDomain::checkMask(void)",
1027                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1028                << "The mask does not have the same size as the local domain." << std::endl
1029                << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1030                << "Mask size is " << mask_2d.extent(0) << " x " << mask_2d.extent(1) << ".");
1031      }
1032
1033      if (!mask_2d.isEmpty())
1034      {
1035        domainMask.resize(mask_2d.extent(0) * mask_2d.extent(1));
1036        for (int j = 0; j < nj; ++j)
1037          for (int i = 0; i < ni; ++i) domainMask(i+j*ni) = mask_2d(i,j);
1038//        mask_2d.reset();
1039      }
1040      else if (mask_1d.isEmpty())
1041      {
1042        domainMask.resize(i_index.numElements());
1043        for (int i = 0; i < i_index.numElements(); ++i) domainMask(i) = true;
1044      }
1045      else
1046      {
1047      domainMask.resize(mask_1d.numElements());
1048      domainMask=mask_1d ;
1049     }
1050   }
1051   CATCH_DUMP_ATTR
1052
1053   //----------------------------------------------------------------
1054
1055   void CDomain::checkDomainData(void)
1056   TRY
1057   {
1058      if (data_dim.isEmpty())
1059      {
1060        data_dim.setValue(1);
1061      }
1062      else if (!(data_dim.getValue() == 1 || data_dim.getValue() == 2))
1063      {
1064        ERROR("CDomain::checkDomainData(void)",
1065              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1066              << "The data dimension is invalid, 'data_dim' must be 1 or 2 not << " << data_dim.getValue() << ".");
1067      }
1068
1069      if (data_ibegin.isEmpty())
1070         data_ibegin.setValue(0);
1071      if (data_jbegin.isEmpty())
1072         data_jbegin.setValue(0);
1073
1074      if (data_ni.isEmpty())
1075      {
1076        data_ni.setValue((data_dim == 1) ? (ni.getValue() * nj.getValue()) : ni.getValue());
1077      }
1078      else if (data_ni.getValue() < 0)
1079      {
1080        ERROR("CDomain::checkDomainData(void)",
1081              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1082              << "The data size cannot be negative ('data_ni' = " << data_ni.getValue() << ").");
1083      }
1084
1085      if (data_nj.isEmpty())
1086      {
1087        data_nj.setValue((data_dim.getValue() == 1) ? (ni.getValue() * nj.getValue()) : nj.getValue());
1088      }
1089      else if (data_nj.getValue() < 0)
1090      {
1091        ERROR("CDomain::checkDomainData(void)",
1092              << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1093              << "The data size cannot be negative ('data_nj' = " << data_nj.getValue() << ").");
1094      }
1095   }
1096   CATCH_DUMP_ATTR
1097
1098   //----------------------------------------------------------------
1099
1100   void CDomain::checkCompression(void)
1101   TRY
1102   {
1103     int i,j,ind;
1104      if (!data_i_index.isEmpty())
1105      {
1106        if (!data_j_index.isEmpty() &&
1107            data_j_index.numElements() != data_i_index.numElements())
1108        {
1109           ERROR("CDomain::checkCompression(void)",
1110                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1111                 << "'data_i_index' and 'data_j_index' arrays must have the same size." << std::endl
1112                 << "'data_i_index' size = " << data_i_index.numElements() << std::endl
1113                 << "'data_j_index' size = " << data_j_index.numElements());
1114        }
1115
1116        if (2 == data_dim)
1117        {
1118          if (data_j_index.isEmpty())
1119          {
1120             ERROR("CDomain::checkCompression(void)",
1121                   << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1122                   << "'data_j_index' must be defined when 'data_i_index' is set and 'data_dim' is 2.");
1123          }
1124          for (int k=0; k<data_i_index.numElements(); ++k)
1125          {
1126            i = data_i_index(k)+data_ibegin ;
1127            j = data_j_index(k)+data_jbegin ;
1128            if (i>=0 && i<ni && j>=0 && j<nj)
1129            {
1130              ind=j*ni+i ;
1131              if (!domainMask(ind))
1132              {
1133                data_i_index(k) = -1;
1134                data_j_index(k) = -1;
1135              }
1136            }
1137            else
1138            {
1139              data_i_index(k) = -1;
1140              data_j_index(k) = -1;
1141            }
1142          }
1143        }
1144        else // (1 == data_dim)
1145        {
1146          if (data_j_index.isEmpty())
1147          {
1148            data_j_index.resize(data_ni);
1149            data_j_index = 0;
1150          }
1151          for (int k=0; k<data_i_index.numElements(); ++k)
1152          {
1153            i=data_i_index(k)+data_ibegin ;
1154            if (i>=0 && i < domainMask.size())
1155            {
1156              if (!domainMask(i)) data_i_index(k) = -1;
1157            }
1158            else
1159              data_i_index(k) = -1;
1160
1161            if (!domainMask(i)) data_i_index(k) = -1;
1162          }
1163        }
1164      }
1165      else
1166      {
1167        if (data_dim == 2 && !data_j_index.isEmpty())
1168          ERROR("CDomain::checkCompression(void)",
1169                << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1170                << "'data_i_index' must be defined when 'data_j_index' is set and 'data_dim' is 2.");
1171
1172        if (1 == data_dim)
1173        {
1174          data_i_index.resize(data_ni);
1175          data_j_index.resize(data_ni);
1176          data_j_index = 0;
1177
1178          for (int k = 0; k < data_ni; ++k)
1179          {
1180            i=k+data_ibegin ;
1181            if (i>=0 && i < domainMask.size())
1182            {
1183              if (domainMask(i))
1184                data_i_index(k) = k;
1185              else
1186                data_i_index(k) = -1;
1187            }
1188            else
1189              data_i_index(k) = -1;
1190          }
1191        }
1192        else // (data_dim == 2)
1193        {
1194          const int dsize = data_ni * data_nj;
1195          data_i_index.resize(dsize);
1196          data_j_index.resize(dsize);
1197
1198          for(int count = 0, kj = 0; kj < data_nj; ++kj)
1199          {
1200            for(int ki = 0; ki < data_ni; ++ki, ++count)
1201            {
1202              i = ki + data_ibegin;
1203              j = kj + data_jbegin;
1204              ind=j*ni+i ;
1205              if (i>=0 && i<ni && j>=0 && j<nj)
1206              {
1207                if (domainMask(ind))
1208                {
1209                  data_i_index(count) = ki;
1210                  data_j_index(count) = kj;
1211                }
1212                else
1213                {
1214                  data_i_index(count) = -1;
1215                  data_j_index(count) = -1;
1216                }
1217              }
1218              else
1219              {
1220                data_i_index(count) = -1;
1221                data_j_index(count) = -1;
1222              }
1223            }
1224          }
1225        }
1226      }
1227   }
1228   CATCH_DUMP_ATTR
1229
1230   //----------------------------------------------------------------
1231   void CDomain::computeLocalMask(void)
1232   TRY
1233   {
1234     localMask.resize(i_index.numElements()) ;
1235     localMask=false ;
1236
1237     size_t dn=data_i_index.numElements() ;
1238     int i,j ;
1239     size_t k,ind ;
1240
1241     for(k=0;k<dn;k++)
1242     {
1243       if (data_dim==2)
1244       {
1245          i=data_i_index(k)+data_ibegin ;
1246          j=data_j_index(k)+data_jbegin ;
1247          if (i>=0 && i<ni && j>=0 && j<nj)
1248          {
1249            ind=j*ni+i ;
1250            localMask(ind)=domainMask(ind) ;
1251          }
1252       }
1253       else
1254       {
1255          i=data_i_index(k)+data_ibegin ;
1256          if (i>=0 && i<i_index.numElements())
1257          {
1258            ind=i ;
1259            localMask(ind)=domainMask(ind) ;
1260          }
1261       }
1262     }
1263   }
1264   CATCH_DUMP_ATTR
1265
1266
1267   //----------------------------------------------------------------
1268
1269   /*
1270     Fill in longitude, latitude, bounds, and area into internal values (lonvalue, latvalue, bounds_lonvalue, bounds_latvalue, areavalue)
1271     which will be used by XIOS.
1272   */
1273   void CDomain::completeLonLatClient(void)
1274   TRY
1275   {
1276     bool lonlatValueExisted = (0 != lonvalue.numElements()) || (0 != latvalue.numElements());
1277     checkBounds() ;
1278     checkArea() ;
1279
1280     if (!lonvalue_2d.isEmpty() && !lonlatValueExisted)
1281     {
1282       lonvalue.resize(ni * nj);
1283       latvalue.resize(ni * nj);
1284       if (hasBounds)
1285       {
1286         bounds_lonvalue.resize(nvertex, ni * nj);
1287         bounds_latvalue.resize(nvertex, ni * nj);
1288       }
1289
1290       for (int j = 0; j < nj; ++j)
1291       {
1292         for (int i = 0; i < ni; ++i)
1293         {
1294           int k = j * ni + i;
1295
1296           lonvalue(k) = lonvalue_2d(i,j);
1297           latvalue(k) = latvalue_2d(i,j);
1298
1299           if (hasBounds)
1300           {
1301             for (int n = 0; n < nvertex; ++n)
1302             {
1303               bounds_lonvalue(n,k) = bounds_lon_2d(n,i,j);
1304               bounds_latvalue(n,k) = bounds_lat_2d(n,i,j);
1305             }
1306           }
1307         }
1308       }
1309     }
1310     else if (!lonvalue_1d.isEmpty()  && !lonlatValueExisted)
1311     {
1312       if (type_attr::rectilinear == type)
1313       {
1314         if (ni == lonvalue_1d.numElements() && nj == latvalue_1d.numElements())
1315         {
1316           lonvalue.resize(ni * nj);
1317           latvalue.resize(ni * nj);
1318           if (hasBounds)
1319           {
1320             bounds_lonvalue.resize(nvertex, ni * nj);
1321             bounds_latvalue.resize(nvertex, ni * nj);
1322           }
1323
1324           for (int j = 0; j < nj; ++j)
1325           {
1326             for (int i = 0; i < ni; ++i)
1327             {
1328               int k = j * ni + i;
1329
1330               lonvalue(k) = lonvalue_1d(i);
1331               latvalue(k) = latvalue_1d(j);
1332
1333               if (hasBounds)
1334               {
1335                 for (int n = 0; n < nvertex; ++n)
1336                 {
1337                   bounds_lonvalue(n,k) = bounds_lon_1d(n,i);
1338                   bounds_latvalue(n,k) = bounds_lat_1d(n,j);
1339                 }
1340               }
1341             }
1342           }
1343         }
1344         else if (i_index.numElements() == lonvalue_1d.numElements() && j_index.numElements() == latvalue_1d.numElements()  && !lonlatValueExisted)
1345         {
1346           lonvalue.reference(lonvalue_1d);
1347           latvalue.reference(latvalue_1d);
1348            if (hasBounds)
1349           {
1350             bounds_lonvalue.reference(bounds_lon_1d);
1351             bounds_latvalue.reference(bounds_lat_1d);
1352           }
1353         }
1354         else
1355           ERROR("CDomain::completeLonClient(void)",
1356                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1357                 << "'lonvalue_1d' and 'latvalue_1d' does not have the same size as the local domain." << std::endl
1358                 << "'lonvalue_1d' size is " << lonvalue_1d.numElements() 
1359                 << " and 'latvalue_1d' size is " << latvalue_1d.numElements() << std::endl
1360                 << " They should be correspondingly " << ni.getValue() << " and "  << nj.getValue() << " or " << std::endl
1361                 << i_index.numElements() << " and "  << j_index.numElements() << ".");
1362       }
1363       else if (type == type_attr::curvilinear || type == type_attr::unstructured  && !lonlatValueExisted)
1364       {
1365         lonvalue.reference(lonvalue_1d);
1366         latvalue.reference(latvalue_1d);
1367         if (hasBounds)
1368         {
1369           bounds_lonvalue.reference(bounds_lon_1d);
1370           bounds_latvalue.reference(bounds_lat_1d);
1371         }
1372       }
1373     }
1374
1375     if (!area.isEmpty() && areavalue.isEmpty())
1376     {
1377        areavalue.resize(ni*nj);
1378       for (int j = 0; j < nj; ++j)
1379       {
1380         for (int i = 0; i < ni; ++i)
1381         {
1382           int k = j * ni + i;
1383           areavalue(k) = area(i,j);
1384         }
1385       }
1386     }
1387   }
1388   CATCH_DUMP_ATTR
1389
1390   /*
1391     Convert internal longitude latitude value used by XIOS to "lonvalue_*" which can be retrieved with Fortran interface
1392   */
1393   void CDomain::convertLonLatValue(void)
1394   TRY
1395   {
1396     bool lonlatValueExisted = (0 != lonvalue.numElements()) || (0 != latvalue.numElements());
1397     if (!lonvalue_2d.isEmpty() && lonlatValueExisted)
1398     {
1399       lonvalue_2d.resize(ni,nj);
1400       latvalue_2d.resize(ni,nj);
1401       if (hasBounds)
1402       {
1403         bounds_lon_2d.resize(nvertex, ni, nj);
1404         bounds_lat_2d.resize(nvertex, ni, nj);
1405       }
1406
1407       for (int j = 0; j < nj; ++j)
1408       {
1409         for (int i = 0; i < ni; ++i)
1410         {
1411           int k = j * ni + i;
1412
1413           lonvalue_2d(i,j) = lonvalue(k);
1414           latvalue_2d(i,j) = latvalue(k);
1415
1416           if (hasBounds)
1417           {
1418             for (int n = 0; n < nvertex; ++n)
1419             {
1420               bounds_lon_2d(n,i,j) = bounds_lonvalue(n,k);
1421               bounds_lat_2d(n,i,j) = bounds_latvalue(n,k);
1422             }
1423           }
1424         }
1425       }
1426     }
1427     else if (!lonvalue_1d.isEmpty()  && lonlatValueExisted)
1428     {
1429       if (type_attr::rectilinear == type)
1430       {
1431         if (ni == lonvalue_1d.numElements() && nj == latvalue_1d.numElements())
1432         {
1433           lonvalue.resize(ni * nj);
1434           latvalue.resize(ni * nj);
1435           if (hasBounds)
1436           {
1437             bounds_lonvalue.resize(nvertex, ni * nj);
1438             bounds_latvalue.resize(nvertex, ni * nj);
1439           }
1440
1441           for (int j = 0; j < nj; ++j)
1442           {
1443             for (int i = 0; i < ni; ++i)
1444             {
1445               int k = j * ni + i;
1446
1447               lonvalue(k) = lonvalue_1d(i);
1448               latvalue(k) = latvalue_1d(j);
1449
1450               if (hasBounds)
1451               {
1452                 for (int n = 0; n < nvertex; ++n)
1453                 {
1454                   bounds_lonvalue(n,k) = bounds_lon_1d(n,i);
1455                   bounds_latvalue(n,k) = bounds_lat_1d(n,j);
1456                 }
1457               }
1458             }
1459           }
1460         }
1461         else if (i_index.numElements() == lonvalue_1d.numElements() && j_index.numElements() == latvalue_1d.numElements()  && !lonlatValueExisted)
1462         {
1463           lonvalue.reference(lonvalue_1d);
1464           latvalue.reference(latvalue_1d);
1465            if (hasBounds)
1466           {
1467             bounds_lonvalue.reference(bounds_lon_1d);
1468             bounds_latvalue.reference(bounds_lat_1d);
1469           }
1470         }
1471         else
1472           ERROR("CDomain::completeLonClient(void)",
1473                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1474                 << "'lonvalue_1d' and 'latvalue_1d' does not have the same size as the local domain." << std::endl
1475                 << "'lonvalue_1d' size is " << lonvalue_1d.numElements() 
1476                 << " and 'latvalue_1d' size is " << latvalue_1d.numElements() << std::endl
1477                 << " They should be correspondingly " << ni.getValue() << " and "  << nj.getValue() << " or " << std::endl
1478                 << i_index.numElements() << " and "  << j_index.numElements() << ".");
1479       }
1480       else if (type == type_attr::curvilinear || type == type_attr::unstructured  && !lonlatValueExisted)
1481       {
1482         lonvalue.reference(lonvalue_1d);
1483         latvalue.reference(latvalue_1d);
1484         if (hasBounds)
1485         {
1486           bounds_lonvalue.reference(bounds_lon_1d);
1487           bounds_latvalue.reference(bounds_lat_1d);
1488         }
1489       }
1490     }
1491   }
1492   CATCH_DUMP_ATTR
1493
1494   void CDomain::checkBounds(void)
1495   TRY
1496   {
1497     bool hasBoundValues = (0 != bounds_lonvalue.numElements()) || (0 != bounds_latvalue.numElements());
1498     if (!nvertex.isEmpty() && nvertex > 0 && !hasBoundValues)
1499     {
1500       if (!bounds_lon_1d.isEmpty() && !bounds_lon_2d.isEmpty())
1501         ERROR("CDomain::checkBounds(void)",
1502               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1503               << "Only one longitude boundary attribute can be used but both 'bounds_lon_1d' and 'bounds_lon_2d' are defined." << std::endl
1504               << "Define only one longitude boundary attribute: 'bounds_lon_1d' or 'bounds_lon_2d'.");
1505
1506       if (!bounds_lat_1d.isEmpty() && !bounds_lat_2d.isEmpty())
1507         ERROR("CDomain::checkBounds(void)",
1508               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1509               << "Only one latitude boundary attribute can be used but both 'bounds_lat_1d' and 'bounds_lat_2d' are defined." << std::endl
1510               << "Define only one latitude boundary attribute: 'bounds_lat_1d' or 'bounds_lat_2d'.");
1511
1512       if ((!bounds_lon_1d.isEmpty() && bounds_lat_1d.isEmpty()) || (bounds_lon_1d.isEmpty() && !bounds_lat_1d.isEmpty()))
1513       {
1514         ERROR("CDomain::checkBounds(void)",
1515               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1516               << "Only 'bounds_lon_1d' or 'bounds_lat_1d' is defined." << std::endl
1517               << "Please define either both attributes or none.");
1518       }
1519
1520       if ((!bounds_lon_2d.isEmpty() && bounds_lat_2d.isEmpty()) || (bounds_lon_2d.isEmpty() && !bounds_lat_2d.isEmpty()))
1521       {
1522         ERROR("CDomain::checkBounds(void)",
1523               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1524               << "Only 'bounds_lon_2d' or 'bounds_lat_2d' is defined." << std::endl
1525               << "Please define either both attributes or none.");
1526       }
1527
1528       if (!bounds_lon_1d.isEmpty() && nvertex.getValue() != bounds_lon_1d.extent(0))
1529         ERROR("CDomain::checkBounds(void)",
1530               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1531               << "'bounds_lon_1d' dimension is not compatible with 'nvertex'." << std::endl
1532               << "'bounds_lon_1d' dimension is " << bounds_lon_1d.extent(0)
1533               << " but nvertex is " << nvertex.getValue() << ".");
1534
1535       if (!bounds_lon_2d.isEmpty() && nvertex.getValue() != bounds_lon_2d.extent(0))
1536         ERROR("CDomain::checkBounds(void)",
1537               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1538               << "'bounds_lon_2d' dimension is not compatible with 'nvertex'." << std::endl
1539               << "'bounds_lon_2d' dimension is " << bounds_lon_2d.extent(0)
1540               << " but nvertex is " << nvertex.getValue() << ".");
1541
1542       if (!bounds_lon_1d.isEmpty() && lonvalue_1d.isEmpty())
1543         ERROR("CDomain::checkBounds(void)",
1544               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1545               << "Since 'bounds_lon_1d' is defined, 'lonvalue_1d' must be defined too." << std::endl);
1546
1547       if (!bounds_lon_2d.isEmpty() && lonvalue_2d.isEmpty())
1548         ERROR("CDomain::checkBounds(void)",
1549               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1550               << "Since 'bounds_lon_2d' is defined, 'lonvalue_2d' must be defined too." << std::endl);
1551
1552       if (!bounds_lat_1d.isEmpty() && nvertex.getValue() != bounds_lat_1d.extent(0))
1553         ERROR("CDomain::checkBounds(void)",
1554               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1555               << "'bounds_lat_1d' dimension is not compatible with 'nvertex'." << std::endl
1556               << "'bounds_lat_1d' dimension is " << bounds_lat_1d.extent(0)
1557               << " but nvertex is " << nvertex.getValue() << ".");
1558
1559       if (!bounds_lat_2d.isEmpty() && nvertex.getValue() != bounds_lat_2d.extent(0))
1560         ERROR("CDomain::checkBounds(void)",
1561               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1562               << "'bounds_lat_2d' dimension is not compatible with 'nvertex'." << std::endl
1563               << "'bounds_lat_2d' dimension is " << bounds_lat_2d.extent(0)
1564               << " but nvertex is " << nvertex.getValue() << ".");
1565
1566       if (!bounds_lat_1d.isEmpty() && latvalue_1d.isEmpty())
1567         ERROR("CDomain::checkBounds(void)",
1568               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1569               << "Since 'bounds_lat_1d' is defined, 'latvalue_1d' must be defined too." << std::endl);
1570
1571       if (!bounds_lat_2d.isEmpty() && latvalue_2d.isEmpty())
1572         ERROR("CDomain::checkBounds(void)",
1573               << "Since 'bounds_lat_2d' is defined, 'latvalue_2d' must be defined too." << std::endl);
1574
1575       // In case of reading UGRID bounds values are not required
1576       hasBounds = (!bounds_lat_1d.isEmpty() || !bounds_lat_2d.isEmpty() );
1577     }
1578     else if (hasBoundValues)
1579     {
1580       hasBounds = true;       
1581     }
1582     else
1583     {
1584       hasBounds = false;
1585     }
1586   }
1587   CATCH_DUMP_ATTR
1588
1589   void CDomain::checkArea(void)
1590   TRY
1591   {
1592     bool hasAreaValue = (!areavalue.isEmpty() && 0 != areavalue.numElements());
1593     hasArea = !area.isEmpty();
1594     if (hasArea && !hasAreaValue)
1595     {
1596       if (area.extent(0) != ni || area.extent(1) != nj)
1597       {
1598         ERROR("CDomain::checkArea(void)",
1599               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1600               << "The area does not have the same size as the local domain." << std::endl
1601               << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1602               << "Area size is " << area.extent(0) << " x " << area.extent(1) << ".");
1603       }
1604//       if (areavalue.isEmpty())
1605//       {
1606//          areavalue.resize(ni*nj);
1607//         for (int j = 0; j < nj; ++j)
1608//         {
1609//           for (int i = 0; i < ni; ++i)
1610//           {
1611//             int k = j * ni + i;
1612//             areavalue(k) = area(i,j);
1613//           }
1614//         }
1615//       }
1616     }
1617   }
1618   CATCH_DUMP_ATTR
1619
1620   void CDomain::checkLonLat()
1621   TRY
1622   {
1623     if (!hasLonLat) hasLonLat = (!latvalue_1d.isEmpty() && !lonvalue_1d.isEmpty()) ||
1624                                 (!latvalue_2d.isEmpty() && !lonvalue_2d.isEmpty());
1625     bool hasLonLatValue = (0 != lonvalue.numElements()) || (0 != latvalue.numElements());
1626     if (hasLonLat && !hasLonLatValue)
1627     {
1628       if (!lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
1629         ERROR("CDomain::checkLonLat()",
1630               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1631               << "Only one longitude attribute can be used but both 'lonvalue_1d' and 'lonvalue_2d' are defined." << std::endl
1632               << "Define only one longitude attribute: 'lonvalue_1d' or 'lonvalue_2d'.");
1633
1634       if (!lonvalue_1d.isEmpty() && lonvalue_2d.isEmpty())
1635       {
1636         if ((type_attr::rectilinear != type) && (lonvalue_1d.numElements() != i_index.numElements()))
1637           ERROR("CDomain::checkLonLat()",
1638                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1639                 << "'lonvalue_1d' does not have the same size as the local domain." << std::endl
1640                 << "Local size is " << i_index.numElements() << "." << std::endl
1641                 << "'lonvalue_1d' size is " << lonvalue_1d.numElements() << ".");
1642       }
1643
1644       if (lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
1645       {
1646         if (lonvalue_2d.extent(0) != ni || lonvalue_2d.extent(1) != nj)
1647           ERROR("CDomain::checkLonLat()",
1648                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1649                 << "'lonvalue_2d' does not have the same size as the local domain." << std::endl
1650                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1651                 << "'lonvalue_2d' size is " << lonvalue_2d.extent(0) << " x " << lonvalue_2d.extent(1) << ".");
1652       }
1653
1654       if (!latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
1655         ERROR("CDomain::checkLonLat()",
1656               << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1657               << "Only one latitude attribute can be used but both 'latvalue_1d' and 'latvalue_2d' are defined." << std::endl
1658               << "Define only one latitude attribute: 'latvalue_1d' or 'latvalue_2d'.");
1659
1660       if (!latvalue_1d.isEmpty() && latvalue_2d.isEmpty())
1661       {
1662         if ((type_attr::rectilinear != type) && (latvalue_1d.numElements() != i_index.numElements()))
1663           ERROR("CDomain::checkLonLat()",
1664                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1665                 << "'latvalue_1d' does not have the same size as the local domain." << std::endl
1666                 << "Local size is " << i_index.numElements() << "." << std::endl
1667                 << "'latvalue_1d' size is " << latvalue_1d.numElements() << ".");
1668       }
1669
1670       if (latvalue_1d.isEmpty() && !latvalue_2d.isEmpty())
1671       {
1672         if (latvalue_2d.extent(0) != ni || latvalue_2d.extent(1) != nj)
1673           ERROR("CDomain::checkLonLat()",
1674                 << "[ id = " << this->getId() << " , context = '" << CObjectFactory::GetCurrentContextId() << " ] "
1675                 << "'latvalue_2d' does not have the same size as the local domain." << std::endl
1676                 << "Local size is " << ni.getValue() << " x " << nj.getValue() << "." << std::endl
1677                 << "'latvalue_2d' size is " << latvalue_2d.extent(0) << " x " << latvalue_2d.extent(1) << ".");
1678       }
1679     }
1680   }
1681   CATCH_DUMP_ATTR
1682
1683   void CDomain::checkAttributes(void)
1684   TRY
1685   {
1686      if (this->checkAttributes_done_) return;
1687      this->checkDomain();
1688      this->checkLonLat();
1689      this->checkBounds();
1690      this->checkArea();
1691      this->checkMask();
1692      this->checkDomainData();
1693      this->checkCompression();
1694      this->computeLocalMask() ;
1695      this->completeLonLatClient();
1696      this->initializeLocalElement() ;
1697      this->addFullView() ; // probably do not automatically add View, but only if requested
1698      this->addWorkflowView() ; // probably do not automatically add View, but only if requested
1699      this->addModelView() ; // probably do not automatically add View, but only if requested
1700      // testing ?
1701     /*
1702      CLocalView* local = localElement_->getView(CElementView::WORKFLOW) ;
1703      CLocalView* model = localElement_->getView(CElementView::MODEL) ;
1704
1705      CLocalConnector test1(model, local) ;
1706      test1.computeConnector() ;
1707      CLocalConnector test2(local, model) ;
1708      test2.computeConnector() ;
1709      CGridLocalConnector gridTest1(vector<CLocalConnector*>{&test1}) ;
1710      CGridLocalConnector gridTest2(vector<CLocalConnector*>{&test2}) ;
1711     
1712     
1713      CArray<int,1> out1 ;
1714      CArray<int,1> out2 ;
1715      test1.transfer(data_i_index,out1,-111) ;
1716      test2.transfer(out1,out2,-111) ;
1717     
1718      out1 = 0 ;
1719      out2 = 0 ;
1720      gridTest1.transfer(data_i_index,out1,-111) ;
1721      gridTest2.transfer(out1, out2,-111) ;
1722    */ 
1723      this->checkAttributes_done_ = true;
1724   }
1725   CATCH_DUMP_ATTR
1726
1727
1728   void CDomain::initializeLocalElement(void)
1729   {
1730      // after checkDomain i_index and j_index of size (ni*nj)
1731      int nij = ni*nj ;
1732      CArray<size_t, 1> ij_index(ni*nj) ;
1733      for(int ij=0; ij<nij ; ij++) ij_index(ij) = i_index(ij)+j_index(ij)*ni_glo ;
1734      int rank = CContext::getCurrent()->getIntraCommRank() ;
1735      localElement_ = new CLocalElement(rank, ni_glo*nj_glo, ij_index) ;
1736   }
1737
1738   void CDomain::addFullView(void)
1739   {
1740      CArray<int,1> index(ni*nj) ;
1741      int nij=ni*nj ;
1742      for(int ij=0; ij<nij ; ij++) index(ij)=ij ;
1743      localElement_ -> addView(CElementView::FULL, index) ;
1744   }
1745
1746   void CDomain::addWorkflowView(void)
1747   {
1748     // information for workflow view is stored in localMask
1749     int nij=ni*nj ;
1750     int nMask=0 ;
1751     for(int ij=0; ij<nij ; ij++) if (localMask(ij)) nMask++ ;
1752     CArray<int,1> index(nMask) ;
1753
1754     nMask=0 ;
1755     for(int ij=0; ij<nij ; ij++) 
1756      if (localMask(ij))
1757      {
1758        index(nMask)=ij ;
1759        nMask++ ;
1760      }
1761      localElement_ -> addView(CElementView::WORKFLOW, index) ;
1762   }
1763
1764   void CDomain::addModelView(void)
1765   {
1766     // information for model view is stored in data_i_index/data_j_index
1767     // very weird, do not mix data_i_index and data_i_begin => in future only keep data_i_index
1768     int dataSize = data_i_index.numElements() ;
1769     CArray<int,1> index(dataSize) ;
1770     int i,j ;
1771     for(int k=0;k<dataSize;k++)
1772     {
1773        if (data_dim==2)
1774        {
1775          i=data_i_index(k)+data_ibegin ; // bad
1776          j=data_j_index(k)+data_jbegin ; // bad
1777          if (i>=0 && i<ni && j>=0 && j<nj) index(k)=i+j*ni ;
1778          else index(k)=-1 ;
1779        }
1780        else if (data_dim==1)
1781        {
1782          i=data_i_index(k)+data_ibegin ; // bad
1783          if (i>=0 && i<ni*nj) index(k)=i ;
1784          else index(k)=-1 ;
1785        }
1786     }
1787     localElement_->addView(CElementView::MODEL, index) ;
1788   }
1789       
1790   void CDomain::computeModelToWorkflowConnector(void)
1791   { 
1792     CLocalView* srcView=getLocalView(CElementView::MODEL) ;
1793     CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ;
1794     modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 
1795     modelToWorkflowConnector_->computeConnector() ;
1796   }
1797
1798
1799   
1800  /* to be removed later when coupling will be reimplemented, just to  not forget */
1801  void CDomain::sendDomainToCouplerOut(CContextClient* client, const string& fieldId, int posInGrid)
1802  {
1803    if (sendDomainToFileServer_done_.count(client)!=0) return ;
1804    else sendDomainToFileServer_done_.insert(client) ;
1805   
1806    const string domainId = "_domain["+std::to_string(posInGrid)+"]_of_"+fieldId ;
1807   
1808    if (!domain_ref.isEmpty())
1809    {
1810      auto domain_ref_tmp=domain_ref.getValue() ;
1811      domain_ref.reset() ; // remove the reference, find an other way to do that more cleanly
1812      this->sendAllAttributesToServer(client, domainId)  ;
1813      domain_ref = domain_ref_tmp ;
1814    }
1815    else this->sendAllAttributesToServer(client, domainId)  ;
1816  }
1817
1818
1819
1820
1821  void CDomain::makeAliasForCoupling(const string& fieldId, int posInGrid)
1822  {
1823    const string domainId = "_domain["+std::to_string(posInGrid)+"]_of_"+fieldId ;
1824    this->createAlias(domainId) ;
1825  }
1826
1827
1828  void CDomain::computeRemoteElement(CContextClient* client, EDistributionType type)
1829  TRY
1830  {
1831    CContext* context = CContext::getCurrent();
1832    map<int, CArray<size_t,1>> globalIndex ;
1833
1834    if (type==EDistributionType::BANDS) // Bands distribution to send to file server
1835    {
1836      int nbServer = client->serverSize;
1837      std::vector<int> nGlobDomain(2);
1838      nGlobDomain[0] = this->ni_glo;
1839      nGlobDomain[1] = this->nj_glo;
1840
1841      // to be changed in future, need to rewrite more simply domain distribution
1842      CServerDistributionDescription serverDescription(nGlobDomain, nbServer);
1843      int distributedPosition ;
1844      if (isUnstructed_) distributedPosition = 0 ;
1845      else distributedPosition = 1 ;
1846     
1847      std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
1848      std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
1849      vector<unordered_map<size_t,vector<int>>> indexServerOnElement ;
1850      CArray<int,1> axisDomainOrder(1) ; axisDomainOrder(0)=2 ;
1851      auto zeroIndex=serverDescription.computeServerGlobalByElement(indexServerOnElement, context->getIntraCommRank(), context->getIntraCommSize(),
1852                                                                  axisDomainOrder,distributedPosition) ;
1853      // distribution is very bad => to redo
1854      // convert indexServerOnElement => map<int,CArray<size_t,1>> - need to be changed later
1855      map<int, vector<size_t>> vectGlobalIndex ;
1856      for(auto& indexRanks : indexServerOnElement[0])
1857      {
1858        size_t index=indexRanks.first ;
1859        auto& ranks=indexRanks.second ;
1860        for(int rank : ranks) vectGlobalIndex[rank].push_back(index) ;
1861      }
1862      for(auto& vect : vectGlobalIndex ) globalIndex.emplace(vect.first, CArray<size_t,1>(vect.second.data(), shape(vect.second.size()),duplicateData)) ;
1863    // some servers receves no index (zeroIndex array) => root process take them into account.
1864      if (context->getIntraCommRank()==0) 
1865        for(auto& rank : zeroIndex) globalIndex[rank] = CArray<size_t,1>() ; 
1866    }
1867    else if (type==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain
1868    {
1869      int nbServer = client->serverSize;
1870      int nglo=ni_glo*nj_glo ;
1871      CArray<size_t,1> indGlo ;
1872      for(size_t i=0;i<nglo;i++) indGlo(i) = i ;
1873      for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer] = indGlo ; 
1874    }
1875    remoteElement_[client] = new CDistributedElement(ni_glo*nj_glo, globalIndex) ;
1876    remoteElement_[client]->addFullView() ;
1877  }
1878  CATCH
1879
1880 
1881
1882  void CDomain::distributeToServer(CContextClient* client, map<int, CArray<size_t,1>>& globalIndex,
1883                                   CScattererConnector* &scattererConnector, const string& domainId)
1884  TRY
1885  {
1886    string serverDomainId = domainId.empty() ? this->getId() : domainId ;
1887    CContext* context = CContext::getCurrent();
1888
1889    this->sendAllAttributesToServer(client, serverDomainId)  ;
1890
1891    CDistributedElement scatteredElement(ni_glo*nj_glo, globalIndex) ;
1892    scatteredElement.addFullView() ;
1893    scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 
1894                                           context->getIntraComm(), client->getRemoteSize()) ;
1895    scattererConnector->computeConnector() ;
1896
1897    // phase 0
1898    // send remote element to construct the full view on server, ie without hole
1899    CEventClient event0(getType(), EVENT_ID_DOMAIN_DISTRIBUTION);
1900    CMessage message0 ;
1901    message0<<serverDomainId<<0 ; 
1902    remoteElement_[client]->sendToServer(client,event0,message0) ; 
1903   
1904    // phase 1
1905    // send the full view of element to construct the connector which connect distributed data coming from client to the full local view
1906    CEventClient event1(getType(), EVENT_ID_DOMAIN_DISTRIBUTION);
1907    CMessage message1 ;
1908    message1<<serverDomainId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 
1909    scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
1910   
1911    sendDistributedAttributes(client, *scattererConnector, domainId) ;
1912
1913 
1914    // phase 2 send the mask : data index + mask2D
1915    CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize());
1916    CArray<bool,1> maskOut ;
1917    CLocalConnector workflowToFull(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ;
1918    workflowToFull.computeConnector() ;
1919    maskIn=true ;
1920    workflowToFull.transfer(maskIn,maskOut,false) ;
1921
1922
1923    // phase 3 : prepare grid scatterer connector to send data from client to server
1924    map<int,CArray<size_t,1>> workflowGlobalIndex ;
1925    map<int,CArray<bool,1>> maskOut2 ; 
1926    scattererConnector->transfer(maskOut, maskOut2, false) ;
1927    scatteredElement.addView(CElementView::WORKFLOW, maskOut2) ;
1928    scatteredElement.getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ;
1929    // create new workflow view for scattered element
1930    CDistributedElement clientToServerElement(scatteredElement.getGlobalSize(), workflowGlobalIndex) ;
1931    clientToServerElement.addFullView() ;
1932    CEventClient event2(getType(), EVENT_ID_DOMAIN_DISTRIBUTION);
1933    CMessage message2 ;
1934    message2<<serverDomainId<<2 ; 
1935    clientToServerElement.sendToServer(client, event2, message2) ; 
1936    clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL),
1937                                                               context->getIntraComm(), client->getRemoteSize()) ;
1938    clientToServerConnector_[client]->computeConnector() ;
1939
1940    clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW));
1941    clientFromServerConnector_[client]->computeConnector() ;
1942
1943  }
1944  CATCH
1945 
1946  void CDomain::recvDomainDistribution(CEventServer& event)
1947  TRY
1948  {
1949    string domainId;
1950    int phasis ;
1951    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> domainId >> phasis ;
1952    get(domainId)->receivedDomainDistribution(event, phasis);
1953  }
1954  CATCH
1955
1956  void CDomain::receivedDomainDistribution(CEventServer& event, int phasis)
1957  TRY
1958  {
1959    CContext* context = CContext::getCurrent();
1960    if (phasis==0) // receive the remote element to construct the full view
1961    {
1962      localElement_ = new  CLocalElement(context->getIntraCommRank(),event) ;
1963      localElement_->addFullView() ;
1964      // construct the local dimension and indexes
1965      auto& globalIndex=localElement_->getGlobalIndex() ;
1966      int nij=globalIndex.numElements() ;
1967      int minI=ni_glo,maxI=-1,minJ=nj_glo,maxJ=-1 ;
1968      int i,j ;
1969      int niGlo=ni_glo, njGlo=njGlo ;
1970      for(int ij=0;ij<nij;ij++)
1971      {
1972        j=globalIndex(ij)/niGlo ;
1973        i=globalIndex(ij)%niGlo ;
1974        if (i<minI) minI=i ;
1975        if (i>maxI) maxI=i ;
1976        if (j<minJ) minJ=j ;
1977        if (j>maxJ) maxJ=j ;
1978      } 
1979      if (maxI>=minI) { ibegin=minI ; ni=maxI-minI+1 ; }
1980      else {ibegin=0; ni=0 ;}
1981      if (maxJ>=minJ) { jbegin=minJ ; nj=maxJ-minJ+1 ; }
1982      else {jbegin=0; nj=0 ;}
1983
1984    }
1985    else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server
1986    {
1987      CContext* context = CContext::getCurrent();
1988      CDistributedElement* elementFrom = new  CDistributedElement(event) ;
1989      elementFrom->addFullView() ;
1990      gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
1991      gathererConnector_->computeConnector() ; 
1992    }
1993    else if (phasis==2)
1994    {
1995//      delete gathererConnector_ ;
1996      elementFrom_ = new  CDistributedElement(event) ;
1997      elementFrom_->addFullView() ;
1998//      gathererConnector_ =  new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
1999//      gathererConnector_ -> computeConnector() ;
2000    }
2001  }
2002  CATCH
2003
2004  void CDomain::setServerMask(CArray<bool,1>& serverMask, CContextClient* client)
2005  TRY
2006  {
2007    // nota : the client is needed to get the remote size for the scatterer connector. Maybe it is not the good place for this
2008    // Later, server to client connector can be computed on demand, with "client" as argument
2009    CContext* context = CContext::getCurrent();
2010    localElement_->addView(CElementView::WORKFLOW, serverMask) ;
2011    mask_1d.reference(serverMask.copy()) ;
2012 
2013    serverFromClientConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ;
2014    serverFromClientConnector_->computeConnector() ;
2015     
2016    serverToClientConnector_ = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL),
2017                                                       context->getIntraComm(), client->getRemoteSize()) ;
2018    serverToClientConnector_->computeConnector() ;
2019  }
2020  CATCH_DUMP_ATTR
2021
2022
2023  void CDomain::sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector,  const string& domainId)
2024  {
2025    string serverDomainId = domainId.empty() ? this->getId() : domainId ;
2026    CContext* context = CContext::getCurrent();
2027
2028    if (hasLonLat)
2029    {
2030      { // send longitude
2031        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
2032        CMessage message ;
2033        message<<serverDomainId<<string("lon") ; 
2034        scattererConnector.transfer(lonvalue, client, event,message) ;
2035      }
2036     
2037      { // send latitude
2038        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
2039        CMessage message ;
2040        message<<serverDomainId<<string("lat") ; 
2041        scattererConnector.transfer(latvalue, client, event, message) ;
2042      }
2043    }
2044
2045    if (hasBounds)
2046    { 
2047      { // send longitude boudaries
2048        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
2049        CMessage message ;
2050        message<<serverDomainId<<string("boundslon") ; 
2051        scattererConnector.transfer(nvertex, bounds_lonvalue, client, event, message ) ;
2052      }
2053
2054      { // send latitude boudaries
2055        CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
2056        CMessage message ;
2057        message<<serverDomainId<<string("boundslat") ; 
2058        scattererConnector.transfer(nvertex, bounds_latvalue, client, event, message ) ;
2059      }
2060    }
2061
2062    if (hasArea)
2063    {  // send area
2064      CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE);
2065      CMessage message ;
2066      message<<serverDomainId<<string("area") ; 
2067      scattererConnector.transfer(areavalue, client, event,message) ;
2068    }
2069  }
2070
2071  void CDomain::recvDistributedAttributes(CEventServer& event)
2072  TRY
2073  {
2074    string domainId;
2075    string type ;
2076    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> domainId >> type ;
2077    get(domainId)->recvDistributedAttributes(event, type);
2078  }
2079  CATCH
2080
2081  void CDomain::recvDistributedAttributes(CEventServer& event, const string& type)
2082  TRY
2083  {
2084    if (type=="lon") 
2085    {
2086      CArray<double,1> value ;
2087      gathererConnector_->transfer(event, value, 0.); 
2088      lonvalue_2d.resize(ni,nj) ;
2089      if (lonvalue_2d.numElements()>0) lonvalue_2d=CArray<double,2>(value.dataFirst(),shape(ni,nj),neverDeleteData) ; 
2090    }
2091    else if (type=="lat")
2092    {
2093      CArray<double,1> value ;
2094      gathererConnector_->transfer(event, value, 0.); 
2095      latvalue_2d.resize(ni,nj) ;
2096      if (latvalue_2d.numElements()>0) latvalue_2d=CArray<double,2>(value.dataFirst(),shape(ni,nj),neverDeleteData) ; 
2097    }
2098    else if (type=="boundslon")
2099    {
2100      CArray<double,1> value ;
2101      gathererConnector_->transfer(event, nvertex, value, 0.); 
2102      bounds_lon_2d.resize(nvertex,ni,nj) ;
2103      if (bounds_lon_2d.numElements()>0) bounds_lon_2d=CArray<double,3>(value.dataFirst(),shape(nvertex,ni,nj),neverDeleteData) ; 
2104    }
2105    else if (type=="boundslat")
2106    {
2107      CArray<double,1> value ;
2108      gathererConnector_->transfer(event, nvertex, value, 0.); 
2109      bounds_lat_2d.resize(nvertex,ni,nj) ;
2110      if (bounds_lat_2d.numElements()>0) bounds_lat_2d=CArray<double,3>(value.dataFirst(),shape(nvertex,ni,nj),neverDeleteData) ; 
2111    }
2112    else if (type=="area") 
2113    {
2114      CArray<double,1> value ;
2115      gathererConnector_->transfer(event, value, 0.); 
2116      area.resize(ni,nj) ;
2117      if (area.numElements()>0) area=CArray<double,2>(value.dataFirst(),shape(ni,nj),neverDeleteData) ; 
2118    }
2119  }
2120  CATCH
2121   
2122  bool CDomain::dispatchEvent(CEventServer& event)
2123  TRY
2124  {
2125    if (SuperClass::dispatchEvent(event)) return true;
2126    else
2127    {
2128      switch(event.type)
2129      {
2130        case EVENT_ID_DOMAIN_DISTRIBUTION:
2131          recvDomainDistribution(event);
2132          return true;
2133          break;
2134        case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE:
2135          recvDistributedAttributes(event);
2136          return true;
2137          break; 
2138        default:
2139          ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
2140                << "Unknown Event");
2141          return false;
2142       }
2143    }
2144  }
2145  CATCH
2146
2147 
2148  /*!
2149    Compare two domain objects.
2150    They are equal if only if they have identical attributes as well as their values.
2151    Moreover, they must have the same transformations.
2152  \param [in] domain Compared domain
2153  \return result of the comparison
2154  */
2155  bool CDomain::isEqual(CDomain* obj)
2156  TRY
2157  {
2158    vector<StdString> excludedAttr;
2159    excludedAttr.push_back("domain_ref");
2160    bool objEqual = SuperClass::isEqual(obj, excludedAttr);
2161    if (!objEqual) return objEqual;
2162
2163    TransMapTypes thisTrans = this->getAllTransformations();
2164    TransMapTypes objTrans  = obj->getAllTransformations();
2165
2166    TransMapTypes::const_iterator it, itb, ite;
2167    std::vector<ETranformationType> thisTransType, objTransType;
2168    for (it = thisTrans.begin(); it != thisTrans.end(); ++it)
2169      thisTransType.push_back(it->first);
2170    for (it = objTrans.begin(); it != objTrans.end(); ++it)
2171      objTransType.push_back(it->first);
2172
2173    if (thisTransType.size() != objTransType.size()) return false;
2174    for (int idx = 0; idx < thisTransType.size(); ++idx)
2175      objEqual &= (thisTransType[idx] == objTransType[idx]);
2176
2177    return objEqual;
2178  }
2179  CATCH_DUMP_ATTR
2180
2181 
2182  CTransformation<CDomain>* CDomain::addTransformation(ETranformationType transType, const StdString& id)
2183  TRY
2184  {
2185    transformationMap_.push_back(std::make_pair(transType, CTransformation<CDomain>::createTransformation(transType,id)));
2186    return transformationMap_.back().second;
2187  }
2188  CATCH_DUMP_ATTR
2189
2190  /*!
2191    Check whether a domain has transformation
2192    \return true if domain has transformation
2193  */
2194  bool CDomain::hasTransformation()
2195  TRY
2196  {
2197    return (!transformationMap_.empty());
2198  }
2199  CATCH_DUMP_ATTR
2200
2201  /*!
2202    Set transformation for current domain. It's the method to move transformation in hierarchy
2203    \param [in] domTrans transformation on domain
2204  */
2205  void CDomain::setTransformations(const TransMapTypes& domTrans)
2206  TRY
2207  {
2208    transformationMap_ = domTrans;
2209  }
2210  CATCH_DUMP_ATTR
2211
2212  /*!
2213    Get all transformation current domain has
2214    \return all transformation
2215  */
2216  CDomain::TransMapTypes CDomain::getAllTransformations(void)
2217  TRY
2218  {
2219    return transformationMap_;
2220  }
2221  CATCH_DUMP_ATTR
2222
2223  void CDomain::duplicateTransformation(CDomain* src)
2224  TRY
2225  {
2226    if (src->hasTransformation())
2227    {
2228      this->setTransformations(src->getAllTransformations());
2229    }
2230  }
2231  CATCH_DUMP_ATTR
2232   
2233  /*!
2234   * Go through the hierarchy to find the domain from which the transformations must be inherited
2235   */
2236  void CDomain::solveInheritanceTransformation()
2237  TRY
2238  {
2239    if (hasTransformation() || !hasDirectDomainReference())
2240      return;
2241
2242    CDomain* domain = this;
2243    std::vector<CDomain*> refDomains;
2244    while (!domain->hasTransformation() && domain->hasDirectDomainReference())
2245    {
2246      refDomains.push_back(domain);
2247      domain = domain->getDirectDomainReference();
2248    }
2249
2250    if (domain->hasTransformation())
2251      for (size_t i = 0; i < refDomains.size(); ++i)
2252        refDomains[i]->setTransformations(domain->getAllTransformations());
2253  }
2254  CATCH_DUMP_ATTR
2255
2256  void CDomain::setContextClient(CContextClient* contextClient)
2257  TRY
2258  {
2259    if (clientsSet.find(contextClient)==clientsSet.end())
2260    {
2261      clients.push_back(contextClient) ;
2262      clientsSet.insert(contextClient);
2263    }
2264  }
2265  CATCH_DUMP_ATTR
2266
2267  /*!
2268    Parse children nodes of a domain in xml file.
2269    Whenver there is a new transformation, its type and name should be added into this function
2270    \param node child node to process
2271  */
2272  void CDomain::parse(xml::CXMLNode & node)
2273  TRY
2274  {
2275    SuperClass::parse(node);
2276
2277    if (node.goToChildElement())
2278    {
2279      StdString nodeElementName;
2280      do
2281      {
2282        StdString nodeId("");
2283        if (node.getAttributes().end() != node.getAttributes().find("id"))
2284        { nodeId = node.getAttributes()["id"]; }
2285
2286        nodeElementName = node.getElementName();
2287        std::map<StdString, ETranformationType>::const_iterator ite = transformationMapList_.end(), it;
2288        it = transformationMapList_.find(nodeElementName);
2289        if (ite != it)
2290        {
2291          transformationMap_.push_back(std::make_pair(it->second, CTransformation<CDomain>::createTransformation(it->second,
2292                                                                                                                nodeId,
2293                                                                                                                &node)));
2294        }
2295        else
2296        {
2297          ERROR("void CDomain::parse(xml::CXMLNode & node)",
2298                << "The transformation " << nodeElementName << " has not been supported yet.");
2299        }
2300      } while (node.goToNextElement()) ;
2301      node.goToParentElement();
2302    }
2303  }
2304  CATCH_DUMP_ATTR
2305   //----------------------------------------------------------------
2306
2307   DEFINE_REF_FUNC(Domain,domain)
2308
2309   ///---------------------------------------------------------------
2310
2311} // namespace xios
Note: See TracBrowser for help on using the repository browser.