source: XMLIO_V2/dev/common/src/xmlio/output/nc4_data_output.cpp @ 219

Last change on this file since 219 was 219, checked in by hozdoba, 13 years ago

Préparation nouvelle arborescence

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