source: XIOS/dev/dev_olga/src/io/nc4_data_output.cpp @ 1589

Last change on this file since 1589 was 1589, checked in by oabramkina, 6 years ago

Backporting r1578 and r1586 to dev, cleaning the code before merging it to XIOS 2.5.

  • 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: 132.0 KB
RevLine 
[219]1#include "nc4_data_output.hpp"
2
[352]3#include "attribute_template.hpp"
4#include "group_template.hpp"
[219]5
6#include "file.hpp"
7#include "calendar.hpp"
[278]8#include "context.hpp"
[300]9#include "context_server.hpp"
[498]10#include "netCdfException.hpp"
11#include "exception.hpp"
[1158]12#include "timer.hpp"
13#include "uuid.hpp"
[335]14namespace xios
[219]15{
[878]16      /// ////////////////////// Dfinitions ////////////////////// ///
[219]17      CNc4DataOutput::CNc4DataOutput
[1158]18         (CFile* file, const StdString & filename, bool exist)
[219]19            : SuperClass()
20            , SuperClassWriter(filename, exist)
21            , filename(filename)
[1158]22            , file(file),hasTimeInstant(false),hasTimeCentered(false), timeCounterType(none)
[219]23      {
[1158]24        SuperClass::type = MULTI_FILE;
[1456]25        compressionLevel= file->compression_level.isEmpty() ? 0 :file->compression_level ;
[219]26      }
27
28      CNc4DataOutput::CNc4DataOutput
[1158]29         (CFile* file, const StdString & filename, bool exist, bool useClassicFormat, bool useCFConvention,
[924]30          MPI_Comm comm_file, bool multifile, bool isCollective, const StdString& timeCounterName)
[219]31            : SuperClass()
[878]32            , SuperClassWriter(filename, exist, useClassicFormat, useCFConvention, &comm_file, multifile, timeCounterName)
[379]33            , comm_file(comm_file)
[219]34            , filename(filename)
[335]35            , isCollective(isCollective)
[1158]36            , file(file),hasTimeInstant(false),hasTimeCentered(false), timeCounterType(none)
[219]37      {
[1158]38        SuperClass::type = (multifile) ? MULTI_FILE : ONE_FILE;
[1459]39        if (file==NULL) compressionLevel = 0 ;
40        else compressionLevel= file->compression_level.isEmpty() ? 0 :file->compression_level ;
[219]41      }
42
43      CNc4DataOutput::~CNc4DataOutput(void)
[879]44    { /* Ne rien faire de plus */ }
[219]45
46      ///--------------------------------------------------------------
47
48      const StdString & CNc4DataOutput::getFileName(void) const
49      {
50         return (this->filename);
51      }
52
53      //---------------------------------------------------------------
54
[347]55      void CNc4DataOutput::writeDomain_(CDomain* domain)
[219]56      {
[1391]57        StdString lonName,latName ;
[1571]58
[1129]59        domain->computeWrittenIndex();
[1249]60        domain->computeWrittenCompressedIndex(comm_file);
61
[881]62        if (domain->type == CDomain::type_attr::unstructured)
63        {
64          if (SuperClassWriter::useCFConvention)
65            writeUnstructuredDomain(domain) ;
66          else
67            writeUnstructuredDomainUgrid(domain) ;
68          return ;
69        }
[488]70
[347]71         CContext* context = CContext::getCurrent() ;
[300]72         CContextServer* server=context->server ;
[488]73
[219]74         if (domain->IsWritten(this->filename)) return;
75         domain->checkAttributes();
[488]76
77         if (domain->isEmpty())
[881]78           if (SuperClass::type==MULTI_FILE) return;
[219]79
80         std::vector<StdString> dim0, dim1;
[772]81         StdString domid = domain->getDomainOutputName();
[318]82         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
[706]83         if (isWrittenDomain(domid)) return ;
[774]84         else setWrittenDomain(domid);
[1132]85       
86         int nvertex = (domain->nvertex.isEmpty()) ? 0 : domain->nvertex;
[449]87
[488]88
[1158]89        StdString dimXid, dimYid ;
90
91        nc_type typePrec ;
92        if (domain->prec.isEmpty()) typePrec =  NC_FLOAT ;
93        else if (domain->prec==4)  typePrec =  NC_FLOAT ;
94        else if (domain->prec==8)   typePrec =  NC_DOUBLE ;
95         
[664]96         bool isRegularDomain = (domain->type == CDomain::type_attr::rectilinear);
[449]97         switch (domain->type)
[433]98         {
[449]99           case CDomain::type_attr::curvilinear :
[1391]100
101             if (domain->lon_name.isEmpty()) lonName = "nav_lon";
102             else lonName = domain->lon_name;
103
104             if (domain->lat_name.isEmpty()) latName = "nav_lat";
105             else latName = domain->lat_name;
106
[1430]107             if (domain->dim_i_name.isEmpty()) dimXid=StdString("x").append(appendDomid);
108             else dimXid=domain->dim_i_name.getValue() + appendDomid;
109
110             if (domain->dim_j_name.isEmpty()) dimYid=StdString("y").append(appendDomid);
111             else dimYid=domain->dim_j_name.getValue() + appendDomid;
112
[449]113             break ;
[1391]114
[664]115           case CDomain::type_attr::rectilinear :
[1391]116
[1430]117             if (domain->lon_name.isEmpty())
118             {
119               if (domain->dim_i_name.isEmpty())
120                   lonName = "lon";
121               else
122                 lonName = domain->dim_i_name.getValue();
123             }
[1391]124             else lonName = domain->lon_name;
125
[1430]126             if (domain->lat_name.isEmpty())
127             {
128               if (domain->dim_j_name.isEmpty())
129                 latName = "lat";
130               else
131                 latName = domain->dim_j_name.getValue();
132             }
[1391]133             else latName = domain->lat_name;
134             
[1430]135             if (domain->dim_i_name.isEmpty()) dimXid = lonName+appendDomid;
136             else dimXid = domain->dim_i_name.getValue()+appendDomid;
137
138             if (domain->dim_j_name.isEmpty()) dimYid = latName+appendDomid;
139             else dimYid = domain->dim_j_name.getValue()+appendDomid;
[449]140             break;
[488]141         }
142
[617]143         StdString dimVertId = StdString("nvertex").append(appendDomid);
144
[449]145         string lonid,latid,bounds_lonid,bounds_latid ;
[611]146         string areaId = "area" + appendDomid;
[391]147/*
[300]148         StdString lonid_loc = (server->intraCommSize > 1)
[318]149                             ? StdString("lon").append(appendDomid).append("_local")
[278]150                             : lonid;
[300]151         StdString latid_loc = (server->intraCommSize > 1)
[318]152                             ? StdString("lat").append(appendDomid).append("_local")
[278]153                             : latid;
[391]154*/
[219]155
[1571]156         CArray<int, 1>& indexToWrite = domain->localIndexToWriteOnServer;
[1129]157         int nbWritten = indexToWrite.numElements();
158         CArray<double,1> writtenLat, writtenLon;
159         CArray<double,2> writtenBndsLat, writtenBndsLon;
160         CArray<double,1> writtenArea;
161
162         if (domain->hasLonLat)
163         {
164           writtenLat.resize(nbWritten);
165           writtenLon.resize(nbWritten);
166           for (int idx = 0; idx < nbWritten; ++idx)
167           {
[1589]168             if (indexToWrite(idx) < 0)
169             {
170               writtenLat(idx) = -1.;   // hole
171               writtenLon(idx) = -1.;
172             }
173             else
174             {
175               writtenLat(idx) = domain->latvalue(indexToWrite(idx));
176               writtenLon(idx) = domain->lonvalue(indexToWrite(idx));
177             }
[1129]178           }
179
180           if (domain->hasBounds)
181           {         
182             int nvertex = domain->nvertex, idx;
183             writtenBndsLat.resize(nvertex, nbWritten);
184             writtenBndsLon.resize(nvertex, nbWritten);
185             CArray<double,2>& boundslat = domain->bounds_latvalue;
186             CArray<double,2>& boundslon = domain->bounds_lonvalue;   
187             for (idx = 0; idx < nbWritten; ++idx)
188               for (int nv = 0; nv < nvertex; ++nv)
189               {
[1571]190                 if (indexToWrite(idx) < 0)
191                 {
192                   writtenBndsLat(nv, idx) = -1.;  // hole
193                   writtenBndsLon(nv, idx) = -1.;
194                 }
195                 else
196                 {
[1390]197                   writtenBndsLat(nv, idx) = boundslat(nv, int(indexToWrite(idx)));
198                   writtenBndsLon(nv, idx) = boundslon(nv, int(indexToWrite(idx)));
[1571]199                 }
[1129]200               }
201           }
202         }
203
204         if (domain->hasArea)
205         {
206           writtenArea.resize(nbWritten);           
207           for (int idx = 0; idx < nbWritten; ++idx)
208           {
[1571]209                  if (indexToWrite(idx) < 0)
210              writtenArea(idx) = -1.;
[1390]211                  else
[1571]212              writtenArea(idx) = domain->areavalue(indexToWrite(idx));
[1129]213           }
214         }
215
[498]216         try
[219]217         {
[498]218           switch (SuperClass::type)
219           {
220              case (MULTI_FILE) :
221              {
222                 switch (domain->type)
223                 {
224                   case CDomain::type_attr::curvilinear :
225                     dim0.push_back(dimYid); dim0.push_back(dimXid);
[1415]226                     lonid = lonName+appendDomid;
227                     latid = latName+appendDomid;
[498]228                     break ;
[664]229                   case CDomain::type_attr::rectilinear :
[1415]230                     lonid = lonName+appendDomid;
231                     latid = latName+appendDomid;
[498]232                     dim0.push_back(dimYid);
233                     dim1.push_back(dimXid);
234                     break;
235                 }
[1430]236                 if (!domain->bounds_lon_name.isEmpty()) bounds_lonid = domain->bounds_lon_name;
237                 else bounds_lonid = "bounds_"+lonName+appendDomid;
238                 if (!domain->bounds_lat_name.isEmpty()) bounds_latid = domain->bounds_lat_name;
239                 else bounds_latid = "bounds_"+latName+appendDomid;
[488]240
[1553]241                 SuperClassWriter::addDimension(dimXid, domain->ni);
242                 SuperClassWriter::addDimension(dimYid, domain->nj);
[488]243
[617]244                 if (domain->hasBounds)
245                   SuperClassWriter::addDimension(dimVertId, domain->nvertex);
246
[498]247                 if (server->intraCommSize > 1)
248                 {
[1553]249                   this->writeLocalAttributes(domain->ibegin,
250                                              domain->ni,
251                                              domain->jbegin,
252                                              domain->nj,
[616]253                                              appendDomid);
[488]254
[628]255                   if (singleDomain)
256                    this->writeLocalAttributes_IOIPSL(dimXid, dimYid,
[1553]257                                                      domain->ibegin,
258                                                      domain->ni,
259                                                      domain->jbegin,
260                                                      domain->nj,
[628]261                                                      domain->ni_glo,domain->nj_glo,
262                                                      server->intraCommRank,server->intraCommSize);
[449]263                 }
[488]264
[665]265                 if (domain->hasLonLat)
[498]266                 {
[665]267                   switch (domain->type)
268                   {
269                     case CDomain::type_attr::curvilinear :
[1456]270                       SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel);
271                       SuperClassWriter::addVariable(lonid, typePrec, dim0, compressionLevel);
[665]272                       break ;
273                      case CDomain::type_attr::rectilinear :
[1456]274                        SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel);
275                        SuperClassWriter::addVariable(lonid, typePrec, dim1, compressionLevel);
[665]276                        break ;
277                   }
[488]278
[665]279                   this->writeAxisAttributes(lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
280                   this->writeAxisAttributes(latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
[219]281
[665]282                   if (domain->hasBounds)
283                   {
284                     SuperClassWriter::addAttribute("bounds", bounds_lonid, &lonid);
285                     SuperClassWriter::addAttribute("bounds", bounds_latid, &latid);
[617]286
[665]287                     dim0.clear();
288                     dim0.push_back(dimYid);
289                     dim0.push_back(dimXid);
290                     dim0.push_back(dimVertId);
[1456]291                     SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0, compressionLevel);
292                     SuperClassWriter::addVariable(bounds_latid, typePrec, dim0, compressionLevel);
[665]293                   }
[617]294                 }
295
[498]296                 dim0.clear();
[616]297                 dim0.push_back(dimYid);
[498]298                 dim0.push_back(dimXid);
[219]299
300
[498]301  // supress mask               if (server->intraCommSize > 1)
302  // supress mask               {
303  // supress mask                  SuperClassWriter::addVariable(maskid, NC_INT, dim0);
304  // supress mask
305  // supress mask                  this->writeMaskAttributes(maskid,
306  // supress mask                     domain->data_dim.getValue()/*,
307  // supress mask                     domain->data_ni.getValue(),
308  // supress mask                     domain->data_nj.getValue(),
309  // supress mask                     domain->data_ibegin.getValue(),
310  // supress mask                     domain->data_jbegin.getValue()*/);
311  // supress mask               }
[488]312
[498]313                 //SuperClassWriter::setDefaultValue(maskid, &dvm);
[219]314
[611]315                 if (domain->hasArea)
316                 {
[1456]317                   SuperClassWriter::addVariable(areaId, typePrec, dim0, compressionLevel);
[614]318                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
[611]319                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
320                 }
321
[498]322                 SuperClassWriter::definition_end();
[449]323
[665]324                 if (domain->hasLonLat)
[498]325                 {
[665]326                   switch (domain->type)
327                   {
[1129]328                     case CDomain::type_attr::curvilinear :                       
329                       SuperClassWriter::writeData(writtenLat, latid, isCollective, 0);
330                       SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0);
[665]331                       break;
332                     case CDomain::type_attr::rectilinear :
[1553]333                       CArray<double,1> lat = writtenLat(Range(fromStart,toEnd,domain->ni)) ;
[665]334                       SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0);
[1553]335                       CArray<double,1> lon = writtenLon(Range(0,domain->ni-1)) ;
[665]336                       SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0);
337                       break;
338                   }
[611]339
[665]340                   if (domain->hasBounds)
341                   {
[1129]342                     SuperClassWriter::writeData(writtenBndsLon, bounds_lonid, isCollective, 0);
343                     SuperClassWriter::writeData(writtenBndsLat, bounds_latid, isCollective, 0);
[665]344                   }
[617]345                 }
346
[611]347                 if (domain->hasArea)
[1129]348                 {
[1132]349                   SuperClassWriter::writeData(writtenArea, areaId, isCollective, 0);                   
[1129]350                 }
351
[498]352                 SuperClassWriter::definition_start();
[219]353
[498]354                 break;
355              }
356              case (ONE_FILE) :
357              {
[1553]358                SuperClassWriter::addDimension(dimXid, domain->ni_glo);
359                SuperClassWriter::addDimension(dimYid, domain->nj_glo);
[286]360
[617]361                 if (domain->hasBounds)
362                   SuperClassWriter::addDimension(dimVertId, domain->nvertex);
363
[665]364                 if (domain->hasLonLat)
[498]365                 {
[665]366                   switch (domain->type)
367                   {
368                     case CDomain::type_attr::curvilinear :
369                       dim0.push_back(dimYid); dim0.push_back(dimXid);
[1415]370                       lonid = lonName+appendDomid;
371                       latid = latName+appendDomid;
[1456]372                       SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel);
373                       SuperClassWriter::addVariable(lonid, typePrec, dim0, compressionLevel);
[665]374                       break;
[449]375
[665]376                     case CDomain::type_attr::rectilinear :
377                       dim0.push_back(dimYid);
378                       dim1.push_back(dimXid);
[1415]379                       lonid = lonName+appendDomid;
380                       latid = latName+appendDomid;
[1456]381                       SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel);
382                       SuperClassWriter::addVariable(lonid, typePrec, dim1, compressionLevel);
[665]383                       break;
384                   }
[1430]385                   if (!domain->bounds_lon_name.isEmpty()) bounds_lonid = domain->bounds_lon_name;
386                   else bounds_lonid = "bounds_"+lonName+appendDomid;
387                   if (!domain->bounds_lat_name.isEmpty()) bounds_latid = domain->bounds_lat_name;
388                   else bounds_latid = "bounds_"+latName+appendDomid;
[665]389
390                   this->writeAxisAttributes
391                      (lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
392                   this->writeAxisAttributes
393                      (latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
394
395                   if (domain->hasBounds)
396                   {
397                     SuperClassWriter::addAttribute("bounds", bounds_lonid, &lonid);
398                     SuperClassWriter::addAttribute("bounds", bounds_latid, &latid);
399
400                     dim0.clear();
[498]401                     dim0.push_back(dimYid);
[665]402                     dim0.push_back(dimXid);
403                     dim0.push_back(dimVertId);
[1456]404                     SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0, compressionLevel);
405                     SuperClassWriter::addVariable(bounds_latid, typePrec, dim0, compressionLevel);
[665]406                   }
[498]407                 }
[611]408
409                 if (domain->hasArea)
410                 {
411                   dim0.clear();
412                   dim0.push_back(dimYid); dim0.push_back(dimXid);
[1456]413                   SuperClassWriter::addVariable(areaId, typePrec, dim0, compressionLevel);
[614]414                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
[611]415                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
416                   dim0.clear();
417                 }
418
419                 SuperClassWriter::definition_end();
[286]420
[498]421                 switch (domain->type)
[384]422                 {
[498]423                   case CDomain::type_attr::curvilinear :
[449]424                   {
[498]425                     std::vector<StdSize> start(2) ;
426                     std::vector<StdSize> count(2) ;
[1571]427// Comment out for a moment because it is not working for a hole
428//                     if (domain->isEmpty())
429//                     {
430//                       start[0]=0 ; start[1]=0 ;
431//                       count[0]=0 ; count[1]=0 ;
432//                     }
433//                     else
[498]434                     {
[1553]435                       start[1]=domain->ibegin;
436                       start[0]=domain->jbegin;
437                       count[1]=domain->ni ; count[0]=domain->nj ;
[498]438                     }
[488]439
[665]440                     if (domain->hasLonLat)
441                     {
[1129]442                       SuperClassWriter::writeData(writtenLat, latid, isCollective, 0,&start,&count);
443                       SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0,&start,&count);
[665]444                     }
[498]445                     break;
446                   }
[664]447                   case CDomain::type_attr::rectilinear :
[449]448                   {
[665]449                     if (domain->hasLonLat)
[498]450                     {
[665]451                       std::vector<StdSize> start(1) ;
452                       std::vector<StdSize> count(1) ;
453                       if (domain->isEmpty())
454                       {
455                         start[0]=0 ;
456                         count[0]=0 ;
[1129]457                         SuperClassWriter::writeData(writtenLat, latid, isCollective, 0,&start,&count);
458                         SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0,&start,&count);
[665]459                       }
460                       else
[1129]461                       { 
[1553]462                         start[0]=domain->jbegin;
463                         count[0]=domain->nj;
464                         CArray<double,1> lat = writtenLat(Range(fromStart,toEnd,domain->ni));
[665]465                         SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0,&start,&count);
466
[1553]467                         start[0]=domain->ibegin;
468                         count[0]=domain->ni;
469                         CArray<double,1> lon = writtenLon(Range(0,domain->ni-1));
[665]470                         SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0,&start,&count);
471                       }
[498]472                     }
473                     break;
[449]474                   }
[384]475                 }
[611]476
[617]477                 if (domain->hasBounds)
478                 {
479                   std::vector<StdSize> start(3);
480                   std::vector<StdSize> count(3);
481                   if (domain->isEmpty())
482                   {
483                     start[2] = start[1] = start[0] = 0;
484                     count[2] = count[1] = count[0] = 0;
485                   }
486                   else
487                   {
488                     start[2] = 0;
[1553]489                     start[1] = domain->ibegin;
490                     start[0] = domain->jbegin;
[1099]491                     count[2] = domain->nvertex;
[1553]492                     count[1] = domain->ni;
493                     count[0] = domain->nj;
[617]494                   }
[1143]495                 
[1129]496                   SuperClassWriter::writeData(writtenBndsLon, bounds_lonid, isCollective, 0, &start, &count);
497                   SuperClassWriter::writeData(writtenBndsLat, bounds_latid, isCollective, 0, &start, &count);
[617]498                 }
499
[611]500                 if (domain->hasArea)
501                 {
502                   std::vector<StdSize> start(2);
503                   std::vector<StdSize> count(2);
504
505                   if (domain->isEmpty())
506                   {
507                     start[0] = 0; start[1] = 0;
508                     count[0] = 0; count[1] = 0;
509                   }
510                   else
511                   {
[1553]512                     start[1] = domain->ibegin;
513                     start[0] = domain->jbegin;
514                     count[1] = domain->ni;
515                     count[0] = domain->nj;
[611]516                   }
[1143]517                   
[1129]518                   SuperClassWriter::writeData(writtenArea, areaId, isCollective, 0, &start, &count);
[611]519                 }
520
[498]521                 SuperClassWriter::definition_start();
522                 break;
523              }
524              default :
525                 ERROR("CNc4DataOutput::writeDomain(domain)",
526                       << "[ type = " << SuperClass::type << "]"
527                       << " not implemented yet !");
528           }
[449]529         }
[498]530         catch (CNetCdfException& e)
531         {
532           StdString msg("On writing the domain : ");
533           msg.append(domid); msg.append("\n");
534           msg.append("In the context : ");
535           msg.append(context->getId()); msg.append("\n");
536           msg.append(e.what());
537           ERROR("CNc4DataOutput::writeDomain_(CDomain* domain)", << msg);
538         }
539
[449]540         domain->addRelFile(this->filename);
541      }
542
[879]543    //--------------------------------------------------------------
[878]544
[879]545    void CNc4DataOutput::writeUnstructuredDomainUgrid(CDomain* domain)
546    {
547      CContext* context = CContext::getCurrent() ;
548      CContextServer* server=context->server ;
[878]549
[879]550      if (domain->IsWritten(this->filename)) return;
[1494]551
552      StdString domid = domain->getDomainOutputName();
553
554      // The first domain for the same mesh that will be written is that with the highest value of nvertex.
555      // Thus the entire mesh connectivity will be generated at once.
556      if (isWrittenDomain(domid)) return ;
557      else setWrittenDomain(domid);
558
[879]559      domain->checkAttributes();
560      if (domain->isEmpty())
561        if (SuperClass::type==MULTI_FILE) return ;
[878]562
[1158]563     nc_type typePrec ;
564     if (domain->prec.isEmpty()) typePrec =  NC_FLOAT ;
565     else if (domain->prec==4)  typePrec =  NC_FLOAT ;
566     else if (domain->prec==8)   typePrec =  NC_DOUBLE ;
567
[879]568      std::vector<StdString> dim0;
569      StdString domainName = domain->name;
[924]570      domain->assignMesh(domainName, domain->nvertex);
[1025]571      domain->mesh->createMeshEpsilon(server->intraComm, domain->lonvalue, domain->latvalue, domain->bounds_lonvalue, domain->bounds_latvalue);
[878]572
[879]573      StdString node_x = domainName + "_node_x";
574      StdString node_y = domainName + "_node_y";
[878]575
[879]576      StdString edge_x = domainName + "_edge_x";
577      StdString edge_y = domainName + "_edge_y";
578      StdString edge_nodes = domainName + "_edge_nodes";
[878]579
[879]580      StdString face_x = domainName + "_face_x";
581      StdString face_y = domainName + "_face_y";
582      StdString face_nodes = domainName + "_face_nodes";
[902]583      StdString face_edges = domainName + "_face_edges";
584      StdString edge_faces = domainName + "_edge_face_links";
585      StdString face_faces = domainName + "_face_links";
[878]586
[879]587      StdString dimNode = "n" + domainName + "_node";
588      StdString dimEdge = "n" + domainName + "_edge";
589      StdString dimFace = "n" + domainName + "_face";
590      StdString dimVertex = "n" + domainName + "_vertex";
591      StdString dimTwo = "Two";
[878]592
[879]593      if (!SuperClassWriter::dimExist(dimTwo)) SuperClassWriter::addDimension(dimTwo, 2);
[1494]594      dim0.clear();
595      SuperClassWriter::addVariable(domainName, NC_INT, dim0, compressionLevel);
596      SuperClassWriter::addAttribute("cf_role", StdString("mesh_topology"), &domainName);
597      SuperClassWriter::addAttribute("long_name", StdString("Topology data of 2D unstructured mesh"), &domainName);
598      SuperClassWriter::addAttribute("topology_dimension", 2, &domainName);
599      SuperClassWriter::addAttribute("node_coordinates", node_x + " " + node_y, &domainName);
[878]600
[879]601      try
602      {
603        switch (SuperClass::type)
604        {
605          case (ONE_FILE) :
606          {
607            // Adding nodes
608            if (domain->nvertex == 1)
609            {
610              if (!SuperClassWriter::varExist(node_x) || !SuperClassWriter::varExist(node_y))
611              {
[902]612                SuperClassWriter::addDimension(dimNode, domain->ni_glo);
[879]613                dim0.clear();
614                dim0.push_back(dimNode);
[1456]615                SuperClassWriter::addVariable(node_x, typePrec, dim0, compressionLevel);
[879]616                SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x);
[924]617                SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x);
[879]618                SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x);
[1456]619                SuperClassWriter::addVariable(node_y, typePrec, dim0, compressionLevel);
[879]620                SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y);
[924]621                SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y);
[879]622                SuperClassWriter::addAttribute("units", StdString("degrees_north"), &node_y);
623              }
624            } // domain->nvertex == 1
[878]625
[879]626            // Adding edges and nodes, if nodes have not been defined previously
627            if (domain->nvertex == 2)
628            {
629              if (!SuperClassWriter::varExist(node_x) || !SuperClassWriter::varExist(node_y))
630              {
[924]631                SuperClassWriter::addDimension(dimNode, domain->mesh->nbNodesGlo);
[879]632                dim0.clear();
633                dim0.push_back(dimNode);
[1456]634                SuperClassWriter::addVariable(node_x, typePrec, dim0, compressionLevel);
[879]635                SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x);
[924]636                SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x);
[879]637                SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x);
[1456]638                SuperClassWriter::addVariable(node_y, typePrec, dim0, compressionLevel);
[879]639                SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y);
[924]640                SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y);
[879]641                SuperClassWriter::addAttribute("units", StdString("degrees_north"), &node_y);
642              }
[924]643              SuperClassWriter::addAttribute("edge_node_connectivity", edge_nodes, &domainName);
644              SuperClassWriter::addAttribute("edge_coordinates", edge_x + " " + edge_y, &domainName);
645              SuperClassWriter::addDimension(dimEdge, domain->ni_glo);
646              dim0.clear();
647              dim0.push_back(dimEdge);
[1456]648              SuperClassWriter::addVariable(edge_x, typePrec, dim0, compressionLevel);
[924]649              SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &edge_x);
650              SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh edges."), &edge_x);
651              SuperClassWriter::addAttribute("units", StdString("degrees_east"), &edge_x);
[1456]652              SuperClassWriter::addVariable(edge_y, typePrec, dim0, compressionLevel);
[924]653              SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &edge_y);
654              SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh edges."), &edge_y);
655              SuperClassWriter::addAttribute("units", StdString("degrees_north"), &edge_y);
656              dim0.clear();
657              dim0.push_back(dimEdge);
658              dim0.push_back(dimTwo);
[1456]659              SuperClassWriter::addVariable(edge_nodes, NC_INT, dim0, compressionLevel);
[924]660              SuperClassWriter::addAttribute("cf_role", StdString("edge_node_connectivity"), &edge_nodes);
661              SuperClassWriter::addAttribute("long_name", StdString("Maps every edge/link to two nodes that it connects."), &edge_nodes);
662              SuperClassWriter::addAttribute("start_index", 0, &edge_nodes);
[879]663            } // domain->nvertex == 2
[878]664
[879]665            // Adding faces, edges, and nodes, if edges and nodes have not been defined previously
666            if (domain->nvertex > 2)
667            {
668              // Nodes
669              if (!SuperClassWriter::varExist(node_x) || !SuperClassWriter::varExist(node_y))
670              {
[924]671                SuperClassWriter::addDimension(dimNode, domain->mesh->nbNodesGlo);
[879]672                dim0.clear();
673                dim0.push_back(dimNode);
[1456]674                SuperClassWriter::addVariable(node_x, typePrec, dim0, compressionLevel);
[879]675                SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x);
[924]676                SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x);
[879]677                SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x);
[1456]678                SuperClassWriter::addVariable(node_y, typePrec, dim0, compressionLevel);
[879]679                SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y);
[924]680                SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y);
[879]681                SuperClassWriter::addAttribute("units", StdString("degrees_north"), &node_y);
682              }
683              if (!SuperClassWriter::varExist(edge_x) || !SuperClassWriter::varExist(edge_y))
684              {
685                SuperClassWriter::addAttribute("edge_coordinates", edge_x + " " + edge_y, &domainName);
686                SuperClassWriter::addAttribute("edge_node_connectivity", edge_nodes, &domainName);
[924]687                SuperClassWriter::addDimension(dimEdge, domain->mesh->nbEdgesGlo);
[879]688                dim0.clear();
689                dim0.push_back(dimEdge);
[1456]690                SuperClassWriter::addVariable(edge_x, typePrec, dim0, compressionLevel);
[879]691                SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &edge_x);
[924]692                SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh edges."), &edge_x);
[879]693                SuperClassWriter::addAttribute("units", StdString("degrees_east"), &edge_x);
[1456]694                SuperClassWriter::addVariable(edge_y, typePrec, dim0, compressionLevel);
[879]695                SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &edge_y);
[924]696                SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh edges."), &edge_y);
[879]697                SuperClassWriter::addAttribute("units", StdString("degrees_north"), &edge_y);
698                dim0.clear();
699                dim0.push_back(dimEdge);
700                dim0.push_back(dimTwo);
[1456]701                SuperClassWriter::addVariable(edge_nodes, NC_INT, dim0, compressionLevel);
[879]702                SuperClassWriter::addAttribute("cf_role", StdString("edge_node_connectivity"), &edge_nodes);
703                SuperClassWriter::addAttribute("long_name", StdString("Maps every edge/link to two nodes that it connects."), &edge_nodes);
704                SuperClassWriter::addAttribute("start_index", 0, &edge_nodes);
705              }
[924]706              SuperClassWriter::addAttribute("face_coordinates", face_x + " " + face_y, &domainName);
707              SuperClassWriter::addAttribute("face_node_connectivity", face_nodes, &domainName);
708              SuperClassWriter::addDimension(dimFace, domain->ni_glo);
709              SuperClassWriter::addDimension(dimVertex, domain->nvertex);
710              dim0.clear();
711              dim0.push_back(dimFace);
[1456]712              SuperClassWriter::addVariable(face_x, typePrec, dim0, compressionLevel);
[924]713              SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &face_x);
714              SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh faces."), &face_x);
715              SuperClassWriter::addAttribute("units", StdString("degrees_east"), &face_x);
[1456]716              SuperClassWriter::addVariable(face_y, typePrec, dim0, compressionLevel);
[924]717              SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &face_y);
718              SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh faces."), &face_y);
719              SuperClassWriter::addAttribute("units", StdString("degrees_north"), &face_y);
720              dim0.clear();
721              dim0.push_back(dimFace);
722              dim0.push_back(dimVertex);
[1456]723              SuperClassWriter::addVariable(face_nodes, NC_INT, dim0, compressionLevel);
[924]724              SuperClassWriter::addAttribute("cf_role", StdString("face_node_connectivity"), &face_nodes);
725              SuperClassWriter::addAttribute("long_name", StdString("Maps every face to its corner nodes."), &face_nodes);
726              SuperClassWriter::addAttribute("start_index", 0, &face_nodes);
727              dim0.clear();
728              dim0.push_back(dimFace);
729              dim0.push_back(dimVertex);
[1456]730              SuperClassWriter::addVariable(face_edges, NC_INT, dim0, compressionLevel);
[924]731              SuperClassWriter::addAttribute("cf_role", StdString("face_edge_connectivity"), &face_edges);
732              SuperClassWriter::addAttribute("long_name", StdString("Maps every face to its edges."), &face_edges);
733              SuperClassWriter::addAttribute("start_index", 0, &face_edges);
[929]734              SuperClassWriter::addAttribute("_FillValue", 999999, &face_edges);
[924]735              dim0.clear();
736              dim0.push_back(dimEdge);
737              dim0.push_back(dimTwo);
[1456]738              SuperClassWriter::addVariable(edge_faces, NC_INT, dim0, compressionLevel);
[924]739              SuperClassWriter::addAttribute("cf_role", StdString("edge_face connectivity"), &edge_faces);
740              SuperClassWriter::addAttribute("long_name", StdString("neighbor faces for edges"), &edge_faces);
741              SuperClassWriter::addAttribute("start_index", 0, &edge_faces);
742              SuperClassWriter::addAttribute("_FillValue", -999, &edge_faces);
743              SuperClassWriter::addAttribute("comment", StdString("missing neighbor faces are indicated using _FillValue"), &edge_faces);
744              dim0.clear();
745              dim0.push_back(dimFace);
746              dim0.push_back(dimVertex);
[1456]747              SuperClassWriter::addVariable(face_faces, NC_INT, dim0, compressionLevel);
[924]748              SuperClassWriter::addAttribute("cf_role", StdString("face_face connectivity"), &face_faces);
749              SuperClassWriter::addAttribute("long_name", StdString("Indicates which other faces neighbor each face"), &face_faces);
750              SuperClassWriter::addAttribute("start_index", 0, &face_faces);
[929]751              SuperClassWriter::addAttribute("_FillValue", 999999, &face_faces);
[924]752              SuperClassWriter::addAttribute("flag_values", -1, &face_faces);
753              SuperClassWriter::addAttribute("flag_meanings", StdString("out_of_mesh"), &face_faces);
[879]754            } // domain->nvertex > 2
[878]755
[879]756            SuperClassWriter::definition_end();
[878]757
[924]758            std::vector<StdSize> startEdges(1) ;
759            std::vector<StdSize> countEdges(1) ;
760            std::vector<StdSize> startNodes(1) ;
761            std::vector<StdSize> countNodes(1) ;
762            std::vector<StdSize> startFaces(1) ;
763            std::vector<StdSize> countFaces(1) ;
764            std::vector<StdSize> startEdgeNodes(2) ;
765            std::vector<StdSize> countEdgeNodes(2) ;
766            std::vector<StdSize> startEdgeFaces(2) ;
767            std::vector<StdSize> countEdgeFaces(2) ;
768            std::vector<StdSize> startFaceConctv(2) ;
769            std::vector<StdSize> countFaceConctv(2) ;
[902]770
[1494]771            if (domain->nvertex == 1)
[879]772            {
[1494]773              if (domain->isEmpty())
774               {
775                 startNodes[0]=0 ;
776                 countNodes[0]=0 ;
777               }
778               else
779               {
[1553]780                 startNodes[0] = domain->ibegin;
781                 countNodes[0] = domain->ni ;
[1494]782               }
[924]783
[1494]784              SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0, &startNodes, &countNodes);
785              SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0, &startNodes, &countNodes);
786            }
787            else if (domain->nvertex == 2)
788            {
789              if (domain->isEmpty())
790               {
791                startEdges[0]=0 ;
792                countEdges[0]=0 ;
793                startNodes[0]=0 ;
794                countNodes[0]=0 ;
795                startEdgeNodes[0]=0;
796                startEdgeNodes[1]=0;
797                countEdgeNodes[0]=0;
798                countEdgeNodes[1]=0;
[924]799
[1494]800               }
801               else
802               {
[1553]803                 startEdges[0] = domain->ibegin;
804                 countEdges[0] = domain->ni;
[1494]805                 startNodes[0] = domain->mesh->node_start;
806                 countNodes[0] = domain->mesh->node_count;
[1553]807                 startEdgeNodes[0] = domain->ibegin;
[1494]808                 startEdgeNodes[1] = 0;
[1553]809                 countEdgeNodes[0] = domain->ni;
[1494]810                 countEdgeNodes[1] = 2;
811               }
812              SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0, &startNodes, &countNodes);
813              SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0, &startNodes, &countNodes);
814              SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0, &startEdges, &countEdges);
815              SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0, &startEdges, &countEdges);
816              SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes, isCollective, 0, &startEdgeNodes, &countEdgeNodes);
817            }
[879]818            else
819            {
[1494]820              if (domain->isEmpty())
821               {
822                 startFaces[0] = 0 ;
823                 countFaces[0] = 0 ;
824                 startNodes[0] = 0;
825                 countNodes[0] = 0;
826                 startEdges[0] = 0;
827                 countEdges[0] = 0;
828                 startEdgeFaces[0] = 0;
829                 startEdgeFaces[1] = 0;
830                 countEdgeFaces[0] = 0;
831                 countEdgeFaces[1] = 0;
832                 startFaceConctv[0] = 0;
833                 startFaceConctv[1] = 0;
834                 countFaceConctv[0] = 0;
835                 countFaceConctv[1] = 0;
836               }
837               else
838               {
[1553]839                 startFaces[0] = domain->ibegin;
840                 countFaces[0] = domain->ni ;
[1494]841                 startNodes[0] = domain->mesh->node_start;
842                 countNodes[0] = domain->mesh->node_count;
843                 startEdges[0] = domain->mesh->edge_start;
844                 countEdges[0] = domain->mesh->edge_count;
845                 startEdgeNodes[0] = domain->mesh->edge_start;
846                 startEdgeNodes[1] = 0;
847                 countEdgeNodes[0] = domain->mesh->edge_count;
848                 countEdgeNodes[1]= 2;
849                 startEdgeFaces[0] = domain->mesh->edge_start;
850                 startEdgeFaces[1]= 0;
851                 countEdgeFaces[0] = domain->mesh->edge_count;
852                 countEdgeFaces[1]= 2;
[1553]853                 startFaceConctv[0] = domain->ibegin;
[1494]854                 startFaceConctv[1] = 0;
[1553]855                 countFaceConctv[0] = domain->ni;
[1494]856                 countFaceConctv[1] = domain->nvertex;
857               }
858              SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0, &startNodes, &countNodes);
859              SuperClassWriter::writeData(domain->mesh->node_lon, node_x, isCollective, 0, &startNodes, &countNodes);
860              SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0, &startEdges, &countEdges);
861              SuperClassWriter::writeData(domain->mesh->edge_lon, edge_x, isCollective, 0, &startEdges, &countEdges);
862              SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes, isCollective, 0, &startEdgeNodes, &countEdgeNodes);
863              SuperClassWriter::writeData(domain->mesh->face_lat, face_y, isCollective, 0, &startFaces, &countFaces);
864              SuperClassWriter::writeData(domain->mesh->face_lon, face_x, isCollective, 0, &startFaces, &countFaces);
865              SuperClassWriter::writeData(domain->mesh->face_nodes, face_nodes, isCollective, 0, &startFaceConctv, &countFaceConctv);
866              SuperClassWriter::writeData(domain->mesh->face_edges, face_edges, isCollective, 0, &startFaceConctv, &countFaceConctv);
867              SuperClassWriter::writeData(domain->mesh->edge_faces, edge_faces, isCollective, 0, &startEdgeFaces, &countEdgeFaces);
868              SuperClassWriter::writeData(domain->mesh->face_faces, face_faces, isCollective, 0, &startFaceConctv, &countFaceConctv);
869            }
[879]870            SuperClassWriter::definition_start();
[878]871
[879]872            break;
873          } // ONE_FILE
[878]874
[879]875          case (MULTI_FILE) :
876          {
[1571]877            ERROR("CNc4DataOutput::writeDomain(domain)",
878            << "[ type = multiple_file ]"
879            << " is not yet implemented for UGRID files !");
[879]880            break;
881          }
[878]882
[879]883          default :
884          ERROR("CNc4DataOutput::writeDomain(domain)",
885          << "[ type = " << SuperClass::type << "]"
886          << " not implemented yet !");
887          } // switch
888        } // try
[878]889
[879]890        catch (CNetCdfException& e)
891        {
892          StdString msg("On writing the domain : ");
893          msg.append(domid); msg.append("\n");
894          msg.append("In the context : ");
895          msg.append(context->getId()); msg.append("\n");
896          msg.append(e.what());
[924]897          ERROR("CNc4DataOutput::writeUnstructuredDomainUgrid(CDomain* domain)", << msg);
[879]898        }
[878]899
[879]900  domain->addRelFile(this->filename);
901  }
[878]902
[879]903    //--------------------------------------------------------------
[878]904
[879]905    void CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)
[449]906      {
907         CContext* context = CContext::getCurrent() ;
908         CContextServer* server=context->server ;
[488]909
[449]910         if (domain->IsWritten(this->filename)) return;
911         domain->checkAttributes();
[488]912
913         if (domain->isEmpty())
[449]914           if (SuperClass::type==MULTI_FILE) return ;
915
916         std::vector<StdString> dim0, dim1;
[772]917         StdString domid = domain->getDomainOutputName();
[705]918         if (isWrittenDomain(domid)) return ;
[774]919         else setWrittenDomain(domid);
[705]920
[449]921         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
922
[1430]923         StdString lonName,latName, cellName ;
[1391]924         if (domain->lon_name.isEmpty()) lonName = "lon";
925         else lonName = domain->lon_name;
926
927         if (domain->lat_name.isEmpty()) latName = "lat";
928         else latName = domain->lat_name;
929
[1430]930         if (!domain->dim_i_name.isEmpty()) cellName=domain->dim_i_name;
931         else cellName="cell";
932         StdString dimXid = cellName+appendDomid;
[449]933         StdString dimVertId = StdString("nvertex").append(appendDomid);
[488]934
[449]935         string lonid,latid,bounds_lonid,bounds_latid ;
[611]936         string areaId = "area" + appendDomid;
[449]937
[1158]938         nc_type typePrec ;
939         if (domain->prec.isEmpty()) typePrec =  NC_FLOAT ;
940         else if (domain->prec==4)  typePrec =  NC_FLOAT ;
941         else if (domain->prec==8)   typePrec =  NC_DOUBLE ;
942
[1132]943         int nvertex = (domain->nvertex.isEmpty()) ? 0 : domain->nvertex;
[1025]944
[1571]945         CArray<int, 1>& indexToWrite = domain->localIndexToWriteOnServer;
[1132]946         int nbWritten = indexToWrite.numElements();
947         CArray<double,1> writtenLat, writtenLon;
948         CArray<double,2> writtenBndsLat, writtenBndsLon;
949         CArray<double,1> writtenArea;
950
951         if (domain->hasLonLat)
952         {
953           writtenLat.resize(nbWritten);
954           writtenLon.resize(nbWritten);
955           for (int idx = 0; idx < nbWritten; ++idx)
956           {
[1571]957             if (indexToWrite(idx) < 0)
958             {
959               writtenLat(idx) = -1.;
960               writtenLon(idx) = -1.;
961             }
962             else
963             {
964               writtenLat(idx) = domain->latvalue(indexToWrite(idx));
965               writtenLon(idx) = domain->lonvalue(indexToWrite(idx));
966             }
[1132]967           }
[1390]968         }
[1132]969         
[1390]970         if (domain->hasBounds)
971         {
972           int nvertex = domain->nvertex, idx;
973           writtenBndsLat.resize(nvertex, nbWritten);
974           writtenBndsLon.resize(nvertex, nbWritten);
975           CArray<double,2>& boundslat = domain->bounds_latvalue;
976           CArray<double,2>& boundslon = domain->bounds_lonvalue;
977           for (idx = 0; idx < nbWritten; ++idx)
978           {
979             for (int nv = 0; nv < nvertex; ++nv)
980             {
[1571]981               if (indexToWrite(idx) < 0)
[1132]982               {
[1571]983                 writtenBndsLat(nv, idx) = -1.;
984                 writtenBndsLon(nv, idx) = -1.;
[1132]985               }
[1390]986               else
987               {
[1571]988                 writtenBndsLat(nv, idx) = boundslat(nv, int(indexToWrite(idx)));
989                 writtenBndsLon(nv, idx) = boundslon(nv, int(indexToWrite(idx)));
[1390]990                }
991             }
[1132]992           }
993         }
994
995         if (domain->hasArea)
996         {
997           writtenArea.resize(nbWritten);           
998           for (int idx = 0; idx < nbWritten; ++idx)
999           {
[1589]1000             if (indexToWrite(idx) < 0)
1001               writtenArea(idx) = -1.;
1002             else
1003               writtenArea(idx) = domain->areavalue(indexToWrite(idx));
[1132]1004           }
1005         }
1006
[498]1007         try
[449]1008         {
[498]1009           switch (SuperClass::type)
1010           {
1011              case (MULTI_FILE) :
1012              {
1013                 dim0.push_back(dimXid);
[1553]1014                 SuperClassWriter::addDimension(dimXid, domain->ni);
[488]1015
[1415]1016                 lonid = lonName+appendDomid;
1017                 latid = latName+appendDomid;
[1430]1018                 if (!domain->bounds_lon_name.isEmpty()) bounds_lonid = domain->bounds_lon_name;
1019                 else bounds_lonid = "bounds_"+lonName+appendDomid;
1020                 if (!domain->bounds_lat_name.isEmpty()) bounds_latid = domain->bounds_lat_name;
1021                 else bounds_latid = "bounds_"+latName+appendDomid;
1022
[665]1023                 if (domain->hasLonLat)
1024                 {
[1456]1025                   SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel);
1026                   SuperClassWriter::addVariable(lonid, typePrec, dim0, compressionLevel);
[665]1027                   this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid);
1028                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
1029                   this->writeAxisAttributes(latid, "", "latitude", "Latitude", "degrees_north", domid);
1030                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
1031                   if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
1032                 }
[498]1033                 dim0.clear();
1034                 if (domain->hasBounds)
1035                 {
1036                   dim0.push_back(dimXid);
1037                   dim0.push_back(dimVertId);
[1456]1038                   SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0, compressionLevel);
1039                   SuperClassWriter::addVariable(bounds_latid, typePrec, dim0, compressionLevel);
[498]1040                 }
1041
1042                 dim0.clear();
[449]1043                 dim0.push_back(dimXid);
[611]1044                 if (domain->hasArea)
1045                 {
[1456]1046                   SuperClassWriter::addVariable(areaId, typePrec, dim0, compressionLevel);
[614]1047                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
[611]1048                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
1049                 }
1050
[498]1051                 SuperClassWriter::definition_end();
[449]1052
[665]1053                 if (domain->hasLonLat)
[498]1054                 {
[1132]1055                   SuperClassWriter::writeData(writtenLat, latid, isCollective, 0);
1056                   SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0);
[665]1057                   if (domain->hasBounds)
1058                   {
[1132]1059                     SuperClassWriter::writeData(writtenBndsLon, bounds_lonid, isCollective, 0);
1060                     SuperClassWriter::writeData(writtenBndsLat, bounds_latid, isCollective, 0);
[665]1061                   }
[498]1062                 }
[611]1063
1064                 if (domain->hasArea)
[1132]1065                   SuperClassWriter::writeData(writtenArea, areaId, isCollective, 0);
[611]1066
[498]1067                 SuperClassWriter::definition_start();
1068                 break ;
1069              }
[488]1070
[498]1071              case (ONE_FILE) :
1072              {
[1415]1073                 lonid = lonName+appendDomid;
1074                 latid = latName+appendDomid;
[1430]1075                 if (!domain->bounds_lon_name.isEmpty()) bounds_lonid = domain->bounds_lon_name;
1076                 else bounds_lonid = "bounds_"+lonName+appendDomid;
1077                 if (!domain->bounds_lat_name.isEmpty()) bounds_latid = domain->bounds_lat_name;
1078                 else bounds_latid = "bounds_"+latName+appendDomid;
[1391]1079
[498]1080                 dim0.push_back(dimXid);
[1132]1081                 SuperClassWriter::addDimension(dimXid, domain->ni_glo);
[665]1082                 if (domain->hasLonLat)
1083                 {
[1456]1084                   SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel);
1085                   SuperClassWriter::addVariable(lonid, typePrec, dim0, compressionLevel);
[665]1086
1087                   this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid);
1088                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
1089                   this->writeAxisAttributes(latid, "", "latitude", "Latitude", "degrees_north", domid);
1090                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
[1025]1091                   if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, nvertex);
[665]1092                 }
[498]1093                 dim0.clear();
[449]1094
[498]1095                 if (domain->hasBounds)
1096                 {
1097                   dim0.push_back(dimXid);
1098                   dim0.push_back(dimVertId);
[1456]1099                   SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0, compressionLevel);
1100                   SuperClassWriter::addVariable(bounds_latid, typePrec, dim0, compressionLevel);
[498]1101                 }
[488]1102
[611]1103                 if (domain->hasArea)
1104                 {
1105                   dim0.clear();
1106                   dim0.push_back(dimXid);
[1456]1107                   SuperClassWriter::addVariable(areaId, typePrec, dim0, compressionLevel);
[614]1108                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
[611]1109                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
1110                 }
1111
[498]1112                 SuperClassWriter::definition_end();
[488]1113
[498]1114                 std::vector<StdSize> start(1), startBounds(2) ;
1115                 std::vector<StdSize> count(1), countBounds(2) ;
1116                 if (domain->isEmpty())
1117                 {
1118                   start[0]=0 ;
1119                   count[0]=0 ;
1120                   startBounds[1]=0 ;
[1025]1121                   countBounds[1]=nvertex ;
[498]1122                   startBounds[0]=0 ;
1123                   countBounds[0]=0 ;
1124                 }
1125                 else
1126                 {
[1553]1127                   start[0]=domain->ibegin;
1128                   count[0]=domain->ni;
1129                   startBounds[0]=domain->ibegin;
[498]1130                   startBounds[1]=0 ;
[1553]1131                   countBounds[0]=domain->ni;
[1025]1132                   countBounds[1]=nvertex ;
[498]1133                 }
[665]1134
1135                 if (domain->hasLonLat)
[498]1136                 {
[1132]1137                   SuperClassWriter::writeData(writtenLat, latid, isCollective, 0,&start,&count);
1138                   SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0,&start,&count);
[665]1139                   if (domain->hasBounds)
1140                   {
[1132]1141                     SuperClassWriter::writeData(writtenBndsLon, bounds_lonid, isCollective, 0,&startBounds,&countBounds);
1142                     SuperClassWriter::writeData(writtenBndsLat, bounds_latid, isCollective, 0,&startBounds,&countBounds);
[665]1143                   }
[498]1144                 }
[488]1145
[611]1146                 if (domain->hasArea)
[1132]1147                   SuperClassWriter::writeData(writtenArea, areaId, isCollective, 0, &start, &count);
[488]1148
[498]1149                 SuperClassWriter::definition_start();
[488]1150
[498]1151                 break;
1152              }
1153              default :
1154                 ERROR("CNc4DataOutput::writeDomain(domain)",
1155                       << "[ type = " << SuperClass::type << "]"
1156                       << " not implemented yet !");
1157           }
[219]1158         }
[498]1159         catch (CNetCdfException& e)
1160         {
1161           StdString msg("On writing the domain : ");
1162           msg.append(domid); msg.append("\n");
1163           msg.append("In the context : ");
1164           msg.append(context->getId()); msg.append("\n");
1165           msg.append(e.what());
1166           ERROR("CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)", << msg);
1167         }
[219]1168         domain->addRelFile(this->filename);
1169      }
1170      //--------------------------------------------------------------
1171
[347]1172      void CNc4DataOutput::writeAxis_(CAxis* axis)
[219]1173      {
[1030]1174        if (axis->IsWritten(this->filename)) return;
1175        axis->checkAttributes();
[488]1176
[1129]1177        axis->computeWrittenIndex();
[1249]1178        axis->computeWrittenCompressedIndex(comm_file);
[1129]1179       
[1559]1180        int size  = (MULTI_FILE == SuperClass::type) ? axis->n.getValue()
1181                                                          : axis->n_glo.getValue();
[1099]1182
[1559]1183        if ((0 == axis->n) && (MULTI_FILE == SuperClass::type)) return;
[1235]1184
[1030]1185        std::vector<StdString> dims;
1186        StdString axisid = axis->getAxisOutputName();
[1435]1187        StdString axisDim, axisBoundsId;
[1030]1188        if (isWrittenAxis(axisid)) return ;
1189        else setWrittenAxis(axisid);
[705]1190
[1158]1191        nc_type typePrec ;
1192        if (axis->prec.isEmpty()) typePrec =  NC_FLOAT ;
[1235]1193        else if (axis->prec==4)   typePrec =  NC_FLOAT ;
[1158]1194        else if (axis->prec==8)   typePrec =  NC_DOUBLE ;
1195         
1196        if (!axis->label.isEmpty()) typePrec = NC_CHAR ;
1197        string strId="str_len" ;
[1030]1198        try
1199        {
[1433]1200          if (axis->dim_name.isEmpty()) axisDim = axisid;
1201          else axisDim=axis->dim_name.getValue();
[1559]1202          SuperClassWriter::addDimension(axisDim, size);
[1433]1203          dims.push_back(axisDim);
1204
[1439]1205          if (!axis->label.isEmpty() && !SuperClassWriter::dimExist(strId)) SuperClassWriter::addDimension(strId, stringArrayLen);
[1433]1206
[1435]1207          if (axis->hasValue || !axis->label.isEmpty())
[816]1208          {
[1158]1209            if (!axis->label.isEmpty()) dims.push_back(strId);
[1430]1210
[1456]1211            SuperClassWriter::addVariable(axisid, typePrec, dims, compressionLevel);
[219]1212
[1030]1213            if (!axis->name.isEmpty())
1214              SuperClassWriter::addAttribute("name", axis->name.getValue(), &axisid);
[219]1215
[1030]1216            if (!axis->standard_name.isEmpty())
1217              SuperClassWriter::addAttribute("standard_name", axis->standard_name.getValue(), &axisid);
[540]1218
[1030]1219            if (!axis->long_name.isEmpty())
1220              SuperClassWriter::addAttribute("long_name", axis->long_name.getValue(), &axisid);
[219]1221
[1030]1222            if (!axis->unit.isEmpty())
1223              SuperClassWriter::addAttribute("units", axis->unit.getValue(), &axisid);
[219]1224
[1430]1225            if (!axis->axis_type.isEmpty())
1226            {
1227              switch(axis->axis_type)
1228              {
1229              case CAxis::axis_type_attr::X :
1230                SuperClassWriter::addAttribute("axis", string("X"), &axisid);
1231                break;
1232              case CAxis::axis_type_attr::Y :
1233                SuperClassWriter::addAttribute("axis", string("Y"), &axisid);
1234                break;
1235              case CAxis::axis_type_attr::Z :
1236                SuperClassWriter::addAttribute("axis", string("Z"), &axisid);
1237                break;
1238              case CAxis::axis_type_attr::T :
1239                SuperClassWriter::addAttribute("axis", string("T"), &axisid);
1240                break;
1241              }
1242            }
1243
[1030]1244            if (!axis->positive.isEmpty())
1245            {
1246              SuperClassWriter::addAttribute("positive",
1247                                             (axis->positive == CAxis::positive_attr::up) ? string("up") : string("down"),
1248                                             &axisid);
1249            }
[399]1250
[1266]1251            if (!axis->formula.isEmpty())
1252              SuperClassWriter::addAttribute("formula", axis->formula.getValue(), &axisid);
1253
1254            if (!axis->formula_term.isEmpty())
1255              SuperClassWriter::addAttribute("formula_term", axis->formula_term.getValue(), &axisid);
1256             
[1435]1257            axisBoundsId = (axis->bounds_name.isEmpty()) ? axisid + "_bounds" : axis->bounds_name;
[1249]1258            if (!axis->bounds.isEmpty() && axis->label.isEmpty())
[1030]1259            {
1260              dims.push_back("axis_nbounds");
[1456]1261              SuperClassWriter::addVariable(axisBoundsId, typePrec, dims, compressionLevel);
[1030]1262              SuperClassWriter::addAttribute("bounds", axisBoundsId, &axisid);
[1288]1263
1264              if (!axis->standard_name.isEmpty())
1265                SuperClassWriter::addAttribute("standard_name", axis->standard_name.getValue(), &axisBoundsId);
1266
1267              if (!axis->unit.isEmpty())
1268                SuperClassWriter::addAttribute("units", axis->unit.getValue(), &axisBoundsId);
1269
[1266]1270              if (!axis->formula_bounds.isEmpty())
[1288]1271                SuperClassWriter::addAttribute("formula", axis->formula_bounds.getValue(), &axisBoundsId);
[1266]1272
1273              if (!axis->formula_term_bounds.isEmpty())
[1288]1274                SuperClassWriter::addAttribute("formula_term", axis->formula_term_bounds.getValue(), &axisBoundsId);
[1030]1275            }
[1435]1276          }
[816]1277
[1435]1278          SuperClassWriter::definition_end();
1279
[1571]1280          CArray<int, 1>& indexToWrite = axis->localIndexToWriteOnServer;
[1435]1281          int nbWritten = indexToWrite.numElements();
1282          CArray<double,1> axis_value(indexToWrite.numElements());
1283          if (!axis->value.isEmpty())
1284          {
[1421]1285            for (int i = 0; i < nbWritten; i++)
1286            {
[1571]1287              if (indexToWrite(i) < 0)
1288                axis_value(i) = -1;   // Some value in case of a hole
1289              else
[1421]1290                axis_value(i) = axis->value(indexToWrite(i));
1291            }
[1435]1292          }
1293          CArray<double,2> axis_bounds;
1294          CArray<string,1> axis_label;
1295          if (!axis->label.isEmpty())
1296          {
1297            axis_label.resize(indexToWrite.numElements());
1298            for (int i = 0; i < nbWritten; i++)
[1235]1299            {
[1571]1300              if (indexToWrite(i) < 0)
1301                axis_label(i) = boost::lexical_cast<string>(-1);  // Some value in case of a hole
1302              else
[1435]1303                axis_label(i) = axis->label(indexToWrite(i));
[1235]1304            }
[1435]1305          }
[1129]1306
[1435]1307          switch (SuperClass::type)
1308          {
1309            case MULTI_FILE:
[1030]1310            {
[1435]1311              if (axis->label.isEmpty())
[1437]1312              {
1313                if (!axis->value.isEmpty())
1314                  SuperClassWriter::writeData(axis_value, axisid, isCollective, 0);
[633]1315
[1437]1316                if (!axis->bounds.isEmpty())
1317                {
[1129]1318                  axis_bounds.resize(2, indexToWrite.numElements());
1319                  for (int i = 0; i < nbWritten; ++i)
1320                  {
[1571]1321                    if (indexToWrite(i) < 0)
[1421]1322                    {
[1571]1323                      axis_bounds(0, i) = -1.; // Some value in case of a hole
1324                      axis_bounds(1, i) = -1.;
[1421]1325                    }
1326                    else
1327                    {
[1571]1328                      axis_bounds(0, i) = axis->bounds(0, int(indexToWrite(i)));
1329                      axis_bounds(1, i) = axis->bounds(1, int(indexToWrite(i)));
[1421]1330                    }
[1129]1331                  }
[1437]1332                  SuperClassWriter::writeData(axis_bounds, axisBoundsId, isCollective, 0);
1333                }
[1435]1334              }
[1437]1335              else
[1435]1336                SuperClassWriter::writeData(axis_label, axisid, isCollective, 0);
1337
1338              SuperClassWriter::definition_start();
1339              break;
1340            }
1341            case ONE_FILE:
1342            {
1343              std::vector<StdSize> start(1), startBounds(2) ;
1344              std::vector<StdSize> count(1), countBounds(2) ;
[1559]1345              start[0] = startBounds[0] = axis->begin;
1346              count[0] = countBounds[0] = axis->n;
[1435]1347              startBounds[1] = 0;
1348              countBounds[1] = 2;
1349
1350              if (axis->label.isEmpty())
[1437]1351              {
1352                if (!axis->value.isEmpty())
1353                  SuperClassWriter::writeData(axis_value, axisid, isCollective, 0, &start, &count);
[1435]1354
[1437]1355                if (!axis->bounds.isEmpty())
[1235]1356                {
[1437]1357                  axis_bounds.resize(2, indexToWrite.numElements());
1358                  for (int i = 0; i < nbWritten; ++i)
[1435]1359                  {
[1571]1360                    if (indexToWrite(i) < 0)
[1437]1361                    {
[1571]1362                      axis_bounds(0, i) = -1.;
1363                      axis_bounds(1, i) = -1.;
[1437]1364                    }
1365                    else
1366                    {
[1571]1367                      axis_bounds(0, i) = axis->bounds(0, int(indexToWrite(i)));
1368                      axis_bounds(1, i) = axis->bounds(1, int(indexToWrite(i)));
[1437]1369                    }
[1435]1370                  }
[1437]1371                  SuperClassWriter::writeData(axis_bounds, axisBoundsId, isCollective, 0, &startBounds, &countBounds);
[1235]1372                }
[1435]1373              }
[1437]1374              else
[1435]1375              {
1376                std::vector<StdSize> startLabel(2), countLabel(2);
1377                startLabel[0] = start[0]; startLabel[1] = 0;
1378                countLabel[0] = count[0]; countLabel[1] = stringArrayLen;
1379                SuperClassWriter::writeData(axis_label, axisid, isCollective, 0, &startLabel, &countLabel);
1380              }
[609]1381
[1435]1382              SuperClassWriter::definition_start();
1383
1384              break;
[609]1385            }
[1435]1386            default :
1387              ERROR("CNc4DataOutput::writeAxis_(CAxis* axis)",
1388                    << "[ type = " << SuperClass::type << "]"
1389                    << " not implemented yet !");
[609]1390          }
[1030]1391        }
1392        catch (CNetCdfException& e)
1393        {
1394          StdString msg("On writing the axis : ");
1395          msg.append(axisid); msg.append("\n");
1396          msg.append("In the context : ");
1397          CContext* context = CContext::getCurrent() ;
1398          msg.append(context->getId()); msg.append("\n");
1399          msg.append(e.what());
1400          ERROR("CNc4DataOutput::writeAxis_(CAxis* axis)", << msg);
1401        }
[1158]1402        axis->addRelFile(this->filename);
[391]1403     }
[488]1404
[887]1405      void CNc4DataOutput::writeScalar_(CScalar* scalar)
1406      {
1407        if (scalar->IsWritten(this->filename)) return;
1408        scalar->checkAttributes();
1409        int scalarSize = 1;
1410
1411        StdString scalaId = scalar->getScalarOutputName();
[1430]1412        StdString boundsId;
[887]1413        if (isWrittenAxis(scalaId)) return ;
1414        else setWrittenAxis(scalaId);
1415
[1158]1416        nc_type typePrec ;
1417        if (scalar->prec.isEmpty()) typePrec =  NC_FLOAT ;
1418        else if (scalar->prec==4)  typePrec =  NC_FLOAT ;
1419        else if (scalar->prec==8)   typePrec =  NC_DOUBLE ;
1420
[1435]1421        if (!scalar->label.isEmpty()) typePrec = NC_CHAR ;
1422        string strId="str_len" ;
1423
[887]1424        try
1425        {
[1439]1426          if (!scalar->label.isEmpty() && !SuperClassWriter::dimExist(strId)) SuperClassWriter::addDimension(strId, stringArrayLen);
[1435]1427
1428          if (!scalar->value.isEmpty() || !scalar->label.isEmpty())
[887]1429          {
[1430]1430            std::vector<StdString> dims;
1431            StdString scalarDim = scalaId;
1432
[1435]1433            if (!scalar->label.isEmpty()) dims.push_back(strId);
1434
[1158]1435            SuperClassWriter::addVariable(scalaId, typePrec, dims);
[887]1436
1437            if (!scalar->name.isEmpty())
1438              SuperClassWriter::addAttribute("name", scalar->name.getValue(), &scalaId);
1439
1440            if (!scalar->standard_name.isEmpty())
1441              SuperClassWriter::addAttribute("standard_name", scalar->standard_name.getValue(), &scalaId);
1442
1443            if (!scalar->long_name.isEmpty())
1444              SuperClassWriter::addAttribute("long_name", scalar->long_name.getValue(), &scalaId);
1445
1446            if (!scalar->unit.isEmpty())
1447              SuperClassWriter::addAttribute("units", scalar->unit.getValue(), &scalaId);
1448
[1430]1449            if (!scalar->axis_type.isEmpty())
1450            {
1451              switch(scalar->axis_type)
1452              {
1453              case CScalar::axis_type_attr::X :
1454                SuperClassWriter::addAttribute("axis", string("X"), &scalaId);
1455                break;
1456              case CScalar::axis_type_attr::Y :
1457                SuperClassWriter::addAttribute("axis", string("Y"), &scalaId);
1458                break;
1459              case CScalar::axis_type_attr::Z :
1460                SuperClassWriter::addAttribute("axis", string("Z"), &scalaId);
1461                break;
1462              case CScalar::axis_type_attr::T :
1463                SuperClassWriter::addAttribute("axis", string("T"), &scalaId);
1464                break;
1465              }
1466            }
1467
[1435]1468            if (!scalar->positive.isEmpty())
[1430]1469            {
[1435]1470              SuperClassWriter::addAttribute("positive",
1471                                             (scalar->positive == CScalar::positive_attr::up) ? string("up") : string("down"),
1472                                             &scalaId);
1473            }
1474
1475            if (!scalar->bounds.isEmpty() && scalar->label.isEmpty())
1476            {
[1436]1477              dims.clear();
1478              dims.push_back("axis_nbounds");
[1435]1479              boundsId = (scalar->bounds_name.isEmpty()) ? (scalaId + "_bounds") : scalar->bounds_name.getValue();
[1430]1480              SuperClassWriter::addVariable(boundsId, typePrec, dims);
[1436]1481              SuperClassWriter::addAttribute("bounds", boundsId, &scalaId);
[1430]1482            }
1483
[887]1484            SuperClassWriter::definition_end();
1485
1486            switch (SuperClass::type)
1487            {
1488              case MULTI_FILE:
1489              {
1490                CArray<double,1> scalarValue(scalarSize);
[1435]1491                CArray<string,1> scalarLabel(scalarSize);
[1436]1492                CArray<double,1> scalarBounds(scalarSize*2);
[1435]1493
1494                if (!scalar->value.isEmpty() && scalar->label.isEmpty())
[1430]1495                {
[1435]1496                  scalarValue(0) = scalar->value;
1497                  SuperClassWriter::writeData(scalarValue, scalaId, isCollective, 0);
1498                }
1499
1500                if (!scalar->bounds.isEmpty() && scalar->label.isEmpty())
1501                {
[1436]1502                  scalarBounds(0) = scalar->bounds(0);
1503                  scalarBounds(1) = scalar->bounds(1);
1504                  SuperClassWriter::writeData(scalarBounds, boundsId, isCollective, 0);
[1430]1505                }
[1435]1506
1507                if (!scalar->label.isEmpty())
1508                {
1509                  scalarLabel(0) = scalar->label;
1510                  SuperClassWriter::writeData(scalarLabel, scalaId, isCollective, 0);
1511                }
1512
[887]1513                SuperClassWriter::definition_start();
1514
1515                break;
1516              }
1517              case ONE_FILE:
1518              {
1519                CArray<double,1> scalarValue(scalarSize);
[1435]1520                CArray<string,1> scalarLabel(scalarSize);
[1436]1521                CArray<double,1> scalarBounds(scalarSize*2);
[887]1522
1523                std::vector<StdSize> start(1);
1524                std::vector<StdSize> count(1);
1525                start[0] = 0;
1526                count[0] = 1;
[1435]1527                if (!scalar->value.isEmpty() && scalar->label.isEmpty())
[1430]1528                {
[1435]1529                  scalarValue(0) = scalar->value;
1530                  SuperClassWriter::writeData(scalarValue, scalaId, isCollective, 0, &start, &count);
1531                }
1532                if (!scalar->bounds.isEmpty() && scalar->label.isEmpty())
1533                {
[1436]1534                  scalarBounds(0) = scalar->bounds(0);
1535                  scalarBounds(1) = scalar->bounds(1);
1536                  count[0] = 2;
1537                  SuperClassWriter::writeData(scalarBounds, boundsId, isCollective, 0, &start, &count);
[1430]1538                }
[1435]1539                if (!scalar->label.isEmpty())
1540                {
1541                  scalarLabel(0) = scalar->label;
1542                  count[0] = stringArrayLen;
1543                  SuperClassWriter::writeData(scalarLabel, scalaId, isCollective, 0, &start, &count);
1544                }
1545
[887]1546                SuperClassWriter::definition_start();
1547
1548                break;
1549              }
1550              default :
1551                ERROR("CNc4DataOutput::writeAxis_(CAxis* scalar)",
1552                      << "[ type = " << SuperClass::type << "]"
1553                      << " not implemented yet !");
1554            }
1555          }
1556        }
1557        catch (CNetCdfException& e)
1558        {
1559          StdString msg("On writing the scalar : ");
1560          msg.append(scalaId); msg.append("\n");
1561          msg.append("In the context : ");
1562          CContext* context = CContext::getCurrent() ;
1563          msg.append(context->getId()); msg.append("\n");
1564          msg.append(e.what());
1565          ERROR("CNc4DataOutput::writeScalar_(CScalar* scalar)", << msg);
1566        }
1567        scalar->addRelFile(this->filename);
1568     }
1569
[676]1570     //--------------------------------------------------------------
1571
1572     void CNc4DataOutput::writeGridCompressed_(CGrid* grid)
1573     {
1574       if (grid->isScalarGrid() || grid->isWrittenCompressed(this->filename)) return;
1575
1576       try
1577       {
[887]1578         CArray<int,1> axisDomainOrder = grid->axis_domain_order;
[676]1579         std::vector<StdString> domainList = grid->getDomainList();
1580         std::vector<StdString> axisList   = grid->getAxisList();
[887]1581         std::vector<StdString> scalarList = grid->getScalarList();
1582         int numElement = axisDomainOrder.numElements(), idxDomain = 0, idxAxis = 0, idxScalar = 0;
[676]1583
1584         std::vector<StdString> dims;
1585
1586         if (grid->isCompressible())
1587         {
1588           StdString varId = grid->getId() + "_points";
1589
1590           int nbIndexes = (SuperClass::type == MULTI_FILE) ? grid->getNumberWrittenIndexes() : grid->getTotalNumberWrittenIndexes();
1591           SuperClassWriter::addDimension(varId, nbIndexes);
1592
1593           dims.push_back(varId);
1594           SuperClassWriter::addVariable(varId, NC_INT, dims);
1595
1596           StdOStringStream compress;
1597           for (int i = numElement - 1; i >= 0; --i)
1598           {
[887]1599             if (2 == axisDomainOrder(i))
[676]1600             {
1601               CDomain* domain = CDomain::get(domainList[domainList.size() - idxDomain - 1]);
[772]1602               StdString domId = domain->getDomainOutputName();
[676]1603               StdString appendDomId  = singleDomain ? "" : "_" + domId;
1604
1605               switch (domain->type)
1606               {
1607                 case CDomain::type_attr::curvilinear:
1608                   compress << "y" << appendDomId << " x" << appendDomId;
1609                   break;
1610                 case CDomain::type_attr::rectilinear:
1611                   compress << "lat" << appendDomId << " lon" << appendDomId;
1612                   break;
1613                 case CDomain::type_attr::unstructured:
[1430]1614                   StdString cellName = (!domain->dim_i_name.isEmpty()) ? cellName=domain->dim_i_name : "cell";
1615                   compress << cellName << appendDomId;
1616//                   compress << "cell" << appendDomId;
[676]1617                   break;
1618               }
1619               ++idxDomain;
1620             }
[887]1621             else if (1 == axisDomainOrder(i))
[676]1622             {
1623               CAxis* axis = CAxis::get(axisList[axisList.size() - idxAxis - 1]);
[772]1624               compress << axis->getAxisOutputName();
[676]1625               ++idxAxis;
1626             }
[887]1627             else
1628             {
1629               CScalar* scalar = CScalar::get(scalarList[scalarList.size() - idxScalar - 1]);
1630               compress << scalar->getScalarOutputName();
1631               ++idxScalar;
1632             }
[676]1633
1634             if (i != 0) compress << ' ';
1635           }
[1144]1636           SuperClassWriter::addAttribute("compress", compress.str(), &varId);         
[676]1637
1638           CArray<int, 1> indexes(grid->getNumberWrittenIndexes());
[1143]1639           indexes = grid->localIndexToWriteOnServer;
[676]1640
1641           switch (SuperClass::type)
1642           {
1643             case (MULTI_FILE):
1644             {
1645               SuperClassWriter::writeData(indexes, varId, isCollective, 0);
1646               break;
1647             }
1648             case (ONE_FILE):
1649             {
1650               if (grid->doGridHaveDataDistributed())
1651                 grid->getDistributionServer()->computeGlobalIndex(indexes);
1652
1653               std::vector<StdSize> start, count;
1654               start.push_back(grid->getOffsetWrittenIndexes());
1655               count.push_back(grid->getNumberWrittenIndexes());
1656
1657               SuperClassWriter::writeData(indexes, varId, isCollective, 0, &start, &count);
1658               break;
1659             }
1660           }
1661         }
1662         else
1663         {
1664           for (int i = 0; i < numElement; ++i)
1665           {
1666             StdString varId, compress;
1667             CArray<int, 1> indexes;
1668             bool isDistributed;
1669             StdSize nbIndexes, totalNbIndexes, offset;
1670             int firstGlobalIndex;
1671
[887]1672             if (2 == axisDomainOrder(i))
[676]1673             {
1674               CDomain* domain = CDomain::get(domainList[idxDomain]);
[774]1675               StdString domId = domain->getDomainOutputName();
1676
[676]1677               if (!domain->isCompressible()
1678                    || domain->type == CDomain::type_attr::unstructured
[774]1679                    || domain->isWrittenCompressed(this->filename)
1680                    || isWrittenCompressedDomain(domId))
[676]1681                 continue;
1682
1683               StdString appendDomId  = singleDomain ? "" : "_" + domId;
1684
1685               varId = domId + "_points";
1686               switch (domain->type)
1687               {
1688                 case CDomain::type_attr::curvilinear:
1689                   compress = "y" + appendDomId + " x" + appendDomId;
1690                   break;
1691                 case CDomain::type_attr::rectilinear:
1692                   compress = "lat" + appendDomId + " lon" + appendDomId;
1693                   break;
1694               }
1695
[1249]1696               // indexes.resize(domain->compressedIndexToWriteOnServer[comm_file].numElements());
1697               // indexes = domain->compressedIndexToWriteOnServer[com_file];
1698               indexes.resize(domain->getCompressedIndexToWriteOnServer(comm_file).numElements());
1699               indexes = domain->getCompressedIndexToWriteOnServer(comm_file);
[1143]1700
[676]1701               isDistributed = domain->isDistributed();
[1249]1702               nbIndexes = domain->getNumberWrittenIndexes(comm_file);
1703               totalNbIndexes = domain->getTotalNumberWrittenIndexes(comm_file);
1704               offset = domain->getOffsetWrittenIndexes(comm_file);
[676]1705               firstGlobalIndex = domain->ibegin + domain->jbegin * domain->ni_glo;
1706
1707               domain->addRelFileCompressed(this->filename);
[774]1708               setWrittenCompressedDomain(domId);
[676]1709               ++idxDomain;
1710             }
[887]1711             else if (1 == axisDomainOrder(i))
[676]1712             {
1713               CAxis* axis = CAxis::get(axisList[idxAxis]);
[774]1714               StdString axisId = axis->getAxisOutputName();
1715
1716               if (!axis->isCompressible()
1717                    || axis->isWrittenCompressed(this->filename)
1718                    || isWrittenCompressedAxis(axisId))
[676]1719                 continue;
1720
1721               varId = axisId + "_points";
1722               compress = axisId;
1723
[1249]1724               // indexes.resize(axis->compressedIndexToWriteOnServer.numElements());
1725               // indexes = axis->compressedIndexToWriteOnServer;
[1143]1726
[1249]1727               indexes.resize(axis->getCompressedIndexToWriteOnServer(comm_file).numElements());
1728               indexes = axis->getCompressedIndexToWriteOnServer(comm_file);
1729
[676]1730               isDistributed = axis->isDistributed();
[1249]1731               nbIndexes = axis->getNumberWrittenIndexes(comm_file);
1732               totalNbIndexes = axis->getTotalNumberWrittenIndexes(comm_file);
1733               offset = axis->getOffsetWrittenIndexes(comm_file);
[676]1734               firstGlobalIndex = axis->begin;
1735
1736               axis->addRelFileCompressed(this->filename);
[774]1737               setWrittenCompressedAxis(axisId);
[676]1738               ++idxAxis;
1739             }
[887]1740             else
1741             {
1742             }
[676]1743
1744             if (!varId.empty())
1745             {
1746               SuperClassWriter::addDimension(varId, (SuperClass::type == MULTI_FILE) ? nbIndexes : totalNbIndexes);
1747
1748               dims.clear();
1749               dims.push_back(varId);
1750               SuperClassWriter::addVariable(varId, NC_INT, dims);
1751
1752               SuperClassWriter::addAttribute("compress", compress, &varId);
1753
1754               switch (SuperClass::type)
1755               {
1756                 case (MULTI_FILE):
1757                 {
1758                   indexes -= firstGlobalIndex;
1759                   SuperClassWriter::writeData(indexes, varId, isCollective, 0);
1760                   break;
1761                 }
1762                 case (ONE_FILE):
1763                 {
1764                   std::vector<StdSize> start, count;
1765                   start.push_back(offset);
1766                   count.push_back(nbIndexes);
1767
1768                   SuperClassWriter::writeData(indexes, varId, isCollective, 0, &start, &count);
1769                   break;
1770                 }
1771               }
1772             }
[1144]1773            }
[676]1774         }
1775
1776         grid->addRelFileCompressed(this->filename);
1777       }
1778       catch (CNetCdfException& e)
1779       {
1780         StdString msg("On writing compressed grid : ");
1781         msg.append(grid->getId()); msg.append("\n");
1782         msg.append("In the context : ");
1783         CContext* context = CContext::getCurrent();
1784         msg.append(context->getId()); msg.append("\n");
1785         msg.append(e.what());
1786         ERROR("CNc4DataOutput::writeGridCompressed_(CGrid* grid)", << msg);
1787       }
1788     }
1789
1790     //--------------------------------------------------------------
1791
[391]1792     void CNc4DataOutput::writeTimeDimension_(void)
1793     {
[498]1794       try
1795       {
[802]1796        SuperClassWriter::addDimension(getTimeCounterName());
[498]1797       }
1798       catch (CNetCdfException& e)
1799       {
[614]1800         StdString msg("On writing time dimension : time_couter\n");
[498]1801         msg.append("In the context : ");
1802         CContext* context = CContext::getCurrent() ;
1803         msg.append(context->getId()); msg.append("\n");
1804         msg.append(e.what());
1805         ERROR("CNc4DataOutput::writeTimeDimension_(void)", << msg);
1806       }
[391]1807     }
[676]1808
[219]1809      //--------------------------------------------------------------
1810
[347]1811      void CNc4DataOutput::writeField_(CField* field)
[219]1812      {
[1158]1813        CContext* context = CContext::getCurrent() ;
1814        CContextServer* server=context->server ;
[300]1815
[1158]1816        std::vector<StdString> dims, coodinates;
1817        CGrid* grid = field->grid;
1818        if (!grid->doGridHaveDataToWrite())
[567]1819          if (SuperClass::type==MULTI_FILE) return ;
[488]1820
[1158]1821        CArray<int,1> axisDomainOrder = grid->axis_domain_order;
1822        int numElement = axisDomainOrder.numElements(), idxDomain = 0, idxAxis = 0, idxScalar = 0;
1823        std::vector<StdString> domainList = grid->getDomainList();
1824        std::vector<StdString> axisList   = grid->getAxisList();
1825        std::vector<StdString> scalarList = grid->getScalarList();       
[219]1826
[1158]1827        StdString timeid  = getTimeCounterName();
1828        StdString dimXid,dimYid;
1829        std::deque<StdString> dimIdList, dimCoordList;
1830        bool hasArea = false;
1831        StdString cellMeasures = "area:";
1832        bool compressedOutput = !field->indexed_output.isEmpty() && field->indexed_output;
[488]1833
[1158]1834        for (int i = 0; i < numElement; ++i)
1835        {
1836          if (2 == axisDomainOrder(i))
1837          {
1838            CDomain* domain = CDomain::get(domainList[idxDomain]);
1839            StdString domId = domain->getDomainOutputName();
1840            StdString appendDomId  = singleDomain ? "" : "_" + domId ;
[1391]1841            StdString lonName,latName ;
[1430]1842            StdString dimIname,dimJname ;
[676]1843
[1415]1844            if (domain->lon_name.isEmpty())
1845            { 
1846              if (domain->type==CDomain::type_attr::curvilinear) lonName = "nav_lon";
1847              else lonName = "lon";
1848            }
[1391]1849            else lonName = domain->lon_name;
1850
[1415]1851            if (domain->lat_name.isEmpty())
1852            {
1853              if (domain->type==CDomain::type_attr::curvilinear) latName = "nav_lat";
1854              else latName = "lat";
1855            }
[1391]1856            else latName = domain->lat_name;
[1430]1857
1858            if (domain->dim_i_name.isEmpty())
1859            {
1860              if (domain->type==CDomain::type_attr::curvilinear) dimIname = "x";
1861              else if (domain->type==CDomain::type_attr::unstructured) dimIname = "cell";
1862              else dimIname = lonName;
1863            }
1864            else dimIname = domain->dim_i_name;
1865
1866            if (domain->dim_j_name.isEmpty())
1867            {
1868              if (domain->type==CDomain::type_attr::curvilinear) dimJname = "y";
1869              else dimJname = latName;
1870            }
1871            else dimJname = domain->dim_j_name;
[1391]1872       
[1158]1873            if (compressedOutput && domain->isCompressible() && domain->type != CDomain::type_attr::unstructured)
1874            {
1875              dimIdList.push_back(domId + "_points");
1876              field->setUseCompressedOutput();
1877            }
[676]1878
[1158]1879            switch (domain->type)
[879]1880            {
[1158]1881              case CDomain::type_attr::curvilinear:
1882                if (!compressedOutput || !domain->isCompressible())
1883                {
[1430]1884                  dimXid=dimIname+appendDomId;
1885                  dimYid=dimJname+appendDomId;
[1158]1886                  dimIdList.push_back(dimXid);
1887                  dimIdList.push_back(dimYid);
1888                }
[1415]1889                dimCoordList.push_back(lonName+appendDomId);
1890                dimCoordList.push_back(latName+appendDomId);
[1158]1891              break ;
1892              case CDomain::type_attr::rectilinear:
1893                if (!compressedOutput || !domain->isCompressible())
1894                {
[1430]1895                  dimXid     = dimIname+appendDomId;
1896                  dimYid     = dimJname+appendDomId;
[1158]1897                  dimIdList.push_back(dimXid);
1898                  dimIdList.push_back(dimYid);
1899                }
[1430]1900                if (lonName != dimIname)  dimCoordList.push_back(lonName+appendDomId);
1901                if (latName != dimJname)  dimCoordList.push_back(latName+appendDomId);
1902
[1158]1903              break ;
1904              case CDomain::type_attr::unstructured:
1905              {
1906                if (SuperClassWriter::useCFConvention)
1907                {
[1430]1908                  dimXid     = dimIname + appendDomId;
[1158]1909                  dimIdList.push_back(dimXid);
[1415]1910                  dimCoordList.push_back(lonName+appendDomId);
1911                  dimCoordList.push_back(latName+appendDomId);
[1158]1912                }
1913                else
1914                {
1915                  StdString domainName = domain->name;
1916                  if (domain->nvertex == 1)
1917                  {
1918                    dimXid     = "n" + domainName + "_node";
1919                    dimIdList.push_back(dimXid);
1920                    dimCoordList.push_back(StdString(domainName + "_node_x"));
1921                    dimCoordList.push_back(StdString(domainName + "_node_y"));
1922                  }
1923                  else if (domain->nvertex == 2)
1924                  {
1925                    dimXid     = "n" + domainName + "_edge";
1926                    dimIdList.push_back(dimXid);
1927                    dimCoordList.push_back(StdString(domainName + "_edge_x"));
1928                    dimCoordList.push_back(StdString(domainName + "_edge_y"));
1929                  }
1930                  else
1931                  {
1932                    dimXid     = "n" + domainName + "_face";
1933                    dimIdList.push_back(dimXid);
1934                    dimCoordList.push_back(StdString(domainName + "_face_x"));
1935                    dimCoordList.push_back(StdString(domainName + "_face_y"));
1936                  }
1937                }  // ugrid convention
1938              }  // case unstructured domain
[879]1939            }
[1158]1940
1941            if (domain->hasArea)
[879]1942            {
[1158]1943              hasArea = true;
1944              cellMeasures += " area" + appendDomId;
[879]1945            }
[1158]1946            ++idxDomain;
1947          }
1948          else if (1 == axisDomainOrder(i))
1949          {
1950            CAxis* axis = CAxis::get(axisList[idxAxis]);
1951            StdString axisId = axis->getAxisOutputName();
[1430]1952            StdString axisDim;
[1158]1953
[1430]1954            if (axis->dim_name.isEmpty()) axisDim = axisId;
1955            else axisDim=axis->dim_name.getValue();
1956
[1158]1957            if (compressedOutput && axis->isCompressible())
[879]1958            {
[1430]1959              dimIdList.push_back(axisDim + "_points");
[1158]1960              field->setUseCompressedOutput();
[879]1961            }
[1158]1962            else
[1430]1963              dimIdList.push_back(axisDim);
[878]1964
[1430]1965            if (axisDim != axisId) dimCoordList.push_back(axisId);
[1158]1966            ++idxAxis;
1967          }
[1430]1968          else
[1158]1969          {
[1430]1970            CScalar* scalar = CScalar::get(scalarList[idxScalar]);
1971            StdString scalarId = scalar->getScalarOutputName();
[1446]1972            if (!scalar->value.isEmpty() || !scalar->label.isEmpty())
1973              dimCoordList.push_back(scalarId);
[1430]1974            ++idxScalar;
[1158]1975          }
1976        }
[488]1977
[1158]1978        StdString fieldid = field->getFieldOutputName();
[219]1979
[1158]1980        nc_type type ;
1981        if (field->prec.isEmpty()) type =  NC_FLOAT ;
1982        else
1983        {
1984          if (field->prec==2) type = NC_SHORT ;
1985          else if (field->prec==4)  type =  NC_FLOAT ;
1986          else if (field->prec==8)   type =  NC_DOUBLE ;
1987        }
[488]1988
[1158]1989        bool wtime   = !(!field->operation.isEmpty() && field->getOperationTimeType() == func::CFunctor::once);
[488]1990
[1158]1991        if (wtime)
1992        {
1993          if (field->hasTimeInstant && hasTimeInstant) coodinates.push_back(string("time_instant"));
1994          else if (field->hasTimeCentered && hasTimeCentered)  coodinates.push_back(string("time_centered"));
1995          dims.push_back(timeid);
1996        }
[488]1997
[1158]1998        if (compressedOutput && grid->isCompressible())
1999        {
2000          dims.push_back(grid->getId() + "_points");
2001          field->setUseCompressedOutput();
2002        }
2003        else
2004        {
2005          while (!dimIdList.empty())
2006          {
2007            dims.push_back(dimIdList.back());
2008            dimIdList.pop_back();
2009          }
2010        }
[219]2011
[1158]2012        while (!dimCoordList.empty())
2013        {
2014          coodinates.push_back(dimCoordList.back());
2015          dimCoordList.pop_back();
2016        }
[219]2017
[1158]2018        try
2019        {
[498]2020           SuperClassWriter::addVariable(fieldid, type, dims);
[488]2021
[498]2022           if (!field->standard_name.isEmpty())
2023              SuperClassWriter::addAttribute
2024                 ("standard_name",  field->standard_name.getValue(), &fieldid);
[219]2025
[498]2026           if (!field->long_name.isEmpty())
2027              SuperClassWriter::addAttribute
2028                 ("long_name", field->long_name.getValue(), &fieldid);
[219]2029
[498]2030           if (!field->unit.isEmpty())
2031              SuperClassWriter::addAttribute
2032                 ("units", field->unit.getValue(), &fieldid);
[463]2033
[1158]2034           // Ugrid field attributes "mesh" and "location"
2035           if (!SuperClassWriter::useCFConvention)
2036           {
2037            if (!domainList.empty())
2038            {
2039              CDomain* domain = CDomain::get(domainList[0]); // Suppose that we have only domain
2040              StdString mesh = domain->name;
2041              SuperClassWriter::addAttribute("mesh", mesh, &fieldid);
2042              StdString location;
2043              if (domain->nvertex == 1)
2044                location = "node";
2045              else if (domain->nvertex == 2)
2046                location = "edge";
2047              else if (domain->nvertex > 2)
2048                location = "face";
2049              SuperClassWriter::addAttribute("location", location, &fieldid);
2050            }
2051
2052           }
2053
2054           if (!field->valid_min.isEmpty())
[498]2055              SuperClassWriter::addAttribute
2056                 ("valid_min", field->valid_min.getValue(), &fieldid);
[463]2057
[498]2058           if (!field->valid_max.isEmpty())
2059              SuperClassWriter::addAttribute
2060                 ("valid_max", field->valid_max.getValue(), &fieldid);
[464]2061
[498]2062            if (!field->scale_factor.isEmpty())
2063              SuperClassWriter::addAttribute
2064                 ("scale_factor", field->scale_factor.getValue(), &fieldid);
[464]2065
[498]2066             if (!field->add_offset.isEmpty())
2067              SuperClassWriter::addAttribute
2068                 ("add_offset", field->add_offset.getValue(), &fieldid);
[488]2069
[498]2070           SuperClassWriter::addAttribute
2071                 ("online_operation", field->operation.getValue(), &fieldid);
[472]2072
[498]2073          // write child variables as attributes
[488]2074
2075
[1021]2076           bool alreadyAddCellMethod = false;
2077           StdString cellMethodsPrefix(""), cellMethodsSuffix("");
2078           if (!field->cell_methods.isEmpty())
2079           {
[1158]2080              StdString cellMethodString = field->cell_methods;
2081              if (field->cell_methods_mode.isEmpty() ||
[1021]2082                 (CField::cell_methods_mode_attr::overwrite == field->cell_methods_mode))
[1158]2083              {
2084                SuperClassWriter::addAttribute("cell_methods", cellMethodString, &fieldid);
2085                alreadyAddCellMethod = true;
2086              }
2087              else
2088              {
2089                switch (field->cell_methods_mode)
2090                {
2091                  case (CField::cell_methods_mode_attr::prefix):
2092                    cellMethodsPrefix = cellMethodString;
2093                    cellMethodsPrefix += " ";
2094                    break;
2095                  case (CField::cell_methods_mode_attr::suffix):
2096                    cellMethodsSuffix = " ";
2097                    cellMethodsSuffix += cellMethodString;
2098                    break;
2099                  case (CField::cell_methods_mode_attr::none):
2100                    break;
2101                  default:
2102                    break;
2103                }
2104              }
[1021]2105           }
[488]2106
[1021]2107
[498]2108           if (wtime)
2109           {
[614]2110              CDuration freqOp = field->freq_op.getValue();
2111              freqOp.solveTimeStep(*context->calendar);
2112              StdString freqOpStr = freqOp.toStringUDUnits();
[612]2113              SuperClassWriter::addAttribute("interval_operation", freqOpStr, &fieldid);
[437]2114
[614]2115              CDuration freqOut = field->getRelFile()->output_freq.getValue();
2116              freqOut.solveTimeStep(*context->calendar);
2117              SuperClassWriter::addAttribute("interval_write", freqOut.toStringUDUnits(), &fieldid);
[612]2118
[1021]2119              StdString cellMethods(cellMethodsPrefix + "time: ");
[612]2120              if (field->operation.getValue() == "instant") cellMethods += "point";
2121              else if (field->operation.getValue() == "average") cellMethods += "mean";
2122              else if (field->operation.getValue() == "accumulate") cellMethods += "sum";
2123              else cellMethods += field->operation;
[614]2124              if (freqOp.resolve(*context->calendar) != freqOut.resolve(*context->calendar))
2125                cellMethods += " (interval: " + freqOpStr + ")";
[1021]2126              cellMethods += cellMethodsSuffix;
2127              if (!alreadyAddCellMethod)
2128                SuperClassWriter::addAttribute("cell_methods", cellMethods, &fieldid);
[498]2129           }
[488]2130
[611]2131           if (hasArea)
2132             SuperClassWriter::addAttribute("cell_measures", cellMeasures, &fieldid);
2133
[498]2134           if (!field->default_value.isEmpty())
2135           {
[1424]2136             double default_value = field->default_value.getValue();
2137             if (type == NC_DOUBLE)
2138             {
2139               SuperClassWriter::setDefaultValue(fieldid, &default_value);
2140             }
2141             else if (type == NC_SHORT)
2142             {
2143               short sdefault_value = (short)default_value;
2144               SuperClassWriter::setDefaultValue(fieldid, &sdefault_value);
2145             }
2146             else
2147             {
2148               float fdefault_value = (float)default_value;
2149               SuperClassWriter::setDefaultValue(fieldid, &fdefault_value);
2150             }
[498]2151           }
2152           else
[517]2153              SuperClassWriter::setDefaultValue(fieldid, (double*)NULL);
[219]2154
[606]2155            if (field->compression_level.isEmpty())
2156              field->compression_level = field->file->compression_level.isEmpty() ? 0 : field->file->compression_level;
2157            SuperClassWriter::setCompressionLevel(fieldid, field->compression_level);
2158
[878]2159           {  // Ecriture des coordonnes
[488]2160
[498]2161              StdString coordstr; //boost::algorithm::join(coodinates, " ")
2162              std::vector<StdString>::iterator
2163                 itc = coodinates.begin(), endc = coodinates.end();
[488]2164
[498]2165              for (; itc!= endc; itc++)
2166              {
2167                 StdString & coord = *itc;
2168                 if (itc+1 != endc)
2169                       coordstr.append(coord).append(" ");
2170                 else  coordstr.append(coord);
2171              }
[219]2172
[498]2173              SuperClassWriter::addAttribute("coordinates", coordstr, &fieldid);
[219]2174
[498]2175           }
[1222]2176
2177           vector<CVariable*> listVars = field->getAllVariables() ;
2178           for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ;
2179
[219]2180         }
[498]2181         catch (CNetCdfException& e)
2182         {
2183           StdString msg("On writing field : ");
2184           msg.append(fieldid); msg.append("\n");
2185           msg.append("In the context : ");
2186           msg.append(context->getId()); msg.append("\n");
2187           msg.append(e.what());
2188           ERROR("CNc4DataOutput::writeField_(CField* field)", << msg);
2189         }
[879]2190      } // writeField_()
[219]2191
2192      //--------------------------------------------------------------
2193
[347]2194      void CNc4DataOutput::writeFile_ (CFile* file)
[219]2195      {
[773]2196         StdString filename = file->getFileOutputName();
[219]2197         StdString description = (!file->description.isEmpty())
2198                               ? file->description.getValue()
[335]2199                               : StdString("Created by xios");
[609]2200
2201         singleDomain = (file->nbDomains == 1);
2202
[1158]2203         StdString conv_str ;
2204         if (file->convention_str.isEmpty())
2205         {
2206            if (SuperClassWriter::useCFConvention) conv_str="CF-1.6" ;
2207            else conv_str="UGRID" ;
2208         }
2209         else conv_str=file->convention_str ;
2210           
[498]2211         try
2212         {
[1309]2213           if (!appendMode) this->writeFileAttributes(filename, description,
2214                                                      conv_str,
2215                                                      StdString("An IPSL model"),
2216                                                      this->getTimeStamp());
[609]2217
[701]2218           if (!appendMode)
2219             SuperClassWriter::addDimension("axis_nbounds", 2);
[498]2220         }
2221         catch (CNetCdfException& e)
2222         {
2223           StdString msg("On writing file : ");
2224           msg.append(filename); msg.append("\n");
2225           msg.append("In the context : ");
2226           CContext* context = CContext::getCurrent() ;
2227           msg.append(context->getId()); msg.append("\n");
2228           msg.append(e.what());
2229           ERROR("CNc4DataOutput::writeFile_ (CFile* file)", << msg);
2230         }
[219]2231      }
[488]2232
[472]2233      void CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)
2234      {
[773]2235        StdString name = var->getVariableOutputName();
[488]2236
[498]2237        try
2238        {
[527]2239          if (var->type.getValue() == CVariable::type_attr::t_int || var->type.getValue() == CVariable::type_attr::t_int32)
2240            addAttribute(name, var->getData<int>(), &fieldId);
2241          else if (var->type.getValue() == CVariable::type_attr::t_int16)
2242            addAttribute(name, var->getData<short int>(), &fieldId);
2243          else if (var->type.getValue() == CVariable::type_attr::t_float)
2244            addAttribute(name, var->getData<float>(), &fieldId);
2245          else if (var->type.getValue() == CVariable::type_attr::t_double)
2246            addAttribute(name, var->getData<double>(), &fieldId);
2247          else if (var->type.getValue() == CVariable::type_attr::t_string)
2248            addAttribute(name, var->getData<string>(), &fieldId);
2249          else
2250            ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)",
2251                  << "Unsupported variable of type " << var->type.getStringValue());
[498]2252        }
2253       catch (CNetCdfException& e)
2254       {
2255         StdString msg("On writing attributes of variable with name : ");
2256         msg.append(name); msg.append("in the field "); msg.append(fieldId); msg.append("\n");
2257         msg.append("In the context : ");
2258         CContext* context = CContext::getCurrent() ;
2259         msg.append(context->getId()); msg.append("\n");
2260         msg.append(e.what());
2261         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)", << msg);
2262       }
[472]2263     }
[488]2264
[472]2265     void CNc4DataOutput::writeAttribute_ (CVariable* var)
2266     {
[773]2267        StdString name = var->getVariableOutputName();
2268
[498]2269        try
2270        {
[527]2271          if (var->type.getValue() == CVariable::type_attr::t_int || var->type.getValue() == CVariable::type_attr::t_int32)
2272            addAttribute(name, var->getData<int>());
2273          else if (var->type.getValue() == CVariable::type_attr::t_int16)
2274            addAttribute(name, var->getData<short int>());
2275          else if (var->type.getValue() == CVariable::type_attr::t_float)
2276            addAttribute(name, var->getData<float>());
2277          else if (var->type.getValue() == CVariable::type_attr::t_double)
2278            addAttribute(name, var->getData<double>());
2279          else if (var->type.getValue() == CVariable::type_attr::t_string)
2280            addAttribute(name, var->getData<string>());
2281          else
2282            ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)",
2283                  << "Unsupported variable of type " << var->type.getStringValue());
[498]2284        }
2285       catch (CNetCdfException& e)
2286       {
2287         StdString msg("On writing attributes of variable with name : ");
2288         msg.append(name); msg.append("\n");
2289         msg.append("In the context : ");
2290         CContext* context = CContext::getCurrent() ;
2291         msg.append(context->getId()); msg.append("\n");
2292         msg.append(e.what());
2293         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)", << msg);
2294       }
[488]2295     }
2296
[321]2297      void CNc4DataOutput::syncFile_ (void)
2298      {
[498]2299        try
2300        {
2301          SuperClassWriter::sync() ;
2302        }
2303        catch (CNetCdfException& e)
2304        {
2305         StdString msg("On synchronizing the write among processes");
2306         msg.append("In the context : ");
2307         CContext* context = CContext::getCurrent() ;
2308         msg.append(context->getId()); msg.append("\n");
2309         msg.append(e.what());
2310         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
2311        }
[321]2312      }
[219]2313
[286]2314      void CNc4DataOutput::closeFile_ (void)
2315      {
[498]2316        try
2317        {
2318          SuperClassWriter::close() ;
2319        }
2320        catch (CNetCdfException& e)
2321        {
2322         StdString msg("On closing file");
2323         msg.append("In the context : ");
2324         CContext* context = CContext::getCurrent() ;
2325         msg.append(context->getId()); msg.append("\n");
2326         msg.append(e.what());
2327         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
2328        }
2329
[286]2330      }
2331
[219]2332      //---------------------------------------------------------------
2333
2334      StdString CNc4DataOutput::getTimeStamp(void) const
2335      {
2336         const int buffer_size = 100;
2337         time_t rawtime;
2338         struct tm * timeinfo = NULL;
2339         char buffer [buffer_size];
[1158]2340         StdString formatStr;
2341         if (file->time_stamp_format.isEmpty()) formatStr="%Y-%b-%d %H:%M:%S %Z" ;
2342         else formatStr=file->time_stamp_format;
[219]2343
[1158]2344//         time ( &rawtime );
2345//         timeinfo = localtime ( &rawtime );
[219]2346         time ( &rawtime );
[1158]2347         timeinfo = gmtime ( &rawtime );
2348         strftime (buffer, buffer_size, formatStr.c_str(), timeinfo);
[219]2349
2350         return (StdString(buffer));
2351      }
[488]2352
[219]2353      //---------------------------------------------------------------
[488]2354
[347]2355      void CNc4DataOutput::writeFieldData_ (CField*  field)
[219]2356      {
[707]2357        CContext* context = CContext::getCurrent();
2358        CContextServer* server = context->server;
2359        CGrid* grid = field->grid;
[300]2360
[1158]2361        if (field->getNStep()<1) 
2362        {
2363          return;
2364        }
[952]2365       
[707]2366        if (!grid->doGridHaveDataToWrite())
[1158]2367          if (SuperClass::type == MULTI_FILE || !isCollective)
2368          {
2369            return;
2370          }
[488]2371
[770]2372        StdString fieldid = field->getFieldOutputName();
[286]2373
[707]2374        StdOStringStream oss;
2375        string timeAxisId;
[1158]2376        if (field->hasTimeInstant) timeAxisId = "time_instant";
2377        else if (field->hasTimeCentered) timeAxisId = "time_centered";
[488]2378
[802]2379        StdString timeBoundId = getTimeCounterName() + "_bounds";
[449]2380
[707]2381        StdString timeAxisBoundId;
[1158]2382        if (field->hasTimeInstant) timeAxisBoundId = "time_instant_bounds";
2383        else if (field->hasTimeCentered) timeAxisBoundId = "time_centered_bounds";
[488]2384
[707]2385        if (!field->wasWritten())
2386        {
[1158]2387          if (appendMode && field->file->record_offset.isEmpty() && 
2388              field->getOperationTimeType() != func::CFunctor::once)
[707]2389          {
[1158]2390            double factorUnit;
2391            if (!field->file->time_units.isEmpty() && field->file->time_units==CFile::time_units_attr::days)
2392            factorUnit=context->getCalendar()->getDayLengthInSeconds() ;
2393            else factorUnit=1 ;
2394            field->resetNStep(getRecordFromTime(field->last_Write_srv,factorUnit) + 1);
[707]2395          }
[488]2396
[707]2397          field->setWritten();
2398        }
[488]2399
2400
[707]2401        CArray<double,1> time_data(1);
2402        CArray<double,1> time_data_bound(2);
2403        CArray<double,1> time_counter(1);
2404        CArray<double,1> time_counter_bound(2);
2405
2406        bool wtime = (field->getOperationTimeType() != func::CFunctor::once);
[1158]2407        bool wtimeCounter =false ;
2408        bool wtimeData =false ;
2409       
[707]2410
[444]2411        if (wtime)
2412        {
[692]2413          Time lastWrite = field->last_Write_srv;
2414          Time lastLastWrite = field->lastlast_Write_srv;
2415
[1158]2416         
2417          if (field->hasTimeInstant)
2418          {
2419            time_data(0) = time_data_bound(1) = lastWrite;
[692]2420            time_data_bound(0) = time_data_bound(1) = lastWrite;
[1158]2421            if (timeCounterType==instant)
2422            {
2423              time_counter(0) = time_data(0);
2424              time_counter_bound(0) = time_data_bound(0);
2425              time_counter_bound(1) = time_data_bound(1);
2426              wtimeCounter=true ;
2427            }
2428            if (hasTimeInstant) wtimeData=true ;
2429          }
2430          else if (field->hasTimeCentered)
[488]2431          {
[1158]2432            time_data(0) = (lastWrite + lastLastWrite) / 2;
[692]2433            time_data_bound(0) = lastLastWrite;
2434            time_data_bound(1) = lastWrite;
[1158]2435            if (timeCounterType==centered)
2436            {
2437              time_counter(0) = time_data(0) ;
2438              time_counter_bound(0) = time_data_bound(0) ;
2439              time_counter_bound(1) = time_data_bound(1) ;
2440              wtimeCounter=true ;
2441            }
2442            if (hasTimeCentered) wtimeData=true ;
[488]2443          }
2444
[1158]2445          if (timeCounterType==record)
2446          {
[692]2447            time_counter(0) = field->getNStep() - 1;
[1158]2448            time_counter_bound(0) = time_counter_bound(1) = field->getNStep() - 1;
2449            wtimeCounter=true ;
2450          }
[692]2451
[1158]2452          if (!field->file->time_units.isEmpty() && field->file->time_units==CFile::time_units_attr::days)
[692]2453          {
[1158]2454            double secByDay=context->getCalendar()->getDayLengthInSeconds() ;
2455            time_data/=secByDay;
2456            time_data_bound/=secByDay;
2457            time_counter/=secByDay;
2458            time_counter_bound/=secByDay;
[692]2459          }
2460        }
2461
[707]2462         bool isRoot = (server->intraCommRank == 0);
[488]2463
[464]2464         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
2465         {
[707]2466           double scaleFactor = 1.0;
2467           double addOffset = 0.0;
2468           if (!field->scale_factor.isEmpty()) scaleFactor = field->scale_factor;
2469           if (!field->add_offset.isEmpty()) addOffset = field->add_offset;
2470           field->scaleFactorAddOffset(scaleFactor, addOffset);
[464]2471         }
[488]2472
[498]2473         try
[219]2474         {
[676]2475           size_t writtenSize;
2476           if (field->getUseCompressedOutput())
2477             writtenSize = grid->getNumberWrittenIndexes();
2478           else
2479             writtenSize = grid->getWrittenDataSize();
2480
2481           CArray<double,1> fieldData(writtenSize);
[567]2482           if (!field->default_value.isEmpty()) fieldData = field->default_value;
[676]2483
2484           if (field->getUseCompressedOutput())
2485             field->outputCompressedField(fieldData);
2486           else
2487             field->outputField(fieldData);
2488
[707]2489           if (!field->prec.isEmpty() && field->prec == 2) fieldData = round(fieldData);
[567]2490
2491           switch (SuperClass::type)
[498]2492           {
[567]2493              case (MULTI_FILE) :
2494              {
[1158]2495                 CTimer::get("Files : writing data").resume();
[692]2496                 SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep() - 1);
[1158]2497                 CTimer::get("Files : writing data").suspend();
[567]2498                 if (wtime)
2499                 {
[1158]2500                   CTimer::get("Files : writing time axis").resume();
2501                   if ( wtimeData)
[692]2502                   {
[1158]2503                       SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep() - 1, isRoot);
2504                       SuperClassWriter::writeTimeAxisDataBounds(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1, isRoot);
2505                  }
2506                   if (wtimeCounter)
2507                   {
2508                     SuperClassWriter::writeTimeAxisData(time_counter, getTimeCounterName(), isCollective, field->getNStep() - 1,isRoot);
2509                     if (timeCounterType!=record) SuperClassWriter::writeTimeAxisDataBounds(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1, isRoot);
[692]2510                   }
[1158]2511                   CTimer::get("Files : writing time axis").suspend();
[567]2512                 }
[707]2513                 break;
[567]2514              }
2515              case (ONE_FILE) :
2516              {
[464]2517
[676]2518                std::vector<StdSize> start, count;
[464]2519
[676]2520                if (field->getUseCompressedOutput())
2521                {
2522                  if (grid->isCompressible())
2523                  {
2524                    start.push_back(grid->getOffsetWrittenIndexes());
2525                    count.push_back(grid->getNumberWrittenIndexes());
2526                  }
2527                  else
2528                  {
[887]2529                    CArray<int,1> axisDomainOrder = grid->axis_domain_order;
[676]2530                    std::vector<StdString> domainList = grid->getDomainList();
2531                    std::vector<StdString> axisList   = grid->getAxisList();
2532                    int numElement = axisDomainOrder.numElements();
2533                    int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
[1553]2534                    int idx = domainList.size() * 2 + axisList.size() - 1;
[464]2535
[1553]2536                    start.reserve(idx+1);
2537                    count.reserve(idx+1);
[676]2538
2539                    for (int i = numElement - 1; i >= 0; --i)
2540                    {
[887]2541                      if (2 == axisDomainOrder(i))
[676]2542                      {
2543                        CDomain* domain = CDomain::get(domainList[idxDomain]);
2544
2545                        if (domain->isCompressible())
2546                        {
[1249]2547                          start.push_back(domain->getOffsetWrittenIndexes(comm_file));
2548                          count.push_back(domain->getNumberWrittenIndexes(comm_file));
[710]2549                          idx -= 2;
[676]2550                        }
2551                        else
2552                        {
[710]2553                          if ((domain->type) != CDomain::type_attr::unstructured)
2554                          {
[1553]2555                            start.push_back(domain->jbegin);
2556                            count.push_back(domain->nj);
[710]2557                          }
2558                          --idx;
[1553]2559                          start.push_back(domain->ibegin);
2560                          count.push_back(domain->ni);
[710]2561                          --idx;
[676]2562                        }
2563                        --idxDomain;
2564                      }
[887]2565                      else if (1 == axisDomainOrder(i))
[676]2566                      {
2567                        CAxis* axis = CAxis::get(axisList[idxAxis]);
2568
2569                        if (axis->isCompressible())
2570                        {
[1249]2571                          start.push_back(axis->getOffsetWrittenIndexes(comm_file));
2572                          count.push_back(axis->getNumberWrittenIndexes(comm_file));
[676]2573                        }
2574                        else
2575                        {
[1553]2576                          start.push_back(axis->begin);
2577                          count.push_back(axis->n);
[676]2578                        }
2579                        --idxAxis;
2580                        --idx;
2581                      }
2582                    }
[1158]2583                  }
[676]2584                }
2585                else
[498]2586                {
[887]2587                  CArray<int,1> axisDomainOrder = grid->axis_domain_order;
[705]2588                  std::vector<StdString> domainList = grid->getDomainList();
2589                  std::vector<StdString> axisList   = grid->getAxisList();
2590                  int numElement = axisDomainOrder.numElements();
2591                  int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
[1553]2592                  int idx = domainList.size() * 2 + axisList.size() - 1;
[705]2593
[1553]2594                  start.reserve(idx+1);
2595                  count.reserve(idx+1);
[705]2596
2597                  for (int i = numElement - 1; i >= 0; --i)
2598                  {
[887]2599                    if (2 == axisDomainOrder(i))
[705]2600                    {
2601                      CDomain* domain = CDomain::get(domainList[idxDomain]);
[710]2602                      if ((domain->type) != CDomain::type_attr::unstructured)
[705]2603                      {
[1553]2604                        start.push_back(domain->jbegin);
2605                        count.push_back(domain->nj);
[705]2606                      }
2607                      --idx ;
[1143]2608
[1553]2609                        start.push_back(domain->ibegin);
2610                        count.push_back(domain->ni);
[705]2611                      --idx ;
2612                      --idxDomain;
2613                    }
[887]2614                    else if (1 == axisDomainOrder(i))
[705]2615                    {
[1143]2616                        CAxis* axis = CAxis::get(axisList[idxAxis]);
[1559]2617                        start.push_back(axis->begin);
2618                        count.push_back(axis->n);
[705]2619                      --idx;
[1025]2620                      --idxAxis;
[887]2621                    }
2622                    else
2623                    {
2624                      if (1 == axisDomainOrder.numElements())
2625                      {
2626                        start.push_back(0);
2627                        count.push_back(1);
2628                      }
2629                      --idx;
2630                    }
[705]2631                  }
[498]2632                }
[488]2633
[1158]2634
2635                CTimer::get("Files : writing data").resume();
[676]2636                SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep() - 1, &start, &count);
[1158]2637                CTimer::get("Files : writing data").suspend();
2638
2639                 if (wtime)
2640                 {
2641                   CTimer::get("Files : writing time axis").resume();
2642                   if ( wtimeData)
[692]2643                   {
[1158]2644                     SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep() - 1, isRoot);
2645                     SuperClassWriter::writeTimeAxisDataBounds(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1, isRoot);
[692]2646                   }
[1158]2647                   if (wtimeCounter)
2648                   {
2649                     SuperClassWriter::writeTimeAxisData(time_counter, getTimeCounterName(), isCollective, field->getNStep() - 1,isRoot);
2650                     if (timeCounterType!=record) SuperClassWriter::writeTimeAxisDataBounds(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1, isRoot);
[586]2651
[1158]2652                   }
2653                   CTimer::get("Files : writing time axis").suspend(); 
2654                 }
2655
[586]2656                break;
[286]2657              }
[567]2658            }
[219]2659         }
[498]2660         catch (CNetCdfException& e)
2661         {
2662           StdString msg("On writing field data: ");
2663           msg.append(fieldid); msg.append("\n");
2664           msg.append("In the context : ");
2665           msg.append(context->getId()); msg.append("\n");
2666           msg.append(e.what());
[1130]2667           ERROR("CNc4DataOutput::writeFieldData_ (CField*  field)", << msg);
[498]2668         }
[219]2669      }
2670
2671      //---------------------------------------------------------------
2672
2673      void CNc4DataOutput::writeTimeAxis_
[347]2674                  (CField*    field,
[1542]2675                   const std::shared_ptr<CCalendar> cal)
[219]2676      {
2677         StdOStringStream oss;
[1158]2678         bool createInstantAxis=false ;
2679         bool createCenteredAxis=false ;
2680         bool createTimeCounterAxis=false ;
2681         
[645]2682         if (field->getOperationTimeType() == func::CFunctor::once) return ;
[488]2683
2684
[1158]2685         StdString axisId ;
2686         StdString axisBoundId;
[802]2687         StdString timeid(getTimeCounterName());
[614]2688         StdString timeBoundId("axis_nbounds");
[488]2689
[1158]2690         StdString strTimeUnits ;
2691         if (!field->file->time_units.isEmpty() && field->file->time_units==CFile::time_units_attr::days) strTimeUnits="days since " ;
2692         else  strTimeUnits="seconds since " ;
2693 
2694         if (field->getOperationTimeType() == func::CFunctor::instant) field->hasTimeInstant = true;
2695         if (field->getOperationTimeType() == func::CFunctor::centered) field->hasTimeCentered = true;
2696
2697
2698         if (field->file->time_counter.isEmpty())
[488]2699         {
[1158]2700           if (timeCounterType==none) createTimeCounterAxis=true ;
2701           if (field->hasTimeCentered)
2702           {
2703             timeCounterType=centered ;
2704             if (!hasTimeCentered) createCenteredAxis=true ;
2705           }
2706           if (field->hasTimeInstant)
2707           {
2708             if (timeCounterType==none) timeCounterType=instant ;
2709             if (!hasTimeInstant) createInstantAxis=true ;
2710           }
[488]2711         }
[1158]2712         else if (field->file->time_counter==CFile::time_counter_attr::instant)
2713         {
2714           if (field->hasTimeCentered)
2715           {
2716             if (!hasTimeCentered) createCenteredAxis=true ;
2717           }
2718           if (field->hasTimeInstant)
2719           {
2720             if (timeCounterType==none) createTimeCounterAxis=true ;
2721             timeCounterType=instant ;
2722             if (!hasTimeInstant) createInstantAxis=true ;
2723           }
2724         }
2725         else if (field->file->time_counter==CFile::time_counter_attr::centered)
2726         {
2727           if (field->hasTimeCentered)
2728           {
2729             if (timeCounterType==none) createTimeCounterAxis=true ;
2730             timeCounterType=centered ;
2731             if (!hasTimeCentered) createCenteredAxis=true ;
2732           }
2733           if (field->hasTimeInstant)
2734           {
2735             if (!hasTimeInstant) createInstantAxis=true ;
2736           }
2737         }
2738         else if (field->file->time_counter==CFile::time_counter_attr::instant_exclusive)
2739         {
2740           if (field->hasTimeCentered)
2741           {
2742             if (!hasTimeCentered) createCenteredAxis=true ;
2743           }
2744           if (field->hasTimeInstant)
2745           {
2746             if (timeCounterType==none) createTimeCounterAxis=true ;
2747             timeCounterType=instant ;
2748           }
2749         }
2750         else if (field->file->time_counter==CFile::time_counter_attr::centered_exclusive)
2751         {
2752           if (field->hasTimeCentered)
2753           {
2754             if (timeCounterType==none) createTimeCounterAxis=true ;
2755             timeCounterType=centered ;
2756           }
2757           if (field->hasTimeInstant)
2758           {
2759             if (!hasTimeInstant) createInstantAxis=true ;
2760           }
2761         }
2762         else if (field->file->time_counter==CFile::time_counter_attr::exclusive)
2763         {
2764           if (field->hasTimeCentered)
2765           {
2766             if (timeCounterType==none) createTimeCounterAxis=true ;
2767             if (timeCounterType==instant) createInstantAxis=true ;
2768             timeCounterType=centered ;
2769           }
2770           if (field->hasTimeInstant)
2771           {
2772             if (timeCounterType==none)
2773             {
2774               createTimeCounterAxis=true ;
2775               timeCounterType=instant ;
2776             }
2777             if (timeCounterType==centered)
2778             {
2779               if (!hasTimeInstant) createInstantAxis=true ;
2780             }
2781           }
2782         }
2783         else if (field->file->time_counter==CFile::time_counter_attr::none)
2784         {
2785           if (field->hasTimeCentered)
2786           {
2787             if (!hasTimeCentered) createCenteredAxis=true ;
2788           }
2789           if (field->hasTimeInstant)
2790           {
2791             if (!hasTimeInstant) createInstantAxis=true ;
2792           }
2793         }
2794         else if (field->file->time_counter==CFile::time_counter_attr::record)
2795         {
2796           if (timeCounterType==none) createTimeCounterAxis=true ;
2797           timeCounterType=record ;
2798           if (field->hasTimeCentered)
2799           {
2800             if (!hasTimeCentered) createCenteredAxis=true ;
2801           }
2802           if (field->hasTimeInstant)
2803           {
2804             if (!hasTimeInstant) createInstantAxis=true ;
2805           }
2806         }
2807         
2808         if (createInstantAxis)
2809         {
2810           axisId="time_instant" ;
2811           axisBoundId="time_instant_bounds";
2812           hasTimeInstant=true ;
2813         }
[488]2814
[1158]2815         if (createCenteredAxis)
2816         {
2817           axisId="time_centered" ;
2818           axisBoundId="time_centered_bounds";
2819           hasTimeCentered=true ;
2820         }
2821
2822         
[498]2823         try
[219]2824         {
[1158]2825            std::vector<StdString> dims;
2826           
2827            if (createInstantAxis || createCenteredAxis)
2828            {
2829              // Adding time_instant or time_centered
2830              dims.push_back(timeid);
2831              if (!SuperClassWriter::varExist(axisId))
2832              {
2833                SuperClassWriter::addVariable(axisId, NC_DOUBLE, dims);
[488]2834
[1158]2835                CDate timeOrigin=cal->getTimeOrigin() ;
2836                StdOStringStream oss2;
2837                StdString strInitdate=oss2.str() ;
2838                StdString strTimeOrigin=timeOrigin.toString() ;
2839                this->writeTimeAxisAttributes(axisId, cal->getType(),strTimeUnits+strTimeOrigin,
2840                                              strTimeOrigin, axisBoundId);
2841             }
[219]2842
[1158]2843             // Adding time_instant_bounds or time_centered_bounds variables
2844             if (!SuperClassWriter::varExist(axisBoundId))
2845             {
2846                dims.clear() ;
2847                dims.push_back(timeid);
2848                dims.push_back(timeBoundId);
2849                SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
2850             }
[498]2851           }
[488]2852
[1158]2853           if (createTimeCounterAxis)
[498]2854           {
[692]2855             // Adding time_counter
[1158]2856             axisId = getTimeCounterName();
[802]2857             axisBoundId = getTimeCounterName() + "_bounds";
[692]2858             dims.clear();
2859             dims.push_back(timeid);
[1158]2860             if (!SuperClassWriter::varExist(axisId))
[692]2861             {
[1158]2862                SuperClassWriter::addVariable(axisId, NC_DOUBLE, dims);
2863                SuperClassWriter::addAttribute("axis", string("T"), &axisId);
[488]2864
[1158]2865                if (field->file->time_counter.isEmpty() || 
2866                   (field->file->time_counter != CFile::time_counter_attr::record))
[692]2867                {
2868                  CDate timeOrigin = cal->getTimeOrigin();
2869                  StdString strTimeOrigin = timeOrigin.toString();
[498]2870
[1158]2871                  this->writeTimeAxisAttributes(axisId, cal->getType(),
2872                                                strTimeUnits+strTimeOrigin,
[692]2873                                                strTimeOrigin, axisBoundId);
2874                }
2875             }
2876
2877             // Adding time_counter_bound dimension
[1158]2878             if (field->file->time_counter.isEmpty() || (field->file->time_counter != CFile::time_counter_attr::record))
[692]2879             {
2880                if (!SuperClassWriter::varExist(axisBoundId))
2881                {
2882                  dims.clear();
2883                  dims.push_back(timeid);
2884                  dims.push_back(timeBoundId);
2885                  SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
2886                }
2887             }
[498]2888           }
[488]2889         }
[498]2890         catch (CNetCdfException& e)
[488]2891         {
[498]2892           StdString msg("On writing time axis data: ");
2893           msg.append("In the context : ");
2894           CContext* context = CContext::getCurrent() ;
2895           msg.append(context->getId()); msg.append("\n");
2896           msg.append(e.what());
2897           ERROR("CNc4DataOutput::writeTimeAxis_ (CField*    field, \
[1542]2898                  const std::shared_ptr<CCalendar> cal)", << msg);
[488]2899         }
[219]2900      }
2901
2902      //---------------------------------------------------------------
[488]2903
[219]2904      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
2905                                                   const StdString & calendar,
2906                                                   const StdString & units,
2907                                                   const StdString & time_origin,
[488]2908                                                   const StdString & time_bounds,
[219]2909                                                   const StdString & standard_name,
[613]2910                                                   const StdString & long_name)
[219]2911      {
[498]2912         try
2913         {
2914           SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
2915           SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
2916           SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
2917           SuperClassWriter::addAttribute("units",         units        , &axis_name);
2918           SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
2919           SuperClassWriter::addAttribute("bounds",        time_bounds  , &axis_name);
2920         }
2921         catch (CNetCdfException& e)
2922         {
2923           StdString msg("On writing time axis Attribute: ");
2924           msg.append("In the context : ");
2925           CContext* context = CContext::getCurrent() ;
2926           msg.append(context->getId()); msg.append("\n");
2927           msg.append(e.what());
2928           ERROR("CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name, \
[613]2929                                                          const StdString & calendar,\
2930                                                          const StdString & units, \
2931                                                          const StdString & time_origin, \
2932                                                          const StdString & time_bounds, \
2933                                                          const StdString & standard_name, \
2934                                                          const StdString & long_name)", << msg);
[498]2935         }
[219]2936      }
[488]2937
[219]2938      //---------------------------------------------------------------
2939
2940      void CNc4DataOutput::writeAxisAttributes(const StdString & axis_name,
2941                                               const StdString & axis,
2942                                               const StdString & standard_name,
2943                                               const StdString & long_name,
2944                                               const StdString & units,
2945                                               const StdString & nav_model)
2946      {
[498]2947         try
2948         {
[613]2949          if (!axis.empty())
2950            SuperClassWriter::addAttribute("axis"       , axis         , &axis_name);
2951
[498]2952          SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
2953          SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
2954          SuperClassWriter::addAttribute("units"        , units        , &axis_name);
[973]2955//          SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
[498]2956         }
2957         catch (CNetCdfException& e)
2958         {
2959           StdString msg("On writing Axis Attribute: ");
2960           msg.append("In the context : ");
2961           CContext* context = CContext::getCurrent() ;
2962           msg.append(context->getId()); msg.append("\n");
2963           msg.append(e.what());
2964           ERROR("CNc4DataOutput::writeAxisAttributes(const StdString & axis_name, \
[613]2965                                                      const StdString & axis, \
2966                                                      const StdString & standard_name, \
2967                                                      const StdString & long_name, \
2968                                                      const StdString & units, \
2969                                                      const StdString & nav_model)", << msg);
[498]2970         }
[219]2971      }
2972
2973      //---------------------------------------------------------------
[488]2974
[219]2975      void CNc4DataOutput::writeLocalAttributes
2976         (int ibegin, int ni, int jbegin, int nj, StdString domid)
2977      {
[498]2978        try
2979        {
[318]2980         SuperClassWriter::addAttribute(StdString("ibegin").append(domid), ibegin);
2981         SuperClassWriter::addAttribute(StdString("ni"    ).append(domid), ni);
2982         SuperClassWriter::addAttribute(StdString("jbegin").append(domid), jbegin);
2983         SuperClassWriter::addAttribute(StdString("nj"    ).append(domid), nj);
[498]2984        }
2985        catch (CNetCdfException& e)
2986        {
2987           StdString msg("On writing Local Attributes: ");
2988           msg.append("In the context : ");
2989           CContext* context = CContext::getCurrent() ;
2990           msg.append(context->getId()); msg.append("\n");
2991           msg.append(e.what());
2992           ERROR("CNc4DataOutput::writeLocalAttributes \
2993                  (int ibegin, int ni, int jbegin, int nj, StdString domid)", << msg);
2994        }
2995
[219]2996      }
2997
[628]2998      void CNc4DataOutput::writeLocalAttributes_IOIPSL(const StdString& dimXid, const StdString& dimYid,
2999                                                       int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)
[391]3000      {
3001         CArray<int,1> array(2) ;
3002
[498]3003         try
3004         {
3005           SuperClassWriter::addAttribute("DOMAIN_number_total",size ) ;
3006           SuperClassWriter::addAttribute("DOMAIN_number", rank) ;
[629]3007           array = SuperClassWriter::getDimension(dimXid) + 1, SuperClassWriter::getDimension(dimYid) + 1;
[498]3008           SuperClassWriter::addAttribute("DOMAIN_dimensions_ids",array) ;
3009           array=ni_glo,nj_glo ;
3010           SuperClassWriter::addAttribute("DOMAIN_size_global", array) ;
3011           array=ni,nj ;
3012           SuperClassWriter::addAttribute("DOMAIN_size_local", array) ;
[819]3013           array=ibegin+1,jbegin+1 ;
[498]3014           SuperClassWriter::addAttribute("DOMAIN_position_first", array) ;
[819]3015           array=ibegin+ni-1+1,jbegin+nj-1+1 ;
[498]3016           SuperClassWriter::addAttribute("DOMAIN_position_last",array) ;
3017           array=0,0 ;
3018           SuperClassWriter::addAttribute("DOMAIN_halo_size_start", array) ;
3019           SuperClassWriter::addAttribute("DOMAIN_halo_size_end", array);
3020           SuperClassWriter::addAttribute("DOMAIN_type",string("box")) ;
3021  /*
3022           SuperClassWriter::addAttribute("DOMAIN_DIM_N001",string("x")) ;
3023           SuperClassWriter::addAttribute("DOMAIN_DIM_N002",string("y")) ;
3024           SuperClassWriter::addAttribute("DOMAIN_DIM_N003",string("axis_A")) ;
3025           SuperClassWriter::addAttribute("DOMAIN_DIM_N004",string("time_counter")) ;
3026  */
3027         }
3028         catch (CNetCdfException& e)
3029         {
[628]3030           StdString msg("On writing Local Attributes IOIPSL \n");
[498]3031           msg.append("In the context : ");
3032           CContext* context = CContext::getCurrent() ;
3033           msg.append(context->getId()); msg.append("\n");
3034           msg.append(e.what());
3035           ERROR("CNc4DataOutput::writeLocalAttributes_IOIPSL \
3036                  (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)", << msg);
3037         }
[391]3038      }
[219]3039      //---------------------------------------------------------------
3040
3041      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
3042                                                const StdString & description,
3043                                                const StdString & conventions,
3044                                                const StdString & production,
3045                                                const StdString & timeStamp)
3046      {
[498]3047         try
3048         {
3049           SuperClassWriter::addAttribute("name"       , name);
3050           SuperClassWriter::addAttribute("description", description);
[613]3051           SuperClassWriter::addAttribute("title"      , description);
3052           SuperClassWriter::addAttribute("Conventions", conventions);
[1158]3053           // SuperClassWriter::addAttribute("production" , production);
3054
3055           StdString timeStampStr ;
3056           if (file->time_stamp_name.isEmpty()) timeStampStr="timeStamp" ;
3057           else timeStampStr=file->time_stamp_name ;
3058           SuperClassWriter::addAttribute(timeStampStr, timeStamp);
3059
3060           StdString uuidName ;
3061           if (file->uuid_name.isEmpty()) uuidName="uuid" ;
3062           else uuidName=file->uuid_name ;
3063
3064           if (file->uuid_format.isEmpty()) SuperClassWriter::addAttribute(uuidName, getUuidStr());
3065           else SuperClassWriter::addAttribute(uuidName, getUuidStr(file->uuid_format));
3066         
[498]3067         }
3068         catch (CNetCdfException& e)
3069         {
3070           StdString msg("On writing File Attributes \n ");
3071           msg.append("In the context : ");
3072           CContext* context = CContext::getCurrent() ;
3073           msg.append(context->getId()); msg.append("\n");
3074           msg.append(e.what());
3075           ERROR("CNc4DataOutput:: writeFileAttributes(const StdString & name, \
3076                                                const StdString & description, \
3077                                                const StdString & conventions, \
3078                                                const StdString & production, \
3079                                                const StdString & timeStamp)", << msg);
3080         }
[219]3081      }
3082
3083      //---------------------------------------------------------------
3084
3085      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
3086                                               int data_dim,
3087                                               int data_ni,
3088                                               int data_nj,
3089                                               int data_ibegin,
3090                                               int data_jbegin)
3091      {
[498]3092         try
3093         {
3094           SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
3095           SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
3096           SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
3097           SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
3098           SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
3099         }
3100         catch (CNetCdfException& e)
3101         {
3102           StdString msg("On writing Mask Attributes \n ");
3103           msg.append("In the context : ");
3104           CContext* context = CContext::getCurrent() ;
3105           msg.append(context->getId()); msg.append("\n");
3106           msg.append(e.what());
3107           ERROR("CNc4DataOutput::writeMaskAttributes(const StdString & mask_name, \
3108                                               int data_dim, \
3109                                               int data_ni, \
3110                                               int data_nj, \
3111                                               int data_ibegin, \
3112                                               int data_jbegin)", << msg);
3113         }
[219]3114      }
3115
3116      ///--------------------------------------------------------------
3117
[1158]3118      StdSize CNc4DataOutput::getRecordFromTime(Time time, double factorUnit)
[707]3119      {
3120        std::map<Time, StdSize>::const_iterator it = timeToRecordCache.find(time);
3121        if (it == timeToRecordCache.end())
3122        {
[802]3123          StdString timeAxisBoundsId(getTimeCounterName() + "_bounds");
[1158]3124          if (!SuperClassWriter::varExist(timeAxisBoundsId)) timeAxisBoundsId = "time_centered_bounds";
3125          if (!SuperClassWriter::varExist(timeAxisBoundsId)) timeAxisBoundsId = "time_instant_bounds";
[707]3126
3127          CArray<double,2> timeAxisBounds;
[1158]3128          std::vector<StdSize> dimSize(SuperClassWriter::getDimensions(timeAxisBoundsId)) ;
3129         
[707]3130          StdSize record = 0;
3131          double dtime(time);
[1158]3132          for (int n = dimSize[0] - 1; n >= 0; n--)
[707]3133          {
[1158]3134            SuperClassWriter::getTimeAxisBounds(timeAxisBounds, timeAxisBoundsId, isCollective, n);
3135            timeAxisBounds*=factorUnit ;
3136            if (timeAxisBounds(1, 0) < dtime)
[707]3137            {
3138              record = n + 1;
3139              break;
3140            }
3141          }
3142          it = timeToRecordCache.insert(std::make_pair(time, record)).first;
3143        }
3144        return it->second;
3145      }
[774]3146
3147      ///--------------------------------------------------------------
3148
3149      bool CNc4DataOutput::isWrittenDomain(const std::string& domainName) const
3150      {
3151        return (this->writtenDomains.find(domainName) != this->writtenDomains.end());
3152      }
3153
3154      bool CNc4DataOutput::isWrittenCompressedDomain(const std::string& domainName) const
3155      {
3156        return (this->writtenCompressedDomains.find(domainName) != this->writtenCompressedDomains.end());
3157      }
3158
3159      bool CNc4DataOutput::isWrittenAxis(const std::string& axisName) const
3160      {
3161        return (this->writtenAxis.find(axisName) != this->writtenAxis.end());
3162      }
3163
3164      bool CNc4DataOutput::isWrittenCompressedAxis(const std::string& axisName) const
3165      {
3166        return (this->writtenCompressedAxis.find(axisName) != this->writtenCompressedAxis.end());
3167      }
3168
[887]3169      bool CNc4DataOutput::isWrittenScalar(const std::string& scalarName) const
3170      {
3171        return (this->writtenScalar.find(scalarName) != this->writtenScalar.end());
3172      }
3173
[774]3174      void CNc4DataOutput::setWrittenDomain(const std::string& domainName)
3175      {
3176        this->writtenDomains.insert(domainName);
3177      }
3178
3179      void CNc4DataOutput::setWrittenCompressedDomain(const std::string& domainName)
3180      {
3181        this->writtenCompressedDomains.insert(domainName);
3182      }
3183
3184      void CNc4DataOutput::setWrittenAxis(const std::string& axisName)
3185      {
3186        this->writtenAxis.insert(axisName);
3187      }
3188
3189      void CNc4DataOutput::setWrittenCompressedAxis(const std::string& axisName)
3190      {
3191        this->writtenCompressedAxis.insert(axisName);
3192      }
[887]3193
3194      void CNc4DataOutput::setWrittenScalar(const std::string& scalarName)
3195      {
3196        this->writtenScalar.insert(scalarName);
3197      }
[335]3198} // namespace xios
Note: See TracBrowser for help on using the repository browser.