Back to index

salome-med  6.5.0
MEDMEM_VtkFieldDriver.hxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 #ifndef VTK_FIELD_DRIVER_HXX
00024 #define VTK_FIELD_DRIVER_HXX
00025 
00026 #include <string>
00027 #include <fstream>
00028 #include <sstream>
00029 
00030 #include "MEDMEM_define.hxx"
00031 
00032 #include "MEDMEM_GenDriver.hxx"
00033 #include "MEDMEM_Utilities.hxx"
00034 
00035 #include "MEDMEM_STRING.hxx"
00036 #include "MEDMEM_Exception.hxx"
00037 #include "MEDMEM_Unit.hxx"
00038 #include "MEDMEM_nArray.hxx"
00039 #include "MEDMEM_ArrayConvert.hxx"
00040 #include "MEDMEM_Support.hxx"
00041 #include "MEDMEM_Mesh.hxx"
00042 #include "MEDMEM_CellModel.hxx"
00043 #include "MEDMEM_VtkMeshDriver.hxx"
00044 
00045 #ifdef WNT
00046 #include <io.h>
00047 #else
00048 #include <unistd.h>
00049 #endif
00050 #include <fcntl.h>
00051 
00060 namespace MEDMEM {
00061 template <class T> class VTK_FIELD_DRIVER : public GENDRIVER
00062 {
00063 protected:
00064   
00065   const FIELD<T> *           _ptrField;
00066   std::string                _fieldName;
00067   int                        _fieldNum;
00068 
00069   mutable ofstream *         _vtkFile ;
00070   mutable _VTK_BinaryWriter* _binaryFile;
00071 
00072 public :
00073 
00077   VTK_FIELD_DRIVER():GENDRIVER(VTK_DRIVER),
00078                      _ptrField(0), _fieldName(""), _fieldNum(MED_EN::MED_INVALID),
00079                      _vtkFile(0), _binaryFile(0)
00080   {
00081     const char * LOC = "VTK_FIELD_DRIVER::VTK_FIELD_DRIVER() ";
00082     BEGIN_OF_MED(LOC);
00083     END_OF_MED(LOC);
00084   }
00088   template <class INTERLACING_TAG>
00089   VTK_FIELD_DRIVER(const std::string &              fileName,
00090                    const FIELD<T, INTERLACING_TAG> * ptrField):
00091     GENDRIVER(fileName, MED_EN::WRONLY, VTK_DRIVER),
00092     _ptrField((const FIELD<T> *) ptrField), _fieldName(fileName),_fieldNum(MED_EN::MED_INVALID),
00093     _vtkFile(0), _binaryFile(0)
00094   {
00095     const char* LOC = "VTK_FIELD_DRIVER::VTK_FIELD_DRIVER(const string & fileName, FIELD<T> * ptrField) ";
00096     BEGIN_OF_MED(LOC);
00097     END_OF_MED(LOC);
00098   }
00099 
00103   VTK_FIELD_DRIVER(const VTK_FIELD_DRIVER & fieldDriver):
00104     GENDRIVER(fieldDriver),
00105     _ptrField(fieldDriver._ptrField),
00106     _fieldName(fieldDriver._fieldName),
00107     _fieldNum(fieldDriver._fieldNum),
00108     _vtkFile(0), _binaryFile(0)
00109   {
00110   }
00111 
00115   ~VTK_FIELD_DRIVER()
00116   {
00117     const char* LOC = "VTK_FIELD_DRIVER::~VTK_FIELD_DRIVER()";
00118     BEGIN_OF_MED(LOC);
00119 
00120     close();
00121 
00122     if ( _vtkFile )    delete _vtkFile ;
00123     if ( _binaryFile ) delete _binaryFile;
00124 
00125     _vtkFile = 0;
00126     _binaryFile = 0;
00127 
00128     END_OF_MED(LOC);
00129   }
00130 
00131   void openConst(bool append=false) const throw (MEDEXCEPTION)
00132   {
00133     const char * LOC = "VTK_FIELD_DRIVER::openConst()" ;
00134     BEGIN_OF_MED(LOC);
00135 
00136   if ( _fileName == "" )
00137     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
00138                                      << "_fileName is |\"\"|, please set a correct fileName before calling open()"));
00139 
00140   if ( DRIVERFACTORY::getVtkBinaryFormatForWriting() )
00141     {
00142       if ( _vtkFile )
00143         {
00144           closeConst();
00145           delete _vtkFile;
00146           _vtkFile = 0;
00147         }
00148       if ( !_binaryFile )
00149         _binaryFile = new _VTK_BinaryWriter( _fileName );
00150       else
00151         _binaryFile->close();
00152       if (!_binaryFile->open(append))
00153         {
00154           delete _binaryFile;
00155           _binaryFile = 0;
00156           throw MED_EXCEPTION( LOCALIZED( STRING(LOC) << "Could not open file "<< _fileName));
00157         }
00158     }
00159   else
00160     {
00161       if ( _binaryFile )
00162         {
00163           _binaryFile->close();
00164           delete _binaryFile;
00165           _binaryFile = 0;
00166         }
00167  
00168       if (!_vtkFile )
00169         _vtkFile = new ofstream();
00170       else
00171         (*_vtkFile).close();
00172 
00173       if ( append )
00174         (*_vtkFile).open(_fileName.c_str(), ofstream::out | ofstream::app);
00175       else
00176         (*_vtkFile).open(_fileName.c_str()); 
00177 
00178       if (!(*_vtkFile))
00179         {
00180           delete _vtkFile;
00181           _vtkFile = 0;
00182           throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) << "Could not open file "<< _fileName));
00183         }
00184     }
00185     END_OF_MED(LOC);
00186   }
00187 
00188   void openConstAppend() const throw (MEDEXCEPTION)
00189   {
00190     openConst(true);
00191   }
00192 
00193   void open() throw (MEDEXCEPTION)
00194   {
00195     openConst() ;
00196   }
00197 
00198   void openAppend() throw (MEDEXCEPTION)
00199   {
00200     openConst(true) ;
00201   }
00202 
00203   void closeConst() const throw (MEDEXCEPTION)
00204   {
00205     const char * LOC = "VTK_FIELD_DRIVER::closeConst() " ;
00206     BEGIN_OF_MED(LOC);
00207 
00208     if ( _vtkFile )
00209       {
00210         if ((*_vtkFile).is_open())
00211           (*_vtkFile).close();
00212 
00213         if ( (*_vtkFile) && _vtkFile->is_open() )
00214           throw MED_EXCEPTION( LOCALIZED( STRING(LOC) << "Could not close file "<< _fileName));
00215       }
00216     if ( _binaryFile )
00217       {
00218         _binaryFile->close();
00219         delete _binaryFile;
00220         _binaryFile = 0;
00221       }
00222 
00223     END_OF_MED(LOC);
00224   }
00225 
00226   void close() {
00227     closeConst() ;
00228   }
00229 
00235   void   setFieldName(const string & fieldName) ;
00236 
00240   string getFieldName() const ;
00241 
00245   void read ( void ) throw (MEDEXCEPTION) ;
00246 
00252   void write( void ) const throw (MEDEXCEPTION) ;
00253 
00259   void writeAppend( void ) const throw (MEDEXCEPTION);
00260 
00261 private:
00262   GENDRIVER * copy ( void ) const ;
00263 
00264 };
00265 
00266   /*-------------------------*/
00267   /* template implementation */
00268   /*-------------------------*/
00269 
00270 /*--------------------- DRIVER PART -------------------------------*/
00271 
00272 template <class T> void VTK_FIELD_DRIVER<T>::setFieldName(const string & fieldName)
00273 {
00274   _fieldName = fieldName; 
00275 }
00276 
00277 template <class T> string  VTK_FIELD_DRIVER<T>::getFieldName() const
00278 {
00279   return _fieldName;
00280 }
00281 
00282 template <class T> GENDRIVER * VTK_FIELD_DRIVER<T>::copy(void) const
00283 {
00284   VTK_FIELD_DRIVER<T> * myDriver = new VTK_FIELD_DRIVER<T>(*this);
00285 
00286   return myDriver ;
00287 }
00288 
00289 template <class T> void VTK_FIELD_DRIVER<T>::read (void)
00290   throw (MEDEXCEPTION)
00291 {
00292   throw MEDEXCEPTION("VTK_FIELD_DRIVER::read : Can't read with a VTK driver because it is write only driver !");
00293 }
00294 
00295 //================================================================================
00299 //================================================================================
00300 
00301 template <class T> void VTK_FIELD_DRIVER<T>::write(void) const
00302   throw (MEDEXCEPTION)
00303 {
00304   const char * LOC = "VTK_FIELD_DRIVER::write(void) const " ;
00305   BEGIN_OF_MED(LOC);
00306 
00307   // we get the Support and its associated Mesh
00308 
00309   const SUPPORT * supportField = _ptrField->getSupport();
00310   const GMESH * meshField = supportField->getMesh();
00311   if (! meshField )
00312     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<": mesh was not read before writing")) ;
00313 
00314   // first, write mesh
00315   {
00316     VTK_MESH_DRIVER meshDriver( _fileName, meshField );
00317     meshDriver.write();
00318   }
00319 
00320   // write field
00321   writeAppend();
00322 }
00323 
00324 //================================================================================
00328 //================================================================================
00329 
00330 template <class T> void VTK_FIELD_DRIVER<T>::writeAppend(void) const
00331   throw (MEDEXCEPTION)
00332 {
00333   const char * LOC = "VTK_FIELD_DRIVER::writeAppend(void) const " ;
00334   BEGIN_OF_MED(LOC);
00335 
00336   // we get the Support and its associated Mesh
00337 
00338   const SUPPORT * supportField = _ptrField->getSupport();
00339   const GMESH * meshField = supportField->getMesh();
00340   MED_EN::medEntityMesh entitySupport = supportField->getEntity();
00341 
00342   if (! meshField )
00343     throw MEDEXCEPTION(LOCALIZED(STRING(LOC)<<": mesh was not read before writing")) ;
00344 
00345   if ( _ptrField->getGaussPresence() )
00346     throw MED_EXCEPTION(LOCALIZED(STRING(LOC) << "Could not write field "<<_ptrField->getName()<<" which use Gauss Points !" << entitySupport));
00347 
00348   if (!(supportField->isOnAllElements()))
00349     throw MED_EXCEPTION(LOCALIZED(STRING(LOC) << "Could not write field "<<_ptrField->getName()<<" which is not on all entities of the mesh !" << entitySupport));
00350 
00351 
00352   // Well we must open vtk file first, because there are
00353   // no other driver than MED for VTK that do it !
00354   openConstAppend() ;
00355 
00356   // first : field on node
00357   // fields is on all node !
00358 
00359   // second : field on cell
00360   // fields is on all cell !
00361 
00362   int dt = _ptrField->getIterationNumber();
00363   int it = _ptrField->getOrderNumber();
00364 
00365   ostringstream name ;
00366   string nameField = _ptrField->getName();
00367   name << nameField << "_" << dt << "_" << it ;
00368 
00369   // BEGIN issue 0020610: [CEA 371] VTK field driver : save many fields.
00370   // POINT_DATA and CELL_DATA must encounters once
00371   STRING dataStr;
00372   if (entitySupport == MED_EN::MED_NODE)
00373     dataStr << "POINT_DATA " << meshField->getNumberOfNodes() ;
00374   else if (entitySupport == MED_EN::MED_CELL)
00375     dataStr << "CELL_DATA " << meshField->getNumberOfElements(MED_EN::MED_CELL,MED_EN::MED_ALL_ELEMENTS);
00376   else
00377     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));
00378 
00379   // check if dataStr is already present in the file
00380   bool toWriteDataStr = true;
00381 #ifdef WNT
00382   int vtkFile = ::_open (_fileName.c_str(), _O_RDONLY|_O_BINARY);
00383 #else
00384   int vtkFile = ::open (_fileName.c_str(), O_RDONLY);
00385 #endif
00386   if ( vtkFile > 0 )
00387   {
00388 #ifdef WNT
00389     ssize_t fileSize = ::_lseek( vtkFile, 0, SEEK_END); ::lseek( vtkFile, 0, SEEK_SET);
00390     char* buf = new char[ fileSize ];
00391     ::_read (vtkFile, buf, fileSize );
00392 #else
00393     ssize_t fileSize = ::lseek( vtkFile, 0, SEEK_END); ::lseek( vtkFile, 0, SEEK_SET);
00394     char* buf = new char[ fileSize ];
00395     ::read (vtkFile, buf, fileSize );
00396 #endif
00397     char *vtkData = buf, *vtkDataEnd = buf+fileSize-dataStr.size();
00398     while ( ++vtkData < vtkDataEnd && toWriteDataStr )
00399       toWriteDataStr = ( strncmp( dataStr.data(), vtkData, dataStr.size()) != 0 );
00400     delete [] buf;
00401 #ifdef WNT
00402     ::_close (vtkFile);
00403 #else
00404     ::close (vtkFile);
00405 #endif
00406   }
00407   std::ostringstream vtkFileStr; // to collect labels
00408   if ( _binaryFile )
00409     vtkFileStr << endl;
00410   if ( toWriteDataStr )
00411     vtkFileStr << dataStr << endl;
00412   // END issue 0020610: [CEA 371] VTK field driver : save many fields
00413 
00414   int NomberOfValue = supportField->getNumberOfElements(MED_EN::MED_ALL_ELEMENTS) ;
00415   int NomberOfComponents =  _ptrField->getNumberOfComponents() ;
00416 
00417   MED_EN::med_type_champ fieldType = _ptrField->getValueType() ;
00418 
00419   SCRUTE_MED(name.str());
00420   SCRUTE_MED(fieldType);
00421 
00422   std::string typeStr;
00423   switch (fieldType)
00424     {
00425     case MED_EN::MED_INT32 :
00426       {
00427         typeStr = " int"; break ;
00428       }
00429     case MED_EN::MED_REEL64 :
00430       {
00431         typeStr = " float"; break ;
00432       }
00433     default :
00434       {
00435         throw MED_EXCEPTION(LOCALIZED(STRING(LOC) << "Could not write field "<< name.str() <<" the type is not int or double !"));
00436       }
00437     }
00438 
00439   if (NomberOfComponents==3)
00440     vtkFileStr << "VECTORS " << name.str() << typeStr << endl ;
00441   else if (NomberOfComponents<=4)
00442     {
00443       vtkFileStr << "SCALARS " << name.str() << typeStr << " " << NomberOfComponents << endl ;
00444       vtkFileStr << "LOOKUP_TABLE default" << endl ;
00445     }
00446   else
00447     throw MED_EXCEPTION(LOCALIZED(STRING(LOC) << "Could not write field "<<_ptrField->getName()<<" there are more than 4 components !"));
00448 
00449   const T * value ;
00450   MEDMEM_Array_ * tmpArray = 0;
00451   if ( _ptrField->getInterlacingType() == MED_EN::MED_FULL_INTERLACE )
00452     {
00453       value = _ptrField->getValue();
00454     }
00455   else if ( _ptrField->getInterlacingType() == MED_EN::MED_NO_INTERLACE_BY_TYPE )
00456     {
00457       MEDMEM_Array_ * ptrArray = _ptrField->getArray();
00458       MEDMEM_Array<T,NoInterlaceByTypeNoGaussPolicy> * temp = dynamic_cast<MEDMEM_Array<T,NoInterlaceByTypeNoGaussPolicy> * >  ( ptrArray );
00459       MEDMEM_Array<T,NoInterlaceNoGaussPolicy> * array = ArrayConvert2No( *temp );
00460       tmpArray = array;
00461       value = array->getPtr();
00462     }
00463   else
00464     {
00465       MEDMEM_Array_ * ptrArray = _ptrField->getArray();
00466       MEDMEM_Array<T,NoInterlaceNoGaussPolicy> * temp = dynamic_cast<MEDMEM_Array<T,NoInterlaceNoGaussPolicy> * >  ( ptrArray );
00467       MEDMEM_Array<T,FullInterlaceNoGaussPolicy> * array = ArrayConvert( *temp );
00468       tmpArray = array;
00469       value = array->getPtr();
00470     }
00471 
00472   if ( _vtkFile ) // ASCII
00473     {
00474       (*_vtkFile) << vtkFileStr.str();
00475       for (int i=0; i<NomberOfValue; i++)
00476         {
00477           for(int j=0; j<NomberOfComponents; j++)
00478             (*_vtkFile) << value[j*NomberOfValue+i] << " " ;
00479           (*_vtkFile) << endl ;
00480         }
00481     }
00482   else // BINARY
00483     {
00484       std::string str = vtkFileStr.str();
00485       _binaryFile->write( str.data(), str.size() );
00486       // Though type "double" is available in VTK but actually it does not work
00487       // (at least paraview shows wrong values)
00488       if ( fieldType == MED_EN::MED_REEL64 )
00489         {
00490           vector<float> floatValue(NomberOfValue * NomberOfComponents );
00491           for ( unsigned i = 0; i < floatValue.size(); ++i )
00492             floatValue[i]=float( value[i] );
00493           _binaryFile->write( &floatValue[0], NomberOfValue * NomberOfComponents );
00494         }
00495       else
00496         {
00497           _binaryFile->write( value, NomberOfValue * NomberOfComponents );
00498         }
00499     }
00500 
00501   if ( _ptrField->getInterlacingType() != MED_EN::MED_FULL_INTERLACE )
00502     delete tmpArray;
00503 
00504   closeConst();
00505 
00506   END_OF_MED(LOC);
00507 }
00508 }//End namespace MEDMEM
00509 
00510 #endif /* VTK_FIELD_DRIVER_HXX */