source: XIOS/trunk/src/io/nc4_data_output.cpp @ 1639

Last change on this file since 1639 was 1639, checked in by yushan, 5 years ago

revert erroneous commit on trunk

  • 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.