source: XIOS/dev/XIOS_DEV_CMIP6/src/io/nc4_data_output.cpp @ 1390

Last change on this file since 1390 was 1390, checked in by oabramkina, 4 years ago

Taking into account a possibility of having a hole on the client side (NEMO-like grid).

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