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

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

Fix axis bounds: the dimensions were reversed.

  • 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: 68.1 KB
Line 
1
2#include "nc4_data_output.hpp"
3
4#include <boost/lexical_cast.hpp>
5#include "attribute_template.hpp"
6#include "group_template.hpp"
7
8#include "file.hpp"
9#include "calendar.hpp"
10#include "context.hpp"
11#include "context_server.hpp"
12#include "netCdfException.hpp"
13#include "exception.hpp"
14
15namespace xios
16{
17      /// ////////////////////// Définitions ////////////////////// ///
18      CNc4DataOutput::CNc4DataOutput
19         (const StdString & filename, bool exist)
20            : SuperClass()
21            , SuperClassWriter(filename, exist)
22            , filename(filename)
23      {
24         StdString timeid = StdString("time_counter");
25         SuperClass::type = MULTI_FILE;
26//         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(0, i + zoom_begin);
661                     axisBounds(1, i) = axis->bounds(1, i + zoom_begin);
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_data_bound(2);
1090         CArray<double,1> time_counter(1) ;
1091         CArray<double,1> time_counter_bound(2);
1092
1093        bool wtime   = !(!field->operation.isEmpty() && (field->foperation->timeType() == func::CFunctor::once));
1094
1095        if (wtime)
1096        {
1097          Time lastWrite = *field->last_Write_srv;
1098          Time lastLastWrite = *field->lastlast_Write_srv;
1099
1100          if (field->foperation->timeType() == func::CFunctor::instant)
1101            time_data(0) = lastWrite;
1102          else if (field->foperation->timeType() == func::CFunctor::centered)
1103            time_data(0) = (lastWrite + lastLastWrite) / 2;
1104
1105          if (field->foperation->timeType() == func::CFunctor::instant)
1106            time_data_bound(0) = time_data_bound(1) = lastWrite;
1107          else if (field->foperation->timeType() == func::CFunctor::centered)
1108          {
1109            time_data_bound(0) = lastLastWrite;
1110            time_data_bound(1) = lastWrite;
1111          }
1112
1113          if (field->file->time_counter == CFile::time_counter_attr::instant)
1114            time_counter(0) = lastWrite;
1115          else if (field->file->time_counter == CFile::time_counter_attr::centered)
1116            time_counter(0) = (lastWrite + lastLastWrite) / 2;
1117          else if (field->file->time_counter == CFile::time_counter_attr::record)
1118            time_counter(0) = field->getNStep() - 1;
1119
1120
1121          if (field->file->time_counter == CFile::time_counter_attr::instant)
1122            time_counter_bound(0) = time_counter_bound(1) = lastWrite;
1123          else if (field->file->time_counter == CFile::time_counter_attr::centered)
1124          {
1125            time_counter_bound(0) = lastLastWrite;
1126            time_counter_bound(1) = lastWrite;
1127          }
1128          else if (field->file->time_counter == CFile::time_counter_attr::record)
1129            time_counter_bound(0) = time_counter_bound(1) = field->getNStep() - 1;
1130         }
1131
1132         bool isRoot ;
1133         if (server->intraCommRank==0) isRoot=true ;
1134         else isRoot=false ;
1135
1136         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
1137         {
1138           double scaleFactor=1. ;
1139           double addOffset=0. ;
1140           if (!field->scale_factor.isEmpty()) scaleFactor=field->scale_factor ;
1141           if (!field->add_offset.isEmpty()) addOffset=field->add_offset ;
1142           field->scaleFactorAddOffset(scaleFactor,addOffset) ;
1143         }
1144
1145         try
1146         {
1147           if (grid->hasAxis()) // 3D
1148           {
1149              CAxis* axis = grid->axis ;
1150              CArray<double,3> field_data3D(domain->zoom_ni_srv,domain->zoom_nj_srv,axis->zoom_size) ;
1151              if (!field->default_value.isEmpty()) field_data3D = field->default_value ;
1152
1153              field->outputField(field_data3D);
1154
1155              if (!field->prec.isEmpty() && field->prec==2) field_data3D=round(field_data3D) ;
1156
1157              switch (SuperClass::type)
1158             {
1159                case (MULTI_FILE) :
1160                {
1161                   SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep() - 1);
1162                   if (wtime)
1163                   {
1164                     SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep() - 1);
1165                     SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1);
1166                     if (field->file->time_counter != CFile::time_counter_attr::none)
1167                     {
1168                       SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep() - 1);
1169                       if (field->file->time_counter != CFile::time_counter_attr::record)
1170                         SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1);
1171                     }
1172                   }
1173                   break ;
1174                }
1175                case (ONE_FILE) :
1176                {
1177                   std::vector<StdSize> start(3) ;
1178                   std::vector<StdSize> count(3) ;
1179                   if (domain->isEmpty())
1180                   {
1181                     start[0]=0 ; start[1]=0 ; start[2]=0 ;
1182                     count[0]=0 ; count[1]=0 ; start[2]=0 ;
1183                   }
1184                   else
1185                   {
1186  //                 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 ;
1187                     start[2]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start [1]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ; start[0]=0 ;
1188                     count[2]=domain->zoom_ni_srv ; count[1]=domain->zoom_nj_srv ; count[0] = axis->zoom_size.getValue();
1189                   }
1190                   SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep() - 1, &start, &count);
1191                   if (wtime)
1192                   {
1193                     SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep() - 1, isRoot);
1194                     SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1, isRoot);
1195                     if (field->file->time_counter != CFile::time_counter_attr::none)
1196                     {
1197                       SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep() - 1, isRoot);
1198                       if (field->file->time_counter != CFile::time_counter_attr::record)
1199                         SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1, isRoot);
1200                     }
1201                   }
1202                   break;
1203                }
1204              }
1205
1206           }
1207           else // 2D
1208           {
1209              CArray<double,2> field_data2D(domain->zoom_ni_srv,domain->zoom_nj_srv) ;
1210              if (!field->default_value.isEmpty()) field_data2D = field->default_value ;
1211              field->outputField(field_data2D);
1212              if (!field->prec.isEmpty() && field->prec==2) field_data2D=round(field_data2D) ;
1213              switch (SuperClass::type)
1214              {
1215                case (MULTI_FILE) :
1216                {
1217                  SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep() - 1);
1218                  if (wtime)
1219                  {
1220                    SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep() - 1);
1221                    SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1);
1222                    if (field->file->time_counter != CFile::time_counter_attr::none)
1223                    {
1224                      SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep() - 1);
1225                      if (field->file->time_counter != CFile::time_counter_attr::record)
1226                        SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1);
1227                    }
1228                  }
1229                  break;
1230                }
1231                case (ONE_FILE) :
1232                {
1233                   std::vector<StdSize> start(2) ;
1234                   std::vector<StdSize> count(2) ;
1235                   if (domain->isEmpty())
1236                   {
1237                     start[0]=0 ; start[1]=0 ;
1238                     count[0]=0 ; count[1]=0 ;
1239                   }
1240                   else
1241                   {
1242                     start[1]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
1243                     count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
1244                   }
1245
1246                   SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep() - 1, &start, &count);
1247                   if (wtime)
1248                   {
1249                     SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep() - 1, isRoot);
1250                     SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep() - 1, isRoot);
1251                     if (field->file->time_counter != CFile::time_counter_attr::none)
1252                     {
1253                       SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep() - 1, isRoot);
1254                       if (field->file->time_counter != CFile::time_counter_attr::record)
1255                         SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep() - 1, isRoot);
1256                     }
1257                   }
1258                   break;
1259
1260                }
1261              }
1262           }
1263         }
1264         catch (CNetCdfException& e)
1265         {
1266           StdString msg("On writing field data: ");
1267           msg.append(fieldid); msg.append("\n");
1268           msg.append("In the context : ");
1269           msg.append(context->getId()); msg.append("\n");
1270           msg.append(e.what());
1271           ERROR("CNc4DataOutput::writeFieldData_ (CField*  field)", << msg);
1272         }
1273      }
1274
1275      //---------------------------------------------------------------
1276
1277      void CNc4DataOutput::writeTimeAxis_
1278                  (CField*    field,
1279                   const boost::shared_ptr<CCalendar> cal)
1280      {
1281         StdOStringStream oss;
1282
1283//         if (field->operation.getValue().compare("once") == 0) return ;
1284         if (field->foperation->timeType() == func::CFunctor::once) return ;
1285
1286//         oss << "time_" << field->operation.getValue()
1287//             << "_" << field->getRelFile()->output_freq.getValue();
1288
1289//         StdString axisid = oss.str();
1290//         if (field->foperation->timeType() == func::CFunctor::centered) axisid="time_centered" ;
1291//         else if (field->foperation->timeType() == func::CFunctor::instant) axisid="time_instant" ;
1292
1293         StdString axisid("time_centered") ;
1294         StdString axisBoundId("time_centered_bounds");
1295         StdString timeid("time_counter");
1296         StdString timeBoundId("axis_nbounds");
1297
1298         if (field->foperation->timeType() == func::CFunctor::instant)
1299         {
1300            axisid = "time_instant";
1301            axisBoundId = "time_instant_bounds";
1302         }
1303
1304         try
1305         {
1306          // Adding time_instant or time_centered
1307           std::vector<StdString> dims;
1308           dims.push_back(timeid);
1309           if (!SuperClassWriter::varExist(axisid))
1310           {
1311              SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1312
1313              CDate timeOrigin=cal->getTimeOrigin() ;
1314              StdOStringStream oss2;
1315  //            oss2<<initDate.getYear()<<"-"<<initDate.getMonth()<<"-"<<initDate.getDay()<<" "
1316  //                <<initDate.getHour()<<"-"<<initDate.getMinute()<<"-"<<initDate.getSecond() ;
1317              StdString strInitdate=oss2.str() ;
1318              StdString strTimeOrigin=timeOrigin.toString() ;
1319              this->writeTimeAxisAttributes
1320                 (axisid, cal->getType(),
1321                  StdString("seconds since ").append(strTimeOrigin),
1322                  strTimeOrigin, axisBoundId);
1323           }
1324
1325           // Adding time_instant_bounds or time_centered_bounds variables
1326           if (!SuperClassWriter::varExist(axisBoundId))
1327           {
1328              dims.clear() ;
1329              dims.push_back(timeid);
1330              dims.push_back(timeBoundId);
1331              SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1332           }
1333
1334           // Adding time_counter
1335           if (field->file->time_counter != CFile::time_counter_attr::none)
1336           {
1337             axisid = "time_counter";
1338             axisBoundId = "time_counter_bounds";
1339             dims.clear();
1340             dims.push_back(timeid);
1341             if (!SuperClassWriter::varExist(axisid))
1342             {
1343                SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1344                SuperClassWriter::addAttribute("axis", string("T"), &axisid);
1345
1346                if (field->file->time_counter != CFile::time_counter_attr::record)
1347                {
1348                  CDate timeOrigin = cal->getTimeOrigin();
1349                  StdString strTimeOrigin = timeOrigin.toString();
1350
1351                  this->writeTimeAxisAttributes(axisid, cal->getType(),
1352                                                StdString("seconds since ").append(strTimeOrigin),
1353                                                strTimeOrigin, axisBoundId);
1354                }
1355             }
1356
1357             // Adding time_counter_bound dimension
1358             if (field->file->time_counter != CFile::time_counter_attr::record)
1359             {
1360               if (!SuperClassWriter::varExist(axisBoundId))
1361               {
1362                  dims.clear();
1363                  dims.push_back(timeid);
1364                  dims.push_back(timeBoundId);
1365                  SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1366               }
1367             }
1368           }
1369         }
1370         catch (CNetCdfException& e)
1371         {
1372           StdString msg("On writing time axis data: ");
1373           msg.append("In the context : ");
1374           CContext* context = CContext::getCurrent() ;
1375           msg.append(context->getId()); msg.append("\n");
1376           msg.append(e.what());
1377           ERROR("CNc4DataOutput::writeTimeAxis_ (CField*    field, \
1378                  const boost::shared_ptr<CCalendar> cal)", << msg);
1379         }
1380      }
1381
1382      //---------------------------------------------------------------
1383
1384      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
1385                                                   const StdString & calendar,
1386                                                   const StdString & units,
1387                                                   const StdString & time_origin,
1388                                                   const StdString & time_bounds,
1389                                                   const StdString & standard_name,
1390                                                   const StdString & long_name)
1391      {
1392         try
1393         {
1394           SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1395           SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
1396           SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
1397           SuperClassWriter::addAttribute("units",         units        , &axis_name);
1398           SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
1399           SuperClassWriter::addAttribute("bounds",        time_bounds  , &axis_name);
1400         }
1401         catch (CNetCdfException& e)
1402         {
1403           StdString msg("On writing time axis Attribute: ");
1404           msg.append("In the context : ");
1405           CContext* context = CContext::getCurrent() ;
1406           msg.append(context->getId()); msg.append("\n");
1407           msg.append(e.what());
1408           ERROR("CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name, \
1409                                                          const StdString & calendar,\
1410                                                          const StdString & units, \
1411                                                          const StdString & time_origin, \
1412                                                          const StdString & time_bounds, \
1413                                                          const StdString & standard_name, \
1414                                                          const StdString & long_name)", << msg);
1415         }
1416      }
1417
1418      //---------------------------------------------------------------
1419
1420      void CNc4DataOutput::writeAxisAttributes(const StdString & axis_name,
1421                                               const StdString & axis,
1422                                               const StdString & standard_name,
1423                                               const StdString & long_name,
1424                                               const StdString & units,
1425                                               const StdString & nav_model)
1426      {
1427         try
1428         {
1429          if (!axis.empty())
1430            SuperClassWriter::addAttribute("axis"       , axis         , &axis_name);
1431
1432          SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1433          SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
1434          SuperClassWriter::addAttribute("units"        , units        , &axis_name);
1435          SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
1436         }
1437         catch (CNetCdfException& e)
1438         {
1439           StdString msg("On writing Axis Attribute: ");
1440           msg.append("In the context : ");
1441           CContext* context = CContext::getCurrent() ;
1442           msg.append(context->getId()); msg.append("\n");
1443           msg.append(e.what());
1444           ERROR("CNc4DataOutput::writeAxisAttributes(const StdString & axis_name, \
1445                                                      const StdString & axis, \
1446                                                      const StdString & standard_name, \
1447                                                      const StdString & long_name, \
1448                                                      const StdString & units, \
1449                                                      const StdString & nav_model)", << msg);
1450         }
1451      }
1452
1453      //---------------------------------------------------------------
1454
1455      void CNc4DataOutput::writeLocalAttributes
1456         (int ibegin, int ni, int jbegin, int nj, StdString domid)
1457      {
1458        try
1459        {
1460         SuperClassWriter::addAttribute(StdString("ibegin").append(domid), ibegin);
1461         SuperClassWriter::addAttribute(StdString("ni"    ).append(domid), ni);
1462         SuperClassWriter::addAttribute(StdString("jbegin").append(domid), jbegin);
1463         SuperClassWriter::addAttribute(StdString("nj"    ).append(domid), nj);
1464        }
1465        catch (CNetCdfException& e)
1466        {
1467           StdString msg("On writing Local Attributes: ");
1468           msg.append("In the context : ");
1469           CContext* context = CContext::getCurrent() ;
1470           msg.append(context->getId()); msg.append("\n");
1471           msg.append(e.what());
1472           ERROR("CNc4DataOutput::writeLocalAttributes \
1473                  (int ibegin, int ni, int jbegin, int nj, StdString domid)", << msg);
1474        }
1475
1476      }
1477
1478      void CNc4DataOutput::writeLocalAttributes_IOIPSL(const StdString& dimXid, const StdString& dimYid,
1479                                                       int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)
1480      {
1481         CArray<int,1> array(2) ;
1482
1483         try
1484         {
1485           SuperClassWriter::addAttribute("DOMAIN_number_total",size ) ;
1486           SuperClassWriter::addAttribute("DOMAIN_number", rank) ;
1487           array = SuperClassWriter::getDimension(dimXid) + 1, SuperClassWriter::getDimension(dimYid) + 1;
1488           SuperClassWriter::addAttribute("DOMAIN_dimensions_ids",array) ;
1489           array=ni_glo,nj_glo ;
1490           SuperClassWriter::addAttribute("DOMAIN_size_global", array) ;
1491           array=ni,nj ;
1492           SuperClassWriter::addAttribute("DOMAIN_size_local", array) ;
1493           array=ibegin,jbegin ;
1494           SuperClassWriter::addAttribute("DOMAIN_position_first", array) ;
1495           array=ibegin+ni-1,jbegin+nj-1 ;
1496           SuperClassWriter::addAttribute("DOMAIN_position_last",array) ;
1497           array=0,0 ;
1498           SuperClassWriter::addAttribute("DOMAIN_halo_size_start", array) ;
1499           SuperClassWriter::addAttribute("DOMAIN_halo_size_end", array);
1500           SuperClassWriter::addAttribute("DOMAIN_type",string("box")) ;
1501  /*
1502           SuperClassWriter::addAttribute("DOMAIN_DIM_N001",string("x")) ;
1503           SuperClassWriter::addAttribute("DOMAIN_DIM_N002",string("y")) ;
1504           SuperClassWriter::addAttribute("DOMAIN_DIM_N003",string("axis_A")) ;
1505           SuperClassWriter::addAttribute("DOMAIN_DIM_N004",string("time_counter")) ;
1506  */
1507         }
1508         catch (CNetCdfException& e)
1509         {
1510           StdString msg("On writing Local Attributes IOIPSL \n");
1511           msg.append("In the context : ");
1512           CContext* context = CContext::getCurrent() ;
1513           msg.append(context->getId()); msg.append("\n");
1514           msg.append(e.what());
1515           ERROR("CNc4DataOutput::writeLocalAttributes_IOIPSL \
1516                  (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)", << msg);
1517         }
1518      }
1519      //---------------------------------------------------------------
1520
1521      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
1522                                                const StdString & description,
1523                                                const StdString & conventions,
1524                                                const StdString & production,
1525                                                const StdString & timeStamp)
1526      {
1527         try
1528         {
1529           SuperClassWriter::addAttribute("name"       , name);
1530           SuperClassWriter::addAttribute("description", description);
1531           SuperClassWriter::addAttribute("title"      , description);
1532           SuperClassWriter::addAttribute("Conventions", conventions);
1533           SuperClassWriter::addAttribute("production" , production);
1534           SuperClassWriter::addAttribute("timeStamp"  , timeStamp);
1535         }
1536         catch (CNetCdfException& e)
1537         {
1538           StdString msg("On writing File Attributes \n ");
1539           msg.append("In the context : ");
1540           CContext* context = CContext::getCurrent() ;
1541           msg.append(context->getId()); msg.append("\n");
1542           msg.append(e.what());
1543           ERROR("CNc4DataOutput:: writeFileAttributes(const StdString & name, \
1544                                                const StdString & description, \
1545                                                const StdString & conventions, \
1546                                                const StdString & production, \
1547                                                const StdString & timeStamp)", << msg);
1548         }
1549      }
1550
1551      //---------------------------------------------------------------
1552
1553      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
1554                                               int data_dim,
1555                                               int data_ni,
1556                                               int data_nj,
1557                                               int data_ibegin,
1558                                               int data_jbegin)
1559      {
1560         try
1561         {
1562           SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
1563           SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
1564           SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
1565           SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
1566           SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
1567         }
1568         catch (CNetCdfException& e)
1569         {
1570           StdString msg("On writing Mask Attributes \n ");
1571           msg.append("In the context : ");
1572           CContext* context = CContext::getCurrent() ;
1573           msg.append(context->getId()); msg.append("\n");
1574           msg.append(e.what());
1575           ERROR("CNc4DataOutput::writeMaskAttributes(const StdString & mask_name, \
1576                                               int data_dim, \
1577                                               int data_ni, \
1578                                               int data_nj, \
1579                                               int data_ibegin, \
1580                                               int data_jbegin)", << msg);
1581         }
1582      }
1583
1584      ///--------------------------------------------------------------
1585
1586} // namespace xios
Note: See TracBrowser for help on using the repository browser.