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

Last change on this file since 1653 was 1653, checked in by oabramkina, 5 years ago

Developments for visualization of XIOS workflow.

Branch is spawned from trunk r1649.

Boost library is used for producing Graphviz DOT files. Current results: a DOT file representing a static workflow. For a complete proof of concept, DOT files for each timestamp should be generated. The necessary information has been collected by XIOS, it only requires rearranging the information for graphing (changes in classes CWorkflowGraph and CGraphviz).

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