source: XIOS/dev/dev_ym/XIOS_COUPLING/src/io/nc4_data_output.cpp @ 1959

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

Xios coupling

Some cleaning...

YM

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