1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // File : SauvMedConvertor.hxx
20 // Created : Tue Aug 16 14:14:02 2011
21 // Author : Edward AGAPOV (eap)
24 #ifndef __SauvMedConvertor_HXX__
25 #define __SauvMedConvertor_HXX__
27 #include "InterpKernelException.hxx"
28 #include "NormalizedUnstructuredMesh.hxx"
29 #include "MEDCouplingRefCountObject.hxx"
30 #include "SauvUtilities.hxx"
40 class DataArrayDouble;
44 class MEDFileFieldMultiTS;
48 namespace SauvUtilities
50 struct IntermediateMED;
52 // ==============================================================================
53 typedef int TID; // an ID countered from 1
54 typedef std::pair<TID,TID> Link; // a pair of node numbers
56 typedef INTERP_KERNEL::NormalizedCellType TCellType;
58 // ==============================================================================
65 bool isUsed() const { return _number != 0; }
68 // ==============================================================================
71 std::vector< Node* > _nodes;
72 mutable bool _reverse; // to reverse orienation of a face only
73 mutable TID* _sortedNodeIDs; // for comparison
76 Cell(size_t nnNodes=0) : _nodes(nnNodes),_reverse(false),_sortedNodeIDs(0),_number(0) {}
78 void init() const { if ( _sortedNodeIDs ) delete [] _sortedNodeIDs; _sortedNodeIDs = 0; }
81 const TID* getSortedNodes() const; // creates if needed and return _sortedNodeIDs
82 bool operator < (const Cell& ma) const;
83 Link link(int i) const;
86 Cell& operator=(const Cell& ma);
88 std::ostream& operator << (std::ostream& os, const Cell& ma);
90 // ==============================================================================
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
106 ParaMEDMEM::DataArrayInt* _medGroup; // result of conversion
107 std::vector< unsigned > _relocTable; // for _cells[i] gives its index in _medGroup
109 bool empty() const { return _cells.empty() && _groups.empty(); }
111 Group():_cellType(INTERP_KERNEL::NORM_ERROR), _isProfile(false), _medGroup(NULL) {}
114 // ==============================================================================
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 // --------------------------------
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
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; }
136 // ----------------------------------------------------------------------------
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
147 std::vector< std::vector< double > > _comp_values;
148 ParaMEDMEM::MEDFileFieldMultiTS* _curMedField;
150 DoubleField( int nb_sub, int total_nb_comp )
151 : _sub(nb_sub), _group(NULL), _curMedField(NULL) { _comp_values.reserve( total_nb_comp ); }
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;
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();
168 //virtual void dump(std::ostream&) const;
169 //virtual ~DoubleField() {}
171 // ==============================================================================
174 * Iterator on set of Cell's of given dimension
177 class CellsByDimIterator
180 CellsByDimIterator( const IntermediateMED & medi, int dim=-1); // dim=-1 - for all dimensions
181 void init(const int dim=-1);
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 ); }
191 const IntermediateMED* myImed;
192 int myCurType, myTypeEnd;
196 // ==============================================================================
199 * Container of Node's. Prevents re-allocation at addition of Node's
204 std::vector< std::vector< Node > > _nodes;
206 Node* getNode( const TID nID )
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 )
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 );
220 return & _nodes[chunkID][pos];
222 bool empty() const { return _nodes.empty(); }
223 size_t size() const { return empty() ? 0 : _nodes.size() * _nodes[0].size(); }
227 // ==============================================================================
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
233 * The elements inserted in maillage are ordered in order to avoid duplicated elements.
236 struct IntermediateMED
240 NodeContainer _points;
241 std::vector<double> _coords;
242 std::vector<Group> _groups;
243 std::vector<DoubleField* > _nodeFields;
244 std::vector<DoubleField* > _cellFields;
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
252 IntermediateMED(): _spaceDim(0), _nbNodes(0) {}
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();
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,
271 std::set< std::string >& usedNames);
272 void setTS( SauvUtilities::DoubleField* fld,
273 ParaMEDMEM::DataArrayDouble* values,
274 ParaMEDMEM::MEDFileFields* medFields,
275 ParaMEDMEM::MEDFileUMesh* mesh,
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 ]; }
294 // { myNodesNumerated = myMaillesNumerated = myGroupsTreated = false; currentTypeMailles = 0; }
295 // ~IntermediateMED();
297 //bool myNodesNumerated, myMaillesNumerated;
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;
306 // ==============================================================================
308 * \brief ASCII sauve file reader
310 class ASCIIReader : public FileReader
313 ASCIIReader(const char* fileName);
314 virtual ~ASCIIReader();
315 virtual bool isASCII() const;
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;
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; }
331 bool getLine(char* & line);
332 void init( int nbToRead, int nbPosInLine, int width, int shift = 0 );
334 // getting a line from the file
336 char* _start; // working buffer beginning
342 int _iPos, _nbPosInLine, _width, _shift;
345 // ==============================================================================
347 * \brief XDR (binary) sauve file reader
349 class XDRReader : public FileReader
352 XDRReader(const char* fileName);
353 virtual ~XDRReader();
354 virtual bool isASCII() const;
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;
362 virtual int getInt() const;
363 virtual float getFloat() const;
364 virtual double getDouble() const;
365 virtual std::string getName() const;
369 void init( int nbToRead, int width = 0 );