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

Last change on this file since 1045 was 1045, checked in by ymipsl, 7 years ago

New attributs prec for axis, domain and scalar to control the output precision of the coordinates.
Correct values are 4 or 8 to output in single or double precision. Default is single precision.

YM

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