source: XIOS/trunk/src/io/nc4_data_output.cpp @ 706

Last change on this file since 706 was 706, checked in by ymipsl, 6 years ago

Little bug fix on output for strutured grid.
YM

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 81.9 KB
Line 
1
2#include "nc4_data_output.hpp"
3
4#include <boost/lexical_cast.hpp>
5#include "attribute_template.hpp"
6#include "group_template.hpp"
7
8#include "file.hpp"
9#include "calendar.hpp"
10#include "context.hpp"
11#include "context_server.hpp"
12#include "netCdfException.hpp"
13#include "exception.hpp"
14
15namespace xios
16{
17      /// ////////////////////// Définitions ////////////////////// ///
18      CNc4DataOutput::CNc4DataOutput
19         (const StdString & filename, bool exist)
20            : SuperClass()
21            , SuperClassWriter(filename, exist)
22            , filename(filename)
23      {
24         StdString timeid = StdString("time_counter");
25         SuperClass::type = MULTI_FILE;
26      }
27
28      CNc4DataOutput::CNc4DataOutput
29         (const StdString & filename, bool exist, bool useClassicFormat,
30          MPI_Comm comm_file,bool multifile, bool isCollective)
31            : SuperClass()
32            , SuperClassWriter(filename, exist, useClassicFormat, &comm_file, multifile)
33            , comm_file(comm_file)
34            , filename(filename)
35            , isCollective(isCollective)
36      {
37         StdString timeid = StdString("time_counter");
38
39         SuperClass::type = (multifile) ? MULTI_FILE : ONE_FILE;
40      }
41
42
43      CNc4DataOutput::~CNc4DataOutput(void)
44      { /* Ne rien faire de plus */ }
45
46      ///--------------------------------------------------------------
47
48      const StdString & CNc4DataOutput::getFileName(void) const
49      {
50         return (this->filename);
51      }
52
53      //---------------------------------------------------------------
54
55      void CNc4DataOutput::writeDomain_(CDomain* domain)
56      {
57         if (domain->type == CDomain::type_attr::unstructured)
58         {
59           writeUnstructuredDomain(domain) ;
60           return ;
61         }
62
63         CContext* context = CContext::getCurrent() ;
64         CContextServer* server=context->server ;
65
66         if (domain->IsWritten(this->filename)) return;
67         domain->checkAttributes();
68
69         if (domain->isEmpty())
70           if (SuperClass::type==MULTI_FILE) return ;
71
72         std::vector<StdString> dim0, dim1;
73         StdString domid     = (!domain->name.isEmpty())
74                             ? domain->name.getValue() : domain->getId();
75         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
76         if (isWrittenDomain(domid)) return ;
77         else writtenDomains.insert(domid) ; 
78
79
80         StdString dimXid, dimYid ;
81
82         bool isRegularDomain = (domain->type == CDomain::type_attr::rectilinear);
83         switch (domain->type)
84         {
85           case CDomain::type_attr::curvilinear :
86             dimXid     = StdString("x").append(appendDomid);
87             dimYid     = StdString("y").append(appendDomid);
88             break ;
89           case CDomain::type_attr::rectilinear :
90             dimXid     = StdString("lon").append(appendDomid);
91             dimYid     = StdString("lat").append(appendDomid);
92             break;
93         }
94
95         StdString dimVertId = StdString("nvertex").append(appendDomid);
96
97         string lonid,latid,bounds_lonid,bounds_latid ;
98         string areaId = "area" + appendDomid;
99/*
100         StdString lonid_loc = (server->intraCommSize > 1)
101                             ? StdString("lon").append(appendDomid).append("_local")
102                             : lonid;
103         StdString latid_loc = (server->intraCommSize > 1)
104                             ? StdString("lat").append(appendDomid).append("_local")
105                             : latid;
106*/
107
108         try
109         {
110           switch (SuperClass::type)
111           {
112              case (MULTI_FILE) :
113              {
114  //               if (domain->isEmpty()) return;
115
116                 if (server->intraCommSize > 1)
117                 {
118  //                 SuperClassWriter::addDimension(lonid, domain->zoom_ni.getValue());
119  //                 SuperClassWriter::addDimension(latid, domain->zoom_nj.getValue());
120                 }
121
122                 switch (domain->type)
123                 {
124                   case CDomain::type_attr::curvilinear :
125                     dim0.push_back(dimYid); dim0.push_back(dimXid);
126                     lonid = StdString("nav_lon").append(appendDomid);
127                     latid = StdString("nav_lat").append(appendDomid);
128                     break ;
129                   case CDomain::type_attr::rectilinear :
130                     lonid = StdString("lon").append(appendDomid);
131                     latid = StdString("lat").append(appendDomid);
132                     dim0.push_back(dimYid);
133                     dim1.push_back(dimXid);
134                     break;
135                 }
136
137                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
138                 bounds_latid = StdString("bounds_lat").append(appendDomid);
139
140                 SuperClassWriter::addDimension(dimXid, domain->zoom_ni_srv);
141                 SuperClassWriter::addDimension(dimYid, domain->zoom_nj_srv);
142
143                 if (domain->hasBounds)
144                   SuperClassWriter::addDimension(dimVertId, domain->nvertex);
145
146                 if (server->intraCommSize > 1)
147                 {
148                   this->writeLocalAttributes(domain->zoom_ibegin_srv,
149                                              domain->zoom_ni_srv,
150                                              domain->zoom_jbegin_srv,
151                                              domain->zoom_nj_srv,
152                                              appendDomid);
153
154                   if (singleDomain)
155                    this->writeLocalAttributes_IOIPSL(dimXid, dimYid,
156                                                      domain->zoom_ibegin_srv,
157                                                      domain->zoom_ni_srv,
158                                                      domain->zoom_jbegin_srv,
159                                                      domain->zoom_nj_srv,
160                                                      domain->ni_glo,domain->nj_glo,
161                                                      server->intraCommRank,server->intraCommSize);
162                 }
163
164                 if (domain->hasLonLat)
165                 {
166                   switch (domain->type)
167                   {
168                     case CDomain::type_attr::curvilinear :
169                       SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
170                       SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
171                       break ;
172                      case CDomain::type_attr::rectilinear :
173                        SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
174                        SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
175                        break ;
176                   }
177
178                   this->writeAxisAttributes(lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
179                   this->writeAxisAttributes(latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
180
181                   if (domain->hasBounds)
182                   {
183                     SuperClassWriter::addAttribute("bounds", bounds_lonid, &lonid);
184                     SuperClassWriter::addAttribute("bounds", bounds_latid, &latid);
185
186                     dim0.clear();
187                     dim0.push_back(dimYid);
188                     dim0.push_back(dimXid);
189                     dim0.push_back(dimVertId);
190                     SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
191                     SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
192                   }
193                 }
194
195                 dim0.clear();
196                 dim0.push_back(dimYid);
197                 dim0.push_back(dimXid);
198
199
200  // supress mask               if (server->intraCommSize > 1)
201  // supress mask               {
202  // supress mask                  SuperClassWriter::addVariable(maskid, NC_INT, dim0);
203  // supress mask
204  // supress mask                  this->writeMaskAttributes(maskid,
205  // supress mask                     domain->data_dim.getValue()/*,
206  // supress mask                     domain->data_ni.getValue(),
207  // supress mask                     domain->data_nj.getValue(),
208  // supress mask                     domain->data_ibegin.getValue(),
209  // supress mask                     domain->data_jbegin.getValue()*/);
210  // supress mask               }
211
212                 //SuperClassWriter::setDefaultValue(maskid, &dvm);
213
214                 if (domain->hasArea)
215                 {
216                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
217                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
218                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
219                 }
220
221                 SuperClassWriter::definition_end();
222
223                 if (domain->hasLonLat)
224                 {
225                   switch (domain->type)
226                   {
227                     case CDomain::type_attr::curvilinear :
228                       SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0);
229                       SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0);
230                       break;
231                     case CDomain::type_attr::rectilinear :
232                       CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;
233                       SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0);
234                       CArray<double,1> lon=domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;
235                       SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0);
236                       break;
237                   }
238
239                   if (domain->hasBounds)
240                   {
241                     SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0);
242                     SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0);
243                   }
244                 }
245
246                 if (domain->hasArea)
247                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0);
248
249                 SuperClassWriter::definition_start();
250
251                 break;
252              }
253              case (ONE_FILE) :
254              {
255                 SuperClassWriter::addDimension(dimXid, domain->global_zoom_ni);
256                 SuperClassWriter::addDimension(dimYid, domain->global_zoom_nj);
257
258                 if (domain->hasBounds)
259                   SuperClassWriter::addDimension(dimVertId, domain->nvertex);
260
261                 if (domain->hasLonLat)
262                 {
263                   switch (domain->type)
264                   {
265                     case CDomain::type_attr::curvilinear :
266                       dim0.push_back(dimYid); dim0.push_back(dimXid);
267                       lonid = StdString("nav_lon").append(appendDomid);
268                       latid = StdString("nav_lat").append(appendDomid);
269                       SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
270                       SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
271                       break;
272
273                     case CDomain::type_attr::rectilinear :
274                       dim0.push_back(dimYid);
275                       dim1.push_back(dimXid);
276                       lonid = StdString("lon").append(appendDomid);
277                       latid = StdString("lat").append(appendDomid);
278                       SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
279                       SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
280                       break;
281                   }
282
283                   bounds_lonid = StdString("bounds_lon").append(appendDomid);
284                   bounds_latid = StdString("bounds_lat").append(appendDomid);
285
286                   this->writeAxisAttributes
287                      (lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
288                   this->writeAxisAttributes
289                      (latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
290
291                   if (domain->hasBounds)
292                   {
293                     SuperClassWriter::addAttribute("bounds", bounds_lonid, &lonid);
294                     SuperClassWriter::addAttribute("bounds", bounds_latid, &latid);
295
296                     dim0.clear();
297                     dim0.push_back(dimYid);
298                     dim0.push_back(dimXid);
299                     dim0.push_back(dimVertId);
300                     SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
301                     SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
302                   }
303                 }
304
305                 if (domain->hasArea)
306                 {
307                   dim0.clear();
308                   dim0.push_back(dimYid); dim0.push_back(dimXid);
309                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
310                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
311                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
312                   dim0.clear();
313                 }
314
315                 SuperClassWriter::definition_end();
316
317                 switch (domain->type)
318                 {
319                   case CDomain::type_attr::curvilinear :
320                   {
321                     std::vector<StdSize> start(2) ;
322                     std::vector<StdSize> count(2) ;
323                     if (domain->isEmpty())
324                     {
325                       start[0]=0 ; start[1]=0 ;
326                       count[0]=0 ; count[1]=0 ;
327                     }
328                     else
329                     {
330                       start[1]=domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
331                       start[0]=domain->zoom_jbegin_srv-domain->global_zoom_jbegin;
332                       count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
333                     }
334
335                     if (domain->hasLonLat)
336                     {
337                       SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
338                       SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
339                     }
340                     break;
341                   }
342                   case CDomain::type_attr::rectilinear :
343                   {
344                     if (domain->hasLonLat)
345                     {
346                       std::vector<StdSize> start(1) ;
347                       std::vector<StdSize> count(1) ;
348                       if (domain->isEmpty())
349                       {
350                         start[0]=0 ;
351                         count[0]=0 ;
352                         SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
353                         SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
354
355                       }
356                       else
357                       {
358                         start[0]=domain->zoom_jbegin_srv-domain->global_zoom_jbegin;
359                         count[0]=domain->zoom_nj_srv ;
360                         CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;
361                         SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0,&start,&count);
362
363                         start[0]=domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
364                         count[0]=domain->zoom_ni_srv ;
365                         CArray<double,1> lon=domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;
366                         SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0,&start,&count);
367                       }
368                     }
369                     break;
370                   }
371                 }
372
373                 if (domain->hasBounds)
374                 {
375                   std::vector<StdSize> start(3);
376                   std::vector<StdSize> count(3);
377                   if (domain->isEmpty())
378                   {
379                     start[2] = start[1] = start[0] = 0;
380                     count[2] = count[1] = count[0] = 0;
381                   }
382                   else
383                   {
384                     start[2] = 0;
385                     start[1] = domain->zoom_ibegin_srv - domain->global_zoom_ibegin;
386                     start[0] = domain->zoom_jbegin_srv - domain->global_zoom_jbegin;
387                     count[2] = domain->nvertex;
388                     count[1] = domain->zoom_ni_srv;
389                     count[0] = domain->zoom_nj_srv;
390                   }
391
392                   SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0, &start, &count);
393                   SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0, &start, &count);
394                 }
395
396                 if (domain->hasArea)
397                 {
398                   std::vector<StdSize> start(2);
399                   std::vector<StdSize> count(2);
400
401                   if (domain->isEmpty())
402                   {
403                     start[0] = 0; start[1] = 0;
404                     count[0] = 0; count[1] = 0;
405                   }
406                   else
407                   {
408                     start[1] = domain->zoom_ibegin_srv - domain->global_zoom_ibegin;
409                     start[0] = domain->zoom_jbegin_srv - domain->global_zoom_jbegin;
410                     count[1] = domain->zoom_ni_srv;
411                     count[0] = domain->zoom_nj_srv;
412                   }
413
414                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0, &start, &count);
415                 }
416
417                 SuperClassWriter::definition_start();
418                 break;
419              }
420              default :
421                 ERROR("CNc4DataOutput::writeDomain(domain)",
422                       << "[ type = " << SuperClass::type << "]"
423                       << " not implemented yet !");
424           }
425         }
426         catch (CNetCdfException& e)
427         {
428           StdString msg("On writing the domain : ");
429           msg.append(domid); msg.append("\n");
430           msg.append("In the context : ");
431           msg.append(context->getId()); msg.append("\n");
432           msg.append(e.what());
433           ERROR("CNc4DataOutput::writeDomain_(CDomain* domain)", << msg);
434         }
435
436         domain->addRelFile(this->filename);
437      }
438
439      void CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)
440      {
441         CContext* context = CContext::getCurrent() ;
442         CContextServer* server=context->server ;
443
444         if (domain->IsWritten(this->filename)) return;
445         domain->checkAttributes();
446
447         if (domain->isEmpty())
448           if (SuperClass::type==MULTI_FILE) return ;
449
450         std::vector<StdString> dim0, dim1;
451         StdString domid     = (!domain->name.isEmpty())
452                             ? domain->name.getValue() : domain->getId();
453         if (isWrittenDomain(domid)) return ;
454         else writtenDomains.insert(domid) ; 
455
456         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
457
458
459         StdString dimXid = StdString("cell").append(appendDomid);
460         StdString dimVertId = StdString("nvertex").append(appendDomid);
461
462         string lonid,latid,bounds_lonid,bounds_latid ;
463         string areaId = "area" + appendDomid;
464
465         try
466         {
467           switch (SuperClass::type)
468           {
469              case (MULTI_FILE) :
470              {
471                 dim0.push_back(dimXid);
472                 SuperClassWriter::addDimension(dimXid, domain->zoom_ni_srv);
473
474                 lonid = StdString("lon").append(appendDomid);
475                 latid = StdString("lat").append(appendDomid);
476                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
477                 bounds_latid = StdString("bounds_lat").append(appendDomid);
478                 if (domain->hasLonLat)
479                 {
480                   SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
481                   SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
482                   this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid);
483                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
484                   this->writeAxisAttributes(latid, "", "latitude", "Latitude", "degrees_north", domid);
485                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
486                   if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
487                 }
488
489                 dim0.clear();
490                 if (domain->hasBounds)
491                 {
492                   dim0.push_back(dimXid);
493                   dim0.push_back(dimVertId);
494                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
495                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
496                 }
497
498                 dim0.clear();
499                 dim0.push_back(dimXid);
500                 if (domain->hasArea)
501                 {
502                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
503                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
504                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
505                 }
506
507                 SuperClassWriter::definition_end();
508
509                 if (domain->hasLonLat)
510                 {
511                   SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0);
512                   SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0);
513                   if (domain->hasBounds)
514                   {
515                     SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0);
516                     SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0);
517                   }
518                 }
519
520                 if (domain->hasArea)
521                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0);
522
523                 SuperClassWriter::definition_start();
524                 break ;
525              }
526
527              case (ONE_FILE) :
528              {
529                 lonid = StdString("lon").append(appendDomid);
530                 latid = StdString("lat").append(appendDomid);
531                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
532                 bounds_latid = StdString("bounds_lat").append(appendDomid);
533                 dim0.push_back(dimXid);
534                 SuperClassWriter::addDimension(dimXid, domain->ni_glo);
535                 if (domain->hasLonLat)
536                 {
537                   SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
538                   SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
539
540                   this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid);
541                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
542                   this->writeAxisAttributes(latid, "", "latitude", "Latitude", "degrees_north", domid);
543                   if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
544                   if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
545                 }
546                 dim0.clear();
547
548                 if (domain->hasBounds)
549                 {
550                   dim0.push_back(dimXid);
551                   dim0.push_back(dimVertId);
552                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
553                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
554                 }
555
556                 if (domain->hasArea)
557                 {
558                   dim0.clear();
559                   dim0.push_back(dimXid);
560                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
561                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
562                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
563                 }
564
565                 SuperClassWriter::definition_end();
566
567                 std::vector<StdSize> start(1), startBounds(2) ;
568                 std::vector<StdSize> count(1), countBounds(2) ;
569                 if (domain->isEmpty())
570                 {
571                   start[0]=0 ;
572                   count[0]=0 ;
573                   startBounds[1]=0 ;
574                   countBounds[1]=domain->nvertex ;
575                   startBounds[0]=0 ;
576                   countBounds[0]=0 ;
577                 }
578                 else
579                 {
580                   start[0]=domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
581                   count[0]=domain->zoom_ni_srv ;
582                   startBounds[0]=domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
583                   startBounds[1]=0 ;
584                   countBounds[0]=domain->zoom_ni_srv ;
585                   countBounds[1]=domain->nvertex ;
586                 }
587
588                 if (domain->hasLonLat)
589                 {
590                   SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
591                   SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
592                   if (domain->hasBounds)
593                   {
594                     SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0,&startBounds,&countBounds);
595                     SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0,&startBounds,&countBounds);
596                   }
597                 }
598
599                 if (domain->hasArea)
600                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0, &start, &count);
601
602                 SuperClassWriter::definition_start();
603
604                 break;
605              }
606              default :
607                 ERROR("CNc4DataOutput::writeDomain(domain)",
608                       << "[ type = " << SuperClass::type << "]"
609                       << " not implemented yet !");
610           }
611         }
612         catch (CNetCdfException& e)
613         {
614           StdString msg("On writing the domain : ");
615           msg.append(domid); msg.append("\n");
616           msg.append("In the context : ");
617           msg.append(context->getId()); msg.append("\n");
618           msg.append(e.what());
619           ERROR("CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)", << msg);
620         }
621         domain->addRelFile(this->filename);
622      }
623      //--------------------------------------------------------------
624
625      void CNc4DataOutput::writeAxis_(CAxis* axis)
626      {
627        if (axis->IsWritten(this->filename)) return;
628        axis->checkAttributes();
629        int zoom_size_srv  = axis->zoom_size_srv;
630        int zoom_begin_srv = axis->zoom_begin_srv;
631        int zoom_size  = (MULTI_FILE == SuperClass::type) ? zoom_size_srv
632                                                              : axis->global_zoom_size;
633        int zoom_begin = (MULTI_FILE == SuperClass::type) ? zoom_begin_srv
634                                                              : axis->global_zoom_begin;
635
636        if ((0 == zoom_size_srv) && (MULTI_FILE == SuperClass::type)) return;
637
638        std::vector<StdString> dims;
639        StdString axisid = !axis->name.isEmpty() ? axis->name.getValue() : axis->getId();
640        if (isWrittenAxis(axisid)) return ;
641        else writtenAxis.insert(axisid) ; 
642
643        try
644        {
645          SuperClassWriter::addDimension(axisid, zoom_size);
646          dims.push_back(axisid);
647          SuperClassWriter::addVariable(axisid, NC_FLOAT, dims);
648
649          if (!axis->name.isEmpty())
650            SuperClassWriter::addAttribute("name", axis->name.getValue(), &axisid);
651
652          if (!axis->standard_name.isEmpty())
653            SuperClassWriter::addAttribute("standard_name", axis->standard_name.getValue(), &axisid);
654
655          if (!axis->long_name.isEmpty())
656            SuperClassWriter::addAttribute("long_name", axis->long_name.getValue(), &axisid);
657
658          if (!axis->unit.isEmpty())
659            SuperClassWriter::addAttribute("units", axis->unit.getValue(), &axisid);
660
661          if (!axis->positive.isEmpty())
662          {
663            SuperClassWriter::addAttribute("axis", string("Z"), &axisid);
664            SuperClassWriter::addAttribute("positive",
665                                           (axis->positive == CAxis::positive_attr::up) ? string("up") : string("down"),
666                                           &axisid);
667          }
668
669          StdString axisBoundsId = axisid + "_bounds";
670          if (!axis->bounds.isEmpty())
671          {
672            dims.push_back("axis_nbounds");
673            SuperClassWriter::addVariable(axisBoundsId, NC_FLOAT, dims);
674            SuperClassWriter::addAttribute("bounds", axisBoundsId, &axisid);
675          }
676
677          SuperClassWriter::definition_end();
678          switch (SuperClass::type)
679          {
680            case MULTI_FILE:
681            {
682              CArray<double,1> axis_value(zoom_size_srv);
683              for (int i = 0; i < zoom_size_srv; i++) axis_value(i) = axis->value_srv(i);
684              SuperClassWriter::writeData(axis_value, axisid, isCollective, 0);
685
686              if (!axis->bounds.isEmpty())
687              {
688                CArray<double,2> axisBounds(2, zoom_size_srv);
689                for (int i = 0; i < zoom_size_srv; i++)
690                {
691                  axisBounds(0, i) = axis->bound_srv(i, 0);
692                  axisBounds(1, i) = axis->bound_srv(i, 1);
693                }
694                SuperClassWriter::writeData(axisBounds, axisBoundsId, isCollective, 0);
695              }
696
697              SuperClassWriter::definition_start();
698
699              break;
700            }
701            case ONE_FILE:
702            {
703              CArray<double,1> axis_value(zoom_size_srv);
704              axis_value = axis->value_srv;
705
706              std::vector<StdSize> start(1) ;
707              std::vector<StdSize> count(1) ;
708              start[0] = zoom_begin_srv-axis->global_zoom_begin;
709              count[0] = zoom_size_srv;
710              SuperClassWriter::writeData(axis_value, axisid, isCollective, 0, &start, &count);
711
712              if (!axis->bounds.isEmpty())
713              {
714                CArray<double,2> axisBounds(2, zoom_size_srv);
715                for (int i = 0; i < zoom_size_srv; ++i)
716                {
717                  axisBounds(0, i+zoom_begin_srv) = axis->bound_srv(i, 0);
718                  axisBounds(1, i+zoom_begin_srv) = axis->bound_srv(i, 1);
719                }
720                SuperClassWriter::writeData(axisBounds, axisBoundsId, isCollective, 0, &start, &count);
721              }
722
723              SuperClassWriter::definition_start();
724
725              break;
726            }
727            default :
728              ERROR("CNc4DataOutput::writeDomain(domain)",
729                    << "[ type = " << SuperClass::type << "]"
730                    << " not implemented yet !");
731          }
732        }
733        catch (CNetCdfException& e)
734        {
735          StdString msg("On writing the axis : ");
736          msg.append(axisid); msg.append("\n");
737          msg.append("In the context : ");
738          CContext* context = CContext::getCurrent() ;
739          msg.append(context->getId()); msg.append("\n");
740          msg.append(e.what());
741          ERROR("CNc4DataOutput::writeAxis_(CAxis* axis)", << msg);
742        }
743        axis->addRelFile(this->filename);
744     }
745
746     //--------------------------------------------------------------
747
748     void CNc4DataOutput::writeGridCompressed_(CGrid* grid)
749     {
750       if (grid->isScalarGrid() || grid->isWrittenCompressed(this->filename)) return;
751
752       try
753       {
754         CArray<bool,1> axisDomainOrder = grid->axis_domain_order;
755         std::vector<StdString> domainList = grid->getDomainList();
756         std::vector<StdString> axisList   = grid->getAxisList();
757         int numElement = axisDomainOrder.numElements(), idxDomain = 0, idxAxis = 0;
758
759         std::vector<StdString> dims;
760
761         if (grid->isCompressible())
762         {
763           StdString varId = grid->getId() + "_points";
764
765           int nbIndexes = (SuperClass::type == MULTI_FILE) ? grid->getNumberWrittenIndexes() : grid->getTotalNumberWrittenIndexes();
766           SuperClassWriter::addDimension(varId, nbIndexes);
767
768           dims.push_back(varId);
769           SuperClassWriter::addVariable(varId, NC_INT, dims);
770
771           StdOStringStream compress;
772           for (int i = numElement - 1; i >= 0; --i)
773           {
774             if (axisDomainOrder(i))
775             {
776               CDomain* domain = CDomain::get(domainList[domainList.size() - idxDomain - 1]);
777               StdString domId = !domain->name.isEmpty() ? domain->name.getValue() : domain->getId();
778               StdString appendDomId  = singleDomain ? "" : "_" + domId;
779
780               switch (domain->type)
781               {
782                 case CDomain::type_attr::curvilinear:
783                   compress << "y" << appendDomId << " x" << appendDomId;
784                   break;
785                 case CDomain::type_attr::rectilinear:
786                   compress << "lat" << appendDomId << " lon" << appendDomId;
787                   break;
788                 case CDomain::type_attr::unstructured:
789                   compress << "cell" << appendDomId;
790                   break;
791               }
792               ++idxDomain;
793             }
794             else
795             {
796               CAxis* axis = CAxis::get(axisList[axisList.size() - idxAxis - 1]);
797               compress << (!axis->name.isEmpty() ? axis->name.getValue() : axis->getId());
798               ++idxAxis;
799             }
800
801             if (i != 0) compress << ' ';
802           }
803           SuperClassWriter::addAttribute("compress", compress.str(), &varId);
804
805           grid->computeCompressedIndex();
806
807           CArray<int, 1> indexes(grid->getNumberWrittenIndexes());
808           std::map<int, CArray<size_t, 1> >::const_iterator it;
809           for (it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
810           {
811             const CArray<size_t, 1> compressedIndexes = grid->compressedOutIndexFromClient[it->first];
812             for (int i = 0; i < it->second.numElements(); i++)
813               indexes(compressedIndexes(i)) = it->second(i);
814           }
815
816           switch (SuperClass::type)
817           {
818             case (MULTI_FILE):
819             {
820               SuperClassWriter::writeData(indexes, varId, isCollective, 0);
821               break;
822             }
823             case (ONE_FILE):
824             {
825               if (grid->doGridHaveDataDistributed())
826                 grid->getDistributionServer()->computeGlobalIndex(indexes);
827
828               std::vector<StdSize> start, count;
829               start.push_back(grid->getOffsetWrittenIndexes());
830               count.push_back(grid->getNumberWrittenIndexes());
831
832               SuperClassWriter::writeData(indexes, varId, isCollective, 0, &start, &count);
833               break;
834             }
835           }
836         }
837         else
838         {
839           for (int i = 0; i < numElement; ++i)
840           {
841             StdString varId, compress;
842             CArray<int, 1> indexes;
843             bool isDistributed;
844             StdSize nbIndexes, totalNbIndexes, offset;
845             int firstGlobalIndex;
846
847             if (axisDomainOrder(i))
848             {
849               CDomain* domain = CDomain::get(domainList[idxDomain]);
850               if (!domain->isCompressible()
851                    || domain->type == CDomain::type_attr::unstructured
852                    || domain->isWrittenCompressed(this->filename))
853                 continue;
854
855               StdString domId = !domain->name.isEmpty() ? domain->name.getValue() : domain->getId();
856               StdString appendDomId  = singleDomain ? "" : "_" + domId;
857
858               varId = domId + "_points";
859               switch (domain->type)
860               {
861                 case CDomain::type_attr::curvilinear:
862                   compress = "y" + appendDomId + " x" + appendDomId;
863                   break;
864                 case CDomain::type_attr::rectilinear:
865                   compress = "lat" + appendDomId + " lon" + appendDomId;
866                   break;
867               }
868
869               const std::vector<int>& indexesToWrite = domain->getIndexesToWrite();
870               indexes.resize(indexesToWrite.size());
871               for (int n = 0; n < indexes.numElements(); ++n)
872                 indexes(n) = indexesToWrite[n];
873
874               isDistributed = domain->isDistributed();
875               nbIndexes = domain->getNumberWrittenIndexes();
876               totalNbIndexes = domain->getTotalNumberWrittenIndexes();
877               offset = domain->getOffsetWrittenIndexes();
878               firstGlobalIndex = domain->ibegin + domain->jbegin * domain->ni_glo;
879
880               domain->addRelFileCompressed(this->filename);
881               ++idxDomain;
882             }
883             else
884             {
885               CAxis* axis = CAxis::get(axisList[idxAxis]);
886               if (!axis->isCompressible() || axis->isWrittenCompressed(this->filename))
887                 continue;
888
889               StdString axisId = !axis->name.isEmpty() ? axis->name.getValue() : axis->getId();
890               varId = axisId + "_points";
891               compress = axisId;
892
893               const std::vector<int>& indexesToWrite = axis->getIndexesToWrite();
894               indexes.resize(indexesToWrite.size());
895               for (int n = 0; n < indexes.numElements(); ++n)
896                 indexes(n) = indexesToWrite[n];
897
898               isDistributed = axis->isDistributed();
899               nbIndexes = axis->getNumberWrittenIndexes();
900               totalNbIndexes = axis->getTotalNumberWrittenIndexes();
901               offset = axis->getOffsetWrittenIndexes();
902               firstGlobalIndex = axis->begin;
903
904               axis->addRelFileCompressed(this->filename);
905               ++idxAxis;
906             }
907
908             if (!varId.empty())
909             {
910               SuperClassWriter::addDimension(varId, (SuperClass::type == MULTI_FILE) ? nbIndexes : totalNbIndexes);
911
912               dims.clear();
913               dims.push_back(varId);
914               SuperClassWriter::addVariable(varId, NC_INT, dims);
915
916               SuperClassWriter::addAttribute("compress", compress, &varId);
917
918               switch (SuperClass::type)
919               {
920                 case (MULTI_FILE):
921                 {
922                   indexes -= firstGlobalIndex;
923                   SuperClassWriter::writeData(indexes, varId, isCollective, 0);
924                   break;
925                 }
926                 case (ONE_FILE):
927                 {
928                   std::vector<StdSize> start, count;
929                   start.push_back(offset);
930                   count.push_back(nbIndexes);
931
932                   SuperClassWriter::writeData(indexes, varId, isCollective, 0, &start, &count);
933                   break;
934                 }
935               }
936             }
937           }
938
939           if (!dims.empty())
940             grid->computeCompressedIndex();
941         }
942
943         grid->addRelFileCompressed(this->filename);
944       }
945       catch (CNetCdfException& e)
946       {
947         StdString msg("On writing compressed grid : ");
948         msg.append(grid->getId()); msg.append("\n");
949         msg.append("In the context : ");
950         CContext* context = CContext::getCurrent();
951         msg.append(context->getId()); msg.append("\n");
952         msg.append(e.what());
953         ERROR("CNc4DataOutput::writeGridCompressed_(CGrid* grid)", << msg);
954       }
955     }
956
957     //--------------------------------------------------------------
958
959     void CNc4DataOutput::writeTimeDimension_(void)
960     {
961       try
962       {
963        SuperClassWriter::addDimension("time_counter");
964       }
965       catch (CNetCdfException& e)
966       {
967         StdString msg("On writing time dimension : time_couter\n");
968         msg.append("In the context : ");
969         CContext* context = CContext::getCurrent() ;
970         msg.append(context->getId()); msg.append("\n");
971         msg.append(e.what());
972         ERROR("CNc4DataOutput::writeTimeDimension_(void)", << msg);
973       }
974     }
975
976      //--------------------------------------------------------------
977
978      void CNc4DataOutput::writeField_(CField* field)
979      {
980         CContext* context = CContext::getCurrent() ;
981         CContextServer* server=context->server ;
982
983         std::vector<StdString> dims, coodinates;
984         CGrid* grid = field->grid;
985         if (!grid->doGridHaveDataToWrite())
986          if (SuperClass::type==MULTI_FILE) return ;
987
988         CArray<bool,1> axisDomainOrder = grid->axis_domain_order;
989         int numElement = axisDomainOrder.numElements(), idxDomain = 0, idxAxis = 0;
990         std::vector<StdString> domainList = grid->getDomainList();
991         std::vector<StdString> axisList   = grid->getAxisList();
992
993         StdString timeid  = StdString("time_counter");
994         StdString dimXid,dimYid;
995         std::deque<StdString> dimIdList, dimCoordList;
996         bool hasArea = false;
997         StdString cellMeasures = "area:";
998         bool compressedOutput = !field->indexed_output.isEmpty() && field->indexed_output;
999
1000         for (int i = 0; i < numElement; ++i)
1001         {
1002           if (axisDomainOrder(i))
1003           {
1004             CDomain* domain = CDomain::get(domainList[idxDomain]);
1005             StdString domId = !domain->name.isEmpty() ? domain->name.getValue() : domain->getId();
1006             StdString appendDomId  = singleDomain ? "" : "_" + domId ;
1007
1008             if (compressedOutput && domain->isCompressible() && domain->type != CDomain::type_attr::unstructured)
1009             {
1010               dimIdList.push_back(domId + "_points");
1011               field->setUseCompressedOutput();
1012             }
1013
1014             switch (domain->type)
1015             {
1016               case CDomain::type_attr::curvilinear:
1017                 if (!compressedOutput || !domain->isCompressible())
1018                 {
1019                   dimXid     = StdString("x").append(appendDomId);
1020                   dimIdList.push_back(dimXid);
1021                   dimYid     = StdString("y").append(appendDomId);
1022                   dimIdList.push_back(dimYid);
1023                 }
1024                 dimCoordList.push_back(StdString("nav_lon").append(appendDomId));
1025                 dimCoordList.push_back(StdString("nav_lat").append(appendDomId));
1026                 break ;
1027               case CDomain::type_attr::rectilinear:
1028                 if (!compressedOutput || !domain->isCompressible())
1029                 {
1030                   dimXid     = StdString("lon").append(appendDomId);
1031                   dimIdList.push_back(dimXid);
1032                   dimYid     = StdString("lat").append(appendDomId);
1033                   dimIdList.push_back(dimYid);
1034                 }
1035                 break ;
1036               case CDomain::type_attr::unstructured:
1037                 dimXid     = StdString("cell").append(appendDomId);
1038                 dimIdList.push_back(dimXid);
1039                 dimCoordList.push_back(StdString("lon").append(appendDomId));
1040                 dimCoordList.push_back(StdString("lat").append(appendDomId));
1041                 break ;
1042             }
1043             if (domain->hasArea)
1044             {
1045               hasArea = true;
1046               cellMeasures += " area" + appendDomId;
1047             }
1048             ++idxDomain;
1049           }
1050           else
1051           {
1052             CAxis* axis = CAxis::get(axisList[idxAxis]);
1053             StdString axisId = !axis->name.isEmpty() ? axis->name.getValue() : axis->getId();
1054
1055             if (compressedOutput && axis->isCompressible())
1056             {
1057               dimIdList.push_back(axisId + "_points");
1058               field->setUseCompressedOutput();
1059             }
1060             else
1061               dimIdList.push_back(axisId);
1062
1063             dimCoordList.push_back(axisId);
1064             ++idxAxis;
1065           }
1066         }
1067
1068/*
1069         StdString lonid_loc = (server->intraCommSize > 1)
1070                             ? StdString("lon").append(appendDomid).append("_local")
1071                             : lonid;
1072         StdString latid_loc = (server->intraCommSize > 1)
1073                             ? StdString("lat").append(appendDomid).append("_local")
1074                             : latid;
1075*/
1076         StdString fieldid   = (!field->name.isEmpty())
1077                             ? field->name.getValue() : field->getBaseFieldReference()->getId();
1078
1079//         unsigned int ssize = domain->zoom_ni_loc.getValue() * domain->zoom_nj_loc.getValue();
1080//         bool isCurvilinear = (domain->lonvalue.getValue()->size() == ssize);
1081//          bool isCurvilinear = domain->isCurvilinear ;
1082
1083         nc_type type ;
1084         if (field->prec.isEmpty()) type =  NC_FLOAT ;
1085         else
1086         {
1087           if (field->prec==2) type = NC_SHORT ;
1088           else if (field->prec==4)  type =  NC_FLOAT ;
1089           else if (field->prec==8)   type =  NC_DOUBLE ;
1090         }
1091
1092         bool wtime   = !(!field->operation.isEmpty() && field->getOperationTimeType() == func::CFunctor::once);
1093
1094         if (wtime)
1095         {
1096
1097            //StdOStringStream oss;
1098           // oss << "time_" << field->operation.getValue()
1099           //     << "_" << field->getRelFile()->output_freq.getValue();
1100          //oss
1101            if (field->getOperationTimeType() == func::CFunctor::instant) coodinates.push_back(string("time_instant"));
1102            else if (field->getOperationTimeType() == func::CFunctor::centered) coodinates.push_back(string("time_centered"));
1103            dims.push_back(timeid);
1104         }
1105
1106         if (compressedOutput && grid->isCompressible())
1107         {
1108           dims.push_back(grid->getId() + "_points");
1109           field->setUseCompressedOutput();
1110         }
1111         else
1112         {
1113           while (!dimIdList.empty())
1114           {
1115             dims.push_back(dimIdList.back());
1116             dimIdList.pop_back();
1117           }
1118         }
1119
1120         while (!dimCoordList.empty())
1121         {
1122           coodinates.push_back(dimCoordList.back());
1123           dimCoordList.pop_back();
1124         }
1125
1126         try
1127         {
1128           SuperClassWriter::addVariable(fieldid, type, dims);
1129
1130           if (!field->standard_name.isEmpty())
1131              SuperClassWriter::addAttribute
1132                 ("standard_name",  field->standard_name.getValue(), &fieldid);
1133
1134           if (!field->long_name.isEmpty())
1135              SuperClassWriter::addAttribute
1136                 ("long_name", field->long_name.getValue(), &fieldid);
1137
1138           if (!field->unit.isEmpty())
1139              SuperClassWriter::addAttribute
1140                 ("units", field->unit.getValue(), &fieldid);
1141
1142            if (!field->valid_min.isEmpty())
1143              SuperClassWriter::addAttribute
1144                 ("valid_min", field->valid_min.getValue(), &fieldid);
1145
1146           if (!field->valid_max.isEmpty())
1147              SuperClassWriter::addAttribute
1148                 ("valid_max", field->valid_max.getValue(), &fieldid);
1149
1150            if (!field->scale_factor.isEmpty())
1151              SuperClassWriter::addAttribute
1152                 ("scale_factor", field->scale_factor.getValue(), &fieldid);
1153
1154             if (!field->add_offset.isEmpty())
1155              SuperClassWriter::addAttribute
1156                 ("add_offset", field->add_offset.getValue(), &fieldid);
1157
1158           SuperClassWriter::addAttribute
1159                 ("online_operation", field->operation.getValue(), &fieldid);
1160
1161          // write child variables as attributes
1162
1163
1164           vector<CVariable*> listVars = field->getAllVariables() ;
1165           for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ;
1166
1167
1168           if (wtime)
1169           {
1170              CDuration freqOp = field->freq_op.getValue();
1171              freqOp.solveTimeStep(*context->calendar);
1172              StdString freqOpStr = freqOp.toStringUDUnits();
1173              SuperClassWriter::addAttribute("interval_operation", freqOpStr, &fieldid);
1174
1175              CDuration freqOut = field->getRelFile()->output_freq.getValue();
1176              freqOut.solveTimeStep(*context->calendar);
1177              SuperClassWriter::addAttribute("interval_write", freqOut.toStringUDUnits(), &fieldid);
1178
1179              StdString cellMethods = "time: ";
1180              if (field->operation.getValue() == "instant") cellMethods += "point";
1181              else if (field->operation.getValue() == "average") cellMethods += "mean";
1182              else if (field->operation.getValue() == "accumulate") cellMethods += "sum";
1183              else cellMethods += field->operation;
1184              if (freqOp.resolve(*context->calendar) != freqOut.resolve(*context->calendar))
1185                cellMethods += " (interval: " + freqOpStr + ")";
1186              SuperClassWriter::addAttribute("cell_methods", cellMethods, &fieldid);
1187           }
1188
1189           if (hasArea)
1190             SuperClassWriter::addAttribute("cell_measures", cellMeasures, &fieldid);
1191
1192           if (!field->default_value.isEmpty())
1193           {
1194              double default_value = field->default_value.getValue();
1195              float fdefault_value = (float)default_value;
1196              if (type == NC_DOUBLE)
1197                 SuperClassWriter::setDefaultValue(fieldid, &default_value);
1198              else
1199                 SuperClassWriter::setDefaultValue(fieldid, &fdefault_value);
1200           }
1201           else
1202              SuperClassWriter::setDefaultValue(fieldid, (double*)NULL);
1203
1204            if (field->compression_level.isEmpty())
1205              field->compression_level = field->file->compression_level.isEmpty() ? 0 : field->file->compression_level;
1206            SuperClassWriter::setCompressionLevel(fieldid, field->compression_level);
1207
1208           {  // Ecriture des coordonnées
1209
1210              StdString coordstr; //boost::algorithm::join(coodinates, " ")
1211              std::vector<StdString>::iterator
1212                 itc = coodinates.begin(), endc = coodinates.end();
1213
1214              for (; itc!= endc; itc++)
1215              {
1216                 StdString & coord = *itc;
1217                 if (itc+1 != endc)
1218                       coordstr.append(coord).append(" ");
1219                 else  coordstr.append(coord);
1220              }
1221
1222              SuperClassWriter::addAttribute("coordinates", coordstr, &fieldid);
1223
1224           }
1225         }
1226         catch (CNetCdfException& e)
1227         {
1228           StdString msg("On writing field : ");
1229           msg.append(fieldid); msg.append("\n");
1230           msg.append("In the context : ");
1231           msg.append(context->getId()); msg.append("\n");
1232           msg.append(e.what());
1233           ERROR("CNc4DataOutput::writeField_(CField* field)", << msg);
1234         }
1235      }
1236
1237      //--------------------------------------------------------------
1238
1239      void CNc4DataOutput::writeFile_ (CFile* file)
1240      {
1241         StdString filename = (!file->name.isEmpty())
1242                            ? file->name.getValue() : file->getId();
1243         StdString description = (!file->description.isEmpty())
1244                               ? file->description.getValue()
1245                               : StdString("Created by xios");
1246
1247         singleDomain = (file->nbDomains == 1);
1248
1249         try
1250         {
1251           this->writeFileAttributes(filename, description,
1252                                     StdString("CF-1.5"),
1253                                     StdString("An IPSL model"),
1254                                     this->getTimeStamp());
1255
1256           if (!appendMode)
1257             SuperClassWriter::addDimension("axis_nbounds", 2);
1258         }
1259         catch (CNetCdfException& e)
1260         {
1261           StdString msg("On writing file : ");
1262           msg.append(filename); msg.append("\n");
1263           msg.append("In the context : ");
1264           CContext* context = CContext::getCurrent() ;
1265           msg.append(context->getId()); msg.append("\n");
1266           msg.append(e.what());
1267           ERROR("CNc4DataOutput::writeFile_ (CFile* file)", << msg);
1268         }
1269      }
1270
1271      void CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)
1272      {
1273        string name ;
1274        if (!var->name.isEmpty()) name=var->name ;
1275        else if (var->hasId()) name=var->getId() ;
1276        else return ;
1277
1278        try
1279        {
1280          if (var->type.getValue() == CVariable::type_attr::t_int || var->type.getValue() == CVariable::type_attr::t_int32)
1281            addAttribute(name, var->getData<int>(), &fieldId);
1282          else if (var->type.getValue() == CVariable::type_attr::t_int16)
1283            addAttribute(name, var->getData<short int>(), &fieldId);
1284          else if (var->type.getValue() == CVariable::type_attr::t_float)
1285            addAttribute(name, var->getData<float>(), &fieldId);
1286          else if (var->type.getValue() == CVariable::type_attr::t_double)
1287            addAttribute(name, var->getData<double>(), &fieldId);
1288          else if (var->type.getValue() == CVariable::type_attr::t_string)
1289            addAttribute(name, var->getData<string>(), &fieldId);
1290          else
1291            ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)",
1292                  << "Unsupported variable of type " << var->type.getStringValue());
1293        }
1294       catch (CNetCdfException& e)
1295       {
1296         StdString msg("On writing attributes of variable with name : ");
1297         msg.append(name); msg.append("in the field "); msg.append(fieldId); msg.append("\n");
1298         msg.append("In the context : ");
1299         CContext* context = CContext::getCurrent() ;
1300         msg.append(context->getId()); msg.append("\n");
1301         msg.append(e.what());
1302         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)", << msg);
1303       }
1304     }
1305
1306     void CNc4DataOutput::writeAttribute_ (CVariable* var)
1307     {
1308        string name ;
1309        if (!var->name.isEmpty()) name=var->name ;
1310        else if (var->hasId()) name=var->getId() ;
1311        else return ;
1312        try
1313        {
1314          if (var->type.getValue() == CVariable::type_attr::t_int || var->type.getValue() == CVariable::type_attr::t_int32)
1315            addAttribute(name, var->getData<int>());
1316          else if (var->type.getValue() == CVariable::type_attr::t_int16)
1317            addAttribute(name, var->getData<short int>());
1318          else if (var->type.getValue() == CVariable::type_attr::t_float)
1319            addAttribute(name, var->getData<float>());
1320          else if (var->type.getValue() == CVariable::type_attr::t_double)
1321            addAttribute(name, var->getData<double>());
1322          else if (var->type.getValue() == CVariable::type_attr::t_string)
1323            addAttribute(name, var->getData<string>());
1324          else
1325            ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)",
1326                  << "Unsupported variable of type " << var->type.getStringValue());
1327        }
1328       catch (CNetCdfException& e)
1329       {
1330         StdString msg("On writing attributes of variable with name : ");
1331         msg.append(name); msg.append("\n");
1332         msg.append("In the context : ");
1333         CContext* context = CContext::getCurrent() ;
1334         msg.append(context->getId()); msg.append("\n");
1335         msg.append(e.what());
1336         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)", << msg);
1337       }
1338     }
1339
1340      void CNc4DataOutput::syncFile_ (void)
1341      {
1342        try
1343        {
1344          SuperClassWriter::sync() ;
1345        }
1346        catch (CNetCdfException& e)
1347        {
1348         StdString msg("On synchronizing the write among processes");
1349         msg.append("In the context : ");
1350         CContext* context = CContext::getCurrent() ;
1351         msg.append(context->getId()); msg.append("\n");
1352         msg.append(e.what());
1353         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
1354        }
1355      }
1356
1357      void CNc4DataOutput::closeFile_ (void)
1358      {
1359        try
1360        {
1361          SuperClassWriter::close() ;
1362        }
1363        catch (CNetCdfException& e)
1364        {
1365         StdString msg("On closing file");
1366         msg.append("In the context : ");
1367         CContext* context = CContext::getCurrent() ;
1368         msg.append(context->getId()); msg.append("\n");
1369         msg.append(e.what());
1370         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
1371        }
1372
1373      }
1374
1375      //---------------------------------------------------------------
1376
1377      StdString CNc4DataOutput::getTimeStamp(void) const
1378      {
1379         const int buffer_size = 100;
1380         time_t rawtime;
1381         struct tm * timeinfo = NULL;
1382         char buffer [buffer_size];
1383
1384         time ( &rawtime );
1385         timeinfo = localtime ( &rawtime );
1386         strftime (buffer, buffer_size, "%Y-%b-%d %H:%M:%S %Z", timeinfo);
1387
1388         return (StdString(buffer));
1389      }
1390
1391      //---------------------------------------------------------------
1392
1393      void CNc4DataOutput::writeFieldData_ (CField*  field)
1394      {
1395         CContext* context = CContext::getCurrent() ;
1396//          if (field->getRelFile()->isSyncTime()) SuperClassWriter::sync() ;
1397         CContextServer* server=context->server ;
1398
1399         CGrid* grid = field->grid ;
1400
1401         if (!grid->doGridHaveDataToWrite())
1402          if (SuperClass::type==MULTI_FILE || !isCollective) return ;
1403
1404         StdString fieldid   = (!field->name.isEmpty())
1405                             ? field->name.getValue()
1406                             : field->getBaseFieldReference()->getId();
1407
1408         StdOStringStream oss;
1409         string timeAxisId ;
1410         if (field->getOperationTimeType() == func::CFunctor::instant)  timeAxisId="time_instant" ;
1411         else if (field->getOperationTimeType() == func::CFunctor::centered)  timeAxisId="time_centered" ;
1412
1413         StdString timeBoundId("time_counter_bounds");
1414
1415         StdString timeAxisBoundId;
1416         if (field->getOperationTimeType() == func::CFunctor::instant)  timeAxisBoundId="time_instant_bounds" ;
1417         else if (field->getOperationTimeType() == func::CFunctor::centered)  timeAxisBoundId="time_centered_bounds" ;
1418
1419         CArray<double,1> time_data(1) ;
1420         CArray<double,1> time_data_bound(2);
1421         CArray<double,1> time_counter(1) ;
1422         CArray<double,1> time_counter_bound(2);
1423
1424        bool wtime   = !(!field->operation.isEmpty() && (field->getOperationTimeType() == func::CFunctor::once));
1425
1426        if (wtime)
1427        {
1428          Time lastWrite = field->last_Write_srv;
1429          Time lastLastWrite = field->lastlast_Write_srv;
1430
1431          if (field->getOperationTimeType() == func::CFunctor::instant)
1432            time_data(0) = lastWrite;
1433          else if (field->getOperationTimeType() == func::CFunctor::centered)
1434            time_data(0) = (lastWrite + lastLastWrite) / 2;
1435
1436          if (field->getOperationTimeType() == func::CFunctor::instant)
1437            time_data_bound(0) = time_data_bound(1) = lastWrite;
1438          else if (field->getOperationTimeType() == func::CFunctor::centered)
1439          {
1440            time_data_bound(0) = lastLastWrite;
1441            time_data_bound(1) = lastWrite;
1442          }
1443
1444          if (field->file->time_counter == CFile::time_counter_attr::instant)
1445            time_counter(0) = lastWrite;
1446          else if (field->file->time_counter == CFile::time_counter_attr::centered)
1447            time_counter(0) = (lastWrite + lastLastWrite) / 2;
1448          else if (field->file->time_counter == CFile::time_counter_attr::record)
1449            time_counter(0) = field->getNStep() - 1;
1450
1451
1452          if (field->file->time_counter == CFile::time_counter_attr::instant)
1453            time_counter_bound(0) = time_counter_bound(1) = lastWrite;
1454          else if (field->file->time_counter == CFile::time_counter_attr::centered)
1455          {
1456            time_counter_bound(0) = lastLastWrite;
1457            time_counter_bound(1) = lastWrite;
1458          }
1459          else if (field->file->time_counter == CFile::time_counter_attr::record)
1460            time_counter_bound(0) = time_counter_bound(1) = field->getNStep() - 1;
1461        }
1462
1463         bool isRoot ;
1464         if (server->intraCommRank==0) isRoot=true ;
1465         else isRoot=false ;
1466
1467         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
1468         {
1469           double scaleFactor=1. ;
1470           double addOffset=0. ;
1471           if (!field->scale_factor.isEmpty()) scaleFactor=field->scale_factor ;
1472           if (!field->add_offset.isEmpty()) addOffset=field->add_offset ;
1473           field->scaleFactorAddOffset(scaleFactor,addOffset) ;
1474         }
1475
1476         try
1477         {
1478           size_t writtenSize;
1479           if (field->getUseCompressedOutput())
1480             writtenSize = grid->getNumberWrittenIndexes();
1481           else
1482             writtenSize = grid->getWrittenDataSize();
1483
1484           CArray<double,1> fieldData(writtenSize);
1485           if (!field->default_value.isEmpty()) fieldData = field->default_value;
1486
1487           if (field->getUseCompressedOutput())
1488             field->outputCompressedField(fieldData);
1489           else
1490             field->outputField(fieldData);
1491
1492           if (!field->prec.isEmpty() && field->prec==2) fieldData=round(fieldData) ;
1493
1494           switch (SuperClass::type)
1495           {
1496              case (MULTI_FILE) :
1497              {
1498                 SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep() - 1);
1499                 if (wtime)
1500                 {
1501                   SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep() - 1);
1502                   SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1);
1503                   if (field->file->time_counter != CFile::time_counter_attr::none)
1504                   {
1505                     SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep() - 1);
1506                     if (field->file->time_counter != CFile::time_counter_attr::record)
1507                       SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1);
1508                   }
1509                 }
1510                 break ;
1511              }
1512              case (ONE_FILE) :
1513              {
1514                const std::vector<int>& nZoomBeginGlobal = grid->getDistributionServer()->getZoomBeginGlobal();
1515                const std::vector<int>& nZoomBeginServer = grid->getDistributionServer()->getZoomBeginServer();
1516                const std::vector<int>& nZoomSizeServer  = grid->getDistributionServer()->getZoomSizeServer();
1517
1518                std::vector<StdSize> start, count;
1519
1520                if (field->getUseCompressedOutput())
1521                {
1522                  if (grid->isCompressible())
1523                  {
1524                    start.push_back(grid->getOffsetWrittenIndexes());
1525                    count.push_back(grid->getNumberWrittenIndexes());
1526                  }
1527                  else
1528                  {
1529                    CArray<bool,1> axisDomainOrder = grid->axis_domain_order;
1530                    std::vector<StdString> domainList = grid->getDomainList();
1531                    std::vector<StdString> axisList   = grid->getAxisList();
1532                    int numElement = axisDomainOrder.numElements();
1533                    int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
1534                    int idx = nZoomBeginGlobal.size() - 1;
1535
1536                    start.reserve(nZoomBeginGlobal.size());
1537                    count.reserve(nZoomBeginGlobal.size());
1538
1539
1540                    for (int i = numElement - 1; i >= 0; --i)
1541                    {
1542                      if (axisDomainOrder(i))
1543                      {
1544                        CDomain* domain = CDomain::get(domainList[idxDomain]);
1545
1546                        if (domain->isCompressible())
1547                        {
1548                          start.push_back(domain->getOffsetWrittenIndexes());
1549                          count.push_back(domain->getNumberWrittenIndexes());
1550                        }
1551                        else
1552                        {
1553                          start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1554                          count.push_back(nZoomSizeServer[idx]);
1555                          start.push_back(nZoomBeginServer[idx - 1] - nZoomBeginGlobal[idx - 1]);
1556                          count.push_back(nZoomSizeServer[idx - 1]);
1557                        }
1558
1559                        --idxDomain;
1560                        idx -= 2;
1561                      }
1562                      else
1563                      {
1564                        CAxis* axis = CAxis::get(axisList[idxAxis]);
1565
1566                        if (axis->isCompressible())
1567                        {
1568                          start.push_back(axis->getOffsetWrittenIndexes());
1569                          count.push_back(axis->getNumberWrittenIndexes());
1570                        }
1571                        else
1572                        {
1573                          start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1574                          count.push_back(nZoomSizeServer[idx]);
1575                        }
1576
1577                        --idxAxis;
1578                        --idx;
1579                      }
1580                    }
1581                  }
1582                }
1583                else
1584                {
1585
1586                  CArray<bool,1> axisDomainOrder = grid->axis_domain_order;
1587                  std::vector<StdString> domainList = grid->getDomainList();
1588                  std::vector<StdString> axisList   = grid->getAxisList();
1589                  int numElement = axisDomainOrder.numElements();
1590                  int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
1591                  int idx = nZoomBeginGlobal.size() - 1;
1592
1593                  start.reserve(nZoomBeginGlobal.size());
1594                  count.reserve(nZoomBeginGlobal.size());
1595
1596                  for (int i = numElement - 1; i >= 0; --i)
1597                  {
1598                    if (axisDomainOrder(i))
1599                    {
1600                      CDomain* domain = CDomain::get(domainList[idxDomain]);
1601                      if (domain->type != CDomain::type_attr::unstructured)
1602                      {
1603                        start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1604                        count.push_back(nZoomSizeServer[idx]);
1605                      }
1606                      --idx ;
1607                      start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1608                      count.push_back(nZoomSizeServer[idx]);
1609                      --idx ;
1610                      --idxDomain;
1611                    }
1612                    else
1613                    {
1614                      start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1615                      count.push_back(nZoomSizeServer[idx]);
1616                      --idx;
1617                     }
1618                  }
1619/*
1620                  int ssize = nZoomBeginGlobal.size();
1621                  for (int i = numElement - 1; i >= 0; --i)
1622
1623
1624                  start.resize(ssize);
1625                  count.resize(ssize);
1626
1627                  for (int i = 0; i < ssize; ++i)
1628                  {
1629                    start[i] = nZoomBeginServer[ssize - i - 1] - nZoomBeginGlobal[ssize - i - 1];
1630                    count[i] = nZoomSizeServer[ssize - i - 1];
1631                  }
1632*/
1633                }
1634
1635                SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep() - 1, &start, &count);
1636                if (wtime)
1637                {
1638                   SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep() - 1, isRoot);
1639                   SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1, isRoot);
1640                   if (field->file->time_counter != CFile::time_counter_attr::none)
1641                   {
1642                     SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep() - 1, isRoot);
1643                     if (field->file->time_counter != CFile::time_counter_attr::record)
1644                       SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1, isRoot);
1645                   }
1646                }
1647
1648                break;
1649              }
1650            }
1651         }
1652         catch (CNetCdfException& e)
1653         {
1654           StdString msg("On writing field data: ");
1655           msg.append(fieldid); msg.append("\n");
1656           msg.append("In the context : ");
1657           msg.append(context->getId()); msg.append("\n");
1658           msg.append(e.what());
1659           ERROR("CNc4DataOutput::writeFieldData_ (CField*  field)", << msg);
1660         }
1661      }
1662
1663      //---------------------------------------------------------------
1664
1665      void CNc4DataOutput::writeTimeAxis_
1666                  (CField*    field,
1667                   const boost::shared_ptr<CCalendar> cal)
1668      {
1669         StdOStringStream oss;
1670
1671         if (field->getOperationTimeType() == func::CFunctor::once) return ;
1672
1673//         oss << "time_" << field->operation.getValue()
1674//             << "_" << field->getRelFile()->output_freq.getValue();
1675
1676//         StdString axisid = oss.str();
1677//         if (field->getOperationTimeType() == func::CFunctor::centered) axisid="time_centered" ;
1678//         else if (field->getOperationTimeType() == func::CFunctor::instant) axisid="time_instant" ;
1679
1680         StdString axisid("time_centered") ;
1681         StdString axisBoundId("time_centered_bounds");
1682         StdString timeid("time_counter");
1683         StdString timeBoundId("axis_nbounds");
1684
1685         if (field->getOperationTimeType() == func::CFunctor::instant)
1686         {
1687            axisid = "time_instant";
1688            axisBoundId = "time_instant_bounds";
1689         }
1690
1691         try
1692         {
1693          // Adding time_instant or time_centered
1694           std::vector<StdString> dims;
1695           dims.push_back(timeid);
1696           if (!SuperClassWriter::varExist(axisid))
1697           {
1698              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1699
1700              CDate timeOrigin=cal->getTimeOrigin() ;
1701              StdOStringStream oss2;
1702  //            oss2<<initDate.getYear()<<"-"<<initDate.getMonth()<<"-"<<initDate.getDay()<<" "
1703  //                <<initDate.getHour()<<"-"<<initDate.getMinute()<<"-"<<initDate.getSecond() ;
1704              StdString strInitdate=oss2.str() ;
1705              StdString strTimeOrigin=timeOrigin.toString() ;
1706              this->writeTimeAxisAttributes
1707                 (axisid, cal->getType(),
1708                  StdString("seconds since ").append(strTimeOrigin),
1709                  strTimeOrigin, axisBoundId);
1710           }
1711
1712           // Adding time_instant_bounds or time_centered_bounds variables
1713           if (!SuperClassWriter::varExist(axisBoundId))
1714           {
1715              dims.clear() ;
1716              dims.push_back(timeid);
1717              dims.push_back(timeBoundId);
1718              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1719           }
1720
1721           if (field->file->time_counter != CFile::time_counter_attr::none)
1722           {
1723             // Adding time_counter
1724             axisid = "time_counter";
1725             axisBoundId = "time_counter_bounds";
1726             dims.clear();
1727             dims.push_back(timeid);
1728             if (!SuperClassWriter::varExist(axisid))
1729             {
1730                SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1731                SuperClassWriter::addAttribute("axis", string("T"), &axisid);
1732
1733                if (field->file->time_counter != CFile::time_counter_attr::record)
1734                {
1735                  CDate timeOrigin = cal->getTimeOrigin();
1736                  StdString strTimeOrigin = timeOrigin.toString();
1737
1738                  this->writeTimeAxisAttributes(axisid, cal->getType(),
1739                                                StdString("seconds since ").append(strTimeOrigin),
1740                                                strTimeOrigin, axisBoundId);
1741                }
1742             }
1743
1744             // Adding time_counter_bound dimension
1745             if (field->file->time_counter != CFile::time_counter_attr::record)
1746             {
1747                if (!SuperClassWriter::varExist(axisBoundId))
1748                {
1749                  dims.clear();
1750                  dims.push_back(timeid);
1751                  dims.push_back(timeBoundId);
1752                  SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1753                }
1754             }
1755           }
1756         }
1757         catch (CNetCdfException& e)
1758         {
1759           StdString msg("On writing time axis data: ");
1760           msg.append("In the context : ");
1761           CContext* context = CContext::getCurrent() ;
1762           msg.append(context->getId()); msg.append("\n");
1763           msg.append(e.what());
1764           ERROR("CNc4DataOutput::writeTimeAxis_ (CField*    field, \
1765                  const boost::shared_ptr<CCalendar> cal)", << msg);
1766         }
1767      }
1768
1769      //---------------------------------------------------------------
1770
1771      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
1772                                                   const StdString & calendar,
1773                                                   const StdString & units,
1774                                                   const StdString & time_origin,
1775                                                   const StdString & time_bounds,
1776                                                   const StdString & standard_name,
1777                                                   const StdString & long_name)
1778      {
1779         try
1780         {
1781           SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1782           SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
1783           SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
1784           SuperClassWriter::addAttribute("units",         units        , &axis_name);
1785           SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
1786           SuperClassWriter::addAttribute("bounds",        time_bounds  , &axis_name);
1787         }
1788         catch (CNetCdfException& e)
1789         {
1790           StdString msg("On writing time axis Attribute: ");
1791           msg.append("In the context : ");
1792           CContext* context = CContext::getCurrent() ;
1793           msg.append(context->getId()); msg.append("\n");
1794           msg.append(e.what());
1795           ERROR("CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name, \
1796                                                          const StdString & calendar,\
1797                                                          const StdString & units, \
1798                                                          const StdString & time_origin, \
1799                                                          const StdString & time_bounds, \
1800                                                          const StdString & standard_name, \
1801                                                          const StdString & long_name)", << msg);
1802         }
1803      }
1804
1805      //---------------------------------------------------------------
1806
1807      void CNc4DataOutput::writeAxisAttributes(const StdString & axis_name,
1808                                               const StdString & axis,
1809                                               const StdString & standard_name,
1810                                               const StdString & long_name,
1811                                               const StdString & units,
1812                                               const StdString & nav_model)
1813      {
1814         try
1815         {
1816          if (!axis.empty())
1817            SuperClassWriter::addAttribute("axis"       , axis         , &axis_name);
1818
1819          SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1820          SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
1821          SuperClassWriter::addAttribute("units"        , units        , &axis_name);
1822          SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
1823         }
1824         catch (CNetCdfException& e)
1825         {
1826           StdString msg("On writing Axis Attribute: ");
1827           msg.append("In the context : ");
1828           CContext* context = CContext::getCurrent() ;
1829           msg.append(context->getId()); msg.append("\n");
1830           msg.append(e.what());
1831           ERROR("CNc4DataOutput::writeAxisAttributes(const StdString & axis_name, \
1832                                                      const StdString & axis, \
1833                                                      const StdString & standard_name, \
1834                                                      const StdString & long_name, \
1835                                                      const StdString & units, \
1836                                                      const StdString & nav_model)", << msg);
1837         }
1838      }
1839
1840      //---------------------------------------------------------------
1841
1842      void CNc4DataOutput::writeLocalAttributes
1843         (int ibegin, int ni, int jbegin, int nj, StdString domid)
1844      {
1845        try
1846        {
1847         SuperClassWriter::addAttribute(StdString("ibegin").append(domid), ibegin);
1848         SuperClassWriter::addAttribute(StdString("ni"    ).append(domid), ni);
1849         SuperClassWriter::addAttribute(StdString("jbegin").append(domid), jbegin);
1850         SuperClassWriter::addAttribute(StdString("nj"    ).append(domid), nj);
1851        }
1852        catch (CNetCdfException& e)
1853        {
1854           StdString msg("On writing Local Attributes: ");
1855           msg.append("In the context : ");
1856           CContext* context = CContext::getCurrent() ;
1857           msg.append(context->getId()); msg.append("\n");
1858           msg.append(e.what());
1859           ERROR("CNc4DataOutput::writeLocalAttributes \
1860                  (int ibegin, int ni, int jbegin, int nj, StdString domid)", << msg);
1861        }
1862
1863      }
1864
1865      void CNc4DataOutput::writeLocalAttributes_IOIPSL(const StdString& dimXid, const StdString& dimYid,
1866                                                       int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)
1867      {
1868         CArray<int,1> array(2) ;
1869
1870         try
1871         {
1872           SuperClassWriter::addAttribute("DOMAIN_number_total",size ) ;
1873           SuperClassWriter::addAttribute("DOMAIN_number", rank) ;
1874           array = SuperClassWriter::getDimension(dimXid) + 1, SuperClassWriter::getDimension(dimYid) + 1;
1875           SuperClassWriter::addAttribute("DOMAIN_dimensions_ids",array) ;
1876           array=ni_glo,nj_glo ;
1877           SuperClassWriter::addAttribute("DOMAIN_size_global", array) ;
1878           array=ni,nj ;
1879           SuperClassWriter::addAttribute("DOMAIN_size_local", array) ;
1880           array=ibegin,jbegin ;
1881           SuperClassWriter::addAttribute("DOMAIN_position_first", array) ;
1882           array=ibegin+ni-1,jbegin+nj-1 ;
1883           SuperClassWriter::addAttribute("DOMAIN_position_last",array) ;
1884           array=0,0 ;
1885           SuperClassWriter::addAttribute("DOMAIN_halo_size_start", array) ;
1886           SuperClassWriter::addAttribute("DOMAIN_halo_size_end", array);
1887           SuperClassWriter::addAttribute("DOMAIN_type",string("box")) ;
1888  /*
1889           SuperClassWriter::addAttribute("DOMAIN_DIM_N001",string("x")) ;
1890           SuperClassWriter::addAttribute("DOMAIN_DIM_N002",string("y")) ;
1891           SuperClassWriter::addAttribute("DOMAIN_DIM_N003",string("axis_A")) ;
1892           SuperClassWriter::addAttribute("DOMAIN_DIM_N004",string("time_counter")) ;
1893  */
1894         }
1895         catch (CNetCdfException& e)
1896         {
1897           StdString msg("On writing Local Attributes IOIPSL \n");
1898           msg.append("In the context : ");
1899           CContext* context = CContext::getCurrent() ;
1900           msg.append(context->getId()); msg.append("\n");
1901           msg.append(e.what());
1902           ERROR("CNc4DataOutput::writeLocalAttributes_IOIPSL \
1903                  (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)", << msg);
1904         }
1905      }
1906      //---------------------------------------------------------------
1907
1908      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
1909                                                const StdString & description,
1910                                                const StdString & conventions,
1911                                                const StdString & production,
1912                                                const StdString & timeStamp)
1913      {
1914         try
1915         {
1916           SuperClassWriter::addAttribute("name"       , name);
1917           SuperClassWriter::addAttribute("description", description);
1918           SuperClassWriter::addAttribute("title"      , description);
1919           SuperClassWriter::addAttribute("Conventions", conventions);
1920           SuperClassWriter::addAttribute("production" , production);
1921           SuperClassWriter::addAttribute("timeStamp"  , timeStamp);
1922         }
1923         catch (CNetCdfException& e)
1924         {
1925           StdString msg("On writing File Attributes \n ");
1926           msg.append("In the context : ");
1927           CContext* context = CContext::getCurrent() ;
1928           msg.append(context->getId()); msg.append("\n");
1929           msg.append(e.what());
1930           ERROR("CNc4DataOutput:: writeFileAttributes(const StdString & name, \
1931                                                const StdString & description, \
1932                                                const StdString & conventions, \
1933                                                const StdString & production, \
1934                                                const StdString & timeStamp)", << msg);
1935         }
1936      }
1937
1938      //---------------------------------------------------------------
1939
1940      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
1941                                               int data_dim,
1942                                               int data_ni,
1943                                               int data_nj,
1944                                               int data_ibegin,
1945                                               int data_jbegin)
1946      {
1947         try
1948         {
1949           SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
1950           SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
1951           SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
1952           SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
1953           SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
1954         }
1955         catch (CNetCdfException& e)
1956         {
1957           StdString msg("On writing Mask Attributes \n ");
1958           msg.append("In the context : ");
1959           CContext* context = CContext::getCurrent() ;
1960           msg.append(context->getId()); msg.append("\n");
1961           msg.append(e.what());
1962           ERROR("CNc4DataOutput::writeMaskAttributes(const StdString & mask_name, \
1963                                               int data_dim, \
1964                                               int data_ni, \
1965                                               int data_nj, \
1966                                               int data_ibegin, \
1967                                               int data_jbegin)", << msg);
1968         }
1969      }
1970
1971      ///--------------------------------------------------------------
1972
1973} // namespace xios
Note: See TracBrowser for help on using the repository browser.