source: XIOS/dev/dev_olga/src/io/nc4_data_output.cpp @ 1130

Last change on this file since 1130 was 1130, checked in by oabramkina, 7 years ago

Two-level server: merging new grid functionalities and changes in the communication protocol (e.g. non-blocking context finalize, registries, oasis).

Tests on curie: test_client, test_complete, nemo (test_xios2_cmip6.exe).

To do: non-structured grid, check reading, possible bug in client/server initialization (?).

  • 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: 125.5 KB
Line 
1#include "nc4_data_output.hpp"
2
3#include <boost/lexical_cast.hpp>
4#include "attribute_template.hpp"
5#include "group_template.hpp"
6
7#include "file.hpp"
8#include "calendar.hpp"
9#include "context.hpp"
10#include "context_server.hpp"
11#include "netCdfException.hpp"
12#include "exception.hpp"
13
14namespace xios
15{
16      /// ////////////////////// Dfinitions ////////////////////// ///
17      CNc4DataOutput::CNc4DataOutput
18         (const StdString & filename, bool exist)
19            : SuperClass()
20            , SuperClassWriter(filename, exist)
21            , filename(filename)
22      {
23    SuperClass::type = MULTI_FILE;
24      }
25
26      CNc4DataOutput::CNc4DataOutput
27         (const StdString & filename, bool exist, bool useClassicFormat, bool useCFConvention,
28          MPI_Comm comm_file, bool multifile, bool isCollective, const StdString& timeCounterName)
29            : SuperClass()
30            , SuperClassWriter(filename, exist, useClassicFormat, useCFConvention, &comm_file, multifile, timeCounterName)
31            , comm_file(comm_file)
32            , filename(filename)
33            , isCollective(isCollective)
34      {
35    SuperClass::type = (multifile) ? MULTI_FILE : ONE_FILE;
36      }
37
38      CNc4DataOutput::~CNc4DataOutput(void)
39    { /* Ne rien faire de plus */ }
40
41      ///--------------------------------------------------------------
42
43      const StdString & CNc4DataOutput::getFileName(void) const
44      {
45         return (this->filename);
46      }
47
48      //---------------------------------------------------------------
49
50      void CNc4DataOutput::writeDomain_(CDomain* domain)
51      {
52        domain->computeWrittenIndex();
53        if (domain->type == CDomain::type_attr::unstructured)
54        {
55          if (SuperClassWriter::useCFConvention)
56            writeUnstructuredDomain(domain) ;
57          else
58            writeUnstructuredDomainUgrid(domain) ;
59          return ;
60        }
61
62       
63         CContext* context = CContext::getCurrent() ;
64         CContextServer* server=context->server ;
65
66         if (domain->IsWritten(this->filename)) return;
67         domain->checkAttributes();
68
69         if (domain->isEmpty())
70           if (SuperClass::type==MULTI_FILE) return;
71
72         std::vector<StdString> dim0, dim1;
73         StdString domid = domain->getDomainOutputName();
74         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
75         if (isWrittenDomain(domid)) return ;
76         else setWrittenDomain(domid);
77
78        // const std::vector<int>& local_size_write  = domain->getLocalWriteSize();
79        // const std::vector<int>& global_size_write = domain->getGlobalWriteSize();
80        // const std::vector<int>& start_write = domain->getStartWriteIndex();
81        // const std::vector<int>& count_write = domain->getCountWriteIndex();
82        int nvertex = (domain->nvertex.isEmpty()) ? 0 : domain->nvertex;
83
84         StdString dimXid, dimYid ;
85
86         bool isRegularDomain = (domain->type == CDomain::type_attr::rectilinear);
87         switch (domain->type)
88         {
89           case CDomain::type_attr::curvilinear :
90             dimXid     = StdString("x").append(appendDomid);
91             dimYid     = StdString("y").append(appendDomid);
92             break ;
93           case CDomain::type_attr::rectilinear :
94             dimXid     = StdString("lon").append(appendDomid);
95             dimYid     = StdString("lat").append(appendDomid);
96             break;
97         }
98
99         StdString dimVertId = StdString("nvertex").append(appendDomid);
100
101         string lonid,latid,bounds_lonid,bounds_latid ;
102         string areaId = "area" + appendDomid;
103/*
104         StdString lonid_loc = (server->intraCommSize > 1)
105                             ? StdString("lon").append(appendDomid).append("_local")
106                             : lonid;
107         StdString latid_loc = (server->intraCommSize > 1)
108                             ? StdString("lat").append(appendDomid).append("_local")
109                             : latid;
110*/
111
112         CArray<size_t, 1>& indexToWrite = domain->localIndexToWriteOnServer;
113         int nbWritten = indexToWrite.numElements();
114         CArray<double,1> writtenLat, writtenLon;
115         CArray<double,2> writtenBndsLat, writtenBndsLon;
116         CArray<double,1> writtenArea;
117
118         if (domain->hasLonLat)
119         {
120           writtenLat.resize(nbWritten);
121           writtenLon.resize(nbWritten);
122           for (int idx = 0; idx < nbWritten; ++idx)
123           {
124              writtenLat(idx) = domain->latvalue(indexToWrite(idx));
125              writtenLon(idx) = domain->lonvalue(indexToWrite(idx));
126           }
127         
128
129           if (domain->hasBounds)
130           {         
131             int nvertex = domain->nvertex, idx;
132             writtenBndsLat.resize(nvertex, nbWritten);
133             writtenBndsLon.resize(nvertex, nbWritten);
134             CArray<double,2>& boundslat = domain->bounds_latvalue;
135             CArray<double,2>& boundslon = domain->bounds_lonvalue;   
136             for (idx = 0; idx < nbWritten; ++idx)
137               for (int nv = 0; nv < nvertex; ++nv)
138               {
139                 writtenBndsLat(nv, idx) = boundslat(nv, int(indexToWrite(idx)));
140                 writtenBndsLon(nv, idx) = boundslon(nv, int(indexToWrite(idx)));
141               }
142           }
143         }
144
145         if (domain->hasArea)
146         {
147           writtenArea.resize(nbWritten);           
148           for (int idx = 0; idx < nbWritten; ++idx)
149           {
150              writtenArea(idx) = domain->areavalue(indexToWrite(idx));                     
151           }
152         }
153
154         try
155         {
156           switch (SuperClass::type)
157           {
158              case (MULTI_FILE) :
159              {
160  //               if (domain->isEmpty()) return;
161
162                 if (server->intraCommSize > 1)
163                 {
164  //                 SuperClassWriter::addDimension(lonid, domain->zoom_ni.getValue());
165  //                 SuperClassWriter::addDimension(latid, domain->zoom_nj.getValue());
166                 }
167
168                 switch (domain->type)
169                 {
170                   case CDomain::type_attr::curvilinear :
171                     dim0.push_back(dimYid); dim0.push_back(dimXid);
172                     lonid = StdString("nav_lon").append(appendDomid);
173                     latid = StdString("nav_lat").append(appendDomid);
174                     break ;
175                   case CDomain::type_attr::rectilinear :
176                     lonid = StdString("lon").append(appendDomid);
177                     latid = StdString("lat").append(appendDomid);
178                     dim0.push_back(dimYid);
179                     dim1.push_back(dimXid);
180                     break;
181                 }
182
183                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
184                 bounds_latid = StdString("bounds_lat").append(appendDomid);
185
186                 SuperClassWriter::addDimension(dimXid, domain->zoom_ni);
187                 SuperClassWriter::addDimension(dimYid, domain->zoom_nj);
188
189                 if (domain->hasBounds)
190                   SuperClassWriter::addDimension(dimVertId, domain->nvertex);
191
192                 if (server->intraCommSize > 1)
193                 {
194                   this->writeLocalAttributes(domain->zoom_ibegin,
195                                              domain->zoom_ni,
196                                              domain->zoom_jbegin,
197                                              domain->zoom_nj,
198                                              appendDomid);
199
200                   if (singleDomain)
201                    this->writeLocalAttributes_IOIPSL(dimXid, dimYid,
202                                                      domain->zoom_ibegin,
203                                                      domain->zoom_ni,
204                                                      domain->zoom_jbegin,
205                                                      domain->zoom_nj,
206                                                      domain->ni_glo,domain->nj_glo,
207                                                      server->intraCommRank,server->intraCommSize);
208                 }
209
210                 if (domain->hasLonLat)
211                 {
212                   switch (domain->type)
213                   {
214                     case CDomain::type_attr::curvilinear :
215                       SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
216                       SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
217                       break ;
218                      case CDomain::type_attr::rectilinear :
219                        SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
220                        SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
221                        break ;
222                   }
223
224                   this->writeAxisAttributes(lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
225                   this->writeAxisAttributes(latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
226
227                   if (domain->hasBounds)
228                   {
229                     SuperClassWriter::addAttribute("bounds", bounds_lonid, &lonid);
230                     SuperClassWriter::addAttribute("bounds", bounds_latid, &latid);
231
232                     dim0.clear();
233                     dim0.push_back(dimYid);
234                     dim0.push_back(dimXid);
235                     dim0.push_back(dimVertId);
236                     SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
237                     SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
238                   }
239                 }
240
241                 dim0.clear();
242                 dim0.push_back(dimYid);
243                 dim0.push_back(dimXid);
244
245
246  // supress mask               if (server->intraCommSize > 1)
247  // supress mask               {
248  // supress mask                  SuperClassWriter::addVariable(maskid, NC_INT, dim0);
249  // supress mask
250  // supress mask                  this->writeMaskAttributes(maskid,
251  // supress mask                     domain->data_dim.getValue()/*,
252  // supress mask                     domain->data_ni.getValue(),
253  // supress mask                     domain->data_nj.getValue(),
254  // supress mask                     domain->data_ibegin.getValue(),
255  // supress mask                     domain->data_jbegin.getValue()*/);
256  // supress mask               }
257
258                 //SuperClassWriter::setDefaultValue(maskid, &dvm);
259
260                 if (domain->hasArea)
261                 {
262                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
263                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
264                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
265                 }
266
267                 SuperClassWriter::definition_end();
268
269                 if (domain->hasLonLat)
270                 {
271                   // CArray<size_t, 1>& indexToWrite = domain->localIndexToWriteOnServer;
272                   // int nbWritten = indexToWrite.numElements();
273                   // CArray<double,1> writtenLat(nbWritten), writtenLon(nbWritten);
274                   // for (int idx = 0; idx < nbWritten; ++idx)
275                   // {
276                   //    writtenLat(idx) = domain->latvalue(indexToWrite(idx));
277                   //    writtenLon(idx) = domain->lonvalue(indexToWrite(idx));
278                   // }
279                   switch (domain->type)
280                   {
281                     case CDomain::type_attr::curvilinear :                       
282                       
283                       // SuperClassWriter::writeData(domain->latvalue, latid, isCollective, 0);
284                       // SuperClassWriter::writeData(domain->lonvalue, lonid, isCollective, 0);
285                       SuperClassWriter::writeData(writtenLat, latid, isCollective, 0);
286                       SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0);
287                       break;
288                     case CDomain::type_attr::rectilinear :
289//                        CArray<double,1> lat = domain->latvalue(Range(fromStart,toEnd,domain->zoom_ni)) ;
290//                        SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0);
291//                        CArray<double,1> lon = domain->lonvalue(Range(0,domain->zoom_ni-1)) ;
292// //                       CArray<double,1> lon = domain->lonvalue(Range(0,local_size_write[1]-1)) ;
293//                        SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0);
294
295                       CArray<double,1> lat = writtenLat(Range(fromStart,toEnd,domain->zoom_ni)) ;
296                       SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0);
297                       CArray<double,1> lon = writtenLon(Range(0,domain->zoom_ni-1)) ;
298//                       CArray<double,1> lon = domain->lonvalue(Range(0,local_size_write[1]-1)) ;
299                       SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0);
300                       break;
301                   }
302
303                   if (domain->hasBounds)
304                   {
305                     // CArray<double,2> writtenBndsLat(nbWritten,2), writtenBndsLon(nbWritten,2);
306                     // for (int idx = 0; idx < nbWritten; ++idx)
307                     //   for (int nv = 0; nv < domain->nvertex; ++nv)
308                     //   {
309                     //     writtenBndsLat(idx) = domain->bounds_latvalue(nv, indexToWrite(idx));
310                     //     writtenBndsLon(idx) = domain->bounds_lonvalue(nv, indexToWrite(idx));
311                     //   }
312
313                     // SuperClassWriter::writeData(domain->bounds_lonvalue, bounds_lonid, isCollective, 0);
314                     // SuperClassWriter::writeData(domain->bounds_latvalue, bounds_latid, isCollective, 0);
315                     SuperClassWriter::writeData(writtenBndsLon, bounds_lonid, isCollective, 0);
316                     SuperClassWriter::writeData(writtenBndsLat, bounds_latid, isCollective, 0);
317                   }
318                 }
319
320                 if (domain->hasArea)
321                 {
322                   // CArray<size_t, 1>& indexToWrite = domain->localIndexToWriteOnServer;
323                   // int nbWritten = indexToWrite.numElements();
324                   // CArray<double,1> writtenArea(nbWritten);
325                   // for (int idx = 0; idx < nbWritten; ++idx)
326                   // {
327                   //    writtenArea(idx) = domain->areavalue(indexToWrite(idx));                     
328                   // }
329
330                   SuperClassWriter::writeData(writtenArea, areaId, isCollective, 0);
331                   // SuperClassWriter::writeData(domain->areavalue, areaId, isCollective, 0);
332                 }
333
334                 SuperClassWriter::definition_start();
335
336                 break;
337              }
338              case (ONE_FILE) :
339              {
340                 SuperClassWriter::addDimension(dimXid, domain->global_zoom_ni);
341                 SuperClassWriter::addDimension(dimYid, domain->global_zoom_nj);
342
343                 if (domain->hasBounds)
344                   SuperClassWriter::addDimension(dimVertId, domain->nvertex);
345
346                 if (domain->hasLonLat)
347                 {
348                   switch (domain->type)
349                   {
350                     case CDomain::type_attr::curvilinear :
351                       dim0.push_back(dimYid); dim0.push_back(dimXid);
352                       lonid = StdString("nav_lon").append(appendDomid);
353                       latid = StdString("nav_lat").append(appendDomid);
354                       SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
355                       SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
356                       break;
357
358                     case CDomain::type_attr::rectilinear :
359                       dim0.push_back(dimYid);
360                       dim1.push_back(dimXid);
361                       lonid = StdString("lon").append(appendDomid);
362                       latid = StdString("lat").append(appendDomid);
363                       SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
364                       SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
365                       break;
366                   }
367
368                   bounds_lonid = StdString("bounds_lon").append(appendDomid);
369                   bounds_latid = StdString("bounds_lat").append(appendDomid);
370
371                   this->writeAxisAttributes
372                      (lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
373                   this->writeAxisAttributes
374                      (latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
375
376                   if (domain->hasBounds)
377                   {
378                     SuperClassWriter::addAttribute("bounds", bounds_lonid, &lonid);
379                     SuperClassWriter::addAttribute("bounds", bounds_latid, &latid);
380
381                     dim0.clear();
382                     dim0.push_back(dimYid);
383                     dim0.push_back(dimXid);
384                     dim0.push_back(dimVertId);
385                     SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
386                     SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
387                   }
388                 }
389
390                 if (domain->hasArea)
391                 {
392                   dim0.clear();
393                   dim0.push_back(dimYid); dim0.push_back(dimXid);
394                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
395                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
396                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
397                   dim0.clear();
398                 }
399
400                 SuperClassWriter::definition_end();
401
402                 switch (domain->type)
403                 {
404                   case CDomain::type_attr::curvilinear :
405                   {
406                     std::vector<StdSize> start(2) ;
407                     std::vector<StdSize> count(2) ;
408                     if (domain->isEmpty())
409                     {
410                       start[0]=0 ; start[1]=0 ;
411                       count[0]=0 ; count[1]=0 ;
412                     }
413                     else
414                     {
415                       start[1]=domain->zoom_ibegin-domain->global_zoom_ibegin;
416                       start[0]=domain->zoom_jbegin-domain->global_zoom_jbegin;
417                       count[1]=domain->zoom_ni ; count[0]=domain->zoom_nj ;
418                     }
419
420                     if (domain->hasLonLat)
421                     {
422                       // SuperClassWriter::writeData(domain->latvalue, latid, isCollective, 0,&start,&count);
423                       // SuperClassWriter::writeData(domain->lonvalue, lonid, isCollective, 0,&start,&count);
424                       SuperClassWriter::writeData(writtenLat, latid, isCollective, 0,&start,&count);
425                       SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0,&start,&count);
426                     }
427                     break;
428                   }
429                   case CDomain::type_attr::rectilinear :
430                   {
431                     if (domain->hasLonLat)
432                     {
433                       std::vector<StdSize> start(1) ;
434                       std::vector<StdSize> count(1) ;
435                       if (domain->isEmpty())
436                       {
437                         start[0]=0 ;
438                         count[0]=0 ;
439                         // SuperClassWriter::writeData(domain->latvalue, latid, isCollective, 0,&start,&count);
440                         // SuperClassWriter::writeData(domain->lonvalue, lonid, isCollective, 0,&start,&count);
441
442                         SuperClassWriter::writeData(writtenLat, latid, isCollective, 0,&start,&count);
443                         SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0,&start,&count);
444                       }
445                       else
446                       { 
447                         start[0]=domain->zoom_jbegin-domain->global_zoom_jbegin;
448                         count[0]=domain->zoom_nj;
449                         // CArray<double,1> lat = domain->latvalue(Range(fromStart,toEnd,domain->zoom_ni));
450                         CArray<double,1> lat = writtenLat(Range(fromStart,toEnd,domain->zoom_ni));
451                         SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0,&start,&count);
452
453                         start[0]=domain->zoom_ibegin-domain->global_zoom_ibegin;
454                         count[0]=domain->zoom_ni;
455                         // CArray<double,1> lon=domain->lonvalue(Range(0,domain->zoom_ni-1));
456                         CArray<double,1> lon = writtenLon(Range(0,domain->zoom_ni-1));
457                         SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0,&start,&count);
458                       }
459                     }
460                     break;
461                   }
462                 }
463
464                 if (domain->hasBounds)
465                 {
466                   std::vector<StdSize> start(3);
467                   std::vector<StdSize> count(3);
468                   if (domain->isEmpty())
469                   {
470                     start[2] = start[1] = start[0] = 0;
471                     count[2] = count[1] = count[0] = 0;
472                   }
473                   else
474                   {
475                     start[2] = 0;
476                     start[1] = domain->zoom_ibegin - domain->global_zoom_ibegin;
477                     start[0] = domain->zoom_jbegin - domain->global_zoom_jbegin;
478                     count[2] = domain->nvertex;
479                     count[1] = domain->zoom_ni;
480                     count[0] = domain->zoom_nj;
481                   }
482
483                 // SuperClassWriter::writeData(domain->bounds_lonvalue, bounds_lonid, isCollective, 0, &start, &count);
484                 // SuperClassWriter::writeData(domain->bounds_latvalue, bounds_latid, isCollective, 0, &start, &count);
485                   SuperClassWriter::writeData(writtenBndsLon, bounds_lonid, isCollective, 0, &start, &count);
486                   SuperClassWriter::writeData(writtenBndsLat, bounds_latid, isCollective, 0, &start, &count);
487                 }
488
489                 if (domain->hasArea)
490                 {
491                   std::vector<StdSize> start(2);
492                   std::vector<StdSize> count(2);
493
494                   if (domain->isEmpty())
495                   {
496                     start[0] = 0; start[1] = 0;
497                     count[0] = 0; count[1] = 0;
498                   }
499                   else
500                   {
501                     start[1] = domain->zoom_ibegin - domain->global_zoom_ibegin;
502                     start[0] = domain->zoom_jbegin - domain->global_zoom_jbegin;
503                     count[1] = domain->zoom_ni;
504                     count[0] = domain->zoom_nj;
505                   }
506
507                   // SuperClassWriter::writeData(domain->areavalue, areaId, isCollective, 0, &start, &count);
508                   SuperClassWriter::writeData(writtenArea, areaId, isCollective, 0, &start, &count);
509                 }
510
511                 SuperClassWriter::definition_start();
512                 break;
513              }
514              default :
515                 ERROR("CNc4DataOutput::writeDomain(domain)",
516                       << "[ type = " << SuperClass::type << "]"
517                       << " not implemented yet !");
518           }
519         }
520         catch (CNetCdfException& e)
521         {
522           StdString msg("On writing the domain : ");
523           msg.append(domid); msg.append("\n");
524           msg.append("In the context : ");
525           msg.append(context->getId()); msg.append("\n");
526           msg.append(e.what());
527           ERROR("CNc4DataOutput::writeDomain_(CDomain* domain)", << msg);
528         }
529
530         domain->addRelFile(this->filename);
531      }
532
533    //--------------------------------------------------------------
534
535    void CNc4DataOutput::writeUnstructuredDomainUgrid(CDomain* domain)
536    {
537      CContext* context = CContext::getCurrent() ;
538      CContextServer* server=context->server ;
539
540      if (domain->IsWritten(this->filename)) return;
541      domain->checkAttributes();
542      if (domain->isEmpty())
543        if (SuperClass::type==MULTI_FILE) return ;
544
545      std::vector<StdString> dim0;
546      StdString domid = domain->getDomainOutputName();
547      StdString domainName = domain->name;
548      domain->assignMesh(domainName, domain->nvertex);
549      domain->mesh->createMeshEpsilon(server->intraComm, domain->lonvalue, domain->latvalue, domain->bounds_lonvalue, domain->bounds_latvalue);
550
551      StdString node_x = domainName + "_node_x";
552      StdString node_y = domainName + "_node_y";
553
554      StdString edge_x = domainName + "_edge_x";
555      StdString edge_y = domainName + "_edge_y";
556      StdString edge_nodes = domainName + "_edge_nodes";
557
558      StdString face_x = domainName + "_face_x";
559      StdString face_y = domainName + "_face_y";
560      StdString face_nodes = domainName + "_face_nodes";
561      StdString face_edges = domainName + "_face_edges";
562      StdString edge_faces = domainName + "_edge_face_links";
563      StdString face_faces = domainName + "_face_links";
564
565      StdString dimNode = "n" + domainName + "_node";
566      StdString dimEdge = "n" + domainName + "_edge";
567      StdString dimFace = "n" + domainName + "_face";
568      StdString dimVertex = "n" + domainName + "_vertex";
569      StdString dimTwo = "Two";
570
571      const std::vector<int>& local_size_write  = domain->getLocalWriteSize();
572      const std::vector<int>& global_size_write = domain->getGlobalWriteSize();
573      const std::vector<int>& start_write = domain->getStartWriteIndex();
574      const std::vector<int>& count_write = domain->getCountWriteIndex();
575
576      if (!SuperClassWriter::dimExist(dimTwo)) SuperClassWriter::addDimension(dimTwo, 2);
577      if (!isWrittenDomain(domid))
578      {
579        dim0.clear();
580        SuperClassWriter::addVariable(domainName, NC_INT, dim0);
581        SuperClassWriter::addAttribute("cf_role", StdString("mesh_topology"), &domainName);
582        SuperClassWriter::addAttribute("long_name", StdString("Topology data of 2D unstructured mesh"), &domainName);
583        SuperClassWriter::addAttribute("topology_dimension", 2, &domainName);
584        SuperClassWriter::addAttribute("node_coordinates", node_x + " " + node_y, &domainName);
585      }
586
587      try
588      {
589        switch (SuperClass::type)
590        {
591          case (ONE_FILE) :
592          {
593            // Adding nodes
594            if (domain->nvertex == 1)
595            {
596              if (!SuperClassWriter::varExist(node_x) || !SuperClassWriter::varExist(node_y))
597              {
598                SuperClassWriter::addDimension(dimNode, domain->ni_glo);
599                dim0.clear();
600                dim0.push_back(dimNode);
601                SuperClassWriter::addVariable(node_x, NC_FLOAT, dim0);
602                SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x);
603                SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x);
604                SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x);
605                SuperClassWriter::addVariable(node_y, NC_FLOAT, dim0);
606                SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y);
607                SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y);
608                SuperClassWriter::addAttribute("units", StdString("degrees_north"), &node_y);
609              }
610            } // domain->nvertex == 1
611
612            // Adding edges and nodes, if nodes have not been defined previously
613            if (domain->nvertex == 2)
614            {
615              if (!SuperClassWriter::varExist(node_x) || !SuperClassWriter::varExist(node_y))
616              {
617                SuperClassWriter::addDimension(dimNode, domain->mesh->nbNodesGlo);
618                dim0.clear();
619                dim0.push_back(dimNode);
620                SuperClassWriter::addVariable(node_x, NC_FLOAT, dim0);
621                SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x);
622                SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x);
623                SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x);
624                SuperClassWriter::addVariable(node_y, NC_FLOAT, dim0);
625                SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y);
626                SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y);
627                SuperClassWriter::addAttribute("units", StdString("degrees_north"), &node_y);
628              }
629              SuperClassWriter::addAttribute("edge_node_connectivity", edge_nodes, &domainName);
630              SuperClassWriter::addAttribute("edge_coordinates", edge_x + " " + edge_y, &domainName);
631              SuperClassWriter::addDimension(dimEdge, domain->ni_glo);
632              dim0.clear();
633              dim0.push_back(dimEdge);
634              SuperClassWriter::addVariable(edge_x, NC_FLOAT, dim0);
635              SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &edge_x);
636              SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh edges."), &edge_x);
637              SuperClassWriter::addAttribute("units", StdString("degrees_east"), &edge_x);
638              SuperClassWriter::addVariable(edge_y, NC_FLOAT, dim0);
639              SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &edge_y);
640              SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh edges."), &edge_y);
641              SuperClassWriter::addAttribute("units", StdString("degrees_north"), &edge_y);
642              dim0.clear();
643              dim0.push_back(dimEdge);
644              dim0.push_back(dimTwo);
645              SuperClassWriter::addVariable(edge_nodes, NC_INT, dim0);
646              SuperClassWriter::addAttribute("cf_role", StdString("edge_node_connectivity"), &edge_nodes);
647              SuperClassWriter::addAttribute("long_name", StdString("Maps every edge/link to two nodes that it connects."), &edge_nodes);
648              SuperClassWriter::addAttribute("start_index", 0, &edge_nodes);
649            } // domain->nvertex == 2
650
651            // Adding faces, edges, and nodes, if edges and nodes have not been defined previously
652            if (domain->nvertex > 2)
653            {
654              // Nodes
655              if (!SuperClassWriter::varExist(node_x) || !SuperClassWriter::varExist(node_y))
656              {
657                SuperClassWriter::addDimension(dimNode, domain->mesh->nbNodesGlo);
658                dim0.clear();
659                dim0.push_back(dimNode);
660                SuperClassWriter::addVariable(node_x, NC_FLOAT, dim0);
661                SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x);
662                SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x);
663                SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x);
664                SuperClassWriter::addVariable(node_y, NC_FLOAT, dim0);
665                SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y);
666                SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y);
667                SuperClassWriter::addAttribute("units", StdString("degrees_north"), &node_y);
668              }
669              if (!SuperClassWriter::varExist(edge_x) || !SuperClassWriter::varExist(edge_y))
670              {
671                SuperClassWriter::addAttribute("edge_coordinates", edge_x + " " + edge_y, &domainName);
672                SuperClassWriter::addAttribute("edge_node_connectivity", edge_nodes, &domainName);
673                SuperClassWriter::addDimension(dimEdge, domain->mesh->nbEdgesGlo);
674                dim0.clear();
675                dim0.push_back(dimEdge);
676                SuperClassWriter::addVariable(edge_x, NC_FLOAT, dim0);
677                SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &edge_x);
678                SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh edges."), &edge_x);
679                SuperClassWriter::addAttribute("units", StdString("degrees_east"), &edge_x);
680                SuperClassWriter::addVariable(edge_y, NC_FLOAT, dim0);
681                SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &edge_y);
682                SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh edges."), &edge_y);
683                SuperClassWriter::addAttribute("units", StdString("degrees_north"), &edge_y);
684                dim0.clear();
685                dim0.push_back(dimEdge);
686                dim0.push_back(dimTwo);
687                SuperClassWriter::addVariable(edge_nodes, NC_INT, dim0);
688                SuperClassWriter::addAttribute("cf_role", StdString("edge_node_connectivity"), &edge_nodes);
689                SuperClassWriter::addAttribute("long_name", StdString("Maps every edge/link to two nodes that it connects."), &edge_nodes);
690                SuperClassWriter::addAttribute("start_index", 0, &edge_nodes);
691              }
692              SuperClassWriter::addAttribute("face_coordinates", face_x + " " + face_y, &domainName);
693              SuperClassWriter::addAttribute("face_node_connectivity", face_nodes, &domainName);
694              SuperClassWriter::addDimension(dimFace, domain->ni_glo);
695              SuperClassWriter::addDimension(dimVertex, domain->nvertex);
696              dim0.clear();
697              dim0.push_back(dimFace);
698              SuperClassWriter::addVariable(face_x, NC_FLOAT, dim0);
699              SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &face_x);
700              SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh faces."), &face_x);
701              SuperClassWriter::addAttribute("units", StdString("degrees_east"), &face_x);
702              SuperClassWriter::addVariable(face_y, NC_FLOAT, dim0);
703              SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &face_y);
704              SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh faces."), &face_y);
705              SuperClassWriter::addAttribute("units", StdString("degrees_north"), &face_y);
706              dim0.clear();
707              dim0.push_back(dimFace);
708              dim0.push_back(dimVertex);
709              SuperClassWriter::addVariable(face_nodes, NC_INT, dim0);
710              SuperClassWriter::addAttribute("cf_role", StdString("face_node_connectivity"), &face_nodes);
711              SuperClassWriter::addAttribute("long_name", StdString("Maps every face to its corner nodes."), &face_nodes);
712              SuperClassWriter::addAttribute("start_index", 0, &face_nodes);
713              dim0.clear();
714              dim0.push_back(dimFace);
715              dim0.push_back(dimVertex);
716              SuperClassWriter::addVariable(face_edges, NC_INT, dim0);
717              SuperClassWriter::addAttribute("cf_role", StdString("face_edge_connectivity"), &face_edges);
718              SuperClassWriter::addAttribute("long_name", StdString("Maps every face to its edges."), &face_edges);
719              SuperClassWriter::addAttribute("start_index", 0, &face_edges);
720              SuperClassWriter::addAttribute("_FillValue", 999999, &face_edges);
721              dim0.clear();
722              dim0.push_back(dimEdge);
723              dim0.push_back(dimTwo);
724              SuperClassWriter::addVariable(edge_faces, NC_INT, dim0);
725              SuperClassWriter::addAttribute("cf_role", StdString("edge_face connectivity"), &edge_faces);
726              SuperClassWriter::addAttribute("long_name", StdString("neighbor faces for edges"), &edge_faces);
727              SuperClassWriter::addAttribute("start_index", 0, &edge_faces);
728              SuperClassWriter::addAttribute("_FillValue", -999, &edge_faces);
729              SuperClassWriter::addAttribute("comment", StdString("missing neighbor faces are indicated using _FillValue"), &edge_faces);
730              dim0.clear();
731              dim0.push_back(dimFace);
732              dim0.push_back(dimVertex);
733              SuperClassWriter::addVariable(face_faces, NC_INT, dim0);
734              SuperClassWriter::addAttribute("cf_role", StdString("face_face connectivity"), &face_faces);
735              SuperClassWriter::addAttribute("long_name", StdString("Indicates which other faces neighbor each face"), &face_faces);
736              SuperClassWriter::addAttribute("start_index", 0, &face_faces);
737              SuperClassWriter::addAttribute("_FillValue", 999999, &face_faces);
738              SuperClassWriter::addAttribute("flag_values", -1, &face_faces);
739              SuperClassWriter::addAttribute("flag_meanings", StdString("out_of_mesh"), &face_faces);
740            } // domain->nvertex > 2
741
742            SuperClassWriter::definition_end();
743
744            std::vector<StdSize> startEdges(1) ;
745            std::vector<StdSize> countEdges(1) ;
746            std::vector<StdSize> startNodes(1) ;
747            std::vector<StdSize> countNodes(1) ;
748            std::vector<StdSize> startFaces(1) ;
749            std::vector<StdSize> countFaces(1) ;
750            std::vector<StdSize> startEdgeNodes(2) ;
751            std::vector<StdSize> countEdgeNodes(2) ;
752            std::vector<StdSize> startEdgeFaces(2) ;
753            std::vector<StdSize> countEdgeFaces(2) ;
754            std::vector<StdSize> startFaceConctv(2) ;
755            std::vector<StdSize> countFaceConctv(2) ;
756
757            if (!isWrittenDomain(domid))
758            {
759              if (domain->nvertex == 1)
760              {
761                if (domain->isEmpty())
762                 {
763                   startNodes[0]=0 ;
764                   countNodes[0]=0 ;
765                 }
766                 else
767                 {
768                   startNodes[0] = start_write[0]; //domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
769                   countNodes[0] = count_write[0]; //domain->zoom_ni_srv ;
770                 }
771
772                SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0, &startNodes, &countNodes);
773                SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0, &startNodes, &countNodes);
774              }
775              else if (domain->nvertex == 2)
776              {
777                if (domain->isEmpty())
778                 {
779                  startEdges[0]=0 ;
780                  countEdges[0]=0 ;
781                  startNodes[0]=0 ;
782                  countNodes[0]=0 ;
783                  startEdgeNodes[0]=0;
784                  startEdgeNodes[1]=0;
785                  countEdgeNodes[0]=0;
786                  countEdgeNodes[1]=0;
787
788                 }
789                 else
790                 {
791                   startEdges[0] = start_write[0]; //domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
792                   countEdges[0] = count_write[0];
793                   startNodes[0] = domain->mesh->node_start;
794                   countNodes[0] = domain->mesh->node_count;
795                   startEdgeNodes[0] = start_write[0]; //domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
796                   startEdgeNodes[1] = 0;
797                   countEdgeNodes[0] = count_write[0]; //domain->zoom_ni_srv;
798                   countEdgeNodes[1]= 2;
799                 }
800                SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0, &startNodes, &countNodes);
801                SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0, &startNodes, &countNodes);
802                SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0, &startEdges, &countEdges);
803                SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0, &startEdges, &countEdges);
804                SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes, isCollective, 0, &startEdgeNodes, &countEdgeNodes);
805              }
806              else
807              {
808                if (domain->isEmpty())
809                 {
810                   startFaces[0] = 0 ;
811                   countFaces[0] = 0 ;
812                   startNodes[0] = 0;
813                   countNodes[0] = 0;
814                   startEdges[0] = 0;
815                   countEdges[0] = 0;
816                   startEdgeFaces[0] = 0;
817                   startEdgeFaces[1] = 0;
818                   countEdgeFaces[0] = 0;
819                   countEdgeFaces[1] = 0;
820                   startFaceConctv[0] = 0;
821                   startFaceConctv[1] = 0;
822                   countFaceConctv[0] = 0;
823                   countFaceConctv[1] = 0;
824                 }
825                 else
826                 {
827                   startFaces[0] = start_write[0]; //domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
828                   countFaces[0] = count_write[0]; //domain->zoom_ni_srv ;
829                   startNodes[0] = domain->mesh->node_start;
830                   countNodes[0] = domain->mesh->node_count;
831                   startEdges[0] = domain->mesh->edge_start;
832                   countEdges[0] = domain->mesh->edge_count;
833                   startEdgeNodes[0] = domain->mesh->edge_start;
834                   startEdgeNodes[1] = 0;
835                   countEdgeNodes[0] = domain->mesh->edge_count;
836                   countEdgeNodes[1]= 2;
837                   startEdgeFaces[0] = domain->mesh->edge_start;
838                   startEdgeFaces[1]= 0;
839                   countEdgeFaces[0] = domain->mesh->edge_count;
840                   countEdgeFaces[1]= 2;
841                   startFaceConctv[0] = start_write[0]; //domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
842                   startFaceConctv[1] = 0; //0;
843                   countFaceConctv[0] = count_write[0]; //domain->zoom_ni_srv;
844                   countFaceConctv[1] = domain->nvertex;
845                 }
846                SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0, &startNodes, &countNodes);
847                SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0, &startNodes, &countNodes);
848                SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0, &startEdges, &countEdges);
849                SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0, &startEdges, &countEdges);
850                SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes, isCollective, 0, &startEdgeNodes, &countEdgeNodes);
851                SuperClassWriter::writeData(domain->mesh->face_lat, face_y, isCollective, 0, &startFaces, &countFaces);
852                SuperClassWriter::writeData(domain->mesh->face_lon, face_x, isCollective, 0, &startFaces, &countFaces);
853                SuperClassWriter::writeData(domain->mesh->face_nodes, face_nodes, isCollective, 0, &startFaceConctv, &countFaceConctv);
854                SuperClassWriter::writeData(domain->mesh->face_edges, face_edges, isCollective, 0, &startFaceConctv, &countFaceConctv);
855                SuperClassWriter::writeData(domain->mesh->edge_faces, edge_faces, isCollective, 0, &startEdgeFaces, &countEdgeFaces);
856                SuperClassWriter::writeData(domain->mesh->face_faces, face_faces, isCollective, 0, &startFaceConctv, &countFaceConctv);
857              }
858              setWrittenDomain(domid);
859            } // !isWrittenDomain
860            else
861            {
862              if (domain->nvertex == 2)
863              {
864                startEdges[0] = start_write[0]; //domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
865                countEdges[0] = count_write[0]; //domain->zoom_ni_srv ;
866                startEdgeNodes[0] = start_write[0]; //domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
867                startEdgeNodes[1] = 0; //0;
868                countEdgeNodes[0] = count_write[0]; //domain->zoom_ni_srv;
869                countEdgeNodes[1]= 2;
870                SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0, &startEdges, &countEdges);
871                SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0, &startEdges, &countEdges);
872                SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes, isCollective, 0, &startEdgeNodes, &countEdgeNodes);
873              } 
874              if (domain->nvertex > 2)
875              {
876
877                if (!domain->mesh->edgesAreWritten)
878                {
879                  startEdges[0] = domain->mesh->edge_start;
880                  countEdges[0] = domain->mesh->edge_count;
881                  startEdgeNodes[0] = domain->mesh->edge_start;
882                  startEdgeNodes[1] = 0;
883                  countEdgeNodes[0] = domain->mesh->edge_count;
884                  countEdgeNodes[1]= 2;
885                  SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0, &startEdges, &countEdges);
886                  SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0, &startEdges, &countEdges);
887                  SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes, isCollective, 0, &startEdgeNodes, &countEdgeNodes);
888                }
889                startFaces[0] = start_write[0]; //domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
890                countFaces[0] = count_write[0]; //domain->zoom_ni_srv;
891                startEdgeFaces[0] = domain->mesh->edge_start;
892                startEdgeFaces[1]= 0;
893                countEdgeFaces[0] = domain->mesh->edge_count;
894                countEdgeFaces[1]= 2;
895                startFaceConctv[0] = start_write[0]; //domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
896                startFaceConctv[1] = 0; //0;
897                countFaceConctv[0] = count_write[0]; //domain->zoom_ni_srv;
898                countFaceConctv[1]= domain->nvertex;
899                SuperClassWriter::writeData(domain->mesh->face_lat, face_y, isCollective, 0, &startFaces, &countFaces);
900                SuperClassWriter::writeData(domain->mesh->face_lon, face_x, isCollective, 0, &startFaces, &countFaces);
901                SuperClassWriter::writeData(domain->mesh->face_nodes, face_nodes, isCollective, 0, &startFaceConctv, &countFaceConctv);
902                SuperClassWriter::writeData(domain->mesh->face_edges, face_edges, isCollective, 0, &startFaceConctv, &countFaceConctv);
903                SuperClassWriter::writeData(domain->mesh->edge_faces, edge_faces, isCollective, 0, &startEdgeFaces, &countEdgeFaces);
904                SuperClassWriter::writeData(domain->mesh->face_faces, face_faces, isCollective, 0, &startFaceConctv, &countFaceConctv);
905              }
906            }// isWrittenDomain
907
908            SuperClassWriter::definition_start();
909
910            break;
911          } // ONE_FILE
912
913          case (MULTI_FILE) :
914          {
915            break;
916          }
917
918          default :
919          ERROR("CNc4DataOutput::writeDomain(domain)",
920          << "[ type = " << SuperClass::type << "]"
921          << " not implemented yet !");
922          } // switch
923        } // try
924
925        catch (CNetCdfException& e)
926        {
927          StdString msg("On writing the domain : ");
928          msg.append(domid); msg.append("\n");
929          msg.append("In the context : ");
930          msg.append(context->getId()); msg.append("\n");
931          msg.append(e.what());
932          ERROR("CNc4DataOutput::writeUnstructuredDomainUgrid(CDomain* domain)", << msg);
933        }
934
935  domain->addRelFile(this->filename);
936  }
937
938    //--------------------------------------------------------------
939
940    void CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)
941      {
942         CContext* context = CContext::getCurrent() ;
943         CContextServer* server=context->server ;
944
945         if (domain->IsWritten(this->filename)) return;
946         domain->checkAttributes();
947
948         if (domain->isEmpty())
949           if (SuperClass::type==MULTI_FILE) return ;
950
951         std::vector<StdString> dim0, dim1;
952         StdString domid = domain->getDomainOutputName();
953         if (isWrittenDomain(domid)) return ;
954         else setWrittenDomain(domid);
955
956         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
957
958         StdString dimXid = StdString("cell").append(appendDomid);
959         StdString dimVertId = StdString("nvertex").append(appendDomid);
960
961         string lonid,latid,bounds_lonid,bounds_latid ;
962         string areaId = "area" + appendDomid;
963
964        const std::vector<int>& local_size_write  = domain->getLocalWriteSize();
965        const std::vector<int>& global_size_write = domain->getGlobalWriteSize();
966        const std::vector<int>& start_write = domain->getStartWriteIndex();
967        const std::vector<int>& count_write = domain->getCountWriteIndex();
968        int nvertex = (domain->nvertex.isEmpty()) ? 0 : domain->nvertex;
969
970         try
971         {
972           switch (SuperClass::type)
973           {
974              case (MULTI_FILE) :
975              {
976                 dim0.push_back(dimXid);
977                 SuperClassWriter::addDimension(dimXid, local_size_write[0]);
978
979                 lonid = StdString("lon").append(appendDomid);
980                 latid = StdString("lat").append(appendDomid);
981                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
982                 bounds_latid = StdString("bounds_lat").append(appendDomid);
983                 if (domain->hasLonLat)
984                 {
985                   SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
986                   SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
987                   this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid);
988                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
989                   this->writeAxisAttributes(latid, "", "latitude", "Latitude", "degrees_north", domid);
990                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
991                   if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
992                 }
993                 dim0.clear();
994                 if (domain->hasBounds)
995                 {
996                   dim0.push_back(dimXid);
997                   dim0.push_back(dimVertId);
998                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
999                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
1000                 }
1001
1002                 dim0.clear();
1003                 dim0.push_back(dimXid);
1004                 if (domain->hasArea)
1005                 {
1006                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
1007                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
1008                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
1009                 }
1010
1011                 SuperClassWriter::definition_end();
1012
1013                 if (domain->hasLonLat)
1014                 {
1015                   SuperClassWriter::writeData(domain->latvalue, latid, isCollective, 0);
1016                   SuperClassWriter::writeData(domain->lonvalue, lonid, isCollective, 0);
1017                   if (domain->hasBounds)
1018                   {
1019                     SuperClassWriter::writeData(domain->bounds_lonvalue, bounds_lonid, isCollective, 0);
1020                     SuperClassWriter::writeData(domain->bounds_latvalue, bounds_latid, isCollective, 0);
1021                   }
1022                 }
1023
1024                 if (domain->hasArea)
1025                   SuperClassWriter::writeData(domain->areavalue, areaId, isCollective, 0);
1026
1027                 SuperClassWriter::definition_start();
1028                 break ;
1029              }
1030
1031              case (ONE_FILE) :
1032              {
1033                 lonid = StdString("lon").append(appendDomid);
1034                 latid = StdString("lat").append(appendDomid);
1035                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
1036                 bounds_latid = StdString("bounds_lat").append(appendDomid);
1037                 dim0.push_back(dimXid);
1038                 SuperClassWriter::addDimension(dimXid, global_size_write[0]);
1039                 if (domain->hasLonLat)
1040                 {
1041                   SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
1042                   SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
1043
1044                   this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid);
1045                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
1046                   this->writeAxisAttributes(latid, "", "latitude", "Latitude", "degrees_north", domid);
1047                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
1048                   if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, nvertex);
1049                 }
1050                 dim0.clear();
1051
1052                 if (domain->hasBounds)
1053                 {
1054                   dim0.push_back(dimXid);
1055                   dim0.push_back(dimVertId);
1056                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
1057                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
1058                 }
1059
1060                 if (domain->hasArea)
1061                 {
1062                   dim0.clear();
1063                   dim0.push_back(dimXid);
1064                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
1065                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
1066                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
1067                 }
1068
1069                 SuperClassWriter::definition_end();
1070
1071                 std::vector<StdSize> start(1), startBounds(2) ;
1072                 std::vector<StdSize> count(1), countBounds(2) ;
1073                 if (domain->isEmpty())
1074                 {
1075                   start[0]=0 ;
1076                   count[0]=0 ;
1077                   startBounds[1]=0 ;
1078                   countBounds[1]=nvertex ;
1079                   startBounds[0]=0 ;
1080                   countBounds[0]=0 ;
1081                 }
1082                 else
1083                 {
1084                   start[0]=start_write[0];
1085                   count[0]=count_write[0];
1086                   startBounds[0]=start_write[0];
1087                   startBounds[1]=0 ;
1088                   countBounds[0]=count_write[0];
1089                   countBounds[1]=nvertex ;
1090                 }
1091
1092                 if (domain->hasLonLat)
1093                 {
1094                   SuperClassWriter::writeData(domain->latvalue, latid, isCollective, 0,&start,&count);
1095                   SuperClassWriter::writeData(domain->lonvalue, lonid, isCollective, 0,&start,&count);
1096                   if (domain->hasBounds)
1097                   {
1098                     SuperClassWriter::writeData(domain->bounds_lonvalue, bounds_lonid, isCollective, 0,&startBounds,&countBounds);
1099                     SuperClassWriter::writeData(domain->bounds_latvalue, bounds_latid, isCollective, 0,&startBounds,&countBounds);
1100                   }
1101                 }
1102
1103                 if (domain->hasArea)
1104                   SuperClassWriter::writeData(domain->areavalue, areaId, isCollective, 0, &start, &count);
1105
1106                 SuperClassWriter::definition_start();
1107
1108                 break;
1109              }
1110              default :
1111                 ERROR("CNc4DataOutput::writeDomain(domain)",
1112                       << "[ type = " << SuperClass::type << "]"
1113                       << " not implemented yet !");
1114           }
1115         }
1116         catch (CNetCdfException& e)
1117         {
1118           StdString msg("On writing the domain : ");
1119           msg.append(domid); msg.append("\n");
1120           msg.append("In the context : ");
1121           msg.append(context->getId()); msg.append("\n");
1122           msg.append(e.what());
1123           ERROR("CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)", << msg);
1124         }
1125         domain->addRelFile(this->filename);
1126      }
1127      //--------------------------------------------------------------
1128
1129      void CNc4DataOutput::writeAxis_(CAxis* axis)
1130      {
1131        CContext* context = CContext::getCurrent();
1132
1133        if (axis->IsWritten(this->filename)) return;
1134        axis->checkAttributes();
1135
1136        axis->computeWrittenIndex();
1137       
1138        int zoom_size  = (MULTI_FILE == SuperClass::type) ? axis->zoom_n
1139                                                          : axis->global_zoom_n;
1140        int zoom_begin = (MULTI_FILE == SuperClass::type) ? axis->zoom_begin
1141                                                          : axis->global_zoom_begin;
1142
1143        if ((0 == axis->zoom_n) && (MULTI_FILE == SuperClass::type)) return;
1144
1145        std::vector<StdString> dims;
1146        StdString axisid = axis->getAxisOutputName();
1147        if (isWrittenAxis(axisid)) return ;
1148        else setWrittenAxis(axisid);
1149
1150        try
1151        {
1152          SuperClassWriter::addDimension(axisid, zoom_size);
1153          if (axis->hasValue)
1154          {
1155            dims.push_back(axisid);
1156            SuperClassWriter::addVariable(axisid, NC_FLOAT, dims);
1157
1158            if (!axis->name.isEmpty())
1159              SuperClassWriter::addAttribute("name", axis->name.getValue(), &axisid);
1160
1161            if (!axis->standard_name.isEmpty())
1162              SuperClassWriter::addAttribute("standard_name", axis->standard_name.getValue(), &axisid);
1163
1164            if (!axis->long_name.isEmpty())
1165              SuperClassWriter::addAttribute("long_name", axis->long_name.getValue(), &axisid);
1166
1167            if (!axis->unit.isEmpty())
1168              SuperClassWriter::addAttribute("units", axis->unit.getValue(), &axisid);
1169
1170            if (!axis->positive.isEmpty())
1171            {
1172              SuperClassWriter::addAttribute("axis", string("Z"), &axisid);
1173              SuperClassWriter::addAttribute("positive",
1174                                             (axis->positive == CAxis::positive_attr::up) ? string("up") : string("down"),
1175                                             &axisid);
1176            }
1177
1178            StdString axisBoundsId = axisid + "_bounds";
1179            if (!axis->bounds.isEmpty())
1180            {
1181              dims.push_back("axis_nbounds");
1182              SuperClassWriter::addVariable(axisBoundsId, NC_FLOAT, dims);
1183              SuperClassWriter::addAttribute("bounds", axisBoundsId, &axisid);
1184            }
1185
1186            SuperClassWriter::definition_end();
1187
1188            CArray<size_t, 1>& indexToWrite = axis->localIndexToWriteOnServer;
1189            int nbWritten = indexToWrite.numElements();
1190            CArray<double,1> axis_value(indexToWrite.numElements());
1191            for (int i = 0; i < nbWritten; i++) axis_value(i) = axis->value(indexToWrite(i));
1192            CArray<double,2> axis_bounds;
1193
1194            switch (SuperClass::type)
1195            {
1196              case MULTI_FILE:
1197              {
1198                // CArray<double,1> axis_value(axis->zoom_n);
1199                // for (int i = 0; i < axis->zoom_n; i++) axis_value(i) = axis->value(i);
1200                SuperClassWriter::writeData(axis_value, axisid, isCollective, 0);
1201
1202                if (!axis->bounds.isEmpty())
1203                  SuperClassWriter::writeData(axis->bounds, axisBoundsId, isCollective, 0);
1204
1205                SuperClassWriter::definition_start();
1206
1207                break;
1208              }
1209              case ONE_FILE:
1210              {
1211                // CArray<double,1> axis_value(axis->zoom_n);
1212                // axis_value = axis->value;
1213                std::vector<StdSize> start(1), startBounds(2) ;
1214                std::vector<StdSize> count(1), countBounds(2) ;
1215                start[0] = startBounds[0] = zoom_begin - axis->global_zoom_begin;
1216                count[0] = countBounds[0] = zoom_size;
1217                startBounds[1] = 0;
1218                countBounds[1] = 2;
1219                SuperClassWriter::writeData(axis_value, axisid, isCollective, 0, &start, &count);
1220
1221                if (!axis->bounds.isEmpty())
1222                {
1223                  axis_bounds.resize(2, indexToWrite.numElements());
1224                  for (int i = 0; i < nbWritten; ++i)
1225                  {
1226                    axis_bounds(0, i) = axis->bounds(0, int(indexToWrite(i)));
1227                    axis_bounds(1, i) = axis->bounds(1, int(indexToWrite(i)));
1228                  }
1229                  SuperClassWriter::writeData(axis->bounds, axisBoundsId, isCollective, 0, &startBounds, &countBounds);
1230                }
1231
1232                SuperClassWriter::definition_start();
1233
1234                break;
1235              }
1236              default :
1237                ERROR("CNc4DataOutput::writeAxis_(CAxis* axis)",
1238                      << "[ type = " << SuperClass::type << "]"
1239                      << " not implemented yet !");
1240            }
1241          }
1242        }
1243        catch (CNetCdfException& e)
1244        {
1245          StdString msg("On writing the axis : ");
1246          msg.append(axisid); msg.append("\n");
1247          msg.append("In the context : ");
1248          CContext* context = CContext::getCurrent() ;
1249          msg.append(context->getId()); msg.append("\n");
1250          msg.append(e.what());
1251          ERROR("CNc4DataOutput::writeAxis_(CAxis* axis)", << msg);
1252        }
1253     
1254      axis->addRelFile(this->filename);
1255     }
1256
1257      void CNc4DataOutput::writeScalar_(CScalar* scalar)
1258      {
1259        if (scalar->IsWritten(this->filename)) return;
1260        scalar->checkAttributes();
1261        int scalarSize = 1;
1262
1263        StdString scalaId = scalar->getScalarOutputName();
1264        if (isWrittenAxis(scalaId)) return ;
1265        else setWrittenAxis(scalaId);
1266
1267        try
1268        {
1269          if (!scalar->value.isEmpty())
1270          {
1271//            dims.push_back(scalaId);
1272            std::vector<StdString> dims;
1273            SuperClassWriter::addVariable(scalaId, NC_FLOAT, dims);
1274
1275            if (!scalar->name.isEmpty())
1276              SuperClassWriter::addAttribute("name", scalar->name.getValue(), &scalaId);
1277
1278            if (!scalar->standard_name.isEmpty())
1279              SuperClassWriter::addAttribute("standard_name", scalar->standard_name.getValue(), &scalaId);
1280
1281            if (!scalar->long_name.isEmpty())
1282              SuperClassWriter::addAttribute("long_name", scalar->long_name.getValue(), &scalaId);
1283
1284            if (!scalar->unit.isEmpty())
1285              SuperClassWriter::addAttribute("units", scalar->unit.getValue(), &scalaId);
1286
1287            SuperClassWriter::definition_end();
1288
1289            switch (SuperClass::type)
1290            {
1291              case MULTI_FILE:
1292              {
1293                CArray<double,1> scalarValue(scalarSize);
1294                scalarValue(0) = scalar->value;
1295                SuperClassWriter::writeData(scalarValue, scalaId, isCollective, 0);
1296                SuperClassWriter::definition_start();
1297
1298                break;
1299              }
1300              case ONE_FILE:
1301              {
1302                CArray<double,1> scalarValue(scalarSize);
1303                scalarValue(0) = scalar->value;
1304
1305                std::vector<StdSize> start(1);
1306                std::vector<StdSize> count(1);
1307                start[0] = 0;
1308                count[0] = 1;
1309                SuperClassWriter::writeData(scalarValue, scalaId, isCollective, 0, &start, &count);
1310                SuperClassWriter::definition_start();
1311
1312                break;
1313              }
1314              default :
1315                ERROR("CNc4DataOutput::writeAxis_(CAxis* scalar)",
1316                      << "[ type = " << SuperClass::type << "]"
1317                      << " not implemented yet !");
1318            }
1319          }
1320        }
1321        catch (CNetCdfException& e)
1322        {
1323          StdString msg("On writing the scalar : ");
1324          msg.append(scalaId); msg.append("\n");
1325          msg.append("In the context : ");
1326          CContext* context = CContext::getCurrent() ;
1327          msg.append(context->getId()); msg.append("\n");
1328          msg.append(e.what());
1329          ERROR("CNc4DataOutput::writeScalar_(CScalar* scalar)", << msg);
1330        }
1331        scalar->addRelFile(this->filename);
1332     }
1333
1334     //--------------------------------------------------------------
1335
1336     void CNc4DataOutput::writeGridCompressed_(CGrid* grid)
1337     {
1338       if (grid->isScalarGrid() || grid->isWrittenCompressed(this->filename)) return;
1339
1340       try
1341       {
1342         CArray<int,1> axisDomainOrder = grid->axis_domain_order;
1343         std::vector<StdString> domainList = grid->getDomainList();
1344         std::vector<StdString> axisList   = grid->getAxisList();
1345         std::vector<StdString> scalarList = grid->getScalarList();
1346         int numElement = axisDomainOrder.numElements(), idxDomain = 0, idxAxis = 0, idxScalar = 0;
1347
1348         std::vector<StdString> dims;
1349
1350         if (grid->isCompressible())
1351         {
1352           StdString varId = grid->getId() + "_points";
1353
1354           int nbIndexes = (SuperClass::type == MULTI_FILE) ? grid->getNumberWrittenIndexes() : grid->getTotalNumberWrittenIndexes();
1355           SuperClassWriter::addDimension(varId, nbIndexes);
1356
1357           dims.push_back(varId);
1358           SuperClassWriter::addVariable(varId, NC_INT, dims);
1359
1360           StdOStringStream compress;
1361           for (int i = numElement - 1; i >= 0; --i)
1362           {
1363             if (2 == axisDomainOrder(i))
1364             {
1365               CDomain* domain = CDomain::get(domainList[domainList.size() - idxDomain - 1]);
1366               StdString domId = domain->getDomainOutputName();
1367               StdString appendDomId  = singleDomain ? "" : "_" + domId;
1368
1369               switch (domain->type)
1370               {
1371                 case CDomain::type_attr::curvilinear:
1372                   compress << "y" << appendDomId << " x" << appendDomId;
1373                   break;
1374                 case CDomain::type_attr::rectilinear:
1375                   compress << "lat" << appendDomId << " lon" << appendDomId;
1376                   break;
1377                 case CDomain::type_attr::unstructured:
1378                   compress << "cell" << appendDomId;
1379                   break;
1380               }
1381               ++idxDomain;
1382             }
1383             else if (1 == axisDomainOrder(i))
1384             {
1385               CAxis* axis = CAxis::get(axisList[axisList.size() - idxAxis - 1]);
1386               compress << axis->getAxisOutputName();
1387               ++idxAxis;
1388             }
1389             else
1390             {
1391               CScalar* scalar = CScalar::get(scalarList[scalarList.size() - idxScalar - 1]);
1392               compress << scalar->getScalarOutputName();
1393               ++idxScalar;
1394             }
1395
1396             if (i != 0) compress << ' ';
1397           }
1398           SuperClassWriter::addAttribute("compress", compress.str(), &varId);
1399
1400           grid->computeCompressedIndex();
1401
1402           CArray<int, 1> indexes(grid->getNumberWrittenIndexes());
1403           std::map<int, CArray<size_t, 1> >::const_iterator it;
1404           for (it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
1405           {
1406             const CArray<size_t, 1> compressedIndexes = grid->compressedOutIndexFromClient[it->first];
1407             for (int i = 0; i < it->second.numElements(); i++)
1408               indexes(compressedIndexes(i)) = it->second(i);
1409           }
1410
1411           switch (SuperClass::type)
1412           {
1413             case (MULTI_FILE):
1414             {
1415               SuperClassWriter::writeData(indexes, varId, isCollective, 0);
1416               break;
1417             }
1418             case (ONE_FILE):
1419             {
1420               if (grid->doGridHaveDataDistributed())
1421                 grid->getDistributionServer()->computeGlobalIndex(indexes);
1422
1423               std::vector<StdSize> start, count;
1424               start.push_back(grid->getOffsetWrittenIndexes());
1425               count.push_back(grid->getNumberWrittenIndexes());
1426
1427               SuperClassWriter::writeData(indexes, varId, isCollective, 0, &start, &count);
1428               break;
1429             }
1430           }
1431         }
1432         else
1433         {
1434           for (int i = 0; i < numElement; ++i)
1435           {
1436             StdString varId, compress;
1437             CArray<int, 1> indexes;
1438             bool isDistributed;
1439             StdSize nbIndexes, totalNbIndexes, offset;
1440             int firstGlobalIndex;
1441
1442             if (2 == axisDomainOrder(i))
1443             {
1444               CDomain* domain = CDomain::get(domainList[idxDomain]);
1445               StdString domId = domain->getDomainOutputName();
1446
1447               if (!domain->isCompressible()
1448                    || domain->type == CDomain::type_attr::unstructured
1449                    || domain->isWrittenCompressed(this->filename)
1450                    || isWrittenCompressedDomain(domId))
1451                 continue;
1452
1453               StdString appendDomId  = singleDomain ? "" : "_" + domId;
1454
1455               varId = domId + "_points";
1456               switch (domain->type)
1457               {
1458                 case CDomain::type_attr::curvilinear:
1459                   compress = "y" + appendDomId + " x" + appendDomId;
1460                   break;
1461                 case CDomain::type_attr::rectilinear:
1462                   compress = "lat" + appendDomId + " lon" + appendDomId;
1463                   break;
1464               }
1465
1466               const std::vector<int>& indexesToWrite = domain->getIndexesToWrite();
1467               indexes.resize(indexesToWrite.size());
1468               for (int n = 0; n < indexes.numElements(); ++n)
1469                 indexes(n) = indexesToWrite[n];
1470
1471               isDistributed = domain->isDistributed();
1472               nbIndexes = domain->getNumberWrittenIndexes();
1473               totalNbIndexes = domain->getTotalNumberWrittenIndexes();
1474               offset = domain->getOffsetWrittenIndexes();
1475               firstGlobalIndex = domain->ibegin + domain->jbegin * domain->ni_glo;
1476
1477               domain->addRelFileCompressed(this->filename);
1478               setWrittenCompressedDomain(domId);
1479               ++idxDomain;
1480             }
1481             else if (1 == axisDomainOrder(i))
1482             {
1483               CAxis* axis = CAxis::get(axisList[idxAxis]);
1484               StdString axisId = axis->getAxisOutputName();
1485
1486               if (!axis->isCompressible()
1487                    || axis->isWrittenCompressed(this->filename)
1488                    || isWrittenCompressedAxis(axisId))
1489                 continue;
1490
1491               varId = axisId + "_points";
1492               compress = axisId;
1493
1494               const std::vector<int>& indexesToWrite = axis->getIndexesToWrite();
1495               indexes.resize(indexesToWrite.size());
1496               for (int n = 0; n < indexes.numElements(); ++n)
1497                 indexes(n) = indexesToWrite[n];
1498
1499               isDistributed = axis->isDistributed();
1500               nbIndexes = axis->getNumberWrittenIndexes();
1501               totalNbIndexes = axis->getTotalNumberWrittenIndexes();
1502               offset = axis->getOffsetWrittenIndexes();
1503               firstGlobalIndex = axis->begin;
1504
1505               axis->addRelFileCompressed(this->filename);
1506               setWrittenCompressedAxis(axisId);
1507               ++idxAxis;
1508             }
1509             else
1510             {
1511             }
1512
1513             if (!varId.empty())
1514             {
1515               SuperClassWriter::addDimension(varId, (SuperClass::type == MULTI_FILE) ? nbIndexes : totalNbIndexes);
1516
1517               dims.clear();
1518               dims.push_back(varId);
1519               SuperClassWriter::addVariable(varId, NC_INT, dims);
1520
1521               SuperClassWriter::addAttribute("compress", compress, &varId);
1522
1523               switch (SuperClass::type)
1524               {
1525                 case (MULTI_FILE):
1526                 {
1527                   indexes -= firstGlobalIndex;
1528                   SuperClassWriter::writeData(indexes, varId, isCollective, 0);
1529                   break;
1530                 }
1531                 case (ONE_FILE):
1532                 {
1533                   std::vector<StdSize> start, count;
1534                   start.push_back(offset);
1535                   count.push_back(nbIndexes);
1536
1537                   SuperClassWriter::writeData(indexes, varId, isCollective, 0, &start, &count);
1538                   break;
1539                 }
1540               }
1541             }
1542           }
1543
1544           if (!dims.empty())
1545             grid->computeCompressedIndex();
1546         }
1547
1548         grid->addRelFileCompressed(this->filename);
1549       }
1550       catch (CNetCdfException& e)
1551       {
1552         StdString msg("On writing compressed grid : ");
1553         msg.append(grid->getId()); msg.append("\n");
1554         msg.append("In the context : ");
1555         CContext* context = CContext::getCurrent();
1556         msg.append(context->getId()); msg.append("\n");
1557         msg.append(e.what());
1558         ERROR("CNc4DataOutput::writeGridCompressed_(CGrid* grid)", << msg);
1559       }
1560     }
1561
1562     //--------------------------------------------------------------
1563
1564     void CNc4DataOutput::writeTimeDimension_(void)
1565     {
1566       try
1567       {
1568        SuperClassWriter::addDimension(getTimeCounterName());
1569       }
1570       catch (CNetCdfException& e)
1571       {
1572         StdString msg("On writing time dimension : time_couter\n");
1573         msg.append("In the context : ");
1574         CContext* context = CContext::getCurrent() ;
1575         msg.append(context->getId()); msg.append("\n");
1576         msg.append(e.what());
1577         ERROR("CNc4DataOutput::writeTimeDimension_(void)", << msg);
1578       }
1579     }
1580
1581      //--------------------------------------------------------------
1582
1583      void CNc4DataOutput::writeField_(CField* field)
1584      {
1585         CContext* context = CContext::getCurrent() ;
1586         CContextServer* server=context->server ;
1587
1588         std::vector<StdString> dims, coodinates;
1589         CGrid* grid = field->grid;
1590         if (!grid->doGridHaveDataToWrite())
1591          if (SuperClass::type==MULTI_FILE) return ;
1592
1593         CArray<int,1> axisDomainOrder = grid->axis_domain_order;
1594         int numElement = axisDomainOrder.numElements(), idxDomain = 0, idxAxis = 0, idxScalar = 0;
1595         std::vector<StdString> domainList = grid->getDomainList();
1596         std::vector<StdString> axisList   = grid->getAxisList();
1597         std::vector<StdString> scalarList = grid->getScalarList();
1598
1599         StdString timeid  = getTimeCounterName();
1600         StdString dimXid,dimYid;
1601         std::deque<StdString> dimIdList, dimCoordList;
1602         bool hasArea = false;
1603         StdString cellMeasures = "area:";
1604         bool compressedOutput = !field->indexed_output.isEmpty() && field->indexed_output;
1605
1606         for (int i = 0; i < numElement; ++i)
1607         {
1608           if (2 == axisDomainOrder(i))
1609           {
1610             CDomain* domain = CDomain::get(domainList[idxDomain]);
1611             StdString domId = domain->getDomainOutputName();
1612             StdString appendDomId  = singleDomain ? "" : "_" + domId ;
1613
1614             if (compressedOutput && domain->isCompressible() && domain->type != CDomain::type_attr::unstructured)
1615             {
1616               dimIdList.push_back(domId + "_points");
1617               field->setUseCompressedOutput();
1618             }
1619
1620             switch (domain->type)
1621             {
1622               case CDomain::type_attr::curvilinear:
1623                 if (!compressedOutput || !domain->isCompressible())
1624                 {
1625                   dimXid     = StdString("x").append(appendDomId);
1626                   dimIdList.push_back(dimXid);
1627                   dimYid     = StdString("y").append(appendDomId);
1628                   dimIdList.push_back(dimYid);
1629                 }
1630                 dimCoordList.push_back(StdString("nav_lon").append(appendDomId));
1631                 dimCoordList.push_back(StdString("nav_lat").append(appendDomId));
1632                 break ;
1633               case CDomain::type_attr::rectilinear:
1634                 if (!compressedOutput || !domain->isCompressible())
1635                 {
1636                   dimXid     = StdString("lon").append(appendDomId);
1637                   dimIdList.push_back(dimXid);
1638                   dimYid     = StdString("lat").append(appendDomId);
1639                   dimIdList.push_back(dimYid);
1640                 }
1641                 break ;
1642               case CDomain::type_attr::unstructured:
1643               {
1644           if (SuperClassWriter::useCFConvention)
1645           {
1646            dimXid     = StdString("cell").append(appendDomId);
1647            dimIdList.push_back(dimXid);
1648            dimCoordList.push_back(StdString("lon").append(appendDomId));
1649            dimCoordList.push_back(StdString("lat").append(appendDomId));
1650          }
1651           else
1652           {
1653            StdString domainName = domain->name;
1654            if (domain->nvertex == 1)
1655            {
1656              dimXid     = "n" + domainName + "_node";
1657              dimIdList.push_back(dimXid);
1658              dimCoordList.push_back(StdString(domainName + "_node_x"));
1659              dimCoordList.push_back(StdString(domainName + "_node_y"));
1660            }
1661            else if (domain->nvertex == 2)
1662            {
1663              dimXid     = "n" + domainName + "_edge";
1664              dimIdList.push_back(dimXid);
1665              dimCoordList.push_back(StdString(domainName + "_edge_x"));
1666              dimCoordList.push_back(StdString(domainName + "_edge_y"));
1667            }
1668            else
1669            {
1670              dimXid     = "n" + domainName + "_face";
1671              dimIdList.push_back(dimXid);
1672              dimCoordList.push_back(StdString(domainName + "_face_x"));
1673              dimCoordList.push_back(StdString(domainName + "_face_y"));
1674            }
1675          }  // ugrid convention
1676        }  // case unstructured domain
1677             }
1678
1679             if (domain->hasArea)
1680             {
1681               hasArea = true;
1682               cellMeasures += " area" + appendDomId;
1683             }
1684             ++idxDomain;
1685           }
1686           else if (1 == axisDomainOrder(i))
1687           {
1688             CAxis* axis = CAxis::get(axisList[idxAxis]);
1689             StdString axisId = axis->getAxisOutputName();
1690
1691             if (compressedOutput && axis->isCompressible())
1692             {
1693               dimIdList.push_back(axisId + "_points");
1694               field->setUseCompressedOutput();
1695             }
1696             else
1697               dimIdList.push_back(axisId);
1698
1699             dimCoordList.push_back(axisId);
1700             ++idxAxis;
1701           }
1702           else // scalar
1703           {
1704             /* Do nothing here */
1705           }
1706         }
1707
1708/*
1709         StdString lonid_loc = (server->intraCommSize > 1)
1710                             ? StdString("lon").append(appendDomid).append("_local")
1711                             : lonid;
1712         StdString latid_loc = (server->intraCommSize > 1)
1713                             ? StdString("lat").append(appendDomid).append("_local")
1714                             : latid;
1715*/
1716         StdString fieldid = field->getFieldOutputName();
1717
1718         nc_type type ;
1719         if (field->prec.isEmpty()) type =  NC_FLOAT ;
1720         else
1721         {
1722           if (field->prec==2) type = NC_SHORT ;
1723           else if (field->prec==4)  type =  NC_FLOAT ;
1724           else if (field->prec==8)   type =  NC_DOUBLE ;
1725         }
1726
1727         bool wtime   = !(!field->operation.isEmpty() && field->getOperationTimeType() == func::CFunctor::once);
1728
1729         if (wtime)
1730         {
1731
1732            //StdOStringStream oss;
1733           // oss << "time_" << field->operation.getValue()
1734           //     << "_" << field->getRelFile()->output_freq.getValue();
1735          //oss
1736            if (field->getOperationTimeType() == func::CFunctor::instant) coodinates.push_back(string("time_instant"));
1737            else if (field->getOperationTimeType() == func::CFunctor::centered) coodinates.push_back(string("time_centered"));
1738            dims.push_back(timeid);
1739         }
1740
1741         if (compressedOutput && grid->isCompressible())
1742         {
1743           dims.push_back(grid->getId() + "_points");
1744           field->setUseCompressedOutput();
1745         }
1746         else
1747         {
1748           while (!dimIdList.empty())
1749           {
1750             dims.push_back(dimIdList.back());
1751             dimIdList.pop_back();
1752           }
1753         }
1754
1755         while (!dimCoordList.empty())
1756         {
1757           coodinates.push_back(dimCoordList.back());
1758           dimCoordList.pop_back();
1759         }
1760
1761         try
1762         {
1763           SuperClassWriter::addVariable(fieldid, type, dims);
1764
1765           if (!field->standard_name.isEmpty())
1766              SuperClassWriter::addAttribute
1767                 ("standard_name",  field->standard_name.getValue(), &fieldid);
1768
1769           if (!field->long_name.isEmpty())
1770              SuperClassWriter::addAttribute
1771                 ("long_name", field->long_name.getValue(), &fieldid);
1772
1773           if (!field->unit.isEmpty())
1774              SuperClassWriter::addAttribute
1775                 ("units", field->unit.getValue(), &fieldid);
1776
1777            if (!field->valid_min.isEmpty())
1778              SuperClassWriter::addAttribute
1779                 ("valid_min", field->valid_min.getValue(), &fieldid);
1780
1781           if (!field->valid_max.isEmpty())
1782              SuperClassWriter::addAttribute
1783                 ("valid_max", field->valid_max.getValue(), &fieldid);
1784
1785            if (!field->scale_factor.isEmpty())
1786              SuperClassWriter::addAttribute
1787                 ("scale_factor", field->scale_factor.getValue(), &fieldid);
1788
1789             if (!field->add_offset.isEmpty())
1790              SuperClassWriter::addAttribute
1791                 ("add_offset", field->add_offset.getValue(), &fieldid);
1792
1793           SuperClassWriter::addAttribute
1794                 ("online_operation", field->operation.getValue(), &fieldid);
1795
1796          // write child variables as attributes
1797
1798
1799           vector<CVariable*> listVars = field->getAllVariables() ;
1800           for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ;
1801
1802           bool alreadyAddCellMethod = false;
1803           StdString cellMethodsPrefix(""), cellMethodsSuffix("");
1804           if (!field->cell_methods.isEmpty())
1805           {
1806             StdString cellMethodString = field->cell_methods;
1807             if (field->cell_methods_mode.isEmpty() ||
1808                 (CField::cell_methods_mode_attr::overwrite == field->cell_methods_mode))
1809             {
1810               SuperClassWriter::addAttribute("cell_methods", cellMethodString, &fieldid);
1811               alreadyAddCellMethod = true;
1812             }
1813             else
1814             {
1815               switch (field->cell_methods_mode)
1816               {
1817               case (CField::cell_methods_mode_attr::prefix):
1818                 cellMethodsPrefix = cellMethodString;
1819                 cellMethodsPrefix += " ";
1820                 break;
1821               case (CField::cell_methods_mode_attr::suffix):
1822                 cellMethodsSuffix = " ";
1823                 cellMethodsSuffix += cellMethodString;
1824                 break;
1825               case (CField::cell_methods_mode_attr::none):
1826                 break;
1827               default:
1828                 break;
1829               }
1830             }
1831           }
1832
1833
1834           if (wtime)
1835           {
1836              CDuration freqOp = field->freq_op.getValue();
1837              freqOp.solveTimeStep(*context->calendar);
1838              StdString freqOpStr = freqOp.toStringUDUnits();
1839              SuperClassWriter::addAttribute("interval_operation", freqOpStr, &fieldid);
1840
1841              CDuration freqOut = field->getRelFile()->output_freq.getValue();
1842              freqOut.solveTimeStep(*context->calendar);
1843              SuperClassWriter::addAttribute("interval_write", freqOut.toStringUDUnits(), &fieldid);
1844
1845              StdString cellMethods(cellMethodsPrefix + "time: ");
1846              if (field->operation.getValue() == "instant") cellMethods += "point";
1847              else if (field->operation.getValue() == "average") cellMethods += "mean";
1848              else if (field->operation.getValue() == "accumulate") cellMethods += "sum";
1849              else cellMethods += field->operation;
1850              if (freqOp.resolve(*context->calendar) != freqOut.resolve(*context->calendar))
1851                cellMethods += " (interval: " + freqOpStr + ")";
1852              cellMethods += cellMethodsSuffix;
1853              if (!alreadyAddCellMethod)
1854                SuperClassWriter::addAttribute("cell_methods", cellMethods, &fieldid);
1855           }
1856
1857           if (hasArea)
1858             SuperClassWriter::addAttribute("cell_measures", cellMeasures, &fieldid);
1859
1860           if (!field->default_value.isEmpty())
1861           {
1862              double default_value = field->default_value.getValue();
1863              float fdefault_value = (float)default_value;
1864              if (type == NC_DOUBLE)
1865                 SuperClassWriter::setDefaultValue(fieldid, &default_value);
1866              else
1867                 SuperClassWriter::setDefaultValue(fieldid, &fdefault_value);
1868           }
1869           else
1870              SuperClassWriter::setDefaultValue(fieldid, (double*)NULL);
1871
1872            if (field->compression_level.isEmpty())
1873              field->compression_level = field->file->compression_level.isEmpty() ? 0 : field->file->compression_level;
1874            SuperClassWriter::setCompressionLevel(fieldid, field->compression_level);
1875
1876           {  // Ecriture des coordonnes
1877
1878              StdString coordstr; //boost::algorithm::join(coodinates, " ")
1879              std::vector<StdString>::iterator
1880                 itc = coodinates.begin(), endc = coodinates.end();
1881
1882              for (; itc!= endc; itc++)
1883              {
1884                 StdString & coord = *itc;
1885                 if (itc+1 != endc)
1886                       coordstr.append(coord).append(" ");
1887                 else  coordstr.append(coord);
1888              }
1889
1890              SuperClassWriter::addAttribute("coordinates", coordstr, &fieldid);
1891
1892           }
1893         }
1894         catch (CNetCdfException& e)
1895         {
1896           StdString msg("On writing field : ");
1897           msg.append(fieldid); msg.append("\n");
1898           msg.append("In the context : ");
1899           msg.append(context->getId()); msg.append("\n");
1900           msg.append(e.what());
1901           ERROR("CNc4DataOutput::writeField_(CField* field)", << msg);
1902         }
1903      } // writeField_()
1904
1905      //--------------------------------------------------------------
1906
1907      void CNc4DataOutput::writeFile_ (CFile* file)
1908      {
1909         StdString filename = file->getFileOutputName();
1910         StdString description = (!file->description.isEmpty())
1911                               ? file->description.getValue()
1912                               : StdString("Created by xios");
1913
1914         singleDomain = (file->nbDomains == 1);
1915
1916         try
1917         {
1918       if (SuperClassWriter::useCFConvention)
1919             this->writeFileAttributes(filename, description,
1920                                       StdString("CF-1.5"),
1921                                       StdString("An IPSL model"),
1922                                       this->getTimeStamp());
1923           else
1924             this->writeFileAttributes(filename, description,
1925                                       StdString("UGRID"),
1926                                       StdString("An IPSL model"),
1927                                       this->getTimeStamp());
1928
1929
1930           if (!appendMode)
1931             SuperClassWriter::addDimension("axis_nbounds", 2);
1932         }
1933         catch (CNetCdfException& e)
1934         {
1935           StdString msg("On writing file : ");
1936           msg.append(filename); msg.append("\n");
1937           msg.append("In the context : ");
1938           CContext* context = CContext::getCurrent() ;
1939           msg.append(context->getId()); msg.append("\n");
1940           msg.append(e.what());
1941           ERROR("CNc4DataOutput::writeFile_ (CFile* file)", << msg);
1942         }
1943      }
1944
1945      void CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)
1946      {
1947        StdString name = var->getVariableOutputName();
1948
1949        try
1950        {
1951          if (var->type.getValue() == CVariable::type_attr::t_int || var->type.getValue() == CVariable::type_attr::t_int32)
1952            addAttribute(name, var->getData<int>(), &fieldId);
1953          else if (var->type.getValue() == CVariable::type_attr::t_int16)
1954            addAttribute(name, var->getData<short int>(), &fieldId);
1955          else if (var->type.getValue() == CVariable::type_attr::t_float)
1956            addAttribute(name, var->getData<float>(), &fieldId);
1957          else if (var->type.getValue() == CVariable::type_attr::t_double)
1958            addAttribute(name, var->getData<double>(), &fieldId);
1959          else if (var->type.getValue() == CVariable::type_attr::t_string)
1960            addAttribute(name, var->getData<string>(), &fieldId);
1961          else
1962            ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)",
1963                  << "Unsupported variable of type " << var->type.getStringValue());
1964        }
1965       catch (CNetCdfException& e)
1966       {
1967         StdString msg("On writing attributes of variable with name : ");
1968         msg.append(name); msg.append("in the field "); msg.append(fieldId); msg.append("\n");
1969         msg.append("In the context : ");
1970         CContext* context = CContext::getCurrent() ;
1971         msg.append(context->getId()); msg.append("\n");
1972         msg.append(e.what());
1973         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)", << msg);
1974       }
1975     }
1976
1977     void CNc4DataOutput::writeAttribute_ (CVariable* var)
1978     {
1979        StdString name = var->getVariableOutputName();
1980
1981        try
1982        {
1983          if (var->type.getValue() == CVariable::type_attr::t_int || var->type.getValue() == CVariable::type_attr::t_int32)
1984            addAttribute(name, var->getData<int>());
1985          else if (var->type.getValue() == CVariable::type_attr::t_int16)
1986            addAttribute(name, var->getData<short int>());
1987          else if (var->type.getValue() == CVariable::type_attr::t_float)
1988            addAttribute(name, var->getData<float>());
1989          else if (var->type.getValue() == CVariable::type_attr::t_double)
1990            addAttribute(name, var->getData<double>());
1991          else if (var->type.getValue() == CVariable::type_attr::t_string)
1992            addAttribute(name, var->getData<string>());
1993          else
1994            ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)",
1995                  << "Unsupported variable of type " << var->type.getStringValue());
1996        }
1997       catch (CNetCdfException& e)
1998       {
1999         StdString msg("On writing attributes of variable with name : ");
2000         msg.append(name); msg.append("\n");
2001         msg.append("In the context : ");
2002         CContext* context = CContext::getCurrent() ;
2003         msg.append(context->getId()); msg.append("\n");
2004         msg.append(e.what());
2005         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)", << msg);
2006       }
2007     }
2008
2009      void CNc4DataOutput::syncFile_ (void)
2010      {
2011        try
2012        {
2013          SuperClassWriter::sync() ;
2014        }
2015        catch (CNetCdfException& e)
2016        {
2017         StdString msg("On synchronizing the write among processes");
2018         msg.append("In the context : ");
2019         CContext* context = CContext::getCurrent() ;
2020         msg.append(context->getId()); msg.append("\n");
2021         msg.append(e.what());
2022         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
2023        }
2024      }
2025
2026      void CNc4DataOutput::closeFile_ (void)
2027      {
2028        try
2029        {
2030          SuperClassWriter::close() ;
2031        }
2032        catch (CNetCdfException& e)
2033        {
2034         StdString msg("On closing file");
2035         msg.append("In the context : ");
2036         CContext* context = CContext::getCurrent() ;
2037         msg.append(context->getId()); msg.append("\n");
2038         msg.append(e.what());
2039         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
2040        }
2041
2042      }
2043
2044      //---------------------------------------------------------------
2045
2046      StdString CNc4DataOutput::getTimeStamp(void) const
2047      {
2048         const int buffer_size = 100;
2049         time_t rawtime;
2050         struct tm * timeinfo = NULL;
2051         char buffer [buffer_size];
2052
2053         time ( &rawtime );
2054         timeinfo = localtime ( &rawtime );
2055         strftime (buffer, buffer_size, "%Y-%b-%d %H:%M:%S %Z", timeinfo);
2056
2057         return (StdString(buffer));
2058      }
2059
2060      //---------------------------------------------------------------
2061
2062      void CNc4DataOutput::writeFieldData_ (CField*  field)
2063      {
2064        CContext* context = CContext::getCurrent();
2065        CContextServer* server = context->server;
2066        CGrid* grid = field->grid;
2067
2068        if (field->getNStep()<1) return ;
2069       
2070        if (!grid->doGridHaveDataToWrite())
2071          if (SuperClass::type == MULTI_FILE || !isCollective) return;
2072
2073        StdString fieldid = field->getFieldOutputName();
2074
2075        StdOStringStream oss;
2076        string timeAxisId;
2077        if (field->getOperationTimeType() == func::CFunctor::instant) timeAxisId = "time_instant";
2078        else if (field->getOperationTimeType() == func::CFunctor::centered) timeAxisId = "time_centered";
2079
2080        StdString timeBoundId = getTimeCounterName() + "_bounds";
2081
2082        StdString timeAxisBoundId;
2083        if (field->getOperationTimeType() == func::CFunctor::instant) timeAxisBoundId = "time_instant_bounds";
2084        else if (field->getOperationTimeType() == func::CFunctor::centered) timeAxisBoundId = "time_centered_bounds";
2085
2086        if (!field->wasWritten())
2087        {
2088          if (appendMode && field->file->record_offset.isEmpty() &&
2089               field->getOperationTimeType() != func::CFunctor::once)
2090          {
2091            field->resetNStep(getRecordFromTime(field->last_Write_srv) + 1);
2092          }
2093
2094          field->setWritten();
2095        }
2096
2097
2098        CArray<double,1> time_data(1);
2099        CArray<double,1> time_data_bound(2);
2100        CArray<double,1> time_counter(1);
2101        CArray<double,1> time_counter_bound(2);
2102
2103        bool wtime = (field->getOperationTimeType() != func::CFunctor::once);
2104
2105        if (wtime)
2106        {
2107          Time lastWrite = field->last_Write_srv;
2108          Time lastLastWrite = field->lastlast_Write_srv;
2109
2110          if (field->getOperationTimeType() == func::CFunctor::instant)
2111            time_data(0) = lastWrite;
2112          else if (field->getOperationTimeType() == func::CFunctor::centered)
2113            time_data(0) = (lastWrite + lastLastWrite) / 2;
2114
2115          if (field->getOperationTimeType() == func::CFunctor::instant)
2116            time_data_bound(0) = time_data_bound(1) = lastWrite;
2117          else if (field->getOperationTimeType() == func::CFunctor::centered)
2118          {
2119            time_data_bound(0) = lastLastWrite;
2120            time_data_bound(1) = lastWrite;
2121          }
2122
2123          if (field->file->time_counter == CFile::time_counter_attr::instant)
2124            time_counter(0) = lastWrite;
2125          else if (field->file->time_counter == CFile::time_counter_attr::centered)
2126            time_counter(0) = (lastWrite + lastLastWrite) / 2;
2127          else if (field->file->time_counter == CFile::time_counter_attr::record)
2128            time_counter(0) = field->getNStep() - 1;
2129
2130
2131          if (field->file->time_counter == CFile::time_counter_attr::instant)
2132            time_counter_bound(0) = time_counter_bound(1) = lastWrite;
2133          else if (field->file->time_counter == CFile::time_counter_attr::centered)
2134          {
2135            time_counter_bound(0) = lastLastWrite;
2136            time_counter_bound(1) = lastWrite;
2137          }
2138          else if (field->file->time_counter == CFile::time_counter_attr::record)
2139            time_counter_bound(0) = time_counter_bound(1) = field->getNStep() - 1;
2140        }
2141
2142         bool isRoot = (server->intraCommRank == 0);
2143
2144         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
2145         {
2146           double scaleFactor = 1.0;
2147           double addOffset = 0.0;
2148           if (!field->scale_factor.isEmpty()) scaleFactor = field->scale_factor;
2149           if (!field->add_offset.isEmpty()) addOffset = field->add_offset;
2150           field->scaleFactorAddOffset(scaleFactor, addOffset);
2151         }
2152
2153         try
2154         {
2155           size_t writtenSize;
2156           if (field->getUseCompressedOutput())
2157             writtenSize = grid->getNumberWrittenIndexes();
2158           else
2159             writtenSize = grid->getWrittenDataSize();
2160
2161           CArray<double,1> fieldData(writtenSize);
2162           if (!field->default_value.isEmpty()) fieldData = field->default_value;
2163
2164           if (field->getUseCompressedOutput())
2165             field->outputCompressedField(fieldData);
2166           else
2167             field->outputField(fieldData);
2168
2169           if (!field->prec.isEmpty() && field->prec == 2) fieldData = round(fieldData);
2170
2171           switch (SuperClass::type)
2172           {
2173              case (MULTI_FILE) :
2174              {
2175                 SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep() - 1);
2176                 if (wtime)
2177                 {
2178                   SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep() - 1);
2179                   SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1);
2180                   if (field->file->time_counter != CFile::time_counter_attr::none)
2181                   {
2182                     SuperClassWriter::writeData(time_counter, getTimeCounterName(), isCollective, field->getNStep() - 1);
2183                     if (field->file->time_counter != CFile::time_counter_attr::record)
2184                       SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1);
2185                   }
2186                 }
2187                 break;
2188              }
2189              case (ONE_FILE) :
2190              {
2191                // const std::vector<int>& nZoomBeginGlobal = grid->getDistributionServer()->getZoomBeginGlobal();
2192                // const std::vector<int>& nZoomBeginServer = grid->getDistributionServer()->getZoomBeginServer();
2193                // const std::vector<int>& nZoomSizeServer  = grid->getDistributionServer()->getZoomSizeServer();
2194
2195                // std::vector<StdSize> start, count;
2196
2197                // if (field->getUseCompressedOutput())
2198                // {
2199                //   if (grid->isCompressible())
2200                //   {
2201                //     start.push_back(grid->getOffsetWrittenIndexes());
2202                //     count.push_back(grid->getNumberWrittenIndexes());
2203                //   }
2204                //   else
2205                //   {
2206                //     CArray<int,1> axisDomainOrder = grid->axis_domain_order;
2207                //     std::vector<StdString> domainList = grid->getDomainList();
2208                //     std::vector<StdString> axisList   = grid->getAxisList();
2209                //     int numElement = axisDomainOrder.numElements();
2210                //     int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
2211                //     int idx = nZoomBeginGlobal.size() - 1;
2212
2213                //     start.reserve(nZoomBeginGlobal.size());
2214                //     count.reserve(nZoomBeginGlobal.size());
2215
2216
2217                //     for (int i = numElement - 1; i >= 0; --i)
2218                //     {
2219                //       if (2 == axisDomainOrder(i))
2220                //       {
2221                //         CDomain* domain = CDomain::get(domainList[idxDomain]);
2222
2223                //         if (domain->isCompressible())
2224                //         {
2225                //           start.push_back(domain->getOffsetWrittenIndexes());
2226                //           count.push_back(domain->getNumberWrittenIndexes());
2227                //           idx -= 2;
2228                //         }
2229                //         else
2230                //         {
2231                //           if ((domain->type) != CDomain::type_attr::unstructured)
2232                //           {
2233                //             start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
2234                //             count.push_back(nZoomSizeServer[idx]);
2235                //           }
2236                //           --idx;
2237                //           start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
2238                //           count.push_back(nZoomSizeServer[idx]);
2239                //           --idx;
2240                //         }
2241                //         --idxDomain;
2242                //       }
2243                //       else if (1 == axisDomainOrder(i))
2244                //       {
2245                //         CAxis* axis = CAxis::get(axisList[idxAxis]);
2246
2247                //         if (axis->isCompressible())
2248                //         {
2249                //           start.push_back(axis->getOffsetWrittenIndexes());
2250                //           count.push_back(axis->getNumberWrittenIndexes());
2251                //         }
2252                //         else
2253                //         {
2254                //           start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
2255                //           count.push_back(nZoomSizeServer[idx]);
2256                //         }
2257
2258                //         --idxAxis;
2259                //         --idx;
2260                //       }
2261                //     }
2262                //   }
2263                const std::vector<int>& nZoomBeginGlobal = grid->getDistributionServer()->getZoomBeginGlobal();
2264                const std::vector<int>& nZoomBeginServer = grid->getDistributionServer()->getZoomBeginServer();
2265                const std::vector<int>& nZoomSizeServer  = grid->getDistributionServer()->getZoomSizeServer();
2266
2267                std::vector<StdSize> start, count;
2268
2269                if (field->getUseCompressedOutput())
2270                {
2271                  if (grid->isCompressible())
2272                  {
2273                    start.push_back(grid->getOffsetWrittenIndexes());
2274                    count.push_back(grid->getNumberWrittenIndexes());
2275                  }
2276                  else
2277                  {
2278                    CArray<int,1> axisDomainOrder = grid->axis_domain_order;
2279                    std::vector<StdString> domainList = grid->getDomainList();
2280                    std::vector<StdString> axisList   = grid->getAxisList();
2281                    int numElement = axisDomainOrder.numElements();
2282                    int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
2283                    int idx = nZoomBeginGlobal.size() - 1;
2284
2285                    start.reserve(nZoomBeginGlobal.size());
2286                    count.reserve(nZoomBeginGlobal.size());
2287
2288
2289                    for (int i = numElement - 1; i >= 0; --i)
2290                    {
2291                      if (2 == axisDomainOrder(i))
2292                      {
2293                        CDomain* domain = CDomain::get(domainList[idxDomain]);
2294
2295                        if (domain->isCompressible())
2296                        {
2297                          start.push_back(domain->getOffsetWrittenIndexes());
2298                          count.push_back(domain->getNumberWrittenIndexes());
2299                          idx -= 2;
2300                        }
2301                        else
2302                        {
2303                          if ((domain->type) != CDomain::type_attr::unstructured)
2304                          {
2305                            start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
2306                            count.push_back(nZoomSizeServer[idx]);
2307                          }
2308                          --idx;
2309                          start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
2310                          count.push_back(nZoomSizeServer[idx]);
2311                          --idx;
2312                        }
2313                        --idxDomain;
2314                      }
2315                      else if (1 == axisDomainOrder(i))
2316                      {
2317                        CAxis* axis = CAxis::get(axisList[idxAxis]);
2318
2319                        if (axis->isCompressible())
2320                        {
2321                          start.push_back(axis->getOffsetWrittenIndexes());
2322                          count.push_back(axis->getNumberWrittenIndexes());
2323                        }
2324                        else
2325                        {
2326                          start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
2327                          count.push_back(nZoomSizeServer[idx]);
2328                        }
2329
2330                        --idxAxis;
2331                        --idx;
2332                      }
2333                    }
2334                  }               
2335                }
2336                else
2337                {
2338                  // CArray<int,1> axisDomainOrder = grid->axis_domain_order;
2339                  // std::vector<StdString> domainList = grid->getDomainList();
2340                  // std::vector<StdString> axisList   = grid->getAxisList();
2341                  // int numElement = axisDomainOrder.numElements();
2342                  // int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
2343                  // int idx = nZoomBeginGlobal.size() - 1;
2344
2345                  // start.reserve(nZoomBeginGlobal.size());
2346                  // count.reserve(nZoomBeginGlobal.size());
2347
2348                  // for (int i = numElement - 1; i >= 0; --i)
2349                  // {
2350                  //   if (2 == axisDomainOrder(i))
2351                  //   {
2352                  //     CDomain* domain = CDomain::get(domainList[idxDomain]);
2353                  //     if ((domain->type) != CDomain::type_attr::unstructured)
2354                  //     {
2355                  //       start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
2356                  //       count.push_back(nZoomSizeServer[idx]);
2357                  //     }
2358                  //     --idx ;
2359                  //     start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
2360                  //     count.push_back(nZoomSizeServer[idx]);
2361                  //     --idx ;
2362                  //     --idxDomain;
2363                  //   }
2364                  //   else if (1 == axisDomainOrder(i))
2365                  //   {
2366                  //     start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
2367                  //     count.push_back(nZoomSizeServer[idx]);
2368                  //     --idx;
2369                  //   }
2370                  //   else
2371                  //   {
2372                  //     if (1 == axisDomainOrder.numElements())
2373                  //     {
2374                  //       start.push_back(0);
2375                  //       count.push_back(1);
2376                  //     }
2377                  //     --idx;
2378                  //   }
2379                  CArray<int,1> axisDomainOrder = grid->axis_domain_order;
2380                  std::vector<StdString> domainList = grid->getDomainList();
2381                  std::vector<StdString> axisList   = grid->getAxisList();
2382                  int numElement = axisDomainOrder.numElements();
2383                  int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
2384                  int idx = domainList.size() * 2 + axisList.size() - 1;// nZoomBeginGlobal.size() - 1;
2385
2386                  start.reserve(nZoomBeginGlobal.size());
2387                  count.reserve(nZoomBeginGlobal.size());
2388
2389                  for (int i = numElement - 1; i >= 0; --i)
2390                  {
2391                    if (2 == axisDomainOrder(i))
2392                    {
2393                      CDomain* domain = CDomain::get(domainList[idxDomain]);
2394                      if ((domain->type) != CDomain::type_attr::unstructured)
2395                      {
2396                        // start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
2397                        // count.push_back(nZoomSizeServer[idx]);
2398                        // start.push_back((domain->getStartWriteIndex())[idx]);
2399                        // count.push_back((domain->getCountWriteIndex())[idx]);
2400                        start.push_back(domain->zoom_jbegin - domain->global_zoom_jbegin);
2401                        count.push_back(domain->zoom_nj);
2402                      }
2403                      --idx ;
2404                      // start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
2405                      // count.push_back(nZoomSizeServer[idx]);
2406                      // start.push_back((domain->getStartWriteIndex())[idx]);
2407                      // count.push_back((domain->getCountWriteIndex())[idx]);
2408                        start.push_back(domain->zoom_ibegin - domain->global_zoom_ibegin);
2409                        count.push_back(domain->zoom_ni);
2410                      --idx ;
2411                      --idxDomain;
2412                    }
2413                    else if (1 == axisDomainOrder(i))
2414                    {
2415                      CAxis* axis = CAxis::get(axisList[idxAxis]);
2416                      // start.push_back(axis->getStartWriteIndex());
2417                      // count.push_back(axis->getCountWriteIndex());
2418                        start.push_back(axis->zoom_begin - axis->global_zoom_begin);
2419                        count.push_back(axis->zoom_n);
2420                      --idx;
2421                      --idxAxis;
2422                    }
2423                    else
2424                    {
2425                      if (1 == axisDomainOrder.numElements())
2426                      {
2427                        start.push_back(0);
2428                        count.push_back(1);
2429                      }
2430                      --idx;
2431                    }
2432                  }
2433                }
2434
2435                SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep() - 1, &start, &count);
2436                if (wtime)
2437                {
2438                   SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep() - 1, isRoot);
2439                   SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1, isRoot);
2440                   if (field->file->time_counter != CFile::time_counter_attr::none)
2441                   {
2442                     SuperClassWriter::writeTimeAxisData(time_counter, getTimeCounterName(), isCollective, field->getNStep() - 1, isRoot);
2443                     if (field->file->time_counter != CFile::time_counter_attr::record)
2444                       SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1, isRoot);
2445                   }
2446                }
2447
2448                break;
2449              }
2450            }
2451         }
2452         catch (CNetCdfException& e)
2453         {
2454           StdString msg("On writing field data: ");
2455           msg.append(fieldid); msg.append("\n");
2456           msg.append("In the context : ");
2457           msg.append(context->getId()); msg.append("\n");
2458           msg.append(e.what());
2459           ERROR("CNc4DataOutput::writeFieldData_ (CField*  field)", << msg);
2460         }
2461      }
2462
2463      //---------------------------------------------------------------
2464
2465      void CNc4DataOutput::writeTimeAxis_
2466                  (CField*    field,
2467                   const boost::shared_ptr<CCalendar> cal)
2468      {
2469         StdOStringStream oss;
2470
2471         if (field->getOperationTimeType() == func::CFunctor::once) return ;
2472
2473//         oss << "time_" << field->operation.getValue()
2474//             << "_" << field->getRelFile()->output_freq.getValue();
2475
2476//         StdString axisid = oss.str();
2477//         if (field->getOperationTimeType() == func::CFunctor::centered) axisid="time_centered" ;
2478//         else if (field->getOperationTimeType() == func::CFunctor::instant) axisid="time_instant" ;
2479
2480         StdString axisid("time_centered") ;
2481         StdString axisBoundId("time_centered_bounds");
2482         StdString timeid(getTimeCounterName());
2483         StdString timeBoundId("axis_nbounds");
2484
2485         if (field->getOperationTimeType() == func::CFunctor::instant)
2486         {
2487            axisid = "time_instant";
2488            axisBoundId = "time_instant_bounds";
2489         }
2490
2491         try
2492         {
2493          // Adding time_instant or time_centered
2494           std::vector<StdString> dims;
2495           dims.push_back(timeid);
2496           if (!SuperClassWriter::varExist(axisid))
2497           {
2498              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
2499
2500              CDate timeOrigin=cal->getTimeOrigin() ;
2501              StdOStringStream oss2;
2502  //            oss2<<initDate.getYear()<<"-"<<initDate.getMonth()<<"-"<<initDate.getDay()<<" "
2503  //                <<initDate.getHour()<<"-"<<initDate.getMinute()<<"-"<<initDate.getSecond() ;
2504              StdString strInitdate=oss2.str() ;
2505              StdString strTimeOrigin=timeOrigin.toString() ;
2506              this->writeTimeAxisAttributes
2507                 (axisid, cal->getType(),
2508                  StdString("seconds since ").append(strTimeOrigin),
2509                  strTimeOrigin, axisBoundId);
2510           }
2511
2512           // Adding time_instant_bounds or time_centered_bounds variables
2513           if (!SuperClassWriter::varExist(axisBoundId))
2514           {
2515              dims.clear() ;
2516              dims.push_back(timeid);
2517              dims.push_back(timeBoundId);
2518              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
2519           }
2520
2521           if (field->file->time_counter != CFile::time_counter_attr::none)
2522           {
2523             // Adding time_counter
2524             axisid = getTimeCounterName();
2525             axisBoundId = getTimeCounterName() + "_bounds";
2526             dims.clear();
2527             dims.push_back(timeid);
2528             if (!SuperClassWriter::varExist(axisid))
2529             {
2530                SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
2531                SuperClassWriter::addAttribute("axis", string("T"), &axisid);
2532
2533                if (field->file->time_counter != CFile::time_counter_attr::record)
2534                {
2535                  CDate timeOrigin = cal->getTimeOrigin();
2536                  StdString strTimeOrigin = timeOrigin.toString();
2537
2538                  this->writeTimeAxisAttributes(axisid, cal->getType(),
2539                                                StdString("seconds since ").append(strTimeOrigin),
2540                                                strTimeOrigin, axisBoundId);
2541                }
2542             }
2543
2544             // Adding time_counter_bound dimension
2545             if (field->file->time_counter != CFile::time_counter_attr::record)
2546             {
2547                if (!SuperClassWriter::varExist(axisBoundId))
2548                {
2549                  dims.clear();
2550                  dims.push_back(timeid);
2551                  dims.push_back(timeBoundId);
2552                  SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
2553                }
2554             }
2555           }
2556         }
2557         catch (CNetCdfException& e)
2558         {
2559           StdString msg("On writing time axis data: ");
2560           msg.append("In the context : ");
2561           CContext* context = CContext::getCurrent() ;
2562           msg.append(context->getId()); msg.append("\n");
2563           msg.append(e.what());
2564           ERROR("CNc4DataOutput::writeTimeAxis_ (CField*    field, \
2565                  const boost::shared_ptr<CCalendar> cal)", << msg);
2566         }
2567      }
2568
2569      //---------------------------------------------------------------
2570
2571      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
2572                                                   const StdString & calendar,
2573                                                   const StdString & units,
2574                                                   const StdString & time_origin,
2575                                                   const StdString & time_bounds,
2576                                                   const StdString & standard_name,
2577                                                   const StdString & long_name)
2578      {
2579         try
2580         {
2581           SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
2582           SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
2583           SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
2584           SuperClassWriter::addAttribute("units",         units        , &axis_name);
2585           SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
2586           SuperClassWriter::addAttribute("bounds",        time_bounds  , &axis_name);
2587         }
2588         catch (CNetCdfException& e)
2589         {
2590           StdString msg("On writing time axis Attribute: ");
2591           msg.append("In the context : ");
2592           CContext* context = CContext::getCurrent() ;
2593           msg.append(context->getId()); msg.append("\n");
2594           msg.append(e.what());
2595           ERROR("CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name, \
2596                                                          const StdString & calendar,\
2597                                                          const StdString & units, \
2598                                                          const StdString & time_origin, \
2599                                                          const StdString & time_bounds, \
2600                                                          const StdString & standard_name, \
2601                                                          const StdString & long_name)", << msg);
2602         }
2603      }
2604
2605      //---------------------------------------------------------------
2606
2607      void CNc4DataOutput::writeAxisAttributes(const StdString & axis_name,
2608                                               const StdString & axis,
2609                                               const StdString & standard_name,
2610                                               const StdString & long_name,
2611                                               const StdString & units,
2612                                               const StdString & nav_model)
2613      {
2614         try
2615         {
2616          if (!axis.empty())
2617            SuperClassWriter::addAttribute("axis"       , axis         , &axis_name);
2618
2619          SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
2620          SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
2621          SuperClassWriter::addAttribute("units"        , units        , &axis_name);
2622//          SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
2623         }
2624         catch (CNetCdfException& e)
2625         {
2626           StdString msg("On writing Axis Attribute: ");
2627           msg.append("In the context : ");
2628           CContext* context = CContext::getCurrent() ;
2629           msg.append(context->getId()); msg.append("\n");
2630           msg.append(e.what());
2631           ERROR("CNc4DataOutput::writeAxisAttributes(const StdString & axis_name, \
2632                                                      const StdString & axis, \
2633                                                      const StdString & standard_name, \
2634                                                      const StdString & long_name, \
2635                                                      const StdString & units, \
2636                                                      const StdString & nav_model)", << msg);
2637         }
2638      }
2639
2640      //---------------------------------------------------------------
2641
2642      void CNc4DataOutput::writeLocalAttributes
2643         (int ibegin, int ni, int jbegin, int nj, StdString domid)
2644      {
2645        try
2646        {
2647         SuperClassWriter::addAttribute(StdString("ibegin").append(domid), ibegin);
2648         SuperClassWriter::addAttribute(StdString("ni"    ).append(domid), ni);
2649         SuperClassWriter::addAttribute(StdString("jbegin").append(domid), jbegin);
2650         SuperClassWriter::addAttribute(StdString("nj"    ).append(domid), nj);
2651        }
2652        catch (CNetCdfException& e)
2653        {
2654           StdString msg("On writing Local Attributes: ");
2655           msg.append("In the context : ");
2656           CContext* context = CContext::getCurrent() ;
2657           msg.append(context->getId()); msg.append("\n");
2658           msg.append(e.what());
2659           ERROR("CNc4DataOutput::writeLocalAttributes \
2660                  (int ibegin, int ni, int jbegin, int nj, StdString domid)", << msg);
2661        }
2662
2663      }
2664
2665      void CNc4DataOutput::writeLocalAttributes_IOIPSL(const StdString& dimXid, const StdString& dimYid,
2666                                                       int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)
2667      {
2668         CArray<int,1> array(2) ;
2669
2670         try
2671         {
2672           SuperClassWriter::addAttribute("DOMAIN_number_total",size ) ;
2673           SuperClassWriter::addAttribute("DOMAIN_number", rank) ;
2674           array = SuperClassWriter::getDimension(dimXid) + 1, SuperClassWriter::getDimension(dimYid) + 1;
2675           SuperClassWriter::addAttribute("DOMAIN_dimensions_ids",array) ;
2676           array=ni_glo,nj_glo ;
2677           SuperClassWriter::addAttribute("DOMAIN_size_global", array) ;
2678           array=ni,nj ;
2679           SuperClassWriter::addAttribute("DOMAIN_size_local", array) ;
2680           array=ibegin+1,jbegin+1 ;
2681           SuperClassWriter::addAttribute("DOMAIN_position_first", array) ;
2682           array=ibegin+ni-1+1,jbegin+nj-1+1 ;
2683           SuperClassWriter::addAttribute("DOMAIN_position_last",array) ;
2684           array=0,0 ;
2685           SuperClassWriter::addAttribute("DOMAIN_halo_size_start", array) ;
2686           SuperClassWriter::addAttribute("DOMAIN_halo_size_end", array);
2687           SuperClassWriter::addAttribute("DOMAIN_type",string("box")) ;
2688  /*
2689           SuperClassWriter::addAttribute("DOMAIN_DIM_N001",string("x")) ;
2690           SuperClassWriter::addAttribute("DOMAIN_DIM_N002",string("y")) ;
2691           SuperClassWriter::addAttribute("DOMAIN_DIM_N003",string("axis_A")) ;
2692           SuperClassWriter::addAttribute("DOMAIN_DIM_N004",string("time_counter")) ;
2693  */
2694         }
2695         catch (CNetCdfException& e)
2696         {
2697           StdString msg("On writing Local Attributes IOIPSL \n");
2698           msg.append("In the context : ");
2699           CContext* context = CContext::getCurrent() ;
2700           msg.append(context->getId()); msg.append("\n");
2701           msg.append(e.what());
2702           ERROR("CNc4DataOutput::writeLocalAttributes_IOIPSL \
2703                  (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)", << msg);
2704         }
2705      }
2706      //---------------------------------------------------------------
2707
2708      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
2709                                                const StdString & description,
2710                                                const StdString & conventions,
2711                                                const StdString & production,
2712                                                const StdString & timeStamp)
2713      {
2714         try
2715         {
2716           SuperClassWriter::addAttribute("name"       , name);
2717           SuperClassWriter::addAttribute("description", description);
2718           SuperClassWriter::addAttribute("title"      , description);
2719           SuperClassWriter::addAttribute("Conventions", conventions);
2720           SuperClassWriter::addAttribute("production" , production);
2721           SuperClassWriter::addAttribute("timeStamp"  , timeStamp);
2722         }
2723         catch (CNetCdfException& e)
2724         {
2725           StdString msg("On writing File Attributes \n ");
2726           msg.append("In the context : ");
2727           CContext* context = CContext::getCurrent() ;
2728           msg.append(context->getId()); msg.append("\n");
2729           msg.append(e.what());
2730           ERROR("CNc4DataOutput:: writeFileAttributes(const StdString & name, \
2731                                                const StdString & description, \
2732                                                const StdString & conventions, \
2733                                                const StdString & production, \
2734                                                const StdString & timeStamp)", << msg);
2735         }
2736      }
2737
2738      //---------------------------------------------------------------
2739
2740      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
2741                                               int data_dim,
2742                                               int data_ni,
2743                                               int data_nj,
2744                                               int data_ibegin,
2745                                               int data_jbegin)
2746      {
2747         try
2748         {
2749           SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
2750           SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
2751           SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
2752           SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
2753           SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
2754         }
2755         catch (CNetCdfException& e)
2756         {
2757           StdString msg("On writing Mask Attributes \n ");
2758           msg.append("In the context : ");
2759           CContext* context = CContext::getCurrent() ;
2760           msg.append(context->getId()); msg.append("\n");
2761           msg.append(e.what());
2762           ERROR("CNc4DataOutput::writeMaskAttributes(const StdString & mask_name, \
2763                                               int data_dim, \
2764                                               int data_ni, \
2765                                               int data_nj, \
2766                                               int data_ibegin, \
2767                                               int data_jbegin)", << msg);
2768         }
2769      }
2770
2771      ///--------------------------------------------------------------
2772
2773      StdSize CNc4DataOutput::getRecordFromTime(Time time)
2774      {
2775        std::map<Time, StdSize>::const_iterator it = timeToRecordCache.find(time);
2776        if (it == timeToRecordCache.end())
2777        {
2778          StdString timeAxisBoundsId(getTimeCounterName() + "_bounds");
2779          if (!SuperClassWriter::varExist(timeAxisBoundsId))
2780            timeAxisBoundsId = "time_instant_bounds";
2781
2782          CArray<double,2> timeAxisBounds;
2783          SuperClassWriter::getTimeAxisBounds(timeAxisBounds, timeAxisBoundsId, isCollective);
2784
2785          StdSize record = 0;
2786          double dtime(time);
2787          for (int n = timeAxisBounds.extent(1) - 1; n >= 0; n--)
2788          {
2789            if (timeAxisBounds(1, n) < dtime)
2790            {
2791              record = n + 1;
2792              break;
2793            }
2794          }
2795          it = timeToRecordCache.insert(std::make_pair(time, record)).first;
2796        }
2797        return it->second;
2798      }
2799
2800      ///--------------------------------------------------------------
2801
2802      bool CNc4DataOutput::isWrittenDomain(const std::string& domainName) const
2803      {
2804        return (this->writtenDomains.find(domainName) != this->writtenDomains.end());
2805      }
2806
2807      bool CNc4DataOutput::isWrittenCompressedDomain(const std::string& domainName) const
2808      {
2809        return (this->writtenCompressedDomains.find(domainName) != this->writtenCompressedDomains.end());
2810      }
2811
2812      bool CNc4DataOutput::isWrittenAxis(const std::string& axisName) const
2813      {
2814        return (this->writtenAxis.find(axisName) != this->writtenAxis.end());
2815      }
2816
2817      bool CNc4DataOutput::isWrittenCompressedAxis(const std::string& axisName) const
2818      {
2819        return (this->writtenCompressedAxis.find(axisName) != this->writtenCompressedAxis.end());
2820      }
2821
2822      bool CNc4DataOutput::isWrittenScalar(const std::string& scalarName) const
2823      {
2824        return (this->writtenScalar.find(scalarName) != this->writtenScalar.end());
2825      }
2826
2827      void CNc4DataOutput::setWrittenDomain(const std::string& domainName)
2828      {
2829        this->writtenDomains.insert(domainName);
2830      }
2831
2832      void CNc4DataOutput::setWrittenCompressedDomain(const std::string& domainName)
2833      {
2834        this->writtenCompressedDomains.insert(domainName);
2835      }
2836
2837      void CNc4DataOutput::setWrittenAxis(const std::string& axisName)
2838      {
2839        this->writtenAxis.insert(axisName);
2840      }
2841
2842      void CNc4DataOutput::setWrittenCompressedAxis(const std::string& axisName)
2843      {
2844        this->writtenCompressedAxis.insert(axisName);
2845      }
2846
2847      void CNc4DataOutput::setWrittenScalar(const std::string& scalarName)
2848      {
2849        this->writtenScalar.insert(scalarName);
2850      }
2851} // namespace xios
Note: See TracBrowser for help on using the repository browser.