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

Last change on this file since 2150 was 2125, checked in by ymipsl, 3 years ago

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