Salome HOME
22341: [CEA 958] sauv2med: different nb of gauss points in components
[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   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                     _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 isSameNbGauss() 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(bool& sameNbGauss) 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     void splitSubWithDiffNbGauss();
167
168     //virtual void dump(std::ostream&) const;
169     //virtual ~DoubleField() {}
170   };
171   // ==============================================================================
172   /*!
173    * \if developper
174    * Iterator on set of Cell's of given dimension
175    * \endif
176    */
177   class CellsByDimIterator
178   {
179   public:
180     CellsByDimIterator( const IntermediateMED & medi, int dim=-1); // dim=-1 - for all dimensions
181     void init(const int  dim=-1);
182
183     //!< return next set of Cell's of required dimension
184     const std::set<Cell > * nextType();
185     //!< return dimension of Cell's returned by the last or further next()
186     int dim(const bool last=true) const;
187     //!< return type of Cell's returned by the last next()
188     TCellType type() const { return TCellType( myCurType ); }
189
190   private:
191     const IntermediateMED* myImed;
192     int myCurType, myTypeEnd;
193     int myDim;
194   };
195
196   // ==============================================================================
197   /*!
198    * \if developper
199    * Container of Node's. Prevents re-allocation at addition of Node's
200    * \endif
201    */
202   class NodeContainer
203   {
204     std::vector< std::vector< Node > > _nodes;
205   public:
206     Node* getNode( const TID nID )
207     {
208       const size_t chunkSize = 1000;
209       const size_t chunkID = (nID-1) / chunkSize;
210       const size_t pos     = (nID-1) % chunkSize;
211       if ( _nodes.size() < chunkID+1 )
212       {
213         std::vector< std::vector< Node > > newNodes(chunkID+1);
214         for ( size_t i = 0; i < _nodes.size(); ++i )
215           newNodes[i].swap( _nodes[i] );
216         for ( size_t i = _nodes.size(); i < newNodes.size(); ++i )
217           newNodes[i].resize( chunkSize );
218         _nodes.swap( newNodes );
219       }
220       return & _nodes[chunkID][pos];
221     }
222     bool empty() const { return _nodes.empty(); }
223     size_t size() const { return empty() ? 0 : _nodes.size() * _nodes[0].size(); }
224     int numberNodes();
225   };
226
227   // ==============================================================================
228   /*!
229    * \if developper
230    * Intermediate structure used to store data read from the Sauve format file.
231    * The structure provides functions that transform the stored data to the MED format
232    *
233    * The elements inserted in maillage are ordered in order to avoid duplicated elements.
234    * \endif
235    */
236   struct IntermediateMED
237   {
238     unsigned                   _spaceDim;
239     unsigned                   _nbNodes;
240     NodeContainer              _points;
241     std::vector<double>        _coords;
242     std::vector<Group>         _groups;
243     std::vector<DoubleField* > _nodeFields;
244     std::vector<DoubleField* > _cellFields;
245
246     // IMP 0020434: mapping GIBI names to MED names
247     std::list<nameGIBItoMED>  _listGIBItoMED_mail; // to read from table "MED_MAIL" of PILE_TABLES
248     std::list<nameGIBItoMED>  _listGIBItoMED_cham; // to read from table "MED_CHAM" of PILE_TABLES
249     std::list<nameGIBItoMED>  _listGIBItoMED_comp; // to read from table "MED_COMP" of PILE_TABLES
250     std::map<int,std::string> _mapStrings;         // to read from PILE_STRINGS
251
252     IntermediateMED(): _spaceDim(0), _nbNodes(0) {}
253     ~IntermediateMED();
254
255     Node* getNode( TID nID ) { return _points.getNode( nID ); }
256     int getNbCellsOfType( TCellType type ) const { return _cellsByType[type].size(); }
257     const Cell* insert(TCellType type, const Cell& ma) { return &( *_cellsByType[type].insert( ma ).first ); }
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