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

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

Fix r628: "DOMAIN_dimensions_ids" should use Fortran indexing.

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