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

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