source: XIOS/trunk/src/output/nc4_data_output.cpp @ 613

Last change on this file since 613 was 613, checked in by rlacroix, 9 years ago

Improve CF compliance: Various cosmetic changes.

  • Remove the axis attribute from the latitute and longitude coordinate variables when using curvilinear or unstructured grids.
  • Add the axis="Z" attribute only when the positive attribute is set for an axis.
  • Rename the conventions attribute to Conventions.
  • Add a global title attribute with the same content as the global description attribute. The old attribute might be removed in the future.
  • Remove the title attribute from the time coordinates.
  • 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
File size: 79.2 KB
Line 
1
2#include "nc4_data_output.hpp"
3
4#include <boost/lexical_cast.hpp>
5#include "attribute_template.hpp"
6#include "group_template.hpp"
7
8#include "file.hpp"
9#include "calendar.hpp"
10#include "context.hpp"
11#include "context_server.hpp"
12#include "netCdfException.hpp"
13#include "exception.hpp"
14
15namespace xios
16{
17      /// ////////////////////// Définitions ////////////////////// ///
18      CNc4DataOutput::CNc4DataOutput
19         (const StdString & filename, bool exist)
20            : SuperClass()
21            , SuperClassWriter(filename, exist)
22            , filename(filename)
23      {
24         StdString timeid = StdString("time_counter");
25         SuperClass::type = MULTI_FILE;
26//         if (!exist)
27//            SuperClassWriter::addDimension(timeid);
28      }
29
30      CNc4DataOutput::CNc4DataOutput
31         (const StdString & filename, bool exist, bool useClassicFormat,
32          MPI_Comm comm_file,bool multifile, bool isCollective)
33            : SuperClass()
34            , SuperClassWriter(filename, exist, useClassicFormat, &comm_file, multifile)
35            , comm_file(comm_file)
36            , filename(filename)
37            , isCollective(isCollective)
38      {
39         StdString timeid = StdString("time_counter");
40
41         SuperClass::type = (multifile) ? MULTI_FILE : ONE_FILE;
42
43 //        if (!exist)
44//            SuperClassWriter::addDimension(timeid);
45      }
46
47
48      CNc4DataOutput::~CNc4DataOutput(void)
49      { /* Ne rien faire de plus */ }
50
51      ///--------------------------------------------------------------
52
53      const StdString & CNc4DataOutput::getFileName(void) const
54      {
55         return (this->filename);
56      }
57
58      //---------------------------------------------------------------
59
60      void CNc4DataOutput::writeDomain_(CDomain* domain)
61      {
62         if (domain->type == CDomain::type_attr::unstructured)
63         {
64           writeUnstructuredDomain(domain) ;
65           return ;
66         }
67
68         CContext* context = CContext::getCurrent() ;
69         CContextServer* server=context->server ;
70
71         if (domain->IsWritten(this->filename)) return;
72         domain->checkAttributes();
73
74         if (domain->isEmpty())
75           if (SuperClass::type==MULTI_FILE) return ;
76
77         std::vector<StdString> dim0, dim1;
78         StdString domid     = (!domain->name.isEmpty())
79                             ? domain->name.getValue() : domain->getId();
80         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
81
82
83         StdString dimXid, dimYid ;
84
85         bool isRegularDomain = (domain->type == CDomain::type_attr::regular);
86         switch (domain->type)
87         {
88           case CDomain::type_attr::curvilinear :
89             dimXid     = StdString("x").append(appendDomid);
90             dimYid     = StdString("y").append(appendDomid);
91             break ;
92           case CDomain::type_attr::regular :
93             dimXid     = StdString("lon").append(appendDomid);
94             dimYid     = StdString("lat").append(appendDomid);
95             break;
96           case CDomain::type_attr::unstructured :
97             dimXid     = StdString("cell").append(appendDomid);
98             break;
99         }
100
101         string lonid,latid,bounds_lonid,bounds_latid ;
102         string areaId = "area" + appendDomid;
103/*
104         StdString lonid_loc = (server->intraCommSize > 1)
105                             ? StdString("lon").append(appendDomid).append("_local")
106                             : lonid;
107         StdString latid_loc = (server->intraCommSize > 1)
108                             ? StdString("lat").append(appendDomid).append("_local")
109                             : latid;
110*/
111
112         try
113         {
114           switch (SuperClass::type)
115           {
116              case (MULTI_FILE) :
117              {
118  //               if (domain->isEmpty()) return;
119
120                 if (server->intraCommSize > 1)
121                 {
122  //                 SuperClassWriter::addDimension(lonid, domain->zoom_ni.getValue());
123  //                 SuperClassWriter::addDimension(latid, domain->zoom_nj.getValue());
124                 }
125
126                 switch (domain->type)
127                 {
128                   case CDomain::type_attr::curvilinear :
129                     dim0.push_back(dimYid); dim0.push_back(dimXid);
130                     lonid = StdString("nav_lon").append(appendDomid);
131                     latid = StdString("nav_lat").append(appendDomid);
132                     break ;
133                   case CDomain::type_attr::regular :
134                     lonid = StdString("lon").append(appendDomid);
135                     latid = StdString("lat").append(appendDomid);
136                     dim0.push_back(dimYid);
137                     dim1.push_back(dimXid);
138                     break;
139                   case CDomain::type_attr::unstructured :
140                     lonid = StdString("lon").append(appendDomid);
141                     latid = StdString("lat").append(appendDomid);
142                     bounds_lonid=string("bounds_lon").append(appendDomid);
143                     bounds_latid=string("bounds_lat").append(appendDomid);
144                     dim0.push_back(dimXid);
145                     break;
146                 }
147
148                 if (domain->type == CDomain::type_attr::unstructured)
149                 {
150                   SuperClassWriter::addDimension(dimXid, domain->nj_glo);
151                 }
152                 else
153                 {
154                   SuperClassWriter::addDimension(dimXid, domain->zoom_ni_srv);
155                   SuperClassWriter::addDimension(dimYid, domain->zoom_nj_srv);
156                 }
157
158                 if (server->intraCommSize > 1)
159                 {
160                    if (domain->type != CDomain::type_attr::unstructured)
161                    {
162                      this->writeLocalAttributes(domain->zoom_ibegin_srv,
163                                                 domain->zoom_ni_srv,
164                                                 domain->zoom_jbegin_srv,
165                                                 domain->zoom_nj_srv,
166                                                 appendDomid);
167
168                      if (singleDomain) this->writeLocalAttributes_IOIPSL(domain->zoom_ibegin_srv,
169                                                 domain->zoom_ni_srv,
170                                                 domain->zoom_jbegin_srv,
171                                                 domain->zoom_nj_srv,
172                                                 domain->ni_glo,domain->nj_glo,
173                                                 server->intraCommRank,server->intraCommSize);
174                   }
175                 }
176
177                 switch (domain->type)
178                 {
179                   case CDomain::type_attr::curvilinear :
180                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
181                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
182                     break ;
183                    case CDomain::type_attr::regular :
184                      SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
185                      SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
186                      break ;
187                    case CDomain::type_attr::unstructured :
188                      SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
189                      SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
190                 }
191
192                 this->writeAxisAttributes(lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
193                 this->writeAxisAttributes(latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
194
195                 dim0.clear();
196                 if (domain->type != CDomain::type_attr::unstructured) dim0.push_back(dimYid);
197                 dim0.push_back(dimXid);
198
199
200  // supress mask               if (server->intraCommSize > 1)
201  // supress mask               {
202  // supress mask                  SuperClassWriter::addVariable(maskid, NC_INT, dim0);
203  // supress mask
204  // supress mask                  this->writeMaskAttributes(maskid,
205  // supress mask                     domain->data_dim.getValue()/*,
206  // supress mask                     domain->data_ni.getValue(),
207  // supress mask                     domain->data_nj.getValue(),
208  // supress mask                     domain->data_ibegin.getValue(),
209  // supress mask                     domain->data_jbegin.getValue()*/);
210  // supress mask               }
211
212                 //SuperClassWriter::setDefaultValue(maskid, &dvm);
213
214                 if (domain->hasArea)
215                 {
216                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
217                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
218                 }
219
220                 SuperClassWriter::definition_end();
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::regular :
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->hasArea)
237                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0);
238
239                 SuperClassWriter::definition_start();
240
241                 break;
242              }
243              case (ONE_FILE) :
244              {
245                 SuperClassWriter::addDimension(dimXid, domain->zoom_ni.getValue());
246                 SuperClassWriter::addDimension(dimYid, domain->zoom_nj.getValue());
247
248                 switch (domain->type)
249                 {
250                   case CDomain::type_attr::curvilinear :
251                     dim0.push_back(dimYid); dim0.push_back(dimXid);
252                     lonid = StdString("nav_lon").append(appendDomid);
253                     latid = StdString("nav_lat").append(appendDomid);
254                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
255                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
256                     break;
257
258                   case CDomain::type_attr::regular :
259                     dim0.push_back(dimYid);
260                     dim1.push_back(dimXid);
261                     lonid = StdString("lon").append(appendDomid);
262                     latid = StdString("lat").append(appendDomid);
263                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
264                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
265                     break;
266                 }
267
268                 if (domain->hasArea)
269                 {
270                   dim0.clear();
271                   dim0.push_back(dimYid); dim0.push_back(dimXid);
272                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
273                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
274                   dim0.clear();
275                 }
276
277                 this->writeAxisAttributes
278                    (lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
279                 this->writeAxisAttributes
280                    (latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
281
282                 SuperClassWriter::definition_end();
283
284                 switch (domain->type)
285                 {
286                   case CDomain::type_attr::curvilinear :
287                   {
288                     std::vector<StdSize> start(2) ;
289                     std::vector<StdSize> count(2) ;
290                     if (domain->isEmpty())
291                     {
292                       start[0]=0 ; start[1]=0 ;
293                       count[0]=0 ; count[1]=0 ;
294                     }
295                     else
296                     {
297                       start[1]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start [0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
298                       count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
299                     }
300
301                     SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
302                     SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
303                     break;
304                   }
305                   case CDomain::type_attr::regular :
306                   {
307                     std::vector<StdSize> start(1) ;
308                     std::vector<StdSize> count(1) ;
309                     if (domain->isEmpty())
310                     {
311                       start[0]=0 ;
312                       count[0]=0 ;
313                       SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
314                       SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);                 }
315                     else
316                     {
317                       start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
318                       count[0]=domain->zoom_nj_srv ;
319                       CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;
320                       SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0,&start,&count);
321
322                       start[0]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ;
323                       count[0]=domain->zoom_ni_srv ;
324                       CArray<double,1> lon=domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;
325                       SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0,&start,&count);
326                     }
327                     break;
328                   }
329                 }
330
331                 if (domain->hasArea)
332                 {
333                   std::vector<StdSize> start(2);
334                   std::vector<StdSize> count(2);
335
336                   if (domain->isEmpty())
337                   {
338                     start[0] = 0; start[1] = 0;
339                     count[0] = 0; count[1] = 0;
340                   }
341                   else
342                   {
343                     start[1] = domain->zoom_ibegin_srv - domain->zoom_ibegin.getValue();
344                     start[0] = domain->zoom_jbegin_srv - domain->zoom_jbegin.getValue();
345                     count[1] = domain->zoom_ni_srv;
346                     count[0] = domain->zoom_nj_srv;
347                   }
348
349                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0, &start, &count);
350                 }
351
352                 SuperClassWriter::definition_start();
353                 break;
354              }
355              default :
356                 ERROR("CNc4DataOutput::writeDomain(domain)",
357                       << "[ type = " << SuperClass::type << "]"
358                       << " not implemented yet !");
359           }
360         }
361         catch (CNetCdfException& e)
362         {
363           StdString msg("On writing the domain : ");
364           msg.append(domid); msg.append("\n");
365           msg.append("In the context : ");
366           msg.append(context->getId()); msg.append("\n");
367           msg.append(e.what());
368           ERROR("CNc4DataOutput::writeDomain_(CDomain* domain)", << msg);
369         }
370
371         domain->addRelFile(this->filename);
372      }
373
374      void CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)
375      {
376         CContext* context = CContext::getCurrent() ;
377         CContextServer* server=context->server ;
378
379         if (domain->IsWritten(this->filename)) return;
380         domain->checkAttributes();
381
382         if (domain->isEmpty())
383           if (SuperClass::type==MULTI_FILE) return ;
384
385         std::vector<StdString> dim0, dim1;
386         StdString domid     = (!domain->name.isEmpty())
387                             ? domain->name.getValue() : domain->getId();
388         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
389
390
391         StdString dimXid = StdString("cell").append(appendDomid);
392         StdString dimVertId = StdString("nvertex").append(appendDomid);
393
394         string lonid,latid,bounds_lonid,bounds_latid ;
395         string areaId = "area" + appendDomid;
396
397         try
398         {
399           switch (SuperClass::type)
400           {
401              case (MULTI_FILE) :
402              {
403                 lonid = StdString("lon").append(appendDomid);
404                 latid = StdString("lat").append(appendDomid);
405                 dim0.push_back(dimXid);
406
407                 SuperClassWriter::addDimension(dimXid, domain->zoom_nj_srv);
408                 SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
409                 SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
410
411                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
412                 bounds_latid = StdString("bounds_lat").append(appendDomid);
413
414
415                 this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid);
416                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
417                 this->writeAxisAttributes(latid, "", "latitude", "Latitude", "degrees_north", domid);
418                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
419                 if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
420                 dim0.clear();
421                 if (domain->hasBounds)
422                 {
423                   dim0.push_back(dimXid);
424                   dim0.push_back(dimVertId);
425                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
426                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
427                 }
428
429                 dim0.clear();
430                 dim0.push_back(dimXid);
431
432                 if (domain->hasArea)
433                 {
434                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
435                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
436                 }
437
438                 SuperClassWriter::definition_end();
439
440                 SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0);
441                 SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0);
442
443                 if (domain->hasBounds)
444                 {
445                   SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0);
446                   SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0);
447                 }
448
449                 if (domain->hasArea)
450                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0);
451
452                 SuperClassWriter::definition_start();
453                 break ;
454              }
455
456              case (ONE_FILE) :
457              {
458                 lonid = StdString("lon").append(appendDomid);
459                 latid = StdString("lat").append(appendDomid);
460                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
461                 bounds_latid = StdString("bounds_lat").append(appendDomid);
462                 dim0.push_back(dimXid);
463                 SuperClassWriter::addDimension(dimXid, domain->nj_glo);
464                 SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
465                 SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
466                 this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid);
467                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
468                 this->writeAxisAttributes(latid, "", "latitude", "Latitude", "degrees_north", domid);
469                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
470                 if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
471                 dim0.clear();
472
473                 if (domain->hasBounds)
474                 {
475                   dim0.push_back(dimXid);
476                   dim0.push_back(dimVertId);
477                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
478                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
479                 }
480
481                 if (domain->hasArea)
482                 {
483                   dim0.clear();
484                   dim0.push_back(dimXid);
485                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
486                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
487                 }
488
489                 SuperClassWriter::definition_end();
490
491                 std::vector<StdSize> start(1), startBounds(2) ;
492                 std::vector<StdSize> count(1), countBounds(2) ;
493                 if (domain->isEmpty())
494                 {
495                   start[0]=0 ;
496                   count[0]=0 ;
497                   startBounds[1]=0 ;
498                   countBounds[1]=domain->nvertex ;
499                   startBounds[0]=0 ;
500                   countBounds[0]=0 ;
501                 }
502                 else
503                 {
504                   start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin ;
505                   count[0]=domain->zoom_nj_srv ;
506                   startBounds[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin ;
507                   startBounds[1]=0 ;
508                   countBounds[0]=domain->zoom_nj_srv ;
509                   countBounds[1]=domain->nvertex ;
510                 }
511                 SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
512                 SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
513                 if (domain->hasBounds)
514                 {
515                   SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0,&startBounds,&countBounds);
516                   SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0,&startBounds,&countBounds);
517                 }
518
519                 if (domain->hasArea)
520                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0, &start, &count);
521
522                 SuperClassWriter::definition_start();
523
524                 break;
525              }
526              default :
527                 ERROR("CNc4DataOutput::writeDomain(domain)",
528                       << "[ type = " << SuperClass::type << "]"
529                       << " not implemented yet !");
530           }
531         }
532         catch (CNetCdfException& e)
533         {
534           StdString msg("On writing the domain : ");
535           msg.append(domid); msg.append("\n");
536           msg.append("In the context : ");
537           msg.append(context->getId()); msg.append("\n");
538           msg.append(e.what());
539           ERROR("CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)", << msg);
540         }
541         domain->addRelFile(this->filename);
542      }
543      //--------------------------------------------------------------
544
545      void CNc4DataOutput::writeAxis_(CAxis* axis)
546      {
547        if (axis->IsWritten(this->filename)) return;
548        axis->checkAttributes();
549        int zoom_size_srv  = axis->zoom_size_srv;
550        int zoom_begin_srv = axis->zoom_begin_srv;
551        int zoom_size  = (MULTI_FILE == SuperClass::type) ? zoom_size_srv : axis->zoom_size;
552        int zoom_begin = (MULTI_FILE == SuperClass::type) ? zoom_begin_srv : axis->zoom_begin;
553
554
555        std::vector<StdString> dims;
556        StdString axisid = !axis->name.isEmpty() ? axis->name.getValue() : axis->getId();
557        try
558        {
559          SuperClassWriter::addDimension(axisid, zoom_size);
560          dims.push_back(axisid);
561
562          switch (SuperClass::type)
563          {
564            case MULTI_FILE:
565            case ONE_FILE:
566            {
567              SuperClassWriter::addVariable(axisid, NC_FLOAT, dims);
568
569              if (!axis->name.isEmpty())
570                SuperClassWriter::addAttribute("name", axis->name.getValue(), &axisid);
571
572              if (!axis->standard_name.isEmpty())
573                SuperClassWriter::addAttribute("standard_name", axis->standard_name.getValue(), &axisid);
574
575              if (!axis->long_name.isEmpty())
576                SuperClassWriter::addAttribute("long_name", axis->long_name.getValue(), &axisid);
577
578              if (!axis->unit.isEmpty())
579                SuperClassWriter::addAttribute("units", axis->unit.getValue(), &axisid);
580
581              if (!axis->positive.isEmpty())
582              {
583                SuperClassWriter::addAttribute("axis", string("Z"), &axisid);
584                SuperClassWriter::addAttribute("positive",
585                                               (axis->positive == CAxis::positive_attr::up) ? string("up") : string("down"),
586                                               &axisid);
587              }
588
589              StdString axisBoundsId = axisid + "_bounds";
590              if (!axis->bounds.isEmpty())
591              {
592                dims.push_back("axis_nbounds");
593                SuperClassWriter::addVariable(axisBoundsId, NC_FLOAT, dims);
594                SuperClassWriter::addAttribute("bounds", axisBoundsId, &axisid);
595              }
596
597              SuperClassWriter::definition_end();
598
599              CArray<double,1> axis_value(zoom_size);
600              for (int i = 0; i < zoom_size_srv; i++) axis_value(i) = axis->value(i + zoom_begin_srv);
601              SuperClassWriter::writeData(axis_value, axisid, isCollective, 0);
602
603              if (!axis->bounds.isEmpty())
604              {
605                CArray<double,2> axisBounds(zoom_size, 2);
606                for (int i = 0; i < zoom_size_srv; i++)
607                {
608                  axisBounds(i, 0) = axis->bounds(i + zoom_begin_srv, 0);
609                  axisBounds(i, 1) = axis->bounds(i + zoom_begin_srv, 1);
610                }
611                SuperClassWriter::writeData(axisBounds, axisBoundsId, isCollective, 0);
612              }
613
614              SuperClassWriter::definition_start();
615
616              break;
617            }
618            default :
619              ERROR("CNc4DataOutput::writeDomain(domain)",
620                    << "[ type = " << SuperClass::type << "]"
621                    << " not implemented yet !");
622          }
623        }
624        catch (CNetCdfException& e)
625        {
626          StdString msg("On writing the axis : ");
627          msg.append(axisid); msg.append("\n");
628          msg.append("In the context : ");
629          CContext* context = CContext::getCurrent() ;
630          msg.append(context->getId()); msg.append("\n");
631          msg.append(e.what());
632          ERROR("CNc4DataOutput::writeAxis_(CAxis* axis)", << msg);
633        }
634        axis->addRelFile(this->filename);
635     }
636
637     void CNc4DataOutput::writeTimeDimension_(void)
638     {
639       try
640       {
641        SuperClassWriter::addDimension("time_counter");
642        SuperClassWriter::addDimension("time_bounds", 2);
643       }
644       catch (CNetCdfException& e)
645       {
646         StdString msg("On writing time dimension : time_couter, time_bounds \n");
647         msg.append("In the context : ");
648         CContext* context = CContext::getCurrent() ;
649         msg.append(context->getId()); msg.append("\n");
650         msg.append(e.what());
651         ERROR("CNc4DataOutput::writeTimeDimension_(void)", << msg);
652       }
653     }
654      //--------------------------------------------------------------
655
656      void CNc4DataOutput::writeField_(CField* field)
657      {
658         CContext* context = CContext::getCurrent() ;
659         CContextServer* server=context->server ;
660
661         std::vector<StdString> dims, coodinates;
662         CGrid* grid = field->grid;
663         if (!grid->doGridHaveDataToWrite())
664          if (SuperClass::type==MULTI_FILE) return ;
665
666         CArray<bool,1> axisDomainOrder = grid->axis_domain_order;
667         int numElement = axisDomainOrder.numElements(), idxDomain = 0, idxAxis = 0;
668         std::vector<StdString> domainList = grid->getDomainList();
669         std::vector<StdString> axisList   = grid->getAxisList();
670
671         StdString timeid  = StdString("time_counter");
672         StdString dimXid,dimYid;
673         std::deque<StdString> dimIdList, dimCoordList;
674         bool hasArea = false;
675         StdString cellMeasures = "area:";
676
677         for (int i = 0; i < numElement; ++i)
678         {
679           if (axisDomainOrder(i))
680           {
681             CDomain* domain = CDomain::get(domainList[idxDomain]);
682             StdString domid = (!domain->name.isEmpty())
683                                 ? domain->name.getValue() : domain->getId();
684             StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
685             switch (domain->type)
686             {
687               case CDomain::type_attr::curvilinear :
688                 dimXid     = StdString("x").append(appendDomid);
689                 dimIdList.push_back(dimXid);
690                 dimYid     = StdString("y").append(appendDomid);
691                 dimIdList.push_back(dimYid);
692                 dimCoordList.push_back(StdString("nav_lon").append(appendDomid));
693                 dimCoordList.push_back(StdString("nav_lat").append(appendDomid));
694                 break ;
695               case CDomain::type_attr::regular :
696                 dimXid     = StdString("lon").append(appendDomid);
697                 dimIdList.push_back(dimXid);
698                 dimYid     = StdString("lat").append(appendDomid);
699                 dimIdList.push_back(dimYid);
700                 break ;
701               case CDomain::type_attr::unstructured :
702                 dimXid     = StdString("cell").append(appendDomid);
703                 dimIdList.push_back(dimXid);
704                 dimCoordList.push_back(StdString("lon").append(appendDomid));
705                 dimCoordList.push_back(StdString("lat").append(appendDomid));
706                 break ;
707            }
708            if (domain->hasArea)
709            {
710              hasArea = true;
711              cellMeasures += " area" + appendDomid;
712            }
713            ++idxDomain;
714           }
715           else
716           {
717             CAxis* axis = CAxis::get(axisList[idxAxis]);
718             StdString axisid = (!axis->name.isEmpty())
719                                ? axis->name.getValue() : axis->getId();
720             dimIdList.push_back(axisid);
721             dimCoordList.push_back(axisid);
722            ++idxAxis;
723           }
724         }
725
726/*
727         StdString lonid_loc = (server->intraCommSize > 1)
728                             ? StdString("lon").append(appendDomid).append("_local")
729                             : lonid;
730         StdString latid_loc = (server->intraCommSize > 1)
731                             ? StdString("lat").append(appendDomid).append("_local")
732                             : latid;
733*/
734         StdString fieldid   = (!field->name.isEmpty())
735                             ? field->name.getValue() : field->getBaseFieldReference()->getId();
736
737//         unsigned int ssize = domain->zoom_ni_loc.getValue() * domain->zoom_nj_loc.getValue();
738//         bool isCurvilinear = (domain->lonvalue.getValue()->size() == ssize);
739//          bool isCurvilinear = domain->isCurvilinear ;
740
741         nc_type type ;
742         if (field->prec.isEmpty()) type =  NC_FLOAT ;
743         else
744         {
745           if (field->prec==2) type = NC_SHORT ;
746           else if (field->prec==4)  type =  NC_FLOAT ;
747           else if (field->prec==8)   type =  NC_DOUBLE ;
748         }
749
750         bool wtime   = !(!field->operation.isEmpty() && field->foperation->timeType() == func::CFunctor::once);
751
752         if (wtime)
753         {
754
755            //StdOStringStream oss;
756           // oss << "time_" << field->operation.getValue()
757           //     << "_" << field->getRelFile()->output_freq.getValue();
758          //oss
759            if (field->foperation->timeType() == func::CFunctor::instant) coodinates.push_back(string("time_instant"));
760            else if (field->foperation->timeType() == func::CFunctor::centered) coodinates.push_back(string("time_centered"));
761            dims.push_back(timeid);
762         }
763
764         while (!dimIdList.empty())
765         {
766           dims.push_back(dimIdList.back());
767           dimIdList.pop_back();
768         }
769
770         while (!dimCoordList.empty())
771         {
772           coodinates.push_back(dimCoordList.back());
773           dimCoordList.pop_back();
774         }
775
776         try
777         {
778           SuperClassWriter::addVariable(fieldid, type, dims);
779
780           if (!field->standard_name.isEmpty())
781              SuperClassWriter::addAttribute
782                 ("standard_name",  field->standard_name.getValue(), &fieldid);
783
784           if (!field->long_name.isEmpty())
785              SuperClassWriter::addAttribute
786                 ("long_name", field->long_name.getValue(), &fieldid);
787
788           if (!field->unit.isEmpty())
789              SuperClassWriter::addAttribute
790                 ("units", field->unit.getValue(), &fieldid);
791
792            if (!field->valid_min.isEmpty())
793              SuperClassWriter::addAttribute
794                 ("valid_min", field->valid_min.getValue(), &fieldid);
795
796           if (!field->valid_max.isEmpty())
797              SuperClassWriter::addAttribute
798                 ("valid_max", field->valid_max.getValue(), &fieldid);
799
800            if (!field->scale_factor.isEmpty())
801              SuperClassWriter::addAttribute
802                 ("scale_factor", field->scale_factor.getValue(), &fieldid);
803
804             if (!field->add_offset.isEmpty())
805              SuperClassWriter::addAttribute
806                 ("add_offset", field->add_offset.getValue(), &fieldid);
807
808           SuperClassWriter::addAttribute
809                 ("online_operation", field->operation.getValue(), &fieldid);
810
811          // write child variables as attributes
812
813
814           vector<CVariable*> listVars = field->getAllVariables() ;
815           for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ;
816
817
818           if (wtime)
819           {
820              CDuration duration = field->freq_op.getValue();
821              duration.solveTimeStep(*context->calendar);
822              StdString freqOpStr = duration.toStringUDUnits();
823              SuperClassWriter::addAttribute("interval_operation", freqOpStr, &fieldid);
824
825              duration = field->getRelFile()->output_freq.getValue();
826              duration.solveTimeStep(*context->calendar);
827              SuperClassWriter::addAttribute("interval_write", duration.toStringUDUnits(), &fieldid);
828
829              StdString cellMethods = coodinates.front() + ": ";
830              if (field->operation.getValue() == "instant") cellMethods += "point";
831              else if (field->operation.getValue() == "average") cellMethods += "mean";
832              else if (field->operation.getValue() == "accumulate") cellMethods += "sum";
833              else cellMethods += field->operation;
834              cellMethods += " (interval: " + freqOpStr + ")";
835              SuperClassWriter::addAttribute("cell_methods", cellMethods, &fieldid);
836           }
837
838           if (hasArea)
839             SuperClassWriter::addAttribute("cell_measures", cellMeasures, &fieldid);
840
841           if (!field->default_value.isEmpty())
842           {
843              double default_value = field->default_value.getValue();
844              float fdefault_value = (float)default_value;
845              if (type == NC_DOUBLE)
846                 SuperClassWriter::setDefaultValue(fieldid, &default_value);
847              else
848                 SuperClassWriter::setDefaultValue(fieldid, &fdefault_value);
849           }
850           else
851              SuperClassWriter::setDefaultValue(fieldid, (double*)NULL);
852
853            if (field->compression_level.isEmpty())
854              field->compression_level = field->file->compression_level.isEmpty() ? 0 : field->file->compression_level;
855            SuperClassWriter::setCompressionLevel(fieldid, field->compression_level);
856
857           {  // Ecriture des coordonnées
858
859              StdString coordstr; //boost::algorithm::join(coodinates, " ")
860              std::vector<StdString>::iterator
861                 itc = coodinates.begin(), endc = coodinates.end();
862
863              for (; itc!= endc; itc++)
864              {
865                 StdString & coord = *itc;
866                 if (itc+1 != endc)
867                       coordstr.append(coord).append(" ");
868                 else  coordstr.append(coord);
869              }
870
871              SuperClassWriter::addAttribute("coordinates", coordstr, &fieldid);
872
873           }
874         }
875         catch (CNetCdfException& e)
876         {
877           StdString msg("On writing field : ");
878           msg.append(fieldid); msg.append("\n");
879           msg.append("In the context : ");
880           msg.append(context->getId()); msg.append("\n");
881           msg.append(e.what());
882           ERROR("CNc4DataOutput::writeField_(CField* field)", << msg);
883         }
884      }
885
886
887//      void CNc4DataOutput::writeField_(CField* field)
888//      {
889//         CContext* context = CContext::getCurrent() ;
890//         CContextServer* server=context->server ;
891//
892//         std::vector<StdString> dims, coodinates;
893//         CGrid* grid = field->grid;
894//         CDomain* domain = grid->domain;
895//
896//         if (domain->isEmpty())
897//           if (SuperClass::type==MULTI_FILE) return ;
898//
899//         StdString timeid    = StdString("time_counter");
900//         StdString domid     = (!domain->name.isEmpty())
901//                             ? domain->name.getValue() : domain->getId();
902//         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
903//
904////         bool isCurvilinear = domain->isCurvilinear ;
905////         bool isCurvilinear = (domain->type == CDomain::type_attr::curvilinear) ;
906//
907//         StdString dimXid,dimYid ;
908//
909//         switch (domain->type)
910//         {
911//           case CDomain::type_attr::curvilinear :
912//             dimXid     = StdString("x").append(appendDomid);
913//             dimYid     = StdString("y").append(appendDomid);
914//             break ;
915//           case CDomain::type_attr::regular :
916//             dimXid     = StdString("lon").append(appendDomid);
917//             dimYid     = StdString("lat").append(appendDomid);
918//             break ;
919//           case CDomain::type_attr::unstructured :
920//             dimXid     = StdString("cell").append(appendDomid);
921//             break ;
922//        }
923//
924///*
925//         StdString lonid_loc = (server->intraCommSize > 1)
926//                             ? StdString("lon").append(appendDomid).append("_local")
927//                             : lonid;
928//         StdString latid_loc = (server->intraCommSize > 1)
929//                             ? StdString("lat").append(appendDomid).append("_local")
930//                             : latid;
931//*/
932//         StdString fieldid   = (!field->name.isEmpty())
933//                             ? field->name.getValue() : field->getBaseFieldReference()->getId();
934//
935////         unsigned int ssize = domain->zoom_ni_loc.getValue() * domain->zoom_nj_loc.getValue();
936////         bool isCurvilinear = (domain->lonvalue.getValue()->size() == ssize);
937////          bool isCurvilinear = domain->isCurvilinear ;
938//
939//         nc_type type ;
940//         if (field->prec.isEmpty()) type =  NC_FLOAT ;
941//         else
942//         {
943//           if (field->prec==2) type = NC_SHORT ;
944//           else if (field->prec==4)  type =  NC_FLOAT ;
945//           else if (field->prec==8)   type =  NC_DOUBLE ;
946//         }
947//
948//         bool wtime   = !(!field->operation.isEmpty() && field->foperation->timeType() == func::CFunctor::once);
949//
950//         if (wtime)
951//         {
952//
953//            //StdOStringStream oss;
954//           // oss << "time_" << field->operation.getValue()
955//           //     << "_" << field->getRelFile()->output_freq.getValue();
956//          //oss
957//            if (field->foperation->timeType() == func::CFunctor::instant) coodinates.push_back(string("time_instant"));
958//            else if (field->foperation->timeType() == func::CFunctor::centered) coodinates.push_back(string("time_centered"));
959//            dims.push_back(timeid);
960//         }
961//
962//         std::vector<StdString> axisList = grid->getAxisList();
963//         if (!axisList.empty())
964//         {
965//           std::vector<StdString>::const_iterator itAxis = axisList.begin(), iteAxis = axisList.end();
966//           for (; itAxis != iteAxis; ++itAxis)
967//           {
968//             CAxis* axis = CAxis::get(*itAxis);
969//             StdString axisid = (!axis->name.isEmpty())
970//                                ? axis->name.getValue() : axis->getId();
971//
972//             dims.push_back(axisid);
973//             coodinates.push_back(axisid);
974//           }
975//         }
976//
977//         switch (domain->type)
978//         {
979//           case CDomain::type_attr::curvilinear :
980//             coodinates.push_back(StdString("nav_lon").append(appendDomid));
981//             coodinates.push_back(StdString("nav_lat").append(appendDomid));
982//             break;
983//           case CDomain::type_attr::regular :
984//           case CDomain::type_attr::unstructured :
985//            coodinates.push_back(StdString("lon").append(appendDomid));
986//            coodinates.push_back(StdString("lat").append(appendDomid));
987//             break;
988//         }
989//
990//         if ( domain->type == CDomain::type_attr::curvilinear || domain->type == CDomain::type_attr::regular)dims.push_back(dimYid);
991//         dims.push_back(dimXid);
992//
993//         try
994//         {
995//           SuperClassWriter::addVariable(fieldid, type, dims);
996//
997//           if (!field->standard_name.isEmpty())
998//              SuperClassWriter::addAttribute
999//                 ("standard_name",  field->standard_name.getValue(), &fieldid);
1000//
1001//           if (!field->long_name.isEmpty())
1002//              SuperClassWriter::addAttribute
1003//                 ("long_name", field->long_name.getValue(), &fieldid);
1004//
1005//           if (!field->unit.isEmpty())
1006//              SuperClassWriter::addAttribute
1007//                 ("units", field->unit.getValue(), &fieldid);
1008//
1009//            if (!field->valid_min.isEmpty())
1010//              SuperClassWriter::addAttribute
1011//                 ("valid_min", field->valid_min.getValue(), &fieldid);
1012//
1013//           if (!field->valid_max.isEmpty())
1014//              SuperClassWriter::addAttribute
1015//                 ("valid_max", field->valid_max.getValue(), &fieldid);
1016//
1017//            if (!field->scale_factor.isEmpty())
1018//              SuperClassWriter::addAttribute
1019//                 ("scale_factor", field->scale_factor.getValue(), &fieldid);
1020//
1021//             if (!field->add_offset.isEmpty())
1022//              SuperClassWriter::addAttribute
1023//                 ("add_offset", field->add_offset.getValue(), &fieldid);
1024//
1025//           SuperClassWriter::addAttribute
1026//                 ("online_operation", field->operation.getValue(), &fieldid);
1027//
1028//          // write child variables as attributes
1029//
1030//
1031//           vector<CVariable*> listVars = field->getAllVariables() ;
1032//           for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ;
1033//
1034//
1035//           if (wtime)
1036//           {
1037//              CDuration duration = field->freq_op.getValue();
1038//              duration.solveTimeStep(*(context->calendar));
1039//              SuperClassWriter::addAttribute("interval_operation", duration.toStringUDUnits(), &fieldid);
1040//
1041//              duration = field->getRelFile()->output_freq.getValue();
1042//              duration.solveTimeStep(*(context->calendar));
1043//              SuperClassWriter::addAttribute("interval_write", duration.toStringUDUnits(), &fieldid);
1044//           }
1045//
1046//           if (!field->default_value.isEmpty())
1047//           {
1048//              double default_value = field->default_value.getValue();
1049//              float fdefault_value = (float)default_value;
1050//              if (type == NC_DOUBLE)
1051//                 SuperClassWriter::setDefaultValue(fieldid, &default_value);
1052//              else
1053//                 SuperClassWriter::setDefaultValue(fieldid, &fdefault_value);
1054//           }
1055//           else
1056//              SuperClassWriter::setDefaultValue(fieldid, (double*)NULL);
1057//
1058//           {  // Ecriture des coordonnées
1059//
1060//              StdString coordstr; //boost::algorithm::join(coodinates, " ")
1061//              std::vector<StdString>::iterator
1062//                 itc = coodinates.begin(), endc = coodinates.end();
1063//
1064//              for (; itc!= endc; itc++)
1065//              {
1066//                 StdString & coord = *itc;
1067//                 if (itc+1 != endc)
1068//                       coordstr.append(coord).append(" ");
1069//                 else  coordstr.append(coord);
1070//              }
1071//
1072//              SuperClassWriter::addAttribute("coordinates", coordstr, &fieldid);
1073//
1074//           }
1075//         }
1076//         catch (CNetCdfException& e)
1077//         {
1078//           StdString msg("On writing field : ");
1079//           msg.append(fieldid); msg.append("\n");
1080//           msg.append("In the context : ");
1081//           msg.append(context->getId()); msg.append("\n");
1082//           msg.append(e.what());
1083//           ERROR("CNc4DataOutput::writeField_(CField* field)", << msg);
1084//         }
1085//      }
1086
1087      //--------------------------------------------------------------
1088
1089      void CNc4DataOutput::writeFile_ (CFile* file)
1090      {
1091         StdString filename = (!file->name.isEmpty())
1092                            ? file->name.getValue() : file->getId();
1093         StdString description = (!file->description.isEmpty())
1094                               ? file->description.getValue()
1095                               : StdString("Created by xios");
1096
1097         singleDomain = (file->nbDomains == 1);
1098
1099         try
1100         {
1101           this->writeFileAttributes(filename, description,
1102                                     StdString("CF-1.1"),
1103                                     StdString("An IPSL model"),
1104                                     this->getTimeStamp());
1105
1106           if (file->nbAxis >= 1)
1107             SuperClassWriter::addDimension("axis_nbounds", 2);
1108         }
1109         catch (CNetCdfException& e)
1110         {
1111           StdString msg("On writing file : ");
1112           msg.append(filename); msg.append("\n");
1113           msg.append("In the context : ");
1114           CContext* context = CContext::getCurrent() ;
1115           msg.append(context->getId()); msg.append("\n");
1116           msg.append(e.what());
1117           ERROR("CNc4DataOutput::writeFile_ (CFile* file)", << msg);
1118         }
1119      }
1120
1121      void CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)
1122      {
1123        string name ;
1124        if (!var->name.isEmpty()) name=var->name ;
1125        else if (var->hasId()) name=var->getId() ;
1126        else return ;
1127
1128        try
1129        {
1130          if (var->type.getValue() == CVariable::type_attr::t_int || var->type.getValue() == CVariable::type_attr::t_int32)
1131            addAttribute(name, var->getData<int>(), &fieldId);
1132          else if (var->type.getValue() == CVariable::type_attr::t_int16)
1133            addAttribute(name, var->getData<short int>(), &fieldId);
1134          else if (var->type.getValue() == CVariable::type_attr::t_float)
1135            addAttribute(name, var->getData<float>(), &fieldId);
1136          else if (var->type.getValue() == CVariable::type_attr::t_double)
1137            addAttribute(name, var->getData<double>(), &fieldId);
1138          else if (var->type.getValue() == CVariable::type_attr::t_string)
1139            addAttribute(name, var->getData<string>(), &fieldId);
1140          else
1141            ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)",
1142                  << "Unsupported variable of type " << var->type.getStringValue());
1143        }
1144       catch (CNetCdfException& e)
1145       {
1146         StdString msg("On writing attributes of variable with name : ");
1147         msg.append(name); msg.append("in the field "); msg.append(fieldId); msg.append("\n");
1148         msg.append("In the context : ");
1149         CContext* context = CContext::getCurrent() ;
1150         msg.append(context->getId()); msg.append("\n");
1151         msg.append(e.what());
1152         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)", << msg);
1153       }
1154     }
1155
1156     void CNc4DataOutput::writeAttribute_ (CVariable* var)
1157     {
1158        string name ;
1159        if (!var->name.isEmpty()) name=var->name ;
1160        else if (var->hasId()) name=var->getId() ;
1161        else return ;
1162        try
1163        {
1164          if (var->type.getValue() == CVariable::type_attr::t_int || var->type.getValue() == CVariable::type_attr::t_int32)
1165            addAttribute(name, var->getData<int>());
1166          else if (var->type.getValue() == CVariable::type_attr::t_int16)
1167            addAttribute(name, var->getData<short int>());
1168          else if (var->type.getValue() == CVariable::type_attr::t_float)
1169            addAttribute(name, var->getData<float>());
1170          else if (var->type.getValue() == CVariable::type_attr::t_double)
1171            addAttribute(name, var->getData<double>());
1172          else if (var->type.getValue() == CVariable::type_attr::t_string)
1173            addAttribute(name, var->getData<string>());
1174          else
1175            ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)",
1176                  << "Unsupported variable of type " << var->type.getStringValue());
1177        }
1178       catch (CNetCdfException& e)
1179       {
1180         StdString msg("On writing attributes of variable with name : ");
1181         msg.append(name); msg.append("\n");
1182         msg.append("In the context : ");
1183         CContext* context = CContext::getCurrent() ;
1184         msg.append(context->getId()); msg.append("\n");
1185         msg.append(e.what());
1186         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)", << msg);
1187       }
1188     }
1189
1190      void CNc4DataOutput::syncFile_ (void)
1191      {
1192        try
1193        {
1194          SuperClassWriter::sync() ;
1195        }
1196        catch (CNetCdfException& e)
1197        {
1198         StdString msg("On synchronizing the write among processes");
1199         msg.append("In the context : ");
1200         CContext* context = CContext::getCurrent() ;
1201         msg.append(context->getId()); msg.append("\n");
1202         msg.append(e.what());
1203         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
1204        }
1205      }
1206
1207      void CNc4DataOutput::closeFile_ (void)
1208      {
1209        try
1210        {
1211          SuperClassWriter::close() ;
1212        }
1213        catch (CNetCdfException& e)
1214        {
1215         StdString msg("On closing file");
1216         msg.append("In the context : ");
1217         CContext* context = CContext::getCurrent() ;
1218         msg.append(context->getId()); msg.append("\n");
1219         msg.append(e.what());
1220         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
1221        }
1222
1223      }
1224
1225      //---------------------------------------------------------------
1226
1227      StdString CNc4DataOutput::getTimeStamp(void) const
1228      {
1229         const int buffer_size = 100;
1230         time_t rawtime;
1231         struct tm * timeinfo = NULL;
1232         char buffer [buffer_size];
1233
1234         time ( &rawtime );
1235         timeinfo = localtime ( &rawtime );
1236         strftime (buffer, buffer_size, "%Y-%b-%d %H:%M:%S %Z", timeinfo);
1237
1238         return (StdString(buffer));
1239      }
1240
1241      //---------------------------------------------------------------
1242
1243      void CNc4DataOutput::writeFieldData_ (CField*  field)
1244      {
1245         CContext* context = CContext::getCurrent() ;
1246//          if (field->getRelFile()->isSyncTime()) SuperClassWriter::sync() ;
1247         CContextServer* server=context->server ;
1248
1249         CGrid* grid = field->grid ;
1250
1251         if (!grid->doGridHaveDataToWrite())
1252          if (SuperClass::type==MULTI_FILE || !isCollective) return ;
1253
1254         StdString fieldid   = (!field->name.isEmpty())
1255                             ? field->name.getValue()
1256                             : field->getBaseFieldReference()->getId();
1257
1258         StdOStringStream oss;
1259         string timeAxisId ;
1260         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisId="time_instant" ;
1261         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisId="time_centered" ;
1262
1263         StdString timeBoundId("time_counter_bounds");
1264
1265         StdString timeAxisBoundId;
1266         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisBoundId="time_instant_bounds" ;
1267         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisBoundId="time_centered_bounds" ;
1268
1269         CArray<double,1> time_data(1) ;
1270         CArray<double,1> time_counter(1) ;
1271         CArray<double,1> time_counter_bound(2);
1272         CArray<double,1> time_data_bound(2);
1273
1274        bool wtime   = !(!field->operation.isEmpty() && (field->foperation->timeType() == func::CFunctor::once));
1275
1276        if (wtime)
1277        {
1278          time_counter(0)= (Time(*field->last_Write_srv) + Time(*field->lastlast_Write_srv)) / 2;
1279          if (field->foperation->timeType() == func::CFunctor::instant)
1280            time_data(0) = Time(*field->last_Write_srv);
1281          else if (field->foperation->timeType() == func::CFunctor::centered) time_data(0) = time_counter(0);
1282
1283          time_counter_bound(0) = Time(*field->lastlast_Write_srv);
1284          time_counter_bound(1) = Time(*field->last_Write_srv);
1285          if (field->foperation->timeType() == func::CFunctor::instant)
1286            time_data_bound(0) = time_data_bound(1) = Time(*field->last_Write_srv);
1287          else if (field->foperation->timeType() == func::CFunctor::centered)
1288          {
1289            time_data_bound(0) = time_counter_bound(0);
1290            time_data_bound(1) = time_counter_bound(1);
1291          }
1292         }
1293
1294         bool isRoot ;
1295         if (server->intraCommRank==0) isRoot=true ;
1296         else isRoot=false ;
1297
1298         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
1299         {
1300           double scaleFactor=1. ;
1301           double addOffset=0. ;
1302           if (!field->scale_factor.isEmpty()) scaleFactor=field->scale_factor ;
1303           if (!field->add_offset.isEmpty()) addOffset=field->add_offset ;
1304           field->scaleFactorAddOffset(scaleFactor,addOffset) ;
1305         }
1306
1307         try
1308         {
1309           CArray<double,1> fieldData(grid->getWrittenDataSize());
1310           if (!field->default_value.isEmpty()) fieldData = field->default_value;
1311           field->outputField(fieldData);
1312           if (!field->prec.isEmpty() && field->prec==2) fieldData=round(fieldData) ;
1313
1314           switch (SuperClass::type)
1315           {
1316              case (MULTI_FILE) :
1317              {
1318                 SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep()-1);
1319                 if (wtime)
1320                 {
1321                   SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep()-1);
1322                   SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep()-1);
1323                   SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1);
1324                   SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1);
1325                 }
1326                 break ;
1327              }
1328              case (ONE_FILE) :
1329              {
1330                std::vector<int> nZoomBeginGlobal = grid->getDistributionServer()->getZoomBeginGlobal();
1331                std::vector<int> nZoomBeginServer = grid->getDistributionServer()->getZoomBeginServer();
1332                std::vector<int> nZoomSizeServer  = grid->getDistributionServer()->getZoomSizeServer();
1333
1334                int ssize = nZoomBeginGlobal.size();
1335
1336                std::vector<StdSize> start(ssize) ;
1337                std::vector<StdSize> count(ssize) ;
1338
1339                for (int i = 0; i < ssize; ++i)
1340                {
1341                  start[i] = nZoomBeginServer[ssize-i-1] - nZoomBeginGlobal[ssize-i-1];
1342                  count[i] = nZoomSizeServer[ssize-i-1];
1343                }
1344
1345                SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep()-1,&start,&count );
1346                if (wtime)
1347                {
1348                  SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot );
1349                  SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot );
1350                  SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot );
1351                  SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot);
1352                }
1353
1354                break;
1355              }
1356            }
1357         }
1358         catch (CNetCdfException& e)
1359         {
1360           StdString msg("On writing field data: ");
1361           msg.append(fieldid); msg.append("\n");
1362           msg.append("In the context : ");
1363           msg.append(context->getId()); msg.append("\n");
1364           msg.append(e.what());
1365           ERROR("CNc4DataOutput::writeFieldData_ (CField*  field)", << msg);
1366         }
1367      }
1368
1369//      //---------------------------------------------------------------
1370//
1371//      void CNc4DataOutput::writeFieldData_ (CField*  field)
1372//      {
1373//         CContext* context = CContext::getCurrent() ;
1374////          if (field->getRelFile()->isSyncTime()) SuperClassWriter::sync() ;
1375//         CContextServer* server=context->server ;
1376//
1377//         CGrid* grid = field->grid ;
1378//         CDomain* domain = grid->domain ;
1379//
1380//         if(SuperClass::type==MULTI_FILE || !isCollective) if (domain->isEmpty()) return;
1381//
1382//
1383//         StdString fieldid   = (!field->name.isEmpty())
1384//                             ? field->name.getValue()
1385//                             : field->getBaseFieldReference()->getId();
1386//
1387//         StdOStringStream oss;
1388//         string timeAxisId ;
1389//         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisId="time_instant" ;
1390//         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisId="time_centered" ;
1391//
1392//         StdString timeBoundId("time_counter_bounds");
1393//
1394//         StdString timeAxisBoundId;
1395//         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisBoundId="time_instant_bounds" ;
1396//         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisBoundId="time_centered_bounds" ;
1397//
1398//         CArray<double,1> time_data(1) ;
1399//         CArray<double,1> time_counter(1) ;
1400//         CArray<double,1> time_counter_bound(2);
1401//         CArray<double,1> time_data_bound(2);
1402//
1403//        bool wtime   = !(!field->operation.isEmpty() && (field->foperation->timeType() == func::CFunctor::once));
1404//
1405//        if (wtime)
1406//        {
1407//          time_counter(0)= (Time(*field->last_Write_srv) + Time(*field->lastlast_Write_srv)) / 2;
1408//          if (field->foperation->timeType() == func::CFunctor::instant)
1409//            time_data(0) = Time(*field->last_Write_srv);
1410//          else if (field->foperation->timeType() == func::CFunctor::centered) time_data(0) = time_counter(0);
1411//
1412//          time_counter_bound(0) = Time(*field->lastlast_Write_srv);
1413//          time_counter_bound(1) = Time(*field->last_Write_srv);
1414//          if (field->foperation->timeType() == func::CFunctor::instant)
1415//            time_data_bound(0) = time_data_bound(1) = Time(*field->last_Write_srv);
1416//          else if (field->foperation->timeType() == func::CFunctor::centered)
1417//          {
1418//            time_data_bound(0) = time_counter_bound(0);
1419//            time_data_bound(1) = time_counter_bound(1);
1420//          }
1421//         }
1422//
1423//         bool isRoot ;
1424//         if (server->intraCommRank==0) isRoot=true ;
1425//         else isRoot=false ;
1426//
1427//         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
1428//         {
1429//           double scaleFactor=1. ;
1430//           double addOffset=0. ;
1431//           if (!field->scale_factor.isEmpty()) scaleFactor=field->scale_factor ;
1432//           if (!field->add_offset.isEmpty()) addOffset=field->add_offset ;
1433//           field->scaleFactorAddOffset(scaleFactor,addOffset) ;
1434//         }
1435//
1436//         try
1437//         {
1438//           if (grid->hasAxis()) // 3D
1439//           {
1440//              CAxis* axis = grid->axis ;
1441//              CArray<double,3> field_data3D(domain->zoom_ni_srv,domain->zoom_nj_srv,axis->zoom_size) ;
1442//              if (!field->default_value.isEmpty()) field_data3D = field->default_value ;
1443//
1444//              field->outputField(field_data3D);
1445//
1446//              if (!field->prec.isEmpty() && field->prec==2) field_data3D=round(field_data3D) ;
1447//
1448//              switch (SuperClass::type)
1449//             {
1450//                case (MULTI_FILE) :
1451//                {
1452//                   SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep()-1);
1453//                   if (wtime)
1454//                   {
1455//                     SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep()-1);
1456//                     SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep()-1);
1457//                     SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1);
1458//                     SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1);
1459//                   }
1460//                   break ;
1461//                }
1462//                case (ONE_FILE) :
1463//                {
1464//                   std::vector<StdSize> start(3) ;
1465//                   std::vector<StdSize> count(3) ;
1466//                   if (domain->isEmpty())
1467//                   {
1468//                     start[0]=0 ; start[1]=0 ; start[2]=0 ;
1469//                     count[0]=0 ; count[1]=0 ; start[2]=0 ;
1470//                   }
1471//                   else
1472//                   {
1473//  //                 start[2]=domain->zoom_ibegin_loc.getValue()-domain->zoom_ibegin.getValue() ; start [1]=domain->zoom_jbegin_loc.getValue()-domain->zoom_jbegin.getValue() ; start[0]=0 ;
1474//                     start[2]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start [1]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ; start[0]=0 ;
1475//                     count[2]=domain->zoom_ni_srv ; count[1]=domain->zoom_nj_srv ; count[0] = axis->zoom_size.getValue();
1476//                   }
1477//                   SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep()-1,&start,&count );
1478//                   if (wtime)
1479//                   {
1480//                     SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot );
1481//                     SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot );
1482//                     SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot );
1483//                     SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot);
1484//                   }
1485//                   break;
1486//                }
1487//              }
1488//
1489//           }
1490//           else // 2D
1491//           {
1492//              CArray<double,2> field_data2D(domain->zoom_ni_srv,domain->zoom_nj_srv) ;
1493//              if (!field->default_value.isEmpty()) field_data2D = field->default_value ;
1494//              field->outputField(field_data2D);
1495//              if (!field->prec.isEmpty() && field->prec==2) field_data2D=round(field_data2D) ;
1496//              switch (SuperClass::type)
1497//              {
1498//                case (MULTI_FILE) :
1499//                {
1500//                  SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep()-1);
1501//                  if (wtime)
1502//                  {
1503//                    SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep()-1);
1504//                    SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep()-1);
1505//                    SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1);
1506//                    SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1);
1507//                  }
1508//                  break;
1509//                }
1510//                case (ONE_FILE) :
1511//                {
1512//                   std::vector<StdSize> start(2) ;
1513//                   std::vector<StdSize> count(2) ;
1514//                   if (domain->isEmpty())
1515//                   {
1516//                     start[0]=0 ; start[1]=0 ;
1517//                     count[0]=0 ; count[1]=0 ;
1518//                   }
1519//                   else
1520//                   {
1521//                     start[1]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
1522//                     count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
1523//                   }
1524//
1525//                   SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep()-1,&start,&count);
1526//                   if (wtime)
1527//                   {
1528//                     SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot);
1529//                     SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot);
1530//                     SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot);
1531//                     SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot);
1532//                   }
1533//                   break;
1534//
1535//                }
1536//              }
1537//           }
1538//         }
1539//         catch (CNetCdfException& e)
1540//         {
1541//           StdString msg("On writing field data: ");
1542//           msg.append(fieldid); msg.append("\n");
1543//           msg.append("In the context : ");
1544//           msg.append(context->getId()); msg.append("\n");
1545//           msg.append(e.what());
1546//           ERROR("CNc4DataOutput::writeFieldData_ (CField*  field)", << msg);
1547//         }
1548//      }
1549
1550      //---------------------------------------------------------------
1551
1552      void CNc4DataOutput::writeTimeAxis_
1553                  (CField*    field,
1554                   const boost::shared_ptr<CCalendar> cal)
1555      {
1556         StdOStringStream oss;
1557
1558//         if (field->operation.getValue().compare("once") == 0) return ;
1559         if (field->foperation->timeType() == func::CFunctor::once) return ;
1560
1561//         oss << "time_" << field->operation.getValue()
1562//             << "_" << field->getRelFile()->output_freq.getValue();
1563
1564//         StdString axisid = oss.str();
1565//         if (field->foperation->timeType() == func::CFunctor::centered) axisid="time_centered" ;
1566//         else if (field->foperation->timeType() == func::CFunctor::instant) axisid="time_instant" ;
1567
1568         StdString axisid("time_centered") ;
1569         StdString axisBoundId("time_centered_bounds");
1570         StdString timeid("time_counter");
1571         StdString timeBoundId("time_bounds");
1572
1573         if (field->foperation->timeType() == func::CFunctor::instant)
1574         {
1575            axisid = "time_instant";
1576            axisBoundId = "time_instant_bounds";
1577         }
1578
1579         try
1580         {
1581          // Adding time_instant or time_centered
1582           std::vector<StdString> dims;
1583           dims.push_back(timeid);
1584           if (!SuperClassWriter::varExist(axisid))
1585           {
1586              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1587
1588              CDate timeOrigin=cal->getTimeOrigin() ;
1589              StdOStringStream oss2;
1590  //            oss2<<initDate.getYear()<<"-"<<initDate.getMonth()<<"-"<<initDate.getDay()<<" "
1591  //                <<initDate.getHour()<<"-"<<initDate.getMinute()<<"-"<<initDate.getSecond() ;
1592              StdString strInitdate=oss2.str() ;
1593              StdString strTimeOrigin=timeOrigin.toString() ;
1594              this->writeTimeAxisAttributes
1595                 (axisid, cal->getType(),
1596                  StdString("seconds since ").append(strTimeOrigin),
1597                  strTimeOrigin, axisBoundId);
1598           }
1599
1600           // Adding time_instant_bounds or time_centered_bounds variables
1601           if (!SuperClassWriter::varExist(axisBoundId))
1602           {
1603              dims.clear() ;
1604              dims.push_back(timeid);
1605              dims.push_back(timeBoundId);
1606              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1607           }
1608
1609           // Adding time_counter
1610           axisid = "time_counter" ;
1611           axisBoundId = "time_counter_bounds" ;
1612           dims.clear() ;
1613           dims.push_back(timeid);
1614           if (!SuperClassWriter::varExist(axisid))
1615           {
1616              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1617              SuperClassWriter::addAttribute("axis", string("T"), &axisid);
1618              CDate timeOrigin=cal->getTimeOrigin() ;
1619              StdString strTimeOrigin=timeOrigin.toString() ;
1620
1621              this->writeTimeAxisAttributes
1622                 (axisid, cal->getType(),
1623                  StdString("seconds since ").append(strTimeOrigin),
1624                  strTimeOrigin, axisBoundId);
1625           }
1626
1627           // Adding time_counter_bound dimension
1628           if (!SuperClassWriter::varExist(axisBoundId))
1629           {
1630              dims.clear();
1631              dims.push_back(timeid);
1632              dims.push_back(timeBoundId);
1633              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1634           }
1635         }
1636         catch (CNetCdfException& e)
1637         {
1638           StdString msg("On writing time axis data: ");
1639           msg.append("In the context : ");
1640           CContext* context = CContext::getCurrent() ;
1641           msg.append(context->getId()); msg.append("\n");
1642           msg.append(e.what());
1643           ERROR("CNc4DataOutput::writeTimeAxis_ (CField*    field, \
1644                  const boost::shared_ptr<CCalendar> cal)", << msg);
1645         }
1646      }
1647
1648      //---------------------------------------------------------------
1649
1650      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
1651                                                   const StdString & calendar,
1652                                                   const StdString & units,
1653                                                   const StdString & time_origin,
1654                                                   const StdString & time_bounds,
1655                                                   const StdString & standard_name,
1656                                                   const StdString & long_name)
1657      {
1658         try
1659         {
1660           SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1661           SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
1662           SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
1663           SuperClassWriter::addAttribute("units",         units        , &axis_name);
1664           SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
1665           SuperClassWriter::addAttribute("bounds",        time_bounds  , &axis_name);
1666         }
1667         catch (CNetCdfException& e)
1668         {
1669           StdString msg("On writing time axis Attribute: ");
1670           msg.append("In the context : ");
1671           CContext* context = CContext::getCurrent() ;
1672           msg.append(context->getId()); msg.append("\n");
1673           msg.append(e.what());
1674           ERROR("CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name, \
1675                                                          const StdString & calendar,\
1676                                                          const StdString & units, \
1677                                                          const StdString & time_origin, \
1678                                                          const StdString & time_bounds, \
1679                                                          const StdString & standard_name, \
1680                                                          const StdString & long_name)", << msg);
1681         }
1682      }
1683
1684      //---------------------------------------------------------------
1685
1686      void CNc4DataOutput::writeAxisAttributes(const StdString & axis_name,
1687                                               const StdString & axis,
1688                                               const StdString & standard_name,
1689                                               const StdString & long_name,
1690                                               const StdString & units,
1691                                               const StdString & nav_model)
1692      {
1693         try
1694         {
1695          if (!axis.empty())
1696            SuperClassWriter::addAttribute("axis"       , axis         , &axis_name);
1697
1698          SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1699          SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
1700          SuperClassWriter::addAttribute("units"        , units        , &axis_name);
1701          SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
1702         }
1703         catch (CNetCdfException& e)
1704         {
1705           StdString msg("On writing Axis Attribute: ");
1706           msg.append("In the context : ");
1707           CContext* context = CContext::getCurrent() ;
1708           msg.append(context->getId()); msg.append("\n");
1709           msg.append(e.what());
1710           ERROR("CNc4DataOutput::writeAxisAttributes(const StdString & axis_name, \
1711                                                      const StdString & axis, \
1712                                                      const StdString & standard_name, \
1713                                                      const StdString & long_name, \
1714                                                      const StdString & units, \
1715                                                      const StdString & nav_model)", << msg);
1716         }
1717      }
1718
1719      //---------------------------------------------------------------
1720
1721      void CNc4DataOutput::writeLocalAttributes
1722         (int ibegin, int ni, int jbegin, int nj, StdString domid)
1723      {
1724        try
1725        {
1726         SuperClassWriter::addAttribute(StdString("ibegin").append(domid), ibegin);
1727         SuperClassWriter::addAttribute(StdString("ni"    ).append(domid), ni);
1728         SuperClassWriter::addAttribute(StdString("jbegin").append(domid), jbegin);
1729         SuperClassWriter::addAttribute(StdString("nj"    ).append(domid), nj);
1730        }
1731        catch (CNetCdfException& e)
1732        {
1733           StdString msg("On writing Local Attributes: ");
1734           msg.append("In the context : ");
1735           CContext* context = CContext::getCurrent() ;
1736           msg.append(context->getId()); msg.append("\n");
1737           msg.append(e.what());
1738           ERROR("CNc4DataOutput::writeLocalAttributes \
1739                  (int ibegin, int ni, int jbegin, int nj, StdString domid)", << msg);
1740        }
1741
1742      }
1743
1744     void CNc4DataOutput::writeLocalAttributes_IOIPSL
1745         (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)
1746      {
1747         CArray<int,1> array(2) ;
1748
1749         try
1750         {
1751           SuperClassWriter::addAttribute("DOMAIN_number_total",size ) ;
1752           SuperClassWriter::addAttribute("DOMAIN_number", rank) ;
1753           array=1,2 ;
1754           SuperClassWriter::addAttribute("DOMAIN_dimensions_ids",array) ;
1755           array=ni_glo,nj_glo ;
1756           SuperClassWriter::addAttribute("DOMAIN_size_global", array) ;
1757           array=ni,nj ;
1758           SuperClassWriter::addAttribute("DOMAIN_size_local", array) ;
1759           array=ibegin,jbegin ;
1760           SuperClassWriter::addAttribute("DOMAIN_position_first", array) ;
1761           array=ibegin+ni-1,jbegin+nj-1 ;
1762           SuperClassWriter::addAttribute("DOMAIN_position_last",array) ;
1763           array=0,0 ;
1764           SuperClassWriter::addAttribute("DOMAIN_halo_size_start", array) ;
1765           SuperClassWriter::addAttribute("DOMAIN_halo_size_end", array);
1766           SuperClassWriter::addAttribute("DOMAIN_type",string("box")) ;
1767  /*
1768           SuperClassWriter::addAttribute("DOMAIN_DIM_N001",string("x")) ;
1769           SuperClassWriter::addAttribute("DOMAIN_DIM_N002",string("y")) ;
1770           SuperClassWriter::addAttribute("DOMAIN_DIM_N003",string("axis_A")) ;
1771           SuperClassWriter::addAttribute("DOMAIN_DIM_N004",string("time_counter")) ;
1772  */
1773         }
1774         catch (CNetCdfException& e)
1775         {
1776           StdString msg("On writing Local Attributes IOI PSL \n");
1777           msg.append("In the context : ");
1778           CContext* context = CContext::getCurrent() ;
1779           msg.append(context->getId()); msg.append("\n");
1780           msg.append(e.what());
1781           ERROR("CNc4DataOutput::writeLocalAttributes_IOIPSL \
1782                  (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)", << msg);
1783         }
1784      }
1785      //---------------------------------------------------------------
1786
1787      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
1788                                                const StdString & description,
1789                                                const StdString & conventions,
1790                                                const StdString & production,
1791                                                const StdString & timeStamp)
1792      {
1793         try
1794         {
1795           SuperClassWriter::addAttribute("name"       , name);
1796           SuperClassWriter::addAttribute("description", description);
1797           SuperClassWriter::addAttribute("title"      , description);
1798           SuperClassWriter::addAttribute("Conventions", conventions);
1799           SuperClassWriter::addAttribute("production" , production);
1800           SuperClassWriter::addAttribute("timeStamp"  , timeStamp);
1801         }
1802         catch (CNetCdfException& e)
1803         {
1804           StdString msg("On writing File Attributes \n ");
1805           msg.append("In the context : ");
1806           CContext* context = CContext::getCurrent() ;
1807           msg.append(context->getId()); msg.append("\n");
1808           msg.append(e.what());
1809           ERROR("CNc4DataOutput:: writeFileAttributes(const StdString & name, \
1810                                                const StdString & description, \
1811                                                const StdString & conventions, \
1812                                                const StdString & production, \
1813                                                const StdString & timeStamp)", << msg);
1814         }
1815      }
1816
1817      //---------------------------------------------------------------
1818
1819      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
1820                                               int data_dim,
1821                                               int data_ni,
1822                                               int data_nj,
1823                                               int data_ibegin,
1824                                               int data_jbegin)
1825      {
1826         try
1827         {
1828           SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
1829           SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
1830           SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
1831           SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
1832           SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
1833         }
1834         catch (CNetCdfException& e)
1835         {
1836           StdString msg("On writing Mask Attributes \n ");
1837           msg.append("In the context : ");
1838           CContext* context = CContext::getCurrent() ;
1839           msg.append(context->getId()); msg.append("\n");
1840           msg.append(e.what());
1841           ERROR("CNc4DataOutput::writeMaskAttributes(const StdString & mask_name, \
1842                                               int data_dim, \
1843                                               int data_ni, \
1844                                               int data_nj, \
1845                                               int data_ibegin, \
1846                                               int data_jbegin)", << msg);
1847         }
1848      }
1849
1850      ///--------------------------------------------------------------
1851
1852} // namespace xios
Note: See TracBrowser for help on using the repository browser.