1 // Copyright (C) 2007-2014 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, or (at your option) any later version.
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);
259 ParaMEDMEM::MEDFileData* convertInMEDFileDS(bool fix2DOri);
263 ParaMEDMEM::MEDFileUMesh* makeMEDFileMesh(bool fix2DOri);
264 ParaMEDMEM::DataArrayDouble * getCoords();
265 void setConnectivity( ParaMEDMEM::MEDFileUMesh* mesh, ParaMEDMEM::DataArrayDouble* coords );
266 void setGroups( ParaMEDMEM::MEDFileUMesh* mesh );
267 ParaMEDMEM::MEDFileFields * makeMEDFileFields(ParaMEDMEM::MEDFileUMesh* mesh);
268 void setFields( SauvUtilities::DoubleField* fld,
269 ParaMEDMEM::MEDFileFields* medFields,
270 ParaMEDMEM::MEDFileUMesh* mesh,
272 std::set< std::string >& usedNames);
273 void setTS( SauvUtilities::DoubleField* fld,
274 ParaMEDMEM::DataArrayDouble* values,
275 ParaMEDMEM::MEDFileFields* medFields,
276 ParaMEDMEM::MEDFileUMesh* mesh,
278 void checkDataAvailability() const;
279 void setGroupLongNames();
280 void setFieldLongNames(std::set< std::string >& usedNames);
281 void makeFieldNewName(std::set< std::string >& usedNames,
282 SauvUtilities::DoubleField* fld );
283 void decreaseHierarchicalDepthOfSubgroups();
284 void eraseUselessGroups();
285 void detectMixDimGroups();
286 void orientElements2D();
287 void orientElements3D(bool fix2DOri);
288 void orientFaces3D();
289 void orientVolumes();
290 void numberElements();
291 bool isOnAll( const Group* grp, int & dimRel ) const;
292 const double* nodeCoords( const Node* n ) { return &_coords[ (n->_coordID-1) * _spaceDim ]; }
295 // { myNodesNumerated = myMaillesNumerated = myGroupsTreated = false; currentTypeMailles = 0; }
296 // ~IntermediateMED();
298 //bool myNodesNumerated, myMaillesNumerated;
300 // mailles groupped by geom type; use insert() for filling in and
301 // _CellsByDimIterator for exploring it
302 //std::set<_Cell> maillage;
303 std::set< Cell > _cellsByType[ INTERP_KERNEL::NORM_HEXA20 + 1 ];
304 friend class CellsByDimIterator;
307 // ==============================================================================
309 * \brief ASCII sauve file reader
311 class ASCIIReader : public FileReader
314 ASCIIReader(const char* fileName);
315 virtual ~ASCIIReader();
316 virtual bool isASCII() const;
318 virtual bool getNextLine (char* & line, bool raiseOEF = true );
319 virtual void initNameReading(int nbValues, int width = 8);
320 virtual void initIntReading(int nbValues);
321 virtual void initDoubleReading(int nbValues);
322 virtual bool more() const;
324 virtual int getInt() const;
325 virtual float getFloat() const;
326 virtual double getDouble() const;
327 virtual std::string getName() const;
328 int lineNb() const { return _lineNb; }
332 bool getLine(char* & line);
333 void init( int nbToRead, int nbPosInLine, int width, int shift = 0 );
335 // getting a line from the file
337 char* _start; // working buffer beginning
343 int _iPos, _nbPosInLine, _width, _shift;
346 // ==============================================================================
348 * \brief XDR (binary) sauve file reader
350 class XDRReader : public FileReader
353 XDRReader(const char* fileName);
354 virtual ~XDRReader();
355 virtual bool isASCII() const;
357 virtual bool getNextLine (char* & line, bool raiseOEF = true );
358 virtual void initNameReading(int nbValues, int width = 8);
359 virtual void initIntReading(int nbValues);
360 virtual void initDoubleReading(int nbValues);
361 virtual bool more() const;
363 virtual int getInt() const;
364 virtual float getFloat() const;
365 virtual double getDouble() const;
366 virtual std::string getName() const;
370 void init( int nbToRead, int width = 0 );