Salome HOME
ebaf41919957960f3aea58a4ada921414a53fd1a
[modules/med.git] / src / MEDLoader / SauvMedConvertor.hxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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   struct 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                     _isProfile; // is a field support or not
98     std::vector<std::string> _refNames;  /* names of groups referring this one;
99                                             _refNames is resized according to nb of references
100                                             while reading a group (pile 1) and it is filled with
101                                             names while reading long names (pile 27); each named
102                                             reference is converted into a copy of the medGroup
103                                             (issue 0021311)
104                                          */
105     ParaMEDMEM::DataArrayInt* _medGroup;   // result of conversion
106     std::vector< unsigned >   _relocTable; // for _cells[i] gives its index in _medGroup
107
108     bool empty() const { return _cells.empty() && _groups.empty(); }
109     int  size()  const;
110     Group():_cellType(INTERP_KERNEL::NORM_ERROR), _isProfile(false), _medGroup(NULL) {}
111   };
112
113   // ==============================================================================
114   struct DoubleField
115   {
116     // a field contains several subcomponents each referring to its own support and
117     // having several named components
118     // ----------------------------------------------------------------------------
119     struct _Sub_data // a subcomponent
120     // --------------------------------
121     {
122       Group*                   _support;    // support
123       std::vector<std::string> _comp_names; // component names
124       std::vector<int>         _nb_gauss;   // nb values per element in a component
125
126       void setData( int nb_comp, Group* supp )
127       { _support = supp; _comp_names.resize(nb_comp); _nb_gauss.resize(nb_comp,1); }
128       int  nbComponents() const { return _comp_names.size(); }
129       std::string & compName( int i_comp ) { return _comp_names[ i_comp ]; }
130       bool isSameNbGauss() const { return *std::max_element( _nb_gauss.begin(), _nb_gauss.end() ) ==
131           *std::min_element( _nb_gauss.begin(), _nb_gauss.end() ); }
132       int  nbGauss() const { return _nb_gauss[0] ? _nb_gauss[0] : 1; }
133       bool hasGauss() const { return nbGauss() > 1; }
134     };
135     // ----------------------------------------------------------------------------
136     TID                      _idInFile;
137     std::string              _name;
138     std::string              _description; // field description
139     std::vector< _Sub_data > _sub;
140     Group*                   _group; /* if _group == NULL then each subcomponent makes a
141                                         separate med field, else all subcomponents
142                                         are converted into timestamps of one med field.
143                                         The latter is possible only if nb of components in all subs
144                                         is the same and supports of subcomponents do not overlap
145                                      */
146     std::vector< std::vector< double > > _comp_values;
147     ParaMEDMEM::MEDFileFieldMultiTS*     _curMedField;
148
149     DoubleField( int nb_sub, int total_nb_comp )
150       : _sub(nb_sub), _group(NULL), _curMedField(NULL) { _comp_values.reserve( total_nb_comp ); }
151     ~DoubleField();
152     std::vector< double >& addComponent( int nb_values ); // return a vector ready to fill in
153     bool hasCommonSupport() const { return _group; } // true if there is one support for all subs
154     bool hasSameComponentsBySupport() const;
155
156     bool isMultiTimeStamps() const;
157     bool isMedCompatible(bool& sameNbGauss) const;
158     ParaMEDMEM::TypeOfField getMedType( const int iSub=0 ) const;
159     ParaMEDMEM::TypeOfTimeDiscretization getMedTimeDisc() const;
160     int getNbTuples( const int iSub=0 ) const;
161     int getNbValuesPerElement( const int iSub=0 ) const;
162     int getNbGauss( const int iSub=0 ) const;
163     const Group* getSupport( const int iSub=0 ) const;
164     int setValues( double * valPtr, const int iSub, const int elemShift=0 ) const;
165     void splitSubWithDiffNbGauss();
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     Group* addNewGroup(std::vector<SauvUtilities::Group*>* groupsToFix=0);
258     ParaMEDMEM::MEDFileData* convertInMEDFileDS();
259
260   private:
261
262     ParaMEDMEM::MEDFileUMesh* makeMEDFileMesh();
263     ParaMEDMEM::DataArrayDouble * getCoords();
264     void setConnectivity( ParaMEDMEM::MEDFileUMesh* mesh, ParaMEDMEM::DataArrayDouble* coords );
265     void setGroups( ParaMEDMEM::MEDFileUMesh* mesh );
266     ParaMEDMEM::MEDFileFields * makeMEDFileFields(ParaMEDMEM::MEDFileUMesh* mesh);
267     void setFields( SauvUtilities::DoubleField*    fld,
268                     ParaMEDMEM::MEDFileFields*     medFields,
269                     ParaMEDMEM::MEDFileUMesh*      mesh,
270                     const TID                      castemID,
271                     std::set< std::string >&       usedNames);
272     void setTS( SauvUtilities::DoubleField*  fld,
273                 ParaMEDMEM::DataArrayDouble* values,
274                 ParaMEDMEM::MEDFileFields*   medFields,
275                 ParaMEDMEM::MEDFileUMesh*    mesh,
276                 const int                    iSub=0);
277     void checkDataAvailability() const;
278     void setGroupLongNames();
279     void setFieldLongNames(std::set< std::string >& usedNames);
280     void makeFieldNewName(std::set< std::string >&    usedNames,
281                           SauvUtilities::DoubleField* fld );
282     void decreaseHierarchicalDepthOfSubgroups();
283     void eraseUselessGroups();
284     void detectMixDimGroups();
285     void orientElements2D();
286     void orientElements3D();
287     void orientFaces3D();
288     void orientVolumes();
289     void numberElements();
290     bool isOnAll( const Group* grp, int & dimRel ) const;
291     const double* nodeCoords( const Node* n ) { return &_coords[ (n->_coordID-1) * _spaceDim ]; }
292
293     // IntermediateMED()
294     // { myNodesNumerated = myMaillesNumerated = myGroupsTreated = false; currentTypeMailles = 0; }
295     // ~IntermediateMED();
296
297     //bool myNodesNumerated, myMaillesNumerated;
298
299     // mailles groupped by geom type; use insert() for filling in and
300     // _CellsByDimIterator for exploring it
301     //std::set<_Cell> maillage;
302     std::set< Cell >  _cellsByType[ INTERP_KERNEL::NORM_HEXA20 + 1 ];
303     friend class CellsByDimIterator;
304   };
305
306 // ==============================================================================
307   /*!
308    * \brief ASCII sauve file reader
309    */
310   class ASCIIReader : public FileReader
311   {
312   public:
313     ASCIIReader(const char* fileName);
314     virtual ~ASCIIReader();
315     virtual bool isASCII() const;
316     virtual bool open();
317     virtual bool getNextLine (char* & line, bool raiseOEF = true );
318     virtual void initNameReading(int nbValues, int width = 8);
319     virtual void initIntReading(int nbValues);
320     virtual void initDoubleReading(int nbValues);
321     virtual bool more() const;
322     virtual void next();
323     virtual int    getInt() const;
324     virtual float  getFloat() const;
325     virtual double getDouble() const;
326     virtual std::string getName() const;
327     int lineNb() const { return _lineNb; }
328
329   private:
330
331     bool getLine(char* & line);
332     void init( int nbToRead, int nbPosInLine, int width, int shift = 0 );
333
334     // getting a line from the file
335     int   _file;
336     char* _start; // working buffer beginning
337     char* _ptr;
338     char* _eptr;
339     int   _lineNb;
340
341     // line parsing
342     int _iPos, _nbPosInLine, _width, _shift;
343     char* _curPos;
344   };
345 // ==============================================================================
346   /*!
347    * \brief XDR (binary) sauve file reader
348    */
349   class XDRReader : public FileReader
350   {
351   public:
352     XDRReader(const char* fileName);
353     virtual ~XDRReader();
354     virtual bool isASCII() const;
355     virtual bool open();
356     virtual bool getNextLine (char* & line, bool raiseOEF = true );
357     virtual void initNameReading(int nbValues, int width = 8);
358     virtual void initIntReading(int nbValues);
359     virtual void initDoubleReading(int nbValues);
360     virtual bool more() const;
361     virtual void next();
362     virtual int    getInt() const;
363     virtual float  getFloat() const;
364     virtual double getDouble() const;
365     virtual std::string getName() const;
366
367   private:
368
369     void init( int nbToRead, int width = 0 );
370
371     FILE* _xdrs_file;
372     void* _xdrs;
373     int* _xdr_ivals;
374     double* _xdr_dvals;
375     char* _xdr_cvals;
376     int _width;
377     int _xdr_kind;
378     enum
379       {
380         _xdr_kind_null,
381         _xdr_kind_char,
382         _xdr_kind_int,
383         _xdr_kind_double
384       };
385   };
386 }
387
388 #endif