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

Last change on this file since 710 was 710, checked in by mhnguyen, 9 years ago

Correcting some conflicts after merging

  • 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: 82.6 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        CContextServer* server = context->server;
1397        CGrid* grid = field->grid;
1398
1399        if (!grid->doGridHaveDataToWrite())
1400          if (SuperClass::type == MULTI_FILE || !isCollective) return;
1401
1402        StdString fieldid = !field->name.isEmpty()
1403                          ? field->name.getValue()
1404                          : field->getBaseFieldReference()->getId();
1405
1406        StdOStringStream oss;
1407        string timeAxisId;
1408        if (field->getOperationTimeType() == func::CFunctor::instant) timeAxisId = "time_instant";
1409        else if (field->getOperationTimeType() == func::CFunctor::centered) timeAxisId = "time_centered";
1410
1411        StdString timeBoundId("time_counter_bounds");
1412
1413        StdString timeAxisBoundId;
1414        if (field->getOperationTimeType() == func::CFunctor::instant) timeAxisBoundId = "time_instant_bounds";
1415        else if (field->getOperationTimeType() == func::CFunctor::centered) timeAxisBoundId = "time_centered_bounds";
1416
1417        if (!field->wasWritten())
1418        {
1419          if (appendMode)
1420          {
1421            field->resetNStep(getRecordFromTime(field->last_Write_srv) + 1);
1422          }
1423
1424          field->setWritten();
1425        }
1426
1427
1428        CArray<double,1> time_data(1);
1429        CArray<double,1> time_data_bound(2);
1430        CArray<double,1> time_counter(1);
1431        CArray<double,1> time_counter_bound(2);
1432
1433        bool wtime = (field->getOperationTimeType() != func::CFunctor::once);
1434
1435        if (wtime)
1436        {
1437          Time lastWrite = field->last_Write_srv;
1438          Time lastLastWrite = field->lastlast_Write_srv;
1439
1440          if (field->getOperationTimeType() == func::CFunctor::instant)
1441            time_data(0) = lastWrite;
1442          else if (field->getOperationTimeType() == func::CFunctor::centered)
1443            time_data(0) = (lastWrite + lastLastWrite) / 2;
1444
1445          if (field->getOperationTimeType() == func::CFunctor::instant)
1446            time_data_bound(0) = time_data_bound(1) = lastWrite;
1447          else if (field->getOperationTimeType() == func::CFunctor::centered)
1448          {
1449            time_data_bound(0) = lastLastWrite;
1450            time_data_bound(1) = lastWrite;
1451          }
1452
1453          if (field->file->time_counter == CFile::time_counter_attr::instant)
1454            time_counter(0) = lastWrite;
1455          else if (field->file->time_counter == CFile::time_counter_attr::centered)
1456            time_counter(0) = (lastWrite + lastLastWrite) / 2;
1457          else if (field->file->time_counter == CFile::time_counter_attr::record)
1458            time_counter(0) = field->getNStep() - 1;
1459
1460
1461          if (field->file->time_counter == CFile::time_counter_attr::instant)
1462            time_counter_bound(0) = time_counter_bound(1) = lastWrite;
1463          else if (field->file->time_counter == CFile::time_counter_attr::centered)
1464          {
1465            time_counter_bound(0) = lastLastWrite;
1466            time_counter_bound(1) = lastWrite;
1467          }
1468          else if (field->file->time_counter == CFile::time_counter_attr::record)
1469            time_counter_bound(0) = time_counter_bound(1) = field->getNStep() - 1;
1470        }
1471
1472         bool isRoot = (server->intraCommRank == 0);
1473
1474         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
1475         {
1476           double scaleFactor = 1.0;
1477           double addOffset = 0.0;
1478           if (!field->scale_factor.isEmpty()) scaleFactor = field->scale_factor;
1479           if (!field->add_offset.isEmpty()) addOffset = field->add_offset;
1480           field->scaleFactorAddOffset(scaleFactor, addOffset);
1481         }
1482
1483         try
1484         {
1485           size_t writtenSize;
1486           if (field->getUseCompressedOutput())
1487             writtenSize = grid->getNumberWrittenIndexes();
1488           else
1489             writtenSize = grid->getWrittenDataSize();
1490
1491           CArray<double,1> fieldData(writtenSize);
1492           if (!field->default_value.isEmpty()) fieldData = field->default_value;
1493
1494           if (field->getUseCompressedOutput())
1495             field->outputCompressedField(fieldData);
1496           else
1497             field->outputField(fieldData);
1498
1499           if (!field->prec.isEmpty() && field->prec == 2) fieldData = round(fieldData);
1500
1501           switch (SuperClass::type)
1502           {
1503              case (MULTI_FILE) :
1504              {
1505                 SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep() - 1);
1506                 if (wtime)
1507                 {
1508                   SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep() - 1);
1509                   SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1);
1510                   if (field->file->time_counter != CFile::time_counter_attr::none)
1511                   {
1512                     SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep() - 1);
1513                     if (field->file->time_counter != CFile::time_counter_attr::record)
1514                       SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1);
1515                   }
1516                 }
1517                 break;
1518              }
1519              case (ONE_FILE) :
1520              {
1521                const std::vector<int>& nZoomBeginGlobal = grid->getDistributionServer()->getZoomBeginGlobal();
1522                const std::vector<int>& nZoomBeginServer = grid->getDistributionServer()->getZoomBeginServer();
1523                const std::vector<int>& nZoomSizeServer  = grid->getDistributionServer()->getZoomSizeServer();
1524
1525                std::vector<StdSize> start, count;
1526
1527                if (field->getUseCompressedOutput())
1528                {
1529                  if (grid->isCompressible())
1530                  {
1531                    start.push_back(grid->getOffsetWrittenIndexes());
1532                    count.push_back(grid->getNumberWrittenIndexes());
1533                  }
1534                  else
1535                  {
1536                    CArray<bool,1> axisDomainOrder = grid->axis_domain_order;
1537                    std::vector<StdString> domainList = grid->getDomainList();
1538                    std::vector<StdString> axisList   = grid->getAxisList();
1539                    int numElement = axisDomainOrder.numElements();
1540                    int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
1541                    int idx = nZoomBeginGlobal.size() - 1;
1542
1543                    start.reserve(nZoomBeginGlobal.size());
1544                    count.reserve(nZoomBeginGlobal.size());
1545
1546
1547                    for (int i = numElement - 1; i >= 0; --i)
1548                    {
1549                      if (axisDomainOrder(i))
1550                      {
1551                        CDomain* domain = CDomain::get(domainList[idxDomain]);
1552
1553                        if (domain->isCompressible())
1554                        {
1555                          start.push_back(domain->getOffsetWrittenIndexes());
1556                          count.push_back(domain->getNumberWrittenIndexes());
1557                          idx -= 2;
1558                        }
1559                        else
1560                        {
1561                          if ((domain->type) != CDomain::type_attr::unstructured)
1562                          {
1563                            start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1564                            count.push_back(nZoomSizeServer[idx]);
1565                          }
1566                          --idx;
1567                          start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1568                          count.push_back(nZoomSizeServer[idx]);
1569                          --idx;
1570                        }
1571                        --idxDomain;
1572                      }
1573                      else
1574                      {
1575                        CAxis* axis = CAxis::get(axisList[idxAxis]);
1576
1577                        if (axis->isCompressible())
1578                        {
1579                          start.push_back(axis->getOffsetWrittenIndexes());
1580                          count.push_back(axis->getNumberWrittenIndexes());
1581                        }
1582                        else
1583                        {
1584                          start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1585                          count.push_back(nZoomSizeServer[idx]);
1586                        }
1587
1588                        --idxAxis;
1589                        --idx;
1590                      }
1591                    }
1592                  }
1593                }
1594                else
1595                {
1596
1597                  CArray<bool,1> axisDomainOrder = grid->axis_domain_order;
1598                  std::vector<StdString> domainList = grid->getDomainList();
1599                  std::vector<StdString> axisList   = grid->getAxisList();
1600                  int numElement = axisDomainOrder.numElements();
1601                  int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
1602                  int idx = nZoomBeginGlobal.size() - 1;
1603
1604                  start.reserve(nZoomBeginGlobal.size());
1605                  count.reserve(nZoomBeginGlobal.size());
1606
1607                  for (int i = numElement - 1; i >= 0; --i)
1608                  {
1609                    if (axisDomainOrder(i))
1610                    {
1611                      CDomain* domain = CDomain::get(domainList[idxDomain]);
1612                      if ((domain->type) != CDomain::type_attr::unstructured)
1613                      {
1614                        start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1615                        count.push_back(nZoomSizeServer[idx]);
1616                      }
1617                      --idx ;
1618                      start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1619                      count.push_back(nZoomSizeServer[idx]);
1620                      --idx ;
1621                      --idxDomain;
1622                    }
1623                    else
1624                    {
1625                      start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1626                      count.push_back(nZoomSizeServer[idx]);
1627                      --idx;
1628                     }
1629                  }
1630                }
1631
1632                SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep() - 1, &start, &count);
1633                if (wtime)
1634                {
1635                   SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep() - 1, isRoot);
1636                   SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1, isRoot);
1637                   if (field->file->time_counter != CFile::time_counter_attr::none)
1638                   {
1639                     SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep() - 1, isRoot);
1640                     if (field->file->time_counter != CFile::time_counter_attr::record)
1641                       SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1, isRoot);
1642                   }
1643                }
1644
1645                break;
1646              }
1647            }
1648         }
1649         catch (CNetCdfException& e)
1650         {
1651           StdString msg("On writing field data: ");
1652           msg.append(fieldid); msg.append("\n");
1653           msg.append("In the context : ");
1654           msg.append(context->getId()); msg.append("\n");
1655           msg.append(e.what());
1656           ERROR("CNc4DataOutput::writeFieldData_ (CField*  field)", << msg);
1657         }
1658      }
1659
1660      //---------------------------------------------------------------
1661
1662      void CNc4DataOutput::writeTimeAxis_
1663                  (CField*    field,
1664                   const boost::shared_ptr<CCalendar> cal)
1665      {
1666         StdOStringStream oss;
1667
1668         if (field->getOperationTimeType() == func::CFunctor::once) return ;
1669
1670//         oss << "time_" << field->operation.getValue()
1671//             << "_" << field->getRelFile()->output_freq.getValue();
1672
1673//         StdString axisid = oss.str();
1674//         if (field->getOperationTimeType() == func::CFunctor::centered) axisid="time_centered" ;
1675//         else if (field->getOperationTimeType() == func::CFunctor::instant) axisid="time_instant" ;
1676
1677         StdString axisid("time_centered") ;
1678         StdString axisBoundId("time_centered_bounds");
1679         StdString timeid("time_counter");
1680         StdString timeBoundId("axis_nbounds");
1681
1682         if (field->getOperationTimeType() == func::CFunctor::instant)
1683         {
1684            axisid = "time_instant";
1685            axisBoundId = "time_instant_bounds";
1686         }
1687
1688         try
1689         {
1690          // Adding time_instant or time_centered
1691           std::vector<StdString> dims;
1692           dims.push_back(timeid);
1693           if (!SuperClassWriter::varExist(axisid))
1694           {
1695              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1696
1697              CDate timeOrigin=cal->getTimeOrigin() ;
1698              StdOStringStream oss2;
1699  //            oss2<<initDate.getYear()<<"-"<<initDate.getMonth()<<"-"<<initDate.getDay()<<" "
1700  //                <<initDate.getHour()<<"-"<<initDate.getMinute()<<"-"<<initDate.getSecond() ;
1701              StdString strInitdate=oss2.str() ;
1702              StdString strTimeOrigin=timeOrigin.toString() ;
1703              this->writeTimeAxisAttributes
1704                 (axisid, cal->getType(),
1705                  StdString("seconds since ").append(strTimeOrigin),
1706                  strTimeOrigin, axisBoundId);
1707           }
1708
1709           // Adding time_instant_bounds or time_centered_bounds variables
1710           if (!SuperClassWriter::varExist(axisBoundId))
1711           {
1712              dims.clear() ;
1713              dims.push_back(timeid);
1714              dims.push_back(timeBoundId);
1715              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1716           }
1717
1718           if (field->file->time_counter != CFile::time_counter_attr::none)
1719           {
1720             // Adding time_counter
1721             axisid = "time_counter";
1722             axisBoundId = "time_counter_bounds";
1723             dims.clear();
1724             dims.push_back(timeid);
1725             if (!SuperClassWriter::varExist(axisid))
1726             {
1727                SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1728                SuperClassWriter::addAttribute("axis", string("T"), &axisid);
1729
1730                if (field->file->time_counter != CFile::time_counter_attr::record)
1731                {
1732                  CDate timeOrigin = cal->getTimeOrigin();
1733                  StdString strTimeOrigin = timeOrigin.toString();
1734
1735                  this->writeTimeAxisAttributes(axisid, cal->getType(),
1736                                                StdString("seconds since ").append(strTimeOrigin),
1737                                                strTimeOrigin, axisBoundId);
1738                }
1739             }
1740
1741             // Adding time_counter_bound dimension
1742             if (field->file->time_counter != CFile::time_counter_attr::record)
1743             {
1744                if (!SuperClassWriter::varExist(axisBoundId))
1745                {
1746                  dims.clear();
1747                  dims.push_back(timeid);
1748                  dims.push_back(timeBoundId);
1749                  SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1750                }
1751             }
1752           }
1753         }
1754         catch (CNetCdfException& e)
1755         {
1756           StdString msg("On writing time axis data: ");
1757           msg.append("In the context : ");
1758           CContext* context = CContext::getCurrent() ;
1759           msg.append(context->getId()); msg.append("\n");
1760           msg.append(e.what());
1761           ERROR("CNc4DataOutput::writeTimeAxis_ (CField*    field, \
1762                  const boost::shared_ptr<CCalendar> cal)", << msg);
1763         }
1764      }
1765
1766      //---------------------------------------------------------------
1767
1768      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
1769                                                   const StdString & calendar,
1770                                                   const StdString & units,
1771                                                   const StdString & time_origin,
1772                                                   const StdString & time_bounds,
1773                                                   const StdString & standard_name,
1774                                                   const StdString & long_name)
1775      {
1776         try
1777         {
1778           SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1779           SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
1780           SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
1781           SuperClassWriter::addAttribute("units",         units        , &axis_name);
1782           SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
1783           SuperClassWriter::addAttribute("bounds",        time_bounds  , &axis_name);
1784         }
1785         catch (CNetCdfException& e)
1786         {
1787           StdString msg("On writing time axis Attribute: ");
1788           msg.append("In the context : ");
1789           CContext* context = CContext::getCurrent() ;
1790           msg.append(context->getId()); msg.append("\n");
1791           msg.append(e.what());
1792           ERROR("CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name, \
1793                                                          const StdString & calendar,\
1794                                                          const StdString & units, \
1795                                                          const StdString & time_origin, \
1796                                                          const StdString & time_bounds, \
1797                                                          const StdString & standard_name, \
1798                                                          const StdString & long_name)", << msg);
1799         }
1800      }
1801
1802      //---------------------------------------------------------------
1803
1804      void CNc4DataOutput::writeAxisAttributes(const StdString & axis_name,
1805                                               const StdString & axis,
1806                                               const StdString & standard_name,
1807                                               const StdString & long_name,
1808                                               const StdString & units,
1809                                               const StdString & nav_model)
1810      {
1811         try
1812         {
1813          if (!axis.empty())
1814            SuperClassWriter::addAttribute("axis"       , axis         , &axis_name);
1815
1816          SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1817          SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
1818          SuperClassWriter::addAttribute("units"        , units        , &axis_name);
1819          SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
1820         }
1821         catch (CNetCdfException& e)
1822         {
1823           StdString msg("On writing Axis Attribute: ");
1824           msg.append("In the context : ");
1825           CContext* context = CContext::getCurrent() ;
1826           msg.append(context->getId()); msg.append("\n");
1827           msg.append(e.what());
1828           ERROR("CNc4DataOutput::writeAxisAttributes(const StdString & axis_name, \
1829                                                      const StdString & axis, \
1830                                                      const StdString & standard_name, \
1831                                                      const StdString & long_name, \
1832                                                      const StdString & units, \
1833                                                      const StdString & nav_model)", << msg);
1834         }
1835      }
1836
1837      //---------------------------------------------------------------
1838
1839      void CNc4DataOutput::writeLocalAttributes
1840         (int ibegin, int ni, int jbegin, int nj, StdString domid)
1841      {
1842        try
1843        {
1844         SuperClassWriter::addAttribute(StdString("ibegin").append(domid), ibegin);
1845         SuperClassWriter::addAttribute(StdString("ni"    ).append(domid), ni);
1846         SuperClassWriter::addAttribute(StdString("jbegin").append(domid), jbegin);
1847         SuperClassWriter::addAttribute(StdString("nj"    ).append(domid), nj);
1848        }
1849        catch (CNetCdfException& e)
1850        {
1851           StdString msg("On writing Local Attributes: ");
1852           msg.append("In the context : ");
1853           CContext* context = CContext::getCurrent() ;
1854           msg.append(context->getId()); msg.append("\n");
1855           msg.append(e.what());
1856           ERROR("CNc4DataOutput::writeLocalAttributes \
1857                  (int ibegin, int ni, int jbegin, int nj, StdString domid)", << msg);
1858        }
1859
1860      }
1861
1862      void CNc4DataOutput::writeLocalAttributes_IOIPSL(const StdString& dimXid, const StdString& dimYid,
1863                                                       int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)
1864      {
1865         CArray<int,1> array(2) ;
1866
1867         try
1868         {
1869           SuperClassWriter::addAttribute("DOMAIN_number_total",size ) ;
1870           SuperClassWriter::addAttribute("DOMAIN_number", rank) ;
1871           array = SuperClassWriter::getDimension(dimXid) + 1, SuperClassWriter::getDimension(dimYid) + 1;
1872           SuperClassWriter::addAttribute("DOMAIN_dimensions_ids",array) ;
1873           array=ni_glo,nj_glo ;
1874           SuperClassWriter::addAttribute("DOMAIN_size_global", array) ;
1875           array=ni,nj ;
1876           SuperClassWriter::addAttribute("DOMAIN_size_local", array) ;
1877           array=ibegin,jbegin ;
1878           SuperClassWriter::addAttribute("DOMAIN_position_first", array) ;
1879           array=ibegin+ni-1,jbegin+nj-1 ;
1880           SuperClassWriter::addAttribute("DOMAIN_position_last",array) ;
1881           array=0,0 ;
1882           SuperClassWriter::addAttribute("DOMAIN_halo_size_start", array) ;
1883           SuperClassWriter::addAttribute("DOMAIN_halo_size_end", array);
1884           SuperClassWriter::addAttribute("DOMAIN_type",string("box")) ;
1885  /*
1886           SuperClassWriter::addAttribute("DOMAIN_DIM_N001",string("x")) ;
1887           SuperClassWriter::addAttribute("DOMAIN_DIM_N002",string("y")) ;
1888           SuperClassWriter::addAttribute("DOMAIN_DIM_N003",string("axis_A")) ;
1889           SuperClassWriter::addAttribute("DOMAIN_DIM_N004",string("time_counter")) ;
1890  */
1891         }
1892         catch (CNetCdfException& e)
1893         {
1894           StdString msg("On writing Local Attributes IOIPSL \n");
1895           msg.append("In the context : ");
1896           CContext* context = CContext::getCurrent() ;
1897           msg.append(context->getId()); msg.append("\n");
1898           msg.append(e.what());
1899           ERROR("CNc4DataOutput::writeLocalAttributes_IOIPSL \
1900                  (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)", << msg);
1901         }
1902      }
1903      //---------------------------------------------------------------
1904
1905      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
1906                                                const StdString & description,
1907                                                const StdString & conventions,
1908                                                const StdString & production,
1909                                                const StdString & timeStamp)
1910      {
1911         try
1912         {
1913           SuperClassWriter::addAttribute("name"       , name);
1914           SuperClassWriter::addAttribute("description", description);
1915           SuperClassWriter::addAttribute("title"      , description);
1916           SuperClassWriter::addAttribute("Conventions", conventions);
1917           SuperClassWriter::addAttribute("production" , production);
1918           SuperClassWriter::addAttribute("timeStamp"  , timeStamp);
1919         }
1920         catch (CNetCdfException& e)
1921         {
1922           StdString msg("On writing File Attributes \n ");
1923           msg.append("In the context : ");
1924           CContext* context = CContext::getCurrent() ;
1925           msg.append(context->getId()); msg.append("\n");
1926           msg.append(e.what());
1927           ERROR("CNc4DataOutput:: writeFileAttributes(const StdString & name, \
1928                                                const StdString & description, \
1929                                                const StdString & conventions, \
1930                                                const StdString & production, \
1931                                                const StdString & timeStamp)", << msg);
1932         }
1933      }
1934
1935      //---------------------------------------------------------------
1936
1937      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
1938                                               int data_dim,
1939                                               int data_ni,
1940                                               int data_nj,
1941                                               int data_ibegin,
1942                                               int data_jbegin)
1943      {
1944         try
1945         {
1946           SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
1947           SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
1948           SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
1949           SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
1950           SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
1951         }
1952         catch (CNetCdfException& e)
1953         {
1954           StdString msg("On writing Mask Attributes \n ");
1955           msg.append("In the context : ");
1956           CContext* context = CContext::getCurrent() ;
1957           msg.append(context->getId()); msg.append("\n");
1958           msg.append(e.what());
1959           ERROR("CNc4DataOutput::writeMaskAttributes(const StdString & mask_name, \
1960                                               int data_dim, \
1961                                               int data_ni, \
1962                                               int data_nj, \
1963                                               int data_ibegin, \
1964                                               int data_jbegin)", << msg);
1965         }
1966      }
1967
1968      ///--------------------------------------------------------------
1969
1970      StdSize CNc4DataOutput::getRecordFromTime(Time time)
1971      {
1972        std::map<Time, StdSize>::const_iterator it = timeToRecordCache.find(time);
1973        if (it == timeToRecordCache.end())
1974        {
1975          StdString timeAxisBoundsId("time_counter_bounds");
1976          if (!SuperClassWriter::varExist(timeAxisBoundsId))
1977            timeAxisBoundsId = "time_instant_bounds";
1978
1979          CArray<double,2> timeAxisBounds;
1980          SuperClassWriter::getTimeAxisBounds(timeAxisBounds, timeAxisBoundsId, isCollective);
1981
1982          StdSize record = 0;
1983          double dtime(time);
1984          for (int n = timeAxisBounds.extent(1) - 1; n >= 0; n--)
1985          {
1986            if (timeAxisBounds(1, n) < dtime)
1987            {
1988              record = n + 1;
1989              break;
1990            }
1991          }
1992          it = timeToRecordCache.insert(std::make_pair(time, record)).first;
1993        }
1994        return it->second;
1995      }
1996} // namespace xios
Note: See TracBrowser for help on using the repository browser.