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

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

Improve CF compliance: Minor tweaks and improvements.

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