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

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