source: XIOS/dev/branch_yushan_merged/src/io/nc4_data_output.cpp @ 1157

Last change on this file since 1157 was 1157, checked in by yushan, 7 years ago

branch re-merged with trunk @1156

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