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

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

Corrections après tests sur titane

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