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 class 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 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; }
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() 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;
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 ParaMEDMEM::MEDFileData* convertInMEDFileDS();
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,
270 std::set< std::string >& usedNames);
271 void setTS( SauvUtilities::DoubleField* fld,
272 ParaMEDMEM::DataArrayDouble* values,
273 ParaMEDMEM::MEDFileFields* medFields,
274 ParaMEDMEM::MEDFileUMesh* mesh,
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 ]; }
293 // { myNodesNumerated = myMaillesNumerated = myGroupsTreated = false; currentTypeMailles = 0; }
294 // ~IntermediateMED();
296 //bool myNodesNumerated, myMaillesNumerated;
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;
305 // ==============================================================================
307 * \brief ASCII sauve file reader
309 class ASCIIReader : public FileReader
312 ASCIIReader(const char* fileName);
313 virtual ~ASCIIReader();
314 virtual bool isASCII() const;
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;
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; }
330 bool getLine(char* & line);
331 void init( int nbToRead, int nbPosInLine, int width, int shift = 0 );
333 // getting a line from the file
335 char* _start; // working buffer beginning
341 int _iPos, _nbPosInLine, _width, _shift;
344 // ==============================================================================
346 * \brief XDR (binary) sauve file reader
348 class XDRReader : public FileReader
351 XDRReader(const char* fileName);
352 virtual ~XDRReader();
353 virtual bool isASCII() const;
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;
361 virtual int getInt() const;
362 virtual float getFloat() const;
363 virtual double getDouble() const;
364 virtual std::string getName() const;
368 void init( int nbToRead, int width = 0 );