source: XIOS/dev/dev_ym/XIOS_COUPLING/src/io/nc4_data_output.cpp @ 1930

Last change on this file since 1930 was 1930, checked in by ymipsl, 14 months ago

Big update on on going work related to data distribution and transfer between clients and servers.
Revisite of the source and store filter using "connectors".

YM

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