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

Last change on this file since 276 was 276, checked in by hozdoba, 10 years ago

Corrections de bugs

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