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

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

Workaround for cases where some servers have no data to write (rectilinear domain, null strides are not tolerated in blitz Range function)

  • 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->dim_j_name.isEmpty()) dimVertId=domain->dim_j_name;
858         else dimVertId = StdString("nvertex").append(appendDomid);
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.