source: XMLIO_V2/dev/dev_rv/src/xmlio/output/nc4_data_output.cpp @ 267

Last change on this file since 267 was 267, checked in by hozdoba, 13 years ago
File size: 20.5 KB
Line 
1
2#include "nc4_data_output.hpp"
3
4#include <boost/lexical_cast.hpp>
5#include "attribute_template_impl.hpp"
6
7#include "file.hpp"
8#include "calendar.hpp"
9
10namespace xmlioserver
11{
12   namespace io
13   {
14      /// ////////////////////// Définitions ////////////////////// ///
15      CNc4DataOutput::CNc4DataOutput
16         (const StdString & filename, bool exist)
17            : SuperClass()
18            , SuperClassWriter(filename, exist)
19            , filename(filename)
20      {
21         StdString timeid = StdString("time_counter");
22         SuperClass::type = MULTI_FILE;
23         if (!exist)
24            SuperClassWriter::addDimension(timeid);
25      }
26
27      CNc4DataOutput::CNc4DataOutput
28         (const StdString & filename, bool exist, bool multigroup, MPI_Comm comm_server)
29            : SuperClass()
30            , SuperClassWriter(filename, exist, &comm_server)
31            , comm_server(comm_server)
32            , filename(filename)
33      {
34         StdString timeid = StdString("time_counter");
35         SuperClass::type = (multigroup) ? MULTI_GROUP : ONE_FILE;
36         if (!exist)
37            SuperClassWriter::addDimension(timeid);
38      }
39
40      CNc4DataOutput::CNc4DataOutput
41         (const StdString & filename, bool exist, bool multigroup, comm::MPIComm comm_server, bool)
42            : SuperClass()
43            , SuperClassWriter(filename, exist, &comm_server, true)
44            , filename(filename)
45      {
46         StdString timeid = StdString("time_counter");
47         SuperClass::type = (multigroup) ? MULTI_GROUP : ONE_FILE;
48         if (!exist)
49            SuperClassWriter::addDimension(timeid);
50      }
51
52      CNc4DataOutput::~CNc4DataOutput(void)
53      { /* Ne rien faire de plus */ }
54
55      ///--------------------------------------------------------------
56
57      const StdString & CNc4DataOutput::getFileName(void) const
58      {
59         return (this->filename);
60      }
61
62      //---------------------------------------------------------------
63
64      void CNc4DataOutput::writeDomain_(const boost::shared_ptr<tree::CDomain> domain)
65      {
66         if (domain->IsWritten(this->filename)) return;
67         domain->checkAttributes();
68         
69         if (domain->isEmpty()) return;
70
71         std::vector<StdString> dim0, dim1;
72         StdString domid     = (!domain->name.isEmpty())
73                             ? domain->name.getValue() : domain->getId();
74         StdString lonid     = StdString("lon_").append(domid);
75         StdString latid     = StdString("lat_").append(domid);
76         StdString lonid_loc = StdString("lon_").append(domid).append("_local");
77         StdString latid_loc = StdString("lat_").append(domid).append("_local");
78         StdString maskid    = StdString("mask_").append(domid).append("_local");
79
80         ARRAY(int, 2) mask = domain->getLocalMask();
81
82         unsigned int ssize = domain->zoom_ni_loc.getValue() * domain->zoom_nj_loc.getValue();
83         bool isCurvilinear = (domain->lonvalue.getValue()->size() == ssize);
84
85         SuperClassWriter::addDimension(lonid, domain->ni_glo.getValue());
86         SuperClassWriter::addDimension(latid, domain->nj_glo.getValue());
87
88         if (isCurvilinear)
89         {
90            dim0.push_back(latid_loc); dim0.push_back(lonid_loc);
91            lonid = StdString("nav_lon_").append(domid);
92            latid = StdString("nav_lat_").append(domid);
93         }
94         else
95         {
96            dim0.push_back(latid_loc);
97            dim1.push_back(lonid_loc);
98         }
99         switch (SuperClass::type)
100         {
101            case (MULTI_FILE) :
102            {
103               SuperClassWriter::addDimension(lonid_loc, domain->zoom_ni_loc.getValue());
104               SuperClassWriter::addDimension(latid_loc, domain->zoom_nj_loc.getValue());
105               this->writeLocalAttributes(domain->zoom_ibegin_loc.getValue(),
106                                          domain->zoom_ni_loc.getValue(),
107                                          domain->zoom_jbegin_loc.getValue(),
108                                          domain->zoom_nj_loc.getValue(),
109                                          domid);
110               if (isCurvilinear)
111               {
112                  SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
113                  SuperClassWriter::addVariable(lonid, NC_FLOAT, dim0);
114               }
115               else
116               {
117                  SuperClassWriter::addVariable(latid, NC_FLOAT, dim0);
118                  SuperClassWriter::addVariable(lonid, NC_FLOAT, dim1);
119               }
120               this->writeAxisAttributes
121                  (latid, "X", "longitude", "Longitude", "degrees_east", domid);
122               this->writeAxisAttributes
123                  (lonid, "Y", "latitude", "Latitude", "degrees_north", domid);
124
125               dim0.clear();
126               dim0.push_back(latid_loc);
127               dim0.push_back(lonid_loc);
128
129               SuperClassWriter::addVariable(maskid, NC_INT, dim0);
130
131               this->writeMaskAttributes(maskid,
132                  domain->data_dim.getValue()/*,
133                  domain->data_ni.getValue(),
134                  domain->data_nj.getValue(),
135                  domain->data_ibegin.getValue(),
136                  domain->data_jbegin.getValue()*/);
137                 
138               //SuperClassWriter::setDefaultValue(maskid, &dvm);
139
140               SuperClassWriter::definition_end();
141               SuperClassWriter::writeData(domain->latvalue.getValue(), latid, true, 0);
142               SuperClassWriter::writeData(domain->lonvalue.getValue(), lonid, true, 0);
143               SuperClassWriter::writeData(mask, maskid);
144               SuperClassWriter::definition_start();
145
146               break;
147            }
148            default :
149               ERROR("CNc4DataOutput::writeDomain(domain)",
150                     << "[ type = " << SuperClass::type << "]"
151                     << " not implemented yet !");
152         }
153         domain->addRelFile(this->filename);
154      }
155
156      //--------------------------------------------------------------
157
158      void CNc4DataOutput::writeAxis_(const boost::shared_ptr<tree::CAxis> axis)
159      {
160         if (axis->IsWritten(this->filename)) return;
161         axis->checkAttributes();
162         std::vector<StdString> dims;
163         StdString axisid = (!axis->name.isEmpty())
164                           ? axis->name.getValue() : axis->getId();
165         SuperClassWriter::addDimension(axisid, axis->size.getValue());
166         dims.push_back(axisid);
167
168         switch (SuperClass::type)
169         {
170            case (MULTI_FILE) :
171            {
172               SuperClassWriter::addVariable(axisid, NC_FLOAT, dims);
173
174               SuperClassWriter::addAttribute("axis", StdString("Z"), &axisid);
175
176               if (!axis->standard_name.isEmpty())
177                  SuperClassWriter::addAttribute
178                     ("standard_name",  axis->standard_name.getValue(), &axisid);
179
180               if (!axis->long_name.isEmpty())
181                  SuperClassWriter::addAttribute
182                     ("long_name", axis->long_name.getValue(), &axisid);
183
184               if (!axis->unit.isEmpty())
185                  SuperClassWriter::addAttribute
186                     ("units", axis->unit.getValue(), &axisid);
187
188               SuperClassWriter::definition_end();
189               SuperClassWriter::writeData(axis->zvalue.getValue(), axisid, true, 0);
190               SuperClassWriter::definition_start();
191
192               break;
193            }
194            default :
195               ERROR("CNc4DataOutput::writeDomain(domain)",
196                     << "[ type = " << SuperClass::type << "]"
197                     << " not implemented yet !");
198         }
199         axis->addRelFile(this->filename);
200      }
201
202      //--------------------------------------------------------------
203
204      void CNc4DataOutput::writeField_(const boost::shared_ptr<tree::CField> field)
205      {
206         std::vector<StdString> dims, coodinates;
207         boost::shared_ptr<CGrid> grid =
208            CObjectFactory::GetObject<CGrid>(field->grid_ref.getValue());
209         boost::shared_ptr<CDomain> domain =
210            CObjectFactory::GetObject<CDomain>(grid->domain_ref.getValue());
211           
212         if (domain->isEmpty()) return;
213
214         StdString timeid    = StdString("time_counter");
215         StdString domid     = (!domain->name.isEmpty())
216                             ? domain->name.getValue() : domain->getId();
217         StdString lonid     = StdString("lon_").append(domid);
218         StdString latid     = StdString("lat_").append(domid);
219         StdString lonid_loc = StdString("lon_").append(domid).append("_local");
220         StdString latid_loc = StdString("lat_").append(domid).append("_local");
221         StdString fieldid   = (!field->name.isEmpty())
222                             ? field->name.getValue() : field->getBaseFieldReference()->getId();
223
224         unsigned int ssize = domain->zoom_ni_loc.getValue() * domain->zoom_nj_loc.getValue();
225         bool isCurvilinear = (domain->lonvalue.getValue()->size() == ssize);
226
227         nc_type type = (!field->prec.isEmpty() &&
228                        ( field->prec.getValue() == 4))
229                        ? NC_FLOAT : NC_DOUBLE;
230         bool wtime   = !(!field->operation.isEmpty() &&
231                         ( field->operation.getValue().compare("once") == 0));
232                         
233         if (wtime)
234         {
235            StdOStringStream oss;
236            oss << "time_" << field->operation.getValue()
237                << "_" << field->getRelFile()->output_freq.getValue();
238
239            coodinates.push_back(oss.str());
240            dims.push_back(timeid);
241         }
242
243         if (!grid->axis_ref.isEmpty())
244         {
245            boost::shared_ptr<CAxis> axis =
246               CObjectFactory::GetObject<CAxis>(grid->axis_ref.getValue());
247            StdString axisid = (!axis->name.isEmpty())
248                             ? axis->name.getValue() : axis->getId();
249            dims.push_back(axisid);
250            coodinates.push_back(axisid);
251         }
252
253         if (isCurvilinear)
254         {
255            coodinates.push_back(StdString("nav_lat_").append(domid));
256            coodinates.push_back(StdString("nav_lon_").append(domid));
257         }
258         else
259         {
260            coodinates.push_back(latid);
261            coodinates.push_back(lonid);
262         }
263
264         switch (SuperClass::type)
265         {
266            case (MULTI_FILE) :
267            {
268               dims.push_back(latid_loc);
269               dims.push_back(lonid_loc);
270               SuperClassWriter::addVariable(fieldid, type, dims);
271
272               if (!field->standard_name.isEmpty())
273                  SuperClassWriter::addAttribute
274                     ("standard_name",  field->standard_name.getValue(), &fieldid);
275
276               if (!field->long_name.isEmpty())
277                  SuperClassWriter::addAttribute
278                     ("long_name", field->long_name.getValue(), &fieldid);
279
280               if (!field->unit.isEmpty())
281                  SuperClassWriter::addAttribute
282                     ("units", field->unit.getValue(), &fieldid);
283                     
284               SuperClassWriter::addAttribute
285                     ("online_operation", field->operation.getValue(), &fieldid);
286                     
287               if (wtime)
288               {
289                  SuperClassWriter::addAttribute
290                        ("interval_operation", field->freq_op.getValue(), &fieldid);
291                  SuperClassWriter::addAttribute
292                        ("interval_write", field->getRelFile()->output_freq.getValue(), &fieldid);
293               }
294               
295               if (!field->default_value.isEmpty())
296               {
297                  double default_value = field->default_value.getValue();
298                  float fdefault_value = (float)default_value;
299                  if (type == NC_DOUBLE)
300                     SuperClassWriter::setDefaultValue(fieldid, &default_value);
301                  else
302                     SuperClassWriter::setDefaultValue(fieldid, &fdefault_value);
303               }
304               else
305               {
306                  double * default_value = NULL;
307                  SuperClassWriter::setDefaultValue(fieldid, default_value);
308               }             
309
310               {  // Ecriture des coordonnées
311               
312                  StdString coordstr; //boost::algorithm::join(coodinates, " ")
313                  std::vector<StdString>::iterator
314                     itc = coodinates.begin(), endc = coodinates.end();
315                 
316                  for (; itc!= endc; itc++)
317                  {
318                     StdString & coord = *itc;
319                     if (itc+1 != endc)
320                           coordstr.append(coord).append(" ");
321                     else  coordstr.append(coord);
322                  }
323
324                  SuperClassWriter::addAttribute("coordinates", coordstr, &fieldid);
325
326               }
327
328               break;
329            }
330            default :
331               ERROR("CNc4DataOutput::writeDomain(domain)",
332                     << "[ type = " << SuperClass::type << "]"
333                     << " not implemented yet !");
334         }
335      }
336
337      //--------------------------------------------------------------
338
339      void CNc4DataOutput::writeFile_ (const boost::shared_ptr<tree::CFile> file)
340      {
341         StdString filename = (!file->name.isEmpty())
342                            ? file->name.getValue() : file->getId();
343         StdString description = (!file->description.isEmpty())
344                               ? file->description.getValue()
345                               : StdString("Created by xmlioserver");
346         this->writeFileAttributes(filename, description,
347                                   StdString ("CF-1.1"),
348                                   StdString("An IPSL model"),
349                                   this->getTimeStamp());
350      }
351
352      //---------------------------------------------------------------
353
354      StdString CNc4DataOutput::getTimeStamp(void) const
355      {
356         const int buffer_size = 100;
357         time_t rawtime;
358         struct tm * timeinfo = NULL;
359         char buffer [buffer_size];
360
361         time ( &rawtime );
362         timeinfo = localtime ( &rawtime );
363         strftime (buffer, buffer_size, "%Y-%b-%d %H:%M:%S %Z", timeinfo);
364
365         return (StdString(buffer));
366      }
367     
368      //---------------------------------------------------------------
369     
370      void CNc4DataOutput::writeFieldData_ (const boost::shared_ptr<tree::CField>  field)
371      {
372         boost::shared_ptr<CGrid> grid =
373            CObjectFactory::GetObject<CGrid>(field->grid_ref.getValue());
374         StdString fieldid   = (!field->name.isEmpty())
375                             ? field->name.getValue() 
376                             : field->getBaseFieldReference()->getId();
377         ARRAY(double, 1) field_data = field->getData();
378         
379         if (grid->hasAxis()) // 3D
380         {
381            ARRAY(double, 3) field_data3D (new CArray<double,3>(grid->getLocalShape()/*, boost::c_storage_order()*/));           
382            grid->outputField(field_data, field_data3D);
383            SuperClassWriter::writeData(field_data3D, fieldid, true, field->getNStep()-1);
384           
385         }
386         else // 2D
387         {
388            ARRAY(double, 2) field_data2D (new CArray<double, 2>(grid->getLocalShape()/*, boost::c_storage_order()*/));
389            grid->outputField(field_data,  field_data2D);
390            SuperClassWriter::writeData(field_data2D, fieldid, true, field->getNStep()-1);
391         }
392      }
393
394      //---------------------------------------------------------------
395
396      void CNc4DataOutput::writeTimeAxis_
397                  (const boost::shared_ptr<tree::CField>    field,
398                   const boost::shared_ptr<date::CCalendar> cal)
399      {
400         StdOStringStream oss;
401         oss << "time_" << field->operation.getValue()
402             << "_" << field->getRelFile()->output_freq.getValue();
403
404         std::vector<StdString> dims;
405         StdString axisid = oss.str();
406         StdString timeid = StdString("time_counter");
407
408         dims.push_back(timeid);
409         if (!SuperClassWriter::varExist(axisid))
410         {
411            SuperClassWriter::addVariable(axisid, NC_DOUBLE, dims);
412            this->writeTimeAxisAttributes
413               (axisid, cal->getId(),
414                StdString("seconds since ").append(cal->getInitDate().toString()),
415                cal->getInitDate().toString());
416         }
417
418      }
419
420      //---------------------------------------------------------------
421     
422      void CNc4DataOutput::writeTimeAxisAttributes(const StdString & axis_name,
423                                                   const StdString & calendar,
424                                                   const StdString & units,
425                                                   const StdString & time_origin,
426                                                   const StdString & standard_name,
427                                                   const StdString & long_name,
428                                                   const StdString & title)
429      {
430         SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
431         SuperClassWriter::addAttribute("long_name",     long_name    , &axis_name);
432         SuperClassWriter::addAttribute("title",         title        , &axis_name);
433         SuperClassWriter::addAttribute("calendar",      calendar     , &axis_name);
434         SuperClassWriter::addAttribute("units",         units        , &axis_name);
435         SuperClassWriter::addAttribute("time_origin",   time_origin  , &axis_name);
436      }
437     
438      //---------------------------------------------------------------
439
440      void CNc4DataOutput::writeAxisAttributes(const StdString & axis_name,
441                                               const StdString & axis,
442                                               const StdString & standard_name,
443                                               const StdString & long_name,
444                                               const StdString & units,
445                                               const StdString & nav_model)
446      {
447         SuperClassWriter::addAttribute("axis"         , axis         , &axis_name);
448         SuperClassWriter::addAttribute("standard_name", standard_name, &axis_name);
449         SuperClassWriter::addAttribute("long_name"    , long_name    , &axis_name);
450         SuperClassWriter::addAttribute("units"        , units        , &axis_name);
451         SuperClassWriter::addAttribute("nav_model"    , nav_model    , &axis_name);
452      }
453
454      //---------------------------------------------------------------
455     
456      void CNc4DataOutput::writeLocalAttributes
457         (int ibegin, int ni, int jbegin, int nj, StdString domid)
458      {
459         SuperClassWriter::addAttribute(StdString("ibegin_").append(domid), ibegin);
460         SuperClassWriter::addAttribute(StdString("ni_"    ).append(domid), ni);
461         SuperClassWriter::addAttribute(StdString("jbegin_").append(domid), jbegin);
462         SuperClassWriter::addAttribute(StdString("nj_"    ).append(domid), nj);
463      }
464
465      //---------------------------------------------------------------
466
467      void CNc4DataOutput:: writeFileAttributes(const StdString & name,
468                                                const StdString & description,
469                                                const StdString & conventions,
470                                                const StdString & production,
471                                                const StdString & timeStamp)
472      {
473         SuperClassWriter::addAttribute("name"       , name);
474         SuperClassWriter::addAttribute("description", description);
475         SuperClassWriter::addAttribute("conventions", conventions);
476         SuperClassWriter::addAttribute("production" , production);
477         SuperClassWriter::addAttribute("timeStamp"  , timeStamp);
478      }
479
480      //---------------------------------------------------------------
481
482      void CNc4DataOutput::writeMaskAttributes(const StdString & mask_name,
483                                               int data_dim,
484                                               int data_ni,
485                                               int data_nj,
486                                               int data_ibegin,
487                                               int data_jbegin)
488      {
489         SuperClassWriter::addAttribute("data_dim"   , data_dim   , &mask_name);
490         SuperClassWriter::addAttribute("data_ni"    , data_ni    , &mask_name);
491         SuperClassWriter::addAttribute("data_nj"    , data_nj    , &mask_name);
492         SuperClassWriter::addAttribute("data_ibegin", data_ibegin, &mask_name);
493         SuperClassWriter::addAttribute("data_jbegin", data_jbegin, &mask_name);
494      }
495
496      ///--------------------------------------------------------------
497
498   } // namespace io
499} // namespace xmlioserver
Note: See TracBrowser for help on using the repository browser.