source: XIOS/trunk/src/output/nc4_data_output.cpp @ 665

Last change on this file since 665 was 665, checked in by mhnguyen, 6 years ago

Changing longitude and latitude (as well as their bounds) be optional

+) Seperate sendIndex, sendLonLat and sendArea

Test
+) On Curie
+) test_client and test_complete are correct

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