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

Last change on this file since 811 was 802, checked in by rlacroix, 8 years ago

Add a new file attribute time_counter_name.

Users can now modify the name of the time counter dimension and axis name.

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