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

Last change on this file since 489 was 488, checked in by mhnguyen, 10 years ago

Ticket 52: Adding some new variables (by default) into output file(s)

+) Add time_bounds dimension
+) Add time_counter_bounds
+) Add time_instant_bounds and/or time_centered_bounds depending on the context

Test
+) On Curie, test_client passed

File size: 48.7 KB
Line 
1
2#include "nc4_data_output.hpp"
3
4#include <boost/lexical_cast.hpp>
5#include "attribute_template.hpp"
6#include "group_template.hpp"
7
8#include "file.hpp"
9#include "calendar.hpp"
10#include "context.hpp"
11#include "context_server.hpp"
12
13namespace xios
14{
15      /// ////////////////////// Définitions ////////////////////// ///
16      CNc4DataOutput::CNc4DataOutput
17         (const StdString & filename, bool exist)
18            : SuperClass()
19            , SuperClassWriter(filename, exist)
20            , filename(filename)
21      {
22         StdString timeid = StdString("time_counter");
23         SuperClass::type = MULTI_FILE;
24//         if (!exist)
25//            SuperClassWriter::addDimension(timeid);
26      }
27
28      CNc4DataOutput::CNc4DataOutput
29         (const StdString & filename, bool exist, MPI_Comm comm_file,bool multifile, bool isCollective)
30            : SuperClass()
31            , SuperClassWriter(filename, exist, &comm_file,multifile)
32            , comm_file(comm_file)
33            , filename(filename)
34            , isCollective(isCollective)
35      {
36         StdString timeid = StdString("time_counter");
37
38         SuperClass::type = (multifile) ? MULTI_FILE : ONE_FILE;
39
40 //        if (!exist)
41//            SuperClassWriter::addDimension(timeid);
42      }
43
44
45      CNc4DataOutput::~CNc4DataOutput(void)
46      { /* Ne rien faire de plus */ }
47
48      ///--------------------------------------------------------------
49
50      const StdString & CNc4DataOutput::getFileName(void) const
51      {
52         return (this->filename);
53      }
54
55      //---------------------------------------------------------------
56
57      void CNc4DataOutput::writeDomain_(CDomain* domain)
58      {
59         if (domain->type == CDomain::type_attr::unstructured)
60         {
61           writeUnstructuredDomain(domain) ;
62           return ;
63         }
64
65         CContext* context = CContext::getCurrent() ;
66         CContextServer* server=context->server ;
67
68         if (domain->IsWritten(this->filename)) return;
69         domain->checkAttributes();
70
71         if (domain->isEmpty())
72           if (SuperClass::type==MULTI_FILE) return ;
73
74         std::vector<StdString> dim0, dim1;
75         StdString domid     = (!domain->name.isEmpty())
76                             ? domain->name.getValue() : domain->getId();
77         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
78
79
80         StdString dimXid, dimYid ;
81
82         switch (domain->type)
83         {
84           case CDomain::type_attr::curvilinear :
85             dimXid     = StdString("x").append(appendDomid);
86             dimYid     = StdString("y").append(appendDomid);
87             break ;
88           case CDomain::type_attr::regular :
89             dimXid     = StdString("lon").append(appendDomid);
90             dimYid     = StdString("lat").append(appendDomid);
91             break;
92           case CDomain::type_attr::unstructured :
93             dimXid     = StdString("cell").append(appendDomid);
94             break;
95         }
96
97         string lonid,latid,bounds_lonid,bounds_latid ;
98/*
99         StdString lonid_loc = (server->intraCommSize > 1)
100                             ? StdString("lon").append(appendDomid).append("_local")
101                             : lonid;
102         StdString latid_loc = (server->intraCommSize > 1)
103                             ? StdString("lat").append(appendDomid).append("_local")
104                             : latid;
105*/
106
107         switch (SuperClass::type)
108         {
109            case (MULTI_FILE) :
110            {
111//               if (domain->isEmpty()) return;
112
113               if (server->intraCommSize > 1)
114               {
115//                 SuperClassWriter::addDimension(lonid, domain->zoom_ni.getValue());
116//                 SuperClassWriter::addDimension(latid, domain->zoom_nj.getValue());
117               }
118
119               switch (domain->type)
120               {
121                 case CDomain::type_attr::curvilinear :
122                   dim0.push_back(dimYid); dim0.push_back(dimXid);
123                   lonid = StdString("nav_lon").append(appendDomid);
124                   latid = StdString("nav_lat").append(appendDomid);
125                   break ;
126                 case CDomain::type_attr::regular :
127                   lonid = StdString("lon").append(appendDomid);
128                   latid = StdString("lat").append(appendDomid);
129                   dim0.push_back(dimYid);
130                   dim1.push_back(dimXid);
131                   break;
132                 case CDomain::type_attr::unstructured :
133                   lonid = StdString("lon").append(appendDomid);
134                   latid = StdString("lat").append(appendDomid);
135                   bounds_lonid=string("bounds_lon").append(appendDomid);
136                   bounds_latid=string("bounds_lat").append(appendDomid);
137                   dim0.push_back(dimXid);
138                   break;
139               }
140
141               if (domain->type == CDomain::type_attr::unstructured)
142               {
143                 SuperClassWriter::addDimension(dimXid, domain->nj_glo);
144               }
145               else
146               {
147                 SuperClassWriter::addDimension(dimXid, domain->zoom_ni_srv);
148                 SuperClassWriter::addDimension(dimYid, domain->zoom_nj_srv);
149               }
150
151               if (server->intraCommSize > 1)
152               {
153                  if (domain->type != CDomain::type_attr::unstructured)
154                  {
155                    this->writeLocalAttributes(domain->zoom_ibegin_srv,
156                                               domain->zoom_ni_srv,
157                                               domain->zoom_jbegin_srv,
158                                               domain->zoom_nj_srv,
159                                               appendDomid);
160
161                    if (singleDomain) this->writeLocalAttributes_IOIPSL(domain->zoom_ibegin_srv,
162                                               domain->zoom_ni_srv,
163                                               domain->zoom_jbegin_srv,
164                                               domain->zoom_nj_srv,
165                                               domain->ni_glo,domain->nj_glo,
166                                               server->intraCommRank,server->intraCommSize);
167                 }
168               }
169
170               switch (domain->type)
171               {
172                 case CDomain::type_attr::curvilinear :
173                   SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
174                   SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
175                   break ;
176                  case CDomain::type_attr::regular :
177                    SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
178                    SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
179                    break ;
180                  case CDomain::type_attr::unstructured :
181                    SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
182                    SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
183               }
184
185               this->writeAxisAttributes(lonid, "X", "longitude", "Longitude", "degrees_east", domid);
186               this->writeAxisAttributes(latid, "Y", "latitude", "Latitude", "degrees_north", domid);
187
188               dim0.clear();
189               if (domain->type != CDomain::type_attr::unstructured) dim0.push_back(dimYid);
190               dim0.push_back(dimXid);
191
192
193// supress mask               if (server->intraCommSize > 1)
194// supress mask               {
195// supress mask                  SuperClassWriter::addVariable(maskid, NC_INT, dim0);
196// supress mask
197// supress mask                  this->writeMaskAttributes(maskid,
198// supress mask                     domain->data_dim.getValue()/*,
199// supress mask                     domain->data_ni.getValue(),
200// supress mask                     domain->data_nj.getValue(),
201// supress mask                     domain->data_ibegin.getValue(),
202// supress mask                     domain->data_jbegin.getValue()*/);
203// supress mask               }
204
205               //SuperClassWriter::setDefaultValue(maskid, &dvm);
206
207               SuperClassWriter::definition_end();
208
209               switch (domain->type)
210               {
211                 case CDomain::type_attr::curvilinear :
212                   SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0);
213                   SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0);
214                   break;
215                 case CDomain::type_attr::regular :
216                   CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;
217                   SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0);
218                   CArray<double,1> lon=domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;
219                   SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0);
220                   break;
221               }
222               SuperClassWriter::definition_start();
223
224               break;
225            }
226            case (ONE_FILE) :
227            {
228               SuperClassWriter::addDimension(dimXid, domain->zoom_ni.getValue());
229               SuperClassWriter::addDimension(dimYid, domain->zoom_nj.getValue());
230
231
232               switch (domain->type)
233               {
234                 case CDomain::type_attr::curvilinear :
235                   dim0.push_back(dimYid); dim0.push_back(dimXid);
236                   lonid = StdString("nav_lon").append(appendDomid);
237                   latid = StdString("nav_lat").append(appendDomid);
238                   SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
239                   SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
240                   break;
241
242                 case CDomain::type_attr::regular :
243                   dim0.push_back(dimYid);
244                   dim1.push_back(dimXid);
245                   lonid = StdString("lon").append(appendDomid);
246                   latid = StdString("lat").append(appendDomid);
247                   SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
248                   SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
249                   break;
250               }
251               this->writeAxisAttributes
252                  (lonid, "X", "longitude", "Longitude", "degrees_east", domid);
253               this->writeAxisAttributes
254                  (latid, "Y", "latitude", "Latitude", "degrees_north", domid);
255
256
257               SuperClassWriter::definition_end();
258               switch (domain->type)
259               {
260                 case CDomain::type_attr::curvilinear :
261                 {
262                   std::vector<StdSize> start(2) ;
263                   std::vector<StdSize> count(2) ;
264                   if (domain->isEmpty())
265                   {
266                     start[0]=0 ; start [1]=0 ;
267                     count[0]=0 ; count[1]=0 ;
268                   }
269                   else
270                   {
271                     start[1]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start [0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
272                     count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
273                   }
274
275                   SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
276                   SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
277                   break;
278                 }
279                 case CDomain::type_attr::regular :
280                 {
281                   std::vector<StdSize> start(1) ;
282                   std::vector<StdSize> count(1) ;
283                   if (domain->isEmpty())
284                   {
285                     start[0]=0 ;
286                     count[0]=0 ;
287                     SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
288                     SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);                 }
289                   else
290                   {
291                     start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
292                     count[0]=domain->zoom_nj_srv ;
293                     CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;
294                     SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0,&start,&count);
295
296                     start[0]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ;
297                     count[0]=domain->zoom_ni_srv ;
298                     CArray<double,1> lon=domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;
299                     SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0,&start,&count);
300                   }
301                   break;
302                 }
303               }
304               SuperClassWriter::definition_start();
305               break;
306            }
307            default :
308               ERROR("CNc4DataOutput::writeDomain(domain)",
309                     << "[ type = " << SuperClass::type << "]"
310                     << " not implemented yet !");
311         }
312         domain->addRelFile(this->filename);
313      }
314
315      void CNc4DataOutput::writeUnstructuredDomain(CDomain* domain)
316      {
317         CContext* context = CContext::getCurrent() ;
318         CContextServer* server=context->server ;
319
320         if (domain->IsWritten(this->filename)) return;
321         domain->checkAttributes();
322
323         if (domain->isEmpty())
324           if (SuperClass::type==MULTI_FILE) return ;
325
326         std::vector<StdString> dim0, dim1;
327         StdString domid     = (!domain->name.isEmpty())
328                             ? domain->name.getValue() : domain->getId();
329         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
330
331
332         StdString dimXid = StdString("cell").append(appendDomid);
333         StdString dimVertId = StdString("nvertex").append(appendDomid);
334
335         string lonid,latid,bounds_lonid,bounds_latid ;
336
337         switch (SuperClass::type)
338         {
339            case (MULTI_FILE) :
340            {
341               lonid = StdString("lon").append(appendDomid);
342               latid = StdString("lat").append(appendDomid);
343               dim0.push_back(dimXid);
344
345               SuperClassWriter::addDimension(dimXid, domain->zoom_nj_srv);
346               SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
347               SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
348
349               bounds_lonid = StdString("bounds_lon").append(appendDomid);
350               bounds_latid = StdString("bounds_lat").append(appendDomid);
351
352
353               this->writeAxisAttributes(lonid, "X", "longitude", "Longitude", "degrees_east", domid);
354               if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
355               this->writeAxisAttributes(latid, "Y", "latitude", "Latitude", "degrees_north", domid);
356               if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
357               if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
358               dim0.clear();
359               if (domain->hasBounds)
360               {
361                 dim0.push_back(dimXid);
362                 dim0.push_back(dimVertId);
363                 SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
364                 SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
365               }
366
367               dim0.clear();
368               dim0.push_back(dimXid);
369
370               SuperClassWriter::definition_end();
371
372               SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0);
373               SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0);
374
375               if (domain->hasBounds)
376               {
377                 SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0);
378                 SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0);
379               }
380               SuperClassWriter::definition_start();
381               break ;
382            }
383
384            case (ONE_FILE) :
385            {
386               lonid = StdString("lon").append(appendDomid);
387               latid = StdString("lat").append(appendDomid);
388               bounds_lonid = StdString("bounds_lon").append(appendDomid);
389               bounds_latid = StdString("bounds_lat").append(appendDomid);
390               dim0.push_back(dimXid);
391               SuperClassWriter::addDimension(dimXid, domain->nj_glo);
392               SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
393               SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
394               this->writeAxisAttributes(lonid, "X", "longitude", "Longitude", "degrees_east", domid);
395               if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid);
396               this->writeAxisAttributes(latid, "Y", "latitude", "Latitude", "degrees_north", domid);
397               if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid);
398               if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);
399               dim0.clear();
400
401               if (domain->hasBounds)
402               {
403                 dim0.push_back(dimXid);
404                 dim0.push_back(dimVertId);
405                 SuperClassWriter::addVariable(bounds_lonid, NC_FLOAT, dim0);
406                 SuperClassWriter::addVariable(bounds_latid, NC_FLOAT, dim0);
407               }
408
409               SuperClassWriter::definition_end();
410
411               std::vector<StdSize> start(1), startBounds(2) ;
412               std::vector<StdSize> count(1), countBounds(2) ;
413               if (domain->isEmpty())
414               {
415                 start[0]=0 ;
416                 count[0]=0 ;
417                 startBounds[1]=0 ;
418                 countBounds[1]=domain->nvertex ;
419                 startBounds[0]=0 ;
420                 countBounds[0]=0 ;
421               }
422               else
423               {
424                 start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin ;
425                 count[0]=domain->zoom_nj_srv ;
426                 startBounds[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin ;
427                 startBounds[1]=0 ;
428                 countBounds[0]=domain->zoom_nj_srv ;
429                 countBounds[1]=domain->nvertex ;
430               }
431               SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count);
432               SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);
433               if (domain->hasBounds)
434               {
435                 SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0,&startBounds,&countBounds);
436                 SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0,&startBounds,&countBounds);
437               }
438
439
440               SuperClassWriter::definition_start();
441
442               break;
443            }
444            default :
445               ERROR("CNc4DataOutput::writeDomain(domain)",
446                     << "[ type = " << SuperClass::type << "]"
447                     << " not implemented yet !");
448         }
449         domain->addRelFile(this->filename);
450      }
451      //--------------------------------------------------------------
452
453      void CNc4DataOutput::writeAxis_(CAxis* axis)
454      {
455         if (axis->IsWritten(this->filename)) return;
456         axis->checkAttributes();
457         StdSize zoom_size=axis->zoom_size.getValue() ;
458         StdSize zoom_begin=axis->zoom_begin.getValue()-1 ;
459
460         std::vector<StdString> dims;
461         StdString axisid = (!axis->name.isEmpty())
462                           ? axis->name.getValue() : axis->getId();
463         SuperClassWriter::addDimension(axisid, zoom_size);
464         dims.push_back(axisid);
465
466         switch (SuperClass::type)
467         {
468            case (MULTI_FILE ) :
469            {}
470            case (ONE_FILE) :
471            {
472               SuperClassWriter::addVariable(axisid, NC_FLOAT, dims);
473
474               SuperClassWriter::addAttribute("axis", StdString("Z"), &axisid);
475
476               if (!axis->standard_name.isEmpty())
477                  SuperClassWriter::addAttribute
478                     ("standard_name",  axis->standard_name.getValue(), &axisid);
479
480               if (!axis->long_name.isEmpty())
481                  SuperClassWriter::addAttribute
482                     ("long_name", axis->long_name.getValue(), &axisid);
483
484               if (!axis->unit.isEmpty())
485                  SuperClassWriter::addAttribute
486                     ("units", axis->unit.getValue(), &axisid);
487
488              if (!axis->positive.isEmpty())
489                if (axis->positive==CAxis::positive_attr::up) SuperClassWriter::addAttribute("positive", string("up"), &axisid);
490                else   SuperClassWriter::addAttribute("positive", string("down"), &axisid);
491
492               SuperClassWriter::definition_end();
493
494               CArray<double,1> axis_value(zoom_size) ;
495               for(StdSize i = 0 ; i < zoom_size ; i++) axis_value(i)=axis->value(i+zoom_begin) ;
496               SuperClassWriter::writeData(axis_value, axisid, isCollective, 0);
497
498               SuperClassWriter::definition_start();
499
500               break;
501            }
502            default :
503               ERROR("CNc4DataOutput::writeDomain(domain)",
504                     << "[ type = " << SuperClass::type << "]"
505                     << " not implemented yet !");
506         }
507         axis->addRelFile(this->filename);
508     }
509
510     void CNc4DataOutput::writeTimeDimension_(void)
511     {
512       SuperClassWriter::addDimension("time_counter");
513       SuperClassWriter::addDimension("time_bounds", 2);
514     }
515      //--------------------------------------------------------------
516
517      void CNc4DataOutput::writeField_(CField* field)
518      {
519         CContext* context = CContext::getCurrent() ;
520         CContextServer* server=context->server ;
521
522         std::vector<StdString> dims, coodinates;
523         CGrid* grid = field->grid;
524         CDomain* domain = grid->domain;
525
526         if (domain->isEmpty())
527           if (SuperClass::type==MULTI_FILE) return ;
528
529         StdString timeid    = StdString("time_counter");
530         StdString domid     = (!domain->name.isEmpty())
531                             ? domain->name.getValue() : domain->getId();
532         StdString appendDomid  = (singleDomain) ? "" : "_"+domid ;
533
534//         bool isCurvilinear = domain->isCurvilinear ;
535//         bool isCurvilinear = (domain->type == CDomain::type_attr::curvilinear) ;
536
537         StdString dimXid,dimYid ;
538
539         switch (domain->type)
540         {
541           case CDomain::type_attr::curvilinear :
542             dimXid     = StdString("x").append(appendDomid);
543             dimYid     = StdString("y").append(appendDomid);
544             break ;
545           case CDomain::type_attr::regular :
546             dimXid     = StdString("lon").append(appendDomid);
547             dimYid     = StdString("lat").append(appendDomid);
548             break ;
549           case CDomain::type_attr::unstructured :
550             dimXid     = StdString("cell").append(appendDomid);
551             break ;
552        }
553
554/*
555         StdString lonid_loc = (server->intraCommSize > 1)
556                             ? StdString("lon").append(appendDomid).append("_local")
557                             : lonid;
558         StdString latid_loc = (server->intraCommSize > 1)
559                             ? StdString("lat").append(appendDomid).append("_local")
560                             : latid;
561*/
562         StdString fieldid   = (!field->name.isEmpty())
563                             ? field->name.getValue() : field->getBaseFieldReference()->getId();
564
565//         unsigned int ssize = domain->zoom_ni_loc.getValue() * domain->zoom_nj_loc.getValue();
566//         bool isCurvilinear = (domain->lonvalue.getValue()->size() == ssize);
567//          bool isCurvilinear = domain->isCurvilinear ;
568
569         nc_type type ;
570         if (field->prec.isEmpty()) type =  NC_FLOAT ;
571         else
572         {
573           if (field->prec==2) type = NC_SHORT ;
574           else if (field->prec==4)  type =  NC_FLOAT ;
575           else if (field->prec==8)   type =  NC_DOUBLE ;
576         }
577
578         bool wtime   = !(!field->operation.isEmpty() && field->foperation->timeType() == func::CFunctor::once);
579
580         if (wtime)
581         {
582
583            //StdOStringStream oss;
584           // oss << "time_" << field->operation.getValue()
585           //     << "_" << field->getRelFile()->output_freq.getValue();
586          //oss
587            if (field->foperation->timeType() == func::CFunctor::instant) coodinates.push_back(string("time_instant"));
588            else if (field->foperation->timeType() == func::CFunctor::centered) coodinates.push_back(string("time_centered"));
589            dims.push_back(timeid);
590         }
591
592         if (!grid->axis_ref.isEmpty())
593         {
594            CAxis* axis = grid->axis ;
595            StdString axisid = (!axis->name.isEmpty()) ? axis->name.getValue() : axis->getId();
596            dims.push_back(axisid);
597            coodinates.push_back(axisid);
598         }
599
600         switch (domain->type)
601         {
602           case CDomain::type_attr::curvilinear :
603             coodinates.push_back(StdString("nav_lon").append(appendDomid));
604             coodinates.push_back(StdString("nav_lat").append(appendDomid));
605             break;
606           case CDomain::type_attr::regular :
607           case CDomain::type_attr::unstructured :
608            coodinates.push_back(StdString("lon").append(appendDomid));
609            coodinates.push_back(StdString("lat").append(appendDomid));
610             break;
611         }
612
613         if ( domain->type == CDomain::type_attr::curvilinear || domain->type == CDomain::type_attr::regular)dims.push_back(dimYid);
614         dims.push_back(dimXid);
615
616         SuperClassWriter::addVariable(fieldid, type, dims);
617
618         if (!field->standard_name.isEmpty())
619            SuperClassWriter::addAttribute
620               ("standard_name",  field->standard_name.getValue(), &fieldid);
621
622         if (!field->long_name.isEmpty())
623            SuperClassWriter::addAttribute
624               ("long_name", field->long_name.getValue(), &fieldid);
625
626         if (!field->unit.isEmpty())
627            SuperClassWriter::addAttribute
628               ("units", field->unit.getValue(), &fieldid);
629
630          if (!field->valid_min.isEmpty())
631            SuperClassWriter::addAttribute
632               ("valid_min", field->valid_min.getValue(), &fieldid);
633
634         if (!field->valid_max.isEmpty())
635            SuperClassWriter::addAttribute
636               ("valid_max", field->valid_max.getValue(), &fieldid);
637
638          if (!field->scale_factor.isEmpty())
639            SuperClassWriter::addAttribute
640               ("scale_factor", field->scale_factor.getValue(), &fieldid);
641
642           if (!field->add_offset.isEmpty())
643            SuperClassWriter::addAttribute
644               ("add_offset", field->add_offset.getValue(), &fieldid);
645
646         SuperClassWriter::addAttribute
647               ("online_operation", field->operation.getValue(), &fieldid);
648
649        // write child variables as attributes
650
651
652         vector<CVariable*> listVars = field->getAllVariables() ;
653         for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ;
654
655
656         if (wtime)
657         {
658            CDuration duration ;
659
660            duration=CDuration::FromString(field->freq_op) ;
661            duration.solveTimeStep(*(context->calendar));
662            SuperClassWriter::addAttribute("interval_operation", duration.toString(), &fieldid);
663
664            duration=CDuration::FromString(field->getRelFile()->output_freq) ;
665            duration.solveTimeStep(*(context->calendar));
666            SuperClassWriter::addAttribute("interval_write", duration.toString(), &fieldid);
667         }
668
669         if (!field->default_value.isEmpty())
670         {
671            double default_value = field->default_value.getValue();
672            float fdefault_value = (float)default_value;
673            if (type == NC_DOUBLE)
674               SuperClassWriter::setDefaultValue(fieldid, &default_value);
675            else
676               SuperClassWriter::setDefaultValue(fieldid, &fdefault_value);
677         }
678         else
679         {
680            double * default_value = NULL;
681            SuperClassWriter::setDefaultValue(fieldid, default_value);
682         }
683
684         {  // Ecriture des coordonnées
685
686            StdString coordstr; //boost::algorithm::join(coodinates, " ")
687            std::vector<StdString>::iterator
688               itc = coodinates.begin(), endc = coodinates.end();
689
690            for (; itc!= endc; itc++)
691            {
692               StdString & coord = *itc;
693               if (itc+1 != endc)
694                     coordstr.append(coord).append(" ");
695               else  coordstr.append(coord);
696            }
697
698            SuperClassWriter::addAttribute("coordinates", coordstr, &fieldid);
699
700         }
701
702      }
703
704      //--------------------------------------------------------------
705
706      void CNc4DataOutput::writeFile_ (CFile* file)
707      {
708         StdString filename = (!file->name.isEmpty())
709                            ? file->name.getValue() : file->getId();
710         StdString description = (!file->description.isEmpty())
711                               ? file->description.getValue()
712                               : StdString("Created by xios");
713         this->writeFileAttributes(filename, description,
714                                   StdString ("CF-1.1"),
715                                   StdString("An IPSL model"),
716                                   this->getTimeStamp());
717         if (file->nbDomain==1) singleDomain=true ;
718         else singleDomain=false ;
719      }
720
721      void CNc4DataOutput::writeAttribute_ (CVariable* var, const string& fieldId)
722      {
723        string name ;
724        if (!var->name.isEmpty()) name=var->name ;
725        else if (var->hasId()) name=var->getId() ;
726        else return ;
727
728        if (var->getVarType()==CVariable::t_int) addAttribute(name,var->getData<int>(),&fieldId) ;
729        else if (var->getVarType()==CVariable::t_short_int) addAttribute(name,var->getData<short int>(),&fieldId) ;
730        else if (var->getVarType()==CVariable::t_long_int) addAttribute(name,var->getData<long int>(),&fieldId) ;
731        else if (var->getVarType()==CVariable::t_float) addAttribute(name,var->getData<float>(),&fieldId) ;
732        else if (var->getVarType()==CVariable::t_double) addAttribute(name,var->getData<double>(),&fieldId) ;
733        else addAttribute(name,var->getData<string>(),&fieldId) ;
734     }
735
736     void CNc4DataOutput::writeAttribute_ (CVariable* var)
737     {
738        string name ;
739        if (!var->name.isEmpty()) name=var->name ;
740        else if (var->hasId()) name=var->getId() ;
741        else return ;
742
743        if (var->getVarType()==CVariable::t_int) addAttribute(name,var->getData<int>()) ;
744        else if (var->getVarType()==CVariable::t_short_int) addAttribute(name,var->getData<short int>()) ;
745        else if (var->getVarType()==CVariable::t_long_int) addAttribute(name,var->getData<long int>()) ;
746        else if (var->getVarType()==CVariable::t_float) addAttribute(name,var->getData<float>()) ;
747        else if (var->getVarType()==CVariable::t_double) addAttribute(name,var->getData<double>()) ;
748        else addAttribute(name,var->getData<string>()) ;
749     }
750
751      void CNc4DataOutput::syncFile_ (void)
752      {
753         SuperClassWriter::sync() ;
754      }
755
756      void CNc4DataOutput::closeFile_ (void)
757      {
758         SuperClassWriter::close() ;
759      }
760
761      //---------------------------------------------------------------
762
763      StdString CNc4DataOutput::getTimeStamp(void) const
764      {
765         const int buffer_size = 100;
766         time_t rawtime;
767         struct tm * timeinfo = NULL;
768         char buffer [buffer_size];
769
770         time ( &rawtime );
771         timeinfo = localtime ( &rawtime );
772         strftime (buffer, buffer_size, "%Y-%b-%d %H:%M:%S %Z", timeinfo);
773
774         return (StdString(buffer));
775      }
776
777      //---------------------------------------------------------------
778
779      void CNc4DataOutput::writeFieldData_ (CField*  field)
780      {
781         CContext* context = CContext::getCurrent() ;
782//          if (field->getRelFile()->isSyncTime()) SuperClassWriter::sync() ;
783         CContextServer* server=context->server ;
784
785         CGrid* grid = field->grid ;
786         CDomain* domain = grid->domain ;
787
788         if(SuperClass::type==MULTI_FILE || !isCollective) if (domain->isEmpty()) return;
789
790
791         StdString fieldid   = (!field->name.isEmpty())
792                             ? field->name.getValue()
793                             : field->getBaseFieldReference()->getId();
794
795         StdOStringStream oss;
796         string timeAxisId ;
797         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisId="time_instant" ;
798         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisId="time_centered" ;
799
800         StdString timeBoundId("time_counter_bounds");
801
802         StdString timeAxisBoundId;
803         if (field->foperation->timeType() == func::CFunctor::instant)  timeAxisBoundId="time_instant_bounds" ;
804         else if (field->foperation->timeType() == func::CFunctor::centered)  timeAxisBoundId="time_centered_bounds" ;
805
806         CArray<double,1> time_data(1) ;
807         CArray<double,1> time_counter(1) ;
808         CArray<double,1> time_counter_bound(2);
809         CArray<double,1> time_data_bound(2);
810
811        bool wtime   = !(!field->operation.isEmpty() && (field->foperation->timeType() == func::CFunctor::once));
812
813        if (wtime)
814        {
815          time_counter(0)= (Time(*field->last_Write_srv)+Time(*field->lastlast_Write_srv))/2 -Time(context->calendar->getTimeOrigin());
816          if (field->foperation->timeType() == func::CFunctor::instant)
817            time_data(0) = Time(*field->last_Write_srv)-Time(context->calendar->getTimeOrigin());
818          else if (field->foperation->timeType() == func::CFunctor::centered) time_data(0) = time_counter(0);
819
820          time_counter_bound(0) = Time(*field->lastlast_Write_srv) - Time(context->calendar->getTimeOrigin());
821          time_counter_bound(1) = Time(*field->last_Write_srv) - Time(context->calendar->getTimeOrigin());
822          if (field->foperation->timeType() == func::CFunctor::instant)
823            time_data_bound(0) = time_data_bound(1) = Time(*field->last_Write_srv)-Time(context->calendar->getTimeOrigin());
824          else if (field->foperation->timeType() == func::CFunctor::centered)
825          {
826            time_data_bound(0) = time_counter_bound(0);
827            time_data_bound(1) = time_counter_bound(1);
828          }
829         }
830
831         bool isRoot ;
832         if (server->intraCommRank==0) isRoot=true ;
833         else isRoot=false ;
834
835         if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty())
836         {
837           double scaleFactor=1. ;
838           double addOffset=0. ;
839           if (!field->scale_factor.isEmpty()) scaleFactor=field->scale_factor ;
840           if (!field->add_offset.isEmpty()) addOffset=field->add_offset ;
841           field->scaleFactorAddOffset(scaleFactor,addOffset) ;
842         }
843
844         if (grid->hasAxis()) // 3D
845         {
846            CAxis* axis = grid->axis ;
847            CArray<double,3> field_data3D(domain->zoom_ni_srv,domain->zoom_nj_srv,axis->zoom_size) ;
848            if (!field->default_value.isEmpty()) field_data3D = field->default_value ;
849
850            field->outputField(field_data3D);
851
852            if (!field->prec.isEmpty() && field->prec==2) field_data3D=round(field_data3D) ;
853
854            switch (SuperClass::type)
855           {
856              case (MULTI_FILE) :
857              {
858                 SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep()-1);
859                 if (wtime)
860                 {
861                   SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep()-1);
862                   SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep()-1);
863                   SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1);
864                   SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1);
865                 }
866                 break ;
867              }
868              case (ONE_FILE) :
869              {
870                 std::vector<StdSize> start(3) ;
871                 std::vector<StdSize> count(3) ;
872                 if (domain->isEmpty())
873                 {
874                   start[0]=0 ; start[1]=0 ; start[2]=0 ;
875                   count[0]=0 ; count[1]=0 ; start[2]=0 ;
876                 }
877                 else
878                 {
879//                 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 ;
880                   start[2]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start [1]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ; start[0]=0 ;
881                   count[2]=domain->zoom_ni_srv ; count[1]=domain->zoom_nj_srv ; count[0] = axis->zoom_size.getValue();
882                 }
883                 SuperClassWriter::writeData(field_data3D, fieldid, isCollective, field->getNStep()-1,&start,&count );
884                 if (wtime)
885                 {
886                   SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot );
887                   SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot );
888                   SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot );
889                   SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot);
890                 }
891                 break;
892              }
893            }
894
895         }
896         else // 2D
897         {
898            CArray<double,2> field_data2D(domain->zoom_ni_srv,domain->zoom_nj_srv) ;
899            if (!field->default_value.isEmpty()) field_data2D = field->default_value ;
900            field->outputField(field_data2D);
901            if (!field->prec.isEmpty() && field->prec==2) field_data2D=round(field_data2D) ;
902            switch (SuperClass::type)
903            {
904              case (MULTI_FILE) :
905              {
906                SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep()-1);
907                if (wtime)
908                {
909                  SuperClassWriter::writeData(time_data, timeAxisId, isCollective, field->getNStep()-1);
910                  SuperClassWriter::writeData(time_counter, string("time_counter"), isCollective, field->getNStep()-1);
911                  SuperClassWriter::writeData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1);
912                  SuperClassWriter::writeData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1);
913                }
914                break;
915              }
916              case (ONE_FILE) :
917              {
918                 std::vector<StdSize> start(2) ;
919                 std::vector<StdSize> count(2) ;
920                 if (domain->isEmpty())
921                 {
922                   start[0]=0 ; start[1]=0 ;
923                   count[0]=0 ; count[1]=0 ;
924                 }
925                 else
926                 {
927                   start[1]=domain->zoom_ibegin_srv-domain->zoom_ibegin.getValue() ; start[0]=domain->zoom_jbegin_srv-domain->zoom_jbegin.getValue() ;
928                   count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
929                 }
930
931                 SuperClassWriter::writeData(field_data2D, fieldid, isCollective, field->getNStep()-1,&start,&count);
932                 if (wtime)
933                 {
934                   SuperClassWriter::writeTimeAxisData(time_data, timeAxisId, isCollective, field->getNStep()-1,isRoot);
935                   SuperClassWriter::writeTimeAxisData(time_counter, string("time_counter"), isCollective, field->getNStep()-1,isRoot);
936                   SuperClassWriter::writeTimeAxisData(time_counter_bound, timeBoundId, isCollective, field->getNStep()-1, isRoot);
937                   SuperClassWriter::writeTimeAxisData(time_data_bound, timeAxisBoundId, isCollective, field->getNStep()-1, isRoot);
938                 }
939                 break;
940
941              }
942            }
943         }
944      }
945
946      //---------------------------------------------------------------
947
948      void CNc4DataOutput::writeTimeAxis_
949                  (CField*    field,
950                   const boost::shared_ptr<CCalendar> cal)
951      {
952         StdOStringStream oss;
953
954//         if (field->operation.getValue().compare("once") == 0) return ;
955         if (field->foperation->timeType() == func::CFunctor::once) return ;
956
957//         oss << "time_" << field->operation.getValue()
958//             << "_" << field->getRelFile()->output_freq.getValue();
959
960//         StdString axisid = oss.str();
961//         if (field->foperation->timeType() == func::CFunctor::centered) axisid="time_centered" ;
962//         else if (field->foperation->timeType() == func::CFunctor::instant) axisid="time_instant" ;
963
964         StdString axisid("time_centered") ;
965         StdString axisBoundId("time_centered_bounds");
966         StdString timeid("time_counter");
967         StdString timeBoundId("time_bounds");
968
969         if (field->foperation->timeType() == func::CFunctor::instant)
970         {
971            axisid = "time_instant";
972            axisBoundId = "time_instant_bounds";
973         }
974
975         // Adding time_instant or time_centered
976         std::vector<StdString> dims;
977         dims.push_back(timeid);
978         if (!SuperClassWriter::varExist(axisid))
979         {
980            SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
981
982            CDate timeOrigin=cal->getTimeOrigin() ;
983            StdOStringStream oss2;
984//            oss2<<initDate.getYear()<<"-"<<initDate.getMonth()<<"-"<<initDate.getDay()<<" "
985//                <<initDate.getHour()<<"-"<<initDate.getMinute()<<"-"<<initDate.getSecond() ;
986            StdString strInitdate=oss2.str() ;
987            StdString strTimeOrigin=timeOrigin.toString() ;
988            this->writeTimeAxisAttributes
989               (axisid, cal->getType(),
990                StdString("seconds since ").append(strTimeOrigin),
991                strTimeOrigin, axisBoundId);
992         }
993
994         // Adding time_instant_bounds or time_centered_bounds variables
995         if (!SuperClassWriter::varExist(axisBoundId))
996         {
997            dims.clear() ;
998            dims.push_back(timeid);
999            dims.push_back(timeBoundId);
1000            SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1001         }
1002
1003         // Adding time_counter
1004         axisid = "time_counter" ;
1005         axisBoundId = "time_counter_bounds" ;
1006         dims.clear() ;
1007         dims.push_back(timeid);
1008         if (!SuperClassWriter::varExist(axisid))
1009         {
1010            SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
1011            SuperClassWriter::addAttribute("axis", string("T"), &axisid);
1012            CDate timeOrigin=cal->getTimeOrigin() ;
1013            StdString strTimeOrigin=timeOrigin.toString() ;
1014
1015            this->writeTimeAxisAttributes
1016               (axisid, cal->getType(),
1017                StdString("seconds since ").append(strTimeOrigin),
1018                strTimeOrigin, axisBoundId);
1019         }
1020
1021         // Adding time_counter_bound dimension
1022         if (!SuperClassWriter::varExist(axisBoundId))
1023         {
1024            dims.clear();
1025            dims.push_back(timeid);
1026            dims.push_back(timeBoundId);
1027            SuperClassWriter::addVariable(axisBoundId, NC_DOUBLE, dims);
1028         }
1029      }
1030
1031      //---------------------------------------------------------------
1032
1033      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
1034                                                   const StdString & calendar,
1035                                                   const StdString & units,
1036                                                   const StdString & time_origin,
1037                                                   const StdString & time_bounds,
1038                                                   const StdString & standard_name,
1039                                                   const StdString & long_name,
1040                                                   const StdString & title)
1041      {
1042         SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1043         SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
1044         SuperClassWriter::addAttribute("title",         title        , &axis_name);
1045         SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
1046         SuperClassWriter::addAttribute("units",         units        , &axis_name);
1047         SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
1048         SuperClassWriter::addAttribute("bounds",        time_bounds  , &axis_name);
1049      }
1050
1051      //---------------------------------------------------------------
1052
1053      void CNc4DataOutput::writeAxisAttributes(const StdString & axis_name,
1054                                               const StdString & axis,
1055                                               const StdString & standard_name,
1056                                               const StdString & long_name,
1057                                               const StdString & units,
1058                                               const StdString & nav_model)
1059      {
1060         SuperClassWriter::addAttribute("axis"         , axis         , &axis_name);
1061         SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
1062         SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
1063         SuperClassWriter::addAttribute("units"        , units        , &axis_name);
1064         SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
1065      }
1066
1067      //---------------------------------------------------------------
1068
1069      void CNc4DataOutput::writeLocalAttributes
1070         (int ibegin, int ni, int jbegin, int nj, StdString domid)
1071      {
1072         SuperClassWriter::addAttribute(StdString("ibegin").append(domid), ibegin);
1073         SuperClassWriter::addAttribute(StdString("ni"    ).append(domid), ni);
1074         SuperClassWriter::addAttribute(StdString("jbegin").append(domid), jbegin);
1075         SuperClassWriter::addAttribute(StdString("nj"    ).append(domid), nj);
1076      }
1077
1078     void CNc4DataOutput::writeLocalAttributes_IOIPSL
1079         (int ibegin, int ni, int jbegin, int nj, int ni_glo, int nj_glo, int rank, int size)
1080      {
1081         CArray<int,1> array(2) ;
1082
1083         SuperClassWriter::addAttribute("DOMAIN_number_total",size ) ;
1084         SuperClassWriter::addAttribute("DOMAIN_number", rank) ;
1085         array=1,2 ;
1086         SuperClassWriter::addAttribute("DOMAIN_dimensions_ids",array) ;
1087         array=ni_glo,nj_glo ;
1088         SuperClassWriter::addAttribute("DOMAIN_size_global", array) ;
1089         array=ni,nj ;
1090         SuperClassWriter::addAttribute("DOMAIN_size_local", array) ;
1091         array=ibegin,jbegin ;
1092         SuperClassWriter::addAttribute("DOMAIN_position_first", array) ;
1093         array=ibegin+ni-1,jbegin+nj-1 ;
1094         SuperClassWriter::addAttribute("DOMAIN_position_last",array) ;
1095         array=0,0 ;
1096         SuperClassWriter::addAttribute("DOMAIN_halo_size_start", array) ;
1097         SuperClassWriter::addAttribute("DOMAIN_halo_size_end", array);
1098         SuperClassWriter::addAttribute("DOMAIN_type",string("box")) ;
1099/*
1100         SuperClassWriter::addAttribute("DOMAIN_DIM_N001",string("x")) ;
1101         SuperClassWriter::addAttribute("DOMAIN_DIM_N002",string("y")) ;
1102         SuperClassWriter::addAttribute("DOMAIN_DIM_N003",string("axis_A")) ;
1103         SuperClassWriter::addAttribute("DOMAIN_DIM_N004",string("time_counter")) ;
1104*/
1105
1106      }
1107      //---------------------------------------------------------------
1108
1109      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
1110                                                const StdString & description,
1111                                                const StdString & conventions,
1112                                                const StdString & production,
1113                                                const StdString & timeStamp)
1114      {
1115         SuperClassWriter::addAttribute("name"       , name);
1116         SuperClassWriter::addAttribute("description", description);
1117         SuperClassWriter::addAttribute("conventions", conventions);
1118         SuperClassWriter::addAttribute("production" , production);
1119         SuperClassWriter::addAttribute("timeStamp"  , timeStamp);
1120      }
1121
1122      //---------------------------------------------------------------
1123
1124      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
1125                                               int data_dim,
1126                                               int data_ni,
1127                                               int data_nj,
1128                                               int data_ibegin,
1129                                               int data_jbegin)
1130      {
1131         SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
1132         SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
1133         SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
1134         SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
1135         SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
1136      }
1137
1138      ///--------------------------------------------------------------
1139
1140} // namespace xios
Note: See TracBrowser for help on using the repository browser.