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 _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
105 ParaMEDMEM::DataArrayInt* _medGroup; // result of conversion
106 std::vector< unsigned > _relocTable; // for _cells[i] gives its index in _medGroup
108 bool empty() const { return _cells.empty() && _groups.empty(); }
110 Group():_cellType(INTERP_KERNEL::NORM_ERROR), _isProfile(false), _medGroup(NULL) {}
113 // ==============================================================================
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 // --------------------------------
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
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; }
135 // ----------------------------------------------------------------------------
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
146 std::vector< std::vector< double > > _comp_values;
147 ParaMEDMEM::MEDFileFieldMultiTS* _curMedField;
149 DoubleField( int nb_sub, int total_nb_comp )
150 : _sub(nb_sub), _group(NULL), _curMedField(NULL) { _comp_values.reserve( total_nb_comp ); }
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;
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();
167 //virtual void dump(std::ostream&) const;
168 //virtual ~DoubleField() {}
170 // ==============================================================================
173 * Iterator on set of Cell's of given dimension
176 class CellsByDimIterator
179 CellsByDimIterator( const IntermediateMED & medi, int dim=-1); // dim=-1 - for all dimensions
180 void init(const int dim=-1);
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 ); }
190 const IntermediateMED* myImed;
191 int myCurType, myTypeEnd;
195 // ==============================================================================
198 * Container of Node's. Prevents re-allocation at addition of Node's
203 std::vector< std::vector< Node > > _nodes;
205 Node* getNode( const TID nID )
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 )
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 );
219 return & _nodes[chunkID][pos];
221 bool empty() const { return _nodes.empty(); }
222 size_t size() const { return empty() ? 0 : _nodes.size() * _nodes[0].size(); }
226 // ==============================================================================
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
232 * The elements inserted in maillage are ordered in order to avoid duplicated elements.
235 struct IntermediateMED
239 NodeContainer _points;
240 std::vector<double> _coords;
241 std::vector<Group> _groups;
242 std::vector<DoubleField* > _nodeFields;
243 std::vector<DoubleField* > _cellFields;
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
251 IntermediateMED(): _spaceDim(0), _nbNodes(0) {}
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();
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 );