Salome HOME
Merge from V6_main_20120808 08Aug12
[modules/med.git] / src / MEDMEM / MEDMEM_MedFileBrowser.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "MEDMEM_MedFileBrowser.hxx"
24
25 #include "MEDMEM_Utilities.hxx"
26 #include "MEDMEM_STRING.hxx"
27 #include "MEDMEM_DriversDef.hxx"
28 #include "MEDMEM_MedVersion.hxx"
29
30 #include <set>
31
32 using namespace std;
33 using namespace MEDMEM;
34 using namespace MED_EN;
35
36 namespace 
37 {
38   /*!
39    * \brief Structure to open a med file and to close it at destruction
40    * (especially useful when we throw an exception)
41    */
42   struct MED_FILE
43   {
44     med_2_3::med_idt _id;
45     MED_FILE(const string fileName)
46     {
47       _id = med_2_3::MEDfileOpen(fileName.c_str(),med_2_3::MED_ACC_RDONLY);
48     }
49     ~MED_FILE()
50     {
51       if ( _id > 0 )
52         med_2_3::MEDfileClose(_id);
53     }
54     operator med_2_3::med_idt() const { return _id; }
55   };
56 }
57 /*!
58
59 \defgroup MEDFILEBROWSER_constructors Initialization
60
61 \defgroup MEDFILEBROWSER_query Query methods
62 These methods enable the user to retrieve information
63 about a MED file structure, i.e. the meshes and fields it contains.
64
65 */
66
67 /*! \if MEDMEM_ug 
68 \addtogroup MEDFILEBROWSER_constructors
69 @{
70 \endif
71 */
72 //================================================================================
73 /*!
74  * \brief Constructor of an empty MEDFILEBROWSER to be filled with \ref readFileStruct()
75  */
76 //================================================================================
77
78 MEDFILEBROWSER::MEDFILEBROWSER()
79 {
80 }
81
82 //================================================================================
83 /*!
84  * \brief This constructor constructs the MEDFILEBROWSER object from the file \a filename.
85  * Names of meshes and fields are read.
86  */
87 //================================================================================
88
89 MEDFILEBROWSER::MEDFILEBROWSER(const std::string & fileName) throw (MED_EXCEPTION)
90 {
91   readFileStruct( fileName );
92 }
93
94 //================================================================================
95 /*!
96  * \brief Read names of meshes and fields from the file \a fileName
97  */
98 //================================================================================
99
100 void MEDFILEBROWSER::readFileStruct(const std::string & fileName) throw (MEDEXCEPTION)
101 {
102   const char * LOC = "MEDFILEBROWSER::readFileStruct() : ";
103   BEGIN_OF_MED(LOC);
104
105   _fileName = fileName;
106   _meshes.clear();
107   _fields.clear();
108
109   // =================
110   // 1. Open the file
111   // =================
112
113   if ( _fileName.empty() )
114     throw MED_EXCEPTION
115       ( LOCALIZED( STRING(LOC) << "_fileName is |\"\"|, please provide a correct fileName"));
116
117   MED_EN::medFileVersion version = getMedFileVersion(_fileName);
118   if ( version == MED_EN::V21 )
119     throw MED_EXCEPTION
120       ( LOCALIZED( STRING(LOC) << _fileName << " is med-2.1 file which is of no longer supported version"));
121
122   MED_FILE medIdt(_fileName);
123
124   if (medIdt < 0)
125     throw MED_EXCEPTION
126       (LOCALIZED( STRING(LOC)<< "Can't open |"  << _fileName<< "|, medIdt : " << medIdt));
127
128   int err,i,j;
129
130   // =========================================
131   // 2. Read number of meshes and their names
132   // =========================================
133   {
134     char                  meshName[MED_NAME_SIZE+1]="";
135     char                  meshDescription[MED_COMMENT_SIZE+1]="";
136     med_2_3::med_int      meshDim;
137     med_2_3::med_mesh_type meshType;
138
139     int numberOfMeshes = med_2_3::MEDnMesh(medIdt) ;
140     if ( numberOfMeshes <= 0 ) 
141       MESSAGE_MED(LOC << "Be careful there is no mesh in file |"<<_fileName<<"| !");
142
143     for (i=1;i<=numberOfMeshes;i++)
144     {
145       //get information on the i^th mesh
146       int spaceDim;
147       int naxis=med_2_3::MEDmeshnAxis(medIdt,i);
148       med_2_3::med_axis_type axistype;
149       med_2_3::med_sorting_type stype;
150       char *axisname=new char[naxis*MED_SNAME_SIZE+1];
151       char *axisunit=new char[naxis*MED_SNAME_SIZE+1];
152       int nstep;
153       char dtunit[MED_COMMENT_SIZE+1];
154       err = med_2_3::MEDmeshInfo(medIdt, i, meshName, &spaceDim, &meshDim, &meshType, meshDescription, dtunit, &stype, &nstep, &axistype, axisname, axisunit) ;
155       delete [] axisname;
156       delete [] axisunit;
157       if (err != MED_VALID)
158         throw MED_EXCEPTION(LOCALIZED(STRING(LOC) << ": can't get information about the mesh #" << i << " of the file |" << _fileName << "| !"));
159
160       // Don't want to prevent the user from reading other correct meshes
161 //       if (meshType != med_2_3::MED_STRUCTURE &&
162 //           meshType != med_2_3::MED_NON_STRUCTURE )
163 //         throw MEDEXCEPTION
164 //           (LOCALIZED(STRING(LOC) << "Bad mesh type of mesh #"<<i <<" in file |"<<_fileName<<"|"));
165       _meshes.insert( make_pair( string(meshName), meshType == med_2_3::MED_STRUCTURED_MESH ));
166     }
167   }
168
169   // ===================================================================
170   // 3. Read number of fields and their (timeStepNumber,iterationNumber)
171   // ===================================================================
172   {
173     //    char                          fieldName[MED_NAME_SIZE+1] = "";
174     char                          fieldName[MED_NAME_SIZE+1] ; // to avoid a crash if the field name is longer than MED_NAME_SIZE....
175     char                          * componentName              = (char *) MED_NULL;
176     char                          * unitName                   = (char *) MED_NULL;
177     char                          meshName[MED_NAME_SIZE+1]  ;
178     med_2_3::med_field_type       type;
179     MESH_ENTITIES::const_iterator currentEntity; 
180     list<MED_EN::medGeometryElement>::const_iterator currentGeometry;
181     med_2_3::med_int              timeStepNumber               =  -1;
182     char                          timeStepUnit[MED_LNAME_SIZE+1] ;
183     double                        timeStep                     = 0.0;
184     med_2_3::med_int              orderNumber                  =  -1;
185     med_2_3::med_bool             meshLink;
186
187     int numberOfFields = med_2_3::MEDnField(medIdt) ;
188
189     for (i=1;i<=numberOfFields;i++)
190     {
191       int numberOfComponents = med_2_3::MEDfieldnComponent(medIdt,i) ;
192
193       componentName = new char[numberOfComponents*MED_SNAME_SIZE+1] ;
194       unitName      = new char[numberOfComponents*MED_SNAME_SIZE+1] ;
195       int nstepsp3;
196       err = med_2_3::MEDfieldInfo(medIdt, i, fieldName, meshName, &meshLink, &type, componentName, 
197                                   unitName, timeStepUnit, &nstepsp3) ;
198       delete[] componentName ;
199       delete[] unitName ;
200
201       MESSAGE_MED("Field #" << i << " is named " << fieldName);
202
203       if (err != MED_VALID)
204         throw MED_EXCEPTION(LOCALIZED(STRING(LOC) << ": can't get information about the field #" << i <<" of the file |" << _fileName << "| !"));
205
206       map< string, FIELD_DATA_ >::iterator name2data =
207         _fields.insert( make_pair( fieldName, FIELD_DATA_() )).first;
208
209       FIELD_DATA_& fieldData = name2data->second;
210       fieldData._type = MED_EN::med_type_champ( type );
211
212       // find all dtid of this field
213       set<DT_IT_, LT_DT_IT_> set_dtit;
214
215       for (j=1;j <= nstepsp3; j++)
216         {
217           err = med_2_3::MEDfieldComputingStepInfo(medIdt, fieldName, j, &timeStepNumber, &orderNumber, &timeStep);
218           
219           if (err == MED_VALID) // we have found for (*currentEntity).first and (*currentGeometry)
220             {
221               DT_IT_ dtIt;
222               if (timeStepNumber<0)  timeStepNumber=-1 ;
223               dtIt.dt  = timeStepNumber;
224               dtIt.it  = orderNumber;
225               
226               set_dtit.insert( dtIt );
227             }
228         }
229       fieldData._meshName = meshName;
230       fieldData._vec_dtit.assign( set_dtit.begin(), set_dtit.end() );
231
232     } // loop on numberOfFields
233   }
234
235   END_OF_MED(LOC);
236 }
237 /*! \if MEDMEM_ug @} \endif */
238
239 /*! \if MEDMEM_ug
240 \addtogroup MEDFILEBROWSER_query
241 @{
242 \endif
243 */
244
245 //================================================================================
246 /*!
247  * \brief Returns the name of a browsed file
248  */
249 //================================================================================
250
251 std::string MEDFILEBROWSER::getFileName() const
252 {
253   return _fileName;
254 }
255
256 //================================================================================
257 /*!
258   \brief Gets the number of meshes in med file.
259 */
260 //================================================================================
261
262 int MEDFILEBROWSER::getNumberOfMeshes ( void ) const
263 {
264   return _meshes.size();
265 }   
266     
267 //================================================================================
268 /*!
269   \brief Gets the number of fields in med file.
270 */
271 //================================================================================
272
273 int MEDFILEBROWSER::getNumberOfFields ( void ) const
274 {
275   return _fields.size(); // we get number of field with different name
276 }       
277
278 //================================================================================
279 /*!
280   \brief Gets the names of all meshes.
281
282   meshNames is an in/out argument.
283
284   It is a string array of size the
285   number of meshes. It must be allocated before calling
286   this method. All names are put in it.
287 */
288 //================================================================================
289
290 void MEDFILEBROWSER::getMeshNames      ( std::string * meshNames ) const
291 {
292   map< string, bool >::const_iterator name_isstruct = _meshes.begin();
293   for ( int i=0; name_isstruct != _meshes.end(); ++i, ++name_isstruct )
294     meshNames[i] = name_isstruct->first;
295 }
296
297 //================================================================================
298 /*!
299   \brief Gets the names of all MESH objects.
300
301   Returns a vector<string> object which contain the name of all MESH objects.
302 */
303 //================================================================================
304
305 vector<string> MEDFILEBROWSER::getMeshNames      () const
306 {
307   vector<string> meshNames( _meshes.size() );
308   map< string, bool >::const_iterator name_isstruct = _meshes.begin();
309   for ( int i=0; name_isstruct != _meshes.end(); ++i, ++name_isstruct )
310     meshNames[i] = name_isstruct->first;
311   return meshNames;
312 }
313
314 //================================================================================
315 /*!
316   \brief Gets the names of all fields.
317
318   fieldNames is an in/out argument.
319
320   It is an array of string of size the
321   number of fields. It must be allocated before calling
322   this method. All names are put in it.
323 */
324 //================================================================================
325
326 void MEDFILEBROWSER::getFieldNames     ( std::string * fieldNames ) const
327 {
328   map< string, FIELD_DATA_ >::const_iterator name_data = _fields.begin();
329   for( int i = 0; name_data != _fields.end(); ++name_data, ++i )
330     fieldNames[i] = name_data->first;
331 }
332
333 //================================================================================
334 /*!
335   \brief Gets the names of all fields.
336 */
337 //================================================================================
338
339 vector<string> MEDFILEBROWSER::getFieldNames     () const
340 {
341   vector<string> fieldNames( _fields.size() );
342   map< string, FIELD_DATA_ >::const_iterator name_data = _fields.begin();
343   for( int i = 0; name_data != _fields.end(); ++name_data, ++i )
344     fieldNames[i] = name_data->first;
345   return fieldNames;
346 }
347
348 //================================================================================
349 /*!
350  * \brief Return true if mesh \a meshName is a structured one
351  */
352 //================================================================================
353
354 bool MEDFILEBROWSER::isStructuredMesh(const std::string & meshName) const throw (MEDEXCEPTION)
355 {
356   const char* LOC="MEDFILEBROWSER::isStructuredMesh(meshName)";
357
358   map< std::string, bool >::const_iterator name_isstruct = _meshes.find(meshName);
359   if ( name_isstruct == _meshes.end() )
360     throw MEDEXCEPTION
361       ( LOCALIZED( STRING(LOC)<< "There is no known mesh named |"<< meshName
362                    << "| in file |" << _fileName <<"|"));
363
364   return name_isstruct->second;
365 }
366
367 //================================================================================
368 /*!
369  * \brief Return type of values of FIELD named \a fieldName 
370  */
371 //================================================================================
372
373 med_type_champ MEDFILEBROWSER::getFieldType(const std::string & fieldName) const throw (MEDEXCEPTION)
374 {
375   const char* LOC="MEDFILEBROWSER::getFieldIteration (fieldName)";
376
377   std::map< std::string, FIELD_DATA_ >::const_iterator name_data = _fields.find(fieldName);
378
379   if ( name_data == _fields.end() )
380     throw MEDEXCEPTION
381       ( LOCALIZED( STRING(LOC)<< "There is no known field named |"<< fieldName
382                    << "| in file |" << _fileName <<"|"));
383
384   return name_data->second._type;
385 }
386
387 //================================================================================
388 /*!
389  * \brief Return name of mesh supporting the FIELD named \a fieldName 
390  */
391 //================================================================================
392
393 std::string MEDFILEBROWSER::getMeshName (const std::string & fieldName) const throw (MEDEXCEPTION)
394 {
395   const char* LOC="MEDFILEBROWSER::getMeshName (fieldName)";
396
397   std::map< std::string, FIELD_DATA_ >::const_iterator name_data = _fields.find(fieldName);
398
399   if ( name_data == _fields.end() )
400     throw MEDEXCEPTION
401       ( LOCALIZED( STRING(LOC)<< "There is no known field named |"<< fieldName
402                    << "| in file |" << _fileName <<"|"));
403
404   return name_data->second._meshName;
405 }
406
407 //================================================================================
408 /*!
409   \brief Returns a vector<DT_IT_> which contain all iteration step for the FIELD 
410   identified by its name.
411
412   DT_IT_ definition is 
413 \verbatim
414 typedef struct { int dt; int it; } DT_IT_;
415 \endverbatim
416
417 \a dt represents the time iteration number, while \a it represents
418 the inner iteration number.
419 */
420 //================================================================================
421
422 vector<DT_IT_> MEDFILEBROWSER::getFieldIteration (const std::string & fieldName) const
423   throw (MED_EXCEPTION)
424 {
425   const char* LOC="MEDFILEBROWSER::getFieldIteration (fieldName)";
426
427   std::map< std::string, FIELD_DATA_ >::const_iterator name_data = _fields.find(fieldName);
428
429   if ( name_data == _fields.end() )
430     throw MEDEXCEPTION
431       ( LOCALIZED( STRING(LOC)<< "There is no known field named |"<< fieldName
432                    << "| in file |" << _fileName <<"|"));
433
434   return name_data->second._vec_dtit;
435 }
436 /*!\if MEDMEM_ug @} \endif */