source: XIOS/branchs/xios-1.0/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: 63.5 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         bool isRegularDomain = (domain->type == CDomain::type_attr::regular);
85         switch (domain->type)
86         {
87           case CDomain::type_attr::curvilinear :
88             dimXid     = StdString("x").append(appendDomid);
89             dimYid     = StdString("y").append(appendDomid);
90             break ;
91           case CDomain::type_attr::regular :
92             dimXid     = StdString("lon").append(appendDomid);
93             dimYid     = StdString("lat").append(appendDomid);
94             break;
95           case CDomain::type_attr::unstructured :
96             dimXid     = StdString("cell").append(appendDomid);
97             break;
98         }
99
100         string lonid,latid,bounds_lonid,bounds_latid ;
101         string areaId = "area" + appendDomid;
102/*
103         StdString lonid_loc = (server->intraCommSize > 1)
104                             ? StdString("lon").append(appendDomid).append("_local")
105                             : lonid;
106         StdString latid_loc = (server->intraCommSize > 1)
107                             ? StdString("lat").append(appendDomid).append("_local")
108                             : latid;
109*/
110
111         try
112         {
113           switch (SuperClass::type)
114           {
115              case (MULTI_FILE) :
116              {
117  //               if (domain->isEmpty()) return;
118
119                 if (server->intraCommSize > 1)
120                 {
121  //                 SuperClassWriter::addDimension(lonid, domain->zoom_ni.getValue());
122  //                 SuperClassWriter::addDimension(latid, domain->zoom_nj.getValue());
123                 }
124
125                 switch (domain->type)
126                 {
127                   case CDomain::type_attr::curvilinear :
128                     dim0.push_back(dimYid); dim0.push_back(dimXid);
129                     lonid = StdString("nav_lon").append(appendDomid);
130                     latid = StdString("nav_lat").append(appendDomid);
131                     break ;
132                   case CDomain::type_attr::regular :
133                     lonid = StdString("lon").append(appendDomid);
134                     latid = StdString("lat").append(appendDomid);
135                     dim0.push_back(dimYid);
136                     dim1.push_back(dimXid);
137                     break;
138                   case CDomain::type_attr::unstructured :
139                     lonid = StdString("lon").append(appendDomid);
140                     latid = StdString("lat").append(appendDomid);
141                     bounds_lonid=string("bounds_lon").append(appendDomid);
142                     bounds_latid=string("bounds_lat").append(appendDomid);
143                     dim0.push_back(dimXid);
144                     break;
145                 }
146
147                 if (domain->type == CDomain::type_attr::unstructured)
148                 {
149                   SuperClassWriter::addDimension(dimXid, domain->nj_glo);
150                 }
151                 else
152                 {
153                   SuperClassWriter::addDimension(dimXid, domain->zoom_ni_srv);
154                   SuperClassWriter::addDimension(dimYid, domain->zoom_nj_srv);
155                 }
156
157                 if (server->intraCommSize > 1)
158                 {
159                    if (domain->type != CDomain::type_attr::unstructured)
160                    {
161                      this->writeLocalAttributes(domain->zoom_ibegin_srv,
162                                                 domain->zoom_ni_srv,
163                                                 domain->zoom_jbegin_srv,
164                                                 domain->zoom_nj_srv,
165                                                 appendDomid);
166
167                      if (singleDomain) this->writeLocalAttributes_IOIPSL(domain->zoom_ibegin_srv,
168                                                 domain->zoom_ni_srv,
169                                                 domain->zoom_jbegin_srv,
170                                                 domain->zoom_nj_srv,
171                                                 domain->ni_glo,domain->nj_glo,
172                                                 server->intraCommRank,server->intraCommSize);
173                   }
174                 }
175
176                 switch (domain->type)
177                 {
178                   case CDomain::type_attr::curvilinear :
179                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
180                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
181                     break ;
182                    case CDomain::type_attr::regular :
183                      SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
184                      SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
185                      break ;
186                    case CDomain::type_attr::unstructured :
187                      SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
188                      SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
189                 }
190
191                 this->writeAxisAttributes(lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
192                 this->writeAxisAttributes(latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
193
194                 dim0.clear();
195                 if (domain->type != CDomain::type_attr::unstructured) dim0.push_back(dimYid);
196                 dim0.push_back(dimXid);
197
198
199  // supress mask               if (server->intraCommSize > 1)
200  // supress mask               {
201  // supress mask                  SuperClassWriter::addVariable(maskid, NC_INT, dim0);
202  // supress mask
203  // supress mask                  this->writeMaskAttributes(maskid,
204  // supress mask                     domain->data_dim.getValue()/*,
205  // supress mask                     domain->data_ni.getValue(),
206  // supress mask                     domain->data_nj.getValue(),
207  // supress mask                     domain->data_ibegin.getValue(),
208  // supress mask                     domain->data_jbegin.getValue()*/);
209  // supress mask               }
210
211                 //SuperClassWriter::setDefaultValue(maskid, &dvm);
212
213                 if (domain->hasArea)
214                 {
215                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
216                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
217                 }
218
219                 SuperClassWriter::definition_end();
220
221                 switch (domain->type)
222                 {
223                   case CDomain::type_attr::curvilinear :
224                     SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0);
225                     SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0);
226                     break;
227                   case CDomain::type_attr::regular :
228                     CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;
229                     SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0);
230                     CArray<double,1> lon=domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;
231                     SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0);
232                     break;
233                 }
234
235                 if (domain->hasArea)
236                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0);
237
238                 SuperClassWriter::definition_start();
239
240                 break;
241              }
242              case (ONE_FILE) :
243              {
244                 SuperClassWriter::addDimension(dimXid, domain->zoom_ni.getValue());
245                 SuperClassWriter::addDimension(dimYid, domain->zoom_nj.getValue());
246
247                 switch (domain->type)
248                 {
249                   case CDomain::type_attr::curvilinear :
250                     dim0.push_back(dimYid); dim0.push_back(dimXid);
251                     lonid = StdString("nav_lon").append(appendDomid);
252                     latid = StdString("nav_lat").append(appendDomid);
253                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
254                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
255                     break;
256
257                   case CDomain::type_attr::regular :
258                     dim0.push_back(dimYid);
259                     dim1.push_back(dimXid);
260                     lonid = StdString("lon").append(appendDomid);
261                     latid = StdString("lat").append(appendDomid);
262                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
263                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
264                     break;
265                 }
266
267                 if (domain->hasArea)
268                 {
269                   dim0.clear();
270                   dim0.push_back(dimYid); dim0.push_back(dimXid);
271                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
272                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
273                   dim0.clear();
274                 }
275
276                 this->writeAxisAttributes
277                    (lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
278                 this->writeAxisAttributes
279                    (latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
280
281                 SuperClassWriter::definition_end();
282
283                 switch (domain->type)
284                 {
285                   case CDomain::type_attr::curvilinear :
286                   {
287                     std::vector<StdSize> start(2) ;
288                     std::vector<StdSize> count(2) ;
289                     if (domain->isEmpty())
290                     {
291                       start[0]=0 ; start[1]=0 ;
292                       count[0]=0 ; count[1]=0 ;
293                     }
294                     else
295                     {
296                       start[1]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start [0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
297                       count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
298                     }
299
300                     SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
301                     SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
302                     break;
303                   }
304                   case CDomain::type_attr::regular :
305                   {
306                     std::vector<StdSize> start(1) ;
307                     std::vector<StdSize> count(1) ;
308                     if (domain->isEmpty())
309                     {
310                       start[0]=0 ;
311                       count[0]=0 ;
312                       SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
313                       SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);                 }
314                     else
315                     {
316                       start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
317                       count[0]=domain->zoom_nj_srv ;
318                       CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;
319                       SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0,&start,&count);
320
321                       start[0]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ;
322                       count[0]=domain->zoom_ni_srv ;
323                       CArray<double,1> lon=domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;
324                       SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0,&start,&count);
325                     }
326                     break;
327                   }
328                 }
329
330                 if (domain->hasArea)
331                 {
332                   std::vector<StdSize> start(2);
333                   std::vector<StdSize> count(2);
334
335                   if (domain->isEmpty())
336                   {
337                     start[0] = 0; start[1] = 0;
338                     count[0] = 0; count[1] = 0;
339                   }
340                   else
341                   {
342                     start[1] = domain->zoom_ibegin_srv - domain->zoom_ibegin.getValue();
343                     start[0] = domain->zoom_jbegin_srv - domain->zoom_jbegin.getValue();
344                     count[1] = domain->zoom_ni_srv;
345                     count[0] = domain->zoom_nj_srv;
346                   }
347
348                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0, &start, &count);
349                 }
350
351                 SuperClassWriter::definition_start();
352
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 = axis->zoom_size.getValue();
550         int zoom_begin = axis->zoom_begin.getValue() - 1;
551
552
553         std::vector<StdString> dims;
554         StdString axisid = (!axis->name.isEmpty())
555                           ? axis->name.getValue() : axis->getId();
556         try
557         {
558           SuperClassWriter::addDimension(axisid, zoom_size);
559           dims.push_back(axisid);
560
561           switch (SuperClass::type)
562           {
563              case (MULTI_FILE ) :
564              {}
565              case (ONE_FILE) :
566              {
567                 SuperClassWriter::addVariable(axisid, NC_FLOAT, dims);
568
569                 if (!axis->standard_name.isEmpty())
570                    SuperClassWriter::addAttribute
571                       ("standard_name",  axis->standard_name.getValue(), &axisid);
572
573                 if (!axis->long_name.isEmpty())
574                    SuperClassWriter::addAttribute
575                       ("long_name", axis->long_name.getValue(), &axisid);
576
577                 if (!axis->unit.isEmpty())
578                    SuperClassWriter::addAttribute
579                       ("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; i++) axis_value(i) = axis->value(i+zoom_begin);
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; i++)
607                   {
608                     axisBounds(i, 0) = axis->bounds(i + zoom_begin, 0);
609                     axisBounds(i, 1) = axis->bounds(i + zoom_begin, 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         CDomain* domain = grid->domain;
664
665         if (domain->isEmpty())
666           if (SuperClass::type==MULTI_FILE) return ;
667
668         StdString timeid    = StdString("time_counter");
669         StdString domid     = (!domain->name.isEmpty())
670                             ? domain->name.getValue() : domain->getId();
671         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
672
673//         bool isCurvilinear = domain->isCurvilinear ;
674//         bool isCurvilinear = (domain->type == CDomain::type_attr::curvilinear) ;
675
676         StdString dimXid,dimYid ;
677
678         switch (domain->type)
679         {
680           case CDomain::type_attr::curvilinear :
681             dimXid     = StdString("x").append(appendDomid);
682             dimYid     = StdString("y").append(appendDomid);
683             break ;
684           case CDomain::type_attr::regular :
685             dimXid     = StdString("lon").append(appendDomid);
686             dimYid     = StdString("lat").append(appendDomid);
687             break ;
688           case CDomain::type_attr::unstructured :
689             dimXid     = StdString("cell").append(appendDomid);
690             break ;
691        }
692
693/*
694         StdString lonid_loc = (server->intraCommSize > 1)
695                             ? StdString("lon").append(appendDomid).append("_local")
696                             : lonid;
697         StdString latid_loc = (server->intraCommSize > 1)
698                             ? StdString("lat").append(appendDomid).append("_local")
699                             : latid;
700*/
701         StdString fieldid   = (!field->name.isEmpty())
702                             ? field->name.getValue() : field->getBaseFieldReference()->getId();
703
704//         unsigned int ssize = domain->zoom_ni_loc.getValue() * domain->zoom_nj_loc.getValue();
705//         bool isCurvilinear = (domain->lonvalue.getValue()->size() == ssize);
706//          bool isCurvilinear = domain->isCurvilinear ;
707
708         nc_type type ;
709         if (field->prec.isEmpty()) type =  NC_FLOAT ;
710         else
711         {
712           if (field->prec==2) type = NC_SHORT ;
713           else if (field->prec==4)  type =  NC_FLOAT ;
714           else if (field->prec==8)   type =  NC_DOUBLE ;
715         }
716
717         bool wtime   = !(!field->operation.isEmpty() && field->foperation->timeType() == func::CFunctor::once);
718
719         if (wtime)
720         {
721
722            //StdOStringStream oss;
723           // oss << "time_" << field->operation.getValue()
724           //     << "_" << field->getRelFile()->output_freq.getValue();
725          //oss
726            if (field->foperation->timeType() == func::CFunctor::instant) coodinates.push_back(string("time_instant"));
727            else if (field->foperation->timeType() == func::CFunctor::centered) coodinates.push_back(string("time_centered"));
728            dims.push_back(timeid);
729         }
730
731         if (!grid->axis_ref.isEmpty())
732         {
733            CAxis* axis = grid->axis ;
734            StdString axisid = (!axis->name.isEmpty()) ? axis->name.getValue() : axis->getId();
735            dims.push_back(axisid);
736            coodinates.push_back(axisid);
737         }
738
739         switch (domain->type)
740         {
741           case CDomain::type_attr::curvilinear :
742             coodinates.push_back(StdString("nav_lon").append(appendDomid));
743             coodinates.push_back(StdString("nav_lat").append(appendDomid));
744             break;
745           case CDomain::type_attr::regular :
746           case CDomain::type_attr::unstructured :
747            coodinates.push_back(StdString("lon").append(appendDomid));
748            coodinates.push_back(StdString("lat").append(appendDomid));
749             break;
750         }
751
752         if ( domain->type == CDomain::type_attr::curvilinear || domain->type == CDomain::type_attr::regular)dims.push_back(dimYid);
753         dims.push_back(dimXid);
754
755         try
756         {
757           SuperClassWriter::addVariable(fieldid, type, dims);
758
759           if (!field->standard_name.isEmpty())
760              SuperClassWriter::addAttribute
761                 ("standard_name",  field->standard_name.getValue(), &fieldid);
762
763           if (!field->long_name.isEmpty())
764              SuperClassWriter::addAttribute
765                 ("long_name", field->long_name.getValue(), &fieldid);
766
767           if (!field->unit.isEmpty())
768              SuperClassWriter::addAttribute
769                 ("units", field->unit.getValue(), &fieldid);
770
771            if (!field->valid_min.isEmpty())
772              SuperClassWriter::addAttribute
773                 ("valid_min", field->valid_min.getValue(), &fieldid);
774
775           if (!field->valid_max.isEmpty())
776              SuperClassWriter::addAttribute
777                 ("valid_max", field->valid_max.getValue(), &fieldid);
778
779            if (!field->scale_factor.isEmpty())
780              SuperClassWriter::addAttribute
781                 ("scale_factor", field->scale_factor.getValue(), &fieldid);
782
783             if (!field->add_offset.isEmpty())
784              SuperClassWriter::addAttribute
785                 ("add_offset", field->add_offset.getValue(), &fieldid);
786
787           SuperClassWriter::addAttribute
788                 ("online_operation", field->operation.getValue(), &fieldid);
789
790          // write child variables as attributes
791
792
793           vector<CVariable*> listVars = field->getAllVariables() ;
794           for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ;
795
796
797           if (wtime)
798           {
799              CDuration duration = CDuration::FromString(field->freq_op);
800              duration.solveTimeStep(*context->calendar);
801              StdString freqOpStr = duration.toStringUDUnits();
802              SuperClassWriter::addAttribute("interval_operation", freqOpStr, &fieldid);
803
804              duration = CDuration::FromString(field->getRelFile()->output_freq);
805              duration.solveTimeStep(*context->calendar);
806              SuperClassWriter::addAttribute("interval_write", duration.toStringUDUnits(), &fieldid);
807
808              StdString cellMethods = coodinates.front() + ": ";
809              if (field->operation.getValue() == "instant") cellMethods += "point";
810              else if (field->operation.getValue() == "average") cellMethods += "mean";
811              else if (field->operation.getValue() == "accumulate") cellMethods += "sum";
812              else cellMethods += field->operation;
813              cellMethods += " (interval: " + freqOpStr + ")";
814              SuperClassWriter::addAttribute("cell_methods", cellMethods, &fieldid);
815           }
816
817           if (domain->hasArea)
818             SuperClassWriter::addAttribute("cell_measures", "area: area" + appendDomid, &fieldid);
819
820           if (!field->default_value.isEmpty())
821           {
822              double default_value = field->default_value.getValue();
823              float fdefault_value = (float)default_value;
824              if (type == NC_DOUBLE)
825                 SuperClassWriter::setDefaultValue(fieldid, &default_value);
826              else
827                 SuperClassWriter::setDefaultValue(fieldid, &fdefault_value);
828           }
829           else
830           {
831              double * default_value = NULL;
832              SuperClassWriter::setDefaultValue(fieldid, default_value);
833           }
834
835           if (field->compression_level.isEmpty())
836             field->compression_level = field->file->compression_level.isEmpty() ? 0 : field->file->compression_level;
837           SuperClassWriter::setCompressionLevel(fieldid, field->compression_level);
838
839           {  // Ecriture des coordonnées
840
841              StdString coordstr; //boost::algorithm::join(coodinates, " ")
842              std::vector<StdString>::iterator
843                 itc = coodinates.begin(), endc = coodinates.end();
844
845              for (; itc!= endc; itc++)
846              {
847                 StdString & coord = *itc;
848                 if (itc+1 != endc)
849                       coordstr.append(coord).append(" ");
850                 else  coordstr.append(coord);
851              }
852
853              SuperClassWriter::addAttribute("coordinates", coordstr, &fieldid);
854
855           }
856         }
857         catch (CNetCdfException& e)
858         {
859           StdString msg("On writing field : ");
860           msg.append(fieldid); msg.append("\n");
861           msg.append("In the context : ");
862           msg.append(context->getId()); msg.append("\n");
863           msg.append(e.what());
864           ERROR("CNc4DataOutput::writeField_(CField* field)", << msg);
865         }
866      }
867
868      //--------------------------------------------------------------
869
870      void CNc4DataOutput::writeFile_ (CFile* file)
871      {
872         StdString filename = (!file->name.isEmpty())
873                            ? file->name.getValue() : file->getId();
874         StdString description = (!file->description.isEmpty())
875                               ? file->description.getValue()
876                               : StdString("Created by xios");
877
878         singleDomain = (file->nbDomains == 1);
879
880         try
881         {
882           this->writeFileAttributes(filename, description,
883                                     StdString("CF-1.1"),
884                                     StdString("An IPSL model"),
885                                     this->getTimeStamp());
886
887           if (file->nbAxis >= 1)
888             SuperClassWriter::addDimension("axis_nbounds", 2);
889         }
890         catch (CNetCdfException& e)
891         {
892           StdString msg("On writing file : ");
893           msg.append(filename); msg.append("\n");
894           msg.append("In the context : ");
895           CContext* context = CContext::getCurrent() ;
896           msg.append(context->getId()); msg.append("\n");
897           msg.append(e.what());
898           ERROR("CNc4DataOutput::writeFile_ (CFile* file)", << msg);
899         }
900      }
901
902      void CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)
903      {
904        string name ;
905        if (!var->name.isEmpty()) name=var->name ;
906        else if (var->hasId()) name=var->getId() ;
907        else return ;
908
909        try
910        {
911          if (var->getVarType()==CVariable::t_int) addAttribute(name,var->getData<int>(),&fieldId) ;
912          else if (var->getVarType()==CVariable::t_short_int) addAttribute(name,var->getData<short int>(),&fieldId) ;
913          else if (var->getVarType()==CVariable::t_long_int) addAttribute(name,var->getData<long int>(),&fieldId) ;
914          else if (var->getVarType()==CVariable::t_float) addAttribute(name,var->getData<float>(),&fieldId) ;
915          else if (var->getVarType()==CVariable::t_double) addAttribute(name,var->getData<double>(),&fieldId) ;
916          else addAttribute(name,var->getData<string>(),&fieldId) ;
917        }
918       catch (CNetCdfException& e)
919       {
920         StdString msg("On writing attributes of variable with name : ");
921         msg.append(name); msg.append("in the field "); msg.append(fieldId); msg.append("\n");
922         msg.append("In the context : ");
923         CContext* context = CContext::getCurrent() ;
924         msg.append(context->getId()); msg.append("\n");
925         msg.append(e.what());
926         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)", << msg);
927       }
928     }
929
930     void CNc4DataOutput::writeAttribute_ (CVariable* var)
931     {
932        string name ;
933        if (!var->name.isEmpty()) name=var->name ;
934        else if (var->hasId()) name=var->getId() ;
935        else return ;
936        try
937        {
938          if (var->getVarType()==CVariable::t_int) addAttribute(name,var->getData<int>()) ;
939          else if (var->getVarType()==CVariable::t_short_int) addAttribute(name,var->getData<short int>()) ;
940          else if (var->getVarType()==CVariable::t_long_int) addAttribute(name,var->getData<long int>()) ;
941          else if (var->getVarType()==CVariable::t_float) addAttribute(name,var->getData<float>()) ;
942          else if (var->getVarType()==CVariable::t_double) addAttribute(name,var->getData<double>()) ;
943          else addAttribute(name,var->getData<string>()) ;
944        }
945       catch (CNetCdfException& e)
946       {
947         StdString msg("On writing attributes of variable with name : ");
948         msg.append(name); msg.append("\n");
949         msg.append("In the context : ");
950         CContext* context = CContext::getCurrent() ;
951         msg.append(context->getId()); msg.append("\n");
952         msg.append(e.what());
953         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)", << msg);
954       }
955     }
956
957      void CNc4DataOutput::syncFile_ (void)
958      {
959        try
960        {
961          SuperClassWriter::sync() ;
962        }
963        catch (CNetCdfException& e)
964        {
965         StdString msg("On synchronizing the write among processes");
966         msg.append("In the context : ");
967         CContext* context = CContext::getCurrent() ;
968         msg.append(context->getId()); msg.append("\n");
969         msg.append(e.what());
970         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
971        }
972      }
973
974      void CNc4DataOutput::closeFile_ (void)
975      {
976        try
977        {
978          SuperClassWriter::close() ;
979        }
980        catch (CNetCdfException& e)
981        {
982         StdString msg("On closing file");
983         msg.append("In the context : ");
984         CContext* context = CContext::getCurrent() ;
985         msg.append(context->getId()); msg.append("\n");
986         msg.append(e.what());
987         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
988        }
989
990      }
991
992      //---------------------------------------------------------------
993
994      StdString CNc4DataOutput::getTimeStamp(void) const
995      {
996         const int buffer_size = 100;
997         time_t rawtime;
998         struct tm * timeinfo = NULL;
999         char buffer [buffer_size];
1000
1001         time ( &rawtime );
1002         timeinfo = localtime ( &rawtime );
1003         strftime (buffer, buffer_size, "%Y-%b-%d %H:%M:%S %Z", timeinfo);
1004
1005         return (StdString(buffer));
1006      }
1007
1008      //---------------------------------------------------------------
1009
1010      void CNc4DataOutput::writeFieldData_ (CField*  field)
1011      {
1012         CContext* context = CContext::getCurrent() ;
1013//          if (field->getRelFile()->isSyncTime()) SuperClassWriter::sync() ;
1014         CContextServer* server=context->server ;
1015
1016         CGrid* grid = field->grid ;
1017         CDomain* domain = grid->domain ;
1018
1019         if(SuperClass::type==MULTI_FILE || !isCollective) if (domain->isEmpty()) return;
1020
1021
1022         StdString fieldid   = (!field->name.isEmpty())
1023                             ? field->name.getValue()
1024                             : field->getBaseFieldReference()->getId();
1025
1026         StdOStringStream oss;
1027         string timeAxisId ;
1028         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisId="time_instant" ;
1029         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisId="time_centered" ;
1030
1031         StdString timeBoundId("time_counter_bounds");
1032
1033         StdString timeAxisBoundId;
1034         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisBoundId="time_instant_bounds" ;
1035         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisBoundId="time_centered_bounds" ;
1036
1037         CArray<double,1> time_data(1) ;
1038         CArray<double,1> time_counter(1) ;
1039         CArray<double,1> time_counter_bound(2);
1040         CArray<double,1> time_data_bound(2);
1041
1042        bool wtime   = !(!field->operation.isEmpty() && (field->foperation->timeType() == func::CFunctor::once));
1043
1044        if (wtime)
1045        {
1046          time_counter(0)= (Time(*field->last_Write_srv) + Time(*field->lastlast_Write_srv)) / 2;
1047          if (field->foperation->timeType() == func::CFunctor::instant)
1048            time_data(0) = Time(*field->last_Write_srv);
1049          else if (field->foperation->timeType() == func::CFunctor::centered) time_data(0) = time_counter(0);
1050
1051          time_counter_bound(0) = Time(*field->lastlast_Write_srv);
1052          time_counter_bound(1) = Time(*field->last_Write_srv);
1053          if (field->foperation->timeType() == func::CFunctor::instant)
1054            time_data_bound(0) = time_data_bound(1) = Time(*field->last_Write_srv);
1055          else if (field->foperation->timeType() == func::CFunctor::centered)
1056          {
1057            time_data_bound(0) = time_counter_bound(0);
1058            time_data_bound(1) = time_counter_bound(1);
1059          }
1060         }
1061
1062         bool isRoot ;
1063         if (server->intraCommRank==0) isRoot=true ;
1064         else isRoot=false ;
1065
1066         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
1067         {
1068           double scaleFactor=1. ;
1069           double addOffset=0. ;
1070           if (!field->scale_factor.isEmpty()) scaleFactor=field->scale_factor ;
1071           if (!field->add_offset.isEmpty()) addOffset=field->add_offset ;
1072           field->scaleFactorAddOffset(scaleFactor,addOffset) ;
1073         }
1074
1075         try
1076         {
1077           if (grid->hasAxis()) // 3D
1078           {
1079              CAxis* axis = grid->axis ;
1080              CArray<double,3> field_data3D(domain->zoom_ni_srv,domain->zoom_nj_srv,axis->zoom_size) ;
1081              if (!field->default_value.isEmpty()) field_data3D = field->default_value ;
1082
1083              field->outputField(field_data3D);
1084
1085              if (!field->prec.isEmpty() && field->prec==2) field_data3D=round(field_data3D) ;
1086
1087              switch (SuperClass::type)
1088             {
1089                case (MULTI_FILE) :
1090                {
1091                   SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep()-1);
1092                   if (wtime)
1093                   {
1094                     SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep()-1);
1095                     SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep()-1);
1096                     SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1);
1097                     SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1);
1098                   }
1099                   break ;
1100                }
1101                case (ONE_FILE) :
1102                {
1103                   std::vector<StdSize> start(3) ;
1104                   std::vector<StdSize> count(3) ;
1105                   if (domain->isEmpty())
1106                   {
1107                     start[0]=0 ; start[1]=0 ; start[2]=0 ;
1108                     count[0]=0 ; count[1]=0 ; start[2]=0 ;
1109                   }
1110                   else
1111                   {
1112  //                 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 ;
1113                     start[2]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start [1]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ; start[0]=0 ;
1114                     count[2]=domain->zoom_ni_srv ; count[1]=domain->zoom_nj_srv ; count[0] = axis->zoom_size.getValue();
1115                   }
1116                   SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep()-1,&start,&count );
1117                   if (wtime)
1118                   {
1119                     SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot );
1120                     SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot );
1121                     SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot );
1122                     SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot);
1123                   }
1124                   break;
1125                }
1126              }
1127
1128           }
1129           else // 2D
1130           {
1131              CArray<double,2> field_data2D(domain->zoom_ni_srv,domain->zoom_nj_srv) ;
1132              if (!field->default_value.isEmpty()) field_data2D = field->default_value ;
1133              field->outputField(field_data2D);
1134              if (!field->prec.isEmpty() && field->prec==2) field_data2D=round(field_data2D) ;
1135              switch (SuperClass::type)
1136              {
1137                case (MULTI_FILE) :
1138                {
1139                  SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep()-1);
1140                  if (wtime)
1141                  {
1142                    SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep()-1);
1143                    SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep()-1);
1144                    SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1);
1145                    SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1);
1146                  }
1147                  break;
1148                }
1149                case (ONE_FILE) :
1150                {
1151                   std::vector<StdSize> start(2) ;
1152                   std::vector<StdSize> count(2) ;
1153                   if (domain->isEmpty())
1154                   {
1155                     start[0]=0 ; start[1]=0 ;
1156                     count[0]=0 ; count[1]=0 ;
1157                   }
1158                   else
1159                   {
1160                     start[1]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
1161                     count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
1162                   }
1163
1164                   SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep()-1,&start,&count);
1165                   if (wtime)
1166                   {
1167                     SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot);
1168                     SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot);
1169                     SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot);
1170                     SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot);
1171                   }
1172                   break;
1173
1174                }
1175              }
1176           }
1177         }
1178         catch (CNetCdfException& e)
1179         {
1180           StdString msg("On writing field data: ");
1181           msg.append(fieldid); msg.append("\n");
1182           msg.append("In the context : ");
1183           msg.append(context->getId()); msg.append("\n");
1184           msg.append(e.what());
1185           ERROR("CNc4DataOutput::writeFieldData_ (CField*  field)", << msg);
1186         }
1187      }
1188
1189      //---------------------------------------------------------------
1190
1191      void CNc4DataOutput::writeTimeAxis_
1192                  (CField*    field,
1193                   const boost::shared_ptr<CCalendar> cal)
1194      {
1195         StdOStringStream oss;
1196
1197//         if (field->operation.getValue().compare("once") == 0) return ;
1198         if (field->foperation->timeType() == func::CFunctor::once) return ;
1199
1200//         oss << "time_" << field->operation.getValue()
1201//             << "_" << field->getRelFile()->output_freq.getValue();
1202
1203//         StdString axisid = oss.str();
1204//         if (field->foperation->timeType() == func::CFunctor::centered) axisid="time_centered" ;
1205//         else if (field->foperation->timeType() == func::CFunctor::instant) axisid="time_instant" ;
1206
1207         StdString axisid("time_centered") ;
1208         StdString axisBoundId("time_centered_bounds");
1209         StdString timeid("time_counter");
1210         StdString timeBoundId("time_bounds");
1211
1212         if (field->foperation->timeType() == func::CFunctor::instant)
1213         {
1214            axisid = "time_instant";
1215            axisBoundId = "time_instant_bounds";
1216         }
1217
1218         try
1219         {
1220          // Adding time_instant or time_centered
1221           std::vector<StdString> dims;
1222           dims.push_back(timeid);
1223           if (!SuperClassWriter::varExist(axisid))
1224           {
1225              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1226
1227              CDate timeOrigin=cal->getTimeOrigin() ;
1228              StdOStringStream oss2;
1229  //            oss2<<initDate.getYear()<<"-"<<initDate.getMonth()<<"-"<<initDate.getDay()<<" "
1230  //                <<initDate.getHour()<<"-"<<initDate.getMinute()<<"-"<<initDate.getSecond() ;
1231              StdString strInitdate=oss2.str() ;
1232              StdString strTimeOrigin=timeOrigin.toString() ;
1233              this->writeTimeAxisAttributes
1234                 (axisid, cal->getType(),
1235                  StdString("seconds since ").append(strTimeOrigin),
1236                  strTimeOrigin, axisBoundId);
1237           }
1238
1239           // Adding time_instant_bounds or time_centered_bounds variables
1240           if (!SuperClassWriter::varExist(axisBoundId))
1241           {
1242              dims.clear() ;
1243              dims.push_back(timeid);
1244              dims.push_back(timeBoundId);
1245              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1246           }
1247
1248           // Adding time_counter
1249           axisid = "time_counter" ;
1250           axisBoundId = "time_counter_bounds" ;
1251           dims.clear() ;
1252           dims.push_back(timeid);
1253           if (!SuperClassWriter::varExist(axisid))
1254           {
1255              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1256              SuperClassWriter::addAttribute("axis", string("T"), &axisid);
1257              CDate timeOrigin=cal->getTimeOrigin() ;
1258              StdString strTimeOrigin=timeOrigin.toString() ;
1259
1260              this->writeTimeAxisAttributes
1261                 (axisid, cal->getType(),
1262                  StdString("seconds since ").append(strTimeOrigin),
1263                  strTimeOrigin, axisBoundId);
1264           }
1265
1266           // Adding time_counter_bound dimension
1267           if (!SuperClassWriter::varExist(axisBoundId))
1268           {
1269              dims.clear();
1270              dims.push_back(timeid);
1271              dims.push_back(timeBoundId);
1272              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1273           }
1274         }
1275         catch (CNetCdfException& e)
1276         {
1277           StdString msg("On writing time axis data: ");
1278           msg.append("In the context : ");
1279           CContext* context = CContext::getCurrent() ;
1280           msg.append(context->getId()); msg.append("\n");
1281           msg.append(e.what());
1282           ERROR("CNc4DataOutput::writeTimeAxis_ (CField*    field, \
1283                  const boost::shared_ptr<CCalendar> cal)", << msg);
1284         }
1285      }
1286
1287      //---------------------------------------------------------------
1288
1289      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
1290                                                   const StdString & calendar,
1291                                                   const StdString & units,
1292                                                   const StdString & time_origin,
1293                                                   const StdString & time_bounds,
1294                                                   const StdString & standard_name,
1295                                                   const StdString & long_name)
1296      {
1297         try
1298         {
1299           SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1300           SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
1301           SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
1302           SuperClassWriter::addAttribute("units",         units        , &axis_name);
1303           SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
1304           SuperClassWriter::addAttribute("bounds",        time_bounds  , &axis_name);
1305         }
1306         catch (CNetCdfException& e)
1307         {
1308           StdString msg("On writing time axis Attribute: ");
1309           msg.append("In the context : ");
1310           CContext* context = CContext::getCurrent() ;
1311           msg.append(context->getId()); msg.append("\n");
1312           msg.append(e.what());
1313           ERROR("CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name, \
1314                                                          const StdString & calendar,\
1315                                                          const StdString & units, \
1316                                                          const StdString & time_origin, \
1317                                                          const StdString & time_bounds, \
1318                                                          const StdString & standard_name, \
1319                                                          const StdString & long_name)", << 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          if (!axis.empty())
1335            SuperClassWriter::addAttribute("axis"       , axis         , &axis_name);
1336
1337          SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1338          SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
1339          SuperClassWriter::addAttribute("units"        , units        , &axis_name);
1340          SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
1341         }
1342         catch (CNetCdfException& e)
1343         {
1344           StdString msg("On writing Axis Attribute: ");
1345           msg.append("In the context : ");
1346           CContext* context = CContext::getCurrent() ;
1347           msg.append(context->getId()); msg.append("\n");
1348           msg.append(e.what());
1349           ERROR("CNc4DataOutput::writeAxisAttributes(const StdString & axis_name, \
1350                                                      const StdString & axis, \
1351                                                      const StdString & standard_name, \
1352                                                      const StdString & long_name, \
1353                                                      const StdString & units, \
1354                                                      const StdString & nav_model)", << msg);
1355         }
1356      }
1357
1358      //---------------------------------------------------------------
1359
1360      void CNc4DataOutput::writeLocalAttributes
1361         (int ibegin, int ni, int jbegin, int nj, StdString domid)
1362      {
1363        try
1364        {
1365         SuperClassWriter::addAttribute(StdString("ibegin").append(domid), ibegin);
1366         SuperClassWriter::addAttribute(StdString("ni"    ).append(domid), ni);
1367         SuperClassWriter::addAttribute(StdString("jbegin").append(domid), jbegin);
1368         SuperClassWriter::addAttribute(StdString("nj"    ).append(domid), nj);
1369        }
1370        catch (CNetCdfException& e)
1371        {
1372           StdString msg("On writing Local Attributes: ");
1373           msg.append("In the context : ");
1374           CContext* context = CContext::getCurrent() ;
1375           msg.append(context->getId()); msg.append("\n");
1376           msg.append(e.what());
1377           ERROR("CNc4DataOutput::writeLocalAttributes \
1378                  (int ibegin, int ni, int jbegin, int nj, StdString domid)", << msg);
1379        }
1380
1381      }
1382
1383     void CNc4DataOutput::writeLocalAttributes_IOIPSL
1384         (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)
1385      {
1386         CArray<int,1> array(2) ;
1387
1388         try
1389         {
1390           SuperClassWriter::addAttribute("DOMAIN_number_total",size ) ;
1391           SuperClassWriter::addAttribute("DOMAIN_number", rank) ;
1392           array=1,2 ;
1393           SuperClassWriter::addAttribute("DOMAIN_dimensions_ids",array) ;
1394           array=ni_glo,nj_glo ;
1395           SuperClassWriter::addAttribute("DOMAIN_size_global", array) ;
1396           array=ni,nj ;
1397           SuperClassWriter::addAttribute("DOMAIN_size_local", array) ;
1398           array=ibegin,jbegin ;
1399           SuperClassWriter::addAttribute("DOMAIN_position_first", array) ;
1400           array=ibegin+ni-1,jbegin+nj-1 ;
1401           SuperClassWriter::addAttribute("DOMAIN_position_last",array) ;
1402           array=0,0 ;
1403           SuperClassWriter::addAttribute("DOMAIN_halo_size_start", array) ;
1404           SuperClassWriter::addAttribute("DOMAIN_halo_size_end", array);
1405           SuperClassWriter::addAttribute("DOMAIN_type",string("box")) ;
1406  /*
1407           SuperClassWriter::addAttribute("DOMAIN_DIM_N001",string("x")) ;
1408           SuperClassWriter::addAttribute("DOMAIN_DIM_N002",string("y")) ;
1409           SuperClassWriter::addAttribute("DOMAIN_DIM_N003",string("axis_A")) ;
1410           SuperClassWriter::addAttribute("DOMAIN_DIM_N004",string("time_counter")) ;
1411  */
1412         }
1413         catch (CNetCdfException& e)
1414         {
1415           StdString msg("On writing Local Attributes IOI PSL \n");
1416           msg.append("In the context : ");
1417           CContext* context = CContext::getCurrent() ;
1418           msg.append(context->getId()); msg.append("\n");
1419           msg.append(e.what());
1420           ERROR("CNc4DataOutput::writeLocalAttributes_IOIPSL \
1421                  (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)", << msg);
1422         }
1423      }
1424      //---------------------------------------------------------------
1425
1426      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
1427                                                const StdString & description,
1428                                                const StdString & conventions,
1429                                                const StdString & production,
1430                                                const StdString & timeStamp)
1431      {
1432         try
1433         {
1434           SuperClassWriter::addAttribute("name"       , name);
1435           SuperClassWriter::addAttribute("description", description);
1436           SuperClassWriter::addAttribute("title"      , description);
1437           SuperClassWriter::addAttribute("Conventions", conventions);
1438           SuperClassWriter::addAttribute("production" , production);
1439           SuperClassWriter::addAttribute("timeStamp"  , timeStamp);
1440         }
1441         catch (CNetCdfException& e)
1442         {
1443           StdString msg("On writing File Attributes \n ");
1444           msg.append("In the context : ");
1445           CContext* context = CContext::getCurrent() ;
1446           msg.append(context->getId()); msg.append("\n");
1447           msg.append(e.what());
1448           ERROR("CNc4DataOutput:: writeFileAttributes(const StdString & name, \
1449                                                const StdString & description, \
1450                                                const StdString & conventions, \
1451                                                const StdString & production, \
1452                                                const StdString & timeStamp)", << msg);
1453         }
1454      }
1455
1456      //---------------------------------------------------------------
1457
1458      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
1459                                               int data_dim,
1460                                               int data_ni,
1461                                               int data_nj,
1462                                               int data_ibegin,
1463                                               int data_jbegin)
1464      {
1465         try
1466         {
1467           SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
1468           SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
1469           SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
1470           SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
1471           SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
1472         }
1473         catch (CNetCdfException& e)
1474         {
1475           StdString msg("On writing Mask Attributes \n ");
1476           msg.append("In the context : ");
1477           CContext* context = CContext::getCurrent() ;
1478           msg.append(context->getId()); msg.append("\n");
1479           msg.append(e.what());
1480           ERROR("CNc4DataOutput::writeMaskAttributes(const StdString & mask_name, \
1481                                               int data_dim, \
1482                                               int data_ni, \
1483                                               int data_nj, \
1484                                               int data_ibegin, \
1485                                               int data_jbegin)", << msg);
1486         }
1487      }
1488
1489      ///--------------------------------------------------------------
1490
1491} // namespace xios
Note: See TracBrowser for help on using the repository browser.