source: XIOS/dev/dev_rv/src/xmlio/output/nc4_data_output.cpp @ 1620

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