1 // Copyright (C) 2007-2016 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"
41 class DataArrayDouble;
45 class MEDFileFieldMultiTS;
49 namespace SauvUtilities
51 struct IntermediateMED;
53 // ==============================================================================
54 typedef int TID; // an ID countered from 1
55 typedef std::pair<TID,TID> Link; // a pair of node numbers
57 typedef INTERP_KERNEL::NormalizedCellType TCellType;
59 // ==============================================================================
66 bool isUsed() const { return _number != 0; }
69 // ==============================================================================
72 std::vector< Node* > _nodes;
73 mutable bool _reverse; // to reverse orienation of a face only
74 mutable TID* _sortedNodeIDs; // for comparison
77 Cell(size_t nnNodes=0) : _nodes(nnNodes),_reverse(false),_sortedNodeIDs(0),_number(0) {}
79 void init() const { if ( _sortedNodeIDs ) delete [] _sortedNodeIDs; _sortedNodeIDs = 0; }
82 const TID* getSortedNodes() const; // creates if needed and return _sortedNodeIDs
83 bool operator < (const Cell& ma) const;
84 Link link(int i) const;
87 Cell& operator=(const Cell& ma);
89 std::ostream& operator << (std::ostream& os, const Cell& ma);
91 // ==============================================================================
96 std::vector<const Cell*> _cells;
97 std::vector< Group* > _groups; // des sous-groupes composant le 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 MEDCoupling::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 MEDCoupling::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 MEDCoupling::TypeOfField getMedType( const int iSub=0 ) const;
160 MEDCoupling::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 Group* addNewGroup(std::vector<SauvUtilities::Group*>* groupsToFix=0);
259 MEDCoupling::MEDFileData* convertInMEDFileDS();
263 MEDCoupling::MEDFileUMesh* makeMEDFileMesh();
264 MEDCoupling::DataArrayDouble * getCoords();
265 void setConnectivity( MEDCoupling::MEDFileUMesh* mesh, MEDCoupling::DataArrayDouble* coords );
266 void setGroups( MEDCoupling::MEDFileUMesh* mesh );
267 MEDCoupling::MEDFileFields * makeMEDFileFields(MEDCoupling::MEDFileUMesh* mesh);
268 void setFields( SauvUtilities::DoubleField* fld,
269 MEDCoupling::MEDFileFields* medFields,
270 MEDCoupling::MEDFileUMesh* mesh,
272 std::set< std::string >& usedNames);
273 void setTS( SauvUtilities::DoubleField* fld,
274 MEDCoupling::DataArrayDouble* values,
275 MEDCoupling::MEDFileFields* medFields,
276 MEDCoupling::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();
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 );