Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/med.git] / src / MEDMEM / MEDMEM_Med.cxx
1 //  Copyright (C) 2007-2008  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 # include <string> 
23 # include <math.h>
24
25 # include "MEDMEM_Med.hxx"
26 # include "MEDMEM_DriverFactory.hxx" 
27 # include "MEDMEM_STRING.hxx"
28
29 # include "MEDMEM_Mesh.hxx"
30 # include "MEDMEM_Grid.hxx"
31 # include "MEDMEM_Field.hxx"
32 # include "MEDMEM_Group.hxx"
33 # include "MEDMEM_Family.hxx"
34
35 # include "MEDMEM_Exception.hxx"
36 # include "MEDMEM_Utilities.hxx"
37
38 using namespace std;
39 using namespace MEDMEM;
40 using namespace MED_EN;
41
42 #define MED_NOPDT -1
43
44 /*!
45
46 \defgroup MED_constructors Constructors
47
48 \defgroup MED_query Query methods
49 These methods enable the user to retrieve information
50 about a MED file structure, i.e. the meshes, supports
51 and fields that it contains.
52
53 \defgroup MED_io File I/O methods
54 These methods are similar to their MESH counterparts. 
55 Reading should be achieved thrfough the MED constructor, while writing 
56 is performed thanks to two calls : one attaching a driver to the MED
57 object, the other one writing the file.
58
59 */
60 MED::MED() {
61   MESSAGE_MED("MED::MED()");
62 }
63
64 /*! \if MEDMEM_ug 
65 \addtogroup MED_constructors
66 @{
67 \endif
68 */
69
70 /*!
71 This constructor constructs the Med object from the file \a filename.
72 The driver type can specify whether the file is opened in read, write or
73 read/write mode. Specifying MED_DRIVER as a \a driverType opens the file in read/write mode.
74 It is also possible to use VTK_DRIVER to open a VTK ascii file.
75 */
76 MED::MED(driverTypes driverType, const string & fileName)
77 {
78   const char* LOC = "MED::MED(driverTypes driverType, const string & fileName) : ";
79   BEGIN_OF_MED(LOC);
80
81   MESSAGE_MED(PREFIX_MED << "driverType = " << driverType);
82
83   int current = addDriver(driverType,fileName,RDONLY);
84
85   _drivers[current]->open();
86   _drivers[current]->readFileStruct();
87   _drivers[current]->close();
88
89   END_OF_MED(LOC);
90 }
91
92 /*!\if MEDMEM_ug @} \endif */
93
94
95 /*!\ifnot MEDMEM_ug
96   Destructor.
97 \endif
98 */
99 MED::~MED()
100 {
101   const char* LOC = "MED::~MED() : ";
102   BEGIN_OF_MED(LOC);
103
104   // Analysis of the object MED
105
106   int index;
107
108   map<FIELD_ *, MESH_NAME_>::const_iterator currentField;
109   index = 0;
110   for ( currentField=_meshName.begin();currentField != _meshName.end(); currentField++ ) {
111     if ( (*currentField).first != NULL) index++;
112   }
113
114   MESSAGE_MED(PREFIX_MED << " there is(are) " << index << " field(s):");
115   for ( currentField=_meshName.begin();currentField != _meshName.end(); currentField++ ) {
116     if ( (*currentField).first != NULL) MESSAGE_MED("             " << ((*currentField).first)->getName().c_str());
117   }
118
119   map<MESH_NAME_, map<MED_EN::medEntityMesh,SUPPORT *> >::iterator itSupportOnMesh ;
120   index = 0;
121   for ( itSupportOnMesh=_support.begin();itSupportOnMesh != _support.end(); itSupportOnMesh++ ) {
122     map<MED_EN::medEntityMesh,SUPPORT *>::iterator itSupport ;
123     for ( itSupport=(*itSupportOnMesh).second.begin();itSupport!=(*itSupportOnMesh).second.end();itSupport++)
124       index++;
125   }
126
127   MESSAGE_MED(PREFIX_MED << " there is(are) " << index << " support(s):");
128
129   map<MESH_NAME_,MESH*>::const_iterator  currentMesh;
130   index =0;
131   for ( currentMesh=_meshes.begin();currentMesh != _meshes.end(); currentMesh++ ) {
132     if ( (*currentMesh).second != NULL)
133       index++;
134   }
135
136   MESSAGE_MED(PREFIX_MED << " there is(are) " << index << " meshe(s):");
137 //   for ( currentMesh=_meshes.begin();currentMesh != _meshes.end(); currentMesh++ ) {
138 //     if ( (*currentMesh).second != NULL)
139 //       {
140 //      SCRUTE_MED((*currentMesh).second);
141
142 //      string meshName = ((*currentMesh).second)->getName();
143
144 //      MESSAGE_MED("             " << meshName);
145 //       }
146 //   }
147
148   // delete all ? : PG : YES !
149   //  map<FIELD_ *, MESH_NAME_>::const_iterator currentField;
150   for ( currentField=_meshName.begin();currentField != _meshName.end(); currentField++ ) {
151     if ( (*currentField).first != NULL) {
152       // cast in right type to delete it !
153       switch ((*currentField).first->getValueType()) {
154       case MED_INT32 : 
155         delete (FIELD<int>*) (*currentField).first ;
156         break ;
157       case MED_REEL64 :
158         delete (FIELD<double>*) (*currentField).first ;
159         break ;
160       default : 
161         MESSAGE_MED(PREFIX_MED << "Field has type different of int or double, could not destroy its values array !") ;
162         delete (*currentField).first;
163       }
164     }
165   }
166   //  map<MESH_NAME_, map<MED_EN::medEntityMesh,SUPPORT *> >::iterator itSupportOnMesh ;
167   for ( itSupportOnMesh=_support.begin();itSupportOnMesh != _support.end(); itSupportOnMesh++ ) {
168     map<MED_EN::medEntityMesh,SUPPORT *>::iterator itSupport ;
169     for ( itSupport=(*itSupportOnMesh).second.begin();itSupport!=(*itSupportOnMesh).second.end();itSupport++)
170       if (! dynamic_cast<GROUP*>( (*itSupport).second ) &&
171           ! dynamic_cast<FAMILY*>( (*itSupport).second ) )
172         delete (*itSupport).second ;
173   }
174
175   //  map<MESH_NAME_,MESH*>::const_iterator  currentMesh;
176   for ( currentMesh=_meshes.begin();currentMesh != _meshes.end(); currentMesh++ ) {
177     if ( (*currentMesh).second != NULL)
178       {
179         if (!((*currentMesh).second)->getIsAGrid())
180           delete (*currentMesh).second;
181         else
182           delete (GRID *) (*currentMesh).second;
183       }
184   }
185
186   index =_drivers.size();
187
188   MESSAGE_MED(PREFIX_MED << "In this object MED there is(are) " << index << " driver(s):");
189
190   for (unsigned int ind=0; ind < _drivers.size(); ind++ )
191     {
192       SCRUTE_MED(_drivers[ind]);
193       if ( _drivers[ind] != NULL) delete _drivers[ind];
194     }
195
196
197
198   END_OF_MED(LOC);
199
200
201 /*! \if MEDMEM_ug
202 \addtogroup MED_io
203 @{
204 \endif
205 */
206
207 /*!
208   Create the specified driver and return its index reference to path to 
209   read or write methods.
210 */
211 int MED::addDriver(driverTypes driverType,
212                    const string & fileName="Default File Name.med",
213                    MED_EN::med_mode_acces access)
214 {
215
216   const char* LOC = "MED::addDriver(driverTypes driverType, const string & fileName=\"Default File Name.med\") : ";
217   BEGIN_OF_MED(LOC);
218
219   MESSAGE_MED(PREFIX_MED << " the file name is " << fileName);
220
221   SCRUTE_MED(driverType);
222   SCRUTE_MED(access);
223
224   GENDRIVER *driver = DRIVERFACTORY::buildDriverForMed(driverType,fileName,
225                                                        this,access);
226
227   _drivers.push_back(driver);
228
229   int current = _drivers.size()-1;
230
231   driver->setId(current); 
232
233   END_OF_MED(LOC);
234
235   return current;
236 }
237
238 /*!
239   Duplicate the given driver and return its index reference to path to 
240   read or write methods.
241 */
242 int  MED::addDriver(GENDRIVER & driver) {
243   int current;
244
245   const char* LOC = "MED::addDriver(GENDRIVER &) : ";
246   BEGIN_OF_MED(LOC);
247   
248   SCRUTE_MED(_drivers.size());
249
250   _drivers.push_back(&driver);
251
252   SCRUTE_MED(_drivers.size());
253
254   SCRUTE_MED(_drivers[0]);
255   SCRUTE_MED(driver);
256
257   current = _drivers.size()-1;
258   SCRUTE_MED(current);
259   driver.setId(current); 
260
261   END_OF_MED(LOC);
262
263   return current;
264   
265 }
266 /*! \if MEDMEM_ug @} \endif */
267
268 /*!
269   Remove the driver referenced by its index.
270 */
271 void MED::rmDriver (int index/*=0*/)
272   throw (MED_EXCEPTION)
273 {
274   const char * LOC = "MED::rmDriver (int index=0): ";
275   BEGIN_OF_MED(LOC);
276
277   if (index >= 0 && index < _drivers.size() && _drivers[index]) {
278     delete _drivers[index];
279     _drivers[index] = 0;
280     //_drivers.erase(&_drivers[index]); 
281   }
282   else
283     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
284                                      << "The index given is invalid, index must be between 0 and |" 
285                                      << _drivers.size()
286                                      )
287                           );   
288   END_OF_MED(LOC);
289 }
290
291 /*!
292   ??? to do comment ???
293 */
294 void MED::writeFrom (int index/*=0*/)
295   throw (MED_EXCEPTION)
296 {
297   const char * LOC = "MED::write (int index=0): ";
298   BEGIN_OF_MED(LOC);
299
300   if (index >= 0 && index < _drivers.size() && _drivers[index]) {
301     // open and close are made by all objects !
302     _drivers[index]->writeFrom();
303   }
304   else {
305     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
306                                      << "The index given is invalid, index must be between 0 and |" 
307                                      << _drivers.size()
308                                      )
309                           ); 
310   }
311   END_OF_MED(LOC);
312
313
314 /*!\if MEDMEM_ug 
315 \addtogroup MED_io
316 @{
317 \endif
318 */
319
320 /*!
321   Write all objects with the driver given by its index.
322 */
323 void MED::write (int index/*=0*/)
324   throw (MED_EXCEPTION)
325 {
326   const char * LOC = "MED::write (int index=0): ";
327   BEGIN_OF_MED(LOC);
328
329   if (_drivers[index]) {
330     // open and close are made by the subsequent objects !
331     _drivers[index]->write(); 
332   }
333   else
334     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
335                                      << "The index given is invalid, index must be between  0 and |" 
336                                      << _drivers.size()
337                                      )
338                           ); 
339   END_OF_MED(LOC);
340
341 /*!\if MEDMEM_ug @} \endif */
342
343 /*!
344   Parse all the file and generate empty object.
345
346   All object must be read explicitly later with their own method read 
347   or use MED::read to read all.
348
349   This method is automatically called by constructor with driver information.
350 */
351 void MED::readFileStruct (int index/*=0*/)
352   throw (MED_EXCEPTION)
353 {
354   const char * LOC = "MED::readFileStruct (int index=0): ";
355   BEGIN_OF_MED(LOC);
356   
357   if (_drivers[index]) {
358     _drivers[index]->open(); 
359     _drivers[index]->readFileStruct(); 
360     _drivers[index]->close(); 
361   }
362   else
363     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
364                                      << "The index given is invalid, index must be between 0 and |" 
365                                      << _drivers.size()
366                                      )
367                           );   
368 }
369
370 /*!
371   Read all objects in the file specified in the driver given by its index.
372 */
373 void MED::read  (int index/*=0*/)
374   throw (MED_EXCEPTION)
375 {
376   const char * LOC = "MED::read (int index=0): ";
377   BEGIN_OF_MED(LOC);
378   
379   SCRUTE_MED(index);
380
381   if (_drivers[index]) {
382     // open and close are made by all objects !
383     SCRUTE_MED(index);
384     SCRUTE_MED(_drivers[index]);
385     SCRUTE_MED(&_drivers[index]);
386     //    _drivers[index]->open();
387     _drivers[index]->read();
388     //    _drivers[index]->close();
389   }
390   else
391     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
392                                      << "The index given is invalid, index must be between  >0 and < |" 
393                                      << _drivers.size()-1 
394                                      )
395                           );  
396   END_OF_MED(LOC);
397   
398 }
399
400 // ------- End Of Drivers Management Part
401
402 /*! \if MEDMEM_ug
403 \addtogroup MED_query
404 @{
405 \endif
406 */
407
408 /*!
409   Gets the number of MESH objects.
410 */
411 int      MED::getNumberOfMeshes ( void ) const
412 {
413   const char* LOC = "MED::getNumberOfMeshes ( void ) const : ";
414   BEGIN_OF_MED(LOC);
415
416   return _meshes.size();
417 }   
418     
419 /*!
420   Gets the number of FIELD objects.
421 */
422 int      MED::getNumberOfFields ( void ) const
423 {
424   const char* LOC = "MED::getNumberOfFields ( void ) const : ";
425   BEGIN_OF_MED(LOC);
426
427   return _fields.size(); // we get number of field with different name
428 }       
429
430 /*!
431   Gets the names of all MESH objects.
432
433   meshNames is an in/out argument.
434
435   It is a string array of size the
436   number of MESH objects. It must be allocated before calling
437   this method. All names are put in it.
438 */
439 void MED::getMeshNames      ( string * meshNames ) const
440   throw (MED_EXCEPTION)
441 {
442   const char* LOC = "MED::getMeshNames ( string * ) const : ";
443   BEGIN_OF_MED(LOC);
444
445   // REM : ALLOCATION D'UN TABLEAU DE POINTEURS SUR STRING FAITE PAR LE CLIENT
446   map<MESH_NAME_,MESH*>::const_iterator  currentMesh; // ??ITERATEUR CONST SUR UN OBJET NON CONST ??
447
448   int meshNamesIndex = 0;
449
450   for ( currentMesh=_meshes.begin();currentMesh != _meshes.end(); currentMesh++ ) {
451     meshNames[meshNamesIndex]=(*currentMesh).first;
452     meshNamesIndex++;                               // CF OPTIMISATION
453   }
454
455   END_OF_MED(LOC);
456 }
457
458 /*!
459   Gets the names of all MESH objects.
460
461   Returns a deque<string> object which contain the name of all MESH objects.
462 */
463 deque<string> MED::getMeshNames      () const
464 {
465   const char* LOC = "MED::getMeshNames () const : ";
466   BEGIN_OF_MED(LOC);
467
468   deque<string> meshNames(_meshes.size());
469   
470   map<MESH_NAME_,MESH*>::const_iterator  currentMesh; // ??ITERATEUR CONST SUR UN OBJET NON CONST ??
471
472   int meshNamesIndex = 0;
473
474   for ( currentMesh=_meshes.begin();currentMesh != _meshes.end(); currentMesh++ ) {
475     meshNames[meshNamesIndex]=(*currentMesh).first;
476     meshNamesIndex++;                               // CF OPTIMISATION
477   }
478
479   END_OF_MED(LOC);
480   return meshNames ;
481 }
482
483
484 /*!
485   Returns a reference to the MESH object named meshName.
486 */
487 MESH   * MED::getMesh           ( const string & meshName )  const
488   throw (MED_EXCEPTION)
489 {
490
491   const char * LOC = "MED::getMesh ( const string & meshName ) const : ";
492   BEGIN_OF_MED(LOC);
493
494   map<MESH_NAME_,MESH*>::const_iterator itMeshes =  _meshes.find(meshName);
495
496   if ( itMeshes == _meshes.end() )
497     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
498                                      << "There is no known mesh named |" 
499                                      << meshName << "|"
500                                      )
501                           );
502   
503   return (*itMeshes).second;
504   
505   END_OF_MED(LOC);
506 }
507
508 /*!
509  \internal Returns a reference to the MESH object associated with 
510  field argument.
511 */
512 MESH   * MED::getMesh           (const FIELD_ * const field ) const
513   throw (MED_EXCEPTION)
514 {
515  
516   const char * LOC = "MED::getMesh ( const FIELD * field ) const : ";
517   BEGIN_OF_MED(LOC);
518
519   FIELD_ * f = const_cast< FIELD_* > (field);     //  Comment faire mieux ?
520   map<FIELD_ *, MESH_NAME_>::const_iterator itMeshName = _meshName.find(f);
521
522   if ( itMeshName  == _meshName.end() )
523     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
524                                      << "There is no known mesh associated with |" 
525                                      << field << "| pointer"
526                                      )
527                           );
528
529   string meshName = (*itMeshName).second;
530   map<MESH_NAME_,MESH*>::const_iterator itMeshes =  _meshes.find(meshName);
531   if ( itMeshes == _meshes.end() )
532     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC)
533                                      << "There is no known mesh named |"
534                                      << meshName << " while it's associated with the found field |"
535                                      << field << "| pointer"
536                                      )
537                           );
538
539   END_OF_MED(LOC);
540
541   return (*itMeshes).second;
542 }
543
544
545 /*!
546   Gets the names of all FIELD objects.
547
548   fieldNames is an in/out argument.
549
550   It is an array of string of size the
551   number of FIELD objects. It must be allocated before calling
552   this method. All names are put in it.
553 */
554 void MED::getFieldNames     ( string * fieldNames ) const
555   throw (MED_EXCEPTION)
556 {
557   const char* LOC = "MED::getFieldNames ( string * ) const : ";
558   BEGIN_OF_MED(LOC);
559
560 //  unsigned int fieldNamesSize =  sizeof(fieldNames) / sizeof(string *);
561  
562 //  if ( fieldNamesSize != _fields.size() )
563 //    throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
564 //                                     << "Size of parameter fieldNames is |" 
565 //                                     << fieldNamesSize     << "| and should be |" 
566 //                                     << _fields.size() << "| and should be |" 
567 //                                     )
568 //                         );   
569   
570   // REM : ALLOCATION D'UN TABLEAU DE POINTEURS SUR STRING FAITE PAR LE CLIENT
571   map<FIELD_NAME_,MAP_DT_IT_>::const_iterator  currentField;
572
573   int fieldNamesIndex = 0;
574   for ( currentField=_fields.begin();currentField != _fields.end(); currentField++ ) {
575     fieldNames[fieldNamesIndex]=(*currentField).first;
576     fieldNamesIndex++;                               // CF OPTIMISATION
577   }
578
579   END_OF_MED(LOC);
580
581 }
582
583 /*!
584   Gets the names of all FIELD objects.
585
586   Returns a deque<string> object which contain the name of all FIELD objects.
587 */
588 deque<string> MED::getFieldNames     () const
589 {
590   const char* LOC = "MED::getFieldNames ( ) const : ";
591   BEGIN_OF_MED(LOC);
592
593   deque<string> fieldNames(_fields.size());
594
595   map<FIELD_NAME_,MAP_DT_IT_>::const_iterator  currentField;
596
597   int fieldNamesIndex = 0;
598
599   for ( currentField=_fields.begin();currentField != _fields.end(); currentField++ ) {
600     fieldNames[fieldNamesIndex]=(*currentField).first;
601     fieldNamesIndex++;                               // CF OPTIMISATION
602   }
603
604   END_OF_MED(LOC);
605   return fieldNames ;
606 }
607
608 /*!
609   Returns a deque<DT_IT_> which contain all iteration step for the FIELD 
610   identified by its name. DT_IT_ definition is 
611 \verbatim
612 typedef struct { int dt; int it; } DT_IT_;
613 \endverbatim
614
615 \a dt represents the time iteration number, while \a it represents
616 the inner iteration number.
617
618 */
619 deque<DT_IT_> MED::getFieldIteration (const string & fieldName) const
620   throw (MED_EXCEPTION)
621 {
622
623   const char * LOC = "MED::getFieldIteration ( const string & ) const : ";
624   BEGIN_OF_MED(LOC);
625
626   map<FIELD_NAME_,MAP_DT_IT_>::const_iterator itFields = _fields.find(fieldName);
627   
628   if ( itFields == _fields.end() ) 
629     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
630                                      << "There is no known field named |" 
631                                      << fieldName << "|"
632                                      )
633                           );   
634   //  const MAP_DT_IT_ & myIterationMap =  const_cast<const MAP_DT_IT_ & > ((*itFields).second);
635   const MAP_DT_IT_ & myIterationMap =  (*itFields).second ;
636   MAP_DT_IT_::const_iterator currentIterator ;
637
638   int iterationSize = myIterationMap.size();
639   
640   SCRUTE_MED(iterationSize);
641
642   deque<DT_IT_> Iteration(iterationSize);
643   
644   int iterationIndex = 0;
645   
646   for (currentIterator = myIterationMap.begin();
647        currentIterator != myIterationMap.end(); currentIterator++ )
648     {
649       SCRUTE_MED(((*currentIterator).first).dt);
650       SCRUTE_MED(((*currentIterator).first).it);
651
652       Iteration[iterationIndex].dt = ((*currentIterator).first).dt;
653       Iteration[iterationIndex].it = ((*currentIterator).first).it;
654
655       //      Iteration[iterationIndex]=(*currentIterator).first;
656       SCRUTE_MED(Iteration[iterationIndex].dt);
657       SCRUTE_MED(Iteration[iterationIndex].it);
658       iterationIndex++;                               // CF OPTIMISATION
659     }
660
661   END_OF_MED(LOC);
662   return Iteration ;
663 }
664
665 /*!
666  Returns a reference to the FIELD object named fieldName with 
667  time step number dt and order number it.
668 */
669 FIELD_  * MED::getField          ( const string & fieldName, const int dt=MED_NOPDT, const int it=MED_NOPDT ) const
670   throw (MED_EXCEPTION)
671 {
672
673   const char * LOC = "MED::getField ( const string &, const int, const int ) const : ";
674   BEGIN_OF_MED(LOC);
675
676   MESSAGE_MED(LOC << "fieldName = "<<fieldName<<", dt ="<<dt<<", it = "<<it);
677
678   DT_IT_ dtIt;
679
680   dtIt.dt= dt;
681   dtIt.it= it;
682
683   map<FIELD_NAME_,MAP_DT_IT_>::const_iterator itFields = _fields.find(fieldName);
684
685   if ( itFields == _fields.end() ) 
686     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
687                                      << "There is no known field named |" 
688                                      << fieldName << "|"
689                                      )
690                           );   
691
692   const MAP_DT_IT_ & map_dtIt =  const_cast<const MAP_DT_IT_ & > ((*itFields).second);
693   MAP_DT_IT_::const_iterator itMap_dtIt =  map_dtIt.find(dtIt);
694
695   if ( itMap_dtIt == map_dtIt.end() )
696     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
697                                      << "There is no (dt,it) |("
698                                      << dt << "," << it << ")| associated with the found field |" 
699                                      << fieldName << "|"
700                                      )
701                           );   
702
703   END_OF_MED(LOC);
704
705   //return _fields[fieldName][dtIt];
706   return (*itMap_dtIt).second;
707   
708 }
709 /*!\if MEDMEM_ug
710  @}
711  \endif 
712 */
713
714
715 /*!
716  Returns a reference to the FIELD object named fieldName with 
717  time and iteration nb it.
718 */
719 FIELD_  *MED::getField2(const string & fieldName, double time, int it) const throw (MEDEXCEPTION)
720 {
721   const char * LOC = "MED::getField2 ( const string &, const int, const int ) const : ";
722   const double eps=1e-9;
723   map<FIELD_NAME_,MAP_DT_IT_>::const_iterator itFields=_fields.find(fieldName);
724   if ( itFields == _fields.end() ) 
725     throw MED_EXCEPTION (LOCALIZED( STRING(LOC) << "There is no known field named |" << fieldName << "|"));
726   MAP_DT_IT_::const_iterator iters=(*itFields).second.begin();
727   bool found=false;
728   FIELD_  *ret;
729   for(;iters!=(*itFields).second.end() && !found;iters++)
730     if(fabs((*iters).second->getTime()-time)<eps)
731       //if(it==(*iters).first.it)
732         {
733           ret=(*iters).second;
734           found=true;
735         }
736   if(!found)
737     throw MED_EXCEPTION(LOCALIZED( STRING(LOC) << "There is no known field existing at specified time and iteration !!! "));
738   return ret;
739   //END_OF_MED();
740 }
741
742 // fiend ostream & MED::operator<<(ostream &os,const MED & med) const {
743 //   return os;
744 // };
745
746
747 /*!
748   Returns a map<MED_EN::medEntityMesh,SUPPORT*> which contain 
749   foreach entity, a reference to the SUPPORT on all elements.
750 */
751 const map<MED_EN::medEntityMesh,SUPPORT*> & MED::getSupports(const string & meshName) const
752   throw (MED_EXCEPTION)
753 {
754   const char * LOC = "MED::getSupports ( const string ) const : ";
755   BEGIN_OF_MED(LOC);
756
757   map<MESH_NAME_, map<MED_EN::medEntityMesh,SUPPORT *> >::const_iterator itSupportOnMesh = _support.find(meshName) ;
758   
759   if ( itSupportOnMesh == _support.end() )
760     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
761                                      << "There is no support on mesh named |" 
762                                      << meshName << "|"
763                                      )
764                           );
765   END_OF_MED(LOC);
766   return (*itSupportOnMesh).second ;
767 }
768
769
770 /*! \if MEDMEM_ug
771 \addtogroup MED_query
772 @{
773 \endif
774 */
775
776 /*!
777   Returns a reference to the SUPPORT object on all elements of entity 
778   for the MESH named meshName.
779 */
780 SUPPORT *  MED::getSupport (const string & meshName,MED_EN::medEntityMesh entity) const 
781   throw (MED_EXCEPTION)
782 {
783   const char * LOC = "MED::getSupport ( const string, MED_EN::medEntityMesh ) const : ";
784   BEGIN_OF_MED(LOC);
785
786   int index = 0;
787   map<MESH_NAME_, map<MED_EN::medEntityMesh,SUPPORT *> >::const_iterator const_itSupportOnMesh;
788
789   for (const_itSupportOnMesh=_support.begin(); const_itSupportOnMesh != _support.end();
790        const_itSupportOnMesh++ )
791     {
792       map<MED_EN::medEntityMesh,SUPPORT *>::const_iterator const_itSupport ;
793       for (const_itSupport=(*const_itSupportOnMesh).second.begin();
794            const_itSupport!=(*const_itSupportOnMesh).second.end();const_itSupport++) index++;
795     }
796
797   MESSAGE_MED(LOC << "In this MED object there is(are) " << index << " support(s):");
798
799   for (const_itSupportOnMesh=_support.begin();const_itSupportOnMesh != _support.end(); const_itSupportOnMesh++ )
800     {
801       map<MED_EN::medEntityMesh,SUPPORT *>::const_iterator const_itSupport ;
802       for (const_itSupport=(*const_itSupportOnMesh).second.begin();
803            const_itSupport!=(*const_itSupportOnMesh).second.end();const_itSupport++)
804         {
805           MESSAGE_MED(LOC << "Support on mesh " << (*const_itSupportOnMesh).first << " on entity " << (*const_itSupport).first << " : " << *((*const_itSupport).second));
806         }
807   }
808
809   const_itSupportOnMesh = _support.find(meshName) ;
810   
811   if ( const_itSupportOnMesh == _support.end() )
812     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
813                                      << "There is no support on mesh named |" 
814                                      << meshName << "|"
815                                      )
816                           );
817  
818 //   map<MED_EN::medEntityMesh,SUPPORT *> & SupportOnMesh = (map<MED_EN::medEntityMesh,SUPPORT *>&) ((*itSupportOnMesh).second) ;
819 //   map<MED_EN::medEntityMesh,SUPPORT *>::const_iterator itSupport = SupportOnMesh.find(entity) ;
820   
821 //   if (itSupport == SupportOnMesh.end() )
822 //     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
823 //                                      << "There is no support on entity "
824 //                                   << entity << " in mesh named |" 
825 //                                      << meshName << "|"
826 //                                      )
827 //                           );
828
829
830   map<MED_EN::medEntityMesh,SUPPORT *> SupportOnMesh = ((*const_itSupportOnMesh).second);
831
832   map<MED_EN::medEntityMesh,SUPPORT *>::const_iterator itSupport = SupportOnMesh.find(entity) ;
833   
834   if (itSupport == SupportOnMesh.end() )
835     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) 
836                                      << "There is no support on entity "
837                                      << entity << " in mesh named |" 
838                                      << meshName << "|"
839                                      )
840                           );
841   END_OF_MED(LOC);
842   return (*itSupport).second ;
843 }
844 /*!\if MEDMEM_ug @} \endif */
845
846
847
848 /*!
849 The need for this method arises from the following situation.
850 When loading a mesh, Medmem reads the constituent elements
851 in the Med file. It is possible at this stage that not all
852 constituent elements are stored in memory (For instance, reading 
853 a 2D mesh, not all the edges are present, because only 
854 the boundaries were stored in the file). 
855 When computing descending connectivities, Medmem stores all the 
856 faces and has a corresponding numbering. This introduces a
857 discrepancy between the support numbering which was determined at
858 file loading and the new numbering. The following method
859 synchronizes the two numberings.
860 */
861 void MED::updateSupport ()
862 {
863   const char* LOC = "MED::updateSupport () : ";
864   BEGIN_OF_MED(LOC);
865
866   map<MESH_NAME_, map<MED_EN::medEntityMesh,SUPPORT *> >::iterator itSupportOnMesh ;
867   for ( itSupportOnMesh=_support.begin();itSupportOnMesh != _support.end(); itSupportOnMesh++ ) {
868     map<MED_EN::medEntityMesh,SUPPORT *>& anEntity2Support = (*itSupportOnMesh).second;
869     map<MED_EN::medEntityMesh,SUPPORT *> anEntity2SupportTmp;
870     map<MED_EN::medEntityMesh,SUPPORT *>::iterator itSupport ;
871     for ( itSupport=anEntity2Support.begin();itSupport!=anEntity2Support.end();itSupport++)
872     {
873       MED_EN::medEntityMesh aKey = (*itSupport).first;
874       SUPPORT* aData = (*itSupport).second;
875       try {
876         aData->update() ;
877         anEntity2SupportTmp[aKey] = aData;
878       }
879       catch (MEDEXCEPTION & ex) {
880         // entity not defined in mesh -> we remove support on it !
881         MESSAGE_MED(PREFIX_MED<<ex.what());
882         delete (*itSupport).second ;
883         //(*itSupportOnMesh).second.erase(itSupport) ; // that's right ????
884         //itSupport-- ;
885         map<MED_EN::medEntityMesh,SUPPORT *>::iterator itSupportCurr = itSupport;
886         itSupport--; // decrement before erase()
887         (*itSupportOnMesh).second.erase(itSupportCurr);
888       }
889     }
890
891     // some entities has not defined in mesh -> we should remove their supports!
892     anEntity2Support.swap( anEntity2SupportTmp );
893
894     for ( itSupport=anEntity2SupportTmp.begin();itSupport!=anEntity2SupportTmp.end();itSupport++)
895     {
896       MED_EN::medEntityMesh aKey = (*itSupport).first;
897       SUPPORT* aData = (*itSupport).second;
898       if( anEntity2Support.find( aKey ) == anEntity2Support.end() )
899         delete aData;
900     }
901   }
902
903   END_OF_MED(LOC);
904 }
905
906 /*!
907   Adds the given MESH object. MED object control it,
908   and destroy it, so you must not destroy it after.
909
910   The meshName is given by the MESH object.
911 */
912 void MED::addMesh( MESH * const ptrMesh)
913   throw (MED_EXCEPTION)
914 {
915   const char * LOC = "MED::addMesh(const MESH * ptrMesh): ";
916   BEGIN_OF_MED(LOC);
917
918   if ( ! ptrMesh ) 
919     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) << "ptrMesh must not be NULL !"));
920  
921   string meshName;
922   if ( ! ( meshName = ptrMesh->getName()).size() ) 
923     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) << "ptrMesh->_name must not be NULL !"));
924
925 //   MESH * meshToMed = new MESH(*ptrMesh); DO WE HAVE TO COPY THE ENTRY MESH OR NOT ????? (NB)
926
927   _meshes[meshName] = ptrMesh; // if ptrMesh->meshName already exists it is modified
928
929 //   _meshes[meshName] = meshToMed;
930
931   END_OF_MED(LOC);
932 }
933
934 /*!
935   Add the given FIELD object. MED object control it,
936   and destroy it, so you must not destroy it after.
937
938   The fieldName is given by the FIELD object.
939 */
940 void MED::addField( FIELD_ * const ptrField)
941   throw (MED_EXCEPTION)
942 {
943   const char * LOC = "MED::addField(const FIELD_ * const ptrField): ";
944   BEGIN_OF_MED(LOC);
945   
946   if ( ! ptrField ) 
947     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) << "ptrField must not be NULL !"));
948
949   string fieldName;
950   if ( ! (fieldName = ptrField->getName()).size() ) 
951     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) << "ptrField->_name must not be NULL !"));
952   
953   SUPPORT * ptrSupport;
954   if ( ! ( ptrSupport = (SUPPORT * ) ptrField->getSupport()) ) 
955     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) << "ptrField->_support must not be NULL !"));
956   
957   MESH * ptrMesh;
958   if ( ! ( ptrMesh = ptrSupport->getMesh()) ) 
959     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) << "ptrField->_support->_mesh must not be NULL !"));
960
961   string meshName;
962   if ( ! ( meshName = ptrMesh->getName()).size() ) 
963     throw MED_EXCEPTION ( LOCALIZED( STRING(LOC) << "ptrField->_support->_mesh->_name must not be NULL !"));
964
965   DT_IT_ dtIt;
966   dtIt.dt  = ptrField->getIterationNumber();
967   dtIt.it  = ptrField->getOrderNumber();
968                 
969   _fields   [fieldName][dtIt] = ptrField; // if it already exists it is replaced
970   _meshName [ptrField]        = meshName; // if it already exists it is replaced
971   _meshes   [meshName]        = ptrMesh;  // if it already exists it is replaced
972
973   //  int  numberOfTypes = ptrSupport->getNumberOfTypes(); !! UNUSED VARIABLE !!
974   _support  [meshName][ptrSupport->getEntity()] = ptrSupport;// if it already exists it is replaced
975
976
977   END_OF_MED(LOC);
978 }