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

Last change on this file since 821 was 821, checked in by mhnguyen, 5 years ago

Making some improvements of transformation algorithm

+) Correct the way to enlisting transformations in an element (domain, axis)
+) Optimize generic transformation to make sure temporary grid to be created on demand
+) Update some mpi tag to prevent conflict
+) Correct some minor stuffs
+) Update documents

Test
+) On Curie
+) all test pass

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