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

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

Correcting a bug in interpolation domain

+) Replace shared send buffer by seperate buffer for each proc
+) Remove some redundant codes

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