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

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

Expected performance enhancement when using append mode.
Instead to read the whole time axis, only the last record is read first, and eventually continue until to reach the record corresponding to the current timestep.
(currently untested)

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