Salome HOME
Fix problem of make distcheck
[modules/med.git] / src / MEDMEM / MEDMEM_VtkFieldDriver.hxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #ifndef VTK_FIELD_DRIVER_HXX
24 #define VTK_FIELD_DRIVER_HXX
25
26 #include <string>
27 #include <fstream>
28 #include <sstream>
29
30 #include "MEDMEM_define.hxx"
31
32 #include "MEDMEM_GenDriver.hxx"
33 #include "MEDMEM_Utilities.hxx"
34
35 #include "MEDMEM_STRING.hxx"
36 #include "MEDMEM_Exception.hxx"
37 #include "MEDMEM_Unit.hxx"
38 #include "MEDMEM_nArray.hxx"
39 #include "MEDMEM_ArrayConvert.hxx"
40 #include "MEDMEM_Support.hxx"
41 #include "MEDMEM_Mesh.hxx"
42 #include "MEDMEM_CellModel.hxx"
43 #include "MEDMEM_VtkMeshDriver.hxx"
44
45 #ifdef WIN32
46 #include <io.h>
47 #else
48 #include <unistd.h>
49 #endif
50 #include <fcntl.h>
51
52 /*!
53
54   Driver Med for FIELD.
55
56   Generic part : implement open and close methods.
57
58 */
59
60 namespace MEDMEM {
61 template <class T> class VTK_FIELD_DRIVER : public GENDRIVER
62 {
63 protected:
64   
65   const FIELD<T> *           _ptrField;
66   std::string                _fieldName;
67   int                        _fieldNum;
68
69   mutable ofstream *         _vtkFile ;
70   mutable _VTK_BinaryWriter* _binaryFile;
71
72 public :
73
74   /*!
75     Constructor.
76   */
77   VTK_FIELD_DRIVER():GENDRIVER(VTK_DRIVER),
78                      _ptrField(0), _fieldName(""), _fieldNum(MED_EN::MED_INVALID),
79                      _vtkFile(0), _binaryFile(0)
80   {
81     const char * LOC = "VTK_FIELD_DRIVER::VTK_FIELD_DRIVER() ";
82     BEGIN_OF_MED(LOC);
83     END_OF_MED(LOC);
84   }
85   /*!
86     Constructor.
87   */
88   template <class INTERLACING_TAG>
89   VTK_FIELD_DRIVER(const std::string &              fileName,
90                    const FIELD<T, INTERLACING_TAG> * ptrField):
91     GENDRIVER(fileName, MED_EN::WRONLY, VTK_DRIVER),
92     _ptrField((const FIELD<T> *) ptrField), _fieldName(fileName),_fieldNum(MED_EN::MED_INVALID),
93     _vtkFile(0), _binaryFile(0)
94   {
95     const char* LOC = "VTK_FIELD_DRIVER::VTK_FIELD_DRIVER(const string & fileName, FIELD<T> * ptrField) ";
96     BEGIN_OF_MED(LOC);
97     END_OF_MED(LOC);
98   }
99
100   /*!
101     Copy constructor.
102   */
103   VTK_FIELD_DRIVER(const VTK_FIELD_DRIVER & fieldDriver):
104     GENDRIVER(fieldDriver),
105     _ptrField(fieldDriver._ptrField),
106     _fieldName(fieldDriver._fieldName),
107     _fieldNum(fieldDriver._fieldNum),
108     _vtkFile(0), _binaryFile(0)
109   {
110   }
111
112   /*!
113     Destructor.
114   */
115   ~VTK_FIELD_DRIVER()
116   {
117     const char* LOC = "VTK_FIELD_DRIVER::~VTK_FIELD_DRIVER()";
118     BEGIN_OF_MED(LOC);
119
120     close();
121
122     if ( _vtkFile )    delete _vtkFile ;
123     if ( _binaryFile ) delete _binaryFile;
124
125     _vtkFile = 0;
126     _binaryFile = 0;
127
128     END_OF_MED(LOC);
129   }
130
131   void openConst(bool append=false) const throw (MEDEXCEPTION)
132   {
133     const char * LOC = "VTK_FIELD_DRIVER::openConst()" ;
134     BEGIN_OF_MED(LOC);
135
136   if ( _fileName == "" )
137     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
138                                      << "_fileName is |\"\"|, please set a correct fileName before calling open()"));
139
140   if ( DRIVERFACTORY::getVtkBinaryFormatForWriting() )
141     {
142       if ( _vtkFile )
143         {
144           closeConst();
145           delete _vtkFile;
146           _vtkFile = 0;
147         }
148       if ( !_binaryFile )
149         _binaryFile = new _VTK_BinaryWriter( _fileName );
150       else
151         _binaryFile->close();
152       if (!_binaryFile->open(append))
153         {
154           delete _binaryFile;
155           _binaryFile = 0;
156           throw MED_EXCEPTION( LOCALIZED( STRING(LOC) << "Could not open file "<< _fileName));
157         }
158     }
159   else
160     {
161       if ( _binaryFile )
162         {
163           _binaryFile->close();
164           delete _binaryFile;
165           _binaryFile = 0;
166         }
167  
168       if (!_vtkFile )
169         _vtkFile = new ofstream();
170       else
171         (*_vtkFile).close();
172
173       if ( append )
174         (*_vtkFile).open(_fileName.c_str(), ofstream::out | ofstream::app);
175       else
176         (*_vtkFile).open(_fileName.c_str()); 
177
178       if (!(*_vtkFile))
179         {
180           delete _vtkFile;
181           _vtkFile = 0;
182           throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) << "Could not open file "<< _fileName));
183         }
184     }
185     END_OF_MED(LOC);
186   }
187
188   void openConstAppend() const throw (MEDEXCEPTION)
189   {
190     openConst(true);
191   }
192
193   void open() throw (MEDEXCEPTION)
194   {
195     openConst() ;
196   }
197
198   void openAppend() throw (MEDEXCEPTION)
199   {
200     openConst(true) ;
201   }
202
203   void closeConst() const throw (MEDEXCEPTION)
204   {
205     const char * LOC = "VTK_FIELD_DRIVER::closeConst() " ;
206     BEGIN_OF_MED(LOC);
207
208     if ( _vtkFile )
209       {
210         if ((*_vtkFile).is_open())
211           (*_vtkFile).close();
212
213         if ( (*_vtkFile) && _vtkFile->is_open() )
214           throw MED_EXCEPTION( LOCALIZED( STRING(LOC) << "Could not close file "<< _fileName));
215       }
216     if ( _binaryFile )
217       {
218         _binaryFile->close();
219         delete _binaryFile;
220         _binaryFile = 0;
221       }
222
223     END_OF_MED(LOC);
224   }
225
226   void close() {
227     closeConst() ;
228   }
229
230   /*!
231     Set the name of the FIELD asked in file.
232
233     It could be different than the name of the FIELD object.
234   */
235   void   setFieldName(const string & fieldName) ;
236
237   /*!
238     Get the name of the FIELD asked in file.
239   */
240   string getFieldName() const ;
241
242   /*!
243     Return a MEDEXCEPTION : it is the write-only driver.
244   */
245   void read ( void ) throw (MEDEXCEPTION) ;
246
247   /*!
248     Write FIELD in the specified file, with its mesh through its support
249     which has to be on all entities (excluding the faces in 3d and edges
250     in 2d).
251   */
252   void write( void ) const throw (MEDEXCEPTION) ;
253
254   /*!
255     Write FIELD in the specified file, the mesh is supposed to be
256     written in this file. The field support has to be on all entities
257     (excluding the faces in 3d and edges in 2d).
258   */
259   void writeAppend( void ) const throw (MEDEXCEPTION);
260
261 private:
262   GENDRIVER * copy ( void ) const ;
263
264 };
265
266   /*-------------------------*/
267   /* template implementation */
268   /*-------------------------*/
269
270 /*--------------------- DRIVER PART -------------------------------*/
271
272 template <class T> void VTK_FIELD_DRIVER<T>::setFieldName(const string & fieldName)
273 {
274   _fieldName = fieldName; 
275 }
276
277 template <class T> string  VTK_FIELD_DRIVER<T>::getFieldName() const
278 {
279   return _fieldName;
280 }
281
282 template <class T> GENDRIVER * VTK_FIELD_DRIVER<T>::copy(void) const
283 {
284   VTK_FIELD_DRIVER<T> * myDriver = new VTK_FIELD_DRIVER<T>(*this);
285
286   return myDriver ;
287 }
288
289 template <class T> void VTK_FIELD_DRIVER<T>::read (void)
290   throw (MEDEXCEPTION)
291 {
292   throw MEDEXCEPTION("VTK_FIELD_DRIVER::read : Can't read with a VTK driver because it is write only driver !");
293 }
294
295 //================================================================================
296 /*!
297  * \brief Write
298  */
299 //================================================================================
300
301 template <class T> void VTK_FIELD_DRIVER<T>::write(void) const
302   throw (MEDEXCEPTION)
303 {
304   const char * LOC = "VTK_FIELD_DRIVER::write(void) const " ;
305   BEGIN_OF_MED(LOC);
306
307   // we get the Support and its associated Mesh
308
309   const SUPPORT * supportField = _ptrField->getSupport();
310   const GMESH * meshField = supportField->getMesh();
311   if (! meshField )
312     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<": mesh was not read before writing")) ;
313
314   // first, write mesh
315   {
316     VTK_MESH_DRIVER meshDriver( _fileName, meshField );
317     meshDriver.write();
318   }
319
320   // write field
321   writeAppend();
322 }
323
324 //================================================================================
325 /*!
326  * \brief Write append
327  */
328 //================================================================================
329
330 template <class T> void VTK_FIELD_DRIVER<T>::writeAppend(void) const
331   throw (MEDEXCEPTION)
332 {
333   const char * LOC = "VTK_FIELD_DRIVER::writeAppend(void) const " ;
334   BEGIN_OF_MED(LOC);
335
336   // we get the Support and its associated Mesh
337
338   const SUPPORT * supportField = _ptrField->getSupport();
339   const GMESH * meshField = supportField->getMesh();
340   MED_EN::medEntityMesh entitySupport = supportField->getEntity();
341
342   if (! meshField )
343     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<": mesh was not read before writing")) ;
344
345   if ( _ptrField->getGaussPresence() )
346     throw MED_EXCEPTION(LOCALIZED(STRING(LOC) << "Could not write field "<<_ptrField->getName()<<" which use Gauss Points !" << entitySupport));
347
348   if (!(supportField->isOnAllElements()))
349     throw MED_EXCEPTION(LOCALIZED(STRING(LOC) << "Could not write field "<<_ptrField->getName()<<" which is not on all entities of the mesh !" << entitySupport));
350
351
352   // Well we must open vtk file first, because there are
353   // no other driver than MED for VTK that do it !
354   openConstAppend() ;
355
356   // first : field on node
357   // fields is on all node !
358
359   // second : field on cell
360   // fields is on all cell !
361
362   int dt = _ptrField->getIterationNumber();
363   int it = _ptrField->getOrderNumber();
364
365   ostringstream name ;
366   string nameField = _ptrField->getName();
367   name << nameField << "_" << dt << "_" << it ;
368
369   // BEGIN issue 0020610: [CEA 371] VTK field driver : save many fields.
370   // POINT_DATA and CELL_DATA must encounters once
371   STRING dataStr;
372   if (entitySupport == MED_EN::MED_NODE)
373     dataStr << "POINT_DATA " << meshField->getNumberOfNodes() ;
374   else if (entitySupport == MED_EN::MED_CELL)
375     dataStr << "CELL_DATA " << meshField->getNumberOfElements(MED_EN::MED_CELL,MED_EN::MED_ALL_ELEMENTS);
376   else
377     throw MED_EXCEPTION(LOCALIZED(STRING(LOC) << "Could not write field "<<_ptrField->getName()<<" which is not on all nodes or cells but it's on !" << entitySupport));
378
379   // check if dataStr is already present in the file
380   bool toWriteDataStr = true;
381 #ifdef WIN32
382   int vtkFile = ::_open (_fileName.c_str(), _O_RDONLY|_O_BINARY);
383 #else
384   int vtkFile = ::open (_fileName.c_str(), O_RDONLY);
385 #endif
386   if ( vtkFile > 0 )
387   {
388 #ifdef WIN32
389     ssize_t fileSize = ::_lseek( vtkFile, 0, SEEK_END); ::lseek( vtkFile, 0, SEEK_SET);
390     char* buf = new char[ fileSize ];
391     ::_read (vtkFile, buf, fileSize );
392 #else
393     ssize_t fileSize = ::lseek( vtkFile, 0, SEEK_END); ::lseek( vtkFile, 0, SEEK_SET);
394     char* buf = new char[ fileSize ];
395     ::read (vtkFile, buf, fileSize );
396 #endif
397     char *vtkData = buf, *vtkDataEnd = buf+fileSize-dataStr.size();
398     while ( ++vtkData < vtkDataEnd && toWriteDataStr )
399       toWriteDataStr = ( strncmp( dataStr.data(), vtkData, dataStr.size()) != 0 );
400     delete [] buf;
401 #ifdef WIN32
402     ::_close (vtkFile);
403 #else
404     ::close (vtkFile);
405 #endif
406   }
407   std::ostringstream vtkFileStr; // to collect labels
408   if ( _binaryFile )
409     vtkFileStr << endl;
410   if ( toWriteDataStr )
411     vtkFileStr << dataStr << endl;
412   // END issue 0020610: [CEA 371] VTK field driver : save many fields
413
414   int NomberOfValue = supportField->getNumberOfElements(MED_EN::MED_ALL_ELEMENTS) ;
415   int NomberOfComponents =  _ptrField->getNumberOfComponents() ;
416
417   MED_EN::med_type_champ fieldType = _ptrField->getValueType() ;
418
419   SCRUTE_MED(name.str());
420   SCRUTE_MED(fieldType);
421
422   std::string typeStr;
423   switch (fieldType)
424     {
425     case MED_EN::MED_INT32 :
426       {
427         typeStr = " int"; break ;
428       }
429     case MED_EN::MED_REEL64 :
430       {
431         typeStr = " float"; break ;
432       }
433     default :
434       {
435         throw MED_EXCEPTION(LOCALIZED(STRING(LOC) << "Could not write field "<< name.str() <<" the type is not int or double !"));
436       }
437     }
438
439   if (NomberOfComponents==3)
440     vtkFileStr << "VECTORS " << name.str() << typeStr << endl ;
441   else if (NomberOfComponents<=4)
442     {
443       vtkFileStr << "SCALARS " << name.str() << typeStr << " " << NomberOfComponents << endl ;
444       vtkFileStr << "LOOKUP_TABLE default" << endl ;
445     }
446   else
447     throw MED_EXCEPTION(LOCALIZED(STRING(LOC) << "Could not write field "<<_ptrField->getName()<<" there are more than 4 components !"));
448
449   const T * value ;
450   MEDMEM_Array_ * tmpArray = 0;
451   if ( _ptrField->getInterlacingType() == MED_EN::MED_FULL_INTERLACE )
452     {
453       value = _ptrField->getValue();
454     }
455   else if ( _ptrField->getInterlacingType() == MED_EN::MED_NO_INTERLACE_BY_TYPE )
456     {
457       MEDMEM_Array_ * ptrArray = _ptrField->getArray();
458       MEDMEM_Array<T,NoInterlaceByTypeNoGaussPolicy> * temp = dynamic_cast<MEDMEM_Array<T,NoInterlaceByTypeNoGaussPolicy> * >  ( ptrArray );
459       MEDMEM_Array<T,NoInterlaceNoGaussPolicy> * array = ArrayConvert2No( *temp );
460       tmpArray = array;
461       value = array->getPtr();
462     }
463   else
464     {
465       MEDMEM_Array_ * ptrArray = _ptrField->getArray();
466       MEDMEM_Array<T,NoInterlaceNoGaussPolicy> * temp = dynamic_cast<MEDMEM_Array<T,NoInterlaceNoGaussPolicy> * >  ( ptrArray );
467       MEDMEM_Array<T,FullInterlaceNoGaussPolicy> * array = ArrayConvert( *temp );
468       tmpArray = array;
469       value = array->getPtr();
470     }
471
472   if ( _vtkFile ) // ASCII
473     {
474       (*_vtkFile) << vtkFileStr.str();
475       for (int i=0; i<NomberOfValue; i++)
476         {
477           for(int j=0; j<NomberOfComponents; j++)
478             (*_vtkFile) << value[j*NomberOfValue+i] << " " ;
479           (*_vtkFile) << endl ;
480         }
481     }
482   else // BINARY
483     {
484       std::string str = vtkFileStr.str();
485       _binaryFile->write( str.data(), str.size() );
486       // Though type "double" is available in VTK but actually it does not work
487       // (at least paraview shows wrong values)
488       if ( fieldType == MED_EN::MED_REEL64 )
489         {
490           vector<float> floatValue(NomberOfValue * NomberOfComponents );
491           for ( unsigned i = 0; i < floatValue.size(); ++i )
492             floatValue[i]=float( value[i] );
493           _binaryFile->write( &floatValue[0], NomberOfValue * NomberOfComponents );
494         }
495       else
496         {
497           _binaryFile->write( value, NomberOfValue * NomberOfComponents );
498         }
499     }
500
501   if ( _ptrField->getInterlacingType() != MED_EN::MED_FULL_INTERLACE )
502     delete tmpArray;
503
504   closeConst();
505
506   END_OF_MED(LOC);
507 }
508 }//End namespace MEDMEM
509
510 #endif /* VTK_FIELD_DRIVER_HXX */