source: XIOS/branchs/xios-1.0/src/output/nc4_data_output.cpp @ 618

Last change on this file since 618 was 618, checked in by rlacroix, 9 years ago

CF compliance: Fix cell_methods attribute.

The specifications do not allow using an auxiliary coordinate to identify an axis. Instead always use the generic standard name "time".

  • 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
File size: 65.7 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//         if (!exist)
27//            SuperClassWriter::addDimension(timeid);
28      }
29
30      CNc4DataOutput::CNc4DataOutput
31         (const StdString & filename, bool exist, MPI_Comm comm_file,bool multifile, bool isCollective)
32            : SuperClass()
33            , SuperClassWriter(filename, exist, &comm_file,multifile)
34            , comm_file(comm_file)
35            , filename(filename)
36            , isCollective(isCollective)
37      {
38         StdString timeid = StdString("time_counter");
39
40         SuperClass::type = (multifile) ? MULTI_FILE : ONE_FILE;
41
42 //        if (!exist)
43//            SuperClassWriter::addDimension(timeid);
44      }
45
46
47      CNc4DataOutput::~CNc4DataOutput(void)
48      { /* Ne rien faire de plus */ }
49
50      ///--------------------------------------------------------------
51
52      const StdString & CNc4DataOutput::getFileName(void) const
53      {
54         return (this->filename);
55      }
56
57      //---------------------------------------------------------------
58
59      void CNc4DataOutput::writeDomain_(CDomain* domain)
60      {
61         if (domain->type == CDomain::type_attr::unstructured)
62         {
63           writeUnstructuredDomain(domain) ;
64           return ;
65         }
66
67         CContext* context = CContext::getCurrent() ;
68         CContextServer* server=context->server ;
69
70         if (domain->IsWritten(this->filename)) return;
71         domain->checkAttributes();
72
73         if (domain->isEmpty())
74           if (SuperClass::type==MULTI_FILE) return ;
75
76         std::vector<StdString> dim0, dim1;
77         StdString domid     = (!domain->name.isEmpty())
78                             ? domain->name.getValue() : domain->getId();
79         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
80
81
82         StdString dimXid, dimYid ;
83
84         bool isRegularDomain = (domain->type == CDomain::type_attr::regular);
85         switch (domain->type)
86         {
87           case CDomain::type_attr::curvilinear :
88             dimXid     = StdString("x").append(appendDomid);
89             dimYid     = StdString("y").append(appendDomid);
90             break ;
91           case CDomain::type_attr::regular :
92             dimXid     = StdString("lon").append(appendDomid);
93             dimYid     = StdString("lat").append(appendDomid);
94             break;
95         }
96
97         StdString dimVertId = StdString("nvertex").append(appendDomid);
98
99         string lonid,latid,bounds_lonid,bounds_latid ;
100         string areaId = "area" + appendDomid;
101/*
102         StdString lonid_loc = (server->intraCommSize > 1)
103                             ? StdString("lon").append(appendDomid).append("_local")
104                             : lonid;
105         StdString latid_loc = (server->intraCommSize > 1)
106                             ? StdString("lat").append(appendDomid).append("_local")
107                             : latid;
108*/
109
110         try
111         {
112           switch (SuperClass::type)
113           {
114              case (MULTI_FILE) :
115              {
116  //               if (domain->isEmpty()) return;
117
118                 if (server->intraCommSize > 1)
119                 {
120  //                 SuperClassWriter::addDimension(lonid, domain->zoom_ni.getValue());
121  //                 SuperClassWriter::addDimension(latid, domain->zoom_nj.getValue());
122                 }
123
124                 switch (domain->type)
125                 {
126                   case CDomain::type_attr::curvilinear :
127                     dim0.push_back(dimYid); dim0.push_back(dimXid);
128                     lonid = StdString("nav_lon").append(appendDomid);
129                     latid = StdString("nav_lat").append(appendDomid);
130                     break ;
131                   case CDomain::type_attr::regular :
132                     lonid = StdString("lon").append(appendDomid);
133                     latid = StdString("lat").append(appendDomid);
134                     dim0.push_back(dimYid);
135                     dim1.push_back(dimXid);
136                     break;
137                 }
138
139                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
140                 bounds_latid = StdString("bounds_lat").append(appendDomid);
141
142                 SuperClassWriter::addDimension(dimXid, domain->zoom_ni_srv);
143                 SuperClassWriter::addDimension(dimYid, domain->zoom_nj_srv);
144
145                 if (domain->hasBounds)
146                   SuperClassWriter::addDimension(dimVertId, domain->nvertex);
147
148                 if (server->intraCommSize > 1)
149                 {
150                   this->writeLocalAttributes(domain->zoom_ibegin_srv,
151                                              domain->zoom_ni_srv,
152                                              domain->zoom_jbegin_srv,
153                                              domain->zoom_nj_srv,
154                                              appendDomid);
155
156                   if (singleDomain) this->writeLocalAttributes_IOIPSL(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                 switch (domain->type)
165                 {
166                   case CDomain::type_attr::curvilinear :
167                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
168                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
169                     break ;
170                    case CDomain::type_attr::regular :
171                      SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
172                      SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
173                      break ;
174                 }
175
176                 this->writeAxisAttributes(lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
177                 this->writeAxisAttributes(latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
178
179                 if (domain->hasBounds)
180                 {
181                   SuperClassWriter::addAttribute("bounds", bounds_lonid, &lonid);
182                   SuperClassWriter::addAttribute("bounds", bounds_latid, &latid);
183
184                   dim0.clear();
185                   dim0.push_back(dimYid);
186                   dim0.push_back(dimXid);
187                   dim0.push_back(dimVertId);
188                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
189                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
190                 }
191
192                 dim0.clear();
193                 dim0.push_back(dimYid);
194                 dim0.push_back(dimXid);
195
196
197  // supress mask               if (server->intraCommSize > 1)
198  // supress mask               {
199  // supress mask                  SuperClassWriter::addVariable(maskid, NC_INT, dim0);
200  // supress mask
201  // supress mask                  this->writeMaskAttributes(maskid,
202  // supress mask                     domain->data_dim.getValue()/*,
203  // supress mask                     domain->data_ni.getValue(),
204  // supress mask                     domain->data_nj.getValue(),
205  // supress mask                     domain->data_ibegin.getValue(),
206  // supress mask                     domain->data_jbegin.getValue()*/);
207  // supress mask               }
208
209                 //SuperClassWriter::setDefaultValue(maskid, &dvm);
210
211                 if (domain->hasArea)
212                 {
213                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
214                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
215                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
216                 }
217
218                 SuperClassWriter::definition_end();
219
220                 switch (domain->type)
221                 {
222                   case CDomain::type_attr::curvilinear :
223                     SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0);
224                     SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0);
225                     break;
226                   case CDomain::type_attr::regular :
227                     CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;
228                     SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0);
229                     CArray<double,1> lon=domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;
230                     SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0);
231                     break;
232                 }
233
234                 if (domain->hasBounds)
235                 {
236                   SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0);
237                   SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0);
238                 }
239
240                 if (domain->hasArea)
241                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0);
242
243                 SuperClassWriter::definition_start();
244
245                 break;
246              }
247              case (ONE_FILE) :
248              {
249                 SuperClassWriter::addDimension(dimXid, domain->zoom_ni.getValue());
250                 SuperClassWriter::addDimension(dimYid, domain->zoom_nj.getValue());
251
252                 if (domain->hasBounds)
253                   SuperClassWriter::addDimension(dimVertId, domain->nvertex);
254
255                 switch (domain->type)
256                 {
257                   case CDomain::type_attr::curvilinear :
258                     dim0.push_back(dimYid); dim0.push_back(dimXid);
259                     lonid = StdString("nav_lon").append(appendDomid);
260                     latid = StdString("nav_lat").append(appendDomid);
261                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
262                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
263                     break;
264
265                   case CDomain::type_attr::regular :
266                     dim0.push_back(dimYid);
267                     dim1.push_back(dimXid);
268                     lonid = StdString("lon").append(appendDomid);
269                     latid = StdString("lat").append(appendDomid);
270                     SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
271                     SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
272                     break;
273                 }
274
275                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
276                 bounds_latid = StdString("bounds_lat").append(appendDomid);
277
278                 if (domain->hasArea)
279                 {
280                   dim0.clear();
281                   dim0.push_back(dimYid); dim0.push_back(dimXid);
282                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
283                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
284                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
285                   dim0.clear();
286                 }
287
288                 this->writeAxisAttributes
289                    (lonid, isRegularDomain ? "X" : "", "longitude", "Longitude", "degrees_east", domid);
290                 this->writeAxisAttributes
291                    (latid, isRegularDomain ? "Y" : "", "latitude", "Latitude", "degrees_north", domid);
292
293                 if (domain->hasBounds)
294                 {
295                   SuperClassWriter::addAttribute("bounds", bounds_lonid, &lonid);
296                   SuperClassWriter::addAttribute("bounds", bounds_latid, &latid);
297
298                   dim0.clear();
299                   dim0.push_back(dimYid);
300                   dim0.push_back(dimXid);
301                   dim0.push_back(dimVertId);
302                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
303                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
304                 }
305
306                 SuperClassWriter::definition_end();
307
308                 switch (domain->type)
309                 {
310                   case CDomain::type_attr::curvilinear :
311                   {
312                     std::vector<StdSize> start(2) ;
313                     std::vector<StdSize> count(2) ;
314                     if (domain->isEmpty())
315                     {
316                       start[0]=0 ; start[1]=0 ;
317                       count[0]=0 ; count[1]=0 ;
318                     }
319                     else
320                     {
321                       start[1]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start [0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
322                       count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
323                     }
324
325                     SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
326                     SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
327                     break;
328                   }
329                   case CDomain::type_attr::regular :
330                   {
331                     std::vector<StdSize> start(1) ;
332                     std::vector<StdSize> count(1) ;
333                     if (domain->isEmpty())
334                     {
335                       start[0]=0 ;
336                       count[0]=0 ;
337                       SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
338                       SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);                 }
339                     else
340                     {
341                       start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
342                       count[0]=domain->zoom_nj_srv ;
343                       CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;
344                       SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0,&start,&count);
345
346                       start[0]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ;
347                       count[0]=domain->zoom_ni_srv ;
348                       CArray<double,1> lon=domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;
349                       SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0,&start,&count);
350                     }
351                     break;
352                   }
353                 }
354
355                 if (domain->hasBounds)
356                 {
357                   std::vector<StdSize> start(3);
358                   std::vector<StdSize> count(3);
359                   if (domain->isEmpty())
360                   {
361                     start[2] = start[1] = start[0] = 0;
362                     count[2] = count[1] = count[0] = 0;
363                   }
364                   else
365                   {
366                     start[2] = 0;
367                     start[1] = domain->zoom_ibegin_srv - domain->zoom_ibegin.getValue();
368                     start[0] = domain->zoom_jbegin_srv - domain->zoom_jbegin.getValue();
369                     count[2] = domain->nvertex;
370                     count[1] = domain->zoom_ni_srv;
371                     count[0] = domain->zoom_nj_srv;
372                   }
373
374                   SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0, &start, &count);
375                   SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0, &start, &count);
376                 }
377
378                 if (domain->hasArea)
379                 {
380                   std::vector<StdSize> start(2);
381                   std::vector<StdSize> count(2);
382
383                   if (domain->isEmpty())
384                   {
385                     start[0] = 0; start[1] = 0;
386                     count[0] = 0; count[1] = 0;
387                   }
388                   else
389                   {
390                     start[1] = domain->zoom_ibegin_srv - domain->zoom_ibegin.getValue();
391                     start[0] = domain->zoom_jbegin_srv - domain->zoom_jbegin.getValue();
392                     count[1] = domain->zoom_ni_srv;
393                     count[0] = domain->zoom_nj_srv;
394                   }
395
396                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0, &start, &count);
397                 }
398
399                 SuperClassWriter::definition_start();
400
401                 break;
402              }
403              default :
404                 ERROR("CNc4DataOutput::writeDomain(domain)",
405                       << "[ type = " << SuperClass::type << "]"
406                       << " not implemented yet !");
407           }
408         }
409         catch (CNetCdfException& e)
410         {
411           StdString msg("On writing the domain : ");
412           msg.append(domid); msg.append("\n");
413           msg.append("In the context : ");
414           msg.append(context->getId()); msg.append("\n");
415           msg.append(e.what());
416           ERROR("CNc4DataOutput::writeDomain_(CDomain* domain)", << msg);
417         }
418
419         domain->addRelFile(this->filename);
420      }
421
422      void CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)
423      {
424         CContext* context = CContext::getCurrent() ;
425         CContextServer* server=context->server ;
426
427         if (domain->IsWritten(this->filename)) return;
428         domain->checkAttributes();
429
430         if (domain->isEmpty())
431           if (SuperClass::type==MULTI_FILE) return ;
432
433         std::vector<StdString> dim0, dim1;
434         StdString domid     = (!domain->name.isEmpty())
435                             ? domain->name.getValue() : domain->getId();
436         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
437
438
439         StdString dimXid = StdString("cell").append(appendDomid);
440         StdString dimVertId = StdString("nvertex").append(appendDomid);
441
442         string lonid,latid,bounds_lonid,bounds_latid ;
443         string areaId = "area" + appendDomid;
444
445         try
446         {
447           switch (SuperClass::type)
448           {
449              case (MULTI_FILE) :
450              {
451                 lonid = StdString("lon").append(appendDomid);
452                 latid = StdString("lat").append(appendDomid);
453                 dim0.push_back(dimXid);
454
455                 SuperClassWriter::addDimension(dimXid, domain->zoom_nj_srv);
456                 SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
457                 SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
458
459                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
460                 bounds_latid = StdString("bounds_lat").append(appendDomid);
461
462
463                 this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid);
464                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
465                 this->writeAxisAttributes(latid, "", "latitude", "Latitude", "degrees_north", domid);
466                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
467                 if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
468                 dim0.clear();
469                 if (domain->hasBounds)
470                 {
471                   dim0.push_back(dimXid);
472                   dim0.push_back(dimVertId);
473                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
474                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
475                 }
476
477                 dim0.clear();
478                 dim0.push_back(dimXid);
479
480                 if (domain->hasArea)
481                 {
482                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
483                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
484                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
485                 }
486
487                 SuperClassWriter::definition_end();
488
489                 SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0);
490                 SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0);
491
492                 if (domain->hasBounds)
493                 {
494                   SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0);
495                   SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0);
496                 }
497
498                 if (domain->hasArea)
499                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0);
500
501                 SuperClassWriter::definition_start();
502                 break ;
503              }
504
505              case (ONE_FILE) :
506              {
507                 lonid = StdString("lon").append(appendDomid);
508                 latid = StdString("lat").append(appendDomid);
509                 bounds_lonid = StdString("bounds_lon").append(appendDomid);
510                 bounds_latid = StdString("bounds_lat").append(appendDomid);
511                 dim0.push_back(dimXid);
512                 SuperClassWriter::addDimension(dimXid, domain->nj_glo);
513                 SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
514                 SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
515                 this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid);
516                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
517                 this->writeAxisAttributes(latid, "", "latitude", "Latitude", "degrees_north", domid);
518                 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
519                 if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
520                 dim0.clear();
521
522                 if (domain->hasBounds)
523                 {
524                   dim0.push_back(dimXid);
525                   dim0.push_back(dimVertId);
526                   SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
527                   SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
528                 }
529
530                 if (domain->hasArea)
531                 {
532                   dim0.clear();
533                   dim0.push_back(dimXid);
534                   SuperClassWriter::addVariable(areaId, NC_FLOAT, dim0);
535                   SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId);
536                   SuperClassWriter::addAttribute("units", StdString("m2"), &areaId);
537                 }
538
539                 SuperClassWriter::definition_end();
540
541                 std::vector<StdSize> start(1), startBounds(2) ;
542                 std::vector<StdSize> count(1), countBounds(2) ;
543                 if (domain->isEmpty())
544                 {
545                   start[0]=0 ;
546                   count[0]=0 ;
547                   startBounds[1]=0 ;
548                   countBounds[1]=domain->nvertex ;
549                   startBounds[0]=0 ;
550                   countBounds[0]=0 ;
551                 }
552                 else
553                 {
554                   start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin ;
555                   count[0]=domain->zoom_nj_srv ;
556                   startBounds[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin ;
557                   startBounds[1]=0 ;
558                   countBounds[0]=domain->zoom_nj_srv ;
559                   countBounds[1]=domain->nvertex ;
560                 }
561                 SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
562                 SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
563                 if (domain->hasBounds)
564                 {
565                   SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0,&startBounds,&countBounds);
566                   SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0,&startBounds,&countBounds);
567                 }
568
569                 if (domain->hasArea)
570                   SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0, &start, &count);
571
572                 SuperClassWriter::definition_start();
573
574                 break;
575              }
576              default :
577                 ERROR("CNc4DataOutput::writeDomain(domain)",
578                       << "[ type = " << SuperClass::type << "]"
579                       << " not implemented yet !");
580           }
581         }
582         catch (CNetCdfException& e)
583         {
584           StdString msg("On writing the domain : ");
585           msg.append(domid); msg.append("\n");
586           msg.append("In the context : ");
587           msg.append(context->getId()); msg.append("\n");
588           msg.append(e.what());
589           ERROR("CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)", << msg);
590         }
591         domain->addRelFile(this->filename);
592      }
593      //--------------------------------------------------------------
594
595      void CNc4DataOutput::writeAxis_(CAxis* axis)
596      {
597         if (axis->IsWritten(this->filename)) return;
598         axis->checkAttributes();
599         int zoom_size = axis->zoom_size.getValue();
600         int zoom_begin = axis->zoom_begin.getValue() - 1;
601
602
603         std::vector<StdString> dims;
604         StdString axisid = (!axis->name.isEmpty())
605                           ? axis->name.getValue() : axis->getId();
606         try
607         {
608           SuperClassWriter::addDimension(axisid, zoom_size);
609           dims.push_back(axisid);
610
611           switch (SuperClass::type)
612           {
613              case (MULTI_FILE ) :
614              {}
615              case (ONE_FILE) :
616              {
617                 SuperClassWriter::addVariable(axisid, NC_FLOAT, dims);
618
619                 if (!axis->standard_name.isEmpty())
620                    SuperClassWriter::addAttribute
621                       ("standard_name",  axis->standard_name.getValue(), &axisid);
622
623                 if (!axis->long_name.isEmpty())
624                    SuperClassWriter::addAttribute
625                       ("long_name", axis->long_name.getValue(), &axisid);
626
627                 if (!axis->unit.isEmpty())
628                    SuperClassWriter::addAttribute
629                       ("units", axis->unit.getValue(), &axisid);
630
631                 if (!axis->positive.isEmpty())
632                 {
633                   SuperClassWriter::addAttribute("axis", string("Z"), &axisid);
634                   SuperClassWriter::addAttribute("positive",
635                                                  (axis->positive == CAxis::positive_attr::up) ? string("up") : string("down"),
636                                                  &axisid);
637                 }
638
639                 StdString axisBoundsId = axisid + "_bounds";
640                 if (!axis->bounds.isEmpty())
641                 {
642                   dims.push_back("axis_nbounds");
643                   SuperClassWriter::addVariable(axisBoundsId, NC_FLOAT, dims);
644                   SuperClassWriter::addAttribute("bounds", axisBoundsId, &axisid);
645                 }
646
647                 SuperClassWriter::definition_end();
648
649                 CArray<double,1> axis_value(zoom_size);
650                 for(int i = 0 ; i < zoom_size; i++) axis_value(i) = axis->value(i+zoom_begin);
651                 SuperClassWriter::writeData(axis_value, axisid, isCollective, 0);
652
653                 if (!axis->bounds.isEmpty())
654                 {
655                   CArray<double,2> axisBounds(2, zoom_size);
656                   for (int i = 0; i < zoom_size; i++)
657                   {
658                     axisBounds(0, i) = axis->bounds(i + zoom_begin, 0);
659                     axisBounds(1, i) = axis->bounds(i + zoom_begin, 1);
660                   }
661                   SuperClassWriter::writeData(axisBounds, axisBoundsId, isCollective, 0);
662                 }
663
664                 SuperClassWriter::definition_start();
665
666                 break;
667              }
668              default :
669                 ERROR("CNc4DataOutput::writeDomain(domain)",
670                       << "[ type = " << SuperClass::type << "]"
671                       << " not implemented yet !");
672           }
673         }
674         catch (CNetCdfException& e)
675         {
676           StdString msg("On writing the axis : ");
677           msg.append(axisid); msg.append("\n");
678           msg.append("In the context : ");
679           CContext* context = CContext::getCurrent() ;
680           msg.append(context->getId()); msg.append("\n");
681           msg.append(e.what());
682           ERROR("CNc4DataOutput::writeAxis_(CAxis* axis)", << msg);
683         }
684         axis->addRelFile(this->filename);
685     }
686
687     void CNc4DataOutput::writeTimeDimension_(void)
688     {
689       try
690       {
691         SuperClassWriter::addDimension("time_counter");
692       }
693       catch (CNetCdfException& e)
694       {
695         StdString msg("On writing time dimension : time_couter\n");
696         msg.append("In the context : ");
697         CContext* context = CContext::getCurrent() ;
698         msg.append(context->getId()); msg.append("\n");
699         msg.append(e.what());
700         ERROR("CNc4DataOutput::writeTimeDimension_(void)", << msg);
701       }
702     }
703      //--------------------------------------------------------------
704
705      void CNc4DataOutput::writeField_(CField* field)
706      {
707         CContext* context = CContext::getCurrent() ;
708         CContextServer* server=context->server ;
709
710         std::vector<StdString> dims, coodinates;
711         CGrid* grid = field->grid;
712         CDomain* domain = grid->domain;
713
714         if (domain->isEmpty())
715           if (SuperClass::type==MULTI_FILE) return ;
716
717         StdString timeid    = StdString("time_counter");
718         StdString domid     = (!domain->name.isEmpty())
719                             ? domain->name.getValue() : domain->getId();
720         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
721
722//         bool isCurvilinear = domain->isCurvilinear ;
723//         bool isCurvilinear = (domain->type == CDomain::type_attr::curvilinear) ;
724
725         StdString dimXid,dimYid ;
726
727         switch (domain->type)
728         {
729           case CDomain::type_attr::curvilinear :
730             dimXid     = StdString("x").append(appendDomid);
731             dimYid     = StdString("y").append(appendDomid);
732             break ;
733           case CDomain::type_attr::regular :
734             dimXid     = StdString("lon").append(appendDomid);
735             dimYid     = StdString("lat").append(appendDomid);
736             break ;
737           case CDomain::type_attr::unstructured :
738             dimXid     = StdString("cell").append(appendDomid);
739             break ;
740        }
741
742/*
743         StdString lonid_loc = (server->intraCommSize > 1)
744                             ? StdString("lon").append(appendDomid).append("_local")
745                             : lonid;
746         StdString latid_loc = (server->intraCommSize > 1)
747                             ? StdString("lat").append(appendDomid).append("_local")
748                             : latid;
749*/
750         StdString fieldid   = (!field->name.isEmpty())
751                             ? field->name.getValue() : field->getBaseFieldReference()->getId();
752
753//         unsigned int ssize = domain->zoom_ni_loc.getValue() * domain->zoom_nj_loc.getValue();
754//         bool isCurvilinear = (domain->lonvalue.getValue()->size() == ssize);
755//          bool isCurvilinear = domain->isCurvilinear ;
756
757         nc_type type ;
758         if (field->prec.isEmpty()) type =  NC_FLOAT ;
759         else
760         {
761           if (field->prec==2) type = NC_SHORT ;
762           else if (field->prec==4)  type =  NC_FLOAT ;
763           else if (field->prec==8)   type =  NC_DOUBLE ;
764         }
765
766         bool wtime   = !(!field->operation.isEmpty() && field->foperation->timeType() == func::CFunctor::once);
767
768         if (wtime)
769         {
770
771            //StdOStringStream oss;
772           // oss << "time_" << field->operation.getValue()
773           //     << "_" << field->getRelFile()->output_freq.getValue();
774          //oss
775            if (field->foperation->timeType() == func::CFunctor::instant) coodinates.push_back(string("time_instant"));
776            else if (field->foperation->timeType() == func::CFunctor::centered) coodinates.push_back(string("time_centered"));
777            dims.push_back(timeid);
778         }
779
780         if (!grid->axis_ref.isEmpty())
781         {
782            CAxis* axis = grid->axis ;
783            StdString axisid = (!axis->name.isEmpty()) ? axis->name.getValue() : axis->getId();
784            dims.push_back(axisid);
785            coodinates.push_back(axisid);
786         }
787
788         switch (domain->type)
789         {
790           case CDomain::type_attr::curvilinear :
791             coodinates.push_back(StdString("nav_lon").append(appendDomid));
792             coodinates.push_back(StdString("nav_lat").append(appendDomid));
793             break;
794           case CDomain::type_attr::regular :
795           case CDomain::type_attr::unstructured :
796            coodinates.push_back(StdString("lon").append(appendDomid));
797            coodinates.push_back(StdString("lat").append(appendDomid));
798             break;
799         }
800
801         if ( domain->type == CDomain::type_attr::curvilinear || domain->type == CDomain::type_attr::regular)dims.push_back(dimYid);
802         dims.push_back(dimXid);
803
804         try
805         {
806           SuperClassWriter::addVariable(fieldid, type, dims);
807
808           if (!field->standard_name.isEmpty())
809              SuperClassWriter::addAttribute
810                 ("standard_name",  field->standard_name.getValue(), &fieldid);
811
812           if (!field->long_name.isEmpty())
813              SuperClassWriter::addAttribute
814                 ("long_name", field->long_name.getValue(), &fieldid);
815
816           if (!field->unit.isEmpty())
817              SuperClassWriter::addAttribute
818                 ("units", field->unit.getValue(), &fieldid);
819
820            if (!field->valid_min.isEmpty())
821              SuperClassWriter::addAttribute
822                 ("valid_min", field->valid_min.getValue(), &fieldid);
823
824           if (!field->valid_max.isEmpty())
825              SuperClassWriter::addAttribute
826                 ("valid_max", field->valid_max.getValue(), &fieldid);
827
828            if (!field->scale_factor.isEmpty())
829              SuperClassWriter::addAttribute
830                 ("scale_factor", field->scale_factor.getValue(), &fieldid);
831
832             if (!field->add_offset.isEmpty())
833              SuperClassWriter::addAttribute
834                 ("add_offset", field->add_offset.getValue(), &fieldid);
835
836           SuperClassWriter::addAttribute
837                 ("online_operation", field->operation.getValue(), &fieldid);
838
839          // write child variables as attributes
840
841
842           vector<CVariable*> listVars = field->getAllVariables() ;
843           for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ;
844
845
846           if (wtime)
847           {
848              CDuration freqOp = CDuration::FromString(field->freq_op);
849              freqOp.solveTimeStep(*context->calendar);
850              StdString freqOpStr = freqOp.toStringUDUnits();
851              SuperClassWriter::addAttribute("interval_operation", freqOpStr, &fieldid);
852
853              CDuration freqOut = CDuration::FromString(field->getRelFile()->output_freq);
854              freqOut.solveTimeStep(*context->calendar);
855              SuperClassWriter::addAttribute("interval_write", freqOut.toStringUDUnits(), &fieldid);
856
857              StdString cellMethods = "time: ";
858              if (field->operation.getValue() == "instant") cellMethods += "point";
859              else if (field->operation.getValue() == "average") cellMethods += "mean";
860              else if (field->operation.getValue() == "accumulate") cellMethods += "sum";
861              else cellMethods += field->operation;
862              if (freqOp.resolve(*context->calendar) != freqOut.resolve(*context->calendar))
863                cellMethods += " (interval: " + freqOpStr + ")";
864              SuperClassWriter::addAttribute("cell_methods", cellMethods, &fieldid);
865           }
866
867           if (domain->hasArea)
868             SuperClassWriter::addAttribute("cell_measures", "area: area" + appendDomid, &fieldid);
869
870           if (!field->default_value.isEmpty())
871           {
872              double default_value = field->default_value.getValue();
873              float fdefault_value = (float)default_value;
874              if (type == NC_DOUBLE)
875                 SuperClassWriter::setDefaultValue(fieldid, &default_value);
876              else
877                 SuperClassWriter::setDefaultValue(fieldid, &fdefault_value);
878           }
879           else
880           {
881              double * default_value = NULL;
882              SuperClassWriter::setDefaultValue(fieldid, default_value);
883           }
884
885           if (field->compression_level.isEmpty())
886             field->compression_level = field->file->compression_level.isEmpty() ? 0 : field->file->compression_level;
887           SuperClassWriter::setCompressionLevel(fieldid, field->compression_level);
888
889           {  // Ecriture des coordonnées
890
891              StdString coordstr; //boost::algorithm::join(coodinates, " ")
892              std::vector<StdString>::iterator
893                 itc = coodinates.begin(), endc = coodinates.end();
894
895              for (; itc!= endc; itc++)
896              {
897                 StdString & coord = *itc;
898                 if (itc+1 != endc)
899                       coordstr.append(coord).append(" ");
900                 else  coordstr.append(coord);
901              }
902
903              SuperClassWriter::addAttribute("coordinates", coordstr, &fieldid);
904
905           }
906         }
907         catch (CNetCdfException& e)
908         {
909           StdString msg("On writing field : ");
910           msg.append(fieldid); msg.append("\n");
911           msg.append("In the context : ");
912           msg.append(context->getId()); msg.append("\n");
913           msg.append(e.what());
914           ERROR("CNc4DataOutput::writeField_(CField* field)", << msg);
915         }
916      }
917
918      //--------------------------------------------------------------
919
920      void CNc4DataOutput::writeFile_ (CFile* file)
921      {
922         StdString filename = (!file->name.isEmpty())
923                            ? file->name.getValue() : file->getId();
924         StdString description = (!file->description.isEmpty())
925                               ? file->description.getValue()
926                               : StdString("Created by xios");
927
928         singleDomain = (file->nbDomains == 1);
929
930         try
931         {
932           this->writeFileAttributes(filename, description,
933                                     StdString("CF-1.5"),
934                                     StdString("An IPSL model"),
935                                     this->getTimeStamp());
936
937           SuperClassWriter::addDimension("axis_nbounds", 2);
938         }
939         catch (CNetCdfException& e)
940         {
941           StdString msg("On writing file : ");
942           msg.append(filename); msg.append("\n");
943           msg.append("In the context : ");
944           CContext* context = CContext::getCurrent() ;
945           msg.append(context->getId()); msg.append("\n");
946           msg.append(e.what());
947           ERROR("CNc4DataOutput::writeFile_ (CFile* file)", << msg);
948         }
949      }
950
951      void CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)
952      {
953        string name ;
954        if (!var->name.isEmpty()) name=var->name ;
955        else if (var->hasId()) name=var->getId() ;
956        else return ;
957
958        try
959        {
960          if (var->getVarType()==CVariable::t_int) addAttribute(name,var->getData<int>(),&fieldId) ;
961          else if (var->getVarType()==CVariable::t_short_int) addAttribute(name,var->getData<short int>(),&fieldId) ;
962          else if (var->getVarType()==CVariable::t_long_int) addAttribute(name,var->getData<long int>(),&fieldId) ;
963          else if (var->getVarType()==CVariable::t_float) addAttribute(name,var->getData<float>(),&fieldId) ;
964          else if (var->getVarType()==CVariable::t_double) addAttribute(name,var->getData<double>(),&fieldId) ;
965          else addAttribute(name,var->getData<string>(),&fieldId) ;
966        }
967       catch (CNetCdfException& e)
968       {
969         StdString msg("On writing attributes of variable with name : ");
970         msg.append(name); msg.append("in the field "); msg.append(fieldId); msg.append("\n");
971         msg.append("In the context : ");
972         CContext* context = CContext::getCurrent() ;
973         msg.append(context->getId()); msg.append("\n");
974         msg.append(e.what());
975         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)", << msg);
976       }
977     }
978
979     void CNc4DataOutput::writeAttribute_ (CVariable* var)
980     {
981        string name ;
982        if (!var->name.isEmpty()) name=var->name ;
983        else if (var->hasId()) name=var->getId() ;
984        else return ;
985        try
986        {
987          if (var->getVarType()==CVariable::t_int) addAttribute(name,var->getData<int>()) ;
988          else if (var->getVarType()==CVariable::t_short_int) addAttribute(name,var->getData<short int>()) ;
989          else if (var->getVarType()==CVariable::t_long_int) addAttribute(name,var->getData<long int>()) ;
990          else if (var->getVarType()==CVariable::t_float) addAttribute(name,var->getData<float>()) ;
991          else if (var->getVarType()==CVariable::t_double) addAttribute(name,var->getData<double>()) ;
992          else addAttribute(name,var->getData<string>()) ;
993        }
994       catch (CNetCdfException& e)
995       {
996         StdString msg("On writing attributes of variable with name : ");
997         msg.append(name); msg.append("\n");
998         msg.append("In the context : ");
999         CContext* context = CContext::getCurrent() ;
1000         msg.append(context->getId()); msg.append("\n");
1001         msg.append(e.what());
1002         ERROR("CNc4DataOutput::writeAttribute_ (CVariable* var)", << msg);
1003       }
1004     }
1005
1006      void CNc4DataOutput::syncFile_ (void)
1007      {
1008        try
1009        {
1010          SuperClassWriter::sync() ;
1011        }
1012        catch (CNetCdfException& e)
1013        {
1014         StdString msg("On synchronizing the write among processes");
1015         msg.append("In the context : ");
1016         CContext* context = CContext::getCurrent() ;
1017         msg.append(context->getId()); msg.append("\n");
1018         msg.append(e.what());
1019         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
1020        }
1021      }
1022
1023      void CNc4DataOutput::closeFile_ (void)
1024      {
1025        try
1026        {
1027          SuperClassWriter::close() ;
1028        }
1029        catch (CNetCdfException& e)
1030        {
1031         StdString msg("On closing file");
1032         msg.append("In the context : ");
1033         CContext* context = CContext::getCurrent() ;
1034         msg.append(context->getId()); msg.append("\n");
1035         msg.append(e.what());
1036         ERROR("CNc4DataOutput::syncFile_ (void)", << msg);
1037        }
1038
1039      }
1040
1041      //---------------------------------------------------------------
1042
1043      StdString CNc4DataOutput::getTimeStamp(void) const
1044      {
1045         const int buffer_size = 100;
1046         time_t rawtime;
1047         struct tm * timeinfo = NULL;
1048         char buffer [buffer_size];
1049
1050         time ( &rawtime );
1051         timeinfo = localtime ( &rawtime );
1052         strftime (buffer, buffer_size, "%Y-%b-%d %H:%M:%S %Z", timeinfo);
1053
1054         return (StdString(buffer));
1055      }
1056
1057      //---------------------------------------------------------------
1058
1059      void CNc4DataOutput::writeFieldData_ (CField*  field)
1060      {
1061         CContext* context = CContext::getCurrent() ;
1062//          if (field->getRelFile()->isSyncTime()) SuperClassWriter::sync() ;
1063         CContextServer* server=context->server ;
1064
1065         CGrid* grid = field->grid ;
1066         CDomain* domain = grid->domain ;
1067
1068         if(SuperClass::type==MULTI_FILE || !isCollective) if (domain->isEmpty()) return;
1069
1070
1071         StdString fieldid   = (!field->name.isEmpty())
1072                             ? field->name.getValue()
1073                             : field->getBaseFieldReference()->getId();
1074
1075         StdOStringStream oss;
1076         string timeAxisId ;
1077         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisId="time_instant" ;
1078         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisId="time_centered" ;
1079
1080         StdString timeBoundId("time_counter_bounds");
1081
1082         StdString timeAxisBoundId;
1083         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisBoundId="time_instant_bounds" ;
1084         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisBoundId="time_centered_bounds" ;
1085
1086         CArray<double,1> time_data(1) ;
1087         CArray<double,1> time_counter(1) ;
1088         CArray<double,1> time_counter_bound(2);
1089         CArray<double,1> time_data_bound(2);
1090
1091        bool wtime   = !(!field->operation.isEmpty() && (field->foperation->timeType() == func::CFunctor::once));
1092
1093        if (wtime)
1094        {
1095          time_counter(0)= (Time(*field->last_Write_srv) + Time(*field->lastlast_Write_srv)) / 2;
1096          if (field->foperation->timeType() == func::CFunctor::instant)
1097            time_data(0) = Time(*field->last_Write_srv);
1098          else if (field->foperation->timeType() == func::CFunctor::centered) time_data(0) = time_counter(0);
1099
1100          time_counter_bound(0) = Time(*field->lastlast_Write_srv);
1101          time_counter_bound(1) = Time(*field->last_Write_srv);
1102          if (field->foperation->timeType() == func::CFunctor::instant)
1103            time_data_bound(0) = time_data_bound(1) = Time(*field->last_Write_srv);
1104          else if (field->foperation->timeType() == func::CFunctor::centered)
1105          {
1106            time_data_bound(0) = time_counter_bound(0);
1107            time_data_bound(1) = time_counter_bound(1);
1108          }
1109         }
1110
1111         bool isRoot ;
1112         if (server->intraCommRank==0) isRoot=true ;
1113         else isRoot=false ;
1114
1115         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
1116         {
1117           double scaleFactor=1. ;
1118           double addOffset=0. ;
1119           if (!field->scale_factor.isEmpty()) scaleFactor=field->scale_factor ;
1120           if (!field->add_offset.isEmpty()) addOffset=field->add_offset ;
1121           field->scaleFactorAddOffset(scaleFactor,addOffset) ;
1122         }
1123
1124         try
1125         {
1126           if (grid->hasAxis()) // 3D
1127           {
1128              CAxis* axis = grid->axis ;
1129              CArray<double,3> field_data3D(domain->zoom_ni_srv,domain->zoom_nj_srv,axis->zoom_size) ;
1130              if (!field->default_value.isEmpty()) field_data3D = field->default_value ;
1131
1132              field->outputField(field_data3D);
1133
1134              if (!field->prec.isEmpty() && field->prec==2) field_data3D=round(field_data3D) ;
1135
1136              switch (SuperClass::type)
1137             {
1138                case (MULTI_FILE) :
1139                {
1140                   SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep()-1);
1141                   if (wtime)
1142                   {
1143                     SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep()-1);
1144                     SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep()-1);
1145                     SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1);
1146                     SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1);
1147                   }
1148                   break ;
1149                }
1150                case (ONE_FILE) :
1151                {
1152                   std::vector<StdSize> start(3) ;
1153                   std::vector<StdSize> count(3) ;
1154                   if (domain->isEmpty())
1155                   {
1156                     start[0]=0 ; start[1]=0 ; start[2]=0 ;
1157                     count[0]=0 ; count[1]=0 ; start[2]=0 ;
1158                   }
1159                   else
1160                   {
1161  //                 start[2]=domain->zoom_ibegin_loc.getValue()-domain->zoom_ibegin.getValue() ; start [1]=domain->zoom_jbegin_loc.getValue()-domain->zoom_jbegin.getValue() ; start[0]=0 ;
1162                     start[2]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start [1]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ; start[0]=0 ;
1163                     count[2]=domain->zoom_ni_srv ; count[1]=domain->zoom_nj_srv ; count[0] = axis->zoom_size.getValue();
1164                   }
1165                   SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep()-1,&start,&count );
1166                   if (wtime)
1167                   {
1168                     SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot );
1169                     SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot );
1170                     SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot );
1171                     SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot);
1172                   }
1173                   break;
1174                }
1175              }
1176
1177           }
1178           else // 2D
1179           {
1180              CArray<double,2> field_data2D(domain->zoom_ni_srv,domain->zoom_nj_srv) ;
1181              if (!field->default_value.isEmpty()) field_data2D = field->default_value ;
1182              field->outputField(field_data2D);
1183              if (!field->prec.isEmpty() && field->prec==2) field_data2D=round(field_data2D) ;
1184              switch (SuperClass::type)
1185              {
1186                case (MULTI_FILE) :
1187                {
1188                  SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep()-1);
1189                  if (wtime)
1190                  {
1191                    SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep()-1);
1192                    SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep()-1);
1193                    SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1);
1194                    SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1);
1195                  }
1196                  break;
1197                }
1198                case (ONE_FILE) :
1199                {
1200                   std::vector<StdSize> start(2) ;
1201                   std::vector<StdSize> count(2) ;
1202                   if (domain->isEmpty())
1203                   {
1204                     start[0]=0 ; start[1]=0 ;
1205                     count[0]=0 ; count[1]=0 ;
1206                   }
1207                   else
1208                   {
1209                     start[1]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
1210                     count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
1211                   }
1212
1213                   SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep()-1,&start,&count);
1214                   if (wtime)
1215                   {
1216                     SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot);
1217                     SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot);
1218                     SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot);
1219                     SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot);
1220                   }
1221                   break;
1222
1223                }
1224              }
1225           }
1226         }
1227         catch (CNetCdfException& e)
1228         {
1229           StdString msg("On writing field data: ");
1230           msg.append(fieldid); msg.append("\n");
1231           msg.append("In the context : ");
1232           msg.append(context->getId()); msg.append("\n");
1233           msg.append(e.what());
1234           ERROR("CNc4DataOutput::writeFieldData_ (CField*  field)", << msg);
1235         }
1236      }
1237
1238      //---------------------------------------------------------------
1239
1240      void CNc4DataOutput::writeTimeAxis_
1241                  (CField*    field,
1242                   const boost::shared_ptr<CCalendar> cal)
1243      {
1244         StdOStringStream oss;
1245
1246//         if (field->operation.getValue().compare("once") == 0) return ;
1247         if (field->foperation->timeType() == func::CFunctor::once) return ;
1248
1249//         oss << "time_" << field->operation.getValue()
1250//             << "_" << field->getRelFile()->output_freq.getValue();
1251
1252//         StdString axisid = oss.str();
1253//         if (field->foperation->timeType() == func::CFunctor::centered) axisid="time_centered" ;
1254//         else if (field->foperation->timeType() == func::CFunctor::instant) axisid="time_instant" ;
1255
1256         StdString axisid("time_centered") ;
1257         StdString axisBoundId("time_centered_bounds");
1258         StdString timeid("time_counter");
1259         StdString timeBoundId("axis_nbounds");
1260
1261         if (field->foperation->timeType() == func::CFunctor::instant)
1262         {
1263            axisid = "time_instant";
1264            axisBoundId = "time_instant_bounds";
1265         }
1266
1267         try
1268         {
1269          // Adding time_instant or time_centered
1270           std::vector<StdString> dims;
1271           dims.push_back(timeid);
1272           if (!SuperClassWriter::varExist(axisid))
1273           {
1274              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1275
1276              CDate timeOrigin=cal->getTimeOrigin() ;
1277              StdOStringStream oss2;
1278  //            oss2<<initDate.getYear()<<"-"<<initDate.getMonth()<<"-"<<initDate.getDay()<<" "
1279  //                <<initDate.getHour()<<"-"<<initDate.getMinute()<<"-"<<initDate.getSecond() ;
1280              StdString strInitdate=oss2.str() ;
1281              StdString strTimeOrigin=timeOrigin.toString() ;
1282              this->writeTimeAxisAttributes
1283                 (axisid, cal->getType(),
1284                  StdString("seconds since ").append(strTimeOrigin),
1285                  strTimeOrigin, axisBoundId);
1286           }
1287
1288           // Adding time_instant_bounds or time_centered_bounds variables
1289           if (!SuperClassWriter::varExist(axisBoundId))
1290           {
1291              dims.clear() ;
1292              dims.push_back(timeid);
1293              dims.push_back(timeBoundId);
1294              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1295           }
1296
1297           // Adding time_counter
1298           axisid = "time_counter" ;
1299           axisBoundId = "time_counter_bounds" ;
1300           dims.clear() ;
1301           dims.push_back(timeid);
1302           if (!SuperClassWriter::varExist(axisid))
1303           {
1304              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1305              SuperClassWriter::addAttribute("axis", string("T"), &axisid);
1306              CDate timeOrigin=cal->getTimeOrigin() ;
1307              StdString strTimeOrigin=timeOrigin.toString() ;
1308
1309              this->writeTimeAxisAttributes
1310                 (axisid, cal->getType(),
1311                  StdString("seconds since ").append(strTimeOrigin),
1312                  strTimeOrigin, axisBoundId);
1313           }
1314
1315           // Adding time_counter_bound dimension
1316           if (!SuperClassWriter::varExist(axisBoundId))
1317           {
1318              dims.clear();
1319              dims.push_back(timeid);
1320              dims.push_back(timeBoundId);
1321              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1322           }
1323         }
1324         catch (CNetCdfException& e)
1325         {
1326           StdString msg("On writing time axis data: ");
1327           msg.append("In the context : ");
1328           CContext* context = CContext::getCurrent() ;
1329           msg.append(context->getId()); msg.append("\n");
1330           msg.append(e.what());
1331           ERROR("CNc4DataOutput::writeTimeAxis_ (CField*    field, \
1332                  const boost::shared_ptr<CCalendar> cal)", << msg);
1333         }
1334      }
1335
1336      //---------------------------------------------------------------
1337
1338      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
1339                                                   const StdString & calendar,
1340                                                   const StdString & units,
1341                                                   const StdString & time_origin,
1342                                                   const StdString & time_bounds,
1343                                                   const StdString & standard_name,
1344                                                   const StdString & long_name)
1345      {
1346         try
1347         {
1348           SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1349           SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
1350           SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
1351           SuperClassWriter::addAttribute("units",         units        , &axis_name);
1352           SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
1353           SuperClassWriter::addAttribute("bounds",        time_bounds  , &axis_name);
1354         }
1355         catch (CNetCdfException& e)
1356         {
1357           StdString msg("On writing time axis Attribute: ");
1358           msg.append("In the context : ");
1359           CContext* context = CContext::getCurrent() ;
1360           msg.append(context->getId()); msg.append("\n");
1361           msg.append(e.what());
1362           ERROR("CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name, \
1363                                                          const StdString & calendar,\
1364                                                          const StdString & units, \
1365                                                          const StdString & time_origin, \
1366                                                          const StdString & time_bounds, \
1367                                                          const StdString & standard_name, \
1368                                                          const StdString & long_name)", << msg);
1369         }
1370      }
1371
1372      //---------------------------------------------------------------
1373
1374      void CNc4DataOutput::writeAxisAttributes(const StdString & axis_name,
1375                                               const StdString & axis,
1376                                               const StdString & standard_name,
1377                                               const StdString & long_name,
1378                                               const StdString & units,
1379                                               const StdString & nav_model)
1380      {
1381         try
1382         {
1383          if (!axis.empty())
1384            SuperClassWriter::addAttribute("axis"       , axis         , &axis_name);
1385
1386          SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1387          SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
1388          SuperClassWriter::addAttribute("units"        , units        , &axis_name);
1389          SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
1390         }
1391         catch (CNetCdfException& e)
1392         {
1393           StdString msg("On writing Axis Attribute: ");
1394           msg.append("In the context : ");
1395           CContext* context = CContext::getCurrent() ;
1396           msg.append(context->getId()); msg.append("\n");
1397           msg.append(e.what());
1398           ERROR("CNc4DataOutput::writeAxisAttributes(const StdString & axis_name, \
1399                                                      const StdString & axis, \
1400                                                      const StdString & standard_name, \
1401                                                      const StdString & long_name, \
1402                                                      const StdString & units, \
1403                                                      const StdString & nav_model)", << msg);
1404         }
1405      }
1406
1407      //---------------------------------------------------------------
1408
1409      void CNc4DataOutput::writeLocalAttributes
1410         (int ibegin, int ni, int jbegin, int nj, StdString domid)
1411      {
1412        try
1413        {
1414         SuperClassWriter::addAttribute(StdString("ibegin").append(domid), ibegin);
1415         SuperClassWriter::addAttribute(StdString("ni"    ).append(domid), ni);
1416         SuperClassWriter::addAttribute(StdString("jbegin").append(domid), jbegin);
1417         SuperClassWriter::addAttribute(StdString("nj"    ).append(domid), nj);
1418        }
1419        catch (CNetCdfException& e)
1420        {
1421           StdString msg("On writing Local Attributes: ");
1422           msg.append("In the context : ");
1423           CContext* context = CContext::getCurrent() ;
1424           msg.append(context->getId()); msg.append("\n");
1425           msg.append(e.what());
1426           ERROR("CNc4DataOutput::writeLocalAttributes \
1427                  (int ibegin, int ni, int jbegin, int nj, StdString domid)", << msg);
1428        }
1429
1430      }
1431
1432     void CNc4DataOutput::writeLocalAttributes_IOIPSL
1433         (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)
1434      {
1435         CArray<int,1> array(2) ;
1436
1437         try
1438         {
1439           SuperClassWriter::addAttribute("DOMAIN_number_total",size ) ;
1440           SuperClassWriter::addAttribute("DOMAIN_number", rank) ;
1441           array=1,2 ;
1442           SuperClassWriter::addAttribute("DOMAIN_dimensions_ids",array) ;
1443           array=ni_glo,nj_glo ;
1444           SuperClassWriter::addAttribute("DOMAIN_size_global", array) ;
1445           array=ni,nj ;
1446           SuperClassWriter::addAttribute("DOMAIN_size_local", array) ;
1447           array=ibegin,jbegin ;
1448           SuperClassWriter::addAttribute("DOMAIN_position_first", array) ;
1449           array=ibegin+ni-1,jbegin+nj-1 ;
1450           SuperClassWriter::addAttribute("DOMAIN_position_last",array) ;
1451           array=0,0 ;
1452           SuperClassWriter::addAttribute("DOMAIN_halo_size_start", array) ;
1453           SuperClassWriter::addAttribute("DOMAIN_halo_size_end", array);
1454           SuperClassWriter::addAttribute("DOMAIN_type",string("box")) ;
1455  /*
1456           SuperClassWriter::addAttribute("DOMAIN_DIM_N001",string("x")) ;
1457           SuperClassWriter::addAttribute("DOMAIN_DIM_N002",string("y")) ;
1458           SuperClassWriter::addAttribute("DOMAIN_DIM_N003",string("axis_A")) ;
1459           SuperClassWriter::addAttribute("DOMAIN_DIM_N004",string("time_counter")) ;
1460  */
1461         }
1462         catch (CNetCdfException& e)
1463         {
1464           StdString msg("On writing Local Attributes IOI PSL \n");
1465           msg.append("In the context : ");
1466           CContext* context = CContext::getCurrent() ;
1467           msg.append(context->getId()); msg.append("\n");
1468           msg.append(e.what());
1469           ERROR("CNc4DataOutput::writeLocalAttributes_IOIPSL \
1470                  (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)", << msg);
1471         }
1472      }
1473      //---------------------------------------------------------------
1474
1475      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
1476                                                const StdString & description,
1477                                                const StdString & conventions,
1478                                                const StdString & production,
1479                                                const StdString & timeStamp)
1480      {
1481         try
1482         {
1483           SuperClassWriter::addAttribute("name"       , name);
1484           SuperClassWriter::addAttribute("description", description);
1485           SuperClassWriter::addAttribute("title"      , description);
1486           SuperClassWriter::addAttribute("Conventions", conventions);
1487           SuperClassWriter::addAttribute("production" , production);
1488           SuperClassWriter::addAttribute("timeStamp"  , timeStamp);
1489         }
1490         catch (CNetCdfException& e)
1491         {
1492           StdString msg("On writing File Attributes \n ");
1493           msg.append("In the context : ");
1494           CContext* context = CContext::getCurrent() ;
1495           msg.append(context->getId()); msg.append("\n");
1496           msg.append(e.what());
1497           ERROR("CNc4DataOutput:: writeFileAttributes(const StdString & name, \
1498                                                const StdString & description, \
1499                                                const StdString & conventions, \
1500                                                const StdString & production, \
1501                                                const StdString & timeStamp)", << msg);
1502         }
1503      }
1504
1505      //---------------------------------------------------------------
1506
1507      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
1508                                               int data_dim,
1509                                               int data_ni,
1510                                               int data_nj,
1511                                               int data_ibegin,
1512                                               int data_jbegin)
1513      {
1514         try
1515         {
1516           SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
1517           SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
1518           SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
1519           SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
1520           SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
1521         }
1522         catch (CNetCdfException& e)
1523         {
1524           StdString msg("On writing Mask Attributes \n ");
1525           msg.append("In the context : ");
1526           CContext* context = CContext::getCurrent() ;
1527           msg.append(context->getId()); msg.append("\n");
1528           msg.append(e.what());
1529           ERROR("CNc4DataOutput::writeMaskAttributes(const StdString & mask_name, \
1530                                               int data_dim, \
1531                                               int data_ni, \
1532                                               int data_nj, \
1533                                               int data_ibegin, \
1534                                               int data_jbegin)", << msg);
1535         }
1536      }
1537
1538      ///--------------------------------------------------------------
1539
1540} // namespace xios
Note: See TracBrowser for help on using the repository browser.