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

Last change on this file since 770 was 770, checked in by rlacroix, 8 years ago

Field: Handle more correctly the output name for the fields with a field_ref.

If the field has an explicitly defined name (which might be inherited) then it is used as the output name.
If no name was defined but an id was set, the id is used as the output name.
If no name was defined and the id was automatically generated, the id of the field directly referenced is used as the output name.

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 81.8 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                SuperClassWriter::writeData(axis->bound_srv, axisBoundsId, isCollective, 0);
688
689              SuperClassWriter::definition_start();
690
691              break;
692            }
693            case ONE_FILE:
694            {
695              CArray<double,1> axis_value(zoom_size_srv);
696              axis_value = axis->value_srv;
697
698              std::vector<StdSize> start(1) ;
699              std::vector<StdSize> count(1) ;
700              start[0] = zoom_begin_srv-axis->global_zoom_begin;
701              count[0] = zoom_size_srv;
702              SuperClassWriter::writeData(axis_value, axisid, isCollective, 0, &start, &count);
703
704              if (!axis->bounds.isEmpty())
705                SuperClassWriter::writeData(axis->bound_srv, axisBoundsId, isCollective, 0, &start, &count);
706
707              SuperClassWriter::definition_start();
708
709              break;
710            }
711            default :
712              ERROR("CNc4DataOutput::writeDomain(domain)",
713                    << "[ type = " << SuperClass::type << "]"
714                    << " not implemented yet !");
715          }
716        }
717        catch (CNetCdfException& e)
718        {
719          StdString msg("On writing the axis : ");
720          msg.append(axisid); msg.append("\n");
721          msg.append("In the context : ");
722          CContext* context = CContext::getCurrent() ;
723          msg.append(context->getId()); msg.append("\n");
724          msg.append(e.what());
725          ERROR("CNc4DataOutput::writeAxis_(CAxis* axis)", << msg);
726        }
727        axis->addRelFile(this->filename);
728     }
729
730     //--------------------------------------------------------------
731
732     void CNc4DataOutput::writeGridCompressed_(CGrid* grid)
733     {
734       if (grid->isScalarGrid() || grid->isWrittenCompressed(this->filename)) return;
735
736       try
737       {
738         CArray<bool,1> axisDomainOrder = grid->axis_domain_order;
739         std::vector<StdString> domainList = grid->getDomainList();
740         std::vector<StdString> axisList   = grid->getAxisList();
741         int numElement = axisDomainOrder.numElements(), idxDomain = 0, idxAxis = 0;
742
743         std::vector<StdString> dims;
744
745         if (grid->isCompressible())
746         {
747           StdString varId = grid->getId() + "_points";
748
749           int nbIndexes = (SuperClass::type == MULTI_FILE) ? grid->getNumberWrittenIndexes() : grid->getTotalNumberWrittenIndexes();
750           SuperClassWriter::addDimension(varId, nbIndexes);
751
752           dims.push_back(varId);
753           SuperClassWriter::addVariable(varId, NC_INT, dims);
754
755           StdOStringStream compress;
756           for (int i = numElement - 1; i >= 0; --i)
757           {
758             if (axisDomainOrder(i))
759             {
760               CDomain* domain = CDomain::get(domainList[domainList.size() - idxDomain - 1]);
761               StdString domId = !domain->name.isEmpty() ? domain->name.getValue() : domain->getId();
762               StdString appendDomId  = singleDomain ? "" : "_" + domId;
763
764               switch (domain->type)
765               {
766                 case CDomain::type_attr::curvilinear:
767                   compress << "y" << appendDomId << " x" << appendDomId;
768                   break;
769                 case CDomain::type_attr::rectilinear:
770                   compress << "lat" << appendDomId << " lon" << appendDomId;
771                   break;
772                 case CDomain::type_attr::unstructured:
773                   compress << "cell" << appendDomId;
774                   break;
775               }
776               ++idxDomain;
777             }
778             else
779             {
780               CAxis* axis = CAxis::get(axisList[axisList.size() - idxAxis - 1]);
781               compress << (!axis->name.isEmpty() ? axis->name.getValue() : axis->getId());
782               ++idxAxis;
783             }
784
785             if (i != 0) compress << ' ';
786           }
787           SuperClassWriter::addAttribute("compress", compress.str(), &varId);
788
789           grid->computeCompressedIndex();
790
791           CArray<int, 1> indexes(grid->getNumberWrittenIndexes());
792           std::map<int, CArray<size_t, 1> >::const_iterator it;
793           for (it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
794           {
795             const CArray<size_t, 1> compressedIndexes = grid->compressedOutIndexFromClient[it->first];
796             for (int i = 0; i < it->second.numElements(); i++)
797               indexes(compressedIndexes(i)) = it->second(i);
798           }
799
800           switch (SuperClass::type)
801           {
802             case (MULTI_FILE):
803             {
804               SuperClassWriter::writeData(indexes, varId, isCollective, 0);
805               break;
806             }
807             case (ONE_FILE):
808             {
809               if (grid->doGridHaveDataDistributed())
810                 grid->getDistributionServer()->computeGlobalIndex(indexes);
811
812               std::vector<StdSize> start, count;
813               start.push_back(grid->getOffsetWrittenIndexes());
814               count.push_back(grid->getNumberWrittenIndexes());
815
816               SuperClassWriter::writeData(indexes, varId, isCollective, 0, &start, &count);
817               break;
818             }
819           }
820         }
821         else
822         {
823           for (int i = 0; i < numElement; ++i)
824           {
825             StdString varId, compress;
826             CArray<int, 1> indexes;
827             bool isDistributed;
828             StdSize nbIndexes, totalNbIndexes, offset;
829             int firstGlobalIndex;
830
831             if (axisDomainOrder(i))
832             {
833               CDomain* domain = CDomain::get(domainList[idxDomain]);
834               if (!domain->isCompressible()
835                    || domain->type == CDomain::type_attr::unstructured
836                    || domain->isWrittenCompressed(this->filename))
837                 continue;
838
839               StdString domId = !domain->name.isEmpty() ? domain->name.getValue() : domain->getId();
840               StdString appendDomId  = singleDomain ? "" : "_" + domId;
841
842               varId = domId + "_points";
843               switch (domain->type)
844               {
845                 case CDomain::type_attr::curvilinear:
846                   compress = "y" + appendDomId + " x" + appendDomId;
847                   break;
848                 case CDomain::type_attr::rectilinear:
849                   compress = "lat" + appendDomId + " lon" + appendDomId;
850                   break;
851               }
852
853               const std::vector<int>& indexesToWrite = domain->getIndexesToWrite();
854               indexes.resize(indexesToWrite.size());
855               for (int n = 0; n < indexes.numElements(); ++n)
856                 indexes(n) = indexesToWrite[n];
857
858               isDistributed = domain->isDistributed();
859               nbIndexes = domain->getNumberWrittenIndexes();
860               totalNbIndexes = domain->getTotalNumberWrittenIndexes();
861               offset = domain->getOffsetWrittenIndexes();
862               firstGlobalIndex = domain->ibegin + domain->jbegin * domain->ni_glo;
863
864               domain->addRelFileCompressed(this->filename);
865               ++idxDomain;
866             }
867             else
868             {
869               CAxis* axis = CAxis::get(axisList[idxAxis]);
870               if (!axis->isCompressible() || axis->isWrittenCompressed(this->filename))
871                 continue;
872
873               StdString axisId = !axis->name.isEmpty() ? axis->name.getValue() : axis->getId();
874               varId = axisId + "_points";
875               compress = axisId;
876
877               const std::vector<int>& indexesToWrite = axis->getIndexesToWrite();
878               indexes.resize(indexesToWrite.size());
879               for (int n = 0; n < indexes.numElements(); ++n)
880                 indexes(n) = indexesToWrite[n];
881
882               isDistributed = axis->isDistributed();
883               nbIndexes = axis->getNumberWrittenIndexes();
884               totalNbIndexes = axis->getTotalNumberWrittenIndexes();
885               offset = axis->getOffsetWrittenIndexes();
886               firstGlobalIndex = axis->begin;
887
888               axis->addRelFileCompressed(this->filename);
889               ++idxAxis;
890             }
891
892             if (!varId.empty())
893             {
894               SuperClassWriter::addDimension(varId, (SuperClass::type == MULTI_FILE) ? nbIndexes : totalNbIndexes);
895
896               dims.clear();
897               dims.push_back(varId);
898               SuperClassWriter::addVariable(varId, NC_INT, dims);
899
900               SuperClassWriter::addAttribute("compress", compress, &varId);
901
902               switch (SuperClass::type)
903               {
904                 case (MULTI_FILE):
905                 {
906                   indexes -= firstGlobalIndex;
907                   SuperClassWriter::writeData(indexes, varId, isCollective, 0);
908                   break;
909                 }
910                 case (ONE_FILE):
911                 {
912                   std::vector<StdSize> start, count;
913                   start.push_back(offset);
914                   count.push_back(nbIndexes);
915
916                   SuperClassWriter::writeData(indexes, varId, isCollective, 0, &start, &count);
917                   break;
918                 }
919               }
920             }
921           }
922
923           if (!dims.empty())
924             grid->computeCompressedIndex();
925         }
926
927         grid->addRelFileCompressed(this->filename);
928       }
929       catch (CNetCdfException& e)
930       {
931         StdString msg("On writing compressed grid : ");
932         msg.append(grid->getId()); msg.append("\n");
933         msg.append("In the context : ");
934         CContext* context = CContext::getCurrent();
935         msg.append(context->getId()); msg.append("\n");
936         msg.append(e.what());
937         ERROR("CNc4DataOutput::writeGridCompressed_(CGrid* grid)", << msg);
938       }
939     }
940
941     //--------------------------------------------------------------
942
943     void CNc4DataOutput::writeTimeDimension_(void)
944     {
945       try
946       {
947        SuperClassWriter::addDimension("time_counter");
948       }
949       catch (CNetCdfException& e)
950       {
951         StdString msg("On writing time dimension : time_couter\n");
952         msg.append("In the context : ");
953         CContext* context = CContext::getCurrent() ;
954         msg.append(context->getId()); msg.append("\n");
955         msg.append(e.what());
956         ERROR("CNc4DataOutput::writeTimeDimension_(void)", << msg);
957       }
958     }
959
960      //--------------------------------------------------------------
961
962      void CNc4DataOutput::writeField_(CField* field)
963      {
964         CContext* context = CContext::getCurrent() ;
965         CContextServer* server=context->server ;
966
967         std::vector<StdString> dims, coodinates;
968         CGrid* grid = field->grid;
969         if (!grid->doGridHaveDataToWrite())
970          if (SuperClass::type==MULTI_FILE) return ;
971
972         CArray<bool,1> axisDomainOrder = grid->axis_domain_order;
973         int numElement = axisDomainOrder.numElements(), idxDomain = 0, idxAxis = 0;
974         std::vector<StdString> domainList = grid->getDomainList();
975         std::vector<StdString> axisList   = grid->getAxisList();
976
977         StdString timeid  = StdString("time_counter");
978         StdString dimXid,dimYid;
979         std::deque<StdString> dimIdList, dimCoordList;
980         bool hasArea = false;
981         StdString cellMeasures = "area:";
982         bool compressedOutput = !field->indexed_output.isEmpty() && field->indexed_output;
983
984         for (int i = 0; i < numElement; ++i)
985         {
986           if (axisDomainOrder(i))
987           {
988             CDomain* domain = CDomain::get(domainList[idxDomain]);
989             StdString domId = !domain->name.isEmpty() ? domain->name.getValue() : domain->getId();
990             StdString appendDomId  = singleDomain ? "" : "_" + domId ;
991
992             if (compressedOutput && domain->isCompressible() && domain->type != CDomain::type_attr::unstructured)
993             {
994               dimIdList.push_back(domId + "_points");
995               field->setUseCompressedOutput();
996             }
997
998             switch (domain->type)
999             {
1000               case CDomain::type_attr::curvilinear:
1001                 if (!compressedOutput || !domain->isCompressible())
1002                 {
1003                   dimXid     = StdString("x").append(appendDomId);
1004                   dimIdList.push_back(dimXid);
1005                   dimYid     = StdString("y").append(appendDomId);
1006                   dimIdList.push_back(dimYid);
1007                 }
1008                 dimCoordList.push_back(StdString("nav_lon").append(appendDomId));
1009                 dimCoordList.push_back(StdString("nav_lat").append(appendDomId));
1010                 break ;
1011               case CDomain::type_attr::rectilinear:
1012                 if (!compressedOutput || !domain->isCompressible())
1013                 {
1014                   dimXid     = StdString("lon").append(appendDomId);
1015                   dimIdList.push_back(dimXid);
1016                   dimYid     = StdString("lat").append(appendDomId);
1017                   dimIdList.push_back(dimYid);
1018                 }
1019                 break ;
1020               case CDomain::type_attr::unstructured:
1021                 dimXid     = StdString("cell").append(appendDomId);
1022                 dimIdList.push_back(dimXid);
1023                 dimCoordList.push_back(StdString("lon").append(appendDomId));
1024                 dimCoordList.push_back(StdString("lat").append(appendDomId));
1025                 break ;
1026             }
1027             if (domain->hasArea)
1028             {
1029               hasArea = true;
1030               cellMeasures += " area" + appendDomId;
1031             }
1032             ++idxDomain;
1033           }
1034           else
1035           {
1036             CAxis* axis = CAxis::get(axisList[idxAxis]);
1037             StdString axisId = !axis->name.isEmpty() ? axis->name.getValue() : axis->getId();
1038
1039             if (compressedOutput && axis->isCompressible())
1040             {
1041               dimIdList.push_back(axisId + "_points");
1042               field->setUseCompressedOutput();
1043             }
1044             else
1045               dimIdList.push_back(axisId);
1046
1047             dimCoordList.push_back(axisId);
1048             ++idxAxis;
1049           }
1050         }
1051
1052/*
1053         StdString lonid_loc = (server->intraCommSize > 1)
1054                             ? StdString("lon").append(appendDomid).append("_local")
1055                             : lonid;
1056         StdString latid_loc = (server->intraCommSize > 1)
1057                             ? StdString("lat").append(appendDomid).append("_local")
1058                             : latid;
1059*/
1060         StdString fieldid = field->getFieldOutputName();
1061
1062//         unsigned int ssize = domain->zoom_ni_loc.getValue() * domain->zoom_nj_loc.getValue();
1063//         bool isCurvilinear = (domain->lonvalue.getValue()->size() == ssize);
1064//          bool isCurvilinear = domain->isCurvilinear ;
1065
1066         nc_type type ;
1067         if (field->prec.isEmpty()) type =  NC_FLOAT ;
1068         else
1069         {
1070           if (field->prec==2) type = NC_SHORT ;
1071           else if (field->prec==4)  type =  NC_FLOAT ;
1072           else if (field->prec==8)   type =  NC_DOUBLE ;
1073         }
1074
1075         bool wtime   = !(!field->operation.isEmpty() && field->getOperationTimeType() == func::CFunctor::once);
1076
1077         if (wtime)
1078         {
1079
1080            //StdOStringStream oss;
1081           // oss << "time_" << field->operation.getValue()
1082           //     << "_" << field->getRelFile()->output_freq.getValue();
1083          //oss
1084            if (field->getOperationTimeType() == func::CFunctor::instant) coodinates.push_back(string("time_instant"));
1085            else if (field->getOperationTimeType() == func::CFunctor::centered) coodinates.push_back(string("time_centered"));
1086            dims.push_back(timeid);
1087         }
1088
1089         if (compressedOutput && grid->isCompressible())
1090         {
1091           dims.push_back(grid->getId() + "_points");
1092           field->setUseCompressedOutput();
1093         }
1094         else
1095         {
1096           while (!dimIdList.empty())
1097           {
1098             dims.push_back(dimIdList.back());
1099             dimIdList.pop_back();
1100           }
1101         }
1102
1103         while (!dimCoordList.empty())
1104         {
1105           coodinates.push_back(dimCoordList.back());
1106           dimCoordList.pop_back();
1107         }
1108
1109         try
1110         {
1111           SuperClassWriter::addVariable(fieldid, type, dims);
1112
1113           if (!field->standard_name.isEmpty())
1114              SuperClassWriter::addAttribute
1115                 ("standard_name",  field->standard_name.getValue(), &fieldid);
1116
1117           if (!field->long_name.isEmpty())
1118              SuperClassWriter::addAttribute
1119                 ("long_name", field->long_name.getValue(), &fieldid);
1120
1121           if (!field->unit.isEmpty())
1122              SuperClassWriter::addAttribute
1123                 ("units", field->unit.getValue(), &fieldid);
1124
1125            if (!field->valid_min.isEmpty())
1126              SuperClassWriter::addAttribute
1127                 ("valid_min", field->valid_min.getValue(), &fieldid);
1128
1129           if (!field->valid_max.isEmpty())
1130              SuperClassWriter::addAttribute
1131                 ("valid_max", field->valid_max.getValue(), &fieldid);
1132
1133            if (!field->scale_factor.isEmpty())
1134              SuperClassWriter::addAttribute
1135                 ("scale_factor", field->scale_factor.getValue(), &fieldid);
1136
1137             if (!field->add_offset.isEmpty())
1138              SuperClassWriter::addAttribute
1139                 ("add_offset", field->add_offset.getValue(), &fieldid);
1140
1141           SuperClassWriter::addAttribute
1142                 ("online_operation", field->operation.getValue(), &fieldid);
1143
1144          // write child variables as attributes
1145
1146
1147           vector<CVariable*> listVars = field->getAllVariables() ;
1148           for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ;
1149
1150
1151           if (wtime)
1152           {
1153              CDuration freqOp = field->freq_op.getValue();
1154              freqOp.solveTimeStep(*context->calendar);
1155              StdString freqOpStr = freqOp.toStringUDUnits();
1156              SuperClassWriter::addAttribute("interval_operation", freqOpStr, &fieldid);
1157
1158              CDuration freqOut = field->getRelFile()->output_freq.getValue();
1159              freqOut.solveTimeStep(*context->calendar);
1160              SuperClassWriter::addAttribute("interval_write", freqOut.toStringUDUnits(), &fieldid);
1161
1162              StdString cellMethods = "time: ";
1163              if (field->operation.getValue() == "instant") cellMethods += "point";
1164              else if (field->operation.getValue() == "average") cellMethods += "mean";
1165              else if (field->operation.getValue() == "accumulate") cellMethods += "sum";
1166              else cellMethods += field->operation;
1167              if (freqOp.resolve(*context->calendar) != freqOut.resolve(*context->calendar))
1168                cellMethods += " (interval: " + freqOpStr + ")";
1169              SuperClassWriter::addAttribute("cell_methods", cellMethods, &fieldid);
1170           }
1171
1172           if (hasArea)
1173             SuperClassWriter::addAttribute("cell_measures", cellMeasures, &fieldid);
1174
1175           if (!field->default_value.isEmpty())
1176           {
1177              double default_value = field->default_value.getValue();
1178              float fdefault_value = (float)default_value;
1179              if (type == NC_DOUBLE)
1180                 SuperClassWriter::setDefaultValue(fieldid, &default_value);
1181              else
1182                 SuperClassWriter::setDefaultValue(fieldid, &fdefault_value);
1183           }
1184           else
1185              SuperClassWriter::setDefaultValue(fieldid, (double*)NULL);
1186
1187            if (field->compression_level.isEmpty())
1188              field->compression_level = field->file->compression_level.isEmpty() ? 0 : field->file->compression_level;
1189            SuperClassWriter::setCompressionLevel(fieldid, field->compression_level);
1190
1191           {  // Ecriture des coordonnées
1192
1193              StdString coordstr; //boost::algorithm::join(coodinates, " ")
1194              std::vector<StdString>::iterator
1195                 itc = coodinates.begin(), endc = coodinates.end();
1196
1197              for (; itc!= endc; itc++)
1198              {
1199                 StdString & coord = *itc;
1200                 if (itc+1 != endc)
1201                       coordstr.append(coord).append(" ");
1202                 else  coordstr.append(coord);
1203              }
1204
1205              SuperClassWriter::addAttribute("coordinates", coordstr, &fieldid);
1206
1207           }
1208         }
1209         catch (CNetCdfException& e)
1210         {
1211           StdString msg("On writing field : ");
1212           msg.append(fieldid); msg.append("\n");
1213           msg.append("In the context : ");
1214           msg.append(context->getId()); msg.append("\n");
1215           msg.append(e.what());
1216           ERROR("CNc4DataOutput::writeField_(CField* field)", << msg);
1217         }
1218      }
1219
1220      //--------------------------------------------------------------
1221
1222      void CNc4DataOutput::writeFile_ (CFile* file)
1223      {
1224         StdString filename = (!file->name.isEmpty())
1225                            ? file->name.getValue() : file->getId();
1226         StdString description = (!file->description.isEmpty())
1227                               ? file->description.getValue()
1228                               : StdString("Created by xios");
1229
1230         singleDomain = (file->nbDomains == 1);
1231
1232         try
1233         {
1234           this->writeFileAttributes(filename, description,
1235                                     StdString("CF-1.5"),
1236                                     StdString("An IPSL model"),
1237                                     this->getTimeStamp());
1238
1239           if (!appendMode)
1240             SuperClassWriter::addDimension("axis_nbounds", 2);
1241         }
1242         catch (CNetCdfException& e)
1243         {
1244           StdString msg("On writing file : ");
1245           msg.append(filename); msg.append("\n");
1246           msg.append("In the context : ");
1247           CContext* context = CContext::getCurrent() ;
1248           msg.append(context->getId()); msg.append("\n");
1249           msg.append(e.what());
1250           ERROR("CNc4DataOutput::writeFile_ (CFile* file)", << msg);
1251         }
1252      }
1253
1254      void CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)
1255      {
1256        string name ;
1257        if (!var->name.isEmpty()) name=var->name ;
1258        else if (var->hasId()) name=var->getId() ;
1259        else return ;
1260
1261        try
1262        {
1263          if (var->type.getValue() == CVariable::type_attr::t_int || var->type.getValue() == CVariable::type_attr::t_int32)
1264            addAttribute(name, var->getData<int>(), &fieldId);
1265          else if (var->type.getValue() == CVariable::type_attr::t_int16)
1266            addAttribute(name, var->getData<short int>(), &fieldId);
1267          else if (var->type.getValue() == CVariable::type_attr::t_float)
1268            addAttribute(name, var->getData<float>(), &fieldId);
1269          else if (var->type.getValue() == CVariable::type_attr::t_double)
1270            addAttribute(name, var->getData<double>(), &fieldId);
1271          else if (var->type.getValue() == CVariable::type_attr::t_string)
1272            addAttribute(name, var->getData<string>(), &fieldId);
1273          else
1274            ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)",
1275                  << "Unsupported variable of type " << var->type.getStringValue());
1276        }
1277       catch (CNetCdfException& e)
1278       {
1279         StdString msg("On writing attributes of variable with name : ");
1280         msg.append(name); msg.append("in the field "); msg.append(fieldId); msg.append("\n");
1281         msg.append("In the context : ");
1282         CContext* context = CContext::getCurrent() ;
1283         msg.append(context->getId()); msg.append("\n");
1284         msg.append(e.what());
1285         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)", << msg);
1286       }
1287     }
1288
1289     void CNc4DataOutput::writeAttribute_ (CVariable* var)
1290     {
1291        string name ;
1292        if (!var->name.isEmpty()) name=var->name ;
1293        else if (var->hasId()) name=var->getId() ;
1294        else return ;
1295        try
1296        {
1297          if (var->type.getValue() == CVariable::type_attr::t_int || var->type.getValue() == CVariable::type_attr::t_int32)
1298            addAttribute(name, var->getData<int>());
1299          else if (var->type.getValue() == CVariable::type_attr::t_int16)
1300            addAttribute(name, var->getData<short int>());
1301          else if (var->type.getValue() == CVariable::type_attr::t_float)
1302            addAttribute(name, var->getData<float>());
1303          else if (var->type.getValue() == CVariable::type_attr::t_double)
1304            addAttribute(name, var->getData<double>());
1305          else if (var->type.getValue() == CVariable::type_attr::t_string)
1306            addAttribute(name, var->getData<string>());
1307          else
1308            ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)",
1309                  << "Unsupported variable of type " << var->type.getStringValue());
1310        }
1311       catch (CNetCdfException& e)
1312       {
1313         StdString msg("On writing attributes of variable with name : ");
1314         msg.append(name); msg.append("\n");
1315         msg.append("In the context : ");
1316         CContext* context = CContext::getCurrent() ;
1317         msg.append(context->getId()); msg.append("\n");
1318         msg.append(e.what());
1319         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)", << msg);
1320       }
1321     }
1322
1323      void CNc4DataOutput::syncFile_ (void)
1324      {
1325        try
1326        {
1327          SuperClassWriter::sync() ;
1328        }
1329        catch (CNetCdfException& e)
1330        {
1331         StdString msg("On synchronizing the write among processes");
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::syncFile_ (void)", << msg);
1337        }
1338      }
1339
1340      void CNc4DataOutput::closeFile_ (void)
1341      {
1342        try
1343        {
1344          SuperClassWriter::close() ;
1345        }
1346        catch (CNetCdfException& e)
1347        {
1348         StdString msg("On closing file");
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
1358      //---------------------------------------------------------------
1359
1360      StdString CNc4DataOutput::getTimeStamp(void) const
1361      {
1362         const int buffer_size = 100;
1363         time_t rawtime;
1364         struct tm * timeinfo = NULL;
1365         char buffer [buffer_size];
1366
1367         time ( &rawtime );
1368         timeinfo = localtime ( &rawtime );
1369         strftime (buffer, buffer_size, "%Y-%b-%d %H:%M:%S %Z", timeinfo);
1370
1371         return (StdString(buffer));
1372      }
1373
1374      //---------------------------------------------------------------
1375
1376      void CNc4DataOutput::writeFieldData_ (CField*  field)
1377      {
1378        CContext* context = CContext::getCurrent();
1379        CContextServer* server = context->server;
1380        CGrid* grid = field->grid;
1381
1382        if (!grid->doGridHaveDataToWrite())
1383          if (SuperClass::type == MULTI_FILE || !isCollective) return;
1384
1385        StdString fieldid = field->getFieldOutputName();
1386
1387        StdOStringStream oss;
1388        string timeAxisId;
1389        if (field->getOperationTimeType() == func::CFunctor::instant) timeAxisId = "time_instant";
1390        else if (field->getOperationTimeType() == func::CFunctor::centered) timeAxisId = "time_centered";
1391
1392        StdString timeBoundId("time_counter_bounds");
1393
1394        StdString timeAxisBoundId;
1395        if (field->getOperationTimeType() == func::CFunctor::instant) timeAxisBoundId = "time_instant_bounds";
1396        else if (field->getOperationTimeType() == func::CFunctor::centered) timeAxisBoundId = "time_centered_bounds";
1397
1398        if (!field->wasWritten())
1399        {
1400          if (appendMode && field->file->record_offset.isEmpty())
1401          {
1402            field->resetNStep(getRecordFromTime(field->last_Write_srv) + 1);
1403          }
1404
1405          field->setWritten();
1406        }
1407
1408
1409        CArray<double,1> time_data(1);
1410        CArray<double,1> time_data_bound(2);
1411        CArray<double,1> time_counter(1);
1412        CArray<double,1> time_counter_bound(2);
1413
1414        bool wtime = (field->getOperationTimeType() != func::CFunctor::once);
1415
1416        if (wtime)
1417        {
1418          Time lastWrite = field->last_Write_srv;
1419          Time lastLastWrite = field->lastlast_Write_srv;
1420
1421          if (field->getOperationTimeType() == func::CFunctor::instant)
1422            time_data(0) = lastWrite;
1423          else if (field->getOperationTimeType() == func::CFunctor::centered)
1424            time_data(0) = (lastWrite + lastLastWrite) / 2;
1425
1426          if (field->getOperationTimeType() == func::CFunctor::instant)
1427            time_data_bound(0) = time_data_bound(1) = lastWrite;
1428          else if (field->getOperationTimeType() == func::CFunctor::centered)
1429          {
1430            time_data_bound(0) = lastLastWrite;
1431            time_data_bound(1) = lastWrite;
1432          }
1433
1434          if (field->file->time_counter == CFile::time_counter_attr::instant)
1435            time_counter(0) = lastWrite;
1436          else if (field->file->time_counter == CFile::time_counter_attr::centered)
1437            time_counter(0) = (lastWrite + lastLastWrite) / 2;
1438          else if (field->file->time_counter == CFile::time_counter_attr::record)
1439            time_counter(0) = field->getNStep() - 1;
1440
1441
1442          if (field->file->time_counter == CFile::time_counter_attr::instant)
1443            time_counter_bound(0) = time_counter_bound(1) = lastWrite;
1444          else if (field->file->time_counter == CFile::time_counter_attr::centered)
1445          {
1446            time_counter_bound(0) = lastLastWrite;
1447            time_counter_bound(1) = lastWrite;
1448          }
1449          else if (field->file->time_counter == CFile::time_counter_attr::record)
1450            time_counter_bound(0) = time_counter_bound(1) = field->getNStep() - 1;
1451        }
1452
1453         bool isRoot = (server->intraCommRank == 0);
1454
1455         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
1456         {
1457           double scaleFactor = 1.0;
1458           double addOffset = 0.0;
1459           if (!field->scale_factor.isEmpty()) scaleFactor = field->scale_factor;
1460           if (!field->add_offset.isEmpty()) addOffset = field->add_offset;
1461           field->scaleFactorAddOffset(scaleFactor, addOffset);
1462         }
1463
1464         try
1465         {
1466           size_t writtenSize;
1467           if (field->getUseCompressedOutput())
1468             writtenSize = grid->getNumberWrittenIndexes();
1469           else
1470             writtenSize = grid->getWrittenDataSize();
1471
1472           CArray<double,1> fieldData(writtenSize);
1473           if (!field->default_value.isEmpty()) fieldData = field->default_value;
1474
1475           if (field->getUseCompressedOutput())
1476             field->outputCompressedField(fieldData);
1477           else
1478             field->outputField(fieldData);
1479
1480           if (!field->prec.isEmpty() && field->prec == 2) fieldData = round(fieldData);
1481
1482           switch (SuperClass::type)
1483           {
1484              case (MULTI_FILE) :
1485              {
1486                 SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep() - 1);
1487                 if (wtime)
1488                 {
1489                   SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep() - 1);
1490                   SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1);
1491                   if (field->file->time_counter != CFile::time_counter_attr::none)
1492                   {
1493                     SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep() - 1);
1494                     if (field->file->time_counter != CFile::time_counter_attr::record)
1495                       SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1);
1496                   }
1497                 }
1498                 break;
1499              }
1500              case (ONE_FILE) :
1501              {
1502                const std::vector<int>& nZoomBeginGlobal = grid->getDistributionServer()->getZoomBeginGlobal();
1503                const std::vector<int>& nZoomBeginServer = grid->getDistributionServer()->getZoomBeginServer();
1504                const std::vector<int>& nZoomSizeServer  = grid->getDistributionServer()->getZoomSizeServer();
1505
1506                std::vector<StdSize> start, count;
1507
1508                if (field->getUseCompressedOutput())
1509                {
1510                  if (grid->isCompressible())
1511                  {
1512                    start.push_back(grid->getOffsetWrittenIndexes());
1513                    count.push_back(grid->getNumberWrittenIndexes());
1514                  }
1515                  else
1516                  {
1517                    CArray<bool,1> axisDomainOrder = grid->axis_domain_order;
1518                    std::vector<StdString> domainList = grid->getDomainList();
1519                    std::vector<StdString> axisList   = grid->getAxisList();
1520                    int numElement = axisDomainOrder.numElements();
1521                    int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
1522                    int idx = nZoomBeginGlobal.size() - 1;
1523
1524                    start.reserve(nZoomBeginGlobal.size());
1525                    count.reserve(nZoomBeginGlobal.size());
1526
1527
1528                    for (int i = numElement - 1; i >= 0; --i)
1529                    {
1530                      if (axisDomainOrder(i))
1531                      {
1532                        CDomain* domain = CDomain::get(domainList[idxDomain]);
1533
1534                        if (domain->isCompressible())
1535                        {
1536                          start.push_back(domain->getOffsetWrittenIndexes());
1537                          count.push_back(domain->getNumberWrittenIndexes());
1538                          idx -= 2;
1539                        }
1540                        else
1541                        {
1542                          if ((domain->type) != CDomain::type_attr::unstructured)
1543                          {
1544                            start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1545                            count.push_back(nZoomSizeServer[idx]);
1546                          }
1547                          --idx;
1548                          start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1549                          count.push_back(nZoomSizeServer[idx]);
1550                          --idx;
1551                        }
1552                        --idxDomain;
1553                      }
1554                      else
1555                      {
1556                        CAxis* axis = CAxis::get(axisList[idxAxis]);
1557
1558                        if (axis->isCompressible())
1559                        {
1560                          start.push_back(axis->getOffsetWrittenIndexes());
1561                          count.push_back(axis->getNumberWrittenIndexes());
1562                        }
1563                        else
1564                        {
1565                          start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1566                          count.push_back(nZoomSizeServer[idx]);
1567                        }
1568
1569                        --idxAxis;
1570                        --idx;
1571                      }
1572                    }
1573                  }
1574                }
1575                else
1576                {
1577
1578                  CArray<bool,1> axisDomainOrder = grid->axis_domain_order;
1579                  std::vector<StdString> domainList = grid->getDomainList();
1580                  std::vector<StdString> axisList   = grid->getAxisList();
1581                  int numElement = axisDomainOrder.numElements();
1582                  int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1;
1583                  int idx = nZoomBeginGlobal.size() - 1;
1584
1585                  start.reserve(nZoomBeginGlobal.size());
1586                  count.reserve(nZoomBeginGlobal.size());
1587
1588                  for (int i = numElement - 1; i >= 0; --i)
1589                  {
1590                    if (axisDomainOrder(i))
1591                    {
1592                      CDomain* domain = CDomain::get(domainList[idxDomain]);
1593                      if ((domain->type) != CDomain::type_attr::unstructured)
1594                      {
1595                        start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1596                        count.push_back(nZoomSizeServer[idx]);
1597                      }
1598                      --idx ;
1599                      start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1600                      count.push_back(nZoomSizeServer[idx]);
1601                      --idx ;
1602                      --idxDomain;
1603                    }
1604                    else
1605                    {
1606                      start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
1607                      count.push_back(nZoomSizeServer[idx]);
1608                      --idx;
1609                     }
1610                  }
1611                }
1612
1613                SuperClassWriter::writeData(fieldData, fieldid, isCollective, field->getNStep() - 1, &start, &count);
1614                if (wtime)
1615                {
1616                   SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep() - 1, isRoot);
1617                   SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1, isRoot);
1618                   if (field->file->time_counter != CFile::time_counter_attr::none)
1619                   {
1620                     SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep() - 1, isRoot);
1621                     if (field->file->time_counter != CFile::time_counter_attr::record)
1622                       SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1, isRoot);
1623                   }
1624                }
1625
1626                break;
1627              }
1628            }
1629         }
1630         catch (CNetCdfException& e)
1631         {
1632           StdString msg("On writing field data: ");
1633           msg.append(fieldid); msg.append("\n");
1634           msg.append("In the context : ");
1635           msg.append(context->getId()); msg.append("\n");
1636           msg.append(e.what());
1637           ERROR("CNc4DataOutput::writeFieldData_ (CField*  field)", << msg);
1638         }
1639      }
1640
1641      //---------------------------------------------------------------
1642
1643      void CNc4DataOutput::writeTimeAxis_
1644                  (CField*    field,
1645                   const boost::shared_ptr<CCalendar> cal)
1646      {
1647         StdOStringStream oss;
1648
1649         if (field->getOperationTimeType() == func::CFunctor::once) return ;
1650
1651//         oss << "time_" << field->operation.getValue()
1652//             << "_" << field->getRelFile()->output_freq.getValue();
1653
1654//         StdString axisid = oss.str();
1655//         if (field->getOperationTimeType() == func::CFunctor::centered) axisid="time_centered" ;
1656//         else if (field->getOperationTimeType() == func::CFunctor::instant) axisid="time_instant" ;
1657
1658         StdString axisid("time_centered") ;
1659         StdString axisBoundId("time_centered_bounds");
1660         StdString timeid("time_counter");
1661         StdString timeBoundId("axis_nbounds");
1662
1663         if (field->getOperationTimeType() == func::CFunctor::instant)
1664         {
1665            axisid = "time_instant";
1666            axisBoundId = "time_instant_bounds";
1667         }
1668
1669         try
1670         {
1671          // Adding time_instant or time_centered
1672           std::vector<StdString> dims;
1673           dims.push_back(timeid);
1674           if (!SuperClassWriter::varExist(axisid))
1675           {
1676              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1677
1678              CDate timeOrigin=cal->getTimeOrigin() ;
1679              StdOStringStream oss2;
1680  //            oss2<<initDate.getYear()<<"-"<<initDate.getMonth()<<"-"<<initDate.getDay()<<" "
1681  //                <<initDate.getHour()<<"-"<<initDate.getMinute()<<"-"<<initDate.getSecond() ;
1682              StdString strInitdate=oss2.str() ;
1683              StdString strTimeOrigin=timeOrigin.toString() ;
1684              this->writeTimeAxisAttributes
1685                 (axisid, cal->getType(),
1686                  StdString("seconds since ").append(strTimeOrigin),
1687                  strTimeOrigin, axisBoundId);
1688           }
1689
1690           // Adding time_instant_bounds or time_centered_bounds variables
1691           if (!SuperClassWriter::varExist(axisBoundId))
1692           {
1693              dims.clear() ;
1694              dims.push_back(timeid);
1695              dims.push_back(timeBoundId);
1696              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1697           }
1698
1699           if (field->file->time_counter != CFile::time_counter_attr::none)
1700           {
1701             // Adding time_counter
1702             axisid = "time_counter";
1703             axisBoundId = "time_counter_bounds";
1704             dims.clear();
1705             dims.push_back(timeid);
1706             if (!SuperClassWriter::varExist(axisid))
1707             {
1708                SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1709                SuperClassWriter::addAttribute("axis", string("T"), &axisid);
1710
1711                if (field->file->time_counter != CFile::time_counter_attr::record)
1712                {
1713                  CDate timeOrigin = cal->getTimeOrigin();
1714                  StdString strTimeOrigin = timeOrigin.toString();
1715
1716                  this->writeTimeAxisAttributes(axisid, cal->getType(),
1717                                                StdString("seconds since ").append(strTimeOrigin),
1718                                                strTimeOrigin, axisBoundId);
1719                }
1720             }
1721
1722             // Adding time_counter_bound dimension
1723             if (field->file->time_counter != CFile::time_counter_attr::record)
1724             {
1725                if (!SuperClassWriter::varExist(axisBoundId))
1726                {
1727                  dims.clear();
1728                  dims.push_back(timeid);
1729                  dims.push_back(timeBoundId);
1730                  SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1731                }
1732             }
1733           }
1734         }
1735         catch (CNetCdfException& e)
1736         {
1737           StdString msg("On writing time axis data: ");
1738           msg.append("In the context : ");
1739           CContext* context = CContext::getCurrent() ;
1740           msg.append(context->getId()); msg.append("\n");
1741           msg.append(e.what());
1742           ERROR("CNc4DataOutput::writeTimeAxis_ (CField*    field, \
1743                  const boost::shared_ptr<CCalendar> cal)", << msg);
1744         }
1745      }
1746
1747      //---------------------------------------------------------------
1748
1749      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
1750                                                   const StdString & calendar,
1751                                                   const StdString & units,
1752                                                   const StdString & time_origin,
1753                                                   const StdString & time_bounds,
1754                                                   const StdString & standard_name,
1755                                                   const StdString & long_name)
1756      {
1757         try
1758         {
1759           SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1760           SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
1761           SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
1762           SuperClassWriter::addAttribute("units",         units        , &axis_name);
1763           SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
1764           SuperClassWriter::addAttribute("bounds",        time_bounds  , &axis_name);
1765         }
1766         catch (CNetCdfException& e)
1767         {
1768           StdString msg("On writing time axis Attribute: ");
1769           msg.append("In the context : ");
1770           CContext* context = CContext::getCurrent() ;
1771           msg.append(context->getId()); msg.append("\n");
1772           msg.append(e.what());
1773           ERROR("CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name, \
1774                                                          const StdString & calendar,\
1775                                                          const StdString & units, \
1776                                                          const StdString & time_origin, \
1777                                                          const StdString & time_bounds, \
1778                                                          const StdString & standard_name, \
1779                                                          const StdString & long_name)", << msg);
1780         }
1781      }
1782
1783      //---------------------------------------------------------------
1784
1785      void CNc4DataOutput::writeAxisAttributes(const StdString & axis_name,
1786                                               const StdString & axis,
1787                                               const StdString & standard_name,
1788                                               const StdString & long_name,
1789                                               const StdString & units,
1790                                               const StdString & nav_model)
1791      {
1792         try
1793         {
1794          if (!axis.empty())
1795            SuperClassWriter::addAttribute("axis"       , axis         , &axis_name);
1796
1797          SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1798          SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
1799          SuperClassWriter::addAttribute("units"        , units        , &axis_name);
1800          SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
1801         }
1802         catch (CNetCdfException& e)
1803         {
1804           StdString msg("On writing Axis Attribute: ");
1805           msg.append("In the context : ");
1806           CContext* context = CContext::getCurrent() ;
1807           msg.append(context->getId()); msg.append("\n");
1808           msg.append(e.what());
1809           ERROR("CNc4DataOutput::writeAxisAttributes(const StdString & axis_name, \
1810                                                      const StdString & axis, \
1811                                                      const StdString & standard_name, \
1812                                                      const StdString & long_name, \
1813                                                      const StdString & units, \
1814                                                      const StdString & nav_model)", << msg);
1815         }
1816      }
1817
1818      //---------------------------------------------------------------
1819
1820      void CNc4DataOutput::writeLocalAttributes
1821         (int ibegin, int ni, int jbegin, int nj, StdString domid)
1822      {
1823        try
1824        {
1825         SuperClassWriter::addAttribute(StdString("ibegin").append(domid), ibegin);
1826         SuperClassWriter::addAttribute(StdString("ni"    ).append(domid), ni);
1827         SuperClassWriter::addAttribute(StdString("jbegin").append(domid), jbegin);
1828         SuperClassWriter::addAttribute(StdString("nj"    ).append(domid), nj);
1829        }
1830        catch (CNetCdfException& e)
1831        {
1832           StdString msg("On writing Local Attributes: ");
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::writeLocalAttributes \
1838                  (int ibegin, int ni, int jbegin, int nj, StdString domid)", << msg);
1839        }
1840
1841      }
1842
1843      void CNc4DataOutput::writeLocalAttributes_IOIPSL(const StdString& dimXid, const StdString& dimYid,
1844                                                       int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)
1845      {
1846         CArray<int,1> array(2) ;
1847
1848         try
1849         {
1850           SuperClassWriter::addAttribute("DOMAIN_number_total",size ) ;
1851           SuperClassWriter::addAttribute("DOMAIN_number", rank) ;
1852           array = SuperClassWriter::getDimension(dimXid) + 1, SuperClassWriter::getDimension(dimYid) + 1;
1853           SuperClassWriter::addAttribute("DOMAIN_dimensions_ids",array) ;
1854           array=ni_glo,nj_glo ;
1855           SuperClassWriter::addAttribute("DOMAIN_size_global", array) ;
1856           array=ni,nj ;
1857           SuperClassWriter::addAttribute("DOMAIN_size_local", array) ;
1858           array=ibegin,jbegin ;
1859           SuperClassWriter::addAttribute("DOMAIN_position_first", array) ;
1860           array=ibegin+ni-1,jbegin+nj-1 ;
1861           SuperClassWriter::addAttribute("DOMAIN_position_last",array) ;
1862           array=0,0 ;
1863           SuperClassWriter::addAttribute("DOMAIN_halo_size_start", array) ;
1864           SuperClassWriter::addAttribute("DOMAIN_halo_size_end", array);
1865           SuperClassWriter::addAttribute("DOMAIN_type",string("box")) ;
1866  /*
1867           SuperClassWriter::addAttribute("DOMAIN_DIM_N001",string("x")) ;
1868           SuperClassWriter::addAttribute("DOMAIN_DIM_N002",string("y")) ;
1869           SuperClassWriter::addAttribute("DOMAIN_DIM_N003",string("axis_A")) ;
1870           SuperClassWriter::addAttribute("DOMAIN_DIM_N004",string("time_counter")) ;
1871  */
1872         }
1873         catch (CNetCdfException& e)
1874         {
1875           StdString msg("On writing Local Attributes IOIPSL \n");
1876           msg.append("In the context : ");
1877           CContext* context = CContext::getCurrent() ;
1878           msg.append(context->getId()); msg.append("\n");
1879           msg.append(e.what());
1880           ERROR("CNc4DataOutput::writeLocalAttributes_IOIPSL \
1881                  (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)", << msg);
1882         }
1883      }
1884      //---------------------------------------------------------------
1885
1886      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
1887                                                const StdString & description,
1888                                                const StdString & conventions,
1889                                                const StdString & production,
1890                                                const StdString & timeStamp)
1891      {
1892         try
1893         {
1894           SuperClassWriter::addAttribute("name"       , name);
1895           SuperClassWriter::addAttribute("description", description);
1896           SuperClassWriter::addAttribute("title"      , description);
1897           SuperClassWriter::addAttribute("Conventions", conventions);
1898           SuperClassWriter::addAttribute("production" , production);
1899           SuperClassWriter::addAttribute("timeStamp"  , timeStamp);
1900         }
1901         catch (CNetCdfException& e)
1902         {
1903           StdString msg("On writing File Attributes \n ");
1904           msg.append("In the context : ");
1905           CContext* context = CContext::getCurrent() ;
1906           msg.append(context->getId()); msg.append("\n");
1907           msg.append(e.what());
1908           ERROR("CNc4DataOutput:: writeFileAttributes(const StdString & name, \
1909                                                const StdString & description, \
1910                                                const StdString & conventions, \
1911                                                const StdString & production, \
1912                                                const StdString & timeStamp)", << msg);
1913         }
1914      }
1915
1916      //---------------------------------------------------------------
1917
1918      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
1919                                               int data_dim,
1920                                               int data_ni,
1921                                               int data_nj,
1922                                               int data_ibegin,
1923                                               int data_jbegin)
1924      {
1925         try
1926         {
1927           SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
1928           SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
1929           SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
1930           SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
1931           SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
1932         }
1933         catch (CNetCdfException& e)
1934         {
1935           StdString msg("On writing Mask Attributes \n ");
1936           msg.append("In the context : ");
1937           CContext* context = CContext::getCurrent() ;
1938           msg.append(context->getId()); msg.append("\n");
1939           msg.append(e.what());
1940           ERROR("CNc4DataOutput::writeMaskAttributes(const StdString & mask_name, \
1941                                               int data_dim, \
1942                                               int data_ni, \
1943                                               int data_nj, \
1944                                               int data_ibegin, \
1945                                               int data_jbegin)", << msg);
1946         }
1947      }
1948
1949      ///--------------------------------------------------------------
1950
1951      StdSize CNc4DataOutput::getRecordFromTime(Time time)
1952      {
1953        std::map<Time, StdSize>::const_iterator it = timeToRecordCache.find(time);
1954        if (it == timeToRecordCache.end())
1955        {
1956          StdString timeAxisBoundsId("time_counter_bounds");
1957          if (!SuperClassWriter::varExist(timeAxisBoundsId))
1958            timeAxisBoundsId = "time_instant_bounds";
1959
1960          CArray<double,2> timeAxisBounds;
1961          SuperClassWriter::getTimeAxisBounds(timeAxisBounds, timeAxisBoundsId, isCollective);
1962
1963          StdSize record = 0;
1964          double dtime(time);
1965          for (int n = timeAxisBounds.extent(1) - 1; n >= 0; n--)
1966          {
1967            if (timeAxisBounds(1, n) < dtime)
1968            {
1969              record = n + 1;
1970              break;
1971            }
1972          }
1973          it = timeToRecordCache.insert(std::make_pair(time, record)).first;
1974        }
1975        return it->second;
1976      }
1977} // namespace xios
Note: See TracBrowser for help on using the repository browser.