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

Last change on this file since 902 was 902, checked in by oabramkina, 7 years ago

Sequential version of new functionalities for mesh connectivity:

edge_faces
face_edges
face_face.

Compilation error of version 900 resolved.

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