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

Last change on this file since 1099 was 1099, checked in by mhnguyen, 7 years ago

Updating 2-level server

+) Make some changes in the way data rebuilt on each level of server
+) Make some changes in the order of functions call during close context to make sure that each server receives the global indexes before calculating index to send to next level
+) Modify some functions to make sure data sent to the correct server pool

Test
+) On Curie
+) Only test_client

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