Salome HOME
Merge from V6_main 01/04/2013
[modules/med.git] / src / MEDLoader / SauvMedConvertor.hxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // File      : SauvMedConvertor.hxx
20 // Created   : Tue Aug 16 14:14:02 2011
21 // Author    : Edward AGAPOV (eap)
22 //
23
24 #ifndef __SauvMedConvertor_HXX__
25 #define __SauvMedConvertor_HXX__
26
27 #include "InterpKernelException.hxx"
28 #include "NormalizedUnstructuredMesh.hxx"
29 #include "MEDCouplingRefCountObject.hxx"
30 #include "SauvUtilities.hxx"
31
32 #include <vector>
33 #include <set>
34 #include <map>
35 #include <list>
36 #include <algorithm>
37
38 namespace ParaMEDMEM
39 {
40   class DataArrayDouble;
41   class DataArrayInt;
42   class MEDFileData;
43   class MEDFileFields;
44   class MEDFileFieldMultiTS;
45   class MEDFileUMesh;
46 }
47
48 namespace SauvUtilities
49 {
50   class IntermediateMED;
51
52   // ==============================================================================
53   typedef int                TID;  // an ID countered from 1
54   typedef std::pair<TID,TID> Link; // a pair of node numbers
55
56   typedef INTERP_KERNEL::NormalizedCellType TCellType;
57
58   // ==============================================================================
59   struct Node
60   {
61     TID    _number;
62     size_t _coordID;
63
64     Node():_number(0){}
65     bool isUsed() const { return _number != 0; }
66   };
67
68   // ==============================================================================
69   struct Cell
70   {
71     std::vector< Node* > _nodes;
72     mutable bool         _reverse; // to reverse orienation of a face only
73     mutable TID*         _sortedNodeIDs; // for comparison
74     mutable TID          _number;
75
76     Cell(size_t nnNodes=0) : _nodes(nnNodes),_reverse(false),_sortedNodeIDs(0),_number(0) {}
77     Cell(const Cell& ma);
78     void init() const { if ( _sortedNodeIDs ) delete [] _sortedNodeIDs; _sortedNodeIDs = 0; }
79     ~Cell() { init(); }
80
81     const TID* getSortedNodes() const; // creates if needed and return _sortedNodeIDs
82     bool operator < (const Cell& ma) const;
83     Link link(int i) const;
84
85   private:
86     Cell& operator=(const Cell& ma);
87   };
88   std::ostream& operator << (std::ostream& os, const Cell& ma);
89
90   // ==============================================================================
91   struct Group
92   {
93     TCellType                _cellType;
94     std::string              _name;
95     std::vector<const Cell*> _cells;
96     std::vector< Group* >    _groups;    // des sous-groupes composant le Group
97     //bool                     _isShared;  // true if any Cell was added to the mesh from other Group
98     bool                     _isProfile; // is a field support or not
99     std::vector<std::string> _refNames;  /* names of groups referring this one;
100                                             _refNames is resized according to nb of references
101                                             while reading a group (pile 1) and it is filled with
102                                             names while reading long names (pile 27); each named
103                                             reference is converted into a copy of the medGroup
104                                             (issue 0021311)
105                                          */
106     ParaMEDMEM::DataArrayInt* _medGroup;   // result of conversion
107     std::vector< unsigned >   _relocTable; // for _cells[i] gives its index in _medGroup
108
109     bool empty() const { return _cells.empty() && _groups.empty(); }
110     int  size()  const;
111     Group():_cellType(INTERP_KERNEL::NORM_ERROR), _isProfile(false), _medGroup(NULL) {}
112   };
113
114   // ==============================================================================
115   struct DoubleField
116   {
117     // a field contains several subcomponents each referring to its own support and
118     // having several named components
119     // ----------------------------------------------------------------------------
120     struct _Sub_data // a subcomponent
121     // --------------------------------
122     {
123       Group*                   _support;    // support
124       std::vector<std::string> _comp_names; // component names
125       std::vector<int>         _nb_gauss;   // nb values per element in a component
126
127       void setData( int nb_comp, Group* supp )
128       { _support = supp; _comp_names.resize(nb_comp); _nb_gauss.resize(nb_comp,1); }
129       int nbComponents() const { return _comp_names.size(); }
130       std::string & compName( int i_comp ) { return _comp_names[ i_comp ]; }
131       bool isValidNbGauss() const { return *std::max_element( _nb_gauss.begin(), _nb_gauss.end() ) ==
132           *std::min_element( _nb_gauss.begin(), _nb_gauss.end() ); }
133       int nbGauss() const { return _nb_gauss[0] ? _nb_gauss[0] : 1; }
134       bool hasGauss() const { return nbGauss() > 1; }
135     };
136     // ----------------------------------------------------------------------------
137     TID                      _idInFile;
138     std::string              _name;
139     std::string              _description; // field description
140     std::vector< _Sub_data > _sub;
141     Group*                   _group; /* if _group == NULL then each subcomponent makes a
142                                         separate med field, else all subcomponents
143                                         are converted into timestamps of one med field.
144                                         The latter is possible only if nb of components in all subs
145                                         is the same and supports of subcomponents do not overlap
146                                      */
147     std::vector< std::vector< double > > _comp_values;
148     ParaMEDMEM::MEDFileFieldMultiTS*     _curMedField;
149
150     DoubleField( int nb_sub, int total_nb_comp )
151       : _sub(nb_sub), _group(NULL), _curMedField(NULL) { _comp_values.reserve( total_nb_comp ); }
152     ~DoubleField();
153     std::vector< double >& addComponent( int nb_values ); // return a vector ready to fill in
154     bool hasCommonSupport() const { return _group; } // true if there is one support for all subs
155     bool hasSameComponentsBySupport() const;
156
157     bool isMultiTimeStamps() const;
158     bool isMedCompatible() const;
159     ParaMEDMEM::TypeOfField getMedType( const int iSub=0 ) const;
160     ParaMEDMEM::TypeOfTimeDiscretization getMedTimeDisc() const;
161     int getNbTuples( const int iSub=0 ) const;
162     int getNbValuesPerElement( const int iSub=0 ) const;
163     int getNbGauss( const int iSub=0 ) const;
164     const Group* getSupport( const int iSub=0 ) const;
165     int setValues( double * valPtr, const int iSub, const int elemShift=0 ) const;
166
167     //virtual void dump(std::ostream&) const;
168     //virtual ~DoubleField() {}
169   };
170   // ==============================================================================
171   /*!
172    * \if developper
173    * Iterator on set of Cell's of given dimension
174    * \endif
175    */
176   class CellsByDimIterator
177   {
178   public:
179     CellsByDimIterator( const IntermediateMED & medi, int dim=-1); // dim=-1 - for all dimensions
180     void init(const int  dim=-1);
181
182     //!< return next set of Cell's of required dimension
183     const std::set<Cell > * nextType();
184     //!< return dimension of Cell's returned by the last or further next()
185     int dim(const bool last=true) const;
186     //!< return type of Cell's returned by the last next()
187     TCellType type() const { return TCellType( myCurType ); }
188
189   private:
190     const IntermediateMED* myImed;
191     int myCurType, myTypeEnd;
192     int myDim;
193   };
194
195   // ==============================================================================
196   /*!
197    * \if developper
198    * Container of Node's. Prevents re-allocation at addition of Node's
199    * \endif
200    */
201   class NodeContainer
202   {
203     std::vector< std::vector< Node > > _nodes;
204   public:
205     Node* getNode( const TID nID )
206     {
207       const size_t chunkSize = 1000;
208       const size_t chunkID = (nID-1) / chunkSize;
209       const size_t pos     = (nID-1) % chunkSize;
210       if ( _nodes.size() < chunkID+1 )
211       {
212         std::vector< std::vector< Node > > newNodes(chunkID+1);
213         for ( size_t i = 0; i < _nodes.size(); ++i )
214           newNodes[i].swap( _nodes[i] );
215         for ( size_t i = _nodes.size(); i < newNodes.size(); ++i )
216           newNodes[i].resize( chunkSize );
217         _nodes.swap( newNodes );
218       }
219       return & _nodes[chunkID][pos];
220     }
221     bool empty() const { return _nodes.empty(); }
222     size_t size() const { return empty() ? 0 : _nodes.size() * _nodes[0].size(); }
223     int numberNodes();
224   };
225
226   // ==============================================================================
227   /*!
228    * \if developper
229    * Intermediate structure used to store data read from the Sauve format file.
230    * The structure provides functions that transform the stored data to the MED format
231    *
232    * The elements inserted in maillage are ordered in order to avoid duplicated elements.
233    * \endif
234    */
235   struct IntermediateMED
236   {
237     unsigned                   _spaceDim;
238     unsigned                   _nbNodes;
239     NodeContainer              _points;
240     std::vector<double>        _coords;
241     std::vector<Group>         _groups;
242     std::vector<DoubleField* > _nodeFields;
243     std::vector<DoubleField* > _cellFields;
244
245     // IMP 0020434: mapping GIBI names to MED names
246     std::list<nameGIBItoMED>  _listGIBItoMED_mail; // to read from table "MED_MAIL" of PILE_TABLES
247     std::list<nameGIBItoMED>  _listGIBItoMED_cham; // to read from table "MED_CHAM" of PILE_TABLES
248     std::list<nameGIBItoMED>  _listGIBItoMED_comp; // to read from table "MED_COMP" of PILE_TABLES
249     std::map<int,std::string> _mapStrings;         // to read from PILE_STRINGS
250
251     IntermediateMED(): _spaceDim(0), _nbNodes(0) {}
252     ~IntermediateMED();
253
254     Node* getNode( TID nID ) { return _points.getNode( nID ); }
255     int getNbCellsOfType( TCellType type ) const { return _cellsByType[type].size(); }
256     const Cell* insert(TCellType type, const Cell& ma) { return &( *_cellsByType[type].insert( ma ).first ); }
257     ParaMEDMEM::MEDFileData* convertInMEDFileDS();
258
259   private:
260
261     ParaMEDMEM::MEDFileUMesh* makeMEDFileMesh();
262     ParaMEDMEM::DataArrayDouble * getCoords();
263     void setConnectivity( ParaMEDMEM::MEDFileUMesh* mesh, ParaMEDMEM::DataArrayDouble* coords );
264     void setGroups( ParaMEDMEM::MEDFileUMesh* mesh );
265     ParaMEDMEM::MEDFileFields * makeMEDFileFields(ParaMEDMEM::MEDFileUMesh* mesh);
266     void setFields( SauvUtilities::DoubleField*    fld,
267                     ParaMEDMEM::MEDFileFields*     medFields,
268                     ParaMEDMEM::MEDFileUMesh*      mesh,
269                     const TID                      castemID,
270                     std::set< std::string >&       usedNames);
271     void setTS( SauvUtilities::DoubleField*  fld,
272                 ParaMEDMEM::DataArrayDouble* values,
273                 ParaMEDMEM::MEDFileFields*   medFields,
274                 ParaMEDMEM::MEDFileUMesh*    mesh,
275                 const int                    iSub=0);
276     void checkDataAvailability() const throw(INTERP_KERNEL::Exception);
277     void setGroupLongNames();
278     void setFieldLongNames(std::set< std::string >& usedNames);
279     void makeFieldNewName(std::set< std::string >&    usedNames,
280                           SauvUtilities::DoubleField* fld );
281     void decreaseHierarchicalDepthOfSubgroups();
282     void eraseUselessGroups();
283     void detectMixDimGroups();
284     void orientElements2D();
285     void orientElements3D();
286     void orientFaces3D();
287     void orientVolumes();
288     void numberElements();
289     bool isOnAll( const Group* grp, int & dimRel ) const;
290     const double* nodeCoords( const Node* n ) { return &_coords[ (n->_coordID-1) * _spaceDim ]; }
291
292     // IntermediateMED()
293     // { myNodesNumerated = myMaillesNumerated = myGroupsTreated = false; currentTypeMailles = 0; }
294     // ~IntermediateMED();
295
296     //bool myNodesNumerated, myMaillesNumerated;
297
298     // mailles groupped by geom type; use insert() for filling in and
299     // _CellsByDimIterator for exploring it
300     //std::set<_Cell> maillage;
301     std::set< Cell >  _cellsByType[ INTERP_KERNEL::NORM_HEXA20 + 1 ];
302     friend class CellsByDimIterator;
303   };
304
305 // ==============================================================================
306   /*!
307    * \brief ASCII sauve file reader
308    */
309   class ASCIIReader : public FileReader
310   {
311   public:
312     ASCIIReader(const char* fileName);
313     virtual ~ASCIIReader();
314     virtual bool isASCII() const;
315     virtual bool open();
316     virtual bool getNextLine (char* & line, bool raiseOEF = true );
317     virtual void initNameReading(int nbValues, int width = 8);
318     virtual void initIntReading(int nbValues);
319     virtual void initDoubleReading(int nbValues);
320     virtual bool more() const;
321     virtual void next();
322     virtual int    getInt() const;
323     virtual float  getFloat() const;
324     virtual double getDouble() const;
325     virtual std::string getName() const;
326     int lineNb() const { return _lineNb; }
327
328   private:
329
330     bool getLine(char* & line);
331     void init( int nbToRead, int nbPosInLine, int width, int shift = 0 );
332
333     // getting a line from the file
334     int   _file;
335     char* _start; // working buffer beginning
336     char* _ptr;
337     char* _eptr;
338     int   _lineNb;
339
340     // line parsing
341     int _iPos, _nbPosInLine, _width, _shift;
342     char* _curPos;
343   };
344 // ==============================================================================
345   /*!
346    * \brief XDR (binary) sauve file reader
347    */
348   class XDRReader : public FileReader
349   {
350   public:
351     XDRReader(const char* fileName);
352     virtual ~XDRReader();
353     virtual bool isASCII() const;
354     virtual bool open();
355     virtual bool getNextLine (char* & line, bool raiseOEF = true );
356     virtual void initNameReading(int nbValues, int width = 8);
357     virtual void initIntReading(int nbValues);
358     virtual void initDoubleReading(int nbValues);
359     virtual bool more() const;
360     virtual void next();
361     virtual int    getInt() const;
362     virtual float  getFloat() const;
363     virtual double getDouble() const;
364     virtual std::string getName() const;
365
366   private:
367
368     void init( int nbToRead, int width = 0 );
369
370     FILE* _xdrs_file;
371     void* _xdrs;
372     int* _xdr_ivals;
373     double* _xdr_dvals;
374     char* _xdr_cvals;
375     int _width;
376     int _xdr_kind;
377     enum
378       {
379         _xdr_kind_null,
380         _xdr_kind_char,
381         _xdr_kind_int,
382         _xdr_kind_double
383       };
384   };
385 }
386
387 #endif