Back to index

salome-med  6.5.0
SauvMedConvertor.hxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 // File      : SauvMedConvertor.hxx
00020 // Created   : Tue Aug 16 14:14:02 2011
00021 // Author    : Edward AGAPOV (eap)
00022 //
00023 
00024 #ifndef __SauvMedConvertor_HXX__
00025 #define __SauvMedConvertor_HXX__
00026 
00027 #include "InterpKernelException.hxx"
00028 #include "NormalizedUnstructuredMesh.hxx"
00029 #include "MEDCouplingRefCountObject.hxx"
00030 #include "SauvUtilities.hxx"
00031 
00032 #include <vector>
00033 #include <set>
00034 #include <map>
00035 #include <list>
00036 #include <algorithm>
00037 
00038 namespace ParaMEDMEM
00039 {
00040   class DataArrayDouble;
00041   class DataArrayInt;
00042   class MEDFileData;
00043   class MEDFileFields;
00044   class MEDFileFieldMultiTS;
00045   class MEDFileUMesh;
00046 }
00047 
00048 namespace SauvUtilities
00049 {
00050   class IntermediateMED;
00051 
00052   // ==============================================================================
00053   typedef int                TID;  // an ID countered from 1
00054   typedef std::pair<TID,TID> Link; // a pair of node numbers
00055 
00056   typedef INTERP_KERNEL::NormalizedCellType TCellType;
00057 
00058   // ==============================================================================
00059   struct Node
00060   {
00061     TID    _number;
00062     size_t _coordID;
00063 
00064     Node():_number(0){}
00065     bool isUsed() const { return _number != 0; }
00066   };
00067 
00068   // ==============================================================================
00069   struct Cell
00070   {
00071     std::vector< Node* > _nodes;
00072     mutable bool         _reverse; // to reverse orienation of a face only
00073     mutable TID*         _sortedNodeIDs; // for comparison
00074     mutable TID          _number;
00075 
00076     Cell(size_t nnNodes=0) : _nodes(nnNodes),_reverse(false),_sortedNodeIDs(0),_number(0) {}
00077     Cell(const Cell& ma);
00078     void init() const { if ( _sortedNodeIDs ) delete [] _sortedNodeIDs; _sortedNodeIDs = 0; }
00079     ~Cell() { init(); }
00080 
00081     const TID* getSortedNodes() const; // creates if needed and return _sortedNodeIDs
00082     bool operator < (const Cell& ma) const;
00083     Link link(int i) const;
00084 
00085   private:
00086     Cell& operator=(const Cell& ma);
00087   };
00088   std::ostream& operator << (std::ostream& os, const Cell& ma);
00089 
00090   // ==============================================================================
00091   struct Group
00092   {
00093     TCellType                _cellType;
00094     std::string              _name;
00095     std::vector<const Cell*> _cells;
00096     std::vector< Group* >    _groups;    // des sous-groupes composant le Group
00097     //bool                     _isShared;  // true if any Cell was added to the mesh from other Group
00098     bool                     _isProfile; // is a field support or not
00099     std::vector<std::string> _refNames;  /* names of groups referring this one;
00100                                             _refNames is resized according to nb of references
00101                                             while reading a group (pile 1) and it is filled with
00102                                             names while reading long names (pile 27); each named
00103                                             reference is converted into a copy of the medGroup
00104                                             (issue 0021311)
00105                                          */
00106     ParaMEDMEM::DataArrayInt* _medGroup;   // result of conversion
00107     std::vector< unsigned >   _relocTable; // for _cells[i] gives its index in _medGroup
00108 
00109     bool empty() const { return _cells.empty() && _groups.empty(); }
00110     int  size()  const;
00111     Group():_cellType(INTERP_KERNEL::NORM_ERROR), _isProfile(false), _medGroup(NULL) {}
00112   };
00113 
00114   // ==============================================================================
00115   struct DoubleField
00116   {
00117     // a field contains several subcomponents each referring to its own support and
00118     // having several named components
00119     // ----------------------------------------------------------------------------
00120     struct _Sub_data // a subcomponent
00121     // --------------------------------
00122     {
00123       Group*                   _support;    // support
00124       std::vector<std::string> _comp_names; // component names
00125       std::vector<int>         _nb_gauss;   // nb values per element in a component
00126 
00127       void setData( int nb_comp, Group* supp )
00128       { _support = supp; _comp_names.resize(nb_comp); _nb_gauss.resize(nb_comp,1); }
00129       int nbComponents() const { return _comp_names.size(); }
00130       std::string & compName( int i_comp ) { return _comp_names[ i_comp ]; }
00131       bool isValidNbGauss() const { return *std::max_element( _nb_gauss.begin(), _nb_gauss.end() ) ==
00132           *std::min_element( _nb_gauss.begin(), _nb_gauss.end() ); }
00133       int nbGauss() const { return _nb_gauss[0] ? _nb_gauss[0] : 1; }
00134       bool hasGauss() const { return nbGauss() > 1; }
00135     };
00136     // ----------------------------------------------------------------------------
00137     TID                      _idInFile;
00138     std::string              _name;
00139     std::string              _description; // field description
00140     std::vector< _Sub_data > _sub;
00141     Group*                   _group; /* if _group == NULL then each subcomponent makes a
00142                                         separate med field, else all subcomponents
00143                                         are converted into timestamps of one med field.
00144                                         The latter is possible only if nb of components in all subs
00145                                         is the same and supports of subcomponents do not overlap
00146                                      */
00147     std::vector< std::vector< double > > _comp_values;
00148     ParaMEDMEM::MEDFileFieldMultiTS*     _curMedField;
00149 
00150     DoubleField( int nb_sub, int total_nb_comp )
00151       : _sub(nb_sub), _group(NULL), _curMedField(NULL) { _comp_values.reserve( total_nb_comp ); }
00152     std::vector< double >& addComponent( int nb_values ); // return a vector ready to fill in
00153     bool hasCommonSupport() const { return _group; } // true if there is one support for all subs
00154     bool hasSameComponentsBySupport() const;
00155 
00156     bool isMultiTimeStamps() const;
00157     bool isMedCompatible() const;
00158     ParaMEDMEM::TypeOfField getMedType( const int iSub=0 ) const;
00159     ParaMEDMEM::TypeOfTimeDiscretization getMedTimeDisc() const;
00160     int getNbTuples( const int iSub=0 ) const;
00161     int getNbValuesPerElement( const int iSub=0 ) const;
00162     int getNbGauss( const int iSub=0 ) const;
00163     const Group* getSupport( const int iSub=0 ) const;
00164     int setValues( double * valPtr, const int iSub, const int elemShift=0 ) const;
00165 
00166     //virtual void dump(std::ostream&) const;
00167     //virtual ~DoubleField() {}
00168   };
00169   // ==============================================================================
00175   class CellsByDimIterator
00176   {
00177   public:
00178     CellsByDimIterator( const IntermediateMED & medi, int dim=-1); // dim=-1 - for all dimensions
00179     void init(const int  dim=-1);
00180 
00182     const std::set<Cell > * nextType();
00184     int dim(const bool last=true) const;
00186     TCellType type() const { return TCellType( myCurType ); }
00187 
00188   private:
00189     const IntermediateMED* myImed;
00190     int myCurType, myTypeEnd;
00191     int myDim;
00192   };
00193 
00194   // ==============================================================================
00200   class NodeContainer
00201   {
00202     std::vector< std::vector< Node > > _nodes;
00203   public:
00204     Node* getNode( const TID nID )
00205     {
00206       const size_t chunkSize = 1000;
00207       const size_t chunkID = (nID-1) / chunkSize;
00208       const size_t pos     = (nID-1) % chunkSize;
00209       if ( _nodes.size() < chunkID+1 )
00210       {
00211         std::vector< std::vector< Node > > newNodes(chunkID+1);
00212         for ( size_t i = 0; i < _nodes.size(); ++i )
00213           newNodes[i].swap( _nodes[i] );
00214         for ( size_t i = _nodes.size(); i < newNodes.size(); ++i )
00215           newNodes[i].resize( chunkSize );
00216         _nodes.swap( newNodes );
00217       }
00218       return & _nodes[chunkID][pos];
00219     }
00220     bool empty() const { return _nodes.empty(); }
00221     size_t size() const { return empty() ? 0 : _nodes.size() * _nodes[0].size(); }
00222     int numberNodes();
00223   };
00224 
00225   // ==============================================================================
00234   struct IntermediateMED
00235   {
00236     unsigned                   _spaceDim;
00237     unsigned                   _nbNodes;
00238     NodeContainer              _points;
00239     std::vector<double>        _coords;
00240     std::vector<Group>         _groups;
00241     std::vector<DoubleField* > _nodeFields;
00242     std::vector<DoubleField* > _cellFields;
00243 
00244     // IMP 0020434: mapping GIBI names to MED names
00245     std::list<nameGIBItoMED>  _listGIBItoMED_mail; // to read from table "MED_MAIL" of PILE_TABLES
00246     std::list<nameGIBItoMED>  _listGIBItoMED_cham; // to read from table "MED_CHAM" of PILE_TABLES
00247     std::list<nameGIBItoMED>  _listGIBItoMED_comp; // to read from table "MED_COMP" of PILE_TABLES
00248     std::map<int,std::string> _mapStrings;         // to read from PILE_STRINGS
00249 
00250     IntermediateMED(): _spaceDim(0), _nbNodes(0) {}
00251     ~IntermediateMED();
00252 
00253     Node* getNode( TID nID ) { return _points.getNode( nID ); }
00254     int getNbCellsOfType( TCellType type ) const { return _cellsByType[type].size(); }
00255     const Cell* insert(TCellType type, const Cell& ma) { return &( *_cellsByType[type].insert( ma ).first ); }
00256     ParaMEDMEM::MEDFileData* convertInMEDFileDS();
00257 
00258   private:
00259 
00260     ParaMEDMEM::MEDFileUMesh* makeMEDFileMesh();
00261     ParaMEDMEM::DataArrayDouble * getCoords();
00262     void setConnectivity( ParaMEDMEM::MEDFileUMesh* mesh, ParaMEDMEM::DataArrayDouble* coords );
00263     void setGroups( ParaMEDMEM::MEDFileUMesh* mesh );
00264     ParaMEDMEM::MEDFileFields * makeMEDFileFields(ParaMEDMEM::MEDFileUMesh* mesh);
00265     void setFields( SauvUtilities::DoubleField*    fld,
00266                     ParaMEDMEM::MEDFileFields*     medFields,
00267                     ParaMEDMEM::MEDFileUMesh*      mesh,
00268                     const TID                      castemID,
00269                     std::set< std::string >&       usedNames);
00270     void setTS( SauvUtilities::DoubleField*  fld,
00271                 ParaMEDMEM::DataArrayDouble* values,
00272                 ParaMEDMEM::MEDFileFields*   medFields,
00273                 ParaMEDMEM::MEDFileUMesh*    mesh,
00274                 const int                    iSub=0);
00275     void checkDataAvailability() const throw(INTERP_KERNEL::Exception);
00276     void setGroupLongNames();
00277     void setFieldLongNames(std::set< std::string >& usedNames);
00278     void makeFieldNewName(std::set< std::string >&    usedNames,
00279                           SauvUtilities::DoubleField* fld );
00280     void decreaseHierarchicalDepthOfSubgroups();
00281     void eraseUselessGroups();
00282     void detectMixDimGroups();
00283     void orientElements2D();
00284     void orientElements3D();
00285     void orientFaces3D();
00286     void orientVolumes();
00287     void numberElements();
00288     bool isOnAll( const Group* grp, int & dimRel ) const;
00289     const double* nodeCoords( const Node* n ) { return &_coords[ (n->_coordID-1) * _spaceDim ]; }
00290 
00291     // IntermediateMED()
00292     // { myNodesNumerated = myMaillesNumerated = myGroupsTreated = false; currentTypeMailles = 0; }
00293     // ~IntermediateMED();
00294 
00295     //bool myNodesNumerated, myMaillesNumerated;
00296 
00297     // mailles groupped by geom type; use insert() for filling in and
00298     // _CellsByDimIterator for exploring it
00299     //std::set<_Cell> maillage;
00300     std::set< Cell >  _cellsByType[ INTERP_KERNEL::NORM_HEXA20 + 1 ];
00301     friend class CellsByDimIterator;
00302   };
00303 
00304 // ==============================================================================
00308   class ASCIIReader : public FileReader
00309   {
00310   public:
00311     ASCIIReader(const char* fileName);
00312     virtual ~ASCIIReader();
00313     virtual bool isASCII() const;
00314     virtual bool open();
00315     virtual bool getNextLine (char* & line, bool raiseOEF = true );
00316     virtual void initNameReading(int nbValues, int width = 8);
00317     virtual void initIntReading(int nbValues);
00318     virtual void initDoubleReading(int nbValues);
00319     virtual bool more() const;
00320     virtual void next();
00321     virtual int    getInt() const;
00322     virtual float  getFloat() const;
00323     virtual double getDouble() const;
00324     virtual std::string getName() const;
00325     int lineNb() const { return _lineNb; }
00326 
00327   private:
00328 
00329     bool getLine(char* & line);
00330     void init( int nbToRead, int nbPosInLine, int width, int shift = 0 );
00331 
00332     // getting a line from the file
00333     int   _file;
00334     char* _start; // working buffer beginning
00335     char* _ptr;
00336     char* _eptr;
00337     int   _lineNb;
00338 
00339     // line parsing
00340     int _iPos, _nbPosInLine, _width, _shift;
00341     char* _curPos;
00342   };
00343 // ==============================================================================
00347   class XDRReader : public FileReader
00348   {
00349   public:
00350     XDRReader(const char* fileName);
00351     virtual ~XDRReader();
00352     virtual bool isASCII() const;
00353     virtual bool open();
00354     virtual bool getNextLine (char* & line, bool raiseOEF = true );
00355     virtual void initNameReading(int nbValues, int width = 8);
00356     virtual void initIntReading(int nbValues);
00357     virtual void initDoubleReading(int nbValues);
00358     virtual bool more() const;
00359     virtual void next();
00360     virtual int    getInt() const;
00361     virtual float  getFloat() const;
00362     virtual double getDouble() const;
00363     virtual std::string getName() const;
00364 
00365   private:
00366 
00367     void init( int nbToRead, int width = 0 );
00368 
00369     FILE* _xdrs_file;
00370     void* _xdrs;
00371     int* _xdr_ivals;
00372     double* _xdr_dvals;
00373     char* _xdr_cvals;
00374     int _width;
00375     int _xdr_kind;
00376     enum
00377       {
00378         _xdr_kind_null,
00379         _xdr_kind_char,
00380         _xdr_kind_int,
00381         _xdr_kind_double
00382       };
00383   };
00384 }
00385 
00386 #endif