source: XIOS3/trunk/src/io/nc4_data_output.cpp @ 2395

Last change on this file since 2395 was 2395, checked in by jderouillat, 22 months ago

Add a nvertex_name attribute for Domain

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