source: XIOS/branchs/xios-1.0/src/output/nc4_data_output.cpp @ 612

Last change on this file since 612 was 612, checked in by rlacroix, 6 years ago

Improve CF compliance: Write the "cell_methods" metadata.

Also try to use the time units defined by the UDUnits specification.

  • 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: 63.3 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, MPI_Comm comm_file,bool multifile, bool isCollective)
32            : SuperClass()
33            , SuperClassWriter(filename, exist, &comm_file,multifile)
34            , comm_file(comm_file)
35            , filename(filename)
36            , isCollective(isCollective)
37      {
38         StdString timeid = StdString("time_counter");
39
40         SuperClass::type = (multifile) ? MULTI_FILE : ONE_FILE;
41
42 //        if (!exist)
43//            SuperClassWriter::addDimension(timeid);
44      }
45
46
47      CNc4DataOutput::~CNc4DataOutput(void)
48      { /* Ne rien faire de plus */ }
49
50      ///--------------------------------------------------------------
51
52      const StdString & CNc4DataOutput::getFileName(void) const
53      {
54         return (this->filename);
55      }
56
57      //---------------------------------------------------------------
58
59      void CNc4DataOutput::writeDomain_(CDomain* domain)
60      {
61         if (domain->type == CDomain::type_attr::unstructured)
62         {
63           writeUnstructuredDomain(domain) ;
64           return ;
65         }
66
67         CContext* context = CContext::getCurrent() ;
68         CContextServer* server=context->server ;
69
70         if (domain->IsWritten(this->filename)) return;
71         domain->checkAttributes();
72
73         if (domain->isEmpty())
74           if (SuperClass::type==MULTI_FILE) return ;
75
76         std::vector<StdString> dim0, dim1;
77         StdString domid     = (!domain->name.isEmpty())
78                             ? domain->name.getValue() : domain->getId();
79         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
80
81
82         StdString dimXid, dimYid ;
83
84         switch (domain->type)
85         {
86           case CDomain::type_attr::curvilinear :
87             dimXid     = StdString("x").append(appendDomid);
88             dimYid     = StdString("y").append(appendDomid);
89             break ;
90           case CDomain::type_attr::regular :
91             dimXid     = StdString("lon").append(appendDomid);
92             dimYid     = StdString("lat").append(appendDomid);
93             break;
94           case CDomain::type_attr::unstructured :
95             dimXid     = StdString("cell").append(appendDomid);
96             break;
97         }
98
99         string lonid,latid,bounds_lonid,bounds_latid ;
100         string areaId = "area" + appendDomid;
101/*
102         StdString lonid_loc = (server->intraCommSize > 1)
103                             ? StdString("lon").append(appendDomid).append("_local")
104                             : lonid;
105         StdString latid_loc = (server->intraCommSize > 1)
106                             ? StdString("lat").append(appendDomid).append("_local")
107                             : latid;
108*/
109
110         try
111         {
112           switch (SuperClass::type)
113           {
114              case (MULTI_FILE) :
115              {
116  //               if (domain->isEmpty()) return;
117
118                 if (server->intraCommSize > 1)
119                 {
120  //                 SuperClassWriter::addDimension(lonid, domain->zoom_ni.getValue());
121  //                 SuperClassWriter::addDimension(latid, domain->zoom_nj.getValue());
122                 }
123
124                 switch (domain->type)
125                 {
126                   case CDomain::type_attr::curvilinear :
127                     dim0.push_back(dimYid); dim0.push_back(dimXid);
128                     lonid = StdString("nav_lon").append(appendDomid);
129                     latid = StdString("nav_lat").append(appendDomid);
130                     break ;
131                   case CDomain::type_attr::regular :
132                     lonid = StdString("lon").append(appendDomid);
133                     latid = StdString("lat").append(appendDomid);
134                     dim0.push_back(dimYid);
135                     dim1.push_back(dimXid);
136                     break;
137                   case CDomain::type_attr::unstructured :
138                     lonid = StdString("lon").append(appendDomid);
139                     latid = StdString("lat").append(appendDomid);
140                     bounds_lonid=string("bounds_lon").append(appendDomid);
141                     bounds_latid=string("bounds_lat").append(appendDomid);
142                     dim0.push_back(dimXid);
143                     break;
144                 }
145
146                 if (domain->type == CDomain::type_attr::unstructured)
147                 {
148                   SuperClassWriter::addDimension(dimXid, domain->nj_glo);
149                 }
150                 else
151                 {
152                   SuperClassWriter::addDimension(dimXid, domain->zoom_ni_srv);
153                   SuperClassWriter::addDimension(dimYid, domain->zoom_nj_srv);
154                 }
155
156                 if (server->intraCommSize > 1)
157                 {
158                    if (domain->type != CDomain::type_attr::unstructured)
159                    {
160                      this->writeLocalAttributes(domain->zoom_ibegin_srv,
161                                                 domain->zoom_ni_srv,
162                                                 domain->zoom_jbegin_srv,
163                                                 domain->zoom_nj_srv,
164                                                 appendDomid);
165
166                      if (singleDomain) this->writeLocalAttributes_IOIPSL(domain->zoom_ibegin_srv,
167                                                 domain->zoom_ni_srv,
168                                                 domain->zoom_jbegin_srv,
169                                                 domain->zoom_nj_srv,
170                                                 domain->ni_glo,domain->nj_glo,
171                                                 server->intraCommRank,server->intraCommSize);
172                   }
173                 }
174
175                 switch (domain->type)
176                 {
177                   case CDomain::type_attr::curvilinear :
178                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
179                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
180                     break ;
181                    case CDomain::type_attr::regular :
182                      SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
183                      SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
184                      break ;
185                    case CDomain::type_attr::unstructured :
186                      SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
187                      SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
188                 }
189
190                 this->writeAxisAttributes(lonid, "X", "longitude", "Longitude", "degrees_east", domid);
191                 this->writeAxisAttributes(latid, "Y", "latitude", "Latitude", "degrees_north", domid);
192
193                 dim0.clear();
194                 if (domain->type != CDomain::type_attr::unstructured) dim0.push_back(dimYid);
195                 dim0.push_back(dimXid);
196
197
198  // supress mask               if (server->intraCommSize > 1)
199  // supress mask               {
200  // supress mask                  SuperClassWriter::addVariable(maskid, NC_INT, dim0);
201  // supress mask
202  // supress mask                  this->writeMaskAttributes(maskid,
203  // supress mask                     domain->data_dim.getValue()/*,
204  // supress mask                     domain->data_ni.getValue(),
205  // supress mask                     domain->data_nj.getValue(),
206  // supress mask                     domain->data_ibegin.getValue(),
207  // supress mask                     domain->data_jbegin.getValue()*/);
208  // supress mask               }
209
210                 //SuperClassWriter::setDefaultValue(maskid, &dvm);
211
212                 if (domain->hasArea)
213                 {
214                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
215                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
216                 }
217
218                 SuperClassWriter::definition_end();
219
220                 switch (domain->type)
221                 {
222                   case CDomain::type_attr::curvilinear :
223                     SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0);
224                     SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0);
225                     break;
226                   case CDomain::type_attr::regular :
227                     CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;
228                     SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0);
229                     CArray<double,1> lon=domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;
230                     SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0);
231                     break;
232                 }
233
234                 if (domain->hasArea)
235                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0);
236
237                 SuperClassWriter::definition_start();
238
239                 break;
240              }
241              case (ONE_FILE) :
242              {
243                 SuperClassWriter::addDimension(dimXid, domain->zoom_ni.getValue());
244                 SuperClassWriter::addDimension(dimYid, domain->zoom_nj.getValue());
245
246                 switch (domain->type)
247                 {
248                   case CDomain::type_attr::curvilinear :
249                     dim0.push_back(dimYid); dim0.push_back(dimXid);
250                     lonid = StdString("nav_lon").append(appendDomid);
251                     latid = StdString("nav_lat").append(appendDomid);
252                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
253                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
254                     break;
255
256                   case CDomain::type_attr::regular :
257                     dim0.push_back(dimYid);
258                     dim1.push_back(dimXid);
259                     lonid = StdString("lon").append(appendDomid);
260                     latid = StdString("lat").append(appendDomid);
261                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
262                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
263                     break;
264                 }
265
266                 if (domain->hasArea)
267                 {
268                   dim0.clear();
269                   dim0.push_back(dimYid); dim0.push_back(dimXid);
270                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
271                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
272                   dim0.clear();
273                 }
274
275                 this->writeAxisAttributes
276                    (lonid, "X", "longitude", "Longitude", "degrees_east", domid);
277                 this->writeAxisAttributes
278                    (latid, "Y", "latitude", "Latitude", "degrees_north", domid);
279
280                 SuperClassWriter::definition_end();
281
282                 switch (domain->type)
283                 {
284                   case CDomain::type_attr::curvilinear :
285                   {
286                     std::vector<StdSize> start(2) ;
287                     std::vector<StdSize> count(2) ;
288                     if (domain->isEmpty())
289                     {
290                       start[0]=0 ; start[1]=0 ;
291                       count[0]=0 ; count[1]=0 ;
292                     }
293                     else
294                     {
295                       start[1]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start [0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
296                       count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
297                     }
298
299                     SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
300                     SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
301                     break;
302                   }
303                   case CDomain::type_attr::regular :
304                   {
305                     std::vector<StdSize> start(1) ;
306                     std::vector<StdSize> count(1) ;
307                     if (domain->isEmpty())
308                     {
309                       start[0]=0 ;
310                       count[0]=0 ;
311                       SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
312                       SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);                 }
313                     else
314                     {
315                       start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
316                       count[0]=domain->zoom_nj_srv ;
317                       CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;
318                       SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0,&start,&count);
319
320                       start[0]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ;
321                       count[0]=domain->zoom_ni_srv ;
322                       CArray<double,1> lon=domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;
323                       SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0,&start,&count);
324                     }
325                     break;
326                   }
327                 }
328
329                 if (domain->hasArea)
330                 {
331                   std::vector<StdSize> start(2);
332                   std::vector<StdSize> count(2);
333
334                   if (domain->isEmpty())
335                   {
336                     start[0] = 0; start[1] = 0;
337                     count[0] = 0; count[1] = 0;
338                   }
339                   else
340                   {
341                     start[1] = domain->zoom_ibegin_srv - domain->zoom_ibegin.getValue();
342                     start[0] = domain->zoom_jbegin_srv - domain->zoom_jbegin.getValue();
343                     count[1] = domain->zoom_ni_srv;
344                     count[0] = domain->zoom_nj_srv;
345                   }
346
347                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0, &start, &count);
348                 }
349
350                 SuperClassWriter::definition_start();
351
352                 break;
353              }
354              default :
355                 ERROR("CNc4DataOutput::writeDomain(domain)",
356                       << "[ type = " << SuperClass::type << "]"
357                       << " not implemented yet !");
358           }
359         }
360         catch (CNetCdfException& e)
361         {
362           StdString msg("On writing the domain : ");
363           msg.append(domid); msg.append("\n");
364           msg.append("In the context : ");
365           msg.append(context->getId()); msg.append("\n");
366           msg.append(e.what());
367           ERROR("CNc4DataOutput::writeDomain_(CDomain* domain)", << msg);
368         }
369
370         domain->addRelFile(this->filename);
371      }
372
373      void CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)
374      {
375         CContext* context = CContext::getCurrent() ;
376         CContextServer* server=context->server ;
377
378         if (domain->IsWritten(this->filename)) return;
379         domain->checkAttributes();
380
381         if (domain->isEmpty())
382           if (SuperClass::type==MULTI_FILE) return ;
383
384         std::vector<StdString> dim0, dim1;
385         StdString domid     = (!domain->name.isEmpty())
386                             ? domain->name.getValue() : domain->getId();
387         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
388
389
390         StdString dimXid = StdString("cell").append(appendDomid);
391         StdString dimVertId = StdString("nvertex").append(appendDomid);
392
393         string lonid,latid,bounds_lonid,bounds_latid ;
394         string areaId = "area" + appendDomid;
395
396         try
397         {
398           switch (SuperClass::type)
399           {
400              case (MULTI_FILE) :
401              {
402                 lonid = StdString("lon").append(appendDomid);
403                 latid = StdString("lat").append(appendDomid);
404                 dim0.push_back(dimXid);
405
406                 SuperClassWriter::addDimension(dimXid, domain->zoom_nj_srv);
407                 SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
408                 SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
409
410                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
411                 bounds_latid = StdString("bounds_lat").append(appendDomid);
412
413
414                 this->writeAxisAttributes(lonid, "X", "longitude", "Longitude", "degrees_east", domid);
415                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
416                 this->writeAxisAttributes(latid, "Y", "latitude", "Latitude", "degrees_north", domid);
417                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
418                 if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
419                 dim0.clear();
420                 if (domain->hasBounds)
421                 {
422                   dim0.push_back(dimXid);
423                   dim0.push_back(dimVertId);
424                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
425                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
426                 }
427
428                 dim0.clear();
429                 dim0.push_back(dimXid);
430
431                 if (domain->hasArea)
432                 {
433                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
434                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
435                 }
436
437                 SuperClassWriter::definition_end();
438
439                 SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0);
440                 SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0);
441
442                 if (domain->hasBounds)
443                 {
444                   SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0);
445                   SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0);
446                 }
447
448                 if (domain->hasArea)
449                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0);
450
451                 SuperClassWriter::definition_start();
452                 break ;
453              }
454
455              case (ONE_FILE) :
456              {
457                 lonid = StdString("lon").append(appendDomid);
458                 latid = StdString("lat").append(appendDomid);
459                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
460                 bounds_latid = StdString("bounds_lat").append(appendDomid);
461                 dim0.push_back(dimXid);
462                 SuperClassWriter::addDimension(dimXid, domain->nj_glo);
463                 SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
464                 SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
465                 this->writeAxisAttributes(lonid, "X", "longitude", "Longitude", "degrees_east", domid);
466                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
467                 this->writeAxisAttributes(latid, "Y", "latitude", "Latitude", "degrees_north", domid);
468                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
469                 if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
470                 dim0.clear();
471
472                 if (domain->hasBounds)
473                 {
474                   dim0.push_back(dimXid);
475                   dim0.push_back(dimVertId);
476                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
477                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
478                 }
479
480                 if (domain->hasArea)
481                 {
482                   dim0.clear();
483                   dim0.push_back(dimXid);
484                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
485                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
486                 }
487
488                 SuperClassWriter::definition_end();
489
490                 std::vector<StdSize> start(1), startBounds(2) ;
491                 std::vector<StdSize> count(1), countBounds(2) ;
492                 if (domain->isEmpty())
493                 {
494                   start[0]=0 ;
495                   count[0]=0 ;
496                   startBounds[1]=0 ;
497                   countBounds[1]=domain->nvertex ;
498                   startBounds[0]=0 ;
499                   countBounds[0]=0 ;
500                 }
501                 else
502                 {
503                   start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin ;
504                   count[0]=domain->zoom_nj_srv ;
505                   startBounds[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin ;
506                   startBounds[1]=0 ;
507                   countBounds[0]=domain->zoom_nj_srv ;
508                   countBounds[1]=domain->nvertex ;
509                 }
510                 SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
511                 SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
512                 if (domain->hasBounds)
513                 {
514                   SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0,&startBounds,&countBounds);
515                   SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0,&startBounds,&countBounds);
516                 }
517
518                 if (domain->hasArea)
519                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0, &start, &count);
520
521                 SuperClassWriter::definition_start();
522
523                 break;
524              }
525              default :
526                 ERROR("CNc4DataOutput::writeDomain(domain)",
527                       << "[ type = " << SuperClass::type << "]"
528                       << " not implemented yet !");
529           }
530         }
531         catch (CNetCdfException& e)
532         {
533           StdString msg("On writing the domain : ");
534           msg.append(domid); msg.append("\n");
535           msg.append("In the context : ");
536           msg.append(context->getId()); msg.append("\n");
537           msg.append(e.what());
538           ERROR("CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)", << msg);
539         }
540         domain->addRelFile(this->filename);
541      }
542      //--------------------------------------------------------------
543
544      void CNc4DataOutput::writeAxis_(CAxis* axis)
545      {
546         if (axis->IsWritten(this->filename)) return;
547         axis->checkAttributes();
548         int zoom_size = axis->zoom_size.getValue();
549         int zoom_begin = axis->zoom_begin.getValue() - 1;
550
551
552         std::vector<StdString> dims;
553         StdString axisid = (!axis->name.isEmpty())
554                           ? axis->name.getValue() : axis->getId();
555         try
556         {
557           SuperClassWriter::addDimension(axisid, zoom_size);
558           dims.push_back(axisid);
559
560           switch (SuperClass::type)
561           {
562              case (MULTI_FILE ) :
563              {}
564              case (ONE_FILE) :
565              {
566                 SuperClassWriter::addVariable(axisid, NC_FLOAT, dims);
567
568                 SuperClassWriter::addAttribute("axis", StdString("Z"), &axisid);
569
570                 if (!axis->standard_name.isEmpty())
571                    SuperClassWriter::addAttribute
572                       ("standard_name",  axis->standard_name.getValue(), &axisid);
573
574                 if (!axis->long_name.isEmpty())
575                    SuperClassWriter::addAttribute
576                       ("long_name", axis->long_name.getValue(), &axisid);
577
578                 if (!axis->unit.isEmpty())
579                    SuperClassWriter::addAttribute
580                       ("units", axis->unit.getValue(), &axisid);
581
582                 if (!axis->positive.isEmpty())
583                   if (axis->positive==CAxis::positive_attr::up) SuperClassWriter::addAttribute("positive", string("up"), &axisid);
584                   else SuperClassWriter::addAttribute("positive", string("down"), &axisid);
585
586                 StdString axisBoundsId = axisid + "_bounds";
587                 if (!axis->bounds.isEmpty())
588                 {
589                   dims.push_back("axis_nbounds");
590                   SuperClassWriter::addVariable(axisBoundsId, NC_FLOAT, dims);
591                   SuperClassWriter::addAttribute("bounds", axisBoundsId, &axisid);
592                 }
593
594                 SuperClassWriter::definition_end();
595
596                 CArray<double,1> axis_value(zoom_size);
597                 for(int i = 0 ; i < zoom_size; i++) axis_value(i) = axis->value(i+zoom_begin);
598                 SuperClassWriter::writeData(axis_value, axisid, isCollective, 0);
599
600                 if (!axis->bounds.isEmpty())
601                 {
602                   CArray<double,2> axisBounds(zoom_size, 2);
603                   for (int i = 0; i < zoom_size; i++)
604                   {
605                     axisBounds(i, 0) = axis->bounds(i + zoom_begin, 0);
606                     axisBounds(i, 1) = axis->bounds(i + zoom_begin, 1);
607                   }
608                   SuperClassWriter::writeData(axisBounds, axisBoundsId, isCollective, 0);
609                 }
610
611                 SuperClassWriter::definition_start();
612
613                 break;
614              }
615              default :
616                 ERROR("CNc4DataOutput::writeDomain(domain)",
617                       << "[ type = " << SuperClass::type << "]"
618                       << " not implemented yet !");
619           }
620         }
621         catch (CNetCdfException& e)
622         {
623           StdString msg("On writing the axis : ");
624           msg.append(axisid); msg.append("\n");
625           msg.append("In the context : ");
626           CContext* context = CContext::getCurrent() ;
627           msg.append(context->getId()); msg.append("\n");
628           msg.append(e.what());
629           ERROR("CNc4DataOutput::writeAxis_(CAxis* axis)", << msg);
630         }
631         axis->addRelFile(this->filename);
632     }
633
634     void CNc4DataOutput::writeTimeDimension_(void)
635     {
636       try
637       {
638        SuperClassWriter::addDimension("time_counter");
639        SuperClassWriter::addDimension("time_bounds", 2);
640       }
641       catch (CNetCdfException& e)
642       {
643         StdString msg("On writing time dimension : time_couter, time_bounds \n");
644         msg.append("In the context : ");
645         CContext* context = CContext::getCurrent() ;
646         msg.append(context->getId()); msg.append("\n");
647         msg.append(e.what());
648         ERROR("CNc4DataOutput::writeTimeDimension_(void)", << msg);
649       }
650     }
651      //--------------------------------------------------------------
652
653      void CNc4DataOutput::writeField_(CField* field)
654      {
655         CContext* context = CContext::getCurrent() ;
656         CContextServer* server=context->server ;
657
658         std::vector<StdString> dims, coodinates;
659         CGrid* grid = field->grid;
660         CDomain* domain = grid->domain;
661
662         if (domain->isEmpty())
663           if (SuperClass::type==MULTI_FILE) return ;
664
665         StdString timeid    = StdString("time_counter");
666         StdString domid     = (!domain->name.isEmpty())
667                             ? domain->name.getValue() : domain->getId();
668         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
669
670//         bool isCurvilinear = domain->isCurvilinear ;
671//         bool isCurvilinear = (domain->type == CDomain::type_attr::curvilinear) ;
672
673         StdString dimXid,dimYid ;
674
675         switch (domain->type)
676         {
677           case CDomain::type_attr::curvilinear :
678             dimXid     = StdString("x").append(appendDomid);
679             dimYid     = StdString("y").append(appendDomid);
680             break ;
681           case CDomain::type_attr::regular :
682             dimXid     = StdString("lon").append(appendDomid);
683             dimYid     = StdString("lat").append(appendDomid);
684             break ;
685           case CDomain::type_attr::unstructured :
686             dimXid     = StdString("cell").append(appendDomid);
687             break ;
688        }
689
690/*
691         StdString lonid_loc = (server->intraCommSize > 1)
692                             ? StdString("lon").append(appendDomid).append("_local")
693                             : lonid;
694         StdString latid_loc = (server->intraCommSize > 1)
695                             ? StdString("lat").append(appendDomid).append("_local")
696                             : latid;
697*/
698         StdString fieldid   = (!field->name.isEmpty())
699                             ? field->name.getValue() : field->getBaseFieldReference()->getId();
700
701//         unsigned int ssize = domain->zoom_ni_loc.getValue() * domain->zoom_nj_loc.getValue();
702//         bool isCurvilinear = (domain->lonvalue.getValue()->size() == ssize);
703//          bool isCurvilinear = domain->isCurvilinear ;
704
705         nc_type type ;
706         if (field->prec.isEmpty()) type =  NC_FLOAT ;
707         else
708         {
709           if (field->prec==2) type = NC_SHORT ;
710           else if (field->prec==4)  type =  NC_FLOAT ;
711           else if (field->prec==8)   type =  NC_DOUBLE ;
712         }
713
714         bool wtime   = !(!field->operation.isEmpty() && field->foperation->timeType() == func::CFunctor::once);
715
716         if (wtime)
717         {
718
719            //StdOStringStream oss;
720           // oss << "time_" << field->operation.getValue()
721           //     << "_" << field->getRelFile()->output_freq.getValue();
722          //oss
723            if (field->foperation->timeType() == func::CFunctor::instant) coodinates.push_back(string("time_instant"));
724            else if (field->foperation->timeType() == func::CFunctor::centered) coodinates.push_back(string("time_centered"));
725            dims.push_back(timeid);
726         }
727
728         if (!grid->axis_ref.isEmpty())
729         {
730            CAxis* axis = grid->axis ;
731            StdString axisid = (!axis->name.isEmpty()) ? axis->name.getValue() : axis->getId();
732            dims.push_back(axisid);
733            coodinates.push_back(axisid);
734         }
735
736         switch (domain->type)
737         {
738           case CDomain::type_attr::curvilinear :
739             coodinates.push_back(StdString("nav_lon").append(appendDomid));
740             coodinates.push_back(StdString("nav_lat").append(appendDomid));
741             break;
742           case CDomain::type_attr::regular :
743           case CDomain::type_attr::unstructured :
744            coodinates.push_back(StdString("lon").append(appendDomid));
745            coodinates.push_back(StdString("lat").append(appendDomid));
746             break;
747         }
748
749         if ( domain->type == CDomain::type_attr::curvilinear || domain->type == CDomain::type_attr::regular)dims.push_back(dimYid);
750         dims.push_back(dimXid);
751
752         try
753         {
754           SuperClassWriter::addVariable(fieldid, type, dims);
755
756           if (!field->standard_name.isEmpty())
757              SuperClassWriter::addAttribute
758                 ("standard_name",  field->standard_name.getValue(), &fieldid);
759
760           if (!field->long_name.isEmpty())
761              SuperClassWriter::addAttribute
762                 ("long_name", field->long_name.getValue(), &fieldid);
763
764           if (!field->unit.isEmpty())
765              SuperClassWriter::addAttribute
766                 ("units", field->unit.getValue(), &fieldid);
767
768            if (!field->valid_min.isEmpty())
769              SuperClassWriter::addAttribute
770                 ("valid_min", field->valid_min.getValue(), &fieldid);
771
772           if (!field->valid_max.isEmpty())
773              SuperClassWriter::addAttribute
774                 ("valid_max", field->valid_max.getValue(), &fieldid);
775
776            if (!field->scale_factor.isEmpty())
777              SuperClassWriter::addAttribute
778                 ("scale_factor", field->scale_factor.getValue(), &fieldid);
779
780             if (!field->add_offset.isEmpty())
781              SuperClassWriter::addAttribute
782                 ("add_offset", field->add_offset.getValue(), &fieldid);
783
784           SuperClassWriter::addAttribute
785                 ("online_operation", field->operation.getValue(), &fieldid);
786
787          // write child variables as attributes
788
789
790           vector<CVariable*> listVars = field->getAllVariables() ;
791           for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ;
792
793
794           if (wtime)
795           {
796              CDuration duration = CDuration::FromString(field->freq_op);
797              duration.solveTimeStep(*context->calendar);
798              StdString freqOpStr = duration.toStringUDUnits();
799              SuperClassWriter::addAttribute("interval_operation", freqOpStr, &fieldid);
800
801              duration = CDuration::FromString(field->getRelFile()->output_freq);
802              duration.solveTimeStep(*context->calendar);
803              SuperClassWriter::addAttribute("interval_write", duration.toStringUDUnits(), &fieldid);
804
805              StdString cellMethods = coodinates.front() + ": ";
806              if (field->operation.getValue() == "instant") cellMethods += "point";
807              else if (field->operation.getValue() == "average") cellMethods += "mean";
808              else if (field->operation.getValue() == "accumulate") cellMethods += "sum";
809              else cellMethods += field->operation;
810              cellMethods += " (interval: " + freqOpStr + ")";
811              SuperClassWriter::addAttribute("cell_methods", cellMethods, &fieldid);
812           }
813
814           if (domain->hasArea)
815             SuperClassWriter::addAttribute("cell_measures", "area: area" + appendDomid, &fieldid);
816
817           if (!field->default_value.isEmpty())
818           {
819              double default_value = field->default_value.getValue();
820              float fdefault_value = (float)default_value;
821              if (type == NC_DOUBLE)
822                 SuperClassWriter::setDefaultValue(fieldid, &default_value);
823              else
824                 SuperClassWriter::setDefaultValue(fieldid, &fdefault_value);
825           }
826           else
827           {
828              double * default_value = NULL;
829              SuperClassWriter::setDefaultValue(fieldid, default_value);
830           }
831
832           if (field->compression_level.isEmpty())
833             field->compression_level = field->file->compression_level.isEmpty() ? 0 : field->file->compression_level;
834           SuperClassWriter::setCompressionLevel(fieldid, field->compression_level);
835
836           {  // Ecriture des coordonnées
837
838              StdString coordstr; //boost::algorithm::join(coodinates, " ")
839              std::vector<StdString>::iterator
840                 itc = coodinates.begin(), endc = coodinates.end();
841
842              for (; itc!= endc; itc++)
843              {
844                 StdString & coord = *itc;
845                 if (itc+1 != endc)
846                       coordstr.append(coord).append(" ");
847                 else  coordstr.append(coord);
848              }
849
850              SuperClassWriter::addAttribute("coordinates", coordstr, &fieldid);
851
852           }
853         }
854         catch (CNetCdfException& e)
855         {
856           StdString msg("On writing field : ");
857           msg.append(fieldid); msg.append("\n");
858           msg.append("In the context : ");
859           msg.append(context->getId()); msg.append("\n");
860           msg.append(e.what());
861           ERROR("CNc4DataOutput::writeField_(CField* field)", << msg);
862         }
863      }
864
865      //--------------------------------------------------------------
866
867      void CNc4DataOutput::writeFile_ (CFile* file)
868      {
869         StdString filename = (!file->name.isEmpty())
870                            ? file->name.getValue() : file->getId();
871         StdString description = (!file->description.isEmpty())
872                               ? file->description.getValue()
873                               : StdString("Created by xios");
874
875         singleDomain = (file->nbDomains == 1);
876
877         try
878         {
879           this->writeFileAttributes(filename, description,
880                                     StdString("CF-1.1"),
881                                     StdString("An IPSL model"),
882                                     this->getTimeStamp());
883
884           if (file->nbAxis >= 1)
885             SuperClassWriter::addDimension("axis_nbounds", 2);
886         }
887         catch (CNetCdfException& e)
888         {
889           StdString msg("On writing file : ");
890           msg.append(filename); msg.append("\n");
891           msg.append("In the context : ");
892           CContext* context = CContext::getCurrent() ;
893           msg.append(context->getId()); msg.append("\n");
894           msg.append(e.what());
895           ERROR("CNc4DataOutput::writeFile_ (CFile* file)", << msg);
896         }
897      }
898
899      void CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)
900      {
901        string name ;
902        if (!var->name.isEmpty()) name=var->name ;
903        else if (var->hasId()) name=var->getId() ;
904        else return ;
905
906        try
907        {
908          if (var->getVarType()==CVariable::t_int) addAttribute(name,var->getData<int>(),&fieldId) ;
909          else if (var->getVarType()==CVariable::t_short_int) addAttribute(name,var->getData<short int>(),&fieldId) ;
910          else if (var->getVarType()==CVariable::t_long_int) addAttribute(name,var->getData<long int>(),&fieldId) ;
911          else if (var->getVarType()==CVariable::t_float) addAttribute(name,var->getData<float>(),&fieldId) ;
912          else if (var->getVarType()==CVariable::t_double) addAttribute(name,var->getData<double>(),&fieldId) ;
913          else addAttribute(name,var->getData<string>(),&fieldId) ;
914        }
915       catch (CNetCdfException& e)
916       {
917         StdString msg("On writing attributes of variable with name : ");
918         msg.append(name); msg.append("in the field "); msg.append(fieldId); msg.append("\n");
919         msg.append("In the context : ");
920         CContext* context = CContext::getCurrent() ;
921         msg.append(context->getId()); msg.append("\n");
922         msg.append(e.what());
923         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)", << msg);
924       }
925     }
926
927     void CNc4DataOutput::writeAttribute_ (CVariable* var)
928     {
929        string name ;
930        if (!var->name.isEmpty()) name=var->name ;
931        else if (var->hasId()) name=var->getId() ;
932        else return ;
933        try
934        {
935          if (var->getVarType()==CVariable::t_int) addAttribute(name,var->getData<int>()) ;
936          else if (var->getVarType()==CVariable::t_short_int) addAttribute(name,var->getData<short int>()) ;
937          else if (var->getVarType()==CVariable::t_long_int) addAttribute(name,var->getData<long int>()) ;
938          else if (var->getVarType()==CVariable::t_float) addAttribute(name,var->getData<float>()) ;
939          else if (var->getVarType()==CVariable::t_double) addAttribute(name,var->getData<double>()) ;
940          else addAttribute(name,var->getData<string>()) ;
941        }
942       catch (CNetCdfException& e)
943       {
944         StdString msg("On writing attributes of variable with name : ");
945         msg.append(name); msg.append("\n");
946         msg.append("In the context : ");
947         CContext* context = CContext::getCurrent() ;
948         msg.append(context->getId()); msg.append("\n");
949         msg.append(e.what());
950         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)", << msg);
951       }
952     }
953
954      void CNc4DataOutput::syncFile_ (void)
955      {
956        try
957        {
958          SuperClassWriter::sync() ;
959        }
960        catch (CNetCdfException& e)
961        {
962         StdString msg("On synchronizing the write among processes");
963         msg.append("In the context : ");
964         CContext* context = CContext::getCurrent() ;
965         msg.append(context->getId()); msg.append("\n");
966         msg.append(e.what());
967         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
968        }
969      }
970
971      void CNc4DataOutput::closeFile_ (void)
972      {
973        try
974        {
975          SuperClassWriter::close() ;
976        }
977        catch (CNetCdfException& e)
978        {
979         StdString msg("On closing file");
980         msg.append("In the context : ");
981         CContext* context = CContext::getCurrent() ;
982         msg.append(context->getId()); msg.append("\n");
983         msg.append(e.what());
984         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
985        }
986
987      }
988
989      //---------------------------------------------------------------
990
991      StdString CNc4DataOutput::getTimeStamp(void) const
992      {
993         const int buffer_size = 100;
994         time_t rawtime;
995         struct tm * timeinfo = NULL;
996         char buffer [buffer_size];
997
998         time ( &rawtime );
999         timeinfo = localtime ( &rawtime );
1000         strftime (buffer, buffer_size, "%Y-%b-%d %H:%M:%S %Z", timeinfo);
1001
1002         return (StdString(buffer));
1003      }
1004
1005      //---------------------------------------------------------------
1006
1007      void CNc4DataOutput::writeFieldData_ (CField*  field)
1008      {
1009         CContext* context = CContext::getCurrent() ;
1010//          if (field->getRelFile()->isSyncTime()) SuperClassWriter::sync() ;
1011         CContextServer* server=context->server ;
1012
1013         CGrid* grid = field->grid ;
1014         CDomain* domain = grid->domain ;
1015
1016         if(SuperClass::type==MULTI_FILE || !isCollective) if (domain->isEmpty()) return;
1017
1018
1019         StdString fieldid   = (!field->name.isEmpty())
1020                             ? field->name.getValue()
1021                             : field->getBaseFieldReference()->getId();
1022
1023         StdOStringStream oss;
1024         string timeAxisId ;
1025         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisId="time_instant" ;
1026         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisId="time_centered" ;
1027
1028         StdString timeBoundId("time_counter_bounds");
1029
1030         StdString timeAxisBoundId;
1031         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisBoundId="time_instant_bounds" ;
1032         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisBoundId="time_centered_bounds" ;
1033
1034         CArray<double,1> time_data(1) ;
1035         CArray<double,1> time_counter(1) ;
1036         CArray<double,1> time_counter_bound(2);
1037         CArray<double,1> time_data_bound(2);
1038
1039        bool wtime   = !(!field->operation.isEmpty() && (field->foperation->timeType() == func::CFunctor::once));
1040
1041        if (wtime)
1042        {
1043          time_counter(0)= (Time(*field->last_Write_srv) + Time(*field->lastlast_Write_srv)) / 2;
1044          if (field->foperation->timeType() == func::CFunctor::instant)
1045            time_data(0) = Time(*field->last_Write_srv);
1046          else if (field->foperation->timeType() == func::CFunctor::centered) time_data(0) = time_counter(0);
1047
1048          time_counter_bound(0) = Time(*field->lastlast_Write_srv);
1049          time_counter_bound(1) = Time(*field->last_Write_srv);
1050          if (field->foperation->timeType() == func::CFunctor::instant)
1051            time_data_bound(0) = time_data_bound(1) = Time(*field->last_Write_srv);
1052          else if (field->foperation->timeType() == func::CFunctor::centered)
1053          {
1054            time_data_bound(0) = time_counter_bound(0);
1055            time_data_bound(1) = time_counter_bound(1);
1056          }
1057         }
1058
1059         bool isRoot ;
1060         if (server->intraCommRank==0) isRoot=true ;
1061         else isRoot=false ;
1062
1063         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
1064         {
1065           double scaleFactor=1. ;
1066           double addOffset=0. ;
1067           if (!field->scale_factor.isEmpty()) scaleFactor=field->scale_factor ;
1068           if (!field->add_offset.isEmpty()) addOffset=field->add_offset ;
1069           field->scaleFactorAddOffset(scaleFactor,addOffset) ;
1070         }
1071
1072         try
1073         {
1074           if (grid->hasAxis()) // 3D
1075           {
1076              CAxis* axis = grid->axis ;
1077              CArray<double,3> field_data3D(domain->zoom_ni_srv,domain->zoom_nj_srv,axis->zoom_size) ;
1078              if (!field->default_value.isEmpty()) field_data3D = field->default_value ;
1079
1080              field->outputField(field_data3D);
1081
1082              if (!field->prec.isEmpty() && field->prec==2) field_data3D=round(field_data3D) ;
1083
1084              switch (SuperClass::type)
1085             {
1086                case (MULTI_FILE) :
1087                {
1088                   SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep()-1);
1089                   if (wtime)
1090                   {
1091                     SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep()-1);
1092                     SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep()-1);
1093                     SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1);
1094                     SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1);
1095                   }
1096                   break ;
1097                }
1098                case (ONE_FILE) :
1099                {
1100                   std::vector<StdSize> start(3) ;
1101                   std::vector<StdSize> count(3) ;
1102                   if (domain->isEmpty())
1103                   {
1104                     start[0]=0 ; start[1]=0 ; start[2]=0 ;
1105                     count[0]=0 ; count[1]=0 ; start[2]=0 ;
1106                   }
1107                   else
1108                   {
1109  //                 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 ;
1110                     start[2]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start [1]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ; start[0]=0 ;
1111                     count[2]=domain->zoom_ni_srv ; count[1]=domain->zoom_nj_srv ; count[0] = axis->zoom_size.getValue();
1112                   }
1113                   SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep()-1,&start,&count );
1114                   if (wtime)
1115                   {
1116                     SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot );
1117                     SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot );
1118                     SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot );
1119                     SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot);
1120                   }
1121                   break;
1122                }
1123              }
1124
1125           }
1126           else // 2D
1127           {
1128              CArray<double,2> field_data2D(domain->zoom_ni_srv,domain->zoom_nj_srv) ;
1129              if (!field->default_value.isEmpty()) field_data2D = field->default_value ;
1130              field->outputField(field_data2D);
1131              if (!field->prec.isEmpty() && field->prec==2) field_data2D=round(field_data2D) ;
1132              switch (SuperClass::type)
1133              {
1134                case (MULTI_FILE) :
1135                {
1136                  SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep()-1);
1137                  if (wtime)
1138                  {
1139                    SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep()-1);
1140                    SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep()-1);
1141                    SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1);
1142                    SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1);
1143                  }
1144                  break;
1145                }
1146                case (ONE_FILE) :
1147                {
1148                   std::vector<StdSize> start(2) ;
1149                   std::vector<StdSize> count(2) ;
1150                   if (domain->isEmpty())
1151                   {
1152                     start[0]=0 ; start[1]=0 ;
1153                     count[0]=0 ; count[1]=0 ;
1154                   }
1155                   else
1156                   {
1157                     start[1]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
1158                     count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
1159                   }
1160
1161                   SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep()-1,&start,&count);
1162                   if (wtime)
1163                   {
1164                     SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot);
1165                     SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot);
1166                     SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot);
1167                     SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot);
1168                   }
1169                   break;
1170
1171                }
1172              }
1173           }
1174         }
1175         catch (CNetCdfException& e)
1176         {
1177           StdString msg("On writing field data: ");
1178           msg.append(fieldid); msg.append("\n");
1179           msg.append("In the context : ");
1180           msg.append(context->getId()); msg.append("\n");
1181           msg.append(e.what());
1182           ERROR("CNc4DataOutput::writeFieldData_ (CField*  field)", << msg);
1183         }
1184      }
1185
1186      //---------------------------------------------------------------
1187
1188      void CNc4DataOutput::writeTimeAxis_
1189                  (CField*    field,
1190                   const boost::shared_ptr<CCalendar> cal)
1191      {
1192         StdOStringStream oss;
1193
1194//         if (field->operation.getValue().compare("once") == 0) return ;
1195         if (field->foperation->timeType() == func::CFunctor::once) return ;
1196
1197//         oss << "time_" << field->operation.getValue()
1198//             << "_" << field->getRelFile()->output_freq.getValue();
1199
1200//         StdString axisid = oss.str();
1201//         if (field->foperation->timeType() == func::CFunctor::centered) axisid="time_centered" ;
1202//         else if (field->foperation->timeType() == func::CFunctor::instant) axisid="time_instant" ;
1203
1204         StdString axisid("time_centered") ;
1205         StdString axisBoundId("time_centered_bounds");
1206         StdString timeid("time_counter");
1207         StdString timeBoundId("time_bounds");
1208
1209         if (field->foperation->timeType() == func::CFunctor::instant)
1210         {
1211            axisid = "time_instant";
1212            axisBoundId = "time_instant_bounds";
1213         }
1214
1215         try
1216         {
1217          // Adding time_instant or time_centered
1218           std::vector<StdString> dims;
1219           dims.push_back(timeid);
1220           if (!SuperClassWriter::varExist(axisid))
1221           {
1222              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1223
1224              CDate timeOrigin=cal->getTimeOrigin() ;
1225              StdOStringStream oss2;
1226  //            oss2<<initDate.getYear()<<"-"<<initDate.getMonth()<<"-"<<initDate.getDay()<<" "
1227  //                <<initDate.getHour()<<"-"<<initDate.getMinute()<<"-"<<initDate.getSecond() ;
1228              StdString strInitdate=oss2.str() ;
1229              StdString strTimeOrigin=timeOrigin.toString() ;
1230              this->writeTimeAxisAttributes
1231                 (axisid, cal->getType(),
1232                  StdString("seconds since ").append(strTimeOrigin),
1233                  strTimeOrigin, axisBoundId);
1234           }
1235
1236           // Adding time_instant_bounds or time_centered_bounds variables
1237           if (!SuperClassWriter::varExist(axisBoundId))
1238           {
1239              dims.clear() ;
1240              dims.push_back(timeid);
1241              dims.push_back(timeBoundId);
1242              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1243           }
1244
1245           // Adding time_counter
1246           axisid = "time_counter" ;
1247           axisBoundId = "time_counter_bounds" ;
1248           dims.clear() ;
1249           dims.push_back(timeid);
1250           if (!SuperClassWriter::varExist(axisid))
1251           {
1252              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1253              SuperClassWriter::addAttribute("axis", string("T"), &axisid);
1254              CDate timeOrigin=cal->getTimeOrigin() ;
1255              StdString strTimeOrigin=timeOrigin.toString() ;
1256
1257              this->writeTimeAxisAttributes
1258                 (axisid, cal->getType(),
1259                  StdString("seconds since ").append(strTimeOrigin),
1260                  strTimeOrigin, axisBoundId);
1261           }
1262
1263           // Adding time_counter_bound dimension
1264           if (!SuperClassWriter::varExist(axisBoundId))
1265           {
1266              dims.clear();
1267              dims.push_back(timeid);
1268              dims.push_back(timeBoundId);
1269              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1270           }
1271         }
1272         catch (CNetCdfException& e)
1273         {
1274           StdString msg("On writing time axis data: ");
1275           msg.append("In the context : ");
1276           CContext* context = CContext::getCurrent() ;
1277           msg.append(context->getId()); msg.append("\n");
1278           msg.append(e.what());
1279           ERROR("CNc4DataOutput::writeTimeAxis_ (CField*    field, \
1280                  const boost::shared_ptr<CCalendar> cal)", << msg);
1281         }
1282      }
1283
1284      //---------------------------------------------------------------
1285
1286      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
1287                                                   const StdString & calendar,
1288                                                   const StdString & units,
1289                                                   const StdString & time_origin,
1290                                                   const StdString & time_bounds,
1291                                                   const StdString & standard_name,
1292                                                   const StdString & long_name,
1293                                                   const StdString & title)
1294      {
1295         try
1296         {
1297           SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1298           SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
1299           SuperClassWriter::addAttribute("title",         title        , &axis_name);
1300           SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
1301           SuperClassWriter::addAttribute("units",         units        , &axis_name);
1302           SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
1303           SuperClassWriter::addAttribute("bounds",        time_bounds  , &axis_name);
1304         }
1305         catch (CNetCdfException& e)
1306         {
1307           StdString msg("On writing time axis Attribute: ");
1308           msg.append("In the context : ");
1309           CContext* context = CContext::getCurrent() ;
1310           msg.append(context->getId()); msg.append("\n");
1311           msg.append(e.what());
1312           ERROR("CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name, \
1313                                                   const StdString & calendar,\
1314                                                   const StdString & units, \
1315                                                   const StdString & time_origin, \
1316                                                   const StdString & time_bounds, \
1317                                                   const StdString & standard_name, \
1318                                                   const StdString & long_name, \
1319                                                   const StdString & title)", << msg);
1320         }
1321      }
1322
1323      //---------------------------------------------------------------
1324
1325      void CNc4DataOutput::writeAxisAttributes(const StdString & axis_name,
1326                                               const StdString & axis,
1327                                               const StdString & standard_name,
1328                                               const StdString & long_name,
1329                                               const StdString & units,
1330                                               const StdString & nav_model)
1331      {
1332         try
1333         {
1334          SuperClassWriter::addAttribute("axis"         , axis         , &axis_name);
1335          SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1336          SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
1337          SuperClassWriter::addAttribute("units"        , units        , &axis_name);
1338          SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
1339         }
1340         catch (CNetCdfException& e)
1341         {
1342           StdString msg("On writing Axis Attribute: ");
1343           msg.append("In the context : ");
1344           CContext* context = CContext::getCurrent() ;
1345           msg.append(context->getId()); msg.append("\n");
1346           msg.append(e.what());
1347           ERROR("CNc4DataOutput::writeAxisAttributes(const StdString & axis_name, \
1348                                               const StdString & axis, \
1349                                               const StdString & standard_name, \
1350                                               const StdString & long_name, \
1351                                               const StdString & units, \
1352                                               const StdString & nav_model)", << msg);
1353         }
1354      }
1355
1356      //---------------------------------------------------------------
1357
1358      void CNc4DataOutput::writeLocalAttributes
1359         (int ibegin, int ni, int jbegin, int nj, StdString domid)
1360      {
1361        try
1362        {
1363         SuperClassWriter::addAttribute(StdString("ibegin").append(domid), ibegin);
1364         SuperClassWriter::addAttribute(StdString("ni"    ).append(domid), ni);
1365         SuperClassWriter::addAttribute(StdString("jbegin").append(domid), jbegin);
1366         SuperClassWriter::addAttribute(StdString("nj"    ).append(domid), nj);
1367        }
1368        catch (CNetCdfException& e)
1369        {
1370           StdString msg("On writing Local Attributes: ");
1371           msg.append("In the context : ");
1372           CContext* context = CContext::getCurrent() ;
1373           msg.append(context->getId()); msg.append("\n");
1374           msg.append(e.what());
1375           ERROR("CNc4DataOutput::writeLocalAttributes \
1376                  (int ibegin, int ni, int jbegin, int nj, StdString domid)", << msg);
1377        }
1378
1379      }
1380
1381     void CNc4DataOutput::writeLocalAttributes_IOIPSL
1382         (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)
1383      {
1384         CArray<int,1> array(2) ;
1385
1386         try
1387         {
1388           SuperClassWriter::addAttribute("DOMAIN_number_total",size ) ;
1389           SuperClassWriter::addAttribute("DOMAIN_number", rank) ;
1390           array=1,2 ;
1391           SuperClassWriter::addAttribute("DOMAIN_dimensions_ids",array) ;
1392           array=ni_glo,nj_glo ;
1393           SuperClassWriter::addAttribute("DOMAIN_size_global", array) ;
1394           array=ni,nj ;
1395           SuperClassWriter::addAttribute("DOMAIN_size_local", array) ;
1396           array=ibegin,jbegin ;
1397           SuperClassWriter::addAttribute("DOMAIN_position_first", array) ;
1398           array=ibegin+ni-1,jbegin+nj-1 ;
1399           SuperClassWriter::addAttribute("DOMAIN_position_last",array) ;
1400           array=0,0 ;
1401           SuperClassWriter::addAttribute("DOMAIN_halo_size_start", array) ;
1402           SuperClassWriter::addAttribute("DOMAIN_halo_size_end", array);
1403           SuperClassWriter::addAttribute("DOMAIN_type",string("box")) ;
1404  /*
1405           SuperClassWriter::addAttribute("DOMAIN_DIM_N001",string("x")) ;
1406           SuperClassWriter::addAttribute("DOMAIN_DIM_N002",string("y")) ;
1407           SuperClassWriter::addAttribute("DOMAIN_DIM_N003",string("axis_A")) ;
1408           SuperClassWriter::addAttribute("DOMAIN_DIM_N004",string("time_counter")) ;
1409  */
1410         }
1411         catch (CNetCdfException& e)
1412         {
1413           StdString msg("On writing Local Attributes IOI PSL \n");
1414           msg.append("In the context : ");
1415           CContext* context = CContext::getCurrent() ;
1416           msg.append(context->getId()); msg.append("\n");
1417           msg.append(e.what());
1418           ERROR("CNc4DataOutput::writeLocalAttributes_IOIPSL \
1419                  (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)", << msg);
1420         }
1421      }
1422      //---------------------------------------------------------------
1423
1424      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
1425                                                const StdString & description,
1426                                                const StdString & conventions,
1427                                                const StdString & production,
1428                                                const StdString & timeStamp)
1429      {
1430         try
1431         {
1432           SuperClassWriter::addAttribute("name"       , name);
1433           SuperClassWriter::addAttribute("description", description);
1434           SuperClassWriter::addAttribute("conventions", conventions);
1435           SuperClassWriter::addAttribute("production" , production);
1436           SuperClassWriter::addAttribute("timeStamp"  , timeStamp);
1437         }
1438         catch (CNetCdfException& e)
1439         {
1440           StdString msg("On writing File Attributes \n ");
1441           msg.append("In the context : ");
1442           CContext* context = CContext::getCurrent() ;
1443           msg.append(context->getId()); msg.append("\n");
1444           msg.append(e.what());
1445           ERROR("CNc4DataOutput:: writeFileAttributes(const StdString & name, \
1446                                                const StdString & description, \
1447                                                const StdString & conventions, \
1448                                                const StdString & production, \
1449                                                const StdString & timeStamp)", << msg);
1450         }
1451      }
1452
1453      //---------------------------------------------------------------
1454
1455      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
1456                                               int data_dim,
1457                                               int data_ni,
1458                                               int data_nj,
1459                                               int data_ibegin,
1460                                               int data_jbegin)
1461      {
1462         try
1463         {
1464           SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
1465           SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
1466           SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
1467           SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
1468           SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
1469         }
1470         catch (CNetCdfException& e)
1471         {
1472           StdString msg("On writing Mask Attributes \n ");
1473           msg.append("In the context : ");
1474           CContext* context = CContext::getCurrent() ;
1475           msg.append(context->getId()); msg.append("\n");
1476           msg.append(e.what());
1477           ERROR("CNc4DataOutput::writeMaskAttributes(const StdString & mask_name, \
1478                                               int data_dim, \
1479                                               int data_ni, \
1480                                               int data_nj, \
1481                                               int data_ibegin, \
1482                                               int data_jbegin)", << msg);
1483         }
1484      }
1485
1486      ///--------------------------------------------------------------
1487
1488} // namespace xios
Note: See TracBrowser for help on using the repository browser.